1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
22 #include "server_setup.h"
26 #define ENABLE_CURLX_PRINTF
27 /* make the curlx header define all printf() functions to use the curlx_*
29 #include "curlx.h" /* from the private lib dir */
31 /* just to please curl_base64.h we create a fake struct */
32 struct SessionHandle {
36 #include "curl_base64.h"
37 #include "curl_memory.h"
39 /* include memdebug.h last */
42 #define EAT_SPACE(p) while(*(p) && ISSPACE(*(p))) (p)++
44 #define EAT_WORD(p) while(*(p) && !ISSPACE(*(p)) && ('>' != *(p))) (p)++
47 #define show(x) printf x
49 #define show(x) Curl_nop_stmt
52 #if defined(_MSC_VER) && defined(_DLL)
53 # pragma warning(disable:4232) /* MSVC extension, dllimport identity */
56 curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
57 curl_free_callback Curl_cfree = (curl_free_callback)free;
58 curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
59 curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)strdup;
60 curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
62 #if defined(_MSC_VER) && defined(_DLL)
63 # pragma warning(default:4232) /* MSVC extension, dllimport identity */
69 * Reads a complete line from a file into a dynamically allocated buffer.
71 * Calling function may call this multiple times with same 'buffer'
72 * and 'bufsize' pointers to avoid multiple buffer allocations. Buffer
73 * will be reallocated and 'bufsize' increased until whole line fits in
74 * buffer before returning it.
76 * Calling function is responsible to free allocated buffer.
78 * This function may return:
84 static int readline(char **buffer, size_t *bufsize, FILE *stream)
91 *buffer = malloc(128);
93 return GPE_OUT_OF_MEMORY;
98 int bytestoread = curlx_uztosi(*bufsize - offset);
100 if(!fgets(*buffer + offset, bytestoread, stream))
101 return (offset != 0) ? GPE_OK : GPE_END_OF_FILE ;
103 length = offset + strlen(*buffer + offset);
104 if(*(*buffer + length - 1) == '\n')
107 if(length < *bufsize - 1)
110 newptr = realloc(*buffer, *bufsize * 2);
112 return GPE_OUT_OF_MEMORY;
123 * This appends data from a given source buffer to the end of the used part of
124 * a destination buffer. Arguments relative to the destination buffer are, the
125 * address of a pointer to the destination buffer 'dst_buf', the length of data
126 * in destination buffer excluding potential null string termination 'dst_len',
127 * the allocated size of destination buffer 'dst_alloc'. All three destination
128 * buffer arguments may be modified by this function. Arguments relative to the
129 * source buffer are, a pointer to the source buffer 'src_buf' and indication
130 * whether the source buffer is base64 encoded or not 'src_b64'.
132 * If the source buffer is indicated to be base64 encoded, this appends the
133 * decoded data, binary or whatever, to the destination. The source buffer
134 * may not hold binary data, only a null terminated string is valid content.
136 * Destination buffer will be enlarged and relocated as needed.
138 * Calling function is responsible to provide preallocated destination
139 * buffer and also to deallocate it when no longer needed.
141 * This function may return:
146 static int appenddata(char **dst_buf, /* dest buffer */
147 size_t *dst_len, /* dest buffer data length */
148 size_t *dst_alloc, /* dest buffer allocated size */
149 char *src_buf, /* source buffer */
150 int src_b64) /* != 0 if source is base64 encoded */
152 size_t need_alloc, src_len;
154 unsigned char *as_uchar;
158 src_len = strlen(src_buf);
162 buf64.as_char = NULL;
165 /* base64 decode the given buffer */
166 int error = (int) Curl_base64_decode(src_buf, &buf64.as_uchar, &src_len);
168 return GPE_OUT_OF_MEMORY;
169 src_buf = buf64.as_char;
170 if(!src_len || !src_buf) {
172 ** currently there is no way to tell apart an OOM condition in
173 ** Curl_base64_decode() from zero length decoded data. For now,
174 ** let's just assume it is an OOM condition, currently we have
175 ** no input for this function that decodes to zero length data.
179 return GPE_OUT_OF_MEMORY;
183 need_alloc = src_len + *dst_len + 1;
185 /* enlarge destination buffer if required */
186 if(need_alloc > *dst_alloc) {
187 size_t newsize = need_alloc * 2;
188 char *newptr = realloc(*dst_buf, newsize);
192 return GPE_OUT_OF_MEMORY;
194 *dst_alloc = newsize;
198 /* memcpy to support binary blobs */
199 memcpy(*dst_buf + *dst_len, src_buf, src_len);
201 *(*dst_buf + *dst_len) = '\0';
212 * This returns whole contents of specified XML-like section and subsection
213 * from the given file. This is mostly used to retrieve a specific part from
214 * a test definition file for consumption by test suite servers.
216 * Data is returned in a dynamically allocated buffer, a pointer to this data
217 * and the size of the data is stored at the addresses that caller specifies.
219 * If the returned data is a string the returned size will be the length of
220 * the string excluding null termination. Otherwise it will just be the size
221 * of the returned binary data.
223 * Calling function is responsible to free returned buffer.
225 * This function may return:
226 * GPE_NO_BUFFER_SPACE
231 int getpart(char **outbuf, size_t *outlen,
232 const char *main, const char *sub, FILE *stream)
234 # define MAX_TAG_LEN 79
235 char couter[MAX_TAG_LEN+1]; /* current outermost section */
236 char cmain[MAX_TAG_LEN+1]; /* current main section */
237 char csub[MAX_TAG_LEN+1]; /* current sub section */
238 char ptag[MAX_TAG_LEN+1]; /* potential tag */
239 char patt[MAX_TAG_LEN+1]; /* potential attributes */
248 size_t outalloc = 256;
249 int in_wanted_part = 0;
259 } state = STATE_OUTSIDE;
262 *outbuf = malloc(outalloc);
264 return GPE_OUT_OF_MEMORY;
267 couter[0] = cmain[0] = csub[0] = ptag[0] = patt[0] = '\0';
269 while((error = readline(&buffer, &bufsize, stream)) == GPE_OK) {
276 show(("=> %s", buffer));
277 error = appenddata(outbuf, outlen, &outalloc, buffer, base64);
288 ** closing section tag
294 if((len.sig = end - ptr) > MAX_TAG_LEN) {
295 error = GPE_NO_BUFFER_SPACE;
298 memcpy(ptag, ptr, len.uns);
299 ptag[len.uns] = '\0';
301 if((STATE_INSUB == state) && !strcmp(csub, ptag)) {
302 /* end of current sub section */
303 state = STATE_INMAIN;
306 /* end of wanted part */
311 else if((STATE_INMAIN == state) && !strcmp(cmain, ptag)) {
312 /* end of current main section */
316 /* end of wanted part */
321 else if((STATE_OUTER == state) && !strcmp(couter, ptag)) {
322 /* end of outermost file section */
323 state = STATE_OUTSIDE;
326 /* end of wanted part */
333 else if(!in_wanted_part) {
335 ** opening section tag
338 /* get potential tag */
341 if((len.sig = end - ptr) > MAX_TAG_LEN) {
342 error = GPE_NO_BUFFER_SPACE;
345 memcpy(ptag, ptr, len.uns);
346 ptag[len.uns] = '\0';
348 /* ignore comments, doctypes and xml declarations */
349 if(('!' == ptag[0]) || ('?' == ptag[0])) {
350 show(("* ignoring (%s)", buffer));
354 /* get all potential attributes */
358 while(*end && ('>' != *end))
360 if((len.sig = end - ptr) > MAX_TAG_LEN) {
361 error = GPE_NO_BUFFER_SPACE;
364 memcpy(patt, ptr, len.uns);
365 patt[len.uns] = '\0';
367 if(STATE_OUTSIDE == state) {
368 /* outermost element (<testcase>) */
369 strcpy(couter, ptag);
373 else if(STATE_OUTER == state) {
374 /* start of a main section */
376 state = STATE_INMAIN;
379 else if(STATE_INMAIN == state) {
380 /* start of a sub section */
383 if(!strcmp(cmain, main) && !strcmp(csub, sub)) {
384 /* start of wanted part */
386 if(strstr(patt, "base64="))
387 /* bit rough test, but "mostly" functional, */
388 /* treat wanted part data as base64 encoded */
397 show(("=> %s", buffer));
398 error = appenddata(outbuf, outlen, &outalloc, buffer, base64);
408 if(error != GPE_OK) {
409 if(error == GPE_END_OF_FILE)