5 * \defgroup VCardMain vCard data type implementation for the Citadel system.
7 * Copyright (C) 1999-2005 by Art Cancro
8 * This code is freely redistributable under the terms of the GNU General
9 * Public License. All other rights reserved.
13 #include "webserver.h"
17 * \brief Constructor (empty vCard)
18 * \return an empty vcard
20 struct vCard *vcard_new() {
23 v = (struct vCard *) malloc(sizeof(struct vCard));
24 if (v == NULL) return v;
26 v->magic = CTDL_VCARD_MAGIC;
35 * \brief Constructor (supply serialized vCard)
36 * \param vtext the text to parse into the new vcard
37 * \return the parsed VCard
39 struct vCard *vcard_load(char *vtext) {
43 char *namebuf, *valuebuf;
47 if (vtext == NULL) return vcard_new();
48 mycopy = strdup(vtext);
49 if (mycopy == NULL) return NULL;
52 * First, fix this big pile o' vCard to make it more parseable.
53 * To make it easier to parse, we convert CRLF to LF, and unfold any
54 * multi-line fields into single lines.
56 for (i=0; i<strlen(mycopy); ++i) {
57 if (!strncmp(&mycopy[i], "\r\n", 2)) {
58 strcpy(&mycopy[i], &mycopy[i+1]);
60 if ( (mycopy[i]=='\n') && (isspace(mycopy[i+1])) ) {
61 strcpy(&mycopy[i], &mycopy[i+1]);
66 if (v == NULL) return v;
69 while (strlen(ptr)>0) {
72 colonpos = pattern2(ptr, ":");
73 nlpos = pattern2(ptr, "\n");
75 if ((nlpos > colonpos) && (colonpos > 0)) {
76 namebuf = malloc(colonpos + 1);
77 valuebuf = malloc(nlpos - colonpos + 1);
78 strncpy(namebuf, ptr, colonpos);
79 namebuf[colonpos] = 0;
80 strncpy(valuebuf, &ptr[colonpos+1], nlpos-colonpos-1);
81 valuebuf[nlpos-colonpos-1] = 0;
83 if (!strcasecmp(namebuf, "end")) {
86 if ( (!strcasecmp(namebuf, "begin"))
87 && (!strcasecmp(valuebuf, "vcard"))
92 if ( (valid) && (strcasecmp(namebuf, "begin")) ) {
94 v->prop = realloc(v->prop,
95 (v->numprops * sizeof(struct vCardProp))
97 v->prop[v->numprops-1].name = namebuf;
98 v->prop[v->numprops-1].value = valuebuf;
107 while ( (*ptr != '\n') && (strlen(ptr)>0) ) {
110 if (*ptr == '\n') ++ptr;
119 * \brief Fetch the value of a particular key.
120 * If is_partial is set to 1, a partial match is ok (for example,
121 * a key of "tel;home" will satisfy a search for "tel").
122 * Set "instance" to a value higher than 0 to return subsequent instances
124 * Set "get_propname" to nonzero to fetch the property name instead of value.
125 * \param v vCard to get keyvalue from
126 * \param propname key to retrieve
127 * \param is_partial dunno???
128 * \param instance if >0 return a later token of the value
129 * \param get_propname if nonzero get the real property name???
130 * \return the requested value / token / propertyname
132 char *vcard_get_prop(struct vCard *v, char *propname,
133 int is_partial, int instance, int get_propname) {
135 int found_instance = 0;
137 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
138 if ( (!strcasecmp(v->prop[i].name, propname))
139 || (propname[0] == 0)
140 || ( (!strncasecmp(v->prop[i].name,
141 propname, strlen(propname)))
142 && (v->prop[i].name[strlen(propname)] == ';')
143 && (is_partial) ) ) {
144 if (instance == found_instance++) {
146 return(v->prop[i].name);
149 return(v->prop[i].value);
164 * \param v the vCard to purge from memory
166 void vcard_free(struct vCard *v) {
169 if (v->magic != CTDL_VCARD_MAGIC) return; /* Self-check */
171 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
172 free(v->prop[i].name);
173 free(v->prop[i].value);
176 if (v->prop != NULL) free(v->prop);
178 memset(v, 0, sizeof(struct vCard));
186 * \brief Set a name/value pair in the card
187 * \param v vCard to inspect
188 * \param name key to set
189 * \param value the value to assign to key
190 * \param append should we append the value to an existing one?
192 void vcard_set_prop(struct vCard *v, char *name, char *value, int append) {
195 if (v->magic != CTDL_VCARD_MAGIC) return; /** Self-check */
197 /** If this key is already present, replace it */
198 if (!append) if (v->numprops) for (i=0; i<(v->numprops); ++i) {
199 if (!strcasecmp(v->prop[i].name, name)) {
200 free(v->prop[i].name);
201 free(v->prop[i].value);
202 v->prop[i].name = strdup(name);
203 v->prop[i].value = strdup(value);
208 /** Otherwise, append it */
210 v->prop = realloc(v->prop,
211 (v->numprops * sizeof(struct vCardProp)) );
212 v->prop[v->numprops-1].name = strdup(name);
213 v->prop[v->numprops-1].value = strdup(value);
220 * \brief Serialize a struct vcard into a standard text/x-vcard MIME type.
221 * \param v vCard to serialize
222 * \return the serialized vCard
224 char *vcard_serialize(struct vCard *v)
230 if (v->magic != CTDL_VCARD_MAGIC) return NULL; /** self check */
232 /** Figure out how big a buffer we need to allocate */
233 len = 64; /** for begin, end, and a little padding for safety */
234 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
236 strlen(v->prop[i].name) +
237 strlen(v->prop[i].value) + 4;
241 if (ser == NULL) return NULL;
243 safestrncpy(ser, "begin:vcard\r\n", len);
244 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
245 strcat(ser, v->prop[i].name);
247 strcat(ser, v->prop[i].value);
250 strcat(ser, "end:vcard\r\n");