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