cleaning, add header queuing

master
Ondřej Hruška 1 year ago
parent 5ae683e3f2
commit 935271510d
  1. 16
      demo/server_demo.c
  2. 2
      spritehttpd/include/httpd-types.h
  3. 30
      spritehttpd/include/httpd-utils.h
  4. 10
      spritehttpd/include/httpd.h
  5. 83
      spritehttpd/src/cgi-espfs.c
  6. 31
      spritehttpd/src/httpd-utils.c
  7. 110
      spritehttpd/src/httpd.c

@ -80,13 +80,13 @@ httpd_cgi_state templateReplacer(HttpdConnData *conn, const char *token)
// httpdGetHeader(conn, "Cookie", ) // httpdGetHeader(conn, "Cookie", )
//} //}
// httpd_cgi_state cgiStartSession(HttpdConnData *conn)
//httpd_cgi_state cgiStartSession(HttpdConnData *conn) {
//{ httpdQueueHeader(conn, "X-Foo", "FOO");
// httpdQueueHeader(conn, "X-Bar", "Bar");
//
// return HTTPD_CGI_NOTFOUND; return HTTPD_CGI_NOTFOUND;
//} }
@ -96,7 +96,7 @@ httpd_cgi_state templateReplacer(HttpdConnData *conn, const char *token)
*/ */
const HttpdBuiltInUrl routes[] = { const HttpdBuiltInUrl routes[] = {
// TODO password lock ... // TODO password lock ...
// ROUTE_CGI("*", cgiStartSession), ROUTE_CGI("*", cgiStartSession),
// --- Web pages --- // --- Web pages ---
// ROUTE_TPL_FILE("/", tplIndex, "/index.tpl"), // ROUTE_TPL_FILE("/", tplIndex, "/index.tpl"),

@ -30,7 +30,7 @@ typedef enum {
HTTPD_CGI_NOTFOUND = 2, HTTPD_CGI_NOTFOUND = 2,
/// This is, in effect, identical to NOTFOUND, it's returned by auth functions when a fall-through is allowed. /// This is, in effect, identical to NOTFOUND, it's returned by auth functions when a fall-through is allowed.
/// The next route in the route list will be attempted. /// The next route in the route list will be attempted.
HTTPD_CGI_AUTHENTICATED = 3, HTTPD_CGI_AUTHENTICATED = 3, // TODO rename to PASS?
} httpd_cgi_state; } httpd_cgi_state;
/** /**

@ -9,18 +9,40 @@
#include "httpd-types.h" #include "httpd-types.h"
// Custom helpers // Custom helpers
/// Test string equality
#define streq(a, b) (strcmp((const char*)(a), (const char*)(b)) == 0) #define streq(a, b) (strcmp((const char*)(a), (const char*)(b)) == 0)
/// Test string equality, case-insensitive
#define strcaseeq(a, b) (strcasecmp((const char*)(a), (const char*)(b)) == 0)
/// Test string equality up to N chars
#define strneq(a, b, n) (strncmp((const char*)(a), (const char*)(b), (n)) == 0) #define strneq(a, b, n) (strncmp((const char*)(a), (const char*)(b), (n)) == 0)
/// Test if string A starts with string B
#define strstarts(a, b) strneq((a), (b), strlen((b))) #define strstarts(a, b) strneq((a), (b), strlen((b)))
/// Get nth char from the end of string (1 = last)
#define last_char_n(str, n) ((str))[strlen((str)) - (n)] #define last_char_n(str, n) ((str))[strlen((str)) - (n)]
/// Get last char of string
#define last_char(str) last_char_n((str), 1) #define last_char(str) last_char_n((str), 1)
/// The container_of macro from the linux kernel
#ifndef container_of #ifndef container_of
#define container_of(ptr, type, member) ({ \ #define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );}) (type *)( (char *)__mptr - offsetof(type,member) );})
#endif #endif
/// Get length of a static or stack array
#define array_len(a) (sizeof((a)) / sizeof((a)[0]))
/**
* Strstr up to N chars into the searched string
*
* @param str - haystack
* @param substr - needle
* @param n - haystack len to search
* @return pointer to the matching substring or NULL
*/
const char *strnstr(const char *str, const char *substr, size_t n);
/** /**
* Turn a nibble (0-15) to a hex char. * Turn a nibble (0-15) to a hex char.
* *
@ -83,12 +105,10 @@ const char *httpdGetMimetype(const char *url);
* @param fallback - fallback mime if none was resolved * @param fallback - fallback mime if none was resolved
* @return mime string * @return mime string
*/ */
static inline const char *httpdGetMimetypeOr(const char *url, const char *fallback) { static inline const char *httpdGetMimetypeOr(const char *url, const char *fallback)
{
const char *mime = httpdGetMimetype(url); const char *mime = httpdGetMimetype(url);
if (!mime) { return mime ? mime : fallback;
mime = fallback;
}
return mime;
} }
/** /**

@ -149,6 +149,16 @@ void httpdEndHeaders(HttpdConnData *conn);
*/ */
int httpdGetHeader(HttpdConnData *conn, const char *header, char *buff, size_t buffLen); int httpdGetHeader(HttpdConnData *conn, const char *header, char *buff, size_t buffLen);
/**
* Queue a header to be sent with the response.
*
* @param conn
* @param header - name
* @param value - value
* @return 1 = OK
*/
void httpdQueueHeader(HttpdConnData *conn, const char *header, const char *value);
/** /**
* Send binary data * Send binary data
* *

@ -21,7 +21,12 @@ Connector to let httpd use the espfs filesystem to serve the files in it.
#include "espfs.h" #include "espfs.h"
#include "espfsformat.h" #include "espfsformat.h"
#define FILE_CHUNK_LEN 512 /// EspFs CGI filename len buffer size
#define ESPFS_FILENAME_LEN 100
/// EspFs CGI file chunk buffer size
#define ESPFS_FILE_CHUNK_LEN 512
/// EspFs CGI header buffer (used to detect gzip)
#define ESPFS_HEADER_LEN 64
// The static files marked with FLAG_GZIP are compressed and will be served with GZIP compression. // The static files marked with FLAG_GZIP are compressed and will be served with GZIP compression.
// If the client does not advertise that he accepts GZIP send following warning message (telnet users for e.g.) // If the client does not advertise that he accepts GZIP send following warning message (telnet users for e.g.)
@ -32,29 +37,6 @@ static const char *gzipNonSupportedMessage = "HTTP/1.0 501 Not implemented\r\n"
"\r\n" "\r\n"
"Your browser does not accept gzip-compressed data.\r\n"; "Your browser does not accept gzip-compressed data.\r\n";
/**
* Try to open a file
* @param path - path to the file, may end with slash
* @param indexname - filename at the path
* @return file pointer or NULL
*/
static EspFsFile *tryOpenIndex_do(const char *path, const char *indexname)
{
char fname[100];
size_t url_len = strlen(path);
strncpy(fname, path, 99);
// Append slash if missing
if (path[url_len - 1] != '/') {
fname[url_len++] = '/';
}
strcpy(fname + url_len, indexname);
// Try to open, returns NULL if failed
return espFsOpen(fname);
}
/** /**
* Try to find index file on a path * Try to find index file on a path
* @param path - directory * @param path - directory
@ -67,17 +49,29 @@ EspFsFile *tryOpenIndex(const char *path)
// no point in trying to look for index. // no point in trying to look for index.
if (strchr(path, '.') != NULL) { return NULL; } if (strchr(path, '.') != NULL) { return NULL; }
file = tryOpenIndex_do(path, "index.html"); char fname[ESPFS_FILENAME_LEN];
if (file != NULL) { return file; } size_t url_len = strlen(path);
if (url_len >= ESPFS_FILENAME_LEN) {
// too long to append anything
return NULL;
}
strncpy(fname, path, ESPFS_FILENAME_LEN - 1);
file = tryOpenIndex_do(path, "index.htm"); // Append slash if missing
if (file != NULL) { return file; } if (path[url_len - 1] != '/') {
fname[url_len++] = '/';
}
file = tryOpenIndex_do(path, "index.tpl.html"); const char *index_names[4] = {
if (file != NULL) { return file; } "index.html", "index.htm", "index.tpl.html", "index.tpl"
};
file = tryOpenIndex_do(path, "index.tpl"); for (size_t i = 0; i < array_len(index_names); i++) {
if (file != NULL) { return file; } strcpy(fname + url_len, index_names[i]);
// Try to open, returns NULL if failed
file = espFsOpen(fname);
if (file != NULL) { return file; }
}
return NULL; // failed to guess the right name return NULL; // failed to guess the right name
} }
@ -86,8 +80,8 @@ static httpd_cgi_state serveStaticFile(HttpdConnData *hconn, const char *filepat
{ {
EspFsFile *file = hconn->cgiData; EspFsFile *file = hconn->cgiData;
size_t len; size_t len;
uint8_t buff[FILE_CHUNK_LEN + 1]; uint8_t buff[ESPFS_FILE_CHUNK_LEN + 1];
char acceptEncodingBuffer[64 + 1]; char acceptEncodingBuffer[ESPFS_HEADER_LEN + 1];
if (hconn->conn == NULL) { if (hconn->conn == NULL) {
//Connection aborted. Clean up. //Connection aborted. Clean up.
@ -123,7 +117,7 @@ static httpd_cgi_state serveStaticFile(HttpdConnData *hconn, const char *filepat
if (isGzip) { if (isGzip) {
// Check the browser's "Accept-Encoding" header. If the client does not // Check the browser's "Accept-Encoding" header. If the client does not
// advertise that he accepts GZIP send a warning message (telnet users for e.g.) // advertise that he accepts GZIP send a warning message (telnet users for e.g.)
httpdGetHeader(hconn, "Accept-Encoding", acceptEncodingBuffer, 64); httpdGetHeader(hconn, "Accept-Encoding", acceptEncodingBuffer, ESPFS_HEADER_LEN);
if (strstr(acceptEncodingBuffer, "gzip") == NULL) { if (strstr(acceptEncodingBuffer, "gzip") == NULL) {
//No Accept-Encoding: gzip header present //No Accept-Encoding: gzip header present
httpdSendStr(hconn, gzipNonSupportedMessage); httpdSendStr(hconn, gzipNonSupportedMessage);
@ -144,12 +138,12 @@ static httpd_cgi_state serveStaticFile(HttpdConnData *hconn, const char *filepat
return HTTPD_CGI_MORE; return HTTPD_CGI_MORE;
} }
len = espFsRead(file, buff, FILE_CHUNK_LEN); len = espFsRead(file, buff, ESPFS_FILE_CHUNK_LEN);
if (len > 0) { if (len > 0) {
espfs_dbg("[EspFS] Read file chunk: %d bytes", len); espfs_dbg("[EspFS] Read file chunk: %d bytes", len);
httpdSend(hconn, buff, len); httpdSend(hconn, buff, len);
} }
if (len != FILE_CHUNK_LEN) { if (len != ESPFS_FILE_CHUNK_LEN) {
//We're done. //We're done.
espFsClose(file); espFsClose(file);
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
@ -182,7 +176,7 @@ typedef struct {
EspFsFile *file; EspFsFile *file;
ssize_t tokenPos; ssize_t tokenPos;
char buff[FILE_CHUNK_LEN + 1]; char buff[ESPFS_FILE_CHUNK_LEN + 1];
char token[HTTPD_ESPFS_TOKEN_LEN]; char token[HTTPD_ESPFS_TOKEN_LEN];
char *pToken; char *pToken;
@ -301,7 +295,7 @@ httpd_cgi_state cgiEspFsTemplate(HttpdConnData *conn)
sp = tdi->buff_sp; sp = tdi->buff_sp;
x = tdi->buff_x; x = tdi->buff_x;
} else { } else {
len = espFsRead(tdi->file, (uint8_t *) buff, FILE_CHUNK_LEN); len = espFsRead(tdi->file, (uint8_t *) buff, ESPFS_FILE_CHUNK_LEN);
tdi->buff_len = len; tdi->buff_len = len;
e = buff; e = buff;
@ -337,19 +331,20 @@ httpd_cgi_state cgiEspFsTemplate(HttpdConnData *conn)
int prefixLen = 0; int prefixLen = 0;
tdi->tokEncode = ENCODE_PLAIN; tdi->tokEncode = ENCODE_PLAIN;
if (strneq(tdi->token, "html:", 5)) { if (strstarts(tdi->token, "html:")) {
prefixLen = 5; prefixLen = 5;
tdi->tokEncode = ENCODE_HTML; tdi->tokEncode = ENCODE_HTML;
} else if (strneq(tdi->token, "h:", 2)) { } else if (strstarts(tdi->token, "h:")) {
prefixLen = 2; prefixLen = 2;
tdi->tokEncode = ENCODE_HTML; tdi->tokEncode = ENCODE_HTML;
} else if (strneq(tdi->token, "js:", 3)) { } else if (strstarts(tdi->token, "js:")) {
prefixLen = 3; prefixLen = 3;
tdi->tokEncode = ENCODE_JS; tdi->tokEncode = ENCODE_JS;
} else if (strneq(tdi->token, "j:", 2)) { } else if (strstarts(tdi->token, "j:")) {
prefixLen = 2; prefixLen = 2;
tdi->tokEncode = ENCODE_JS; tdi->tokEncode = ENCODE_JS;
} }
// TODO implement "include" tokens?
tdi->pToken = &tdi->token[prefixLen]; tdi->pToken = &tdi->token[prefixLen];
} }
@ -410,7 +405,7 @@ httpd_cgi_state cgiEspFsTemplate(HttpdConnData *conn)
httpdSendStrN(conn, e, (size_t) sp); httpdSendStrN(conn, e, (size_t) sp);
} }
if (len != FILE_CHUNK_LEN) { if (len != ESPFS_FILE_CHUNK_LEN) {
//We're done. //We're done.
TplCallback callback = (TplCallback) conn->cgiArg; TplCallback callback = (TplCallback) conn->cgiArg;

@ -1,6 +1,23 @@
#include "httpd-utils.h" #include "httpd-utils.h"
#include "httpd-logging.h" #include "httpd-logging.h"
const char *strnstr(const char *str, const char *substr, size_t n)
{
if (!str || !substr) {
return NULL;
}
size_t substr_len = strlen(substr);
if (0 == substr_len || substr_len > n) { return NULL; }
const char *pEnd = str + n + 1 - substr_len;
for (const char *p = str; p < pEnd; p++) {
if (0 == strncmp(p, substr, substr_len)) {
return p;
}
}
return NULL;
}
char httpdHexNibble(uint8_t val) char httpdHexNibble(uint8_t val)
{ {
val &= 0xf; val &= 0xf;
@ -25,7 +42,7 @@ size_t httpdUrlDecode(const char *val, size_t valLen, char *buff, size_t buffLen
uint8_t escVal = 0; uint8_t escVal = 0;
while (s < valLen && d < buffLen) { while (s < valLen && d < buffLen) {
if (esced == 1) { if (esced == 1) {
escVal = httpdHexVal(val[s]) << 4; escVal = (uint8_t) (httpdHexVal(val[s]) << 4);
esced = 2; esced = 2;
} else if (esced == 2) { } else if (esced == 2) {
escVal |= httpdHexVal(val[s]); escVal |= httpdHexVal(val[s]);
@ -58,7 +75,7 @@ int httpdFindArg(const char *line, const char *arg, char *buff, size_t buffLen)
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, (int) (e - p)); router_dbg("findArg: val %s len %d", p, (int) (e - p));
return (int) httpdUrlDecode(p, (size_t)(e - p), buff, buffLen); return (int) httpdUrlDecode(p, (size_t) (e - p), buff, buffLen);
} }
p = strstr(p, "&"); p = strstr(p, "&");
if (p != NULL) { p += 1; } if (p != NULL) { p += 1; }
@ -95,21 +112,23 @@ static const MimeMap MIME_TYPES[] = {
{"svg", "image/svg+xml"}, {"svg", "image/svg+xml"},
{"xml", "text/xml"}, {"xml", "text/xml"},
{"json", "application/json"}, {"json", "application/json"},
{NULL, NULL}, //default value
}; };
const char *httpdGetMimetype(const char *url) const char *httpdGetMimetype(const char *url)
{ {
int i = 0;
//Go find the extension //Go find the extension
const char *ext = url + (strlen(url) - 1); const char *ext = url + (strlen(url) - 1);
while (ext != url && *ext != '.') { ext--; } while (ext != url && *ext != '.') { ext--; }
if (*ext == '.') { ext++; } if (*ext == '.') { ext++; }
while (MIME_TYPES[i].ext != NULL && strcasecmp(ext, MIME_TYPES[i].ext) != 0) { i++; } for (size_t i = 0; i < array_len(MIME_TYPES); i++) {
if (strcaseeq(ext, MIME_TYPES[i].ext)) {
return MIME_TYPES[i].mimetype;
}
}
return MIME_TYPES[i].mimetype; return NULL;
} }

@ -19,6 +19,7 @@ Esp8266 http server - core routines
#include "httpd-logging.h" #include "httpd-logging.h"
static void cleanupCgiAndUserData(HttpdConnData *hconn); static void cleanupCgiAndUserData(HttpdConnData *hconn);
static void httpdRetireConn(HttpdConnData *hconn); static void httpdRetireConn(HttpdConnData *hconn);
_Static_assert(HTTPD_MAX_CONNECTIONS < 256, "HTTPD_MAX_CONNECTIONS must be at most 255"); _Static_assert(HTTPD_MAX_CONNECTIONS < 256, "HTTPD_MAX_CONNECTIONS must be at most 255");
@ -27,6 +28,14 @@ _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;
struct HttpdQueuedHeader;
typedef struct HttpdQueuedHeader {
/// Pointer to the next queued header
struct HttpdQueuedHeader *next;
/// Text of the header, including CRLF
char headerLine[];
} HttpdQueuedHeader;
typedef struct HttpSendBacklogItem HttpSendBacklogItem; typedef struct HttpSendBacklogItem HttpSendBacklogItem;
struct HttpSendBacklogItem { struct HttpSendBacklogItem {
@ -52,6 +61,7 @@ struct HttpdPriv {
size_t sendBuffLen; size_t sendBuffLen;
char *chunkHdr; char *chunkHdr;
HttpSendBacklogItem *sendBacklog; HttpSendBacklogItem *sendBacklog;
HttpdQueuedHeader *headersToSend; // Linked list of headers to send with the response. Will be freed with the request.
size_t sendBacklogSize; size_t sendBacklogSize;
uint8_t flags; uint8_t flags;
}; };
@ -60,7 +70,7 @@ struct HttpdPriv {
//Connection pool //Connection pool
HttpdConnData *s_connData[HTTPD_MAX_CONNECTIONS]; HttpdConnData *s_connData[HTTPD_MAX_CONNECTIONS];
void httpdInternalCloseAllSockets() void httpdInternalCloseAllSockets(void)
{ {
httpdPlatLock(); httpdPlatLock();
/*release data connection*/ /*release data connection*/
@ -89,8 +99,7 @@ void httpdAddCacheHeaders(HttpdConnData *connData, const char *mime)
if (streq(mime, "text/html") if (streq(mime, "text/html")
|| streq(mime, "text/plain") || streq(mime, "text/plain")
|| streq(mime, "text/csv") || streq(mime, "text/csv")
|| streq(mime, "application/json") || streq(mime, "application/json")) {
) {
return; return;
} }
@ -191,6 +200,37 @@ int httpdGetHeader(HttpdConnData *conn, const char *header, char *buff, size_t b
return 0; return 0;
} }
void httpdQueueHeader(HttpdConnData *conn, const char *header, const char *value)
{
if (!conn || !header || !value) {
return;
}
if (conn->priv->flags & HFL_SENDINGBODY) {
http_error("Headers already sent.");
return;
}
HttpdQueuedHeader *queEntry = httpdPlatMalloc(sizeof(void *) + strlen(header) + strlen(value) + 5);
if (!queEntry) {
http_error("httpdQueueHeader - no mem");
return;
}
queEntry->next = NULL;
queEntry->headerLine[0] = 0;
strcat(queEntry->headerLine, header);
strcat(queEntry->headerLine, ": ");
strcat(queEntry->headerLine, value);
strcat(queEntry->headerLine, "\r\n");
// Attach it to the linked list
HttpdQueuedHeader **ph = &conn->priv->headersToSend;
while (*ph) {
ph = &(*ph)->next;
}
*ph = queEntry;
}
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) {
@ -224,12 +264,12 @@ void httpdStartResponse(HttpdConnData *conn, int code)
} }
} }
size_t l = (size_t)sprintf(buff, "HTTP/1.%d %d %s\r\nServer: %s\r\n%s", size_t l = (size_t) sprintf(buff, "HTTP/1.%d %d %s\r\nServer: %s\r\n%s",
((conn->priv->flags & HFL_HTTP11) ? 1 : 0), ((conn->priv->flags & HFL_HTTP11) ? 1 : 0),
code, code,
httpdStatusName(code), httpdStatusName(code),
s_serverName, s_serverName,
connStr); connStr);
httpdSendStrN(conn, buff, l); httpdSendStrN(conn, buff, l);
@ -252,6 +292,15 @@ void httpdHeader(HttpdConnData *conn, const char *field, const char *val)
//Finish the headers. //Finish the headers.
void httpdEndHeaders(HttpdConnData *conn) void httpdEndHeaders(HttpdConnData *conn)
{ {
// Add queued headers
HttpdQueuedHeader *qh = conn->priv->headersToSend;
while (qh) {
httpdSendStr(conn, qh->headerLine);
HttpdQueuedHeader *next = qh->next;
httpdPlatFree(qh);
qh = next;
}
httpdSendStr(conn, "\r\n"); httpdSendStr(conn, "\r\n");
conn->priv->flags |= HFL_SENDINGBODY; conn->priv->flags |= HFL_SENDINGBODY;
} }
@ -309,17 +358,21 @@ int httpdSend_html(HttpdConnData *conn, const char *data, ssize_t len)
} }
if (c == '"' || c == '\'' || c == '<' || c == '>') { if (c == '"' || c == '\'' || c == '<' || c == '>') {
if (start < end) httpdSend_orDie(conn, data + start, end - start); if (start < end) {
httpdSend_orDie(conn, data + start, end - start);
}
start = end + 1; start = end + 1;
} }
if (c == '"') httpdSendStr_orDie(conn, "&#34;"); if (c == '"') { httpdSendStr_orDie(conn, "&#34;"); }
else if (c == '\'') httpdSendStr_orDie(conn, "&#39;"); else if (c == '\'') { httpdSendStr_orDie(conn, "&#39;"); }
else if (c == '<') httpdSendStr_orDie(conn, "&lt;"); else if (c == '<') { httpdSendStr_orDie(conn, "&lt;"); }
else if (c == '>') httpdSendStr_orDie(conn, "&gt;"); else if (c == '>') { httpdSendStr_orDie(conn, "&gt;"); }
} }
if (start < end) httpdSend_orDie(conn, data + start, end - start); if (start < end) {
httpdSend_orDie(conn, data + start, end - start);
}
return 1; return 1;
} }
@ -340,20 +393,24 @@ int httpdSend_js(HttpdConnData *conn, const char *data, ssize_t len)
} }
if (c == '"' || c == '\\' || c == '\'' || c == '<' || c == '>' || c == '\n' || c == '\r') { if (c == '"' || c == '\\' || c == '\'' || c == '<' || c == '>' || c == '\n' || c == '\r') {
if (start < end) httpdSend_orDie(conn, data + start, end - start); if (start < end) {
httpdSend_orDie(conn, data + start, end - start);
}
start = end + 1; start = end + 1;
} }
if (c == '"') httpdSendStr_orDie(conn, "\\\""); if (c == '"') { httpdSendStr_orDie(conn, "\\\""); }
else if (c == '\'') httpdSendStr_orDie(conn, "\\'"); else if (c == '\'') { httpdSendStr_orDie(conn, "\\'"); }
else if (c == '\\') httpdSendStr_orDie(conn, "\\\\"); else if (c == '\\') { httpdSendStr_orDie(conn, "\\\\"); }
else if (c == '<') httpdSendStr_orDie(conn, "\\u003C"); else if (c == '<') { httpdSendStr_orDie(conn, "\\u003C"); }
else if (c == '>') httpdSendStr_orDie(conn, "\\u003E"); else if (c == '>') { httpdSendStr_orDie(conn, "\\u003E"); }
else if (c == '\n') httpdSendStr_orDie(conn, "\\n"); else if (c == '\n') { httpdSendStr_orDie(conn, "\\n"); }
else if (c == '\r') httpdSendStr_orDie(conn, "\\r"); 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);
}
return 1; return 1;
} }
@ -371,7 +428,7 @@ bool httpdFlushSendBuffer(HttpdConnData *conn)
//Finish chunk with cr/lf //Finish chunk with cr/lf
httpdSendStr(conn, "\r\n"); httpdSendStr(conn, "\r\n");
//Calculate length of chunk //Calculate length of chunk
len = (size_t) ((char *)(&conn->priv->sendBuff[conn->priv->sendBuffLen]) - conn->priv->chunkHdr) - 8; len = (size_t) ((char *) (&conn->priv->sendBuff[conn->priv->sendBuffLen]) - conn->priv->chunkHdr) - 8;
//Fix up chunk header to correct value //Fix up chunk header to correct value
conn->priv->chunkHdr[0] = httpdHexNibble((uint8_t) (len >> 12)); conn->priv->chunkHdr[0] = httpdHexNibble((uint8_t) (len >> 12));
conn->priv->chunkHdr[1] = httpdHexNibble((uint8_t) (len >> 8)); conn->priv->chunkHdr[1] = httpdHexNibble((uint8_t) (len >> 8));
@ -507,7 +564,6 @@ void httpdContinue(HttpdConnData *conn)
//find the next cgi function, wait till the cgi data is sent or close up the connection. //find the next cgi function, wait till the cgi data is sent or close up the connection.
static void httpdProcessRequest(HttpdConnData *conn) static void httpdProcessRequest(HttpdConnData *conn)
{ {
int r;
int i = 0; int i = 0;
if (conn->url == NULL) { if (conn->url == NULL) {
router_warn("WtF? url = NULL"); router_warn("WtF? url = NULL");
@ -564,7 +620,7 @@ static void httpdProcessRequest(HttpdConnData *conn)
//Okay, we have a CGI function that matches the URL. See if it wants to handle the //Okay, we have a CGI function that matches the URL. See if it wants to handle the
//particular URL we're supposed to handle. //particular URL we're supposed to handle.
r = conn->cgi(conn); httpd_cgi_state r = conn->cgi(conn);
if (r == HTTPD_CGI_MORE) { if (r == HTTPD_CGI_MORE) {
//Yep, it's happy to do so and has more data to send. //Yep, it's happy to do so and has more data to send.
if (conn->recvHdl) { if (conn->recvHdl) {

Loading…
Cancel
Save