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