diff --git a/src/admin.c b/src/admin.c index 5b49617e..262bda9e 100644 --- a/src/admin.c +++ b/src/admin.c @@ -344,6 +344,7 @@ void admin_handle_request(client_t *client, const char *uri) const char *mount; const admin_command_handler_t* handler; source_t *source = NULL; + admin_format_t format; ICECAST_LOG_DEBUG("Got admin request '%s'", uri); @@ -405,7 +406,13 @@ void admin_handle_request(client_t *client, const char *uri) return; } - handler->function(client, source, handler->format); + if (handler->format == ADMIN_FORMAT_AUTO) { + format = client_get_admin_format_by_content_negotiation(client); + } else { + format = handler->format; + } + + handler->function(client, source, format); if (source) { avl_tree_unlock(global.source_tree); } diff --git a/src/admin.h b/src/admin.h index 66a6a8d8..494c5341 100644 --- a/src/admin.h +++ b/src/admin.h @@ -17,6 +17,14 @@ #include #include +/* formats */ +typedef enum { + ADMIN_FORMAT_AUTO, + ADMIN_FORMAT_RAW, + ADMIN_FORMAT_TRANSFORMED, + ADMIN_FORMAT_PLAINTEXT +} admin_format_t; + #include "refbuf.h" #include "client.h" #include "source.h" @@ -28,13 +36,6 @@ #define ADMINTYPE_MOUNT 2 #define ADMINTYPE_HYBRID (ADMINTYPE_GENERAL|ADMINTYPE_MOUNT) -/* formats */ -typedef enum { - ADMIN_FORMAT_RAW, - ADMIN_FORMAT_TRANSFORMED, - ADMIN_FORMAT_PLAINTEXT -} admin_format_t; - /* special commands */ #define ADMIN_COMMAND_ERROR (-1) #define ADMIN_COMMAND_ANY 0 /* for ACL framework */ diff --git a/src/auth.h b/src/auth.h index ce676823..f0795ebb 100644 --- a/src/auth.h +++ b/src/auth.h @@ -19,7 +19,7 @@ #endif struct source_tag; -struct auth_tag; +typedef struct auth_tag auth_t; #include #include @@ -66,7 +66,7 @@ typedef struct auth_client_tag } auth_client; -typedef struct auth_tag +struct auth_tag { /* unique ID */ unsigned long id; @@ -113,7 +113,7 @@ typedef struct auth_tag acl_t *acl; /* role name for later matching, may be NULL if no role name was given in config */ char *role; -} auth_t; +}; typedef struct auth_stack_tag auth_stack_t; diff --git a/src/client.c b/src/client.c index 18288f6a..d7b17d1a 100644 --- a/src/client.c +++ b/src/client.c @@ -366,6 +366,26 @@ static inline void client_send_500(client_t *client, const char *message) client_destroy(client); } +admin_format_t client_get_admin_format_by_content_negotiation(client_t *client) +{ + const char *pref; + + if (!client || !client->parser) + return CLIENT_DEFAULT_ADMIN_FORMAT; + + pref = util_http_select_best(httpp_getvar(client->parser, "accept"), "text/xml", "text/html", "text/plain", (const char*)NULL); + + if (strcmp(pref, "text/xml") == 0) { + return ADMIN_FORMAT_RAW; + } else if (strcmp(pref, "text/html") == 0) { + return ADMIN_FORMAT_TRANSFORMED; + } else if (strcmp(pref, "text/plain") == 0) { + return ADMIN_FORMAT_PLAINTEXT; + } else { + return CLIENT_DEFAULT_ADMIN_FORMAT; + } +} + /* helper function for sending the data to a client */ int client_send_bytes(client_t *client, const void *buf, unsigned len) { diff --git a/src/client.h b/src/client.h index c61a9579..7ab8e3f6 100644 --- a/src/client.h +++ b/src/client.h @@ -19,14 +19,19 @@ #ifndef __CLIENT_H__ #define __CLIENT_H__ +typedef struct _client_tag client_t; + #include "errors.h" #include "connection.h" #include "refbuf.h" #include "acl.h" #include "cfgfile.h" +#include "admin.h" #include "common/httpp/httpp.h" #include "common/httpp/encoding.h" +#define CLIENT_DEFAULT_ADMIN_FORMAT ADMIN_FORMAT_TRANSFORMED + typedef enum _protocol_tag { ICECAST_PROTOCOL_HTTP = 0, ICECAST_PROTOCOL_SHOUTCAST @@ -41,7 +46,7 @@ typedef enum _reuse_tag { ICECAST_REUSE_UPGRADETLS } reuse_t; -typedef struct _client_tag +struct _client_tag { /* mode of operation for this client */ operation_mode mode; @@ -106,13 +111,14 @@ typedef struct _client_tag /* function to check if refbuf needs updating */ int (*check_buffer)(struct source_tag *source, struct _client_tag *client); -} client_t; +}; int client_create (client_t **c_ptr, connection_t *con, http_parser_t *parser); void client_destroy(client_t *client); void client_send_error_by_id(client_t *client, icecast_error_id_t id); void client_send_101(client_t *client, reuse_t reuse); void client_send_426(client_t *client, reuse_t reuse); +admin_format_t client_get_admin_format_by_content_negotiation(client_t *client); int client_send_bytes (client_t *client, const void *buf, unsigned len); int client_read_bytes (client_t *client, void *buf, unsigned len); void client_set_queue (client_t *client, refbuf_t *refbuf); diff --git a/src/source.h b/src/source.h index ea527283..8a5e1f15 100644 --- a/src/source.h +++ b/src/source.h @@ -14,6 +14,8 @@ #ifndef __SOURCE_H__ #define __SOURCE_H__ +typedef struct source_tag source_t; + #include "cfgfile.h" #include "yp.h" #include "util.h" @@ -23,7 +25,7 @@ #include -typedef struct source_tag +struct source_tag { mutex_t lock; client_t *client; @@ -82,7 +84,7 @@ typedef struct source_tag playlist_t *history; -} source_t; +}; source_t *source_reserve (const char *mount); void *source_client_thread (void *arg);