asp.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /****************************************************************************
  2. * Copyright (c) 2004 by Michael Fischer. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the author nor the names of its contributors may
  14. * be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  21. * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. ****************************************************************************
  31. * History:
  32. *
  33. * 31.03.04 mifi First Version
  34. * 02.10.04 mifi Add function to register a user callback
  35. * 04.08.05 or Adopted to new new mime-handler framework
  36. ****************************************************************************/
  37. /*
  38. * $Log$
  39. * Revision 1.6 2009/02/13 14:52:05 haraldkipp
  40. * Include memdebug.h for heap management debugging support.
  41. *
  42. * Revision 1.5 2009/02/06 15:40:29 haraldkipp
  43. * Using newly available strdup() and calloc().
  44. * Replaced NutHeap routines by standard malloc/free.
  45. * Replaced pointer value 0 by NULL.
  46. *
  47. * Revision 1.4 2008/05/16 01:46:43 thiagocorrea
  48. * Minor spellcheck fix on the documentation.
  49. *
  50. * Revision 1.3 2006/03/16 15:25:38 haraldkipp
  51. * Changed human readable strings from u_char to char to stop GCC 4 from
  52. * nagging about signedness.
  53. *
  54. * Revision 1.2 2005/08/10 09:26:38 olereinhardt
  55. * Corrected documentation
  56. *
  57. * Revision 1.1 2005/08/05 11:21:02 olereinhardt
  58. * Added Michael Fischers ASP support. Initial checkin
  59. *
  60. */
  61. /*!
  62. * \addtogroup xgHTTPD
  63. */
  64. /*@{*/
  65. #include <sys/heap.h>
  66. #include <sys/confnet.h>
  67. #include <sys/version.h>
  68. #include <stdlib.h>
  69. #include <string.h>
  70. #include <io.h>
  71. #include <fcntl.h>
  72. #include <memdebug.h>
  73. #include <pro/httpd.h>
  74. #include <pro/asp.h>
  75. #include <arpa/inet.h>
  76. extern CONFNET confnet;
  77. /*==========================================================*/
  78. /* DEFINE: All Structures and Common Constants */
  79. /*==========================================================*/
  80. /*
  81. * Use the half size of the normal buffer, because we need
  82. * 2 buffers. To save memory, we have divide the size too.
  83. */
  84. #define MAX_BUFFER_SIZE 256
  85. /*
  86. * Do NOT use more than 250 for the len.
  87. * Because we use a unsigned char for the ASPFuncLen
  88. */
  89. #define MAX_ASP_FUNC_SIZE 64
  90. enum {
  91. ASP_STATE_IDLE = 0,
  92. ASP_STATE_START,
  93. ASP_STATE_COPY_FUNC
  94. };
  95. /*==========================================================*/
  96. /* DEFINE: Definition of all local Data */
  97. /*==========================================================*/
  98. static int (*asp_callback)(char *, FILE *) = NULL;
  99. /*==========================================================*/
  100. /* DEFINE: Definition of all local Procedures */
  101. /*==========================================================*/
  102. /************************************************************/
  103. /* ProcessASPFunction */
  104. /************************************************************/
  105. static void ProcessAspFunction(char *pASPFunction, FILE * stream)
  106. {
  107. if (strstr(pASPFunction, "nut_version") != NULL) {
  108. fprintf(stream, "%s", NutVersionString());
  109. return;
  110. }
  111. if (strstr(pASPFunction, "nut_mac_addr") != NULL) {
  112. fprintf(stream, "%02X:%02X:%02X:%02X:%02X:%02X",
  113. confnet.cdn_mac[0], confnet.cdn_mac[1], confnet.cdn_mac[2],
  114. confnet.cdn_mac[3], confnet.cdn_mac[4], confnet.cdn_mac[5]);
  115. return;
  116. }
  117. if (strstr(pASPFunction, "nut_ip_addr") != NULL) {
  118. fputs(inet_ntoa(confnet.cdn_ip_addr), stream);
  119. return;
  120. }
  121. if (strstr(pASPFunction, "nut_ip_mask") != NULL) {
  122. fputs(inet_ntoa(confnet.cdn_ip_mask), stream);
  123. return;
  124. }
  125. if (strstr(pASPFunction, "nut_gateway") != NULL) {
  126. fputs(inet_ntoa(confnet.cdn_gateway), stream);
  127. return;
  128. }
  129. /*
  130. * Check if the user has registered an ASPCallback
  131. */
  132. if (asp_callback != NULL) {
  133. asp_callback(pASPFunction, stream);
  134. }
  135. }
  136. /*==========================================================*/
  137. /* DEFINE: All code exported */
  138. /*==========================================================*/
  139. /************************************************************/
  140. /* NutHttpCheckAsp */
  141. /************************************************************/
  142. void NutHttpProcessAsp(FILE * stream, int fd, int file_len, char* http_root, REQUEST *req)
  143. {
  144. int n;
  145. char *pReadBuffer = NULL;
  146. char *pWriteBuffer = NULL;
  147. char *pASPFunction = NULL;
  148. char Data;
  149. int Size;
  150. long lFileLen;
  151. unsigned char bASPState = ASP_STATE_IDLE;
  152. int ReadCount;
  153. int WriteCount;
  154. unsigned char bASPFuncLen;
  155. lFileLen = _filelength(fd);
  156. Size = MAX_BUFFER_SIZE;
  157. WriteCount = 0;
  158. bASPFuncLen = 0;
  159. pASPFunction = malloc(MAX_ASP_FUNC_SIZE);
  160. pReadBuffer = malloc(Size);
  161. /*
  162. * For our VERY SPECIAL case, the size of the WriteBuffer must have one char more
  163. * as the ReadBuffer. Because we must be able to save one more char from the round before.
  164. */
  165. pWriteBuffer = malloc(Size + 1);
  166. if ((pReadBuffer != NULL) && (pWriteBuffer != NULL) && (pASPFunction != NULL)) {
  167. while (lFileLen) {
  168. if (lFileLen < MAX_BUFFER_SIZE) {
  169. Size = (int) lFileLen;
  170. }
  171. n = _read(fd, pReadBuffer, Size);
  172. for (ReadCount = 0; ReadCount < n; ReadCount++) {
  173. Data = pReadBuffer[ReadCount];
  174. switch (bASPState) {
  175. case ASP_STATE_IDLE:
  176. if (Data == '<') {
  177. bASPState = ASP_STATE_START;
  178. }
  179. pWriteBuffer[WriteCount] = Data;
  180. WriteCount++;
  181. break;
  182. /* ASP_STATE_IDLE */
  183. case ASP_STATE_START:
  184. if (Data == '%') {
  185. bASPState = ASP_STATE_COPY_FUNC;
  186. if (WriteCount) {
  187. WriteCount--;
  188. }
  189. /*
  190. * Write the data up to the ASPFunction
  191. */
  192. if (WriteCount) {
  193. fwrite(pWriteBuffer, 1, WriteCount, stream);
  194. WriteCount = 0;
  195. }
  196. } else {
  197. bASPState = ASP_STATE_IDLE;
  198. pWriteBuffer[WriteCount] = Data;
  199. WriteCount++;
  200. }
  201. break;
  202. /* ASP_STATE_START_1 */
  203. case ASP_STATE_COPY_FUNC:
  204. if (Data == '>') {
  205. bASPState = ASP_STATE_IDLE;
  206. pASPFunction[bASPFuncLen] = 0;
  207. ProcessAspFunction(pASPFunction, stream);
  208. bASPFuncLen = 0;
  209. } else {
  210. /*
  211. * Skip over the END of an ASPFunction
  212. */
  213. if (Data == '%') {
  214. Data = 0;
  215. }
  216. pASPFunction[bASPFuncLen] = Data;
  217. bASPFuncLen++;
  218. if (bASPFuncLen >= MAX_ASP_FUNC_SIZE) {
  219. /*
  220. * This make no sense, but protect our stack
  221. */
  222. bASPFuncLen = 0;
  223. }
  224. }
  225. break;
  226. /* ASP_STATE_COPY_FUNC */
  227. } /* end switch (bASPState) */
  228. } /* end for */
  229. /*
  230. * If data are available in the WriteBuffer,
  231. * send it out...
  232. */
  233. if (WriteCount) {
  234. /*
  235. * Now we must test a VERY SPECIAL case !
  236. * It could be possible that the last char in the buffer is a '<'.
  237. * Now the State is ASP_STATE_START. If the next chunk starts with a
  238. * '%' it is to late, because we have send out the '<'.
  239. * Therefore we must test if the last char is a '<', in this case send all the
  240. * rest and save the '<' for the next round.
  241. */
  242. if (pWriteBuffer[WriteCount - 1] == '<') {
  243. WriteCount--;
  244. fwrite(pWriteBuffer, 1, WriteCount, stream);
  245. /*
  246. * Now put the '<' in the buffer for the next round
  247. */
  248. pWriteBuffer[0] = '<';
  249. WriteCount = 1;
  250. } else {
  251. fwrite(pWriteBuffer, 1, WriteCount, stream);
  252. WriteCount = 0;
  253. }
  254. }
  255. lFileLen -= (long) n;
  256. }
  257. }
  258. if (pReadBuffer != NULL) {
  259. free(pReadBuffer);
  260. }
  261. if (pWriteBuffer != NULL) {
  262. free(pWriteBuffer);
  263. }
  264. if (pASPFunction != NULL) {
  265. free(pASPFunction);
  266. }
  267. }
  268. /************************************************************/
  269. /* NutRegisterAspCallback */
  270. /* */
  271. /* return 0 on success, -1 otherwise. */
  272. /************************************************************/
  273. int NutRegisterAspCallback(int (*func) (char *, FILE *))
  274. {
  275. register int result = 0;
  276. if (asp_callback == NULL) {
  277. asp_callback = func;
  278. } else {
  279. result = -1;
  280. }
  281. return (result);
  282. }
  283. /*!
  284. * \brief Register ASP handler for asp files.
  285. *
  286. * asp files may use the following syntax:
  287. *
  288. * <%my_function%>
  289. */
  290. void NutRegisterAsp(void)
  291. {
  292. NutSetMimeHandler(".asp", NutHttpProcessAsp);
  293. }
  294. /*@}*/