X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fhttp.c;h=54521b16a2eaeb0adf6ea650103fee034119d987;hp=397b7bdfc5946a84ed64d6b1da6460573a5e535c;hb=766712116d6bb82fd0ef8ab6eff32ea31ac65608;hpb=833bf58328945361db8a744c0dec2c925c97d43a diff --git a/src/http.c b/src/http.c index 397b7bd..54521b1 100644 --- a/src/http.c +++ b/src/http.c @@ -1,5 +1,5 @@ /* This file is part of the YAZ toolkit. - * Copyright (C) 1995-2013 Index Data + * Copyright (C) Index Data * See the file LICENSE for details. */ /** @@ -16,6 +16,7 @@ #include #include #include +#include static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers, char **content_buf, int *content_len) @@ -48,19 +49,14 @@ static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers, break; } *headers = (Z_HTTP_Header *) odr_malloc(o, sizeof(**headers)); - (*headers)->name = (char*) odr_malloc(o, i - po + 1); - memcpy ((*headers)->name, buf + po, i - po); - (*headers)->name[i - po] = '\0'; + (*headers)->name = odr_strdupn(o, buf + po, i - po); i++; while (i < size-1 && buf[i] == ' ') i++; for (po = i; i < size-1 && !strchr("\r\n", buf[i]); i++) ; - (*headers)->value = (char*) odr_malloc(o, i - po + 1); - memcpy ((*headers)->value, buf + po, i - po); - (*headers)->value[i - po] = '\0'; - + (*headers)->value = odr_strdupn(o, buf + po, i - po); if (!yaz_strcasecmp((*headers)->name, "Transfer-Encoding") && !yaz_strcasecmp((*headers)->value, "chunked")) @@ -142,9 +138,7 @@ static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers, else { *content_len = size - i; - *content_buf = (char*) odr_malloc(o, *content_len + 1); - memcpy(*content_buf, buf + i, *content_len); - (*content_buf)[*content_len] = '\0'; + *content_buf = odr_strdupn(o, buf + i, *content_len); } } return 1; @@ -287,11 +281,8 @@ Z_GDU *z_get_HTTP_Request_host_path(ODR odr, 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); + char *h = odr_strdupn(odr, cp0, cp1 - cp0); + z_HTTP_header_add(odr, &p->u.HTTP_Request->headers, "Host", h); } } return p; @@ -314,11 +305,8 @@ Z_GDU *z_get_HTTP_Request_uri(ODR odr, const char *uri, const char *args, 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); + char *h = odr_strdupn(odr, cp0, cp1 - cp0); + z_HTTP_header_add(odr, &p->u.HTTP_Request->headers, "Host", h); } if (!args) @@ -340,7 +328,8 @@ Z_GDU *z_get_HTTP_Request_uri(ODR odr, const char *uri, const char *args, return p; } -Z_GDU *z_get_HTTP_Response_details(ODR o, int code, const char *details) +Z_GDU *z_get_HTTP_Response_server(ODR o, int code, const char *details, + const char *server, const char *server_url) { Z_GDU *p = (Z_GDU *) odr_malloc(o, sizeof(*p)); Z_HTTP_Response *hres; @@ -353,8 +342,7 @@ Z_GDU *z_get_HTTP_Response_details(ODR o, int code, const char *details) hres->content_buf = 0; hres->code = code; hres->version = "1.1"; - z_HTTP_header_add(o, &hres->headers, "Server", - "YAZ/" YAZ_VERSION); + z_HTTP_header_add(o, &hres->headers, "Server", server); if (code != 200) { const char *http_err = z_HTTP_errmsg(code); @@ -366,13 +354,13 @@ Z_GDU *z_get_HTTP_Response_details(ODR o, int code, const char *details) " \"http://www.w3.org/TR/html4/strict.dtd\">\n" "\n" " \n" - " YAZ " YAZ_VERSION "\n" + " %s\n" " \n" " \n" - "

YAZ " - YAZ_VERSION "

\n" + "

%s

\n" "

Error: %d

\n" - "

Description: %s

\n", code, http_err); + "

Description: %s

\n", server, server_url, server, + code, http_err); if (details) { sprintf(hres->content_buf + strlen(hres->content_buf), @@ -387,6 +375,12 @@ Z_GDU *z_get_HTTP_Response_details(ODR o, int code, const char *details) return p; } +Z_GDU *z_get_HTTP_Response_details(ODR o, int code, const char *details) +{ + return z_get_HTTP_Response_server(o, code, details, "YAZ/" YAZ_VERSION, + "http://www.indexdata.com/yaz"); +} + Z_GDU *z_get_HTTP_Response(ODR o, int code) { return z_get_HTTP_Response_details(o, code, 0); @@ -489,10 +483,7 @@ int yaz_decode_http_response(ODR o, Z_HTTP_Response **hr_p) po = i = 5; while (i < size-2 && !strchr(" \r\n", buf[i])) i++; - hr->version = (char *) odr_malloc(o, i - po + 1); - if (i - po) - memcpy(hr->version, buf + po, i - po); - hr->version[i-po] = 0; + hr->version = odr_strdupn(o, buf + po, i - po); if (buf[i] != ' ') { o->error = OHTTP; @@ -517,9 +508,9 @@ int yaz_decode_http_request(ODR o, Z_HTTP_Request **hr_p) Z_HTTP_Request *hr = (Z_HTTP_Request *) odr_malloc(o, sizeof(*hr)); const char *buf = o->op->buf; int size = o->op->size; + int lspace = 0; *hr_p = hr; - /* method .. */ for (i = 0; buf[i] != ' '; i++) if (i >= size-5 || i > 30) @@ -527,35 +518,22 @@ int yaz_decode_http_request(ODR o, Z_HTTP_Request **hr_p) o->error = OHTTP; return 0; } - hr->method = (char *) odr_malloc(o, i+1); - memcpy (hr->method, buf, i); - hr->method[i] = '\0'; - /* path */ - po = i+1; - for (i = po; buf[i] != ' '; i++) - if (i >= size-5) - { - o->error = OHTTP; - return 0; - } - hr->path = (char *) odr_malloc(o, i - po + 1); - memcpy (hr->path, buf+po, i - po); - hr->path[i - po] = '\0'; - /* HTTP version */ - i++; - if (i > size-5 || memcmp(buf+i, "HTTP/", 5)) + hr->method = odr_strdupn(o, buf, i); + po = ++i; + while (i < size && !strchr("\r\n", buf[i])) + { + if (buf[i] == ' ') + lspace = i; + i++; + } + if (!lspace || i >= size || lspace >= size - 5 || + memcmp(buf + lspace + 1, "HTTP/", 5)) { o->error = OHTTP; return 0; } - i+= 5; - po = i; - while (i < size && !strchr("\r\n", buf[i])) - i++; - hr->version = (char *) odr_malloc(o, i - po + 1); - memcpy(hr->version, buf + po, i - po); - hr->version[i - po] = '\0'; - /* headers */ + hr->path = odr_strdupn(o, buf + po, lspace - po); + hr->version = odr_strdupn(o, buf + lspace + 6, i - (lspace + 6)); if (i < size-1 && buf[i] == '\r') i++; if (buf[i] != '\n') @@ -563,29 +541,30 @@ int yaz_decode_http_request(ODR o, Z_HTTP_Request **hr_p) o->error = OHTTP; return 0; } + /* headers */ return decode_headers_content(o, i, &hr->headers, &hr->content_buf, &hr->content_len); } static void dump_http_package(ODR o, const char *buf, size_t len) { - int i; + int i, limit = 8192; for (i = 0; ; i++) { if (i == len) { - odr_printf(o, "%.*s\n", i, buf); + o->op->stream_write(o, o->op->print, ODR_VISIBLESTRING, buf, i); break; } - else if (i > 8192) + else if (i >= limit) { - odr_printf(o, "%.*s\n", i, buf); - odr_printf(o, "(truncated\n", (long) len); + o->op->stream_write(o, o->op->print, ODR_VISIBLESTRING, buf, i); + odr_printf(o, "(truncated from %ld to %d\n", (long) len, i); break; } else if (buf[i] == 0) { - odr_printf(o, "%.*s\n", i, buf); + o->op->stream_write(o, o->op->print, ODR_VISIBLESTRING, buf, i); odr_printf(o, "(binary data)\n", (long) len); break; } @@ -631,11 +610,13 @@ int yaz_encode_http_response(ODR o, Z_HTTP_Response *hr) int yaz_encode_http_request(ODR o, Z_HTTP_Request *hr) { Z_HTTP_Header *h; + char *cp; int top0 = o->op->top; odr_write(o, hr->method, strlen(hr->method)); odr_write(o, " ", 1); - odr_write(o, hr->path, strlen(hr->path)); + cp = strchr(hr->path, '#'); + odr_write(o, hr->path, cp ? (cp - hr->path) : strlen(hr->path)); odr_write(o, " HTTP/", 6); odr_write(o, hr->version, strlen(hr->version)); odr_write(o, "\r\n", 2); @@ -667,6 +648,32 @@ int yaz_encode_http_request(ODR o, Z_HTTP_Request *hr) return 1; } +const char *yaz_check_location(ODR odr, const char *uri, const char *location, + int *host_change) +{ + if (*location == '/') + { /* relative location */ + char *args = 0; + char *nlocation = (char *) odr_malloc(odr, strlen(location) + + strlen(uri) + 3); + strcpy(nlocation, uri); + cs_get_host_args(nlocation, (const char **) &args); + if (!args || !*args) + args = nlocation + strlen(nlocation); + else + args--; + strcpy(args, location); + *host_change = 0; + return nlocation; + } + else + { + /* we don't check if host is the same as before - yet */ + *host_change = 1; + return location; + } +} + /* * Local variables: * c-basic-offset: 4