SpriteHTTPD - embedded HTTP server with read-only filesystem and templating, originally developed for ESP8266, now stand-alone and POSIX compatible.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
spritehttpd/spritehttpd/src/httpd-utils.c

161 lines
4.0 KiB

#include "httpd-utils.h"
#include "httpd-logging.h"
char httpdHexNibble(uint8_t val)
{
val &= 0xf;
if (val < 10) { return (char) ('0' + val); }
return (char) ('A' + (val - 10));
}
uint8_t httpdHexVal(char c)
{
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; }
return 0;
}
int httpdUrlDecode(const char *val, size_t valLen, char *buff, size_t buffLen)
{
size_t s = 0, d = 0;
int esced = 0;
char escVal = 0;
while (s < valLen && d < buffLen) {
if (esced == 1) {
escVal = httpdHexVal(val[s]) << 4;
esced = 2;
} else if (esced == 2) {
escVal |= httpdHexVal(val[s]);
buff[d++] = escVal;
esced = 0;
} else if (val[s] == '%') {
esced = 1;
} else if (val[s] == '+') {
buff[d++] = ' ';
} else {
buff[d++] = val[s];
}
s++;
}
if (d < buffLen) { buff[d] = 0; }
return d;
}
int httpdFindArg(const char *line, const char *arg, char *buff, size_t buffLen)
{
const char *p, *e;
if (line == NULL) { return -1; }
const size_t arglen = strlen(arg);
p = line;
while (p != NULL && *p != '\n' && *p != '\r' && *p != 0) {
router_dbg("findArg: %s", p);
if (strstarts(p, arg) && p[arglen] == '=') {
p += arglen + 1; //move p to start of value
e = strstr(p, "&");
if (e == NULL) { e = p + strlen(p); }
router_dbg("findArg: val %s len %d", p, (int) (e - p));
return httpdUrlDecode(p, (int)(e - p), buff, buffLen);
}
p = strstr(p, "&");
if (p != NULL) { p += 1; }
}
router_error("Finding arg %s in %s: Not found :/", arg, line);
return -1; //not found
}
//Struct to keep extension->mime data in
typedef struct {
const char *ext;
const char *mimetype;
} MimeMap;
/**
* The mappings from file extensions to mime types. If you need an extra mime type,
* add it here.
*/
static const MimeMap MIME_TYPES[] = {
{"htm", "text/html"},
{"html", "text/html"},
{"css", "text/css"},
{"js", "text/javascript"},
{"txt", "text/plain"},
{"csv", "text/csv"},
{"ico", "image/x-icon"},
{"jpg", "image/jpeg"},
{"jpeg", "image/jpeg"},
{"png", "image/png"},
{"gif", "image/gif"},
{"bmp", "image/bmp"},
{"svg", "image/svg+xml"},
{"xml", "text/xml"},
{"json", "application/json"},
{NULL, "text/html"}, //default value
};
const char *httpdGetMimetype(const char *url)
{
int i = 0;
//Go find the extension
const char *ext = url + (strlen(url) - 1);
while (ext != url && *ext != '.') { ext--; }
if (*ext == '.') { ext++; }
while (MIME_TYPES[i].ext != NULL && strcasecmp(ext, MIME_TYPES[i].ext) != 0) { i++; }
return MIME_TYPES[i].mimetype;
}
const char *httpdMethodName(httpd_method m)
{
switch (m) {
default:
case HTTPD_METHOD_GET:
return "GET";
case HTTPD_METHOD_POST:
return "POST";
case HTTPD_METHOD_OPTIONS:
return "OPTIONS";
case HTTPD_METHOD_PUT:
return "PUT";
case HTTPD_METHOD_DELETE:
return "DELETE";
case HTTPD_METHOD_PATCH:
return "PATCH";
case HTTPD_METHOD_HEAD:
return "HEAD";
}
}
const char *httpdStatusName(int code)
{
// TODO more codes
switch (code) {
case 200:
return "OK";
case 301:
return "Moved Permanently";
case 302:
return "Found";
case 400:
return "Bad Request";
case 401:
return "Unauthorized";
case 403:
return "Forbidden";
case 404:
return "Not Found";
default:
if (code >= 500) { return "Server Error"; }
if (code >= 400) { return "Client Error"; }
return "OK";
}
}