+int client_show_raw_begin(struct client *cl, int position,
+ const char *syntax, const char *esn,
+ void *data,
+ void (*error_handler)(void *data, const char *addinfo),
+ void (*record_handler)(void *data, const char *buf,
+ size_t sz),
+ void **data2,
+ int binary)
+{
+ struct show_raw *rr, **rrp;
+ if (!cl->connection)
+ { /* the client has no connection */
+ return -1;
+ }
+ rr = xmalloc(sizeof(*rr));
+ *data2 = rr;
+ rr->position = position;
+ rr->active = 0;
+ rr->data = data;
+ rr->error_handler = error_handler;
+ rr->record_handler = record_handler;
+ rr->binary = binary;
+ if (syntax)
+ rr->syntax = xstrdup(syntax);
+ else
+ rr->syntax = 0;
+ if (esn)
+ rr->esn = xstrdup(esn);
+ else
+ rr->esn = 0;
+ rr->next = 0;
+
+ for (rrp = &cl->show_raw; *rrp; rrp = &(*rrp)->next)
+ ;
+ *rrp = rr;
+
+ if (cl->state == Client_Failed)
+ {
+ client_show_raw_error(cl, "client failed");
+ }
+ else if (cl->state == Client_Disconnected)
+ {
+ client_show_raw_error(cl, "client disconnected");
+ }
+ else
+ {
+ client_continue(cl);
+ }
+ return 0;
+}
+
+void client_show_raw_remove(struct client *cl, void *data)
+{
+ struct show_raw *rr = data;
+ struct show_raw **rrp = &cl->show_raw;
+ while (*rrp != rr)
+ rrp = &(*rrp)->next;
+ if (*rrp)
+ {
+ *rrp = rr->next;
+ xfree(rr);
+ }
+}
+
+void client_show_raw_dequeue(struct client *cl)
+{
+ struct show_raw *rr = cl->show_raw;
+
+ cl->show_raw = rr->next;
+ xfree(rr);
+}
+
+static void client_show_raw_error(struct client *cl, const char *addinfo)
+{
+ while (cl->show_raw)
+ {
+ cl->show_raw->error_handler(cl->show_raw->data, addinfo);
+ client_show_raw_dequeue(cl);
+ }
+}
+
+static void client_show_raw_cancel(struct client *cl)
+{
+ while (cl->show_raw)
+ {
+ cl->show_raw->error_handler(cl->show_raw->data, "cancel");
+ client_show_raw_dequeue(cl);
+ }
+}
+
+static void client_present_syntax(Z_APDU *a, const char *syntax)
+{
+ // empty string for syntax OMITS preferredRecordSyntax (OPTIONAL)
+ if (syntax && *syntax)
+ a->u.presentRequest->preferredRecordSyntax =
+ yaz_string_to_oid_odr(yaz_oid_std(),
+ CLASS_RECSYN, syntax,
+ global_parameters.odr_out);
+}
+
+static void client_present_elements(Z_APDU *a, const char *elements)
+{
+ if (elements && *elements) // element set is optional
+ {
+ Z_ElementSetNames *elementSetNames =
+ odr_malloc(global_parameters.odr_out, sizeof(*elementSetNames));
+ Z_RecordComposition *compo =
+ odr_malloc(global_parameters.odr_out, sizeof(*compo));
+ a->u.presentRequest->recordComposition = compo;
+
+ compo->which = Z_RecordComp_simple;
+ compo->u.simple = elementSetNames;
+
+ elementSetNames->which = Z_ElementSetNames_generic;
+ elementSetNames->u.generic =
+ odr_strdup(global_parameters.odr_out, elements);
+ }
+}
+
+void client_send_raw_present(struct client *cl)
+{
+ struct session_database *sdb = client_get_database(cl);
+ Z_APDU *a = zget_APDU(global_parameters.odr_out, Z_APDU_presentRequest);
+ int toget = 1;
+ int start = cl->show_raw->position;
+ const char *syntax = 0;
+ const char *elements = 0;
+
+ assert(cl->show_raw);
+
+ yaz_log(YLOG_DEBUG, "%s: trying to present %d record(s) from %d",
+ client_get_url(cl), toget, start);
+
+ a->u.presentRequest->resultSetStartPoint = &start;
+ a->u.presentRequest->numberOfRecordsRequested = &toget;
+
+ if (cl->show_raw->syntax)
+ syntax = cl->show_raw->syntax;
+ else
+ syntax = session_setting_oneval(sdb, PZ_REQUESTSYNTAX);
+
+ client_present_syntax(a, syntax);
+ if (cl->show_raw->esn)
+ elements = cl->show_raw->esn;
+ else
+ elements = session_setting_oneval(sdb, PZ_ELEMENTS);
+ client_present_elements(a, elements);
+
+ if (send_apdu(cl, a) >= 0)
+ {
+ cl->show_raw->active = 1;
+ cl->state = Client_Presenting;
+ }
+ else
+ {
+ client_show_raw_error(cl, "send_apdu failed");
+ cl->state = Client_Error;
+ }
+ odr_reset(global_parameters.odr_out);
+}
+