From d374b9a320269d52166e1ab5f7b1a4888f49b965 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Wed, 13 Feb 2002 22:47:51 +0000 Subject: [PATCH] * Added some rudimentary support for displaying vCards as card-looking things --- webcit/ChangeLog | 4 +- webcit/Makefile.in | 4 +- webcit/messages.c | 74 +++++++++++++- webcit/tools.c | 12 +++ webcit/vcard.c | 245 +++++++++++++++++++++++++++++++++++++++++++++ webcit/vcard.h | 33 ++++++ webcit/webcit.h | 1 + 7 files changed, 368 insertions(+), 5 deletions(-) create mode 100644 webcit/vcard.c create mode 100644 webcit/vcard.h diff --git a/webcit/ChangeLog b/webcit/ChangeLog index 5a780b3da..53ef7e157 100644 --- a/webcit/ChangeLog +++ b/webcit/ChangeLog @@ -1,4 +1,7 @@ $Log$ +Revision 323.3 2002/02/13 22:47:51 ajc +* Added some rudimentary support for displaying vCards as card-looking things + Revision 323.2 2002/02/13 15:04:25 ajc * Began some hacks for vCard processing @@ -716,4 +719,3 @@ Sun Dec 6 19:50:55 EST 1998 Art Cancro 1998-12-03 Nathan Bryant * webserver.c: warning fix - diff --git a/webcit/Makefile.in b/webcit/Makefile.in index 5c5195f95..277dd5590 100644 --- a/webcit/Makefile.in +++ b/webcit/Makefile.in @@ -25,12 +25,12 @@ distclean: clean webserver: webserver.o context_loop.o tools.o \ cookie_conversion.o locate_host.o \ webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o \ - roomops.o messages.o userlist.o paging.o sysmsgs.o \ + roomops.o messages.o userlist.o paging.o sysmsgs.o vcard.o \ mime_parser.o graphics.o netconf.o siteconfig.o subst.o $(LIBOBJS) $(CC) webserver.o context_loop.o tools.o cookie_conversion.o \ webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o \ roomops.o messages.o userlist.o paging.o sysmsgs.o \ - locate_host.o siteconfig.o subst.o \ + locate_host.o siteconfig.o subst.o vcard.o \ mime_parser.o graphics.o netconf.o \ $(LIBOBJS) $(LIBS) -o webserver strip webserver diff --git a/webcit/messages.c b/webcit/messages.c index da0e2b6be..09b031c39 100644 --- a/webcit/messages.c +++ b/webcit/messages.c @@ -24,6 +24,7 @@ #include #include #include "webcit.h" +#include "vcard.h" /* @@ -81,6 +82,76 @@ char buf[]; } + + +/* + * Experimental output type of thing + */ +void display_vcard(char *vcard_source) { + int i, j; + struct vCard *v; + char buf[SIZ]; + + v = vcard_load(vcard_source); + if (v == NULL) return; + + wprintf(""); + if (v->numprops) for (i=0; i<(v->numprops); ++i) { + if (!strcasecmp(v->prop[i].name, "n")) { + wprintf("\n"); + } + else if (!strcasecmp(v->prop[i].name, "email;internet")) { + wprintf("" + "\n"); + } + else if (!strcasecmp(v->prop[i].name, "adr")) { + wprintf("\n"); + } + else if (!strncasecmp(v->prop[i].name, "tel;", 4)) { + wprintf("\n"); + } + else { + wprintf("\n"); + } + } + + wprintf("
"); + escputs(v->prop[i].value); + wprintf("
Internet e-mail:prop[i].value); + wprintf("\">"); + escputs(v->prop[i].value); + wprintf("
Address:"); + for (j=0; jprop[i].value, ';'); ++j) { + extract_token(buf, v->prop[i].value, j, ';'); + if (strlen(buf) > 0) { + escputs(buf); + wprintf("
"); + } + } + wprintf("
%s telephone:", + &v->prop[i].name[4]); + for (j=0; jprop[i].value, ';'); ++j) { + extract_token(buf, v->prop[i].value, j, ';'); + if (strlen(buf) > 0) { + escputs(buf); + wprintf("
"); + } + } + wprintf("
"); + escputs(v->prop[i].name); + wprintf(""); + escputs(v->prop[i].value); + wprintf("
\n"); + + vcard_free(v); +} + + + + + + void read_message(long msgnum, int is_summary) { char buf[SIZ]; char mime_partnum[SIZ]; @@ -320,8 +391,7 @@ void read_message(long msgnum, int is_summary) { if (strlen(vcard_partnum) > 0) { vcard_source = load_mimepart(msgnum, vcard_partnum); if (vcard_source != NULL) { - wprintf("vcard object length = %d
\n", - strlen(vcard_source)); + display_vcard(vcard_source); free(vcard_source); } } diff --git a/webcit/tools.c b/webcit/tools.c index 8bcccaed6..adc840618 100644 --- a/webcit/tools.c +++ b/webcit/tools.c @@ -262,4 +262,16 @@ char *memreadline(char *start, char *buf, int maxlen) +/* + * pattern2() - searches for patn within search string, returns pos + */ +int pattern2(char *search, char *patn) +{ + int a; + for (a=0; a +#include +#include +#include +#include + +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#include +#include +#include +#include +#include + +#include "webcit.h" +#include "vcard.h" + +/* + * Constructor (empty vCard) + */ +struct vCard *vcard_new() { + struct vCard *v; + + v = (struct vCard *) malloc(sizeof(struct vCard)); + if (v == NULL) return v; + + v->magic = CTDL_VCARD_MAGIC; + v->numprops = 0; + v->prop = NULL; + + return v; +} + + +/* + * Constructor (supply serialized vCard) + */ +struct vCard *vcard_load(char *vtext) { + struct vCard *v; + int valid = 0; + char *mycopy, *ptr; + char *namebuf, *valuebuf; + int i; + int colonpos, nlpos; + + mycopy = strdup(vtext); + if (mycopy == NULL) return NULL; + + /* First, fix this big pile o' vCard to make it more parseable. + * To make it easier to parse, we convert CRLF to LF, and unfold any + * multi-line fields into single lines. + */ + for (i=0; i0) { + colonpos = (-1); + nlpos = (-1); + colonpos = pattern2(ptr, ":"); + nlpos = pattern2(ptr, "\n"); + + if (nlpos > colonpos > 0) { + namebuf = malloc(colonpos + 1); + valuebuf = malloc(nlpos - colonpos + 1); + strncpy(namebuf, ptr, colonpos); + namebuf[colonpos] = 0; + strncpy(valuebuf, &ptr[colonpos+1], nlpos-colonpos-1); + valuebuf[nlpos-colonpos-1] = 0; + + if ( (!strcasecmp(namebuf, "end")) + && (!strcasecmp(valuebuf, "vcard")) ) valid = 0; + if ( (!strcasecmp(namebuf, "begin")) + && (!strcasecmp(valuebuf, "vcard")) ) valid = 1; + + if ( (valid) && (strcasecmp(namebuf, "begin")) ) { + ++v->numprops; + v->prop = realloc(v->prop, + (v->numprops * sizeof(char *) * 2) ); + v->prop[v->numprops-1].name = namebuf; + v->prop[v->numprops-1].value = valuebuf; + } + else { + free(namebuf); + free(valuebuf); + } + + } + + while ( (*ptr != '\n') && (strlen(ptr)>0) ) { + ++ptr; + } + if (*ptr == '\n') ++ptr; + } + + free(mycopy); + return v; +} + + +/* + * Fetch the value of a particular key + * If is_partial is set to 1, a partial match is ok (for example, + * a key of "tel;home" will satisfy a search for "tel") + * Set "instance" to a value higher than 0 to return subsequent instances + * of the same key + */ +char *vcard_get_prop(struct vCard *v, char *propname, + int is_partial, int instance) { + int i; + int found_instance = 0; + + if (v->numprops) for (i=0; i<(v->numprops); ++i) { + if ( (!strcasecmp(v->prop[i].name, propname)) + || ( (!strncasecmp(v->prop[i].name, + propname, strlen(propname))) + && (v->prop[i].name[strlen(propname)] == ';') + && (is_partial) ) ) { + if (instance == found_instance++) { + return(v->prop[i].value); + } + } + } + + return NULL; +} + + + + +/* + * Destructor + */ +void vcard_free(struct vCard *v) { + int i; + + if (v->magic != CTDL_VCARD_MAGIC) return; /* Self-check */ + + if (v->numprops) for (i=0; i<(v->numprops); ++i) { + free(v->prop[i].name); + free(v->prop[i].value); + } + + if (v->prop != NULL) free(v->prop); + + memset(v, 0, sizeof(struct vCard)); + free(v); +} + + + + +/* + * Set a name/value pair in the card + */ +void vcard_set_prop(struct vCard *v, char *name, char *value, int append) { + int i; + + if (v->magic != CTDL_VCARD_MAGIC) return; /* Self-check */ + + /* If this key is already present, replace it */ + if (!append) if (v->numprops) for (i=0; i<(v->numprops); ++i) { + if (!strcasecmp(v->prop[i].name, name)) { + free(v->prop[i].name); + free(v->prop[i].value); + v->prop[i].name = strdup(name); + v->prop[i].value = strdup(value); + return; + } + } + + /* Otherwise, append it */ + ++v->numprops; + v->prop = realloc(v->prop, + (v->numprops * sizeof(char *) * 2) ); + v->prop[v->numprops-1].name = strdup(name); + v->prop[v->numprops-1].value = strdup(value); +} + + + + +/* + * Serialize a struct vcard into a standard text/x-vcard MIME type. + * + */ +char *vcard_serialize(struct vCard *v) +{ + char *ser; + int i; + size_t len; + + if (v->magic != CTDL_VCARD_MAGIC) return NULL; /* self check */ + + /* Figure out how big a buffer we need to allocate */ + len = 64; /* for begin, end, and a little padding for safety */ + if (v->numprops) for (i=0; i<(v->numprops); ++i) { + len = len + + strlen(v->prop[i].name) + + strlen(v->prop[i].value) + 4; + } + + ser = malloc(len); + if (ser == NULL) return NULL; + + strcpy(ser, "begin:vcard\r\n"); + if (v->numprops) for (i=0; i<(v->numprops); ++i) { + strcat(ser, v->prop[i].name); + strcat(ser, ":"); + strcat(ser, v->prop[i].value); + strcat(ser, "\r\n"); + } + strcat(ser, "end:vcard\r\n"); + + return ser; +} diff --git a/webcit/vcard.h b/webcit/vcard.h new file mode 100644 index 000000000..743efa990 --- /dev/null +++ b/webcit/vcard.h @@ -0,0 +1,33 @@ +/* + * $Id$ + * + * vCard implementation for Citadel/UX + * + * Copyright (C) 1999 by Art Cancro + * This code is freely redistributable under the terms of the GNU General + * Public License. All other rights reserved. + */ + + +#define CTDL_VCARD_MAGIC 0xa1f9 + +/* + * This data structure represents a vCard object currently in memory. + */ +struct vCard { + int magic; + int numprops; + struct vCardProp { + char *name; + char *value; + } *prop; +}; + + +struct vCard *vcard_new(void); +struct vCard *vcard_load(char *); +void vcard_free(struct vCard *); +void vcard_set_prop(struct vCard *v, char *name, char *value, int append); +char *vcard_get_prop(struct vCard *v, char *propname, int is_partial, + int instance); +char *vcard_serialize(struct vCard *); diff --git a/webcit/webcit.h b/webcit/webcit.h index ab70de2f0..e54372d61 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -286,3 +286,4 @@ void extract_token(char *dest, char *source, int parmnum, char separator); void remove_token(char *source, int parmnum, char separator); int decode_base64(char *dest, char *source); char *load_mimepart(long msgnum, char *partnum); +int pattern2(char *search, char *patn); -- 2.39.2