Dates
[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.12 2003-02-21 12:08:57 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 COMSTACK cs_create_host(const char *type_and_host, int blocking, void **vp)
40 {
41     enum oid_proto proto = PROTO_Z3950;
42     const char *host = 0;
43     COMSTACK cs;
44     CS_TYPE t;
45
46     if (strncmp (type_and_host, "tcp:", 4) == 0)
47     {
48         t = tcpip_type;
49         host = type_and_host + 4;
50     }
51     else if (strncmp (type_and_host, "ssl:", 4) == 0)
52     {
53 #if HAVE_OPENSSL_SSL_H
54         t = ssl_type;
55         host = type_and_host + 4;
56 #else
57         return 0;
58 #endif
59     }
60     else if (strncmp (type_and_host, "unix:", 5) == 0)
61     {
62 #ifndef WIN32
63         t = unix_type;
64         host = type_and_host + 5;
65 #else
66         return 0;
67 #endif
68     }
69     else if (strncmp(type_and_host, "http:", 5) == 0)
70     {
71         t = tcpip_type;
72         host = type_and_host + 5;
73         if (host[0] == '/' && host[1] == '/')
74             host = host + 2;
75         proto = PROTO_HTTP;
76     }
77     else if (strncmp(type_and_host, "https:", 6) == 0)
78     {
79 #if HAVE_OPENSSL_SSL_H
80         t = ssl_type;
81         host = type_and_host + 6;
82         if (host[0] == '/' && host[1] == '/')
83             host = host + 2;
84 #else
85         return 0;
86 #endif
87         proto = PROTO_HTTP;
88     }
89     else
90     {
91         t = tcpip_type;
92         host = type_and_host;
93         
94     }
95     cs = cs_create (t, blocking, proto);
96     if (!cs)
97         return 0;
98
99     if (!(*vp = cs_straddr(cs, host)))
100     {
101         cs_close (cs);
102         return 0;
103     }    
104     return cs;
105 }
106
107 int cs_look (COMSTACK cs)
108 {
109     return cs->event;
110 }
111
112 int cs_complete_auto(const unsigned char *buf, int len)
113 {
114     if (!len)
115         return 0;
116     if (!buf[0] && !buf[1])
117         return 0;
118     if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f
119                 && buf[1] >= 0x20 && buf[1] < 0x7f
120                 && buf[2] >= 0x20 && buf[2] < 0x7f)
121     {
122         /* deal with HTTP request/response */
123         int i = 2, content_len = 0;
124
125         while (i <= len-4)
126         {
127             if (buf[i] == '\r' && buf[i+1] == '\n')
128             {
129                 i += 2;
130                 if (buf[i] == '\r' && buf[i+1] == '\n')
131                 {
132                     /* i += 2 seems not to work with GCC -O2 .. 
133                        so i+2 is used instead .. */
134                     if (len >= (i+2)+ content_len)
135                         return (i+2)+ content_len;
136                     break;
137                 }
138                 if (i < len-18)
139                 {
140                     if (!memcmp(buf+i, "Content-Length:", 15))
141                     {
142                         i+= 15;
143                         if (buf[i] == ' ')
144                             i++;
145                         content_len = 0;
146                         while (i <= len-4 && isdigit(buf[i]))
147                             content_len = content_len*10 + (buf[i++] - '0');
148                         if (content_len < 0) /* prevent negative offsets */
149                             content_len = 0;
150                     }
151                 }
152             }
153             else
154                 i++;
155         }
156         return 0;
157     }
158     return completeBER(buf, len);
159 }