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