Implemented bug #806: Deal with HTTP clients sending LF in HTTP headers.
[yaz-moved-to-github.git] / src / zgdu.c
index 0dfdbaf..49f1ea3 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.
  *
- * $Id: zgdu.c,v 1.14 2006-03-01 23:24:25 adam Exp $
+ * $Id: zgdu.c,v 1.18 2007-01-11 10:30:41 adam Exp $
  */
 
 /**
@@ -28,17 +28,16 @@ static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers,
     int chunked = 0;
 
     *headers = 0;
-    while (i < o->size-1 && o->buf[i] == '\r')
+    while (i < o->size-1 && o->buf[i] == '\n')
     {
         int po;
         i++;
-        if (o->buf[i] != '\n')
+        if (o->buf[i] == '\r' && i < o->size-1 && o->buf[i+1] == '\n')
         {
-            o->error = OHTTP;
-            return 0;
+            i++;
+            break;
         }
-        i++;
-        if (o->buf[i] == '\r')
+        if (o->buf[i] == '\n')
             break;
         for (po = i; ; i++)
         {
@@ -57,7 +56,7 @@ static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers,
         i++;
         while (i < o->size-1 && o->buf[i] == ' ')
             i++;
-        for (po = i; i < o->size-1 && o->buf[i] != '\r' ; i++)
+        for (po = i; i < o->size-1 && !strchr("\r\n", o->buf[i]); i++)
             ;
         
         (*headers)->value = (char*) odr_malloc(o, i - po + 1);
@@ -69,9 +68,10 @@ static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers,
             !strcasecmp((*headers)->value, "chunked"))
             chunked = 1;
         headers = &(*headers)->next;
+        if (i < o->size-1 && o->buf[i] == '\r')
+            i++;
     }
     *headers = 0;
-    i++;
     if (o->buf[i] != '\n')
     {
         o->error = OHTTP;
@@ -179,7 +179,7 @@ void z_HTTP_header_add(ODR o, Z_HTTP_Header **hp, const char *n,
     (*hp)->next = 0;
 }
 
-const char *z_HTTP_header_lookup(Z_HTTP_Header *hp, const char *n)
+const char *z_HTTP_header_lookup(const Z_HTTP_Header *hp, const char *n)
 {
     for (; hp; hp = hp->next)
         if (!yaz_matchstr(hp->name, n))
@@ -207,6 +207,41 @@ Z_GDU *z_get_HTTP_Request(ODR o)
     return p;
 }
 
+
+Z_GDU *z_get_HTTP_Request_host_path(ODR odr,
+                                    const char *host,
+                                    const char *path)
+{
+    Z_GDU *p = z_get_HTTP_Request(odr);
+
+    p->u.HTTP_Request->path = odr_strdup(odr, path);
+
+    if (host)
+    {
+        const char *cp0 = strstr(host, "://");
+        const char *cp1 = 0;
+        if (cp0)
+            cp0 = cp0+3;
+        else
+            cp0 = host;
+
+        cp1 = strchr(cp0, '/');
+        if (!cp1)
+            cp1 = cp0+strlen(cp0);
+
+        if (cp0 && cp1)
+        {
+            char *h = (char*) odr_malloc(odr, cp1 - cp0 + 1);
+            memcpy (h, cp0, cp1 - cp0);
+            h[cp1-cp0] = '\0';
+            z_HTTP_header_add(odr, &p->u.HTTP_Request->headers,
+                              "Host", h);
+        }
+    }
+    return p;
+}
+
+
 Z_GDU *z_get_HTTP_Response(ODR o, int code)
 {
     Z_GDU *p = (Z_GDU *) odr_malloc(o, sizeof(*p));
@@ -277,7 +312,7 @@ int z_GDU (ODR o, Z_GDU **p, int opt, const char *name)
             hr->content_len = 0;
 
             po = i = 5;
-            while (i < o->size-2 && o->buf[i] != ' ' && o->buf[i] != '\r')
+            while (i < o->size-2 && !strchr(" \r\n", o->buf[i]))
                 i++;
             hr->version = (char *) odr_malloc(o, i - po + 1);
             if (i - po)
@@ -295,7 +330,7 @@ int z_GDU (ODR o, Z_GDU **p, int opt, const char *name)
                 hr->code = hr->code*10 + (o->buf[i] - '0');
                 i++;
             }
-            while (i < o->size-1 && o->buf[i] != '\r')
+            while (i < o->size-1 && o->buf[i] != '\n')
                 i++;
             return decode_headers_content(o, i, &hr->headers,
                                           &hr->content_buf, &hr->content_len);            
@@ -343,19 +378,19 @@ int z_GDU (ODR o, Z_GDU **p, int opt, const char *name)
             }
             i+= 5;
             po = i;
-            while (o->buf[i] != '\r')
-            {
-                if (i >= o->size-1)
-                {
-                    o->error = OHTTP;
-                    return 0;
-                }
+            while (i < o->size && !strchr("\r\n", o->buf[i]))
                 i++;
-            }
             hr->version = (char *) odr_malloc(o, i - po + 1);
             memcpy(hr->version, o->buf + po, i - po);
             hr->version[i - po] = '\0';
             /* headers */
+            if (i < o->size-1 && o->buf[i] == '\r')
+                i++;
+            if (o->buf[i] != '\n')
+            {
+                o->error = OHTTP;
+                return 0;
+            }
             return decode_headers_content(o, i, &hr->headers,
                                           &hr->content_buf, &hr->content_len);