1 /*
2 This file is part of libXMLRPC - a C library for xml-encoded function calls.
3
4 Author: Dan Libby (dan@libby.com)
5 Epinions.com may be contacted at feedback@epinions-inc.com
6 */
7
8 /*
9 Copyright 2000 Epinions, Inc.
10
11 Subject to the following 3 conditions, Epinions, Inc. permits you, free
12 of charge, to (a) use, copy, distribute, modify, perform and display this
13 software and associated documentation files (the "Software"), and (b)
14 permit others to whom the Software is furnished to do so as well.
15
16 1) The above copyright notice and this permission notice shall be included
17 without modification in all copies or substantial portions of the
18 Software.
19
20 2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF
21 ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY
22 IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 PURPOSE OR NONINFRINGEMENT.
24
25 3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
26 SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
27 OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING
28 NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH
29 DAMAGES.
30
31 */
32
33
34 /****h* ABOUT/xmlrpc
35 * NAME
36 * XMLRPC_VALUE
37 * AUTHOR
38 * Dan Libby, aka danda (dan@libby.com)
39 * CREATION DATE
40 * 9/1999 - 10/2000
41 * HISTORY
42 * $Log$
43 * Revision 1.8.4.3.2.1 2008/09/10 00:07:44 felipe
44 * MFH:
45 * - Merged fix from SF project (Import Jeff Lawsons patches for XML datetime bug fixes)
46 * Fixed bugs:
47 * #45226 (xmlrpc_set_type() segfaults with valid ISO8601 date string)
48 * #18916 (xmlrpc_set_type() "not working")
49 *
50 * Revision 1.8.4.3 2007/09/18 19:49:53 iliaa
51 *
52 * Fixed bug #42189 (xmlrpc_set_type() crashes php on invalid datetime
53 * values).
54 *
55 * Revision 1.8.4.2 2007/06/07 09:07:36 tony2001
56 * MFH: php_localtime_r() checks
57 *
58 * Revision 1.8.4.1 2006/11/30 16:38:37 iliaa
59 * last set of zts fixes
60 *
61 * Revision 1.8 2005/03/28 00:07:24 edink
62 * Reshufle includes to make it compile on windows
63 *
64 * Revision 1.7 2005/03/26 03:13:58 sniper
65 * - Made it possible to build ext/xmlrpc with libxml2
66 *
67 * Revision 1.6 2004/04/27 17:33:59 iliaa
68 * Removed C++ style comments.
69 *
70 * Revision 1.5 2003/12/16 21:00:21 sniper
71 * Fix some compile warnings (patch by Joe Orton)
72 *
73 * Revision 1.4 2002/07/05 04:43:53 danda
74 * merged in updates from SF project. bring php repository up to date with xmlrpc-epi version 0.51
75 *
76 * Revision 1.22 2002/03/09 23:15:44 danda
77 * add fault interrogation funcs
78 *
79 * Revision 1.21 2002/03/09 22:27:41 danda
80 * win32 build patches contributed by Jeff Lawson
81 *
82 * Revision 1.20 2002/02/13 20:58:50 danda
83 * patch to make source more windows friendly, contributed by Jeff Lawson
84 *
85 * Revision 1.19 2001/10/12 23:25:54 danda
86 * default to writing xmlrpc
87 *
88 * Revision 1.18 2001/09/29 21:58:05 danda
89 * adding cvs log to history section
90 *
91 * 10/15/2000 -- danda -- adding robodoc documentation
92 * 08/2000 -- danda -- PHP C extension that uses XMLRPC
93 * 08/2000 -- danda -- support for two vocabularies: danda-rpc and xml-rpc
94 * 09/1999 -- danda -- Initial API, before I even knew of standard XMLRPC vocab. Response only.
95 * 07/2000 -- danda -- wrote new implementation to be compatible with xmlrpc standard and
96 * incorporated some ideas from ensor, most notably the separation of
97 * xml dom from xmlrpc api.
98 * 06/2000 -- danda -- played with expat-ensor from www.ensor.org. Cool, but some flaws.
99 * TODO
100 * PORTABILITY
101 * Coded on RedHat Linux 6.2. Builds on Solaris x86. Should build on just
102 * about anything with minor mods.
103 * NOTES
104 * Welcome to XMLRPC. For more info on the specification and history, see
105 * http://www.xmlrpc.org.
106 *
107 * This code aims to be a full-featured C implementation of XMLRPC. It does not
108 * have any networking code. Rather, it is intended to be plugged into apps
109 * or libraries with existing networking facilities, eg PHP, apache, perl, mozilla,
110 * home-brew application servers, etc.
111 *
112 * Usage Paradigm:
113 * The user of this library will typically be implementing either an XMLRPC server,
114 * an XMLRPC client, or both. The client will use the library to build an in-memory
115 * representation of a request, and then serialize (encode) that request into XML. The
116 * client will then send the XML to the server via external mechanism. The server will
117 * de-serialize the XML back into an binary representation, call the appropriate registered
118 * method -- thereby generating a response. The response will be serialized into XML and
119 * sent back to the client. The client will de-serialize it into memory, and can
120 * iterate through the results via API.
121 *
122 * Both the request and the response may consist of arbitrarily long, arbitrarily nested
123 * values. The values may be one of several types, as defined by XMLRPC_VALUE_TYPE.
124 *
125 * Features and Architecture:
126 * - The XML parsing (xml_element.c) is completely independent of the XMLRPC api. In fact,
127 * it can be used as a standalone dom implementation.
128 * - Because of this, the same XMLRPC data can be serialized into multiple xml vocabularies.
129 * It is simply a matter of writing a transport. So far, two transports have been defined.
130 * The default xmlrpc vocab (xml_to_xmlrpc.c), and simple-rpc (xml_to_dandarpc.c) which is
131 * proprietary, but imho more readable, and nice for proprietary legacy reasons.
132 * - Various output options, including: xml escaping via CDATA or entity, case folding,
133 * vocab version, and character encoding.
134 * - One to One mapping between C structures and actual values, unlike ensor which forces
135 * one to understand the arcana of the xmlrpc vocab.
136 * - support for mixed indexed/keyed vector types, making it more compatible with
137 * languages such as PHP.
138 * - quite speedy compared to implementations written in interpreted languages. Also, uses
139 * intelligent string handling, so not many strlen() calls, etc.
140 * - comprehensive API for manipulation of values
141 *******/
142
143 #include "ext/xml/expat_compat.h"
144 #include "main/php_reentrancy.h"
145 #include <stdio.h>
146 #include <stdlib.h>
147 #include <string.h>
148 #include <stdarg.h>
149 #include <time.h>
150 #include <ctype.h>
151
152 #include "queue.h"
153 #include "xmlrpc.h"
154 #include "base64.h"
155
156 #include "xml_to_xmlrpc.h"
157 #include "xml_to_dandarpc.h"
158 #include "xml_to_soap.h"
159 #include "xml_element.h"
160 #include "xmlrpc_private.h"
161 #include "xmlrpc_introspection_private.h"
162 #include "system_methods_private.h"
163
164
165
166 /*-*********************
167 * Begin Time Functions *
168 ***********************/
169
mkgmtime(struct tm * tm)170 static time_t mkgmtime(struct tm *tm)
171 {
172 static const int mdays[12] = {0,31,59,90,120,151,181,212,243,273,304,334};
173
174 return ((((((tm->tm_year - 70) * 365) + mdays[tm->tm_mon] + tm->tm_mday-1 +
175 (tm->tm_year-68-1+(tm->tm_mon>=2))/4) * 24) + tm->tm_hour) * 60 +
176 tm->tm_min) * 60 + tm->tm_sec;
177 }
178
date_from_ISO8601(const char * text,time_t * value)179 static int date_from_ISO8601 (const char *text, time_t * value) {
180 struct tm tm;
181 int n;
182 int i;
183 char buf[30];
184
185
186 if (strchr (text, '-')) {
187 char *p = (char *) text, *p2 = buf;
188 while (p && *p) {
189 if (*p != '-') {
190 *p2 = *p;
191 p2++;
192 if (p2-buf >= sizeof(buf)) {
193 return -1;
194 }
195 }
196 p++;
197 }
198 *p2 = 0;
199 text = buf;
200 }
201
202 if (strlen(text)<17) {
203 return -1;
204 }
205
206 tm.tm_isdst = -1;
207
208 #define XMLRPC_IS_NUMBER(x) if (x < '0' || x > '9') return -1;
209
210 n = 1000;
211 tm.tm_year = 0;
212 for(i = 0; i < 4; i++) {
213 XMLRPC_IS_NUMBER(text[i])
214 tm.tm_year += (text[i]-'0')*n;
215 n /= 10;
216 }
217 n = 10;
218 tm.tm_mon = 0;
219 for(i = 0; i < 2; i++) {
220 XMLRPC_IS_NUMBER(text[i+4])
221 tm.tm_mon += (text[i+4]-'0')*n;
222 n /= 10;
223 }
224 tm.tm_mon --;
225 if(tm.tm_mon < 0 || tm.tm_mon > 11) {
226 return -1;
227 }
228
229 n = 10;
230 tm.tm_mday = 0;
231 for(i = 0; i < 2; i++) {
232 XMLRPC_IS_NUMBER(text[i+6])
233 tm.tm_mday += (text[i+6]-'0')*n;
234 n /= 10;
235 }
236
237 n = 10;
238 tm.tm_hour = 0;
239 for(i = 0; i < 2; i++) {
240 XMLRPC_IS_NUMBER(text[i+9])
241 tm.tm_hour += (text[i+9]-'0')*n;
242 n /= 10;
243 }
244
245 n = 10;
246 tm.tm_min = 0;
247 for(i = 0; i < 2; i++) {
248 XMLRPC_IS_NUMBER(text[i+12])
249 tm.tm_min += (text[i+12]-'0')*n;
250 n /= 10;
251 }
252
253 n = 10;
254 tm.tm_sec = 0;
255 for(i = 0; i < 2; i++) {
256 XMLRPC_IS_NUMBER(text[i+15])
257 tm.tm_sec += (text[i+15]-'0')*n;
258 n /= 10;
259 }
260
261 tm.tm_year -= 1900;
262
263 *value = mkgmtime(&tm);
264
265 return 0;
266
267 }
268
date_to_ISO8601(time_t value,char * buf,int length)269 static int date_to_ISO8601 (time_t value, char *buf, int length) {
270 struct tm *tm, tmbuf;
271 tm = php_gmtime_r(&value, &tmbuf);
272 if (!tm) {
273 return 0;
274 }
275 #if 0 /* TODO: soap seems to favor this method. xmlrpc the latter. */
276 return strftime (buf, length, "%Y-%m-%dT%H:%M:%SZ", tm);
277 #else
278 return strftime(buf, length, "%Y%m%dT%H:%M:%SZ", tm);
279 #endif
280 }
281
282 /*-*******************
283 * End Time Functions *
284 *********************/
285
286
287 /*-***************************
288 * Begin XMLRPC_REQUEST funcs *
289 *****************************/
290
291 /****f* REQUEST/XMLRPC_RequestNew
292 * NAME
293 * XMLRPC_RequestNew
294 * SYNOPSIS
295 * XMLRPC_REQUEST XMLRPC_RequestNew()
296 * FUNCTION
297 * Creates a new XMLRPC_Request data struct
298 * INPUTS
299 * none
300 * SEE ALSO
301 * XMLRPC_RequestFree ()
302 * SOURCE
303 */
XMLRPC_RequestNew()304 XMLRPC_REQUEST XMLRPC_RequestNew() {
305 XMLRPC_REQUEST xRequest = ecalloc(1, sizeof(STRUCT_XMLRPC_REQUEST));
306 if(xRequest) {
307 simplestring_init(&xRequest->methodName);
308 }
309 return xRequest;
310 }
311
312 /*******/
313
314 /****f* REQUEST/XMLRPC_RequestFree
315 * NAME
316 * XMLRPC_RequestFree
317 * SYNOPSIS
318 * void XMLRPC_RequestFree(XMLRPC_REQUEST request, int bFreeIO)
319 * FUNCTION
320 * Free XMLRPC Request and all sub-values
321 * INPUTS
322 * request -- previously allocated request struct
323 * bFreeIO -- 1 = also free request value data, if any, 0 = ignore.
324 * SEE ALSO
325 * XMLRPC_RequestNew ()
326 * XMLRPC_CleanupValue ()
327 * SOURCE
328 */
XMLRPC_RequestFree(XMLRPC_REQUEST request,int bFreeIO)329 void XMLRPC_RequestFree(XMLRPC_REQUEST request, int bFreeIO) {
330 if(request) {
331 simplestring_free(&request->methodName);
332
333 if(request->io && bFreeIO) {
334 XMLRPC_CleanupValue(request->io);
335 }
336 if(request->error) {
337 XMLRPC_CleanupValue(request->error);
338 }
339 my_free(request);
340 }
341 }
342
343 /*******/
344
345 /* Set Method Name to call */
346 /****f* REQUEST/XMLRPC_RequestSetMethodName
347 * NAME
348 * XMLRPC_RequestSetMethodName
349 * SYNOPSIS
350 * const char* XMLRPC_RequestSetMethodName(XMLRPC_REQUEST request, const char* methodName)
351 * FUNCTION
352 * Set name of method to call with this request.
353 * INPUTS
354 * request -- previously allocated request struct
355 * methodName -- name of method
356 * SEE ALSO
357 * XMLRPC_RequestNew ()
358 * XMLRPC_RequestGetMethodName ()
359 * XMLRPC_RequestFree ()
360 * SOURCE
361 */
XMLRPC_RequestSetMethodName(XMLRPC_REQUEST request,const char * methodName)362 const char* XMLRPC_RequestSetMethodName(XMLRPC_REQUEST request, const char* methodName) {
363 if(request) {
364 simplestring_clear(&request->methodName);
365 simplestring_add(&request->methodName, methodName);
366 return request->methodName.str;
367 }
368 return NULL;
369 }
370
371 /*******/
372
373 /****f* REQUEST/XMLRPC_RequestGetMethodName
374 * NAME
375 * XMLRPC_RequestGetMethodName
376 * SYNOPSIS
377 * const char* XMLRPC_RequestGetMethodName(XMLRPC_REQUEST request)
378 * FUNCTION
379 * Get name of method called by this request
380 * INPUTS
381 * request -- previously allocated request struct
382 * SEE ALSO
383 * XMLRPC_RequestNew ()
384 * XMLRPC_RequestSetMethodName ()
385 * XMLRPC_RequestFree ()
386 * SOURCE
387 */
XMLRPC_RequestGetMethodName(XMLRPC_REQUEST request)388 const char* XMLRPC_RequestGetMethodName(XMLRPC_REQUEST request) {
389 return request ? request->methodName.str : NULL;
390 }
391
392 /*******/
393
394 /****f* REQUEST/XMLRPC_RequestSetRequestType
395 * NAME
396 * XMLRPC_RequestSetRequestType
397 * SYNOPSIS
398 * XMLRPC_REQUEST_TYPE XMLRPC_RequestSetRequestType(XMLRPC_REQUEST request, XMLRPC_REQUEST_TYPE type)
399 * FUNCTION
400 * A request struct may be allocated by a caller or by xmlrpc
401 * in response to a request. This allows setting the
402 * request type.
403 * INPUTS
404 * request -- previously allocated request struct
405 * type -- request type [xmlrpc_method_call | xmlrpc_method_response]
406 * SEE ALSO
407 * XMLRPC_RequestNew ()
408 * XMLRPC_RequestGetRequestType ()
409 * XMLRPC_RequestFree ()
410 * XMLRPC_REQUEST_TYPE
411 * SOURCE
412 */
XMLRPC_RequestSetRequestType(XMLRPC_REQUEST request,XMLRPC_REQUEST_TYPE type)413 XMLRPC_REQUEST_TYPE XMLRPC_RequestSetRequestType (XMLRPC_REQUEST request,
414 XMLRPC_REQUEST_TYPE type) {
415 if(request) {
416 request->request_type = type;
417 return request->request_type;
418 }
419 return xmlrpc_request_none;
420 }
421
422 /*******/
423
424 /****f* REQUEST/XMLRPC_RequestGetRequestType
425 * NAME
426 * XMLRPC_RequestGetRequestType
427 * SYNOPSIS
428 * XMLRPC_REQUEST_TYPE XMLRPC_RequestGetRequestType(XMLRPC_REQUEST request)
429 * FUNCTION
430 * A request struct may be allocated by a caller or by xmlrpc
431 * in response to a request. This allows setting the
432 * request type.
433 * INPUTS
434 * request -- previously allocated request struct
435 * RESULT
436 * type -- request type [xmlrpc_method_call | xmlrpc_method_response]
437 * SEE ALSO
438 * XMLRPC_RequestNew ()
439 * XMLRPC_RequestSetRequestType ()
440 * XMLRPC_RequestFree ()
441 * XMLRPC_REQUEST_TYPE
442 * SOURCE
443 */
XMLRPC_RequestGetRequestType(XMLRPC_REQUEST request)444 XMLRPC_REQUEST_TYPE XMLRPC_RequestGetRequestType(XMLRPC_REQUEST request) {
445 return request ? request->request_type : xmlrpc_request_none;
446 }
447
448 /*******/
449
450
451 /****f* REQUEST/XMLRPC_RequestSetData
452 * NAME
453 * XMLRPC_RequestSetData
454 * SYNOPSIS
455 * XMLRPC_VALUE XMLRPC_RequestSetData(XMLRPC_REQUEST request, XMLRPC_VALUE data)
456 * FUNCTION
457 * Associates a block of xmlrpc data with the request. The
458 * data is *not* copied. A pointer is kept. The caller
459 * should be careful not to doubly free the data value,
460 * which may optionally be free'd by XMLRPC_RequestFree().
461 * INPUTS
462 * request -- previously allocated request struct
463 * data -- previously allocated data struct
464 * RESULT
465 * XMLRPC_VALUE -- pointer to value stored, or NULL
466 * SEE ALSO
467 * XMLRPC_RequestNew ()
468 * XMLRPC_RequestGetData ()
469 * XMLRPC_RequestFree ()
470 * XMLRPC_REQUEST
471 * XMLRPC_VALUE
472 * SOURCE
473 */
XMLRPC_RequestSetData(XMLRPC_REQUEST request,XMLRPC_VALUE data)474 XMLRPC_VALUE XMLRPC_RequestSetData(XMLRPC_REQUEST request, XMLRPC_VALUE data) {
475 if(request && data) {
476 if (request->io) {
477 XMLRPC_CleanupValue (request->io);
478 }
479 request->io = XMLRPC_CopyValue(data);
480 return request->io;
481 }
482 return NULL;
483 }
484
485 /*******/
486
487 /****f* REQUEST/XMLRPC_RequestGetData
488 * NAME
489 * XMLRPC_RequestGetData
490 * SYNOPSIS
491 * XMLRPC_VALUE XMLRPC_RequestGetData(XMLRPC_REQUEST request)
492 * FUNCTION
493 * Returns data associated with request, if any.
494 * INPUTS
495 * request -- previously allocated request struct
496 * RESULT
497 * XMLRPC_VALUE -- pointer to value stored, or NULL
498 * SEE ALSO
499 * XMLRPC_RequestNew ()
500 * XMLRPC_RequestSetData ()
501 * XMLRPC_RequestFree ()
502 * XMLRPC_REQUEST
503 * XMLRPC_VALUE
504 * SOURCE
505 */
XMLRPC_RequestGetData(XMLRPC_REQUEST request)506 XMLRPC_VALUE XMLRPC_RequestGetData(XMLRPC_REQUEST request) {
507 return request ? request->io : NULL;
508 }
509
510 /*******/
511
512 /****f* REQUEST/XMLRPC_RequestSetError
513 * NAME
514 * XMLRPC_RequestSetError
515 * SYNOPSIS
516 * XMLRPC_VALUE XMLRPC_RequestSetError(XMLRPC_REQUEST request, XMLRPC_VALUE error)
517 * FUNCTION
518 * Associates a block of xmlrpc data, representing an error
519 * condition, with the request.
520 * INPUTS
521 * request -- previously allocated request struct
522 * error -- previously allocated error code or struct
523 * RESULT
524 * XMLRPC_VALUE -- pointer to value stored, or NULL
525 * NOTES
526 * This is a private function for usage by internals only.
527 * SEE ALSO
528 * XMLRPC_RequestGetError ()
529 * SOURCE
530 */
XMLRPC_RequestSetError(XMLRPC_REQUEST request,XMLRPC_VALUE error)531 XMLRPC_VALUE XMLRPC_RequestSetError (XMLRPC_REQUEST request, XMLRPC_VALUE error) {
532 if (request && error) {
533 if (request->error) {
534 XMLRPC_CleanupValue (request->error);
535 }
536 request->error = XMLRPC_CopyValue (error);
537 return request->error;
538 }
539 return NULL;
540 }
541
542 /*******/
543
544 /****f* REQUEST/XMLRPC_RequestGetError
545 * NAME
546 * XMLRPC_RequestGetError
547 * SYNOPSIS
548 * XMLRPC_VALUE XMLRPC_RequestGetError(XMLRPC_REQUEST request)
549 * FUNCTION
550 * Returns error data associated with request, if any.
551 * INPUTS
552 * request -- previously allocated request struct
553 * RESULT
554 * XMLRPC_VALUE -- pointer to error value stored, or NULL
555 * NOTES
556 * This is a private function for usage by internals only.
557 * SEE ALSO
558 * XMLRPC_RequestSetError ()
559 * XMLRPC_RequestFree ()
560 * SOURCE
561 */
XMLRPC_RequestGetError(XMLRPC_REQUEST request)562 XMLRPC_VALUE XMLRPC_RequestGetError (XMLRPC_REQUEST request) {
563 return request ? request->error : NULL;
564 }
565
566 /*******/
567
568
569 /****f* REQUEST/XMLRPC_RequestSetOutputOptions
570 * NAME
571 * XMLRPC_RequestSetOutputOptions
572 * SYNOPSIS
573 * XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestSetOutputOptions(XMLRPC_REQUEST request, XMLRPC_REQUEST_OUTPUT_OPTIONS output)
574 * FUNCTION
575 * Sets output options used for generating XML. The output struct
576 * is copied, and may be freed by the caller.
577 * INPUTS
578 * request -- previously allocated request struct
579 * output -- output options struct initialized by caller
580 * RESULT
581 * XMLRPC_REQUEST_OUTPUT_OPTIONS -- pointer to value stored, or NULL
582 * SEE ALSO
583 * XMLRPC_RequestNew ()
584 * XMLRPC_RequestGetOutputOptions ()
585 * XMLRPC_RequestFree ()
586 * XMLRPC_REQUEST
587 * XMLRPC_REQUEST_OUTPUT_OPTIONS
588 * SOURCE
589 */
XMLRPC_RequestSetOutputOptions(XMLRPC_REQUEST request,XMLRPC_REQUEST_OUTPUT_OPTIONS output)590 XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestSetOutputOptions(XMLRPC_REQUEST request, XMLRPC_REQUEST_OUTPUT_OPTIONS output) {
591 if(request && output) {
592 memcpy (&request->output, output,
593 sizeof (STRUCT_XMLRPC_REQUEST_OUTPUT_OPTIONS));
594 return &request->output;
595 }
596 return NULL;
597 }
598
599 /*******/
600
601
602 /****f* REQUEST/XMLRPC_RequestGetOutputOptions
603 * NAME
604 * XMLRPC_RequestGetOutputOptions
605 * SYNOPSIS
606 * XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestGetOutputOptions(XMLRPC_REQUEST request)
607 * FUNCTION
608 * Gets a pointer to output options used for generating XML.
609 * INPUTS
610 * request -- previously allocated request struct
611 * RESULT
612 * XMLRPC_REQUEST_OUTPUT_OPTIONS -- pointer to options stored, or NULL
613 * SEE ALSO
614 * XMLRPC_RequestNew ()
615 * XMLRPC_RequestSetOutputOptions ()
616 * XMLRPC_RequestFree ()
617 * XMLRPC_REQUEST
618 * XMLRPC_REQUEST_OUTPUT_OPTIONS
619 * SOURCE
620 */
XMLRPC_RequestGetOutputOptions(XMLRPC_REQUEST request)621 XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestGetOutputOptions(XMLRPC_REQUEST request) {
622 return request ? &request->output : NULL;
623 }
624
625 /*******/
626
627 /*-*************************
628 * End XMLRPC_REQUEST funcs *
629 ***************************/
630
631
632 /*-***************************
633 * Begin Serializiation funcs *
634 *****************************/
635
636 /****f* SERIALIZE/XMLRPC_VALUE_ToXML
637 * NAME
638 * XMLRPC_VALUE_ToXML
639 * SYNOPSIS
640 * char* XMLRPC_VALUE_ToXML(XMLRPC_VALUE val)
641 * FUNCTION
642 * encode XMLRPC_VALUE into XML buffer. Note that the generated
643 * buffer will not contain a methodCall.
644 * INPUTS
645 * val -- previously allocated XMLRPC_VALUE
646 * buf_len -- length of returned buffer, if not null
647 * RESULT
648 * char* -- newly allocated buffer containing XML.
649 * It is the caller's responsibility to free it.
650 * SEE ALSO
651 * XMLRPC_REQUEST_ToXML ()
652 * XMLRPC_VALUE_FromXML ()
653 * XMLRPC_Free ()
654 * XMLRPC_VALUE
655 * SOURCE
656 */
XMLRPC_VALUE_ToXML(XMLRPC_VALUE val,int * buf_len)657 char* XMLRPC_VALUE_ToXML(XMLRPC_VALUE val, int* buf_len) {
658 xml_element *root_elem = XMLRPC_VALUE_to_xml_element(val);
659 char* pRet = NULL;
660
661 if(root_elem) {
662 pRet = xml_elem_serialize_to_string(root_elem, NULL, buf_len);
663 xml_elem_free(root_elem);
664 }
665 return pRet;
666 }
667
668 /*******/
669
670 /****f* SERIALIZE/XMLRPC_REQUEST_ToXML
671 * NAME
672 * XMLRPC_REQUEST_ToXML
673 * SYNOPSIS
674 * char* XMLRPC_REQUEST_ToXML(XMLRPC_REQUEST request)
675 * FUNCTION
676 * encode XMLRPC_REQUEST into XML buffer
677 * INPUTS
678 * request -- previously allocated XMLRPC_REQUEST
679 * buf_len -- size of returned buf, if not null
680 * RESULT
681 * char* -- newly allocated buffer containing XML.
682 * It is the caller's responsibility to free it.
683 * SEE ALSO
684 * XMLRPC_REQUEST_ToXML ()
685 * XMLRPC_REQUEST_FromXML ()
686 * XMLRPC_Free ()
687 * XMLRPC_VALUE_ToXML ()
688 * XMLRPC_REQUEST
689 * SOURCE
690 */
XMLRPC_REQUEST_ToXML(XMLRPC_REQUEST request,int * buf_len)691 char* XMLRPC_REQUEST_ToXML(XMLRPC_REQUEST request, int* buf_len) {
692 char* pRet = NULL;
693 if (request) {
694 xml_element *root_elem = NULL;
695 if (request->output.version == xmlrpc_version_simple) {
696 root_elem = DANDARPC_REQUEST_to_xml_element (request);
697 }
698 else if (request->output.version == xmlrpc_version_1_0 ||
699 request->output.version == xmlrpc_version_none) {
700 root_elem = XMLRPC_REQUEST_to_xml_element (request);
701 }
702 else if (request->output.version == xmlrpc_version_soap_1_1) {
703 root_elem = SOAP_REQUEST_to_xml_element (request);
704 }
705
706 if(root_elem) {
707 pRet =
708 xml_elem_serialize_to_string (root_elem,
709 &request->output.xml_elem_opts,
710 buf_len);
711 xml_elem_free(root_elem);
712 }
713 }
714 return pRet;
715 }
716
717 /*******/
718
719 /****f* SERIALIZE/XMLRPC_VALUE_FromXML
720 * NAME
721 * XMLRPC_VALUE_FromXML
722 * SYNOPSIS
723 * XMLRPC_VALUE XMLRPC_VALUE_FromXML(const char* in_buf, int le
724 * FUNCTION
725 * Retrieve XMLRPC_VALUE from XML buffer. Note that this will
726 * ignore any methodCall. See XMLRPC_REQUEST_FromXML
727 * INPUTS
728 * in_buf -- character buffer containing XML
729 * len -- length of buffer
730 * RESULT
731 * XMLRPC_VALUE -- newly allocated data, or NULL if error. Should
732 * be free'd by caller.
733 * SEE ALSO
734 * XMLRPC_VALUE_ToXML ()
735 * XMLRPC_REQUEST_FromXML ()
736 * XMLRPC_VALUE
737 * SOURCE
738 */
XMLRPC_VALUE_FromXML(const char * in_buf,int len,XMLRPC_REQUEST_INPUT_OPTIONS in_options)739 XMLRPC_VALUE XMLRPC_VALUE_FromXML (const char *in_buf, int len, XMLRPC_REQUEST_INPUT_OPTIONS in_options) {
740 XMLRPC_VALUE xResponse = NULL;
741 XMLRPC_REQUEST req = XMLRPC_REQUEST_FromXML(in_buf, len, in_options);
742
743 if(req) {
744 xResponse = req->io;
745 XMLRPC_RequestFree(req, 0);
746 }
747 return xResponse;
748 }
749
750 /*******/
751
752 /* map parser errors to standard xml-rpc errors */
map_expat_errors(XML_ELEM_ERROR error)753 static XMLRPC_VALUE map_expat_errors(XML_ELEM_ERROR error) {
754 XMLRPC_VALUE xReturn = NULL;
755 if(error) {
756 XMLRPC_ERROR_CODE code;
757 char buf[1024];
758 snprintf(buf, sizeof(buf),
759 "error occurred at line %ld, column %ld, byte index %ld",
760 error->line, error->column, error->byte_index);
761
762 /* expat specific errors */
763 switch(error->parser_code) {
764 case XML_ERROR_UNKNOWN_ENCODING:
765 code = xmlrpc_error_parse_unknown_encoding;
766 break;
767 case XML_ERROR_INCORRECT_ENCODING:
768 code = xmlrpc_error_parse_bad_encoding;
769 break;
770 default:
771 code = xmlrpc_error_parse_xml_syntax;
772 break;
773 }
774 xReturn = XMLRPC_UtilityCreateFault(code, buf);
775 }
776 return xReturn;
777 }
778
779 /****f* SERIALIZE/XMLRPC_REQUEST_FromXML
780 * NAME
781 * XMLRPC_REQUEST_FromXML
782 * SYNOPSIS
783 * XMLRPC_REQUEST XMLRPC_REQUEST_FromXML(const char* in_buf, int le
784 * FUNCTION
785 * Retrieve XMLRPC_REQUEST from XML buffer
786 * INPUTS
787 * in_buf -- character buffer containing XML
788 * len -- length of buffer
789 * RESULT
790 * XMLRPC_REQUEST -- newly allocated data, or NULL if error. Should
791 * be free'd by caller.
792 * SEE ALSO
793 * XMLRPC_REQUEST_ToXML ()
794 * XMLRPC_VALUE_FromXML ()
795 * XMLRPC_REQUEST
796 * SOURCE
797 */
XMLRPC_REQUEST_FromXML(const char * in_buf,int len,XMLRPC_REQUEST_INPUT_OPTIONS in_options)798 XMLRPC_REQUEST XMLRPC_REQUEST_FromXML (const char *in_buf, int len,
799 XMLRPC_REQUEST_INPUT_OPTIONS in_options) {
800 XMLRPC_REQUEST request = XMLRPC_RequestNew();
801 STRUCT_XML_ELEM_ERROR error = {0};
802
803 if(request) {
804 xml_element *root_elem =
805 xml_elem_parse_buf (in_buf, len,
806 (in_options ? &in_options->xml_elem_opts : NULL),
807 &error);
808
809 if(root_elem) {
810 if(!strcmp(root_elem->name, "simpleRPC")) {
811 request->output.version = xmlrpc_version_simple;
812 xml_element_to_DANDARPC_REQUEST(request, root_elem);
813 }
814 else if (!strcmp (root_elem->name, "SOAP-ENV:Envelope")) {
815 request->output.version = xmlrpc_version_soap_1_1;
816 xml_element_to_SOAP_REQUEST (request, root_elem);
817 }
818 else {
819 request->output.version = xmlrpc_version_1_0;
820 xml_element_to_XMLRPC_REQUEST(request, root_elem);
821 }
822 xml_elem_free(root_elem);
823 }
824 else {
825 if(error.parser_error) {
826 XMLRPC_RequestSetError (request, map_expat_errors (&error));
827 }
828 }
829 }
830
831 return request;
832 }
833
834 /*******/
835
836 /*-************************
837 * End Serialization Funcs *
838 **************************/
839
840
841
842 /****f* VALUE/XMLRPC_CreateValueEmpty
843 * NAME
844 * XMLRPC_CreateValueEmpty
845 * SYNOPSIS
846 * XMLRPC_VALUE XMLRPC_CreateValueEmpty ()
847 * FUNCTION
848 * Create an XML value to be used/modified elsewhere.
849 * INPUTS
850 * RESULT
851 * XMLRPC_VALUE. The new value, or NULL on failure.
852 * SEE ALSO
853 * XMLRPC_CleanupValue ()
854 * XMLRPC_VALUE
855 * SOURCE
856 */
XMLRPC_CreateValueEmpty()857 XMLRPC_VALUE XMLRPC_CreateValueEmpty() {
858 XMLRPC_VALUE v = ecalloc(1, sizeof(STRUCT_XMLRPC_VALUE));
859 if(v) {
860 #ifdef XMLRPC_DEBUG_REFCOUNT
861 printf ("calloc'd 0x%x\n", v);
862 #endif
863 v->type = xmlrpc_empty;
864 simplestring_init(&v->id);
865 simplestring_init(&v->str);
866 }
867 return v;
868 }
869
870 /*******/
871
872 /****f* VALUE/XMLRPC_SetValueID_Case
873 * NAME
874 * XMLRPC_SetValueID_Case
875 * SYNOPSIS
876 * const char *XMLRPC_SetValueID_Case(XMLRPC_VALUE value, const char* id, int len, XMLRPC_CASE id_case)
877 * FUNCTION
878 * Assign an ID (key) to an XMLRPC value.
879 * INPUTS
880 * value The xml value who's ID we will set.
881 * id The desired new id.
882 * len length of id string if known, or 0 if unknown.
883 * id_case one of XMLRPC_CASE
884 * RESULT
885 * const char* pointer to the newly allocated id string, or NULL
886 * SEE ALSO
887 * XMLRPC_SetValueID ()
888 * XMLRPC_GetValueID ()
889 * XMLRPC_VALUE
890 * XMLRPC_CASE
891 * SOURCE
892 */
XMLRPC_SetValueID_Case(XMLRPC_VALUE value,const char * id,int len,XMLRPC_CASE id_case)893 const char *XMLRPC_SetValueID_Case(XMLRPC_VALUE value, const char* id, int len, XMLRPC_CASE id_case) {
894 const char* pRetval = NULL;
895 if(value) {
896 if(id) {
897 simplestring_clear(&value->id);
898 (len > 0) ? simplestring_addn(&value->id, id, len) :
899 simplestring_add(&value->id, id);
900
901 /* upper or lower case string in place if required. could be a separate func. */
902 if(id_case == xmlrpc_case_lower || id_case == xmlrpc_case_upper) {
903 int i;
904 for(i = 0; i < value->id.len; i++) {
905 value->id.str[i] =
906 (id_case ==
907 xmlrpc_case_lower) ? tolower (value->id.
908 str[i]) : toupper (value->
909 id.
910 str[i]);
911 }
912 }
913
914 pRetval = value->id.str;
915
916 #ifdef XMLRPC_DEBUG_REFCOUNT
917 printf("set value id: %s\n", pRetval);
918 #endif
919 }
920 }
921
922 return pRetval;
923 }
924
925 /*******/
926
927
928 /****f* VALUE/XMLRPC_SetValueString
929 * NAME
930 * XMLRPC_SetValueString
931 * SYNOPSIS
932 * const char *XMLRPC_SetValueString(XMLRPC_VALUE value, const char* val, int len)
933 * FUNCTION
934 * Assign a string value to an XMLRPC_VALUE, and set it to type xmlrpc_string
935 * INPUTS
936 * value The xml value who's ID we will set.
937 * val The desired new string val.
938 * len length of val string if known, or 0 if unknown.
939 * RESULT
940 * const char* pointer to the newly allocated value string, or NULL
941 * SEE ALSO
942 * XMLRPC_GetValueString ()
943 * XMLRPC_VALUE
944 * XMLRPC_VALUE_TYPE
945 * SOURCE
946 */
XMLRPC_SetValueString(XMLRPC_VALUE value,const char * val,int len)947 const char *XMLRPC_SetValueString(XMLRPC_VALUE value, const char* val, int len) {
948 char *pRetval = NULL;
949 if(value && val) {
950 simplestring_clear(&value->str);
951 (len > 0) ? simplestring_addn(&value->str, val, len) :
952 simplestring_add(&value->str, val);
953 value->type = xmlrpc_string;
954 pRetval = (char *)value->str.str;
955 }
956
957 return pRetval;
958 }
959
960 /*******/
961
962 /****f* VALUE/XMLRPC_SetValueInt
963 * NAME
964 * XMLRPC_SetValueInt
965 * SYNOPSIS
966 * void XMLRPC_SetValueInt(XMLRPC_VALUE value, int val)
967 * FUNCTION
968 * Assign an int value to an XMLRPC_VALUE, and set it to type xmlrpc_int
969 * INPUTS
970 * value The xml value who's ID we will set.
971 * val The desired new integer value
972 * RESULT
973 * SEE ALSO
974 * XMLRPC_GetValueInt ()
975 * XMLRPC_VALUE
976 * XMLRPC_VALUE_TYPE
977 * SOURCE
978 */
XMLRPC_SetValueInt(XMLRPC_VALUE value,int val)979 void XMLRPC_SetValueInt(XMLRPC_VALUE value, int val) {
980 if(value) {
981 value->type = xmlrpc_int;
982 value->i = val;
983 }
984 }
985
986 /*******/
987
988 /****f* VALUE/XMLRPC_SetValueBoolean
989 * NAME
990 * XMLRPC_SetValueBoolean
991 * SYNOPSIS
992 * void XMLRPC_SetValueBoolean(XMLRPC_VALUE value, int val)
993 * FUNCTION
994 * Assign a boolean value to an XMLRPC_VALUE, and set it to type xmlrpc_boolean
995 * INPUTS
996 * value The xml value who's value we will set.
997 * val The desired new boolean value. [0 | 1]
998 * RESULT
999 * SEE ALSO
1000 * XMLRPC_GetValueBoolean ()
1001 * XMLRPC_VALUE
1002 * XMLRPC_VALUE_TYPE
1003 * SOURCE
1004 */
XMLRPC_SetValueBoolean(XMLRPC_VALUE value,int val)1005 void XMLRPC_SetValueBoolean(XMLRPC_VALUE value, int val) {
1006 if(value) {
1007 value->type = xmlrpc_boolean;
1008 value->i = val ? 1 : 0;
1009 }
1010 }
1011
1012 /*******/
1013
1014
1015 /****f* VECTOR/XMLRPC_SetIsVector
1016 * NAME
1017 * XMLRPC_SetIsVector
1018 * SYNOPSIS
1019 * int XMLRPC_SetIsVector(XMLRPC_VALUE value, XMLRPC_VECTOR_TYPE type)
1020 * FUNCTION
1021 * Set the XMLRPC_VALUE to be a vector (list) type. The vector may be one of
1022 * [xmlrpc_array | xmlrpc_struct | xmlrpc_mixed]. An array has only index values.
1023 * A struct has key/val pairs. Mixed allows both index and key/val combinations.
1024 * INPUTS
1025 * value The xml value who's vector type we will set
1026 * type New type of vector as enumerated by XMLRPC_VECTOR_TYPE
1027 * RESULT
1028 * int 1 if successful, 0 otherwise
1029 * SEE ALSO
1030 * XMLRPC_GetValueType ()
1031 * XMLRPC_GetVectorType ()
1032 * XMLRPC_VALUE
1033 * XMLRPC_VECTOR_TYPE
1034 * XMLRPC_VALUE_TYPE
1035 * SOURCE
1036 */
XMLRPC_SetIsVector(XMLRPC_VALUE value,XMLRPC_VECTOR_TYPE type)1037 int XMLRPC_SetIsVector(XMLRPC_VALUE value, XMLRPC_VECTOR_TYPE type) {
1038 int bSuccess = 0;
1039
1040 if (value) {
1041 /* we can change the type so long as nothing is currently stored. */
1042 if(value->type == xmlrpc_vector) {
1043 if(value->v) {
1044 if(!Q_Size(value->v->q)) {
1045 value->v->type = type;
1046 }
1047 }
1048 }
1049 else {
1050 value->v = ecalloc(1, sizeof(STRUCT_XMLRPC_VECTOR));
1051 if(value->v) {
1052 value->v->q = (queue*)emalloc(sizeof(queue));
1053 if(value->v->q) {
1054 Q_Init(value->v->q);
1055 value->v->type = type;
1056 value->type = xmlrpc_vector;
1057 bSuccess = 1;
1058 }
1059 }
1060 }
1061 }
1062
1063 return bSuccess;
1064 }
1065
1066 /*******/
1067
1068 /****f* VECTOR/XMLRPC_CreateVector
1069 * NAME
1070 * XMLRPC_CreateVector
1071 * SYNOPSIS
1072 * XMLRPC_VALUE XMLRPC_CreateVector(const char* id, XMLRPC_VECTOR_TYPE type)
1073 * FUNCTION
1074 * Create a new vector and optionally set an id.
1075 * INPUTS
1076 * id The id of the vector, or NULL
1077 * type New type of vector as enumerated by XMLRPC_VECTOR_TYPE
1078 * RESULT
1079 * XMLRPC_VALUE The new vector, or NULL on failure.
1080 * SEE ALSO
1081 * XMLRPC_CreateValueEmpty ()
1082 * XMLRPC_SetIsVector ()
1083 * XMLRPC_GetValueType ()
1084 * XMLRPC_GetVectorType ()
1085 * XMLRPC_VALUE
1086 * XMLRPC_VECTOR_TYPE
1087 * XMLRPC_VALUE_TYPE
1088 * SOURCE
1089 */
XMLRPC_CreateVector(const char * id,XMLRPC_VECTOR_TYPE type)1090 XMLRPC_VALUE XMLRPC_CreateVector(const char* id, XMLRPC_VECTOR_TYPE type) {
1091 XMLRPC_VALUE val = NULL;
1092
1093 val = XMLRPC_CreateValueEmpty();
1094 if(val) {
1095 if(XMLRPC_SetIsVector(val, type)) {
1096 if(id) {
1097 const char *pSVI = NULL;
1098
1099 pSVI = XMLRPC_SetValueID(val, id, 0);
1100 if(NULL == pSVI) {
1101 val = NULL;
1102 }
1103 }
1104 }
1105 else {
1106 val = NULL;
1107 }
1108 }
1109 return val;
1110 }
1111
1112 /*******/
1113
1114
1115 /* Not yet implemented.
1116 *
1117 * This should use a hash to determine if a given target id has already
1118 * been appended.
1119 *
1120 * Alternately, it could walk the entire vector, but that could be quite
1121 * slow for very large lists.
1122 */
isDuplicateEntry(XMLRPC_VALUE target,XMLRPC_VALUE source)1123 static int isDuplicateEntry(XMLRPC_VALUE target, XMLRPC_VALUE source) {
1124 return 0;
1125 }
1126
1127 /****f* VECTOR/XMLRPC_AddValueToVector
1128 * NAME
1129 * XMLRPC_AddValueToVector
1130 * SYNOPSIS
1131 * int XMLRPC_AddValueToVector(XMLRPC_VALUE target, XMLRPC_VALUE source)
1132 * FUNCTION
1133 * Add (append) an existing XMLRPC_VALUE to a vector.
1134 * INPUTS
1135 * target The target vector
1136 * source The source value to append
1137 * RESULT
1138 * int 1 if successful, else 0
1139 * SEE ALSO
1140 * XMLRPC_AddValuesToVector ()
1141 * XMLRPC_VectorGetValueWithID_Case ()
1142 * XMLRPC_VALUE
1143 * NOTES
1144 * The function will fail and return 0 if an attempt is made to add
1145 * a value with an ID into a vector of type xmlrpc_vector_array. Such
1146 * values can only be added to xmlrpc_vector_struct.
1147 * SOURCE
1148 */
XMLRPC_AddValueToVector(XMLRPC_VALUE target,XMLRPC_VALUE source)1149 int XMLRPC_AddValueToVector(XMLRPC_VALUE target, XMLRPC_VALUE source) {
1150 if(target && source) {
1151 if(target->type == xmlrpc_vector && target->v &&
1152 target->v->q && target->v->type != xmlrpc_vector_none) {
1153
1154 /* guard against putting value of unknown type into vector */
1155 switch(source->type) {
1156 case xmlrpc_empty:
1157 case xmlrpc_base64:
1158 case xmlrpc_boolean:
1159 case xmlrpc_datetime:
1160 case xmlrpc_double:
1161 case xmlrpc_int:
1162 case xmlrpc_string:
1163 case xmlrpc_vector:
1164 /* Guard against putting a key/val pair into an array vector */
1165 if( !(source->id.len && target->v->type == xmlrpc_vector_array) ) {
1166 if (isDuplicateEntry (target, source)
1167 || Q_PushTail (target->v->q, XMLRPC_CopyValue (source))) {
1168 return 1;
1169 }
1170 }
1171 else {
1172 /* fprintf (stderr,
1173 "xmlrpc: attempted to add key/val pair to vector of type array\n"); */
1174 }
1175 break;
1176 default:
1177 /* fprintf (stderr,
1178 "xmlrpc: attempted to add value of unknown type to vector\n"); */
1179 break;
1180 }
1181 }
1182 }
1183 return 0;
1184 }
1185
1186 /*******/
1187
1188
1189 /****f* VECTOR/XMLRPC_AddValuesToVector
1190 * NAME
1191 * XMLRPC_AddValuesToVector
1192 * SYNOPSIS
1193 * XMLRPC_AddValuesToVector ( target, val1, val2, val3, val(n), 0 )
1194 * XMLRPC_AddValuesToVector( XMLRPC_VALUE, ... )
1195 * FUNCTION
1196 * Add (append) a series of existing XMLRPC_VALUE to a vector.
1197 * INPUTS
1198 * target The target vector
1199 * ... The source value(s) to append. The last item *must* be 0.
1200 * RESULT
1201 * int 1 if successful, else 0
1202 * SEE ALSO
1203 * XMLRPC_AddValuesToVector ()
1204 * XMLRPC_VectorGetValueWithID_Case ()
1205 * XMLRPC_VALUE
1206 * NOTES
1207 * This function may actually return failure after it has already modified
1208 * or added items to target. You can not trust the state of target
1209 * if this function returns failure.
1210 * SOURCE
1211 */
XMLRPC_AddValuesToVector(XMLRPC_VALUE target,...)1212 int XMLRPC_AddValuesToVector(XMLRPC_VALUE target, ...) {
1213 int iRetval = 0;
1214
1215 if(target) {
1216 if(target->type == xmlrpc_vector) {
1217 XMLRPC_VALUE v = NULL;
1218 va_list vl;
1219
1220 va_start(vl, target);
1221
1222 do {
1223 v = va_arg(vl, XMLRPC_VALUE);
1224 if(v) {
1225 if(!XMLRPC_AddValueToVector(target, v)) {
1226 iRetval = 0;
1227 break;
1228 }
1229 }
1230 }
1231 while (v);
1232
1233 va_end(vl);
1234
1235 if(NULL == v) {
1236 iRetval = 1;
1237 }
1238 }
1239 }
1240 return iRetval;
1241 }
1242
1243 /*******/
1244
1245
1246 /****f* VECTOR/XMLRPC_VectorGetValueWithID_Case
1247 * NAME
1248 * XMLRPC_VectorGetValueWithID_Case
1249 * SYNOPSIS
1250 * XMLRPC_VALUE XMLRPC_VectorGetValueWithID_Case(XMLRPC_VALUE vector, const char* id, XMLRPC_CASE_COMPARISON id_case)
1251 * FUNCTION
1252 * Get value from vector matching id (key)
1253 * INPUTS
1254 * vector The source vector
1255 * id The key to find
1256 * id_case Rule for how to match key
1257 * RESULT
1258 * int 1 if successful, else 0
1259 * SEE ALSO
1260 * XMLRPC_SetValueID_Case ()
1261 * XMLRPC_VALUE
1262 * XMLRPC_CASE_COMPARISON
1263 * SOURCE
1264 */
XMLRPC_VectorGetValueWithID_Case(XMLRPC_VALUE vector,const char * id,XMLRPC_CASE_COMPARISON id_case)1265 XMLRPC_VALUE XMLRPC_VectorGetValueWithID_Case (XMLRPC_VALUE vector, const char *id,
1266 XMLRPC_CASE_COMPARISON id_case) {
1267 if(vector && vector->v && vector->v->q) {
1268 q_iter qi = Q_Iter_Head_F(vector->v->q);
1269
1270 while(qi) {
1271 XMLRPC_VALUE xIter = Q_Iter_Get_F(qi);
1272 if(xIter && xIter->id.str) {
1273 if(id_case == xmlrpc_case_sensitive) {
1274 if(!strcmp(xIter->id.str, id)) {
1275 return xIter;
1276 }
1277 }
1278 else if(id_case == xmlrpc_case_insensitive) {
1279 if(!strcasecmp(xIter->id.str, id)) {
1280 return xIter;
1281 }
1282 }
1283 }
1284 qi = Q_Iter_Next_F(qi);
1285 }
1286 }
1287 return NULL;
1288 }
1289
1290 /*******/
1291
1292
XMLRPC_VectorRemoveValue(XMLRPC_VALUE vector,XMLRPC_VALUE value)1293 int XMLRPC_VectorRemoveValue(XMLRPC_VALUE vector, XMLRPC_VALUE value) {
1294 if(vector && vector->v && vector->v->q && value) {
1295 q_iter qi = Q_Iter_Head_F(vector->v->q);
1296
1297 while(qi) {
1298 XMLRPC_VALUE xIter = Q_Iter_Get_F(qi);
1299 if(xIter == value) {
1300 XMLRPC_CleanupValue(xIter);
1301 Q_Iter_Del(vector->v->q, qi);
1302 return 1;
1303 }
1304 qi = Q_Iter_Next_F(qi);
1305 }
1306 }
1307 return 0;
1308 }
1309
1310
1311 /****f* VALUE/XMLRPC_CreateValueString
1312 * NAME
1313 * XMLRPC_CreateValueString
1314 * SYNOPSIS
1315 * XMLRPC_VALUE XMLRPC_CreateValueString(const char* id, const char* val, int len)
1316 * FUNCTION
1317 * Create an XMLRPC_VALUE, and assign a string to it
1318 * INPUTS
1319 * id The id of the value, or NULL
1320 * val The desired new string val.
1321 * len length of val string if known, or 0 if unknown.
1322 * RESULT
1323 * newly allocated XMLRPC_VALUE, or NULL
1324 * SEE ALSO
1325 * XMLRPC_GetValueString ()
1326 * XMLRPC_CreateValueEmpty ()
1327 * XMLRPC_VALUE
1328 * XMLRPC_VALUE_TYPE
1329 * SOURCE
1330 */
XMLRPC_CreateValueString(const char * id,const char * val,int len)1331 XMLRPC_VALUE XMLRPC_CreateValueString(const char* id, const char* val, int len) {
1332 XMLRPC_VALUE value = NULL;
1333 if(val) {
1334 value = XMLRPC_CreateValueEmpty();
1335 if(value) {
1336 XMLRPC_SetValueString(value, val, len);
1337 if(id) {
1338 XMLRPC_SetValueID(value, id, 0);
1339 }
1340 }
1341 }
1342 return value;
1343 }
1344
1345 /*******/
1346
1347 /****f* VALUE/XMLRPC_CreateValueInt
1348 * NAME
1349 * XMLRPC_CreateValueInt
1350 * SYNOPSIS
1351 * XMLRPC_VALUE XMLRPC_CreateValueInt(const char* id, int i)
1352 * FUNCTION
1353 * Create an XMLRPC_VALUE, and assign an int to it
1354 * INPUTS
1355 * id The id of the value, or NULL
1356 * i The desired new int val.
1357 * RESULT
1358 * newly allocated XMLRPC_VALUE, or NULL
1359 * SEE ALSO
1360 * XMLRPC_GetValueInt ()
1361 * XMLRPC_CreateValueEmpty ()
1362 * XMLRPC_VALUE
1363 * XMLRPC_VALUE_TYPE
1364 * SOURCE
1365 */
XMLRPC_CreateValueInt(const char * id,int i)1366 XMLRPC_VALUE XMLRPC_CreateValueInt(const char* id, int i) {
1367 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1368 if(val) {
1369 XMLRPC_SetValueInt(val, i);
1370 if(id) {
1371 XMLRPC_SetValueID(val, id, 0);
1372 }
1373 }
1374 return val;
1375 }
1376
1377 /*******/
1378
1379 /****f* VALUE/XMLRPC_CreateValueBoolean
1380 * NAME
1381 * XMLRPC_CreateValueBoolean
1382 * SYNOPSIS
1383 * XMLRPC_VALUE XMLRPC_CreateValueBoolean(const char* id, int i)
1384 * FUNCTION
1385 * Create an XMLRPC_VALUE, and assign an int to it
1386 * INPUTS
1387 * id The id of the value, or NULL
1388 * i The desired new int val.
1389 * RESULT
1390 * newly allocated XMLRPC_VALUE, or NULL
1391 * SEE ALSO
1392 * XMLRPC_GetValueBoolean ()
1393 * XMLRPC_CreateValueEmpty ()
1394 * XMLRPC_VALUE
1395 * XMLRPC_VALUE_TYPE
1396 * SOURCE
1397 */
XMLRPC_CreateValueBoolean(const char * id,int i)1398 XMLRPC_VALUE XMLRPC_CreateValueBoolean(const char* id, int i) {
1399 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1400 if(val) {
1401 XMLRPC_SetValueBoolean(val, i);
1402 if(id) {
1403 XMLRPC_SetValueID(val, id, 0);
1404 }
1405 }
1406 return val;
1407 }
1408
1409 /*******/
1410
1411
1412 /****f* VALUE/XMLRPC_CleanupValue
1413 * NAME
1414 * XMLRPC_CleanupValue
1415 * SYNOPSIS
1416 * void XMLRPC_CleanupValue(XMLRPC_VALUE value)
1417 * FUNCTION
1418 * Frees all memory allocated for an XMLRPC_VALUE and any of its children (if a vector)
1419 * INPUTS
1420 * value The id of the value to be cleaned up.
1421 * RESULT
1422 * void
1423 * NOTES
1424 * Normally this function will be called for the topmost vector, thus free-ing
1425 * all children. If a child of a vector is free'd first, results are undefined.
1426 * Failure to call this function *will* cause memory leaks.
1427 *
1428 * Also, this function is implemented using reference counting. Thus a value
1429 * may be added and freed from multiple parents so long as a reference is added
1430 * first using XMLRPC_CopyValue()
1431 * SEE ALSO
1432 * XMLRPC_RequestFree ()
1433 * XMLRPC_CreateValueEmpty ()
1434 * XMLRPC_CopyValue()
1435 * XMLRPC_VALUE
1436 * SOURCE
1437 */
XMLRPC_CleanupValue(XMLRPC_VALUE value)1438 void XMLRPC_CleanupValue(XMLRPC_VALUE value) {
1439 if(value) {
1440 if(value->iRefCount > 0) {
1441 value->iRefCount --;
1442 }
1443
1444 #ifdef XMLRPC_DEBUG_REFCOUNT
1445 if(value->id.str) {
1446 printf ("decremented refcount of %s, now %i\n", value->id.str,
1447 value->iRefCount);
1448 }
1449 else {
1450 printf ("decremented refcount of 0x%x, now %i\n", value,
1451 value->iRefCount);
1452 }
1453 #endif
1454
1455 if(value->type == xmlrpc_vector) {
1456 if(value->v) {
1457 if(value->iRefCount == 0) {
1458 XMLRPC_VALUE cur = (XMLRPC_VALUE)Q_Head(value->v->q);
1459 while( cur ) {
1460 XMLRPC_CleanupValue(cur);
1461
1462 /* Make sure some idiot didn't include a vector as a child of itself
1463 * and thus it would have already free'd these.
1464 */
1465 if(value->v && value->v->q) {
1466 cur = Q_Next(value->v->q);
1467 }
1468 else {
1469 break;
1470 }
1471 }
1472
1473 Q_Destroy(value->v->q);
1474 my_free(value->v->q);
1475 my_free(value->v);
1476 }
1477 }
1478 }
1479
1480
1481 if(value->iRefCount == 0) {
1482
1483 /* guard against freeing invalid types */
1484 switch(value->type) {
1485 case xmlrpc_empty:
1486 case xmlrpc_base64:
1487 case xmlrpc_boolean:
1488 case xmlrpc_datetime:
1489 case xmlrpc_double:
1490 case xmlrpc_int:
1491 case xmlrpc_string:
1492 case xmlrpc_vector:
1493 #ifdef XMLRPC_DEBUG_REFCOUNT
1494 if(value->id.str) {
1495 printf("free'd %s\n", value->id.str);
1496 }
1497 else {
1498 printf("free'd 0x%x\n", value);
1499 }
1500 #endif
1501 simplestring_free(&value->id);
1502 simplestring_free(&value->str);
1503
1504 memset(value, 0, sizeof(STRUCT_XMLRPC_VALUE));
1505 my_free(value);
1506 break;
1507 default:
1508 /* fprintf (stderr,
1509 "xmlrpc: attempted to free value of invalid type\n"); */
1510 break;
1511 }
1512 }
1513 }
1514 }
1515
1516 /*******/
1517
1518
1519 /****f* VALUE/XMLRPC_SetValueDateTime
1520 * NAME
1521 * XMLRPC_SetValueDateTime
1522 * SYNOPSIS
1523 * void XMLRPC_SetValueDateTime(XMLRPC_VALUE value, time_t time)
1524 * FUNCTION
1525 * Assign time value to XMLRPC_VALUE
1526 * INPUTS
1527 * value The target XMLRPC_VALUE
1528 * time The desired new unix time value (time_t)
1529 * RESULT
1530 * void
1531 * SEE ALSO
1532 * XMLRPC_GetValueDateTime ()
1533 * XMLRPC_SetValueDateTime_ISO8601 ()
1534 * XMLRPC_CreateValueDateTime ()
1535 * XMLRPC_VALUE
1536 * SOURCE
1537 */
XMLRPC_SetValueDateTime(XMLRPC_VALUE value,time_t time)1538 void XMLRPC_SetValueDateTime(XMLRPC_VALUE value, time_t time) {
1539 if(value) {
1540 char timeBuf[30];
1541 value->type = xmlrpc_datetime;
1542 value->i = time;
1543
1544 timeBuf[0] = 0;
1545
1546 date_to_ISO8601(time, timeBuf, sizeof(timeBuf));
1547
1548 if(timeBuf[0]) {
1549 XMLRPC_SetValueDateTime_ISO8601 (value, timeBuf);
1550 }
1551 }
1552 }
1553
1554 /*******/
1555
1556 /****f* VALUE/XMLRPC_CopyValue
1557 * NAME
1558 * XMLRPC_CopyValue
1559 * SYNOPSIS
1560 * XMLRPC_VALUE XMLRPC_CopyValue(XMLRPC_VALUE value)
1561 * FUNCTION
1562 * Make a copy (reference) of an XMLRPC_VALUE
1563 * INPUTS
1564 * value The target XMLRPC_VALUE
1565 * RESULT
1566 * XMLRPC_VALUE -- address of the copy
1567 * SEE ALSO
1568 * XMLRPC_CleanupValue ()
1569 * XMLRPC_DupValueNew ()
1570 * NOTES
1571 * This function is implemented via reference counting, so the
1572 * returned value is going to be the same as the passed in value.
1573 * The value must be freed the same number of times it is copied
1574 * or there will be a memory leak.
1575 * SOURCE
1576 */
XMLRPC_CopyValue(XMLRPC_VALUE value)1577 XMLRPC_VALUE XMLRPC_CopyValue(XMLRPC_VALUE value) {
1578 if(value) {
1579 value->iRefCount ++;
1580 #ifdef XMLRPC_DEBUG_REFCOUNT
1581 if(value->id.str) {
1582 printf ("incremented refcount of %s, now %i\n", value->id.str,
1583 value->iRefCount);
1584 }
1585 else {
1586 printf ("incremented refcount of 0x%x, now %i\n", value,
1587 value->iRefCount);
1588 }
1589 #endif
1590 }
1591 return value;
1592 }
1593
1594 /*******/
1595
1596
1597 /****f* VALUE/XMLRPC_DupValueNew
1598 * NAME
1599 * XMLRPC_DupValueNew
1600 * SYNOPSIS
1601 * XMLRPC_VALUE XMLRPC_DupValueNew(XMLRPC_VALUE value)
1602 * FUNCTION
1603 * Make a duplicate (non reference) of an XMLRPC_VALUE with newly allocated mem.
1604 * INPUTS
1605 * value The source XMLRPC_VALUE to duplicate
1606 * RESULT
1607 * XMLRPC_VALUE -- address of the duplicate value
1608 * SEE ALSO
1609 * XMLRPC_CleanupValue ()
1610 * XMLRPC_CopyValue ()
1611 * NOTES
1612 * Use this when function when you need to modify the contents of
1613 * the copied value separately from the original.
1614 *
1615 * this function is recursive, thus the value and all of its children
1616 * (if any) will be duplicated.
1617 * SOURCE
1618 */
XMLRPC_DupValueNew(XMLRPC_VALUE xSource)1619 XMLRPC_VALUE XMLRPC_DupValueNew (XMLRPC_VALUE xSource) {
1620 XMLRPC_VALUE xReturn = NULL;
1621 if (xSource) {
1622 xReturn = XMLRPC_CreateValueEmpty ();
1623 if (xSource->id.len) {
1624 XMLRPC_SetValueID (xReturn, xSource->id.str, xSource->id.len);
1625 }
1626
1627 switch (xSource->type) {
1628 case xmlrpc_int:
1629 case xmlrpc_boolean:
1630 XMLRPC_SetValueInt (xReturn, xSource->i);
1631 break;
1632 case xmlrpc_string:
1633 case xmlrpc_base64:
1634 XMLRPC_SetValueString (xReturn, xSource->str.str, xSource->str.len);
1635 break;
1636 case xmlrpc_datetime:
1637 XMLRPC_SetValueDateTime (xReturn, xSource->i);
1638 break;
1639 case xmlrpc_double:
1640 XMLRPC_SetValueDouble (xReturn, xSource->d);
1641 break;
1642 case xmlrpc_vector:
1643 {
1644 q_iter qi = Q_Iter_Head_F (xSource->v->q);
1645 XMLRPC_SetIsVector (xReturn, xSource->v->type);
1646
1647 while (qi) {
1648 XMLRPC_VALUE xIter = Q_Iter_Get_F (qi);
1649 XMLRPC_AddValueToVector (xReturn, XMLRPC_DupValueNew (xIter));
1650 qi = Q_Iter_Next_F (qi);
1651 }
1652 }
1653 break;
1654 default:
1655 break;
1656 }
1657 }
1658 return xReturn;
1659 }
1660
1661 /*******/
1662
1663
1664
1665 /****f* VALUE/XMLRPC_CreateValueDateTime
1666 * NAME
1667 * XMLRPC_CreateValueDateTime
1668 * SYNOPSIS
1669 * XMLRPC_VALUE XMLRPC_CreateValueDateTime(const char* id, time_t time)
1670 * FUNCTION
1671 * Create new datetime value from time_t
1672 * INPUTS
1673 * id id of the new value, or NULL
1674 * time The desired unix time value (time_t)
1675 * RESULT
1676 * void
1677 * SEE ALSO
1678 * XMLRPC_GetValueDateTime ()
1679 * XMLRPC_SetValueDateTime ()
1680 * XMLRPC_CreateValueDateTime_ISO8601 ()
1681 * XMLRPC_VALUE
1682 * SOURCE
1683 */
XMLRPC_CreateValueDateTime(const char * id,time_t time)1684 XMLRPC_VALUE XMLRPC_CreateValueDateTime(const char* id, time_t time) {
1685 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1686 if(val) {
1687 XMLRPC_SetValueDateTime(val, time);
1688 if(id) {
1689 XMLRPC_SetValueID(val, id, 0);
1690 }
1691 }
1692 return val;
1693 }
1694
1695 /*******/
1696
1697
1698 /****f* VALUE/XMLRPC_SetValueDateTime_ISO8601
1699 * NAME
1700 * XMLRPC_SetValueDateTime_ISO8601
1701 * SYNOPSIS
1702 * void XMLRPC_SetValueDateTime_ISO8601(XMLRPC_VALUE value, const char* s)
1703 * FUNCTION
1704 * Set datetime value from IS08601 encoded string
1705 * INPUTS
1706 * value The target XMLRPC_VALUE
1707 * s The desired new time value
1708 * RESULT
1709 * void
1710 * BUGS
1711 * This function currently attempts to convert the time string to a valid unix time
1712 * value before passing it. Behavior when the string is invalid or out of range
1713 * is not well defined, but will probably result in Jan 1, 1970 (0) being passed.
1714 * SEE ALSO
1715 * XMLRPC_GetValueDateTime_ISO8601 ()
1716 * XMLRPC_CreateValueDateTime_ISO8601 ()
1717 * XMLRPC_CreateValueDateTime ()
1718 * XMLRPC_VALUE
1719 * SOURCE
1720 */
XMLRPC_SetValueDateTime_ISO8601(XMLRPC_VALUE value,const char * s)1721 void XMLRPC_SetValueDateTime_ISO8601(XMLRPC_VALUE value, const char* s) {
1722 if(value) {
1723 time_t time_val = 0;
1724 if(s) {
1725 value->type = xmlrpc_datetime;
1726 date_from_ISO8601(s, &time_val);
1727 value->i = time_val;
1728 simplestring_clear(&value->str);
1729 simplestring_add(&value->str, s);
1730 }
1731 }
1732 }
1733
1734 /*******/
1735
1736 /****f* VALUE/XMLRPC_CreateValueDateTime_ISO8601
1737 * NAME
1738 * XMLRPC_CreateValueDateTime_ISO8601
1739 * SYNOPSIS
1740 * XMLRPC_VALUE XMLRPC_CreateValueDateTime_ISO8601(const char* id, const char *s)
1741 * FUNCTION
1742 * Create datetime value from IS08601 encoded string
1743 * INPUTS
1744 * id The id of the new value, or NULL
1745 * s The desired new time value
1746 * RESULT
1747 * newly allocated XMLRPC_VALUE, or NULL if no value created.
1748 * BUGS
1749 * See XMLRPC_SetValueDateTime_ISO8601 ()
1750 * SEE ALSO
1751 * XMLRPC_GetValueDateTime_ISO8601 ()
1752 * XMLRPC_SetValueDateTime_ISO8601 ()
1753 * XMLRPC_CreateValueDateTime ()
1754 * XMLRPC_VALUE
1755 * SOURCE
1756 */
XMLRPC_CreateValueDateTime_ISO8601(const char * id,const char * s)1757 XMLRPC_VALUE XMLRPC_CreateValueDateTime_ISO8601(const char* id, const char *s) {
1758 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1759 if(val) {
1760 XMLRPC_SetValueDateTime_ISO8601(val, s);
1761 if(id) {
1762 XMLRPC_SetValueID(val, id, 0);
1763 }
1764 }
1765 return val;
1766 }
1767
1768 /*******/
1769
1770
1771 /****f* VALUE/XMLRPC_SetValueBase64
1772 * NAME
1773 * XMLRPC_SetValueBase64
1774 * SYNOPSIS
1775 * void XMLRPC_SetValueBase64(XMLRPC_VALUE value, const char* s, int len)
1776 * FUNCTION
1777 * Set base64 value. Base64 is useful for transferring binary data, such as an image.
1778 * INPUTS
1779 * value The target XMLRPC_VALUE
1780 * s The desired new binary value
1781 * len The length of s, or NULL. If buffer is not null terminated, len *must* be passed.
1782 * RESULT
1783 * void
1784 * NOTES
1785 * Data is set/stored/retrieved as passed in, but is base64 encoded for XML transfer, and
1786 * decoded on the other side. This is transparent to the caller.
1787 * SEE ALSO
1788 * XMLRPC_GetValueBase64 ()
1789 * XMLRPC_CreateValueBase64 ()
1790 * XMLRPC_VALUE
1791 * SOURCE
1792 */
XMLRPC_SetValueBase64(XMLRPC_VALUE value,const char * s,int len)1793 void XMLRPC_SetValueBase64(XMLRPC_VALUE value, const char* s, int len) {
1794 if(value && s) {
1795 simplestring_clear(&value->str);
1796 (len > 0) ? simplestring_addn(&value->str, s, len) :
1797 simplestring_add(&value->str, s);
1798 value->type = xmlrpc_base64;
1799 }
1800 }
1801
1802 /*******/
1803
1804
1805 /****f* VALUE/XMLRPC_CreateValueBase64
1806 * NAME
1807 * XMLRPC_CreateValueBase64
1808 * SYNOPSIS
1809 * XMLRPC_VALUE XMLRPC_CreateValueBase64(const char* id, const char* s, int len)
1810 * FUNCTION
1811 * Create base64 value. Base64 is useful for transferring binary data, such as an image.
1812 * INPUTS
1813 * id id of the new value, or NULL
1814 * s The desired new binary value
1815 * len The length of s, or NULL. If buffer is not null terminated, len *must* be passed.
1816 * RESULT
1817 * newly allocated XMLRPC_VALUE, or NULL if error
1818 * NOTES
1819 * See XMLRPC_SetValueBase64 ()
1820 * SEE ALSO
1821 * XMLRPC_GetValueBase64 ()
1822 * XMLRPC_SetValueBase64 ()
1823 * XMLRPC_VALUE
1824 * SOURCE
1825 */
XMLRPC_CreateValueBase64(const char * id,const char * s,int len)1826 XMLRPC_VALUE XMLRPC_CreateValueBase64(const char* id, const char* s, int len) {
1827 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1828 if(val) {
1829 XMLRPC_SetValueBase64(val, s, len);
1830 if(id) {
1831 XMLRPC_SetValueID(val, id, 0);
1832 }
1833 }
1834 return val;
1835 }
1836
1837 /*******/
1838
1839 /****f* VALUE/XMLRPC_SetValueDouble
1840 * NAME
1841 * XMLRPC_SetValueDouble
1842 * SYNOPSIS
1843 * void XMLRPC_SetValueDouble(XMLRPC_VALUE value, double val)
1844 * FUNCTION
1845 * Set double (floating point) value.
1846 * INPUTS
1847 * value The target XMLRPC_VALUE
1848 * val The desired new double value
1849 * RESULT
1850 * void
1851 * SEE ALSO
1852 * XMLRPC_GetValueDouble ()
1853 * XMLRPC_CreateValueDouble ()
1854 * XMLRPC_VALUE
1855 * SOURCE
1856 */
XMLRPC_SetValueDouble(XMLRPC_VALUE value,double val)1857 void XMLRPC_SetValueDouble(XMLRPC_VALUE value, double val) {
1858 if(value) {
1859 value->type = xmlrpc_double;
1860 value->d = val;
1861 }
1862 }
1863
1864 /*******/
1865
1866 /****f* VALUE/XMLRPC_CreateValueDouble
1867 * NAME
1868 * XMLRPC_CreateValueDouble
1869 * SYNOPSIS
1870 * XMLRPC_VALUE XMLRPC_CreateValueDouble(const char* id, double d)
1871 * FUNCTION
1872 * Create double (floating point) value.
1873 * INPUTS
1874 * id id of the newly created value, or NULL
1875 * d The desired new double value
1876 * RESULT
1877 * void
1878 * SEE ALSO
1879 * XMLRPC_GetValueDouble ()
1880 * XMLRPC_CreateValueDouble ()
1881 * XMLRPC_VALUE
1882 * SOURCE
1883 */
XMLRPC_CreateValueDouble(const char * id,double d)1884 XMLRPC_VALUE XMLRPC_CreateValueDouble(const char* id, double d) {
1885 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1886 if(val) {
1887 XMLRPC_SetValueDouble(val, d);
1888 if(id) {
1889 XMLRPC_SetValueID(val, id, 0);
1890 }
1891 }
1892 return val;
1893 }
1894
1895 /*******/
1896
1897 /****f* VALUE/XMLRPC_GetValueString
1898 * NAME
1899 * XMLRPC_GetValueString
1900 * SYNOPSIS
1901 * const char* XMLRPC_GetValueString(XMLRPC_VALUE value)
1902 * FUNCTION
1903 * retrieve string value
1904 * INPUTS
1905 * value source XMLRPC_VALUE of type xmlrpc_string
1906 * RESULT
1907 * void
1908 * SEE ALSO
1909 * XMLRPC_SetValueString ()
1910 * XMLRPC_GetValueType ()
1911 * XMLRPC_VALUE
1912 * SOURCE
1913 */
XMLRPC_GetValueString(XMLRPC_VALUE value)1914 const char* XMLRPC_GetValueString(XMLRPC_VALUE value) {
1915 return ((value && value->type == xmlrpc_string) ? value->str.str : 0);
1916 }
1917
1918 /*******/
1919
1920 /****f* VALUE/XMLRPC_GetValueStringLen
1921 * NAME
1922 * XMLRPC_GetValueStringLen
1923 * SYNOPSIS
1924 * int XMLRPC_GetValueStringLen(XMLRPC_VALUE value)
1925 * FUNCTION
1926 * determine length of string value
1927 * INPUTS
1928 * value XMLRPC_VALUE of type xmlrpc_string
1929 * RESULT
1930 * length of string, or 0
1931 * NOTES
1932 * SEE ALSO
1933 * XMLRPC_SetValueString ()
1934 * XMLRPC_GetValueString ()
1935 * SOURCE
1936 */
XMLRPC_GetValueStringLen(XMLRPC_VALUE value)1937 int XMLRPC_GetValueStringLen(XMLRPC_VALUE value) {
1938 return ((value) ? value->str.len : 0);
1939 }
1940
1941 /*******/
1942
1943 /****f* VALUE/XMLRPC_GetValueInt
1944 * NAME
1945 * XMLRPC_GetValueInt
1946 * SYNOPSIS
1947 * int XMLRPC_GetValueInt(XMLRPC_VALUE value)
1948 * FUNCTION
1949 * retrieve integer value.
1950 * INPUTS
1951 * value XMLRPC_VALUE of type xmlrpc_int
1952 * RESULT
1953 * integer value or 0 if value is not valid int
1954 * NOTES
1955 * use XMLRPC_GetValueType () to be sure if 0 is real return value or not
1956 * SEE ALSO
1957 * XMLRPC_SetValueInt ()
1958 * XMLRPC_CreateValueInt ()
1959 * SOURCE
1960 */
XMLRPC_GetValueInt(XMLRPC_VALUE value)1961 int XMLRPC_GetValueInt(XMLRPC_VALUE value) {
1962 return ((value && value->type == xmlrpc_int) ? value->i : 0);
1963 }
1964
1965 /*******/
1966
1967 /****f* VALUE/XMLRPC_GetValueBoolean
1968 * NAME
1969 * XMLRPC_GetValueBoolean
1970 * SYNOPSIS
1971 * int XMLRPC_GetValueBoolean(XMLRPC_VALUE value)
1972 * FUNCTION
1973 * retrieve boolean value.
1974 * INPUTS
1975 * XMLRPC_VALUE of type xmlrpc_boolean
1976 * RESULT
1977 * boolean value or 0 if value is not valid boolean
1978 * NOTES
1979 * use XMLRPC_GetValueType() to be sure if 0 is real value or not
1980 * SEE ALSO
1981 * XMLRPC_SetValueBoolean ()
1982 * XMLRPC_CreateValueBoolean ()
1983 * SOURCE
1984 */
XMLRPC_GetValueBoolean(XMLRPC_VALUE value)1985 int XMLRPC_GetValueBoolean(XMLRPC_VALUE value) {
1986 return ((value && value->type == xmlrpc_boolean) ? value->i : 0);
1987 }
1988
1989 /*******/
1990
1991 /****f* VALUE/XMLRPC_GetValueDouble
1992 * NAME
1993 * XMLRPC_GetValueDouble
1994 * SYNOPSIS
1995 * double XMLRPC_GetValueDouble(XMLRPC_VALUE value)
1996 * FUNCTION
1997 * retrieve double value
1998 * INPUTS
1999 * XMLRPC_VALUE of type xmlrpc_double
2000 * RESULT
2001 * double value or 0 if value is not valid double.
2002 * NOTES
2003 * use XMLRPC_GetValueType() to be sure if 0 is real value or not
2004 * SEE ALSO
2005 * XMLRPC_SetValueDouble ()
2006 * XMLRPC_CreateValueDouble ()
2007 * SOURCE
2008 */
XMLRPC_GetValueDouble(XMLRPC_VALUE value)2009 double XMLRPC_GetValueDouble(XMLRPC_VALUE value) {
2010 return ((value && value->type == xmlrpc_double) ? value->d : 0);
2011 }
2012
2013 /*******/
2014
2015 /****f* VALUE/XMLRPC_GetValueBase64
2016 * NAME
2017 * XMLRPC_GetValueBase64
2018 * SYNOPSIS
2019 * const char* XMLRPC_GetValueBase64(XMLRPC_VALUE value)
2020 * FUNCTION
2021 * retrieve binary value
2022 * INPUTS
2023 * XMLRPC_VALUE of type xmlrpc_base64
2024 * RESULT
2025 * pointer to binary value or 0 if value is not valid.
2026 * SEE ALSO
2027 * XMLRPC_SetValueBase64 ()
2028 * XMLRPC_CreateValueBase64 ()
2029 * NOTES
2030 * Call XMLRPC_GetValueStringLen() to retrieve real length of binary data. strlen()
2031 * will not be accurate, as returned data may contain embedded nulls.
2032 * SOURCE
2033 */
XMLRPC_GetValueBase64(XMLRPC_VALUE value)2034 const char* XMLRPC_GetValueBase64(XMLRPC_VALUE value) {
2035 return ((value && value->type == xmlrpc_base64) ? value->str.str : 0);
2036 }
2037
2038 /*******/
2039
2040 /****f* VALUE/XMLRPC_GetValueDateTime
2041 * NAME
2042 * XMLRPC_GetValueDateTime
2043 * SYNOPSIS
2044 * time_t XMLRPC_GetValueDateTime(XMLRPC_VALUE value)
2045 * FUNCTION
2046 * retrieve time_t value
2047 * INPUTS
2048 * XMLRPC_VALUE of type xmlrpc_datetime
2049 * RESULT
2050 * time_t value or 0 if value is not valid datetime.
2051 * NOTES
2052 * use XMLRPC_GetValueType() to be sure if 0 is real value or not
2053 * SEE ALSO
2054 * XMLRPC_SetValueDateTime ()
2055 * XMLRPC_GetValueDateTime_ISO8601 ()
2056 * XMLRPC_CreateValueDateTime ()
2057 * SOURCE
2058 */
XMLRPC_GetValueDateTime(XMLRPC_VALUE value)2059 time_t XMLRPC_GetValueDateTime(XMLRPC_VALUE value) {
2060 return (time_t)((value && value->type == xmlrpc_datetime) ? value->i : 0);
2061 }
2062
2063 /*******/
2064
2065 /****f* VALUE/XMLRPC_GetValueDateTime_IOS8601
2066 * NAME
2067 * XMLRPC_GetValueDateTime_IOS8601
2068 * SYNOPSIS
2069 * const char* XMLRPC_GetValueDateTime_IOS8601(XMLRPC_VALUE value)
2070 * FUNCTION
2071 * retrieve ISO8601 formatted time value
2072 * INPUTS
2073 * XMLRPC_VALUE of type xmlrpc_datetime
2074 * RESULT
2075 * const char* value or 0 if value is not valid datetime.
2076 * SEE ALSO
2077 * XMLRPC_SetValueDateTime_IOS8601 ()
2078 * XMLRPC_GetValueDateTime ()
2079 * XMLRPC_CreateValueDateTime_IOS8601 ()
2080 * SOURCE
2081 */
XMLRPC_GetValueDateTime_ISO8601(XMLRPC_VALUE value)2082 const char* XMLRPC_GetValueDateTime_ISO8601(XMLRPC_VALUE value) {
2083 return ((value && value->type == xmlrpc_datetime) ? value->str.str : 0);
2084 }
2085
2086 /*******/
2087
2088 /* Get ID (key) of value or NULL */
2089 /****f* VALUE/XMLRPC_GetValueID
2090 * NAME
2091 * XMLRPC_GetValueID
2092 * SYNOPSIS
2093 * const char* XMLRPC_GetValueID(XMLRPC_VALUE value)
2094 * FUNCTION
2095 * retrieve id (key) of value
2096 * INPUTS
2097 * XMLRPC_VALUE of any type
2098 * RESULT
2099 * const char* pointer to id of value, or NULL
2100 * NOTES
2101 * SEE ALSO
2102 * XMLRPC_SetValueID()
2103 * XMLRPC_CreateValueEmpty()
2104 * SOURCE
2105 */
XMLRPC_GetValueID(XMLRPC_VALUE value)2106 const char* XMLRPC_GetValueID(XMLRPC_VALUE value) {
2107 return (const char*)((value && value->id.len) ? value->id.str : 0);
2108 }
2109
2110 /*******/
2111
2112
2113 /****f* VECTOR/XMLRPC_VectorSize
2114 * NAME
2115 * XMLRPC_VectorSize
2116 * SYNOPSIS
2117 * int XMLRPC_VectorSize(XMLRPC_VALUE value)
2118 * FUNCTION
2119 * retrieve size of vector
2120 * INPUTS
2121 * XMLRPC_VALUE of type xmlrpc_vector
2122 * RESULT
2123 * count of items in vector
2124 * NOTES
2125 * This is a cheap operation even on large vectors. Vector size is
2126 * maintained by queue during add/remove ops.
2127 * SEE ALSO
2128 * XMLRPC_AddValueToVector ()
2129 * SOURCE
2130 */
XMLRPC_VectorSize(XMLRPC_VALUE value)2131 int XMLRPC_VectorSize(XMLRPC_VALUE value) {
2132 int size = 0;
2133 if(value && value->type == xmlrpc_vector && value->v) {
2134 size = Q_Size(value->v->q);
2135 }
2136 return size;
2137 }
2138
2139 /*******/
2140
2141 /****f* VECTOR/XMLRPC_VectorRewind
2142 * NAME
2143 * XMLRPC_VectorRewind
2144 * SYNOPSIS
2145 * XMLRPC_VALUE XMLRPC_VectorRewind(XMLRPC_VALUE value)
2146 * FUNCTION
2147 * reset vector to first item
2148 * INPUTS
2149 * XMLRPC_VALUE of type xmlrpc_vector
2150 * RESULT
2151 * first XMLRPC_VALUE in list, or NULL if empty or error.
2152 * NOTES
2153 * Be careful to rewind any vector passed in to you if you expect to
2154 * iterate through the entire list.
2155 * SEE ALSO
2156 * XMLRPC_VectorNext ()
2157 * SOURCE
2158 */
XMLRPC_VectorRewind(XMLRPC_VALUE value)2159 XMLRPC_VALUE XMLRPC_VectorRewind(XMLRPC_VALUE value) {
2160 XMLRPC_VALUE xReturn = NULL;
2161 if(value && value->type == xmlrpc_vector && value->v) {
2162 xReturn = (XMLRPC_VALUE)Q_Head(value->v->q);
2163 }
2164 return xReturn;
2165 }
2166
2167 /*******/
2168
2169 /****f* VECTOR/XMLRPC_VectorNext
2170 * NAME
2171 * XMLRPC_VectorNext
2172 * SYNOPSIS
2173 * XMLRPC_VALUE XMLRPC_VectorNext(XMLRPC_VALUE value)
2174 * FUNCTION
2175 * Iterate vector to next item in list.
2176 * INPUTS
2177 * XMLRPC_VALUE of type xmlrpc_vector
2178 * RESULT
2179 * Next XMLRPC_VALUE in vector, or NULL if at end.
2180 * NOTES
2181 * SEE ALSO
2182 * XMLRPC_VectorRewind ()
2183 * SOURCE
2184 */
XMLRPC_VectorNext(XMLRPC_VALUE value)2185 XMLRPC_VALUE XMLRPC_VectorNext(XMLRPC_VALUE value) {
2186 XMLRPC_VALUE xReturn = NULL;
2187 if(value && value->type == xmlrpc_vector && value->v) {
2188 xReturn = (XMLRPC_VALUE)Q_Next(value->v->q);
2189 }
2190 return xReturn;
2191 }
2192
2193 /*******/
2194
2195 /****f* VALUE/XMLRPC_GetValueType
2196 * NAME
2197 * XMLRPC_GetValueType
2198 * SYNOPSIS
2199 * XMLRPC_VALUE_TYPE XMLRPC_GetValueType(XMLRPC_VALUE value)
2200 * FUNCTION
2201 * determine data type of the XMLRPC_VALUE
2202 * INPUTS
2203 * XMLRPC_VALUE target of query
2204 * RESULT
2205 * data type of value as enumerated by XMLRPC_VALUE_TYPE
2206 * NOTES
2207 * all values are of type xmlrpc_empty until set.
2208 * Deprecated for public use. See XMLRPC_GetValueTypeEasy
2209 * SEE ALSO
2210 * XMLRPC_SetValue*
2211 * XMLRPC_CreateValue*
2212 * XMLRPC_Append*
2213 * XMLRPC_GetValueTypeEasy ()
2214 * SOURCE
2215 */
XMLRPC_GetValueType(XMLRPC_VALUE value)2216 XMLRPC_VALUE_TYPE XMLRPC_GetValueType(XMLRPC_VALUE value) {
2217 return value ? value->type : xmlrpc_empty;
2218 }
2219
2220 /*******/
2221
2222 /* Vector type accessor */
2223 /****f* VALUE/XMLRPC_GetVectorType
2224 * NAME
2225 * XMLRPC_GetVectorType
2226 * SYNOPSIS
2227 * XMLRPC_VECTOR_TYPE XMLRPC_GetVectorType(XMLRPC_VALUE value)
2228 * FUNCTION
2229 * determine vector type of the XMLRPC_VALUE
2230 * INPUTS
2231 * XMLRPC_VALUE of type xmlrpc_vector
2232 * RESULT
2233 * vector type of value as enumerated by XMLRPC_VECTOR_TYPE.
2234 * xmlrpc_none if not a value.
2235 * NOTES
2236 * xmlrpc_none is returned if value is not a vector
2237 * Deprecated for public use. See XMLRPC_GetValueTypeEasy
2238 * SEE ALSO
2239 * XMLRPC_SetIsVector ()
2240 * XMLRPC_GetValueType ()
2241 * XMLRPC_GetValueTypeEasy ()
2242 * SOURCE
2243 */
XMLRPC_GetVectorType(XMLRPC_VALUE value)2244 XMLRPC_VECTOR_TYPE XMLRPC_GetVectorType(XMLRPC_VALUE value) {
2245 return(value && value->v) ? value->v->type : xmlrpc_vector_none;
2246 }
2247
2248 /*******/
2249
2250 /****f* VALUE/XMLRPC_GetValueTypeEasy
2251 * NAME
2252 * XMLRPC_GetValueTypeEasy
2253 * SYNOPSIS
2254 * XMLRPC_VALUE_TYPE_EASY XMLRPC_GetValueTypeEasy(XMLRPC_VALUE value)
2255 * FUNCTION
2256 * determine data type of the XMLRPC_VALUE. includes vector types.
2257 * INPUTS
2258 * XMLRPC_VALUE target of query
2259 * RESULT
2260 * data type of value as enumerated by XMLRPC_VALUE_TYPE_EASY
2261 * xmlrpc_type_none if not a value.
2262 * NOTES
2263 * all values are of type xmlrpc_type_empty until set.
2264 * SEE ALSO
2265 * XMLRPC_SetValue*
2266 * XMLRPC_CreateValue*
2267 * XMLRPC_Append*
2268 * SOURCE
2269 */
XMLRPC_GetValueTypeEasy(XMLRPC_VALUE value)2270 XMLRPC_VALUE_TYPE_EASY XMLRPC_GetValueTypeEasy (XMLRPC_VALUE value) {
2271 if (value) {
2272 switch (value->type) {
2273 case xmlrpc_vector:
2274 switch (value->v->type) {
2275 case xmlrpc_vector_none:
2276 return xmlrpc_type_none;
2277 case xmlrpc_vector_struct:
2278 return xmlrpc_type_struct;
2279 case xmlrpc_vector_mixed:
2280 return xmlrpc_type_mixed;
2281 case xmlrpc_vector_array:
2282 return xmlrpc_type_array;
2283 }
2284 default:
2285 /* evil cast, but we know they are the same */
2286 return(XMLRPC_VALUE_TYPE_EASY) value->type;
2287 }
2288 }
2289 return xmlrpc_type_none;
2290 }
2291
2292 /*******/
2293
2294
2295
2296 /*-*******************
2297 * Begin Server Funcs *
2298 *********************/
2299
2300
2301 /****f* VALUE/XMLRPC_ServerCreate
2302 * NAME
2303 * XMLRPC_ServerCreate
2304 * SYNOPSIS
2305 * XMLRPC_SERVER XMLRPC_ServerCreate()
2306 * FUNCTION
2307 * Allocate/Init XMLRPC Server Resources.
2308 * INPUTS
2309 * none
2310 * RESULT
2311 * newly allocated XMLRPC_SERVER
2312 * NOTES
2313 * SEE ALSO
2314 * XMLRPC_ServerDestroy ()
2315 * XMLRPC_GetGlobalServer ()
2316 * SOURCE
2317 */
XMLRPC_ServerCreate()2318 XMLRPC_SERVER XMLRPC_ServerCreate() {
2319 XMLRPC_SERVER server = ecalloc(1, sizeof(STRUCT_XMLRPC_SERVER));
2320 if(server) {
2321 Q_Init(&server->methodlist);
2322 Q_Init(&server->docslist);
2323
2324 /* register system methods */
2325 xsm_register(server);
2326 }
2327 return server;
2328 }
2329
2330 /*******/
2331
2332 /* Return global server. Not locking! Not Thread Safe! */
2333 /****f* VALUE/XMLRPC_GetGlobalServer
2334 * NAME
2335 * XMLRPC_GetGlobalServer
2336 * SYNOPSIS
2337 * XMLRPC_SERVER XMLRPC_GetGlobalServer()
2338 * FUNCTION
2339 * Allocates a global (process-wide) server, or returns pointer if pre-existing.
2340 * INPUTS
2341 * none
2342 * RESULT
2343 * pointer to global server, or 0 if error.
2344 * NOTES
2345 * ***WARNING*** This function is not thread safe. It is included only for the very lazy.
2346 * Multi-threaded programs that use this may experience problems.
2347 * BUGS
2348 * There is currently no way to cleanup the global server gracefully.
2349 * SEE ALSO
2350 * XMLRPC_ServerCreate ()
2351 * SOURCE
2352 */
XMLRPC_GetGlobalServer()2353 XMLRPC_SERVER XMLRPC_GetGlobalServer() {
2354 static XMLRPC_SERVER xsServer = 0;
2355 if(!xsServer) {
2356 xsServer = XMLRPC_ServerCreate();
2357 }
2358 return xsServer;
2359 }
2360
2361 /*******/
2362
2363 /****f* VALUE/XMLRPC_ServerDestroy
2364 * NAME
2365 * XMLRPC_ServerDestroy
2366 * SYNOPSIS
2367 * void XMLRPC_ServerDestroy(XMLRPC_SERVER server)
2368 * FUNCTION
2369 * Free Server Resources
2370 * INPUTS
2371 * server The server to be free'd
2372 * RESULT
2373 * void
2374 * NOTES
2375 * This frees the server struct and any methods that have been added.
2376 * SEE ALSO
2377 * XMLRPC_ServerCreate ()
2378 * SOURCE
2379 */
XMLRPC_ServerDestroy(XMLRPC_SERVER server)2380 void XMLRPC_ServerDestroy(XMLRPC_SERVER server) {
2381 if(server) {
2382 doc_method* dm = Q_Head(&server->docslist);
2383 server_method* sm = Q_Head(&server->methodlist);
2384 while( dm ) {
2385 my_free(dm);
2386 dm = Q_Next(&server->docslist);
2387 }
2388 while( sm ) {
2389 my_free(sm->name);
2390 if(sm->desc) {
2391 XMLRPC_CleanupValue(sm->desc);
2392 }
2393 my_free(sm);
2394 sm = Q_Next(&server->methodlist);
2395 }
2396 if (server->xIntrospection) {
2397 XMLRPC_CleanupValue(server->xIntrospection);
2398 }
2399
2400 Q_Destroy(&server->methodlist);
2401 Q_Destroy(&server->docslist);
2402 my_free(server);
2403 }
2404 }
2405
2406 /*******/
2407
2408
2409 /****f* VALUE/XMLRPC_ServerRegisterMethod
2410 * NAME
2411 * XMLRPC_ServerRegisterMethod
2412 * SYNOPSIS
2413 * void XMLRPC_ServerRegisterMethod(XMLRPC_SERVER server, const char *name, XMLRPC_Callback cb)
2414 * FUNCTION
2415 * Register new XMLRPC method with server
2416 * INPUTS
2417 * server The XMLRPC_SERVER to register the method with
2418 * name public name of the method
2419 * cb C function that implements the method
2420 * RESULT
2421 * int - 1 if success, else 0
2422 * NOTES
2423 * A C function must be registered for every "method" that the server recognizes. The
2424 * method name is equivalent to <methodCall><name> method name </name></methodCall> in the
2425 * XML syntax.
2426 * SEE ALSO
2427 * XMLRPC_ServerFindMethod ()
2428 * XMLRPC_ServerCallMethod ()
2429 * SOURCE
2430 */
XMLRPC_ServerRegisterMethod(XMLRPC_SERVER server,const char * name,XMLRPC_Callback cb)2431 int XMLRPC_ServerRegisterMethod(XMLRPC_SERVER server, const char *name, XMLRPC_Callback cb) {
2432 if(server && name && cb) {
2433
2434 server_method* sm = emalloc(sizeof(server_method));
2435
2436 if(sm) {
2437 sm->name = estrdup(name);
2438 sm->method = cb;
2439 sm->desc = NULL;
2440
2441 return Q_PushTail(&server->methodlist, sm);
2442 }
2443 }
2444 return 0;
2445 }
2446
2447 /*******/
2448
find_method(XMLRPC_SERVER server,const char * name)2449 server_method* find_method(XMLRPC_SERVER server, const char* name) {
2450 server_method* sm;
2451
2452 q_iter qi = Q_Iter_Head_F(&server->methodlist);
2453
2454 while( qi ) {
2455 sm = Q_Iter_Get_F(qi);
2456 if(sm && !strcmp(sm->name, name)) {
2457 return sm;
2458 }
2459 qi = Q_Iter_Next_F(qi);
2460 }
2461 return NULL;
2462 }
2463
2464
type_to_str(XMLRPC_VALUE_TYPE type,XMLRPC_VECTOR_TYPE vtype)2465 const char* type_to_str(XMLRPC_VALUE_TYPE type, XMLRPC_VECTOR_TYPE vtype) {
2466 switch(type) {
2467 case xmlrpc_none:
2468 return "none";
2469 case xmlrpc_empty:
2470 return "empty";
2471 case xmlrpc_base64:
2472 return "base64";
2473 case xmlrpc_boolean:
2474 return "boolean";
2475 case xmlrpc_datetime:
2476 return "datetime";
2477 case xmlrpc_double:
2478 return "double";
2479 case xmlrpc_int:
2480 return "int";
2481 case xmlrpc_string:
2482 return "string";
2483 case xmlrpc_vector:
2484 switch(vtype) {
2485 case xmlrpc_vector_none:
2486 return "none";
2487 case xmlrpc_vector_array:
2488 return "array";
2489 case xmlrpc_vector_mixed:
2490 return "mixed vector (struct)";
2491 case xmlrpc_vector_struct:
2492 return "struct";
2493 }
2494 }
2495 return "unknown";
2496 }
2497
2498 /****f* VALUE/XMLRPC_ServerFindMethod
2499 * NAME
2500 * XMLRPC_ServerFindMethod
2501 * SYNOPSIS
2502 * XMLRPC_Callback XMLRPC_ServerFindMethod(XMLRPC_SERVER server, const char* callName)
2503 * FUNCTION
2504 * retrieve C callback associated with a given method name.
2505 * INPUTS
2506 * server The XMLRPC_SERVER the method is registered with
2507 * callName the method to find
2508 * RESULT
2509 * previously registered XMLRPC_Callback, or NULL
2510 * NOTES
2511 * Typically, this is used to determine if a requested method exists, without actually calling it.
2512 * SEE ALSO
2513 * XMLRPC_ServerCallMethod ()
2514 * XMLRPC_ServerRegisterMethod ()
2515 * SOURCE
2516 */
XMLRPC_ServerFindMethod(XMLRPC_SERVER server,const char * callName)2517 XMLRPC_Callback XMLRPC_ServerFindMethod(XMLRPC_SERVER server, const char* callName) {
2518 if(server && callName) {
2519 q_iter qi = Q_Iter_Head_F(&server->methodlist);
2520 while( qi ) {
2521 server_method* sm = Q_Iter_Get_F(qi);
2522 if(sm && !strcmp(sm->name, callName)) {
2523 return sm->method;
2524 }
2525 qi = Q_Iter_Next_F(qi);
2526 }
2527 }
2528 return NULL;
2529 }
2530
2531 /*******/
2532
2533
2534 /* Call method specified in request */
2535 /****f* VALUE/XMLRPC_ServerCallMethod
2536 * NAME
2537 * XMLRPC_ServerCallMethod
2538 * SYNOPSIS
2539 * XMLRPC_VALUE XMLRPC_ServerCallMethod(XMLRPC_SERVER server, XMLRPC_REQUEST request, void* userData)
2540 * FUNCTION
2541 *
2542 * INPUTS
2543 * server The XMLRPC_SERVER the method is registered with
2544 * request the request to handle
2545 * userData any additional data to pass to the C callback, or NULL
2546 * RESULT
2547 * XMLRPC_VALUE allocated by the callback, or NULL
2548 * NOTES
2549 * It is typically the caller's responsibility to free the returned value.
2550 *
2551 * Often the caller will want to serialize the result as XML, via
2552 * XMLRPC_VALUE_To_XML () or XMLRPC_REQUEST_To_XML ()
2553 * SEE ALSO
2554 * XMLRPC_ServerFindMethod ()
2555 * XMLRPC_ServerRegisterMethod ()
2556 * XMLRPC_CleanupValue ()
2557 * SOURCE
2558 */
XMLRPC_ServerCallMethod(XMLRPC_SERVER server,XMLRPC_REQUEST request,void * userData)2559 XMLRPC_VALUE XMLRPC_ServerCallMethod(XMLRPC_SERVER server, XMLRPC_REQUEST request, void* userData) {
2560 XMLRPC_VALUE xReturn = NULL;
2561
2562 /* check for error set during request parsing / generation */
2563 if(request && request->error) {
2564 xReturn = XMLRPC_CopyValue(request->error);
2565 }
2566 else if (server && request) {
2567 XMLRPC_Callback cb =
2568 XMLRPC_ServerFindMethod (server, request->methodName.str);
2569 if(cb) {
2570 xReturn = cb(server, request, userData);
2571 }
2572 else {
2573 xReturn =
2574 XMLRPC_UtilityCreateFault (xmlrpc_error_unknown_method,
2575 request->methodName.str);
2576 }
2577 }
2578 return xReturn;
2579 }
2580
2581 /*******/
2582
2583 /*-*****************
2584 * End server funcs *
2585 *******************/
2586
2587
2588 /*-***********************************
2589 * Begin XMLRPC General Options funcs *
2590 *************************************/
2591
2592 /* For options used by XMLRPC_VALUE funcs that otherwise do not have
2593 * parameters for options. Kind of gross. :(
2594 */
2595 typedef struct _xmlrpc_options {
2596 XMLRPC_CASE id_case;
2597 XMLRPC_CASE_COMPARISON id_case_compare;
2598 }
2599 STRUCT_XMLRPC_OPTIONS, *XMLRPC_OPTIONS;
2600
XMLRPC_GetDefaultOptions()2601 static XMLRPC_OPTIONS XMLRPC_GetDefaultOptions() {
2602 static STRUCT_XMLRPC_OPTIONS options = {
2603 xmlrpc_case_exact,
2604 xmlrpc_case_sensitive
2605 };
2606 return &options;
2607 }
2608
2609 /****f* VALUE/XMLRPC_GetDefaultIdCase
2610 * NAME
2611 * XMLRPC_GetDefaultIdCase
2612 * SYNOPSIS
2613 * XMLRPC_CASE XMLRPC_GetDefaultIdCase()
2614 * FUNCTION
2615 * Gets default case options used by XMLRPC_VALUE funcs
2616 * INPUTS
2617 * none
2618 * RESULT
2619 * XMLRPC_CASE
2620 * BUGS
2621 * Nasty and gross. Should be server specific, but that requires changing all
2622 * the XMLRPC_VALUE api's.
2623 * SEE ALSO
2624 * XMLRPC_SetDefaultIdCase ()
2625 * SOURCE
2626 */
XMLRPC_GetDefaultIdCase()2627 XMLRPC_CASE XMLRPC_GetDefaultIdCase() {
2628 XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2629 return options->id_case;
2630 }
2631
2632 /*******/
2633
2634 /****f* VALUE/XMLRPC_SetDefaultIdCase
2635 * NAME
2636 * XMLRPC_SetDefaultIdCase
2637 * SYNOPSIS
2638 * XMLRPC_CASE XMLRPC_SetDefaultIdCase(XMLRPC_CASE id_case)
2639 * FUNCTION
2640 * Sets default case options used by XMLRPC_VALUE funcs
2641 * INPUTS
2642 * id_case case options as enumerated by XMLRPC_CASE
2643 * RESULT
2644 * XMLRPC_CASE -- newly set option
2645 * BUGS
2646 * Nasty and gross. Should be server specific, but that requires changing all
2647 * the XMLRPC_VALUE api's.
2648 * SEE ALSO
2649 * XMLRPC_GetDefaultIdCase ()
2650 * SOURCE
2651 */
XMLRPC_SetDefaultIdCase(XMLRPC_CASE id_case)2652 XMLRPC_CASE XMLRPC_SetDefaultIdCase(XMLRPC_CASE id_case) {
2653 XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2654 options->id_case = id_case;
2655 return options->id_case;
2656 }
2657
2658 /*******/
2659
2660 /****f* VALUE/XMLRPC_GetDefaultIdCaseComparison
2661 * NAME
2662 * XMLRPC_GetDefaultIdCaseComparison
2663 * SYNOPSIS
2664 * XMLRPC_CASE XMLRPC_GetDefaultIdCaseComparison( )
2665 * FUNCTION
2666 * Gets default case comparison options used by XMLRPC_VALUE funcs
2667 * INPUTS
2668 * none
2669 * RESULT
2670 * XMLRPC_CASE_COMPARISON default
2671 * BUGS
2672 * Nasty and gross. Should be server specific, but that requires changing all
2673 * the XMLRPC_VALUE api's.
2674 * SEE ALSO
2675 * XMLRPC_SetDefaultIdCaseComparison ()
2676 * SOURCE
2677 */
XMLRPC_GetDefaultIdCaseComparison()2678 XMLRPC_CASE_COMPARISON XMLRPC_GetDefaultIdCaseComparison() {
2679 XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2680 return options->id_case_compare;
2681 }
2682
2683 /*******/
2684
2685 /****f* VALUE/XMLRPC_SetDefaultIdCaseComparison
2686 * NAME
2687 * XMLRPC_SetDefaultIdCaseComparison
2688 * SYNOPSIS
2689 * XMLRPC_CASE XMLRPC_SetDefaultIdCaseComparison( XMLRPC_CASE_COMPARISON id_case_compare )
2690 * FUNCTION
2691 * Gets default case comparison options used by XMLRPC_VALUE funcs
2692 * INPUTS
2693 * id_case_compare case comparison rule to set as default
2694 * RESULT
2695 * XMLRPC_CASE_COMPARISON newly set default
2696 * BUGS
2697 * Nasty and gross. Should be server specific, but that requires changing all
2698 * the XMLRPC_VALUE api's.
2699 * SEE ALSO
2700 * XMLRPC_GetDefaultIdCaseComparison ()
2701 * SOURCE
2702 */
XMLRPC_SetDefaultIdCaseComparison(XMLRPC_CASE_COMPARISON id_case_compare)2703 XMLRPC_CASE_COMPARISON XMLRPC_SetDefaultIdCaseComparison(XMLRPC_CASE_COMPARISON id_case_compare) {
2704 XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2705 options->id_case_compare = id_case_compare;
2706 return options->id_case_compare;
2707 }
2708
2709 /*******/
2710
2711 /*-*********************************
2712 * End XMLRPC General Options funcs *
2713 ***********************************/
2714
2715
2716 /*-******************
2717 * Fault API funcs *
2718 ********************/
2719
2720 /****f* UTILITY/XMLRPC_UtilityCreateFault
2721 * NAME
2722 * XMLRPC_UtilityCreateFault
2723 * SYNOPSIS
2724 * XMLRPC_VALUE XMLRPC_UtilityCreateFault( int fault_code, const char* fault_string )
2725 * FUNCTION
2726 * generates a struct containing a string member with id "faultString" and an int member
2727 * with id "faultCode". When using the xmlrpc xml serialization, these will be translated
2728 * to <fault><value><struct>... format.
2729 * INPUTS
2730 * fault_code application specific error code. can be 0.
2731 * fault_string application specific error string. cannot be null.
2732 * RESULT
2733 * XMLRPC_VALUE a newly created struct vector representing the error, or null on error.
2734 * NOTES
2735 * This is a utility function. xmlrpc "faults" are not directly represented in this xmlrpc
2736 * API or data structures. It is the author's view, that this API is intended for simple
2737 * data types, and a "fault" is a complex data type consisting of multiple simple data
2738 * types. This function is provided for convenience only, the same result could be
2739 * achieved directly by the application.
2740 *
2741 * This function now supports some "standardized" fault codes, as specified at.
2742 * http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php.
2743 * If one of these fault codes is received, the description string will automatically
2744 * be prefixed with a standard error string and 2 newlines.
2745 *
2746 * The actual transformation between this complex type and the xml "<fault>" element takes
2747 * place in the xmlrpc to xml serialization layer. This step is not performed when using the
2748 * simplerpc serialization, meaning that there will be no "<fault>" element in that
2749 * serialization. There will simply be a standard struct with 2 child elements.
2750 * imho, the "<fault>" element is unnecessary and/or out of place as part of the standard API.
2751 *
2752 * SOURCE
2753 */
XMLRPC_UtilityCreateFault(int fault_code,const char * fault_string)2754 XMLRPC_VALUE XMLRPC_UtilityCreateFault(int fault_code, const char* fault_string) {
2755 XMLRPC_VALUE xOutput = NULL;
2756
2757 char* string = NULL;
2758 simplestring description;
2759 simplestring_init(&description);
2760
2761 switch (fault_code) {
2762 case xmlrpc_error_parse_xml_syntax:
2763 string = xmlrpc_error_parse_xml_syntax_str;
2764 break;
2765 case xmlrpc_error_parse_unknown_encoding:
2766 string = xmlrpc_error_parse_unknown_encoding_str;
2767 break;
2768 case xmlrpc_error_parse_bad_encoding:
2769 string = xmlrpc_error_parse_bad_encoding_str;
2770 break;
2771 case xmlrpc_error_invalid_xmlrpc:
2772 string = xmlrpc_error_invalid_xmlrpc_str;
2773 break;
2774 case xmlrpc_error_unknown_method:
2775 string = xmlrpc_error_unknown_method_str;
2776 break;
2777 case xmlrpc_error_invalid_params:
2778 string = xmlrpc_error_invalid_params_str;
2779 break;
2780 case xmlrpc_error_internal_server:
2781 string = xmlrpc_error_internal_server_str;
2782 break;
2783 case xmlrpc_error_application:
2784 string = xmlrpc_error_application_str;
2785 break;
2786 case xmlrpc_error_system:
2787 string = xmlrpc_error_system_str;
2788 break;
2789 case xmlrpc_error_transport:
2790 string = xmlrpc_error_transport_str;
2791 break;
2792 }
2793
2794 simplestring_add(&description, string);
2795
2796 if(string && fault_string) {
2797 simplestring_add(&description, "\n\n");
2798 }
2799 simplestring_add(&description, fault_string);
2800
2801
2802 if(description.len) {
2803 xOutput = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
2804
2805 XMLRPC_VectorAppendString (xOutput, "faultString", description.str,
2806 description.len);
2807 XMLRPC_VectorAppendInt(xOutput, "faultCode", fault_code);
2808 }
2809
2810 simplestring_free(&description);
2811
2812 return xOutput;
2813 }
2814
2815 /*******/
2816
2817
2818 /****f* FAULT/XMLRPC_ValueIsFault
2819 * NAME
2820 * XMLRPC_ValueIsFault
2821 * SYNOPSIS
2822 * int XMLRPC_ValueIsFault (XMLRPC_VALUE value)
2823 * FUNCTION
2824 * Determines if a value encapsulates a fault "object"
2825 * INPUTS
2826 * value any XMLRPC_VALUE
2827 * RESULT
2828 * 1 if it is a fault, else 0
2829 * SEE ALSO
2830 * XMLRPC_ResponseIsFault ()
2831 * SOURCE
2832 */
XMLRPC_ValueIsFault(XMLRPC_VALUE value)2833 int XMLRPC_ValueIsFault (XMLRPC_VALUE value) {
2834 if( XMLRPC_VectorGetValueWithID(value, "faultCode") &&
2835 XMLRPC_VectorGetValueWithID(value, "faultString") ) {
2836 return 1;
2837 }
2838 return 0;
2839 }
2840 /*******/
2841
2842
2843 /****f* FAULT/XMLRPC_ResponseIsFault
2844 * NAME
2845 * XMLRPC_ResponseIsFault
2846 * SYNOPSIS
2847 * int XMLRPC_ResponseIsFault (XMLRPC_REQUEST response)
2848 * FUNCTION
2849 * Determines if a response contains an encapsulated fault "object"
2850 * INPUTS
2851 * value any XMLRPC_REQUEST. typically of type xmlrpc_request_response
2852 * RESULT
2853 * 1 if it contains a fault, else 0
2854 * SEE ALSO
2855 * XMLRPC_ValueIsFault ()
2856 * SOURCE
2857 */
XMLRPC_ResponseIsFault(XMLRPC_REQUEST response)2858 int XMLRPC_ResponseIsFault(XMLRPC_REQUEST response) {
2859 return XMLRPC_ValueIsFault( XMLRPC_RequestGetData(response) );
2860 }
2861
2862 /*******/
2863
2864 /****f* FAULT/XMLRPC_GetValueFaultCode
2865 * NAME
2866 * XMLRPC_GetValueFaultCode
2867 * SYNOPSIS
2868 * int XMLRPC_GetValueFaultCode (XMLRPC_VALUE value)
2869 * FUNCTION
2870 * returns fault code from a struct, if any
2871 * INPUTS
2872 * value XMLRPC_VALUE of type xmlrpc_vector_struct.
2873 * RESULT
2874 * fault code, else 0.
2875 * BUGS
2876 * impossible to distinguish faultCode == 0 from faultCode not present.
2877 * SEE ALSO
2878 * XMLRPC_GetResponseFaultCode ()
2879 * SOURCE
2880 */
XMLRPC_GetValueFaultCode(XMLRPC_VALUE value)2881 int XMLRPC_GetValueFaultCode (XMLRPC_VALUE value) {
2882 return XMLRPC_VectorGetIntWithID(value, "faultCode");
2883 }
2884
2885 /*******/
2886
2887 /****f* FAULT/XMLRPC_GetResponseFaultCode
2888 * NAME
2889 * XMLRPC_GetResponseFaultCode
2890 * SYNOPSIS
2891 * int XMLRPC_GetResponseFaultCode(XMLRPC_REQUEST response)
2892 * FUNCTION
2893 * returns fault code from a response, if any
2894 * INPUTS
2895 * response XMLRPC_REQUEST. typically of type xmlrpc_request_response.
2896 * RESULT
2897 * fault code, else 0.
2898 * BUGS
2899 * impossible to distinguish faultCode == 0 from faultCode not present.
2900 * SEE ALSO
2901 * XMLRPC_GetValueFaultCode ()
2902 * SOURCE
2903 */
XMLRPC_GetResponseFaultCode(XMLRPC_REQUEST response)2904 int XMLRPC_GetResponseFaultCode(XMLRPC_REQUEST response) {
2905 return XMLRPC_GetValueFaultCode( XMLRPC_RequestGetData(response) );
2906 }
2907
2908 /*******/
2909
2910
2911 /****f* FAULT/XMLRPC_GetValueFaultString
2912 * NAME
2913 * XMLRPC_GetValueFaultString
2914 * SYNOPSIS
2915 * const char* XMLRPC_GetValueFaultString (XMLRPC_VALUE value)
2916 * FUNCTION
2917 * returns fault string from a struct, if any
2918 * INPUTS
2919 * value XMLRPC_VALUE of type xmlrpc_vector_struct.
2920 * RESULT
2921 * fault string, else 0.
2922 * SEE ALSO
2923 * XMLRPC_GetResponseFaultString ()
2924 * SOURCE
2925 */
XMLRPC_GetValueFaultString(XMLRPC_VALUE value)2926 const char* XMLRPC_GetValueFaultString (XMLRPC_VALUE value) {
2927 return XMLRPC_VectorGetStringWithID(value, "faultString");
2928 }
2929
2930 /*******/
2931
2932 /****f* FAULT/XMLRPC_GetResponseFaultString
2933 * NAME
2934 * XMLRPC_GetResponseFaultString
2935 * SYNOPSIS
2936 * const char* XMLRPC_GetResponseFaultString (XMLRPC_REQUEST response)
2937 * FUNCTION
2938 * returns fault string from a response, if any
2939 * INPUTS
2940 * response XMLRPC_REQUEST. typically of type xmlrpc_request_response.
2941 * RESULT
2942 * fault string, else 0.
2943 * SEE ALSO
2944 * XMLRPC_GetValueFaultString ()
2945 * SOURCE
2946 */
XMLRPC_GetResponseFaultString(XMLRPC_REQUEST response)2947 const char* XMLRPC_GetResponseFaultString (XMLRPC_REQUEST response) {
2948 return XMLRPC_GetValueFaultString( XMLRPC_RequestGetData(response) );
2949 }
2950
2951 /*******/
2952
2953
2954 /*-******************
2955 * Utility API funcs *
2956 ********************/
2957
2958
2959 /****f* UTILITY/XMLRPC_Free
2960 * NAME
2961 * XMLRPC_Free
2962 * SYNOPSIS
2963 * void XMLRPC_Free(void* mem)
2964 * FUNCTION
2965 * frees a block of memory allocated by xmlrpc.
2966 * INPUTS
2967 * mem memory to free
2968 * RESULT
2969 * void
2970 * NOTES
2971 * Useful for OS's where memory must be free'd
2972 * in the same library in which it is allocated.
2973 * SOURCE
2974 */
XMLRPC_Free(void * mem)2975 void XMLRPC_Free(void* mem) {
2976 my_free(mem);
2977 }
2978
2979 /*******/
2980
2981
2982 /****f* UTILITY/XMLRPC_GetVersionString
2983 * NAME
2984 * XMLRPC_GetVersionString
2985 * SYNOPSIS
2986 * const char* XMLRPC_GetVersionString()
2987 * FUNCTION
2988 * returns library version string
2989 * INPUTS
2990 *
2991 * RESULT
2992 * const char*
2993 * NOTES
2994 * SOURCE
2995 */
XMLRPC_GetVersionString()2996 const char* XMLRPC_GetVersionString() {
2997 return XMLRPC_VERSION_STR;
2998 }
2999
3000 /*******/
3001
3002
3003 /*-**********************
3004 * End Utility API funcs *
3005 ************************/
3006