summaryrefslogtreecommitdiffstats
path: root/kio/httpfilter/httpfilter.cc
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch)
tree5ac38a06f3dde268dc7927dc155896926aaf7012 /kio/httpfilter/httpfilter.cc
downloadtdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz
tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kio/httpfilter/httpfilter.cc')
-rw-r--r--kio/httpfilter/httpfilter.cc372
1 files changed, 372 insertions, 0 deletions
diff --git a/kio/httpfilter/httpfilter.cc b/kio/httpfilter/httpfilter.cc
new file mode 100644
index 000000000..d828064b7
--- /dev/null
+++ b/kio/httpfilter/httpfilter.cc
@@ -0,0 +1,372 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2002 Waldo Bastian <[email protected]>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kio/global.h>
+
+#include <klocale.h>
+
+#include "httpfilter.h"
+
+HTTPFilterBase::HTTPFilterBase()
+ : last(0)
+{
+}
+
+HTTPFilterBase::~HTTPFilterBase()
+{
+ delete last;
+}
+
+void
+HTTPFilterBase::chain(HTTPFilterBase *previous)
+{
+ last = previous;
+ connect(last, SIGNAL(output(const QByteArray &)),
+ this, SLOT(slotInput(const QByteArray &)));
+}
+
+HTTPFilterChain::HTTPFilterChain()
+ : first(0)
+{
+}
+
+void
+HTTPFilterChain::addFilter(HTTPFilterBase *filter)
+{
+ if (!last)
+ {
+ first = filter;
+ }
+ else
+ {
+ disconnect(last, SIGNAL(output(const QByteArray &)), 0, 0);
+ filter->chain(last);
+ }
+ last = filter;
+ connect(filter, SIGNAL(output(const QByteArray &)),
+ this, SIGNAL(output(const QByteArray &)));
+ connect(filter, SIGNAL(error(int, const QString &)),
+ this, SIGNAL(error(int, const QString &)));
+}
+
+void
+HTTPFilterChain::slotInput(const QByteArray &d)
+{
+ if (first)
+ first->slotInput(d);
+ else
+ emit output(d);
+}
+
+HTTPFilterMD5::HTTPFilterMD5()
+{
+}
+
+QString
+HTTPFilterMD5::md5()
+{
+ return QString::fromLatin1(context.base64Digest());
+}
+
+void
+HTTPFilterMD5::slotInput(const QByteArray &d)
+{
+ context.update(d);
+ emit output(d);
+}
+
+
+HTTPFilterGZip::HTTPFilterGZip()
+{
+#ifdef DO_GZIP
+ bHasHeader = false;
+ bHasFinished = false;
+ bPlainText = false;
+ bEatTrailer = false;
+ bEof = false;
+ zstr.next_in = (Bytef *) Z_NULL;
+ zstr.avail_in = 0;
+ zstr.zalloc = Z_NULL;
+ zstr.zfree = Z_NULL;
+ zstr.opaque = Z_NULL;
+
+ inflateInit2(&zstr, -MAX_WBITS);
+
+ iTrailer = 8;
+#endif
+}
+
+HTTPFilterGZip::~HTTPFilterGZip()
+{
+#ifdef DO_GZIP
+ inflateEnd(&zstr);
+#endif
+
+}
+
+/* The get_byte() and checkHeader() functions are modified version from */
+/* the correpsonding functions that can be found in zlib, the following */
+/* copyright notice applies to these functions: */
+
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.1.3, July 9th, 1998
+
+ Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+int
+HTTPFilterGZip::get_byte()
+{
+#ifdef DO_GZIP
+ if (bEof) return EOF;
+ if (zstr.avail_in == 0)
+ {
+ bEof = true;
+ return EOF;
+ }
+ zstr.avail_in--;
+ zstr.total_in++;
+ return *(zstr.next_in)++;
+#else
+ return 0;
+#endif
+}
+
+#ifdef DO_GZIP
+
+static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define RESERVED 0xE0 /* bits 5..7: reserved */
+#endif
+
+// 0 : ok
+// 1 : not gzip
+// 2 : no header
+int
+HTTPFilterGZip::checkHeader()
+{
+#ifdef DO_GZIP
+ uInt len;
+ int c;
+
+ /* Check the gzip magic header */
+ for (len = 0; len < 2; len++) {
+ c = get_byte();
+ if (c != gz_magic[len]) {
+ if (len != 0)
+ {
+ zstr.avail_in++;
+ zstr.next_in--;
+ }
+ if (c != EOF) {
+ zstr.avail_in++;
+ zstr.next_in--;
+ return 1;
+ }
+ return 2;
+ }
+ }
+
+ int method = get_byte(); /* method byte */
+ int flags = get_byte(); /* flags byte */
+
+ if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
+ return bEof ? 2 : 1;
+ }
+
+ /* Discard time, xflags and OS code: */
+ for (len = 0; len < 6; len++) (void)get_byte();
+
+ if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
+ len = (uInt)get_byte();
+ len += ((uInt)get_byte())<<8;
+ /* len is garbage if EOF but the loop below will quit anyway */
+ while (len-- != 0 && get_byte() != EOF) ;
+ }
+ if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
+ while ((c = get_byte()) != 0 && c != EOF) ;
+ }
+ if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
+ while ((c = get_byte()) != 0 && c != EOF) ;
+ }
+ if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
+ for (len = 0; len < 2; len++) (void)get_byte();
+ }
+
+ return bEof ? 2 : 0;
+#else
+ return 0;
+#endif
+}
+
+void
+HTTPFilterGZip::slotInput(const QByteArray &d)
+{
+#ifdef DO_GZIP
+ if (bPlainText)
+ {
+ emit output(d);
+ return;
+ }
+ if (d.size() == 0)
+ {
+ if (bEatTrailer)
+ bHasFinished = true;
+ if (!bHasFinished)
+ {
+ // Make sure we get the last bytes still in the pipe.
+ // Needed with "deflate".
+ QByteArray flush(4);
+ flush.fill(0);
+ slotInput(flush);
+ if (!bHasFinished && !bHasHeader)
+ {
+ // Send as-is
+ emit output(headerData);
+ bHasFinished = true;
+ // End of data
+ emit output(QByteArray());
+ }
+ }
+ if (!bHasFinished)
+ emit error( KIO::ERR_SLAVE_DEFINED, i18n("Unexpected end of data, some information may be lost."));
+ return;
+ }
+ if (bHasFinished)
+ return;
+
+ if (bEatTrailer)
+ {
+ iTrailer -= d.size();
+ if (iTrailer <= 0)
+ {
+ bHasFinished = true;
+ // End of data
+ emit output(QByteArray());
+ }
+ return;
+ }
+
+ if (!bHasHeader)
+ {
+ bEof = false;
+
+ // Add data to header.
+ int orig_size = headerData.size();
+ headerData.resize(orig_size+d.size());
+ memcpy(headerData.data()+orig_size, d.data(), d.size());
+
+ zstr.avail_in = headerData.size();
+ zstr.next_in = (Bytef *) headerData.data();
+
+ int result = checkHeader();
+ if (result == 1)
+ {
+ bPlainText = true;
+ output(headerData);
+ return;
+ }
+
+ if (result != 0)
+ return; // next time better
+
+ bHasHeader = true;
+ }
+ else
+ {
+ zstr.avail_in = d.size();
+ zstr.next_in = (Bytef *) d.data();
+ }
+
+ while( zstr.avail_in )
+ {
+ char buf[8192];
+ zstr.next_out = (Bytef *) buf;
+ zstr.avail_out = 8192;
+ int result = inflate( &zstr, Z_NO_FLUSH );
+ if ((result != Z_OK) && (result != Z_STREAM_END))
+ {
+ emit error( KIO::ERR_SLAVE_DEFINED, i18n("Receiving corrupt data."));
+ break;
+ }
+ int bytesOut = 8192 - zstr.avail_out;
+ if (bytesOut)
+ {
+ QByteArray d;
+ d.setRawData( buf, bytesOut );
+ emit output(d);
+ d.resetRawData( buf, bytesOut );
+ }
+ if (result == Z_STREAM_END)
+ {
+ if (iTrailer)
+ {
+ bEatTrailer = true;
+ }
+ else
+ {
+ bHasFinished = true;
+ // End of data
+ emit output(QByteArray());
+ }
+ return;
+ }
+ }
+#endif
+}
+
+HTTPFilterDeflate::HTTPFilterDeflate()
+{
+#ifdef DO_GZIP
+ bHasHeader = true;
+ iTrailer = 0;
+#endif
+}
+
+#include "httpfilter.moc"