Annotation of embedaddon/php/ext/xmlrpc/libxmlrpc/xmlrpc.c, revision 1.1.1.2

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>