• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • 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 "httpfilter.h"
00021 
00022 #include <kio/global.h>
00023 
00024 #include <klocale.h>
00025 
00026 #include <stdio.h>
00027 
00028 HTTPFilterBase::HTTPFilterBase()
00029  : last(0)
00030 {
00031 }
00032 
00033 HTTPFilterBase::~HTTPFilterBase()
00034 {
00035    delete last;
00036 }
00037 
00038 void
00039 HTTPFilterBase::chain(HTTPFilterBase *previous)
00040 {
00041    last = previous;
00042    connect(last, SIGNAL(output(const QByteArray &)),
00043            this, SLOT(slotInput(const QByteArray &)));
00044 }
00045 
00046 HTTPFilterChain::HTTPFilterChain()
00047  : first(0)
00048 {
00049 }
00050 
00051 void
00052 HTTPFilterChain::addFilter(HTTPFilterBase *filter)
00053 {
00054    if (!last)
00055    {
00056       first = filter;
00057    }
00058    else
00059    {
00060       disconnect(last, SIGNAL(output(const QByteArray &)), 0, 0);
00061       filter->chain(last);
00062    }
00063    last = filter;
00064    connect(filter, SIGNAL(output(const QByteArray &)),
00065            this, SIGNAL(output(const QByteArray &)));
00066    connect(filter, SIGNAL(error(int, const QString &)),
00067            this, SIGNAL(error(int, const QString &)));
00068 }
00069 
00070 void
00071 HTTPFilterChain::slotInput(const QByteArray &d)
00072 {
00073    if (first)
00074       first->slotInput(d);
00075    else
00076       emit output(d);      
00077 }
00078 
00079 HTTPFilterMD5::HTTPFilterMD5()
00080 {
00081 }
00082 
00083 QString 
00084 HTTPFilterMD5::md5()
00085 {
00086    return QLatin1String(context.base64Digest());
00087 }
00088 
00089 void 
00090 HTTPFilterMD5::slotInput(const QByteArray &d)
00091 {
00092    context.update(d);
00093    emit output(d);
00094 }
00095 
00096 
00097 HTTPFilterGZip::HTTPFilterGZip()
00098 {
00099 #ifdef DO_GZIP
00100   bHasHeader = false;
00101   bHasFinished = false;
00102   bPlainText = false;
00103   bEatTrailer = false;
00104   bEof = false;
00105   zstr.next_in = (Bytef *) Z_NULL;
00106   zstr.avail_in = 0;
00107   zstr.zalloc = Z_NULL;
00108   zstr.zfree = Z_NULL;
00109   zstr.opaque = Z_NULL;
00110   inflateInit2(&zstr, -MAX_WBITS);
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     int method = get_byte(); /* method byte */
00216     int flags = get_byte(); /* flags byte */
00217 
00218     if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
00219     return bEof ? 2 : 1;
00220     }
00221 
00222     /* Discard time, xflags and OS code: */
00223     for (len = 0; len < 6; ++len) (void)get_byte();
00224 
00225     if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
00226     len  =  (uInt)get_byte();
00227     len += ((uInt)get_byte())<<8;
00228     /* len is garbage if EOF but the loop below will quit anyway */
00229     while (len-- != 0 && get_byte() != EOF) ;
00230     }
00231     if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
00232     while ((c = get_byte()) != 0 && c != EOF) ;
00233     }
00234     if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
00235     while ((c = get_byte()) != 0 && c != EOF) ;
00236     }
00237     if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
00238     for (len = 0; len < 2; ++len) (void)get_byte();
00239     }
00240     
00241     return bEof ? 2 : 0;
00242 #else
00243     return 0;
00244 #endif
00245 } 
00246 
00247 void 
00248 HTTPFilterGZip::slotInput(const QByteArray &d)
00249 {
00250 #ifdef DO_GZIP
00251   if (bPlainText)
00252   {
00253      emit output(d);
00254      return;
00255   }
00256   if (d.size() == 0)
00257   {
00258      if (bEatTrailer)
00259         bHasFinished = true;
00260      if (!bHasFinished)
00261      {
00262         // Make sure we get the last bytes still in the pipe.
00263         // Needed with "deflate".
00264         QByteArray flush(4, 0);
00265         slotInput(flush);
00266         if (!bHasFinished && !bHasHeader)
00267         {
00268            // Send as-is
00269            emit output(headerData);
00270            bHasFinished = true;
00271            // End of data
00272            emit output(QByteArray());
00273         }
00274      }
00275      if (!bHasFinished)
00276         emit error( KIO::ERR_SLAVE_DEFINED, i18n("Unexpected end of data, some information may be lost."));
00277      return;
00278   }
00279   if (bHasFinished)
00280      return;
00281 
00282   if (bEatTrailer)
00283   {
00284      iTrailer -= d.size();
00285      if (iTrailer <= 0)
00286      {
00287         bHasFinished = true;
00288         // End of data
00289         emit output(QByteArray());
00290      }
00291      return;
00292   }
00293 
00294   if (!bHasHeader)
00295   {
00296      bEof = false;
00297 
00298      // Add data to header.
00299      int orig_size = headerData.size();
00300      headerData.resize(orig_size+d.size());
00301      memcpy(headerData.data()+orig_size, d.data(), d.size());
00302 
00303      zstr.avail_in = headerData.size();
00304      zstr.next_in = (Bytef *) headerData.data();     
00305 
00306      int result = checkHeader();
00307      if (result == 1)
00308      {
00309         bPlainText = true;
00310         output(headerData);
00311         return;
00312      }
00313 
00314      if (result != 0)
00315         return; // next time better
00316 
00317      bHasHeader = true;
00318   }
00319   else
00320   {
00321      zstr.avail_in = d.size();
00322      zstr.next_in = (Bytef *) d.data();
00323   }
00324 
00325   while( zstr.avail_in )
00326   {
00327      char buf[8192];
00328      zstr.next_out = (Bytef *) buf;
00329      zstr.avail_out = 8192;
00330      int result = inflate( &zstr, Z_NO_FLUSH );
00331      if ((result != Z_OK) && (result != Z_STREAM_END))
00332      {
00333         emit error( KIO::ERR_SLAVE_DEFINED, i18n("Receiving corrupt data."));
00334         break;
00335      }
00336      int bytesOut = 8192 - zstr.avail_out;
00337      if (bytesOut)
00338      {
00339         QByteArray d( buf, bytesOut );
00340         emit output(d);
00341      }
00342      if (result == Z_STREAM_END)
00343      {
00344         if (iTrailer)
00345         {
00346            bEatTrailer = true;
00347         }
00348         else
00349         {
00350            bHasFinished = true;
00351            // End of data
00352            emit output(QByteArray());
00353         }
00354         return;
00355      }
00356   }  
00357 #endif
00358 }
00359 
00360 HTTPFilterDeflate::HTTPFilterDeflate()
00361 {
00362 #ifdef DO_GZIP
00363   bHasHeader = true;
00364   iTrailer = 0;
00365 #endif
00366 }
00367 
00368 #include "httpfilter.moc"

KIO

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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