mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2025-01-03 14:56:34 -05:00
sync with master excluding change in r18364.
svn path=/icecast/branches/ph3/icecast/; revision=19273
This commit is contained in:
parent
6be7448832
commit
bc1ff182df
@ -279,7 +279,7 @@ void admin_send_response (xmlDocPtr doc, client_t *client,
|
||||
len = util_http_build_header(client->refbuf->data, buf_len, 0,
|
||||
0, 200, NULL,
|
||||
"text/xml", "utf-8",
|
||||
NULL);
|
||||
NULL, NULL);
|
||||
len += snprintf (client->refbuf->data + len, buf_len - len, "Content-Length: %d\r\n\r\n%s", xmlStrlen(buff), buff);
|
||||
|
||||
client->refbuf->len = len;
|
||||
@ -573,7 +573,7 @@ static void html_success(client_t *client, char *message)
|
||||
ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
|
||||
0, 200, NULL,
|
||||
"text/html", "utf-8",
|
||||
"");
|
||||
"", NULL);
|
||||
snprintf(client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret,
|
||||
"<html><head><title>Admin request successful</title></head>"
|
||||
"<body><p>%s</p></body></html>", message);
|
||||
@ -712,7 +712,7 @@ static void command_buildm3u(client_t *client, const char *mount)
|
||||
ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
|
||||
0, 200, NULL,
|
||||
"audio/x-mpegurl", NULL,
|
||||
NULL);
|
||||
NULL, NULL);
|
||||
|
||||
config = config_get_config();
|
||||
snprintf (client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret,
|
||||
@ -1032,7 +1032,7 @@ static void command_list_mounts(client_t *client, int response)
|
||||
util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
|
||||
0, 200, NULL,
|
||||
"text/plain", "utf-8",
|
||||
"");
|
||||
"", NULL);
|
||||
client->refbuf->len = strlen (client->refbuf->data);
|
||||
client->respcode = 200;
|
||||
|
||||
|
193
src/cfgfile.c
193
src/cfgfile.c
@ -59,7 +59,7 @@
|
||||
#define CONFIG_DEFAULT_GROUP NULL
|
||||
#define CONFIG_MASTER_UPDATE_INTERVAL 120
|
||||
#define CONFIG_YP_URL_TIMEOUT 10
|
||||
#define CONFIG_DEFAULT_CIPHER_LIST "ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM"
|
||||
#define CONFIG_DEFAULT_CIPHER_LIST "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS"
|
||||
|
||||
#ifndef _WIN32
|
||||
#define CONFIG_DEFAULT_BASE_DIR "/usr/local/icecast"
|
||||
@ -87,6 +87,8 @@ static void _parse_logging(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
|
||||
static void _parse_security(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
|
||||
static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node,
|
||||
ice_config_t *c);
|
||||
static void _parse_http_headers(xmlDocPtr doc, xmlNodePtr node,
|
||||
ice_config_http_header_t **http_headers);
|
||||
static void _parse_relay(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
|
||||
static void _parse_mount(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
|
||||
static void _parse_listen_socket(xmlDocPtr doc, xmlNodePtr node,
|
||||
@ -124,6 +126,58 @@ void config_init_configuration(ice_config_t *configuration)
|
||||
_set_defaults(configuration);
|
||||
}
|
||||
|
||||
static void config_clear_http_header(ice_config_http_header_t *header) {
|
||||
ice_config_http_header_t *old;
|
||||
|
||||
while (header) {
|
||||
xmlFree(header->name);
|
||||
xmlFree(header->value);
|
||||
old = header;
|
||||
header = header->next;
|
||||
free(old);
|
||||
}
|
||||
}
|
||||
|
||||
static inline ice_config_http_header_t * config_copy_http_header(ice_config_http_header_t *header) {
|
||||
ice_config_http_header_t *ret = NULL;
|
||||
ice_config_http_header_t *cur = NULL;
|
||||
ice_config_http_header_t *old = NULL;
|
||||
|
||||
while (header) {
|
||||
if (cur) {
|
||||
cur->next = calloc(1, sizeof(ice_config_http_header_t));
|
||||
old = cur;
|
||||
cur = cur->next;
|
||||
} else {
|
||||
ret = calloc(1, sizeof(ice_config_http_header_t));
|
||||
cur = ret;
|
||||
}
|
||||
|
||||
if (!cur) return ret; /* TODO: do better error handling */
|
||||
|
||||
cur->type = header->type;
|
||||
cur->name = (char *)xmlCharStrdup(header->name);
|
||||
cur->value = (char *)xmlCharStrdup(header->value);
|
||||
cur->status = header->status;
|
||||
|
||||
if (!cur->name || !cur->value) {
|
||||
if (cur->name) xmlFree(cur->name);
|
||||
if (cur->value) xmlFree(cur->value);
|
||||
if (old) {
|
||||
old->next = NULL;
|
||||
} else {
|
||||
ret = NULL;
|
||||
}
|
||||
free(cur);
|
||||
return ret;
|
||||
}
|
||||
|
||||
header = header->next;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void config_clear_mount (mount_proxy *mount)
|
||||
{
|
||||
config_options_t *option;
|
||||
@ -156,6 +210,7 @@ static void config_clear_mount (mount_proxy *mount)
|
||||
option = nextopt;
|
||||
}
|
||||
auth_release (mount->auth);
|
||||
config_clear_http_header(mount->http_headers);
|
||||
free (mount);
|
||||
}
|
||||
|
||||
@ -295,6 +350,8 @@ void config_clear(ice_config_t *c)
|
||||
while ((c->cpis = config_clear_cpi (c->cpis)))
|
||||
;
|
||||
|
||||
config_clear_http_header(c->http_headers);
|
||||
|
||||
memset(c, 0, sizeof(ice_config_t));
|
||||
}
|
||||
|
||||
@ -476,9 +533,13 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node,
|
||||
_parse_plugins(doc, node->xmlChildrenNode, configuration);
|
||||
} else if (xmlStrcmp (node->name, XMLSTR("port")) == 0) {
|
||||
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
configuration->port = atoi(tmp);
|
||||
configuration->listen_sock->port = atoi(tmp);
|
||||
if (tmp) xmlFree(tmp);
|
||||
if (tmp) {
|
||||
configuration->port = atoi(tmp);
|
||||
configuration->listen_sock->port = atoi(tmp);
|
||||
xmlFree(tmp);
|
||||
} else {
|
||||
ICECAST_LOG_WARN("<port> must not be empty.");
|
||||
}
|
||||
} else if (xmlStrcmp (node->name, XMLSTR("bind-address")) == 0) {
|
||||
if (configuration->listen_sock->bind_address)
|
||||
xmlFree(configuration->listen_sock->bind_address);
|
||||
@ -505,6 +566,8 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node,
|
||||
configuration->shoutcast_mount = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
} else if (xmlStrcmp (node->name, XMLSTR("limits")) == 0) {
|
||||
_parse_limits(doc, node->xmlChildrenNode, configuration);
|
||||
} else if (xmlStrcmp (node->name, XMLSTR("http-headers")) == 0) {
|
||||
_parse_http_headers(doc, node->xmlChildrenNode, &(configuration->http_headers));
|
||||
} else if (xmlStrcmp (node->name, XMLSTR("relay")) == 0) {
|
||||
_parse_relay(doc, node->xmlChildrenNode, configuration);
|
||||
} else if (xmlStrcmp (node->name, XMLSTR("mount")) == 0) {
|
||||
@ -741,6 +804,8 @@ static void _parse_mount(xmlDocPtr doc, xmlNodePtr node,
|
||||
} else if (xmlStrcmp (node->name, XMLSTR("subtype")) == 0) {
|
||||
mount->subtype = (char *)xmlNodeListGetString(
|
||||
doc, node->xmlChildrenNode, 1);
|
||||
} else if (xmlStrcmp (node->name, XMLSTR("http-headers")) == 0) {
|
||||
_parse_http_headers(doc, node->xmlChildrenNode, &(mount->http_headers));
|
||||
}
|
||||
} while ((node = node->next));
|
||||
|
||||
@ -775,6 +840,63 @@ static void _parse_mount(xmlDocPtr doc, xmlNodePtr node,
|
||||
configuration->mounts = mount;
|
||||
}
|
||||
|
||||
static void _parse_http_headers(xmlDocPtr doc, xmlNodePtr node, ice_config_http_header_t **http_headers) {
|
||||
ice_config_http_header_t *header;
|
||||
ice_config_http_header_t *next;
|
||||
char *name = NULL;
|
||||
char *value = NULL;
|
||||
char *tmp;
|
||||
int status;
|
||||
http_header_type type;
|
||||
|
||||
do {
|
||||
if (node == NULL) break;
|
||||
if (xmlIsBlankNode(node)) continue;
|
||||
if (xmlStrcmp (node->name, XMLSTR("header")) != 0) break;
|
||||
if (!(name = (char *)xmlGetProp(node, XMLSTR("name")))) break;
|
||||
if (!(value = (char *)xmlGetProp(node, XMLSTR("value")))) break;
|
||||
|
||||
type = HTTP_HEADER_TYPE_STATIC; /* default */
|
||||
if ((tmp = (char *)xmlGetProp(node, XMLSTR("type")))) {
|
||||
if (strcmp(tmp, "static") == 0) {
|
||||
type = HTTP_HEADER_TYPE_STATIC;
|
||||
} else {
|
||||
ICECAST_LOG_WARN("Unknown type %s for HTTP Header %s", tmp, name);
|
||||
xmlFree(tmp);
|
||||
break;
|
||||
}
|
||||
xmlFree(tmp);
|
||||
}
|
||||
|
||||
status = 0; /* default: any */
|
||||
if ((tmp = (char *)xmlGetProp(node, XMLSTR("status")))) {
|
||||
status = atoi(tmp);
|
||||
xmlFree(tmp);
|
||||
}
|
||||
|
||||
header = calloc(1, sizeof(ice_config_http_header_t));
|
||||
if (!header) break;
|
||||
header->type = type;
|
||||
header->name = name;
|
||||
header->value = value;
|
||||
header->status = status;
|
||||
name = NULL;
|
||||
value = NULL;
|
||||
|
||||
if (!*http_headers) {
|
||||
*http_headers = header;
|
||||
continue;
|
||||
}
|
||||
next = *http_headers;
|
||||
while (next->next) next = next->next;
|
||||
next->next = header;
|
||||
} while ((node = node->next));
|
||||
/* in case we used break we may need to clean those up */
|
||||
if (name)
|
||||
xmlFree(name);
|
||||
if (value)
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
static void _parse_relay(xmlDocPtr doc, xmlNodePtr node,
|
||||
ice_config_t *configuration)
|
||||
@ -811,8 +933,12 @@ static void _parse_relay(xmlDocPtr doc, xmlNodePtr node,
|
||||
}
|
||||
else if (xmlStrcmp (node->name, XMLSTR("port")) == 0) {
|
||||
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
relay->port = atoi(tmp);
|
||||
if(tmp) xmlFree(tmp);
|
||||
if (tmp) {
|
||||
relay->port = atoi(tmp);
|
||||
xmlFree(tmp);
|
||||
} else {
|
||||
ICECAST_LOG_WARN("<port> must not be empty.");
|
||||
}
|
||||
}
|
||||
else if (xmlStrcmp (node->name, XMLSTR("mount")) == 0) {
|
||||
if (relay->mount) xmlFree (relay->mount);
|
||||
@ -869,10 +995,14 @@ static void _parse_listen_socket(xmlDocPtr doc, xmlNodePtr node,
|
||||
|
||||
if (xmlStrcmp (node->name, XMLSTR("port")) == 0) {
|
||||
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
if(configuration->port == 0)
|
||||
configuration->port = atoi(tmp);
|
||||
listener->port = atoi(tmp);
|
||||
if(tmp) xmlFree(tmp);
|
||||
if (tmp) {
|
||||
if(configuration->port == 0)
|
||||
configuration->port = atoi(tmp);
|
||||
listener->port = atoi(tmp);
|
||||
xmlFree(tmp);
|
||||
} else {
|
||||
ICECAST_LOG_WARN("<port> must not be empty.");
|
||||
}
|
||||
}
|
||||
else if (xmlStrcmp (node->name, XMLSTR("ssl")) == 0) {
|
||||
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
@ -1119,8 +1249,12 @@ static void _parse_paths(xmlDocPtr doc, xmlNodePtr node,
|
||||
if (configuration->base_dir) xmlFree(configuration->base_dir);
|
||||
configuration->base_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
} else if (xmlStrcmp (node->name, XMLSTR("logdir")) == 0) {
|
||||
if (!(temp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1))) {
|
||||
ICECAST_LOG_WARN("<logdir> must not be empty.");
|
||||
continue;
|
||||
}
|
||||
if (configuration->log_dir) xmlFree(configuration->log_dir);
|
||||
configuration->log_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
configuration->log_dir = temp;
|
||||
} else if (xmlStrcmp (node->name, XMLSTR("pidfile")) == 0) {
|
||||
if (configuration->pidfile) xmlFree(configuration->pidfile);
|
||||
configuration->pidfile = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
@ -1137,14 +1271,22 @@ static void _parse_paths(xmlDocPtr doc, xmlNodePtr node,
|
||||
if (configuration->cipher_list) xmlFree(configuration->cipher_list);
|
||||
configuration->cipher_list = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
} else if (xmlStrcmp (node->name, XMLSTR("webroot")) == 0) {
|
||||
if (!(temp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1))) {
|
||||
ICECAST_LOG_WARN("<webroot> must not be empty.");
|
||||
continue;
|
||||
}
|
||||
if (configuration->webroot_dir) xmlFree(configuration->webroot_dir);
|
||||
configuration->webroot_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
configuration->webroot_dir = temp;
|
||||
if(configuration->webroot_dir[strlen(configuration->webroot_dir)-1] == '/')
|
||||
configuration->webroot_dir[strlen(configuration->webroot_dir)-1] = 0;
|
||||
} else if (xmlStrcmp (node->name, XMLSTR("adminroot")) == 0) {
|
||||
if (!(temp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1))) {
|
||||
ICECAST_LOG_WARN("<adminroot> must not be empty.");
|
||||
continue;
|
||||
}
|
||||
if (configuration->adminroot_dir)
|
||||
xmlFree(configuration->adminroot_dir);
|
||||
configuration->adminroot_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
configuration->adminroot_dir = (char *)temp;
|
||||
if(configuration->adminroot_dir[strlen(configuration->adminroot_dir)-1] == '/')
|
||||
configuration->adminroot_dir[strlen(configuration->adminroot_dir)-1] = 0;
|
||||
} else if (xmlStrcmp (node->name, XMLSTR("alias")) == 0) {
|
||||
@ -1189,16 +1331,25 @@ static void _parse_paths(xmlDocPtr doc, xmlNodePtr node,
|
||||
static void _parse_logging(xmlDocPtr doc, xmlNodePtr node,
|
||||
ice_config_t *configuration)
|
||||
{
|
||||
char *tmp;
|
||||
do {
|
||||
if (node == NULL) break;
|
||||
if (xmlIsBlankNode(node)) continue;
|
||||
|
||||
if (xmlStrcmp (node->name, XMLSTR("accesslog")) == 0) {
|
||||
if (!(tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1))) {
|
||||
ICECAST_LOG_WARN("<accesslog> must not be empty.");
|
||||
continue;
|
||||
}
|
||||
if (configuration->access_log) xmlFree(configuration->access_log);
|
||||
configuration->access_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
configuration->access_log = tmp;
|
||||
} else if (xmlStrcmp (node->name, XMLSTR("errorlog")) == 0) {
|
||||
if (!(tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1))) {
|
||||
ICECAST_LOG_WARN("<errorlog> must not be empty.");
|
||||
continue;
|
||||
}
|
||||
if (configuration->error_log) xmlFree(configuration->error_log);
|
||||
configuration->error_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
configuration->error_log = tmp;
|
||||
} else if (xmlStrcmp (node->name, XMLSTR("playlistlog")) == 0) {
|
||||
if (configuration->playlist_log) xmlFree(configuration->playlist_log);
|
||||
configuration->playlist_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
@ -1299,6 +1450,9 @@ static void _add_server(xmlDocPtr doc, xmlNodePtr node,
|
||||
}
|
||||
|
||||
static void merge_mounts(mount_proxy * dst, mount_proxy * src) {
|
||||
ice_config_http_header_t *http_header_next;
|
||||
ice_config_http_header_t **http_header_tail;
|
||||
|
||||
if (!dst || !src)
|
||||
return;
|
||||
|
||||
@ -1360,6 +1514,15 @@ static void merge_mounts(mount_proxy * dst, mount_proxy * src) {
|
||||
dst->subtype = (char*)xmlStrdup((xmlChar*)src->subtype);
|
||||
if (dst->yp_public == -1)
|
||||
dst->yp_public = src->yp_public;
|
||||
|
||||
if (dst->http_headers) {
|
||||
http_header_next = dst->http_headers;
|
||||
while (http_header_next->next) http_header_next = http_header_next->next;
|
||||
http_header_tail = &(http_header_next->next);
|
||||
} else {
|
||||
http_header_tail = &(dst->http_headers);
|
||||
}
|
||||
*http_header_tail = config_copy_http_header(src->http_headers);
|
||||
}
|
||||
|
||||
static inline void _merge_mounts_all(ice_config_t *c) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
* This program is distributed under the GNU General Public License, version 2.
|
||||
* A copy of this license is included with this source.
|
||||
*
|
||||
* Copyright 2000-2004, Jack Moffitt <jack@xiph.org,
|
||||
* Copyright 2000-2004, Jack Moffitt <jack@xiph.org>,
|
||||
* Michael Smith <msmith@xiph.org>,
|
||||
* oddsock <oddsock@xiph.org>,
|
||||
* Karl Heyes <karl@xiph.org>
|
||||
@ -32,8 +32,27 @@ struct _mount_proxy;
|
||||
|
||||
#define XMLSTR(str) ((xmlChar *)(str))
|
||||
|
||||
typedef struct ice_config_dir_tag
|
||||
{
|
||||
typedef enum _http_header_type {
|
||||
/* static: headers are passed as is to the client. */
|
||||
HTTP_HEADER_TYPE_STATIC
|
||||
} http_header_type;
|
||||
|
||||
typedef struct ice_config_http_header_tag {
|
||||
/* type of this header. See http_header_type */
|
||||
http_header_type type;
|
||||
|
||||
/* name and value of the header */
|
||||
char *name;
|
||||
char *value;
|
||||
|
||||
/* filters */
|
||||
int status;
|
||||
|
||||
/* link to the next list element */
|
||||
struct ice_config_http_header_tag *next;
|
||||
} ice_config_http_header_t;
|
||||
|
||||
typedef struct ice_config_dir_tag {
|
||||
char *host;
|
||||
int touch_interval;
|
||||
struct ice_config_dir_tag *next;
|
||||
@ -79,6 +98,8 @@ typedef struct _mount_proxy {
|
||||
char *charset; /* character set if not utf8 */
|
||||
int mp3_meta_interval; /* outgoing per-stream metadata interval */
|
||||
|
||||
ice_config_http_header_t *http_headers; /* additional HTTP headers */
|
||||
|
||||
char *auth_type; /* Authentication type */
|
||||
struct auth_tag *auth;
|
||||
char *cluster_password;
|
||||
@ -131,8 +152,7 @@ typedef struct _cpi_t {
|
||||
int autoload;
|
||||
} cpi_t;
|
||||
|
||||
typedef struct ice_config_tag
|
||||
{
|
||||
typedef struct ice_config_tag {
|
||||
char *config_filename;
|
||||
|
||||
char *location;
|
||||
@ -173,6 +193,8 @@ typedef struct ice_config_tag
|
||||
char *master_username;
|
||||
char *master_password;
|
||||
|
||||
ice_config_http_header_t *http_headers;
|
||||
|
||||
relay_server *relay;
|
||||
|
||||
mount_proxy *mounts;
|
||||
@ -238,6 +260,3 @@ void config_release_config(void);
|
||||
ice_config_t *config_get_config_unlocked(void);
|
||||
|
||||
#endif /* __CFGFILE_H__ */
|
||||
|
||||
|
||||
|
||||
|
@ -190,7 +190,7 @@ static void client_send_error(client_t *client, int status, int plain, const cha
|
||||
ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
|
||||
0, status, NULL,
|
||||
plain ? "text/plain" : "text/html", "utf-8",
|
||||
plain ? message : "");
|
||||
plain ? message : "", NULL);
|
||||
|
||||
if (!plain)
|
||||
snprintf(client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret,
|
||||
|
@ -204,7 +204,11 @@ static void get_ssl_certificate (ice_config_t *config)
|
||||
method = SSLv23_server_method();
|
||||
ssl_ctx = SSL_CTX_new (method);
|
||||
ssl_opts = SSL_CTX_get_options (ssl_ctx);
|
||||
SSL_CTX_set_options (ssl_ctx, ssl_opts|SSL_OP_NO_SSLv2);
|
||||
#ifdef SSL_OP_NO_COMPRESSION
|
||||
SSL_CTX_set_options (ssl_ctx, ssl_opts|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_COMPRESSION);
|
||||
#else
|
||||
SSL_CTX_set_options (ssl_ctx, ssl_opts|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3);
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -299,7 +299,7 @@ static int format_prepare_headers (source_t *source, client_t *client)
|
||||
ptr = client->refbuf->data;
|
||||
client->respcode = 200;
|
||||
|
||||
bytes = util_http_build_header (ptr, remaining, 0, 0, 200, NULL, source->format->contenttype, NULL, NULL);
|
||||
bytes = util_http_build_header (ptr, remaining, 0, 0, 200, NULL, source->format->contenttype, NULL, NULL, source);
|
||||
|
||||
remaining -= bytes;
|
||||
ptr += bytes;
|
||||
|
@ -458,7 +458,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
|
||||
httpclient->respcode = 200;
|
||||
ret = util_http_build_header (httpclient->refbuf->data, BUFSIZE, 0,
|
||||
0, 200, NULL,
|
||||
"audio/x-mpegurl", NULL, "");
|
||||
"audio/x-mpegurl", NULL, "", NULL);
|
||||
if (host == NULL)
|
||||
{
|
||||
config = config_get_config();
|
||||
@ -501,7 +501,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
|
||||
config = config_get_config();
|
||||
if (config->fileserve == 0)
|
||||
{
|
||||
ICECAST_LOG_DEBUG("on demand file \"%H\" refused", fullpath);
|
||||
ICECAST_LOG_DEBUG("on demand file \"%H\" refused. Serving static files has been disabled in the config", fullpath);
|
||||
client_send_404 (httpclient, "The file you requested could not be found");
|
||||
config_release_config();
|
||||
free (fullpath);
|
||||
@ -567,7 +567,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
|
||||
bytes = util_http_build_header (httpclient->refbuf->data, BUFSIZE, 0,
|
||||
0, 206, NULL,
|
||||
type, NULL,
|
||||
NULL);
|
||||
NULL, NULL);
|
||||
bytes += snprintf (httpclient->refbuf->data + bytes, BUFSIZE - bytes,
|
||||
"Accept-Ranges: bytes\r\n"
|
||||
"Content-Length: %" PRI_OFF_T "\r\n"
|
||||
@ -593,7 +593,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
|
||||
bytes = util_http_build_header (httpclient->refbuf->data, BUFSIZE, 0,
|
||||
0, 200, NULL,
|
||||
type, NULL,
|
||||
NULL);
|
||||
NULL, NULL);
|
||||
bytes += snprintf (httpclient->refbuf->data + bytes, BUFSIZE - bytes,
|
||||
"Accept-Ranges: bytes\r\n"
|
||||
"Content-Length: %" PRI_OFF_T "\r\n\r\n",
|
||||
|
18
src/main.c
18
src/main.c
@ -209,6 +209,16 @@ static int _parse_config_opts(int argc, char **argv, char *filename, int size)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _start_logging_stdout(void) {
|
||||
errorlog = log_open_file(stderr);
|
||||
if ( errorlog < 0 )
|
||||
return 0;
|
||||
|
||||
log_set_level(errorlog, 2 /* WARN */);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _start_logging(void)
|
||||
{
|
||||
char fn_error[FILENAME_MAX];
|
||||
@ -227,8 +237,7 @@ static int _start_logging(void)
|
||||
log_set_trigger (errorlog, config->logsize);
|
||||
log_set_archive_timestamp(errorlog, config->logarchive);
|
||||
} else {
|
||||
errorlog = log_open_file(stderr);
|
||||
log_to_stderr = 1;
|
||||
/* this is already in place because of _start_logging_stdout() */
|
||||
}
|
||||
|
||||
if (errorlog < 0) {
|
||||
@ -443,6 +452,11 @@ int main(int argc, char **argv)
|
||||
#if !defined(_WIN32) || defined(_CONSOLE) || defined(__MINGW32__) || defined(__MINGW64__)
|
||||
/* startup all the modules */
|
||||
initialize_subsystems();
|
||||
if (!_start_logging_stdout()) {
|
||||
_fatal_error("FATAL: Could not start logging on stderr.");
|
||||
shutdown_subsystems();
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
/* parse the config file */
|
||||
config_get_config();
|
||||
|
63
src/util.c
63
src/util.c
@ -45,6 +45,7 @@
|
||||
#include "refbuf.h"
|
||||
#include "connection.h"
|
||||
#include "client.h"
|
||||
#include "source.h"
|
||||
|
||||
#define CATMODULE "util"
|
||||
|
||||
@ -486,11 +487,65 @@ char *util_base64_decode(const char *data)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* TODO, FIXME: handle memory allocation errors better. */
|
||||
static inline void _build_headers_loop(char **ret, size_t *len, ice_config_http_header_t *header, int status) {
|
||||
size_t headerlen;
|
||||
const char *name;
|
||||
const char *value;
|
||||
char * r = *ret;
|
||||
|
||||
if (!header)
|
||||
return;
|
||||
|
||||
do {
|
||||
/* filter out header's we don't use. */
|
||||
if (header->status != 0 && header->status != status) continue;
|
||||
|
||||
/* get the name of the header */
|
||||
name = header->name;
|
||||
|
||||
/* handle type of the header */
|
||||
switch (header->type) {
|
||||
case HTTP_HEADER_TYPE_STATIC:
|
||||
value = header->value;
|
||||
break;
|
||||
}
|
||||
|
||||
/* append the header to the buffer */
|
||||
headerlen = strlen(name) + strlen(value) + 4;
|
||||
*len += headerlen;
|
||||
r = realloc(r, *len);
|
||||
strcat(r, name);
|
||||
strcat(r, ": ");
|
||||
strcat(r, value);
|
||||
strcat(r, "\r\n");
|
||||
} while ((header = header->next));
|
||||
*ret = r;
|
||||
}
|
||||
static inline char * _build_headers(int status, ice_config_t *config, source_t *source) {
|
||||
mount_proxy *mountproxy = NULL;
|
||||
char *ret = NULL;
|
||||
size_t len = 1;
|
||||
|
||||
if (source)
|
||||
mountproxy = config_find_mount(config, source->mount, MOUNT_TYPE_NORMAL);
|
||||
|
||||
ret = calloc(1, 1);
|
||||
*ret = 0;
|
||||
|
||||
_build_headers_loop(&ret, &len, config->http_headers, status);
|
||||
if (mountproxy && mountproxy->http_headers)
|
||||
_build_headers_loop(&ret, &len, mountproxy->http_headers, status);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t util_http_build_header(char * out, size_t len, ssize_t offset,
|
||||
int cache,
|
||||
int status, const char * statusmsg,
|
||||
const char * contenttype, const char * charset,
|
||||
const char * datablock) {
|
||||
const char * datablock,
|
||||
struct source_tag * source) {
|
||||
const char * http_version = "1.0";
|
||||
ice_config_t *config;
|
||||
time_t now;
|
||||
@ -500,6 +555,7 @@ ssize_t util_http_build_header(char * out, size_t len, ssize_t offset,
|
||||
char status_buffer[80];
|
||||
char contenttype_buffer[80];
|
||||
ssize_t ret;
|
||||
char * extra_headers;
|
||||
|
||||
if (!out)
|
||||
return -1;
|
||||
@ -563,7 +619,8 @@ ssize_t util_http_build_header(char * out, size_t len, ssize_t offset,
|
||||
currenttime_buffer[0] = '\0';
|
||||
|
||||
config = config_get_config();
|
||||
ret = snprintf (out, len, "%sServer: %s\r\n%s%s%s%s%s%s",
|
||||
extra_headers = _build_headers(status, config, source);
|
||||
ret = snprintf (out, len, "%sServer: %s\r\n%s%s%s%s%s%s%s",
|
||||
status_buffer,
|
||||
config->server_id,
|
||||
currenttime_buffer,
|
||||
@ -572,8 +629,10 @@ ssize_t util_http_build_header(char * out, size_t len, ssize_t offset,
|
||||
(cache ? "" : "Cache-Control: no-cache\r\n"
|
||||
"Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n"
|
||||
"Pragma: no-cache\r\n"),
|
||||
extra_headers,
|
||||
(datablock ? "\r\n" : ""),
|
||||
(datablock ? datablock : ""));
|
||||
free(extra_headers);
|
||||
config_release_config();
|
||||
|
||||
return ret;
|
||||
|
@ -56,11 +56,14 @@ char *util_url_escape(const char *src);
|
||||
* If datablock is NULL no end-of-header nor any data is appended.
|
||||
* Returns the number of bytes written or -1 on error.
|
||||
*/
|
||||
struct source_tag; /* use forward decleration so we do not need to
|
||||
* include <source.h> that would cause other conflicts. */
|
||||
ssize_t util_http_build_header(char * out, size_t len, ssize_t offset,
|
||||
int cache,
|
||||
int status, const char * statusmsg,
|
||||
const char * contenttype, const char * charset,
|
||||
const char * datablock);
|
||||
const char * datablock,
|
||||
struct source_tag * source);
|
||||
|
||||
/* String dictionary type, without support for NULL keys, or multiple
|
||||
* instances of the same key */
|
||||
|
@ -238,7 +238,7 @@ void xslt_transform(xmlDocPtr doc, const char *xslfilename, client_t *client)
|
||||
|
||||
if (string == NULL)
|
||||
string = xmlCharStrdup ("");
|
||||
ret = util_http_build_header(refbuf->data, full_len, 0, 0, 200, NULL, mediatype, charset, NULL);
|
||||
ret = util_http_build_header(refbuf->data, full_len, 0, 0, 200, NULL, mediatype, charset, NULL, NULL);
|
||||
snprintf (refbuf->data + ret, full_len - ret,
|
||||
"Content-Length: %d\r\n\r\n%s",
|
||||
len, string);
|
||||
|
@ -4,15 +4,11 @@ AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
webdir = $(pkgdatadir)/web
|
||||
dist_web_DATA = status.xsl \
|
||||
status2.xsl \
|
||||
corner_bottomleft.jpg \
|
||||
corner_bottomright.jpg \
|
||||
corner_topleft.jpg \
|
||||
corner_topright.jpg \
|
||||
icecast.png \
|
||||
key.gif \
|
||||
style.css \
|
||||
auth.xsl \
|
||||
server_version.xsl \
|
||||
tunein.png \
|
||||
key.png
|
||||
key.png \
|
||||
status-json.xsl \
|
||||
xml2json.xslt
|
||||
|
116
web/auth.xsl
116
web/auth.xsl
@ -1,57 +1,59 @@
|
||||
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >
|
||||
<xsl:output omit-xml-declaration="no" method="html" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
|
||||
<xsl:template match = "/icestats" >
|
||||
<html>
|
||||
<head>
|
||||
<title>Icecast Streaming Media Server</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
<body topmargin="0" leftmargin="0" rightmargin="0" bottommargin="0">
|
||||
<table border="0" width="100%%">
|
||||
<tr>
|
||||
<td width="50"></td>
|
||||
<td>
|
||||
<h2>Authorization Page</h2>
|
||||
<div class="roundcont">
|
||||
<div class="roundtop">
|
||||
<img src="/corner_topleft.jpg" class="corner" style="display: none" />
|
||||
</div>
|
||||
<div class="newscontent">
|
||||
<xsl:for-each select="source">
|
||||
<xsl:choose>
|
||||
<xsl:when test="listeners">
|
||||
<xsl:if test="authenticator">
|
||||
<xsl:if test="server_name"><xsl:value-of select="server_name" /> </xsl:if>
|
||||
<h3>(<xsl:value-of select="@mount" />)</h3>
|
||||
<form method="GET" action="/admin/buildm3u">
|
||||
<table border="0" cellpadding="4">
|
||||
<tr><td>Username : <input type="text" name="username"/></td></tr>
|
||||
<tr><td>Password : <input type="password" name="password"/></td></tr>
|
||||
<tr><td><input type="Submit" value="Login"/></td></tr>
|
||||
</table>
|
||||
<input type="hidden" name="mount" value="{@mount}"/>
|
||||
</form>
|
||||
</xsl:if>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<h3><xsl:value-of select="@mount" /> - Not Connected</h3>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<br></br>
|
||||
<br></br>
|
||||
</xsl:for-each>
|
||||
<xsl:text disable-output-escaping="yes">&</xsl:text>nbsp;
|
||||
</div>
|
||||
<div class="roundbottom">
|
||||
<img src="/corner_bottomleft.jpg" class="corner" style="display: none" />
|
||||
</div>
|
||||
</div>
|
||||
<br></br><br></br>
|
||||
</td>
|
||||
<td width="25"></td></tr>
|
||||
</table>
|
||||
<div class="poster">Support icecast development at <a class="nav" target="_blank" href="http://www.icecast.org">www.icecast.org</a></div>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >
|
||||
<xsl:output omit-xml-declaration="no" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
|
||||
<xsl:template match = "/icestats" >
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Icecast Streaming Media Server</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="header">Icecast2 Status</h1>
|
||||
<!--index header menu -->
|
||||
<div id="menu">
|
||||
<ul>
|
||||
<li><a href="admin/">Administration</a></li>
|
||||
<li><a href="status.xsl">Server Status</a></li>
|
||||
<li><a href="server_version.xsl">Version</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--end index header menu -->
|
||||
<h2>Authorization Page</h2>
|
||||
<xsl:for-each select="source">
|
||||
<xsl:choose>
|
||||
<xsl:when test="listeners">
|
||||
<xsl:if test="authenticator">
|
||||
<div class="roundbox">
|
||||
<h3 class="mount">
|
||||
Mount Point <xsl:value-of select="@mount" />
|
||||
<xsl:if test="server_name">
|
||||
<small><xsl:value-of select="server_name" /></small>
|
||||
</xsl:if>
|
||||
</h3>
|
||||
<form class="alignedform" method="get" action="/admin/buildm3u">
|
||||
<p>
|
||||
<label for="name">Username: </label>
|
||||
<input id="name" name="username" type="text" />
|
||||
</p>
|
||||
<p>
|
||||
<label for="password">Password: </label>
|
||||
<input id="password" name="password" type="password" />
|
||||
</p>
|
||||
<input type="hidden" name="mount" value="{@mount}" />
|
||||
<input type="submit" value="Login" />
|
||||
</form>
|
||||
</div>
|
||||
</xsl:if>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<h3><xsl:value-of select="@mount" /> - Not Connected</h3>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:for-each>
|
||||
<div id="footer">
|
||||
Support icecast development at <a href="http://www.icecast.org">www.icecast.org</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 8.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 8.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 8.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 8.0 KiB |
BIN
web/key.gif
BIN
web/key.gif
Binary file not shown.
Before Width: | Height: | Size: 1.5 KiB |
@ -1,91 +1,73 @@
|
||||
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >
|
||||
<xsl:output omit-xml-declaration="no" method="html" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
|
||||
<xsl:template match = "/icestats" >
|
||||
<html>
|
||||
<head>
|
||||
<title>Icecast Streaming Media Server</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
<body topmargin="0" leftmargin="0" rightmargin="0" bottommargin="0">
|
||||
<h2>Server Information</h2>
|
||||
<br />
|
||||
<!--index header menu -->
|
||||
<div class="roundcont">
|
||||
<div class="roundtop">
|
||||
<img src="/corner_topleft.jpg" class="corner" style="display: none" />
|
||||
</div>
|
||||
<table border="0" width="100%" id="table1" cellspacing="0" cellpadding="4">
|
||||
<tr>
|
||||
<td bgcolor="#656565">
|
||||
<a class="nav" href="admin/">Administration</a>
|
||||
<a class="nav" href="status.xsl">Server Status</a>
|
||||
<a class="nav" href="server_version.xsl">Version</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="roundbottom">
|
||||
<img src="/corner_bottomleft.jpg" class="corner" style="display: none" />
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<!--end index header menu -->
|
||||
|
||||
<div class="roundcont">
|
||||
<div class="roundtop">
|
||||
<img src="/corner_topleft.jpg" class="corner" style="display: none" />
|
||||
</div>
|
||||
<div class="newscontent">
|
||||
<h3>Server Information</h3>
|
||||
<table border="0" cellpadding="4">
|
||||
<xsl:for-each select="/icestats">
|
||||
<tr>
|
||||
<td width="130">Location</td>
|
||||
<td class="streamdata"><xsl:value-of select="location" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="130">Admin</td>
|
||||
<td class="streamdata"><xsl:value-of select="admin" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="130">Host</td>
|
||||
<td class="streamdata"><xsl:value-of select="host" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="130">Version</td>
|
||||
<td class="streamdata"><xsl:value-of select="server_id" /></td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
<tr>
|
||||
<td width="130">Download</td>
|
||||
<td class="streamdata"><a class="nav" target="_blank" href="http://icecast.org/download.php">icecast.org</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="130">Subversion</td>
|
||||
<td class="streamdata"><a class="nav" target="_blank" href="http://icecast.org/svn.php">click here</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="130">Documentation</td>
|
||||
<td class="streamdata"><a class="nav" target="_blank" href="http://icecast.org/docs.php">click here</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="130">Stream Directory </td>
|
||||
<td class="streamdata"><a class="nav" target="_blank" href="http://dir.xiph.org/index.php">dir.xiph.org</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="130">Community</td>
|
||||
<td class="streamdata"><a class="nav" target="_blank" href="http://forum.icecast.org/">forum.icecast.org</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="roundbottom">
|
||||
<img src="/corner_bottomleft.jpg" class="corner" style="display: none" />
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<div class="poster">Support icecast development at <a class="nav" target="_blank" href="http://www.icecast.org">www.icecast.org</a></div>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0">
|
||||
<xsl:output omit-xml-declaration="no" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
|
||||
<xsl:template match = "/icestats">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Icecast Streaming Media Server</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="header">Server Information</h1>
|
||||
<!--index header menu -->
|
||||
<div id="menu">
|
||||
<ul>
|
||||
<li><a href="admin/">Administration</a></li>
|
||||
<li><a href="status.xsl">Server Status</a></li>
|
||||
<li><a href="server_version.xsl">Version</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--end index header menu -->
|
||||
|
||||
<div class="roundbox">
|
||||
<h3>Server Information</h3>
|
||||
<table class="yellowkeys">
|
||||
<tbody>
|
||||
<xsl:for-each select="/icestats">
|
||||
<tr>
|
||||
<td>Location</td>
|
||||
<td><xsl:value-of select="location" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Admin</td>
|
||||
<td><xsl:value-of select="admin" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Host</td>
|
||||
<td><xsl:value-of select="host" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Version</td>
|
||||
<td><xsl:value-of select="server_id" /></td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
<tr>
|
||||
<td>Download</td>
|
||||
<td><a href="http://icecast.org/download.php">icecast.org</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Subversion</td>
|
||||
<td><a href="http://icecast.org/svn.php">icecast.org/svn.php</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Documentation</td>
|
||||
<td><a href="http://icecast.org/docs.php">icecast.org/docs.php</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Stream Directory</td>
|
||||
<td><a href="http://dir.xiph.org/index.php">dir.xiph.org</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Community</td>
|
||||
<td><a href="http://icecast.org/community.php">icecast.org/community.php</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id="footer">
|
||||
Support icecast development at <a href="http://www.icecast.org">www.icecast.org</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
|
24
web/status-json.xsl
Normal file
24
web/status-json.xsl
Normal file
@ -0,0 +1,24 @@
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
<xsl:import href="xml2json.xslt"/>
|
||||
<xsl:output indent="no" omit-xml-declaration="yes" method="text" encoding="UTF-8" media-type="application/json"/>
|
||||
<xsl:strip-space elements="*"/>
|
||||
|
||||
<!-- override imported transform variable to enable output -->
|
||||
<xsl:variable name="output">true</xsl:variable>
|
||||
|
||||
<!-- hide certain nodes from all sources -->
|
||||
<xsl:template match="icestats/source/max_listeners"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
|
||||
<xsl:template match="icestats/source/public"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
|
||||
<xsl:template match="icestats/source/source_ip"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
|
||||
<xsl:template match="icestats/source/slow_listeners"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
|
||||
<xsl:template match="icestats/source/*[contains(name(), 'total_bytes')]"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
|
||||
<xsl:template match="icestats/source/user_agent" ><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
|
||||
|
||||
<!-- hide certain global nodes -->
|
||||
<xsl:template match="icestats/sources"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
|
||||
<xsl:template match="icestats/clients"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
|
||||
<xsl:template match="icestats/stats"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
|
||||
<xsl:template match="icestats/listeners"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
|
||||
<xsl:template match="node()[contains(name(), 'connections')]"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
293
web/status.xsl
293
web/status.xsl
@ -1,126 +1,167 @@
|
||||
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >
|
||||
<xsl:output omit-xml-declaration="no" method="html" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
|
||||
<xsl:template match = "/icestats" >
|
||||
<html>
|
||||
<head>
|
||||
<title>Icecast Streaming Media Server</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
<body topmargin="0" leftmargin="0" rightmargin="0" bottommargin="0">
|
||||
<h2>Icecast2 Status</h2>
|
||||
<br />
|
||||
<!--index header menu -->
|
||||
<div class="roundcont">
|
||||
<div class="roundtop">
|
||||
<img src="/corner_topleft.jpg" class="corner" style="display: none" />
|
||||
</div>
|
||||
<table border="0" width="100%" id="table1" cellspacing="0" cellpadding="4">
|
||||
<tr>
|
||||
<td bgcolor="#656565">
|
||||
<a class="nav" href="admin/">Administration</a>
|
||||
<a class="nav" href="status.xsl">Server Status</a>
|
||||
<a class="nav" href="server_version.xsl">Version</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="roundbottom">
|
||||
<img src="/corner_bottomleft.jpg" class="corner" style="display: none" />
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<!--end index header menu -->
|
||||
<!--mount point stats-->
|
||||
<xsl:for-each select="source">
|
||||
<xsl:choose>
|
||||
<xsl:when test="listeners">
|
||||
<div class="roundcont">
|
||||
<div class="roundtop">
|
||||
<img src="/corner_topleft.jpg" class="corner" style="display: none" />
|
||||
</div>
|
||||
<div class="newscontent">
|
||||
<div class="streamheader">
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<colgroup align="left" />
|
||||
<colgroup align="right" width="300" />
|
||||
<tr>
|
||||
<td><h3>Mount Point <xsl:value-of select="@mount" /></h3></td>
|
||||
<xsl:choose>
|
||||
<xsl:when test="authenticator">
|
||||
<td align="right"><a class="auth" href="/auth.xsl">Login</a></td>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<td align="right">
|
||||
<a href="{@mount}.m3u">M3U</a>
|
||||
<a href="{@mount}.xspf">XSPF</a>
|
||||
<a href="{@mount}.vclt">VCLT</a>
|
||||
</td>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</tr></table>
|
||||
</div>
|
||||
|
||||
<table border="0" cellpadding="4">
|
||||
<xsl:if test="server_name">
|
||||
<tr><td>Stream Title:</td><td class="streamdata"> <xsl:value-of select="server_name" /></td></tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="server_description">
|
||||
<tr><td>Stream Description:</td><td class="streamdata"> <xsl:value-of select="server_description" /></td></tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="server_type">
|
||||
<tr><td>Content Type:</td><td class="streamdata"><xsl:value-of select="server_type" /></td></tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="stream_start">
|
||||
<tr><td>Mount started:</td><td class="streamdata"><xsl:value-of select="stream_start" /></td></tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="bitrate">
|
||||
<tr><td>Bitrate:</td><td class="streamdata"> <xsl:value-of select="bitrate" /></td></tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="quality">
|
||||
<tr><td>Quality:</td><td class="streamdata"> <xsl:value-of select="quality" /></td></tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="video_quality">
|
||||
<tr><td>Video Quality:</td><td class="streamdata"> <xsl:value-of select="video_quality" /></td></tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="frame_size">
|
||||
<tr><td>Framesize:</td><td class="streamdata"> <xsl:value-of select="frame_size" /></td></tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="frame_rate">
|
||||
<tr><td>Framerate:</td><td class="streamdata"> <xsl:value-of select="frame_rate" /></td></tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="listeners">
|
||||
<tr><td>Current Listeners:</td><td class="streamdata"> <xsl:value-of select="listeners" /></td></tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="listener_peak">
|
||||
<tr><td>Peak Listeners:</td><td class="streamdata"> <xsl:value-of select="listener_peak" /></td></tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="genre">
|
||||
<tr><td>Stream Genre:</td><td class="streamdata"> <xsl:value-of select="genre" /></td></tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="server_url">
|
||||
<tr><td>Stream URL:</td><td class="streamdata"> <a target="_blank" href="{server_url}"><xsl:value-of select="server_url" /></a></td></tr>
|
||||
</xsl:if>
|
||||
<tr><td>Current Song:</td><td class="streamdata">
|
||||
<xsl:if test="artist"><xsl:value-of select="artist" /> - </xsl:if><xsl:value-of select="title" /></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="roundbottom">
|
||||
<img src="/corner_bottomleft.jpg" class="corner" style="display: none" />
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<h3><xsl:value-of select="@mount" /> - Not Connected</h3>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
|
||||
</xsl:for-each>
|
||||
<xsl:text disable-output-escaping="yes">&</xsl:text>nbsp;
|
||||
|
||||
|
||||
<div class="poster">Support icecast development at <a class="nav" target="_blank" href="http://www.icecast.org">www.icecast.org</a></div>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0">
|
||||
<xsl:output omit-xml-declaration="no" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
|
||||
<xsl:template match = "/icestats">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Icecast Streaming Media Server</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="header">Icecast2 Status</h1>
|
||||
<!--index header menu -->
|
||||
<div id="menu">
|
||||
<ul>
|
||||
<li><a href="admin/">Administration</a></li>
|
||||
<li><a href="status.xsl">Server Status</a></li>
|
||||
<li><a href="server_version.xsl">Version</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--end index header menu -->
|
||||
<xsl:text disable-output-escaping="yes">
|
||||
<!-- WARNING:
|
||||
DO NOT ATTEMPT TO PARSE ICECAST HTML OUTPUT!
|
||||
The web interface may change completely between releases.
|
||||
If you have a need for automatic processing of server data,
|
||||
please read the appropriate documentation. Latest docs:
|
||||
http://icecast.org/docs/icecast-latest/icecast2_stats.html
|
||||
-->
|
||||
</xsl:text>
|
||||
<!--mount point stats-->
|
||||
<xsl:for-each select="source">
|
||||
<xsl:choose>
|
||||
<xsl:when test="listeners">
|
||||
<div class="roundbox">
|
||||
<div class="mounthead">
|
||||
<h3 class="mount">Mount Point <xsl:value-of select="@mount" /></h3>
|
||||
<div class="right">
|
||||
<xsl:choose>
|
||||
<xsl:when test="authenticator">
|
||||
<a class="auth" href="/auth.xsl">Login</a>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<ul class="mountlist">
|
||||
<li><a class="play" href="{@mount}.m3u">M3U</a></li>
|
||||
<li><a class="play" href="{@mount}.xspf">XSPF</a></li>
|
||||
<li><a class="play" href="{@mount}.vclt">VCLT</a></li>
|
||||
</ul>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mountcont">
|
||||
<xsl:if test="server_type and ((server_type = 'application/ogg') or (server_type = 'audio/ogg'))">
|
||||
<div class="audioplayer">
|
||||
<audio controls="controls" preload="none">
|
||||
<source src="{@mount}" type="{server_type}" />
|
||||
</audio>
|
||||
</div>
|
||||
</xsl:if>
|
||||
<table class="yellowkeys">
|
||||
<tbody>
|
||||
<xsl:if test="server_name">
|
||||
<tr>
|
||||
<td>Stream Name:</td>
|
||||
<td><xsl:value-of select="server_name" /></td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="server_description">
|
||||
<tr>
|
||||
<td>Stream Description:</td>
|
||||
<td><xsl:value-of select="server_description" /></td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="server_type">
|
||||
<tr>
|
||||
<td>Content Type:</td>
|
||||
<td><xsl:value-of select="server_type" /></td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="stream_start">
|
||||
<tr>
|
||||
<td>Stream started:</td>
|
||||
<td class="streamstats"><xsl:value-of select="stream_start" /></td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="bitrate">
|
||||
<tr>
|
||||
<td>Bitrate:</td>
|
||||
<td class="streamstats"><xsl:value-of select="bitrate" /></td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="quality">
|
||||
<tr>
|
||||
<td>Quality:</td>
|
||||
<td class="streamstats"><xsl:value-of select="quality" /></td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="video_quality">
|
||||
<tr>
|
||||
<td>Video Quality:</td>
|
||||
<td class="streamstats"><xsl:value-of select="video_quality" /></td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="frame_size">
|
||||
<tr>
|
||||
<td>Framesize:</td>
|
||||
<td class="streamstats"><xsl:value-of select="frame_size" /></td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="frame_rate">
|
||||
<tr>
|
||||
<td>Framerate:</td>
|
||||
<td class="streamstats"><xsl:value-of select="frame_rate" /></td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="listeners">
|
||||
<tr>
|
||||
<td>Listeners (current):</td>
|
||||
<td class="streamstats"><xsl:value-of select="listeners" /></td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="listener_peak">
|
||||
<tr>
|
||||
<td>Listeners (peak):</td>
|
||||
<td class="streamstats"><xsl:value-of select="listener_peak" /></td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="genre">
|
||||
<tr>
|
||||
<td>Genre:</td>
|
||||
<td class="streamstats"><xsl:value-of select="genre" /></td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="server_url">
|
||||
<tr>
|
||||
<td>Stream URL:</td>
|
||||
<td class="streamstats">
|
||||
<a href="{server_url}"><xsl:value-of select="server_url" /></a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<tr>
|
||||
<td>Currently playing:</td>
|
||||
<td class="streamstats">
|
||||
<xsl:if test="artist">
|
||||
<xsl:value-of select="artist" /> -
|
||||
</xsl:if>
|
||||
<xsl:value-of select="title" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<h3><xsl:value-of select="@mount" /> - Not Connected</h3>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:for-each>
|
||||
<div id="footer">
|
||||
Support icecast development at <a href="http://www.icecast.org">www.icecast.org</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
|
@ -1,12 +0,0 @@
|
||||
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >
|
||||
<xsl:output omit-xml-declaration="no" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
|
||||
<xsl:template match = "/icestats" >
|
||||
<pre>
|
||||
MountPoint,Connections,Stream Name,Current Listeners,Description,Currently Playing,Stream URL
|
||||
Global,Client:<xsl:value-of select="connections" /> Source: <xsl:value-of select="source_connections" />,,<xsl:value-of select="listeners" />,,
|
||||
<xsl:for-each select="source">
|
||||
<xsl:value-of select="@mount" />,,<xsl:value-of select="name" />,<xsl:value-of select="listeners" />,<xsl:value-of select="description" />,<xsl:value-of select="artist" /> - <xsl:value-of select="title" />,<xsl:value-of select="url" />
|
||||
</xsl:for-each>
|
||||
</pre>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
456
web/style.css
456
web/style.css
@ -1,250 +1,274 @@
|
||||
/******************************************************************************
|
||||
|
||||
This file styles the bar that goes across the top of all Xiph.Org
|
||||
pages.
|
||||
|
||||
The style that comes from this was first (to my knowledge) at
|
||||
http://alistapart.com/stories/practicalcss/ in the
|
||||
"Splitting the Difference" section.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
/* This effect doesn't work at all if all content is pinched in a bit. */
|
||||
html, body {
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
margin-left: 50px;
|
||||
margin-right: 25px;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.xiphnav {
|
||||
body {
|
||||
padding: 0 25px 0 50px;
|
||||
background-color: #000;
|
||||
font-family: Verdana, sans-serif;
|
||||
font-weight: normal;
|
||||
padding: .25em;
|
||||
margin-bottom: .5em;
|
||||
border-bottom: 1px solid #000;
|
||||
color: #000;
|
||||
background: #aaa;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
}
|
||||
h2 {
|
||||
|
||||
a {
|
||||
color: #f8ef64;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dotted #f8ef64;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #f8ef64;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid #f8ef64;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
font-size: 3em;
|
||||
color: #fff;
|
||||
padding: 10px 0px 10px 80px;
|
||||
margin-top:3px;
|
||||
background: transparent url(/icecast.png) no-repeat scroll left center
|
||||
}
|
||||
h1 {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
font-size: 100%;
|
||||
color: #fff;
|
||||
margin-top:3px;
|
||||
}
|
||||
.nav {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
font-size: 110%;
|
||||
color: #fff;
|
||||
}
|
||||
.nav:hover {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
color: #f8ef64;
|
||||
}
|
||||
.xiphnav_a {
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
color: #000;
|
||||
}
|
||||
.news {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
color: #fff;
|
||||
}
|
||||
.newsheader {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
font-size: 110%;
|
||||
color: #f8ef64;
|
||||
background: #444;
|
||||
}
|
||||
.streamtd {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
font-size: 85%;
|
||||
color: #fff;
|
||||
padding:15px;
|
||||
}
|
||||
.streamtd_alt {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
font-size: 85%;
|
||||
color: #fff;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.streamtd_alt_2 {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: underline;
|
||||
font-weight: normal;
|
||||
font-size: 85%;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
td {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
color: #fff;
|
||||
}
|
||||
.roundcont {
|
||||
width: 90%;
|
||||
background-color: #656565;
|
||||
color: #fff;
|
||||
}
|
||||
.roundcont a {
|
||||
margin: 0px 10px;
|
||||
}
|
||||
.newscontent {
|
||||
margin: 0 20px;
|
||||
}
|
||||
h3 {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
font-size: 110%;
|
||||
color: #f8ef64;
|
||||
}
|
||||
.newscontent h3 {
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px groove #ACACAC;
|
||||
|
||||
h1#header{
|
||||
padding: 10px 0px 10px 80px;
|
||||
background: transparent url(/icecast.png) no-repeat scroll left center;
|
||||
}
|
||||
.newscontent h4 {
|
||||
margin: 10px 0px;
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
font-size: 110%;
|
||||
|
||||
h3 small {
|
||||
color: #fff;
|
||||
font-size: 70%;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
form.alignedform label {
|
||||
text-align: right;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 10em;
|
||||
margin: 0 1em 0 0;
|
||||
}
|
||||
|
||||
form.alignedform input {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
border: 1px solid #f8ef64;
|
||||
background-color: #333;
|
||||
color: #f8ef64;
|
||||
}
|
||||
.newscontent p {
|
||||
margin: 0 0;
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: none;
|
||||
font-size: 90%;
|
||||
}
|
||||
.newscontent td {
|
||||
margin: 0 0;
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: none;
|
||||
font-size: 90%;
|
||||
}
|
||||
.newscontent td.streamdata {
|
||||
margin: 0 0;
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: none;
|
||||
font-size: 90%;
|
||||
color: #f8ef64;
|
||||
}
|
||||
.streamheader table {
|
||||
width: 100%;
|
||||
margin-bottom: 5px;
|
||||
border-bottom: 1px groove #ACACAC;
|
||||
}
|
||||
.streamheader td {
|
||||
margin: 0px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
padding: 10 5 10 5;
|
||||
border: 0px solid white;
|
||||
}
|
||||
.streamheader h3 {
|
||||
border: 0px;
|
||||
}
|
||||
.streamheader a {
|
||||
padding: 8px 5px 3px 30px;
|
||||
text-decoration: none;
|
||||
background: transparent url("/tunein.png") no-repeat left center;
|
||||
}
|
||||
.streamheader a.auth {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 32px;
|
||||
background: transparent url("/key.png") no-repeat left center;
|
||||
}
|
||||
.newscontent a {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
margin: 0px;
|
||||
color: #f8ef64;
|
||||
}
|
||||
.newscontent a:hover {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
.newscontent a.nav2 {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
padding: 2px 9px;
|
||||
background: #444;
|
||||
color: #f8ef64;
|
||||
}
|
||||
.newscontent a.nav2:hover {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
background: #777;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
.poster {
|
||||
font-family: Verdana, sans-serif;
|
||||
margin: 50px 120px 20px 0px;
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
font-size: 100%;
|
||||
color: #f8ef64;
|
||||
padding: 5px;
|
||||
border-top: 1px groove #ACACAC;
|
||||
}
|
||||
.roundcont p {
|
||||
margin: 10px 50px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.roundtop {
|
||||
background: url(/corner_topright.jpg) no-repeat top right;
|
||||
#menu {
|
||||
border-top: 3px solid #7B96C6;
|
||||
border-bottom: 3px solid #7B96C6;
|
||||
text-align: center;
|
||||
margin-bottom: 35px;
|
||||
}
|
||||
|
||||
.roundbottom {
|
||||
background: url(/corner_bottomright.jpg) no-repeat top right;
|
||||
#menu ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
img.corner {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
#menu ul li {
|
||||
float: left;
|
||||
padding-left: 25px;
|
||||
padding-right: 25px;
|
||||
}
|
||||
|
||||
#menu ul li a {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
border: none;
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
#menu ul li a:hover {
|
||||
color: #f8ef64;
|
||||
}
|
||||
|
||||
.roundbox {
|
||||
width: 90%;
|
||||
background-color: #656565;
|
||||
border-radius: 10px;
|
||||
padding: 15px 20px;
|
||||
margin-bottom: 35px;
|
||||
}
|
||||
|
||||
.roundbox h3 {
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px groove #ACACAC;
|
||||
}
|
||||
|
||||
.roundbox table.yellowkeys tr td:last-child {
|
||||
color: #f8ef64;
|
||||
}
|
||||
|
||||
table.colortable {
|
||||
border-collapse: collapse;
|
||||
padding: 20px 0 20px 0;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
table.colortable td {
|
||||
border: 1px solid #000;
|
||||
text-align: center;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
table.colortable thead tr td {
|
||||
color: #656565;
|
||||
background: #f8ef64;
|
||||
border-color: white;
|
||||
}
|
||||
|
||||
.roundbox table.yellowkeys tr td {
|
||||
padding: 5px 5px 0 0;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.mounthead h3 {
|
||||
float: left;
|
||||
margin-bottom: 0px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.mountcont {
|
||||
border-top: 1px groove #ACACAC;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
ul.mountlist {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.mountlist li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
a.play {
|
||||
padding-left: 22px;
|
||||
margin-left: 25px;
|
||||
border: none;
|
||||
background: transparent url(/tunein.png) no-repeat scroll left center;
|
||||
background-size: auto 100%;
|
||||
}
|
||||
|
||||
a.auth {
|
||||
padding-left: 22px;
|
||||
margin-left: 25px;
|
||||
border: none;
|
||||
background: transparent url(/key.png) no-repeat scroll left top;
|
||||
background-size: auto 100%;
|
||||
}
|
||||
|
||||
/* Admin navigation */
|
||||
|
||||
ul.nav {
|
||||
margin: 0;
|
||||
padding: 5px 0 10px 0;
|
||||
clear: both;
|
||||
list-style: none;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
ul.nav li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
ul.nav li a {
|
||||
border: none;
|
||||
display: inline-block;
|
||||
padding: .2em .7em;
|
||||
margin-top: .2em;
|
||||
background-color: #333;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
ul.nav li a:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
|
||||
#footer {
|
||||
border-top: 1px groove #ACACAC;
|
||||
margin-top: 20px;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
|
||||
body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.roundbox {
|
||||
width: auto;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.roundbox table.yellowkeys tr td {
|
||||
display: block;
|
||||
padding: 5px 5px 0 0;
|
||||
}
|
||||
|
||||
.roundbox table.yellowkeys tr td:last-child {
|
||||
margin-bottom: 5px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.scrolltable {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: 320px) {
|
||||
|
||||
ul.nav, #menu ul {
|
||||
display: block;
|
||||
}
|
||||
|
||||
ul.nav li, #menu ul li {
|
||||
float: none;
|
||||
}
|
||||
|
||||
ul.nav li a, #menu ul li a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
ul.nav li + li, #menu ul li + li {
|
||||
border-top: 1px solid #ACACAC;
|
||||
}
|
||||
|
||||
a.play {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user