1 /* $NetBSD: checker.c,v 1.4 2014/12/10 04:37:55 christos Exp $ */
4 static char *rcsid
= "Id: checker.c,v 1.1 2003/06/04 00:25:49 marka Exp ";
8 * Copyright (c) 2001,2002 Japan Network Information Center.
11 * By using this file, you agree to the terms and conditions set forth bellow.
13 * LICENSE TERMS AND CONDITIONS
15 * The following License Terms and Conditions apply, unless a different
16 * license is obtained from Japan Network Information Center ("JPNIC"),
17 * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
18 * Chiyoda-ku, Tokyo 101-0047, Japan.
20 * 1. Use, Modification and Redistribution (including distribution of any
21 * modified or derived work) in source and/or binary forms is permitted
22 * under this License Terms and Conditions.
24 * 2. Redistribution of source code must retain the copyright notices as they
25 * appear in each source code file, this License Terms and Conditions.
27 * 3. Redistribution in binary form must reproduce the Copyright Notice,
28 * this License Terms and Conditions, in the documentation and/or other
29 * materials provided with the distribution. For the purposes of binary
30 * distribution the "Copyright Notice" refers to the following language:
31 * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
33 * 4. The name of JPNIC may not be used to endorse or promote products
34 * derived from this Software without specific prior written approval of
37 * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
38 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
39 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
40 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
41 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
43 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
44 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
45 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
46 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
47 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
56 #include <idn/result.h>
57 #include <idn/assert.h>
58 #include <idn/logmacro.h>
59 #include <idn/checker.h>
60 #include <idn/strhash.h>
61 #include <idn/debug.h>
64 * Type for checking scheme.
69 idn_checker_createproc_t create
;
70 idn_checker_destroyproc_t destroy
;
71 idn_checker_lookupproc_t lookup
;
76 * Standard checking schemes.
78 static const check_scheme_t rfc3491_prohibit_scheme
= {
81 idn_nameprep_createproc
,
82 idn_nameprep_destroyproc
,
83 idn_nameprep_prohibitproc
,
87 static const check_scheme_t rfc3491_unasigned_scheme
= {
90 idn_nameprep_createproc
,
91 idn_nameprep_destroyproc
,
92 idn_nameprep_unassignedproc
,
96 static const check_scheme_t rfc3491_bidi_scheme
= {
99 idn_nameprep_createproc
,
100 idn_nameprep_destroyproc
,
101 idn_nameprep_bidiproc
,
105 static const check_scheme_t filecheck_prohibit_scheme
= {
108 idn__filechecker_createproc
,
109 idn__filechecker_destroyproc
,
110 idn__filechecker_lookupproc
,
114 static const check_scheme_t filecheck_unassigned_scheme
= {
115 "unassigned#fileset",
117 idn__filechecker_createproc
,
118 idn__filechecker_destroyproc
,
119 idn__filechecker_lookupproc
,
123 static const check_scheme_t
*standard_check_schemes
[] = {
124 &rfc3491_unasigned_scheme
,
125 &rfc3491_prohibit_scheme
,
126 &rfc3491_bidi_scheme
,
127 &filecheck_prohibit_scheme
,
128 &filecheck_unassigned_scheme
,
133 * Hash table for checking schemes.
135 static idn__strhash_t scheme_hash
= NULL
;
138 * Mapper object type.
143 check_scheme_t
*schemes
;
147 #define MAPPER_INITIAL_SCHEME_SIZE 1
150 idn_checker_initialize(void) {
152 check_scheme_t
**scheme
;
154 TRACE(("idn_checker_initialize()\n"));
156 if (scheme_hash
!= NULL
) {
157 r
= idn_success
; /* already initialized */
161 r
= idn__strhash_create(&scheme_hash
);
162 if (r
!= idn_success
) {
166 for (scheme
= (check_scheme_t
**)standard_check_schemes
;
167 *scheme
!= NULL
; scheme
++) {
168 r
= idn__strhash_put(scheme_hash
, (*scheme
)->prefix
, *scheme
);
169 if (r
!= idn_success
)
175 if (r
!= idn_success
) {
176 if (scheme_hash
!= NULL
) {
177 idn__strhash_destroy(scheme_hash
, NULL
);
181 TRACE(("idn_checker_initialize(): %s\n", idn_result_tostring(r
)));
186 idn_checker_create(idn_checker_t
*ctxp
) {
187 idn_checker_t ctx
= NULL
;
190 assert(scheme_hash
!= NULL
);
191 assert(ctxp
!= NULL
);
193 TRACE(("idn_checker_create()\n"));
195 ctx
= (idn_checker_t
) malloc(sizeof(struct idn_checker
));
201 ctx
->schemes
= (check_scheme_t
*) malloc(sizeof(check_scheme_t
)
202 * MAPPER_INITIAL_SCHEME_SIZE
);
203 if (ctx
->schemes
== NULL
) {
209 ctx
->scheme_size
= MAPPER_INITIAL_SCHEME_SIZE
;
210 ctx
->reference_count
= 1;
214 if (r
!= idn_success
) {
219 TRACE(("idn_checker_create(): %s\n", idn_result_tostring(r
)));
224 idn_checker_destroy(idn_checker_t ctx
) {
227 assert(scheme_hash
!= NULL
);
230 TRACE(("idn_checker_destroy()\n"));
232 ctx
->reference_count
--;
233 if (ctx
->reference_count
<= 0) {
234 TRACE(("idn_checker_destroy(): the object is destroyed\n"));
235 for (i
= 0; i
< ctx
->nschemes
; i
++)
236 ctx
->schemes
[i
].destroy(ctx
->schemes
[i
].context
);
240 TRACE(("idn_checker_destroy(): "
241 "update reference count (%d->%d)\n",
242 ctx
->reference_count
+ 1, ctx
->reference_count
));
247 idn_checker_incrref(idn_checker_t ctx
) {
248 assert(ctx
!= NULL
&& scheme_hash
!= NULL
);
250 TRACE(("idn_checker_incrref()\n"));
251 TRACE(("idn_checker_incrref: update reference count (%d->%d)\n",
252 ctx
->reference_count
, ctx
->reference_count
+ 1));
254 ctx
->reference_count
++;
258 idn_checker_add(idn_checker_t ctx
, const char *scheme_name
) {
260 check_scheme_t
*scheme
;
261 const char *scheme_prefix
;
262 const char *scheme_parameter
;
263 void *scheme_context
= NULL
;
266 assert(scheme_hash
!= NULL
);
269 TRACE(("idn_checker_add(scheme_name=%s)\n",
270 idn__debug_xstring(scheme_name
, 50)));
273 * Split `scheme_name' into `scheme_prefix' and `scheme_parameter'.
275 scheme_parameter
= strchr(scheme_name
, ':');
276 if (scheme_parameter
== NULL
) {
277 scheme_prefix
= scheme_name
;
278 scheme_parameter
= NULL
;
280 ptrdiff_t scheme_prefixlen
;
282 scheme_prefixlen
= scheme_parameter
- scheme_name
;
283 buffer
= (char *) malloc(scheme_prefixlen
+ 1);
284 if (buffer
== NULL
) {
288 memcpy(buffer
, scheme_name
, scheme_prefixlen
);
289 *(buffer
+ scheme_prefixlen
) = '\0';
290 scheme_prefix
= buffer
;
297 if (idn__strhash_get(scheme_hash
, scheme_prefix
, (void **)&scheme
)
299 ERROR(("idn_checker_add(): invalid scheme \"%-.30s\"\n",
301 r
= idn_invalid_name
;
304 if (scheme_parameter
== NULL
&& scheme
->parameter
!= NULL
)
305 scheme_parameter
= scheme
->parameter
;
310 assert(ctx
->nschemes
<= ctx
->scheme_size
);
312 if (ctx
->nschemes
== ctx
->scheme_size
) {
313 check_scheme_t
*new_schemes
;
315 new_schemes
= (check_scheme_t
*) realloc(ctx
->schemes
,
316 sizeof(check_scheme_t
) * ctx
->scheme_size
* 2);
317 if (new_schemes
== NULL
) {
321 ctx
->schemes
= new_schemes
;
322 ctx
->scheme_size
*= 2;
325 r
= scheme
->create(scheme_parameter
, &scheme_context
);
326 if (r
!= idn_success
)
329 memcpy(ctx
->schemes
+ ctx
->nschemes
, scheme
, sizeof(check_scheme_t
));
330 ctx
->schemes
[ctx
->nschemes
].context
= scheme_context
;
336 if (r
!= idn_success
)
337 free(scheme_context
);
338 TRACE(("idn_checker_add(): %s\n", idn_result_tostring(r
)));
343 idn_checker_addall(idn_checker_t ctx
, const char **scheme_names
,
348 assert(scheme_hash
!= NULL
);
349 assert(ctx
!= NULL
&& scheme_names
!= NULL
);
351 TRACE(("idn_checker_addall(nschemes=%d)\n", nschemes
));
353 for (i
= 0; i
< nschemes
; i
++) {
354 r
= idn_checker_add(ctx
, (const char *)*scheme_names
);
355 if (r
!= idn_success
)
362 TRACE(("idn_checker_addall(): %s\n", idn_result_tostring(r
)));
367 idn_checker_lookup(idn_checker_t ctx
, const unsigned long *ucs4
,
368 const unsigned long **found
) {
372 assert(scheme_hash
!= NULL
);
373 assert(ctx
!= NULL
&& ucs4
!= NULL
&& found
!= NULL
);
375 TRACE(("idn_checker_lookup(ucs4=\"%s\")\n",
376 idn__debug_ucs4xstring(ucs4
, 50)));
383 for (i
= 0; i
< ctx
->nschemes
; i
++) {
384 TRACE(("idn_checker_lookup(): lookup %s\n",
385 ctx
->schemes
[i
].prefix
));
387 r
= (ctx
->schemes
[i
].lookup
)(ctx
->schemes
[i
].context
, ucs4
,
389 if (r
!= idn_success
)
397 if (*found
== NULL
) {
398 TRACE(("idn_checker_lookup(): %s (not found)\n",
399 idn_result_tostring(r
)));
401 TRACE(("idn_checker_lookup(): %s (found \\x%04lx)\n",
402 idn_result_tostring(r
), **found
));
408 idn_checker_register(const char *prefix
,
409 idn_checker_createproc_t create
,
410 idn_checker_destroyproc_t destroy
,
411 idn_checker_lookupproc_t lookup
) {
413 check_scheme_t
*scheme
= NULL
;
415 assert(scheme_hash
!= NULL
);
416 assert(prefix
!= NULL
&& create
!= NULL
&& destroy
!= NULL
&&
419 TRACE(("idn_checker_register(prefix=%s)\n", prefix
));
421 scheme
= (check_scheme_t
*) malloc(sizeof(check_scheme_t
));
422 if (scheme
== NULL
) {
427 scheme
->prefix
= (char *) malloc(strlen(prefix
) + 1);
428 if (scheme
->prefix
== NULL
) {
433 strcpy(scheme
->prefix
, prefix
);
434 scheme
->parameter
= NULL
;
435 scheme
->create
= create
;
436 scheme
->destroy
= destroy
;
437 scheme
->lookup
= lookup
;
439 r
= idn__strhash_put(scheme_hash
, prefix
, scheme
);
441 if (r
!= idn_success
) {
443 free(scheme
->prefix
);
446 TRACE(("idn_checker_register(): %s\n", idn_result_tostring(r
)));