dee25a74addce52499a9b57d78de045f7dc3fd67
[yaz-moved-to-github.git] / odr / odr_oct.c
1 /*
2  * Copyright (c) 1995-2003, Index Data
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Id: odr_oct.c,v 1.21 2003-03-11 11:03:31 adam Exp $
7  */
8 #if HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <yaz/log.h>
13 #include "odr-priv.h"
14
15 /*
16  * Top level octet string en/decoder.
17  * Returns 1 on success, 0 on error.
18  */
19 int odr_octetstring(ODR o, Odr_oct **p, int opt, const char *name)
20 {
21     int res, cons = 0;
22
23     if (o->error)
24         return 0;
25     if (o->t_class < 0)
26     {
27         o->t_class = ODR_UNIVERSAL;
28         o->t_tag = ODR_OCTETSTRING;
29     }
30     if ((res = ber_tag(o, p, o->t_class, o->t_tag, &cons, opt)) < 0)
31         return 0;
32     if (!res)
33         return opt;
34     if (o->direction == ODR_PRINT)
35     {
36         int i;
37         odr_prname(o, name);
38         fprintf(o->print, "OCTETSTRING(len=%d)", (*p)->len);
39         for (i = 0; i<(*p)->len; i++)
40         {
41             if (i < 5 || i > ((*p)->len - 4))
42             {
43                 fprintf (o->print, " %02X", (*p)->buf[i]);
44             }
45             else if (i == 5)
46                 fprintf (o->print, " .. ");
47         }
48         fprintf(o->print, "\n");
49         return 1;
50     }
51     if (o->direction == ODR_DECODE)
52     {
53         *p = (Odr_oct *)odr_malloc(o, sizeof(Odr_oct));
54         (*p)->size= 0;
55         (*p)->len = 0;
56         (*p)->buf = 0;
57     }
58     if (ber_octetstring(o, *p, cons))
59         return 1;
60     odr_seterror(o, OOTHER, 43);
61     return 0;
62 }
63
64 /*
65  * Friendlier interface to octetstring.
66  */
67 int odr_cstring(ODR o, char **p, int opt, const char *name)
68 {
69     int cons = 0, res;
70     Odr_oct *t;
71
72     if (o->error)
73         return 0;
74     if (o->t_class < 0)
75     {
76         o->t_class = ODR_UNIVERSAL;
77         o->t_tag = ODR_OCTETSTRING;
78     }
79     if ((res = ber_tag(o, p, o->t_class, o->t_tag, &cons, opt)) < 0)
80         return 0;
81     if (!res)
82         return opt;
83     if (o->direction == ODR_PRINT)
84     {
85         odr_prname(o, name);
86         fprintf(o->print, "'%s'\n", *p);
87         return 1;
88     }
89     t = (Odr_oct *)odr_malloc(o, sizeof(Odr_oct)); /* wrapper for octstring */
90     if (o->direction == ODR_ENCODE)
91     {
92         t->buf = (unsigned char *) *p;
93         t->size = t->len = strlen(*p);
94     }
95     else
96     {
97         t->size= 0;
98         t->len = 0;
99         t->buf = 0;
100     }
101     if (!ber_octetstring(o, t, cons))
102         return 0;
103     if (o->direction == ODR_DECODE)
104     {
105         *p = (char *) t->buf;
106         *(*p + t->len) = '\0';  /* ber_octs reserves space for this */
107     }
108     return 1;
109 }
110
111 /*
112  * iconv interface to octetstring.
113  */
114 int odr_iconv_string(ODR o, char **p, int opt, const char *name)
115 {
116     int cons = 0, res;
117     Odr_oct *t;
118
119     if (o->error)
120         return 0;
121     if (o->t_class < 0)
122     {
123         o->t_class = ODR_UNIVERSAL;
124         o->t_tag = ODR_OCTETSTRING;
125     }
126     if ((res = ber_tag(o, p, o->t_class, o->t_tag, &cons, opt)) < 0)
127         return 0;
128     if (!res)
129         return opt;
130     if (o->direction == ODR_PRINT)
131     {
132         odr_prname(o, name);
133         fprintf(o->print, "'%s'\n", *p);
134         return 1;
135     }
136     t = (Odr_oct *)odr_malloc(o, sizeof(Odr_oct)); /* wrapper for octstring */
137     if (o->direction == ODR_ENCODE)
138     {
139         t->buf = 0;
140
141         if (o->op->iconv_handle != 0)
142         {
143             size_t inleft = strlen(*p);
144             char *inbuf = *p;
145             size_t outleft = 4 * inleft + 2;
146             char *outbuf = (char *) odr_malloc (o, outleft);
147             size_t ret;
148             
149             t->buf = (unsigned char *) outbuf;
150             
151             ret = yaz_iconv (o->op->iconv_handle, &inbuf, &inleft,
152                              &outbuf, &outleft);
153             if (ret == (size_t)(-1))
154             {
155                 odr_seterror(o, ODATA, 44);
156                 return 0;
157             }
158             t->size = t->len = outbuf - (char*) t->buf;
159         }
160         if (!t->buf)
161         {
162             t->buf = (unsigned char *) *p;
163             t->size = t->len = strlen(*p);
164         }
165     }
166     else
167     {
168         t->size= 0;
169         t->len = 0;
170         t->buf = 0;
171     }
172     if (!ber_octetstring(o, t, cons))
173         return 0;
174     if (o->direction == ODR_DECODE)
175     {
176         *p = 0;
177
178         if (o->op->iconv_handle != 0)
179         {
180             size_t inleft = t->len;
181             char *inbuf = (char *) t->buf;
182             size_t outleft = 4 * inleft + 2;
183             char *outbuf = (char *) odr_malloc (o, outleft);
184             size_t ret;
185
186             *p = outbuf;
187             
188             ret = yaz_iconv (o->op->iconv_handle, &inbuf, &inleft,
189                              &outbuf, &outleft);
190             if (ret == (size_t)(-1))
191             {
192                 odr_seterror(o, ODATA, 45);
193                 return 0;
194             }
195             inleft = outbuf - (char*) *p;
196             
197             (*p)[inleft] = '\0';    /* null terminate it */
198         }
199         if (!*p)
200         {
201             *p = (char *) t->buf;
202             *(*p + t->len) = '\0';  /* ber_octs reserves space for this */
203         }
204     }
205     return 1;
206 }