1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-09-28 19:05:55 +08:00
ULib/examples/http_header/HttpCookie.cpp
stefanocasazza 08e7f90afd sync
2016-05-23 14:58:24 +02:00

368 lines
7.5 KiB
C++

// HttpCookie.cpp
#include <HttpCookie.h>
/*
The following grammar uses the notation, and tokens DIGIT (decimal digits) and
token (informally, a sequence of non-special, non-white space characters).
cookie = "Cookie:" cookie-version 1*((";" | ",") cookie-value)
cookie-value = NAME "=" VALUE [";" path] [";" domain] [";" port]
cookie-version = "$Version" "=" value
NAME = attr
VALUE = value
path = "$Path" "=" value
domain = "$Domain" "=" value
port = "$Port" [ "=" <"> value <"> ]
attr = token
value = word
word = token | quoted-string
Example:
Cookie: $Version="1";
Part_Number="Riding_Rocket_0023"; $Path="/acme/ammo";
Part_Number="Rocket_Launcher_0001"; $Path="/acme"
*/
// #define SERGIO
#ifdef SERGIO
static unsigned cookie_split(UVector<UString>& vec, const UString& buffer, const char* delim)
{
U_TRACE(5, "cookie_split(%p,%.*S,%S)", &vec, U_STRING_TO_TRACE(buffer), delim)
UString x;
unsigned r, n = vec.size();
const char* s = buffer.data();
const char* ss = s;
const char* end = s + buffer.size();
const char* p;
const char* b = s;
loop:
if (s >= end) goto done;
if (strchr(delim, *s))
{
++s;
goto loop;
}
else
{
while (isspace(*s)) s++;
p = s++;
if (*(s-1) == '"')
{
while (s < end && *s != '"') ++s;
}
ss = s;
while (s < end && strchr(delim,*s) == 0)
{
++s;
if (!isspace(*(s-1))) ss = s;
}
}
if (*p == '"' && *(ss-1) == '"')
{
p++;
ss--;
}
x = buffer.substr(p - b, ss - p);
vec.push_back(x);
++s;
goto loop;
done:
r = vec.size() - n;
#ifdef DEBUG
for (unsigned i = 0; i < r; ++i)
{
U_DUMP("vec[%d] = %.*S", n+i, U_STRING_TO_TRACE(vec[n+i]))
}
#endif
U_RETURN(r);
}
#endif
HttpCookie::HttpCookie(const char* name_, unsigned name_len, const char* value_, unsigned value_len)
{
U_TRACE_REGISTER_OBJECT(5, HttpCookie, "%.*S,%u,%.*S,%u", name_len, name_, name_len, value_len, value_, value_len)
U_INTERNAL_ASSERT(memcmp(name_, U_CONSTANT_TO_PARAM("Cookie")) == 0)
name.assign(name_, name_len);
buffer.assign(value_, value_len);
is_path = is_domain = is_port = false;
#ifdef SERGIO
// NOTA BENE: La virgola come separatore non viene supportata per consentire l'utilizzo di COOKIE_SPECIAL_VALUE
UVector<UString> tvec,tvec1;
(void) cookie_split(tvec, buffer, "=");
const char* pc;
unsigned i, num;
const char* delim;
for (i = 0; i < tvec.size(); i++)
{
const char* s = tvec[i].data();
/* modifica stefano */
unsigned size = tvec[i].size();
pc = (const char*) memrchr(s, ',', size);
const char* p = (const char*) memrchr(s, ';', size);
if (pc > p)
{
p = pc;
delim = ",";
}
else
{
delim = ";";
}
if (p != NULL)
{
/* modifica stefano */
num = cookie_split(tvec1, tvec[i], delim);
U_INTERNAL_ASSERT(num > 1)
vec.push_back(tvec1[0]);
vec.push_back(tvec1[1]);
tvec1.clear();
}
else
{
vec.push_back(tvec[i]);
}
}
tvec.clear();
#else
(void) U_VEC_SPLIT(vec, buffer, "=;, \r\n");
#endif
}
unsigned HttpCookie::count(const UString& name_)
{
U_TRACE(5, "HttpCookie::count(%.*S)", U_STRING_TO_TRACE(name_))
unsigned i, j;
for (i = j = 0; i < vec.size(); i += 2)
{
if (name_ == vec[i])
{
++j;
}
}
U_RETURN(j);
}
void HttpCookie::add(const UString& name_, const UString& value_)
{
U_TRACE(5, "HttpCookie::add(%.*S,%.*S)", U_STRING_TO_TRACE(name_), U_STRING_TO_TRACE(value_))
vec.push_back(name_);
vec.push_back(value_);
}
bool HttpCookie::check(unsigned i)
{
U_TRACE(5, "HttpCookie::check(%u)", i)
is_path = (vec[i] == U_STRING_FROM_CONSTANT("$Path"));
is_port = (vec[i] == U_STRING_FROM_CONSTANT("$Port"));
is_domain = (vec[i] == U_STRING_FROM_CONSTANT("$Domain"));
U_RETURN(is_path || is_port || is_domain);
}
#define SET_VALUE(n) \
if (is_path) path = vec[i+n]; \
else if (is_domain) domain = vec[i+n]; \
else port = vec[i+n];
bool HttpCookie::find(const UString& name_, UString& value_, UString& path, UString& domain, UString& port, unsigned index)
{
U_TRACE(5, "HttpCookie::find(%.*S,%.*S,%.*S,%.*S,%d)",
U_STRING_TO_TRACE(name_), U_STRING_TO_TRACE(value_), U_STRING_TO_TRACE(path), U_STRING_TO_TRACE(domain), index)
unsigned i, j;
for (i = j = 0; i < vec.size(); i += 2)
{
if (name_ == vec[i])
{
if (index == j && (i + 1) < vec.size())
{
value_ = vec[i+1];
if ((i + 3) < vec.size() && check(i+2))
{
SET_VALUE(3);
}
if ((i + 5) < vec.size() && check(i+4))
{
SET_VALUE(5);
}
if ((i + 7) < vec.size() && check(i+6))
{
SET_VALUE(7);
}
U_RETURN(true);
}
++j;
}
}
U_RETURN(false);
}
bool HttpCookie::del(const UString& name_, unsigned index)
{
U_TRACE(5, "HttpCookie::del(%.*S,%d)", U_STRING_TO_TRACE(name_), index)
unsigned i, j;
for (i = j = 0; i < vec.size(); i += 2)
{
if (name_ == vec[i])
{
if (index == j)
{
// erase [first,last[
unsigned first = i, last = i+2;
if ((i + 3) < vec.size() && check(i+2))
{
last = i+4;
}
if ((i + 5) < vec.size() && check(i+4))
{
last = i+6;
}
if ((i + 7) < vec.size() && check(i+6))
{
last = i+8;
}
U_VEC_ERASE2(vec, first, last);
U_RETURN(true);
}
++j;
}
}
U_RETURN(false);
}
bool HttpCookie::del_all(const UString& name_)
{
U_TRACE(5, "HttpCookie::del_all(%.*S)", U_STRING_TO_TRACE(name_))
if (del(name_) == false)
{
U_RETURN(false);
}
while (del(name_))
{
}
U_RETURN(true);
}
void HttpCookie::stringify(UString& field)
{
U_TRACE(5, "HttpCookie::stringify(%.*S)", U_STRING_TO_TRACE(field))
field += name;
field.append(U_CONSTANT_TO_PARAM(": "));
/*
unsigned i = 0;
while (i < vec.size())
{
field += vec[i];
field.append(1, '=');
field += vec[i+1];
i += 2;
if (i < vec.size())
{
field.append(U_CONSTANT_TO_PARAM("; "));
}
}
*/
field.append(buffer);
field.append(U_CONSTANT_TO_PARAM("\r\n"));
U_INTERNAL_DUMP("field = %.*S", U_STRING_TO_TRACE(field))
}
// DEBUG
#if defined(U_STDCPP_ENABLE) && defined(DEBUG)
const char* HttpCookie::dump(bool reset) const
{
HttpField::dump(false);
*UObjectIO::os << "\n"
<< "is_path " << is_path << "\n"
<< "is_port " << is_port << "\n"
<< "is_domain " << is_domain << "\n"
<< "vec (UVector " << (void*)&vec << ")\n"
<< "buffer (UString " << (void*)&buffer << ")";
if (reset)
{
UObjectIO::output();
return UObjectIO::buffer_output;
}
return 0;
}
#endif