wn_module_ssi.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * File : wn_module_ssi.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
  5. *
  6. * This software is dual-licensed: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation. For the terms of this
  9. * license, see <http://www.gnu.org/licenses/>.
  10. *
  11. * You are free to use this software under the terms of the GNU General
  12. * Public License, but WITHOUT ANY WARRANTY; without even the implied
  13. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. * See the GNU General Public License for more details.
  15. *
  16. * Alternatively for commercial application, you can contact us
  17. * by email <business@rt-thread.com> for commercial license.
  18. *
  19. * Change Logs:
  20. * Date Author Notes
  21. * 2012-06-25 Bernard the first version
  22. */
  23. #include <webnet.h>
  24. #include <wn_session.h>
  25. #include <wn_module.h>
  26. #ifdef RT_USING_DFS
  27. #include <dfs_posix.h>
  28. #endif
  29. #if defined(WEBNET_USING_SSI)
  30. #define SSI_INCLUDE_STRING "<!--#include "
  31. #define SSI_EXEC_STRING "<!--#exec "
  32. #define SSI_VIRTUAL_STRING "virtual=\""
  33. #define SSI_FILE_STRING "file=\""
  34. #define SSI_CGI_STRING "cgi=\""
  35. #define SSI_END_STRING "\" -->"
  36. static void _webnet_ssi_sendfile(struct webnet_session* session, const char* filename)
  37. {
  38. int fd;
  39. int file_length;
  40. rt_size_t size, readbytes;
  41. fd = open(filename, O_RDONLY, 0);
  42. if (fd < 0) return; /* open file failed */
  43. /* get file size */
  44. file_length = lseek(fd, 0, SEEK_END);
  45. /* seek to beginning of file */
  46. lseek(fd, 0, SEEK_SET);
  47. if (file_length <= 0)
  48. {
  49. close(fd);
  50. return ;
  51. }
  52. while (file_length)
  53. {
  54. if (file_length > sizeof(session->buffer))
  55. size = (rt_size_t) sizeof(session->buffer);
  56. else
  57. size = file_length;
  58. readbytes = read(fd, session->buffer, size);
  59. if (readbytes <= 0)
  60. /* no more data */
  61. break;
  62. if (webnet_session_write(session, session->buffer, readbytes) == 0)
  63. break;
  64. file_length -= (long) readbytes;
  65. }
  66. /* close file */
  67. close(fd);
  68. }
  69. static void _webnet_ssi_dofile(struct webnet_session* session, int fd)
  70. {
  71. char *ssi_begin, *ssi_end;
  72. char *offset, *end;
  73. char *buffer;
  74. char *path;
  75. rt_uint32_t length;
  76. ssi_begin = ssi_end = RT_NULL;
  77. offset = end = RT_NULL;
  78. buffer = path = RT_NULL;
  79. /* get file length */
  80. length = lseek(fd, 0, SEEK_END);
  81. lseek(fd, 0, SEEK_SET);
  82. /* allocate ssi include file path */
  83. path = (char*) wn_malloc(WEBNET_PATH_MAX);
  84. /* allocate read buffer */
  85. buffer = (char*) wn_malloc (length);
  86. if (path == RT_NULL || buffer == RT_NULL)
  87. {
  88. session->request->result_code = 500;
  89. goto __exit;
  90. }
  91. /* write page header */
  92. webnet_session_set_header(session, "text/html", 200, "OK", -1);
  93. /* read file to buffer */
  94. if (read(fd, buffer, length) != length) /* read failed */
  95. {
  96. session->request->result_code = 500;
  97. close(fd);
  98. goto __exit;
  99. }
  100. /* close file */
  101. close(fd);
  102. offset = buffer;
  103. end = buffer + length;
  104. while (offset < end)
  105. {
  106. /* get beginning of ssi */
  107. ssi_begin = strstr(offset, SSI_INCLUDE_STRING);
  108. if (ssi_begin == RT_NULL)
  109. {
  110. /* write content directly */
  111. webnet_session_write(session, (const rt_uint8_t*)offset, end - offset);
  112. break;
  113. }
  114. /* get end of ssi */
  115. ssi_end = strstr(ssi_begin, "\" -->");
  116. if (ssi_end == RT_NULL)
  117. {
  118. /* write content directly */
  119. webnet_session_write(session, (const rt_uint8_t*)offset, end - offset);
  120. break;
  121. }
  122. else
  123. {
  124. char *include_begin, *include_end;
  125. char *filename;
  126. /* write content */
  127. webnet_session_write(session, (const rt_uint8_t*)offset, ssi_begin - offset);
  128. offset = ssi_begin + sizeof(SSI_INCLUDE_STRING) - 1;
  129. include_begin = strstr(ssi_begin, SSI_VIRTUAL_STRING);
  130. if (include_begin != RT_NULL)
  131. {
  132. filename = include_begin + sizeof(SSI_VIRTUAL_STRING) - 1;
  133. include_end = strstr(filename, "\"");
  134. *include_end = '\0';
  135. if (webnet_session_get_physical_path(session, filename, path) == 0)
  136. {
  137. _webnet_ssi_sendfile(session, path);
  138. }
  139. }
  140. else
  141. {
  142. include_begin = strstr(ssi_begin, SSI_FILE_STRING);
  143. if (include_begin != RT_NULL)
  144. {
  145. filename = include_begin + sizeof(SSI_FILE_STRING) - 1;
  146. include_end = strstr(filename, "\"");
  147. *include_end = '\0';
  148. _webnet_ssi_sendfile(session, filename);
  149. }
  150. }
  151. offset = ssi_end + sizeof(SSI_END_STRING) - 1;
  152. }
  153. }
  154. /* exit and release buffer buffer */
  155. __exit:
  156. if (path != RT_NULL) wn_free(path);
  157. if (buffer != RT_NULL) wn_free(buffer);
  158. }
  159. static const char* ssi_extension[] =
  160. {
  161. ".shtm",
  162. ".SHTM",
  163. ".shtml",
  164. ".SHTML",
  165. ".stm",
  166. ".STM",
  167. RT_NULL
  168. };
  169. int webnet_module_ssi(struct webnet_session* session, int event)
  170. {
  171. struct webnet_request* request;
  172. /* check parameter */
  173. RT_ASSERT(session != RT_NULL);
  174. request = session->request;
  175. RT_ASSERT(request != RT_NULL);
  176. if (event == WEBNET_EVENT_URI_POST)
  177. {
  178. int fd;
  179. int index;
  180. /* check whether a ssi file */
  181. index = 0;
  182. while (ssi_extension[index] != RT_NULL)
  183. {
  184. if (strstr(request->path, ssi_extension[index]) != RT_NULL)
  185. {
  186. /* try to open this file */
  187. fd = open(request->path, O_RDONLY, 0);
  188. if ( fd >= 0)
  189. {
  190. _webnet_ssi_dofile(session, fd);
  191. close(fd);
  192. return WEBNET_MODULE_FINISHED;
  193. }
  194. else
  195. {
  196. /* no this file */
  197. request->result_code = 404;
  198. return WEBNET_MODULE_FINISHED;
  199. }
  200. }
  201. index ++;
  202. }
  203. /* no this file, try index.shtm */
  204. {
  205. char *ssi_filename;
  206. ssi_filename = (char*) wn_malloc (WEBNET_PATH_MAX);
  207. if (ssi_filename != RT_NULL)
  208. {
  209. rt_snprintf(ssi_filename, WEBNET_PATH_MAX, "%s/index.shtm", request->path);
  210. fd = open(ssi_filename, O_RDONLY, 0);
  211. if (fd >= 0)
  212. {
  213. wn_free(ssi_filename);
  214. _webnet_ssi_dofile(session, fd);
  215. close(fd);
  216. return WEBNET_MODULE_FINISHED;
  217. }
  218. }
  219. wn_free(ssi_filename);
  220. }
  221. }
  222. return WEBNET_MODULE_CONTINUE;
  223. }
  224. #endif