1 /* $NetBSD: filechecker.c,v 1.4 2014/12/10 04:37:55 christos Exp $ */ 2 3 #ifndef lint 4 static char *rcsid = "Id: filechecker.c,v 1.1 2003/06/04 00:25:52 marka Exp "; 5 #endif 6 7 /* 8 * Copyright (c) 2001,2002 Japan Network Information Center. 9 * All rights reserved. 10 * 11 * By using this file, you agree to the terms and conditions set forth bellow. 12 * 13 * LICENSE TERMS AND CONDITIONS 14 * 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. 19 * 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. 23 * 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. 26 * 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." 32 * 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 35 * JPNIC. 36 * 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. 48 */ 49 50 #include <config.h> 51 52 #include <stdlib.h> 53 #include <stdio.h> 54 #include <string.h> 55 #include <ctype.h> 56 57 #include <idn/result.h> 58 #include <idn/assert.h> 59 #include <idn/log.h> 60 #include <idn/logmacro.h> 61 #include <idn/ucsset.h> 62 #include <idn/filechecker.h> 63 #include <idn/debug.h> 64 65 #define SUPPORT_VERSIONING 66 67 struct idn__filechecker { 68 idn_ucsset_t set; 69 }; 70 71 static idn_result_t read_file(const char *file, FILE *fp, 72 idn_ucsset_t set); 73 static int get_range(char *s, unsigned long *ucs1, 74 unsigned long *ucs2); 75 static char *get_ucs(char *p, unsigned long *vp); 76 77 78 idn_result_t 79 idn__filechecker_create(const char *file, idn__filechecker_t *ctxp) { 80 FILE *fp; 81 idn__filechecker_t ctx; 82 idn_result_t r; 83 84 assert(file != NULL && ctxp != NULL); 85 86 TRACE(("idn__filechecker_create(file=\"%-.100s\")\n", file)); 87 88 if ((fp = fopen(file, "r")) == NULL) { 89 WARNING(("idn__filechecker_create: cannot open %-.100s\n", 90 file)); 91 return (idn_nofile); 92 } 93 94 if ((ctx = malloc(sizeof(struct idn__filechecker))) == NULL) 95 return (idn_nomemory); 96 97 if ((r = idn_ucsset_create(&ctx->set)) != idn_success) { 98 free(ctx); 99 return (r); 100 } 101 102 r = read_file(file, fp, ctx->set); 103 fclose(fp); 104 105 if (r == idn_success) { 106 idn_ucsset_fix(ctx->set); 107 *ctxp = ctx; 108 } else { 109 idn_ucsset_destroy(ctx->set); 110 free(ctx); 111 } 112 return (r); 113 } 114 115 void 116 idn__filechecker_destroy(idn__filechecker_t ctx) { 117 assert(ctx != NULL); 118 119 TRACE(("idn__filechecker_destroy()\n")); 120 121 idn_ucsset_destroy(ctx->set); 122 free(ctx); 123 } 124 125 idn_result_t 126 idn__filechecker_lookup(idn__filechecker_t ctx, const unsigned long *str, 127 const unsigned long **found) { 128 idn_result_t r = idn_success; 129 130 assert(ctx != NULL && str != NULL); 131 132 TRACE(("idn__filechecker_lookup(str=\"%s\")\n", 133 idn__debug_ucs4xstring(str, 50))); 134 135 while (*str != '\0') { 136 int exists; 137 138 r = idn_ucsset_lookup(ctx->set, *str, &exists); 139 140 if (r != idn_success) { 141 return (r); 142 } else if (exists) { 143 /* Found. */ 144 *found = str; 145 return (idn_success); 146 } 147 str++; 148 } 149 *found = NULL; 150 return (idn_success); 151 } 152 153 static idn_result_t 154 read_file(const char *file, FILE *fp, idn_ucsset_t set) { 155 char line[256]; 156 idn_result_t r; 157 int lineno = 0; 158 159 while (fgets(line, sizeof(line), fp) != NULL) { 160 char *p = line; 161 unsigned long ucs1, ucs2; 162 163 lineno++; 164 while (isspace((unsigned char)*p)) 165 p++; 166 if (*p == '\0' || *p == '#') 167 continue; 168 169 #ifdef SUPPORT_VERSIONING 170 /* Skip version tag. */ 171 if (lineno == 1 && strncmp("version=", line, 8) == 0) 172 continue; 173 #endif 174 if (!get_range(p, &ucs1, &ucs2)) { 175 WARNING(("syntax error in file \"%-.100s\" line %d: " 176 "%-.100s", file, lineno, line)); 177 return (idn_invalid_syntax); 178 } 179 if ((r = idn_ucsset_addrange(set, ucs1, ucs2)) != idn_success) 180 return (r); 181 } 182 return (idn_success); 183 } 184 185 static int 186 get_range(char *s, unsigned long *ucs1, unsigned long *ucs2) { 187 if ((s = get_ucs(s, ucs1)) == NULL) 188 return (0); 189 *ucs2 = *ucs1; 190 191 switch (s[0]) { 192 case '\0': 193 case '\n': 194 case '#': 195 case ';': 196 return (1); 197 case '-': 198 break; 199 default: 200 return (0); 201 } 202 203 if ((s = get_ucs(s + 1, ucs2)) == NULL) 204 return (0); 205 206 if (*ucs1 > *ucs2) { 207 INFO(("idn__filechecker_create: invalid range spec " 208 "U+%X-U+%X\n", *ucs1, *ucs2)); 209 return (0); 210 } 211 212 switch (s[0]) { 213 case '\0': 214 case '\n': 215 case '#': 216 case ';': 217 return (1); 218 default: 219 return (0); 220 } 221 } 222 223 224 static char * 225 get_ucs(char *p, unsigned long *vp) { 226 char *end; 227 228 /* Skip leading space */ 229 while (isspace((unsigned char)*p)) 230 p++; 231 232 /* Skip optional 'U+' */ 233 if (strncmp(p, "U+", 2) == 0) 234 p += 2; 235 236 *vp = strtoul(p, &end, 16); 237 if (end == p) { 238 INFO(("idn__filechecker_create: UCS code point expected\n")); 239 return (NULL); 240 } 241 p = end; 242 243 /* Skip trailing space */ 244 while (isspace((unsigned char)*p)) 245 p++; 246 return p; 247 } 248 249 idn_result_t 250 idn__filechecker_createproc(const char *parameter, void **ctxp) { 251 return idn__filechecker_create(parameter, (idn__filechecker_t *)ctxp); 252 } 253 254 void 255 idn__filechecker_destroyproc(void *ctxp) { 256 idn__filechecker_destroy((idn__filechecker_t)ctxp); 257 } 258 259 idn_result_t 260 idn__filechecker_lookupproc(void *ctx, const unsigned long *str, 261 const unsigned long **found) { 262 return idn__filechecker_lookup((idn__filechecker_t)ctx, str, found); 263 } 264