static char rcsid[] = "@(#)$Id: string.c,v 1.50.18.1 2007/08/25 06:35:47 hurtta Exp $"; /****************************************************************************** * The Elm (ME+) Mail System - $Revision: 1.50.18.1 $ $State: Exp $ * * Author: Kari Hurtta (was hurtta+elm@ozone.FMI.FI) *****************************************************************************/ #include "headers.h" #include "s_me.h" #include "cs_imp.h" #ifdef USE_DLOPEN #include "shared_imp.h" #endif DEBUG_VAR(Debug,__FILE__,"charset"); static unsigned char *s2us P_((char *str)); static unsigned char *s2us(str) char *str; { return (unsigned char *)str; } static char *us2s P_((unsigned char *str)); static char *us2s(str) unsigned char *str; { return (char *)str; } static CONST char *cus2s P_((const unsigned char *str)); static CONST char *cus2s(str) CONST unsigned char *str; { return (CONST char *)str; } #define INVALID_MAP(cs) ((cs)->map_info && \ (cs)->map_info->map_type != (cs)->charset_type) int verify_string(str) struct string *str; { if (!str) { DPRINT(Debug,1,(&Debug,"verify_string=0: FAILURE str = NULL\n")); return 0; } if (!str->string_type) { DPRINT(Debug,1,(&Debug, "verify_string=0: FAILURE str->string_type = NULL (str=%p)\n", str)); return 0; } if (CS_charset_magic != str->string_type->magic) { DPRINT(Debug,1,(&Debug, "verify_string=0: FAILURE Bad magic (str=%p)\n", str)); return 0; } if (INVALID_MAP(str->string_type)) { DPRINT(Debug,1,(&Debug, "verify_string=0: FAILURE Bad map (str=%p)\n", str)); return 0; } return 1; } static struct string * malloc_string P_((charset_t set)); static struct string * malloc_string(set) charset_t set; { struct string * res = safe_malloc(sizeof (struct string)); /* defined in hdrs/defs.h */ bzero((void *)res,sizeof (struct string)); if (CS_charset_magic != set->magic) panic("STRING PANIC",__FILE__,__LINE__,"malloc_string", "Bad magic number (set)",0); if (INVALID_MAP(set)) panic("STRING PANIC",__FILE__,__LINE__,"malloc_string", "Bad map (set)",0); /* Initialize associated map if not done already ... */ if (set->map_info && !set->map_info->map_initialized) set->map_info->map_init_it(set->map_info); res->string_type = set; res->p = safe_malloc(sizeof (struct str_private_data)); /* defined in hdrs/defs.h */ bzero((void *)res->p,sizeof (struct str_private_data)); res->p->magic = CS_str_magic; res->p->len = 0; res->p->state = NULL; res->p->private_flag = 0; /* Mostly not used */ res->p->lang = NULL; res->string_type->charset_type->cs_init_it(res); return res; } /* ------------------------------------------------------------------------- */ struct string * new_string(set) charset_t set; { struct string *res; DPRINT(Debug,60,(&Debug,"new_string(set=%p '%s')\n", set, set->MIME_name ? set->MIME_name : "")); res = malloc_string(set); DPRINT(Debug,60,(&Debug,"new_string=%p (type=%p '%s')\n", res, res->string_type->charset_type, res->string_type->charset_type->type_name)); return res; } struct string * new_langstring(set,lang) charset_t set; char *lang; { struct string *res; DPRINT(Debug,60,(&Debug,"new_langstring(set=%p '%s', lang=%s)\n", set, set->MIME_name ? set->MIME_name : "", lang)); res = malloc_string(set); res->p->lang = safe_strdup(lang); DPRINT(Debug,60,(&Debug,"new_langstring=%p (type=%p '%s')\n", res, res->string_type->charset_type, res->string_type->charset_type->type_name)); return res; } struct string * new_string2 P_((charset_t set, CONST unsigned char *data)); struct string * new_string2(set,data) charset_t set; CONST unsigned char *data; { struct string * res; int ERRORS = 0; DPRINT(Debug,60,(&Debug, "new_string2: set=%p '%s'\n", set, set->MIME_name ? set->MIME_name : "")); if (set == display_charset || set == system_charset) { DPRINT(Debug,61,(&Debug, "new_string2 -- data=%s\n",data)); } res = malloc_string(set); res->string_type->charset_type-> cs_add_streambytes_to_it(res, strlen(cus2s(data)), data,&ERRORS); DPRINT(Debug,60,(&Debug, "new_string2=%p (type=%p '%s'): len=%d ERRORS=%d\n", res, res->string_type->charset_type, res->string_type->charset_type->type_name, res->p->len, ERRORS)); return res; } void free_string(str) struct string **str; { if (CS_charset_magic != (*str)->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"free_string", "Bad magic number (string type)",0); if (INVALID_MAP((*str)->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"free_string", "Bad map (string type)",0); DPRINT(Debug,60,(&Debug,"free_string(*str=%p) ('%s'; type=%p '%s')\n", (*str), (*str)->string_type->MIME_name ? (*str)->string_type->MIME_name : "", (*str)->string_type->charset_type, (*str)->string_type->charset_type->type_name)); if ((*str)->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"free_string", "Bad magic number (str_private_data)",0); if ((*str)->p->state && (*str)->p->state->charset != (*str)->string_type) panic("STRING PANIC",__FILE__,__LINE__,"free_string", "Bad magic number (state charset)",0); (*str)->string_type->charset_type->cs_free_it(*str); if ((*str)->p->state) { free_state_internal(&((*str)->p->state)); } if ((*str)->p->lang) { free((*str)->p->lang); (*str)->p->lang = NULL; } free((*str)->p); (*str)->p = NULL; (*str)->string_type = NULL; free(*str); *str = NULL; } CONST char * get_string_lang(str) CONST struct string *str; { if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"get_string_lang", "Bad magic number (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"get_string_lang", "Bad magic number (str_private_data)",0); return str->p->lang; } CONST char * get_string_MIME_name(str) CONST struct string *str; { if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"get_string_MIME_name", "Bad magic number (string type)",0); return str->string_type->MIME_name; } int add_streambyte_to_string(str,ch) struct string *str; int ch; { int r; if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"add_streambyte_to_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"add_streambyte_to_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"add_streambyte_to_string", "Bad magic number (str_private_data)",0); if (str->p->state && str->p->state->charset != str->string_type) panic("STRING PANIC",__FILE__,__LINE__,"add_streambyte_to_string", "Bad magic number (state charset)",0); DPRINT(Debug,60,(&Debug, "add_streambyte_to_string: str=%p ('%s'; type=%p '%s')\n", str, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name)); if (str->string_type == display_charset || str->string_type == system_charset) { DPRINT(Debug,61,(&Debug, "add_streambyte_to_string -- ch=%d '%c'\n",ch,ch)); } else { DPRINT(Debug,61,(&Debug, "add_streambyte_to_string -- ch=%d\n",ch)); } r = str->string_type->charset_type->cs_add_streambyte_to_it(str,ch); DPRINT(Debug,60,(&Debug, "add_streambyte_to_string=%d\n", r)); return r; } int add_streambytes_to_string(str,count,data, errors) struct string *str; int count; CONST unsigned char *data; int *errors; { int r; int ERRORS = 0; if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"add_streambytes_to_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"add_streambytes_to_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"add_streambytes_to_string", "Bad magic number (str_private_data)",0); if (str->p->state && str->p->state->charset != str->string_type) panic("STRING PANIC",__FILE__,__LINE__,"add_streambytes_to_string", "Bad magic number (state charset)",0); DPRINT(Debug,60,(&Debug, "add_streambytes_to_string: str=%p, count=%d, data=%p ('%s'; type=%p '%s')\n", str,count,data, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name)); if (str->string_type == display_charset || str->string_type == system_charset) { DPRINT(Debug,61,(&Debug, "add_streambytes_to_string -- data='%.*s'\n", count,data)); } r = str->string_type->charset_type->cs_add_streambytes_to_it(str, count,data, &ERRORS); if (errors) *errors = ERRORS; DPRINT(Debug,60,(&Debug,"add_streambytes_to_string=%d ERRORS=%d\n", r,ERRORS)); return r; } static CONST unsigned char * csUs P_((const char *str)); static CONST unsigned char * csUs(str) CONST char *str; { return (CONST unsigned char *)str; } static CONST char * cUss P_((const unsigned char *str)); static CONST char * cUss(str) CONST unsigned char *str; { return (CONST char *)str; } static void add_name_to_string P_((struct string *str, CONST unsigned char *ascii)); static void add_name_to_string(str,ascii) struct string *str; CONST unsigned char *ascii; { int l = strlen(cUss(ascii)); int i; uint16 * vector = safe_malloc ( (l) * sizeof (uint16)); /* Ascii and UNICODE have save codes ... */ for (i = 0; i < l ; i++) /* ascii string is unsigned ... */ if (ascii[i] < 128) vector[i] = ascii[i]; else vector[i] = '?'; str->string_type->charset_type->cs_add_unicodedata_to_it(str,l,vector); free(vector); } void add_unicode_to_string(str,len,vector) struct string *str; int len; CONST uint16 *vector; { if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"add_unicode_to_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"add_unicode_to_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"add_unicode_to_string", "Bad magic number (str_private_data)",0); if (len < 0) panic("STRING PANIC",__FILE__,__LINE__,"add_unicode_to_string", "Bad vector len",0); DPRINT(Debug,60,(&Debug, "add_unicode_to_string(%p,len=%d) ('%s'; type=%p '%s')\n", str,len, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name)); str->string_type->charset_type->cs_add_unicodedata_to_it(str,len,vector); DPRINT(Debug,60,(&Debug, "add_unicode_to_string: len = %d\n",str->p->len)); } struct string * cat_strings(str1,str2,printind) CONST struct string *str1; CONST struct string *str2; int printind; { struct string *ret = NULL; if (CS_charset_magic != str1->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"cat_strings", "Bad magic number (string type)",0); if (CS_charset_magic != str2->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"cat_strings", "Bad magic number (string type)",0); if (INVALID_MAP(str1->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"cat_strings", "Bad map (string type)",0); if (INVALID_MAP(str2->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"cat_strings", "Bad map (string type)",0); if (str1->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"cat_strings", "Bad magic number (str_private_data)",0); if (str2->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"cat_strings", "Bad magic number (str_private_data)",0); DPRINT(Debug,60,(&Debug, "cat_strings(%p,%p) ('%s'; type=%p '%s', len=%d), ('%s'; type=%p '%s', len=%d)\n", str1,str2, str1->string_type->MIME_name ? str1->string_type->MIME_name : "", str1->string_type->charset_type, str1->string_type->charset_type->type_name, str1->p->len, str2->string_type->MIME_name ? str2->string_type->MIME_name : "", str2->string_type->charset_type, str2->string_type->charset_type->type_name, str2->p->len)); /* Check lengths */ str1->string_type->charset_type->cs_check_length_it(str1); str2->string_type->charset_type->cs_check_length_it(str2); /* Either one is empty, produce other, but not if other is not printable and printind is set. */ if (str1->p->len == 0 && (!printind || 0 != (charset_properties(str2 -> string_type) & CS_mapping))) { ret = malloc_string(str2 -> string_type); ret->string_type->charset_type->cs_add_intdata_to_it(ret,str2); if (str2->p->lang) { ret->p->lang = safe_strdup(str2->p->lang); } } else if (str2->p->len == 0 && (!printind || 0 != (charset_properties(str1 -> string_type) & CS_mapping))) { ret = malloc_string(str1 -> string_type); ret->string_type->charset_type->cs_add_intdata_to_it(ret,str1); if (str1->p->lang) { ret->p->lang = safe_strdup(str1->p->lang); } } else if (str1 -> string_type == str2 -> string_type) { /* 1) Same CHARSET */ ret = malloc_string(str1 -> string_type); ret->string_type->charset_type->cs_add_intdata_to_it(ret,str1); ret->string_type->charset_type->cs_add_intdata_to_it(ret,str2); if (str1->p->lang && str2->p->lang && 0 == strcmp(str1->p->lang, str2->p->lang)) { ret->p->lang = safe_strdup(str1->p->lang); } } else if (str1 -> string_type -> charset_type == str2 -> string_type -> charset_type && charset_superset_of(str1 -> string_type,str2 -> string_type)) { /* 2) CHARSET of str1 is superset of CHARSET of str2 */ ret = malloc_string(str1 -> string_type); ret->string_type->charset_type->cs_add_intdata_to_it(ret,str1); ret->string_type->charset_type->cs_add_intdata_to_it(ret,str2); if (str1->p->lang && str2->p->lang && 0 == strcmp(str1->p->lang, str2->p->lang)) { ret->p->lang = safe_strdup(str1->p->lang); } } else if (str1 -> string_type -> charset_type == str2 -> string_type -> charset_type && charset_superset_of(str2 -> string_type,str1 -> string_type)) { /* 3) CHARSET of str2 is superset of CHARSET of str1 */ ret = malloc_string(str2 -> string_type); ret->string_type->charset_type->cs_add_intdata_to_it(ret,str1); ret->string_type->charset_type->cs_add_intdata_to_it(ret,str2); if (str1->p->lang && str2->p->lang && 0 == strcmp(str1->p->lang, str2->p->lang)) { ret->p->lang = safe_strdup(str1->p->lang); } } else if (printind && 0 != (charset_properties(str1 -> string_type) & CS_mapping) && 0 == (charset_properties(str2 -> string_type) & CS_mapping) && str2 -> string_type -> MIME_name) { /* Add just str1 and indicate that 2 is not mappable */ ret = malloc_string(str1 -> string_type); ret->string_type->charset_type->cs_add_intdata_to_it(ret,str1); add_name_to_string(ret,csUs("[?")); add_name_to_string(ret,csUs(str2 -> string_type -> MIME_name)); add_name_to_string(ret,csUs("?]")); } else if (printind && 0 != (charset_properties(str2 -> string_type) & CS_mapping) && 0 == (charset_properties(str1 -> string_type) & CS_mapping) && str1 -> string_type -> MIME_name) { /* Add just str2 and indicate that 1 is not mappable */ ret = malloc_string(str2 -> string_type); add_name_to_string(ret,csUs("[?")); add_name_to_string(ret,csUs(str2 -> string_type -> MIME_name)); add_name_to_string(ret,csUs("?]")); ret->string_type->charset_type->cs_add_intdata_to_it(ret,str2); } else if (0 == str1->p->len && 0 == str2->p->len) { /* Avoid mallocing null vector */ ret = malloc_string(display_charset); } else { /* 4) Unrelated CHARSETs -- so we try use display charset or UTF-8 instead */ int i; int l = 0; uint16 * vector = safe_malloc ( (str1->p->len + str2->p->len) * sizeof (uint16)); charset_t target_set = MIME_name_to_charset("UTF-8",0); if (!target_set) panic("CHARSET PANIC",__FILE__,__LINE__,"cat_strings", "UTF-8 not found",0); /* If display charset is superset of charset of strings use it */ if (0 != (charset_properties(display_charset) & CS_mapping) && ( charset_superset_of(display_charset, str1 -> string_type) && charset_superset_of(display_charset, str2 -> string_type) || 0 != (charset_properties(display_charset) & CS_universal_set) )) target_set = display_charset; if (0 == (charset_properties(target_set) & CS_mapping)) { DPRINT(Debug,5,(&Debug, "cat_strings: selected charset do not have mapping info, using ASCII as target set\n")); target_set = ASCII_SET; } ret = malloc_string(target_set); for (i = 0; i < str1->p->len; i++) { int found; uint16 c = str1->string_type->charset_type-> cs_give_unicode_from_it(str1,i,&found); vector[l++] = c; } for (i = 0; i < str2->p->len; i++) { int found; uint16 c = str2->string_type->charset_type-> cs_give_unicode_from_it(str2,i,&found); vector[l++] = c; } ret->string_type->charset_type->cs_add_unicodedata_to_it(ret,l,vector); free(vector); if (str1->p->lang && str2->p->lang && 0 == strcmp(str1->p->lang, str2->p->lang)) { ret->p->lang = safe_strdup(str1->p->lang); } } DPRINT(Debug,60,(&Debug, "cat_strings=%p ('%s'; type=%p '%s'): len=%d\n", ret, ret->string_type->MIME_name ? ret->string_type->MIME_name : "", ret->string_type->charset_type, ret->string_type->charset_type->type_name, ret->p->len)); return ret; } int string_len(str) CONST struct string *str; { if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"string_len", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"string_len", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"string_len", "Bad magic number (str_private_data)",0); /* Check length */ str->string_type->charset_type->cs_check_length_it(str); DPRINT(Debug,60,(&Debug,"string_len(%p)=%d ('%s'; type=%p '%s')\n", str,str->p->len, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name)); return str->p->len; } int string_cmp(str1,str2,unknown_val) CONST struct string *str1; CONST struct string *str2; int unknown_val; { int ret = 0; int not_found = 0; int i; int str1_len; int str2_len; cs_give_unicode_from_string *str1_get_unicode; cs_give_unicode_from_string *str2_get_unicode; if (CS_charset_magic != str1->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"string_cmp", "Bad magic number (string type)",0); if (CS_charset_magic != str2->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"string_cmp", "Bad magic number (string type)",0); if (INVALID_MAP(str1->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"string_cmp", "Bad map (string type)",0); if (INVALID_MAP(str2->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"string_cmp", "Bad map (string type)",0); if (str1->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"string_cmp", "Bad magic number (str_private_data)",0); if (str2->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"string_cmp", "Bad magic number (str_private_data)",0); DPRINT(Debug,60,(&Debug, "string_cmp(%p,%p,unknown_val=%d) ('%s'; type=%p '%s', len=%d), ('%s'; type=%p '%s', len=%d)\n", str1,str2,unknown_val, str1->string_type->MIME_name ? str1->string_type->MIME_name : "", str1->string_type->charset_type, str1->string_type->charset_type->type_name, str1->p->len, str2->string_type->MIME_name ? str2->string_type->MIME_name : "", str2->string_type->charset_type, str2->string_type->charset_type->type_name, str2->p->len)); /* Check lengths -- do compressions and so on */ str1->string_type->charset_type->cs_check_length_it(str1); str2->string_type->charset_type->cs_check_length_it(str2); str1_len = str1->p->len; str2_len = str2->p->len; str1_get_unicode = str1->string_type->charset_type->cs_give_unicode_from_it; str2_get_unicode = str2->string_type->charset_type->cs_give_unicode_from_it; /* Make unicode compare first to make comparision to stable */ for (i = 0; i < str1_len && i < str2_len; i++) { int found1,found2; uint16 c1 = str1_get_unicode(str1,i,&found1); uint16 c2 = str2_get_unicode(str2,i,&found2); if (!found1 || !found2) { ret = 0; not_found = 1; break; } else if (c1 < c2) ret = -1; else if (c1 > c2) ret = 1; if (ret != 0) break; } DPRINT(Debug,61,(&Debug, "string_cmp: i=%d, str1 len=%d, str2 len=%d, not_found=%d\n", i,str1->p->len,str2->p->len,not_found)); if (!not_found) { if (0 == ret && i < str1->p->len) ret = 1; if (0 == ret && i < str2->p->len) ret = -1; DPRINT(Debug,61,(&Debug, "string_cmp: unicode cmp ret=%d\n",ret)); } if (0 == ret && str1 -> string_type == str2 -> string_type) { ret = str1 -> string_type->charset_type->cs_cmp_it(str1,str2); DPRINT(Debug,61,(&Debug, "string_cmp: cs_cmp_it ret=%d\n",ret)); if (ret < 0) ret = -1; else if (ret > 0) ret = 1; } else if (0 == ret && not_found) { DPRINT(Debug,61,(&Debug,"string_cmp: Unable to compare values!\n")); ret = unknown_val; } DPRINT(Debug,60,(&Debug,"string_cmp=%d\n",ret)); return ret; } struct string * dup_string(str) CONST struct string *str; { struct string *ret; if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"dup_string", "Bad magic number (str_private_data)",0); DPRINT(Debug,60,(&Debug,"dup_string: str=%p ('%s'; type=%p '%s')\n", str, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name)); ret = malloc_string(str -> string_type); ret->string_type->charset_type->cs_add_intdata_to_it(ret,str); if (str->p->lang) { ret->p->lang = safe_strdup(str->p->lang); } DPRINT(Debug,60,(&Debug,"dup_string=%p ('%s'; type=%p '%s')\n", ret, ret->string_type->MIME_name ? ret->string_type->MIME_name : "", ret->string_type->charset_type, ret->string_type->charset_type->type_name)); return ret; } struct string * convert_string(set,str,printind) charset_t set; CONST struct string *str; int printind; { struct string *ret = malloc_string(set); if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"convert_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"convert_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"convert_string", "Bad magic number (str_private_data)",0); DPRINT(Debug,60,(&Debug, "convert_string(set=%p '%s',str=%p) ('%s', type=%p '%s', len=%d)\n", set, set->MIME_name ? set->MIME_name : "", str, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name, str->p->len)); /* Check lengths -- do compressions and so on */ str->string_type->charset_type->cs_check_length_it(str); if (0 == str->p->len) { /* 0) Empty string is always convertable because nothing need to be added to result */ } else if (set == str->string_type) { /* 1) Same charset */ ret->string_type->charset_type->cs_add_intdata_to_it(ret,str); if (str->p->lang) { ret->p->lang = safe_strdup(str->p->lang); } } else if (printind && 0 != (charset_properties(set) & CS_mapping) && 0 == (charset_properties(str -> string_type) & CS_mapping) && str -> string_type -> MIME_name) { /* Just indicate that str is not mappable */ add_name_to_string(ret,csUs("[?")); add_name_to_string(ret,csUs(str -> string_type -> MIME_name)); add_name_to_string(ret,csUs("?]")); } else { /* 2) Different charset */ int i; int l = 0; uint16 * vector = safe_malloc ( (str->p->len) * sizeof (uint16)); for (i = 0; i < str->p->len; i++) { int found; uint16 c = str->string_type->charset_type-> cs_give_unicode_from_it(str,i,&found); vector[l++] = c; } ret->string_type->charset_type->cs_add_unicodedata_to_it(ret,l,vector); free(vector); if (str->p->lang) { ret->p->lang = safe_strdup(str->p->lang); } } DPRINT(Debug,60,(&Debug, "convert_string=%p ('%s'; type=%p '%s'): len=%d\n", ret, ret->string_type->MIME_name ? ret->string_type->MIME_name : "", ret->string_type->charset_type, ret->string_type->charset_type->type_name, ret->p->len)); return ret; } unsigned char *stream_from_string(str, printable,terminal) CONST struct string *str; int printable; screen_info_p terminal; { int reslen; unsigned char * ret; char *ret0 = NULL; if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"stream_from_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"stream_from_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"stream_from_string", "Bad magic number (str_private_data)",0); DPRINT(Debug,60,(&Debug,"stream_from_string: ret=%p ('%s'; type=%p '%s')\n", str, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name)); if (terminal && str->string_type->iso2022_info) ret0 = terminal_charset_post_init(terminal, str->string_type->iso2022_info); /* Catenate order is ret == ret0 + ret */ ret = str->string_type->charset_type->cs_stream_from_it(str, printable, terminal, &reslen); DPRINT(Debug,60,(&Debug, "stream_from_string -- reslen=%d\n",reslen)); if (str->string_type == display_charset) { DPRINT(Debug,61,(&Debug, "stream_from_string -- ret='%s'%s\n", ret, ret0 ? " (without post init)" : "")); } if (ret0) { int i; DPRINT(Debug,8,(&Debug,"Post init terminal charset %s (", str->string_type->MIME_name ? str->string_type->MIME_name : "")); for (i = 0; ret0[i]; i++) { DPRINT(Debug,8,(&Debug,"%s%02X", i ? " " : "", ret0[i])); } DPRINT(Debug,8,(&Debug,")\n")); /* Catenate order is ret == ret0 + ret */ ret0 = strmcat(ret0,us2s(ret)); free(ret); ret = s2us(ret0); } DPRINT(Debug,60,(&Debug,"stream_from_string=%p\n", ret)); return ret; } /* result is malloced */ void bytestream_from_string(str,res,reslen) CONST struct string *str; char **res; int *reslen; { if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"bytestream_from_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"bytestream_from_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"bytestream_from_string", "Bad magic number (str_private_data)",0); DPRINT(Debug,60,(&Debug, "bytestream_from_string: str=%p ('%s'; type=%p '%s')\n", str, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name)); *res = us2s(str->string_type->charset_type->cs_stream_from_it(str,0,NULL, reslen)); DPRINT(Debug,60,(&Debug, "bytestream_from_string: *res=%p, reslen=%d\n", *res,reslen)); } unsigned char *streamclip_from_string(str,pos,len,terminal,printable_len) CONST struct string *str; int *pos; int len; screen_info_p terminal; struct cs_printable_len *printable_len; { int p = *pos; unsigned char * ret; char *ret0 = NULL; if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"streamclip_from_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"streamclip_from_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"streamclip_from_string", "Bad magic number (str_private_data)",0); if (printable_len && !terminal) panic("STRING PANIC",__FILE__,__LINE__,"streamclip_from_string", "printable_len argument requires terminal argument",0); if (printable_len && 0 == ( CS_printable_len & str->string_type->charset_type->cs_it_properties(str->string_type))) panic("STRING PANIC",__FILE__,__LINE__,"streamclip_from_string", "Charset does not support printable_len argument",0); if (terminal && str->string_type->iso2022_info) ret0 = terminal_charset_post_init(terminal, str->string_type->iso2022_info); /* Catenate order is ret == ret0 + ret */ DPRINT(Debug,60,(&Debug, "streamclip_from_string(%p,%d,%d) ('%s'; type=%p '%s')\n", str,p,len, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name)); ret = str->string_type->charset_type->cs_streamclip_from_it(str,pos,len, terminal, printable_len); if (str->string_type == display_charset) { DPRINT(Debug,61,(&Debug, "streamclip_from_string -- ret='%s'%s\n", ret, ret0 ? " (without post init)" : "")); } if (ret0) { int i; DPRINT(Debug,8,(&Debug, "Post init terminal charset %s (", str->string_type->MIME_name ? str->string_type->MIME_name : "")); for (i = 0; ret0[i]; i++) { DPRINT(Debug,8,(&Debug,"%s%02X", i ? " " : "", ret0[i])); } DPRINT(Debug,8,(&Debug,")\n")); /* Catenate order is ret == ret0 + ret */ ret0 = strmcat(ret0,us2s(ret)); free(ret); ret = s2us(ret0); } DPRINT(Debug,60,(&Debug, "streamclip_from_string [%d(..%d)] =%p ('%s'; type=%p '%s')", p,*pos,ret, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name)); if (printable_len) { DPRINT(Debug,60,(&Debug, " printable_len: max_len=%d ret_len=%d", printable_len->max_len, printable_len->ret_len)); } DPRINT(Debug,60,(&Debug,"\n")); return ret; } int estimate_clip_string(str,pos,len,terminal,printable_len) CONST struct string *str; int pos; int len; /* UPPER LIMIT */ screen_info_p terminal; struct cs_printable_len *printable_len; { int ret; if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"estimate_clip_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"estimate_clip_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"estimate_clip_string", "Bad magic number (str_private_data)",0); if (0 == ( CS_printable_len & str->string_type->charset_type->cs_it_properties(str->string_type))) panic("STRING PANIC",__FILE__,__LINE__,"estimate_clip_string", "Charset does not support function",0); if (!printable_len || !terminal) panic("STRING PANIC",__FILE__,__LINE__,"estimate_clip_string", "printable_len and terminal required",0); ret = str->string_type->charset_type->cs_estimate_clip_it(str,pos,len, terminal, printable_len); DPRINT(Debug,60,(&Debug, "estimate_clip_it(%p,%d,%d,...) =%d ('%s'; type=%p '%s')", str,pos,len,ret, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name)); DPRINT(Debug,60,(&Debug, " printable_len: max_len=%d ret_len=%d\n", printable_len->max_len, printable_len->ret_len)); return ret; } struct string *clip_from_string(str,pos,len) CONST struct string *str; int *pos; int len; { struct string *ret = malloc_string(str->string_type); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"clip_from_string", "Bad magic number (str_private_data)",0); DPRINT(Debug,60,(&Debug, "clip_from_string(%p,%d,%d) ('%s'; type=%p '%s')\n", str,*pos,len, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name)); /* It is assumed that compressions are done .. ie string_length() function is called */ str->string_type->charset_type->cs_clip_from_it(ret,str,pos,len); DPRINT(Debug,60,(&Debug, "clip_from_string=%p ('%s'; type=%p '%s'): len=%d\n", ret, ret->string_type->MIME_name ? ret->string_type->MIME_name : "", ret->string_type->charset_type, ret->string_type->charset_type->type_name, ret->p->len)); return ret; } struct string *ascify_string(str) CONST struct string *str; { int can_ascii; charset_t ascii_ptr = MIME_name_to_charset("US-ASCII",0); struct string *ret; if (!ascii_ptr) panic("STRING PANIC",__FILE__,__LINE__,"ascify_string", "US-ASCII not found",0); if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"ascify_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"ascify_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"ascify_string", "Bad magic number (str_private_data)",0); DPRINT(Debug,60,(&Debug, "ascify_string(%p) ('%s'; type=%p '%s', len=%d)\n", str, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name, str->p->len)); /* Check lengths -- do compressions and so on */ str->string_type->charset_type->cs_check_length_it(str); can_ascii = str->string_type->charset_type->cs_can_ascii_it(str); if (can_ascii) { int i; int l = 0; uint16 * vector = safe_malloc ( (str->p->len) * sizeof (uint16)); ret = malloc_string(ascii_ptr); for (i = 0; i < str->p->len; i++) { int found; uint16 c = str->string_type->charset_type-> cs_give_unicode_from_it(str,i,&found); vector[l++] = c; } ret->string_type->charset_type->cs_add_unicodedata_to_it(ret,l,vector); free(vector); } else { ret = malloc_string(str -> string_type); ret->string_type->charset_type->cs_add_intdata_to_it(ret,str); } if (str->p->lang) { ret->p->lang = safe_strdup(str->p->lang); } DPRINT(Debug,60,(&Debug, "ascify_string=%p ('%s'; type=%p '%s'): len=%d\n", ret, ret->string_type->MIME_name ? ret->string_type->MIME_name : "", ret->string_type->charset_type, ret->string_type->charset_type->type_name, ret->p->len)); return ret; } int can_ascii_string(str) CONST struct string *str; { int ret; if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"can_ascii_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"can_ascii_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"can_ascii_string", "Bad magic number (str_private_data)",0); ret= str->string_type->charset_type->cs_can_ascii_it(str); DPRINT(Debug,60,(&Debug, "can_ascii_string(%p)=%d ('%s'; type=%p '%s', len=%d)\n", str,ret, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name, str->p->len)); return ret; } void add_ascii_to_string(str,ascii) struct string *str; CONST unsigned char *ascii; { if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"add_ascii_to_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"add_ascii_to_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"add_ascii_to_string", "Bad magic number (str_private_data)",0); DPRINT(Debug,60,(&Debug, "add_ascii_to_string(%p) ('%s'; type=%p '%s')\n", str, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name)); DPRINT(Debug,61,(&Debug, "add_ascii_to_string -- ascii=%s\n",ascii)); add_name_to_string(str,ascii); DPRINT(Debug,60,(&Debug, "add_ascii_to_string: len = %d\n",str->p->len)); } void fill_ascii_to_string(str,count,ascii) struct string *str; int count; unsigned int ascii; { int i; uint16 * vector; if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"fill_ascii_to_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"fill_ascii_to_string", "Bad map (string type)",0); if (count < 1) panic("STRING PANIC",__FILE__,__LINE__,"fill_ascii_to_string", "bad count",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"fill_ascii_to_string", "Bad magic number (str_private_data)",0); if (str->p->state) { if (str->p->state->charset != str->string_type) panic("STRING PANIC",__FILE__,__LINE__,"fill_ascii_to_string", "Bad magic number (state charset)",0); free_state_internal(&(str->p->state)); } vector = safe_malloc ( count * sizeof (uint16)); /* Ascii and UNICODE have save codes ... */ for (i = 0; i < count ; i++) /* ascii is unsigned ... */ if (ascii < 128) vector[i] = ascii; else vector[i] = '?'; /* XXX */ str->string_type->charset_type->cs_add_unicodedata_to_it(str,count,vector); free(vector); DPRINT(Debug,60,(&Debug, "fill_ascii_to_string(%p,%d,%d) ('%s'; type=%p '%s'): len=%d\n", str,count,ascii, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name, str->p->len)); } struct string *collapse_spaces_from_string(str) const struct string *str; { struct charset_type * cstype; struct string *ret; int i, j = 0; if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"collapse_spaces_from_string", "Bad magic number (string type)",0); cstype = str->string_type->charset_type; if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"collapse_spaces_from_string", "Bad magic number (str_private_data)",0); DPRINT(Debug,60,(&Debug, "collapse_spaces_from_string(%p) ('%s'; type=%p '%s', len=%d)\n", str, str->string_type->MIME_name ? str->string_type->MIME_name : "", cstype, cstype->type_name, str->p->len)); /* Check lengths -- do compressions and so on */ str->string_type->charset_type->cs_check_length_it(str); ret = malloc_string(str->string_type); for (i = 0; i < str->p->len; i = j) { int is_space = 0; int POS; int len; /* Scan to next space */ for (j = i; j < str->p->len; j++) { int found; uint16 c = cstype->cs_give_unicode_from_it(str,j,&found); if (!found) { DPRINT(Debug,61,(&Debug, "collapse_spaces_from_string -- failing at %d -- no unicode\n", i)); } else is_space = unicode_ch(c,UOP_space); if (is_space) break; } POS = i; len = j-i; if (len > 0) { struct string *tmp = malloc_string(str->string_type); DPRINT(Debug,61,(&Debug, "collapse_spaces_from_string: clipping no space from %d -- len %d\n", POS,len)); cstype->cs_clip_from_it(tmp,str,&POS,len); cstype->cs_add_intdata_to_it(ret,tmp); free_string(&tmp); } /* Skip over space */ if (is_space) { uint16 SPACE_val = 0x0020; cstype->cs_add_unicodedata_to_it(ret,1,&SPACE_val); for (; j < str->p->len; j++) { int found; uint16 c = cstype->cs_give_unicode_from_it(str,j,&found); if (!found) { DPRINT(Debug,61,(&Debug, "collapse_spaces_from_string -- failing at %d -- no unicode\n", j)); } else is_space = unicode_ch(c,UOP_space); if (!is_space) break; } } } DPRINT(Debug,60,(&Debug, "collapse_spaces_from_string=%p ('%s'; type=%p '%s'): len=%d\n", ret, ret->string_type->MIME_name ? ret->string_type->MIME_name : "", ret->string_type->charset_type, ret->string_type->charset_type->type_name, ret->p->len)); return ret; } struct string *skip_ascii_head_from_string(str,ascii,ignore_case) CONST struct string *str; CONST unsigned char *ascii; int ignore_case; { struct string *ret = malloc_string(str->string_type); int X = 0; int x; if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"skip_ascii_head_from_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"skip_ascii_head_from_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"skip_ascii_head_from_string", "Bad magic number (str_private_data)",0); DPRINT(Debug,60,(&Debug, "skip_ascii_head_from_string(%p) ('%s'; type=%p '%s', len=%d)\n", str, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name, str->p->len)); DPRINT(Debug,60,(&Debug, "skip_ascii_head_from_string -- ascii=%s\n",ascii)); /* Check lengths -- do compressions and so on */ str->string_type->charset_type->cs_check_length_it(str); while(1) { int i; CONST unsigned char * p = ascii; DPRINT(Debug,61,(&Debug, "skip_ascii_head_from_string -- starting pos %d\n", X)); for (i = X; /* ascii string is unsigned ... */ *p && *p < 128 && i < str->p->len; i++, p++) { int found; uint16 c = str->string_type->charset_type-> cs_give_unicode_from_it(str,i,&found); unsigned char c1 = *p; if (!found) { DPRINT(Debug,61,(&Debug, "skip_ascii_head_from_string -- failing at %d -- no unicode\n", i)); break; } if (ignore_case) { c = unicode_ch(c,UOP_lowercase); if (!c) { DPRINT(Debug,61,(&Debug, "skip_ascii_head_from_string -- failing at %d -- no lowercasing\n", i)); break; } } if (ignore_case && c1 >= 0x41 && c1 <= 0x5A) { c1 = ( c1 - 0x41) + 0x61; } if (c1 != c) { DPRINT(Debug,61,(&Debug, "skip_ascii_head_from_string -- failing at %d -- mismatch %02X (%c) <> %04X\n", i,c1,c1,c)); break; } } if (*p) { DPRINT(Debug,61,(&Debug, "skip_ascii_head_from_string -- hit end at %d\n", i)); break; } /* Try next sequence */ X = i; DPRINT(Debug,61,(&Debug, "skip_ascii_head_from_string -- got %d\n", X)); } x = X; str->string_type->charset_type->cs_clip_from_it(ret,str,&X,str->p->len); DPRINT(Debug,60,(&Debug, "skip_ascii_head_from_string=%p ('%s'; type=%p '%s'): len=%d (clip=%d..%d)\n", ret, ret->string_type->MIME_name ? ret->string_type->MIME_name : "", ret->string_type->charset_type, ret->string_type->charset_type->type_name, ret->p->len,x,X)); return ret; } /* WARNING: get_word_from_string does everything via Unicode * may lose information on some situations */ int get_word_from_string(str,word,pos,flags,ascii_delim, found_delim) CONST struct string *str; struct string **word; int *pos; int flags; CONST unsigned char *ascii_delim; uint16 *found_delim; { int lowercase = flags & GWF_lowercase; int trim = flags & GWF_trim_space; int X = *pos; int last_X; int X1; uint16 *data = NULL; int dx = 0; int ret = 0; if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"get_word_from_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"get_word_from_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"get_word_from_string", "Bad magic number (str_private_data)",0); *word = malloc_string(str->string_type); DPRINT(Debug,60,(&Debug, "get_word_from_string(%p) ('%s'; type=%p '%s', len=%d), *pos=%d\n", str, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name, str->p->len, *pos)); if (found_delim) *found_delim = 0; /* Check lengths -- do compressions and so on */ str->string_type->charset_type->cs_check_length_it(str); if (str->p->len < 1) goto fail; /* SKIP delim */ while (X < str->p->len) { int found; int sp; uint16 c = str->string_type->charset_type-> cs_give_unicode_from_it(str,X,&found); /* ascii string is unsigned ... */ CONST unsigned char *y = NULL; if (!found) { DPRINT(Debug,57,(&Debug, "get_word_from_string -- failing at %d -- no unicode\n", X)); break; } /* Is space? (returns 0 or original character) */ sp = unicode_ch(c,UOP_space); if (sp) { if (trim) { X++; continue; } c = 0x0020; /* Treat all unicode space characters as ascii space */ } for (y = ascii_delim; *y; y++) if (*y == c || *y == sp) break; /* Delim not found ? */ if (! *y) break; X++; } X1 = X; data = safe_malloc(str->p->len * sizeof (data[0])); dx = 0; last_X = 0; /* Read first word */ while (X < str->p->len) { int found; uint16 c = str->string_type->charset_type-> cs_give_unicode_from_it(str,X,&found); int sp; /* ascii string is unsigned ... */ CONST unsigned char *y = NULL; if (!found) { DPRINT(Debug,57,(&Debug, "get_word_from_string -- failing at %d -- no unicode\n", X)); ret = 0; goto fail; } /* Is space? (returns 0 or original character) */ sp = unicode_ch(c,UOP_space); if (sp) c = 0x0020; /* Treat all unicode space characters as ascii space */ for (y = ascii_delim; *y; y++) if (*y == c || *y == sp) break; /* Delim found */ if (*y) { if (found_delim) *found_delim = c; break; } data[dx++] = lowercase ? unicode_ch(c,UOP_lowercase) : c; if (!sp) last_X = dx; X++; } if (trim && last_X < dx) dx = last_X; (*word)->string_type->charset_type->cs_add_unicodedata_to_it(*word,dx,data); ret = X -*pos; *pos = X; fail: if (data) free(data); DPRINT(Debug,58,(&Debug, "get_word_from_string=%d, *pos=%d",ret,*pos)); if (found_delim) { DPRINT(Debug,60,(&Debug,", *found_delim=%04x",*found_delim)); } DPRINT(Debug,58,(&Debug,"\n")); return ret; } int locate_unicode_from_string(str,unicode) CONST struct string *str; int unicode; { /* NOTE: We can not trim string !!! */ int i; if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"locate_unicode_from_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"locate_unicode_from_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"locate_unicode_from_string", "Bad magic number (str_private_data)",0); DPRINT(Debug,60,(&Debug, "locate_unicode_from_string(%p) ('%s'; type=%p '%s', len=%d)\n", str, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name, str->p->len)); for (i = 0; i < str->p->len; i++) { int found; uint16 c = str->string_type->charset_type-> cs_give_unicode_from_it(str,i,&found); if (found && c == unicode) { DPRINT(Debug,60,(&Debug, "locate_unicode_from_string=%d\n",i)); return i; } } DPRINT(Debug,60,(&Debug, "locate_unicode_from_string=-1 (not found)\n")); return -1; } int find_pattern_from_string(str,pattern,ignore_case) CONST struct string *str; CONST struct string *pattern; int ignore_case; { int ret = -1; if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"find_pattern_from_string", "Bad magic number (string type)",0); if (CS_charset_magic != pattern->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"find_pattern_from_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"find_pattern_from_string", "Bad map (string type)",0); if (INVALID_MAP(pattern->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"find_pattern_from_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"find_pattern_from_string", "Bad magic number (str_private_data)",0); if (pattern->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"find_pattern_from_string", "Bad magic number (str_private_data)",0); DPRINT(Debug,60,(&Debug, "find_pattern_from_string(%p,%p,%d) ('%s'; type=%p '%s', len=%d), ('%s'; type=%p '%s', len=%d)\n", str,pattern,ignore_case, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name, str->p->len, pattern->string_type->MIME_name ? pattern->string_type->MIME_name : "", pattern->string_type->charset_type, pattern->string_type->charset_type->type_name, pattern->p->len)); /* Check lengths -- do compressions and so on */ str->string_type->charset_type->cs_check_length_it(str); pattern->string_type->charset_type->cs_check_length_it(pattern); if (0 == str->p->len) { /* Nothing can be found from empty string */ DPRINT(Debug,63,(&Debug, "cs_find_pattern_from_string=0 -- empty string\n")); ret = 0; } else if (0 == pattern->p->len) { /* Empty pattern can found from anywhere */ DPRINT(Debug,63,(&Debug, "cs_find_pattern_from_string=1 -- empty pattern\n")); ret = 1; } else if (str -> string_type == pattern -> string_type) ret = str->string_type->charset_type-> cs_find_pattern_from_it(str,pattern,ignore_case); /* -1 indicates that unicode values should be used on comparision ... */ if (ret < 0) { int l1 = 0; uint16 * vector1 = safe_malloc ( (str->p->len) * sizeof (uint16)); int l2 = 0; uint16 * vector2 = safe_malloc ( (pattern->p->len) * sizeof (uint16)); int i,j; ret = 0; for (i = 0; i < str->p->len; i++) { int found; uint16 c = str->string_type->charset_type-> cs_give_unicode_from_it(str,i,&found); /* TODO: Should lowercase ANY unicode value ... */ if (!found) c = MAPPING_NONE; else if (ignore_case) { c = unicode_ch(c,UOP_lowercase); if (!c) c = MAPPING_NONE; } vector1[l1++] = c; } for (i = 0; i < pattern->p->len; i++) { int found; uint16 c = pattern->string_type->charset_type-> cs_give_unicode_from_it(pattern,i,&found); if (!found) c = MAPPING_NONE; else if (ignore_case) { c = unicode_ch(c,UOP_lowercase); if (!c) c = MAPPING_NONE; } vector2[l2++] = c; } for (i = 0; i < l1; ) { CONST int s = i + 1; for (j = 0; j < l2 && i < l1; j++,i++) { if (vector1[i] != vector2[j]) break; /* MAPPING_NONE matches newer ... */ if (MAPPING_NONE == vector1[i] || MAPPING_NONE == vector2[j]) break; } if (j >= l2) { DPRINT(Debug,63,(&Debug, "cs_find_pattern_from_string=1 MATCH\n")); ret = 1; break; } i = s; } if (!ret) { DPRINT(Debug,63,(&Debug, "cs_find_pattern_from_string=0 NO MATCH\n")); } free(vector1); free(vector2); } DPRINT(Debug,60,(&Debug, "find_pattern_from_string=%d\n",ret)); return ret; } static int string_match_part P_((const struct string * name, int name_X, const struct string * pat, int pat_X)); static int string_match_part(name,name_X,pat,pat_X) CONST struct string * name; int name_X; CONST struct string * pat; int pat_X; { int r = 1; /* It is assumed that compressions are already done ... */ while (pat_X < pat->p->len) { int pat_found = 0; uint16 code_pat = pat->string_type->charset_type-> cs_give_unicode_from_it(pat, pat_X, &pat_found); if (pat_found && 0x002A /* '*' */ == code_pat) { if (name_X < name->p->len) { if (string_match_part(name,name_X,pat,pat_X+1)) { /* Tail matches */ goto succeed; } /* Try match to next starting position */ name_X++; } else { /* '*' matches to empty string */ pat_X++; } } else if (name_X < name->p->len) { int name_found = 0; uint16 code_name = name->string_type->charset_type-> cs_give_unicode_from_it(name, name_X, &name_found); if (pat_found && 0x003F /* '?' */ == code_pat) { /* Accept any character */ name_X++; pat_X++; } else if (pat_found && name_found && code_pat == code_name) { /* Accept character */ name_X++; pat_X++; } else { r = 0; DPRINT(Debug,55,(&Debug, "-- Match fail on pat_X=%d (%04X) name_X=%d (%04X)\n", pat_X,code_pat,name_X,code_name)); break; } } else { r = 0; DPRINT(Debug,55,(&Debug, "-- Match fail on pat_X=%d name_X=%d (end of name)\n", pat_X,name_X)); break; } } if (name_X != name->p->len || pat_X != pat->p->len) { DPRINT(Debug,55,(&Debug, "-- Match fail on pat_X=%d name_X=%d (failure?)\n", pat_X,name_X)); r = 0; } succeed: return r; } /* return 1 on succeed and 0 on failure */ int string_match(name,pat) CONST struct string * name; CONST struct string * pat; { int r = 0; if (CS_charset_magic != name->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"string_match", "Bad magic number (string type)",0); if (CS_charset_magic != pat->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"string_match", "Bad magic number (string type)",0); if (INVALID_MAP(name->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"string_match", "Bad map (string type)",0); if (INVALID_MAP(pat->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"string_match", "Bad map (string type)",0); if (name->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"string_match", "Bad magic number (str_private_data)",0); if (pat->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"string_match", "Bad magic number (str_private_data)",0); DPRINT(Debug,60,(&Debug, "string_match(%p,%p) ('%s'; type=%p '%s', len=%d), ('%s'; type=%p '%s', len=%d)\n", name,pat, name->string_type->MIME_name ? name->string_type->MIME_name : "", name->string_type->charset_type, name->string_type->charset_type->type_name, name->p->len, pat->string_type->MIME_name ? pat->string_type->MIME_name : "", pat->string_type->charset_type, pat->string_type->charset_type->type_name, pat->p->len)); /* Check lengths -- do compressions and so on */ name->string_type->charset_type->cs_check_length_it(name); pat->string_type->charset_type->cs_check_length_it(pat); r = string_match_part(name,0,pat,0); DPRINT(Debug,60,(&Debug, "string_match=%d\n",r)); return r; } uint16 give_unicode_from_string(str,pos) CONST struct string *str; int pos; { int found; uint16 ret; if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"give_unicode_from_string", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"give_unicode_from_string", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"give_unicode_from_string", "Bad magic number (str_private_data)",0); /* It is assumed that compressions are done .. ie string_length() function is called */ ret = str->string_type->charset_type-> cs_give_unicode_from_it(str,pos, &found); DPRINT(Debug,60,(&Debug, "give_unicode_from_string(%p,%d)=%d ('%s'; type=%p '%s')%s\n", str,pos,ret, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name, found ? "" : " [NOT FOUND]")); return ret; } void remove_control(str) CONST struct string *str; { if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"remove_control", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"remove_control", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"remove_control", "Bad magic number (str_private_data)",0); if (str->p->state) { if (str->p->state->charset != str->string_type) panic("STRING PANIC",__FILE__,__LINE__,"remove_control", "Bad magic number (state charset)",0); free_state_internal(&(str->p->state)); } DPRINT(Debug,60,(&Debug, "remove_control(%p) ('%s'; type=%p '%s')\n", str, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name)); str->string_type->charset_type->cs_remove_control_it(str); } void add_state_to_string(str,ch) struct string *str; struct charset_state *ch; { if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"add_state_to_string", "Bad magic number (string type)",0); if (CS_charset_magic != ch->charset->magic) panic("STRING PANIC",__FILE__,__LINE__,"add_state_to_string", "Bad magic number (charset)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"add_state_to_string", "Bad map (string type)",0); if (INVALID_MAP(ch->charset)) panic("STRING PANIC",__FILE__,__LINE__,"add_state_to_string", "Bad map (charset)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"add_state_to_string", "Bad magic number (str_private_data)",0); if (str->p->state) { if (str->p->state->charset != str->string_type) panic("STRING PANIC",__FILE__,__LINE__,"add_state_to_string", "Bad magic number (state charset)",0); free_state_internal(&(str->p->state)); } DPRINT(Debug,60,(&Debug, "add_state_to_it(%p,%p) ('%s'; type=%p '%s', '%s'; type=%p '%s')\n", str,ch, str->string_type->MIME_name ? str->string_type->MIME_name : "", str->string_type->charset_type, str->string_type->charset_type->type_name, ch->charset->MIME_name ? ch->charset->MIME_name : "", ch->charset->charset_type, ch->charset->charset_type->type_name)); if (ch->charset == str->string_type) str->string_type->charset_type->cs_add_state_to_it(str,ch); else { int found; uint16 val = ch->charset->charset_type->cs_give_unicode_from_s_it(ch,&found); str->string_type->charset_type-> cs_add_unicodedata_to_it(str,1,&val); } } int charset_properties(ptr) charset_t ptr; { int prop = 0; if (CS_charset_magic != ptr->magic) panic("STRING PANIC",__FILE__,__LINE__,"charset_properties", "Bad magic number (charset)",0); if (INVALID_MAP(ptr)) panic("STRING PANIC",__FILE__,__LINE__,"charset_properties", "Bad map (charset)",0); prop = ptr->charset_type->cs_it_properties(ptr); DPRINT(Debug,11,(&Debug, "charset_properties(%p '%s'; type=%p)=%d\n", ptr, ptr->MIME_name ? ptr->MIME_name : "", ptr->charset_type, prop)); return prop; } /* bad_pos is -1 if string is OK */ long string_to_long(str,bad_pos) CONST struct string *str; int *bad_pos; { long val = 0L; int found; int pos = 0; uint16 c; int plus_minus = 1; if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"string_to_long", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"string_to_long", "Bad magic number (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"string_to_long", "Bad magic number (str_private_data)",0); *bad_pos = -1; pos = 0; if (str->p->len < 1) goto fail; c = str->string_type->charset_type-> cs_give_unicode_from_it(str,pos,&found); if (!found) goto fail; if (0x002B /* + */ == c) { plus_minus = 1; pos++; } else if (0x002D /* - */ == c) { plus_minus = -1; pos++; } while (pos < str->p->len) { int num; long l1; c = str->string_type->charset_type-> cs_give_unicode_from_it(str,pos,&found); if (!found) goto fail; if (c < 0x0030 /* 0 */ || c > 0x0039 /* 9 */) goto fail; num = c - 0x0030; l1 = val * 10 + num; if (l1 < val) { /* Overflow */ goto fail; } val = l1; pos++; } val = val * plus_minus; DPRINT(Debug,30,(&Debug, "string_to_long: %S gives value %ld\n", str,val)); return val; fail: *bad_pos = pos; val = val * plus_minus; DPRINT(Debug,30,(&Debug, "string_to_long: %S gives value %ld, error on position %d\n", str,val,pos)); return val; } /* Return 1 is matches, otherwise 0 */ int string_matches_ascii(str,ascii) CONST struct string *str; CONST unsigned char *ascii; { int i; if (CS_charset_magic != str->string_type->magic) panic("STRING PANIC",__FILE__,__LINE__,"string_matches_ascii", "Bad magic number (string type)",0); if (INVALID_MAP(str->string_type)) panic("STRING PANIC",__FILE__,__LINE__,"string_matches_ascii", "Bad map (string type)",0); if (str->p->magic != CS_str_magic) panic("STRING PANIC",__FILE__,__LINE__,"string_matches_ascii", "Bad magic number (str_private_data)",0); for (i = 0; i < str->p->len; i++) { uint16 c; int found; c = str->string_type->charset_type-> cs_give_unicode_from_it(str,i,&found); if (!found) { DPRINT(Debug,30,(&Debug, "string_matches_ascii=0 on pos %d (unicode not found)\n", i)); return 0; } if (!ascii[i]) { DPRINT(Debug,30,(&Debug, "string_matches_ascii=0 on pos %d (ascii string ended)\n", i)); return 0; } if (c != ascii[i]) { DPRINT(Debug,30,(&Debug, "string_matches_ascii=0 on pos %d (mismatch)\n", i)); return 0; } } if (ascii[i]) { DPRINT(Debug,30,(&Debug, "string_matches_ascii=0 on pos %d (ascii string not ended)\n", i)); return 0; } DPRINT(Debug,30,(&Debug, "string_matches_ascii=1 on pos %d (matches)\n", i)); return 1; } /* * Local Variables: * mode:c * c-basic-offset:4 * buffer-file-coding-system: iso-8859-1 * End: */