c02ae3b7fe3dc1089963c5bfa0779f561f26b43a
[yaz-moved-to-github.git] / src / dumpber.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2011 Index Data
3  * See the file LICENSE for details.
4  */
5
6 /**
7  * \file dumpber.c
8  * \brief Implements BER dumping
9  */
10
11 #if HAVE_CONFIG_H
12 #include <config.h>
13 #endif
14
15 #include <stdio.h>
16 #include "odr-priv.h"
17
18 static int do_dumpBER(FILE *f, const char *buf, int len, int level, int offset)
19 {
20     int res, ll, zclass, tag, cons, lenlen, taglen;
21     const char *b = buf, *bp = buf;
22     
23     if (!len)
24         return 0;
25     if (!buf[0] && !buf[1])
26         return 0;
27     if ((res = ber_dectag((unsigned char*)b, &zclass, &tag, &cons, len)) <= 0)
28         return 0;
29     if (res > len)
30     {
31         fprintf(stderr, "Unexpected end of buffer\n");
32         return 0;
33     }
34     fprintf(f, "%5d: %*s", offset, level * 4, "");
35     if (zclass == ODR_UNIVERSAL)
36     {
37         static char *nl[] =
38         {
39             "[Univ 0]", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING",
40             "NULL", "OID", "OBJECT DESCIPTOR", "EXTERNAL", "REAL",
41             "ENUM", "[UNIV 11]", "[UNIV 12]", "[UNIV 13]", "[UNIV 14]",
42             "[UNIV 15]", "SEQUENCE", "SET", "NUMERICSTRING", "PRINTABLESTRING",
43             "[UNIV 20]", "[UNIV 21]", "[UNIV 22]", "[UNIV 23]", "[UNIV 24]",
44             "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", "[UNIV 28]"
45         };
46
47         if (tag >= 0 && tag < 28)
48             fprintf(f, "%s", nl[tag]);
49         else
50             fprintf(f, "[UNIV %d]", tag);
51     }
52     else if (zclass == ODR_CONTEXT)
53         fprintf(f, "[%d]", tag);
54     else
55         fprintf(f, "[%d:%d]", zclass, tag);
56     b += res;
57     taglen = res;
58     len -= res;
59     bp = b;
60     if ((res = ber_declen((unsigned char*)b, &ll, len)) <= 0)
61     {
62         fprintf(f, "\n%*sBad length\n", level*4+5, "");
63         return 0;
64     }
65     lenlen = res;
66     b += res;
67     len -= res;
68     if (ll >= 0)
69         fprintf(f, " len=%d", ll);
70     else
71         fprintf(f, " len=?");
72     fprintf(f, "       tl=%d, ll=%d cons=%d\n", taglen, lenlen, cons);
73     if (!cons)
74     {
75         if (ll < 0 || ll > len)
76         {
77             fprintf(f, "%*sBad length on primitive type. ll=%d len=%d\n",
78                     level*4+5, "", ll, len);
79             return 0;
80         }
81         return ll + (b - buf);
82     }
83     if (ll >= 0)
84     {
85         if (ll > len)
86         {
87             fprintf(f, "%*sBad length of constructed type ll=%d len=%d.\n",
88                     level*4+5, "", ll, len);
89             return 0;
90         }
91         len = ll;
92     }
93     /* constructed - cycle through children */
94     while ((ll == -1 && len >= 2) || (ll >= 0 && len))
95     {
96         if (ll == -1 && *b == 0 && *(b + 1) == 0)
97             break;
98         if (!(res = do_dumpBER(f, b, len, level + 1, offset + (b - buf))))
99         {
100             fprintf(f, "%*sDump of content element failed.\n", level*4+5, "");
101             return 0;
102         }
103         b += res;
104         len -= res;
105         if (len < 0)
106         {
107             fprintf(f, "%*sBad length\n", level*4+5, "");
108             return 0;
109         }
110     }
111     if (ll == -1)
112     {
113         if (len < 2)
114         {
115             fprintf(f, "%*sBuffer too short in indefinite length.\n",
116                     level*4+5, "");
117             return 0;
118         }
119         return (b - buf) + 2;
120     }
121     return b - buf;
122 }
123
124 int odr_dumpBER(FILE *f, const char *buf, int len)
125 {
126     return do_dumpBER(f, buf, len, 0, 0);
127 }
128 /*
129  * Local variables:
130  * c-basic-offset: 4
131  * c-file-style: "Stroustrup"
132  * indent-tabs-mode: nil
133  * End:
134  * vim: shiftwidth=4 tabstop=8 expandtab
135  */
136