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
send_page(struct MHD_Connection * connection,const char * page)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
iterate_post(void * coninfo_cls,enum MHD_ValueKind kind,const char * key,const char * filename,const char * content_type,const char * transfer_encoding,const char * data,uint64_t off,size_t size)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
request_completed(void * cls,struct MHD_Connection * connection,void ** con_cls,enum MHD_RequestTerminationCode toe)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
answer_to_connection(void * cls,struct MHD_Connection * connection,const char * url,const char * method,const char * version,const char * upload_data,size_t * upload_data_size,void ** con_cls)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
main()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