Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(193)

Side by Side Diff: nss/lib/base/nssutf8.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « nss/lib/base/nssbaset.h ('k') | nss/lib/base/tracker.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « nss/lib/base/nssbaset.h ('k') | nss/lib/base/tracker.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698