kio Library API Documentation

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"
KDE Logo
This file is part of the documentation for kio Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Sep 29 09:43:50 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003