# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: kinkie@squid-cache.org-20090218094532-19aico1zm0ubc11y # target_branch: http://www.squid-cache.org/bzr/squid3/trunk # testament_sha1: 2b8fd0af7b2608e3c19dd5da0fb4af68c50e7f86 # timestamp: 2009-02-18 11:03:20 +0100 # base_revision_id: chtsanti@users.sourceforge.net-20090216233348-\ # zr0awtvru9zw7dyc # # Begin patch === modified file 'src/ACLExtUser.cc' --- src/ACLExtUser.cc 2009-01-29 14:50:26 +0000 +++ src/ACLExtUser.cc 2009-02-10 11:02:53 +0000 @@ -79,7 +79,7 @@ ACLExtUser::match(ACLChecklist *checklist) { if (checklist->request->extacl_user.size()) { - return data->match(checklist->request->extacl_user.unsafeBuf()); + return data->match(checklist->request->extacl_user.termedBuf()); } else { return -1; } === modified file 'src/CommonPool.h' --- src/CommonPool.h 2009-01-29 14:50:26 +0000 +++ src/CommonPool.h 2009-02-11 17:08:24 +0000 @@ -59,7 +59,7 @@ void *operator new(size_t); void operator delete (void *); static CommonPool *Factory (unsigned char _class, CompositePoolNode::Pointer&); - char const* theClassTypeLabel() const {return typeLabel.unsafeBuf();} + char const* theClassTypeLabel() const {return typeLabel.termedBuf();} protected: CommonPool(); === modified file 'src/DelayTagged.cc' --- src/DelayTagged.cc 2009-01-29 14:50:26 +0000 +++ src/DelayTagged.cc 2009-02-18 09:45:32 +0000 @@ -77,7 +77,7 @@ DelayTaggedCmp(DelayTaggedBucket::Pointer const &left, DelayTaggedBucket::Pointer const &right) { /* for rate limiting, case insensitive */ - return left->tag.caseCmp(right->tag.unsafeBuf()); + return left->tag.caseCmp(right->tag); } void @@ -195,7 +195,7 @@ void DelayTaggedBucket::stats (StoreEntry *entry) const { - storeAppendPrintf(entry, " %s:", tag.unsafeBuf()); + storeAppendPrintf(entry, " :" SQUIDSTRINGPH , SQUIDSTRINGPRINT(tag)); theBucket.stats (entry); } === modified file 'src/DiskIO/AIO/AIODiskFile.cc' --- src/DiskIO/AIO/AIODiskFile.cc 2009-01-29 14:50:26 +0000 +++ src/DiskIO/AIO/AIODiskFile.cc 2009-02-11 17:08:24 +0000 @@ -87,10 +87,9 @@ { /* Simulate async calls */ #ifdef _SQUID_WIN32_ - fd = aio_open(path.unsafeBuf(), flags); + fd = aio_open(path.termedBuf(), flags); #else - - fd = file_open(path.unsafeBuf() , flags); + fd = file_open(path.termedBuf() , flags); #endif ioRequestor = callback; @@ -130,7 +129,7 @@ fatal("Aiee! out of aiocb slots! - FIXME and wrap file_read\n"); debugs(79, 1, "WARNING: out of aiocb slots!"); /* fall back to blocking method */ - // file_read(fd, request->unsafeBuf, request->len, request->offset, callback, data); + // file_read(fd, request->buf, request->len, request->offset, callback, data); return; } @@ -167,7 +166,7 @@ fatalf("Aiee! aio_read() returned error (%d) FIXME and wrap file_read !\n", errno); debugs(79, 1, "WARNING: aio_read() returned error: " << xstrerror()); /* fall back to blocking method */ - // file_read(fd, request->unsafeBuf, request->len, request->offset, callback, data); + // file_read(fd, request->buf, request->len, request->offset, callback, data); } } @@ -188,7 +187,7 @@ fatal("Aiee! out of aiocb slots FIXME and wrap file_write !\n"); debugs(79, 1, "WARNING: out of aiocb slots!"); /* fall back to blocking method */ - // file_write(fd, offset, unsafeBuf, len, callback, data, freefunc); + // file_write(fd, offset, buf, len, callback, data, freefunc); return; } @@ -225,7 +224,7 @@ fatalf("Aiee! aio_write() returned error (%d) FIXME and wrap file_write !\n", errno); debugs(79, 1, "WARNING: aio_write() returned error: " << xstrerror()); /* fall back to blocking method */ - // file_write(fd, offset, unsafeBuf, len, callback, data, freefunc); + // file_write(fd, offset, buf, len, callback, data, freefunc); } } === modified file 'src/ESI.cc' --- src/ESI.cc 2009-02-04 23:25:42 +0000 +++ src/ESI.cc 2009-02-11 17:08:24 +0000 @@ -2430,7 +2430,7 @@ */ return 0; - if (strstr (sctusable->content.unsafeBuf(), "ESI/1.0")) + if (sctusable->content.pos("ESI/1.0") != NULL) rv = 1; httpHdrScTargetDestroy (sctusable); === modified file 'src/ESIAssign.cc' --- src/ESIAssign.cc 2009-02-04 23:25:42 +0000 +++ src/ESIAssign.cc 2009-02-11 17:08:24 +0000 @@ -89,7 +89,7 @@ variable = NULL; if (unevaluatedVariable.size()) { - varState->feedData(unevaluatedVariable.unsafeBuf(), unevaluatedVariable.size()); + varState->feedData(unevaluatedVariable.rawBuf(), unevaluatedVariable.size()); char const *result = varState->extractChar (); /* Consider activating this, when we want to evaluate variables to a @@ -123,7 +123,7 @@ if (!value) return ESI_PROCESS_COMPLETE; - varState->addVariable (name.unsafeBuf(), name.size(), value); + varState->addVariable (name.rawBuf(), name.size(), value); value = NULL; @@ -194,7 +194,7 @@ ESIVariableExpression::eval (ESIVarState &state, char const *subref, char const *defaultOnEmpty) const { /* XXX: Implement evaluation of the expression */ - ESISegment::ListAppend (state.getOutput(), expression.unsafeBuf(), expression.size()); + ESISegment::ListAppend (state.getOutput(), expression.rawBuf(), expression.size()); } #endif /* USE_SQUID_ESI == 1 */ === modified file 'src/ESICustomParser.cc' --- src/ESICustomParser.cc 2009-02-04 23:25:42 +0000 +++ src/ESICustomParser.cc 2009-02-10 11:02:53 +0000 @@ -109,7 +109,8 @@ } size_t openESITags (0); - char const *currentPos = content.unsafeBuf(); + //erring on the safe side. Probably rawBuf would be ok too + char const *currentPos = content.termedBuf(); size_t remainingCount = content.size(); char const *tag = NULL; @@ -302,7 +303,7 @@ ESICustomParser::errorString() const { if (error.size()) - return error.unsafeBuf(); + return error.termedBuf(); else return "Parsing error strings not implemented"; } === modified file 'src/ESISegment.cc' --- src/ESISegment.cc 2009-02-04 23:25:42 +0000 +++ src/ESISegment.cc 2009-02-06 00:59:06 +0000 @@ -236,5 +236,5 @@ { String temp; temp.limitInit(buf, len); - debugs(86, 9, "ESISegment::dumpOne: \"" << temp.unsafeBuf() << "\""); + debugs(86, 9, "ESISegment::dumpOne: \"" << temp << "\""); } === modified file 'src/HttpHdrCc.cc' --- src/HttpHdrCc.cc 2009-01-31 17:04:05 +0000 +++ src/HttpHdrCc.cc 2009-02-12 16:06:20 +0000 @@ -235,9 +235,8 @@ if (EBIT_TEST(cc->mask, flag) && flag != CC_OTHER) { /* print option name */ - packerPrintf(p, (pcount ? ", %.*s" : "%.*s"), - CcFieldsInfo[flag].name.size(), - CcFieldsInfo[flag].name.rawBuf()); + packerPrintf(p, (pcount ? ", " SQUIDSTRINGPH : SQUIDSTRINGPH), + SQUIDSTRINGPRINT(CcFieldsInfo[flag].name)); /* handle options with values */ @@ -254,9 +253,9 @@ } } - if (cc->other.size()) - packerPrintf(p, (pcount ? ", %.*s" : "%.*s"), - cc->other.size(), cc->other.rawBuf()); + if (cc->other.size() != 0) + packerPrintf(p, (pcount ? ", " SQUIDSTRINGPH : SQUIDSTRINGPH), + SQUIDSTRINGPRINT(cc->other)); } /* negative max_age will clean old max_Age setting */ === modified file 'src/HttpHdrSc.cc' --- src/HttpHdrSc.cc 2009-01-31 17:23:17 +0000 +++ src/HttpHdrSc.cc 2009-02-12 16:06:20 +0000 @@ -257,9 +257,8 @@ if (EBIT_TEST(sc->mask, flag) && flag != SC_OTHER) { /* print option name */ - packerPrintf(p, (pcount ? ", %.*s" : "%.*s"), - ScFieldsInfo[flag].name.size(), - ScFieldsInfo[flag].name.rawBuf()); + packerPrintf(p, (pcount ? ", " SQUIDSTRINGPH : SQUIDSTRINGPH), + SQUIDSTRINGPRINT(ScFieldsInfo[flag].name)); /* handle options with values */ @@ -267,14 +266,14 @@ packerPrintf(p, "=%d", (int) sc->max_age); if (flag == SC_CONTENT) - packerPrintf(p, "=\"%.*s\"", sc->content.size(), sc->content.rawBuf()); + packerPrintf(p, "=\"" SQUIDSTRINGPH "\"", SQUIDSTRINGPRINT(sc->content)); pcount++; } } if (sc->target.size()) - packerPrintf (p, ";%.*s", sc->target.size(), sc->target.rawBuf()); + packerPrintf (p, ";" SQUIDSTRINGPH, SQUIDSTRINGPRINT(sc->target)); } void === modified file 'src/HttpHeader.cc' --- src/HttpHeader.cc 2009-01-31 18:23:44 +0000 +++ src/HttpHeader.cc 2009-02-09 15:47:31 +0000 @@ -1683,7 +1683,7 @@ } http_hdr_type -httpHeaderIdByName(const char *name, int name_len, const HttpHeaderFieldInfo * info, int end) +httpHeaderIdByName(const char *name, size_t name_len, const HttpHeaderFieldInfo * info, int end) { int i; === modified file 'src/HttpHeader.h' --- src/HttpHeader.h 2009-01-21 03:47:47 +0000 +++ src/HttpHeader.h 2009-02-11 15:28:22 +0000 @@ -33,12 +33,21 @@ #ifndef SQUID_HTTPHEADER_H #define SQUID_HTTPHEADER_H - /* because we pass a spec by value */ #include "HttpHeaderRange.h" /* HttpHeader holds a HttpHeaderMask */ #include "HttpHeaderMask.h" + +/* class forward declarations */ +class HttpVersion; +class HttpHdrContRange; +class HttpHdrCc; +class HttpHdrSc; +class HttpHdrRange; +class String; + + /* constant attributes of http header fields */ /** recognized or "known" header fields; @?@ add more! */ @@ -149,13 +158,6 @@ field_type type; }; -class HttpVersion; - -class HttpHdrContRange; - -class HttpHdrCc; - -class HttpHdrSc; /** Iteration for headers; use HttpHeaderPos as opaque type, do not interpret */ typedef ssize_t HttpHeaderPos; === modified file 'src/HttpReply.cc' --- src/HttpReply.cc 2009-02-04 13:48:24 +0000 +++ src/HttpReply.cc 2009-02-18 09:45:32 +0000 @@ -439,7 +439,8 @@ bool HttpReply::sanityCheckStartLine(MemBuf *buf, http_status *error) { - if (buf->contentSize() >= protoPrefix.size() && protoPrefix.cmp(buf->content(), protoPrefix.size()) != 0) { + //hack warning: using psize instead of size here due to type mismatches with MemBuf. + if (buf->contentSize() >= protoPrefix.psize() && protoPrefix.cmp(buf->content(), protoPrefix.size()) != 0) { debugs(58, 3, "HttpReply::sanityCheckStartLine: missing protocol prefix (" << protoPrefix << ") in '" << buf->content() << "'"); *error = HTTP_INVALID_HEADER; return false; === modified file 'src/HttpRequest.cc' --- src/HttpRequest.cc 2009-02-09 05:33:18 +0000 +++ src/HttpRequest.cc 2009-02-12 16:06:20 +0000 @@ -298,8 +298,8 @@ { assert(p); /* pack request-line */ - packerPrintf(p, "%s %.*s HTTP/1.0\r\n", - RequestMethodStr(method), urlpath.size(), urlpath.rawBuf()); + packerPrintf(p, "%s " SQUIDSTRINGPH " HTTP/1.0\r\n", + RequestMethodStr(method), SQUIDSTRINGPRINT(urlpath)); /* headers */ header.packInto(p); /* trailer */ === modified file 'src/ICAP/ICAPModXact.cc' --- src/ICAP/ICAPModXact.cc 2009-01-31 16:05:18 +0000 +++ src/ICAP/ICAPModXact.cc 2009-02-12 16:06:20 +0000 @@ -1029,8 +1029,8 @@ * XXX These should use HttpHdr interfaces instead of Printfs */ const Adaptation::ServiceConfig &s = service().cfg(); - buf.Printf("%s %.*s ICAP/1.0\r\n", s.methodStr(), s.uri.size(), s.uri.rawBuf()); - buf.Printf("Host: %.*s:%d\r\n", s.host.size(), s.host.rawBuf(), s.port); + 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 (!TheICAPConfig.reuse_connections) @@ -1040,14 +1040,12 @@ // as ICAP headers. if (virgin.header->header.has(HDR_PROXY_AUTHENTICATE)) { String vh=virgin.header->header.getByName("Proxy-Authenticate"); - buf.Printf("Proxy-Authenticate: %.*s\r\n", - vh.size(), vh.rawBuf()); + 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: %.*s\r\n", - vh.size(), vh.rawBuf()); + buf.Printf("Proxy-Authorization: " SQUIDSTRINGPH "\r\n", SQUIDSTRINGPRINT(vh)); } buf.Printf("Encapsulated: "); @@ -1111,7 +1109,7 @@ if (TheICAPConfig.send_client_username && request) makeUsernameHeader(request, buf); - // fprintf(stderr, "%s\n", unsafeBuf.content()); + // fprintf(stderr, "%s\n", buf.content()); buf.append(ICAP::crlf, 2); // terminate ICAP header @@ -1272,7 +1270,7 @@ Must(!preview.ad()); // do not add last-chunk because our Encapsulated header says null-body - // addLastRequestChunk(unsafeBuf); + // addLastRequestChunk(buf); preview.wrote(0, true); Must(preview.done()); === modified file 'src/ICAP/ICAPOptXact.cc' --- src/ICAP/ICAPOptXact.cc 2009-01-30 14:55:22 +0000 +++ src/ICAP/ICAPOptXact.cc 2009-02-12 16:06:20 +0000 @@ -44,9 +44,9 @@ { const Adaptation::Service &s = service(); const String uri = s.cfg().uri; - buf.Printf("OPTIONS %.*s ICAP/1.0\r\n", uri.size(), uri.rawBuf()); + buf.Printf("OPTIONS " SQUIDSTRINGPH " ICAP/1.0\r\n", SQUIDSTRINGPRINT(uri)); const String host = s.cfg().host; - buf.Printf("Host: %.*s:%d\r\n", host.size(), host.rawBuf(), s.cfg().port); + buf.Printf("Host: " SQUIDSTRINGPH ":%d\r\n", SQUIDSTRINGPRINT(host), s.cfg().port); buf.append(ICAP::crlf, 2); } === modified file 'src/ICAP/ICAPServiceRep.cc' --- src/ICAP/ICAPServiceRep.cc 2009-01-30 14:55:22 +0000 +++ src/ICAP/ICAPServiceRep.cc 2009-02-10 11:02:53 +0000 @@ -279,7 +279,7 @@ if (!method_found) { debugs(93,1, "WARNING: Squid is configured to use ICAP method " << cfg().methodStr() << - " for service " << cfg().uri.unsafeBuf() << + " for service " << cfg().uri << " but OPTIONS response declares the methods are " << method_list); } } @@ -293,7 +293,7 @@ // TODO: If skew is negative, the option will be considered down // because of stale options. We should probably change this. debugs(93, 1, "ICAP service's clock is skewed by " << skew << - " seconds: " << cfg().uri.unsafeBuf()); + " seconds: " << cfg().uri); } } === modified file 'src/ICAP/ICAPXaction.cc' --- src/ICAP/ICAPXaction.cc 2009-01-29 14:50:26 +0000 +++ src/ICAP/ICAPXaction.cc 2009-02-18 09:45:32 +0000 @@ -76,7 +76,7 @@ disableRetries(); // this will also safely drain pconn pool // TODO: check whether NULL domain is appropriate here - connection = icapPconnPool->pop(s.cfg().host.unsafeBuf(), s.cfg().port, NULL, client_addr, isRetriable); + connection = icapPconnPool->pop(s.cfg().host.termedBuf(), s.cfg().port, NULL, client_addr, isRetriable); if (connection >= 0) { debugs(93,3, HERE << "reused pconn FD " << connection); @@ -96,12 +96,12 @@ IpAddress outgoing; connection = comm_open(SOCK_STREAM, 0, outgoing, - COMM_NONBLOCKING, s.cfg().uri.unsafeBuf()); + COMM_NONBLOCKING, s.cfg().uri.termedBuf()); if (connection < 0) dieOnConnectionFailure(); // throws - debugs(93,3, typeName << " opens connection to " << s.cfg().host.unsafeBuf() << ":" << s.cfg().port); + debugs(93,3, typeName << " opens connection to " << s.cfg().host << ":" << s.cfg().port); // TODO: service bypass status may differ from that of a transaction typedef CommCbMemFunT TimeoutDialer; @@ -119,7 +119,7 @@ typedef CommCbMemFunT ConnectDialer; connector = asyncCall(93,3, "ICAPXaction::noteCommConnected", ConnectDialer(this, &ICAPXaction::noteCommConnected)); - commConnectStart(connection, s.cfg().host.unsafeBuf(), s.cfg().port, connector); + commConnectStart(connection, s.cfg().host.termedBuf(), s.cfg().port, connector); } /* @@ -148,19 +148,22 @@ cancelRead(); // may not work if (reuseConnection && !doneWithIo()) { + //status() adds leading spaces. debugs(93,5, HERE << "not reusing pconn due to pending I/O" << status()); reuseConnection = false; } if (reuseConnection) { IpAddress client_addr; + //status() adds leading spaces. debugs(93,3, HERE << "pushing pconn" << status()); AsyncCall::Pointer call = NULL; commSetTimeout(connection, -1, call); - icapPconnPool->push(connection, theService->cfg().host.unsafeBuf(), + icapPconnPool->push(connection, theService->cfg().host.termedBuf(), theService->cfg().port, NULL, client_addr); disableRetries(); } else { + //status() adds leading spaces. debugs(93,3, HERE << "closing pconn" << status()); // comm_close will clear timeout comm_close(connection); @@ -232,7 +235,7 @@ { debugs(93, 2, HERE << typeName << " failed: timeout with " << theService->cfg().methodStr() << " " << - theService->cfg().uri.unsafeBuf() << status()); + theService->cfg().uri << status()); reuseConnection = false; service().noteFailure(); @@ -295,7 +298,7 @@ /* * See comments in ICAPXaction.h about why we use commBuf - * here instead of reading directly into readBuf.unsafeBuf. + * here instead of reading directly into readBuf.buf. */ typedef CommCbMemFunT Dialer; reader = asyncCall(93,3, "ICAPXaction::noteCommRead", @@ -320,7 +323,7 @@ /* * See comments in ICAPXaction.h about why we use commBuf - * here instead of reading directly into readBuf.unsafeBuf. + * here instead of reading directly into readBuf.buf. */ if (io.size > 0) { === modified file 'src/Makefile.am' --- src/Makefile.am 2009-02-13 11:23:13 +0000 +++ src/Makefile.am 2009-02-17 08:40:45 +0000 @@ -1512,6 +1512,7 @@ $(SWAP_TEST_GEN_SOURCES) tests_testDiskIO_LDADD = \ ip/libip.la \ + libsquid.la \ @DISK_LIBS@ \ $(SWAP_TEST_LDADD) \ SquidConfig.o === modified file 'src/SquidString.h' --- src/SquidString.h 2009-02-04 22:39:55 +0000 +++ src/SquidString.h 2009-02-12 16:06:20 +0000 @@ -40,6 +40,12 @@ /** todo checks to wrap this include properly */ #include +/* squid string placeholder (for printf) */ +#ifndef SQUIDSTRINGPH +#define SQUIDSTRINGPH "%.*s" +#define SQUIDSTRINGPRINT(s) s.psize(),s.rawBuf() +#endif /* SQUIDSTRINGPH */ + #define DEBUGSTRINGS 0 #if DEBUGSTRINGS @@ -86,6 +92,9 @@ String (String const &); ~String(); + 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; @@ -97,8 +106,10 @@ */ _SQUID_INLINE_ char operator [](unsigned int pos) const; - _SQUID_INLINE_ int size() const; - _SQUID_INLINE_ char const * unsafeBuf() 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 @@ -126,33 +137,28 @@ void append(char const); void append (String const &); void absorb(String &old); - _SQUID_INLINE_ const char * pos(char const *) const; - _SQUID_INLINE_ const char * pos(char const ch) const; + const char * pos(char const *aString) const; + const char * pos(char const ch) const; ///offset from string start of the first occurrence of ch - /// returns std::string::npos if ch is not found - _SQUID_INLINE_ size_t find(char const ch) const; - _SQUID_INLINE_ const char * rpos(char const ch) const; + /// returns String::npos if ch is not found + 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_t count) 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_t count) const; + _SQUID_INLINE_ int caseCmp (char const *, size_type count) const; _SQUID_INLINE_ int caseCmp (String const &) const; - /** \deprecated Use assignment to [] position instead. - * ie str[0] = 'h'; - */ - _SQUID_INLINE_ void set(char const *loc, char const ch); - - /** \deprecated Use assignment to [] position instead. - * ie str[newLength] = '\0'; - */ - _SQUID_INLINE_ void cut(size_t newLength); - - /** \deprecated Use assignment to [] position instead. - * ie str[newLength] = '\0'; - */ - _SQUID_INLINE_ void cutPointer(char const *loc); + String substr(size_type from, size_type to) const; + + /** \deprecated Use assignment to [] position instead. + * ie str[newLength] = '\0'; + */ + _SQUID_INLINE_ void cut(size_type newLength); + #if DEBUGSTRINGS @@ -164,15 +170,19 @@ private: void allocAndFill(const char *str, int len); - void allocBuffer(size_t sz); - void setBuffer(char *buf, size_t sz); + void allocBuffer(size_type sz); + void setBuffer(char *buf, size_type sz); /* never reference these directly! */ - unsigned short int size_; /* buffer size; 64K limit */ + size_type size_; /* buffer size; 64K limit */ - unsigned short int len_; /* current length */ + 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); === modified file 'src/String.cc' --- src/String.cc 2009-02-03 17:36:15 +0000 +++ src/String.cc 2009-02-12 16:06:20 +0000 @@ -35,11 +35,20 @@ #include "squid.h" #include "Store.h" +#include "TextException.h" + +int +String::psize() const +{ + Must(size() < INT_MAX); + return size(); +} + // low-level buffer allocation, // does not free old buffer and does not adjust or look at len_ void -String::allocBuffer(size_t sz) +String::allocBuffer(String::size_type sz) { PROF_start(StringInitBuf); assert (undefined()); @@ -51,7 +60,7 @@ // low-level buffer assignment // does not free old buffer and does not adjust or look at len_ void -String::setBuffer(char *aBuf, size_t aSize) +String::setBuffer(char *aBuf, String::size_type aSize) { assert(undefined()); assert(aSize < 65536); @@ -233,6 +242,19 @@ old.len_ = 0; } +String +String::substr(String::size_type from, String::size_type to) const +{ + Must(from >= 0 && from < size()); + Must(to > 0 && to <= size()); + Must(to > from); + + String rv; + rv.limitInit(rawBuf()+from,to-from); + return rv; +} + + #if DEBUGSTRINGS void String::stat(StoreEntry *entry) const @@ -279,7 +301,7 @@ StringRegistry StringRegistry::Instance_; -extern size_t memStringCount(); +extern String::size_type memStringCount(); void StringRegistry::Stat(StoreEntry *entry) @@ -412,6 +434,56 @@ return p ? p : "(NULL)"; } +const char * +String::pos(char const *aString) const +{ + return strstr(termedBuf(), aString); +} + +const char * +String::pos(char const ch) const +{ + return strchr(termedBuf(), ch); +} + +const char * +String::rpos(char const ch) const +{ + return strrchr(termedBuf(), (ch)); +} + +String::size_type +String::find(char const ch) const +{ + const char *c; + c=pos(ch); + if (c==NULL) + return npos; + return c-rawBuf(); +} + +String::size_type +String::find(char const *aString) const +{ + const char *c; + c=pos(aString); + if (c==NULL) + return npos; + return c-rawBuf(); +} + +String::size_type +String::rfind(char const ch) const +{ + const char *c; + c=rpos(ch); + if (c==NULL) + return npos; + return c-rawBuf(); +} + + + #ifndef _USE_INLINE_ #include "String.cci" #endif === modified file 'src/String.cci' --- src/String.cci 2009-02-04 22:39:55 +0000 +++ src/String.cci 2009-02-18 09:45:32 +0000 @@ -32,9 +32,19 @@ * */ +#include "config.h" #include "assert.h" #include +#ifdef HAVE_STDINT_H +#include //for INT_MAX +#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 @@ -42,18 +52,12 @@ #endif } -int +String::size_type String::size() const { return len_; } -char const * -String::unsafeBuf() const -{ - return buf_; -} - bool String::defined() const { return buf_!=NULL; @@ -84,33 +88,6 @@ return buf_[pos]; } -const char * -String::pos(char const *aString) const -{ - return strstr(termedBuf(), aString); -} - -const char * -String::pos(char const ch) const -{ - return strchr(termedBuf(), ch); -} - -size_t -String::find(char const ch) const -{ - const char *c; - c=pos(ch); - if (c==NULL) - return std::string::npos; - return c-rawBuf(); -} - -const char * -String::rpos(char const ch) const -{ - return strrchr(termedBuf(), (ch)); -} int String::cmp (char const *aString) const @@ -130,7 +107,7 @@ } int -String::cmp (char const *aString, size_t count) const +String::cmp (char const *aString, String::size_type count) const { /* always the same at length 0 */ @@ -173,7 +150,7 @@ } int -String::caseCmp(char const *aString, size_t count) const +String::caseCmp(char const *aString, String::size_type count) const { return strncasecmp(termedBuf(), aString, count); } @@ -194,7 +171,7 @@ } void -String::cut(size_t newLength) +String::cut(String::size_type newLength) { if (newLength < 0 || newLength > len_) return; === modified file 'src/access_log.cc' --- src/access_log.cc 2009-01-29 14:50:26 +0000 +++ src/access_log.cc 2009-02-06 00:59:06 +0000 @@ -625,7 +625,7 @@ if (al->request) sb = al->request->header.getByName(fmt->data.header.header); - out = sb.unsafeBuf(); + out = sb.termedBuf(); quote = 1; @@ -635,7 +635,7 @@ if (al->reply) sb = al->reply->header.getByName(fmt->data.header.header); - out = sb.unsafeBuf(); + out = sb.termedBuf(); quote = 1; @@ -645,7 +645,7 @@ if (al->request) sb = al->request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); - out = sb.unsafeBuf(); + out = sb.termedBuf(); quote = 1; @@ -655,7 +655,7 @@ if (al->reply) sb = al->reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); - out = sb.unsafeBuf(); + out = sb.termedBuf(); quote = 1; @@ -764,7 +764,7 @@ case LFT_REQUEST_URLPATH: if (al->request) { - out = al->request->urlpath.unsafeBuf(); + out = al->request->urlpath.termedBuf(); quote = 1; } break; @@ -810,7 +810,7 @@ case LFT_TAG: if (al->request) - out = al->request->tag.unsafeBuf(); + out = al->request->tag.termedBuf(); quote = 1; @@ -823,7 +823,7 @@ case LFT_EXT_LOG: if (al->request) - out = al->request->extacl_log.unsafeBuf(); + out = al->request->extacl_log.termedBuf(); quote = 1; === modified file 'src/adaptation/Config.cc' --- src/adaptation/Config.cc 2009-02-16 23:33:48 +0000 +++ src/adaptation/Config.cc 2009-02-17 08:40:45 +0000 @@ -68,8 +68,11 @@ typedef Services::iterator SCI; for (SCI i = AllServices().begin(); i != AllServices().end(); ++i) { const ServiceConfig &cfg = (*i)->cfg(); - storeAppendPrintf(entry, "%s %.*s_%s %s %d %.*s\n", name, cfg.key.size(), cfg.key.rawBuf(), - cfg.methodStr(), cfg.vectPointStr(), cfg.bypass, cfg.uri.size(), cfg.uri.rawBuf()); + storeAppendPrintf(entry, "%s " SQUIDSTRINGPH "_%s %s %d " SQUIDSTRINGPH "\n", + name, + SQUIDSTRINGPRINT(cfg.key), + cfg.methodStr(), cfg.vectPointStr(), cfg.bypass, + SQUIDSTRINGPRINT(cfg.uri)); } } @@ -141,7 +144,7 @@ { typedef Groups::iterator GI; for (GI i = AllGroups().begin(); i != AllGroups().end(); ++i) - storeAppendPrintf(entry, "%s %s\n", name, (*i)->id.unsafeBuf()); + storeAppendPrintf(entry, "%s " SQUIDSTRINGPH "\n", name, SQUIDSTRINGPRINT((*i)->id)); } void @@ -173,7 +176,7 @@ typedef AccessRules::iterator CI; for (CI i = AllRules().begin(); i != AllRules().end(); ++i) { - snprintf(nom, 64, "%s %s", name, (*i)->groupId.unsafeBuf()); + snprintf(nom, 64, "%s " SQUIDSTRINGPH, name, SQUIDSTRINGPRINT((*i)->groupId)); dump_acl_access(entry, nom, (*i)->acl); } } === modified file 'src/adaptation/ServiceConfig.cc' --- src/adaptation/ServiceConfig.cc 2009-02-16 21:24:39 +0000 +++ src/adaptation/ServiceConfig.cc 2009-02-17 08:40:45 +0000 @@ -75,11 +75,13 @@ // extract scheme and use it as the service_configConfig protocol const char *schemeSuffix = "://"; - if (const char *schemeEnd = uri.pos(schemeSuffix)) - protocol.limitInit(uri.rawBuf(), schemeEnd - uri.rawBuf()); //substring + if (const String::size_type schemeEnd=uri.find(schemeSuffix)) + protocol=uri.substr(0,schemeEnd-1); + debugs(3, 5, HERE << cfg_filename << ':' << config_lineno << ": " << "service protocol is " << protocol); - if (!protocol.size()) + + if (protocol.size() == 0) return false; // skip scheme === modified file 'src/client_side.cc' --- src/client_side.cc 2009-02-13 04:32:34 +0000 +++ src/client_side.cc 2009-02-17 08:40:45 +0000 @@ -489,7 +489,7 @@ al.http.content_type = al.reply->content_type.termedBuf(); } else if (loggingEntry() && loggingEntry()->mem_obj) { al.http.code = loggingEntry()->mem_obj->getReply()->sline.status; - al.http.content_type = loggingEntry()->mem_obj->getReply()->content_type.unsafeBuf(); + al.http.content_type = loggingEntry()->mem_obj->getReply()->content_type.termedBuf(); } debugs(33, 9, "clientLogRequest: http.code='" << al.http.code << "'"); @@ -852,7 +852,7 @@ static void clientPackTermBound(String boundary, MemBuf * mb) { - mb->Printf("\r\n--%.*s--\r\n", boundary.size(), boundary.rawBuf()); + mb->Printf("\r\n--" SQUIDSTRINGPH "--\r\n", SQUIDSTRINGPRINT(boundary)); debugs(33, 6, "clientPackTermBound: buf offset: " << mb->size); } @@ -868,7 +868,7 @@ /* put boundary */ debugs(33, 5, "clientPackRangeHdr: appending boundary: " << boundary); /* rfc2046 requires to _prepend_ boundary with ! */ - mb->Printf("\r\n--%.*s\r\n", boundary.size(), boundary.rawBuf()); + mb->Printf("\r\n--" SQUIDSTRINGPH "\r\n", SQUIDSTRINGPRINT(boundary)); /* stuff the header with required entries and pack it */ @@ -890,7 +890,7 @@ } /** - * extracts a "range" from *unsafeBuf and appends them to mb, updating + * extracts a "range" from *buf and appends them to mb, updating * all offsets and such. */ void @@ -1168,8 +1168,8 @@ /* delete old Content-Type, add ours */ hdr->delById(HDR_CONTENT_TYPE); httpHeaderPutStrf(hdr, HDR_CONTENT_TYPE, - "multipart/byteranges; boundary=\"%s\"", - http->range_iter.boundary.unsafeBuf()); + "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(); @@ -1923,7 +1923,7 @@ req_sz = HttpParserReqSz(hp); } - /* We know the whole request is in hp->unsafeBuf now */ + /* We know the whole request is in hp->buf now */ assert(req_sz <= (size_t) hp->bufsiz); @@ -2639,7 +2639,7 @@ } /** - * called when new request body data has been buffered in in.unsafeBuf + * called when new request body data has been buffered in in.buf * may close the connection if we were closing and piped everything out */ void === modified file 'src/client_side_reply.cc' --- src/client_side_reply.cc 2009-02-13 04:32:34 +0000 +++ src/client_side_reply.cc 2009-02-17 08:40:45 +0000 @@ -1671,7 +1671,7 @@ } /* - * accepts chunk of a http message in unsafeBuf, parses prefix, filters headers and + * accepts chunk of a http message in buf, parses prefix, filters headers and * such, writes processed message to the message recipient */ void === modified file 'src/client_side_request.cc' --- src/client_side_request.cc 2009-02-04 22:39:55 +0000 +++ src/client_side_request.cc 2009-02-11 17:08:24 +0000 @@ -426,7 +426,7 @@ const char *asciiaddr; int l; struct in_addr addr; - p = request->x_forwarded_for_iterator.unsafeBuf(); + p = request->x_forwarded_for_iterator.termedBuf(); l = request->x_forwarded_for_iterator.size(); /* @@ -897,7 +897,7 @@ } #if FORW_VIA_DB - fvdbCountVia(s.unsafeBuf()); + fvdbCountVia(s.termedBuf()); #endif @@ -923,7 +923,7 @@ if (req_hdr->has(HDR_X_FORWARDED_FOR)) { String s = req_hdr->getList(HDR_X_FORWARDED_FOR); - fvdbCountForw(s.unsafeBuf()); + fvdbCountForw(s.termedBuf()); s.clean(); } === modified file 'src/eCAP/MessageRep.cc' --- src/eCAP/MessageRep.cc 2009-01-29 16:14:56 +0000 +++ src/eCAP/MessageRep.cc 2009-02-11 17:08:24 +0000 @@ -192,7 +192,7 @@ Ecap::RequestLineRep::Area Ecap::RequestLineRep::uri() const { - return Area::FromTempBuffer(theMessage.urlpath.unsafeBuf(), + return Area::FromTempBuffer(theMessage.urlpath.rawBuf(), theMessage.urlpath.size()); } === modified file 'src/errorpage.cc' --- src/errorpage.cc 2009-01-29 14:50:26 +0000 +++ src/errorpage.cc 2009-02-18 09:45:32 +0000 @@ -556,9 +556,16 @@ if (NULL != request) { Packer p; - str.Printf("%s %s HTTP/%d.%d\n", + String urlpath_or_slash; + + if (request->urlpath.size() != 0) + urlpath_or_slash = request->urlpath; + else + urlpath_or_slash = "/"; + + str.Printf("%s " SQUIDSTRINGPH " HTTP/%d.%d\n", RequestMethodStr(request->method), - request->urlpath.size() ? request->urlpath.unsafeBuf() : "/", + SQUIDSTRINGPRINT(urlpath_or_slash), request->http_ver.major, request->http_ver.minor); packerToMemInit(&p, &str); request->header.packInto(&p); @@ -734,9 +741,16 @@ if (NULL != request) { Packer p; - mb.Printf("%s %s HTTP/%d.%d\n", + String urlpath_or_slash; + + if (request->urlpath.size() != 0) + urlpath_or_slash = request->urlpath; + else + urlpath_or_slash = "/"; + + mb.Printf("%s " SQUIDSTRINGPH " HTTP/%d.%d\n", RequestMethodStr(request->method), - request->urlpath.size() ? request->urlpath.unsafeBuf() : "/", + SQUIDSTRINGPRINT(urlpath_or_slash), request->http_ver.major, request->http_ver.minor); packerToMemInit(&p, &mb); request->header.packInto(&p); @@ -928,8 +942,7 @@ */ if (!Config.errorDirectory && request && request->header.getList(HDR_ACCEPT_LANGUAGE, &hdr) ) { - const char *unsafeBuf = hdr.unsafeBuf(); // raw header string for parsing - int pos = 0; // current parsing position in header string + size_t pos = 0; // current parsing position in header string char *reset = NULL; // where to reset the p pointer for each new tag file char *dt = NULL; @@ -950,12 +963,12 @@ * - IFF a tag contains only two characters we can wildcard ANY translations matching: '-'? .* * with preference given to an exact match. */ - while (pos < hdr.size() && unsafeBuf[pos] != ';' && unsafeBuf[pos] != ',' && !xisspace(unsafeBuf[pos]) && dt < (dir+256) ) { - *dt++ = xtolower(unsafeBuf[pos++]); + while (pos < hdr.size() && hdr[pos] != ';' && hdr[pos] != ',' && !xisspace(hdr[pos]) && dt < (dir+256) ) { + *dt++ = xtolower(hdr[pos++]); } *dt++ = '\0'; // nul-terminated the filename content string before system use. - debugs(4, 9, HERE << "STATE: dt='" << dt << "', reset='" << reset << "', reset[1]='" << reset[1] << "', pos=" << pos << ", buf='" << &unsafeBuf[pos] << "'"); + debugs(4, 9, HERE << "STATE: dt='" << dt << "', reset='" << reset << "', reset[1]='" << reset[1] << "', pos=" << pos << ", buf='" << hdr.substr(pos,hdr.size()) << "'"); /* if we found anything we might use, try it. */ if (*reset != '\0') { @@ -983,8 +996,8 @@ dt = reset; // reset for next tag testing. we replace the failed name instead of cloning. // IFF we terminated the tag on ';' we need to skip the 'q=' bit to the next ',' or end. - while (pos < hdr.size() && unsafeBuf[pos] != ',') pos++; - if (unsafeBuf[pos] == ',') pos++; + while (pos < hdr.size() && hdr[pos] != ',') pos++; + if (hdr[pos] == ',') pos++; } } #endif /* USE_ERR_LOCALES */ === modified file 'src/external_acl.cc' --- src/external_acl.cc 2009-02-05 10:59:06 +0000 +++ src/external_acl.cc 2009-02-10 11:02:53 +0000 @@ -753,7 +753,7 @@ external_acl_cache_touch(acl->def, entry); result = entry->result; - external_acl_message = entry->message.unsafeBuf(); + external_acl_message = entry->message.termedBuf(); debugs(82, 2, "aclMatchExternal: " << acl->def->name << " = " << result); === modified file 'src/ftp.cc' --- src/ftp.cc 2009-02-03 23:13:10 +0000 +++ src/ftp.cc 2009-02-12 16:06:20 +0000 @@ -1445,16 +1445,20 @@ return 0; /* different username */ } +static String str_type_eq; void FtpStateData::checkUrlpath() { int l; - const char *t; - - if ((t = request->urlpath.rpos(';')) != NULL) { - if (strncasecmp(t + 1, "type=", 5) == 0) { - typecode = (char) xtoupper(*(t + 6)); - request->urlpath.cutPointer(t); + size_t t; + + if (str_type_eq.undefined()) //hack. String doesn't support global-static + str_type_eq="type="; + + if ((t = request->urlpath.rfind(';')) != String::npos) { + if (request->urlpath.substr(t+1,t+1+str_type_eq.size())==str_type_eq) { + typecode = (char)xtoupper(request->urlpath[t+str_type_eq.size()+1]); + request->urlpath.cut(t); } } @@ -3742,7 +3746,7 @@ request->urlpath.absorb(newbuf); safe_free(request->canonical); } else if ( !strncmp(request->urlpath.termedBuf(), "%2f", 3) ) { - newbuf.append(request->urlpath.rawBuf() +1, request->urlpath.size()-1); + newbuf.append(request->urlpath.substr(1,request->urlpath.size())); request->urlpath.absorb(newbuf); safe_free(request->canonical); } === modified file 'src/gopher.cc' --- src/gopher.cc 2009-01-31 16:40:06 +0000 +++ src/gopher.cc 2009-02-11 17:08:24 +0000 @@ -853,7 +853,7 @@ do_next_read = 0; } else if (len == 0) { /* Connection closed; retrieval done. */ - /* flush the rest of data in temp unsafeBuf if there is one. */ + /* flush the rest of data in temp buf if there is one. */ if (gopherState->conversion != gopher_ds::NORMAL) gopherEndHTML(gopherState); === modified file 'src/http.cc' --- src/http.cc 2009-02-09 10:52:15 +0000 +++ src/http.cc 2009-02-12 16:06:20 +0000 @@ -1542,11 +1542,9 @@ } else if (strcmp(orig_request->peer_login, "PASS") == 0) { if (orig_request->extacl_user.size() && orig_request->extacl_passwd.size()) { char loginbuf[256]; - snprintf(loginbuf, sizeof(loginbuf), "%.*s:%.*s", - orig_request->extacl_user.size(), - orig_request->extacl_user.rawBuf(), - orig_request->extacl_passwd.size(), - orig_request->extacl_passwd.rawBuf()); + snprintf(loginbuf, sizeof(loginbuf), SQUIDSTRINGPH ":" SQUIDSTRINGPH, + SQUIDSTRINGPRINT(orig_request->extacl_user), + SQUIDSTRINGPRINT(orig_request->extacl_passwd)); httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s", base64_encode(loginbuf)); } @@ -1573,11 +1571,9 @@ hdr_out->putStr(HDR_AUTHORIZATION, auth); } else if (orig_request->extacl_user.size() && orig_request->extacl_passwd.size()) { char loginbuf[256]; - snprintf(loginbuf, sizeof(loginbuf), "%.*s:%.*s", - orig_request->extacl_user.size(), - orig_request->extacl_user.rawBuf(), - orig_request->extacl_passwd.size(), - orig_request->extacl_passwd.rawBuf()); + snprintf(loginbuf, sizeof(loginbuf), SQUIDSTRINGPH ":" SQUIDSTRINGPH, + SQUIDSTRINGPRINT(orig_request->extacl_user), + SQUIDSTRINGPRINT(orig_request->extacl_passwd)); httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s", base64_encode(loginbuf)); } @@ -1808,7 +1804,7 @@ * pass on all other header fields * which are NOT listed by the special Connection: header. */ - if (strConnection.size()>0 && strListIsMember(&strConnection, e->name.unsafeBuf(), ',')) { + if (strConnection.size()>0 && strListIsMember(&strConnection, e->name.termedBuf(), ',')) { debugs(11, 2, "'" << e->name << "' header cropped by Connection: definition"); return; } === modified file 'src/peer_digest.cc' --- src/peer_digest.cc 2009-01-29 14:50:26 +0000 +++ src/peer_digest.cc 2009-02-12 10:46:08 +0000 @@ -231,7 +231,7 @@ { eventAdd("peerDigestCheck", peerDigestCheck, pd, (double) delay, 1); pd->times.next_check = squid_curtime + delay; - debugs(72, 3, "peerDigestSetCheck: will check peer " << pd->host.unsafeBuf() << " in " << delay << " secs"); + debugs(72, 3, "peerDigestSetCheck: will check peer " << pd->host << " in " << delay << " secs"); } /* @@ -241,10 +241,10 @@ peerDigestNotePeerGone(PeerDigest * pd) { if (pd->flags.requested) { - debugs(72, 2, "peerDigest: peer " << pd->host.unsafeBuf() << " gone, will destroy after fetch."); + debugs(72, 2, "peerDigest: peer " << pd->host << " gone, will destroy after fetch."); /* do nothing now, the fetching chain will notice and take action */ } else { - debugs(72, 2, "peerDigest: peer " << pd->host.unsafeBuf() << " is gone, destroying now."); + debugs(72, 2, "peerDigest: peer " << pd->host << " is gone, destroying now."); peerDigestDestroy(pd); } } @@ -279,7 +279,7 @@ /* per-peer limit */ if (req_time - pd->times.received < PeerDigestReqMinGap) { - debugs(72, 2, "peerDigestCheck: " << pd->host.unsafeBuf() << + debugs(72, 2, "peerDigestCheck: " << pd->host << ", avoiding close peer requests (" << (int) (req_time - pd->times.received) << " < " << (int) PeerDigestReqMinGap << " secs)."); @@ -289,7 +289,7 @@ /* global limit */ if (req_time - pd_last_req_time < GlobDigestReqMinGap) { - debugs(72, 2, "peerDigestCheck: " << pd->host.unsafeBuf() << + debugs(72, 2, "peerDigestCheck: " << pd->host << ", avoiding close requests (" << (int) (req_time - pd_last_req_time) << " < " << (int) GlobDigestReqMinGap << " secs)."); @@ -544,7 +544,7 @@ assert(reply); assert (reply->sline.status != 0); status = reply->sline.status; - debugs(72, 3, "peerDigestFetchReply: " << pd->host.unsafeBuf() << " status: " << status << + debugs(72, 3, "peerDigestFetchReply: " << pd->host << " status: " << status << ", expires: " << (long int) reply->expires << " (" << std::showpos << (int) (reply->expires - squid_curtime) << ")"); @@ -634,7 +634,7 @@ assert (fetch->entry->getReply()->sline.status != 0); if (fetch->entry->getReply()->sline.status != HTTP_OK) { - debugs(72, 1, "peerDigestSwapInHeaders: " << fetch->pd->host.unsafeBuf() << + debugs(72, 1, "peerDigestSwapInHeaders: " << fetch->pd->host << " status " << fetch->entry->getReply()->sline.status << " got cached!"); @@ -762,7 +762,7 @@ #endif else - host = pd->host.unsafeBuf(); + host = pd->host.termedBuf(); } debugs(72, 6, step_name << ": peer " << host << ", offset: " << @@ -813,7 +813,7 @@ peerDigestFetchStop(DigestFetchState * fetch, char *buf, const char *reason) { assert(reason); - debugs(72, 2, "peerDigestFetchStop: peer " << fetch->pd->host.unsafeBuf() << ", reason: " << reason); + debugs(72, 2, "peerDigestFetchStop: peer " << fetch->pd->host << ", reason: " << reason); peerDigestReqFinish(fetch, buf, 1, 1, 1, reason, 0); } @@ -822,7 +822,7 @@ peerDigestFetchAbort(DigestFetchState * fetch, char *buf, const char *reason) { assert(reason); - debugs(72, 2, "peerDigestFetchAbort: peer " << fetch->pd->host.unsafeBuf() << ", reason: " << reason); + debugs(72, 2, "peerDigestFetchAbort: peer " << fetch->pd->host << ", reason: " << reason); peerDigestReqFinish(fetch, buf, 1, 1, 1, reason, 1); } @@ -872,7 +872,7 @@ peerDigestPDFinish(DigestFetchState * fetch, int pcb_valid, int err) { PeerDigest *pd = fetch->pd; - const char *host = pd->host.unsafeBuf(); + const char *host = pd->host.termedBuf(); pd->times.received = squid_curtime; pd->times.req_delay = fetch->resp_time; @@ -986,7 +986,7 @@ { StoreDigestCBlock cblock; int freed_size = 0; - const char *host = pd->host.unsafeBuf(); + const char *host = pd->host.termedBuf(); xmemcpy(&cblock, buf, sizeof(cblock)); /* network -> host conversions */ @@ -1080,7 +1080,7 @@ const int bit_util = cacheDigestBitUtil(pd->cd); if (bit_util > 65) { - debugs(72, 0, "Warning: " << pd->host.unsafeBuf() << + debugs(72, 0, "Warning: " << pd->host << " peer digest has too many bits on (" << bit_util << "%%)."); return 0; @@ -1106,7 +1106,7 @@ assert(pd); - const char *host = pd->host.unsafeBuf(); + const char *host = pd->host.termedBuf(); storeAppendPrintf(e, "\npeer digest from %s\n", host); cacheDigestGuessStatsReport(&pd->stats.guess, e, host); === modified file 'src/protos.h' --- src/protos.h 2009-02-08 00:02:47 +0000 +++ src/protos.h 2009-02-11 15:28:22 +0000 @@ -179,6 +179,7 @@ SQUIDCEXTERN void ftpStart(FwdState *); class HttpRequest; +class HttpReply; /// \ingroup ServerProtocolFTPAPI SQUIDCEXTERN const char *ftpUrlWith2f(HttpRequest *); @@ -255,7 +256,7 @@ class HttpHeaderFieldInfo; SQUIDCEXTERN HttpHeaderFieldInfo *httpHeaderBuildFieldsInfo(const HttpHeaderFieldAttrs * attrs, int count); SQUIDCEXTERN void httpHeaderDestroyFieldsInfo(HttpHeaderFieldInfo * info, int count); -SQUIDCEXTERN http_hdr_type httpHeaderIdByName(const char *name, int name_len, const HttpHeaderFieldInfo * attrs, int end); +SQUIDCEXTERN http_hdr_type httpHeaderIdByName(const char *name, size_t name_len, const HttpHeaderFieldInfo * attrs, int end); SQUIDCEXTERN http_hdr_type httpHeaderIdByNameDef(const char *name, int name_len); SQUIDCEXTERN const char *httpHeaderNameById(int id); SQUIDCEXTERN int httpHeaderHasConnDir(const HttpHeader * hdr, const char *directive); === modified file 'src/store.cc' --- src/store.cc 2009-02-08 00:02:47 +0000 +++ src/store.cc 2009-02-12 10:46:08 +0000 @@ -696,9 +696,9 @@ #if X_ACCELERATOR_VARY vary = mem_obj->getReply()->header.getList(HDR_X_ACCELERATOR_VARY); - if (vary.unsafeBuf()) { + if (vary.defined()) { /* Again, we own this structure layout */ - rep->header.putStr(HDR_X_ACCELERATOR_VARY, vary.unsafeBuf()); + rep->header.putStr(HDR_X_ACCELERATOR_VARY, vary.termedBuf()); vary.clean(); } === modified file 'src/store_log.cc' --- src/store_log.cc 2009-01-29 14:50:26 +0000 +++ src/store_log.cc 2009-02-12 16:06:20 +0000 @@ -52,12 +52,17 @@ static Logfile *storelog = NULL; +static String str_unknown; + void storeLog(int tag, const StoreEntry * e) { MemObject *mem = e->mem_obj; HttpReply const *reply; + if (str_unknown.undefined()) + str_unknown="unknown"; //hack. Delay initialization as string doesn't support global variables.. + if (NULL == storelog) return; @@ -75,7 +80,10 @@ * Because if we print it before the swap file number, it'll break * the existing log format. */ - logfilePrintf(storelog, "%9d.%03d %-7s %02d %08X %s %4d %9d %9d %9d %s %"PRId64"/%"PRId64" %s %s\n", + + String ctype=(reply->content_type.size() ? reply->content_type.termedBuf() : str_unknown); + + logfilePrintf(storelog, "%9d.%03d %-7s %02d %08X %s %4d %9d %9d %9d " SQUIDSTRINGPH " %"PRId64"/%"PRId64" %s %s\n", (int) current_time.tv_sec, (int) current_time.tv_usec / 1000, storeLogTags[tag], @@ -86,7 +94,7 @@ (int) reply->date, (int) reply->last_modified, (int) reply->expires, - reply->content_type.size() ? reply->content_type.unsafeBuf() : "unknown", + SQUIDSTRINGPRINT(ctype), reply->content_length, e->contentLen(), RequestMethodStr(mem->method), === modified file 'src/tests/testEvent.cc' --- src/tests/testEvent.cc 2009-01-30 14:55:22 +0000 +++ src/tests/testEvent.cc 2009-02-11 15:28:22 +0000 @@ -97,7 +97,7 @@ /* loop over the strings, showing exactly where they differ (if at all) */ printf("Actual Text:\n"); /* TODO: these should really be just [] lookups, but String doesn't have those here yet. */ - for ( int i = 0; i < anEntry->_appended_text.size(); i++) { + for ( unsigned int i = 0; i < anEntry->_appended_text.size(); i++) { CPPUNIT_ASSERT( expect[i] ); CPPUNIT_ASSERT( anEntry->_appended_text[i] ); === modified file 'src/tests/testString.cc' --- src/tests/testString.cc 2008-05-27 14:01:49 +0000 +++ src/tests/testString.cc 2009-02-11 15:28:22 +0000 @@ -59,3 +59,11 @@ CPPUNIT_ASSERT(right.cmp("foo") < 0); CPPUNIT_ASSERT(right.cmp("foo", 1) < 0); } + +void testString::testSubstr() +{ + String s("0123456789"); + String check=s.substr(3,5); + String ref("34"); + CPPUNIT_ASSERT(check == ref); +} === modified file 'src/tests/testString.h' --- src/tests/testString.h 2007-05-29 19:31:36 +0000 +++ src/tests/testString.h 2009-02-09 15:47:31 +0000 @@ -14,6 +14,8 @@ CPPUNIT_TEST( testCmpDefault ); CPPUNIT_TEST( testCmpEmptyString ); CPPUNIT_TEST( testCmpNotEmptyDefault ); + CPPUNIT_TEST( testSubstr ); + CPPUNIT_TEST_SUITE_END(); public: @@ -23,6 +25,7 @@ void testCmpDefault(); void testCmpEmptyString(); void testCmpNotEmptyDefault(); + void testSubstr(); }; #endif === modified file 'src/url.cc' --- src/url.cc 2009-02-03 17:36:15 +0000 +++ src/url.cc 2009-02-12 16:06:20 +0000 @@ -439,9 +439,8 @@ return request->canonical; if (request->protocol == PROTO_URN) { - snprintf(urlbuf, MAX_URL, "urn:%.*s", - request->urlpath.size(), - request->urlpath.rawBuf()); + snprintf(urlbuf, MAX_URL, "urn:" SQUIDSTRINGPH, + SQUIDSTRINGPRINT(request->urlpath)); } else { /// \todo AYJ: this could use "if..else and method == METHOD_CONNECT" easier. switch (request->method.id()) { @@ -456,14 +455,13 @@ if (request->port != urlDefaultPort(request->protocol)) snprintf(portbuf, 32, ":%d", request->port); - snprintf(urlbuf, MAX_URL, "%s://%s%s%s%s%.*s", + snprintf(urlbuf, MAX_URL, "%s://%s%s%s%s" SQUIDSTRINGPH, ProtocolStr[request->protocol], request->login, *request->login ? "@" : null_string, request->GetHost(), portbuf, - request->urlpath.size(), - request->urlpath.rawBuf()); + SQUIDSTRINGPRINT(request->urlpath)); break; } @@ -485,8 +483,8 @@ char *t; if (request->protocol == PROTO_URN) { - snprintf(buf, MAX_URL, "urn:%.*s", - request->urlpath.size(), request->urlpath.rawBuf()); + snprintf(buf, MAX_URL, "urn:" SQUIDSTRINGPH, + SQUIDSTRINGPRINT(request->urlpath)); } else { /// \todo AYJ: this could use "if..else and method == METHOD_CONNECT" easier. switch (request->method.id()) { @@ -514,13 +512,12 @@ strcat(loginbuf, "@"); } - snprintf(buf, MAX_URL, "%s://%s%s%s%.*s", + snprintf(buf, MAX_URL, "%s://%s%s%s" SQUIDSTRINGPH, ProtocolStr[request->protocol], loginbuf, request->GetHost(), portbuf, - request->urlpath.size(), - request->urlpath.rawBuf()); + SQUIDSTRINGPRINT(request->urlpath)); /* * strip arguments AFTER a question-mark */ @@ -589,9 +586,8 @@ char *urlbuf = (char *)xmalloc(MAX_URL * sizeof(char)); if (req->protocol == PROTO_URN) { - snprintf(urlbuf, MAX_URL, "urn:%.*s", - req->urlpath.size(), - req->urlpath.rawBuf()); + snprintf(urlbuf, MAX_URL, "urn:" SQUIDSTRINGPH, + SQUIDSTRINGPRINT(req->urlpath)); return (urlbuf); } === modified file 'src/urn.cc' --- src/urn.cc 2009-02-03 17:36:15 +0000 +++ src/urn.cc 2009-02-12 11:17:16 +0000 @@ -57,7 +57,7 @@ char *getHost (String &urlpath); void setUriResFromRequest(HttpRequest *); bool RequestNeedsMenu(HttpRequest *r); - void updateRequestURL(HttpRequest *r, char const *newPath); + void updateRequestURL(HttpRequest *r, char const *newPath, const size_t newPath_len); void createUriResRequest (String &uri); virtual ~UrnState(); @@ -171,7 +171,7 @@ /** FIXME: this appears to be parsing the URL. *very* badly. */ /* a proper encapsulated URI/URL type needs to clear this up. */ - if ((p=urlpath.find(':')) != std::string::npos) { + if ((p=urlpath.find(':')) != String::npos) { result=xstrndup(urlpath.rawBuf(),p-1); } else { result = xstrndup(urlpath.rawBuf(),urlpath.size()); @@ -182,13 +182,16 @@ bool UrnState::RequestNeedsMenu(HttpRequest *r) { - return strncasecmp(r->urlpath.unsafeBuf(), "menu.", 5) == 0; + if (r->urlpath.size() < 5) + return false; + //now we're sure it's long enough + return strncasecmp(r->urlpath.rawBuf(), "menu.", 5) == 0; } void -UrnState::updateRequestURL(HttpRequest *r, char const *newPath) +UrnState::updateRequestURL(HttpRequest *r, char const *newPath, const size_t newPath_len) { - char *new_path = xstrdup (newPath); + char *new_path = xstrndup (newPath, newPath_len); r->urlpath = new_path; xfree(new_path); } @@ -198,7 +201,8 @@ { LOCAL_ARRAY(char, local_urlres, 4096); char *host = getHost (uri); - snprintf(local_urlres, 4096, "http://%s/uri-res/N2L?urn:%s", host, uri.unsafeBuf()); + snprintf(local_urlres, 4096, "http://%s/uri-res/N2L?urn:" SQUIDSTRINGPH, + host, SQUIDSTRINGPRINT(uri)); safe_free (host); safe_free (urlres); urlres = xstrdup (local_urlres); @@ -209,7 +213,7 @@ UrnState::setUriResFromRequest(HttpRequest *r) { if (RequestNeedsMenu(r)) { - updateRequestURL(r, r->urlpath.unsafeBuf() + 5); + updateRequestURL(r, r->urlpath.rawBuf() + 5, r->urlpath.size() - 5 ); flags.force_menu = 1; } === modified file 'src/whois.cc' --- src/whois.cc 2009-01-29 14:50:26 +0000 +++ src/whois.cc 2009-02-12 11:17:16 +0000 @@ -98,7 +98,8 @@ buf = (char *)xmalloc(l); - snprintf(buf, l, "%s\r\n", p->request->urlpath.unsafeBuf() + 1); + String str_print=p->request->urlpath.substr(1,p->request->urlpath.size()); + snprintf(buf, l, SQUIDSTRINGPH"\r\n", SQUIDSTRINGPRINT(str_print)); comm_write(fd, buf, strlen(buf), whoisWriteComplete, p, NULL); comm_read(fd, p->buf, BUFSIZ, whoisReadReply, p); # Begin bundle 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 woSGbip3WA==