Home | History | Annotate | Download | only in xmlwf
      1 #include <string.h>
      2 #include "xmlmime.h"
      3 
      4 static const char *
      5 getTok(const char **pp)
      6 {
      7   /* inComment means one level of nesting; inComment+1 means two levels etc */
      8   enum { inAtom, inString, init, inComment };
      9   int state = init;
     10   const char *tokStart = 0;
     11   for (;;) {
     12     switch (**pp) {
     13     case '\0':
     14       if (state == inAtom)
     15         return tokStart;
     16       return 0;
     17     case ' ':
     18     case '\r':
     19     case '\t':
     20     case '\n':
     21       if (state == inAtom)
     22         return tokStart;
     23       break;
     24     case '(':
     25       if (state == inAtom)
     26         return tokStart;
     27       if (state != inString)
     28         state++;
     29       break;
     30     case ')':
     31       if (state > init)
     32         --state;
     33       else if (state != inString)
     34         return 0;
     35       break;
     36     case ';':
     37     case '/':
     38     case '=':
     39       if (state == inAtom)
     40         return tokStart;
     41       if (state == init)
     42         return (*pp)++;
     43       break;
     44     case '\\':
     45       ++*pp;
     46       if (**pp == '\0')
     47         return 0;
     48       break;
     49     case '"':
     50       switch (state) {
     51       case inString:
     52         ++*pp;
     53         return tokStart;
     54       case inAtom:
     55         return tokStart;
     56       case init:
     57         tokStart = *pp;
     58         state = inString;
     59         break;
     60       }
     61       break;
     62     default:
     63       if (state == init) {
     64         tokStart = *pp;
     65         state = inAtom;
     66       }
     67       break;
     68     }
     69     ++*pp;
     70   }
     71   /* not reached */
     72 }
     73 
     74 /* key must be lowercase ASCII */
     75 
     76 static int
     77 matchkey(const char *start, const char *end, const char *key)
     78 {
     79   if (!start)
     80     return 0;
     81   for (; start != end; start++, key++)
     82     if (*start != *key && *start != 'A' + (*key - 'a'))
     83       return 0;
     84   return *key == '\0';
     85 }
     86 
     87 void
     88 getXMLCharset(const char *buf, char *charset)
     89 {
     90   const char *next, *p;
     91 
     92   charset[0] = '\0';
     93   next = buf;
     94   p = getTok(&next);
     95   if (matchkey(p, next, "text"))
     96     strcpy(charset, "us-ascii");
     97   else if (!matchkey(p, next, "application"))
     98     return;
     99   p = getTok(&next);
    100   if (!p || *p != '/')
    101     return;
    102   p = getTok(&next);
    103 #if 0
    104   if (!matchkey(p, next, "xml") && charset[0] == '\0')
    105     return;
    106 #endif
    107   p = getTok(&next);
    108   while (p) {
    109     if (*p == ';') {
    110       p = getTok(&next);
    111       if (matchkey(p, next, "charset")) {
    112         p = getTok(&next);
    113         if (p && *p == '=') {
    114           p = getTok(&next);
    115           if (p) {
    116             char *s = charset;
    117             if (*p == '"') {
    118               while (++p != next - 1) {
    119                 if (*p == '\\')
    120                   ++p;
    121                 if (s == charset + CHARSET_MAX - 1) {
    122                   charset[0] = '\0';
    123                   break;
    124                 }
    125                 *s++ = *p;
    126               }
    127               *s++ = '\0';
    128             }
    129             else {
    130               if (next - p > CHARSET_MAX - 1)
    131                 break;
    132               while (p != next)
    133                 *s++ = *p++;
    134               *s = 0;
    135               break;
    136             }
    137           }
    138         }
    139         break;
    140       }
    141     }
    142   else
    143     p = getTok(&next);
    144   }
    145 }
    146 
    147 #ifdef TEST
    148 
    149 #include <stdio.h>
    150 
    151 int
    152 main(int argc, char *argv[])
    153 {
    154   char buf[CHARSET_MAX];
    155   if (argc <= 1)
    156     return 1;
    157   printf("%s\n", argv[1]);
    158   getXMLCharset(argv[1], buf);
    159   printf("charset=\"%s\"\n", buf);
    160   return 0;
    161 }
    162 
    163 #endif /* TEST */
    164