24#include <boost/algorithm/string.hpp>
30#include <unordered_map>
36 unordered_map<string, string> contentTypeMap = {
38 {
"arc",
"application/x-freearc"},
39 {
"avi",
"video/x-msvideo"},
40 {
"azw",
"application/vnd.amazon.ebook"},
42 {
"bz",
"application/x-bzip"},
43 {
"bz2",
"application/x-bzip2"},
44 {
"csh",
"application/x-csh"},
47 {
"deb",
"application/vnd.debian.binary-package"},
48 {
"doc",
"application/msword"},
49 {
"dot",
"application/msword"},
50 {
"docx",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
51 {
"dotx",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
52 {
"eot",
"application/vnd.ms-fontobject"},
53 {
"epub",
"application/epub+zip"},
54 {
"flv",
"video/x-flv"},
58 {
"gz",
"application/x-gzip"},
60 {
"html",
"text/html"},
61 {
"ico",
"image/vnd.microsoft.icon"},
62 {
"ics",
"text/calendar"},
63 {
"jar",
"application/java-archive"},
64 {
"java",
"text/plain"},
65 {
"jpg",
"image/jpeg"},
66 {
"jpeg",
"image/jpeg"},
67 {
"js",
"text/javascript"},
68 {
"json",
"application/json"},
69 {
"mid",
"audio/x-midi"},
70 {
"midi",
"audio/x-midi"},
71 {
"mjs",
"application/javascript"},
72 {
"mp3",
"audio/mpeg"},
73 {
"mpeg",
"video/mpeg"},
74 {
"mp4",
"application/mp4"},
77 {
"mpkg",
"application/vnd.apple.installer+xml"},
78 {
"odp",
"application/vnd.oasis.opendocument.presentation"},
79 {
"otp",
"application/vnd.oasis.opendocument.presentation"},
80 {
"ods",
"application/vnd.oasis.opendocument.spreadsheet"},
81 {
"ots",
"application/vnd.oasis.opendocument.spreadsheet"},
82 {
"odt",
"application/vnd.oasis.opendocument.text"},
83 {
"ott",
"application/vnd.oasis.opendocument.text"},
84 {
"ogg",
"application/ogg"},
85 {
"ogx",
"application/ogg"},
90 {
"pdf",
"application/pdf"},
91 {
"ppt",
"application/vnd.ms-powerpoint"},
92 {
"pptx",
"application/vnd.openxmlformats-officedocument.presentationml.presentation"},
93 {
"rar",
"application/x-rar-compressed"},
94 {
"rtf",
"application/rtf"},
95 {
"sh",
"application/x-sh"},
96 {
"svg",
"image/svg+xml"},
97 {
"swf",
"application/x-shockwave-flash"},
98 {
"tar",
"application/x-tar"},
99 {
"tif",
"image/tiff"},
100 {
"tiff",
"image/tiff"},
102 {
"txt",
"text/plain"},
103 {
"vsd",
"application/vnd.visio"},
104 {
"wav",
"audio/wav"},
105 {
"weba",
"audio/webm"},
106 {
"webm",
"video/webm"},
107 {
"webp",
"image/webp"},
108 {
"woff",
"font/woff"},
109 {
"woff2",
"font/woff2"},
110 {
"xhtml",
"application/xhtml+xml"},
111 {
"xls",
"application/vnd.ms-excel"},
112 {
"xlt",
"application/vnd.ms-excel"},
113 {
"xlsx",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
114 {
"xltx",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
115 {
"xml",
"application/xml"},
116 {
"xul",
"application/vnd.mozilla.xul+xml"},
117 {
"xz",
"application/x-xz"},
118 {
"zip",
"application/zip"},
119 {
"3gp",
"video/3gpp"},
120 {
"3g2",
"video/3gpp2"},
121 {
"7z",
"application/x-7z-compressed"}};
129 inline string getDayOfWeek(
int dow) {
165 inline string getMonth(
int mon) {
214 std::function<std::string(std::vector<std::string>
const&)>
const& fmt) {
216 int marks = rgx.mark_count();
218 vector<int> submatchList;
219 for (
int i = -1; i <= marks; ++i) {
220 submatchList.push_back(i);
223 sregex_token_iterator begin(s.begin(), s.end(), rgx, submatchList), end;
228 vector<string> submatchVector;
229 for (
auto it = begin; it != end; ++it) {
230 if (submatch == -1) {
234 submatchVector.push_back(it->str());
235 if (submatch < marks) {
238 out << fmt(submatchVector);
239 submatchVector.clear();
249 rets << hex << setfill(
'0');
251 rets << setw(2) << (int) (
unsigned char) c;
257 transform(s.begin(), s.end(), s.begin(), ::tolower);
262 transform(s.begin(), s.end(), s.begin(), ::toupper);
269 switch (httpStatus) {
271 errorStr =
"Bad Request";
272 explanation =
"The server cannot process your request.";
275 errorStr =
"Unauthorized";
276 explanation =
"The necessary credentials have not been provided.";
279 errorStr =
"Forbidden";
280 explanation =
"You do not have the necessary permissions to view this page.";
283 errorStr =
"Not Found";
284 explanation =
"The requested URL was not found on this server.";
287 errorStr =
"Method Not Allowed";
288 explanation =
"The used request method is not supported for the requested resource.";
291 errorStr =
"Not Applicable";
292 explanation =
"The requested function is unable to produce a resource that satisfies your browser's Accept header.";
295 errorStr =
"Request Timeout";
296 explanation =
"A timeout occurred while waiting for your request.";
299 errorStr =
"Conflict";
300 explanation =
"The request cannot be processed due to a conflict on the underlying resource.";
304 explanation =
"The requested resource is no longer available.";
307 errorStr =
"Unsupported Media Type";
308 explanation =
"Your browser has requested a media type that cannot be provided by this resource.";
311 errorStr =
"I'm a teapot";
312 explanation =
"I cannot brew coffee for you.";
315 errorStr =
"Too Many Requests";
318 errorStr =
"Unavailable For Legal Reasons";
321 errorStr =
"Internal Server Error";
322 explanation =
"The server encountered an internal error and is unable to fulfill your request.";
325 errorStr =
"Not Implemented";
326 explanation =
"The server is not able to fulfill your request.";
329 errorStr =
"Service Unavailable";
330 explanation =
"This service is currently unavailable. Please try again later.";
333 errorStr =
"Unknown Error";
337 ep <<
"<!DOCTYPE html><html><head><title>" << httpStatus <<
' ' << errorStr <<
"</title></head><body><h1>"
338 << errorStr <<
"</h1><p>" << explanation <<
"</p></body></html>";
345 return filename.substr(filename.find_last_of(
'.') + 1);
346 }
catch (out_of_range&) {}
353 if (contentTypeMap.count(ext) == 1) {
354 return contentTypeMap.at(ext);
356 return "application/octet-stream";
360 stringstream httpTime;
362 gmtime_r(&time, &gmt);
363 httpTime << getDayOfWeek(gmt.tm_wday) << put_time(&gmt,
", %d ") << getMonth(gmt.tm_mon);
364 httpTime << put_time(&gmt,
" %Y %H:%M:%S GMT");
366 return httpTime.str();
370 istringstream timeStream(httpTime);
372 timeStream >> get_time(&timeStruct,
"%a, %d %b %Y %H:%M:%S GMT");
375 return timegm(&timeStruct);
379 stringstream smtpTime;
381 localtime_r(&time, <ime);
382 smtpTime << getDayOfWeek(ltime.tm_wday) << put_time(<ime,
", %e ") << getMonth(ltime.tm_mon);
383 smtpTime << put_time(<ime,
" %Y %H:%M:%S %z");
385 return smtpTime.str();
389 string smtpTimeM = smtpTime;
397 if (smtpTimeM.length() > 5 && smtpTimeM[5] ==
' ') {
400 istringstream timeStream(smtpTimeM);
401 timeStream >> get_time(&timeStruct,
"%a, %d %b %Y %H:%M:%S %z");
404 time_t unixTime = timegm(&timeStruct);
407 if (smtpTimeM.length() > 30) {
408 int tzAdjust = smtpTimeM[26] ==
'-' ? 1 : -1;
409 int tzH = stoi(smtpTimeM.substr(27, 2));
410 int tzM = stoi(smtpTimeM.substr(29, 2));
411 unixTime += tzAdjust * (tzH * 3600 + tzM * 60);
420 for (
size_t pos = 0; !str.empty();) {
421 pos = str.find_first_of(delimiter);
422 auto token = str.substr(0, pos);
423 if (!ignoreEmpty || !token.empty()) {
424 ret.push_back(str.substr(0, pos));
426 if (pos < str.length()) {
427 str = str.substr(pos + 1);
439 stringstream stringPath;
440 for (
auto const& e : path) {
441 stringPath <<
'/' << e;
443 return stringPath.str();
448 string rawPath = pathString.substr(0, pathString.find(
'?'));
454 for (
const auto& c : in) {
465 ifstream f(path, ifstream::binary);
469 throw Exception(__PRETTY_FUNCTION__, 1,
"Cannot open file for reading");
473 f.seekg(0, ios::end);
478 string ret(
static_cast<unsigned long>(fs),
'\0');
485 for (
auto const& [key, val] : patterns) {
486 replace(input.begin(), input.end(), key, val);
492 for (
auto const& [key, val] : patterns) {
493 for (
size_t pos = input.find(key); pos != string::npos;) {
494 input.replace(pos, key.length(), val);
495 pos = input.find(key, pos + val.length());
503 size_t qmrkPos = queryString.find_first_of(
'?');
504 unordered_multimap<string, string> ret;
505 if (qmrkPos != string::npos && queryString.length() > qmrkPos) {
506 qs = queryString.substr(qmrkPos + 1);
507 }
else if (qmrkPos == string::npos) {
511 for (
auto const& p : pairs) {
512 size_t eqPos = p.find_first_of(
'=');
513 string k = p.substr(0, eqPos);
521 unordered_map<string, string> ret;
523 boost::erase_all(rawHeaders,
"\r");
526 for (
auto const& line : lines) {
527 auto colonPos = line.find_first_of(
':');
528 if (line.length() < colonPos + 2) {
532 auto val = line.substr(colonPos + 1);
533 boost::trim_left(val);
540 unordered_multimap<std::string, std::string> ret;
543 for (
auto c : cookies) {
547 auto eqPos = c.find_first_of(
'=');
548 if (c.length() < eqPos + 2) {
551 auto key = c.substr(0, eqPos);
552 auto val = c.substr(eqPos + 1);
553 ret.insert({key, val});
Exception class that can be used by apps to catch errors resulting from nawa function calls.
Namespace containing functions for text encoding and decoding.
std::string urlDecode(std::string input)
void regexReplaceCallback(std::string &s, std::regex const &rgx, std::function< std::string(std::vector< std::string > const &)> const &fmt)
std::string hexDump(std::string const &in)
std::string getFileContents(std::string const &path)
time_t readSmtpTime(std::string const &smtpTime)
std::unordered_multimap< std::string, std::string > splitQueryString(std::string const &queryString)
std::string convertLineEndings(std::string const &in, std::string const &ending)
time_t readHttpTime(std::string const &httpTime)
std::unordered_multimap< std::string, std::string > parseCookies(std::string const &rawCookies)
std::string stringReplace(std::string input, std::unordered_map< char, char > const &patterns)
std::string generateErrorPage(unsigned int httpStatus)
std::vector< std::string > splitPath(std::string const &pathString)
std::string toLowercase(std::string s)
std::string contentTypeByExtension(std::string extension)
std::string toUppercase(std::string s)
std::string getFileExtension(std::string const &filename)
std::string makeHttpTime(time_t time)
std::vector< std::string > splitString(std::string str, char delimiter, bool ignoreEmpty=false)
std::string makeSmtpTime(time_t time)
std::string mergePath(std::vector< std::string > const &path)
std::unordered_map< std::string, std::string > parseHeaders(std::string rawHeaders)
Contains useful functions that improve the readability and facilitate maintenance of the NAWA code.