ssi_example.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /**
  2. * @file
  3. * HTTPD simple SSI example
  4. *
  5. * This file demonstrates how to add support for SSI.
  6. * It does this in a very simple way by providing the three tags 'HelloWorld'
  7. * 'counter', and 'MultiPart'.
  8. *
  9. * This file also demonstrates how to integrate CGI with SSI.
  10. */
  11. /*
  12. * Copyright (c) 2017 Simon Goldschmidt
  13. * All rights reserved.
  14. *
  15. * Redistribution and use in source and binary forms, with or without modification,
  16. * are permitted provided that the following conditions are met:
  17. *
  18. * 1. Redistributions of source code must retain the above copyright notice,
  19. * this list of conditions and the following disclaimer.
  20. * 2. Redistributions in binary form must reproduce the above copyright notice,
  21. * this list of conditions and the following disclaimer in the documentation
  22. * and/or other materials provided with the distribution.
  23. * 3. The name of the author may not be used to endorse or promote products
  24. * derived from this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  27. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  28. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  29. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  30. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  31. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  32. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  33. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  34. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  35. * OF SUCH DAMAGE.
  36. *
  37. * This file is part of the lwIP TCP/IP stack.
  38. *
  39. * Author: Simon Goldschmidt <goldsimon@gmx.de>
  40. *
  41. */
  42. #include "lwip/opt.h"
  43. #include "ssi_example.h"
  44. #include "lwip/apps/httpd.h"
  45. #include "lwip/def.h"
  46. #include "lwip/mem.h"
  47. #include <stdio.h>
  48. #include <string.h>
  49. /** define LWIP_HTTPD_EXAMPLE_SSI_SIMPLE to 1 to enable this ssi example*/
  50. #ifndef LWIP_HTTPD_EXAMPLE_SSI_SIMPLE
  51. #define LWIP_HTTPD_EXAMPLE_SSI_SIMPLE 0
  52. #endif
  53. /** define LWIP_HTTPD_EXAMPLE_SSI_SIMPLE_CGI_INTEGRATION to 1 to show how to
  54. * integrate CGI into SSI (LWIP_HTTPD_CGI_SSI) */
  55. #ifndef LWIP_HTTPD_EXAMPLE_SSI_SIMPLE_CGI_INTEGRATION
  56. #define LWIP_HTTPD_EXAMPLE_SSI_SIMPLE_CGI_INTEGRATION 0
  57. #endif
  58. #if LWIP_HTTPD_EXAMPLE_SSI_SIMPLE
  59. #if LWIP_HTTPD_EXAMPLE_SSI_SIMPLE_CGI_INTEGRATION
  60. #if !LWIP_HTTPD_FILE_STATE
  61. #error LWIP_HTTPD_EXAMPLE_SSI_SIMPLE_CGI_INTEGRATION needs LWIP_HTTPD_FILE_STATE
  62. #endif
  63. #if !LWIP_HTTPD_CGI_SSI
  64. #error LWIP_HTTPD_EXAMPLE_SSI_SIMPLE_CGI_INTEGRATION needs LWIP_HTTPD_CGI_SSI
  65. #endif
  66. #define MAX_CGI_LEN 16
  67. #endif
  68. const char * ssi_example_tags[] = {
  69. "HellWorl",
  70. "counter",
  71. "MultPart"
  72. #if LWIP_HTTPD_EXAMPLE_SSI_SIMPLE_CGI_INTEGRATION
  73. ,"CgiParam"
  74. #endif
  75. };
  76. u16_t ssi_example_ssi_handler(
  77. #if LWIP_HTTPD_SSI_RAW
  78. const char* ssi_tag_name,
  79. #else /* LWIP_HTTPD_SSI_RAW */
  80. int iIndex,
  81. #endif /* LWIP_HTTPD_SSI_RAW */
  82. char *pcInsert, int iInsertLen
  83. #if LWIP_HTTPD_SSI_MULTIPART
  84. , u16_t current_tag_part, u16_t *next_tag_part
  85. #endif /* LWIP_HTTPD_SSI_MULTIPART */
  86. #if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE
  87. , void *connection_state
  88. #endif /* LWIP_HTTPD_FILE_STATE */
  89. )
  90. {
  91. size_t printed;
  92. #if LWIP_HTTPD_SSI_RAW
  93. /* a real application could use if(!strcmp) blocks here, but we want to keep
  94. the differences between configurations small, so translate string to index here */
  95. int iIndex;
  96. for (iIndex = 0; iIndex < LWIP_ARRAYSIZE(ssi_example_tags); iIndex++) {
  97. if(!strcmp(ssi_tag_name, ssi_example_tags[iIndex])) {
  98. break;
  99. }
  100. }
  101. #endif
  102. #if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE
  103. LWIP_UNUSED_ARG(connection_state);
  104. #endif
  105. switch (iIndex) {
  106. case 0: /* "HelloWorld" */
  107. printed = snprintf(pcInsert, iInsertLen, "Hello World!");
  108. break;
  109. case 1: /* "counter" */
  110. {
  111. static int counter;
  112. counter++;
  113. printed = snprintf(pcInsert, iInsertLen, "%d", counter);
  114. }
  115. break;
  116. case 2: /* "MultPart" */
  117. #if LWIP_HTTPD_SSI_MULTIPART
  118. switch (current_tag_part) {
  119. case 0:
  120. printed = snprintf(pcInsert, iInsertLen, "part0");
  121. *next_tag_part = 1;
  122. break;
  123. case 1:
  124. printed = snprintf(pcInsert, iInsertLen, "part1");
  125. *next_tag_part = 2;
  126. break;
  127. case 2:
  128. printed = snprintf(pcInsert, iInsertLen, "part2");
  129. break;
  130. default:
  131. printed = snprintf(pcInsert, iInsertLen, "unhandled part: %d", (int)current_tag_part);
  132. break;
  133. }
  134. #else
  135. printed = snprintf(pcInsert, iInsertLen, "LWIP_HTTPD_SSI_MULTIPART disabled");
  136. #endif
  137. break;
  138. #if LWIP_HTTPD_EXAMPLE_SSI_SIMPLE_CGI_INTEGRATION
  139. case 3:
  140. if (connection_state) {
  141. char *params = (char *)connection_state;
  142. if (*params) {
  143. printed = snprintf(pcInsert, iInsertLen, "%s", (char *)params);
  144. } else {
  145. printed = snprintf(pcInsert, iInsertLen, "none");
  146. }
  147. } else {
  148. printed = snprintf(pcInsert, iInsertLen, "NULL");
  149. }
  150. break;
  151. #endif
  152. default: /* unknown tag */
  153. printed = 0;
  154. break;
  155. }
  156. LWIP_ASSERT("sane length", printed <= 0xFFFF);
  157. return (u16_t)printed;
  158. }
  159. void
  160. ssi_ex_init(void)
  161. {
  162. int i;
  163. for (i = 0; i < LWIP_ARRAYSIZE(ssi_example_tags); i++) {
  164. LWIP_ASSERT("tag too long for LWIP_HTTPD_MAX_TAG_NAME_LEN",
  165. strlen(ssi_example_tags[i]) <= LWIP_HTTPD_MAX_TAG_NAME_LEN);
  166. }
  167. http_set_ssi_handler(ssi_example_ssi_handler,
  168. #if LWIP_HTTPD_SSI_RAW
  169. NULL, 0
  170. #else
  171. ssi_example_tags, LWIP_ARRAYSIZE(ssi_example_tags)
  172. #endif
  173. );
  174. }
  175. #if LWIP_HTTPD_EXAMPLE_SSI_SIMPLE_CGI_INTEGRATION
  176. void *
  177. fs_state_init(struct fs_file *file, const char *name)
  178. {
  179. char *ret;
  180. LWIP_UNUSED_ARG(file);
  181. LWIP_UNUSED_ARG(name);
  182. ret = (char *)mem_malloc(MAX_CGI_LEN);
  183. if (ret) {
  184. *ret = 0;
  185. }
  186. return ret;
  187. }
  188. void
  189. fs_state_free(struct fs_file *file, void *state)
  190. {
  191. LWIP_UNUSED_ARG(file);
  192. if (state != NULL) {
  193. mem_free(state);
  194. }
  195. }
  196. void
  197. httpd_cgi_handler(struct fs_file *file, const char* uri, int iNumParams,
  198. char **pcParam, char **pcValue
  199. #if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE
  200. , void *connection_state
  201. #endif /* LWIP_HTTPD_FILE_STATE */
  202. )
  203. {
  204. LWIP_UNUSED_ARG(file);
  205. LWIP_UNUSED_ARG(uri);
  206. if (connection_state != NULL) {
  207. char *start = (char *)connection_state;
  208. char *end = start + MAX_CGI_LEN;
  209. int i;
  210. memset(start, 0, MAX_CGI_LEN);
  211. /* print a string of the arguments: */
  212. for (i = 0; i < iNumParams; i++) {
  213. size_t len;
  214. len = end - start;
  215. if (len) {
  216. size_t inlen = strlen(pcParam[i]);
  217. size_t copylen = LWIP_MIN(inlen, len);
  218. memcpy(start, pcParam[i], copylen);
  219. start += copylen;
  220. len -= copylen;
  221. }
  222. if (len) {
  223. *start = '=';
  224. start++;
  225. len--;
  226. }
  227. if (len) {
  228. size_t inlen = strlen(pcValue[i]);
  229. size_t copylen = LWIP_MIN(inlen, len);
  230. memcpy(start, pcValue[i], copylen);
  231. start += copylen;
  232. len -= copylen;
  233. }
  234. if (len) {
  235. *start = ';';
  236. len--;
  237. }
  238. /* ensure NULL termination */
  239. end--;
  240. *end = 0;
  241. }
  242. }
  243. }
  244. #endif /* LWIP_HTTPD_EXAMPLE_SSI_SIMPLE_CGI_INTEGRATION */
  245. #endif /* LWIP_HTTPD_EXAMPLE_SSI_SIMPLE */