Defined log level bits app2 and app3
[yaz-moved-to-github.git] / comstack / comstack.c
1 /*
2  * Copyright (c) 1995-2003, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Id: comstack.c,v 1.14 2003-04-24 13:04:45 adam Exp $
6  */
7
8 #include <string.h>
9 #include <ctype.h>
10
11 #include <yaz/comstack.h>
12 #include <yaz/tcpip.h>
13 #include <yaz/unix.h>
14 #include <yaz/odr.h>
15
16 static const char *cs_errlist[] =
17 {
18     "No error or unspecified error",
19     "System (lower-layer) error",
20     "Operation out of state",
21     "No data (operation would block)",
22     "New data while half of old buffer is on the line (flow control)",
23     "Permission denied",
24     "SSL error"
25 };
26
27 const char *cs_errmsg(int n)
28 {
29     if (n < 0 || n > 6)
30         n = 0;
31     return cs_errlist[n];
32 }
33
34 const char *cs_strerror(COMSTACK h)
35 {
36     return cs_errmsg(h->cerrno);
37 }
38
39 void cs_get_host_args(const char *type_and_host, const char **args)
40 {
41     
42     *args = "";
43     if (*type_and_host && strncmp(type_and_host, "unix:", 5))
44     {
45         const char *cp;
46         cp = strstr(type_and_host, "://");
47         if (cp)
48             cp = cp+3;
49         else
50             cp = type_and_host;
51         cp = strchr(cp, '/');
52         if (cp)
53             *args = cp+1;
54     }
55 }
56
57 COMSTACK cs_create_host(const char *type_and_host, int blocking, void **vp)
58 {
59     enum oid_proto proto = PROTO_Z3950;
60     const char *host = 0;
61     COMSTACK cs;
62     CS_TYPE t;
63
64     if (strncmp (type_and_host, "tcp:", 4) == 0)
65     {
66         t = tcpip_type;
67         host = type_and_host + 4;
68     }
69     else if (strncmp (type_and_host, "ssl:", 4) == 0)
70     {
71 #if HAVE_OPENSSL_SSL_H
72         t = ssl_type;
73         host = type_and_host + 4;
74 #else
75         return 0;
76 #endif
77     }
78     else if (strncmp (type_and_host, "unix:", 5) == 0)
79     {
80 #ifndef WIN32
81         t = unix_type;
82         host = type_and_host + 5;
83 #else
84         return 0;
85 #endif
86     }
87     else if (strncmp(type_and_host, "http:", 5) == 0)
88     {
89         t = tcpip_type;
90         host = type_and_host + 5;
91         if (host[0] == '/' && host[1] == '/')
92             host = host + 2;
93         proto = PROTO_HTTP;
94     }
95     else if (strncmp(type_and_host, "https:", 6) == 0)
96     {
97 #if HAVE_OPENSSL_SSL_H
98         t = ssl_type;
99         host = type_and_host + 6;
100         if (host[0] == '/' && host[1] == '/')
101             host = host + 2;
102 #else
103         return 0;
104 #endif
105         proto = PROTO_HTTP;
106     }
107     else
108     {
109         t = tcpip_type;
110         host = type_and_host;
111         
112     }
113     cs = cs_create (t, blocking, proto);
114     if (!cs)
115         return 0;
116
117     if (!(*vp = cs_straddr(cs, host)))
118     {
119         cs_close (cs);
120         return 0;
121     }    
122     return cs;
123 }
124
125 int cs_look (COMSTACK cs)
126 {
127     return cs->event;
128 }
129
130 int cs_complete_auto(const unsigned char *buf, int len)
131 {
132     if (!len)
133         return 0;
134     if (!buf[0] && !buf[1])
135         return 0;
136     if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f
137                 && buf[1] >= 0x20 && buf[1] < 0x7f
138                 && buf[2] >= 0x20 && buf[2] < 0x7f)
139     {
140         /* deal with HTTP request/response */
141         int i = 2, content_len = 0, chunked = 0;
142
143         while (i <= len-4)
144         {
145             if (buf[i] == '\r' && buf[i+1] == '\n')
146             {
147                 i += 2;
148                 if (buf[i] == '\r' && buf[i+1] == '\n')
149                 {
150                     if (chunked)
151                     { 
152                         while(1)
153                         {
154                             int chunk_len = 0;
155                             i += 2;
156
157 #if 0
158 /* debugging */
159                             if (i <len-2)
160                             {
161                                 printf ("\n>>>");
162                                 for (j = i; j <= i+4; j++)
163                                     printf ("%c", buf[j]);
164                                 printf ("<<<\n");
165                             }
166 #endif
167                             while (1)
168                                 if (i >= len-2) {
169 #if 0
170 /* debugging */                                    
171                                     printf ("XXXXXXXX not there yet 1\n");
172                                     printf ("i=%d len=%d\n", i, len);
173 #endif
174                                     return 0;
175                                 } else if (isdigit(buf[i]))
176                                     chunk_len = chunk_len * 16 + 
177                                         (buf[i++] - '0');
178                                 else if (isupper(buf[i]))
179                                     chunk_len = chunk_len * 16 + 
180                                         (buf[i++] - ('A'-10));
181                                 else if (islower(buf[i]))
182                                     chunk_len = chunk_len * 16 + 
183                                         (buf[i++] - ('a'-10));
184                                 else
185                                     break;
186                             if (buf[i] != '\r' || buf[i+1] != '\n' ||
187                                 chunk_len < 0)
188                                 return i+2;    /* bad. stop now */
189                             if (chunk_len == 0)
190                             {
191                                 /* consider trailing headers .. */
192                                 while(i <= len-4)
193                                 {
194                                     if (buf[i] == '\r' &&  buf[i+1] == '\n' &&
195                                         buf[i+2] == '\r' && buf[i+3] == '\n')
196                                         if (len >= i+4)
197                                             return i+4;
198                                     i++;
199                                 }
200 #if 0
201 /* debugging */
202                                 printf ("XXXXXXXXX not there yet 2\n");
203                                 printf ("i=%d len=%d\n", i, len);
204 #endif
205                                 return 0;
206                             }
207                             i += chunk_len+2;
208                         }
209                     }
210                     else
211                     {
212                         /* i += 2 seems not to work with GCC -O2 .. 
213                            so i+2 is used instead .. */
214                         if (len >= (i+2)+ content_len)
215                             return (i+2)+ content_len;
216                     }
217                     break;
218                 }
219                 else if (i < len - 21 &&
220                          !memcmp(buf+i, "Transfer-Encoding: ", 18))
221                 {
222                     i+=18;
223                     if (buf[i] == ' ')
224                         i++;
225                     if (i < len - 8)
226                         if (!memcmp(buf+i, "chunked", 7))
227                             chunked = 1;
228                 }
229                 else if (i < len - 18 &&
230                          !memcmp(buf+i, "Content-Length: ", 15))
231                 {
232                     i+= 15;
233                     if (buf[i] == ' ')
234                         i++;
235                     content_len = 0;
236                     while (i <= len-4 && isdigit(buf[i]))
237                         content_len = content_len*10 + (buf[i++] - '0');
238                     if (content_len < 0) /* prevent negative offsets */
239                         content_len = 0;
240                 }
241                 else
242                     i++;
243             }
244             else
245                 i++;
246         }
247         return 0;
248     }
249     return completeBER(buf, len);
250 }