X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fzgdu.c;h=d7d76df9189aa762dd3b2e30090fa1d93d0d82ac;hb=5c3d2d2ab097e4bb59ba5718a396b020a2d302c0;hp=a37a96e7221a32ac6c3b0386e2fb801c34624b87;hpb=c6e47cbbff56f39f6d81b079ebaeac41d793d4d9;p=yaz-moved-to-github.git diff --git a/src/zgdu.c b/src/zgdu.c index a37a96e..d7d76df 100644 --- a/src/zgdu.c +++ b/src/zgdu.c @@ -1,18 +1,31 @@ /* - * Copyright (c) 2002-2003, Index Data. + * Copyright (c) 2002-2004, Index Data. * See the file LICENSE for details. * - * $Id: zgdu.c,v 1.1 2003-10-27 12:21:36 adam Exp $ + * $Id: zgdu.c,v 1.11 2004-10-15 00:19:01 adam Exp $ */ +/** + * \file zgdu.c + * \brief Implements HTTP and Z39.50 encoding and decoding. + */ + +#include #include #include +#include #include +#ifdef WIN32 +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#endif + static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers, char **content_buf, int *content_len) { int i = off; + int chunked = 0; *headers = 0; while (i < o->size-1 && o->buf[i] == '\r') @@ -51,6 +64,10 @@ static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers, memcpy ((*headers)->value, o->buf + po, i - po); (*headers)->value[i - po] = '\0'; + if (!strcasecmp((*headers)->name, "Transfer-Encoding") + && + !strcasecmp((*headers)->value, "chunked")) + chunked = 1; headers = &(*headers)->next; } *headers = 0; @@ -62,22 +79,75 @@ static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers, } i++; - if (i > o->size) - { - o->error = OHTTP; - return 0; - } - else if (i == o->size) + if (chunked) { - *content_buf = 0; - *content_len = 0; + int off = 0; + + /* we know buffer will be smaller than o->size - i*/ + *content_buf = (char*) odr_malloc(o, o->size - i); + + while (1) + { + /* chunk length .. */ + int chunk_len = 0; + for (; i < o->size-2; i++) + if (isdigit(o->buf[i])) + chunk_len = chunk_len * 16 + + (o->buf[i] - '0'); + else if (isupper(o->buf[i])) + chunk_len = chunk_len * 16 + + (o->buf[i] - ('A'-10)); + else if (islower(o->buf[i])) + chunk_len = chunk_len * 16 + + (o->buf[i] - ('a'-10)); + else + break; + /* chunk extension ... */ + while (o->buf[i] != '\r' && o->buf[i+1] != '\n') + { + if (i >= o->size-2) + { + o->error = OHTTP; + return 0; + } + i++; + } + i += 2; /* skip CRLF */ + if (chunk_len == 0) + break; + if (chunk_len < 0 || off + chunk_len > o->size) + { + o->error = OHTTP; + return 0; + } + /* copy chunk .. */ + memcpy (*content_buf + off, o->buf + i, chunk_len); + i += chunk_len + 2; /* skip chunk+CRLF */ + off += chunk_len; + } + if (!off) + *content_buf = 0; + *content_len = off; } - else + else { - *content_len = o->size - i; - *content_buf = (char*) odr_malloc(o, *content_len + 1); - memcpy(*content_buf, o->buf + i, *content_len); - (*content_buf)[*content_len] = '\0'; + if (i > o->size) + { + o->error = OHTTP; + return 0; + } + else if (i == o->size) + { + *content_buf = 0; + *content_len = 0; + } + else + { + *content_len = o->size - i; + *content_buf = (char*) odr_malloc(o, *content_len + 1); + memcpy(*content_buf, o->buf + i, *content_len); + (*content_buf)[*content_len] = '\0'; + } } return 1; } @@ -96,7 +166,7 @@ void z_HTTP_header_add(ODR o, Z_HTTP_Header **hp, const char *n, const char *z_HTTP_header_lookup(Z_HTTP_Header *hp, const char *n) { for (; hp; hp = hp->next) - if (!strcmp(hp->name, n)) + if (!yaz_matchstr(hp->name, n)) return hp->value; return 0; } @@ -187,6 +257,9 @@ int z_GDU (ODR o, Z_GDU **p, int opt, const char *name) hr = (*p)->u.HTTP_Response = (Z_HTTP_Response *) odr_malloc(o, sizeof(*hr)); + hr->content_buf = 0; + hr->content_len = 0; + po = i = 5; while (i < o->size-2 && o->buf[i] != ' ' && o->buf[i] != '\r') i++; @@ -293,11 +366,10 @@ int z_GDU (ODR o, Z_GDU **p, int opt, const char *name) if (!z_HTTP_header_lookup((*p)->u.HTTP_Response->headers, "Content-Length")) { - char lstr[20]; - sprintf(lstr, "%d", (*p)->u.HTTP_Response->content_len); - z_HTTP_header_add(o, - &(*p)->u.HTTP_Response->headers, - "Content-Length", lstr); + char lstr[60]; + sprintf(lstr, "Content-Length: %d\r\n", + (*p)->u.HTTP_Response->content_len); + odr_write(o, (unsigned char *) lstr, strlen(lstr)); } for (h = (*p)->u.HTTP_Response->headers; h; h = h->next) { @@ -313,9 +385,9 @@ int z_GDU (ODR o, Z_GDU **p, int opt, const char *name) (*p)->u.HTTP_Response->content_len); if (o->direction == ODR_PRINT) { - fprintf(o->print, "-- HTTP response:\n%.*s\n", o->top - top0, - o->buf + top0); - fprintf(o->print, "-- \n"); + odr_printf(o, "-- HTTP response:\n%.*s\n", o->top - top0, + o->buf + top0); + odr_printf(o, "-- \n"); } break; case Z_GDU_HTTP_Request: @@ -332,11 +404,10 @@ int z_GDU (ODR o, Z_GDU **p, int opt, const char *name) !z_HTTP_header_lookup((*p)->u.HTTP_Request->headers, "Content-Length")) { - char lstr[20]; - sprintf(lstr, "%d", (*p)->u.HTTP_Request->content_len); - z_HTTP_header_add(o, - &(*p)->u.HTTP_Request->headers, - "Content-Length", lstr); + char lstr[60]; + sprintf(lstr, "Content-Length: %d\r\n", + (*p)->u.HTTP_Request->content_len); + odr_write(o, (unsigned char *) lstr, strlen(lstr)); } for (h = (*p)->u.HTTP_Request->headers; h; h = h->next) { @@ -352,7 +423,9 @@ int z_GDU (ODR o, Z_GDU **p, int opt, const char *name) (*p)->u.HTTP_Request->content_len); if (o->direction == ODR_PRINT) { - fprintf(o->print, "-- HTTP request:\n%.*s\n", o->top, o->buf); + odr_printf(o, "-- HTTP request:\n%.*s\n", o->top - top0, + o->buf + top0); + odr_printf(o, "-- \n"); } break; case Z_GDU_Z3950: