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")
140 * Set "instance" to a value higher than 0 to return subsequent instances
143 char *vcard_get_prop(struct vCard *v, char *propname,
144 int is_partial, int instance) {
146 int found_instance = 0;
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);
169 void vcard_free(struct vCard *v) {
172 if (v->magic != CTDL_VCARD_MAGIC) return; /* Self-check */
174 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
175 phree(v->prop[i].name);
176 phree(v->prop[i].value);
179 if (v->prop != NULL) phree(v->prop);
181 memset(v, 0, sizeof(struct vCard));
189 * Set a name/value pair in the card
191 void vcard_set_prop(struct vCard *v, char *name, char *value, int append) {
194 if (v->magic != CTDL_VCARD_MAGIC) return; /* Self-check */
196 /* If this key is already present, replace it */
197 if (!append) if (v->numprops) for (i=0; i<(v->numprops); ++i) {
198 if (!strcasecmp(v->prop[i].name, name)) {
199 phree(v->prop[i].name);
200 phree(v->prop[i].value);
201 v->prop[i].name = strdoop(name);
202 v->prop[i].value = strdoop(value);
207 /* Otherwise, append it */
209 v->prop = reallok(v->prop,
210 (v->numprops * sizeof(char *) * 2) );
211 v->prop[v->numprops-1].name = strdoop(name);
212 v->prop[v->numprops-1].value = strdoop(value);
219 * Serialize a struct vcard into a standard text/x-vcard MIME type.
222 char *vcard_serialize(struct vCard *v)
228 if (v->magic != CTDL_VCARD_MAGIC) return NULL; /* self check */
230 /* Figure out how big a buffer we need to allocate */
231 len = 64; /* for begin, end, and a little padding for safety */
232 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
234 strlen(v->prop[i].name) +
235 strlen(v->prop[i].value) + 4;
239 if (ser == NULL) return NULL;
241 strcpy(ser, "begin:vcard\r\n");
242 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
243 strcat(ser, v->prop[i].name);
245 strcat(ser, v->prop[i].value);
248 strcat(ser, "end:vcard\r\n");