1 /* stringprep.c library implementing IETF stringprep specification
2 * Copyright (C) 2002 Simon Josefsson
4 * This file is part of libstringprep.
6 * Libstringprep is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * Libstringprep is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with libstringprep; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 stringprep_find_character_in_table (unsigned long ucs4
,
28 Stringprep_table_element
* table
)
32 for (i
= 0; table
[i
].start
; i
++)
33 if (ucs4
>= table
[i
].start
&&
34 ucs4
<= (table
[i
].end
? table
[i
].end
: table
[i
].start
))
41 stringprep_find_string_in_table (unsigned long *ucs4
,
44 Stringprep_table_element
* table
)
48 for (j
= 0; j
< ucs4len
; j
++)
49 if ((pos
= stringprep_find_character_in_table (ucs4
[j
], table
)) != -1)
60 stringprep_apply_table_to_string (unsigned long *ucs4
,
63 Stringprep_table_element
* table
)
68 while ((pos
= stringprep_find_string_in_table
69 (ucs4
, *ucs4len
, &i
, table
)) != -1)
72 printf ("hit %06lx %06lx-%06lx\n", ucs4
[pos
], table
[i
].start
,
76 for (maplen
= 0; table
[i
].map
[maplen
]; maplen
++)
79 if (*ucs4len
- 1 + maplen
>= maxucs4len
)
80 return STRINGPREP_TOO_SMALL_BUFFER
;
82 memmove (&ucs4
[pos
+ maplen
], &ucs4
[pos
+ 1],
83 *ucs4len
* sizeof (unsigned long) - (&ucs4
[pos
+ 1] - ucs4
));
84 memcpy (&ucs4
[pos
], table
[i
].map
, sizeof (unsigned long) * maplen
);
85 *ucs4len
= *ucs4len
- 1 + maplen
;
91 #define INVERTED(x) ((x) & ((~0UL) >> 1))
92 #define UNAPPLICAPLEFLAGS(flags, profileflags) \
93 ((!INVERTED(profileflags) && !(profileflags & flags) && profileflags) || \
94 ( INVERTED(profileflags) && (profileflags & flags)))
98 * @in: input/ouput array with string to prepare.
99 * @maxlen: maximum length of input/output array.
100 * @flags: optional stringprep profile flags.
101 * @profile: pointer to stringprep profile to use.
103 * Prepare the input UTF-8 string according to the stringprep profile.
104 * Normally application programmers use stringprep profile macros such
105 * as stringprep_nameprep(), stringprep_kerberos5() etc instead of
106 * calling this function directly.
108 * Return value: Returns 0 iff successful, or an error code.
111 stringprep (char *in
, int maxlen
, int flags
, Stringprep_profile
* profile
)
116 unsigned long *q
= 0;
121 ucs4
= stringprep_utf8_to_ucs4 (in
, -1, &ucs4len
);
122 maxucs4len
= 4 * ucs4len
+ 10;
123 ucs4
= realloc (ucs4
, 1 + maxucs4len
* sizeof (unsigned long));
126 rc
= STRINGPREP_MALLOC_ERROR
;
133 printf ("\t;; in: ");
134 for (j
= 0; j
< ucs4len
; j
++)
135 printf ("U+%06lx ", ucs4
[j
]);
140 for (i
= 0; profile
[i
].operation
; i
++)
142 switch (profile
[i
].operation
)
144 case STRINGPREP_NFKC
:
145 if (UNAPPLICAPLEFLAGS (flags
, profile
[i
].flags
))
147 if (flags
& STRINGPREP_NO_NFKC
&& !profile
[i
].flags
)
149 /* Profile requires NFKC, but callee asked for no NFKC. */
150 rc
= STRINGPREP_FLAG_ERROR
;
154 q
= stringprep_ucs4_nfkc_normalize (ucs4
, ucs4len
);
158 rc
= STRINGPREP_NFKC_FAILED
;
162 for (ucs4len
= 0; ucs4
[ucs4len
]; ucs4len
++)
170 case STRINGPREP_PROHIBIT_TABLE
:
171 if (stringprep_find_string_in_table
172 (ucs4
, ucs4len
, NULL
, profile
[i
].table
) != -1)
174 rc
= STRINGPREP_CONTAINS_PROHIBITED
;
179 case STRINGPREP_UNASSIGNED_TABLE
:
180 if (UNAPPLICAPLEFLAGS (flags
, profile
[i
].flags
))
182 if (flags
& STRINGPREP_NO_UNASSIGNED
)
183 if (stringprep_find_string_in_table
184 (ucs4
, ucs4len
, NULL
, profile
[i
].table
) != -1)
186 rc
= STRINGPREP_CONTAINS_UNASSIGNED
;
191 case STRINGPREP_MAP_TABLE
:
192 if (UNAPPLICAPLEFLAGS (flags
, profile
[i
].flags
))
194 rc
= stringprep_apply_table_to_string
195 (ucs4
, &ucs4len
, maxucs4len
, profile
[i
].table
);
196 if (rc
!= STRINGPREP_OK
)
200 case STRINGPREP_BIDI_PROHIBIT_TABLE
:
201 case STRINGPREP_BIDI_RAL_TABLE
:
202 case STRINGPREP_BIDI_L_TABLE
:
205 case STRINGPREP_BIDI
:
207 int done_prohibited
= 0;
210 int contains_ral
= -1;
214 for (j
= 0; profile
[j
].operation
; j
++)
215 if (profile
[j
].operation
== STRINGPREP_BIDI_PROHIBIT_TABLE
)
218 if (stringprep_find_string_in_table
219 (ucs4
, ucs4len
, NULL
, profile
[j
].table
) != -1)
221 rc
= STRINGPREP_BIDI_CONTAINS_PROHIBITED
;
225 else if (profile
[j
].operation
== STRINGPREP_BIDI_RAL_TABLE
)
228 if (stringprep_find_string_in_table
229 (ucs4
, ucs4len
, NULL
, profile
[j
].table
) != -1)
232 else if (profile
[j
].operation
== STRINGPREP_BIDI_L_TABLE
)
235 if (stringprep_find_string_in_table
236 (ucs4
, ucs4len
, NULL
, profile
[j
].table
) != -1)
240 if (!done_prohibited
|| !done_ral
|| !done_l
)
242 rc
= STRINGPREP_PROFILE_ERROR
;
246 if (contains_ral
!= -1 && contains_l
!= -1)
248 rc
= STRINGPREP_BIDI_BOTH_L_AND_RAL
;
252 if (contains_ral
!= -1)
253 if (!(stringprep_find_character_in_table
254 (ucs4
[0], profile
[contains_ral
].table
) != -1 &&
255 stringprep_find_character_in_table
256 (ucs4
[ucs4len
- 1], profile
[contains_ral
].table
) != -1))
258 rc
= STRINGPREP_BIDI_LEADTRAIL_NOT_RAL
;
265 rc
= STRINGPREP_PROFILE_ERROR
;
272 printf ("\t;; %5s: ", profile
[i
].name
? profile
[i
].name
: "<NONAME>");
273 for (j
= 0; j
< ucs4len
; j
++)
274 printf ("U+%06lx ", ucs4
[j
]);
280 p
= stringprep_ucs4_to_utf8 (ucs4
, ucs4len
, 0, 0);
282 if (strlen (p
) >= maxlen
)
284 rc
= STRINGPREP_TOO_SMALL_BUFFER
;
288 strcpy (in
, p
); /* flawfinder: ignore */