Fix crash in record conv rule select YAZ-812
[yaz-moved-to-github.git] / src / seshigh.c
index 5a6a26f..52ced9b 100644 (file)
@@ -1,5 +1,5 @@
 /* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2012 Index Data
+ * Copyright (C) Index Data
  * See the file LICENSE for details.
  */
 /**
@@ -56,6 +56,7 @@
 #include <libxml/tree.h>
 #endif
 
+#include <yaz/facet.h>
 #include <yaz/xmalloc.h>
 #include <yaz/comstack.h>
 #include "eventl.h"
@@ -73,7 +74,7 @@
 #include <yaz/yaz-util.h>
 #include <yaz/pquery.h>
 #include <yaz/oid_db.h>
-
+#include <yaz/query-charset.h>
 #include <yaz/srw.h>
 #include <yaz/backend.h>
 #include <yaz/yaz-ccl.h>
@@ -478,8 +479,10 @@ void ir_session(IOCHAN h, int event)
 static int process_z_request(association *assoc, request *req, char **msg);
 
 
-static void assoc_init_reset(association *assoc)
+static void assoc_init_reset(association *assoc, const char *peer_name1)
 {
+    const char *peer_name2 = cs_addrstr(assoc->client_link);
+
     xfree(assoc->init);
     assoc->init = (bend_initrequest *) xmalloc(sizeof(*assoc->init));
 
@@ -509,13 +512,24 @@ static void assoc_init_reset(association *assoc)
     assoc->init->charneg_response = NULL;
 
     assoc->init->decode = assoc->decode;
-    assoc->init->peer_name =
-        odr_strdup(assoc->encode, cs_addrstr(assoc->client_link));
+
+    assoc->init->peer_name = (char *)
+        odr_malloc(assoc->encode,
+                   (peer_name1 ? strlen(peer_name1) : 0)
+                   + 4 + strlen(peer_name2));
+    strcpy(assoc->init->peer_name, "");
+    if (peer_name1)
+    {
+        strcat(assoc->init->peer_name, peer_name1);
+        strcat(assoc->init->peer_name, ", ");
+    }
+    strcat(assoc->init->peer_name, peer_name2);
 
     yaz_log(log_requestdetail, "peer %s", assoc->init->peer_name);
 }
 
-static int srw_bend_init(association *assoc, Z_SRW_diagnostic **d, int *num, Z_SRW_PDU *sr)
+static int srw_bend_init(association *assoc, Z_HTTP_Header *headers,
+                         Z_SRW_diagnostic **d, int *num, Z_SRW_PDU *sr)
 {
     statserv_options_block *cb = statserv_getcontrol();
     if (!assoc->init)
@@ -525,7 +539,7 @@ static int srw_bend_init(association *assoc, Z_SRW_diagnostic **d, int *num, Z_S
         bend_initresult *binitres;
 
         yaz_log(log_requestdetail, "srw_bend_init config=%s", cb->configname);
-        assoc_init_reset(assoc);
+        assoc_init_reset(assoc, z_HTTP_header_lookup(headers, "X-Forwarded-For"));
 
         if (sr->username)
         {
@@ -639,23 +653,58 @@ static int retrieve_fetch(association *assoc, bend_fetch_rr *rr)
             rr->request_format = backend_syntax;
     }
     (*assoc->init->bend_fetch)(assoc->backend, rr);
-    if (rc && rr->record && rr->errcode == 0 && rr->len > 0)
+    if (rc && rr->record && rr->errcode == 0)
     {   /* post conversion must take place .. */
         WRBUF output_record = wrbuf_alloc();
-        int r = yaz_record_conv_record(rc, rr->record, rr->len, output_record);
-        if (r)
-        {
-            const char *details = yaz_record_conv_get_error(rc);
-            rr->errcode = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
-            if (details)
-                rr->errstring = odr_strdup(rr->stream, details);
+        int r = 1;
+        const char *details = 0;
+        if (rr->len > 0)
+        {
+            r = yaz_record_conv_record(rc, rr->record, rr->len, output_record);
+            if (r)
+                details = yaz_record_conv_get_error(rc);
+        }
+        else if (rr->len == -1 && rr->output_format &&
+                 !oid_oidcmp(rr->output_format, yaz_oid_recsyn_opac))
+        {
+            r = yaz_record_conv_opac_record(
+                rc, (Z_OPACRecord *) rr->record, output_record);
+            if (r)
+                details = yaz_record_conv_get_error(rc);
+        }
+        if (r == 0 && match_syntax &&
+            !oid_oidcmp(match_syntax, yaz_oid_recsyn_opac))
+        {
+            yaz_marc_t mt = yaz_marc_create();
+            Z_OPACRecord *opac = 0;
+            if (yaz_xml_to_opac(mt, wrbuf_buf(output_record),
+                                wrbuf_len(output_record),
+                                &opac, 0 /* iconv */, rr->stream->mem, 0)
+                && opac)
+            {
+                rr->len = -1;
+                rr->record = (char *) opac;
+            }
+            else
+            {
+                details = "XML to OPAC conversion failed";
+                r = 1;
+            }
+            yaz_marc_destroy(mt);
         }
-        else
+        else if (r == 0)
         {
             rr->len = wrbuf_len(output_record);
             rr->record = (char *) odr_malloc(rr->stream, rr->len);
             memcpy(rr->record, wrbuf_buf(output_record), rr->len);
         }
+        if (r)
+        {
+            rr->errcode = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
+            rr->surrogate_flag = 1;
+            if (details)
+                rr->errstring = odr_strdup(rr->stream, details);
+        }
         wrbuf_destroy(output_record);
     }
     if (match_syntax)
@@ -867,6 +916,7 @@ static int ccl2pqf(ODR odr, const Odr_oct *ccl, CCL_bibset bibset,
 }
 
 static void srw_bend_search(association *assoc,
+                            Z_HTTP_Header *headers,
                             Z_SRW_PDU *sr,
                             Z_SRW_PDU *res,
                             int *http_code)
@@ -878,7 +928,8 @@ static void srw_bend_search(association *assoc,
 
     *http_code = 200;
     yaz_log(log_requestdetail, "Got SRW SearchRetrieveRequest");
-    srw_bend_init(assoc, &srw_res->diagnostics, &srw_res->num_diagnostics, sr);
+    srw_bend_init(assoc, headers,
+                  &srw_res->diagnostics, &srw_res->num_diagnostics, sr);
     if (srw_res->num_diagnostics == 0 && assoc->init)
     {
         bend_search_rr rr;
@@ -896,12 +947,14 @@ static void srw_bend_search(association *assoc,
         rr.query->u.type_1 = 0;
         rr.extra_args = sr->extra_args;
         rr.extra_response_data = 0;
+        rr.present_number = srw_req->maximumRecords ?
+            *srw_req->maximumRecords : 0;
 
-        if (srw_req->query_type == Z_SRW_query_type_cql)
+        if (!srw_req->queryType || !strcmp(srw_req->queryType, "cql"))
         {
             if (assoc->server && assoc->server->cql_transform)
             {
-                int srw_errcode = cql2pqf(assoc->encode, srw_req->query.cql,
+                int srw_errcode = cql2pqf(assoc->encode, srw_req->query,
                                           assoc->server->cql_transform,
                                           rr.query,
                                           &rr.srw_sortKeys);
@@ -923,21 +976,20 @@ static void srw_bend_search(association *assoc,
                 ext->indirect_reference = 0;
                 ext->descriptor = 0;
                 ext->which = Z_External_CQL;
-                ext->u.cql = srw_req->query.cql;
+                ext->u.cql = srw_req->query;
 
                 rr.query->which = Z_Query_type_104;
                 rr.query->u.type_104 =  ext;
             }
         }
-        else if (srw_req->query_type == Z_SRW_query_type_pqf)
+        else if (!strcmp(srw_req->queryType, "pqf"))
         {
             Z_RPNQuery *RPNquery;
             YAZ_PQF_Parser pqf_parser;
 
             pqf_parser = yaz_pqf_create();
 
-            RPNquery = yaz_pqf_parse(pqf_parser, assoc->decode,
-                                     srw_req->query.pqf);
+            RPNquery = yaz_pqf_parse(pqf_parser, assoc->decode, srw_req->query);
             if (!RPNquery)
             {
                 const char *pqf_msg;
@@ -973,6 +1025,11 @@ static void srw_bend_search(association *assoc,
             rr.errstring = 0;
             rr.search_info = 0;
             rr.search_input = 0;
+
+            if (srw_req->facetList)
+                yaz_oi_set_facetlist(&rr.search_input, assoc->encode,
+                                     srw_req->facetList);
+
             yaz_log_zquery_level(log_requestdetail,rr.query);
 
             (assoc->init->bend_search)(assoc->backend, &rr);
@@ -1011,6 +1068,7 @@ static void srw_bend_search(association *assoc,
                         odr_intdup(assoc->encode, *rr.srw_setnameIdleTime );
                }
 
+                srw_res->facetList = yaz_oi_get_facetlist(&rr.search_info);
                 if (start > rr.hits || start < 1)
                 {
                     /* if hits<=0 and start=1 we don't return a diagnostic */
@@ -1125,7 +1183,19 @@ static void srw_bend_search(association *assoc,
                     res->extraResponseData_buf = rr.extra_response_data;
                     res->extraResponseData_len = strlen(rr.extra_response_data);
                 }
-                if (rr.estimated_hit_count || rr.partial_resultset)
+                if (strcmp(res->srw_version, "2.") > 0)
+                {
+                    if (rr.estimated_hit_count)
+                        srw_res->resultCountPrecision =
+                            odr_strdup(assoc->encode, "estimate");
+                    else if (rr.partial_resultset)
+                        srw_res->resultCountPrecision =
+                            odr_strdup(assoc->encode, "minimum");
+                    else
+                        srw_res->resultCountPrecision =
+                            odr_strdup(assoc->encode, "exact");
+                }
+                else if (rr.estimated_hit_count || rr.partial_resultset)
                 {
                     yaz_add_srw_diagnostic(
                         assoc->encode,
@@ -1139,21 +1209,8 @@ static void srw_bend_search(association *assoc,
     }
     if (log_request)
     {
-        const char *querystr = "?";
-        const char *querytype = "?";
         WRBUF wr = wrbuf_alloc();
 
-        switch (srw_req->query_type)
-        {
-        case Z_SRW_query_type_cql:
-            querytype = "CQL";
-            querystr = srw_req->query.cql;
-            break;
-        case Z_SRW_query_type_pqf:
-            querytype = "PQF";
-            querystr = srw_req->query.pqf;
-            break;
-        }
         wrbuf_printf(wr, "SRWSearch %s ", srw_req->database);
         if (srw_res->num_diagnostics)
             wrbuf_printf(wr, "ERROR %s", srw_res->diagnostics[0].uri);
@@ -1170,7 +1227,8 @@ static void srw_bend_search(association *assoc,
                       srw_res->resultSetId : "-"),
                      (srw_req->startRecord ? *srw_req->startRecord : 1),
                      srw_res->num_records);
-        yaz_log(log_request, "%s %s: %s", wrbuf_cstr(wr), querytype, querystr);
+        yaz_log(log_request, "%s %s: %s", wrbuf_cstr(wr), srw_req->queryType,
+                srw_req->query);
         wrbuf_destroy(wr);
     }
 }
@@ -1212,14 +1270,17 @@ static char *srw_bend_explain_default(bend_explain_rr *rr)
 }
 
 static void srw_bend_explain(association *assoc,
+                             Z_HTTP_Header *headers,
                              Z_SRW_PDU *sr,
                              Z_SRW_explainResponse *srw_res,
                              int *http_code)
 {
     Z_SRW_explainRequest *srw_req = sr->u.explain_request;
     yaz_log(log_requestdetail, "Got SRW ExplainRequest");
-    *http_code = 404;
-    srw_bend_init(assoc, &srw_res->diagnostics, &srw_res->num_diagnostics, sr);
+    srw_bend_init(assoc, headers,
+                  &srw_res->diagnostics, &srw_res->num_diagnostics, sr);
+    if (!assoc->init && srw_res->num_diagnostics == 0)
+        *http_code = 404;
     if (assoc->init)
     {
         bend_explain_rr rr;
@@ -1260,15 +1321,18 @@ static void srw_bend_explain(association *assoc,
 }
 
 static void srw_bend_scan(association *assoc,
+                          Z_HTTP_Header *headers,
                           Z_SRW_PDU *sr,
-                          Z_SRW_scanResponse *srw_res,
+                          Z_SRW_PDU *res,
                           int *http_code)
 {
     Z_SRW_scanRequest *srw_req = sr->u.scan_request;
+    Z_SRW_scanResponse *srw_res = res->u.scan_response;
     yaz_log(log_requestdetail, "Got SRW ScanRequest");
 
     *http_code = 200;
-    srw_bend_init(assoc, &srw_res->diagnostics, &srw_res->num_diagnostics, sr);
+    srw_bend_init(assoc, headers,
+                  &srw_res->diagnostics, &srw_res->num_diagnostics, sr);
     if (srw_res->num_diagnostics == 0 && assoc->init)
     {
         int step_size = 0;
@@ -1292,6 +1356,8 @@ static void srw_bend_scan(association *assoc,
         bsrr->step_size = &step_size;
         bsrr->entries = 0;
         bsrr->setname = 0;
+        bsrr->extra_args = sr->extra_args;
+        bsrr->extra_response_data = 0;
 
         if (bsrr->num_entries > 0)
         {
@@ -1310,20 +1376,20 @@ static void srw_bend_scan(association *assoc,
         }
         save_entries = bsrr->entries;  /* save it so we can compare later */
 
-        if (srw_req->query_type == Z_SRW_query_type_pqf &&
+        if (srw_req->queryType && !strcmp(srw_req->queryType, "pqf") &&
             assoc->init->bend_scan)
         {
             YAZ_PQF_Parser pqf_parser = yaz_pqf_create();
 
             bsrr->term = yaz_pqf_scan(pqf_parser, assoc->decode,
                                       &bsrr->attributeset,
-                                      srw_req->scanClause.pqf);
+                                      srw_req->scanClause);
             yaz_pqf_destroy(pqf_parser);
             bsrr->scanClause = 0;
             ((int (*)(void *, bend_scan_rr *))
              (*assoc->init->bend_scan))(assoc->backend, bsrr);
         }
-        else if (srw_req->query_type == Z_SRW_query_type_cql
+        else if ((!srw_req->queryType || !strcmp(srw_req->queryType, "cql"))
                  && assoc->init->bend_scan && assoc->server
                  && assoc->server->cql_transform)
         {
@@ -1333,7 +1399,7 @@ static void srw_bend_scan(association *assoc,
             bsrr->term = (Z_AttributesPlusTerm *)
                 odr_malloc(assoc->decode, sizeof(*bsrr->term));
             srw_error = cql2pqf_scan(assoc->encode,
-                                     srw_req->scanClause.cql,
+                                     srw_req->scanClause,
                                      assoc->server->cql_transform,
                                      bsrr->term);
             if (srw_error)
@@ -1346,12 +1412,12 @@ static void srw_bend_scan(association *assoc,
                  (*assoc->init->bend_scan))(assoc->backend, bsrr);
             }
         }
-        else if (srw_req->query_type == Z_SRW_query_type_cql
+        else if ((!srw_req->queryType || !strcmp(srw_req->queryType, "cql"))
                  && assoc->init->bend_srw_scan)
         {
             bsrr->term = 0;
             bsrr->attributeset = 0;
-            bsrr->scanClause = srw_req->scanClause.cql;
+            bsrr->scanClause = srw_req->scanClause;
             ((int (*)(void *, bend_scan_rr *))
              (*assoc->init->bend_srw_scan))(assoc->backend, bsrr);
         }
@@ -1361,6 +1427,11 @@ static void srw_bend_scan(association *assoc,
                                    &srw_res->num_diagnostics,
                                    YAZ_SRW_UNSUPP_OPERATION, "scan");
         }
+        if (bsrr->extra_response_data)
+        {
+            res->extraResponseData_buf = bsrr->extra_response_data;
+            res->extraResponseData_len = strlen(bsrr->extra_response_data);
+        }
         if (bsrr->errcode)
         {
             int srw_error;
@@ -1407,24 +1478,6 @@ static void srw_bend_scan(association *assoc,
     if (log_request)
     {
         WRBUF wr = wrbuf_alloc();
-        const char *querytype = 0;
-        const char *querystr = 0;
-
-        switch(srw_req->query_type)
-        {
-        case Z_SRW_query_type_pqf:
-            querytype = "PQF";
-            querystr = srw_req->scanClause.pqf;
-            break;
-        case Z_SRW_query_type_cql:
-            querytype = "CQL";
-            querystr = srw_req->scanClause.cql;
-            break;
-        default:
-            querytype = "UNKNOWN";
-            querystr = "";
-        }
-
         wrbuf_printf(wr, "SRWScan %s ", srw_req->database);
 
         if (srw_res->num_diagnostics)
@@ -1440,7 +1493,7 @@ static void srw_bend_scan(association *assoc,
                      (srw_req->maximumTerms ?
                       *srw_req->maximumTerms : 1));
         /* there is no step size in SRU/W ??? */
-        wrbuf_printf(wr, "%s: %s ", querytype, querystr);
+        wrbuf_printf(wr, "%s: %s ", srw_req->queryType, srw_req->scanClause);
         yaz_log(log_request, "%s ", wrbuf_cstr(wr) );
         wrbuf_destroy(wr);
     }
@@ -1448,6 +1501,7 @@ static void srw_bend_scan(association *assoc,
 }
 
 static void srw_bend_update(association *assoc,
+                            Z_HTTP_Header *headers,
                            Z_SRW_PDU *sr,
                            Z_SRW_updateResponse *srw_res,
                            int *http_code)
@@ -1455,8 +1509,10 @@ static void srw_bend_update(association *assoc,
     Z_SRW_updateRequest *srw_req = sr->u.update_request;
     yaz_log(log_session, "SRWUpdate action=%s", srw_req->operation);
     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, sr);
+    srw_bend_init(assoc, headers,
+                  &srw_res->diagnostics, &srw_res->num_diagnostics, sr);
+    if (!assoc->init && srw_res->num_diagnostics == 0)
+        *http_code = 404;
     if (assoc->init)
     {
        bend_update_rr rr;
@@ -1806,8 +1862,8 @@ static void process_http_request(association *assoc, request *req)
         if (sr->which == Z_SRW_searchRetrieve_request)
         {
             Z_SRW_PDU *res =
-                yaz_srw_get_pdu(assoc->encode, Z_SRW_searchRetrieve_response,
-                                sr->srw_version);
+                yaz_srw_get_pdu_e(assoc->encode, Z_SRW_searchRetrieve_response,
+                                  sr);
             stylesheet = sr->u.request->stylesheet;
             if (num_diagnostic)
             {
@@ -1816,36 +1872,35 @@ static void process_http_request(association *assoc, request *req)
             }
             else
             {
-                srw_bend_search(assoc, sr, res, &http_code);
+                srw_bend_search(assoc, hreq->headers, sr, res, &http_code);
             }
             if (http_code == 200)
                 soap_package->u.generic->p = res;
         }
         else if (sr->which == Z_SRW_explain_request)
         {
-            Z_SRW_PDU *res = yaz_srw_get_pdu(o, Z_SRW_explain_response,
-                                             sr->srw_version);
+            Z_SRW_PDU *res = yaz_srw_get_pdu_e(o, Z_SRW_explain_response, sr);
             stylesheet = sr->u.explain_request->stylesheet;
             if (num_diagnostic)
             {
                 res->u.explain_response->diagnostics = diagnostic;
                 res->u.explain_response->num_diagnostics = num_diagnostic;
             }
-            srw_bend_explain(assoc, sr, res->u.explain_response, &http_code);
+            srw_bend_explain(assoc, hreq->headers,
+                             sr, res->u.explain_response, &http_code);
             if (http_code == 200)
                 soap_package->u.generic->p = res;
         }
         else if (sr->which == Z_SRW_scan_request)
         {
-            Z_SRW_PDU *res = yaz_srw_get_pdu(o, Z_SRW_scan_response,
-                                             sr->srw_version);
+            Z_SRW_PDU *res = yaz_srw_get_pdu_e(o, Z_SRW_scan_response, sr);
             stylesheet = sr->u.scan_request->stylesheet;
             if (num_diagnostic)
             {
                 res->u.scan_response->diagnostics = diagnostic;
                 res->u.scan_response->num_diagnostics = num_diagnostic;
             }
-            srw_bend_scan(assoc, sr, res->u.scan_response, &http_code);
+            srw_bend_scan(assoc, hreq->headers, sr, res, &http_code);
             if (http_code == 200)
                 soap_package->u.generic->p = res;
         }
@@ -1860,7 +1915,8 @@ static void process_http_request(association *assoc, request *req)
                 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, sr, res->u.update_response, &http_code);
+            srw_bend_update(assoc, hreq->headers,
+                            sr, res->u.update_response, &http_code);
             if (http_code == 200)
                 soap_package->u.generic->p = res;
         }
@@ -1899,11 +1955,6 @@ static void process_http_request(association *assoc, request *req)
             hres->code = http_code;
 
             strcpy(ctype, "text/xml");
-            if (charset && strlen(charset) < sizeof(ctype)-30)
-            {
-                strcat(ctype, "; charset=");
-                strcat(ctype, charset);
-            }
             z_HTTP_header_add(o, &hres->headers, "Content-Type", ctype);
         }
         else
@@ -2158,8 +2209,9 @@ static Z_APDU *process_initRequest(association *assoc, request *reqb)
         yaz_log(log_requestdetail, "Version:   %s",
                 req->implementationVersion);
 
-    assoc_init_reset(assoc);
-
+    assoc_init_reset(assoc, 
+                     yaz_oi_get_string_oid(&req->otherInfo,
+                                           yaz_oid_userinfo_client_ip, 1, 0));
     assoc->init->auth = req->idAuthentication;
     assoc->init->referenceId = req->referenceId;
 
@@ -2446,7 +2498,8 @@ static Z_Records *pack_records(association *a, char *setname, Odr_int start,
                                Z_ReferenceId *referenceId,
                                Odr_oid *oid, int *errcode)
 {
-    int recno, total_length = 0, dumped_records = 0;
+    int recno;
+    Odr_int dumped_records = 0;
     int toget = odr_int_to_int(*num);
     Z_Records *records =
         (Z_Records *) odr_malloc(a->encode, sizeof(*records));
@@ -2476,13 +2529,13 @@ static Z_Records *pack_records(association *a, char *setname, Odr_int start,
     {
         bend_fetch_rr freq;
         Z_NamePlusRecord *thisrec;
-        int this_length = 0;
+        Odr_int this_length = 0;
         /*
          * we get the number of bytes allocated on the stream before any
          * allocation done by the backend - this should give us a reasonable
          * idea of the total size of the data so far.
          */
-        total_length = odr_total(a->encode) - dumped_records;
+        Odr_int total_length = odr_total(a->encode) - dumped_records;
         freq.errcode = 0;
         freq.errstring = 0;
         freq.basename = 0;
@@ -2538,10 +2591,11 @@ static Z_Records *pack_records(association *a, char *setname, Odr_int start,
             this_length = freq.len;
         else
             this_length = odr_total(a->encode) - total_length - dumped_records;
-        yaz_log(YLOG_DEBUG, "  fetched record, len=%d, total=%d dumped=%d",
-            this_length, total_length, dumped_records);
+        yaz_log(log_requestdetail, "  fetched record, len=" ODR_INT_PRINTF
+                " total=" ODR_INT_PRINTF " dumped=" ODR_INT_PRINTF,
+                this_length, total_length, dumped_records);
         if (a->preferredMessageSize > 0 &&
-                this_length + total_length > a->preferredMessageSize)
+            this_length + total_length > a->preferredMessageSize)
         {
             /* record is small enough, really */
             if (this_length <= a->preferredMessageSize && recno > start)
@@ -2571,7 +2625,7 @@ static Z_Records *pack_records(association *a, char *setname, Odr_int start,
             else /* too big entirely */
             {
                 yaz_log(log_requestdetail, "Record > maxrcdsz "
-                        "this=%d max=%d",
+                        "this=" ODR_INT_PRINTF " max=%d",
                         this_length, a->maximumRecordSize);
                 reclist->records[reclist->num_records] =
                     surrogatediagrec(
@@ -2649,7 +2703,23 @@ static Z_APDU *process_searchRequest(association *assoc, request *reqb)
         bsrr->errcode = 0;
         bsrr->errstring = NULL;
         bsrr->search_info = NULL;
-        bsrr->search_input = req->otherInfo;
+        bsrr->search_input = req->additionalSearchInfo;
+        if (!bsrr->search_input)
+            bsrr->search_input = req->otherInfo;
+        bsrr->present_number = *req->mediumSetPresentNumber;
+
+        if (assoc->server && assoc->server->client_query_charset &&
+            req->query->which == Z_Query_type_1)
+        {
+            yaz_iconv_t cd =
+                yaz_iconv_open("UTF-8", assoc->server->client_query_charset);
+            if (cd)
+            {
+                yaz_query_charset_convert_rpnquery(req->query->u.type_1,
+                                                   assoc->decode, cd);
+                yaz_iconv_close(cd);
+            }
+        }
 
         if (assoc->server && assoc->server->cql_transform
             && req->query->which == Z_Query_type_104
@@ -3007,6 +3077,8 @@ static Z_APDU *process_scanRequest(association *assoc, request *reqb)
     bsrr->setname = yaz_oi_get_string_oid(&req->otherInfo,
                                           yaz_oid_userinfo_scan_set, 1, 0);
     bsrr->entries = 0;
+    bsrr->extra_args = 0;
+    bsrr->extra_response_data = 0;
     /* For YAZ 2.0 and earlier it was the backend handler that
        initialized entries (member display_term did not exist)
        YAZ 2.0 and later sets 'entries'  and initialize all members
@@ -3063,7 +3135,6 @@ static Z_APDU *process_scanRequest(association *assoc, request *reqb)
         {
             Z_Entry *e;
             Z_TermInfo *t;
-            Odr_oct *o;
 
             tab[i] = e = (Z_Entry *)odr_malloc(assoc->encode, sizeof(*e));
             if (bsrr->entries[i].occurrences >= 0)
@@ -3090,12 +3161,10 @@ static Z_APDU *process_scanRequest(association *assoc, request *reqb)
                 t->term = (Z_Term *)
                     odr_malloc(assoc->encode, sizeof(*t->term));
                 t->term->which = Z_Term_general;
-                t->term->u.general = o =
-                    (Odr_oct *)odr_malloc(assoc->encode, sizeof(Odr_oct));
-                o->buf = (unsigned char *)
-                    odr_malloc(assoc->encode, o->len = o->size =
-                               strlen(bsrr->entries[i].term));
-                memcpy(o->buf, bsrr->entries[i].term, o->len);
+                t->term->u.general =
+                    odr_create_Odr_oct(assoc->encode,
+                                       bsrr->entries[i].term,
+                                       strlen(bsrr->entries[i].term));
                 yaz_log(YLOG_DEBUG, "  term #%d: '%s' (" ODR_INT_PRINTF ")", i,
                          bsrr->entries[i].term, bsrr->entries[i].occurrences);
             }