Z_GDU *z_get_HTTP_Request_host_path(ODR odr, const char *host, const char *path) { Z_GDU *p = z_get_HTTP_Request(odr); p->u.HTTP_Request->path = odr_strdup(odr, path); if (host) { const char *cp0 = strstr(host, "://"); const char *cp1 = 0; if (cp0) cp0 = cp0+3; else cp0 = host; 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); } } return p; }
void z_HTTP_header_add_content_type(ODR o, Z_HTTP_Header **hp, const char *content_type, const char *charset) { const char *l = "Content-Type"; if (charset) { char *ctype = (char *) odr_malloc(o, strlen(content_type)+strlen(charset) + 15); sprintf(ctype, "%s; charset=%s", content_type, charset); z_HTTP_header_add(o, hp, l, ctype); } else z_HTTP_header_add(o, hp, l, content_type); }
void yaz_cookies_request(yaz_cookies_t yc, ODR odr, Z_HTTP_Request *req) { struct cookie *c; size_t sz = 0; for (c = yc->list; c; c = c->next) { if (c->name && c->value) sz += strlen(c->name) + strlen(c->value) + 3; } if (sz) { char *buf = odr_malloc(odr, sz + 1); *buf = '\0'; for (c = yc->list; c; c = c->next) { if (*buf) strcat(buf, "; "); strcat(buf, c->name); strcat(buf, "="); strcat(buf, c->value); } z_HTTP_header_add(odr, &req->headers, "Cookie", buf); } }
Z_GDU *z_get_HTTP_Response(ODR o, int code) { Z_GDU *p = (Z_GDU *) odr_malloc(o, sizeof(*p)); Z_HTTP_Response *hres; p->which = Z_GDU_HTTP_Response; p->u.HTTP_Response = (Z_HTTP_Response *) odr_malloc(o, sizeof(*hres)); hres = p->u.HTTP_Response; hres->headers = 0; hres->content_len = 0; hres->content_buf = 0; hres->code = code; hres->version = "1.1"; z_HTTP_header_add(o, &hres->headers, "Server", "YAZ/" YAZ_VERSION); if (code != 200) { hres->content_buf = (char*) odr_malloc(o, 400); sprintf(hres->content_buf, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"" " \"http://www.w3.org/TR/html4/strict.dtd\">\n" "<HTML>\n" " <HEAD>\n" " <TITLE>YAZ " YAZ_VERSION "</TITLE>\n" " </HEAD>\n" " <BODY>\n" " <P><A HREF=\"http://www.indexdata.com/yaz/\">YAZ</A> " YAZ_VERSION "</P>\n" " <P>Error: %d</P>\n" " <P>Description: %.50s</P>\n" " </BODY>\n" "</HTML>\n", code, z_HTTP_errmsg(code)); 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_Request(ODR o) { Z_GDU *p = (Z_GDU *) odr_malloc(o, sizeof(*p)); Z_HTTP_Request *hreq; p->which = Z_GDU_HTTP_Request; p->u.HTTP_Request = (Z_HTTP_Request *) odr_malloc(o, sizeof(*hreq)); hreq = p->u.HTTP_Request; hreq->headers = 0; hreq->content_len = 0; hreq->content_buf = 0; hreq->version = "1.1"; hreq->method = "POST"; hreq->path = "/"; z_HTTP_header_add(o, &hreq->headers, "User-Agent", "YAZ/" YAZ_VERSION); return p; }
/* * HTTP Basic authentication is described at: * http://tools.ietf.org/html/rfc1945#section-11.1 */ void z_HTTP_header_add_basic_auth(ODR o, Z_HTTP_Header **hp, const char *username, const char *password) { char *tmp, *buf; int len; if (username == 0) return; if (password == 0) password = ""; len = strlen(username) + strlen(password); tmp = (char *) odr_malloc(o, len+2); sprintf(tmp, "%s:%s", username, password); 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_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; }
int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu, ODR odr, const char *charset) { Z_SOAP_Handler handlers[3] = { #if YAZ_HAVE_XML2 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec}, {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec}, #endif {0, 0, 0} }; Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p)); z_HTTP_header_add_basic_auth(odr, &hreq->headers, srw_pdu->username, srw_pdu->password); z_HTTP_header_add_content_type(odr, &hreq->headers, "text/xml", 0 /* no charset in MIME */); z_HTTP_header_add(odr, &hreq->headers, "SOAPAction", "\"\""); p->which = Z_SOAP_generic; p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic)); p->u.generic->no = 0; p->u.generic->ns = 0; p->u.generic->p = srw_pdu; p->ns = "http://schemas.xmlsoap.org/soap/envelope/"; #if YAZ_HAVE_XML2 if (srw_pdu->which == Z_SRW_update_request || srw_pdu->which == Z_SRW_update_response) p->u.generic->no = 1; /* second handler */ #endif return z_soap_codec_enc(odr, &p, &hreq->content_buf, &hreq->content_len, handlers, charset); }
Z_HTTP_Response *yaz_url_exec(yaz_url_t p, const char *uri, const char *method, Z_HTTP_Header *user_headers, const char *buf, size_t len) { Z_HTTP_Response *res = 0; int number_of_redirects = 0; yaz_cookies_reset(p->cookies); wrbuf_rewind(p->w_error); while (1) { void *add; COMSTACK conn = 0; int code; const char *location = 0; char *http_user = 0; char *http_pass = 0; char *uri_lean = 0; Z_GDU *gdu; extract_user_pass(p->odr_out->mem, uri, &uri_lean, &http_user, &http_pass); gdu = z_get_HTTP_Request_uri(p->odr_out, uri_lean, 0, p->proxy ? 1 : 0); gdu->u.HTTP_Request->method = odr_strdup(p->odr_out, method); yaz_cookies_request(p->cookies, p->odr_out, gdu->u.HTTP_Request); for ( ; user_headers; user_headers = user_headers->next) { /* prefer new Host over user-supplied Host */ if (!strcmp(user_headers->name, "Host")) ; /* prefer user-supplied User-Agent over YAZ' own */ else if (!strcmp(user_headers->name, "User-Agent")) z_HTTP_header_set(p->odr_out, &gdu->u.HTTP_Request->headers, user_headers->name, user_headers->value); else z_HTTP_header_add(p->odr_out, &gdu->u.HTTP_Request->headers, user_headers->name, user_headers->value); } if (http_user && http_pass) z_HTTP_header_add_basic_auth(p->odr_out, &gdu->u.HTTP_Request->headers, http_user, http_pass); res = 0; if (buf && len) { gdu->u.HTTP_Request->content_buf = (char *) buf; gdu->u.HTTP_Request->content_len = len; } if (!z_GDU(p->odr_out, &gdu, 0, 0)) { wrbuf_printf(p->w_error, "Can not encode HTTP request for URL %s", uri); log_warn(p); return 0; } conn = cs_create_host_proxy(uri_lean, 1, &add, p->proxy); if (!conn) { wrbuf_printf(p->w_error, "Can not resolve URL %s", uri); log_warn(p); } else if (cs_connect(conn, add) < 0) { wrbuf_printf(p->w_error, "Can not connect to URL %s", uri); log_warn(p); } else { int len; char *buf = odr_getbuf(p->odr_out, &len, 0); if (p->verbose) fwrite(buf, 1, len, stdout); if (cs_put(conn, buf, len) < 0) { wrbuf_printf(p->w_error, "cs_put fail for URL %s", uri); log_warn(p); } else { char *netbuffer = 0; int netlen = 0; int cs_res = cs_get(conn, &netbuffer, &netlen); if (cs_res <= 0) { wrbuf_printf(p->w_error, "cs_get failed for URL %s", uri); log_warn(p); } else { Z_GDU *gdu; if (p->verbose) fwrite(netbuffer, 1, cs_res, stdout); odr_setbuf(p->odr_in, netbuffer, cs_res, 0); if (!z_GDU(p->odr_in, &gdu, 0, 0) || gdu->which != Z_GDU_HTTP_Response) { wrbuf_printf(p->w_error, "HTTP decoding fail for " "URL %s", uri); log_warn(p); } else { res = gdu->u.HTTP_Response; } } xfree(netbuffer); } } if (conn) cs_close(conn); if (!res) break; code = res->code; location = z_HTTP_header_lookup(res->headers, "Location"); if (++number_of_redirects <= p->max_redirects && location && (code == 301 || code == 302 || code == 307)) { int host_change = 0; const char *nlocation = yaz_check_location(p->odr_in, uri, location, &host_change); odr_reset(p->odr_out); uri = odr_strdup(p->odr_out, nlocation); } else break; yaz_cookies_response(p->cookies, res); odr_reset(p->odr_in); } return res; }