Many improvements. Modified to proxy server to work with "sessions"
[yazpp-moved-to-github.git] / src / yaz-ir-assoc.cpp
1 /*
2  * Copyright (c) 1998-1999, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  * 
6  * $Log: yaz-ir-assoc.cpp,v $
7  * Revision 1.7  1999-04-21 12:09:01  adam
8  * Many improvements. Modified to proxy server to work with "sessions"
9  * based on cookies.
10  *
11  * Revision 1.6  1999/04/20 10:30:05  adam
12  * Implemented various stuff for client and proxy. Updated calls
13  * to ODR to reflect new name parameter.
14  *
15  * Revision 1.5  1999/04/09 11:46:57  adam
16  * Added object Yaz_Z_Assoc. Much more functional client.
17  */
18
19 #include <assert.h>
20
21 #include <log.h>
22 #include <yaz-ir-assoc.h>
23
24 Yaz_IR_Assoc::Yaz_IR_Assoc(IYaz_PDU_Observable *the_PDU_Observable)
25     : Yaz_Z_Assoc(the_PDU_Observable)
26 {
27     m_num_databaseNames = 0;
28     m_databaseNames = 0;
29     m_preferredRecordSyntax = VAL_NONE;
30     m_elementSetNames = 0;
31     m_lastReceived = 0;
32     m_host = 0;
33     m_proxy = 0;
34     m_cookie = 0;
35     const char *db = "Default";
36     set_databaseNames(1, &db);
37 }
38
39 Yaz_IR_Assoc::~Yaz_IR_Assoc()
40 {
41     if (m_elementSetNames)
42         delete [] m_elementSetNames->u.generic;
43     delete [] m_elementSetNames;
44     delete [] m_host;
45     delete [] m_proxy;
46     delete [] m_cookie;
47 }
48
49 void Yaz_IR_Assoc::get_databaseNames (int *num, char ***list)
50 {
51     *num = m_num_databaseNames;
52     *list = m_databaseNames;
53 }
54
55 void Yaz_IR_Assoc::set_databaseNames (int num, const char **list)
56 {
57     int i;
58     logf (LOG_LOG, "Yaz_IR_Assoc::set_databaseNames num=%d", num);
59     for (i = 0; i<m_num_databaseNames; i++)
60         delete [] m_databaseNames[i];
61     delete [] m_databaseNames;
62     m_num_databaseNames = num;
63     m_databaseNames = new (char*) [num];
64     for (i = 0; i<m_num_databaseNames; i++)
65     {
66         m_databaseNames[i] = new char[strlen(list[i])+1];
67         strcpy(m_databaseNames[i], list[i]);
68     }
69 }
70
71 void Yaz_IR_Assoc::set_databaseNames(const char *dblist, const char *sep)
72 {
73     const char **list = new (const char*) [strlen(dblist)];
74     char *dbtmp = new char[strlen(dblist)+1];
75     strcpy(dbtmp, dblist);
76     int num = 0;
77     int len = 0;
78     for (char *cp = dbtmp; ; cp++)
79         if (*cp && !strchr(sep, *cp))
80             len++;
81         else
82         {
83             if (len)
84             {
85                 list[num] = cp - len;
86                 num++;
87             }
88             if (!*cp)
89                 break;
90             *cp = '\0';
91             len = 0;
92         }
93     set_databaseNames (num, list);
94     delete [] dbtmp;
95     delete [] list;
96 }
97
98 void Yaz_IR_Assoc::set_preferredRecordSyntax (int value)
99 {
100     m_preferredRecordSyntax = value;
101 }
102
103 void Yaz_IR_Assoc::set_preferredRecordSyntax (const char *syntax)
104 {
105     m_preferredRecordSyntax = VAL_NONE;
106     if (syntax && *syntax)
107         m_preferredRecordSyntax = oid_getvalbyname (syntax);
108 }
109
110 void Yaz_IR_Assoc::get_preferredRecordSyntax (int *value)
111 {
112     *value = m_preferredRecordSyntax;
113 }
114
115 void Yaz_IR_Assoc::get_preferredRecordSyntax (const char **dst)
116 {
117     struct oident ent;
118     ent.proto = PROTO_Z3950;
119     ent.oclass = CLASS_RECSYN;
120     ent.value = (enum oid_value) m_preferredRecordSyntax;
121
122     int oid[OID_SIZE];
123     oid_ent_to_oid (&ent, oid);
124     struct oident *entp = oid_getentbyoid (oid);
125     
126     *dst = entp ? entp->desc : "";
127 }
128
129 void Yaz_IR_Assoc::set_elementSetName (const char *elementSetName)
130 {
131     if (m_elementSetNames)
132         delete [] m_elementSetNames->u.generic;
133     delete m_elementSetNames;
134     m_elementSetNames = 0;
135     if (elementSetName && *elementSetName)
136     {
137         m_elementSetNames = new Z_ElementSetNames;
138         m_elementSetNames->which = Z_ElementSetNames_generic;
139         m_elementSetNames->u.generic = new char[strlen(elementSetName)+1];
140         strcpy (m_elementSetNames->u.generic, elementSetName);
141     }
142 }
143
144 void Yaz_IR_Assoc::get_elementSetName (Z_ElementSetNames **elementSetNames)
145 {
146     *elementSetNames = m_elementSetNames;
147 }
148
149 void Yaz_IR_Assoc::get_elementSetName (const char **elementSetName)
150 {
151     if (!m_elementSetNames ||
152         m_elementSetNames->which != Z_ElementSetNames_generic)
153     {
154         *elementSetName = 0;
155         return;
156     }
157     *elementSetName = m_elementSetNames->u.generic;
158 }
159
160 void Yaz_IR_Assoc::recv_Z_PDU(Z_APDU *apdu)
161 {
162     logf (LOG_LOG, "recv_Z_PDU");
163     m_lastReceived = apdu->which;
164     switch (apdu->which)
165     {
166     case Z_APDU_initResponse:
167         logf (LOG_LOG, "recv InitResponse");
168         recv_initResponse(apdu->u.initResponse);
169         break;
170     case Z_APDU_initRequest:
171         logf (LOG_LOG, "recv InitRequest");
172         recv_initRequest(apdu->u.initRequest);
173         break;
174     case Z_APDU_searchRequest:
175         logf (LOG_LOG, "recv searchRequest");
176         recv_searchRequest(apdu->u.searchRequest);
177         break;
178     case Z_APDU_searchResponse:
179         logf (LOG_LOG, "recv searchResponse"); 
180         recv_searchResponse(apdu->u.searchResponse);
181         break;
182     case Z_APDU_presentRequest:
183         logf (LOG_LOG, "recv presentRequest");
184         recv_presentRequest(apdu->u.presentRequest);
185         break;
186     case Z_APDU_presentResponse:
187         logf (LOG_LOG, "recv presentResponse");
188         recv_presentResponse(apdu->u.presentResponse);
189         break;
190     }
191 }
192
193 int Yaz_IR_Assoc::send_searchRequest(Yaz_Z_Query *query)
194 {
195     Z_APDU *apdu = create_Z_PDU(Z_APDU_searchRequest);
196     Z_SearchRequest *req = apdu->u.searchRequest;
197     int recordSyntax;
198
199     req->query = query->get_Z_Query();
200     if (!req->query)
201         return -1;
202     get_databaseNames (&req->num_databaseNames, &req->databaseNames);
203     int oid_syntax[OID_SIZE];
204     oident prefsyn;
205     get_preferredRecordSyntax(&recordSyntax);
206     if (recordSyntax != VAL_NONE)
207     {
208         prefsyn.proto = PROTO_Z3950;
209         prefsyn.oclass = CLASS_RECSYN;
210         prefsyn.value = (enum oid_value) recordSyntax;
211         oid_ent_to_oid(&prefsyn, oid_syntax);
212         req->preferredRecordSyntax = oid_syntax;
213     }
214     logf (LOG_LOG, "send_searchRequest");
215     assert (req->otherInfo == 0);
216     if (m_cookie)
217     {
218         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
219         assert (req->otherInfo);
220     }
221     return send_Z_PDU(apdu);
222 }
223
224 int Yaz_IR_Assoc::send_presentRequest(int start, int number)
225 {
226     Z_APDU *apdu = create_Z_PDU(Z_APDU_presentRequest);
227     Z_PresentRequest *req = apdu->u.presentRequest;
228
229     req->resultSetStartPoint = &start;
230     req->numberOfRecordsRequested = &number;
231
232     int oid_syntax[OID_SIZE];
233     oident prefsyn;
234     int recordSyntax;
235     get_preferredRecordSyntax (&recordSyntax);
236     if (recordSyntax != VAL_NONE)
237     {
238         prefsyn.proto = PROTO_Z3950;
239         prefsyn.oclass = CLASS_RECSYN;
240         prefsyn.value = (enum oid_value) recordSyntax;
241         oid_ent_to_oid(&prefsyn, oid_syntax);
242         req->preferredRecordSyntax = oid_syntax;
243     }
244     Z_RecordComposition compo;
245     Z_ElementSetNames *elementSetNames;
246     get_elementSetName (&elementSetNames);
247     if (elementSetNames)
248     {
249         req->recordComposition = &compo;
250         compo.which = Z_RecordComp_simple;
251         compo.u.simple = elementSetNames;
252     }
253     if (m_cookie)
254         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
255     return send_Z_PDU(apdu);
256 }
257
258 void Yaz_IR_Assoc::set_proxy(const char *str)
259 {
260     delete [] m_proxy;
261     m_proxy = 0;
262     if (str)
263     {
264         m_proxy = new char[strlen(str)+1];
265         strcpy (m_proxy, str);
266     }
267 }
268
269 void Yaz_IR_Assoc::set_cookie(const char *str)
270 {
271     delete [] m_cookie;
272     m_cookie = 0;
273     if (str)
274     {
275         m_cookie = new char[strlen(str)+1];
276         strcpy(m_cookie, str);
277     }
278 }
279
280 const char *Yaz_IR_Assoc::get_cookie()
281 {
282     return m_cookie;
283 }
284
285 void Yaz_IR_Assoc::client(const char *addr)
286 {
287     delete [] m_host;
288     m_host = new char[strlen(addr)+1];
289     strcpy(m_host, addr);
290     const char *zurl_p = (m_proxy ? m_proxy : m_host);
291     char *zurl = new char[strlen(zurl_p)+1];
292     strcpy(zurl, zurl_p);
293     char *dbpart = strchr(zurl, '/');
294     if (dbpart)
295     {
296         set_databaseNames (dbpart+1, "+ ");
297         *dbpart = '\0';
298     }
299     Yaz_Z_Assoc::client(zurl);
300     delete [] zurl;
301 }
302
303 const char *Yaz_IR_Assoc::get_proxy()
304 {
305     return m_proxy;
306 }
307
308 const char *Yaz_IR_Assoc::get_host()
309 {
310     return m_host;
311 }
312
313 void Yaz_IR_Assoc::recv_searchRequest(Z_SearchRequest *searchRequest)
314 {
315     Z_APDU *apdu = create_Z_PDU(Z_APDU_searchResponse);
316     send_Z_PDU(apdu);
317 }
318
319 void Yaz_IR_Assoc::recv_presentRequest(Z_PresentRequest *presentRequest)
320 {
321     Z_APDU *apdu = create_Z_PDU(Z_APDU_presentResponse);
322     send_Z_PDU(apdu);
323 }
324
325 void Yaz_IR_Assoc::recv_initRequest(Z_InitRequest *initRequest)
326 {
327     Z_APDU *apdu = create_Z_PDU(Z_APDU_initResponse);
328     send_Z_PDU(apdu);
329 }
330
331 void Yaz_IR_Assoc::recv_searchResponse (Z_SearchResponse *searchResponse)
332 {
333 }
334
335 void Yaz_IR_Assoc::recv_presentResponse (Z_PresentResponse *presentResponse)
336 {
337 }
338
339 void Yaz_IR_Assoc::recv_initResponse(Z_InitResponse *initResponse)
340 {
341 }
342
343 int Yaz_IR_Assoc::get_lastReceived()
344 {
345     return m_lastReceived;
346 }
347
348 void Yaz_IR_Assoc::set_lastReceived(int lastReceived)
349 {
350     m_lastReceived = lastReceived;
351 }
352
353 int Yaz_IR_Assoc::send_initRequest()
354 {
355     Z_APDU *apdu = create_Z_PDU(Z_APDU_initRequest);
356     Z_InitRequest *req = apdu->u.initRequest;
357     
358     ODR_MASK_SET(req->options, Z_Options_search);
359     ODR_MASK_SET(req->options, Z_Options_present);
360     ODR_MASK_SET(req->options, Z_Options_namedResultSets);
361     ODR_MASK_SET(req->options, Z_Options_triggerResourceCtrl);
362     ODR_MASK_SET(req->options, Z_Options_scan);
363     ODR_MASK_SET(req->options, Z_Options_sort);
364     ODR_MASK_SET(req->options, Z_Options_extendedServices);
365     ODR_MASK_SET(req->options, Z_Options_delSet);
366
367     ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_1);
368     ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_2);
369     ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_3);
370
371     if (m_proxy && m_host)
372         set_otherInformationString(&req->otherInfo, VAL_PROXY, 1, m_host);
373     if (m_cookie)
374         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
375     return send_Z_PDU(apdu);
376 }
377