4 * vCard implementation for Citadel/UX
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.
28 #include "sysdep_decls.h"
35 * Constructor (empty vCard)
37 struct vCard *vcard_new() {
40 v = (struct vCard *) mallok(sizeof(struct vCard));
41 if (v == NULL) return v;
43 v->magic = CTDL_VCARD_MAGIC;
52 * Constructor (supply serialized vCard)
54 struct vCard *vcard_load(char *vtext) {
58 char *namebuf, *valuebuf;
62 mycopy = strdoop(vtext);
63 if (mycopy == NULL) return NULL;
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.
69 for (i=0; i<strlen(mycopy); ++i) {
70 if (!strncmp(&mycopy[i], "\r\n", 2)) {
71 strcpy(&mycopy[i], &mycopy[i+1]);
73 if ( (mycopy[i]=='\n') && (isspace(mycopy[i+1])) ) {
74 strcpy(&mycopy[i], &mycopy[i+1]);
79 if (v == NULL) return v;
82 while (strlen(ptr)>0) {
85 colonpos = pattern2(ptr, ":");
86 nlpos = pattern2(ptr, "\n");
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;
96 if ( (!strcasecmp(namebuf, "end"))
97 && (!strcasecmp(valuebuf, "vcard")) ) valid = 0;
98 if ( (!strcasecmp(namebuf, "begin"))
99 && (!strcasecmp(valuebuf, "vcard")) ) valid = 1;
101 if ( (valid) && (strcasecmp(namebuf, "begin")) ) {
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;
115 while ( (*ptr != '\n') && (strlen(ptr)>0) ) {
118 if (*ptr == '\n') ++ptr;
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")
131 char *vcard_get_prop(struct vCard *v, char *propname, int is_partial) {
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);
146 lprintf(9, "not found: returning null\n");
156 void vcard_free(struct vCard *v) {
159 if (v->magic != CTDL_VCARD_MAGIC) return; /* Self-check */
161 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
162 phree(v->prop[i].name);
163 phree(v->prop[i].value);
166 if (v->prop != NULL) phree(v->prop);
168 memset(v, 0, sizeof(struct vCard));
174 * Set a name/value pair in the card
176 void vcard_set_prop(struct vCard *v, char *name, char *value) {
179 if (v->magic != CTDL_VCARD_MAGIC) return; /* Self-check */
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);
192 /* Otherwise, append it */
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);
204 * Serialize a struct vcard into a standard text/x-vcard MIME type.
207 char *vcard_serialize(struct vCard *v)
213 if (v->magic != CTDL_VCARD_MAGIC) return NULL; /* self check */
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) {
219 strlen(v->prop[i].name) +
220 strlen(v->prop[i].value) + 4;
224 if (ser == NULL) return NULL;
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);
230 strcat(ser, v->prop[i].value);
233 strcat(ser, "end:vcard\r\n");