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.
19 #if TIME_WITH_SYS_TIME
20 # include <sys/time.h>
24 # include <sys/time.h>
38 #include "sysdep_decls.h"
45 * Constructor (empty vCard)
47 struct vCard *vcard_new() {
50 v = (struct vCard *) mallok(sizeof(struct vCard));
51 if (v == NULL) return v;
53 v->magic = CTDL_VCARD_MAGIC;
62 * Constructor (supply serialized vCard)
64 struct vCard *vcard_load(char *vtext) {
68 char *namebuf, *valuebuf;
72 mycopy = strdoop(vtext);
73 if (mycopy == NULL) return NULL;
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.
79 for (i=0; i<strlen(mycopy); ++i) {
80 if (!strncmp(&mycopy[i], "\r\n", 2)) {
81 strcpy(&mycopy[i], &mycopy[i+1]);
83 if ( (mycopy[i]=='\n') && (isspace(mycopy[i+1])) ) {
84 strcpy(&mycopy[i], &mycopy[i+1]);
89 if (v == NULL) return v;
92 while (strlen(ptr)>0) {
95 colonpos = pattern2(ptr, ":");
96 nlpos = pattern2(ptr, "\n");
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;
106 if ( (!strcasecmp(namebuf, "end"))
107 && (!strcasecmp(valuebuf, "vcard")) ) valid = 0;
108 if ( (!strcasecmp(namebuf, "begin"))
109 && (!strcasecmp(valuebuf, "vcard")) ) valid = 1;
111 if ( (valid) && (strcasecmp(namebuf, "begin")) ) {
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;
125 while ( (*ptr != '\n') && (strlen(ptr)>0) ) {
128 if (*ptr == '\n') ++ptr;
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")
141 char *vcard_get_prop(struct vCard *v, char *propname, int is_partial) {
144 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
145 if ( (!strcasecmp(v->prop[i].name, propname))
146 || ( (!strncasecmp(v->prop[i].name,
147 propname, strlen(propname)))
148 && (v->prop[i].name[strlen(propname)] == ';')
149 && (is_partial) ) ) {
150 return(v->prop[i].value);
163 void vcard_free(struct vCard *v) {
166 if (v->magic != CTDL_VCARD_MAGIC) return; /* Self-check */
168 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
169 phree(v->prop[i].name);
170 phree(v->prop[i].value);
173 if (v->prop != NULL) phree(v->prop);
175 memset(v, 0, sizeof(struct vCard));
181 * Set a name/value pair in the card
183 void vcard_set_prop(struct vCard *v, char *name, char *value) {
186 if (v->magic != CTDL_VCARD_MAGIC) return; /* Self-check */
188 /* If this key is already present, replace it */
189 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
190 if (!strcasecmp(v->prop[i].name, name)) {
191 phree(v->prop[i].name);
192 phree(v->prop[i].value);
193 v->prop[i].name = strdoop(name);
194 v->prop[i].value = strdoop(value);
199 /* Otherwise, append it */
201 v->prop = reallok(v->prop,
202 (v->numprops * sizeof(char *) * 2) );
203 v->prop[v->numprops-1].name = strdoop(name);
204 v->prop[v->numprops-1].value = strdoop(value);
211 * Serialize a struct vcard into a standard text/x-vcard MIME type.
214 char *vcard_serialize(struct vCard *v)
220 if (v->magic != CTDL_VCARD_MAGIC) return NULL; /* self check */
222 /* Figure out how big a buffer we need to allocate */
223 len = 64; /* for begin, end, and a little padding for safety */
224 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
226 strlen(v->prop[i].name) +
227 strlen(v->prop[i].value) + 4;
231 if (ser == NULL) return NULL;
233 strcpy(ser, "begin:vcard\r\n");
234 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
235 strcat(ser, v->prop[i].name);
237 strcat(ser, v->prop[i].value);
240 strcat(ser, "end:vcard\r\n");