X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fhttp.c;h=07005f56166f157354fbdf96ad5e770be50495f1;hp=43e2786f10b321dbda927652aa703dbb555dcd48;hb=fbd98e3ba1435882c6fa121e5dee6648ed295b60;hpb=8ac95eb45804822f698ab98bc6d42c8305eb12f8 diff --git a/src/http.c b/src/http.c index 43e2786..07005f5 100644 --- a/src/http.c +++ b/src/http.c @@ -17,11 +17,6 @@ #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) { @@ -64,9 +59,9 @@ 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") + if (!yaz_strcasecmp((*headers)->name, "Transfer-Encoding") && - !strcasecmp((*headers)->value, "chunked")) + !yaz_strcasecmp((*headers)->value, "chunked")) chunked = 1; headers = &(*headers)->next; if (i < o->size-1 && o->buf[i] == '\r') @@ -191,7 +186,7 @@ void z_HTTP_header_add_basic_auth(ODR o, Z_HTTP_Header **hp, buf = (char *) odr_malloc(o, (len+1) * 8/6 + 12); strcpy(buf, "Basic "); yaz_base64encode(tmp, &buf[strlen(buf)]); - z_HTTP_header_add(o, hp, "Authorization", buf); + z_HTTP_header_set(o, hp, "Authorization", buf); } @@ -206,14 +201,12 @@ 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, +void z_HTTP_header_set(ODR o, Z_HTTP_Header **hp, const char *n, const char *v) { while (*hp) { - if (!strcmp((*hp)->name, n)) + if (!yaz_strcasecmp((*hp)->name, n)) { (*hp)->value = odr_strdup(o, v); return; @@ -225,12 +218,26 @@ static void z_HTTP_header_set(ODR o, Z_HTTP_Header **hp, const char *n, (*hp)->value = odr_strdup(o, v); (*hp)->next = 0; } -#endif + +const char *z_HTTP_header_remove(Z_HTTP_Header **hp, const char *n) +{ + while (*hp) + { + if (!yaz_strcasecmp((*hp)->name, n)) + { + const char *v = (*hp)->value; + *hp = (*hp)->next; + return v; + } + hp = &(*hp)->next; + } + return 0; +} const char *z_HTTP_header_lookup(const Z_HTTP_Header *hp, const char *n) { for (; hp; hp = hp->next) - if (!yaz_matchstr(hp->name, n)) + if (!yaz_strcasecmp(hp->name, n)) return hp->value; return 0; } @@ -331,7 +338,8 @@ Z_GDU *z_get_HTTP_Request_uri(ODR odr, const char *uri, const char *args, return p; } -Z_GDU *z_get_HTTP_Response(ODR o, int code) +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; @@ -344,46 +352,131 @@ Z_GDU *z_get_HTTP_Response(ODR o, int code) 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) { - hres->content_buf = (char*) odr_malloc(o, 400); + const char *http_err = z_HTTP_errmsg(code); + size_t sz = 400 + strlen(http_err) + (details ? + strlen(details) : 0); + hres->content_buf = (char*) odr_malloc(o, sz); sprintf(hres->content_buf, "\n" "\n" " \n" - " YAZ " YAZ_VERSION "\n" + " %s\n" " \n" " \n" - "

YAZ " - YAZ_VERSION "

\n" + "

%s

\n" "

Error: %d

\n" - "

Description: %.50s

\n" + "

Description: %s

\n", server, server_url, server, + code, http_err); + if (details) + { + sprintf(hres->content_buf + strlen(hres->content_buf), + "

Details: %s

\n", details); + } + sprintf(hres->content_buf + strlen(hres->content_buf), " \n" - "\n", - code, z_HTTP_errmsg(code)); + "\n"); hres->content_len = strlen(hres->content_buf); z_HTTP_header_add(o, &hres->headers, "Content-Type", "text/html"); } 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); +} + const char *z_HTTP_errmsg(int code) { - if (code == 200) + switch (code) + { + case 100: + return "Continue"; + case 101: + return "Switching Protocols"; + case 200: return "OK"; - else if (code == 400) + case 201: + return "Created"; + case 202: + return "Accepted"; + case 203: + return "Non-Authoritative Information"; + case 204: + return "No Content"; + case 205: + return "Reset Content"; + case 206: + return "Partial Content"; + case 300: + return "Multiple Choices"; + case 301: + return "Moved Permenently"; + case 302: + return "Found"; + case 303: + return "See Other"; + case 304: + return "Not Modified"; + case 305: + return "Use Proxy"; + case 307: + return "Temporary Redirect"; + case 400: return "Bad Request"; - else if (code == 404) + case 404: return "Not Found"; - else if (code == 405) + case 405: return "Method Not Allowed"; - else if (code == 500) + case 406: + return "Not Acceptable"; + case 407: + return "Proxy Authentication Required"; + case 408: + return "Request Timeout"; + case 409: + return "Conflict"; + case 410: + return "Gone"; + case 411: + return "Length Required"; + case 412: + return "Precondition Failed"; + case 413: + return "Request Entity Too Large"; + case 414: + return "Request-URI Too Long"; + case 415: + return "Unsupported Media Type"; + case 416: + return "Requested Range Not Satisfiable"; + case 417: + return "Expectation Failed"; + case 500: return "Internal Error"; - else + case 501: + return "Not Implemented"; + case 502: + return "Bad Gateway"; + case 503: + return "Service Unavailable"; + case 504: + return "Gateway Timeout"; + case 505: + return "HTTP Version Not Supported"; + default: return "Unknown Error"; + } } int yaz_decode_http_response(ODR o, Z_HTTP_Response **hr_p) @@ -509,21 +602,19 @@ int yaz_encode_http_response(ODR o, Z_HTTP_Response *hr) hr->code, z_HTTP_errmsg(hr->code)); odr_write2(o, sbuf, strlen(sbuf)); - /* apply Content-Length if not already applied */ - if (!z_HTTP_header_lookup(hr->headers, - "Content-Length")) - { - char lstr[60]; - sprintf(lstr, "Content-Length: %d\r\n", - hr->content_len); - odr_write2(o, lstr, strlen(lstr)); - } + /* use content_len for Content-Length */ + sprintf(sbuf, "Content-Length: %d\r\n", hr->content_len); + odr_write2(o, sbuf, strlen(sbuf)); for (h = hr->headers; h; h = h->next) { - 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); + if (yaz_strcasecmp(h->name, "Content-Length") + && yaz_strcasecmp(h->name, "Transfer-Encoding")) + { /* skip Content-Length if given. content_len rules */ + 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)