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 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
135 if ( (!strcasecmp(v->prop[i].name, propname))
136 || ( (!strncasecmp(v->prop[i].name,
137 propname, strlen(propname)))
138 && (v->prop[i].name[strlen(propname)] == ';')
139 && (is_partial) ) ) {
140 return(v->prop[i].value);
153 void vcard_free(struct vCard *v) {
156 if (v->magic != CTDL_VCARD_MAGIC) return; /* Self-check */
158 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
159 phree(v->prop[i].name);
160 phree(v->prop[i].value);
163 if (v->prop != NULL) phree(v->prop);
165 memset(v, 0, sizeof(struct vCard));
171 * Set a name/value pair in the card
173 void vcard_set_prop(struct vCard *v, char *name, char *value) {
176 if (v->magic != CTDL_VCARD_MAGIC) return; /* Self-check */
178 /* If this key is already present, replace it */
179 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
180 if (!strcasecmp(v->prop[i].name, name)) {
181 phree(v->prop[i].name);
182 phree(v->prop[i].value);
183 v->prop[i].name = strdoop(name);
184 v->prop[i].value = strdoop(value);
189 /* Otherwise, append it */
191 v->prop = reallok(v->prop,
192 (v->numprops * sizeof(char *) * 2) );
193 v->prop[v->numprops-1].name = strdoop(name);
194 v->prop[v->numprops-1].value = strdoop(value);
201 * Serialize a struct vcard into a standard text/x-vcard MIME type.
204 char *vcard_serialize(struct vCard *v)
210 if (v->magic != CTDL_VCARD_MAGIC) return NULL; /* self check */
212 /* Figure out how big a buffer we need to allocate */
213 len = 64; /* for begin, end, and a little padding for safety */
214 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
216 strlen(v->prop[i].name) +
217 strlen(v->prop[i].value) + 4;
221 if (ser == NULL) return NULL;
223 strcpy(ser, "begin:vcard\r\n");
224 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
225 strcat(ser, v->prop[i].name);
227 strcat(ser, v->prop[i].value);
230 strcat(ser, "end:vcard\r\n");