]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/HttpHeaderTools.cc
Merged from trunk (r13356).
[thirdparty/squid.git] / src / HttpHeaderTools.cc
index d16d790ca8f81367420b3cb63b6e138076b0414e..ce24eed4266760f8767e75e0b3e19d567eeb6459 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DEBUG: section 66    HTTP Header Tools
  * AUTHOR: Alex Rousskov
  *
 #include "squid.h"
 #include "acl/FilledChecklist.h"
 #include "acl/Gadgets.h"
-#include "client_side_request.h"
 #include "client_side.h"
+#include "client_side_request.h"
 #include "comm/Connection.h"
 #include "compat/strtoll.h"
+#include "ConfigParser.h"
 #include "fde.h"
+#include "globals.h"
 #include "HttpHdrContRange.h"
 #include "HttpHeader.h"
+#include "HttpHeaderFieldInfo.h"
 #include "HttpHeaderTools.h"
 #include "HttpRequest.h"
 #include "MemBuf.h"
-#include "protos.h"
+#include "SquidConfig.h"
 #include "Store.h"
+#include "StrList.h"
 
-#if USE_SSL
+#if USE_OPENSSL
 #include "ssl/support.h"
 #endif
 
@@ -181,124 +183,6 @@ httpHeaderHasConnDir(const HttpHeader * hdr, const char *directive)
     return res;
 }
 
-/** returns true iff "m" is a member of the list */
-int
-strListIsMember(const String * list, const char *m, char del)
-{
-    const char *pos = NULL;
-    const char *item;
-    int ilen = 0;
-    int mlen;
-    assert(list && m);
-    mlen = strlen(m);
-
-    while (strListGetItem(list, del, &item, &ilen, &pos)) {
-        if (mlen == ilen && !strncasecmp(item, m, ilen))
-            return 1;
-    }
-
-    return 0;
-}
-
-/** returns true iff "s" is a substring of a member of the list */
-int
-strListIsSubstr(const String * list, const char *s, char del)
-{
-    assert(list && del);
-    return (list->find(s) != String::npos);
-
-    /** \note
-     * Note: the original code with a loop is broken because it uses strstr()
-     * instead of strnstr(). If 's' contains a 'del', strListIsSubstr() may
-     * return true when it should not. If 's' does not contain a 'del', the
-     * implementaion is equavalent to strstr()! Thus, we replace the loop with
-     * strstr() above until strnstr() is available.
-     */
-}
-
-/** appends an item to the list */
-void
-strListAdd(String * str, const char *item, char del)
-{
-    assert(str && item);
-
-    if (str->size()) {
-        char buf[3];
-        buf[0] = del;
-        buf[1] = ' ';
-        buf[2] = '\0';
-        str->append(buf, 2);
-    }
-
-    str->append(item, strlen(item));
-}
-
-/**
- * iterates through a 0-terminated string of items separated by 'del's.
- * white space around 'del' is considered to be a part of 'del'
- * like strtok, but preserves the source, and can iterate several strings at once
- *
- * returns true if next item is found.
- * init pos with NULL to start iteration.
- */
-int
-strListGetItem(const String * str, char del, const char **item, int *ilen, const char **pos)
-{
-    size_t len;
-    /* ',' is always enabled as field delimiter as this is required for
-     * processing merged header values properly, even if Cookie normally
-     * uses ';' as delimiter.
-     */
-    static char delim[3][8] = {
-        "\"?,",
-        "\"\\",
-        " ?,\t\r\n"
-    };
-    int quoted = 0;
-    assert(str && item && pos);
-
-    delim[0][1] = del;
-    delim[2][1] = del;
-
-    if (!*pos) {
-        *pos = str->termedBuf();
-
-        if (!*pos)
-            return 0;
-    }
-
-    /* skip leading whitespace and delimiters */
-    *pos += strspn(*pos, delim[2]);
-
-    *item = *pos;              /* remember item's start */
-
-    /* find next delimiter */
-    do {
-        *pos += strcspn(*pos, delim[quoted]);
-        if (**pos == '"') {
-            quoted = !quoted;
-            *pos += 1;
-        } else if (quoted && **pos == '\\') {
-            *pos += 1;
-            if (**pos)
-                *pos += 1;
-        } else {
-            break;             /* Delimiter found, marking the end of this value */
-        }
-    } while (**pos);
-
-    len = *pos - *item;                /* *pos points to del or '\0' */
-
-    /* rtrim */
-    while (len > 0 && xisspace((*item)[len - 1]))
-        --len;
-
-    if (ilen)
-        *ilen = len;
-
-    return len > 0;
-}
-
 /** handy to printf prefixes of potentially very long buffers */
 const char *
 getStringPrefix(const char *str, const char *end)
@@ -410,11 +294,41 @@ httpHeaderParseQuotedString(const char *start, const int len, String *val)
         return 0;
     }
     /* Make sure it's defined even if empty "" */
-    if (!val->defined())
+    if (!val->termedBuf())
         val->limitInit("", 0);
     return 1;
 }
 
+// TODO: Optimize using SBuf
+String
+httpHeaderQuoteString(const char *raw)
+{
+    assert(raw);
+
+    // HTTPbis says Senders SHOULD NOT escape octets in quoted-strings that
+    // do not require escaping (i.e., except DQUOTE and the backslash octet).
+    bool needInnerQuote = false;
+    for (const char *s = raw; !needInnerQuote &&  *s; ++s)
+        needInnerQuote = *s == '"' || *s == '\\';
+
+    static String quotedStr;
+    quotedStr.clean();
+    quotedStr.append('"');
+
+    if (needInnerQuote) {
+        for (const char *s = raw; *s; ++s) {
+            if (*s == '"' || *s == '\\')
+                quotedStr.append('\\');
+            quotedStr.append(*s);
+        }
+    } else {
+        quotedStr.append(raw);
+    }
+    
+    quotedStr.append('"');
+    return quotedStr;
+}
+
 /**
  * Checks the anonymizer (header_access) configuration.
  *
@@ -445,7 +359,7 @@ httpHdrMangle(HttpHeaderEntry * e, HttpRequest * request, int req_or_rep)
     if (!hms)
         return 1;
 
-    const header_mangler *hm = hms->find(*e);
+    const headerMangler *hm = hms->find(*e);
 
     /* mangler or checklist went away. default allow */
     if (!hm || !hm->access_list) {
@@ -489,7 +403,7 @@ httpHdrMangleList(HttpHeader * l, HttpRequest * request, int req_or_rep)
 }
 
 static
-void header_mangler_clean(header_mangler &m)
+void header_mangler_clean(headerMangler &m)
 {
     aclDestroyAccessList(&m.access_list);
     safe_free(m.replacement);
@@ -497,7 +411,7 @@ void header_mangler_clean(header_mangler &m)
 
 static
 void header_mangler_dump_access(StoreEntry * entry, const char *option,
-                                const header_mangler &m, const char *name)
+                                const headerMangler &m, const char *name)
 {
     if (m.access_list != NULL) {
         storeAppendPrintf(entry, "%s ", option);
@@ -507,7 +421,7 @@ void header_mangler_dump_access(StoreEntry * entry, const char *option,
 
 static
 void header_mangler_dump_replacement(StoreEntry * entry, const char *option,
-                                     const header_mangler &m, const char *name)
+                                     const headerMangler &m, const char *name)
 {
     if (m.replacement)
         storeAppendPrintf(entry, "%s %s %s\n", option, name, m.replacement);
@@ -563,7 +477,7 @@ HeaderManglers::dumpReplacement(StoreEntry * entry, const char *name) const
     header_mangler_dump_replacement(entry, name, all, "All");
 }
 
-header_mangler *
+headerMangler *
 HeaderManglers::track(const char *name)
 {
     int id = httpHeaderIdByNameDef(name, strlen(name));
@@ -575,7 +489,7 @@ HeaderManglers::track(const char *name)
             id = HDR_OTHER;
     }
 
-    header_mangler *m = NULL;
+    headerMangler *m = NULL;
     if (id == HDR_ENUM_END) {
         m = &all;
     } else if (id == HDR_BAD_HDR) {
@@ -593,13 +507,13 @@ HeaderManglers::setReplacement(const char *name, const char *value)
 {
     // for backword compatibility, we allow replacements to be configured
     // for headers w/o access rules, but such replacements are ignored
-    header_mangler *m = track(name);
+    headerMangler *m = track(name);
 
     safe_free(m->replacement); // overwrite old value if any
     m->replacement = xstrdup(value);
 }
 
-const header_mangler *
+const headerMangler *
 HeaderManglers::find(const HttpHeaderEntry &e) const
 {
     // a known header with a configured ACL list