summaryrefslogtreecommitdiffstats
path: root/debian/opensync/opensync-0.22/formats/vformats-xml/vformat.c
diff options
context:
space:
mode:
Diffstat (limited to 'debian/opensync/opensync-0.22/formats/vformats-xml/vformat.c')
-rw-r--r--debian/opensync/opensync-0.22/formats/vformats-xml/vformat.c2005
1 files changed, 0 insertions, 2005 deletions
diff --git a/debian/opensync/opensync-0.22/formats/vformats-xml/vformat.c b/debian/opensync/opensync-0.22/formats/vformats-xml/vformat.c
deleted file mode 100644
index 547eef74..00000000
--- a/debian/opensync/opensync-0.22/formats/vformats-xml/vformat.c
+++ /dev/null
@@ -1,2005 +0,0 @@
-/*
- * Copyright (C) 2003 Ximian, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; 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)
- * Author: Armin Bauer (armin.bauer@opensync.org)
- *
- */
-
-#include "vformat.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <iconv.h>
-#include <opensync/opensync.h>
-
-static size_t base64_encode_step(unsigned char *in, size_t len, gboolean break_lines, unsigned char *out, int *state, int *save);
-static size_t base64_decode_step(unsigned char *in, size_t len, unsigned char *out, int *state, unsigned int *save);
-size_t base64_decode_simple (char *data, size_t len);
-char *base64_encode_simple (const char *data, size_t len);
-
-size_t quoted_decode_simple (char *data, size_t len);
-char *quoted_encode_simple (const unsigned char *string, int len);
-
-
-/**
- * _helper_is_base64 is helper function to check i a string is "b" or "base64"
- * @param check_string string that should be compared with "b" or "base64"
- * @return 0 if check_string is not base64 and 1 if it is
- */
-static int _helper_is_base64(const char *check_string)
-{
- if(!g_ascii_strcasecmp ((char *) check_string, "BASE64") ||
- !g_ascii_strcasecmp ((char *) check_string, "b") )
- return (1);
- return (0);
-}
-
-time_t vformat_time_to_unix(const char *inptime)
-{
- char *date = NULL;
- char *time = NULL;
- char *ftime = NULL;
- if ((ftime = g_strrstr(inptime, "T"))) {
-
- date = g_strndup(inptime, ftime - inptime);
- if (ftime[3] == ':')
- time = g_strndup(ftime + 1, 8);
- else
- time = g_strndup(ftime + 1, 6);
- } else {
- date = g_strdup(inptime);
- }
-
- struct tm btime;
- memset(&btime, 0, sizeof(struct tm));
-
- if (strlen(date) == 10) {
- btime.tm_year = date[0] * 1000 + date[1] * 100 + date[2] * 10 + date[3] - '0' * 1111 - 1900;
- btime.tm_mon = date[5] * 10 + date[6] - '0' * 11 - 1;
- btime.tm_mday = date[8] * 10 + date[9] - '0' * 11;
- } else {
- btime.tm_year = date[0] * 1000 + date[1] * 100 + date[2] * 10 + date[3] - '0' * 1111- 1900;
- btime.tm_mon = date[4] * 10 + date[5] - '0' * 11 - 1;
- btime.tm_mday = date[6] * 10 + date[7] - '0' * 11;
- }
-
- if (time && strlen(time) == 8) {
- //Time
- btime.tm_hour = time[0] * 10 + time[1] - '0' * 11;
- btime.tm_min = time[3] * 10 + time[4] - '0' * 11;
- btime.tm_sec = time[6] * 10 + time[7] - '0' * 11;
- } else if (time && strlen(time) == 6) {
- btime.tm_hour = time[0] * 10 + time[1] - '0' * 11;
- btime.tm_min = time[2] * 10 + time[3] - '0' * 11;
- btime.tm_sec = time[4] * 10 + time[5] - '0' * 11;
- }
-
- time_t utime = mktime(&btime);
- return utime;
-}
-
-static char *_fold_lines (char *buf)
-{
- GString *str = g_string_new ("");
- GString *line = g_string_new ("");
- char *p = buf;
- char *next, *next2, *q;
- gboolean newline = TRUE;
- gboolean quotedprintable = FALSE;
-
- /*
- * We're pretty liberal with line folding here. We handle
- * lines folded with \r\n<WS>, \n\r<WS>, \n<WS>, =\r\n and =\n\r.
- * We also turn single \r's and \n's not followed by <WS> into \r\n's.
- */
-
- while (*p) {
-
- /* search new lines for quoted printable encoding */
- if (newline) {
- for (q=p; *q != '\n' && *q != '\0'; q++)
- line = g_string_append_unichar (line, g_utf8_get_char (q));
-
- if (strstr(line->str, "ENCODING=QUOTED-PRINTABLE"))
- quotedprintable = TRUE;
-
- g_string_free(line, TRUE);
- line = g_string_new ("");
-
- newline = FALSE;
- }
-
-
- if ((quotedprintable && *p == '=') || *p == '\r' || *p == '\n') {
- next = g_utf8_next_char (p);
- if (*next == '\n' || *next == '\r') {
- next2 = g_utf8_next_char (next);
- if (*next2 == '\n' || *next2 == '\r' || *next2 == ' ' || *next2 == '\t') {
- p = g_utf8_next_char (next2);
- }
- else {
- str = g_string_append (str, CRLF);
- p = g_utf8_next_char (next);
- newline = TRUE;
- quotedprintable = FALSE;
- }
- }
- else if (*p == '=') {
- str = g_string_append_unichar (str, g_utf8_get_char (p));
- p = g_utf8_next_char (p);
- }
- else if (*next == ' ' || *next == '\t') {
- p = g_utf8_next_char (next);
- }
- else {
- str = g_string_append (str, CRLF);
- p = g_utf8_next_char (p);
- newline = TRUE;
- quotedprintable = FALSE;
- }
- }
- else {
- str = g_string_append_unichar (str, g_utf8_get_char (p));
- p = g_utf8_next_char (p);
- }
- }
-
- g_free (buf);
- g_string_free(line, TRUE);
-
- 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. leave *p
- pointing at the character that causes us to stop */
-static void _skip_until (char **p, char *s)
-{
- char *lp;
-
- lp = *p;
-
- while (*lp != '\r' && *lp != '\0') {
- gboolean s_matches = FALSE;
- char *ls;
- for (ls = s; *ls; ls = g_utf8_next_char (ls)) {
- if (g_utf8_get_char (ls) == g_utf8_get_char (lp)) {
- s_matches = TRUE;
- break;
- }
- }
-
- if (s_matches)
- break;
- lp++;
- }
-
- *p = lp;
-}
-
-static void _read_attribute_value_add (VFormatAttribute *attr, GString *str, GString *charset)
-{
- /* don't convert empty strings */
- if (str->len == 0) {
- vformat_attribute_add_value(attr, str->str);
- return;
- }
-
- char *inbuf, *outbuf, *p;
- size_t inbytesleft, outbytesleft;
-
- inbuf = str->str;
- p = outbuf = malloc(str->len*2);
- inbytesleft = str->len;
- outbytesleft = str->len*2;
-
- iconv_t cd;
-
- /* if a CHARSET was given, let's try to convert inbuf to UTF-8 */
- if (charset) {
-
- cd = iconv_open("UTF-8", charset->str);
-#ifdef SOLARIS
- if (iconv(cd, (const char**)&inbuf, &inbytesleft, &p, &outbytesleft) != (size_t)(-1)) {
-#else
- if (iconv(cd, &inbuf, &inbytesleft, &p, &outbytesleft) != (size_t)(-1)) {
-#endif
- *p = 0;
- vformat_attribute_add_value(attr, outbuf);
-
- } else {
-
- /* hmm, should not happen */
- vformat_attribute_add_value(attr, str->str);
-
- }
-
- iconv_close(cd);
-
- } else {
-
- /* no CHARSET was given, if inbuf is already UTF-8 we add str->str */
- if (g_utf8_validate (inbuf, -1, NULL)) {
-
- vformat_attribute_add_value (attr, str->str);
-
- } else {
-
- /* because inbuf is not UTF-8, we think it is ISO-8859-1 */
- cd = iconv_open("UTF-8", "ISO-8859-1");
-#ifdef SOLARIS
- if (iconv(cd, (const char**)&inbuf, &inbytesleft, &p, &outbytesleft) != (size_t)(-1)) {
-#else
- if (iconv(cd, &inbuf, &inbytesleft, &p, &outbytesleft) != (size_t)(-1)) {
-#endif
- *p = 0;
- vformat_attribute_add_value (attr, outbuf);
-
- } else {
-
- vformat_attribute_add_value (attr, str->str);
-
- }
-
- iconv_close(cd);
-
- }
-
- }
-
- free(outbuf);
-
-}
-
-static void _read_attribute_value (VFormatAttribute *attr, char **p, int format_encoding, GString *charset)
-{
- char *lp = *p;
- GString *str;
-
- /* read in the value */
- str = g_string_new ("");
- while (*lp != '\r' && *lp != '\0') {
- if (*lp == '=' && format_encoding == VF_ENCODING_QP) {
- char a, b, x1=0, x2=0;
-
- if ((a = *(++lp)) == '\0') break;
- if ((b = *(++lp)) == '\0') break;
-
- if (isalnum(a)) {
- if (isalnum(b)) {
- /* e.g. ...N=C3=BCrnberg\r\n
- * ^^^
- */
- x1=a;
- x2=b;
- }
- else if (b == '=') {
- /* e.g. ...N=C=\r\n
- * ^^^
- * 3=BCrnberg...
- * ^
- */
- char *tmplp = lp;
- if (*(++tmplp) == '\r' && *(++tmplp) == '\n' && isalnum(*(++tmplp))) {
- x1 = a;
- x2 = *tmplp;
- lp = tmplp;
- }
- }
- else {
- /* append malformed input, and
- continue parsing */
- str = g_string_append_c(str, a);
- str = g_string_append_c(str, b);
- }
- }
- else if (a == '=') {
- char *tmplp = lp;
- char c, d, e;
- c = *(++tmplp);
- d = *(++tmplp);
- e = *(++tmplp);
- if (b == '\r' && c == '\n' && isalnum(d) && isalnum(e)) {
- x1 = d;
- x2 = e;
- lp = tmplp;
- }
- else {
- /* append malformed input, and
- continue parsing */
- str = g_string_append_c(str, a);
- str = g_string_append_c(str, b);
- }
- }
- else {
- /* append malformed input, and
- continue parsing */
- str = g_string_append_c(str, a);
- str = g_string_append_c(str, b);
- }
- if (x1 && x2) {
- char c;
-
- a = tolower (x1);
- b = tolower (x2);
-
- 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);
- }
- lp++;
- x1 = x2 = 0;
- }
- else if (format_encoding == VF_ENCODING_BASE64) {
- if((*lp != ' ') && (*lp != '\t') )
- str = g_string_append_unichar (str, g_utf8_get_char (lp));
- lp = g_utf8_next_char(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 ',':
- if (!strcmp (attr->name, "CATEGORIES")) {
- //We need to handle categories here to work
- //aroung a bug in evo2
- _read_attribute_value_add (attr, str, charset);
- g_string_assign (str, "");
- } else
- str = g_string_append_c (str, ',');
- break;
- case '\\': str = g_string_append_c (str, '\\'); break;
- case '"': str = g_string_append_c (str, '"'); break;
- /* \t is (incorrectly) used by kOrganizer, so handle it here */
- case 't': str = g_string_append_c (str, '\t'); break;
- default:
- osync_trace(TRACE_INTERNAL, "invalid escape, passing it through. escaped char was %i", *lp);
- 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 == ';') ||
- (*lp == ',' && !strcmp (attr->name, "CATEGORIES"))) {
- _read_attribute_value_add (attr, str, charset);
- 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) {
- _read_attribute_value_add (attr, str, charset);
- 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(VFormatAttribute *attr, char **p, int *format_encoding, GString **charset)
-{
- char *lp = *p;
- GString *str;
- VFormatParam *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 == '_' || *lp == '/' || *lp == '.' || *lp == ' ') {
- str = g_string_append_unichar (str, g_utf8_get_char (lp));
- lp = g_utf8_next_char (lp);
- }
- /* 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.)
- */
- else if (*lp == '=') {
- if (str->len > 0) {
- param = vformat_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) {
- vformat_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) {
- vformat_attribute_param_free (param);
- param = NULL;
- if (!colon)
- lp = g_utf8_next_char (lp);
- }
- }
-
- if (param
- && !g_ascii_strcasecmp (param->name, "encoding")) {
- if (!g_ascii_strcasecmp (param->values->data, "quoted-printable")) {
- *format_encoding = VF_ENCODING_QP;
- vformat_attribute_param_free (param);
- param = NULL;
- } else if ( _helper_is_base64(param->values->data)) {
- *format_encoding = VF_ENCODING_BASE64;
-// vformat_attribute_param_free (param);
-// param = NULL;
- }
- } else if (param && !g_ascii_strcasecmp(param->name, "charset")) {
- *charset = g_string_new(param->values->data);
- vformat_attribute_param_free (param);
- param = NULL;
- }
- }
- else {
- if (str->len > 0) {
- char *param_name;
- if (!g_ascii_strcasecmp (str->str,
- "quoted-printable")) {
- param_name = "ENCODING";
- *format_encoding = VF_ENCODING_QP;
- }
- /* apple's broken addressbook app outputs naked BASE64
- parameters, which aren't even vcard 3.0 compliant. */
- else if (!g_ascii_strcasecmp (str->str,
- "base64")) {
- param_name = "ENCODING";
- g_string_assign (str, "b");
- *format_encoding = VF_ENCODING_BASE64;
- }
- else {
- param_name = "TYPE";
- }
-
- if (param_name) {
- param = vformat_attribute_param_new (param_name);
- vformat_attribute_param_add_value (param, str->str);
- }
- g_string_assign (str, "");
- if (!colon)
- lp = g_utf8_next_char (lp);
- }
- else {
- /* we've got an attribute with a truly empty
- attribute parameter. So it's of the form:
-
- ATTR;[PARAM=value;]*;[PARAM=value;]*:
-
- (note the extra ';')
-
- the only thing to do here is, well.. nothing.
- we skip over the character if it's not a colon,
- and the rest is handled for us: We'll either
- continue through the loop again if we hit a ';',
- or we'll break out correct below if it was a ':' */
- if (!colon)
- lp = g_utf8_next_char (lp);
- }
- }
- if (param && !comma) {
- vformat_attribute_add_param (attr, param);
- param = NULL;
- }
- if (colon)
- break;
- }
- else {
- osync_trace(TRACE_INTERNAL, "invalid character found in parameter spec: \"%i\" String so far: %s", lp[0], str->str);
- 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 VFormatAttribute *_read_attribute (char **p)
-{
- char *attr_group = NULL;
- char *attr_name = NULL;
- VFormatAttribute *attr = NULL;
- GString *str, *charset = NULL;
- 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) {
- osync_trace(TRACE_INTERNAL, "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 == '_' || *lp == '/') {
- str = g_string_append_unichar (str, g_utf8_get_char (lp));
- }
- else {
- osync_trace(TRACE_INTERNAL, "invalid character found in attribute group/name: \"%i\" String so far: %s", lp[0], str->str);
- 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 = vformat_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, &charset);
- }
- if (*lp == ':') {
- /* skip past the ':' */
- lp = g_utf8_next_char(lp);
- _read_attribute_value (attr, &lp, is_qp, charset);
- }
-
- if (charset) g_string_free(charset, TRUE);
- *p = lp;
-
- if (!attr->values)
- goto lose;
-
- return attr;
- lose:
- if (attr)
- vformat_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(VFormat *evc, const char *str)
-{
- char *buf = g_strdup (str);
- char *p, *end;
- VFormatAttribute *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 */
- osync_trace(TRACE_INTERNAL, "invalid utf8 passed to VFormat. Limping along.");
- *end = '\0';
- }
-
- buf = _fold_lines (buf);
-
- p = buf;
-
- attr = _read_attribute (&p);
- if (!attr)
- attr = _read_attribute (&p);
-
- if (!attr || attr->group || g_ascii_strcasecmp (attr->name, "begin")) {
- osync_trace(TRACE_INTERNAL, "vformat began without a BEGIN\n");
- }
- if (attr && !g_ascii_strcasecmp (attr->name, "begin"))
- vformat_attribute_free (attr);
- else if (attr)
- vformat_add_attribute (evc, attr);
-
- while (*p) {
- VFormatAttribute *next_attr = _read_attribute (&p);
-
- if (next_attr) {
- //if (g_ascii_strcasecmp (next_attr->name, "end"))
- vformat_add_attribute (evc, next_attr);
- attr = next_attr;
- }
- }
-
- if (!attr || attr->group || g_ascii_strcasecmp (attr->name, "end")) {
- osync_trace(TRACE_INTERNAL, "vformat ended without END");
- }
-
- g_free (buf);
-}
-
-char *vformat_escape_string (const char *s, VFormatType type)
-{
- GString *str;
- const char *p;
-
- str = g_string_new ("");
-
- /* 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 ',':
- if (type == VFORMAT_CARD_30 || type == VFORMAT_EVENT_20 || type == VFORMAT_TODO_20)
- str = g_string_append (str, "\\,");
- else
- str = g_string_append_c (str, *p);
- break;
- case '\\':
- /**
- * We won't escape backslashes
- * on vcard 2.1, unless it is in the end of a value.
- * See comments above for a better explanation
- **/
- if (*p != '\0' && type == VFORMAT_CARD_21) {
- osync_trace(TRACE_INTERNAL, "[%s]We won't escape backslashes", __func__);
- str = g_string_append_c(str, *p);
- }
- else {
- osync_trace(TRACE_INTERNAL, "[%s] escape backslashes!!", __func__);
- str = g_string_append (str, "\\\\");
- }
- break;
- default:
- str = g_string_append_c (str, *p);
- break;
- }
- }
-
- return g_string_free (str, FALSE);
-}
-
-char*
-vformat_unescape_string (const char *s)
-{
- GString *str;
- const char *p;
-
- g_return_val_if_fail (s != NULL, NULL);
-
- str = g_string_new ("");
-
- /* Unescape a string as described in RFC2426, section 4 (Formal Grammar) */
- 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;
- case '"': str = g_string_append_c (str, '"'); break;
- /* \t is (incorrectly) used by kOrganizer, so handle it here */
- case 't': str = g_string_append_c (str, '\t'); break;
- default:
- osync_trace(TRACE_INTERNAL, "invalid escape, passing it through. escaped char was %s", *p);
- str = g_string_append_c (str, '\\');
- str = g_string_append_unichar (str, g_utf8_get_char(p));
- break;
- }
- }
- }
-
- return g_string_free (str, FALSE);
-}
-
-void
-vformat_construct (VFormat *evc, const char *str)
-{
- g_return_if_fail (str != NULL);
-
- if (*str)
- _parse (evc, str);
-}
-
-void vformat_free(VFormat *format)
-{
- g_list_foreach (format->attributes, (GFunc)vformat_attribute_free, NULL);
- g_list_free (format->attributes);
- g_free(format);
-}
-
-VFormat *vformat_new_from_string (const char *str)
-{
- g_return_val_if_fail (str != NULL, NULL);
- VFormat *evc = g_malloc0(sizeof(VFormat));
-
- vformat_construct (evc, str);
-
- return evc;
-}
-
-VFormat *vformat_new(void)
-{
- return vformat_new_from_string ("");
-}
-
-VFormatAttribute *vformat_find_attribute(VFormat *vcard, const char *name)
-{
- GList *attributes = vformat_get_attributes(vcard);
- GList *a = NULL;
- for (a = attributes; a; a = a->next) {
- VFormatAttribute *attr = a->data;
- if (!strcmp(vformat_attribute_get_name(attr), name)) {
- return attr;
- }
- }
- return NULL;
-}
-
-char *vformat_to_string (VFormat *evc, VFormatType type)
-{
- osync_trace(TRACE_ENTRY, "%s(%p, %i)", __func__, type);
- GList *l;
- GList *v;
-
- GString *str = g_string_new ("");
-
- switch (type) {
- case VFORMAT_CARD_21:
- str = g_string_append (str, "BEGIN:VCARD\r\nVERSION:2.1\r\n");
- break;
- case VFORMAT_CARD_30:
- str = g_string_append (str, "BEGIN:VCARD\r\nVERSION:3.0\r\n");
- break;
- case VFORMAT_TODO_10:
- case VFORMAT_EVENT_10:
- str = g_string_append (str, "BEGIN:VCALENDAR\r\nVERSION:1.0\r\n");
- break;
- case VFORMAT_TODO_20:
- case VFORMAT_EVENT_20:
- str = g_string_append (str, "BEGIN:VCALENDAR\r\nVERSION:2.0\r\n");
- break;
- case VFORMAT_NOTE:
- str = g_string_append (str, "BEGIN:VNOTE\r\nVERSION:1.1\r\n");
- break;
- }
-
- for (l = evc->attributes; l; l = l->next) {
- GList *p;
- VFormatAttribute *attr = l->data;
- GString *attr_str;
- int l;
- int format_encoding = VF_ENCODING_RAW;
-
- 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) {
- VFormatParam *param = p->data;
- /* 5.8.2:
- * param = param-name "=" param-value *("," param-value)
- */
- if( type == VFORMAT_CARD_30 || type == VFORMAT_TODO_20
- || type == VFORMAT_EVENT_20) {
-
- /**
- * Character set can only be specified on the CHARSET
- * parameter on the Content-Type MIME header field.
- **/
- 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) {
- attr_str = g_string_append_c (attr_str, '=');
- }
- for (v = param->values; v; v = v->next) {
- if (_helper_is_base64((const char *) v->data)) {
- format_encoding = VF_ENCODING_BASE64;
- /*Only the "B" encoding of [RFC 2047] is an allowed*/
- v->data="B";
- }
- /**
- * QUOTED-PRINTABLE inline encoding has been
- * eliminated.
- **/
- if (!g_ascii_strcasecmp (param->name, "ENCODING") && !g_ascii_strcasecmp ((char *) v->data, "QUOTED-PRINTABLE")) {
- osync_trace(TRACE_ERROR, "%s false encoding QUOTED-PRINTABLE is not allowed", __func__);
- format_encoding = VF_ENCODING_QP;
- }
- attr_str = g_string_append (attr_str, v->data);
-
- if (v->next)
- attr_str = g_string_append_c (attr_str, ',');
- }
- }
- else {
- attr_str = g_string_append_c (attr_str, ';');
- /**
- * The "TYPE=" is optional skip it.
- * LOGO, PHOTO and SOUND multimedia formats MUST
- * have a "TYPE=" parameter
- **/
- gboolean must_have_type = FALSE;
- if (!g_ascii_strcasecmp (attr->name, "PHOTO") || !g_ascii_strcasecmp (attr->name, "LOGO") || !g_ascii_strcasecmp (attr->name, "SOUND") )
- must_have_type = TRUE;
- if ( must_have_type || g_ascii_strcasecmp (param->name, "TYPE") )
- attr_str = g_string_append (attr_str, param->name);
- if ( param->values && (must_have_type || g_ascii_strcasecmp (param->name, "TYPE")) )
- attr_str = g_string_append_c (attr_str, '=');
- for (v = param->values; v; v = v->next) {
- // check for quoted-printable encoding
- if (!g_ascii_strcasecmp (param->name, "ENCODING") && !g_ascii_strcasecmp ((char *) v->data, "QUOTED-PRINTABLE"))
- format_encoding = VF_ENCODING_QP;
- // check for base64 encoding
- if (_helper_is_base64((const char *) v->data)) {
- format_encoding = VF_ENCODING_BASE64;
- v->data="BASE64";
- }
- attr_str = g_string_append (attr_str, v->data);
- 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;
-
- if (!strcmp (attr->name, "RRULE") &&
- strstr (value, "BYDAY") == v->data) {
- attr_str = g_string_append (attr_str, value);
- } else {
- escaped_value = vformat_escape_string (value, type);
- 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);
- }
-
- /* Folding lines:
- * ^^^^^^^^^^^^^^
- *
- * rfc 2426 (vCard), 2.6 Line Delimiting and Folding:
- * After generating a content line,
- * lines longer than 75 characters SHOULD be folded according to the
- * folding procedure described in [MIME-DIR].
- *
- * rfc 2445 (iCalendar), 4.1 Content Lines:
- * Lines of text SHOULD NOT be longer than 75 octets, excluding the line
- * break. Long content lines SHOULD be split into a multiple line
- * representations using a line "folding" technique. That is, a long
- * line can be split between any two characters by inserting a CRLF
- * immediately followed by a single linear white space character (i.e.,
- * SPACE, US-ASCII decimal 32 or HTAB, US-ASCII decimal 9). Any sequence
- * of CRLF followed immediately by a single linear white space character
- * is ignored (i.e., removed) when processing the content type.
- *
- * SUMMARY: When generating a content line, lines longer then 75 characters SHOULD be folded!
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- *
- * Differences between encodings:
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- *
- * rfc 2425 [MIME-DIR], 5.8.1:
- * A logical line MAY be continued on the next physical line anywhere
- * between two characters by inserting a CRLF immediately followed by a
- * single <WS> (white space) character.
- *
- * rfc 2045, 6.7, chapter 5:
- * The quoted-printable specs says that softbreaks should be generated by inserting a =\r\n
- * without follwing <WS>
- *
- * UTF-8
- * ^^^^^
- *
- * Note that all the line folding above is described in terms of characters
- * not bytes. In particular, it would be an error to put a line break
- * within a UTF-8 character.
- */
-
- l = 0;
- do {
- if (g_utf8_strlen(attr_str->str, attr_str->len) - l > 75) {
- l += 75;
-
- /* If using QP, must be sure that we do not fold within a quote sequence */
- if (format_encoding == VF_ENCODING_QP) {
- if (g_utf8_get_char(g_utf8_offset_to_pointer(attr_str->str, l-1)) == '=') l--;
- else if (g_utf8_get_char(g_utf8_offset_to_pointer(attr_str->str, l-2)) == '=') l -= 2;
- }
-
- char *p = g_utf8_offset_to_pointer(attr_str->str, l);
-
- if (format_encoding == VF_ENCODING_QP)
- attr_str = g_string_insert_len (attr_str, p - attr_str->str, "=" CRLF "", sizeof ("=" CRLF "") - 1);
- else
- attr_str = g_string_insert_len (attr_str, p - attr_str->str, CRLF " ", sizeof (CRLF " ") - 1);
- }
- else
- break;
- } while (l < g_utf8_strlen(attr_str->str, attr_str->len));
-
- attr_str = g_string_append (attr_str, CRLF);
- /**
- * base64= <MIME RFC 1521 base64 text>
- * the end of the text is marked with two CRLF sequences
- * this results in one blank line before the start of the
- * next property
- **/
- if( format_encoding == VF_ENCODING_BASE64
- && (type == VFORMAT_CARD_21))
- attr_str = g_string_append (attr_str, CRLF);
-
- str = g_string_append (str, attr_str->str);
- g_string_free (attr_str, TRUE);
- }
-
- switch (type) {
- case VFORMAT_CARD_21:
- str = g_string_append (str, "END:VCARD\r\n");
- break;
- case VFORMAT_CARD_30:
- str = g_string_append (str, "END:VCARD\r\n");
- break;
- case VFORMAT_TODO_10:
- case VFORMAT_EVENT_10:
- str = g_string_append (str, "END:VCALENDAR\r\n");
- break;
- case VFORMAT_TODO_20:
- case VFORMAT_EVENT_20:
- str = g_string_append (str, "END:VCALENDAR\r\n");
- break;
- case VFORMAT_NOTE:
- str = g_string_append (str, "END:VNOTE\r\n");
- break;
- }
-
- osync_trace(TRACE_EXIT, "%s(%p, %i)", __func__, type);
- return g_string_free (str, FALSE);
-}
-
-void vformat_dump_structure (VFormat *evc)
-{
- GList *a;
- GList *v;
- int i;
-
- printf ("VFormat\n");
- for (a = evc->attributes; a; a = a->next) {
- GList *p;
- VFormatAttribute *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++) {
- VFormatParam *param = p->data;
- printf (" | [%d] = %s", i,param->name);
- printf ("(");
- for (v = param->values; v; v = v->next) {
- char *value = vformat_escape_string ((char*)v->data, VFORMAT_CARD_21);
- 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);
- }
- }
-}
-
-VFormatAttribute *vformat_attribute_new (const char *attr_group, const char *attr_name)
-{
- VFormatAttribute *attr;
-
- attr = g_new0 (VFormatAttribute, 1);
-
- attr->group = g_strdup (attr_group);
- attr->name = g_strdup (attr_name);
-
- return attr;
-}
-
-void
-vformat_attribute_free (VFormatAttribute *attr)
-{
- g_return_if_fail (attr != NULL);
-
- g_free (attr->group);
- g_free (attr->name);
-
- vformat_attribute_remove_values (attr);
-
- vformat_attribute_remove_params (attr);
-
- g_free (attr);
-}
-
-VFormatAttribute*
-vformat_attribute_copy (VFormatAttribute *attr)
-{
- VFormatAttribute *a;
- GList *p;
-
- g_return_val_if_fail (attr != NULL, NULL);
-
- a = vformat_attribute_new (vformat_attribute_get_group (attr),
- vformat_attribute_get_name (attr));
-
- for (p = attr->values; p; p = p->next)
- vformat_attribute_add_value (a, p->data);
-
- for (p = attr->params; p; p = p->next)
- vformat_attribute_add_param (a, vformat_attribute_param_copy (p->data));
-
- return a;
-}
-
-void
-vformat_remove_attributes (VFormat *evc, const char *attr_group, const char *attr_name)
-{
- GList *attr;
-
- g_return_if_fail (attr_name != NULL);
-
- attr = evc->attributes;
- while (attr) {
- GList *next_attr;
- VFormatAttribute *a = attr->data;
-
- next_attr = attr->next;
-
- if (((!attr_group && !a->group) ||
- (attr_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->attributes = g_list_remove_link (evc->attributes, attr);
-
- vformat_attribute_free (a);
- }
-
- attr = next_attr;
- }
-}
-
-void
-vformat_remove_attribute (VFormat *evc, VFormatAttribute *attr)
-{
- g_return_if_fail (attr != NULL);
-
- evc->attributes = g_list_remove (evc->attributes, attr);
- vformat_attribute_free (attr);
-}
-
-void
-vformat_add_attribute (VFormat *evc, VFormatAttribute *attr)
-{
- g_return_if_fail (attr != NULL);
-
- evc->attributes = g_list_append (evc->attributes, attr);
-}
-
-void
-vformat_add_attribute_with_value (VFormat *VFormat,
- VFormatAttribute *attr, const char *value)
-{
- g_return_if_fail (attr != NULL);
-
- vformat_attribute_add_value (attr, value);
-
- vformat_add_attribute (VFormat, attr);
-}
-
-void
-vformat_add_attribute_with_values (VFormat *VFormat, VFormatAttribute *attr, ...)
-{
- va_list ap;
- char *v;
-
- g_return_if_fail (attr != NULL);
-
- va_start (ap, attr);
-
- while ((v = va_arg (ap, char*))) {
- vformat_attribute_add_value (attr, v);
- }
-
- va_end (ap);
-
- vformat_add_attribute (VFormat, attr);
-}
-
-void
-vformat_attribute_add_value (VFormatAttribute *attr, const char *value)
-{
- g_return_if_fail (attr != NULL);
-
- attr->values = g_list_append (attr->values, g_strdup (value));
-}
-
-void
-vformat_attribute_add_value_decoded (VFormatAttribute *attr, const char *value, int len)
-{
- g_return_if_fail (attr != NULL);
-
- switch (attr->encoding) {
- case VF_ENCODING_RAW:
- osync_trace(TRACE_INTERNAL, "can't add_value_decoded with an attribute using RAW encoding. you must set the ENCODING parameter first");
- break;
- case VF_ENCODING_BASE64: {
- char *b64_data = base64_encode_simple (value, len);
- GString *decoded = g_string_new_len (value, len);
-
- /* make sure the decoded list is up to date */
- vformat_attribute_get_values_decoded (attr);
-
- attr->values = g_list_append (attr->values, b64_data);
- attr->decoded_values = g_list_append (attr->decoded_values, decoded);
- break;
- }
- case VF_ENCODING_QP: {
- char *qp_data = quoted_encode_simple ((unsigned char*)value, len);
- GString *decoded = g_string_new (value);
-
- /* make sure the decoded list is up to date */
- vformat_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;
- }
- case VF_ENCODING_8BIT: {
- char *data = g_strdup(value);
- GString *decoded = g_string_new (value);
-
- /* make sure the decoded list is up to date */
- vformat_attribute_get_values_decoded (attr);
-
- attr->values = g_list_append (attr->values, data);
- attr->decoded_values = g_list_append (attr->decoded_values, decoded);
- break;
- }
- }
-}
-
-void
-vformat_attribute_add_values (VFormatAttribute *attr, ...)
-{
- va_list ap;
- char *v;
-
- g_return_if_fail (attr != NULL);
-
- va_start (ap, attr);
-
- while ((v = va_arg (ap, char*))) {
- vformat_attribute_add_value (attr, v);
- }
-
- va_end (ap);
-}
-
-static void
-free_gstring (GString *str)
-{
- g_string_free (str, TRUE);
-}
-
-void
-vformat_attribute_remove_values (VFormatAttribute *attr)
-{
- g_return_if_fail (attr != NULL);
-
- g_list_foreach (attr->values, (GFunc)g_free, NULL);
- g_list_free (attr->values);
- attr->values = NULL;
-
- g_list_foreach (attr->decoded_values, (GFunc)free_gstring, NULL);
- g_list_free (attr->decoded_values);
- attr->decoded_values = NULL;
-}
-
-void
-vformat_attribute_remove_params (VFormatAttribute *attr)
-{
- g_return_if_fail (attr != NULL);
-
- g_list_foreach (attr->params, (GFunc)vformat_attribute_param_free, NULL);
- g_list_free (attr->params);
- attr->params = NULL;
-
- /* also remove the cached encoding on this attribute */
- attr->encoding_set = FALSE;
- attr->encoding = VF_ENCODING_RAW;
-}
-
-VFormatParam*
-vformat_attribute_param_new (const char *name)
-{
- VFormatParam *param = g_new0 (VFormatParam, 1);
- param->name = g_strdup (name);
-
- return param;
-}
-
-void
-vformat_attribute_param_free (VFormatParam *param)
-{
- g_return_if_fail (param != NULL);
-
- g_free (param->name);
-
- vformat_attribute_param_remove_values (param);
-
- g_free (param);
-}
-
-VFormatParam*
-vformat_attribute_param_copy (VFormatParam *param)
-{
- VFormatParam *p;
- GList *l;
-
- g_return_val_if_fail (param != NULL, NULL);
-
- p = vformat_attribute_param_new (vformat_attribute_param_get_name (param));
-
- for (l = param->values; l; l = l->next) {
- vformat_attribute_param_add_value (p, l->data);
- }
-
- return p;
-}
-
-void
-vformat_attribute_add_param (VFormatAttribute *attr,
- VFormatParam *param)
-{
- g_return_if_fail (attr != NULL);
- g_return_if_fail (param != NULL);
-
- attr->params = g_list_append (attr->params, param);
-
- /* we handle our special encoding stuff here */
-
- if (!g_ascii_strcasecmp (param->name, "ENCODING")) {
- if (attr->encoding_set) {
- osync_trace(TRACE_INTERNAL, "ENCODING specified twice");
- return;
- }
-
- if (param->values && param->values->data) {
- if (_helper_is_base64((const char*)param->values->data))
- attr->encoding = VF_ENCODING_BASE64;
- else if (!g_ascii_strcasecmp ((char*)param->values->data, "QUOTED-PRINTABLE"))
- attr->encoding = VF_ENCODING_QP;
- else if (!g_ascii_strcasecmp ((char *)param->values->data, "8BIT"))
- attr->encoding = VF_ENCODING_8BIT;
- else {
- osync_trace(TRACE_INTERNAL, "Unknown value `%s' for ENCODING parameter. values will be treated as raw",
- (char*)param->values->data);
- }
-
- attr->encoding_set = TRUE;
- }
- else {
- osync_trace(TRACE_INTERNAL, "ENCODING parameter added with no value");
- }
- }
-}
-
-VFormatParam *vformat_attribute_find_param(VFormatAttribute *attr, const char *name)
-{
- g_return_val_if_fail (attr != NULL, NULL);
- GList *p = NULL;
- for (p = attr->params; p; p = p->next) {
- VFormatParam *param = p->data;
- if (!g_ascii_strcasecmp (param->name, name))
- return param;
- }
- return NULL;
-}
-
-void
-vformat_attribute_set_value (VFormatAttribute *attr,
- int nth, const char *value)
-{
- GList *param = g_list_nth(attr->values, nth);
- g_free(param->data);
- param->data = g_strdup(value);
-}
-
-void
-vformat_attribute_param_add_value (VFormatParam *param,
- const char *value)
-{
- g_return_if_fail (param != NULL);
-
- param->values = g_list_append (param->values, g_strdup (value));
-}
-
-void
-vformat_attribute_param_add_values (VFormatParam *param,
- ...)
-{
- va_list ap;
- char *v;
-
- g_return_if_fail (param != NULL);
-
- va_start (ap, param);
-
- while ((v = va_arg (ap, char*))) {
- vformat_attribute_param_add_value (param, v);
- }
-
- va_end (ap);
-}
-
-void
-vformat_attribute_add_param_with_value (VFormatAttribute *attr, const char *name, const char *value)
-{
- g_return_if_fail (attr != NULL);
- g_return_if_fail (name != NULL);
-
- if (!value)
- return;
-
- VFormatParam *param = vformat_attribute_param_new(name);
-
- vformat_attribute_param_add_value (param, value);
-
- vformat_attribute_add_param (attr, param);
-}
-
-void
-vformat_attribute_add_param_with_values (VFormatAttribute *attr,
- VFormatParam *param, ...)
-{
- va_list ap;
- char *v;
-
- g_return_if_fail (attr != NULL);
- g_return_if_fail (param != NULL);
-
- va_start (ap, param);
-
- while ((v = va_arg (ap, char*))) {
- vformat_attribute_param_add_value (param, v);
- }
-
- va_end (ap);
-
- vformat_attribute_add_param (attr, param);
-}
-
-void
-vformat_attribute_param_remove_values (VFormatParam *param)
-{
- g_return_if_fail (param != NULL);
-
- g_list_foreach (param->values, (GFunc)g_free, NULL);
- g_list_free (param->values);
- param->values = NULL;
-}
-
-GList*
-vformat_get_attributes (VFormat *format)
-{
- return format->attributes;
-}
-
-const char*
-vformat_attribute_get_group (VFormatAttribute *attr)
-{
- g_return_val_if_fail (attr != NULL, NULL);
-
- return attr->group;
-}
-
-const char*
-vformat_attribute_get_name (VFormatAttribute *attr)
-{
- g_return_val_if_fail (attr != NULL, NULL);
-
- return attr->name;
-}
-
-GList*
-vformat_attribute_get_values (VFormatAttribute *attr)
-{
- g_return_val_if_fail (attr != NULL, NULL);
-
- return attr->values;
-}
-
-GList*
-vformat_attribute_get_values_decoded (VFormatAttribute *attr)
-{
- g_return_val_if_fail (attr != NULL, NULL);
-
- if (!attr->decoded_values) {
- GList *l;
- switch (attr->encoding) {
- case VF_ENCODING_RAW:
- case VF_ENCODING_8BIT:
- 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 VF_ENCODING_BASE64:
- for (l = attr->values; l; l = l->next) {
- char *decoded = g_strdup ((char*)l->data);
- int len = 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 VF_ENCODING_QP:
- for (l = attr->values; l; l = l->next) {
- if (!(l->data))
- continue;
- char *decoded = g_strdup ((char*)l->data);
- int len = 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;
- }
- }
-
- return attr->decoded_values;
-}
-
-gboolean
-vformat_attribute_is_single_valued (VFormatAttribute *attr)
-{
- g_return_val_if_fail (attr != NULL, FALSE);
-
- if (attr->values == NULL
- || attr->values->next != NULL)
- return FALSE;
-
- return TRUE;
-}
-
-char*
-vformat_attribute_get_value (VFormatAttribute *attr)
-{
- GList *values;
-
- g_return_val_if_fail (attr != NULL, NULL);
-
- values = vformat_attribute_get_values (attr);
-
- if (!vformat_attribute_is_single_valued (attr))
- osync_trace(TRACE_INTERNAL, "vformat_attribute_get_value called on multivalued attribute");
-
- return values ? g_strdup ((char*)values->data) : NULL;
-}
-
-GString*
-vformat_attribute_get_value_decoded (VFormatAttribute *attr)
-{
- GList *values;
- GString *str = NULL;
-
- g_return_val_if_fail (attr != NULL, NULL);
-
- values = vformat_attribute_get_values_decoded (attr);
-
- if (!vformat_attribute_is_single_valued (attr))
- osync_trace(TRACE_INTERNAL, "vformat_attribute_get_value_decoded called on multivalued attribute");
-
- if (values)
- str = values->data;
-
- return str ? g_string_new_len (str->str, str->len) : NULL;
-}
-
-const char *vformat_attribute_get_nth_value(VFormatAttribute *attr, int nth)
-{
- GList *values = vformat_attribute_get_values_decoded(attr);
- if (!values)
- return NULL;
- GString *retstr = (GString *)g_list_nth_data(values, nth);
- if (!retstr)
- return NULL;
-
- if (!g_utf8_validate(retstr->str, -1, NULL)) {
- values = vformat_attribute_get_values(attr);
- if (!values)
- return NULL;
- return g_list_nth_data(values, nth);
- }
-
- return retstr->str;
-}
-
-gboolean
-vformat_attribute_has_type (VFormatAttribute *attr, const char *typestr)
-{
- GList *params;
- GList *p;
-
- g_return_val_if_fail (attr != NULL, FALSE);
- g_return_val_if_fail (typestr != NULL, FALSE);
-
- params = vformat_attribute_get_params (attr);
-
- for (p = params; p; p = p->next) {
- VFormatParam *param = p->data;
-
- if (!strcasecmp (vformat_attribute_param_get_name (param), "TYPE")) {
- GList *values = vformat_attribute_param_get_values (param);
- GList *v;
-
- for (v = values; v; v = v->next) {
- if (!strcasecmp ((char*)v->data, typestr))
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-
-gboolean vformat_attribute_has_param(VFormatAttribute *attr, const char *name)
-{
- g_return_val_if_fail (attr != NULL, FALSE);
- g_return_val_if_fail (name != NULL, FALSE);
-
- GList *params = vformat_attribute_get_params(attr);
- GList *p;
- for (p = params; p; p = p->next) {
- VFormatParam *param = p->data;
- if (!strcasecmp(name, vformat_attribute_param_get_name(param)))
- return TRUE;
- }
- return FALSE;
-}
-
-GList*
-vformat_attribute_get_params (VFormatAttribute *attr)
-{
- g_return_val_if_fail (attr != NULL, NULL);
-
- return attr->params;
-}
-
-const char*
-vformat_attribute_param_get_name (VFormatParam *param)
-{
- g_return_val_if_fail (param != NULL, NULL);
-
- return param->name;
-}
-
-GList*
-vformat_attribute_param_get_values (VFormatParam *param)
-{
- g_return_val_if_fail (param != NULL, NULL);
-
- return param->values;
-}
-
-const char *vformat_attribute_param_get_nth_value(VFormatParam *param, int nth)
-{
- const char *ret = NULL;
- GList *values = vformat_attribute_param_get_values(param);
- if (!values)
- return NULL;
- ret = g_list_nth_data(values, nth);
- return ret;
-}
-
-static const char *base64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-//static unsigned char _evc_base64_rank[256];
-
-static void base64_init(char *rank)
-{
- int i;
-
- memset(rank, 0xff, sizeof(rank));
- for (i=0;i<64;i++) {
- rank[(unsigned int)base64_alphabet[i]] = i;
- }
- rank['='] = 0;
-}
-
-/* call this when finished encoding everything, to
- flush off the last little bit */
-static size_t 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 += base64_encode_step(in, inlen, break_lines, outptr, state, save);
-
- c1 = ((unsigned char *)save)[1];
- c2 = ((unsigned char *)save)[2];
-
- switch (((char *)save)[0]) {
- case 2:
- outptr[2] = base64_alphabet[ ( (c2 &0x0f) << 2 ) ];
- g_assert(outptr[2] != 0);
- goto skip;
- case 1:
- outptr[2] = '=';
- skip:
- outptr[0] = base64_alphabet[ c1 >> 2 ];
- outptr[1] = 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 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 (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++ = base64_alphabet[ c1 >> 2 ];
- *outptr++ = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 ) ];
- *outptr++ = base64_alphabet[ ( (c2 &0x0f) << 2 ) | (c3 >> 6) ];
- *outptr++ = 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 (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;
- }
-
- 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 base64_decode_step(unsigned char *in, size_t len, unsigned char *out, int *state, unsigned int *save)
-{
- unsigned char base64_rank[256];
- base64_init((char*)base64_rank);
-
- 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 = 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 (base64_rank[*inptr] != 0xff) {
- if (*inptr == '=' && outptr>out)
- outptr--;
- i--;
- }
- }
-
- /* if i!= 0 then there is a truncation error! */
- return outptr-out;
-}
-
-char *base64_encode_simple (const char *data, size_t len)
-{
- unsigned char *out;
- int state = 0, outlen;
- unsigned int save = 0;
-
- g_return_val_if_fail (data != NULL, NULL);
-
- out = g_malloc (len * 4 / 3 + 5);
- outlen = base64_encode_close ((unsigned char *)data, len, FALSE,
- out, &state, (int*)&save);
- out[outlen] = '\0';
- return (char *)out;
-}
-
-size_t base64_decode_simple (char *data, size_t len)
-{
- int state = 0;
- unsigned int save = 0;
-
- g_return_val_if_fail (data != NULL, 0);
-
- return base64_decode_step ((unsigned char *)data, len,
- (unsigned char *)data, &state, &save);
-}
-
-char *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 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);
-}