?? httpconnection.cpp.svn-base
字號:
}
// gzip /////////////////////////////////////////////////////////////////////
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define RESERVED 0xE0 /* bits 5..7: reserved */
static unsigned gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
int CHttpConnection::CheckGzipHeader(unsigned char *iStr, BOOL *rs) {
LOG0(5, "CHttpConnection::CheckGzipHeader()");
enum { GZIP_INIT = 0, GZIP_OS, GZIP_EXTRA0, GZIP_EXTRA1, GZIP_EXTRA2, GZIP_ORIG, GZIP_COMMENT, GZIP_CRC };
char c;
int mSkipCount = 0, mFlags = 0, hMode = GZIP_INIT, mLen = 0;
*rs = TRUE;
int streamLen = 0;
DWORD read;
BOOL mCheckHeaderDone = FALSE;
while (!mCheckHeaderDone) {
if (streamLen == 0) {
if (!ReceiveBlock(iStr, CHUNK, &read)) {
*rs = FALSE;
return 0;
}
streamLen = read;
}
switch (hMode) {
case GZIP_INIT:
c = *iStr++;
streamLen--;
if (mSkipCount == 0 && ((unsigned) c & 0377) != gz_magic[0]) {
*rs = FALSE;
return 0;
}
if (mSkipCount == 1 && ((unsigned)c & 0377) != gz_magic[1]) {
*rs = FALSE;
return 0;
}
if (mSkipCount == 2 && ((unsigned)c & 0377) != Z_DEFLATED) {
*rs = FALSE;
return 0;
}
mSkipCount++;
if (mSkipCount == 4) {
mFlags = (unsigned) c & 0377;
if (mFlags & RESERVED) {
*rs = FALSE;
return 0;
}
hMode = GZIP_OS;
mSkipCount = 0;
}
break;
case GZIP_OS:
c = *iStr++;
streamLen--;
mSkipCount++;
if (mSkipCount == 6)
hMode = GZIP_EXTRA0;
break;
case GZIP_EXTRA0:
if (mFlags & EXTRA_FIELD) {
c = *iStr++;
streamLen--;
mLen = (uInt) c & 0377;
hMode = GZIP_EXTRA1;
}
else
hMode = GZIP_ORIG;
break;
case GZIP_EXTRA1:
c = *iStr++;
streamLen--;
mLen = ((uInt) c & 0377) << 8;
mSkipCount = 0;
hMode = GZIP_EXTRA2;
break;
case GZIP_EXTRA2:
if (mSkipCount == mLen)
hMode = GZIP_ORIG;
else {
c = *iStr++;
streamLen--;
mSkipCount++;
}
break;
case GZIP_ORIG:
if (mFlags & ORIG_NAME) {
c = *iStr++;
streamLen--;
if (c == 0)
hMode = GZIP_COMMENT;
}
else
hMode = GZIP_COMMENT;
break;
case GZIP_COMMENT:
if (mFlags & GZIP_COMMENT) {
c = *iStr++;
streamLen--;
if (c == 0) {
hMode = GZIP_CRC;
mSkipCount = 0;
}
}
else {
hMode = GZIP_CRC;
mSkipCount = 0;
}
break;
case GZIP_CRC:
if (mFlags & HEAD_CRC) {
c = *iStr++;
streamLen--;
mSkipCount++;
if (mSkipCount == 2) {
mCheckHeaderDone = TRUE;
return read - streamLen;
}
}
else {
mCheckHeaderDone = TRUE;
return read - streamLen;
}
break;
} // switch
} // while
return read - streamLen;
}
BOOL CHttpConnection::ReceiveResponseBodyCompressed(CBufferedFile &file, EContentEncoding contentEnc) {
LOG1(5, "CHttpConnection::ReceiveResponseBodyCompressed(, %d)", contentEnc);
BOOL mDummyStreamInitialised = FALSE;
int ret;
unsigned have;
z_stream strm;
unsigned char in[CHUNK];
unsigned char out[CHUNK];
// allocate inflate state
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
int hdrLen = 0;
if (contentEnc == CONTENT_ENCODING_GZIP) {
BOOL rv;
hdrLen = CheckGzipHeader(in, &rv);
if (!rv)
return FALSE;
if (inflateInit2(&strm, -15) != Z_OK)
return FALSE;
strm.next_in = in + hdrLen;
strm.avail_in = (uInt) CHUNK - hdrLen;
}
else {
// deflate
if (inflateInit(&strm) != Z_OK)
return FALSE;
strm.avail_in = 0;
strm.next_in = Z_NULL;
}
DWORD read;
// decompress until deflate stream ends or end of file
do {
if (strm.avail_in == 0) {
if (!ReceiveBlock(in, CHUNK, &read)) {
(void) inflateEnd(&strm);
return FALSE;
}
strm.avail_in = read;
if (strm.avail_in == 0) {
break;
}
strm.next_in = in;
}
// run inflate() on input until output buffer not full
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
if (ret == Z_DATA_ERROR) {
unsigned char *org_next_in = strm.next_in;
uInt org_avail_in = strm.avail_in;
// this is taken from firefox source code
//
// some servers (notably Apache with mod_deflate) don't generate zlib headers
// insert a dummy header and try again
static char dummy_head[2] = {
0x8 + 0x7 * 0x10,
(((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
};
inflateReset(&strm);
strm.next_in = (Bytef*) dummy_head;
strm.avail_in = sizeof(dummy_head);
ret = inflate(&strm, Z_NO_FLUSH);
if (ret != Z_OK)
return FALSE;
// stop an endless loop caused by non-deflate data being labelled as deflate
if (mDummyStreamInitialised) {
// endless loop detected
return FALSE;
}
mDummyStreamInitialised = TRUE;
// reset stream pointers to our original data
strm.next_in = org_next_in;
strm.avail_in = org_avail_in;
}
else if (ret == Z_MEM_ERROR) {
(void) inflateEnd(&strm);
return FALSE;
}
else if (ret == Z_OK || ret == Z_STREAM_END) {
have = CHUNK - strm.avail_out;
DWORD written;
if (!file.Write(out, have, &written) || written != have) {
(void) inflateEnd(&strm);
return FALSE;
}
}
} while (strm.avail_out == 0);
// done when inflate() says it's done
} while (ret != Z_STREAM_END);
// clean up and return
(void) inflateEnd(&strm);
return ret == Z_STREAM_END ? TRUE : FALSE;
}
BOOL CHttpConnection::GetFile(CHttpResponse *res, const CString &fileName) {
LOG0(5, "CHttpConnection::GetFile()");
BOOL ret = FALSE;
SysError = 0;
// check response headers
// Content-Encoding header
EContentEncoding contentEncoding;
CString sContentEncoding;
if (res->GetHeader(_T("Content-Encoding"), sContentEncoding)) {
if (sContentEncoding.Compare(_T("gzip")) == 0)
contentEncoding = CONTENT_ENCODING_GZIP;
else if (sContentEncoding.Compare(_T("deflate")) == 0)
contentEncoding = CONTENT_ENCODING_DEFLATE;
else
contentEncoding = CONTENT_ENCODING_PLAIN;
}
else
contentEncoding = CONTENT_ENCODING_PLAIN;
// find Transfer-Encoding: chunked
ChunkedTransfer = FALSE;
CString sTransferEncoding;
if (res->GetHeader(_T("Transfer-Encoding"), sTransferEncoding) &&
sTransferEncoding.Compare(_T("chunked")) == 0) {
ChunkedTransfer = TRUE;
ChunkRemain = 0;
}
CString sContentLength;
ResponseBodySize = 0;
ResponseBodyDownloaded = 0;
if (res->GetHeader(_T("Content-Range"), sContentLength)) {
DWORD end;
swscanf(sContentLength, _T("bytes %d-%d/%d"), &ResponseBodyDownloaded, &end, &ResponseBodySize);
}
else if (res->GetHeader(_T("Content-Length"), sContentLength)) {
swscanf(sContentLength, _T("%d"), &ResponseBodySize);
}
BOOL append = res->GetStatusCode() == HTTP_STATUS_PARTIAL_CONTENT;
// get file
CBufferedFile file;
DWORD dwCreationDispostion = append ? OPEN_EXISTING : CREATE_ALWAYS;
if (file.Create(fileName, GENERIC_WRITE, FILE_SHARE_READ, dwCreationDispostion, FILE_ATTRIBUTE_NORMAL)) {
if (append) file.Seek(0, FILE_END);
switch (contentEncoding) {
case CONTENT_ENCODING_GZIP:
case CONTENT_ENCODING_DEFLATE:
ret = ReceiveResponseBodyCompressed(file, contentEncoding);
break;
default:
ret = ReceiveResponseBodyPlain(file);
break;
}
if (!ret) SysError = GetLastError();
file.Close();
}
else {
SysError = GetLastError();
}
return ret;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -