1 /* Feel free to use this example code in any way 2 you see fit (Public Domain) */ 3 4 #include <sys/types.h> 5 #ifndef _WIN32 6 #include <sys/select.h> 7 #include <sys/socket.h> 8 #else 9 #include <winsock2.h> 10 #endif 11 #include <microhttpd.h> 12 #include <stdio.h> 13 #include <string.h> 14 #include <stdlib.h> 15 16 #define PORT 8888 17 #define POSTBUFFERSIZE 512 18 #define MAXNAMESIZE 20 19 #define MAXANSWERSIZE 512 20 21 #define GET 0 22 #define POST 1 23 24 struct connection_info_struct 25 { 26 int connectiontype; 27 char *answerstring; 28 struct MHD_PostProcessor *postprocessor; 29 }; 30 31 const char *askpage = "<html><body>\ 32 What's your name, Sir?<br>\ 33 <form action=\"/namepost\" method=\"post\">\ 34 <input name=\"name\" type=\"text\"\ 35 <input type=\"submit\" value=\" Send \"></form>\ 36 </body></html>"; 37 38 const char *greetingpage = 39 "<html><body><h1>Welcome, %s!</center></h1></body></html>"; 40 41 const char *errorpage = 42 "<html><body>This doesn't seem to be right.</body></html>"; 43 44 45 static int 46 send_page (struct MHD_Connection *connection, const char *page) 47 { 48 int ret; 49 struct MHD_Response *response; 50 51 52 response = 53 MHD_create_response_from_buffer (strlen (page), (void *) page, 54 MHD_RESPMEM_PERSISTENT); 55 if (!response) 56 return MHD_NO; 57 58 ret = MHD_queue_response (connection, MHD_HTTP_OK, response); 59 MHD_destroy_response (response); 60 61 return ret; 62 } 63 64 65 static int 66 iterate_post (void *coninfo_cls, enum MHD_ValueKind kind, const char *key, 67 const char *filename, const char *content_type, 68 const char *transfer_encoding, const char *data, uint64_t off, 69 size_t size) 70 { 71 struct connection_info_struct *con_info = coninfo_cls; 72 73 if (0 == strcmp (key, "name")) 74 { 75 if ((size > 0) && (size <= MAXNAMESIZE)) 76 { 77 char *answerstring; 78 answerstring = malloc (MAXANSWERSIZE); 79 if (!answerstring) 80 return MHD_NO; 81 82 snprintf (answerstring, MAXANSWERSIZE, greetingpage, data); 83 con_info->answerstring = answerstring; 84 } 85 else 86 con_info->answerstring = NULL; 87 88 return MHD_NO; 89 } 90 91 return MHD_YES; 92 } 93 94 static void 95 request_completed (void *cls, struct MHD_Connection *connection, 96 void **con_cls, enum MHD_RequestTerminationCode toe) 97 { 98 struct connection_info_struct *con_info = *con_cls; 99 100 if (NULL == con_info) 101 return; 102 103 if (con_info->connectiontype == POST) 104 { 105 MHD_destroy_post_processor (con_info->postprocessor); 106 if (con_info->answerstring) 107 free (con_info->answerstring); 108 } 109 110 free (con_info); 111 *con_cls = NULL; 112 } 113 114 115 static int 116 answer_to_connection (void *cls, struct MHD_Connection *connection, 117 const char *url, const char *method, 118 const char *version, const char *upload_data, 119 size_t *upload_data_size, void **con_cls) 120 { 121 if (NULL == *con_cls) 122 { 123 struct connection_info_struct *con_info; 124 125 con_info = malloc (sizeof (struct connection_info_struct)); 126 if (NULL == con_info) 127 return MHD_NO; 128 con_info->answerstring = NULL; 129 130 if (0 == strcmp (method, "POST")) 131 { 132 con_info->postprocessor = 133 MHD_create_post_processor (connection, POSTBUFFERSIZE, 134 iterate_post, (void *) con_info); 135 136 if (NULL == con_info->postprocessor) 137 { 138 free (con_info); 139 return MHD_NO; 140 } 141 142 con_info->connectiontype = POST; 143 } 144 else 145 con_info->connectiontype = GET; 146 147 *con_cls = (void *) con_info; 148 149 return MHD_YES; 150 } 151 152 if (0 == strcmp (method, "GET")) 153 { 154 return send_page (connection, askpage); 155 } 156 157 if (0 == strcmp (method, "POST")) 158 { 159 struct connection_info_struct *con_info = *con_cls; 160 161 if (*upload_data_size != 0) 162 { 163 MHD_post_process (con_info->postprocessor, upload_data, 164 *upload_data_size); 165 *upload_data_size = 0; 166 167 return MHD_YES; 168 } 169 else if (NULL != con_info->answerstring) 170 return send_page (connection, con_info->answerstring); 171 } 172 173 return send_page (connection, errorpage); 174 } 175 176 int 177 main () 178 { 179 struct MHD_Daemon *daemon; 180 181 daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL, 182 &answer_to_connection, NULL, 183 MHD_OPTION_NOTIFY_COMPLETED, request_completed, 184 NULL, MHD_OPTION_END); 185 if (NULL == daemon) 186 return 1; 187 188 (void) getchar (); 189 190 MHD_stop_daemon (daemon); 191 192 return 0; 193 } 194