From 9ec2088d5a1da0bd6bbfb5d6dea0844ed7806d59 Mon Sep 17 00:00:00 2001 From: Thomas Roessler Date: Tue, 15 Sep 1998 16:00:57 +0000 Subject: [PATCH] Add charset alias support and fix various errors in the character set code. --- charset.c | 90 ++++++++++++++++++++++++++++++------------- charset.h | 15 ++++---- charsets/Makefile.in | 4 +- charsets/gen_charsets | 7 +++- charsets/parse_i18n.c | 46 +++++++++++++++++++++- handler.c | 16 ++++---- 6 files changed, 131 insertions(+), 47 deletions(-) diff --git a/charset.c b/charset.c index dd12df09..0de70c9c 100644 --- a/charset.c +++ b/charset.c @@ -25,13 +25,13 @@ static HASH *Translations = NULL; static HASH *Charsets = NULL; +static HASH *CharsetAliases = NULL; static CHARSET *mutt_new_charset(void) { CHARSET *chs; chs = safe_malloc(sizeof(CHARSET)); - chs->name = NULL; chs->map = NULL; return chs; @@ -43,7 +43,6 @@ static void mutt_free_charset(CHARSET **chsp) { CHARSET *chs = *chsp; - safe_free((void **) &chs->name); safe_free((void **) &chs->map); safe_free((void **) chsp); } @@ -77,8 +76,7 @@ static CHARSET *load_charset(const char *name) int i; chs = mutt_new_charset(); - chs->name = safe_strdup(name); - + snprintf(path, sizeof(path), "%s/charsets/%s", SHAREDIR, name); if((fp = fopen(path, "r")) == NULL) goto bail; @@ -89,7 +87,7 @@ static CHARSET *load_charset(const char *name) if(strcmp(buffer, CHARSET_MAGIC) != 0) goto bail; - chs->map = safe_malloc(sizeof(UNICODE_MAP)); + chs->map = safe_malloc(sizeof(CHARSET_MAP)); for(i = 0; i < 256; i++) { @@ -106,30 +104,64 @@ static CHARSET *load_charset(const char *name) return chs; } +static HASH *load_charset_aliases(void) +{ + FILE *fp; + char buffer[LONG_STRING]; + char *t; + HASH *charset_aliases; + + sprintf(buffer, "%s/charsets/charsets.alias", SHAREDIR); + if(!(fp = fopen(buffer, "r"))) + return NULL; + + charset_aliases = hash_create(256); + + while(fgets(buffer, sizeof(buffer), fp)) + { + if((t = strchr(buffer, '\n'))) + *t = '\0'; + + if(!(t = strchr(buffer, ' '))) + continue; + + *t++ = '\0'; + hash_insert(charset_aliases, safe_strdup(buffer), safe_strdup(t), 1); + } + fclose(fp); + return charset_aliases; +} + static void init_charsets() { if(Charsets) return; - Charsets = hash_create(128); - Translations = hash_create(256); + Charsets = hash_create(128); + Translations = hash_create(256); + CharsetAliases = load_charset_aliases(); } CHARSET *mutt_get_charset(const char *name) { CHARSET *charset; char buffer[SHORT_STRING]; + char *real_charset; init_charsets(); canonical_charset(buffer, sizeof(buffer), name); - if(!(charset = hash_find(Charsets, buffer))) + + if(!CharsetAliases || !(real_charset = hash_find(CharsetAliases, buffer))) + real_charset = buffer; + + if(!(charset = hash_find(Charsets, real_charset))) { - charset = load_charset(buffer); - hash_insert(Charsets, buffer, charset, 0); + charset = load_charset(real_charset); + hash_insert(Charsets, safe_strdup(real_charset), charset, 1); } return charset; } -static int translate_char(UNICODE_MAP *to, int ch) +static int translate_char(CHARSET_MAP *to, int ch) { int i; @@ -142,10 +174,10 @@ static int translate_char(UNICODE_MAP *to, int ch) return '?'; } -UNICODE_MAP *build_translation(UNICODE_MAP *from, UNICODE_MAP *to) +CHARSET_MAP *build_translation(CHARSET_MAP *from, CHARSET_MAP *to) { int i; - UNICODE_MAP *map = safe_malloc(sizeof(UNICODE_MAP)); + CHARSET_MAP *map = safe_malloc(sizeof(CHARSET_MAP)); for(i = 0; i < 256; i++) (*map)[i] = translate_char(to, (*from)[i]); @@ -153,24 +185,30 @@ UNICODE_MAP *build_translation(UNICODE_MAP *from, UNICODE_MAP *to) return map; } -UNICODE_MAP *mutt_get_translation(const char *_from, const char *_to) +CHARSET_MAP *mutt_get_translation(const char *_from, const char *_to) { - char from[SHORT_STRING]; - char to[SHORT_STRING]; + char from_canon[SHORT_STRING]; + char to_canon[SHORT_STRING]; char key[SHORT_STRING]; + char *from, *to; CHARSET *from_cs, *to_cs; - UNICODE_MAP *map; + CHARSET_MAP *map; if(!_from || !_to) return NULL; init_charsets(); - canonical_charset(from, sizeof(from), _from); - canonical_charset(to, sizeof(to), _to); + canonical_charset(from_canon, sizeof(from_canon), _from); + canonical_charset(to_canon, sizeof(to_canon), _to); + + if(!CharsetAliases || !(from = hash_find(CharsetAliases, from_canon))) + from = from_canon; + if(!CharsetAliases || !(to = hash_find(CharsetAliases, to_canon))) + to = to_canon; /* quick check for the identity mapping */ - if((*from == *to) && !strcmp(from, to)) + if((from == to) || ((*from == *to) && !strcmp(from, to))) return NULL; snprintf(key, sizeof(key), "%s %s", from, to); @@ -183,20 +221,20 @@ UNICODE_MAP *mutt_get_translation(const char *_from, const char *_to) return NULL; map = build_translation(from_cs->map, to_cs->map); - hash_insert(Translations, key, map, 0); + hash_insert(Translations, safe_strdup(key), map, 1); } return map; } -int mutt_display_char(int ch, UNICODE_MAP *map) +unsigned char mutt_display_char(unsigned char ch, CHARSET_MAP *map) { - if (!map || (ch <= 0) || (ch > 255)) + if (!map || !ch) return ch; - - return (*map)[ch]; + + return (unsigned char) (*map)[ch]; } -int mutt_display_string(char *str, UNICODE_MAP *map) +int mutt_display_string(char *str, CHARSET_MAP *map) { if(!map) return -1; diff --git a/charset.h b/charset.h index 88d53913..aa29f78b 100644 --- a/charset.h +++ b/charset.h @@ -23,18 +23,17 @@ #ifndef _GEN_CHARSETS -typedef int UNICODE_MAP[256]; +typedef int CHARSET_MAP[256]; typedef struct { - char *name; - UNICODE_MAP *map; + CHARSET_MAP *map; } CHARSET; - -CHARSET *mutt_get_charset(const char *); -UNICODE_MAP *mutt_get_translation(const char *, const char *); -int mutt_display_char(int, UNICODE_MAP *); -int mutt_display_string(char *, UNICODE_MAP *); + +CHARSET *mutt_get_charset(const char *); +CHARSET_MAP *mutt_get_translation(const char *, const char *); +unsigned char mutt_display_char(unsigned char, CHARSET_MAP *); +int mutt_display_string(char *, CHARSET_MAP *); #endif diff --git a/charsets/Makefile.in b/charsets/Makefile.in index 689cf751..11da4bed 100644 --- a/charsets/Makefile.in +++ b/charsets/Makefile.in @@ -36,7 +36,7 @@ distclean: clean -rm -f Makefile veryclean: - -rm -f `cat charsets.list` charsets.list + -rm -f `cat charsets.list` charsets.list charsets.alias charmaps: parse_i18n ( cd $(srcdir) && ./gen_charsets ) @@ -45,4 +45,4 @@ install: charsets.list $(srcdir)/../mkinstalldirs $(sharedir)/charsets ( cd $(srcdir) && $(INSTALL) \ -m 644 `cat charsets.list` $(sharedir)/charsets ) - + $(INSTALL) -m 644 charsets.alias $(sharedir)/charsets diff --git a/charsets/gen_charsets b/charsets/gen_charsets index 4ab05ab7..00fae06f 100755 --- a/charsets/gen_charsets +++ b/charsets/gen_charsets @@ -4,8 +4,11 @@ dirs="/usr/local/lib/nls /usr/lib/nls /usr/local/share/nls /usr/share/nls" dirs="$dirs /usr/local/lib/i18n /usr/lib/i18n /usr/local/share/i18n" dirs="$dirs /usr/share/i18n" -rm -f ./charsets.list +rm -f ./charsets.list ./charsets.alias ./charsets.$$ for d in $dirs ; do - [ -d $d/charmaps ] && ./parse_i18n ./ $d/charmaps/* >> ./charsets.list + [ -d $d/charmaps ] && ./parse_i18n ./ $d/charmaps/* >> ./charsets.$$ done + +awk '$1 == "charset" { printf ("%s\n", $2); }' ./charsets.$$ > charsets.list +awk '$1 == "alias" { printf ("%s %s\n", $2, $3); }' ./charsets.$$ > charsets.alias diff --git a/charsets/parse_i18n.c b/charsets/parse_i18n.c index a8325589..02eaba79 100644 --- a/charsets/parse_i18n.c +++ b/charsets/parse_i18n.c @@ -31,12 +31,19 @@ static char *basedir = NULL; typedef int MAP[256]; +typedef struct alias +{ + char *charset; + struct alias *next; +} ALIAS; + typedef struct { char *charset; char escape_char; char comment_char; short is_valid; + ALIAS *aliases; MAP map; } CHARMAP; @@ -100,6 +107,8 @@ static CHARMAP *charmap_new(void) m->escape_char = '\\'; m->comment_char = '#'; m->is_valid = 0; + + m->aliases = NULL; for(i = 0; i < 256; i++) m->map[i] = -1; @@ -109,15 +118,35 @@ static CHARMAP *charmap_new(void) static void charmap_free(CHARMAP **cp) { + ALIAS *p, *q; + if(!cp || !*cp) return ; + for(p = (*cp)->aliases; p; p = q) + { + q = p->next; + safe_free((void **) &p->charset); + safe_free((void **) &p); + } + safe_free((void **) &(*cp)->charset); safe_free((void **) cp); return; } +static void add_alias(CHARMAP *m, const char *alias) +{ + ALIAS *aptr; + + aptr = safe_malloc(sizeof(ALIAS)); + aptr->charset = safe_strdup(alias); + canonical_charset(aptr->charset, strlen(aptr->charset) + 1, aptr->charset); + aptr->next = m->aliases; + m->aliases = aptr; +} + static CHARMAP *parse_charmap_header(FILE *fp, const char *prefix) { char buffer[1024]; @@ -139,7 +168,14 @@ static CHARMAP *parse_charmap_header(FILE *fp, const char *prefix) break; if(*buffer == m->comment_char) + { + if((t = strtok(buffer + 1, "\t ")) && !strcasecmp(t, "alias")) + { + while((t = strtok(NULL, "\t, "))) + add_alias(m, t); + } continue; + } if(!(t = strtok(buffer, "\t "))) continue; @@ -282,6 +318,7 @@ int main(int argc, const char *argv[]) { FILE *fp; CHARMAP *m; + ALIAS *aptr; int i; char buffer[1024]; @@ -310,8 +347,15 @@ int main(int argc, const char *argv[]) if((fp = fopen(buffer, "w"))) { - printf("%s\n", m->charset); write_charmap(fp, m); + + printf("charset %s\n", m->charset); + for(aptr = m->aliases; aptr; aptr = aptr->next) + { + if(strcmp(aptr->charset, m->charset)) + printf("alias %s %s\n", aptr->charset, m->charset); + } + fclose(fp); } else diff --git a/handler.c b/handler.c index 86e8f645..417ede45 100644 --- a/handler.c +++ b/handler.c @@ -72,7 +72,7 @@ void mutt_decode_xbit (STATE *s, BODY *b, int istext) if (istext) { - UNICODE_MAP *map; + CHARSET_MAP *map; map = mutt_get_translation(mutt_get_parameter("charset", b->parameter), Charset); @@ -97,7 +97,7 @@ void mutt_decode_xbit (STATE *s, BODY *b, int istext) } } - state_putc(mutt_display_char(c, map), s); + state_putc(mutt_display_char((unsigned char) c, map), s); if(c == '\n') lbreak = 1; } @@ -122,7 +122,7 @@ void mutt_decode_quoted (STATE *s, BODY *b, int istext) { long len = b->length; int ch, lbreak = 1; - UNICODE_MAP *map = mutt_get_translation(mutt_get_parameter("charset", b->parameter), Charset); + CHARSET_MAP *map = mutt_get_translation(mutt_get_parameter("charset", b->parameter), Charset); while (len > 0) { @@ -190,7 +190,7 @@ void mutt_decode_quoted (STATE *s, BODY *b, int istext) } if(ch != EOF) - state_putc(istext ? mutt_display_char(ch, map) : ch, s); + state_putc(istext ? mutt_display_char((unsigned char) ch, map) : ch, s); if(ch == '\n') lbreak = 1; @@ -202,7 +202,7 @@ void mutt_decode_base64 (STATE *s, BODY *b, int istext) long len = b->length; char buf[5]; int c1, c2, c3, c4, ch, cr = 0, i; - UNICODE_MAP *map = mutt_get_translation(mutt_get_parameter("charset", b->parameter), Charset); + CHARSET_MAP *map = mutt_get_translation(mutt_get_parameter("charset", b->parameter), Charset); buf[4] = 0; @@ -231,7 +231,7 @@ void mutt_decode_base64 (STATE *s, BODY *b, int istext) cr = 1; else { - state_putc(istext ? mutt_display_char(ch, map) : ch, s); + state_putc(istext ? mutt_display_char((unsigned char) ch, map) : ch, s); if (ch == '\n' && s->prefix) state_puts (s->prefix, s); } @@ -248,7 +248,7 @@ void mutt_decode_base64 (STATE *s, BODY *b, int istext) cr = 1; else { - state_putc(istext ? mutt_display_char(ch, map) : ch, s); + state_putc(istext ? mutt_display_char((unsigned char)ch, map) : ch, s); if (ch == '\n' && s->prefix) state_puts (s->prefix, s); } @@ -265,7 +265,7 @@ void mutt_decode_base64 (STATE *s, BODY *b, int istext) cr = 1; else { - state_putc(istext ? mutt_display_char(ch, map) : ch, s); + state_putc(istext ? mutt_display_char((unsigned char) ch, map) : ch, s); if (ch == '\n' && s->prefix) state_puts (s->prefix, s); } -- 2.40.0