/* * tvheadend, WEBUI / HTML user interface * Copyright (C) 2008 Andreas Öman * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #define _GNU_SOURCE /* for splice() */ #include #include #include #include #include #include #include #include #include #include "tvhead.h" #include "access.h" #include "http.h" #include "webui.h" #include "dvr/dvr.h" static int is_client_simple(http_connection_t *hc) { char *c; if((c = http_arg_get(&hc->hc_args, "UA-OS")) != NULL) { if(strstr(c, "Windows CE") || strstr(c, "Pocket PC")) return 1; } if((c = http_arg_get(&hc->hc_args, "x-wap-profile")) != NULL) { return 1; } return 0; } /** * Root page, we direct the client to different pages depending * on if it is a full blown browser or just some mobile app */ static int page_root(http_connection_t *hc, const char *remain, void *opaque) { if(is_client_simple(hc)) { http_redirect(hc, "/simple.html"); } else { http_redirect(hc, "/extjs.html"); } return 0; } /** * Static download of a file from the filesystem */ static int page_static(http_connection_t *hc, const char *remain, void *opaque) { int fd; const char *rootpath = HTS_BUILD_ROOT "/tvheadend/webui/static"; char path[500]; struct stat st; const char *content = NULL, *postfix; if(strstr(remain, "..")) return HTTP_STATUS_BAD_REQUEST; postfix = strrchr(remain, '.'); if(postfix != NULL) { postfix++; if(!strcmp(postfix, "js")) content = "text/javascript; charset=UTF-8"; } snprintf(path, sizeof(path), "%s/%s", rootpath, remain); if((fd = open(path, O_RDONLY)) < 0) return 404; if(fstat(fd, &st) < 0) { close(fd); return 404; } http_send_header(hc, 200, content, st.st_size, NULL, NULL, 10); sendfile(hc->hc_fd, fd, NULL, st.st_size); close(fd); return 0; } /** * Download a recorded file */ static int page_dvrfile(http_connection_t *hc, const char *remain, void *opaque) { int fd; struct stat st; const char *content = NULL, *postfix, *range; dvr_entry_t *de; char *fname; if(remain == NULL) return 404; pthread_mutex_lock(&global_lock); de = dvr_entry_find_by_id(atoi(remain)); if(de == NULL || de->de_filename == NULL) { pthread_mutex_unlock(&global_lock); return 404; } fname = strdup(de->de_filename); pthread_mutex_unlock(&global_lock); postfix = strrchr(remain, '.'); if(postfix != NULL) { postfix++; if(!strcmp(postfix, "mkv")) content = "video/x-matroska"; } fd = open(fname, O_RDONLY); free(fname); if(fd < 0) return 404; if(fstat(fd, &st) < 0) { close(fd); return 404; } range = http_arg_get(&hc->hc_args, "Range"); #if 0 if(range != NULL) { printf("Range req: %s\n", range); } #endif http_send_header(hc, 200, content, st.st_size, NULL, NULL, 10); sendfile(hc->hc_fd, fd, NULL, st.st_size); close(fd); return 0; } /** * WEB user interface */ void webui_init(void) { http_path_add("/", NULL, page_root, ACCESS_WEB_INTERFACE); http_path_add("/static", NULL, page_static, ACCESS_WEB_INTERFACE); http_path_add("/dvrfile", NULL, page_dvrfile, ACCESS_WEB_INTERFACE); // simpleui_start(); extjs_start(); comet_init(); }