/* DEBUG: section 55 HTTP Header */
#include "squid.h"
+#include "base/CharacterSet.h"
#include "base/EnumIterator.h"
#include "base64.h"
#include "globals.h"
if (!e || skipUpdateHeader(e->id))
continue;
String value;
- const char *name = e->name.termedBuf();
- if (!hasNamed(name, strlen(name), &value) ||
- (value != fresh->getByName(name)))
+ if (!hasNamed(e->name, &value) ||
+ (value != fresh->getByName(e->name)))
return true;
}
return false;
if (e->id != Http::HdrType::OTHER)
delById(e->id);
else
- delByName(e->name.termedBuf());
+ delByName(e->name);
}
pos = HttpHeaderInitPos;
return 0;
}
- if (e->id == Http::HdrType::OTHER && stringHasWhitespace(e->name.termedBuf())) {
+ /* AYJ 2017-05-23: I suspect we need to change this whitespace check to conform to the
+ updated WSP character set in RFC 7230/7231. For now I left it as the
+ characters in w_space which the previous code was using. */
+ static CharacterSet wsp = (CharacterSet::WSP + CharacterSet::CR + CharacterSet::LF);
+ if (e->id == Http::HdrType::OTHER && e->name.findFirstOf(wsp) != SBuf::npos) {
debugs(55, warnOnError, "WARNING: found whitespace in HTTP header name {" <<
getStringPrefix(field_start, field_end-field_start) << "}");
break;
}
if (maskThisEntry) {
- p->append(e->name.rawBuf(), e->name.size());
+ p->append(e->name.rawContent(), e->name.length());
p->append(": ** NOT DISPLAYED **\r\n", 23);
} else {
e->packInto(p);
return nullptr; /* not reached */
}
-/*
- * deletes all fields with a given name if any, returns #fields deleted;
- */
int
-HttpHeader::delByName(const char *name)
+HttpHeader::delByName(const SBuf &name)
{
int count = 0;
HttpHeaderPos pos = HttpHeaderInitPos;
- HttpHeaderEntry *e;
httpHeaderMaskInit(&mask, 0); /* temporal inconsistency */
debugs(55, 9, "deleting '" << name << "' fields in hdr " << this);
- while ((e = getEntry(&pos))) {
+ while (const HttpHeaderEntry *e = getEntry(&pos)) {
if (!e->name.caseCmp(name))
delAt(pos, count);
else
e = static_cast<HttpHeaderEntry*>(entries[pos]);
entries[pos] = NULL;
/* decrement header length, allow for ": " and crlf */
- len -= e->name.size() + 2 + e->value.size() + 2;
+ len -= e->name.length() + 2 + e->value.size() + 2;
assert(len >= 0);
delete e;
++headers_deleted;
{
assert(e);
assert(any_HdrType_enum_value(e->id));
- assert(e->name.size());
+ assert(e->name.length());
debugs(55, 7, this << " adding entry: " << e->id << " at " << entries.size());
entries.push_back(e);
/* increment header length, allow for ": " and crlf */
- len += e->name.size() + 2 + e->value.size() + 2;
+ len += e->name.length() + 2 + e->value.size() + 2;
}
/* inserts an entry;
entries.insert(entries.begin(),e);
/* increment header length, allow for ": " and crlf */
- len += e->name.size() + 2 + e->value.size() + 2;
+ len += e->name.length() + 2 + e->value.size() + 2;
}
bool
}
bool
-HttpHeader::hasNamed(const char *name, int namelen, String *result) const
+HttpHeader::hasNamed(const char *name, unsigned int namelen, String *result) const
{
Http::HdrType id;
HttpHeaderPos pos = HttpHeaderInitPos;
/* Sorry, an unknown header name. Do linear search */
bool found = false;
while ((e = getEntry(&pos))) {
- if (e->id == Http::HdrType::OTHER && e->name.size() == static_cast<String::size_type>(namelen) && e->name.caseCmp(name, namelen) == 0) {
+ if (e->id == Http::HdrType::OTHER && e->name.length() == namelen && e->name.caseCmp(name, namelen) == 0) {
found = true;
if (!result)
break;
assert(any_registered_header(id));
assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftInt); /* must be of an appropriate type */
assert(number >= 0);
- addEntry(new HttpHeaderEntry(id, NULL, xitoa(number)));
+ addEntry(new HttpHeaderEntry(id, SBuf(), xitoa(number)));
}
void
assert(any_registered_header(id));
assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftInt64); /* must be of an appropriate type */
assert(number >= 0);
- addEntry(new HttpHeaderEntry(id, NULL, xint64toa(number)));
+ addEntry(new HttpHeaderEntry(id, SBuf(), xint64toa(number)));
}
void
assert(any_registered_header(id));
assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftDate_1123); /* must be of an appropriate type */
assert(htime >= 0);
- addEntry(new HttpHeaderEntry(id, NULL, mkrfc1123(htime)));
+ addEntry(new HttpHeaderEntry(id, SBuf(), mkrfc1123(htime)));
}
void
assert(any_registered_header(id));
assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftStr); /* must be of an appropriate type */
assert(str);
- addEntry(new HttpHeaderEntry(id, NULL, str));
+ addEntry(new HttpHeaderEntry(id, SBuf(), str));
}
void
mb.init();
cc->packInto(&mb);
/* put */
- addEntry(new HttpHeaderEntry(Http::HdrType::CACHE_CONTROL, NULL, mb.buf));
+ addEntry(new HttpHeaderEntry(Http::HdrType::CACHE_CONTROL, SBuf(), mb.buf));
/* cleanup */
mb.clean();
}
mb.init();
httpHdrContRangePackInto(cr, &mb);
/* put */
- addEntry(new HttpHeaderEntry(Http::HdrType::CONTENT_RANGE, NULL, mb.buf));
+ addEntry(new HttpHeaderEntry(Http::HdrType::CONTENT_RANGE, SBuf(), mb.buf));
/* cleanup */
mb.clean();
}
mb.init();
range->packInto(&mb);
/* put */
- addEntry(new HttpHeaderEntry(Http::HdrType::RANGE, NULL, mb.buf));
+ addEntry(new HttpHeaderEntry(Http::HdrType::RANGE, SBuf(), mb.buf));
/* cleanup */
mb.clean();
}
mb.init();
sc->packInto(&mb);
/* put */
- addEntry(new HttpHeaderEntry(Http::HdrType::SURROGATE_CONTROL, NULL, mb.buf));
+ addEntry(new HttpHeaderEntry(Http::HdrType::SURROGATE_CONTROL, SBuf(), mb.buf));
/* cleanup */
mb.clean();
}
{
assert(name && value);
debugs(55, 8, this << " adds ext entry " << name << " : " << value);
- addEntry(new HttpHeaderEntry(Http::HdrType::OTHER, name, value));
+ addEntry(new HttpHeaderEntry(Http::HdrType::OTHER, SBuf(name), value));
}
int
* HttpHeaderEntry
*/
-HttpHeaderEntry::HttpHeaderEntry(Http::HdrType anId, const char *aName, const char *aValue)
+HttpHeaderEntry::HttpHeaderEntry(Http::HdrType anId, const SBuf &aName, const char *aValue)
{
assert(any_HdrType_enum_value(anId));
id = anId;
Http::HdrType id = Http::HeaderLookupTable.lookup(field_start,name_len).id;
debugs(55, 9, "got hdr-id=" << id);
- String name;
+ SBuf theName;
String value;
/* set field name */
if (id == Http::HdrType::OTHER)
- name.limitInit(field_start, name_len);
+ theName.append(field_start, name_len);
else
- name = Http::HeaderLookupTable.lookup(id).name;
+ theName = Http::HeaderLookupTable.lookup(id).name;
/* trim field value */
while (value_start < field_end && xisspace(*value_start))
if (field_end - value_start > 65534) {
/* String must be LESS THAN 64K and it adds a terminating NULL */
- debugs(55, DBG_IMPORTANT, "WARNING: ignoring '" << name << "' header of " << (field_end - value_start) << " bytes");
-
- if (id == Http::HdrType::OTHER)
- name.clean();
-
+ debugs(55, DBG_IMPORTANT, "WARNING: ignoring '" << theName << "' header of " << (field_end - value_start) << " bytes");
return NULL;
}
if (id != Http::HdrType::BAD_HDR)
++ headerStatsTable[id].seenCount;
- debugs(55, 9, "parsed HttpHeaderEntry: '" << name << ": " << value << "'");
+ debugs(55, 9, "parsed HttpHeaderEntry: '" << theName << ": " << value << "'");
- return new HttpHeaderEntry(id, name.termedBuf(), value.termedBuf());
+ return new HttpHeaderEntry(id, theName, value.termedBuf());
}
HttpHeaderEntry *
HttpHeaderEntry::clone() const
{
- return new HttpHeaderEntry(id, name.termedBuf(), value.termedBuf());
+ return new HttpHeaderEntry(id, name, value.termedBuf());
}
void
HttpHeaderEntry::packInto(Packable * p) const
{
assert(p);
- p->append(name.rawBuf(), name.size());
+ p->append(name.rawContent(), name.length());
p->append(": ", 2);
p->append(value.rawBuf(), value.size());
p->append("\r\n", 2);
int headers_deleted = 0;
while ((e = getEntry(&pos))) {
- if (strListIsMember(&strConnection, e->name.termedBuf(), ','))
+ if (strListIsMember(&strConnection, e->name, ','))
delAt(pos, headers_deleted);
}
if (headers_deleted)
MEMPROXY_CLASS(HttpHeaderEntry);
public:
- HttpHeaderEntry(Http::HdrType id, const char *name, const char *value);
+ HttpHeaderEntry(Http::HdrType id, const SBuf &name, const char *value);
~HttpHeaderEntry();
static HttpHeaderEntry *parse(const char *field_start, const char *field_end);
HttpHeaderEntry *clone() const;
int64_t getInt64() const;
Http::HdrType id;
- String name;
+ SBuf name;
String value;
};
void packInto(Packable * p, bool mask_sensitive_info=false) const;
HttpHeaderEntry *getEntry(HttpHeaderPos * pos) const;
HttpHeaderEntry *findEntry(Http::HdrType id) const;
- int delByName(const char *name);
+ /// deletes all fields with a given name, if any.
+ /// \return #fields deleted
+ int delByName(const SBuf &name);
+ /// \deprecated use SBuf method instead. performance regression: reallocates
+ int delByName(const char *name) { return delByName(SBuf(name)); }
int delById(Http::HdrType id);
void delAt(HttpHeaderPos pos, int &headers_deleted);
void refreshMask();
/// returns true iff a [possibly empty] named field is there
/// when returning true, also sets the `value` parameter (if it is not nil)
bool hasNamed(const SBuf &s, String *value = 0) const;
- bool hasNamed(const char *name, int namelen, String *value = 0) const;
+ /// \deprecated use SBuf method instead.
+ bool hasNamed(const char *name, unsigned int namelen, String *value = 0) const;
String getByNameListMember(const char *name, const char *member, const char separator) const;
String getListMember(Http::HdrType id, const char *member, const char separator) const;
int has(Http::HdrType id) const;