Minor changes.
[egate.git] / zlayer / zaccess.c
1 /*
2  * Europagate, 1995
3  *
4  * $Log: zaccess.c,v $
5  * Revision 1.4  1995/02/16 15:33:45  quinn
6  * Fixed bug in KWAQS generator
7  *
8  * Revision 1.3  1995/02/16  15:20:45  quinn
9  * Added initialization of response from search
10  *
11  * Revision 1.2  1995/02/16  15:14:53  quinn
12  * Fixed KWAQS-generator
13  *
14  * Revision 1.1  1995/02/16  14:47:55  quinn
15  * First kick.
16  *
17  */
18
19 /*
20  * Interface to the Z39.50 toolkit.
21  */
22
23 #include <stdlib.h>
24 #include <assert.h>
25
26 #include <z3950.h>
27 #include <z3950sup.h>
28 #include <zutil.h>
29
30 #include <gw-log.h>
31
32 #include <ccl.h>
33 #include <zaccess.h>
34
35 struct zass    /* Z-assoc */
36 {
37     NETBOXPROFILE *ass;              /* ZDIST association handle */
38     int fd;                         /* low-level socket (for select only) */
39     int maxrecordsize;
40     int preferredmessagesize;
41     char *buf;                      /* intermediary buffer */
42 };
43
44 int rpn2kwaqs(struct ccl_rpn_node *q, char **p)
45 {
46     struct ccl_rpn_attr *i;
47     static char *ops[] = {"and", "or", "not"};
48
49     assert(!CCL_RPN_AND);
50     switch (q->kind)
51     {
52         case CCL_RPN_TERM:
53             strcpy(*p, q->u.t.term);
54             (*p) += strlen(q->u.t.term);
55             if (q->u.t.attr_list)
56             {
57                 strcat(*p, "[");
58                 (*p)++;
59                 for (i = q->u.t.attr_list; i; i = i->next)
60                 {
61                     sprintf(*p, "%d,%d%s", i->type, i->value, i->next ?
62                         "," : "");
63                     *p += strlen(*p);
64                 }
65                 strcat(*p, "]");
66                 (*p)++;
67             }
68             return 0;
69         case CCL_RPN_SET:
70             gw_log(GW_LOG_FATAL, ZASS_TYPE, "KWAQS Doesn't support set refs");
71             return -1;
72         case CCL_RPN_AND: case CCL_RPN_OR: case CCL_RPN_NOT:
73             strcpy(*p, ops[q->kind]);
74             *p += strlen(ops[q->kind]);
75             strcat(*p, "(");
76             (*p)++;
77             if (rpn2kwaqs(q->u.p[0], p) < 0)
78                 return -1;
79             strcat(*p, ",");
80             (*p)++;
81             if (rpn2kwaqs(q->u.p[1], p) < 0)
82                 return -1;
83             strcat(*p, ")");
84             (*p)++;
85             return 0;
86         default:
87             gw_log(GW_LOG_FATAL, ZASS_TYPE, "Unknown RPN node");
88             return -1;
89     }
90 }
91
92 ZASS zass_open(char *host, int port)
93 {
94     struct zass *p;
95     PINITREQUEST ireq;
96     PINITRESPONSE ires;
97     int len;
98
99     if (!(p = malloc(sizeof(*p))))
100     {
101         gw_log(GW_LOG_FATAL, ZASS_TYPE, "memory alloc failed");
102         return 0;
103     }
104     p->maxrecordsize = ZASS_MAXRECORDSIZE;
105     p->preferredmessagesize = ZASS_PREFERREDMESSAGESIZE;
106     if (!(p->buf = malloc(ZASS_MAXRECORDSIZE + 100)))
107     {
108         gw_log(GW_LOG_FATAL, ZASS_TYPE, "alloc zass-buffer");
109         return 0;
110     }
111     if (!(p->ass = NEWSTRUCT(NETBOXPROFILE)))
112     {
113         gw_log(GW_LOG_FATAL, ZASS_TYPE, "memory alloc failed");
114         return 0;
115     }
116     p->ass->TimeOutSec = 120;
117     p->ass->TimeOutUSec = 0;
118     strcpy(p->ass->HostName, host);
119     p->ass->Port = port;
120
121     if (netbox_Open(p->ass) != 1)
122     {
123         gw_log(GW_LOG_WARN, ZASS_TYPE, "netbox_Open failed");
124         return 0;
125     }
126     gw_log(ZASS_DEBUG, ZASS_TYPE, "Opened connection to %s:%d", p->ass->HostName,
127         p->ass->Port);
128     ireq = InitRequest_CreateInitAllASCII(0, "yy", "yy", p->maxrecordsize,
129         p->preferredmessagesize, ZASS_ID, ZASS_NAME, ZASS_VERSION, 0);
130     if (!ireq)
131     {
132         gw_log(GW_LOG_FATAL, "ZASS_TYPE", "failed to create initrequest");
133         return 0;
134     }
135     zutil_GetBEREncodedBuffer(ireq, (unsigned char*)p->buf, &len,
136         p->maxrecordsize);
137     if (len <= 0)
138     {
139         gw_log(GW_LOG_FATAL, ZASS_TYPE, "Failed to encode initrequest");
140         return 0;
141     }
142     InitRequest_Destroy(ireq);
143     if (netbox_SendBuffer(p->ass, p->buf, len) != len)
144     {
145         gw_log(GW_LOG_FATAL, ZASS_TYPE, "Failed to send initrequest");
146         return 0;
147     }
148     gw_log(ZASS_DEBUG, ZASS_TYPE, "Sent initrequest.");
149     if ((len = zutil_GetBERFromNet(p->ass, (unsigned char*)p->buf,
150         p->maxrecordsize)) <= 0)
151     {
152         gw_log(GW_LOG_FATAL, ZASS_TYPE, "Failed to receive initresponse");
153         return 0;
154     }
155     ires = (PINITRESPONSE) zutil_CreateFromData((unsigned char*)p->buf, len);
156     if (InitResponse_GetTag(ires) != INITRESPONSE_TAG)
157     {
158         gw_log(GW_LOG_FATAL, ZASS_TYPE, "Expected initresponse from target");
159         return 0;
160     }
161     gw_log(ZASS_DEBUG, ZASS_TYPE, "Got initresponse");
162     if (!InitResponse_GetResult(ires))
163     {
164         gw_log(GW_LOG_FATAL, ZASS_TYPE, "Access to target denied.");
165         return 0;
166     }
167     gw_log(ZASS_DEBUG, ZASS_TYPE, "Connected OK");
168     p->preferredmessagesize = InitResponse_GetPreferredMessageSize(ires);
169     p->maxrecordsize = InitResponse_GetExceptionalRecordSize(ires);
170     InitResponse_Destroy(ires);
171     return p;
172 }
173
174 const struct zass_searchent *zass_search(ZASS a, struct ccl_rpn_node *query,
175     char *resname, char *databases)
176 {
177     static struct zass_searchent r;
178     char kwaqs[512], *p;
179     DATA_DIR *pdu, *record;
180     int len;
181
182     p = kwaqs;
183     if (rpn2kwaqs(query, &p) < 0)
184     {
185         gw_log(GW_LOG_FATAL, ZASS_TYPE, "Failed to encode query");
186         return 0;
187     }
188     gw_log(ZASS_DEBUG, ZASS_TYPE, "Query: KWAQS: '%s'", kwaqs);
189     pdu = SearchRequest_CreateInitAllASCII(0, 0, 2, 0, 1, resname, databases,
190         0, 0, 0, kwaqs, BIB1_OID);
191     if (!pdu)
192     {
193         gw_log(GW_LOG_FATAL, "ZASS_TYPE", "failed to create searchrequest");
194         return 0;
195     }
196     zutil_GetBEREncodedBuffer(pdu, (unsigned char*)a->buf, &len,
197         a->maxrecordsize);
198     if (len <= 0)
199     {
200         gw_log(GW_LOG_FATAL, ZASS_TYPE, "Failed to encode initrequest");
201         return 0;
202     }
203     SearchRequest_Destroy(pdu);
204     if (netbox_SendBuffer(a->ass, a->buf, len) != len)
205     {
206         gw_log(GW_LOG_FATAL, ZASS_TYPE, "Failed to send initrequest");
207         return 0;
208     }
209     gw_log(ZASS_DEBUG, ZASS_TYPE, "Sent searchrequest.");
210     if ((len = zutil_GetBERFromNet(a->ass, (unsigned char*)a->buf,
211         a->maxrecordsize)) <= 0)
212     {
213         gw_log(GW_LOG_FATAL, ZASS_TYPE, "Failed to receive searchresponse");
214         return 0;
215     }
216     pdu = zutil_CreateFromData((unsigned char*)a->buf, len);
217     if (zutil_GetTag(pdu) != SEARCHRESPONSE_TAG)
218     {
219         gw_log(GW_LOG_FATAL, ZASS_TYPE, "Expected serchresponse from target");
220         return 0;
221     }
222     gw_log(ZASS_DEBUG, ZASS_TYPE, "Got searchresponse");
223     r.status = SearchResponse_GetSearchStatus(pdu);
224     r.num = SearchResponse_GetResultCount(pdu);
225     r.status = SearchResponse_GetResultSetStatus(pdu);
226     r.errcode = -1;
227     *r.errstring = '\0';
228     if ((record = SearchResponse_GetRecords(pdu)))
229     {
230         if (zutil_GetTag(record) == NONSURROGATEDIAGNOSTIC_TAG)
231         {
232             DATA_DIR *ad;
233
234             r.errcode = zutil_GetTaggedInt(record, ASN1_INTEGER);
235             if ((ad = zutil_GetTaggedObject(record, ASN1_VISIBLESTRING)))
236             {
237                 char *s;
238
239                 if ((s = OctetString_GetASCIIString(ad)))
240                 {
241                     strcpy(r.errstring, s);
242                     FREE(s);
243                 }
244             }
245         }
246         else
247             gw_log(GW_LOG_WARN, ZASS_TYPE, "Got real record in SRCHRESP");
248     }
249     SearchResponse_Destroy(pdu);
250
251     return &r;
252 }
253
254 /*
255  * Note that 1== first record.
256  */
257 const struct zass_presentent *zass_present(ZASS a, char *resname, int start,
258     int num)
259 {
260     return 0;
261 }