]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/HttpHeaderTools.cc
Docs: Copyright updates for 2018 (#114)
[thirdparty/squid.git] / src / HttpHeaderTools.cc
index 3d7bda667e6bec453a3b777f38e37adc1f08f324..da6c48a247ff245aed501905a7328bc6485cb56d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
@@ -78,36 +78,30 @@ httpHeaderAddContRange(HttpHeader * hdr, HttpHdrRangeSpec spec, int64_t ent_len)
     assert(hdr && ent_len >= 0);
     httpHdrContRangeSet(cr, spec, ent_len);
     hdr->putContRange(cr);
-    httpHdrContRangeDestroy(cr);
+    delete cr;
 }
 
 /**
- * return true if a given directive is found in at least one of
- * the "connection" header-fields note: if Http::HdrType::PROXY_CONNECTION is
- * present we ignore Http::HdrType::CONNECTION.
+ * \return true if a given directive is found in the Connection header field-value.
+ *
+ * \note if no Connection header exists we may check the Proxy-Connection header
  */
-int
-httpHeaderHasConnDir(const HttpHeader * hdr, const char *directive)
+bool
+httpHeaderHasConnDir(const HttpHeader * hdr, const SBuf &directive)
 {
     String list;
-    int res;
+
     /* what type of header do we have? */
+    if (hdr->getList(Http::HdrType::CONNECTION, &list))
+        return strListIsMember(&list, directive, ',') != 0;
 
 #if USE_HTTP_VIOLATIONS
-    if (hdr->has(Http::HdrType::PROXY_CONNECTION))
-        list = hdr->getList(Http::HdrType::PROXY_CONNECTION);
-    else
+    if (hdr->getList(Http::HdrType::PROXY_CONNECTION, &list))
+        return strListIsMember(&list, directive, ',') != 0;
 #endif
-        if (hdr->has(Http::HdrType::CONNECTION))
-            list = hdr->getList(Http::HdrType::CONNECTION);
-        else
-            return 0;
-
-    res = strListIsMember(&list, directive, ',');
-
-    list.clean();
 
-    return res;
+    // else, no connection header for it to exist in
+    return false;
 }
 
 /** handy to printf prefixes of potentially very long buffers */
@@ -138,18 +132,29 @@ httpHeaderParseInt(const char *start, int *value)
     return 1;
 }
 
-int
-httpHeaderParseOffset(const char *start, int64_t * value)
+bool
+httpHeaderParseOffset(const char *start, int64_t *value, char **endPtr)
 {
+    char *end = nullptr;
     errno = 0;
-    int64_t res = strtoll(start, NULL, 10);
-    if (!res && EINVAL == errno) {   /* maybe not portable? */
-        debugs(66, 7, "failed to parse offset in " << start);
-        return 0;
+    const int64_t res = strtoll(start, &end, 10);
+    if (errno && !res) {
+        debugs(66, 7, "failed to parse malformed offset in " << start);
+        return false;
+    }
+    if (errno == ERANGE && (res == LLONG_MIN || res == LLONG_MAX)) { // no overflow
+        debugs(66, 7, "failed to parse huge offset in " << start);
+        return false;
+    }
+    if (start == end) {
+        debugs(66, 7, "failed to parse empty offset");
+        return false;
     }
     *value = res;
+    if (endPtr)
+        *endPtr = end;
     debugs(66, 7, "offset " << start << " parsed as " << res);
-    return 1;
+    return true;
 }
 
 /**
@@ -284,7 +289,7 @@ httpHdrMangle(HttpHeaderEntry * e, HttpRequest * request, HeaderManglers *hms)
 
     ACLFilledChecklist checklist(hm->access_list, request, NULL);
 
-    if (checklist.fastCheck() == ACCESS_ALLOWED) {
+    if (checklist.fastCheck().allowed()) {
         /* aclCheckFast returns true for allow. */
         debugs(66, 7, "checklist for mangler is positive. Mangle");
         retval = 1;
@@ -451,7 +456,8 @@ HeaderManglers::find(const HttpHeaderEntry &e) const
     if (e.id == Http::HdrType::OTHER) {
         // does it have an ACL list configured?
         // Optimize: use a name type that we do not need to convert to here
-        const ManglersByName::const_iterator i = custom.find(e.name.termedBuf());
+        SBuf tmp(e.name); // XXX: performance regression. c_str() reallocates
+        const ManglersByName::const_iterator i = custom.find(tmp.c_str());
         if (i != custom.end())
             return &i->second;
     }
@@ -473,7 +479,7 @@ httpHdrAdd(HttpHeader *heads, HttpRequest *request, const AccessLogEntryPointer
     ACLFilledChecklist checklist(NULL, request, NULL);
 
     for (HeaderWithAclList::const_iterator hwa = headersAdd.begin(); hwa != headersAdd.end(); ++hwa) {
-        if (!hwa->aclList || checklist.fastCheck(hwa->aclList) == ACCESS_ALLOWED) {
+        if (!hwa->aclList || checklist.fastCheck(hwa->aclList).allowed()) {
             const char *fieldValue = NULL;
             MemBuf mb;
             if (hwa->quoted) {
@@ -489,8 +495,7 @@ httpHdrAdd(HttpHeader *heads, HttpRequest *request, const AccessLogEntryPointer
             if (!fieldValue || fieldValue[0] == '\0')
                 fieldValue = "-";
 
-            HttpHeaderEntry *e = new HttpHeaderEntry(hwa->fieldId, hwa->fieldName.c_str(),
-                    fieldValue);
+            HttpHeaderEntry *e = new HttpHeaderEntry(hwa->fieldId, SBuf(hwa->fieldName), fieldValue);
             heads->addEntry(e);
         }
     }