kio
httpfilter.cc
Go to the documentation of this file.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
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
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
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};
00178
00179
00180 #define ASCII_FLAG 0x01
00181 #define HEAD_CRC 0x02
00182 #define EXTRA_FIELD 0x04
00183 #define ORIG_NAME 0x08
00184 #define COMMENT 0x10
00185 #define RESERVED 0xE0
00186 #endif
00187
00188
00189
00190
00191 int
00192 HTTPFilterGZip::checkHeader()
00193 {
00194 #ifdef DO_GZIP
00195 uInt len;
00196 int c;
00197
00198
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();
00217 int flags = get_byte();
00218
00219 if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
00220 return bEof ? 2 : 1;
00221 }
00222
00223
00224 for (len = 0; len < 6; len++) (void)get_byte();
00225
00226 if ((flags & EXTRA_FIELD) != 0) {
00227 len = (uInt)get_byte();
00228 len += ((uInt)get_byte())<<8;
00229
00230 while (len-- != 0 && get_byte() != EOF) ;
00231 }
00232 if ((flags & ORIG_NAME) != 0) {
00233 while ((c = get_byte()) != 0 && c != EOF) ;
00234 }
00235 if ((flags & COMMENT) != 0) {
00236 while ((c = get_byte()) != 0 && c != EOF) ;
00237 }
00238 if ((flags & HEAD_CRC) != 0) {
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
00264
00265 QByteArray flush(4);
00266 flush.fill(0);
00267 slotInput(flush);
00268 if (!bHasFinished && !bHasHeader)
00269 {
00270
00271 emit output(headerData);
00272 bHasFinished = true;
00273
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
00291 emit output(QByteArray());
00292 }
00293 return;
00294 }
00295
00296 if (!bHasHeader)
00297 {
00298 bEof = false;
00299
00300
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;
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
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"