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
30 # if !STDC_HEADERS && HAVE_MEMORY_H
39 # include <inttypes.h>
46 #include <sys/types.h>
49 #include <stringprep.h>
50 #include <stringprep_generic.h>
55 stringprep_find_character_in_table (long ucs4
,
56 struct stringprep_table_element
*table
)
60 for (i
= 0; table
[i
].start
; i
++)
61 if (ucs4
>= table
[i
].start
&&
62 ucs4
<= (table
[i
].end
? table
[i
].end
: table
[i
].start
))
69 stringprep_find_string_in_table (long *ucs4
,
72 struct stringprep_table_element
*table
)
76 for (j
= 0; j
< ucs4len
; j
++)
77 if ((pos
= stringprep_find_character_in_table (ucs4
[j
], table
)) != -1)
88 stringprep_apply_table_to_string (long *ucs4
,
91 struct stringprep_table_element
*table
)
98 for (i
= 0; i
< *ucs4len
; i
++)
99 printf ("U+%06x ", ucs4
[i
]);
104 stringprep_find_string_in_table (ucs4
, *ucs4len
, &i
, table
)) != -1)
107 printf ("hit %06x %06x-%06x\n", ucs4
[pos
], table
[i
].start
,
111 for (maplen
= 0; table
[i
].map
[maplen
]; maplen
++)
114 if (*ucs4len
- 1 + maplen
>= maxucs4len
)
115 return STRINGPREP_TOO_SMALL_BUFFER
;
117 memmove (&ucs4
[pos
+ maplen
], &ucs4
[pos
+ 1],
118 *ucs4len
* sizeof (uint32_t) - (&ucs4
[pos
+ 1] - ucs4
));
119 memcpy (&ucs4
[pos
], table
[i
].map
, sizeof (uint32_t) * maplen
);
120 *ucs4len
= *ucs4len
- 1 + maplen
;
125 for (i
= 0; i
< *ucs4len
; i
++)
126 printf ("U+%06x ", ucs4
[i
]);
130 return STRINGPREP_OK
;
134 stringprep (char *in
, int maxlen
, int flags
, stringprep_profile
* profile
)
144 ucs4
= stringprep_utf8_to_ucs4_fast (in
, -1, &ucs4len
);
145 maxucs4len
= 4 * ucs4len
+ 10;
146 ucs4
= realloc (ucs4
, 1 + maxucs4len
* sizeof (long));
149 rc
= STRINGPREP_MALLOC_ERROR
;
153 for (i
= 0; profile
[i
].flags
|| profile
[i
].table
; i
++)
155 if (!profile
[i
].table
&& profile
[i
].flags
== ~STRINGPREP_NO_NFKC
&&
156 !(flags
& STRINGPREP_NO_NFKC
))
159 q
= stringprep_ucs4_nfkc_normalize (ucs4
, ucs4len
);
163 rc
= STRINGPREP_NFKC_FAILED
;
167 for (ucs4len
= 0; ucs4
[ucs4len
]; ucs4len
++)
176 else if (profile
[i
].flags
& STRINGPREP_INVERT_MAGIC
)
178 if (flags
& (~profile
[i
].flags
))
183 if (profile
[i
].flags
!= 0 && !(flags
& profile
[i
].flags
))
187 if (!profile
[i
].table
)
188 continue; /* this indicates an error in the profile ... */
190 rc
= stringprep_apply_table_to_string
191 (ucs4
, &ucs4len
, maxucs4len
, profile
[i
].table
);
192 if (rc
!= STRINGPREP_OK
)
196 if (!(flags
& STRINGPREP_NO_BIDI
))
198 int done_prohibited
= 0;
201 int contains_ral
= 0;
204 for (i
= 0; profile
[i
].flags
|| profile
[i
].table
; i
++)
205 if (profile
[i
].flags
== STRINGPREP_BIDI_PROHIBITED_MASK
)
208 rc
= stringprep_apply_table_to_string
209 (ucs4
, &ucs4len
, maxucs4len
, profile
[i
].table
);
210 if (rc
!= STRINGPREP_OK
)
213 else if (profile
[i
].flags
== STRINGPREP_BIDI_RAL_MASK
)
216 contains_ral
= stringprep_find_string_in_table
217 (ucs4
, ucs4len
, 0, profile
[i
].table
) != -1;
219 else if (profile
[i
].flags
== STRINGPREP_BIDI_L_MASK
)
222 contains_l
= stringprep_find_string_in_table
223 (ucs4
, ucs4len
, 0, profile
[i
].table
) != -1;
226 if (!done_prohibited
|| !done_ral
|| !done_l
)
228 rc
= STRINGPREP_BIDI_NOT_IN_PROFILE
;
232 if (contains_ral
&& contains_l
)
234 rc
= STRINGPREP_BIDI_BOTH_L_AND_RAL
;
239 (!stringprep_find_character_in_table (ucs4
[0],
241 !stringprep_find_character_in_table (ucs4
[ucs4len
],
244 rc
= STRINGPREP_BIDI_LEADTRAIL_NOT_RAL
;
249 p
= stringprep_ucs4_to_utf8 (ucs4
, ucs4len
, 0, 0);
251 if (strlen (p
) >= maxlen
)
253 rc
= STRINGPREP_TOO_SMALL_BUFFER
;