curl/tests/server/getpart.c

243 строки
6.3 KiB
C

/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include "setup.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "getpart.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* just to please base64.h we create a fake struct */
struct SessionHandle {
int fake;
};
#include "base64.h"
/* include memdebug.h last */
#include "memdebug.h"
#define EAT_SPACE(ptr) while( ptr && *ptr && ISSPACE(*ptr) ) ptr++
#define EAT_WORD(ptr) while( ptr && *ptr && !ISSPACE(*ptr) && \
('>' != *ptr)) ptr++
#ifdef DEBUG
#define show(x) printf x
#else
#define show(x)
#endif
curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
curl_free_callback Curl_cfree = (curl_free_callback)free;
curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)strdup;
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
static
char *appendstring(char *string, /* original string */
char *buffer, /* to append */
size_t *stringlen, /* length of string */
size_t *stralloc, /* allocated size */
char base64) /* 1 if base64 encoded */
{
size_t len = strlen(buffer);
size_t needed_len = len + *stringlen + 1;
char *buf64=NULL;
if(base64) {
/* decode the given buffer first */
len = Curl_base64_decode(buffer, (unsigned char**)&buf64); /* updated len */
buffer = buf64;
needed_len = len + *stringlen + 1; /* recalculate */
}
if(needed_len >= *stralloc) {
char *newptr;
size_t newsize = needed_len*2; /* get twice the needed size */
newptr = realloc(string, newsize);
if(newptr) {
string = newptr;
*stralloc = newsize;
}
else {
if(buf64)
free(buf64);
return NULL;
}
}
/* memcpy to support binary blobs */
memcpy(&string[*stringlen], buffer, len);
*stringlen += len;
string[*stringlen]=0;
if(buf64)
free(buf64);
return string;
}
const char *spitout(FILE *stream,
const char *main,
const char *sub, size_t *size)
{
char buffer[8192]; /* big enough for anything */
char cmain[128]=""; /* current main section */
char csub[128]=""; /* current sub section */
char *ptr;
char *end;
char display = 0;
char *string;
size_t stringlen=0;
size_t stralloc=256;
char base64 = 0; /* set to 1 if true */
enum {
STATE_OUTSIDE,
STATE_OUTER,
STATE_INMAIN,
STATE_INSUB,
STATE_ILLEGAL
} state = STATE_OUTSIDE;
string = (char *)malloc(stralloc);
if(!string)
return NULL;
string[0] = 0; /* zero first byte in case of no data */
while(fgets(buffer, sizeof(buffer), stream)) {
ptr = buffer;
/* pass white spaces */
EAT_SPACE(ptr);
if('<' != *ptr) {
if(display) {
show(("=> %s", buffer));
string = appendstring(string, buffer, &stringlen, &stralloc, base64);
show(("* %s\n", buffer));
}
continue;
}
ptr++;
EAT_SPACE(ptr);
if('/' == *ptr) {
/* end of a section */
ptr++;
EAT_SPACE(ptr);
end = ptr;
EAT_WORD(end);
*end = 0;
if((state == STATE_INSUB) &&
!strcmp(csub, ptr)) {
/* this is the end of the currently read sub section */
state--;
csub[0]=0; /* no sub anymore */
display=0;
}
else if((state == STATE_INMAIN) &&
!strcmp(cmain, ptr)) {
/* this is the end of the currently read main section */
state--;
cmain[0]=0; /* no main anymore */
display=0;
}
else if(state == STATE_OUTER) {
/* this is the end of the outermost file section */
state--;
}
}
else if(!display) {
/* this is the beginning of a section */
end = ptr;
EAT_WORD(end);
*end = 0;
switch(state) {
case STATE_OUTSIDE:
/* Skip over the outermost element (<testcase>), but if it turns out
to be a comment, completely ignore it below */
strcpy(cmain, ptr);
state = STATE_OUTER;
break;
case STATE_OUTER:
strcpy(cmain, ptr);
state = STATE_INMAIN;
break;
case STATE_INMAIN:
strcpy(csub, ptr);
state = STATE_INSUB;
break;
default:
break;
}
if(!end[1] != '>') {
/* There might be attributes here. Check for those we know of and care
about. */
if(strstr(&end[1], "base64=")) {
/* rough and dirty, but "mostly" functional */
/* Treat all data as base64 encoded */
base64 = 1;
}
}
}
if(display) {
string = appendstring(string, buffer, &stringlen, &stralloc, base64);
show(("* %s\n", buffer));
}
if((STATE_INSUB == state) &&
!strcmp(cmain, main) &&
!strcmp(csub, sub)) {
show(("* (%d bytes) %s\n", stringlen, buffer));
display = 1; /* start displaying */
}
else if ((*cmain == '?') || (*cmain == '!') || (*csub == '!')) {
/* Ignore comments, DOCTYPEs and XML declarations */
show(("%d ignoring (%s/%s)\n", state, cmain, csub));
state--;
}
else {
show(("%d (%s/%s): %s\n", state, cmain, csub, buffer));
display = 0; /* no display */
}
}
*size = stringlen;
return string;
}