This source file includes following definitions.
- find_named_value
- check_docs_loaded
- describe_method
- xi_system_describe_methods_cb
- xi_system_list_methods_cb
- xi_system_method_signature_cb
- xi_system_method_help_cb
- xi_register_system_methods
- describeValue_worker
- xml_element_to_method_description
- XMLRPC_IntrospectionCreateDescription
- XMLRPC_ServerAddIntrospectionData
- XMLRPC_ServerRegisterIntrospectionCallback
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 #ifdef _WIN32
55 #include "xmlrpc_win32.h"
56 #endif
57 #include "queue.h"
58 #include "xmlrpc.h"
59 #include "xmlrpc_private.h"
60 #include "xmlrpc_introspection_private.h"
61 #include <string.h>
62 #include <stdlib.h>
63 #include <stdarg.h>
64
65
66
67 static XMLRPC_VALUE xi_system_describe_methods_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData);
68 static XMLRPC_VALUE xi_system_list_methods_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData);
69 static XMLRPC_VALUE xi_system_method_signature_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData);
70 static XMLRPC_VALUE xi_system_method_help_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData);
71
72
73
74
75
76
77
78
79
80 static inline XMLRPC_VALUE find_named_value(XMLRPC_VALUE list, const char* needle) {
81 XMLRPC_VALUE xIter = XMLRPC_VectorRewind(list);
82 while(xIter) {
83 const char* name = XMLRPC_VectorGetStringWithID(xIter, xi_token_name);
84 if(name && !strcmp(name, needle)) {
85 return xIter;
86 }
87 xIter = XMLRPC_VectorNext(list);
88 }
89 return NULL;
90 }
91
92
93
94 static void check_docs_loaded(XMLRPC_SERVER server, void* userData) {
95 if(server) {
96 q_iter qi = Q_Iter_Head_F(&server->docslist);
97 while( qi ) {
98 doc_method* dm = Q_Iter_Get_F(qi);
99 if(dm && !dm->b_called) {
100 dm->method(server, userData);
101 dm->b_called = 1;
102 }
103 qi = Q_Iter_Next_F(qi);
104 }
105 }
106 }
107
108
109
110 static inline void describe_method(XMLRPC_SERVER server, XMLRPC_VALUE vector, const char* method) {
111 if(method) {
112 server_method* sm = find_method(server, method);
113 if(sm) {
114 XMLRPC_AddValueToVector(vector, sm->desc);
115 }
116 }
117 }
118
119
120
121
122 static XMLRPC_VALUE xi_system_describe_methods_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData) {
123 XMLRPC_VALUE xParams = XMLRPC_VectorRewind(XMLRPC_RequestGetData(input));
124 XMLRPC_VALUE xResponse = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
125 XMLRPC_VALUE xMethodList = XMLRPC_CreateVector("methodList", xmlrpc_vector_array);
126 XMLRPC_VALUE xTypeList = NULL;
127 int bAll = 1;
128
129
130 check_docs_loaded(server, userData);
131
132 xTypeList = XMLRPC_VectorGetValueWithID(server->xIntrospection, "typeList");
133
134 XMLRPC_AddValueToVector(xResponse, xTypeList);
135 XMLRPC_AddValueToVector(xResponse, xMethodList);
136
137
138 if(xParams) {
139
140 XMLRPC_VALUE_TYPE type = XMLRPC_GetValueType(xParams);
141 if(type == xmlrpc_string) {
142
143 describe_method(server, xMethodList, XMLRPC_GetValueString(xParams));
144 bAll = 0;
145 }
146 else if(type == xmlrpc_vector) {
147
148 XMLRPC_VALUE xIter = XMLRPC_VectorRewind(xParams);
149 while(xIter) {
150 describe_method(server, xMethodList, XMLRPC_GetValueString(xIter));
151 xIter = XMLRPC_VectorNext(xParams);
152 }
153 bAll = 0;
154 }
155 }
156
157
158 if(bAll) {
159 q_iter qi = Q_Iter_Head_F(&server->methodlist);
160 while( qi ) {
161 server_method* sm = Q_Iter_Get_F(qi);
162 if(sm) {
163 XMLRPC_AddValueToVector(xMethodList, sm->desc);
164 }
165 qi = Q_Iter_Next_F(qi);
166 }
167 }
168
169 return xResponse;
170 }
171
172
173 static XMLRPC_VALUE xi_system_list_methods_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData) {
174 XMLRPC_VALUE xResponse = XMLRPC_CreateVector(NULL, xmlrpc_vector_array);
175
176 q_iter qi = Q_Iter_Head_F(&server->methodlist);
177 while( qi ) {
178 server_method* sm = Q_Iter_Get_F(qi);
179 if(sm) {
180 XMLRPC_VectorAppendString(xResponse, 0, sm->name, 0);
181 }
182 qi = Q_Iter_Next_F(qi);
183 }
184 return xResponse;
185 }
186
187
188
189
190 static XMLRPC_VALUE xi_system_method_signature_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData) {
191 const char* method = XMLRPC_GetValueString(XMLRPC_VectorRewind(XMLRPC_RequestGetData(input)));
192 XMLRPC_VALUE xResponse = NULL;
193
194
195 check_docs_loaded(server, userData);
196
197 if(method) {
198 server_method* sm = find_method(server, method);
199 if(sm && sm->desc) {
200 XMLRPC_VALUE xTypesArray = XMLRPC_CreateVector(NULL, xmlrpc_vector_array);
201 XMLRPC_VALUE xIter, xParams, xSig, xSigIter;
202 const char* type;
203
204
205 xResponse = XMLRPC_CreateVector(NULL, xmlrpc_vector_array);
206
207
208 xSig = XMLRPC_VectorGetValueWithID(sm->desc, xi_token_signatures);
209 xSigIter = XMLRPC_VectorRewind( xSig );
210
211
212 while(xSigIter) {
213
214 type = XMLRPC_VectorGetStringWithID(XMLRPC_VectorRewind(
215 XMLRPC_VectorGetValueWithID(xSigIter, xi_token_returns)),
216 xi_token_type);
217 XMLRPC_AddValueToVector(xTypesArray,
218 XMLRPC_CreateValueString(NULL,
219 type ? type : type_to_str(xmlrpc_none, 0),
220 0));
221
222
223 xParams = XMLRPC_VectorGetValueWithID(xSigIter, xi_token_params);
224 xIter = XMLRPC_VectorRewind(xParams);
225
226
227 while(xIter) {
228 XMLRPC_AddValueToVector(xTypesArray,
229 XMLRPC_CreateValueString(NULL,
230 XMLRPC_VectorGetStringWithID(xIter, xi_token_type),
231 0));
232 xIter = XMLRPC_VectorNext(xParams);
233 }
234
235
236 XMLRPC_AddValueToVector(xResponse, xTypesArray);
237
238 xSigIter = XMLRPC_VectorNext( xSig );
239 }
240 }
241 }
242
243 return xResponse;
244 }
245
246
247
248
249 static XMLRPC_VALUE xi_system_method_help_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData) {
250 const char* method = XMLRPC_GetValueString(XMLRPC_VectorRewind(XMLRPC_RequestGetData(input)));
251 XMLRPC_VALUE xResponse = NULL;
252
253
254 check_docs_loaded(server, userData);
255
256 if(method) {
257 server_method* sm = find_method(server, method);
258 if(sm && sm->desc) {
259 const char* help = XMLRPC_VectorGetStringWithID(sm->desc, xi_token_purpose);
260
261
262 xResponse = XMLRPC_CreateValueString(NULL, help ? help : xi_token_empty, 0);
263 }
264 }
265
266 return xResponse;
267 }
268
269
270
271
272
273
274
275
276
277
278
279 void xi_register_system_methods(XMLRPC_SERVER server) {
280 XMLRPC_ServerRegisterMethod(server, xi_token_system_list_methods, xi_system_list_methods_cb);
281 XMLRPC_ServerRegisterMethod(server, xi_token_system_method_help, xi_system_method_help_cb);
282 XMLRPC_ServerRegisterMethod(server, xi_token_system_method_signature, xi_system_method_signature_cb);
283 XMLRPC_ServerRegisterMethod(server, xi_token_system_describe_methods, xi_system_describe_methods_cb);
284 }
285
286
287 static XMLRPC_VALUE describeValue_worker(const char* type, const char* id, const char* desc, int optional, const char* default_val, XMLRPC_VALUE sub_params) {
288 XMLRPC_VALUE xParam = NULL;
289 if(id || desc) {
290 xParam = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
291 XMLRPC_VectorAppendString(xParam, xi_token_name, id, 0);
292 XMLRPC_VectorAppendString(xParam, xi_token_type, type, 0);
293 XMLRPC_VectorAppendString(xParam, xi_token_description, desc, 0);
294 if(optional != 2) {
295 XMLRPC_VectorAppendInt(xParam, xi_token_optional, optional);
296 }
297 if(optional == 1 && default_val) {
298 XMLRPC_VectorAppendString(xParam, xi_token_default, default_val, 0);
299 }
300 XMLRPC_AddValueToVector(xParam, sub_params);
301 }
302 return xParam;
303 }
304
305
306
307
308
309 XMLRPC_VALUE xml_element_to_method_description(xml_element* el, XMLRPC_ERROR err) {
310 XMLRPC_VALUE xReturn = NULL;
311
312 if(el->name) {
313 const char* name = NULL;
314 const char* type = NULL;
315 const char* basetype = NULL;
316 const char* desc = NULL;
317 const char* def = NULL;
318 int optional = 0;
319 xml_element_attr* attr_iter = Q_Head(&el->attrs);
320
321
322 while(attr_iter) {
323 if(!strcmp(attr_iter->key, "name")) {
324 name = attr_iter->val;
325 }
326 else if(!strcmp(attr_iter->key, "type")) {
327 type = attr_iter->val;
328 }
329 else if(!strcmp(attr_iter->key, "basetype")) {
330 basetype = attr_iter->val;
331 }
332 else if(!strcmp(attr_iter->key, "desc")) {
333 desc = attr_iter->val;
334 }
335 else if(!strcmp(attr_iter->key, "optional")) {
336 if(attr_iter->val && !strcmp(attr_iter->val, "yes")) {
337 optional = 1;
338 }
339 }
340 else if(!strcmp(attr_iter->key, "default")) {
341 def = attr_iter->val;
342 }
343 attr_iter = Q_Next(&el->attrs);
344 }
345
346
347 if(!strcmp(el->name, "value") || !strcmp(el->name, "typeDescription")) {
348 XMLRPC_VALUE xSubList = NULL;
349 const char* ptype = !strcmp(el->name, "value") ? type : basetype;
350 if(ptype) {
351 if(Q_Size(&el->children) &&
352 (!strcmp(ptype, "array") || !strcmp(ptype, "struct") || !strcmp(ptype, "mixed"))) {
353 xSubList = XMLRPC_CreateVector("member", xmlrpc_vector_array);
354
355 if(xSubList) {
356 xml_element* elem_iter = Q_Head(&el->children);
357 while(elem_iter) {
358 XMLRPC_AddValueToVector(xSubList,
359 xml_element_to_method_description(elem_iter, err));
360 elem_iter = Q_Next(&el->children);
361 }
362 }
363 }
364 xReturn = describeValue_worker(ptype, name, (desc ? desc : (xSubList ? NULL : el->text.str)), optional, def, xSubList);
365 }
366 }
367
368
369 else if(!strcmp(el->name, "params") ||
370 !strcmp(el->name, "returns") ||
371 !strcmp(el->name, "signature")) {
372 if(Q_Size(&el->children)) {
373 xml_element* elem_iter = Q_Head(&el->children);
374 xReturn = XMLRPC_CreateVector(!strcmp(el->name, "signature") ? NULL : el->name, xmlrpc_vector_struct);
375
376
377 while(elem_iter) {
378 XMLRPC_AddValueToVector(xReturn,
379 xml_element_to_method_description(elem_iter, err));
380 elem_iter = Q_Next(&el->children);
381 }
382 }
383 }
384
385
386 else if(!strcmp(el->name, "methodDescription")) {
387 xml_element* elem_iter = Q_Head(&el->children);
388 xReturn = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
389
390 XMLRPC_VectorAppendString(xReturn, xi_token_name, name, 0);
391
392 while(elem_iter) {
393 XMLRPC_AddValueToVector(xReturn,
394 xml_element_to_method_description(elem_iter, err));
395 elem_iter = Q_Next(&el->children);
396 }
397 }
398
399
400 else if(!strcmp(el->name, "item")) {
401 xReturn = XMLRPC_CreateValueString(name, el->text.str, el->text.len);
402 }
403
404
405 else if(Q_Size(&el->children)) {
406 xml_element* elem_iter = Q_Head(&el->children);
407 xReturn = XMLRPC_CreateVector(el->name, xmlrpc_vector_mixed);
408
409 while(elem_iter) {
410 XMLRPC_AddValueToVector(xReturn,
411 xml_element_to_method_description(elem_iter, err));
412 elem_iter = Q_Next(&el->children);
413 }
414 }
415
416
417
418
419 else if(el->name && el->text.len) {
420 xReturn = XMLRPC_CreateValueString(el->name, el->text.str, el->text.len);
421 }
422 }
423
424 return xReturn;
425 }
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458 XMLRPC_VALUE XMLRPC_IntrospectionCreateDescription(const char* xml, XMLRPC_ERROR err) {
459 XMLRPC_VALUE xReturn = NULL;
460 xml_element* root = xml_elem_parse_buf(xml, 0, 0, err ? &err->xml_elem_error : NULL);
461
462 if(root) {
463 xReturn = xml_element_to_method_description(root, err);
464
465 xml_elem_free(root);
466 }
467
468 return xReturn;
469
470 }
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500 int XMLRPC_ServerAddIntrospectionData(XMLRPC_SERVER server, XMLRPC_VALUE desc) {
501 int bSuccess = 0;
502 if(server && desc) {
503 XMLRPC_VALUE xNewTypes = XMLRPC_VectorGetValueWithID(desc, "typeList");
504 XMLRPC_VALUE xNewMethods = XMLRPC_VectorGetValueWithID(desc, "methodList");
505 XMLRPC_VALUE xServerTypes = XMLRPC_VectorGetValueWithID(server->xIntrospection, "typeList");
506
507 if(xNewMethods) {
508 XMLRPC_VALUE xMethod = XMLRPC_VectorRewind(xNewMethods);
509
510 while(xMethod) {
511 const char* name = XMLRPC_VectorGetStringWithID(xMethod, xi_token_name);
512 server_method* sm = find_method(server, name);
513
514 if(sm) {
515 if(sm->desc) {
516 XMLRPC_CleanupValue(sm->desc);
517 }
518 sm->desc = XMLRPC_CopyValue(xMethod);
519 bSuccess = 1;
520 }
521
522 xMethod = XMLRPC_VectorNext(xNewMethods);
523 }
524 }
525 if(xNewTypes) {
526 if(!xServerTypes) {
527 if(!server->xIntrospection) {
528 server->xIntrospection = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
529 }
530
531 XMLRPC_AddValueToVector(server->xIntrospection, xNewTypes);
532 bSuccess = 1;
533 }
534 else {
535 XMLRPC_VALUE xIter = XMLRPC_VectorRewind(xNewTypes);
536 while(xIter) {
537
538 XMLRPC_VALUE xPrev = find_named_value(xServerTypes, XMLRPC_VectorGetStringWithID(xIter, xi_token_name));
539 if(xPrev) {
540 XMLRPC_VectorRemoveValue(xServerTypes, xPrev);
541 }
542 XMLRPC_AddValueToVector(xServerTypes, xIter);
543 bSuccess = 1;
544 xIter = XMLRPC_VectorNext(xNewTypes);
545 }
546 }
547 }
548 }
549 return bSuccess;
550 }
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577 int XMLRPC_ServerRegisterIntrospectionCallback(XMLRPC_SERVER server, XMLRPC_IntrospectionCallback cb) {
578 int bSuccess = 0;
579 if(server && cb) {
580
581 doc_method* dm = calloc(1, sizeof(doc_method));
582
583 if(dm) {
584 dm->method = cb;
585 dm->b_called = 0;
586
587 if(Q_PushTail(&server->docslist, dm)) {
588 bSuccess = 1;
589 }
590 else {
591 my_free(dm);
592 }
593 }
594 }
595 return 0;
596 }
597
598
599
600
601
602
603
604