📄 databuffer.cpp
字号:
//Please refer to http://dansguardian.org/?page=copyright//for the license for this code.//Written by Daniel Barron (daniel@//jadeb/.com).//For support go to http://groups.yahoo.com/group/dansguardian// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA#include <syslog.h>#include "String.hpp"#include <algorithm>#include "DataBuffer.hpp"#include <cstdlib>#include <unistd.h>#include <zlib.h>#include <cerrno>#include <fstream>#ifdef __GCCVER3 #include <istream>#else #include <istream.h>#endifextern OptionContainer o;DataBuffer::DataBuffer():data(new char[0]),buffer_length(0),compresseddata(NULL),compressed_buffer_length(0),timeout(20),decompress("") {}// set buffer length to zero and initialise the char* memory block to hold// the data - initialisation/creation functionDataBuffer::~DataBuffer() { delete[] data; if (compresseddata != NULL) { delete[] compresseddata; compresseddata = NULL; }}// delete the memory block when the class is destryedbool DataBuffer::in(Socket *sock) {// if (decompress.contains("gzip")) {// ingzip(sock); // incomming stream is gzip compressed// return;// } bool toobig = false; int rc, newsize; char* block; // buffer for storing a grabbed block from the // imput stream char* temp; while(true) { if (buffer_length >= 32768) { newsize = buffer_length; } else { newsize = 32768; } block = new char[newsize]; try { (*sock).checkForInput(timeout); } catch (exception& e) { delete[] block; break; } rc = (*sock).readFromSocket(block, newsize, 0, timeout); // grab a block of input, doubled each time if (rc < 1) { delete[] block; break; // an error occured so end the while() // or none received so pipe is closed } if (rc > 0) { temp = new char[buffer_length + rc]; // replacement store memcpy(temp, data, buffer_length); // copy the current data memcpy(temp + buffer_length, block, rc); // copy the new data delete[] data; // delete the current data block data = temp; buffer_length += rc; // update data size counter } delete[] block; if (buffer_length > o.max_content_filter_size) { toobig = true; break; } } if (!toobig) { if (decompress.contains("deflate")) { #ifdef DGDEBUG std::cout << "zlib format" << std::endl; #endif zlibinflate(false); // incoming stream was zlib compressed } else if (decompress.contains("gzip")) { #ifdef DGDEBUG std::cout << "gzip format" << std::endl; #endif zlibinflate(true); // incoming stream was gzip compressed } } return toobig;}void DataBuffer::read(Socket *sock, int l) throw (exception) { delete[] data; // delete the current data store (should be emtpy anyway) data = new char[l + 2]; // create a new store large enough int rc; rc = (*sock).readFromSocketn(data, l, 0, timeout); // read in the [POST] data if (rc < 0) { throw exception(); // danger, danger Will Robinson } // The above should be all that's needed - but wait there's more! // Normal data appended to the header by POST is actually 2 bytes longer // than the Content-Length header says. It contains a carrage return and // a new line character. Simple - just add a fudgefactor of 2. // No. Because when uploading a file via a form the POST data is // *exactly* as stated and trying to read even 1 more byte will cause the // read to hang. Also Netscape 4.7x it does it differently. // So we need to check the status of the connection to see if there really // are more bytes to read. if ((*sock).checkForInput()) { rc = (*sock).readFromSocket(data + l, 2, 0, timeout); // if an error occured (rc < 1) we ignore it and try and continue if (rc > 0) { l += 2; // adjust the length } } buffer_length = l; // update data size counter}void DataBuffer::out(Socket *sock) throw(exception) { (*sock).readyForOutput(timeout); // exceptions on timeout or error // need exception or something for a bad write if (!(*sock).writeToSocket(data, buffer_length, 0, timeout)) { throw exception(); } // write the data block out to the stream}void DataBuffer::copytomemory(char* location) { memcpy(location, data, buffer_length); // doh? what does this do?}void DataBuffer::setTimeout(int t) { timeout = t;}void DataBuffer::setDecompress(String d) { decompress = d;}void DataBuffer::zlibinflate(bool header) { if (buffer_length < 12) { return; // it can't possibly be zlib'd } #ifdef DGDEBUG std::cout << "compressed size:" << buffer_length << std::endl; #endif #if ZLIB_VERNUM < 0x1210 #warning ************************************ #warning For gzip support you need zlib 1.2.1 #warning or later to be installed. #warning You can ignore this warning but #warning internet bandwidth may be wasted. #warning ************************************ if (header) { return; } #endif// ofstream logfile("/tmp/zlib", ios::out);// logfile.write(data, buffer_length);// logfile.close(); int newsize = buffer_length * 5; // good estimate of deflated HTML char* block; char* temp; block = new char[newsize]; int err; int bout; int bytesgot = 0; z_stream d_stream; d_stream.zalloc = (alloc_func)0; d_stream.zfree = (free_func)0; d_stream.opaque = (voidpf)0; d_stream.next_in = (Bytef*)data; d_stream.avail_in = buffer_length; d_stream.next_out = (Bytef*)block; d_stream.avail_out = newsize; if (header) { err = inflateInit2(&d_stream, 15 + 32); } else { err = inflateInit2(&d_stream, -15); } if (err != Z_OK) { // was a problem so just return delete[] block; // don't forget to free claimed memory #ifdef DGDEBUG std::cerr << "bad init inflate:" << err << std::endl; #endif return; } while (true) { #ifdef DGDEBUG std::cerr << "inflate loop" << std::endl; #endif err = inflate(&d_stream, Z_NO_FLUSH); bout = newsize - bytesgot - d_stream.avail_out; bytesgot += bout; if (err == Z_STREAM_END) { break; } if (err != Z_OK) { // was a problem so just return delete[] block; // don't forget to free claimed memory #ifdef DGDEBUG std::cerr << "bad inflate:" << String(err) << std::endl; #endif return; } newsize = bytesgot * 2; temp = new char[newsize]; memcpy(temp, block, bytesgot); delete[] block; block = temp; d_stream.next_out = (Bytef*)(block + bytesgot); d_stream.avail_out = newsize - bytesgot; } compresseddata = data; compressed_buffer_length = buffer_length; data = block; buffer_length = bytesgot; // I could create a new block the exact size and memcpy // it over to save RAM but RAM is cheap and this saves CPU// data = new char[bytesgot];// memcpy(data, block, bytesgot);// delete[] block;}// Does a regexp search and replace.bool DataBuffer::contentRegExp(int filtergroup) { #ifdef DGDEBUG std::cout << "Starting content reg exp replace" << std::endl; #endif bool contentmodified = false; unsigned int i; int j; unsigned int s = (*o.fg[filtergroup]).content_regexp_list_comp.size(); int matches; String exp; String replacement; int replen; int sizediff; char* newblock; char* dstpos; int srcoff; int nextoffset; for (i = 0; i < s; i++) { if ((*o.fg[filtergroup]).content_regexp_list_comp[i].match(data)) { replacement = (*o.fg[filtergroup]).content_regexp_list_rep[i]; replen = replacement.length(); matches = (*o.fg[filtergroup]).content_regexp_list_comp[i].numberOfMatches(); sizediff = matches * replen; for (j = 0; j < matches; j++) { sizediff -= (*o.fg[filtergroup]).content_regexp_list_comp[i].length(j); } newblock = new char[buffer_length + sizediff]; srcoff = 0; dstpos = newblock; #ifdef DGDEBUG std::cout << "content matches:" << matches << std::endl; #endif for (j = 0; j < matches; j++) { nextoffset = (*o.fg[filtergroup]).content_regexp_list_comp[i].offset(j); if (nextoffset > srcoff) { memcpy(dstpos, data + srcoff, nextoffset - srcoff); dstpos += nextoffset - srcoff; srcoff = nextoffset; } memcpy(dstpos, replacement.toCharArray(), replen); dstpos += replen; srcoff += (*o.fg[filtergroup]).content_regexp_list_comp[i].length(j); } if (srcoff < buffer_length) { memcpy(dstpos, data + srcoff, buffer_length - srcoff); } delete[] data; data = newblock; buffer_length = buffer_length + sizediff; contentmodified = true; } } return contentmodified;}void DataBuffer::swapbacktocompressed() { if (compresseddata != NULL && compressed_buffer_length > 0) { delete[] data; buffer_length = compressed_buffer_length; data = compresseddata; compresseddata = NULL; compressed_buffer_length = 0; } // drop the decompressed version if there}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -