1 /*
2 * Copyright 1999-2006 University of Chicago
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18 #include "globus_soap_message_attrs.h"
19 #include "globus_soap_message_utils.h"
20 #include "globus_i_soap_message.h"
21
22 typedef struct globus_l_message_attr_s
23 {
24 char * name;
25 void * value;
26 globus_soap_message_attr_copy_func_t copy;
27 globus_soap_message_attr_destroy_func_t destroy;
28 } globus_l_message_attr_t;
29
30 static
31 void
32 globus_l_message_attr_destroy(
33 void * attr)
34 406347 {
35 globus_l_message_attr_t * attribute;
36 GlobusFuncName(globus_l_message_attr_destroy);
37 406347 GlobusSoapMessageDebugEnter();
38
39
40 406347 attribute = (globus_l_message_attr_t *) attr;
41
42 406347 if(attribute)
43 {
44 406347 if(attribute->name)
45 {
46 406347 free(attribute->name);
47 }
48
49 406347 if(attribute->destroy && attribute->value)
50 {
51 206489 attribute->destroy(attribute->value);
52 }
53
54 406347 free(attribute);
55 }
56
57 406347 GlobusSoapMessageDebugExit();
58 406347 }
59
60 /**
61 * Initialize a new SOAP Message Attribute Set
62 * @ingroup globus_soap_message_attrs
63 *
64 * @param attrs
65 * New attribute set to initialize.
66 *
67 * @retval GLOBUS_SUCCESS
68 * Attributes successfully initialized.
69 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
70 * The @a attrs parameter was NULL.
71 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
72 * Insufficient memory to initialize the attributes.
73 */
74 globus_result_t
75 globus_soap_message_attr_init(
76 globus_soap_message_attr_t * attrs)
77 86674 {
78 86674 globus_result_t result = GLOBUS_SUCCESS;
79 GlobusFuncName(globus_soap_message_attr_init);
80 86674 GlobusSoapMessageDebugEnter();
81
82 86674 if (attrs == NULL)
83 {
84 0 result = GlobusSoapMessageErrorNullParam;
85
86 0 goto out;
87 }
88
89 86674 result = globus_hashtable_init(attrs, 19,
90 globus_hashtable_string_hash,
91 globus_hashtable_string_keyeq);
92
93 86674 if (result != GLOBUS_SUCCESS)
94 {
95 0 result = GlobusSoapMessageErrorOutOfMemory;
96 }
97 86674 GlobusSoapMessageDebugExit();
98 86674 out:
99 86674 return result;
100 }
101
102 /**
103 * Copy the contents of a SOAP Message Attribute Set to a new Attribute Set
104 * @ingroup globus_soap_message_attrs
105 *
106 * @param copied_attrs
107 * Attribute set to be initialized to contain the same attributes as
108 * @a attrs.
109 * @param attrs
110 * Attribute set to copy.
111 *
112 * @retval GLOBUS_SUCCESS
113 * Attributes successfully copied.
114 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
115 * The @a copied_attrs or @a attrs parameter was NULL.
116 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
117 * Insufficient memory to copy the attributes.
118 */
119 globus_result_t
120 globus_soap_message_attr_copy(
121 globus_soap_message_attr_t * copied_attrs,
122 globus_soap_message_attr_t attrs)
123 19273 {
124 globus_soap_message_attr_t new_attrs;
125 globus_l_message_attr_t * attr;
126 19273 globus_result_t result = GLOBUS_SUCCESS;
127 GlobusFuncName(globus_soap_message_attr_copy);
128 19273 GlobusSoapMessageDebugEnter();
129
130 19273 if (attrs == NULL || copied_attrs == NULL)
131 {
132 0 result = GlobusSoapMessageErrorNullParam;
133
134 0 goto error_exit;
135 }
136
137 19273 result = globus_soap_message_attr_init(&new_attrs);
138
139 19273 if (result != GLOBUS_SUCCESS)
140 {
141 0 goto error_exit;
142 }
143
144 19273 attr = globus_hashtable_first(&attrs);
145 98932 while(attr)
146 {
147 /* _set will copy the attr value */
148 60386 result = globus_soap_message_attr_set(
149 new_attrs,
150 attr->name,
151 attr->copy,
152 attr->destroy,
153 attr->value);
154 60386 if(result != GLOBUS_SUCCESS)
155 {
156 0 goto free_attrs_error;
157 }
158
159 60386 attr = globus_hashtable_next(&attrs);
160 }
161
162 19273 *copied_attrs = new_attrs;
163
164
165 19273 free_attrs_error:
166 19273 if (result != GLOBUS_SUCCESS)
167 {
168 0 globus_hashtable_destroy_all(
169 &new_attrs, globus_l_message_attr_destroy);
170 0 error_exit:
171 0 GlobusSoapMessageDebugError(result);
172 }
173 19273 GlobusSoapMessageDebugExit();
174 19273 return result;
175 }
176 /* globus_soap_message_attr_copy() */
177
178 /**
179 * Destroy a SOAP Message Attribute Set
180 * @ingroup globus_soap_message_attrs
181 *
182 * @param attrs
183 * Attribute set to destroy.
184 */
185 void
186 globus_soap_message_attr_destroy(
187 globus_soap_message_attr_t attrs)
188 86080 {
189 GlobusFuncName(globus_soap_message_attr_destroy);
190 86080 GlobusSoapMessageDebugEnter();
191
192 86080 globus_hashtable_destroy_all(
193 &attrs, globus_l_message_attr_destroy);
194
195 86080 GlobusSoapMessageDebugExit();
196 86080 }
197 /* globus_soap_message_attr_destroy() */
198
199 /**
200 * Set the value of an attribute
201 * @ingroup globus_soap_message_attrs
202 *
203 * @param attrs
204 * Attribute set to modify.
205 * @param name
206 * Name of the attribute to set.
207 * @param copy
208 * Function to make a copy of the attribute value. If this is NULL, then
209 * the attribute value will be treated as a scalar.
210 * @param destroy
211 * Function to destroy a copy of the attribute value. This may be NULL if
212 * the attribute value is a scalar.
213 * @param attrvalue
214 * Value to set the attribute to.
215 *
216 * @retval GLOBUS_SUCCESS
217 * Attributes successfully set.
218 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
219 * The @a attrs or @a name parameter was NULL.
220 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
221 * Insufficient memory to set the attribute.
222 */
223 globus_result_t
224 globus_soap_message_attr_set(
225 globus_soap_message_attr_t attrs,
226 const char * name,
227 globus_soap_message_attr_copy_func_t copy,
228 globus_soap_message_attr_destroy_func_t destroy,
229 void * attrvalue)
230 492565 {
231 492565 void * newvalue = NULL;
232 492565 globus_result_t result = GLOBUS_SUCCESS;
233 globus_l_message_attr_t * attr;
234 GlobusFuncName(globus_soap_message_attr_set);
235 492565 GlobusSoapMessageDebugEnter();
236
237 492565 if (attrs == NULL || name == NULL)
238 {
239 0 result = GlobusSoapMessageErrorNullParam;
240
241 0 goto error_exit;
242 }
243 492565 if(copy)
244 {
245 254756 result = copy(&newvalue, attrvalue);
246
247 254756 if (result != GLOBUS_SUCCESS)
248 {
249 0 goto error_exit;
250 }
251 }
252 else
253 {
254 237809 newvalue = attrvalue;
255 }
256
257 492565 attr = globus_hashtable_lookup(&attrs, (char *)name);
258 492565 if(!attr)
259 {
260 406849 attr = malloc(sizeof(globus_l_message_attr_t));
261 406849 if(!attr)
262 {
263 0 result = GlobusSoapMessageErrorOutOfMemory;
264 0 goto error_exit;
265 }
266 406849 memset(attr, 0, sizeof(globus_l_message_attr_t));
267
268 406849 attr->name = globus_libc_strdup(name);
269 406849 if (!attr->name)
270 {
271 0 result = GlobusSoapMessageErrorOutOfMemory;
272
273 0 goto free_attr_exit;
274 }
275 406849 attr->destroy = destroy;
276 406849 attr->copy = copy;
277
278 406849 result = globus_hashtable_insert(&attrs,
279 attr->name, attr);
280 406849 if(result != GLOBUS_SUCCESS)
281 {
282 0 result = GlobusSoapMessageErrorOutOfMemory;
283
284 0 goto free_attr_name_exit;
285 }
286 }
287 else
288 {
289 85716 if(attr->destroy)
290 {
291 48151 attr->destroy(attr->value);
292 }
293
294 85716 attr->destroy = destroy;
295 85716 attr->copy = copy;
296 }
297 492565 attr->value = newvalue;
298
299 492565 if (result != GLOBUS_SUCCESS)
300 {
301 0 free_attr_name_exit:
302 0 free(attr->name);
303 0 free_attr_exit:
304 0 free(attr);
305 0 error_exit:
306 0 GlobusSoapMessageDebugError(result);
307 }
308 492565 GlobusSoapMessageDebugExit();
309 492565 return result;
310 }
311 /* globus_soap_message_attr_set() */
312
313 /**
314 * Set the value of an attribute on a handle
315 * @ingroup globus_soap_message_attrs
316 *
317 * Adds or changes the value of a SOAP attribute on a SOAP message handle.
318 *
319 * @param handle
320 * Handle whose attributes will be modified.
321 * @param attr_name
322 * Name of the attribute to set.
323 * @param copy
324 * Function to make a copy of the attribute value. If this is NULL, then
325 * the attribute value will be treated as a scalar.
326 * @param destroy
327 * Function to destroy a copy of the attribute value. This may be NULL if
328 * the attribute value is a scalar.
329 * @param attrvalue
330 * Value to set the attribute to.
331 *
332 * @retval GLOBUS_SUCCESS
333 * Attributes successfully set.
334 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
335 * The @a handle or @a name parameter was NULL.
336 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
337 * Insufficient memory to set the attribute.
338 */
339 globus_result_t
340 globus_soap_message_handle_set_attr(
341 globus_soap_message_handle_t handle,
342 const char * attr_name,
343 globus_soap_message_attr_copy_func_t copy,
344 globus_soap_message_attr_destroy_func_t destroy,
345 void * attrvalue)
346 380221 {
347 380221 globus_result_t result = GLOBUS_SUCCESS;
348 GlobusFuncName(globus_soap_message_handle_set_attr);
349 380221 GlobusSoapMessageDebugEnter();
350
351 380221 if (handle == NULL || attr_name == NULL)
352 {
353 0 result = GlobusSoapMessageErrorNullParam;
354
355 0 goto error_exit;
356 }
357
358 380221 if (handle->attrs == NULL)
359 {
360 0 result = globus_soap_message_attr_init(&handle->attrs);
361
362 0 if (result != GLOBUS_SUCCESS)
363 {
364 0 goto error_exit;
365 }
366 }
367
368 380221 result = globus_soap_message_attr_set(
369 handle->attrs,
370 attr_name,
371 copy,
372 destroy,
373 attrvalue);
374
375 380221 if (result != GLOBUS_SUCCESS)
376 {
377 0 goto error_exit;
378 }
379 /* Hack: make the verbose attribute part of the handle struct for
380 * performance as its queried during all serialization and deserialization
381 * errors.
382 */
383 380221 if (strcmp(attr_name, GLOBUS_SOAP_MESSAGE_VERBOSE_ERRORS_KEY) == 0)
384 {
385 192 handle->verbose = (globus_bool_t) attrvalue;
386 }
387
388 380221 error_exit:
389 380221 GlobusSoapMessageDebugExit();
390 380221 return result;
391 }
392 /* globus_soap_message_handle_set_attr() */
393
394 /**
395 * Remove an attribute from an attribute set
396 * @ingroup globus_soap_message_attrs
397 *
398 * @param attrs
399 * Attribute set to modify.
400 * @param attr_name
401 * Name of the attribute to remove from the attribute set. Its current
402 * value will be returned.
403 *
404 * @return
405 * Returns the current value of the named attribute. This value is not
406 * managed by the handle and should be freed by the caller if it is a
407 * non-scalar value.
408 */
409 void *
410 globus_soap_message_attr_remove(
411 globus_soap_message_attr_t attrs,
412 const char * attr_name)
413 0 {
414 void * value;
415 globus_l_message_attr_t * attr;
416 GlobusFuncName(globus_soap_message_attr_remove);
417 0 GlobusSoapMessageDebugEnter();
418
419 0 if (attrs == NULL || attr_name == NULL)
420 {
421 0 value = NULL;
422
423 0 goto exit;
424 }
425 0 attr = globus_hashtable_remove(&attrs, (void *)attr_name);
426 0 if(!attr)
427 {
428 0 value = NULL;
429 0 goto exit;
430 }
431
432 0 value = attr->value;
433 0 attr->value = NULL;
434
435 0 globus_l_message_attr_destroy(attr);
436
437 0 exit:
438
439 0 GlobusSoapMessageDebugExit();
440 0 return value;
441 }
442 /* globus_soap_message_attr_remove() */
443
444 /**
445 * Remove an attribute from a handle's attribute set
446 * @ingroup globus_soap_message_attrs
447 *
448 * @param handle
449 * Handle to modify.
450 * @param attr_name
451 * Name of the attribute to remove from the handle's attribute set. Its
452 * current value will be returned.
453 *
454 * @return
455 * Returns the current value of the named attribute. This value is not
456 * managed by the handle and should be freed by the caller if it is a
457 * non-scalar value.
458 */
459 void *
460 globus_soap_message_handle_remove_attr(
461 globus_soap_message_handle_t handle,
462 const char * attr_name)
463 0 {
464 0 if (handle == NULL)
465 {
466 0 return NULL;
467 }
468 0 return globus_soap_message_attr_remove(
469 handle->attrs, attr_name);
470 }
471 /* globus_soap_message_handle_remove_attr() */
472
473 /**
474 * Get the current value of a SOAP message attribute
475 * @ingroup globus_soap_message_attrs
476 *
477 * @param attrs
478 * Attribute set to query.
479 * @param attr_name
480 * Name of the attribute to retrieve.
481 *
482 * @return
483 * Returns the current value of the named attribute. This value is managed
484 * by the handle and should not be freed or modified by the caller.
485 */
486 void *
487 globus_soap_message_attr_get(
488 globus_soap_message_attr_t attrs,
489 const char * attr_name)
490 832600 {
491 void * value;
492 globus_l_message_attr_t * attr;
493 GlobusFuncName(globus_soap_message_attr_get);
494 832600 GlobusSoapMessageDebugEnter();
495
496 832600 if (attrs == NULL || attr_name == NULL)
497 {
498 0 value = NULL;
499
500 0 goto exit;
501 }
502 832600 attr = globus_hashtable_lookup(&attrs, (char *)attr_name);
503 832600 if(!attr)
504 {
505 423276 value = NULL;
506 423276 goto exit;
507 }
508
509 409324 value = attr->value;
510
511 832600 exit:
512
513 832600 GlobusSoapMessageDebugExit();
514 832600 return value;
515 }
516 /* globus_soap_message_attr_get() */
517
518 /**
519 * Get the current value of a SOAP message attribute from a handle
520 * @ingroup globus_soap_message_attrs
521 *
522 * @param handle
523 * Handle to query.
524 * @param attr_name
525 * Name of the attribute to retrieve.
526 *
527 * @return
528 * Returns the current value of the named attribute. This value is managed
529 * by the handle and should not be freed or modified by the caller.
530 */
531 void *
532 globus_soap_message_handle_get_attr(
533 globus_soap_message_handle_t handle,
534 char * attr_name)
535 746117 {
536 void * value;
537 GlobusFuncName(globus_soap_message_handle_get_attr);
538 746117 GlobusSoapMessageDebugEnter();
539
540 746117 if (handle == NULL || attr_name == NULL)
541 {
542 0 value = NULL;
543
544 0 goto exit;
545 }
546
547 746117 value = globus_soap_message_attr_get(
548 handle->attrs,
549 attr_name);
550
551 746117 exit:
552 746117 GlobusSoapMessageDebugExit();
553 746117 return value;
554 }
555 /* globus_soap_message_handle_get_attr() */
556
557 /**
558 * Copy a SOAP message attribute set to a handle
559 * @ingroup globus_soap_message_attrs
560 *
561 * Replaces all of the attributes in an SOAP message handle with those in the
562 * given attribute set.
563 *
564 * @param handle
565 * Handle to modify. If this function is successfull, all attributes
566 * set on the handle will be freed and a copy of the attributes in
567 * @a attrs will be set on the handle.
568 * @param attrs
569 * New attributes to set on the handle.
570 *
571 * @retval GLOBUS_SUCCESS
572 * Attributes successfully set.
573 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
574 * The @a handle or @a attrs parameter was NULL.
575 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
576 * Insufficient memory to copy the attributes.
577 */
578 globus_result_t
579 globus_soap_message_handle_set_attrs(
580 globus_soap_message_handle_t handle,
581 globus_soap_message_attr_t attrs)
582 18544 {
583 globus_result_t result;
584 globus_soap_message_attr_t tmp_attrs;
585 GlobusFuncName(globus_soap_message_handle_set_attr);
586 18544 GlobusSoapMessageDebugEnter();
587
588 18544 if (handle == NULL || attrs == NULL)
589 {
590 0 result = GlobusSoapMessageErrorNullParam;
591
592 0 goto exit;
593 }
594 18544 tmp_attrs = handle->attrs;
595
596 18544 result = globus_soap_message_attr_copy(
597 &handle->attrs, attrs);
598
599 18544 if (result != GLOBUS_SUCCESS)
600 {
601 0 handle->attrs = tmp_attrs;
602 0 goto exit;
603 }
604 /* Hack: make the verbose attribute part of the handle struct for
605 * performance as its queried during all serialization and deserialization
606 * errors.
607 */
608 18544 handle->verbose = (globus_bool_t) globus_soap_message_attr_get(
609 attrs,
610 GLOBUS_SOAP_MESSAGE_VERBOSE_ERRORS_KEY);
611
612
613 if(tmp_attrs);
614 {
615 18544 globus_soap_message_attr_destroy(tmp_attrs);
616 }
617 18544 GlobusSoapMessageDebugExit();
618 18544 exit:
619 18544 return result;
620 }
621 /* globus_soap_message_handle_set_attrs() */
622
623 /**
624 * String copy wrapper for SOAP Message Attributes
625 * @ingroup globus_soap_message_attrs
626 *
627 * A version of strdup which matches the globus_soap_message_attr_copy_func_t
628 * function signature.
629 *
630 * @param new_str
631 * @param str
632 *
633 * @retval GLOBUS_SUCCESS
634 * String successfully copied.
635 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
636 * The @a new_str or @a str parameter was NULL.
637 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
638 * Insufficient memory to copy the string.
639 */
640 globus_result_t
641 globus_soap_message_attr_copy_string(
642 void ** new_str,
643 const void * str)
644 133938 {
645 133938 globus_result_t result = GLOBUS_SUCCESS;
646
647 133938 if (new_str == NULL || str == NULL)
648 {
649 0 result = GlobusSoapMessageErrorNullParam;
650
651 0 goto exit;
652 }
653 133938 *new_str = (void *) globus_libc_strdup((char *)str);
654
655 133938 if (*new_str == NULL)
656 {
657 0 result = GlobusSoapMessageErrorOutOfMemory;
658
659 0 goto exit;
660 }
661
662 133938 exit:
663 133938 return result;
664 }