From: <svn...@op...> - 2010-02-06 17:40:56
|
Author: scriptor Date: Sat Feb 6 18:40:46 2010 New Revision: 6032 URL: http://www.opensync.org/changeset/6032 Log: I have removed several leaks. Please note: In order to avoid certain libxml leaks, the user CAN define the constant ENABLE_XML_CLEANUP_PARSER in ldap_plugin.h. This will lead to a call of xmlCleanupParser() somewhere in ldap_format.c. However, this is quite a dangerous function call. Especially in a library, and even more so in a plugin for this library. Therefore it's better to leave this undefined by default, as it seems. Modified: plugins/ldap-sync/misc/ldap_format_convert.c plugins/ldap-sync/src/ldap_connect.c plugins/ldap-sync/src/ldap_debug.c plugins/ldap-sync/src/ldap_format.c plugins/ldap-sync/src/ldap_format.h plugins/ldap-sync/src/ldap_plugin.c plugins/ldap-sync/src/ldap_plugin.h plugins/ldap-sync/tests/check_do_convert_from_to.c Modified: plugins/ldap-sync/misc/ldap_format_convert.c ============================================================================== --- plugins/ldap-sync/misc/ldap_format_convert.c Sat Feb 6 18:40:02 2010 (r6031) +++ plugins/ldap-sync/misc/ldap_format_convert.c Sat Feb 6 18:40:46 2010 (r6032) @@ -1141,6 +1141,7 @@ } + // Analyze the source format sourceformat = osync_format_env_detect_objformat(format_env, data); if (sourceformat == NULL) { @@ -1181,7 +1182,7 @@ if (!ldap_format_prepare_xmlformat_data(buffer, size, "todo", "xmlformat-todo", &data, &sourceformat, &error)) { goto error; } - } if (!strcmp(sourceformat_name, "xmlformat-note-doc")) { + } else if (!strcmp(sourceformat_name, "xmlformat-note-doc")) { if (!ldap_format_prepare_xmlformat_data(buffer, size, "note", "xmlformat-note", &data, &sourceformat, &error)) { goto error; } @@ -1257,32 +1258,53 @@ if (converter_path) osync_converter_path_unref(converter_path); + if (sourceformat_name) + { + if (!strncmp(sourceformat_name, "xmlformat-", 10)) { + if (sourceformat) + osync_objformat_unref(sourceformat); + + if (buffer) + osync_free(buffer); + } + } + if (format_env) osync_format_env_unref(format_env); - if (result) + if (result) { osync_free(result); - - xmlCleanupParser(); + result = NULL; + } out: osync_trace(TRACE_EXIT, "%s", __func__); return 0; -error: +error: if (data) osync_data_unref(data); if (converter_path) osync_converter_path_unref(converter_path); + if (sourceformat_name) { + if (!strncmp(sourceformat_name, "xmlformat-", 10)) { + if (sourceformat) + osync_objformat_unref(sourceformat); + + if (buffer) + osync_free(buffer); + } + } + if (format_env) osync_format_env_unref(format_env); - if (result) + if (result) { osync_free(result); - - xmlCleanupParser(); + result = NULL; + } if (!osync_error_is_set(&error)) { osync_error_set(&error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: Unknown reason.\n", __FILE__, __LINE__); Modified: plugins/ldap-sync/src/ldap_connect.c ============================================================================== --- plugins/ldap-sync/src/ldap_connect.c Sat Feb 6 18:40:02 2010 (r6031) +++ plugins/ldap-sync/src/ldap_connect.c Sat Feb 6 18:40:46 2010 (r6032) @@ -42,58 +42,6 @@ * @{ */ -/** - * @brief Frees a GList that consists of LDAPMod's - * @param ldapmods the GList with LDAPMod's - * @returns Nothing. - * - */ -void ldap_plugin_free_ldapmods_list(GList *ldapmods) -{ - GList *list = NULL; - - - if (ldapmods == NULL) { - return; - } - - - for (list = g_list_first(ldapmods) ; list ; list = g_list_next(list)) - { - if (list->data) { - - if (((LDAPMod *)(list->data))->mod_type) { - g_free(((LDAPMod *)(list->data))->mod_type); // from strdup() in ldap_format_create_ldap_entry_from_ldapmods(GList *ldapmods) - ((LDAPMod *)(list->data))->mod_type = NULL; - } - - if (((LDAPMod *)(list->data))->mod_bvalues) { - if (((LDAPMod *)(list->data))->mod_bvalues[0]) { - if (((LDAPMod *)(list->data))->mod_bvalues[0]->bv_val) { - g_free(((LDAPMod *)(list->data))->mod_bvalues[0]->bv_val); // from strdup() in ldap_format_create_ldap_entry_from_ldapmods(GList *ldapmods) - ((LDAPMod *)(list->data))->mod_bvalues[0]->bv_val = NULL; - } - - g_free(((LDAPMod *)(list->data))->mod_bvalues[0]); - ((LDAPMod *)(list->data))->mod_bvalues[0] = NULL; - } - - g_free(((LDAPMod *)(list->data))->mod_bvalues); - ((LDAPMod *)(list->data))->mod_bvalues = NULL; - } - - g_free(list->data); // this is an LDAPMod... So g_free() maybe insufficient? - list->data = NULL; - } - - } - - - g_list_free(ldapmods); - -} - - /** * @brief Connects with the LDAP server. @@ -1941,12 +1889,13 @@ * operational attributes are to be shown. * ldap_plugin.h defines 3 types: USER_ATTRIBUTES, * OPERATIONAL_ATTRIBUTES and OBJECTCLASSES. - * * @param sinkenv The object type specific environment - * @param results This function fills this struct with the search result. * @param ignore_no_such_object This variable tells this function whether * or not it should ignore "No such object" * messages by libldap. + * @param results This function fills this struct with the search result. + * It needs to be freed with ldap_msgfree() by the caller. + * * @param error The libopensync error pointer. * * @returns TRUE on success, FALSE, on failure. @@ -2073,7 +2022,8 @@ NULL, ///< client controls NULL, ///< timeout STRING_SIZE, ///< sizelimit - results ///< The result of the search + results ///< The result of the search. Needs to be freed with + ///< ldap_msgfree(). ); @@ -2643,7 +2593,7 @@ osync_error_unref(error); } - goto done; + goto free_all_results_and_done; } else { goto error; @@ -2670,10 +2620,10 @@ #endif if (result_code == LDAP_SUCCESS) { - goto done; + goto free_all_results_and_done; } else if (result_code == LDAP_NO_SUCH_OBJECT) { - goto done; + goto free_all_results_and_done; } else { char *ldap_error = ldap_plugin_report_ldap_error(sinkenv, __FILE__, __LINE__, result_code); @@ -2803,13 +2753,15 @@ } // for (result = ldap_first_entry(sinkenv->ld, all_results) ; result ; result = ldap_next_entry(sinkenv->ld, result)) + + + +free_all_results_and_done: if (all_results) { ldap_msgfree(all_results); all_results = NULL; } - -done: osync_trace(TRACE_EXIT, "%s: *entrylist = %p", __func__, (void *) *entrylist); return TRUE; @@ -3364,7 +3316,8 @@ * @param uid The particular uid. This MUST NOT be the id of a subentry. It * MUST always be the DN of the top entry one level below * "ou=addressbook" or "ou=calendar" etc. - * @param actual_hash The resulting hash value. + * @param actual_hash The resulting hash value. This needs to be freed by the + * caller. * @param error The libopensync error pointer. * * @returns TRUE on success, FALSE otherwise. @@ -4289,12 +4242,17 @@ /* Free up attribute structures */ + ldap_plugin_free_ldap_mods_array(entry->mods); + entry->mods = NULL; + +#if 0 + // this is insufficient xxx jl for ( i = 0 ; entry->mods[i] ; i++ ) { g_free(entry->mods[i]); } g_free(entry->mods); - +#endif // Recreate the LDAP attributes @@ -4354,7 +4312,6 @@ } - g_free(list->data); i++; } @@ -4592,6 +4549,11 @@ ldap_plugin_printf("%s:%i: ldap attribute \"%s\" should have been deleted, actually. But it is part of the DN.\n", __FILE__, __LINE__, ldap_attribute); #endif } + + if (tmp) { + g_free(tmp); + tmp = NULL; + } } else { osync_trace(TRACE_INTERNAL, "%s:%i: ldap attribute \"%s\" should have actually been deleted, but it is equal to the key attribute.\n", __FILE__, __LINE__, ldap_attribute); @@ -4687,8 +4649,9 @@ out: - if (modifications) - g_list_free(modifications); + if (modifications) { + ldap_plugin_free_ldap_mods_list(modifications); + } @@ -4839,9 +4802,15 @@ ldap_plugin_rewrite_ldap_entry(entry, new_set_of_mods, error); if (osync_error_is_set(error)) { osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_plugin_rewrite_ldap_entry() has failed.", __FILE__, __LINE__); + + ldap_plugin_free_ldap_mods_list(new_set_of_mods); + new_set_of_mods = NULL; goto error; } + ldap_plugin_free_ldap_mods_list(new_set_of_mods); + new_set_of_mods = NULL; + #endif } // if (!found_attribute) Modified: plugins/ldap-sync/src/ldap_debug.c ============================================================================== --- plugins/ldap-sync/src/ldap_debug.c Sat Feb 6 18:40:02 2010 (r6031) +++ plugins/ldap-sync/src/ldap_debug.c Sat Feb 6 18:40:46 2010 (r6032) @@ -606,8 +606,13 @@ #endif } - if (msg3 && msg3[0]) { - strncat(buf, msg3, STRING_SIZE - 1 - strlen(buf)); + if (msg3) { + if (msg3[0]) { + strncat(buf, msg3, STRING_SIZE - 1 - strlen(buf)); + } + + ldap_memfree(msg3); + msg3 = NULL; } return buf; Modified: plugins/ldap-sync/src/ldap_format.c ============================================================================== --- plugins/ldap-sync/src/ldap_format.c Sat Feb 6 18:40:02 2010 (r6031) +++ plugins/ldap-sync/src/ldap_format.c Sat Feb 6 18:40:46 2010 (r6032) @@ -133,7 +133,8 @@ if (mod->mod_type) { - g_free(mod->mod_type); // from strdup() in ldap_format_create_ldap_entry_from_ldapmods(GList *ldapmods) + g_free(mod->mod_type); ///< @sa strdup() in ldap_format_create_ldap_entry_from_ldapmods(GList *ldapmods) + ///< @sa strdup() in ldap_format_append_ldapmod() mod->mod_type = NULL; } @@ -176,7 +177,9 @@ * ldap_format_free_ldap_entries(). * * @param entry The LDAP entry to be freed. - * @param user_data ??????? + * @param user_data This points to a user_data_carrier struct, that has + * been allocated either in ldap_format_initialize_converter() + * or in ldap_format_initialize_format1(). * * @returns Nothing. */ @@ -217,7 +220,8 @@ } if (entry->mods[i]->mod_type) { - g_free(entry->mods[i]->mod_type); + g_free(entry->mods[i]->mod_type); ///< from strdup() in ldap_format_create_ldap_entry_from_ldapmods(GList *ldapmods) + ///< @sa strdup() in ldap_format_append_ldapmod() entry->mods[i]->mod_type = NULL; } } @@ -1068,10 +1072,6 @@ } - // xxx jl: Das ist, glaube ich, falsch: Es kopiert die subentries - // auf eine hoehere Stufe. - // Siehe line 779 - // Add the resulting subentry to the just freshly created LDAP entry: if (entry) { if (target_subentry) { @@ -1175,75 +1175,78 @@ children_node = xmlnode->next; - if (children_node) { - for (node = children_node ; node; node = node->next) { - const xmlChar *child_name = NULL; + if (children_node == NULL) { + children_node = (xmlNode *)xmlnode; + } - child_name = node->name; - if (child_name == NULL) { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: child_name = NULL. Ignoring this node.\n", __FILE__, __LINE__); - continue; - } + for (node = children_node ; node; node = node->next) { + const xmlChar *child_name = NULL; + + + child_name = node->name; + if (child_name == NULL) { + osync_trace(TRACE_ERROR, "%s:%i: ERROR: child_name = NULL. Ignoring this node.\n", __FILE__, __LINE__); + continue; + } - if (child_name[0] == 0) { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: child_name[0] = 0. Ignoring this node.\n", __FILE__, __LINE__); - continue; - } + if (child_name[0] == 0) { + osync_trace(TRACE_ERROR, "%s:%i: ERROR: child_name[0] = 0. Ignoring this node.\n", __FILE__, __LINE__); + continue; + } - if (!xmlStrcmp(child_name, (xmlChar *)"attribute")) { + if (!xmlStrcmp(child_name, (xmlChar *)"attribute")) { #ifdef DEBUG_convert_xmlinternal2ldap - ldap_plugin_printf("%s:%i: attribute found! (2)", __FILE__, __LINE__); + ldap_plugin_printf("%s:%i: Attribute found (2):", __FILE__, __LINE__); #endif - for (attribute_node = node->children; attribute_node; attribute_node = attribute_node->next) { - if (!xmlStrcmp(attribute_node->name, (xmlChar *)"name")) { - xmlChar *buf = xmlNodeGetContent(attribute_node); - // if (xmlNodeGetContent(attribute_node) != NULL) { - if (buf) { - if (*attr1_name == NULL) { - // *attr1_name = g_strdup_printf("%s", xmlNodeGetContent(attribute_node)); - *attr1_name = g_strdup_printf("%s", buf); - - } else if (*attr2_name == NULL) { - // *attr2_name = g_strdup_printf("%s", xmlNodeGetContent(attribute_node)); - *attr2_name = g_strdup_printf("%s", buf); - } else { - osync_trace(TRACE_ERROR, "%s:%i: WARNING: Maximal number of attributes already exhausted. Ignoring this one (name = \"%s\").\n", __FILE__, __LINE__, xmlNodeGetContent(attribute_node)); - } // if (*attr1_name == NULL) + for (attribute_node = node->children; attribute_node; attribute_node = attribute_node->next) { + if (!xmlStrcmp(attribute_node->name, (xmlChar *)"name")) { + xmlChar *buf = xmlNodeGetContent(attribute_node); + // if (xmlNodeGetContent(attribute_node) != NULL) { + if (buf) { + if (*attr1_name == NULL) { + // *attr1_name = g_strdup_printf("%s", xmlNodeGetContent(attribute_node)); + *attr1_name = g_strdup_printf("%s", buf); + + } else if (*attr2_name == NULL) { + // *attr2_name = g_strdup_printf("%s", xmlNodeGetContent(attribute_node)); + *attr2_name = g_strdup_printf("%s", buf); + } else { + osync_trace(TRACE_ERROR, "%s:%i: WARNING: Maximal number of attributes already exhausted. Ignoring this one (name = \"%s\").\n", __FILE__, __LINE__, xmlNodeGetContent(attribute_node)); + } // if (*attr1_name == NULL) - xmlFree(buf); - buf = NULL; + xmlFree(buf); + buf = NULL; + } else { + osync_trace(TRACE_ERROR, "%s:%i: WARNING: Empty attribute name returned. Ignoring this attribute.\n", __FILE__, __LINE__); + } // if (xmlNodeGetContent(attribute_node) != NULL) + } // if (!xmlStrcmp(attribute_node->name, (xmlChar *)"name")) + + if (!xmlStrcmp(attribute_node->name, (xmlChar *)"value")) { + xmlChar *content1 = xmlNodeGetContent(attribute_node); + if (content1 != NULL) { + + if (*attr1_value == NULL) { + *attr1_value = g_strdup_printf("%s", content1); + } else if (*attr2_value == NULL) { + *attr2_value = g_strdup_printf("%s", content1); } else { - osync_trace(TRACE_ERROR, "%s:%i: WARNING: Empty attribute name returned. Ignoring this attribute.\n", __FILE__, __LINE__); - } // if (xmlNodeGetContent(attribute_node) != NULL) - } // if (!xmlStrcmp(attribute_node->name, (xmlChar *)"name")) - - if (!xmlStrcmp(attribute_node->name, (xmlChar *)"value")) { - xmlChar *content1 = xmlNodeGetContent(attribute_node); - if (content1 != NULL) { - - if (*attr1_value == NULL) { - *attr1_value = g_strdup_printf("%s", content1); - } else if (*attr2_value == NULL) { - *attr2_value = g_strdup_printf("%s", content1); - } else { - osync_trace(TRACE_ERROR, "%s:%i: WARNING: Maximal number of attributes already exhausted. Ignoring this one (value = \"%s\").\n", __FILE__, __LINE__, xmlNodeGetContent(attribute_node)); - } // if (*attr1_value == NULL) { + osync_trace(TRACE_ERROR, "%s:%i: WARNING: Maximal number of attributes already exhausted. Ignoring this one (value = \"%s\").\n", __FILE__, __LINE__, xmlNodeGetContent(attribute_node)); + } // if (*attr1_value == NULL) { - xmlFree(content1); - content1 = NULL; + xmlFree(content1); + content1 = NULL; - } else { - osync_trace(TRACE_ERROR, "%s:%i: WARNING: Empty attribute name returned. Ignoring this attribute.\n", __FILE__, __LINE__); - } // if (xmlNodeGetContent(attribute_node) != NULL) - } // if (!xmlStrcmp(attribute_node->name, (xmlChar *)"value")) - } // for (xmlNode *attribute_node... - } // if (!xmlStrcmp(child_name, (xmlChar *)"attribute")) - } // for (xmlNode *node = children_node - } // if (children_node) + } else { + osync_trace(TRACE_ERROR, "%s:%i: WARNING: Empty attribute name returned. Ignoring this attribute.\n", __FILE__, __LINE__); + } // if (xmlNodeGetContent(attribute_node) != NULL) + } // if (!xmlStrcmp(attribute_node->name, (xmlChar *)"value")) + } // for (xmlNode *attribute_node... + } // if (!xmlStrcmp(child_name, (xmlChar *)"attribute")) + } // for (xmlNode *node = children_node #ifdef DEBUG_convert_xmlinternal2ldap @@ -1391,7 +1394,7 @@ * @returns TRUE on success, FALSE in case of any errors. */ -static osync_bool ldap_format_parse_xml_subentry(const xmlNode *xmlnode, const gchar *dn, complex_elements *element_lists, GList **ldap_entries, OSyncError **error) +static osync_bool ldap_format_do_parse_xml_subentry(const xmlNode *xmlnode, const gchar *dn, complex_elements *element_lists, GList **ldap_entries, OSyncError **error) { xmlChar *name = NULL; xmlChar *value = NULL; @@ -1413,7 +1416,7 @@ if (!xmlnode) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: subentry_node = NULL.\n", __FILE__, __LINE__); + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: xmlnode = NULL (was: subentry_node).\n", __FILE__, __LINE__); goto error; } @@ -1445,8 +1448,9 @@ goto error; } - - +#ifdef DEBUG_convert_xmlinternal2ldap + ldap_plugin_printf("%s:%i: name = \"%s\"", __FILE__, __LINE__, __NULLSTR((char *)name)); +#endif if (!strcmp((char *)name, "TimezoneComponent")) { if (!ldap_format_add_counter_suffix(&element_lists->timezone_components, &name, error)) @@ -1545,6 +1549,9 @@ if (!strncmp((char *)name, "AddressLabel", 12)) { + if (value) + xmlFree(value); + value = xmlNodeGetContent((xmlNode *)xmlnode); if (value == NULL) { osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: value = NULL.\n", __FILE__, __LINE__); @@ -1553,27 +1560,23 @@ } - ldapmods_subentry = ldap_format_append_ldapmod(ldapmods_subentry, (gchar *)"objectClass", (gchar *)"organizationalUnit"); -#if 1 - // xxx jl: Wasn't here before... if (name && name[0]) { ldapmods_subentry = ldap_format_append_ldapmod(ldapmods_subentry, (gchar *)"ou", (gchar *)name); } -#endif - if (value && value[0]) { - ldapmods_subentry = ldap_format_append_ldapmod(ldapmods_subentry, (gchar *)"description", (gchar *)value); + if (value) { + if (value[0]) { + ldapmods_subentry = ldap_format_append_ldapmod(ldapmods_subentry, (gchar *)"description", (gchar *)value); + } + xmlFree(value); value = NULL; } - - - // Look for any XML attributes if (!ldap_format_get_attributes(xmlnode, &attr1_name, &attr1_value, &attr2_name, &attr2_value, error)) { osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_format_get_attributes() has failed.\n", __FILE__, __LINE__); @@ -1597,9 +1600,6 @@ } - - - // Now create the ldap_subentry out of those mods ldap_subentry = ldap_format_create_ldap_entry_from_ldapmods(ldapmods_subentry); if (ldap_subentry == NULL) { @@ -1667,6 +1667,10 @@ for (node = children_node; node; node = node->next) { const xmlChar *child_name = node->name; + + + + if (child_name == NULL) { osync_trace(TRACE_ERROR, "%s:%i: WARNING: child_name = NULL. Ignoring this node.\n", __FILE__, __LINE__); @@ -1683,6 +1687,10 @@ continue; } +#ifdef DEBUG_convert_xmlinternal2ldap + ldap_plugin_printf("%s:%i: child_name = \"%s\"", __FILE__, __LINE__, __NULLSTR((char *)child_name)); +#endif + xmlChar *child_value = xmlNodeGetContent(node); @@ -1694,6 +1702,10 @@ if (child_value[0] == 0) { osync_trace(TRACE_INTERNAL, "%s:%i: WARNING: child_value[0] = 0. Ignoring this node with child_name = \"%s\"\n", __FILE__, __LINE__, child_name); + + xmlFree(child_value); + child_value = NULL; + continue; } @@ -1781,7 +1793,7 @@ ldapmods_subentry = NULL; } - // new_name is freed in ldap_format_convert_xmlinternal2ldap() + // new_name will be freed in ldap_format_convert_xmlinternal2ldap() if (attr1_name) { g_free(attr1_name); @@ -1819,7 +1831,7 @@ ldapmods_subentry = NULL; } - // new_name is freed in ldap_format_convert_xmlinternal2ldap() + // new_name will be freed in ldap_format_convert_xmlinternal2ldap() if (attr1_name) { g_free(attr1_name); @@ -1965,7 +1977,7 @@ } - + // Free any references still present in user_data if (!ldap_format_finalize_format1(user_data, error)) { if (!osync_error_is_set(error)) osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: ldap_format_finalize_format1() has failed.", __FILE__, __LINE__); @@ -1974,6 +1986,33 @@ } + // http://localhost/usr_share_doc/libxslt-devel-1.1.26/html/libxslt-xslt.html#xsltCleanupGlobals + xsltCleanupGlobals(); + + + // http://localhost/usr_share_doc/libxml2-devel-2.7.6/html/libxml-parser.html#xmlCleanupParser + /* + * "This function name is somewhat misleading. It does not clean up + * parser state, it cleans up memory allocated by the library itself. + * It is a cleanup function for the XML library. It tries to reclaim all + * related global memory allocated for the library processing. + * It doesn't deallocate any document related memory. One should call + * xmlCleanupParser() only when the process has finished using the library + * and all XML/HTML documents built with it. See also xmlInitParser() + * which has the opposite function of preparing the library for operations. + * WARNING: if your application is multithreaded or has + * plugin support calling this may crash the application if another thread + * or a plugin is still using libxml2. It's sometimes very hard to guess + * if libxml2 is in use in the application, some libraries or plugins + * may use it without notice. In case of doubt abstain from calling + * this function or do it just before calling exit() to avoid leak reports + * from valgrind!" + * + */ +#ifdef ENABLE_XML_CLEANUP_PARSER + xmlCleanupParser(); +#endif + osync_trace(TRACE_EXIT, "%s", __func__); return TRUE; @@ -2045,7 +2084,7 @@ OSyncXMLFormatSchema *xmlformat_schema = osync_xmlformat_schema_new(objtype, error); if (xmlformat_schema) { if (osync_xmlformat_schema_validate (xmlformat_schema, xmlformat, error)) { -#ifdef DEBUG_do_apply_stylesheet +#ifdef DEBUG_apply_stylesheet ldap_plugin_printf("%s:%i: OK. XML result as produced by means of \"%s\" is valid.\n", __FILE__, __LINE__, stylesheet_file); #endif @@ -2209,19 +2248,19 @@ if (dtd) { -#ifdef DEBUG_do_apply_stylesheet +#ifdef DEBUG_apply_stylesheet ldap_plugin_printf("\n\n\n--------------"); #endif if (!xmlSchemaValidateDoc(dtd, xmlcard)) { -#ifdef DEBUG_do_apply_stylesheet +#ifdef DEBUG_apply_stylesheet ldap_plugin_printf("%s:%i: OK. XML result as produced by means of \"%s\" is valid.", __FILE__, __LINE__, stylesheet_file); #endif osync_trace(TRACE_INTERNAL, "%s:%i: OK. Resulting xmlformat as produced by means of \"%s\" is valid.", __FILE__, __LINE__, stylesheet_file); -#ifdef DEBUG_do_apply_stylesheet +#ifdef DEBUG_apply_stylesheet ldap_plugin_printf("-------------\n\n"); #endif @@ -2256,6 +2295,7 @@ xmlChar *xmlbuffer = NULL; int xmlbuffer_size = 0; + xmlIndentTreeOutput = 1; xmlDocDumpFormatMemory(xmlcard, &xmlbuffer, &xmlbuffer_size, 1); if (xmlbuffer) { @@ -2265,7 +2305,7 @@ } -#ifdef DEBUG_do_apply_stylesheet +#ifdef DEBUG_apply_stylesheet ldap_plugin_printf("-------------\n\n"); #endif @@ -2565,7 +2605,7 @@ * */ -static osync_bool ldap_format_do_apply_stylesheet(char *input, unsigned int inpsize, char **output, unsigned int *outpsize, const char *config, void *user_data, const char *stylesheet_file, OSyncError **error) +static osync_bool ldap_format_apply_stylesheet(char *input, unsigned int inpsize, char **output, unsigned int *outpsize, const char *config, void *user_data, const char *stylesheet_file, OSyncError **error) { unsigned int size = 0 ; char *str = NULL; @@ -2582,6 +2622,7 @@ osync_trace(TRACE_ENTRY, "%s(%p, %u, %p, %p, %p, %p, %p, %p)", __func__, (void *)input, inpsize, (void *)output, (void *)outpsize, (void *)config, (void *)user_data, (void *)stylesheet_file, (void *)error); + if (config) { if (config[0]) { osync_trace(TRACE_INTERNAL, "%s(): config = \"%s\"", __func__, config); @@ -2625,10 +2666,9 @@ -#ifdef DEBUG_do_apply_stylesheet +#ifdef DEBUG_apply_stylesheet ldap_plugin_printf("\n\n\n\n%s:%i:%s(): ", __FILE__, __LINE__, __func__); ldap_plugin_printf("inpsize = %u bytes", inpsize); - ldap_plugin_printf("input = \n\"%.*s\"\n", inpsize, input); #endif @@ -2637,32 +2677,68 @@ // First off, try and find out what type of data has been casted to char *: + osync_trace(TRACE_INTERNAL, "%s:%i: What is input? inpsize = %i", __FILE__, __LINE__, inpsize); + if (inpsize >= 6 && !strncmp(input, "<?xml ", 6)) { +#ifdef DEBUG_apply_stylesheet + ldap_plugin_printf("input = \n\"%.*s\"\n", inpsize, input); +#endif + osync_trace(TRACE_INTERNAL, "%s:%i: Looks like a human-readable XML string.", __FILE__, __LINE__); // Convert an xmlChar string of the input into an xmlDoc struct: input_doc = xmlParseMemory(input, inpsize); - } else { - osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: input does not seem to be a human readable xml string.\n", __FILE__, __LINE__); + } else if (inpsize == osync_xmlformat_size()) { + unsigned int buf_size = 0; + char *buf = NULL; - osync_trace(TRACE_INTERNAL, "%s:%i: What is input? inpsize = %i", __FILE__, __LINE__, inpsize); - if (inpsize == osync_xmlformat_size()) { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: Looks like opensync specific xmlformat.\n", __FILE__, __LINE__); + osync_trace(TRACE_INTERNAL, "%s:%i: Looks like the opensync specific xmlformat.\n", __FILE__, __LINE__); - } else if (inpsize == 0) { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: inpsize = 0.\n", __FILE__, __LINE__); - } else if (inpsize == sizeof(glist_container)) { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: Looks like a glist_container.", __FILE__, __LINE__); + // Convert from OSyncXMLFormat to a human-readable XML string: + xmlIndentTreeOutput = 1; + if (!osync_xmlformat_assemble((OSyncXMLFormat *)input, &buf, &buf_size, error)) + { + if (!osync_error_is_set(error)) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: osync_xmlformat_assemble() has failed.", __FILE__, __LINE__); + } - } else if (inpsize == sizeof(GList)) { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: Looks like a GList.", __FILE__, __LINE__); + goto error; + } - } else { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: Could be xmlinternal?\n", __FILE__, __LINE__); + if (buf == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: osync_xmlformat_assemble() has failed (1).\n", __FILE__, __LINE__); + goto error; + } + + if (buf_size == 0) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: osync_xmlformat_assemble() has failed (2).\n", __FILE__, __LINE__); + xmlFree(buf); + buf = NULL; + goto error; } + + // Convert an xmlChar string of the input into an xmlDoc struct: + input_doc = xmlParseMemory(buf, buf_size); + xmlFree(buf); + buf = NULL; + + } else if (inpsize == 0) { + osync_trace(TRACE_ERROR, "%s:%i: ERROR: inpsize = 0.\n", __FILE__, __LINE__); + goto error; + + } else if (inpsize == sizeof(glist_container)) { + osync_trace(TRACE_ERROR, "%s:%i: ERROR: Looks like a glist_container.", __FILE__, __LINE__); + goto error; + + } else if (inpsize == sizeof(GList)) { + osync_trace(TRACE_ERROR, "%s:%i: ERROR: Looks like a GList.", __FILE__, __LINE__); + goto error; + + } else { + osync_trace(TRACE_ERROR, "%s:%i: ERROR: Don't know what that is.\n", __FILE__, __LINE__); goto error; } @@ -2741,12 +2817,12 @@ } if (xmlbuffer == NULL) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: xmlDocDumpMemory() has failed.\n", __FILE__, __LINE__); + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: xmlDocDumpFormatMemory() has failed.\n", __FILE__, __LINE__); goto error; } -#ifdef DEBUG_do_apply_stylesheet +#ifdef DEBUG_apply_stylesheet ldap_plugin_printf("%s:%i: %s: Result from conversion = \n\"%s\"", __FILE__, __LINE__, __func__, xmlbuffer); #endif @@ -2754,7 +2830,7 @@ if (xmlbuffer_size >= 6) { if (!strncmp((char *)xmlbuffer, "<?xml ", 6)) { -#ifdef DEBUG_do_apply_stylesheet +#ifdef DEBUG_apply_stylesheet ldap_plugin_printf("%s:%i: OK. xmlbuffer starts with <?xml.", __FILE__, __LINE__); #endif } else { @@ -2786,7 +2862,7 @@ -#ifdef DEBUG_do_apply_stylesheet +#ifdef DEBUG_apply_stylesheet ldap_plugin_printf("%s:%i: ---------- <osync_xmlformat_parse()> -----------", __FILE__, __LINE__); #endif @@ -2798,7 +2874,7 @@ osync_trace(TRACE_INTERNAL, "%s:%i: This needs to be freed eventually. But by whom? And where and when exactly?", __FILE__, __LINE__); -#ifdef DEBUG_do_apply_stylesheet +#ifdef DEBUG_apply_stylesheet ldap_plugin_printf("%s:%i: ---------- </osync_xmlformat_parse()> -----------", __FILE__, __LINE__); #endif @@ -2886,6 +2962,7 @@ *outpsize = osync_xmlformat_size(); // Returns the size of the OSyncXMLFormat struct. + xmlIndentTreeOutput = 1; if (!osync_xmlformat_assemble(xmlformat, &str, &size, error)) { if (!osync_error_is_set(error)) { @@ -2922,7 +2999,6 @@ } - if (xmlcard) { xmlFreeDoc(xmlcard); xmlcard = NULL; @@ -2990,7 +3066,7 @@ xmlFree(xmlbuffer); xmlbuffer = NULL; } - + if (fullpath) { g_free(fullpath); fullpath = NULL; @@ -3007,106 +3083,6 @@ -/** - * @brief Ensures that do_apply_stylesheet is always provided with - * human readable xml data rather than with a libopensync specific xmlformat - * struct. - * - * Sometimes a human readable xml document comes from the peer, and sometimes - * an xmlformat struct, specific to libopensync. This function converts - * the latter one to the human readable version. This is to make sure - * that the main conversion function will always be provided with one - * and the same format type. This does NOT mean that the result would - * not be accompanied with an xmlformat. - * - * @param input The document to be converted. - * @param inpsize Its size. - * @param output This will contain the result after conversion - * @param outpsize Its size. - * @param config ??? - * @param user_data Points to a user_data_carrier struct, that has been - * allocated in ldap_format_initialize_converter(). - * @param stylesheet The particular XSLT stylesheet to be used. - * @param error if something bad happens and you cannot convert, set the error! - * - * @returns TRUE on success, FALSE on failure - */ -static osync_bool ldap_format_apply_stylesheet_workaround(char *input, unsigned int inpsize, char **output, unsigned int *outpsize, const char *config, void *user_data, const char *stylesheet, OSyncError **error) -{ - osync_trace(TRACE_ENTRY, "%s(%p, %u, %p, %p, %p, %p, %p, %p)", __func__, (void *)input, inpsize, (void *)output, (void *)outpsize, (void *)config, user_data, (void *)stylesheet, (void *)error); - - - if (stylesheet == NULL) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: stylesheet = NULL.\n", __FILE__, __LINE__); - goto error; - } - - - // EITHER this function is provided with a human readable xml string OR - // with an opensync specific xmlformat. But not sometimes the former, - // and at other times the latter format. So right now, we choose - // the human readable format. - if (inpsize >= 6 && !strncmp(input, "<?xml ", 6)) { - if (!ldap_format_do_apply_stylesheet(input, inpsize, output, outpsize, config, user_data, stylesheet, error)) { - if (!osync_error_is_set(error)) - osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: ldap_format_do_apply_stylesheet() has failed.\n\n", __FILE__, __LINE__); - - goto error; - } - - osync_trace(TRACE_EXIT, "%s", __func__); - return TRUE; - - - } else { - unsigned int size = 0; - char *buf = NULL; - - - if (!osync_xmlformat_assemble((OSyncXMLFormat *)input, &buf, &size, error)) - { - if (!osync_error_is_set(error)) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: osync_xmlformat_assemble() has failed.", __FILE__, __LINE__); - } - - goto error; - } - - if (buf == NULL) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: osync_xmlformat_assemble() has failed (1).\n", __FILE__, __LINE__); - goto error; - } - - if (size == 0) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: osync_xmlformat_assemble() has failed (2).\n", __FILE__, __LINE__); - goto error; - } - - - - osync_bool rv = ldap_format_do_apply_stylesheet(buf, size, output, outpsize, config, user_data, stylesheet, error); - - if (buf) { - g_free(buf); - buf = NULL; - size = 0; - } - - - osync_trace(TRACE_EXIT, "%s(): Return value of ldap_format_do_apply_stylesheet(): %s", __func__, rv ? "TRUE" : "FALSE"); - return rv; - -error: - if (!osync_error_is_set(error)) - osync_error_set(error, OSYNC_ERROR_GENERIC, "Unknown reason.\n"); - - osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); - return FALSE; - } -} - - - /** * @brief This function adds a subentry to an XML tree. @@ -3292,13 +3268,6 @@ continue; } -#if 0 -#ifdef DEBUG_convert_ldap2xmlinternal - ldap_plugin_printf("%s:%i:", __FILE__, __LINE__); - ldap_plugin_printf("token = \"%s\"", token); - ldap_plugin_printf("node2->name = \"%s\"", node2->name); -#endif -#endif if (g_strstr_len((gchar *)token, -1, (gchar *)node2->name)) { possible_parent = node2; @@ -3421,6 +3390,10 @@ // This is the base entry. Its attribute name ("description") is // at the same time the name of the XML element *name = xmlStrdup((xmlChar *)mod->mod_type); + + if (*value) + xmlFree(*value); + *value = xmlStrdup((xmlChar *)mod->mod_bvalues[0]->bv_val); } else { @@ -3445,36 +3418,80 @@ if (!strncmp((char *)n, "TimezoneRule", 12)) { *name = xmlStrdup((xmlChar *)"TimezoneRule"); + + if (*value) + xmlFree(*value); + *value = xmlStrdup((xmlChar *)""); } else if (!strncmp((char *)n, "TimezoneComponent", 17)) { *name = xmlStrdup((xmlChar *)"TimezoneComponent"); + + if (*value) + xmlFree(*value); + *value = xmlStrdup((xmlChar *)""); } else if (!strncmp((char *)n, "postalAddress", 13)) { *name = xmlStrdup((xmlChar *)"postalAddress"); + + if (*value) + xmlFree(*value); + *value = xmlStrdup((xmlChar *)""); } else if (!strncmp((char *)n, "AlarmAudio", 10)) { *name = xmlStrdup((xmlChar *)"AlarmAudio"); + + if (*value) + xmlFree(*value); + *value = xmlStrdup((xmlChar *)""); } else if (!strncmp((char *)n, "AlarmDisplay", 12)) { *name = xmlStrdup((xmlChar *)"AlarmDisplay"); + + if (*value) + xmlFree(*value); + *value = xmlStrdup((xmlChar *)""); } else if (!strncmp((char *)n, "AlarmEmail", 10)) { *name = xmlStrdup((xmlChar *)"AlarmEmail"); + + if (*value) + xmlFree(*value); + *value = xmlStrdup((xmlChar *)""); } else if (!strncmp((char *)n, "AlarmProcedure", 14)) { *name = xmlStrdup((xmlChar *)"AlarmProcedure"); + + if (*value) + xmlFree(*value); + *value = xmlStrdup((xmlChar *)""); } else if (!strncmp((char *)n, "RecurrenceRule", 14)) { *name = xmlStrdup((xmlChar *)"RecurrenceRule"); + + if (*value) + xmlFree(*value); + *value = xmlStrdup((xmlChar *)""); } else if (!strncmp((char *)n, "RecurrenceRuleExtended", 22)) { *name = xmlStrdup((xmlChar *)"RecurrenceRuleExtended"); + + if (*value) + xmlFree(*value); + *value = xmlStrdup((xmlChar *)""); } else if (!strncmp((char *)n, "AddressLabel", 12)) { *name = xmlStrdup((xmlChar *)"AddressLabel"); + + if (*value) + xmlFree(*value); + *value = xmlStrdup((xmlChar *)""); } else if (!strncmp((char *)n, "Address", 7)) { *name = xmlStrdup((xmlChar *)"Address"); + + if (*value) + xmlFree(*value); + *value = xmlStrdup((xmlChar *)""); } else { *name = xmlStrdup((xmlChar *)(mod->mod_bvalues[0]->bv_val)); @@ -3491,6 +3508,9 @@ // "description" holds the value of an XML element. } else if (!strcmp(mod->mod_type, "description")) { + if (*value) + xmlFree(*value); + if ((xmlChar *)mod->mod_bvalues[0]->bv_val) { *value = xmlStrdup((xmlChar *)mod->mod_bvalues[0]->bv_val); } else { @@ -3563,7 +3583,7 @@ /** * @brief This function generates the head of an XML document. - * Helper function for ldap_format_convert_ldap2xmlinternal(). + * Helper function for ldap_format_do_convert_ldap2xmlinternal(). * * @param objtype The object type, such as "contact", "event", "todo" or "note". * @param ldap_format_name The format name, such as "ldap-evolutionperson". @@ -3575,7 +3595,7 @@ * @returns TRUE on success, FALSE in case of any error. */ osync_bool -ldap_format_convert_ldap2xmlinternal_create_head(const char *objtype, const char *ldap_format_name, xmlDoc **doc, xmlNode **root_node, OSyncError **error) +ldap_format_do_convert_ldap2xmlinternal_create_head(const char *objtype, const char *ldap_format_name, xmlDoc **doc, xmlNode **root_node, OSyncError **error) { @@ -3692,7 +3712,7 @@ /* * @brief This function generates the rest of an XML document, * after its head has been created. - * Helper function for ldap_format_convert_ldap2xmlinternal(). + * Helper function for ldap_format_do_convert_ldap2xmlinternal(). * * @param entry An LDAP entry struct, that is to be added as an * XML child. @@ -3705,7 +3725,7 @@ * @returns TRUE on success, FALSE in case of any error. */ osync_bool -ldap_format_convert_ldap2xmlinternal_add_child_nodes(const ldap_entry *entry, const osync_bool is_subentry, xmlNode **root_node, OSyncError **error) +ldap_format_do_convert_ldap2xmlinternal_add_child_nodes(const ldap_entry *entry, const osync_bool is_subentry, xmlNode **root_node, OSyncError **error) { xmlChar *name = NULL; xmlChar *value = NULL; @@ -3995,18 +4015,6 @@ continue; } -#if 0 -#ifdef DEBUG_convert_ldap2xmlinternal - if (token) { - ldap_plugin_printf("\n\ntoken = \"%s\"", token); - } else { - ldap_plugin_printf("\n\ntoken = NULL"); - } - ldap_plugin_printf("entry->dn = \"%s\"", entry->dn); - ldap_plugin_printf("entry->id = \"%s\"", entry->id); - ldap_plugin_printf("\n"); -#endif -#endif if (!ldap_format_add_xml_subsubentry(*root_node, (xmlChar *)token, name, value, attr1_name, attr1_value, attr2_name, attr2_value, error)) { osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_format_add_xml_subsubentry() has failed.\n", __FILE__, __LINE__); @@ -4145,7 +4153,7 @@ * */ -static xmlDoc *ldap_format_convert_ldap2xmlinternal(GList *ldap_entries, const char *objtype, const char *ldap_format_name, OSyncError **error) +static xmlDoc *ldap_format_do_convert_ldap2xmlinternal(GList *ldap_entries, const char *objtype, const char *ldap_format_name, OSyncError **error) { xmlDoc *doc = NULL; xmlNode *root_node = NULL; @@ -4185,9 +4193,9 @@ - if (!ldap_format_convert_ldap2xmlinternal_create_head(objtype, ldap_format_name, &doc, &root_node, error)) { + if (!ldap_format_do_convert_ldap2xmlinternal_create_head(objtype, ldap_format_name, &doc, &root_node, error)) { if (!osync_error_is_set(error)) - osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: ldap_format_convert_ldap2xmlinternal_create_head() has failed.", __FILE__, __LINE__); + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: ldap_format_do_convert_ldap2xmlinternal_create_head() has failed.", __FILE__, __LINE__); goto error; } @@ -4203,16 +4211,16 @@ } - if (!ldap_format_convert_ldap2xmlinternal_add_child_nodes(entry, i, &root_node, error)) { + if (!ldap_format_do_convert_ldap2xmlinternal_add_child_nodes(entry, i, &root_node, error)) { if (osync_error_is_set(error)) { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_format_convert_ldap2xmlinternal_add_child_nodes() has failed: \"%s\". Ignoring this ldap entry.", __FILE__, __LINE__, osync_error_print(error)); + osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_format_do_convert_ldap2xmlinternal_add_child_nodes() has failed: \"%s\". Ignoring this ldap entry.", __FILE__, __LINE__, osync_error_print(error)); osync_error_unref(error); } else { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_format_convert_ldap2xmlinternal_add_child_nodes() has failed. Ignoring this ldap entry.\n", __FILE__, __LINE__); + osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_format_do_convert_ldap2xmlinternal_add_child_nodes() has failed. Ignoring this ldap entry.\n", __FILE__, __LINE__); } continue; - } // if (!ldap_format_convert_ldap2xmlinternal_add_child_nodes) + } // if (!ldap_format_do_convert_ldap2xmlinternal_add_child_nodes) // And now the subentries. @@ -4224,16 +4232,16 @@ ldap_entry *subentry = g_list_nth_data(entry->subentries, j); - if (!ldap_format_convert_ldap2xmlinternal_add_child_nodes(subentry, TRUE, &root_node, error)) { + if (!ldap_format_do_convert_ldap2xmlinternal_add_child_nodes(subentry, TRUE, &root_node, error)) { if (osync_error_is_set(error)) { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_format_convert_ldap2xmlinternal_add_child_nodes() has failed: \"%s\". Ignoring this LDAP subentry.", __FILE__, __LINE__, osync_error_print(error)); + osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_format_do_convert_ldap2xmlinternal_add_child_nodes() has failed: \"%s\". Ignoring this LDAP subentry.", __FILE__, __LINE__, osync_error_print(error)); osync_error_unref(error); } else { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_format_convert_ldap2xmlinternal_add_child_nodes() has failed. Ignoring this LDAP subentry.\n", __FILE__, __LINE__); + osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_format_do_convert_ldap2xmlinternal_add_child_nodes() has failed. Ignoring this LDAP subentry.\n", __FILE__, __LINE__); } continue; - } // if (!ldap_format_convert_ldap2xmlinternal_add_child_nodes) + } // if (!ldap_format_do_convert_ldap2xmlinternal_add_child_nodes) } // for (j = 0; i < subentry_max; j++) } // if (entry->subentries) } // for (i = 0; i < g_list_length(ldap_entries); i++) @@ -4397,7 +4405,7 @@ ldap_plugin_printf("%s:%i:%s(): Input:", __FILE__, __LINE__, __func__); xmlIndentTreeOutput = 1; - xmlDocDumpMemory((xmlDoc *)xmldata, &b, &b_size); + xmlDocDumpFormatMemory((xmlDoc *)xmldata, &b, &b_size, 1); if (b) { if (b[0]) { @@ -4430,22 +4438,335 @@ - if (buf) { - g_free(buf); - buf = NULL; - } - + if (buf) { + g_free(buf); + buf = NULL; + } + + + + osync_trace(TRACE_EXIT, "%s(): *root = %p, (*root)->name = \"%s\"", __func__, (void *) *root, (*root)->name); + return TRUE; + +error: + if (buf) { + g_free(buf); + buf = NULL; + } + + if (!osync_error_is_set(error)) + osync_error_set(error, OSYNC_ERROR_GENERIC, "Unknown reason.\n"); + + osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); + return FALSE; +} + + + + +/** + * @brief This function maps from certain XML subnodes to LDAP subentries. + * Helper function for ldap_format_do_parse_xmlinternal_child_nodes(). + * + * @param subentry_node An XML node below of the top level (below of the + * root level) + * @param dn The distinguished name in terms of LDAP intended for this subentry. + * @param complex_element_lists Several glists of LDAP subentries for certain + * special elements. + * @param potential_subentries As a result of this function this glist will + * be filled with LDAP subentries. + * @param error The libopensync error pointer. + * + * @returns TRUE on success, FALSE in case of any error + */ + +osync_bool ldap_format_parse_xml_subentry(xmlNode *subentry_node, const char *dn, complex_elements *complex_element_lists, GList **potential_subentries, OSyncError **error) +{ + GList *ldap_subentries = NULL; + ldap_entry *ldap_subentry = NULL; + unsigned int i = 0; + + + osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p)", __func__, (void *)subentry_node, (void *)dn, (void *)complex_element_lists, (void *)potential_subentries, (void *)error); + + + + if (!subentry_node) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: subentry_node = NULL (was: subentry_node).\n", __FILE__, __LINE__); + goto error; + } + + if (complex_element_lists == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: complex_element_lists = NULL.\n", __FILE__, __LINE__); + goto error; + } + + if (potential_subentries == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: potential_subentries = NULL.\n", __FILE__, __LINE__); + goto error; + } + + if (dn == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: dn = NULL.\n", __FILE__, __LINE__); + goto error; + } + + + if (!ldap_format_do_parse_xml_subentry(subentry_node, dn, complex_element_lists, &ldap_subentries, error)) { + if (!osync_error_is_set(error)) { + osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_format_do_parse_xml_subentry() has failed. Ignoring this xml subentry.\n", __FILE__, __LINE__); + } else { + osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_format_do_parse_xml_subentry() has failed: \"%s\". Ignoring this xml subentry.\n", __FILE__, __LINE__, osync_error_print(error)); + osync_error_unref(error); + } + + goto out1; + } + + + if (ldap_subentries == NULL) { + osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_subentries = NULL. Ignoring.\n", __FILE__, __LINE__); + goto out1; + } + + + // Add the result from the parsing of the subentry element to + // the GList *potential_subentries + unsigned int max = g_list_length(ldap_subentries); + +#ifdef DEBUG_convert_xmlinternal2ldap + osync_trace(TRACE_ERROR, "\n%s:%i: max = %u\n", __FILE__, __LINE__, max); +#endif + + for (i = 0; i < max; i++) { + ldap_subentry = g_list_nth_data(ldap_subentries, i); + if (!ldap_subentry) { + osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_subentry is NULL. ldap_format_do_parse_xml_subentry() must have failed. Ignoring this xml subentry.\n", __FILE__, __LINE__); + continue; + } + + + if (ldap_subentry->id == NULL) { + osync_trace(TRACE_ERROR, "%s:%i: ERROR: id = NULL. Skipping this subentry.\n", __FILE__, __LINE__); + continue; + } + + osync_assert(potential_subentries != NULL); + *potential_subentries = g_list_append(*potential_subentries, ldap_subentry); + if (*potential_subentries == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: g_list_append() has produced a NULL pointer.\n", __FILE__, __LINE__); + goto error; + } + } + + g_list_free(ldap_subentries); + ldap_subentries = NULL; + + +out1: + osync_trace(TRACE_EXIT, "%s()", __func__); + return TRUE; + + +error: + if (!osync_error_is_set(error)) + osync_error_set(error, OSYNC_ERROR_GENERIC, "Unknown reason.\n"); + + osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); + return FALSE; +} + + + + + +/** + * @brief This function parses the child nodes for a particular + * XML node and calls the necessary functions to translate them + * into LDAP subentries. + * + * @param dn The distinguished name in terms of LDAP intended for + * the LDAP entry that is to be created by this function. + * @param name The name of the current XML element. + * @param xmlnode The XML node with 0 or more child nodes that will + * become LDAP subentries. + * @param value The value of the current XML element. + * @param complex_element_lists GLists of LDAP entries for several special + * elements. + * @param potential_subentries As a result of this function this glist will + * be filled with LDAP subentries. These LDAP + * LDAP subentries will be derived from the + * XML child nodes. + * @param attr1_name The name of the first XML attribute, if present, at all. + * @param attr1_value The value of the first XML attribute, if present. + * @param attr2_name The name of the second XML attribute, if present, at all. + * @param attr2_value The value of the second XML attribute, if present. + * @param error The libopensync error pointer. + * + * @returns TRUE on succeess, FALSE in case of any error. + */ +osync_bool ldap_format_do_parse_xmlinternal_child_nodes(const char *dn, const xmlChar *name, const xmlNode *xmlnode, xmlChar **value, complex_elements *complex_element_lists, GList **potential_subentries, char **attr1_name, char **attr1_value, char **attr2_name, char **attr2_value, OSyncError **error) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p)", __func__, (void *)dn, (void *)name, (void *)xmlnode, (void *)value, (void *)complex_element_lists, (void *)potential_subentries, (void *)attr1_name, (void *)attr1_value, (void *)attr2_name, (void *)attr2_value, (void *)error); + + + if (dn == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: dn = NULL.\n", __FILE__, __LINE__); + goto error; + } + + if (name == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: name = NULL.\n", __FILE__, __LINE__); + goto error; + } + + if (xmlnode == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: xmlnode = NULL.\n", __FILE__, __LINE__); + goto error; + } + + if (xmlnode->xmlChildrenNode == NULL) { + osync_trace(TRACE_INTERNAL, "%s:%i: WARNING: xmlnode->xmlChildrenNode = NULL with dn = \"%s\". Ignoring.\n", __FILE__, __LINE__, __NULLSTR(dn)); + goto out1; + } + + if (complex_element_lists == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: complex_element_lists = NULL.\n", __FILE__, __LINE__); + goto error; + } + + if (potential_subentries == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: potential_subentries = NULL.\n", __FILE__, __LINE__); + goto error; + } + + if (attr1_name == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: attr1_name = NULL.\n", __FILE__, __LINE__); + goto error; + } + + if (attr2_name == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: attr2_name = NULL.\n", __FILE__, __LINE__); + goto error; + } + + if (attr1_value == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: attr1_value = NULL.\n", __FILE__, __LINE__); + goto error; + } + + if (attr2_value == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: attr2_value = NULL.\n", __FILE__, __LINE__); + goto error; + } + + + // This is an XML element, that is intended to be located one level lower + // in the DIT: <subentry>...</subentry> + if (!strcmp((char *)name, "subentry")) { + xmlNode *subentry_node = NULL; + + + subentry_node = xmlnode->xmlChildrenNode->next; + if (subentry_node && strcmp((char *)subentry_node->name, "subentry") && strcmp((char *)subentry_node->name, "attribute")) { + +#ifdef DEBUG_convert_xmlinternal2ldap + ldap_plugin_printf("%s:%i: subentry_node->name = \"%s\"", __FILE__, __LINE__, __NULLSTR((char *)subentry_node->name)); +#endif + + if (!ldap_format_parse_xml_subentry(subentry_node, dn, complex_element_lists, potential_subentries, error)) { + goto error; + } + + } else { + subentry_node = xmlnode->xmlChildrenNode; + + while (subentry_node) { +#ifdef DEBUG_convert_xmlinternal2ldap + ldap_plugin_printf("%s:%i: subentry_node->name = \"%s\"", __FILE__, __LINE__, __NULLSTR((char *)subentry_node->name)); +#endif + + if (subentry_node->name == NULL) + break; + + if (strcmp((char *)subentry_node->name, "subentry") && strcmp((char *)subentry_node->name, "attribute")) { + if (!ldap_format_parse_xml_subentry(subentry_node, dn, complex_element_lists, potential_subentries, error)) { + goto error; + } + } + + subentry_node = subentry_node->next; + } + } + } // if (!strcmp((char *)name, "subentry")) + + + + + // Look for any XML attribute elements + if (!strcmp((char *)xmlnode->xmlChildrenNode->name, "attribute")) { + + osync_trace(TRACE_INTERNAL, "%s:%i: WARNING: XML attributes are NOT allowed on the level of the base entry, because there is not a single LDAP attribute that could be abused for this. name = \"%s\"\n", __FILE__, __LINE__, name); + + if (!ldap_format_get_attributes(xmlnode->xmlChildrenNode, attr1_name, attr1_value, attr2_name, attr2_value, error)) { + osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_format_get_attributes() has failed.\n", __FILE__, __LINE__); + + if (!osync_error_is_set(error)) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: ldap_format_get_attributes() has failed.\n", __FILE__, __LINE__); + } + + goto error; + } // if (!ldap_format_get_attributes(xmlnode->xmlChildrenNode, &attr1_name, &attr1_value, &attr2_name, &attr2_value, error)) + + + xmlNode *m = xmlnode->xmlChildrenNode; + while(m) { + if (m->name == NULL) + break; + + if (strcmp((char *)m->name, "attribute")) { + *value = xmlNodeGetContent(m); + } + + m = m->next; + } + + } // if (!strcmp((char *)xmlnode->xmlChildrenNode->name, "attribute")) + + + +#ifdef DEBUG_convert_xmlinternal2ldap + if (attr1_name && attr1_name[0]) { + if (attr1_value) { + ldap_plugin_printf("%s:%i: Attribute found (1):", __FILE__, __LINE__); + ldap_plugin_printf("\"%s\" - \"%s\"", attr1_name, attr1_value); + + } else { + ldap_plugin_printf("%s:%i: ERROR: attr1_value = NULL", __FILE__, __LINE__); + } + } + + if (attr2_name && attr2_name[0]) { + if (attr2_value) { + ldap_plugin_printf("%s:%i: Attribute found (1):", __FILE__, __LINE__); + ldap_plugin_printf("\"%s\" - \"%s\"", attr2_name, attr2_value); + } else { + ldap_plugin_printf("%s:%i: ERROR: attr2_value = NULL.", __FILE__, __LINE__); + } + } +#endif + + + - osync_trace(TRACE_EXIT, "%s(): *root = %p, (*root)->name = \"%s\"", __func__, (void *) *root, (*root)->name); + +out1: + osync_trace(TRACE_EXIT, "%s()", __func__); return TRUE; -error: - if (buf) { - g_free(buf); - buf = NULL; - } +error: if (!osync_error_is_set(error)) osync_error_set(error, OSYNC_ERROR_GENERIC, "Unknown reason.\n"); @@ -4455,6 +4776,13 @@ + + + + + + + /** * @brief This function parses the XML document and extracts the bare * ldapmods and subentries. They will have to be supplemented by @@ -4514,7 +4842,6 @@ for (; xmlnode; xmlnode = xmlnode->next) { const xmlChar *name = NULL; xmlChar *value = NULL; - unsigned int i = 0; gchar *attr1_name = NULL; gchar *attr1_value = NULL; gchar *attr2_name = NULL; @@ -4523,192 +4850,95 @@ // Skip certain elements - if (xmlnode && xmlnode->name) { - // Omit "<contact>...</contact>" or "<note>...</note>" - if (!strcmp((char *)xmlnode->name, objtype)) { - osync_trace(TRACE_INTERNAL, "%s:%i:%s(): Skipping \"<%s>\" with objtype \"%s\"", __FILE__, __LINE__, __func__, (char *)xmlnode->name, objtype); - continue; - } + if (xmlnode) { + if (xmlnode->name) { + // Omit "<contact>...</contact>" or "<note>...</note>" + if (!strcmp((char *)xmlnode->name, objtype)) { + osync_trace(TRACE_INTERNAL, "%s:%i:%s(): Skipping \"<%s>\" with objtype \"%s\"", __FILE__, __LINE__, __func__, (char *)xmlnode->name, objtype); + continue; + } - if (!strcmp((char *)xmlnode->name, "text")) { - osync_trace(TRACE_INTERNAL, "%s:%i:%s(): Skipping \"<%s>\" with objtype \"%s\"", __FILE__, __LINE__, __func__, (char *)xmlnode->name, objtype); - continue; - } + // Omit "<text>...</text>" + if (!strcmp((char *)xmlnode->name, "text")) { + osync_trace(TRACE_INTERNAL, "%s:%i:%s(): Skipping \"<%s>\" with objtype \"%s\"", __FILE__, __LINE__, __func__, (char *)xmlnode->name, objtype); + continue; + } - if (!strcmp((char *)xmlnode->name, "comment")) { - osync_trace(TRACE_INTERNAL, "%s:%i:%s(): Skipping \"<%s>\" with objtype \"%s\"", __FILE__, __LINE__, __func__, (char *)xmlnode->name, objtype); + // Skip comments + if (!strcmp((char *)xmlnode->name, "comment")) { + osync_trace(TRACE_INTERNAL, "%s:%i:%s(): Skipping \"<%s>\" with objtype \"%s\"", __FILE__, __LINE__, __func__, (char *)xmlnode->name, objtype); + continue; + } + + } else { + osync_trace(TRACE_ERROR, "%s:%i: WARNING: xmlnode->name = NULL. Advancing to the next xmlnode.", __FILE__, __LINE__); continue; } + + } else { + osync_trace(TRACE_ERROR, "%s:%i: WARNING: xmlnode = NULL. Advancing to the next xmlnode.", __FILE__, __LINE__); + continue; } // Extract the name of this XML node name = xmlnode->name; if (name == NULL) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: name = NULL. Skipping this xmlnode.\n", __FILE__, __LINE__); + osync_trace(TRACE_ERROR, "%s:%i: WARNING: name = NULL. Skipping this xmlnode.\n", __FILE__, __LINE__); continue; } if (name[0] == 0) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: name[0] = 0. Skipping this xmlnode.\n", __FILE__, __LINE__); + osync_trace(TRACE_ERROR, "%s:%i: ERROR: name[0] = 0. Skipping this xmlnode.\n", __FILE__, __LINE__); continue; } - - - - // This is an XML element, that is intended to be located one level lower - // in the DIT: <subentry>...</subentry> - if (!strcmp((char *)name, "subentry")) { - xmlNode *subentry_node = NULL; - GList *ldap_subentries = NULL; - ldap_entry *ldap_subentry = NULL; - - - if (xmlnode->xmlChildrenNode) { - subentry_node = xmlnode->xmlChildrenNode->next; - } else { - osync_trace(TRACE_INTERNAL, "%s:%i: WARNING: xmlnode->xmlChildrenNode = NULL with dn = \"%s\". Ignoring.\n", __FILE__, __LINE__, dn); - continue; - } - - - if (!subentry_node) { - osync_trace(TRACE_INTERNAL, "%s:%i: WARNING: subentry_node = NULL with dn = \"%s\". Ignoring.\n", __FILE__, __LINE__, dn); - continue; - - } else { - if (!ldap_format_parse_xml_subentry(subentry_node, dn, complex_element_lists, &ldap_subentries, error)) { - if (!osync_error_is_set(error)) { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_format_parse_xml_subentry() has failed. Ignoring this xml subentry.\n", __FILE__, __LINE__); - } else { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_format_parse_xml_subentry() has failed: \"%s\". Ignoring this xml subentry.\n", __FILE__, __LINE__, osync_error_print(error)); - osync_error_unref(error); - } - - continue; - } - - - if (ldap_subentries == NULL) { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_subentries = NULL. Ignoring.\n", __FILE__, __LINE__); - continue; - } - - - // Add the result from the parsing of the subentry element to - // the GList *potential_subentries - unsigned int max = g_list_length(ldap_subentries); - for (i = 0; i < max; i++) { - ldap_subentry = g_list_nth_data(ldap_subentries, i); - if (!ldap_subentry) { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: ldap_subentry is NULL. ldap_format_parse_xml_subentry() must have failed. Ignoring this xml subentry.\n", __FILE__, __LINE__); - continue; - } - - - if (ldap_subentry->id == NULL) { - osync_trace(TRACE_ERROR, "%s:%i: ERROR: id = NULL. Skipping this subentry.\n", __FILE__, __LINE__); - continue; - } - - - *potential_subentries = g_list_append(*potential_subentries, ldap_subentry); - if (*potential_subentries == NULL) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: g_list_append() has produced a NULL pointer.\n", __FILE__, __LINE__); - goto error; - } - } - - g_list_free(ldap_subentries); - ldap_subentries = NULL; - } - - - continue; // advance to the next xmlnode. - } // if (!strcmp((char *)name, "subentry")) - - - - - // Look for any XML attribute elements - if (xmlnode->xmlChildrenNode) { - - - if (!strcmp((char *)xmlnode->xmlChildre... [truncated message content] |