X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fcomstack.c;h=db3b00291098e30e97534219ae8dd06d424a7e0b;hp=12b52182e10310d53fc39b70b969f8297cb833c6;hb=3822378d7b75625b8b879025b22bffeb5483b788;hpb=32687c1504015e0675d49983707576f8db9b7bfc diff --git a/src/comstack.c b/src/comstack.c index 12b5218..db3b002 100644 --- a/src/comstack.c +++ b/src/comstack.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 1995-2006, Index Data ApS + * Copyright (C) 1995-2007, Index Data ApS * See the file LICENSE for details. * - * $Id: comstack.c,v 1.16 2006-08-24 13:25:45 adam Exp $ + * $Id: comstack.c,v 1.18 2007-01-11 10:30:41 adam Exp $ */ /** @@ -146,148 +146,180 @@ int cs_look (COMSTACK cs) return cs->event; } -#define CHUNK_DEBUG 0 -int cs_complete_auto(const unsigned char *buf, int len) +static int skip_crlf(const char *buf, int len, int *i) { - if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f - && buf[1] >= 0x20 && buf[1] < 0x7f - && buf[2] >= 0x20 && buf[2] < 0x7f) + if (*i < len) { - /* deal with HTTP request/response */ - int i = 2, content_len = 0, chunked = 0; + if (buf[*i] == '\r' && *i < len-1 && buf[*i + 1] == '\n') + { + (*i) += 2; + return 1; + } + else if (buf[*i] == '\n') + { + (*i)++; + return 1; + } + } + return 0; +} - /* if dealing with HTTP responses - then default - content length is unlimited (socket close) */ - if (!memcmp(buf, "HTTP/", 5)) - content_len = -1; +#define CHUNK_DEBUG 0 - while (i <= len-4) +int cs_complete_http(const char *buf, int len) +{ + /* deal with HTTP request/response */ + int i = 2, content_len = 0, chunked = 0; + + if (len < 6) + return 0; + + /* if dealing with HTTP responses - then default + content length is unlimited (socket close) */ + if (!memcmp(buf, "HTTP/", 5)) + content_len = -1; + +#if 0 + printf("len = %d\n", len); + fwrite (buf, 1, len, stdout); + printf("----------\n"); +#endif + while (i <= len-2) + { + if (i > 8192) { - if (i > 8192) - { - return i; /* do not allow more than 8K HTTP header */ - } - if (buf[i] == '\r' && buf[i+1] == '\n') + return i; /* do not allow more than 8K HTTP header */ + } + if (skip_crlf(buf, len, &i)) + { + if (skip_crlf(buf, len, &i)) { - i += 2; - if (buf[i] == '\r' && buf[i+1] == '\n') - { - if (chunked) - { - /* inside chunked body .. */ - while(1) - { - int j, chunk_len = 0; - i += 2; + /* inside content */ + if (chunked) + { + /* inside chunked body .. */ + while(1) + { + int chunk_len = 0; #if CHUNK_DEBUG -/* debugging */ - if (i >>\n"); - } + if (i < len-2) + { + printf ("\n<<<"); + int j; + for (j = i; j <= i+3; j++) + printf ("%c", buf[j]); + printf (">>>\n"); + } #endif - /* read chunk length */ - while (1) - if (i >= len-2) { + /* read chunk length */ + while (1) + if (i >= len-2) { #if CHUNK_DEBUG -/* debugging */ - printf ("XXXXXXXX not there yet 1\n"); - printf ("i=%d len=%d\n", i, len); + printf ("returning incomplete read at 1\n"); + printf ("i=%d len=%d\n", i, len); #endif - return 0; - } else if (isdigit(buf[i])) - chunk_len = chunk_len * 16 + - (buf[i++] - '0'); - else if (isupper(buf[i])) - chunk_len = chunk_len * 16 + - (buf[i++] - ('A'-10)); - else if (islower(buf[i])) - chunk_len = chunk_len * 16 + - (buf[i++] - ('a'-10)); - else - break; - /* move forward until CRLF - skip chunk ext */ - j = 0; - while (buf[i] != '\r' && buf[i+1] != '\n') - { - if (i >= len-2) - return 0; /* need more buffer .. */ - if (++j > 1000) - return i; /* enough.. stop */ - i++; - } - /* got CRLF */ -#if CHUNK_DEBUG - printf ("XXXXXX chunk_len=%d\n", chunk_len); -#endif - if (chunk_len < 0) - return i+2; /* bad chunk_len */ - if (chunk_len == 0) + return 0; + } else if (isdigit(buf[i])) + chunk_len = chunk_len * 16 + + (buf[i++] - '0'); + else if (isupper(buf[i])) + chunk_len = chunk_len * 16 + + (buf[i++] - ('A'-10)); + else if (islower(buf[i])) + chunk_len = chunk_len * 16 + + (buf[i++] - ('a'-10)); + else break; - i += chunk_len+2; - } - /* consider trailing headers .. */ - while(i <= len-4) + if (chunk_len == 0) + break; + if (chunk_len < 0) + return i; + + while (1) { - if (buf[i] == '\r' && buf[i+1] == '\n' && - buf[i+2] == '\r' && buf[i+3] == '\n') - if (len >= i+4) - return i+4; + if (i >= len -1) + return 0; + if (skip_crlf(buf, len, &i)) + break; i++; } + /* got CRLF */ #if CHUNK_DEBUG -/* debugging */ - printf ("XXXXXXXXX not there yet 2\n"); - printf ("i=%d len=%d\n", i, len); -#endif - return 0; + printf ("chunk_len=%d\n", chunk_len); +#endif + i += chunk_len; + if (i >= len-2) + return 0; + if (!skip_crlf(buf, len, &i)) + return 0; } - else - { /* not chunked ; inside body */ - /* i += 2 seems not to work with GCC -O2 .. - so i+2 is used instead .. */ - if (content_len == -1) - return 0; /* no content length */ - else if (len >= (i+2)+ content_len) + /* consider trailing headers .. */ + while (i < len) + { + if (skip_crlf(buf, len, &i)) { - return (i+2)+ content_len; + if (skip_crlf(buf, len, &i)) + return i; } + else + i++; } - break; - } - else if (i < len - 20 && - !strncasecmp((const char *) buf+i, "Transfer-Encoding:", 18)) - { - i+=18; - while (buf[i] == ' ') - i++; - if (i < len - 8) - if (!strncasecmp((const char *) buf+i, "chunked", 7)) - chunked = 1; - } - else if (i < len - 17 && - !strncasecmp((const char *)buf+i, "Content-Length:", 15)) - { - i+= 15; - while (buf[i] == ' ') - i++; - content_len = 0; - while (i <= len-4 && isdigit(buf[i])) - content_len = content_len*10 + (buf[i++] - '0'); - if (content_len < 0) /* prevent negative offsets */ - content_len = 0; +#if CHUNK_DEBUG + printf ("returning incomplete read at 2\n"); + printf ("i=%d len=%d\n", i, len); +#endif + return 0; } else + { /* not chunked ; inside body */ + if (content_len == -1) + return 0; /* no content length */ + else if (len >= i + content_len) + { + return i + content_len; + } + } + break; + } + else if (i < len - 20 && + !strncasecmp((const char *) buf+i, "Transfer-Encoding:", 18)) + { + i+=18; + while (buf[i] == ' ') + i++; + if (i < len - 8) + if (!strncasecmp((const char *) buf+i, "chunked", 7)) + chunked = 1; + } + else if (i < len - 17 && + !strncasecmp((const char *)buf+i, "Content-Length:", 15)) + { + i+= 15; + while (buf[i] == ' ') i++; + content_len = 0; + while (i <= len-4 && isdigit(buf[i])) + content_len = content_len*10 + (buf[i++] - '0'); + if (content_len < 0) /* prevent negative offsets */ + content_len = 0; } else i++; } - return 0; + else + i++; + } + return 0; +} + +int cs_complete_auto(const unsigned char *buf, int len) +{ + if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f + && buf[1] >= 0x20 && buf[1] < 0x7f + && buf[2] >= 0x20 && buf[2] < 0x7f) + { + int r = cs_complete_http((const char *) buf, len); + return r; } return completeBER(buf, len); }