]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/cache_cf.cc
Removed squid-old.h
[thirdparty/squid.git] / src / cache_cf.cc
index 0e1c9242d22ef9b2e2df39d662555b11b38fea0b..58a693b974653e56305e0b74a51dc612a4e55b33 100644 (file)
  *
  */
 
-#include "squid-old.h"
-
+#include "squid.h"
 #include "acl/Acl.h"
 #include "acl/Gadgets.h"
 #include "acl/MethodData.h"
+#include "anyp/PortCfg.h"
+#include "base/RunnersRegistry.h"
+#include "ConfigParser.h"
+#include "CpuAffinityMap.h"
+#include "DiskIO/DiskIOModule.h"
+#include "eui/Config.h"
+#include "format/Format.h"
+#include "globals.h"
+#include "HttpRequestMethod.h"
+#include "ident/Config.h"
+#include "ip/Intercept.h"
+#include "ip/QosConfig.h"
+#include "ip/tools.h"
+#include "ipc/Kids.h"
+#include "log/Config.h"
+#include "MemBuf.h"
+#include "mgr/Registration.h"
+#include "Parsing.h"
+#include "protos.h"
+#include "rfc1738.h"
+#include "Store.h"
+#include "StoreFileSystem.h"
+#include "structs.h"
+#include "SwapDir.h"
+#include "wordlist.h"
 #if USE_ADAPTATION
 #include "adaptation/Config.h"
 #endif
@@ -46,7 +70,6 @@
 #if USE_ECAP
 #include "adaptation/ecap/Config.h"
 #endif
-#include "anyp/PortCfg.h"
 #if USE_SSL
 #include "ssl/support.h"
 #include "ssl/Config.h"
 #include "auth/Config.h"
 #include "auth/Scheme.h"
 #endif
-#include "base/RunnersRegistry.h"
-#include "ConfigParser.h"
-#include "CpuAffinityMap.h"
-#include "DiskIO/DiskIOModule.h"
-#include "eui/Config.h"
 #if USE_SQUID_ESI
 #include "esi/Parser.h"
 #endif
-#include "format/Format.h"
-#include "HttpRequestMethod.h"
-#include "ident/Config.h"
-#include "ip/Intercept.h"
-#include "ip/QosConfig.h"
-#include "ip/tools.h"
-#include "log/Config.h"
-#include "MemBuf.h"
-#include "mgr/Registration.h"
-#include "Parsing.h"
-#include "rfc1738.h"
 #if SQUID_SNMP
 #include "snmp.h"
 #endif
-#include "Store.h"
-#include "StoreFileSystem.h"
-#include "SwapDir.h"
-#include "wordlist.h"
-#include "ipc/Kids.h"
+
+
+
 
 #if HAVE_GLOB_H
 #include <glob.h>
 #include <limits>
 #endif
 
+#if HAVE_LIST
+#include <list>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_PWD_H
+#include <pwd.h>
+#endif
+#if HAVE_GRP_H
+#include <grp.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
 #if USE_SSL
 #include "ssl/gadgets.h"
 #endif
@@ -171,13 +192,17 @@ static void free_all(void);
 void requirePathnameExists(const char *name, const char *path);
 static OBJH dump_config;
 #if USE_HTTP_VIOLATIONS
-static void dump_http_header_access(StoreEntry * entry, const char *name, header_mangler header[]);
-static void parse_http_header_access(header_mangler header[]);
-static void free_http_header_access(header_mangler header[]);
-static void dump_http_header_replace(StoreEntry * entry, const char *name, header_mangler header[]);
-static void parse_http_header_replace(header_mangler * header);
-static void free_http_header_replace(header_mangler * header);
+static void free_HeaderManglers(HeaderManglers **pm);
+static void dump_http_header_access(StoreEntry * entry, const char *name, const HeaderManglers *manglers);
+static void parse_http_header_access(HeaderManglers **manglers);
+#define free_http_header_access free_HeaderManglers
+static void dump_http_header_replace(StoreEntry * entry, const char *name, const HeaderManglers *manglers);
+static void parse_http_header_replace(HeaderManglers **manglers);
+#define free_http_header_replace free_HeaderManglers
 #endif
+static void dump_HeaderWithAclList(StoreEntry * entry, const char *name, HeaderWithAclList *headers);
+static void parse_HeaderWithAclList(HeaderWithAclList **header);
+static void free_HeaderWithAclList(HeaderWithAclList **header);
 static void parse_denyinfo(acl_deny_info_list ** var);
 static void dump_denyinfo(StoreEntry * entry, const char *name, acl_deny_info_list * var);
 static void free_denyinfo(acl_deny_info_list ** var);
@@ -239,7 +264,7 @@ update_maxobjsize(void)
     int i;
     int64_t ms = -1;
 
-    for (i = 0; i < Config.cacheSwap.n_configured; i++) {
+    for (i = 0; i < Config.cacheSwap.n_configured; ++i) {
         assert (Config.cacheSwap.swapDirs[i].getRaw());
 
         if (dynamic_cast<SwapDir *>(Config.cacheSwap.swapDirs[i].getRaw())->
@@ -287,7 +312,7 @@ parseManyConfigFiles(char* files, int depth)
                    path, xstrerror());
         }
     }
-    for (i = 0; i < (int)globbuf.gl_pathc; i++) {
+    for (i = 0; i < (int)globbuf.gl_pathc; ++i) {
         error_count += parseOneConfigFile(globbuf.gl_pathv[i], depth);
     }
     globfree(&globbuf);
@@ -417,7 +442,7 @@ parseOneConfigFile(const char *file_name, unsigned int depth)
     int err_count = 0;
     int is_pipe = 0;
 
-    debugs(3, 1, "Processing Configuration File: " << file_name << " (depth " << depth << ")");
+    debugs(3, DBG_IMPORTANT, "Processing Configuration File: " << file_name << " (depth " << depth << ")");
     if (depth > 16) {
         fatalf("WARNING: can't include %s: includes are nested too deeply (>16)!\n", file_name);
         return 1;
@@ -445,7 +470,7 @@ parseOneConfigFile(const char *file_name, unsigned int depth)
 
     Vector<bool> if_states;
     while (fgets(config_input_line, BUFSIZ, fp)) {
-        config_lineno++;
+        ++config_lineno;
 
         if ((token = strchr(config_input_line, '\n')))
             *token = '\0';
@@ -469,7 +494,7 @@ parseOneConfigFile(const char *file_name, unsigned int depth)
                 continue;      /* Not a valid #line directive, may be a comment */
 
             while (*file && xisspace((unsigned char) *file))
-                file++;
+                ++file;
 
             if (*file) {
                 if (*file != '"')
@@ -529,8 +554,8 @@ parseOneConfigFile(const char *file_name, unsigned int depth)
             if (tmp_line_len >= 9 && strncmp(tmp_line, "include", 7) == 0 && xisspace(tmp_line[7])) {
                 err_count += parseManyConfigFiles(tmp_line + 8, depth + 1);
             } else if (!parse_line(tmp_line)) {
-                debugs(3, 0, HERE << cfg_filename << ":" << config_lineno << " unrecognized: '" << tmp_line << "'");
-                err_count++;
+                debugs(3, DBG_CRITICAL, HERE << cfg_filename << ":" << config_lineno << " unrecognized: '" << tmp_line << "'");
+                ++err_count;
             }
         }
 
@@ -625,7 +650,7 @@ configDoConfigure(void)
 
 #if SIZEOF_OFF_T <= 4
     if (Config.Store.maxObjectSize > 0x7FFF0000) {
-        debugs(3, 0, "WARNING: This Squid binary can not handle files larger than 2GB. Limiting maximum_object_size to just below 2GB");
+        debugs(3, DBG_CRITICAL, "WARNING: This Squid binary can not handle files larger than 2GB. Limiting maximum_object_size to just below 2GB");
         Config.Store.maxObjectSize = 0x7FFF0000;
     }
 #endif
@@ -634,7 +659,7 @@ configDoConfigure(void)
         (void) 0;
     else if (Store::Root().maxSize() < Config.memMaxSize)
         /* This is bogus. folk with NULL caches will want this */
-        debugs(3, 0, "WARNING cache_mem is larger than total disk cache space!");
+        debugs(3, DBG_CRITICAL, "WARNING cache_mem is larger than total disk cache space!");
 
     if (Config.Announce.period > 0) {
         Config.onoff.announce = 1;
@@ -736,7 +761,7 @@ configDoConfigure(void)
             if (!R->flags.override_expire)
                 continue;
 
-            debugs(22, 1, "WARNING: use of 'override-expire' in 'refresh_pattern' violates HTTP");
+            debugs(22, DBG_IMPORTANT, "WARNING: use of 'override-expire' in 'refresh_pattern' violates HTTP");
 
             break;
         }
@@ -745,7 +770,7 @@ configDoConfigure(void)
             if (!R->flags.override_lastmod)
                 continue;
 
-            debugs(22, 1, "WARNING: use of 'override-lastmod' in 'refresh_pattern' violates HTTP");
+            debugs(22, DBG_IMPORTANT, "WARNING: use of 'override-lastmod' in 'refresh_pattern' violates HTTP");
 
             break;
         }
@@ -754,7 +779,7 @@ configDoConfigure(void)
             if (!R->flags.reload_into_ims)
                 continue;
 
-            debugs(22, 1, "WARNING: use of 'reload-into-ims' in 'refresh_pattern' violates HTTP");
+            debugs(22, DBG_IMPORTANT, "WARNING: use of 'reload-into-ims' in 'refresh_pattern' violates HTTP");
 
             break;
         }
@@ -763,7 +788,7 @@ configDoConfigure(void)
             if (!R->flags.ignore_reload)
                 continue;
 
-            debugs(22, 1, "WARNING: use of 'ignore-reload' in 'refresh_pattern' violates HTTP");
+            debugs(22, DBG_IMPORTANT, "WARNING: use of 'ignore-reload' in 'refresh_pattern' violates HTTP");
 
             break;
         }
@@ -772,7 +797,7 @@ configDoConfigure(void)
             if (!R->flags.ignore_no_cache)
                 continue;
 
-            debugs(22, 1, "WARNING: use of 'ignore-no-cache' in 'refresh_pattern' violates HTTP");
+            debugs(22, DBG_IMPORTANT, "WARNING: use of 'ignore-no-cache' in 'refresh_pattern' violates HTTP");
 
             break;
         }
@@ -781,7 +806,7 @@ configDoConfigure(void)
             if (!R->flags.ignore_no_store)
                 continue;
 
-            debugs(22, 1, "WARNING: use of 'ignore-no-store' in 'refresh_pattern' violates HTTP");
+            debugs(22, DBG_IMPORTANT, "WARNING: use of 'ignore-no-store' in 'refresh_pattern' violates HTTP");
 
             break;
         }
@@ -789,7 +814,7 @@ configDoConfigure(void)
         for (R = Config.Refresh; R; R = R->next) {
             if (!R->flags.ignore_must_revalidate)
                 continue;
-            debugs(22, 1, "WARNING: use of 'ignore-must-revalidate' in 'refresh_pattern' violates HTTP");
+            debugs(22, DBG_IMPORTANT, "WARNING: use of 'ignore-must-revalidate' in 'refresh_pattern' violates HTTP");
             break;
         }
 
@@ -797,7 +822,7 @@ configDoConfigure(void)
             if (!R->flags.ignore_private)
                 continue;
 
-            debugs(22, 1, "WARNING: use of 'ignore-private' in 'refresh_pattern' violates HTTP");
+            debugs(22, DBG_IMPORTANT, "WARNING: use of 'ignore-private' in 'refresh_pattern' violates HTTP");
 
             break;
         }
@@ -806,7 +831,7 @@ configDoConfigure(void)
             if (!R->flags.ignore_auth)
                 continue;
 
-            debugs(22, 1, "WARNING: use of 'ignore-auth' in 'refresh_pattern' violates HTTP");
+            debugs(22, DBG_IMPORTANT, "WARNING: use of 'ignore-auth' in 'refresh_pattern' violates HTTP");
 
             break;
         }
@@ -818,7 +843,7 @@ configDoConfigure(void)
 #else
 
     if (!Config.onoff.via)
-        debugs(22, 1, "WARNING: HTTP requires the use of Via");
+        debugs(22, DBG_IMPORTANT, "WARNING: HTTP requires the use of Via");
 
 #endif
 
@@ -826,7 +851,7 @@ configDoConfigure(void)
     // TODO: replace with a dedicated "purge" ACL option?
     Config2.onoff.enable_purge = (ACLMethodData::ThePurgeCount > 0);
 
-    Config2.onoff.mangle_request_headers = httpReqHdrManglersConfigured();
+    Config2.onoff.mangle_request_headers = (Config.request_header_access != NULL);
 
     if (geteuid() == 0) {
         if (NULL != Config.effectiveUser) {
@@ -885,13 +910,13 @@ configDoConfigure(void)
     HttpRequestMethod::Configure(Config);
 #if USE_SSL
 
-    debugs(3, 1, "Initializing https proxy context");
+    debugs(3, DBG_IMPORTANT, "Initializing https proxy context");
 
     Config.ssl_client.sslContext = sslCreateClientContext(Config.ssl_client.cert, Config.ssl_client.key, Config.ssl_client.version, Config.ssl_client.cipher, Config.ssl_client.options, Config.ssl_client.flags, Config.ssl_client.cafile, Config.ssl_client.capath, Config.ssl_client.crlfile);
 
     for (peer *p = Config.peers; p != NULL; p = p->next) {
         if (p->use_ssl) {
-            debugs(3, 1, "Initializing cache_peer " << p->name << " SSL context");
+            debugs(3, DBG_IMPORTANT, "Initializing cache_peer " << p->name << " SSL context");
             p->sslContext = sslCreateClientContext(p->sslcert, p->sslkey, p->sslversion, p->sslcipher, p->ssloptions, p->sslflags, p->sslcafile, p->sslcapath, p->sslcrlfile);
         }
     }
@@ -900,12 +925,12 @@ configDoConfigure(void)
         if (!s->sslBump)
             continue;
 
-        debugs(3, 1, "Initializing http_port " << s->s << " SSL context");
+        debugs(3, DBG_IMPORTANT, "Initializing http_port " << s->s << " SSL context");
         s->configureSslServerContext();
     }
 
     for (AnyP::PortCfg *s = Config.Sockaddr.https; s != NULL; s = s->next) {
-        debugs(3, 1, "Initializing https_port " << s->s << " SSL context");
+        debugs(3, DBG_IMPORTANT, "Initializing https_port " << s->s << " SSL context");
         s->configureSslServerContext();
     }
 
@@ -979,7 +1004,7 @@ parseTimeLine(time_msec_t * tptr, const char *units,  bool allowMsec)
     if (0 == d)
         (void) 0;
     else if ((token = strtok(NULL, w_space)) == NULL)
-        debugs(3, 0, "WARNING: No units on '" <<
+        debugs(3, DBG_CRITICAL, "WARNING: No units on '" <<
                config_input_line << "', assuming " <<
                d << " " << units  );
     else if ((m = parseTimeUnits(token, allowMsec)) == 0)
@@ -1021,7 +1046,7 @@ parseTimeUnits(const char *unit, bool allowMsec)
     if (!strncasecmp(unit, T_DECADE_STR, strlen(T_DECADE_STR)))
         return static_cast<uint64_t>(86400 * 1000 * 365.2522 * 10);
 
-    debugs(3, 1, "parseTimeUnits: unknown time unit '" << unit << "'");
+    debugs(3, DBG_IMPORTANT, "parseTimeUnits: unknown time unit '" << unit << "'");
 
     return 0;
 }
@@ -1056,7 +1081,7 @@ parseBytesLine64(int64_t * bptr, const char *units)
     if (0.0 == d)
         (void) 0;
     else if ((token = strtok(NULL, w_space)) == NULL)
-        debugs(3, 0, "WARNING: No units on '" <<
+        debugs(3, DBG_CRITICAL, "WARNING: No units on '" <<
                config_input_line << "', assuming " <<
                d << " " <<  units  );
     else if ((m = parseBytesUnits(token)) == 0) {
@@ -1101,7 +1126,7 @@ parseBytesLine(size_t * bptr, const char *units)
     if (0.0 == d)
         (void) 0;
     else if ((token = strtok(NULL, w_space)) == NULL)
-        debugs(3, 0, "WARNING: No units on '" <<
+        debugs(3, DBG_CRITICAL, "WARNING: No units on '" <<
                config_input_line << "', assuming " <<
                d << " " <<  units  );
     else if ((m = parseBytesUnits(token)) == 0) {
@@ -1146,7 +1171,7 @@ parseBytesLineSigned(ssize_t * bptr, const char *units)
     if (0.0 == d)
         (void) 0;
     else if ((token = strtok(NULL, w_space)) == NULL)
-        debugs(3, 0, "WARNING: No units on '" <<
+        debugs(3, DBG_CRITICAL, "WARNING: No units on '" <<
                config_input_line << "', assuming " <<
                d << " " <<  units  );
     else if ((m = parseBytesUnits(token)) == 0) {
@@ -1180,7 +1205,7 @@ static void parseBytesOptionValue(size_t * bptr, const char *units, char const *
     char const * number_end = value;
 
     while ((*number_end >= '0' && *number_end <= '9')) {
-        number_end++;
+        ++number_end;
     }
 
     String number;
@@ -1679,135 +1704,65 @@ parse_client_delay_pool_access(ClientDelayConfig * cfg)
 
 #if USE_HTTP_VIOLATIONS
 static void
-dump_http_header_access(StoreEntry * entry, const char *name, header_mangler header[])
+dump_http_header_access(StoreEntry * entry, const char *name, const HeaderManglers *manglers)
 {
-    int i;
-
-    for (i = 0; i < HDR_ENUM_END; i++) {
-        if (header[i].access_list != NULL) {
-            storeAppendPrintf(entry, "%s ", name);
-            dump_acl_access(entry, httpHeaderNameById(i),
-                            header[i].access_list);
-        }
-    }
+    if (manglers)
+        manglers->dumpAccess(entry, name);
 }
 
 static void
-parse_http_header_access(header_mangler header[])
+parse_http_header_access(HeaderManglers **pm)
 {
-    int id, i;
     char *t = NULL;
 
     if ((t = strtok(NULL, w_space)) == NULL) {
-        debugs(3, 0, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
-        debugs(3, 0, "parse_http_header_access: missing header name.");
-        return;
-    }
-
-    /* Now lookup index of header. */
-    id = httpHeaderIdByNameDef(t, strlen(t));
-
-    if (strcmp(t, "All") == 0)
-        id = HDR_ENUM_END;
-    else if (strcmp(t, "Other") == 0)
-        id = HDR_OTHER;
-    else if (id == -1) {
-        debugs(3, 0, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
-        debugs(3, 0, "parse_http_header_access: unknown header name '" << t << "'");
+        debugs(3, DBG_CRITICAL, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
+        debugs(3, DBG_CRITICAL, "parse_http_header_access: missing header name.");
         return;
     }
 
-    if (id != HDR_ENUM_END) {
-        parse_acl_access(&header[id].access_list);
-    } else {
-        char *next_string = t + strlen(t) - 1;
-        *next_string = 'A';
-        *(next_string + 1) = ' ';
-
-        for (i = 0; i < HDR_ENUM_END; i++) {
-            char *new_string = xstrdup(next_string);
-            strtok(new_string, w_space);
-            parse_acl_access(&header[i].access_list);
-            safe_free(new_string);
-        }
-    }
+    if (!*pm)
+        *pm = new HeaderManglers;
+    HeaderManglers *manglers = *pm;
+    header_mangler *mangler = manglers->track(t);
+    assert(mangler);
+    parse_acl_access(&mangler->access_list);
 }
 
 static void
-free_http_header_access(header_mangler header[])
+free_HeaderManglers(HeaderManglers **pm)
 {
-    int i;
-
-    for (i = 0; i < HDR_ENUM_END; i++) {
-        free_acl_access(&header[i].access_list);
+    // we delete the entire http_header_* mangler configuration at once
+    if (const HeaderManglers *manglers = *pm) {
+        delete manglers;
+        *pm = NULL;
     }
 }
 
 static void
-dump_http_header_replace(StoreEntry * entry, const char *name, header_mangler
-                         header[])
+dump_http_header_replace(StoreEntry * entry, const char *name, const HeaderManglers *manglers)
 {
-    int i;
-
-    for (i = 0; i < HDR_ENUM_END; i++) {
-        if (NULL == header[i].replacement)
-            continue;
-
-        storeAppendPrintf(entry, "%s %s %s\n", name, httpHeaderNameById(i),
-                          header[i].replacement);
-    }
+    if (manglers)
+        manglers->dumpReplacement(entry, name);
 }
 
 static void
-parse_http_header_replace(header_mangler header[])
+parse_http_header_replace(HeaderManglers **pm)
 {
-    int id, i;
     char *t = NULL;
 
     if ((t = strtok(NULL, w_space)) == NULL) {
-        debugs(3, 0, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
-        debugs(3, 0, "parse_http_header_replace: missing header name.");
-        return;
-    }
-
-    /* Now lookup index of header. */
-    id = httpHeaderIdByNameDef(t, strlen(t));
-
-    if (strcmp(t, "All") == 0)
-        id = HDR_ENUM_END;
-    else if (strcmp(t, "Other") == 0)
-        id = HDR_OTHER;
-    else if (id == -1) {
-        debugs(3, 0, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
-        debugs(3, 0, "parse_http_header_replace: unknown header name " << t << ".");
-
+        debugs(3, DBG_CRITICAL, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
+        debugs(3, DBG_CRITICAL, "parse_http_header_replace: missing header name.");
         return;
     }
 
-    if (id != HDR_ENUM_END) {
-        if (header[id].replacement != NULL)
-            safe_free(header[id].replacement);
+    const char *value = t + strlen(t) + 1;
 
-        header[id].replacement = xstrdup(t + strlen(t) + 1);
-    } else {
-        for (i = 0; i < HDR_ENUM_END; i++) {
-            if (header[i].replacement != NULL)
-                safe_free(header[i].replacement);
-
-            header[i].replacement = xstrdup(t + strlen(t) + 1);
-        }
-    }
-}
-
-static void
-free_http_header_replace(header_mangler header[])
-{
-    int i;
-
-    for (i = 0; i < HDR_ENUM_END; i++) {
-        if (header[i].replacement != NULL)
-            safe_free(header[i].replacement);
-    }
+    if (!*pm)
+        *pm = new HeaderManglers;
+    HeaderManglers *manglers = *pm;
+    manglers->setReplacement(t, value);
 }
 
 #endif
@@ -1819,7 +1774,7 @@ dump_cachedir(StoreEntry * entry, const char *name, SquidConfig::_cacheSwap swap
     int i;
     assert (entry);
 
-    for (i = 0; i < swap.n_configured; i++) {
+    for (i = 0; i < swap.n_configured; ++i) {
         s = dynamic_cast<SwapDir *>(swap.swapDirs[i].getRaw());
         if (!s) continue;
         storeAppendPrintf(entry, "%s %s %s", name, s->type(), s->path);
@@ -1928,7 +1883,7 @@ parse_cachedir(SquidConfig::_cacheSwap * swap)
 
     /* reconfigure existing dir */
 
-    for (i = 0; i < swap->n_configured; i++) {
+    for (i = 0; i < swap->n_configured; ++i) {
         assert (swap->swapDirs[i].getRaw());
 
         if ((strcasecmp(path_str, dynamic_cast<SwapDir *>(swap->swapDirs[i].getRaw())->path)) == 0) {
@@ -1942,7 +1897,7 @@ parse_cachedir(SquidConfig::_cacheSwap * swap)
             sd = dynamic_cast<SwapDir *>(swap->swapDirs[i].getRaw());
 
             if (strcmp(sd->type(), StoreFileSystem::FileSystems().items[fs]->type()) != 0) {
-                debugs(3, 0, "ERROR: Can't change type of existing cache_dir " <<
+                debugs(3, DBG_CRITICAL, "ERROR: Can't change type of existing cache_dir " <<
                        sd->type() << " " << sd->path << " to " << type_str << ". Restart required");
                 return;
             }
@@ -2055,7 +2010,7 @@ isUnsignedNumeric(const char *str, size_t len)
 {
     if (len < 1) return false;
 
-    for (; len >0 && *str; str++, len--) {
+    for (; len >0 && *str; ++str, --len) {
         if (! isdigit(*str))
             return false;
     }
@@ -2191,8 +2146,10 @@ parse_peer(peer ** head)
             char *mode, *nextmode;
             for (mode = nextmode = tmp; mode; mode = nextmode) {
                 nextmode = strchr(mode, ',');
-                if (nextmode)
-                    *nextmode++ = '\0';
+                if (nextmode) {
+                    *nextmode = '\0';
+                    ++nextmode;
+                }
                 if (!strcasecmp(mode, "no-clr")) {
                     if (p->options.htcp_only_clr)
                         fatalf("parse_peer: can't set htcp-no-clr and htcp-only-clr simultaneously");
@@ -2343,7 +2300,7 @@ parse_peer(peer ** head)
         } else if (strcmp(token, "connection-auth=auto") == 0) {
             p->connection_auth = 2;
         } else {
-            debugs(3, 0, "parse_peer: token='" << token << "'");
+            debugs(3, DBG_CRITICAL, "parse_peer: token='" << token << "'");
             self_destruct();
         }
     }
@@ -2451,7 +2408,7 @@ parse_cachemgrpasswd(cachemgr_passwd ** head)
                 if (strcmp(w->key, u->key))
                     continue;
 
-                debugs(0, 0, "WARNING: action '" << u->key << "' (line " << config_lineno << ") already has a password");
+                debugs(0, DBG_CRITICAL, "WARNING: action '" << u->key << "' (line " << config_lineno << ") already has a password");
             }
         }
     }
@@ -2528,7 +2485,7 @@ parse_peer_access(void)
         self_destruct();
 
     if ((p = peerFindByName(host)) == NULL) {
-        debugs(15, 0, "" << cfg_filename << ", line " << config_lineno << ": No cache_peer '" << host << "'");
+        debugs(15, DBG_CRITICAL, "" << cfg_filename << ", line " << config_lineno << ": No cache_peer '" << host << "'");
         return;
     }
 
@@ -2550,7 +2507,7 @@ parse_hostdomain(void)
         peer *p;
 
         if ((p = peerFindByName(host)) == NULL) {
-            debugs(15, 0, "" << cfg_filename << ", line " << config_lineno << ": No cache_peer '" << host << "'");
+            debugs(15, DBG_CRITICAL, "" << cfg_filename << ", line " << config_lineno << ": No cache_peer '" << host << "'");
             continue;
         }
 
@@ -2559,7 +2516,7 @@ parse_hostdomain(void)
 
         if (*domain == '!') {  /* check for !.edu */
             l->do_ping = 0;
-            domain++;
+            ++domain;
         }
 
         l->domain = xstrdup(domain);
@@ -2588,7 +2545,7 @@ parse_hostdomaintype(void)
         peer *p;
 
         if ((p = peerFindByName(host)) == NULL) {
-            debugs(15, 0, "" << cfg_filename << ", line " << config_lineno << ": No cache_peer '" << host << "'");
+            debugs(15, DBG_CRITICAL, "" << cfg_filename << ", line " << config_lineno << ": No cache_peer '" << host << "'");
             return;
         }
 
@@ -2852,14 +2809,14 @@ parse_refreshpattern(refresh_t ** head)
 #endif
 
         } else
-            debugs(22, 0, "refreshAddToList: Unknown option '" << pattern << "': " << token);
+            debugs(22, DBG_CRITICAL, "refreshAddToList: Unknown option '" << pattern << "': " << token);
     }
 
     if ((errcode = regcomp(&comp, pattern, flags)) != 0) {
         char errbuf[256];
         regerror(errcode, &comp, errbuf, sizeof errbuf);
-        debugs(22, 0, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
-        debugs(22, 0, "refreshAddToList: Invalid regular expression '" << pattern << "': " << errbuf);
+        debugs(22, DBG_CRITICAL, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
+        debugs(22, DBG_CRITICAL, "refreshAddToList: Invalid regular expression '" << pattern << "': " << errbuf);
         return;
     }
 
@@ -3001,7 +2958,7 @@ parse_eol(char *volatile *var)
     }
 
     while (*token && xisspace(*token))
-        token++;
+        ++token;
 
     if (!*token) {
         self_destruct();
@@ -3039,7 +2996,7 @@ static void
 dump_time_msec(StoreEntry * entry, const char *name, time_msec_t var)
 {
     if (var % 1000)
-        storeAppendPrintf(entry, "%s %"PRId64" milliseconds\n", name, var);
+        storeAppendPrintf(entry, "%s %" PRId64 " milliseconds\n", name, var);
     else
         storeAppendPrintf(entry, "%s %d seconds\n", name, (int)(var/1000) );
 }
@@ -3090,13 +3047,13 @@ dump_kb_size_t(StoreEntry * entry, const char *name, size_t var)
 static void
 dump_b_int64_t(StoreEntry * entry, const char *name, int64_t var)
 {
-    storeAppendPrintf(entry, "%s %"PRId64" %s\n", name, var, B_BYTES_STR);
+    storeAppendPrintf(entry, "%s %" PRId64 " %s\n", name, var, B_BYTES_STR);
 }
 
 static void
 dump_kb_int64_t(StoreEntry * entry, const char *name, int64_t var)
 {
-    storeAppendPrintf(entry, "%s %"PRId64" %s\n", name, var, B_KBYTES_STR);
+    storeAppendPrintf(entry, "%s %" PRId64 " %s\n", name, var, B_KBYTES_STR);
 }
 
 #if UNUSED_CODE
@@ -3432,7 +3389,7 @@ parseNeighborType(const char *s)
     if (!strcasecmp(s, "multicast"))
         return PEER_MULTICAST;
 
-    debugs(15, 0, "WARNING: Unknown neighbor type: " << s);
+    debugs(15, DBG_CRITICAL, "WARNING: Unknown neighbor type: " << s);
 
     return PEER_SIBLING;
 }
@@ -3513,7 +3470,8 @@ parsePortSpecification(AnyP::PortCfg * s, char *token)
             debugs(3, DBG_CRITICAL, s->protocol << "_port: missing ']' on IPv6 address: " << token);
             self_destruct();
         }
-        *t++ = '\0';
+        *t = '\0';
+        ++t;
         if (*t != ':') {
             debugs(3, DBG_CRITICAL, s->protocol << "_port: missing Port in: " << token);
             self_destruct();
@@ -3699,12 +3657,12 @@ parse_port_option(AnyP::PortCfg * s, char *token)
         s->tcp_keepalive.idle = atoi(t);
         t = strchr(t, ',');
         if (t) {
-            t++;
+            ++t;
             s->tcp_keepalive.interval = atoi(t);
             t = strchr(t, ',');
         }
         if (t) {
-            t++;
+            ++t;
             s->tcp_keepalive.timeout = atoi(t);
             t = strchr(t, ',');
         }
@@ -4064,7 +4022,7 @@ parse_access_log(customlog ** logs)
         cl->type = Log::Format::CLF_CUSTOM;
         cl->logFormat = lf;
     } else if (strcmp(logdef_name, "auto") == 0) {
-        debugs(0,0, "WARNING: Log format 'auto' no longer exists. Using 'squid' instead.");
+        debugs(0, DBG_CRITICAL, "WARNING: Log format 'auto' no longer exists. Using 'squid' instead.");
         cl->type = Log::Format::CLF_SQUID;
     } else if (strcmp(logdef_name, "squid") == 0) {
         cl->type = Log::Format::CLF_SQUID;
@@ -4081,7 +4039,7 @@ parse_access_log(customlog ** logs)
     } else if (strcmp(logdef_name, "referrer") == 0) {
         cl->type = Log::Format::CLF_REFERER;
     } else {
-        debugs(3, 0, "Log format '" << logdef_name << "' is not defined");
+        debugs(3, DBG_CRITICAL, "Log format '" << logdef_name << "' is not defined");
         self_destruct();
         return;
     }
@@ -4313,7 +4271,7 @@ dump_icap_service_type(StoreEntry * entry, const char *name, const Adaptation::I
 static void
 parse_icap_class_type()
 {
-    debugs(93, 0, "WARNING: 'icap_class' is depricated. " <<
+    debugs(93, DBG_CRITICAL, "WARNING: 'icap_class' is depricated. " <<
            "Use 'adaptation_service_set' instead");
     Adaptation::Config::ParseServiceSet();
 }
@@ -4321,7 +4279,7 @@ parse_icap_class_type()
 static void
 parse_icap_access_type()
 {
-    debugs(93, 0, "WARNING: 'icap_access' is depricated. " <<
+    debugs(93, DBG_CRITICAL, "WARNING: 'icap_access' is depricated. " <<
            "Use 'adaptation_access' instead");
     Adaptation::Config::ParseAccess(LegacyParser);
 }
@@ -4363,7 +4321,7 @@ static void parse_icap_service_failure_limit(Adaptation::Icap::Config *cfg)
         return;
 
     if (strcmp(token,"in") != 0) {
-        debugs(3, 0, "expecting 'in' on'"  << config_input_line << "'");
+        debugs(3, DBG_CRITICAL, "expecting 'in' on'"  << config_input_line << "'");
         self_destruct();
     }
 
@@ -4378,7 +4336,7 @@ static void parse_icap_service_failure_limit(Adaptation::Icap::Config *cfg)
     if (0 == d)
         (void) 0;
     else if ((token = strtok(NULL, w_space)) == NULL) {
-        debugs(3, 0, "No time-units on '" << config_input_line << "'");
+        debugs(3, DBG_CRITICAL, "No time-units on '" << config_input_line << "'");
         self_destruct();
     } else if ((m = parseTimeUnits(token, false)) == 0)
         self_destruct();
@@ -4411,11 +4369,11 @@ static void parse_sslproxy_cert_adapt(sslproxy_cert_adapt **cert_adapt)
         self_destruct();
         return;
     }
-    
+
     const char *param;
     if ( char *s = strchr(al, '{')) {
         *s = '\0'; // terminate the al string
-        s++;
+        ++s;
         param = s;
         s = strchr(s, '}');
         if (!s) {
@@ -4423,19 +4381,16 @@ static void parse_sslproxy_cert_adapt(sslproxy_cert_adapt **cert_adapt)
             return;
         }
         *s = '\0';
-    }
-    else
+    } else
         param = NULL;
 
     if (strcmp(al, Ssl::CertAdaptAlgorithmStr[Ssl::algSetValidAfter]) == 0) {
         ca->alg = Ssl::algSetValidAfter;
         ca->param = strdup("on");
-    }
-    else if (strcmp(al, Ssl::CertAdaptAlgorithmStr[Ssl::algSetValidBefore]) == 0) {
+    } else if (strcmp(al, Ssl::CertAdaptAlgorithmStr[Ssl::algSetValidBefore]) == 0) {
         ca->alg = Ssl::algSetValidBefore;
         ca->param = strdup("on");
-    }
-    else if (strcmp(al, Ssl::CertAdaptAlgorithmStr[Ssl::algSetCommonName]) == 0) {
+    } else if (strcmp(al, Ssl::CertAdaptAlgorithmStr[Ssl::algSetCommonName]) == 0) {
         ca->alg = Ssl::algSetCommonName;
         if (param) {
             if (strlen(param) > 64) {
@@ -4453,7 +4408,7 @@ static void parse_sslproxy_cert_adapt(sslproxy_cert_adapt **cert_adapt)
 
     aclParseAclList(LegacyParser, &ca->aclList);
 
-    while(*cert_adapt)
+    while (*cert_adapt)
         cert_adapt = &(*cert_adapt)->next;
 
     *cert_adapt = ca;
@@ -4472,7 +4427,7 @@ static void dump_sslproxy_cert_adapt(StoreEntry *entry, const char *name, sslpro
 
 static void free_sslproxy_cert_adapt(sslproxy_cert_adapt **cert_adapt)
 {
-    while(*cert_adapt) {
+    while (*cert_adapt) {
         sslproxy_cert_adapt *ca = *cert_adapt;
         *cert_adapt = ca->next;
         safe_free(ca->param);
@@ -4507,7 +4462,7 @@ static void parse_sslproxy_cert_sign(sslproxy_cert_sign **cert_sign)
 
     aclParseAclList(LegacyParser, &cs->aclList);
 
-    while(*cert_sign)
+    while (*cert_sign)
         cert_sign = &(*cert_sign)->next;
 
     *cert_sign = cs;
@@ -4527,7 +4482,7 @@ static void dump_sslproxy_cert_sign(StoreEntry *entry, const char *name, sslprox
 
 static void free_sslproxy_cert_sign(sslproxy_cert_sign **cert_sign)
 {
-    while(*cert_sign) {
+    while (*cert_sign) {
         sslproxy_cert_sign *cs = *cert_sign;
         *cert_sign = cs->next;
 
@@ -4625,7 +4580,7 @@ static void parse_sslproxy_ssl_bump(acl_access **ssl_bump)
     }
 
     if (bumpCfgStyleLast != bcsNone && bumpCfgStyleNow != bumpCfgStyleLast) {
-        debugs(3, DBG_CRITICAL, "FATAL: do not mix " << bumpCfgStyleNow << " actions with " << 
+        debugs(3, DBG_CRITICAL, "FATAL: do not mix " << bumpCfgStyleNow << " actions with " <<
                bumpCfgStyleLast << " actions. Update your ssl_bump rules.");
         self_destruct();
         return;
@@ -4658,3 +4613,68 @@ static void free_sslproxy_ssl_bump(acl_access **ssl_bump)
 }
 
 #endif
+
+static void dump_HeaderWithAclList(StoreEntry * entry, const char *name, HeaderWithAclList *headers)
+{
+    if (!headers)
+        return;
+
+    for (HeaderWithAclList::iterator hwa = headers->begin(); hwa != headers->end(); ++hwa) {
+        storeAppendPrintf(entry, "%s ", hwa->fieldName.c_str());
+        storeAppendPrintf(entry, "%s ", hwa->fieldValue.c_str());
+        if (hwa->aclList)
+            dump_acl_list(entry, hwa->aclList);
+        storeAppendPrintf(entry, "\n");
+    }
+}
+
+static void parse_HeaderWithAclList(HeaderWithAclList **headers)
+{
+    char *fn;
+    if (!*headers) {
+        *headers = new HeaderWithAclList;
+    }
+    if ((fn = strtok(NULL, w_space)) == NULL) {
+        self_destruct();
+        return;
+    }
+    HeaderWithAcl hwa;
+    hwa.fieldName = fn;
+    hwa.fieldId = httpHeaderIdByNameDef(fn, strlen(fn));
+    if (hwa.fieldId == HDR_BAD_HDR)
+        hwa.fieldId = HDR_OTHER;
+
+    String buf;
+    bool wasQuoted;
+    ConfigParser::ParseQuotedString(&buf, &wasQuoted);
+    hwa.fieldValue = buf.termedBuf();
+    hwa.quoted = wasQuoted;
+    if (hwa.quoted) {
+        Format::Format *nlf =  new ::Format::Format("hdrWithAcl");
+        if (!nlf->parse(hwa.fieldValue.c_str())) {
+            self_destruct();
+            return;
+        }
+        hwa.valueFormat = nlf;
+    }
+    aclParseAclList(LegacyParser, &hwa.aclList);
+    (*headers)->push_back(hwa);
+}
+
+static void free_HeaderWithAclList(HeaderWithAclList **header)
+{
+    if (!(*header))
+        return;
+
+    for (HeaderWithAclList::iterator hwa = (*header)->begin(); hwa != (*header)->end(); ++hwa) {
+        if (hwa->aclList)
+            aclDestroyAclList(&hwa->aclList);
+
+        if (hwa->valueFormat) {
+            delete hwa->valueFormat;
+            hwa->valueFormat = NULL;
+        }
+    }
+    delete *header;
+    *header = NULL;
+}