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