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.
27 #include "sysdep_decls.h"
34 * Constructor (empty vCard)
36 struct vCard *vcard_new() {
39 v = (struct vCard *) mallok(sizeof(struct vCard));
40 if (v == NULL) return v;
42 v->magic = CTDL_VCARD_MAGIC;
51 * Constructor (supply serialized vCard)
53 struct vCard *vcard_load(char *vtext) {
57 char *namebuf, *valuebuf;
61 mycopy = strdoop(vtext);
62 if (mycopy == NULL) return NULL;
64 /* First, fix this big pile o' vCard to make it more parseable.
65 * To make it easier to parse, we convert CRLF to LF, and unfold any
66 * multi-line fields into single lines.
68 for (i=0; i<strlen(mycopy); ++i) {
69 if (!strncmp(&mycopy[i], "\r\n", 2)) {
70 strcpy(&mycopy[i], &mycopy[i+1]);
72 if ( (mycopy[i]=='\n') && (isspace(mycopy[i+1])) ) {
73 strcpy(&mycopy[i], &mycopy[i+1]);
78 if (v == NULL) return v;
81 while (strlen(ptr)>0) {
84 colonpos = pattern2(ptr, ":");
85 nlpos = pattern2(ptr, "\n");
87 if (nlpos > colonpos > 0) {
88 namebuf = mallok(colonpos + 1);
89 valuebuf = mallok(nlpos - colonpos + 1);
90 strncpy(namebuf, ptr, colonpos);
91 namebuf[colonpos] = 0;
92 strncpy(valuebuf, &ptr[colonpos+1], nlpos-colonpos-1);
93 valuebuf[nlpos-colonpos-1] = 0;
95 if ( (!strcasecmp(namebuf, "end"))
96 && (!strcasecmp(valuebuf, "vcard")) ) valid = 0;
97 if ( (!strcasecmp(namebuf, "begin"))
98 && (!strcasecmp(valuebuf, "vcard")) ) valid = 1;
100 if ( (valid) && (strcasecmp(namebuf, "begin")) ) {
102 v->prop = reallok(v->prop,
103 (v->numprops * sizeof(char *) * 2) );
104 v->prop[v->numprops-1].name = namebuf;
105 v->prop[v->numprops-1].value = valuebuf;
114 while ( (*ptr != '\n') && (strlen(ptr)>0) ) {
117 if (*ptr == '\n') ++ptr;
126 * Fetch the value of a particular key
127 * If is_partial is set to 1, a partial match is ok (for example,
128 * a key of "tel;home" will satisfy a search for "tel")
130 char *vcard_get_prop(struct vCard *v, char *propname, int is_partial) {
133 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
134 if ( (!strcasecmp(v->prop[i].name, propname))
135 || ( (!strncasecmp(v->prop[i].name,
136 propname, strlen(propname)))
137 && (v->prop[i].name[strlen(propname)] == ';')
138 && (is_partial) ) ) {
139 return(v->prop[i].value);
152 void vcard_free(struct vCard *v) {
155 if (v->magic != CTDL_VCARD_MAGIC) return; /* Self-check */
157 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
158 phree(v->prop[i].name);
159 phree(v->prop[i].value);
162 if (v->prop != NULL) phree(v->prop);
164 memset(v, 0, sizeof(struct vCard));
170 * Set a name/value pair in the card
172 void vcard_set_prop(struct vCard *v, char *name, char *value) {
175 if (v->magic != CTDL_VCARD_MAGIC) return; /* Self-check */
177 /* If this key is already present, replace it */
178 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
179 if (!strcasecmp(v->prop[i].name, name)) {
180 phree(v->prop[i].name);
181 phree(v->prop[i].value);
182 v->prop[i].name = strdoop(name);
183 v->prop[i].value = strdoop(value);
188 /* Otherwise, append it */
190 v->prop = reallok(v->prop,
191 (v->numprops * sizeof(char *) * 2) );
192 v->prop[v->numprops-1].name = strdoop(name);
193 v->prop[v->numprops-1].value = strdoop(value);
200 * Serialize a struct vcard into a standard text/x-vcard MIME type.
203 char *vcard_serialize(struct vCard *v)
209 if (v->magic != CTDL_VCARD_MAGIC) return NULL; /* self check */
211 /* Figure out how big a buffer we need to allocate */
212 len = 64; /* for begin, end, and a little padding for safety */
213 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
215 strlen(v->prop[i].name) +
216 strlen(v->prop[i].value) + 4;
220 if (ser == NULL) return NULL;
222 strcpy(ser, "begin:vcard\r\n");
223 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
224 strcat(ser, v->prop[i].name);
226 strcat(ser, v->prop[i].value);
229 strcat(ser, "end:vcard\r\n");