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