source: branches/z3950-branch/gsdl/src/recpt/z3950proto.cpp@ 1168

Last change on this file since 1168 was 1168, checked in by johnmcp, 24 years ago

added proper config file parsing for z39.50 servers, and minor changes
to pageaction (minor bug when display collections from >1 proto) and
cgiwrapper (announces which collections are z39.50 servers).

  • Property svn:keywords set to Author Date Id Revision
File size: 10.4 KB
Line 
1
2#ifndef Z3950PROTO_H
3#define Z3050PROTO_H
4
5#include "z3950proto.h"
6#include "comtypes.h"
7#include <stdio.h>
8
9// config file parsing stuff
10#include "z3950cfg.h" // for reading in config files -
11// defines "struct z3950cfg *zserver_list" as the head of the list.
12extern FILE *yyin;
13// for some reason, adding the following line screws up the linking...
14//extern int zconfigparse();
15
16/***
17 We will use the "collection" argument as the name of the database
18 to query on the z3950 server.
19***/
20
21
22z3950_server::z3950_server() {
23 count=0;
24 info=NULL;
25 meta["iconcollection"]="/~johnmcp/gsdl/images/zserver.png";
26 // meta["collectionextra"]="Extra collection information";
27 // meta["collectionname"]="overwritten";
28}
29void z3950_server::setMeta(const text_t &key, const text_t &value) {
30 meta[key]=value;
31}
32void z3950_server::setName(const text_t &newname) {
33 title=newname;
34 meta["collectionname"]=newname;
35 // cout << "Have set server name\n";
36}
37
38
39
40
41// z3950 Protocol functions
42z3950proto::z3950proto() {
43 zserver_count=0;
44}
45
46void z3950proto::add_server (const z3950_server& zserver) {
47
48 // append the new server
49 zserver_count++;
50 zservers.push_back(zserver);
51}
52
53void z3950proto::read_config_file(const text_t &filename) {
54 struct z3950cfg *here;
55 z3950_server *zserver;
56 ShortColInfo_t *tempinfo;
57
58 cerr << "attempting to read config file: " << filename.getcstr() << "\n";
59 // zconfigparse() is defined in zparse.tab.c,
60 // which is the bison output of zparse.y
61
62 yyin=fopen(filename.getcstr(),"r");
63 if (yyin==NULL) {
64 cerr << "Could not open "<<filename.getcstr()<<" for reading.\n";
65 }
66 zconfigparse();
67 // we now have the config files in the ptr zserver_list
68 if (zserver_list==NULL)
69 return; // no valid servers found in the config file - note that
70 // the parser will have already spat out any errors.
71
72 // now create z3950servers for each structure in server_list
73 here=zserver_list;
74 while (here!=NULL) {
75 zserver=new z3950_server;
76 tempinfo=new ShortColInfo_t;
77
78 tempinfo->host.setcstr(here->hostname);
79 tempinfo->port=here->port;
80 tempinfo->name.setcstr(here->dbname);
81 zserver->setInfo(tempinfo);
82 zserver->setName(here->shortname);
83 // now collection metadata.
84 zserver->setMeta("collectionname",here->longname);
85 if (here->icon!=NULL)
86 zserver->setMeta("iconcollection",here->icon);
87 if (here->smallicon!=NULL)
88 zserver->setMeta("iconcollectionsmall",here->smallicon);
89 if (0) {
90 cerr << "creating metadata:\n\tcolname is " << here->longname
91 << "\n\ticoncollection is " << here->icon
92 << "\n and\ticoncollectionsmall is " << here->smallicon
93 << "\n";
94 }
95
96 // and about list .... later.
97
98 add_server(*zserver);
99 here=here->next;
100 }
101
102 // finally, delete all unneeded allocated memory in server_list
103
104}
105
106void z3950proto::configure (const text_t &key,
107 const text_tarray &cfgline) {
108
109 // this is called for each line in the gsdlsite.cfg file
110
111 if (0)
112 cerr << "z3950proto::configure called:"
113 << "key is " << key.getcstr()
114 << "\n1st line is " << cfgline[0].getcstr() << endl;
115
116}
117
118
119bool z3950proto::init (ostream &/*logout*/) {
120 // set up tcp connection to server here?
121 // we might also read in the config file here (instead of librarymain.cpp)
122
123 //
124
125 // logout goes to initout.txt
126 // logout <<"zdebug:init:Number of z3950 servers: "<< zserver_count << "\n";
127 //logout << "\t1st server name: " << zservers[0].getName().getcstr() << "\n";
128 return true;
129
130}
131
132/*text_t z3950proto::get_protocol_name () {
133 return "z3950proto";
134}
135*/
136
137void z3950proto::get_collection_list (text_tarray &collist,
138 comerror_t &/*err*/,
139 ostream &/*logout*/) {
140 // logout here DOESN'T go to initout.txt
141 // logout << "zdebug: get_collection_list called:\n";
142
143 /** *** for now, we are assuming that each SERVER is a GSDL collection,
144 as opposed to each DATABASE on the servers.
145 */
146 z3950_server_array::iterator here = zservers.begin();
147 z3950_server_array::iterator end = zservers.end();
148 while (here != end) {
149 collist.push_back(here->getName());
150 //const ShortColInfo_t *info=here->getInfo();
151 //collist.push_back(info->name);
152 here++;
153 }
154}
155
156void z3950proto::has_collection (const text_t &collection, bool &hascollection,
157 comerror_t &/*err*/, ostream &/*logout*/) {
158 z3950_server_array::iterator here = zservers.begin();
159 z3950_server_array::iterator end = zservers.end();
160 while (here != end) {
161 if(here->getName()==collection) {
162 hascollection=true;
163 return;
164 }
165 here++;
166 }
167 hascollection=false;
168}
169
170void z3950proto::ping (const text_t &/*collection*/, bool &wassuccess,
171 comerror_t &/*err*/, ostream &/*logout*/) {
172 // should we just ping the server, or actually create a connection
173 // to the z39.50 server process on the machine ?
174 wassuccess = true;
175}
176
177void z3950proto::get_collectinfo (const text_t &collection,
178 ColInfoResponse_t &collectinfo,
179 comerror_t &err, ostream &logout) {
180
181 // set err to protocolError if something goes wrong...
182
183 z3950_server_array::iterator here = zservers.begin();
184 z3950_server_array::iterator end = zservers.end();
185 while (here != end) {
186 if(here->getName()==collection) {
187 break;
188 }
189 here++;
190 }
191
192 // is this right? ie does end refer to the last element, or AFTER the
193 // last element?
194 if (here==end) {
195 err=protocolError;
196 logout << "z39.50: couldn't find collection"
197 << collection.getcstr()
198 << endl;
199 return;
200 }
201
202 /* collectinfo.shortInfo.name="sdfg";
203 collectinfo.shortInfo.host="localhost";
204 collectinfo.shortInfo.port=0; */
205 const ShortColInfo_t *colinfo=here->getInfo();
206 collectinfo.shortInfo.name=colinfo->name;
207 collectinfo.shortInfo.host=colinfo->host;
208 collectinfo.shortInfo.port=colinfo->port;
209
210 collectinfo.isPublic=true;
211 // don't use beta field
212 /*collectinfo.isBeta=false;*/
213 collectinfo.buildDate=1;
214 // leave ccsCols empty (no cross-coll. searching - for now)
215 /*collectinfo.ccsCols=(text_tarray);*/ //not like this!!!
216 collectinfo.languages.push_back("en");
217 collectinfo.languages.push_back("fr");
218 collectinfo.numDocs=0;
219 collectinfo.numWords=0;
220 collectinfo.numBytes=0;
221 // copy the text maps over.
222 // collectinfo.collectionmeta; // text_tmap
223 // delete collectinfo.collectionmeta;
224 collectinfo.collectionmeta=*(here->getMeta());
225 /* collectinfo.format; //text_tmap
226 collectinfo.building; //text_tmap
227 */
228
229 ////collectinfo.receptionist="z3950";
230 /* for now... this is a url, relative to .../cgi-bin.
231 NOTE: if this is empty, it defaults to _gwcgi_?a=p&p=about&c=<colname>
232 */
233}
234
235void z3950proto::get_filterinfo (const text_t &/*collection*/,
236 InfoFiltersResponse_t &/*response*/,
237 comerror_t &/*err*/, ostream &/*logout*/) {
238
239}
240
241void z3950proto::filter (const text_t &collection,
242 FilterRequest_t &request,
243 FilterResponse_t &response,
244 comerror_t &err, ostream &logout) {
245
246 // this function is called when:
247 // * creating the title page,(looking for iconcoll* & collectname metadata)
248 // * creating the about page (looking for "Title" metadata)
249 // For the title page, we should not create a connection to the target
250 // (target means the actual z39.50 server, origin means us), but
251 // for the about page and query pages, we need to get information from the
252 // origin. (eg for the about page, we will print out some info such as ID,
253 // name and version.
254
255 // cerr now goes to errout.txt in etc directory
256
257 response.numDocs=0;
258 response.isApprox=Approximate; // Exact | Approximate | MoreThan
259 // leave response.termInfo empty
260 // leave response.docInfo empty
261 /* got the following for first query:
262 request.filterResultOptions=FRmetadata;
263 request.getParents=getParents
264 request.fields=metadata
265 request.docSet (includes OID);
266 */
267
268 // response.termInfo.push_back(""); ??????? (should be empty if not req.)
269
270
271 if (request.filterResultOptions & FRmetadata) {
272
273 ColInfoResponse_t *info = new ColInfoResponse_t;
274 get_collectinfo (collection, *info, err, logout);
275 // should check err returned here....
276
277 ////////// cerr << "Filter.\n";
278
279 ResultDocInfo_t *docInfo=new ResultDocInfo_t;
280
281 /* In the absence of any other information, (eg commented code),
282 assuming that if the request.fields is empty, then we should return
283 all metadata, otherwise return only the requested fields */
284
285 if (!request.fields.empty()) {
286 // loop on all the metadata fields in request.fields (type text_tset)
287 text_tset::iterator fields_here=request.fields.begin();
288 text_tset::iterator fields_end=request.fields.end();
289 text_tmap::iterator it;
290 while (fields_here!=fields_end) {
291 it=info->collectionmeta.find(*fields_here);
292 ////////// cerr << "filter: getting " << (*fields_here).getcstr();
293 if (it!=info->collectionmeta.end())
294 docInfo->metadata[*fields_here].values.push_back((*it).second);
295 else {
296 docInfo->metadata[*fields_here].values.push_back("");
297 /////// cerr << " (not found)";
298 }
299 ////////cerr << "\n";
300 fields_here++;
301 } // end of while loop
302 } // end of if (!request.fields.empty())
303 else {
304 // return all metadata for about page or query
305 text_tmap::iterator colmeta_here=info->collectionmeta.begin();
306 text_tmap::iterator colmeta_end=info->collectionmeta.end();
307 while (colmeta_here!=colmeta_end) {
308 docInfo->metadata[(*colmeta_here).first].
309 values.push_back((*colmeta_here).second);
310 /////cerr << "\t" << (*colmeta_here).first.getcstr() << "\n";
311 colmeta_here++;
312 }
313 // get data from target.
314 z3950_server_array::iterator zserver = zservers.begin();
315 z3950_server_array::iterator zend = zservers.end();
316 while (zserver != zend) {
317 if(zserver->getName()==collection) {
318 break;
319 }
320 zserver++;
321 }
322 // now have collection in zserver.
323 // check if "collectionextra" metadata is set. If it isn't, we should
324 // create connection to target to get it.
325 if (info->collectionmeta.find("collectionextra")==colmeta_end) {
326 // it doesn't exist.
327 zserver->setMeta("collectionextra","This is some extra info.");
328 docInfo->metadata["collectionextra"].values.push_back("This is extra");
329 }
330
331 } // end of else
332
333 response.docInfo.push_back(*docInfo);
334 } //end of if (... & FRmetadata) ...
335 err=noError;
336}
337
338void z3950proto::get_document (const text_t &/*collection*/,
339 const DocumentRequest_t &/*request*/,
340 DocumentResponse_t &/*response*/,
341 comerror_t &err, ostream &logout) {
342
343 if (0) {
344 err=protocolError;
345 logout << "Some error\n";
346 }
347}
348
349
350#endif
Note: See TracBrowser for help on using the repository browser.