static void process_gzip(class tcpdemux &demux, std::stringstream &ss, const std::string &fname,const unsigned char *base,size_t len) { if((len>4) && (base[0]==0x1f) && (base[1]==0x8b) && (base[2]==0x08) && (base[3]==0x00)) { size_t uncompr_size = len * 16; unsigned char *decompress_buf = (unsigned char *)malloc(uncompr_size); if(decompress_buf==0) return; // too big? z_stream zs; memset(&zs,0,sizeof(zs)); zs.next_in = (Bytef *)base; // note that next_in should be typedef const but is not zs.avail_in = len; zs.next_out = decompress_buf; zs.avail_out = uncompr_size; int r = inflateInit2(&zs,16+MAX_WBITS); if(r==0) { r = inflate(&zs,Z_SYNC_FLUSH); /* Ignore the error return; process data if we got anything */ if(zs.total_out>0) { demux.write_to_file(ss,fname,sbuf_t(pos0_t(),decompress_buf,zs.total_out,zs.total_out,false)); } inflateEnd(&zs); } free(decompress_buf); } }
void process_path_printer(const scanner_params &sp) { /* 1. Get next token * 2. if prefix part is a number, skip forward that much in sbuf and repeat. * if the prefix is PRINT, print the buffer * if next part is a string, strip it and run that decoder. * if next part is a |, print * 3. If we are print, throw an exception to prevent continued analysis of buffer. */ std::string new_path = sp.sbuf.pos0.path; std::string prefix = get_and_remove_token(new_path); /* Time to print ?*/ if(prefix.size()==0 || prefix=="PRINT"){ uint64_t print_start = 0; uint64_t print_len = 4096; /* Check for options */ scanner_params::PrintOptions::iterator it; it = sp.print_options.find("Content-Length"); if(it!=sp.print_options.end()){ print_len = stoi64(it->second); } it = sp.print_options.find("Range"); if(it!=sp.print_options.end()){ if(it->second[5]=='='){ size_t dash = it->second.find('-'); std::string v1 = it->second.substr(6,dash-6); std::string v2 = it->second.substr(dash+1); print_start = stoi64(v1); print_len = stoi64(v2)-print_start+1; } } if(print_start>sp.sbuf.bufsize){ print_len = 0; // can't print anything } if(print_len>0 && print_start+print_len>sp.sbuf.bufsize){ print_len = sp.sbuf.bufsize-print_start; } switch(scanner_params::getPrintMode(sp.print_options)){ case scanner_params::MODE_HTTP: std::cout << "Content-Length: " << print_len << HTTP_EOL; std::cout << "Content-Range: bytes " << print_start << "-" << print_start+print_len-1 << HTTP_EOL; std::cout << "X-Range-Available: bytes " << 0 << "-" << sp.sbuf.bufsize-1 << HTTP_EOL; std::cout << HTTP_EOL; sp.sbuf.raw_dump(std::cout,print_start,print_len); // send to stdout as binary break; case scanner_params::MODE_RAW: std::cout << print_len << HTTP_EOL; std::cout.flush(); sp.sbuf.raw_dump(std::cout,print_start,print_len); // send to stdout as binary break; case scanner_params::MODE_HEX: sp.sbuf.hex_dump(std::cout,print_start,print_len); break; case scanner_params::MODE_NONE: break; } throw printing_done; //return; // our job is done } /* If we are in an offset block, process recursively with the offset */ if(isdigit(prefix[0])){ uint64_t offset = stoi64(prefix); if(offset>sp.sbuf.bufsize){ printf("Error: %s only has %u bytes; can't offset to %u\n", new_path.c_str(),(unsigned int)sp.sbuf.bufsize,(unsigned int)offset); return; } process_path_printer(scanner_params(scanner_params::PHASE_SCAN, sbuf_t(new_path,sp.sbuf+offset), sp.fs,sp.print_options)); return; } /* Find the scanner and use it */ scanner_t *s = be13::plugin::find_scanner(lowerstr(prefix)); if(s){ (*s)(scanner_params(scanner_params::PHASE_SCAN, sbuf_t(new_path,sp.sbuf), sp.fs,sp.print_options), recursion_control_block(process_path_printer,prefix)); return; } std::cerr << "Unknown name in path: " << prefix << "\n"; }