Fixed bug.
[yaz-moved-to-github.git] / asn / proto.c
1 /*
2  * Copyright (C) 1994, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: proto.c,v $
7  * Revision 1.19  1995-04-11 11:58:35  quinn
8  * Fixed bug.
9  *
10  * Revision 1.18  1995/04/11  11:52:02  quinn
11  * Fixed possible buf in proto.c
12  *
13  * Revision 1.17  1995/04/10  10:22:22  quinn
14  * Added SCAN.
15  *
16  * Revision 1.16  1995/03/30  10:26:43  quinn
17  * Added Term structure
18  *
19  * Revision 1.15  1995/03/30  09:08:39  quinn
20  * Added Resource control protocol
21  *
22  * Revision 1.14  1995/03/29  08:06:13  quinn
23  * Added a few v3 elements
24  *
25  * Revision 1.13  1995/03/20  11:26:52  quinn
26  * *** empty log message ***
27  *
28  * Revision 1.12  1995/03/20  09:45:09  quinn
29  * Working towards v3
30  *
31  * Revision 1.11  1995/03/17  10:17:25  quinn
32  * Added memory management.
33  *
34  * Revision 1.10  1995/03/15  11:17:40  quinn
35  * Fixed some return-checks from choice.. need better ay to handle those..
36  *
37  * Revision 1.9  1995/03/15  08:37:06  quinn
38  * Fixed protocol bugs.
39  *
40  * Revision 1.8  1995/03/14  16:59:24  quinn
41  * Fixed OPTIONAL flag in attributeelement
42  *
43  * Revision 1.7  1995/03/07  16:29:33  quinn
44  * Added authentication stuff.
45  *
46  * Revision 1.6  1995/03/01  14:46:03  quinn
47  * Fixed protocol bug in 8777query.
48  *
49  * Revision 1.5  1995/02/14  11:54:22  quinn
50  * Fixing include.
51  *
52  * Revision 1.4  1995/02/10  15:54:30  quinn
53  * Small adjustments.
54  *
55  * Revision 1.3  1995/02/09  15:51:39  quinn
56  * Works better now.
57  *
58  * Revision 1.2  1995/02/06  21:26:07  quinn
59  * Repaired this evening's damages..
60  *
61  * Revision 1.1  1995/02/06  16:44:47  quinn
62  * First hack at Z/SR protocol
63  *
64  */
65
66 #include <odr.h>
67
68 #include <proto.h>
69
70 /* ---------------------- GLOBAL DEFS ------------------- */
71
72 int z_ReferenceId(ODR o, Z_ReferenceId **p, int opt)
73 {
74     return odr_implicit(o, odr_octetstring, (Odr_oct**) p, ODR_CONTEXT, 2, opt);
75 }
76
77 int z_DatabaseName(ODR o, Z_DatabaseName **p, int opt)
78 {
79     return odr_implicit(o, odr_visiblestring, (char **) p, ODR_CONTEXT, 105,
80         opt);
81 }
82
83 int z_ResultSetId(ODR o, char **p, int opt)
84 {
85     return odr_implicit(o, odr_visiblestring, (char **) p, ODR_CONTEXT, 31,
86         opt);
87 }
88
89 int z_UserInformationField(ODR o, Z_UserInformationField **p, int opt)
90 {
91     return odr_explicit(o, odr_external, (Odr_external **)p, ODR_CONTEXT,
92         11, opt);
93 }
94
95 /* ---------------------- INITIALIZE SERVICE ------------------- */
96
97 int z_NSRAuthentication(ODR o, Z_NSRAuthentication **p, int opt)
98 {
99     if (!odr_sequence_begin(o, p, sizeof(**p)))
100         return opt;
101     return
102         odr_visiblestring(o, &(*p)->user, 0) &&
103         odr_visiblestring(o, &(*p)->password, 0) &&
104         odr_visiblestring(o, &(*p)->account, 0) &&
105         odr_sequence_end(o);
106 }
107
108 int z_IdPass(ODR o, Z_IdPass **p, int opt)
109 {
110     if (!odr_sequence_begin(o, p, sizeof(**p)))
111         return opt;
112     return
113         odr_implicit(o, odr_visiblestring, &(*p)->groupId, ODR_CONTEXT, 0, 0) &&
114         odr_implicit(o, odr_visiblestring, &(*p)->userId, ODR_CONTEXT, 1, 0) &&
115         odr_implicit(o, odr_visiblestring, &(*p)->password, ODR_CONTEXT, 2,
116             0) &&
117         odr_sequence_end(o);
118 }
119
120 int z_StrAuthentication(ODR o, char **p, int opt)
121 {
122     return odr_visiblestring(o, p, opt);
123 }
124
125 int z_IdAuthentication(ODR o, Z_IdAuthentication **p, int opt)
126 {
127     static Odr_arm arm[] =
128     {
129         {-1, -1, -1, Z_IdAuthentication_open, z_StrAuthentication},
130         {-1, -1, -1, Z_IdAuthentication_idPass, z_NSRAuthentication},
131         {-1, -1, -1, Z_IdAuthentication_anonymous, odr_null},
132         {-1, -1, -1, Z_IdAuthentication_other, odr_external},
133         {-1, -1, -1, -1, 0}
134     };
135
136     if (o->direction == ODR_DECODE)
137         *p = odr_malloc(o, sizeof(**p));
138
139     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
140         return 1;
141     *p = 0;
142     return opt && !o->error;
143 }
144
145 int z_InitRequest(ODR o, Z_InitRequest **p, int opt)
146 {
147     Z_InitRequest *pp;
148
149     if (!odr_sequence_begin(o, p, sizeof(**p)))
150         return opt;
151     pp = *p;
152     return
153         z_ReferenceId(o, &pp->referenceId, 1) &&
154         odr_implicit(o, odr_bitstring, &pp->protocolVersion, ODR_CONTEXT, 
155             3, 0) &&
156         odr_implicit(o, odr_bitstring, &pp->options, ODR_CONTEXT, 4, 0) &&
157         odr_implicit(o, odr_integer, &pp->preferredMessageSize, ODR_CONTEXT,
158             5, 0) &&
159         odr_implicit(o, odr_integer, &pp->maximumRecordSize, ODR_CONTEXT,
160             6, 0) &&
161         odr_explicit(o, z_IdAuthentication, &pp->idAuthentication, ODR_CONTEXT,
162             7, 1) &&
163         odr_implicit(o, odr_visiblestring, &pp->implementationId, ODR_CONTEXT,
164             110, 1) &&
165         odr_implicit(o, odr_visiblestring, &pp->implementationName, ODR_CONTEXT,
166             111, 1) &&
167         odr_implicit(o, odr_visiblestring, &pp->implementationVersion,
168             ODR_CONTEXT, 112, 1) &&
169         z_UserInformationField(o, &pp->userInformationField, 1) &&
170         odr_sequence_end(o);
171 }
172
173 int z_InitResponse(ODR o, Z_InitResponse **p, int opt)
174 {
175     Z_InitResponse *pp;
176
177     if (!odr_sequence_begin(o, p, sizeof(**p)))
178         return opt;
179     pp = *p;
180     return
181         z_ReferenceId(o, &pp->referenceId, 1) &&
182         odr_implicit(o, odr_bitstring, &pp->protocolVersion, ODR_CONTEXT, 
183             3, 0) &&
184         odr_implicit(o, odr_bitstring, &pp->options, ODR_CONTEXT, 4, 0) &&
185         odr_implicit(o, odr_integer, &pp->preferredMessageSize, ODR_CONTEXT,
186             5, 0) &&
187         odr_implicit(o, odr_integer, &pp->maximumRecordSize, ODR_CONTEXT,
188             6, 0) &&
189         odr_implicit(o, odr_bool, &pp->result, ODR_CONTEXT, 12, 0) &&
190         odr_implicit(o, odr_visiblestring, &pp->implementationId, ODR_CONTEXT,
191             110, 1) &&
192         odr_implicit(o, odr_visiblestring, &pp->implementationName, ODR_CONTEXT,
193             111, 1) &&
194         odr_implicit(o, odr_visiblestring, &pp->implementationVersion,
195             ODR_CONTEXT, 112, 1) &&
196         z_UserInformationField(o, &pp->userInformationField, 1) &&
197         odr_sequence_end(o);
198 }
199
200 /* ------------------ RESOURCE CONTROL ----------------*/
201
202 int z_TriggerResourceControlRequest(ODR o, Z_TriggerResourceControlRequest **p,
203                                     int opt)
204 {
205     if (!odr_sequence_begin(o, p, sizeof(**p)))
206         return opt;
207     return
208         z_ReferenceId(o, &(*p)->referenceId, 1) &&
209         odr_implicit(o, odr_integer, &(*p)->requestedAction, ODR_CONTEXT,
210             46, 0) &&
211         odr_implicit(o, odr_oid, &(*p)->prefResourceReportFormat,
212             ODR_CONTEXT, 47, 1) &&
213         odr_implicit(o, odr_bool, &(*p)->resultSetWanted, ODR_CONTEXT,
214             48, 1) &&
215         odr_sequence_end(o);
216 }
217
218 int z_ResourceControlRequest(ODR o, Z_ResourceControlRequest **p, int opt)
219 {
220     if (!odr_sequence_begin(o, p, sizeof(**p)))
221         return opt;
222     return
223         z_ReferenceId(o, &(*p)->referenceId, 1) &&
224         odr_implicit(o, odr_bool, &(*p)->suspendedFlag, ODR_CONTEXT, 39, 1)&&
225         odr_explicit(o, odr_external, &(*p)->resourceReport, ODR_CONTEXT,
226             40, 1) &&
227         odr_implicit(o, odr_integer, &(*p)->partialResultsAvailable,
228             ODR_CONTEXT, 41, 1) &&
229         odr_implicit(o, odr_bool, &(*p)->responseRequired, ODR_CONTEXT,
230             42, 0) &&
231         odr_implicit(o, odr_bool, &(*p)->triggeredRequestFlag,
232             ODR_CONTEXT, 43, 1) &&
233         odr_sequence_end(o);
234 }
235
236 int z_ResourceControlResponse(ODR o, Z_ResourceControlResponse **p, int opt)
237 {
238     if (!odr_sequence_begin(o, p, sizeof(**p)))
239         return opt;
240     return
241         z_ReferenceId(o, &(*p)->referenceId, 1) &&
242         odr_implicit(o, odr_bool, &(*p)->continueFlag, ODR_CONTEXT, 44, 0) &&
243         odr_implicit(o, odr_bool, &(*p)->resultSetWanted, ODR_CONTEXT,
244             45, 1) &&
245         odr_sequence_end(o);
246 }
247
248 /* ------------------------ SEARCH SERVICE ----------------------- */
249
250 int z_ElementSetName(ODR o, char **p, int opt)
251 {
252     return odr_implicit(o, odr_visiblestring, (char**) p, ODR_CONTEXT, 103,
253         opt);
254 }
255
256 int z_PreferredRecordSyntax(ODR o, Z_PreferredRecordSyntax **p, int opt)
257 {
258     return odr_implicit(o, odr_oid, (Odr_oid**) p, ODR_CONTEXT, 104, opt);
259 }
260
261 int z_DatabaseSpecificUnit(ODR o, Z_DatabaseSpecificUnit **p, int opt)
262 {
263     if (!odr_sequence_begin(o, p, sizeof(**p)))
264         return opt;
265     return
266         z_DatabaseName(o, &(*p)->databaseName, 0) &&
267         z_ElementSetName(o, &(*p)->elementSetName, 0) &&
268         odr_sequence_end(o);
269 }
270
271 int z_DatabaseSpecific(ODR o, Z_DatabaseSpecific **p, int opt)
272 {
273     if (o->direction == ODR_DECODE)
274         *p = odr_malloc(o, sizeof(**p));
275     else if (!*p)
276         return opt;
277
278     odr_implicit_settag(o, ODR_CONTEXT, 1);
279     if (odr_sequence_of(o, z_DatabaseSpecificUnit, &(*p)->elements,
280         &(*p)->num_elements))
281         return 1;
282     *p = 0;
283     return 0;
284 }
285
286 int z_ElementSetNames(ODR o, Z_ElementSetNames **p, int opt)
287 {
288     static Odr_arm arm[] =
289     {
290         {ODR_IMPLICIT, ODR_CONTEXT, 0, Z_ElementSetNames_generic,
291             z_ElementSetName},
292         {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_ElementSetNames_databaseSpecific,
293             z_DatabaseSpecific},
294         {-1, -1, -1, -1, 0}
295     };
296
297     if (!odr_constructed_begin(o, p, ODR_CONTEXT, 19))
298         return opt;
299
300     if (o->direction == ODR_DECODE)
301         *p = odr_malloc(o, sizeof(**p));
302
303     if (odr_choice(o, arm, &(*p)->u, &(*p)->which) &&
304         odr_constructed_end(o))
305         return 1;
306     *p = 0;
307     return 0;
308 }
309
310 /* ----------------------- RPN QUERY -----------------------*/
311
312 int z_AttributeElement(ODR o, Z_AttributeElement **p, int opt)
313 {
314     if (!odr_sequence_begin(o, p, sizeof(**p)))
315         return opt;
316     return
317         odr_implicit(o, odr_integer, &(*p)->attributeType, ODR_CONTEXT,
318             120, 0) &&
319         odr_implicit(o, odr_integer, &(*p)->attributeValue, ODR_CONTEXT,
320             121, 0) &&
321         odr_sequence_end(o);
322 }
323
324 #ifdef Z_V3
325
326 int z_Term(ODR o, Z_Term **p, int opt)
327 {
328     static Odr_arm arm[] =
329     {
330         {ODR_IMPLICIT, ODR_CONTEXT, 45, Z_Term_general, odr_octetstring},
331         {ODR_IMPLICIT, ODR_CONTEXT, 215, Z_Term_numeric, odr_integer},
332         {ODR_IMPLICIT, ODR_CONTEXT, 216, Z_Term_characterString,
333             odr_visiblestring},
334         {ODR_IMPLICIT, ODR_CONTEXT, 217, Z_Term_oid, odr_oid},
335         {ODR_IMPLICIT, ODR_CONTEXT, 218, Z_Term_dateTime, odr_cstring},
336         {ODR_IMPLICIT, ODR_CONTEXT, 219, Z_Term_external, odr_external},
337         /* add intUnit here */
338         {ODR_IMPLICIT, ODR_CONTEXT, 221, Z_Term_null, odr_null},
339         {-1, -1, -1, -1, 0}
340     };
341
342     if (o->direction ==ODR_DECODE)
343         *p = odr_malloc(o, sizeof(**p));
344     else if (!*p)
345         return opt;
346     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
347         return 1;
348     *p = 0;
349     return opt && !o->error;
350 }
351
352 #endif
353
354 int z_AttributesPlusTerm(ODR o, Z_AttributesPlusTerm **p, int opt)
355 {
356     if (!(odr_implicit_settag(o, ODR_CONTEXT, 102) &&
357         odr_sequence_begin(o, p, sizeof(**p))))
358         return opt;
359     return
360         odr_implicit_settag(o, ODR_CONTEXT, 44) &&
361         odr_sequence_of(o, z_AttributeElement, &(*p)->attributeList,
362             &(*p)->num_attributes) &&
363 #ifdef Z_V3
364         z_Term(o, &(*p)->term, 0) &&
365 #else
366         odr_implicit(o, odr_octetstring, &(*p)->term, ODR_CONTEXT, 45, 0) &&
367 #endif
368         odr_sequence_end(o);
369 }
370
371 int z_Operator(ODR o, Z_Operator **p, int opt)
372 {
373     static Odr_arm arm[] =
374     {
375         {ODR_IMPLICIT, ODR_CONTEXT, 0, Z_Operator_and, odr_null},
376         {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_Operator_or, odr_null},
377         {ODR_IMPLICIT, ODR_CONTEXT, 2, Z_Operator_and_not, odr_null},
378         {-1, -1, -1, -1, 0}
379     };
380     int dummy = 999;
381
382     if (!*p && o->direction != ODR_DECODE)
383         return opt;
384     if (!odr_constructed_begin(o, p, ODR_CONTEXT, 46))
385         return opt;
386     if (o->direction == ODR_DECODE)
387         *p = odr_malloc(o, sizeof(**p));
388     else
389         (*p)->u.and = &dummy;
390
391     if (odr_choice(o, arm, &(*p)->u, &(*p)->which) &&
392         odr_constructed_end(o))
393         return 1;
394     *p = 0;
395     return opt && !o->error;
396 }
397
398 int z_Operand(ODR o, Z_Operand **p, int opt)
399 {
400     static Odr_arm arm[] =
401     {
402         {-1, -1, -1, Z_Operand_APT, z_AttributesPlusTerm},
403         {-1, -1, -1, Z_Operand_resultSetId, z_ResultSetId},
404         {-1, -1, -1, -1, 0}
405     };
406
407     if (o->direction ==ODR_DECODE)
408         *p = odr_malloc(o, sizeof(**p));
409     else if (!*p)
410         return opt;
411     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
412         return 1;
413     *p = 0;
414     return opt && !o->error;
415 }
416
417 int z_RPNStructure(ODR o, Z_RPNStructure **p, int opt);
418
419 int z_Complex(ODR o, Z_Complex **p, int opt)
420 {
421     if (!odr_sequence_begin(o, p, sizeof(**p)))
422         return opt;
423     return
424         z_RPNStructure(o, &(*p)->s1, 0) &&
425         z_RPNStructure(o, &(*p)->s2, 0) &&
426         z_Operator(o, &(*p)->operator, 0) &&
427         odr_sequence_end(o);
428 }
429
430 int z_RPNStructure(ODR o, Z_RPNStructure **p, int opt)
431 {
432     static Odr_arm arm[] = 
433     {
434         {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_RPNStructure_simple, z_Operand},
435         {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_RPNStructure_complex, z_Complex},
436         {-1 -1, -1, -1, 0}
437     };
438
439     if (o->direction == ODR_DECODE)
440         *p = odr_malloc(o, sizeof(**p));
441     else if (!*p)
442         return opt;
443     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
444         return 1;
445     *p = 0;
446     return opt && !o->error;
447 }
448
449 int z_RPNQuery(ODR o, Z_RPNQuery **p, int opt)
450 {
451     if (!odr_sequence_begin(o, p, sizeof(**p)))
452         return opt;
453     return
454         odr_oid(o, &(*p)->attributeSetId, 0) &&
455         z_RPNStructure(o, &(*p)->RPNStructure, 0) &&
456         odr_sequence_end(o);
457 }
458
459 /* -----------------------END RPN QUERY ----------------------- */
460
461 int z_Query(ODR o, Z_Query **p, int opt)
462 {
463     static Odr_arm arm[] = 
464     {
465         {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_Query_type_1, z_RPNQuery},
466         {ODR_EXPLICIT, ODR_CONTEXT, 2, Z_Query_type_2, odr_octetstring},
467         {-1, -1, -1, -1, 0}
468     };
469
470     if (o->direction == ODR_DECODE)
471         *p = odr_malloc(o, sizeof(**p));
472     else if (!*p)
473         return opt;
474     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
475         return 1;
476     *p = 0;
477     return opt && !o->error;
478 }
479
480 int z_SearchRequest(ODR o, Z_SearchRequest **p, int opt)
481 {
482     Z_SearchRequest *pp;
483
484     if (!odr_sequence_begin(o, p, sizeof(**p)))
485         return opt;
486     pp = *p;
487     return
488         z_ReferenceId(o, &pp->referenceId, 1) &&
489         odr_implicit(o, odr_integer, &pp->smallSetUpperBound, ODR_CONTEXT,
490             13, 0) &&
491         odr_implicit(o, odr_integer, &pp->largeSetLowerBound, ODR_CONTEXT,
492             14, 0) &&
493         odr_implicit(o, odr_integer, &pp->mediumSetPresentNumber, ODR_CONTEXT,
494             15, 0) &&
495         odr_implicit(o, odr_bool, &pp->replaceIndicator, ODR_CONTEXT, 16, 1) &&
496         odr_implicit(o, odr_visiblestring, &pp->resultSetName, ODR_CONTEXT,
497             17, 9) &&
498         odr_implicit_settag(o, ODR_CONTEXT, 18) &&
499         odr_sequence_of(o, z_DatabaseName, &pp->databaseNames,
500             &pp->num_databaseNames) &&
501         odr_explicit(o, z_ElementSetNames, &pp->smallSetElementSetNames,
502             ODR_CONTEXT, 100, 1) &&
503         odr_explicit(o, z_ElementSetNames, &pp->mediumSetElementSetNames,
504             ODR_CONTEXT, 101, 1) &&
505         z_PreferredRecordSyntax(o, &pp->preferredRecordSyntax, 1) &&
506         odr_explicit(o, z_Query, &pp->query, ODR_CONTEXT, 21, 0) &&
507         odr_sequence_end(o);
508 }
509
510 /* ------------------------ RECORD ------------------------- */
511
512 int z_DatabaseRecord(ODR o, Z_DatabaseRecord **p, int opt)
513 {
514     return odr_external(o, (Odr_external **) p, opt);
515 }
516
517 int z_DiagRec(ODR o, Z_DiagRec **p, int opt)
518 {
519     if (!odr_sequence_begin(o, p, sizeof(**p)))
520         return opt;
521     return
522         odr_oid(o, &(*p)->diagnosticSetId, 1) &&       /* SHOULD NOT BE OPT */
523         odr_integer(o, &(*p)->condition, 0) &&
524         (odr_visiblestring(o, &(*p)->addinfo, 0) ||
525         odr_implicit(o, odr_cstring, &(*p)->addinfo, ODR_CONTEXT, ODR_VISIBLESTRING, 1)) &&
526         odr_sequence_end(o);
527 }
528
529 int z_NamePlusRecord(ODR o, Z_NamePlusRecord **p, int opt)
530 {
531     static Odr_arm arm[] =
532     {
533         {ODR_EXPLICIT, ODR_CONTEXT, 1, Z_NamePlusRecord_databaseRecord,
534             z_DatabaseRecord},
535         {ODR_EXPLICIT, ODR_CONTEXT, 2, Z_NamePlusRecord_surrogateDiagnostic,
536             z_DiagRec},
537         {-1, -1, -1, -1, 0}
538     };
539
540     if (!odr_sequence_begin(o, p, sizeof(**p)))
541         return opt;
542     return
543         odr_implicit(o, z_DatabaseName, &(*p)->databaseName, ODR_CONTEXT,
544             0, 1) &&
545         odr_constructed_begin(o, &(*p)->u, ODR_CONTEXT, 1) &&
546         odr_choice(o, arm, &(*p)->u, &(*p)->which) &&
547         odr_constructed_end(o) &&
548         odr_sequence_end(o);
549 }
550
551 int z_NamePlusRecordList(ODR o, Z_NamePlusRecordList **p, int opt)
552 {
553     if (o->direction == ODR_DECODE)
554         *p = odr_malloc(o, sizeof(**p));
555     if (odr_sequence_of(o, z_NamePlusRecord, &(*p)->records,
556         &(*p)->num_records))
557         return 1;
558     *p = 0;
559     return 0;
560 }
561
562 int z_Records(ODR o, Z_Records **p, int opt)
563 {
564     Odr_arm arm[] = 
565     {
566         {ODR_IMPLICIT, ODR_CONTEXT, 28, Z_Records_DBOSD, z_NamePlusRecordList},
567         {ODR_IMPLICIT, ODR_CONTEXT, 130, Z_Records_NSD, z_DiagRec},
568         {-1, -1, -1, -1, 0}
569     };
570
571     if (o->direction == ODR_DECODE)
572         *p = odr_malloc(o, sizeof(**p));
573     else if (!*p)
574         return opt;
575     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
576         return 1;
577     *p = 0;
578     return opt && !o->error;
579 }
580
581 /* ------------------------ SCAN SERVICE -------------------- */
582
583 int z_AttributeList(ODR o, Z_AttributeList **p, int opt)
584 {
585     if (o->direction == ODR_DECODE)
586         *p = odr_malloc(o, sizeof(**p));
587     else if (!*p)
588         return opt;
589
590     odr_implicit_settag(o, ODR_CONTEXT, 44);
591     if (odr_sequence_of(o, z_AttributeElement, &(*p)->attributes,
592         &(*p)->num_attributes))
593         return 1;
594     *p = 0;
595     return opt && !o->error;
596 }
597
598 /*
599  * This is a temporary hack. We don't know just *what* old version of the
600  * protocol willow uses, so we'll just patiently wait for them to update
601  */
602 static int willow_scan = 0;
603
604 int z_WillowAttributesPlusTerm(ODR o, Z_AttributesPlusTerm **p, int opt)
605 {
606     if (!*p && o->direction != ODR_DECODE)
607         return opt;
608     if (!odr_constructed_begin(o, p, ODR_CONTEXT, 4))
609     {
610         o->t_class = -1;
611         return opt;
612     }
613     if (!odr_constructed_begin(o, p, ODR_CONTEXT, 1))
614         return 0;
615     if (!odr_constructed_begin(o, p, ODR_UNIVERSAL, ODR_SEQUENCE))
616         return 0;
617     if (!odr_implicit_settag(o, ODR_CONTEXT, 44))
618         return 0;
619     if (o->direction == ODR_DECODE)
620         *p = odr_malloc(o, sizeof(**p));
621     if (!odr_sequence_of(o, z_AttributeElement, &(*p)->attributeList,
622         &(*p)->num_attributes))
623         return 0;
624     if (!odr_sequence_end(o) || !odr_sequence_end(o))
625         return 0;
626     if (!z_Term(o, &(*p)->term, 0))
627         return 0;
628     if (!odr_constructed_end(o))
629         return 0;
630     willow_scan = 1;
631     return 1;
632 }
633
634 int z_AlternativeTerm(ODR o, Z_AlternativeTerm **p, int opt)
635 {
636     if (o->direction == ODR_DECODE)
637         *p = odr_malloc(o, sizeof(**p));
638     else if (!*p)
639     {
640         o->t_class = -1;
641         return opt;
642     }
643
644     if (odr_sequence_of(o, z_AttributesPlusTerm, &(*p)->terms,
645         &(*p)->num_terms))
646         return 1;
647     *p = 0;
648     return opt && !o->error;
649 }
650
651 int z_OccurrenceByAttributes(ODR o, Z_OccurrenceByAttributes **p, int opt)
652 {
653     if (!odr_sequence_begin(o, p, sizeof(**p)))
654         return opt;
655     return
656         odr_explicit(o, z_AttributeList, &(*p)->attributes, ODR_CONTEXT, 1, 1)&&
657         odr_explicit(o, odr_integer, &(*p)->global, ODR_CONTEXT, 2, 1) &&
658         odr_sequence_end(o);
659 }
660
661 int z_TermInfo(ODR o, Z_TermInfo **p, int opt)
662 {
663     if (!odr_sequence_begin(o, p, sizeof(**p)))
664         return opt;
665     return
666         (willow_scan ? 
667             odr_implicit(o, z_Term, &(*p)->term, ODR_CONTEXT, 1, 0) :
668             z_Term(o, &(*p)->term, 0)) &&
669         z_AttributeList(o, &(*p)->suggestedAttributes, 1) &&
670         odr_implicit(o, z_AlternativeTerm, &(*p)->alternativeTerm,
671             ODR_CONTEXT, 4, 1) &&
672         odr_implicit(o, odr_integer, &(*p)->globalOccurrences, ODR_CONTEXT,
673             2, 1) &&
674         odr_implicit(o, z_OccurrenceByAttributes, &(*p)->byAttributes,
675             ODR_CONTEXT, 3, 1) &&
676         odr_sequence_end(o);
677 }
678
679 int z_Entry(ODR o, Z_Entry **p, int opt)
680 {
681     static Odr_arm arm[] =
682     {
683         {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_Entry_termInfo, z_TermInfo},
684         {ODR_EXPLICIT, ODR_CONTEXT, 2, Z_Entry_surrogateDiagnostic,
685             z_DiagRec},
686         {-1, -1, -1, -1, 0}
687     };
688
689     if (o->direction == ODR_DECODE)
690         *p = odr_malloc(o, sizeof(**p));
691
692     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
693         return 1;
694     *p = 0;
695     return opt && !o->error;
696 }
697
698 int z_Entries(ODR o, Z_Entries **p, int opt)
699 {
700     if (o->direction == ODR_DECODE)
701         *p = odr_malloc(o, sizeof(**p));
702     else if (!*p)
703         return opt;
704
705     if (odr_sequence_of(o, z_Entry, &(*p)->entries,
706         &(*p)->num_entries))
707         return 1;
708     *p = 0;
709     return 0;
710 }
711
712 int z_DiagRecs(ODR o, Z_DiagRecs **p, int opt)
713 {
714     if (o->direction == ODR_DECODE)
715         *p = odr_malloc(o, sizeof(**p));
716     else if (!*p)
717         return opt;
718
719         if (odr_sequence_of(o, z_DiagRec, &(*p)->diagRecs,
720         &(*p)->num_diagRecs))
721         return 1;
722     *p = 0;
723     return 0;
724 }
725
726 int z_ListEntries(ODR o, Z_ListEntries **p, int opt)
727 {
728     static Odr_arm arm[] =
729     {
730         {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_ListEntries_entries, z_Entries},
731         {ODR_IMPLICIT, ODR_CONTEXT, 2, Z_ListEntries_nonSurrogateDiagnostics,
732             z_DiagRecs},
733         {-1, -1, -1, -1, 0}
734     };
735
736     if (o->direction == ODR_DECODE)
737         *p = odr_malloc(o, sizeof(**p));
738
739     if (odr_choice(o, arm, &(*p)->u, &(*p)->which))
740         return 1;
741     *p = 0;
742     return opt && !o->error;
743 }
744
745 int z_ScanRequest(ODR o, Z_ScanRequest **p, int opt)
746 {
747     if (!odr_sequence_begin(o, p, sizeof(**p)))
748         return opt;
749     willow_scan = 0;
750     return
751         z_ReferenceId(o, &(*p)->referenceId, 1) &&
752         odr_implicit_settag(o, ODR_CONTEXT, 3) &&
753         odr_sequence_of(o, z_DatabaseName, &(*p)->databaseNames,
754             &(*p)->num_databaseNames) &&
755         odr_oid(o, &(*p)->attributeSet, 1) &&
756         (z_AttributesPlusTerm(o, &(*p)->termListAndStartPoint, 1) ?
757             ((*p)->termListAndStartPoint ? 1 : 
758         z_WillowAttributesPlusTerm(o, &(*p)->termListAndStartPoint, 0)) : 0) &&
759         odr_implicit(o, odr_integer, &(*p)->stepSize, ODR_CONTEXT, 5, 1) &&
760         odr_implicit(o, odr_integer, &(*p)->numberOfTermsRequested,
761             ODR_CONTEXT, 6, 0) &&
762         odr_implicit(o, odr_integer, &(*p)->preferredPositionInResponse,
763             ODR_CONTEXT, 7, 1) &&
764         odr_sequence_end(o);
765 }
766
767 int z_ScanResponse(ODR o, Z_ScanResponse **p, int opt)
768 {
769     if (!odr_sequence_begin(o, p, sizeof(**p)))
770         return opt;
771     return
772         z_ReferenceId(o, &(*p)->referenceId, 1) &&
773         odr_implicit(o, odr_integer, &(*p)->stepSize, ODR_CONTEXT, 3, 1) &&
774         odr_implicit(o, odr_integer, &(*p)->scanStatus, ODR_CONTEXT, 4, 0) &&
775         odr_implicit(o, odr_integer, &(*p)->numberOfEntriesReturned,
776             ODR_CONTEXT, 5, 0) &&
777         odr_implicit(o, odr_integer, &(*p)->positionOfTerm, ODR_CONTEXT, 6, 1)&&
778         odr_explicit(o, z_ListEntries, &(*p)->entries, ODR_CONTEXT, 7, 1) &&
779         odr_implicit(o, odr_oid, &(*p)->attributeSet, ODR_CONTEXT, 8, 1) &&
780         odr_sequence_end(o);
781 }
782
783 /* ------------------------ SEARCHRESPONSE ----------------*/
784
785 int z_NumberOfRecordsReturned(ODR o, int **p, int opt)
786 {
787     return odr_implicit(o, odr_integer, p, ODR_CONTEXT, 24, opt);
788 }
789
790 int z_NextResultSetPosition(ODR o, int **p, int opt)
791 {
792     return odr_implicit(o, odr_integer, p, ODR_CONTEXT, 25, opt);
793 }
794
795 int z_PresentStatus(ODR o, int **p, int opt)
796 {
797     return odr_implicit(o, odr_integer, p, ODR_CONTEXT, 27, opt);
798 }
799
800 int z_SearchResponse(ODR o, Z_SearchResponse **p, int opt)
801 {
802     Z_SearchResponse *pp;
803
804     if (!odr_sequence_begin(o, p, sizeof(**p)))
805         return opt;
806     pp = *p;
807     return
808         z_ReferenceId(o, &pp->referenceId, 1) &&
809         odr_implicit(o, odr_integer, &pp->resultCount, ODR_CONTEXT, 23, 0) &&
810         z_NumberOfRecordsReturned(o, &pp->numberOfRecordsReturned, 0) &&
811         z_NextResultSetPosition(o, &pp->nextResultSetPosition, 0) &&
812         odr_implicit(o, odr_bool, &pp->searchStatus, ODR_CONTEXT, 22, 0) &&
813         odr_implicit(o, odr_integer, &pp->resultSetStatus, ODR_CONTEXT, 26, 1) &&
814         z_PresentStatus(o, &pp->presentStatus, 1) &&
815         z_Records(o, &pp->records, 1) &&
816         odr_sequence_end(o);
817 }
818
819 /* --------------------- PRESENT SERVICE ---------------------- */
820
821 int z_PresentRequest(ODR o, Z_PresentRequest **p, int opt)
822 {
823     Z_PresentRequest *pp;
824
825     if (!odr_sequence_begin(o, p, sizeof(**p)))
826         return opt;
827     pp = *p;
828     return
829         z_ReferenceId(o, &pp->referenceId, 1) &&
830         z_ResultSetId(o, &pp->resultSetId, 0) &&
831         odr_implicit(o, odr_integer, &pp->resultSetStartPoint, ODR_CONTEXT,
832             30, 0) &&
833         odr_implicit(o, odr_integer, &pp->numberOfRecordsRequested, ODR_CONTEXT,
834             29, 0) &&
835         z_ElementSetNames(o, &pp->elementSetNames, 1) &&
836         z_PreferredRecordSyntax(o, &pp->preferredRecordSyntax, 1) &&
837         odr_sequence_end(o);
838 }
839
840 int z_PresentResponse(ODR o, Z_PresentResponse **p, int opt)
841 {
842     Z_PresentResponse *pp;
843
844     if (!odr_sequence_begin(o, p, sizeof(**p)))
845         return opt;
846     pp = *p;
847     return
848         z_ReferenceId(o, &pp->referenceId, 1) &&
849         z_NumberOfRecordsReturned(o, &pp->numberOfRecordsReturned, 0) &&
850         z_NextResultSetPosition(o, &pp->nextResultSetPosition, 0) &&
851         z_PresentStatus(o, &pp->presentStatus, 0) &&
852         z_Records(o, &pp->records, 1) &&
853         odr_sequence_end(o);
854 }
855
856 /* ------------------------ APDU ------------------------- */
857
858 int z_APDU(ODR o, Z_APDU **p, int opt)
859 {
860     static Odr_arm arm[] =
861     {
862         {ODR_IMPLICIT, ODR_CONTEXT, 20, Z_APDU_initRequest, z_InitRequest},
863         {ODR_IMPLICIT, ODR_CONTEXT, 21, Z_APDU_initResponse, z_InitResponse},
864         {ODR_IMPLICIT, ODR_CONTEXT, 22, Z_APDU_searchRequest, z_SearchRequest},
865         {ODR_IMPLICIT, ODR_CONTEXT, 23, Z_APDU_searchResponse, z_SearchResponse},
866         {ODR_IMPLICIT, ODR_CONTEXT, 24, Z_APDU_presentRequest, z_PresentRequest},
867         {ODR_IMPLICIT, ODR_CONTEXT, 25, Z_APDU_presentResponse, z_PresentResponse},
868         {ODR_IMPLICIT, ODR_CONTEXT, 35, Z_APDU_scanRequest, z_ScanRequest},
869         {ODR_IMPLICIT, ODR_CONTEXT, 36, Z_APDU_scanResponse, z_ScanResponse},
870
871         {-1, -1, -1, -1, 0}
872     };
873
874     if (o->direction == ODR_DECODE)
875         *p = odr_malloc(o, sizeof(**p));
876     if (!odr_choice(o, arm, &(*p)->u, &(*p)->which))
877     {
878         if (o->direction == ODR_DECODE)
879             *p = 0;
880         return opt && !o->error;
881     }
882     return 1;
883 }