/*
- silcvcard.c
+ silcvcard.c
Author: Pekka Riikonen <priikone@silcnet.org>
#define VCARD_HEADER "BEGIN:VCARD\n"
#define VCARD_VERSION "VERSION:3.0\n"
-#define VCARD_FOOTER "END:VCARD"
+#define VCARD_FOOTER "END:VCARD\n"
/* Encode VCard */
"FN:", vcard->full_name, "\n",
"N:", vcard->family_name, ";", vcard->first_name, ";",
vcard->middle_names, ";", vcard->prefix, ";", vcard->suffix, "\n",
- SILC_STR_END);
+ SILC_STRFMT_END);
if (vcard->nickname)
silc_buffer_strformat(&buffer,
"NICKNAME:", vcard->nickname, "\n",
- SILC_STR_END);
+ SILC_STRFMT_END);
if (vcard->bday)
silc_buffer_strformat(&buffer,
"BDAY:", vcard->bday, "\n",
- SILC_STR_END);
+ SILC_STRFMT_END);
if (vcard->title)
silc_buffer_strformat(&buffer,
"TITLE:", vcard->title, "\n",
- SILC_STR_END);
+ SILC_STRFMT_END);
if (vcard->role)
silc_buffer_strformat(&buffer,
"ROLE:", vcard->role, "\n",
- SILC_STR_END);
+ SILC_STRFMT_END);
if (vcard->org_name)
silc_buffer_strformat(&buffer,
"ORG:", vcard->org_name, ";", vcard->org_unit, "\n",
- SILC_STR_END);
+ SILC_STRFMT_END);
if (vcard->categories)
silc_buffer_strformat(&buffer,
"CATEGORIES:", vcard->categories, "\n",
- SILC_STR_END);
- if (vcard->class)
+ SILC_STRFMT_END);
+ if (vcard->catclass)
silc_buffer_strformat(&buffer,
- "CLASS:", vcard->class, "\n",
- SILC_STR_END);
+ "CLASS:", vcard->catclass, "\n",
+ SILC_STRFMT_END);
if (vcard->url)
silc_buffer_strformat(&buffer,
"URL:", vcard->url, "\n",
- SILC_STR_END);
+ SILC_STRFMT_END);
if (vcard->label)
silc_buffer_strformat(&buffer,
"LABEL;", vcard->url, "\n",
- SILC_STR_END);
+ SILC_STRFMT_END);
for (i = 0; i < vcard->num_addrs; i++) {
silc_buffer_strformat(&buffer,
"ADR;TYPE=",
vcard->addrs[i].state, ";",
vcard->addrs[i].code, ";",
vcard->addrs[i].country, "\n",
- SILC_STR_END);
+ SILC_STRFMT_END);
}
for (i = 0; i < vcard->num_tels; i++) {
silc_buffer_strformat(&buffer,
"TEL;TYPE=",
vcard->tels[i].type, ":",
- vcard->tels[i].tel, "\n",
- SILC_STR_END);
+ vcard->tels[i].telnum, "\n",
+ SILC_STRFMT_END);
}
for (i = 0; i < vcard->num_emails; i++) {
silc_buffer_strformat(&buffer,
"EMAIL;TYPE=",
vcard->emails[i].type, ":",
vcard->emails[i].address, "\n",
- SILC_STR_END);
+ SILC_STRFMT_END);
}
if (vcard->note)
silc_buffer_strformat(&buffer,
"NOTE:", vcard->note, "\n",
- SILC_STR_END);
+ SILC_STRFMT_END);
if (vcard->rev)
silc_buffer_strformat(&buffer,
"REV:", vcard->rev, "\n",
- SILC_STR_END);
+ SILC_STRFMT_END);
- silc_buffer_strformat(&buffer, VCARD_FOOTER, SILC_STR_END);
+ silc_buffer_strformat(&buffer, VCARD_FOOTER, SILC_STRFMT_END);
if (vcard_len)
*vcard_len = buffer.truelen;
continue; \
}
-/* Take on TYPE= token and prepare for next token */
-#define VCARD_TYPETOKEN(x) \
- if (!(x)) { \
- int tmpi; \
- (x) = silc_memdup(val + off + 5, i - off - 5 - 1); \
- tmpi = off + 5 + strlen((x)) + 1; \
- off = i; \
- i = tmpi; \
+/* Take on TYPE= token and prepare for next token, accept the
+ type also without TYPE= as it is possible */
+#define VCARD_TYPETOKEN(x) \
+ if (!(x)) { \
+ int tmpi = 0; \
+ if (!strncasecmp(val + off, "TYPE=", 5)) \
+ tmpi = 5; \
+ (x) = silc_memdup(val + off + tmpi, i - off - tmpi - 1); \
+ tmpi = off + tmpi + strlen((x)) + 1; \
+ off = i; \
+ i = tmpi; \
}
/* Take last token */
(x) = silc_memdup(val + off, len - off); \
} \
+/* Get one (single) field */
+#define VCARD_FIELD(val, c, x) \
+do { \
+ if (!strncasecmp(val, (c), strlen((c)))) { \
+ int tmpl = strlen((c)); \
+ if ((x)) \
+ break; \
+ if (len - tmpl > 0) \
+ (x) = silc_memdup(val + tmpl, len - tmpl); \
+ goto next; \
+ } \
+} while(0)
+
/* Decode VCard */
bool silc_vcard_decode(const unsigned char *data, SilcUInt32 data_len,
unsigned char *val;
bool has_begin = FALSE, has_end = FALSE;
int len, i, off = 0;
-
+
val = (unsigned char *)data;
while (val) {
- if (!strchr(val, '\n'))
- break;
- len = strchr(val, '\n') - (char *)val;
- if (len > data_len - (val - data))
+ len = 0;
+ for (i = (val - data); i < data_len; i++) {
+ if (data[i] == '\0' || data[i] == '\n') {
+ len = i - (val - data);
+ break;
+ }
+ }
+ if (!len || len > data_len - (val - data))
break;
+ /* Check for mandatory header and footer */
if (!strncasecmp(val, VCARD_HEADER, strlen(VCARD_HEADER))) {
has_begin = TRUE;
- } else if (!strncasecmp(val, "FN:", 3)) {
- if (vcard->full_name)
- break;
- if (len - 3)
- vcard->full_name = silc_memdup(val + 3, len - 3);
- } else if (!strncasecmp(val, "N:", 2)) {
+ goto next;
+ }
+ if (!strncasecmp(val, VCARD_FOOTER, strlen(VCARD_FOOTER))) {
+ has_end = TRUE;
+ goto next;
+ }
+
+ /* Get single fields */
+ VCARD_FIELD(val, "FN:", vcard->full_name);
+ VCARD_FIELD(val, "NICKNAME:", vcard->nickname);
+ VCARD_FIELD(val, "BDAY:", vcard->bday);
+ VCARD_FIELD(val, "TITLE:", vcard->title);
+ VCARD_FIELD(val, "ROLE:", vcard->role);
+ VCARD_FIELD(val, "CATEGORIES:", vcard->categories);
+ VCARD_FIELD(val, "CLASS:", vcard->catclass);
+ VCARD_FIELD(val, "URL:", vcard->url);
+ VCARD_FIELD(val, "LABEL;", vcard->label);
+ VCARD_FIELD(val, "NOTE:", vcard->note);
+ VCARD_FIELD(val, "REV:", vcard->rev);
+
+ /* Get multi-column fields */
+
+ if (!strncasecmp(val, "N:", 2)) {
if (vcard->family_name)
break;
if (len - 2) {
VCARD_TOKEN(vcard->middle_names);
VCARD_TOKEN(vcard->prefix);
}
- VCARD_LASTTOKEN(vcard->suffix);
+ if (!vcard->family_name && !vcard->first_name) {
+ VCARD_LASTTOKEN(vcard->family_name);
+ off += (len - off);
+ }
+ if (!vcard->first_name) {
+ VCARD_LASTTOKEN(vcard->first_name);
+ } else {
+ VCARD_LASTTOKEN(vcard->suffix);
+ }
}
- } else if (!strncasecmp(val, "NICKNAME:", 9)) {
- if (vcard->nickname)
- continue;
- if (len - 9)
- vcard->nickname = silc_memdup(val + 9, len - 9);
- } else if (!strncasecmp(val, "BDAY:", 5)) {
- if (vcard->bday)
- continue;
- if (len - 5)
- vcard->bday = silc_memdup(val + 5, len - 5);
- } else if (!strncasecmp(val, "TITLE:", 6)) {
- if (vcard->title)
- continue;
- if (len - 6)
- vcard->title = silc_memdup(val + 6, len - 6);
- } else if (!strncasecmp(val, "ROLE:", 5)) {
- if (vcard->role)
- continue;
- if (len - 5)
- vcard->role = silc_memdup(val + 5, len - 5);
- } else if (!strncasecmp(val, "ORG:", 4)) {
+ goto next;
+ }
+
+ if (!strncasecmp(val, "ORG:", 4)) {
if (vcard->org_name)
continue;
if (len - 4) {
VCARD_LASTTOKEN(vcard->org_unit);
}
}
- } else if (!strncasecmp(val, "CATEGORIES:", 11)) {
- if (vcard->categories)
- continue;
- if (len - 11)
- vcard->categories = silc_memdup(val + 11, len - 11);
- } else if (!strncasecmp(val, "CLASS:", 6)) {
- if (vcard->class)
- continue;
- if (len - 6)
- vcard->class = silc_memdup(val + 6, len - 6);
- } else if (!strncasecmp(val, "URL:", 4)) {
- if (vcard->url)
- continue;
- if (len - 4)
- vcard->url = silc_memdup(val + 4, len - 4);
- } else if (!strncasecmp(val, "LABEL;", 6)) {
- if (vcard->label)
- continue;
- if (len - 6)
- vcard->label = silc_memdup(val + 6, len - 6);
- } else if (!strncasecmp(val, "ADR;", 4)) {
+ goto next;
+ }
+
+ if (!strncasecmp(val, "ADR;", 4)) {
vcard->addrs = silc_realloc(vcard->addrs, sizeof(*vcard->addrs) *
(vcard->num_addrs + 1));
+ memset(&vcard->addrs[vcard->num_addrs], 0, sizeof(*vcard->addrs));
if (len - 4) {
off = 4;
for (i = off; i < len; i++)
VCARD_LASTTOKEN(vcard->addrs[vcard->num_addrs].country);
}
vcard->num_addrs++;
- } else if (!strncasecmp(val, "TEL;", 4)) {
+ goto next;
+ }
+
+ if (!strncasecmp(val, "TEL;", 4)) {
vcard->tels = silc_realloc(vcard->tels, sizeof(*vcard->tels) *
(vcard->num_tels + 1));
+ memset(&vcard->tels[vcard->num_tels], 0, sizeof(*vcard->tels));
if (len - 4) {
off = 4;
for (i = off; i < len; i++)
VCARD_TYPETOKEN(vcard->tels[vcard->num_tels].type);
break;
}
- VCARD_LASTTOKEN(vcard->tels[vcard->num_tels].tel);
+ VCARD_LASTTOKEN(vcard->tels[vcard->num_tels].telnum);
}
vcard->num_tels++;
- } else if (!strncasecmp(val, "EMAIL;", 6)) {
+ goto next;
+ }
+
+ if (!strncasecmp(val, "EMAIL;", 6)) {
vcard->emails = silc_realloc(vcard->emails, sizeof(*vcard->emails) *
(vcard->num_emails + 1));
+ memset(&vcard->emails[vcard->num_emails], 0, sizeof(*vcard->emails));
if (len - 6) {
off = 6;
for (i = off; i < len; i++)
VCARD_LASTTOKEN(vcard->emails[vcard->num_emails].address);
}
vcard->num_emails++;
- } else if (!strncasecmp(val, "NOTE:", 5)) {
- if (vcard->note)
- continue;
- if (len - 5)
- vcard->note = silc_memdup(val + 5, len - 5);
- } else if (!strncasecmp(val, "REV:", 4)) {
- if (vcard->rev)
- continue;
- if (len - 4)
- vcard->rev = silc_memdup(val + 4, len - 4);
- } else if (!strncasecmp(val, VCARD_FOOTER, strlen(VCARD_FOOTER))) {
- has_end = TRUE;
- break;
+ goto next;
}
+ next:
val = strchr(val, '\n');
- if (!val || !(*val))
+ if (!val)
break;
val++;
if (!val || !(*val))
break;
}
- if (!has_begin || !has_end) {
+ if (!has_begin || !has_end || !vcard->full_name) {
silc_vcard_free(vcard);
return FALSE;
}
silc_free(vcard->org_name);
silc_free(vcard->org_unit);
silc_free(vcard->categories);
- silc_free(vcard->class);
+ silc_free(vcard->catclass);
silc_free(vcard->url);
silc_free(vcard->label);
for (i = 0; i < vcard->num_addrs; i++) {
silc_free(vcard->addrs);
for (i = 0; i < vcard->num_tels; i++) {
silc_free(vcard->tels[i].type);
- silc_free(vcard->tels[i].tel);
+ silc_free(vcard->tels[i].telnum);
}
silc_free(vcard->tels);
for (i = 0; i < vcard->num_emails; i++) {
silc_free(vcard->emails);
silc_free(vcard->note);
silc_free(vcard->rev);
+ if (!vcard->dynamic)
+ memset(vcard, 0, sizeof(*vcard));
if (vcard->dynamic) {
- memset(vcard, 'F', sizeof(*vcard));
+ memset(vcard, 0, sizeof(*vcard));
silc_free(vcard);
}
}
vcard->org_unit ? vcard->org_unit : "");
if (vcard->categories)
fprintf(stream, "CATEGORIES:%s\n", vcard->categories);
- if (vcard->class)
- fprintf(stream, "CLASS:%s\n", vcard->class);
+ if (vcard->catclass)
+ fprintf(stream, "CLASS:%s\n", vcard->catclass);
if (vcard->url)
fprintf(stream, "URL:%s\n", vcard->url);
if (vcard->label)
for (i = 0; i < vcard->num_tels; i++) {
fprintf(stream, "TEL;TYPE=%s:%s\n",
vcard->tels[i].type,
- vcard->tels[i].tel ? vcard->tels[i].tel : "");
+ vcard->tels[i].telnum ? vcard->tels[i].telnum : "");
}
for (i = 0; i < vcard->num_emails; i++) {
fprintf(stream, "EMAIL;TYPE=%s:%s\n",