Defined log level bits app2 and app3
[yaz-moved-to-github.git] / comstack / comstack.c
index 8460316..583817a 100644 (file)
@@ -1,37 +1,17 @@
 /*
 /*
- * Copyright (c) 1995-1998, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * See the file LICENSE for details.
- * Sebastian Hammer, Adam Dickmeiss
- *
- * $Log: comstack.c,v $
- * Revision 1.6  1999-11-30 13:47:11  adam
- * Improved installation. Moved header files to include/yaz.
- *
- * Revision 1.5  1998/06/22 11:32:35  adam
- * Added 'conditional cs_listen' feature.
- *
- * Revision 1.4  1997/09/29 07:16:14  adam
- * Array cs_errlist no longer global.
- *
- * Revision 1.3  1997/09/01 08:49:14  adam
- * New windows NT/95 port using MSV5.0. Minor changes only.
- *
- * Revision 1.2  1995/09/29 17:01:48  quinn
- * More Windows work
- *
- * Revision 1.1  1995/06/14  09:58:20  quinn
- * Renamed yazlib to comstack.
- *
- * Revision 1.2  1995/05/16  08:51:15  quinn
- * License, documentation, and memory fixes
- *
- * Revision 1.1  1995/03/14  10:28:34  quinn
- * Adding server-side support to tcpip.c and fixing bugs in nonblocking I/O
- *
  *
  *
+ * $Id: comstack.c,v 1.14 2003-04-24 13:04:45 adam Exp $
  */
 
  */
 
+#include <string.h>
+#include <ctype.h>
+
 #include <yaz/comstack.h>
 #include <yaz/comstack.h>
+#include <yaz/tcpip.h>
+#include <yaz/unix.h>
+#include <yaz/odr.h>
 
 static const char *cs_errlist[] =
 {
 
 static const char *cs_errlist[] =
 {
@@ -40,10 +20,231 @@ static const char *cs_errlist[] =
     "Operation out of state",
     "No data (operation would block)",
     "New data while half of old buffer is on the line (flow control)",
     "Operation out of state",
     "No data (operation would block)",
     "New data while half of old buffer is on the line (flow control)",
-    "Permission denied"
+    "Permission denied",
+    "SSL error"
 };
 
 const char *cs_errmsg(int n)
 {
 };
 
 const char *cs_errmsg(int n)
 {
+    if (n < 0 || n > 6)
+       n = 0;
     return cs_errlist[n];
 }
     return cs_errlist[n];
 }
+
+const char *cs_strerror(COMSTACK h)
+{
+    return cs_errmsg(h->cerrno);
+}
+
+void cs_get_host_args(const char *type_and_host, const char **args)
+{
+    
+    *args = "";
+    if (*type_and_host && strncmp(type_and_host, "unix:", 5))
+    {
+        const char *cp;
+        cp = strstr(type_and_host, "://");
+        if (cp)
+            cp = cp+3;
+        else
+            cp = type_and_host;
+        cp = strchr(cp, '/');
+        if (cp)
+            *args = cp+1;
+    }
+}
+
+COMSTACK cs_create_host(const char *type_and_host, int blocking, void **vp)
+{
+    enum oid_proto proto = PROTO_Z3950;
+    const char *host = 0;
+    COMSTACK cs;
+    CS_TYPE t;
+
+    if (strncmp (type_and_host, "tcp:", 4) == 0)
+    {
+       t = tcpip_type;
+        host = type_and_host + 4;
+    }
+    else if (strncmp (type_and_host, "ssl:", 4) == 0)
+    {
+#if HAVE_OPENSSL_SSL_H
+       t = ssl_type;
+        host = type_and_host + 4;
+#else
+       return 0;
+#endif
+    }
+    else if (strncmp (type_and_host, "unix:", 5) == 0)
+    {
+#ifndef WIN32
+       t = unix_type;
+        host = type_and_host + 5;
+#else
+       return 0;
+#endif
+    }
+    else if (strncmp(type_and_host, "http:", 5) == 0)
+    {
+       t = tcpip_type;
+        host = type_and_host + 5;
+        if (host[0] == '/' && host[1] == '/')
+            host = host + 2;
+        proto = PROTO_HTTP;
+    }
+    else if (strncmp(type_and_host, "https:", 6) == 0)
+    {
+#if HAVE_OPENSSL_SSL_H
+       t = ssl_type;
+        host = type_and_host + 6;
+        if (host[0] == '/' && host[1] == '/')
+            host = host + 2;
+#else
+       return 0;
+#endif
+        proto = PROTO_HTTP;
+    }
+    else
+    {
+       t = tcpip_type;
+       host = type_and_host;
+        
+    }
+    cs = cs_create (t, blocking, proto);
+    if (!cs)
+       return 0;
+
+    if (!(*vp = cs_straddr(cs, host)))
+    {
+       cs_close (cs);
+       return 0;
+    }    
+    return cs;
+}
+
+int cs_look (COMSTACK cs)
+{
+    return cs->event;
+}
+
+int cs_complete_auto(const unsigned char *buf, int len)
+{
+    if (!len)
+       return 0;
+    if (!buf[0] && !buf[1])
+       return 0;
+    if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f
+               && buf[1] >= 0x20 && buf[1] < 0x7f
+               && buf[2] >= 0x20 && buf[2] < 0x7f)
+    {
+        /* deal with HTTP request/response */
+       int i = 2, content_len = 0, chunked = 0;
+
+        while (i <= len-4)
+        {
+            if (buf[i] == '\r' && buf[i+1] == '\n')
+            {
+                i += 2;
+                if (buf[i] == '\r' && buf[i+1] == '\n')
+                {
+                    if (chunked)
+                    { 
+                        while(1)
+                        {
+                            int chunk_len = 0;
+                            i += 2;
+
+#if 0
+/* debugging */
+                            if (i <len-2)
+                            {
+                                printf ("\n>>>");
+                                for (j = i; j <= i+4; j++)
+                                    printf ("%c", buf[j]);
+                                printf ("<<<\n");
+                            }
+#endif
+                            while (1)
+                                if (i >= len-2) {
+#if 0
+/* debugging */                                    
+                                    printf ("XXXXXXXX not there yet 1\n");
+                                    printf ("i=%d len=%d\n", i, len);
+#endif
+                                    return 0;
+                                } else if (isdigit(buf[i]))
+                                    chunk_len = chunk_len * 16 + 
+                                        (buf[i++] - '0');
+                                else if (isupper(buf[i]))
+                                    chunk_len = chunk_len * 16 + 
+                                        (buf[i++] - ('A'-10));
+                                else if (islower(buf[i]))
+                                    chunk_len = chunk_len * 16 + 
+                                        (buf[i++] - ('a'-10));
+                                else
+                                    break;
+                            if (buf[i] != '\r' || buf[i+1] != '\n' ||
+                                chunk_len < 0)
+                                return i+2;    /* bad. stop now */
+                            if (chunk_len == 0)
+                            {
+                                /* consider trailing headers .. */
+                                while(i <= len-4)
+                                {
+                                    if (buf[i] == '\r' &&  buf[i+1] == '\n' &&
+                                        buf[i+2] == '\r' && buf[i+3] == '\n')
+                                        if (len >= i+4)
+                                            return i+4;
+                                    i++;
+                                }
+#if 0
+/* debugging */
+                                printf ("XXXXXXXXX not there yet 2\n");
+                                printf ("i=%d len=%d\n", i, len);
+#endif
+                                return 0;
+                            }
+                            i += chunk_len+2;
+                        }
+                    }
+                    else
+                    {
+                        /* i += 2 seems not to work with GCC -O2 .. 
+                           so i+2 is used instead .. */
+                        if (len >= (i+2)+ content_len)
+                            return (i+2)+ content_len;
+                    }
+                    break;
+                }
+                else if (i < len - 21 &&
+                         !memcmp(buf+i, "Transfer-Encoding: ", 18))
+                {
+                    i+=18;
+                    if (buf[i] == ' ')
+                        i++;
+                    if (i < len - 8)
+                        if (!memcmp(buf+i, "chunked", 7))
+                            chunked = 1;
+                }
+                else if (i < len - 18 &&
+                         !memcmp(buf+i, "Content-Length: ", 15))
+                {
+                    i+= 15;
+                    if (buf[i] == ' ')
+                        i++;
+                    content_len = 0;
+                    while (i <= len-4 && isdigit(buf[i]))
+                        content_len = content_len*10 + (buf[i++] - '0');
+                    if (content_len < 0) /* prevent negative offsets */
+                        content_len = 0;
+                }
+                else
+                    i++;
+            }
+            else
+                i++;
+        }
+        return 0;
+    }
+    return completeBER(buf, len);
+}