1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-06-16 06:15:24 +00:00

Refactor admin.c handlers

This commit is contained in:
Marvin Scholz 2017-03-04 02:39:47 +01:00
parent e99ebfae3a
commit cf21756035
2 changed files with 133 additions and 278 deletions

View File

@ -62,46 +62,6 @@
#define COMMAND_ERROR ADMIN_COMMAND_ERROR
#define COMMAND_ANY ADMIN_COMMAND_ANY
/* Mount-specific commands (block 1-49 and 50-99) */
#define COMMAND_RAW_FALLBACK 1
#define COMMAND_RAW_METADATA_UPDATE 2
#define COMMAND_RAW_SHOW_LISTENERS 3
#define COMMAND_RAW_MOVE_CLIENTS 4
#define COMMAND_RAW_MANAGEAUTH 5
#define COMMAND_SHOUTCAST_METADATA_UPDATE 6
#define COMMAND_RAW_UPDATEMETADATA 7
#define COMMAND_TRANSFORMED_FALLBACK 50
#define COMMAND_TRANSFORMED_SHOW_LISTENERS 53
#define COMMAND_TRANSFORMED_MOVE_CLIENTS 54
#define COMMAND_TRANSFORMED_MANAGEAUTH 55
#define COMMAND_TRANSFORMED_UPDATEMETADATA 56
#define COMMAND_TRANSFORMED_METADATA_UPDATE 57
/* Global commands (block 101-199 and 201-299) */
#define COMMAND_RAW_LIST_MOUNTS 101
#define COMMAND_RAW_STATS 102
#define COMMAND_RAW_LISTSTREAM 103
#define COMMAND_PLAINTEXT_LISTSTREAM 104
#define COMMAND_RAW_QUEUE_RELOAD 105
#define COMMAND_TRANSFORMED_LIST_MOUNTS 201
#define COMMAND_TRANSFORMED_STATS 202
#define COMMAND_TRANSFORMED_LISTSTREAM 203
#define COMMAND_TRANSFORMED_QUEUE_RELOAD 205
/* Client management commands (block 301-399 and 401-499) */
#define COMMAND_RAW_KILL_CLIENT 301
#define COMMAND_RAW_KILL_SOURCE 302
#define COMMAND_TRANSFORMED_KILL_CLIENT 401
#define COMMAND_TRANSFORMED_KILL_SOURCE 402
/* Admin commands requiring no auth (block 501-599) */
#define COMMAND_BUILDM3U 501
/* Experimental features (e.g. in feature branches) (block 801-899) */
/* Private features (in branches not for merge with master) (block 901-999) */
#define FALLBACK_RAW_REQUEST "fallbacks"
#define FALLBACK_TRANSFORMED_REQUEST "fallbacks.xsl"
#define SHOUTCAST_METADATA_REQUEST "admin.cgi"
@ -133,98 +93,99 @@
#define DEFAULT_TRANSFORMED_REQUEST ""
#define BUILDM3U_RAW_REQUEST "buildm3u"
typedef struct admin_command_tag {
const int id;
const char *name;
const int type;
const int format;
} admin_command_t;
typedef void (*request_function_ptr)(client_t *, source_t *, int);
/*
COMMAND_TRANSFORMED_METADATA_UPDATE -> METADATA_TRANSFORMED_REQUEST
COMMAND_TRANSFORMED_UPDATEMETADATA -> UPDATEMETADATA_TRANSFORMED_REQUEST
*/
typedef struct admin_command_handler {
const char *route;
const int type;
const int format;
const request_function_ptr function;
} admin_command_handler_t;
static const admin_command_t commands[] = {
{COMMAND_RAW_FALLBACK, FALLBACK_RAW_REQUEST, ADMINTYPE_MOUNT, RAW},
{COMMAND_TRANSFORMED_FALLBACK, FALLBACK_TRANSFORMED_REQUEST, ADMINTYPE_MOUNT, TRANSFORMED},
{COMMAND_RAW_METADATA_UPDATE, METADATA_RAW_REQUEST, ADMINTYPE_MOUNT, RAW},
{COMMAND_SHOUTCAST_METADATA_UPDATE, SHOUTCAST_METADATA_REQUEST, ADMINTYPE_MOUNT, TRANSFORMED},
{COMMAND_TRANSFORMED_METADATA_UPDATE, METADATA_TRANSFORMED_REQUEST, ADMINTYPE_MOUNT, TRANSFORMED},
{COMMAND_RAW_SHOW_LISTENERS, LISTCLIENTS_RAW_REQUEST, ADMINTYPE_MOUNT, RAW},
{COMMAND_TRANSFORMED_SHOW_LISTENERS, LISTCLIENTS_TRANSFORMED_REQUEST, ADMINTYPE_MOUNT, TRANSFORMED},
{COMMAND_RAW_STATS, STATS_RAW_REQUEST, ADMINTYPE_HYBRID, RAW},
{COMMAND_TRANSFORMED_STATS, STATS_TRANSFORMED_REQUEST, ADMINTYPE_HYBRID, TRANSFORMED},
{COMMAND_RAW_STATS, "stats.xml", ADMINTYPE_HYBRID, RAW}, /* The old way */
{COMMAND_RAW_QUEUE_RELOAD, QUEUE_RELOAD_RAW_REQUEST, ADMINTYPE_GENERAL, RAW},
{COMMAND_TRANSFORMED_QUEUE_RELOAD, QUEUE_RELOAD_TRANSFORMED_REQUEST, ADMINTYPE_GENERAL, TRANSFORMED},
{COMMAND_RAW_LIST_MOUNTS, LISTMOUNTS_RAW_REQUEST, ADMINTYPE_GENERAL, RAW},
{COMMAND_TRANSFORMED_LIST_MOUNTS, LISTMOUNTS_TRANSFORMED_REQUEST, ADMINTYPE_GENERAL, TRANSFORMED},
{COMMAND_RAW_LISTSTREAM, STREAMLIST_RAW_REQUEST, ADMINTYPE_GENERAL, RAW},
{COMMAND_PLAINTEXT_LISTSTREAM, STREAMLIST_PLAINTEXT_REQUEST, ADMINTYPE_GENERAL, PLAINTEXT},
{COMMAND_TRANSFORMED_LISTSTREAM, STREAMLIST_TRANSFORMED_REQUEST, ADMINTYPE_GENERAL, TRANSFORMED},
{COMMAND_RAW_MOVE_CLIENTS, MOVECLIENTS_RAW_REQUEST, ADMINTYPE_MOUNT, RAW},
{COMMAND_TRANSFORMED_MOVE_CLIENTS, MOVECLIENTS_TRANSFORMED_REQUEST, ADMINTYPE_HYBRID, TRANSFORMED},
{COMMAND_RAW_KILL_CLIENT, KILLCLIENT_RAW_REQUEST, ADMINTYPE_MOUNT, RAW},
{COMMAND_TRANSFORMED_KILL_CLIENT, KILLCLIENT_TRANSFORMED_REQUEST, ADMINTYPE_MOUNT, TRANSFORMED},
{COMMAND_RAW_KILL_SOURCE, KILLSOURCE_RAW_REQUEST, ADMINTYPE_MOUNT, RAW},
{COMMAND_TRANSFORMED_KILL_SOURCE, KILLSOURCE_TRANSFORMED_REQUEST, ADMINTYPE_MOUNT, TRANSFORMED},
{COMMAND_RAW_MANAGEAUTH, MANAGEAUTH_RAW_REQUEST, ADMINTYPE_GENERAL, RAW},
{COMMAND_TRANSFORMED_MANAGEAUTH, MANAGEAUTH_TRANSFORMED_REQUEST, ADMINTYPE_GENERAL, TRANSFORMED},
{COMMAND_RAW_UPDATEMETADATA, UPDATEMETADATA_RAW_REQUEST, ADMINTYPE_MOUNT, RAW},
{COMMAND_TRANSFORMED_UPDATEMETADATA, UPDATEMETADATA_TRANSFORMED_REQUEST, ADMINTYPE_MOUNT, TRANSFORMED},
{COMMAND_BUILDM3U, BUILDM3U_RAW_REQUEST, ADMINTYPE_MOUNT, RAW},
{COMMAND_TRANSFORMED_STATS, DEFAULT_TRANSFORMED_REQUEST, ADMINTYPE_HYBRID, TRANSFORMED},
{COMMAND_TRANSFORMED_STATS, DEFAULT_RAW_REQUEST, ADMINTYPE_HYBRID, TRANSFORMED},
{COMMAND_ANY, "*", ADMINTYPE_GENERAL, TRANSFORMED} /* for ACL framework */
static void command_fallback (client_t *client, source_t *source, int response);
static void command_metadata (client_t *client, source_t *source, int response);
static void command_shoutcast_metadata (client_t *client, source_t *source, int response);
static void command_show_listeners (client_t *client, source_t *source, int response);
static void command_stats (client_t *client, source_t *source, int response);
static void command_queue_reload (client_t *client, source_t *source, int response);
static void command_list_mounts (client_t *client, source_t *source, int response);
static void command_move_clients (client_t *client, source_t *source, int response);
static void command_kill_client (client_t *client, source_t *source, int response);
static void command_kill_source (client_t *client, source_t *source, int response);
static void command_manageauth (client_t *client, source_t *source, int response);
static void command_updatemetadata (client_t *client, source_t *source, int response);
static void command_buildm3u (client_t *client, source_t *source, int response);
static const admin_command_handler_t handlers[] = {
{ "*", ADMINTYPE_GENERAL, TRANSFORMED, NULL }, /* for ACL framework */
{ FALLBACK_RAW_REQUEST, ADMINTYPE_MOUNT, RAW, command_fallback },
{ FALLBACK_TRANSFORMED_REQUEST, ADMINTYPE_MOUNT, TRANSFORMED, command_fallback },
{ METADATA_RAW_REQUEST, ADMINTYPE_MOUNT, RAW, command_metadata },
{ METADATA_TRANSFORMED_REQUEST, ADMINTYPE_MOUNT, TRANSFORMED, command_metadata },
{ SHOUTCAST_METADATA_REQUEST, ADMINTYPE_MOUNT, TRANSFORMED, command_shoutcast_metadata },
{ LISTCLIENTS_RAW_REQUEST, ADMINTYPE_MOUNT, RAW, command_show_listeners },
{ LISTCLIENTS_TRANSFORMED_REQUEST, ADMINTYPE_MOUNT, TRANSFORMED, command_show_listeners },
{ STATS_RAW_REQUEST, ADMINTYPE_HYBRID, RAW, command_stats },
{ STATS_TRANSFORMED_REQUEST, ADMINTYPE_HYBRID, TRANSFORMED, command_stats },
{ "stats.xml", ADMINTYPE_HYBRID, RAW, command_stats },
{ QUEUE_RELOAD_RAW_REQUEST, ADMINTYPE_GENERAL, RAW, command_queue_reload },
{ QUEUE_RELOAD_TRANSFORMED_REQUEST, ADMINTYPE_GENERAL, TRANSFORMED, command_queue_reload },
{ LISTMOUNTS_RAW_REQUEST, ADMINTYPE_GENERAL, RAW, command_list_mounts },
{ LISTMOUNTS_TRANSFORMED_REQUEST, ADMINTYPE_GENERAL, TRANSFORMED, command_list_mounts },
{ STREAMLIST_RAW_REQUEST, ADMINTYPE_GENERAL, RAW, command_list_mounts },
{ STREAMLIST_PLAINTEXT_REQUEST, ADMINTYPE_GENERAL, PLAINTEXT, command_list_mounts },
{ STREAMLIST_TRANSFORMED_REQUEST, ADMINTYPE_GENERAL, TRANSFORMED, command_list_mounts },
{ MOVECLIENTS_RAW_REQUEST, ADMINTYPE_MOUNT, RAW, command_move_clients },
{ MOVECLIENTS_TRANSFORMED_REQUEST, ADMINTYPE_HYBRID, TRANSFORMED, command_move_clients },
{ KILLCLIENT_RAW_REQUEST, ADMINTYPE_MOUNT, RAW, command_kill_client },
{ KILLCLIENT_TRANSFORMED_REQUEST, ADMINTYPE_MOUNT, TRANSFORMED, command_kill_client },
{ KILLSOURCE_RAW_REQUEST, ADMINTYPE_MOUNT, RAW, command_kill_source },
{ KILLSOURCE_TRANSFORMED_REQUEST, ADMINTYPE_MOUNT, TRANSFORMED, command_kill_source },
{ MANAGEAUTH_RAW_REQUEST, ADMINTYPE_GENERAL, RAW, command_manageauth },
{ MANAGEAUTH_TRANSFORMED_REQUEST, ADMINTYPE_GENERAL, TRANSFORMED, command_manageauth },
{ UPDATEMETADATA_RAW_REQUEST, ADMINTYPE_MOUNT, RAW, command_updatemetadata },
{ UPDATEMETADATA_TRANSFORMED_REQUEST, ADMINTYPE_MOUNT, TRANSFORMED, command_updatemetadata },
{ BUILDM3U_RAW_REQUEST, ADMINTYPE_MOUNT, RAW, command_buildm3u },
{ DEFAULT_TRANSFORMED_REQUEST, ADMINTYPE_HYBRID, TRANSFORMED, command_stats },
{ DEFAULT_RAW_REQUEST, ADMINTYPE_HYBRID, TRANSFORMED, command_stats }
};
#define HANDLERS_COUNT (sizeof(handlers)/sizeof(*handlers))
int admin_get_command(const char *command)
{
size_t i;
for (i = 0; i < (sizeof(commands)/sizeof(*commands)); i++)
if (strcmp(commands[i].name, command) == 0)
return commands[i].id;
for (i = 0; i < HANDLERS_COUNT; i++)
if (strcmp(handlers[i].route, command) == 0)
return i;
return COMMAND_ERROR;
}
/* Get the command handler for command or NULL
*/
const admin_command_handler_t* admin_get_handler(int command)
{
if (command > 0 && command < HANDLERS_COUNT)
return &handlers[command];
return NULL;
}
/* Get the command type for command
* If the command is invalid, ADMINTYPE_ERROR is returned.
*/
int admin_get_command_type(int command)
{
size_t i;
const admin_command_handler_t* handler = admin_get_handler(command);
if (command == ADMIN_COMMAND_ERROR || command == COMMAND_ANY)
return ADMINTYPE_ERROR;
for (i = 0; i < (sizeof(commands)/sizeof(*commands)); i++)
if (commands[i].id == command)
return commands[i].type;
if (handler != NULL)
return handler->type;
return ADMINTYPE_ERROR;
}
static void command_fallback(client_t *client, source_t *source, int response);
static void command_metadata(client_t *client, source_t *source, int response);
static void command_shoutcast_metadata(client_t *client, source_t *source);
static void command_show_listeners(client_t *client, source_t *source,
int response);
static void command_move_clients(client_t *client, source_t *source,
int response);
static void command_stats(client_t *client, const char *mount, int response);
static void command_queue_reload(client_t *client, int response);
static void command_list_mounts(client_t *client, int response);
static void command_kill_client(client_t *client, source_t *source,
int response);
static void command_manageauth(client_t *client, int response);
static void command_buildm3u(client_t *client, const char *mount);
static void command_kill_source(client_t *client, source_t *source,
int response);
static void command_updatemetadata(client_t *client, source_t *source,
int response);
static void admin_handle_mount_request(client_t *client, source_t *source);
static void admin_handle_general_request(client_t *client);
/* build an XML doc containing information about currently running sources.
* If a mountpoint is passed then that source will not be added to the XML
* doc even if the source is running */
@ -377,37 +338,29 @@ void admin_send_response(xmlDocPtr doc,
}
}
void admin_handle_request(client_t *client, const char *uri)
{
const char *mount, *command_string;
const char *mount;
const admin_command_handler_t* handler;
source_t *source = NULL;
ICECAST_LOG_DEBUG("Admin request (%s)", uri);
if (!((strcmp(uri, "/admin.cgi") == 0) ||
(strncmp("/admin/", uri, 7) == 0))) {
ICECAST_LOG_ERROR("Internal error: admin request isn't");
client_send_error(client, 401, 1, "You need to authenticate\r\n");
return;
}
ICECAST_LOG_DEBUG("Got admin request '%s'", uri);
if (strcmp(uri, "/admin.cgi") == 0) {
command_string = uri + 1;
}
else {
command_string = uri + 7;
}
handler = admin_get_handler(client->admin_command);
ICECAST_LOG_DEBUG("Got command (%s)", command_string);
if (client->admin_command <= 0) {
ICECAST_LOG_ERROR("Error parsing command string or unrecognised command: %s",
command_string);
/* Check if admin command is valid */
if (handler == NULL) {
ICECAST_LOG_ERROR("Error parsing command string or unrecognised command: %H",
uri);
client_send_error(client, 400, 0, "Unrecognised command");
return;
}
/* Check ACL */
if (acl_test_admin(client->acl, client->admin_command) != ACL_POLICY_ALLOW) {
if (client->admin_command == COMMAND_RAW_METADATA_UPDATE &&
/* ACL disallows, check exceptions */
if ((handler->function == command_metadata && handler->format == RAW) &&
(acl_test_method(client->acl, httpp_req_source) == ACL_POLICY_ALLOW ||
acl_test_method(client->acl, httpp_req_put) == ACL_POLICY_ALLOW)) {
ICECAST_LOG_DEBUG("Granted right to call COMMAND_RAW_METADATA_UPDATE to "
@ -420,155 +373,42 @@ void admin_handle_request(client_t *client, const char *uri)
mount = httpp_get_query_param(client->parser, "mount");
/* Find mountpoint source */
if(mount != NULL) {
source_t *source;
/* this request does not require auth but can apply to files on webroot */
if (client->admin_command == COMMAND_BUILDM3U) {
command_buildm3u(client, mount);
return;
}
/* This is a mount request, handle it as such */
avl_tree_rlock(global.source_tree);
source = source_find_mount_raw(mount);
/* No Source found */
if (source == NULL) {
ICECAST_LOG_WARN("Admin command %s on non-existent source %s",
command_string, mount);
avl_tree_unlock(global.source_tree);
ICECAST_LOG_WARN("Admin command \"%H\" on non-existent source \"%H\"",
uri, mount);
client_send_error(client, 400, 0, "Source does not exist");
} else {
if (source->running == 0 && source->on_demand == 0) {
avl_tree_unlock(global.source_tree);
ICECAST_LOG_INFO("Received admin command %s on unavailable mount \"%s\"",
command_string, mount);
client_send_error(client, 400, 0, "Source is not available");
return;
}
if (client->admin_command == COMMAND_SHOUTCAST_METADATA_UPDATE &&
source->shoutcast_compat == 0) {
avl_tree_unlock(global.source_tree);
ICECAST_LOG_ERROR("illegal change of metadata on non-shoutcast "
"compatible stream");
client_send_error(client, 400, 0, "illegal metadata call");
return;
}
ICECAST_LOG_INFO("Received admin command %s on mount \"%s\"",
command_string, mount);
admin_handle_mount_request(client, source);
return;
} /* No Source running */
else if (source->running == 0 && source->on_demand == 0) {
avl_tree_unlock(global.source_tree);
ICECAST_LOG_INFO("Received admin command \"%H\" on unavailable mount \"%H\"",
uri, mount);
client_send_error(client, 400, 0, "Source is not available");
return;
}
} else {
admin_handle_general_request(client);
ICECAST_LOG_INFO("Received admin command %H on mount '%s'",
uri, mount);
}
}
static void admin_handle_general_request(client_t *client)
{
switch(client->admin_command) {
case COMMAND_RAW_STATS:
command_stats(client, NULL, RAW);
break;
case COMMAND_RAW_QUEUE_RELOAD:
command_queue_reload(client, RAW);
break;
case COMMAND_RAW_LIST_MOUNTS:
command_list_mounts(client, RAW);
break;
case COMMAND_RAW_LISTSTREAM:
command_list_mounts(client, RAW);
break;
case COMMAND_PLAINTEXT_LISTSTREAM:
command_list_mounts(client, PLAINTEXT);
break;
case COMMAND_TRANSFORMED_STATS:
command_stats(client, NULL, TRANSFORMED);
break;
case COMMAND_TRANSFORMED_QUEUE_RELOAD:
command_queue_reload(client, TRANSFORMED);
break;
case COMMAND_TRANSFORMED_LIST_MOUNTS:
command_list_mounts(client, TRANSFORMED);
break;
case COMMAND_TRANSFORMED_LISTSTREAM:
command_list_mounts(client, TRANSFORMED);
break;
case COMMAND_TRANSFORMED_MOVE_CLIENTS:
command_list_mounts(client, TRANSFORMED);
break;
case COMMAND_TRANSFORMED_MANAGEAUTH:
command_manageauth(client, TRANSFORMED);
break;
case COMMAND_RAW_MANAGEAUTH:
command_manageauth(client, RAW);
break;
default:
ICECAST_LOG_WARN("General admin request not recognised");
client_send_error(client, 400, 0, "Unknown admin request");
if (handler->type == ADMINTYPE_MOUNT && !source) {
client_send_error(client, 400, 0, "Mount parameter mandatory");
return;
}
}
static void admin_handle_mount_request(client_t *client, source_t *source)
{
switch(client->admin_command) {
case COMMAND_RAW_STATS:
command_stats(client, source->mount, RAW);
break;
case COMMAND_RAW_FALLBACK:
command_fallback(client, source, RAW);
break;
case COMMAND_RAW_METADATA_UPDATE:
command_metadata(client, source, RAW);
break;
case COMMAND_TRANSFORMED_METADATA_UPDATE:
command_metadata(client, source, TRANSFORMED);
break;
case COMMAND_SHOUTCAST_METADATA_UPDATE:
command_shoutcast_metadata(client, source);
break;
case COMMAND_RAW_SHOW_LISTENERS:
command_show_listeners(client, source, RAW);
break;
case COMMAND_RAW_MOVE_CLIENTS:
command_move_clients(client, source, RAW);
break;
case COMMAND_RAW_KILL_CLIENT:
command_kill_client(client, source, RAW);
break;
case COMMAND_RAW_KILL_SOURCE:
command_kill_source(client, source, RAW);
break;
case COMMAND_TRANSFORMED_STATS:
command_stats(client, source->mount, TRANSFORMED);
break;
case COMMAND_TRANSFORMED_FALLBACK:
command_fallback(client, source, RAW);
break;
case COMMAND_TRANSFORMED_SHOW_LISTENERS:
command_show_listeners(client, source, TRANSFORMED);
break;
case COMMAND_TRANSFORMED_MOVE_CLIENTS:
command_move_clients(client, source, TRANSFORMED);
break;
case COMMAND_TRANSFORMED_KILL_CLIENT:
command_kill_client(client, source, TRANSFORMED);
break;
case COMMAND_TRANSFORMED_KILL_SOURCE:
command_kill_source(client, source, TRANSFORMED);
break;
case COMMAND_TRANSFORMED_UPDATEMETADATA:
command_updatemetadata(client, source, TRANSFORMED);
break;
case COMMAND_RAW_UPDATEMETADATA:
command_updatemetadata(client, source, RAW);
break;
default:
ICECAST_LOG_WARN("Mount request not recognised");
client_send_error(client, 400, 0, "Mount request unknown");
break;
handler->function(client, source, handler->format);
if (source) {
avl_tree_unlock(global.source_tree);
}
return;
}
static void html_success(client_t *client, char *message)
@ -752,8 +592,9 @@ static void command_show_listeners(client_t *client,
xmlFreeDoc(doc);
}
static void command_buildm3u(client_t *client, const char *mount)
static void command_buildm3u(client_t *client, source_t *source, int format)
{
const char *mount = source->mount;
const char *username = NULL;
const char *password = NULL;
ice_config_t *config;
@ -814,7 +655,7 @@ xmlNodePtr admin_add_role_to_authentication(auth_t *auth, xmlNodePtr parent)
return rolenode;
}
static void command_manageauth(client_t *client, int response)
static void command_manageauth(client_t *client, source_t *source, int response)
{
xmlDocPtr doc;
xmlNodePtr node, rolenode, usersnode, msgnode;
@ -1057,7 +898,7 @@ static void command_metadata(client_t *client,
plugin = source->format;
if (source->client && strcmp(client->con->ip, source->client->con->ip) != 0)
if (response == RAW && acl_test_admin(client->acl, COMMAND_RAW_METADATA_UPDATE) != ACL_POLICY_ALLOW)
if (response == RAW && acl_test_admin(client->acl, client->admin_command) != ACL_POLICY_ALLOW)
same_ip = 0;
if (same_ip && plugin && plugin->set_tag) {
@ -1090,7 +931,9 @@ static void command_metadata(client_t *client,
xmlFreeDoc(doc);
}
static void command_shoutcast_metadata(client_t *client, source_t *source)
static void command_shoutcast_metadata(client_t *client,
source_t *source,
int format)
{
const char *action;
const char *value;
@ -1098,6 +941,13 @@ static void command_shoutcast_metadata(client_t *client, source_t *source)
ICECAST_LOG_DEBUG("Got shoutcast metadata update request");
if (source->shoutcast_compat == 0) {
ICECAST_LOG_ERROR("illegal change of metadata on non-shoutcast "
"compatible stream");
client_send_error(client, 400, 0, "illegal metadata call");
return;
}
if (source->parser->req_type == httpp_req_put) {
ICECAST_LOG_ERROR("Got legacy shoutcast-style metadata update command "
"on source connected with PUT at mountpoint %s", source->mount);
@ -1111,7 +961,7 @@ static void command_shoutcast_metadata(client_t *client, source_t *source)
return;
}
if (source->client && strcmp (client->con->ip, source->client->con->ip) != 0)
if (acl_test_admin(client->acl, COMMAND_RAW_METADATA_UPDATE) != ACL_POLICY_ALLOW)
if (acl_test_admin(client->acl, client->admin_command) != ACL_POLICY_ALLOW)
same_ip = 0;
if (same_ip && source->format && source->format->set_tag) {
@ -1126,8 +976,9 @@ static void command_shoutcast_metadata(client_t *client, source_t *source)
}
}
static void command_stats(client_t *client, const char *mount, int response)
static void command_stats(client_t *client, source_t *source, int response)
{
const char *mount = (source) ? source->mount : NULL;
xmlDocPtr doc;
ICECAST_LOG_DEBUG("Stats request, sending xml stats");
@ -1138,7 +989,7 @@ static void command_stats(client_t *client, const char *mount, int response)
return;
}
static void command_queue_reload(client_t *client, int response)
static void command_queue_reload(client_t *client, source_t *source, int response)
{
xmlDocPtr doc;
xmlNodePtr node;
@ -1158,7 +1009,7 @@ static void command_queue_reload(client_t *client, int response)
}
static void command_list_mounts(client_t *client, int response)
static void command_list_mounts(client_t *client, source_t *source, int response)
{
ICECAST_LOG_DEBUG("List mounts request");

View File

@ -914,11 +914,15 @@ static void _handle_get_request(client_t *client, char *uri) {
stats_event_inc(NULL, "client_connections");
/* Dispatch all admin requests */
if ((strcmp(uri, "/admin.cgi") == 0) ||
(strncmp(uri, "/admin/", 7) == 0)) {
/* Dispatch legacy admin.cgi requests */
if (strcmp(uri, "/admin.cgi") == 0) {
ICECAST_LOG_DEBUG("Client %p requesting admin interface.", client);
admin_handle_request(client, uri);
admin_handle_request(client, uri + 1);
return;
} /* Dispatch all admin requests */
else if (strncmp(uri, "/admin/", 7) == 0) {
ICECAST_LOG_DEBUG("Client %p requesting admin interface.", client);
admin_handle_request(client, uri + 7);
return;
}