kio Library: httpfilter.cc Source File (kio Library)

| # kio Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# httpfilter.cc

    00001 /*
    00002    This file is part of the KDE libraries
    00003    Copyright (c) 2002 Waldo Bastian <bastian@kde.org>
    00004
    00005    This library is free software; you can redistribute it and/or
    00006    modify it under the terms of the GNU Library General Public
    00007    License version 2 as published by the Free Software Foundation.
    00008
    00009    This library is distributed in the hope that it will be useful,
    00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00012    Library General Public License for more details.
    00013
    00014    You should have received a copy of the GNU Library General Public License
    00015    along with this library; see the file COPYING.LIB.  If not, write to
    00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00017    Boston, MA 02111-1307, USA.
    00018 */
    00019
    00020 #include <kio/global.h>
    00021
    00022 #include <klocale.h>
    00023
    00024 #include "httpfilter.h"
    00025
    00026 HTTPFilterBase::HTTPFilterBase()
    00027  : last(0)
    00028 {
    00029 }
    00030
    00031 HTTPFilterBase::~HTTPFilterBase()
    00032 {
    00033    delete last;
    00034 }
    00035
    00036 void
    00037 HTTPFilterBase::chain(HTTPFilterBase *previous)
    00038 {
    00039    last = previous;
    00040    connect(last, SIGNAL(output(const QByteArray &)),
    00041            this, SLOT(slotInput(const QByteArray &)));
    00042 }
    00043
    00044 HTTPFilterChain::HTTPFilterChain()
    00045  : first(0)
    00046 {
    00047 }
    00048
    00049 void
    00050 HTTPFilterChain::addFilter(HTTPFilterBase *filter)
    00051 {
    00052    if (!last)
    00053    {
    00054       first = filter;
    00055    }
    00056    else
    00057    {
    00058       disconnect(last, SIGNAL(output(const QByteArray &)), 0, 0);
    00059       filter->chain(last);
    00060    }
    00061    last = filter;
    00062    connect(filter, SIGNAL(output(const QByteArray &)),
    00063            this, SIGNAL(output(const QByteArray &)));
    00064    connect(filter, SIGNAL(error(int, const QString &)),
    00065            this, SIGNAL(error(int, const QString &)));
    00066 }
    00067
    00068 void
    00069 HTTPFilterChain::slotInput(const QByteArray &d)
    00070 {
    00071    if (first)
    00072       first->slotInput(d);
    00073    else
    00074       emit output(d);
    00075 }
    00076
    00077 HTTPFilterMD5::HTTPFilterMD5()
    00078 {
    00079 }
    00080
    00081 QString
    00082 HTTPFilterMD5::md5()
    00083 {
    00084    return QString::fromLatin1(context.base64Digest());
    00085 }
    00086
    00087 void
    00088 HTTPFilterMD5::slotInput(const QByteArray &d)
    00089 {
    00090    context.update(d);
    00091    emit output(d);
    00092 }
    00093
    00094
    00095 HTTPFilterGZip::HTTPFilterGZip()
    00096 {
    00097 #ifdef DO_GZIP
    00098   bHasHeader = false;
    00099   bHasFinished = false;
    00100   bPlainText = false;
    00101   bEatTrailer = false;
    00102   bEof = false;
    00103   zstr.next_in = (Bytef *) Z_NULL;
    00104   zstr.avail_in = 0;
    00105   zstr.zalloc = Z_NULL;
    00106   zstr.zfree = Z_NULL;
    00107   zstr.opaque = Z_NULL;
    00108   inflateInit2(&zstr, -MAX_WBITS);
    00109   iTrailer = 8;
    00110 #endif
    00111 }
    00112
    00113 HTTPFilterGZip::~HTTPFilterGZip()
    00114 {
    00115 #ifdef DO_GZIP
    00116   inflateEnd(&zstr);
    00117 #endif
    00118
    00119 }
    00120
    00121 /* The get_byte() and checkHeader() functions are modified version from */
    00122 /* the correpsonding functions that can be found in zlib, the following */
    00123 /* copyright notice applies to these functions:                         */
    00124
    00125 /* zlib.h -- interface of the 'zlib' general purpose compression library
    00126   version 1.1.3, July 9th, 1998
    00127
    00128   Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
    00129
    00130   This software is provided 'as-is', without any express or implied
    00131   warranty.  In no event will the authors be held liable for any damages
    00132   arising from the use of this software.
    00133
    00134   Permission is granted to anyone to use this software for any purpose,
    00135   including commercial applications, and to alter it and redistribute it
    00136   freely, subject to the following restrictions:
    00137
    00138   1. The origin of this software must not be misrepresented; you must not
    00139      claim that you wrote the original software. If you use this software
    00140      in a product, an acknowledgment in the product documentation would be
    00141      appreciated but is not required.
    00142   2. Altered source versions must be plainly marked as such, and must not be
    00143      misrepresented as being the original software.
    00144   3. This notice may not be removed or altered from any source distribution.
    00145
    00146   Jean-loup Gailly        Mark Adler
    00147   jloup@gzip.org          madler@alumni.caltech.edu
    00148
    00149
    00150   The data format used by the zlib library is described by RFCs (Request for
    00151   Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
    00152   (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
    00153 */
    00154
    00155 int
    00156 HTTPFilterGZip::get_byte()
    00157 {
    00158 #ifdef DO_GZIP
    00159     if (bEof) return EOF;
    00160     if (zstr.avail_in == 0)
    00161     {
    00162         bEof = true;
    00163         return EOF;
    00164     }
    00165     zstr.avail_in--;
    00166     zstr.total_in++;
    00167     return *(zstr.next_in)++;
    00168 #else
    00169     return 0;
    00170 #endif
    00171 }
    00172
    00173 #ifdef DO_GZIP
    00174
    00175 static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
    00176
    00177 /* gzip flag byte */
    00178 #define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
    00179 #define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
    00180 #define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
    00181 #define ORIG_NAME    0x08 /* bit 3 set: original file name present */
    00182 #define COMMENT      0x10 /* bit 4 set: file comment present */
    00183 #define RESERVED     0xE0 /* bits 5..7: reserved */
    00184 #endif
    00185
    00186 // 0 : ok
    00187 // 1 : not gzip
    00188 // 2 : no header
    00189 int
    00190 HTTPFilterGZip::checkHeader()
    00191 {
    00192 #ifdef DO_GZIP
    00193     uInt len;
    00194     int c;
    00195
    00196     /* Check the gzip magic header */
    00197     for (len = 0; len < 2; len++) {
    00198     c = get_byte();
    00199     if (c != gz_magic[len]) {
    00200         if (len != 0)
    00201         {
    00202            zstr.avail_in++;
    00203            zstr.next_in--;
    00204         }
    00205         if (c != EOF) {
    00206         zstr.avail_in++;
    00207         zstr.next_in--;
    00208         return 1;
    00209         }
    00210         return 2;
    00211     }
    00212     }
    00213     int method = get_byte(); /* method byte */
    00214     int flags = get_byte(); /* flags byte */
    00215
    00216     if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
    00217     return bEof ? 2 : 1;
    00218     }
    00219
    00220     /* Discard time, xflags and OS code: */
    00221     for (len = 0; len < 6; len++) (void)get_byte();
    00222
    00223     if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
    00224     len  =  (uInt)get_byte();
    00225     len += ((uInt)get_byte())<<8;
    00226     /* len is garbage if EOF but the loop below will quit anyway */
    00227     while (len-- != 0 && get_byte() != EOF) ;
    00228     }
    00229     if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
    00230     while ((c = get_byte()) != 0 && c != EOF) ;
    00231     }
    00232     if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
    00233     while ((c = get_byte()) != 0 && c != EOF) ;
    00234     }
    00235     if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
    00236     for (len = 0; len < 2; len++) (void)get_byte();
    00237     }
    00238
    00239     return bEof ? 2 : 0;
    00240 #else
    00241     return 0;
    00242 #endif
    00243 }
    00244
    00245 void
    00246 HTTPFilterGZip::slotInput(const QByteArray &d)
    00247 {
    00248 #ifdef DO_GZIP
    00249   if (bPlainText)
    00250   {
    00251      emit output(d);
    00252      return;
    00253   }
    00254   if (d.size() == 0)
    00255   {
    00256      if (bEatTrailer)
    00257         bHasFinished = true;
    00258      if (!bHasFinished)
    00259      {
    00260         // Make sure we get the last bytes still in the pipe.
    00261         // Needed with "deflate".
    00262         QByteArray flush(4);
    00263         flush.fill(0);
    00264         slotInput(flush);
    00265         if (!bHasFinished && !bHasHeader)
    00266         {
    00267            // Send as-is
    00268            emit output(headerData);
    00269            bHasFinished = true;
    00270            // End of data
    00271            emit output(QByteArray());
    00272         }
    00273      }
    00274      if (!bHasFinished)
    00275         emit error( KIO::ERR_SLAVE_DEFINED, i18n("Unexpected end of data, some information may be lost."));
    00276      return;
    00277   }
    00278   if (bHasFinished)
    00279      return;
    00280
    00281   if (bEatTrailer)
    00282   {
    00283      iTrailer -= d.size();
    00284      if (iTrailer <= 0)
    00285      {
    00286         bHasFinished = true;
    00287         // End of data
    00288         emit output(QByteArray());
    00289      }
    00290      return;
    00291   }
    00292
    00293   if (!bHasHeader)
    00294   {
    00295      bEof = false;
    00296
    00297      // Add data to header.
    00298      int orig_size = headerData.size();
    00299      headerData.resize(orig_size+d.size());
    00300      memcpy(headerData.data()+orig_size, d.data(), d.size());
    00301
    00302      zstr.avail_in = headerData.size();
    00303      zstr.next_in = (Bytef *) headerData.data();
    00304
    00305      int result = checkHeader();
    00306      if (result == 1)
    00307      {
    00308         bPlainText = true;
    00309         output(headerData);
    00310         return;
    00311      }
    00312
    00313      if (result != 0)
    00314         return; // next time better
    00315
    00316      bHasHeader = true;
    00317   }
    00318   else
    00319   {
    00320      zstr.avail_in = d.size();
    00321      zstr.next_in = (Bytef *) d.data();
    00322   }
    00323
    00324   while( zstr.avail_in )
    00325   {
    00326      char buf[8192];
    00327      zstr.next_out = (Bytef *) buf;
    00328      zstr.avail_out = 8192;
    00329      int result = inflate( &zstr, Z_NO_FLUSH );
    00330      if ((result != Z_OK) && (result != Z_STREAM_END))
    00331      {
    00332         emit error( KIO::ERR_SLAVE_DEFINED, i18n("Receiving corrupt data."));
    00333         break;
    00334      }
    00335      int bytesOut = 8192 - zstr.avail_out;
    00336      if (bytesOut)
    00337      {
    00338         QByteArray d;
    00339         d.setRawData( buf, bytesOut );
    00340         emit output(d);
    00341         d.resetRawData( buf, bytesOut );
    00342      }
    00343      if (result == Z_STREAM_END)
    00344      {
    00345         if (iTrailer)
    00346         {
    00347            bEatTrailer = true;
    00348         }
    00349         else
    00350         {
    00351            bHasFinished = true;
    00352            // End of data
    00353            emit output(QByteArray());
    00354         }
    00355         return;
    00356      }
    00357   }
    00358 #endif
    00359 }
    00360
    00361 HTTPFilterDeflate::HTTPFilterDeflate()
    00362 {
    00363 #ifdef DO_GZIP
    00364   bHasHeader = true;
    00365   iTrailer = 0;
    00366 #endif
    00367 }
    00368
    00369 #include "httpfilter.moc"

This file is part of the documentation for kio Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:23:53 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003