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