@ -29,8 +29,6 @@ _Static_assert(HTTPD_MAX_CONNECTIONS < 256, "HTTPD_MAX_CONNECTIONS must be at mo
static const HttpdBuiltInUrl * s_builtInUrls ;
static const HttpdBuiltInUrl * s_builtInUrls ;
static const char * s_serverName = HTTPD_SERVERNAME ;
static const char * s_serverName = HTTPD_SERVERNAME ;
//Connection pool
//Connection pool
HttpdConnData s_connData [ HTTPD_MAX_CONNECTIONS ] ;
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
//Get the value of a certain header in the HTTP client head
//Returns true when found, false when not found.
//Returns true when found, false when not found.
int httpdGetHeader ( HttpdConnData * conn , const char * header , char * buff , size_t buffLen )
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 ;
char * p = conn - > priv . head ;
p = p + strlen ( p ) + 1 ; //skip GET/POST part
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 ;
p = p + strlen ( header ) + 1 ;
//Skip past spaces after the colon
//Skip past spaces after the colon
while ( * p = = ' ' ) { p + + ; }
while ( * p = = ' ' ) { p + + ; }
//Copy from p to end
return p ;
while ( * p ! = 0 & & * p ! = ' \r ' & & * p ! = ' \n ' & & buffLen > 1 ) {
* buff + + = * p + + ;
buffLen - - ;
}
//Zero-terminate string
* buff = 0 ;
//All done :)
return 1 ;
}
}
p + = strlen ( p ) + 1 ; //Skip past end of string and \0 terminator
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 )
void httpdQueueHeader ( HttpdConnData * conn , const char * header , const char * value )
@ -234,24 +241,6 @@ bool httpdSetCookie(HttpdConnData *conn, const SetCookie *parm)
return false ;
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_SET_COOKIE "Set-Cookie: "
# define COOKIE_PART_EXPIRES "; Expires="
# define COOKIE_PART_EXPIRES "; Expires="
# define COOKIE_PART_MAX_AGE "; Max-Age="
# define COOKIE_PART_MAX_AGE "; Max-Age="
@ -295,7 +284,7 @@ bool httpdSetCookie(HttpdConnData *conn, const SetCookie *parm)
buflen + = strlen ( COOKIE_PART_HTTP_ONLY ) ;
buflen + = strlen ( COOKIE_PART_HTTP_ONLY ) ;
}
}
HttpdQueuedHeader * queEntry = httpdMalloc ( buflen ) ;
HttpdQueuedHeader * queEntry = httpdMalloc ( sizeof ( void * ) + buflen ) ;
if ( ! queEntry ) {
if ( ! queEntry ) {
http_error ( " httpdSetCookie - no mem " ) ;
http_error ( " httpdSetCookie - no mem " ) ;
return false ;
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 )
void httdSetTransferMode ( HttpdConnData * conn , httpd_transfer_opt mode )
{
{
if ( mode = = HTTPD_TRANSFER_CLOSE ) {
if ( mode = = HTTPD_TRANSFER_CLOSE ) {