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