source: titan/titan/httpd.h @ 15345

Last change on this file since 15345 was 15345, checked in by nit, 10 years ago

[titan] extend html api

File size: 15.1 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, int fmt)
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, "getrccodes") == 0)
151                webgetrccodes(fmt);
152        if(ostrcmp(query, "getmute") == 0)
153                webgetmute(fmt);
154        if(ostrcmp(query, "getvol") == 0)
155                webgetvol(fmt);
156        if(ostrcmp(query, "sendrc") == 0)
157                websendrc(param, fmt);
158        if(ostrcmp(query, "getrectimer") == 0)
159                buf = webgetrectimer(param, 0, fmt);
160        if(ostrcmp(query, "addrectimer") == 0)
161                buf = webaddrectimer(param, fmt);
162        if(ostrcmp(query, "delrectimer") == 0)
163                buf = webdelrectimer(param, fmt);
164        if(ostrcmp(query, "editrectimer") == 0)
165                buf = webeditrectimer(param, fmt);
166        if(ostrcmp(query, "rectimersend") == 0)
167                buf = webrectimersend(param, fmt);
168        if(ostrcmp(query, "getrectimerarchive") == 0)
169                buf = webgetrectimer(param, 1, fmt);
170        if(ostrcmp(query, "setvol") == 0)
171                buf = websetvol(param, fmt);
172        if(ostrcmp(query, "setmute") == 0)
173                buf = websetmute(param, fmt);
174        if(ostrcmp(query, "getbouquet") == 0)
175                buf = webgetbouquet(fmt);
176        if(ostrcmp(query, "getsat") == 0)
177                buf = webgetsat(fmt);
178        if(ostrcmp(query, "getprovider") == 0)
179                buf = webgetprovider(fmt);
180        if(ostrcmp(query, "getaz") == 0)
181                buf = webgetaz(fmt);
182        if(ostrcmp(query, "getchannelpage") == 0)
183                buf = webgetchannelpage(param, fmt);
184        if(ostrcmp(query, "getallchannel") == 0)
185                buf = webgetchannel(0, 0, 1, fmt);
186        if(ostrcmp(query, "getbouquetchannel") == 0)
187                buf = webgetbouquetchannel(param, fmt);
188        if(ostrcmp(query, "getsatchannel") == 0 && param != NULL)
189                buf = webgetchannel(atoi(param), 1, 1, fmt);
190        if(ostrcmp(query, "getproviderchannel") == 0 && param != NULL)
191                buf = webgetchannel(atoi(param), 2, 1, fmt);
192        if(ostrcmp(query, "getazchannel") == 0 && param != NULL)
193                buf = webgetchannel(atoi(param), 3, 1, fmt);
194        if(ostrcmp(query, "switch") == 0)
195                buf = webswitch(param, fmt);
196        if(ostrcmp(query, "getaktservice") == 0)
197                buf = webgetaktservice(fmt);
198        if(ostrcmp(query, "getepg") == 0)
199                buf = webgetepg(param, fmt);
200        if(ostrcmp(query, "getmovieepg") == 0)
201                buf = webgetmovieepg(param, getconfig("rec_streampath", NULL), 1, fmt);
202        if(ostrcmp(query, "getsingleepg") == 0)
203                buf = webgetsingleepg(param, fmt);
204        if(ostrcmp(query, "getgmultiepg") == 0)
205                buf = webgetgmultiepg(param, fmt);
206        if(query != NULL && strstr(query, "getepgsearch") == query)
207                buf = webgetepgsearch(query, param, fmt);
208        if(ostrcmp(query, "getsignal") == 0)
209                buf = webgetsignal(fmt);
210        if(ostrcmp(query, "getmoviefilelist") == 0)
211                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, fmt);
212        if(ostrcmp(query, "delmoviefile") == 0)
213                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, fmt);
214        if(ostrcmp(query, "getm3u") == 0)
215        {
216                buf = webgetm3u(param, *connfd, fmt);
217                if(fmt == 0)
218                {
219                        ext = "Content-Disposition: attachment; filename=stream.m3u";
220                        mime = "text/plain";
221                }
222        }
223        if(ostrcmp(query, "getvideo") == 0)
224                buf = webgetvideo(param, *connfd, fmt);
225        if(ostrcmp(query, "getshoot") == 0)
226        {
227                webgetshoot(param, fmt);
228                if(fmt == 0)
229                {
230                        ext = "Location: shoot.html";
231                        onlyheader = 1;
232                        code = 302;
233                }
234                else
235                        buf = ostrcat("shoot.html", NULL, 0, 0);
236        }
237        if(query != NULL && strstr(query, "poweroff") == query)
238                oshutdown(1, 1);
239        if(query != NULL && strstr(query, "restart") == query)
240                oshutdown(2, 1);
241        if(query != NULL && strstr(query, "guirestart") == query)
242                oshutdown(3, 1);
243        if(query != NULL && strstr(query, "standby") == query)
244        {
245                status.standby = 2;
246                addtimer(&screenstandby, START, 1000, 1, NULL, NULL, NULL);
247        }
248        if(query != NULL && strstr(query, "boxstatus") == query)
249        {
250                if(status.standby > 0)
251                {
252                        if(fmt == 0)
253                                sendoktext(connfd, "standby", auth);
254                        else
255                                buf = ostrcat("standby", NULL, 0, 0);
256                }
257                else
258                {
259                        if(fmt == 0)
260                                sendoktext(connfd, "running", auth);
261                        else
262                                buf = ostrcat("running", NULL, 0, 0);
263                }
264        }
265        if(query != NULL && strstr(query, "message") == query)
266                buf = websendmessage(query, fmt);
267               
268        if(buf != NULL || onlyheader == 1)
269        {
270                if(buflen == 0 && onlyheader == 0) buflen = strlen(buf);
271
272                header = createheader(buflen, NULL, mime, ext, code, auth);
273                socksend(connfd, (unsigned char*)header, strlen(header), 5000 * 1000);
274                if(onlyheader == 0 && auth == 0)
275                        socksend(connfd, (unsigned char*)buf, buflen, 5000 * 1000);
276        }
277        else
278                senderror(connfd, "query", "Error in query string", auth);
279
280        free(header);
281        free(buf);
282}
283
284void gotdata(int* connfd)
285{
286        int ret = 0, filefd = -1, auth = 0;
287        unsigned char* buf = NULL;
288        char* tmpstr = NULL, *tmpstr1 = NULL, *filename = NULL, *fullfilename = NULL, *header = NULL, *query = NULL;
289
290        buf = malloc(MINMALLOC);
291        if(buf == NULL)
292        {
293                err("no mem");
294                sockclose(connfd);
295                return;
296        }
297        memset(buf, 0, MINMALLOC);
298
299        debug(250, "get client data");
300
301        //read one line
302        unsigned char* pbuf = buf;
303        while(pbuf - buf < MINMALLOC)
304        {
305                unsigned char c;
306
307                ret = sockreceive(connfd, &c, 1, 5000 * 1000);
308                if(ret != 0)
309                {
310                        err("no client data in buffer");
311                        break;
312                }
313
314                *pbuf = c;
315                if(buf != NULL && (strstr((char*)buf, "\n\n") != NULL || strstr((char*)buf, "\r\n\r\n") != NULL))
316                        break;
317                pbuf++;
318        }
319
320        if(buf != NULL)
321        {
322                tmpstr = strstr((char*)buf, "GET /");
323                tmpstr1 = strstr((char*)buf, "Authorization: Basic ");
324        }
325
326        //Auth Password
327        if(status.httpauth != NULL)
328        {
329                if(tmpstr1 != NULL)
330                {
331                        tmpstr1 += 21;
332                        char* tmpstr3 = malloc(255);
333                        if(tmpstr3 != NULL)
334                        {
335                                int l = b64dec(tmpstr3, tmpstr1);
336                                if(l < 255) tmpstr3[l] = '\0';
337                        }
338                        if(ostrncmp(tmpstr3, status.httpauth, strlen(status.httpauth)) != 0)
339                        {
340                                //not ok:
341                                tmpstr1 = NULL;
342                        }
343                        free(tmpstr3); tmpstr3 = NULL;
344                }
345       
346                if(tmpstr1 == NULL) auth = 1;
347        }
348
349        if(tmpstr != NULL)
350        {
351                tmpstr += 4;
352
353                filename = malloc(MINMALLOC);
354                if(filename == NULL)
355                {
356                        err("no mem");
357                        sockclose(connfd);
358                        free(buf); buf = NULL;
359                        tmpstr = NULL;
360                        return;
361                }
362                memset(filename, 0, MINMALLOC);
363
364                ret = sscanf(tmpstr, "%s", filename);
365                if(ret == 1)
366                {
367                        htmldecode(filename, filename);
368                       
369                        if(strstr(filename, "xmessage") == filename + 1  || strstr(filename, "/cgi-bin/xmessage") == filename )
370                        {       
371                                xmessage(filename);
372                                sendoktext(connfd, "ok", 0);
373                                //senderror(connfd, "ok", "ok", 0);
374                                free(buf); buf = NULL;
375                                free(filename); filename = NULL;
376                                tmpstr = NULL;
377                                return;
378                        }
379
380                        //create query
381                        query = strchr(filename, '?');
382                        if(query != NULL)
383                        {
384                                *query++ = '\0';
385                                debug(250, "httpd query=%s", query);
386                        }
387
388                        //queryraw
389                        if(ostrcmp(filename, "/queryraw") == 0 && query != NULL)
390                        {
391                                checkquery(connfd, query, auth, 1);
392                                free(buf); buf = NULL;
393                                free(filename); filename = NULL;
394                                tmpstr = NULL;
395                                return;
396                        }
397
398                        //query
399                        if(ostrcmp(filename, "/query") == 0 && query != NULL)
400                        {
401                                checkquery(connfd, query, auth, 0);
402                                free(buf); buf = NULL;
403                                free(filename); filename = NULL;
404                                tmpstr = NULL;
405                                return;
406                        }
407
408                        //create index.html
409                        if(filename[strlen(filename) - 1] == '/')
410                                filename = ostrcat(filename, "index.html", 1, 0);
411
412                        debug(250, "httpd filename=%s", filename);
413
414                        if(strstr(filename, "/movie/") != NULL)
415                                fullfilename = ostrcat(filename,"", 0, 0);
416                        else
417                                fullfilename = ostrcat(getconfig("httpdpath", NULL), filename, 0, 0);
418                        filefd = open(fullfilename, O_RDONLY | O_LARGEFILE);
419                        if(filefd < 0)
420                        {
421                                perr("open filename=%s", fullfilename);
422                                senderror(connfd, "Open File", "Can't open File", auth);
423                                free(fullfilename); fullfilename = NULL;
424                                free(buf); buf = NULL;
425                                free(filename); filename = NULL;
426                                tmpstr = NULL;
427                                return;
428                        }
429                        debug(250, "sende OK response to client");
430                        char* rpath = realpath(fullfilename, NULL);
431                        header = createheader(getfilesize(rpath), fullfilename, NULL, NULL, 200, auth);
432                        free(rpath); rpath = NULL;
433                        free(fullfilename); fullfilename = NULL;
434                        ret = socksend(connfd, (unsigned char*)header, strlen(header), 5000 * 1000);
435                        free(header); header = NULL;
436
437                        if(ret != 0)
438                        {
439                                sockclose(connfd);
440                                free(buf); buf = NULL;
441                                free(filename); filename = NULL;
442                                tmpstr = NULL;
443                                return;
444                        }
445
446                        //TODO:
447                        int readret = 1;
448                        while(readret > 0 && auth == 0)
449                        {
450                                readret = dvbreadfd(filefd, buf, 0, MINMALLOC, 1000);
451                                if(readret > 0)
452                                        socksend(connfd, buf, readret, 5000 * 1000);
453                        }
454                }
455        }
456
457        close(filefd);
458        free(buf); buf = NULL;
459        free(filename); filename = NULL;
460        tmpstr = NULL;
461}
462
463int newconn(int* streamfd, int* connfd)
464{
465        int i, fd = -1;
466
467        fd = sockaccept(streamfd, 1);
468        if(fd < 0) return -1;
469
470        for(i = 0; i < MAXHTTPDCONN; i++)
471        {
472                if(connfd[i] < 0)
473                {
474                        connfd[i] = fd;
475                        debug(250, "accept httpd connection fd=%d", fd);
476                        fd = -1;
477                        break;
478                }
479        }
480
481        if(fd != -1)
482        {
483                debug(250, "all connections in use");
484                sockclose(&fd);
485                return -1;
486        }
487
488        return 0;
489}
490
491void httpdthreadfunc(struct stimerthread* timernode)
492{
493        struct timeval timeout;
494        fd_set rfds;
495        int i, ret = 0, streamfd = -1, connfd[MAXHTTPDCONN], maxfd = -1;
496
497        debug(250, "Starting httpd thread");
498
499        for(i = 0; i < MAXHTTPDCONN; i++)
500                connfd[i] = -1;
501
502        while(timernode->aktion != STOP)
503        {
504                if(streamfd < 0)
505                {
506                        sockportcreate(&streamfd, getconfigint("httpdport", NULL), MAXHTTPDCONN);
507                        if(streamfd < 0) break;
508                        maxfd = streamfd;
509
510                        //set nonblocking
511                        fcntl(streamfd, F_SETFL, fcntl(streamfd, F_GETFL) | O_NONBLOCK);
512                }
513
514                timeout.tv_sec = 1;
515                timeout.tv_usec = 0;
516
517                FD_ZERO(&rfds);
518                FD_SET(streamfd, &rfds);
519
520                for(i = 0; i < MAXHTTPDCONN; i++)
521                {
522                        if(connfd[i] > -1)
523                        {
524                                FD_SET(connfd[i], &rfds);
525                                if(connfd[i] > maxfd) maxfd = connfd[i];
526                        }
527                }
528
529                ret = TEMP_FAILURE_RETRY(select(maxfd + 1, &rfds , NULL, NULL, &timeout));
530
531                if(ret < 0)
532                {
533                        perr("httpd listen socket fd=%d", maxfd);
534                        sleep(1);
535                        continue;
536                }
537                if(ret == 0) continue; //timeout
538
539                if(FD_ISSET(streamfd, &rfds))
540                {
541                        ret = newconn(&streamfd, connfd);
542                        if(ret < 0) continue;
543                }
544
545                for(i = 0; i < MAXHTTPDCONN; i++)
546                {
547                        if(connfd[i] > -1 && FD_ISSET(connfd[i], &rfds))
548                                gotdata(&connfd[i]);
549                }
550        }
551
552        debug(250, "Stopping httpd thread");
553        sockclose(&streamfd);
554        for(i = 0; i < MAXHTTPDCONN; i++)
555                sockclose(&connfd[i]);
556
557        return;
558}
559
560void sendoktext(int* connfd, char* text, int auth)
561{
562        char* buf = NULL;
563        char* header = NULL;
564        buf = webcreatehead(buf, NULL, 1);
565        buf = ostrcat(buf, "<tr><td align=center valign=top><font class=biglabel><br><br>", 1, 0);
566        buf = ostrcat(buf, text, 1, 0);
567        buf = ostrcat(buf, "</font></td></tr>", 1, 0);
568        buf = webcreatetail(buf, 1);
569        int buflen = strlen(buf);
570        header = createheader(buflen, NULL, NULL, NULL, 200, auth);
571        socksend(connfd, (unsigned char*)header, strlen(header), 5000 * 1000);
572        if(auth == 0)
573                socksend(connfd, (unsigned char*)buf, buflen, 5000 * 1000);
574        free(buf); buf=NULL;
575        free(header); header=NULL;
576}
577
578#endif
Note: See TracBrowser for help on using the repository browser.