aboutsummaryrefslogtreecommitdiffstats
path: root/addressbook/backend/ebook/e-vcard.c
diff options
context:
space:
mode:
Diffstat (limited to 'addressbook/backend/ebook/e-vcard.c')
-rw-r--r--addressbook/backend/ebook/e-vcard.c1383
1 files changed, 0 insertions, 1383 deletions
diff --git a/addressbook/backend/ebook/e-vcard.c b/addressbook/backend/ebook/e-vcard.c
deleted file mode 100644
index 5207d0fefe..0000000000
--- a/addressbook/backend/ebook/e-vcard.c
+++ /dev/null
@@ -1,1383 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* e-vcard.c
- *
- * Copyright (C) 2003 Ximian, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: Chris Toshok (toshok@ximian.com)
- */
-
-#include <glib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include "e-vcard.h"
-
-#define CRLF "\r\n"
-
-typedef enum {
- EVC_ENCODING_RAW, /* no encoding */
- EVC_ENCODING_BASE64, /* base64 */
- EVC_ENCODING_QP /* quoted-printable */
-} EVCardEncoding;
-
-struct _EVCardPrivate {
- GList *attributes;
-};
-
-struct _EVCardAttribute {
- char *group;
- char *name;
- GList *params; /* EVCardParam */
- GList *values;
- GList *decoded_values;
- EVCardEncoding encoding;
- gboolean encoding_set;
-};
-
-struct _EVCardAttributeParam {
- char *name;
- GList *values; /* GList of char*'s*/
-};
-
-static GObjectClass *parent_class;
-
-static void _evc_base64_init(void);
-static size_t _evc_base64_encode_step(unsigned char *in, size_t len, gboolean break_lines, unsigned char *out, int *state, int *save);
-static size_t _evc_base64_decode_step(unsigned char *in, size_t len, unsigned char *out, int *state, unsigned int *save);
-size_t _evc_base64_decode_simple (char *data, size_t len);
-char *_evc_base64_encode_simple (const char *data, size_t len);
-
-static void
-e_vcard_dispose (GObject *object)
-{
- EVCard *evc = E_VCARD (object);
-
- if (!evc->priv)
- return;
-
- g_list_foreach (evc->priv->attributes, (GFunc)e_vcard_attribute_free, NULL);
- g_list_free (evc->priv->attributes);
-
- g_free (evc->priv);
- evc->priv = NULL;
-
- if (G_OBJECT_CLASS (parent_class)->dispose)
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-e_vcard_class_init (EVCardClass *klass)
-{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS(klass);
-
- parent_class = g_type_class_ref (G_TYPE_OBJECT);
-
- object_class->dispose = e_vcard_dispose;
-
- _evc_base64_init();
-}
-
-static void
-e_vcard_init (EVCard *evc)
-{
- evc->priv = g_new0 (EVCardPrivate, 1);
-}
-
-GType
-e_vcard_get_type (void)
-{
- static GType vcard_type = 0;
-
- if (!vcard_type) {
- static const GTypeInfo vcard_info = {
- sizeof (EVCardClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) e_vcard_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (EVCard),
- 0, /* n_preallocs */
- (GInstanceInitFunc) e_vcard_init,
- };
-
- vcard_type = g_type_register_static (G_TYPE_OBJECT, "EVCard", &vcard_info, 0);
- }
-
- return vcard_type;
-}
-
-
-
-static char*
-fold_lines (char *buf)
-{
- GString *str = g_string_new ("");
- char *p = buf;
- char *next, *next2;
-
- /* we're pretty liberal with line folding here. We handle
- lines folded with \r\n<WS>... and \n\r<WS>... and
- \n<WS>... We also turn single \r's and \n's not followed by
- WS into \r\n's. */
- while (*p) {
- if (*p == '\r' || *p == '\n') {
- next = g_utf8_next_char (p);
- if (*next == '\n' || *next == '\r') {
- next2 = g_utf8_next_char (next);
- if (*next2 == ' ' || *next2 == '\t') {
- p = g_utf8_next_char (next2);
- }
- else {
- str = g_string_append (str, CRLF);
- p = g_utf8_next_char (next);
- }
- }
- else if (*next == ' ' || *next == '\t') {
- p = g_utf8_next_char (next);
- }
- else {
- str = g_string_append (str, CRLF);
- p = g_utf8_next_char (p);
- }
- }
- else {
- str = g_string_append_unichar (str, g_utf8_get_char (p));
- p = g_utf8_next_char (p);
- }
- }
-
- g_free (buf);
-
- return g_string_free (str, FALSE);
-}
-
-/* skip forward until we hit the CRLF, or \0 */
-static void
-skip_to_next_line (char **p)
-{
- char *lp;
- lp = *p;
-
- while (*lp != '\r' && *lp != '\0')
- lp = g_utf8_next_char (lp);
-
- if (*lp == '\r') {
- lp = g_utf8_next_char (lp); /* \n */
- lp = g_utf8_next_char (lp); /* start of the next line */
- }
-
- *p = lp;
-}
-
-/* skip forward until we hit a character in @s, CRLF, or \0 */
-static void
-skip_until (char **p, char *s)
-{
- /* XXX write me plz k thx */
- g_assert_not_reached();
-}
-
-static void
-read_attribute_value (EVCardAttribute *attr, char **p, gboolean quoted_printable)
-{
- char *lp = *p;
- GString *str;
-
- /* read in the value */
- str = g_string_new ("");
- while (*lp != '\r' && *lp != '\0') {
- if (*lp == '=' && quoted_printable) {
- char a, b;
- if ((a = *(++lp)) == '\0') break;
- if ((b = *(++lp)) == '\0') break;
- if (a == '\r' && b == '\n') {
- /* it was a = at the end of the line,
- * just ignore this and continue
- * parsing on the next line. yay for
- * 2 kinds of line folding
- */
- }
- else if (isalnum(a) && isalnum (b)) {
- char c;
-
- a = tolower (a);
- b = tolower (b);
-
- c = (((a>='a'?a-'a'+10:a-'0')&0x0f) << 4)
- | ((b>='a'?b-'a'+10:b-'0')&0x0f);
-
- str = g_string_append_c (str, c);
- }
- /* silently consume malformed input, and
- continue parsing */
- lp++;
- }
- else if (*lp == '\\') {
- /* convert back to the non-escaped version of
- the characters */
- lp = g_utf8_next_char(lp);
- if (*lp == '\0') {
- str = g_string_append_c (str, '\\');
- break;
- }
- switch (*lp) {
- case 'n': str = g_string_append_c (str, '\n'); break;
- case 'r': str = g_string_append_c (str, '\r'); break;
- case ';': str = g_string_append_c (str, ';'); break;
- case ',': str = g_string_append_c (str, ','); break;
- case '\\': str = g_string_append_c (str, '\\'); break;
- default:
- g_warning ("invalid escape, passing it through");
- str = g_string_append_c (str, '\\');
- str = g_string_append_unichar (str, g_utf8_get_char(lp));
- break;
- }
- lp = g_utf8_next_char(lp);
- }
- else if (*lp == ';') {
- e_vcard_attribute_add_value (attr, str->str);
- g_string_assign (str, "");
- lp = g_utf8_next_char(lp);
- }
- else {
- str = g_string_append_unichar (str, g_utf8_get_char (lp));
- lp = g_utf8_next_char(lp);
- }
- }
- if (str) {
- e_vcard_attribute_add_value (attr, str->str);
- g_string_free (str, TRUE);
- }
-
- if (*lp == '\r') {
- lp = g_utf8_next_char (lp); /* \n */
- lp = g_utf8_next_char (lp); /* start of the next line */
- }
-
- *p = lp;
-}
-
-static void
-read_attribute_params (EVCardAttribute *attr, char **p, gboolean *quoted_printable)
-{
- char *lp = *p;
- GString *str;
- EVCardAttributeParam *param = NULL;
-
- str = g_string_new ("");
- while (*lp != '\0') {
- /* accumulate until we hit the '=' or ';'. If we hit
- * a '=' the string contains the parameter name. if
- * we hit a ';' the string contains the parameter
- * value and the name is either ENCODING (if value ==
- * QUOTED-PRINTABLE) or TYPE (in any other case.)
- */
- if (*lp == '=') {
- if (str->len > 0) {
- param = e_vcard_attribute_param_new (str->str);
- g_string_assign (str, "");
- lp = g_utf8_next_char (lp);
- }
- else {
- skip_until (&lp, ":;");
- if (*lp == '\r') {
- lp = g_utf8_next_char (lp); /* \n */
- lp = g_utf8_next_char (lp); /* start of the next line */
- break;
- }
- else if (*lp == ';')
- lp = g_utf8_next_char (lp);
- }
- }
- else if (*lp == ';' || *lp == ':' || *lp == ',') {
- gboolean colon = (*lp == ':');
- gboolean comma = (*lp == ',');
-
- if (param) {
- if (str->len > 0) {
- e_vcard_attribute_param_add_value (param, str->str);
- g_string_assign (str, "");
- if (!colon)
- lp = g_utf8_next_char (lp);
- }
- else {
- /* we've got a parameter of the form:
- * PARAM=(.*,)?[:;]
- * so what we do depends on if there are already values
- * for the parameter. If there are, we just finish
- * this parameter and skip past the offending character
- * (unless it's the ':'). If there aren't values, we free
- * the parameter then skip past the character.
- */
- if (!param->values) {
- e_vcard_attribute_param_free (param);
- param = NULL;
- }
- }
-
- if (param
- && !g_ascii_strcasecmp (param->name, "encoding")
- && !g_ascii_strcasecmp (param->values->data, "quoted-printable")) {
- *quoted_printable = TRUE;
- e_vcard_attribute_param_free (param);
- param = NULL;
- }
- }
- else {
- if (str->len > 0) {
- char *param_name;
- if (!g_ascii_strcasecmp (str->str,
- "quoted-printable")) {
- param_name = NULL;
- *quoted_printable = TRUE;
- }
- else {
- param_name = "TYPE";
- }
-
- if (param_name) {
- param = e_vcard_attribute_param_new (param_name);
- e_vcard_attribute_param_add_value (param, str->str);
- }
- g_string_assign (str, "");
- if (!colon)
- lp = g_utf8_next_char (lp);
- }
- else {
- /* XXX more here */
- g_assert_not_reached ();
- }
- }
- if (param && !comma) {
- e_vcard_attribute_add_param (attr, param);
- param = NULL;
- }
- if (colon)
- break;
- }
- else if (g_unichar_isalnum (g_utf8_get_char (lp)) || *lp == '-' || *lp == '_') {
- str = g_string_append_unichar (str, g_utf8_get_char (lp));
- lp = g_utf8_next_char (lp);
- }
- else {
- g_warning ("invalid character found in parameter spec");
- g_string_assign (str, "");
- skip_until (&lp, ":;");
- }
- }
-
- if (str)
- g_string_free (str, TRUE);
-
- *p = lp;
-}
-
-/* reads an entire attribute from the input buffer, leaving p pointing
- at the start of the next line (past the \r\n) */
-static EVCardAttribute*
-read_attribute (char **p)
-{
- char *attr_group = NULL;
- char *attr_name = NULL;
- EVCardAttribute *attr = NULL;
- GString *str;
- char *lp = *p;
- gboolean is_qp = FALSE;
-
- /* first read in the group/name */
- str = g_string_new ("");
- while (*lp != '\r' && *lp != '\0') {
- if (*lp == ':' || *lp == ';') {
- if (str->len != 0) {
- /* we've got a name, break out to the value/attribute parsing */
- attr_name = g_string_free (str, FALSE);
- break;
- }
- else {
- /* a line of the form:
- * (group.)?[:;]
- *
- * since we don't have an attribute
- * name, skip to the end of the line
- * and try again.
- */
- g_string_free (str, TRUE);
- *p = lp;
- skip_to_next_line(p);
- goto lose;
- }
- }
- else if (*lp == '.') {
- if (attr_group) {
- g_warning ("extra `.' in attribute specification. ignoring extra group `%s'",
- str->str);
- g_string_free (str, TRUE);
- str = g_string_new ("");
- }
- if (str->len != 0) {
- attr_group = g_string_free (str, FALSE);
- str = g_string_new ("");
- }
- }
- else if (g_unichar_isalnum (g_utf8_get_char (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_string_free (str, TRUE);
- *p = lp;
- skip_to_next_line(p);
- goto lose;
- }
-
- lp = g_utf8_next_char(lp);
- }
-
- if (!attr_name) {
- skip_to_next_line (p);
- goto lose;
- }
-
- attr = e_vcard_attribute_new (attr_group, attr_name);
- g_free (attr_group);
- g_free (attr_name);
-
- if (*lp == ';') {
- /* skip past the ';' */
- lp = g_utf8_next_char(lp);
- read_attribute_params (attr, &lp, &is_qp);
- }
- if (*lp == ':') {
- /* skip past the ':' */
- lp = g_utf8_next_char(lp);
- read_attribute_value (attr, &lp, is_qp);
- }
-
- *p = lp;
-
- if (!attr->values)
- goto lose;
-
- return attr;
- lose:
- if (attr)
- e_vcard_attribute_free (attr);
- return NULL;
-}
-
-/* we try to be as forgiving as we possibly can here - this isn't a
- * validator. Almost nothing is considered a fatal error. We always
- * try to return *something*.
- */
-static void
-parse (EVCard *evc, const char *str)
-{
- char *buf = g_strdup (str);
- char *p, *end;
- EVCardAttribute *attr;
-
- /* first validate the string is valid utf8 */
- if (!g_utf8_validate (buf, -1, (const char **)&end)) {
- /* if the string isn't valid, we parse as much as we can from it */
- g_warning ("invalid utf8 passed to EVCard. Limping along.");
- *end = '\0';
- }
-
-#if DEBUG_FOLDING
- printf ("BEFORE FOLDING:\n");
- printf (str);
-#endif
- buf = fold_lines (buf);
-
-#if DEBUG_FOLDING
- printf ("\n\nAFTER FOLDING:\n");
- printf (buf);
-#endif
- p = buf;
-
- attr = read_attribute (&p);
- if (!attr || attr->group || g_ascii_strcasecmp (attr->name, "begin")) {
- g_warning ("vcard began without a BEGIN:VCARD\n");
- }
- if (attr)
- e_vcard_attribute_free (attr);
-
- while (*p) {
- EVCardAttribute *next_attr = read_attribute (&p);
-
- if (next_attr) {
- if (g_ascii_strcasecmp (next_attr->name, "end"))
- e_vcard_add_attribute (evc, next_attr);
- attr = next_attr;
- }
- }
-
- if (!attr || attr->group || g_ascii_strcasecmp (attr->name, "end")) {
- g_warning ("vcard ended without END:VCARD\n");
- }
-
- if (attr && !g_ascii_strcasecmp (attr->name, "end"))
- e_vcard_attribute_free (attr);
-
- g_free (buf);
-}
-
-static char*
-escape_string (const char *s)
-{
- GString *str = g_string_new ("");
- const char *p;
-
- /* Escape a string as described in RFC2426, section 5 */
- for (p = s; p && *p; p++) {
- switch (*p) {
- case '\n':
- str = g_string_append (str, "\\n");
- break;
- case '\r':
- if (*(p+1) == '\n')
- p++;
- str = g_string_append (str, "\\n");
- break;
- case ';':
- str = g_string_append (str, "\\;");
- break;
- case ',':
- str = g_string_append (str, "\\,");
- break;
- case '\\':
- str = g_string_append (str, "\\\\");
- break;
- default:
- str = g_string_append_c (str, *p);
- break;
- }
- }
-
- return g_string_free (str, FALSE);
-}
-
-#if notyet
-static char*
-unescape_string (const char *s)
-{
- GString *str = g_string_new ("");
- const char *p;
-
- /* Unescape a string as described in RFC2426, section 5 */
- for (p = s; *p; p++) {
- if (*p == '\\') {
- p++;
- if (*p == '\0') {
- str = g_string_append_c (str, '\\');
- break;
- }
- switch (*p) {
- case 'n': str = g_string_append_c (str, '\n'); break;
- case 'r': str = g_string_append_c (str, '\r'); break;
- case ';': str = g_string_append_c (str, ';'); break;
- case ',': str = g_string_append_c (str, ','); break;
- case '\\': str = g_string_append_c (str, '\\'); break;
- default:
- g_warning ("invalid escape, passing it through");
- str = g_string_append_c (str, '\\');
- str = g_string_append_unichar (str, g_utf8_get_char(p));
- break;
- }
- }
- }
-
- return g_string_free (str, FALSE);
-}
-#endif
-
-void
-e_vcard_construct (EVCard *evc, const char *str)
-{
- if (*str)
- parse (evc, str);
-}
-
-EVCard *
-e_vcard_new ()
-{
- return e_vcard_new_from_string ("");
-}
-
-EVCard *
-e_vcard_new_from_string (const char *str)
-{
- EVCard *evc;
-
- g_return_val_if_fail (str, NULL);
-
- evc = g_object_new (E_TYPE_VCARD, NULL);
-
- e_vcard_construct (evc, str);
-
- return evc;
-}
-
-static char*
-e_vcard_to_string_vcard_21 (EVCard *evc)
-{
- g_warning ("need to implement e_vcard_to_string_vcard_21");
- return g_strdup ("");
-}
-
-static char*
-e_vcard_to_string_vcard_30 (EVCard *evc)
-{
- GList *l;
- GList *v;
-
- GString *str = g_string_new ("");
-
- str = g_string_append (str, "BEGIN:vCard" CRLF);
-
- for (l = evc->priv->attributes; l; l = l->next) {
- GList *p;
- EVCardAttribute *attr = l->data;
- GString *attr_str = g_string_new ("");
- int l;
-
- /* 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)
- */
- attr_str = g_string_append_c (attr_str, ';');
- attr_str = g_string_append (attr_str, param->name);
- if (param->values) {
- attr_str = g_string_append_c (attr_str, '=');
- for (v = param->values; v; v = v->next) {
- char *value = v->data;
- attr_str = g_string_append (attr_str, value);
- 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 = escape_string (value);
-
- attr_str = g_string_append (attr_str, escaped_value);
- if (v->next)
- 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");
-
- return g_string_free (str, FALSE);
-}
-
-char*
-e_vcard_to_string (EVCard *evc, EVCardFormat format)
-{
- switch (format) {
- case EVC_FORMAT_VCARD_21:
- return e_vcard_to_string_vcard_21 (evc);
- case EVC_FORMAT_VCARD_30:
- return e_vcard_to_string_vcard_30 (evc);
- default:
- g_warning ("invalid format specifier passed to e_vcard_to_string");
- return g_strdup ("");
- }
-}
-
-void
-e_vcard_dump_structure (EVCard *evc)
-{
- GList *a;
- GList *v;
- int i;
-
- printf ("vCard\n");
- for (a = evc->priv->attributes; a; a = a->next) {
- GList *p;
- EVCardAttribute *attr = a->data;
- printf ("+-- %s\n", attr->name);
- if (attr->params) {
- printf (" +- params=\n");
-
- for (p = attr->params, i = 0; p; p = p->next, i++) {
- EVCardAttributeParam *param = p->data;
- printf (" | [%d] = %s", i,param->name);
- printf ("(");
- for (v = param->values; v; v = v->next) {
- char *value = escape_string ((char*)v->data);
- printf ("%s", value);
- if (v->next)
- printf (",");
- g_free (value);
- }
-
- printf (")\n");
- }
- }
- printf (" +- values=\n");
- for (v = attr->values, i = 0; v; v = v->next, i++) {
- printf (" [%d] = `%s'\n", i, (char*)v->data);
- }
- }
-}
-
-
-EVCardAttribute*
-e_vcard_attribute_new (const char *attr_group, const char *attr_name)
-{
- EVCardAttribute *attr = g_new0 (EVCardAttribute, 1);
-
- attr->group = g_strdup (attr_group);
- attr->name = g_strdup (attr_name);
-
- return attr;
-}
-
-void
-e_vcard_attribute_free (EVCardAttribute *attr)
-{
- g_free (attr->group);
- g_free (attr->name);
-
- e_vcard_attribute_remove_values (attr);
-
- e_vcard_attribute_remove_params (attr);
-
- g_free (attr);
-}
-
-EVCardAttribute*
-e_vcard_attribute_copy (EVCardAttribute *attr)
-{
- EVCardAttribute *a = e_vcard_attribute_new (e_vcard_attribute_get_group (attr),
- e_vcard_attribute_get_name (attr));
- GList *p;
-
- for (p = attr->values; p; p = p->next)
- e_vcard_attribute_add_value (a, p->data);
-
- for (p = attr->params; p; p = p->next)
- e_vcard_attribute_add_param (a, e_vcard_attribute_param_copy (p->data));
-
- return a;
-}
-
-void
-e_vcard_remove_attributes (EVCard *evc, const char *attr_group, const char *attr_name)
-{
- GList *attr;
-
- attr = evc->priv->attributes;
- while (attr) {
- GList *next_attr;
- EVCardAttribute *a = attr->data;
-
- next_attr = attr->next;
-
- if (((!attr_group && !a->group) || !g_ascii_strcasecmp (attr_group, a->group)) &&
- ((!attr_name && !a->name) || !g_ascii_strcasecmp (attr_name, a->name))) {
-
- /* matches, remove/delete the attribute */
- evc->priv->attributes = g_list_remove_link (evc->priv->attributes, attr);
-
- e_vcard_attribute_free (a);
- }
-
- attr = next_attr;
- }
-}
-
-void
-e_vcard_remove_attribute (EVCard *evc, EVCardAttribute *attr)
-{
- evc->priv->attributes = g_list_remove (evc->priv->attributes, attr);
- e_vcard_attribute_free (attr);
-}
-
-void
-e_vcard_add_attribute (EVCard *evc, EVCardAttribute *attr)
-{
- evc->priv->attributes = g_list_append (evc->priv->attributes, attr);
-}
-
-void
-e_vcard_add_attribute_with_value (EVCard *evcard,
- EVCardAttribute *attr, const char *value)
-{
- e_vcard_attribute_add_value (attr, value);
-
- e_vcard_add_attribute (evcard, attr);
-}
-
-void
-e_vcard_add_attribute_with_values (EVCard *evcard, EVCardAttribute *attr, ...)
-{
- va_list ap;
- char *v;
-
- va_start (ap, attr);
-
- while ((v = va_arg (ap, char*))) {
- e_vcard_attribute_add_value (attr, v);
- }
-
- va_end (ap);
-
- e_vcard_add_attribute (evcard, attr);
-}
-
-void
-e_vcard_attribute_add_value (EVCardAttribute *attr, const char *value)
-{
- attr->values = g_list_append (attr->values, g_strdup (value));
-}
-
-void
-e_vcard_attribute_add_value_decoded (EVCardAttribute *attr, const char *value, int len)
-{
- 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);
-
- printf ("base64 encoded value: %s\n", b64_data);
- 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;
- }
-}
-
-void
-e_vcard_attribute_add_values (EVCardAttribute *attr,
- ...)
-{
- va_list ap;
- char *v;
-
- va_start (ap, attr);
-
- while ((v = va_arg (ap, char*))) {
- e_vcard_attribute_add_value (attr, v);
- }
-
- va_end (ap);
-}
-
-static void
-free_gstring (GString *str)
-{
- g_string_free (str, TRUE);
-}
-
-void
-e_vcard_attribute_remove_values (EVCardAttribute *attr)
-{
- g_list_foreach (attr->values, (GFunc)g_free, NULL);
- g_list_free (attr->values);
- g_list_foreach (attr->decoded_values, (GFunc)free_gstring, NULL);
- g_list_free (attr->decoded_values);
- attr->values = NULL;
-}
-
-void
-e_vcard_attribute_remove_params (EVCardAttribute *attr)
-{
- g_list_foreach (attr->params, (GFunc)e_vcard_attribute_param_free, NULL);
- g_list_free (attr->params);
- attr->params = NULL;
-}
-
-EVCardAttributeParam*
-e_vcard_attribute_param_new (const char *name)
-{
- EVCardAttributeParam *param = g_new0 (EVCardAttributeParam, 1);
- param->name = g_strdup (name);
-
- return param;
-}
-
-void
-e_vcard_attribute_param_free (EVCardAttributeParam *param)
-{
- g_free (param->name);
-
- e_vcard_attribute_param_remove_values (param);
-
- g_free (param);
-}
-
-EVCardAttributeParam*
-e_vcard_attribute_param_copy (EVCardAttributeParam *param)
-{
- EVCardAttributeParam *p = e_vcard_attribute_param_new (e_vcard_attribute_param_get_name (param));
- GList *l;
-
- for (l = param->values; l; l = l->next) {
- e_vcard_attribute_param_add_value (p, l->data);
- }
-
- return p;
-}
-
-void
-e_vcard_attribute_add_param (EVCardAttribute *attr,
- EVCardAttributeParam *param)
-{
- attr->params = g_list_append (attr->params, param);
-
- /* we handle our special encoding stuff here */
-
- if (!g_ascii_strcasecmp (param->name, EVC_ENCODING)) {
- if (attr->encoding_set) {
- g_warning ("ENCODING specified twice");
- return;
- }
-
- if (param->values && param->values->data) {
- if (!g_ascii_strcasecmp ((char*)param->values->data, "b"))
- attr->encoding = EVC_ENCODING_BASE64;
- else if (!g_ascii_strcasecmp ((char*)param->values->data, EVC_QUOTEDPRINTABLE))
- attr->encoding = EVC_ENCODING_QP;
- else {
- g_warning ("Unknown value `%s' for ENCODING parameter. values will be treated as raw",
- (char*)param->values->data);
- }
-
- attr->encoding_set = TRUE;
- }
- else {
- g_warning ("ENCODING parameter added with no value");
- }
- }
-}
-
-void
-e_vcard_attribute_param_add_value (EVCardAttributeParam *param,
- const char *value)
-{
- param->values = g_list_append (param->values, g_strdup (value));
-}
-
-void
-e_vcard_attribute_param_add_values (EVCardAttributeParam *param,
- ...)
-{
- va_list ap;
- char *v;
-
- va_start (ap, param);
-
- while ((v = va_arg (ap, char*))) {
- e_vcard_attribute_param_add_value (param, v);
- }
-
- va_end (ap);
-}
-
-void
-e_vcard_attribute_add_param_with_value (EVCardAttribute *attr,
- EVCardAttributeParam *param, const char *value)
-{
- e_vcard_attribute_param_add_value (param, value);
-
- e_vcard_attribute_add_param (attr, param);
-}
-
-void
-e_vcard_attribute_add_param_with_values (EVCardAttribute *attr,
- EVCardAttributeParam *param, ...)
-{
- va_list ap;
- char *v;
-
- va_start (ap, param);
-
- while ((v = va_arg (ap, char*))) {
- e_vcard_attribute_param_add_value (param, v);
- }
-
- va_end (ap);
-
- e_vcard_attribute_add_param (attr, param);
-}
-
-void
-e_vcard_attribute_param_remove_values (EVCardAttributeParam *param)
-{
- g_list_foreach (param->values, (GFunc)g_free, NULL);
- g_list_free (param->values);
- param->values = NULL;
-}
-
-GList*
-e_vcard_get_attributes (EVCard *evcard)
-{
- return evcard->priv->attributes;
-}
-
-const char*
-e_vcard_attribute_get_group (EVCardAttribute *attr)
-{
- return attr->group;
-}
-
-const char*
-e_vcard_attribute_get_name (EVCardAttribute *attr)
-{
- return attr->name;
-}
-
-GList*
-e_vcard_attribute_get_values (EVCardAttribute *attr)
-{
- return attr->values;
-}
-
-GList*
-e_vcard_attribute_get_values_decoded (EVCardAttribute *attr)
-{
- if (!attr->decoded_values) {
- GList *l;
- switch (attr->encoding) {
- case EVC_ENCODING_RAW:
- for (l = attr->values; l; l = l->next)
- attr->decoded_values = g_list_append (attr->decoded_values, g_string_new ((char*)l->data));
- break;
- case EVC_ENCODING_BASE64:
- for (l = attr->values; l; l = l->next) {
- char *decoded = g_strdup ((char*)l->data);
- int len = _evc_base64_decode_simple (decoded, strlen (decoded));
- attr->decoded_values = g_list_append (attr->decoded_values, g_string_new_len (decoded, len));
- g_free (decoded);
- }
- break;
- case EVC_ENCODING_QP:
- g_warning ("need to implement quoted printable decoding");
- break;
- }
- }
-
- return attr->decoded_values;
-}
-
-GList*
-e_vcard_attribute_get_params (EVCardAttribute *attr)
-{
- return attr->params;
-}
-
-const char*
-e_vcard_attribute_param_get_name (EVCardAttributeParam *param)
-{
- return param->name;
-}
-
-GList*
-e_vcard_attribute_param_get_values (EVCardAttributeParam *param)
-{
- return param->values;
-}
-
-
-
-/* encoding/decoding stuff ripped from camel-mime-utils.c */
-
-static char *_evc_base64_alphabet =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-static unsigned char _evc_base64_rank[256];
-
-static void
-_evc_base64_init(void)
-{
- int i;
-
- memset(_evc_base64_rank, 0xff, sizeof(_evc_base64_rank));
- for (i=0;i<64;i++) {
- _evc_base64_rank[(unsigned int)_evc_base64_alphabet[i]] = i;
- }
- _evc_base64_rank['='] = 0;
-}
-
-/* call this when finished encoding everything, to
- flush off the last little bit */
-static size_t
-_evc_base64_encode_close(unsigned char *in, size_t inlen, gboolean break_lines, unsigned char *out, int *state, int *save)
-{
- int c1, c2;
- unsigned char *outptr = out;
-
- if (inlen>0)
- outptr += _evc_base64_encode_step(in, inlen, break_lines, outptr, state, save);
-
- c1 = ((unsigned char *)save)[1];
- c2 = ((unsigned char *)save)[2];
-
-#if 0
- d(printf("mode = %d\nc1 = %c\nc2 = %c\n",
- (int)((char *)save)[0],
- (int)((char *)save)[1],
- (int)((char *)save)[2]));
-#endif
-
- switch (((char *)save)[0]) {
- case 2:
- outptr[2] = _evc_base64_alphabet[ ( (c2 &0x0f) << 2 ) ];
- g_assert(outptr[2] != 0);
- goto skip;
- case 1:
- outptr[2] = '=';
- skip:
- outptr[0] = _evc_base64_alphabet[ c1 >> 2 ];
- outptr[1] = _evc_base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 )];
- outptr[3] = '=';
- outptr += 4;
- break;
- }
- if (break_lines)
- *outptr++ = '\n';
-
- *save = 0;
- *state = 0;
-
- return outptr-out;
-}
-
-/*
- performs an 'encode step', only encodes blocks of 3 characters to the
- output at a time, saves left-over state in state and save (initialise to
- 0 on first invocation).
-*/
-static size_t
-_evc_base64_encode_step(unsigned char *in, size_t len, gboolean break_lines, unsigned char *out, int *state, int *save)
-{
- register unsigned char *inptr, *outptr;
-
- if (len<=0)
- return 0;
-
- inptr = in;
- outptr = out;
-
-#if 0
- d(printf("we have %d chars, and %d saved chars\n", len, ((char *)save)[0]));
-#endif
-
- if (len + ((char *)save)[0] > 2) {
- unsigned char *inend = in+len-2;
- register int c1, c2, c3;
- register int already;
-
- already = *state;
-
- switch (((char *)save)[0]) {
- case 1: c1 = ((unsigned char *)save)[1]; goto skip1;
- case 2: c1 = ((unsigned char *)save)[1];
- c2 = ((unsigned char *)save)[2]; goto skip2;
- }
-
- /* yes, we jump into the loop, no i'm not going to change it, it's beautiful! */
- while (inptr < inend) {
- c1 = *inptr++;
- skip1:
- c2 = *inptr++;
- skip2:
- c3 = *inptr++;
- *outptr++ = _evc_base64_alphabet[ c1 >> 2 ];
- *outptr++ = _evc_base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 ) ];
- *outptr++ = _evc_base64_alphabet[ ( (c2 &0x0f) << 2 ) | (c3 >> 6) ];
- *outptr++ = _evc_base64_alphabet[ c3 & 0x3f ];
- /* this is a bit ugly ... */
- if (break_lines && (++already)>=19) {
- *outptr++='\n';
- already = 0;
- }
- }
-
- ((char *)save)[0] = 0;
- len = 2-(inptr-inend);
- *state = already;
- }
-
-#if 0
- d(printf("state = %d, len = %d\n",
- (int)((char *)save)[0],
- len));
-#endif
-
- if (len>0) {
- register char *saveout;
-
- /* points to the slot for the next char to save */
- saveout = & (((char *)save)[1]) + ((char *)save)[0];
-
- /* len can only be 0 1 or 2 */
- switch(len) {
- case 2: *saveout++ = *inptr++;
- case 1: *saveout++ = *inptr++;
- }
- ((char *)save)[0]+=len;
- }
-
-#if 0
- d(printf("mode = %d\nc1 = %c\nc2 = %c\n",
- (int)((char *)save)[0],
- (int)((char *)save)[1],
- (int)((char *)save)[2]));
-#endif
-
- return outptr-out;
-}
-
-
-/**
- * base64_decode_step: decode a chunk of base64 encoded data
- * @in: input stream
- * @len: max length of data to decode
- * @out: output stream
- * @state: holds the number of bits that are stored in @save
- * @save: leftover bits that have not yet been decoded
- *
- * Decodes a chunk of base64 encoded data
- **/
-static size_t
-_evc_base64_decode_step(unsigned char *in, size_t len, unsigned char *out, int *state, unsigned int *save)
-{
- register unsigned char *inptr, *outptr;
- unsigned char *inend, c;
- register unsigned int v;
- int i;
-
- inend = in+len;
- outptr = out;
-
- /* convert 4 base64 bytes to 3 normal bytes */
- v=*save;
- i=*state;
- inptr = in;
- while (inptr<inend) {
- c = _evc_base64_rank[*inptr++];
- if (c != 0xff) {
- v = (v<<6) | c;
- i++;
- if (i==4) {
- *outptr++ = v>>16;
- *outptr++ = v>>8;
- *outptr++ = v;
- i=0;
- }
- }
- }
-
- *save = v;
- *state = i;
-
- /* quick scan back for '=' on the end somewhere */
- /* fortunately we can drop 1 output char for each trailing = (upto 2) */
- i=2;
- while (inptr>in && i) {
- inptr--;
- if (_evc_base64_rank[*inptr] != 0xff) {
- if (*inptr == '=' && outptr>out)
- outptr--;
- i--;
- }
- }
-
- /* if i!= 0 then there is a truncation error! */
- return outptr-out;
-}
-
-char *
-_evc_base64_encode_simple (const char *data, size_t len)
-{
- unsigned char *out;
- int state = 0, outlen;
- unsigned int save = 0;
-
- out = g_malloc (len * 4 / 3 + 5);
- outlen = _evc_base64_encode_close ((unsigned char *)data, len, FALSE,
- out, &state, &save);
- out[outlen] = '\0';
- return (char *)out;
-}
-
-size_t
-_evc_base64_decode_simple (char *data, size_t len)
-{
- int state = 0;
- unsigned int save = 0;
-
- return _evc_base64_decode_step ((unsigned char *)data, len,
- (unsigned char *)data, &state, &save);
-}