1 | /*
|
---|
2 | * Copyright (c) 1995-2000, Index Data
|
---|
3 | * See the file LICENSE for details.
|
---|
4 | * Sebastian Hammer, Adam Dickmeiss
|
---|
5 | *
|
---|
6 | * $Log$
|
---|
7 | * Revision 1.1 2000/08/03 03:11:16 johnmcp
|
---|
8 | * Added the YAZ toolkit source to the packages directory (for z39.50 stuff)
|
---|
9 | *
|
---|
10 | * Revision 1.22 2000/02/29 13:44:55 adam
|
---|
11 | * Check for config.h (currently not generated).
|
---|
12 | *
|
---|
13 | * Revision 1.21 2000/01/31 13:15:21 adam
|
---|
14 | * Removed uses of assert(3). Cleanup of ODR. CCL parser update so
|
---|
15 | * that some characters are not surrounded by spaces in resulting term.
|
---|
16 | * ILL-code updates.
|
---|
17 | *
|
---|
18 | * Revision 1.20 1999/11/30 13:47:11 adam
|
---|
19 | * Improved installation. Moved header files to include/yaz.
|
---|
20 | *
|
---|
21 | * Revision 1.19 1999/01/08 11:23:25 adam
|
---|
22 | * Added const modifier to some of the BER/ODR encoding routines.
|
---|
23 | *
|
---|
24 | * Revision 1.18 1998/02/11 11:53:34 adam
|
---|
25 | * Changed code so that it compiles as C++.
|
---|
26 | *
|
---|
27 | * Revision 1.17 1997/09/30 09:33:10 adam
|
---|
28 | * Minor changes - removed indentation of ifdef.
|
---|
29 | *
|
---|
30 | * Revision 1.16 1997/09/17 12:10:33 adam
|
---|
31 | * YAZ version 1.4.
|
---|
32 | *
|
---|
33 | * Revision 1.15 1997/09/01 08:51:06 adam
|
---|
34 | * New windows NT/95 port using MSV5.0. Had to avoid a few static
|
---|
35 | * variables used in function ber_tag. These are now part of the
|
---|
36 | * ODR structure.
|
---|
37 | *
|
---|
38 | * Revision 1.14 1997/05/14 06:53:56 adam
|
---|
39 | * C++ support.
|
---|
40 | *
|
---|
41 | * Revision 1.13 1995/09/29 17:12:21 quinn
|
---|
42 | * Smallish
|
---|
43 | *
|
---|
44 | * Revision 1.12 1995/09/27 15:02:57 quinn
|
---|
45 | * Modified function heads & prototypes.
|
---|
46 | *
|
---|
47 | * Revision 1.11 1995/05/16 08:50:48 quinn
|
---|
48 | * License, documentation, and memory fixes
|
---|
49 | *
|
---|
50 | * Revision 1.10 1995/04/18 08:15:18 quinn
|
---|
51 | * Added dynamic memory allocation on encoding (whew). Code is now somewhat
|
---|
52 | * neater. We'll make the same change for decoding one day.
|
---|
53 | *
|
---|
54 | * Revision 1.9 1995/03/15 08:37:18 quinn
|
---|
55 | * Fixed protocol bugs.
|
---|
56 | *
|
---|
57 | * Revision 1.8 1995/03/10 11:44:40 quinn
|
---|
58 | * Fixed serious stack-bug in odr_cons_begin
|
---|
59 | *
|
---|
60 | * Revision 1.7 1995/03/08 12:12:13 quinn
|
---|
61 | * Added better error checking.
|
---|
62 | *
|
---|
63 | * Revision 1.6 1995/02/14 11:54:33 quinn
|
---|
64 | * Adjustments.
|
---|
65 | *
|
---|
66 | * Revision 1.5 1995/02/10 18:57:24 quinn
|
---|
67 | * More in the way of error-checking.
|
---|
68 | *
|
---|
69 | * Revision 1.4 1995/02/10 15:55:28 quinn
|
---|
70 | * Bug fixes, mostly.
|
---|
71 | *
|
---|
72 | * Revision 1.3 1995/02/09 15:51:46 quinn
|
---|
73 | * Works better now.
|
---|
74 | *
|
---|
75 | * Revision 1.2 1995/02/07 17:52:59 quinn
|
---|
76 | * A damn mess, but now things work, I think.
|
---|
77 | *
|
---|
78 | * Revision 1.1 1995/02/02 16:21:53 quinn
|
---|
79 | * First kick.
|
---|
80 | *
|
---|
81 | */
|
---|
82 | #if HAVE_CONFIG_H
|
---|
83 | #include <config.h>
|
---|
84 | #endif
|
---|
85 |
|
---|
86 | #include <stdio.h>
|
---|
87 | #include <yaz/odr.h>
|
---|
88 |
|
---|
89 | /* ber_tag
|
---|
90 | * On encoding:
|
---|
91 | * if p: write tag. return 1 (success) or -1 (error).
|
---|
92 | * if !p: return 0.
|
---|
93 | * On decoding:
|
---|
94 | * if tag && zclass match up, advance pointer and return 1. set cons.
|
---|
95 | * else leave pointer unchanged. Return 0.
|
---|
96 | *
|
---|
97 | * Should perhaps be odr_tag?
|
---|
98 | */
|
---|
99 | int ber_tag(ODR o, void *p, int zclass, int tag, int *constructed, int opt)
|
---|
100 | {
|
---|
101 | Odr_ber_tag *odr_ber_tag = &o->odr_ber_tag;
|
---|
102 | int rd;
|
---|
103 | char **pp = (char **)p;
|
---|
104 |
|
---|
105 | if (o->direction == ODR_DECODE)
|
---|
106 | *pp = 0;
|
---|
107 | o->t_class = -1;
|
---|
108 | if (o->stackp < 0)
|
---|
109 | {
|
---|
110 | odr_seek(o, ODR_S_SET, 0);
|
---|
111 | o->top = 0;
|
---|
112 | o->bp = o->buf;
|
---|
113 | odr_ber_tag->lclass = -1;
|
---|
114 | }
|
---|
115 | switch (o->direction)
|
---|
116 | {
|
---|
117 | case ODR_ENCODE:
|
---|
118 | if (!*pp)
|
---|
119 | {
|
---|
120 | if (!opt)
|
---|
121 | o->error = OREQUIRED;
|
---|
122 | return 0;
|
---|
123 | }
|
---|
124 | if ((rd = ber_enctag(o, zclass, tag, *constructed)) < 0)
|
---|
125 | return -1;
|
---|
126 | #ifdef ODR_DEBUG
|
---|
127 | fprintf(stderr, "\n[class=%d,tag=%d,cons=%d,stackp=%d]", zclass, tag,
|
---|
128 | *constructed, o->stackp);
|
---|
129 | #endif
|
---|
130 | return 1;
|
---|
131 |
|
---|
132 | case ODR_DECODE:
|
---|
133 | if (o->stackp > -1 && !odr_constructed_more(o))
|
---|
134 | {
|
---|
135 | if (!opt)
|
---|
136 | o->error = OREQUIRED;
|
---|
137 | return 0;
|
---|
138 | }
|
---|
139 | if (odr_ber_tag->lclass < 0)
|
---|
140 | {
|
---|
141 | if ((odr_ber_tag->br = ber_dectag(o->bp, &odr_ber_tag->lclass,
|
---|
142 | &odr_ber_tag->ltag, &odr_ber_tag->lcons)) <= 0)
|
---|
143 | {
|
---|
144 | o->error = OPROTO;
|
---|
145 | return 0;
|
---|
146 | }
|
---|
147 | #ifdef ODR_DEBUG
|
---|
148 | fprintf(stderr,
|
---|
149 | "\n[class=%d,tag=%d,cons=%d,stackp=%d]",
|
---|
150 | odr_ber_tag->lclass, odr_ber_tag->ltag,
|
---|
151 | odr_ber_tag->lcons, o->stackp);
|
---|
152 | #endif
|
---|
153 | }
|
---|
154 | if (zclass == odr_ber_tag->lclass && tag == odr_ber_tag->ltag)
|
---|
155 | {
|
---|
156 | o->bp += odr_ber_tag->br;
|
---|
157 | *constructed = odr_ber_tag->lcons;
|
---|
158 | odr_ber_tag->lclass = -1;
|
---|
159 | return 1;
|
---|
160 | }
|
---|
161 | else
|
---|
162 | {
|
---|
163 | if (!opt)
|
---|
164 | o->error = OREQUIRED;
|
---|
165 | return 0;
|
---|
166 | }
|
---|
167 | case ODR_PRINT:
|
---|
168 | if (!*pp && !opt)
|
---|
169 | o->error = OREQUIRED;
|
---|
170 | return *pp != 0;
|
---|
171 | default:
|
---|
172 | o->error = OOTHER;
|
---|
173 | return 0;
|
---|
174 | }
|
---|
175 | }
|
---|
176 |
|
---|
177 | /* ber_enctag
|
---|
178 | * BER-encode a zclass/tag/constructed package (identifier octets). Return
|
---|
179 | * number of bytes encoded, or -1 if out of bounds.
|
---|
180 | */
|
---|
181 | int ber_enctag(ODR o, int zclass, int tag, int constructed)
|
---|
182 | {
|
---|
183 | int cons = (constructed ? 1 : 0), n = 0;
|
---|
184 | unsigned char octs[sizeof(int)], b;
|
---|
185 |
|
---|
186 | b = (zclass << 6) & 0XC0;
|
---|
187 | b |= (cons << 5) & 0X20;
|
---|
188 | if (tag <= 30)
|
---|
189 | {
|
---|
190 | b |= tag & 0X1F;
|
---|
191 | if (odr_putc(o, b) < 0)
|
---|
192 | return -1;
|
---|
193 | return 1;
|
---|
194 | }
|
---|
195 | else
|
---|
196 | {
|
---|
197 | b |= 0X1F;
|
---|
198 | if (odr_putc(o, b) < 0)
|
---|
199 | return -1;
|
---|
200 | do
|
---|
201 | {
|
---|
202 | octs[n++] = tag & 0X7F;
|
---|
203 | tag >>= 7;
|
---|
204 | }
|
---|
205 | while (tag);
|
---|
206 | while (n--)
|
---|
207 | {
|
---|
208 | unsigned char oo;
|
---|
209 |
|
---|
210 | oo = octs[n] | ((n > 0) << 7);
|
---|
211 | if (odr_putc(o, oo) < 0)
|
---|
212 | return -1;
|
---|
213 | }
|
---|
214 | return 0;
|
---|
215 | }
|
---|
216 | }
|
---|
217 |
|
---|
218 | /* ber_dectag
|
---|
219 | * Decode BER identifier octets. Return number of bytes read or -1 for error.
|
---|
220 | */
|
---|
221 | int ber_dectag(const unsigned char *buf, int *zclass, int *tag, int *constructed)
|
---|
222 | {
|
---|
223 | const unsigned char *b = buf;
|
---|
224 |
|
---|
225 | *zclass = *b >> 6;
|
---|
226 | *constructed = (*b >> 5) & 0X01;
|
---|
227 | if ((*tag = *b & 0x1F) <= 30)
|
---|
228 | return 1;
|
---|
229 | b++;
|
---|
230 | *tag = 0;
|
---|
231 | do
|
---|
232 | {
|
---|
233 | *tag <<= 7;
|
---|
234 | *tag |= *b & 0X7F;
|
---|
235 | if (b - buf >= 5) /* Precaution */
|
---|
236 | return -1;
|
---|
237 | }
|
---|
238 | while (*(b++) & 0X80);
|
---|
239 | return b - buf;
|
---|
240 | }
|
---|