/*
- * $Id: HttpHdrRange.cc,v 1.45 2007/08/13 17:20:51 hno Exp $
+ * $Id$
*
* DEBUG: section 64 HTTP Range Header
* AUTHOR: Alex Rousskov
*
*/
-#include "squid.h"
+#include "squid-old.h"
#include "Store.h"
#include "HttpHeaderRange.h"
#include "client_side_request.h"
} 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))
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;
}
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()
}
/*
- * 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 */
+ 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;