]> code.citadel.org Git - citadel.git/blob - citadel/vcard.c
* added vcard_to_html() function
[citadel.git] / citadel / vcard.c
1 /*
2  * $Id$
3  *
4  * vCard implementation for Citadel/UX
5  *
6  * Copyright (C) 1999 by Art Cancro
7  * This code is freely redistributable under the terms of the GNU General
8  * Public License.  All other rights reserved.
9  */
10
11
12 #include "sysdep.h"
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <stdio.h>
16 #include <fcntl.h>
17 #include <signal.h>
18
19 #if TIME_WITH_SYS_TIME
20 # include <sys/time.h>
21 # include <time.h>
22 #else
23 # if HAVE_SYS_TIME_H
24 #  include <sys/time.h>
25 # else
26 #  include <time.h>
27 # endif
28 #endif
29
30 #include <ctype.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <limits.h>
34 #include <syslog.h>
35 #include "citadel.h"
36 #include "server.h"
37 #include "control.h"
38 #include "sysdep_decls.h"
39 #include "support.h"
40 #include "config.h"
41 #include "tools.h"
42 #include "vcard.h"
43
44 /* 
45  * Constructor (empty vCard)
46  */
47 struct vCard *vcard_new() {
48         struct vCard *v;
49
50         v = (struct vCard *) mallok(sizeof(struct vCard));
51         if (v == NULL) return v;
52
53         v->magic = CTDL_VCARD_MAGIC;
54         v->numprops = 0;
55         v->prop = NULL;
56
57         return v;
58 }
59
60
61 /*
62  * Constructor (supply serialized vCard)
63  */
64 struct vCard *vcard_load(char *vtext) {
65         struct vCard *v;
66         int valid = 0;
67         char *mycopy, *ptr;
68         char *namebuf, *valuebuf;
69         int i;
70         int colonpos, nlpos;
71
72         mycopy = strdoop(vtext);
73         if (mycopy == NULL) return NULL;
74
75         /* First, fix this big pile o' vCard to make it more parseable.
76          * To make it easier to parse, we convert CRLF to LF, and unfold any
77          * multi-line fields into single lines.
78          */
79         for (i=0; i<strlen(mycopy); ++i) {
80                 if (!strncmp(&mycopy[i], "\r\n", 2)) {
81                         strcpy(&mycopy[i], &mycopy[i+1]);
82                 }
83                 if ( (mycopy[i]=='\n') && (isspace(mycopy[i+1])) ) {
84                         strcpy(&mycopy[i], &mycopy[i+1]);
85                 }
86         }
87
88         v = vcard_new();
89         if (v == NULL) return v;
90
91         ptr = mycopy;
92         while (strlen(ptr)>0) {
93                 colonpos = (-1);
94                 nlpos = (-1);
95                 colonpos = pattern2(ptr, ":");
96                 nlpos = pattern2(ptr, "\n");
97
98                 if (nlpos > colonpos > 0) {
99                         namebuf = mallok(colonpos + 1);
100                         valuebuf = mallok(nlpos - colonpos + 1);
101                         strncpy(namebuf, ptr, colonpos);
102                         namebuf[colonpos] = 0;
103                         strncpy(valuebuf, &ptr[colonpos+1], nlpos-colonpos-1);
104                         valuebuf[nlpos-colonpos-1] = 0;
105
106                         if ( (!strcasecmp(namebuf, "end"))
107                            && (!strcasecmp(valuebuf, "vcard")) )  valid = 0;
108                         if ( (!strcasecmp(namebuf, "begin"))
109                            && (!strcasecmp(valuebuf, "vcard")) )  valid = 1;
110
111                         if ( (valid) && (strcasecmp(namebuf, "begin")) ) {
112                                 ++v->numprops;
113                                 v->prop = reallok(v->prop,
114                                         (v->numprops * sizeof(char *) * 2) );
115                                 v->prop[v->numprops-1].name = namebuf;
116                                 v->prop[v->numprops-1].value = valuebuf;
117                         } 
118                         else {
119                                 phree(namebuf);
120                                 phree(valuebuf);
121                         }
122
123                 }
124
125                 while ( (*ptr != '\n') && (strlen(ptr)>0) ) {
126                         ++ptr;
127                 }
128                 if (*ptr == '\n') ++ptr;
129         }
130
131         phree(mycopy);
132         return v;
133 }
134
135
136 /*
137  * Fetch the value of a particular key
138  * If is_partial is set to 1, a partial match is ok (for example,
139  * a key of "tel;home" will satisfy a search for "tel")
140  * Set "instance" to a value higher than 0 to return subsequent instances
141  * of the same key
142  */
143 char *vcard_get_prop(struct vCard *v, char *propname,
144                         int is_partial, int instance) {
145         int i;
146         int found_instance = 0;
147
148         if (v->numprops) for (i=0; i<(v->numprops); ++i) {
149                 if ( (!strcasecmp(v->prop[i].name, propname))
150                    || (  (!strncasecmp(v->prop[i].name,
151                                         propname, strlen(propname)))
152                          && (v->prop[i].name[strlen(propname)] == ';')
153                          && (is_partial) ) ) {
154                         if (instance == found_instance++) {
155                                 return(v->prop[i].value);
156                         }
157                 }
158         }
159
160         return NULL;
161 }
162
163
164
165
166 /*
167  * Destructor
168  */
169 void vcard_free(struct vCard *v) {
170         int i;
171         
172         if (v->magic != CTDL_VCARD_MAGIC) return;       /* Self-check */
173         
174         if (v->numprops) for (i=0; i<(v->numprops); ++i) {
175                 phree(v->prop[i].name);
176                 phree(v->prop[i].value);
177         }
178
179         if (v->prop != NULL) phree(v->prop);
180         
181         memset(v, 0, sizeof(struct vCard));
182         phree(v);
183 }
184
185
186 /*
187  * Experimental output type of thing
188  */
189 char *vcard_to_html(struct vCard *v) {
190         char *html = NULL;
191         int i;
192         size_t len = 256;
193
194         if (v == NULL) return NULL;
195
196         if (v->numprops) for (i=0; i<(v->numprops); ++i) {
197                 len += strlen(v->prop[i].name);
198                 len += strlen(v->prop[i].value);
199         }
200
201         html = mallok(len);
202         if (html == NULL) return NULL;
203
204         sprintf(html, "<TABLE bgcolor=#888888>");
205         if (v->numprops) for (i=0; i<(v->numprops); ++i) {
206                 sprintf(&html[strlen(html),
207                         "<TR><TD>%s</TD><TD>%s</TD></TR>\n",
208                         v->prop[i].name,
209                         v->prop[i].value
210                 );
211         }
212
213         strcat(html, "</TABLE>");
214
215         return(html);
216 }
217
218
219
220
221 /*
222  * Set a name/value pair in the card
223  */
224 void vcard_set_prop(struct vCard *v, char *name, char *value, int append) {
225         int i;
226
227         if (v->magic != CTDL_VCARD_MAGIC) return;       /* Self-check */
228
229         /* If this key is already present, replace it */
230         if (!append) if (v->numprops) for (i=0; i<(v->numprops); ++i) {
231                 if (!strcasecmp(v->prop[i].name, name)) {
232                         phree(v->prop[i].name);
233                         phree(v->prop[i].value);
234                         v->prop[i].name = strdoop(name);
235                         v->prop[i].value = strdoop(value);
236                         return;
237                 }
238         }
239
240         /* Otherwise, append it */
241         ++v->numprops;
242         v->prop = reallok(v->prop,
243                 (v->numprops * sizeof(char *) * 2) );
244         v->prop[v->numprops-1].name = strdoop(name);
245         v->prop[v->numprops-1].value = strdoop(value);
246 }
247
248
249
250
251 /*
252  * Serialize a struct vcard into a standard text/x-vcard MIME type.
253  *
254  */
255 char *vcard_serialize(struct vCard *v)
256 {
257         char *ser;
258         int i;
259         size_t len;
260
261         if (v->magic != CTDL_VCARD_MAGIC) return NULL;  /* self check */
262
263         /* Figure out how big a buffer we need to allocate */
264         len = 64;       /* for begin, end, and a little padding for safety */
265         if (v->numprops) for (i=0; i<(v->numprops); ++i) {
266                 len = len +
267                         strlen(v->prop[i].name) +
268                         strlen(v->prop[i].value) + 4;
269         }
270
271         ser = mallok(len);
272         if (ser == NULL) return NULL;
273
274         strcpy(ser, "begin:vcard\r\n");
275         if (v->numprops) for (i=0; i<(v->numprops); ++i) {
276                 strcat(ser, v->prop[i].name);
277                 strcat(ser, ":");
278                 strcat(ser, v->prop[i].value);
279                 strcat(ser, "\r\n");
280         }
281         strcat(ser, "end:vcard\r\n");
282
283         return ser;
284 }