Added function yaz_oid_add which adds custom OID entry to database.
[yaz-moved-to-github.git] / src / comstack.c
index 68aeb67..db3b002 100644 (file)
@@ -1,8 +1,8 @@
 /*
 /*
- * Copyright (C) 1995-2005, Index Data ApS
+ * Copyright (C) 1995-2007, Index Data ApS
  * See the file LICENSE for details.
  *
  * See the file LICENSE for details.
  *
- * $Id: comstack.c,v 1.15 2005-06-25 15:46:03 adam Exp $
+ * $Id: comstack.c,v 1.18 2007-01-11 10:30:41 adam Exp $
  */
 
 /** 
  */
 
 /** 
@@ -14,6 +14,7 @@
 #include <ctype.h>
 #include <errno.h>
 
 #include <ctype.h>
 #include <errno.h>
 
+#include <yaz/log.h>
 #include <yaz/comstack.h>
 #include <yaz/tcpip.h>
 #include <yaz/unix.h>
 #include <yaz/comstack.h>
 #include <yaz/tcpip.h>
 #include <yaz/unix.h>
@@ -31,7 +32,8 @@ static const char *cs_errlist[] =
     "No data (operation would block)",
     "New data while half of old buffer is on the line (flow control)",
     "Permission denied",
     "No data (operation would block)",
     "New data while half of old buffer is on the line (flow control)",
     "Permission denied",
-    "SSL error"
+    "SSL error",
+    "Too large incoming buffer"
 };
 
 const char *cs_errmsg(int n)
 };
 
 const char *cs_errmsg(int n)
@@ -144,151 +146,189 @@ int cs_look (COMSTACK cs)
     return cs->event;
 }
 
     return cs->event;
 }
 
-#define CHUNK_DEBUG 0
-int cs_complete_auto(const unsigned char *buf, int len)
+static int skip_crlf(const char *buf, int len, int *i)
 {
 {
-    if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f
-                && buf[1] >= 0x20 && buf[1] < 0x7f
-                && buf[2] >= 0x20 && buf[2] < 0x7f)
+    if (*i < len)
     {
     {
-        /* deal with HTTP request/response */
-        int i = 2, content_len = 0, chunked = 0;
-        
-        /* if dealing with HTTP responses - then default
-           content length is unlimited (socket close) */
-        if (!memcmp(buf, "HTTP/", 5))
-            content_len = -1; 
+        if (buf[*i] == '\r' && *i < len-1 && buf[*i + 1] == '\n')
+        {
+            (*i) += 2;
+            return 1;
+        }
+        else if (buf[*i] == '\n')
+        {
+            (*i)++;
+            return 1;
+        }
+    }
+    return 0;
+}
+
+#define CHUNK_DEBUG 0
+
+int cs_complete_http(const char *buf, int len)
+{
+    /* deal with HTTP request/response */
+    int i = 2, content_len = 0, chunked = 0;
 
 
-        while (i <= len-4)
+    if (len < 6)
+        return 0;
+
+    /* if dealing with HTTP responses - then default
+       content length is unlimited (socket close) */
+    if (!memcmp(buf, "HTTP/", 5))
+        content_len = -1; 
+
+#if 0
+    printf("len = %d\n", len);
+    fwrite (buf, 1, len, stdout);
+    printf("----------\n");
+#endif
+    while (i <= len-2)
+    {
+        if (i > 8192)
         {
         {
-            if (i > 8192)
-            {
-                return i;  /* do not allow more than 8K HTTP header */
-            }
-            if (buf[i] == '\r' && buf[i+1] == '\n')
+            return i;  /* do not allow more than 8K HTTP header */
+        }
+        if (skip_crlf(buf, len, &i))
+        {
+            if (skip_crlf(buf, len, &i))
             {
             {
-                i += 2;
-                if (buf[i] == '\r' && buf[i+1] == '\n')
-                {
-                    if (chunked)
-                    { 
-                        /* inside chunked body .. */
-                        while(1)
-                        {
-                            int j, chunk_len = 0;
-                            i += 2;
+                /* inside content */
+                if (chunked)
+                { 
+                    /* inside chunked body .. */
+                    while(1)
+                    {
+                        int chunk_len = 0;
 #if CHUNK_DEBUG
 #if CHUNK_DEBUG
-/* debugging */
-                            if (i <len-2)
-                            {
-                                printf ("\n<<<");
-                                int j;
-                                for (j = i; j <= i+4; j++)
-                                    printf ("%c", buf[j]);
-                                printf (">>>\n");
-                            }
+                        if (i < len-2)
+                        {
+                            printf ("\n<<<");
+                            int j;
+                            for (j = i; j <= i+3; j++)
+                                printf ("%c", buf[j]);
+                            printf (">>>\n");
+                        }
 #endif
 #endif
-                            /* read chunk length */
-                            while (1)
-                                if (i >= len-2) {
+                        /* read chunk length */
+                        while (1)
+                            if (i >= len-2) {
 #if CHUNK_DEBUG
 #if CHUNK_DEBUG
-/* debugging */                                    
-                                    printf ("XXXXXXXX not there yet 1\n");
-                                    printf ("i=%d len=%d\n", i, len);
+                                printf ("returning incomplete read at 1\n");
+                                printf ("i=%d len=%d\n", i, len);
 #endif
 #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;
-                            /* move forward until CRLF - skip chunk ext */
-                            j = 0;
-                            while (buf[i] != '\r' && buf[i+1] != '\n')
-                            {
-                                if (i >= len-2)
-                                    return 0;   /* need more buffer .. */
-                                if (++j > 1000)
-                                    return i; /* enough.. stop */
-                                i++;
-                            }
-                            /* got CRLF */
-#if CHUNK_DEBUG
-                            printf ("XXXXXX chunk_len=%d\n", chunk_len);
-#endif                      
-                            if (chunk_len < 0)
-                                return i+2;    /* bad chunk_len */
-                            if (chunk_len == 0)
+                                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;
                                 break;
-                            i += chunk_len+2;
-                        }
-                        /* consider trailing headers .. */
-                        while(i <= len-4)
+                        if (chunk_len == 0)
+                            break;
+                        if (chunk_len < 0)
+                            return i;
+                        
+                        while (1)
                         {
                         {
-                            if (buf[i] == '\r' &&  buf[i+1] == '\n' &&
-                                buf[i+2] == '\r' && buf[i+3] == '\n')
-                                if (len >= i+4)
-                                    return i+4;
+                            if (i >= len -1)
+                                return 0;
+                            if (skip_crlf(buf, len, &i))
+                                break;
                             i++;
                         }
                             i++;
                         }
+                        /* got CRLF */
 #if CHUNK_DEBUG
 #if CHUNK_DEBUG
-/* debugging */
-                        printf ("XXXXXXXXX not there yet 2\n");
-                        printf ("i=%d len=%d\n", i, len);
-#endif
-                        return 0;
+                        printf ("chunk_len=%d\n", chunk_len);
+#endif                      
+                        i += chunk_len;
+                        if (i >= len-2)
+                            return 0;
+                        if (!skip_crlf(buf, len, &i))
+                            return 0;
                     }
                     }
-                    else
-                    {   /* not chunked ; inside body */
-                        /* i += 2 seems not to work with GCC -O2 .. 
-                           so i+2 is used instead .. */
-                        if (content_len == -1)
-                            return 0;   /* no content length */
-                        else if (len >= (i+2)+ content_len)
+                    /* consider trailing headers .. */
+                    while (i < len)
+                    {
+                        if (skip_crlf(buf, len, &i))
                         {
                         {
-                            return (i+2)+ content_len;
+                            if (skip_crlf(buf, len, &i))
+                                return i;
                         }
                         }
+                        else
+                            i++;
                     }
                     }
-                    break;
-                }
-                else if (i < len - 20 && 
-                         !strncasecmp((const char *) buf+i, "Transfer-Encoding:", 18))
-                {
-                    i+=18;
-                    while (buf[i] == ' ')
-                        i++;
-                    if (i < len - 8)
-                        if (!strncasecmp((const char *) buf+i, "chunked", 7))
-                            chunked = 1;
-                }
-                else if (i < len - 17 &&
-                         !strncasecmp((const char *)buf+i, "Content-Length:", 15))
-                {
-                    i+= 15;
-                    while (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;
+#if CHUNK_DEBUG
+                    printf ("returning incomplete read at 2\n");
+                    printf ("i=%d len=%d\n", i, len);
+#endif
+                    return 0;
                 }
                 else
                 }
                 else
+                {   /* not chunked ; inside body */
+                    if (content_len == -1)
+                        return 0;   /* no content length */
+                    else if (len >= i + content_len)
+                    {
+                        return i + content_len;
+                    }
+                }
+                break;
+            }
+            else if (i < len - 20 && 
+                     !strncasecmp((const char *) buf+i, "Transfer-Encoding:", 18))
+            {
+                i+=18;
+                while (buf[i] == ' ')
                     i++;
                     i++;
+                if (i < len - 8)
+                    if (!strncasecmp((const char *) buf+i, "chunked", 7))
+                        chunked = 1;
+            }
+            else if (i < len - 17 &&
+                     !strncasecmp((const char *)buf+i, "Content-Length:", 15))
+            {
+                i+= 15;
+                while (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;
+        else
+            i++;
+    }
+    return 0;
+}
+
+int cs_complete_auto(const unsigned char *buf, int len)
+{
+    if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f
+                && buf[1] >= 0x20 && buf[1] < 0x7f
+                && buf[2] >= 0x20 && buf[2] < 0x7f)
+    {
+        int r = cs_complete_http((const char *) buf, len);
+        return r;
     }
     return completeBER(buf, len);
 }
     }
     return completeBER(buf, len);
 }
+
+void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes)
+{
+    cs->max_recv_bytes = max_recv_bytes;
+}
+
 /*
  * Local variables:
  * c-basic-offset: 4
 /*
  * Local variables:
  * c-basic-offset: 4