From 694a3ea878536e2deda1c0168e51837a31b81af7 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Fri, 10 Mar 2006 23:04:31 +0000 Subject: [PATCH] Began making changes to do better handling of character sets. --- webcit/groupdav_get.c | 8 ++- webcit/tools.c | 67 +++++++++++++++++++++ webcit/vcard.c | 133 +++++++++++++++++++++++++++++++++++++++--- webcit/vcard_edit.c | 2 +- webcit/webcit.h | 1 + 5 files changed, 202 insertions(+), 9 deletions(-) diff --git a/webcit/groupdav_get.c b/webcit/groupdav_get.c index e42a26778..d773fe29b 100644 --- a/webcit/groupdav_get.c +++ b/webcit/groupdav_get.c @@ -122,7 +122,13 @@ void groupdav_get(char *dav_pathname) { wprintf("%s\r\n", buf); } else if (!strncasecmp(buf, "Content-type: ", 14)) { - wprintf("%s\r\n", buf); + wprintf("%s", buf); + if (bmstrcasestr(buf, "charset=")) { + wprintf("%s\r\n", buf); + } + else { + wprintf("%s;charset=UTF-8\r\n", buf); + } found_content_type = 1; } else if ((strlen(buf) == 0) && (in_body == 0)) { diff --git a/webcit/tools.c b/webcit/tools.c index df27503ff..0a0718381 100644 --- a/webcit/tools.c +++ b/webcit/tools.c @@ -548,4 +548,71 @@ void CtdlMakeTempFileName(char *name, int len) { +/* + * \brief case-insensitive substring search + * + * This uses the Boyer-Moore search algorithm and is therefore quite fast. + * The code is roughly based on the strstr() replacement from 'tin' written + * by Urs Jannsen. + * + * \param text String to be searched + * \param pattern String to search for + */ +char *bmstrcasestr(char *text, char *pattern) { + + register unsigned char *p, *t; + register int i, j, *delta; + register size_t p1; + int deltaspace[256]; + size_t textlen; + size_t patlen; + + textlen = strlen (text); + patlen = strlen (pattern); + + /* algorithm fails if pattern is empty */ + if ((p1 = patlen) == 0) + return (text); + + /* code below fails (whenever i is unsigned) if pattern too long */ + if (p1 > textlen) + return (NULL); + + /* set up deltas */ + delta = deltaspace; + for (i = 0; i <= 255; i++) + delta[i] = p1; + for (p = (unsigned char *) pattern, i = p1; --i > 0;) + delta[tolower(*p++)] = i; + + /* + * From now on, we want patlen - 1. + * In the loop below, p points to the end of the pattern, + * t points to the end of the text to be tested against the + * pattern, and i counts the amount of text remaining, not + * including the part to be tested. + */ + p1--; + p = (unsigned char *) pattern + p1; + t = (unsigned char *) text + p1; + i = textlen - patlen; + while(1) { + if (tolower(p[0]) == tolower(t[0])) { + if (strncasecmp ((const char *)(p - p1), (const char *)(t - p1), p1) == 0) { + return ((char *)t - p1); + } + } + j = delta[tolower(t[0])]; + if (i < j) + break; + i -= j; + t += j; + } + return (NULL); +} + + + + + /*@}*/ diff --git a/webcit/vcard.c b/webcit/vcard.c index b71c55508..d236b00c5 100644 --- a/webcit/vcard.c +++ b/webcit/vcard.c @@ -1,6 +1,6 @@ /* * $Id$ - * Copyright (C) 1999-2005 by Art Cancro + * Copyright (C) 1999-2006 by Art Cancro * This code is freely redistributable under the terms of the GNU General * Public License. All other rights reserved. */ @@ -30,6 +30,48 @@ struct vCard *vcard_new() { return v; } +/** + * \brief Remove the "charset=" attribute from a vCard property name + * + * \param strbuf The property name string to be stripped + */ +void remove_charset_attribute(char *strbuf) +{ + int i, t; + char compare[256]; + + t = num_tokens(strbuf, ';'); + for (i=0; inumprops; v->prop = realloc(v->prop, (v->numprops * sizeof(struct vCardProp)) @@ -224,8 +267,9 @@ void vcard_set_prop(struct vCard *v, char *name, char *value, int append) { char *vcard_serialize(struct vCard *v) { char *ser; - int i; + int i, j; size_t len; + int is_utf8 = 0; if (v->magic != CTDL_VCARD_MAGIC) return NULL; /** self check */ @@ -234,7 +278,7 @@ char *vcard_serialize(struct vCard *v) if (v->numprops) for (i=0; i<(v->numprops); ++i) { len = len + strlen(v->prop[i].name) + - strlen(v->prop[i].value) + 4; + strlen(v->prop[i].value) + 16; } ser = malloc(len); @@ -242,10 +286,21 @@ char *vcard_serialize(struct vCard *v) safestrncpy(ser, "begin:vcard\r\n", len); 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"); + if (strcasecmp(v->prop[i].name, "end")) { + is_utf8 = 0; + for (j=0; iprop[i].value); ++i) { + if ( (v->prop[i].value[j] < 32) || (v->prop[i].value[j] > 126) ) { + is_utf8 = 1; + } + } + strcat(ser, v->prop[i].name); + if (is_utf8) { + strcat(ser, ";charset=UTF-8"); + } + strcat(ser, ":"); + strcat(ser, v->prop[i].value); + strcat(ser, "\r\n"); + } } strcat(ser, "end:vcard\r\n"); @@ -254,4 +309,68 @@ char *vcard_serialize(struct vCard *v) +/* + * \brief Convert FN (Friendly Name) into N (Name) + * + * \param vname Supplied friendly-name + * \param n Target buffer to store Name + * \param vname_size Size of buffer + */ +void vcard_fn_to_n(char *vname, char *n, size_t vname_size) { + char lastname[256]; + char firstname[256]; + char middlename[256]; + char honorific_prefixes[256]; + char honorific_suffixes[256]; + char buf[256]; + + safestrncpy(buf, n, sizeof buf); + + /* Try to intelligently convert the screen name to a + * fully expanded vCard name based on the number of + * words in the name + */ + safestrncpy(lastname, "", sizeof lastname); + safestrncpy(firstname, "", sizeof firstname); + safestrncpy(middlename, "", sizeof middlename); + safestrncpy(honorific_prefixes, "", sizeof honorific_prefixes); + safestrncpy(honorific_suffixes, "", sizeof honorific_suffixes); + + /* Honorific suffixes */ + if (num_tokens(buf, ',') > 1) { + extract_token(honorific_suffixes, buf, (num_tokens(buf, ' ') - 1), ',', + sizeof honorific_suffixes); + remove_token(buf, (num_tokens(buf, ',') - 1), ','); + } + + /* Find a last name */ + extract_token(lastname, buf, (num_tokens(buf, ' ') - 1), ' ', sizeof lastname); + remove_token(buf, (num_tokens(buf, ' ') - 1), ' '); + + /* Find honorific prefixes */ + if (num_tokens(buf, ' ') > 2) { + extract_token(honorific_prefixes, buf, 0, ' ', sizeof honorific_prefixes); + remove_token(buf, 0, ' '); + } + + /* Find a middle name */ + if (num_tokens(buf, ' ') > 1) { + extract_token(middlename, buf, (num_tokens(buf, ' ') - 1), ' ', sizeof middlename); + remove_token(buf, (num_tokens(buf, ' ') - 1), ' '); + } + + /* Anything left is probably the first name */ + safestrncpy(firstname, buf, sizeof firstname); + striplt(firstname); + + /* Compose the structured name */ + snprintf(vname, vname_size, "%s;%s;%s;%s;%s", lastname, firstname, middlename, + honorific_prefixes, honorific_suffixes); +} + + + + + + /*@}*/ diff --git a/webcit/vcard_edit.c b/webcit/vcard_edit.c index dae082e8e..2c78477e1 100644 --- a/webcit/vcard_edit.c +++ b/webcit/vcard_edit.c @@ -375,7 +375,7 @@ void submit_vcard(void) { return; } - serv_puts("Content-type: text/x-vcard"); + serv_puts("Content-type: text/x-vcard; charset=UTF-8"); serv_puts(""); serv_puts("begin:vcard"); serv_printf("n:%s;%s;%s;%s;%s", diff --git a/webcit/webcit.h b/webcit/webcit.h index 869979a68..92eae15fd 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -686,6 +686,7 @@ void begin_tab(int tabnum, int num_tabs); void end_tab(int tabnum, int num_tabs); void str_wiki_index(char *s); void display_wiki_page(void); +char *bmstrcasestr(char *text, char *pattern); #ifdef HAVE_ICONV iconv_t ctdl_iconv_open(const char *tocode, const char *fromcode); -- 2.39.2