* ChunkedEncoding.{h,cc}: fixed the bug that if chunk data is binary,

decoding did not work properly.
pull/1/head
Tatsuhiro Tsujikawa 2006-03-09 14:52:07 +00:00
parent 2a1b2c8ab4
commit a59301bef0
3 changed files with 43 additions and 30 deletions

View File

@ -1,3 +1,8 @@
2006-03-09 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
* ChunkedEncoding.{h,cc}: fixed the bug that if chunk data is binary,
decoding did not work properly.
2006-03-07 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com> 2006-03-07 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
* DownloadEngine.h: included sys/time.h * DownloadEngine.h: included sys/time.h

View File

@ -31,7 +31,7 @@
ChunkedEncoding::ChunkedEncoding() { ChunkedEncoding::ChunkedEncoding() {
strbufSize = 4096; strbufSize = 4096;
strbuf = new char[strbufSize]; strbuf = new char[strbufSize];
strbuf[0] = '\0'; strbufTail = strbuf;
state = READ_SIZE; state = READ_SIZE;
chunkSize = 0; chunkSize = 0;
} }
@ -76,21 +76,21 @@ void ChunkedEncoding::inflate(char* outbuf, int& outlen, const char* inbuf, int
} else { } else {
break; break;
} }
// Was all bytes in strbuf examined? // all bytes in strbuf were examined?
if(strbuf+strlen(strbuf) <= p) { if(strbufTail <= p) {
break; break;
} }
} }
if(strbuf+strlen(strbuf) <= p) { if(strbufTail <= p) {
// make strbuf NULL-string strbufTail = strbuf;
strbuf[0] = '\0';
} else { } else {
// copy string between [p, strbuf+strlen(strbuf)+1], +1 is for NULL // copy string between [p, strbufTail]
// character. int unreadSize = strbufTail-p;
char* temp = new char[strbufSize]; char* temp = new char[strbufSize];
memcpy(temp, p, strbuf+strlen(strbuf)-p+1); memcpy(temp, p, unreadSize);
delete [] strbuf; delete [] strbuf;
strbuf = temp; strbuf = temp;
strbufTail = strbuf+unreadSize;
} }
outlen = clen; outlen = clen;
} }
@ -103,8 +103,8 @@ int ChunkedEncoding::readData(char** pp, char* buf, int& len, int maxlen) {
return readDataEOL(pp); return readDataEOL(pp);
} }
int wsize; int wsize;
if(strlen(*pp) < (unsigned long int)chunkSize) { if(strbufTail-*pp < chunkSize) {
wsize = strlen(*pp) <= (unsigned int)maxlen-len ? strlen(*pp) : maxlen-len; wsize = strbufTail-*pp <= maxlen-len ? strbufTail-*pp : maxlen-len;
} else { } else {
wsize = chunkSize <= maxlen-len ? chunkSize : maxlen-len; wsize = chunkSize <= maxlen-len ? chunkSize : maxlen-len;
} }
@ -112,7 +112,6 @@ int ChunkedEncoding::readData(char** pp, char* buf, int& len, int maxlen) {
chunkSize -= wsize; chunkSize -= wsize;
len += wsize; len += wsize;
*pp += wsize; *pp += wsize;
if(chunkSize == 0) { if(chunkSize == 0) {
return readDataEOL(pp); return readDataEOL(pp);
} else { } else {
@ -121,54 +120,62 @@ int ChunkedEncoding::readData(char** pp, char* buf, int& len, int maxlen) {
} }
int ChunkedEncoding::readDataEOL(char** pp) { int ChunkedEncoding::readDataEOL(char** pp) {
if(strstr(*pp, "\r\n") == *pp) { char* np = (char*)memchr(*pp, '\n', strbufTail-*pp);
char* rp = (char*)memchr(*pp, '\r', strbufTail-*pp);
if(np != NULL && rp != NULL && np-rp == 1 && *pp == rp) {
*pp += 2; *pp += 2;
return 0; return 0;
} else if(strlen(*pp) < 2) { } else if(strbufTail-*pp < 2) {
return -1; return -1;
} else { } else {
throw new DlAbortEx(EX_INVALID_CHUNK_SIZE); throw new DlAbortEx(EX_INVALID_CHUNK_SIZE);
} }
} }
// strbuf is NULL terminated string, and inlen is strlen(strbuf).
// therefore, strbuf[inlen] = '\0'
int ChunkedEncoding::readChunkSize(char** pp) { int ChunkedEncoding::readChunkSize(char** pp) {
// we read chunk-size from *pp // we read chunk-size from *pp
char* p = strstr(*pp, "\r\n"); char* p;
// \r\n is not found. Return -1 char* np = (char*)memchr(*pp, '\n', strbufTail-*pp);
if(p == NULL) { char* rp = (char*)memchr(*pp, '\r', strbufTail-*pp);
if(np == NULL || rp == NULL || np-rp != 1) {
// \r\n is not found. Return -1
return -1; return -1;
} }
p = rp;
// We ignore chunk-extension // We ignore chunk-extension
char* exsp = index(*pp, ';'); char* exsp = (char*)memchr(*pp, ';', strbufTail-*pp);
if(exsp == NULL) { if(exsp == NULL) {
exsp = p; exsp = p;
} }
// TODO check invalid characters in buffer // TODO check invalid characters in buffer
chunkSize = strtol(*pp, NULL, 16); char* temp = new char[exsp-*pp+1];
memcpy(temp, *pp, exsp-*pp);
temp[exsp-*pp] = '\0';
chunkSize = strtol(temp, NULL, 16);
if(chunkSize < 0) { if(chunkSize < 0) {
throw new DlAbortEx(EX_INVALID_CHUNK_SIZE); throw new DlAbortEx(EX_INVALID_CHUNK_SIZE);
} else if(errno == ERANGE && (chunkSize == LONG_MAX || chunkSize == LONG_MIN)) { } else if(errno == ERANGE && (chunkSize == LONG_MAX || chunkSize == LONG_MIN)) {
throw new DlAbortEx(strerror(errno)); throw new DlAbortEx(strerror(errno));
} }
*pp = p+2; *pp = p+2;
return 0; return 0;
} }
void ChunkedEncoding::addBuffer(const char* inbuf, int inlen) { void ChunkedEncoding::addBuffer(const char* inbuf, int inlen) {
if(strlen(strbuf)+inlen >= (unsigned int)strbufSize) { int realbufSize = strbufTail-strbuf;
if(strlen(strbuf)+inlen+1 > MAX_BUFSIZE) { if(realbufSize+inlen >= strbufSize) {
throw new DlAbortEx(EX_TOO_LARGE_CHUNK, strlen(strbuf)+inlen+1); if(realbufSize+inlen > MAX_BUFSIZE) {
throw new DlAbortEx(EX_TOO_LARGE_CHUNK, realbufSize+inlen);
} }
strbufSize = strlen(strbuf)+inlen+1; strbufSize = realbufSize+inlen;
char* temp = new char[strbufSize]; char* temp = new char[strbufSize];
memcpy(temp, strbuf, strlen(strbuf)+1); memcpy(temp, strbuf, realbufSize);
delete [] strbuf; delete [] strbuf;
strbuf = temp; strbuf = temp;
strbufTail = strbuf+realbufSize;
} }
int origlen = strlen(strbuf); memcpy(strbufTail, inbuf, inlen);
memcpy(strbuf+origlen, inbuf, inlen); strbufTail += inlen;
strbuf[origlen+inlen] = '\0';
} }

View File

@ -35,6 +35,7 @@ private:
int state; int state;
char* strbuf; char* strbuf;
int strbufSize; int strbufSize;
char* strbufTail;
int readChunkSize(char** pp); int readChunkSize(char** pp);
int readData(char** pp, char* buf, int& len, int maxlen); int readData(char** pp, char* buf, int& len, int maxlen);