6753fc9b4bf4295cb687f63138716c8e1febdca6
[yazpp-moved-to-github.git] / src / yaz-ir-assoc.cpp
1 /*
2  * Copyright (c) 1998-2000, Index Data.
3  * See the file LICENSE for details.
4  * 
5  * $Log: yaz-ir-assoc.cpp,v $
6  * Revision 1.13  2000-09-06 14:23:45  adam
7  * WIN32 updates.
8  *
9  * Revision 1.12  2000/05/10 11:36:58  ian
10  * Added default parameters for refid to request functions.
11  * Added default parameter for result set name to search and present request.
12  * Commented out forced logging of PDU contents.
13  * Added send_deleteResultSetRequest
14  *
15  * Revision 1.11  1999/12/06 13:52:45  adam
16  * Modified for new location of YAZ header files. Experimental threaded
17  * operation.
18  *
19  * Revision 1.10  1999/04/29 07:33:28  adam
20  * Changed setting of host in connect/proxy setting. YAZ' strtoaddr now
21  * ignores database part of host.
22  *
23  * Revision 1.9  1999/04/28 13:29:14  adam
24  * Yet another fix regarding database settings.
25  *
26  * Revision 1.8  1999/04/28 13:04:03  adam
27  * Fixed setting of proxy otherInfo so that database(s) are removed.
28  *
29  * Revision 1.7  1999/04/21 12:09:01  adam
30  * Many improvements. Modified to proxy server to work with "sessions"
31  * based on cookies.
32  *
33  * Revision 1.6  1999/04/20 10:30:05  adam
34  * Implemented various stuff for client and proxy. Updated calls
35  * to ODR to reflect new name parameter.
36  *
37  * Revision 1.5  1999/04/09 11:46:57  adam
38  * Added object Yaz_Z_Assoc. Much more functional client.
39  */
40
41 #include <assert.h>
42
43 #include <yaz/log.h>
44 #include <yaz-ir-assoc.h>
45
46 Yaz_IR_Assoc::Yaz_IR_Assoc(IYaz_PDU_Observable *the_PDU_Observable)
47     : Yaz_Z_Assoc(the_PDU_Observable)
48 {
49     m_num_databaseNames = 0;
50     m_databaseNames = 0;
51     m_preferredRecordSyntax = VAL_NONE;
52     m_elementSetNames = 0;
53     m_lastReceived = 0;
54     m_host = 0;
55     m_proxy = 0;
56     m_cookie = 0;
57     m_log = LOG_DEBUG;
58     const char *db = "Default";
59     set_databaseNames(1, &db);
60 }
61
62 Yaz_IR_Assoc::~Yaz_IR_Assoc()
63 {
64     if (m_elementSetNames)
65         delete [] m_elementSetNames->u.generic;
66     delete [] m_elementSetNames;
67     delete [] m_host;
68     delete [] m_proxy;
69     delete [] m_cookie;
70 }
71
72 void Yaz_IR_Assoc::get_databaseNames (int *num, char ***list)
73 {
74     *num = m_num_databaseNames;
75     *list = m_databaseNames;
76 }
77
78 typedef char *charp;
79 void Yaz_IR_Assoc::set_databaseNames (int num, const char **list)
80 {
81     int i;
82     logf (m_log, "Yaz_IR_Assoc::set_databaseNames num=%d", num);
83     for (i = 0; i<m_num_databaseNames; i++)
84         delete [] m_databaseNames[i];
85     delete [] m_databaseNames;
86     m_num_databaseNames = num;
87
88     m_databaseNames = new char *[num];
89     for (i = 0; i<m_num_databaseNames; i++)
90     {
91         m_databaseNames[i] = new char[strlen(list[i])+1];
92         strcpy(m_databaseNames[i], list[i]);
93     }
94 }
95
96 void Yaz_IR_Assoc::set_databaseNames(const char *dblist, const char *sep)
97 {
98     const char **list = new const char* [strlen(dblist)];
99     char *dbtmp = new char[strlen(dblist)+1];
100     strcpy(dbtmp, dblist);
101     int num = 0;
102     int len = 0;
103     for (char *cp = dbtmp; ; cp++)
104         if (*cp && !strchr(sep, *cp))
105             len++;
106         else
107         {
108             if (len)
109             {
110                 list[num] = cp - len;
111                 num++;
112             }
113             if (!*cp)
114                 break;
115             *cp = '\0';
116             len = 0;
117         }
118     set_databaseNames (num, list);
119     delete [] dbtmp;
120     delete [] list;
121 }
122
123 void Yaz_IR_Assoc::set_preferredRecordSyntax (int value)
124 {
125     m_preferredRecordSyntax = value;
126 }
127
128 void Yaz_IR_Assoc::set_preferredRecordSyntax (const char *syntax)
129 {
130     m_preferredRecordSyntax = VAL_NONE;
131     if (syntax && *syntax)
132         m_preferredRecordSyntax = oid_getvalbyname (syntax);
133 }
134
135 void Yaz_IR_Assoc::get_preferredRecordSyntax (int *value)
136 {
137     *value = m_preferredRecordSyntax;
138 }
139
140 void Yaz_IR_Assoc::get_preferredRecordSyntax (const char **dst)
141 {
142     struct oident ent;
143     ent.proto = PROTO_Z3950;
144     ent.oclass = CLASS_RECSYN;
145     ent.value = (enum oid_value) m_preferredRecordSyntax;
146
147     int oid[OID_SIZE];
148     oid_ent_to_oid (&ent, oid);
149     struct oident *entp = oid_getentbyoid (oid);
150     
151     *dst = entp ? entp->desc : "";
152 }
153
154 void Yaz_IR_Assoc::set_elementSetName (const char *elementSetName)
155 {
156     if (m_elementSetNames)
157         delete [] m_elementSetNames->u.generic;
158     delete m_elementSetNames;
159     m_elementSetNames = 0;
160     if (elementSetName && *elementSetName)
161     {
162         m_elementSetNames = new Z_ElementSetNames;
163         m_elementSetNames->which = Z_ElementSetNames_generic;
164         m_elementSetNames->u.generic = new char[strlen(elementSetName)+1];
165         strcpy (m_elementSetNames->u.generic, elementSetName);
166     }
167 }
168
169 void Yaz_IR_Assoc::get_elementSetName (Z_ElementSetNames **elementSetNames)
170 {
171     *elementSetNames = m_elementSetNames;
172 }
173
174 void Yaz_IR_Assoc::get_elementSetName (const char **elementSetName)
175 {
176     if (!m_elementSetNames ||
177         m_elementSetNames->which != Z_ElementSetNames_generic)
178     {
179         *elementSetName = 0;
180         return;
181     }
182     *elementSetName = m_elementSetNames->u.generic;
183 }
184
185 void Yaz_IR_Assoc::recv_Z_PDU(Z_APDU *apdu)
186 {
187     logf (m_log, "recv_Z_PDU");
188     m_lastReceived = apdu->which;
189     switch (apdu->which)
190     {
191     case Z_APDU_initResponse:
192         logf (m_log, "recv InitResponse");
193         recv_initResponse(apdu->u.initResponse);
194         break;
195     case Z_APDU_initRequest:
196         logf (m_log, "recv InitRequest");
197         recv_initRequest(apdu->u.initRequest);
198         break;
199     case Z_APDU_searchRequest:
200         logf (m_log, "recv searchRequest");
201         recv_searchRequest(apdu->u.searchRequest);
202         break;
203     case Z_APDU_searchResponse:
204         logf (m_log, "recv searchResponse"); 
205         recv_searchResponse(apdu->u.searchResponse);
206         break;
207     case Z_APDU_presentRequest:
208         logf (m_log, "recv presentRequest");
209         recv_presentRequest(apdu->u.presentRequest);
210         break;
211     case Z_APDU_presentResponse:
212         logf (m_log, "recv presentResponse");
213         recv_presentResponse(apdu->u.presentResponse);
214         break;
215     }
216 }
217
218 int Yaz_IR_Assoc::send_searchRequest(Yaz_Z_Query *query,
219                                      char* pResultSetId,
220                                      char* pRefId)
221 {
222     Z_APDU *apdu = create_Z_PDU(Z_APDU_searchRequest);
223     Z_SearchRequest *req = apdu->u.searchRequest;
224     int recordSyntax;
225
226     req->query = query->get_Z_Query();
227     if (!req->query)
228         return -1;
229     get_databaseNames (&req->num_databaseNames, &req->databaseNames);
230     int oid_syntax[OID_SIZE];
231     oident prefsyn;
232     get_preferredRecordSyntax(&recordSyntax);
233     if (recordSyntax != VAL_NONE)
234     {
235         prefsyn.proto = PROTO_Z3950;
236         prefsyn.oclass = CLASS_RECSYN;
237         prefsyn.value = (enum oid_value) recordSyntax;
238         oid_ent_to_oid(&prefsyn, oid_syntax);
239         req->preferredRecordSyntax = oid_syntax;
240     }
241     logf (m_log, "send_searchRequest");
242     assert (req->otherInfo == 0);
243     if (m_cookie)
244     {
245         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
246         assert (req->otherInfo);
247     }
248
249     if ( pRefId )
250     {
251         req->referenceId = getRefID(pRefId);
252     }
253
254     if ( pResultSetId )
255     {
256         req->resultSetName = pResultSetId;
257     }
258
259     return send_Z_PDU(apdu);
260 }
261
262 int Yaz_IR_Assoc::send_presentRequest(int start, 
263                                       int number, 
264                                       char* pResultSetId,
265                                       char* pRefId)
266 {
267     Z_APDU *apdu = create_Z_PDU(Z_APDU_presentRequest);
268     Z_PresentRequest *req = apdu->u.presentRequest;
269
270     req->resultSetStartPoint = &start;
271     req->numberOfRecordsRequested = &number;
272
273     int oid_syntax[OID_SIZE];
274     oident prefsyn;
275     int recordSyntax;
276     get_preferredRecordSyntax (&recordSyntax);
277     if (recordSyntax != VAL_NONE)
278     {
279         prefsyn.proto = PROTO_Z3950;
280         prefsyn.oclass = CLASS_RECSYN;
281         prefsyn.value = (enum oid_value) recordSyntax;
282         oid_ent_to_oid(&prefsyn, oid_syntax);
283         req->preferredRecordSyntax = oid_syntax;
284     }
285     Z_RecordComposition compo;
286     Z_ElementSetNames *elementSetNames;
287     get_elementSetName (&elementSetNames);
288     if (elementSetNames)
289     {
290         req->recordComposition = &compo;
291         compo.which = Z_RecordComp_simple;
292         compo.u.simple = elementSetNames;
293     }
294
295     if (m_cookie)
296         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
297
298     if ( pRefId )
299     {
300         req->referenceId = getRefID(pRefId);
301     }
302
303     if ( pResultSetId )
304     {
305         req->resultSetId = pResultSetId;
306     }
307
308     return send_Z_PDU(apdu);
309 }
310
311 void Yaz_IR_Assoc::set_proxy(const char *str)
312 {
313     delete [] m_proxy;
314     m_proxy = 0;
315     if (str)
316     {
317         m_proxy = new char[strlen(str)+1];
318         strcpy (m_proxy, str);
319     }
320 }
321
322 void Yaz_IR_Assoc::set_cookie(const char *str)
323 {
324     delete [] m_cookie;
325     m_cookie = 0;
326     if (str)
327     {
328         m_cookie = new char[strlen(str)+1];
329         strcpy(m_cookie, str);
330     }
331 }
332
333 const char *Yaz_IR_Assoc::get_cookie()
334 {
335     return m_cookie;
336 }
337
338 void Yaz_IR_Assoc::client(const char *addr)
339 {
340     delete [] m_host;
341     m_host = new char[strlen(addr)+1];
342     strcpy(m_host, addr);
343     const char *dbpart = strchr(m_host, '/');
344     if (dbpart)
345         set_databaseNames (dbpart+1, "+ ");
346     Yaz_Z_Assoc::client(m_proxy ? m_proxy : m_host);
347 }
348
349 const char *Yaz_IR_Assoc::get_proxy()
350 {
351     return m_proxy;
352 }
353
354 const char *Yaz_IR_Assoc::get_host()
355 {
356     return m_host;
357 }
358
359 void Yaz_IR_Assoc::recv_searchRequest(Z_SearchRequest *searchRequest)
360 {
361     Z_APDU *apdu = create_Z_PDU(Z_APDU_searchResponse);
362     send_Z_PDU(apdu);
363 }
364
365 void Yaz_IR_Assoc::recv_presentRequest(Z_PresentRequest *presentRequest)
366 {
367     Z_APDU *apdu = create_Z_PDU(Z_APDU_presentResponse);
368     send_Z_PDU(apdu);
369 }
370
371 void Yaz_IR_Assoc::recv_initRequest(Z_InitRequest *initRequest)
372 {
373     Z_APDU *apdu = create_Z_PDU(Z_APDU_initResponse);
374     send_Z_PDU(apdu);
375 }
376
377 void Yaz_IR_Assoc::recv_searchResponse (Z_SearchResponse *searchResponse)
378 {
379 }
380
381 void Yaz_IR_Assoc::recv_presentResponse (Z_PresentResponse *presentResponse)
382 {
383 }
384
385 void Yaz_IR_Assoc::recv_initResponse(Z_InitResponse *initResponse)
386 {
387 }
388
389 int Yaz_IR_Assoc::get_lastReceived()
390 {
391     return m_lastReceived;
392 }
393
394 void Yaz_IR_Assoc::set_lastReceived(int lastReceived)
395 {
396     m_lastReceived = lastReceived;
397 }
398
399 int Yaz_IR_Assoc::send_initRequest(char* pRefId)
400 {
401     Z_APDU *apdu = create_Z_PDU(Z_APDU_initRequest);
402     Z_InitRequest *req = apdu->u.initRequest;
403     
404     ODR_MASK_SET(req->options, Z_Options_search);
405     ODR_MASK_SET(req->options, Z_Options_present);
406     ODR_MASK_SET(req->options, Z_Options_namedResultSets);
407     ODR_MASK_SET(req->options, Z_Options_triggerResourceCtrl);
408     ODR_MASK_SET(req->options, Z_Options_scan);
409     ODR_MASK_SET(req->options, Z_Options_sort);
410     ODR_MASK_SET(req->options, Z_Options_extendedServices);
411     ODR_MASK_SET(req->options, Z_Options_delSet);
412
413     ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_1);
414     ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_2);
415     ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_3);
416
417     if ( pRefId )
418     {
419         req->referenceId = getRefID(pRefId);
420     }
421
422     if (m_proxy && m_host)
423         set_otherInformationString(&req->otherInfo, VAL_PROXY, 1, m_host);
424     if (m_cookie)
425         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
426     return send_Z_PDU(apdu);
427 }
428
429 int Yaz_IR_Assoc::send_deleteResultSetRequest(char* pResultSetId, char* pRefId)
430 {
431     char* ResultSetIds[1];
432
433     Z_APDU *apdu = create_Z_PDU(Z_APDU_deleteResultSetRequest);
434     Z_DeleteResultSetRequest *req = apdu->u.deleteResultSetRequest;
435
436     if ( pResultSetId )
437     {
438         *req->deleteFunction = Z_DeleteResultSetRequest_list;
439         req->num_resultSetList = 1;
440         ResultSetIds[0] = pResultSetId;
441         req->resultSetList = ResultSetIds;
442     }
443     else
444     {
445         *req->deleteFunction = Z_DeleteResultSetRequest_all;
446     }
447     
448     if ( pRefId )
449     {
450         req->referenceId = getRefID(pRefId);
451     }
452
453     if (m_proxy && m_host)
454         set_otherInformationString(&req->otherInfo, VAL_PROXY, 1, m_host);
455     if (m_cookie)
456         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
457
458
459     return send_Z_PDU(apdu);
460 }
461
462