source: titan/titan/httpd.h @ 15272

Last change on this file since 15272 was 14619, checked in by gost, 10 years ago

[titan] Download videos via WebIf

File size: 14.3 KB
Line 
1#ifndef HTTPD_H
2#define HTTPD_H
3
4char* getmimetype(char* name, char* mime)
5{
6        char* dot;
7
8        if(mime != NULL) return mime;
9        if(name == NULL) return "text/html";
10
11        dot = strrchr( name, '.' );
12        if(dot == NULL || strcmp(dot, ".html") == 0 || strcmp(dot, ".htm") == 0)
13                return "text/html";
14        if(strcmp(dot, ".jpg") == 0 || strcmp( dot, ".jpeg" ) == 0)
15                return "image/jpeg";
16        if(strcmp(dot, ".gif") == 0)
17                return "image/gif";
18        if(strcmp(dot, ".png") == 0)
19                return "image/png";
20        if(strcmp(dot, ".css") == 0)
21                return "text/css";
22        if(strcmp(dot, ".au") == 0)
23                return "audio/basic";
24        if(strcmp(dot, ".wav") == 0)
25                return "audio/wav";
26        if(strcmp(dot, ".avi") == 0)
27                return "video/x-msvideo";
28        if(strcmp(dot, ".mov") == 0 || strcmp(dot, ".qt" ) == 0)
29                return "video/quicktime";
30        if(strcmp(dot, ".mpeg") == 0 || strcmp(dot, ".mpe" ) == 0)
31                return "video/mpeg";
32        if(strcmp(dot, ".ts") == 0)
33                return "video/MP2T";   
34        if(strcmp(dot, ".vrml") == 0 || strcmp(dot, ".wrl" ) == 0)
35                return "model/vrml";
36        if(strcmp(dot, ".midi") == 0 || strcmp(dot, ".mid" ) == 0)
37                return "audio/midi";
38        if(strcmp(dot, ".mp3") == 0)
39                return "audio/mpeg";
40        if(strcmp(dot, ".ogg") == 0)
41                return "application/ogg";
42        if(strcmp(dot, ".pac") == 0)
43                return "application/x-ns-proxy-autoconfig";
44
45        return "text/html";
46}
47
48char* createheader(off64_t len, char* filename, char* mime, char* ext, int code, int auth)
49{
50        char* header = NULL, *buf = NULL;
51        time_t now = time(NULL);
52
53        buf = malloc(100);
54        if(buf == NULL)
55        {
56                err("no mem");
57                return NULL;
58        }
59
60        if(auth == 1) code=401;
61        switch(code)
62        {
63                case 200:
64                        header = ostrcat(header, "HTTP/1.1 200 OK\r\n", 1, 0);
65                        break;
66                case 302:
67                        header = ostrcat(header, "HTTP/1.1 302 Found\r\n", 1, 0);
68                        break;
69                case 401:
70                        header = ostrcat(header, "HTTP/1.1 401 Unauthorized\r\n", 1, 0);
71                        break;
72                case 500:
73                        header = ostrcat(header, "HTTP/1.1 500 Internal Server Error\r\n", 1, 0);
74                        break;
75        }
76
77        snprintf(buf, 99, "Server: %s\r\n", PROGNAME);
78        header = ostrcat(header, buf, 1, 0);
79
80        if(auth == 1)
81        {
82                snprintf(buf, 99, "WWW-Authenticate: Basic realm=\"Contol Panel\"\r\n");
83                header = ostrcat(header, buf, 1, 0);
84        }
85
86        strftime(buf, 99, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", gmtime(&now));
87        header = ostrcat(header, buf, 1, 0);
88
89        header = ostrcat(header, "Content-Type: ", 1, 0);
90        header = ostrcat(header, getmimetype(filename, mime), 1, 0);
91        header = ostrcat(header, "\r\n", 1, 0);
92
93        if(auth == 1) len = 0;
94        snprintf(buf, 99, "Content-Length: %lld\r\n", len);
95        header = ostrcat(header, buf, 1, 0);
96
97        strftime(buf, 99, "Expires: %a, %d %b %Y %H:%M:%S GMT\r\n", gmtime(&now));
98        header = ostrcat(header, buf, 1, 0);
99
100        if(filename != NULL)
101        {
102                now = getfiletime(filename, 1);
103                strftime(buf, 99, "Last-Modified: %a, %d %b %Y %H:%M:%S GMT\r\n", gmtime(&now));
104                header = ostrcat(header, buf, 1, 0);
105        }
106
107        if(ext != NULL)
108        {
109                header = ostrcat(header, ext, 1, 0);
110                header = ostrcat(header, "\r\n", 1, 0);
111        }
112
113        header = ostrcat(header, "Connection: close\r\n", 1, 0);
114        header = ostrcat(header, "\r\n", 1, 0);
115
116        free(buf);
117        return header;
118}
119
120void senderror(int* connfd, char* title, char* text, int auth)
121{
122        char* buf = NULL, *header = NULL;;
123
124        buf = ostrcat(buf, "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><link rel=stylesheet type=text/css href=titan.css><title>Error ", 1, 0);
125        buf = ostrcat(buf, title, 1, 0);
126        buf = ostrcat(buf, "</title></head><body class=body><font class=error>Error - ", 1, 0);
127        buf = ostrcat(buf, text, 1, 0);
128        buf = ostrcat(buf, "</font></body></html>", 1, 0);
129
130        header = createheader(strlen(buf), NULL, NULL, NULL, 500, auth);
131
132        socksend(connfd, (unsigned char*)header, strlen(header), 5000 * 1000);
133        socksend(connfd, (unsigned char*)buf, strlen(buf), 5000 * 1000);
134
135        free(header);
136        free(buf);
137}
138
139void checkquery(int* connfd, char* query, int auth)
140{
141        char* buf = NULL, *header = NULL, *param = NULL;
142        char* ext = NULL, *mime = NULL;
143        int buflen = 0, onlyheader = 0, code = 200;
144
145        //create param
146        param = strchr(query, '&');
147        if(param != NULL)
148                *param++ = '\0';
149
150        if(ostrcmp(query, "sendrc") == 0)
151                websendrc(param);
152        if(ostrcmp(query, "getrectimer") == 0)
153                buf = webgetrectimer(param, 0);
154        if(ostrcmp(query, "addrectimer") == 0)
155                buf = webaddrectimer(param);
156        if(ostrcmp(query, "delrectimer") == 0)
157                buf = webdelrectimer(param);
158        if(ostrcmp(query, "editrectimer") == 0)
159                buf = webeditrectimer(param);
160        if(ostrcmp(query, "rectimersend") == 0)
161                buf = webrectimersend(param);
162        if(ostrcmp(query, "getrectimerarchive") == 0)
163                buf = webgetrectimer(param, 1);
164        if(ostrcmp(query, "setvol") == 0)
165                buf = websetvol(param);
166        if(ostrcmp(query, "setmute") == 0)
167                buf = websetmute(param);
168        if(ostrcmp(query, "getbouquet") == 0)
169                buf = webgetbouquet();
170        if(ostrcmp(query, "getsat") == 0)
171                buf = webgetsat();
172        if(ostrcmp(query, "getprovider") == 0)
173                buf = webgetprovider();
174        if(ostrcmp(query, "getaz") == 0)
175                buf = webgetaz();
176        if(ostrcmp(query, "getchannelpage") == 0)
177                buf = webgetchannelpage(param);
178        if(ostrcmp(query, "getallchannel") == 0)
179                buf = webgetchannel(0, 0, 1);
180        if(ostrcmp(query, "getbouquetchannel") == 0)
181                buf = webgetbouquetchannel(param);
182        if(ostrcmp(query, "getsatchannel") == 0 && param != NULL)
183                buf = webgetchannel(atoi(param), 1, 1);
184        if(ostrcmp(query, "getproviderchannel") == 0 && param != NULL)
185                buf = webgetchannel(atoi(param), 2, 1);
186        if(ostrcmp(query, "getazchannel") == 0 && param != NULL)
187                buf = webgetchannel(atoi(param), 3, 1);
188        if(ostrcmp(query, "switch") == 0)
189                buf = webswitch(param);
190        if(ostrcmp(query, "getaktservice") == 0)
191                buf = webgetaktservice();
192        if(ostrcmp(query, "getepg") == 0)
193                buf = webgetepg(param);
194        if(ostrcmp(query, "getmovieepg") == 0)
195                buf = webgetmovieepg(param, getconfig("rec_streampath", NULL), 1);
196        if(ostrcmp(query, "getsingleepg") == 0)
197                buf = webgetsingleepg(param);
198        if(ostrcmp(query, "getgmultiepg") == 0)
199                buf = webgetgmultiepg(param);
200        if(query != NULL && strstr(query, "getepgsearch") == query)
201                buf = webgetepgsearch(query, param);
202        if(ostrcmp(query, "getsignal") == 0)
203                buf = webgetsignal();
204        if(ostrcmp(query, "getmoviefilelist") == 0)
205                buf = webgetfilelist(param, "getmoviefilelist", "delmoviefile", getconfig("rec_streampath", NULL), "*.avi *.dat *.divx *.flv *.mkv *.m4v *.mp4 *.mov *.mpg *.mpeg *.mts *.m2ts *.trp *.ts *.vdr *.vob *.wmv *.rm", 31);
206        if(ostrcmp(query, "delmoviefile") == 0)
207                buf = webdelfile(param, "getmoviefilelist", "delmoviefile", getconfig("rec_streampath", NULL), "*.avi *.dat *.divx *.flv *.mkv *.m4v *.mp4 *.mov *.mpg *.mpeg *.mts *.m2ts *.trp *.ts *.vdr *.vob *.wmv *.rm", 31);
208        if(ostrcmp(query, "getm3u") == 0)
209        {
210                buf = webgetm3u(param, *connfd);
211                ext = "Content-Disposition: attachment; filename=stream.m3u";
212                mime = "text/plain";
213        }
214        if(ostrcmp(query, "getvideo") == 0)
215                buf = webgetvideo(param, *connfd);
216        if(ostrcmp(query, "getshoot") == 0)
217        {
218                webgetshoot(param);
219                ext = "Location: shoot.html";
220                onlyheader = 1;
221                code = 302;
222        }
223        if(query != NULL && strstr(query, "poweroff") == query)
224                oshutdown(1, 1);
225        if(query != NULL && strstr(query, "restart") == query)
226                oshutdown(2, 1);
227        if(query != NULL && strstr(query, "guirestart") == query)
228                oshutdown(3, 1);
229        if(query != NULL && strstr(query, "standby") == query)
230        {
231                status.standby = 2;
232                addtimer(&screenstandby, START, 1000, 1, NULL, NULL, NULL);
233        }
234        if(query != NULL && strstr(query, "boxstatus") == query)
235        {
236                if(status.standby > 0)
237                        sendoktext(connfd, "standby", auth);
238                else
239                        sendoktext(connfd, "running", auth);
240        }
241        if(query != NULL && strstr(query, "message") == query)
242                buf = websendmessage(query);
243               
244        if(buf != NULL || onlyheader == 1)
245        {
246                if(buflen == 0 && onlyheader == 0) buflen = strlen(buf);
247
248                header = createheader(buflen, NULL, mime, ext, code, auth);
249                socksend(connfd, (unsigned char*)header, strlen(header), 5000 * 1000);
250                if(onlyheader == 0 && auth == 0)
251                        socksend(connfd, (unsigned char*)buf, buflen, 5000 * 1000);
252        }
253        else
254                senderror(connfd, "query", "Error in query string", auth);
255
256        free(header);
257        free(buf);
258}
259
260void gotdata(int* connfd)
261{
262        int ret = 0, filefd = -1, auth = 0;
263        unsigned char* buf = NULL;
264        char* tmpstr = NULL, *tmpstr1 = NULL, *filename = NULL, *fullfilename = NULL, *header = NULL, *query = NULL;
265
266        buf = malloc(MINMALLOC);
267        if(buf == NULL)
268        {
269                err("no mem");
270                sockclose(connfd);
271                return;
272        }
273        memset(buf, 0, MINMALLOC);
274
275        debug(250, "get client data");
276
277        //read one line
278        unsigned char* pbuf = buf;
279        while(pbuf - buf < MINMALLOC)
280        {
281                unsigned char c;
282
283                ret = sockreceive(connfd, &c, 1, 5000 * 1000);
284                if(ret != 0)
285                {
286                        err("no client data in buffer");
287                        break;
288                }
289
290                *pbuf = c;
291                if(buf != NULL && (strstr((char*)buf, "\n\n") != NULL || strstr((char*)buf, "\r\n\r\n") != NULL))
292                        break;
293                pbuf++;
294        }
295
296        if(buf != NULL)
297        {
298                tmpstr = strstr((char*)buf, "GET /");
299                tmpstr1 = strstr((char*)buf, "Authorization: Basic ");
300        }
301
302        //Auth Password
303        if(status.httpauth != NULL)
304        {
305                if(tmpstr1 != NULL)
306                {
307                        tmpstr1 += 21;
308                        char* tmpstr3 = malloc(255);
309                        if(tmpstr3 != NULL)
310                        {
311                                int l = b64dec(tmpstr3, tmpstr1);
312                                if(l < 255) tmpstr3[l] = '\0';
313                        }
314                        if(ostrncmp(tmpstr3, status.httpauth, strlen(status.httpauth)) != 0)
315                        {
316                                //not ok:
317                                tmpstr1 = NULL;
318                        }
319                        free(tmpstr3); tmpstr3 = NULL;
320                }
321       
322                if(tmpstr1 == NULL) auth = 1;
323        }
324
325        if(tmpstr != NULL)
326        {
327                tmpstr += 4;
328
329                filename = malloc(MINMALLOC);
330                if(filename == NULL)
331                {
332                        err("no mem");
333                        sockclose(connfd);
334                        free(buf); buf = NULL;
335                        tmpstr = NULL;
336                        return;
337                }
338                memset(filename, 0, MINMALLOC);
339
340                ret = sscanf(tmpstr, "%s", filename);
341                if(ret == 1)
342                {
343                        htmldecode(filename, filename);
344                       
345                        if(strstr(filename, "xmessage") == filename + 1  || strstr(filename, "/cgi-bin/xmessage") == filename )
346                        {       
347                                xmessage(filename);
348                                sendoktext(connfd, "ok", 0);
349                                //senderror(connfd, "ok", "ok", 0);
350                                free(buf); buf = NULL;
351                                free(filename); filename = NULL;
352                                tmpstr = NULL;
353                                return;
354                        }
355
356                        //create query
357                        query = strchr(filename, '?');
358                        if(query != NULL)
359                        {
360                                *query++ = '\0';
361                                debug(250, "httpd query=%s", query);
362                        }
363
364                        //query
365                        if(ostrcmp(filename, "/query") == 0 && query != NULL)
366                        {
367                                checkquery(connfd, query, auth);
368                                free(buf); buf = NULL;
369                                free(filename); filename = NULL;
370                                tmpstr = NULL;
371                                return;
372                        }
373
374                        //create index.html
375                        if(filename[strlen(filename) - 1] == '/')
376                                filename = ostrcat(filename, "index.html", 1, 0);
377
378                        debug(250, "httpd filename=%s", filename);
379
380                        if(strstr(filename, "/movie/") != NULL)
381                                fullfilename = ostrcat(filename,"", 0, 0);
382                        else
383                                fullfilename = ostrcat(getconfig("httpdpath", NULL), filename, 0, 0);
384                        filefd = open(fullfilename, O_RDONLY | O_LARGEFILE);
385                        if(filefd < 0)
386                        {
387                                perr("open filename=%s", fullfilename);
388                                senderror(connfd, "Open File", "Can't open File", auth);
389                                free(fullfilename); fullfilename = NULL;
390                                free(buf); buf = NULL;
391                                free(filename); filename = NULL;
392                                tmpstr = NULL;
393                                return;
394                        }
395                        debug(250, "sende OK response to client");
396                        char* rpath = realpath(fullfilename, NULL);
397                        header = createheader(getfilesize(rpath), fullfilename, NULL, NULL, 200, auth);
398                        free(rpath); rpath = NULL;
399                        free(fullfilename); fullfilename = NULL;
400                        ret = socksend(connfd, (unsigned char*)header, strlen(header), 5000 * 1000);
401                        free(header); header = NULL;
402
403                        if(ret != 0)
404                        {
405                                sockclose(connfd);
406                                free(buf); buf = NULL;
407                                free(filename); filename = NULL;
408                                tmpstr = NULL;
409                                return;
410                        }
411
412                        //TODO:
413                        int readret = 1;
414                        while(readret > 0 && auth == 0)
415                        {
416                                readret = dvbreadfd(filefd, buf, 0, MINMALLOC, 1000);
417                                if(readret > 0)
418                                        socksend(connfd, buf, readret, 5000 * 1000);
419                        }
420                }
421        }
422
423        close(filefd);
424        free(buf); buf = NULL;
425        free(filename); filename = NULL;
426        tmpstr = NULL;
427}
428
429int newconn(int* streamfd, int* connfd)
430{
431        int i, fd = -1;
432
433        fd = sockaccept(streamfd, 1);
434        if(fd < 0) return -1;
435
436        for(i = 0; i < MAXHTTPDCONN; i++)
437        {
438                if(connfd[i] < 0)
439                {
440                        connfd[i] = fd;
441                        debug(250, "accept httpd connection fd=%d", fd);
442                        fd = -1;
443                        break;
444                }
445        }
446
447        if(fd != -1)
448        {
449                debug(250, "all connections in use");
450                sockclose(&fd);
451                return -1;
452        }
453
454        return 0;
455}
456
457void httpdthreadfunc(struct stimerthread* timernode)
458{
459        struct timeval timeout;
460        fd_set rfds;
461        int i, ret = 0, streamfd = -1, connfd[MAXHTTPDCONN], maxfd = -1;
462
463        debug(250, "Starting httpd thread");
464
465        for(i = 0; i < MAXHTTPDCONN; i++)
466                connfd[i] = -1;
467
468        while(timernode->aktion != STOP)
469        {
470                if(streamfd < 0)
471                {
472                        sockportcreate(&streamfd, getconfigint("httpdport", NULL), MAXHTTPDCONN);
473                        if(streamfd < 0) break;
474                        maxfd = streamfd;
475
476                        //set nonblocking
477                        fcntl(streamfd, F_SETFL, fcntl(streamfd, F_GETFL) | O_NONBLOCK);
478                }
479
480                timeout.tv_sec = 1;
481                timeout.tv_usec = 0;
482
483                FD_ZERO(&rfds);
484                FD_SET(streamfd, &rfds);
485
486                for(i = 0; i < MAXHTTPDCONN; i++)
487                {
488                        if(connfd[i] > -1)
489                        {
490                                FD_SET(connfd[i], &rfds);
491                                if(connfd[i] > maxfd) maxfd = connfd[i];
492                        }
493                }
494
495                ret = TEMP_FAILURE_RETRY(select(maxfd + 1, &rfds , NULL, NULL, &timeout));
496
497                if(ret < 0)
498                {
499                        perr("httpd listen socket fd=%d", maxfd);
500                        sleep(1);
501                        continue;
502                }
503                if(ret == 0) continue; //timeout
504
505                if(FD_ISSET(streamfd, &rfds))
506                {
507                        ret = newconn(&streamfd, connfd);
508                        if(ret < 0) continue;
509                }
510
511                for(i = 0; i < MAXHTTPDCONN; i++)
512                {
513                        if(connfd[i] > -1 && FD_ISSET(connfd[i], &rfds))
514                                gotdata(&connfd[i]);
515                }
516        }
517
518        debug(250, "Stopping httpd thread");
519        sockclose(&streamfd);
520        for(i = 0; i < MAXHTTPDCONN; i++)
521                sockclose(&connfd[i]);
522
523        return;
524}
525
526void sendoktext(int* connfd, char* text, int auth)
527{
528        char* buf = NULL;
529        char* header = NULL;
530        buf = webcreatehead(buf, NULL, 1);
531        buf = ostrcat(buf, "<tr><td align=center valign=top><font class=biglabel><br><br>", 1, 0);
532        buf = ostrcat(buf, text, 1, 0);
533        buf = ostrcat(buf, "</font></td></tr>", 1, 0);
534        buf = webcreatetail(buf, 1);
535        int buflen = strlen(buf);
536        header = createheader(buflen, NULL, NULL, NULL, 200, auth);
537        socksend(connfd, (unsigned char*)header, strlen(header), 5000 * 1000);
538        if(auth == 0)
539                socksend(connfd, (unsigned char*)buf, buflen, 5000 * 1000);
540        free(buf); buf=NULL;
541        free(header); header=NULL;
542}
543
544#endif
Note: See TracBrowser for help on using the repository browser.