1 /* zxidmkwsf.c  -  Handwritten nitty-gritty functions for constructing various elems
2  * Copyright (c) 2010-2011 Sampo Kellomaki <sampo@iki.fi>, All Rights Reserved.
3  * Copyright (c) 2007-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: zxidmkwsf.c,v 1.12 2009-11-24 23:53:40 sampo Exp $
10  *
11  * 12.1.2007, created --Sampo
12  * 7.10.2008, added documentation --Sampo
13  * 15.11.2009, added ID-WSF <lu:Status> --Sampo
14  * 25.5.2010, added SOAP fault, tas3:Status, error formatting --Sampo
15  */
16 
17 #include "platform.h"
18 #include "errmac.h"
19 #include "zxid.h"
20 #include "zxidconf.h"
21 #include "saml2.h"
22 #include "wsf.h"
23 #include "c/zx-const.h"
24 #include "c/zx-ns.h"
25 #include "c/zx-data.h"
26 
27 /* *** What correct API should look like? This is still in flux
28  * and the initial goal is just to make single query for single
29  * service. All other complicated options and multi service queries
30  * will come in later releases. */
31 
32 /*() Create ID-WSF protocol <lu:Status> element, given various levels of error input.
33  *
34  * sc1:: First level status code
35  * sc2:: Second level status code, if any
36  * msg:: First level status message
37  * ref:: First level Status/@ref. Ref is used to point to culprit XML element, if any.
38  * returns:: lu:Status data structure with fields populated.
39  *
40  * See also: zxid_mk_fault() */
41 
42 /* Called by:  covimp_test, zxid_di_query x2, zxid_idp_as_do x3, zxid_idp_map_nid2uid, zxid_imreq x6, zxid_mk_fault, zxid_mk_lu_Status, zxid_mk_tas3_status, zxid_ps_addent_invite x2, zxid_ps_resolv_id */
zxid_mk_lu_Status(zxid_conf * cf,struct zx_elem_s * father,const char * sc1,const char * sc2,const char * msg,const char * ref)43 struct zx_lu_Status_s* zxid_mk_lu_Status(zxid_conf* cf, struct zx_elem_s* father, const char* sc1, const char* sc2, const char* msg, const char* ref)
44 {
45   struct zx_lu_Status_s* st = zx_NEW_lu_Status(cf->ctx,father);
46   st->code      = zx_dup_attr(cf->ctx, &st->gg, zx_code_ATTR, STRNULLCHKQ(sc1));
47   if (msg)
48     st->comment = zx_dup_attr(cf->ctx, &st->gg, zx_comment_ATTR, msg);
49   if (ref)
50     st->ref     = zx_dup_attr(cf->ctx, &st->gg, zx_ref_ATTR, ref);
51   if (sc2)
52     st->Status  = zxid_mk_lu_Status(cf, &st->gg, sc2, 0, 0, 0);
53   return st;
54 }
55 
56 /*() Create TAS3 application level Status (error) header. */
57 
58 /* Called by:  covimp_test, zxid_get_fault_status */
zxid_mk_tas3_status(zxid_conf * cf,struct zx_elem_s * father,const char * ctlpt,const char * sc1,const char * sc2,const char * msg,const char * ref)59 zxid_tas3_status* zxid_mk_tas3_status(zxid_conf* cf, struct zx_elem_s* father, const char* ctlpt, const char* sc1, const char* sc2, const char* msg, const char* ref)
60 {
61   zxid_tas3_status* st = zx_NEW_tas3_Status(cf->ctx, father);
62   st->mustUnderstand = zx_ref_attr(cf->ctx, &st->gg, zx_e_mustUnderstand_ATTR, "0");
63   if (ref)
64     st->ref          = zx_dup_attr(cf->ctx, &st->gg, zx_ref_ATTR, ref);
65   if (ctlpt)
66     st->ctlpt        = zx_dup_attr(cf->ctx, &st->gg, zx_ctlpt_ATTR, ctlpt);
67   if (msg)
68     st->comment      = zx_dup_attr(cf->ctx, &st->gg, zx_comment_ATTR, msg);
69   st->code           = zx_dup_attr(cf->ctx, &st->gg, zx_code_ATTR, STRNULLCHKQ(sc1));
70   if (sc2)
71     st->Status       = zxid_mk_lu_Status(cf, &st->gg, sc2, 0, 0, 0);
72   return st;
73 }
74 
75 /*() Create SOAP Fault element (see Table 2 of [SOAPBind2], pp.12-13)
76  *
77  * cf:: Configuration object
78  * father:: Optional father XML element
79  * fa:: Optional fault actor, such as one of the TAS3 control points (ctlpt)
80  * fc:: Fault code. Should be "e:Client" or "e:Server".
81  * fs:: Fault string. Human readable string explanation of the fault.
82  * sc1:: First level status code (to be placed inside <detail> element)
83  * sc2:: Second level status code, if any
84  * msg:: First level status message
85  * ref:: First level Status/@ref. Ref is used to point to culprit XML element, if any.
86  * returns:: Fault data structure with fields populated.
87  *
88  * See also: zxid_mk_lu_Status()
89  */
90 
91 /* Called by:  covimp_test, zxid_call, zxid_query_ctlpt_pdp x2, zxid_timestamp_chk x2, zxid_validate_cond x3, zxid_wsc_call, zxid_wsc_valid_re_env x11, zxid_wsf_validate_a7n x6, zxid_wsp_validate x2, zxid_wsp_validate_env x11 */
zxid_mk_fault(zxid_conf * cf,struct zx_elem_s * father,const char * fa,const char * fc,const char * fs,const char * sc1,const char * sc2,const char * msg,const char * ref)92 zxid_fault* zxid_mk_fault(zxid_conf* cf, struct zx_elem_s* father, const char* fa, const char* fc, const char* fs, const char* sc1, const char* sc2, const char* msg, const char* ref)
93 {
94   zxid_fault* flt = zx_NEW_e_Fault(cf->ctx, father);
95   if (sc1) {
96     flt->detail = zx_NEW_e_detail(cf->ctx, &flt->gg);
97     flt->detail->Status = zxid_mk_lu_Status(cf, &flt->detail->gg, sc1, sc2, msg, ref);
98   }
99   if (fa)
100     flt->faultactor  = zx_dup_elem(cf->ctx, &flt->gg, zx_e_faultactor_ELEM, fa);
101   flt->faultstring   = zx_dup_elem(cf->ctx, &flt->gg, zx_e_faultstring_ELEM, fs?fs:"Unknown");
102   flt->faultcode     = zx_dup_elem(cf->ctx, &flt->gg, zx_e_faultcode_ELEM,fc?fc:"e:Client");
103   return flt;
104 }
105 
106 /*() Construct SOAP Fault data structure from zx_str arguments. */
107 
108 /* Called by:  zxid_wsc_call */
zxid_mk_fault_zx_str(zxid_conf * cf,struct zx_elem_s * father,struct zx_str * fa,struct zx_str * fc,struct zx_str * fs)109 zxid_fault* zxid_mk_fault_zx_str(zxid_conf* cf, struct zx_elem_s* father, struct zx_str* fa, struct zx_str* fc, struct zx_str* fs)
110 {
111   zxid_fault* flt = zx_NEW_e_Fault(cf->ctx, father);
112   if (fa)
113     flt->faultactor  = zx_dup_len_elem(cf->ctx, &flt->gg, zx_e_faultactor_ELEM, fa->len, fa->s);
114   flt->faultstring   = zx_dup_len_elem(cf->ctx, &flt->gg, zx_e_faultstring_ELEM, fs?fs->len:sizeof("Unknown")-1, fs?fs->s:"Unknown");
115   flt->faultcode     = zx_dup_len_elem(cf->ctx, &flt->gg, zx_e_faultcode_ELEM, fc?fc->len:sizeof("e:Client")-1, fc?fc->s:"e:Client");
116   return flt;
117 }
118 
119 /*() Set current SOAP Fault of the session. If current fault is set, the zxid_wsp_decorate()
120  * function will generate a SOAP Fault response instead of normal SOAP response. If
121  * you wish to return application response in situation where fault has been
122  * detected, you can use this function to reset the current fault to null. */
123 
124 /* Called by:  zxid_call, zxid_query_ctlpt_pdp x2, zxid_timestamp_chk x2, zxid_validate_cond x3, zxid_wsc_call x2, zxid_wsc_valid_re_env x12, zxid_wsf_validate_a7n x6, zxid_wsp_validate x2, zxid_wsp_validate_env x12 */
zxid_set_fault(zxid_conf * cf,zxid_ses * ses,zxid_fault * flt)125 void zxid_set_fault(zxid_conf* cf, zxid_ses* ses, zxid_fault* flt) {
126   if (ses->curflt) /* Free the previous fault */
127     zx_free_elem(cf->ctx, &ses->curflt->gg, 1);
128   ses->curflt = flt;
129 }
130 
131 /*() Read current SOAP Fault of the session. NULL return means that there was no fault. */
132 
133 /* Called by:  covimp_test */
zxid_get_fault(zxid_conf * cf,zxid_ses * ses)134 zxid_fault* zxid_get_fault(zxid_conf* cf, zxid_ses* ses) {
135   return ses->curflt;
136 }
137 
138 /*() Return first level status code from SOAP Fault.
139  * Typically called as  sc1 = zxid_get_tas3_fault_sc1(cf, zxid_get_fault(cf, ses)); */
140 
141 /* Called by:  covimp_test x2, zxid_get_fault_status */
zxid_get_tas3_fault_sc1(zxid_conf * cf,zxid_fault * flt)142 char* zxid_get_tas3_fault_sc1(zxid_conf* cf, zxid_fault* flt) {
143   if (!flt || !ZX_SIMPLE_ELEM_CHK(flt->faultcode))
144     return 0;
145   return zx_str_to_c(cf->ctx, ZX_GET_CONTENT(flt->faultcode));
146 }
147 
148 /*() Return second level status code from SOAP Fault.
149  * Typically called as  sc2 = zxid_get_tas3_fault_sc2(cf, zxid_get_fault(cf, ses)); */
150 
151 /* Called by:  covimp_test x2 */
zxid_get_tas3_fault_sc2(zxid_conf * cf,zxid_fault * flt)152 char* zxid_get_tas3_fault_sc2(zxid_conf* cf, zxid_fault* flt) {
153   if (!flt || !flt->detail || !flt->detail->Status || !flt->detail->Status->code || !flt->detail->Status->code->g.s)
154     return 0;
155   return zx_str_to_c(cf->ctx, &flt->detail->Status->code->g);
156 }
157 
158 /*() Return comment field from SOAP Fault.
159  * Typically called as  c = zxid_get_tas3_fault_comment(cf, zxid_get_fault(cf, ses)); */
160 
161 /* Called by:  covimp_test x2, zxid_get_fault_status */
zxid_get_tas3_fault_comment(zxid_conf * cf,zxid_fault * flt)162 char* zxid_get_tas3_fault_comment(zxid_conf* cf, zxid_fault* flt) {
163   if (!flt || !ZX_SIMPLE_ELEM_CHK(flt->faultstring))
164     return 0;
165   return zx_str_to_c(cf->ctx, ZX_GET_CONTENT(flt->faultstring));
166 }
167 
168 /*() Return reference field from SOAP Fault.
169  * Typically called as  ref = zxid_get_tas3_fault_ref(cf, zxid_get_fault(cf, ses));
170  *
171  * Reference field may indicate which XML element is causing the fault.
172  * Its value correspons to id XML attribute of the faulting element. */
173 
174 /* Called by:  covimp_test x2 */
zxid_get_tas3_fault_ref(zxid_conf * cf,zxid_fault * flt)175 char* zxid_get_tas3_fault_ref(zxid_conf* cf, zxid_fault* flt) {
176   if (!flt || !flt->detail || !flt->detail->Status || !flt->detail->Status->ref || !flt->detail->Status->ref->g.s)
177     return 0;
178   return zx_str_to_c(cf->ctx, &flt->detail->Status->ref->g);
179 }
180 
181 /*() Return actor field from SOAP Fault.
182  * Typically called as  act = zxid_get_tas3_fault_actor(cf, zxid_get_fault(cf, ses));
183  *
184  * Actor field may indicate whether the detected error is attributable to Server or Client. */
185 
186 /* Called by:  covimp_test x2, zxid_get_fault_status */
zxid_get_tas3_fault_actor(zxid_conf * cf,zxid_fault * flt)187 char* zxid_get_tas3_fault_actor(zxid_conf* cf, zxid_fault* flt) {
188   if (!flt || !ZX_SIMPLE_ELEM_CHK(flt->faultactor))
189     return 0;
190   return zx_str_to_c(cf->ctx, ZX_GET_CONTENT(flt->faultactor));
191 }
192 
193 /*() Extract TAS3 status from SOAP Fault */
194 
195 /* Called by: */
zxid_get_fault_status(zxid_conf * cf,zxid_fault * flt)196 zxid_tas3_status* zxid_get_fault_status(zxid_conf* cf, zxid_fault* flt) {
197   zxid_tas3_status* st;
198   if (!flt || !flt->detail || !flt->detail->Status)
199     return 0;
200   st = zxid_mk_tas3_status(cf, 0,
201 			   zxid_get_tas3_fault_actor(cf, flt),
202 			   zxid_get_tas3_fault_sc1(cf, flt),
203 			   0,
204 			   zxid_get_tas3_fault_comment(cf, flt),
205 			   0);
206   st->Status = flt->detail->Status;
207   return st;
208 }
209 
210 /*() Set current TAS3 Status of the session. If current Status is set,
211  * the zxid_wsp_decorate() function will generate a TAS3 status
212  * header. */
213 
214 /* Called by:  zxid_wsc_valid_re_env, zxid_wsp_validate_env */
zxid_set_tas3_status(zxid_conf * cf,zxid_ses * ses,zxid_tas3_status * status)215 void zxid_set_tas3_status(zxid_conf* cf, zxid_ses* ses, zxid_tas3_status* status) {
216   D("curstatus=%p status=%p", ses->curstatus, status);
217   if (ses->curstatus) /* Free the previous fault */
218     zx_free_elem(cf->ctx, &ses->curstatus->gg, 0);
219   ses->curstatus = status;
220 }
221 
222 /*() Read current fault of the session. NULL return means that there was no fault. */
223 
224 /* Called by:  covimp_test */
zxid_get_tas3_status(zxid_conf * cf,zxid_ses * ses)225 zxid_tas3_status* zxid_get_tas3_status(zxid_conf* cf, zxid_ses* ses) {
226   return ses->curstatus;
227 }
228 
229 /*() Return first level status code from TAS3 status.
230  * Typically called as  sc1 = zxid_get_tas3_status_sc1(cf, zxid_get_tas3_status(cf, ses)); */
231 
232 /* Called by:  covimp_test x2 */
zxid_get_tas3_status_sc1(zxid_conf * cf,zxid_tas3_status * st)233 char* zxid_get_tas3_status_sc1(zxid_conf* cf, zxid_tas3_status* st) {
234   if (!st || !st->code || !st->code->g.s)
235     return 0;
236   return zx_str_to_c(cf->ctx, &st->code->g);
237 }
238 
239 /*() Return second level status code from TAS3 status.
240  * Typically called as  sc2 = zxid_get_tas3_status_sc2(cf, zxid_get_tas3_status(cf, ses)); */
241 
242 /* Called by:  covimp_test x2 */
zxid_get_tas3_status_sc2(zxid_conf * cf,zxid_tas3_status * st)243 char* zxid_get_tas3_status_sc2(zxid_conf* cf, zxid_tas3_status* st) {
244   if (!st || !st->Status || !st->Status->code || !st->Status->code->g.s)
245     return 0;
246   return zx_str_to_c(cf->ctx, &st->Status->code->g);
247 }
248 
249 /*() Return comment from TAS3 status.
250  * Typically called as  c = zxid_get_tas3_status_comment(cf, zxid_get_tas3_status(cf, ses)); */
251 
252 /* Called by:  covimp_test x2 */
zxid_get_tas3_status_comment(zxid_conf * cf,zxid_tas3_status * st)253 char* zxid_get_tas3_status_comment(zxid_conf* cf, zxid_tas3_status* st) {
254   if (!st || !st->comment || !st->comment->g.s)
255     return 0;
256   return zx_str_to_c(cf->ctx, &st->comment->g);
257 }
258 
259 /*() Return reference field from TAS3 status.
260  * Typically called as  ref = zxid_get_tas3_status_ref(cf, zxid_get_tas3_status(cf, ses));
261  *
262  * Reference field may indicate which XML element is causing the fault.
263  * Its value correspons to id XML attribute of the faulting element. */
264 
265 /* Called by:  covimp_test x2 */
zxid_get_tas3_status_ref(zxid_conf * cf,zxid_tas3_status * st)266 char* zxid_get_tas3_status_ref(zxid_conf* cf, zxid_tas3_status* st) {
267   if (!st || !st->ref || !st->ref->g.s)
268     return 0;
269   return zx_str_to_c(cf->ctx, &st->ref->g);
270 }
271 
272 /*() Return control point from TAS3 status.
273  * Typically called as  cp = zxid_get_tas3_status_ctlpt(cf, zxid_get_tas3_status(cf, ses));
274  *
275  * Control points are Policy Enforcement Points (PEPs) defined in TAS3
276  * architecture, e.g. "urn:tas3:ctlpt:pep:rq:out", "urn:tas3:ctlpt:pep:rq:in",
277  * "urn:tas3:ctlpt:pep:rs:out", or "urn:tas3:ctlpt:pep:rs:in". */
278 
279 /* Called by:  covimp_test x2 */
zxid_get_tas3_status_ctlpt(zxid_conf * cf,zxid_tas3_status * st)280 char* zxid_get_tas3_status_ctlpt(zxid_conf* cf, zxid_tas3_status* st) {
281   if (!st || !st->ctlpt || !st->ctlpt->g.s)
282     return 0;
283   return zx_str_to_c(cf->ctx, &st->ctlpt->g);
284 }
285 
286 /*() Low level constructor for discovery <di:RequestedService>. */
287 
288 /* Called by:  zxid_mk_di_query */
zxid_mk_di_req_svc(zxid_conf * cf,struct zx_elem_s * father,int req_id,const char * svc_type,const char * url,const char * di_opt,const char * action)289 static struct zx_di_RequestedService_s* zxid_mk_di_req_svc(zxid_conf* cf, struct zx_elem_s* father, int req_id, const char* svc_type, const char* url, const char* di_opt, const char* action)
290 {
291   struct zx_di_RequestedService_s* rs = zx_NEW_di_RequestedService(cf->ctx, father);
292   if (svc_type)
293     rs->ServiceType = zx_ref_elem(cf->ctx, &rs->gg, zx_di_ServiceType_ELEM, svc_type);
294   if (url)
295     rs->ProviderID = zx_ref_elem(cf->ctx, &rs->gg, zx_di_ProviderID_ELEM, url);
296   if (di_opt) {
297     rs->Options = zx_NEW_di_Options(cf->ctx, &rs->gg);
298     /* N.B: We adopt here a simplification that there can only be one option, but it
299      * can be fully generic URI, including a query string. If it is desireable to
300      * support additional options, dollar ($) could be used as a separator. */
301     rs->Options->Option = zx_ref_elem(cf->ctx, &rs->Options->gg, zx_di_Option_ELEM, di_opt);
302   }
303 #if 0
304   rs->reqID = zx_strf(cf->ctx, "RS%x", req_id);
305   rs->resultType = zx_ref_str(cf->ctx, "all");  /* OPTIONAL: "best", "only-one" */
306   rs->SecurityMechID = zx_ref_elem(cf->ctx, &rs->gg, zx_di_SecurityMechID_ELEM, WSF20_SEC_MECH_TLS_BEARER);
307   rs->SecurityMechID = zx_ref_elem(cf->ctx, &rs->gg, zx_di_SecurityMechID_ELEM, WSF20_SEC_MECH_TLS_SAML2);
308 #endif
309   rs->Framework = zx_NEW_di_Framework(cf->ctx, &rs->gg);
310   rs->Framework->version = zx_ref_attr(cf->ctx, &rs->Framework->gg, zx_version_ATTR, "2.0");  /* Request specific framework, omit=any */
311   if (action)
312     rs->Action = zx_ref_elem(cf->ctx, &rs->gg, zx_di_Action_ELEM, action);
313   zx_reverse_elem_lists(&rs->gg);
314   return rs;
315 }
316 
317 /*() Low level constructor for discovery <di:Query>. */
318 
319 /* Called by:  main x2, zxid_get_epr */
zxid_mk_di_query(zxid_conf * cf,struct zx_elem_s * father,const char * svc_type,const char * url,const char * di_opt,const char * action)320 struct zx_di_Query_s* zxid_mk_di_query(zxid_conf* cf, struct zx_elem_s* father, const char* svc_type, const char* url, const char* di_opt, const char* action)
321 {
322   struct zx_di_Query_s* q = zx_NEW_di_Query(cf->ctx, father);
323   q->RequestedService = zxid_mk_di_req_svc(cf, &q->gg, 1, svc_type, url, di_opt, action);
324   return q;
325 }
326 
327 /*() Low level constructor for WSA <Address>. */
328 
329 /* Called by:  zxid_wsc_prep, zxid_wsf_decor */
zxid_mk_addr(zxid_conf * cf,struct zx_elem_s * father,struct zx_str * url)330 struct zx_a_Address_s* zxid_mk_addr(zxid_conf* cf, struct zx_elem_s* father, struct zx_str* url)
331 {
332   struct zx_a_Address_s* addr = zx_NEW_a_Address(cf->ctx, father);
333   zx_add_content(cf->ctx, &addr->gg, url);
334   return addr;
335 }
336 
337 /* --------------- DAP: Select and QueryItem -------------- */
338 
339 /*() Low level constructor for <dap:Select>. */
340 
341 /* Called by:  covimp_test x2, main x4 */
zxid_mk_dap_select(zxid_conf * cf,struct zx_elem_s * father,char * dn,char * filter,char * attributes,int derefaliases,int scope,int sizelimit,int timelimit,int typesonly)342 struct zx_dap_Select_s* zxid_mk_dap_select(zxid_conf* cf, struct zx_elem_s* father, char* dn, char* filter, char* attributes, int derefaliases, int scope, int sizelimit, int timelimit, int typesonly)
343 {
344   struct zx_dap_Select_s* sel = zx_NEW_dap_Select(cf->ctx, father);
345   if (dn)           sel->dn = zx_ref_elem(cf->ctx, &sel->gg, zx_dap_dn_ELEM, dn);
346   if (filter)       sel->filter = zx_ref_elem(cf->ctx, &sel->gg, zx_dap_filter_ELEM, filter);
347   if (attributes)   sel->attributes = zx_ref_attr(cf->ctx, &sel->gg, zx_attributes_ATTR, attributes);
348   if (derefaliases) sel->derefaliases = zx_attrf(cf->ctx, &sel->gg, zx_derefaliases_ATTR, "%d", derefaliases);
349   if (scope)        sel->scope = zx_attrf(cf->ctx, &sel->gg, zx_scope_ATTR, "%d", scope);
350   if (sizelimit)    sel->sizelimit = zx_attrf(cf->ctx, &sel->gg, zx_sizelimit_ATTR, "%d", sizelimit);
351   if (timelimit)    sel->timelimit = zx_attrf(cf->ctx, &sel->gg, zx_timelimit_ATTR, "%d", timelimit);
352   if (typesonly)    sel->typesonly = zx_ref_attr(cf->ctx, &sel->gg, zx_typesonly_ATTR, XML_TRUE);
353   return sel;
354 }
355 
356 /*() Low level constructor for <dap:QueryItem>. */
357 
358 /* Called by:  covimp_test, main x3 */
zxid_mk_dap_query_item(zxid_conf * cf,struct zx_elem_s * father,struct zx_dap_Select_s * sel,char * objtype,char * predef,char * sort,char * changed_since,int incl_common_attr,int offset,int count,char * setreq,char * setid,char * contingent_itemidref)359 struct zx_dap_QueryItem_s* zxid_mk_dap_query_item(zxid_conf* cf, struct zx_elem_s* father, struct zx_dap_Select_s* sel, char* objtype, char* predef, char* sort, char* changed_since, int incl_common_attr, int offset, int count, char* setreq, char* setid, char* contingent_itemidref)
360 {
361   struct zx_dap_QueryItem_s* qi = zx_NEW_dap_QueryItem(cf->ctx, father);
362   qi->Select = sel;
363   if (objtype)       qi->objectType = zx_ref_attr(cf->ctx, &qi->gg, zx_objectType_ATTR, objtype);
364   if (changed_since) qi->changedSince = zx_ref_attr(cf->ctx, &qi->gg, zx_changedSince_ATTR, changed_since);
365   if (predef)        qi->predefined = zx_ref_attr(cf->ctx, &qi->gg, zx_predefined_ATTR, predef);
366   if (sort)          qi->Sort = zx_ref_elem(cf->ctx, &qi->gg, zx_dap_Sort_ELEM, sort);
367 
368 #if 0
369   /* ID-DAP specification only allows ChangeFormat == "currentElements"
370    * and in fact recommends omitting it altogether. */
371   if (changed_elems)
372     qi->ChangeFormat = zx_ref_elem(cf->ctx, &qi->gg, zx_dap_ChangeFormat_ELEM, "changedElements");
373   if (curr_elems) {
374     if (qi->ChangeFormat)
375       qi->ChangeFormat->g.n = (struct zx_node_s*)zx_ref_elem(cf->ctx, &qi->gg, zx_dap_ChangeFormat_ELEM, "currentElements");
376     else
377       qi->ChangeFormat = zx_ref_elem(cf->ctx, &qi->gg, zx_dap_ChangeFormat_ELEM, "currentElements");
378   }
379 #endif
380 
381   if (incl_common_attr) qi->includeCommonAttributes = zx_ref_attr(cf->ctx, &qi->gg, zx_includeCommonAttributes_ATTR, XML_TRUE);
382   if (offset)           qi->offset = zx_attrf(cf->ctx, &qi->gg, zx_offset_ATTR, "%d", offset);
383   if (count)            qi->count  = zx_attrf(cf->ctx, &qi->gg, zx_count_ATTR,  "%d", count);
384 
385   if (setreq) qi->setReq = zx_ref_attr(cf->ctx, &qi->gg, zx_setReq_ATTR, setreq);  /* Request new set */
386   if (setid)  qi->setID  = zx_ref_attr(cf->ctx, &qi->gg, zx_setID_ATTR, setid);    /* Continue to use existing set */
387 
388   qi->itemID = zxid_mk_id_attr(cf, &qi->gg, zx_itemID_ATTR, "qi", ZXID_ID_BITS);
389 
390   if (contingent_itemidref) {
391     qi->itemIDRef = zx_ref_attr(cf->ctx, &qi->gg, zx_itemIDRef_ATTR, contingent_itemidref);
392     qi->contingency = zx_ref_attr(cf->ctx, &qi->gg, zx_contingency_ATTR, XML_TRUE);
393   }
394   return qi;
395 }
396 
397 /* --------------- DAP: Test -------------- */
398 
399 /*() Low level constructor for <dap:TestOp>. */
400 
401 /* Called by:  covimp_test, main */
zxid_mk_dap_testop(zxid_conf * cf,struct zx_elem_s * father,char * dn,char * filter,char * attributes,int derefaliases,int scope,int sizelimit,int timelimit,int typesonly)402 struct zx_dap_TestOp_s* zxid_mk_dap_testop(zxid_conf* cf, struct zx_elem_s* father, char* dn, char* filter, char* attributes, int derefaliases, int scope, int sizelimit, int timelimit, int typesonly)
403 {
404   struct zx_dap_TestOp_s* sel = zx_NEW_dap_TestOp(cf->ctx, father);
405   if (dn)           sel->dn = zx_ref_elem(cf->ctx, &sel->gg, zx_dap_dn_ELEM, dn);
406   if (filter)       sel->filter = zx_ref_elem(cf->ctx, &sel->gg, zx_dap_filter_ELEM, filter);
407   if (attributes)   sel->attributes = zx_ref_attr(cf->ctx, &sel->gg, zx_attributes_ATTR, attributes);
408   if (derefaliases) sel->derefaliases = zx_attrf(cf->ctx, &sel->gg, zx_derefaliases_ATTR, "%d", derefaliases);
409   if (scope)        sel->scope = zx_attrf(cf->ctx, &sel->gg, zx_scope_ATTR, "%d", scope);
410   if (sizelimit)    sel->sizelimit = zx_attrf(cf->ctx, &sel->gg, zx_sizelimit_ATTR, "%d", sizelimit);
411   if (timelimit)    sel->timelimit = zx_attrf(cf->ctx, &sel->gg, zx_timelimit_ATTR, "%d", timelimit);
412   if (typesonly)    sel->typesonly = zx_ref_attr(cf->ctx, &sel->gg, zx_typesonly_ATTR, XML_TRUE);
413   return sel;
414 }
415 
416 /*() Low level constructor for <dap:TestItem>. */
417 
418 /* Called by:  covimp_test, main */
zxid_mk_dap_test_item(zxid_conf * cf,struct zx_elem_s * father,struct zx_dap_TestOp_s * top,char * objtype,char * predef)419 struct zx_dap_TestItem_s* zxid_mk_dap_test_item(zxid_conf* cf, struct zx_elem_s* father, struct zx_dap_TestOp_s* top, char* objtype, char* predef)
420 {
421   struct zx_dap_TestItem_s* ti = zx_NEW_dap_TestItem(cf->ctx, father);
422   ti->TestOp = top;
423   ti->id = ti->itemID = zxid_mk_id_attr(cf, &ti->gg, zx_id_ATTR, "ti", ZXID_ID_BITS);
424   if (objtype) ti->objectType = zx_ref_attr(cf->ctx, &ti->gg, zx_objectType_ATTR, objtype);
425   if (predef)  ti->predefined = zx_ref_attr(cf->ctx, &ti->gg, zx_predefined_ATTR, predef);
426   return ti;
427 }
428 
429 /* --------------- DAP: ResultQuery and Subscription -------------- */
430 
431 /*() Low level constructor for <dap:ResultQuery>. */
432 
433 /* Called by:  covimp_test, main */
zxid_mk_dap_resquery(zxid_conf * cf,struct zx_elem_s * father,struct zx_dap_Select_s * sel,char * objtype,char * predef,char * sort,char * changed_since,int incl_common_attr,char * contingent_itemidref)434 struct zx_dap_ResultQuery_s* zxid_mk_dap_resquery(zxid_conf* cf, struct zx_elem_s* father, struct zx_dap_Select_s* sel, char* objtype, char* predef, char* sort, char* changed_since, int incl_common_attr, char* contingent_itemidref)
435 {
436   struct zx_dap_ResultQuery_s* qi = zx_NEW_dap_ResultQuery(cf->ctx, father);
437   qi->Select = sel;
438   if (changed_since) qi->changedSince = zx_ref_attr(cf->ctx, &qi->gg, zx_changedSince_ATTR, changed_since);
439   if (objtype)       qi->objectType = zx_ref_attr(cf->ctx, &qi->gg, zx_objectType_ATTR, objtype);
440   if (predef)        qi->predefined = zx_ref_attr(cf->ctx, &qi->gg, zx_predefined_ATTR, predef);
441   if (sort)          qi->Sort = zx_ref_elem(cf->ctx, &qi->gg, zx_dap_Sort_ELEM, sort);
442 
443 #if 0
444   /* ID-DAP specification only allows ChangeFormat == "currentElements"
445    * and in fact recommends omitting it altogether. */
446   if (changed_elems)
447     qi->ChangeFormat = zx_ref_elem(cf->ctx, &qi->gg, zx_dap_ChangeFormat_ELEM, "changedElements");
448   if (curr_elems) {
449     if (qi->ChangeFormat)
450       qi->ChangeFormat->g.n = (struct zx_node_s*)zx_ref_elem(cf->ctx, &qi->gg, zx_dap_ChangeFormat_ELEM, "currentElements");
451     else
452       qi->ChangeFormat = zx_ref_elem(cf->ctx, &qi->gg, zx_dap_ChangeFormat_ELEM, "currentElements");
453   }
454 #endif
455 
456   if (incl_common_attr)
457     qi->includeCommonAttributes = zx_ref_attr(cf->ctx, &qi->gg, zx_includeCommonAttributes_ATTR, XML_TRUE);
458 
459   qi->itemID = zxid_mk_id_attr(cf, &qi->gg, zx_itemID_ATTR, "qi", ZXID_ID_BITS);
460 
461   if (contingent_itemidref) {
462     qi->itemIDRef = zx_ref_attr(cf->ctx, &qi->gg, zx_itemIDRef_ATTR, contingent_itemidref);
463     qi->contingency = zx_ref_attr(cf->ctx, &qi->gg, zx_contingency_ATTR, XML_TRUE);
464   }
465   return qi;
466 }
467 
468 /*() Low level constructor for <dap:Subscription>. */
469 
470 /* Called by:  covimp_test, main */
zxid_mk_dap_subscription(zxid_conf * cf,struct zx_elem_s * father,char * subsID,char * itemidref,struct zx_dap_ResultQuery_s * rq,char * aggreg,char * trig,char * starts,char * expires,int incl_data,char * admin_notif,char * notify_ref)471 struct zx_dap_Subscription_s* zxid_mk_dap_subscription(zxid_conf* cf, struct zx_elem_s* father, char* subsID, char* itemidref, struct zx_dap_ResultQuery_s* rq, char* aggreg, char* trig, char* starts, char* expires, int incl_data, char* admin_notif, char* notify_ref)
472 {
473   struct zx_dap_Subscription_s* subs = zx_NEW_dap_Subscription(cf->ctx, father);
474   if (itemidref) {
475     subs->RefItem = zx_NEW_subs_RefItem(cf->ctx, &subs->gg);
476     subs->RefItem->itemIDRef = zx_ref_attr(cf->ctx, &subs->RefItem->gg, zx_itemIDRef_ATTR, itemidref);
477     if (subsID)
478       subs->RefItem->subscriptionID = zx_ref_attr(cf->ctx, &subs->RefItem->gg, zx_subscriptionID_ATTR, subsID);
479   }
480   subs->ResultQuery = rq;
481   if (aggreg)  subs->Aggregation = zx_ref_elem(cf->ctx, &subs->gg, zx_dap_Aggregation_ELEM, aggreg);
482   if (trig)    subs->Trigger = zx_ref_elem(cf->ctx, &subs->gg, zx_dap_Trigger_ELEM, trig);
483   if (starts)  subs->starts = zx_ref_attr(cf->ctx, &subs->gg, zx_starts_ATTR, starts);
484   if (expires) subs->expires = zx_ref_attr(cf->ctx, &subs->gg, zx_expires_ATTR, expires);
485   if (incl_data)   subs->includeData = zx_ref_attr(cf->ctx, &subs->gg, zx_includeData_ATTR, XML_TRUE);
486   if (admin_notif) subs->adminNotifyToRef = zx_ref_attr(cf->ctx, &subs->gg, zx_adminNotifyToRef_ATTR, admin_notif);
487   if (notify_ref)  subs->notifyToRef = zx_ref_attr(cf->ctx, &subs->gg, zx_notifyToRef_ATTR, notify_ref);
488   subs->subscriptionID = zxid_mk_id_attr(cf, &subs->gg, zx_subscriptionID_ATTR, "subs", ZXID_ID_BITS);;
489   return subs;
490 }
491 
492 /* --------------- DAP: Query -------------- */
493 
494 /*() Low level constructor for <dap:Query>. */
495 
496 /* Called by:  covimp_test, main x3 */
zxid_mk_dap_query(zxid_conf * cf,struct zx_elem_s * father,struct zx_dap_TestItem_s * tis,struct zx_dap_QueryItem_s * qis,struct zx_dap_Subscription_s * subs)497 struct zx_dap_Query_s* zxid_mk_dap_query(zxid_conf* cf, struct zx_elem_s* father, struct zx_dap_TestItem_s* tis, struct zx_dap_QueryItem_s* qis, struct zx_dap_Subscription_s* subs)
498 {
499   struct zx_dap_Query_s* q = zx_NEW_dap_Query(cf->ctx, father);
500   q->TestItem = tis;
501   q->QueryItem = qis;
502   q->Subscription = subs;
503   q->itemID = zx_ref_attr(cf->ctx, &q->gg, zx_itemID_ATTR, "QRY");
504   return q;
505 }
506 
507 /* EOF  --  zxidmkwsf.c */
508