X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fhttp.c;h=43e2786f10b321dbda927652aa703dbb555dcd48;hp=4362c757a85d305bdf8ac67406a36808d2259572;hb=8ac95eb45804822f698ab98bc6d42c8305eb12f8;hpb=88d3bedf772316f87e1996f655ccf8d1e2589755 diff --git a/src/http.c b/src/http.c index 4362c75..43e2786 100644 --- a/src/http.c +++ b/src/http.c @@ -1,75 +1,26 @@ /* This file is part of the YAZ toolkit. - * Copyright (C) 1995-2010 Index Data + * Copyright (C) 1995-2013 Index Data * See the file LICENSE for details. */ - /** * \file http.c * \brief Implements HTTP decoding */ +#if HAVE_CONFIG_H +#include +#endif -#include #include #include #include #include #include +#include #ifdef WIN32 #define strncasecmp _strnicmp #define strcasecmp _stricmp #endif - - -/* - * This function's counterpart, yaz_base64decode(), is in srwutil.c. - * I feel bad that they're not together, but each function is only - * needed in one place, and those places are not together. Maybe one - * day we'll move them into a new httputil.c, and declare them in a - * corresponding httputil.h - */ -static void yaz_base64encode(const char *in, char *out) -{ - static char encoding[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - unsigned char buf[3]; - long n; - - while (*in != 0) { - char *pad = 0; - buf[0] = in[0]; - buf[1] = in[1]; - if (in[1] == 0) { - buf[2] = 0; - pad = "=="; - } else { - buf[2] = in[2]; - if (in[2] == 0) - pad = "="; - } - - /* Treat three eight-bit numbers as on 24-bit number */ - n = (buf[0] << 16) + (buf[1] << 8) + buf[2]; - - /* Write the six-bit chunks out as four encoded characters */ - *out++ = encoding[(n >> 18) & 63]; - *out++ = encoding[(n >> 12) & 63]; - if (in[1] != 0) - *out++ = encoding[(n >> 6) & 63]; - if (in[1] != 0 && in[2] != 0) - *out++ = encoding[n & 63]; - - if (pad != 0) { - while (*pad != 0) - *out++ = *pad++; - break; - } - in += 3; - } - - *out++ = 0; -} - static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers, char **content_buf, int *content_len) @@ -108,11 +59,11 @@ static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers, i++; for (po = i; i < o->size-1 && !strchr("\r\n", o->buf[i]); i++) ; - + (*headers)->value = (char*) odr_malloc(o, i - po + 1); memcpy ((*headers)->value, o->buf + po, i - po); (*headers)->value[i - po] = '\0'; - + if (!strcasecmp((*headers)->name, "Transfer-Encoding") && !strcasecmp((*headers)->value, "chunked")) @@ -132,23 +83,23 @@ static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers, if (chunked) { int off = 0; - + /* we know buffer will be smaller than o->size - i*/ - *content_buf = (char*) odr_malloc(o, 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 + + if (yaz_isdigit(o->buf[i])) + chunk_len = chunk_len * 16 + (o->buf[i] - '0'); - else if (isupper(o->buf[i])) - chunk_len = chunk_len * 16 + + else if (yaz_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 + + else if (yaz_islower(o->buf[i])) + chunk_len = chunk_len * 16 + (o->buf[i] - ('a'-10)); else break; @@ -191,7 +142,7 @@ static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers, *content_buf = 0; *content_len = 0; } - else + else { *content_len = o->size - i; *content_buf = (char*) odr_malloc(o, *content_len + 1); @@ -231,6 +182,8 @@ void z_HTTP_header_add_basic_auth(ODR o, Z_HTTP_Header **hp, if (username == 0) return; + if (password == 0) + password = ""; len = strlen(username) + strlen(password); tmp = (char *) odr_malloc(o, len+2); @@ -253,6 +206,27 @@ void z_HTTP_header_add(ODR o, Z_HTTP_Header **hp, const char *n, (*hp)->next = 0; } +#if 0 +/* not in use yet */ +static void z_HTTP_header_set(ODR o, Z_HTTP_Header **hp, const char *n, + const char *v) +{ + while (*hp) + { + if (!strcmp((*hp)->name, n)) + { + (*hp)->value = odr_strdup(o, v); + return; + } + hp = &(*hp)->next; + } + *hp = (Z_HTTP_Header *) odr_malloc(o, sizeof(**hp)); + (*hp)->name = odr_strdup(o, n); + (*hp)->value = odr_strdup(o, v); + (*hp)->next = 0; +} +#endif + const char *z_HTTP_header_lookup(const Z_HTTP_Header *hp, const char *n) { for (; hp; hp = hp->next) @@ -314,6 +288,48 @@ Z_GDU *z_get_HTTP_Request_host_path(ODR odr, return p; } +Z_GDU *z_get_HTTP_Request_uri(ODR odr, const char *uri, const char *args, + int use_full_uri) +{ + Z_GDU *p = z_get_HTTP_Request(odr); + const char *cp0 = strstr(uri, "://"); + const char *cp1 = 0; + if (cp0) + cp0 = cp0+3; + else + cp0 = uri; + + cp1 = strchr(cp0, '/'); + if (!cp1) + cp1 = cp0+strlen(cp0); + + if (cp0 && cp1) + { + char *h = (char*) odr_malloc(odr, cp1 - cp0 + 1); + memcpy (h, cp0, cp1 - cp0); + h[cp1-cp0] = '\0'; + z_HTTP_header_add(odr, &p->u.HTTP_Request->headers, + "Host", h); + } + + if (!args) + { + if (*cp1) + args = cp1 + 1; + else + args = ""; + } + p->u.HTTP_Request->path = odr_malloc(odr, cp1 - uri + strlen(args) + 2); + if (use_full_uri) + { + memcpy(p->u.HTTP_Request->path, uri, cp1 - uri); + strcpy(p->u.HTTP_Request->path + (cp1 - uri), "/"); + } + else + strcpy(p->u.HTTP_Request->path, "/"); + strcat(p->u.HTTP_Request->path, args); + return p; +} Z_GDU *z_get_HTTP_Response(ODR o, int code) { @@ -333,7 +349,7 @@ Z_GDU *z_get_HTTP_Response(ODR o, int code) if (code != 200) { hres->content_buf = (char*) odr_malloc(o, 400); - sprintf(hres->content_buf, + sprintf(hres->content_buf, "\n" "\n" @@ -341,7 +357,7 @@ Z_GDU *z_get_HTTP_Response(ODR o, int code) " YAZ " YAZ_VERSION "\n" " \n" " \n" - "

YAZ " + "

YAZ " YAZ_VERSION "

\n" "

Error: %d

\n" "

Description: %.50s

\n" @@ -374,11 +390,11 @@ int yaz_decode_http_response(ODR o, Z_HTTP_Response **hr_p) { int i, po; Z_HTTP_Response *hr = (Z_HTTP_Response *) odr_malloc(o, sizeof(*hr)); - + *hr_p = hr; hr->content_buf = 0; hr->content_len = 0; - + po = i = 5; while (i < o->size-2 && !strchr(" \r\n", o->buf[i])) i++; @@ -401,16 +417,16 @@ int yaz_decode_http_response(ODR o, Z_HTTP_Response **hr_p) while (i < o->size-1 && o->buf[i] != '\n') i++; return decode_headers_content(o, i, &hr->headers, - &hr->content_buf, &hr->content_len); + &hr->content_buf, &hr->content_len); } int yaz_decode_http_request(ODR o, Z_HTTP_Request **hr_p) { int i, po; Z_HTTP_Request *hr = (Z_HTTP_Request *) odr_malloc(o, sizeof(*hr)); - + *hr_p = hr; - + /* method .. */ for (i = 0; o->buf[i] != ' '; i++) if (i >= o->size-5 || i > 30) @@ -458,6 +474,31 @@ int yaz_decode_http_request(ODR o, Z_HTTP_Request **hr_p) &hr->content_buf, &hr->content_len); } +static void dump_http_package(ODR o, const char *buf, size_t len) +{ + int i; + for (i = 0; ; i++) + { + if (i == len) + { + odr_printf(o, "%.*s\n", i, buf); + break; + } + else if (i > 8192) + { + odr_printf(o, "%.*s\n", i, buf); + odr_printf(o, "(truncated\n", (long) len); + break; + } + else if (buf[i] == 0) + { + odr_printf(o, "%.*s\n", i, buf); + odr_printf(o, "(binary data)\n", (long) len); + break; + } + } +} + int yaz_encode_http_response(ODR o, Z_HTTP_Response *hr) { char sbuf[80]; @@ -467,7 +508,7 @@ int yaz_encode_http_response(ODR o, Z_HTTP_Response *hr) sprintf(sbuf, "HTTP/%s %d %s\r\n", hr->version, hr->code, z_HTTP_errmsg(hr->code)); - odr_write(o, (unsigned char *) sbuf, strlen(sbuf)); + odr_write2(o, sbuf, strlen(sbuf)); /* apply Content-Length if not already applied */ if (!z_HTTP_header_lookup(hr->headers, "Content-Length")) @@ -475,25 +516,23 @@ int yaz_encode_http_response(ODR o, Z_HTTP_Response *hr) char lstr[60]; sprintf(lstr, "Content-Length: %d\r\n", hr->content_len); - odr_write(o, (unsigned char *) lstr, strlen(lstr)); + odr_write2(o, lstr, strlen(lstr)); } for (h = hr->headers; h; h = h->next) { - odr_write(o, (unsigned char *) h->name, strlen(h->name)); - odr_write(o, (unsigned char *) ": ", 2); - odr_write(o, (unsigned char *) h->value, strlen(h->value)); - odr_write(o, (unsigned char *) "\r\n", 2); + odr_write2(o, h->name, strlen(h->name)); + odr_write2(o, ": ", 2); + odr_write2(o, h->value, strlen(h->value)); + odr_write2(o, "\r\n", 2); } odr_write(o, (unsigned char *) "\r\n", 2); if (hr->content_buf) - odr_write(o, (unsigned char *) - hr->content_buf, - hr->content_len); + odr_write2(o, hr->content_buf, hr->content_len); if (o->direction == ODR_PRINT) { - odr_printf(o, "-- HTTP response:\n%.*s\n", o->top - top0, - o->buf + top0); - odr_printf(o, "-- \n"); + odr_printf(o, "-- HTTP response:\n"); + dump_http_package(o, (const char *) o->buf + top0, o->top - top0); + odr_printf(o, "--\n"); } return 1; } @@ -503,15 +542,12 @@ int yaz_encode_http_request(ODR o, Z_HTTP_Request *hr) Z_HTTP_Header *h; int top0 = o->top; - odr_write(o, (unsigned char *) hr->method, - strlen(hr->method)); - odr_write(o, (unsigned char *) " ", 1); - odr_write(o, (unsigned char *) hr->path, - strlen(hr->path)); - odr_write(o, (unsigned char *) " HTTP/", 6); - odr_write(o, (unsigned char *) hr->version, - strlen(hr->version)); - odr_write(o, (unsigned char *) "\r\n", 2); + odr_write2(o, hr->method, strlen(hr->method)); + odr_write2(o, " ", 1); + odr_write2(o, hr->path, strlen(hr->path)); + odr_write2(o, " HTTP/", 6); + odr_write2(o, hr->version, strlen(hr->version)); + odr_write2(o, "\r\n", 2); if (hr->content_len && !z_HTTP_header_lookup(hr->headers, "Content-Length")) @@ -519,25 +555,23 @@ int yaz_encode_http_request(ODR o, Z_HTTP_Request *hr) char lstr[60]; sprintf(lstr, "Content-Length: %d\r\n", hr->content_len); - odr_write(o, (unsigned char *) lstr, strlen(lstr)); + odr_write2(o, lstr, strlen(lstr)); } for (h = hr->headers; h; h = h->next) { - odr_write(o, (unsigned char *) h->name, strlen(h->name)); - odr_write(o, (unsigned char *) ": ", 2); - odr_write(o, (unsigned char *) h->value, strlen(h->value)); - odr_write(o, (unsigned char *) "\r\n", 2); + odr_write2(o, h->name, strlen(h->name)); + odr_write2(o, ": ", 2); + odr_write2(o, h->value, strlen(h->value)); + odr_write2(o, "\r\n", 2); } - odr_write(o, (unsigned char *) "\r\n", 2); + odr_write2(o, "\r\n", 2); if (hr->content_buf) - odr_write(o, (unsigned char *) - hr->content_buf, - hr->content_len); + odr_write2(o, hr->content_buf, hr->content_len); if (o->direction == ODR_PRINT) { - odr_printf(o, "-- HTTP request:\n%.*s\n", o->top - top0, - o->buf + top0); - odr_printf(o, "-- \n"); + odr_printf(o, "-- HTTP request:\n"); + dump_http_package(o, (const char *) o->buf + top0, o->top - top0); + odr_printf(o, "--\n"); } return 1; }