1 /* $Id$
2  *
3  * Lasso - A free implementation of the Liberty Alliance specifications.
4  *
5  * Copyright (C) 2004-2007 Entr'ouvert
6  * http://lasso.entrouvert.org
7  *
8  * Authors: See AUTHORS file in top-level directory.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 /**
25  * SECTION:identity
26  * @short_description: Principal identity
27  *
28  * A #LassoIdentity object records the identifers that a principal use two federate pairs of
29  * providers.
30  *
31  **/
32 
33 #include "../xml/private.h"
34 #include <config.h>
35 #include "../utils.h"
36 #include "identity.h"
37 
38 #ifdef LASSO_WSF_ENABLED
39 #include "../id-wsf/id_ff_extensions.h"
40 #endif
41 
42 #include "identityprivate.h"
43 #include "../lasso_config.h"
44 
45 /*****************************************************************************/
46 /* public methods                                                            */
47 /*****************************************************************************/
48 
49 /**
50  * lasso_identity_add_federation:
51  * @identity: a #LassoIdentity
52  * @federation: the #LassoFederation
53  *
54  * Adds @federation as a known federation for @identity.  @federation is
55  * then owned by the identity; caller must not free it.
56  *
57  * Return value: 0 on success; or a negative value otherwise.
58  **/
59 gint
lasso_identity_add_federation(LassoIdentity * identity,LassoFederation * federation)60 lasso_identity_add_federation(LassoIdentity *identity, LassoFederation *federation)
61 {
62 	g_return_val_if_fail(LASSO_IS_IDENTITY(identity), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
63 	g_return_val_if_fail(LASSO_IS_FEDERATION(federation),
64 			LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
65 
66 	/* add the federation, replace if one already exists */
67 	g_hash_table_insert(identity->federations,
68 			g_strdup(federation->remote_providerID), federation);
69 	identity->is_dirty = TRUE;
70 
71 	return 0;
72 }
73 
74 /**
75  * lasso_identity_get_federation:
76  * @identity: a #LassoIdentity
77  * @providerID: the provider ID
78  *
79  * Looks up and returns the #LassoFederation for this provider ID.
80  *
81  * Return value:(transfer none): the #LassoFederation; or NULL if it didn't exist.  The
82  *      #LassoFederation is internally allocated.  It must not be freed,
83  *      modified or stored.
84  **/
85 LassoFederation*
lasso_identity_get_federation(LassoIdentity * identity,const char * providerID)86 lasso_identity_get_federation(LassoIdentity *identity, const char *providerID)
87 {
88 	if (! LASSO_IS_IDENTITY(identity) ||
89 		providerID == NULL ||
90 		identity->federations == NULL) {
91 		return NULL;
92 	}
93 
94 	return g_hash_table_lookup(identity->federations, providerID);
95 }
96 
97 /**
98  * lasso_identity_remove_federation:
99  * @identity: a #LassoIdentity
100  * @providerID: the provider ID
101  *
102  * Remove federation between identity and provider with @providerID
103  *
104  * Return value: 0 on success; or a negative value otherwise.
105  **/
106 gint
lasso_identity_remove_federation(LassoIdentity * identity,const char * providerID)107 lasso_identity_remove_federation(LassoIdentity *identity, const char *providerID)
108 {
109 	g_return_val_if_fail(LASSO_IS_IDENTITY(identity), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
110 	g_return_val_if_fail(providerID != NULL, LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
111 
112 	if (g_hash_table_remove(identity->federations, providerID) == FALSE) {
113 		return LASSO_PROFILE_ERROR_FEDERATION_NOT_FOUND;
114 	}
115 	identity->is_dirty = TRUE;
116 
117 	return 0;
118 }
119 
120 /**
121  * lasso_identity_destroy:
122  * @identity: a #LassoIdentity
123  *
124  * Destroys an identity.
125  **/
126 void
lasso_identity_destroy(LassoIdentity * identity)127 lasso_identity_destroy(LassoIdentity *identity)
128 {
129 	if (identity == NULL)
130 		return;
131 	lasso_node_destroy(LASSO_NODE(identity));
132 }
133 
134 
135 /*****************************************************************************/
136 /* private methods                                                           */
137 /*****************************************************************************/
138 
139 static LassoNodeClass *parent_class = NULL;
140 
141 static void
add_childnode_from_hashtable(G_GNUC_UNUSED gchar * key,LassoNode * value,xmlNode * xmlnode)142 add_childnode_from_hashtable(G_GNUC_UNUSED gchar *key, LassoNode *value, xmlNode *xmlnode)
143 {
144 	xmlAddChild(xmlnode, lasso_node_get_xmlNode(LASSO_NODE(value), TRUE));
145 }
146 
147 #ifdef LASSO_WSF_ENABLED
148 static void
add_text_childnode_from_list(gchar * value,xmlNode * xmlnode)149 add_text_childnode_from_list(gchar *value, xmlNode *xmlnode)
150 {
151 	xmlNewTextChild(xmlnode, NULL, (xmlChar*)"SvcMDID", (xmlChar*)value);
152 }
153 #endif
154 
155 static xmlNode*
get_xmlNode(LassoNode * node,G_GNUC_UNUSED gboolean lasso_dump)156 get_xmlNode(LassoNode *node, G_GNUC_UNUSED gboolean lasso_dump)
157 {
158 	xmlNode *xmlnode;
159 	LassoIdentity *identity = LASSO_IDENTITY(node);
160 #ifdef LASSO_WSF_ENABLED
161 	xmlNode *t;
162 #endif
163 
164 	xmlnode = xmlNewNode(NULL, (xmlChar*)"Identity");
165 	xmlSetNs(xmlnode, xmlNewNs(xmlnode, (xmlChar*)LASSO_LASSO_HREF, NULL));
166 	xmlSetProp(xmlnode, (xmlChar*)"Version", (xmlChar*)"2");
167 
168 	/* Federations */
169 	if (g_hash_table_size(identity->federations))
170 		g_hash_table_foreach(identity->federations,
171 				(GHFunc)add_childnode_from_hashtable, xmlnode);
172 #ifdef LASSO_WSF_ENABLED
173 	/* Resource Offerings */
174 	g_hash_table_foreach(identity->private_data->resource_offerings_map,
175 			(GHFunc)add_childnode_from_hashtable, xmlnode);
176 
177 	/* Service Metadatas IDs (svcMDID) */
178 	if (identity->private_data->svcMDID != NULL) {
179 		t = xmlNewTextChild(xmlnode, NULL, (xmlChar*)"SvcMDIDs", NULL);
180 		g_list_foreach(identity->private_data->svcMDID,
181 				(GFunc)add_text_childnode_from_list, t);
182 	}
183 #endif
184 
185 	return xmlnode;
186 }
187 
188 static int
init_from_xml(LassoNode * node,xmlNode * xmlnode)189 init_from_xml(LassoNode *node, xmlNode *xmlnode)
190 {
191 	LassoIdentity *identity = LASSO_IDENTITY(node);
192 	xmlNode *t;
193 #ifdef LASSO_WSF_ENABLED
194 	xmlNode *t2;
195 	xmlChar *xml_content;
196 	gchar *content;
197 #endif
198 
199 	t = xmlnode->children;
200 	while (t) {
201 		if (t->type != XML_ELEMENT_NODE) {
202 			t = t->next;
203 			continue;
204 		}
205 
206 		/* Federations */
207 		if (strcmp((char*)t->name, "Federation") == 0) {
208 			LassoFederation *federation;
209 			federation = LASSO_FEDERATION(lasso_node_new_from_xmlNode(t));
210 			g_hash_table_insert(
211 					identity->federations,
212 					g_strdup(federation->remote_providerID), federation);
213 		}
214 
215 #ifdef LASSO_WSF_ENABLED
216 		/* Resource Offerings */
217 		if (strcmp((char*)t->name, "ResourceOffering") == 0) {
218 			LassoDiscoResourceOffering *offering;
219 			offering = LASSO_DISCO_RESOURCE_OFFERING(lasso_node_new_from_xmlNode(t));
220 			g_hash_table_insert(identity->private_data->resource_offerings_map,
221 				g_strdup(offering->entryID),
222 				g_object_ref(offering));
223 		}
224 
225 		/* Service Metadatas IDs (SvcMDID) */
226 		if (strcmp((char*)t->name, "SvcMDIDs") == 0) {
227 			t2 = t->children;
228 			while (t2) {
229 				if (t2->type != XML_ELEMENT_NODE) {
230 					t2 = t2->next;
231 					continue;
232 				}
233 				xml_content = xmlNodeGetContent(t2);
234 				content = g_strdup((gchar *)xml_content);
235 				identity->private_data->svcMDID = g_list_append(
236 					identity->private_data->svcMDID, content);
237 				xmlFree(xml_content);
238 				t2 = t2->next;
239 			}
240 		}
241 #endif
242 
243 		t = t->next;
244 	}
245 
246 	return 0;
247 }
248 
249 
250 /*****************************************************************************/
251 /* overridden parent class methods                                           */
252 /*****************************************************************************/
253 
254 static void
dispose(GObject * object)255 dispose(GObject *object)
256 {
257 	LassoIdentity *identity = LASSO_IDENTITY(object);
258 
259 
260 	if (identity->private_data->dispose_has_run == FALSE) {
261 		identity->private_data->dispose_has_run = TRUE;
262 #ifdef LASSO_WSF_ENABLED
263 		lasso_release_list_of_strings(identity->private_data->svcMDID);
264 		lasso_release_ghashtable(identity->private_data->resource_offerings_map);
265 #endif
266 
267 		lasso_release_ghashtable(identity->federations);
268 
269 		G_OBJECT_CLASS(parent_class)->dispose(object);
270 	}
271 }
272 
273 static void
finalize(GObject * object)274 finalize(GObject *object)
275 {
276 	LassoIdentity *identity = LASSO_IDENTITY(object);
277 	lasso_release(identity->private_data);
278 	identity->private_data = NULL;
279 	G_OBJECT_CLASS(parent_class)->finalize(object);
280 }
281 
282 /*****************************************************************************/
283 /* instance and class init functions                                         */
284 /*****************************************************************************/
285 
286 static void
instance_init(LassoIdentity * identity)287 instance_init(LassoIdentity *identity)
288 {
289 	identity->private_data = g_new0(LassoIdentityPrivate, 1);
290 	identity->private_data->dispose_has_run = FALSE;
291 #ifdef LASSO_WSF_ENABLED
292 	identity->private_data->svcMDID = NULL;
293 	identity->private_data->last_entry_id = 0;
294 	identity->private_data->resource_offerings_map = g_hash_table_new_full(g_str_hash,
295 			g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)g_object_unref);
296 #endif
297 	identity->federations = g_hash_table_new_full(g_str_hash, g_str_equal,
298 			(GDestroyNotify)g_free,
299 			(GDestroyNotify)lasso_federation_destroy);
300 	identity->is_dirty = FALSE;
301 }
302 
303 static void
class_init(LassoIdentityClass * klass,void * unused G_GNUC_UNUSED)304 class_init(LassoIdentityClass *klass, void *unused G_GNUC_UNUSED)
305 {
306 	parent_class = g_type_class_peek_parent(klass);
307 	LassoNodeClass *nclass = LASSO_NODE_CLASS(klass);
308 
309 	nclass->get_xmlNode = get_xmlNode;
310 	nclass->init_from_xml = init_from_xml;
311 	nclass->node_data = g_new0(LassoNodeClassData, 1);
312 	lasso_node_class_set_nodename(nclass, "Identity");
313 	lasso_node_class_set_ns(nclass, LASSO_LASSO_HREF, LASSO_LASSO_PREFIX);
314 
315 	G_OBJECT_CLASS(klass)->dispose = dispose;
316 	G_OBJECT_CLASS(klass)->finalize = finalize;
317 }
318 
319 GType
lasso_identity_get_type()320 lasso_identity_get_type()
321 {
322 	static GType this_type = 0;
323 
324 	if (!this_type) {
325 		static const GTypeInfo this_info = {
326 			sizeof (LassoIdentityClass),
327 			NULL,
328 			NULL,
329 			(GClassInitFunc) class_init,
330 			NULL,
331 			NULL,
332 			sizeof(LassoIdentity),
333 			0,
334 			(GInstanceInitFunc) instance_init,
335 			NULL
336 		};
337 
338 		this_type = g_type_register_static(LASSO_TYPE_NODE,
339 				"LassoIdentity", &this_info, 0);
340 	}
341 	return this_type;
342 }
343 
344 /**
345  * lasso_identity_new:
346  *
347  * Creates a new #LassoIdentity.
348  *
349  * Return value: a newly created #LassoIdentity
350  **/
351 LassoIdentity*
lasso_identity_new()352 lasso_identity_new()
353 {
354 	return g_object_new(LASSO_TYPE_IDENTITY, NULL);
355 }
356 
357 /**
358  * lasso_identity_new_from_dump:
359  * @dump: XML server dump
360  *
361  * Restores the @dump to a new #LassoIdentity.
362  *
363  * Return value: a newly created #LassoIdentity; or NULL if an error occured
364  **/
365 LassoIdentity*
lasso_identity_new_from_dump(const gchar * dump)366 lasso_identity_new_from_dump(const gchar *dump)
367 {
368 	LassoIdentity *identity;
369 
370 	identity = (LassoIdentity*)lasso_node_new_from_dump(dump);
371 	if (! LASSO_IS_IDENTITY(identity)) {
372 		lasso_release_gobject(identity);
373 	}
374 
375 	return identity;
376 }
377 
378 /**
379  * lasso_identity_dump:
380  * @identity: a #LassoIdentity
381  *
382  * Dumps @identity content to an XML string.
383  *
384  * Return value:(transfer full): the dump string.  It must be freed by the caller.
385  **/
386 gchar*
lasso_identity_dump(LassoIdentity * identity)387 lasso_identity_dump(LassoIdentity *identity)
388 {
389 	return lasso_node_dump(LASSO_NODE(identity));
390 }
391