File: | src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c |
Location: | line 625, column 10 |
Description: | Access to field 'fault_occurred' results in a dereference of a null pointer (loaded from variable 'envP') |
1 | /* Copyright information is at end of file */ | |||
2 | ||||
3 | /* Implementation note: | |||
4 | ||||
5 | The printf format specifiers we use appear to be entirely standard, | |||
6 | except for the "long long" one, which is %I64 on Windows and %lld | |||
7 | everywhere else. We could use the C99 standard macro PRId64 for that, | |||
8 | but on at least one 64-bit-long GNU compiler, PRId64 is "ld", which is | |||
9 | considered to be incompatible with long long. So we have XMLRPC_PRId64. | |||
10 | */ | |||
11 | ||||
12 | #include "xmlrpc_config.h" | |||
13 | ||||
14 | #include <assert.h> | |||
15 | #include <stddef.h> | |||
16 | #include <stdarg.h> | |||
17 | #include <stdlib.h> | |||
18 | #include <stdio.h> | |||
19 | #include <string.h> | |||
20 | #include <float.h> | |||
21 | ||||
22 | #include "int.h" | |||
23 | #include "xmlrpc-c/base.h" | |||
24 | #include "xmlrpc-c/base_int.h" | |||
25 | #include "xmlrpc-c/string_int.h" | |||
26 | #include "double.h" | |||
27 | ||||
28 | #define CRLF"\015\012" "\015\012" | |||
29 | #define XML_PROLOGUE"<?xml version=\"1.0\" encoding=\"UTF-8\"?>""\015\012" "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"CRLF"\015\012" | |||
30 | #define APACHE_URL"http://ws.apache.org/xmlrpc/namespaces/extensions" "http://ws.apache.org/xmlrpc/namespaces/extensions" | |||
31 | #define XMLNS_APACHE"xmlns:ex=\"" "http://ws.apache.org/xmlrpc/namespaces/extensions" "\"" "xmlns:ex=\"" APACHE_URL"http://ws.apache.org/xmlrpc/namespaces/extensions" "\"" | |||
32 | ||||
33 | ||||
34 | static void | |||
35 | addString(xmlrpc_env * const envP, | |||
36 | xmlrpc_mem_block * const outputP, | |||
37 | const char * const string) { | |||
38 | ||||
39 | XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, string, strlen(string))xmlrpc_mem_block_append(envP, outputP, string, sizeof(char) * (strlen(string))); | |||
40 | } | |||
41 | ||||
42 | ||||
43 | ||||
44 | static void | |||
45 | formatOut(xmlrpc_env * const envP, | |||
46 | xmlrpc_mem_block * const outputP, | |||
47 | const char * const formatString, | |||
48 | ...) { | |||
49 | /*---------------------------------------------------------------------------- | |||
50 | A lightweight print routine for use with various serialization | |||
51 | functions. | |||
52 | ||||
53 | Use this routine only for printing small objects -- it uses a | |||
54 | fixed-size internal buffer and returns an error on overflow. In | |||
55 | particular, do NOT use this routine to print XML-RPC string values! | |||
56 | -----------------------------------------------------------------------------*/ | |||
57 | va_list args; | |||
58 | char buffer[128]; | |||
59 | int rc; | |||
60 | ||||
61 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c", 61); while (0); | |||
62 | ||||
63 | va_start(args, formatString)__builtin_va_start(args, formatString); | |||
64 | ||||
65 | rc = XMLRPC_VSNPRINTFvsnprintf(buffer, sizeof(buffer), formatString, args); | |||
66 | ||||
67 | /* Old vsnprintf() (and Windows) fails with return value -1 if the full | |||
68 | string doesn't fit in the buffer. New vsnprintf() puts whatever will | |||
69 | fit in the buffer, and returns the length of the full string | |||
70 | regardless. For us, this truncation is a failure. | |||
71 | */ | |||
72 | ||||
73 | if (rc < 0) | |||
74 | xmlrpc_faultf(envP, "formatOut() overflowed internal buffer"); | |||
75 | else { | |||
76 | unsigned int const formattedLen = rc; | |||
77 | ||||
78 | if (formattedLen + 1 >= (sizeof(buffer))) | |||
79 | xmlrpc_faultf(envP, "formatOut() overflowed internal buffer"); | |||
80 | else | |||
81 | XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, buffer, formattedLen)xmlrpc_mem_block_append(envP, outputP, buffer, sizeof(char) * (formattedLen)); | |||
82 | } | |||
83 | va_end(args)__builtin_va_end(args); | |||
84 | } | |||
85 | ||||
86 | ||||
87 | ||||
88 | static void | |||
89 | assertValidUtf8(const char * const str ATTR_UNUSED__attribute__((__unused__)), | |||
90 | size_t const len ATTR_UNUSED__attribute__((__unused__))) { | |||
91 | /*---------------------------------------------------------------------------- | |||
92 | Assert that the string 'str' of length 'len' is valid UTF-8. | |||
93 | -----------------------------------------------------------------------------*/ | |||
94 | #if !defined NDEBUG | |||
95 | /* Check the assertion; if it's false, issue a message to | |||
96 | Standard Error, but otherwise ignore it. | |||
97 | */ | |||
98 | xmlrpc_env env; | |||
99 | ||||
100 | xmlrpc_env_init(&env); | |||
101 | xmlrpc_validate_utf8(&env, str, len); | |||
102 | if (env.fault_occurred) | |||
103 | fprintf(stderrstderr, "*** xmlrpc-c WARNING ***: %s (%s)\n", | |||
104 | "Xmlrpc-c sending corrupted UTF-8 data to network", | |||
105 | env.fault_string); | |||
106 | xmlrpc_env_clean(&env); | |||
107 | #endif | |||
108 | } | |||
109 | ||||
110 | ||||
111 | ||||
112 | static size_t | |||
113 | escapedSize(const char * const chars, | |||
114 | size_t const len) { | |||
115 | ||||
116 | size_t size; | |||
117 | size_t i; | |||
118 | ||||
119 | size = 0; | |||
120 | for (i = 0; i < len; ++i) { | |||
121 | if (chars[i] == '<') | |||
122 | size += 4; /* < */ | |||
123 | else if (chars[i] == '>') | |||
124 | size += 4; /* > */ | |||
125 | else if (chars[i] == '&') | |||
126 | size += 5; /* & */ | |||
127 | else if (chars[i] == '\r') | |||
128 | size += 6; /* 
 */ | |||
129 | else | |||
130 | size += 1; | |||
131 | } | |||
132 | return size; | |||
133 | } | |||
134 | ||||
135 | ||||
136 | ||||
137 | static void | |||
138 | escapeForXml(xmlrpc_env * const envP, | |||
139 | const char * const chars, | |||
140 | size_t const len, | |||
141 | xmlrpc_mem_block ** const outputPP) { | |||
142 | /*---------------------------------------------------------------------------- | |||
143 | Escape & and < in a UTF-8 string so as to make it suitable for the | |||
144 | content of an XML element. I.e. turn them into entity references | |||
145 | & and <. | |||
146 | ||||
147 | Also change > to >, even though not required for XML, for | |||
148 | symmetry. | |||
149 | ||||
150 | < etc. are known in XML as "entity references." | |||
151 | ||||
152 | Also Escape CR as 
 . While raw CR _is_ allowed in the content | |||
153 | of an XML element, it has a special meaning -- it means line ending. | |||
154 | Our input uses LF for for line endings. Since it also means line ending | |||
155 | in XML, we just pass it through to our output like it were a regular | |||
156 | character. | |||
157 | ||||
158 | 
 is known in XML as a "character reference." | |||
159 | ||||
160 | We assume chars[] is is ASCII. That isn't right -- we should | |||
161 | handle all valid UTF-8. Someday, we must do something more complex | |||
162 | and copy over multibyte characters verbatim. (The code here could | |||
163 | erroneously find that e.g. the 2nd byte of a UTF-8 character is a | |||
164 | CR). | |||
165 | -----------------------------------------------------------------------------*/ | |||
166 | xmlrpc_mem_block * outputP; | |||
167 | size_t outputSize; | |||
168 | ||||
169 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c", 169); while (0); | |||
170 | XMLRPC_ASSERT(chars != NULL)do if (!(chars != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c" , 170); while (0); | |||
171 | ||||
172 | assertValidUtf8(chars, len); | |||
173 | ||||
174 | /* Note that in UTF-8, any byte that has high bit of zero is a | |||
175 | character all by itself (every byte of a multi-byte UTF-8 character | |||
176 | has the high bit set). Also, the Unicode code points < 128 are | |||
177 | identical to the ASCII ones. | |||
178 | */ | |||
179 | ||||
180 | outputSize = escapedSize(chars, len); | |||
181 | ||||
182 | outputP = XMLRPC_MEMBLOCK_NEW(char, envP, outputSize)xmlrpc_mem_block_new((envP), sizeof(char) * (outputSize)); | |||
183 | if (!envP->fault_occurred) { | |||
184 | char * p; | |||
185 | size_t i; | |||
186 | p = XMLRPC_MEMBLOCK_CONTENTS(char, outputP)((char*) xmlrpc_mem_block_contents(outputP)); /* Start at beginning */ | |||
187 | ||||
188 | for (i = 0; i < len; i++) { | |||
189 | if (chars[i] == '<') { | |||
190 | memcpy(p, "<", 4); | |||
191 | p += 4; | |||
192 | } else if (chars[i] == '>') { | |||
193 | memcpy(p, ">", 4); | |||
194 | p += 4; | |||
195 | } else if (chars[i] == '&') { | |||
196 | memcpy(p, "&", 5); | |||
197 | p += 5; | |||
198 | } else if (chars[i] == '\r') { | |||
199 | memcpy(p, "
", 6); | |||
200 | p += 6; | |||
201 | } else { | |||
202 | /* Either a plain character or a LF line delimiter */ | |||
203 | *p = chars[i]; | |||
204 | p += 1; | |||
205 | } | |||
206 | } | |||
207 | *outputPP = outputP; | |||
208 | assert(p == XMLRPC_MEMBLOCK_CONTENTS(char, outputP) + outputSize)((p == ((char*) xmlrpc_mem_block_contents(outputP)) + outputSize ) ? (void) (0) : __assert_fail ("p == ((char*) xmlrpc_mem_block_contents(outputP)) + outputSize" , "../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c", 208, __PRETTY_FUNCTION__ )); | |||
209 | ||||
210 | if (envP->fault_occurred) | |||
211 | XMLRPC_MEMBLOCK_FREE(char, outputP)xmlrpc_mem_block_free(outputP); | |||
212 | } | |||
213 | } | |||
214 | ||||
215 | ||||
216 | ||||
217 | static void | |||
218 | serializeUtf8MemBlock(xmlrpc_env * const envP, | |||
219 | xmlrpc_mem_block * const outputP, | |||
220 | xmlrpc_mem_block * const inputP) { | |||
221 | /*---------------------------------------------------------------------------- | |||
222 | Append the characters in *inputP to the XML stream in *outputP. | |||
223 | ||||
224 | *inputP contains Unicode characters in UTF-8. | |||
225 | ||||
226 | We assume *inputP ends with a NUL character that marks end of | |||
227 | string, and we ignore that. (There might also be NUL characters | |||
228 | inside the string, though). | |||
229 | -----------------------------------------------------------------------------*/ | |||
230 | xmlrpc_mem_block * escapedP; | |||
231 | ||||
232 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c", 232); while (0); | |||
233 | XMLRPC_ASSERT(outputP != NULL)do if (!(outputP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c" , 233); while (0); | |||
234 | XMLRPC_ASSERT(inputP != NULL)do if (!(inputP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c" , 234); while (0); | |||
235 | ||||
236 | escapeForXml(envP, | |||
237 | XMLRPC_MEMBLOCK_CONTENTS(const char, inputP)((const char*) xmlrpc_mem_block_contents(inputP)), | |||
238 | XMLRPC_MEMBLOCK_SIZE(const char, inputP)(xmlrpc_mem_block_size(inputP) / sizeof(const char)) - 1, | |||
239 | /* -1 is for the terminating NUL */ | |||
240 | &escapedP); | |||
241 | if (!envP->fault_occurred) { | |||
242 | const char * const contents = | |||
243 | XMLRPC_MEMBLOCK_CONTENTS(const char, escapedP)((const char*) xmlrpc_mem_block_contents(escapedP)); | |||
244 | size_t const size = XMLRPC_MEMBLOCK_SIZE(char, escapedP)(xmlrpc_mem_block_size(escapedP) / sizeof(char)); | |||
245 | ||||
246 | XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, contents, size)xmlrpc_mem_block_append(envP, outputP, contents, sizeof(char) * (size)); | |||
247 | ||||
248 | XMLRPC_MEMBLOCK_FREE(const char, escapedP)xmlrpc_mem_block_free(escapedP); | |||
249 | } | |||
250 | } | |||
251 | ||||
252 | ||||
253 | ||||
254 | static void | |||
255 | xmlrpc_serialize_base64_data(xmlrpc_env * const envP, | |||
256 | xmlrpc_mem_block * const output, | |||
257 | unsigned char * const data, | |||
258 | size_t const len) { | |||
259 | /*---------------------------------------------------------------------------- | |||
260 | Encode the 'len' bytes at 'data' in base64 ASCII and append the result to | |||
261 | 'output'. | |||
262 | -----------------------------------------------------------------------------*/ | |||
263 | xmlrpc_mem_block * encoded; | |||
264 | ||||
265 | encoded = xmlrpc_base64_encode(envP, data, len); | |||
266 | if (!envP->fault_occurred) { | |||
267 | unsigned char * const contents = | |||
268 | XMLRPC_MEMBLOCK_CONTENTS(unsigned char, encoded)((unsigned char*) xmlrpc_mem_block_contents(encoded)); | |||
269 | size_t const size = | |||
270 | XMLRPC_MEMBLOCK_SIZE(unsigned char, encoded)(xmlrpc_mem_block_size(encoded) / sizeof(unsigned char)); | |||
271 | ||||
272 | XMLRPC_MEMBLOCK_APPEND(char, envP, output, contents, size)xmlrpc_mem_block_append(envP, output, contents, sizeof(char) * (size)); | |||
273 | ||||
274 | XMLRPC_MEMBLOCK_FREE(char, encoded)xmlrpc_mem_block_free(encoded); | |||
275 | } | |||
276 | } | |||
277 | ||||
278 | ||||
279 | ||||
280 | static void | |||
281 | serializeDatetime(xmlrpc_env * const envP, | |||
282 | xmlrpc_mem_block * const outputP, | |||
283 | xmlrpc_value * const valueP) { | |||
284 | /*---------------------------------------------------------------------------- | |||
285 | Add to *outputP the content of a <value> element to represent | |||
286 | the datetime value *valueP. I.e. | |||
287 | "<dateTime.iso8601> ... </dateTime.iso8601>". | |||
288 | -----------------------------------------------------------------------------*/ | |||
289 | ||||
290 | addString(envP, outputP, "<dateTime.iso8601>"); | |||
291 | if (!envP->fault_occurred) { | |||
292 | char dtString[64]; | |||
293 | ||||
294 | snprintf(dtString, sizeof(dtString), | |||
295 | "%u%02u%02uT%02u:%02u:%02u", | |||
296 | valueP->_value.dt.Y, | |||
297 | valueP->_value.dt.M, | |||
298 | valueP->_value.dt.D, | |||
299 | valueP->_value.dt.h, | |||
300 | valueP->_value.dt.m, | |||
301 | valueP->_value.dt.s); | |||
302 | ||||
303 | if (valueP->_value.dt.u != 0) { | |||
304 | char usecString[64]; | |||
305 | assert(valueP->_value.dt.u < 1000000)((valueP->_value.dt.u < 1000000) ? (void) (0) : __assert_fail ("valueP->_value.dt.u < 1000000", "../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c" , 305, __PRETTY_FUNCTION__)); | |||
306 | snprintf(usecString, sizeof(usecString), ".%06u", | |||
307 | valueP->_value.dt.u); | |||
308 | STRSCAT(dtString, usecString)(__builtin_strncat ((dtString), (usecString), sizeof(dtString )-strlen(dtString)), *((dtString)+sizeof(dtString)-1) = '\0'); | |||
309 | } | |||
310 | addString(envP, outputP, dtString); | |||
311 | ||||
312 | if (!envP->fault_occurred) { | |||
313 | addString(envP, outputP, "</dateTime.iso8601>"); | |||
314 | } | |||
315 | } | |||
316 | } | |||
317 | ||||
318 | ||||
319 | ||||
320 | static void | |||
321 | serializeStructMember(xmlrpc_env * const envP, | |||
322 | xmlrpc_mem_block * const outputP, | |||
323 | xmlrpc_value * const memberKeyP, | |||
324 | xmlrpc_value * const memberValueP, | |||
325 | xmlrpc_dialect const dialect) { | |||
326 | ||||
327 | addString(envP, outputP, "<member><name>"); | |||
328 | ||||
329 | if (!envP->fault_occurred) { | |||
330 | serializeUtf8MemBlock(envP, outputP, &memberKeyP->_block); | |||
331 | ||||
332 | if (!envP->fault_occurred) { | |||
333 | addString(envP, outputP, "</name>"CRLF"\015\012"); | |||
334 | ||||
335 | if (!envP->fault_occurred) { | |||
336 | xmlrpc_serialize_value2(envP, outputP, memberValueP, dialect); | |||
337 | ||||
338 | if (!envP->fault_occurred) { | |||
339 | addString(envP, outputP, "</member>"CRLF"\015\012"); | |||
340 | } | |||
341 | } | |||
342 | } | |||
343 | } | |||
344 | } | |||
345 | ||||
346 | ||||
347 | ||||
348 | static void | |||
349 | serializeStruct(xmlrpc_env * const envP, | |||
350 | xmlrpc_mem_block * const outputP, | |||
351 | xmlrpc_value * const structP, | |||
352 | xmlrpc_dialect const dialect) { | |||
353 | /*---------------------------------------------------------------------------- | |||
354 | Add to *outputP the content of a <value> element to represent | |||
355 | the structure value *valueP. I.e. "<struct> ... </struct>". | |||
356 | -----------------------------------------------------------------------------*/ | |||
357 | addString(envP, outputP, "<struct>"CRLF"\015\012"); | |||
358 | if (!envP->fault_occurred) { | |||
359 | unsigned int const size = xmlrpc_struct_size(envP, structP); | |||
360 | if (!envP->fault_occurred) { | |||
361 | unsigned int i; | |||
362 | for (i = 0; i < size && !envP->fault_occurred; ++i) { | |||
363 | xmlrpc_value * memberKeyP; | |||
364 | xmlrpc_value * memberValueP; | |||
365 | ||||
366 | xmlrpc_struct_get_key_and_value(envP, structP, i, | |||
367 | &memberKeyP, &memberValueP); | |||
368 | if (!envP->fault_occurred) { | |||
369 | serializeStructMember(envP, outputP, | |||
370 | memberKeyP, memberValueP, dialect); | |||
371 | } | |||
372 | } | |||
373 | addString(envP, outputP, "</struct>"); | |||
374 | } | |||
375 | } | |||
376 | } | |||
377 | ||||
378 | ||||
379 | ||||
380 | static void | |||
381 | serializeArray(xmlrpc_env * const envP, | |||
382 | xmlrpc_mem_block * const outputP, | |||
383 | xmlrpc_value * const valueP, | |||
384 | xmlrpc_dialect const dialect) { | |||
385 | /*---------------------------------------------------------------------------- | |||
386 | Add to *outputP the content of a <value> element to represent | |||
387 | the array value *valueP. I.e. "<array> ... </array>". | |||
388 | -----------------------------------------------------------------------------*/ | |||
389 | int const size = xmlrpc_array_size(envP, valueP); | |||
390 | ||||
391 | if (!envP->fault_occurred) { | |||
392 | addString(envP, outputP, "<array><data>"CRLF"\015\012"); | |||
393 | if (!envP->fault_occurred) { | |||
394 | int i; | |||
395 | /* Serialize each item. */ | |||
396 | for (i = 0; i < size && !envP->fault_occurred; ++i) { | |||
397 | xmlrpc_value * const itemP = | |||
398 | xmlrpc_array_get_item(envP, valueP, i); | |||
399 | if (!envP->fault_occurred) { | |||
400 | xmlrpc_serialize_value2(envP, outputP, itemP, dialect); | |||
401 | if (!envP->fault_occurred) | |||
402 | addString(envP, outputP, CRLF"\015\012"); | |||
403 | } | |||
404 | } | |||
405 | } | |||
406 | } | |||
407 | if (!envP->fault_occurred) | |||
408 | addString(envP, outputP, "</data></array>"); | |||
409 | } | |||
410 | ||||
411 | ||||
412 | ||||
413 | static void | |||
414 | formatValueContent(xmlrpc_env * const envP, | |||
415 | xmlrpc_mem_block * const outputP, | |||
416 | xmlrpc_value * const valueP, | |||
417 | xmlrpc_dialect const dialect) { | |||
418 | /*---------------------------------------------------------------------------- | |||
419 | Add to *outputP the content of a <value> element to represent | |||
420 | value *valueP. E.g. "<int>42</int>" | |||
421 | -----------------------------------------------------------------------------*/ | |||
422 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c", 422); while (0); | |||
423 | ||||
424 | switch (valueP->_type) { | |||
425 | case XMLRPC_TYPE_INT: | |||
426 | formatOut(envP, outputP, "<i4>%d</i4>", valueP->_value.i); | |||
427 | break; | |||
428 | ||||
429 | case XMLRPC_TYPE_I8: { | |||
430 | const char * const elemName = | |||
431 | dialect == xmlrpc_dialect_apache ? "ex:i8" : "i8"; | |||
432 | formatOut(envP, outputP, "<%s>%" PRId64"l" "d" "</%s>", | |||
433 | elemName, valueP->_value.i8, elemName); | |||
434 | } break; | |||
435 | ||||
436 | case XMLRPC_TYPE_BOOL: | |||
437 | formatOut(envP, outputP, "<boolean>%s</boolean>", | |||
438 | valueP->_value.b ? "1" : "0"); | |||
439 | break; | |||
440 | ||||
441 | case XMLRPC_TYPE_DOUBLE: { | |||
442 | const char * serializedValue; | |||
443 | xmlrpc_formatFloat(envP, valueP->_value.d, &serializedValue); | |||
444 | if (!envP->fault_occurred) { | |||
445 | addString(envP, outputP, "<double>"); | |||
446 | if (!envP->fault_occurred) { | |||
447 | addString(envP, outputP, serializedValue); | |||
448 | if (!envP->fault_occurred) | |||
449 | addString(envP, outputP, "</double>"); | |||
450 | } | |||
451 | xmlrpc_strfree(serializedValue); | |||
452 | } | |||
453 | } break; | |||
454 | ||||
455 | case XMLRPC_TYPE_DATETIME: | |||
456 | serializeDatetime(envP, outputP, valueP); | |||
457 | break; | |||
458 | ||||
459 | case XMLRPC_TYPE_STRING: | |||
460 | addString(envP, outputP, "<string>"); | |||
461 | if (!envP->fault_occurred) { | |||
462 | serializeUtf8MemBlock(envP, outputP, &valueP->_block); | |||
463 | if (!envP->fault_occurred) | |||
464 | addString(envP, outputP, "</string>"); | |||
465 | } | |||
466 | break; | |||
467 | ||||
468 | case XMLRPC_TYPE_BASE64: { | |||
469 | unsigned char * const contents = | |||
470 | XMLRPC_MEMBLOCK_CONTENTS(unsigned char, &valueP->_block)((unsigned char*) xmlrpc_mem_block_contents(&valueP->_block )); | |||
471 | size_t const size = | |||
472 | XMLRPC_MEMBLOCK_SIZE(unsigned char, &valueP->_block)(xmlrpc_mem_block_size(&valueP->_block) / sizeof(unsigned char)); | |||
473 | addString(envP, outputP, "<base64>"CRLF"\015\012"); | |||
474 | if (!envP->fault_occurred) { | |||
475 | xmlrpc_serialize_base64_data(envP, outputP, contents, size); | |||
476 | if (!envP->fault_occurred) | |||
477 | addString(envP, outputP, "</base64>"); | |||
478 | } | |||
479 | } break; | |||
480 | ||||
481 | case XMLRPC_TYPE_ARRAY: | |||
482 | serializeArray(envP, outputP, valueP, dialect); | |||
483 | break; | |||
484 | ||||
485 | case XMLRPC_TYPE_STRUCT: | |||
486 | serializeStruct(envP, outputP, valueP, dialect); | |||
487 | break; | |||
488 | ||||
489 | case XMLRPC_TYPE_C_PTR: | |||
490 | xmlrpc_faultf(envP, "Tried to serialize a C pointer value."); | |||
491 | break; | |||
492 | ||||
493 | case XMLRPC_TYPE_NIL: { | |||
494 | const char * const elemName = | |||
495 | dialect == xmlrpc_dialect_apache ? "ex:nil" : "nil"; | |||
496 | formatOut(envP, outputP, "<%s/>", elemName); | |||
497 | } break; | |||
498 | ||||
499 | case XMLRPC_TYPE_DEAD: | |||
500 | xmlrpc_faultf(envP, "Tried to serialize a dead value."); | |||
501 | break; | |||
502 | ||||
503 | default: | |||
504 | xmlrpc_faultf(envP, "Invalid xmlrpc_value type: %d", valueP->_type); | |||
505 | } | |||
506 | } | |||
507 | ||||
508 | ||||
509 | ||||
510 | void | |||
511 | xmlrpc_serialize_value2(xmlrpc_env * const envP, | |||
512 | xmlrpc_mem_block * const outputP, | |||
513 | xmlrpc_value * const valueP, | |||
514 | xmlrpc_dialect const dialect) { | |||
515 | /*---------------------------------------------------------------------------- | |||
516 | Generate the XML to represent XML-RPC value 'valueP' in XML-RPC. | |||
517 | ||||
518 | Add it to *outputP. | |||
519 | -----------------------------------------------------------------------------*/ | |||
520 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c", 520); while (0); | |||
521 | XMLRPC_ASSERT(outputP != NULL)do if (!(outputP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c" , 521); while (0); | |||
522 | XMLRPC_ASSERT_VALUE_OK(valueP)do if (!((valueP) != ((void*)0) && (valueP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c" , 522); while (0); | |||
523 | ||||
524 | addString(envP, outputP, "<value>"); | |||
525 | ||||
526 | if (!envP->fault_occurred) { | |||
527 | formatValueContent(envP, outputP, valueP, dialect); | |||
528 | ||||
529 | if (!envP->fault_occurred) | |||
530 | addString(envP, outputP, "</value>"); | |||
531 | } | |||
532 | } | |||
533 | ||||
534 | ||||
535 | ||||
536 | void | |||
537 | xmlrpc_serialize_value(xmlrpc_env * const envP, | |||
538 | xmlrpc_mem_block * const outputP, | |||
539 | xmlrpc_value * const valueP) { | |||
540 | ||||
541 | xmlrpc_serialize_value2(envP, outputP, valueP, xmlrpc_dialect_i8); | |||
542 | } | |||
543 | ||||
544 | ||||
545 | ||||
546 | void | |||
547 | xmlrpc_serialize_params2(xmlrpc_env * const envP, | |||
548 | xmlrpc_mem_block * const outputP, | |||
549 | xmlrpc_value * const paramArrayP, | |||
550 | xmlrpc_dialect const dialect) { | |||
551 | /*---------------------------------------------------------------------------- | |||
552 | Serialize the parameter list of an XML-RPC call. | |||
553 | -----------------------------------------------------------------------------*/ | |||
554 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c", 554); while (0); | |||
555 | XMLRPC_ASSERT(outputP != NULL)do if (!(outputP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c" , 555); while (0); | |||
556 | XMLRPC_ASSERT_VALUE_OK(paramArrayP)do if (!((paramArrayP) != ((void*)0) && (paramArrayP) ->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c" , 556); while (0); | |||
557 | ||||
558 | addString(envP, outputP, "<params>"CRLF"\015\012"); | |||
559 | if (!envP->fault_occurred) { | |||
560 | /* Serialize each parameter. */ | |||
561 | int const paramCount = xmlrpc_array_size(envP, paramArrayP); | |||
562 | if (!envP->fault_occurred) { | |||
563 | int paramSeq; | |||
564 | for (paramSeq = 0; | |||
565 | paramSeq < paramCount && !envP->fault_occurred; | |||
566 | ++paramSeq) { | |||
567 | ||||
568 | addString(envP, outputP, "<param>"); | |||
569 | if (!envP->fault_occurred) { | |||
570 | xmlrpc_value * const itemP = | |||
571 | xmlrpc_array_get_item(envP, paramArrayP, paramSeq); | |||
572 | if (!envP->fault_occurred) { | |||
573 | xmlrpc_serialize_value2(envP, outputP, itemP, dialect); | |||
574 | if (!envP->fault_occurred) | |||
575 | addString(envP, outputP, "</param>"CRLF"\015\012"); | |||
576 | } | |||
577 | } | |||
578 | } | |||
579 | } | |||
580 | } | |||
581 | ||||
582 | if (!envP->fault_occurred) | |||
583 | addString(envP, outputP, "</params>"CRLF"\015\012"); | |||
584 | } | |||
585 | ||||
586 | ||||
587 | ||||
588 | void | |||
589 | xmlrpc_serialize_params(xmlrpc_env * const envP, | |||
590 | xmlrpc_mem_block * const outputP, | |||
591 | xmlrpc_value * const paramArrayP) { | |||
592 | /*---------------------------------------------------------------------------- | |||
593 | Serialize the parameter list of an XML-RPC call in the original | |||
594 | "i8" dialect. | |||
595 | -----------------------------------------------------------------------------*/ | |||
596 | xmlrpc_serialize_params2(envP, outputP, paramArrayP, xmlrpc_dialect_i8); | |||
597 | } | |||
598 | ||||
599 | ||||
600 | ||||
601 | /*========================================================================= | |||
602 | ** xmlrpc_serialize_call | |||
603 | **========================================================================= | |||
604 | ** Serialize an XML-RPC call. | |||
605 | */ | |||
606 | ||||
607 | void | |||
608 | xmlrpc_serialize_call2(xmlrpc_env * const envP, | |||
609 | xmlrpc_mem_block * const outputP, | |||
610 | const char * const methodName, | |||
611 | xmlrpc_value * const paramArrayP, | |||
612 | xmlrpc_dialect const dialect) { | |||
613 | /*---------------------------------------------------------------------------- | |||
614 | Serialize an XML-RPC call of method named 'methodName' with parameter | |||
615 | list *paramArrayP. Use XML-RPC dialect 'dialect'. | |||
616 | ||||
617 | Append the call XML ot *outputP. | |||
618 | -----------------------------------------------------------------------------*/ | |||
619 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c", 619); while (0); | |||
620 | XMLRPC_ASSERT(outputP != NULL)do if (!(outputP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c" , 620); while (0); | |||
621 | XMLRPC_ASSERT(methodName != NULL)do if (!(methodName != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c" , 621); while (0); | |||
622 | XMLRPC_ASSERT_VALUE_OK(paramArrayP)do if (!((paramArrayP) != ((void*)0) && (paramArrayP) ->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c" , 622); while (0); | |||
623 | ||||
624 | addString(envP, outputP, XML_PROLOGUE"<?xml version=\"1.0\" encoding=\"UTF-8\"?>""\015\012"); | |||
625 | if (!envP->fault_occurred) { | |||
| ||||
626 | const char * const xmlns = | |||
627 | dialect == xmlrpc_dialect_apache ? " " XMLNS_APACHE"xmlns:ex=\"" "http://ws.apache.org/xmlrpc/namespaces/extensions" "\"" : ""; | |||
628 | formatOut(envP, outputP, "<methodCall%s>"CRLF"\015\012""<methodName>", xmlns); | |||
629 | if (!envP->fault_occurred) { | |||
630 | xmlrpc_mem_block * encodedP; | |||
631 | escapeForXml(envP, methodName, strlen(methodName), &encodedP); | |||
632 | if (!envP->fault_occurred) { | |||
633 | const char * const contents = | |||
634 | XMLRPC_MEMBLOCK_CONTENTS(char, encodedP)((char*) xmlrpc_mem_block_contents(encodedP)); | |||
635 | size_t const size = XMLRPC_MEMBLOCK_SIZE(char, encodedP)(xmlrpc_mem_block_size(encodedP) / sizeof(char)); | |||
636 | XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, contents, size)xmlrpc_mem_block_append(envP, outputP, contents, sizeof(char) * (size)); | |||
637 | if (!envP->fault_occurred) { | |||
638 | addString(envP, outputP, "</methodName>"CRLF"\015\012"); | |||
639 | if (!envP->fault_occurred) { | |||
640 | xmlrpc_serialize_params2(envP, outputP, paramArrayP, | |||
641 | dialect); | |||
642 | if (!envP->fault_occurred) | |||
643 | addString(envP, outputP, "</methodCall>"CRLF"\015\012"); | |||
644 | } | |||
645 | } | |||
646 | XMLRPC_MEMBLOCK_FREE(char, encodedP)xmlrpc_mem_block_free(encodedP); | |||
647 | } | |||
648 | } | |||
649 | } | |||
650 | } | |||
651 | ||||
652 | ||||
653 | ||||
654 | void | |||
655 | xmlrpc_serialize_call(xmlrpc_env * const envP, | |||
656 | xmlrpc_mem_block * const outputP, | |||
657 | const char * const methodName, | |||
658 | xmlrpc_value * const paramArrayP) { | |||
659 | ||||
660 | xmlrpc_serialize_call2(envP, outputP, methodName, paramArrayP, | |||
| ||||
661 | xmlrpc_dialect_i8); | |||
662 | } | |||
663 | ||||
664 | ||||
665 | ||||
666 | void | |||
667 | xmlrpc_serialize_response2(xmlrpc_env * const envP, | |||
668 | xmlrpc_mem_block * const outputP, | |||
669 | xmlrpc_value * const valueP, | |||
670 | xmlrpc_dialect const dialect) { | |||
671 | /*---------------------------------------------------------------------------- | |||
672 | Serialize a result response to an XML-RPC call. | |||
673 | ||||
674 | The result is 'valueP'. | |||
675 | ||||
676 | Add the response XML to *outputP. | |||
677 | -----------------------------------------------------------------------------*/ | |||
678 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c", 678); while (0); | |||
679 | XMLRPC_ASSERT(outputP != NULL)do if (!(outputP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c" , 679); while (0); | |||
680 | XMLRPC_ASSERT_VALUE_OK(valueP)do if (!((valueP) != ((void*)0) && (valueP)->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c" , 680); while (0); | |||
681 | ||||
682 | addString(envP, outputP, XML_PROLOGUE"<?xml version=\"1.0\" encoding=\"UTF-8\"?>""\015\012"); | |||
683 | if (!envP->fault_occurred) { | |||
684 | const char * const xmlns = | |||
685 | dialect == xmlrpc_dialect_apache ? " " XMLNS_APACHE"xmlns:ex=\"" "http://ws.apache.org/xmlrpc/namespaces/extensions" "\"" : ""; | |||
686 | formatOut(envP, outputP, | |||
687 | "<methodResponse%s>"CRLF"\015\012""<params>"CRLF"\015\012""<param>", xmlns); | |||
688 | if (!envP->fault_occurred) { | |||
689 | xmlrpc_serialize_value2(envP, outputP, valueP, dialect); | |||
690 | if (!envP->fault_occurred) { | |||
691 | addString(envP, outputP, | |||
692 | "</param>"CRLF"\015\012""</params>"CRLF"\015\012" | |||
693 | "</methodResponse>"CRLF"\015\012"); | |||
694 | } | |||
695 | } | |||
696 | } | |||
697 | } | |||
698 | ||||
699 | ||||
700 | ||||
701 | void | |||
702 | xmlrpc_serialize_response(xmlrpc_env * const envP, | |||
703 | xmlrpc_mem_block * const outputP, | |||
704 | xmlrpc_value * const valueP) { | |||
705 | ||||
706 | xmlrpc_serialize_response2(envP, outputP, valueP, xmlrpc_dialect_i8); | |||
707 | } | |||
708 | ||||
709 | ||||
710 | ||||
711 | void | |||
712 | xmlrpc_serialize_fault(xmlrpc_env * const envP, | |||
713 | xmlrpc_mem_block * const outputP, | |||
714 | const xmlrpc_env * const faultP) { | |||
715 | /*---------------------------------------------------------------------------- | |||
716 | Serialize a fault response to an XML-RPC call. | |||
717 | ||||
718 | 'faultP' is the fault. | |||
719 | ||||
720 | Add the response XML to *outputP. | |||
721 | -----------------------------------------------------------------------------*/ | |||
722 | xmlrpc_value * faultStructP; | |||
723 | ||||
724 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c", 724); while (0); | |||
725 | XMLRPC_ASSERT(outputP != NULL)do if (!(outputP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c" , 725); while (0); | |||
726 | XMLRPC_ASSERT(faultP != NULL)do if (!(faultP != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c" , 726); while (0); | |||
727 | XMLRPC_ASSERT(faultP->fault_occurred)do if (!(faultP->fault_occurred)) xmlrpc_assertion_failed( "../../../../libs/xmlrpc-c/src/xmlrpc_serialize.c", 727); while (0); | |||
728 | ||||
729 | faultStructP = xmlrpc_build_value(envP, "{s:i,s:s}", | |||
730 | "faultCode", | |||
731 | (xmlrpc_int32) faultP->fault_code, | |||
732 | "faultString", faultP->fault_string); | |||
733 | if (!envP->fault_occurred) { | |||
734 | addString(envP, outputP, XML_PROLOGUE"<?xml version=\"1.0\" encoding=\"UTF-8\"?>""\015\012"); | |||
735 | if (!envP->fault_occurred) { | |||
736 | addString(envP, outputP, "<methodResponse>"CRLF"\015\012""<fault>"CRLF"\015\012"); | |||
737 | if (!envP->fault_occurred) { | |||
738 | xmlrpc_serialize_value(envP, outputP, faultStructP); | |||
739 | if (!envP->fault_occurred) { | |||
740 | addString(envP, outputP, | |||
741 | CRLF"\015\012""</fault>"CRLF"\015\012""</methodResponse>"CRLF"\015\012"); | |||
742 | } | |||
743 | } | |||
744 | } | |||
745 | xmlrpc_DECREF(faultStructP); | |||
746 | } | |||
747 | } | |||
748 | ||||
749 | ||||
750 | ||||
751 | /* Copyright (C) 2001 by First Peer, Inc. All rights reserved. | |||
752 | ** | |||
753 | ** Redistribution and use in source and binary forms, with or without | |||
754 | ** modification, are permitted provided that the following conditions | |||
755 | ** are met: | |||
756 | ** 1. Redistributions of source code must retain the above copyright | |||
757 | ** notice, this list of conditions and the following disclaimer. | |||
758 | ** 2. Redistributions in binary form must reproduce the above copyright | |||
759 | ** notice, this list of conditions and the following disclaimer in the | |||
760 | ** documentation and/or other materials provided with the distribution. | |||
761 | ** 3. The name of the author may not be used to endorse or promote products | |||
762 | ** derived from this software without specific prior written permission. | |||
763 | ** | |||
764 | ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||
765 | ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
766 | ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
767 | ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||
768 | ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
769 | ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
770 | ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
771 | ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
772 | ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
773 | ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
774 | ** SUCH DAMAGE. */ |