Setting tag plcapi-5.3-11
[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$";
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_nil:
1113             case xmlrpc_base64:
1114             case xmlrpc_boolean:
1115             case xmlrpc_datetime:
1116             case xmlrpc_double:
1117             case xmlrpc_int:
1118             case xmlrpc_string:
1119             case xmlrpc_vector:
1120                /* Guard against putting a key/val pair into an array vector */
1121                if( !(source->id.len && target->v->type == xmlrpc_vector_array) ) {
1122                                         if (isDuplicateEntry (target, source)
1123                                                  || Q_PushTail (target->v->q, XMLRPC_CopyValue (source))) {
1124                      return 1;
1125                   }
1126                }
1127                else {
1128                                         fprintf (stderr,
1129                                                                 "xmlrpc: attempted to add key/val pair to vector of type array\n");
1130                }
1131                break;
1132             default:
1133                                 fprintf (stderr,
1134                                                         "xmlrpc: attempted to add value of unknown type to vector\n");
1135                break;
1136          }
1137       }
1138    }
1139    return 0;
1140 }
1141
1142 /*******/
1143
1144
1145 /****f* VECTOR/XMLRPC_AddValuesToVector
1146  * NAME
1147  *   XMLRPC_AddValuesToVector
1148  * SYNOPSIS
1149  *   XMLRPC_AddValuesToVector ( target, val1, val2, val3, val(n), 0 )
1150  *   XMLRPC_AddValuesToVector( XMLRPC_VALUE, ... )
1151  * FUNCTION
1152  *   Add (append) a series of existing XMLRPC_VALUE to a vector.
1153  * INPUTS
1154  *   target    The target vector
1155  *   ...       The source value(s) to append.  The last item *must* be 0.
1156  * RESULT
1157  *   int       1 if successful, else 0
1158  * SEE ALSO
1159  *   XMLRPC_AddValuesToVector ()
1160  *   XMLRPC_VectorGetValueWithID_Case ()
1161  *   XMLRPC_VALUE
1162  * NOTES
1163  *   This function may actually return failure after it has already modified
1164  *     or added items to target.  You can not trust the state of target
1165  *     if this function returns failure.
1166  * SOURCE
1167  */
1168 int XMLRPC_AddValuesToVector(XMLRPC_VALUE target, ...) {
1169    int iRetval = 0;
1170
1171    if(target) {
1172       if(target->type == xmlrpc_vector) {
1173          XMLRPC_VALUE v = NULL;
1174          va_list vl;
1175
1176          va_start(vl, target);
1177
1178          do {
1179             v = va_arg(vl, XMLRPC_VALUE);
1180             if(v) {
1181                if(!XMLRPC_AddValueToVector(target, v)) {
1182                   iRetval = 0;
1183                   break;
1184                }
1185             }
1186                         }
1187                         while (v);
1188
1189          va_end(vl);
1190
1191          if(NULL == v) {
1192             iRetval = 1;
1193          }
1194       }
1195    }
1196    return iRetval;
1197 }
1198
1199 /*******/
1200
1201
1202 /****f* VECTOR/XMLRPC_VectorGetValueWithID_Case
1203  * NAME
1204  *   XMLRPC_VectorGetValueWithID_Case
1205  * SYNOPSIS
1206  *   XMLRPC_VALUE XMLRPC_VectorGetValueWithID_Case(XMLRPC_VALUE vector, const char* id, XMLRPC_CASE_COMPARISON id_case)
1207  * FUNCTION
1208  *   Get value from vector matching id (key)
1209  * INPUTS
1210  *   vector    The source vector
1211  *   id        The key to find
1212  *   id_case   Rule for how to match key
1213  * RESULT
1214  *   int       1 if successful, else 0
1215  * SEE ALSO
1216  *   XMLRPC_SetValueID_Case ()
1217  *   XMLRPC_VALUE
1218  *   XMLRPC_CASE_COMPARISON
1219  * SOURCE
1220  */
1221 XMLRPC_VALUE XMLRPC_VectorGetValueWithID_Case (XMLRPC_VALUE vector, const char *id,
1222                                                                                                                           XMLRPC_CASE_COMPARISON id_case) {
1223    if(vector && vector->v && vector->v->q) {
1224        q_iter qi = Q_Iter_Head_F(vector->v->q);
1225
1226        while(qi) {
1227           XMLRPC_VALUE xIter = Q_Iter_Get_F(qi);
1228           if(xIter && xIter->id.str) {
1229              if(id_case == xmlrpc_case_sensitive) {
1230                 if(!strcmp(xIter->id.str, id)) {
1231                    return xIter;
1232                 }
1233              }
1234              else if(id_case == xmlrpc_case_insensitive) {
1235                 if(!strcasecmp(xIter->id.str, id)) {
1236                    return xIter;
1237                 }
1238              }
1239           }
1240           qi = Q_Iter_Next_F(qi);
1241        }
1242    }
1243    return NULL;
1244 }
1245
1246 /*******/
1247
1248
1249 int XMLRPC_VectorRemoveValue(XMLRPC_VALUE vector, XMLRPC_VALUE value) {
1250    if(vector && vector->v && vector->v->q && value) {
1251        q_iter qi = Q_Iter_Head_F(vector->v->q);
1252
1253        while(qi) {
1254           XMLRPC_VALUE xIter = Q_Iter_Get_F(qi);
1255           if(xIter == value) {
1256              XMLRPC_CleanupValue(xIter);
1257              Q_Iter_Del(vector->v->q, qi);
1258              return 1;
1259           }
1260           qi = Q_Iter_Next_F(qi);
1261        }
1262    }
1263    return 0;
1264 }
1265
1266
1267 /****f* VALUE/XMLRPC_CreateValueString
1268  * NAME
1269  *   XMLRPC_CreateValueString
1270  * SYNOPSIS
1271  *   XMLRPC_VALUE XMLRPC_CreateValueString(const char* id, const char* val, int len)
1272  * FUNCTION
1273  *   Create an XMLRPC_VALUE, and assign a string to it
1274  * INPUTS
1275  *   id        The id of the value, or NULL
1276  *   val       The desired new string val.
1277  *   len       length of val string if known, or 0 if unknown.
1278  * RESULT
1279  *   newly allocated XMLRPC_VALUE, or NULL
1280  * SEE ALSO
1281  *   XMLRPC_GetValueString ()
1282  *   XMLRPC_CreateValueEmpty ()
1283  *   XMLRPC_VALUE
1284  *   XMLRPC_VALUE_TYPE
1285  * SOURCE
1286  */
1287 XMLRPC_VALUE XMLRPC_CreateValueString(const char* id, const char* val, int len) {
1288    XMLRPC_VALUE value = NULL;
1289    if(val) {
1290       value = XMLRPC_CreateValueEmpty();
1291       if(value) {
1292          XMLRPC_SetValueString(value, val, len);
1293          if(id) {
1294             XMLRPC_SetValueID(value, id, 0);
1295          }
1296       }
1297    }
1298    return value;
1299 }
1300
1301 /*******/
1302
1303 /****f* VALUE/XMLRPC_CreateValueInt
1304  * NAME
1305  *   XMLRPC_CreateValueInt
1306  * SYNOPSIS
1307  *   XMLRPC_VALUE XMLRPC_CreateValueInt(const char* id, int i)
1308  * FUNCTION
1309  *   Create an XMLRPC_VALUE, and assign an int to it
1310  * INPUTS
1311  *   id        The id of the value, or NULL
1312  *   i         The desired new int val.
1313  * RESULT
1314  *   newly allocated XMLRPC_VALUE, or NULL
1315  * SEE ALSO
1316  *   XMLRPC_GetValueInt ()
1317  *   XMLRPC_CreateValueEmpty ()
1318  *   XMLRPC_VALUE
1319  *   XMLRPC_VALUE_TYPE
1320  * SOURCE
1321  */
1322 XMLRPC_VALUE XMLRPC_CreateValueInt(const char* id, int i) {
1323    XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1324    if(val) {
1325       XMLRPC_SetValueInt(val, i);
1326       if(id) {
1327          XMLRPC_SetValueID(val, id, 0);
1328       }
1329    }
1330    return val;
1331 }
1332
1333 /*******/
1334
1335 /****f* VALUE/XMLRPC_CreateValueBoolean
1336  * NAME
1337  *   XMLRPC_CreateValueBoolean
1338  * SYNOPSIS
1339  *   XMLRPC_VALUE XMLRPC_CreateValueBoolean(const char* id, int i)
1340  * FUNCTION
1341  *   Create an XMLRPC_VALUE, and assign an int to it
1342  * INPUTS
1343  *   id        The id of the value, or NULL
1344  *   i         The desired new int val.
1345  * RESULT
1346  *   newly allocated XMLRPC_VALUE, or NULL
1347  * SEE ALSO
1348  *   XMLRPC_GetValueBoolean ()
1349  *   XMLRPC_CreateValueEmpty ()
1350  *   XMLRPC_VALUE
1351  *   XMLRPC_VALUE_TYPE
1352  * SOURCE
1353  */
1354 XMLRPC_VALUE XMLRPC_CreateValueBoolean(const char* id, int i) {
1355    XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1356    if(val) {
1357       XMLRPC_SetValueBoolean(val, i);
1358       if(id) {
1359          XMLRPC_SetValueID(val, id, 0);
1360       }
1361    }
1362    return val;
1363 }
1364
1365 /*******/
1366
1367
1368 /****f* VALUE/XMLRPC_CleanupValue
1369  * NAME
1370  *   XMLRPC_CleanupValue
1371  * SYNOPSIS
1372  *   void XMLRPC_CleanupValue(XMLRPC_VALUE value)
1373  * FUNCTION
1374  *   Frees all memory allocated for an XMLRPC_VALUE and any of its children (if a vector)
1375  * INPUTS
1376  *   value     The id of the value to be cleaned up.
1377  * RESULT
1378  *   void
1379  * NOTES
1380  *   Normally this function will be called for the topmost vector, thus free-ing
1381  *   all children.  If a child of a vector is free'd first, results are undefined.
1382  *   Failure to call this function *will* cause memory leaks.
1383  *
1384  *   Also, this function is implemented using reference counting.  Thus a value
1385  *   may be added and freed from multiple parents so long as a reference is added
1386  *   first using XMLRPC_CopyValue()
1387  * SEE ALSO
1388  *   XMLRPC_RequestFree ()
1389  *   XMLRPC_CreateValueEmpty ()
1390  *   XMLRPC_CopyValue()
1391  *   XMLRPC_VALUE
1392  * SOURCE
1393  */
1394 void XMLRPC_CleanupValue(XMLRPC_VALUE value) {
1395    if(value) {
1396       if(value->iRefCount > 0) {
1397          value->iRefCount --;
1398       }
1399
1400 #ifdef XMLRPC_DEBUG_REFCOUNT
1401       if(value->id.str) {
1402                         printf ("decremented refcount of %s, now %i\n", value->id.str,
1403                                           value->iRefCount);
1404       }
1405       else {
1406                         printf ("decremented refcount of 0x%x, now %i\n", value,
1407                                           value->iRefCount);
1408       }
1409 #endif
1410
1411       if(value->type == xmlrpc_vector) {
1412          if(value->v) {
1413             if(value->iRefCount == 0) {
1414                XMLRPC_VALUE cur = (XMLRPC_VALUE)Q_Head(value->v->q);
1415                while( cur ) {
1416                   XMLRPC_CleanupValue(cur);
1417    
1418                   /* Make sure some idiot didn't include a vector as a child of itself
1419                    * and thus it would have already free'd these.
1420                    */
1421                   if(value->v && value->v->q) {
1422                      cur = Q_Next(value->v->q);
1423                   }
1424                   else {
1425                      break;
1426                   }
1427                }
1428
1429                Q_Destroy(value->v->q);
1430                my_free(value->v->q);
1431                my_free(value->v);
1432             }
1433          }
1434       }
1435
1436
1437       if(value->iRefCount == 0) {
1438
1439          /* guard against freeing invalid types */
1440          switch(value->type) {
1441             case xmlrpc_empty:
1442             case xmlrpc_base64:
1443             case xmlrpc_boolean:
1444             case xmlrpc_datetime:
1445             case xmlrpc_double:
1446             case xmlrpc_int:
1447             case xmlrpc_string:
1448             case xmlrpc_vector:
1449 #ifdef XMLRPC_DEBUG_REFCOUNT
1450                if(value->id.str) {
1451                   printf("free'd %s\n", value->id.str);
1452                }
1453                else {
1454                   printf("free'd 0x%x\n", value);
1455                }
1456 #endif 
1457                simplestring_free(&value->id);
1458                simplestring_free(&value->str);
1459
1460                memset(value, 0, sizeof(STRUCT_XMLRPC_VALUE));
1461                my_free(value);
1462                break;
1463             default:
1464                                 fprintf (stderr,
1465                                                         "xmlrpc: attempted to free value of invalid type\n");
1466                break;
1467          }
1468       }
1469    }
1470 }
1471
1472 /*******/
1473
1474
1475 /****f* VALUE/XMLRPC_SetValueDateTime
1476  * NAME
1477  *   XMLRPC_SetValueDateTime
1478  * SYNOPSIS
1479  *   void XMLRPC_SetValueDateTime(XMLRPC_VALUE value, time_t time)
1480  * FUNCTION
1481  *   Assign time value to XMLRPC_VALUE
1482  * INPUTS
1483  *   value     The target XMLRPC_VALUE
1484  *   time      The desired new unix time value (time_t)
1485  * RESULT
1486  *   void
1487  * SEE ALSO
1488  *   XMLRPC_GetValueDateTime ()
1489  *   XMLRPC_SetValueDateTime_ISO8601 ()
1490  *   XMLRPC_CreateValueDateTime ()
1491  *   XMLRPC_VALUE
1492  * SOURCE
1493  */
1494 void XMLRPC_SetValueDateTime(XMLRPC_VALUE value, time_t time) {
1495    if(value) {
1496       char timeBuf[30];
1497       value->type = xmlrpc_datetime;
1498       value->i = time;
1499
1500       timeBuf[0] = 0;
1501
1502       date_to_ISO8601(time, timeBuf, sizeof(timeBuf));
1503
1504       if(timeBuf[0]) {
1505          simplestring_clear(&value->str);
1506          simplestring_add(&value->str, timeBuf);
1507       }
1508    }
1509 }
1510
1511 /*******/
1512
1513 /****f* VALUE/XMLRPC_CopyValue
1514  * NAME
1515  *   XMLRPC_CopyValue
1516  * SYNOPSIS
1517  *   XMLRPC_VALUE XMLRPC_CopyValue(XMLRPC_VALUE value)
1518  * FUNCTION
1519  *   Make a copy (reference) of an XMLRPC_VALUE
1520  * INPUTS
1521  *   value     The target XMLRPC_VALUE
1522  * RESULT
1523  *   XMLRPC_VALUE -- address of the copy
1524  * SEE ALSO
1525  *   XMLRPC_CleanupValue ()
1526  *   XMLRPC_DupValueNew ()
1527  * NOTES
1528  *   This function is implemented via reference counting, so the
1529  *   returned value is going to be the same as the passed in value.
1530  *   The value must be freed the same number of times it is copied
1531  *   or there will be a memory leak.
1532  * SOURCE
1533  */
1534 XMLRPC_VALUE XMLRPC_CopyValue(XMLRPC_VALUE value) {
1535    if(value) {
1536       value->iRefCount ++;
1537 #ifdef XMLRPC_DEBUG_REFCOUNT
1538       if(value->id.str) {
1539                         printf ("incremented refcount of %s, now %i\n", value->id.str,
1540                                           value->iRefCount);
1541                 }
1542                 else {
1543                         printf ("incremented refcount of 0x%x, now %i\n", value,
1544                                           value->iRefCount);
1545       }
1546 #endif
1547    }
1548    return value;
1549 }
1550
1551 /*******/
1552
1553
1554 /****f* VALUE/XMLRPC_DupValueNew
1555  * NAME
1556  *   XMLRPC_DupValueNew
1557  * SYNOPSIS
1558  *   XMLRPC_VALUE XMLRPC_DupValueNew(XMLRPC_VALUE value)
1559  * FUNCTION
1560  *   Make a duplicate (non reference) of an XMLRPC_VALUE with newly allocated mem.
1561  * INPUTS
1562  *   value     The source XMLRPC_VALUE to duplicate
1563  * RESULT
1564  *   XMLRPC_VALUE -- address of the duplicate value
1565  * SEE ALSO
1566  *   XMLRPC_CleanupValue ()
1567  *   XMLRPC_CopyValue ()
1568  * NOTES
1569  *   Use this when function when you need to modify the contents of
1570  *   the copied value seperately from the original.
1571  *   
1572  *   this function is recursive, thus the value and all of its children
1573  *   (if any) will be duplicated.
1574  * SOURCE
1575  */
1576 XMLRPC_VALUE XMLRPC_DupValueNew (XMLRPC_VALUE xSource) {
1577         XMLRPC_VALUE xReturn = NULL;
1578         if (xSource) {
1579                 xReturn = XMLRPC_CreateValueEmpty ();
1580                 if (xSource->id.len) {
1581                         XMLRPC_SetValueID (xReturn, xSource->id.str, xSource->id.len);
1582                 }
1583
1584                 switch (xSource->type) {
1585                 case xmlrpc_int:
1586                 case xmlrpc_boolean:
1587                         XMLRPC_SetValueInt (xReturn, xSource->i);
1588                         break;
1589                 case xmlrpc_string:
1590                 case xmlrpc_base64:
1591                         XMLRPC_SetValueString (xReturn, xSource->str.str, xSource->str.len);
1592                         break;
1593                 case xmlrpc_datetime:
1594                         XMLRPC_SetValueDateTime (xReturn, xSource->i);
1595                         break;
1596                 case xmlrpc_double:
1597                         XMLRPC_SetValueDouble (xReturn, xSource->d);
1598                         break;
1599                 case xmlrpc_vector:
1600                         {
1601                                 q_iter qi = Q_Iter_Head_F (xSource->v->q);
1602                                 XMLRPC_SetIsVector (xReturn, xSource->v->type);
1603
1604                                 while (qi) {
1605                                         XMLRPC_VALUE xIter = Q_Iter_Get_F (qi);
1606                                         XMLRPC_AddValueToVector (xReturn, XMLRPC_DupValueNew (xIter));
1607                                         qi = Q_Iter_Next_F (qi);
1608                                 }
1609                         }
1610                         break;
1611                 default:
1612                         break;
1613                 }
1614         }
1615         return xReturn;
1616 }
1617
1618 /*******/
1619
1620
1621
1622 /****f* VALUE/XMLRPC_CreateValueDateTime
1623  * NAME
1624  *   XMLRPC_CreateValueDateTime
1625  * SYNOPSIS
1626  *   XMLRPC_VALUE XMLRPC_CreateValueDateTime(const char* id, time_t time)
1627  * FUNCTION
1628  *   Create new datetime value from time_t
1629  * INPUTS
1630  *   id        id of the new value, or NULL
1631  *   time      The desired unix time value (time_t)
1632  * RESULT
1633  *   void
1634  * SEE ALSO
1635  *   XMLRPC_GetValueDateTime ()
1636  *   XMLRPC_SetValueDateTime ()
1637  *   XMLRPC_CreateValueDateTime_ISO8601 ()
1638  *   XMLRPC_VALUE
1639  * SOURCE
1640  */
1641 XMLRPC_VALUE XMLRPC_CreateValueDateTime(const char* id, time_t time) {
1642    XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1643    if(val) {
1644       XMLRPC_SetValueDateTime(val, time);
1645       if(id) {
1646          XMLRPC_SetValueID(val, id, 0);
1647       }
1648    }
1649    return val;
1650 }
1651
1652 /*******/
1653
1654
1655 /****f* VALUE/XMLRPC_SetValueDateTime_ISO8601
1656  * NAME
1657  *   XMLRPC_SetValueDateTime_ISO8601
1658  * SYNOPSIS
1659  *   void XMLRPC_SetValueDateTime_ISO8601(XMLRPC_VALUE value, const char* s)
1660  * FUNCTION
1661  *   Set datetime value from IS08601 encoded string
1662  * INPUTS
1663  *   value     The target XMLRPC_VALUE
1664  *   s         The desired new time value
1665  * RESULT
1666  *   void                                
1667  * BUGS
1668  *   This function currently attempts to convert the time string to a valid unix time
1669  *   value before passing it. Behavior when the string is invalid or out of range
1670  *   is not well defined, but will probably result in Jan 1, 1970 (0) being passed.
1671  * SEE ALSO
1672  *   XMLRPC_GetValueDateTime_ISO8601 ()
1673  *   XMLRPC_CreateValueDateTime_ISO8601 ()
1674  *   XMLRPC_CreateValueDateTime ()
1675  *   XMLRPC_VALUE
1676  * SOURCE
1677  */
1678 void XMLRPC_SetValueDateTime_ISO8601(XMLRPC_VALUE value, const char* s) {
1679    if(value) {
1680       time_t time_val = 0;
1681       if(s) {
1682          date_from_ISO8601(s, &time_val);
1683          XMLRPC_SetValueDateTime(value, time_val);
1684       }
1685    }
1686 }
1687
1688 /*******/
1689
1690 /****f* VALUE/XMLRPC_CreateValueDateTime_ISO8601
1691  * NAME
1692  *   XMLRPC_CreateValueDateTime_ISO8601
1693  * SYNOPSIS
1694  *   XMLRPC_VALUE XMLRPC_CreateValueDateTime_ISO8601(const char* id, const char *s)
1695  * FUNCTION
1696  *   Create datetime value from IS08601 encoded string
1697  * INPUTS
1698  *   id        The id of the new value, or NULL
1699  *   s         The desired new time value
1700  * RESULT
1701  *   newly allocated XMLRPC_VALUE, or NULL if no value created.                                
1702  * BUGS
1703  *   See XMLRPC_SetValueDateTime_ISO8601 ()
1704  * SEE ALSO
1705  *   XMLRPC_GetValueDateTime_ISO8601 ()
1706  *   XMLRPC_SetValueDateTime_ISO8601 ()
1707  *   XMLRPC_CreateValueDateTime ()
1708  *   XMLRPC_VALUE
1709  * SOURCE
1710  */
1711 XMLRPC_VALUE XMLRPC_CreateValueDateTime_ISO8601(const char* id, const char *s) {
1712    XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1713    if(val) {
1714       XMLRPC_SetValueDateTime_ISO8601(val, s);
1715       if(id) {
1716          XMLRPC_SetValueID(val, id, 0);
1717       }
1718    }
1719    return val;
1720 }
1721
1722 /*******/
1723
1724
1725 /****f* VALUE/XMLRPC_SetValueBase64
1726  * NAME
1727  *   XMLRPC_SetValueBase64
1728  * SYNOPSIS
1729  *   void XMLRPC_SetValueBase64(XMLRPC_VALUE value, const char* s, int len)
1730  * FUNCTION
1731  *   Set base64 value.  Base64 is useful for transferring binary data, such as an image.
1732  * INPUTS
1733  *   value     The target XMLRPC_VALUE
1734  *   s         The desired new binary value
1735  *   len       The length of s, or NULL. If buffer is not null terminated, len *must* be passed.
1736  * RESULT
1737  *   void                                
1738  * NOTES
1739  *   Data is set/stored/retrieved as passed in, but is base64 encoded for XML transfer, and
1740  *   decoded on the other side.  This is transparent to the caller.
1741  * SEE ALSO
1742  *   XMLRPC_GetValueBase64 ()
1743  *   XMLRPC_CreateValueBase64 ()
1744  *   XMLRPC_VALUE
1745  * SOURCE
1746  */
1747 void XMLRPC_SetValueBase64(XMLRPC_VALUE value, const char* s, int len) {
1748    if(value && s) {
1749       simplestring_clear(&value->str);
1750       (len > 0) ? simplestring_addn(&value->str, s, len) :
1751                   simplestring_add(&value->str, s);
1752       value->type = xmlrpc_base64;
1753    }
1754 }
1755
1756 /*******/
1757
1758
1759 /****f* VALUE/XMLRPC_CreateValueBase64
1760  * NAME
1761  *   XMLRPC_CreateValueBase64
1762  * SYNOPSIS
1763  *   XMLRPC_VALUE XMLRPC_CreateValueBase64(const char* id, const char* s, int len)
1764  * FUNCTION
1765  *   Create base64 value.  Base64 is useful for transferring binary data, such as an image.
1766  * INPUTS
1767  *   id        id of the new value, or NULL
1768  *   s         The desired new binary value
1769  *   len       The length of s, or NULL. If buffer is not null terminated, len *must* be passed.
1770  * RESULT
1771  *   newly allocated XMLRPC_VALUE, or NULL if error
1772  * NOTES
1773  *   See XMLRPC_SetValueBase64 ()
1774  * SEE ALSO
1775  *   XMLRPC_GetValueBase64 ()
1776  *   XMLRPC_SetValueBase64 ()
1777  *   XMLRPC_VALUE
1778  * SOURCE
1779  */
1780 XMLRPC_VALUE XMLRPC_CreateValueBase64(const char* id, const char* s, int len) {
1781    XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1782    if(val) {
1783       XMLRPC_SetValueBase64(val, s, len);
1784       if(id) {
1785          XMLRPC_SetValueID(val, id, 0);
1786       }
1787    }
1788    return val;
1789 }
1790
1791 /*******/
1792
1793 /****f* VALUE/XMLRPC_SetValueDouble
1794  * NAME
1795  *   XMLRPC_SetValueDouble
1796  * SYNOPSIS
1797  *   void XMLRPC_SetValueDouble(XMLRPC_VALUE value, double val)
1798  * FUNCTION
1799  *   Set double (floating point) value.
1800  * INPUTS
1801  *   value     The target XMLRPC_VALUE
1802  *   val       The desired new double value
1803  * RESULT
1804  *   void                                
1805  * SEE ALSO
1806  *   XMLRPC_GetValueDouble ()
1807  *   XMLRPC_CreateValueDouble ()
1808  *   XMLRPC_VALUE
1809  * SOURCE
1810  */
1811 void XMLRPC_SetValueDouble(XMLRPC_VALUE value, double val) {
1812    if(value) {
1813       value->type = xmlrpc_double;
1814       value->d = val;
1815    }
1816 }
1817
1818 /*******/
1819
1820 /****f* VALUE/XMLRPC_CreateValueDouble
1821  * NAME
1822  *   XMLRPC_CreateValueDouble
1823  * SYNOPSIS
1824  *   XMLRPC_VALUE XMLRPC_CreateValueDouble(const char* id, double d)
1825  * FUNCTION
1826  *   Create double (floating point) value.
1827  * INPUTS
1828  *   id        id of the newly created value, or NULL
1829  *   d         The desired new double value
1830  * RESULT
1831  *   void                                
1832  * SEE ALSO
1833  *   XMLRPC_GetValueDouble ()
1834  *   XMLRPC_CreateValueDouble ()
1835  *   XMLRPC_VALUE
1836  * SOURCE
1837  */
1838 XMLRPC_VALUE XMLRPC_CreateValueDouble(const char* id, double d) {
1839    XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1840    if(val) {
1841       XMLRPC_SetValueDouble(val, d);
1842       if(id) {
1843          XMLRPC_SetValueID(val, id, 0);
1844       }
1845    }
1846    return val;
1847 }
1848
1849 /*******/
1850
1851 /****f* VALUE/XMLRPC_GetValueString
1852  * NAME
1853  *   XMLRPC_GetValueString
1854  * SYNOPSIS
1855  *   const char* XMLRPC_GetValueString(XMLRPC_VALUE value)
1856  * FUNCTION
1857  *   retrieve string value
1858  * INPUTS
1859  *   value     source XMLRPC_VALUE of type xmlrpc_string
1860  * RESULT
1861  *   void                                
1862  * SEE ALSO
1863  *   XMLRPC_SetValueString ()
1864  *   XMLRPC_GetValueType ()
1865  *   XMLRPC_VALUE
1866  * SOURCE
1867  */
1868 const char* XMLRPC_GetValueString(XMLRPC_VALUE value) {
1869     return ((value && value->type == xmlrpc_string) ? value->str.str : 0);
1870 }
1871
1872 /*******/
1873
1874 /****f* VALUE/XMLRPC_GetValueStringLen
1875  * NAME
1876  *   XMLRPC_GetValueStringLen
1877  * SYNOPSIS
1878  *   int XMLRPC_GetValueStringLen(XMLRPC_VALUE value)
1879  * FUNCTION
1880  *   determine length of string value
1881  * INPUTS
1882  *   value     XMLRPC_VALUE of type xmlrpc_string 
1883  * RESULT
1884  *   length of string, or 0
1885  * NOTES
1886  * SEE ALSO
1887  *   XMLRPC_SetValueString ()
1888  *   XMLRPC_GetValueString ()
1889  * SOURCE
1890  */
1891 int XMLRPC_GetValueStringLen(XMLRPC_VALUE value) {
1892     return ((value) ? value->str.len : 0);
1893 }
1894
1895 /*******/
1896
1897 /****f* VALUE/XMLRPC_GetValueInt
1898  * NAME
1899  *   XMLRPC_GetValueInt
1900  * SYNOPSIS
1901  *   int XMLRPC_GetValueInt(XMLRPC_VALUE value)
1902  * FUNCTION
1903  *   retrieve integer value.
1904  * INPUTS
1905  *   value     XMLRPC_VALUE of type xmlrpc_int 
1906  * RESULT
1907  *   integer value or 0 if value is not valid int
1908  * NOTES
1909  *   use XMLRPC_GetValueType () to be sure if 0 is real return value or not
1910  * SEE ALSO
1911  *   XMLRPC_SetValueInt ()
1912  *   XMLRPC_CreateValueInt ()
1913  * SOURCE
1914  */
1915 int XMLRPC_GetValueInt(XMLRPC_VALUE value) {
1916     return ((value && value->type == xmlrpc_int) ? value->i : 0);
1917 }
1918
1919 /*******/
1920
1921 /****f* VALUE/XMLRPC_GetValueBoolean
1922  * NAME
1923  *   XMLRPC_GetValueBoolean
1924  * SYNOPSIS
1925  *   int XMLRPC_GetValueBoolean(XMLRPC_VALUE value)
1926  * FUNCTION
1927  *   retrieve boolean value.
1928  * INPUTS
1929  *   XMLRPC_VALUE of type xmlrpc_boolean
1930  * RESULT
1931  *   boolean value or 0 if value is not valid boolean
1932  * NOTES
1933  *   use XMLRPC_GetValueType() to be sure if 0 is real value or not
1934  * SEE ALSO
1935  *   XMLRPC_SetValueBoolean ()
1936  *   XMLRPC_CreateValueBoolean ()
1937  * SOURCE
1938  */
1939 int XMLRPC_GetValueBoolean(XMLRPC_VALUE value) {
1940     return ((value && value->type == xmlrpc_boolean) ? value->i : 0);
1941 }
1942
1943 /*******/
1944
1945 /****f* VALUE/XMLRPC_GetValueDouble
1946  * NAME
1947  *   XMLRPC_GetValueDouble
1948  * SYNOPSIS
1949  *   double XMLRPC_GetValueDouble(XMLRPC_VALUE value)
1950  * FUNCTION
1951  *   retrieve double value
1952  * INPUTS
1953  *   XMLRPC_VALUE of type xmlrpc_double
1954  * RESULT
1955  *   double value or 0 if value is not valid double.
1956  * NOTES
1957  *   use XMLRPC_GetValueType() to be sure if 0 is real value or not
1958  * SEE ALSO
1959  *   XMLRPC_SetValueDouble ()
1960  *   XMLRPC_CreateValueDouble ()
1961  * SOURCE
1962  */
1963 double XMLRPC_GetValueDouble(XMLRPC_VALUE value) {
1964     return ((value && value->type == xmlrpc_double) ? value->d : 0);
1965 }
1966
1967 /*******/
1968
1969 /****f* VALUE/XMLRPC_GetValueBase64
1970  * NAME
1971  *   XMLRPC_GetValueBase64
1972  * SYNOPSIS
1973  *   const char* XMLRPC_GetValueBase64(XMLRPC_VALUE value)
1974  * FUNCTION
1975  *   retrieve binary value
1976  * INPUTS
1977  *   XMLRPC_VALUE of type xmlrpc_base64
1978  * RESULT
1979  *   pointer to binary value or 0 if value is not valid.
1980  * SEE ALSO
1981  *   XMLRPC_SetValueBase64 ()
1982  *   XMLRPC_CreateValueBase64 ()
1983  * NOTES
1984  *   Call XMLRPC_GetValueStringLen() to retrieve real length of binary data.  strlen()
1985  *   will not be accurate, as returned data may contain embedded nulls.
1986  * SOURCE
1987  */
1988 const char* XMLRPC_GetValueBase64(XMLRPC_VALUE value) {
1989     return ((value && value->type == xmlrpc_base64) ? value->str.str : 0);
1990 }
1991
1992 /*******/
1993
1994 /****f* VALUE/XMLRPC_GetValueDateTime
1995  * NAME
1996  *   XMLRPC_GetValueDateTime
1997  * SYNOPSIS
1998  *   time_t XMLRPC_GetValueDateTime(XMLRPC_VALUE value)
1999  * FUNCTION
2000  *   retrieve time_t value
2001  * INPUTS
2002  *   XMLRPC_VALUE of type xmlrpc_datetime
2003  * RESULT
2004  *   time_t value or 0 if value is not valid datetime.
2005  * NOTES
2006  *   use XMLRPC_GetValueType() to be sure if 0 is real value or not
2007  * SEE ALSO
2008  *   XMLRPC_SetValueDateTime ()
2009  *   XMLRPC_GetValueDateTime_ISO8601 ()
2010  *   XMLRPC_CreateValueDateTime ()
2011  * SOURCE
2012  */
2013 time_t XMLRPC_GetValueDateTime(XMLRPC_VALUE value) {
2014     return (time_t)((value && value->type == xmlrpc_datetime) ? value->i : 0);
2015 }
2016
2017 /*******/
2018
2019 /****f* VALUE/XMLRPC_GetValueDateTime_IOS8601
2020  * NAME
2021  *   XMLRPC_GetValueDateTime_IOS8601
2022  * SYNOPSIS
2023  *   const char* XMLRPC_GetValueDateTime_IOS8601(XMLRPC_VALUE value)
2024  * FUNCTION
2025  *   retrieve ISO8601 formatted time value
2026  * INPUTS
2027  *   XMLRPC_VALUE of type xmlrpc_datetime
2028  * RESULT
2029  *   const char* value or 0 if value is not valid datetime.
2030  * SEE ALSO
2031  *   XMLRPC_SetValueDateTime_IOS8601 ()
2032  *   XMLRPC_GetValueDateTime ()
2033  *   XMLRPC_CreateValueDateTime_IOS8601 ()
2034  * SOURCE
2035  */
2036 const char* XMLRPC_GetValueDateTime_ISO8601(XMLRPC_VALUE value) {
2037     return ((value && value->type == xmlrpc_datetime) ? value->str.str : 0);
2038 }
2039
2040 /*******/
2041
2042 /* Get ID (key) of value or NULL */
2043 /****f* VALUE/XMLRPC_GetValueID
2044  * NAME
2045  *   XMLRPC_GetValueID
2046  * SYNOPSIS
2047  *   const char* XMLRPC_GetValueID(XMLRPC_VALUE value)
2048  * FUNCTION
2049  *   retrieve id (key) of value
2050  * INPUTS
2051  *   XMLRPC_VALUE of any type
2052  * RESULT
2053  *   const char* pointer to id of value, or NULL
2054  * NOTES
2055  * SEE ALSO
2056  *   XMLRPC_SetValueID()
2057  *   XMLRPC_CreateValueEmpty()
2058  * SOURCE
2059  */
2060 const char* XMLRPC_GetValueID(XMLRPC_VALUE value) {
2061     return (const char*)((value && value->id.len) ? value->id.str : 0);
2062 }
2063
2064 /*******/
2065
2066
2067 /****f* VECTOR/XMLRPC_VectorSize
2068  * NAME
2069  *   XMLRPC_VectorSize
2070  * SYNOPSIS
2071  *   int XMLRPC_VectorSize(XMLRPC_VALUE value)
2072  * FUNCTION
2073  *   retrieve size of vector
2074  * INPUTS
2075  *   XMLRPC_VALUE of type xmlrpc_vector
2076  * RESULT
2077  *   count of items in vector
2078  * NOTES
2079  *   This is a cheap operation even on large vectors.  Vector size is 
2080  *   maintained by queue during add/remove ops.
2081  * SEE ALSO
2082  *   XMLRPC_AddValueToVector ()
2083  * SOURCE
2084  */
2085 int XMLRPC_VectorSize(XMLRPC_VALUE value) {
2086    int size = 0;
2087    if(value && value->type == xmlrpc_vector && value->v) {
2088       size = Q_Size(value->v->q);
2089    }
2090    return size;
2091 }
2092
2093 /*******/
2094
2095 /****f* VECTOR/XMLRPC_VectorRewind
2096  * NAME
2097  *   XMLRPC_VectorRewind
2098  * SYNOPSIS
2099  *   XMLRPC_VALUE XMLRPC_VectorRewind(XMLRPC_VALUE value)
2100  * FUNCTION
2101  *   reset vector to first item
2102  * INPUTS
2103  *   XMLRPC_VALUE of type xmlrpc_vector
2104  * RESULT
2105  *   first XMLRPC_VALUE in list, or NULL if empty or error.
2106  * NOTES
2107  *   Be careful to rewind any vector passed in to you if you expect to
2108  *   iterate through the entire list.
2109  * SEE ALSO
2110  *   XMLRPC_VectorNext ()
2111  * SOURCE
2112  */
2113 XMLRPC_VALUE XMLRPC_VectorRewind(XMLRPC_VALUE value) {
2114    XMLRPC_VALUE xReturn = NULL;
2115    if(value && value->type == xmlrpc_vector && value->v) {
2116       xReturn = (XMLRPC_VALUE)Q_Head(value->v->q);
2117    }
2118    return xReturn;
2119 }
2120
2121 /*******/
2122
2123 /****f* VECTOR/XMLRPC_VectorNext
2124  * NAME
2125  *   XMLRPC_VectorNext
2126  * SYNOPSIS
2127  *   XMLRPC_VALUE XMLRPC_VectorNext(XMLRPC_VALUE value)
2128  * FUNCTION
2129  *   Iterate vector to next item in list.
2130  * INPUTS
2131  *   XMLRPC_VALUE of type xmlrpc_vector
2132  * RESULT
2133  *   Next XMLRPC_VALUE in vector, or NULL if at end.
2134  * NOTES
2135  * SEE ALSO
2136  *   XMLRPC_VectorRewind ()
2137  * SOURCE
2138  */
2139 XMLRPC_VALUE XMLRPC_VectorNext(XMLRPC_VALUE value) {
2140    XMLRPC_VALUE xReturn = NULL;
2141    if(value && value->type == xmlrpc_vector && value->v) {
2142       xReturn = (XMLRPC_VALUE)Q_Next(value->v->q);
2143    }
2144    return xReturn;
2145 }
2146
2147 /*******/
2148
2149 /****f* VALUE/XMLRPC_GetValueType
2150  * NAME
2151  *   XMLRPC_GetValueType
2152  * SYNOPSIS
2153  *   XMLRPC_VALUE_TYPE XMLRPC_GetValueType(XMLRPC_VALUE value)
2154  * FUNCTION
2155  *   determine data type of the XMLRPC_VALUE
2156  * INPUTS
2157  *   XMLRPC_VALUE target of query
2158  * RESULT
2159  *   data type of value as enumerated by XMLRPC_VALUE_TYPE
2160  * NOTES
2161  *   all values are of type xmlrpc_empty until set.
2162  *   Deprecated for public use.  See XMLRPC_GetValueTypeEasy
2163  * SEE ALSO
2164  *   XMLRPC_SetValue*
2165  *   XMLRPC_CreateValue*
2166  *   XMLRPC_Append*
2167  *   XMLRPC_GetValueTypeEasy ()
2168  * SOURCE
2169  */
2170 XMLRPC_VALUE_TYPE XMLRPC_GetValueType(XMLRPC_VALUE value) {
2171    return value ? value->type : xmlrpc_empty;
2172 }
2173
2174 /*******/
2175
2176 /* Vector type accessor */
2177 /****f* VALUE/XMLRPC_GetVectorType
2178  * NAME
2179  *   XMLRPC_GetVectorType
2180  * SYNOPSIS
2181  *   XMLRPC_VECTOR_TYPE XMLRPC_GetVectorType(XMLRPC_VALUE value)
2182  * FUNCTION
2183  *   determine vector type of the XMLRPC_VALUE
2184  * INPUTS
2185  *   XMLRPC_VALUE of type xmlrpc_vector
2186  * RESULT
2187  *   vector type of value as enumerated by XMLRPC_VECTOR_TYPE.
2188  *   xmlrpc_none if not a value.
2189  * NOTES
2190  *   xmlrpc_none is returned if value is not a vector
2191  *   Deprecated for public use.  See XMLRPC_GetValueTypeEasy
2192  * SEE ALSO
2193  *   XMLRPC_SetIsVector ()
2194  *   XMLRPC_GetValueType ()
2195  *   XMLRPC_GetValueTypeEasy ()
2196  * SOURCE
2197  */
2198 XMLRPC_VECTOR_TYPE XMLRPC_GetVectorType(XMLRPC_VALUE value) {
2199    return(value && value->v) ? value->v->type : xmlrpc_none;
2200 }
2201
2202 /*******/
2203
2204 /****f* VALUE/XMLRPC_GetValueTypeEasy
2205  * NAME
2206  *   XMLRPC_GetValueTypeEasy
2207  * SYNOPSIS
2208  *   XMLRPC_VALUE_TYPE_EASY XMLRPC_GetValueTypeEasy(XMLRPC_VALUE value)
2209  * FUNCTION
2210  *   determine data type of the XMLRPC_VALUE. includes vector types.
2211  * INPUTS
2212  *   XMLRPC_VALUE target of query
2213  * RESULT
2214  *   data type of value as enumerated by XMLRPC_VALUE_TYPE_EASY
2215  *   xmlrpc_type_none if not a value.
2216  * NOTES
2217  *   all values are of type xmlrpc_type_empty until set. 
2218  * SEE ALSO
2219  *   XMLRPC_SetValue*
2220  *   XMLRPC_CreateValue*
2221  *   XMLRPC_Append*
2222  * SOURCE
2223  */
2224 XMLRPC_VALUE_TYPE_EASY XMLRPC_GetValueTypeEasy (XMLRPC_VALUE value) {
2225         if (value) {
2226                 switch (value->type) {
2227                 case xmlrpc_vector:
2228                         switch (value->v->type) {
2229                         case xmlrpc_vector_none:
2230                                 return xmlrpc_type_none;
2231                         case xmlrpc_vector_struct:
2232                                 return xmlrpc_type_struct;
2233                         case xmlrpc_vector_mixed:
2234                                 return xmlrpc_type_mixed;
2235                         case xmlrpc_vector_array:
2236                                 return xmlrpc_type_array;
2237                         }
2238                 default:
2239                         /* evil cast, but we know they are the same */
2240                         return(XMLRPC_VALUE_TYPE_EASY) value->type;
2241                 }
2242         }
2243         return xmlrpc_none;
2244 }
2245
2246 /*******/
2247
2248
2249
2250 /*-*******************
2251 * Begin Server Funcs *
2252 *********************/
2253
2254
2255 /****f* VALUE/XMLRPC_ServerCreate
2256  * NAME
2257  *   XMLRPC_ServerCreate
2258  * SYNOPSIS
2259  *   XMLRPC_SERVER XMLRPC_ServerCreate()
2260  * FUNCTION
2261  *   Allocate/Init XMLRPC Server Resources.
2262  * INPUTS
2263  *   none
2264  * RESULT
2265  *   newly allocated XMLRPC_SERVER
2266  * NOTES
2267  * SEE ALSO
2268  *   XMLRPC_ServerDestroy ()
2269  *   XMLRPC_GetGlobalServer ()
2270  * SOURCE
2271  */
2272 XMLRPC_SERVER XMLRPC_ServerCreate() {
2273    XMLRPC_SERVER server = calloc(1, sizeof(STRUCT_XMLRPC_SERVER));
2274    if(server) {
2275       Q_Init(&server->methodlist);
2276       Q_Init(&server->docslist);
2277
2278       /* register system methods */
2279       xsm_register(server);
2280    }
2281    return server;
2282 }
2283
2284 /*******/
2285
2286 /* Return global server.  Not locking! Not Thread Safe! */
2287 /****f* VALUE/XMLRPC_GetGlobalServer
2288  * NAME
2289  *   XMLRPC_GetGlobalServer
2290  * SYNOPSIS
2291  *   XMLRPC_SERVER XMLRPC_GetGlobalServer()
2292  * FUNCTION
2293  *   Allocates a global (process-wide) server, or returns pointer if pre-existing.
2294  * INPUTS
2295  *   none
2296  * RESULT
2297  *   pointer to global server, or 0 if error.
2298  * NOTES
2299  *   ***WARNING*** This function is not thread safe.  It is included only for the very lazy.
2300  *   Multi-threaded programs that use this may experience problems.
2301  * BUGS
2302  *   There is currently no way to cleanup the global server gracefully.
2303  * SEE ALSO
2304  *   XMLRPC_ServerCreate ()
2305  * SOURCE
2306  */
2307 XMLRPC_SERVER XMLRPC_GetGlobalServer() {
2308    static XMLRPC_SERVER xsServer = 0;
2309    if(!xsServer) {
2310       xsServer = XMLRPC_ServerCreate();
2311    }
2312    return xsServer;
2313 }
2314
2315 /*******/
2316
2317 /****f* VALUE/XMLRPC_ServerDestroy
2318  * NAME
2319  *   XMLRPC_ServerDestroy
2320  * SYNOPSIS
2321  *   void XMLRPC_ServerDestroy(XMLRPC_SERVER server)
2322  * FUNCTION
2323  *   Free Server Resources
2324  * INPUTS
2325  *   server     The server to be free'd
2326  * RESULT
2327  *   void
2328  * NOTES
2329  *   This frees the server struct and any methods that have been added.
2330  * SEE ALSO
2331  *   XMLRPC_ServerCreate ()
2332  * SOURCE
2333  */
2334 void XMLRPC_ServerDestroy(XMLRPC_SERVER server) {
2335    if(server) {
2336       doc_method* dm = Q_Head(&server->docslist);
2337       server_method* sm = Q_Head(&server->methodlist);
2338       while( dm ) {
2339          my_free(dm);
2340          dm = Q_Next(&server->docslist);
2341       }
2342       while( sm ) {
2343          if(sm->name) {
2344             my_free(sm->name);
2345          }
2346          if(sm->desc) {
2347             XMLRPC_CleanupValue(sm->desc);
2348          }
2349          my_free(sm);
2350          sm = Q_Next(&server->methodlist);
2351       }
2352       if(server->xIntrospection) {
2353          XMLRPC_CleanupValue(server->xIntrospection);
2354       }
2355
2356       Q_Destroy(&server->methodlist);
2357       Q_Destroy(&server->docslist);
2358       my_free(server);
2359    }
2360 }
2361
2362 /*******/
2363
2364
2365 /****f* VALUE/XMLRPC_ServerRegisterMethod
2366  * NAME
2367  *   XMLRPC_ServerRegisterMethod
2368  * SYNOPSIS
2369  *   void XMLRPC_ServerRegisterMethod(XMLRPC_SERVER server, const char *name, XMLRPC_Callback cb)
2370  * FUNCTION
2371  *   Register new XMLRPC method with server
2372  * INPUTS
2373  *   server     The XMLRPC_SERVER to register the method with
2374  *   name       public name of the method
2375  *   cb         C function that implements the method
2376  * RESULT
2377  *   int  - 1 if success, else 0
2378  * NOTES
2379  *   A C function must be registered for every "method" that the server recognizes.  The
2380  *   method name is equivalent to <methodCall><name> method name </name></methodCall> in the
2381  *   XML syntax.
2382  * SEE ALSO
2383  *   XMLRPC_ServerFindMethod ()
2384  *   XMLRPC_ServerCallMethod ()
2385  * SOURCE
2386  */
2387 int XMLRPC_ServerRegisterMethod(XMLRPC_SERVER server, const char *name, XMLRPC_Callback cb) {
2388    if(server && name && cb) {
2389
2390       server_method* sm = malloc(sizeof(server_method));
2391       
2392       if(sm) {
2393          sm->name = strdup(name);
2394          sm->method = cb;
2395          sm->desc = NULL;
2396
2397          return Q_PushTail(&server->methodlist, sm);
2398       }
2399    }
2400    return 0;
2401 }
2402
2403 /*******/
2404
2405 server_method* find_method(XMLRPC_SERVER server, const char* name) {
2406    server_method* sm;
2407
2408    q_iter qi = Q_Iter_Head_F(&server->methodlist);
2409
2410    while( qi ) {
2411       sm = Q_Iter_Get_F(qi);
2412       if(sm && !strcmp(sm->name, name)) {
2413          return sm;
2414       }
2415       qi = Q_Iter_Next_F(qi);
2416    }
2417    return NULL;
2418 }
2419
2420
2421 const char* type_to_str(XMLRPC_VALUE_TYPE type, XMLRPC_VECTOR_TYPE vtype) {
2422     switch(type) {
2423        case xmlrpc_none:
2424           return "none";
2425        case xmlrpc_empty:
2426           return "empty";
2427        case xmlrpc_nil:
2428           return "nil";
2429        case xmlrpc_base64:
2430           return "base64";
2431        case xmlrpc_boolean:
2432           return "boolean";
2433        case xmlrpc_datetime:
2434           return "datetime";
2435        case xmlrpc_double:
2436           return "double";
2437        case xmlrpc_int:
2438           return "int";
2439        case xmlrpc_string:
2440           return "string";
2441        case xmlrpc_vector:
2442           switch(vtype) {
2443              case xmlrpc_vector_none:
2444                 return "none";
2445              case xmlrpc_vector_array:
2446                 return "array";
2447              case xmlrpc_vector_mixed:
2448                 return "mixed vector (struct)";
2449              case xmlrpc_vector_struct:
2450                 return "struct";
2451           }
2452     }
2453     return "unknown";
2454 }
2455
2456 /****f* VALUE/XMLRPC_ServerFindMethod
2457  * NAME
2458  *   XMLRPC_ServerFindMethod
2459  * SYNOPSIS
2460  *   XMLRPC_Callback XMLRPC_ServerFindMethod(XMLRPC_SERVER server, const char* callName)
2461  * FUNCTION
2462  *   retrieve C callback associated with a given method name.
2463  * INPUTS       
2464  *   server     The XMLRPC_SERVER the method is registered with
2465  *   callName   the method to find
2466  * RESULT
2467  *   previously registered XMLRPC_Callback, or NULL
2468  * NOTES
2469  *   Typically, this is used to determine if a requested method exists, without actually calling it.
2470  * SEE ALSO
2471  *   XMLRPC_ServerCallMethod ()
2472  *   XMLRPC_ServerRegisterMethod ()
2473  * SOURCE
2474  */
2475 XMLRPC_Callback XMLRPC_ServerFindMethod(XMLRPC_SERVER server, const char* callName) {
2476    if(server && callName) {
2477       q_iter qi = Q_Iter_Head_F(&server->methodlist);
2478       while( qi ) {
2479          server_method* sm = Q_Iter_Get_F(qi);
2480          if(sm && !strcmp(sm->name, callName)) {
2481             return sm->method;
2482          }
2483          qi = Q_Iter_Next_F(qi);
2484       }
2485    }
2486    return NULL;
2487 }
2488
2489 /*******/
2490
2491
2492 /* Call method specified in request */
2493 /****f* VALUE/XMLRPC_ServerCallMethod
2494  * NAME
2495  *   XMLRPC_ServerCallMethod
2496  * SYNOPSIS
2497  *   XMLRPC_VALUE XMLRPC_ServerCallMethod(XMLRPC_SERVER server, XMLRPC_REQUEST request, void* userData)
2498  * FUNCTION
2499  *
2500  * INPUTS
2501  *   server     The XMLRPC_SERVER the method is registered with
2502  *   request    the request to handle
2503  *   userData   any additional data to pass to the C callback, or NULL
2504  * RESULT
2505  *   XMLRPC_VALUE allocated by the callback, or NULL
2506  * NOTES
2507  *   It is typically the caller's responsibility to free the returned value.
2508  *
2509  *   Often the caller will want to serialize the result as XML, via 
2510  *   XMLRPC_VALUE_To_XML () or XMLRPC_REQUEST_To_XML ()
2511  * SEE ALSO
2512  *   XMLRPC_ServerFindMethod ()
2513  *   XMLRPC_ServerRegisterMethod ()
2514  *   XMLRPC_CleanupValue ()
2515  * SOURCE
2516  */
2517 XMLRPC_VALUE XMLRPC_ServerCallMethod(XMLRPC_SERVER server, XMLRPC_REQUEST request, void* userData) {
2518    XMLRPC_VALUE xReturn = NULL;
2519
2520    /* check for error set during request parsing / generation */
2521    if(request && request->error) {
2522       xReturn = XMLRPC_CopyValue(request->error);
2523    }
2524         else if (server && request) {
2525                 XMLRPC_Callback cb =
2526                 XMLRPC_ServerFindMethod (server, request->methodName.str);
2527       if(cb) {
2528          xReturn = cb(server, request, userData);
2529       }
2530       else {
2531                         xReturn =
2532                         XMLRPC_UtilityCreateFault (xmlrpc_error_unknown_method,
2533                                                                                                 request->methodName.str);
2534       }
2535    }
2536    return xReturn;
2537 }
2538
2539 /*******/
2540
2541 /*-*****************
2542 * End server funcs *
2543 *******************/
2544
2545
2546 /*-***********************************
2547 * Begin XMLRPC General Options funcs *
2548 *************************************/
2549
2550 /* For options used by XMLRPC_VALUE funcs that otherwise do not have
2551  * parameters for options.  Kind of gross.  :(
2552  */
2553 typedef struct _xmlrpc_options {
2554    XMLRPC_CASE id_case;
2555    XMLRPC_CASE_COMPARISON id_case_compare;
2556 }
2557 STRUCT_XMLRPC_OPTIONS, *XMLRPC_OPTIONS;
2558
2559 static XMLRPC_OPTIONS XMLRPC_GetDefaultOptions() {
2560    static STRUCT_XMLRPC_OPTIONS options = {
2561       xmlrpc_case_exact,
2562       xmlrpc_case_sensitive
2563    };
2564    return &options;
2565 }
2566
2567 /****f* VALUE/XMLRPC_GetDefaultIdCase
2568  * NAME
2569  *   XMLRPC_GetDefaultIdCase
2570  * SYNOPSIS
2571  *   XMLRPC_CASE XMLRPC_GetDefaultIdCase()
2572  * FUNCTION
2573  *   Gets default case options used by XMLRPC_VALUE funcs
2574  * INPUTS
2575  *   none
2576  * RESULT
2577  *   XMLRPC_CASE
2578  * BUGS
2579  *   Nasty and gross.  Should be server specific, but that requires changing all
2580  *  the XMLRPC_VALUE api's.
2581  * SEE ALSO
2582  *   XMLRPC_SetDefaultIdCase ()
2583  * SOURCE
2584  */
2585 XMLRPC_CASE XMLRPC_GetDefaultIdCase() {
2586    XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2587    return options->id_case;
2588 }
2589
2590 /*******/
2591
2592 /****f* VALUE/XMLRPC_SetDefaultIdCase
2593  * NAME
2594  *   XMLRPC_SetDefaultIdCase
2595  * SYNOPSIS
2596  *   XMLRPC_CASE XMLRPC_SetDefaultIdCase(XMLRPC_CASE id_case)
2597  * FUNCTION
2598  *   Sets default case options used by XMLRPC_VALUE funcs
2599  * INPUTS
2600  *   id_case   case options as enumerated by XMLRPC_CASE
2601  * RESULT
2602  *   XMLRPC_CASE -- newly set option
2603  * BUGS
2604  *   Nasty and gross.  Should be server specific, but that requires changing all
2605  *  the XMLRPC_VALUE api's.
2606  * SEE ALSO
2607  *   XMLRPC_GetDefaultIdCase ()
2608  * SOURCE
2609  */
2610 XMLRPC_CASE XMLRPC_SetDefaultIdCase(XMLRPC_CASE id_case) {
2611    XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2612    options->id_case = id_case;
2613    return options->id_case;
2614 }
2615
2616 /*******/
2617
2618 /****f* VALUE/XMLRPC_GetDefaultIdCaseComparison
2619  * NAME
2620  *   XMLRPC_GetDefaultIdCaseComparison
2621  * SYNOPSIS
2622  *   XMLRPC_CASE XMLRPC_GetDefaultIdCaseComparison( )
2623  * FUNCTION
2624  *   Gets default case comparison options used by XMLRPC_VALUE funcs
2625  * INPUTS
2626  *   none
2627  * RESULT
2628  *   XMLRPC_CASE_COMPARISON default
2629  * BUGS
2630  *   Nasty and gross.  Should be server specific, but that requires changing all
2631  *  the XMLRPC_VALUE api's.
2632  * SEE ALSO
2633  *   XMLRPC_SetDefaultIdCaseComparison ()
2634  * SOURCE
2635  */
2636 XMLRPC_CASE_COMPARISON XMLRPC_GetDefaultIdCaseComparison() {
2637    XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2638    return options->id_case_compare;
2639 }
2640
2641 /*******/
2642
2643 /****f* VALUE/XMLRPC_SetDefaultIdCaseComparison
2644  * NAME
2645  *   XMLRPC_SetDefaultIdCaseComparison
2646  * SYNOPSIS
2647  *   XMLRPC_CASE XMLRPC_SetDefaultIdCaseComparison( XMLRPC_CASE_COMPARISON id_case_compare )
2648  * FUNCTION
2649  *   Gets default case comparison options used by XMLRPC_VALUE funcs
2650  * INPUTS
2651  *   id_case_compare  case comparison rule to set as default
2652  * RESULT
2653  *   XMLRPC_CASE_COMPARISON newly set default
2654  * BUGS
2655  *   Nasty and gross.  Should be server specific, but that requires changing all
2656  *  the XMLRPC_VALUE api's.
2657  * SEE ALSO
2658  *   XMLRPC_GetDefaultIdCaseComparison ()
2659  * SOURCE
2660  */
2661 XMLRPC_CASE_COMPARISON XMLRPC_SetDefaultIdCaseComparison(XMLRPC_CASE_COMPARISON id_case_compare) {
2662    XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2663    options->id_case_compare = id_case_compare;
2664    return options->id_case_compare;
2665 }
2666
2667 /*******/
2668
2669 /*-*********************************
2670 * End XMLRPC General Options funcs *
2671 ***********************************/
2672
2673
2674 /*-******************
2675 * Fault API funcs   *
2676 ********************/
2677
2678 /****f* UTILITY/XMLRPC_UtilityCreateFault
2679  * NAME
2680  *   XMLRPC_UtilityCreateFault
2681  * SYNOPSIS
2682  *   XMLRPC_VALUE XMLRPC_UtilityCreateFault( int fault_code, const char* fault_string )
2683  * FUNCTION
2684  *   generates a struct containing a string member with id "faultString" and an int member
2685  *   with id "faultCode". When using the xmlrpc xml serialization, these will be translated
2686  *   to <fault><value><struct>... format.
2687  * INPUTS
2688  *   fault_code     application specific error code. can be 0.
2689  *   fault_string   application specific error string.  cannot be null.
2690  * RESULT
2691  *   XMLRPC_VALUE a newly created struct vector representing the error, or null on error.
2692  * NOTES
2693  *   This is a utility function. xmlrpc "faults" are not directly represented in this xmlrpc
2694  *   API or data structures. It is the author's view, that this API is intended for simple
2695  *   data types, and a "fault" is a complex data type consisting of multiple simple data
2696  *   types.  This function is provided for convenience only, the same result could be
2697  *   achieved directly by the application.
2698  *
2699  *   This function now supports some "standardized" fault codes, as specified at.
2700  *   http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php.
2701  *   If one of these fault codes is received, the description string will automatically
2702  *   be prefixed with a standard error string and 2 newlines.  
2703  *
2704  *   The actual transformation between this complex type and the xml "<fault>" element takes
2705  *   place in the xmlrpc to xml serialization layer.  This step is not performed when using the
2706  *   simplerpc serialization, meaning that there will be no "<fault>" element in that
2707  *   serialization. There will simply be a standard struct with 2 child elements.  
2708  *   imho, the "<fault>" element is unnecessary and/or out of place as part of the standard API.
2709  *
2710  * SOURCE
2711  */
2712 XMLRPC_VALUE XMLRPC_UtilityCreateFault(int fault_code, const char* fault_string) {
2713    XMLRPC_VALUE xOutput = NULL;
2714
2715    char* string = NULL;
2716    simplestring description;
2717    simplestring_init(&description);
2718
2719    switch (fault_code) {
2720         case xmlrpc_error_parse_xml_syntax:
2721                 string = xmlrpc_error_parse_xml_syntax_str;
2722                 break;
2723         case xmlrpc_error_parse_unknown_encoding:
2724                 string = xmlrpc_error_parse_unknown_encoding_str;
2725                 break;
2726         case xmlrpc_error_parse_bad_encoding:
2727                 string = xmlrpc_error_parse_bad_encoding_str;
2728                 break;
2729         case xmlrpc_error_invalid_xmlrpc:
2730                 string = xmlrpc_error_invalid_xmlrpc_str;
2731                 break;
2732         case xmlrpc_error_unknown_method:
2733                 string = xmlrpc_error_unknown_method_str;
2734                 break;
2735         case xmlrpc_error_invalid_params:
2736                 string = xmlrpc_error_invalid_params_str;
2737                 break;
2738         case xmlrpc_error_internal_server:
2739                 string = xmlrpc_error_internal_server_str;
2740                 break;
2741         case xmlrpc_error_application:
2742                 string = xmlrpc_error_application_str;
2743                 break;
2744         case xmlrpc_error_system:
2745                 string = xmlrpc_error_system_str;
2746                 break;
2747         case xmlrpc_error_transport:
2748                 string = xmlrpc_error_transport_str;
2749                 break;
2750    }
2751
2752    simplestring_add(&description, string);
2753
2754    if(string && fault_string) {
2755       simplestring_add(&description, "\n\n");
2756    }
2757    simplestring_add(&description, fault_string);
2758
2759
2760    if(description.len) {
2761       xOutput = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
2762
2763                 XMLRPC_VectorAppendString (xOutput, "faultString", description.str,
2764                                                                                         description.len);
2765       XMLRPC_VectorAppendInt(xOutput, "faultCode", fault_code);
2766    }
2767
2768    simplestring_free(&description);
2769
2770    return xOutput;
2771 }
2772
2773 /*******/
2774
2775
2776 /****f* FAULT/XMLRPC_ValueIsFault
2777  * NAME
2778  *   XMLRPC_ValueIsFault
2779  * SYNOPSIS
2780  *   int XMLRPC_ValueIsFault (XMLRPC_VALUE value)
2781  * FUNCTION
2782  *   Determines if a value encapsulates a fault "object"
2783  * INPUTS
2784  *   value  any XMLRPC_VALUE
2785  * RESULT
2786  *   1 if it is a fault, else 0
2787  * SEE ALSO
2788  *   XMLRPC_ResponseIsFault ()
2789  * SOURCE
2790  */
2791 int XMLRPC_ValueIsFault (XMLRPC_VALUE value) {
2792    if( XMLRPC_VectorGetValueWithID(value, "faultCode") &&
2793        XMLRPC_VectorGetValueWithID(value, "faultString") ) {
2794       return 1;
2795    }
2796    return 0;
2797 }
2798 /*******/
2799
2800
2801 /****f* FAULT/XMLRPC_ResponseIsFault
2802  * NAME
2803  *   XMLRPC_ResponseIsFault
2804  * SYNOPSIS
2805  *   int XMLRPC_ResponseIsFault (XMLRPC_REQUEST response)
2806  * FUNCTION
2807  *   Determines if a response contains an encapsulated fault "object"
2808  * INPUTS
2809  *   value  any XMLRPC_REQUEST. typically of type xmlrpc_request_response
2810  * RESULT
2811  *   1 if it contains a fault, else 0
2812  * SEE ALSO
2813  *   XMLRPC_ValueIsFault ()
2814  * SOURCE
2815  */
2816 int XMLRPC_ResponseIsFault(XMLRPC_REQUEST response) {
2817    return XMLRPC_ValueIsFault( XMLRPC_RequestGetData(response) );
2818 }
2819
2820 /*******/
2821
2822 /****f* FAULT/XMLRPC_GetValueFaultCode
2823  * NAME
2824  *   XMLRPC_GetValueFaultCode
2825  * SYNOPSIS
2826  *   int XMLRPC_GetValueFaultCode (XMLRPC_VALUE value)
2827  * FUNCTION
2828  *   returns fault code from a struct, if any
2829  * INPUTS
2830  *   value  XMLRPC_VALUE of type xmlrpc_vector_struct.
2831  * RESULT
2832  *   fault code, else 0.
2833  * BUGS
2834  *   impossible to distinguish faultCode == 0 from faultCode not present.
2835  * SEE ALSO
2836  *   XMLRPC_GetResponseFaultCode ()
2837  * SOURCE
2838  */
2839 int XMLRPC_GetValueFaultCode (XMLRPC_VALUE value) {
2840    return XMLRPC_VectorGetIntWithID(value, "faultCode");
2841 }
2842
2843 /*******/
2844
2845 /****f* FAULT/XMLRPC_GetResponseFaultCode
2846  * NAME
2847  *   XMLRPC_GetResponseFaultCode
2848  * SYNOPSIS
2849  *   int XMLRPC_GetResponseFaultCode(XMLRPC_REQUEST response)
2850  * FUNCTION
2851  *   returns fault code from a response, if any
2852  * INPUTS
2853  *   response  XMLRPC_REQUEST. typically of type xmlrpc_request_response.
2854  * RESULT
2855  *   fault code, else 0.
2856  * BUGS
2857  *   impossible to distinguish faultCode == 0 from faultCode not present.
2858  * SEE ALSO
2859  *   XMLRPC_GetValueFaultCode ()
2860  * SOURCE
2861  */
2862 int XMLRPC_GetResponseFaultCode(XMLRPC_REQUEST response) {
2863    return XMLRPC_GetValueFaultCode( XMLRPC_RequestGetData(response) );
2864 }
2865
2866 /*******/
2867
2868
2869 /****f* FAULT/XMLRPC_GetValueFaultString
2870  * NAME
2871  *   XMLRPC_GetValueFaultString
2872  * SYNOPSIS
2873  *   const char* XMLRPC_GetValueFaultString (XMLRPC_VALUE value)
2874  * FUNCTION
2875  *   returns fault string from a struct, if any
2876  * INPUTS
2877  *   value  XMLRPC_VALUE of type xmlrpc_vector_struct.
2878  * RESULT
2879  *   fault string, else 0.
2880  * SEE ALSO
2881  *   XMLRPC_GetResponseFaultString ()
2882  * SOURCE
2883  */
2884 const char* XMLRPC_GetValueFaultString (XMLRPC_VALUE value) {
2885    return XMLRPC_VectorGetStringWithID(value, "faultString");
2886 }
2887
2888 /*******/
2889
2890 /****f* FAULT/XMLRPC_GetResponseFaultString
2891  * NAME
2892  *   XMLRPC_GetResponseFaultString
2893  * SYNOPSIS
2894  *   const char* XMLRPC_GetResponseFaultString (XMLRPC_REQUEST response)
2895  * FUNCTION
2896  *   returns fault string from a response, if any
2897  * INPUTS
2898  *   response  XMLRPC_REQUEST. typically of type xmlrpc_request_response.
2899  * RESULT
2900  *   fault string, else 0.
2901  * SEE ALSO
2902  *   XMLRPC_GetValueFaultString ()
2903  * SOURCE
2904  */
2905 const char* XMLRPC_GetResponseFaultString (XMLRPC_REQUEST response) {
2906    return XMLRPC_GetValueFaultString( XMLRPC_RequestGetData(response) );
2907 }
2908
2909 /*******/
2910
2911
2912 /*-******************
2913 * Utility API funcs *
2914 ********************/
2915
2916
2917 /****f* UTILITY/XMLRPC_Free
2918  * NAME
2919  *   XMLRPC_Free
2920  * SYNOPSIS
2921  *   void XMLRPC_Free(void* mem)
2922  * FUNCTION
2923  *   frees a block of memory allocated by xmlrpc. 
2924  * INPUTS
2925  *   mem    memory to free
2926  * RESULT
2927  *   void
2928  * NOTES
2929  *   Useful for OS's where memory must be free'd
2930  *   in the same library in which it is allocated.
2931  * SOURCE
2932  */
2933 void XMLRPC_Free(void* mem) {
2934    my_free(mem);
2935 }
2936
2937 /*******/
2938
2939
2940 /****f* UTILITY/XMLRPC_GetVersionString
2941  * NAME
2942  *   XMLRPC_GetVersionString
2943  * SYNOPSIS
2944  *   const char* XMLRPC_GetVersionString()
2945  * FUNCTION
2946  *   returns library version string
2947  * INPUTS
2948  *   
2949  * RESULT
2950  *   const char* 
2951  * NOTES
2952  * SOURCE
2953  */
2954 const char*  XMLRPC_GetVersionString() {
2955    return XMLRPC_VERSION_STR;
2956 }
2957
2958 /*******/
2959
2960
2961 /*-**********************
2962 * End Utility API funcs *
2963 ************************/