source: gsdl/trunk/runtime-src/src/z3950/z3950server.cpp@ 18178

Last change on this file since 18178 was 18178, checked in by mdewsnip, 15 years ago

Fixed another DB special, where the collectset() constructor wasn't changed to use the modified version with both gsdlhome and collecthome.

File size: 26.8 KB
Line 
1
2
3// Standard headers
4
5#if defined(GSDL_USE_OBJECTSPACE)
6# include <ospace\std\iostream>
7# include <ospace\std\fstream>
8# include <ospace\std\sstream>
9#elif defined(GSDL_USE_IOS_H)
10# include <iostream.h>
11# include <fstream.h>
12# include <strstream.h>
13#else
14# include <iostream>
15# include <fstream>
16# include <sstream>
17#endif
18
19#include <string>
20#include <list>
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <ctype.h>
25#include <time.h>
26
27// Greenstone headers
28#include "fileutil.h"
29#include "comtypes.h"
30#include "nullproto.h"
31
32// Z39.50 server headers
33#include "z3950parser.h"
34#include "z3950explain.h"
35
36#include "z3950server.h"
37
38// Dublin Core -> MARC (d2m) headers and source files
39#include "d2m4gs.h"
40
41// these globals are local to each thread,
42// one Z39.50 connection = one thread.
43text_t gsdlhome; // this is set by the collectset object from the gsdlsite.cfg file
44text_t collecthome; // this is set by the collectset object
45list<FilterResponse_t> Response_tlist; // list of response sets
46list<text_t> Response_tlist_colnames; // collection names for the above
47list<int> Response_tlist_sizes; // sizes (number of records) for the above
48z3950Server *Server = NULL;
49collectset *Cservers = NULL;
50nullproto *Protocol = NULL;
51
52map<text_t, gsdlCollection> Collection_map; // info and tools for collections
53map<text_t, text_t> Resultsets; // mapping from ResultSetId to GSQuery
54
55int z3950_verbosity_ = 3;
56
57// *** initialize things here ***
58bend_initresult *bend_init(bend_initrequest *q)
59{
60 // *** called when client connects to the server ***
61 if (z3950_verbosity_ > 1) {
62 cerr << "Entering bend_init" << endl;
63 }
64
65 Protocol = new nullproto();
66 Cservers = new collectset(gsdlhome, collecthome);
67 Protocol->set_collectset(Cservers);
68
69 cerr << "Starting Z39.50 Server ..." << endl;
70
71 Server = new z3950Server(Protocol, gsdlhome);
72 cerr << "Server constructed" << endl;
73
74 const bool status = Server->initialise();
75 cerr << "Initialised server: return status = " << status << endl;
76
77 text_tarray collist;
78 comerror_t err;
79 Protocol->get_collection_list( collist, err, cout );
80
81 // display the list of available Greenstone collections
82 text_tarray::iterator cols_here=collist.begin();
83 text_tarray::iterator cols_end=collist.end();
84 while (cols_here != cols_end) {
85 gsdlCollection tmpcol(*cols_here, gsdlhome);
86
87 Collection_map[*cols_here] = tmpcol;
88
89 if (tmpcol.z3950Capeable()) {
90 cerr << " " << tmpcol.getName() << "\tis Z39.50 capable" << endl;
91 }
92 cols_here++;
93 }
94
95
96 bend_initresult *r = (bend_initresult *) odr_malloc (q->stream, sizeof(*r));
97 //static char *dummy = "Hej fister"; // what's this for?
98
99 r->errcode = 0;
100 r->errstring = 0;
101 r->handle = Protocol;
102 q->bend_sort = ztest_sort; /* register sort handler */
103 q->bend_search = ztest_search; /* register search handler */
104 q->bend_present = ztest_present; /* register present handle */
105 q->bend_esrequest = ztest_esrequest;
106 q->bend_delete = ztest_delete;
107 q->bend_fetch = ztest_fetch;
108 q->bend_scan = ztest_scan;
109
110 return r;
111}
112
113// *** perform query, get number of hits ***
114int ztest_search (void *handle, bend_search_rr *rr)
115{
116 // *** called when client issues a "find" command
117 if (z3950_verbosity_>1) {
118 cerr << "Entering ztest_search" << endl;
119 }
120
121 Response_tlist.clear();
122 Response_tlist_colnames.clear();
123 Response_tlist_sizes.clear();
124
125 comerror_t err;
126 FilterRequest_t request;
127
128 request.filterName = "QueryFilter";
129 request.filterResultOptions = FROID | FRtermFreq | FRmetadata;
130
131 OptionValue_t option;
132
133 // how many results to get. grouping all results together into
134 // one set instead of breaking up into "pages".
135 // note: see if Z39.50 has a concept of pages.
136 option.name = "StartResults";
137 option.value = "1";
138 request.filterOptions.push_back (option);
139 option.name = "EndResults";
140 option.value = MAXHITS;
141 request.filterOptions.push_back (option);
142 option.name = "Maxdocs";
143 option.value = MAXHITS;
144 request.filterOptions.push_back (option);
145
146 text_t GSQuery = ZQueryToGSQuery(rr);
147 option.name = "Term";
148 option.value = GSQuery;
149 request.filterOptions.push_back (option);
150 Resultsets[Resultsets.size()+1] = GSQuery;
151
152 option.name = "QueryType";
153 option.value = "boolean";
154 request.filterOptions.push_back (option);
155
156 option.name = "MatchMode";
157 option.value = "all";
158 request.filterOptions.push_back (option);
159
160 option.name = "Casefold";
161 option.value = "true";
162 request.filterOptions.push_back (option);
163
164 option.name = "Stem";
165 option.value = "false";
166 request.filterOptions.push_back (option);
167
168 option.name = "AccentFold";
169 option.value = "false";
170 request.filterOptions.push_back (option);
171
172 // MG queries don't need this, MGPP queries do.
173 // doesn't do any harm to include it anyway.
174 // note: not all collections have document-level granularity...
175 option.name = "Level";
176 option.value = "Doc";
177 request.filterOptions.push_back (option);
178
179 // Z39.50 supports the searching of multiple databases
180 rr->hits = 0;
181 for (int i = 0; i < rr->num_bases; i++) {
182 FilterResponse_t response;
183 cerr << "Searching basename = " << rr->basenames[i] << endl;
184 // intercept Explain requests
185 if (strcmp(rr->basenames[i], "IR-Explain-1")==0) {
186 //ColInfoResponse_t collectinfo;
187 //Protocol->get_collectinfo("csbib", collectinfo, err, cerr);
188 //response.numDocs = 1;
189 //ResultDocInfo_t docinfo;
190 //docinfo.metadata["foo"].values.push_back("bar");
191 getExplainInfo(rr, response, err);
192 //response.docInfo.push_back(docinfo);
193 } else {
194 cerr << "calling filter..." << endl;
195 Protocol->filter(rr->basenames[i], request, response, err, cerr);
196 cerr << "returned from filter." << endl;
197 if (response.numDocs > MAXHITS) {
198 response.numDocs = MAXHITS;
199 }
200 }
201 rr->hits += response.numDocs;
202 Response_tlist.push_back(response);
203 text_t basename = rr->basenames[i];
204 Response_tlist_colnames.push_back(basename);
205 Response_tlist_sizes.push_back(response.numDocs);
206 cerr << "search complete." << endl;
207 }
208
209 if (rr->hits > MAXHITS) rr->hits = MAXHITS;
210 return 0;
211}
212
213// *** extra code for showing results, not needed ***
214int ztest_present (void *handle, bend_present_rr *rr)
215{
216 // *** called when client issues a "show" command, 1st of 5
217 if (z3950_verbosity_>1) {
218 cerr << "entering ztest_present" << endl;
219 }
220 return 0;
221}
222
223int ztest_esrequest (void *handle, bend_esrequest_rr *rr)
224{
225
226 if (z3950_verbosity_>1) {
227 cerr << "Entering ztest_esrequest" << endl;
228 }
229 yaz_log(LOG_LOG, "function: %d", *rr->esr->function);
230 if (rr->esr->packageName)
231 yaz_log(LOG_LOG, "packagename: %s", rr->esr->packageName);
232 yaz_log(LOG_LOG, "Waitaction: %d", *rr->esr->waitAction);
233
234 if (!rr->esr->taskSpecificParameters)
235 {
236 yaz_log (LOG_WARN, "No task specific parameters");
237 }
238 else if (rr->esr->taskSpecificParameters->which == Z_External_itemOrder)
239 {
240 Z_ItemOrder *it = rr->esr->taskSpecificParameters->u.itemOrder;
241 yaz_log (LOG_LOG, "Received ItemOrder");
242 switch (it->which)
243 {
244#ifdef ASN_COMPILED
245 case Z_IOItemOrder_esRequest:
246#else
247 case Z_ItemOrder_esRequest:
248#endif
249 {
250 Z_IORequest *ir = it->u.esRequest;
251 Z_IOOriginPartToKeep *k = ir->toKeep;
252 Z_IOOriginPartNotToKeep *n = ir->notToKeep;
253
254 if (k && k->contact)
255 {
256 if (k->contact->name)
257 yaz_log(LOG_LOG, "contact name %s", k->contact->name);
258 if (k->contact->phone)
259 yaz_log(LOG_LOG, "contact phone %s", k->contact->phone);
260 if (k->contact->email)
261 yaz_log(LOG_LOG, "contact email %s", k->contact->email);
262 }
263 if (k->addlBilling)
264 {
265 yaz_log(LOG_LOG, "Billing info (not shown)");
266 }
267
268 if (n->resultSetItem)
269 {
270 yaz_log(LOG_LOG, "resultsetItem");
271 yaz_log(LOG_LOG, "setId: %s", n->resultSetItem->resultSetId);
272 yaz_log(LOG_LOG, "item: %d", *n->resultSetItem->item);
273 }
274#ifdef ASN_COMPILED
275 if (n->itemRequest)
276 {
277 Z_External *r = (Z_External*) n->itemRequest;
278 ILL_ItemRequest *item_req = 0;
279 ILL_Request *ill_req = 0;
280 if (r->direct_reference)
281 {
282 oident *ent = oid_getentbyoid(r->direct_reference);
283 if (ent)
284 yaz_log(LOG_LOG, "OID %s", ent->desc);
285 if (ent && ent->value == VAL_ISO_ILL_1)
286 {
287 yaz_log (LOG_LOG, "ItemRequest");
288 if (r->which == ODR_EXTERNAL_single)
289 {
290 odr_setbuf(rr->decode,
291 (char*)(r->u.single_ASN1_type->buf),
292 r->u.single_ASN1_type->len, 0);
293
294 if (!ill_ItemRequest (rr->decode, &item_req, 0, 0))
295 {
296 yaz_log (LOG_LOG,
297 "Couldn't decode ItemRequest %s near %d",
298 odr_errmsg(odr_geterror(rr->decode)),
299 odr_offset(rr->decode));
300 yaz_log(LOG_LOG, "PDU dump:");
301 odr_dumpBER(yaz_log_file(),
302 (const char*)(r->u.single_ASN1_type->buf),
303 r->u.single_ASN1_type->len);
304 }
305 if (rr->print)
306 {
307 ill_ItemRequest (rr->print, &item_req, 0,
308 "ItemRequest");
309 odr_reset (rr->print);
310 }
311 }
312 if (!item_req && r->which == ODR_EXTERNAL_single)
313 {
314 yaz_log (LOG_LOG, "ILLRequest");
315 odr_setbuf(rr->decode,
316 (char*)(r->u.single_ASN1_type->buf),
317 r->u.single_ASN1_type->len, 0);
318
319 if (!ill_Request (rr->decode, &ill_req, 0, 0))
320 {
321 yaz_log (LOG_LOG,
322 "Couldn't decode ILLRequest %s near %d",
323 odr_errmsg(odr_geterror(rr->decode)),
324 odr_offset(rr->decode));
325 yaz_log(LOG_LOG, "PDU dump:");
326 odr_dumpBER(yaz_log_file(),
327 (const char*)(r->u.single_ASN1_type->buf),
328 r->u.single_ASN1_type->len);
329 }
330 if (rr->print)
331 {
332 ill_Request (rr->print, &ill_req, 0,
333 "ILLRequest");
334 odr_reset (rr->print);
335 }
336 }
337 }
338 }
339 if (item_req)
340 {
341 yaz_log (LOG_LOG, "ILL protocol version = %d",
342 *item_req->protocol_version_num);
343 }
344 }
345#endif
346 }
347 break;
348 }
349 }
350 else if (rr->esr->taskSpecificParameters->which == Z_External_update)
351 {
352 Z_IUUpdate *up = rr->esr->taskSpecificParameters->u.update;
353 yaz_log (LOG_LOG, "Received DB Update");
354 if (up->which == Z_IUUpdate_esRequest)
355 {
356 Z_IUUpdateEsRequest *esRequest = up->u.esRequest;
357 Z_IUOriginPartToKeep *toKeep = esRequest->toKeep;
358 Z_IUSuppliedRecords *notToKeep = esRequest->notToKeep;
359
360 yaz_log (LOG_LOG, "action");
361 if (toKeep->action)
362 {
363 switch (*toKeep->action)
364 {
365 case Z_IUOriginPartToKeep_recordInsert:
366 yaz_log (LOG_LOG, " recordInsert");
367 break;
368 case Z_IUOriginPartToKeep_recordReplace:
369 yaz_log (LOG_LOG, " recordUpdate");
370 break;
371 case Z_IUOriginPartToKeep_recordDelete:
372 yaz_log (LOG_LOG, " recordDelete");
373 break;
374 case Z_IUOriginPartToKeep_elementUpdate:
375 yaz_log (LOG_LOG, " elementUpdate");
376 break;
377 case Z_IUOriginPartToKeep_specialUpdate:
378 yaz_log (LOG_LOG, " specialUpdate");
379 break;
380 default:
381 yaz_log (LOG_LOG, " unknown (%d)", *toKeep->action);
382 }
383 }
384 if (toKeep->databaseName)
385 {
386 yaz_log (LOG_LOG, "database: %s", toKeep->databaseName);
387 if (!strcmp(toKeep->databaseName, "fault"))
388 {
389 rr->errcode = 109;
390 rr->errstring = toKeep->databaseName;
391 }
392 if (!strcmp(toKeep->databaseName, "accept"))
393 rr->errcode = -1;
394 }
395 if (notToKeep)
396 {
397 int i;
398 for (i = 0; i < notToKeep->num; i++)
399 {
400 Z_External *rec = notToKeep->elements[i]->record;
401
402 if (rec->direct_reference)
403 {
404 struct oident *oident;
405 oident = oid_getentbyoid(rec->direct_reference);
406 if (oident)
407 yaz_log (LOG_LOG, "record %d type %s", i,
408 oident->desc);
409 }
410 switch (rec->which)
411 {
412 case Z_External_sutrs:
413 if (rec->u.octet_aligned->len > 170)
414 yaz_log (LOG_LOG, "%d bytes:\n%.168s ...",
415 rec->u.sutrs->len,
416 rec->u.sutrs->buf);
417 else
418 yaz_log (LOG_LOG, "%d bytes:\n%s",
419 rec->u.sutrs->len,
420 rec->u.sutrs->buf);
421 break;
422 case Z_External_octet :
423 if (rec->u.octet_aligned->len > 170)
424 yaz_log (LOG_LOG, "%d bytes:\n%.168s ...",
425 rec->u.octet_aligned->len,
426 rec->u.octet_aligned->buf);
427 else
428 yaz_log (LOG_LOG, "%d bytes\n%s",
429 rec->u.octet_aligned->len,
430 rec->u.octet_aligned->buf);
431 }
432 }
433 }
434 }
435 }
436 else
437 {
438 yaz_log (LOG_WARN, "Unknown Extended Service(%d)",
439 rr->esr->taskSpecificParameters->which);
440
441 }
442 return 0;
443}
444
445int ztest_delete (void *handle, bend_delete_rr *rr)
446{
447 // *** called when client issues a "delete" command
448 if (z3950_verbosity_>1) {
449 cerr << "Entering ztest_delete" << endl;
450 }
451 if (rr->num_setnames == 1 && !strcmp (rr->setnames[0], "1"))
452 rr->delete_status = Z_DeleteStatus_success;
453 else
454 rr->delete_status = Z_DeleteStatus_resultSetDidNotExist;
455 return 0;
456}
457
458// *** do we want to sort the results? ***
459/* Our sort handler really doesn't sort... */
460int ztest_sort (void *handle, bend_sort_rr *rr)
461{
462 if (z3950_verbosity_>1) {
463 cerr << "entering ztest_sort" << endl;
464 }
465 rr->errcode = 0;
466 rr->sort_status = Z_SortStatus_success;
467 return 0;
468}
469
470static int atoin (const char *buf, int n)
471{
472 // *** called when client issues a "show" command, 5th of 5
473 // *** NOT called if the "show" command has an invalid argument
474 if (z3950_verbosity_>1) {
475 cerr << "Entering atoin" << endl;
476 }
477 int val = 0;
478 while (--n >= 0)
479 {
480 if (isdigit(*buf))
481 val = val*10 + (*buf - '0');
482 buf++;
483 }
484 return val;
485}
486
487
488bool get_sutrs_record (int recnum, text_t &MetadataResult, text_t &CollectionName)
489{
490 if (z3950_verbosity_>1) {
491 cerr << "Entering get_sutrs_record" << endl;
492 }
493 int total_records = 0;
494
495 list<FilterResponse_t>::iterator RESPONSE_here = Response_tlist.begin();
496 list<FilterResponse_t>::iterator RESPONSE_end = Response_tlist.end();
497 list<text_t>::iterator RESPONSE_COLNAMES_here = Response_tlist_colnames.begin();
498 list<text_t>::iterator RESPONSE_COLNAMES_end = Response_tlist_colnames.end();
499 list<int>::iterator RESPONSE_SIZES_here = Response_tlist_sizes.begin();
500 list<int>::iterator RESPONSE_SIZES_end = Response_tlist_sizes.end();
501
502 RESPONSE_here = Response_tlist.begin();
503 RESPONSE_end = Response_tlist.end();
504 while (RESPONSE_here != RESPONSE_end) {
505 total_records += (*RESPONSE_here).numDocs;
506 RESPONSE_here++;
507 }
508
509 // check that the index is within bounds
510 if (recnum < 1 || recnum > total_records) {
511 cerr << "get_sutrs_record failed" << endl;
512 return false; // failed
513 } else {
514 FilterResponse_t response;
515 // iterate through Response_tlist to find the right response
516 RESPONSE_here = Response_tlist.begin();
517 RESPONSE_end = Response_tlist.end();
518 RESPONSE_COLNAMES_here = Response_tlist_colnames.begin();
519 RESPONSE_COLNAMES_end = Response_tlist_colnames.end();
520 RESPONSE_SIZES_here = Response_tlist_sizes.begin();
521 RESPONSE_SIZES_end = Response_tlist_sizes.end();
522 int n = 0;
523
524 while (RESPONSE_here != RESPONSE_end) {
525 n += *RESPONSE_SIZES_here;
526 if (n >= recnum) {
527 response = *RESPONSE_here;
528 CollectionName = *RESPONSE_COLNAMES_here;
529 recnum = *RESPONSE_SIZES_here - (n - recnum);
530 break;
531 }
532 // these should all have the same number of elements,
533 // so only need to check that one is within bounds.
534 // may want to combine these into a larger data structure later.
535 RESPONSE_here++;
536 RESPONSE_COLNAMES_here++;
537 RESPONSE_SIZES_here++;
538 }
539
540 // locate the desired record in the response
541
542 MetadataInfo_tmap::iterator METAFIELD_here = response.docInfo[recnum-1].metadata.begin();
543 MetadataInfo_tmap::iterator METAFIELD_end = response.docInfo[recnum-1].metadata.end();
544
545 while (METAFIELD_here!=METAFIELD_end) {
546 text_tarray::iterator METAVALUE_here = METAFIELD_here->second.values.begin();
547 text_tarray::iterator METAVALUE_end = METAFIELD_here->second.values.end();
548 while (METAVALUE_here!=METAVALUE_end) {
549 // construct a text_t containing the record:
550 // there are multiple metadata fields,
551 // each field can have multiple values.
552 /*
553 // don't include fields starting with a lowercase letter,
554 // these are system fields.
555 // later: include these anyway, since Explain fields start with lowercase letters
556 if (METAFIELD_here->first[0] >= 'A' &&
557 METAFIELD_here->first[0] <= 'Z') {
558 */
559 MetadataResult += METAFIELD_here->first; // field name
560 MetadataResult += " ";
561 MetadataResult += *METAVALUE_here; // field contents
562 MetadataResult += "\n";
563 //}
564 METAVALUE_here++;
565 }
566 METAFIELD_here++;
567 }
568 return true; // succeeded
569 }
570}
571
572bool get_marc_record (int recnum, list<metatag*> &Metatag_list, text_t &CollectionName)
573{
574 if (z3950_verbosity_>1) {
575 cerr << "Entering get_marc_record" << endl;
576 }
577 int total_records = 0;
578
579 list<FilterResponse_t>::iterator RESPONSE_here = Response_tlist.begin();
580 list<FilterResponse_t>::iterator RESPONSE_end = Response_tlist.end();
581 list<text_t>::iterator RESPONSE_COLNAMES_here = Response_tlist_colnames.begin();
582 list<text_t>::iterator RESPONSE_COLNAMES_end = Response_tlist_colnames.end();
583 list<int>::iterator RESPONSE_SIZES_here = Response_tlist_sizes.begin();
584 list<int>::iterator RESPONSE_SIZES_end = Response_tlist_sizes.end();
585
586 RESPONSE_here = Response_tlist.begin();
587 RESPONSE_end = Response_tlist.end();
588 while (RESPONSE_here != RESPONSE_end) {
589 total_records += (*RESPONSE_here).numDocs;
590 RESPONSE_here++;
591 }
592
593 // check that the index is within bounds
594 if (recnum < 1 || recnum > total_records) {
595 cerr << "get_marc_record failed" << endl;
596 return false; // failed
597 } else {
598 FilterResponse_t response;
599 // iterate through Response_tlist to find the right response
600 RESPONSE_here = Response_tlist.begin();
601 RESPONSE_end = Response_tlist.end();
602 RESPONSE_COLNAMES_here = Response_tlist_colnames.begin();
603 RESPONSE_COLNAMES_end = Response_tlist_colnames.end();
604 RESPONSE_SIZES_here = Response_tlist_sizes.begin();
605 RESPONSE_SIZES_end = Response_tlist_sizes.end();
606 int n = 0;
607 while (RESPONSE_here != RESPONSE_end) {
608 n += *RESPONSE_SIZES_here;
609 if (n >= recnum) {
610 response = *RESPONSE_here;
611 CollectionName = *RESPONSE_COLNAMES_here;
612 recnum = *RESPONSE_SIZES_here - (n - recnum);
613 break;
614 }
615 // these should all have the same number of elements,
616 // so only need to check that one is within bounds.
617 // may want to combine these into a larger data structure later.
618 RESPONSE_here++;
619 RESPONSE_COLNAMES_here++;
620 RESPONSE_SIZES_here++;
621 }
622
623 // locate the desired record in the response
624
625 MetadataInfo_tmap::iterator METAFIELD_here = response.docInfo[recnum-1].metadata.begin();
626 MetadataInfo_tmap::iterator METAFIELD_end = response.docInfo[recnum-1].metadata.end();
627
628 while (METAFIELD_here!=METAFIELD_end) {
629 text_tarray::iterator METAVALUE_here = METAFIELD_here->second.values.begin();
630 text_tarray::iterator METAVALUE_end = METAFIELD_here->second.values.end();
631 while (METAVALUE_here!=METAVALUE_end) {
632 if (METAFIELD_here->first[0] >= 'A' &&
633 METAFIELD_here->first[0] <= 'Z') {
634 metatag *tmptag = new metatag();
635 tmptag->name = METAFIELD_here->first.getcstr();
636 tmptag->type = "";
637 tmptag->scheme = "";
638 tmptag->value = (*METAVALUE_here).getcstr();
639 Metatag_list.push_back(tmptag);
640 }
641 METAVALUE_here++;
642 }
643 METAFIELD_here++;
644 }
645 return true; // succeeded
646 }
647}
648
649// *** implement this ***
650int ztest_fetch(void *handle, bend_fetch_rr *r)
651{
652 // *** called when client issues a "show" command, 2nd of 5
653 if (z3950_verbosity_>1) {
654 cerr << "Entering ztest_fetch" << endl;
655 }
656 char *cp;
657 r->errstring = 0;
658 r->last_in_set = 0;
659 r->basename = "DUMMY"; // this is set below
660 r->output_format = r->request_format;
661
662 // *** use this until found a good way of mapping Greenstone
663 // *** metadata fields to USMARC fields
664 if (r->request_format == VAL_SUTRS)
665 {
666 // copies record into r, errcode will be 13 if fails
667 text_t MetadataResult;
668 text_t CollectionName;
669 if (!get_sutrs_record(r->number, MetadataResult, CollectionName)) {
670 r->errcode = 13;
671 return 0;
672 } else {
673 r->len = MetadataResult.size();
674 r->record = (char*) odr_malloc(r->stream, r->len+1);
675 char *tmptxt = MetadataResult.getcstr();
676 strcpy(r->record, tmptxt);
677 delete tmptxt;
678 r->basename = (char*) odr_malloc(r->stream, CollectionName.size()+1);
679 tmptxt = CollectionName.getcstr();
680 strcpy(r->basename, tmptxt);
681 delete tmptxt;
682 }
683 }
684 // *** do we want to use this format? ***
685 else if (r->request_format == VAL_GRS1)
686 {
687 // bail out, since we don't support grs (yet?)
688 r->errcode = 107; // "Query type not supported"
689 return 0;
690
691 }
692 // assume that here on in is some sort of MARC format
693 else {
694 marcrec *mrec = new marcrec;
695
696 mrec = (marcrec*) malloc(sizeof(*mrec));
697
698 mrec->marcline = (char*) malloc(100000);
699 mrec->partitle = (char*) malloc(10000);
700 mrec->subtitle = (char*) malloc(10000);
701 mrec->year = (char*) malloc(1000);
702 mrec->url = (char*) malloc(1000);
703 mrec->fmat = (char*) malloc(1000);
704 mrec->s008 = (char*) malloc(41);
705
706 mrec->ncreators = 0;
707 mrec->ntitles = 0;
708 *mrec->marcline = 0;
709 *mrec->subtitle = 0;
710 *mrec->partitle = 0;
711 *mrec->year = 0;
712 *mrec->url = 0;
713 *mrec->fmat = 0;
714 strcpy(mrec->s008, " ");
715
716 text_t CollectionName;
717 list<metatag*> Metatag_list;
718
719 if (!get_marc_record(r->number, Metatag_list, CollectionName)) {
720 r->errcode = 13;
721 return 0;
722 } else {
723 list<metatag*>::iterator METATAG_here = Metatag_list.begin();
724 list<metatag*>::iterator METATAG_end = Metatag_list.end();
725 while (METATAG_here != METATAG_end) {
726 usMARC(*METATAG_here, mrec);
727 METATAG_here++;
728 }
729
730 // set the date in the marc record to the current date
731 char today[32];
732 time_t d;
733 struct tm *time_struct;
734 //putenv("TZ=NFT-1DFT");
735 d = time(NULL);
736 time_struct = localtime(&d);
737 strftime(today, 16, "%y%m%d", time_struct);
738 put008(mrec->s008, today, F008_DATE_ENTERED);
739 put008(mrec->s008, "s", F008_TYPE_OF_DATE);
740
741 // to do: make this safer + more efficient
742 cp = new char[1000000];
743 char *cp2 = new char[1000000];
744
745 switch(r->request_format) {
746 case VAL_DANMARC: {
747 MARCtidy(mrec, cp, DANMARC);
748 r->output_format = VAL_DANMARC;
749 break; }
750 case VAL_FINMARC: {
751 MARCtidy(mrec, cp, FINMARC);
752 r->output_format = VAL_FINMARC;
753 break; }
754 // YAZ doesn't know about ISMARC
755 /*
756 case VAL_ISMARC: {
757 put008(mrec->s008, "k", F008_FORM_OF_PUBLICATION);
758 MARCtidy(mrec, cp, ISMARC);
759 r->output_format = VAL_ISMARC;
760 break; }
761 */
762 case VAL_NORMARC: {
763 MARCtidy(mrec, cp, NORMARC);
764 r->output_format = VAL_NORMARC;
765 break; }
766 case VAL_SWEMARC: {
767 MARCtidy(mrec, cp, SWEMARC);
768 r->output_format = VAL_SWEMARC;
769 break; }
770 default: {
771 MARCtidy(mrec, cp, USMARC);
772 r->output_format = VAL_USMARC;
773 break; }
774 }
775
776 sprintf(cp2, "%s", (char*) MARC2709(cp, 0, 6, 'n', 'm', ' '));
777 r->len = strlen(cp2);
778 r->record = (char*) odr_malloc(r->stream, r->len+1);
779 strcpy(r->record, cp2);
780 r->basename = (char*) odr_malloc(r->stream, CollectionName.size()+1);
781 char *tmptxt;
782 tmptxt = CollectionName.getcstr();
783 strcpy(r->basename, tmptxt);
784 delete tmptxt;
785 delete cp2;
786 cerr << "dumping record:`" << cp << "'" << endl;
787 delete cp;
788 }
789 }
790
791 r->errcode = 0;
792 return 0;
793}
794
795/*
796 * silly dummy-scan what reads words from a file.
797 */
798int ztest_scan(void *handle, bend_scan_rr *q)
799{
800 // *** called when client issues a "scan" command
801 if (z3950_verbosity_>1) {
802 cerr << "Entering ztest_scan" << endl;
803 }
804
805 // bail out, since we don't support scan (yet?)
806 q->errcode = 107; // "Query type not supported"
807 return 0;
808
809 static FILE *f = 0;
810 static struct scan_entry list[200];
811 static char entries[200][80];
812 int hits[200];
813 char term[80], *p;
814 int i, pos;
815 int term_position_req = q->term_position;
816 int num_entries_req = q->num_entries;
817
818 q->errcode = 0;
819 q->errstring = 0;
820 q->entries = list;
821 q->status = BEND_SCAN_SUCCESS;
822 if (!f && !(f = fopen("dummy-words", "r")))
823 {
824 perror("dummy-words");
825 exit(1);
826 }
827 if (q->term->term->which != Z_Term_general)
828 {
829 q->errcode = 229; /* unsupported term type */
830 return 0;
831 }
832 if (*q->step_size != 0)
833 {
834 q->errcode = 205; /*Only zero step size supported for Scan */
835 return 0;
836 }
837 if (q->term->term->u.general->len >= 80)
838 {
839 q->errcode = 11; /* term too long */
840 return 0;
841 }
842 if (q->num_entries > 200)
843 {
844 q->errcode = 31;
845 return 0;
846 }
847 memcpy(term, q->term->term->u.general->buf, q->term->term->u.general->len);
848 term[q->term->term->u.general->len] = '\0';
849 for (p = term; *p; p++)
850 if (islower(*p))
851 *p = toupper(*p);
852
853 fseek(f, 0, SEEK_SET);
854 q->num_entries = 0;
855
856 for (i = 0, pos = 0; fscanf(f, " %79[^:]:%d", entries[pos], &hits[pos]) == 2;
857 i++, pos < 199 ? pos++ : (pos = 0))
858 {
859 if (!q->num_entries && strcmp(entries[pos], term) >= 0) /* s-point fnd */
860 {
861 if ((q->term_position = term_position_req) > i + 1)
862 {
863 q->term_position = i + 1;
864 q->status = BEND_SCAN_PARTIAL;
865 }
866 for (; q->num_entries < q->term_position; q->num_entries++)
867 {
868 int po;
869
870 po = pos - q->term_position + q->num_entries+1; /* find pos */
871 if (po < 0)
872 po += 200;
873
874 if (!strcmp (term, "SD") && q->num_entries == 2)
875 {
876 list[q->num_entries].term = entries[pos];
877 list[q->num_entries].occurrences = -1;
878 list[q->num_entries].errcode = 233;
879 list[q->num_entries].errstring = "SD for Scan Term";
880 }
881 else
882 {
883 list[q->num_entries].term = entries[po];
884 list[q->num_entries].occurrences = hits[po];
885 }
886 }
887 }
888 else if (q->num_entries)
889 {
890 list[q->num_entries].term = entries[pos];
891 list[q->num_entries].occurrences = hits[pos];
892 q->num_entries++;
893 }
894 if (q->num_entries >= num_entries_req)
895 break;
896 }
897 if (feof(f))
898 q->status = BEND_SCAN_PARTIAL;
899 return 0;
900}
901
902
903
904void bend_close(void *handle)
905{
906 if (z3950_verbosity_>1) {
907 cerr << "Entering bend_close" << endl;
908 }
909 delete Server;
910 delete Cservers;
911 delete Protocol;
912 if (z3950_verbosity_>1) {
913 cerr << "heap cleaned up, exiting bend_close" << endl;
914 }
915 return;
916}
917
918int main (int argc, char *argv[])
919{
920
921 const int statserv_var = statserv_main(argc, argv, bend_init, bend_close);
922 cerr << "statserv_main returns: " << statserv_var << endl;
923 return statserv_var;
924
925 return 0;
926}
927
928
Note: See TracBrowser for help on using the repository browser.