1 /* zxlib.c - Utility functions for generated (and other) code
2 * Copyright (c) 2010-2011 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
3 * Copyright (c) 2006-2009 Symlabs (symlabs@symlabs.com), All Rights Reserved.
4 * Author: Sampo Kellomaki (sampo@iki.fi)
5 * This is confidential unpublished proprietary source code of the author.
6 * NO WARRANTY, not even implied warranties. Contains trade secrets.
7 * Distribution prohibited unless authorized in writing.
8 * Licensed under Apache License 2.0, see file COPYING.
9 * $Id: zxlib.c,v 1.41 2009-11-24 23:53:40 sampo Exp $
10 *
11 * 28.5.2006, created --Sampo
12 * 8.8.2006, moved lookup functions to generated code --Sampo
13 * 12.8.2006, added special scanning of xmlns to avoid backtracking elem recognition --Sampo
14 * 26.8.2006, significant Common Subexpression Elimination (CSE) --Sampo
15 * 30.9.2007, more CSE --Sampo
16 * 7.10.2008, added documentation --Sampo
17 * 26.5.2010, added XML parse error reporting --Sampo
18 * 27.10.2010, re-engineered namespace handling --Sampo
19 */
20
21 #include "platform.h" /* needed on Win32 for snprintf(), va_copy() et al. */
22
23 //#include <pthread.h>
24 #include <memory.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <sys/stat.h>
30
31 #include "errmac.h"
32 #include "zx.h"
33 #include "c/zx-ns.h"
34 #include "c/zx-data.h"
35
36 /*(-) ZX implementation of memmem(3) for platforms that do not have this. */
37
38 /* Called by: */
zx_memmem(const char * haystack,int haystack_len,const char * needle,int needle_len)39 char* zx_memmem(const char* haystack, int haystack_len, const char* needle, int needle_len)
40 {
41 const char* lim = haystack + haystack_len - needle_len;
42 for (; haystack < lim; ++haystack)
43 if (!memcmp(haystack, needle, needle_len))
44 return (char*)haystack; /* discards const qualifier, but is right if haystack was modifiable, as often is the case. */
45 return 0;
46 }
47
48 #ifdef MINGW
49 /*(-) On windows the errno is not set. */
50 /* Called by: */
zx_CreateFile(LPCTSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile)51 HANDLE zx_CreateFile(LPCTSTR lpFileName,
52 DWORD dwDesiredAccess, DWORD dwShareMode,
53 LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
54 DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
55 {
56 D("CreateFile(%s)", lpFileName);
57 HANDLE res = CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
58 dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
59 errno = GetLastError();
60 return res;
61 }
62 #endif
63
64 #ifdef MINGW
65 #ifdef stat
66 #undef stat
67 #endif
68 #endif
69
70 /*(-) ZX implmentation of stat for mingw which is dumb */
71 /* Called by: */
zx_stat(const char * path,struct stat * buffer)72 int zx_stat( const char *path, struct stat *buffer )
73 {
74 int rv = 0;
75 char *p = (char*)malloc( strlen( path ) + 1 );
76 strcpy( p, path );
77
78 if( p[ strlen(p) - 1 ] == '/' )
79 p[ strlen(p) - 1 ] = '\0';
80
81 rv = stat( p, buffer );
82 free( p );
83 return rv;
84 }
85
86 /*() ZX memory allocator that does not zero the buffer. Allocation is
87 * potentially done relative to ZX context <<italic: c>>, though
88 * actual (2008) implementation simply uses malloc(3). See also zx_reset_ctx().
89 *
90 * Rather than reference this function directly, you should
91 * use the ZX_ALLOC() macro as much as possible.
92 *
93 * Some implementations may take c->mx mutex lock. However, they will
94 * do so such that no deadlock will result even if already taken. */
95
96 /* Called by: zx_zalloc */
zx_alloc(struct zx_ctx * c,int size)97 void* zx_alloc(struct zx_ctx* c, int size) {
98 char* p;
99 p = (c&&c->malloc_func)?c->malloc_func(size):malloc(size);
100 DD("malloc %p size=%d", p, size);
101 if (!p) {
102 ERR("Out-of-memory(%d)", size);
103 if (size < 0)
104 DIE_ACTION(1);
105 exit(1);
106 }
107 return p;
108 }
109
110 /*() ZX memory allocator that zeroes the buffer. Allocation is
111 * potentially done relative to ZX context <<italic: c>>, though
112 * actual (2008) implementation simply uses malloc(3).
113 *
114 * Rather than reference this function directly, you should
115 * use the ZX_ALLOC() macro as much as possible. */
116
117 /* Called by: zxid_parse_conf_raw */
zx_zalloc(struct zx_ctx * c,int size)118 void* zx_zalloc(struct zx_ctx* c, int size) {
119 char* p = zx_alloc(c, size);
120 ZERO(p, size);
121 return p;
122 }
123
124
125 /*() ZX memory free'er. Freeing is
126 * potentially done relative to ZX context <<italic: c>>, though
127 * actual (2008) implementation simply uses free(3).
128 *
129 * Rather than reference this function directly, you should
130 * use the ZX_FREE() macro as much as possible. */
131
132 /* Called by: */
zx_free(struct zx_ctx * c,void * p)133 void* zx_free(struct zx_ctx* c, void* p) {
134 if (!p)
135 return 0;
136 if (c && c->free_func)
137 c->free_func(p);
138 else
139 free(p);
140 return 0;
141 }
142
143 /*() Convert zx_str to C string. The ZX context will provide the memory. */
144
145 /* Called by: */
zx_str_to_c(struct zx_ctx * c,struct zx_str * ss)146 char* zx_str_to_c(struct zx_ctx* c, struct zx_str* ss) {
147 char* p = ZX_ALLOC(c, ss->len+1);
148 memcpy(p, ss->s, ss->len);
149 p[ss->len] = 0;
150 return p;
151 }
152
153 /*() zx_str_conv() helps SWIG typemaps to achieve natural conversion
154 * to native length + data representations of scripting languages.
155 * Should not need to use directly. */
156
157 /* Called by: covimp_test */
zx_str_conv(struct zx_str * ss,int * out_len,char ** out_s)158 void zx_str_conv(struct zx_str* ss, int* out_len, char** out_s) /* SWIG typemap friendly */
159 {
160 *out_s = 0;
161 *out_len = 0;
162 if (!ss)
163 return;
164 *out_s = ss->s;
165 *out_len = ss->len;
166 }
167
168 /*() Free both the zx_str node and the underlying string data */
169
170 /* Called by: main, zx_free_elem, zx_prefix_seen_whine, zxbus_send_cmdf, zxenc_privkey_dec, zxenc_pubkey_enc, zxenc_symkey_enc, zxid_addmd x3, zxid_anoint_a7n x5, zxid_anoint_sso_resp x4, zxid_az_soap x3, zxid_cache_epr, zxid_decode_redir_or_post, zxid_deflate_safe_b64, zxid_fed_mgmt_cf x3, zxid_idp_dispatch x2, zxid_idp_list_cf_cgi x3, zxid_idp_soap, zxid_idp_soap_dispatch x2, zxid_idp_sso x4, zxid_lecp_check, zxid_mgmt x3, zxid_mk_art_deref, zxid_mk_enc_a7n, zxid_mk_enc_id, zxid_mk_mni, zxid_mk_oauth_az_req x2, zxid_psobj_dec, zxid_psobj_enc, zxid_reg_svc x3, zxid_saml2_post_enc x2, zxid_saml2_redir, zxid_saml2_redir_enc x2, zxid_saml2_redir_url, zxid_saml2_resp_redir, zxid_send_sp_meta, zxid_simple_no_ses_cf x4, zxid_simple_ses_active_cf, zxid_simple_show_idp_sel, zxid_simple_show_page x3, zxid_slo_resp_redir, zxid_snarf_eprs_from_ses, zxid_soap_call_raw, zxid_soap_cgi_resp_body x2, zxid_sp_dispatch x2, zxid_sp_mni_soap, zxid_sp_slo_soap, zxid_sp_soap, zxid_sp_soap_dispatch x7, zxid_sp_sso_finalize, zxid_sso_issue_jwt x2, zxid_ssos_anreq, zxid_start_sso_location, zxid_user_sha1_name, zxid_write_ent_to_cache, zxid_wsf_validate_a7n, zxsig_sign */
zx_str_free(struct zx_ctx * c,struct zx_str * ss)171 void zx_str_free(struct zx_ctx* c, struct zx_str* ss) {
172 if (ss->s)
173 ZX_FREE(c, ss->s);
174 ZX_FREE(c, ss);
175 }
176
177 /*() Construct zx_str from length and raw string data, which will be referenced, not copied. */
178
179 /* Called by: */
zx_ref_len_str(struct zx_ctx * c,int len,const char * s)180 struct zx_str* zx_ref_len_str(struct zx_ctx* c, int len, const char* s) {
181 struct zx_str* ss = ZX_ZALLOC(c, struct zx_str);
182 ss->s = (char*)s; /* ref points to underlying data */
183 ss->len = len;
184 return ss;
185 }
186
187 /*() Construct zx_str from C string, which will be referenced, not copied. */
188
189 /* Called by: */
zx_ref_str(struct zx_ctx * c,const char * s)190 struct zx_str* zx_ref_str(struct zx_ctx* c, const char* s) {
191 if (!s)
192 return 0;
193 return zx_ref_len_str(c, strlen(s), s);
194 }
195
196 /*() Newly allocated string (node and data) of specified length, but uninitialized */
197
198 /* Called by: */
zx_new_len_str(struct zx_ctx * c,int len)199 struct zx_str* zx_new_len_str(struct zx_ctx* c, int len) {
200 struct zx_str* ss = ZX_ZALLOC(c, struct zx_str);
201 ss->s = ZX_ALLOC(c, len+1);
202 ss->s[len] = 0;
203 ss->len = len;
204 return ss;
205 }
206
207 /*() Construct zx_str by duplication of raw string data of given length. */
208
209 /* Called by: */
zx_dup_len_str(struct zx_ctx * c,int len,const char * s)210 struct zx_str* zx_dup_len_str(struct zx_ctx* c, int len, const char* s) {
211 struct zx_str* ss = zx_new_len_str(c, len);
212 memcpy(ss->s, s, len);
213 return ss;
214 }
215
216 /*() Construct zx_str by duplication of C string. */
217
218 /* Called by: */
zx_dup_str(struct zx_ctx * c,const char * s)219 struct zx_str* zx_dup_str(struct zx_ctx* c, const char* s) {
220 return zx_dup_len_str(c, strlen(s), s);
221 }
222
223 /*() Create an allocated cstr (nul terminated) from len and ptr. */
224
225 /* Called by: */
zx_dup_len_cstr(struct zx_ctx * c,int len,const char * str)226 char* zx_dup_len_cstr(struct zx_ctx* c, int len, const char* str) {
227 char* s = ZX_ALLOC(c, len+1);
228 memcpy(s, str, len);
229 s[len] = 0; /* nul termination */
230 return s;
231 }
232
233 /*() ZX version of strdup(). */
234
235 /* Called by: */
zx_dup_cstr(struct zx_ctx * c,const char * str)236 char* zx_dup_cstr(struct zx_ctx* c, const char* str) {
237 int len = strlen(str);
238 return zx_dup_len_cstr(c, len, str);
239 }
240
241 /* Called by: zxid_call_trustpdp x3, zxid_wsp_validate_env x2 */
zx_dup_zx_str(struct zx_ctx * c,struct zx_str * ss)242 struct zx_str* zx_dup_zx_str(struct zx_ctx* c, struct zx_str* ss) {
243 return zx_dup_len_str(c, ss->len, ss->s);
244 }
245
246 /* ------------------ ATTR ------------------ */
247
248 /*() Construct zx_attr_s from length and raw string data, which will be referenced, not copied. */
249
250 /* Called by: */
zx_ref_len_attr(struct zx_ctx * c,struct zx_elem_s * father,int tok,int len,const char * s)251 struct zx_attr_s* zx_ref_len_attr(struct zx_ctx* c, struct zx_elem_s* father, int tok, int len, const char* s)
252 {
253 struct zx_attr_s* ss = ZX_ZALLOC(c, struct zx_attr_s);
254 ss->g.s = (char*)s; /* ref points to underlying data */
255 ss->g.len = len;
256 ss->g.tok = tok;
257 if (father) {
258 ss->g.n = &father->attr->g;
259 father->attr = ss;
260 }
261 return ss;
262 }
263
264 /*() Construct zx_attr_s from C string, which will be referenced, not copied. */
265
266 /* Called by: */
zx_ref_attr(struct zx_ctx * c,struct zx_elem_s * father,int tok,const char * s)267 struct zx_attr_s* zx_ref_attr(struct zx_ctx* c, struct zx_elem_s* father, int tok, const char* s) {
268 if (!s)
269 return 0;
270 return zx_ref_len_attr(c, father, tok, strlen(s), s);
271 }
272
273 /*() Newly allocated attribute (node and data) of specified length, but uninitialized */
274
275 /* Called by: zx_dup_len_attr */
zx_new_len_attr(struct zx_ctx * c,struct zx_elem_s * father,int tok,int len)276 struct zx_attr_s* zx_new_len_attr(struct zx_ctx* c, struct zx_elem_s* father, int tok, int len)
277 {
278 struct zx_attr_s* ss = ZX_ZALLOC(c, struct zx_attr_s);
279 ss->g.s = ZX_ALLOC(c, len+1);
280 ss->g.s[len] = 0;
281 ss->g.len = len;
282 ss->g.tok = tok;
283 if (father) {
284 ss->g.n = &father->attr->g;
285 father->attr = ss;
286 }
287 return ss;
288 }
289
290 /*() Construct zx_str by duplication of raw string data of given length. */
291
292 /* Called by: */
zx_dup_len_attr(struct zx_ctx * c,struct zx_elem_s * father,int tok,int len,const char * s)293 struct zx_attr_s* zx_dup_len_attr(struct zx_ctx* c, struct zx_elem_s* father, int tok, int len, const char* s) {
294 struct zx_attr_s* ss = zx_new_len_attr(c, father, tok, len);
295 memcpy(ss->g.s, s, len);
296 return ss;
297 }
298
299 /*() Construct zx_str by duplication of C string. */
300
301 /* Called by: */
zx_dup_attr(struct zx_ctx * c,struct zx_elem_s * father,int tok,const char * s)302 struct zx_attr_s* zx_dup_attr(struct zx_ctx* c, struct zx_elem_s* father, int tok, const char* s) {
303 return zx_dup_len_attr(c, father, tok, strlen(s), s);
304 }
305
306 /*() vasprintf(3) implementation that will grab its memory from ZX memory allocator.
307 * String will be nul terminated. Optional retlen result paremeter allows the
308 * length to be returned. Specify 0 if this is not needed. */
309
310 /* Called by: zx_alloc_sprintf, zx_attrf, zx_strf, zxid_callf, zxid_callf_epr, zxid_wsc_prepare_callf, zxid_wsp_decoratef */
zx_alloc_vasprintf(struct zx_ctx * c,int * retlen,const char * f,va_list ap)311 char* zx_alloc_vasprintf(struct zx_ctx* c, int* retlen, const char* f, va_list ap) /* data is new memory */
312 {
313 va_list ap2;
314 int len;
315 char* s;
316 char buf[2];
317 va_copy(ap2, ap);
318 /* Windows _vsnprintf() is quite different (and broken IMHO) wrt return value of vsnprintf()
319 * http://msdn.microsoft.com/en-us/library/2ts7cx93.aspx
320 * However, while undocumented, passing NULL buffer and zero size (instead of
321 * the traditional buffer of size 1) seems to produce desired result - at least
322 * on recent Windows releases (2013, Win7?). */
323 #if MINGW
324 len = vsnprintf(0, 0, f, ap2);
325 #else
326 len = vsnprintf(buf, 1, f, ap2);
327 #endif
328 va_end(ap2);
329 if (len < 0) {
330 platform_broken_snprintf(len, __FUNCTION__, 1, f);
331 if (retlen)
332 *retlen = 0;
333 s = ZX_ALLOC(c, 1);
334 s[0] = 0;
335 return s;
336 }
337 s = ZX_ALLOC(c, len+1);
338 vsnprintf(s, len+1, f, ap);
339 s[len] = 0; /* must terminate manually as on win32 nul termination is not guaranteed */
340 if (retlen)
341 *retlen = len;
342 return s;
343 }
344
345 /*() sprintf(3) implementation that will grab its memory from ZX memory allocator.
346 * String will be nul terminated. Optional retlen result paremeter allows the
347 * length to be returned. Specify 0 if this is not needed. */
348
349 /* Called by: zxid_add_env_if_needed, zxid_pool2env x4, zxid_ps_accept_invite, zxid_ps_finalize_invite, zxid_pw_authn x2, zxid_query_ctlpt_pdp, zxid_saml2_post_enc x2, zxid_show_protected_content_setcookie x4, zxid_simple_idp_an_ok_do_rest, zxid_simple_idp_new_user, zxid_simple_idp_recover_password, zxid_simple_idp_show_an, zxid_simple_show_err, zxid_sso_issue_jwt */
zx_alloc_sprintf(struct zx_ctx * c,int * retlen,const char * f,...)350 char* zx_alloc_sprintf(struct zx_ctx* c, int* retlen, const char* f, ...) /* data is new memory */
351 {
352 char* ret;
353 va_list ap;
354 va_start(ap, f);
355 ret = zx_alloc_vasprintf(c, retlen, f, ap);
356 va_end(ap);
357 return ret;
358 }
359
360 /*(i) Construct zx_str given sprintf(3) format and grabbing memory from ZX memory allocator. */
361
362 /* Called by: */
zx_strf(struct zx_ctx * c,const char * f,...)363 struct zx_str* zx_strf(struct zx_ctx* c, const char* f, ...) /* data is new memory */
364 {
365 va_list ap;
366 int len;
367 char* s;
368 va_start(ap, f);
369 s = zx_alloc_vasprintf(c, &len, f, ap);
370 va_end(ap);
371 return zx_ref_len_str(c, len, s);
372 }
373
374 /* Called by: */
zx_attrf(struct zx_ctx * c,struct zx_elem_s * father,int tok,const char * f,...)375 struct zx_attr_s* zx_attrf(struct zx_ctx* c, struct zx_elem_s* father, int tok, const char* f, ...) /* data is new memory */
376 {
377 va_list ap;
378 int len;
379 char* s;
380 va_start(ap, f);
381 s = zx_alloc_vasprintf(c, &len, f, ap);
382 va_end(ap);
383 return zx_ref_len_attr(c, father, tok, len, s);
384 }
385
386 /*() Check if string ends in suffix */
387
388 /* Called by: */
zx_str_ends_in(struct zx_str * ss,int len,const char * suffix)389 int zx_str_ends_in(struct zx_str* ss, int len, const char* suffix)
390 {
391 return !memcmp(ss->s + ss->len - len, suffix, len);
392 }
393
394 /*() Compare two zx_strs; return -1 if a<b; 0 if a==b; 1 if a>b. */
395
zx_str_cmp(struct zx_str * a,struct zx_str * b)396 int zx_str_cmp(struct zx_str* a, struct zx_str* b)
397 {
398 int r;
399 if (!a || !a->s || !a->len)
400 return 1; /* missing parts: sort to end of list */
401 if (!b || !b->s || !b->len)
402 return -1;
403 r = memcmp(a->s, b->s, MIN(a->len, b->len));
404 if (r)
405 return r; /* decided by differing characters */
406 if (a->len == b->len)
407 return 0; /* equal in characters and length */
408 if (a->len < b->len)
409 return -1;
410 return 1;
411 }
412
413 /*() Add non-XML content to the kids list. These essentially appear as DATA items. */
414
415 /* Called by: test_ibm_cert_problem_enc_dec, x509_test, zx_new_str_elem, zxid_attach_sol1_usage_directive, zxid_az_soap x5, zxid_check_fed, zxid_issuer, zxid_mk_addr, zxid_mk_sa_attribute_ss x2, zxid_mk_subj, zxid_mk_transient_nid, zxid_new_epr, zxid_org_desc x4, zxid_parse_mni, zxid_ps_addent_invite x2, zxid_wsc_prep, zxid_wsc_prep_secmech x3, zxid_wsf_decor x4, zxsig_sign */
zx_add_content(struct zx_ctx * c,struct zx_elem_s * x,struct zx_str * cont)416 void zx_add_content(struct zx_ctx* c, struct zx_elem_s* x, struct zx_str* cont)
417 {
418 if (!cont || !x) {
419 ERR("Call to zx_add_content(c,%p,%p) with null values", x, cont);
420 return;
421 }
422 cont->tok = ZX_TOK_DATA;
423 cont->n = &x->kids->g;
424 x->kids = (struct zx_elem_s*)cont;
425 }
426
427 /*() Add kid to head of kids list. Usually you should add in schema order
428 * and in the end call zx_reverse_elem_lists() to make the list right order. */
429
430 /* Called by: zx_add_kid_after_sa_Issuer, zxid_add_fed_tok2epr, zxid_az_soap, zxid_di_query, zxid_idp_as_do, zxid_imreq, zxid_mk_a7n x3, zxid_mk_logout_resp, zxid_mk_mni_resp, zxid_mk_saml_resp, zxid_soap_call_hdr_body x2, zxid_soap_cgi_resp_body, zxid_sp_soap_dispatch, zxid_wsf_sign */
zx_add_kid(struct zx_elem_s * father,struct zx_elem_s * kid)431 struct zx_elem_s* zx_add_kid(struct zx_elem_s* father, struct zx_elem_s* kid)
432 {
433 if (!kid) {
434 ERR("kid argument missing father=%p", father);
435 return 0;
436 }
437 if (father) {
438 kid->g.n = &father->kids->g;
439 father->kids = kid;
440 }
441 return kid;
442 }
443
444 /*() Add kid before another elem. This assumes father is already in
445 * forward order, i.e. zx_reverse_elem_lists() was already called. */
446
447 /* Called by: zxid_add_fed_tok2epr, zxid_choose_sectok x2, zxid_ins_xacml_az_cd1_stmt x2, zxid_ins_xacml_az_stmt x2, zxid_sso_issue_a7n, zxid_wsc_prep_secmech */
zx_add_kid_before(struct zx_elem_s * father,int before,struct zx_elem_s * kid)448 struct zx_elem_s* zx_add_kid_before(struct zx_elem_s* father, int before, struct zx_elem_s* kid)
449 {
450 if (!father->kids) {
451 father->kids = kid;
452 return kid;
453 }
454 if (father->kids->g.tok == before) {
455 kid->g.n = &father->kids->g;
456 father->kids = kid;
457 return kid;
458 }
459 for (father = father->kids;
460 father->g.n && father->g.n->tok != before;
461 father = (struct zx_elem_s*)father->g.n) ;
462
463 kid->g.n = father->g.n;
464 father->g.n = &kid->g;
465 return kid;
466 }
467
468 /*() Add Signature right after sa:Issuer. This assumes father is
469 * already in forward order (i.e. zx_reverse_elem_lists() was already
470 * called. */
471
472 /* Called by: zxid_anoint_a7n, zxid_anoint_sso_resp, zxid_az_soap x2, zxid_idp_soap_dispatch x2, zxid_idp_sso, zxid_mk_art_deref, zxid_sp_mni_soap, zxid_sp_slo_soap, zxid_sp_soap_dispatch x6, zxid_ssos_anreq */
zx_add_kid_after_sa_Issuer(struct zx_elem_s * father,struct zx_elem_s * kid)473 struct zx_elem_s* zx_add_kid_after_sa_Issuer(struct zx_elem_s* father, struct zx_elem_s* kid)
474 {
475 if (father->kids->g.tok == zx_sa_Issuer_ELEM) {
476 father = father->kids;
477 kid->g.n = father->g.n;
478 father->g.n = &kid->g;
479 return kid;
480 }
481 ERR("No <sa:Issuer> found. Adding signature at list head. %d", father->kids->g.tok);
482 return zx_add_kid(father, kid);
483 }
484
485 /*() Replace kid element. */
486
487 /* Called by: zxid_soap_cgi_resp_body, zxid_wsp_decorate */
zx_replace_kid(struct zx_elem_s * father,struct zx_elem_s * kid)488 struct zx_elem_s* zx_replace_kid(struct zx_elem_s* father, struct zx_elem_s* kid)
489 {
490 if (!father->kids) {
491 father->kids = kid;
492 return kid;
493 }
494 if (father->kids->g.tok == kid->g.tok) {
495 kid->g.n = father->kids->g.n;
496 father->kids = kid;
497 return kid;
498 }
499 for (father = father->kids;
500 father->g.n && father->g.n->tok != kid->g.tok;
501 father = (struct zx_elem_s*)father->g.n) ;
502
503 kid->g.n = father->g.n->n;
504 father->g.n = &kid->g;
505 return kid;
506 }
507
508 /*() Construct new simple element from zx_str by referencing, not copying, it. */
509
510 /* Called by: */
zx_new_str_elem(struct zx_ctx * c,struct zx_elem_s * father,int tok,struct zx_str * ss)511 struct zx_elem_s* zx_new_str_elem(struct zx_ctx* c, struct zx_elem_s* father, int tok, struct zx_str* ss)
512 {
513 struct zx_elem_s* el;
514 el = ZX_ZALLOC(c, struct zx_elem_s);
515 el->g.tok = tok;
516 if (father) {
517 el->g.n = &father->kids->g;
518 father->kids = el;
519 }
520 zx_add_content(c, el, ss);
521 return el;
522 }
523
524 /*() Helper function for the zx_NEW_*() macros */
525
526 /* Called by: zxid_mk_xacml_simple_at */
zx_new_elem(struct zx_ctx * c,struct zx_elem_s * father,int tok)527 struct zx_elem_s* zx_new_elem(struct zx_ctx* c, struct zx_elem_s* father, int tok)
528 {
529 const struct zx_el_desc* ed;
530 struct zx_elem_s* el;
531 ed = zx_el_desc_lookup(tok);
532 if (ed) {
533 el = ZX_ALLOC(c, ed->siz);
534 ZERO(el, ed->siz);
535 } else {
536 INFO("Unknown element tok=%06x in tok=%06x", tok, father?father->g.tok:0);
537 el = ZX_ZALLOC(c, struct zx_elem_s);
538 tok = ZX_TOK_NOT_FOUND;
539 }
540 el->g.tok = tok;
541 if (father) {
542 el->g.n = &father->kids->g;
543 father->kids = el;
544 }
545 return el;
546 }
547
548 /*() Construct new simple element by referencing, not copying, raw string data of given length. */
549
550 /* Called by: */
zx_ref_len_elem(struct zx_ctx * c,struct zx_elem_s * father,int tok,int len,const char * s)551 struct zx_elem_s* zx_ref_len_elem(struct zx_ctx* c, struct zx_elem_s* father, int tok, int len, const char* s)
552 {
553 return zx_new_str_elem(c, father, tok, zx_ref_len_str(c, len, s));
554 }
555
556 /*() Construct new simple element by referencing, not copying, C string. */
557
558 /* Called by: */
zx_ref_elem(struct zx_ctx * c,struct zx_elem_s * father,int tok,const char * s)559 struct zx_elem_s* zx_ref_elem(struct zx_ctx* c, struct zx_elem_s* father, int tok, const char* s)
560 {
561 return zx_ref_len_elem(c, father, tok, strlen(s), s);
562 }
563
564 /* Called by: zx_dup_elem, zxid_mk_fault_zx_str x3 */
zx_dup_len_elem(struct zx_ctx * c,struct zx_elem_s * father,int tok,int len,const char * s)565 struct zx_elem_s* zx_dup_len_elem(struct zx_ctx* c, struct zx_elem_s* father, int tok, int len, const char* s)
566 {
567 return zx_new_str_elem(c, father, tok, zx_dup_len_str(c, len, s));
568 }
569
570 /* Called by: zxid_add_fed_tok2epr, zxid_mk_an_stmt, zxid_mk_fault x3, zxid_new_epr x3, zxid_set_epr_secmech x2 */
zx_dup_elem(struct zx_ctx * c,struct zx_elem_s * father,int tok,const char * s)571 struct zx_elem_s* zx_dup_elem(struct zx_ctx* c, struct zx_elem_s* father, int tok, const char* s)
572 {
573 return zx_dup_len_elem(c, father, tok, strlen(s), s);
574 }
575
576 /* ----------- F r e e ----------- */
577
578 /* Called by: zx_free_elem */
zx_free_attr(struct zx_ctx * c,struct zx_attr_s * aa,int free_strs)579 void zx_free_attr(struct zx_ctx* c, struct zx_attr_s* aa, int free_strs)
580 {
581 struct zx_attr_s* aan;
582 for (; aa; aa = aan) { /* attributes */
583 aan = (struct zx_attr_s*)aa->g.n;
584 if (free_strs && aa->name)
585 ZX_FREE(c, aa->name);
586 if (free_strs && aa->g.s)
587 ZX_FREE(c, aa->g.s);
588 ZX_FREE(c, aa);
589 }
590 }
591
592 /*() Free element and its attributes, child elements, and content.
593 * Depth first traversal of data structure to free it and its subelements. Simple
594 * strings are handled as a special case according to the free_strs flag. This
595 * is useful if the strings point to underlying data from the wire that was
596 * allocated differently. */
597
598 /* Called by: main, zx_free_elem, zxid_mk_mni, zxid_parse_meta, zxid_set_fault, zxid_set_tas3_status */
zx_free_elem(struct zx_ctx * c,struct zx_elem_s * x,int free_strs)599 void zx_free_elem(struct zx_ctx* c, struct zx_elem_s* x, int free_strs)
600 {
601 struct zx_elem_s* ae;
602 struct zx_elem_s* aen;
603
604 if (x->g.tok == ZX_TOK_NOT_FOUND && free_strs) {
605 ae = x;
606 if (ae->g.s)
607 ZX_FREE(c, ae->g.s);
608 }
609 zx_free_attr(c, x->attr, free_strs);
610
611 for (ae = x->kids; ae; ae = aen) { /* elements */
612 aen = (struct zx_elem_s*)ae->g.n;
613 switch (ae->g.tok) {
614 case ZX_TOK_DATA:
615 if (free_strs)
616 zx_str_free(c, &ae->g);
617 else
618 ZX_FREE(c, ae);
619 break;
620 default:
621 zx_free_elem(c, ae, free_strs);
622 //zx_FREE_elem(c, ae, free_strs);
623 }
624 }
625 ZX_FREE(c, x);
626 }
627
628 #ifdef ZX_ENA_AUX
629
630 /* *** clone code has not been updated since great namespace reform */
631
632 /* Called by: */
zx_dup_attr(struct zx_ctx * c,struct zx_str * attr)633 void zx_dup_attr(struct zx_ctx* c, struct zx_str* attr)
634 {
635 char* p;
636 for (; attr; attr = (struct zx_str*)attr->g.n)
637 if (attr->s) {
638 p = ZX_ALLOC(c, attr->len);
639 memcpy(p, attr->s, attr->len);
640 attr->s = p;
641 }
642 }
643
644 /* Called by: */
zx_clone_attr(struct zx_ctx * c,struct zx_str * attr)645 struct zx_str* zx_clone_attr(struct zx_ctx* c, struct zx_str* attr)
646 {
647 struct zx_str* ret;
648 struct zx_str* attrnn;
649 struct zx_str* attrn;
650 char* p;
651 for (attrnn = 0; attr; attr = (struct zx_str*)attr->g.n) {
652 ZX_DUPALLOC(c, struct zx_str, attrn, attr);
653 if (!attrnn)
654 ret = attrn;
655 else
656 attrnn->g.n = &attrn->g;
657 attrnn = attrn;
658 if (attrn->s) {
659 p = ZX_ALLOC(c, attrn->len);
660 memcpy(p, attrn->s, attrn->len);
661 attrn->s = p;
662 }
663 }
664 return ret;
665 }
666
667 /* Called by: TXDEEP_CLONE_ELNAME */
zx_clone_elem_common(struct zx_ctx * c,struct zx_elem_s * x,int size,int dup_strs)668 struct zx_elem_s* zx_clone_elem_common(struct zx_ctx* c, struct zx_elem_s* x, int size, int dup_strs)
669 {
670 struct zx_attr_s* aa;
671 struct zx_elem_s* ae;
672 struct zx_attr_s* aan;
673 struct zx_elem_s* aen;
674 struct zx_attr_s* aann;
675 struct zx_elem_s* aenn;
676 char* p;
677
678 if (x->g.tok == ZX_TOK_NOT_FOUND) {
679 ae = (struct zx_elem_s*)x;
680 ZX_DUPALLOC(c, struct zx_elem_s, aen, ae);
681 if (dup_strs) {
682 aen->name = ZX_ALLOC(c, ae->name_len);
683 memcpy(aen->name, ae->name, ae->name_len);
684 }
685 x = &aen->gg;
686 } else {
687 struct zx_elem_s* xx = (struct zx_elem_s*)ZX_ALLOC(c, size);
688 memcpy(xx, x, size);
689 x = xx;
690 }
691
692 /* *** deal with xmlns specifications in exc c14n way */
693
694 for (aann = 0, aa = x->attr; aa; aa = (struct zx_attr_s*)aa->ss.g.n) { /* unknown attributes */
695 ZX_DUPALLOC(c, struct zx_attr_s, aan, aa);
696 if (!aann)
697 x->any_attr = aan;
698 else
699 aann->ss.g.n = &aan->ss.g;
700 aann = aan;
701
702 if (dup_strs && aan->name) {
703 p = ZX_ALLOC(c, aan->name_len);
704 memcpy(p, aan->name, aan->name_len);
705 aan->name = p;
706 }
707 if (dup_strs && aan->ss.s) {
708 p = ZX_ALLOC(c, aan->ss.len);
709 memcpy(p, aan->ss.s, aan->ss.len);
710 aan->ss.s = p;
711 }
712 }
713
714 for (aenn = 0, ae = x->kids; ae; ae = (struct zx_elem_s*)ae->gg.g.n) { /* unknown elements */
715 switch (ae->g.tok) {
716 case ZX_TOK_DATA:
717 ZX_DUPALLOC(c, struct zx_str, aen, ae);
718 if (aen->g.s) {
719 p = ZX_ALLOC(c, aen->g.len);
720 memcpy(p, aen->g.s, aen->g.len);
721 aen->s = p;
722 }
723 break;
724 default:
725 aen = (struct zx_elem_s*)zx_DEEP_CLONE_elem(c, &ae->gg, dup_strs);
726 }
727 if (!aenn)
728 x->kids = aen;
729 else
730 aenn->gg.g.n = &aen->gg.g;
731 aenn = aen;
732 }
733 return x;
734 }
735
736 /* Called by: TXDUP_STRS_ELNAME */
zx_dup_strs_common(struct zx_ctx * c,struct zx_elem_s * x)737 void zx_dup_strs_common(struct zx_ctx* c, struct zx_elem_s* x)
738 {
739 struct zx_attr_s* aa;
740 struct zx_elem_s* ae;
741 char* p;
742
743 if (x->g.tok == ZX_TOK_NOT_FOUND) {
744 ae = (struct zx_elem_s*)x;
745 p = ZX_ALLOC(c, ae->name_len);
746 memcpy(p, ae->name, ae->name_len);
747 ae->name = p;
748 }
749
750 /* *** deal with xmlns specifications in exc c14n way */
751
752 for (aa = x->attr; aa; aa = (struct zx_attr_s*)aa->ss.g.n) { /* unknown attributes */
753 if (aa->name) {
754 p = ZX_ALLOC(c, aa->name_len);
755 memcpy(p, aa->name, aa->name_len);
756 aa->name = p;
757 }
758 if (aa->ss.s) {
759 p = ZX_ALLOC(c, aa->ss.len);
760 memcpy(p, aa->ss.s, aa->ss.len);
761 aa->ss.s = p;
762 }
763 }
764
765 for (ae = x->kids; ae; ae = (struct zx_elem_s*)ae->gg.g.n) /* unknown elements */
766 switch (ae->g.tok) {
767 case ZX_TOK_DATA:
768 if (ae->g.s) {
769 p = ZX_ALLOC(c, ae->g.len);
770 memcpy(p, ae->g.s, ae->g.len);
771 ss->s = p;
772 }
773 break;
774 default:
775 zx_DUP_STRS_elem(c, &ae->gg);
776 }
777 }
778
zx_walk_so_unknown_attributes(struct zx_ctx * c,struct zx_elem_s * x,void * ctx,int (* callback)(struct zx_node_s * node,void * ctx))779 int zx_walk_so_unknown_attributes(struct zx_ctx* c, struct zx_elem_s* x, void* ctx, int (*callback)(struct zx_node_s* node, void* ctx))
780 {
781 struct zx_attr_s* aa;
782 int ret;
783
784 for (aa = x->attr; aa; aa = (struct zx_attr_s*)aa->ss.g.n) { /* unknown attributes */
785 ret = callback(&aa->ss.g, ctx);
786 if (ret)
787 return ret;
788 }
789 return 0;
790 }
791
zx_walk_so_unknown_elems_and_content(struct zx_ctx * c,struct zx_elem_s * x,void * ctx,int (* callback)(struct zx_node_s * node,void * ctx))792 int zx_walk_so_unknown_elems_and_content(struct zx_ctx* c, struct zx_elem_s* x, void* ctx, int (*callback)(struct zx_node_s* node, void* ctx))
793 {
794 struct zx_elem_s* ae;
795 int ret;
796
797 for (ae = x->kids; ae; ae = (struct zx_elem_s*)ae->gg.g.n) { /* unknown elements */
798 switch (ae->g.tok) {
799 case ZX_TOK_DATA:
800 ret = callback(ae, ctx);
801 break;
802 default:
803 ret = zx_WALK_SO_elem(c, ae, ctx, callback);
804 }
805 if (ret)
806 return ret;
807 }
808 return 0;
809 }
810
811 /* Called by: */
zx_deep_clone_elems(struct zx_ctx * c,struct zx_elem_s * x,int dup_strs)812 struct zx_elem_s* zx_deep_clone_elems(struct zx_ctx* c, struct zx_elem_s* x, int dup_strs)
813 {
814 struct zx_elem_s* se;
815 struct zx_elem_s* sen;
816 struct zx_elem_s* senn;
817
818 for (senn = 0, se = x; se; se = (struct zx_elem_s*)se->g.n) {
819 sen = zx_DEEP_CLONE_elem(c, se, dup_strs);
820 if (!senn)
821 x = sen;
822 else
823 senn->g.n = &sen->g;
824 senn = sen;
825 }
826 return x;
827 }
828
zx_walk_so_elems(struct zx_ctx * c,struct zx_elem_s * se,void * ctx,int (* callback)(struct zx_node_s * node,void * ctx))829 int zx_walk_so_elems(struct zx_ctx* c, struct zx_elem_s* se, void* ctx, int (*callback)(struct zx_node_s* node, void* ctx))
830 {
831 int ret;
832
833 for (; se; se = (struct zx_elem_s*)se->g.n) {
834 ret = zx_WALK_SO_elem(c, se, ctx, callback);
835 if (ret)
836 return ret;
837 }
838 return 0;
839 }
840
841 /* Called by: */
zx_dup_strs_elems(struct zx_ctx * c,struct zx_elem_s * se)842 void zx_dup_strs_elems(struct zx_ctx* c, struct zx_elem_s* se)
843 {
844 for (; se; se = (struct zx_elem_s*)se->g.n)
845 zx_DUP_STRS_elem(c, se);
846 }
847
848 #endif /* end ZX_ENA_AUX */
849
850 /* EOF -- zxlib.c */
851