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