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


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:09