Back to index

php5  5.3.10
xmlrpc.c
Go to the documentation of this file.
00001 /*
00002   This file is part of libXMLRPC - a C library for xml-encoded function calls.
00003 
00004   Author: Dan Libby (dan@libby.com)
00005   Epinions.com may be contacted at feedback@epinions-inc.com
00006 */
00007 
00008 /*  
00009   Copyright 2000 Epinions, Inc. 
00010 
00011   Subject to the following 3 conditions, Epinions, Inc.  permits you, free 
00012   of charge, to (a) use, copy, distribute, modify, perform and display this 
00013   software and associated documentation files (the "Software"), and (b) 
00014   permit others to whom the Software is furnished to do so as well.  
00015 
00016   1) The above copyright notice and this permission notice shall be included 
00017   without modification in all copies or substantial portions of the 
00018   Software.  
00019 
00020   2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF 
00021   ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY 
00022   IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR 
00023   PURPOSE OR NONINFRINGEMENT.  
00024 
00025   3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, 
00026   SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT 
00027   OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING 
00028   NEGLIGENCE), EVEN IF EPINIONS, INC.  IS AWARE OF THE POSSIBILITY OF SUCH 
00029   DAMAGES.    
00030 
00031 */
00032 
00033 
00034 static const char rcsid[] = "#(@) $Id: xmlrpc.c 270900 2008-12-09 17:22:12Z iliaa $";
00035 
00036 
00037 /****h* ABOUT/xmlrpc
00038  * NAME
00039  *   XMLRPC_VALUE
00040  * AUTHOR
00041  *   Dan Libby, aka danda  (dan@libby.com)
00042  * CREATION DATE
00043  *   9/1999 - 10/2000
00044  * HISTORY
00045  *   $Log$
00046  *   Revision 1.8.4.3.2.1  2008/09/10 00:07:44  felipe
00047  *   MFH:
00048  *   - Merged fix from SF project (Import Jeff Lawsons patches for XML datetime bug fixes)
00049  *     Fixed bugs:
00050  *     #45226 (xmlrpc_set_type() segfaults with valid ISO8601 date string)
00051  *     #18916 (xmlrpc_set_type() "not working")
00052  *
00053  *   Revision 1.8.4.3  2007/09/18 19:49:53  iliaa
00054  *
00055  *   Fixed bug #42189 (xmlrpc_set_type() crashes php on invalid datetime
00056  *     values).
00057  *
00058  *   Revision 1.8.4.2  2007/06/07 09:07:36  tony2001
00059  *   MFH: php_localtime_r() checks
00060  *
00061  *   Revision 1.8.4.1  2006/11/30 16:38:37  iliaa
00062  *   last set of zts fixes
00063  *
00064  *   Revision 1.8  2005/03/28 00:07:24  edink
00065  *   Reshufle includes to make it compile on windows
00066  *
00067  *   Revision 1.7  2005/03/26 03:13:58  sniper
00068  *   - Made it possible to build ext/xmlrpc with libxml2
00069  *
00070  *   Revision 1.6  2004/04/27 17:33:59  iliaa
00071  *   Removed C++ style comments.
00072  *
00073  *   Revision 1.5  2003/12/16 21:00:21  sniper
00074  *   Fix some compile warnings (patch by Joe Orton)
00075  *
00076  *   Revision 1.4  2002/07/05 04:43:53  danda
00077  *   merged in updates from SF project.  bring php repository up to date with xmlrpc-epi version 0.51
00078  *
00079  *   Revision 1.22  2002/03/09 23:15:44  danda
00080  *   add fault interrogation funcs
00081  *
00082  *   Revision 1.21  2002/03/09 22:27:41  danda
00083  *   win32 build patches contributed by Jeff Lawson
00084  *
00085  *   Revision 1.20  2002/02/13 20:58:50  danda
00086  *   patch to make source more windows friendly, contributed by Jeff Lawson
00087  *
00088  *   Revision 1.19  2001/10/12 23:25:54  danda
00089  *   default to writing xmlrpc
00090  *
00091  *   Revision 1.18  2001/09/29 21:58:05  danda
00092  *   adding cvs log to history section
00093  *
00094  *   10/15/2000 -- danda -- adding robodoc documentation
00095  *   08/2000 -- danda -- PHP C extension that uses XMLRPC                     
00096  *   08/2000 -- danda -- support for two vocabularies: danda-rpc and xml-rpc
00097  *   09/1999 -- danda -- Initial API, before I even knew of standard XMLRPC vocab. Response only.
00098  *   07/2000 -- danda -- wrote new implementation to be compatible with xmlrpc standard and
00099  *                       incorporated some ideas from ensor, most notably the separation of
00100  *                       xml dom from xmlrpc api.
00101  *   06/2000 -- danda -- played with expat-ensor from www.ensor.org.  Cool, but some flaws.
00102  * TODO
00103  * PORTABILITY
00104  *   Coded on RedHat Linux 6.2.  Builds on Solaris x86.  Should build on just
00105  *   about anything with minor mods.
00106  * NOTES
00107  *   Welcome to XMLRPC.  For more info on the specification and history, see
00108  *   http://www.xmlrpc.org.
00109  *
00110  *   This code aims to be a full-featured C implementation of XMLRPC.  It does not
00111  *   have any networking code.  Rather, it is intended to be plugged into apps
00112  *   or libraries with existing networking facilities, eg PHP, apache, perl, mozilla, 
00113  *   home-brew application servers, etc.
00114  *
00115  *   Usage Paradigm:
00116  *     The user of this library will typically be implementing either an XMLRPC server,
00117  *     an XMLRPC client, or both.  The client will use the library to build an in-memory
00118  *     representation of a request, and then serialize (encode) that request into XML. The
00119  *     client will then send the XML to the server via external mechanism.  The server will
00120  *     de-serialize the XML back into an binary representation, call the appropriate registered
00121  *     method -- thereby generating a response.  The response will be serialized into XML and
00122  *     sent back to the client.  The client will de-serialize it into memory, and can
00123  *     iterate through the results via API.
00124  *
00125  *     Both the request and the response may consist of arbitrarily long, arbitrarily nested
00126  *     values.  The values may be one of several types, as defined by XMLRPC_VALUE_TYPE.
00127  *
00128  *   Features and Architecture:
00129  *     - The XML parsing (xml_element.c) is completely independent of the XMLRPC api. In fact,
00130  *       it can be used as a standalone dom implementation.
00131  *     - Because of this, the same XMLRPC data can be serialized into multiple xml vocabularies.
00132  *       It is simply a matter of writing a transport.  So far, two transports have been defined.
00133  *       The default xmlrpc vocab (xml_to_xmlrpc.c), and simple-rpc (xml_to_dandarpc.c) which is 
00134  *       proprietary, but imho more readable, and nice for proprietary legacy reasons.
00135  *     - Various output options, including: xml escaping via CDATA or entity, case folding,
00136  *       vocab version, and character encoding.
00137  *     - One to One mapping between C structures and actual values, unlike ensor which forces
00138  *       one to understand the arcana of the xmlrpc vocab.
00139  *     - support for mixed indexed/keyed vector types, making it more compatible with 
00140  *       languages such as PHP.
00141  *     - quite speedy compared to implementations written in interpreted languages. Also, uses
00142  *       intelligent string handling, so not many strlen() calls, etc.
00143  *     - comprehensive API for manipulation of values
00144  *******/
00145 
00146 #include "ext/xml/expat_compat.h"
00147 #include "main/php_reentrancy.h"
00148 #ifdef _WIN32
00149 #include "xmlrpc_win32.h"
00150 #endif
00151 #include <stdio.h>
00152 #include <stdlib.h>
00153 #include <string.h>
00154 #include <stdarg.h>
00155 #include <time.h>
00156 #include <ctype.h>
00157 
00158 #include "queue.h"
00159 #include "xmlrpc.h"
00160 #include "base64.h"
00161 
00162 #include "xml_to_xmlrpc.h"
00163 #include "xml_to_dandarpc.h"
00164 #include "xml_to_soap.h"
00165 #include "xml_element.h"
00166 #include "xmlrpc_private.h"
00167 #include "xmlrpc_introspection_private.h"
00168 #include "system_methods_private.h"
00169 
00170 
00171 
00172 /*-*********************
00173 * Begin Time Functions *
00174 ***********************/
00175 
00176 static time_t mkgmtime(struct tm *tm)
00177 {
00178     static const int mdays[12] = {0,31,59,90,120,151,181,212,243,273,304,334};
00179 
00180     return ((((((tm->tm_year - 70) * 365) + mdays[tm->tm_mon] + tm->tm_mday-1 +
00181                   (tm->tm_year-68-1+(tm->tm_mon>=2))/4) * 24) + tm->tm_hour) * 60 +
00182         tm->tm_min) * 60 + tm->tm_sec;
00183 }
00184 
00185 static int date_from_ISO8601 (const char *text, time_t * value) {
00186    struct tm tm;
00187    int n;
00188    int i;
00189    char buf[30];
00190        
00191 
00192        if (strchr (text, '-')) {
00193               char *p = (char *) text, *p2 = buf;
00194               while (p && *p) {
00195                      if (*p != '-') {
00196                             *p2 = *p;
00197                             p2++;
00198                             if (p2-buf >= sizeof(buf)) {
00199                                    return -1;
00200                             }
00201                      }
00202                      p++;
00203               }
00204                      text = buf;
00205        }
00206 
00207 
00208    tm.tm_isdst = -1;
00209 
00210 #define XMLRPC_IS_NUMBER(x) if (x < '0' || x > '9') return -1;
00211 
00212    n = 1000;
00213    tm.tm_year = 0;
00214    for(i = 0; i < 4; i++) {
00215       XMLRPC_IS_NUMBER(text[i])
00216       tm.tm_year += (text[i]-'0')*n;
00217       n /= 10;
00218    }
00219    n = 10;
00220    tm.tm_mon = 0;
00221    for(i = 0; i < 2; i++) {
00222       XMLRPC_IS_NUMBER(text[i])
00223       tm.tm_mon += (text[i+4]-'0')*n;
00224       n /= 10;
00225    }
00226    tm.tm_mon --;
00227 
00228    n = 10;
00229    tm.tm_mday = 0;
00230    for(i = 0; i < 2; i++) {
00231       XMLRPC_IS_NUMBER(text[i])
00232       tm.tm_mday += (text[i+6]-'0')*n;
00233       n /= 10;
00234    }
00235 
00236    n = 10;
00237    tm.tm_hour = 0;
00238    for(i = 0; i < 2; i++) {
00239       XMLRPC_IS_NUMBER(text[i])
00240       tm.tm_hour += (text[i+9]-'0')*n;
00241       n /= 10;
00242    }
00243 
00244    n = 10;
00245    tm.tm_min = 0;
00246    for(i = 0; i < 2; i++) {
00247       XMLRPC_IS_NUMBER(text[i])
00248       tm.tm_min += (text[i+12]-'0')*n;
00249       n /= 10;
00250    }
00251 
00252    n = 10;
00253    tm.tm_sec = 0;
00254    for(i = 0; i < 2; i++) {
00255       XMLRPC_IS_NUMBER(text[i])
00256       tm.tm_sec += (text[i+15]-'0')*n;
00257       n /= 10;
00258    }
00259 
00260    tm.tm_year -= 1900;
00261 
00262    *value = mkgmtime(&tm);
00263 
00264    return 0;
00265 
00266 }
00267 
00268 static int date_to_ISO8601 (time_t value, char *buf, int length) {
00269    struct tm *tm, tmbuf;
00270    tm = php_gmtime_r(&value, &tmbuf);
00271    if (!tm) {
00272           return 0;
00273    }
00274 #if 0  /* TODO: soap seems to favor this method. xmlrpc the latter. */
00275        return strftime (buf, length, "%Y-%m-%dT%H:%M:%SZ", tm);
00276 #else
00277    return strftime(buf, length, "%Y%m%dT%H:%M:%SZ", tm);
00278 #endif
00279 }
00280 
00281 /*-*******************
00282 * End Time Functions *
00283 *********************/
00284 
00285 
00286 /*-***************************
00287 * Begin XMLRPC_REQUEST funcs *
00288 *****************************/
00289 
00290 /****f* REQUEST/XMLRPC_RequestNew
00291  * NAME
00292  *   XMLRPC_RequestNew
00293  * SYNOPSIS
00294  *   XMLRPC_REQUEST XMLRPC_RequestNew()
00295  * FUNCTION
00296  *   Creates a new XMLRPC_Request data struct
00297  * INPUTS
00298  *   none
00299  * SEE ALSO
00300  *   XMLRPC_RequestFree ()
00301  * SOURCE
00302  */
00303 XMLRPC_REQUEST XMLRPC_RequestNew() {
00304    XMLRPC_REQUEST xRequest = calloc(1, sizeof(STRUCT_XMLRPC_REQUEST));
00305    if(xRequest) {
00306       simplestring_init(&xRequest->methodName);
00307    }
00308    return xRequest;
00309 }
00310 
00311 /*******/
00312 
00313 /****f* REQUEST/XMLRPC_RequestFree
00314  * NAME
00315  *   XMLRPC_RequestFree
00316  * SYNOPSIS
00317  *   void XMLRPC_RequestFree(XMLRPC_REQUEST request, int bFreeIO)
00318  * FUNCTION
00319  *   Free XMLRPC Request and all sub-values
00320  * INPUTS
00321  *   request -- previously allocated request struct
00322  *   bFreeIO -- 1 = also free request value data, if any, 0 = ignore.
00323  * SEE ALSO
00324  *   XMLRPC_RequestNew ()
00325  *   XMLRPC_CleanupValue ()
00326  * SOURCE
00327  */
00328 void XMLRPC_RequestFree(XMLRPC_REQUEST request, int bFreeIO) {
00329    if(request) {
00330       simplestring_free(&request->methodName);
00331 
00332       if(request->io && bFreeIO) {
00333          XMLRPC_CleanupValue(request->io);
00334       }
00335       if(request->error) {
00336          XMLRPC_CleanupValue(request->error);
00337       }
00338       my_free(request);
00339    }
00340 }
00341 
00342 /*******/
00343 
00344 /* Set Method Name to call */
00345 /****f* REQUEST/XMLRPC_RequestSetMethodName
00346  * NAME
00347  *   XMLRPC_RequestSetMethodName
00348  * SYNOPSIS
00349  *   const char* XMLRPC_RequestSetMethodName(XMLRPC_REQUEST request, const char* methodName)
00350  * FUNCTION
00351  *   Set name of method to call with this request.
00352  * INPUTS
00353  *   request -- previously allocated request struct
00354  *   methodName -- name of method
00355  * SEE ALSO
00356  *   XMLRPC_RequestNew ()
00357  *   XMLRPC_RequestGetMethodName ()
00358  *   XMLRPC_RequestFree ()
00359  * SOURCE
00360  */
00361 const char* XMLRPC_RequestSetMethodName(XMLRPC_REQUEST request, const char* methodName) {
00362    if(request) {
00363       simplestring_clear(&request->methodName);
00364       simplestring_add(&request->methodName, methodName);
00365       return request->methodName.str;
00366    }
00367    return NULL;
00368 }
00369 
00370 /*******/
00371 
00372 /****f* REQUEST/XMLRPC_RequestGetMethodName
00373  * NAME
00374  *   XMLRPC_RequestGetMethodName
00375  * SYNOPSIS
00376  *   const char* XMLRPC_RequestGetMethodName(XMLRPC_REQUEST request)
00377  * FUNCTION
00378  *   Get name of method called by this request
00379  * INPUTS
00380  *   request -- previously allocated request struct
00381  * SEE ALSO
00382  *   XMLRPC_RequestNew ()
00383  *   XMLRPC_RequestSetMethodName ()
00384  *   XMLRPC_RequestFree ()
00385  * SOURCE
00386  */
00387 const char* XMLRPC_RequestGetMethodName(XMLRPC_REQUEST request) {
00388    return request ? request->methodName.str : NULL;
00389 }
00390 
00391 /*******/
00392 
00393 /****f* REQUEST/XMLRPC_RequestSetRequestType
00394  * NAME
00395  *   XMLRPC_RequestSetRequestType
00396  * SYNOPSIS
00397  *   XMLRPC_REQUEST_TYPE XMLRPC_RequestSetRequestType(XMLRPC_REQUEST request, XMLRPC_REQUEST_TYPE type)
00398  * FUNCTION
00399  *   A request struct may be allocated by a caller or by xmlrpc
00400  *   in response to a request.  This allows setting the
00401  *   request type.
00402  * INPUTS
00403  *   request -- previously allocated request struct
00404  *   type    -- request type [xmlrpc_method_call | xmlrpc_method_response]
00405  * SEE ALSO
00406  *   XMLRPC_RequestNew ()
00407  *   XMLRPC_RequestGetRequestType ()
00408  *   XMLRPC_RequestFree ()
00409  *   XMLRPC_REQUEST_TYPE
00410  * SOURCE
00411  */
00412 XMLRPC_REQUEST_TYPE XMLRPC_RequestSetRequestType (XMLRPC_REQUEST request,
00413                                                                                                                   XMLRPC_REQUEST_TYPE type) {
00414    if(request) {
00415       request->request_type = type;
00416       return request->request_type;
00417    }
00418    return xmlrpc_request_none;
00419 }
00420 
00421 /*******/
00422 
00423 /****f* REQUEST/XMLRPC_RequestGetRequestType
00424  * NAME
00425  *   XMLRPC_RequestGetRequestType
00426  * SYNOPSIS
00427  *   XMLRPC_REQUEST_TYPE XMLRPC_RequestGetRequestType(XMLRPC_REQUEST request)
00428  * FUNCTION
00429  *   A request struct may be allocated by a caller or by xmlrpc
00430  *   in response to a request.  This allows setting the
00431  *   request type.
00432  * INPUTS
00433  *   request -- previously allocated request struct
00434  * RESULT
00435  *   type    -- request type [xmlrpc_method_call | xmlrpc_method_response]
00436  * SEE ALSO
00437  *   XMLRPC_RequestNew ()
00438  *   XMLRPC_RequestSetRequestType ()
00439  *   XMLRPC_RequestFree ()
00440  *   XMLRPC_REQUEST_TYPE
00441  * SOURCE
00442  */
00443 XMLRPC_REQUEST_TYPE XMLRPC_RequestGetRequestType(XMLRPC_REQUEST request) {
00444    return request ? request->request_type : xmlrpc_request_none;
00445 }
00446 
00447 /*******/
00448 
00449 
00450 /****f* REQUEST/XMLRPC_RequestSetData
00451  * NAME
00452  *   XMLRPC_RequestSetData
00453  * SYNOPSIS
00454  *   XMLRPC_VALUE XMLRPC_RequestSetData(XMLRPC_REQUEST request, XMLRPC_VALUE data)
00455  * FUNCTION
00456  *   Associates a block of xmlrpc data with the request.  The
00457  *   data is *not* copied.  A pointer is kept.  The caller
00458  *   should be careful not to doubly free the data value,
00459  *   which may optionally be free'd by XMLRPC_RequestFree().
00460  * INPUTS
00461  *   request -- previously allocated request struct
00462  *   data    -- previously allocated data struct
00463  * RESULT
00464  *   XMLRPC_VALUE -- pointer to value stored, or NULL
00465  * SEE ALSO
00466  *   XMLRPC_RequestNew ()
00467  *   XMLRPC_RequestGetData ()
00468  *   XMLRPC_RequestFree ()
00469  *   XMLRPC_REQUEST
00470  *   XMLRPC_VALUE
00471  * SOURCE
00472  */
00473 XMLRPC_VALUE XMLRPC_RequestSetData(XMLRPC_REQUEST request, XMLRPC_VALUE data) {
00474    if(request && data) {
00475               if (request->io) {
00476                      XMLRPC_CleanupValue (request->io);
00477               }
00478       request->io = XMLRPC_CopyValue(data);
00479       return request->io;
00480    }
00481    return NULL;
00482 }
00483 
00484 /*******/
00485 
00486 /****f* REQUEST/XMLRPC_RequestGetData
00487  * NAME
00488  *   XMLRPC_RequestGetData
00489  * SYNOPSIS
00490  *   XMLRPC_VALUE XMLRPC_RequestGetData(XMLRPC_REQUEST request)
00491  * FUNCTION
00492  *   Returns data associated with request, if any.
00493  * INPUTS
00494  *   request -- previously allocated request struct
00495  * RESULT
00496  *   XMLRPC_VALUE -- pointer to value stored, or NULL
00497  * SEE ALSO
00498  *   XMLRPC_RequestNew ()
00499  *   XMLRPC_RequestSetData ()
00500  *   XMLRPC_RequestFree ()
00501  *   XMLRPC_REQUEST
00502  *   XMLRPC_VALUE
00503  * SOURCE
00504  */
00505 XMLRPC_VALUE XMLRPC_RequestGetData(XMLRPC_REQUEST request) {
00506    return request ? request->io : NULL;
00507 }
00508 
00509 /*******/
00510 
00511 /****f* REQUEST/XMLRPC_RequestSetError
00512  * NAME
00513  *   XMLRPC_RequestSetError
00514  * SYNOPSIS
00515  *   XMLRPC_VALUE XMLRPC_RequestSetError(XMLRPC_REQUEST request, XMLRPC_VALUE error)
00516  * FUNCTION
00517  *   Associates a block of xmlrpc data, representing an error
00518  *   condition, with the request. 
00519  * INPUTS
00520  *   request -- previously allocated request struct
00521  *   error   -- previously allocated error code or struct
00522  * RESULT
00523  *   XMLRPC_VALUE -- pointer to value stored, or NULL
00524  * NOTES
00525  *   This is a private function for usage by internals only.
00526  * SEE ALSO
00527  *   XMLRPC_RequestGetError ()
00528  * SOURCE
00529  */
00530 XMLRPC_VALUE XMLRPC_RequestSetError (XMLRPC_REQUEST request, XMLRPC_VALUE error) {
00531        if (request && error) {
00532               if (request->error) {
00533                      XMLRPC_CleanupValue (request->error);
00534               }
00535               request->error = XMLRPC_CopyValue (error);
00536               return request->error;
00537        }
00538        return NULL;
00539 }
00540 
00541 /*******/
00542 
00543 /****f* REQUEST/XMLRPC_RequestGetError
00544  * NAME
00545  *   XMLRPC_RequestGetError
00546  * SYNOPSIS
00547  *   XMLRPC_VALUE XMLRPC_RequestGetError(XMLRPC_REQUEST request)
00548  * FUNCTION
00549  *   Returns error data associated with request, if any.
00550  * INPUTS
00551  *   request -- previously allocated request struct
00552  * RESULT
00553  *   XMLRPC_VALUE -- pointer to error value stored, or NULL
00554  * NOTES
00555  *   This is a private function for usage by internals only.
00556  * SEE ALSO
00557  *   XMLRPC_RequestSetError ()
00558  *   XMLRPC_RequestFree ()
00559  * SOURCE
00560  */
00561 XMLRPC_VALUE XMLRPC_RequestGetError (XMLRPC_REQUEST request) {
00562        return request ? request->error : NULL;
00563 }
00564 
00565 /*******/
00566 
00567 
00568 /****f* REQUEST/XMLRPC_RequestSetOutputOptions
00569  * NAME
00570  *   XMLRPC_RequestSetOutputOptions
00571  * SYNOPSIS
00572  *   XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestSetOutputOptions(XMLRPC_REQUEST request, XMLRPC_REQUEST_OUTPUT_OPTIONS output)
00573  * FUNCTION
00574  *   Sets output options used for generating XML. The output struct
00575  *   is copied, and may be freed by the caller.
00576  * INPUTS
00577  *   request -- previously allocated request struct
00578  *   output  -- output options struct initialized by caller
00579  * RESULT
00580  *   XMLRPC_REQUEST_OUTPUT_OPTIONS -- pointer to value stored, or NULL
00581  * SEE ALSO
00582  *   XMLRPC_RequestNew ()
00583  *   XMLRPC_RequestGetOutputOptions ()
00584  *   XMLRPC_RequestFree ()
00585  *   XMLRPC_REQUEST
00586  *   XMLRPC_REQUEST_OUTPUT_OPTIONS
00587  * SOURCE
00588  */
00589 XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestSetOutputOptions(XMLRPC_REQUEST request, XMLRPC_REQUEST_OUTPUT_OPTIONS output) {
00590    if(request && output) {
00591               memcpy (&request->output, output,
00592                               sizeof (STRUCT_XMLRPC_REQUEST_OUTPUT_OPTIONS));
00593       return &request->output;
00594    }
00595    return NULL;
00596 }
00597 
00598 /*******/
00599 
00600 
00601 /****f* REQUEST/XMLRPC_RequestGetOutputOptions
00602  * NAME
00603  *   XMLRPC_RequestGetOutputOptions
00604  * SYNOPSIS
00605  *   XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestGetOutputOptions(XMLRPC_REQUEST request)
00606  * FUNCTION
00607  *   Gets a pointer to output options used for generating XML.
00608  * INPUTS
00609  *   request -- previously allocated request struct
00610  * RESULT
00611  *   XMLRPC_REQUEST_OUTPUT_OPTIONS -- pointer to options stored, or NULL
00612  * SEE ALSO
00613  *   XMLRPC_RequestNew ()
00614  *   XMLRPC_RequestSetOutputOptions ()
00615  *   XMLRPC_RequestFree ()
00616  *   XMLRPC_REQUEST
00617  *   XMLRPC_REQUEST_OUTPUT_OPTIONS
00618  * SOURCE
00619  */
00620 XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestGetOutputOptions(XMLRPC_REQUEST request) {
00621    return request ? &request->output : NULL;
00622 }
00623 
00624 /*******/
00625 
00626 /*-*************************
00627 * End XMLRPC_REQUEST funcs *
00628 ***************************/
00629 
00630 
00631 /*-***************************
00632 * Begin Serializiation funcs *
00633 *****************************/
00634 
00635 /****f* SERIALIZE/XMLRPC_VALUE_ToXML
00636  * NAME
00637  *   XMLRPC_VALUE_ToXML
00638  * SYNOPSIS
00639  *   char* XMLRPC_VALUE_ToXML(XMLRPC_VALUE val)
00640  * FUNCTION
00641  *   encode XMLRPC_VALUE into XML buffer.  Note that the generated
00642  *   buffer will not contain a methodCall.
00643  * INPUTS
00644  *   val -- previously allocated XMLRPC_VALUE
00645  *   buf_len -- length of returned buffer, if not null
00646  * RESULT
00647  *   char* -- newly allocated buffer containing XML. 
00648  *   It is the caller's responsibility to free it.
00649  * SEE ALSO
00650  *   XMLRPC_REQUEST_ToXML ()
00651  *   XMLRPC_VALUE_FromXML ()
00652  *   XMLRPC_Free ()
00653  *   XMLRPC_VALUE
00654  * SOURCE
00655  */
00656 char* XMLRPC_VALUE_ToXML(XMLRPC_VALUE val, int* buf_len) {
00657    xml_element *root_elem = XMLRPC_VALUE_to_xml_element(val);
00658    char* pRet = NULL;
00659 
00660    if(root_elem) {
00661       pRet = xml_elem_serialize_to_string(root_elem, NULL, buf_len);
00662       xml_elem_free(root_elem);
00663    }
00664    return pRet;
00665 }
00666 
00667 /*******/
00668 
00669 /****f* SERIALIZE/XMLRPC_REQUEST_ToXML
00670  * NAME
00671  *   XMLRPC_REQUEST_ToXML
00672  * SYNOPSIS
00673  *   char* XMLRPC_REQUEST_ToXML(XMLRPC_REQUEST request)
00674  * FUNCTION
00675  *   encode XMLRPC_REQUEST into XML buffer
00676  * INPUTS
00677  *   request -- previously allocated XMLRPC_REQUEST
00678  *   buf_len -- size of returned buf, if not null
00679  * RESULT
00680  *   char* -- newly allocated buffer containing XML. 
00681  *   It is the caller's responsibility to free it.
00682  * SEE ALSO
00683  *   XMLRPC_REQUEST_ToXML ()
00684  *   XMLRPC_REQUEST_FromXML ()
00685  *   XMLRPC_Free ()
00686  *   XMLRPC_VALUE_ToXML ()
00687  *   XMLRPC_REQUEST
00688  * SOURCE
00689  */
00690 char* XMLRPC_REQUEST_ToXML(XMLRPC_REQUEST request, int* buf_len) {
00691       char* pRet = NULL;
00692        if (request) {
00693               xml_element *root_elem = NULL;
00694               if (request->output.version == xmlrpc_version_simple) {
00695                      root_elem = DANDARPC_REQUEST_to_xml_element (request);
00696               }
00697               else if (request->output.version == xmlrpc_version_1_0 ||
00698                                    request->output.version == xmlrpc_version_none) {
00699                      root_elem = XMLRPC_REQUEST_to_xml_element (request);
00700               }
00701               else if (request->output.version == xmlrpc_version_soap_1_1) {
00702                      root_elem = SOAP_REQUEST_to_xml_element (request);
00703               }
00704 
00705       if(root_elem) {
00706                      pRet =
00707                      xml_elem_serialize_to_string (root_elem,
00708                                                                                            &request->output.xml_elem_opts,
00709                                                                                            buf_len);
00710          xml_elem_free(root_elem);
00711       }
00712    }
00713        return pRet;
00714 }
00715 
00716 /*******/
00717 
00718 /****f* SERIALIZE/XMLRPC_VALUE_FromXML
00719  * NAME
00720  *   XMLRPC_VALUE_FromXML
00721  * SYNOPSIS
00722  *   XMLRPC_VALUE XMLRPC_VALUE_FromXML(const char* in_buf, int le
00723  * FUNCTION
00724  *   Retrieve XMLRPC_VALUE from XML buffer. Note that this will
00725  *   ignore any methodCall.  See XMLRPC_REQUEST_FromXML
00726  * INPUTS
00727  *   in_buf -- character buffer containing XML
00728  *   len    -- length of buffer
00729  * RESULT
00730  *   XMLRPC_VALUE -- newly allocated data, or NULL if error. Should
00731  *   be free'd by caller.
00732  * SEE ALSO
00733  *   XMLRPC_VALUE_ToXML ()
00734  *   XMLRPC_REQUEST_FromXML ()
00735  *   XMLRPC_VALUE
00736  * SOURCE
00737  */
00738 XMLRPC_VALUE XMLRPC_VALUE_FromXML (const char *in_buf, int len, XMLRPC_REQUEST_INPUT_OPTIONS in_options) {
00739    XMLRPC_VALUE xResponse = NULL;
00740    XMLRPC_REQUEST req = XMLRPC_REQUEST_FromXML(in_buf, len, in_options);
00741 
00742    if(req) {
00743       xResponse = req->io;
00744       XMLRPC_RequestFree(req, 0);
00745    }
00746    return xResponse;
00747 }
00748 
00749 /*******/
00750 
00751 /* map parser errors to standard xml-rpc errors */
00752 static XMLRPC_VALUE map_expat_errors(XML_ELEM_ERROR error) {
00753    XMLRPC_VALUE xReturn = NULL;
00754    if(error) {
00755       XMLRPC_ERROR_CODE code;
00756       char buf[1024];
00757       snprintf(buf, sizeof(buf), 
00758                "error occurred at line %ld, column %ld, byte index %ld", 
00759                                     error->line, error->column, error->byte_index);
00760 
00761       /* expat specific errors */
00762       switch(error->parser_code) {
00763       case XML_ERROR_UNKNOWN_ENCODING:
00764          code = xmlrpc_error_parse_unknown_encoding;
00765          break;
00766       case XML_ERROR_INCORRECT_ENCODING:
00767          code = xmlrpc_error_parse_bad_encoding;
00768          break;
00769       default:
00770          code = xmlrpc_error_parse_xml_syntax;
00771          break;
00772       }
00773       xReturn = XMLRPC_UtilityCreateFault(code, buf);
00774    }
00775    return xReturn;
00776 }
00777 
00778 /****f* SERIALIZE/XMLRPC_REQUEST_FromXML
00779  * NAME
00780  *   XMLRPC_REQUEST_FromXML
00781  * SYNOPSIS
00782  *   XMLRPC_REQUEST XMLRPC_REQUEST_FromXML(const char* in_buf, int le
00783  * FUNCTION
00784  *   Retrieve XMLRPC_REQUEST from XML buffer
00785  * INPUTS
00786  *   in_buf -- character buffer containing XML
00787  *   len    -- length of buffer
00788  * RESULT
00789  *   XMLRPC_REQUEST -- newly allocated data, or NULL if error. Should
00790  *   be free'd by caller.
00791  * SEE ALSO
00792  *   XMLRPC_REQUEST_ToXML ()
00793  *   XMLRPC_VALUE_FromXML ()
00794  *   XMLRPC_REQUEST
00795  * SOURCE
00796  */
00797 XMLRPC_REQUEST XMLRPC_REQUEST_FromXML (const char *in_buf, int len, 
00798                                                                                            XMLRPC_REQUEST_INPUT_OPTIONS in_options) {
00799    XMLRPC_REQUEST request = XMLRPC_RequestNew();
00800    STRUCT_XML_ELEM_ERROR error = {0};
00801 
00802    if(request) {
00803               xml_element *root_elem =
00804               xml_elem_parse_buf (in_buf, len,
00805                                                           (in_options ? &in_options->xml_elem_opts : NULL),
00806                                                           &error);
00807 
00808       if(root_elem) {
00809          if(!strcmp(root_elem->name, "simpleRPC")) {
00810             request->output.version = xmlrpc_version_simple;
00811             xml_element_to_DANDARPC_REQUEST(request, root_elem);
00812          }
00813                      else if (!strcmp (root_elem->name, "SOAP-ENV:Envelope")) {
00814                             request->output.version = xmlrpc_version_soap_1_1;
00815                             xml_element_to_SOAP_REQUEST (request, root_elem);
00816                      }
00817          else {
00818             request->output.version = xmlrpc_version_1_0;
00819             xml_element_to_XMLRPC_REQUEST(request, root_elem);
00820          }
00821          xml_elem_free(root_elem);
00822       }
00823       else {
00824          if(error.parser_error) {
00825                             XMLRPC_RequestSetError (request, map_expat_errors (&error));
00826          }
00827       }
00828    }
00829 
00830    return request;
00831 }
00832 
00833 /*******/
00834 
00835 /*-************************
00836 * End Serialization Funcs *
00837 **************************/
00838 
00839 
00840 
00841 /****f* VALUE/XMLRPC_CreateValueEmpty
00842  * NAME
00843  *   XMLRPC_CreateValueEmpty
00844  * SYNOPSIS
00845  *   XMLRPC_VALUE XMLRPC_CreateValueEmpty ()
00846  * FUNCTION
00847  *   Create an XML value to be used/modified elsewhere.
00848  * INPUTS
00849  * RESULT
00850  *   XMLRPC_VALUE.  The new value, or NULL on failure.
00851  * SEE ALSO
00852  *   XMLRPC_CleanupValue ()
00853  *   XMLRPC_VALUE
00854  * SOURCE
00855  */
00856 XMLRPC_VALUE XMLRPC_CreateValueEmpty() {
00857    XMLRPC_VALUE v = calloc(1, sizeof(STRUCT_XMLRPC_VALUE));
00858    if(v) {
00859 #ifdef XMLRPC_DEBUG_REFCOUNT
00860               printf ("calloc'd 0x%x\n", v);
00861 #endif
00862       v->type = xmlrpc_empty;
00863       simplestring_init(&v->id);
00864       simplestring_init(&v->str);
00865    }
00866    return v;
00867 }
00868 
00869 /*******/
00870 
00871 /****f* VALUE/XMLRPC_SetValueID_Case
00872  * NAME
00873  *   XMLRPC_SetValueID_Case
00874  * SYNOPSIS
00875  *   const char *XMLRPC_SetValueID_Case(XMLRPC_VALUE value, const char* id, int len, XMLRPC_CASE id_case)
00876  * FUNCTION
00877  *   Assign an ID (key) to an XMLRPC value.
00878  * INPUTS
00879  *   value     The xml value who's ID we will set.
00880  *   id        The desired new id.
00881  *   len       length of id string if known, or 0 if unknown.
00882  *   id_case   one of XMLRPC_CASE
00883  * RESULT
00884  *   const char*  pointer to the newly allocated id string, or NULL
00885  * SEE ALSO
00886  *   XMLRPC_SetValueID ()
00887  *   XMLRPC_GetValueID ()
00888  *   XMLRPC_VALUE
00889  *   XMLRPC_CASE
00890  * SOURCE
00891  */
00892 const char *XMLRPC_SetValueID_Case(XMLRPC_VALUE value, const char* id, int len, XMLRPC_CASE id_case) {
00893    const char* pRetval = NULL;
00894    if(value) {
00895       if(id) {
00896          simplestring_clear(&value->id);
00897          (len > 0) ? simplestring_addn(&value->id, id, len) :
00898                      simplestring_add(&value->id, id);
00899 
00900          /* upper or lower case string in place if required. could be a seperate func. */
00901          if(id_case == xmlrpc_case_lower || id_case == xmlrpc_case_upper) {
00902             int i;
00903             for(i = 0; i < value->id.len; i++) {
00904                                    value->id.str[i] =
00905                                    (id_case ==
00906                                     xmlrpc_case_lower) ? tolower (value->id.
00907                                                                                                           str[i]) : toupper (value->
00908                                                                                                                                                      id.
00909                                                                                                                                                      str[i]);
00910             }
00911          }
00912 
00913          pRetval = value->id.str;
00914 
00915 #ifdef XMLRPC_DEBUG_REFCOUNT
00916          printf("set value id: %s\n", pRetval);
00917 #endif 
00918       }
00919    }
00920 
00921    return pRetval;
00922 }
00923 
00924 /*******/
00925 
00926 
00927 /****f* VALUE/XMLRPC_SetValueString
00928  * NAME
00929  *   XMLRPC_SetValueString
00930  * SYNOPSIS
00931  *   const char *XMLRPC_SetValueString(XMLRPC_VALUE value, const char* val, int len)
00932  * FUNCTION
00933  *   Assign a string value to an XMLRPC_VALUE, and set it to type xmlrpc_string
00934  * INPUTS
00935  *   value     The xml value who's ID we will set.
00936  *   val        The desired new string val.
00937  *   len       length of val string if known, or 0 if unknown.
00938  * RESULT
00939  *   const char*  pointer to the newly allocated value string, or NULL
00940  * SEE ALSO
00941  *   XMLRPC_GetValueString ()
00942  *   XMLRPC_VALUE
00943  *   XMLRPC_VALUE_TYPE
00944  * SOURCE
00945  */
00946 const char *XMLRPC_SetValueString(XMLRPC_VALUE value, const char* val, int len) {
00947    char *pRetval = NULL;
00948    if(value && val) {
00949       simplestring_clear(&value->str);
00950       (len > 0) ? simplestring_addn(&value->str, val, len) :
00951                   simplestring_add(&value->str, val);
00952       value->type = xmlrpc_string;
00953       pRetval = (char *)value->str.str;
00954    }
00955 
00956    return pRetval;
00957 }
00958 
00959 /*******/
00960 
00961 /****f* VALUE/XMLRPC_SetValueInt
00962  * NAME
00963  *   XMLRPC_SetValueInt
00964  * SYNOPSIS
00965  *   void XMLRPC_SetValueInt(XMLRPC_VALUE value, int val)
00966  * FUNCTION
00967  *   Assign an int value to an XMLRPC_VALUE, and set it to type xmlrpc_int
00968  * INPUTS
00969  *   value     The xml value who's ID we will set.
00970  *   val        The desired new integer value
00971  * RESULT
00972  * SEE ALSO
00973  *   XMLRPC_GetValueInt ()
00974  *   XMLRPC_VALUE
00975  *   XMLRPC_VALUE_TYPE
00976  * SOURCE
00977  */
00978 void XMLRPC_SetValueInt(XMLRPC_VALUE value, int val) {
00979    if(value) {
00980       value->type = xmlrpc_int;
00981       value->i = val;
00982    }
00983 }
00984 
00985 /*******/
00986 
00987 /****f* VALUE/XMLRPC_SetValueBoolean
00988  * NAME
00989  *   XMLRPC_SetValueBoolean
00990  * SYNOPSIS
00991  *   void XMLRPC_SetValueBoolean(XMLRPC_VALUE value, int val)
00992  * FUNCTION
00993  *   Assign a boolean value to an XMLRPC_VALUE, and set it to type xmlrpc_boolean
00994  * INPUTS
00995  *   value     The xml value who's value we will set.
00996  *   val        The desired new boolean value. [0 | 1]
00997  * RESULT
00998  * SEE ALSO
00999  *   XMLRPC_GetValueBoolean ()
01000  *   XMLRPC_VALUE
01001  *   XMLRPC_VALUE_TYPE
01002  * SOURCE
01003  */
01004 void XMLRPC_SetValueBoolean(XMLRPC_VALUE value, int val) {
01005    if(value) {
01006       value->type = xmlrpc_boolean;
01007       value->i = val ? 1 : 0;
01008    }
01009 }
01010 
01011 /*******/
01012 
01013 
01014 /****f* VECTOR/XMLRPC_SetIsVector
01015  * NAME
01016  *   XMLRPC_SetIsVector
01017  * SYNOPSIS
01018  *   int XMLRPC_SetIsVector(XMLRPC_VALUE value, XMLRPC_VECTOR_TYPE type)
01019  * FUNCTION
01020  *   Set the XMLRPC_VALUE to be a vector (list) type.  The vector may be one of
01021  *   [xmlrpc_array | xmlrpc_struct | xmlrpc_mixed].  An array has only index values.
01022  *   A struct has key/val pairs.  Mixed allows both index and key/val combinations. 
01023  * INPUTS
01024  *   value     The xml value who's vector type we will set
01025  *   type      New type of vector as enumerated by XMLRPC_VECTOR_TYPE
01026  * RESULT
01027  *   int       1 if successful, 0 otherwise
01028  * SEE ALSO
01029  *   XMLRPC_GetValueType ()
01030  *   XMLRPC_GetVectorType ()
01031  *   XMLRPC_VALUE
01032  *   XMLRPC_VECTOR_TYPE
01033  *   XMLRPC_VALUE_TYPE
01034  * SOURCE
01035  */
01036 int XMLRPC_SetIsVector(XMLRPC_VALUE value, XMLRPC_VECTOR_TYPE type) {
01037    int bSuccess = 0;
01038 
01039        if (value) {
01040               /* we can change the type so long as nothing is currently stored. */
01041               if(value->type == xmlrpc_vector) {
01042                      if(value->v) {
01043                             if(!Q_Size(value->v->q)) {
01044                                    value->v->type = type;
01045                             }
01046                      }
01047               }
01048               else {
01049       value->v = calloc(1, sizeof(STRUCT_XMLRPC_VECTOR));
01050       if(value->v) {
01051          value->v->q = (queue*)malloc(sizeof(queue));
01052          if(value->v->q) {
01053             Q_Init(value->v->q);
01054             value->v->type = type;
01055             value->type = xmlrpc_vector;
01056             bSuccess = 1;
01057          }
01058       }
01059    }
01060        }
01061 
01062    return bSuccess;
01063 }
01064 
01065 /*******/
01066 
01067 /****f* VECTOR/XMLRPC_CreateVector
01068  * NAME
01069  *   XMLRPC_CreateVector
01070  * SYNOPSIS
01071  *   XMLRPC_VALUE XMLRPC_CreateVector(const char* id, XMLRPC_VECTOR_TYPE type)
01072  * FUNCTION
01073  *   Create a new vector and optionally set an id.
01074  * INPUTS
01075  *   id        The id of the vector, or NULL
01076  *   type      New type of vector as enumerated by XMLRPC_VECTOR_TYPE
01077  * RESULT
01078  *   XMLRPC_VALUE  The new vector, or NULL on failure.
01079  * SEE ALSO
01080  *   XMLRPC_CreateValueEmpty ()
01081  *   XMLRPC_SetIsVector ()
01082  *   XMLRPC_GetValueType ()
01083  *   XMLRPC_GetVectorType ()
01084  *   XMLRPC_VALUE
01085  *   XMLRPC_VECTOR_TYPE
01086  *   XMLRPC_VALUE_TYPE
01087  * SOURCE
01088  */
01089 XMLRPC_VALUE XMLRPC_CreateVector(const char* id, XMLRPC_VECTOR_TYPE type) {
01090    XMLRPC_VALUE val = NULL;
01091 
01092    val = XMLRPC_CreateValueEmpty();
01093    if(val) {
01094       if(XMLRPC_SetIsVector(val, type)) {
01095          if(id) {
01096             const char *pSVI = NULL;
01097 
01098             pSVI = XMLRPC_SetValueID(val, id, 0);
01099             if(NULL == pSVI) {
01100                val = NULL;
01101             }
01102          }
01103       }
01104       else {
01105          val = NULL;
01106       }
01107    }
01108    return val;
01109 }
01110 
01111 /*******/
01112 
01113 
01114 /* Not yet implemented.
01115  *
01116  * This should use a hash to determine if a given target id has already
01117  * been appended.  
01118  *
01119  * Alternately, it could walk the entire vector, but that could be quite
01120  * slow for very large lists.
01121  */
01122 static int isDuplicateEntry(XMLRPC_VALUE target, XMLRPC_VALUE source) {
01123    return 0;
01124 }
01125 
01126 /****f* VECTOR/XMLRPC_AddValueToVector
01127  * NAME
01128  *   XMLRPC_AddValueToVector
01129  * SYNOPSIS
01130  *   int XMLRPC_AddValueToVector(XMLRPC_VALUE target, XMLRPC_VALUE source)
01131  * FUNCTION
01132  *   Add (append) an existing XMLRPC_VALUE to a vector.
01133  * INPUTS
01134  *   target    The target vector
01135  *   source    The source value to append
01136  * RESULT
01137  *   int       1 if successful, else 0
01138  * SEE ALSO
01139  *   XMLRPC_AddValuesToVector ()
01140  *   XMLRPC_VectorGetValueWithID_Case ()
01141  *   XMLRPC_VALUE
01142  * NOTES
01143  *   The function will fail and return 0 if an attempt is made to add
01144  *   a value with an ID into a vector of type xmlrpc_vector_array. Such
01145  *   values can only be added to xmlrpc_vector_struct.
01146  * SOURCE
01147  */
01148 int XMLRPC_AddValueToVector(XMLRPC_VALUE target, XMLRPC_VALUE source) {
01149    if(target && source) {
01150       if(target->type == xmlrpc_vector && target->v && 
01151          target->v->q && target->v->type != xmlrpc_vector_none) {
01152 
01153          /* guard against putting value of unknown type into vector */
01154          switch(source->type) {
01155             case xmlrpc_empty:
01156             case xmlrpc_base64:
01157             case xmlrpc_boolean:
01158             case xmlrpc_datetime:
01159             case xmlrpc_double:
01160             case xmlrpc_int:
01161             case xmlrpc_string:
01162             case xmlrpc_vector:
01163                /* Guard against putting a key/val pair into an array vector */
01164                if( !(source->id.len && target->v->type == xmlrpc_vector_array) ) {
01165                                    if (isDuplicateEntry (target, source)
01166                                            || Q_PushTail (target->v->q, XMLRPC_CopyValue (source))) {
01167                      return 1;
01168                   }
01169                }
01170                else {
01171                                    /* fprintf (stderr,
01172                                                         "xmlrpc: attempted to add key/val pair to vector of type array\n"); */
01173                }
01174                break;
01175             default:
01176                             /* fprintf (stderr,
01177                                                  "xmlrpc: attempted to add value of unknown type to vector\n"); */
01178                break;
01179          }
01180       }
01181    }
01182    return 0;
01183 }
01184 
01185 /*******/
01186 
01187 
01188 /****f* VECTOR/XMLRPC_AddValuesToVector
01189  * NAME
01190  *   XMLRPC_AddValuesToVector
01191  * SYNOPSIS
01192  *   XMLRPC_AddValuesToVector ( target, val1, val2, val3, val(n), 0 )
01193  *   XMLRPC_AddValuesToVector( XMLRPC_VALUE, ... )
01194  * FUNCTION
01195  *   Add (append) a series of existing XMLRPC_VALUE to a vector.
01196  * INPUTS
01197  *   target    The target vector
01198  *   ...       The source value(s) to append.  The last item *must* be 0.
01199  * RESULT
01200  *   int       1 if successful, else 0
01201  * SEE ALSO
01202  *   XMLRPC_AddValuesToVector ()
01203  *   XMLRPC_VectorGetValueWithID_Case ()
01204  *   XMLRPC_VALUE
01205  * NOTES
01206  *   This function may actually return failure after it has already modified
01207  *     or added items to target.  You can not trust the state of target
01208  *     if this function returns failure.
01209  * SOURCE
01210  */
01211 int XMLRPC_AddValuesToVector(XMLRPC_VALUE target, ...) {
01212    int iRetval = 0;
01213 
01214    if(target) {
01215       if(target->type == xmlrpc_vector) {
01216          XMLRPC_VALUE v = NULL;
01217          va_list vl;
01218 
01219          va_start(vl, target);
01220 
01221          do {
01222             v = va_arg(vl, XMLRPC_VALUE);
01223             if(v) {
01224                if(!XMLRPC_AddValueToVector(target, v)) {
01225                   iRetval = 0;
01226                   break;
01227                }
01228             }
01229                      }
01230                      while (v);
01231 
01232          va_end(vl);
01233 
01234          if(NULL == v) {
01235             iRetval = 1;
01236          }
01237       }
01238    }
01239    return iRetval;
01240 }
01241 
01242 /*******/
01243 
01244 
01245 /****f* VECTOR/XMLRPC_VectorGetValueWithID_Case
01246  * NAME
01247  *   XMLRPC_VectorGetValueWithID_Case
01248  * SYNOPSIS
01249  *   XMLRPC_VALUE XMLRPC_VectorGetValueWithID_Case(XMLRPC_VALUE vector, const char* id, XMLRPC_CASE_COMPARISON id_case)
01250  * FUNCTION
01251  *   Get value from vector matching id (key)
01252  * INPUTS
01253  *   vector    The source vector
01254  *   id        The key to find
01255  *   id_case   Rule for how to match key
01256  * RESULT
01257  *   int       1 if successful, else 0
01258  * SEE ALSO
01259  *   XMLRPC_SetValueID_Case ()
01260  *   XMLRPC_VALUE
01261  *   XMLRPC_CASE_COMPARISON
01262  * SOURCE
01263  */
01264 XMLRPC_VALUE XMLRPC_VectorGetValueWithID_Case (XMLRPC_VALUE vector, const char *id,
01265                                                                                                            XMLRPC_CASE_COMPARISON id_case) {
01266    if(vector && vector->v && vector->v->q) {
01267        q_iter qi = Q_Iter_Head_F(vector->v->q);
01268 
01269        while(qi) {
01270           XMLRPC_VALUE xIter = Q_Iter_Get_F(qi);
01271           if(xIter && xIter->id.str) {
01272              if(id_case == xmlrpc_case_sensitive) {
01273                 if(!strcmp(xIter->id.str, id)) {
01274                    return xIter;
01275                 }
01276              }
01277              else if(id_case == xmlrpc_case_insensitive) {
01278                 if(!strcasecmp(xIter->id.str, id)) {
01279                    return xIter;
01280                 }
01281              }
01282           }
01283           qi = Q_Iter_Next_F(qi);
01284        }
01285    }
01286    return NULL;
01287 }
01288 
01289 /*******/
01290 
01291 
01292 int XMLRPC_VectorRemoveValue(XMLRPC_VALUE vector, XMLRPC_VALUE value) {
01293    if(vector && vector->v && vector->v->q && value) {
01294        q_iter qi = Q_Iter_Head_F(vector->v->q);
01295 
01296        while(qi) {
01297           XMLRPC_VALUE xIter = Q_Iter_Get_F(qi);
01298           if(xIter == value) {
01299              XMLRPC_CleanupValue(xIter);
01300              Q_Iter_Del(vector->v->q, qi);
01301              return 1;
01302           }
01303           qi = Q_Iter_Next_F(qi);
01304        }
01305    }
01306    return 0;
01307 }
01308 
01309 
01310 /****f* VALUE/XMLRPC_CreateValueString
01311  * NAME
01312  *   XMLRPC_CreateValueString
01313  * SYNOPSIS
01314  *   XMLRPC_VALUE XMLRPC_CreateValueString(const char* id, const char* val, int len)
01315  * FUNCTION
01316  *   Create an XMLRPC_VALUE, and assign a string to it
01317  * INPUTS
01318  *   id        The id of the value, or NULL
01319  *   val       The desired new string val.
01320  *   len       length of val string if known, or 0 if unknown.
01321  * RESULT
01322  *   newly allocated XMLRPC_VALUE, or NULL
01323  * SEE ALSO
01324  *   XMLRPC_GetValueString ()
01325  *   XMLRPC_CreateValueEmpty ()
01326  *   XMLRPC_VALUE
01327  *   XMLRPC_VALUE_TYPE
01328  * SOURCE
01329  */
01330 XMLRPC_VALUE XMLRPC_CreateValueString(const char* id, const char* val, int len) {
01331    XMLRPC_VALUE value = NULL;
01332    if(val) {
01333       value = XMLRPC_CreateValueEmpty();
01334       if(value) {
01335          XMLRPC_SetValueString(value, val, len);
01336          if(id) {
01337             XMLRPC_SetValueID(value, id, 0);
01338          }
01339       }
01340    }
01341    return value;
01342 }
01343 
01344 /*******/
01345 
01346 /****f* VALUE/XMLRPC_CreateValueInt
01347  * NAME
01348  *   XMLRPC_CreateValueInt
01349  * SYNOPSIS
01350  *   XMLRPC_VALUE XMLRPC_CreateValueInt(const char* id, int i)
01351  * FUNCTION
01352  *   Create an XMLRPC_VALUE, and assign an int to it
01353  * INPUTS
01354  *   id        The id of the value, or NULL
01355  *   i         The desired new int val.
01356  * RESULT
01357  *   newly allocated XMLRPC_VALUE, or NULL
01358  * SEE ALSO
01359  *   XMLRPC_GetValueInt ()
01360  *   XMLRPC_CreateValueEmpty ()
01361  *   XMLRPC_VALUE
01362  *   XMLRPC_VALUE_TYPE
01363  * SOURCE
01364  */
01365 XMLRPC_VALUE XMLRPC_CreateValueInt(const char* id, int i) {
01366    XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
01367    if(val) {
01368       XMLRPC_SetValueInt(val, i);
01369       if(id) {
01370          XMLRPC_SetValueID(val, id, 0);
01371       }
01372    }
01373    return val;
01374 }
01375 
01376 /*******/
01377 
01378 /****f* VALUE/XMLRPC_CreateValueBoolean
01379  * NAME
01380  *   XMLRPC_CreateValueBoolean
01381  * SYNOPSIS
01382  *   XMLRPC_VALUE XMLRPC_CreateValueBoolean(const char* id, int i)
01383  * FUNCTION
01384  *   Create an XMLRPC_VALUE, and assign an int to it
01385  * INPUTS
01386  *   id        The id of the value, or NULL
01387  *   i         The desired new int val.
01388  * RESULT
01389  *   newly allocated XMLRPC_VALUE, or NULL
01390  * SEE ALSO
01391  *   XMLRPC_GetValueBoolean ()
01392  *   XMLRPC_CreateValueEmpty ()
01393  *   XMLRPC_VALUE
01394  *   XMLRPC_VALUE_TYPE
01395  * SOURCE
01396  */
01397 XMLRPC_VALUE XMLRPC_CreateValueBoolean(const char* id, int i) {
01398    XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
01399    if(val) {
01400       XMLRPC_SetValueBoolean(val, i);
01401       if(id) {
01402          XMLRPC_SetValueID(val, id, 0);
01403       }
01404    }
01405    return val;
01406 }
01407 
01408 /*******/
01409 
01410 
01411 /****f* VALUE/XMLRPC_CleanupValue
01412  * NAME
01413  *   XMLRPC_CleanupValue
01414  * SYNOPSIS
01415  *   void XMLRPC_CleanupValue(XMLRPC_VALUE value)
01416  * FUNCTION
01417  *   Frees all memory allocated for an XMLRPC_VALUE and any of its children (if a vector)
01418  * INPUTS
01419  *   value     The id of the value to be cleaned up.
01420  * RESULT
01421  *   void
01422  * NOTES
01423  *   Normally this function will be called for the topmost vector, thus free-ing
01424  *   all children.  If a child of a vector is free'd first, results are undefined.
01425  *   Failure to call this function *will* cause memory leaks.
01426  *
01427  *   Also, this function is implemented using reference counting.  Thus a value
01428  *   may be added and freed from multiple parents so long as a reference is added
01429  *   first using XMLRPC_CopyValue()
01430  * SEE ALSO
01431  *   XMLRPC_RequestFree ()
01432  *   XMLRPC_CreateValueEmpty ()
01433  *   XMLRPC_CopyValue()
01434  *   XMLRPC_VALUE
01435  * SOURCE
01436  */
01437 void XMLRPC_CleanupValue(XMLRPC_VALUE value) {
01438    if(value) {
01439       if(value->iRefCount > 0) {
01440          value->iRefCount --;
01441       }
01442 
01443 #ifdef XMLRPC_DEBUG_REFCOUNT
01444       if(value->id.str) {
01445                      printf ("decremented refcount of %s, now %i\n", value->id.str,
01446                                      value->iRefCount);
01447       }
01448       else {
01449                      printf ("decremented refcount of 0x%x, now %i\n", value,
01450                                      value->iRefCount);
01451       }
01452 #endif
01453 
01454       if(value->type == xmlrpc_vector) {
01455          if(value->v) {
01456             if(value->iRefCount == 0) {
01457                XMLRPC_VALUE cur = (XMLRPC_VALUE)Q_Head(value->v->q);
01458                while( cur ) {
01459                   XMLRPC_CleanupValue(cur);
01460    
01461                   /* Make sure some idiot didn't include a vector as a child of itself
01462                    * and thus it would have already free'd these.
01463                    */
01464                   if(value->v && value->v->q) {
01465                      cur = Q_Next(value->v->q);
01466                   }
01467                   else {
01468                      break;
01469                   }
01470                }
01471 
01472                Q_Destroy(value->v->q);
01473                my_free(value->v->q);
01474                my_free(value->v);
01475             }
01476          }
01477       }
01478 
01479 
01480       if(value->iRefCount == 0) {
01481 
01482          /* guard against freeing invalid types */
01483          switch(value->type) {
01484             case xmlrpc_empty:
01485             case xmlrpc_base64:
01486             case xmlrpc_boolean:
01487             case xmlrpc_datetime:
01488             case xmlrpc_double:
01489             case xmlrpc_int:
01490             case xmlrpc_string:
01491             case xmlrpc_vector:
01492 #ifdef XMLRPC_DEBUG_REFCOUNT
01493                if(value->id.str) {
01494                   printf("free'd %s\n", value->id.str);
01495                }
01496                else {
01497                   printf("free'd 0x%x\n", value);
01498                }
01499 #endif 
01500                simplestring_free(&value->id);
01501                simplestring_free(&value->str);
01502 
01503                memset(value, 0, sizeof(STRUCT_XMLRPC_VALUE));
01504                my_free(value);
01505                break;
01506             default:
01507                             /* fprintf (stderr,
01508                                                  "xmlrpc: attempted to free value of invalid type\n"); */
01509                break;
01510          }
01511       }
01512    }
01513 }
01514 
01515 /*******/
01516 
01517 
01518 /****f* VALUE/XMLRPC_SetValueDateTime
01519  * NAME
01520  *   XMLRPC_SetValueDateTime
01521  * SYNOPSIS
01522  *   void XMLRPC_SetValueDateTime(XMLRPC_VALUE value, time_t time)
01523  * FUNCTION
01524  *   Assign time value to XMLRPC_VALUE
01525  * INPUTS
01526  *   value     The target XMLRPC_VALUE
01527  *   time      The desired new unix time value (time_t)
01528  * RESULT
01529  *   void
01530  * SEE ALSO
01531  *   XMLRPC_GetValueDateTime ()
01532  *   XMLRPC_SetValueDateTime_ISO8601 ()
01533  *   XMLRPC_CreateValueDateTime ()
01534  *   XMLRPC_VALUE
01535  * SOURCE
01536  */
01537 void XMLRPC_SetValueDateTime(XMLRPC_VALUE value, time_t time) {
01538    if(value) {
01539       char timeBuf[30];
01540       value->type = xmlrpc_datetime;
01541       value->i = time;
01542 
01543       timeBuf[0] = 0;
01544 
01545       date_to_ISO8601(time, timeBuf, sizeof(timeBuf));
01546 
01547       if(timeBuf[0]) {
01548          XMLRPC_SetValueDateTime_ISO8601 (value, timeBuf);
01549       }
01550    }
01551 }
01552 
01553 /*******/
01554 
01555 /****f* VALUE/XMLRPC_CopyValue
01556  * NAME
01557  *   XMLRPC_CopyValue
01558  * SYNOPSIS
01559  *   XMLRPC_VALUE XMLRPC_CopyValue(XMLRPC_VALUE value)
01560  * FUNCTION
01561  *   Make a copy (reference) of an XMLRPC_VALUE
01562  * INPUTS
01563  *   value     The target XMLRPC_VALUE
01564  * RESULT
01565  *   XMLRPC_VALUE -- address of the copy
01566  * SEE ALSO
01567  *   XMLRPC_CleanupValue ()
01568  *   XMLRPC_DupValueNew ()
01569  * NOTES
01570  *   This function is implemented via reference counting, so the
01571  *   returned value is going to be the same as the passed in value.
01572  *   The value must be freed the same number of times it is copied
01573  *   or there will be a memory leak.
01574  * SOURCE
01575  */
01576 XMLRPC_VALUE XMLRPC_CopyValue(XMLRPC_VALUE value) {
01577    if(value) {
01578       value->iRefCount ++;
01579 #ifdef XMLRPC_DEBUG_REFCOUNT
01580       if(value->id.str) {
01581                      printf ("incremented refcount of %s, now %i\n", value->id.str,
01582                                      value->iRefCount);
01583               }
01584               else {
01585                      printf ("incremented refcount of 0x%x, now %i\n", value,
01586                                      value->iRefCount);
01587       }
01588 #endif
01589    }
01590    return value;
01591 }
01592 
01593 /*******/
01594 
01595 
01596 /****f* VALUE/XMLRPC_DupValueNew
01597  * NAME
01598  *   XMLRPC_DupValueNew
01599  * SYNOPSIS
01600  *   XMLRPC_VALUE XMLRPC_DupValueNew(XMLRPC_VALUE value)
01601  * FUNCTION
01602  *   Make a duplicate (non reference) of an XMLRPC_VALUE with newly allocated mem.
01603  * INPUTS
01604  *   value     The source XMLRPC_VALUE to duplicate
01605  * RESULT
01606  *   XMLRPC_VALUE -- address of the duplicate value
01607  * SEE ALSO
01608  *   XMLRPC_CleanupValue ()
01609  *   XMLRPC_CopyValue ()
01610  * NOTES
01611  *   Use this when function when you need to modify the contents of
01612  *   the copied value seperately from the original.
01613  *   
01614  *   this function is recursive, thus the value and all of its children
01615  *   (if any) will be duplicated.
01616  * SOURCE
01617  */
01618 XMLRPC_VALUE XMLRPC_DupValueNew (XMLRPC_VALUE xSource) {
01619        XMLRPC_VALUE xReturn = NULL;
01620        if (xSource) {
01621               xReturn = XMLRPC_CreateValueEmpty ();
01622               if (xSource->id.len) {
01623                      XMLRPC_SetValueID (xReturn, xSource->id.str, xSource->id.len);
01624               }
01625 
01626               switch (xSource->type) {
01627               case xmlrpc_int:
01628               case xmlrpc_boolean:
01629                      XMLRPC_SetValueInt (xReturn, xSource->i);
01630                      break;
01631               case xmlrpc_string:
01632               case xmlrpc_base64:
01633                      XMLRPC_SetValueString (xReturn, xSource->str.str, xSource->str.len);
01634                      break;
01635               case xmlrpc_datetime:
01636                      XMLRPC_SetValueDateTime (xReturn, xSource->i);
01637                      break;
01638               case xmlrpc_double:
01639                      XMLRPC_SetValueDouble (xReturn, xSource->d);
01640                      break;
01641               case xmlrpc_vector:
01642                      {
01643                             q_iter qi = Q_Iter_Head_F (xSource->v->q);
01644                             XMLRPC_SetIsVector (xReturn, xSource->v->type);
01645 
01646                             while (qi) {
01647                                    XMLRPC_VALUE xIter = Q_Iter_Get_F (qi);
01648                                    XMLRPC_AddValueToVector (xReturn, XMLRPC_DupValueNew (xIter));
01649                                    qi = Q_Iter_Next_F (qi);
01650                             }
01651                      }
01652                      break;
01653               default:
01654                      break;
01655               }
01656        }
01657        return xReturn;
01658 }
01659 
01660 /*******/
01661 
01662 
01663 
01664 /****f* VALUE/XMLRPC_CreateValueDateTime
01665  * NAME
01666  *   XMLRPC_CreateValueDateTime
01667  * SYNOPSIS
01668  *   XMLRPC_VALUE XMLRPC_CreateValueDateTime(const char* id, time_t time)
01669  * FUNCTION
01670  *   Create new datetime value from time_t
01671  * INPUTS
01672  *   id        id of the new value, or NULL
01673  *   time      The desired unix time value (time_t)
01674  * RESULT
01675  *   void
01676  * SEE ALSO
01677  *   XMLRPC_GetValueDateTime ()
01678  *   XMLRPC_SetValueDateTime ()
01679  *   XMLRPC_CreateValueDateTime_ISO8601 ()
01680  *   XMLRPC_VALUE
01681  * SOURCE
01682  */
01683 XMLRPC_VALUE XMLRPC_CreateValueDateTime(const char* id, time_t time) {
01684    XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
01685    if(val) {
01686       XMLRPC_SetValueDateTime(val, time);
01687       if(id) {
01688          XMLRPC_SetValueID(val, id, 0);
01689       }
01690    }
01691    return val;
01692 }
01693 
01694 /*******/
01695 
01696 
01697 /****f* VALUE/XMLRPC_SetValueDateTime_ISO8601
01698  * NAME
01699  *   XMLRPC_SetValueDateTime_ISO8601
01700  * SYNOPSIS
01701  *   void XMLRPC_SetValueDateTime_ISO8601(XMLRPC_VALUE value, const char* s)
01702  * FUNCTION
01703  *   Set datetime value from IS08601 encoded string
01704  * INPUTS
01705  *   value     The target XMLRPC_VALUE
01706  *   s         The desired new time value
01707  * RESULT
01708  *   void                                
01709  * BUGS
01710  *   This function currently attempts to convert the time string to a valid unix time
01711  *   value before passing it. Behavior when the string is invalid or out of range
01712  *   is not well defined, but will probably result in Jan 1, 1970 (0) being passed.
01713  * SEE ALSO
01714  *   XMLRPC_GetValueDateTime_ISO8601 ()
01715  *   XMLRPC_CreateValueDateTime_ISO8601 ()
01716  *   XMLRPC_CreateValueDateTime ()
01717  *   XMLRPC_VALUE
01718  * SOURCE
01719  */
01720 void XMLRPC_SetValueDateTime_ISO8601(XMLRPC_VALUE value, const char* s) {
01721    if(value) {
01722       time_t time_val = 0;
01723       if(s) {
01724          value->type = xmlrpc_datetime;
01725          date_from_ISO8601(s, &time_val);
01726          value->i = time_val;
01727          simplestring_clear(&value->str);
01728          simplestring_add(&value->str, s);
01729       }
01730    }
01731 }
01732 
01733 /*******/
01734 
01735 /****f* VALUE/XMLRPC_CreateValueDateTime_ISO8601
01736  * NAME
01737  *   XMLRPC_CreateValueDateTime_ISO8601
01738  * SYNOPSIS
01739  *   XMLRPC_VALUE XMLRPC_CreateValueDateTime_ISO8601(const char* id, const char *s)
01740  * FUNCTION
01741  *   Create datetime value from IS08601 encoded string
01742  * INPUTS
01743  *   id        The id of the new value, or NULL
01744  *   s         The desired new time value
01745  * RESULT
01746  *   newly allocated XMLRPC_VALUE, or NULL if no value created.                                
01747  * BUGS
01748  *   See XMLRPC_SetValueDateTime_ISO8601 ()
01749  * SEE ALSO
01750  *   XMLRPC_GetValueDateTime_ISO8601 ()
01751  *   XMLRPC_SetValueDateTime_ISO8601 ()
01752  *   XMLRPC_CreateValueDateTime ()
01753  *   XMLRPC_VALUE
01754  * SOURCE
01755  */
01756 XMLRPC_VALUE XMLRPC_CreateValueDateTime_ISO8601(const char* id, const char *s) {
01757    XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
01758    if(val) {
01759       XMLRPC_SetValueDateTime_ISO8601(val, s);
01760       if(id) {
01761          XMLRPC_SetValueID(val, id, 0);
01762       }
01763    }
01764    return val;
01765 }
01766 
01767 /*******/
01768 
01769 
01770 /****f* VALUE/XMLRPC_SetValueBase64
01771  * NAME
01772  *   XMLRPC_SetValueBase64
01773  * SYNOPSIS
01774  *   void XMLRPC_SetValueBase64(XMLRPC_VALUE value, const char* s, int len)
01775  * FUNCTION
01776  *   Set base64 value.  Base64 is useful for transferring binary data, such as an image.
01777  * INPUTS
01778  *   value     The target XMLRPC_VALUE
01779  *   s         The desired new binary value
01780  *   len       The length of s, or NULL. If buffer is not null terminated, len *must* be passed.
01781  * RESULT
01782  *   void                                
01783  * NOTES
01784  *   Data is set/stored/retrieved as passed in, but is base64 encoded for XML transfer, and
01785  *   decoded on the other side.  This is transparent to the caller.
01786  * SEE ALSO
01787  *   XMLRPC_GetValueBase64 ()
01788  *   XMLRPC_CreateValueBase64 ()
01789  *   XMLRPC_VALUE
01790  * SOURCE
01791  */
01792 void XMLRPC_SetValueBase64(XMLRPC_VALUE value, const char* s, int len) {
01793    if(value && s) {
01794       simplestring_clear(&value->str);
01795       (len > 0) ? simplestring_addn(&value->str, s, len) :
01796                   simplestring_add(&value->str, s);
01797       value->type = xmlrpc_base64;
01798    }
01799 }
01800 
01801 /*******/
01802 
01803 
01804 /****f* VALUE/XMLRPC_CreateValueBase64
01805  * NAME
01806  *   XMLRPC_CreateValueBase64
01807  * SYNOPSIS
01808  *   XMLRPC_VALUE XMLRPC_CreateValueBase64(const char* id, const char* s, int len)
01809  * FUNCTION
01810  *   Create base64 value.  Base64 is useful for transferring binary data, such as an image.
01811  * INPUTS
01812  *   id        id of the new value, or NULL
01813  *   s         The desired new binary value
01814  *   len       The length of s, or NULL. If buffer is not null terminated, len *must* be passed.
01815  * RESULT
01816  *   newly allocated XMLRPC_VALUE, or NULL if error
01817  * NOTES
01818  *   See XMLRPC_SetValueBase64 ()
01819  * SEE ALSO
01820  *   XMLRPC_GetValueBase64 ()
01821  *   XMLRPC_SetValueBase64 ()
01822  *   XMLRPC_VALUE
01823  * SOURCE
01824  */
01825 XMLRPC_VALUE XMLRPC_CreateValueBase64(const char* id, const char* s, int len) {
01826    XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
01827    if(val) {
01828       XMLRPC_SetValueBase64(val, s, len);
01829       if(id) {
01830          XMLRPC_SetValueID(val, id, 0);
01831       }
01832    }
01833    return val;
01834 }
01835 
01836 /*******/
01837 
01838 /****f* VALUE/XMLRPC_SetValueDouble
01839  * NAME
01840  *   XMLRPC_SetValueDouble
01841  * SYNOPSIS
01842  *   void XMLRPC_SetValueDouble(XMLRPC_VALUE value, double val)
01843  * FUNCTION
01844  *   Set double (floating point) value.
01845  * INPUTS
01846  *   value     The target XMLRPC_VALUE
01847  *   val       The desired new double value
01848  * RESULT
01849  *   void                                
01850  * SEE ALSO
01851  *   XMLRPC_GetValueDouble ()
01852  *   XMLRPC_CreateValueDouble ()
01853  *   XMLRPC_VALUE
01854  * SOURCE
01855  */
01856 void XMLRPC_SetValueDouble(XMLRPC_VALUE value, double val) {
01857    if(value) {
01858       value->type = xmlrpc_double;
01859       value->d = val;
01860    }
01861 }
01862 
01863 /*******/
01864 
01865 /****f* VALUE/XMLRPC_CreateValueDouble
01866  * NAME
01867  *   XMLRPC_CreateValueDouble
01868  * SYNOPSIS
01869  *   XMLRPC_VALUE XMLRPC_CreateValueDouble(const char* id, double d)
01870  * FUNCTION
01871  *   Create double (floating point) value.
01872  * INPUTS
01873  *   id        id of the newly created value, or NULL
01874  *   d         The desired new double value
01875  * RESULT
01876  *   void                                
01877  * SEE ALSO
01878  *   XMLRPC_GetValueDouble ()
01879  *   XMLRPC_CreateValueDouble ()
01880  *   XMLRPC_VALUE
01881  * SOURCE
01882  */
01883 XMLRPC_VALUE XMLRPC_CreateValueDouble(const char* id, double d) {
01884    XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
01885    if(val) {
01886       XMLRPC_SetValueDouble(val, d);
01887       if(id) {
01888          XMLRPC_SetValueID(val, id, 0);
01889       }
01890    }
01891    return val;
01892 }
01893 
01894 /*******/
01895 
01896 /****f* VALUE/XMLRPC_GetValueString
01897  * NAME
01898  *   XMLRPC_GetValueString
01899  * SYNOPSIS
01900  *   const char* XMLRPC_GetValueString(XMLRPC_VALUE value)
01901  * FUNCTION
01902  *   retrieve string value
01903  * INPUTS
01904  *   value     source XMLRPC_VALUE of type xmlrpc_string
01905  * RESULT
01906  *   void                                
01907  * SEE ALSO
01908  *   XMLRPC_SetValueString ()
01909  *   XMLRPC_GetValueType ()
01910  *   XMLRPC_VALUE
01911  * SOURCE
01912  */
01913 const char* XMLRPC_GetValueString(XMLRPC_VALUE value) {
01914     return ((value && value->type == xmlrpc_string) ? value->str.str : 0);
01915 }
01916 
01917 /*******/
01918 
01919 /****f* VALUE/XMLRPC_GetValueStringLen
01920  * NAME
01921  *   XMLRPC_GetValueStringLen
01922  * SYNOPSIS
01923  *   int XMLRPC_GetValueStringLen(XMLRPC_VALUE value)
01924  * FUNCTION
01925  *   determine length of string value
01926  * INPUTS
01927  *   value     XMLRPC_VALUE of type xmlrpc_string 
01928  * RESULT
01929  *   length of string, or 0
01930  * NOTES
01931  * SEE ALSO
01932  *   XMLRPC_SetValueString ()
01933  *   XMLRPC_GetValueString ()
01934  * SOURCE
01935  */
01936 int XMLRPC_GetValueStringLen(XMLRPC_VALUE value) {
01937     return ((value) ? value->str.len : 0);
01938 }
01939 
01940 /*******/
01941 
01942 /****f* VALUE/XMLRPC_GetValueInt
01943  * NAME
01944  *   XMLRPC_GetValueInt
01945  * SYNOPSIS
01946  *   int XMLRPC_GetValueInt(XMLRPC_VALUE value)
01947  * FUNCTION
01948  *   retrieve integer value.
01949  * INPUTS
01950  *   value     XMLRPC_VALUE of type xmlrpc_int 
01951  * RESULT
01952  *   integer value or 0 if value is not valid int
01953  * NOTES
01954  *   use XMLRPC_GetValueType () to be sure if 0 is real return value or not
01955  * SEE ALSO
01956  *   XMLRPC_SetValueInt ()
01957  *   XMLRPC_CreateValueInt ()
01958  * SOURCE
01959  */
01960 int XMLRPC_GetValueInt(XMLRPC_VALUE value) {
01961     return ((value && value->type == xmlrpc_int) ? value->i : 0);
01962 }
01963 
01964 /*******/
01965 
01966 /****f* VALUE/XMLRPC_GetValueBoolean
01967  * NAME
01968  *   XMLRPC_GetValueBoolean
01969  * SYNOPSIS
01970  *   int XMLRPC_GetValueBoolean(XMLRPC_VALUE value)
01971  * FUNCTION
01972  *   retrieve boolean value.
01973  * INPUTS
01974  *   XMLRPC_VALUE of type xmlrpc_boolean
01975  * RESULT
01976  *   boolean value or 0 if value is not valid boolean
01977  * NOTES
01978  *   use XMLRPC_GetValueType() to be sure if 0 is real value or not
01979  * SEE ALSO
01980  *   XMLRPC_SetValueBoolean ()
01981  *   XMLRPC_CreateValueBoolean ()
01982  * SOURCE
01983  */
01984 int XMLRPC_GetValueBoolean(XMLRPC_VALUE value) {
01985     return ((value && value->type == xmlrpc_boolean) ? value->i : 0);
01986 }
01987 
01988 /*******/
01989 
01990 /****f* VALUE/XMLRPC_GetValueDouble
01991  * NAME
01992  *   XMLRPC_GetValueDouble
01993  * SYNOPSIS
01994  *   double XMLRPC_GetValueDouble(XMLRPC_VALUE value)
01995  * FUNCTION
01996  *   retrieve double value
01997  * INPUTS
01998  *   XMLRPC_VALUE of type xmlrpc_double
01999  * RESULT
02000  *   double value or 0 if value is not valid double.
02001  * NOTES
02002  *   use XMLRPC_GetValueType() to be sure if 0 is real value or not
02003  * SEE ALSO
02004  *   XMLRPC_SetValueDouble ()
02005  *   XMLRPC_CreateValueDouble ()
02006  * SOURCE
02007  */
02008 double XMLRPC_GetValueDouble(XMLRPC_VALUE value) {
02009     return ((value && value->type == xmlrpc_double) ? value->d : 0);
02010 }
02011 
02012 /*******/
02013 
02014 /****f* VALUE/XMLRPC_GetValueBase64
02015  * NAME
02016  *   XMLRPC_GetValueBase64
02017  * SYNOPSIS
02018  *   const char* XMLRPC_GetValueBase64(XMLRPC_VALUE value)
02019  * FUNCTION
02020  *   retrieve binary value
02021  * INPUTS
02022  *   XMLRPC_VALUE of type xmlrpc_base64
02023  * RESULT
02024  *   pointer to binary value or 0 if value is not valid.
02025  * SEE ALSO
02026  *   XMLRPC_SetValueBase64 ()
02027  *   XMLRPC_CreateValueBase64 ()
02028  * NOTES
02029  *   Call XMLRPC_GetValueStringLen() to retrieve real length of binary data.  strlen()
02030  *   will not be accurate, as returned data may contain embedded nulls.
02031  * SOURCE
02032  */
02033 const char* XMLRPC_GetValueBase64(XMLRPC_VALUE value) {
02034     return ((value && value->type == xmlrpc_base64) ? value->str.str : 0);
02035 }
02036 
02037 /*******/
02038 
02039 /****f* VALUE/XMLRPC_GetValueDateTime
02040  * NAME
02041  *   XMLRPC_GetValueDateTime
02042  * SYNOPSIS
02043  *   time_t XMLRPC_GetValueDateTime(XMLRPC_VALUE value)
02044  * FUNCTION
02045  *   retrieve time_t value
02046  * INPUTS
02047  *   XMLRPC_VALUE of type xmlrpc_datetime
02048  * RESULT
02049  *   time_t value or 0 if value is not valid datetime.
02050  * NOTES
02051  *   use XMLRPC_GetValueType() to be sure if 0 is real value or not
02052  * SEE ALSO
02053  *   XMLRPC_SetValueDateTime ()
02054  *   XMLRPC_GetValueDateTime_ISO8601 ()
02055  *   XMLRPC_CreateValueDateTime ()
02056  * SOURCE
02057  */
02058 time_t XMLRPC_GetValueDateTime(XMLRPC_VALUE value) {
02059     return (time_t)((value && value->type == xmlrpc_datetime) ? value->i : 0);
02060 }
02061 
02062 /*******/
02063 
02064 /****f* VALUE/XMLRPC_GetValueDateTime_IOS8601
02065  * NAME
02066  *   XMLRPC_GetValueDateTime_IOS8601
02067  * SYNOPSIS
02068  *   const char* XMLRPC_GetValueDateTime_IOS8601(XMLRPC_VALUE value)
02069  * FUNCTION
02070  *   retrieve ISO8601 formatted time value
02071  * INPUTS
02072  *   XMLRPC_VALUE of type xmlrpc_datetime
02073  * RESULT
02074  *   const char* value or 0 if value is not valid datetime.
02075  * SEE ALSO
02076  *   XMLRPC_SetValueDateTime_IOS8601 ()
02077  *   XMLRPC_GetValueDateTime ()
02078  *   XMLRPC_CreateValueDateTime_IOS8601 ()
02079  * SOURCE
02080  */
02081 const char* XMLRPC_GetValueDateTime_ISO8601(XMLRPC_VALUE value) {
02082     return ((value && value->type == xmlrpc_datetime) ? value->str.str : 0);
02083 }
02084 
02085 /*******/
02086 
02087 /* Get ID (key) of value or NULL */
02088 /****f* VALUE/XMLRPC_GetValueID
02089  * NAME
02090  *   XMLRPC_GetValueID
02091  * SYNOPSIS
02092  *   const char* XMLRPC_GetValueID(XMLRPC_VALUE value)
02093  * FUNCTION
02094  *   retrieve id (key) of value
02095  * INPUTS
02096  *   XMLRPC_VALUE of any type
02097  * RESULT
02098  *   const char* pointer to id of value, or NULL
02099  * NOTES
02100  * SEE ALSO
02101  *   XMLRPC_SetValueID()
02102  *   XMLRPC_CreateValueEmpty()
02103  * SOURCE
02104  */
02105 const char* XMLRPC_GetValueID(XMLRPC_VALUE value) {
02106     return (const char*)((value && value->id.len) ? value->id.str : 0);
02107 }
02108 
02109 /*******/
02110 
02111 
02112 /****f* VECTOR/XMLRPC_VectorSize
02113  * NAME
02114  *   XMLRPC_VectorSize
02115  * SYNOPSIS
02116  *   int XMLRPC_VectorSize(XMLRPC_VALUE value)
02117  * FUNCTION
02118  *   retrieve size of vector
02119  * INPUTS
02120  *   XMLRPC_VALUE of type xmlrpc_vector
02121  * RESULT
02122  *   count of items in vector
02123  * NOTES
02124  *   This is a cheap operation even on large vectors.  Vector size is 
02125  *   maintained by queue during add/remove ops.
02126  * SEE ALSO
02127  *   XMLRPC_AddValueToVector ()
02128  * SOURCE
02129  */
02130 int XMLRPC_VectorSize(XMLRPC_VALUE value) {
02131    int size = 0;
02132    if(value && value->type == xmlrpc_vector && value->v) {
02133       size = Q_Size(value->v->q);
02134    }
02135    return size;
02136 }
02137 
02138 /*******/
02139 
02140 /****f* VECTOR/XMLRPC_VectorRewind
02141  * NAME
02142  *   XMLRPC_VectorRewind
02143  * SYNOPSIS
02144  *   XMLRPC_VALUE XMLRPC_VectorRewind(XMLRPC_VALUE value)
02145  * FUNCTION
02146  *   reset vector to first item
02147  * INPUTS
02148  *   XMLRPC_VALUE of type xmlrpc_vector
02149  * RESULT
02150  *   first XMLRPC_VALUE in list, or NULL if empty or error.
02151  * NOTES
02152  *   Be careful to rewind any vector passed in to you if you expect to
02153  *   iterate through the entire list.
02154  * SEE ALSO
02155  *   XMLRPC_VectorNext ()
02156  * SOURCE
02157  */
02158 XMLRPC_VALUE XMLRPC_VectorRewind(XMLRPC_VALUE value) {
02159    XMLRPC_VALUE xReturn = NULL;
02160    if(value && value->type == xmlrpc_vector && value->v) {
02161       xReturn = (XMLRPC_VALUE)Q_Head(value->v->q);
02162    }
02163    return xReturn;
02164 }
02165 
02166 /*******/
02167 
02168 /****f* VECTOR/XMLRPC_VectorNext
02169  * NAME
02170  *   XMLRPC_VectorNext
02171  * SYNOPSIS
02172  *   XMLRPC_VALUE XMLRPC_VectorNext(XMLRPC_VALUE value)
02173  * FUNCTION
02174  *   Iterate vector to next item in list.
02175  * INPUTS
02176  *   XMLRPC_VALUE of type xmlrpc_vector
02177  * RESULT
02178  *   Next XMLRPC_VALUE in vector, or NULL if at end.
02179  * NOTES
02180  * SEE ALSO
02181  *   XMLRPC_VectorRewind ()
02182  * SOURCE
02183  */
02184 XMLRPC_VALUE XMLRPC_VectorNext(XMLRPC_VALUE value) {
02185    XMLRPC_VALUE xReturn = NULL;
02186    if(value && value->type == xmlrpc_vector && value->v) {
02187       xReturn = (XMLRPC_VALUE)Q_Next(value->v->q);
02188    }
02189    return xReturn;
02190 }
02191 
02192 /*******/
02193 
02194 /****f* VALUE/XMLRPC_GetValueType
02195  * NAME
02196  *   XMLRPC_GetValueType
02197  * SYNOPSIS
02198  *   XMLRPC_VALUE_TYPE XMLRPC_GetValueType(XMLRPC_VALUE value)
02199  * FUNCTION
02200  *   determine data type of the XMLRPC_VALUE
02201  * INPUTS
02202  *   XMLRPC_VALUE target of query
02203  * RESULT
02204  *   data type of value as enumerated by XMLRPC_VALUE_TYPE
02205  * NOTES
02206  *   all values are of type xmlrpc_empty until set.
02207  *   Deprecated for public use.  See XMLRPC_GetValueTypeEasy
02208  * SEE ALSO
02209  *   XMLRPC_SetValue*
02210  *   XMLRPC_CreateValue*
02211  *   XMLRPC_Append*
02212  *   XMLRPC_GetValueTypeEasy ()
02213  * SOURCE
02214  */
02215 XMLRPC_VALUE_TYPE XMLRPC_GetValueType(XMLRPC_VALUE value) {
02216    return value ? value->type : xmlrpc_empty;
02217 }
02218 
02219 /*******/
02220 
02221 /* Vector type accessor */
02222 /****f* VALUE/XMLRPC_GetVectorType
02223  * NAME
02224  *   XMLRPC_GetVectorType
02225  * SYNOPSIS
02226  *   XMLRPC_VECTOR_TYPE XMLRPC_GetVectorType(XMLRPC_VALUE value)
02227  * FUNCTION
02228  *   determine vector type of the XMLRPC_VALUE
02229  * INPUTS
02230  *   XMLRPC_VALUE of type xmlrpc_vector
02231  * RESULT
02232  *   vector type of value as enumerated by XMLRPC_VECTOR_TYPE.
02233  *   xmlrpc_none if not a value.
02234  * NOTES
02235  *   xmlrpc_none is returned if value is not a vector
02236  *   Deprecated for public use.  See XMLRPC_GetValueTypeEasy
02237  * SEE ALSO
02238  *   XMLRPC_SetIsVector ()
02239  *   XMLRPC_GetValueType ()
02240  *   XMLRPC_GetValueTypeEasy ()
02241  * SOURCE
02242  */
02243 XMLRPC_VECTOR_TYPE XMLRPC_GetVectorType(XMLRPC_VALUE value) {
02244    return(value && value->v) ? value->v->type : xmlrpc_none;
02245 }
02246 
02247 /*******/
02248 
02249 /****f* VALUE/XMLRPC_GetValueTypeEasy
02250  * NAME
02251  *   XMLRPC_GetValueTypeEasy
02252  * SYNOPSIS
02253  *   XMLRPC_VALUE_TYPE_EASY XMLRPC_GetValueTypeEasy(XMLRPC_VALUE value)
02254  * FUNCTION
02255  *   determine data type of the XMLRPC_VALUE. includes vector types.
02256  * INPUTS
02257  *   XMLRPC_VALUE target of query
02258  * RESULT
02259  *   data type of value as enumerated by XMLRPC_VALUE_TYPE_EASY
02260  *   xmlrpc_type_none if not a value.
02261  * NOTES
02262  *   all values are of type xmlrpc_type_empty until set. 
02263  * SEE ALSO
02264  *   XMLRPC_SetValue*
02265  *   XMLRPC_CreateValue*
02266  *   XMLRPC_Append*
02267  * SOURCE
02268  */
02269 XMLRPC_VALUE_TYPE_EASY XMLRPC_GetValueTypeEasy (XMLRPC_VALUE value) {
02270        if (value) {
02271               switch (value->type) {
02272               case xmlrpc_vector:
02273                      switch (value->v->type) {
02274                      case xmlrpc_vector_none:
02275                             return xmlrpc_type_none;
02276                      case xmlrpc_vector_struct:
02277                             return xmlrpc_type_struct;
02278                      case xmlrpc_vector_mixed:
02279                             return xmlrpc_type_mixed;
02280                      case xmlrpc_vector_array:
02281                             return xmlrpc_type_array;
02282                      }
02283               default:
02284                      /* evil cast, but we know they are the same */
02285                      return(XMLRPC_VALUE_TYPE_EASY) value->type;
02286               }
02287        }
02288        return xmlrpc_none;
02289 }
02290 
02291 /*******/
02292 
02293 
02294 
02295 /*-*******************
02296 * Begin Server Funcs *
02297 *********************/
02298 
02299 
02300 /****f* VALUE/XMLRPC_ServerCreate
02301  * NAME
02302  *   XMLRPC_ServerCreate
02303  * SYNOPSIS
02304  *   XMLRPC_SERVER XMLRPC_ServerCreate()
02305  * FUNCTION
02306  *   Allocate/Init XMLRPC Server Resources.
02307  * INPUTS
02308  *   none
02309  * RESULT
02310  *   newly allocated XMLRPC_SERVER
02311  * NOTES
02312  * SEE ALSO
02313  *   XMLRPC_ServerDestroy ()
02314  *   XMLRPC_GetGlobalServer ()
02315  * SOURCE
02316  */
02317 XMLRPC_SERVER XMLRPC_ServerCreate() {
02318    XMLRPC_SERVER server = calloc(1, sizeof(STRUCT_XMLRPC_SERVER));
02319    if(server) {
02320       Q_Init(&server->methodlist);
02321       Q_Init(&server->docslist);
02322 
02323       /* register system methods */
02324       xsm_register(server);
02325    }
02326    return server;
02327 }
02328 
02329 /*******/
02330 
02331 /* Return global server.  Not locking! Not Thread Safe! */
02332 /****f* VALUE/XMLRPC_GetGlobalServer
02333  * NAME
02334  *   XMLRPC_GetGlobalServer
02335  * SYNOPSIS
02336  *   XMLRPC_SERVER XMLRPC_GetGlobalServer()
02337  * FUNCTION
02338  *   Allocates a global (process-wide) server, or returns pointer if pre-existing.
02339  * INPUTS
02340  *   none
02341  * RESULT
02342  *   pointer to global server, or 0 if error.
02343  * NOTES
02344  *   ***WARNING*** This function is not thread safe.  It is included only for the very lazy.
02345  *   Multi-threaded programs that use this may experience problems.
02346  * BUGS
02347  *   There is currently no way to cleanup the global server gracefully.
02348  * SEE ALSO
02349  *   XMLRPC_ServerCreate ()
02350  * SOURCE
02351  */
02352 XMLRPC_SERVER XMLRPC_GetGlobalServer() {
02353    static XMLRPC_SERVER xsServer = 0;
02354    if(!xsServer) {
02355       xsServer = XMLRPC_ServerCreate();
02356    }
02357    return xsServer;
02358 }
02359 
02360 /*******/
02361 
02362 /****f* VALUE/XMLRPC_ServerDestroy
02363  * NAME
02364  *   XMLRPC_ServerDestroy
02365  * SYNOPSIS
02366  *   void XMLRPC_ServerDestroy(XMLRPC_SERVER server)
02367  * FUNCTION
02368  *   Free Server Resources
02369  * INPUTS
02370  *   server     The server to be free'd
02371  * RESULT
02372  *   void
02373  * NOTES
02374  *   This frees the server struct and any methods that have been added.
02375  * SEE ALSO
02376  *   XMLRPC_ServerCreate ()
02377  * SOURCE
02378  */
02379 void XMLRPC_ServerDestroy(XMLRPC_SERVER server) {
02380    if(server) {
02381       doc_method* dm = Q_Head(&server->docslist);
02382       server_method* sm = Q_Head(&server->methodlist);
02383       while( dm ) {
02384          my_free(dm);
02385          dm = Q_Next(&server->docslist);
02386       }
02387       while( sm ) {
02388          if(sm->name) {
02389             my_free(sm->name);
02390          }
02391          if(sm->desc) {
02392             XMLRPC_CleanupValue(sm->desc);
02393          }
02394          my_free(sm);
02395          sm = Q_Next(&server->methodlist);
02396       }
02397       if(server->xIntrospection) {
02398          XMLRPC_CleanupValue(server->xIntrospection);
02399       }
02400 
02401       Q_Destroy(&server->methodlist);
02402       Q_Destroy(&server->docslist);
02403       my_free(server);
02404    }
02405 }
02406 
02407 /*******/
02408 
02409 
02410 /****f* VALUE/XMLRPC_ServerRegisterMethod
02411  * NAME
02412  *   XMLRPC_ServerRegisterMethod
02413  * SYNOPSIS
02414  *   void XMLRPC_ServerRegisterMethod(XMLRPC_SERVER server, const char *name, XMLRPC_Callback cb)
02415  * FUNCTION
02416  *   Register new XMLRPC method with server
02417  * INPUTS
02418  *   server     The XMLRPC_SERVER to register the method with
02419  *   name       public name of the method
02420  *   cb         C function that implements the method
02421  * RESULT
02422  *   int  - 1 if success, else 0
02423  * NOTES
02424  *   A C function must be registered for every "method" that the server recognizes.  The
02425  *   method name is equivalent to <methodCall><name> method name </name></methodCall> in the
02426  *   XML syntax.
02427  * SEE ALSO
02428  *   XMLRPC_ServerFindMethod ()
02429  *   XMLRPC_ServerCallMethod ()
02430  * SOURCE
02431  */
02432 int XMLRPC_ServerRegisterMethod(XMLRPC_SERVER server, const char *name, XMLRPC_Callback cb) {
02433    if(server && name && cb) {
02434 
02435       server_method* sm = malloc(sizeof(server_method));
02436       
02437       if(sm) {
02438          sm->name = strdup(name);
02439          sm->method = cb;
02440          sm->desc = NULL;
02441 
02442          return Q_PushTail(&server->methodlist, sm);
02443       }
02444    }
02445    return 0;
02446 }
02447 
02448 /*******/
02449 
02450 server_method* find_method(XMLRPC_SERVER server, const char* name) {
02451    server_method* sm;
02452 
02453    q_iter qi = Q_Iter_Head_F(&server->methodlist);
02454 
02455    while( qi ) {
02456       sm = Q_Iter_Get_F(qi);
02457       if(sm && !strcmp(sm->name, name)) {
02458          return sm;
02459       }
02460       qi = Q_Iter_Next_F(qi);
02461    }
02462    return NULL;
02463 }
02464 
02465 
02466 const char* type_to_str(XMLRPC_VALUE_TYPE type, XMLRPC_VECTOR_TYPE vtype) {
02467     switch(type) {
02468        case xmlrpc_none:
02469           return "none";
02470        case xmlrpc_empty:
02471           return "empty";
02472        case xmlrpc_base64:
02473           return "base64";
02474        case xmlrpc_boolean:
02475           return "boolean";
02476        case xmlrpc_datetime:
02477           return "datetime";
02478        case xmlrpc_double:
02479           return "double";
02480        case xmlrpc_int:
02481           return "int";
02482        case xmlrpc_string:
02483           return "string";
02484        case xmlrpc_vector:
02485           switch(vtype) {
02486              case xmlrpc_vector_none:
02487                 return "none";
02488              case xmlrpc_vector_array:
02489                 return "array";
02490              case xmlrpc_vector_mixed:
02491                 return "mixed vector (struct)";
02492              case xmlrpc_vector_struct:
02493                 return "struct";
02494           }
02495     }
02496     return "unknown";
02497 }
02498 
02499 /****f* VALUE/XMLRPC_ServerFindMethod
02500  * NAME
02501  *   XMLRPC_ServerFindMethod
02502  * SYNOPSIS
02503  *   XMLRPC_Callback XMLRPC_ServerFindMethod(XMLRPC_SERVER server, const char* callName)
02504  * FUNCTION
02505  *   retrieve C callback associated with a given method name.
02506  * INPUTS       
02507  *   server     The XMLRPC_SERVER the method is registered with
02508  *   callName   the method to find
02509  * RESULT
02510  *   previously registered XMLRPC_Callback, or NULL
02511  * NOTES
02512  *   Typically, this is used to determine if a requested method exists, without actually calling it.
02513  * SEE ALSO
02514  *   XMLRPC_ServerCallMethod ()
02515  *   XMLRPC_ServerRegisterMethod ()
02516  * SOURCE
02517  */
02518 XMLRPC_Callback XMLRPC_ServerFindMethod(XMLRPC_SERVER server, const char* callName) {
02519    if(server && callName) {
02520       q_iter qi = Q_Iter_Head_F(&server->methodlist);
02521       while( qi ) {
02522          server_method* sm = Q_Iter_Get_F(qi);
02523          if(sm && !strcmp(sm->name, callName)) {
02524             return sm->method;
02525          }
02526          qi = Q_Iter_Next_F(qi);
02527       }
02528    }
02529    return NULL;
02530 }
02531 
02532 /*******/
02533 
02534 
02535 /* Call method specified in request */
02536 /****f* VALUE/XMLRPC_ServerCallMethod
02537  * NAME
02538  *   XMLRPC_ServerCallMethod
02539  * SYNOPSIS
02540  *   XMLRPC_VALUE XMLRPC_ServerCallMethod(XMLRPC_SERVER server, XMLRPC_REQUEST request, void* userData)
02541  * FUNCTION
02542  *
02543  * INPUTS
02544  *   server     The XMLRPC_SERVER the method is registered with
02545  *   request    the request to handle
02546  *   userData   any additional data to pass to the C callback, or NULL
02547  * RESULT
02548  *   XMLRPC_VALUE allocated by the callback, or NULL
02549  * NOTES
02550  *   It is typically the caller's responsibility to free the returned value.
02551  *
02552  *   Often the caller will want to serialize the result as XML, via 
02553  *   XMLRPC_VALUE_To_XML () or XMLRPC_REQUEST_To_XML ()
02554  * SEE ALSO
02555  *   XMLRPC_ServerFindMethod ()
02556  *   XMLRPC_ServerRegisterMethod ()
02557  *   XMLRPC_CleanupValue ()
02558  * SOURCE
02559  */
02560 XMLRPC_VALUE XMLRPC_ServerCallMethod(XMLRPC_SERVER server, XMLRPC_REQUEST request, void* userData) {
02561    XMLRPC_VALUE xReturn = NULL;
02562 
02563    /* check for error set during request parsing / generation */
02564    if(request && request->error) {
02565       xReturn = XMLRPC_CopyValue(request->error);
02566    }
02567        else if (server && request) {
02568               XMLRPC_Callback cb =
02569               XMLRPC_ServerFindMethod (server, request->methodName.str);
02570       if(cb) {
02571          xReturn = cb(server, request, userData);
02572       }
02573       else {
02574                      xReturn =
02575                      XMLRPC_UtilityCreateFault (xmlrpc_error_unknown_method,
02576                                                                                     request->methodName.str);
02577       }
02578    }
02579    return xReturn;
02580 }
02581 
02582 /*******/
02583 
02584 /*-*****************
02585 * End server funcs *
02586 *******************/
02587 
02588 
02589 /*-***********************************
02590 * Begin XMLRPC General Options funcs *
02591 *************************************/
02592 
02593 /* For options used by XMLRPC_VALUE funcs that otherwise do not have
02594  * parameters for options.  Kind of gross.  :(
02595  */
02596 typedef struct _xmlrpc_options {
02597    XMLRPC_CASE id_case;
02598    XMLRPC_CASE_COMPARISON id_case_compare;
02599 }
02600 STRUCT_XMLRPC_OPTIONS, *XMLRPC_OPTIONS;
02601 
02602 static XMLRPC_OPTIONS XMLRPC_GetDefaultOptions() {
02603    static STRUCT_XMLRPC_OPTIONS options = {
02604       xmlrpc_case_exact,
02605       xmlrpc_case_sensitive
02606    };
02607    return &options;
02608 }
02609 
02610 /****f* VALUE/XMLRPC_GetDefaultIdCase
02611  * NAME
02612  *   XMLRPC_GetDefaultIdCase
02613  * SYNOPSIS
02614  *   XMLRPC_CASE XMLRPC_GetDefaultIdCase()
02615  * FUNCTION
02616  *   Gets default case options used by XMLRPC_VALUE funcs
02617  * INPUTS
02618  *   none
02619  * RESULT
02620  *   XMLRPC_CASE
02621  * BUGS
02622  *   Nasty and gross.  Should be server specific, but that requires changing all
02623  *  the XMLRPC_VALUE api's.
02624  * SEE ALSO
02625  *   XMLRPC_SetDefaultIdCase ()
02626  * SOURCE
02627  */
02628 XMLRPC_CASE XMLRPC_GetDefaultIdCase() {
02629    XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
02630    return options->id_case;
02631 }
02632 
02633 /*******/
02634 
02635 /****f* VALUE/XMLRPC_SetDefaultIdCase
02636  * NAME
02637  *   XMLRPC_SetDefaultIdCase
02638  * SYNOPSIS
02639  *   XMLRPC_CASE XMLRPC_SetDefaultIdCase(XMLRPC_CASE id_case)
02640  * FUNCTION
02641  *   Sets default case options used by XMLRPC_VALUE funcs
02642  * INPUTS
02643  *   id_case   case options as enumerated by XMLRPC_CASE
02644  * RESULT
02645  *   XMLRPC_CASE -- newly set option
02646  * BUGS
02647  *   Nasty and gross.  Should be server specific, but that requires changing all
02648  *  the XMLRPC_VALUE api's.
02649  * SEE ALSO
02650  *   XMLRPC_GetDefaultIdCase ()
02651  * SOURCE
02652  */
02653 XMLRPC_CASE XMLRPC_SetDefaultIdCase(XMLRPC_CASE id_case) {
02654    XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
02655    options->id_case = id_case;
02656    return options->id_case;
02657 }
02658 
02659 /*******/
02660 
02661 /****f* VALUE/XMLRPC_GetDefaultIdCaseComparison
02662  * NAME
02663  *   XMLRPC_GetDefaultIdCaseComparison
02664  * SYNOPSIS
02665  *   XMLRPC_CASE XMLRPC_GetDefaultIdCaseComparison( )
02666  * FUNCTION
02667  *   Gets default case comparison options used by XMLRPC_VALUE funcs
02668  * INPUTS
02669  *   none
02670  * RESULT
02671  *   XMLRPC_CASE_COMPARISON default
02672  * BUGS
02673  *   Nasty and gross.  Should be server specific, but that requires changing all
02674  *  the XMLRPC_VALUE api's.
02675  * SEE ALSO
02676  *   XMLRPC_SetDefaultIdCaseComparison ()
02677  * SOURCE
02678  */
02679 XMLRPC_CASE_COMPARISON XMLRPC_GetDefaultIdCaseComparison() {
02680    XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
02681    return options->id_case_compare;
02682 }
02683 
02684 /*******/
02685 
02686 /****f* VALUE/XMLRPC_SetDefaultIdCaseComparison
02687  * NAME
02688  *   XMLRPC_SetDefaultIdCaseComparison
02689  * SYNOPSIS
02690  *   XMLRPC_CASE XMLRPC_SetDefaultIdCaseComparison( XMLRPC_CASE_COMPARISON id_case_compare )
02691  * FUNCTION
02692  *   Gets default case comparison options used by XMLRPC_VALUE funcs
02693  * INPUTS
02694  *   id_case_compare  case comparison rule to set as default
02695  * RESULT
02696  *   XMLRPC_CASE_COMPARISON newly set default
02697  * BUGS
02698  *   Nasty and gross.  Should be server specific, but that requires changing all
02699  *  the XMLRPC_VALUE api's.
02700  * SEE ALSO
02701  *   XMLRPC_GetDefaultIdCaseComparison ()
02702  * SOURCE
02703  */
02704 XMLRPC_CASE_COMPARISON XMLRPC_SetDefaultIdCaseComparison(XMLRPC_CASE_COMPARISON id_case_compare) {
02705    XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
02706    options->id_case_compare = id_case_compare;
02707    return options->id_case_compare;
02708 }
02709 
02710 /*******/
02711 
02712 /*-*********************************
02713 * End XMLRPC General Options funcs *
02714 ***********************************/
02715 
02716 
02717 /*-******************
02718 * Fault API funcs   *
02719 ********************/
02720 
02721 /****f* UTILITY/XMLRPC_UtilityCreateFault
02722  * NAME
02723  *   XMLRPC_UtilityCreateFault
02724  * SYNOPSIS
02725  *   XMLRPC_VALUE XMLRPC_UtilityCreateFault( int fault_code, const char* fault_string )
02726  * FUNCTION
02727  *   generates a struct containing a string member with id "faultString" and an int member
02728  *   with id "faultCode". When using the xmlrpc xml serialization, these will be translated
02729  *   to <fault><value><struct>... format.
02730  * INPUTS
02731  *   fault_code     application specific error code. can be 0.
02732  *   fault_string   application specific error string.  cannot be null.
02733  * RESULT
02734  *   XMLRPC_VALUE a newly created struct vector representing the error, or null on error.
02735  * NOTES
02736  *   This is a utility function. xmlrpc "faults" are not directly represented in this xmlrpc
02737  *   API or data structures. It is the author's view, that this API is intended for simple
02738  *   data types, and a "fault" is a complex data type consisting of multiple simple data
02739  *   types.  This function is provided for convenience only, the same result could be
02740  *   achieved directly by the application.
02741  *
02742  *   This function now supports some "standardized" fault codes, as specified at.
02743  *   http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php.
02744  *   If one of these fault codes is received, the description string will automatically
02745  *   be prefixed with a standard error string and 2 newlines.  
02746  *
02747  *   The actual transformation between this complex type and the xml "<fault>" element takes
02748  *   place in the xmlrpc to xml serialization layer.  This step is not performed when using the
02749  *   simplerpc serialization, meaning that there will be no "<fault>" element in that
02750  *   serialization. There will simply be a standard struct with 2 child elements.  
02751  *   imho, the "<fault>" element is unnecessary and/or out of place as part of the standard API.
02752  *
02753  * SOURCE
02754  */
02755 XMLRPC_VALUE XMLRPC_UtilityCreateFault(int fault_code, const char* fault_string) {
02756    XMLRPC_VALUE xOutput = NULL;
02757 
02758    char* string = NULL;
02759    simplestring description;
02760    simplestring_init(&description);
02761 
02762    switch (fault_code) {
02763        case xmlrpc_error_parse_xml_syntax:
02764               string = xmlrpc_error_parse_xml_syntax_str;
02765               break;
02766        case xmlrpc_error_parse_unknown_encoding:
02767               string = xmlrpc_error_parse_unknown_encoding_str;
02768               break;
02769        case xmlrpc_error_parse_bad_encoding:
02770               string = xmlrpc_error_parse_bad_encoding_str;
02771               break;
02772        case xmlrpc_error_invalid_xmlrpc:
02773               string = xmlrpc_error_invalid_xmlrpc_str;
02774               break;
02775        case xmlrpc_error_unknown_method:
02776               string = xmlrpc_error_unknown_method_str;
02777               break;
02778        case xmlrpc_error_invalid_params:
02779               string = xmlrpc_error_invalid_params_str;
02780               break;
02781        case xmlrpc_error_internal_server:
02782               string = xmlrpc_error_internal_server_str;
02783               break;
02784        case xmlrpc_error_application:
02785               string = xmlrpc_error_application_str;
02786               break;
02787        case xmlrpc_error_system:
02788               string = xmlrpc_error_system_str;
02789               break;
02790        case xmlrpc_error_transport:
02791               string = xmlrpc_error_transport_str;
02792               break;
02793    }
02794 
02795    simplestring_add(&description, string);
02796 
02797    if(string && fault_string) {
02798       simplestring_add(&description, "\n\n");
02799    }
02800    simplestring_add(&description, fault_string);
02801 
02802 
02803    if(description.len) {
02804       xOutput = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
02805 
02806               XMLRPC_VectorAppendString (xOutput, "faultString", description.str,
02807                                                                              description.len);
02808       XMLRPC_VectorAppendInt(xOutput, "faultCode", fault_code);
02809    }
02810 
02811    simplestring_free(&description);
02812 
02813    return xOutput;
02814 }
02815 
02816 /*******/
02817 
02818 
02819 /****f* FAULT/XMLRPC_ValueIsFault
02820  * NAME
02821  *   XMLRPC_ValueIsFault
02822  * SYNOPSIS
02823  *   int XMLRPC_ValueIsFault (XMLRPC_VALUE value)
02824  * FUNCTION
02825  *   Determines if a value encapsulates a fault "object"
02826  * INPUTS
02827  *   value  any XMLRPC_VALUE
02828  * RESULT
02829  *   1 if it is a fault, else 0
02830  * SEE ALSO
02831  *   XMLRPC_ResponseIsFault ()
02832  * SOURCE
02833  */
02834 int XMLRPC_ValueIsFault (XMLRPC_VALUE value) {
02835    if( XMLRPC_VectorGetValueWithID(value, "faultCode") &&
02836        XMLRPC_VectorGetValueWithID(value, "faultString") ) {
02837       return 1;
02838    }
02839    return 0;
02840 }
02841 /*******/
02842 
02843 
02844 /****f* FAULT/XMLRPC_ResponseIsFault
02845  * NAME
02846  *   XMLRPC_ResponseIsFault
02847  * SYNOPSIS
02848  *   int XMLRPC_ResponseIsFault (XMLRPC_REQUEST response)
02849  * FUNCTION
02850  *   Determines if a response contains an encapsulated fault "object"
02851  * INPUTS
02852  *   value  any XMLRPC_REQUEST. typically of type xmlrpc_request_response
02853  * RESULT
02854  *   1 if it contains a fault, else 0
02855  * SEE ALSO
02856  *   XMLRPC_ValueIsFault ()
02857  * SOURCE
02858  */
02859 int XMLRPC_ResponseIsFault(XMLRPC_REQUEST response) {
02860    return XMLRPC_ValueIsFault( XMLRPC_RequestGetData(response) );
02861 }
02862 
02863 /*******/
02864 
02865 /****f* FAULT/XMLRPC_GetValueFaultCode
02866  * NAME
02867  *   XMLRPC_GetValueFaultCode
02868  * SYNOPSIS
02869  *   int XMLRPC_GetValueFaultCode (XMLRPC_VALUE value)
02870  * FUNCTION
02871  *   returns fault code from a struct, if any
02872  * INPUTS
02873  *   value  XMLRPC_VALUE of type xmlrpc_vector_struct.
02874  * RESULT
02875  *   fault code, else 0.
02876  * BUGS
02877  *   impossible to distinguish faultCode == 0 from faultCode not present.
02878  * SEE ALSO
02879  *   XMLRPC_GetResponseFaultCode ()
02880  * SOURCE
02881  */
02882 int XMLRPC_GetValueFaultCode (XMLRPC_VALUE value) {
02883    return XMLRPC_VectorGetIntWithID(value, "faultCode");
02884 }
02885 
02886 /*******/
02887 
02888 /****f* FAULT/XMLRPC_GetResponseFaultCode
02889  * NAME
02890  *   XMLRPC_GetResponseFaultCode
02891  * SYNOPSIS
02892  *   int XMLRPC_GetResponseFaultCode(XMLRPC_REQUEST response)
02893  * FUNCTION
02894  *   returns fault code from a response, if any
02895  * INPUTS
02896  *   response  XMLRPC_REQUEST. typically of type xmlrpc_request_response.
02897  * RESULT
02898  *   fault code, else 0.
02899  * BUGS
02900  *   impossible to distinguish faultCode == 0 from faultCode not present.
02901  * SEE ALSO
02902  *   XMLRPC_GetValueFaultCode ()
02903  * SOURCE
02904  */
02905 int XMLRPC_GetResponseFaultCode(XMLRPC_REQUEST response) {
02906    return XMLRPC_GetValueFaultCode( XMLRPC_RequestGetData(response) );
02907 }
02908 
02909 /*******/
02910 
02911 
02912 /****f* FAULT/XMLRPC_GetValueFaultString
02913  * NAME
02914  *   XMLRPC_GetValueFaultString
02915  * SYNOPSIS
02916  *   const char* XMLRPC_GetValueFaultString (XMLRPC_VALUE value)
02917  * FUNCTION
02918  *   returns fault string from a struct, if any
02919  * INPUTS
02920  *   value  XMLRPC_VALUE of type xmlrpc_vector_struct.
02921  * RESULT
02922  *   fault string, else 0.
02923  * SEE ALSO
02924  *   XMLRPC_GetResponseFaultString ()
02925  * SOURCE
02926  */
02927 const char* XMLRPC_GetValueFaultString (XMLRPC_VALUE value) {
02928    return XMLRPC_VectorGetStringWithID(value, "faultString");
02929 }
02930 
02931 /*******/
02932 
02933 /****f* FAULT/XMLRPC_GetResponseFaultString
02934  * NAME
02935  *   XMLRPC_GetResponseFaultString
02936  * SYNOPSIS
02937  *   const char* XMLRPC_GetResponseFaultString (XMLRPC_REQUEST response)
02938  * FUNCTION
02939  *   returns fault string from a response, if any
02940  * INPUTS
02941  *   response  XMLRPC_REQUEST. typically of type xmlrpc_request_response.
02942  * RESULT
02943  *   fault string, else 0.
02944  * SEE ALSO
02945  *   XMLRPC_GetValueFaultString ()
02946  * SOURCE
02947  */
02948 const char* XMLRPC_GetResponseFaultString (XMLRPC_REQUEST response) {
02949    return XMLRPC_GetValueFaultString( XMLRPC_RequestGetData(response) );
02950 }
02951 
02952 /*******/
02953 
02954 
02955 /*-******************
02956 * Utility API funcs *
02957 ********************/
02958 
02959 
02960 /****f* UTILITY/XMLRPC_Free
02961  * NAME
02962  *   XMLRPC_Free
02963  * SYNOPSIS
02964  *   void XMLRPC_Free(void* mem)
02965  * FUNCTION
02966  *   frees a block of memory allocated by xmlrpc. 
02967  * INPUTS
02968  *   mem    memory to free
02969  * RESULT
02970  *   void
02971  * NOTES
02972  *   Useful for OS's where memory must be free'd
02973  *   in the same library in which it is allocated.
02974  * SOURCE
02975  */
02976 void XMLRPC_Free(void* mem) {
02977    my_free(mem);
02978 }
02979 
02980 /*******/
02981 
02982 
02983 /****f* UTILITY/XMLRPC_GetVersionString
02984  * NAME
02985  *   XMLRPC_GetVersionString
02986  * SYNOPSIS
02987  *   const char* XMLRPC_GetVersionString()
02988  * FUNCTION
02989  *   returns library version string
02990  * INPUTS
02991  *   
02992  * RESULT
02993  *   const char* 
02994  * NOTES
02995  * SOURCE
02996  */
02997 const char*  XMLRPC_GetVersionString() {
02998    return XMLRPC_VERSION_STR;
02999 }
03000 
03001 /*******/
03002 
03003 
03004 /*-**********************
03005 * End Utility API funcs *
03006 ************************/