254 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			254 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/***************************************************************************
 | 
						|
 *                                  _   _ ____  _
 | 
						|
 *  Project                     ___| | | |  _ \| |
 | 
						|
 *                             / __| | | | |_) | |
 | 
						|
 *                            | (__| |_| |  _ <| |___
 | 
						|
 *                             \___|\___/|_| \_\_____|
 | 
						|
 *
 | 
						|
 * Copyright (C) 1998 - 2008, 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: getpart.c,v 1.28 2008-10-23 14:07:28 yangtse Exp $
 | 
						|
 ***************************************************************************/
 | 
						|
 | 
						|
#include "setup.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 "curl_base64.h"
 | 
						|
#include "memory.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
 | 
						|
 | 
						|
#if defined(_MSC_VER) && defined(_DLL)
 | 
						|
#  pragma warning(disable:4232) /* MSVC extension, dllimport identity */
 | 
						|
#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;
 | 
						|
 | 
						|
#if defined(_MSC_VER) && defined(_DLL)
 | 
						|
#  pragma warning(default:4232) /* MSVC extension, dllimport identity */
 | 
						|
#endif
 | 
						|
 | 
						|
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 */
 | 
						|
{
 | 
						|
  union {
 | 
						|
    unsigned char * as_uchar;
 | 
						|
             char * as_char;
 | 
						|
  } buf64;
 | 
						|
 | 
						|
  size_t len = strlen(buffer);
 | 
						|
  size_t needed_len = len + *stringlen + 1;
 | 
						|
 | 
						|
  buf64.as_char = NULL;
 | 
						|
 | 
						|
  if(base64) {
 | 
						|
    /* decode the given buffer first */
 | 
						|
    len = Curl_base64_decode(buffer, &buf64.as_uchar); /* updated len */
 | 
						|
    buffer = buf64.as_char;
 | 
						|
    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.as_char)
 | 
						|
        free(buf64.as_char);
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  /* memcpy to support binary blobs */
 | 
						|
  memcpy(&string[*stringlen], buffer, len);
 | 
						|
  *stringlen += len;
 | 
						|
  string[*stringlen]=0;
 | 
						|
 | 
						|
  if(buf64.as_char)
 | 
						|
    free(buf64.as_char);
 | 
						|
 | 
						|
  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 = 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;
 | 
						|
}
 | 
						|
 |