static char rcsid[] = "@(#)$Id: charset.c,v 1.5 2006/08/02 08:46:02 hurtta Exp $"; /****************************************************************************** * The Elm (ME+) Mail System - $Revision: 1.5 $ $State: Exp $ * * Author: Kari Hurtta * or Kari Hurtta *****************************************************************************/ #include "def_misc.h" #include "s_me.h" #include "cs_imp.h" DEBUG_VAR(Debug,__FILE__,"charset"); static int name_ok P_((CONST char *name)); static int name_ok(name) CONST char *name; { if ('\0' == *name) return 0; return strlen(name) == strspn(name, "ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789abcdefghijklmnopqrstuvwxyz"); } static void dump_alias_info P_((FILE *f,struct charcode_info *info)); static void dump_alias_info(f,info) FILE *f; struct charcode_info *info; { int i; for (i = 0; i < charset_alias_count; i++) if (info == charset_alias_list[i].set && charset_alias_list[i].name) { if (name_ok(charset_alias_list[i].name)) elm_fprintf(f,FRM(";alias=%s"),charset_alias_list[i].name); else elm_fprintf(f,FRM(";alias=%Q"),charset_alias_list[i].name); } } void dump_map_info(f,info) FILE *f; struct charcode_info *info; { if (!info->MIME_name) { if (!info->codeset) fputs("# ",f); } else if (name_ok(info->MIME_name)) { fputs(info->MIME_name,f); } else { elm_fprintf(f,FRM("%Q"),info->MIME_name); } if (info->codeset) { elm_fprintf(f,FRM("%scodeset=%Q"), info->MIME_name ? ";" : "", info->codeset); } else if (0 != (info->flags & SET_nodata)) { fputs(";!",f); return; } if (&cs_unknown != info->charset_type) elm_fprintf(f,FRM(";type=%s"),info->charset_type->type_name); if (info->map_info && name_ok(info->map_info->map_name)) elm_fprintf(f,FRM(";map=%s"),info->map_info->map_name); else if (info->map_info) elm_fprintf(f,FRM(";map=%Q"),info->map_info->map_name); if (info->subtype && info->subtype->MIME_name && name_ok(info->subtype->MIME_name)) elm_fprintf(f,FRM(";MIME-subset=%s"),info->subtype->MIME_name); else if (info->subtype && info->subtype->MIME_name) elm_fprintf(f,FRM(";MIME-subset=%Q"),info->subtype->MIME_name); if (info->MIBenum) { fprintf(f,";MIBenum=%d",info->MIBenum); } if (info->iso2022_info) print_setlist(f,info->iso2022_info); if (0 != (info->flags & SET_havealias)) { dump_alias_info(f,info); } } void dump_by_MIBenum(FILE *f) { int class; fprintf(f,"# Start of MIBenum listing -------------------------------\n"); for (class = 0; class < MIBenum_CLASS_len; class++) { int j; fprintf(f,"# MIBenum %d-%d\n", class * MIBenum_class_divide , class * MIBenum_class_divide + MIBenum_CLASS[class].MIBenum_array_len -1); for (j = 0; j < MIBenum_CLASS[class].MIBenum_array_len; j++) { if (MIBenum_CLASS[class].MIBenum_array[j]) { fprintf(f,"-\t"); dump_map_info(f,MIBenum_CLASS[class].MIBenum_array[j]); fputc('\n',f); } } } fprintf(f,"# End of MIBenum listing ---------------------------------\n"); } void dump_charset_map(f,map) FILE *f; struct charset_map_item *map; { int i; struct charset_map_item *ptr; for (ptr = map; ptr && ptr->charset; ptr++) { ptr->charset->flags &= ~SET_printed; DPRINT(Debug,25,(&Debug, "dump_charset_map: map[%d] %p - '%s' - flags=%X\n", ptr-map,ptr->charset, ptr->charset->MIME_name ? ptr->charset->MIME_name :"", ptr->charset->flags)); } for (ptr = map; ptr && ptr->charset; ptr++) { if (!ptr->match && 0 != (ptr->charset->flags & SET_printed) && 2 == ptr->is_def) continue; /* Several aliases lines? */ if (!ptr->match && 0 == (ptr->charset->flags & SET_valid)) { fputc('#',f); /* Ignored charset */ } if (ptr->match) fputs(ptr->match,f); else fputc('-',f); fputc('\t',f); if (0 != (ptr->charset->flags & SET_printed) && 2 == ptr->is_def) { /* Several aliases lines? */ goto noalias; } if (0 == (ptr->charset->flags & SET_valid)) { /* Ignored charset? */ if (ptr->match) goto noalias; } switch(ptr->is_def) { case 0: /* Simple mapping */ noalias: if (!ptr->charset->MIME_name) { if (ptr->charset->codeset) elm_fprintf(f,FRM("codeset=%Q"), ptr->charset->codeset); else fputs("(unsupported)",f); } else if (name_ok(ptr->charset->MIME_name)) { fputs(ptr->charset->MIME_name,f); } else { elm_fprintf(f,FRM("%Q"),ptr->charset->MIME_name); } break; case 1: /* Redefination */ dump_map_info(f,ptr->charset); ptr->charset->flags |= SET_printed; break; case 2: /* alias */ if (!ptr->charset->MIME_name) { if (ptr->charset->codeset) elm_fprintf(f,FRM("codeset=%Q"), ptr->charset->codeset); else fputs("# ",f); } else if (name_ok(ptr->charset->MIME_name)) { fputs(ptr->charset->MIME_name,f); } else { elm_fprintf(f,FRM("%Q"),ptr->charset->MIME_name); } dump_alias_info(f,ptr->charset); ptr->charset->flags |= SET_printed; break; } fputc('\n',f); DPRINT(Debug,25,(&Debug, "dump_charset_map: map[%d] %p - '%s' - flags=%X\n", ptr-map,ptr->charset, ptr->charset->MIME_name ? ptr->charset->MIME_name :"", ptr->charset->flags)); } } void free_charset_map(map) struct charset_map_item **map; { struct charset_map_item *ptr; for (ptr = *map; ptr && ptr->charset; ptr++) { if (ptr->match) { free(ptr->match); ptr->match = NULL; } } free(*map); *map = NULL; } static int match_item P_((struct charset_map_item *a, struct charset_map_item *b)); static int match_item(a,b) struct charset_map_item *a; struct charset_map_item*b; { if (a->is_def != b->is_def) return 0; if (a->match && b->match) { /* if this is locale -> charset mapping then match item is only required for match */ if (0 != strcmp(a->match,b->match)) return 0; else if (0 == a->is_def) return 1; } else { if (a->match || b->match) return 0; } if (a->charset == b->charset) return 1; if (a->charset->MIME_name && b->charset->MIME_name) { if (0 == strcmp(a->charset->MIME_name,b->charset->MIME_name)) return 1; else return 0; } else { if (a->charset->MIME_name || b->charset->MIME_name) return 0; } if (a->charset->codeset && b->charset->codeset && 0 == strcmp(a->charset->codeset,b->charset->codeset)) return 1; return 0; } void change_charset_map(map,new) struct charset_map_item **map; struct charset_map_item *new; { int count = 0; struct charset_map_item *ptr; for (ptr = *map; ptr && ptr->charset; ptr++) count++; for (ptr = new; ptr && ptr->charset; ptr++) count++; if (!count) return; if (!*map) { *map = safe_malloc((count+1) * sizeof ((*map)[0])); (*map)->charset = NULL; } else *map = safe_realloc(*map, (count+1) * sizeof ((*map)[0])); for (ptr = new; ptr && ptr->charset; ptr++) { struct charset_map_item *ptr2; for (ptr2 = *map; ptr2->charset; ptr2++) { if (match_item(ptr,ptr2)) { goto set_it; } } if (ptr2 > (*map) + count) panic("CHARSET PANIC",__FILE__,__LINE__,"change_charset_map", "Overflow",0); ptr2->match = NULL; if (ptr->match) ptr2->match = safe_strdup(ptr->match); ptr2->is_def = ptr->is_def; (ptr2+1)->match = NULL; (ptr2+1)->charset = NULL; set_it: (ptr2)->charset = ptr->charset; } } /* * Local Variables: * mode:c * c-basic-offset:4 * buffer-file-coding-system: iso-8859-1 * End: */