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 <hurtta+elm@posti.FMI.FI>
* or Kari Hurtta <elm@elmme-mailer.org>
*****************************************************************************/
#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("# <No MIME name> ",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 :"<none>",
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("# <No MIME name> ",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 :"<none>",
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:
*/
syntax highlighted by Code2HTML, v. 0.9.1