Fixed bugs in completeBER and (serious one in) ber_oid.
[yaz-moved-to-github.git] / odr / ber_oid.c
1 /*
2  * Copyright (C) 1994, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: ber_oid.c,v $
7  * Revision 1.2  1995-02-14 20:39:55  quinn
8  * Fixed bugs in completeBER and (serious one in) ber_oid.
9  *
10  * Revision 1.1  1995/02/03  17:04:36  quinn
11  * Initial revision
12  *
13  */
14
15 #include <odr.h>
16
17 int ber_oid(ODR o, Odr_oid *p)
18 {
19     int len;
20     unsigned char *lenp;
21     int pos, n, res, id;
22     unsigned char octs[8];
23
24     switch (o->direction)
25     {
26         case ODR_DECODE:
27             if ((res = ber_declen(o->bp, &len)) < 1)
28                 return 0;
29             if (len < 0)
30                 return 0;
31             o->bp += res;
32             o->left -= res;
33             if (len == 0)
34             {
35                 *p = -1;
36                 return 1;
37             }
38             p[0] = *o->bp / 40;
39             if (p[0] > 2)
40                 p[0] = 2;
41             p[1] = *o->bp - p[0] * 40;
42             o->bp++;
43             o->left--;
44             pos = 2;
45             len--;
46             while (len)
47             {
48                 p[pos] = 0;
49                 do
50                 {
51                     if (!len)
52                         return 0;
53                     p[pos] <<= 7;
54                     p[pos] |= *o->bp & 0X7F;
55                     len--;
56                     o->left--;
57                 }
58                 while (*(o->bp++) & 0X80);
59                 pos++;
60             }
61             p[pos] = -1;
62             return 1;
63         case ODR_ENCODE:
64             /* we'll allow ourselves the quiet luxury of only doing encodings
65                shorter than 127 */
66             lenp = o->bp;
67             o->bp++;
68             o->left--;
69             if (p[0] < 0 && p[1] <= 0)
70                 return 0;
71             p[1] = p[0] * 40 + p[1];
72             for (pos = 1; p[pos] >= 0; pos++)
73             {
74                 id = p[pos];
75                 n = 0;
76                 do
77                 {
78                     octs[n++] = id & 0X7F;
79                     id >>= 7;
80                 }
81                 while (id);
82                 if (n > o->left)
83                     return 0;
84                 o->left -= n;
85                 while (n--)
86                     *(o->bp++) = octs[n] | ((n > 0) << 7);
87             }
88             if (ber_enclen(lenp, (o->bp - lenp) - 1, 1, 1) != 1)
89                 return 0;
90             return 1;
91         default: return 0;
92     }
93 }