#include "httpd-utils.h" #include "httpd.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"; } }