#define SQUID_SBUF_H
#include "base/InstanceId.h"
+#include "Debug.h"
#include "MemBlob.h"
#include "SBufExceptions.h"
#include "SquidString.h"
return buf;
}
+/**
+ * Copy an SBuf into a C-string.
+ *
+ * Guarantees that the output is a c-string of length
+ * no more than SBuf::length()+1 by appending a \0 byte
+ * to the C-string copy of the SBuf contents.
+ *
+ * \note The destination c-string memory MUST be of at least
+ * length()+1 bytes.
+ *
+ * No protection is added to prevent \0 bytes within the string.
+ * Unexpectedly short strings are a problem for the receiver
+ * to deal with if it cares.
+ *
+ * Unlike SBuf::c_str() does not alter the SBuf in any way.
+ */
+inline void
+SBufToCstring(char *d, const SBuf &s)
+{
+ s.copy(d, s.length());
+ d[s.length()] = '\0'; // 0-terminate the destination
+ debugs(1, DBG_DATA, "built c-string '" << d << "' from " << s);
+}
+
+/**
+ * Copy an SBuf into a C-string.
+ *
+ * \see SBufToCstring(char *d, const SBuf &s)
+ *
+ * \returns A dynamically allocated c-string based on SBuf.
+ * Use xfree() / safe_free() to release the c-string.
+ */
+inline char *
+SBufToCstring(const SBuf &s)
+{
+ char *d = static_cast<char*>(xmalloc(s.length()+1));
+ SBufToCstring(d, s);
+ return d;
+}
+
inline
SBufIterator::SBufIterator(const SBuf &s, size_type pos)
: iter(s.rawContent()+pos)
int
ACLUrlStrategy::match (ACLData<char const *> * &data, ACLFilledChecklist *checklist, ACLFlags &)
{
- const SBuf &tmp = checklist->request->effectiveRequestUri();
- char *esc_buf = xstrndup(tmp.rawContent(), tmp.length()+1);
+ char *esc_buf = SBufToCstring(checklist->request->effectiveRequestUri());
rfc1738_unescape(esc_buf);
int result = data->match(esc_buf);
xfree(esc_buf);
if (checklist->request->url.path().isEmpty())
return -1;
- SBuf tmp = checklist->request->url.path();
- char *esc_buf = xstrndup(tmp.rawContent(), tmp.length()+1);
+ char *esc_buf = SBufToCstring(checklist->request->url.path());
rfc1738_unescape(esc_buf);
int result = data->match(esc_buf);
xfree(esc_buf);
* requested url. may be rewritten later, so make extra room */
int url_sz = hp->requestUri().length() + Config.appendDomainLen + 5;
http->uri = (char *)xcalloc(url_sz, 1);
- xstrncpy(http->uri, hp->requestUri().rawContent(), hp->requestUri().length()+1);
+ SBufToCstring(http->uri, hp->requestUri());
}
result->flags.parsed_ok = 1;
}
/* ACCESS_ALLOWED continues here ... */
- safe_free(http->uri);
- const SBuf tmp(http->request->effectiveRequestUri());
- http->uri = xstrndup(tmp.rawContent(), tmp.length()+1);
+ xfree(http->uri);
+ http->uri = SBufToCstring(http->request->effectiveRequestUri());
http->doCallouts();
}
}
// update the current working ClientHttpRequest fields
- safe_free(http->uri);
- const SBuf tmp(new_request->effectiveRequestUri());
- http->uri = xstrndup(tmp.rawContent(), tmp.length()+1);
+ xfree(http->uri);
+ http->uri = SBufToCstring(new_request->effectiveRequestUri());
HTTPMSGUNLOCK(old_request);
http->request = new_request;
HTTPMSGLOCK(http->request);
* Store the new URI for logging
*/
xfree(uri);
- const SBuf tmp(request->effectiveRequestUri());
- uri = xstrndup(tmp.rawContent(), tmp.length()+1);
+ uri = SBufToCstring(request->effectiveRequestUri());
setLogUri(this, urlCanonicalClean(request));
assert(request->method.id());
} else if (HttpReply *new_rep = dynamic_cast<HttpReply*>(msg)) {
debugs(9, 3, HERE << "code=" << code);
if (code == 200) {
- const SBuf tmp = ftpState->request->url.path();
- p = path = xstrndup(tmp.rawContent(),tmp.length()+1);
+ p = path = SBufToCstring(ftpState->request->url.path());
if (*p == '/')
++p;
safe_free(ftpState->filepath);
/* Build the new path (urlpath begins with /) */
- const SBuf tmp = ftpState->request->url.path();
- path = xstrndup(tmp.rawContent(), tmp.length()+1);
- path[tmp.length()] = '\0';
+ path = SBufToCstring(ftpState->request->url.path());
rfc1738_unescape(path);
*type_id = typeId[0];
if (request) {
- SBuf path = tok.remaining().substr(0, MAX_URL-1);
- xstrncpy(request, path.rawContent(), path.length()+1);
+ SBufToCstring(request, tok.remaining().substr(0, MAX_URL-1));
/* convert %xx to char */
rfc1738_unescape(request);
}
p.chop(0, sizeof(header)-1);
// return the header field-value
- xstrncpy(header, p.rawContent(), p.length()+1);
+ SBufToCstring(header, p);
debugs(25, 5, "returning " << header);
return header;
}
++statCounter.server.other.requests;
tunnelState = new TunnelStateData;
- tunnelState->url = xstrndup(url.rawContent(), url.length()+1);
+ tunnelState->url = SBufToCstring(url);
tunnelState->request = request;
tunnelState->server.size_ptr = NULL; //Set later if ClientSocketContext is available
// XXX: crops bits in the middle of the combined URL.
lastSlashPos = MAX_URL - urllen - 1;
}
- xstrncpy(&urlbuf[urllen], path.rawContent(), lastSlashPos);
+ SBufToCstring(&urlbuf[urllen], path.substr(0,lastSlashPos));
urllen += lastSlashPos;
if (urllen + 1 < MAX_URL) {
xstrncpy(&urlbuf[urllen], relUrl, MAX_URL - urllen - 1);
char *
UrnState::getHost(const SBuf &urlpath)
{
- char * result;
- size_t p;
-
/** 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(':')) != SBuf::npos) {
- result = xstrndup(urlpath.rawContent(), (p-1) /*but xstrndup truncates*/+1 );
- } else {
- result = xstrndup(urlpath.rawContent(), urlpath.length()+1);
- }
- return result;
+ size_t p;
+ if ((p = urlpath.find(':')) != SBuf::npos)
+ return SBufToCstring(urlpath.substr(0, p-1));
+
+ return SBufToCstring(urlpath);
}
void