1 /*
2 ** Copyright 2002-2004 Double Precision, Inc. See COPYING for
3 ** distribution information.
4 */
5
6 /*
7 */
8
9 #if HAVE_CONFIG_H
10 #include "rfc2045_config.h"
11 #endif
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include "rfc2045.h"
17 #include <errno.h>
18
19 static const char xdigit[]="0123456789ABCDEFabcdef";
20
21 #define DOENCODE(c) \
22 (strchr("()'\"\\%:;=", (c)) || (c) <= ' ' || (c) >= 127)
23
24 static int docreate(const char *name,
25 char *attrvalue,
26 int (*cb_func)(const char *param,
27 const char *value,
28 void *void_arg),
29 void *cb_arg);
30
rfc2231_attrCreate(const char * name,const char * value,const char * charset,const char * language,int (* cb_func)(const char * param,const char * value,void * void_arg),void * cb_arg)31 int rfc2231_attrCreate(const char *name, const char *value,
32 const char *charset,
33 const char *language,
34 int (*cb_func)(const char *param,
35 const char *value,
36 void *void_arg),
37 void *cb_arg)
38 {
39 size_t l;
40 const char *cp;
41 char *p, *q;
42 int rc;
43
44 if (strlen(name)>60)
45 {
46 errno=EINVAL;
47 return -1; /* You kidding me? */
48 }
49
50 for (l=0; value[l]; l++)
51 if (DOENCODE(value[l]))
52 break;
53
54 if (value[l] == 0 && strlen(name)+strlen(value)<75) /* No need to encode */
55 {
56 char *p=malloc(strlen(value)+3);
57
58 if (!p)
59 return -1;
60
61 strcat(strcat(strcpy(p, "\""), value), "\"");
62
63 rc=(*cb_func)(name, p, cb_arg);
64 free(p);
65 return rc;
66 }
67
68 if (!charset) charset="";
69 if (!language) language="";
70
71 l=strlen(charset)+strlen(language)+strlen(value)+3;
72
73 for (cp=value; *cp; cp++)
74 if (DOENCODE(*cp))
75 l += 2;
76
77 p=malloc(l);
78 if (!p)
79 return -1;
80
81 strcat(strcat(strcat(strcpy(p, charset), "'"),language), "'");
82 q=p+strlen(p);
83 for (cp=value; *cp; cp++)
84 {
85 if (DOENCODE(*cp))
86 {
87 *q++='%';
88 *q++ = xdigit[ ((unsigned char)*cp / 16) & 15];
89 *q++ = xdigit[ *cp & 15];
90 }
91 else
92 *q++= *cp;
93 }
94 *q=0;
95
96 rc=docreate(name, p, cb_func, cb_arg);
97 free(p);
98 return rc;
99 }
100
docreate(const char * name,char * q,int (* cb_func)(const char * param,const char * value,void * void_arg),void * cb_arg)101 static int docreate(const char *name,
102 char *q,
103 int (*cb_func)(const char *param,
104 const char *value,
105 void *void_arg),
106 void *cb_arg)
107 {
108 char c;
109 char *r;
110 int rc;
111 size_t l;
112 int n;
113
114 r=malloc(strlen(name)+20);
115 if (!r)
116 return -1;
117
118 rc=0;
119 n=0;
120
121 while (*q)
122 {
123 sprintf(r, "%s*%d*", name, n++);
124
125 l=strlen(q);
126 if (l > 70-strlen(r))
127 l=70-strlen(r);
128
129 if (q[l] == '%')
130 l += 3;
131 else if (l && q[l-1] == '%')
132 l += 2;
133 else if (l > 1 && q[l-2] == '%')
134 l += 1;
135
136 c=q[l];
137 q[l]=0;
138
139 rc=(*cb_func)(r, q, cb_arg);
140 if (rc)
141 break;
142 q[l]=c;
143 q += l;
144 }
145 free(r);
146 return rc;
147 }
148