]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/HttpHdrCc.cc
Source Format Enforcement (#1234)
[thirdparty/squid.git] / src / HttpHdrCc.cc
index 3ffd29a5baf916aae1cacfd26f3d30070d7078b9..b95b133e615c330e5c1ab6783d286763df17c4c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
@@ -15,7 +15,7 @@
 #include "HttpHeaderFieldStat.h"
 #include "HttpHeaderStat.h"
 #include "HttpHeaderTools.h"
-#include "SBuf.h"
+#include "sbuf/SBuf.h"
 #include "StatHist.h"
 #include "Store.h"
 #include "StrList.h"
 
 #include <map>
 #include <vector>
+#include <ostream>
 
 // invariant: row[j].id == j
-static LookupTable<http_hdr_cc_type>::Record CcAttrs[] = {
-    {"public", CC_PUBLIC},
-    {"private", CC_PRIVATE},
-    {"no-cache", CC_NO_CACHE},
-    {"no-store", CC_NO_STORE},
-    {"no-transform", CC_NO_TRANSFORM},
-    {"must-revalidate", CC_MUST_REVALIDATE},
-    {"proxy-revalidate", CC_PROXY_REVALIDATE},
-    {"max-age", CC_MAX_AGE},
-    {"s-maxage", CC_S_MAXAGE},
-    {"max-stale", CC_MAX_STALE},
-    {"min-fresh", CC_MIN_FRESH},
-    {"only-if-cached", CC_ONLY_IF_CACHED},
-    {"stale-if-error", CC_STALE_IF_ERROR},
-    {"Other,", CC_OTHER}, /* ',' will protect from matches */
-    {nullptr, CC_ENUM_END}
+static LookupTable<HttpHdrCcType>::Record CcAttrs[] = {
+    {"public", HttpHdrCcType::CC_PUBLIC},
+    {"private", HttpHdrCcType::CC_PRIVATE},
+    {"no-cache", HttpHdrCcType::CC_NO_CACHE},
+    {"no-store", HttpHdrCcType::CC_NO_STORE},
+    {"no-transform", HttpHdrCcType::CC_NO_TRANSFORM},
+    {"must-revalidate", HttpHdrCcType::CC_MUST_REVALIDATE},
+    {"proxy-revalidate", HttpHdrCcType::CC_PROXY_REVALIDATE},
+    {"max-age", HttpHdrCcType::CC_MAX_AGE},
+    {"s-maxage", HttpHdrCcType::CC_S_MAXAGE},
+    {"max-stale", HttpHdrCcType::CC_MAX_STALE},
+    {"min-fresh", HttpHdrCcType::CC_MIN_FRESH},
+    {"only-if-cached", HttpHdrCcType::CC_ONLY_IF_CACHED},
+    {"stale-if-error", HttpHdrCcType::CC_STALE_IF_ERROR},
+    {"immutable", HttpHdrCcType::CC_IMMUTABLE},
+    {"Other,", HttpHdrCcType::CC_OTHER}, /* ',' will protect from matches */
+    {nullptr, HttpHdrCcType::CC_ENUM_END}
 };
-LookupTable<http_hdr_cc_type> ccLookupTable(CC_OTHER,CcAttrs);
-std::vector<HttpHeaderFieldStat> ccHeaderStats(CC_ENUM_END);
+LookupTable<HttpHdrCcType> ccLookupTable(HttpHdrCcType::CC_OTHER,CcAttrs);
+std::vector<HttpHeaderFieldStat> ccHeaderStats(HttpHdrCcType::CC_ENUM_END);
 
 /// used to walk a table of http_header_cc_type structs
-http_hdr_cc_type &operator++ (http_hdr_cc_type &aHeader)
+static HttpHdrCcType &
+operator++ (HttpHdrCcType &aHeader)
 {
     int tmp = (int)aHeader;
-    aHeader = (http_hdr_cc_type)(++tmp);
+    aHeader = (HttpHdrCcType)(++tmp);
     return aHeader;
 }
 
@@ -58,21 +61,34 @@ void
 httpHdrCcInitModule(void)
 {
     // check invariant on initialization table
-    for (int j = 0; CcAttrs[j].name != nullptr; ++j) {
-        assert (CcAttrs[j].id == j);
+    for (unsigned int j = 0; CcAttrs[j].name != nullptr; ++j) {
+        assert(static_cast<decltype(j)>(CcAttrs[j].id) == j);
     }
 }
 
-/// Module cleanup hook.
 void
-httpHdrCcCleanModule(void)
+HttpHdrCc::clear()
 {
+    *this=HttpHdrCc();
 }
 
+/// set a data member to a new value, and set the corresponding mask-bit.
+/// if setting is false, then the mask-bit is cleared.
 void
-HttpHdrCc::clear()
+HttpHdrCc::setValue(int32_t &value, int32_t new_value, HttpHdrCcType hdr, bool setting)
 {
-    *this=HttpHdrCc();
+    if (setting) {
+        if (new_value < 0) {
+            debugs(65, 3, "rejecting negative-value Cache-Control directive " << hdr
+                   << " value " << new_value);
+            return;
+        }
+    } else {
+        new_value = -1; //rely on the convention that "unknown" is -1
+    }
+
+    value = new_value;
+    setMask(hdr,setting);
 }
 
 bool
@@ -80,7 +96,7 @@ HttpHdrCc::parse(const String & str)
 {
     const char *item;
     const char *p;      /* '=' parameter */
-    const char *pos = NULL;
+    const char *pos = nullptr;
     int ilen;
     int nlen;
 
@@ -97,11 +113,11 @@ HttpHdrCc::parse(const String & str)
         }
 
         /* find type */
-        const http_hdr_cc_type type = ccLookupTable.lookup(SBuf(item,nlen));
+        const HttpHdrCcType type = ccLookupTable.lookup(SBuf(item,nlen));
 
         // ignore known duplicate directives
         if (isSet(type)) {
-            if (type != CC_OTHER) {
+            if (type != HttpHdrCcType::CC_OTHER) {
                 debugs(65, 2, "hdr cc: ignoring duplicate cache-directive: near '" << item << "' in '" << str << "'");
                 ++ ccHeaderStats[type].repCount;
                 continue;
@@ -111,7 +127,7 @@ HttpHdrCc::parse(const String & str)
         /* special-case-parsing and attribute-setting */
         switch (type) {
 
-        case CC_MAX_AGE:
+        case HttpHdrCcType::CC_MAX_AGE:
             if (!p || !httpHeaderParseInt(p, &max_age) || max_age < 0) {
                 debugs(65, 2, "cc: invalid max-age specs near '" << item << "'");
                 clearMaxAge();
@@ -120,7 +136,7 @@ HttpHdrCc::parse(const String & str)
             }
             break;
 
-        case CC_S_MAXAGE:
+        case HttpHdrCcType::CC_S_MAXAGE:
             if (!p || !httpHeaderParseInt(p, &s_maxage) || s_maxage < 0) {
                 debugs(65, 2, "cc: invalid s-maxage specs near '" << item << "'");
                 clearSMaxAge();
@@ -129,7 +145,7 @@ HttpHdrCc::parse(const String & str)
             }
             break;
 
-        case CC_MAX_STALE:
+        case HttpHdrCcType::CC_MAX_STALE:
             if (!p || !httpHeaderParseInt(p, &max_stale) || max_stale < 0) {
                 debugs(65, 2, "cc: max-stale directive is valid without value");
                 maxStale(MAX_STALE_ANY);
@@ -138,7 +154,7 @@ HttpHdrCc::parse(const String & str)
             }
             break;
 
-        case CC_MIN_FRESH:
+        case HttpHdrCcType::CC_MIN_FRESH:
             if (!p || !httpHeaderParseInt(p, &min_fresh) || min_fresh < 0) {
                 debugs(65, 2, "cc: invalid min-fresh specs near '" << item << "'");
                 clearMinFresh();
@@ -147,7 +163,7 @@ HttpHdrCc::parse(const String & str)
             }
             break;
 
-        case CC_STALE_IF_ERROR:
+        case HttpHdrCcType::CC_STALE_IF_ERROR:
             if (!p || !httpHeaderParseInt(p, &stale_if_error) || stale_if_error < 0) {
                 debugs(65, 2, "cc: invalid stale-if-error specs near '" << item << "'");
                 clearStaleIfError();
@@ -156,7 +172,7 @@ HttpHdrCc::parse(const String & str)
             }
             break;
 
-        case CC_PRIVATE: {
+        case HttpHdrCcType::CC_PRIVATE: {
             String temp;
             if (!p)  {
                 // Value parameter is optional.
@@ -171,7 +187,7 @@ HttpHdrCc::parse(const String & str)
         }
         break;
 
-        case CC_NO_CACHE: {
+        case HttpHdrCcType::CC_NO_CACHE: {
             String temp;
             if (!p) {
                 // On Requests, missing value parameter is expected syntax.
@@ -189,26 +205,29 @@ HttpHdrCc::parse(const String & str)
         }
         break;
 
-        case CC_PUBLIC:
+        case HttpHdrCcType::CC_PUBLIC:
             Public(true);
             break;
-        case CC_NO_STORE:
+        case HttpHdrCcType::CC_NO_STORE:
             noStore(true);
             break;
-        case CC_NO_TRANSFORM:
+        case HttpHdrCcType::CC_NO_TRANSFORM:
             noTransform(true);
             break;
-        case CC_MUST_REVALIDATE:
+        case HttpHdrCcType::CC_MUST_REVALIDATE:
             mustRevalidate(true);
             break;
-        case CC_PROXY_REVALIDATE:
+        case HttpHdrCcType::CC_PROXY_REVALIDATE:
             proxyRevalidate(true);
             break;
-        case CC_ONLY_IF_CACHED:
+        case HttpHdrCcType::CC_ONLY_IF_CACHED:
             onlyIfCached(true);
             break;
+        case HttpHdrCcType::CC_IMMUTABLE:
+            Immutable(true);
+            break;
 
-        case CC_OTHER:
+        case HttpHdrCcType::CC_OTHER:
             if (other.size())
                 other.append(", ");
 
@@ -231,35 +250,62 @@ HttpHdrCc::packInto(Packable * p) const
     if (mask==0)
         return;
 
-    http_hdr_cc_type flag;
+    HttpHdrCcType flag;
     int pcount = 0;
     assert(p);
 
-    for (flag = CC_PUBLIC; flag < CC_ENUM_END; ++flag) {
-        if (isSet(flag) && flag != CC_OTHER) {
+    for (flag = HttpHdrCcType::CC_PUBLIC; flag < HttpHdrCcType::CC_ENUM_END; ++flag) {
+        if (isSet(flag) && flag != HttpHdrCcType::CC_OTHER) {
 
             /* print option name for all options */
-            p->appendf((pcount ? ", %s": "%s") , CcAttrs[flag].name);
+            p->appendf((pcount ? ", %s": "%s"), CcAttrs[flag].name);
 
             /* for all options having values, "=value" after the name */
             switch (flag) {
-            case CC_MAX_AGE:
-                p->appendf("=%d", maxAge());
+            case HttpHdrCcType::CC_PUBLIC:
+                break;
+            case HttpHdrCcType::CC_PRIVATE:
+                if (private_.size())
+                    p->appendf("=\"" SQUIDSTRINGPH "\"", SQUIDSTRINGPRINT(private_));
+                break;
+
+            case HttpHdrCcType::CC_NO_CACHE:
+                if (no_cache.size())
+                    p->appendf("=\"" SQUIDSTRINGPH "\"", SQUIDSTRINGPRINT(no_cache));
                 break;
-            case CC_S_MAXAGE:
-                p->appendf("=%d", sMaxAge());
+            case HttpHdrCcType::CC_NO_STORE:
                 break;
-            case CC_MAX_STALE:
+            case HttpHdrCcType::CC_NO_TRANSFORM:
+                break;
+            case HttpHdrCcType::CC_MUST_REVALIDATE:
+                break;
+            case HttpHdrCcType::CC_PROXY_REVALIDATE:
+                break;
+            case HttpHdrCcType::CC_MAX_AGE:
+                p->appendf("=%d", max_age);
+                break;
+            case HttpHdrCcType::CC_S_MAXAGE:
+                p->appendf("=%d", s_maxage);
+                break;
+            case HttpHdrCcType::CC_MAX_STALE:
                 /* max-stale's value is optional.
                   If we didn't receive it, don't send it */
-                if (maxStale()!=MAX_STALE_ANY)
-                    p->appendf("=%d", maxStale());
+                if (max_stale != MAX_STALE_ANY)
+                    p->appendf("=%d", max_stale);
                 break;
-            case CC_MIN_FRESH:
-                p->appendf("=%d", minFresh());
+            case HttpHdrCcType::CC_MIN_FRESH:
+                p->appendf("=%d", min_fresh);
                 break;
-            default:
-                /* do nothing, directive was already printed */
+            case HttpHdrCcType::CC_ONLY_IF_CACHED:
+                break;
+            case HttpHdrCcType::CC_STALE_IF_ERROR:
+                p->appendf("=%d", stale_if_error);
+                break;
+            case HttpHdrCcType::CC_IMMUTABLE:
+                break;
+            case HttpHdrCcType::CC_OTHER:
+            case HttpHdrCcType::CC_ENUM_END:
+                // done below after the loop
                 break;
             }
 
@@ -276,7 +322,7 @@ httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist)
 {
     assert(cc);
 
-    for (http_hdr_cc_type c = CC_PUBLIC; c < CC_ENUM_END; ++c)
+    for (HttpHdrCcType c = HttpHdrCcType::CC_PUBLIC; c < HttpHdrCcType::CC_ENUM_END; ++c)
         if (cc->isSet(c))
             hist->count(c);
 }
@@ -286,7 +332,7 @@ httpHdrCcStatDumper(StoreEntry * sentry, int, double val, double, int count)
 {
     extern const HttpHeaderStat *dump_stat; /* argh! */
     const int id = static_cast<int>(val);
-    const int valid_id = id < CC_ENUM_END;
+    const bool valid_id = id >= 0 && id < static_cast<int>(HttpHdrCcType::CC_ENUM_END);
     const char *name = valid_id ? CcAttrs[id].name : "INVALID";
 
     if (count || valid_id)
@@ -294,7 +340,14 @@ httpHdrCcStatDumper(StoreEntry * sentry, int, double val, double, int count)
                           id, name, count, xdiv(count, dump_stat->ccParsedCount));
 }
 
-#if !_USE_INLINE_
-#include "HttpHdrCc.cci"
-#endif
+std::ostream &
+operator<< (std::ostream &s, HttpHdrCcType c)
+{
+    const unsigned char ic = static_cast<int>(c);
+    if (c < HttpHdrCcType::CC_ENUM_END)
+        s << CcAttrs[ic].name << '[' << ic << ']' ;
+    else
+        s << "*invalid hdrcc* [" << ic << ']';
+    return s;
+}