1 /*=============================================================================
3 ===============================================================================
5 This is the interface to the libxmlrpc_util library, which contains
6 utility routines that have nothing to do with XML-RPC. The library
7 exists because other Xmlrpc-c libraries use the utilities.
9 By Bryan Henderson, San Jose, CA 05.09.21.
11 Contributed to the public domain by its author.
12 =============================================================================*/
14 #ifndef XMLRPC_C_UTIL_H_INCLUDED
15 #define XMLRPC_C_UTIL_H_INCLUDED
17 #include <sys/types.h>
24 /* GNU_PRINTF_ATTR lets the GNU compiler check printf-type
25 calls to be sure the arguments match the format string, thus preventing
26 runtime segmentation faults and incorrect messages.
29 #define GNU_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b)))
31 #define GNU_PRINTF_ATTR(a,b)
35 /*=========================================================================
36 ** C struct size computations
37 **=======================================================================*/
39 /* Use XMLRPC_STRUCT_MEMBER_SIZE() to determine how big a structure is
40 up to and including a specified member. E.g. if you have
41 struct mystruct {int red; int green; int blue};, then
42 XMLRPC_STRUCT_MEMBER_SIZE(mystruct, green) is (8).
45 #define _XMLRPC_STRUCT_MEMBER_OFFSET(TYPE, MBRNAME) \
46 ((unsigned long)(char*)&((TYPE *)0)->MBRNAME)
47 #define _XMLRPC_STRUCT_MEMBER_SIZE(TYPE, MBRNAME) \
48 sizeof(((TYPE *)0)->MBRNAME)
49 #define XMLRPC_STRUCTSIZE(TYPE, MBRNAME) \
50 (_XMLRPC_STRUCT_MEMBER_OFFSET(TYPE, MBRNAME) + \
51 _XMLRPC_STRUCT_MEMBER_SIZE(TYPE, MBRNAME))
53 /*=========================================================================
54 ** Assertions and Debugging
55 **=========================================================================
56 ** Note that an assertion is _not_ a directive to check a condition and
57 ** crash if it isn't true. It is an assertion that the condition _is_
58 ** true. This assertion helps people to read the code. The program
59 ** may also check the assertion as it runs, and if it conflicts with reality,
60 ** recognize that the program is incorrect and abort it. In practice,
61 ** it does this checking when the program was compiled without the NDEBUG
67 #define XMLRPC_ASSERT(cond) \
70 xmlrpc_assertion_failed(__FILE__, __LINE__); \
74 #define XMLRPC_ASSERT(cond) while (0) {}
78 xmlrpc_assertion_failed(const char * const fileName,
79 int const lineNumber);
81 /* Validate a pointer. */
82 #define XMLRPC_ASSERT_PTR_OK(ptr) \
83 XMLRPC_ASSERT((ptr) != NULL)
85 /* We only call this if something truly drastic happens. */
86 #define XMLRPC_FATAL_ERROR(msg) xmlrpc_fatal_error(__FILE__, __LINE__, (msg))
88 extern void xmlrpc_fatal_error (char* file, int line, char* msg);
91 /*=========================================================================
93 **=========================================================================
94 ** XML-RPC represents runtime errors as <fault> elements. These contain
95 ** <faultCode> and <faultString> elements.
97 ** Since we need as much thread-safety as possible, we borrow an idea from
98 ** CORBA--we store exception information in an "environment" object.
99 ** You'll pass this to many different functions, and it will get filled
100 ** out appropriately.
106 ** xmlrpc_env_init(&env);
108 ** xmlrpc_do_something(&env);
109 ** if (env.fault_occurred)
110 ** report_error_appropriately();
112 ** xmlrpc_env_clean(&env);
115 #define XMLRPC_INTERNAL_ERROR (-500)
116 #define XMLRPC_TYPE_ERROR (-501)
117 #define XMLRPC_INDEX_ERROR (-502)
118 #define XMLRPC_PARSE_ERROR (-503)
119 #define XMLRPC_NETWORK_ERROR (-504)
120 #define XMLRPC_TIMEOUT_ERROR (-505)
121 #define XMLRPC_NO_SUCH_METHOD_ERROR (-506)
122 #define XMLRPC_REQUEST_REFUSED_ERROR (-507)
123 #define XMLRPC_INTROSPECTION_DISABLED_ERROR (-508)
124 #define XMLRPC_LIMIT_EXCEEDED_ERROR (-509)
125 #define XMLRPC_INVALID_UTF8_ERROR (-510)
127 typedef struct _xmlrpc_env {
133 /* Initialize and destroy the contents of the provided xmlrpc_env object.
134 ** These functions will never fail. */
135 void xmlrpc_env_init (xmlrpc_env* env);
136 void xmlrpc_env_clean (xmlrpc_env* env);
138 /* Fill out an xmlrpc_fault with the specified values, and set the
139 ** fault_occurred flag. This function will make a private copy of 'string',
140 ** so you retain responsibility for your copy. */
142 xmlrpc_env_set_fault(xmlrpc_env * const env,
144 const char * const faultDescription);
146 /* The same as the above, but using a printf-style format string. */
148 xmlrpc_env_set_fault_formatted(xmlrpc_env * const envP,
150 const char * const format,
151 ...) GNU_PRINTF_ATTR(3,4);
153 /* This one infers XMLRPC_INTERNAL_ERROR and has a shorter name.
154 So a call takes up less source code space.
157 xmlrpc_faultf(xmlrpc_env * const envP,
158 const char * const format,
159 ...) GNU_PRINTF_ATTR(2,3);
161 /* A simple debugging assertion. */
162 #define XMLRPC_ASSERT_ENV_OK(envP) \
163 XMLRPC_ASSERT((envP) != NULL && \
164 (envP->fault_string == NULL) && \
165 !(envP)->fault_occurred)
167 /* This version must *not* interpret 'str' as a format string, to avoid
168 ** several evil attacks. */
169 #define XMLRPC_FAIL(env,code,str) \
170 do { xmlrpc_env_set_fault((env),(code),(str)); goto cleanup; } while (0)
172 #define XMLRPC_FAIL1(env,code,str,arg1) \
174 xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1)); \
178 #define XMLRPC_FAIL2(env,code,str,arg1,arg2) \
180 xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1),(arg2)); \
184 #define XMLRPC_FAIL3(env,code,str,arg1,arg2,arg3) \
186 xmlrpc_env_set_fault_formatted((env),(code), \
187 (str),(arg1),(arg2),(arg3)); \
191 #define XMLRPC_FAIL_IF_NULL(ptr,env,code,str) \
194 XMLRPC_FAIL((env),(code),(str)); \
197 #define XMLRPC_FAIL_IF_FAULT(env) \
198 do { if ((env)->fault_occurred) goto cleanup; } while (0)
201 /*=========================================================================
203 **=========================================================================
204 ** To discourage denial-of-service attacks, we provide several adjustable
205 ** resource limits. These functions are *not* re-entrant.
208 /* Limit IDs. There will be more of these as time goes on. */
209 #define XMLRPC_NESTING_LIMIT_ID (0)
210 #define XMLRPC_XML_SIZE_LIMIT_ID (1)
211 #define XMLRPC_LAST_LIMIT_ID (XMLRPC_XML_SIZE_LIMIT_ID)
213 /* By default, deserialized data may be no more than 64 levels deep. */
214 #define XMLRPC_NESTING_LIMIT_DEFAULT (64)
216 /* By default, XML data from the network may be no larger than 512K.
217 ** Some client and server modules may fail to enforce this properly. */
218 #define XMLRPC_XML_SIZE_LIMIT_DEFAULT (512*1024)
220 /* Set a specific limit to the specified value. */
221 extern void xmlrpc_limit_set (int limit_id, size_t value);
223 /* Get the value of a specified limit. */
224 extern size_t xmlrpc_limit_get (int limit_id);
227 /*=========================================================================
229 **=========================================================================
230 ** A resizable chunk of memory. This is mostly used internally, but it is
231 ** also used by the public API in a few places.
232 ** The struct fields are private!
235 typedef struct _xmlrpc_mem_block {
241 /* Allocate a new xmlrpc_mem_block. */
242 xmlrpc_mem_block* xmlrpc_mem_block_new (xmlrpc_env* env, size_t size);
244 /* Destroy an existing xmlrpc_mem_block, and everything it contains. */
245 void xmlrpc_mem_block_free (xmlrpc_mem_block* block);
247 /* Initialize the contents of the provided xmlrpc_mem_block. */
248 void xmlrpc_mem_block_init
249 (xmlrpc_env* env, xmlrpc_mem_block* block, size_t size);
251 /* Deallocate the contents of the provided xmlrpc_mem_block, but not the
253 void xmlrpc_mem_block_clean (xmlrpc_mem_block* block);
255 /* Get the size and contents of the xmlrpc_mem_block. */
257 xmlrpc_mem_block_size(const xmlrpc_mem_block * const block);
260 xmlrpc_mem_block_contents(const xmlrpc_mem_block * const block);
262 /* Resize an xmlrpc_mem_block, preserving as much of the contents as
264 void xmlrpc_mem_block_resize
265 (xmlrpc_env* env, xmlrpc_mem_block* block, size_t size);
267 /* Append data to an existing xmlrpc_mem_block. */
268 void xmlrpc_mem_block_append
269 (xmlrpc_env* env, xmlrpc_mem_block* block, const void *data, size_t len);
271 #define XMLRPC_MEMBLOCK_NEW(type,env,size) \
272 xmlrpc_mem_block_new((env), sizeof(type) * (size))
273 #define XMLRPC_MEMBLOCK_FREE(type,block) \
274 xmlrpc_mem_block_free(block)
275 #define XMLRPC_MEMBLOCK_INIT(type,env,block,size) \
276 xmlrpc_mem_block_init((env), (block), sizeof(type) * (size))
277 #define XMLRPC_MEMBLOCK_CLEAN(type,block) \
278 xmlrpc_mem_block_clean(block)
279 #define XMLRPC_MEMBLOCK_SIZE(type,block) \
280 (xmlrpc_mem_block_size(block) / sizeof(type))
281 #define XMLRPC_MEMBLOCK_CONTENTS(type,block) \
282 ((type*) xmlrpc_mem_block_contents(block))
283 #define XMLRPC_MEMBLOCK_RESIZE(type,env,block,size) \
284 xmlrpc_mem_block_resize(env, block, sizeof(type) * (size))
285 #define XMLRPC_MEMBLOCK_APPEND(type,env,block,data,size) \
286 xmlrpc_mem_block_append(env, block, data, sizeof(type) * (size))
288 /* Here are some backward compatibility definitions. These longer names
289 used to be the only ones and typed memory blocks were considered
292 #define XMLRPC_TYPED_MEM_BLOCK_NEW(type,env,size) \
293 XMLRPC_MEMBLOCK_NEW(type,env,size)
294 #define XMLRPC_TYPED_MEM_BLOCK_FREE(type,block) \
295 XMLRPC_MEMBLOCK_FREE(type,block)
296 #define XMLRPC_TYPED_MEM_BLOCK_INIT(type,env,block,size) \
297 XMLRPC_MEMBLOCK_INIT(type,env,block,size)
298 #define XMLRPC_TYPED_MEM_BLOCK_CLEAN(type,block) \
299 XMLRPC_MEMBLOCK_CLEAN(type,block)
300 #define XMLRPC_TYPED_MEM_BLOCK_SIZE(type,block) \
301 XMLRPC_MEMBLOCK_SIZE(type,block)
302 #define XMLRPC_TYPED_MEM_BLOCK_CONTENTS(type,block) \
303 XMLRPC_MEMBLOCK_CONTENTS(type,block)
304 #define XMLRPC_TYPED_MEM_BLOCK_RESIZE(type,env,block,size) \
305 XMLRPC_MEMBLOCK_RESIZE(type,env,block,size)
306 #define XMLRPC_TYPED_MEM_BLOCK_APPEND(type,env,block,data,size) \
307 XMLRPC_MEMBLOCK_APPEND(type,env,block,data,size)