diff options
| author | Michele Calgaro <michele.calgaro@yahoo.it> | 2020-09-11 14:38:47 +0900 |
|---|---|---|
| committer | Michele Calgaro <michele.calgaro@yahoo.it> | 2020-09-11 14:38:47 +0900 |
| commit | 884c8093d63402a1ad0b502244b791e3c6782be3 (patch) | |
| tree | a600d4ab0d431a2bdfe4c15b70df43c14fbd8dd0 /debian/opensync/opensync-0.22/formats/vformats-xml/xml-vcard.c | |
| parent | 14e1aa2006796f147f3f4811fb908a6b01e79253 (diff) | |
| download | extra-dependencies-884c8093d63402a1ad0b502244b791e3c6782be3.tar.gz extra-dependencies-884c8093d63402a1ad0b502244b791e3c6782be3.zip | |
Added debian extra dependency packages.
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
Diffstat (limited to 'debian/opensync/opensync-0.22/formats/vformats-xml/xml-vcard.c')
| -rw-r--r-- | debian/opensync/opensync-0.22/formats/vformats-xml/xml-vcard.c | 1405 |
1 files changed, 1405 insertions, 0 deletions
diff --git a/debian/opensync/opensync-0.22/formats/vformats-xml/xml-vcard.c b/debian/opensync/opensync-0.22/formats/vformats-xml/xml-vcard.c new file mode 100644 index 00000000..a577ed86 --- /dev/null +++ b/debian/opensync/opensync-0.22/formats/vformats-xml/xml-vcard.c @@ -0,0 +1,1405 @@ +/* + * xml-vcard - A plugin for parsing vcard objects for the opensync framework + * Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org> + * + * 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 + * + */ + +#include "xml-support.h" +#include "vformat.h" +#include "xml-vcard.h" +#include <opensync/opensync_xml.h> +#include <glib.h> + +static const char * rewrite_mime_type(const char * source_format, int use_iana); +static int _helper_is_base64(const char *); + +static void handle_unknown_parameter(xmlNode *current, VFormatParam *param) +{ + osync_trace(TRACE_INTERNAL, "Handling unknown parameter %s", vformat_attribute_param_get_name(param)); + xmlNode *property = xmlNewTextChild(current, NULL, (xmlChar*)"UnknownParam", + (xmlChar*)vformat_attribute_param_get_nth_value(param, 0)); + osxml_node_add(property, "ParamName", vformat_attribute_param_get_name(param)); +} + +static void handle_encoding_parameter(xmlNode *current, VFormatParam *param) +{ + osync_trace(TRACE_INTERNAL, "%s: xmlNodeName=%s, param=%s", __func__, + (char *)current->name, + vformat_attribute_param_get_name(param)); + GList *v = vformat_attribute_param_get_values(param); + for (; v; v = v->next) { + char * content = g_strdup(v->data); + if (_helper_is_base64((const char *)content)) + { + g_free(content); + content=g_strdup("B"); + } + xmlNewTextChild(current, NULL, (xmlChar*)"Encoding", (xmlChar*)content); + g_free(content); + } +} + +static void handle_type_parameter(xmlNode *current, VFormatParam *param) +{ + osync_trace(TRACE_INTERNAL, "%s: xmlNodeName=%s, param=%s", __func__, + (char *)current->name, + vformat_attribute_param_get_name(param)); + GList *v = vformat_attribute_param_get_values(param); + /** + * PHOTO and LOGO TYPE parameter should be rewritten + * PHOTO;TYPE=JPEG -> PHOTO;TYPE=image/jpeg + **/ + if ( xmlStrcmp(current->name, (const xmlChar *)"Photo") && xmlStrcmp(current->name, (const xmlChar *)"Logo")) { + for (; v; v = v->next) { + xmlNewTextChild(current, NULL, + (xmlChar*)"Type", (xmlChar*)v->data); + } + } else { + for (; v; v = v->next) { + const char * tmp = rewrite_mime_type(v->data, 1); + if (tmp) + xmlNewTextChild(current, NULL, (xmlChar*)"Type", + (xmlChar*)tmp); + } + } + +} + +static void handle_value_parameter(xmlNode *current, VFormatParam *param) +{ + osync_trace(TRACE_INTERNAL, "Handling value parameter %s", vformat_attribute_param_get_name(param)); + + GList *v = vformat_attribute_param_get_values(param); + for (; v; v = v->next) { + xmlNewTextChild(current, NULL, (xmlChar*)"Value", (xmlChar*)v->data); + } +} + +static xmlNode *handle_formatted_name_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling formatted name attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"FormattedName", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_name_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling name attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Name", NULL); + osxml_node_add(current, "LastName", vformat_attribute_get_nth_value(attr, 0)); + osxml_node_add(current, "FirstName", vformat_attribute_get_nth_value(attr, 1)); + osxml_node_add(current, "Additional", vformat_attribute_get_nth_value(attr, 2)); + osxml_node_add(current, "Prefix", vformat_attribute_get_nth_value(attr, 3)); + osxml_node_add(current, "Suffix", vformat_attribute_get_nth_value(attr, 4)); + return current; +} + +static xmlNode *handle_agent_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling agent attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Agent", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_photo_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "%s:Handling photo attribute", __func__); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Photo", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_birthday_attribute(xmlNode *root, VFormatAttribute *attr) +{ + char *datestamp; + const char *tmp; + + osync_trace(TRACE_INTERNAL, "Handling birthday attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Birthday", NULL); + tmp = vformat_attribute_get_nth_value(attr, 0); + datestamp = osync_time_datestamp(tmp); + osxml_node_add(current, "Content", datestamp); + free(datestamp); + + return current; +} + +static xmlNode *handle_address_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling address attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Address", NULL); + osxml_node_add(current, "PostalBox", vformat_attribute_get_nth_value(attr, 0)); + osxml_node_add(current, "ExtendedAddress", vformat_attribute_get_nth_value(attr, 1)); + osxml_node_add(current, "Street", vformat_attribute_get_nth_value(attr, 2)); + osxml_node_add(current, "City", vformat_attribute_get_nth_value(attr, 3)); + osxml_node_add(current, "Region", vformat_attribute_get_nth_value(attr, 4)); + osxml_node_add(current, "PostalCode", vformat_attribute_get_nth_value(attr, 5)); + osxml_node_add(current, "Country", vformat_attribute_get_nth_value(attr, 6)); + return current; +} + +static xmlNode *handle_label_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling AddressLabel attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"AddressLabel", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_telephone_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Telephone attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Telephone", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_email_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling EMail attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"EMail", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_mailer_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Mailer attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Mailer", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_timezone_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Timezone attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Timezone", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_location_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Location attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Location", NULL); + osxml_node_add(current, "Latitude", vformat_attribute_get_nth_value(attr, 0)); + osxml_node_add(current, "Longitude", vformat_attribute_get_nth_value(attr, 1)); + return current; +} + +static xmlNode *handle_title_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Title attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Title", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_role_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Role attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Role", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_logo_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Logo attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Logo", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_organization_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Organization attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Organization", NULL); + osxml_node_add(current, "Name", vformat_attribute_get_nth_value(attr, 0)); + osxml_node_add(current, "Department", vformat_attribute_get_nth_value(attr, 1)); + + GList *values = vformat_attribute_get_values_decoded(attr); + values = g_list_nth(values, 2); + for (; values; values = values->next) { + GString *retstr = (GString *)values->data; + g_assert(retstr); + osxml_node_add(current, "Unit", retstr->str); + } + return current; +} + +static xmlNode *handle_note_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Note attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Note", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_revision_attribute(xmlNode *root, VFormatAttribute *attr) +{ + const char *tmp; + char *revision; + + osync_trace(TRACE_INTERNAL, "Handling Revision attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Revision", NULL); + tmp = vformat_attribute_get_nth_value(attr, 0); + revision = osync_time_timestamp(tmp); + osxml_node_add(current, "Content", revision); + free(revision); + return current; +} + +static xmlNode *handle_sound_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Sound attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Sound", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_url_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Url attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Url", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_uid_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Uid attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Uid", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_key_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Key attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Key", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_nickname_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Nickname attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Nickname", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_class_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Class attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Class", NULL); + osxml_node_add(current, "Content", vformat_attribute_get_nth_value(attr, 0)); + return current; +} + +static xmlNode *handle_categories_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling Categories attribute"); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Categories", NULL); + + GList *values = vformat_attribute_get_values_decoded(attr); + for (; values; values = values->next) { + GString *retstr = (GString *)values->data; + g_assert(retstr); + osxml_node_add(current, "Category", retstr->str); + } + + return current; +} + +static xmlNode *handle_unknown_attribute(xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_INTERNAL, "Handling unknown attribute %s", vformat_attribute_get_name(attr)); + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"UnknownNode", NULL); + osxml_node_add(current, "NodeName", vformat_attribute_get_name(attr)); + GList *values = vformat_attribute_get_values_decoded(attr); + for (; values; values = values->next) { + GString *retstr = (GString *)values->data; + g_assert(retstr); + osxml_node_add(current, "Content", retstr->str); + } + return current; +} + +static void vcard_handle_parameter(GHashTable *hooks, xmlNode *current, VFormatParam *param) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, hooks, current, param); + + //Find the handler for this parameter + void (* param_handler)(xmlNode *, VFormatParam *); + char *paramname = g_strdup_printf("%s=%s", vformat_attribute_param_get_name(param), vformat_attribute_param_get_nth_value(param, 0)); + param_handler = g_hash_table_lookup(hooks, paramname); + g_free(paramname); + if (!param_handler) + param_handler = g_hash_table_lookup(hooks, vformat_attribute_param_get_name(param)); + + if (param_handler == HANDLE_IGNORE) { + osync_trace(TRACE_EXIT, "%s: Ignored", __func__); + return; + } + + if (param_handler) + param_handler(current, param); + else + handle_unknown_parameter(current, param); + + osync_trace(TRACE_EXIT, "%s", __func__); +} + +static void vcard_handle_attribute(GHashTable *hooks, xmlNode *root, VFormatAttribute *attr) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p, %p:%s)", __func__, hooks, root, attr, attr ? vformat_attribute_get_name(attr) : "None"); + xmlNode *current = NULL; + + //Dont add empty stuff + GList *v; + for (v = vformat_attribute_get_values(attr); v; v = v->next) { + char *value = v->data; + if (strlen(value) != 0) + goto has_value; + } + osync_trace(TRACE_EXIT, "%s: No values", __func__); + return; + +has_value:; + + //We need to find the handler for this attribute + xmlNode *(* attr_handler)(xmlNode *, VFormatAttribute *) = g_hash_table_lookup(hooks, vformat_attribute_get_name(attr)); + osync_trace(TRACE_INTERNAL, "Hook is: %p", attr_handler); + if (attr_handler == HANDLE_IGNORE) { + osync_trace(TRACE_EXIT, "%s: Ignored", __func__); + return; + } + if (attr_handler) + current = attr_handler(root, attr); + else + current = handle_unknown_attribute(root, attr); + + //Handle all parameters of this attribute + GList *params = vformat_attribute_get_params(attr); + GList *p = NULL; + for (p = params; p; p = p->next) { + VFormatParam *param = p->data; + vcard_handle_parameter(hooks, current, param); + } + osync_trace(TRACE_EXIT, "%s", __func__); +} + +static void _generate_formatted_name(VFormat *vcard, xmlNode *root) +{ + osync_trace(TRACE_ENTRY, "%s(%p)", __func__, root); + VFormatAttribute *n = vformat_find_attribute(vcard, "N"); + GList *v = vformat_attribute_get_values(n); + GString *fnentry; + fnentry = g_string_new(""); + + // NAME:LAST;FIRST;ADDITIONAL;PREFIX;SUFFIX + // FN:PREFIX FIRST ADDITIONAL LAST SUFFIX + + int order[5] = {3, 1, 2, 0, 4}; + int i = 0; + char *str = NULL; + for (i = 0; i < 5; i++) { + if ((str = g_list_nth_data(v, order[i])) && str[0]) { + if (fnentry->len != 0) + g_string_append(fnentry, " "); + g_string_append(fnentry, str); + } + } + + osync_trace(TRACE_INTERNAL, "Handling formattedname attribute"); + + if (fnentry->len != 0) { + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"FormattedName", NULL); + osxml_node_add(current, "Content", fnentry->str); + } else { + osync_trace(TRACE_INTERNAL, "FN is empty!"); + } + + g_string_free(fnentry,TRUE); + osync_trace(TRACE_EXIT, "%s", __func__); + return; +} + +static void _generate_name_from_fn(VFormat *vcard, xmlNode *root) +{ + /* + * We copy FN to N:LASTNAME because we don't now how FN was build. + * e.g. we don't know if FN is "PREFIX FIRST LAST" or "FIRST ADDITIONAL LAST" + * With copying FN to N we prevent the vcard from being invalid. + */ + + osync_trace(TRACE_ENTRY, "%s(%p)", __func__, root); + VFormatAttribute *n = vformat_find_attribute(vcard, "FN"); + char *fn = vformat_attribute_get_value(n); + + osync_trace(TRACE_INTERNAL, "Handling name attribute"); + if (strlen(fn) != 0) { + xmlNode *current = xmlNewTextChild(root, NULL, (xmlChar*)"Name", NULL); + osxml_node_add(current, "LastName", fn); + } else { + osync_trace(TRACE_INTERNAL, "Name is empty"); + } + + osync_trace(TRACE_EXIT, "%s", __func__); + return; +} + +static osync_bool conv_vcard_to_xml(void *conv_data, char *input, int inpsize, char **output, int *outpsize, osync_bool *free_input, OSyncError **error) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p, %i, %p, %p, %p, %p)", __func__, conv_data, input, inpsize, output, outpsize, free_input, error); + + GHashTable *hooks = (GHashTable *)conv_data; + + osync_trace(TRACE_SENSITIVE, "Input Vcard is:\n%s", input); + + /* The input is not null-terminated, but vformat_new_from_string() expects a null-terminated string */ + char *input_str = g_malloc(inpsize + 1); + memcpy(input_str, input, inpsize); + input_str[inpsize] = '\0'; + + //Parse the vcard + VFormat *vcard = vformat_new_from_string(input_str); + + g_free(input_str); + + osync_trace(TRACE_INTERNAL, "Creating xml doc"); + + //Create a new xml document + xmlDoc *doc = xmlNewDoc((xmlChar*)"1.0"); + xmlNode *root = osxml_node_add_root(doc, "contact"); + + osync_trace(TRACE_INTERNAL, "parsing attributes"); + + //For every attribute we have call the handling hook + GList *attributes = vformat_get_attributes(vcard); + GList *a = NULL; + for (a = attributes; a; a = a->next) { + VFormatAttribute *attr = a->data; + vcard_handle_attribute(hooks, root, attr); + } + + //Generate FormattedName from Name if it doesn't exist + if (!vformat_find_attribute(vcard, "FN") && vformat_find_attribute(vcard, "N")) { + _generate_formatted_name(vcard,root); + } + + //Generate Name from FormattedName if it doesn't exist + if (!vformat_find_attribute(vcard, "N") && vformat_find_attribute(vcard, "FN")) { + _generate_name_from_fn(vcard,root); + } + + xmlChar *str = osxml_write_to_string(doc); + osync_trace(TRACE_SENSITIVE, "Output XML is:\n%s", str); + xmlFree(str); + + *free_input = TRUE; + *output = (char *)doc; + *outpsize = sizeof(doc); + osync_trace(TRACE_EXIT, "%s: TRUE", __func__); + return TRUE; +} + +static osync_bool needs_encoding(const unsigned char *tmp, const char *encoding) +{ + int i = 0; + if (!strcmp(encoding, "QUOTED-PRINTABLE")) { + while (tmp[i] != 0) { + if (tmp[i] > 127 || tmp[i] == 10 || tmp[i] == 13) + return TRUE; + i++; + } + } else { + return !g_utf8_validate((gchar*)tmp, -1, NULL); + } + return FALSE; +} + +static osync_bool needs_charset(const unsigned char *tmp) +{ + int i = 0; + while (tmp[i] != 0) { + if (tmp[i] > 127) + return TRUE; + i++; + } + return FALSE; +} + +static void add_value(VFormatAttribute *attr, xmlNode *parent, const char *name, const char *encoding) +{ + char *tmp = osxml_find_node(parent, name); + + if (!tmp) { + /* If there is no node with the given name, add an empty value to the list. + * This is necessary because some fields (N and ADR, for example) need + * a specific order of the values + */ + tmp = g_strdup(""); + } + + if (needs_charset((unsigned char*)tmp)) + if (!vformat_attribute_has_param (attr, "CHARSET")) + vformat_attribute_add_param_with_value(attr, "CHARSET", "UTF-8"); + + if (needs_encoding((unsigned char*)tmp, encoding)) { + if (!vformat_attribute_has_param (attr, "ENCODING")) + vformat_attribute_add_param_with_value(attr, "ENCODING", encoding); + vformat_attribute_add_value_decoded(attr, tmp, strlen(tmp) + 1); + } else + vformat_attribute_add_value(attr, tmp); + g_free(tmp); +} + +/** + * handle_xml_type_parameter: + * Photo or Logo Type will be IANA Mime type or not set + * @param attr + * @param current + */ +static void handle_xml_type_parameter(VFormatAttribute *attr, xmlNode *current) +{ + osync_trace(TRACE_INTERNAL, "%s: nodename=%s", + __func__, (char *)current->parent->name); + char *content = (char*)xmlNodeGetContent(current); + if(!xmlStrcmp(current->parent->name, (const xmlChar *)"Photo") || !xmlStrcmp(current->parent->name, (const xmlChar *)"Logo")) { + content = (char *)rewrite_mime_type((const char *)content, 1); + if(!content) + return; + } + VFormatParam *param = vformat_attribute_param_new("TYPE"); + vformat_attribute_param_add_value(param, content); + vformat_attribute_add_param (attr, param); +} + +/** + * handle_xml_type_parameter: + * Photo or Logo Type will be not IANA Mime type or not set + * @param attr + * @param current + */ +static void handle_xml_type_no_iana_parameter(VFormatAttribute *attr, xmlNode *current) +{ + osync_trace(TRACE_INTERNAL, "%s: nodename=%s", + __func__, (char *)current->parent->name); + char *content = (char*)xmlNodeGetContent(current); + if(!xmlStrcmp(current->parent->name, (const xmlChar *)"Photo") || !xmlStrcmp(current->parent->name, (const xmlChar *)"Logo")) { + content = (char *)rewrite_mime_type((const char *)content, 0); + if(!content) + return; + } + VFormatParam *param = vformat_attribute_param_new("TYPE"); + vformat_attribute_param_add_value(param, content); + vformat_attribute_add_param (attr, param); +} + +static void handle_xml_encoding_21_parameter(VFormatAttribute *attr, xmlNode *current) +{ + osync_trace(TRACE_INTERNAL, "%s()",__func__); + char *content = (char*)xmlNodeGetContent(current); + if (_helper_is_base64((const char *)content)) + { + g_free(content); + content=g_strdup("BASE64"); + } + VFormatParam *param = vformat_attribute_param_new("ENCODING"); + vformat_attribute_param_add_value(param, content); + vformat_attribute_add_param (attr, param); + g_free(content); +} + +static void handle_xml_encoding_30_parameter(VFormatAttribute *attr, xmlNode *current) +{ + osync_trace(TRACE_INTERNAL, "%s()",__func__); + char *content = (char*)xmlNodeGetContent(current); + VFormatParam *param = vformat_attribute_param_new("ENCODING"); + if (_helper_is_base64((const char *)content)) + { + g_free(content); + content=g_strdup("B"); + } + vformat_attribute_param_add_value(param, content); + vformat_attribute_add_param (attr, param); + g_free(content); +} + +static void handle_xml_value_parameter(VFormatAttribute *attr, xmlNode *current) +{ + osync_trace(TRACE_INTERNAL, "Handling value xml parameter"); + char *content = (char*)xmlNodeGetContent(current); + VFormatParam *param = vformat_attribute_param_new("VALUE"); + vformat_attribute_param_add_value(param, content); + vformat_attribute_add_param (attr, param); + g_free(content); +} + +static void handle_xml_category_parameter(VFormatAttribute *attr, xmlNode *current) +{ + osync_trace(TRACE_INTERNAL, "Handling category xml parameter"); + char *content = (char*)xmlNodeGetContent(current); + vformat_attribute_add_value(attr, content); + g_free(content); +} + +static void handle_xml_unit_parameter(VFormatAttribute *attr, xmlNode *current) +{ + osync_trace(TRACE_INTERNAL, "Handling unit xml parameter"); + char *content = (char*)xmlNodeGetContent(current); + vformat_attribute_add_value(attr, content); + g_free(content); +} + +static void xml_handle_unknown_parameter(VFormatAttribute *attr, xmlNode *current) +{ + osync_trace(TRACE_INTERNAL, "Handling unknown xml parameter %s", current->name); + char *content = (char*)xmlNodeGetContent(current); + vformat_attribute_add_param_with_value(attr, (char*)current->name, content); + g_free(content); +} + +static void xml_vcard_handle_parameter(OSyncHookTables *hooks, VFormatAttribute *attr, xmlNode *current) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p, %p:%s)", __func__, hooks, attr, current, current ? (char *)current->name : "None"); + + //Find the handler for this parameter + void (* xml_param_handler)(VFormatAttribute *attr, xmlNode *); + char *content = (char*)xmlNodeGetContent(current); + char *paramname = g_strdup_printf("%s=%s", current->name, content); + g_free(content); + xml_param_handler = g_hash_table_lookup(hooks->parameters, paramname); + g_free(paramname); + if (!xml_param_handler) + xml_param_handler = g_hash_table_lookup(hooks->parameters, current->name); + + if (xml_param_handler == HANDLE_IGNORE) { + osync_trace(TRACE_EXIT, "%s: Ignored", __func__); + return; + } + + if (xml_param_handler) + xml_param_handler(attr, current); + + osync_trace(TRACE_EXIT, "%s", __func__); +} + +static VFormatAttribute *xml_handle_unknown_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling unknown xml attribute %s", root->name); + char *name = osxml_find_node(root, "NodeName"); + VFormatAttribute *attr = vformat_attribute_new(NULL, name); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_formatted_name_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling formatted name xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "FN"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_name_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling name xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "N"); + add_value(attr, root, "LastName", encoding); + add_value(attr, root, "FirstName", encoding); + add_value(attr, root, "Additional", encoding); + add_value(attr, root, "Prefix", encoding); + add_value(attr, root, "Suffix", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_agent_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling agent xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "AGENT"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static void xml_vcard_handle_attribute(OSyncHookTables *hooks, VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p, %p:%s)", __func__, hooks, vcard, root, root ? (char *)root->name : "None"); + VFormatAttribute *attr = NULL; + + //We need to find the handler for this attribute + VFormatAttribute *(* xml_attr_handler)(VFormat *vcard, xmlNode *root, const char *) = g_hash_table_lookup(hooks->attributes, root->name); + osync_trace(TRACE_INTERNAL, "xml hook is: %p", xml_attr_handler); + if (xml_attr_handler == HANDLE_IGNORE) { + osync_trace(TRACE_EXIT, "%s: Ignored", __func__); + return; + } + if (xml_attr_handler) + attr = xml_attr_handler(vcard, root, encoding); + else { + osync_trace(TRACE_EXIT, "%s: Ignored2", __func__); + return; + } + + //Handle all parameters of this attribute + xmlNode *child = root->xmlChildrenNode; + while (child) { + xml_vcard_handle_parameter(hooks, attr, child); + child = child->next; + } + osync_trace(TRACE_EXIT, "%s", __func__); +} + +static VFormatAttribute *handle_xml_photo_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "%s:Handling photo xml attribute", __func__); + VFormatAttribute *attr = vformat_attribute_new(NULL, "PHOTO"); + add_value(attr, root, "Content", encoding); +// vformat_attribute_add_param_with_value(attr, "ENCODING", "b"); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_photo_base64_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "%s:Handling photo xml attribute", __func__); + VFormatAttribute *attr = vformat_attribute_new(NULL, "PHOTO"); + add_value(attr, root, "Content", encoding); +// vformat_attribute_add_param_with_value(attr, "ENCODING", "BASE64"); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_birthday_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling birthday xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "BDAY"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_address_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling address xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "ADR"); + add_value(attr, root, "PostalBox", encoding); + add_value(attr, root, "ExtendedAddress", encoding); + add_value(attr, root, "Street", encoding); + add_value(attr, root, "City", encoding); + add_value(attr, root, "Region", encoding); + add_value(attr, root, "PostalCode", encoding); + add_value(attr, root, "Country", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_label_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling label xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "LABEL"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_telephone_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling telephone xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "TEL"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_email_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling email xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "EMAIL"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_mailer_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling mailer xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "MAILER"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_timezone_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling timezone xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "TZ"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_location_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling location xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "GEO"); + add_value(attr, root, "Latitude", encoding); + add_value(attr, root, "Longitude", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_title_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling title xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "TITLE"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_role_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling role xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "ROLE"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_logo_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling logo xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "LOGO"); + add_value(attr, root, "Content", encoding); + //vformat_attribute_add_param_with_value(attr, "ENCODING", "b"); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_organization_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling organization xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "ORG"); + add_value(attr, root, "Name", encoding); + add_value(attr, root, "Department", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_note_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling note xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "NOTE"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_revision_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling revision xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "REV"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_sound_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling sound xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "SOUND"); + add_value(attr, root, "Content", encoding); + //vformat_attribute_add_param_with_value(attr, "ENCODING", "b"); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_url_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling url xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "URL"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_uid_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling uid xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "UID"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_key_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling key xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "KEY"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_nickname_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling nickname xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "NICKNAME"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_class_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling class xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "CLASS"); + add_value(attr, root, "Content", encoding); + vformat_add_attribute(vcard, attr); + return attr; +} + +static VFormatAttribute *handle_xml_categories_attribute(VFormat *vcard, xmlNode *root, const char *encoding) +{ + osync_trace(TRACE_INTERNAL, "Handling categories xml attribute"); + VFormatAttribute *attr = vformat_attribute_new(NULL, "CATEGORIES"); + vformat_add_attribute(vcard, attr); + return attr; +} + +static osync_bool conv_xml_to_vcard(void *user_data, char *input, int inpsize, char **output, int *outpsize, osync_bool *free_input, OSyncError **error, int target) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p, %i, %p, %p, %p, %p)", __func__, user_data, input, inpsize, output, outpsize, free_input, error); + + xmlChar *str = osxml_write_to_string((xmlDoc *)input); + osync_trace(TRACE_SENSITIVE, "Input XML is:\n%s", str); + xmlFree(str); + + //Get the root node of the input document + xmlNode *root = xmlDocGetRootElement((xmlDoc *)input); + if (!root) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to get xml root element"); + osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); + return FALSE; + } + + if (xmlStrcmp(root->name, (const xmlChar *)"contact")) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "Wrong xml root element"); + osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); + return FALSE; + } + + //Make the new vcard + VFormat *vcard = vformat_new(); + + osync_trace(TRACE_INTERNAL, "parsing cml attributes"); + const char *std_encoding = NULL; + if (target == VFORMAT_CARD_21) + std_encoding = "QUOTED-PRINTABLE"; + else + std_encoding = "B"; + + OSyncHookTables *hooks = (OSyncHookTables *)user_data; + /* vcard21 / vcard30 */ + if (target == VFORMAT_CARD_21) { + g_hash_table_insert(hooks->attributes, "Photo", handle_xml_photo_base64_attribute); + g_hash_table_insert(hooks->parameters, "Type", handle_xml_type_no_iana_parameter); + g_hash_table_insert(hooks->parameters, "Encoding", handle_xml_encoding_21_parameter); + } else { + g_hash_table_insert(hooks->attributes, "Photo", handle_xml_photo_attribute); + g_hash_table_insert(hooks->parameters, "Type", handle_xml_type_parameter); + g_hash_table_insert(hooks->parameters, "Encoding", handle_xml_encoding_30_parameter); + } + + if (root) + root = root->children; + while (root) { + xml_vcard_handle_attribute(hooks, vcard, root, std_encoding); + root = root->next; + } + + *free_input = TRUE; + *output = vformat_to_string(vcard, target); + osync_trace(TRACE_SENSITIVE, "vcard output is: \n%s", *output); + *outpsize = strlen(*output); + osync_trace(TRACE_EXIT, "%s", __func__); + + return TRUE; +} + +static osync_bool conv_xml_to_vcard30(void *user_data, char *input, int inpsize, char **output, int *outpsize, osync_bool *free_input, OSyncError **error) +{ + return conv_xml_to_vcard(user_data, input, inpsize, output, outpsize, free_input, error, VFORMAT_CARD_30); +} + +static osync_bool conv_xml_to_vcard21(void *user_data, char *input, int inpsize, char **output, int *outpsize, osync_bool *free_input, OSyncError **error) +{ + return conv_xml_to_vcard(user_data, input, inpsize, output, outpsize, free_input, error, VFORMAT_CARD_21); +} + +static OSyncConvCmpResult compare_contact(OSyncChange *leftchange, OSyncChange *rightchange) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, leftchange, rightchange); + + OSyncXMLScore score[] = + { + //{30, "/contact/FullName"}, + {100, "/contact/Name"}, + //{20, "/contact/Telephone"}, + //{20, "/contact/Address"}, + {0, "/contact/UnknownNode"}, + {0, "/contact/*/Slot"}, + {0, "/contact/*/Type"}, + {0, "/contact/WantsHtml"}, + {0, "/contact/Class"}, + {0, "/contact/FileAs"}, + {0, "/contact/IM-ICQ"}, + {0, "/contact/AddressLabel"}, + {0, "/contact/Uid"}, + {0, "/contact/Revision"}, + {0, NULL} + }; + + OSyncConvCmpResult ret = osxml_compare((xmlDoc*)osync_change_get_data(leftchange), (xmlDoc*)osync_change_get_data(rightchange), score, 0, 99); + + osync_trace(TRACE_EXIT, "%s: %i", __func__, ret); + return ret; +} + +static char *print_contact(OSyncChange *change) +{ + xmlDoc *doc = (xmlDoc *)osync_change_get_data(change); + + return (char *)osxml_write_to_string(doc); +} + +static void destroy_xml(char *data, size_t size) +{ + xmlFreeDoc((xmlDoc *)data); +} + +static void *init_vcard_to_xml(void) +{ + osync_trace(TRACE_ENTRY, "%s", __func__); + GHashTable *table = g_hash_table_new(g_str_hash, g_str_equal); + + g_hash_table_insert(table, "FN", handle_formatted_name_attribute); + g_hash_table_insert(table, "N", handle_name_attribute); + g_hash_table_insert(table, "AGENT", handle_agent_attribute); + g_hash_table_insert(table, "PHOTO", handle_photo_attribute); + g_hash_table_insert(table, "BDAY", handle_birthday_attribute); + g_hash_table_insert(table, "ADR", handle_address_attribute); + g_hash_table_insert(table, "LABEL", handle_label_attribute); + g_hash_table_insert(table, "TEL", handle_telephone_attribute); + g_hash_table_insert(table, "EMAIL", handle_email_attribute); + g_hash_table_insert(table, "MAILER", handle_mailer_attribute); + g_hash_table_insert(table, "TZ", handle_timezone_attribute); + g_hash_table_insert(table, "GEO", handle_location_attribute); + g_hash_table_insert(table, "TITLE", handle_title_attribute); + g_hash_table_insert(table, "ROLE", handle_role_attribute); + g_hash_table_insert(table, "LOGO", handle_logo_attribute); + g_hash_table_insert(table, "ORG", handle_organization_attribute); + g_hash_table_insert(table, "NOTE", handle_note_attribute); + g_hash_table_insert(table, "REV", handle_revision_attribute); + g_hash_table_insert(table, "SOUND", handle_sound_attribute); + g_hash_table_insert(table, "URL", handle_url_attribute); + g_hash_table_insert(table, "UID", handle_uid_attribute); + g_hash_table_insert(table, "KEY", handle_key_attribute); + g_hash_table_insert(table, "NICKNAME", handle_nickname_attribute); + g_hash_table_insert(table, "CLASS", handle_class_attribute); + g_hash_table_insert(table, "CATEGORIES", handle_categories_attribute); + + g_hash_table_insert(table, "VERSION", HANDLE_IGNORE); + g_hash_table_insert(table, "BEGIN", HANDLE_IGNORE); + g_hash_table_insert(table, "END", HANDLE_IGNORE); + + g_hash_table_insert(table, "ENCODING", handle_encoding_parameter); + g_hash_table_insert(table, "CHARSET", HANDLE_IGNORE); + + g_hash_table_insert(table, "TYPE", handle_type_parameter); + g_hash_table_insert(table, "VALUE", handle_value_parameter); + + g_hash_table_insert(table, "X-IRMC-LUID", HANDLE_IGNORE); + + osync_trace(TRACE_EXIT, "%s: %p", __func__, table); + return (void *)table; +} + +static void fin_vcard_to_xml(void *data) +{ + g_hash_table_destroy((GHashTable *)data); +} + +static void *init_xml_to_vcard(void) +{ + osync_trace(TRACE_ENTRY, "%s", __func__); + + OSyncHookTables *hooks = g_malloc0(sizeof(OSyncHookTables)); + + hooks->attributes = g_hash_table_new(g_str_hash, g_str_equal); + hooks->parameters = g_hash_table_new(g_str_hash, g_str_equal); + + g_hash_table_insert(hooks->attributes, "FormattedName", handle_xml_formatted_name_attribute); + g_hash_table_insert(hooks->attributes, "Name", handle_xml_name_attribute); + g_hash_table_insert(hooks->attributes, "Agent", handle_xml_agent_attribute); + g_hash_table_insert(hooks->attributes, "Birthday", handle_xml_birthday_attribute); + g_hash_table_insert(hooks->attributes, "Address", handle_xml_address_attribute); + g_hash_table_insert(hooks->attributes, "AddressLabel", handle_xml_label_attribute); + g_hash_table_insert(hooks->attributes, "Telephone", handle_xml_telephone_attribute); + g_hash_table_insert(hooks->attributes, "EMail", handle_xml_email_attribute); + g_hash_table_insert(hooks->attributes, "Mailer", handle_xml_mailer_attribute); + g_hash_table_insert(hooks->attributes, "Timezone", handle_xml_timezone_attribute); + g_hash_table_insert(hooks->attributes, "Location", handle_xml_location_attribute); + g_hash_table_insert(hooks->attributes, "Title", handle_xml_title_attribute); + g_hash_table_insert(hooks->attributes, "Role", handle_xml_role_attribute); + g_hash_table_insert(hooks->attributes, "Logo", handle_xml_logo_attribute); + g_hash_table_insert(hooks->attributes, "Organization", handle_xml_organization_attribute); + g_hash_table_insert(hooks->attributes, "Note", handle_xml_note_attribute); + g_hash_table_insert(hooks->attributes, "Revision", handle_xml_revision_attribute); + g_hash_table_insert(hooks->attributes, "Sound", handle_xml_sound_attribute); + g_hash_table_insert(hooks->attributes, "Url", handle_xml_url_attribute); + g_hash_table_insert(hooks->attributes, "Uid", handle_xml_uid_attribute); + g_hash_table_insert(hooks->attributes, "Key", handle_xml_key_attribute); + g_hash_table_insert(hooks->attributes, "Nickname", handle_xml_nickname_attribute); + g_hash_table_insert(hooks->attributes, "Class", handle_xml_class_attribute); + g_hash_table_insert(hooks->attributes, "Categories", handle_xml_categories_attribute); + g_hash_table_insert(hooks->attributes, "UnknownNode", xml_handle_unknown_attribute); + + /* disable general Type handling .... because Photo type needs to be handled + seperatly + g_hash_table_insert(hooks->parameters, "Type", handle_xml_type_parameter);*/ + g_hash_table_insert(hooks->parameters, "Value", handle_xml_value_parameter); + g_hash_table_insert(hooks->parameters, "Category", handle_xml_category_parameter); + g_hash_table_insert(hooks->parameters, "Unit", handle_xml_unit_parameter); + + g_hash_table_insert(hooks->parameters, "UnknownParam", xml_handle_unknown_parameter); + + osync_trace(TRACE_EXIT, "%s: %p", __func__, hooks); + return (void *)hooks; +} + +static void fin_xml_to_vcard(void *data) +{ + OSyncHookTables *hooks = (OSyncHookTables *)data; + g_hash_table_destroy(hooks->attributes); + g_hash_table_destroy(hooks->parameters); + g_free(hooks); +} + +static time_t get_revision(OSyncChange *change, OSyncError **error) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, change, error); + + xmlDoc *doc = (xmlDoc *)osync_change_get_data(change); + + xmlXPathObject *xobj = osxml_get_nodeset(doc, "/contact/Revision"); + + xmlNodeSet *nodes = xobj->nodesetval; + + int size = (nodes) ? nodes->nodeNr : 0; + if (size != 1) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to find the revision"); + osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); + return -1; + } + + char *revision = (char*)osxml_find_node(nodes->nodeTab[0], "Content"); + + osync_trace(TRACE_INTERNAL, "About to convert string %s", revision); + time_t time = vformat_time_to_unix(revision); + g_free(revision); + xmlXPathFreeObject(xobj); + osync_trace(TRACE_EXIT, "%s: %i", __func__, time); + return time; +} + +void get_info(OSyncEnv *env) +{ + osync_env_register_objtype(env, "contact"); + osync_env_register_objformat(env, "contact", "xml-contact"); + osync_env_format_set_compare_func(env, "xml-contact", compare_contact); + osync_env_format_set_destroy_func(env, "xml-contact", destroy_xml); + osync_env_format_set_print_func(env, "xml-contact", print_contact); + osync_env_format_set_copy_func(env, "xml-contact", osxml_copy); + osync_env_format_set_revision_func(env, "xml-contact", get_revision); + osync_env_format_set_marshall_func(env, "xml-contact", osxml_marshall); + osync_env_format_set_demarshall_func(env, "xml-contact", osxml_demarshall); + + osync_env_register_converter(env, CONVERTER_CONV, "vcard21", "xml-contact", conv_vcard_to_xml); + osync_env_converter_set_init(env, "vcard21", "xml-contact", init_vcard_to_xml, fin_vcard_to_xml); + osync_env_register_converter(env, CONVERTER_CONV, "xml-contact", "vcard21", conv_xml_to_vcard21); + osync_env_converter_set_init(env, "xml-contact", "vcard21", init_xml_to_vcard, fin_xml_to_vcard); + + osync_env_register_converter(env, CONVERTER_CONV, "vcard30", "xml-contact", conv_vcard_to_xml); + osync_env_converter_set_init(env, "vcard30", "xml-contact", init_vcard_to_xml, fin_vcard_to_xml); + osync_env_register_converter(env, CONVERTER_CONV, "xml-contact", "vcard30", conv_xml_to_vcard30); + osync_env_converter_set_init(env, "xml-contact", "vcard30", init_xml_to_vcard, fin_xml_to_vcard); +} + +/** + * rewrite_mime_type: rewrites a IANA or not IANA mime type + * Internet Assigned Numbers Authority mime types are only supported in + * VCARD:3.0. + * VCARD:2.1 only supports the following mime types: GIF, CGM, WMF, BMP, + * MET, PMB, DIB, PICT, TIFF, PS, PDF, JPEG, MPEG, MPEG2, AVI, QTIME, WAVE, + * PCM, AIFF + * + * @param source_format: could be a IANA ("image/jpeg") or not IANA ("JPEG") + * @param use_iana: 0 rewrite to not IANA, 1 rewrite to IANA + * @returns IANA / not IANA mime type or NULL if not found + **/ +static const char * rewrite_mime_type(const char * source_format, int use_iana) +{ + osync_trace(TRACE_INTERNAL, "%s: source_format = %s", __func__, source_format); + char * iana_format = NULL; + char * not_iana_format = NULL; + + if ( (!g_ascii_strcasecmp (source_format, "JPEG")) || + (!g_ascii_strcasecmp (source_format, "image/jpeg")) ) { + iana_format = "image/jpeg"; + not_iana_format = "JPEG"; + goto NORMAL_EXIT; + } + if ( (!g_ascii_strcasecmp (source_format, "TIFF")) || + (!g_ascii_strcasecmp (source_format, "image/tiff")) ) { + iana_format = "image/tiff"; + not_iana_format = "TIFF"; + goto NORMAL_EXIT; + } + if ( (!g_ascii_strcasecmp (source_format, "GIF")) || + (!g_ascii_strcasecmp (source_format, "image/gif")) ) { + iana_format = "image/gif"; + not_iana_format = "GIF"; + goto NORMAL_EXIT; + } + if ( (!g_ascii_strcasecmp (source_format, "CGM")) || + (!g_ascii_strcasecmp (source_format, "image/cgm")) ) { + iana_format = "image/cgm"; + not_iana_format = "CGM"; + goto NORMAL_EXIT; + } + if ( (!g_ascii_strcasecmp (source_format, "BMP")) || + (!g_ascii_strcasecmp (source_format, "image/x-ms-bmp")) ) { + iana_format = "image/x-ms-bmp"; + not_iana_format = "BMP"; + goto NORMAL_EXIT; + } + if ( (!g_ascii_strcasecmp (source_format, "PS")) || + (!g_ascii_strcasecmp (source_format, "application/postscript")) ) { + iana_format = "application/postscript"; + not_iana_format = "PS"; + goto NORMAL_EXIT; + } + if ( (!g_ascii_strcasecmp (source_format, "PDF")) || + (!g_ascii_strcasecmp (source_format, "application/pdf")) ) { + iana_format = "application/pdf"; + not_iana_format = "PDF"; + goto NORMAL_EXIT; + } + if ( (!g_ascii_strcasecmp (source_format, "MPEG")) || + (!g_ascii_strcasecmp (source_format, "video/mpeg")) ) { + iana_format = "video/mpeg"; + not_iana_format = "MPEG"; + goto NORMAL_EXIT; + } + if ( (!g_ascii_strcasecmp (source_format, "MPEG2")) || + (!g_ascii_strcasecmp (source_format, "video/mpeg")) ) { + iana_format = "video/mpeg"; + not_iana_format = "MPEG2"; + goto NORMAL_EXIT; + } + if ( (!g_ascii_strcasecmp (source_format, "AVI")) || + (!g_ascii_strcasecmp (source_format, "video/x-msvideo")) ) { + iana_format = "video/x-msvideo"; + not_iana_format = "AVI"; + goto NORMAL_EXIT; + } + if ( (!g_ascii_strcasecmp (source_format, "QTIME")) || + (!g_ascii_strcasecmp (source_format, "video/quicktime")) ) { + iana_format = "video/quicktime"; + not_iana_format = "QTIME"; + goto NORMAL_EXIT; + } + + /*FIXME:vcard 2.1 only no iana typ found*/ + if ( !g_ascii_strcasecmp (source_format, "WMF") ) { + goto NO_IANA; + } + if ( !g_ascii_strcasecmp (source_format, "MET") ) { + goto NO_IANA; + } + if ( !g_ascii_strcasecmp (source_format, "PMB") ) { + goto NO_IANA; + } + if ( !g_ascii_strcasecmp (source_format, "DIB") ) { + goto NO_IANA; + } + if ( !g_ascii_strcasecmp (source_format, "PICT") ) { + goto NO_IANA; + } + if ( !g_ascii_strcasecmp (source_format, "WAVE") ) { + goto NO_IANA; + } + if ( !g_ascii_strcasecmp (source_format, "PCM") ) { + goto NO_IANA; + } + if ( !g_ascii_strcasecmp (source_format, "AIFF") ) { + goto NO_IANA; + } + +/*NO_MATCH:*/ + osync_trace(TRACE_INTERNAL, "%s:[NO_MATCH] output = NULL ", __func__); + return(NULL); + +NO_IANA: + osync_trace(TRACE_INTERNAL, "%s:[NO_IANA] output = %s ", __func__, source_format); + if (!use_iana) + return(source_format); + return(NULL); + +NORMAL_EXIT: + if (use_iana) + { + osync_trace(TRACE_INTERNAL, "%s:[NORMAL_EXIT] output = %s ", __func__, iana_format); + return (iana_format); + } + osync_trace(TRACE_INTERNAL, "%s:[NORMAL_EXIT] output = %s ", __func__, not_iana_format); + return(not_iana_format); +} + +/** + * _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); +} |
