=== modified file 'src/HttpHdrCc.h' --- src/HttpHdrCc.h 2013-03-26 10:33:10 +0000 +++ src/HttpHdrCc.h 2013-11-22 14:52:28 +0000 @@ -61,53 +61,53 @@ min_fresh(MIN_FRESH_UNKNOWN) {} /// reset data-members to default state void clear(); /// parse a header-string and fill in appropriate values. bool parse(const String & s); //manipulation for Cache-Control: public header bool hasPublic() const {return isSet(CC_PUBLIC);} bool Public() const {return isSet(CC_PUBLIC);} void Public(bool v) {setMask(CC_PUBLIC,v);} void clearPublic() {setMask(CC_PUBLIC,false);} //manipulation for Cache-Control: private header bool hasPrivate() const {return isSet(CC_PRIVATE);} const String &Private() const {return private_;} void Private(String &v) { setMask(CC_PRIVATE,true); // uses append for multi-line headers - if (private_.defined()) + if (private_.size() > 0) private_.append(","); private_.append(v); } void clearPrivate() {setMask(CC_PRIVATE,false); private_.clean();} //manipulation for Cache-Control: no-cache header bool hasNoCache() const {return isSet(CC_NO_CACHE);} const String &noCache() const {return no_cache;} void noCache(String &v) { setMask(CC_NO_CACHE,true); // uses append for multi-line headers - if (no_cache.defined()) + if (no_cache.size() > 0) no_cache.append(","); no_cache.append(v); } void clearNoCache() {setMask(CC_NO_CACHE,false); no_cache.clean();} //manipulation for Cache-Control: no-store header bool hasNoStore() const {return isSet(CC_NO_STORE);} bool noStore() const {return isSet(CC_NO_STORE);} void noStore(bool v) {setMask(CC_NO_STORE,v);} void clearNoStore() {setMask(CC_NO_STORE,false);} //manipulation for Cache-Control: no-transform header bool hasNoTransform() const {return isSet(CC_NO_TRANSFORM);} bool noTransform() const {return isSet(CC_NO_TRANSFORM);} void noTransform(bool v) {setMask(CC_NO_TRANSFORM,v);} void clearNoTransform() {setMask(CC_NO_TRANSFORM,false);} //manipulation for Cache-Control: must-revalidate header bool hasMustRevalidate() const {return isSet(CC_MUST_REVALIDATE);} bool mustRevalidate() const {return isSet(CC_MUST_REVALIDATE);} === modified file 'src/HttpHeaderTools.cc' --- src/HttpHeaderTools.cc 2013-10-25 00:13:46 +0000 +++ src/HttpHeaderTools.cc 2013-11-22 14:55:11 +0000 @@ -277,41 +277,41 @@ } end = pos; while (end < (start+len) && *end != '\\' && *end != '\"' && (unsigned char)*end > 0x1F && *end != 0x7F) ++end; if (((unsigned char)*end <= 0x1F && *end != '\r' && *end != '\n') || *end == 0x7F) { debugs(66, 2, HERE << "failed to parse a quoted-string header field with CTL octet " << (start-pos) << " bytes into '" << start << "'"); val->clean(); return 0; } val->append(pos, end-pos); pos = end; } if (*pos != '\"') { debugs(66, 2, HERE << "failed to parse a quoted-string header field which did not end with \" "); val->clean(); return 0; } /* Make sure it's defined even if empty "" */ - if (!val->defined()) + if (!val->termedBuf()) val->limitInit("", 0); return 1; } /** * Checks the anonymizer (header_access) configuration. * * \retval 0 Header is explicitly blocked for removal * \retval 1 Header is explicitly allowed * \retval 1 Header has been replaced, the current version can be used. * \retval 1 Header has no access controls to test */ static int httpHdrMangle(HttpHeaderEntry * e, HttpRequest * request, int req_or_rep) { int retval; /* check with anonymizer tables */ HeaderManglers *hms = NULL; assert(e); === modified file 'src/SquidString.h' --- src/SquidString.h 2013-10-04 13:55:21 +0000 +++ src/SquidString.h 2013-11-22 15:04:22 +0000 @@ -55,48 +55,40 @@ typedef size_t size_type; //storage size intentionally unspecified const static size_type npos = std::string::npos; String &operator =(char const *); String &operator =(String const &); bool operator ==(String const &) const; bool operator !=(String const &) const; /** * Retrieve a single character in the string. \param pos Position of character to retrieve. */ _SQUID_INLINE_ char operator [](unsigned int pos) const; _SQUID_INLINE_ size_type size() const; /// variant of size() suited to be used for printf-alikes. /// throws when size() > MAXINT int psize() const; /** - * \retval true the String has some contents - */ - _SQUID_INLINE_ bool defined() const; - /** - * \retval true the String does not hold any contents - */ - _SQUID_INLINE_ bool undefined() const; - /** * Returns a raw pointer to the underlying backing store. The caller has been * verified not to make any assumptions about null-termination */ _SQUID_INLINE_ char const * rawBuf() const; /** * Returns a raw pointer to the underlying backing store. * The caller requires it to be null-terminated. */ _SQUID_INLINE_ char const * termedBuf() const; void limitInit(const char *str, int len); // TODO: rename to assign() void clean(); void reset(char const *str); void append(char const *buf, int len); void append(char const *buf); void append(char const); void append(String const &); void absorb(String &old); const char * pos(char const *aString) const; const char * pos(char const ch) const; ///offset from string start of the first occurrence of ch @@ -104,40 +96,43 @@ size_type find(char const ch) const; size_type find(char const *aString) const; const char * rpos(char const ch) const; size_type rfind(char const ch) const; _SQUID_INLINE_ int cmp(char const *) const; _SQUID_INLINE_ int cmp(char const *, size_type count) const; _SQUID_INLINE_ int cmp(String const &) const; _SQUID_INLINE_ int caseCmp(char const *) const; _SQUID_INLINE_ int caseCmp(char const *, size_type count) const; _SQUID_INLINE_ int caseCmp(String const &) const; String substr(size_type from, size_type to) const; _SQUID_INLINE_ void cut(size_type newLength); private: void allocAndFill(const char *str, int len); void allocBuffer(size_type sz); void setBuffer(char *buf, size_type sz); + bool defined() const {return buf_!=NULL;} + bool undefined() const {return !defined();} + _SQUID_INLINE_ bool nilCmp(bool, bool, int &) const; /* never reference these directly! */ size_type size_; /* buffer size; 64K limit */ size_type len_; /* current length */ char *buf_; _SQUID_INLINE_ void set(char const *loc, char const ch); _SQUID_INLINE_ void cutPointer(char const *loc); }; _SQUID_INLINE_ std::ostream & operator<<(std::ostream& os, String const &aString); _SQUID_INLINE_ bool operator<(const String &a, const String &b); #if _USE_INLINE_ #include "String.cci" === modified file 'src/String.cci' --- src/String.cci 2012-09-22 01:28:35 +0000 +++ src/String.cci 2013-11-22 15:01:15 +0000 @@ -36,50 +36,40 @@ #include #else /* HAVE_STDINT_H */ #ifndef INT_MAX #define INT_MAX 1<<31 //hack but a safe bet #endif /* INT_MAX */ #endif /* HAVE_STDINT_H */ String::String() : size_(0), len_(0), buf_(NULL) { #if DEBUGSTRINGS StringRegistry::Instance().add(this); #endif } String::size_type String::size() const { return len_; } -bool String::defined() const -{ - return buf_!=NULL; -} - -bool String::undefined() const -{ - return buf_==NULL; -} - char const * String::rawBuf() const { return buf_; } char const * String::termedBuf() const { return buf_; } char String::operator [](unsigned int aPos) const { assert(aPos < size_); return buf_[aPos]; } === modified file 'src/acl/HttpHeaderData.cc' --- src/acl/HttpHeaderData.cc 2013-10-31 19:13:17 +0000 +++ src/acl/HttpHeaderData.cc 2013-11-22 14:41:12 +0000 @@ -58,47 +58,42 @@ } bool ACLHTTPHeaderData::match(HttpHeader* hdr) { if (hdr == NULL) return false; debugs(28, 3, "aclHeaderData::match: checking '" << hdrName << "'"); String value; if (hdrId != HDR_BAD_HDR) { if (!hdr->has(hdrId)) return false; value = hdr->getStrOrList(hdrId); } else { if (!hdr->getByNameIfPresent(hdrName.termedBuf(), value)) return false; } - // By now, we know the header is present, but: - // HttpHeader::get*() return an undefined String for empty header values; - // String::termedBuf() returns NULL for undefined Strings; and - // ACLRegexData::match() always fails on NULL strings. - // This makes it possible to detect an empty header value using regex: - const char *cvalue = value.defined() ? value.termedBuf() : ""; - return regex_rule->match(cvalue); + const SBuf cvalue(value); + return regex_rule->match(cvalue.c_str()); } wordlist * ACLHTTPHeaderData::dump() { wordlist *W = NULL; wordlistAdd(&W, hdrName.termedBuf()); wordlist * regex_dump = regex_rule->dump(); wordlistAddWl(&W, regex_dump); wordlistDestroy(®ex_dump); return W; } void ACLHTTPHeaderData::parse() { char* t = strtokFile(); assert (t != NULL); hdrName = t; hdrId = httpHeaderIdByNameDef(hdrName.rawBuf(), hdrName.size()); === modified file 'src/adaptation/ecap/MessageRep.cc' --- src/adaptation/ecap/MessageRep.cc 2013-10-25 00:13:46 +0000 +++ src/adaptation/ecap/MessageRep.cc 2013-11-22 14:39:07 +0000 @@ -22,41 +22,41 @@ { } bool Adaptation::Ecap::HeaderRep::hasAny(const Name &name) const { const http_hdr_type squidId = TranslateHeaderId(name); // XXX: optimize to remove getByName: we do not need the value here return squidId == HDR_OTHER ? theHeader.getByName(name.image().c_str()).size() > 0: (bool)theHeader.has(squidId); } Adaptation::Ecap::HeaderRep::Value Adaptation::Ecap::HeaderRep::value(const Name &name) const { const http_hdr_type squidId = TranslateHeaderId(name); const String value = squidId == HDR_OTHER ? theHeader.getByName(name.image().c_str()) : theHeader.getStrOrList(squidId); - return value.defined() ? + return value.size() > 0 ? Value::FromTempString(value.termedBuf()) : Value(); } void Adaptation::Ecap::HeaderRep::add(const Name &name, const Value &value) { const http_hdr_type squidId = TranslateHeaderId(name); // HDR_OTHER OK HttpHeaderEntry *e = new HttpHeaderEntry(squidId, name.image().c_str(), value.toString().c_str()); theHeader.addEntry(e); if (squidId == HDR_CONTENT_LENGTH) theMessage.content_length = theHeader.getInt64(HDR_CONTENT_LENGTH); } void Adaptation::Ecap::HeaderRep::removeAny(const Name &name) { const http_hdr_type squidId = TranslateHeaderId(name); if (squidId == HDR_OTHER) === modified file 'src/adaptation/ecap/XactionRep.cc' --- src/adaptation/ecap/XactionRep.cc 2013-10-25 00:13:46 +0000 +++ src/adaptation/ecap/XactionRep.cc 2013-11-22 15:22:04 +0000 @@ -126,41 +126,41 @@ client_addr = request->client_addr; if (!client_addr.isAnyAddr() && !client_addr.isNoAddr()) { char ntoabuf[MAX_IPSTRLEN] = ""; client_addr.toStr(ntoabuf,MAX_IPSTRLEN); return libecap::Area::FromTempBuffer(ntoabuf, strlen(ntoabuf)); } } return libecap::Area(); } const libecap::Area Adaptation::Ecap::XactionRep::usernameValue() const { #if USE_AUTH const HttpRequest *request = dynamic_cast(theCauseRep ? theCauseRep->raw().header : theVirginRep.raw().header); Must(request); if (request->auth_user_request != NULL) { if (char const *name = request->auth_user_request->username()) return libecap::Area::FromTempBuffer(name, strlen(name)); - else if (request->extacl_user.defined() && request->extacl_user.size()) + else if (request->extacl_user.size() > 0) return libecap::Area::FromTempBuffer(request->extacl_user.rawBuf(), request->extacl_user.size()); } #endif return libecap::Area(); } const libecap::Area Adaptation::Ecap::XactionRep::masterxSharedValue(const libecap::Name &name) const { const HttpRequest *request = dynamic_cast(theCauseRep ? theCauseRep->raw().header : theVirginRep.raw().header); Must(request); if (name.known()) { // must check to avoid empty names matching unset cfg Adaptation::History::Pointer ah = request->adaptHistory(false); if (ah != NULL) { String name, value; if (ah->getXxRecord(name, value)) return libecap::Area::FromTempBuffer(value.rawBuf(), value.size()); } === modified file 'src/adaptation/icap/ModXact.cc' --- src/adaptation/icap/ModXact.cc 2013-11-11 12:09:44 +0000 +++ src/adaptation/icap/ModXact.cc 2013-11-22 14:37:06 +0000 @@ -1335,41 +1335,41 @@ const Adaptation::ServiceConfig &s = service().cfg(); buf.Printf("%s " SQUIDSTRINGPH " ICAP/1.0\r\n", s.methodStr(), SQUIDSTRINGPRINT(s.uri)); buf.Printf("Host: " SQUIDSTRINGPH ":%d\r\n", SQUIDSTRINGPRINT(s.host), s.port); buf.Printf("Date: %s\r\n", mkrfc1123(squid_curtime)); if (!TheConfig.reuse_connections) buf.Printf("Connection: close\r\n"); const HttpRequest *request = &virginRequest(); // we must forward "Proxy-Authenticate" and "Proxy-Authorization" // as ICAP headers. if (virgin.header->header.has(HDR_PROXY_AUTHENTICATE)) { String vh=virgin.header->header.getByName("Proxy-Authenticate"); buf.Printf("Proxy-Authenticate: " SQUIDSTRINGPH "\r\n",SQUIDSTRINGPRINT(vh)); } if (virgin.header->header.has(HDR_PROXY_AUTHORIZATION)) { String vh=virgin.header->header.getByName("Proxy-Authorization"); buf.Printf("Proxy-Authorization: " SQUIDSTRINGPH "\r\n", SQUIDSTRINGPRINT(vh)); - } else if (request->extacl_user.defined() && request->extacl_user.size() && request->extacl_passwd.defined() && request->extacl_passwd.size()) { + } else if (request->extacl_user.size() > 0 && request->extacl_passwd.size() > 0) { char loginbuf[256]; snprintf(loginbuf, sizeof(loginbuf), SQUIDSTRINGPH ":" SQUIDSTRINGPH, SQUIDSTRINGPRINT(request->extacl_user), SQUIDSTRINGPRINT(request->extacl_passwd)); buf.Printf("Proxy-Authorization: Basic %s\r\n", old_base64_encode(loginbuf)); } // share the cross-transactional database records if needed if (Adaptation::Config::masterx_shared_name) { Adaptation::History::Pointer ah = request->adaptHistory(false); if (ah != NULL) { String name, value; if (ah->getXxRecord(name, value)) { buf.Printf(SQUIDSTRINGPH ": " SQUIDSTRINGPH "\r\n", SQUIDSTRINGPRINT(name), SQUIDSTRINGPRINT(value)); } } } buf.Printf("Encapsulated: "); @@ -1492,41 +1492,41 @@ else if (allow204out) allowHeader = "Allow: 204\r\n"; else if (allow206) allowHeader = "Allow: 206\r\n"; if (allowHeader) { // may be nil if only allow204in is true buf.append(allowHeader, strlen(allowHeader)); debugs(93,5, HERE << "Will write " << allowHeader); } } void Adaptation::Icap::ModXact::makeUsernameHeader(const HttpRequest *request, MemBuf &buf) { #if USE_AUTH if (request->auth_user_request != NULL) { char const *name = request->auth_user_request->username(); if (name) { const char *value = TheConfig.client_username_encode ? old_base64_encode(name) : name; buf.Printf("%s: %s\r\n", TheConfig.client_username_header, value); } - } else if (request->extacl_user.defined() && request->extacl_user.size()) { + } else if (request->extacl_user.size() > 0) { const char *value = TheConfig.client_username_encode ? old_base64_encode(request->extacl_user.termedBuf()) : request->extacl_user.termedBuf(); buf.Printf("%s: %s\r\n", TheConfig.client_username_header, value); } #endif } void Adaptation::Icap::ModXact::encapsulateHead(MemBuf &icapBuf, const char *section, MemBuf &httpBuf, const HttpMsg *head) { // update ICAP header icapBuf.Printf("%s=%d, ", section, (int) httpBuf.contentSize()); // begin cloning HttpMsg::Pointer headClone; if (const HttpRequest* old_request = dynamic_cast(head)) { HttpRequest::Pointer new_request(new HttpRequest); Must(old_request->canonical); urlParse(old_request->method, old_request->canonical, new_request.getRaw()); new_request->http_ver = old_request->http_ver; headClone = new_request.getRaw(); === modified file 'src/client_side.cc' --- src/client_side.cc 2013-11-11 12:09:44 +0000 +++ src/client_side.cc 2013-11-22 14:51:16 +0000 @@ -3772,41 +3772,41 @@ } else { Ssl::CrtdMessage reply_message(Ssl::CrtdMessage::REPLY); if (reply_message.parse(reply.other().content(), reply.other().contentSize()) != Ssl::CrtdMessage::OK) { debugs(33, 5, HERE << "Reply from ssl_crtd for " << sslConnectHostOrIp << " is incorrect"); } else { if (reply.result != HelperReply::Okay) { debugs(33, 5, HERE << "Certificate for " << sslConnectHostOrIp << " cannot be generated. ssl_crtd response: " << reply_message.getBody()); } else { debugs(33, 5, HERE << "Certificate for " << sslConnectHostOrIp << " was successfully recieved from ssl_crtd"); SSL_CTX *ctx = Ssl::generateSslContextUsingPkeyAndCertFromMemory(reply_message.getBody().c_str(), *port); getSslContextDone(ctx, true); return; } } } getSslContextDone(NULL); } void ConnStateData::buildSslCertGenerationParams(Ssl::CertificateProperties &certProperties) { - certProperties.commonName = sslCommonName.defined() ? sslCommonName.termedBuf() : sslConnectHostOrIp.termedBuf(); + certProperties.commonName = sslCommonName.size() > 0 ? sslCommonName.termedBuf() : sslConnectHostOrIp.termedBuf(); // fake certificate adaptation requires bump-server-first mode if (!sslServerBump) { assert(port->signingCert.get()); certProperties.signWithX509.resetAndLock(port->signingCert.get()); if (port->signPkey.get()) certProperties.signWithPkey.resetAndLock(port->signPkey.get()); certProperties.signAlgorithm = Ssl::algSignTrusted; return; } // In case of an error while connecting to the secure server, use a fake // trusted certificate, with no mimicked fields and no adaptation // algorithms. There is nothing we can mimic so we want to minimize the // number of warnings the user will have to see to get to the error page. assert(sslServerBump->entry); if (sslServerBump->entry->isEmpty()) { if (X509 *mimicCert = sslServerBump->serverCert.get()) certProperties.mimicCert.resetAndLock(mimicCert); @@ -3867,41 +3867,41 @@ assert(port->signingCert.get()); certProperties.signWithX509.resetAndLock(port->signingCert.get()); if (port->signPkey.get()) certProperties.signWithPkey.resetAndLock(port->signPkey.get()); } signAlgorithm = certProperties.signAlgorithm; } void ConnStateData::getSslContextStart() { assert(areAllContextsForThisConnection()); freeAllContexts(); /* careful: freeAllContexts() above frees request, host, etc. */ if (port->generateHostCertificates) { Ssl::CertificateProperties certProperties; buildSslCertGenerationParams(certProperties); sslBumpCertKey = certProperties.dbKey().c_str(); - assert(sslBumpCertKey.defined() && sslBumpCertKey[0] != '\0'); + assert(sslBumpCertKey.size() > 0 && sslBumpCertKey[0] != '\0'); debugs(33, 5, HERE << "Finding SSL certificate for " << sslBumpCertKey << " in cache"); Ssl::LocalContextStorage & ssl_ctx_cache(Ssl::TheGlobalContextStorage.getLocalStorage(port->s)); SSL_CTX * dynCtx = NULL; Ssl::SSL_CTX_Pointer *cachedCtx = ssl_ctx_cache.get(sslBumpCertKey.termedBuf()); if (cachedCtx && (dynCtx = cachedCtx->get())) { debugs(33, 5, HERE << "SSL certificate for " << sslBumpCertKey << " have found in cache"); if (Ssl::verifySslCertificate(dynCtx, certProperties)) { debugs(33, 5, HERE << "Cached SSL certificate for " << sslBumpCertKey << " is valid"); getSslContextDone(dynCtx); return; } else { debugs(33, 5, HERE << "Cached SSL certificate for " << sslBumpCertKey << " is out of date. Delete this certificate from cache"); ssl_ctx_cache.del(sslBumpCertKey.termedBuf()); } } else { debugs(33, 5, HERE << "SSL certificate for " << sslBumpCertKey << " haven't found in cache"); } #if USE_SSL_CRTD @@ -3934,41 +3934,41 @@ ConnStateData::getSslContextDone(SSL_CTX * sslContext, bool isNew) { // Try to add generated ssl context to storage. if (port->generateHostCertificates && isNew) { if (signAlgorithm == Ssl::algSignTrusted) { // Add signing certificate to the certificates chain X509 *cert = port->signingCert.get(); if (SSL_CTX_add_extra_chain_cert(sslContext, cert)) { // increase the certificate lock CRYPTO_add(&(cert->references),1,CRYPTO_LOCK_X509); } else { const int ssl_error = ERR_get_error(); debugs(33, DBG_IMPORTANT, "WARNING: can not add signing certificate to SSL context chain: " << ERR_error_string(ssl_error, NULL)); } Ssl::addChainToSslContext(sslContext, port->certsToChain.get()); } //else it is self-signed or untrusted do not attrach any certificate Ssl::LocalContextStorage & ssl_ctx_cache(Ssl::TheGlobalContextStorage.getLocalStorage(port->s)); - assert(sslBumpCertKey.defined() && sslBumpCertKey[0] != '\0'); + assert(sslBumpCertKey.size() > 0 && sslBumpCertKey[0] != '\0'); if (sslContext) { if (!ssl_ctx_cache.add(sslBumpCertKey.termedBuf(), new Ssl::SSL_CTX_Pointer(sslContext))) { // If it is not in storage delete after using. Else storage deleted it. fd_table[clientConnection->fd].dynamicSslContext = sslContext; } } else { debugs(33, 2, HERE << "Failed to generate SSL cert for " << sslConnectHostOrIp); } } // If generated ssl context = NULL, try to use static ssl context. if (!sslContext) { if (!port->staticSslContext) { debugs(83, DBG_IMPORTANT, "Closing SSL " << clientConnection->remote << " as lacking SSL context"); clientConnection->close(); return; } else { debugs(33, 5, HERE << "Using static ssl context."); sslContext = port->staticSslContext.get(); } === modified file 'src/errorpage.cc' --- src/errorpage.cc 2013-10-25 00:13:46 +0000 +++ src/errorpage.cc 2013-11-22 14:51:57 +0000 @@ -822,41 +822,41 @@ break; case 'B': if (building_deny_info_url) break; p = request ? ftpUrlWith2f(request) : "[no URL]"; break; case 'c': if (building_deny_info_url) break; p = errorPageName(type); break; case 'D': if (!allowRecursion) p = "%D"; // if recursion is not allowed, do not convert #if USE_SSL // currently only SSL error details implemented else if (detail) { detail->useRequest(request); const String &errDetail = detail->toString(); - if (errDetail.defined()) { + if (errDetail.size() > 0) { MemBuf *detail_mb = ConvertText(errDetail.termedBuf(), false); mb.append(detail_mb->content(), detail_mb->contentSize()); delete detail_mb; do_quote = 0; } } #endif if (!mb.contentSize()) mb.Printf("[No Error Detail]"); break; case 'e': mb.Printf("%d", xerrno); break; case 'E': if (xerrno) mb.Printf("(%d) %s", xerrno, strerror(xerrno)); else mb.Printf("[No Error]"); === modified file 'src/http.cc' --- src/http.cc 2013-11-18 15:55:05 +0000 +++ src/http.cc 2013-11-22 15:18:38 +0000 @@ -345,41 +345,41 @@ // NP: reverse-proxy traffic our parent server has instructed us never to cache if (surrogateNoStore) { debugs(22, 3, HERE << "NO because Surrogate-Control:no-store"); return 0; } // RFC 2616: HTTP/1.1 Cache-Control conditions if (!ignoreCacheControl) { // XXX: check to see if the request headers alone were enough to prevent caching earlier // (ie no-store request header) no need to check those all again here if so. // for now we are not reliably doing that so we waste CPU re-checking request CC // RFC 2616 section 14.9.2 - MUST NOT cache any response with request CC:no-store if (request && request->cache_control && request->cache_control->noStore() && !REFRESH_OVERRIDE(ignore_no_store)) { debugs(22, 3, HERE << "NO because client request Cache-Control:no-store"); return 0; } // NP: request CC:no-cache only means cache READ is forbidden. STORE is permitted. - if (rep->cache_control && rep->cache_control->hasNoCache() && rep->cache_control->noCache().defined()) { + if (rep->cache_control && rep->cache_control->hasNoCache() && rep->cache_control->noCache().size() > 0) { /* TODO: we are allowed to cache when no-cache= has parameters. * Provided we strip away any of the listed headers unless they are revalidated * successfully (ie, must revalidate AND these headers are prohibited on stale replies). * That is a bit tricky for squid right now so we avoid caching entirely. */ debugs(22, 3, HERE << "NO because server reply Cache-Control:no-cache has parameters"); return 0; } // NP: request CC:private is undefined. We ignore. // NP: other request CC flags are limiters on HIT/MISS. We don't care about here. // RFC 2616 section 14.9.2 - MUST NOT cache any response with CC:no-store if (rep->cache_control && rep->cache_control->noStore() && !REFRESH_OVERRIDE(ignore_no_store)) { debugs(22, 3, HERE << "NO because server reply Cache-Control:no-store"); return 0; } // RFC 2616 section 14.9.1 - MUST NOT cache any response with CC:private in a shared cache like Squid. @@ -410,41 +410,41 @@ debugs(22, 3, HERE << "NO because Authenticated and ignoring Cache-Control"); return 0; } bool mayStore = false; // HTTPbis pt6 section 3.2: a response CC:public is present if (rep->cache_control->Public()) { debugs(22, 3, HERE << "Authenticated but server reply Cache-Control:public"); mayStore = true; // HTTPbis pt6 section 3.2: a response CC:must-revalidate is present } else if (rep->cache_control->mustRevalidate() && !REFRESH_OVERRIDE(ignore_must_revalidate)) { debugs(22, 3, HERE << "Authenticated but server reply Cache-Control:public"); mayStore = true; #if USE_HTTP_VIOLATIONS // NP: given the must-revalidate exception we should also be able to exempt no-cache. // HTTPbis WG verdict on this is that it is omitted from the spec due to being 'unexpected' by // some. The caching+revalidate is not exactly unsafe though with Squids interpretation of no-cache // (without parameters) as equivalent to must-revalidate in the reply. - } else if (rep->cache_control->hasNoCache() && !rep->cache_control->noCache().defined() && !REFRESH_OVERRIDE(ignore_must_revalidate)) { + } else if (rep->cache_control->hasNoCache() && rep->cache_control->noCache().size() > 0 && !REFRESH_OVERRIDE(ignore_must_revalidate)) { debugs(22, 3, HERE << "Authenticated but server reply Cache-Control:no-cache (equivalent to must-revalidate)"); mayStore = true; #endif // HTTPbis pt6 section 3.2: a response CC:s-maxage is present } else if (rep->cache_control->sMaxAge()) { debugs(22, 3, HERE << "Authenticated but server reply Cache-Control:s-maxage"); mayStore = true; } if (!mayStore) { debugs(22, 3, HERE << "NO because Authenticated transaction"); return 0; } // NP: response CC:no-cache is equivalent to CC:must-revalidate,max-age=0. We MAY cache, and do so. // NP: other request CC flags are limiters on HIT/MISS/REFRESH. We don't care about here. } /* HACK: The "multipart/x-mixed-replace" content type is used for @@ -1689,41 +1689,41 @@ StoreEntry * entry, const AccessLogEntryPointer &al, HttpHeader * hdr_out, const HttpStateFlags &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 = &request->header; const HttpHeaderEntry *e = NULL; HttpHeaderPos pos = HttpHeaderInitPos; assert (hdr_out->owner == hoRequest); /* use our IMS header if the cached entry has Last-Modified time */ if (request->lastmod > -1) hdr_out->putTime(HDR_IF_MODIFIED_SINCE, request->lastmod); // Add our own If-None-Match field if the cached entry has a strong ETag. // copyOneHeaderFromClientsideRequestToUpstreamRequest() adds client ones. - if (request->etag.defined()) { + if (request->etag.size() > 0) { hdr_out->addEntry(new HttpHeaderEntry(HDR_IF_NONE_MATCH, NULL, request->etag.termedBuf())); } bool we_do_ranges = decideIfWeDoRanges (request); String strConnection (hdr_in->getList(HDR_CONNECTION)); while ((e = hdr_in->getEntry(&pos))) copyOneHeaderFromClientsideRequestToUpstreamRequest(e, strConnection, 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 && request->multipartRangeRequest()) { /* don't cache the result */ request->flags.cachable = false; /* pretend it's not a range request */ delete request->range; request->range = NULL; === modified file 'src/redirect.cc' --- src/redirect.cc 2013-10-26 15:56:57 +0000 +++ src/redirect.cc 2013-11-22 14:37:53 +0000 @@ -242,42 +242,41 @@ Http::StatusCode status; char claddr[MAX_IPSTRLEN]; char myaddr[MAX_IPSTRLEN]; /** TODO: create a standalone method to initialize * the RedirectStateData for all the helpers. */ RedirectStateData *r = new RedirectStateData(http->uri); if (conn != NULL) r->client_addr = conn->log_addr; else r->client_addr.setNoAddr(); r->client_ident = NULL; #if USE_AUTH if (http->request->auth_user_request != NULL) { r->client_ident = http->request->auth_user_request->username(); debugs(61, 5, HERE << "auth-user=" << (r->client_ident?r->client_ident:"NULL")); } #endif - // HttpRequest initializes with null_string. So we must check both defined() and size() - if (!r->client_ident && http->request->extacl_user.defined() && http->request->extacl_user.size()) { + if (!r->client_ident && http->request->extacl_user.size() > 0) { r->client_ident = http->request->extacl_user.termedBuf(); debugs(61, 5, HERE << "acl-user=" << (r->client_ident?r->client_ident:"NULL")); } if (!r->client_ident && conn != NULL && conn->clientConnection != NULL && conn->clientConnection->rfc931[0]) { r->client_ident = conn->clientConnection->rfc931; debugs(61, 5, HERE << "ident-user=" << (r->client_ident?r->client_ident:"NULL")); } #if USE_SSL if (!r->client_ident && conn != NULL && Comm::IsConnOpen(conn->clientConnection)) { r->client_ident = sslGetUserEmail(fd_table[conn->clientConnection->fd].ssl); debugs(61, 5, HERE << "ssl-user=" << (r->client_ident?r->client_ident:"NULL")); } #endif if (!r->client_ident) r->client_ident = dash_str; === modified file 'src/ssl/ErrorDetail.cc' --- src/ssl/ErrorDetail.cc 2013-11-07 10:46:14 +0000 +++ src/ssl/ErrorDetail.cc 2013-11-22 14:53:40 +0000 @@ -387,41 +387,41 @@ /** * The subject of the current certification in text form */ const char *Ssl::ErrorDetail::subject() const { if (!broken_cert) return "[Not available]"; static char tmpBuffer[256]; // A temporary buffer X509_NAME_oneline(X509_get_subject_name(broken_cert.get()), tmpBuffer, sizeof(tmpBuffer)); return tmpBuffer; } // helper function to be used with Ssl::matchX509CommonNames static int copy_cn(void *check_data, ASN1_STRING *cn_data) { String *str = (String *)check_data; if (!str) // no data? abort return 0; - if (str->defined()) + if (str->size() > 0) str->append(", "); str->append((const char *)cn_data->data, cn_data->length); return 1; } /** * The list with certificates cn and alternate names */ const char *Ssl::ErrorDetail::cn() const { if (!broken_cert) return "[Not available]"; static String tmpStr; ///< A temporary string buffer tmpStr.clean(); Ssl::matchX509CommonNames(broken_cert.get(), &tmpStr, copy_cn); return tmpStr.termedBuf(); } /** @@ -484,41 +484,41 @@ snprintf(tmpBuffer, 64, "%d", (int)error_no); err = tmpBuffer; } return err; } /** * A short description of the error_no */ const char *Ssl::ErrorDetail::err_descr() const { if (error_no == SSL_ERROR_NONE) return "[No Error]"; if (const char *err = detailEntry.descr.termedBuf()) return err; return "[Not available]"; } const char *Ssl::ErrorDetail::err_lib_error() const { - if (errReason.defined()) + if (errReason.size() > 0) return errReason.termedBuf(); else if (lib_error_no != SSL_ERROR_NONE) return ERR_error_string(lib_error_no, NULL); else return "[No Error]"; } /** * Converts the code to a string value. Supported formating codes are: * * Error meta information: * %err_name: The name of a high-level SSL error (e.g., X509_V_ERR_*) * %ssl_error_descr: A short description of the SSL error * %ssl_lib_error: human-readable low-level error string by ERR_error_string(3SSL) * * Certificate information extracted from broken (not necessarily peer!) cert * %ssl_cn: The comma-separated list of common and alternate names * %ssl_subject: The certificate subject * %ssl_ca_name: The certificate issuer name * %ssl_notbefore: The certificate "not before" field @@ -557,41 +557,41 @@ s = detailEntry.detail.termedBuf(); if (!s) s = SslErrorDetailDefaultStr; assert(s); while ((p = strchr(s, '%'))) { errDetailStr.append(s, p - s); code_len = convert(++p, &t); if (code_len) errDetailStr.append(t); else errDetailStr.append("%"); s = p + code_len; } errDetailStr.append(s, strlen(s)); } const String &Ssl::ErrorDetail::toString() const { - if (!errDetailStr.defined()) + if (errDetailStr.size() == 0) buildDetail(); return errDetailStr; } Ssl::ErrorDetail::ErrorDetail( Ssl::ssl_error_t err_no, X509 *cert, X509 *broken, const char *aReason): error_no (err_no), lib_error_no(SSL_ERROR_NONE), errReason(aReason) { if (cert) peer_cert.resetAndLock(cert); if (broken) broken_cert.resetAndLock(broken); else broken_cert.resetAndLock(cert); detailEntry.error_no = SSL_ERROR_NONE; } Ssl::ErrorDetail::ErrorDetail(Ssl::ErrorDetail const &anErrDetail) { error_no = anErrDetail.error_no; === modified file 'src/ssl/ErrorDetailManager.cc' --- src/ssl/ErrorDetailManager.cc 2013-11-07 10:46:14 +0000 +++ src/ssl/ErrorDetailManager.cc 2013-11-22 15:00:34 +0000 @@ -213,44 +213,43 @@ const String errorName = parser.getByName("name"); if (!errorName.size()) { debugs(83, DBG_IMPORTANT, HERE << "WARNING! invalid or no error detail name on:" << s); return false; } Ssl::ssl_error_t ssl_error = Ssl::GetErrorCode(errorName.termedBuf()); if (ssl_error != SSL_ERROR_NONE) { if (theDetails->getErrorDetail(ssl_error)) { debugs(83, DBG_IMPORTANT, HERE << "WARNING! duplicate entry: " << errorName); return false; } ErrorDetailEntry &entry = theDetails->theList[ssl_error]; entry.error_no = ssl_error; entry.name = errorName; String tmp = parser.getByName("detail"); - httpHeaderParseQuotedString(tmp.termedBuf(), tmp.size(), &entry.detail); + int detailsParseOk = httpHeaderParseQuotedString(tmp.termedBuf(), tmp.size(), &entry.detail); tmp = parser.getByName("descr"); - httpHeaderParseQuotedString(tmp.termedBuf(), tmp.size(), &entry.descr); - bool parseOK = entry.descr.defined() && entry.detail.defined(); + int descrParseOk = httpHeaderParseQuotedString(tmp.termedBuf(), tmp.size(), &entry.descr); - if (!parseOK) { + if (!detailsParseOk || !descrParseOk) { debugs(83, DBG_IMPORTANT, HERE << "WARNING! missing important field for detail error: " << errorName); return false; } } else if (!Ssl::ErrorIsOptional(errorName.termedBuf())) { debugs(83, DBG_IMPORTANT, HERE << "WARNING! invalid error detail name: " << errorName); return false; } }// else {only spaces and black lines; just ignore} buf.consume(size); } debugs(83, 9, HERE << " Remain size: " << buf.contentSize() << " Content: " << buf.content()); return true; } === modified file 'src/stat.cc' --- src/stat.cc 2013-10-25 00:13:46 +0000 +++ src/stat.cc 2013-11-22 14:56:52 +0000 @@ -2033,41 +2033,41 @@ storeAppendPrintf(s, "\tnrequests: %d\n", conn->nrequests); } storeAppendPrintf(s, "uri %s\n", http->uri); storeAppendPrintf(s, "logType %s\n", LogTags_str[http->logType]); storeAppendPrintf(s, "out.offset %ld, out.size %lu\n", (long int) http->out.offset, (unsigned long int) http->out.size); storeAppendPrintf(s, "req_sz %ld\n", (long int) http->req_sz); e = http->storeEntry(); storeAppendPrintf(s, "entry %p/%s\n", e, e ? e->getMD5Text() : "N/A"); storeAppendPrintf(s, "start %ld.%06d (%f seconds ago)\n", (long int) http->start_time.tv_sec, (int) http->start_time.tv_usec, tvSubDsec(http->start_time, current_time)); #if USE_AUTH if (http->request->auth_user_request != NULL) p = http->request->auth_user_request->username(); else #endif - if (http->request->extacl_user.defined()) { + if (http->request->extacl_user.size() > 0) { p = http->request->extacl_user.termedBuf(); } if (!p && conn != NULL && conn->clientConnection->rfc931[0]) p = conn->clientConnection->rfc931; #if USE_SSL if (!p && conn != NULL && Comm::IsConnOpen(conn->clientConnection)) p = sslGetUserEmail(fd_table[conn->clientConnection->fd].ssl); #endif if (!p) p = dash_str; storeAppendPrintf(s, "username %s\n", p); #if USE_DELAY_POOLS storeAppendPrintf(s, "delay_pool %d\n", DelayId::DelayClient(http).pool()); === modified file 'src/store.cc' --- src/store.cc 2013-10-25 00:13:46 +0000 +++ src/store.cc 2013-11-22 14:57:10 +0000 @@ -771,41 +771,41 @@ // TODO: storeGetPublic() calls below may create unlocked entries. // We should add/use storeHas() API or lock/unlock those entries. if (mem_obj->vary_headers && !storeGetPublic(mem_obj->url, mem_obj->method)) { /* Create "vary" base object */ String vary; StoreEntry *pe = storeCreateEntry(mem_obj->url, mem_obj->log_url, request->flags, request->method); /* We are allowed to do this typecast */ HttpReply *rep = new HttpReply; rep->setHeaders(Http::scOkay, "Internal marker object", "x-squid-internal/vary", -1, -1, squid_curtime + 100000); vary = mem_obj->getReply()->header.getList(HDR_VARY); if (vary.size()) { /* Again, we own this structure layout */ rep->header.putStr(HDR_VARY, vary.termedBuf()); vary.clean(); } #if X_ACCELERATOR_VARY vary = mem_obj->getReply()->header.getList(HDR_X_ACCELERATOR_VARY); - if (vary.defined()) { + if (vary.size() > 0) { /* Again, we own this structure layout */ rep->header.putStr(HDR_X_ACCELERATOR_VARY, vary.termedBuf()); vary.clean(); } #endif pe->replaceHttpReply(rep); pe->timestampsSet(); pe->makePublic(); pe->complete(); pe->unlock(); } newkey = storeKeyPublicByRequest(mem_obj->request); } else newkey = storeKeyPublic(mem_obj->url, mem_obj->method);