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