int command_list_mounts(client_t *client, int response) { DEBUG0("List mounts request"); client_set_queue (client, NULL); client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE); if (response == TEXT) { redirector_update (client); snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"); client->refbuf->len = strlen (client->refbuf->data); client->respcode = 200; if (strcmp (httpp_getvar (client->parser, HTTPP_VAR_URI), "/admin/streams") == 0) client->refbuf->next = stats_get_streams (1); else client->refbuf->next = stats_get_streams (0); return fserve_setup_client (client); } else { xmlDocPtr doc; int show_listeners = httpp_get_query_param (client->parser, "with_listeners") ? 1 : 0; avl_tree_rlock (global.source_tree); doc = admin_build_sourcelist (NULL, show_listeners); avl_tree_unlock (global.source_tree); return admin_send_response (doc, client, response, "listmounts.xsl"); } }
int fserve_kill_client (client_t *client, const char *mount, int response) { int loop = 2, id; fbinfo finfo; xmlDocPtr doc; xmlNodePtr node; const char *idtext, *v = "0"; char buf[50]; finfo.flags = 0; finfo.mount = (char*)mount; finfo.limit = 0; finfo.fallback = NULL; idtext = httpp_get_query_param (client->parser, "id"); if (idtext == NULL) return client_send_400 (client, "missing parameter id"); id = atoi(idtext); doc = xmlNewDoc(XMLSTR("1.0")); node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL); xmlDocSetRootElement(doc, node); snprintf (buf, sizeof(buf), "Client %d not found", id); avl_tree_rlock (fh_cache); while (1) { avl_node *node; fh_node *fh = find_fh (&finfo); if (fh) { thread_mutex_lock (&fh->lock); avl_tree_unlock (fh_cache); node = avl_get_first (fh->clients); while (node) { client_t *listener = (client_t *)node->key; if (listener->connection.id == id) { listener->connection.error = 1; snprintf (buf, sizeof(buf), "Client %d removed", id); v = "1"; loop = 0; break; } node = avl_get_next (node); } thread_mutex_unlock (&fh->lock); avl_tree_rlock (fh_cache); } if (loop == 0) break; loop--; if (loop == 1) finfo.flags = FS_FALLBACK; } avl_tree_unlock (fh_cache); xmlNewChild (node, NULL, XMLSTR("message"), XMLSTR(buf)); xmlNewChild (node, NULL, XMLSTR("return"), XMLSTR(v)); return admin_send_response (doc, client, response, "response.xsl"); }
static int command_require (client_t *client, const char *name, const char **var) { *var = httpp_get_query_param((client)->parser, (name)); if (*var == NULL) return -1; return 0; }
/* Add listener to the pending lists of either the source or fserve thread. This can be run * from the connection or auth thread context. return -1 to indicate that client has been * terminated, 0 for receiving content. */ static int add_authenticated_listener (const char *mount, mount_proxy *mountinfo, client_t *client) { int ret = 0; if (client->parser->req_type != httpp_req_head) client->flags |= CLIENT_AUTHENTICATED; /* some win32 setups do not do TCP win scaling well, so allow an override */ if (mountinfo && mountinfo->so_sndbuf > 0) sock_set_send_buffer (client->connection.sock, mountinfo->so_sndbuf); /* check whether we are processing a streamlist request for slaves */ if (strcmp (mount, "/admin/streams") == 0) { client->flags |= CLIENT_IS_SLAVE; if (client->parser->req_type == httpp_req_stats) { stats_add_listener (client, STATS_SLAVE|STATS_GENERAL); return 0; } mount = httpp_get_query_param (client->parser, "mount"); if (mount == NULL) { command_list_mounts (client, TEXT); return 0; } mountinfo = config_find_mount (config_get_config_unlocked(), mount); } /* 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 (mount) == XSLT_CONTENT) { /* If the file exists, then transform it, otherwise, write a 404 */ DEBUG0("Stats request, sending XSL transformed stats"); return stats_transform_xslt (client, mount); } ret = source_add_listener (mount, mountinfo, client); if (ret == -2) { if (mountinfo && mountinfo->file_seekable == 0) { DEBUG1 ("disable seek on file matching %s", mountinfo->mountname); httpp_deletevar (client->parser, "range"); client->flags |= CLIENT_NO_CONTENT_LENGTH; } ret = fserve_client_create (client, mount); } return ret; }
static int command_list_log (client_t *client, int response) { refbuf_t *content; const char *logname = httpp_get_query_param (client->parser, "log"); int log = -1; ice_config_t *config; if (logname == NULL) return client_send_400 (client, "No log specified"); config = config_get_config (); if (strcmp (logname, "errorlog") == 0) log = config->error_log.logid; else if (strcmp (logname, "accesslog") == 0) log = config->access_log.logid; else if (strcmp (logname, "playlistlog") == 0) log = config->playlist_log.logid; if (log < 0) { config_release_config(); WARN1 ("request to show unknown log \"%s\"", logname); return client_send_400 (client, "unknown"); } content = refbuf_new (0); log_contents (log, &content->data, &content->len); config_release_config(); if (response == XSLT) { xmlNodePtr xmlnode; xmlDocPtr doc; doc = xmlNewDoc(XMLSTR("1.0")); xmlnode = xmlNewDocNode(doc, NULL, XMLSTR("icestats"), NULL); xmlDocSetRootElement(doc, xmlnode); xmlNewTextChild (xmlnode, NULL, XMLSTR("log"), XMLSTR(content->data)); refbuf_release (content); return admin_send_response (doc, client, XSLT, "showlog.xsl"); } else { refbuf_t *http = refbuf_new (100); int len = snprintf (http->data, 100, "%s", "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n"); http->len = len; http->next = content; client->respcode = 200; client_set_queue (client, http); return fserve_setup_client (client); } }
void stats_transform_xslt(client_t *client, const char *uri) { xmlDocPtr doc; char *xslpath = util_get_path_from_normalised_uri(uri); const char *mount = httpp_get_query_param(client->parser, "mount"); doc = stats_get_xml(0, mount, client->mode); xslt_transform(doc, xslpath, client); xmlFreeDoc(doc); free(xslpath); }
/* catch all function for admin requests. If file has xsl extension then * transform it using the available stats, else send the XML tree of the * stats */ static int command_stats (client_t *client, const char *filename) { admin_response_type response = RAW; const char *show_mount = NULL; xmlDocPtr doc; if (filename) if (util_check_valid_extension (filename) == XSLT_CONTENT) response = XSLT; show_mount = httpp_get_query_param (client->parser, "mount"); doc = stats_get_xml (STATS_ALL, show_mount); return admin_send_response (doc, client, response, filename); }
int admin_mount_request (client_t *client, const char *uri) { source_t *source; const char *mount = httpp_get_query_param (client->parser, "mount"); struct admin_command *cmd = find_admin_command (admin_mount, uri); if (cmd == NULL) return command_stats (client, uri); if (cmd == NULL || cmd->handle.source == NULL) { INFO0("mount request not recognised"); return client_send_400 (client, "unknown request"); } avl_tree_rlock(global.source_tree); source = source_find_mount_raw(mount); if (source == NULL) { avl_tree_unlock(global.source_tree); if (strncmp (cmd->request, "stats", 5) == 0) return command_stats (client, uri); if (strncmp (cmd->request, "listclients", 11) == 0) return fserve_list_clients (client, mount, cmd->response, 1); if (strncmp (cmd->request, "killclient", 10) == 0) return fserve_kill_client (client, mount, cmd->response); WARN1("Admin command on non-existent source %s", mount); return client_send_400 (client, "Source does not exist"); } else { int ret = 0; thread_mutex_lock (&source->lock); if (source_available (source) == 0) { thread_mutex_unlock (&source->lock); avl_tree_unlock (global.source_tree); INFO1("Received admin command on unavailable mount \"%s\"", mount); return client_send_400 (client, "Source is not available"); } ret = cmd->handle.source (client, source, cmd->response); avl_tree_unlock(global.source_tree); return ret; } }
int stats_transform_xslt (client_t *client, const char *uri) { xmlDocPtr doc; char *xslpath = util_get_path_from_normalised_uri (uri, 0); const char *mount = httpp_get_query_param (client->parser, "mount"); int ret; if (mount == NULL && client->server_conn->shoutcast_mount && strcmp (uri, "/7.xsl") == 0) mount = client->server_conn->shoutcast_mount; doc = stats_get_xml (STATS_PUBLIC, mount); ret = xslt_transform (doc, xslpath, client); xmlFreeDoc(doc); free (xslpath); return ret; }
void httpp_set_query_param(http_parser_t *parser, const char *name, const char *value) { http_var_t *var; if (name == NULL || value == NULL) return; var = (http_var_t *)amalloc(sizeof(http_var_t)); var->name = strdup(name); var->value = url_escape(value); if (httpp_get_query_param(parser, name) == NULL) { avl_insert(parser->queryvars, (void *)var); } else { avl_delete(parser->queryvars, (void *)var, _free_vars); avl_insert(parser->queryvars, (void *)var); } }
static int get_image (client_t *client, struct _format_plugin_tag *format) { const char *serialp = httpp_get_query_param (client->parser, "serial"); ogg_state_t *ogg_info = format->_state; ogg_codec_t *codec = ogg_info->codecs; long serial; if (serialp) serial = atoll (serialp); while (codec) { if (serialp == NULL || serial == codec->os.serialno) { int ret = 0; if (codec->get_image) ret = codec->get_image (client, codec); return ret; } codec = codec->next; } return 0; }
static int command_reset_stats (client_t *client, source_t *source, int response) { const char *msg = "Failed to reset values"; const char *name = httpp_get_query_param (client->parser, "setting"); int all = 0, ok = 0; xmlDocPtr doc; xmlNodePtr node; if (name == NULL) all = 1; if (all || strstr (name, "peak")) { source->peak_listeners = source->listeners; source->prev_listeners = source->peak_listeners+1; ok = 1; } if (all || strstr (name, "read")) if (source->format) { source->format->read_bytes = 0; ok = 1; } if (all || strstr (name, "sent")) if (source->format) { source->format->sent_bytes = 0; ok = 1; } if (ok) msg = "have reset settings"; doc = xmlNewDoc(XMLSTR("1.0")); node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL); xmlDocSetRootElement(doc, node); xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR(msg)); xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); return admin_send_response (doc, client, response, "response.xsl"); }
void admin_handle_request(client_t *client, const char *uri) { const char *mount, *command_string; int command; DEBUG1("Admin request (%s)", uri); if (!((strcmp(uri, "/admin.cgi") == 0) || (strncmp("/admin/", uri, 7) == 0))) { ERROR0("Internal error: admin request isn't"); client_send_401(client); return; } if (strcmp(uri, "/admin.cgi") == 0) { command_string = uri + 1; } else { command_string = uri + 7; } DEBUG1("Got command (%s)", command_string); command = admin_get_command(command_string); if(command < 0) { ERROR1("Error parsing command string or unrecognised command: %s", command_string); client_send_400(client, "Unrecognised command"); return; } if (command == COMMAND_SHOUTCAST_METADATA_UPDATE) { ice_config_t *config; const char *sc_mount; const char *pass = httpp_get_query_param (client->parser, "pass"); listener_t *listener; if (pass == NULL) { client_send_400 (client, "missing pass parameter"); return; } config = config_get_config (); sc_mount = config->shoutcast_mount; listener = config_get_listen_sock (config, client->con); if (listener && listener->shoutcast_mount) sc_mount = listener->shoutcast_mount; httpp_set_query_param (client->parser, "mount", sc_mount); httpp_setvar (client->parser, HTTPP_VAR_PROTOCOL, "ICY"); httpp_setvar (client->parser, HTTPP_VAR_ICYPASSWORD, pass); config_release_config (); } mount = httpp_get_query_param(client->parser, "mount"); if(mount != NULL) { source_t *source; /* this request does not require auth but can apply to files on webroot */ if (command == COMMAND_BUILDM3U) { command_buildm3u (client, mount); return; } /* This is a mount request, handle it as such */ if (!connection_check_admin_pass(client->parser)) { if (!connection_check_source_pass(client->parser, mount)) { INFO1("Bad or missing password on mount modification admin " "request (command: %s)", command_string); client_send_401(client); return; } } avl_tree_rlock(global.source_tree); source = source_find_mount_raw(mount); if (source == NULL) { WARN2("Admin command %s on non-existent source %s", command_string, mount); avl_tree_unlock(global.source_tree); client_send_400(client, "Source does not exist"); } else { if (source->running == 0 && source->on_demand == 0) { avl_tree_unlock (global.source_tree); INFO2("Received admin command %s on unavailable mount \"%s\"", command_string, mount); client_send_400 (client, "Source is not available"); return; } if (command == COMMAND_SHOUTCAST_METADATA_UPDATE && source->shoutcast_compat == 0) { avl_tree_unlock (global.source_tree); ERROR0 ("illegal change of metadata on non-shoutcast " "compatible stream"); client_send_400 (client, "illegal metadata call"); return; } INFO2("Received admin command %s on mount \"%s\"", command_string, mount); admin_handle_mount_request(client, source, command); avl_tree_unlock(global.source_tree); } } else { if (command == COMMAND_PLAINTEXT_LISTSTREAM) { /* this request is used by a slave relay to retrieve mounts from the master, so handle this request validating against the relay password */ if(!connection_check_relay_pass(client->parser)) { INFO1("Bad or missing password on admin command " "request (command: %s)", command_string); client_send_401(client); return; } } else { if(!connection_check_admin_pass(client->parser)) { INFO1("Bad or missing password on admin command " "request (command: %s)", command_string); client_send_401(client); return; } } admin_handle_general_request(client, command); } }
int format_general_headers (format_plugin_t *plugin, client_t *client) { unsigned remaining = 4096 - client->refbuf->len; char *ptr = client->refbuf->data + client->refbuf->len; int bytes = 0; int bitrate_filtered = 0; avl_node *node; ice_config_t *config; uint64_t length = 0; /* hack for flash player, it wants a length. */ if (httpp_getvar (client->parser, "x-flash-version")) length = 221183499; else { // flash may not send above header, so check for swf in referer const char *referer = httpp_getvar (client->parser, "referer"); if (referer) { int len = strcspn (referer, "?"); if (len >= 4 && strncmp (referer+len-4, ".swf", 4) == 0) length = 221183499; } } if (client->respcode == 0) { const char *useragent = httpp_getvar (client->parser, "user-agent"); const char *protocol = "HTTP/1.0"; const char *contenttypehdr = "Content-Type"; const char *contenttype = plugin->contenttype; const char *range = httpp_getvar (client->parser, "range"); const char *fs = httpp_getvar (client->parser, "__FILESIZE"); if (useragent) { const char *resp = httpp_get_query_param (client->parser, "_hdr"); int fmtcode = 0; #define FMT_RETURN_ICY 1 #define FMT_LOWERCASE_TYPE 2 #define FMT_FORCE_AAC 4 do { if (resp) { fmtcode = atoi (resp); break; } if (fs) break; // ignore following settings for files. if (strstr (useragent, "shoutcastsource")) /* hack for mpc */ fmtcode = FMT_RETURN_ICY; if (strstr (useragent, "Windows-Media-Player") || strstr (useragent, "WMFSDK")) /* hack for wmp*/ fmtcode = FMT_RETURN_ICY; if (strstr (useragent, "RealMedia")) /* hack for rp (mainly mobile) */ fmtcode = FMT_RETURN_ICY; if (strstr (useragent, "Shoutcast Server")) /* hack for sc_serv */ fmtcode = FMT_LOWERCASE_TYPE; // if (strstr (useragent, "Sonos")) // contenttypehdr = "content-type"; if (plugin->type == FORMAT_TYPE_AAC && strstr (useragent, "AppleWebKit")) fmtcode |= FMT_FORCE_AAC; if (strstr (useragent, "BlackBerry")) { fmtcode |= FMT_RETURN_ICY; if (plugin->type == FORMAT_TYPE_AAC) fmtcode |= FMT_FORCE_AAC; } } while (0); if (fmtcode & FMT_RETURN_ICY) protocol = "ICY"; if (fmtcode & FMT_LOWERCASE_TYPE) contenttypehdr = "content-type"; if (fmtcode & FMT_FORCE_AAC) // ie for avoiding audio/aacp contenttype = "audio/aac"; } if (fs) { uint64_t pos1 = 0, pos2 = length ? length : 50000000, max = pos2; char buf[30]; sscanf (fs, "%" SCNuMAX, &max); if (range) { if (strncmp (range, "bytes=-", 7) == 0) { sscanf (range, "bytes=-%" SCNuMAX, &pos2); pos1 = max-pos2; pos2 = max-1; } else { if (sscanf (range, "bytes=%" SCNuMAX "-%" SCNuMAX, &pos1, &pos2) < 2) pos2 = max-1; } if (pos2 >= max || pos1 >= pos2) { DEBUG2 ("client range invalid (%" PRIu64 ", %" PRIu64 ")", pos1, pos2); return -1; } length = pos2 - pos1 + 1; snprintf (buf, 30, "%" PRIu64, length); httpp_setvar (client->parser, "__LENGTH", buf); client->respcode = 206; client->intro_offset = pos1; bytes = snprintf (ptr, remaining, "%s 206 Partial Content\r\n" "%s: %s\r\n" "Content-Length: %" PRIu64 "\r\n" "Content-Range: bytes %" PRIu64 "-%" PRIu64 "/%" PRIu64 "\r\n", protocol, contenttypehdr, contenttype ? contenttype : "application/octet-stream", length, pos1, pos2, max); } else { client->respcode = 200; bytes = snprintf (ptr, remaining, "%s 200 OK\r\n" "Content-Length: %" PRIu64 "\r\n" "%s: %s\r\n", protocol, max, contenttypehdr, contenttype); } } else { client->respcode = 200; bytes = snprintf (ptr, remaining, "%s 200 OK\r\n" "%s: %s\r\n", protocol, contenttypehdr, contenttype); } remaining -= bytes; ptr += bytes; } if (plugin && plugin->parser) { /* iterate through source http headers and send to client */ avl_tree_rlock (plugin->parser->vars); node = avl_get_first (plugin->parser->vars); while (node) { int next = 1; http_var_t *var = (http_var_t *)node->key; bytes = 0; if (!strcasecmp (var->name, "ice-audio-info")) { /* convert ice-audio-info to icy-br */ char *brfield = NULL; unsigned int bitrate; if (bitrate_filtered == 0) brfield = strstr (var->value, "bitrate="); if (brfield && sscanf (brfield, "bitrate=%u", &bitrate)) { bytes = snprintf (ptr, remaining, "icy-br:%u\r\n", bitrate); next = 0; bitrate_filtered = 1; } else /* show ice-audio_info header as well because of relays */ bytes = snprintf (ptr, remaining, "%s: %s\r\n", var->name, var->value); } else { if (strcasecmp (var->name, "ice-password") && strcasecmp (var->name, "icy-metaint")) { if (!strncasecmp ("ice-", var->name, 4)) { if (!strcasecmp ("ice-public", var->name)) bytes = snprintf (ptr, remaining, "icy-pub:%s\r\n", var->value); else if (!strcasecmp ("ice-bitrate", var->name)) bytes = snprintf (ptr, remaining, "icy-br:%s\r\n", var->value); else bytes = snprintf (ptr, remaining, "icy%s:%s\r\n", var->name + 3, var->value); } else if (!strncasecmp ("icy-", var->name, 4)) { bytes = snprintf (ptr, remaining, "icy%s:%s\r\n", var->name + 3, var->value); } } } remaining -= bytes; ptr += bytes; if (next) node = avl_get_next (node); } avl_tree_unlock (plugin->parser->vars); } config = config_get_config(); bytes = snprintf (ptr, remaining, "Server: %s\r\n", config->server_id); config_release_config(); remaining -= bytes; ptr += bytes; /* prevent proxy servers from caching */ bytes = snprintf (ptr, remaining, "Cache-Control: no-cache\r\nPragma: no-cache\r\n" "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n"); remaining -= bytes; ptr += bytes; bytes = snprintf (ptr, remaining, "\r\n"); remaining -= bytes; ptr += bytes; client->refbuf->len = 4096 - remaining; client->refbuf->flags |= WRITE_BLOCK_GENERIC; return 0; }
int format_general_headers (format_plugin_t *plugin, client_t *client) { unsigned remaining = 4096 - client->refbuf->len; char *ptr = client->refbuf->data + client->refbuf->len; int bytes; int bitrate_filtered = 0; avl_node *node; ice_config_t *config; if (client->respcode == 0) { const char *useragent = httpp_getvar (client->parser, "user-agent"); const char *protocol = "HTTP/1.0"; const char *contenttypehdr = "Content-Type"; const char *contenttype = plugin->contenttype; if (useragent) { const char *resp = httpp_get_query_param (client->parser, "_hdr"); int fmtcode = 0; #define FMT_RETURN_ICY 1 #define FMT_LOWERCASE_TYPE 2 #define FMT_FORCE_AAC 4 if (resp) fmtcode = atoi (resp); else { if (strstr (useragent, "shoutcastsource")) /* hack for mpc */ fmtcode = FMT_RETURN_ICY; if (strstr (useragent, "Windows-Media-Player")) /* hack for wmp*/ fmtcode = FMT_RETURN_ICY; if (strstr (useragent, "Shoutcast Server")) /* hack for sc_serv */ fmtcode = FMT_LOWERCASE_TYPE; // if (strstr (useragent, "Sonos")) // contenttypehdr = "content-type"; if (plugin->type == FORMAT_TYPE_AAC) { if (strstr (useragent, "BlackBerry")) fmtcode = FMT_FORCE_AAC; } } if (fmtcode & FMT_RETURN_ICY) protocol = "ICY"; if (fmtcode & FMT_LOWERCASE_TYPE) contenttypehdr = "content-type"; if (fmtcode & FMT_FORCE_AAC) // ie for avoiding audio/aacp contenttype = "audio/aac"; } bytes = snprintf (ptr, remaining, "%s 200 OK\r\n" "%s: %s\r\n", protocol, contenttypehdr, contenttype); remaining -= bytes; ptr += bytes; client->respcode = 200; } if (plugin->parser) { /* iterate through source http headers and send to client */ avl_tree_rlock (plugin->parser->vars); node = avl_get_first (plugin->parser->vars); while (node) { int next = 1; http_var_t *var = (http_var_t *)node->key; bytes = 0; if (!strcasecmp (var->name, "ice-audio-info")) { /* convert ice-audio-info to icy-br */ char *brfield = NULL; unsigned int bitrate; if (bitrate_filtered == 0) brfield = strstr (var->value, "bitrate="); if (brfield && sscanf (brfield, "bitrate=%u", &bitrate)) { bytes = snprintf (ptr, remaining, "icy-br:%u\r\n", bitrate); next = 0; bitrate_filtered = 1; } else /* show ice-audio_info header as well because of relays */ bytes = snprintf (ptr, remaining, "%s: %s\r\n", var->name, var->value); } else { if (strcasecmp (var->name, "ice-password") && strcasecmp (var->name, "icy-metaint")) { if (!strncasecmp ("ice-", var->name, 4)) { if (!strcasecmp ("ice-public", var->name)) bytes = snprintf (ptr, remaining, "icy-pub:%s\r\n", var->value); else if (!strcasecmp ("ice-bitrate", var->name)) bytes = snprintf (ptr, remaining, "icy-br:%s\r\n", var->value); else bytes = snprintf (ptr, remaining, "icy%s:%s\r\n", var->name + 3, var->value); } else if (!strncasecmp ("icy-", var->name, 4)) { bytes = snprintf (ptr, remaining, "icy%s:%s\r\n", var->name + 3, var->value); } } } remaining -= bytes; ptr += bytes; if (next) node = avl_get_next (node); } avl_tree_unlock (plugin->parser->vars); } config = config_get_config(); bytes = snprintf (ptr, remaining, "Server: %s\r\n", config->server_id); config_release_config(); remaining -= bytes; ptr += bytes; /* prevent proxy servers from caching */ bytes = snprintf (ptr, remaining, "Cache-Control: no-cache\r\n"); remaining -= bytes; ptr += bytes; bytes = snprintf (ptr, remaining, "\r\n"); remaining -= bytes; ptr += bytes; client->refbuf->len = 4096 - remaining; client->refbuf->flags |= WRITE_BLOCK_GENERIC; return 0; }
int admin_handle_request (client_t *client, const char *uri) { const char *mount = httpp_get_query_param(client->parser, "mount"); if (strcmp (uri, "/admin.cgi") == 0) { const char *pass = httpp_get_query_param (client->parser, "pass"); if (pass == NULL) return client_send_400 (client, "missing pass parameter"); uri++; if (mount == NULL) { if (client->server_conn && client->server_conn->shoutcast_mount) httpp_set_query_param (client->parser, "mount", client->server_conn->shoutcast_mount); mount = httpp_get_query_param (client->parser, "mount"); } httpp_setvar (client->parser, HTTPP_VAR_PROTOCOL, "ICY"); httpp_setvar (client->parser, HTTPP_VAR_ICYPASSWORD, pass); client->username = strdup ("source"); client->password = strdup (pass); } else uri += 7; if (connection_check_admin_pass (client->parser)) client->flags |= CLIENT_AUTHENTICATED; else { /* special case for slaves requesting a streamlist for authenticated relaying */ if (strcmp (uri, "streams") == 0 || strcmp (uri, "streamlist.txt") == 0) { if (connection_check_relay_pass (client->parser)) client->flags |= CLIENT_AUTHENTICATED; } } if (mount) { /* no auth/stream required for this */ if (strcmp (uri, "buildm3u") == 0) return command_buildm3u (client, mount); if (strcmp (uri, "showimage") == 0) return command_show_image (client, mount); /* This is a mount request, but admin user is allowed */ if ((client->flags & CLIENT_AUTHENTICATED) == 0) { switch (auth_check_source (client, mount)) { case 0: break; default: INFO1("Bad or missing password on mount modification " "admin request (%s)", uri); return client_send_401 (client, NULL); /* fall through */ case 1: return 0; } } if (strcmp (uri, "streams") == 0) return auth_add_listener ("/admin/streams", client); return admin_mount_request (client, uri); } return admin_handle_general_request (client, uri); }