]> code.citadel.org Git - citadel.git/blob - citadel/vcard.c
* serv_vcard.c: fixed crashola bug in cmd_greg()
[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 #include <time.h>
19 #include <ctype.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <limits.h>
23 #include <pthread.h>
24 #include <syslog.h>
25 #include "citadel.h"
26 #include "server.h"
27 #include "control.h"
28 #include "sysdep_decls.h"
29 #include "support.h"
30 #include "config.h"
31 #include "tools.h"
32 #include "vcard.h"
33
34 /* 
35  * Constructor (empty vCard)
36  */
37 struct vCard *vcard_new() {
38         struct vCard *v;
39
40         v = (struct vCard *) mallok(sizeof(struct vCard));
41         if (v == NULL) return v;
42
43         v->magic = CTDL_VCARD_MAGIC;
44         v->numprops = 0;
45         v->prop = NULL;
46
47         return v;
48 }
49
50
51 /*
52  * Constructor (supply serialized vCard)
53  */
54 struct vCard *vcard_load(char *vtext) {
55         struct vCard *v;
56         int valid = 0;
57         char *mycopy, *ptr;
58         char *namebuf, *valuebuf;
59         int i;
60         int colonpos, nlpos;
61
62         mycopy = strdoop(vtext);
63         if (mycopy == NULL) return NULL;
64
65         /* First, fix this big pile o' vCard to make it more parseable.
66          * To make it easier to parse, we convert CRLF to LF, and unfold any
67          * multi-line fields into single lines.
68          */
69         for (i=0; i<strlen(mycopy); ++i) {
70                 if (!strncmp(&mycopy[i], "\r\n", 2)) {
71                         strcpy(&mycopy[i], &mycopy[i+1]);
72                 }
73                 if ( (mycopy[i]=='\n') && (isspace(mycopy[i+1])) ) {
74                         strcpy(&mycopy[i], &mycopy[i+1]);
75                 }
76         }
77
78         v = vcard_new();
79         if (v == NULL) return v;
80
81         ptr = mycopy;
82         while (strlen(ptr)>0) {
83                 colonpos = (-1);
84                 nlpos = (-1);
85                 colonpos = pattern2(ptr, ":");
86                 nlpos = pattern2(ptr, "\n");
87
88                 if (nlpos > colonpos > 0) {
89                         namebuf = mallok(colonpos + 1);
90                         valuebuf = mallok(nlpos - colonpos + 1);
91                         strncpy(namebuf, ptr, colonpos);
92                         namebuf[colonpos] = 0;
93                         strncpy(valuebuf, &ptr[colonpos+1], nlpos-colonpos-1);
94                         valuebuf[nlpos-colonpos-1] = 0;
95
96                         if ( (!strcasecmp(namebuf, "end"))
97                            && (!strcasecmp(valuebuf, "vcard")) )  valid = 0;
98                         if ( (!strcasecmp(namebuf, "begin"))
99                            && (!strcasecmp(valuebuf, "vcard")) )  valid = 1;
100
101                         if ( (valid) && (strcasecmp(namebuf, "begin")) ) {
102                                 ++v->numprops;
103                                 v->prop = reallok(v->prop,
104                                         (v->numprops * sizeof(char *) * 2) );
105                                 v->prop[v->numprops-1].name = namebuf;
106                                 v->prop[v->numprops-1].value = valuebuf;
107                         } 
108                         else {
109                                 phree(namebuf);
110                                 phree(valuebuf);
111                         }
112
113                 }
114
115                 while ( (*ptr != '\n') && (strlen(ptr)>0) ) {
116                         ++ptr;
117                 }
118                 if (*ptr == '\n') ++ptr;
119         }
120
121         phree(mycopy);
122         return v;
123 }
124
125
126 /*
127  * Fetch the value of a particular key
128  * If is_partial is set to 1, a partial match is ok (for example,
129  * a key of "tel;home" will satisfy a search for "tel")
130  */
131 char *vcard_get_prop(struct vCard *v, char *propname, int is_partial) {
132         int i;
133
134         lprintf(9, "vcard_get_prop(%s, %d) called\n", propname, is_partial);
135         if (v->numprops) for (i=0; i<(v->numprops); ++i) {
136                 if ( (!strcasecmp(v->prop[i].name, propname))
137                    || (  (!strncasecmp(v->prop[i].name,
138                                         propname, strlen(propname)))
139                          && (v->prop[i].name[strlen(propname)] == ';')
140                          && (is_partial) ) ) {
141                         return(v->prop[i].value);
142                         lprintf(9, "found: value is <%s>\n", v->prop[i].value);
143                 }
144         }
145
146         lprintf(9, "not found: returning null\n");
147         return NULL;
148 }
149
150
151
152
153 /*
154  * Destructor
155  */
156 void vcard_free(struct vCard *v) {
157         int i;
158         
159         if (v->magic != CTDL_VCARD_MAGIC) return;       /* Self-check */
160         
161         if (v->numprops) for (i=0; i<(v->numprops); ++i) {
162                 phree(v->prop[i].name);
163                 phree(v->prop[i].value);
164         }
165
166         if (v->prop != NULL) phree(v->prop);
167         
168         memset(v, 0, sizeof(struct vCard));
169         phree(v);
170 }
171
172
173 /*
174  * Set a name/value pair in the card
175  */
176 void vcard_set_prop(struct vCard *v, char *name, char *value) {
177         int i;
178
179         if (v->magic != CTDL_VCARD_MAGIC) return;       /* Self-check */
180
181         /* If this key is already present, replace it */
182         if (v->numprops) for (i=0; i<(v->numprops); ++i) {
183                 if (!strcasecmp(v->prop[i].name, name)) {
184                         phree(v->prop[i].name);
185                         phree(v->prop[i].value);
186                         v->prop[i].name = strdoop(name);
187                         v->prop[i].value = strdoop(value);
188                         return;
189                 }
190         }
191
192         /* Otherwise, append it */
193         ++v->numprops;
194         v->prop = reallok(v->prop,
195                 (v->numprops * sizeof(char *) * 2) );
196         v->prop[v->numprops-1].name = strdoop(name);
197         v->prop[v->numprops-1].value = strdoop(value);
198 }
199
200
201
202
203 /*
204  * Serialize a struct vcard into a standard text/x-vcard MIME type.
205  *
206  */
207 char *vcard_serialize(struct vCard *v)
208 {
209         char *ser;
210         int i;
211         size_t len;
212
213         if (v->magic != CTDL_VCARD_MAGIC) return NULL;  /* self check */
214
215         /* Figure out how big a buffer we need to allocate */
216         len = 64;       /* for begin, end, and a little padding for safety */
217         if (v->numprops) for (i=0; i<(v->numprops); ++i) {
218                 len = len +
219                         strlen(v->prop[i].name) +
220                         strlen(v->prop[i].value) + 4;
221         }
222
223         ser = mallok(len);
224         if (ser == NULL) return NULL;
225
226         strcpy(ser, "begin:vcard\r\n");
227         if (v->numprops) for (i=0; i<(v->numprops); ++i) {
228                 strcat(ser, v->prop[i].name);
229                 strcat(ser, ":");
230                 strcat(ser, v->prop[i].value);
231                 strcat(ser, "\r\n");
232         }
233         strcat(ser, "end:vcard\r\n");
234
235         return ser;
236 }