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