diff -rNU 60 ../squid-3.1.12-o/src/HttpRequest.cc ./src/HttpRequest.cc
--- ../squid-3.1.12-o/src/HttpRequest.cc	2011-04-04 03:24:06.000000000 +0200
+++ ./src/HttpRequest.cc	2014-04-14 16:12:18.000000000 +0200
@@ -556,60 +556,76 @@
 
     if (protocol == PROTO_CACHEOBJ)
         return false;
 
     return true;
 }
 
 bool
 HttpRequest::conditional() const
 {
     return flags.ims ||
            header.has(HDR_IF_MATCH) ||
            header.has(HDR_IF_NONE_MATCH);
 }
 
 bool HttpRequest::inheritProperties(const HttpMsg *aMsg)
 {
     const HttpRequest* aReq = dynamic_cast<const HttpRequest*>(aMsg);
     if (!aReq)
         return false;
 
     client_addr = aReq->client_addr;
 #if FOLLOW_X_FORWARDED_FOR
     indirect_client_addr = aReq->indirect_client_addr;
 #endif
     my_addr = aReq->my_addr;
 
     dnsWait = aReq->dnsWait;
 
 #if USE_ADAPTATION
     adaptHistory_ = aReq->adaptHistory();
 #endif
 #if ICAP_CLIENT
     icapHistory_ = aReq->icapHistory();
 #endif
 
     // This may be too conservative for the 204 No Content case
     // may eventually need cloneNullAdaptationImmune() for that.
     flags = aReq->flags.cloneAdaptationImmune();
 
     if (aReq->auth_user_request) {
         auth_user_request = aReq->auth_user_request;
         AUTHUSERREQUESTLOCK(auth_user_request, "inheritProperties");
     }
 
     if (aReq->pinned_connection) {
         pinned_connection = cbdataReference(aReq->pinned_connection);
     }
     return true;
 }
 
 void HttpRequest::recordLookup(const DnsLookupDetails &dns)
 {
     if (dns.wait >= 0) { // known delay
         if (dnsWait >= 0) // have recorded DNS wait before
             dnsWait += dns.wait;
         else
             dnsWait = dns.wait;
     }
 }
+
+
+
+void HttpRequest::ignoreRange(const char *reason)
+{
+    if (range) {
+        debugs(73, 3, static_cast<void*>(range) << " for " << reason);
+        delete range;
+        range = NULL;
+    }
+    // Some callers also reset isRanged but it may not be safe for all callers:
+    // isRanged is used to determine whether a weak ETag comparison is allowed,
+    // and that check should not ignore the Range header if it was present.
+    // TODO: Some callers also delete HDR_RANGE, HDR_REQUEST_RANGE. Should we?
+}
+
diff -rNU 60 ../squid-3.1.12-o/src/HttpRequest.h ./src/HttpRequest.h
--- ../squid-3.1.12-o/src/HttpRequest.h	2011-04-04 03:24:06.000000000 +0200
+++ ./src/HttpRequest.h	2014-04-14 16:12:18.000000000 +0200
@@ -181,76 +181,80 @@
 
     char *peer_login;		/* Configured peer login:password */
 
     time_t lastmod;		/* Used on refreshes */
 
     const char *vary_headers;	/* Used when varying entities are detected. Changes how the store key is calculated */
 
     char *peer_domain;		/* Configured peer forceddomain */
 
     String myportname; // Internal tag name= value from port this requests arrived in.
 
     String tag;			/* Internal tag for this request */
 
     String extacl_user;		/* User name returned by extacl lookup */
 
     String extacl_passwd;	/* Password returned by extacl lookup */
 
     String extacl_log;		/* String to be used for access.log purposes */
 
     String extacl_message;	/* String to be used for error page purposes */
 
 #if FOLLOW_X_FORWARDED_FOR
     String x_forwarded_for_iterator; /* XXX a list of IP addresses */
 #endif /* FOLLOW_X_FORWARDED_FOR */
 
 public:
     bool multipartRangeRequest() const;
 
     bool parseFirstLine(const char *start, const char *end);
 
     int parseHeader(const char *parse_start, int len);
 
     virtual bool expectingBody(const HttpRequestMethod& unused, int64_t&) const;
 
     bool bodyNibbled() const; // the request has a [partially] consumed body
 
     int prefixLen();
 
     void swapOut(StoreEntry * e);
 
     void pack(Packer * p);
 
     static void httpRequestPack(void *obj, Packer *p);
 
     static HttpRequest * CreateFromUrlAndMethod(char * url, const HttpRequestMethod& method);
 
     static HttpRequest * CreateFromUrl(char * url);
 
     void setPinnedConnection(ConnStateData *conn) {
         pinned_connection = cbdataReference(conn);
     }
 
     ConnStateData *pinnedConnection() {
         return pinned_connection;
     }
 
     void releasePinnedConnection() {
         cbdataReferenceDone(pinned_connection);
     }
 
+    /// forgets about the cached Range header (for a reason)
+    void ignoreRange(const char *reason);
+
+
 private:
     const char *packableURI(bool full_uri) const;
 
 protected:
     virtual void packFirstLineInto(Packer * p, bool full_uri) const;
 
     virtual bool sanityCheckStartLine(MemBuf *buf, const size_t hdr_len, http_status *error);
 
     virtual void hdrCacheInit();
 
     virtual bool inheritProperties(const HttpMsg *aMsg);
 };
 
 MEMPROXY_CLASS_INLINE(HttpRequest);
 
 #endif /* SQUID_HTTPREQUEST_H */
diff -rNU 60 ../squid-3.1.12-o/src/client_side.cc ./src/client_side.cc
--- ../squid-3.1.12-o/src/client_side.cc	2011-04-04 03:24:06.000000000 +0200
+++ ./src/client_side.cc	2014-04-14 16:12:18.000000000 +0200
@@ -1080,123 +1080,121 @@
 
     assert(0);			/* should not happen */
     return 0;
 }
 
 /**
  * generates a "unique" boundary string for multipart responses
  * the caller is responsible for cleaning the string */
 String
 ClientHttpRequest::rangeBoundaryStr() const
 {
     assert(this);
     const char *key;
     String b(APP_FULLNAME);
     b.append(":",1);
     key = storeEntry()->getMD5Text();
     b.append(key, strlen(key));
     return b;
 }
 
 /** adds appropriate Range headers if needed */
 void
 ClientSocketContext::buildRangeHeader(HttpReply * rep)
 {
     HttpHeader *hdr = rep ? &rep->header : 0;
     const char *range_err = NULL;
     HttpRequest *request = http->request;
     assert(request->range);
     /* check if we still want to do ranges */
 
     if (!rep)
         range_err = "no [parse-able] reply";
     else if ((rep->sline.status != HTTP_OK) && (rep->sline.status != HTTP_PARTIAL_CONTENT))
         range_err = "wrong status code";
     else if (hdr->has(HDR_CONTENT_RANGE))
         range_err = "origin server does ranges";
     else if (rep->content_length < 0)
         range_err = "unknown length";
     else if (rep->content_length != http->memObject()->getReply()->content_length)
         range_err = "INCONSISTENT length";	/* a bug? */
 
     /* hits only - upstream peer determines correct behaviour on misses, and client_side_reply determines
      * hits candidates
      */
     else if (logTypeIsATcpHit(http->logType) && http->request->header.has(HDR_IF_RANGE) && !clientIfRangeMatch(http, rep))
         range_err = "If-Range match failed";
     else if (!http->request->range->canonize(rep))
         range_err = "canonization failed";
     else if (http->request->range->isComplex())
         range_err = "too complex range header";
     else if (!logTypeIsATcpHit(http->logType) && http->request->range->offsetLimitExceeded())
         range_err = "range outside range_offset_limit";
 
     /* get rid of our range specs on error */
     if (range_err) {
         /* XXX We do this here because we need canonisation etc. However, this current
          * code will lead to incorrect store offset requests - the store will have the
          * offset data, but we won't be requesting it.
          * So, we can either re-request, or generate an error
          */
-        debugs(33, 3, "clientBuildRangeHeader: will not do ranges: " << range_err << ".");
-        delete http->request->range;
-        http->request->range = NULL;
+	http->request->ignoreRange(range_err);
     } else {
         /* XXX: TODO: Review, this unconditional set may be wrong. - TODO: review. */
         httpStatusLineSet(&rep->sline, rep->sline.version,
                           HTTP_PARTIAL_CONTENT, NULL);
         // web server responded with a valid, but unexpected range.
         // will (try-to) forward as-is.
         //TODO: we should cope with multirange request/responses
         bool replyMatchRequest = rep->content_range != NULL ?
                                  request->range->contains(rep->content_range->spec) :
                                  true;
         const int spec_count = http->request->range->specs.count;
         int64_t actual_clen = -1;
 
         debugs(33, 3, "clientBuildRangeHeader: range spec count: " <<
                spec_count << " virgin clen: " << rep->content_length);
         assert(spec_count > 0);
         /* append appropriate header(s) */
 
         if (spec_count == 1) {
             if (!replyMatchRequest) {
                 hdr->delById(HDR_CONTENT_RANGE);
                 hdr->putContRange(rep->content_range);
                 actual_clen = rep->content_length;
                 //http->range_iter.pos = rep->content_range->spec.begin();
                 (*http->range_iter.pos)->offset = rep->content_range->spec.offset;
                 (*http->range_iter.pos)->length = rep->content_range->spec.length;
 
             } else {
                 HttpHdrRange::iterator pos = http->request->range->begin();
                 assert(*pos);
                 /* append Content-Range */
 
                 if (!hdr->has(HDR_CONTENT_RANGE)) {
                     /* No content range, so this was a full object we are
                      * sending parts of.
                      */
                     httpHeaderAddContRange(hdr, **pos, rep->content_length);
                 }
 
                 /* set new Content-Length to the actual number of bytes
                  * transmitted in the message-body */
                 actual_clen = (*pos)->length;
             }
         } else {
             /* multipart! */
             /* generate boundary string */
             http->range_iter.boundary = http->rangeBoundaryStr();
             /* delete old Content-Type, add ours */
             hdr->delById(HDR_CONTENT_TYPE);
             httpHeaderPutStrf(hdr, HDR_CONTENT_TYPE,
                               "multipart/byteranges; boundary=\"" SQUIDSTRINGPH "\"",
                               SQUIDSTRINGPRINT(http->range_iter.boundary));
             /* Content-Length is not required in multipart responses
              * but it is always nice to have one */
             actual_clen = http->mRangeCLen();
             /* http->out needs to start where we want data at */
             http->out.offset = http->range_iter.currentSpec()->offset;
         }
 
         /* replace Content-Length header */
@@ -1429,123 +1427,129 @@
      * At this point we either have a parsed request (which we've
      * kicked off the processing for) or not. If we have a deferred
      * request (parsed but deferred for pipeling processing reasons)
      * then look at processing it. If not, simply kickstart
      * another read.
      */
 
     if ((deferredRequest = conn->getCurrentContext()).getRaw()) {
         debugs(33, 3, "ClientSocketContext:: FD " << conn->fd << ": calling PushDeferredIfNeeded");
         ClientSocketContextPushDeferredIfNeeded(deferredRequest, conn);
     } else {
         debugs(33, 3, "ClientSocketContext:: FD " << conn->fd << ": calling conn->readNextRequest()");
         conn->readNextRequest();
     }
 }
 
 void
 clientUpdateSocketStats(log_type logType, size_t size)
 {
     if (size == 0)
         return;
 
     kb_incr(&statCounter.client_http.kbytes_out, size);
 
     if (logTypeIsATcpHit(logType))
         kb_incr(&statCounter.client_http.hit_kbytes_out, size);
 }
 
 /**
  * increments iterator "i"
  * used by clientPackMoreRanges
  *
  \retval true    there is still data available to pack more ranges
  \retval false
  */
 bool
 ClientSocketContext::canPackMoreRanges() const
 {
     /** first update iterator "i" if needed */
 
     if (!http->range_iter.debt()) {
         debugs(33, 5, "ClientSocketContext::canPackMoreRanges: At end of current range spec for FD " << fd());
 
         if (http->range_iter.pos.incrementable())
             ++http->range_iter.pos;
 
         http->range_iter.updateSpec();
     }
 
     assert(!http->range_iter.debt() == !http->range_iter.currentSpec());
 
     /* paranoid sync condition */
     /* continue condition: need_more_data */
     debugs(33, 5, "ClientSocketContext::canPackMoreRanges: returning " << (http->range_iter.currentSpec() ? true : false));
     return http->range_iter.currentSpec() ? true : false;
 }
 
 int64_t
 ClientSocketContext::getNextRangeOffset() const
 {
+    debugs (33, 5, "range: " << http->request->range <<
+            "; http offset " << http->out.offset <<
+            "; reply " << reply);
+
+    // XXX: This method is called from many places, including pullData() which
+    // may be called before prepareReply() [on some Squid-generated errors].
+    // Hence, we may not even know yet whether we should honor/do ranges.
+
     if (http->request->range) {
-        /* offset in range specs does not count the prefix of an http msg */
-        debugs (33, 5, "ClientSocketContext::getNextRangeOffset: http offset " << http->out.offset);
         /* check: reply was parsed and range iterator was initialized */
         assert(http->range_iter.valid);
         /* filter out data according to range specs */
         assert (canPackMoreRanges());
         {
             int64_t start;		/* offset of still missing data */
             assert(http->range_iter.currentSpec());
             start = http->range_iter.currentSpec()->offset + http->range_iter.currentSpec()->length - http->range_iter.debt();
             debugs(33, 3, "clientPackMoreRanges: in:  offset: " << http->out.offset);
             debugs(33, 3, "clientPackMoreRanges: out:"
                    " start: " << start <<
                    " spec[" << http->range_iter.pos - http->request->range->begin() << "]:" <<
                    " [" << http->range_iter.currentSpec()->offset <<
                    ", " << http->range_iter.currentSpec()->offset + http->range_iter.currentSpec()->length << "),"
                    " len: " << http->range_iter.currentSpec()->length <<
                    " debt: " << http->range_iter.debt());
             if (http->range_iter.currentSpec()->length != -1)
                 assert(http->out.offset <= start);	/* we did not miss it */
 
             return start;
         }
 
     } else if (reply && reply->content_range) {
         /* request does not have ranges, but reply does */
         /** \todo FIXME: should use range_iter_pos on reply, as soon as reply->content_range
          *        becomes HttpHdrRange rather than HttpHdrRangeSpec.
          */
         return http->out.offset + reply->content_range->spec.offset;
     }
 
     return http->out.offset;
 }
 
 void
 ClientSocketContext::pullData()
 {
     debugs(33, 5, "ClientSocketContext::pullData: FD " << fd() <<
            " attempting to pull upstream data");
 
     /* More data will be coming from the stream. */
     StoreIOBuffer readBuffer;
     /* XXX: Next requested byte in the range sequence */
     /* XXX: length = getmaximumrangelenfgth */
     readBuffer.offset = getNextRangeOffset();
     readBuffer.length = HTTP_REQBUF_SZ;
     readBuffer.data = reqbuf;
     /* we may note we have reached the end of the wanted ranges */
     clientStreamRead(getTail(), http, readBuffer);
 }
 
 clientStream_status_t
 ClientSocketContext::socketState()
 {
     switch (clientStreamStatus(getTail(), http)) {
 
     case STREAM_NONE:
         /* check for range support ending */
 
         if (http->request->range) {
             /* check: reply was parsed and range iterator was initialized */
diff -rNU 60 ../squid-3.1.12-o/src/client_side_reply.cc ./src/client_side_reply.cc
--- ../squid-3.1.12-o/src/client_side_reply.cc	2014-04-14 16:04:30.000000000 +0200
+++ ./src/client_side_reply.cc	2014-04-14 16:12:18.000000000 +0200
@@ -52,120 +52,123 @@
 #endif
 #include "MemObject.h"
 #include "fde.h"
 #include "acl/FilledChecklist.h"
 #include "acl/Gadgets.h"
 #if DELAY_POOLS
 #include "DelayPools.h"
 #endif
 #include "client_side.h"
 #include "SquidTime.h"
 
 CBDATA_CLASS_INIT(clientReplyContext);
 
 /* Local functions */
 extern "C" CSS clientReplyStatus;
 extern ErrorState *clientBuildError(err_type, http_status, char const *, IpAddress &, HttpRequest *);
 
 /* privates */
 
 clientReplyContext::~clientReplyContext()
 {
     deleting = true;
     /* This may trigger a callback back into SendMoreData as the cbdata
      * is still valid
      */
     removeClientStoreReference(&sc, http);
     /* old_entry might still be set if we didn't yet get the reply
      * code in HandleIMSReply() */
     removeStoreReference(&old_sc, &old_entry);
     safe_free(tempBuffer.data);
     cbdataReferenceDone(http);
     HTTPMSGUNLOCK(reply);
 }
 
 clientReplyContext::clientReplyContext(ClientHttpRequest *clientContext) : http (cbdataReference(clientContext)), old_entry (NULL), old_sc(NULL), deleting(false)
 {}
 
 /** Create an error in the store awaiting the client side to read it.
  *
  * This may be better placed in the clientStream logic, but it has not been
  * relocated there yet
  */
 void
 clientReplyContext::setReplyToError(
     err_type err, http_status status, const HttpRequestMethod& method, char const *uri,
     IpAddress &addr, HttpRequest * failedrequest, const char *unparsedrequest,
     AuthUserRequest * auth_user_request)
 {
     ErrorState *errstate =
         clientBuildError(err, status, uri, addr, failedrequest);
 
     if (unparsedrequest)
         errstate->request_hdrs = xstrdup(unparsedrequest);
 
     if (status == HTTP_NOT_IMPLEMENTED && http->request)
         /* prevent confusion over whether we default to persistent or not */
         http->request->flags.proxy_keepalive = 0;
 
     http->al.http.code = errstate->httpStatus;
 
+    if (http->request)
+        http->request->ignoreRange("responding with a Squid-generated error");
+
     createStoreEntry(method, request_flags());
 
     if (auth_user_request) {
         errstate->auth_user_request = auth_user_request;
         AUTHUSERREQUESTLOCK(errstate->auth_user_request, "errstate");
     }
 
     assert(errstate->callback_data == NULL);
     errorAppendEntry(http->storeEntry(), errstate);
     /* Now the caller reads to get this */
 }
 
 void
 clientReplyContext::removeStoreReference(store_client ** scp,
         StoreEntry ** ep)
 {
     StoreEntry *e;
     store_client *sc_tmp = *scp;
 
     if ((e = *ep) != NULL) {
         *ep = NULL;
         storeUnregister(sc_tmp, e, this);
         *scp = NULL;
         e->unlock();
     }
 }
 
 void
 clientReplyContext::removeClientStoreReference(store_client **scp, ClientHttpRequest *aHttpRequest)
 {
     StoreEntry *reference = aHttpRequest->storeEntry();
     removeStoreReference(scp, &reference);
     aHttpRequest->storeEntry(reference);
 }
 
 void *
 clientReplyContext::operator new (size_t byteCount)
 {
     /* derived classes with different sizes must implement their own new */
     assert (byteCount == sizeof (clientReplyContext));
     CBDATA_INIT_TYPE(clientReplyContext);
     return cbdataAlloc(clientReplyContext);
 }
 
 void
 clientReplyContext::operator delete (void *address)
 {
     clientReplyContext * tmp = (clientReplyContext *)address;
     cbdataFree (tmp);
 }
 
 void
 clientReplyContext::saveState()
 {
     assert(old_sc == NULL);
     debugs(88, 3, "clientReplyContext::saveState: saving store context");
     old_entry = http->storeEntry();
     old_sc = sc;
     old_reqsize = reqsize;
     tempBuffer.offset = reqofs;
@@ -2073,90 +2076,93 @@
 
     if (errorInStream(result, reqofs)) {
         sendStreamError(result);
         return;
     }
 
     if (flags.headersSent) {
         pushStreamData (result, buf);
         return;
     }
 
     cloneReply();
 
     /* handle headers */
 
     if (Config.onoff.log_mime_hdrs) {
         size_t k;
 
         if ((k = headersEnd(buf, reqofs))) {
             safe_free(http->al.headers.reply);
             http->al.headers.reply = (char *)xcalloc(k + 1, 1);
             xstrncpy(http->al.headers.reply, buf, k);
         }
     }
 
     holdingBuffer = result;
     processReplyAccess();
     return;
 }
 
 
 
 /* Using this breaks the client layering just a little!
  */
 void
 clientReplyContext::createStoreEntry(const HttpRequestMethod& m, request_flags reqFlags)
 {
     assert(http != NULL);
     /*
      * For erroneous requests, we might not have a h->request,
      * so make a fake one.
      */
 
     if (http->request == NULL)
         http->request = HTTPMSGLOCK(new HttpRequest(m, PROTO_NONE, null_string));
 
     StoreEntry *e = storeCreateEntry(http->uri, http->log_uri, reqFlags, m);
 
     sc = storeClientListAdd(e, this);
 
 #if DELAY_POOLS
 
     sc->setDelayId(DelayId::DelayClient(http));
 
 #endif
 
     reqofs = 0;
 
     reqsize = 0;
 
+
     /* I don't think this is actually needed! -- adrian */
     /* http->reqbuf = http->norm_reqbuf; */
     //    assert(http->reqbuf == http->norm_reqbuf);
     /* The next line is illegal because we don't know if the client stream
      * buffers have been set up
      */
     //    storeClientCopy(http->sc, e, 0, HTTP_REQBUF_SZ, http->reqbuf,
     //        SendMoreData, this);
     /* So, we mark the store logic as complete */
     flags.storelogiccomplete = 1;
 
     /* and get the caller to request a read, from whereever they are */
     /* NOTE: after ANY data flows down the pipe, even one step,
      * this function CAN NOT be used to manage errors
      */
     http->storeEntry(e);
 }
 
 ErrorState *
 clientBuildError(err_type page_id, http_status status, char const *url,
                  IpAddress &src_addr, HttpRequest * request)
 {
     ErrorState *err = errorCon(page_id, status, request);
     err->src_addr = src_addr;
 
     if (url)
         err->url = xstrdup(url);
 
     return err;
 }
+
+
diff -rNU 60 ../squid-3.1.12-o/src/client_side_request.cc ./src/client_side_request.cc
--- ../squid-3.1.12-o/src/client_side_request.cc	2011-04-04 03:24:06.000000000 +0200
+++ ./src/client_side_request.cc	2014-04-14 16:12:18.000000000 +0200
@@ -799,122 +799,121 @@
             if (http->flags.accel && request->flags.ims) {
                 if ((str = req_hdr->getStr(HDR_USER_AGENT))) {
                     if (strstr(str, "MSIE 5.01") != NULL)
                         no_cache++;
                     else if (strstr(str, "MSIE 5.0") != NULL)
                         no_cache++;
                     else if (strstr(str, "MSIE 4.") != NULL)
                         no_cache++;
                     else if (strstr(str, "MSIE 3.") != NULL)
                         no_cache++;
                 }
             }
         }
     }
 
     if (request->method == METHOD_OTHER) {
         no_cache++;
     }
 
     if (no_cache) {
 #if HTTP_VIOLATIONS
 
         if (Config.onoff.reload_into_ims)
             request->flags.nocache_hack = 1;
         else if (refresh_nocache_hack)
             request->flags.nocache_hack = 1;
         else
 #endif
 
             request->flags.nocache = 1;
     }
 
     /* ignore range header in non-GETs or non-HEADs */
     if (request->method == METHOD_GET || request->method == METHOD_HEAD) {
         // XXX: initialize if we got here without HttpRequest::parseHeader()
         if (!request->range)
             request->range = req_hdr->getRange();
 
         if (request->range) {
             request->flags.range = 1;
             clientStreamNode *node = (clientStreamNode *)http->client_stream.tail->data;
             /* XXX: This is suboptimal. We should give the stream the range set,
              * and thereby let the top of the stream set the offset when the
              * size becomes known. As it is, we will end up requesting from 0
              * for evey -X range specification.
              * RBC - this may be somewhat wrong. We should probably set the range
              * iter up at this point.
              */
             node->readBuffer.offset = request->range->lowestOffset(0);
             http->range_iter.pos = request->range->begin();
             http->range_iter.valid = true;
         }
     }
 
     /* Only HEAD and GET requests permit a Range or Request-Range header.
      * If these headers appear on any other type of request, delete them now.
      */
     else {
         req_hdr->delById(HDR_RANGE);
         req_hdr->delById(HDR_REQUEST_RANGE);
-        delete request->range;
-        request->range = NULL;
+	request->ignoreRange("neither HEAD nor GET");
     }
 
     if (req_hdr->has(HDR_AUTHORIZATION))
         request->flags.auth = 1;
 
     ConnStateData *http_conn = http->getConn();
     assert(http_conn);
     request->flags.connection_auth_disabled = http_conn->port->connection_auth_disabled;
     if (!request->flags.connection_auth_disabled) {
         if (http_conn->pinning.fd != -1) {
             if (http_conn->pinning.auth) {
                 request->flags.connection_auth = 1;
                 request->flags.auth = 1;
             } else {
                 request->flags.connection_proxy_auth = 1;
             }
             request->setPinnedConnection(http_conn);
         }
     }
 
     /* check if connection auth is used, and flag as candidate for pinning
      * in such case.
      * Note: we may need to set flags.connection_auth even if the connection
      * is already pinned if it was pinned earlier due to proxy auth
      */
     if (!request->flags.connection_auth) {
         if (req_hdr->has(HDR_AUTHORIZATION) || req_hdr->has(HDR_PROXY_AUTHORIZATION)) {
             HttpHeaderPos pos = HttpHeaderInitPos;
             HttpHeaderEntry *e;
             int may_pin = 0;
             while ((e = req_hdr->getEntry(&pos))) {
                 if (e->id == HDR_AUTHORIZATION || e->id == HDR_PROXY_AUTHORIZATION) {
                     const char *value = e->value.rawBuf();
                     if (strncasecmp(value, "NTLM ", 5) == 0
                             ||
                             strncasecmp(value, "Negotiate ", 10) == 0
                             ||
                             strncasecmp(value, "Kerberos ", 9) == 0) {
                         if (e->id == HDR_AUTHORIZATION) {
                             request->flags.connection_auth = 1;
                             may_pin = 1;
                         } else {
                             request->flags.connection_proxy_auth = 1;
                             may_pin = 1;
                         }
                     }
                 }
             }
             if (may_pin && !request->pinnedConnection()) {
                 request->setPinnedConnection(http->getConn());
             }
         }
     }
 
 
     if (request->login[0] != '\0')
         request->flags.auth = 1;
 
     if (req_hdr->has(HDR_VIA)) {
         String s = req_hdr->getList(HDR_VIA);
diff -rNU 60 ../squid-3.1.12-o/src/http.cc ./src/http.cc
--- ../squid-3.1.12-o/src/http.cc	2011-04-04 03:24:06.000000000 +0200
+++ ./src/http.cc	2014-04-14 16:13:28.000000000 +0200
@@ -1472,122 +1472,121 @@
 // Close the HTTP server connection. Used by serverComplete().
 void
 HttpStateData::closeServer()
 {
     debugs(11,5, HERE << "closing HTTP server FD " << fd << " this " << this);
 
     if (fd >= 0) {
         fwd->unregister(fd);
         comm_remove_close_handler(fd, closeHandler);
         closeHandler = NULL;
         comm_close(fd);
         fd = -1;
     }
 }
 
 bool
 HttpStateData::doneWithServer() const
 {
     return fd < 0;
 }
 
 /*
  * build request headers and append them to a given MemBuf
  * used by buildRequestPrefix()
  * note: initialised the HttpHeader, the caller is responsible for Clean()-ing
  */
 void
 HttpStateData::httpBuildRequestHeader(HttpRequest * request,
                                       HttpRequest * orig_request,
                                       StoreEntry * entry,
                                       HttpHeader * hdr_out,
                                       const http_state_flags flags)
 {
     /* building buffer for complex strings */
 #define BBUF_SZ (MAX_URL+32)
     LOCAL_ARRAY(char, bbuf, BBUF_SZ);
     LOCAL_ARRAY(char, ntoabuf, MAX_IPSTRLEN);
     const HttpHeader *hdr_in = &orig_request->header;
     const HttpHeaderEntry *e = NULL;
     HttpHeaderPos pos = HttpHeaderInitPos;
     assert (hdr_out->owner == hoRequest);
 
     /* append our IMS header */
     if (request->lastmod > -1)
         hdr_out->putTime(HDR_IF_MODIFIED_SINCE, request->lastmod);
 
     bool we_do_ranges = decideIfWeDoRanges (orig_request);
 
     String strConnection (hdr_in->getList(HDR_CONNECTION));
 
     while ((e = hdr_in->getEntry(&pos)))
         copyOneHeaderFromClientsideRequestToUpstreamRequest(e, strConnection, request, orig_request, hdr_out, we_do_ranges, flags);
 
     /* Abstraction break: We should interpret multipart/byterange responses
      * into offset-length data, and this works around our inability to do so.
      */
     if (!we_do_ranges && orig_request->multipartRangeRequest()) {
         /* don't cache the result */
         orig_request->flags.cachable = 0;
         /* pretend it's not a range request */
-        delete orig_request->range;
-        orig_request->range = NULL;
+	orig_request->ignoreRange("want to request the whole object");
         orig_request->flags.range = 0;
     }
 
     /* append Via */
     if (Config.onoff.via) {
         String strVia;
         strVia = hdr_in->getList(HDR_VIA);
         snprintf(bbuf, BBUF_SZ, "%d.%d %s",
                  orig_request->http_ver.major,
                  orig_request->http_ver.minor, ThisCache);
         strListAdd(&strVia, bbuf, ',');
         hdr_out->putStr(HDR_VIA, strVia.termedBuf());
         strVia.clean();
     }
 
 #if USE_SQUID_ESI
     if (orig_request->flags.accelerated) {
         /* Append Surrogate-Capabilities */
         String strSurrogate (hdr_in->getList(HDR_SURROGATE_CAPABILITY));
         snprintf(bbuf, BBUF_SZ, "%s=\"Surrogate/1.0 ESI/1.0\"",
                  Config.Accel.surrogate_id);
         strListAdd(&strSurrogate, bbuf, ',');
         hdr_out->putStr(HDR_SURROGATE_CAPABILITY, strSurrogate.termedBuf());
     }
 #endif
 
     /** \pre Handle X-Forwarded-For */
     if (strcmp(opt_forwarded_for, "delete") != 0) {
 
         String strFwd = hdr_in->getList(HDR_X_FORWARDED_FOR);
 
         if (strFwd.size() > 65536/2) {
             // There is probably a forwarding loop with Via detection disabled.
             // If we do nothing, String will assert on overflow soon.
             // TODO: Terminate all transactions with huge XFF?
             strFwd = "error";
 
             static int warnedCount = 0;
             if (warnedCount++ < 100) {
                 const char *url = entry ? entry->url() : urlCanonical(orig_request);
                 debugs(11, 1, "Warning: likely forwarding loop with " << url);
             }
         }
 
         if (strcmp(opt_forwarded_for, "on") == 0) {
             /** If set to ON - append client IP or 'unknown'. */
             if ( orig_request->client_addr.IsNoAddr() )
                 strListAdd(&strFwd, "unknown", ',');
             else
                 strListAdd(&strFwd, orig_request->client_addr.NtoA(ntoabuf, MAX_IPSTRLEN), ',');
         } else if (strcmp(opt_forwarded_for, "off") == 0) {
             /** If set to OFF - append 'unknown'. */
             strListAdd(&strFwd, "unknown", ',');
         } else if (strcmp(opt_forwarded_for, "transparent") == 0) {
             /** If set to TRANSPARENT - pass through unchanged. */
         } else if (strcmp(opt_forwarded_for, "truncate") == 0) {
             /** If set to TRUNCATE - drop existing list and replace with client IP or 'unknown'. */
             if ( orig_request->client_addr.IsNoAddr() )
                 strFwd = "unknown";
             else
