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 "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
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 int method = get_byte();
00216 int flags = get_byte();
00217
00218 if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
00219 return bEof ? 2 : 1;
00220 }
00221
00222
00223 for (len = 0; len < 6; ++len) (void)get_byte();
00224
00225 if ((flags & EXTRA_FIELD) != 0) {
00226 len = (uInt)get_byte();
00227 len += ((uInt)get_byte())<<8;
00228
00229 while (len-- != 0 && get_byte() != EOF) ;
00230 }
00231 if ((flags & ORIG_NAME) != 0) {
00232 while ((c = get_byte()) != 0 && c != EOF) ;
00233 }
00234 if ((flags & COMMENT) != 0) {
00235 while ((c = get_byte()) != 0 && c != EOF) ;
00236 }
00237 if ((flags & HEAD_CRC) != 0) {
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
00263
00264 QByteArray flush(4, 0);
00265 slotInput(flush);
00266 if (!bHasFinished && !bHasHeader)
00267 {
00268
00269 emit output(headerData);
00270 bHasFinished = true;
00271
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
00289 emit output(QByteArray());
00290 }
00291 return;
00292 }
00293
00294 if (!bHasHeader)
00295 {
00296 bEof = false;
00297
00298
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;
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
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"