diff --git a/conf/icecast.xml b/conf/icecast.xml
index e28435fa..71b790c2 100644
--- a/conf/icecast.xml
+++ b/conf/icecast.xml
@@ -32,6 +32,7 @@
/usr/local/icecast
/tmp
+ /usr/local/icecast/webroot
diff --git a/src/Makefile.am b/src/Makefile.am
index d89e1fb2..29a64718 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,23 +11,20 @@ noinst_HEADERS = config.h os.h logging.h sighandler.h connection.h global.h\
compat.h format_mp3.h
icecast_SOURCES = config.c main.c logging.c sighandler.c connection.c global.c\
util.c slave.c source.c stats.c refbuf.c client.c format.c format_vorbis.c\
- format_mp3.c
+ format_mp3.c xslt.c
icecast_LDADD = net/libicenet.la thread/libicethread.la httpp/libicehttpp.la\
log/libicelog.la avl/libiceavl.la timing/libicetiming.la
-LIBS = @LIBS@ -lpthread @SOCKET_LIBS@ @XML_LIBS@ @OGG_LIBS@ @VORBIS_LIBS@
-CFLAGS = @CFLAGS@ @XML_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@
+LIBS = @LIBS@ -lxslt -lpthread @SOCKET_LIBS@ @XML_LIBS@ @OGG_LIBS@ @VORBIS_LIBS@
+CFLAGS = -g @CFLAGS@ @XML_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@
INCLUDES = -I$(srcdir)/net -I$(srcdir)/thread -I$(srcdir)/avl -I$(srcdir)/httpp \
-I$(srcdir)/log -I$(srcdir)/timing
-# SCCS stuff (for BitKeeper)
-GET = true
-
debug:
- $(MAKE) all CFLAGS="@DEBUG@ @XML_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@"
+ $(MAKE) all CFLAGS="@DEBUG@ @XML_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@"
profile:
- $(MAKE) all CFLAGS="@PROFILE@ @XML_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@"
+ $(MAKE) all CFLAGS="@PROFILE@ @XML_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@"
diff --git a/src/config.c b/src/config.c
index 8f403024..ff659be0 100644
--- a/src/config.c
+++ b/src/config.c
@@ -28,9 +28,11 @@
#ifndef _WIN32
#define CONFIG_DEFAULT_BASE_DIR "/usr/local/icecast"
#define CONFIG_DEFAULT_LOG_DIR "/usr/local/icecast/logs"
+#define CONFIG_DEFAULT_WEBROOT_DIR "/usr/local/icecast/webroot"
#else
#define CONFIG_DEFAULT_BASE_DIR ".\\"
#define CONFIG_DEFAULT_LOG_DIR ".\\logs"
+#define CONFIG_DEFAULT_WEBROOT_DIR ".\\webroot"
#endif
ice_config_t _configuration;
@@ -278,6 +280,9 @@ static void _parse_paths(xmlDocPtr doc, xmlNodePtr node)
} else if (strcmp(node->name, "logdir") == 0) {
if (_configuration.log_dir) free(_configuration.log_dir);
_configuration.log_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+ } else if (strcmp(node->name, "webroot") == 0) {
+ if (_configuration.webroot_dir) free(_configuration.webroot_dir);
+ _configuration.webroot_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
}
} while ((node = node->next));
}
diff --git a/src/config.h b/src/config.h
index 37fd87f3..4534d1a7 100644
--- a/src/config.h
+++ b/src/config.h
@@ -39,6 +39,7 @@ typedef struct ice_config_tag
char *base_dir;
char *log_dir;
+ char *webroot_dir;
char *access_log;
char *error_log;
diff --git a/src/connection.c b/src/connection.c
index 42aeb59d..51d7a721 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#ifndef _WIN32
#include
@@ -32,6 +33,7 @@
#include "stats.h"
#include "format.h"
#include "logging.h"
+#include "xslt.h"
#include "source.h"
@@ -333,6 +335,8 @@ static void *_handle_connection(void *arg)
http_var_t *var;
client_t *client;
int bytes;
+ struct stat statbuf;
+ char fullPath[4096];
while (global.running == ICE_RUNNING) {
memset(header, 0, 4096);
@@ -437,6 +441,27 @@ static void *_handle_connection(void *arg)
if (strcmp(httpp_getvar(parser, HTTPP_VAR_URI), "/stats.xml") == 0) {
printf("sending stats.xml\n");
stats_sendxml(client);
+ client_destroy(client);
+ continue;
+ }
+
+ /* Here we are parsing the URI request to see
+ ** if the extension is .xsl, if so, then process
+ ** this request as an XSLT request
+ */
+ if (util_check_valid_extension(httpp_getvar(parser, HTTPP_VAR_URI)) == XSLT_CONTENT) {
+ util_get_full_path(httpp_getvar(parser, HTTPP_VAR_URI), fullPath, sizeof(fullPath));
+
+ /* If the file exists, then transform it, otherwise, write a 404 error */
+ if (stat(fullPath, &statbuf) == 0) {
+ sock_write(client->con->sock, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
+ stats_transform_xslt(client, fullPath);
+ }
+ else {
+ sock_write(client->con->sock, "HTTP/1.0 404 File Not Found\r\nContent-Type: text/html\r\n\r\n"\
+ "The file you requested could not be found.\r\n");
+ }
+ client_destroy(client);
continue;
}
diff --git a/src/stats.c b/src/stats.c
index 8d04f807..8e336a2b 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -18,6 +18,7 @@
#include "refbuf.h"
#include "client.h"
#include "stats.h"
+#include "xslt.h"
#ifdef _WIN32
#define vsnprintf _vsnprintf
@@ -728,6 +729,45 @@ static xmlNodePtr _find_xml_node(char *mount, source_xml_t **list, xmlNodePtr ro
return node->node;
}
+void stats_transform_xslt(client_t *client, char *xslpath)
+{
+ xmlDocPtr doc;
+
+ stats_get_xml(&doc);
+
+ transformXSLT(doc, xslpath, client);
+
+ xmlFreeDoc(doc);
+}
+
+void stats_get_xml(xmlDocPtr *doc)
+{
+ stats_event_t *event;
+ stats_event_t *queue;
+ xmlNodePtr node, srcnode;
+ source_xml_t *src_nodes = NULL;
+
+ queue = NULL;
+ _dump_stats_to_queue(&queue);
+
+ *doc = xmlNewDoc("1.0");
+ node = xmlNewDocNode(*doc, NULL, "icestats", NULL);
+ xmlDocSetRootElement(*doc, node);
+
+
+ event = _get_event_from_queue(&queue);
+ while (event) {
+ if (event->source == NULL) {
+ xmlNewChild(node, NULL, event->name, event->value);
+ } else {
+ srcnode = _find_xml_node(event->source, &src_nodes, node);
+ xmlNewChild(srcnode, NULL, event->name, event->value);
+ }
+
+ _free_event(event);
+ event = _get_event_from_queue(&queue);
+ }
+}
void stats_sendxml(client_t *client)
{
int bytes;
diff --git a/src/stats.h b/src/stats.h
index 2cffa71e..91855124 100644
--- a/src/stats.h
+++ b/src/stats.h
@@ -4,6 +4,10 @@
#include "connection.h"
#include "httpp.h"
#include "client.h"
+#include
+#include
+#include
+
typedef struct _stats_connection_tag
{
@@ -70,7 +74,9 @@ void stats_event_dec(char *source, char *name);
void *stats_connection(void *arg);
void *stats_callback(void *arg);
+void stats_transform_xslt(client_t *client, char *xslpath);
void stats_sendxml(client_t *client);
+void stats_get_xml(xmlDocPtr *doc);
#endif /* __STATS_H__ */
diff --git a/src/thread/thread.c b/src/thread/thread.c
index e312e3fb..d4e56724 100644
--- a/src/thread/thread.c
+++ b/src/thread/thread.c
@@ -115,11 +115,6 @@ void thread_initialize(void)
{
thread_t *thread;
- /* this must be called to init pthreads-win32 */
-#ifdef _WIN32
- ptw32_processInitialize();
-#endif
-
/* set up logging */
log_initialize();
@@ -129,7 +124,7 @@ void thread_initialize(void)
log_set_level(_logid, THREAD_DEBUG);
#endif
- /* create all the interal mutexes, and initialize the mutex tree */
+ /* create all the internal mutexes, and initialize the mutex tree */
_mutextree = avl_tree_new(_compare_mutexes, NULL);
diff --git a/src/util.c b/src/util.c
index 980bbe70..76687b85 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,4 +1,6 @@
#include
+#include
+#include
#ifndef _WIN32
#include
@@ -10,12 +12,17 @@
#else
#include
#include
+#include
+#define snprintf _snprintf
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
#endif
#include "sock.h"
#include "config.h"
#include "util.h"
+#include "os.h"
/* Abstract out an interface to use either poll or select depending on which
* is available (poll is preferred) to watch a single fd.
@@ -85,6 +92,46 @@ int util_read_header(int sock, char *buff, unsigned long len)
return ret;
}
-
+int util_get_full_path(char *uri, char *fullPath, int fullPathLen) {
+ int ret = 0;
+ if (uri) {
+ memset(fullPath, '\000', fullPathLen);
+ snprintf(fullPath, fullPathLen-1, "%s%s%s", config_get_config()->webroot_dir, PATH_SEPARATOR, uri);
+ ret = 1;
+ }
+ return ret;
+}
+
+int util_check_valid_extension(char *uri) {
+ int ret = 0;
+ char *p2;
+
+ if (uri) {
+ p2 = strrchr(uri, '.');
+ if (p2) {
+ p2++;
+ if (strncmp(p2, "xsl", strlen("xsl")) == 0) {
+ /* Build the full path for the request, concatenating the webroot from the config.
+ ** Here would be also a good time to prevent accesses like '../../../../etc/passwd' or somesuch.
+ */
+ ret = XSLT_CONTENT;
+ }
+ if (strncmp(p2, "htm", strlen("htm")) == 0) {
+ /* Build the full path for the request, concatenating the webroot from the config.
+ ** Here would be also a good time to prevent accesses like '../../../../etc/passwd' or somesuch.
+ */
+ ret = HTML_CONTENT;
+ }
+ if (strncmp(p2, "html", strlen("html")) == 0) {
+ /* Build the full path for the request, concatenating the webroot from the config.
+ ** Here would be also a good time to prevent accesses like '../../../../etc/passwd' or somesuch.
+ */
+ ret = HTML_CONTENT;
+ }
+
+ }
+ }
+ return ret;
+}
diff --git a/src/util.h b/src/util.h
index d3da771f..f034794b 100644
--- a/src/util.h
+++ b/src/util.h
@@ -1,7 +1,12 @@
#ifndef __UTIL_H__
#define __UTIL_H__
+#define XSLT_CONTENT 1
+#define HTML_CONTENT 2
+
int util_timed_wait_for_fd(int fd, int timeout);
int util_read_header(int sock, char *buff, unsigned long len);
+int util_get_full_path(char *uri, char *fullPath, int fullPathLen);
+int util_check_valid_extension(char *uri);
#endif /* __UTIL_H__ */