Back to index

courier  0.68.2
rfc2231encode.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2002-2004 Double Precision, Inc.  See COPYING for
00003 ** distribution information.
00004 */
00005 
00006 /*
00007 */
00008 
00009 #if    HAVE_CONFIG_H
00010 #include "rfc2045_config.h"
00011 #endif
00012 #include      <stdlib.h>
00013 #include      <stdio.h>
00014 #include      <string.h>
00015 #include      <ctype.h>
00016 #include      "rfc2045.h"
00017 #include      <errno.h>
00018 
00019 static const char xdigit[]="0123456789ABCDEFabcdef";
00020 
00021 #define DOENCODE(c) \
00022        (strchr("()'\"\\%:;=", (c)) || (c) <= ' ' || (c) >= 127)
00023 
00024 static int docreate(const char *name,
00025                   char *attrvalue,
00026                   int (*cb_func)(const char *param,
00027                                const char *value,
00028                                void *void_arg),
00029                   void *cb_arg);
00030 
00031 int rfc2231_attrCreate(const char *name, const char *value,
00032                      const char *charset,
00033                      const char *language,
00034                      int (*cb_func)(const char *param,
00035                                   const char *value,
00036                                   void *void_arg),
00037                      void *cb_arg)
00038 {
00039        size_t l;
00040        const char *cp;
00041        char *p, *q;
00042        int rc;
00043 
00044        if (strlen(name)>60)
00045        {
00046               errno=EINVAL;
00047               return -1; /* You kidding me? */
00048        }
00049 
00050        for (l=0; value[l]; l++)
00051               if (DOENCODE(value[l]))
00052                      break;
00053 
00054        if (value[l] == 0 && strlen(name)+strlen(value)<75) /* No need to encode */
00055        {
00056               char *p=malloc(strlen(value)+3);
00057 
00058               if (!p)
00059                      return -1;
00060 
00061               strcat(strcat(strcpy(p, "\""), value), "\"");
00062 
00063               rc=(*cb_func)(name, p, cb_arg);
00064               free(p);
00065               return rc;
00066        }
00067 
00068        if (!charset) charset="";
00069        if (!language) language="";
00070 
00071        l=strlen(charset)+strlen(language)+strlen(value)+3;
00072 
00073        for (cp=value; *cp; cp++)
00074               if (DOENCODE(*cp))
00075                      l += 2;
00076 
00077        p=malloc(l);
00078        if (!p)
00079               return -1;
00080 
00081        strcat(strcat(strcat(strcpy(p, charset), "'"),language), "'");
00082        q=p+strlen(p);
00083        for (cp=value; *cp; cp++)
00084        {
00085               if (DOENCODE(*cp))
00086               {
00087                      *q++='%';
00088                      *q++ = xdigit[ ((unsigned char)*cp / 16) & 15];
00089                      *q++ = xdigit[ *cp & 15];
00090               }
00091               else
00092                      *q++= *cp;
00093        }
00094        *q=0;
00095 
00096        rc=docreate(name, p, cb_func, cb_arg);
00097        free(p);
00098        return rc;
00099 }
00100 
00101 static int docreate(const char *name,
00102                   char *q,
00103                   int (*cb_func)(const char *param,
00104                                const char *value,
00105                                void *void_arg),
00106                   void *cb_arg)
00107 {
00108        char c;
00109        char *r;
00110        int rc;
00111        size_t l;
00112        int n;
00113 
00114        r=malloc(strlen(name)+20);
00115        if (!r)
00116               return -1;
00117 
00118        rc=0;
00119        n=0;
00120 
00121        while (*q)
00122        {
00123               sprintf(r, "%s*%d*", name, n++);
00124 
00125               l=strlen(q);
00126               if (l > 70-strlen(r))
00127                      l=70-strlen(r);
00128 
00129               if (q[l] == '%')
00130                      l += 3;
00131               else if (l && q[l-1] == '%')
00132                      l += 2;
00133               else if (l > 1 && q[l-2] == '%')
00134                      l += 1;
00135                      
00136               c=q[l];
00137               q[l]=0;
00138 
00139               rc=(*cb_func)(r, q, cb_arg);
00140               if (rc)
00141                      break;
00142               q[l]=c;
00143               q += l;
00144        }
00145        free(r);
00146        return rc;
00147 }