Beispiel #1
0
int yaz_srw_check_content_type(Z_HTTP_Response *hres)
{
    const char *content_type = z_HTTP_header_lookup(hres->headers,
                                                    "Content-Type");
    if (content_type)
    {
        if (!yaz_strcmp_del("text/xml", content_type, "; "))
            return 1;
        if (!yaz_strcmp_del("application/xml", content_type, "; "))
            return 1;
    }
    return 0;
}
Beispiel #2
0
static void cmd_settings(struct http_channel *c)
{
    struct http_response *rs = c->response;
    struct http_request *rq = c->request;
    struct http_session *s = locate_session(c);
    const char *content_type = http_lookup_header(rq->headers, "Content-Type");

    if (!s)
        return;

    if (rq->content_len && content_type &&
            !yaz_strcmp_del("text/xml", content_type, "; "))
    {
        xmlDoc *doc = xmlParseMemory(rq->content_buf, rq->content_len);
        xmlNode *root_n;
        int ret;
        if (!doc)
        {
            error(rs, PAZPAR2_MALFORMED_SETTING, 0);
            release_session(c,s);
            return;
        }
        root_n = xmlDocGetRootElement(doc);
        ret = settings_read_node_x(root_n, s->psession, apply_local_setting);
        xmlFreeDoc(doc);
        if (ret)
        {
            error(rs, PAZPAR2_MALFORMED_SETTING, 0);
            release_session(c,s);
            return;
        }
    }
    if (process_settings(s->psession, rq, rs) < 0)
    {
        release_session(c, s);
        return;
    }
    response_open(c, "settings");
    response_close(c, "settings");
    release_session(c, s);
}
Beispiel #3
0
struct http_request *http_parse_request(struct http_channel *c,
                                        struct http_buf **queue,
                                        int len)
{
    struct http_request *r = nmem_malloc(c->nmem, sizeof(*r));
    char *p, *p2;
    char *start = nmem_malloc(c->nmem, len+1);
    char *buf = start;

    if (http_buf_read(c->http_server, queue, buf, len) < len)
    {
        yaz_log(YLOG_WARN, "http_buf_read < len (%d)", len);
        return 0;
    }
    r->search = "";
    r->channel = c;
    r->arguments = 0;
    r->headers = 0;
    r->content_buf = 0;
    r->content_len = 0;
    // Parse first line
    for (p = buf, p2 = r->method; *p && *p != ' ' && p - buf < 19; p++)
        *(p2++) = *p;
    if (*p != ' ')
    {
        yaz_log(YLOG_WARN, "Unexpected HTTP method in request");
        return 0;
    }
    *p2 = '\0';

    if (!(buf = strchr(buf, ' ')))
    {
        yaz_log(YLOG_WARN, "Missing Request-URI in HTTP request");
        return 0;
    }
    buf++;
    if (!(p = strchr(buf, ' ')))
    {
        yaz_log(YLOG_WARN, "HTTP Request-URI not terminated (too long?)");
        return 0;
    }
    *(p++) = '\0';
    if ((p2 = strchr(buf, '?'))) // Do we have arguments?
        *(p2++) = '\0';
    r->path = nmem_strdup(c->nmem, buf);
    if (p2)
    {
        r->search = nmem_strdup(c->nmem, p2);
        // Parse Arguments
        http_parse_arguments(r, c->nmem, p2);
    }
    buf = p;

    if (strncmp(buf, "HTTP/", 5))
        strcpy(r->http_version, "1.0");
    else
    {
        size_t skipped;
        buf += 5; // strlen("HTTP/")

        p = (char*) next_crlf(buf, &skipped);
        if (!p || skipped < 3 || skipped > 5)
            return 0;

        memcpy(r->http_version, buf, skipped);
        r->http_version[skipped] = '\0';
        buf = p;
    }
    strcpy(c->version, r->http_version);

    r->headers = 0;
    while (*buf)
    {
        size_t skipped;

        p = (char *) next_crlf(buf, &skipped);
        if (!p)
        {
            return 0;
        }
        else if (skipped == 0)
        {
            buf = p;
            break;
        }
        else
        {
            char *cp;
            char *n_v = nmem_malloc(c->nmem, skipped+1);
            struct http_header *h = nmem_malloc(c->nmem, sizeof(*h));

            memcpy(n_v, buf, skipped);
            n_v[skipped] = '\0';

            if (!(cp = strchr(n_v, ':')))
                return 0;
            h->name = nmem_strdupn(c->nmem, n_v, cp - n_v);
            cp++;
            while (isspace(*cp))
                cp++;
            h->value = nmem_strdup(c->nmem, cp);
            h->next = r->headers;
            r->headers = h;
            buf = p;
        }
    }

    // determine if we do keep alive
    if (!strcmp(c->version, "1.0"))
    {
        const char *v = http_lookup_header(r->headers, "Connection");
        if (v && !strcmp(v, "Keep-Alive"))
            c->keep_alive = 1;
        else
            c->keep_alive = 0;
    }
    else
    {
        const char *v = http_lookup_header(r->headers, "Connection");
        if (v && !strcmp(v, "close"))
            c->keep_alive = 0;
        else
            c->keep_alive = 1;
    }
    if (buf < start + len)
    {
        const char *content_type = http_lookup_header(r->headers,
                                                      "Content-Type");
        r->content_len = start + len - buf;
        r->content_buf = buf;

        if (!yaz_strcmp_del("application/x-www-form-urlencoded",
                            content_type, "; "))
        {
            http_parse_arguments(r, c->nmem, r->content_buf);
        }
    }
    return r;
}
Beispiel #4
0
/**
   http://www.loc.gov/z3950/agency/zing/srw/service.html
*/
int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
                   Z_SOAP **soap_package, ODR decode, char **charset,
                   Z_SRW_diagnostic **diag, int *num_diag)
{
#if YAZ_HAVE_XML2
    static Z_SOAP_Handler soap_handlers[2] = {
        {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
        {0, 0, 0}
    };
#endif
    const char *content_type = z_HTTP_header_lookup(hreq->headers,
                                                    "Content-Type");

    /*
      SRU GET: ignore content type.
      SRU POST: we support "application/x-www-form-urlencoded";
      not  "multipart/form-data" .
    */
    if (!strcmp(hreq->method, "GET")
        ||
        (!strcmp(hreq->method, "POST") && content_type &&
         !yaz_strcmp_del("application/x-www-form-urlencoded",
                         content_type, "; ")))
    {
        char *db = "Default";
        const char *p0 = hreq->path, *p1;
#if YAZ_HAVE_XML2
        const char *operation = 0;
        char *version = 0;
        char *query = 0;
        char *queryType = "cql";
        char *username = 0;
        char *password = 0;
        char *sortKeys = 0;
        char *stylesheet = 0;
        char *scanClause = 0;
        char *recordXPath = 0;
        char *recordSchema = 0;
        char *recordXMLEscaping = 0;
        char *recordPacking = 0;
        char *maximumRecords = 0;
        char *startRecord = 0;
        char *maximumTerms = 0;
        char *responsePosition = 0;
        const char *facetLimit = 0;
        const char *facetStart = 0;
        const char *facetSort = 0;
        Z_SRW_extra_arg *extra_args = 0;
#endif
        char **uri_name;
        char **uri_val;

        grab_charset(decode, content_type, charset);
        if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
            *charset = "UTF-8";

        if (*p0 == '/')
            p0++;
        p1 = strchr(p0, '?');
        if (!p1)
            p1 = p0 + strlen(p0);
        if (p1 != p0)
            db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
        if (!strcmp(hreq->method, "POST"))
            p1 = hreq->content_buf;
        yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
#if YAZ_HAVE_XML2
        if (uri_name)
        {
            int i;
            for (i = 0; uri_name[i]; i++)
            {
                char *n = uri_name[i];
                char *v = uri_val[i];
                if (!strcmp(n, "query"))
                    query = v;
                else if (!strcmp(n, "x-pquery"))
                {
                    query = v;
                    queryType = "pqf";
                }
                else if (!strcmp(n, "queryType"))
                    queryType = v;
                else if (!strcmp(n, "x-username"))
                    username = v;
                else if (!strcmp(n, "x-password"))
                    password = v;
                else if (!strcmp(n, "operation"))
                    operation = v;
                else if (!strcmp(n, "stylesheet"))
                    stylesheet = v;
                else if (!strcmp(n, "sortKeys"))
                    sortKeys = v;
                else if (!strcmp(n, "recordXPath"))
                    recordXPath = v;
                else if (!strcmp(n, "recordSchema"))
                    recordSchema = v;
                else if (!strcmp(n, "recordPacking"))
                    recordPacking = v;
                else if (!strcmp(n, "recordXMLEscaping"))
                    recordXMLEscaping = v;
                else if (!strcmp(n, "version"))
                    version = v;
                else if (!strcmp(n, "scanClause"))
                    scanClause = v;
                else if (!strcmp(n, "x-pScanClause"))
                {
                    scanClause = v;
                    queryType = "pqf";
                }
                else if (!strcmp(n, "maximumRecords"))
                    maximumRecords = v;
                else if (!strcmp(n, "startRecord"))
                    startRecord = v;
                else if (!strcmp(n, "maximumTerms"))
                    maximumTerms = v;
                else if (!strcmp(n, "responsePosition"))
                    responsePosition = v;
                else if (!strcmp(n, "facetLimit"))
                    facetLimit = v;
                else if (!strcmp(n, "facetStart"))
                    facetStart = v;
                else if (!strcmp(n, "facetSort"))
                    facetSort = v;
                else if (!strcmp(n, "extraRequestData"))
                    ; /* ignoring extraRequestData */
                else if (n[0] == 'x' && n[1] == '-')
                {
                    append_extra_arg(decode, &extra_args, n, v);
                }
                else
                {
                    if (*num_diag < 10)
                        yaz_add_srw_diagnostic(decode, diag, num_diag,
                                               YAZ_SRW_UNSUPP_PARAMETER, n);
                }
            }
        }
        if (!operation)
        {
            if (query)
                operation = "searchRetrieve";
            else if (scanClause)
                operation = "scan";
            else
                operation = "explain";
        }
        version = yaz_negotiate_sru_version(version);

        if (!version)
        {   /* negotiation failed. */
            yaz_add_srw_diagnostic(decode, diag, num_diag,
                                   YAZ_SRW_UNSUPP_VERSION, "2.0");
            version = "2.0";
        }
        if (!operation)
        {
            if (uri_name)
                yaz_add_srw_diagnostic(
                    decode, diag, num_diag,
                    YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
            operation = "explain";
        }
        if (strcmp(version, "2.0"))
        {
            if (recordXMLEscaping)
            {
                yaz_add_srw_diagnostic(decode, diag, num_diag,
                                       YAZ_SRW_UNSUPP_PARAMETER,
                                       "recordXMLEscaping");

            }
            recordXMLEscaping = recordPacking;
            recordPacking = "packed";
        }
        if (!recordXMLEscaping)
            recordXMLEscaping = "xml";
        if (!strcmp(operation, "searchRetrieve"))
        {
            Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);

            sr->srw_version = version;
            sr->extra_args = extra_args;
            *srw_pdu = sr;
            yaz_srw_decodeauth(sr, hreq, username, password, decode);

            sr->u.request->queryType = queryType;
            sr->u.request->query = query;

            if (!query)
                yaz_add_srw_diagnostic(
                    decode, diag, num_diag,
                    YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");

            if (sortKeys)
            {
                sr->u.request->sort_type = Z_SRW_sort_type_sort;
                sr->u.request->sort.sortKeys = sortKeys;
            }
            sr->u.request->recordXPath = recordXPath;
            sr->u.request->recordSchema = recordSchema;
            sr->u.request->recordPacking = recordXMLEscaping;
            sr->u.request->packing = recordPacking;
            sr->u.request->stylesheet = stylesheet;
            yaz_sru_facet_request(decode , &sr->u.request->facetList,
                                  &facetLimit, &facetStart, &facetSort);

            yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
                                   &sr->u.request->maximumRecords,
                                   diag, num_diag, 0);

            yaz_sru_decode_integer(decode, "startRecord", startRecord,
                                   &sr->u.request->startRecord,
                                   diag, num_diag, 1);

            sr->u.request->database = db;

            (*soap_package) = (Z_SOAP *)
                odr_malloc(decode, sizeof(**soap_package));
            (*soap_package)->which = Z_SOAP_generic;

            (*soap_package)->u.generic = (Z_SOAP_Generic *)
                odr_malloc(decode, sizeof(*(*soap_package)->u.generic));

            (*soap_package)->u.generic->p = sr;
            (*soap_package)->u.generic->ns = soap_handlers[0].ns;
            (*soap_package)->u.generic->no = 0;

            (*soap_package)->ns = "SRU";

            return 0;
        }
        else if (!strcmp(operation, "explain"))
        {
            /* Transfer SRU explain parameters to common struct */
            /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
            Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);

            sr->srw_version = version;
            sr->extra_args = extra_args;
            yaz_srw_decodeauth(sr, hreq, username, password, decode);
            *srw_pdu = sr;
            sr->u.explain_request->recordPacking = recordXMLEscaping;
            sr->u.explain_request->packing = recordPacking;
            sr->u.explain_request->database = db;

            sr->u.explain_request->stylesheet = stylesheet;

            (*soap_package) = (Z_SOAP *)
                odr_malloc(decode, sizeof(**soap_package));
            (*soap_package)->which = Z_SOAP_generic;

            (*soap_package)->u.generic = (Z_SOAP_Generic *)
                odr_malloc(decode, sizeof(*(*soap_package)->u.generic));

            (*soap_package)->u.generic->p = sr;
            (*soap_package)->u.generic->ns = soap_handlers[0].ns;
            (*soap_package)->u.generic->no = 0;

            (*soap_package)->ns = "SRU";

            return 0;
        }
        else if (!strcmp(operation, "scan"))
        {
            /* Transfer SRU scan parameters to common struct */
            /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
            Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);

            sr->srw_version = version;
            sr->extra_args = extra_args;
            *srw_pdu = sr;
            yaz_srw_decodeauth(sr, hreq, username, password, decode);

            sr->u.scan_request->queryType = queryType;
            sr->u.scan_request->scanClause = scanClause;

            if (!scanClause)
                yaz_add_srw_diagnostic(
                    decode, diag, num_diag,
                    YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
            sr->u.scan_request->database = db;

            yaz_sru_decode_integer(decode, "maximumTerms",
                                   maximumTerms,
                                   &sr->u.scan_request->maximumTerms,
                                   diag, num_diag, 0);

            yaz_sru_decode_integer(decode, "responsePosition",
                                   responsePosition,
                                   &sr->u.scan_request->responsePosition,
                                   diag, num_diag, 0);

            sr->u.scan_request->stylesheet = stylesheet;

            (*soap_package) = (Z_SOAP *)
                odr_malloc(decode, sizeof(**soap_package));
            (*soap_package)->which = Z_SOAP_generic;

            (*soap_package)->u.generic = (Z_SOAP_Generic *)
                odr_malloc(decode, sizeof(*(*soap_package)->u.generic));

            (*soap_package)->u.generic->p = sr;
            (*soap_package)->u.generic->ns = soap_handlers[0].ns;
            (*soap_package)->u.generic->no = 0;

            (*soap_package)->ns = "SRU";

            return 0;
        }
        else
        {
            /* unsupported operation ... */
            /* Act as if we received a explain request and throw diagnostic. */

            Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);

            sr->srw_version = version;
            *srw_pdu = sr;
            sr->u.explain_request->recordPacking = recordPacking;
            sr->u.explain_request->database = db;

            sr->u.explain_request->stylesheet = stylesheet;

            (*soap_package) = (Z_SOAP *)
                odr_malloc(decode, sizeof(**soap_package));
            (*soap_package)->which = Z_SOAP_generic;

            (*soap_package)->u.generic = (Z_SOAP_Generic *)
                odr_malloc(decode, sizeof(*(*soap_package)->u.generic));

            (*soap_package)->u.generic->p = sr;
            (*soap_package)->u.generic->ns = soap_handlers[0].ns;
            (*soap_package)->u.generic->no = 0;

            (*soap_package)->ns = "SRU";

            yaz_add_srw_diagnostic(decode, diag, num_diag,
                                   YAZ_SRW_UNSUPP_OPERATION, operation);
            return 0;
        }
#else
        return 1;
#endif
    }
    return 2;
}
Beispiel #5
0
int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
                   Z_SOAP **soap_package, ODR decode, char **charset)
{
    if (!strcmp(hreq->method, "POST"))
    {
        const char *content_type = z_HTTP_header_lookup(hreq->headers,
                                                        "Content-Type");
        if (content_type &&
            (!yaz_strcmp_del("text/xml", content_type, "; ") ||
             !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
             !yaz_strcmp_del("text/plain", content_type, "; ")))
        {
            char *db = "Default";
            const char *p0 = hreq->path, *p1;
            int ret = -1;

            static Z_SOAP_Handler soap_handlers[5] = {
#if YAZ_HAVE_XML2
                { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
                { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
                { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
                { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec },
#endif
                {0, 0, 0}
            };

            if (*p0 == '/')
                p0++;
            p1 = strchr(p0, '?');
            if (!p1)
                p1 = p0 + strlen(p0);
            if (p1 != p0)
                db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);

            ret = z_soap_codec(decode, soap_package,
                               &hreq->content_buf, &hreq->content_len,
                               soap_handlers);
            if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
            {
                *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
                yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode);

                /* last entry in handlers - SRU 2.0 - is turned into
                   offset 0.. due to other pieces relying on it */
                if ((*soap_package)->u.generic->no == 3)
                    (*soap_package)->u.generic->no = 0;
                if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
                    (*srw_pdu)->u.request->database == 0)
                    (*srw_pdu)->u.request->database = db;

                if ((*srw_pdu)->which == Z_SRW_explain_request &&
                    (*srw_pdu)->u.explain_request->database == 0)
                    (*srw_pdu)->u.explain_request->database = db;

                if ((*srw_pdu)->which == Z_SRW_scan_request &&
                    (*srw_pdu)->u.scan_request->database == 0)
                    (*srw_pdu)->u.scan_request->database = db;

                if ((*srw_pdu)->which == Z_SRW_update_request &&
                    (*srw_pdu)->u.update_request->database == 0)
                    (*srw_pdu)->u.update_request->database = db;

                return 0;
            }
            return 1;
        }
    }
    return 2;
}
Beispiel #6
0
static void cmd_init(struct http_channel *c)
{
    struct http_request *r = c->request;
    const char *clear = http_argbyname(r, "clear");
    const char *content_type = http_lookup_header(r->headers, "Content-Type");
    unsigned int sesid;
    struct http_session *s;
    struct http_response *rs = c->response;
    struct conf_service *service = 0; /* no service (yet) */

    if (r->content_len && content_type &&
            !yaz_strcmp_del("text/xml", content_type, "; "))
    {
        xmlDoc *doc = xmlParseMemory(r->content_buf, r->content_len);
        xmlNode *root_n;
        if (!doc)
        {
            error(rs, PAZPAR2_MALFORMED_SETTING, 0);
            return;
        }
        root_n = xmlDocGetRootElement(doc);
        service = service_create(c->server, root_n);
        xmlFreeDoc(doc);
        if (!service)
        {
            error(rs, PAZPAR2_MALFORMED_SETTING, 0);
            return;
        }
    }

    if (!service)
    {
        const char *service_name = http_argbyname(c->request, "service");
        service = locate_service(c->server, service_name);
        if (!service)
        {
            error(rs, PAZPAR2_NO_SERVICE, service_name ? service_name : "unnamed");
            return;
        }
    }
    sesid = make_sessionid();
    s = http_session_create(service, c->http_sessions, sesid);

    yaz_log(c->http_sessions->log_level, "Session init %u ", sesid);
    if (!clear || *clear == '0')
        session_init_databases(s->psession);
    else
        yaz_log(YLOG_LOG, "Session %u init: No databases preloaded", sesid);

    if (process_settings(s->psession, c->request, c->response) < 0)
        return;

    response_open(c, "init");
    wrbuf_printf(c->wrbuf, "<session>%d", sesid);
    if (c->server->server_id)
    {
        wrbuf_puts(c->wrbuf, ".");
        wrbuf_puts(c->wrbuf, c->server->server_id);
    }
    wrbuf_puts(c->wrbuf, "</session>"
               "<protocol>" PAZPAR2_PROTOCOL_VERSION "</protocol>");

    wrbuf_printf(c->wrbuf, "<keepAlive>%d</keepAlive>\n", 1000 * ((s->psession->service->session_timeout >= 20) ?
                 (s->psession->service->session_timeout - 10) : 50));
    response_close(c, "init");
}