• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kio

httpfilter.cc

Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, 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 
00109   inflateInit2(&zstr, -MAX_WBITS);
00110 
00111   iTrailer = 8;
00112 #endif
00113 }
00114 
00115 HTTPFilterGZip::~HTTPFilterGZip()
00116 {
00117 #ifdef DO_GZIP
00118   inflateEnd(&zstr);
00119 #endif
00120   
00121 }
00122 
00123 /* The get_byte() and checkHeader() functions are modified version from */
00124 /* the correpsonding functions that can be found in zlib, the following */
00125 /* copyright notice applies to these functions:                         */
00126 
00127 /* zlib.h -- interface of the 'zlib' general purpose compression library
00128   version 1.1.3, July 9th, 1998
00129 
00130   Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
00131 
00132   This software is provided 'as-is', without any express or implied
00133   warranty.  In no event will the authors be held liable for any damages
00134   arising from the use of this software.
00135 
00136   Permission is granted to anyone to use this software for any purpose,
00137   including commercial applications, and to alter it and redistribute it
00138   freely, subject to the following restrictions:
00139 
00140   1. The origin of this software must not be misrepresented; you must not
00141      claim that you wrote the original software. If you use this software
00142      in a product, an acknowledgment in the product documentation would be
00143      appreciated but is not required.
00144   2. Altered source versions must be plainly marked as such, and must not be
00145      misrepresented as being the original software.
00146   3. This notice may not be removed or altered from any source distribution.
00147 
00148   Jean-loup Gailly        Mark Adler
00149   jloup@gzip.org          madler@alumni.caltech.edu
00150 
00151 
00152   The data format used by the zlib library is described by RFCs (Request for
00153   Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
00154   (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
00155 */
00156 
00157 int
00158 HTTPFilterGZip::get_byte()
00159 {
00160 #ifdef DO_GZIP
00161     if (bEof) return EOF;
00162     if (zstr.avail_in == 0)
00163     {
00164         bEof = true;
00165         return EOF;
00166     }
00167     zstr.avail_in--;
00168     zstr.total_in++;
00169     return *(zstr.next_in)++;
00170 #else 
00171     return 0;
00172 #endif
00173 }
00174 
00175 #ifdef DO_GZIP
00176 
00177 static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
00178 
00179 /* gzip flag byte */
00180 #define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
00181 #define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
00182 #define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
00183 #define ORIG_NAME    0x08 /* bit 3 set: original file name present */
00184 #define COMMENT      0x10 /* bit 4 set: file comment present */
00185 #define RESERVED     0xE0 /* bits 5..7: reserved */
00186 #endif
00187 
00188 // 0 : ok
00189 // 1 : not gzip
00190 // 2 : no header
00191 int
00192 HTTPFilterGZip::checkHeader()
00193 {
00194 #ifdef DO_GZIP
00195     uInt len;
00196     int c;
00197 
00198     /* Check the gzip magic header */
00199     for (len = 0; len < 2; len++) {
00200     c = get_byte();
00201     if (c != gz_magic[len]) {
00202         if (len != 0) 
00203         {
00204            zstr.avail_in++;
00205            zstr.next_in--;
00206         }
00207         if (c != EOF) {
00208         zstr.avail_in++;
00209         zstr.next_in--;
00210         return 1;
00211         }
00212         return 2;
00213     }
00214     }
00215 
00216     int method = get_byte(); /* method byte */
00217     int flags = get_byte(); /* flags byte */
00218 
00219     if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
00220     return bEof ? 2 : 1;
00221     }
00222 
00223     /* Discard time, xflags and OS code: */
00224     for (len = 0; len < 6; len++) (void)get_byte();
00225 
00226     if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
00227     len  =  (uInt)get_byte();
00228     len += ((uInt)get_byte())<<8;
00229     /* len is garbage if EOF but the loop below will quit anyway */
00230     while (len-- != 0 && get_byte() != EOF) ;
00231     }
00232     if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
00233     while ((c = get_byte()) != 0 && c != EOF) ;
00234     }
00235     if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
00236     while ((c = get_byte()) != 0 && c != EOF) ;
00237     }
00238     if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
00239     for (len = 0; len < 2; len++) (void)get_byte();
00240     }
00241     
00242     return bEof ? 2 : 0;
00243 #else
00244     return 0;
00245 #endif
00246 } 
00247 
00248 void 
00249 HTTPFilterGZip::slotInput(const QByteArray &d)
00250 {
00251 #ifdef DO_GZIP
00252   if (bPlainText)
00253   {
00254      emit output(d);
00255      return;
00256   }
00257   if (d.size() == 0)
00258   {
00259      if (bEatTrailer)
00260         bHasFinished = true;
00261      if (!bHasFinished)
00262      {
00263         // Make sure we get the last bytes still in the pipe.
00264         // Needed with "deflate".
00265         QByteArray flush(4);
00266         flush.fill(0);
00267         slotInput(flush);
00268         if (!bHasFinished && !bHasHeader)
00269         {
00270            // Send as-is
00271            emit output(headerData);
00272            bHasFinished = true;
00273            // End of data
00274            emit output(QByteArray());
00275         }
00276      }
00277      if (!bHasFinished)
00278         emit error( KIO::ERR_SLAVE_DEFINED, i18n("Unexpected end of data, some information may be lost."));
00279      return;
00280   }
00281   if (bHasFinished)
00282      return;
00283 
00284   if (bEatTrailer)
00285   {
00286      iTrailer -= d.size();
00287      if (iTrailer <= 0)
00288      {
00289         bHasFinished = true;
00290         // End of data
00291         emit output(QByteArray());
00292      }
00293      return;
00294   }
00295 
00296   if (!bHasHeader)
00297   {
00298      bEof = false;
00299 
00300      // Add data to header.
00301      int orig_size = headerData.size();
00302      headerData.resize(orig_size+d.size());
00303      memcpy(headerData.data()+orig_size, d.data(), d.size());
00304 
00305      zstr.avail_in = headerData.size();
00306      zstr.next_in = (Bytef *) headerData.data();     
00307 
00308      int result = checkHeader();
00309      if (result == 1)
00310      {
00311         bPlainText = true;
00312         output(headerData);
00313         return;
00314      }
00315 
00316      if (result != 0)
00317         return; // next time better
00318 
00319      bHasHeader = true;
00320   }
00321   else
00322   {
00323      zstr.avail_in = d.size();
00324      zstr.next_in = (Bytef *) d.data();
00325   }
00326 
00327   while( zstr.avail_in )
00328   {
00329      char buf[8192];
00330      zstr.next_out = (Bytef *) buf;
00331      zstr.avail_out = 8192;
00332      int result = inflate( &zstr, Z_NO_FLUSH );
00333      if ((result != Z_OK) && (result != Z_STREAM_END))
00334      {
00335         emit error( KIO::ERR_SLAVE_DEFINED, i18n("Receiving corrupt data."));
00336         break;
00337      }
00338      int bytesOut = 8192 - zstr.avail_out;
00339      if (bytesOut)
00340      {
00341         QByteArray d;
00342         d.setRawData( buf, bytesOut );
00343         emit output(d);
00344         d.resetRawData( buf, bytesOut );
00345      }
00346      if (result == Z_STREAM_END)
00347      {
00348         if (iTrailer)
00349         {
00350            bEatTrailer = true;
00351         }
00352         else
00353         {
00354            bHasFinished = true;
00355            // End of data
00356            emit output(QByteArray());
00357         }
00358         return;
00359      }
00360   }  
00361 #endif
00362 }
00363 
00364 HTTPFilterDeflate::HTTPFilterDeflate()
00365 {
00366 #ifdef DO_GZIP
00367   bHasHeader = true;
00368   iTrailer = 0;
00369 #endif
00370 }
00371 
00372 #include "httpfilter.moc"

kio

Skip menu "kio"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal