Re: [Evolution-hackers] vcard 2.1 implementation
- From: Armin Bauer <azrael desscon com>
- To: JP Rosevear <jpr novell com>
- Cc: Siva <snallagatla novell com>, evolution-hackers lists ximian com
- Subject: Re: [Evolution-hackers] vcard 2.1 implementation
- Date: Wed, 26 Jan 2005 11:14:06 +0100
On Wed, 2005-01-26 at 07:10, JP Rosevear wrote:
> On Tue, 2005-01-25 at 12:28 +0100, Armin Bauer wrote:
> > Hi,
> >
> > i was just wondering if anyone is working on the task to implement vcard
> > 2.1 support in e-vcard.c? If not i will work on this.
>
> I don't know of anyone currently working on this, so feel free to take a
> crack at this.
>
Here is the patch. It adds the capability to generate 2.1 cards, encode
and decode quoted-printable and fixes a bug. it still has some quirks
(for example len in quoted_decode and encode is ignored). i will keep
you updated when i improve this.
Attached is also a vcard that made the vcard parser run in a loop. thats
what the lp++; is for.
> > Did you think about making a vcard parsing library out of this? There is
> > currently no usable vcard lib.
>
> Standalone you mean? I don't think we'd really thought about that much.
>
> -JP
--- evolution-data-server-1.1.3/addressbook/libebook/e-vcard.c 2004-08-05 20:25:21.000000000 +0200
+++ e-vcard.c 2005-01-26 11:03:22.000000000 +0100
@@ -22,6 +22,7 @@
#include <glib.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "e-vcard.h"
@@ -63,6 +64,9 @@
size_t _evc_base64_decode_simple (char *data, size_t len);
char *_evc_base64_encode_simple (const char *data, size_t len);
+size_t _evc_quoted_decode_simple (char *data, size_t len);
+char *_evc_quoted_encode_simple (const unsigned char *string, int len);
+
static void
e_vcard_dispose (GObject *object)
{
@@ -196,7 +200,7 @@
char *lp;
lp = *p;
-
+
while (*lp != '\r' && *lp != '\0') {
gboolean s_matches = FALSE;
char *ls;
@@ -209,6 +213,7 @@
if (s_matches)
break;
+ lp++;
}
*p = lp;
@@ -303,12 +308,13 @@
EVCardAttributeParam *param = NULL;
gboolean in_quote = FALSE;
str = g_string_new ("");
+
while (*lp != '\0') {
if (*lp == '"') {
in_quote = !in_quote;
lp = g_utf8_next_char (lp);
}
- else if (in_quote || g_unichar_isalnum (g_utf8_get_char (lp)) || *lp == '-' || *lp == '_') {
+ else if (in_quote || g_unichar_isalnum (g_utf8_get_char (lp)) || *lp == '-' || *lp == '_' || *lp == '/') {
str = g_string_append_unichar (str, g_utf8_get_char (lp));
lp = g_utf8_next_char (lp);
}
@@ -423,7 +429,7 @@
break;
}
else {
- g_warning ("invalid character found in parameter spec");
+ g_warning ("invalid character found in parameter spec: %c", lp[0]);
g_string_assign (str, "");
skip_until (&lp, ":;");
}
@@ -482,11 +488,11 @@
str = g_string_new ("");
}
}
- else if (g_unichar_isalnum (g_utf8_get_char (lp)) || *lp == '-' || *lp == '_') {
+ else if (g_unichar_isalnum (g_utf8_get_char (lp)) || *lp == '-' || *lp == '_' || *lp == '/') {
str = g_string_append_unichar (str, g_utf8_get_char (lp));
}
else {
- g_warning ("invalid character found in attribute group/name");
+ g_warning ("invalid character found in attribute group/name: %c", lp[0]);
g_string_free (str, TRUE);
*p = lp;
skip_to_next_line(p);
@@ -677,7 +683,6 @@
e_vcard_new_from_string (const char *str)
{
EVCard *evc;
-
g_return_val_if_fail (str != NULL, NULL);
evc = g_object_new (E_TYPE_VCARD, NULL);
@@ -690,7 +695,122 @@
static char*
e_vcard_to_string_vcard_21 (EVCard *evc)
{
- g_warning ("need to implement e_vcard_to_string_vcard_21");
+ GList *l;
+ GList *v;
+
+ GString *str = g_string_new ("");
+
+ str = g_string_append (str, "BEGIN:VCARD" CRLF);
+
+ /* we hardcode the version (since we're outputting to a
+ specific version) and ignore any version attributes the
+ vcard might contain */
+ str = g_string_append (str, "VERSION:2.1" CRLF);
+
+ for (l = evc->priv->attributes; l; l = l->next) {
+ GList *p;
+ EVCardAttribute *attr = l->data;
+ GString *attr_str;
+ int l;
+
+ if (!g_ascii_strcasecmp (attr->name, "VERSION"))
+ continue;
+
+ attr_str = g_string_new ("");
+
+ /* From rfc2425, 5.8.2
+ *
+ * contentline = [group "."] name *(";" param) ":" value CRLF
+ */
+
+ if (attr->group) {
+ attr_str = g_string_append (attr_str, attr->group);
+ attr_str = g_string_append_c (attr_str, '.');
+ }
+ attr_str = g_string_append (attr_str, attr->name);
+
+ /* handle the parameters */
+ for (p = attr->params; p; p = p->next) {
+ EVCardAttributeParam *param = p->data;
+ /* 5.8.2:
+ * param = param-name "=" param-value *("," param-value)
+ */
+ gboolean has_name = FALSE;
+ attr_str = g_string_append_c (attr_str, ';');
+ if (g_ascii_strcasecmp (param->name, "TYPE")) {
+ attr_str = g_string_append (attr_str, param->name);
+ has_name = TRUE;
+ }
+ if (param->values) {
+ if (has_name)
+ attr_str = g_string_append_c (attr_str, '=');
+ for (v = param->values; v; v = v->next) {
+ char *value = v->data;
+ char *p = value;
+ gboolean quotes = FALSE;
+ while (*p) {
+ if (g_utf8_get_char (p) != '-' && !g_unichar_isalnum (g_utf8_get_char (p))) {
+ quotes = TRUE;
+ break;
+ }
+ p = g_utf8_next_char (p);
+ }
+ if (quotes)
+ attr_str = g_string_append_c (attr_str, '"');
+ attr_str = g_string_append (attr_str, value);
+ if (quotes)
+ attr_str = g_string_append_c (attr_str, '"');
+ if (v->next)
+ attr_str = g_string_append_c (attr_str, ',');
+ }
+ }
+ }
+
+ attr_str = g_string_append_c (attr_str, ':');
+
+ for (v = attr->values; v; v = v->next) {
+ char *value = v->data;
+ char *escaped_value = NULL;
+
+ escaped_value = e_vcard_escape_string (value);
+
+ attr_str = g_string_append (attr_str, escaped_value);
+ if (v->next) {
+ /* XXX toshok - i hate you, rfc 2426.
+ why doesn't CATEGORIES use a ; like
+ a normal list attribute? */
+ if (!strcmp (attr->name, "CATEGORIES"))
+ attr_str = g_string_append_c (attr_str, ',');
+ else
+ attr_str = g_string_append_c (attr_str, ';');
+ }
+
+ g_free (escaped_value);
+ }
+
+ /* 5.8.2:
+ * When generating a content line, lines longer than 75
+ * characters SHOULD be folded
+ */
+ l = 0;
+ do {
+ if (attr_str->len - l > 75) {
+ l += 75;
+ attr_str = g_string_insert_len (attr_str, l, CRLF " ", sizeof (CRLF " ") - 1);
+ }
+ else
+ break;
+ } while (l < attr_str->len);
+
+ attr_str = g_string_append (attr_str, CRLF);
+
+ str = g_string_append (str, attr_str->str);
+ g_string_free (attr_str, TRUE);
+ }
+
+ str = g_string_append (str, "END:VCARD\r\n\r\n");
+
+ return g_string_free (str, FALSE);
return g_strdup ("");
}
@@ -737,6 +857,8 @@
/* 5.8.2:
* param = param-name "=" param-value *("," param-value)
*/
+ if (!g_ascii_strcasecmp (param->name, "CHARSET"))
+ continue;
attr_str = g_string_append_c (attr_str, ';');
attr_str = g_string_append (attr_str, param->name);
if (param->values) {
@@ -1008,26 +1130,34 @@
g_return_if_fail (attr != NULL);
switch (attr->encoding) {
- case EVC_ENCODING_RAW:
- g_warning ("can't add_value_decoded with an attribute using RAW encoding. you must set the ENCODING parameter first");
- break;
- case EVC_ENCODING_BASE64: {
- char *b64_data = _evc_base64_encode_simple (value, len);
- GString *decoded = g_string_new_len (value, len);
-
- /* make sure the decoded list is up to date */
- e_vcard_attribute_get_values_decoded (attr);
-
- d(printf ("base64 encoded value: %s\n", b64_data));
- d(printf ("original length: %d\n", len));
-
- attr->values = g_list_append (attr->values, b64_data);
- attr->decoded_values = g_list_append (attr->decoded_values, decoded);
- break;
- }
- case EVC_ENCODING_QP:
- g_warning ("need to implement quoted printable decoding");
- break;
+ case EVC_ENCODING_RAW:
+ g_warning ("can't add_value_decoded with an attribute using RAW encoding. you must set the ENCODING parameter first");
+ break;
+ case EVC_ENCODING_BASE64: {
+ char *b64_data = _evc_base64_encode_simple (value, len);
+ GString *decoded = g_string_new_len (value, len);
+
+ /* make sure the decoded list is up to date */
+ e_vcard_attribute_get_values_decoded (attr);
+
+ d(printf ("base64 encoded value: %s\n", b64_data));
+ d(printf ("original length: %d\n", len));
+
+ attr->values = g_list_append (attr->values, b64_data);
+ attr->decoded_values = g_list_append (attr->decoded_values, decoded);
+ break;
+ }
+ case EVC_ENCODING_QP: {
+ char *qp_data = _evc_quoted_encode_simple (value, len);
+ GString *decoded = g_string_new (value);
+
+ /* make sure the decoded list is up to date */
+ e_vcard_attribute_get_values_decoded (attr);
+
+ attr->values = g_list_append (attr->values, qp_data);
+ attr->decoded_values = g_list_append (attr->decoded_values, decoded);
+ break;
+ }
}
}
@@ -1279,7 +1409,14 @@
}
break;
case EVC_ENCODING_QP:
- g_warning ("need to implement quoted printable decoding");
+ for (l = attr->values; l; l = l->next) {
+ if (!(l->data))
+ continue;
+ char *decoded = g_strdup ((char*)l->data);
+ int len = _evc_quoted_decode_simple (decoded, strlen (decoded));
+ attr->decoded_values = g_list_append (attr->decoded_values, g_string_new_len (decoded, len));
+ g_free (decoded);
+ }
break;
}
}
@@ -1614,3 +1751,56 @@
return _evc_base64_decode_step ((unsigned char *)data, len,
(unsigned char *)data, &state, &save);
}
+
+char *
+_evc_quoted_encode_simple(const unsigned char *string, int len)
+{
+ GString *tmp = g_string_new("");
+
+ int i = 0;
+ while(string[i] != 0) {
+ if (string[i] > 127 || string[i] == 13 || string[i] == 10 || string[i] == '=') {
+ g_string_append_printf(tmp, "=%02X", string[i]);
+ } else {
+ g_string_append_c(tmp, string[i]);
+ }
+ i++;
+ }
+
+ char *ret = tmp->str;
+ g_string_free(tmp, FALSE);
+ return ret;
+}
+
+
+size_t
+_evc_quoted_decode_simple (char *data, size_t len)
+{
+ g_return_val_if_fail (data != NULL, 0);
+
+ GString *string = g_string_new(data);
+ if (!string)
+ return 0;
+
+ char hex[5];
+ hex[4] = 0;
+
+ while (1) {
+ //Get the index of the next encoded char
+ int i = strcspn(string->str, "=");
+ if (i >= strlen(string->str))
+ break;
+
+ strcpy(hex, "0x");
+ strncat(hex, &string->str[i + 1], 2);
+ char rep = ((int)(strtod(hex, NULL)));
+ g_string_erase(string, i, 2);
+ g_string_insert_c(string, i, rep);
+ }
+
+ memset(data, 0, strlen(data));
+ strcpy(data, string->str);
+ g_string_free(string, 1);
+
+ return strlen(data);
+}
BEGIN:VCARD
ADR;TYPE=home;TYPE=pref:1234567890;;Foo Palace,\n173/A Foo Tower Road,\n98t
h Precinct.\nLeave any parcels in the nook of the tree at the top of the ga
rden next to the old Roman columns which are covered in poison ivy and have
lots of spiders in them. Make sure you put the parcel in a sealed containe
r to keep out the spiders and the rain. Leave a piece of bread for the bird
s while you are there. The birds help keep the spiders under control and Fo
o hates spiders.;Foosville;Foo Valley Heights;9876543210;Australia
ADR;TYPE=work:123;;This is Foo's work address.\n15 FooBar Tce,\nFooBar Town
;Bar Heights;Bartonia;1234;Australia
CLASS:PUBLIC
EMAIL;TYPE=PREF:foo bar com
EMAIL:foo bar org
FN:Foo Bar
GEO:-36.900002;149.399994
N:Bar;Foo;;;
NICKNAME:Nickname Foo
NOTE:This is a note and this is it's first line.\nThis is the second line o
f the note.\nThis is the third line of the note.\nThis is the fourth line o
f the note.\nThis is the fifth line of the note.\nThis is one very long lin
e, it contains a whole lot of characters and its purpose is to test that lo
ng lines are properly supported by any vcard reader or writer, this is done
because some vcard readers balk at reading lines longer than seventy chara
cters.\nThis is some "double quoted text".\nThis is some 'single quoted tex
t'.\n\nAbove is a blank line.\nHere are some punctuation characters ~`! #$%
^&*()_+=\|[{]};:'",<.>/?.\nAnd this is the very last line of the note.
ORG:Fooo Fab International
PHOTO;ENCODING=b;TYPE=image/png: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
GG2VMFAAAAAElFTkSuQmCC
REV:2005-01-23T12:22:28Z
ROLE:VCard Test Engineer
TEL;TYPE=FAX;TYPE=HOME:home fax
TEL;TYPE=FAX;TYPE=WORK:work fax number
TEL;TYPE=WORK:work phone number
TEL;TYPE=CELL:mobile phone number
TEL;TYPE=HOME;TYPE=PREF:home phone number
TEL;TYPE=MSG:messenger number
TEL;TYPE=CAR;TYPE=ISDN;TYPE=VIDEO:Car ISDN video number
UID:jKbODaDMj0
URL:http://www.foobar.com
VERSION:3.0
X-KADDRESSBOOK-23/01/2005:2000-01-01
X-KADDRESSBOOK-X-Department:Department Foo
X-KADDRESSBOOK-X-Office:Office Foo
X-KADDRESSBOOK-X-Profession:Profession Foo
X-KADDRESSBOOK-X-SpousesName:Spouse Foo
X-KADDRESSBOOK-customnumericfield:123
X-KADDRESSBOOK-my_customdatetimefield:1999-12-30T23:58:59
X-KADDRESSBOOK-mycustombooleanfield:true
X-KADDRESSBOOK-mycustomdatefield:1998-12-30
X-KADDRESSBOOK-mycustomtextfield:This is my custom text field. It can conta
in one line of text data only.
X-KADDRESSBOOK-mycustomtimefield:23:59:59
END:VCARD
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]