initial load of upstream version 1.06.32
[xmlrpc-c] / include / xmlrpc-c / util.h
1 /*=============================================================================
2                                  xmlrpc-c/util.h
3 ===============================================================================
4
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.
8
9   By Bryan Henderson, San Jose, CA 05.09.21.
10
11   Contributed to the public domain by its author.
12 =============================================================================*/
13
14 #ifndef XMLRPC_C_UTIL_H_INCLUDED
15 #define XMLRPC_C_UTIL_H_INCLUDED
16
17 #include <sys/types.h>
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22
23
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.
27 */
28 #ifdef __GNUC__
29 #define GNU_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b)))
30 #else
31 #define GNU_PRINTF_ATTR(a,b)
32 #endif
33
34
35 /*=========================================================================
36 **  C struct size computations
37 **=======================================================================*/
38
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).
43 */
44
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))
52
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
62 **  macro defined.
63 */
64
65 #ifndef NDEBUG
66
67 #define XMLRPC_ASSERT(cond) \
68     do \
69         if (!(cond)) \
70             xmlrpc_assertion_failed(__FILE__, __LINE__); \
71     while (0)
72
73 #else
74 #define XMLRPC_ASSERT(cond) while (0) {}
75 #endif
76
77 void
78 xmlrpc_assertion_failed(const char * const fileName,
79                         int          const lineNumber);
80
81 /* Validate a pointer. */
82 #define XMLRPC_ASSERT_PTR_OK(ptr) \
83     XMLRPC_ASSERT((ptr) != NULL)
84
85 /* We only call this if something truly drastic happens. */
86 #define XMLRPC_FATAL_ERROR(msg) xmlrpc_fatal_error(__FILE__, __LINE__, (msg))
87
88 extern void xmlrpc_fatal_error (char* file, int line, char* msg);
89
90
91 /*=========================================================================
92 **  xmlrpc_env
93 **=========================================================================
94 **  XML-RPC represents runtime errors as <fault> elements. These contain
95 **  <faultCode> and <faultString> elements.
96 **
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.
101 **
102 **  For example:
103 **
104 **    xmlrpc_env env;
105 **
106 **    xmlrpc_env_init(&env);
107 **
108 **    xmlrpc_do_something(&env);
109 **    if (env.fault_occurred)
110 **        report_error_appropriately();
111 **
112 **    xmlrpc_env_clean(&env);
113 */
114
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)
126
127 typedef struct _xmlrpc_env {
128     int    fault_occurred;
129     int    fault_code;
130     char * fault_string;
131 } xmlrpc_env;
132
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);
137
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. */
141 void 
142 xmlrpc_env_set_fault(xmlrpc_env * const env, 
143                      int          const faultCode, 
144                      const char * const faultDescription);
145
146 /* The same as the above, but using a printf-style format string. */
147 void 
148 xmlrpc_env_set_fault_formatted(xmlrpc_env * const envP, 
149                                int          const code,
150                                const char * const format, 
151                                ...) GNU_PRINTF_ATTR(3,4);
152
153 /* This one infers XMLRPC_INTERNAL_ERROR and has a shorter name.
154    So a call takes up less source code space.
155 */
156 void
157 xmlrpc_faultf(xmlrpc_env * const envP,
158               const char * const format,
159               ...) GNU_PRINTF_ATTR(2,3);
160
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)
166
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)
171
172 #define XMLRPC_FAIL1(env,code,str,arg1) \
173     do { \
174         xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1)); \
175         goto cleanup; \
176     } while (0)
177
178 #define XMLRPC_FAIL2(env,code,str,arg1,arg2) \
179     do { \
180         xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1),(arg2)); \
181         goto cleanup; \
182     } while (0)
183
184 #define XMLRPC_FAIL3(env,code,str,arg1,arg2,arg3) \
185     do { \
186         xmlrpc_env_set_fault_formatted((env),(code), \
187                                        (str),(arg1),(arg2),(arg3)); \
188         goto cleanup; \
189     } while (0)
190
191 #define XMLRPC_FAIL_IF_NULL(ptr,env,code,str) \
192     do { \
193         if ((ptr) == NULL) \
194             XMLRPC_FAIL((env),(code),(str)); \
195     } while (0)
196
197 #define XMLRPC_FAIL_IF_FAULT(env) \
198     do { if ((env)->fault_occurred) goto cleanup; } while (0)
199
200
201 /*=========================================================================
202 **  Resource Limits
203 **=========================================================================
204 **  To discourage denial-of-service attacks, we provide several adjustable
205 **  resource limits. These functions are *not* re-entrant.
206 */
207
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)
212
213 /* By default, deserialized data may be no more than 64 levels deep. */
214 #define XMLRPC_NESTING_LIMIT_DEFAULT  (64)
215
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)
219
220 /* Set a specific limit to the specified value. */
221 extern void xmlrpc_limit_set (int limit_id, size_t value);
222
223 /* Get the value of a specified limit. */
224 extern size_t xmlrpc_limit_get (int limit_id);
225
226
227 /*=========================================================================
228 **  xmlrpc_mem_block
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!
233 */
234
235 typedef struct _xmlrpc_mem_block {
236     size_t _size;
237     size_t _allocated;
238     void*  _block;
239 } xmlrpc_mem_block;
240
241 /* Allocate a new xmlrpc_mem_block. */
242 xmlrpc_mem_block* xmlrpc_mem_block_new (xmlrpc_env* env, size_t size);
243
244 /* Destroy an existing xmlrpc_mem_block, and everything it contains. */
245 void xmlrpc_mem_block_free (xmlrpc_mem_block* block);
246
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);
250
251 /* Deallocate the contents of the provided xmlrpc_mem_block, but not the
252 ** block itself. */
253 void xmlrpc_mem_block_clean (xmlrpc_mem_block* block);
254
255 /* Get the size and contents of the xmlrpc_mem_block. */
256 size_t 
257 xmlrpc_mem_block_size(const xmlrpc_mem_block * const block);
258
259 void * 
260 xmlrpc_mem_block_contents(const xmlrpc_mem_block * const block);
261
262 /* Resize an xmlrpc_mem_block, preserving as much of the contents as
263 ** possible. */
264 void xmlrpc_mem_block_resize
265     (xmlrpc_env* env, xmlrpc_mem_block* block, size_t size);
266
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);
270
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))
287
288 /* Here are some backward compatibility definitions.  These longer names
289    used to be the only ones and typed memory blocks were considered
290    special.
291 */
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)
308
309 #ifdef __cplusplus
310 }
311 #endif
312
313 #endif