1#ifndef lint 2static char *rcsid = "$Id: aliaslist.c,v 1.1 2003/06/04 00:25:47 marka Exp $"; 3#endif 4 5/* 6 * Copyright (c) 2002 Japan Network Information Center. All rights reserved. 7 * 8 * By using this file, you agree to the terms and conditions set forth bellow. 9 * 10 * LICENSE TERMS AND CONDITIONS 11 * 12 * The following License Terms and Conditions apply, unless a different 13 * license is obtained from Japan Network Information Center ("JPNIC"), 14 * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda, 15 * Chiyoda-ku, Tokyo 101-0047, Japan. 16 * 17 * 1. Use, Modification and Redistribution (including distribution of any 18 * modified or derived work) in source and/or binary forms is permitted 19 * under this License Terms and Conditions. 20 * 21 * 2. Redistribution of source code must retain the copyright notices as they 22 * appear in each source code file, this License Terms and Conditions. 23 * 24 * 3. Redistribution in binary form must reproduce the Copyright Notice, 25 * this License Terms and Conditions, in the documentation and/or other 26 * materials provided with the distribution. For the purposes of binary 27 * distribution the "Copyright Notice" refers to the following language: 28 * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved." 29 * 30 * 4. The name of JPNIC may not be used to endorse or promote products 31 * derived from this Software without specific prior written approval of 32 * JPNIC. 33 * 34 * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC 35 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 36 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 37 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE 38 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 39 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 40 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 42 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 43 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 44 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 45 */ 46 47#include <config.h> 48 49#include <stddef.h> 50#include <stdlib.h> 51#include <stdio.h> 52#include <string.h> 53#include <ctype.h> 54 55#include <idn/aliaslist.h> 56#include <idn/assert.h> 57#include <idn/logmacro.h> 58#include <idn/result.h> 59 60struct aliasitem { 61 char *pattern; /* name pattern */ 62 char *encoding; /* MIME-preferred charset name */ 63 struct aliasitem *next; 64}; 65typedef struct aliasitem *aliasitem_t; 66 67struct idn__aliaslist { 68 aliasitem_t first_item; /* first item of the list */ 69}; 70 71static idn_result_t 72additem_to_top(idn__aliaslist_t list, 73 const char *pattern, const char *encoding); 74 75static idn_result_t 76additem_to_bottom(idn__aliaslist_t list, 77 const char *pattern, const char *encoding); 78 79static int match(const char *pattern, const char *str); 80 81static idn_result_t create_item(const char *pattern, const char *encoding, 82 aliasitem_t *itemp); 83 84#ifdef DEBUG 85static void dump_list(idn__aliaslist_t list); 86#endif 87 88idn_result_t 89idn__aliaslist_create(idn__aliaslist_t *listp) { 90 static int size = sizeof(struct idn__aliaslist); 91 92 TRACE(("idn__aliaslist_create()\n")); 93 94 assert(listp != NULL); 95 96 if ((*listp = malloc(size)) == NULL) { 97 return (idn_nomemory); 98 } 99 (*listp)->first_item = NULL; 100 101 return (idn_success); 102} 103 104void 105idn__aliaslist_destroy(idn__aliaslist_t list) { 106 aliasitem_t current; 107 aliasitem_t next; 108 109 TRACE(("idn__aliaslist_destroy()\n")); 110 111 assert(list != NULL); 112 113 current = list->first_item; 114 while (current != NULL) { 115 if (current->pattern != NULL) { 116 free(current->pattern); 117 } 118 if (current->encoding != NULL) { 119 free(current->encoding); 120 } 121 next = current->next; 122 free(current); 123 current = next; 124 } 125 free(list); 126} 127 128idn_result_t 129idn__aliaslist_aliasfile(idn__aliaslist_t list, const char *path) { 130 FILE *fp; 131 int line_no; 132 idn_result_t r = idn_success; 133 char line[200], alias[200], real[200]; 134 135 assert(path != NULL); 136 137 TRACE(("idn__aliaslist_aliasfile(path=%s)\n", path)); 138 139 if ((fp = fopen(path, "r")) == NULL) { 140 return (idn_nofile); 141 } 142 for (line_no = 1; fgets(line, sizeof(line), fp) != NULL; line_no++) { 143 unsigned char *p = (unsigned char *)line; 144 145 while (isascii(*p) && isspace(*p)) 146 p++; 147 if (*p == '#' || *p == '\n') 148 continue; 149 if (sscanf((char *)p, "%s %s", alias, real) == 2) { 150 r = additem_to_bottom(list, alias, real); 151 if (r != idn_success) 152 break; 153 } else { 154 INFO(("idn__aliaslist_aliasfile: file %s has " 155 "invalid contents at line %d\n", 156 path, line_no)); 157 r = idn_invalid_syntax; 158 break; 159 } 160 } 161 fclose(fp); 162 163#ifdef DEBUG 164 dump_list(list); 165#endif 166 167 return (r); 168} 169 170idn_result_t 171idn__aliaslist_additem(idn__aliaslist_t list, 172 const char *pattern, const char *encoding, 173 int first_item) { 174 if (first_item) { 175 return additem_to_top(list, pattern, encoding); 176 } else { 177 return additem_to_bottom(list, pattern, encoding); 178 } 179} 180 181static idn_result_t 182additem_to_top(idn__aliaslist_t list, 183 const char *pattern, const char *encoding) { 184 aliasitem_t new_item; 185 idn_result_t r; 186 187 TRACE(("additem_to_top()\n")); 188 189 assert(list != NULL); 190 assert(pattern != NULL); 191 assert(encoding != NULL); 192 193 if ((r = create_item(pattern, encoding, &new_item)) 194 != idn_success) { 195 WARNING(("additem_to_top: malloc failed\n")); 196 return (r); 197 } 198 199 new_item->next = list->first_item; 200 list->first_item = new_item; 201 202#ifdef DEBUG 203 dump_list(list); 204#endif 205 206 return (idn_success); 207} 208 209static idn_result_t 210additem_to_bottom(idn__aliaslist_t list, 211 const char *pattern, const char *encoding) { 212 aliasitem_t new_item; 213 idn_result_t r; 214 215 TRACE(("additem_to_bottom()\n")); 216 217 assert(list != NULL); 218 assert(pattern != NULL); 219 assert(encoding != NULL); 220 221 r = create_item(pattern, encoding, &new_item); 222 if (r != idn_success) { 223 WARNING(("additem_to_bottom: malloc failed\n")); 224 return r; 225 } 226 227 if (list->first_item == NULL) { 228 list->first_item = new_item; 229 } else { 230 aliasitem_t cur_item = list->first_item; 231 for (;;) { 232 if (cur_item->next == NULL) { 233 break; 234 } 235 cur_item = cur_item->next; 236 } 237 cur_item->next = new_item; 238 } 239 240 return (idn_success); 241} 242 243idn_result_t 244idn__aliaslist_find(idn__aliaslist_t list, 245 const char *pattern, char **encodingp) { 246 aliasitem_t current; 247 248 TRACE(("idn__aliaslist_find()\n")); 249 250 assert(list != NULL); 251 assert(pattern != NULL); 252 253#ifdef DEBUG 254 DUMP(("target pattern: %s\n", pattern)); 255#endif 256 current = list->first_item; 257 while (current != NULL) { 258#ifdef DEBUG 259 DUMP(("current pattern: %s, encoding: %s\n", 260 current->pattern, current->encoding)); 261#endif 262 if (match(current->pattern, pattern)) { 263 *encodingp = current->encoding; 264 return (idn_success); 265 } 266 current = current->next; 267 } 268 269 TRACE(("idn__aliaslist_find(): not found\n")); 270 *encodingp = (char *)pattern; 271 return (idn_notfound); 272} 273 274/* 275 * Wild card matching function that supports only '*'. 276 */ 277static int 278match(const char *pattern, const char *str) { 279 for (;;) { 280 int c; 281 282 switch (c = *pattern++) { 283 case '\0': 284 return (*str == '\0'); 285 case '*': 286 while (!match(pattern, str)) { 287 if (*str == '\0') 288 return (0); 289 str++; 290 } 291 return (1); 292 break; 293 default: 294 if (*str++ != c) 295 return (0); 296 break; 297 } 298 } 299} 300 301/* 302 * List item creation. 303 * pattern and encoding must not be NULL. 304 */ 305static idn_result_t 306create_item(const char *pattern, const char *encoding, 307 aliasitem_t *itemp) { 308 static size_t size = sizeof(struct aliasitem); 309 310 assert(pattern != NULL); 311 assert(encoding != NULL); 312 313 if ((*itemp = malloc(size)) == NULL) 314 return (idn_nomemory); 315 316 if (((*itemp)->pattern = malloc(strlen(pattern) + 1)) == NULL) { 317 free(*itemp); 318 *itemp = NULL; 319 return (idn_nomemory); 320 } 321 322 if (((*itemp)->encoding = malloc(strlen(encoding) + 1)) == NULL) { 323 free((*itemp)->pattern); 324 free(*itemp); 325 *itemp = NULL; 326 return (idn_nomemory); 327 } 328 329 (void)strcpy((*itemp)->pattern, pattern); 330 (void)strcpy((*itemp)->encoding, encoding); 331 (*itemp)->next = NULL; 332 333 return (idn_success); 334} 335 336#ifdef DEBUG 337static void 338dump_list(idn__aliaslist_t list) { 339 aliasitem_t item; 340 int i; 341 342 TRACE(("dump_list()\n")); 343 if (list == NULL) { 344 TRACE(("list is NULL\n")); 345 return; 346 } 347 item = list->first_item; 348 i = 0; 349 while (item != NULL) { 350 DUMP(("%d: %s\t%s\n", i, item->pattern, item->encoding)); 351 item = item->next; 352 i++; 353 } 354} 355#endif 356