httpfilter.cc
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
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 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00137 
00138 
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
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}; 
00176 
00177 
00178 #define ASCII_FLAG   0x01 
00179 #define HEAD_CRC     0x02 
00180 #define EXTRA_FIELD  0x04 
00181 #define ORIG_NAME    0x08 
00182 #define COMMENT      0x10 
00183 #define RESERVED     0xE0 
00184 #endif
00185 
00186 
00187 
00188 
00189 int
00190 HTTPFilterGZip::checkHeader()
00191 {
00192 #ifdef DO_GZIP
00193     uInt len;
00194     int c;
00195 
00196     
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(); 
00214     int flags = get_byte(); 
00215 
00216     if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
00217     return bEof ? 2 : 1;
00218     }
00219 
00220     
00221     for (len = 0; len < 6; len++) (void)get_byte();
00222 
00223     if ((flags & EXTRA_FIELD) != 0) { 
00224     len  =  (uInt)get_byte();
00225     len += ((uInt)get_byte())<<8;
00226     
00227     while (len-- != 0 && get_byte() != EOF) ;
00228     }
00229     if ((flags & ORIG_NAME) != 0) { 
00230     while ((c = get_byte()) != 0 && c != EOF) ;
00231     }
00232     if ((flags & COMMENT) != 0) {   
00233     while ((c = get_byte()) != 0 && c != EOF) ;
00234     }
00235     if ((flags & HEAD_CRC) != 0) {  
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         
00261         
00262         QByteArray flush(4);
00263         flush.fill(0);
00264         slotInput(flush);
00265         if (!bHasFinished && !bHasHeader)
00266         {
00267            
00268            emit output(headerData);
00269            bHasFinished = true;
00270            
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         
00288         emit output(QByteArray());
00289      }
00290      return;
00291   }
00292 
00293   if (!bHasHeader)
00294   {
00295      bEof = false;
00296 
00297      
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; 
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            
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.2.0.