int getpart(char **outbuf, size_t *outlen, const char *main, const char *sub, FILE *stream) { # define MAX_TAG_LEN 79 char couter[MAX_TAG_LEN+1]; /* current outermost section */ char cmain[MAX_TAG_LEN+1]; /* current main section */ char csub[MAX_TAG_LEN+1]; /* current sub section */ char ptag[MAX_TAG_LEN+1]; /* potential tag */ char patt[MAX_TAG_LEN+1]; /* potential attributes */ char *buffer = NULL; char *ptr; char *end; union { ssize_t sig; size_t uns; } len; size_t bufsize = 0; size_t outalloc = 256; int in_wanted_part = 0; int base64 = 0; int error; enum { STATE_OUTSIDE = 0, STATE_OUTER = 1, STATE_INMAIN = 2, STATE_INSUB = 3, STATE_ILLEGAL = 4 } state = STATE_OUTSIDE; *outlen = 0; *outbuf = malloc(outalloc); if(!*outbuf) return GPE_OUT_OF_MEMORY; *(*outbuf) = '\0'; couter[0] = cmain[0] = csub[0] = ptag[0] = patt[0] = '\0'; while((error = readline(&buffer, &bufsize, stream)) == GPE_OK) { ptr = buffer; EAT_SPACE(ptr); if('<' != *ptr) { if(in_wanted_part) { show(("=> %s", buffer)); error = appenddata(outbuf, outlen, &outalloc, buffer, base64); if(error) break; } continue; } ptr++; if('/' == *ptr) { /* ** closing section tag */ ptr++; end = ptr; EAT_WORD(end); if((len.sig = end - ptr) > MAX_TAG_LEN) { error = GPE_NO_BUFFER_SPACE; break; } memcpy(ptag, ptr, len.uns); ptag[len.uns] = '\0'; if((STATE_INSUB == state) && !strcmp(csub, ptag)) { /* end of current sub section */ state = STATE_INMAIN; csub[0] = '\0'; if(in_wanted_part) { /* end of wanted part */ in_wanted_part = 0; break; } } else if((STATE_INMAIN == state) && !strcmp(cmain, ptag)) { /* end of current main section */ state = STATE_OUTER; cmain[0] = '\0'; if(in_wanted_part) { /* end of wanted part */ in_wanted_part = 0; break; } } else if((STATE_OUTER == state) && !strcmp(couter, ptag)) { /* end of outermost file section */ state = STATE_OUTSIDE; couter[0] = '\0'; if(in_wanted_part) { /* end of wanted part */ in_wanted_part = 0; break; } } } else if(!in_wanted_part) { /* ** opening section tag */ /* get potential tag */ end = ptr; EAT_WORD(end); if((len.sig = end - ptr) > MAX_TAG_LEN) { error = GPE_NO_BUFFER_SPACE; break; } memcpy(ptag, ptr, len.uns); ptag[len.uns] = '\0'; /* ignore comments, doctypes and xml declarations */ if(('!' == ptag[0]) || ('?' == ptag[0])) { show(("* ignoring (%s)", buffer)); continue; } /* get all potential attributes */ ptr = end; EAT_SPACE(ptr); end = ptr; while(*end && ('>' != *end)) end++; if((len.sig = end - ptr) > MAX_TAG_LEN) { error = GPE_NO_BUFFER_SPACE; break; } memcpy(patt, ptr, len.uns); patt[len.uns] = '\0'; if(STATE_OUTSIDE == state) { /* outermost element (<testcase>) */ strcpy(couter, ptag); state = STATE_OUTER; continue; } else if(STATE_OUTER == state) { /* start of a main section */ strcpy(cmain, ptag); state = STATE_INMAIN; continue; } else if(STATE_INMAIN == state) { /* start of a sub section */ strcpy(csub, ptag); state = STATE_INSUB; if(!strcmp(cmain, main) && !strcmp(csub, sub)) { /* start of wanted part */ in_wanted_part = 1; if(strstr(patt, "base64=")) /* bit rough test, but "mostly" functional, */ /* treat wanted part data as base64 encoded */ base64 = 1; } continue; } } if(in_wanted_part) { show(("=> %s", buffer)); error = appenddata(outbuf, outlen, &outalloc, buffer, base64); if(error) break; } } /* while */ if(buffer) free(buffer); if(error != GPE_OK) { if(error == GPE_END_OF_FILE) error = GPE_OK; else { if(*outbuf) free(*outbuf); *outbuf = NULL; *outlen = 0; } } return error; }
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; }