/* 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_metadata (client_t *client, source_t *source, int response) { const char *song, *title, *artist, *artwork, *charset, *url; format_plugin_t *plugin; xmlDocPtr doc; xmlNodePtr node; int same_ip = 1; doc = xmlNewDoc(XMLSTR("1.0")); node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL); xmlDocSetRootElement(doc, node); DEBUG0("Got metadata update request"); COMMAND_OPTIONAL(client, "song", song); COMMAND_OPTIONAL(client, "title", title); COMMAND_OPTIONAL(client, "artist", artist); COMMAND_OPTIONAL(client, "url", url); COMMAND_OPTIONAL(client, "artwork", artwork); COMMAND_OPTIONAL(client, "charset", charset); plugin = source->format; if (source_running (source)) if (strcmp (client->connection.ip, source->client->connection.ip) != 0) if (response == RAW && connection_check_admin_pass (client->parser) == 0) same_ip = 0; /* Update stream metadata if needed */ if (same_ip) { static const struct { const char *param; const char *stat_name; const char *hdr[3]; } fwd[] = { {"xstreamname", "server_name", {"ice-name", "icy-name", "x-audiocast-name"}}, {"xstreamdesc", "server_description", {"ice-description", "icy-description", "x-audiocast-description"}}, {"xstreamurl", "server_url", {"ice-url", "icy-url", "x-audiocast-url"}}, {"xstreamgenre", "genre", {"ice-genre", "icy-genre", "x-audiocast-genre"}} }; unsigned i; for (i = 0; i < sizeof(fwd) / sizeof(*fwd); i++) { const char *value; unsigned j; COMMAND_OPTIONAL(client, fwd[i].param, value); if (value && *value) { value = auto_recode(value); if (source->format->charset) stats_set_conv (source->stats, fwd[i].stat_name, value, source->format->charset); else stats_set (source->stats, fwd[i].stat_name, value); } else if (value) { stats_set (source->stats, fwd[i].stat_name, NULL); } for (j = 0; j < 3; j++) { if (j == 0 && value && *value) { httpp_setvar(source->format->parser, fwd[i].hdr[j], value); } else if (value && !*value) { httpp_deletevar(source->format->parser, fwd[i].hdr[j]); } } } } do { if (same_ip == 0 || plugin == NULL) break; /* Charset detection (if none specified) */ if (!charset) { const char *r; int len; charset = "UTF8"; #define CCONV(s) \ if (s && (r = auto_recode(s))) { \ len = strlen(r); \ s = alloca(len + 1); \ memcpy((char*)s, r, len + 1); \ } CCONV(title); CCONV(song); CCONV(artist); } /* Now send prepared metadata */ if (artwork) stats_event (source->mount, "artwork", artwork); if (plugin->set_tag) { if (url) { plugin->set_tag (plugin, "url", url, charset); INFO2 ("Metadata url on %s set to \"%s\"", source->mount, url); } if (song) { plugin->set_tag (plugin, "artist", NULL, NULL); plugin->set_tag (plugin, "title", song, charset); INFO2("Metadata song on %s set to \"%s\"", source->mount, song); } if (artist) { plugin->set_tag (plugin, "artist", artist, charset); INFO2 ("Metadata artist on %s changed to \"%s\"", source->mount, artist); } if (title) { plugin->set_tag (plugin, "title", title, charset); INFO2 ("Metadata title on %s changed to \"%s\"", source->mount, title); } /* updates are now done, let them be pushed into the stream */ plugin->set_tag (plugin, NULL, NULL, NULL); } else { break; } thread_mutex_unlock (&source->lock); xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("Metadata update successful")); xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); return admin_send_response(doc, client, response, "response.xsl"); } while (0); thread_mutex_unlock (&source->lock); xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("Mountpoint will not accept this URL update")); xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); return admin_send_response(doc, client, response, "response.xsl"); }