int client_send_404 (client_t *client, const char *message) { int ret = -1; if (client->worker == NULL) /* client is not on any worker now */ { client_destroy (client); return 0; } client_set_queue (client, NULL); if (client->respcode) { worker_t *worker = client->worker; if (client->respcode >= 300) client->flags = client->flags & ~CLIENT_AUTHENTICATED; client->flags |= CLIENT_ACTIVE; worker_wakeup (worker); } else { if (message == NULL) message = "Not Available"; client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE); snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 404 Not Available\r\n" "Content-Type: text/html\r\n\r\n" "<b>%s</b>\r\n", message); client->respcode = 404; client->refbuf->len = strlen (client->refbuf->data); ret = fserve_setup_client (client); } return ret; }
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; avl_tree_rlock (global.source_tree); doc = admin_build_sourcelist(NULL); avl_tree_unlock (global.source_tree); return admin_send_response (doc, client, response, "listmounts.xsl"); } }
int client_send_404 (client_t *client, const char *message) { int ret = -1; if (client->worker == NULL) /* client is not on any worker now */ { client_destroy (client); return 0; } client_set_queue (client, NULL); if (client->respcode) { worker_t *worker = client->worker; if (client->respcode >= 300) client->flags = client->flags & ~CLIENT_AUTHENTICATED; client->flags |= CLIENT_ACTIVE; worker_wakeup (worker); } else { if (client->parser->req_type == httpp_req_head || message == NULL) message = "Not Available"; ret = strlen (message); client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE); snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 404 Not Available\r\n" "%s\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n" "%s", client_keepalive_header (client), ret, message ? message: ""); client->respcode = 404; client->refbuf->len = strlen (client->refbuf->data); ret = fserve_setup_client (client); } return ret; }
int client_send_501(client_t *client) { client_set_queue (client, NULL); client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE); snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 501 Not Implemented\r\n\r\n"); client->respcode = 501; client->refbuf->len = strlen (client->refbuf->data); return fserve_setup_client (client); }
int client_send_416(client_t *client) { client_set_queue (client, NULL); client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE); snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 416 Request Range Not Satisfiable\r\n\r\n"); client->respcode = 416; client->refbuf->len = strlen (client->refbuf->data); return fserve_setup_client (client); }
static int html_success (client_t *client, const char *message) { client->respcode = 200; snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" "<html><head><title>Admin request successful</title></head>" "<body><p>%s</p></body></html>", message); client->refbuf->len = strlen (client->refbuf->data); return fserve_setup_client (client); }
int client_send_400(client_t *client, const char *message) { client_set_queue (client, NULL); client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE); snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 400 Bad Request\r\n" "Content-Type: text/html\r\n\r\n" "<b>%s</b>\r\n", message?message:""); client->respcode = 400; client->refbuf->len = strlen (client->refbuf->data); return fserve_setup_client (client); }
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); } }
int client_send_403(client_t *client, const char *reason) { if (reason == NULL) reason = "Forbidden"; client_set_queue (client, NULL); client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE); snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 403 %s\r\n" "Content-Type: text/html\r\n\r\n", reason); client->respcode = 403; client->refbuf->len = strlen (client->refbuf->data); return fserve_setup_client (client); }
int client_send_options(client_t *client) { client_set_queue (client, NULL); client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE); snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.1 200 OK\r\n" "Access-Control-Allow-Origin: *\r\n" "Access-Control-Allow-Headers: Origin, Accept, X-Requested-With, Content-Type\r\n" "Access-Control-Allow-Methods: GET, OPTIONS, STATS\r\n\r\n"); client->respcode = 200; client->refbuf->len = strlen (client->refbuf->data); return fserve_setup_client (client); }
int client_send_302(client_t *client, const char *location) { client_set_queue (client, NULL); client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE); snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 302 Temporarily Moved\r\n" "Content-Type: text/html\r\n" "Location: %s\r\n\r\n" "Moved <a href=\"%s\">here</a>\r\n", location, location); client->respcode = 302; client->refbuf->len = strlen (client->refbuf->data); return fserve_setup_client (client); }
int admin_send_response (xmlDocPtr doc, client_t *client, admin_response_type response, const char *xslt_template) { int ret = -1; if (response == RAW) { xmlChar *buff = NULL; int len = 0; unsigned int buf_len; const char *http = "HTTP/1.0 200 OK\r\n" "Content-Type: text/xml\r\n" "Content-Length: "; xmlDocDumpFormatMemoryEnc (doc, &buff, &len, NULL, 1); buf_len = strlen (http) + len + 20; client_set_queue (client, NULL); client->refbuf = refbuf_new (buf_len); len = snprintf (client->refbuf->data, buf_len, "%s%d\r\n\r\n%s", http, len, buff); client->refbuf->len = len; xmlFree(buff); xmlFreeDoc (doc); client->respcode = 200; return fserve_setup_client (client); } if (response == XSLT) { char *fullpath_xslt_template; int fullpath_xslt_template_len; ice_config_t *config = config_get_config(); fullpath_xslt_template_len = strlen (config->adminroot_dir) + strlen(xslt_template) + 2; fullpath_xslt_template = malloc(fullpath_xslt_template_len); snprintf(fullpath_xslt_template, fullpath_xslt_template_len, "%s%s%s", config->adminroot_dir, PATH_SEPARATOR, xslt_template); config_release_config(); DEBUG1("Sending XSLT (%s)", fullpath_xslt_template); ret = xslt_transform (doc, fullpath_xslt_template, client); free(fullpath_xslt_template); xmlFreeDoc(doc); } return ret; }
int client_send_401 (client_t *client, const char *realm) { ice_config_t *config = config_get_config (); if (realm == NULL) realm = config->server_id; client_set_queue (client, NULL); client->refbuf = refbuf_new (500); snprintf (client->refbuf->data, 500, "HTTP/1.0 401 Authentication Required\r\n" "WWW-Authenticate: Basic realm=\"%s\"\r\n" "\r\n" "You need to authenticate\r\n", realm); config_release_config(); client->respcode = 401; client->refbuf->len = strlen (client->refbuf->data); return fserve_setup_client (client); }
int client_send_302(client_t *client, const char *location) { int len; char body [4096]; client_set_queue (client, NULL); client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE); len = snprintf (body, sizeof body, "Moved <a href=\"%s\">here</a>\r\n", location); len = snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 302 Temporarily Moved\r\n" "Content-Type: text/html\r\n" "Content-Length: %d\r\n" "Location: %s\r\n\r\n%s", len, location, body); client->respcode = 302; client->flags &= ~CLIENT_KEEPALIVE; client->refbuf->len = len; return fserve_setup_client (client); }
static int command_buildm3u (client_t *client, const char *mount) { const char *username = NULL; const char *password = NULL; ice_config_t *config; const char *host = httpp_getvar (client->parser, "host"); if (COMMAND_REQUIRE(client, "username", username) < 0 || COMMAND_REQUIRE(client, "password", password) < 0) return client_send_400 (client, "missing arg, username/password"); client->respcode = 200; config = config_get_config(); if (host) { char port[10] = ""; if (strchr (host, ':') == NULL) snprintf (port, sizeof (port), ":%u", config->port); snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 200 OK\r\n" "Content-Type: audio/x-mpegurl\r\n" "Content-Disposition = attachment; filename=listen.m3u\r\n\r\n" "http://%s:%s@%s%s%s\r\n", username, password, host, port, mount); } else { snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 200 OK\r\n" "Content-Type: audio/x-mpegurl\r\n" "Content-Disposition = attachment; filename=listen.m3u\r\n\r\n" "http://%s:%s@%s:%d%s\r\n", username, password, config->hostname, config->port, mount); } config_release_config(); client->refbuf->len = strlen (client->refbuf->data); return fserve_setup_client (client); }
static int command_show_image (client_t *client, const char *mount) { source_t *source; avl_tree_rlock (global.source_tree); source = source_find_mount_raw (mount); if (source && source->format && source->format->get_image) { thread_mutex_lock (&source->lock); avl_tree_unlock (global.source_tree); if (source->format->get_image (client, source->format) == 0) { thread_mutex_unlock (&source->lock); return fserve_setup_client (client); } thread_mutex_unlock (&source->lock); } else avl_tree_unlock (global.source_tree); return client_send_404 (client, "No image available"); }
int xslt_transform (xmlDocPtr doc, const char *xslfilename, client_t *client) { xmlDocPtr res; xsltStylesheetPtr cur; int len; refbuf_t *content = NULL; char **params = NULL; xmlSetGenericErrorFunc ("", log_parse_failure); xsltSetGenericErrorFunc ("", log_parse_failure); thread_mutex_lock(&xsltlock); cur = xslt_get_stylesheet(xslfilename); if (cur == NULL) { thread_mutex_unlock(&xsltlock); ERROR1 ("problem reading stylesheet \"%s\"", xslfilename); return client_send_404 (client, "Could not parse XSLT file"); } if (client->parser->queryvars) { // annoying but we need to surround the args with ' when passing them in int i, arg_count = client->parser->queryvars->length * 2; avl_node *node = avl_get_first (client->parser->queryvars); params = calloc (arg_count+1, sizeof (char *)); for (i = 0; node && i < arg_count; node = avl_get_next (node)) { http_var_t *param = (http_var_t *)node->key; char *tmp = util_url_escape (param->value); params[i++] = param->name; // use alloca for now, should really url esc into a supplied buffer params[i] = (char*)alloca (strlen (tmp) + 3); sprintf (params[i++], "\'%s\'", tmp); free (tmp); } params[i] = NULL; } res = xsltApplyStylesheet (cur, doc, (const char **)params); free (params); if (res == NULL || xslt_SaveResultToBuf (&content, &len, res, cur) < 0) { thread_mutex_unlock (&xsltlock); xmlFreeDoc (res); WARN1 ("problem applying stylesheet \"%s\"", xslfilename); return client_send_404 (client, "XSLT problem"); } else { /* the 100 is to allow for the hardcoded headers */ refbuf_t *refbuf = refbuf_new (100); const char *mediatype = NULL; /* lets find out the content type to use */ if (cur->mediaType) mediatype = (char *)cur->mediaType; else { /* check method for the default, a missing method assumes xml */ if (cur->method && xmlStrcmp (cur->method, XMLSTR("html")) == 0) mediatype = "text/html"; else if (cur->method && xmlStrcmp (cur->method, XMLSTR("text")) == 0) mediatype = "text/plain"; else mediatype = "text/xml"; } snprintf (refbuf->data, 100, "HTTP/1.0 200 OK\r\nContent-Type: %s\r\nContent-Length: %d\r\n\r\n", mediatype, len); thread_mutex_unlock (&xsltlock); client->respcode = 200; client_set_queue (client, NULL); client->refbuf = refbuf; refbuf->len = strlen (refbuf->data); refbuf->next = content; } xmlFreeDoc(res); return fserve_setup_client (client); }
// requires xslt_lock before being called, released on return static int xslt_send_sheet (client_t *client, xmlDocPtr doc, int idx) { xmlDocPtr res; xsltStylesheetPtr cur = cache [idx].stylesheet; char **params = NULL; refbuf_t *content = NULL; int len; if (client->parser->queryvars) { // annoying but we need to surround the args with ' when passing them in int j, arg_count = client->parser->queryvars->length * 2; avl_node *node = avl_get_first (client->parser->queryvars); params = calloc (arg_count+1, sizeof (char *)); for (j = 0; node && j < arg_count; node = avl_get_next (node)) { http_var_t *param = (http_var_t *)node->key; char *tmp = util_url_escape (param->value); params[j++] = param->name; // use alloca for now, should really url esc into a supplied buffer params[j] = (char*)alloca (strlen (tmp) + 3); sprintf (params[j++], "\'%s\'", tmp); free (tmp); } params[j] = NULL; } res = xsltApplyStylesheet (cur, doc, (const char **)params); free (params); client->shared_data = NULL; if (res == NULL || xslt_SaveResultToBuf (&content, &len, res, cur) < 0) { thread_rwlock_unlock (&xslt_lock); xmlFreeDoc (res); xmlFreeDoc (doc); WARN1 ("problem applying stylesheet \"%s\"", cache [idx].filename); return client_send_404 (client, "XSLT problem"); } else { /* the 100 is to allow for the hardcoded headers */ refbuf_t *refbuf = refbuf_new (500); const char *mediatype = NULL; /* lets find out the content type to use */ if (cur->mediaType) mediatype = (char *)cur->mediaType; else { /* check method for the default, a missing method assumes xml */ if (cur->method && xmlStrcmp (cur->method, XMLSTR("html")) == 0) mediatype = "text/html"; else if (cur->method && xmlStrcmp (cur->method, XMLSTR("text")) == 0) mediatype = "text/plain"; else mediatype = "text/xml"; } snprintf (refbuf->data, 500, "HTTP/1.0 200 OK\r\nContent-Type: %s\r\nContent-Length: %d\r\n%s" "Expires: Thu, 19 Nov 1981 08:52:00 GMT\r\n" "Cache-Control: no-store, no-cache, must-revalidate\r\n" "Pragma: no-cache\r\n%s\r\n" "Access-Control-Allow-Origin: *\r\n" "Access-Control-Allow-Headers: Origin, Accept, X-Requested-With, Content-Type\r\n" "Access-Control-Allow-Methods: GET, OPTIONS, HEAD\r\n" "\r\n", mediatype, len, cache[idx].disposition ? cache[idx].disposition : "", client_keepalive_header (client)); thread_rwlock_unlock (&xslt_lock); client->respcode = 200; client_set_queue (client, NULL); client->refbuf = refbuf; refbuf->len = strlen (refbuf->data); refbuf->next = content; } xmlFreeDoc(res); xmlFreeDoc(doc); return fserve_setup_client (client); }