-/*
- * Copyright (C) 1995-2006, Index Data ApS
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2010 Index Data
* See the file LICENSE for details.
- *
- * $Id: yaz-illclient.c,v 1.3 2007-04-18 07:17:19 adam Exp $
*/
-/* NOTE - This is work in progress - not at all ready */
+/* WARNING - This is work in progress - not at all ready */
/** \file yaz-illclient.c
* \brief client for ILL requests (ISO 10161-1)
#include <yaz/odr.h>
#include <yaz/log.h>
#include <yaz/ill.h>
+#include <yaz/oclc-ill-req-ext.h>
+
+
+/* A structure for holding name-value pairs in a linked list */
+struct nameval {
+ char *name;
+ char *val;
+ struct nameval *next;
+};
/* A structure for storing all the arguments */
struct prog_args {
char *host;
char *auth_userid;
char *auth_passwd;
+ char *oclc_recno; /* record number in oclc-mode */
+ int oclc_auth; /* 1=use oclc-type auth */
+ struct nameval* namevals; /* circular list, points to last */
} ;
+
/* Call-back to be called for every field in the ill-request */
/* It can set values to any field, perhaps from the prog_args */
const char *get_ill_element(void *clientData, const char *element) {
- struct prog_args *args = clientData;
+ struct prog_args *args = (struct prog_args *) clientData;
+ struct nameval *nv=args->namevals;
char *ret=0;
- if (!strcmp(element,"foo")) {
- ret=args->host;
- } else if (!strcmp(element,"ill,protocol-version-num")) {
- ret="2";
- } else if (!strcmp(element,"ill,transaction-id,initial-requester-id,person-or-institution-symbol,institution")) {
- ret="IndexData";
- }
- yaz_log(YLOG_DEBUG,"get_ill_element: '%s' -> '%s' ", element, ret );
+ if (!nv)
+ return "";
+ do {
+ nv=nv->next;
+ /* printf("comparing '%s' with '%s' \n",element, nv->name ); */
+ if ( strcmp(element, nv->name) == 0 )
+ ret = nv->val;
+ } while ( ( !ret) && ( nv != args->namevals) );
+ yaz_log(YLOG_DEBUG,"get_ill_element:'%s'->'%s'", element, ret );
return ret;
}
/* * * * * * * * * * * * * * * * * */
+
+/** \brief parse a parameter string */
+/* string is like 'name=value' */
+struct nameval *parse_nameval( char *arg ) {
+ struct nameval *nv = (struct nameval *) xmalloc(sizeof(*nv));
+ char *p=arg;
+ int len;
+ if (!p || !*p)
+ return 0; /* yeah, leaks a bit of memory. so what */
+ while ( *p && ( *p != '=' ) )
+ p++;
+ len = p - arg;
+ if (!len)
+ return 0;
+ nv->name = (char *) xmalloc(len+1);
+ strncpy(nv->name, arg, len);
+ nv->name[len]='\0';
+ if (*p == '=' )
+ p++; /* skip the '=' */
+ else
+ return 0; /* oops, no '=' */
+ if (!*p)
+ return 0; /* no value */
+ nv->val=xstrdup(p);
+ nv->next=0;
+ yaz_log(YLOG_DEBUG,"parse_nameval: n='%s' v='%s'", nv->name, nv->val );
+ return nv;
+}
+
+/** \brief append nv to the list of namevals */
+void append_nameval (struct prog_args *args, struct nameval *nv) {
+ if (!nv)
+ return;
+ if (args->namevals) {
+ nv->next=args->namevals->next; /* first */
+ args->namevals->next=nv;
+ args->namevals=nv;
+ } else {
+ nv->next=nv;
+ args->namevals=nv;
+ }
+} /* append_nameval */
+
+/** \brief parse a parameter file */
+void parse_paramfile(char *arg, struct prog_args *args) {
+ FILE *f=fopen(arg,"r");
+#define BUFSIZE 4096
+ char buf[BUFSIZE];
+ int len;
+ struct nameval *nv;
+ if (!f) {
+ yaz_log(YLOG_FATAL,"Could not open param file '%s' ", arg);
+ printf("Could not open file '%s' \n",arg);
+ exit(1);
+ }
+ yaz_log(YLOG_DEBUG,"Opened input file '%s' ",arg );
+ while (fgets(buf,BUFSIZE,f)) {
+ if (buf[0] != '#' ) {
+ len=strlen(buf)-1;
+ if (buf[len] == '\n')
+ buf[len] = '\0' ;
+ nv=parse_nameval(buf);
+ append_nameval(args, nv);
+ } /* not a comment */
+ }
+ (void) fclose(f);
+
+ if (0) {
+ nv=args->namevals;
+ printf("nv chain: ================ \n");
+ printf("(last:) %p: '%s' = '%s' (%p) \n",nv, nv->name, nv->val, nv->next );
+ do {
+ nv=nv->next;
+ printf("%p: '%s' = '%s' (%p)\n",nv, nv->name, nv->val, nv->next );
+ } while (nv != args->namevals );
+ exit(1);
+ }
+
+} /* parse_paramfile */
+
+
/** \brief Parse program arguments */
void parseargs( int argc, char * argv[], struct prog_args *args) {
int ret;
char *arg;
char *prog=*argv;
- char *version="$Id: yaz-illclient.c,v 1.3 2007-04-18 07:17:19 adam Exp $"; /* from cvs */
+ char version[60];
+ struct nameval *nv;
/* default values */
args->host = 0; /* not known (yet) */
+ args->namevals=0; /* none set up */
+ args->oclc_auth=0;
+ args->oclc_recno=0;
+ args->auth_userid = 0;
+ args->auth_passwd = 0;
#if 0
- args->auth_userid = "100-228-301" ; /* FIXME - get from cmd line */
- args->auth_passwd = "dxg5magxc" ; /* FIXME - get from cmd line */
-#else
- args->auth_userid = "100070049" ; /* FIXME - get from cmd line */
- args->auth_passwd = "cowgirl" ; /* FIXME - get from cmd line */
+ /* Example 3 - directly from OCLC, supposed to work on their test server*/
+ args->auth_userid = "100-310-658" ; /* FIXME - get from cmd line */
+ args->auth_passwd = "apii2test" ; /* FIXME - get from cmd line */
#endif
-
- while ((ret = options("k:c:q:a:b:m:v:p:u:t:Vxd:", argv, argc, &arg)) != -2)
+ while ((ret = options("Vov:p:u:D:f:r:l:", argv, argc, &arg)) != -2)
{
+ yaz_log(YLOG_DEBUG,"parsing option '%c' '%s'",ret, arg);
switch (ret)
{
case 0:
}
else
{
- fprintf(stderr, "%s: Specify most one server address\n",
+ fprintf(stderr, "%s: Specify at most one server address\n",
prog);
exit(1);
}
case 'v':
yaz_log_init(yaz_log_mask_str(arg), "", 0);
break;
+ case 'l':
+ yaz_log_init_file(arg);
+ break;
case 'V':
- printf("%s %s",prog, version );
+ yaz_version(version, 0);
+ printf("%s %s\n",prog, version);
+ break;
+ case 'D':
+ nv=parse_nameval(arg);
+ append_nameval(args,nv);
+ break;
+ case 'f':
+ parse_paramfile(arg,args);
+ break;
+ case 'o':
+ args->oclc_auth=1;
+ break;
+ case 'u':
+ args->auth_userid=xstrdup(arg);
+ break;
+ case 'p':
+ args->auth_passwd=xstrdup(arg);
+ break;
+ case 'r':
+ args->oclc_recno=xstrdup(arg);
break;
default:
fprintf (stderr, "Usage: %s "
+ " [-f filename]"
" [-v loglevel...]"
+ " [-D name=value ]"
+ " [-o -u user -p passwd]"
" [-V]"
" <server-addr>\n",
prog);
"as in 'bagel.indexdata.dk:210' \n");
exit(1);
}
+ if (args->oclc_auth && ((!args->auth_userid) || (!args->auth_passwd))){
+ fprintf(stderr, "-o option requires -u <user> and -p <pwd>\n");
+ exit(1);
+ }
} /* validateargs */
/* * * * * * * * * * * * * * * */
/* Makes a Z39.50-like prompt package with username and password */
Z_PromptObject1 *makeprompt(struct prog_args *args, ODR odr) {
- Z_PromptObject1 *p = odr_malloc(odr, sizeof(*p) );
- Z_ResponseUnit1 *ru;
+ Z_PromptObject1 *p = (Z_PromptObject1 *) odr_malloc(odr, sizeof(*p) );
+ Z_ResponseUnit1 *ru = (Z_ResponseUnit1 *) odr_malloc(odr, sizeof(*ru) );
p->which=Z_PromptObject1_response;
- p->u.response = odr_malloc(odr, sizeof(*(p->u.response)) );
+ p->u.response = (Z_Response1*) odr_malloc(odr, sizeof(*(p->u.response)) );
p->u.response->num=2;
- p->u.response->elements=odr_malloc(odr,
+ p->u.response->elements= (Z_ResponseUnit1 **) odr_malloc(odr,
p->u.response->num*sizeof(*(p->u.response->elements)) );
/* user id, aka "oclc authorization number" */
- ru = odr_malloc(odr, sizeof(*ru) );
p->u.response->elements[0] = ru;
- ru->promptId = odr_malloc(odr, sizeof(*(ru->promptId) ));
+ ru->promptId = (Z_PromptId *) odr_malloc(odr, sizeof(*(ru->promptId) ));
ru->promptId->which = Z_PromptId_enumeratedPrompt;
- ru->promptId->u.enumeratedPrompt =
+ ru->promptId->u.enumeratedPrompt = (Z_PromptIdEnumeratedPrompt *)
odr_malloc(odr, sizeof(*(ru->promptId->u.enumeratedPrompt) ));
ru->promptId->u.enumeratedPrompt->type =
odr_intdup(odr,Z_PromptIdEnumeratedPrompt_userId);
ru->which = Z_ResponseUnit1_string ;
ru->u.string = odr_strdup(odr, args->auth_userid);
/* password */
- ru = odr_malloc(odr, sizeof(*ru) );
+ ru = (Z_ResponseUnit1 *) odr_malloc(odr, sizeof(*ru) );
p->u.response->elements[1] = ru;
- ru->promptId = odr_malloc(odr, sizeof(*(ru->promptId) ));
+ ru->promptId = (Z_PromptId *) odr_malloc(odr, sizeof(*(ru->promptId) ));
ru->promptId->which = Z_PromptId_enumeratedPrompt;
- ru->promptId->u.enumeratedPrompt =
+ ru->promptId->u.enumeratedPrompt = (Z_PromptIdEnumeratedPrompt *)
odr_malloc(odr, sizeof(*(ru->promptId->u.enumeratedPrompt) ));
ru->promptId->u.enumeratedPrompt->type =
odr_intdup(odr,Z_PromptIdEnumeratedPrompt_password);
ILL_Extension *makepromptextension(struct prog_args *args, ODR odr) {
ODR odr_ext = odr_createmem(ODR_ENCODE);
ODR odr_prt = odr_createmem(ODR_PRINT);
- ILL_Extension *e = odr_malloc(odr, sizeof(*e));
+ ILL_Extension *e = (ILL_Extension *) odr_malloc(odr, sizeof(*e));
Z_PromptObject1 *p = makeprompt(args,odr_ext);
char * buf;
int siz;
- Z_External *ext = odr_malloc(odr, sizeof(*ext));
+ Z_External *ext = (Z_External *) odr_malloc(odr, sizeof(*ext));
ext->direct_reference = odr_getoidbystr(odr,"1.2.840.10003.8.1");
ext->indirect_reference=0;
ext->descriptor=0;
exit (6);
}
+ printf ("Prompt: \n"); /*!*/
z_PromptObject1(odr_prt, &p, 0,0 ); /*!*/
buf= odr_getbuf(odr_ext,&siz,0);
- ext->u.single_ASN1_type=odr_malloc(odr,sizeof(*ext->u.single_ASN1_type));
- ext->u.single_ASN1_type->buf= odr_malloc(odr, siz);
+ ext->u.single_ASN1_type=(Odr_any *)
+ odr_malloc(odr,sizeof(*ext->u.single_ASN1_type));
+ ext->u.single_ASN1_type->buf= (unsigned char *) odr_malloc(odr, siz);
memcpy(ext->u.single_ASN1_type->buf,buf, siz );
ext->u.single_ASN1_type->len = ext->u.single_ASN1_type->size = siz;
odr_reset(odr_ext);
+ odr_reset(odr_prt); /*!*/
e->identifier = odr_intdup(odr,1);
- e->critical = odr_intdup(odr,0);
- e->item=odr_malloc(odr,sizeof(*e->item));
+ e->critical = odr_booldup(odr,0);
+ e->item = (Odr_any *) odr_malloc(odr,sizeof(*e->item));
if ( ! z_External(odr_ext, &ext,0,0) ) {
yaz_log(YLOG_FATAL,"Encoding of z_External failed ");
exit (6);
}
+ printf("External: \n");
+ z_External(odr_prt, &ext,0,0); /*!*/
buf= odr_getbuf(odr_ext,&siz,0);
- e->item->buf= odr_malloc(odr, siz);
+ e->item->buf= (unsigned char *) odr_malloc(odr, siz);
memcpy(e->item->buf,buf, siz );
e->item->len = e->item->size = siz;
+ odr_destroy(odr_prt);
+ odr_destroy(odr_ext);
return e;
} /* makepromptextension */
+ILL_Extension *makeoclcextension(struct prog_args *args, ODR odr) {
+ /* The oclc extension is required, but only contains optional */
+ /* fields. Here we just null them all out */
+ ODR odr_ext = odr_createmem(ODR_ENCODE);
+ ODR odr_prt = odr_createmem(ODR_PRINT);
+ ILL_Extension *e = (ILL_Extension *) odr_malloc(odr, sizeof(*e));
+ ILL_OCLCILLRequestExtension *oc = (ILL_OCLCILLRequestExtension *)
+ odr_malloc(odr_ext, sizeof(*oc));
+ char * buf;
+ int siz;
+ Z_External *ext = (Z_External *) odr_malloc(odr, sizeof(*ext));
+ oc->clientDepartment = 0;
+ oc->paymentMethod = 0;
+ oc->uniformTitle = 0;
+ oc->dissertation = 0;
+ oc->issueNumber = 0;
+ oc->volume = 0;
+ oc->affiliations = 0;
+ oc->source = 0;
+ ext->direct_reference = odr_getoidbystr(odr,"1.0.10161.13.2");
+ ext->indirect_reference=0;
+ ext->descriptor=0;
+ ext->which=Z_External_single;
+ if ( ! ill_OCLCILLRequestExtension(odr_ext, &oc, 0,0 ) ) {
+ yaz_log(YLOG_FATAL,"Encoding of ill_OCLCILLRequestExtension failed ");
+ exit (6);
+ }
+
+ printf ("OCLC: \n"); /*!*/
+ ill_OCLCILLRequestExtension(odr_prt, &oc, 0,0 ); /*!*/
+
+ buf= odr_getbuf(odr_ext,&siz,0);
+ ext->u.single_ASN1_type = (Odr_any*)
+ odr_malloc(odr,sizeof(*ext->u.single_ASN1_type));
+ ext->u.single_ASN1_type->buf = (unsigned char *) odr_malloc(odr, siz);
+ memcpy(ext->u.single_ASN1_type->buf,buf, siz );
+ ext->u.single_ASN1_type->len = ext->u.single_ASN1_type->size = siz;
+ odr_reset(odr_ext);
+ odr_reset(odr_prt); /*!*/
+
+ e->identifier = odr_intdup(odr,1);
+ e->critical = odr_booldup(odr,0);
+ e->item = (Odr_any *) odr_malloc(odr,sizeof(*e->item));
+ if ( ! z_External(odr_ext, &ext,0,0) ) {
+ yaz_log(YLOG_FATAL,"Encoding of z_External failed ");
+ exit (6);
+ }
+ printf("External: \n");
+ z_External(odr_prt, &ext,0,0); /*!*/
+ buf= odr_getbuf(odr_ext,&siz,0);
+ e->item->buf= (unsigned char *) odr_malloc(odr, siz);
+ memcpy(e->item->buf, buf, siz);
+ e->item->len = e->item->size = siz;
+
+ odr_destroy(odr_prt);
+ odr_destroy(odr_ext);
+ return e;
+
+} /* makeoclcextension */
+
ILL_APDU *createrequest( struct prog_args *args, ODR odr) {
struct ill_get_ctl ctl;
ILL_APDU *apdu;
ILL_Request *req;
ctl.odr = odr;
- ctl.clientData = & args;
+ ctl.clientData = args;
ctl.f = get_ill_element;
- apdu = odr_malloc( odr, sizeof(*apdu) );
+ apdu = (ILL_APDU *) odr_malloc( odr, sizeof(*apdu) );
apdu->which=ILL_APDU_ILL_Request;
req = ill_get_ILLRequest(&ctl, "ill", 0);
apdu->u.illRequest=req;
- req->num_iLL_request_extensions=1;
- req->iLL_request_extensions=
- odr_malloc(odr, req->num_iLL_request_extensions*sizeof(*req->iLL_request_extensions));
- req->iLL_request_extensions[0]=makepromptextension(args,odr);
+ if (args->oclc_auth) {
+ req->num_iLL_request_extensions=2;
+ req->iLL_request_extensions=
+ (ILL_Extension **)
+ odr_malloc(odr, req->num_iLL_request_extensions*
+ sizeof(*req->iLL_request_extensions));
+ req->iLL_request_extensions[0]=makepromptextension(args,odr);
+ req->iLL_request_extensions[1]=makeoclcextension(args,odr);
+ }
if (!req) {
yaz_log(YLOG_FATAL,"Could not create ill request");
exit(2);
yaz_log(YLOG_FATAL,"Could not send packet. code %d",res );
exit (4);
}
+ if (1) {
+ FILE *F = fopen("req.apdu","w");
+ if (!F)
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "open req.apdu failed");
+ }
+ else
+ {
+ if (fwrite ( buf_out, 1, len_out, F) != len_out)
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "write req.apdu failed");
+ if (fclose(F))
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "write req.apdu failed");
+ }
+ }
+
} /* sendrequest */
/* * * * * * * * * * * * * * * */
printf("Already forwarded: \n");
break;
case ILL_User_Error_Report_intermediary_problem:
- printf("Intermediary problem: %p\n",
- uerr->u.intermediary_problem);
+ printf("Intermediary problem: " ODR_INT_PRINTF "\n",
+ *uerr->u.intermediary_problem);
break;
case ILL_User_Error_Report_security_problem:
printf("Security problem: %s\n",
getillstring(uerr->u.security_problem));
break;
case ILL_User_Error_Report_unable_to_perform:
- printf("Unable to perform: %p\n",
- uerr->u.unable_to_perform);
+ printf("Unable to perform: " ODR_INT_PRINTF "\n",
+ *uerr->u.unable_to_perform);
break;
default:
printf("Unknown problem");
ILL_Provider_Error_Report *perr= err->provider_error_report;
switch( perr->which ) {
case ILL_Provider_Error_Report_general_problem:
- printf("General Problem: %p\n",
- perr->u.general_problem);
+ printf("General Problem: " ODR_INT_PRINTF ":",
+ *perr->u.general_problem);
break;
case ILL_Provider_Error_Report_transaction_id_problem:
- printf("Transaction Id Problem: %p\n",
- perr->u.general_problem);
+ printf("Transaction Id Problem: " ODR_INT_PRINTF ":",
+ *perr->u.general_problem);
break;
case ILL_Provider_Error_Report_state_transition_prohibited:
- printf("State Transition prohibited \n");
+ printf("State Transition prohibited:");
break;
}
- exit(7);
+ /*exit(7);*/
}
/* fallbacks */
if ( staterr->note )
printf("%s", getillstring(staterr->note));
else
printf("Unknown error type");
+ printf("\n");
exit(7);
}
} /* checkerr */
/*
* Local variables:
* c-basic-offset: 4
+ * c-file-style: "Stroustrup"
* indent-tabs-mode: nil
* End:
* vim: shiftwidth=4 tabstop=8 expandtab