Added utilities z_ext_record_{xml,sutrs,usmarc}.
[yaz-moved-to-github.git] / src / zoom-c.c
index 15047d4..fb30049 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2007, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: zoom-c.c,v 1.108 2007-01-12 21:03:31 adam Exp $
+ * $Id: zoom-c.c,v 1.124 2007-04-13 09:55:41 adam Exp $
  */
 /**
  * \file zoom-c.c
@@ -35,10 +35,27 @@ typedef enum {
     zoom_complete
 } zoom_ret;
 
+static void resultset_destroy(ZOOM_resultset r);
 static zoom_ret ZOOM_connection_send_init(ZOOM_connection c);
 static zoom_ret do_write_ex(ZOOM_connection c, char *buf_out, int len_out);
 static char *cql2pqf(ZOOM_connection c, const char *cql);
 
+
+/*
+ * This wrapper is just for logging failed lookups.  It would be nicer
+ * if it could cause failure when a lookup fails, but that's hard.
+ */
+static int *zoom_yaz_str_to_z3950oid(ZOOM_connection c,
+                                     int oid_class, const char *str) {
+    int *res = yaz_string_to_oid_odr(yaz_oid_std(), oid_class, str,
+                                     c->odr_out);
+    if (res == 0)
+        yaz_log(YLOG_WARN, "%p OID lookup (%d, '%s') failed",
+                c, (int) oid_class, str);
+    return res;
+}
+
+
 static void initlog(void)
 {
     static int log_level_initialized = 0;
@@ -103,6 +120,13 @@ static ZOOM_Event ZOOM_connection_get_event(ZOOM_connection c)
     return event;
 }
 
+static void ZOOM_connection_remove_events(ZOOM_connection c)
+{
+    ZOOM_Event event;
+    while ((event = ZOOM_connection_get_event(c)))
+        ZOOM_Event_destroy(event);
+}
+
 ZOOM_API(int) ZOOM_connection_peek_event(ZOOM_connection c)
 {
     ZOOM_Event event = c->m_queue_front;
@@ -110,6 +134,8 @@ ZOOM_API(int) ZOOM_connection_peek_event(ZOOM_connection c)
     return event ? event->kind : ZOOM_EVENT_NONE;
 }
 
+void ZOOM_connection_remove_tasks(ZOOM_connection c);
+
 static void set_dset_error(ZOOM_connection c, int error,
                            const char *dset,
                            const char *addinfo, const char *addinfo2)
@@ -135,11 +161,14 @@ static void set_dset_error(ZOOM_connection c, int error,
     }
     else if (addinfo)
         c->addinfo = xstrdup(addinfo);
-    if (error)
+    if (error != ZOOM_ERROR_NONE)
+    {
         yaz_log(log_api, "%p set_dset_error %s %s:%d %s %s",
                 c, c->host_port ? c->host_port : "<>", dset, error,
                 addinfo ? addinfo : "",
                 addinfo2 ? addinfo2 : "");
+        ZOOM_connection_remove_tasks(c);
+    }
 }
 
 #if YAZ_HAVE_XML2
@@ -150,6 +179,7 @@ static void set_HTTP_error(ZOOM_connection c, int error,
 }
 #endif
 
+
 static void set_ZOOM_error(ZOOM_connection c, int error,
                            const char *addinfo)
 {
@@ -165,6 +195,8 @@ static void clear_error(ZOOM_connection c)
      * or Init Refused are not cleared, because they are not
      * recoverable: doing another search doesn't help.
      */
+
+    ZOOM_connection_remove_events(c);
     switch (c->error)
     {
     case ZOOM_ERROR_CONNECT:
@@ -248,12 +280,12 @@ void ZOOM_connection_remove_task(ZOOM_connection c)
         switch (task->which)
         {
         case ZOOM_TASK_SEARCH:
-            ZOOM_resultset_destroy(task->u.search.resultset);
+            resultset_destroy(task->u.search.resultset);
             xfree(task->u.search.syntax);
             xfree(task->u.search.elementSetName);
             break;
         case ZOOM_TASK_RETRIEVE:
-            ZOOM_resultset_destroy(task->u.retrieve.resultset);
+            resultset_destroy(task->u.retrieve.resultset);
             xfree(task->u.retrieve.syntax);
             xfree(task->u.retrieve.elementSetName);
             break;
@@ -266,7 +298,7 @@ void ZOOM_connection_remove_task(ZOOM_connection c)
             ZOOM_package_destroy(task->u.package);
             break;
         case ZOOM_TASK_SORT:
-            ZOOM_resultset_destroy(task->u.sort.resultset);
+            resultset_destroy(task->u.sort.resultset);
             ZOOM_query_destroy(task->u.sort.q);
             break;
         default:
@@ -362,7 +394,7 @@ static char **set_DatabaseNames(ZOOM_connection con, ZOOM_options options,
     }
     if (!cp)
         cp = "Default";
-    nmem_strsplit(odr->mem, "+", cp,  &databaseNames, num);
+    nmem_strsplit(odr_getmem(odr), "+", cp,  &databaseNames, num);
     return databaseNames;
 }
 
@@ -398,7 +430,7 @@ ZOOM_API(void)
     initlog();
 
     yaz_log(log_api, "%p ZOOM_connection_connect host=%s portnum=%d",
-            c, host, portnum);
+            c, host ? host : "null", portnum);
 
     set_ZOOM_error(c, ZOOM_ERROR_NONE, 0);
     ZOOM_connection_remove_tasks(c);
@@ -440,15 +472,18 @@ ZOOM_API(void)
     else
         c->lang = 0;
 
-    xfree(c->host_port);
-    if (portnum)
+    if (host)
     {
-        char hostn[128];
-        sprintf(hostn, "%.80s:%d", host, portnum);
-        c->host_port = xstrdup(hostn);
-    }
-    else
-        c->host_port = xstrdup(host);
+        xfree(c->host_port);
+        if (portnum)
+        {
+            char hostn[128];
+            sprintf(hostn, "%.80s:%d", host, portnum);
+            c->host_port = xstrdup(hostn);
+        }
+        else
+            c->host_port = xstrdup(host);
+    }        
 
     {
         /*
@@ -549,7 +584,7 @@ ZOOM_API(int)
     s->query_string = odr_strdup(s->odr, str);
     s->z_query = (Z_Query *) odr_malloc(s->odr, sizeof(*s->z_query));
     s->z_query->which = Z_Query_type_1;
-    s->z_query->u.type_1 =  p_query_rpn(s->odr, PROTO_Z3950, str);
+    s->z_query->u.type_1 =  p_query_rpn(s->odr, str);
     if (!s->z_query->u.type_1)
     {
         yaz_log(log_details, "%p ZOOM_query_prefix str=%s failed", s, str);
@@ -640,8 +675,8 @@ ZOOM_API(int)
         WRBUF wr = wrbuf_alloc();
         ccl_pquery(wr, rpn);
         ccl_rpn_delete(rpn);
-        ret = ZOOM_query_prefix(s, wrbuf_buf(wr));
-        wrbuf_free(wr, 1);
+        ret = ZOOM_query_prefix(s, wrbuf_cstr(wr));
+        wrbuf_destroy(wr);
     }
     ccl_qual_rm(&bibset);
     return ret;
@@ -682,6 +717,7 @@ ZOOM_API(void)
     odr_destroy(c->odr_out);
     ZOOM_options_destroy(c->options);
     ZOOM_connection_remove_tasks(c);
+    ZOOM_connection_remove_events(c);
     xfree(c->host_port);
     xfree(c->path);
     xfree(c->proxy);
@@ -818,16 +854,11 @@ ZOOM_API(ZOOM_resultset)
     return r;
 }
 
-/*
- * This is the old result-set sorting API, which is maintained only
- * for the sake of binary compatibility.  There is no reason ever to
- * use this rather than ZOOM_resultset_sort1().
- */
 ZOOM_API(void)
     ZOOM_resultset_sort(ZOOM_resultset r,
-                        const char *sort_type, const char *sort_spec)
+                         const char *sort_type, const char *sort_spec)
 {
-    (void) ZOOM_resultset_sort1(r, sort_type, sort_spec);
+    (void) ZOOM_resultset_sort(r, sort_type, sort_spec);
 }
 
 ZOOM_API(int)
@@ -888,11 +919,11 @@ ZOOM_API(void)
         for (rc = r->record_hash[i]; rc; rc = rc->next)
         {
             if (rc->rec.wrbuf_marc)
-                wrbuf_free(rc->rec.wrbuf_marc, 1);
+                wrbuf_destroy(rc->rec.wrbuf_marc);
             if (rc->rec.wrbuf_iconv)
-                wrbuf_free(rc->rec.wrbuf_iconv, 1);
+                wrbuf_destroy(rc->rec.wrbuf_iconv);
             if (rc->rec.wrbuf_opac)
-                wrbuf_free(rc->rec.wrbuf_opac, 1);
+                wrbuf_destroy(rc->rec.wrbuf_opac);
         }
         r->record_hash[i] = 0;
     }
@@ -901,6 +932,11 @@ ZOOM_API(void)
 ZOOM_API(void)
     ZOOM_resultset_destroy(ZOOM_resultset r)
 {
+    resultset_destroy(r);
+}
+
+static void resultset_destroy(ZOOM_resultset r)
+{
     if (!r)
         return;
     (r->refcount)--;
@@ -953,12 +989,18 @@ static void do_close(ZOOM_connection c)
 
 static int ZOOM_test_reconnect(ZOOM_connection c)
 {
+    ZOOM_Event event;
+
     if (!c->reconnect_ok)
         return 0;
     do_close(c);
     c->reconnect_ok = 0;
     c->tasks->running = 0;
     ZOOM_connection_insert_task(c, ZOOM_TASK_CONNECT);
+
+    event = ZOOM_Event_create(ZOOM_EVENT_CONNECT);
+    ZOOM_connection_put_event(c, event);
+
     return 1;
 }
 
@@ -1131,11 +1173,11 @@ static void otherInfo_attach(ZOOM_connection c, Z_APDU *a, ODR out)
     for (i = 0; i<200; i++)
     {
         size_t len;
+        int *oid;
         Z_OtherInformation **oi;
         char buf[80];
         const char *val;
         const char *cp;
-        int oidval;
 
         sprintf(buf, "otherInfo%d", i);
         val = ZOOM_options_get(c->options, buf);
@@ -1149,12 +1191,14 @@ static void otherInfo_attach(ZOOM_connection c, Z_APDU *a, ODR out)
             len = sizeof(buf)-1;
         memcpy(buf, val, len);
         buf[len] = '\0';
-        oidval = oid_getvalbyname(buf);
-        if (oidval == VAL_NONE)
+        
+        oid = yaz_string_to_oid_odr(yaz_oid_std(), CLASS_USERINFO,
+                                    buf, out);
+        if (!oid)
             continue;
         
         yaz_oi_APDU(a, &oi);
-        yaz_oi_set_string_oidval(oi, out, oidval, 1, cp+1);
+        yaz_oi_set_string_oid(oi, out, oid, 1, cp+1);
     }
 }
 
@@ -1163,15 +1207,19 @@ static int encode_APDU(ZOOM_connection c, Z_APDU *a, ODR out)
     assert(a);
     if (c->cookie_out)
     {
+        const int *oid = yaz_string_to_oid(
+            yaz_oid_std(), CLASS_USERINFO, OID_STR_COOKIE);
         Z_OtherInformation **oi;
         yaz_oi_APDU(a, &oi);
-        yaz_oi_set_string_oidval(oi, out, VAL_COOKIE, 1, c->cookie_out);
+        yaz_oi_set_string_oid(oi, out, oid, 1, c->cookie_out);
     }
     if (c->client_IP)
     {
+        const int *oid = yaz_string_to_oid(
+            yaz_oid_std(), CLASS_USERINFO, OID_STR_CLIENT_IP);
         Z_OtherInformation **oi;
         yaz_oi_APDU(a, &oi);
-        yaz_oi_set_string_oidval(oi, out, VAL_CLIENT_IP, 1, c->client_IP);
+        yaz_oi_set_string_oid(oi, out, oid, 1, c->client_IP);
     }
     otherInfo_attach(c, a, out);
     if (!z_APDU(out, &a, 0, 0))
@@ -1250,7 +1298,7 @@ static zoom_ret ZOOM_connection_send_init(ZOOM_connection c)
                     odr_prepend(c->odr_out, "ZOOM-C",
                                 ireq->implementationName));
     
-    version = odr_strdup(c->odr_out, "$Revision: 1.108 $");
+    version = odr_strdup(c->odr_out, "$Revision: 1.124 $");
     if (strlen(version) > 10)   /* check for unexpanded CVS strings */
         version[strlen(version)-2] = '\0';
     ireq->implementationVersion = 
@@ -1308,8 +1356,12 @@ static zoom_ret ZOOM_connection_send_init(ZOOM_connection c)
         ireq->idAuthentication = auth;
     }
     if (c->proxy)
-        yaz_oi_set_string_oidval(&ireq->otherInfo, c->odr_out,
-                                 VAL_PROXY, 1, c->host_port);
+    {
+        const int *oid = yaz_string_to_oid(
+            yaz_oid_std(), CLASS_USERINFO, OID_STR_CLIENT_IP);
+        yaz_oi_set_string_oid(&ireq->otherInfo, c->odr_out,
+                              oid, 1, c->host_port);
+    }
     if (c->charset || c->lang)
     {
         Z_OtherInformation **oi;
@@ -1552,7 +1604,7 @@ static zoom_ret ZOOM_connection_send_search(ZOOM_connection c)
     }
     if (syntax)
         search_req->preferredRecordSyntax =
-            yaz_str_to_z3950oid(c->odr_out, CLASS_RECSYN, syntax);
+            zoom_yaz_str_to_z3950oid(c, CLASS_RECSYN, syntax);
     
     if (!r->setname)
     {
@@ -1605,7 +1657,8 @@ static void response_default_diag(ZOOM_connection c, Z_DefaultDiagFormat *r)
     xfree(c->addinfo);
     c->addinfo = 0;
     set_dset_error(c, *r->condition,
-                   yaz_z3950oid_to_str(r->diagnosticSetId, &oclass),
+                   yaz_oid_to_string(yaz_oid_std(), 
+                                     r->diagnosticSetId, &oclass),
                    addinfo, 0);
 }
 
@@ -1680,11 +1733,11 @@ ZOOM_API(void)
     if (!rec)
         return;
     if (rec->wrbuf_marc)
-        wrbuf_free(rec->wrbuf_marc, 1);
+        wrbuf_destroy(rec->wrbuf_marc);
     if (rec->wrbuf_iconv)
-        wrbuf_free(rec->wrbuf_iconv, 1);
+        wrbuf_destroy(rec->wrbuf_iconv);
     if (rec->wrbuf_opac)
-        wrbuf_free(rec->wrbuf_opac, 1);
+        wrbuf_destroy(rec->wrbuf_opac);
     odr_destroy(rec->odr);
     xfree(rec);
 }
@@ -1737,7 +1790,7 @@ static const char *marc_iconv_return(ZOOM_record rec, int marc_type,
             yaz_iconv_close(cd);
         if (len)
             *len = wrbuf_len(rec->wrbuf_marc);
-        return wrbuf_buf(rec->wrbuf_marc);
+        return wrbuf_cstr(rec->wrbuf_marc);
     }
     yaz_marc_destroy(mt);
     if (cd)
@@ -1755,6 +1808,7 @@ static const char *record_iconv_return(ZOOM_record rec, int *len,
 
     *from = '\0';
     strcpy(to, "UTF-8");
+
     if (record_charset && *record_charset)
     {
         /* Use "from,to" or just "from" */
@@ -1776,32 +1830,15 @@ static const char *record_iconv_return(ZOOM_record rec, int *len,
 
     if (*from && *to && (cd = yaz_iconv_open(to, from)))
     {
-        char outbuf[12];
-        size_t inbytesleft = sz;
-        const char *inp = buf;
-        
         if (!rec->wrbuf_iconv)
             rec->wrbuf_iconv = wrbuf_alloc();
 
         wrbuf_rewind(rec->wrbuf_iconv);
 
-        while (inbytesleft)
-        {
-            size_t outbytesleft = sizeof(outbuf);
-            char *outp = outbuf;
-            size_t r = yaz_iconv(cd, (char**) &inp,
-                                 &inbytesleft, 
-                                 &outp, &outbytesleft);
-            if (r == (size_t) (-1))
-            {
-                int e = yaz_iconv_error(cd);
-                if (e != YAZ_ICONV_E2BIG)
-                    break;
-            }
-            wrbuf_write(rec->wrbuf_iconv, outbuf, outp - outbuf);
-        }
-        wrbuf_puts(rec->wrbuf_iconv, "");
-        buf = wrbuf_buf(rec->wrbuf_iconv);
+        wrbuf_iconv_write(rec->wrbuf_iconv, cd, buf, sz);
+        wrbuf_iconv_reset(rec->wrbuf_iconv, cd);
+
+        buf = wrbuf_cstr(rec->wrbuf_iconv);
         sz = wrbuf_len(rec->wrbuf_iconv);
         yaz_iconv_close(cd);
     }
@@ -1841,7 +1878,9 @@ ZOOM_API(int)
                 break;
             }
             if (diagset)
-                *diagset = yaz_z3950oid_to_str(ddf->diagnosticSetId, &oclass);
+                *diagset =
+                    yaz_oid_to_string(yaz_oid_std(),
+                                      ddf->diagnosticSetId, &oclass);
         }
         else
         {
@@ -1925,9 +1964,7 @@ ZOOM_API(const char *)
         if (npr->which == Z_NamePlusRecord_databaseRecord)
         {
             Z_External *r = (Z_External *) npr->u.databaseRecord;
-            oident *ent = oid_getentbyoid(r->direct_reference);
-            if (ent)
-                desc = ent->desc;
+            desc = yaz_oid_to_string(yaz_oid_std(), r->direct_reference, 0);
         }
         if (!desc)
             desc = "none";
@@ -1942,7 +1979,7 @@ ZOOM_API(const char *)
     if (!strcmp(type, "render"))
     {
         Z_External *r = (Z_External *) npr->u.databaseRecord;
-        oident *ent = oid_getentbyoid(r->direct_reference);
+        const int *oid = r->direct_reference;
 
         /* render bibliographic record .. */
         if (r->which == Z_External_OPAC)
@@ -1950,7 +1987,7 @@ ZOOM_API(const char *)
             r = r->u.opac->bibliographicRecord;
             if (!r)
                 return 0;
-            ent = oid_getentbyoid(r->direct_reference);
+            oid = r->direct_reference;
         }
         if (r->which == Z_External_sutrs)
             return record_iconv_return(rec, len,
@@ -1959,18 +1996,9 @@ ZOOM_API(const char *)
                                        charset);
         else if (r->which == Z_External_octet)
         {
-            const char *ret_buf;
-            switch (ent->value)
+            if (yaz_oid_is_iso2709(oid))
             {
-            case VAL_SOIF:
-            case VAL_HTML:
-            case VAL_SUTRS:
-                break;
-            case VAL_TEXT_XML:
-            case VAL_APPLICATION_XML:
-                break;
-            default:
-                ret_buf = marc_iconv_return(
+                const char *ret_buf = marc_iconv_return(
                     rec, YAZ_MARC_LINE, len,
                     (const char *) r->u.octet_aligned->buf,
                     r->u.octet_aligned->len,
@@ -1999,7 +2027,7 @@ ZOOM_API(const char *)
     else if (!strcmp(type, "xml"))
     {
         Z_External *r = (Z_External *) npr->u.databaseRecord;
-        oident *ent = oid_getentbyoid(r->direct_reference);
+        const int *oid = r->direct_reference;
 
         /* render bibliographic record .. */
         if (r->which == Z_External_OPAC)
@@ -2007,7 +2035,7 @@ ZOOM_API(const char *)
             r = r->u.opac->bibliographicRecord;
             if (!r)
                 return 0;
-            ent = oid_getentbyoid(r->direct_reference);
+            oid = r->direct_reference;
         }
         
         if (r->which == Z_External_sutrs)
@@ -2017,20 +2045,10 @@ ZOOM_API(const char *)
                                        charset);
         else if (r->which == Z_External_octet)
         {
-            const char *ret_buf;
             int marc_decode_type = YAZ_MARC_MARCXML;
-
-            switch (ent->value)
+            if (yaz_oid_is_iso2709(oid))
             {
-            case VAL_SOIF:
-            case VAL_HTML:
-            case VAL_SUTRS:
-                break;
-            case VAL_TEXT_XML:
-            case VAL_APPLICATION_XML:
-                break;
-            default:
-                ret_buf = marc_iconv_return(
+                const char *ret_buf = marc_iconv_return(
                     rec, marc_decode_type, len,
                     (const char *) r->u.octet_aligned->buf,
                     r->u.octet_aligned->len,
@@ -2247,7 +2265,7 @@ static void handle_records(ZOOM_connection c, Z_Records *sr,
                     resultset, *start, *count);
 
             /* transfer our response to search_nmem .. we need it later */
-            nmem_transfer(resultset->odr->mem, nmem);
+            nmem_transfer(odr_getmem(resultset->odr), nmem);
             nmem_destroy(nmem);
             if (present_phase && p->num_records == 0)
             {
@@ -2392,6 +2410,16 @@ static void handle_search_response(ZOOM_connection c, Z_SearchResponse *sr)
 
     resultset = c->tasks->u.search.resultset;
 
+    if (sr->resultSetStatus)
+    {
+        ZOOM_options_set_int(resultset->options, "resultSetStatus",
+                             *sr->resultSetStatus);
+    }
+    if (sr->presentStatus)
+    {
+        ZOOM_options_set_int(resultset->options, "presentStatus",
+                             *sr->presentStatus);
+    }
     handle_searchResult(c, resultset, sr->additionalSearchInfo);
 
     resultset->size = *sr->resultCount;
@@ -2416,7 +2444,7 @@ static int scan_response(ZOOM_connection c, Z_ScanResponse *res)
     if (res->entries && res->entries->nonsurrogateDiagnostics)
         response_diag(c, res->entries->nonsurrogateDiagnostics[0]);
     scan->scan_response = res;
-    nmem_transfer(scan->odr->mem, nmem);
+    nmem_transfer(odr_getmem(scan->odr), nmem);
     if (res->stepSize)
         ZOOM_options_set_int(scan->options, "stepSize", *res->stepSize);
     if (res->positionOfTerm)
@@ -2537,7 +2565,7 @@ static zoom_ret send_present(ZOOM_connection c)
 
     if (syntax && *syntax)
         req->preferredRecordSyntax =
-            yaz_str_to_z3950oid(c->odr_out, CLASS_RECSYN, syntax);
+            zoom_yaz_str_to_z3950oid(c, CLASS_RECSYN, syntax);
 
     if (resultset->schema && *resultset->schema)
     {
@@ -2557,14 +2585,14 @@ static zoom_ret send_present(ZOOM_connection c)
 
         compo->u.complex->generic->which = Z_Schema_oid;
         compo->u.complex->generic->schema.oid = (Odr_oid *)
-            yaz_str_to_z3950oid (c->odr_out, CLASS_SCHEMA, resultset->schema);
+            zoom_yaz_str_to_z3950oid (c, CLASS_SCHEMA, resultset->schema);
 
         if (!compo->u.complex->generic->schema.oid)
         {
             /* OID wasn't a schema! Try record syntax instead. */
 
             compo->u.complex->generic->schema.oid = (Odr_oid *)
-                yaz_str_to_z3950oid (c->odr_out, CLASS_RECSYN, resultset->schema);
+                zoom_yaz_str_to_z3950oid (c, CLASS_RECSYN, resultset->schema);
         }
         if (elementSetName && *elementSetName)
         {
@@ -2821,7 +2849,7 @@ ZOOM_API(void)
     ZOOM_options_set(scan->options, key, val);
 }
 
-static Z_APDU *create_es_package(ZOOM_package p, int type)
+static Z_APDU *create_es_package(ZOOM_package p, const char *type)
 {
     const char *str;
     Z_APDU *apdu = zget_APDU(p->odr_out, Z_APDU_extendedServicesRequest);
@@ -2831,14 +2859,14 @@ static Z_APDU *create_es_package(ZOOM_package p, int type)
     
     str = ZOOM_options_get(p->options, "package-name");
     if (str && *str)
-        req->packageName = nmem_strdup(p->odr_out->mem, str);
+        req->packageName = odr_strdup(p->odr_out, str);
     
     str = ZOOM_options_get(p->options, "user-id");
     if (str)
-        req->userId = nmem_strdup(p->odr_out->mem, str);
+        req->userId = odr_strdup(p->odr_out, str);
     
-    req->packageType = yaz_oidval_to_z3950oid(p->odr_out, CLASS_EXTSERV,
-                                              type);
+    req->packageType = yaz_string_to_oid_odr(yaz_oid_std(), CLASS_EXTSERV,
+                                             type, p->odr_out);
 
     str = ZOOM_options_get(p->options, "function");
     if (str)
@@ -2882,16 +2910,14 @@ static Z_External *encode_ill_request(ZOOM_package p)
     }
     else
     {
-        oident oid;
         int illRequest_size = 0;
         char *illRequest_buf = odr_getbuf(out, &illRequest_size, 0);
                 
-        oid.proto = PROTO_GENERAL;
-        oid.oclass = CLASS_GENERAL;
-        oid.value = VAL_ISO_ILL_1;
-                
         r = (Z_External *) odr_malloc(out, sizeof(*r));
-        r->direct_reference = odr_oiddup(out,oid_getoidbyent(&oid)); 
+        r->direct_reference = yaz_string_to_oid_odr(yaz_oid_std(),
+                                                    CLASS_GENERAL,
+                                                    OID_STR_ILL_1,
+                                                    out);
         r->indirect_reference = 0;
         r->descriptor = 0;
         r->which = Z_External_single;
@@ -2922,15 +2948,15 @@ static Z_ItemOrder *encode_item_order(ZOOM_package p)
         
     str = ZOOM_options_get(p->options, "contact-name");
     req->u.esRequest->toKeep->contact->name = str ?
-        nmem_strdup(p->odr_out->mem, str) : 0;
+        odr_strdup(p->odr_out, str) : 0;
         
     str = ZOOM_options_get(p->options, "contact-phone");
     req->u.esRequest->toKeep->contact->phone = str ?
-        nmem_strdup(p->odr_out->mem, str) : 0;
+        odr_strdup(p->odr_out, str) : 0;
         
     str = ZOOM_options_get(p->options, "contact-email");
     req->u.esRequest->toKeep->contact->email = str ?
-        nmem_strdup(p->odr_out->mem, str) : 0;
+        odr_strdup(p->odr_out, str) : 0;
         
     req->u.esRequest->toKeep->addlBilling = 0;
         
@@ -2950,7 +2976,7 @@ static Z_ItemOrder *encode_item_order(ZOOM_package p)
             odr_malloc(p->odr_out, sizeof(Z_IOResultSetItem));
 
         req->u.esRequest->notToKeep->resultSetItem->resultSetId =
-            nmem_strdup(p->odr_out->mem, str);
+            odr_strdup(p->odr_out, str);
         req->u.esRequest->notToKeep->resultSetItem->item =
             (int *) odr_malloc(p->odr_out, sizeof(int));
         
@@ -2958,7 +2984,15 @@ static Z_ItemOrder *encode_item_order(ZOOM_package p)
         *req->u.esRequest->notToKeep->resultSetItem->item =
             (str ? atoi(str) : 1);
     }
-    req->u.esRequest->notToKeep->itemRequest = encode_ill_request(p);
+
+    str = ZOOM_options_get(p->options, "doc");
+    if (str)
+    {
+        req->u.esRequest->notToKeep->itemRequest =
+            z_ext_record_xml(p->odr_out, str, strlen(str));
+    }
+    else
+        req->u.esRequest->notToKeep->itemRequest = encode_ill_request(p);
     
     return req;
 }
@@ -2967,7 +3001,7 @@ Z_APDU *create_admin_package(ZOOM_package p, int type,
                              Z_ESAdminOriginPartToKeep **toKeepP,
                              Z_ESAdminOriginPartNotToKeep **notToKeepP)
 {
-    Z_APDU *apdu = create_es_package(p, VAL_ADMINSERVICE);
+    Z_APDU *apdu = create_es_package(p, OID_STR_ADMIN);
     if (apdu)
     {
         Z_ESAdminOriginPartToKeep  *toKeep;
@@ -2981,8 +3015,8 @@ Z_APDU *create_admin_package(ZOOM_package p, int type,
             first_db = db[0];
             
         r->direct_reference =
-            yaz_oidval_to_z3950oid(p->odr_out, CLASS_EXTSERV,
-                                   VAL_ADMINSERVICE);
+            yaz_string_to_oid_odr(yaz_oid_std(),
+                                  CLASS_EXTSERV, OID_STR_ADMIN, p->odr_out);
         r->descriptor = 0;
         r->indirect_reference = 0;
         r->which = Z_External_ESAdmin;
@@ -3017,7 +3051,7 @@ Z_APDU *create_admin_package(ZOOM_package p, int type,
 
 static Z_APDU *create_xmlupdate_package(ZOOM_package p)
 {
-    Z_APDU *apdu = create_es_package(p, VAL_XMLES);
+    Z_APDU *apdu = create_es_package(p, OID_STR_XMLES);
     Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
     Z_External *ext = (Z_External *) odr_malloc(p->odr_out, sizeof(*ext));
     const char *doc = ZOOM_options_get(p->options, "doc");
@@ -3048,19 +3082,26 @@ static Z_APDU *create_update_package(ZOOM_package p)
     const char *recordIdNumber = ZOOM_options_get(p->options, "recordIdNumber");
     const char *record_buf = ZOOM_options_get(p->options, "record");
     const char *syntax_str = ZOOM_options_get(p->options, "syntax");
-    int syntax_oid = VAL_NONE;
     int action_no = -1;
-    
-    if (syntax_str)
-        syntax_oid = oid_getvalbyname(syntax_str);
+    int *syntax_oid = 0;
+
+    if (!syntax_str)
+        syntax_str = "xml";
     if (!record_buf)
     {
         record_buf = "void";
-        syntax_oid = VAL_SUTRS;
+        syntax_str = "SUTRS";
     }
-    if (syntax_oid == VAL_NONE)
-        syntax_oid = VAL_TEXT_XML;
-    
+
+    if (syntax_str)
+    {
+        syntax_oid = yaz_string_to_oid_odr(yaz_oid_std(),
+                                           CLASS_RECSYN, syntax_str,
+                                           p->odr_out);
+    }
+    if (!syntax_oid)
+        return 0;
+
     if (num_db > 0)
         first_db = db[0];
     
@@ -3080,7 +3121,7 @@ static Z_APDU *create_update_package(ZOOM_package p)
     else
         return 0;
 
-    apdu = create_es_package(p, VAL_DBUPDATE);
+    apdu = create_es_package(p, OID_STR_EXT_UPDATE);
     if (apdu)
     {
         Z_IUOriginPartToKeep *toKeep;
@@ -3089,10 +3130,11 @@ static Z_APDU *create_update_package(ZOOM_package p)
             odr_malloc(p->odr_out, sizeof(*r));
         
         apdu->u.extendedServicesRequest->taskSpecificParameters = r;
+
         
         r->direct_reference =
-            yaz_oidval_to_z3950oid(p->odr_out, CLASS_EXTSERV,
-                                   VAL_DBUPDATE);
+            yaz_string_to_oid_odr(yaz_oid_std(), CLASS_EXTSERV,
+                                  OID_STR_EXT_UPDATE, p->odr_out);
         r->descriptor = 0;
         r->which = Z_External_update;
         r->indirect_reference = 0;
@@ -3140,8 +3182,8 @@ static Z_APDU *create_update_package(ZOOM_package p)
         notToKeep->elements[0]->supplementalId = 0;
         notToKeep->elements[0]->correlationInfo = 0;
         notToKeep->elements[0]->record =
-            z_ext_record(p->odr_out, syntax_oid,
-                         record_buf, strlen(record_buf));
+            z_ext_record_oid(p->odr_out, syntax_oid,
+                             record_buf, strlen(record_buf));
     }
     if (0 && apdu)
     {
@@ -3166,14 +3208,14 @@ ZOOM_API(void)
     p->buf_out = 0;
     if (!strcmp(type, "itemorder"))
     {
-        apdu = create_es_package(p, VAL_ITEMORDER);
+        apdu = create_es_package(p, OID_STR_ITEMORDER);
         if (apdu)
         {
             Z_External *r = (Z_External *) odr_malloc(p->odr_out, sizeof(*r));
             
             r->direct_reference =
-                yaz_oidval_to_z3950oid(p->odr_out, CLASS_EXTSERV,
-                                       VAL_ITEMORDER);
+                yaz_string_to_oid_odr(yaz_oid_std(), CLASS_EXTSERV,
+                                      OID_STR_ITEMORDER, p->odr_out);
             r->descriptor = 0;
             r->which = Z_External_itemOrder;
             r->indirect_reference = 0;
@@ -3467,9 +3509,12 @@ static void recv_apdu(ZOOM_connection c, Z_APDU *apdu)
         }
         else
         {
+            const int *oid = yaz_string_to_oid(yaz_oid_std(),
+                                               CLASS_USERINFO,
+                                               OID_STR_COOKIE);
             char *cookie =
-                yaz_oi_get_string_oidval(&apdu->u.initResponse->otherInfo,
-                                         VAL_COOKIE, 1, 0);
+                yaz_oi_get_string_oid(&apdu->u.initResponse->otherInfo,
+                                      oid, 1, 0);
             xfree(c->cookie_in);
             c->cookie_in = 0;
             if (cookie)
@@ -3617,7 +3662,8 @@ static void handle_srw_response(ZOOM_connection c,
             odr_malloc(c->odr_in, sizeof(Z_External));
         npr->u.databaseRecord->descriptor = 0;
         npr->u.databaseRecord->direct_reference =
-            yaz_oidval_to_z3950oid(c->odr_in, CLASS_RECSYN, VAL_TEXT_XML);
+            yaz_string_to_oid_odr(yaz_oid_std(), CLASS_RECSYN, OID_STR_XML,
+                                  c->odr_in);
         npr->u.databaseRecord->which = Z_External_octet;
 
         npr->u.databaseRecord->u.octet_aligned = (Odr_oct *)
@@ -3643,7 +3689,7 @@ static void handle_srw_response(ZOOM_connection c,
         }
     }
     nmem = odr_extract_mem(c->odr_in);
-    nmem_transfer(resultset->odr->mem, nmem);
+    nmem_transfer(odr_getmem(resultset->odr), nmem);
     nmem_destroy(nmem);
 }
 #endif
@@ -3728,11 +3774,7 @@ static int do_read(ZOOM_connection c)
         return 0;
     if (r <= 0)
     {
-        if (ZOOM_test_reconnect(c))
-        {
-            yaz_log(log_details, "%p do_read reconnect read", c);
-        }
-        else
+        if (!ZOOM_test_reconnect(c))
         {
             set_ZOOM_error(c, ZOOM_ERROR_CONNECTION_LOST, c->host_port);
             do_close(c);
@@ -4023,12 +4065,7 @@ static void ZOOM_connection_do_io(ZOOM_connection c, int mask)
     {
         if (mask & ZOOM_SELECT_EXCEPT)
         {
-            if (ZOOM_test_reconnect(c))
-            {
-                event = ZOOM_Event_create(ZOOM_EVENT_CONNECT);
-                ZOOM_connection_put_event(c, event);
-            }
-            else
+            if (!ZOOM_test_reconnect(c))
             {
                 set_ZOOM_error(c, ZOOM_ERROR_CONNECTION_LOST, c->host_port);
                 do_close(c);
@@ -4051,6 +4088,12 @@ ZOOM_API(int)
 }
 
 
+static void cql2pqf_wrbuf_puts(const char *buf, void *client_data)
+{
+    WRBUF wrbuf = client_data;
+    wrbuf_puts(wrbuf, buf);
+}
+
 /*
  * Returns an xmalloc()d string containing RPN that corresponds to the
  * CQL passed in.  On error, sets the Connection object's error state
@@ -4061,10 +4104,9 @@ static char *cql2pqf(ZOOM_connection c, const char *cql)
 {
     CQL_parser parser;
     int error;
-    struct cql_node *node;
     const char *cqlfile;
-    static cql_transform_t trans;
-    char pqfbuf[512];
+    cql_transform_t trans;
+    char *result = 0;
 
     parser = cql_parser_create();
     if ((error = cql_parser_string(parser, cql)) != 0) {
@@ -4073,42 +4115,40 @@ static char *cql2pqf(ZOOM_connection c, const char *cql)
         return 0;
     }
 
-    node = cql_parser_result(parser);
-    /* ### Do not call cql_parser_destroy() yet: it destroys `node'! */
-
     cqlfile = ZOOM_connection_option_get(c, "cqlfile");
-    if (cqlfile == 0) {
-        cql_parser_destroy(parser);
-        cql_node_destroy(node);
+    if (cqlfile == 0) 
+    {
         set_ZOOM_error(c, ZOOM_ERROR_CQL_TRANSFORM, "no CQL transform file");
-        return 0;
     }
-
-    if ((trans = cql_transform_open_fname(cqlfile)) == 0) {
+    else if ((trans = cql_transform_open_fname(cqlfile)) == 0) 
+    {
         char buf[512];        
-        cql_parser_destroy(parser);
-        cql_node_destroy(node);
         sprintf(buf, "can't open CQL transform file '%.200s': %.200s",
                 cqlfile, strerror(errno));
         set_ZOOM_error(c, ZOOM_ERROR_CQL_TRANSFORM, buf);
-        return 0;
     }
-
-    error = cql_transform_buf(trans, node, pqfbuf, sizeof pqfbuf);
-    cql_parser_destroy(parser);
-    cql_node_destroy(node);
-    if (error != 0) {
-        char buf[512];
-        const char *addinfo;
-        error = cql_transform_error(trans, &addinfo);
+    else 
+    {
+        WRBUF wrbuf_result = wrbuf_alloc();
+        error = cql_transform(trans, cql_parser_result(parser),
+                              cql2pqf_wrbuf_puts, wrbuf_result);
+        if (error != 0) {
+            char buf[512];
+            const char *addinfo;
+            error = cql_transform_error(trans, &addinfo);
+            sprintf(buf, "%.200s (addinfo=%.200s)", 
+                    cql_strerror(error), addinfo);
+            set_ZOOM_error(c, ZOOM_ERROR_CQL_TRANSFORM, buf);
+        }
+        else
+        {
+            result = xstrdup(wrbuf_cstr(wrbuf_result));
+        }
         cql_transform_close(trans);
-        sprintf(buf, "%.200s (addinfo=%.200s)", cql_strerror(error), addinfo);
-        set_ZOOM_error(c, ZOOM_ERROR_CQL_TRANSFORM, buf);
-        return 0;
+        wrbuf_destroy(wrbuf_result);
     }
-
-    cql_transform_close(trans);
-    return xstrdup(pqfbuf);
+    cql_parser_destroy(parser);
+    return result;
 }
 
 ZOOM_API(int) ZOOM_connection_fire_event_timeout(ZOOM_connection c)