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