CivetServer.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Copyright (c) 2013 No Face Press, LLC
  3. * License http://opensource.org/licenses/mit-license.php MIT License
  4. */
  5. #include "CivetServer.h"
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <assert.h>
  9. #ifndef UNUSED_PARAMETER
  10. #define UNUSED_PARAMETER(x) (void)(x)
  11. #endif
  12. bool CivetHandler::handleGet(CivetServer *server, struct mg_connection *conn) {
  13. UNUSED_PARAMETER(server);
  14. UNUSED_PARAMETER(conn);
  15. return false;
  16. }
  17. bool CivetHandler::handlePost(CivetServer *server, struct mg_connection *conn) {
  18. UNUSED_PARAMETER(server);
  19. UNUSED_PARAMETER(conn);
  20. return false;
  21. }
  22. bool CivetHandler::handlePut(CivetServer *server, struct mg_connection *conn) {
  23. UNUSED_PARAMETER(server);
  24. UNUSED_PARAMETER(conn);
  25. return false;
  26. }
  27. bool CivetHandler::handleDelete(CivetServer *server, struct mg_connection *conn) {
  28. UNUSED_PARAMETER(server);
  29. UNUSED_PARAMETER(conn);
  30. return false;
  31. }
  32. int CivetServer::requestHandler(struct mg_connection *conn, void *cbdata) {
  33. struct mg_request_info *request_info = mg_get_request_info(conn);
  34. CivetServer *me = (CivetServer*) (request_info->user_data);
  35. CivetHandler *handler = (CivetHandler *)cbdata;
  36. if (handler) {
  37. if (strcmp(request_info->request_method, "GET") == 0) {
  38. return handler->handleGet(me, conn) ? 1 : 0;
  39. } else if (strcmp(request_info->request_method, "POST") == 0) {
  40. return handler->handlePost(me, conn) ? 1 : 0;
  41. } else if (strcmp(request_info->request_method, "PUT") == 0) {
  42. return !handler->handlePut(me, conn) ? 1 : 0;
  43. } else if (strcmp(request_info->request_method, "DELETE") == 0) {
  44. return !handler->handleDelete(me, conn) ? 1 : 0;
  45. }
  46. }
  47. return 0; // No handler found
  48. }
  49. CivetServer::CivetServer(const char **options,
  50. const struct mg_callbacks *_callbacks) :
  51. context(0) {
  52. if (_callbacks) {
  53. context = mg_start(_callbacks, this, options);
  54. } else {
  55. struct mg_callbacks callbacks;
  56. memset(&callbacks, 0, sizeof(callbacks));
  57. context = mg_start(&callbacks, this, options);
  58. }
  59. }
  60. CivetServer::~CivetServer() {
  61. close();
  62. }
  63. void CivetServer::addHandler(const std::string &uri, CivetHandler *handler) {
  64. mg_set_request_handler(context, uri.c_str(), requestHandler, handler);
  65. }
  66. void CivetServer::removeHandler(const std::string &uri) {
  67. mg_set_request_handler(context, uri.c_str(), NULL, NULL);
  68. }
  69. void CivetServer::close() {
  70. if (context) {
  71. mg_stop (context);
  72. context = 0;
  73. }
  74. }
  75. int CivetServer::getCookie(struct mg_connection *conn, const std::string &cookieName, std::string &cookieValue)
  76. {
  77. //Maximum cookie length as per microsoft is 4096. http://msdn.microsoft.com/en-us/library/ms178194.aspx
  78. char _cookieValue[4096];
  79. const char *cookie = mg_get_header(conn, "Cookie");
  80. int lRead = mg_get_cookie(cookie, cookieName.c_str(), _cookieValue, sizeof(_cookieValue));
  81. cookieValue.clear();
  82. cookieValue.append(_cookieValue);
  83. return lRead;
  84. }
  85. const char* CivetServer::getHeader(struct mg_connection *conn, const std::string &headerName)
  86. {
  87. return mg_get_header(conn, headerName.c_str());
  88. }
  89. void
  90. CivetServer::urlDecode(const char *src, std::string &dst, bool is_form_url_encoded) {
  91. urlDecode(src, strlen(src), dst, is_form_url_encoded);
  92. }
  93. void
  94. CivetServer::urlDecode(const char *src, size_t src_len, std::string &dst, bool is_form_url_encoded) {
  95. int i, j, a, b;
  96. #define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
  97. dst.clear();
  98. for (i = j = 0; i < (int)src_len; i++, j++) {
  99. if (src[i] == '%' && i < (int)src_len - 2 &&
  100. isxdigit(* (const unsigned char *) (src + i + 1)) &&
  101. isxdigit(* (const unsigned char *) (src + i + 2))) {
  102. a = tolower(* (const unsigned char *) (src + i + 1));
  103. b = tolower(* (const unsigned char *) (src + i + 2));
  104. dst.push_back((char) ((HEXTOI(a) << 4) | HEXTOI(b)));
  105. i += 2;
  106. } else if (is_form_url_encoded && src[i] == '+') {
  107. dst.push_back(' ');
  108. } else {
  109. dst.push_back(src[i]);
  110. }
  111. }
  112. }
  113. bool
  114. CivetServer::getParam(struct mg_connection *conn, const char *name,
  115. std::string &dst, size_t occurrence) {
  116. const char *query = mg_get_request_info(conn)->query_string;
  117. return getParam(query, strlen(query), name, dst, occurrence);
  118. }
  119. bool
  120. CivetServer::getParam(const char *data, size_t data_len, const char *name,
  121. std::string &dst, size_t occurrence) {
  122. const char *p, *e, *s;
  123. size_t name_len;
  124. dst.clear();
  125. if (data == NULL || name == NULL || data_len == 0) {
  126. return false;
  127. }
  128. name_len = strlen(name);
  129. e = data + data_len;
  130. // data is "var1=val1&var2=val2...". Find variable first
  131. for (p = data; p + name_len < e; p++) {
  132. if ((p == data || p[-1] == '&') && p[name_len] == '=' &&
  133. !mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
  134. // Point p to variable value
  135. p += name_len + 1;
  136. // Point s to the end of the value
  137. s = (const char *) memchr(p, '&', (size_t)(e - p));
  138. if (s == NULL) {
  139. s = e;
  140. }
  141. assert(s >= p);
  142. // Decode variable into destination buffer
  143. urlDecode(p, (int)(s - p), dst, true);
  144. return true;
  145. }
  146. }
  147. return false;
  148. }
  149. void
  150. CivetServer::urlEncode(const char *src, std::string &dst, bool append) {
  151. urlEncode(src, strlen(src), dst, append);
  152. }
  153. void
  154. CivetServer::urlEncode(const char *src, size_t src_len, std::string &dst, bool append) {
  155. static const char *dont_escape = "._-$,;~()";
  156. static const char *hex = "0123456789abcdef";
  157. if (!append)
  158. dst.clear();
  159. for (; src_len > 0; src_len--) {
  160. if (isalnum(*(const unsigned char *) src) ||
  161. strchr(dont_escape, * (const unsigned char *) src) != NULL) {
  162. dst.push_back(*src);
  163. } else {
  164. dst.push_back('%');
  165. dst.push_back(hex[(* (const unsigned char *) src) >> 4]);
  166. dst.push_back(hex[(* (const unsigned char *) src) & 0xf]);
  167. }
  168. }
  169. }