X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fseshigh.c;h=22df1a80d83ae3ad48209115cbe74e72e6a58acb;hp=e307b629949509052affc0279eb864045ff0aa8b;hb=a6af2d19dddb0c2ef961d087d8ca0f2b3bda8f7a;hpb=bd203324142f86a236b9867e10102abe14b7c676 diff --git a/src/seshigh.c b/src/seshigh.c index e307b62..22df1a8 100644 --- a/src/seshigh.c +++ b/src/seshigh.c @@ -2,7 +2,7 @@ * Copyright (C) 1995-2005, Index Data ApS * See the file LICENSE for details. * - * $Id: seshigh.c,v 1.60 2005-08-30 20:13:51 adam Exp $ + * $Id: seshigh.c,v 1.69 2006-03-15 13:32:05 adam Exp $ */ /** * \file seshigh.c @@ -60,10 +60,12 @@ #include #include "eventl.h" #include "session.h" +#include "mime.h" #include #include #include #include +#include #include #include #include @@ -243,6 +245,7 @@ static void do_close_req(association *a, int reason, char *message, request_release(req); yaz_log(log_requestdetail, "v2 client. No Close PDU"); iochan_setevent(a->client_chan, EVENT_TIMEOUT); /* force imm close */ + a->cs_put_mask = 0; } a->state = ASSOC_DEAD; } @@ -473,6 +476,7 @@ static void assoc_init_reset(association *assoc) assoc->init->bend_fetch = NULL; assoc->init->bend_explain = NULL; assoc->init->bend_srw_scan = NULL; + assoc->init->bend_srw_update = NULL; assoc->init->charneg_request = NULL; assoc->init->charneg_response = NULL; @@ -722,7 +726,8 @@ static void srw_bend_search(association *assoc, request *req, rr.basenames = &srw_req->database; rr.referenceId = 0; rr.srw_sortKeys = 0; - + rr.srw_setname = 0; + rr.srw_setnameIdleTime = 0; rr.query = (Z_Query *) odr_malloc (assoc->decode, sizeof(*rr.query)); rr.query->u.type_1 = 0; @@ -827,6 +832,13 @@ static void srw_bend_search(association *assoc, request *req, start, number, rr.hits); srw_res->numberOfRecords = odr_intdup(assoc->encode, rr.hits); + if (rr.srw_setname) + { + srw_res->resultSetId = + odr_strdup(assoc->encode, rr.srw_setname ); + srw_res->resultSetIdleTime = + odr_intdup(assoc->encode, *rr.srw_setnameIdleTime ); + } if (number > 0) { int i; @@ -843,18 +855,27 @@ static void srw_bend_search(association *assoc, request *req, int packing = Z_SRW_recordPacking_string; if (start + number > rr.hits) number = rr.hits - start + 1; - if (srw_req->recordPacking && - !strcmp(srw_req->recordPacking, "xml")) - packing = Z_SRW_recordPacking_XML; + if (srw_req->recordPacking){ + if (!strcmp(srw_req->recordPacking, "xml")) + packing = Z_SRW_recordPacking_XML; + if (!strcmp(srw_req->recordPacking, "url")) + packing = Z_SRW_recordPacking_URL; + } srw_res->records = (Z_SRW_record *) odr_malloc(assoc->encode, number * sizeof(*srw_res->records)); + + srw_res->extra_records = (Z_SRW_extra_record **) + odr_malloc(assoc->encode, + number*sizeof(*srw_res->extra_records)); + for (i = 0; irecords[j].recordPacking = packing; srw_res->records[j].recordData_buf = 0; + srw_res->extra_records[j] = 0; yaz_log(YLOG_DEBUG, "srw_bend_fetch %d", i+start); errcode = srw_bend_fetch(assoc, i+start, srw_req, srw_res->records + j); @@ -980,9 +1001,13 @@ static void srw_bend_explain(association *assoc, request *req, if (rr.explain_buf) { int packing = Z_SRW_recordPacking_string; - if (srw_req->recordPacking && - !strcmp(srw_req->recordPacking, "xml")) - packing = Z_SRW_recordPacking_XML; + if (srw_req->recordPacking) + { + if (!strcmp(srw_req->recordPacking, "xml")) + packing = Z_SRW_recordPacking_XML; + else if (!strcmp(srw_req->recordPacking, "url")) + packing = Z_SRW_recordPacking_URL; + } srw_res->record.recordSchema = rr.schema; srw_res->record.recordPacking = packing; srw_res->record.recordData_buf = rr.explain_buf; @@ -1063,37 +1088,35 @@ static void srw_bend_scan(association *assoc, request *req, (*assoc->init->bend_scan))(assoc->backend, bsrr); } else if (srw_req->query_type == Z_SRW_query_type_cql - && assoc->init->bend_srw_scan) + && assoc->init->bend_scan && assoc->cql_transform) { - if (assoc->cql_transform) - { - int srw_error; - bsrr->scanClause = 0; - bsrr->attributeset = VAL_NONE; - bsrr->term = odr_malloc(assoc->decode, sizeof(*bsrr->term)); - srw_error = cql2pqf_scan(assoc->encode, - srw_req->scanClause.cql, - assoc->cql_transform, - bsrr->term); - if (srw_error) - yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, - &srw_res->num_diagnostics, - srw_error, 0); - else - { - ((int (*)(void *, bend_scan_rr *)) - (*assoc->init->bend_scan))(assoc->backend, bsrr); - } - } + int srw_error; + bsrr->scanClause = 0; + bsrr->attributeset = VAL_NONE; + bsrr->term = odr_malloc(assoc->decode, sizeof(*bsrr->term)); + srw_error = cql2pqf_scan(assoc->encode, + srw_req->scanClause.cql, + assoc->cql_transform, + bsrr->term); + if (srw_error) + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + srw_error, 0); else { - bsrr->term = 0; - bsrr->attributeset = VAL_NONE; - bsrr->scanClause = srw_req->scanClause.cql; ((int (*)(void *, bend_scan_rr *)) - (*assoc->init->bend_srw_scan))(assoc->backend, bsrr); + (*assoc->init->bend_scan))(assoc->backend, bsrr); } } + else if (srw_req->query_type == Z_SRW_query_type_cql + && assoc->init->bend_srw_scan) + { + bsrr->term = 0; + bsrr->attributeset = VAL_NONE; + bsrr->scanClause = srw_req->scanClause.cql; + ((int (*)(void *, bend_scan_rr *)) + (*assoc->init->bend_srw_scan))(assoc->backend, bsrr); + } else { yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, @@ -1179,6 +1202,213 @@ static void srw_bend_scan(association *assoc, request *req, } +static void srw_bend_update(association *assoc, request *req, + Z_SRW_updateRequest *srw_req, + Z_SRW_updateResponse *srw_res, + int *http_code) +{ + yaz_log(YLOG_DEBUG, "Got SRW UpdateRequest"); + yaz_log(YLOG_DEBUG, "num_diag = %d", srw_res->num_diagnostics ); + *http_code = 404; + srw_bend_init(assoc, &srw_res->diagnostics, &srw_res->num_diagnostics); + if (assoc->init) + { + bend_update_rr rr; + + rr.stream = assoc->encode; + rr.print = assoc->print; + rr.num_bases = 1; + rr.basenames = &srw_req->database; + rr.operation = srw_req->operation; + rr.operation_status = "failed"; + rr.record_id = 0; + rr.record_version = 0; + rr.record_checksum = 0; + rr.record_old_version = 0; + rr.record_packing = "xml"; + rr.record_schema = 0; + rr.record_data = 0; + rr.request_extra_record = 0; + rr.response_extra_record = 0; + rr.extra_request_data = 0; + rr.extra_response_data = 0; + rr.errcode = 0; + rr.errstring = 0; + + yaz_log(YLOG_DEBUG, "basename = %s", rr.basenames[0] ); + yaz_log(YLOG_DEBUG, "Operation = %s", rr.operation ); + if ( !strcmp( rr.operation, "delete" ) ){ + if ( !srw_req->recordId ){ + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 7, "recordId" ); + } + else { + rr.record_id = srw_req->recordId; + } + if ( !srw_req->recordVersion ){ + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 7, "recordVersion" ); + } + else { + rr.record_version = odr_strdup( assoc->encode, + srw_req->recordVersion ); + + } + if ( srw_req->recordOldVersion ){ + rr.record_old_version = odr_strdup(assoc->encode, + srw_req->recordOldVersion ); + } + if ( srw_req->extraRequestData ){ + rr.extra_request_data = odr_strdup(assoc->encode, + srw_req->extraRequestData ); + } + } + else if ( !strcmp( rr.operation, "replace" ) ){ + if ( !srw_req->recordId ){ + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 7, "recordId" ); + } + else { + rr.record_id = srw_req->recordId; + } + if ( srw_req->record.recordSchema == 0 ){ + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 7, "recordSchema" ); + } + else { + rr.record_schema = odr_strdup(assoc->encode, + srw_req->record.recordSchema ); + } + switch (srw_req->record.recordPacking) + { + case Z_SRW_recordPacking_string: + rr.record_packing = "string"; + break; + case Z_SRW_recordPacking_XML: + rr.record_packing = "xml"; + break; + case Z_SRW_recordPacking_URL: + rr.record_packing = "url"; + break; + } + if ( srw_req->record.recordData_len ){ + rr.record_data = odr_strdupn(assoc->encode, + srw_req->record.recordData_buf, + srw_req->record.recordData_len ); + rr.request_extra_record = srw_req->extra_record; + } + else { + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 7, "recordData" ); + } + if (srw_req->extraRequestData) + rr.extra_request_data = odr_strdup(assoc->encode, + srw_req->extraRequestData ); + } + else if ( !strcmp( rr.operation, "insert" ) ) + { + if ( srw_req->record.recordSchema == 0 ){ + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 7, "recordSchema" ); + } + else { + rr.record_schema = odr_strdup(assoc->encode, + srw_req->record.recordSchema); + } + switch (srw_req->record.recordPacking) + { + case Z_SRW_recordPacking_string: + rr.record_packing = "string"; + break; + case Z_SRW_recordPacking_XML: + rr.record_packing = "xml"; + break; + case Z_SRW_recordPacking_URL: + rr.record_packing = "url"; + break; + } + + if (srw_req->record.recordData_len) + { + rr.record_data = odr_strdupn(assoc->encode, + srw_req->record.recordData_buf, + srw_req->record.recordData_len ); + rr.request_extra_record = srw_req->extra_record; + } + else + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 7, "recordData" ); + if ( srw_req->extraRequestData ) + rr.extra_request_data = odr_strdup(assoc->encode, + srw_req->extraRequestData ); + } + if (srw_res->num_diagnostics == 0) + { + if ( assoc->init->bend_srw_update) + (*assoc->init->bend_srw_update)(assoc->backend, &rr); + else { + yaz_log( YLOG_WARN, "Got No Update function!"); + return; + } + } + if (rr.errcode) + yaz_add_srw_diagnostic(assoc->encode, + &srw_res->diagnostics, + &srw_res->num_diagnostics, + rr.errcode, rr.errstring); + srw_res->recordId = rr.record_id; + srw_res->operationStatus = rr.operation_status; + srw_res->recordVersion = rr.record_version; + srw_res->recordChecksum = rr.record_checksum; + srw_res->extraResponseData = rr.extra_response_data; + srw_res->record.recordPosition = 0; + if (srw_res->num_diagnostics == 0 && rr.record_data) + { + srw_res->record.recordSchema = rr.record_schema; + srw_res->record.recordPacking = srw_req->record.recordPacking; + srw_res->record.recordData_buf = rr.record_data; + srw_res->record.recordData_len = strlen(rr.record_data); + srw_res->extra_record = rr.response_extra_record; + + } + else + srw_res->record.recordData_len = 0; + *http_code = 200; + } +} + +/* check if path is OK (1); BAD (0) */ +static int check_path(const char *path) +{ + if (*path != '/') + return 0; + if (strstr(path, "..")) + return 0; + return 1; +} + +static char *read_file(const char *fname, ODR o, int *sz) +{ + char *buf; + FILE *inf = fopen(fname, "rb"); + if (!inf) + return 0; + + fseek(inf, 0L, SEEK_END); + *sz = ftell(inf); + rewind(inf); + buf = odr_malloc(o, *sz); + fread(buf, 1, *sz, inf); + fclose(inf); + return buf; +} static void process_http_request(association *assoc, request *req) { @@ -1191,7 +1421,7 @@ static void process_http_request(association *assoc, request *req) char *charset = 0; Z_HTTP_Response *hres = 0; int keepalive = 1; - char *stylesheet = 0; + const char *stylesheet = 0; /* for now .. set later */ Z_SRW_diagnostic *diagnostic = 0; int num_diagnostic = 0; const char *host = z_HTTP_header_lookup(hreq->headers, "Host"); @@ -1201,14 +1431,63 @@ static void process_http_request(association *assoc, request *req) p = z_get_HTTP_Response(o, 404); r = 1; } - if (r == 2 && !strcmp(hreq->path, "/test")) + if (r == 2 && assoc->docpath && hreq->path[0] == '/' + && + /* check if path is a proper prefix of documentroot */ + strncmp(hreq->path+1, assoc->docpath, strlen(assoc->docpath)) + == 0) { - p = z_get_HTTP_Response(o, 200); - hres = p->u.HTTP_Response; - hres->content_buf = "1234567890\n"; - hres->content_len = strlen(hres->content_buf); + if (!check_path(hreq->path)) + { + yaz_log(YLOG_LOG, "File %s access forbidden", hreq->path+1); + p = z_get_HTTP_Response(o, 404); + } + else + { + int content_size = 0; + char *content_buf = read_file(hreq->path+1, o, &content_size); + if (!content_buf) + { + yaz_log(YLOG_LOG, "File %s not found", hreq->path+1); + p = z_get_HTTP_Response(o, 404); + } + else + { + const char *ctype = 0; + yaz_mime_types types = yaz_mime_types_create(); + + yaz_mime_types_add(types, "xsl", "application/xml"); + yaz_mime_types_add(types, "xml", "application/xml"); + yaz_mime_types_add(types, "css", "text/css"); + yaz_mime_types_add(types, "html", "text/html"); + yaz_mime_types_add(types, "htm", "text/html"); + yaz_mime_types_add(types, "txt", "text/plain"); + + yaz_mime_types_add(types, "gif", "image/gif"); + yaz_mime_types_add(types, "png", "image/png"); + yaz_mime_types_add(types, "jpg", "image/jpeg"); + yaz_mime_types_add(types, "jpeg", "image/jpeg"); + + ctype = yaz_mime_lookup_fname(types, hreq->path); + if (!ctype) + { + yaz_log(YLOG_LOG, "No mime type for %s", hreq->path+1); + p = z_get_HTTP_Response(o, 404); + } + else + { + p = z_get_HTTP_Response(o, 200); + hres = p->u.HTTP_Response; + hres->content_buf = content_buf; + hres->content_len = content_size; + z_HTTP_header_add(o, &hres->headers, "Content-Type", ctype); + } + yaz_mime_types_destroy(types); + } + } r = 1; } + if (r == 2) { r = yaz_srw_decode(hreq, &sr, &soap_package, assoc->decode, &charset); @@ -1266,26 +1545,43 @@ static void process_http_request(association *assoc, request *req) res->u.scan_response->num_diagnostics = num_diagnostic; } srw_bend_scan(assoc, req, sr->u.scan_request, - res->u.scan_response, &http_code); + res->u.scan_response, &http_code); + if (http_code == 200) + soap_package->u.generic->p = res; + } + else if (sr->which == Z_SRW_update_request) + { + Z_SRW_PDU *res = yaz_srw_get(o, Z_SRW_update_response); + yaz_log(YLOG_DEBUG, "handling SRW UpdateRequest"); + if (num_diagnostic) + { + res->u.update_response->diagnostics = diagnostic; + res->u.update_response->num_diagnostics = num_diagnostic; + } + yaz_log(YLOG_DEBUG, "num_diag = %d", res->u.update_response->num_diagnostics ); + srw_bend_update(assoc, req, sr->u.update_request, + res->u.update_response, &http_code); if (http_code == 200) soap_package->u.generic->p = res; } else { yaz_log(log_request, "SOAP ERROR"); - /* FIXME - what error, what query */ + /* FIXME - what error, what query */ http_code = 500; z_soap_error(assoc->encode, soap_package, "SOAP-ENV:Client", "Bad method", 0); } if (http_code == 200 || http_code == 500) { - static Z_SOAP_Handler soap_handlers[3] = { + static Z_SOAP_Handler soap_handlers[4] = { #if HAVE_XML2 {"http://www.loc.gov/zing/srw/", 0, (Z_SOAP_fun) yaz_srw_codec}, {"http://www.loc.gov/zing/srw/v1.0/", 0, (Z_SOAP_fun) yaz_srw_codec}, + {"http://www.loc.gov/zing/srw/update/", 0, + (Z_SOAP_fun) yaz_ucp_codec}, #endif {0, 0, 0} }; @@ -1293,6 +1589,11 @@ static void process_http_request(association *assoc, request *req) int ret; p = z_get_HTTP_Response(o, 200); hres = p->u.HTTP_Response; + + yaz_log(YLOG_LOG, "assoc->stylesheet=%s", assoc->stylesheet); + if (!stylesheet) + stylesheet = assoc->stylesheet; + ret = z_soap_codec_enc_xsl(assoc->encode, &soap_package, &hres->content_buf, &hres->content_len, soap_handlers, charset, stylesheet); @@ -1767,7 +2068,7 @@ static Z_APDU *process_initRequest(association *assoc, request *reqb) assoc->init->implementation_name, odr_prepend(assoc->encode, "GFS", resp->implementationName)); - version = odr_strdup(assoc->encode, "$Revision: 1.60 $"); + version = odr_strdup(assoc->encode, "$Revision: 1.69 $"); if (strlen(version) > 10) /* check for unexpanded CVS strings */ version[strlen(version)-2] = '\0'; resp->implementationVersion = odr_prepend(assoc->encode, @@ -1785,6 +2086,38 @@ static Z_APDU *process_initRequest(association *assoc, request *reqb) } if (log_request) { + if (!req->idAuthentication) + yaz_log(log_request, "Auth none"); + else if (req->idAuthentication->which == Z_IdAuthentication_open) + { + const char *open = req->idAuthentication->u.open; + const char *slash = strchr(open, '/'); + int len; + if (slash) + len = slash - open; + else + len = strlen(open); + yaz_log(log_request, "Auth open %.*s", len, open); + } + else if (req->idAuthentication->which == Z_IdAuthentication_idPass) + { + const char *user = req->idAuthentication->u.idPass->userId; + const char *group = req->idAuthentication->u.idPass->groupId; + yaz_log(log_request, "Auth idPass %s %s", + user ? user : "-", group ? group : "-"); + } + else if (req->idAuthentication->which + == Z_IdAuthentication_anonymous) + { + yaz_log(log_request, "Auth anonymous"); + } + else + { + yaz_log(log_request, "Auth other"); + } + } + if (log_request) + { WRBUF wr = wrbuf_alloc(); wrbuf_printf(wr, "Init "); if (binitres->errcode) @@ -2015,6 +2348,8 @@ static Z_APDU *process_searchRequest(association *assoc, request *reqb, bsrr->referenceId = req->referenceId; save_referenceId (reqb, bsrr->referenceId); bsrr->srw_sortKeys = 0; + bsrr->srw_setname = 0; + bsrr->srw_setnameIdleTime = 0; yaz_log (log_requestdetail, "ResultSet '%s'", req->resultSetName); if (req->databaseNames) @@ -2182,7 +2517,7 @@ static Z_APDU *response_searchRequest(association *assoc, request *reqb, wrbuf_printf(wr, "OK %d", bsrt->hits); wrbuf_printf(wr, " %s 1+%d ", req->resultSetName, returnedrecs); - wrbuf_put_zquery(wr, req->query); + yaz_query_to_wrbuf(wr, req->query); yaz_log(log_request, "Search %s", wrbuf_buf(wr)); wrbuf_free(wr, 1); @@ -2486,9 +2821,8 @@ static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd) *req->preferredPositionInResponse : 1), *req->numberOfTermsRequested, (res->stepSize ? *res->stepSize : 0)); - wrbuf_scan_term(wr, req->termListAndStartPoint, - bsrr->attributeset); - + yaz_scan_to_wrbuf(wr, req->termListAndStartPoint, + bsrr->attributeset); yaz_log(log_request, "Scan %s", wrbuf_buf(wr) ); wrbuf_free(wr, 1); } @@ -2767,6 +3101,7 @@ static Z_APDU *process_segmentRequest (association *assoc, request *reqb) static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd) { bend_esrequest_rr esrequest; + const char *ext_name = "unknown"; Z_ExtendedServicesRequest *req = reqb->apdu_request->u.extendedServicesRequest; @@ -2774,8 +3109,6 @@ static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd) Z_ExtendedServicesResponse *resp = apdu->u.extendedServicesResponse; - yaz_log(log_requestdetail,"Got EsRequest"); - esrequest.esr = reqb->apdu_request->u.extendedServicesRequest; esrequest.stream = assoc->encode; esrequest.decode = assoc->decode; @@ -2786,7 +3119,24 @@ static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd) esrequest.association = assoc; esrequest.taskPackage = 0; esrequest.referenceId = req->referenceId; + + if (esrequest.esr && esrequest.esr->taskSpecificParameters) + { + switch(esrequest.esr->taskSpecificParameters->which) + { + case Z_External_itemOrder: + ext_name = "ItemOrder"; break; + case Z_External_update: + ext_name = "Update"; break; + case Z_External_update0: + ext_name = "Update0"; break; + case Z_External_ESAdmin: + ext_name = "Admin"; break; + + } + } + (*assoc->init->bend_esrequest)(assoc->backend, &esrequest); /* If the response is being delayed, return NULL */ @@ -2798,13 +3148,13 @@ static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd) if (esrequest.errcode == -1) { /* Backend service indicates request will be processed */ - yaz_log(log_request,"EsRequest OK: Accepted !"); + yaz_log(log_request, "Extended Service: %s (accepted)", ext_name); *resp->operationStatus = Z_ExtendedServicesResponse_accepted; } else if (esrequest.errcode == 0) { /* Backend service indicates request will be processed */ - yaz_log(log_request,"EsRequest OK: Done !"); + yaz_log(log_request, "Extended Service: %s (done)", ext_name); *resp->operationStatus = Z_ExtendedServicesResponse_done; } else @@ -2813,7 +3163,7 @@ static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd) zget_DiagRecs(assoc->encode, esrequest.errcode, esrequest.errstring); /* Backend indicates error, request will not be processed */ - yaz_log(YLOG_DEBUG,"Request could not be processed...failure !"); + yaz_log(log_request, "Extended Service: %s (failed)", ext_name); *resp->operationStatus = Z_ExtendedServicesResponse_failure; resp->num_diagnostics = diagRecs->num_diagRecs; resp->diagnostics = diagRecs->diagRecs;