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)))
97 stringprep (char *in
, int maxlen
, int flags
, Stringprep_profile
* profile
)
102 unsigned long *q
= 0;
107 ucs4
= stringprep_utf8_to_ucs4 (in
, -1, &ucs4len
);
108 maxucs4len
= 4 * ucs4len
+ 10;
109 ucs4
= realloc (ucs4
, 1 + maxucs4len
* sizeof (unsigned long));
112 rc
= STRINGPREP_MALLOC_ERROR
;
119 printf ("\t;; in: ");
120 for (j
= 0; j
< ucs4len
; j
++)
121 printf ("U+%06lx ", ucs4
[j
]);
126 for (i
= 0; profile
[i
].operation
; i
++)
128 switch (profile
[i
].operation
)
130 case STRINGPREP_NFKC
:
131 if (UNAPPLICAPLEFLAGS (flags
, profile
[i
].flags
))
133 if (flags
& STRINGPREP_NO_NFKC
&& !profile
[i
].flags
)
135 /* Profile requires NFKC, but callee asked for no NFKC. */
136 rc
= STRINGPREP_FLAG_ERROR
;
140 q
= stringprep_ucs4_nfkc_normalize (ucs4
, ucs4len
);
144 rc
= STRINGPREP_NFKC_FAILED
;
148 for (ucs4len
= 0; ucs4
[ucs4len
]; ucs4len
++)
156 case STRINGPREP_PROHIBIT_TABLE
:
157 if (stringprep_find_string_in_table
158 (ucs4
, ucs4len
, NULL
, profile
[i
].table
) != -1)
160 rc
= STRINGPREP_CONTAINS_PROHIBITED
;
165 case STRINGPREP_UNASSIGNED_TABLE
:
166 if (UNAPPLICAPLEFLAGS (flags
, profile
[i
].flags
))
168 if (flags
& STRINGPREP_NO_UNASSIGNED
)
169 if (stringprep_find_string_in_table
170 (ucs4
, ucs4len
, NULL
, profile
[i
].table
) != -1)
172 rc
= STRINGPREP_CONTAINS_UNASSIGNED
;
177 case STRINGPREP_MAP_TABLE
:
178 if (UNAPPLICAPLEFLAGS (flags
, profile
[i
].flags
))
180 rc
= stringprep_apply_table_to_string
181 (ucs4
, &ucs4len
, maxucs4len
, profile
[i
].table
);
182 if (rc
!= STRINGPREP_OK
)
186 case STRINGPREP_BIDI_PROHIBIT_TABLE
:
187 case STRINGPREP_BIDI_RAL_TABLE
:
188 case STRINGPREP_BIDI_L_TABLE
:
191 case STRINGPREP_BIDI
:
193 int done_prohibited
= 0;
196 int contains_ral
= -1;
200 for (j
= 0; profile
[j
].operation
; j
++)
201 if (profile
[j
].operation
== STRINGPREP_BIDI_PROHIBIT_TABLE
)
204 if (stringprep_find_string_in_table
205 (ucs4
, ucs4len
, NULL
, profile
[j
].table
) != -1)
207 rc
= STRINGPREP_BIDI_CONTAINS_PROHIBITED
;
211 else if (profile
[j
].operation
== STRINGPREP_BIDI_RAL_TABLE
)
214 if (stringprep_find_string_in_table
215 (ucs4
, ucs4len
, NULL
, profile
[j
].table
) != -1)
218 else if (profile
[j
].operation
== STRINGPREP_BIDI_L_TABLE
)
221 if (stringprep_find_string_in_table
222 (ucs4
, ucs4len
, NULL
, profile
[j
].table
) != -1)
226 if (!done_prohibited
|| !done_ral
|| !done_l
)
228 rc
= STRINGPREP_PROFILE_ERROR
;
232 if (contains_ral
!= -1 && contains_l
!= -1)
234 rc
= STRINGPREP_BIDI_BOTH_L_AND_RAL
;
238 if (contains_ral
!= -1)
239 if (!(stringprep_find_character_in_table
240 (ucs4
[0], profile
[contains_ral
].table
) != -1 &&
241 stringprep_find_character_in_table
242 (ucs4
[ucs4len
- 1], profile
[contains_ral
].table
) != -1))
244 rc
= STRINGPREP_BIDI_LEADTRAIL_NOT_RAL
;
251 rc
= STRINGPREP_PROFILE_ERROR
;
258 printf ("\t;; %5s: ", profile
[i
].name
? profile
[i
].name
: "<NONAME>");
259 for (j
= 0; j
< ucs4len
; j
++)
260 printf ("U+%06lx ", ucs4
[j
]);
266 p
= stringprep_ucs4_to_utf8 (ucs4
, ucs4len
, 0, 0);
268 if (strlen (p
) >= maxlen
)
270 rc
= STRINGPREP_TOO_SMALL_BUFFER
;
274 strcpy (in
, p
); /* flawfinder: ignore */