httpopt.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /*
  2. * Copyright (C) 2008 by egnite GmbH. All rights reserved.
  3. * Copyright (C) 2001-2007 by egnite Software GmbH. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the copyright holders nor the names of
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  21. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  22. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  23. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  24. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  25. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  26. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  27. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  28. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. *
  31. * For additional information see http://www.ethernut.de/
  32. */
  33. /*!
  34. * \file pro/httpopt.c
  35. * \brief Optional HTTP routines.
  36. *
  37. * \verbatim
  38. *
  39. * $Log$
  40. * Revision 1.4 2009/02/13 14:52:05 haraldkipp
  41. * Include memdebug.h for heap management debugging support.
  42. *
  43. * Revision 1.3 2008/08/11 07:00:35 haraldkipp
  44. * BSD types replaced by stdint types (feature request #1282721).
  45. *
  46. * Revision 1.2 2008/05/13 21:46:06 thiagocorrea
  47. * Fix a few documentation typos.
  48. *
  49. * Revision 1.1 2008/04/01 10:11:35 haraldkipp
  50. * Added the new, enhanced httpd API library.
  51. * Bugs #1839026 and #1839029 fixed.
  52. *
  53. *
  54. * \endverbatim
  55. */
  56. #include <cfg/arch.h>
  57. #include <string.h>
  58. #include <io.h>
  59. #include <fcntl.h>
  60. #include <ctype.h>
  61. #include <stdlib.h>
  62. #include <memdebug.h>
  63. #include <sys/heap.h>
  64. #include <sys/version.h>
  65. #include "dencode.h"
  66. #include <pro/httpd.h>
  67. /*!
  68. * \addtogroup xgHTTPD
  69. */
  70. /*@{*/
  71. extern MIMETYPES mimeTypes[];
  72. extern char *http_root;
  73. /*!
  74. * \brief Set the mime type handler for a specified file extension.
  75. *
  76. * This is the function that handles / sends a specific file type to the
  77. * client. Specially used for server side includes (shtml files)
  78. *
  79. * \param extension Filename extension the handler should be registered for
  80. * \param handler pointer to a function of the type void (u_char filename)
  81. * \return 1 on error or 0 on success
  82. */
  83. uint8_t NutSetMimeHandler(char *extension, void (*handler)(FILE *stream, int fd, int file_len, char *http_root, REQUEST *req))
  84. {
  85. size_t i;
  86. if (extension == NULL)
  87. return 1;
  88. for (i = 0; mimeTypes[i].mtyp_ext; i++)
  89. if (strcasecmp(extension, mimeTypes[i].mtyp_ext) == 0) {
  90. mimeTypes[i].mtyp_handler = handler;
  91. return 0;
  92. }
  93. return 1;
  94. }
  95. /*!
  96. * \brief URLEncodes a string
  97. *
  98. * \param str String to encode
  99. *
  100. * \return A new allocated encoded string, or NULL if str is null, or
  101. * if there's not enough memory for the new string.
  102. *
  103. * \note Remember to free() to the returned string.
  104. */
  105. char *NutHttpURLEncode(char *str)
  106. {
  107. static char *hexdigits = "0123456789ABCDEF";
  108. register char *ptr1, *ptr2;
  109. char *encstring;
  110. int numEncs = 0;
  111. if (!str)
  112. return NULL;
  113. /* Calculate how many characters we need to encode */
  114. for (ptr1 = str; *ptr1; ptr1++) {
  115. if (!isalnum((unsigned char)*ptr1) || *ptr1 == '%' || *ptr1 == '&'|| *ptr1 == '+' ||
  116. *ptr1 == ',' || *ptr1 == ':' || *ptr1 == ';'|| *ptr1 == '='|| *ptr1 == '?'|| *ptr1 == '@')
  117. numEncs++;
  118. }
  119. /* Now we can calculate the encoded string length */
  120. encstring = (char *) malloc(strlen(str) + 2 * numEncs + 1);
  121. if (encstring) {
  122. /* Encode the string. ptr1 refers to the original string,
  123. * and ptr2 refers to the new string. */
  124. ptr2 = encstring;
  125. for (ptr1 = str; *ptr1; ptr1++) {
  126. if (isalnum((unsigned char)*ptr1) || *ptr1 == '%' || *ptr1 == '&'|| *ptr1 == '+' ||
  127. *ptr1 == ',' || *ptr1 == ':' || *ptr1 == ';'|| *ptr1 == '='|| *ptr1 == '?'|| *ptr1 == '@')
  128. *ptr2++ = *ptr1;
  129. else {
  130. *ptr2++ = '%';
  131. *ptr2++ = hexdigits[(*ptr1 >> 4)];
  132. *ptr2++ = hexdigits[*ptr1 & 0x0F];
  133. }
  134. }
  135. *ptr2++ = 0;
  136. }
  137. return encstring;
  138. }
  139. /*!
  140. * \brief Parses the QueryString
  141. *
  142. * Reads the query from input stream and parses it into
  143. * name/value table. To save RAM, this method allocated ram and
  144. * uses req_query to store the input data. Then it creates a table
  145. * of pointers into the req_query buffer.
  146. *
  147. * \param stream Input stream
  148. * \param req Request object to parse
  149. */
  150. void NutHttpProcessPostQuery(FILE *stream, REQUEST * req)
  151. {
  152. int got;
  153. register int i;
  154. register char *ptr;
  155. if (req->req_query != NULL)
  156. return;
  157. if (!stream)
  158. return;
  159. if (req->req_method == METHOD_POST) {
  160. req->req_query = malloc(req->req_length+1);
  161. if (req->req_query == NULL) {
  162. /* Out of memory */
  163. req->req_numqptrs = 0;
  164. return;
  165. }
  166. memset(req->req_query, 0, req->req_length+1);
  167. i = 0;
  168. while (i < req->req_length) {
  169. got = fread(&req->req_query[i], 1, req->req_length-i, stream);
  170. if (got <= 0) {
  171. free(req->req_query);
  172. req->req_numqptrs = 0;
  173. req->req_query = NULL;
  174. return;
  175. }
  176. i += got;
  177. }
  178. } else return;
  179. req->req_numqptrs = 1;
  180. for (ptr = req->req_query; *ptr; ptr++)
  181. if (*ptr == '&')
  182. req->req_numqptrs++;
  183. req->req_qptrs = (char **) malloc(sizeof(char *) * (req->req_numqptrs * 2));
  184. if (!req->req_qptrs) {
  185. /* Out of memory */
  186. free(req->req_query);
  187. req->req_numqptrs = 0;
  188. req->req_query = NULL;
  189. return;
  190. }
  191. req->req_qptrs[0] = req->req_query;
  192. req->req_qptrs[1] = 0;
  193. for (ptr = req->req_query, i = 2; *ptr; ptr++) {
  194. if (*ptr == '&') {
  195. req->req_qptrs[i] = ptr + 1;
  196. req->req_qptrs[i + 1] = NULL;
  197. *ptr = 0;
  198. i += 2;
  199. }
  200. }
  201. for (i = 0; i < req->req_numqptrs; i++) {
  202. for (ptr = req->req_qptrs[i * 2]; *ptr; ptr++) {
  203. if (*ptr == '=') {
  204. req->req_qptrs[i * 2 + 1] = ptr + 1;
  205. *ptr = 0;
  206. NutHttpURLDecode(req->req_qptrs[i * 2 + 1]);
  207. break;
  208. }
  209. }
  210. NutHttpURLDecode(req->req_qptrs[i * 2]);
  211. }
  212. }
  213. /*!
  214. * \brief Gets a request parameter value by name
  215. *
  216. * \param req Request object
  217. * \param name Name of parameter
  218. *
  219. * \return Pointer to the parameter value.
  220. */
  221. char *NutHttpGetParameter(REQUEST * req, char *name)
  222. {
  223. int i;
  224. for (i = 0; i < req->req_numqptrs; i++)
  225. if (strcmp(req->req_qptrs[i * 2], name) == 0)
  226. return req->req_qptrs[i * 2 + 1];
  227. return NULL;
  228. }
  229. /*!
  230. * \brief Gets the number of request parameters
  231. *
  232. * The following code fragment retrieves all name/value pairs of the
  233. * request.
  234. *
  235. * \code
  236. * #include &lt;pro/httpd.h&gt;
  237. *
  238. * char *name;
  239. * char *value;
  240. * int i;
  241. * int n = NutHttpGetParameterCount(req);
  242. *
  243. * for (i = 0; i &lt; n; i++) {
  244. * name = NutHttpGetParameterName(req, i);
  245. * value = NutHttpGetParameterValue(req, i);
  246. * }
  247. * \endcode
  248. *
  249. * \param req Request object
  250. *
  251. * \return The number of request parameters
  252. */
  253. int NutHttpGetParameterCount(REQUEST * req)
  254. {
  255. return req->req_numqptrs;
  256. }
  257. /*!
  258. * \brief Gets the name of a request parameter
  259. *
  260. * \param req Request object
  261. * \param index Index of the requested parameter.
  262. *
  263. * \return Pointer to the parameter name at the given index,
  264. * or NULL if index is out of range.
  265. */
  266. char *NutHttpGetParameterName(REQUEST * req, int index)
  267. {
  268. if (index < 0 || index >= NutHttpGetParameterCount(req))
  269. return NULL;
  270. return req->req_qptrs[index * 2];
  271. }
  272. /*!
  273. * \brief Get the value of a request parameter
  274. *
  275. * \param req Request object
  276. * \param index Index to the requested parameter.
  277. *
  278. * \return Pointer to the parameter value at the given index,
  279. * or NULL if index is out of range.
  280. */
  281. char *NutHttpGetParameterValue(REQUEST * req, int index)
  282. {
  283. if (index < 0 || index >= NutHttpGetParameterCount(req))
  284. return NULL;
  285. return req->req_qptrs[index * 2 + 1];
  286. }
  287. /*@}*/