1 /* stringprep.c Core stringprep implementation.
2 * Copyright (C) 2002, 2003 Simon Josefsson
4 * This file is part of GNU Libidn.
6 * GNU Libidn 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 * GNU Libidn 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 GNU Libidn; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 stringprep_find_character_in_table (unsigned long ucs4
,
26 Stringprep_table_element
* table
)
30 for (i
= 0; table
[i
].start
; i
++)
31 if (ucs4
>= table
[i
].start
&&
32 ucs4
<= (table
[i
].end
? table
[i
].end
: table
[i
].start
))
39 stringprep_find_string_in_table (unsigned long *ucs4
,
42 Stringprep_table_element
* table
)
47 for (j
= 0; j
< ucs4len
; j
++)
48 if ((pos
= stringprep_find_character_in_table (ucs4
[j
], table
)) != -1)
59 stringprep_apply_table_to_string (unsigned long *ucs4
,
62 Stringprep_table_element
* table
,
63 const char *tablename
)
69 while ((pos
= stringprep_find_string_in_table
70 (ucs4
, *ucs4len
, &i
, table
)) != -1)
72 for(maplen
= STRINGPREP_MAX_MAP_CHARS
;
73 maplen
> 0 && table
[i
].map
[maplen
-1] == 0;
77 if (*ucs4len
- 1 + maplen
>= maxucs4len
)
78 return STRINGPREP_TOO_SMALL_BUFFER
;
80 memmove (&ucs4
[pos
+ maplen
], &ucs4
[pos
+ 1],
81 *ucs4len
* sizeof (unsigned long) - (&ucs4
[pos
+ 1] - ucs4
));
82 memcpy (&ucs4
[pos
], table
[i
].map
, sizeof (unsigned long) * maplen
);
83 *ucs4len
= *ucs4len
- 1 + maplen
;
89 #define INVERTED(x) ((x) & ((~0UL) >> 1))
90 #define UNAPPLICAPLEFLAGS(flags, profileflags) \
91 ((!INVERTED(profileflags) && !(profileflags & flags) && profileflags) || \
92 ( INVERTED(profileflags) && (profileflags & flags)))
96 * @in: input/ouput array with string to prepare.
97 * @maxlen: maximum length of input/output array.
98 * @flags: optional stringprep profile flags.
99 * @profile: pointer to stringprep profile to use.
101 * Prepare the input UTF-8 string according to the stringprep profile.
102 * Normally application programmers use stringprep profile macros such
103 * as stringprep_nameprep(), stringprep_kerberos5() etc instead of
104 * calling this function directly.
106 * Since the stringprep operation can expand the string, @maxlen
107 * indicate how large the buffer holding the string is. The @flags
108 * are one of Stringprep_profile_flags, or 0. The profile indicates
109 * processing details, see the profile header files, such as
110 * stringprep_generic.h and stringprep_nameprep.h for two examples.
111 * Your application can define new profiles, possibly re-using the
112 * generic stringprep tables that always will be part of the library.
113 * Note that you must convert strings entered in the systems locale
114 * into UTF-8 before using this function.
116 * Return value: Returns 0 iff successful, or an error code.
119 stringprep (char *in
, size_t maxlen
, int flags
, Stringprep_profile
* profile
)
124 unsigned long *q
= 0;
126 size_t ucs4len
, maxucs4len
;
128 ucs4
= stringprep_utf8_to_ucs4 (in
, -1, &ucs4len
);
129 maxucs4len
= 4 * ucs4len
+ 10; /* XXX */
130 ucs4
= realloc (ucs4
, 1 + maxucs4len
* sizeof (unsigned long));
133 rc
= STRINGPREP_MALLOC_ERROR
;
137 for (i
= 0; profile
[i
].operation
; i
++)
139 switch (profile
[i
].operation
)
141 case STRINGPREP_NFKC
:
142 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 (j
= 0; q
[j
]; j
++)
171 case STRINGPREP_PROHIBIT_TABLE
:
172 j
= stringprep_find_string_in_table (ucs4
, ucs4len
,
173 NULL
, profile
[i
].table
);
176 rc
= STRINGPREP_CONTAINS_PROHIBITED
;
181 case STRINGPREP_UNASSIGNED_TABLE
:
182 if (UNAPPLICAPLEFLAGS (flags
, profile
[i
].flags
))
184 if (flags
& STRINGPREP_NO_UNASSIGNED
)
186 j
= stringprep_find_string_in_table
187 (ucs4
, ucs4len
, NULL
, profile
[i
].table
);
190 rc
= STRINGPREP_CONTAINS_UNASSIGNED
;
196 case STRINGPREP_MAP_TABLE
:
197 if (UNAPPLICAPLEFLAGS (flags
, profile
[i
].flags
))
199 rc
= stringprep_apply_table_to_string
200 (ucs4
, &ucs4len
, maxucs4len
, profile
[i
].table
, profile
[i
].name
);
201 if (rc
!= STRINGPREP_OK
)
205 case STRINGPREP_BIDI_PROHIBIT_TABLE
:
206 case STRINGPREP_BIDI_RAL_TABLE
:
207 case STRINGPREP_BIDI_L_TABLE
:
210 case STRINGPREP_BIDI
:
212 int done_prohibited
= 0;
215 int contains_ral
= -1;
219 for (j
= 0; profile
[j
].operation
; j
++)
220 if (profile
[j
].operation
== STRINGPREP_BIDI_PROHIBIT_TABLE
)
223 k
= stringprep_find_string_in_table (ucs4
, ucs4len
,
224 NULL
, profile
[j
].table
);
227 rc
= STRINGPREP_BIDI_CONTAINS_PROHIBITED
;
231 else if (profile
[j
].operation
== STRINGPREP_BIDI_RAL_TABLE
)
234 if (stringprep_find_string_in_table
235 (ucs4
, ucs4len
, NULL
, profile
[j
].table
) != -1)
238 else if (profile
[j
].operation
== STRINGPREP_BIDI_L_TABLE
)
241 if (stringprep_find_string_in_table
242 (ucs4
, ucs4len
, NULL
, profile
[j
].table
) != -1)
246 if (!done_prohibited
|| !done_ral
|| !done_l
)
248 rc
= STRINGPREP_PROFILE_ERROR
;
252 if (contains_ral
!= -1 && contains_l
!= -1)
254 rc
= STRINGPREP_BIDI_BOTH_L_AND_RAL
;
258 if (contains_ral
!= -1)
260 if (!(stringprep_find_character_in_table
261 (ucs4
[0], profile
[contains_ral
].table
) != -1 &&
262 stringprep_find_character_in_table
263 (ucs4
[ucs4len
- 1], profile
[contains_ral
].table
) != -1))
265 rc
= STRINGPREP_BIDI_LEADTRAIL_NOT_RAL
;
273 rc
= STRINGPREP_PROFILE_ERROR
;
279 p
= stringprep_ucs4_to_utf8 (ucs4
, ucs4len
, 0, 0);
281 if (strlen (p
) >= maxlen
)
283 rc
= STRINGPREP_TOO_SMALL_BUFFER
;
287 strcpy (in
, p
); /* flawfinder: ignore */
302 * stringprep_profile:
303 * @in: input/ouput array with string to prepare.
304 * @out: output variable with newly allocate string.
305 * @flags: optional stringprep profile flags.
306 * @profile: name of stringprep profile to use.
308 * Prepare the input UTF-8 string according to the stringprep profile.
309 * Normally application programmers use stringprep profile macros such
310 * as stringprep_nameprep(), stringprep_kerberos5() etc instead of
311 * calling this function directly.
313 * Note that you must convert strings entered in the systems locale
314 * into UTF-8 before using this function.
316 * The output @out variable must be deallocated by the caller.
318 * Return value: Returns 0 iff successful, or an error code.
321 stringprep_profile (char *in
, char **out
, char *profile
, int flags
)
323 Stringprep_profiles
*p
;
328 for (p
= &stringprep_profiles
[0]; p
->name
; p
++)
329 if (strcmp(p
->name
, profile
) == 0)
332 if (!p
|| !p
->name
|| !p
->tables
)
333 return STRINGPREP_UNKNOWN_PROFILE
;
335 len
= strlen(in
) + BUFSIZ
;
336 str
= (char*) malloc(len
);
338 return STRINGPREP_MALLOC_ERROR
;
342 rc
= stringprep (str
, len
, flags
, p
->tables
);
344 if (rc
== STRINGPREP_OK
)