/*
- * $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
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)
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.
*
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) {
}
static
-void header_mangler_clean(header_mangler &m)
+void header_mangler_clean(headerMangler &m)
{
aclDestroyAccessList(&m.access_list);
safe_free(m.replacement);
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);
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);
header_mangler_dump_replacement(entry, name, all, "All");
}
-header_mangler *
+headerMangler *
HeaderManglers::track(const char *name)
{
int id = httpHeaderIdByNameDef(name, strlen(name));
id = HDR_OTHER;
}
- header_mangler *m = NULL;
+ headerMangler *m = NULL;
if (id == HDR_ENUM_END) {
m = &all;
} else if (id == HDR_BAD_HDR) {
{
// 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