1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker * _ _ ____ _
3*6236dae4SAndroid Build Coastguard Worker * Project ___| | | | _ \| |
4*6236dae4SAndroid Build Coastguard Worker * / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker * | (__| |_| | _ <| |___
6*6236dae4SAndroid Build Coastguard Worker * \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker *
8*6236dae4SAndroid Build Coastguard Worker * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker *
10*6236dae4SAndroid Build Coastguard Worker * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker *
14*6236dae4SAndroid Build Coastguard Worker * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker *
18*6236dae4SAndroid Build Coastguard Worker * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker *
21*6236dae4SAndroid Build Coastguard Worker * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker *
23*6236dae4SAndroid Build Coastguard Worker ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker #include "server_setup.h"
25*6236dae4SAndroid Build Coastguard Worker
26*6236dae4SAndroid Build Coastguard Worker #include "getpart.h"
27*6236dae4SAndroid Build Coastguard Worker
28*6236dae4SAndroid Build Coastguard Worker #include "curlx.h" /* from the private lib dir */
29*6236dae4SAndroid Build Coastguard Worker
30*6236dae4SAndroid Build Coastguard Worker #include "curl_base64.h"
31*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
32*6236dae4SAndroid Build Coastguard Worker
33*6236dae4SAndroid Build Coastguard Worker /* include memdebug.h last */
34*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
35*6236dae4SAndroid Build Coastguard Worker
36*6236dae4SAndroid Build Coastguard Worker #define EAT_SPACE(p) while(*(p) && ISSPACE(*(p))) (p)++
37*6236dae4SAndroid Build Coastguard Worker
38*6236dae4SAndroid Build Coastguard Worker #define EAT_WORD(p) while(*(p) && !ISSPACE(*(p)) && ('>' != *(p))) (p)++
39*6236dae4SAndroid Build Coastguard Worker
40*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUG_GETPART
41*6236dae4SAndroid Build Coastguard Worker #define show(x) printf x
42*6236dae4SAndroid Build Coastguard Worker #else
43*6236dae4SAndroid Build Coastguard Worker #define show(x) Curl_nop_stmt
44*6236dae4SAndroid Build Coastguard Worker #endif
45*6236dae4SAndroid Build Coastguard Worker
46*6236dae4SAndroid Build Coastguard Worker #if defined(_MSC_VER) && defined(_DLL)
47*6236dae4SAndroid Build Coastguard Worker # pragma warning(push)
48*6236dae4SAndroid Build Coastguard Worker # pragma warning(disable:4232) /* MSVC extension, dllimport identity */
49*6236dae4SAndroid Build Coastguard Worker #endif
50*6236dae4SAndroid Build Coastguard Worker
51*6236dae4SAndroid Build Coastguard Worker curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
52*6236dae4SAndroid Build Coastguard Worker curl_free_callback Curl_cfree = (curl_free_callback)free;
53*6236dae4SAndroid Build Coastguard Worker curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
54*6236dae4SAndroid Build Coastguard Worker curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)strdup;
55*6236dae4SAndroid Build Coastguard Worker curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
56*6236dae4SAndroid Build Coastguard Worker #if defined(_WIN32) && defined(UNICODE)
57*6236dae4SAndroid Build Coastguard Worker curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
58*6236dae4SAndroid Build Coastguard Worker #endif
59*6236dae4SAndroid Build Coastguard Worker
60*6236dae4SAndroid Build Coastguard Worker #if defined(_MSC_VER) && defined(_DLL)
61*6236dae4SAndroid Build Coastguard Worker # pragma warning(pop)
62*6236dae4SAndroid Build Coastguard Worker #endif
63*6236dae4SAndroid Build Coastguard Worker
64*6236dae4SAndroid Build Coastguard Worker
65*6236dae4SAndroid Build Coastguard Worker /*
66*6236dae4SAndroid Build Coastguard Worker * line_length()
67*6236dae4SAndroid Build Coastguard Worker *
68*6236dae4SAndroid Build Coastguard Worker * Counts the number of characters in a line including a new line.
69*6236dae4SAndroid Build Coastguard Worker * Unlike strlen() it does not stop at nul bytes.
70*6236dae4SAndroid Build Coastguard Worker *
71*6236dae4SAndroid Build Coastguard Worker */
line_length(const char * buffer,int bytestocheck)72*6236dae4SAndroid Build Coastguard Worker static size_t line_length(const char *buffer, int bytestocheck)
73*6236dae4SAndroid Build Coastguard Worker {
74*6236dae4SAndroid Build Coastguard Worker size_t length = 1;
75*6236dae4SAndroid Build Coastguard Worker
76*6236dae4SAndroid Build Coastguard Worker while(*buffer != '\n' && --bytestocheck) {
77*6236dae4SAndroid Build Coastguard Worker length++;
78*6236dae4SAndroid Build Coastguard Worker buffer++;
79*6236dae4SAndroid Build Coastguard Worker }
80*6236dae4SAndroid Build Coastguard Worker if(*buffer != '\n') {
81*6236dae4SAndroid Build Coastguard Worker /*
82*6236dae4SAndroid Build Coastguard Worker * We didn't find a new line so the last byte must be a
83*6236dae4SAndroid Build Coastguard Worker * '\0' character inserted by fgets() which we should not
84*6236dae4SAndroid Build Coastguard Worker * count.
85*6236dae4SAndroid Build Coastguard Worker */
86*6236dae4SAndroid Build Coastguard Worker length--;
87*6236dae4SAndroid Build Coastguard Worker }
88*6236dae4SAndroid Build Coastguard Worker
89*6236dae4SAndroid Build Coastguard Worker return length;
90*6236dae4SAndroid Build Coastguard Worker }
91*6236dae4SAndroid Build Coastguard Worker
92*6236dae4SAndroid Build Coastguard Worker /*
93*6236dae4SAndroid Build Coastguard Worker * readline()
94*6236dae4SAndroid Build Coastguard Worker *
95*6236dae4SAndroid Build Coastguard Worker * Reads a complete line from a file into a dynamically allocated buffer.
96*6236dae4SAndroid Build Coastguard Worker *
97*6236dae4SAndroid Build Coastguard Worker * Calling function may call this multiple times with same 'buffer'
98*6236dae4SAndroid Build Coastguard Worker * and 'bufsize' pointers to avoid multiple buffer allocations. Buffer
99*6236dae4SAndroid Build Coastguard Worker * will be reallocated and 'bufsize' increased until whole line fits in
100*6236dae4SAndroid Build Coastguard Worker * buffer before returning it.
101*6236dae4SAndroid Build Coastguard Worker *
102*6236dae4SAndroid Build Coastguard Worker * Calling function is responsible to free allocated buffer.
103*6236dae4SAndroid Build Coastguard Worker *
104*6236dae4SAndroid Build Coastguard Worker * This function may return:
105*6236dae4SAndroid Build Coastguard Worker * GPE_OUT_OF_MEMORY
106*6236dae4SAndroid Build Coastguard Worker * GPE_END_OF_FILE
107*6236dae4SAndroid Build Coastguard Worker * GPE_OK
108*6236dae4SAndroid Build Coastguard Worker */
109*6236dae4SAndroid Build Coastguard Worker
readline(char ** buffer,size_t * bufsize,size_t * length,FILE * stream)110*6236dae4SAndroid Build Coastguard Worker static int readline(char **buffer, size_t *bufsize, size_t *length,
111*6236dae4SAndroid Build Coastguard Worker FILE *stream)
112*6236dae4SAndroid Build Coastguard Worker {
113*6236dae4SAndroid Build Coastguard Worker size_t offset = 0;
114*6236dae4SAndroid Build Coastguard Worker char *newptr;
115*6236dae4SAndroid Build Coastguard Worker
116*6236dae4SAndroid Build Coastguard Worker if(!*buffer) {
117*6236dae4SAndroid Build Coastguard Worker *buffer = calloc(1, 128);
118*6236dae4SAndroid Build Coastguard Worker if(!*buffer)
119*6236dae4SAndroid Build Coastguard Worker return GPE_OUT_OF_MEMORY;
120*6236dae4SAndroid Build Coastguard Worker *bufsize = 128;
121*6236dae4SAndroid Build Coastguard Worker }
122*6236dae4SAndroid Build Coastguard Worker
123*6236dae4SAndroid Build Coastguard Worker for(;;) {
124*6236dae4SAndroid Build Coastguard Worker int bytestoread = curlx_uztosi(*bufsize - offset);
125*6236dae4SAndroid Build Coastguard Worker
126*6236dae4SAndroid Build Coastguard Worker if(!fgets(*buffer + offset, bytestoread, stream))
127*6236dae4SAndroid Build Coastguard Worker return (offset != 0) ? GPE_OK : GPE_END_OF_FILE;
128*6236dae4SAndroid Build Coastguard Worker
129*6236dae4SAndroid Build Coastguard Worker *length = offset + line_length(*buffer + offset, bytestoread);
130*6236dae4SAndroid Build Coastguard Worker if(*(*buffer + *length - 1) == '\n')
131*6236dae4SAndroid Build Coastguard Worker break;
132*6236dae4SAndroid Build Coastguard Worker offset = *length;
133*6236dae4SAndroid Build Coastguard Worker if(*length < *bufsize - 1)
134*6236dae4SAndroid Build Coastguard Worker continue;
135*6236dae4SAndroid Build Coastguard Worker
136*6236dae4SAndroid Build Coastguard Worker newptr = realloc(*buffer, *bufsize * 2);
137*6236dae4SAndroid Build Coastguard Worker if(!newptr)
138*6236dae4SAndroid Build Coastguard Worker return GPE_OUT_OF_MEMORY;
139*6236dae4SAndroid Build Coastguard Worker memset(&newptr[*bufsize], 0, *bufsize);
140*6236dae4SAndroid Build Coastguard Worker *buffer = newptr;
141*6236dae4SAndroid Build Coastguard Worker *bufsize *= 2;
142*6236dae4SAndroid Build Coastguard Worker }
143*6236dae4SAndroid Build Coastguard Worker
144*6236dae4SAndroid Build Coastguard Worker return GPE_OK;
145*6236dae4SAndroid Build Coastguard Worker }
146*6236dae4SAndroid Build Coastguard Worker
147*6236dae4SAndroid Build Coastguard Worker /*
148*6236dae4SAndroid Build Coastguard Worker * appenddata()
149*6236dae4SAndroid Build Coastguard Worker *
150*6236dae4SAndroid Build Coastguard Worker * This appends data from a given source buffer to the end of the used part of
151*6236dae4SAndroid Build Coastguard Worker * a destination buffer. Arguments relative to the destination buffer are, the
152*6236dae4SAndroid Build Coastguard Worker * address of a pointer to the destination buffer 'dst_buf', the length of data
153*6236dae4SAndroid Build Coastguard Worker * in destination buffer excluding potential null string termination 'dst_len',
154*6236dae4SAndroid Build Coastguard Worker * the allocated size of destination buffer 'dst_alloc'. All three destination
155*6236dae4SAndroid Build Coastguard Worker * buffer arguments may be modified by this function. Arguments relative to the
156*6236dae4SAndroid Build Coastguard Worker * source buffer are, a pointer to the source buffer 'src_buf' and indication
157*6236dae4SAndroid Build Coastguard Worker * whether the source buffer is base64 encoded or not 'src_b64'.
158*6236dae4SAndroid Build Coastguard Worker *
159*6236dae4SAndroid Build Coastguard Worker * If the source buffer is indicated to be base64 encoded, this appends the
160*6236dae4SAndroid Build Coastguard Worker * decoded data, binary or whatever, to the destination. The source buffer
161*6236dae4SAndroid Build Coastguard Worker * may not hold binary data, only a null terminated string is valid content.
162*6236dae4SAndroid Build Coastguard Worker *
163*6236dae4SAndroid Build Coastguard Worker * Destination buffer will be enlarged and relocated as needed.
164*6236dae4SAndroid Build Coastguard Worker *
165*6236dae4SAndroid Build Coastguard Worker * Calling function is responsible to provide preallocated destination
166*6236dae4SAndroid Build Coastguard Worker * buffer and also to deallocate it when no longer needed.
167*6236dae4SAndroid Build Coastguard Worker *
168*6236dae4SAndroid Build Coastguard Worker * This function may return:
169*6236dae4SAndroid Build Coastguard Worker * GPE_OUT_OF_MEMORY
170*6236dae4SAndroid Build Coastguard Worker * GPE_OK
171*6236dae4SAndroid Build Coastguard Worker */
172*6236dae4SAndroid Build Coastguard Worker
appenddata(char ** dst_buf,size_t * dst_len,size_t * dst_alloc,char * src_buf,size_t src_len,int src_b64)173*6236dae4SAndroid Build Coastguard Worker static int appenddata(char **dst_buf, /* dest buffer */
174*6236dae4SAndroid Build Coastguard Worker size_t *dst_len, /* dest buffer data length */
175*6236dae4SAndroid Build Coastguard Worker size_t *dst_alloc, /* dest buffer allocated size */
176*6236dae4SAndroid Build Coastguard Worker char *src_buf, /* source buffer */
177*6236dae4SAndroid Build Coastguard Worker size_t src_len, /* source buffer length */
178*6236dae4SAndroid Build Coastguard Worker int src_b64) /* != 0 if source is base64 encoded */
179*6236dae4SAndroid Build Coastguard Worker {
180*6236dae4SAndroid Build Coastguard Worker size_t need_alloc = 0;
181*6236dae4SAndroid Build Coastguard Worker
182*6236dae4SAndroid Build Coastguard Worker if(!src_len)
183*6236dae4SAndroid Build Coastguard Worker return GPE_OK;
184*6236dae4SAndroid Build Coastguard Worker
185*6236dae4SAndroid Build Coastguard Worker need_alloc = src_len + *dst_len + 1;
186*6236dae4SAndroid Build Coastguard Worker
187*6236dae4SAndroid Build Coastguard Worker if(src_b64) {
188*6236dae4SAndroid Build Coastguard Worker if(src_buf[src_len - 1] == '\r')
189*6236dae4SAndroid Build Coastguard Worker src_len--;
190*6236dae4SAndroid Build Coastguard Worker
191*6236dae4SAndroid Build Coastguard Worker if(src_buf[src_len - 1] == '\n')
192*6236dae4SAndroid Build Coastguard Worker src_len--;
193*6236dae4SAndroid Build Coastguard Worker }
194*6236dae4SAndroid Build Coastguard Worker
195*6236dae4SAndroid Build Coastguard Worker /* enlarge destination buffer if required */
196*6236dae4SAndroid Build Coastguard Worker if(need_alloc > *dst_alloc) {
197*6236dae4SAndroid Build Coastguard Worker size_t newsize = need_alloc * 2;
198*6236dae4SAndroid Build Coastguard Worker char *newptr = realloc(*dst_buf, newsize);
199*6236dae4SAndroid Build Coastguard Worker if(!newptr) {
200*6236dae4SAndroid Build Coastguard Worker return GPE_OUT_OF_MEMORY;
201*6236dae4SAndroid Build Coastguard Worker }
202*6236dae4SAndroid Build Coastguard Worker *dst_alloc = newsize;
203*6236dae4SAndroid Build Coastguard Worker *dst_buf = newptr;
204*6236dae4SAndroid Build Coastguard Worker }
205*6236dae4SAndroid Build Coastguard Worker
206*6236dae4SAndroid Build Coastguard Worker /* memcpy to support binary blobs */
207*6236dae4SAndroid Build Coastguard Worker memcpy(*dst_buf + *dst_len, src_buf, src_len);
208*6236dae4SAndroid Build Coastguard Worker *dst_len += src_len;
209*6236dae4SAndroid Build Coastguard Worker *(*dst_buf + *dst_len) = '\0';
210*6236dae4SAndroid Build Coastguard Worker
211*6236dae4SAndroid Build Coastguard Worker return GPE_OK;
212*6236dae4SAndroid Build Coastguard Worker }
213*6236dae4SAndroid Build Coastguard Worker
decodedata(char ** buf,size_t * len)214*6236dae4SAndroid Build Coastguard Worker static int decodedata(char **buf, /* dest buffer */
215*6236dae4SAndroid Build Coastguard Worker size_t *len) /* dest buffer data length */
216*6236dae4SAndroid Build Coastguard Worker {
217*6236dae4SAndroid Build Coastguard Worker CURLcode error = CURLE_OK;
218*6236dae4SAndroid Build Coastguard Worker unsigned char *buf64 = NULL;
219*6236dae4SAndroid Build Coastguard Worker size_t src_len = 0;
220*6236dae4SAndroid Build Coastguard Worker
221*6236dae4SAndroid Build Coastguard Worker if(!*len)
222*6236dae4SAndroid Build Coastguard Worker return GPE_OK;
223*6236dae4SAndroid Build Coastguard Worker
224*6236dae4SAndroid Build Coastguard Worker /* base64 decode the given buffer */
225*6236dae4SAndroid Build Coastguard Worker error = Curl_base64_decode(*buf, &buf64, &src_len);
226*6236dae4SAndroid Build Coastguard Worker if(error)
227*6236dae4SAndroid Build Coastguard Worker return GPE_OUT_OF_MEMORY;
228*6236dae4SAndroid Build Coastguard Worker
229*6236dae4SAndroid Build Coastguard Worker if(!src_len) {
230*6236dae4SAndroid Build Coastguard Worker /*
231*6236dae4SAndroid Build Coastguard Worker ** currently there is no way to tell apart an OOM condition in
232*6236dae4SAndroid Build Coastguard Worker ** Curl_base64_decode() from zero length decoded data. For now,
233*6236dae4SAndroid Build Coastguard Worker ** let's just assume it is an OOM condition, currently we have
234*6236dae4SAndroid Build Coastguard Worker ** no input for this function that decodes to zero length data.
235*6236dae4SAndroid Build Coastguard Worker */
236*6236dae4SAndroid Build Coastguard Worker free(buf64);
237*6236dae4SAndroid Build Coastguard Worker
238*6236dae4SAndroid Build Coastguard Worker return GPE_OUT_OF_MEMORY;
239*6236dae4SAndroid Build Coastguard Worker }
240*6236dae4SAndroid Build Coastguard Worker
241*6236dae4SAndroid Build Coastguard Worker /* memcpy to support binary blobs */
242*6236dae4SAndroid Build Coastguard Worker memcpy(*buf, buf64, src_len);
243*6236dae4SAndroid Build Coastguard Worker *len = src_len;
244*6236dae4SAndroid Build Coastguard Worker *(*buf + src_len) = '\0';
245*6236dae4SAndroid Build Coastguard Worker
246*6236dae4SAndroid Build Coastguard Worker free(buf64);
247*6236dae4SAndroid Build Coastguard Worker
248*6236dae4SAndroid Build Coastguard Worker return GPE_OK;
249*6236dae4SAndroid Build Coastguard Worker }
250*6236dae4SAndroid Build Coastguard Worker
251*6236dae4SAndroid Build Coastguard Worker /*
252*6236dae4SAndroid Build Coastguard Worker * getpart()
253*6236dae4SAndroid Build Coastguard Worker *
254*6236dae4SAndroid Build Coastguard Worker * This returns whole contents of specified XML-like section and subsection
255*6236dae4SAndroid Build Coastguard Worker * from the given file. This is mostly used to retrieve a specific part from
256*6236dae4SAndroid Build Coastguard Worker * a test definition file for consumption by test suite servers.
257*6236dae4SAndroid Build Coastguard Worker *
258*6236dae4SAndroid Build Coastguard Worker * Data is returned in a dynamically allocated buffer, a pointer to this data
259*6236dae4SAndroid Build Coastguard Worker * and the size of the data is stored at the addresses that caller specifies.
260*6236dae4SAndroid Build Coastguard Worker *
261*6236dae4SAndroid Build Coastguard Worker * If the returned data is a string the returned size will be the length of
262*6236dae4SAndroid Build Coastguard Worker * the string excluding null termination. Otherwise it will just be the size
263*6236dae4SAndroid Build Coastguard Worker * of the returned binary data.
264*6236dae4SAndroid Build Coastguard Worker *
265*6236dae4SAndroid Build Coastguard Worker * Calling function is responsible to free returned buffer.
266*6236dae4SAndroid Build Coastguard Worker *
267*6236dae4SAndroid Build Coastguard Worker * This function may return:
268*6236dae4SAndroid Build Coastguard Worker * GPE_NO_BUFFER_SPACE
269*6236dae4SAndroid Build Coastguard Worker * GPE_OUT_OF_MEMORY
270*6236dae4SAndroid Build Coastguard Worker * GPE_OK
271*6236dae4SAndroid Build Coastguard Worker */
272*6236dae4SAndroid Build Coastguard Worker
getpart(char ** outbuf,size_t * outlen,const char * main,const char * sub,FILE * stream)273*6236dae4SAndroid Build Coastguard Worker int getpart(char **outbuf, size_t *outlen,
274*6236dae4SAndroid Build Coastguard Worker const char *main, const char *sub, FILE *stream)
275*6236dae4SAndroid Build Coastguard Worker {
276*6236dae4SAndroid Build Coastguard Worker # define MAX_TAG_LEN 200
277*6236dae4SAndroid Build Coastguard Worker char couter[MAX_TAG_LEN + 1]; /* current outermost section */
278*6236dae4SAndroid Build Coastguard Worker char cmain[MAX_TAG_LEN + 1]; /* current main section */
279*6236dae4SAndroid Build Coastguard Worker char csub[MAX_TAG_LEN + 1]; /* current sub section */
280*6236dae4SAndroid Build Coastguard Worker char ptag[MAX_TAG_LEN + 1]; /* potential tag */
281*6236dae4SAndroid Build Coastguard Worker char patt[MAX_TAG_LEN + 1]; /* potential attributes */
282*6236dae4SAndroid Build Coastguard Worker char *buffer = NULL;
283*6236dae4SAndroid Build Coastguard Worker char *ptr;
284*6236dae4SAndroid Build Coastguard Worker char *end;
285*6236dae4SAndroid Build Coastguard Worker union {
286*6236dae4SAndroid Build Coastguard Worker ssize_t sig;
287*6236dae4SAndroid Build Coastguard Worker size_t uns;
288*6236dae4SAndroid Build Coastguard Worker } len;
289*6236dae4SAndroid Build Coastguard Worker size_t bufsize = 0;
290*6236dae4SAndroid Build Coastguard Worker size_t outalloc = 256;
291*6236dae4SAndroid Build Coastguard Worker size_t datalen;
292*6236dae4SAndroid Build Coastguard Worker int in_wanted_part = 0;
293*6236dae4SAndroid Build Coastguard Worker int base64 = 0;
294*6236dae4SAndroid Build Coastguard Worker int nonewline = 0;
295*6236dae4SAndroid Build Coastguard Worker int error;
296*6236dae4SAndroid Build Coastguard Worker
297*6236dae4SAndroid Build Coastguard Worker enum {
298*6236dae4SAndroid Build Coastguard Worker STATE_OUTSIDE = 0,
299*6236dae4SAndroid Build Coastguard Worker STATE_OUTER = 1,
300*6236dae4SAndroid Build Coastguard Worker STATE_INMAIN = 2,
301*6236dae4SAndroid Build Coastguard Worker STATE_INSUB = 3,
302*6236dae4SAndroid Build Coastguard Worker STATE_ILLEGAL = 4
303*6236dae4SAndroid Build Coastguard Worker } state = STATE_OUTSIDE;
304*6236dae4SAndroid Build Coastguard Worker
305*6236dae4SAndroid Build Coastguard Worker *outlen = 0;
306*6236dae4SAndroid Build Coastguard Worker *outbuf = malloc(outalloc);
307*6236dae4SAndroid Build Coastguard Worker if(!*outbuf)
308*6236dae4SAndroid Build Coastguard Worker return GPE_OUT_OF_MEMORY;
309*6236dae4SAndroid Build Coastguard Worker *(*outbuf) = '\0';
310*6236dae4SAndroid Build Coastguard Worker
311*6236dae4SAndroid Build Coastguard Worker couter[0] = cmain[0] = csub[0] = ptag[0] = patt[0] = '\0';
312*6236dae4SAndroid Build Coastguard Worker
313*6236dae4SAndroid Build Coastguard Worker while((error = readline(&buffer, &bufsize, &datalen, stream)) == GPE_OK) {
314*6236dae4SAndroid Build Coastguard Worker
315*6236dae4SAndroid Build Coastguard Worker ptr = buffer;
316*6236dae4SAndroid Build Coastguard Worker EAT_SPACE(ptr);
317*6236dae4SAndroid Build Coastguard Worker
318*6236dae4SAndroid Build Coastguard Worker if('<' != *ptr) {
319*6236dae4SAndroid Build Coastguard Worker if(in_wanted_part) {
320*6236dae4SAndroid Build Coastguard Worker show(("=> %s", buffer));
321*6236dae4SAndroid Build Coastguard Worker error = appenddata(outbuf, outlen, &outalloc, buffer, datalen,
322*6236dae4SAndroid Build Coastguard Worker base64);
323*6236dae4SAndroid Build Coastguard Worker if(error)
324*6236dae4SAndroid Build Coastguard Worker break;
325*6236dae4SAndroid Build Coastguard Worker }
326*6236dae4SAndroid Build Coastguard Worker continue;
327*6236dae4SAndroid Build Coastguard Worker }
328*6236dae4SAndroid Build Coastguard Worker
329*6236dae4SAndroid Build Coastguard Worker ptr++;
330*6236dae4SAndroid Build Coastguard Worker
331*6236dae4SAndroid Build Coastguard Worker if('/' == *ptr) {
332*6236dae4SAndroid Build Coastguard Worker /*
333*6236dae4SAndroid Build Coastguard Worker ** closing section tag
334*6236dae4SAndroid Build Coastguard Worker */
335*6236dae4SAndroid Build Coastguard Worker
336*6236dae4SAndroid Build Coastguard Worker ptr++;
337*6236dae4SAndroid Build Coastguard Worker end = ptr;
338*6236dae4SAndroid Build Coastguard Worker EAT_WORD(end);
339*6236dae4SAndroid Build Coastguard Worker len.sig = end - ptr;
340*6236dae4SAndroid Build Coastguard Worker if(len.sig > MAX_TAG_LEN) {
341*6236dae4SAndroid Build Coastguard Worker error = GPE_NO_BUFFER_SPACE;
342*6236dae4SAndroid Build Coastguard Worker break;
343*6236dae4SAndroid Build Coastguard Worker }
344*6236dae4SAndroid Build Coastguard Worker memcpy(ptag, ptr, len.uns);
345*6236dae4SAndroid Build Coastguard Worker ptag[len.uns] = '\0';
346*6236dae4SAndroid Build Coastguard Worker
347*6236dae4SAndroid Build Coastguard Worker if((STATE_INSUB == state) && !strcmp(csub, ptag)) {
348*6236dae4SAndroid Build Coastguard Worker /* end of current sub section */
349*6236dae4SAndroid Build Coastguard Worker state = STATE_INMAIN;
350*6236dae4SAndroid Build Coastguard Worker csub[0] = '\0';
351*6236dae4SAndroid Build Coastguard Worker if(in_wanted_part) {
352*6236dae4SAndroid Build Coastguard Worker /* end of wanted part */
353*6236dae4SAndroid Build Coastguard Worker in_wanted_part = 0;
354*6236dae4SAndroid Build Coastguard Worker
355*6236dae4SAndroid Build Coastguard Worker /* Do we need to base64 decode the data? */
356*6236dae4SAndroid Build Coastguard Worker if(base64) {
357*6236dae4SAndroid Build Coastguard Worker error = decodedata(outbuf, outlen);
358*6236dae4SAndroid Build Coastguard Worker if(error)
359*6236dae4SAndroid Build Coastguard Worker return error;
360*6236dae4SAndroid Build Coastguard Worker }
361*6236dae4SAndroid Build Coastguard Worker if(nonewline)
362*6236dae4SAndroid Build Coastguard Worker (*outlen)--;
363*6236dae4SAndroid Build Coastguard Worker break;
364*6236dae4SAndroid Build Coastguard Worker }
365*6236dae4SAndroid Build Coastguard Worker }
366*6236dae4SAndroid Build Coastguard Worker else if((STATE_INMAIN == state) && !strcmp(cmain, ptag)) {
367*6236dae4SAndroid Build Coastguard Worker /* end of current main section */
368*6236dae4SAndroid Build Coastguard Worker state = STATE_OUTER;
369*6236dae4SAndroid Build Coastguard Worker cmain[0] = '\0';
370*6236dae4SAndroid Build Coastguard Worker if(in_wanted_part) {
371*6236dae4SAndroid Build Coastguard Worker /* end of wanted part */
372*6236dae4SAndroid Build Coastguard Worker in_wanted_part = 0;
373*6236dae4SAndroid Build Coastguard Worker
374*6236dae4SAndroid Build Coastguard Worker /* Do we need to base64 decode the data? */
375*6236dae4SAndroid Build Coastguard Worker if(base64) {
376*6236dae4SAndroid Build Coastguard Worker error = decodedata(outbuf, outlen);
377*6236dae4SAndroid Build Coastguard Worker if(error)
378*6236dae4SAndroid Build Coastguard Worker return error;
379*6236dae4SAndroid Build Coastguard Worker }
380*6236dae4SAndroid Build Coastguard Worker if(nonewline)
381*6236dae4SAndroid Build Coastguard Worker (*outlen)--;
382*6236dae4SAndroid Build Coastguard Worker break;
383*6236dae4SAndroid Build Coastguard Worker }
384*6236dae4SAndroid Build Coastguard Worker }
385*6236dae4SAndroid Build Coastguard Worker else if((STATE_OUTER == state) && !strcmp(couter, ptag)) {
386*6236dae4SAndroid Build Coastguard Worker /* end of outermost file section */
387*6236dae4SAndroid Build Coastguard Worker state = STATE_OUTSIDE;
388*6236dae4SAndroid Build Coastguard Worker couter[0] = '\0';
389*6236dae4SAndroid Build Coastguard Worker if(in_wanted_part) {
390*6236dae4SAndroid Build Coastguard Worker /* end of wanted part */
391*6236dae4SAndroid Build Coastguard Worker in_wanted_part = 0;
392*6236dae4SAndroid Build Coastguard Worker break;
393*6236dae4SAndroid Build Coastguard Worker }
394*6236dae4SAndroid Build Coastguard Worker }
395*6236dae4SAndroid Build Coastguard Worker
396*6236dae4SAndroid Build Coastguard Worker }
397*6236dae4SAndroid Build Coastguard Worker else if(!in_wanted_part) {
398*6236dae4SAndroid Build Coastguard Worker /*
399*6236dae4SAndroid Build Coastguard Worker ** opening section tag
400*6236dae4SAndroid Build Coastguard Worker */
401*6236dae4SAndroid Build Coastguard Worker
402*6236dae4SAndroid Build Coastguard Worker /* get potential tag */
403*6236dae4SAndroid Build Coastguard Worker end = ptr;
404*6236dae4SAndroid Build Coastguard Worker EAT_WORD(end);
405*6236dae4SAndroid Build Coastguard Worker len.sig = end - ptr;
406*6236dae4SAndroid Build Coastguard Worker if(len.sig > MAX_TAG_LEN) {
407*6236dae4SAndroid Build Coastguard Worker error = GPE_NO_BUFFER_SPACE;
408*6236dae4SAndroid Build Coastguard Worker break;
409*6236dae4SAndroid Build Coastguard Worker }
410*6236dae4SAndroid Build Coastguard Worker memcpy(ptag, ptr, len.uns);
411*6236dae4SAndroid Build Coastguard Worker ptag[len.uns] = '\0';
412*6236dae4SAndroid Build Coastguard Worker
413*6236dae4SAndroid Build Coastguard Worker /* ignore comments, doctypes and xml declarations */
414*6236dae4SAndroid Build Coastguard Worker if(('!' == ptag[0]) || ('?' == ptag[0])) {
415*6236dae4SAndroid Build Coastguard Worker show(("* ignoring (%s)", buffer));
416*6236dae4SAndroid Build Coastguard Worker continue;
417*6236dae4SAndroid Build Coastguard Worker }
418*6236dae4SAndroid Build Coastguard Worker
419*6236dae4SAndroid Build Coastguard Worker /* get all potential attributes */
420*6236dae4SAndroid Build Coastguard Worker ptr = end;
421*6236dae4SAndroid Build Coastguard Worker EAT_SPACE(ptr);
422*6236dae4SAndroid Build Coastguard Worker end = ptr;
423*6236dae4SAndroid Build Coastguard Worker while(*end && ('>' != *end))
424*6236dae4SAndroid Build Coastguard Worker end++;
425*6236dae4SAndroid Build Coastguard Worker len.sig = end - ptr;
426*6236dae4SAndroid Build Coastguard Worker if(len.sig > MAX_TAG_LEN) {
427*6236dae4SAndroid Build Coastguard Worker error = GPE_NO_BUFFER_SPACE;
428*6236dae4SAndroid Build Coastguard Worker break;
429*6236dae4SAndroid Build Coastguard Worker }
430*6236dae4SAndroid Build Coastguard Worker memcpy(patt, ptr, len.uns);
431*6236dae4SAndroid Build Coastguard Worker patt[len.uns] = '\0';
432*6236dae4SAndroid Build Coastguard Worker
433*6236dae4SAndroid Build Coastguard Worker if(STATE_OUTSIDE == state) {
434*6236dae4SAndroid Build Coastguard Worker /* outermost element (<testcase>) */
435*6236dae4SAndroid Build Coastguard Worker strcpy(couter, ptag);
436*6236dae4SAndroid Build Coastguard Worker state = STATE_OUTER;
437*6236dae4SAndroid Build Coastguard Worker continue;
438*6236dae4SAndroid Build Coastguard Worker }
439*6236dae4SAndroid Build Coastguard Worker else if(STATE_OUTER == state) {
440*6236dae4SAndroid Build Coastguard Worker /* start of a main section */
441*6236dae4SAndroid Build Coastguard Worker strcpy(cmain, ptag);
442*6236dae4SAndroid Build Coastguard Worker state = STATE_INMAIN;
443*6236dae4SAndroid Build Coastguard Worker continue;
444*6236dae4SAndroid Build Coastguard Worker }
445*6236dae4SAndroid Build Coastguard Worker else if(STATE_INMAIN == state) {
446*6236dae4SAndroid Build Coastguard Worker /* start of a sub section */
447*6236dae4SAndroid Build Coastguard Worker strcpy(csub, ptag);
448*6236dae4SAndroid Build Coastguard Worker state = STATE_INSUB;
449*6236dae4SAndroid Build Coastguard Worker if(!strcmp(cmain, main) && !strcmp(csub, sub)) {
450*6236dae4SAndroid Build Coastguard Worker /* start of wanted part */
451*6236dae4SAndroid Build Coastguard Worker in_wanted_part = 1;
452*6236dae4SAndroid Build Coastguard Worker if(strstr(patt, "base64="))
453*6236dae4SAndroid Build Coastguard Worker /* bit rough test, but "mostly" functional, */
454*6236dae4SAndroid Build Coastguard Worker /* treat wanted part data as base64 encoded */
455*6236dae4SAndroid Build Coastguard Worker base64 = 1;
456*6236dae4SAndroid Build Coastguard Worker if(strstr(patt, "nonewline=")) {
457*6236dae4SAndroid Build Coastguard Worker show(("* setting nonewline\n"));
458*6236dae4SAndroid Build Coastguard Worker nonewline = 1;
459*6236dae4SAndroid Build Coastguard Worker }
460*6236dae4SAndroid Build Coastguard Worker }
461*6236dae4SAndroid Build Coastguard Worker continue;
462*6236dae4SAndroid Build Coastguard Worker }
463*6236dae4SAndroid Build Coastguard Worker
464*6236dae4SAndroid Build Coastguard Worker }
465*6236dae4SAndroid Build Coastguard Worker
466*6236dae4SAndroid Build Coastguard Worker if(in_wanted_part) {
467*6236dae4SAndroid Build Coastguard Worker show(("=> %s", buffer));
468*6236dae4SAndroid Build Coastguard Worker error = appenddata(outbuf, outlen, &outalloc, buffer, datalen, base64);
469*6236dae4SAndroid Build Coastguard Worker if(error)
470*6236dae4SAndroid Build Coastguard Worker break;
471*6236dae4SAndroid Build Coastguard Worker }
472*6236dae4SAndroid Build Coastguard Worker
473*6236dae4SAndroid Build Coastguard Worker } /* while */
474*6236dae4SAndroid Build Coastguard Worker
475*6236dae4SAndroid Build Coastguard Worker free(buffer);
476*6236dae4SAndroid Build Coastguard Worker
477*6236dae4SAndroid Build Coastguard Worker if(error != GPE_OK) {
478*6236dae4SAndroid Build Coastguard Worker if(error == GPE_END_OF_FILE)
479*6236dae4SAndroid Build Coastguard Worker error = GPE_OK;
480*6236dae4SAndroid Build Coastguard Worker else {
481*6236dae4SAndroid Build Coastguard Worker free(*outbuf);
482*6236dae4SAndroid Build Coastguard Worker *outbuf = NULL;
483*6236dae4SAndroid Build Coastguard Worker *outlen = 0;
484*6236dae4SAndroid Build Coastguard Worker }
485*6236dae4SAndroid Build Coastguard Worker }
486*6236dae4SAndroid Build Coastguard Worker
487*6236dae4SAndroid Build Coastguard Worker return error;
488*6236dae4SAndroid Build Coastguard Worker }
489