1 #include "config.h"
2 #include <string.h>
3 #include <orbit/orbit.h>
4 #include "orb-core-export.h"
5 #include "../util/orbit-purify.h"
6 
7 static gboolean
free_entry(gpointer key,gpointer value,gpointer user_data)8 free_entry (gpointer key, gpointer value, gpointer user_data)
9 {
10 	g_free (key);
11 	g_free (value);
12 
13 	return TRUE;
14 }
15 
16 static void ORBit_Context_free_fn(ORBit_RootObject ctx);
17 
18 static void
free_child(gpointer value,gpointer user_data)19 free_child (gpointer value, gpointer user_data)
20 {
21 	CORBA_Context ctx = value;
22 
23 	ctx->parent.refs = 0;
24 	ctx->parent_ctx = CORBA_OBJECT_NIL;
25 	ORBit_Context_free_fn (ORBIT_ROOT_OBJECT (ctx));
26 }
27 
28 static void
ORBit_Context_free_fn(ORBit_RootObject obj_in)29 ORBit_Context_free_fn (ORBit_RootObject obj_in)
30 {
31 	CORBA_Context ctx = (CORBA_Context) obj_in;
32 
33 	if (ctx->children) {
34 		g_slist_foreach (ctx->children, free_child, NULL);
35 		g_slist_free (ctx->children);
36 	}
37 
38 	if (ctx->mappings) {
39 		g_hash_table_foreach_remove (ctx->mappings, free_entry, NULL);
40 		g_hash_table_destroy (ctx->mappings);
41 	}
42 
43 	if (ctx->parent_ctx != CORBA_OBJECT_NIL)
44 		ctx->parent_ctx->children = g_slist_remove (
45 			ctx->parent_ctx->children, ctx);
46 
47 	g_free (ctx->the_name);
48 
49 	p_free (ctx, struct CORBA_Context_type);
50 }
51 
52 static const ORBit_RootObject_Interface CORBA_Context_epv =
53 {
54 	ORBIT_ROT_CONTEXT,
55 	ORBit_Context_free_fn
56 };
57 
58 static CORBA_Context
CORBA_Context_new(CORBA_Context parent,const char * name,CORBA_Environment * ev)59 CORBA_Context_new (CORBA_Context      parent,
60 		   const char        *name,
61 		   CORBA_Environment *ev)
62 {
63 	CORBA_Context retval;
64 
65 	retval = g_new0 (struct CORBA_Context_type, 1);
66 
67 	ORBit_RootObject_init (&retval->parent, &CORBA_Context_epv);
68 
69 	if (name)
70 		retval->the_name = g_strdup (name);
71 
72 	retval->parent_ctx = parent;
73 	if (parent)
74 		parent->children = g_slist_prepend (parent->children, retval);
75 
76 	return ORBit_RootObject_duplicate (retval);
77 }
78 
79 void
CORBA_ORB_get_default_context(CORBA_ORB orb,CORBA_Context * ctx,CORBA_Environment * ev)80 CORBA_ORB_get_default_context (CORBA_ORB          orb,
81 			       CORBA_Context     *ctx,
82 			       CORBA_Environment *ev)
83 {
84 	g_return_if_fail (ev != NULL);
85 
86 	if (!orb->default_ctx)
87 		orb->default_ctx = CORBA_Context_new (
88 			CORBA_OBJECT_NIL, NULL, ev);
89 
90 	*ctx = ORBit_RootObject_duplicate (orb->default_ctx);
91 }
92 
93 void
CORBA_Context_set_one_value(CORBA_Context ctx,const CORBA_char * prop_name,const CORBA_char * value,CORBA_Environment * ev)94 CORBA_Context_set_one_value (CORBA_Context      ctx,
95 			     const CORBA_char  *prop_name,
96 			     const CORBA_char  *value,
97 			     CORBA_Environment *ev)
98 {
99 	gpointer old_nom, old_value;
100 
101 	g_return_if_fail (ev != NULL);
102 
103 	if (!ctx->mappings)
104 		ctx->mappings = g_hash_table_new (g_str_hash, g_str_equal);
105 
106 	if (g_hash_table_lookup_extended (
107 		ctx->mappings, prop_name, &old_nom, &old_value)) {
108 		g_hash_table_remove (ctx->mappings, prop_name);
109 		g_free (old_nom);
110 		g_free (old_value);
111 	}
112 
113 	g_hash_table_insert (ctx->mappings,
114 			     g_strdup (prop_name),
115 			     g_strdup (value));
116 }
117 
118 void
CORBA_Context_set_values(CORBA_Context ctx,const CORBA_NVList values,CORBA_Environment * ev)119 CORBA_Context_set_values(CORBA_Context ctx,
120 			 const CORBA_NVList values,
121 			 CORBA_Environment * ev)
122 {
123   int i;
124 
125   for(i = 0; i < values->list->len; i++)
126     {
127       CORBA_NamedValue *nvp;
128 
129       nvp = ((CORBA_NamedValue *)values->list->data) + i;
130 
131       g_assert(nvp->argument._type == TC_CORBA_string);
132 
133       CORBA_Context_set_one_value(ctx, nvp->name, nvp->argument._value, ev);
134     }
135 }
136 
137 typedef struct {
138 	CORBA_Context      ctx;
139 	const CORBA_char  *prop_name;
140 	CORBA_NVList       values;
141 	CORBA_Environment *ev;
142 	int                len;
143 } CTXSearchInfo;
144 
145 static gboolean
list_has_key(CORBA_NVList list,const char * key)146 list_has_key (CORBA_NVList list, const char *key)
147 {
148 	int i;
149 
150 	for (i = 0; i < list->list->len; i++) {
151 		CORBA_NamedValue *nvp;
152 
153 		nvp = ((CORBA_NamedValue *)list->list->data) + i;
154 
155 		if (!strcmp(nvp->name, key))
156 			return TRUE;
157 	}
158 
159 	return FALSE;
160 }
161 
162 static void
search_props(gpointer key,gpointer value,CTXSearchInfo * csi)163 search_props (gpointer       key,
164 	      gpointer       value,
165 	      CTXSearchInfo *csi)
166 {
167 	if (strncmp (key, csi->prop_name, csi->len))
168 		return;
169 
170 	if (list_has_key (csi->values, key))
171 		return;
172 
173 	CORBA_NVList_add_item (
174 		csi->values, key, TC_CORBA_string,
175 		(CORBA_OpaqueValue) &value,
176 		strlen (value) + 1, CORBA_IN_COPY_VALUE, NULL);
177 }
178 
179 static void
ctx_get_values(CORBA_Context ctx,CORBA_Flags op_flags,const CORBA_char * prop_name,CORBA_NVList * values,gint is_wc,CORBA_Environment * ev)180 ctx_get_values (CORBA_Context      ctx,
181 		CORBA_Flags        op_flags,
182 		const CORBA_char  *prop_name,
183 		CORBA_NVList      *values,
184 		gint               is_wc,
185 		CORBA_Environment *ev)
186 {
187 	gboolean go_up = FALSE;
188 
189 	if (is_wc >= 0) {
190 		CTXSearchInfo csi;
191 
192 		csi.ctx = ctx;
193 		csi.prop_name = prop_name;
194 		csi.values = *values;
195 		csi.ev = ev;
196 		csi.len = is_wc;
197 
198 		if (ctx->mappings)
199 			g_hash_table_foreach (
200 				ctx->mappings, (GHFunc) search_props, &csi);
201 
202 		go_up = TRUE;
203 	} else {
204 		char *val = NULL;
205 
206 		if (ctx->mappings)
207 			val = g_hash_table_lookup (ctx->mappings, prop_name);
208 
209 		if (val)
210 			CORBA_NVList_add_item (
211 				*values, prop_name, TC_CORBA_string,
212 				(CORBA_OpaqueValue) &val,
213 				strlen (val) + 1, CORBA_IN_COPY_VALUE, ev);
214 		else
215 			go_up = TRUE;
216 	}
217 
218 	if (go_up && ctx->parent_ctx &&
219 	    !(op_flags & CORBA_CTX_RESTRICT_SCOPE))
220 		ctx_get_values (ctx->parent_ctx, op_flags,
221 				prop_name, values, is_wc, ev);
222 }
223 
224 void
CORBA_Context_get_values(CORBA_Context ctx,const CORBA_char * start_scope,const CORBA_Flags op_flags,const CORBA_char * prop_name,CORBA_NVList * values,CORBA_Environment * ev)225 CORBA_Context_get_values (CORBA_Context      ctx,
226 			  const CORBA_char  *start_scope,
227 			  const CORBA_Flags  op_flags,
228 			  const CORBA_char  *prop_name,
229 			  CORBA_NVList      *values,
230 			  CORBA_Environment *ev)
231 {
232 	if (start_scope && *start_scope) {
233 		while (ctx && (!ctx->the_name ||
234 			       strcmp (ctx->the_name, start_scope)))
235 			ctx = ctx->parent_ctx;
236 
237 		if (!ctx) {
238 			CORBA_exception_set_system (
239 				ev, ex_CORBA_INV_IDENT, CORBA_COMPLETED_NO);
240 			return;
241 		}
242 	}
243 
244 	CORBA_ORB_create_list (CORBA_OBJECT_NIL, 0, values, ev);
245 
246 	ctx_get_values (ctx, op_flags, prop_name, values,
247 			(prop_name [strlen (prop_name) - 1] == '*'), ev);
248 
249 	if ((*values)->list->len == 0) {
250 		CORBA_NVList_free (*values, ev);
251 		*values = NULL;
252 		CORBA_exception_set_system (
253 			ev, ex_CORBA_UNKNOWN, CORBA_COMPLETED_NO);
254 	}
255 }
256 
257 static void
delete_props(gpointer key,gpointer value,CTXSearchInfo * csi)258 delete_props (gpointer key, gpointer value, CTXSearchInfo *csi)
259 {
260 	if (strncmp (key, csi->prop_name, csi->len))
261 		return;
262 
263 	g_hash_table_remove (csi->ctx->mappings, key);
264 	g_free (key);
265 	g_free (value);
266 }
267 
268 void
CORBA_Context_delete_values(CORBA_Context ctx,const CORBA_char * prop_name,CORBA_Environment * ev)269 CORBA_Context_delete_values (CORBA_Context      ctx,
270 			     const CORBA_char  *prop_name,
271 			     CORBA_Environment *ev)
272 {
273 	char *ctmp;
274 	int   wc_pos;
275 
276 	if (!ctx->mappings)
277 		return;
278 
279 	ctmp = strchr (prop_name, '*');
280 	if (ctmp)
281 		wc_pos = ctmp - prop_name;
282 	else
283 		wc_pos = -1;
284 
285 	if (wc_pos >= 0) {
286 		CTXSearchInfo csi;
287 
288 		memset (&csi, 0, sizeof (csi));
289 		csi.ctx = ctx;
290 		csi.prop_name = prop_name;
291 		csi.ev = ev;
292 		csi.len = wc_pos;
293 
294 		g_hash_table_foreach (ctx->mappings, (GHFunc) delete_props, &csi);
295 	} else {
296 		gpointer old_nom, old_value;
297 
298 		if (g_hash_table_lookup_extended (
299 			ctx->mappings, prop_name, &old_nom, &old_value)) {
300 			g_free (old_nom);
301 			g_free (old_value);
302 		}
303 	}
304 }
305 
306 void
CORBA_Context_create_child(CORBA_Context ctx,const CORBA_char * ctx_name,CORBA_Context * child_ctx,CORBA_Environment * ev)307 CORBA_Context_create_child (CORBA_Context      ctx,
308 			    const CORBA_char  *ctx_name,
309 			    CORBA_Context     *child_ctx,
310 			    CORBA_Environment *ev)
311 {
312 	*child_ctx = CORBA_Context_new (ctx, ctx_name, ev);
313 }
314 
315 void
CORBA_Context_delete(CORBA_Context ctx,const CORBA_Flags del_flags,CORBA_Environment * ev)316 CORBA_Context_delete (CORBA_Context      ctx,
317 		      const CORBA_Flags  del_flags,
318 		      CORBA_Environment *ev)
319 {
320 	if ((del_flags & CORBA_CTX_DELETE_DESCENDENTS) ||
321 	    !ctx->children)
322 		free_child (ctx, NULL);
323 }
324 
325 void
ORBit_Context_marshal(CORBA_Context ctx,const ORBit_ContextMarshalItem * mlist,CORBA_unsigned_long nitems,GIOPSendBuffer * buf)326 ORBit_Context_marshal (CORBA_Context                   ctx,
327 		       const ORBit_ContextMarshalItem *mlist,
328 		       CORBA_unsigned_long             nitems,
329 		       GIOPSendBuffer                 *buf)
330 {
331 	CORBA_unsigned_long  real_nitems, ltmp;
332 	guchar              *marker;
333 	int                  i;
334 
335 	marker = giop_send_buffer_append_aligned (buf, &nitems, 4);
336 
337 	if (!ctx->mappings) {
338 		real_nitems = 0;
339 		memcpy (marker, &real_nitems, 4);
340 
341 		return;
342 	}
343 
344 	for (real_nitems = i = 0; i < nitems; i++) {
345 		char *value;
346 
347 		value = g_hash_table_lookup (ctx->mappings, mlist[i].str);
348 		if (!value)
349 			continue;
350 
351 		/* Key */
352 		giop_send_buffer_append_aligned (buf, &mlist[i].len, sizeof(mlist[i].len));
353 		giop_send_buffer_append (buf, mlist[i].str, mlist[i].len);
354 		real_nitems++;
355 
356 		/* Value */
357 		ltmp = strlen (value) + 1;
358 		giop_send_buffer_append_aligned (buf, &ltmp, 4);
359 		giop_send_buffer_append (buf, value, ltmp);
360 		real_nitems++;
361 	}
362 
363 	memcpy (marker, &real_nitems, 4);
364 }
365 
366 #define ALIGNFOR(x) recv_buffer->cur = ALIGN_ADDRESS(recv_buffer->cur, sizeof(x))
367 
368 gboolean
ORBit_Context_demarshal(CORBA_Context parent,CORBA_Context initme,GIOPRecvBuffer * buf)369 ORBit_Context_demarshal (CORBA_Context   parent,
370 			 CORBA_Context   initme,
371 			 GIOPRecvBuffer *buf)
372 {
373 	CORBA_unsigned_long nstrings, keylen, vallen, i;
374 	char               *key, *value;
375 
376 	initme->parent.refs = ORBIT_REFCOUNT_STATIC;
377 	initme->parent_ctx = parent;
378 	initme->mappings = NULL;
379 
380 	buf->cur = ALIGN_ADDRESS (buf->cur, 4);
381 	if ((buf->cur + 4) > buf->end)
382 		goto errout;
383 	nstrings = *(CORBA_unsigned_long *) buf->cur;
384 	if (giop_msg_conversion_needed (buf))
385 		nstrings = GUINT32_SWAP_LE_BE (nstrings);
386 	buf->cur += 4;
387 	if ((buf->cur + nstrings * 8) > buf->end)
388 		goto errout;
389 
390 	if (nstrings)
391 		initme->mappings = g_hash_table_new (g_str_hash, g_str_equal);
392 	else
393 		goto errout;
394 
395 	for (i = 0; i < nstrings; ) {
396 		buf->cur = ALIGN_ADDRESS (buf->cur, 4);
397 		if ((buf->cur + 4) > buf->end)
398 			goto errout;
399 		keylen = *(CORBA_unsigned_long *) buf->cur;
400 		if (giop_msg_conversion_needed (buf))
401 			keylen = GUINT32_SWAP_LE_BE(keylen);
402 		buf->cur += 4;
403 		if ((buf->cur + keylen) > buf->end ||
404 		    (buf->cur + keylen) < buf->cur)
405 			goto errout;
406 		key = buf->cur;
407 		buf->cur += keylen;
408 		i++;
409 
410 		if (i >= nstrings)
411 			break;
412 
413 		buf->cur = ALIGN_ADDRESS (buf->cur, 4);
414 		if ((buf->cur + 4) > buf->end)
415 			goto errout;
416 		vallen = *(CORBA_unsigned_long *) buf->cur;
417 		if (giop_msg_conversion_needed (buf))
418 			vallen = GUINT32_SWAP_LE_BE(vallen);
419 		buf->cur += 4;
420 		if ((buf->cur + vallen) > buf->end ||
421 		    (buf->cur + vallen) < buf->cur)
422 			goto errout;
423 		value = buf->cur;
424 		buf->cur += vallen;
425 		i++;
426 
427 		g_hash_table_insert (initme->mappings, key, value);
428 	}
429 
430 	return FALSE;
431 
432  errout:
433 	if (initme->mappings)
434 		g_hash_table_destroy (initme->mappings);
435 
436 	return TRUE;
437 }
438 
439 void
ORBit_Context_server_free(CORBA_Context ctx)440 ORBit_Context_server_free (CORBA_Context ctx)
441 {
442 	g_hash_table_destroy (ctx->mappings);
443 }
444