config.c 15.5 KB
Newer Older
Jack Moffitt's avatar
Jack Moffitt committed
1 2 3
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Michael Smith's avatar
Michael Smith committed
4 5
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
Jack Moffitt's avatar
Jack Moffitt committed
6 7 8 9 10 11 12 13 14
#include "config.h"

#define CONFIG_DEFAULT_LOCATION "Earth"
#define CONFIG_DEFAULT_ADMIN "icemaster@localhost"
#define CONFIG_DEFAULT_CLIENT_LIMIT 256
#define CONFIG_DEFAULT_SOURCE_LIMIT 16
#define CONFIG_DEFAULT_THREADPOOL_SIZE 4
#define CONFIG_DEFAULT_CLIENT_TIMEOUT 30
#define CONFIG_DEFAULT_HEADER_TIMEOUT 15
15
#define CONFIG_DEFAULT_SOURCE_TIMEOUT 10
Jack Moffitt's avatar
Jack Moffitt committed
16
#define CONFIG_DEFAULT_SOURCE_PASSWORD "changeme"
17
#define CONFIG_DEFAULT_RELAY_PASSWORD "changeme"
18
#define CONFIG_DEFAULT_ICE_LOGIN 0
Jack Moffitt's avatar
Jack Moffitt committed
19 20 21 22 23
#define CONFIG_DEFAULT_TOUCH_FREQ 5
#define CONFIG_DEFAULT_HOSTNAME "localhost"
#define CONFIG_DEFAULT_PORT 8888
#define CONFIG_DEFAULT_ACCESS_LOG "access.log"
#define CONFIG_DEFAULT_ERROR_LOG "error.log"
24
#define CONFIG_DEFAULT_LOG_LEVEL 4
25 26 27 28
#define CONFIG_DEFAULT_CHROOT 0
#define CONFIG_DEFAULT_CHUID 0
#define CONFIG_DEFAULT_USER NULL
#define CONFIG_DEFAULT_GROUP NULL
29
#define CONFIG_MASTER_UPDATE_INTERVAL 120
Jack Moffitt's avatar
Jack Moffitt committed
30

31 32 33
#ifndef _WIN32
#define CONFIG_DEFAULT_BASE_DIR "/usr/local/icecast"
#define CONFIG_DEFAULT_LOG_DIR "/usr/local/icecast/logs"
34
#define CONFIG_DEFAULT_WEBROOT_DIR "/usr/local/icecast/webroot"
35 36 37
#else
#define CONFIG_DEFAULT_BASE_DIR ".\\"
#define CONFIG_DEFAULT_LOG_DIR ".\\logs"
38
#define CONFIG_DEFAULT_WEBROOT_DIR ".\\webroot"
39 40
#endif

Jack Moffitt's avatar
Jack Moffitt committed
41 42 43 44 45 46 47 48 49
ice_config_t _configuration;
char *_config_filename;

static void _set_defaults(void);
static void _parse_root(xmlDocPtr doc, xmlNodePtr node);
static void _parse_limits(xmlDocPtr doc, xmlNodePtr node);
static void _parse_directory(xmlDocPtr doc, xmlNodePtr node);
static void _parse_paths(xmlDocPtr doc, xmlNodePtr node);
static void _parse_logging(xmlDocPtr doc, xmlNodePtr node);
50
static void _parse_security(xmlDocPtr doc, xmlNodePtr node);
Jack Moffitt's avatar
Jack Moffitt committed
51 52 53 54 55 56 57 58 59 60 61
static void _add_server(xmlDocPtr doc, xmlNodePtr node);

void config_initialize(void)
{
	memset(&_configuration, 0, sizeof(ice_config_t));
	_set_defaults();
	_config_filename = NULL;
}

void config_shutdown(void)
{
62
	ice_config_dir_t *dirnode, *nextdirnode;
63
    ice_config_t *c = &_configuration;
Jack Moffitt's avatar
Jack Moffitt committed
64

65
	if (_config_filename) free(_config_filename);
66 67 68 69 70 71 72

	if (c->location && c->location != CONFIG_DEFAULT_LOCATION) 
        xmlFree(c->location);
	if (c->admin && c->admin != CONFIG_DEFAULT_ADMIN) 
        xmlFree(c->admin);
	if (c->source_password && c->source_password != CONFIG_DEFAULT_SOURCE_PASSWORD)
        xmlFree(c->source_password);
73 74
	if (c->relay_password && c->relay_password != CONFIG_DEFAULT_SOURCE_PASSWORD)
        xmlFree(c->relay_password);
75 76 77 78 79 80
	if (c->hostname && c->hostname != CONFIG_DEFAULT_HOSTNAME) 
        xmlFree(c->hostname);
	if (c->base_dir && c->base_dir != CONFIG_DEFAULT_BASE_DIR) 
        xmlFree(c->base_dir);
	if (c->log_dir && c->log_dir != CONFIG_DEFAULT_LOG_DIR) 
        xmlFree(c->log_dir);
Michael Smith's avatar
Michael Smith committed
81
    if (c->webroot_dir && c->webroot_dir != CONFIG_DEFAULT_WEBROOT_DIR)
82
        xmlFree(c->webroot_dir);
83 84 85 86 87 88 89
	if (c->access_log && c->access_log != CONFIG_DEFAULT_ACCESS_LOG) 
        xmlFree(c->access_log);
	if (c->error_log && c->error_log != CONFIG_DEFAULT_ERROR_LOG) 
        xmlFree(c->error_log);
    if (c->bind_address) xmlFree(c->bind_address);
    if (c->user) xmlFree(c->user);
    if (c->group) xmlFree(c->group);
90 91 92
    dirnode = _configuration.dir_list;
    while(dirnode) {
        nextdirnode = dirnode->next;
93
        xmlFree(dirnode->host);
94 95 96
        free(dirnode);
        dirnode = nextdirnode;
    }
Jack Moffitt's avatar
Jack Moffitt committed
97

98
    memset(c, 0, sizeof(ice_config_t));
Jack Moffitt's avatar
Jack Moffitt committed
99 100 101 102 103 104 105 106 107 108 109
}

int config_parse_file(const char *filename)
{
	xmlDocPtr doc;
	xmlNodePtr node;

	if (filename == NULL || strcmp(filename, "") == 0) return CONFIG_EINSANE;
	
	_config_filename = (char *)strdup(filename);

Michael Smith's avatar
Michael Smith committed
110
    xmlInitParser();
Jack Moffitt's avatar
Jack Moffitt committed
111 112
	doc = xmlParseFile(_config_filename);
	if (doc == NULL) {
113
		return CONFIG_EPARSE;
Jack Moffitt's avatar
Jack Moffitt committed
114 115 116 117 118
	}

	node = xmlDocGetRootElement(doc);
	if (node == NULL) {
		xmlFreeDoc(doc);
Michael Smith's avatar
Michael Smith committed
119
        xmlCleanupParser();
Jack Moffitt's avatar
Jack Moffitt committed
120 121 122 123 124
		return CONFIG_ENOROOT;
	}

	if (strcmp(node->name, "icecast") != 0) {
		xmlFreeDoc(doc);
Michael Smith's avatar
Michael Smith committed
125
        xmlCleanupParser();
Jack Moffitt's avatar
Jack Moffitt committed
126 127 128 129 130 131
		return CONFIG_EBADROOT;
	}

	_parse_root(doc, node->xmlChildrenNode);

	xmlFreeDoc(doc);
Michael Smith's avatar
Michael Smith committed
132
    xmlCleanupParser();
Jack Moffitt's avatar
Jack Moffitt committed
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153

	return 0;
}

int config_parse_cmdline(int arg, char **argv)
{
	return 0;
}

int config_rehash(void)
{
	return 0;
}

ice_config_t *config_get_config(void)
{
	return &_configuration;
}

static void _set_defaults(void)
{
154 155
	_configuration.location = CONFIG_DEFAULT_LOCATION;
	_configuration.admin = CONFIG_DEFAULT_ADMIN;
Jack Moffitt's avatar
Jack Moffitt committed
156 157 158 159 160
	_configuration.client_limit = CONFIG_DEFAULT_CLIENT_LIMIT;
	_configuration.source_limit = CONFIG_DEFAULT_SOURCE_LIMIT;
	_configuration.threadpool_size = CONFIG_DEFAULT_THREADPOOL_SIZE;
	_configuration.client_timeout = CONFIG_DEFAULT_CLIENT_TIMEOUT;
	_configuration.header_timeout = CONFIG_DEFAULT_HEADER_TIMEOUT;
161
	_configuration.source_timeout = CONFIG_DEFAULT_SOURCE_TIMEOUT;
162
	_configuration.source_password = CONFIG_DEFAULT_SOURCE_PASSWORD;
163
	_configuration.relay_password = CONFIG_DEFAULT_RELAY_PASSWORD;
164
	_configuration.ice_login = CONFIG_DEFAULT_ICE_LOGIN;
Jack Moffitt's avatar
Jack Moffitt committed
165 166
	_configuration.touch_freq = CONFIG_DEFAULT_TOUCH_FREQ;
	_configuration.dir_list = NULL;
167
	_configuration.hostname = CONFIG_DEFAULT_HOSTNAME;
Jack Moffitt's avatar
Jack Moffitt committed
168 169
	_configuration.port = CONFIG_DEFAULT_PORT;
	_configuration.bind_address = NULL;
170 171 172
	_configuration.master_server = NULL;
	_configuration.master_server_port = CONFIG_DEFAULT_PORT;
    _configuration.master_update_interval = CONFIG_MASTER_UPDATE_INTERVAL;
173
	_configuration.master_password = NULL;
174 175
	_configuration.base_dir = CONFIG_DEFAULT_BASE_DIR;
	_configuration.log_dir = CONFIG_DEFAULT_LOG_DIR;
176
    _configuration.webroot_dir = CONFIG_DEFAULT_WEBROOT_DIR;
177 178
	_configuration.access_log = CONFIG_DEFAULT_ACCESS_LOG;
	_configuration.error_log = CONFIG_DEFAULT_ERROR_LOG;
179
	_configuration.loglevel = CONFIG_DEFAULT_LOG_LEVEL;
180 181 182 183
    _configuration.chroot = CONFIG_DEFAULT_CHROOT;
    _configuration.chuid = CONFIG_DEFAULT_CHUID;
    _configuration.user = CONFIG_DEFAULT_USER;
    _configuration.group = CONFIG_DEFAULT_GROUP;
Jack Moffitt's avatar
Jack Moffitt committed
184 185 186 187 188 189 190 191 192 193 194
}

static void _parse_root(xmlDocPtr doc, xmlNodePtr node)
{
	char *tmp;

	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "location") == 0) {
195
			if (_configuration.location && _configuration.location != CONFIG_DEFAULT_LOCATION) xmlFree(_configuration.location);
Jack Moffitt's avatar
Jack Moffitt committed
196 197
			_configuration.location = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
		} else if (strcmp(node->name, "admin") == 0) {
198
			if (_configuration.admin && _configuration.admin != CONFIG_DEFAULT_ADMIN) xmlFree(_configuration.admin);
Jack Moffitt's avatar
Jack Moffitt committed
199 200
			_configuration.admin = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
		} else if (strcmp(node->name, "source-password") == 0) {
201 202 203 204 205 206
            char *mount, *pass;
            if ((mount = (char *)xmlGetProp(node, "mount")) != NULL) {
                pass = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
                /* FIXME: This is a placeholder for per-mount passwords */
            }
            else {
207
			    if (_configuration.source_password && _configuration.source_password != CONFIG_DEFAULT_SOURCE_PASSWORD) xmlFree(_configuration.source_password);
208 209
			    _configuration.source_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
            }
210 211 212
        } else if (strcmp(node->name, "relay-password") == 0) {
			    if (_configuration.relay_password && _configuration.relay_password != CONFIG_DEFAULT_RELAY_PASSWORD) xmlFree(_configuration.relay_password);
			    _configuration.relay_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
213 214 215 216
		} else if (strcmp(node->name, "icelogin") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
			_configuration.ice_login = atoi(tmp);
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
217
		} else if (strcmp(node->name, "hostname") == 0) {
218
			if (_configuration.hostname && _configuration.hostname != CONFIG_DEFAULT_HOSTNAME) xmlFree(_configuration.hostname);
Jack Moffitt's avatar
Jack Moffitt committed
219 220 221 222
			_configuration.hostname = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
		} else if (strcmp(node->name, "port") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
			_configuration.port = atoi(tmp);
223
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
224
		} else if (strcmp(node->name, "bind-address") == 0) {
225
			if (_configuration.bind_address) xmlFree(_configuration.bind_address);
Jack Moffitt's avatar
Jack Moffitt committed
226
			_configuration.bind_address = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
227
		} else if (strcmp(node->name, "master-server") == 0) {
228
			if (_configuration.master_server) xmlFree(_configuration.master_server);
229
			_configuration.master_server = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
230 231 232
		} else if (strcmp(node->name, "master-password") == 0) {
			if (_configuration.master_password) xmlFree(_configuration.master_password);
			_configuration.master_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
233 234 235 236 237 238
		} else if (strcmp(node->name, "master-server-port") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
			_configuration.master_server_port = atoi(tmp);
        } else if (strcmp(node->name, "master-update-interval") == 0) {
            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
            _configuration.master_update_interval = atoi(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
239 240 241 242 243 244 245 246
		} else if (strcmp(node->name, "limits") == 0) {
			_parse_limits(doc, node->xmlChildrenNode);
		} else if (strcmp(node->name, "directory") == 0) {
			_parse_directory(doc, node->xmlChildrenNode);
		} else if (strcmp(node->name, "paths") == 0) {
			_parse_paths(doc, node->xmlChildrenNode);
		} else if (strcmp(node->name, "logging") == 0) {
			_parse_logging(doc, node->xmlChildrenNode);
247 248
        } else if (strcmp(node->name, "security") == 0) {
            _parse_security(doc, node->xmlChildrenNode);
Jack Moffitt's avatar
Jack Moffitt committed
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
		}
	} while ((node = node->next));
}

static void _parse_limits(xmlDocPtr doc, xmlNodePtr node)
{
	char *tmp;

	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "clients") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
			_configuration.client_limit = atoi(tmp);
264
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
265 266 267
		} else if (strcmp(node->name, "sources") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
			_configuration.source_limit = atoi(tmp);
268
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
269 270 271
		} else if (strcmp(node->name, "threadpool") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
			_configuration.threadpool_size = atoi(tmp);
272
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
273 274 275
		} else if (strcmp(node->name, "client-timeout") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
			_configuration.client_timeout = atoi(tmp);
276
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
277 278 279
		} else if (strcmp(node->name, "header-timeout") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
			_configuration.header_timeout = atoi(tmp);
280
			if (tmp) xmlFree(tmp);
281 282 283
		} else if (strcmp(node->name, "source-timeout") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
			_configuration.source_timeout = atoi(tmp);
284
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
		}
	} while ((node = node->next));
}

static void _parse_directory(xmlDocPtr doc, xmlNodePtr node)
{
	char *tmp;

	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "server") == 0) {
			_add_server(doc, node->xmlChildrenNode);
		} else if (strcmp(node->name, "touch-freq") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
			_configuration.touch_freq = atoi(tmp);
302
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
303 304 305 306 307 308 309 310 311 312 313
		}
	} while ((node = node->next));
}

static void _parse_paths(xmlDocPtr doc, xmlNodePtr node)
{
	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "basedir") == 0) {
314
			if (_configuration.base_dir && _configuration.base_dir != CONFIG_DEFAULT_BASE_DIR) xmlFree(_configuration.base_dir);
Jack Moffitt's avatar
Jack Moffitt committed
315 316
			_configuration.base_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
		} else if (strcmp(node->name, "logdir") == 0) {
317
			if (_configuration.log_dir && _configuration.log_dir != CONFIG_DEFAULT_LOG_DIR) xmlFree(_configuration.log_dir);
Jack Moffitt's avatar
Jack Moffitt committed
318
			_configuration.log_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
319
		} else if (strcmp(node->name, "webroot") == 0) {
320
			if (_configuration.webroot_dir && _configuration.webroot_dir != CONFIG_DEFAULT_WEBROOT_DIR) xmlFree(_configuration.webroot_dir);
321
			_configuration.webroot_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
322 323 324
            if(_configuration.webroot_dir[strlen(_configuration.webroot_dir)-1] == '/')
                _configuration.webroot_dir[strlen(_configuration.webroot_dir)-1] = 0;

Jack Moffitt's avatar
Jack Moffitt committed
325 326 327 328 329 330 331 332 333 334 335
		}
	} while ((node = node->next));
}

static void _parse_logging(xmlDocPtr doc, xmlNodePtr node)
{
	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "accesslog") == 0) {
336
			if (_configuration.access_log && _configuration.access_log != CONFIG_DEFAULT_ACCESS_LOG) xmlFree(_configuration.access_log);
Jack Moffitt's avatar
Jack Moffitt committed
337 338
			_configuration.access_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
		} else if (strcmp(node->name, "errorlog") == 0) {
339
			if (_configuration.error_log && _configuration.error_log != CONFIG_DEFAULT_ERROR_LOG) xmlFree(_configuration.error_log);
Jack Moffitt's avatar
Jack Moffitt committed
340
			_configuration.error_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
341 342 343
		} else if (strcmp(node->name, "loglevel") == 0) {
           char *tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
           _configuration.loglevel = atoi(tmp);
344
           if (tmp) xmlFree(tmp);
345
        }
Jack Moffitt's avatar
Jack Moffitt committed
346 347 348
	} while ((node = node->next));
}

349 350 351 352 353 354 355 356 357 358 359 360
static void _parse_security(xmlDocPtr doc, xmlNodePtr node)
{
   char *tmp;
   xmlNodePtr oldnode;

   do {
       if (node == NULL) break;
       if (xmlIsBlankNode(node)) continue;

       if (strcmp(node->name, "chroot") == 0) {
           tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
           _configuration.chroot = atoi(tmp);
361
           if (tmp) xmlFree(tmp);
362 363 364 365 366 367 368 369
       } else if (strcmp(node->name, "changeowner") == 0) {
           _configuration.chuid = 1;
           oldnode = node;
           node = node->xmlChildrenNode;
           do {
               if(node == NULL) break;
               if(xmlIsBlankNode(node)) continue;
               if(strcmp(node->name, "user") == 0) {
370
                   if(_configuration.user) xmlFree(_configuration.user);
371 372
                   _configuration.user = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
               } else if(strcmp(node->name, "group") == 0) {
373
                   if(_configuration.group) xmlFree(_configuration.group);
374 375 376 377 378 379 380 381
                   _configuration.group = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
               }
           } while((node = node->next));
           node = oldnode;
       }
   } while ((node = node->next));
}

Jack Moffitt's avatar
Jack Moffitt committed
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
static void _add_server(xmlDocPtr doc, xmlNodePtr node)
{
	ice_config_dir_t *dirnode, *server;
	int addnode;
	char *tmp;

	server = (ice_config_dir_t *)malloc(sizeof(ice_config_dir_t));
	server->touch_freq = _configuration.touch_freq;
	server->host = NULL;
	addnode = 0;
	
	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "host") == 0) {
			server->host = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
			addnode = 1;
		} else if (strcmp(node->name, "touch-freq") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
			server->touch_freq = atoi(tmp);
403
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
		}
		server->next = NULL;
	} while ((node = node->next));

	if (addnode) {
		dirnode = _configuration.dir_list;
		if (dirnode == NULL) {
			_configuration.dir_list = server;
		} else {
			while (dirnode->next) dirnode = dirnode->next;
			
			dirnode->next = server;
		}
		
		server = NULL;
		addnode = 0;
	}
	
}