dist dummy.c.
[libidn.git] / stringprep.c
blobc934514f66ce78b124279e05f9f6658f1806b265
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
22 #include "internal.h"
24 #define DBG 0
26 static int
27 stringprep_find_character_in_table (unsigned long ucs4,
28 Stringprep_table_element * table)
30 int i;
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))
35 return i;
37 return -1;
40 static int
41 stringprep_find_string_in_table (unsigned long *ucs4,
42 int ucs4len,
43 int *tablepos,
44 Stringprep_table_element * table)
46 int j, pos;
48 for (j = 0; j < ucs4len; j++)
49 if ((pos = stringprep_find_character_in_table (ucs4[j], table)) != -1)
51 if (tablepos)
52 *tablepos = pos;
53 return j;
56 return -1;
59 static int
60 stringprep_apply_table_to_string (unsigned long *ucs4,
61 int *ucs4len,
62 int maxucs4len,
63 Stringprep_table_element * table)
65 int i;
66 int pos, maplen;
68 while ((pos = stringprep_find_string_in_table
69 (ucs4, *ucs4len, &i, table)) != -1)
71 #if DBG
72 printf ("hit %06lx %06lx-%06lx\n", ucs4[pos], table[i].start,
73 table[i].end);
74 #endif
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;
88 return STRINGPREP_OK;
91 #define INVERTED(x) ((x) & ((~0UL) >> 1))
92 #define UNAPPLICAPLEFLAGS(flags, profileflags) \
93 ((!INVERTED(profileflags) && !(profileflags & flags) && profileflags) || \
94 ( INVERTED(profileflags) && (profileflags & flags)))
96 /**
97 * stringprep:
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)
113 int i;
114 int rc;
115 char *p = 0;
116 unsigned long *q = 0;
117 unsigned long *ucs4;
118 int ucs4len;
119 int maxucs4len;
121 ucs4 = stringprep_utf8_to_ucs4 (in, -1, &ucs4len);
122 maxucs4len = 4 * ucs4len + 10;
123 ucs4 = realloc (ucs4, 1 + maxucs4len * sizeof (unsigned long));
124 if (!ucs4)
126 rc = STRINGPREP_MALLOC_ERROR;
127 goto done;
130 #if DBG
132 int j;
133 printf ("\t;; in: ");
134 for (j = 0; j < ucs4len; j++)
135 printf ("U+%06lx ", ucs4[j]);
136 printf ("\n");
138 #endif
140 for (i = 0; profile[i].operation; i++)
142 switch (profile[i].operation)
144 case STRINGPREP_NFKC:
145 if (UNAPPLICAPLEFLAGS (flags, profile[i].flags))
146 break;
147 if (flags & STRINGPREP_NO_NFKC && !profile[i].flags)
149 /* Profile requires NFKC, but callee asked for no NFKC. */
150 rc = STRINGPREP_FLAG_ERROR;
151 goto done;
154 q = stringprep_ucs4_nfkc_normalize (ucs4, ucs4len);
156 if (!q)
158 rc = STRINGPREP_NFKC_FAILED;
159 goto done;
162 for (ucs4len = 0; ucs4[ucs4len]; ucs4len++)
165 free (ucs4);
166 ucs4 = q;
167 q = 0;
168 break;
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;
175 goto done;
177 break;
179 case STRINGPREP_UNASSIGNED_TABLE:
180 if (UNAPPLICAPLEFLAGS (flags, profile[i].flags))
181 break;
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;
187 goto done;
189 break;
191 case STRINGPREP_MAP_TABLE:
192 if (UNAPPLICAPLEFLAGS (flags, profile[i].flags))
193 break;
194 rc = stringprep_apply_table_to_string
195 (ucs4, &ucs4len, maxucs4len, profile[i].table);
196 if (rc != STRINGPREP_OK)
197 goto done;
198 break;
200 case STRINGPREP_BIDI_PROHIBIT_TABLE:
201 case STRINGPREP_BIDI_RAL_TABLE:
202 case STRINGPREP_BIDI_L_TABLE:
203 break;
205 case STRINGPREP_BIDI:
207 int done_prohibited = 0;
208 int done_ral = 0;
209 int done_l = 0;
210 int contains_ral = -1;
211 int contains_l = -1;
212 int j;
214 for (j = 0; profile[j].operation; j++)
215 if (profile[j].operation == STRINGPREP_BIDI_PROHIBIT_TABLE)
217 done_prohibited = 1;
218 if (stringprep_find_string_in_table
219 (ucs4, ucs4len, NULL, profile[j].table) != -1)
221 rc = STRINGPREP_BIDI_CONTAINS_PROHIBITED;
222 goto done;
225 else if (profile[j].operation == STRINGPREP_BIDI_RAL_TABLE)
227 done_ral = 1;
228 if (stringprep_find_string_in_table
229 (ucs4, ucs4len, NULL, profile[j].table) != -1)
230 contains_ral = j;
232 else if (profile[j].operation == STRINGPREP_BIDI_L_TABLE)
234 done_l = 1;
235 if (stringprep_find_string_in_table
236 (ucs4, ucs4len, NULL, profile[j].table) != -1)
237 contains_l = j;
240 if (!done_prohibited || !done_ral || !done_l)
242 rc = STRINGPREP_PROFILE_ERROR;
243 goto done;
246 if (contains_ral != -1 && contains_l != -1)
248 rc = STRINGPREP_BIDI_BOTH_L_AND_RAL;
249 goto done;
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;
259 goto done;
262 break;
264 default:
265 rc = STRINGPREP_PROFILE_ERROR;
266 goto done;
267 break;
269 #if DBG
271 int j;
272 printf ("\t;; %5s: ", profile[i].name ? profile[i].name : "<NONAME>");
273 for (j = 0; j < ucs4len; j++)
274 printf ("U+%06lx ", ucs4[j]);
275 printf ("\n");
277 #endif
280 p = stringprep_ucs4_to_utf8 (ucs4, ucs4len, 0, 0);
282 if (strlen (p) >= maxlen)
284 rc = STRINGPREP_TOO_SMALL_BUFFER;
285 goto done;
288 strcpy (in, p); /* flawfinder: ignore */
290 rc = STRINGPREP_OK;
292 done:
293 if (p)
294 free (p);
295 if (q)
296 free (q);
297 if (ucs4)
298 free (ucs4);
299 return rc;