]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/HttpHdrRange.cc
Renamed squid.h to squid-old.h and config.h to squid.h
[thirdparty/squid.git] / src / HttpHdrRange.cc
index a12265177396fa4bdcacd77dc5b3f5c681df8194..f43b7f62f02998c55255b121e7896b07590b104a 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: HttpHdrRange.cc,v 1.45 2007/08/13 17:20:51 hno Exp $
+ * $Id$
  *
  * DEBUG: section 64    HTTP Range Header
  * AUTHOR: Alex Rousskov
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
  *  (at your option) any later version.
- *  
+ *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *  
+ *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  *
  */
 
-#include "squid.h"
+#include "squid-old.h"
 #include "Store.h"
 #include "HttpHeaderRange.h"
 #include "client_side_request.h"
@@ -69,7 +69,7 @@ int64_t const HttpHdrRangeSpec::UnknownPosition = -1;
  * Range-Spec
  */
 
-HttpHdrRangeSpec::HttpHdrRangeSpec() : offset(UnknownPosition), length(UnknownPosition){}
+HttpHdrRangeSpec::HttpHdrRangeSpec() : offset(UnknownPosition), length(UnknownPosition) {}
 
 /* parses range-spec and returns new object on success */
 HttpHdrRangeSpec *
@@ -98,7 +98,7 @@ HttpHdrRangeSpec::parseInit(const char *field, int flen)
     } else
         /* must have a '-' somewhere in _this_ field */
         if (!((p = strchr(field, '-')) || (p - field >= flen))) {
-            debugs(64, 2, "ignoring invalid (missing '-') range-spec near: '" << field << "'");
+            debugs(64, 2, "invalid (missing '-') range-spec near: '" << field << "'");
             return false;
         } else {
             if (!httpHeaderParseOffset(field, &offset))
@@ -113,18 +113,18 @@ HttpHdrRangeSpec::parseInit(const char *field, int flen)
                 if (!httpHeaderParseOffset(p, &last_pos))
                     return false;
 
+                // RFC 2616 s14.35.1 MUST: last-byte-pos >= first-byte-pos
+                if (last_pos < offset) {
+                    debugs(64, 2, "invalid (last-byte-pos < first-byte-pos) range-spec near: " << field);
+                    return false;
+                }
+
                 HttpHdrRangeSpec::HttpRange aSpec (offset, last_pos + 1);
 
                 length = aSpec.size();
             }
         }
 
-    /* we managed to parse, check if the result makes sence */
-    if (length == 0) {
-        debugs(64, 2, "ignoring invalid (zero length) range-spec near: '" << field << "'");
-        return false;
-    }
-
     return true;
 }
 
@@ -158,12 +158,10 @@ HttpHdrRangeSpec::canonize(int64_t clen)
     outputInfo ("have");
     HttpRange object(0, clen);
 
-    if (!known_spec(offset))   /* suffix */
-    {
+    if (!known_spec(offset)) { /* suffix */
         assert(known_spec(length));
         offset = object.intersection(HttpRange (clen - length, clen)).start;
-    } else if (!known_spec(length))            /* trailer */
-    {
+    } else if (!known_spec(length)) {  /* trailer */
         assert(known_spec(offset));
         HttpRange newRange = object.intersection(HttpRange (offset, clen));
         length = newRange.size();
@@ -250,35 +248,36 @@ HttpHdrRange::parseInit(const String * range_spec)
     const char *item;
     const char *pos = NULL;
     int ilen;
-    int count = 0;
     assert(this && range_spec);
     ++ParsedCount;
-    debugs(64, 8, "parsing range field: '" << range_spec->buf() << "'");
+    debugs(64, 8, "parsing range field: '" << range_spec << "'");
     /* check range type */
 
     if (range_spec->caseCmp("bytes=", 6))
         return 0;
 
     /* skip "bytes="; hack! */
-    pos = range_spec->buf() + 6;
+    pos = range_spec->termedBuf() + 6;
 
     /* iterate through comma separated list */
     while (strListGetItem(range_spec, ',', &item, &ilen, &pos)) {
         HttpHdrRangeSpec *spec = HttpHdrRangeSpec::Create(item, ilen);
         /*
-         * HTTP/1.1 draft says we must ignore the whole header field if one spec
-         * is invalid. However, RFC 2068 just says that we must ignore that spec.
+         * RFC 2616 section 14.35.1: MUST ignore Range with
+         * at least one syntactically invalid byte-range-specs.
          */
+        if (!spec) {
+            while (!specs.empty())
+                delete specs.pop_back();
+            debugs(64, 2, "ignoring invalid range field: '" << range_spec << "'");
+            break;
+        }
 
-        if (spec)
-            specs.push_back(spec);
-
-        ++count;
+        specs.push_back(spec);
     }
 
-    debugs(64, 8, "parsed range range count: " << count << ", kept " <<
-           specs.size());
-    return specs.count != 0;
+    debugs(64, 8, "got range specs: " << specs.size());
+    return !specs.empty();
 }
 
 HttpHdrRange::~HttpHdrRange()
@@ -343,7 +342,7 @@ HttpHdrRange::merge (Vector<HttpHdrRangeSpec *> &basis)
     /* reset old array */
     specs.clean();
     /* merge specs:
-     * take one spec from "goods" and merge it with specs from 
+     * take one spec from "goods" and merge it with specs from
      * "specs" (if any) until there is no overlap */
     iterator i = basis.begin();
 
@@ -383,9 +382,9 @@ HttpHdrRange::getCanonizedSpecs (Vector<HttpHdrRangeSpec *> &copy)
 
 /*
  * canonizes all range specs within a set preserving the order
- * returns true if the set is valid after canonization; 
- * the set is valid if 
- *   - all range specs are valid and 
+ * returns true if the set is valid after canonization;
+ * the set is valid if
+ *   - all range specs are valid and
  *   - there is at least one range spec
  */
 int
@@ -526,31 +525,29 @@ HttpHdrRange::lowestOffset(int64_t size) const
 }
 
 /*
- * Return true if the first range offset is larger than the configured
- * limit.
- * Note that exceeding the limit (returning true) results in only 
- * grabbing the needed range elements from the origin.
+ * \retval true   Fetch only requested ranges. The first range is larger that configured limit.
+ * \retval false  Full download. Not a range request, no limit, or the limit is not yet reached.
  */
 bool
-HttpHdrRange::offsetLimitExceeded() const
+HttpHdrRange::offsetLimitExceeded(const int64_t limit) const
 {
     if (NULL == this)
         /* not a range request */
         return false;
 
-    if (Config.rangeOffsetLimit == 0)
-       /* disabled */
-       return true;
+    if (limit == 0)
+        /* 0 == disabled */
+        return true;
 
-    if (-1 == Config.rangeOffsetLimit)
-        /* forced */
+    if (-1 == limit)
+        /* 'none' == forced */
         return false;
 
     if (firstOffset() == -1)
         /* tail request */
         return true;
 
-    if (Config.rangeOffsetLimit >= firstOffset())
+    if (limit >= firstOffset())
         /* below the limit */
         return false;