@ -162,7 +162,7 @@ const char *httpdGetVersion(void)
return HTTPDVER ;
return HTTPDVER ;
}
}
in t httpGetBacklogSize ( const HttpdConnData * conn )
size_ t httpGetBacklogSize ( const HttpdConnData * conn )
{
{
HttpSendBacklogItem * bl = conn - > priv - > sendBacklog ;
HttpSendBacklogItem * bl = conn - > priv - > sendBacklog ;
if ( ! bl ) { return 0 ; }
if ( ! bl ) { return 0 ; }
@ -193,6 +193,9 @@ static HttpdConnData *httpdFindConnData(ConnTypePtr conn, const char *remIp, int
//Retires a connection for re-use
//Retires a connection for re-use
static void httpdRetireConn ( HttpdConnData * conn )
static void httpdRetireConn ( HttpdConnData * conn )
{
{
if ( ! conn ) {
return ;
}
if ( conn - > priv - > sendBacklog ! = NULL ) {
if ( conn - > priv - > sendBacklog ! = NULL ) {
HttpSendBacklogItem * i , * j ;
HttpSendBacklogItem * i , * j ;
i = conn - > priv - > sendBacklog ;
i = conn - > priv - > sendBacklog ;
@ -205,14 +208,14 @@ static void httpdRetireConn(HttpdConnData *conn)
if ( conn - > post - > buff ! = NULL ) { httpdPlatFree ( conn - > post - > buff ) ; }
if ( conn - > post - > buff ! = NULL ) { httpdPlatFree ( conn - > post - > buff ) ; }
if ( conn - > post ! = NULL ) { httpdPlatFree ( conn - > post ) ; }
if ( conn - > post ! = NULL ) { httpdPlatFree ( conn - > post ) ; }
if ( conn - > priv ! = NULL ) { httpdPlatFree ( conn - > priv ) ; }
if ( conn - > priv ! = NULL ) { httpdPlatFree ( conn - > priv ) ; }
if ( conn ) { httpdPlatFree ( conn ) ; }
httpdPlatFree ( conn ) ;
for ( int i = 0 ; i < HTTPD_MAX_CONNECTIONS ; i + + ) {
for ( int i = 0 ; i < HTTPD_MAX_CONNECTIONS ; i + + ) {
if ( s_connData [ i ] = = conn ) { s_connData [ i ] = NULL ; }
if ( s_connData [ i ] = = conn ) { s_connData [ i ] = NULL ; }
}
}
}
}
//Stupid li'l helper function that returns the value of a hex char.
//Stupid li'l helper function that returns the value of a hex char.
static int httpdHexVal ( char c )
static char httpdHexVal ( char c )
{
{
if ( c > = ' 0 ' & & c < = ' 9 ' ) { return c - ' 0 ' ; }
if ( c > = ' 0 ' & & c < = ' 9 ' ) { return c - ' 0 ' ; }
if ( c > = ' A ' & & c < = ' F ' ) { return c - ' A ' + 10 ; }
if ( c > = ' A ' & & c < = ' F ' ) { return c - ' A ' + 10 ; }
@ -227,13 +230,14 @@ static int httpdHexVal(char c)
int httpdUrlDecode ( const char * val , int valLen , char * ret , int retLen )
int httpdUrlDecode ( const char * val , int valLen , char * ret , int retLen )
{
{
int s = 0 , d = 0 ;
int s = 0 , d = 0 ;
int esced = 0 , escVal = 0 ;
int esced = 0 ;
char escVal = 0 ;
while ( s < valLen & & d < retLen ) {
while ( s < valLen & & d < retLen ) {
if ( esced = = 1 ) {
if ( esced = = 1 ) {
escVal = httpdHexVal ( val [ s ] ) < < 4 ;
escVal = httpdHexVal ( val [ s ] ) < < 4 ;
esced = 2 ;
esced = 2 ;
} else if ( esced = = 2 ) {
} else if ( esced = = 2 ) {
escVal + = httpdHexVal ( val [ s ] ) ;
escVal | = httpdHexVal ( val [ s ] ) ;
ret [ d + + ] = escVal ;
ret [ d + + ] = escVal ;
esced = 0 ;
esced = 0 ;
} else if ( val [ s ] = = ' % ' ) {
} else if ( val [ s ] = = ' % ' ) {
@ -266,8 +270,8 @@ int httpdFindArg(const char *line, const char *arg, char *buff, int buffLen)
p + = arglen + 1 ; //move p to start of value
p + = arglen + 1 ; //move p to start of value
e = strstr ( p , " & " ) ;
e = strstr ( p , " & " ) ;
if ( e = = NULL ) { e = p + strlen ( p ) ; }
if ( e = = NULL ) { e = p + strlen ( p ) ; }
router_dbg ( " findArg: val %s len %d " , p , ( e - p ) ) ;
router_dbg ( " findArg: val %s len %d " , p , ( int ) ( e - p ) ) ;
return httpdUrlDecode ( p , ( e - p ) , buff , buffLen ) ;
return httpdUrlDecode ( p , ( int ) ( e - p ) , buff , buffLen ) ;
}
}
p = strstr ( p , " & " ) ;
p = strstr ( p , " & " ) ;
if ( p ! = NULL ) { p + = 1 ; }
if ( p ! = NULL ) { p + = 1 ; }
@ -339,28 +343,28 @@ void httpdStartResponse(HttpdConnData *conn, int code)
code2str ( code ) ,
code2str ( code ) ,
serverName ,
serverName ,
connStr ) ;
connStr ) ;
httpdSend ( conn , buff , l ) ;
httpdSendStrN ( conn , buff , l ) ;
if ( 0 = = ( conn - > priv - > flags & HFL_NOCORS ) ) {
if ( 0 = = ( conn - > priv - > flags & HFL_NOCORS ) ) {
// CORS headers
// CORS headers
httpdSend ( conn , " Access-Control-Allow-Origin: * \r \n " , - 1 ) ;
httpdSendStr ( conn , " Access-Control-Allow-Origin: * \r \n " ) ;
httpdSend ( conn , " Access-Control-Allow-Methods: GET,POST,OPTIONS \r \n " , - 1 ) ;
httpdSendStr ( conn , " Access-Control-Allow-Methods: GET,POST,OPTIONS \r \n " ) ;
}
}
}
}
//Send a http header.
//Send a http header.
void httpdHeader ( HttpdConnData * conn , const char * field , const char * val )
void httpdHeader ( HttpdConnData * conn , const char * field , const char * val )
{
{
httpdSend ( conn , field , - 1 ) ;
httpdSendStr ( conn , field ) ;
httpdSend ( conn , " : " , - 1 ) ;
httpdSendStr ( conn , " : " ) ;
httpdSend ( conn , val , - 1 ) ;
httpdSendStr ( conn , val ) ;
httpdSend ( conn , " \r \n " , - 1 ) ;
httpdSendStr ( conn , " \r \n " ) ;
}
}
//Finish the headers.
//Finish the headers.
void httpdEndHeaders ( HttpdConnData * conn )
void httpdEndHeaders ( HttpdConnData * conn )
{
{
httpdSend ( conn , " \r \n " , - 1 ) ;
httpdSendStr ( conn , " \r \n " ) ;
conn - > priv - > flags | = HFL_SENDINGBODY ;
conn - > priv - > flags | = HFL_SENDINGBODY ;
}
}
@ -371,8 +375,8 @@ void httpdRedirect(HttpdConnData *conn, const char *newUrl)
httpdStartResponse ( conn , 302 ) ;
httpdStartResponse ( conn , 302 ) ;
httpdHeader ( conn , " Location " , newUrl ) ;
httpdHeader ( conn , " Location " , newUrl ) ;
httpdEndHeaders ( conn ) ;
httpdEndHeaders ( conn ) ;
httpdSend ( conn , " Moved to " , - 1 ) ;
httpdSendStr ( conn , " Moved to " ) ;
httpdSend ( conn , newUrl , - 1 ) ;
httpdSendStr ( conn , newUrl ) ;
}
}
//Use this as a cgi function to redirect one url to another.
//Use this as a cgi function to redirect one url to another.
@ -392,7 +396,7 @@ static httpd_cgi_state cgiNotFound(HttpdConnData *connData)
if ( connData - > conn = = NULL ) { return HTTPD_CGI_DONE ; }
if ( connData - > conn = = NULL ) { return HTTPD_CGI_DONE ; }
httpdStartResponse ( connData , 404 ) ;
httpdStartResponse ( connData , 404 ) ;
httpdEndHeaders ( connData ) ;
httpdEndHeaders ( connData ) ;
httpdSend ( connData , " 404 File not found. " , - 1 ) ;
httpdSendStr ( connData , " 404 File not found. " ) ;
return HTTPD_CGI_DONE ;
return HTTPD_CGI_DONE ;
}
}
@ -406,7 +410,6 @@ httpd_cgi_state cgiRedirectToHostname(HttpdConnData *connData)
static const char hostFmt [ ] = " http://%s/ " ;
static const char hostFmt [ ] = " http://%s/ " ;
char * buff ;
char * buff ;
int isIP = 0 ;
int isIP = 0 ;
int x ;
if ( connData - > conn = = NULL ) {
if ( connData - > conn = = NULL ) {
//Connection aborted. Clean up.
//Connection aborted. Clean up.
return HTTPD_CGI_DONE ;
return HTTPD_CGI_DONE ;
@ -419,7 +422,7 @@ httpd_cgi_state cgiRedirectToHostname(HttpdConnData *connData)
//Quick and dirty code to see if host is an IP
//Quick and dirty code to see if host is an IP
if ( strlen ( connData - > hostName ) > 8 ) {
if ( strlen ( connData - > hostName ) > 8 ) {
isIP = 1 ;
isIP = 1 ;
for ( x = 0 ; x < strlen ( connData - > hostName ) ; x + + ) {
for ( size_t x = 0 ; x < strlen ( connData - > hostName ) ; x + + ) {
if ( connData - > hostName [ x ] ! = ' . ' & & ( connData - > hostName [ x ] < ' 0 ' | | connData - > hostName [ x ] > ' 9 ' ) ) { isIP = 0 ; }
if ( connData - > hostName [ x ] ! = ' . ' & & ( connData - > hostName [ x ] < ' 0 ' | | connData - > hostName [ x ] > ' 9 ' ) ) { isIP = 0 ; }
}
}
}
}
@ -443,10 +446,9 @@ httpd_cgi_state cgiRedirectToHostname(HttpdConnData *connData)
//Add data to the send buffer. len is the length of the data. If len is -1
//Add data to the send buffer. len is the length of the data. If len is -1
//the data is seen as a C-string.
//the data is seen as a C-string.
//Returns 1 for success, 0 for out-of-memory.
//Returns 1 for success, 0 for out-of-memory.
int httpdSend ( HttpdConnData * conn , const char * data , in t len )
int httpdSend ( HttpdConnData * conn , const uint8_t * data , size_ t len )
{
{
if ( conn - > conn = = NULL ) { return 0 ; }
if ( conn - > conn = = NULL ) { return 0 ; }
if ( len < 0 ) { len = strlen ( data ) ; }
if ( len = = 0 ) { return 0 ; }
if ( len = = 0 ) { return 0 ; }
if ( conn - > priv - > flags & HFL_CHUNKED & & conn - > priv - > flags & HFL_SENDINGBODY & & conn - > priv - > chunkHdr = = NULL ) {
if ( conn - > priv - > flags & HFL_CHUNKED & & conn - > priv - > flags & HFL_SENDINGBODY & & conn - > priv - > chunkHdr = = NULL ) {
if ( conn - > priv - > sendBuffLen + len + 6 > HTTPD_MAX_SENDBUFF_LEN ) { return 0 ; }
if ( conn - > priv - > sendBuffLen + len + 6 > HTTPD_MAX_SENDBUFF_LEN ) { return 0 ; }
@ -464,19 +466,21 @@ int httpdSend(HttpdConnData *conn, const char *data, int len)
static char httpdHexNibble ( int val )
static char httpdHexNibble ( int val )
{
{
val & = 0xf ;
val & = 0xf ;
if ( val < 10 ) { return ' 0 ' + val ; }
if ( val < 10 ) { return ( char ) ( ' 0 ' + val ) ; }
return ' A ' + ( val - 10 ) ;
return ( char ) ( ' A ' + ( val - 10 ) ) ;
}
}
# define httpdSend_orDie(conn, data, len) do { if (!httpdSend((conn), (data), (len))) return false; } while (0)
# define httpdSend_orDie(conn, data, len) do { if (!httpdSend((conn), (const uint8_t *)(data), (len))) return false; } while (0)
# define httpdSendStr_orDie(conn, data) do { if (!httpdSendStr((conn), (data))) return false; } while (0)
/* encode for HTML. returns 0 or 1 - 1 = success */
/* encode for HTML. returns 0 or 1 - 1 = success */
int httpdSend_html ( HttpdConnData * conn , const char * data , in t len )
int httpdSend_html ( HttpdConnData * conn , const uint8_t * data , ssize_ t len )
{
{
int start = 0 , end = 0 ;
int start = 0 , end = 0 ;
char c ;
uint8_t c ;
if ( conn - > conn = = NULL ) { return 0 ; }
if ( conn - > conn = = NULL ) { return 0 ; }
if ( len < 0 ) { len = ( int ) strlen ( data ) ; }
if ( len < 0 ) { len = ( int ) strlen ( ( const char * ) data ) ; }
if ( len = = 0 ) { return 0 ; }
if ( len = = 0 ) { return 0 ; }
for ( end = 0 ; end < len ; end + + ) {
for ( end = 0 ; end < len ; end + + ) {
@ -491,10 +495,10 @@ int httpdSend_html(HttpdConnData *conn, const char *data, int len)
start = end + 1 ;
start = end + 1 ;
}
}
if ( c = = ' " ' ) httpdSend_orDie ( conn , " " " , 5 ) ;
if ( c = = ' " ' ) httpdSendStr _orDie ( conn , " " " ) ;
else if ( c = = ' \' ' ) httpdSend_orDie ( conn , " ' ; " , 5 );
else if ( c = = ' \' ' ) httpdSendStr _orDie ( conn , " ' ; " );
else if ( c = = ' < ' ) httpdSend_orDie ( conn , " < ; " , 4 );
else if ( c = = ' < ' ) httpdSendStr _orDie ( conn , " < ; " );
else if ( c = = ' > ' ) httpdSend_orDie ( conn , " > ; " , 4 );
else if ( c = = ' > ' ) httpdSendStr _orDie ( conn , " > ; " );
}
}
if ( start < end ) httpdSend_orDie ( conn , data + start , end - start ) ;
if ( start < end ) httpdSend_orDie ( conn , data + start , end - start ) ;
@ -502,12 +506,12 @@ int httpdSend_html(HttpdConnData *conn, const char *data, int len)
}
}
/* encode for JS. returns 0 or 1 - 1 = success */
/* encode for JS. returns 0 or 1 - 1 = success */
int httpdSend_js ( HttpdConnData * conn , const char * data , in t len )
int httpdSend_js ( HttpdConnData * conn , const uint8_t * data , ssize_ t len )
{
{
int start = 0 , end = 0 ;
int start = 0 , end = 0 ;
char c ;
uint8_t c ;
if ( conn - > conn = = NULL ) { return 0 ; }
if ( conn - > conn = = NULL ) { return 0 ; }
if ( len < 0 ) { len = ( int ) strlen ( data ) ; }
if ( len < 0 ) { len = ( int ) strlen ( ( const char * ) data ) ; }
if ( len = = 0 ) { return 0 ; }
if ( len = = 0 ) { return 0 ; }
for ( end = 0 ; end < len ; end + + ) {
for ( end = 0 ; end < len ; end + + ) {
@ -522,13 +526,13 @@ int httpdSend_js(HttpdConnData *conn, const char *data, int len)
start = end + 1 ;
start = end + 1 ;
}
}
if ( c = = ' " ' ) httpdSend_orDie ( conn , " \\ \" " , 2 ) ;
if ( c = = ' " ' ) httpdSendStr _orDie ( conn , " \\ \" " ) ;
else if ( c = = ' \' ' ) httpdSend_orDie ( conn , " \\ ' " , 2 ) ;
else if ( c = = ' \' ' ) httpdSendStr _orDie ( conn , " \\ ' " ) ;
else if ( c = = ' \\ ' ) httpdSend_orDie ( conn , " \\ \\ " , 2 ) ;
else if ( c = = ' \\ ' ) httpdSendStr _orDie ( conn , " \\ \\ " ) ;
else if ( c = = ' < ' ) httpdSend_orDie ( conn , " \\ u003C " , 6 ) ;
else if ( c = = ' < ' ) httpdSendStr _orDie ( conn , " \\ u003C " ) ;
else if ( c = = ' > ' ) httpdSend_orDie ( conn , " \\ u003E " , 6 ) ;
else if ( c = = ' > ' ) httpdSendStr _orDie ( conn , " \\ u003E " ) ;
else if ( c = = ' \n ' ) httpdSend_orDie ( conn , " \\ n " , 2 ) ;
else if ( c = = ' \n ' ) httpdSendStr _orDie ( conn , " \\ n " ) ;
else if ( c = = ' \r ' ) httpdSend_orDie ( conn , " \\ r " , 2 ) ;
else if ( c = = ' \r ' ) httpdSendStr _orDie ( conn , " \\ r " ) ;
}
}
if ( start < end ) httpdSend_orDie ( conn , data + start , end - start ) ;
if ( start < end ) httpdSend_orDie ( conn , data + start , end - start ) ;
@ -546,7 +550,7 @@ bool httpdFlushSendBuffer(HttpdConnData *conn)
if ( conn - > priv - > chunkHdr ! = NULL ) {
if ( conn - > priv - > chunkHdr ! = NULL ) {
//We're sending chunked data, and the chunk needs fixing up.
//We're sending chunked data, and the chunk needs fixing up.
//Finish chunk with cr/lf
//Finish chunk with cr/lf
httpdSend ( conn , " \r \n " , 2 ) ;
httpdSendStr ( conn , " \r \n " ) ;
//Calculate length of chunk
//Calculate length of chunk
len = ( ( & conn - > priv - > sendBuff [ conn - > priv - > sendBuffLen ] ) - conn - > priv - > chunkHdr ) - 8 ;
len = ( ( & conn - > priv - > sendBuff [ conn - > priv - > sendBuffLen ] ) - conn - > priv - > chunkHdr ) - 8 ;
//Fix up chunk header to correct value
//Fix up chunk header to correct value
@ -708,7 +712,7 @@ static void httpdProcessRequest(HttpdConnData *conn)
//Look up URL in the built-in URL table.
//Look up URL in the built-in URL table.
while ( builtInUrls [ i ] . url ! = NULL ) {
while ( builtInUrls [ i ] . url ! = NULL ) {
int match = 0 ;
int match = 0 ;
const char const * route = builtInUrls [ i ] . url ;
const char * route = builtInUrls [ i ] . url ;
//See if there's a literal match
//See if there's a literal match
if ( streq ( route , conn - > url ) ) { match = 1 ; }
if ( streq ( route , conn - > url ) ) { match = 1 ; }
//See if there's a wildcard match (*)
//See if there's a wildcard match (*)