Fixed two bugs in OID codec - ber_oidc. Throw error when encoding or
[yaz-moved-to-github.git] / src / ber_oid.c
1 /*
2  * Copyright (c) 1995-2004, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Id: ber_oid.c,v 1.2 2004-02-11 23:49:28 adam Exp $
6  */
7 #if HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10
11 #include "odr-priv.h"
12
13 int ber_oidc(ODR o, Odr_oid *p)
14 {
15     int len, lenp, end;
16     int pos, n, res, id;
17     unsigned char octs[8];
18
19     switch (o->direction)
20     {
21     case ODR_DECODE:
22         if ((res = ber_declen(o->bp, &len, odr_max(o))) < 1)
23         {
24             odr_seterror(o, OPROTO, 18);
25             return 0;
26         }
27         if (len <= 0)
28         {
29             odr_seterror(o, OPROTO, 19);
30             return 0;
31         }
32         o->bp += res;
33         if (len > odr_max(o))
34         {
35             odr_seterror(o, OPROTO, 20);
36             return 0;
37         }
38         pos = 0;
39         while (len)
40         {
41             int id = 0;
42             do
43             {
44                 if (!len)
45                 {
46                     odr_seterror(o, OPROTO, 21);
47                     return 0;
48                 }
49                 id <<= 7;
50                 id |= *o->bp & 0X7F;
51                 len--;
52             }
53             while (*(o->bp++) & 0X80);
54             if (pos > 0)
55                 p[pos++] = id;
56             else
57             {
58                 p[0] = id / 40;
59                 if (p[0] > 2)
60                     p[0] = 2;
61                 p[1] = id - p[0] * 40;
62                 pos = 2;
63             }
64         }
65         p[pos] = -1;
66         return 1;
67     case ODR_ENCODE:
68         /* we'll allow ourselves the quiet luxury of only doing encodings
69            shorter than 127 */
70         lenp = odr_tell(o);
71         if (odr_putc(o, 0) < 0)   /* dummy */
72             return 0;
73         if (p[0] < 0 || p[1] <= 0)
74         {
75             odr_seterror(o, ODATA, 23);
76             return 0;
77         }
78         for (pos = 1; p[pos] >= 0; pos++)
79         {
80             n = 0;
81             if (pos == 1)
82                 id = p[0]*40 + p[1];
83             else 
84                 id = p[pos];
85             do
86             {
87                 octs[n++] = id & 0X7F;
88                 id >>= 7;
89             }
90             while (id);
91             while (n--)
92             {
93                 unsigned char p;
94
95                 p = octs[n] | ((n > 0) << 7);
96                 if (odr_putc(o, p) < 0)
97                     return 0;
98             }
99         }
100         end = odr_tell(o);
101         odr_seek(o, ODR_S_SET, lenp);
102         if (ber_enclen(o, (end - lenp) - 1, 1, 1) != 1)
103         {
104             odr_seterror(o, OOTHER, 52);
105             return 0;
106         }
107         odr_seek(o, ODR_S_END, 0);
108         return 1;
109     default: 
110         odr_seterror(o, OOTHER, 22);
111         return 0;
112     }
113 }