OLD | NEW |
| (Empty) |
1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
4 | |
5 /* | |
6 * utf8.c | |
7 * | |
8 * This file contains some additional utility routines required for | |
9 * handling UTF8 strings. | |
10 */ | |
11 | |
12 #ifndef BASE_H | |
13 #include "base.h" | |
14 #endif /* BASE_H */ | |
15 | |
16 #include "plstr.h" | |
17 | |
18 /* | |
19 * NOTES: | |
20 * | |
21 * There's an "is hex string" function in pki1/atav.c. If we need | |
22 * it in more places, pull that one out. | |
23 */ | |
24 | |
25 /* | |
26 * nssUTF8_CaseIgnoreMatch | |
27 * | |
28 * Returns true if the two UTF8-encoded strings pointed to by the | |
29 * two specified NSSUTF8 pointers differ only in typcase. | |
30 * | |
31 * The error may be one of the following values: | |
32 * NSS_ERROR_INVALID_POINTER | |
33 * | |
34 * Return value: | |
35 * PR_TRUE if the strings match, ignoring case | |
36 * PR_FALSE if they don't | |
37 * PR_FALSE upon error | |
38 */ | |
39 | |
40 NSS_IMPLEMENT PRBool | |
41 nssUTF8_CaseIgnoreMatch(const NSSUTF8 *a, const NSSUTF8 *b, PRStatus *statusOpt) | |
42 { | |
43 #ifdef NSSDEBUG | |
44 if (((const NSSUTF8 *)NULL == a) || ((const NSSUTF8 *)NULL == b)) { | |
45 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
46 if ((PRStatus *)NULL != statusOpt) { | |
47 *statusOpt = PR_FAILURE; | |
48 } | |
49 return PR_FALSE; | |
50 } | |
51 #endif /* NSSDEBUG */ | |
52 | |
53 if ((PRStatus *)NULL != statusOpt) { | |
54 *statusOpt = PR_SUCCESS; | |
55 } | |
56 | |
57 /* | |
58 * XXX fgmr | |
59 * | |
60 * This is, like, so wrong! | |
61 */ | |
62 if (0 == PL_strcasecmp((const char *)a, (const char *)b)) { | |
63 return PR_TRUE; | |
64 } else { | |
65 return PR_FALSE; | |
66 } | |
67 } | |
68 | |
69 /* | |
70 * nssUTF8_PrintableMatch | |
71 * | |
72 * Returns true if the two Printable strings pointed to by the | |
73 * two specified NSSUTF8 pointers match when compared with the | |
74 * rules for Printable String (leading and trailing spaces are | |
75 * disregarded, extents of whitespace match irregardless of length, | |
76 * and case is not significant), then PR_TRUE will be returned. | |
77 * Otherwise, PR_FALSE will be returned. Upon failure, PR_FALSE | |
78 * will be returned. If the optional statusOpt argument is not | |
79 * NULL, then PR_SUCCESS or PR_FAILURE will be stored in that | |
80 * location. | |
81 * | |
82 * The error may be one of the following values: | |
83 * NSS_ERROR_INVALID_POINTER | |
84 * | |
85 * Return value: | |
86 * PR_TRUE if the strings match, ignoring case | |
87 * PR_FALSE if they don't | |
88 * PR_FALSE upon error | |
89 */ | |
90 | |
91 NSS_IMPLEMENT PRBool | |
92 nssUTF8_PrintableMatch(const NSSUTF8 *a, const NSSUTF8 *b, PRStatus *statusOpt) | |
93 { | |
94 PRUint8 *c; | |
95 PRUint8 *d; | |
96 | |
97 #ifdef NSSDEBUG | |
98 if (((const NSSUTF8 *)NULL == a) || ((const NSSUTF8 *)NULL == b)) { | |
99 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
100 if ((PRStatus *)NULL != statusOpt) { | |
101 *statusOpt = PR_FAILURE; | |
102 } | |
103 return PR_FALSE; | |
104 } | |
105 #endif /* NSSDEBUG */ | |
106 | |
107 if ((PRStatus *)NULL != statusOpt) { | |
108 *statusOpt = PR_SUCCESS; | |
109 } | |
110 | |
111 c = (PRUint8 *)a; | |
112 d = (PRUint8 *)b; | |
113 | |
114 while (' ' == *c) { | |
115 c++; | |
116 } | |
117 | |
118 while (' ' == *d) { | |
119 d++; | |
120 } | |
121 | |
122 while (('\0' != *c) && ('\0' != *d)) { | |
123 PRUint8 e, f; | |
124 | |
125 e = *c; | |
126 f = *d; | |
127 | |
128 if (('a' <= e) && (e <= 'z')) { | |
129 e -= ('a' - 'A'); | |
130 } | |
131 | |
132 if (('a' <= f) && (f <= 'z')) { | |
133 f -= ('a' - 'A'); | |
134 } | |
135 | |
136 if (e != f) { | |
137 return PR_FALSE; | |
138 } | |
139 | |
140 c++; | |
141 d++; | |
142 | |
143 if (' ' == *c) { | |
144 while (' ' == *c) { | |
145 c++; | |
146 } | |
147 c--; | |
148 } | |
149 | |
150 if (' ' == *d) { | |
151 while (' ' == *d) { | |
152 d++; | |
153 } | |
154 d--; | |
155 } | |
156 } | |
157 | |
158 while (' ' == *c) { | |
159 c++; | |
160 } | |
161 | |
162 while (' ' == *d) { | |
163 d++; | |
164 } | |
165 | |
166 if (*c == *d) { | |
167 /* And both '\0', btw */ | |
168 return PR_TRUE; | |
169 } else { | |
170 return PR_FALSE; | |
171 } | |
172 } | |
173 | |
174 /* | |
175 * nssUTF8_Duplicate | |
176 * | |
177 * This routine duplicates the UTF8-encoded string pointed to by the | |
178 * specified NSSUTF8 pointer. If the optional arenaOpt argument is | |
179 * not null, the memory required will be obtained from that arena; | |
180 * otherwise, the memory required will be obtained from the heap. | |
181 * A pointer to the new string will be returned. In case of error, | |
182 * an error will be placed on the error stack and NULL will be | |
183 * returned. | |
184 * | |
185 * The error may be one of the following values: | |
186 * NSS_ERROR_INVALID_POINTER | |
187 * NSS_ERROR_INVALID_ARENA | |
188 * NSS_ERROR_NO_MEMORY | |
189 */ | |
190 | |
191 NSS_IMPLEMENT NSSUTF8 * | |
192 nssUTF8_Duplicate(const NSSUTF8 *s, NSSArena *arenaOpt) | |
193 { | |
194 NSSUTF8 *rv; | |
195 PRUint32 len; | |
196 | |
197 #ifdef NSSDEBUG | |
198 if ((const NSSUTF8 *)NULL == s) { | |
199 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
200 return (NSSUTF8 *)NULL; | |
201 } | |
202 | |
203 if ((NSSArena *)NULL != arenaOpt) { | |
204 if (PR_SUCCESS != nssArena_verifyPointer(arenaOpt)) { | |
205 return (NSSUTF8 *)NULL; | |
206 } | |
207 } | |
208 #endif /* NSSDEBUG */ | |
209 | |
210 len = PL_strlen((const char *)s); | |
211 #ifdef PEDANTIC | |
212 if ('\0' != ((const char *)s)[len]) { | |
213 /* must have wrapped, e.g., too big for PRUint32 */ | |
214 nss_SetError(NSS_ERROR_NO_MEMORY); | |
215 return (NSSUTF8 *)NULL; | |
216 } | |
217 #endif /* PEDANTIC */ | |
218 len++; /* zero termination */ | |
219 | |
220 rv = nss_ZAlloc(arenaOpt, len); | |
221 if ((void *)NULL == rv) { | |
222 return (NSSUTF8 *)NULL; | |
223 } | |
224 | |
225 (void)nsslibc_memcpy(rv, s, len); | |
226 return rv; | |
227 } | |
228 | |
229 /* | |
230 * nssUTF8_Size | |
231 * | |
232 * This routine returns the length in bytes (including the terminating | |
233 * null) of the UTF8-encoded string pointed to by the specified | |
234 * NSSUTF8 pointer. Zero is returned on error. | |
235 * | |
236 * The error may be one of the following values: | |
237 * NSS_ERROR_INVALID_POINTER | |
238 * NSS_ERROR_VALUE_TOO_LARGE | |
239 * | |
240 * Return value: | |
241 * 0 on error | |
242 * nonzero length of the string. | |
243 */ | |
244 | |
245 NSS_IMPLEMENT PRUint32 | |
246 nssUTF8_Size(const NSSUTF8 *s, PRStatus *statusOpt) | |
247 { | |
248 PRUint32 sv; | |
249 | |
250 #ifdef NSSDEBUG | |
251 if ((const NSSUTF8 *)NULL == s) { | |
252 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
253 if ((PRStatus *)NULL != statusOpt) { | |
254 *statusOpt = PR_FAILURE; | |
255 } | |
256 return 0; | |
257 } | |
258 #endif /* NSSDEBUG */ | |
259 | |
260 sv = PL_strlen((const char *)s) + 1; | |
261 #ifdef PEDANTIC | |
262 if ('\0' != ((const char *)s)[sv - 1]) { | |
263 /* wrapped */ | |
264 nss_SetError(NSS_ERROR_VALUE_TOO_LARGE); | |
265 if ((PRStatus *)NULL != statusOpt) { | |
266 *statusOpt = PR_FAILURE; | |
267 } | |
268 return 0; | |
269 } | |
270 #endif /* PEDANTIC */ | |
271 | |
272 if ((PRStatus *)NULL != statusOpt) { | |
273 *statusOpt = PR_SUCCESS; | |
274 } | |
275 | |
276 return sv; | |
277 } | |
278 | |
279 /* | |
280 * nssUTF8_Length | |
281 * | |
282 * This routine returns the length in characters (not including the | |
283 * terminating null) of the UTF8-encoded string pointed to by the | |
284 * specified NSSUTF8 pointer. | |
285 * | |
286 * The error may be one of the following values: | |
287 * NSS_ERROR_INVALID_POINTER | |
288 * NSS_ERROR_VALUE_TOO_LARGE | |
289 * NSS_ERROR_INVALID_STRING | |
290 * | |
291 * Return value: | |
292 * length of the string (which may be zero) | |
293 * 0 on error | |
294 */ | |
295 | |
296 NSS_IMPLEMENT PRUint32 | |
297 nssUTF8_Length(const NSSUTF8 *s, PRStatus *statusOpt) | |
298 { | |
299 PRUint32 l = 0; | |
300 const PRUint8 *c = (const PRUint8 *)s; | |
301 | |
302 #ifdef NSSDEBUG | |
303 if ((const NSSUTF8 *)NULL == s) { | |
304 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
305 goto loser; | |
306 } | |
307 #endif /* NSSDEBUG */ | |
308 | |
309 /* | |
310 * From RFC 2044: | |
311 * | |
312 * UCS-4 range (hex.) UTF-8 octet sequence (binary) | |
313 * 0000 0000-0000 007F 0xxxxxxx | |
314 * 0000 0080-0000 07FF 110xxxxx 10xxxxxx | |
315 * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx | |
316 * 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | |
317 * 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx | |
318 * 0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx | |
319 */ | |
320 | |
321 while (0 != *c) { | |
322 PRUint32 incr; | |
323 if ((*c & 0x80) == 0) { | |
324 incr = 1; | |
325 } else if ((*c & 0xE0) == 0xC0) { | |
326 incr = 2; | |
327 } else if ((*c & 0xF0) == 0xE0) { | |
328 incr = 3; | |
329 } else if ((*c & 0xF8) == 0xF0) { | |
330 incr = 4; | |
331 } else if ((*c & 0xFC) == 0xF8) { | |
332 incr = 5; | |
333 } else if ((*c & 0xFE) == 0xFC) { | |
334 incr = 6; | |
335 } else { | |
336 nss_SetError(NSS_ERROR_INVALID_STRING); | |
337 goto loser; | |
338 } | |
339 | |
340 l += incr; | |
341 | |
342 #ifdef PEDANTIC | |
343 if (l < incr) { | |
344 /* Wrapped-- too big */ | |
345 nss_SetError(NSS_ERROR_VALUE_TOO_LARGE); | |
346 goto loser; | |
347 } | |
348 | |
349 { | |
350 PRUint8 *d; | |
351 for (d = &c[1]; d < &c[incr]; d++) { | |
352 if ((*d & 0xC0) != 0xF0) { | |
353 nss_SetError(NSS_ERROR_INVALID_STRING); | |
354 goto loser; | |
355 } | |
356 } | |
357 } | |
358 #endif /* PEDANTIC */ | |
359 | |
360 c += incr; | |
361 } | |
362 | |
363 if ((PRStatus *)NULL != statusOpt) { | |
364 *statusOpt = PR_SUCCESS; | |
365 } | |
366 | |
367 return l; | |
368 | |
369 loser: | |
370 if ((PRStatus *)NULL != statusOpt) { | |
371 *statusOpt = PR_FAILURE; | |
372 } | |
373 | |
374 return 0; | |
375 } | |
376 | |
377 /* | |
378 * nssUTF8_Create | |
379 * | |
380 * This routine creates a UTF8 string from a string in some other | |
381 * format. Some types of string may include embedded null characters, | |
382 * so for them the length parameter must be used. For string types | |
383 * that are null-terminated, the length parameter is optional; if it | |
384 * is zero, it will be ignored. If the optional arena argument is | |
385 * non-null, the memory used for the new string will be obtained from | |
386 * that arena, otherwise it will be obtained from the heap. This | |
387 * routine may return NULL upon error, in which case it will have | |
388 * placed an error on the error stack. | |
389 * | |
390 * The error may be one of the following: | |
391 * NSS_ERROR_INVALID_POINTER | |
392 * NSS_ERROR_NO_MEMORY | |
393 * NSS_ERROR_UNSUPPORTED_TYPE | |
394 * | |
395 * Return value: | |
396 * NULL upon error | |
397 * A non-null pointer to a new UTF8 string otherwise | |
398 */ | |
399 | |
400 extern const NSSError NSS_ERROR_INTERNAL_ERROR; /* XXX fgmr */ | |
401 | |
402 NSS_IMPLEMENT NSSUTF8 * | |
403 nssUTF8_Create(NSSArena *arenaOpt, nssStringType type, const void *inputString, | |
404 PRUint32 size /* in bytes, not characters */ | |
405 ) | |
406 { | |
407 NSSUTF8 *rv = NULL; | |
408 | |
409 #ifdef NSSDEBUG | |
410 if ((NSSArena *)NULL != arenaOpt) { | |
411 if (PR_SUCCESS != nssArena_verifyPointer(arenaOpt)) { | |
412 return (NSSUTF8 *)NULL; | |
413 } | |
414 } | |
415 | |
416 if ((const void *)NULL == inputString) { | |
417 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
418 return (NSSUTF8 *)NULL; | |
419 } | |
420 #endif /* NSSDEBUG */ | |
421 | |
422 switch (type) { | |
423 case nssStringType_DirectoryString: | |
424 /* This is a composite type requiring BER */ | |
425 nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE); | |
426 break; | |
427 case nssStringType_TeletexString: | |
428 /* | |
429 * draft-ietf-pkix-ipki-part1-11 says in part: | |
430 * | |
431 * In addition, many legacy implementations support names encoded | |
432 * in the ISO 8859-1 character set (Latin1String) but tag them as | |
433 * TeletexString. The Latin1String includes characters used in | |
434 * Western European countries which are not part of the | |
435 * TeletexString charcter set. Implementations that process | |
436 * TeletexString SHOULD be prepared to handle the entire ISO | |
437 * 8859-1 character set.[ISO 8859-1]. | |
438 */ | |
439 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
440 break; | |
441 case nssStringType_PrintableString: | |
442 /* | |
443 * PrintableString consists of A-Za-z0-9 ,()+,-./:=? | |
444 * This is a subset of ASCII, which is a subset of UTF8. | |
445 * So we can just duplicate the string over. | |
446 */ | |
447 | |
448 if (0 == size) { | |
449 rv = nssUTF8_Duplicate((const NSSUTF8 *)inputString, arenaOpt); | |
450 } else { | |
451 rv = nss_ZAlloc(arenaOpt, size + 1); | |
452 if ((NSSUTF8 *)NULL == rv) { | |
453 return (NSSUTF8 *)NULL; | |
454 } | |
455 | |
456 (void)nsslibc_memcpy(rv, inputString, size); | |
457 } | |
458 | |
459 break; | |
460 case nssStringType_UniversalString: | |
461 /* 4-byte unicode */ | |
462 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
463 break; | |
464 case nssStringType_BMPString: | |
465 /* Base Multilingual Plane of Unicode */ | |
466 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
467 break; | |
468 case nssStringType_UTF8String: | |
469 if (0 == size) { | |
470 rv = nssUTF8_Duplicate((const NSSUTF8 *)inputString, arenaOpt); | |
471 } else { | |
472 rv = nss_ZAlloc(arenaOpt, size + 1); | |
473 if ((NSSUTF8 *)NULL == rv) { | |
474 return (NSSUTF8 *)NULL; | |
475 } | |
476 | |
477 (void)nsslibc_memcpy(rv, inputString, size); | |
478 } | |
479 | |
480 break; | |
481 case nssStringType_PHGString: | |
482 /* | |
483 * PHGString is an IA5String (with case-insensitive comparisons). | |
484 * IA5 is ~almost~ ascii; ascii has dollar-sign where IA5 has | |
485 * currency symbol. | |
486 */ | |
487 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
488 break; | |
489 case nssStringType_GeneralString: | |
490 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
491 break; | |
492 default: | |
493 nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE); | |
494 break; | |
495 } | |
496 | |
497 return rv; | |
498 } | |
499 | |
500 NSS_IMPLEMENT NSSItem * | |
501 nssUTF8_GetEncoding(NSSArena *arenaOpt, NSSItem *rvOpt, nssStringType type, | |
502 NSSUTF8 *string) | |
503 { | |
504 NSSItem *rv = (NSSItem *)NULL; | |
505 PRStatus status = PR_SUCCESS; | |
506 | |
507 #ifdef NSSDEBUG | |
508 if ((NSSArena *)NULL != arenaOpt) { | |
509 if (PR_SUCCESS != nssArena_verifyPointer(arenaOpt)) { | |
510 return (NSSItem *)NULL; | |
511 } | |
512 } | |
513 | |
514 if ((NSSUTF8 *)NULL == string) { | |
515 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
516 return (NSSItem *)NULL; | |
517 } | |
518 #endif /* NSSDEBUG */ | |
519 | |
520 switch (type) { | |
521 case nssStringType_DirectoryString: | |
522 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
523 break; | |
524 case nssStringType_TeletexString: | |
525 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
526 break; | |
527 case nssStringType_PrintableString: | |
528 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
529 break; | |
530 case nssStringType_UniversalString: | |
531 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
532 break; | |
533 case nssStringType_BMPString: | |
534 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
535 break; | |
536 case nssStringType_UTF8String: { | |
537 NSSUTF8 *dup = nssUTF8_Duplicate(string, arenaOpt); | |
538 if ((NSSUTF8 *)NULL == dup) { | |
539 return (NSSItem *)NULL; | |
540 } | |
541 | |
542 if ((NSSItem *)NULL == rvOpt) { | |
543 rv = nss_ZNEW(arenaOpt, NSSItem); | |
544 if ((NSSItem *)NULL == rv) { | |
545 (void)nss_ZFreeIf(dup); | |
546 return (NSSItem *)NULL; | |
547 } | |
548 } else { | |
549 rv = rvOpt; | |
550 } | |
551 | |
552 rv->data = dup; | |
553 dup = (NSSUTF8 *)NULL; | |
554 rv->size = nssUTF8_Size(rv->data, &status); | |
555 if ((0 == rv->size) && (PR_SUCCESS != status)) { | |
556 if ((NSSItem *)NULL == rvOpt) { | |
557 (void)nss_ZFreeIf(rv); | |
558 } | |
559 return (NSSItem *)NULL; | |
560 } | |
561 } break; | |
562 case nssStringType_PHGString: | |
563 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
564 break; | |
565 default: | |
566 nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE); | |
567 break; | |
568 } | |
569 | |
570 return rv; | |
571 } | |
572 | |
573 /* | |
574 * nssUTF8_CopyIntoFixedBuffer | |
575 * | |
576 * This will copy a UTF8 string into a fixed-length buffer, making | |
577 * sure that the all characters are valid. Any remaining space will | |
578 * be padded with the specified ASCII character, typically either | |
579 * null or space. | |
580 * | |
581 * Blah, blah, blah. | |
582 */ | |
583 | |
584 NSS_IMPLEMENT PRStatus | |
585 nssUTF8_CopyIntoFixedBuffer(NSSUTF8 *string, char *buffer, PRUint32 bufferSize, | |
586 char pad) | |
587 { | |
588 PRUint32 stringSize = 0; | |
589 | |
590 #ifdef NSSDEBUG | |
591 if ((char *)NULL == buffer) { | |
592 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
593 return PR_FALSE; | |
594 } | |
595 | |
596 if (0 == bufferSize) { | |
597 nss_SetError(NSS_ERROR_INVALID_ARGUMENT); | |
598 return PR_FALSE; | |
599 } | |
600 | |
601 if ((pad & 0x80) != 0x00) { | |
602 nss_SetError(NSS_ERROR_INVALID_ARGUMENT); | |
603 return PR_FALSE; | |
604 } | |
605 #endif /* NSSDEBUG */ | |
606 | |
607 if ((NSSUTF8 *)NULL == string) { | |
608 string = (NSSUTF8 *)""; | |
609 } | |
610 | |
611 stringSize = nssUTF8_Size(string, (PRStatus *)NULL); | |
612 stringSize--; /* don't count the trailing null */ | |
613 if (stringSize > bufferSize) { | |
614 PRUint32 bs = bufferSize; | |
615 (void)nsslibc_memcpy(buffer, string, bufferSize); | |
616 | |
617 if (( ((buffer[bs - 1] & 0x80) == 0x00)) || | |
618 ((bs > 1) && ((buffer[bs - 2] & 0xE0) == 0xC0)) || | |
619 ((bs > 2) && ((buffer[bs - 3] & 0xF0) == 0xE0)) || | |
620 ((bs > 3) && ((buffer[bs - 4] & 0xF8) == 0xF0)) || | |
621 ((bs > 4) && ((buffer[bs - 5] & 0xFC) == 0xF8)) || | |
622 ((bs > 5) && ((buffer[bs - 6] & 0xFE) == 0xFC))) { | |
623 /* It fit exactly */ | |
624 return PR_SUCCESS; | |
625 } | |
626 | |
627 /* Too long. We have to trim the last character */ | |
628 for (/*bs*/; bs != 0; bs--) { | |
629 if ((buffer[bs - 1] & 0xC0) != 0x80) { | |
630 buffer[bs - 1] = pad; | |
631 break; | |
632 } else { | |
633 buffer[bs - 1] = pad; | |
634 } | |
635 } | |
636 } else { | |
637 (void)nsslibc_memset(buffer, pad, bufferSize); | |
638 (void)nsslibc_memcpy(buffer, string, stringSize); | |
639 } | |
640 | |
641 return PR_SUCCESS; | |
642 } | |
643 | |
644 /* | |
645 * nssUTF8_Equal | |
646 * | |
647 */ | |
648 | |
649 NSS_IMPLEMENT PRBool | |
650 nssUTF8_Equal(const NSSUTF8 *a, const NSSUTF8 *b, PRStatus *statusOpt) | |
651 { | |
652 PRUint32 la, lb; | |
653 | |
654 #ifdef NSSDEBUG | |
655 if (((const NSSUTF8 *)NULL == a) || ((const NSSUTF8 *)NULL == b)) { | |
656 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
657 if ((PRStatus *)NULL != statusOpt) { | |
658 *statusOpt = PR_FAILURE; | |
659 } | |
660 return PR_FALSE; | |
661 } | |
662 #endif /* NSSDEBUG */ | |
663 | |
664 la = nssUTF8_Size(a, statusOpt); | |
665 if (0 == la) { | |
666 return PR_FALSE; | |
667 } | |
668 | |
669 lb = nssUTF8_Size(b, statusOpt); | |
670 if (0 == lb) { | |
671 return PR_FALSE; | |
672 } | |
673 | |
674 if (la != lb) { | |
675 return PR_FALSE; | |
676 } | |
677 | |
678 return nsslibc_memequal(a, b, la, statusOpt); | |
679 } | |
OLD | NEW |