|
2250
|
1 /* ================================================================= |
|
|
2 * |
|
|
3 * http.c |
|
|
4 * |
|
|
5 * Handles the client requests. |
|
|
6 * |
|
|
7 * ================================================================= |
|
|
8 * ####ECOSGPLCOPYRIGHTBEGIN#### |
|
|
9 * ------------------------------------------- |
|
|
10 * This file is part of eCos, the Embedded Configurable Operating |
|
|
11 * System. |
|
|
12 * Copyright (C) 2005 eCosCentric Ltd. |
|
|
13 * |
|
|
14 * eCos is free software; you can redistribute it and/or modify it |
|
|
15 * under the terms of the GNU General Public License as published by |
|
|
16 * the Free Software Foundation; either version 2 or (at your option) |
|
|
17 * any later version. |
|
|
18 * |
|
|
19 * eCos is distributed in the hope that it will be useful, but |
|
|
20 * WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
|
22 * General Public License for more details. |
|
|
23 * |
|
|
24 * You should have received a copy of the GNU General Public License |
|
|
25 * along with eCos; if not, write to the Free Software Foundation, |
|
|
26 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
|
|
27 * |
|
|
28 * As a special exception, if other files instantiate templates or |
|
|
29 * use macros or inline functions from this file, or you compile this |
|
|
30 * file and link it with other works to produce a work based on this |
|
|
31 * file, this file does not by itself cause the resulting work to be |
|
|
32 * covered by the GNU General Public License. However the source code |
|
|
33 * for this file must still be made available in accordance with |
|
|
34 * section (3) of the GNU General Public License. |
|
|
35 * |
|
|
36 * This exception does not invalidate any other reasons why a work |
|
|
37 * based on this file might be covered by the GNU General Public |
|
|
38 * License. |
|
|
39 * |
|
|
40 * ------------------------------------------- |
|
|
41 * ####ECOSGPLCOPYRIGHTEND#### |
|
|
42 * ================================================================= |
|
|
43 * #####DESCRIPTIONBEGIN#### |
|
|
44 * |
|
|
45 * Author(s): Anthony Tonizzo (atonizzo@gmail.com) |
|
2265
|
46 * Contributors: Sergei Gavrikov (w3sg@SoftHome.net) |
|
2250
|
47 * Date: 2006-06-12 |
|
|
48 * Purpose: |
|
|
49 * Description: |
|
|
50 * |
|
|
51 * ####DESCRIPTIONEND#### |
|
|
52 * |
|
|
53 * ================================================================= |
|
|
54 */ |
|
|
55 |
|
|
56 #include <pkgconf/hal.h> |
|
|
57 #include <pkgconf/kernel.h> |
|
|
58 #include <cyg/kernel/kapi.h> // Kernel API. |
|
|
59 #include <cyg/infra/diag.h> // For diagnostic printing. |
|
|
60 #include <network.h> |
|
|
61 #include <time.h> |
|
|
62 |
|
|
63 #include <cyg/hal/hal_tables.h> |
|
|
64 #include <cyg/fileio/fileio.h> |
|
|
65 #include <stdio.h> // sprintf(). |
|
|
66 #include <stdlib.h> |
|
|
67 |
|
|
68 #ifdef CYGOPT_NET_ATHTTPD_USE_CGIBIN_OBJLOADER |
|
|
69 #include <cyg/objloader/elf.h> |
|
|
70 #include <cyg/objloader/objelf.h> |
|
|
71 #endif |
|
|
72 |
|
|
73 #include <cyg/athttpd/http.h> |
|
|
74 #include <cyg/athttpd/socket.h> |
|
|
75 #include <cyg/athttpd/handler.h> |
|
|
76 #include <cyg/athttpd/forms.h> |
|
|
77 |
|
|
78 cyg_int32 debug_print = 0; |
|
|
79 |
|
|
80 const char *day_of_week[7] = { "Sun", "Mon", "Tue", "Wed", |
|
|
81 "Thu", "Fri", "Sat" }; |
|
|
82 const char *month_of_year[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", |
|
|
83 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; |
|
|
84 const char *home_pages[] = { "index.html", "index.htm", |
|
|
85 "default.html", "home.html" }; |
|
|
86 CYG_HAL_TABLE_BEGIN(cyg_httpd_mime_table, httpd_mime_table); |
|
|
87 CYG_HAL_TABLE_END(cyg_httpd_mime_table_end, httpd_mime_table); |
|
|
88 |
|
|
89 __externC cyg_httpd_mime_table_entry cyg_httpd_mime_table[]; |
|
|
90 __externC cyg_httpd_mime_table_entry cyg_httpd_mime_table_end[]; |
|
|
91 |
|
|
92 // Standard handlers added by default. Correspond to the most used extensions. |
|
|
93 // The user can add his/her own later. |
|
|
94 CYG_HTTPD_MIME_TABLE_ENTRY(hal_htm_entry, "htm", |
|
|
95 "text/html; charset=iso-8859-1"); |
|
|
96 CYG_HTTPD_MIME_TABLE_ENTRY(hal_html_entry, "html", |
|
|
97 "text/html; charset=iso-8859-1"); |
|
|
98 CYG_HTTPD_MIME_TABLE_ENTRY(hal_gif_entry, "gif", "image/gif"); |
|
|
99 CYG_HTTPD_MIME_TABLE_ENTRY(hal_jpg_entry, "jpg", "image/jpg"); |
|
|
100 CYG_HTTPD_MIME_TABLE_ENTRY(hal_css_entry, "css", "text/css"); |
|
|
101 CYG_HTTPD_MIME_TABLE_ENTRY(hal_js_entry, "js", "application/x-javascript"); |
|
|
102 |
|
|
103 void |
|
|
104 cyg_httpd_format_time_string(char *ptr, time_t *t) |
|
|
105 { |
|
|
106 struct tm *gmt_time = gmtime(t); |
|
|
107 if (gmt_time != NULL) |
|
|
108 sprintf(ptr, |
|
|
109 "%s, %02d %s %d %02d:%02d:%02d GMT", |
|
|
110 day_of_week[gmt_time->tm_wday], |
|
|
111 gmt_time->tm_mday, |
|
|
112 month_of_year[gmt_time->tm_mon], |
|
|
113 1900 + gmt_time->tm_year, |
|
|
114 gmt_time->tm_hour, |
|
|
115 gmt_time->tm_min, |
|
|
116 gmt_time->tm_sec); |
|
|
117 else |
|
|
118 // If anything fails, then we'll just create a bogus date. |
|
|
119 sprintf(ptr, "Thu, 01 Jan 1970 00:00:01 GMT"); |
|
|
120 } |
|
|
121 |
|
|
122 void |
|
|
123 cyg_httpd_send_error(cyg_int32 err_type) |
|
|
124 { |
|
|
125 httpstate.status_code = err_type; |
|
|
126 |
|
|
127 #if CYGOPT_NET_ATHTTPD_DEBUG_LEVEL > 1 |
|
|
128 diag_printf("Sending error: %d\n", err_type); |
|
|
129 #endif |
|
|
130 |
|
|
131 #ifdef CYGOPT_NET_ATHTTPD_USE_FS |
|
|
132 // Check if the user has defines his own error pages. |
|
|
133 struct stat sp; |
|
|
134 char file_name[CYG_HTTPD_MAXPATH]; |
|
|
135 strcpy(file_name, CYGDAT_NET_ATHTTPD_SERVEROPT_ROOTDIR); |
|
|
136 if (file_name[strlen(file_name)-1] != '/') |
|
|
137 strcat(file_name, "/"); |
|
|
138 strcat(file_name, CYGDAT_NET_ATHTTPD_SERVEROPT_ERRORDIR); |
|
|
139 if (file_name[strlen(file_name)-1] != '/') |
|
|
140 strcat(file_name, "/"); |
|
|
141 sprintf(file_name + strlen(file_name), "error_%d.html", err_type); |
|
|
142 cyg_httpd_cleanup_filename(file_name); |
|
|
143 cyg_int32 rc = stat(file_name, &sp); |
|
|
144 if (rc == 0) |
|
|
145 { |
|
|
146 char *extension = rindex(file_name, '.'); |
|
|
147 if (extension == NULL) |
|
|
148 // No extension in the file name. |
|
|
149 httpstate.mime_type = 0; |
|
|
150 else |
|
|
151 httpstate.mime_type = cyg_httpd_find_mime_string(++extension); |
|
|
152 |
|
|
153 httpstate.payload_len = sp.st_size; |
|
|
154 cyg_int32 header_length = cyg_httpd_format_header(); |
|
|
155 cyg_httpd_write(httpstate.outbuffer, header_length); |
|
|
156 |
|
|
157 // File found. |
|
|
158 FILE *fp = fopen(file_name, "r"); |
|
|
159 if(fp == NULL) |
|
|
160 return; |
|
|
161 |
|
2265
|
162 ssize_t payload_size = fread(httpstate.outbuffer, |
|
|
163 1, |
|
|
164 CYG_HTTPD_MAXOUTBUFFER, |
|
|
165 fp); |
|
2250
|
166 while (payload_size > 0) |
|
|
167 { |
|
|
168 ssize_t bytes_written = cyg_httpd_write_chunked(httpstate.outbuffer, |
|
|
169 payload_size); |
|
|
170 if (bytes_written != payload_size) |
|
|
171 break; |
|
|
172 |
|
|
173 payload_size = fread(httpstate.outbuffer, |
|
|
174 1, |
|
|
175 CYG_HTTPD_MAXOUTBUFFER, |
|
|
176 fp); |
|
|
177 } |
|
|
178 |
|
|
179 fclose(fp); |
|
|
180 return; |
|
|
181 } |
|
|
182 #endif |
|
|
183 |
|
|
184 // If no file has been defined, send a simple notification. We use inbuffer |
|
|
185 // for temporary storage of the error messages, so that we know the length |
|
|
186 // of the frame prior to building the header, thus avoiding the use of |
|
|
187 // chunked frames. |
|
|
188 strcpy(httpstate.inbuffer, |
|
|
189 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"); |
|
|
190 switch (err_type) |
|
|
191 { |
|
|
192 case CYG_HTTPD_STATUS_MOVED_PERMANENTLY: |
|
|
193 strcat(httpstate.inbuffer, |
|
|
194 "<html><head><title>301 Moved Permanently</title></head>\r\n" |
|
|
195 "<body><h1>Moved Permanently</h1>\r\n" |
|
|
196 "<p>The documenthas moved <a href=\"" ); |
|
|
197 strcat(httpstate.inbuffer, httpstate.url); |
|
|
198 strcat(httpstate.inbuffer, "\">here</a>.\r\n"); |
|
|
199 break; |
|
|
200 case CYG_HTTPD_STATUS_NOT_AUTHORIZED: |
|
|
201 strcat(httpstate.inbuffer, |
|
|
202 "<html><head><title>401 Not Authorized</title></head>\r\n"); |
|
|
203 strcat(httpstate.inbuffer, |
|
|
204 "<p>Authorization required to access this URL.</p>"); |
|
|
205 break; |
|
|
206 case CYG_HTTPD_STATUS_NOT_MODIFIED: |
|
|
207 httpstate.mode |= CYG_HTTPD_SEND_HEADER_ONLY; |
|
|
208 break; |
|
|
209 case CYG_HTTPD_STATUS_NOT_FOUND: |
|
|
210 strcat(httpstate.inbuffer, |
|
|
211 "<html><head><title>404 Not Found</title></head>\r\n"); |
|
|
212 sprintf(httpstate.inbuffer + strlen(httpstate.inbuffer), |
|
|
213 "<p>The requested URL: %s was not found on" |
|
|
214 " this server</p>", |
|
|
215 httpstate.url); |
|
|
216 break; |
|
|
217 case CYG_HTTPD_STATUS_SYSTEM_ERROR: |
|
|
218 strcat(httpstate.inbuffer, |
|
|
219 "<html><head><title>500 Server Error</title></head>\r\n"); |
|
|
220 strcat(httpstate.inbuffer, |
|
|
221 "<p>The server encountered an unexpected condition that " |
|
|
222 "prevented it from fulfilling the request by the client</p>"); |
|
|
223 break; |
|
|
224 case CYG_HTTPD_STATUS_NOT_IMPLEMENTED: |
|
|
225 strcat(httpstate.inbuffer, |
|
|
226 "<html><head><title>501 Not Implemented</title></head>\r\n"); |
|
|
227 strcat(httpstate.inbuffer, |
|
|
228 "<p>The method requested is not implemented</p>"); |
|
|
229 break; |
|
|
230 default: |
|
|
231 strcat(httpstate.inbuffer, |
|
|
232 "<html><head><title>400 Bad Request</title></head>\r\n"); |
|
|
233 strcat(httpstate.inbuffer, |
|
|
234 "<p>Bad request</p>"); |
|
|
235 break; |
|
|
236 } |
|
|
237 |
|
|
238 sprintf(httpstate.inbuffer + strlen(httpstate.inbuffer), |
|
|
239 "</p><hr><address>%s at %d.%d.%d.%d Port %d</address>\r\n" |
|
|
240 "</body></html>\r\n", |
|
|
241 CYGDAT_NET_ATHTTPD_SERVEROPT_SERVERID, |
|
|
242 httpstate.host[0], |
|
|
243 httpstate.host[1], |
|
|
244 httpstate.host[2], |
|
|
245 httpstate.host[3], |
|
|
246 CYGNUM_NET_ATHTTPD_SERVEROPT_PORT); |
|
|
247 |
|
|
248 httpstate.last_modified = -1; |
|
|
249 httpstate.mime_type = cyg_httpd_find_mime_string("html"); |
|
|
250 httpstate.mode |= CYG_HTTPD_MODE_CLOSE_CONN; |
|
|
251 httpstate.payload_len = strlen(httpstate.inbuffer); |
|
|
252 cyg_int32 header_length = cyg_httpd_format_header(); |
|
|
253 cyg_httpd_write(httpstate.outbuffer, header_length); |
|
|
254 if (httpstate.mode & CYG_HTTPD_SEND_HEADER_ONLY) |
|
|
255 return; |
|
|
256 cyg_httpd_write(httpstate.inbuffer, strlen(httpstate.inbuffer)); |
|
|
257 } |
|
|
258 |
|
|
259 time_t |
|
|
260 cyg_httpd_parse_date(char *time) |
|
|
261 { |
|
|
262 int i; |
|
|
263 char month[4]; |
|
|
264 struct tm tm_mod; |
|
|
265 |
|
2265
|
266 // We are going to get rid of the day of the week. This is always the first |
|
2250
|
267 // part of the string, separated by a blank. |
|
|
268 time = strchr( time, ' ' ); |
|
|
269 if ( time == NULL ) |
|
|
270 return 0; |
|
|
271 time++; |
|
|
272 |
|
|
273 /// RFC1123. The date is in the format: Sun, 06 Nov 1994 08:49:37 GMT. |
|
|
274 cyg_int32 rc = sscanf(time, |
|
|
275 "%2d %3s %4d %2d:%2d:%2d GMT", |
|
|
276 &tm_mod.tm_mday, |
|
|
277 month, |
|
|
278 &tm_mod.tm_year, |
|
|
279 &tm_mod.tm_hour, |
|
|
280 &tm_mod.tm_min, |
|
|
281 &tm_mod.tm_sec); |
|
|
282 if (rc != 6) |
|
|
283 { |
|
|
284 // RFC1036. The date is in the format: Sunday, 06-Nov-94 08:49:37 GMT. |
|
|
285 rc = sscanf(time, |
|
|
286 "%2d-%3s-%2d %2d:%2d:%2d GMT", |
|
|
287 &tm_mod.tm_mday, |
|
|
288 month, |
|
|
289 &tm_mod.tm_year, |
|
|
290 &tm_mod.tm_hour, |
|
|
291 &tm_mod.tm_min, |
|
|
292 &tm_mod.tm_sec); |
|
|
293 if (rc != 6) |
|
|
294 { |
|
|
295 // asctime() in the stdlibc library. |
|
|
296 // The date is in the format: Sun Nov 6 08:49:37 1994. |
|
|
297 rc = sscanf(time,"%3s %2d %2d:%2d:%2d %4d", |
|
|
298 month, |
|
|
299 &tm_mod.tm_mday, |
|
|
300 &tm_mod.tm_hour, |
|
|
301 &tm_mod.tm_min, |
|
|
302 &tm_mod.tm_sec, |
|
|
303 &tm_mod.tm_year); |
|
|
304 if (rc != 6) |
|
|
305 return 0; |
|
|
306 } |
|
|
307 } |
|
|
308 |
|
|
309 for (i = 0; i < sizeof(month_of_year); i++) |
|
|
310 if (strcmp(month, month_of_year[i]) == 0) |
|
|
311 { |
|
|
312 tm_mod.tm_mon = i; |
|
|
313 if (tm_mod.tm_year > 1900) |
|
|
314 tm_mod.tm_year -= 1900; |
|
|
315 return mktime(&tm_mod); |
|
|
316 } |
|
|
317 |
|
|
318 return 0; |
|
|
319 } |
|
|
320 |
|
|
321 // Finds the mime string into the mime_table associated with a specific |
|
|
322 // extension. Returns the MIME type to send in the header, or NULL if the |
|
2265
|
323 // extension is not in the table. |
|
2250
|
324 char* |
|
2265
|
325 cyg_httpd_find_mime_string(char *ext) |
|
2250
|
326 { |
|
|
327 cyg_httpd_mime_table_entry *entry = cyg_httpd_mime_table; |
|
|
328 |
|
|
329 while (entry != cyg_httpd_mime_table_end) |
|
|
330 { |
|
2265
|
331 if (!strcmp((const char*)ext, entry->extension )) |
|
2250
|
332 return entry->mime_string; |
|
|
333 entry++; |
|
|
334 } |
|
|
335 |
|
|
336 return (char*)0; |
|
|
337 } |
|
|
338 |
|
|
339 void |
|
|
340 cyg_httpd_cleanup_filename(char *filename) |
|
|
341 { |
|
|
342 char *src = filename; |
|
|
343 |
|
|
344 src = strstr(filename, "//"); |
|
|
345 while (src != 0) |
|
|
346 { |
|
|
347 strcpy(src + 1, src + 2); |
|
|
348 src = strstr(filename, "//"); |
|
|
349 } |
|
|
350 |
|
|
351 src = strstr(filename, "/./"); |
|
|
352 while (src != 0) |
|
|
353 { |
|
|
354 strcpy(src + 1, src + 3); |
|
|
355 src = strstr(filename, "/./"); |
|
|
356 } |
|
|
357 |
|
|
358 src = strstr(filename, "/../"); |
|
|
359 while (src != 0) |
|
|
360 { |
|
|
361 char *comp1 = filename, *comp2 = filename; |
|
|
362 |
|
|
363 // Search the path component before this redirection. |
|
|
364 while ((comp1 = strchr(comp1, '/')) != src) |
|
|
365 comp2 = ++comp1; |
|
|
366 |
|
|
367 strcpy(comp2, src + 4); |
|
|
368 src = strstr(filename, "/../"); |
|
|
369 } |
|
|
370 } |
|
|
371 |
|
|
372 cyg_int32 |
|
|
373 cyg_httpd_initialize(void) |
|
|
374 { |
|
|
375 httpstate.needs_auth = (cyg_httpd_auth_table_entry *)0; |
|
|
376 return 0; |
|
|
377 } |
|
|
378 |
|
|
379 void |
|
|
380 cyg_httpd_append_homepage(char *root) |
|
|
381 { |
|
|
382 #ifdef CYGOPT_NET_ATHTTPD_USE_FS |
|
|
383 struct stat sp; |
|
|
384 cyg_int32 i; |
|
|
385 |
|
|
386 cyg_int32 root_len = strlen(root); |
|
|
387 for (i = 0; i < sizeof(home_pages)/sizeof(char*); i++) |
|
|
388 { |
|
|
389 root[root_len] = '\0'; |
|
|
390 sprintf(root + root_len, "%s", home_pages[i]); |
|
|
391 cyg_int32 rc = stat(root, &sp); |
|
|
392 if (rc == 0) |
|
|
393 return; |
|
|
394 } |
|
|
395 root[root_len] = 0; |
|
|
396 #endif |
|
|
397 |
|
|
398 #ifdef CYGDAT_NET_ATHTTPD_ALTERNATE_HOME |
|
|
399 if (strcmp(root, "/") == 0) |
|
|
400 // The client is trying to open the main index file. |
|
|
401 strcat(root, CYGDAT_NET_ATHTTPD_ALTERNATE_HOME); |
|
|
402 #endif |
|
|
403 } |
|
|
404 |
|
|
405 #ifdef CYGOPT_NET_ATHTTPD_USE_FS |
|
|
406 void |
|
|
407 cyg_httpd_send_file(char *name) |
|
|
408 { |
|
|
409 cyg_int32 err; |
|
|
410 FILE *fp; |
|
|
411 struct stat sp; |
|
|
412 char file_name[CYG_HTTPD_MAXPATH]; |
|
|
413 |
|
|
414 #if CYGOPT_NET_ATHTTPD_DEBUG_LEVEL > 1 |
|
|
415 diag_printf("Sending file: %s\n", name); |
|
|
416 #endif |
|
|
417 #ifdef CYGOPT_NET_ATHTTPD_USE_AUTH |
|
|
418 // Let's check that the requested URL is not inside some directory that |
|
|
419 // needs authentication. |
|
|
420 cyg_httpd_auth_table_entry* auth = cyg_httpd_is_authenticated(name); |
|
|
421 if (auth != 0) |
|
|
422 { |
|
|
423 cyg_httpd_send_error(CYG_HTTPD_STATUS_NOT_AUTHORIZED); |
|
|
424 return; |
|
|
425 } |
|
|
426 #endif |
|
|
427 |
|
|
428 strcpy(file_name, CYGDAT_NET_ATHTTPD_SERVEROPT_ROOTDIR); |
|
|
429 if (file_name[strlen(file_name)-1] != '/') |
|
|
430 strcat(file_name, "/"); |
|
|
431 strcat(file_name, name); |
|
|
432 cyg_httpd_cleanup_filename(file_name); |
|
|
433 |
|
|
434 // Check if the file is in the file system. This will also give us the |
|
|
435 // size of the file, to be used in the HTTP header. |
|
|
436 cyg_int32 rc = stat(file_name, &sp); |
|
|
437 if (rc < 0) |
|
|
438 { |
|
|
439 // Before giving up, we make a last ditch attempt at finding a file |
|
|
440 // within the internal resources of the server. The user can add |
|
|
441 // his/her own files to the table. |
|
|
442 cyg_httpd_ires_table_entry *p = cyg_httpd_find_ires(name); |
|
|
443 if (p != NULL) |
|
|
444 { |
|
|
445 #if CYGOPT_NET_ATHTTPD_DEBUG_LEVEL > 1 |
|
|
446 diag_printf("Sending Internal Resource: %s\n", name); |
|
|
447 #endif |
|
|
448 cyg_httpd_send_ires(p); |
|
|
449 } |
|
|
450 else |
|
|
451 cyg_httpd_send_error(CYG_HTTPD_STATUS_NOT_FOUND); |
|
|
452 return; |
|
|
453 } |
|
|
454 |
|
|
455 if (S_ISDIR(sp.st_mode)) |
|
|
456 { |
|
|
457 char tmp_url[CYG_HTTPD_MAXURL]; |
|
|
458 strcpy(tmp_url, httpstate.url); |
|
|
459 // Directories need a trialing slash, and if missing, we'll redirect |
|
|
460 // the client to the right URL. This is called (appropriately |
|
|
461 // enough) "Trailing-Slash Redirection". |
|
|
462 if (name[strlen(name)-1] != '/') |
|
|
463 { |
|
|
464 if (CYGNUM_NET_ATHTTPD_SERVEROPT_PORT == 80) |
|
|
465 sprintf(httpstate.url, |
|
|
466 "http://%d.%d.%d.%d%s/", |
|
|
467 httpstate.host[0], |
|
|
468 httpstate.host[1], |
|
|
469 httpstate.host[2], |
|
|
470 httpstate.host[3], |
|
|
471 tmp_url); |
|
|
472 else |
|
|
473 sprintf(httpstate.url, |
|
|
474 "http://%d.%d.%d.%d:%d%s/", |
|
|
475 httpstate.host[0], |
|
|
476 httpstate.host[1], |
|
|
477 httpstate.host[2], |
|
|
478 httpstate.host[3], |
|
|
479 CYGNUM_NET_ATHTTPD_SERVEROPT_PORT, |
|
|
480 tmp_url); |
|
|
481 cyg_httpd_send_error(CYG_HTTPD_STATUS_MOVED_PERMANENTLY); |
|
|
482 return; |
|
|
483 } |
|
|
484 |
|
2265
|
485 // We are going to try to locate an index page in the directory we got |
|
|
486 // in the URL. |
|
2250
|
487 cyg_httpd_append_homepage(file_name); |
|
|
488 if (file_name[strlen(file_name)-1] == '/') |
|
|
489 { |
|
|
490 #ifdef CYGOPT_NET_ATHTTPD_USE_DIRLIST |
|
|
491 // No home page found, we are sending a directory listing. |
|
|
492 cyg_httpd_send_directory_listing(name); |
|
|
493 #else |
|
|
494 cyg_httpd_send_error(CYG_HTTPD_STATUS_NOT_FOUND); |
|
|
495 #endif |
|
|
496 return; |
|
|
497 } |
|
|
498 stat(file_name, &sp); |
|
|
499 } |
|
|
500 |
|
|
501 httpstate.last_modified = sp.st_mtime; |
|
|
502 |
|
|
503 // Let's see if we luck out and can send a 304. |
|
|
504 if ((httpstate.modified_since != -1) && |
|
|
505 (httpstate.modified_since >= sp.st_mtime)) |
|
|
506 { |
|
|
507 cyg_httpd_send_error(CYG_HTTPD_STATUS_NOT_MODIFIED); |
|
|
508 return; |
|
|
509 } |
|
|
510 else |
|
|
511 httpstate.status_code = CYG_HTTPD_STATUS_OK; |
|
|
512 |
|
|
513 // Here we'll look for extension to the file. Consider the case where |
|
|
514 // there might be more than one dot in the file name. We'll look for |
|
|
515 // the last dot, then we'll check the extension. |
|
|
516 char *extension = rindex(file_name, '.'); |
|
|
517 if (extension == NULL) |
|
|
518 httpstate.mime_type = 0; |
|
|
519 else |
|
|
520 httpstate.mime_type = cyg_httpd_find_mime_string(++extension); |
|
|
521 |
|
|
522 httpstate.payload_len = sp.st_size; |
|
|
523 cyg_int32 payload_size = cyg_httpd_format_header(); |
|
|
524 if ((httpstate.mode & CYG_HTTPD_SEND_HEADER_ONLY) != 0) |
|
|
525 { |
|
|
526 send(httpstate.sockets[httpstate.client_index].descriptor, |
|
|
527 httpstate.outbuffer, |
|
|
528 payload_size, |
|
|
529 0); |
|
|
530 return; |
|
|
531 } |
|
|
532 |
|
|
533 fp = fopen(file_name, "r"); |
|
|
534 if(fp == NULL) |
|
|
535 { |
|
|
536 // We should really read errno and send messages accordingly... |
|
|
537 cyg_httpd_send_error(CYG_HTTPD_STATUS_SYSTEM_ERROR); |
|
|
538 return; |
|
|
539 } |
|
|
540 |
|
|
541 // Fill up the rest of the buffer and send it out. |
|
|
542 cyg_int32 bread = fread(httpstate.outbuffer + strlen(httpstate.outbuffer), |
|
|
543 1, |
|
|
544 CYG_HTTPD_MAXOUTBUFFER - payload_size, |
|
|
545 fp); |
|
|
546 cyg_httpd_write(httpstate.outbuffer, payload_size + bread); |
|
|
547 |
|
|
548 cyg_iovec bufs[2] = { { httpstate.outbuffer, 0 }, |
|
|
549 { httpstate.inbuffer, 0 } }; |
|
|
550 ssize_t bytes_written = 0; |
|
|
551 sp.st_size -= bread; |
|
|
552 while (bytes_written < sp.st_size) |
|
|
553 if (sp.st_size - bytes_written <= CYG_HTTPD_MAXOUTBUFFER) |
|
|
554 { |
|
|
555 bufs[0].iov_len = fread(httpstate.outbuffer, |
|
|
556 1, |
|
|
557 CYG_HTTPD_MAXOUTBUFFER, |
|
|
558 fp); |
|
|
559 bytes_written += cyg_httpd_write(httpstate.outbuffer, |
|
|
560 bufs[0].iov_len); |
|
|
561 } |
|
|
562 else |
|
|
563 { |
|
|
564 bufs[0].iov_len = fread(httpstate.outbuffer, |
|
|
565 1, |
|
|
566 CYG_HTTPD_MAXOUTBUFFER, |
|
|
567 fp); |
|
|
568 bufs[1].iov_len = fread(httpstate.inbuffer, |
|
|
569 1, |
|
|
570 CYG_HTTPD_MAXINBUFFER, |
|
|
571 fp); |
|
|
572 bytes_written += cyg_httpd_writev(bufs, 2); |
|
|
573 } |
|
|
574 |
|
|
575 err = fclose(fp); |
|
|
576 if(err < 0) |
|
|
577 cyg_httpd_send_error(CYG_HTTPD_STATUS_SYSTEM_ERROR); |
|
|
578 } |
|
|
579 #endif |
|
|
580 |
|
|
581 cyg_int32 |
|
|
582 cyg_httpd_format_header(void) |
|
|
583 { |
|
|
584 char date[CYG_HTTPD_TIME_STRING_LEN]; |
|
|
585 sprintf(httpstate.outbuffer, "HTTP/1.1 %d", httpstate.status_code); |
|
|
586 time_t time_val = time(NULL); |
|
|
587 |
|
|
588 // Error messages (i.e. with status other than OK, automatically add |
|
|
589 // the no-cache header. |
|
|
590 switch (httpstate.status_code) |
|
|
591 { |
|
|
592 case CYG_HTTPD_STATUS_MOVED_PERMANENTLY: |
|
|
593 strcat(httpstate.outbuffer, " Moved Permanently\r\n"); |
|
|
594 strcat(httpstate.outbuffer, "Location: "); |
|
|
595 strcat(httpstate.outbuffer, httpstate.url); |
|
|
596 strcat(httpstate.outbuffer, "\r\n"); |
|
|
597 strcat(httpstate.outbuffer, "Cache-Control: no-cache\r\n"); |
|
|
598 sprintf(httpstate.outbuffer + strlen(httpstate.outbuffer), |
|
|
599 "Content-Length: %d\r\n", |
|
|
600 httpstate.payload_len); |
|
|
601 break; |
|
|
602 #ifdef CYGOPT_NET_ATHTTPD_USE_AUTH |
|
|
603 case CYG_HTTPD_STATUS_NOT_AUTHORIZED: |
|
|
604 // A 401 error closes the connection right away. |
|
|
605 httpstate.mode |= CYG_HTTPD_MODE_CLOSE_CONN; |
|
|
606 strcat(httpstate.outbuffer, " Not Authorized\r\n"); |
|
|
607 |
|
|
608 // Here we should set the proper header based on the authentication |
|
|
609 // required (httpstate.needs_authMode) but for now, with only |
|
|
610 // Basic Authentication supported, there is no need to do so. |
|
|
611 if (httpstate.needs_auth->auth_mode == CYG_HTTPD_AUTH_BASIC) |
|
|
612 { |
|
|
613 sprintf(httpstate.outbuffer + strlen(httpstate.outbuffer), |
|
|
614 "WWW-Authenticate: Basic realm=\"%s\"\r\n", |
|
|
615 httpstate.needs_auth->auth_domainname); |
|
|
616 } |
|
|
617 else |
|
|
618 { |
|
|
619 sprintf(httpstate.outbuffer + strlen(httpstate.outbuffer), |
|
|
620 "WWW-Authenticate: Digest realm=\"%s\" ", |
|
|
621 httpstate.needs_auth->auth_domainname); |
|
|
622 cyg_httpd_format_time_string(cyg_httpd_md5_nonce, &time_val); |
|
|
623 sprintf(httpstate.outbuffer + strlen(httpstate.outbuffer), |
|
|
624 "nonce=\"%s\" ", cyg_httpd_md5_nonce); |
|
|
625 sprintf(httpstate.outbuffer + strlen(httpstate.outbuffer), |
|
|
626 "opaque=\"%s\", ", |
|
|
627 CYG_HTTPD_MD5_AUTH_OPAQUE); |
|
|
628 sprintf(httpstate.outbuffer + strlen(httpstate.outbuffer), |
|
|
629 "stale=false, algorithm=%s, qop=\"%s\"\r\n", |
|
|
630 CYG_HTTPD_MD5_AUTH_NAME, |
|
|
631 CYG_HTTPD_MD5_AUTH_QOP ); |
|
|
632 } |
|
|
633 strcat(httpstate.outbuffer, "Cache-Control: no-cache\r\n"); |
|
|
634 break; |
|
|
635 #endif |
|
|
636 case CYG_HTTPD_STATUS_NOT_MODIFIED: |
|
|
637 strcat(httpstate.outbuffer, " Not Modified\r\n"); |
|
|
638 strcat(httpstate.outbuffer, "Cache-Control: no-cache\r\n"); |
|
|
639 break; |
|
|
640 case CYG_HTTPD_STATUS_NOT_FOUND: |
|
|
641 strcat(httpstate.outbuffer, " Not Found\r\n"); |
|
|
642 strcat(httpstate.outbuffer, "Cache-Control: no-cache\r\n"); |
|
|
643 sprintf(httpstate.outbuffer + strlen(httpstate.outbuffer), |
|
|
644 "Content-Length: %d\r\n", |
|
|
645 httpstate.payload_len); |
|
|
646 break; |
|
|
647 case CYG_HTTPD_STATUS_METHOD_NOT_ALLOWED: |
|
|
648 strcat(httpstate.outbuffer, " Method Not Allowed\r\n"); |
|
|
649 strcat(httpstate.outbuffer, "Cache-Control: no-cache\r\n"); |
|
|
650 break; |
|
|
651 default: |
|
|
652 strcat(httpstate.outbuffer, " OK\r\n"); |
|
|
653 if ((httpstate.mode & CYG_HTTPD_MODE_TRANSFER_CHUNKED) == 0) |
|
|
654 sprintf(httpstate.outbuffer + strlen(httpstate.outbuffer), |
|
|
655 "Content-Length: %d\r\n", |
|
|
656 httpstate.payload_len); |
|
|
657 break; |
|
|
658 } |
|
|
659 |
|
|
660 cyg_httpd_format_time_string(date, &time_val); |
|
|
661 sprintf(httpstate.outbuffer + strlen(httpstate.outbuffer), |
|
|
662 "Date: %s\r\n", |
|
|
663 date); |
|
|
664 sprintf(httpstate.outbuffer + strlen(httpstate.outbuffer), |
|
|
665 "Server: %s\r\n", |
|
|
666 CYGDAT_NET_ATHTTPD_SERVEROPT_SERVERID); |
|
|
667 |
|
|
668 if (httpstate.mode & CYG_HTTPD_MODE_CLOSE_CONN) |
|
|
669 strcat(httpstate.outbuffer, "Connection: close\r\n"); |
|
|
670 else |
|
|
671 strcat(httpstate.outbuffer, "Connection: keep-alive\r\n"); |
|
|
672 |
|
|
673 if (httpstate.mime_type != 0) |
|
|
674 { |
|
|
675 sprintf(httpstate.outbuffer + strlen(httpstate.outbuffer), |
|
|
676 "Content-Type: %s\r\n", |
|
|
677 httpstate.mime_type); |
|
|
678 } |
|
|
679 else |
|
|
680 // When we cannot find the appropriate MIME type, we'll send a |
|
|
681 // default type. |
|
|
682 sprintf(httpstate.outbuffer + strlen(httpstate.outbuffer), |
|
|
683 "Content-Type: %s\r\n", |
|
|
684 CYGDAT_NET_ATHTTPD_DEFAULT_MIME_TYPE); |
|
|
685 |
|
|
686 if (httpstate.mode & CYG_HTTPD_MODE_TRANSFER_CHUNKED) |
|
|
687 strcat(httpstate.outbuffer, "Transfer-Encoding: chunked\r\n"); |
|
|
688 |
|
|
689 if (httpstate.last_modified != -1) |
|
|
690 { |
|
|
691 time_val = httpstate.last_modified; |
|
|
692 cyg_httpd_format_time_string(httpstate.inbuffer, &time_val); |
|
|
693 sprintf(httpstate.outbuffer + strlen(httpstate.outbuffer), |
|
|
694 "Last-Modified: %s\r\n", |
|
|
695 httpstate.inbuffer); |
|
|
696 } |
|
|
697 |
|
|
698 // There must be 2 carriage returns between the header and the body, |
|
|
699 // so if you modify this function make sure that there is another |
|
|
700 // CRLF already terminating the buffer thus far. |
|
|
701 strcat(httpstate.outbuffer, "\r\n"); |
|
|
702 return strlen(httpstate.outbuffer); |
|
|
703 } |
|
|
704 |
|
|
705 void |
|
|
706 cyg_httpd_handle_method_GET(void) |
|
|
707 { |
|
|
708 // Handlers are executed first. |
|
|
709 handler h = cyg_httpd_find_handler(); |
|
|
710 if (h != 0) |
|
|
711 { |
|
|
712 // A handler was found. We'll call the function associated to it. If |
|
|
713 // the return value is 0 we'll also try to see if the file by the same |
|
|
714 // name is available in the file system or internal resources. |
|
|
715 #ifdef CYGOPT_NET_ATHTTPD_USE_FS |
|
|
716 cyg_int32 rc = h(&httpstate); |
|
|
717 if (rc != 0) |
|
|
718 return; |
|
|
719 #else |
|
|
720 h(&httpstate); |
|
|
721 return; |
|
|
722 #endif |
|
|
723 } |
|
|
724 |
|
|
725 #ifdef CYGOPT_NET_ATHTTPD_USE_CGIBIN_OBJLOADER |
|
|
726 // If the URL is a CGI script, there is a different directory... |
|
|
727 if (httpstate.url[0] == '/' && |
|
|
728 !strncmp(httpstate.url + 1, |
|
|
729 CYGDAT_NET_ATHTTPD_SERVEROPT_CGIDIR, |
|
|
730 strlen(CYGDAT_NET_ATHTTPD_SERVEROPT_CGIDIR))) |
|
|
731 { |
|
|
732 cyg_httpd_exec_cgi(); |
|
|
733 return; |
|
|
734 } |
|
|
735 // If the OBJLOADER package is not loaded, then the request for a library |
|
|
736 // will likely generate a 404. |
|
|
737 #endif |
|
|
738 |
|
|
739 #ifdef CYGOPT_NET_ATHTTPD_USE_FS |
|
|
740 // No handler, we'll redirect to the file system. |
|
|
741 cyg_httpd_send_file(httpstate.url); |
|
|
742 #else |
|
|
743 // If we do not have a file system, we look for the file within the |
|
|
744 // internal resources of the server. The user can add his/her own files |
|
|
745 // to the table. |
|
|
746 if (strcmp(httpstate.url, "/") == 0) |
|
|
747 { |
|
|
748 int i; |
|
|
749 cyg_httpd_ires_table_entry *p; |
|
|
750 for (i = 0; i < sizeof(home_pages)/sizeof(char*); i++) |
|
|
751 { |
|
|
752 httpstate.url[1] = '\0'; |
|
|
753 strcat(httpstate.url, home_pages[i]); |
|
|
754 p = cyg_httpd_find_ires(httpstate.url); |
|
|
755 if (p != NULL) |
|
|
756 { |
|
|
757 cyg_httpd_send_ires(p); |
|
|
758 return; |
|
|
759 } |
|
|
760 } |
|
|
761 } |
|
|
762 else |
|
|
763 { |
|
|
764 cyg_httpd_ires_table_entry *p = cyg_httpd_find_ires(httpstate.url); |
|
|
765 if (p != NULL) |
|
|
766 { |
|
|
767 cyg_httpd_send_ires(p); |
|
|
768 return; |
|
|
769 } |
|
|
770 } |
|
|
771 cyg_httpd_send_error(CYG_HTTPD_STATUS_NOT_FOUND); |
|
|
772 #endif |
|
|
773 } |
|
|
774 |
|
|
775 char* |
|
|
776 cyg_httpd_get_URL(char* p) |
|
|
777 { |
|
|
778 char* dest = httpstate.url; |
|
|
779 |
|
|
780 // First get rid of multiple leading slashes. |
|
|
781 while ((p[0] == '/') && (p[1] == '/')) |
|
|
782 p++; |
|
|
783 |
|
|
784 // Store the url, and check if there is a form result in it. |
|
|
785 while ((*p != ' ') && (*p != '?') && |
|
|
786 ((dest - httpstate.url) < CYG_HTTPD_MAXURL - 1)) |
|
|
787 { |
|
|
788 // Look for encoded characters in the URL. |
|
|
789 if (*p == '%') |
|
|
790 { |
|
|
791 p++; |
|
|
792 if (*p) |
|
|
793 *dest = cyg_httpd_from_hex(*p++) * 16; |
|
|
794 if (*p) |
|
|
795 *dest += cyg_httpd_from_hex(*p++); |
|
|
796 } |
|
|
797 else |
|
|
798 *dest++ = *p++; |
|
|
799 } |
|
|
800 |
|
|
801 // Terminate the file name... |
|
|
802 *dest = '\0'; |
|
|
803 |
|
|
804 // The URL must start with a leadng slash. |
|
|
805 if (httpstate.url[0] != '/') |
|
|
806 { |
|
|
807 cyg_httpd_send_error(CYG_HTTPD_STATUS_BAD_REQUEST); |
|
|
808 return (char*)0; |
|
|
809 } |
|
|
810 |
|
|
811 // Run past white spaces. |
|
|
812 while ((*p == ' ') && (*p != '\0')) |
|
|
813 p++; |
|
|
814 return p; |
|
|
815 } |
|
|
816 |
|
|
817 char* |
|
|
818 cyg_httpd_parse_POST(char* p) |
|
|
819 { |
|
|
820 #if CYGOPT_NET_ATHTTPD_DEBUG_LEVEL > 1 |
|
|
821 diag_printf("POST Request URL: %s\n", httpstate.url); |
|
|
822 #endif |
|
|
823 httpstate.method = CYG_HTTPD_METHOD_POST; |
|
|
824 httpstate.mode &= ~CYG_HTTPD_SEND_HEADER_ONLY; |
|
|
825 p = cyg_httpd_get_URL(p); |
|
|
826 if (p == 0) |
|
|
827 return 0; |
|
|
828 |
|
|
829 while (*p++ != '\n'); |
|
|
830 return p; |
|
|
831 } |
|
|
832 |
|
|
833 char* |
|
|
834 cyg_httpd_parse_GET(char* p) |
|
|
835 { |
|
|
836 #if CYGOPT_NET_ATHTTPD_DEBUG_LEVEL > 1 |
|
|
837 diag_printf("GET Request URL: %s\n", httpstate.url); |
|
|
838 #endif |
|
|
839 httpstate.method = CYG_HTTPD_METHOD_GET; |
|
|
840 httpstate.mode &= ~CYG_HTTPD_SEND_HEADER_ONLY; |
|
|
841 p = cyg_httpd_get_URL(p); |
|
|
842 if (p == 0) |
|
|
843 return 0; |
|
|
844 |
|
|
845 if (*p == '?') |
|
|
846 // If we have a GET header with form variables we'll get the |
|
|
847 // variables out of it and store them in the variable table. |
|
|
848 p = cyg_httpd_store_form_data(++p); |
|
|
849 |
|
|
850 // Run past white spaces. |
|
|
851 while (*p == ' ') |
|
|
852 p++; |
|
|
853 return p; |
|
|
854 } |
|
|
855 |
|
|
856 char* |
|
|
857 cyg_httpd_parse_HEAD(char* p) |
|
|
858 { |
|
|
859 #if CYGOPT_NET_ATHTTPD_DEBUG_LEVEL > 1 |
|
|
860 diag_printf("HEAD Request URL: %s\n", httpstate.url); |
|
|
861 #endif |
|
|
862 httpstate.method = CYG_HTTPD_METHOD_HEAD; |
|
|
863 httpstate.mode |= CYG_HTTPD_SEND_HEADER_ONLY; |
|
|
864 p = cyg_httpd_get_URL(p); |
|
|
865 if (p == 0) |
|
|
866 return 0; |
|
|
867 |
|
|
868 // Can we have variables in a HEAD request? I'll assume the answer is a yes |
|
|
869 // for now. |
|
|
870 if (*p == '?') |
|
|
871 p = cyg_httpd_store_form_data(++p); |
|
|
872 |
|
|
873 // Run past white spaces. |
|
|
874 while (*p == ' ') |
|
|
875 p++; |
|
|
876 return p; |
|
|
877 } |
|
|
878 |
|
|
879 cyg_int32 |
|
|
880 cyg_httpd_process_header(void) |
|
|
881 { |
|
|
882 char *cp; |
|
|
883 char *p = httpstate.inbuffer; |
|
|
884 |
|
|
885 // The deafult for HTTP 1.1 is keep-alive connections, unless specifically |
|
|
886 // closed by the far end. |
|
|
887 httpstate.mode &= ~CYG_HTTPD_MODE_CLOSE_CONN; |
|
|
888 httpstate.modified_since = -1; |
|
|
889 while (*p) |
|
|
890 { |
|
|
891 if (!strncasecmp("GET ", p, 4)) |
|
|
892 { |
|
|
893 p = cyg_httpd_parse_GET(httpstate.inbuffer + 4); |
|
|
894 if (p ==0) |
|
|
895 return 0; |
|
|
896 } |
|
|
897 else if (!strncasecmp("POST ", p, 5)) |
|
|
898 { |
|
|
899 p = cyg_httpd_parse_POST(httpstate.inbuffer + 5); |
|
|
900 if (p ==0) |
|
|
901 return 0; |
|
|
902 } |
|
|
903 else if (!strncasecmp("HEAD ", p, 5)) |
|
|
904 { |
|
|
905 p = cyg_httpd_parse_HEAD(httpstate.inbuffer + 5); |
|
|
906 if (p ==0) |
|
|
907 return 0; |
|
|
908 } |
|
|
909 else if (strncasecmp(p, "Content-Length: ", 16) == 0) |
|
|
910 { |
|
|
911 cp = strchr(p, ':') + 2; |
|
|
912 if(cp) |
|
|
913 httpstate.inbuffer_len = atoi(cp); |
|
|
914 while(*p != '\n') |
|
|
915 p++; |
|
|
916 } |
|
|
917 else if (strncasecmp("Host:", p, 5) == 0) |
|
|
918 { |
|
|
919 p += 5; |
|
|
920 if ( *p == ' ' ) |
|
|
921 p++; |
|
|
922 sscanf(p, |
|
|
923 "%d.%d.%d.%d", |
|
|
924 &httpstate.host[0], |
|
|
925 &httpstate.host[1], |
|
|
926 &httpstate.host[2], |
|
|
927 &httpstate.host[3]); |
|
|
928 while ( *p != '\n') |
|
|
929 p++; |
|
|
930 p++; |
|
|
931 } |
|
|
932 else if (strncasecmp("If-Modified-Since:", p, 18) == 0) |
|
|
933 { |
|
|
934 p += 18; |
|
|
935 if ( *p == ' ' ) |
|
|
936 p++; |
|
|
937 httpstate.modified_since = cyg_httpd_parse_date(p); |
|
|
938 while ( *p != '\n') |
|
|
939 p++; |
|
|
940 p++; |
|
|
941 } |
|
|
942 #ifdef CYGOPT_NET_ATHTTPD_USE_AUTH |
|
|
943 else if (strncasecmp("Authorization:", p, 14) == 0) |
|
|
944 { |
|
|
945 p += 14; |
|
|
946 while (*p == ' ') |
|
|
947 p++; |
|
|
948 if (!strncasecmp("Basic", p, 5)) |
|
|
949 { |
|
|
950 char *cr = cyg_httpd_md5_digest; |
|
|
951 p += 5; |
|
|
952 while (*p == ' ') |
|
|
953 p++; |
|
|
954 while ((*p != '\r') && (*p != '\n') && (*p != ' ')) |
|
|
955 *cr++ = *p++; |
|
|
956 *cr = '\0'; |
|
|
957 } |
|
|
958 else if (strncasecmp(p, "Digest", 6) == 0) |
|
|
959 { |
|
|
960 diag_printf(httpstate.inbuffer); |
|
|
961 p += 6; |
|
|
962 while (*p == ' ') |
|
|
963 p++; |
|
|
964 while ((*p != '\r') && (*p != '\n')) |
|
|
965 { |
|
|
966 if (strncasecmp(p, "realm=", 6) == 0) |
|
|
967 p = cyg_httpd_digest_skip(p + 6); |
|
|
968 else if (strncasecmp(p, "username=", 9) == 0) |
|
|
969 p = cyg_httpd_digest_skip(p + 9); |
|
|
970 else if (strncasecmp(p, "nonce=", 6) == 0) |
|
|
971 p = cyg_httpd_digest_skip(p + 6); |
|
|
972 else if (strncasecmp(p, "response=", 9) == 0) |
|
|
973 p = cyg_httpd_digest_data(cyg_httpd_md5_response, |
|
|
974 p + 9); |
|
|
975 else if (strncasecmp(p, "cnonce=", 7) == 0) |
|
|
976 p = cyg_httpd_digest_data(cyg_httpd_md5_cnonce, p + 7); |
|
|
977 else if (strncasecmp(p, "qop=", 4) == 0) |
|
|
978 p = cyg_httpd_digest_skip(p + 4); |
|
|
979 else if (strncasecmp(p, "nc=", 3) == 0) |
|
|
980 p = cyg_httpd_digest_data(cyg_httpd_md5_noncecount, |
|
|
981 p + 3); |
|
|
982 else if (strncasecmp(p, "algorithm=", 10) == 0) |
|
|
983 p = cyg_httpd_digest_skip(p + 10); |
|
|
984 else if (strncasecmp(p, "opaque=", 7) == 0) |
|
|
985 p = cyg_httpd_digest_skip(p + 7); |
|
|
986 else if (strncasecmp(p, "uri=", 4) == 0) |
|
|
987 p = cyg_httpd_digest_skip(p + 4); |
|
|
988 } |
|
|
989 } |
|
|
990 else |
|
|
991 { |
|
|
992 while (*p != '\n') |
|
|
993 p++; |
|
|
994 p++; |
|
|
995 } |
|
|
996 } |
|
|
997 #endif // CYGOPT_NET_ATHTTPD_USE_AUTH |
|
|
998 else if (strncasecmp(p, "Connection:", 11) == 0) |
|
|
999 { |
|
|
1000 p += 11; |
|
|
1001 while (*p == ' ') |
|
|
1002 p++; |
|
|
1003 if (strncasecmp(p, "close", 5) == 0) |
|
|
1004 httpstate.mode |= CYG_HTTPD_MODE_CLOSE_CONN; |
|
|
1005 while(*p != '\n') |
|
|
1006 p++; |
|
|
1007 p++; |
|
|
1008 } |
|
|
1009 else |
|
|
1010 { |
|
|
1011 // We'll just dump the rest of the line and move on to the next. |
|
|
1012 while(*p != '\n') |
|
|
1013 p++; |
|
|
1014 p++; |
|
|
1015 } |
|
|
1016 } |
|
|
1017 return 1; |
|
|
1018 } |
|
|
1019 |
|
|
1020 cyg_int32 |
|
|
1021 cyg_httpd_process_method(void) |
|
|
1022 { |
|
|
1023 cyg_int32 rc = cyg_httpd_process_header(); |
|
|
1024 if (rc == 0) |
|
|
1025 return 0; |
|
|
1026 |
|
|
1027 switch (httpstate.method) |
|
|
1028 { |
|
|
1029 case CYG_HTTPD_METHOD_GET: |
|
|
1030 case CYG_HTTPD_METHOD_HEAD: |
|
|
1031 cyg_httpd_handle_method_GET(); |
|
|
1032 break; |
|
|
1033 case CYG_HTTPD_METHOD_POST: |
|
|
1034 cyg_httpd_handle_method_POST(); |
|
|
1035 break; |
|
|
1036 default: |
|
|
1037 cyg_httpd_send_error(CYG_HTTPD_STATUS_NOT_IMPLEMENTED); |
|
|
1038 break; |
|
|
1039 } |
|
|
1040 return 0; |
|
|
1041 } |
|
|
1042 |