handle_form.inl 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /* Copyright (c) 2016 the Civetweb developers
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to deal
  5. * in the Software without restriction, including without limitation the rights
  6. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. * copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. * THE SOFTWARE.
  20. */
  21. /********************/
  22. /* EXPERIMENTAL !!! */
  23. /********************/
  24. #ifdef USE_EXPERIMENTAL
  25. void
  26. mirror_body___dev_helper(struct mg_connection *conn)
  27. {
  28. /* TODO: remove this function when handle_form_data is completed. */
  29. char buf[256];
  30. int r;
  31. mg_printf(conn, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n");
  32. do {
  33. r = mg_read(conn, buf, sizeof(buf));
  34. mg_write(conn, buf, r);
  35. } while (r > 0);
  36. }
  37. struct mg_form_data_handler {
  38. int (*field_found)(const char *key,
  39. size_t keylen,
  40. const char *value,
  41. size_t vallen,
  42. void *user_data);
  43. int (*file_found)(const char *key,
  44. size_t keylen,
  45. const char *filename,
  46. int *disposition,
  47. void *user_data);
  48. void *user_data;
  49. };
  50. int
  51. mg_handle_form_data(struct mg_connection *conn,
  52. struct mg_form_data_handler *fdh)
  53. {
  54. const char *content_type;
  55. const char *boundary;
  56. const char *data;
  57. int has_body_data =
  58. (conn->request_info.content_length > 0) || (conn->is_chunked);
  59. /* There are three ways to encode data from a HTML form:
  60. * 1) method: GET (default)
  61. * The form data is in the HTTP query string.
  62. * 2) method: POST, enctype: "application/x-www-form-urlencoded"
  63. * The form data is in the request body.
  64. * The body is url encoded (the default encoding for POST).
  65. * 3) method: POST, enctype: "multipart/form-data".
  66. * The form data is in the request body of a multipart message.
  67. * This is the typical way to handle file upload from a form.
  68. */
  69. if (!has_body_data) {
  70. if (strcmp(conn->request_info.request_method, "GET")) {
  71. /* No body data, but not a GET request.
  72. * This is not a valid form request. */
  73. return 0;
  74. }
  75. /* GET request: form data is in the query string. */
  76. data = conn->request_info.query_string;
  77. if (!data) {
  78. /* No query string. */
  79. return 0;
  80. }
  81. /* Split data in a=1&b&c=3&c=4 ... */
  82. while (*data) {
  83. const char *val = strchr(data, '=');
  84. const char *next;
  85. ptrdiff_t keylen, vallen;
  86. if (!val) {
  87. break;
  88. }
  89. keylen = val - data;
  90. val++;
  91. next = strchr(val, '&');
  92. if (next) {
  93. vallen = next - val;
  94. next++;
  95. } else {
  96. vallen = strlen(val);
  97. }
  98. /* Call callback */
  99. fdh->field_found(
  100. data, (size_t)keylen, val, (size_t)vallen, fdh->user_data);
  101. /* Proceed to next entry */
  102. data = val + vallen;
  103. }
  104. return 0;
  105. }
  106. content_type = mg_get_header(conn, "Content-Type");
  107. if (!content_type
  108. || !mg_strcasecmp(content_type, "APPLICATION/X-WWW-FORM-URLENCODED")) {
  109. /* The form data is in the request body data, encoded in key/value
  110. * pairs. */
  111. /* Read body data and split it in a=1&b&c=3&c=4 ... */
  112. /* The encoding is like in the "GET" case above, but here we read data
  113. * on the fly */
  114. char buf[/*10*/ 24];
  115. int buf_fill = 0;
  116. buf_fill = mg_read(conn, buf, sizeof(buf) - 1);
  117. if (buf_fill <= 0) {
  118. /* No data available */
  119. return 0;
  120. }
  121. buf[buf_fill] = 0;
  122. data = buf;
  123. while (*data) {
  124. const char *val = strchr(data, '=');
  125. const char *next;
  126. ptrdiff_t keylen, vallen;
  127. if (!val) {
  128. size_t used = data - buf;
  129. char *tgt = buf + sizeof(buf) - used;
  130. /* Drop used data (used = data - buf) */
  131. memmove(buf, data, used);
  132. buf_fill -= used;
  133. buf_fill += mg_read(conn, tgt, used);
  134. buf[sizeof(buf) - 1] = 0;
  135. val = strchr(data, '=');
  136. if (!val) {
  137. break;
  138. }
  139. }
  140. keylen = val - data;
  141. val++;
  142. next = strchr(val, '&');
  143. if (next) {
  144. vallen = next - val;
  145. next++;
  146. } else {
  147. vallen = strlen(val);
  148. }
  149. /* Call callback */
  150. fdh->field_found(
  151. data, (size_t)keylen, val, (size_t)vallen, fdh->user_data);
  152. /* Proceed to next entry */
  153. data = val + vallen;
  154. }
  155. return 0;
  156. }
  157. mirror_body___dev_helper(conn);
  158. if (!mg_strncasecmp(content_type, "MULTIPART/FORM-DATA;", 20)) {
  159. /* The form data is in the request body data, encoded as multipart
  160. * content. */
  161. /* There has to be a BOUNDARY definition in the Content-Type header */
  162. if (!mg_strncasecmp(content_type + 20, "BOUNDARY=", 9)) {
  163. /* Malformed request */
  164. return 0;
  165. }
  166. /* TODO: handle multipart request */
  167. return 0;
  168. }
  169. /* Unknown Content-Type */
  170. return 0;
  171. }
  172. #endif