X-Git-Url: http://lists.indexdata.dk/cgi-bin?a=blobdiff_plain;f=src%2Fpazpar2.c;h=79bc2bafde4795d1f42e23e7d001c53cc55ef482;hb=acd965f3e537fd2449d99a8ce7ee731112cd7c4e;hp=9465ef65b650a55a9efbc96e08ec3e842f89e910;hpb=59f03637638041bd0e8540c0ab76991dc178bdbf;p=pazpar2-moved-to-github.git diff --git a/src/pazpar2.c b/src/pazpar2.c index 9465ef6..79bc2ba 100644 --- a/src/pazpar2.c +++ b/src/pazpar2.c @@ -1,4 +1,4 @@ -/* $Id: pazpar2.c,v 1.60 2007-04-03 03:55:12 quinn Exp $ */ +/* $Id: pazpar2.c,v 1.66 2007-04-08 22:38:45 quinn Exp $ */ #include #include @@ -48,9 +48,8 @@ static void client_fatal(struct client *cl); static void connection_destroy(struct connection *co); static int client_prep_connection(struct client *cl); static void ingest_records(struct client *cl, Z_Records *r); -//static struct conf_retrievalprofile *database_retrieval_profile(struct database *db); void session_alert_watch(struct session *s, int what); -char *session_setting_oneval(struct session *s, struct database *db, const char *name); +char *session_setting_oneval(struct session *s, struct database *db, int offset); IOCHAN channel_list = 0; // Master list of connections we're handling events to @@ -88,7 +87,6 @@ struct parameters global_parameters = 100, MAX_CHUNK, 0, - 0, 0 }; @@ -120,6 +118,23 @@ static int send_apdu(struct client *c, Z_APDU *a) return 0; } +// Set authentication token in init if one is set for the client +// TODO: Extend this to handle other schemes than open (should be simple) +static void init_authentication(struct client *cl, Z_InitRequest *req) +{ + struct database *db = cl->database; + struct session *se = cl->session; + char *auth = session_setting_oneval(se, db, PZ_AUTHENTICATION); + + if (auth) + { + Z_IdAuthentication *idAuth = odr_malloc(global_parameters.odr_out, + sizeof(*idAuth)); + idAuth->which = Z_IdAuthentication_open; + idAuth->u.open = auth; + req->idAuthentication = idAuth; + } +} static void send_init(IOCHAN i) { @@ -140,6 +155,7 @@ static void send_init(IOCHAN i) ODR_MASK_SET(a->u.initRequest->protocolVersion, Z_ProtocolVersion_2); ODR_MASK_SET(a->u.initRequest->protocolVersion, Z_ProtocolVersion_3); + init_authentication(cl, a->u.initRequest); /* add virtual host if tunneling through Z39.50 proxy */ @@ -148,8 +164,6 @@ static void send_init(IOCHAN i) yaz_oi_set_string_oidval(&a->u.initRequest->otherInfo, global_parameters.odr_out, VAL_PROXY, 1, cl->database->url); - - if (send_apdu(cl, a) >= 0) { @@ -231,9 +245,9 @@ static void send_search(IOCHAN i) for (ndb = 0; db->databases[ndb]; ndb++) databaselist[ndb] = db->databases[ndb]; - if (!(piggyback = session_setting_oneval(se, db, "pz:piggyback")) || *piggyback == '1') + if (!(piggyback = session_setting_oneval(se, db, PZ_PIGGYBACK)) || *piggyback == '1') { - if ((recsyn = session_setting_oneval(se, db, "pz:syntax"))) + if ((recsyn = session_setting_oneval(se, db, PZ_NATIVESYNTAX))) a->u.searchRequest->preferredRecordSyntax = yaz_str_to_z3950oid(global_parameters.odr_out, CLASS_RECSYN, recsyn); @@ -281,7 +295,7 @@ static void send_present(IOCHAN i) a->u.presentRequest->resultSetId = "Default"; - if ((recsyn = session_setting_oneval(se, db, "pz:syntax"))) + if ((recsyn = session_setting_oneval(se, db, PZ_NATIVESYNTAX))) a->u.presentRequest->preferredRecordSyntax = yaz_str_to_z3950oid(global_parameters.odr_out, CLASS_RECSYN, recsyn); @@ -302,7 +316,7 @@ static void do_initResponse(IOCHAN i, Z_APDU *a) struct client *cl = co->client; Z_InitResponse *r = a->u.initResponse; - yaz_log(YLOG_DEBUG, "Received init response"); + yaz_log(YLOG_DEBUG, "Init response %s", cl->database->url); if (*r->result) { @@ -319,7 +333,8 @@ static void do_searchResponse(IOCHAN i, Z_APDU *a) struct session *se = cl->session; Z_SearchResponse *r = a->u.searchResponse; - yaz_log(YLOG_DEBUG, "Searchresponse (status=%d)", *r->searchStatus); + yaz_log(YLOG_DEBUG, "Search response %s (status=%d)", + cl->database->url, *r->searchStatus); if (*r->searchStatus) { @@ -327,7 +342,8 @@ static void do_searchResponse(IOCHAN i, Z_APDU *a) se->total_hits += cl->hits; if (r->presentStatus && !*r->presentStatus && r->records) { - yaz_log(YLOG_DEBUG, "Records in search response"); + yaz_log(YLOG_DEBUG, "Records in search response %s", + cl->database->url); ingest_records(cl, r->records); } cl->state = Client_Idle; @@ -340,7 +356,9 @@ static void do_searchResponse(IOCHAN i, Z_APDU *a) Z_Records *recs = r->records; if (recs->which == Z_Records_NSD) { - yaz_log(YLOG_WARN, "Non-surrogate diagnostic"); + yaz_log(YLOG_WARN, + "Search response: Non-surrogate diagnostic %s", + cl->database->url); cl->diagnostic = *recs->u.nonSurrogateDiagnostic->condition; cl->state = Client_Error; } @@ -348,6 +366,19 @@ static void do_searchResponse(IOCHAN i, Z_APDU *a) } } +static void do_closeResponse(IOCHAN i, Z_APDU *a) +{ + struct connection *co = iochan_getdata(i); + struct client *cl = co->client; + /* Z_Close *r = a->u.close; */ + + yaz_log(YLOG_WARN, "Close response %s", cl->database->url); + + cl->state = Client_Failed; + connection_destroy(co); +} + + char *normalize_mergekey(char *buf, int skiparticle) { char *p = buf, *pout = buf; @@ -389,42 +420,6 @@ char *normalize_mergekey(char *buf, int skiparticle) return buf; } - -#ifdef GAGA -// FIXME needs to be generalized. Should flexibly generate X lists per search -static void extract_subject(struct session *s, const char *rec) -{ - const char *field, *subfield; - - while ((field = find_field(rec, "650"))) - { - rec = field; - if ((subfield = find_subfield(field, 'a'))) - { - char *e, *ef; - char buf[1024]; - int len; - - ef = index(subfield, '\n'); - if (!ef) - return; - if ((e = index(subfield, '\t')) && e < ef) - ef = e; - while (ef > subfield && !isalpha(*(ef - 1)) && *(ef - 1) != ')') - ef--; - len = ef - subfield; - assert(len < 1023); - memcpy(buf, subfield, len); - buf[len] = '\0'; -#ifdef FIXME - if (*buf) - termlist_insert(s->termlist, buf); -#endif - } - } -} -#endif - static void add_facet(struct session *s, const char *type, const char *value) { int i; @@ -450,32 +445,35 @@ static void add_facet(struct session *s, const char *type, const char *value) static xmlDoc *normalize_record(struct client *cl, Z_External *rec) { - struct conf_retrievalprofile *rprofile = cl->database->rprofile; - struct conf_retrievalmap *m; + struct database_retrievalmap *m; + struct database *db = cl->database; xmlNode *res; xmlDoc *rdoc; // First normalize to XML - if (rprofile->native_syntax == Nativesyn_iso2709) + if (db->yaz_marc) { char *buf; int len; if (rec->which != Z_External_octet) { - yaz_log(YLOG_WARN, "Unexpected external branch, probably BER"); + yaz_log(YLOG_WARN, "Unexpected external branch, probably BER %s", + cl->database->url); return 0; } buf = (char*) rec->u.octet_aligned->buf; len = rec->u.octet_aligned->len; - if (yaz_marc_read_iso2709(rprofile->yaz_marc, buf, len) < 0) + if (yaz_marc_read_iso2709(db->yaz_marc, buf, len) < 0) { - yaz_log(YLOG_WARN, "Failed to decode MARC"); + yaz_log(YLOG_WARN, "Failed to decode MARC %s", + cl->database->url); return 0; } - if (yaz_marc_write_xml(rprofile->yaz_marc, &res, + if (yaz_marc_write_xml(db->yaz_marc, &res, "http://www.loc.gov/MARC21/slim", 0, 0) < 0) { - yaz_log(YLOG_WARN, "Failed to encode as XML"); + yaz_log(YLOG_WARN, "Failed to encode as XML %s", + cl->database->url); return 0; } rdoc = xmlNewDoc((xmlChar *) "1.0"); @@ -497,14 +495,9 @@ static xmlDoc *normalize_record(struct client *cl, Z_External *rec) #endif } - for (m = rprofile->maplist; m; m = m->next) + for (m = db->map; m; m = m->next) { xmlDoc *new; - if (m->type != Map_xslt) - { - yaz_log(YLOG_WARN, "Unknown map type"); - return 0; - } if (!(new = xsltApplyStylesheet(m->stylesheet, rdoc, 0))) { yaz_log(YLOG_WARN, "XSLT transformation failed"); @@ -780,12 +773,8 @@ static struct record *ingest_record(struct client *cl, Z_External *rec) // Retrieve first defined value for 'name' for given database. // Will be extended to take into account user associated with session -char *session_setting_oneval(struct session *s, struct database *db, const char *name) +char *session_setting_oneval(struct session *s, struct database *db, int offset) { - int offset = settings_offset(name); - - if (offset < 0) - return 0; if (!db->settings[offset]) return 0; return db->settings[offset]->value; @@ -811,7 +800,9 @@ static void ingest_records(struct client *cl, Z_Records *r) cl->records++; if (npr->which != Z_NamePlusRecord_databaseRecord) { - yaz_log(YLOG_WARN, "Unexpected record type, probably diagnostic"); + yaz_log(YLOG_WARN, + "Unexpected record type, probably diagnostic %s", + cl->database->url); continue; } @@ -841,7 +832,8 @@ static void do_presentResponse(IOCHAN i, Z_APDU *a) Z_Records *recs = r->records; if (recs->which == Z_Records_NSD) { - yaz_log(YLOG_WARN, "Non-surrogate diagnostic"); + yaz_log(YLOG_WARN, "Non-surrogate diagnostic %s", + cl->database->url); cl->diagnostic = *recs->u.nonSurrogateDiagnostic->condition; cl->state = Client_Error; } @@ -849,13 +841,15 @@ static void do_presentResponse(IOCHAN i, Z_APDU *a) if (!*r->presentStatus && cl->state != Client_Error) { - yaz_log(YLOG_DEBUG, "Good Present response"); + yaz_log(YLOG_DEBUG, "Good Present response %s", + cl->database->url); ingest_records(cl, r->records); cl->state = Client_Idle; } else if (*r->presentStatus) { - yaz_log(YLOG_WARN, "Bad Present response"); + yaz_log(YLOG_WARN, "Bad Present response %s", + cl->database->url); cl->state = Client_Error; } } @@ -901,13 +895,14 @@ static void handler(IOCHAN i, int event) if (len < 0) { - yaz_log(YLOG_WARN|YLOG_ERRNO, "Error reading from Z server"); + yaz_log(YLOG_WARN|YLOG_ERRNO, "Error reading from %s", + cl->database->url); connection_destroy(co); return; } else if (len == 0) { - yaz_log(YLOG_WARN, "EOF reading from Z server"); + yaz_log(YLOG_WARN, "EOF reading from %s", cl->database->url); connection_destroy(co); return; } @@ -937,8 +932,13 @@ static void handler(IOCHAN i, int event) case Z_APDU_presentResponse: do_presentResponse(i, a); break; + case Z_APDU_close: + do_closeResponse(i, a); + break; default: - yaz_log(YLOG_WARN, "Unexpected result from server"); + yaz_log(YLOG_WARN, + "Unexpected Z39.50 response from %s", + cl->database->url); client_fatal(cl); return; } @@ -1046,9 +1046,6 @@ static struct connection *connection_create(struct client *cl) yaz_log(YLOG_DEBUG, "Connection create %s proxy %s", cl->database->url, global_parameters.zproxy_override); - yaz_log(YLOG_LOG, "Connection cs_create_host %s proxy %s", - cl->database->url, global_parameters.zproxy_override); - if (!(addr = cs_straddr(link, global_parameters.zproxy_override))) { yaz_log(YLOG_WARN|YLOG_ERRNO, @@ -1142,114 +1139,6 @@ static int client_prep_connection(struct client *cl) return 0; } -#ifdef GAGA // Moved to database.c - -// This function will most likely vanish when a proper target profile mechanism is -// introduced. -void load_simpletargets(const char *fn) -{ - FILE *f = fopen(fn, "r"); - char line[256]; - - if (!f) - { - yaz_log(YLOG_WARN|YLOG_ERRNO, "open %s", fn); - exit(1); - } - - while (fgets(line, 255, f)) - { - char *url, *db; - char *name; - struct host *host; - struct database *database; - - if (strncmp(line, "target ", 7)) - continue; - line[strlen(line) - 1] = '\0'; - - if ((name = strchr(line, ';'))) - *(name++) = '\0'; - - url = line + 7; - if ((db = strchr(url, '/'))) - *(db++) = '\0'; - else - db = "Default"; - - yaz_log(YLOG_LOG, "Target: %s, '%s'", url, db); - for (host = hosts; host; host = host->next) - if (!strcmp((const char *) url, host->hostport)) - break; - if (!host) - { - struct addrinfo *addrinfo, hints; - char *port; - char ipport[128]; - unsigned char addrbuf[4]; - int res; - - host = xmalloc(sizeof(struct host)); - host->hostport = xstrdup(url); - host->connections = 0; - - if ((port = strchr(url, ':'))) - *(port++) = '\0'; - else - port = "210"; - - hints.ai_flags = 0; - hints.ai_family = PF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_addrlen = 0; - hints.ai_addr = 0; - hints.ai_canonname = 0; - hints.ai_next = 0; - // This is not robust code. It assumes that getaddrinfo returns AF_INET - // address. - if ((res = getaddrinfo(url, port, &hints, &addrinfo))) - { - yaz_log(YLOG_WARN, "Failed to resolve %s: %s", url, gai_strerror(res)); - xfree(host->hostport); - xfree(host); - continue; - } - assert(addrinfo->ai_family == PF_INET); - memcpy(addrbuf, &((struct sockaddr_in*)addrinfo->ai_addr)->sin_addr.s_addr, 4); - sprintf(ipport, "%u.%u.%u.%u:%s", - addrbuf[0], addrbuf[1], addrbuf[2], addrbuf[3], port); - host->ipport = xstrdup(ipport); - freeaddrinfo(addrinfo); - host->next = hosts; - hosts = host; - } - database = xmalloc(sizeof(struct database)); - database->host = host; - database->url = xmalloc(strlen(url) + strlen(db) + 2); - strcpy(database->url, url); - strcat(database->url, "/"); - strcat(database->url, db); - if (name) - database->name = xstrdup(name); - else - database->name = 0; - - database->databases = xmalloc(2 * sizeof(char *)); - database->databases[0] = xstrdup(db); - database->databases[1] = 0; - database->errors = 0; - database->qprofile = 0; - database->rprofile = database_retrieval_profile(database); - database->next = databases; - databases = database; - - } - fclose(f); -} - -#endif - static struct client *client_create(void) { struct client *r; @@ -1607,36 +1496,6 @@ static void start_http_listener(void) http_init(hp); } -// Initialize CCL map for a target -// Note: This approach ignores user-specific CCL maps, for which I -// don't presently see any application. -static void prepare_cclmap(void *context, struct database *db) -{ - struct setting *s; - - if (!db->settings) - return; - db->ccl_map = ccl_qual_mk(); - for (s = db->settings[PZ_CCLMAP]; s; s = s->next) - if (!*s->user) - { - char *p = strchr(s->name + 3, ':'); - if (!p) - { - yaz_log(YLOG_FATAL, "Malformed cclmap name: %s", s->name); - exit(1); - } - p++; - ccl_qual_fitem(db->ccl_map, s->value, p); - } -} - -// Read settings for each database, and prepare a CCL map for that database -static void prepare_cclmaps(void) -{ - grep_databases(0, 0, prepare_cclmap); -} - static void start_proxy(void) { char hp[128] = ""; @@ -1759,10 +1618,8 @@ int main(int argc, char **argv) else if (global_parameters.server->settings) settings_read(global_parameters.server->settings); else - yaz_log(YLOG_WARN, "No settings-directory specified. Problems may ensue!"); - prepare_cclmaps(); - global_parameters.yaz_marc = yaz_marc_create(); - yaz_marc_subfield_str(global_parameters.yaz_marc, "\t"); + yaz_log(YLOG_WARN, "No settings-directory specified. Problems may well ensue!"); + prepare_databases(); global_parameters.odr_in = odr_createmem(ODR_DECODE); global_parameters.odr_out = odr_createmem(ODR_ENCODE);