|
|
|
@ -29,8 +29,6 @@ _Static_assert(HTTPD_MAX_CONNECTIONS < 256, "HTTPD_MAX_CONNECTIONS must be at mo |
|
|
|
|
static const HttpdBuiltInUrl *s_builtInUrls; |
|
|
|
|
static const char *s_serverName = HTTPD_SERVERNAME; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Connection pool
|
|
|
|
|
HttpdConnData s_connData[HTTPD_MAX_CONNECTIONS]; |
|
|
|
|
|
|
|
|
@ -140,6 +138,23 @@ static void httpdRetireConn(HttpdConnData *hconn) |
|
|
|
|
//Get the value of a certain header in the HTTP client head
|
|
|
|
|
//Returns true when found, false when not found.
|
|
|
|
|
int httpdGetHeader(HttpdConnData *conn, const char *header, char *buff, size_t buffLen) |
|
|
|
|
{ |
|
|
|
|
const char *p = httpdGetHeaderPtr(conn, header); |
|
|
|
|
if (!p) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
while (*p != 0 && buffLen > 1) { // && *p != '\r' && *p != '\n'
|
|
|
|
|
*buff++ = *p++; |
|
|
|
|
buffLen--; |
|
|
|
|
} |
|
|
|
|
//Zero-terminate string
|
|
|
|
|
*buff = 0; |
|
|
|
|
//All done :)
|
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const char * httpdGetHeaderPtr(HttpdConnData *conn, const char *header) |
|
|
|
|
{ |
|
|
|
|
char *p = conn->priv.head; |
|
|
|
|
p = p + strlen(p) + 1; //skip GET/POST part
|
|
|
|
@ -152,19 +167,11 @@ int httpdGetHeader(HttpdConnData *conn, const char *header, char *buff, size_t b |
|
|
|
|
p = p + strlen(header) + 1; |
|
|
|
|
//Skip past spaces after the colon
|
|
|
|
|
while (*p == ' ') { p++; } |
|
|
|
|
//Copy from p to end
|
|
|
|
|
while (*p != 0 && *p != '\r' && *p != '\n' && buffLen > 1) { |
|
|
|
|
*buff++ = *p++; |
|
|
|
|
buffLen--; |
|
|
|
|
} |
|
|
|
|
//Zero-terminate string
|
|
|
|
|
*buff = 0; |
|
|
|
|
//All done :)
|
|
|
|
|
return 1; |
|
|
|
|
return p; |
|
|
|
|
} |
|
|
|
|
p += strlen(p) + 1; //Skip past end of string and \0 terminator
|
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void httpdQueueHeader(HttpdConnData *conn, const char *header, const char *value) |
|
|
|
@ -234,24 +241,6 @@ bool httpdSetCookie(HttpdConnData *conn, const SetCookie *parm) |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Set-Cookie: <cookie-name>=<cookie-value> |
|
|
|
|
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value> |
|
|
|
|
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date> |
|
|
|
|
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly |
|
|
|
|
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<number> |
|
|
|
|
Set-Cookie: <cookie-name>=<cookie-value>; Partitioned |
|
|
|
|
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value> |
|
|
|
|
Set-Cookie: <cookie-name>=<cookie-value>; Secure |
|
|
|
|
|
|
|
|
|
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict |
|
|
|
|
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax |
|
|
|
|
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=None; Secure |
|
|
|
|
|
|
|
|
|
// Multiple attributes are also possible, for example:
|
|
|
|
|
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#define COOKIE_PART_SET_COOKIE "Set-Cookie: " |
|
|
|
|
#define COOKIE_PART_EXPIRES "; Expires=" |
|
|
|
|
#define COOKIE_PART_MAX_AGE "; Max-Age=" |
|
|
|
@ -295,7 +284,7 @@ bool httpdSetCookie(HttpdConnData *conn, const SetCookie *parm) |
|
|
|
|
buflen += strlen(COOKIE_PART_HTTP_ONLY); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
HttpdQueuedHeader *queEntry = httpdMalloc(buflen); |
|
|
|
|
HttpdQueuedHeader *queEntry = httpdMalloc(sizeof(void*) + buflen); |
|
|
|
|
if (!queEntry) { |
|
|
|
|
http_error("httpdSetCookie - no mem"); |
|
|
|
|
return false; |
|
|
|
@ -344,6 +333,41 @@ bool httpdSetCookie(HttpdConnData *conn, const SetCookie *parm) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool httpdGetCookie(HttpdConnData *conn, const char *name, char *buff, size_t buffLen) |
|
|
|
|
{ |
|
|
|
|
const char *p = httpdGetHeaderPtr(conn, "Cookie"); |
|
|
|
|
if (!p) return 0; |
|
|
|
|
|
|
|
|
|
size_t namelen = strlen(name); |
|
|
|
|
while (*p != 0 && *p != '\r' && *p != '\n') { |
|
|
|
|
if (*p == ' ') { // skip whitespace
|
|
|
|
|
p++; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const char *next_semi = strchr(p, ';'); |
|
|
|
|
if (!next_semi) { |
|
|
|
|
next_semi = p + strlen(p); // end of string
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (strstarts(p, name) && p[namelen] == '=') { |
|
|
|
|
const char * valuestart = p + namelen + 1; |
|
|
|
|
|
|
|
|
|
size_t valuelen = (size_t) (next_semi - valuestart); |
|
|
|
|
if (valuelen >= buffLen - 1) { |
|
|
|
|
valuelen = buffLen - 1; |
|
|
|
|
} |
|
|
|
|
strncpy(buff, valuestart, valuelen); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
p = next_semi + 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void httdSetTransferMode(HttpdConnData *conn, httpd_transfer_opt mode) |
|
|
|
|
{ |
|
|
|
|
if (mode == HTTPD_TRANSFER_CLOSE) { |
|
|
|
|