diff --git a/bindings/bindings.py b/bindings/bindings.py index 0654be35..b46357d7 100644 --- a/bindings/bindings.py +++ b/bindings/bindings.py @@ -374,7 +374,7 @@ class DocString: raise Exception('should not happen: could not found type for default: ' + annotation) arg[2]['default'] = prefix + m.group(1) arg[2]['optional'] = True - m = re.search(r'\(\s*element-type\s+(\w+)(?:\s+(\w+))?', annotation) + m = re.search(r'\(\s*element-type\s+([\w*]+)(?:\s+([\w*]+))?', annotation) if m: if len(m.groups()) > 2: arg[2]['key-type'] = \ diff --git a/bindings/overrides.xml b/bindings/overrides.xml index 451199c6..88cedcaa 100644 --- a/bindings/overrides.xml +++ b/bindings/overrides.xml @@ -198,6 +198,10 @@ + + + + diff --git a/bindings/python/lang.py b/bindings/python/lang.py index 3b8ec92a..4ef79ead 100644 --- a/bindings/python/lang.py +++ b/bindings/python/lang.py @@ -87,7 +87,13 @@ class Binding: else: raise Exception('Unsupported caller owned return type %s' % ((repr(type), name),)) elif is_hashtable(type): - raise Exception('Unsupported caller owned return type %s' % ((repr(type), name),)) + el_type = element_type(type) + k_type = key_type(type) + v_type = value_type(type) + if is_cstring(el_type) or (is_cstring(k_type) and is_cstring(v_type)): + print_(' g_hash_table_destroy(%s);' % name, file=fd) + else: + raise Exception('Unsupported free value of type GHashTable: %s' % type) elif is_object(type): print_(' if (return_value) g_object_unref(%s);' % name, file=fd) else: @@ -528,7 +534,9 @@ if WSF_SUPPORT: print_(' rc = _lasso.%s(self._cptr%s)' % ( function_name, c_args), file=fd) print_(' Error.raise_on_rc(rc)', file=fd) - elif is_int(m.return_arg, self.binding_data) or is_xml_node(m.return_arg) or is_cstring(m.return_arg) or is_boolean(m.return_arg): + elif (is_int(m.return_arg, self.binding_data) or is_xml_node(m.return_arg) or + is_cstring(m.return_arg) or is_boolean(m.return_arg) or + is_hashtable(m.return_arg)): print_(' return _lasso.%s(self._cptr%s)' % ( function_name, c_args), file=fd) elif is_glist(m.return_arg): @@ -539,13 +547,11 @@ if WSF_SUPPORT: print_(' if value is not None:', file=fd) print_(' value = tuple([cptrToPy(x) for x in value])', file=fd) print_(' return value', file=fd) - elif is_cstring(el_type): + elif is_cstring(el_type) or is_xml_node(el_type): print_(' return _lasso.%s(self._cptr%s)' % ( function_name, c_args), file=fd) else: raise Exception('Return Type GList<%s> is not supported' % el_type) - elif is_hashtable(m.return_arg): - raise Exception('Return type GHashTable unsupported') elif is_object(m.return_arg): print_(' return cptrToPy(_lasso.%s(self._cptr%s))' % ( function_name, c_args), file=fd) @@ -929,7 +935,7 @@ register_constants(PyObject *d) arg_def = ' %s %s = %s;' % (arg[0], arg[1], defval) else: arg_def = ' %s %s;' % (arg[0], arg[1]) - elif is_xml_node(arg) or is_list(arg) or is_time_t_pointer(arg): + elif is_hashtable(arg) or is_xml_node(arg) or is_list(arg) or is_time_t_pointer(arg): parse_tuple_format.append('O') parse_tuple_args.append('&cvt_%s' % aname) arg_def = ' %s %s = NULL;' % (arg[0], arg[1]) @@ -970,7 +976,7 @@ register_constants(PyObject *d) qualifier = element_type(arg) if is_cstring(qualifier): print_(' set_list_of_strings(&%s, cvt_%s);' % (arg[1], arg[1]), file=fd) - elif qualifier == 'xmlNode*': + elif is_xml_node(qualifier): print_(' set_list_of_xml_nodes(&%s, cvt_%s);' % (arg[1], arg[1]), file=fd) elif isinstance(qualifier, str) and qualifier.startswith('Lasso'): print_(' set_list_of_pygobject(&%s, cvt_%s);' % (arg[1], arg[1]), file=fd) @@ -980,6 +986,14 @@ register_constants(PyObject *d) print_(' %s = get_xml_node_from_pystring(cvt_%s);' % (arg[1], arg[1]), file=fd) elif is_time_t_pointer(arg): print_(' %s = get_time_t(cvt_%s);' % (arg[1], arg[1]), file=fd) + elif is_hashtable(arg): + el_type = element_type(arg) + k_type = key_type(arg) + v_type = value_type(arg) + if is_cstring(el_type) or (is_cstring(k_type) and is_cstring(v_type)): + + print_(' %s = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);' % arg[1], file=fd) + print_(' set_hashtable_of_strings(%s, cvt_%s);' % (arg[1], arg[1]), file=fd) elif f == 'O': if is_optional(arg): print_(' if (PyObject_TypeCheck((PyObject*)cvt_%s, &PyGObjectPtrType)) {' % arg[1], file=fd) @@ -1021,14 +1035,16 @@ register_constants(PyObject *d) print_(' PyList_SetItem(cvt_%s_out, 0, out_pyvalue);' % arg[1], file=fd) elif arg[0] == 'GList*': qualifier = arg[2].get('element-type') - if qualifier == 'char*': + if is_cstring(qualifier): print_(' free_list(&%s, (GFunc)g_free);' % arg[1], file=fd) - elif qualifier == 'xmlNode*': + elif is_xml_node(qualifier): print_(' free_list(&%s, (GFunc)xmlFreeNode);' % arg[1], file=fd) - elif qualifier == 'LassoNode': + elif is_object(qualifier): print_(' free_list(&%s, (GFunc)g_object_unref);' % arg[1], file=fd) elif is_time_t_pointer(arg): print_(' if (%s) free(%s);' % (arg[1], arg[1]), file=fd) + elif not is_transfer_full(arg) and is_hashtable(arg): + self.free_value(fd, arg) elif not is_transfer_full(arg) and is_xml_node(arg): self.free_value(fd, arg) diff --git a/bindings/python/tests/binding_tests.py b/bindings/python/tests/binding_tests.py index 3e395122..6d8e0dfa 100755 --- a/bindings/python/tests/binding_tests.py +++ b/bindings/python/tests/binding_tests.py @@ -301,6 +301,28 @@ class BindingTestCase(unittest.TestCase): server = lasso.Server.newFromDump(server_dump) assert isinstance(server, lasso.Server) + def test12(self): + node = lasso.Samlp2Extensions() + assert not node.any + content = ''' + %s + ''' + node = lasso.Node.newFromXmlNode(content) + assert 'next_url' in node.any[1] + assert 'huhu' in node.attributes.keys()[0] + assert node.attributes.values()[0] == 'xxx' + node.any = ('coin',) + node.attributes = {'michou': 'zozo'} + assert 'coin' in node.dump() + assert 'michou="zozo"' in node.dump() + node = lasso.Node.newFromDump(node.dump()) + assert node.any == ('coin',) + # on reparse non namespaces attributes are ignore, they should not exist + assert node.attributes == {} + + bindingSuite = unittest.makeSuite(BindingTestCase, 'test') allTests = unittest.TestSuite((bindingSuite, )) diff --git a/bindings/python/wrapper_top.c b/bindings/python/wrapper_top.c index 09e999f3..ac930f9e 100644 --- a/bindings/python/wrapper_top.c +++ b/bindings/python/wrapper_top.c @@ -148,18 +148,20 @@ get_dict_from_hashtable_of_strings(GHashTable *value) dict = PyDict_New(); - begin = keys = g_hash_table_get_keys(value); - for (; keys; keys = g_list_next(keys)) { - item_value = g_hash_table_lookup(value, keys->data); - if (item_value) { - item = PyString_FromString(item_value); - PyDict_SetItemString(dict, (char*)keys->data, item); - Py_DECREF(item); - } else { - PyErr_Warn(PyExc_RuntimeWarning, "hashtable contains a null value"); + if (value) { + begin = keys = g_hash_table_get_keys(value); + for (; keys; keys = g_list_next(keys)) { + item_value = g_hash_table_lookup(value, keys->data); + if (item_value) { + item = PyString_FromString(item_value); + PyDict_SetItemString(dict, (char*)keys->data, item); + Py_DECREF(item); + } else { + PyErr_Warn(PyExc_RuntimeWarning, "hashtable contains a null value"); + } } + g_list_free(begin); } - g_list_free(begin); proxy = PyDictProxy_New(dict); Py_DECREF(dict); @@ -303,7 +305,7 @@ set_hashtable_of_strings(GHashTable *a_hash, PyObject *dict) while (PyDict_Next(dict, &i, &key, &value)) { char *ckey = PyString_AsString(key); char *cvalue = PyString_AsString(value); - g_hash_table_insert (a_hash, ckey, cvalue); + g_hash_table_insert (a_hash, g_strdup(ckey), g_strdup(cvalue)); } failure: return; diff --git a/lasso/utils.h b/lasso/utils.h index 6128c9a3..cb1491de 100644 --- a/lasso/utils.h +++ b/lasso/utils.h @@ -325,6 +325,17 @@ } \ } +#define lasso_assign_list_of_xml_node(dest, src) \ + { \ + GList *__tmp = src; \ + GList *__iter_dest; \ + lasso_release_list_of_xml_node(dest); \ + dest = g_list_copy(__tmp); \ + for (__iter_dest = dest ; __iter_dest != NULL ; __iter_dest = g_list_next(__iter_dest)) { \ + __iter_dest->data = xmlCopyNode(__iter_dest->data, 1); \ + } \ + } + #define lasso_assign_new_sec_key(dest, src) \ { \ xmlSecKey *__tmp = (src); \ @@ -344,6 +355,21 @@ dest = __tmp; \ } +G_GNUC_UNUSED static void +_lasso_copy_helper_assign_table_of_attributes(gpointer key, gpointer val, gpointer dest){ + g_hash_table_insert((GHashTable*) dest, g_strdup(key), g_strdup(val)); +} + +#define lasso_assign_table_of_attributes(dest, src) \ + {\ + if (!dest) {\ + (dest) = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);\ + }\ + g_hash_table_remove_all(dest);\ + g_hash_table_foreach(src, _lasso_copy_helper_assign_table_of_attributes, dest);\ + } + + /* List appending */ /* lasso_list_add_xxx macros, simplify code around list manipulation (g_list_append needs to be diff --git a/lasso/xml/saml-2.0/samlp2_extensions.c b/lasso/xml/saml-2.0/samlp2_extensions.c index 6dc342b3..65875d78 100644 --- a/lasso/xml/saml-2.0/samlp2_extensions.c +++ b/lasso/xml/saml-2.0/samlp2_extensions.c @@ -45,33 +45,35 @@ * */ +typedef struct _LassoSamlp2ExtensionsPrivate LassoSamlp2ExtensionsPrivate; + +struct _LassoSamlp2ExtensionsPrivate { + GList *any; + GHashTable *attributes; +}; + /*****************************************************************************/ /* private methods */ /*****************************************************************************/ static struct XmlSnippet schema_snippets[] = { + {"", SNIPPET_LIST_XMLNODES | SNIPPET_ANY | SNIPPET_PRIVATE, + G_STRUCT_OFFSET(LassoSamlp2ExtensionsPrivate, any), NULL, NULL, NULL}, + {"", SNIPPET_ATTRIBUTE | SNIPPET_ANY | SNIPPET_PRIVATE, + G_STRUCT_OFFSET(LassoSamlp2ExtensionsPrivate, attributes), NULL, NULL, NULL}, {NULL, 0, 0, NULL, NULL, NULL} }; static LassoNodeClass *parent_class = NULL; +#define GET_PRIVATE(x) G_TYPE_INSTANCE_GET_PRIVATE(x, \ + LASSO_TYPE_SAMLP2_EXTENSIONS, LassoSamlp2ExtensionsPrivate) + /*****************************************************************************/ /* instance and class init functions */ /*****************************************************************************/ -static xmlNode* -get_xmlNode(LassoNode *node, gboolean lasso_dump) -{ - LassoNodeClass *parent_class = NULL; - xmlNode *cur; - - parent_class = g_type_class_peek_parent(LASSO_NODE_GET_CLASS(node)); - cur = parent_class->get_xmlNode(node, lasso_dump); - - return lasso_node_get_xmlnode_for_any_type(node, cur); -} - static void class_init(LassoSamlp2ExtensionsClass *klass) { @@ -80,10 +82,10 @@ class_init(LassoSamlp2ExtensionsClass *klass) parent_class = g_type_class_peek_parent(klass); nclass->node_data = g_new0(LassoNodeClassData, 1); nclass->node_data->keep_xmlnode = TRUE; - nclass->get_xmlNode = get_xmlNode; lasso_node_class_set_nodename(nclass, "Extensions"); lasso_node_class_set_ns(nclass, LASSO_SAML2_PROTOCOL_HREF, LASSO_SAML2_PROTOCOL_PREFIX); lasso_node_class_add_snippets(nclass, schema_snippets); + g_type_class_add_private(G_OBJECT_CLASS(klass), sizeof(LassoSamlp2ExtensionsPrivate)); } GType @@ -123,3 +125,70 @@ lasso_samlp2_extensions_new() { return g_object_new(LASSO_TYPE_SAMLP2_EXTENSIONS, NULL); } + +/** + * lasso_samlp2_extensions_get_any: + * + * Return the list of contained XML nodes. + * + * Return value:(element-type xmlNode)(transfer none): a #GList of xmlNode. + */ +GList* +lasso_samlp2_extensions_get_any(LassoSamlp2Extensions *extensions) +{ + LassoSamlp2ExtensionsPrivate *pv = NULL; + + pv = GET_PRIVATE(extensions); + + return pv->any; +} + +/** + * lasso_samlp2_extensions_set_any: + * @any:(allow-none)(element-type xmlNode)(transfer none): a list of xmlNode. + * + * Set the list of contained XML nodes. + * + */ +void +lasso_samlp2_extensions_set_any(LassoSamlp2Extensions *extensions, GList *any) +{ + LassoSamlp2ExtensionsPrivate *pv = NULL; + + pv = GET_PRIVATE(extensions); + + lasso_assign_list_of_xml_node(pv->any, any); +} + +/** + * lasso_samlp2_extensions_get_attributes: + * + * Return the list of contained XML nodes. + * + * Return value:(element-type xmlNode)(transfer none): a #GList of xmlNode. + */ +GHashTable* +lasso_samlp2_extensions_get_attributes(LassoSamlp2Extensions *extensions) +{ + LassoSamlp2ExtensionsPrivate *pv = NULL; + + pv = GET_PRIVATE(extensions); + + return pv->attributes; +} + +/** + * lasso_samlp2_extensions_set_attributes: + * @attributes:(element-type char* char*): table of attributes. + * + * Set the table of XML attributes. + */ +void +lasso_samlp2_extensions_set_attributes(LassoSamlp2Extensions *extensions, GHashTable *attributes) +{ + LassoSamlp2ExtensionsPrivate *pv = NULL; + + pv = GET_PRIVATE(extensions); + + lasso_assign_table_of_attributes(pv->attributes, attributes); +} diff --git a/lasso/xml/saml-2.0/samlp2_extensions.h b/lasso/xml/saml-2.0/samlp2_extensions.h index 37c33fcc..91e795b7 100644 --- a/lasso/xml/saml-2.0/samlp2_extensions.h +++ b/lasso/xml/saml-2.0/samlp2_extensions.h @@ -62,7 +62,10 @@ struct _LassoSamlp2ExtensionsClass { LASSO_EXPORT GType lasso_samlp2_extensions_get_type(void); LASSO_EXPORT LassoNode* lasso_samlp2_extensions_new(void); - +LASSO_EXPORT GList* lasso_samlp2_extensions_get_any(LassoSamlp2Extensions *extensions); +LASSO_EXPORT void lasso_samlp2_extensions_set_any(LassoSamlp2Extensions *extensions, GList *any); +LASSO_EXPORT GHashTable* lasso_samlp2_extensions_get_attributes(LassoSamlp2Extensions *extensions); +LASSO_EXPORT void lasso_samlp2_extensions_set_attributes(LassoSamlp2Extensions *extensions, GHashTable *attributes); #ifdef __cplusplus