1 | #include "z3950server.h"
|
---|
2 | #include "comtypes.h"
|
---|
3 | #include <stdio.h>
|
---|
4 | // z39.50 yaz stuff
|
---|
5 |
|
---|
6 | extern "C" {
|
---|
7 | #include "yaz/client/yaz_zclient.h"
|
---|
8 | }
|
---|
9 |
|
---|
10 | /***
|
---|
11 | each z39.50 server+database pair is a GSDL collection.
|
---|
12 | ***/
|
---|
13 |
|
---|
14 | z3950_server::z3950_server() {
|
---|
15 | info=NULL;
|
---|
16 | connected=false;
|
---|
17 | titles=NULL;
|
---|
18 | // for now, assume that all records will have text associated with them.
|
---|
19 | meta["hastxt"]="1";
|
---|
20 | }
|
---|
21 |
|
---|
22 | z3950_server::~z3950_server() {
|
---|
23 | }
|
---|
24 |
|
---|
25 | void z3950_server::setMeta(const text_t &key, const text_t &value) {
|
---|
26 | meta[key]=value;
|
---|
27 | }
|
---|
28 |
|
---|
29 | void z3950_server::setName(const text_t &newname) {
|
---|
30 | title=newname;
|
---|
31 | meta["collectionname"]=newname;
|
---|
32 | }
|
---|
33 |
|
---|
34 | void z3950_server::addcfgAbout(const text_t &lang, const text_t &abouttext) {
|
---|
35 | about[lang]=abouttext;
|
---|
36 | }
|
---|
37 |
|
---|
38 | bool z3950_server::getcfgAbout(const text_t &lang, text_t &abouttxt) {
|
---|
39 | text_tmap::iterator it;
|
---|
40 | it=about.find(lang);
|
---|
41 | if (it==about.end()) return (false);
|
---|
42 | abouttxt=((*it).second);
|
---|
43 | return (true);
|
---|
44 | }
|
---|
45 |
|
---|
46 |
|
---|
47 | // now functions that actually talk over the tcp connection.
|
---|
48 |
|
---|
49 | // create a tcp connection to the associated target. Currently, this will
|
---|
50 | // re-initialise if we are already connected.
|
---|
51 | bool z3950_server::connect() {
|
---|
52 | text_t server_and_port;
|
---|
53 | char *zserverinfo;
|
---|
54 |
|
---|
55 | server_and_port=info->host+":"+info->port;
|
---|
56 | // remember that info.name is the database name
|
---|
57 |
|
---|
58 | z_initialize();
|
---|
59 |
|
---|
60 | if (z_cmd_open(server_and_port.getcstr(),info->name.getcstr())==1)
|
---|
61 | // we got a connection error
|
---|
62 | return false;
|
---|
63 |
|
---|
64 | // get initialisation response.
|
---|
65 | z_getnextAPDU();
|
---|
66 | zserverinfo=z_get_initResponse();
|
---|
67 | if (zserverinfo!=NULL) {
|
---|
68 | z_initstr.appendcstr(zserverinfo);
|
---|
69 | }
|
---|
70 | free(zserverinfo);
|
---|
71 |
|
---|
72 | connected=true;
|
---|
73 | return true;
|
---|
74 | }
|
---|
75 |
|
---|
76 | text_tarray *z3950_server::getbriefrecords(const text_t &query,
|
---|
77 | int first, int count,
|
---|
78 | int *nummatches, comerror_t &err) {
|
---|
79 | char **c_str_titles;
|
---|
80 | int i;
|
---|
81 | int last;
|
---|
82 | if (titles!=NULL) delete (titles);
|
---|
83 | titles=new text_tarray;
|
---|
84 |
|
---|
85 | if (connected==false)
|
---|
86 | if (connect()==false) {
|
---|
87 | // we could not connect.
|
---|
88 | err=protocolError;
|
---|
89 | return (NULL);
|
---|
90 | }
|
---|
91 |
|
---|
92 |
|
---|
93 | // We need to format the query string into RPN -
|
---|
94 | // by just passing it like this, it will only work for simple queries.
|
---|
95 | /* check if connected */
|
---|
96 | /* titles->push_back("first dummy title");
|
---|
97 | titles->push_back("Second dummy title");
|
---|
98 | return titles;
|
---|
99 | */
|
---|
100 | // following functions defined in yaz_zclient.c
|
---|
101 | *nummatches=z_cmd_dosearch(query.getcstr()); // returns # found, -1 on err.
|
---|
102 | // could just check if (*nummatches)==0.
|
---|
103 |
|
---|
104 | // could do a sort eventually, eg on date, title, etc.
|
---|
105 | // (non-existent function) z_sort(field, asc|desc);
|
---|
106 | /* min of (count, first + (*nummatches) ) */
|
---|
107 | c_str_titles=z_getbriefrecords(first,count);
|
---|
108 | if (c_str_titles==NULL) {
|
---|
109 | // an error occurred. we need a logout/err as an arg
|
---|
110 | return (NULL);
|
---|
111 | }
|
---|
112 | if (c_str_titles[0]==0) {
|
---|
113 | // no matches.
|
---|
114 | return (NULL);
|
---|
115 | }
|
---|
116 | last=(int)c_str_titles[0];
|
---|
117 | for (i=1;i<=last;i++) {
|
---|
118 | titles->push_back(c_str_titles[i]);
|
---|
119 | free(c_str_titles[i]);
|
---|
120 | }
|
---|
121 | free(c_str_titles);
|
---|
122 | return (titles);
|
---|
123 |
|
---|
124 | }
|
---|
125 |
|
---|
126 | bool z3950_server::getfullrecord(const int ID, text_t &rettitle,
|
---|
127 | text_t &rettext, comerror_t &err) {
|
---|
128 | if (connected==false) {
|
---|
129 | if (connect()==false) {
|
---|
130 | // error connecting...
|
---|
131 | err=protocolError;
|
---|
132 | return (false);
|
---|
133 | }
|
---|
134 | // since we have just re-connected, we need to do the
|
---|
135 | // query again.
|
---|
136 | }
|
---|
137 |
|
---|
138 | if (rettitle!="unneeded") {
|
---|
139 | /*char **c_str_titles;
|
---|
140 | int dummy;
|
---|
141 | c_str_titles=z_getbriefrecords("the",ID,1,&dummy); // check this return value.
|
---|
142 | if (c_str_titles!=NULL && (int)c_str_titles[0]==1) {
|
---|
143 | rettitle.setcstr(c_str_titles[1]); // and check this
|
---|
144 | free (c_str_titles);
|
---|
145 | */
|
---|
146 | // rettitle=(*titles)[ID]; // this isn't quite right, as ID isn't the offset
|
---|
147 | rettitle="Dummy Title";
|
---|
148 | }
|
---|
149 |
|
---|
150 | if (rettext!="unneeded") {
|
---|
151 | // get the text
|
---|
152 | rettext="Dummy Text. This is here as a placeholder until I work out";
|
---|
153 | rettext+=" a way to get the query again when running in simple cgi\n";
|
---|
154 | rettext+="as after each page is completed, the connection is lost to the";
|
---|
155 | rettext+=" server, and we forget what the query was\n";
|
---|
156 | }
|
---|
157 | return (true);
|
---|
158 | }
|
---|
159 |
|
---|
160 | text_t &z3950_server::getzAbout() {
|
---|
161 | text_t zserverresp;
|
---|
162 |
|
---|
163 | // Assume we have not yet connected, so that must be done here.
|
---|
164 | if (connected==true)
|
---|
165 | return (z_initstr);
|
---|
166 |
|
---|
167 | // we need to create the tcp connection to the target (server)
|
---|
168 | // z_initstr=new text_t;
|
---|
169 |
|
---|
170 | if (connect()==false) {
|
---|
171 | z_initstr.setcstr("<H2>Server offline</H2>Error - could not connect to server <B>");
|
---|
172 | z_initstr += info->host.getcstr();
|
---|
173 | z_initstr += "</B> on port ";
|
---|
174 | z_initstr += info->port;
|
---|
175 | z_initstr += "\n";
|
---|
176 | return (z_initstr);
|
---|
177 | }
|
---|
178 |
|
---|
179 | // z_initstr currently contains the target's response. We want to
|
---|
180 | // PREPEND the following information.
|
---|
181 | zserverresp=z_initstr;
|
---|
182 | z_initstr="Internet server: <b>";
|
---|
183 | z_initstr+=info->host;
|
---|
184 | z_initstr+="</b> on port ";
|
---|
185 | z_initstr+=info->port;
|
---|
186 | z_initstr+=".<br>\n";
|
---|
187 | z_initstr+=zserverresp;
|
---|
188 |
|
---|
189 | // should close /******* WHAT IF DOING A QUERY!??!?!? ********/
|
---|
190 | // z_cmd_close(0);
|
---|
191 | // connected=false;
|
---|
192 | return (z_initstr);
|
---|
193 | }
|
---|
194 |
|
---|