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 #ifndef __LASSO_UTILS_H__
25 #define __LASSO_UTILS_H__
26
27 #include <stdio.h>
28 #include <glib.h>
29 #include <glib-object.h>
30 #include <xmlsec/keys.h>
31 #include "debug.h"
32 #include "backward_comp.h"
33 #include "xml/tools.h"
34 #include "logging.h"
35
36 #ifdef LASSO_DEBUG
37 #ifdef __GNUC__
38 #define lasso_check_type_equality(a,b) \
39 { \
40 enum { TYPE_MISMATCH = (1 / __builtin_types_compatible_p(typeof(a), typeof(b))) }; \
41 }
42 #else
43 #define lasso_check_type_equality(a,b)
44 #endif
45 #else
46 #define lasso_check_type_equality(a,b)
47 #endif
48
49 #ifdef __GNUC__
50 #define lasso_check_type_equality2(a,b,c) \
51 { \
52 enum { TYPE_MISMATCH = (1 / (__builtin_types_compatible_p(typeof(a), typeof(b))+__builtin_types_compatible_p(typeof(a), typeof(c)))) }; \
53 }
54 #else
55 #define lasso_check_type_equality2(a,b,c)
56 #endif
57
58 #define lasso_private_data(object) ((object)->private_data)
59
60 /**
61 * lasso_ref:
62 * @object: an object whose reference count must be incremented.
63 *
64 * Increment the reference count of an object, do not emit warning if it is NULL.
65 *
66 * Return value: the @object.
67 */
68 #define lasso_ref(object) ((object) != NULL ? (g_object_ref(object), object) : NULL)
69
70 /**
71 * lasso_unref:
72 * @object: an object whose reference count must be decremented.
73 *
74 * Decrement the reference count of an object, do not emit warnings if it is NULL.
75 *
76 * Return value: the @object.
77 */
78 #define lasso_unref(object) ((object) != NULL ? (g_object_unref(object), object) : NULL)
79
80 /* Freeing */
81
82 /*
83 * lasso_release_xxx are macros which ensure you do not get 'double free' errors, they first check
84 * that the variable is not NULL before calling the deallocation function, and after deallocation
85 * they reset the variable to NULL, preventing 'double free'.
86 */
87 #define lasso_release(dest) \
88 { \
89 if (dest) { \
90 g_free(dest); dest = NULL; \
91 } \
92 }
93
94 #define lasso_release_full(dest, free_function) \
95 { \
96 if (dest) { \
97 free_function(dest); dest = NULL; \
98 } \
99 }
100
101 #define lasso_release_full2(dest, free_function, type) \
102 { \
103 lasso_check_type_equality(dest, type); \
104 if (dest) { \
105 free_function(dest); dest = NULL; \
106 } \
107 }
108
109 #define lasso_release_gobject(dest) \
110 { \
111 if (G_IS_OBJECT(dest) || dest == NULL) { \
112 lasso_release_full(dest, g_object_unref); \
113 } else { \
114 message(G_LOG_LEVEL_CRITICAL, "Trying to unref a non GObject pointer file=%s:%u pointerbybname=%s pointer=%p", __FILE__, __LINE__, #dest, dest); \
115 } \
116 }
117
118 #define lasso_release_string(dest) \
119 lasso_release_full(dest, g_free)
120
121 #define lasso_release_list(dest) \
122 lasso_release_full2(dest, g_list_free, GList*)
123
124 #define lasso_release_slist(dest) \
125 lasso_release_full2(dest, g_slist_free, GSList*)
126
127 #define lasso_release_list_of_full(dest, free_function) \
128 { \
129 GList **__tmp = &(dest); \
130 if (*__tmp) { \
131 g_list_foreach(*__tmp, (GFunc)(void*)free_function, NULL); \
132 lasso_release_list(*__tmp); \
133 } \
134 }
135
136 #define lasso_release_list_of_strings(dest) \
137 lasso_release_list_of_full(dest, g_free)
138
139 #define lasso_release_list_of_gobjects(dest) \
140 lasso_release_list_of_full(dest, g_object_unref)
141
142 #define lasso_release_list_of_xml_node(dest) \
143 lasso_release_list_of_full(dest, xmlFreeNode)
144
145 #define lasso_release_list_of_xml_node_list(dest) \
146 lasso_release_list_of_full(dest, xmlFreeNodeList)
147
148 #define lasso_release_list_of_sec_key(dest) \
149 lasso_release_list_of_full(dest, xmlSecKeyDestroy)
150
151 #define lasso_release_xml_node(node) \
152 lasso_release_full2(node, xmlFreeNode, xmlNodePtr)
153
154 #define lasso_release_xml_node_list(node) \
155 lasso_release_full2(node, xmlFreeNodeList, xmlNodePtr)
156
157 #define lasso_release_doc(doc) \
158 lasso_release_full2(doc, xmlFreeDoc, xmlDocPtr)
159
160 #define lasso_release_xml_string(dest) \
161 lasso_release_full2(dest, xmlFree, xmlChar*)
162
163 #define lasso_release_encrypt_context(dest) \
164 lasso_release_full2(dest, xmlSecEncCtxDestroy, xmlSecEncCtxPtr)
165
166 #define lasso_release_signature_context(dest) \
167 lasso_release_full2(dest, xmlSecDSigCtxDestroy,xmlSecDSigCtxPtr)
168
169 #define lasso_release_key_manager(dest) \
170 lasso_release_full2(dest, xmlSecKeysMngrDestroy, xmlSecKeysMngrPtr)
171
172 #define lasso_release_output_buffer(dest) \
173 lasso_release_full2(dest, xmlOutputBufferClose, xmlOutputBufferPtr)
174
175 #define lasso_release_xpath_object(dest) \
176 lasso_release_full2(dest, xmlXPathFreeObject, xmlXPathObjectPtr)
177
178 #define lasso_release_xpath_context(dest) \
179 lasso_release_full2(dest, xmlXPathFreeContext, xmlXPathContextPtr)
180
181 #define lasso_release_xpath_job(xpathObject, xpathContext, xmlDocument) \
182 lasso_release_xpath_object(xpathObject); \
183 lasso_release_xpath_context(xpathContext); \
184 lasso_release_doc(xmlDocument)
185
186 #define lasso_release_sec_key(dest) \
187 lasso_release_full2(dest, xmlSecKeyDestroy, xmlSecKeyPtr)
188
189 #define lasso_release_ghashtable(dest) \
190 lasso_release_full(dest, g_hash_table_destroy)
191
192 #define lasso_release_gstring(dest, b) \
193 { \
194 GString **__tmp = &(dest); \
195 if (*__tmp) {\
196 g_string_free(*__tmp, (b)); \
197 *__tmp = NULL; \
198 } \
199 }
200
201 #define lasso_release_array_of_xml_strings(dest) \
202 { \
203 xmlChar ***__tmp = &(dest);\
204 if (*__tmp) {\
205 int i = 0;\
206 for (i = 0; (*__tmp)[i]; i++) {\
207 lasso_release_xml_string((*__tmp)[i]);\
208 }\
209 lasso_release((*__tmp));\
210 }\
211 }
212
213 /* Assignment and list appending */
214 /*
215 * lasso_assign_xxx macros ensure that you dot leak previous value of assigned things, they use
216 * lasso_release_xxx macros to deallocate, they also ensure proper reference counting on passed by
217 * references values and proper copying on passed by value values.
218 */
219 #define lasso_assign_string(dest,src) \
220 { \
221 char *__tmp = g_strdup(src);\
222 lasso_release_string(dest); \
223 dest = __tmp; \
224 }
225
226 #define lasso_assign_xml_string(dest,src) \
227 { \
228 xmlChar *__tmp = xmlStrdup(src); \
229 lasso_release_xml_string(dest); \
230 dest = __tmp; \
231 }
232
233 #define lasso_assign_new_string(dest,src) \
234 { \
235 char *__tmp = src; \
236 if (dest != __tmp) \
237 lasso_release_string(dest); \
238 dest = __tmp; \
239 }
240
241 #define lasso_assign_gobject(dest,src) \
242 { \
243 GObject *__tmp = G_OBJECT(src); \
244 if (__tmp) \
245 g_object_ref(__tmp); \
246 lasso_release_gobject(dest); \
247 dest = (void*)(__tmp); \
248 }
249
250 #define lasso_assign_new_gobject(dest,src) \
251 { \
252 GObject *__tmp = G_OBJECT(src); \
253 if (dest != (void*)__tmp) \
254 lasso_release_gobject(dest); \
255 dest = (void*)(__tmp); \
256 }
257
258 #define lasso_assign_xml_node(dest,src) \
259 { \
260 xmlNode *__tmp = (src); \
261 lasso_check_type_equality(dest, src); \
262 if (dest) \
263 xmlFreeNode(dest); \
264 dest = xmlCopyNode(__tmp, 1); \
265 }
266
267 #define lasso_assign_new_xml_node(dest,src) \
268 { \
269 xmlNode *__tmp = (src); \
270 lasso_check_type_equality(dest, src); \
271 if (dest) \
272 xmlFreeNode(dest); \
273 dest = __tmp; \
274 }
275
276 #define lasso_assign_xml_node_list(dest,src) \
277 { \
278 xmlNode *__tmp = (src); \
279 lasso_check_type_equality(dest, src); \
280 if (dest) \
281 xmlFreeNode(dest); \
282 dest = xmlCopyNodeList(__tmp); \
283 }
284
285 #define lasso_assign_new_xml_node_list(dest,src) \
286 lasso_assign_new_xml(dest, src)
287
288 #define lasso_assign_list(dest, src) \
289 { \
290 GList **__tmp = &(dest); \
291 if (*__tmp) \
292 g_list_free(*__tmp); \
293 *__tmp = g_list_copy((src)); \
294 }
295
296 #define lasso_assign_new_list_of_gobjects(dest, src) \
297 { \
298 GList *__tmp = (src); \
299 lasso_release_list_of_gobjects(dest); \
300 dest = (GList*)__tmp; \
301 }
302
303 #define lasso_assign_new_list_of_strings(dest, src) \
304 { \
305 GList *__tmp = (src); \
306 lasso_release_list_of_strings(dest); \
307 dest = (GList*)__tmp; \
308 }
309
310 #define lasso_assign_new_list_of_xml_node(dest, src) \
311 { \
312 GList *__tmp = (src); \
313 lasso_release_list_of_xml_node(dest); \
314 dest = (GList*)__tmp; \
315 }
316
317 #define lasso_assign_list_of_gobjects(dest, src) \
318 { \
319 GList *__tmp = (src); \
320 lasso_release_list_of_gobjects(dest); \
321 dest = g_list_copy(__tmp); \
322 for (;__tmp != NULL; __tmp = g_list_next(__tmp)) { \
323 if (G_IS_OBJECT(__tmp->data)) { \
324 g_object_ref(__tmp->data); \
325 } \
326 } \
327 }
328
329 #define lasso_assign_list_of_strings(dest, src) \
330 { \
331 GList *__tmp = src; \
332 GList *__iter_dest; \
333 lasso_release_list_of_strings(dest); \
334 dest = g_list_copy(__tmp); \
335 for (__iter_dest = dest ; __iter_dest != NULL ; __iter_dest = g_list_next(__iter_dest)) { \
336 __iter_dest->data = g_strdup(__iter_dest->data); \
337 } \
338 }
339
340 #define lasso_assign_list_of_xml_node(dest, src) \
341 { \
342 GList *__tmp = src; \
343 GList *__iter_dest; \
344 lasso_release_list_of_xml_node(dest); \
345 dest = g_list_copy(__tmp); \
346 for (__iter_dest = dest ; __iter_dest != NULL ; __iter_dest = g_list_next(__iter_dest)) { \
347 __iter_dest->data = xmlCopyNode(__iter_dest->data, 1); \
348 } \
349 }
350
351 #define lasso_assign_new_sec_key(dest, src) \
352 { \
353 xmlSecKey *__tmp = (src); \
354 if (dest) \
355 lasso_release_sec_key(dest); \
356 dest = __tmp; \
357 }
358
359 #define lasso_assign_sec_key(dest, src) \
360 { \
361 xmlSecKey *__tmp = NULL; \
362 if (src) {\
363 __tmp = xmlSecKeyDuplicate(src); \
364 } \
365 if (dest) \
366 lasso_release_sec_key(dest); \
367 dest = __tmp; \
368 }
369
370 G_GNUC_UNUSED static void
_lasso_copy_helper_assign_table_of_attributes(gpointer key,gpointer val,gpointer dest)371 _lasso_copy_helper_assign_table_of_attributes(gpointer key, gpointer val, gpointer dest){
372 g_hash_table_insert((GHashTable*) dest, g_strdup(key), g_strdup(val));
373 }
374
375 #define lasso_assign_table_of_attributes(dest, src) \
376 {\
377 if (!dest) {\
378 (dest) = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);\
379 }\
380 g_hash_table_remove_all(dest);\
381 g_hash_table_foreach(src, _lasso_copy_helper_assign_table_of_attributes, dest);\
382 }
383
384
385 /* List appending */
386
387 /* lasso_list_add_xxx macros, simplify code around list manipulation (g_list_append needs to be
388 * used like this 'l = g_list_appen(l, value)' ) and ensure proper reference count or copying of
389 * values.
390 */
391 #define lasso_list_add(dest, src) \
392 { \
393 lasso_check_type_equality((src), void*); \
394 dest = g_list_append(dest, (src)); \
395 }
396
397 #define lasso_list_add_non_null(dest, src) \
398 { \
399 void *__tmp_non_null_src = (src); \
400 if (__tmp_non_null_src != NULL) { \
401 dest = g_list_append(dest, __tmp_non_null_src); \
402 } else { \
403 message(G_LOG_LEVEL_CRITICAL, "Adding a NULL value to a non-NULL content list: dest=%s src=%s", #dest, #src); \
404 } \
405 }
406
407 #define lasso_list_add_string(dest, src) \
408 { \
409 lasso_list_add_non_null(dest, g_strdup(src));\
410 }
411
412 #define lasso_list_add_new_string(dest, src) \
413 { \
414 gchar *__tmp = src; \
415 lasso_list_add_non_null(dest, __tmp); \
416 }
417
418 #define lasso_list_add_xml_string(dest, src) \
419 {\
420 xmlChar *__tmp_src = (src);\
421 lasso_list_add_non_null(dest, (void*)g_strdup((char*)__tmp_src));\
422 }
423
424 #define lasso_list_add_gobject(dest, src) \
425 { \
426 void *__tmp_src = (src); \
427 if (G_IS_OBJECT(__tmp_src)) { \
428 dest = g_list_append(dest, g_object_ref(__tmp_src)); \
429 } else { \
430 message(G_LOG_LEVEL_CRITICAL, "Trying to add to a GList* a non GObject pointer dest=%s src=%s", #dest, #src); \
431 } \
432 }
433
434 #define lasso_list_add_new_gobject(dest, src) \
435 { \
436 void *__tmp_src = (src); \
437 if (G_IS_OBJECT(__tmp_src)) { \
438 dest = g_list_append(dest, __tmp_src); \
439 } else { \
440 message(G_LOG_LEVEL_CRITICAL, "Trying to add to a GList* a non GObject pointer dest=%s src=%s", #dest, #src); \
441 } \
442 }
443
444 #define lasso_list_add_xml_node(dest, src) \
445 { \
446 xmlNode *__tmp_src = xmlCopyNode(src, 1); \
447 lasso_list_add_non_null(dest, __tmp_src); \
448 }
449
450 #define lasso_list_add_new_xml_node(dest, src) \
451 { \
452 xmlNode *__tmp_src = src; \
453 lasso_list_add_non_null(dest, __tmp_src); \
454 }
455
456 #define lasso_list_add_xml_node_list(dest, src) \
457 { \
458 xmlNode *__tmp_src = xmlCopyNodeList(src); \
459 lasso_list_add_non_null(dest, __tmp_src); \
460 }
461
462 #define lasso_list_add_new_xml_node_list(dest, src) \
463 lasso_list_add_new_xml_node(dest, src)
464
465 #define lasso_list_add_gstrv(dest, src) \
466 { \
467 GList **__tmp_dest = &(dest); \
468 const char **__iter = (const char**)(src); \
469 while (__iter && *__iter) { \
470 lasso_list_add_string(*__tmp_dest, *__iter); \
471 } \
472 }
473
474 #define lasso_list_add_new_sec_key(dest, src) \
475 { \
476 xmlSecKey *__tmp_src = (src); \
477 lasso_list_add_non_null(dest, __tmp_src); \
478 }
479
480 /* List element removal */
481 #define lasso_list_remove_gobject(list, gobject) \
482 do { void *__tmp = gobject; GList **__tmp_list = &(list); \
483 *__tmp_list = g_list_remove(*__tmp_list, __tmp); \
484 lasso_unref(__tmp); } while(0)
485
486 /* List element membership */
487 #define lasso_is_in_list_of_strings(list, item) \
488 g_list_find_custom(list, item, (GCompareFunc)g_strcmp0) == NULL ? FALSE : TRUE
489
490
491 /* Pointer ownership transfer */
492
493 /* lasso_transfer_xxx macros are like lasso_assign_xxx but they do not increment reference count or
494 * copy the source value, instead they steal the value (and set the source to NULL, preventing stale
495 * references).
496 */
497 #define lasso_transfer_full(dest, src, kind) \
498 {\
499 lasso_release_##kind((dest)); \
500 lasso_check_type_equality(dest, src); \
501 (dest) = (void*)(src); \
502 (src) = NULL; \
503 }
504
505 #define lasso_transfer_xpath_object(dest, src) \
506 lasso_transfer_full(dest, src, xpath_object)
507
508 #define lasso_transfer_string(dest, src) \
509 lasso_transfer_full(dest, src, string)
510
511 #define lasso_transfer_gobject(dest, src) \
512 lasso_transfer_full(dest, src, gobject)
513
514 #define lasso_transfer_xml_node(dest, src) \
515 lasso_transfer_full(dest, src, xml_node)
516
517 /* Node extraction */
518 #define lasso_extract_node_or_fail(to, from, kind, error) \
519 {\
520 void *__tmp = (from); \
521 if (LASSO_IS_##kind(__tmp)) { \
522 to = LASSO_##kind(__tmp); \
523 } else { \
524 rc = error; \
525 goto cleanup; \
526 }\
527 }
528
529 /* Bad param handling */
530 #define lasso_return_val_if_invalid_param(kind, name, val) \
531 g_return_val_if_fail(LASSO_IS_##kind(name), val)
532
533 #define lasso_bad_param(kind, name) \
534 lasso_return_val_if_invalid_param(kind, name, \
535 LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
536
537 #define lasso_null_param(name) \
538 g_return_val_if_fail(name != NULL, LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
539
540 /**
541 * lasso_check_non_empty_string:
542 * @str: a char pointer
543 *
544 * Check that @str is non-NULL and not empty, otherwise jump to cleanup and return
545 * LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ.
546 */
547 #define lasso_check_non_empty_string(str) \
548 goto_cleanup_if_fail_with_rc(! lasso_strisempty(str), \
549 LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
550
551 /*
552 * We extensively use goto operator but in a formalized way, i.e. only for error checking code
553 * paths.
554 *
555 * The next macros goto_cleanup_xxxx encapsulate idioms used in lasso, like checking for a condition
556 * or setting the return code which must be called 'rc' and be of an 'int' type.
557 */
558
559 /*
560 * The following macros are made to create some formalism for function's cleanup code.
561 *
562 * The exit label should be called 'cleanup'. And for functions returning an integer error code, the
563 * error code should be named 'rc' and 'return rc;' should be the last statement of the function.
564 */
565
566 /**
567 * goto_cleanup_with_rc:
568 * @rc_value: integer return value
569 *
570 * This macro jump to the 'cleanup' label and set the return value to @rc_value.
571 *
572 */
573 #define goto_cleanup_with_rc(rc_value) \
574 do {\
575 rc = (rc_value); \
576 goto cleanup; \
577 } while(0);
578
579 /**
580 * goto_cleanup_if_fail:
581 * @condition: a boolean condition
582 *
583 * Jump to the 'cleanup' label if the @condition is FALSE.
584 *
585 */
586 #define goto_cleanup_if_fail(condition) \
587 {\
588 if (! (condition) ) {\
589 goto cleanup; \
590 } \
591 }
592
593 /**
594 * goto_cleanup_if_fail_with_rc:
595 * @condition: a boolean condition
596 * @rc_value: integer return value
597 *
598 * Jump to the 'cleanup' label if the @condition is FALSE and set the return value to
599 * @rc_value.
600 *
601 */
602 #define goto_cleanup_if_fail_with_rc(condition, rc_value) \
603 {\
604 if (! (condition) ) {\
605 rc = (rc_value); \
606 goto cleanup; \
607 } \
608 }
609
610 /**
611 * goto_cleanup_if_fail_with_rc_with_warning:
612 * @condition: a boolean condition
613 * @rc_value: integer return value
614 *
615 * Jump to the 'cleanup' label if the @condition is FALSE and set the return value to
616 * @rc_value. Also emit a warning, showing the condition and the return value.
617 *
618 */
619 #define goto_cleanup_if_fail_with_rc_with_warning(condition, rc_value) \
620 {\
621 if (! (condition) ) {\
622 message(G_LOG_LEVEL_WARNING, "%s failed, returning %s", #condition, #rc_value);\
623 rc = (rc_value); \
624 goto cleanup; \
625 } \
626 }
627
628 /**
629 * check_good_rc:
630 * @what: a call to a function returning a lasso error code
631 *
632 * Check if return code is 0, if not store it in rc and jump to cleanup label.
633 */
634 #define lasso_check_good_rc(what) \
635 { \
636 int __rc = (what);\
637 goto_cleanup_if_fail_with_rc(__rc == 0, __rc); \
638 }
639
640 #define lasso_mem_debug(who, what, where) \
641 { \
642 if (lasso_flag_memory_debug) \
643 fprintf(stderr, " freeing %s/%s (at %p)\n", who, what, (void*)where); \
644 }
645
646 /**
647 * lasso_foreach:
648 * @_iter: a #GList variable, which will server to traverse @_list
649 * @_list: a #GList value, which we will traverse
650 *
651 * Traverse a #GList list using 'for' construct. It must be followed by a block or a statement.
652 */
653 #define lasso_foreach(_iter, _list) \
654 for (_iter = (_list); _iter; _iter = g_list_next(_iter))
655
656 /**
657 * lasso_foreach_full_begin:
658 * @_type: the type of the variable @_data
659 * @_data: the name of the variable to define to store data values
660 * @_iter: the name of the variable to define to store the iterator
661 * @_list: the GList* to iterate
662 *
663 * Traverse a GList* @_list, using @_iter as iteration variable extract data field to variable
664 * @_data of type @_type.
665 */
666 #define lasso_foreach_full_begin(_type, _data, _iter, _list) \
667 { \
668 _type _data = NULL; \
669 GList *_iter = NULL; \
670 for (_iter = (_list); _iter && ((_data = _iter->data), 1); _iter = g_list_next(_iter)) \
671 {
672
673 #define lasso_foreach_full_end() \
674 } }
675
676 /**
677 * lasso_list_get_first_child:
678 * @list:(allowed-none): a #GList node or NULL.
679 *
680 * Return the first child in a list, or NULL.
681 */
682 #define lasso_list_get_first_child(list) \
683 ((list) ? (list)->data : NULL)
684
685 /* Get a printable extract for error messages */
686 char* lasso_safe_prefix_string(const char *str, gsize length);
687
688 int lasso_gobject_is_of_type(GObject *a, GType b);
689
690 GObject *lasso_extract_gtype_from_list(GType type, GList *list);
691
692 GObject * lasso_extract_gtype_from_list_or_new(GType type, GList **list, gboolean create);
693
694 /* Get first node of this type in a list */
695 /* ex: lasso_extract_node (LassoNode, LASSO_TYPE_NODE, list) */
696 #define lasso_extract_gobject_from_list(type, gobjecttype, list) \
697 ((type*) lasso_extract_gtype_from_list(gobjecttype, list))
698
699 /*
700 * Simplify simple accessors argument checking.
701 *
702 */
703 #define lasso_return_val_if_fail(assertion, value) \
704 if (!(assertion)) return (value);
705
706 #define lasso_return_null_if_fail(assertion) \
707 lasso_return_val_if_fail(assertion, NULL)
708
709 #define lasso_return_if_fail(assertion) \
710 if (!(assertion)) return;
711
712 #define lasso_trace(args...) \
713 if (lasso_flag_memory_debug) { \
714 fprintf(stderr, ## args); \
715 }
716
717 /* Lasso string data helpers */
718 inline static gboolean
lasso_strisequal(const char * a,const char * b)719 lasso_strisequal(const char *a, const char *b) {
720 return (g_strcmp0(a,b) == 0);
721 }
722 inline static gboolean
lasso_strisnotequal(const char * a,const char * b)723 lasso_strisnotequal(const char *a, const char *b) {
724 return ! lasso_strisequal(a,b);
725 }
726 inline static gboolean
lasso_strisempty(const char * str)727 lasso_strisempty(const char *str) {
728 return ((str) == NULL || (str)[0] == '\0');
729 }
730 inline static gboolean
lasso_xmlstrisnotequal(const xmlChar * a,const xmlChar * b)731 lasso_xmlstrisnotequal(const xmlChar *a, const xmlChar *b) {
732 return lasso_strisnotequal((char*)a, (char*)b);
733 }
734
735 /**
736 * lasso_crypto_memequal:
737 * @a: first buffer
738 * @b: second buffer
739 * @l: common length
740 *
741 * Compare two buffers, preventing timing attacks.
742 */
743 static inline gboolean
lasso_crypto_memequal(void * a,void * b,unsigned int l)744 lasso_crypto_memequal(void *a, void *b, unsigned int l)
745 {
746 unsigned char *x = a, *y = b;
747 gboolean result = TRUE;
748
749 for (;l;l--, x++, y++) {
750 result = result && (*x == *y);
751 }
752 return result;
753 }
754
755 #endif /* __LASSO_UTILS_H__ */
756