exsltRegisterAll in proper place
[yaz-moved-to-github.git] / src / ber_oid.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5
6 /**
7  * \file ber_oid.c
8  * \brief Implements BER OID encoding and decoding
9  *
10  * This source file implements BER encoding and decoding of
11  * the OID type.
12  */
13 #if HAVE_CONFIG_H
14 #include <config.h>
15 #endif
16
17 #include "odr-priv.h"
18
19 int ber_oidc(ODR o, Odr_oid *p, int max_oid_size)
20 {
21     int len, lenp, end;
22     int pos, n, res, id;
23     unsigned char octs[8];
24
25     switch (o->direction)
26     {
27     case ODR_DECODE:
28         if ((res = ber_declen(o->op->bp, &len, odr_max(o))) < 1)
29         {
30             odr_seterror(o, OPROTO, 18);
31             return 0;
32         }
33         if (len < 0)
34         {
35             odr_seterror(o, OPROTO, 19);
36             return 0;
37         }
38         o->op->bp += res;
39         if (len > odr_max(o))
40         {
41             odr_seterror(o, OPROTO, 20);
42             return 0;
43         }
44         pos = 0;
45         while (len)
46         {
47             int id = 0;
48             do
49             {
50                 if (!len)
51                 {
52                     odr_seterror(o, OPROTO, 21);
53                     return 0;
54                 }
55                 id <<= 7;
56                 id |= *o->op->bp & 0X7F;
57                 len--;
58             }
59             while (*(o->op->bp++) & 0X80);
60
61             if (id < 0)
62             {
63                 odr_seterror(o, ODATA, 23);
64                 return 0;
65             }
66             if (pos > 0)
67                 p[pos++] = id;
68             else
69             {
70                 p[0] = id / 40;
71                 if (p[0] > 2)
72                     p[0] = 2;
73                 p[1] = id - p[0] * 40;
74                 pos = 2;
75             }
76             if (pos >= max_oid_size)
77             {
78                 odr_seterror(o, OPROTO, 55);
79                 return 0;
80             }
81         }
82         if (pos < 2 || p[0] < 0 || p[1] < 0)
83         {
84             odr_seterror(o, ODATA, 23);
85             return 0;
86         }
87         p[pos] = -1;
88         return 1;
89     case ODR_ENCODE:
90         /* we'll allow ourselves the quiet luxury of only doing encodings
91            shorter than 127 */
92         lenp = odr_tell(o);
93         if (odr_putc(o, 0) < 0)   /* dummy */
94             return 0;
95         if (p[0] < 0 || p[1] < 0)
96         {
97             odr_seterror(o, ODATA, 23);
98             return 0;
99         }
100         for (pos = 1; p[pos] != -1; pos++)
101         {
102             n = 0;
103             if (pos == 1)
104                 id = p[0]*40 + p[1];
105             else
106                 id = p[pos];
107             do
108             {
109                 octs[n++] = id & 0X7F;
110                 id >>= 7;
111             }
112             while (id);
113             while (n--)
114             {
115                 unsigned char p;
116
117                 p = octs[n] | ((n > 0) << 7);
118                 if (odr_putc(o, p) < 0)
119                     return 0;
120             }
121         }
122         end = odr_tell(o);
123         odr_seek(o, ODR_S_SET, lenp);
124         if (ber_enclen(o, (end - lenp) - 1, 1, 1) != 1)
125         {
126             odr_seterror(o, OOTHER, 52);
127             return 0;
128         }
129         odr_seek(o, ODR_S_END, 0);
130         return 1;
131     default:
132         odr_seterror(o, OOTHER, 22);
133         return 0;
134     }
135 }
136 /*
137  * Local variables:
138  * c-basic-offset: 4
139  * c-file-style: "Stroustrup"
140  * indent-tabs-mode: nil
141  * End:
142  * vim: shiftwidth=4 tabstop=8 expandtab
143  */
144