2005-02-22 21:08:27 +03:00
|
|
|
/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
|
|
|
|
**
|
|
|
|
** Redistribution and use in source and binary forms, with or without
|
|
|
|
** modification, are permitted provided that the following conditions
|
|
|
|
** are met:
|
|
|
|
** 1. Redistributions of source code must retain the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer.
|
|
|
|
** 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer in the
|
|
|
|
** documentation and/or other materials provided with the distribution.
|
|
|
|
** 3. The name of the author may not be used to endorse or promote products
|
|
|
|
** derived from this software without specific prior written permission.
|
|
|
|
**
|
|
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
|
|
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
** SUCH DAMAGE. */
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef _XMLRPC_H_
|
|
|
|
#define _XMLRPC_H_ 1
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_UNICODE_WCHAR
|
|
|
|
#include <wchar.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** Typedefs
|
|
|
|
**=========================================================================
|
|
|
|
** We define names for these types, because they may change from platform
|
|
|
|
** to platform.
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef signed int xmlrpc_int;
|
|
|
|
/* An integer of the type defined by XML-RPC <int>; i.e. 32 bit */
|
|
|
|
typedef signed int xmlrpc_int32;
|
|
|
|
/* An integer of the type defined by XML-RPC <int4>; i.e. 32 bit */
|
|
|
|
typedef int xmlrpc_bool;
|
|
|
|
/* A boolean (of the type defined by XML-RPC <boolean>, but there's
|
|
|
|
really only one kind)
|
|
|
|
*/
|
|
|
|
typedef double xmlrpc_double;
|
|
|
|
/* A double precision floating point number as defined by
|
|
|
|
XML-RPC <float>. But the C "double" type is universally the same,
|
|
|
|
so it's probably clearer just to use that. This typedef is here
|
|
|
|
for mathematical completeness.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define XMLRPC_INT32_MAX (2147483647)
|
|
|
|
#define XMLRPC_INT32_MIN (-XMLRPC_INT32_MAX - 1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** C struct size computations
|
|
|
|
**=======================================================================*/
|
|
|
|
|
|
|
|
/* Use XMLRPC_STRUCT_MEMBER_SIZE() to determine how big a structure is
|
|
|
|
up to and including a specified member. E.g. if you have
|
|
|
|
struct mystruct {int red; int green; int blue};, then
|
|
|
|
XMLRPC_STRUCT_MEMBER_SIZE(mystruct, green) is (8).
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define _XMLRPC_STRUCT_MEMBER_OFFSET(TYPE, MBRNAME) \
|
|
|
|
((unsigned int)(char*)&((TYPE *)0)->MBRNAME)
|
|
|
|
#define _XMLRPC_STRUCT_MEMBER_SIZE(TYPE, MBRNAME) \
|
|
|
|
sizeof(((TYPE *)0)->MBRNAME)
|
|
|
|
#define XMLRPC_STRUCTSIZE(TYPE, MBRNAME) \
|
|
|
|
(_XMLRPC_STRUCT_MEMBER_OFFSET(TYPE, MBRNAME) + \
|
|
|
|
_XMLRPC_STRUCT_MEMBER_SIZE(TYPE, MBRNAME))
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** Assertions and Debugging
|
|
|
|
**=========================================================================
|
|
|
|
** We use xmlrpc_assert for internal sanity checks. For example:
|
|
|
|
**
|
|
|
|
** xmlrpc_assert(ptr != NULL);
|
|
|
|
**
|
|
|
|
** Assertions are only evaluated when debugging code is turned on. (To
|
|
|
|
** turn debugging off, define NDEBUG.) Some rules for using assertions:
|
|
|
|
**
|
|
|
|
** 1) Assertions should never have side effects.
|
|
|
|
** 2) Assertions should never be used for run-time error checking.
|
|
|
|
** Instead, they should be used to check for "can't happen" errors.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
|
|
|
#define XMLRPC_ASSERT(cond) \
|
|
|
|
do \
|
|
|
|
if (!(cond)) \
|
|
|
|
xmlrpc_assertion_failed(__FILE__, __LINE__); \
|
|
|
|
while (0)
|
|
|
|
|
|
|
|
#else
|
|
|
|
#define XMLRPC_ASSERT(cond) (0)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
extern void xmlrpc_assertion_failed (char* file, int line);
|
|
|
|
|
|
|
|
/* Validate a pointer. */
|
|
|
|
#define XMLRPC_ASSERT_PTR_OK(ptr) \
|
|
|
|
XMLRPC_ASSERT((ptr) != NULL)
|
|
|
|
|
|
|
|
/* We only call this if something truly drastic happens. */
|
|
|
|
#define XMLRPC_FATAL_ERROR(msg) xmlrpc_fatal_error(__FILE__, __LINE__, (msg))
|
|
|
|
|
|
|
|
extern void xmlrpc_fatal_error (char* file, int line, char* msg);
|
|
|
|
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** Strings
|
|
|
|
**=======================================================================*/
|
|
|
|
|
|
|
|
/* Traditional C strings are char *, because they come from a time before
|
|
|
|
there was 'const'. Now, const char * makes a lot more sense. Also,
|
|
|
|
in modern times, we tend to dynamically allocate memory for strings.
|
|
|
|
We need this free function accordingly. Ordinary free() doesn't check
|
|
|
|
the type, and can generate a warning due to the 'const'.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
xmlrpc_strfree(const char * const string);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** xmlrpc_env
|
|
|
|
**=========================================================================
|
|
|
|
** XML-RPC represents runtime errors as <fault> elements. These contain
|
|
|
|
** <faultCode> and <faultString> elements.
|
|
|
|
**
|
|
|
|
** Since we need as much thread-safety as possible, we borrow an idea from
|
|
|
|
** CORBA--we store exception information in an "environment" object.
|
|
|
|
** You'll pass this to many different functions, and it will get filled
|
|
|
|
** out appropriately.
|
|
|
|
**
|
|
|
|
** For example:
|
|
|
|
**
|
|
|
|
** xmlrpc_env env;
|
|
|
|
**
|
|
|
|
** xmlrpc_env_init(&env);
|
|
|
|
**
|
|
|
|
** xmlrpc_do_something(&env);
|
|
|
|
** if (env.fault_occurred)
|
|
|
|
** report_error_appropriately();
|
|
|
|
**
|
|
|
|
** xmlrpc_env_clean(&env);
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define XMLRPC_INTERNAL_ERROR (-500)
|
|
|
|
#define XMLRPC_TYPE_ERROR (-501)
|
|
|
|
#define XMLRPC_INDEX_ERROR (-502)
|
|
|
|
#define XMLRPC_PARSE_ERROR (-503)
|
|
|
|
#define XMLRPC_NETWORK_ERROR (-504)
|
|
|
|
#define XMLRPC_TIMEOUT_ERROR (-505)
|
|
|
|
#define XMLRPC_NO_SUCH_METHOD_ERROR (-506)
|
|
|
|
#define XMLRPC_REQUEST_REFUSED_ERROR (-507)
|
|
|
|
#define XMLRPC_INTROSPECTION_DISABLED_ERROR (-508)
|
|
|
|
#define XMLRPC_LIMIT_EXCEEDED_ERROR (-509)
|
|
|
|
#define XMLRPC_INVALID_UTF8_ERROR (-510)
|
|
|
|
|
|
|
|
typedef struct _xmlrpc_env {
|
|
|
|
int fault_occurred;
|
|
|
|
xmlrpc_int32 fault_code;
|
|
|
|
char* fault_string;
|
|
|
|
} xmlrpc_env;
|
|
|
|
|
|
|
|
/* Initialize and destroy the contents of the provided xmlrpc_env object.
|
|
|
|
** These functions will never fail. */
|
|
|
|
void xmlrpc_env_init (xmlrpc_env* env);
|
|
|
|
void xmlrpc_env_clean (xmlrpc_env* env);
|
|
|
|
|
|
|
|
/* Fill out an xmlrpc_fault with the specified values, and set the
|
|
|
|
** fault_occurred flag. This function will make a private copy of 'string',
|
|
|
|
** so you retain responsibility for your copy. */
|
|
|
|
void
|
|
|
|
xmlrpc_env_set_fault(xmlrpc_env * const env,
|
|
|
|
int const faultCode,
|
|
|
|
const char * const faultDescription);
|
|
|
|
|
|
|
|
/* The same as the above, but using a printf-style format string. */
|
|
|
|
void
|
|
|
|
xmlrpc_env_set_fault_formatted (xmlrpc_env * const envP,
|
|
|
|
int const code,
|
|
|
|
const char * const format,
|
|
|
|
...);
|
|
|
|
|
|
|
|
/* A simple debugging assertion. */
|
|
|
|
#define XMLRPC_ASSERT_ENV_OK(env) \
|
|
|
|
XMLRPC_ASSERT((env) != NULL && !(env)->fault_occurred)
|
|
|
|
|
|
|
|
/* This version must *not* interpret 'str' as a format string, to avoid
|
|
|
|
** several evil attacks. */
|
|
|
|
#define XMLRPC_FAIL(env,code,str) \
|
|
|
|
do { xmlrpc_env_set_fault((env),(code),(str)); goto cleanup; } while (0)
|
|
|
|
|
|
|
|
#define XMLRPC_FAIL1(env,code,str,arg1) \
|
|
|
|
do { \
|
|
|
|
xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1)); \
|
|
|
|
goto cleanup; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define XMLRPC_FAIL2(env,code,str,arg1,arg2) \
|
|
|
|
do { \
|
|
|
|
xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1),(arg2)); \
|
|
|
|
goto cleanup; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define XMLRPC_FAIL3(env,code,str,arg1,arg2,arg3) \
|
|
|
|
do { \
|
|
|
|
xmlrpc_env_set_fault_formatted((env),(code), \
|
|
|
|
(str),(arg1),(arg2),(arg3)); \
|
|
|
|
goto cleanup; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define XMLRPC_FAIL_IF_NULL(ptr,env,code,str) \
|
|
|
|
do { \
|
|
|
|
if ((ptr) == NULL) \
|
|
|
|
XMLRPC_FAIL((env),(code),(str)); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define XMLRPC_FAIL_IF_FAULT(env) \
|
|
|
|
do { if ((env)->fault_occurred) goto cleanup; } while (0)
|
|
|
|
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** Resource Limits
|
|
|
|
**=========================================================================
|
|
|
|
** To discourage denial-of-service attacks, we provide several adjustable
|
|
|
|
** resource limits. These functions are *not* re-entrant.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Limit IDs. There will be more of these as time goes on. */
|
|
|
|
#define XMLRPC_NESTING_LIMIT_ID (0)
|
|
|
|
#define XMLRPC_XML_SIZE_LIMIT_ID (1)
|
|
|
|
#define XMLRPC_LAST_LIMIT_ID (XMLRPC_XML_SIZE_LIMIT_ID)
|
|
|
|
|
|
|
|
/* By default, deserialized data may be no more than 64 levels deep. */
|
|
|
|
#define XMLRPC_NESTING_LIMIT_DEFAULT (64)
|
|
|
|
|
|
|
|
/* By default, XML data from the network may be no larger than 512K.
|
|
|
|
** Some client and server modules may fail to enforce this properly. */
|
|
|
|
#define XMLRPC_XML_SIZE_LIMIT_DEFAULT (512*1024)
|
|
|
|
|
|
|
|
/* Set a specific limit to the specified value. */
|
|
|
|
extern void xmlrpc_limit_set (int limit_id, size_t value);
|
|
|
|
|
|
|
|
/* Get the value of a specified limit. */
|
|
|
|
extern size_t xmlrpc_limit_get (int limit_id);
|
|
|
|
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** xmlrpc_mem_block
|
|
|
|
**=========================================================================
|
|
|
|
** A resizable chunk of memory. This is mostly used internally, but it is
|
|
|
|
** also used by the public API in a few places.
|
|
|
|
** The struct fields are private!
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef struct _xmlrpc_mem_block {
|
|
|
|
size_t _size;
|
|
|
|
size_t _allocated;
|
|
|
|
void* _block;
|
|
|
|
} xmlrpc_mem_block;
|
|
|
|
|
|
|
|
/* Allocate a new xmlrpc_mem_block. */
|
2005-02-24 04:28:21 +03:00
|
|
|
xmlrpc_mem_block* xmlrpc_mem_block_new (xmlrpc_env* const env, size_t const size);
|
2005-02-22 21:08:27 +03:00
|
|
|
|
|
|
|
/* Destroy an existing xmlrpc_mem_block, and everything it contains. */
|
|
|
|
void xmlrpc_mem_block_free (xmlrpc_mem_block* block);
|
|
|
|
|
|
|
|
/* Initialize the contents of the provided xmlrpc_mem_block. */
|
|
|
|
void xmlrpc_mem_block_init
|
|
|
|
(xmlrpc_env* env, xmlrpc_mem_block* block, size_t size);
|
|
|
|
|
|
|
|
/* Deallocate the contents of the provided xmlrpc_mem_block, but not the
|
|
|
|
** block itself. */
|
|
|
|
void xmlrpc_mem_block_clean (xmlrpc_mem_block* block);
|
|
|
|
|
|
|
|
/* Get the size and contents of the xmlrpc_mem_block. */
|
|
|
|
size_t
|
|
|
|
xmlrpc_mem_block_size(const xmlrpc_mem_block * const block);
|
|
|
|
|
|
|
|
void *
|
|
|
|
xmlrpc_mem_block_contents(const xmlrpc_mem_block * const block);
|
|
|
|
|
|
|
|
/* Resize an xmlrpc_mem_block, preserving as much of the contents as
|
|
|
|
** possible. */
|
|
|
|
void xmlrpc_mem_block_resize
|
2005-02-24 04:28:21 +03:00
|
|
|
(xmlrpc_env* const env, xmlrpc_mem_block* const block, size_t const size);
|
2005-02-22 21:08:27 +03:00
|
|
|
|
|
|
|
/* Append data to an existing xmlrpc_mem_block. */
|
|
|
|
void xmlrpc_mem_block_append
|
2005-02-24 04:28:21 +03:00
|
|
|
(xmlrpc_env* const env, xmlrpc_mem_block* const block, void *const data, size_t const len);
|
2005-02-22 21:08:27 +03:00
|
|
|
|
|
|
|
#define XMLRPC_MEMBLOCK_NEW(type,env,size) \
|
|
|
|
xmlrpc_mem_block_new((env), sizeof(type) * (size))
|
|
|
|
#define XMLRPC_MEMBLOCK_FREE(type,block) \
|
|
|
|
xmlrpc_mem_block_free(block)
|
|
|
|
#define XMLRPC_MEMBLOCK_INIT(type,env,block,size) \
|
|
|
|
xmlrpc_mem_block_init((env), (block), sizeof(type) * (size))
|
|
|
|
#define XMLRPC_MEMBLOCK_CLEAN(type,block) \
|
|
|
|
xmlrpc_mem_block_clean(block)
|
|
|
|
#define XMLRPC_MEMBLOCK_SIZE(type,block) \
|
|
|
|
(xmlrpc_mem_block_size(block) / sizeof(type))
|
|
|
|
#define XMLRPC_MEMBLOCK_CONTENTS(type,block) \
|
|
|
|
((type*) xmlrpc_mem_block_contents(block))
|
|
|
|
#define XMLRPC_MEMBLOCK_RESIZE(type,env,block,size) \
|
|
|
|
xmlrpc_mem_block_resize(env, block, sizeof(type) * (size))
|
|
|
|
#define XMLRPC_MEMBLOCK_APPEND(type,env,block,data,size) \
|
|
|
|
xmlrpc_mem_block_append(env, block, data, sizeof(type) * (size))
|
|
|
|
|
|
|
|
/* Here are some backward compatibility definitions. These longer names
|
|
|
|
used to be the only ones and typed memory blocks were considered
|
|
|
|
special.
|
|
|
|
*/
|
|
|
|
#define XMLRPC_TYPED_MEM_BLOCK_NEW(type,env,size) \
|
|
|
|
XMLRPC_MEMBLOCK_NEW(type,env,size)
|
|
|
|
#define XMLRPC_TYPED_MEM_BLOCK_FREE(type,block) \
|
|
|
|
XMLRPC_MEMBLOCK_FREE(type,block)
|
|
|
|
#define XMLRPC_TYPED_MEM_BLOCK_INIT(type,env,block,size) \
|
|
|
|
XMLRPC_MEMBLOCK_INIT(type,env,block,size)
|
|
|
|
#define XMLRPC_TYPED_MEM_BLOCK_CLEAN(type,block) \
|
|
|
|
XMLRPC_MEMBLOCK_CLEAN(type,block)
|
|
|
|
#define XMLRPC_TYPED_MEM_BLOCK_SIZE(type,block) \
|
|
|
|
XMLRPC_MEMBLOCK_SIZE(type,block)
|
|
|
|
#define XMLRPC_TYPED_MEM_BLOCK_CONTENTS(type,block) \
|
|
|
|
XMLRPC_MEMBLOCK_CONTENTS(type,block)
|
|
|
|
#define XMLRPC_TYPED_MEM_BLOCK_RESIZE(type,env,block,size) \
|
|
|
|
XMLRPC_MEMBLOCK_RESIZE(type,env,block,size)
|
|
|
|
#define XMLRPC_TYPED_MEM_BLOCK_APPEND(type,env,block,data,size) \
|
|
|
|
XMLRPC_MEMBLOCK_APPEND(type,env,block,data,size)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** xmlrpc_value
|
|
|
|
**=========================================================================
|
|
|
|
** An XML-RPC value (of any type).
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
XMLRPC_TYPE_INT = 0,
|
|
|
|
XMLRPC_TYPE_BOOL = 1,
|
|
|
|
XMLRPC_TYPE_DOUBLE = 2,
|
|
|
|
XMLRPC_TYPE_DATETIME = 3,
|
|
|
|
XMLRPC_TYPE_STRING = 4,
|
|
|
|
XMLRPC_TYPE_BASE64 = 5,
|
|
|
|
XMLRPC_TYPE_ARRAY = 6,
|
|
|
|
XMLRPC_TYPE_STRUCT = 7,
|
|
|
|
XMLRPC_TYPE_C_PTR = 8,
|
|
|
|
XMLRPC_TYPE_DEAD = 0xDEAD,
|
|
|
|
} xmlrpc_type;
|
|
|
|
|
|
|
|
/* These are *always* allocated on the heap. No exceptions. */
|
|
|
|
typedef struct _xmlrpc_value xmlrpc_value;
|
|
|
|
|
|
|
|
#define XMLRPC_ASSERT_VALUE_OK(val) \
|
|
|
|
XMLRPC_ASSERT((val) != NULL && (val)->_type != XMLRPC_TYPE_DEAD)
|
|
|
|
|
|
|
|
/* A handy type-checking routine. */
|
|
|
|
#define XMLRPC_TYPE_CHECK(env,v,t) \
|
|
|
|
do \
|
|
|
|
if ((v)->_type != (t)) \
|
|
|
|
XMLRPC_FAIL(env, XMLRPC_TYPE_ERROR, "Expected " #t); \
|
|
|
|
while (0)
|
|
|
|
|
|
|
|
void
|
|
|
|
xmlrpc_abort_if_array_bad(xmlrpc_value * const arrayP);
|
|
|
|
|
|
|
|
#define XMLRPC_ASSERT_ARRAY_OK(val) \
|
|
|
|
xmlrpc_abort_if_array_bad(val)
|
|
|
|
|
|
|
|
/* Increment the reference count of an xmlrpc_value. */
|
2005-02-24 04:28:21 +03:00
|
|
|
extern void xmlrpc_INCREF (xmlrpc_value* const value);
|
2005-02-22 21:08:27 +03:00
|
|
|
|
|
|
|
/* Decrement the reference count of an xmlrpc_value. If there
|
|
|
|
** are no more references, free it. */
|
2005-02-24 04:28:21 +03:00
|
|
|
extern void xmlrpc_DECREF (xmlrpc_value* const value);
|
2005-02-22 21:08:27 +03:00
|
|
|
|
|
|
|
/* Get the type of an XML-RPC value. */
|
|
|
|
extern xmlrpc_type xmlrpc_value_type (xmlrpc_value* value);
|
|
|
|
|
|
|
|
/* Build an xmlrpc_value from a format string.
|
|
|
|
** Increments the reference counts of input arguments if necessary.
|
|
|
|
** See the xmlrpc-c documentation for more information. */
|
|
|
|
xmlrpc_value *
|
|
|
|
xmlrpc_build_value(xmlrpc_env * const env,
|
|
|
|
const char * const format,
|
|
|
|
...);
|
|
|
|
|
|
|
|
/* The same as the above, but using a va_list and more general */
|
|
|
|
void
|
|
|
|
xmlrpc_build_value_va(xmlrpc_env * const env,
|
|
|
|
const char * const format,
|
|
|
|
va_list args,
|
|
|
|
xmlrpc_value ** const valPP,
|
|
|
|
const char ** const tailP);
|
|
|
|
|
|
|
|
/* Extract values from an xmlrpc_value and store them into C variables.
|
|
|
|
** Does not increment the reference counts of output values.
|
|
|
|
** See the xmlrpc-c documentation for more information. */
|
|
|
|
void
|
|
|
|
xmlrpc_parse_value(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const value,
|
|
|
|
const char * const format,
|
|
|
|
...);
|
|
|
|
|
|
|
|
/* The same as the above, but using a va_list. */
|
|
|
|
void
|
|
|
|
xmlrpc_parse_value_va(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const value,
|
|
|
|
const char * const format,
|
|
|
|
va_list args);
|
|
|
|
|
|
|
|
void
|
|
|
|
xmlrpc_read_int(xmlrpc_env * const envP,
|
|
|
|
const xmlrpc_value * const valueP,
|
|
|
|
int * const intValueP);
|
|
|
|
|
|
|
|
void
|
|
|
|
xmlrpc_read_double(xmlrpc_env * const envP,
|
|
|
|
const xmlrpc_value * const valueP,
|
|
|
|
xmlrpc_double * const doubleValueP);
|
|
|
|
|
|
|
|
void
|
|
|
|
xmlrpc_read_bool(xmlrpc_env * const envP,
|
|
|
|
const xmlrpc_value * const valueP,
|
|
|
|
xmlrpc_bool * const boolValueP);
|
|
|
|
|
|
|
|
void
|
|
|
|
xmlrpc_read_string(xmlrpc_env * const envP,
|
|
|
|
const xmlrpc_value * const valueP,
|
|
|
|
const char ** const stringValueP);
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
xmlrpc_read_string_lp(xmlrpc_env * const envP,
|
|
|
|
const xmlrpc_value * const valueP,
|
|
|
|
unsigned int * const lengthP,
|
|
|
|
const char ** const stringValueP);
|
|
|
|
|
|
|
|
/* Return the number of elements in an XML-RPC array.
|
|
|
|
** Sets XMLRPC_TYPE_ERROR if 'array' is not an array. */
|
|
|
|
int
|
|
|
|
xmlrpc_array_size(xmlrpc_env * const env,
|
|
|
|
const xmlrpc_value * const array);
|
|
|
|
|
|
|
|
/* Append an item to an XML-RPC array.
|
|
|
|
** Increments the reference count of 'value' if no fault occurs.
|
|
|
|
** Sets XMLRPC_TYPE_ERROR if 'array' is not an array. */
|
|
|
|
extern void
|
2005-02-24 04:28:21 +03:00
|
|
|
xmlrpc_array_append_item (xmlrpc_env* const env,
|
|
|
|
xmlrpc_value* const array,
|
|
|
|
xmlrpc_value* const value);
|
2005-02-22 21:08:27 +03:00
|
|
|
|
|
|
|
void
|
|
|
|
xmlrpc_array_read_item(xmlrpc_env * const envP,
|
|
|
|
const xmlrpc_value * const arrayP,
|
|
|
|
unsigned int const index,
|
|
|
|
xmlrpc_value ** const valuePP);
|
|
|
|
|
|
|
|
/* Get an item from an XML-RPC array.
|
|
|
|
** Does not increment the reference count of the returned value.
|
|
|
|
** Sets XMLRPC_TYPE_ERROR if 'array' is not an array.
|
|
|
|
** Sets XMLRPC_INDEX_ERROR if 'index' is out of bounds. */
|
|
|
|
xmlrpc_value *
|
|
|
|
xmlrpc_array_get_item(xmlrpc_env * const env,
|
|
|
|
const xmlrpc_value * const array,
|
|
|
|
int const index);
|
|
|
|
|
|
|
|
/* Not implemented--we don't need it yet.
|
|
|
|
extern
|
|
|
|
int xmlrpc_array_set_item (xmlrpc_env* env,
|
|
|
|
xmlrpc_value* array,
|
|
|
|
int index,
|
|
|
|
xmlrpc_value* value);
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Create a new struct. Deprecated. xmlrpc_build_value() is the
|
|
|
|
general way to create an xmlrpc_value, including an empty struct.
|
|
|
|
*/
|
|
|
|
xmlrpc_value *
|
|
|
|
xmlrpc_struct_new(xmlrpc_env * env);
|
|
|
|
|
|
|
|
/* Return the number of key/value pairs in a struct.
|
|
|
|
** Sets XMLRPC_TYPE_ERROR if 'strct' is not a struct. */
|
|
|
|
int
|
|
|
|
xmlrpc_struct_size (xmlrpc_env * env,
|
|
|
|
xmlrpc_value * strct);
|
|
|
|
|
|
|
|
/* Returns true iff 'strct' contains 'key'.
|
|
|
|
** Sets XMLRPC_TYPE_ERROR if 'strct' is not a struct. */
|
|
|
|
int
|
|
|
|
xmlrpc_struct_has_key(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const strctP,
|
|
|
|
const char * const key);
|
|
|
|
|
|
|
|
/* The same as the above, but the key may contain zero bytes.
|
|
|
|
Deprecated. xmlrpc_struct_get_value_v() is more general, and this
|
|
|
|
case is not common enough to warrant a shortcut.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
xmlrpc_struct_has_key_n(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const strctP,
|
|
|
|
const char * const key,
|
|
|
|
size_t const key_len);
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/* Not implemented yet, but needed for completeness. */
|
|
|
|
int
|
|
|
|
xmlrpc_struct_has_key_v(xmlrpc_env * env,
|
|
|
|
xmlrpc_value * strct,
|
|
|
|
xmlrpc_value * const keyval);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
xmlrpc_struct_find_value(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const structP,
|
|
|
|
const char * const key,
|
|
|
|
xmlrpc_value ** const valuePP);
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
xmlrpc_struct_find_value_v(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const structP,
|
|
|
|
xmlrpc_value * const keyP,
|
|
|
|
xmlrpc_value ** const valuePP);
|
|
|
|
|
|
|
|
void
|
|
|
|
xmlrpc_struct_read_value_v(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const structP,
|
|
|
|
xmlrpc_value * const keyP,
|
|
|
|
xmlrpc_value ** const valuePP);
|
|
|
|
|
|
|
|
void
|
|
|
|
xmlrpc_struct_read_value(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const strctP,
|
|
|
|
const char * const key,
|
|
|
|
xmlrpc_value ** const valuePP);
|
|
|
|
|
|
|
|
/* The "get_value" functions are deprecated. Use the "find_value"
|
|
|
|
and "read_value" functions instead.
|
|
|
|
*/
|
|
|
|
xmlrpc_value *
|
|
|
|
xmlrpc_struct_get_value(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const strctP,
|
|
|
|
const char * const key);
|
|
|
|
|
|
|
|
/* The same as above, but the key may contain zero bytes.
|
|
|
|
Deprecated. xmlrpc_struct_get_value_v() is more general, and this
|
|
|
|
case is not common enough to warrant a shortcut.
|
|
|
|
*/
|
|
|
|
xmlrpc_value *
|
|
|
|
xmlrpc_struct_get_value_n(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const strctP,
|
|
|
|
const char * const key,
|
|
|
|
size_t const key_len);
|
|
|
|
|
|
|
|
/* Set the value associated with 'key' in 'strct' to 'value'.
|
|
|
|
** Increments the reference count of value.
|
|
|
|
** Sets XMLRPC_TYPE_ERROR if 'strct' is not a struct. */
|
|
|
|
void
|
|
|
|
xmlrpc_struct_set_value(xmlrpc_env * const env,
|
|
|
|
xmlrpc_value * const strct,
|
|
|
|
const char * const key,
|
|
|
|
xmlrpc_value * const value);
|
|
|
|
|
|
|
|
/* The same as above, but the key may contain zero bytes. Deprecated.
|
|
|
|
The general way to set a structure value is xmlrpc_struct_set_value_v(),
|
|
|
|
and this case is not common enough to deserve a shortcut.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
xmlrpc_struct_set_value_n(xmlrpc_env * const env,
|
|
|
|
xmlrpc_value * const strct,
|
|
|
|
const char * const key,
|
|
|
|
size_t const key_len,
|
|
|
|
xmlrpc_value * const value);
|
|
|
|
|
|
|
|
/* The same as above, but the key must be an XML-RPC string.
|
|
|
|
** Fails with XMLRPC_TYPE_ERROR if 'keyval' is not a string. */
|
|
|
|
void
|
|
|
|
xmlrpc_struct_set_value_v(xmlrpc_env * const env,
|
|
|
|
xmlrpc_value * const strct,
|
|
|
|
xmlrpc_value * const keyval,
|
|
|
|
xmlrpc_value * const value);
|
|
|
|
|
|
|
|
/* Given a zero-based index, return the matching key and value. This
|
|
|
|
** is normally used in conjunction with xmlrpc_struct_size.
|
|
|
|
** Fails with XMLRPC_TYPE_ERROR if 'struct' is not a struct.
|
|
|
|
** Fails with XMLRPC_INDEX_ERROR if 'index' is out of bounds. */
|
|
|
|
|
|
|
|
void
|
|
|
|
xmlrpc_struct_read_member(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const structP,
|
|
|
|
unsigned int const index,
|
|
|
|
xmlrpc_value ** const keyvalP,
|
|
|
|
xmlrpc_value ** const valueP);
|
|
|
|
|
|
|
|
/* The same as above, but does not increment the reference count of the
|
|
|
|
two values it returns, and return NULL for both if it fails, and
|
|
|
|
takes a signed integer for the index (but fails if it is negative).
|
|
|
|
|
|
|
|
Deprecated.
|
|
|
|
*/
|
|
|
|
void
|
2005-02-24 04:28:21 +03:00
|
|
|
xmlrpc_struct_get_key_and_value(xmlrpc_env * const env,
|
|
|
|
xmlrpc_value * const strct,
|
|
|
|
int const index,
|
|
|
|
xmlrpc_value ** const out_keyval,
|
|
|
|
xmlrpc_value ** const out_value);
|
2005-02-22 21:08:27 +03:00
|
|
|
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** Encoding XML
|
|
|
|
**=======================================================================*/
|
|
|
|
|
|
|
|
/* Serialize an XML value without any XML header. This is primarily used
|
|
|
|
** for testing purposes. */
|
|
|
|
void
|
|
|
|
xmlrpc_serialize_value(xmlrpc_env * env,
|
|
|
|
xmlrpc_mem_block * output,
|
|
|
|
xmlrpc_value * value);
|
|
|
|
|
|
|
|
/* Serialize a list of parameters without any XML header. This is
|
|
|
|
** primarily used for testing purposes. */
|
|
|
|
void
|
|
|
|
xmlrpc_serialize_params(xmlrpc_env * env,
|
|
|
|
xmlrpc_mem_block * output,
|
|
|
|
xmlrpc_value * param_array);
|
|
|
|
|
|
|
|
/* Serialize an XML-RPC call. */
|
|
|
|
void
|
|
|
|
xmlrpc_serialize_call (xmlrpc_env * const env,
|
|
|
|
xmlrpc_mem_block * const output,
|
|
|
|
const char * const method_name,
|
|
|
|
xmlrpc_value * const param_array);
|
|
|
|
|
|
|
|
/* Serialize an XML-RPC return value. */
|
|
|
|
extern void
|
|
|
|
xmlrpc_serialize_response(xmlrpc_env * env,
|
|
|
|
xmlrpc_mem_block * output,
|
|
|
|
xmlrpc_value * value);
|
|
|
|
|
|
|
|
/* Serialize an XML-RPC fault (as specified by 'fault'). */
|
|
|
|
extern void
|
|
|
|
xmlrpc_serialize_fault(xmlrpc_env * env,
|
|
|
|
xmlrpc_mem_block * output,
|
|
|
|
xmlrpc_env * fault);
|
|
|
|
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** Decoding XML
|
|
|
|
**=======================================================================*/
|
|
|
|
|
|
|
|
/* Parse an XML-RPC call. If an error occurs, set a fault and set
|
|
|
|
** the output variables to NULL.
|
|
|
|
** The caller is responsible for calling free(*out_method_name) and
|
|
|
|
** xmlrpc_DECREF(*out_param_array). */
|
|
|
|
void
|
|
|
|
xmlrpc_parse_call(xmlrpc_env * const envP,
|
|
|
|
const char * const xml_data,
|
|
|
|
size_t const xml_len,
|
|
|
|
const char ** const out_method_name,
|
|
|
|
xmlrpc_value ** const out_param_array);
|
|
|
|
|
|
|
|
/* Parse an XML-RPC response. If a fault occurs (or was received over the
|
|
|
|
** wire), return NULL and set up 'env'. The calling is responsible for
|
|
|
|
** calling xmlrpc_DECREF on the return value (if it isn't NULL). */
|
|
|
|
xmlrpc_value *
|
|
|
|
xmlrpc_parse_response(xmlrpc_env * env,
|
|
|
|
const char * xml_data,
|
|
|
|
size_t xml_len);
|
|
|
|
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** XML-RPC Base64 Utilities
|
|
|
|
**=========================================================================
|
|
|
|
** Here are some lightweight utilities which can be used to encode and
|
|
|
|
** decode Base64 data. These are exported mainly for testing purposes.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* This routine inserts newlines every 76 characters, as required by the
|
|
|
|
** Base64 specification. */
|
|
|
|
xmlrpc_mem_block *
|
|
|
|
xmlrpc_base64_encode(xmlrpc_env * env,
|
|
|
|
unsigned char * bin_data,
|
|
|
|
size_t bin_len);
|
|
|
|
|
|
|
|
/* This routine encodes everything in one line. This is needed for HTTP
|
|
|
|
** authentication and similar tasks. */
|
|
|
|
xmlrpc_mem_block *
|
|
|
|
xmlrpc_base64_encode_without_newlines(xmlrpc_env * env,
|
|
|
|
unsigned char * bin_data,
|
|
|
|
size_t bin_len);
|
|
|
|
|
|
|
|
/* This decodes Base64 data with or without newlines. */
|
|
|
|
extern xmlrpc_mem_block *
|
|
|
|
xmlrpc_base64_decode(xmlrpc_env * env,
|
|
|
|
char * ascii_data,
|
|
|
|
size_t ascii_len);
|
|
|
|
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** UTF-8 Encoding and Decoding
|
|
|
|
**=========================================================================
|
|
|
|
** We need a correct, reliable and secure UTF-8 decoder. This decoder
|
|
|
|
** raises a fault if it encounters invalid UTF-8.
|
|
|
|
**
|
|
|
|
** Note that ANSI C does not precisely define the representation used
|
|
|
|
** by wchar_t--it may be UCS-2, UTF-16, UCS-4, or something from outer
|
|
|
|
** space. If your platform does something especially bizarre, you may
|
|
|
|
** need to reimplement these routines.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_UNICODE_WCHAR
|
|
|
|
|
|
|
|
/* Ensure that a string contains valid, legally-encoded UTF-8 data.
|
|
|
|
** (Incorrectly-encoded UTF-8 strings are often used to bypass security
|
|
|
|
** checks.) */
|
|
|
|
void
|
|
|
|
xmlrpc_validate_utf8 (xmlrpc_env * const env,
|
|
|
|
const char * const utf8_data,
|
|
|
|
size_t const utf8_len);
|
|
|
|
|
|
|
|
/* Decode a UTF-8 string. */
|
|
|
|
xmlrpc_mem_block *
|
|
|
|
xmlrpc_utf8_to_wcs(xmlrpc_env * env,
|
|
|
|
char * utf8_data,
|
|
|
|
size_t utf8_len);
|
|
|
|
|
|
|
|
/* Encode a UTF-8 string. */
|
|
|
|
xmlrpc_mem_block *
|
|
|
|
xmlrpc_wcs_to_utf8(xmlrpc_env * env,
|
|
|
|
wchar_t * wcs_data,
|
|
|
|
size_t wcs_len);
|
|
|
|
|
|
|
|
#endif /* HAVE_UNICODE_WCHAR */
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** Authorization Cookie Handling
|
|
|
|
**=========================================================================
|
|
|
|
** Routines to get and set values for authorizing via authorization
|
|
|
|
** cookies. Both the client and server use HTTP_COOKIE_AUTH to store
|
|
|
|
** the representation of the authorization value, which is actually
|
|
|
|
** just a base64 hash of username:password. (This entire method is
|
|
|
|
** a cookie replacement of basic authentication.)
|
|
|
|
**/
|
|
|
|
|
|
|
|
extern void xmlrpc_authcookie_set(xmlrpc_env * env,
|
|
|
|
const char * username,
|
|
|
|
const char * password);
|
|
|
|
|
|
|
|
char *xmlrpc_authcookie(void);
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* In the days before xmlrpc_server.h existed, some of what's in it was
|
|
|
|
in here. For backward compatibility, we need to include it here, even
|
|
|
|
though it really isn't logical to do so.
|
|
|
|
*/
|
|
|
|
#include <xmlrpc_server.h>
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|