1#ifndef lint 2static char *rcsid = "$Id: filechecker.c,v 1.1 2003/06/04 00:25:52 marka Exp $"; 3#endif 4 5/* 6 * Copyright (c) 2001,2002 Japan Network Information Center. 7 * All rights reserved. 8 * 9 * By using this file, you agree to the terms and conditions set forth bellow. 10 * 11 * LICENSE TERMS AND CONDITIONS 12 * 13 * The following License Terms and Conditions apply, unless a different 14 * license is obtained from Japan Network Information Center ("JPNIC"), 15 * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda, 16 * Chiyoda-ku, Tokyo 101-0047, Japan. 17 * 18 * 1. Use, Modification and Redistribution (including distribution of any 19 * modified or derived work) in source and/or binary forms is permitted 20 * under this License Terms and Conditions. 21 * 22 * 2. Redistribution of source code must retain the copyright notices as they 23 * appear in each source code file, this License Terms and Conditions. 24 * 25 * 3. Redistribution in binary form must reproduce the Copyright Notice, 26 * this License Terms and Conditions, in the documentation and/or other 27 * materials provided with the distribution. For the purposes of binary 28 * distribution the "Copyright Notice" refers to the following language: 29 * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved." 30 * 31 * 4. The name of JPNIC may not be used to endorse or promote products 32 * derived from this Software without specific prior written approval of 33 * JPNIC. 34 * 35 * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC 36 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 37 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 38 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE 39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 40 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 41 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 42 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 43 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 44 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 45 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 46 */ 47 48#include <config.h> 49 50#include <stdlib.h> 51#include <stdio.h> 52#include <string.h> 53#include <ctype.h> 54 55#include <idn/result.h> 56#include <idn/assert.h> 57#include <idn/log.h> 58#include <idn/logmacro.h> 59#include <idn/ucsset.h> 60#include <idn/filechecker.h> 61#include <idn/debug.h> 62 63#define SUPPORT_VERSIONING 64 65struct idn__filechecker { 66 idn_ucsset_t set; 67}; 68 69static idn_result_t read_file(const char *file, FILE *fp, 70 idn_ucsset_t set); 71static int get_range(char *s, unsigned long *ucs1, 72 unsigned long *ucs2); 73static char *get_ucs(char *p, unsigned long *vp); 74 75 76idn_result_t 77idn__filechecker_create(const char *file, idn__filechecker_t *ctxp) { 78 FILE *fp; 79 idn__filechecker_t ctx; 80 idn_result_t r; 81 82 assert(file != NULL && ctxp != NULL); 83 84 TRACE(("idn__filechecker_create(file=\"%-.100s\")\n", file)); 85 86 if ((fp = fopen(file, "r")) == NULL) { 87 WARNING(("idn__filechecker_create: cannot open %-.100s\n", 88 file)); 89 return (idn_nofile); 90 } 91 92 if ((ctx = malloc(sizeof(struct idn__filechecker))) == NULL) 93 return (idn_nomemory); 94 95 if ((r = idn_ucsset_create(&ctx->set)) != idn_success) { 96 free(ctx); 97 return (r); 98 } 99 100 r = read_file(file, fp, ctx->set); 101 fclose(fp); 102 103 if (r == idn_success) { 104 idn_ucsset_fix(ctx->set); 105 *ctxp = ctx; 106 } else { 107 idn_ucsset_destroy(ctx->set); 108 free(ctx); 109 } 110 return (r); 111} 112 113void 114idn__filechecker_destroy(idn__filechecker_t ctx) { 115 assert(ctx != NULL); 116 117 TRACE(("idn__filechecker_destroy()\n")); 118 119 idn_ucsset_destroy(ctx->set); 120 free(ctx); 121} 122 123idn_result_t 124idn__filechecker_lookup(idn__filechecker_t ctx, const unsigned long *str, 125 const unsigned long **found) { 126 idn_result_t r = idn_success; 127 128 assert(ctx != NULL && str != NULL); 129 130 TRACE(("idn__filechecker_lookup(str=\"%s\")\n", 131 idn__debug_ucs4xstring(str, 50))); 132 133 while (*str != '\0') { 134 int exists; 135 136 r = idn_ucsset_lookup(ctx->set, *str, &exists); 137 138 if (r != idn_success) { 139 return (r); 140 } else if (exists) { 141 /* Found. */ 142 *found = str; 143 return (idn_success); 144 } 145 str++; 146 } 147 *found = NULL; 148 return (idn_success); 149} 150 151static idn_result_t 152read_file(const char *file, FILE *fp, idn_ucsset_t set) { 153 char line[256]; 154 idn_result_t r; 155 int lineno = 0; 156 157 while (fgets(line, sizeof(line), fp) != NULL) { 158 char *p = line; 159 unsigned long ucs1, ucs2; 160 161 lineno++; 162 while (isspace((unsigned char)*p)) 163 p++; 164 if (*p == '\0' || *p == '#') 165 continue; 166 167#ifdef SUPPORT_VERSIONING 168 /* Skip version tag. */ 169 if (lineno == 1 && strncmp("version=", line, 8) == 0) 170 continue; 171#endif 172 if (!get_range(p, &ucs1, &ucs2)) { 173 WARNING(("syntax error in file \"%-.100s\" line %d: " 174 "%-.100s", file, lineno, line)); 175 return (idn_invalid_syntax); 176 } 177 if ((r = idn_ucsset_addrange(set, ucs1, ucs2)) != idn_success) 178 return (r); 179 } 180 return (idn_success); 181} 182 183static int 184get_range(char *s, unsigned long *ucs1, unsigned long *ucs2) { 185 if ((s = get_ucs(s, ucs1)) == NULL) 186 return (0); 187 *ucs2 = *ucs1; 188 189 switch (s[0]) { 190 case '\0': 191 case '\n': 192 case '#': 193 case ';': 194 return (1); 195 case '-': 196 break; 197 default: 198 return (0); 199 } 200 201 if ((s = get_ucs(s + 1, ucs2)) == NULL) 202 return (0); 203 204 if (*ucs1 > *ucs2) { 205 INFO(("idn__filechecker_create: invalid range spec " 206 "U+%X-U+%X\n", *ucs1, *ucs2)); 207 return (0); 208 } 209 210 switch (s[0]) { 211 case '\0': 212 case '\n': 213 case '#': 214 case ';': 215 return (1); 216 default: 217 return (0); 218 } 219} 220 221 222static char * 223get_ucs(char *p, unsigned long *vp) { 224 char *end; 225 226 /* Skip leading space */ 227 while (isspace((unsigned char)*p)) 228 p++; 229 230 /* Skip optional 'U+' */ 231 if (strncmp(p, "U+", 2) == 0) 232 p += 2; 233 234 *vp = strtoul(p, &end, 16); 235 if (end == p) { 236 INFO(("idn__filechecker_create: UCS code point expected\n")); 237 return (NULL); 238 } 239 p = end; 240 241 /* Skip trailing space */ 242 while (isspace((unsigned char)*p)) 243 p++; 244 return p; 245} 246 247idn_result_t 248idn__filechecker_createproc(const char *parameter, void **ctxp) { 249 return idn__filechecker_create(parameter, (idn__filechecker_t *)ctxp); 250} 251 252void 253idn__filechecker_destroyproc(void *ctxp) { 254 idn__filechecker_destroy((idn__filechecker_t)ctxp); 255} 256 257idn_result_t 258idn__filechecker_lookupproc(void *ctx, const unsigned long *str, 259 const unsigned long **found) { 260 return idn__filechecker_lookup((idn__filechecker_t)ctx, str, found); 261} 262