19bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/***************************************************************************
29bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                                  _   _ ____  _
39bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *  Project                     ___| | | |  _ \| |
49bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                             / __| | | | |_) | |
59bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                            | (__| |_| |  _ <| |___
69bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                             \___|\___/|_| \_\_____|
79bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
8e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
99bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This software is licensed as described in the file COPYING, which
119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * you should have received as part of this distribution. The terms
129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * are also available at http://curl.haxx.se/docs/copyright.html.
139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * You may opt to use, copy, modify, merge, publish, distribute and/or sell
159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * copies of the Software, and permit persons to whom the Software is
169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * furnished to do so, under the terms of the COPYING file.
179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * KIND, either express or implied.
209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ***************************************************************************/
22e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "server_setup.h"
239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "getpart.h"
259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define ENABLE_CURLX_PRINTF
279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* make the curlx header define all printf() functions to use the curlx_*
289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels   versions instead */
299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "curlx.h" /* from the private lib dir */
309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
31e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* just to please curl_base64.h we create a fake struct */
329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstruct SessionHandle {
339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  int fake;
349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels};
359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "curl_base64.h"
379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "curl_memory.h"
389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* include memdebug.h last */
409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "memdebug.h"
419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define EAT_SPACE(p) while(*(p) && ISSPACE(*(p))) (p)++
439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define EAT_WORD(p)  while(*(p) && !ISSPACE(*(p)) && ('>' != *(p))) (p)++
459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef DEBUG_GETPART
479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define show(x) printf x
489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#else
49e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#define show(x) Curl_nop_stmt
509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif
519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#if defined(_MSC_VER) && defined(_DLL)
539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#  pragma warning(disable:4232) /* MSVC extension, dllimport identity */
549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif
559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelscurl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelscurl_free_callback Curl_cfree = (curl_free_callback)free;
589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelscurl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelscurl_strdup_callback Curl_cstrdup = (curl_strdup_callback)strdup;
609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelscurl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
61e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#if defined(WIN32) && defined(UNICODE)
62e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETcurl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
63e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif
649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#if defined(_MSC_VER) && defined(_DLL)
669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#  pragma warning(default:4232) /* MSVC extension, dllimport identity */
679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif
689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/*
709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * readline()
719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Reads a complete line from a file into a dynamically allocated buffer.
739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Calling function may call this multiple times with same 'buffer'
759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * and 'bufsize' pointers to avoid multiple buffer allocations. Buffer
769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * will be reallocated and 'bufsize' increased until whole line fits in
779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * buffer before returning it.
789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Calling function is responsible to free allocated buffer.
809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This function may return:
829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *   GPE_OUT_OF_MEMORY
839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *   GPE_END_OF_FILE
849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *   GPE_OK
859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */
869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int readline(char **buffer, size_t *bufsize, FILE *stream)
889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  size_t offset = 0;
909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  size_t length;
919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  char *newptr;
929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if(!*buffer) {
949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    *buffer = malloc(128);
959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    if(!*buffer)
969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      return GPE_OUT_OF_MEMORY;
979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    *bufsize = 128;
989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  for(;;) {
1019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    int bytestoread = curlx_uztosi(*bufsize - offset);
1029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    if(!fgets(*buffer + offset, bytestoread, stream))
1049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      return (offset != 0) ? GPE_OK : GPE_END_OF_FILE ;
1059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    length = offset + strlen(*buffer + offset);
1079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    if(*(*buffer + length - 1) == '\n')
1089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      break;
1099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    offset = length;
1109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    if(length < *bufsize - 1)
1119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      continue;
1129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    newptr = realloc(*buffer, *bufsize * 2);
1149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    if(!newptr)
1159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      return GPE_OUT_OF_MEMORY;
1169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    *buffer = newptr;
1179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    *bufsize *= 2;
1189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
1199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return GPE_OK;
1219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
1229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/*
1249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * appenddata()
1259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
1269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This appends data from a given source buffer to the end of the used part of
1279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * a destination buffer. Arguments relative to the destination buffer are, the
1289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * address of a pointer to the destination buffer 'dst_buf', the length of data
1299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * in destination buffer excluding potential null string termination 'dst_len',
1309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * the allocated size of destination buffer 'dst_alloc'. All three destination
1319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * buffer arguments may be modified by this function. Arguments relative to the
1329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * source buffer are, a pointer to the source buffer 'src_buf' and indication
1339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * whether the source buffer is base64 encoded or not 'src_b64'.
1349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
1359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * If the source buffer is indicated to be base64 encoded, this appends the
1369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * decoded data, binary or whatever, to the destination. The source buffer
1379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * may not hold binary data, only a null terminated string is valid content.
1389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
1399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Destination buffer will be enlarged and relocated as needed.
1409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
1419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Calling function is responsible to provide preallocated destination
1429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * buffer and also to deallocate it when no longer needed.
1439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
1449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This function may return:
1459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *   GPE_OUT_OF_MEMORY
1469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *   GPE_OK
1479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */
1489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int appenddata(char  **dst_buf,   /* dest buffer */
1509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels                      size_t *dst_len,   /* dest buffer data length */
1519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels                      size_t *dst_alloc, /* dest buffer allocated size */
1529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels                      char   *src_buf,   /* source buffer */
1539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels                      int     src_b64)   /* != 0 if source is base64 encoded */
1549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
155e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  size_t need_alloc = 0;
156e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  size_t src_len = strlen(src_buf);
1579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if(!src_len)
1599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    return GPE_OK;
1609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
161e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  need_alloc = src_len + *dst_len + 1;
1629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if(src_b64) {
164e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    if(src_buf[src_len - 1] == '\r')
165e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      src_len--;
1669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
167e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    if(src_buf[src_len - 1] == '\n')
168e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      src_len--;
169e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  }
1709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  /* enlarge destination buffer if required */
1729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if(need_alloc > *dst_alloc) {
1739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    size_t newsize = need_alloc * 2;
1749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    char *newptr = realloc(*dst_buf, newsize);
1759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    if(!newptr) {
1769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      return GPE_OUT_OF_MEMORY;
1779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    }
1789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    *dst_alloc = newsize;
1799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    *dst_buf = newptr;
1809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
1819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  /* memcpy to support binary blobs */
1839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  memcpy(*dst_buf + *dst_len, src_buf, src_len);
1849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  *dst_len += src_len;
1859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  *(*dst_buf + *dst_len) = '\0';
1869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
187e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  return GPE_OK;
188e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET}
189e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
190e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic int decodedata(char  **buf,   /* dest buffer */
191e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                      size_t *len)   /* dest buffer data length */
192e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{
193e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  int error = 0;
194e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  unsigned char *buf64 = NULL;
195e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  size_t src_len = 0;
196e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
197e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(!*len)
198e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    return GPE_OK;
199e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
200e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  /* base64 decode the given buffer */
201e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  error = (int) Curl_base64_decode(*buf, &buf64, &src_len);
202e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(error)
203e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    return GPE_OUT_OF_MEMORY;
204e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
205e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(!src_len) {
206e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    /*
207e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    ** currently there is no way to tell apart an OOM condition in
208e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    ** Curl_base64_decode() from zero length decoded data. For now,
209e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    ** let's just assume it is an OOM condition, currently we have
210e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    ** no input for this function that decodes to zero length data.
211e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    */
212e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    free(buf64);
213e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
214e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    return GPE_OUT_OF_MEMORY;
215e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  }
216e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
217e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  /* memcpy to support binary blobs */
218e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  memcpy(*buf, buf64, src_len);
219e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  *len = src_len;
220e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  *(*buf + src_len) = '\0';
221e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
222e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  free(buf64);
2239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return GPE_OK;
2259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
2269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/*
2289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * getpart()
2299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
2309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This returns whole contents of specified XML-like section and subsection
2319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * from the given file. This is mostly used to retrieve a specific part from
2329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * a test definition file for consumption by test suite servers.
2339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
2349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Data is returned in a dynamically allocated buffer, a pointer to this data
2359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * and the size of the data is stored at the addresses that caller specifies.
2369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
2379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * If the returned data is a string the returned size will be the length of
2389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * the string excluding null termination. Otherwise it will just be the size
2399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * of the returned binary data.
2409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
2419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Calling function is responsible to free returned buffer.
2429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
2439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This function may return:
2449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *   GPE_NO_BUFFER_SPACE
2459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *   GPE_OUT_OF_MEMORY
2469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *   GPE_OK
2479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */
2489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsint getpart(char **outbuf, size_t *outlen,
2509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels            const char *main, const char *sub, FILE *stream)
2519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
2529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels# define MAX_TAG_LEN 79
2539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  char couter[MAX_TAG_LEN+1]; /* current outermost section */
2549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  char cmain[MAX_TAG_LEN+1];  /* current main section */
2559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  char csub[MAX_TAG_LEN+1];   /* current sub section */
2569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  char ptag[MAX_TAG_LEN+1];   /* potential tag */
2579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  char patt[MAX_TAG_LEN+1];   /* potential attributes */
2589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  char *buffer = NULL;
2599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  char *ptr;
2609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  char *end;
2619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  union {
2629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    ssize_t sig;
2639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels     size_t uns;
2649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  } len;
2659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  size_t bufsize = 0;
2669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  size_t outalloc = 256;
2679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  int in_wanted_part = 0;
2689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  int base64 = 0;
2699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  int error;
2709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  enum {
2729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    STATE_OUTSIDE = 0,
2739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    STATE_OUTER   = 1,
2749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    STATE_INMAIN  = 2,
2759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    STATE_INSUB   = 3,
2769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    STATE_ILLEGAL = 4
2779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  } state = STATE_OUTSIDE;
2789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  *outlen = 0;
2809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  *outbuf = malloc(outalloc);
2819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if(!*outbuf)
2829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    return GPE_OUT_OF_MEMORY;
2839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  *(*outbuf) = '\0';
2849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  couter[0] = cmain[0] = csub[0] = ptag[0] = patt[0] = '\0';
2869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  while((error = readline(&buffer, &bufsize, stream)) == GPE_OK) {
2889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    ptr = buffer;
2909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    EAT_SPACE(ptr);
2919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    if('<' != *ptr) {
2939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      if(in_wanted_part) {
2949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        show(("=> %s", buffer));
2959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        error = appenddata(outbuf, outlen, &outalloc, buffer, base64);
2969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        if(error)
2979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          break;
2989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      }
2999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      continue;
3009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    }
3019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    ptr++;
3039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    if('/' == *ptr) {
3059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      /*
3069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      ** closing section tag
3079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      */
3089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      ptr++;
3109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      end = ptr;
3119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      EAT_WORD(end);
3129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      if((len.sig = end - ptr) > MAX_TAG_LEN) {
3139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        error = GPE_NO_BUFFER_SPACE;
3149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        break;
3159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      }
3169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      memcpy(ptag, ptr, len.uns);
3179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      ptag[len.uns] = '\0';
3189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      if((STATE_INSUB == state) && !strcmp(csub, ptag)) {
3209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        /* end of current sub section */
3219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        state = STATE_INMAIN;
3229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        csub[0] = '\0';
3239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        if(in_wanted_part) {
3249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          /* end of wanted part */
3259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          in_wanted_part = 0;
326e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
327e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          /* Do we need to base64 decode the data? */
328e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          if(base64) {
329e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            error = decodedata(outbuf, outlen);
330e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            if(error)
331e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              return error;
332e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          }
3339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          break;
3349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        }
3359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      }
3369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      else if((STATE_INMAIN == state) && !strcmp(cmain, ptag)) {
3379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        /* end of current main section */
3389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        state = STATE_OUTER;
3399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        cmain[0] = '\0';
3409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        if(in_wanted_part) {
3419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          /* end of wanted part */
3429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          in_wanted_part = 0;
343e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
344e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          /* Do we need to base64 decode the data? */
345e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          if(base64) {
346e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            error = decodedata(outbuf, outlen);
347e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            if(error)
348e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              return error;
349e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          }
3509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          break;
3519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        }
3529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      }
3539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      else if((STATE_OUTER == state) && !strcmp(couter, ptag)) {
3549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        /* end of outermost file section */
3559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        state = STATE_OUTSIDE;
3569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        couter[0] = '\0';
3579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        if(in_wanted_part) {
3589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          /* end of wanted part */
3599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          in_wanted_part = 0;
3609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          break;
3619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        }
3629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      }
3639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    }
3659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    else if(!in_wanted_part) {
3669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      /*
3679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      ** opening section tag
3689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      */
3699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      /* get potential tag */
3719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      end = ptr;
3729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      EAT_WORD(end);
3739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      if((len.sig = end - ptr) > MAX_TAG_LEN) {
3749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        error = GPE_NO_BUFFER_SPACE;
3759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        break;
3769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      }
3779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      memcpy(ptag, ptr, len.uns);
3789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      ptag[len.uns] = '\0';
3799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      /* ignore comments, doctypes and xml declarations */
3819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      if(('!' == ptag[0]) || ('?' == ptag[0])) {
3829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        show(("* ignoring (%s)", buffer));
3839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        continue;
3849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      }
3859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      /* get all potential attributes */
3879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      ptr = end;
3889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      EAT_SPACE(ptr);
3899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      end = ptr;
3909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      while(*end && ('>' != *end))
3919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        end++;
3929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      if((len.sig = end - ptr) > MAX_TAG_LEN) {
3939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        error = GPE_NO_BUFFER_SPACE;
3949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        break;
3959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      }
3969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      memcpy(patt, ptr, len.uns);
3979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      patt[len.uns] = '\0';
3989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      if(STATE_OUTSIDE == state) {
4009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        /* outermost element (<testcase>) */
4019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        strcpy(couter, ptag);
4029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        state = STATE_OUTER;
4039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        continue;
4049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      }
4059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      else if(STATE_OUTER == state) {
4069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        /* start of a main section */
4079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        strcpy(cmain, ptag);
4089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        state = STATE_INMAIN;
4099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        continue;
4109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      }
4119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      else if(STATE_INMAIN == state) {
4129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        /* start of a sub section */
4139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        strcpy(csub, ptag);
4149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        state = STATE_INSUB;
4159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        if(!strcmp(cmain, main) && !strcmp(csub, sub)) {
4169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          /* start of wanted part */
4179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          in_wanted_part = 1;
4189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels          if(strstr(patt, "base64="))
4199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels              /* bit rough test, but "mostly" functional, */
4209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels              /* treat wanted part data as base64 encoded */
4219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels              base64 = 1;
4229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        }
4239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        continue;
4249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      }
4259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
4269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    }
4279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
4289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    if(in_wanted_part) {
4299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      show(("=> %s", buffer));
4309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      error = appenddata(outbuf, outlen, &outalloc, buffer, base64);
4319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      if(error)
4329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        break;
4339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    }
4349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
4359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  } /* while */
4369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
437e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  free(buffer);
4389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
4399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  if(error != GPE_OK) {
4409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    if(error == GPE_END_OF_FILE)
4419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      error = GPE_OK;
4429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    else {
443e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      free(*outbuf);
4449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      *outbuf = NULL;
4459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      *outlen = 0;
4469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    }
4479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
4489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
4499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return error;
4509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
4519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
452