diff options
Diffstat (limited to 'src/client.c')
-rw-r--r-- | src/client.c | 1171 |
1 files changed, 0 insertions, 1171 deletions
diff --git a/src/client.c b/src/client.c deleted file mode 100644 index 22862020..00000000 --- a/src/client.c +++ /dev/null | |||
@@ -1,1171 +0,0 @@ | |||
1 | /* Copyrights 2002 Luis Figueiredo (stdio@netc.pt) All rights reserved. | ||
2 | * | ||
3 | * See the LICENSE file | ||
4 | * | ||
5 | * The origin of this software must not be misrepresented, either by | ||
6 | * explicit claim or by omission. Since few users ever read sources, | ||
7 | * credits must appear in the documentation. | ||
8 | * | ||
9 | * date: Sat Mar 30 14:44:42 GMT 2002 | ||
10 | * | ||
11 | * -- client handler functions | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | |||
16 | #include "client.h" | ||
17 | #include "outstream.h" | ||
18 | #include "clientinfo.h" | ||
19 | |||
20 | int WEBTIMEOUT=10000; | ||
21 | |||
22 | /*********************************************************************************************************/ | ||
23 | /* | ||
24 | * initializate (allocate) client list | ||
25 | */ | ||
26 | struct web_client *__ILWS_init_client_list() { | ||
27 | struct web_client *ret; | ||
28 | ret=__ILWS_malloc(sizeof(struct web_client)); | ||
29 | if(ret==NULL) { | ||
30 | return NULL; | ||
31 | }; | ||
32 | #ifdef HAVE_OPENSSL | ||
33 | ret->ssl=NULL; // ssl handler for this client | ||
34 | #endif | ||
35 | ret->next=NULL; | ||
36 | return ret; | ||
37 | } | ||
38 | |||
39 | |||
40 | /*********************************************************************************************************/ | ||
41 | /* | ||
42 | * Add a client node to client list | ||
43 | */ | ||
44 | int __ILWS_add_client(struct web_client *list, struct web_client *node) { | ||
45 | struct web_client *temp=list; | ||
46 | |||
47 | #ifdef WIN32 | ||
48 | unsigned long t=IOC_INOUT; | ||
49 | #endif | ||
50 | while(temp->next!=NULL)temp=temp->next; // run to last client | ||
51 | temp->next=node; | ||
52 | temp->next->rbuf=NULL; | ||
53 | temp->next->rbufsize=0; | ||
54 | |||
55 | if(!(temp->next->outstream=__ILWS_init_outstream_list())) { | ||
56 | return 0; | ||
57 | }; | ||
58 | if(!(temp->next->varlist=__ILWS_init_var_list())) { | ||
59 | return 0; | ||
60 | }; | ||
61 | |||
62 | temp->next->contentlength=0; | ||
63 | temp->next->headersize=0; | ||
64 | |||
65 | temp->next->wheadersize=0; | ||
66 | temp->next->writelength=0; | ||
67 | temp->next->readsize=0; | ||
68 | temp->next->range=0; | ||
69 | temp->next->skipped=0; | ||
70 | temp->next->cookies=NULL; | ||
71 | //temp->next->oldcl=clock(); | ||
72 | |||
73 | |||
74 | temp->next->newdata_try=0; | ||
75 | #ifdef WIN32 | ||
76 | // should be optional | ||
77 | ioctlsocket(temp->next->socket,FIONBIO,&t); //non blocking sockets for win32 | ||
78 | #else | ||
79 | fcntl(temp->next->socket,F_SETFL,O_NONBLOCK); | ||
80 | #endif | ||
81 | temp->next->next=NULL; | ||
82 | temp->next->HTTPdirective=NULL; | ||
83 | temp->next->stat=1; // Add a connected client | ||
84 | |||
85 | return 1; | ||
86 | } | ||
87 | /*********************************************************************************************************/ | ||
88 | |||
89 | |||
90 | |||
91 | /*********************************************************************************************************/ | ||
92 | /* | ||
93 | * Delete client node | ||
94 | */ | ||
95 | void __ILWS_delete_client(struct web_client *node) { | ||
96 | int rt; | ||
97 | rt=shutdown(node->socket,SHUT_RDWR); | ||
98 | #ifdef WIN32 | ||
99 | rt=closesocket(node->socket); | ||
100 | #else | ||
101 | rt=close(node->socket); | ||
102 | #endif | ||
103 | __ILWS_free(node->cookies); // (0.5.1) | ||
104 | __ILWS_delete_outstream_list(node->outstream); | ||
105 | __ILWS_delete_var_list(node->varlist); | ||
106 | #ifdef HAVE_OPENSSL | ||
107 | SSL_free (node->ssl); | ||
108 | #endif | ||
109 | __ILWS_free(node->rbuf); // free's | ||
110 | __ILWS_free(node); // free's | ||
111 | |||
112 | } | ||
113 | |||
114 | |||
115 | /*********************************************************************************************************/ | ||
116 | /* | ||
117 | * Delete next client node | ||
118 | */ | ||
119 | void __ILWS_delete_next_client(struct web_client *node) { | ||
120 | struct web_client *temp=node->next; | ||
121 | node->next=node->next->next; | ||
122 | __ILWS_delete_client(temp); | ||
123 | } | ||
124 | |||
125 | /*********************************************************************************************************/ | ||
126 | /* | ||
127 | * Delete entire client list | ||
128 | */ | ||
129 | void __ILWS_delete_client_list(struct web_client *node) { | ||
130 | struct web_client *next; | ||
131 | |||
132 | while(node) { | ||
133 | next = node->next; | ||
134 | __ILWS_free(node); | ||
135 | node = next; | ||
136 | } | ||
137 | } | ||
138 | |||
139 | /*********************************************************************************************************/ | ||
140 | /* | ||
141 | * Read what client have to say | ||
142 | */ | ||
143 | void __ILWS_read_client(struct web_client *node) { | ||
144 | int tmp,tmp1; | ||
145 | char *tmp2,*tmp3=NULL; | ||
146 | char readtemp[READMAX+1]; | ||
147 | unsigned long datasize=0; | ||
148 | |||
149 | #ifdef HAVE_OPENSSL | ||
150 | if(node->ssl!=NULL) { | ||
151 | tmp=SSL_read(node->ssl,readtemp,READMAX); | ||
152 | } else { | ||
153 | tmp=__ILWS_read(node->socket,readtemp,READMAX); | ||
154 | }; | ||
155 | #else | ||
156 | tmp=__ILWS_read(node->socket,readtemp,READMAX); | ||
157 | #endif | ||
158 | //fprintf(stderr,"readed %d bytes\n",tmp); | ||
159 | if(tmp<1) { | ||
160 | |||
161 | #ifdef WIN32 | ||
162 | if(WSAGetLastError()!=WSAEWOULDBLOCK) { | ||
163 | #else | ||
164 | if(errno!=EAGAIN) { | ||
165 | #endif | ||
166 | node->stat=5;return; | ||
167 | |||
168 | }; | ||
169 | //fprintf(stderr,"try: %d (%s)\n",node->newdata_try,node->rbuf); | ||
170 | // check if it is over | ||
171 | node->newdata_try++; | ||
172 | //fprintf(stderr,"node->newdata_try:%d\n",node->newdata_try); | ||
173 | if(node->rbufsize >0) { //&& node->newdata_try>5) { | ||
174 | if(node->headersize==0) { // always reachs "\r\n\r\n" | ||
175 | if((tmp3=strstr(node->rbuf,"\r\n\r\n"))) { | ||
176 | node->headersize=(tmp3-node->rbuf); | ||
177 | }; | ||
178 | } else { | ||
179 | datasize=node->rbufsize-node->headersize; | ||
180 | if(node->contentlength==0) { // well if it 0 read all at once | ||
181 | __ILWS_init_clientinfo(); // always call this? | ||
182 | node->contentlength=atol(ClientInfo->Header("Content-Length")); | ||
183 | // range for resuming | ||
184 | if((tmp3=strstr(ClientInfo->Header("Range"),"bytes="))) { // if it is in bytes (i hope, always) | ||
185 | tmp3+=6; // go to end of "bytes=" | ||
186 | node->range=atol(tmp3); | ||
187 | //printf("Range is %d - %s - %s\n",node->range,ClientInfo->Header("Range"),tmp3); | ||
188 | }; | ||
189 | // end range | ||
190 | __ILWS_free_clientinfo(); | ||
191 | }; | ||
192 | if(node->contentlength==datasize-4) { | ||
193 | //fprintf(stderr,"client (%d) all readed (%d) (try's)-%d\n",node->socket,node->curcl-node->oldcl,node->newdata_try); | ||
194 | node->newdata_try=WEBTIMEOUT; // assume done reading | ||
195 | //fprintf(stderr,"Ended naturaly\n"); | ||
196 | |||
197 | } | ||
198 | }; | ||
199 | if((node->newdata_try>=WEBTIMEOUT)) { // All readed | ||
200 | node->rbuf[node->rbufsize]='\0'; | ||
201 | node->stat=2; // Next state | ||
202 | //fprintf(stderr,"%s\n",node->rbuf); | ||
203 | //fprintf(stderr,"%d\n",node->rbufsize); | ||
204 | } | ||
205 | }; | ||
206 | }else { | ||
207 | tmp1=node->rbufsize; | ||
208 | node->rbufsize+=tmp; | ||
209 | tmp2=__ILWS_realloc(node->rbuf,node->rbufsize+1); | ||
210 | if(tmp2==NULL) { | ||
211 | node->stat=5; | ||
212 | |||
213 | return; | ||
214 | }else { | ||
215 | node->rbuf=tmp2; | ||
216 | }; | ||
217 | memcpy(node->rbuf+tmp1,readtemp,tmp); | ||
218 | node->newdata_try=0; | ||
219 | }; | ||
220 | } | ||
221 | |||
222 | |||
223 | /*********************************************************************************************************/ | ||
224 | /* | ||
225 | * Process headers w/ get handlers | ||
226 | */ | ||
227 | void __ILWS_process_client(struct web_client *node,struct gethandler *list) { | ||
228 | struct gethandler *gettemp=list; | ||
229 | long secs=time(NULL); | ||
230 | // for determining content length | ||
231 | #define RTMPMAX 400 | ||
232 | struct outstream *tmpstream; // new on 0.5.1 | ||
233 | char rtmp[RTMPMAX+1]; | ||
234 | int rtmps=0; | ||
235 | char *thead=NULL; | ||
236 | char *tmpl; | ||
237 | /// | ||
238 | int tmp=0; | ||
239 | int oumask=0; // old usermask | ||
240 | char *tmp1=__ILWS_web_client_getreq(); | ||
241 | char matchbuf[MATCHMAX]; | ||
242 | FILE *nfile; // new file | ||
243 | char *fname; // new file name | ||
244 | |||
245 | |||
246 | while(gettemp->next!=NULL && tmp==0) { | ||
247 | gettemp=gettemp->next; | ||
248 | snprintf(matchbuf,MATCHMAX,"%s",gettemp->str); | ||
249 | if(!tmp1) { | ||
250 | __ILWS_web_client_writef(node,"HTTP/1.1 400 Invalid request\r\n"); | ||
251 | __ILWS_web_client_writef(node,"Server: %s\r\n",_libwebserver_version); | ||
252 | __ILWS_web_client_writef(node,"Date: %s\r\n",__ILWS_date(mktime(gmtime(&secs)),"%a, %d %b %Y %H:%M:%S GMT")); // Date header | ||
253 | __ILWS_web_client_writef(node,"Content-type: text/html\r\n\r\n<HTML><title>Invalid request</title><body bgcolor=FFFFFF><font size=6>400 Invalid request</font><BR><BR><small>Yout request doesn't match the requesits to be processed</small><BR><HR><small><i>%s</i></small></body></html>\n\r",_libwebserver_version); | ||
254 | tmpl=__ILWS_web_client_getreqline(); | ||
255 | web_log("%s - - [%s] \"%s\" 400 (invalid request)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); | ||
256 | __ILWS_free(tmpl); | ||
257 | node->stat=5; | ||
258 | return; | ||
259 | }; | ||
260 | if(strlen(tmp1)>MAXURLSIZE) { | ||
261 | __ILWS_web_client_writef(node,"HTTP/1.1 414 URL to large\r\n"); | ||
262 | __ILWS_web_client_writef(node,"Server: %s\r\n",_libwebserver_version); | ||
263 | __ILWS_web_client_writef(node,"Date: %s\r\n",__ILWS_date(mktime(gmtime(&secs)),"%a, %d %b %Y %H:%M:%S GMT")); // Date header | ||
264 | __ILWS_web_client_writef(node,"Content-type: text/html\r\n\r\n<HTML><title>URL to large</title><body bgcolor=FFFFFF><font size=6>414 Requested url to large</font><BR><BR><small>Wonder this... why is that so large?</small><BR><HR><small><i>%s</i></small></body></html>\n\r",_libwebserver_version); | ||
265 | tmpl=__ILWS_web_client_getreqline(); | ||
266 | web_log("%s - - [%s] \"%s\" 414 (url to large)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); | ||
267 | __ILWS_free(tmpl); | ||
268 | node->stat=5; | ||
269 | __ILWS_free(tmp1); | ||
270 | return; | ||
271 | }; | ||
272 | if(!fnmatch(matchbuf,tmp1,5)) { | ||
273 | if((gettemp->flag & WS_LOCAL) == WS_LOCAL) { | ||
274 | if(node->sa.sin_addr.s_addr!=0x0100007F) { | ||
275 | __ILWS_web_client_writef(node,"HTTP/1.1 403 Forbidden\r\n"); | ||
276 | __ILWS_web_client_writef(node,"Server: %s\r\n",_libwebserver_version); | ||
277 | __ILWS_web_client_writef(node,"Date: %s\r\n",__ILWS_date(mktime(gmtime(&secs)),"%a, %d %b %Y %H:%M:%S GMT")); // Date header | ||
278 | __ILWS_web_client_writef(node,"Content-type: text/html\r\n\r\n<HTML><title>Forbidden</title><body bgcolor=FFFFFF><font size=6>403 Forbidden</font><BR><BR><small>only local host accepted</small><BR><HR><small><i>%s</i></small></body></html>\n\r",_libwebserver_version); | ||
279 | tmpl=__ILWS_web_client_getreqline(); | ||
280 | web_log("%s - - [%s] \"%s\" 403 (Forbidden)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); | ||
281 | __ILWS_free(tmpl); | ||
282 | node->stat=5; | ||
283 | __ILWS_free(tmp1); | ||
284 | return; | ||
285 | }; | ||
286 | }; | ||
287 | tmp=1; // Was found | ||
288 | node->outstream->flags=(gettemp->flag & WS_DYNVAR); // pass to outstreams | ||
289 | }; | ||
290 | }; | ||
291 | __ILWS_free(tmp1); | ||
292 | if(!tmp) { // Nothing found | ||
293 | __ILWS_web_client_writef(node,"HTTP/1.1 404 Not Found\r\n"); | ||
294 | __ILWS_web_client_writef(node,"Server: %s\r\n",_libwebserver_version); | ||
295 | __ILWS_web_client_writef(node,"Date: %s\r\n",__ILWS_date(mktime(gmtime(&secs)),"%a, %d %b %Y %H:%M:%S GMT")); // Date header | ||
296 | __ILWS_web_client_writef(node,"Content-type: text/html\r\n\r\n<HTML><title>not found</title><body bgcolor=FFFFFF><font size=6>404 NOT FOUND</font><BR><BR><small>The requested content wasn't found</small><BR><HR><small><i>%s</i></small></body></html>\n\r",_libwebserver_version); | ||
297 | tmpl=__ILWS_web_client_getreqline(); | ||
298 | web_log("%s - - [%s] \"%s\" 404 (Not Found)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); | ||
299 | __ILWS_free(tmpl); | ||
300 | node->stat=5; | ||
301 | }else { | ||
302 | |||
303 | // if cgi do something else, present headers | ||
304 | oumask=umask(077); | ||
305 | if(!(fname=__ILWS_tmpfname())) { | ||
306 | libws_error(LE_FILESYS,": Error giving a temp filename\n"); | ||
307 | node->stat=5; | ||
308 | return; | ||
309 | }; | ||
310 | if((nfile=freopen(fname,"wb+",stdout))!=NULL) { | ||
311 | flock(fileno(stdout),LOCK_EX); | ||
312 | tmp=dup(fileno(stdout)); | ||
313 | nfile=fdopen(tmp,"wb+"); | ||
314 | if(!__ILWS_add_outstream(node->outstream,fname,nfile,1)) { | ||
315 | node->stat=5; // (delete client) | ||
316 | return; // ERROR reported by add_outstream | ||
317 | |||
318 | }; | ||
319 | // THE PROCESS | ||
320 | |||
321 | // Setup Clientinfo before running function | ||
322 | if(gettemp->type==GH_FUNCTION) { | ||
323 | __ILWS_init_clientinfo(); | ||
324 | gettemp->hdl.func(); // changed (0.5.3) Access by named union (Hilobok Andrew (han@km.if.ua) said that wasn't compile on freeBSD) | ||
325 | __ILWS_free_clientinfo(); | ||
326 | }; | ||
327 | // new on 0.5.2 | ||
328 | if(gettemp->type==GH_DIRECTORY) { // as builtin function for directory listing | ||
329 | __ILWS_init_clientinfo(); | ||
330 | if(strcmp(gettemp->str,"* /*"))ClientInfo->request+=1; // skip '/' if not equal to "* /*" (used by default) | ||
331 | __ILWS_lws_list(gettemp->hdl.path); // changed (0.5.3) Access by named union (Hilobok Andrew (han@km.if.ua) said that wasn't compile on freeBSD) | ||
332 | __ILWS_free_clientinfo(); | ||
333 | }; | ||
334 | |||
335 | fflush(stdout); | ||
336 | fclose(stdout); // it is a tempfile freopened | ||
337 | __ILWS_free(fname); // doesn't need anymore | ||
338 | #ifdef WIN32 | ||
339 | freopen("con","w",stdout); | ||
340 | #else | ||
341 | freopen("/dev/tty","w",stdout); | ||
342 | #endif | ||
343 | if((gettemp->flag & WS_USELEN) == WS_USELEN) { | ||
344 | // determine writelength (for content-length: header) (new on 0.5.1) | ||
345 | tmpstream=node->outstream; | ||
346 | tmp=0; | ||
347 | while(tmpstream->next!=NULL) { // end of header probably in the firsts outstream nodes check for that | ||
348 | if(tmpstream->next->fname!=NULL) { | ||
349 | if(tmpstream->next->fstream==NULL) { | ||
350 | nfile=fopen(tmpstream->next->fname,"rb"); | ||
351 | tmpstream->next->fstream=nfile; // here (corrected on 0.5.3); | ||
352 | } else { | ||
353 | fflush(tmpstream->next->fstream); // <- flush tha thing | ||
354 | nfile=tmpstream->next->fstream; | ||
355 | fseek(nfile,0,SEEK_SET); | ||
356 | }; | ||
357 | if(nfile!=NULL) { | ||
358 | rtmps=0; | ||
359 | while((!node->wheadersize) && (!feof(nfile))) { // wheadersize is 0, suposed to be fast, at least if is not malformed | ||
360 | if(rtmps>0) {tmp-=4;fseek(nfile,rtmps-4,SEEK_SET);} | ||
361 | if((rtmps=fread(rtmp,1,RTMPMAX,nfile))>0) { | ||
362 | rtmp[rtmps]=0; | ||
363 | if((tmp1=strstr(rtmp,"\r\n\r\n"))) { | ||
364 | node->wheadersize=(tmp+((tmp1+4)-rtmp)); | ||
365 | rtmps=((tmp1+4)-rtmp); | ||
366 | |||
367 | }; | ||
368 | if(node->range>0) { | ||
369 | tmp1=realloc(thead,tmp+rtmps+1); | ||
370 | thead=tmp1; | ||
371 | memcpy(thead+tmp,rtmp,rtmps); | ||
372 | thead[tmp+rtmps]=0; | ||
373 | }; | ||
374 | tmp+=rtmps; | ||
375 | }; | ||
376 | }; | ||
377 | fseek(nfile,SEEK_END,SEEK_END); | ||
378 | node->writelength+=(ftell(nfile)-2); | ||
379 | //fclose(nfile); // <- don't worry they close the file later | ||
380 | }; | ||
381 | }; | ||
382 | tmpstream=tmpstream->next; | ||
383 | |||
384 | }; | ||
385 | // end writelength | ||
386 | } else { | ||
387 | node->range=0; // no content-range | ||
388 | }; | ||
389 | |||
390 | if(node->range>node->writelength-node->wheadersize && node->range>0) { | ||
391 | __ILWS_web_client_writef(node,"HTTP/1.1 416 Requested Range Not Satisfiable\r\n"); | ||
392 | __ILWS_web_client_writef(node,"Server: %s\r\n",_libwebserver_version); | ||
393 | __ILWS_web_client_writef(node,"Date: %s\r\n",__ILWS_date(mktime(gmtime(&secs)),"%a, %d %b %Y %H:%M:%S GMT")); // Date header | ||
394 | __ILWS_web_client_writef(node,"Content-range: bytes */%d\r\n",node->writelength-node->wheadersize); | ||
395 | __ILWS_web_client_writef(node,"Content-type: text/html\r\n\r\n<HTML><title>Requested Range Not Satisfiable</title><body bgcolor=FFFFFF><font size=6>416 Requested Range Not Satisfiable</font><BR><BR><small>You're trying to resume an content that is smaller than the requested range</small><BR><HR><small><i>%s</i></small></body></html>\n\r",_libwebserver_version); | ||
396 | tmpl=__ILWS_web_client_getreqline(); | ||
397 | web_log("%s - - [%s] \"%s\" 416 (Requested Range Not Satisfiable)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); | ||
398 | __ILWS_free(tmpl); | ||
399 | node->stat=5; | ||
400 | __ILWS_free(thead); | ||
401 | umask(oumask); | ||
402 | return; | ||
403 | }; | ||
404 | if(node->range>0 && ((node->outstream->flags & WS_DYNVAR)==WS_DYNVAR)) { // if request range interval and dynvar on than produces not implemented | ||
405 | __ILWS_web_client_writef(node,"HTTP/1.1 501 Not Implemented\r\n"); | ||
406 | __ILWS_web_client_writef(node,"Server: %s\r\n",_libwebserver_version); | ||
407 | __ILWS_web_client_writef(node,"Date: %s\r\n",__ILWS_date(mktime(gmtime(&secs)),"%a, %d %b %Y %H:%M:%S GMT")); // Date header | ||
408 | __ILWS_web_client_writef(node,"Content-type: text/html\r\n\r\n<HTML><title>Not implemented</title><body bgcolor=FFFFFF><font size=6>501 Not implemented</font><BR><BR><small>Your trying to resume an content that is not possible to resume(WS_DYNVAR fault)</small><BR><HR><small><i>%s</i></small></body></html>\n\r",_libwebserver_version); | ||
409 | tmpl=__ILWS_web_client_getreqline(); | ||
410 | web_log("%s - - [%s] \"%s\" 501 (Not Implemented)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); | ||
411 | __ILWS_free(tmpl); | ||
412 | node->stat=5; | ||
413 | __ILWS_free(thead); | ||
414 | umask(oumask); | ||
415 | return; | ||
416 | }; | ||
417 | |||
418 | } | ||
419 | node->stat=4; | ||
420 | if(node->HTTPdirective==NULL) { | ||
421 | if(node->range>0) { | ||
422 | __ILWS_web_client_writef(node,"HTTP/1.1 206 Partial Content\r\n"); | ||
423 | tmpl=__ILWS_web_client_getreqline(); | ||
424 | web_log("%s - - [%s] \"%s\" 206 (Partial Content)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); | ||
425 | __ILWS_free(tmpl); | ||
426 | } else { | ||
427 | __ILWS_web_client_writef(node,"HTTP/1.1 200 OK\r\n"); | ||
428 | tmpl=__ILWS_web_client_getreqline(); | ||
429 | web_log("%s - - [%s] \"%s\" 200 (OK)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); | ||
430 | __ILWS_free(tmpl); | ||
431 | }; | ||
432 | |||
433 | } else { | ||
434 | __ILWS_web_client_writef(node,"%s\r\n",node->HTTPdirective); | ||
435 | tmpl=__ILWS_web_client_getreqline(); | ||
436 | web_log("%s - - [%s] \"%s\" XXX (User defined)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); | ||
437 | __ILWS_free(tmpl); | ||
438 | }; | ||
439 | __ILWS_web_client_writef(node,"Server: %s\r\n",_libwebserver_version); | ||
440 | __ILWS_web_client_writef(node,"Date: %s\r\n",__ILWS_date(mktime(gmtime(&secs)),"%a, %d %b %Y %H:%M:%S GMT")); // Date header | ||
441 | __ILWS_web_client_writef(node,"Accept-Ranges: bytes\r\n"); | ||
442 | if((((node->writelength-node->wheadersize)-node->range)>0) && !((node->outstream->flags & WS_DYNVAR)==WS_DYNVAR))__ILWS_web_client_writef(node,"Content-length: %d\r\n",(node->writelength-node->wheadersize)-node->range); | ||
443 | if(node->cookies!=NULL)__ILWS_web_client_writef(node,"%s",node->cookies); // new (0.5.1) | ||
444 | if(node->range>0) { | ||
445 | __ILWS_web_client_writef(node,"Content-range: bytes %d-%d/%d\r\n",node->range,(node->writelength-node->wheadersize)-1,node->writelength-node->wheadersize); | ||
446 | __ILWS_web_client_writef(node,"%s",thead); // the rest of header | ||
447 | __ILWS_free(thead); | ||
448 | }; | ||
449 | umask(oumask); | ||
450 | |||
451 | }; | ||
452 | |||
453 | } | ||
454 | /*********************************************************************************************************/ | ||
455 | /* | ||
456 | * Process stream output | ||
457 | */ | ||
458 | void __ILWS_output_client(struct web_client *node) { | ||
459 | struct outstream *tstream=node->outstream; | ||
460 | char *tmp1,*tmp2,*tmp3; | ||
461 | char writetemp[WRITEMAX+1]; | ||
462 | int beginsize=0; | ||
463 | int endsize=0; | ||
464 | int varsize=0; | ||
465 | int namesize=0; | ||
466 | if(tstream->next!=NULL) { | ||
467 | if(tstream->next->fname!=NULL) { | ||
468 | if(tstream->next->fstream==NULL) { | ||
469 | if((tstream->next->fstream=fopen(tstream->next->fname,"rb"))==NULL) { | ||
470 | __ILWS_delete_next_outstream(tstream); | ||
471 | //node->outstream->next=tstream->next; | ||
472 | return; | ||
473 | } | ||
474 | }; | ||
475 | |||
476 | // read part (must always read) | ||
477 | if(tstream->next->rsize==0) { // start from 0 | ||
478 | fseek(tstream->next->fstream,0,SEEK_SET); | ||
479 | }; | ||
480 | memset(writetemp,0,WRITEMAX); | ||
481 | tstream->next->rsize=fread(writetemp,1,WRITEMAX,tstream->next->fstream); | ||
482 | writetemp[tstream->next->rsize]=0; | ||
483 | // if read make var changes on writetemp; | ||
484 | // new on 0.5.1 -- UNDERDEV // FIX - | ||
485 | if((node->outstream->flags & WS_DYNVAR) == WS_DYNVAR) { | ||
486 | |||
487 | tmp1=writetemp; | ||
488 | while(((tmp1=strstr(tmp1,"$")+1)!=(char*)1) && beginsize==0) { // check var found | ||
489 | for(namesize=0;namesize<50;namesize++) { | ||
490 | if(tmp1[namesize]==';') {namesize++;break;} | ||
491 | if((tmp1[namesize]<'a' || tmp1[namesize]>'z') && | ||
492 | (tmp1[namesize]<'A' || tmp1[namesize]>'Z') && | ||
493 | (tmp1[namesize]<'1' || tmp1[namesize]>'0') && | ||
494 | tmp1[namesize]!='_') {namesize=0;break;}; | ||
495 | |||
496 | }; | ||
497 | if(namesize>0) { | ||
498 | if(namesize==1) { // this is $; for sure | ||
499 | if(!(tmp3=__ILWS_malloc(2))) { | ||
500 | node->stat=5; | ||
501 | return; | ||
502 | }; | ||
503 | memcpy(tmp3,"$",namesize); | ||
504 | tmp3[namesize]=0; | ||
505 | } else { | ||
506 | if(!(tmp3=__ILWS_malloc(namesize))) { | ||
507 | node->stat=5; | ||
508 | return; | ||
509 | }; | ||
510 | memcpy(tmp3,tmp1,namesize-1); | ||
511 | tmp3[namesize-1]=0; | ||
512 | }; | ||
513 | |||
514 | tmp1-=1; | ||
515 | |||
516 | beginsize=tmp1-writetemp; | ||
517 | tmp1+=namesize; // get var from whateverwhere (client node probably) | ||
518 | |||
519 | endsize=strlen(tmp1); | ||
520 | |||
521 | //varsize=2; | ||
522 | |||
523 | if((tmp2=__ILWS_malloc(beginsize+1))) { | ||
524 | memcpy(tmp2,writetemp,beginsize); | ||
525 | tmp2[beginsize]=0; | ||
526 | if(namesize==1) { | ||
527 | varsize=strlen(tmp3); | ||
528 | snprintf(writetemp,WRITEMAX,"%s%s",tmp2,tmp3); | ||
529 | } else { | ||
530 | varsize=strlen(__ILWS_get_var(node->varlist,tmp3)); | ||
531 | snprintf(writetemp,WRITEMAX,"%s%s",tmp2,__ILWS_get_var(node->varlist,tmp3)); | ||
532 | }; | ||
533 | writetemp[strlen(tmp2)+varsize]=0; | ||
534 | __ILWS_free(tmp2); | ||
535 | __ILWS_free(tmp3); | ||
536 | tstream->next->rsize=(beginsize+varsize); | ||
537 | tstream->next->varsize+=(varsize-namesize)-1; | ||
538 | } else { | ||
539 | __ILWS_free(tmp3); | ||
540 | node->stat=5; | ||
541 | return; | ||
542 | }; | ||
543 | }; | ||
544 | }; | ||
545 | }; // dynvar | ||
546 | |||
547 | /* there is nothing more to read here */ | ||
548 | if(tstream->next->rsize<1){ // i guess rsize < 1 is eof (make sure that server writed last time) | ||
549 | //only change if everything written | ||
550 | if(feof(tstream->next->fstream) && (ftell(tstream->next->fstream)==tstream->next->wrotesize)) { | ||
551 | //fclose(tstream->next->fstream); | ||
552 | |||
553 | __ILWS_delete_next_outstream(tstream); | ||
554 | //node->outstream->next=tstream->next; | ||
555 | } | ||
556 | return; | ||
557 | } | ||
558 | node->readsize+=tstream->next->rsize; | ||
559 | if(!node->skipped && node->range>0) { | ||
560 | tstream->next->wsize=tstream->next->rsize; | ||
561 | tstream->next->wrotesize+=tstream->next->wsize; | ||
562 | if((node->readsize-node->wheadersize)<node->range) { // skip range bytes | ||
563 | return; // do nothing | ||
564 | }else { | ||
565 | node->skipped=1; | ||
566 | tstream->next->wrotesize-=(node->readsize-node->wheadersize)-node->range; // the right offset | ||
567 | fseek(tstream->next->fstream,tstream->next->wrotesize,SEEK_SET); | ||
568 | tstream->next->wsize=tstream->next->rsize; | ||
569 | return; | ||
570 | }; | ||
571 | }; | ||
572 | // write part | ||
573 | |||
574 | #ifdef HAVE_OPENSSL | ||
575 | if(node->ssl!=NULL) { | ||
576 | tstream->next->wsize=SSL_write(node->ssl,writetemp,tstream->next->rsize); | ||
577 | } else { | ||
578 | tstream->next->wsize=send(node->socket,writetemp,tstream->next->rsize,0); | ||
579 | }; | ||
580 | #else | ||
581 | tstream->next->wsize=send(node->socket,writetemp,tstream->next->rsize,0); | ||
582 | #endif | ||
583 | if(tstream->next->wsize>0) { | ||
584 | tstream->next->wrotesize+=tstream->next->wsize; | ||
585 | if(tstream->next->rsize!=tstream->next->wsize || beginsize>0) { // FIX | ||
586 | fseek(tstream->next->fstream,tstream->next->wrotesize-(tstream->next->varsize),SEEK_SET); // FIX | ||
587 | }; | ||
588 | }; | ||
589 | #ifdef WIN32 | ||
590 | if((tstream->next->wsize<=0) && (WSAGetLastError()!=WSAEWOULDBLOCK)) { // WIN32 only | ||
591 | #else | ||
592 | if(tstream->next->wsize<=0 && errno!=EAGAIN) { // linux only // *nix i guess | ||
593 | #endif | ||
594 | //fclose(tstream->next->fstream); | ||
595 | |||
596 | __ILWS_delete_next_outstream(tstream); | ||
597 | //node->outstream->next=tstream->next; | ||
598 | return; | ||
599 | }else { // broken pipe | ||
600 | if(tstream->next->wsize<0) { | ||
601 | fseek(tstream->next->fstream,tstream->next->wrotesize-(tstream->next->varsize),SEEK_SET); //didn't read must back to where it was | ||
602 | }; | ||
603 | }; | ||
604 | |||
605 | }else { // filename is null | ||
606 | |||
607 | __ILWS_delete_next_outstream(tstream); | ||
608 | return; | ||
609 | }; | ||
610 | }else { // End of streams | ||
611 | |||
612 | current_web_client->stat=5; // done | ||
613 | |||
614 | }; | ||
615 | } | ||
616 | |||
617 | /*********************************************************************************************************/ | ||
618 | /* | ||
619 | * Set http directive | ||
620 | */ | ||
621 | void web_client_HTTPdirective(char *str) { | ||
622 | current_web_client->HTTPdirective=str; | ||
623 | } | ||
624 | |||
625 | |||
626 | /*********************************************************************************************************/ | ||
627 | /* | ||
628 | * GET request name | ||
629 | */ | ||
630 | char *__ILWS_web_client_getreq() { | ||
631 | char *ret; | ||
632 | char *tmp1=strstr(current_web_client->rbuf,"?"); | ||
633 | char *tmp2=strstr(current_web_client->rbuf," HTTP"); | ||
634 | char *tmp3=strstr(current_web_client->rbuf,"\r\n"); | ||
635 | int size; | ||
636 | if(tmp1==NULL || tmp1>tmp2) { | ||
637 | tmp1=tmp2; | ||
638 | }; | ||
639 | if(tmp2>tmp3) { | ||
640 | return NULL; | ||
641 | }; | ||
642 | size=tmp1-current_web_client->rbuf; | ||
643 | if(size<1) return NULL; | ||
644 | |||
645 | if(!(ret=__ILWS_malloc(size+1))) { | ||
646 | return NULL; | ||
647 | }; | ||
648 | memcpy(ret,current_web_client->rbuf,size); | ||
649 | ret[size]=0; | ||
650 | return ret; | ||
651 | |||
652 | }; | ||
653 | |||
654 | /*********************************************************************************************************/ | ||
655 | /* | ||
656 | * GET request line | ||
657 | */ | ||
658 | char *__ILWS_web_client_getreqline() { | ||
659 | char *ret; | ||
660 | char *tmp1=strstr(current_web_client->rbuf,"\r\n"); | ||
661 | int size=0; | ||
662 | if(tmp1==NULL) return NULL; | ||
663 | size=tmp1-current_web_client->rbuf; | ||
664 | if(size<1) return NULL; | ||
665 | |||
666 | if(!(ret=__ILWS_malloc(size+1))) { | ||
667 | return NULL; | ||
668 | }; | ||
669 | memcpy(ret,current_web_client->rbuf,size); | ||
670 | ret[size]=0; | ||
671 | return ret; | ||
672 | } | ||
673 | |||
674 | |||
675 | /*********************************************************************************************************/ | ||
676 | /* | ||
677 | * Add a FILE stream type to client output | ||
678 | */ | ||
679 | int web_client_addfile(char *in) { | ||
680 | int ret=__ILWS_add_outstream(current_web_client->outstream,in,NULL,0); | ||
681 | int nfd=0; | ||
682 | char *fname; | ||
683 | FILE *nfile=NULL; | ||
684 | fname=__ILWS_tmpfname(); | ||
685 | fflush(stdout); | ||
686 | fclose(stdout); // oldstdout close it? | ||
687 | |||
688 | if((nfile=freopen(fname,"w+b",stdout))!=NULL){ // redirect | ||
689 | flock(fileno(stdout),LOCK_EX); // <- yah | ||
690 | nfd=dup(fileno(stdout)); | ||
691 | nfile=fdopen(nfd,"wb+"); | ||
692 | if(!__ILWS_add_outstream(current_web_client->outstream,fname,nfile,1)) { | ||
693 | return 0; | ||
694 | }; | ||
695 | }; | ||
696 | __ILWS_free(fname); | ||
697 | ClientInfo->outfd=fileno(nfile); | ||
698 | return ret; | ||
699 | } | ||
700 | |||
701 | |||
702 | /*********************************************************************************************************/ | ||
703 | /* | ||
704 | * Output data as gif (with width w and height h) | ||
705 | */ | ||
706 | unsigned char __ILWS_GLOBALGIFPAL[256][3]; | ||
707 | |||
708 | |||
709 | void web_client_gifsetpalette(const char *fname) { | ||
710 | int j; | ||
711 | FILE *palfile; | ||
712 | if(strcmp(fname,"EGA")==0) { | ||
713 | static int EGApalette[16][3] = { | ||
714 | {0,0,0}, {0,0,128}, {0,128,0}, {0,128,128}, | ||
715 | {128,0,0}, {128,0,128}, {128,128,0}, {200,200,200}, | ||
716 | {100,100,100}, {100,100,255}, {100,255,100}, {100,255,255}, | ||
717 | {255,100,100}, {255,100,255}, {255,255,100}, {255,255,255} }; | ||
718 | for (j=0; j<256; j++) { | ||
719 | __ILWS_GLOBALGIFPAL[j][0] = (unsigned char)EGApalette[j&15][0]; | ||
720 | __ILWS_GLOBALGIFPAL[j][1] = (unsigned char)EGApalette[j&15][1]; | ||
721 | __ILWS_GLOBALGIFPAL[j][2] = (unsigned char)EGApalette[j&15][2]; | ||
722 | } | ||
723 | } else { | ||
724 | if(!(palfile=fopen(fname,"rb"))) { | ||
725 | return; | ||
726 | }; | ||
727 | fread(__ILWS_GLOBALGIFPAL,sizeof(__ILWS_GLOBALGIFPAL),1,palfile); | ||
728 | fclose(palfile); | ||
729 | }; | ||
730 | }; | ||
731 | |||
732 | int web_client_gifoutput(char *data,int w,int h,int transparencyindex) { | ||
733 | int i; | ||
734 | unsigned char rm[256],gm[256],bm[256]; | ||
735 | for(i=0;i<256;i++) { | ||
736 | rm[i]=__ILWS_GLOBALGIFPAL[i][0]; | ||
737 | gm[i]=__ILWS_GLOBALGIFPAL[i][1]; | ||
738 | bm[i]=__ILWS_GLOBALGIFPAL[i][2]; | ||
739 | }; | ||
740 | |||
741 | i=__ILWS_WriteGIF(stdout,data,w,h,rm,gm,bm,256,0,transparencyindex,"libwebserver export gif (xvgifwr.c)"); | ||
742 | |||
743 | return i; | ||
744 | }; | ||
745 | |||
746 | |||
747 | /*********************************************************************************************************/ | ||
748 | /* | ||
749 | * an util to write with format on client_nodes | ||
750 | */ | ||
751 | void __ILWS_web_client_writef(struct web_client *node,const char *fmt,...) { | ||
752 | va_list args; | ||
753 | char buf[WRITEMAX]; | ||
754 | va_start(args,fmt); | ||
755 | vsnprintf(buf,512,fmt,args); | ||
756 | va_end(args); | ||
757 | |||
758 | #ifdef HAVE_OPENSSL | ||
759 | if(node->ssl!=NULL) { | ||
760 | SSL_write(node->ssl,buf,strlen(buf)); | ||
761 | } else { | ||
762 | send(node->socket,buf,strlen(buf),0); | ||
763 | }; | ||
764 | #else | ||
765 | send(node->socket,buf,strlen(buf),0); | ||
766 | #endif | ||
767 | } | ||
768 | |||
769 | |||
770 | /*********************************************************************************************************/ | ||
771 | /* | ||
772 | * function "web_client_setcookie" (improved on 0.5.1) to be called what ever were over handler function | ||
773 | * | ||
774 | * name = Name of the cookie | ||
775 | * value = Value of the cookie | ||
776 | * timeout = Timeout in second from current time on | ||
777 | * (0 = Until end of session) | ||
778 | * (-1 = Delete cookie) | ||
779 | * path = Subset of URLs in a domain for which the cookie is valid | ||
780 | * (If the path is not specified (path == NULL), it as assumed to be | ||
781 | * the same path as the document being described by the header which | ||
782 | * contains the cookie.) | ||
783 | * domain = Domain the cookie is valid for | ||
784 | * (If the domain is not set (domain == NULL), the default value of | ||
785 | * domain is the host name of the server which generated the cookie | ||
786 | * response.) | ||
787 | * secure = If a cookie is marked secure (secure == 1), it will only be | ||
788 | * transmitted if the communications channel with the host is a | ||
789 | * secure one. Currently this means that secure cookies will only be | ||
790 | * sent to HTTPS (HTTP over SSL) servers. | ||
791 | * (If secure is not specified (secure == 0), a cookie is considered | ||
792 | * safe to be sent in the clear over unsecured channels. ) | ||
793 | */ | ||
794 | void web_client_setcookie(char *name, char *value, char *timeoutf, char *path, char *domain, int secure) { | ||
795 | char *tmp1=timeoutf; | ||
796 | long toffset=0; | ||
797 | time_t secs; // to time offset | ||
798 | int timeout; | ||
799 | int offset=(current_web_client->cookies!=NULL)?strlen(current_web_client->cookies):0; | ||
800 | if(timeoutf==NULL) { | ||
801 | timeout=0; | ||
802 | } else if (!strcmp(timeoutf,"DEL")){ | ||
803 | timeout=-1; | ||
804 | } else { | ||
805 | while(*tmp1) { | ||
806 | if(*tmp1=='S')toffset=1; // seconds | ||
807 | if(*tmp1=='M')toffset=60; // minutes | ||
808 | if(*tmp1=='H')toffset=60*60; // hours | ||
809 | if(*tmp1=='d')toffset=60*60*24; // days | ||
810 | if(*tmp1=='m')toffset=60*60*24*30; // Month | ||
811 | if(*tmp1=='y')toffset=60*60*24*365; // years | ||
812 | tmp1++; | ||
813 | }; | ||
814 | timeout=atoi(timeoutf)*toffset; | ||
815 | }; | ||
816 | |||
817 | if (timeout < 0){ | ||
818 | current_web_client->cookies=__ILWS_realloc(current_web_client->cookies,offset+59+strlen(name)); | ||
819 | snprintf(current_web_client->cookies+offset,59+strlen(name),"Set-Cookie: %s=deleted; expires=%s", name, __ILWS_date(time(NULL)-31536001,"%a, %d-%b-%Y %H:%M:%S GMT")); | ||
820 | offset+=59+strlen(name); | ||
821 | }else{ | ||
822 | current_web_client->cookies=__ILWS_realloc(current_web_client->cookies,offset+14+strlen(name)+strlen(value)); | ||
823 | snprintf(current_web_client->cookies+offset,14+strlen(name)+strlen(value),"Set-Cookie: %s=%s", name, value); | ||
824 | offset+=13+strlen(name)+strlen(value); | ||
825 | |||
826 | if (timeout != 0){ | ||
827 | //timeout += timezone; Hilobok Andrew (han@km.if.ua) removed this and use gmtime (thanks) | ||
828 | // exchanged by mktime(gmtime(&secs)) | ||
829 | current_web_client->cookies=__ILWS_realloc(current_web_client->cookies,offset+40); | ||
830 | secs=time(NULL); | ||
831 | snprintf(current_web_client->cookies+offset,40,"; expires=%s", __ILWS_date(mktime(gmtime(&secs))+timeout,"%a, %d-%b-%Y %H:%M:%S GMT")); | ||
832 | offset+=39; | ||
833 | } | ||
834 | if (path != NULL && *path!=0) { | ||
835 | current_web_client->cookies=__ILWS_realloc(current_web_client->cookies,offset+8+strlen(path)); | ||
836 | snprintf(current_web_client->cookies+offset,8+strlen(path),"; path=%s", path); | ||
837 | offset+=7+strlen(path); | ||
838 | } | ||
839 | if (domain != NULL && *domain!=0){ | ||
840 | current_web_client->cookies=__ILWS_realloc(current_web_client->cookies,offset+10+strlen(domain)); | ||
841 | snprintf(current_web_client->cookies+offset,10+strlen(domain),"; domain=%s", domain); | ||
842 | offset+=9+strlen(domain); | ||
843 | }; | ||
844 | if (secure == 1) { | ||
845 | current_web_client->cookies=__ILWS_realloc(current_web_client->cookies,offset+9); | ||
846 | snprintf(current_web_client->cookies+offset,9,"; secure"); | ||
847 | offset+=8; | ||
848 | }; | ||
849 | } | ||
850 | |||
851 | current_web_client->cookies=__ILWS_realloc(current_web_client->cookies,offset+3); | ||
852 | snprintf(current_web_client->cookies+offset,3,"\r\n"); // '\0' included | ||
853 | offset+=2; | ||
854 | // fprintf(stderr,"current_web_client->cookies=\"%s\"\n",current_web_client->cookies); // DEBUG TO REMOVE | ||
855 | |||
856 | |||
857 | } | ||
858 | |||
859 | |||
860 | |||
861 | |||
862 | /* | ||
863 | * function "web_client_deletecookie" | ||
864 | * | ||
865 | * name = Name of the cookie to delete | ||
866 | */ | ||
867 | |||
868 | void web_client_deletecookie(char *name){ | ||
869 | web_client_setcookie(name, NULL, "DEL", NULL, NULL, 0); | ||
870 | } | ||
871 | |||
872 | |||
873 | |||
874 | |||
875 | |||
876 | |||
877 | |||
878 | |||
879 | int web_client_setvar(char *name,char *value) { | ||
880 | return __ILWS_add_var(current_web_client->varlist,name,value); | ||
881 | }; | ||
882 | char *web_client_getvar(char *name) { | ||
883 | return __ILWS_get_var(current_web_client->varlist,name); | ||
884 | |||
885 | }; | ||
886 | int web_client_delvar(char *name) { | ||
887 | return __ILWS_del_var(current_web_client->varlist,name); | ||
888 | |||
889 | }; | ||
890 | |||
891 | |||
892 | /*************** | ||
893 | * variables | ||
894 | ***************/ | ||
895 | |||
896 | |||
897 | // prepare this to work in another file var.c | ||
898 | struct web_var *__ILWS_init_var_list() { | ||
899 | struct web_var *ret; | ||
900 | if(!(ret=__ILWS_malloc(sizeof(struct web_var)))) { | ||
901 | return NULL; | ||
902 | }; | ||
903 | ret->name=NULL; | ||
904 | ret->value=NULL; | ||
905 | ret->next=NULL; | ||
906 | return ret; | ||
907 | }; | ||
908 | |||
909 | int __ILWS_add_var(struct web_var *list, char *name, char *value) { | ||
910 | struct web_var *node=list; | ||
911 | int namesize=strlen(name); | ||
912 | int valuesize=strlen(value); | ||
913 | while(node->next!=NULL) { | ||
914 | if(!strcmp(node->next->name,name)) { | ||
915 | return 0; | ||
916 | }; | ||
917 | node=node->next; | ||
918 | }; | ||
919 | |||
920 | if(!(node->next=__ILWS_malloc(sizeof(struct web_var)))) { | ||
921 | return 0; | ||
922 | }; | ||
923 | |||
924 | if(!(node->next->name=__ILWS_malloc(namesize+1))) { | ||
925 | return 0; | ||
926 | }; | ||
927 | memcpy(node->next->name,name,namesize); | ||
928 | node->next->name[namesize]=0; | ||
929 | |||
930 | if(!(node->next->value=__ILWS_malloc(valuesize+1))) { | ||
931 | return 0; | ||
932 | }; | ||
933 | memcpy(node->next->value,value,valuesize); | ||
934 | node->next->value[valuesize]=0; | ||
935 | node->next->next=NULL; | ||
936 | return 1; | ||
937 | }; | ||
938 | |||
939 | int __ILWS_del_var(struct web_var *list, char *name) { | ||
940 | struct web_var *node=list; | ||
941 | struct web_var *tmp; | ||
942 | while(node->next!=NULL) { | ||
943 | if(!strcmp(node->next->name,name)) { | ||
944 | tmp=node->next; | ||
945 | node->next=node->next->next; | ||
946 | __ILWS_free(tmp->name); | ||
947 | __ILWS_free(tmp->value); | ||
948 | __ILWS_free(tmp); | ||
949 | return 1; | ||
950 | }; | ||
951 | }; | ||
952 | return 0; | ||
953 | }; | ||
954 | void __ILWS_delete_var_list(struct web_var *list) { | ||
955 | struct web_var *node=list; | ||
956 | struct web_var *tmp; | ||
957 | |||
958 | while(node->next!=NULL) { | ||
959 | tmp=node->next; | ||
960 | node->next=node->next->next; | ||
961 | __ILWS_free(tmp->name); | ||
962 | __ILWS_free(tmp->value); | ||
963 | |||
964 | __ILWS_free(tmp); | ||
965 | }; | ||
966 | __ILWS_free(node); | ||
967 | }; | ||
968 | |||
969 | |||
970 | char *__ILWS_get_var(struct web_var *list , char *name) { | ||
971 | struct web_var *node=list; | ||
972 | while(node->next!=NULL) { | ||
973 | if(!strcmp(node->next->name,name)) { | ||
974 | return node->next->value; | ||
975 | }; | ||
976 | node=node->next; | ||
977 | }; | ||
978 | return ""; | ||
979 | }; | ||
980 | |||
981 | |||
982 | /**************************** | ||
983 | * give mime by ext (mime file declared on server) | ||
984 | */ | ||
985 | |||
986 | void web_client_contenttype(char *ext) { | ||
987 | FILE *mimefileh; | ||
988 | char *mimedata; | ||
989 | char *mimeline; | ||
990 | size_t extsize; | ||
991 | size_t mimesize; | ||
992 | char *tmp; | ||
993 | /* -- mime */ | ||
994 | int isok=0; | ||
995 | size_t i; | ||
996 | |||
997 | if(ext==NULL || current_web_server->mimefile==NULL) { | ||
998 | printf("Content-type: text/plain\r\n\r\n"); // <- mime type, change this calculating mime with extension | ||
999 | } else { | ||
1000 | extsize=strlen(ext); | ||
1001 | if((mimefileh=fopen(current_web_server->mimefile,"r"))) { | ||
1002 | // retrieve file size | ||
1003 | fseek(mimefileh,SEEK_END,SEEK_END); | ||
1004 | mimesize=ftell(mimefileh); | ||
1005 | fseek(mimefileh,0,SEEK_SET); | ||
1006 | // | ||
1007 | // malloc and read data | ||
1008 | mimedata=__ILWS_malloc(mimesize+1); | ||
1009 | fread(mimedata,1,mimesize,mimefileh); | ||
1010 | fclose(mimefileh); // close file | ||
1011 | // | ||
1012 | for(i=0;i<mimesize;i++)if(mimedata[i]=='\t')mimedata[i]=' '; // translate \t to 1 space | ||
1013 | mimedata[mimesize]=0; | ||
1014 | |||
1015 | isok=0; | ||
1016 | mimeline=strtok(mimedata,"\n"); | ||
1017 | while((mimeline=strtok(NULL,"\n")) && !isok) { | ||
1018 | if(mimeline[0]!='#') { // is not a comment | ||
1019 | tmp=mimeline; | ||
1020 | while((tmp=strstr(tmp,ext)) && !isok) { | ||
1021 | //fprintf(stderr,"extsize(%d),found in %s (%s) %x\n",extsize,mimeline,tmp,tmp[extsize]); | ||
1022 | if(tmp[-1]==' ' && (tmp[extsize]==' ' || tmp[extsize]=='\0') ) { | ||
1023 | if((tmp=strchr(mimeline,' '))) { // the first space? | ||
1024 | tmp[0]='\0'; | ||
1025 | //fprintf(stderr,"content is: %s\n",mimeline); | ||
1026 | printf("Content-type: %s\r\n\r\n",mimeline); | ||
1027 | isok=1; | ||
1028 | }; | ||
1029 | }; | ||
1030 | tmp+=extsize; | ||
1031 | }; | ||
1032 | |||
1033 | }; | ||
1034 | }; | ||
1035 | if(!isok) { | ||
1036 | printf("Content-type: text/plain\r\n\r\n"); | ||
1037 | }; | ||
1038 | //printf("%s\n",tmp); | ||
1039 | __ILWS_free(mimedata); | ||
1040 | |||
1041 | }; | ||
1042 | }; | ||
1043 | }; | ||
1044 | |||
1045 | |||
1046 | /********************************** | ||
1047 | * internal directory generator | ||
1048 | */ | ||
1049 | |||
1050 | int __ILWS_lws_list(char *inpath) { | ||
1051 | /* for type directory */ | ||
1052 | /* mime*/ | ||
1053 | char *ext; | ||
1054 | struct dirent *dire; | ||
1055 | DIR *cd; | ||
1056 | struct stat cfstat; | ||
1057 | char *dirpath=NULL; | ||
1058 | char *filepath; | ||
1059 | char *tmp; | ||
1060 | char *readfile; | ||
1061 | float filesize; | ||
1062 | char filesizeu; | ||
1063 | //// | ||
1064 | |||
1065 | |||
1066 | //printf("ClientInfo->request=<B>%s</B><BR>\n",ClientInfo->request); | ||
1067 | //readfile=__ILWS_malloc(strlen(ClientInfo->request)+1); | ||
1068 | readfile=ClientInfo->request; | ||
1069 | while((tmp=strstr(readfile,"./"))) { // this skip ../ also | ||
1070 | readfile=tmp+1; | ||
1071 | }; | ||
1072 | while((tmp=strstr(readfile,"//"))) { | ||
1073 | readfile=tmp+1; | ||
1074 | }; | ||
1075 | |||
1076 | tmp=strstr(readfile,"/"); | ||
1077 | if(tmp!=NULL) { | ||
1078 | readfile=tmp+1; // must be in the first | ||
1079 | }; | ||
1080 | // skip beind dir | ||
1081 | if(strlen(readfile)) { | ||
1082 | filepath=__ILWS_malloc(strlen(inpath)+strlen(readfile)+3); | ||
1083 | snprintf(filepath,strlen(inpath)+strlen(readfile)+2,"%s%s%s",inpath,(inpath[strlen(inpath)-1]=='/')?"":"/",readfile); | ||
1084 | //printf("pum ->%s<BR>\n",filepath); | ||
1085 | if(readfile[strlen(readfile)-1]=='/') { | ||
1086 | dirpath=__ILWS_malloc(strlen(filepath)+1); | ||
1087 | memcpy(dirpath,filepath,strlen(filepath)+1); // the 0 included | ||
1088 | } else { | ||
1089 | if(!stat(filepath,&cfstat)) { // file must exist | ||
1090 | if((cfstat.st_mode & S_IFDIR) != S_IFDIR) { | ||
1091 | // search for mime | ||
1092 | ext=strrchr(filepath,'.'); | ||
1093 | tmp=strrchr(filepath,'/'); | ||
1094 | ext+=1; | ||
1095 | if(ext<=tmp) { // is not a extension | ||
1096 | ext=NULL; | ||
1097 | }; | ||
1098 | |||
1099 | //Wed, 22 Oct 2003 16:04:04 GMT | ||
1100 | printf("Last-Modified: %s\r\n",__ILWS_date(mktime(gmtime(&cfstat.st_mtime)),"%a, %d %b %Y %H:%M:%S GMT")); // new on 0.5.3 | ||
1101 | web_client_contenttype(ext); | ||
1102 | web_client_addfile(filepath); // fopen and write, maybe? | ||
1103 | __ILWS_free(filepath); | ||
1104 | return 1; | ||
1105 | } else { | ||
1106 | web_client_HTTPdirective("HTTP/1.1 404 File Not Found"); | ||
1107 | printf("Content-type: text/html\r\n\r\n<HTML><title>file not found</title><body bgcolor=FFFFFF><font size=6>404 FILE NOT FOUND</font><BR><BR><small>The request \"%s\" wasn't found, try this <a href='%s/'>link</a></small><BR><HR><small><i>%s</i></small></body></html>\n\r",filepath,ClientInfo->request,_libwebserver_version); | ||
1108 | __ILWS_free(filepath); | ||
1109 | return 0; | ||
1110 | }; | ||
1111 | }else { | ||
1112 | web_client_HTTPdirective("HTTP/1.1 404 File Not Found"); | ||
1113 | printf("Content-type: text/html\r\n\r\n<HTML><title>file not found</title><body bgcolor=FFFFFF><font size=6>404 FILE NOT FOUND</font><BR><BR><small>The request \"%s\" wasn't found</small><BR><HR><small><i>%s</i></small></body></html>\n\r",filepath,_libwebserver_version); | ||
1114 | __ILWS_free(filepath); | ||
1115 | return 0; | ||
1116 | }; | ||
1117 | }; | ||
1118 | __ILWS_free(filepath); | ||
1119 | }; | ||
1120 | //printf("Content-type: text/html\r\n\r\n"); | ||
1121 | //fprintf(stderr,"dirpath=%s inpath=%s\n",dirpath,inpath); | ||
1122 | if(dirpath==NULL) { | ||
1123 | dirpath=__ILWS_malloc(strlen(inpath)+1); | ||
1124 | memcpy(dirpath,inpath,strlen(inpath)+1); | ||
1125 | }; | ||
1126 | cd=opendir(dirpath); | ||
1127 | if(cd!=NULL) { | ||
1128 | printf("Content-type: text/html\r\n\r\n"); | ||
1129 | printf("<HTML><HEAD><TITLE>Contents of %s</TITLE></HEAD><BODY>\n",dirpath); | ||
1130 | printf("<h1>Contents of directory %s</h1><HR>\n",dirpath); | ||
1131 | printf("<form><input type=text name=match value=\"%s\"><input type=submit name='send' value='wildcard'></form>\n",strlen(ClientInfo->Query("match"))?ClientInfo->Query("match"):"*"); | ||
1132 | printf("<PRE>\n"); | ||
1133 | while((dire=readdir(cd))) { | ||
1134 | if( ((dire->d_name[0]!='.') || (strcmp(dirpath,inpath) && !strcmp(dire->d_name,".."))) && (!fnmatch(ClientInfo->Query("match"),dire->d_name,0) || !strlen(ClientInfo->Query("match"))) ) { | ||
1135 | filepath=__ILWS_malloc(strlen(dirpath)+strlen(dire->d_name)+2); | ||
1136 | snprintf(filepath,strlen(dirpath)+strlen(dire->d_name)+2,"%s%s%s",dirpath,(dirpath[strlen(dirpath)-1]=='/')?"":"/",dire->d_name); | ||
1137 | //fprintf(stderr,"filename=%s\n",filepath); | ||
1138 | if(!stat(filepath,&cfstat)) { | ||
1139 | if((cfstat.st_mode & S_IFDIR) == S_IFDIR) { | ||
1140 | printf("%s <DIR> <a href=\"%s/\">%s</a>\n",__ILWS_date(cfstat.st_mtime,"%a, %d %b %Y %H:%M"),dire->d_name,dire->d_name); | ||
1141 | }else { | ||
1142 | filesize=(float)cfstat.st_size; | ||
1143 | filesizeu=0; | ||
1144 | while(filesize>1024) { | ||
1145 | filesize/=1024; | ||
1146 | filesizeu++; | ||
1147 | }; | ||
1148 | printf("%s %.1f%c <a href=\"%s\">%s</a>\n",__ILWS_date(cfstat.st_mtime,"%a, %d %b %Y %H:%M"),filesize,(filesizeu==2)?'M':(filesizeu==1)?'K':'b',dire->d_name,dire->d_name); | ||
1149 | }; | ||
1150 | }; | ||
1151 | __ILWS_free(filepath); | ||
1152 | }; | ||
1153 | |||
1154 | }; | ||
1155 | printf("</PRE>\n"); | ||
1156 | printf("<HR>\n"); | ||
1157 | printf("<address>%s</address>\n",_libwebserver_version); | ||
1158 | printf("</BODY></HTML>\r\n"); | ||
1159 | __ILWS_free(dirpath); | ||
1160 | closedir(cd); | ||
1161 | } else { | ||
1162 | web_client_HTTPdirective("HTTP/1.1 404 File Not Found"); | ||
1163 | printf("Content-type: text/html\r\n\r\n<HTML><title>file not found</title><body bgcolor=FFFFFF><font size=6>404 FILE NOT FOUND</font><BR><BR><small>The request \"%s\" wasn't found</small><BR><HR><small><i>%s</i></small></body></html>\n\r",dirpath,_libwebserver_version); | ||
1164 | return 0; | ||
1165 | }; | ||
1166 | return 1; | ||
1167 | }; | ||
1168 | |||
1169 | |||
1170 | |||
1171 | |||