SOAP, SRW codecs and HTTP transport for YAZ using libxml2.
[yaz-moved-to-github.git] / odr / ber_any.c
1 /*
2  * Copyright (c) 1995-2003, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Id: ber_any.c,v 1.21 2003-02-12 15:06:43 adam Exp $
6  */
7 #if HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 #include "odr-priv.h"
11
12 int ber_any(ODR o, Odr_any **p)
13 {
14     int res;
15     int left = o->size - (o->bp - o->buf);
16
17     switch (o->direction)
18     {
19         case ODR_DECODE:
20             if ((res = completeBER(o->bp, left)) <= 0)        /* FIX THIS */
21             {
22                 o->error = OPROTO;
23                 return 0;
24             }
25             (*p)->buf = (unsigned char *)odr_malloc(o, res);
26             memcpy((*p)->buf, o->bp, res);
27             (*p)->len = (*p)->size = res;
28             o->bp += res;
29             return 1;
30         case ODR_ENCODE:
31             if (odr_write(o, (*p)->buf, (*p)->len) < 0)
32                 return 0;
33             return 1;
34         default: o->error = OOTHER; return 0;
35     }
36 }
37
38 /*
39  * Return length of BER-package or 0.
40  */
41 int completeBER(const unsigned char *buf, int len)
42 {
43     int res, ll, zclass, tag, cons;
44     const unsigned char *b = buf;
45     
46     if (!len)
47         return 0;
48     if (!buf[0] && !buf[1])
49         return 0;
50     if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f
51                 && buf[1] >= 0x20 && buf[1] < 0x7f
52                 && buf[2] >= 0x20 && buf[2] < 0x7f)
53     {
54         /* deal with HTTP request/response */
55         int i = 2, content_len = 0;
56
57         while (i <= len-4)
58         {
59             if (buf[i] == '\r' && buf[i+1] == '\n')
60             {
61                 i += 2;
62                 if (buf[i] == '\r' && buf[i+1] == '\n')
63                 {
64                     /* i += 2 seems not to work with GCC -O2 .. 
65                        so i+2 is used instead .. */
66                     if (len >= (i+2)+ content_len)
67                         return (i+2)+ content_len;
68                     break;
69                 }
70                 if (i < len-18)
71                 {
72                     if (!memcmp(buf+i, "Content-Length:", 15))
73                     {
74                         i+= 15;
75                         if (buf[i] == ' ')
76                             i++;
77                         content_len = 0;
78                         while (i <= len-4 && isdigit(buf[i]))
79                             content_len = content_len*10 + (buf[i++] - '0');
80                         if (content_len < 0) /* prevent negative offsets */
81                             content_len = 0;
82                     }
83                 }
84             }
85             else
86                 i++;
87         }
88         return 0;
89     }
90     /* BER from now on .. */
91     if ((res = ber_dectag(b, &zclass, &tag, &cons)) <= 0)
92         return 0;
93     if (res > len)
94         return 0;
95     b += res;
96     len -= res;
97     if ((res = ber_declen(b, &ll)) <= 0)
98         return 0;
99     if (res > len)
100         return 0;
101     b += res;
102     len -= res;
103     if (ll >= 0)
104         return (len >= ll ? ll + (b-buf) : 0);
105     if (!cons)
106         return 0;    
107     /* constructed - cycle through children */
108     while (len >= 2)
109     {
110         if (*b == 0 && *(b + 1) == 0)
111             break;
112         if (!(res = completeBER(b, len)))
113             return 0;
114         b += res;
115         len -= res;
116     }
117     if (len < 2)
118         return 0;
119     return (b - buf) + 2;
120 }