static char *fserve_content_type(char *path) { char *ext = util_get_extension(path); mime_type exttype = {ext, NULL}; void *result; if (!avl_get_by_key (mimetypes, &exttype, &result)) { mime_type *mime = result; return mime->type; } else { /* Fallbacks for a few basic ones */ if(!strcmp(ext, "ogg")) return "application/ogg"; else if(!strcmp(ext, "mp3")) return "audio/mpeg"; else if(!strcmp(ext, "html")) return "text/html"; else if(!strcmp(ext, "css")) return "text/css"; else if(!strcmp(ext, "txt")) return "text/plain"; else return "application/octet-stream"; } }
int cartridge_save_image(int type, const char *filename) { char *ext = util_get_extension((char *)filename); if (ext != NULL && !strcmp(ext, "crt")) { return cartridge_crt_save(type, filename); } return cartridge_bin_save(type, filename); }
static int disk_image_check_for_d1m(disk_image_t *image) { unsigned int blk = 0; char *ext; size_t len; BYTE block[256]; fsimage_t *fsimage; fsimage = image->media.fsimage; /* reject files with unknown size */ if (!(IS_D1M_LEN(util_file_length(fsimage->fd)))) { return 0; } /* .d81 images share the same sizes with .d1m, so we reject based on the file extension what is likely a .d81 image */ ext = util_get_extension(fsimage->name); if ((ext[0]) && (ext[1] == '8') && (ext[2] == '1')) { return 0; } image->type = DISK_IMAGE_TYPE_D1M; image->tracks = NUM_TRACKS_1000; image->max_half_tracks = MAX_TRACKS_1000 * 2; rewind(fsimage->fd); while ((len = fread(block, 1, 256, fsimage->fd)) == 256) { if (++blk > NUM_BLOCKS_1000 + 13) { log_error(disk_image_probe_log, "Disk image too large."); break; } } if (disk_image_check_min_block(blk, NUM_BLOCKS_1000) < 0) { return 0; } switch (blk) { case NUM_BLOCKS_1000: case NUM_BLOCKS_1000 + 12: /* with errors */ image->tracks = NUM_TRACKS_1000; image->max_half_tracks = MAX_TRACKS_1000 * 2; break; default: return 0; } disk_image_check_log(image, "D1M"); return 1; }
/* string returned needs to be free'd */ char *fserve_content_type (const char *path) { char *ext = util_get_extension(path); mime_type exttype = { NULL, NULL }; void *result; char *type; if (ext == NULL) return strdup ("text/html"); exttype.ext = strdup (ext); thread_spin_lock (&pending_lock); if (mimetypes && !avl_get_by_key (mimetypes, &exttype, &result)) { mime_type *mime = result; free (exttype.ext); type = strdup (mime->type); } else { free (exttype.ext); /* Fallbacks for a few basic ones */ if(!strcmp(ext, "ogg")) type = strdup ("application/ogg"); else if(!strcmp(ext, "mp3")) type = strdup ("audio/mpeg"); else if(!strcmp(ext, "html")) type = strdup ("text/html"); else if(!strcmp(ext, "css")) type = strdup ("text/css"); else if(!strcmp(ext, "txt")) type = strdup ("text/plain"); else if(!strcmp(ext, "jpg")) type = strdup ("image/jpeg"); else if(!strcmp(ext, "png")) type = strdup ("image/png"); else if(!strcmp(ext, "m3u")) type = strdup ("audio/x-mpegurl"); else if(!strcmp(ext, "aac")) type = strdup ("audio/aac"); else type = strdup ("application/octet-stream"); } thread_spin_unlock (&pending_lock); return type; }
/* string returned needs to be free'd */ char *fserve_content_type (const char *path) { char *ext = util_get_extension(path); mime_type exttype = { NULL, NULL }; void *result; char *type; if (ext == NULL) return strdup ("text/html"); exttype.ext = strdup (ext); thread_spin_lock (&pending_lock); if (mimetypes && !avl_get_by_key (mimetypes, &exttype, &result)) { mime_type *mime = result; type = strdup (mime->type); } else type = strdup ("application/octet-stream"); thread_spin_unlock (&pending_lock); free (exttype.ext); return type; }
/* client has requested a file, so check for it and send the file. Do not * refer to the client_t afterwards. return 0 for success, -1 on error. */ int fserve_client_create (client_t *httpclient, const char *path) { struct stat file_buf; char *fullpath; int m3u_requested = 0, m3u_file_available = 1; int xspf_requested = 0, xspf_file_available = 1; int ret = -1; ice_config_t *config; fbinfo finfo; char fsize[20]; fullpath = util_get_path_from_normalised_uri (path, 0); DEBUG2 ("checking for file %s (%s)", path, fullpath); if (strcmp (util_get_extension (fullpath), "m3u") == 0) m3u_requested = 1; if (strcmp (util_get_extension (fullpath), "xspf") == 0) xspf_requested = 1; /* check for the actual file */ if (stat (fullpath, &file_buf) != 0) { /* the m3u can be generated, but send an m3u file if available */ if (m3u_requested == 0 && xspf_requested == 0) { if (redirect_client (path, httpclient) == 0) { if ((httpclient->flags & CLIENT_SKIP_ACCESSLOG) == 0) WARN2 ("req for file \"%s\" %s", fullpath, strerror (errno)); ret = client_send_404 (httpclient, "The file you requested could not be found"); } free (fullpath); return ret; } m3u_file_available = 0; xspf_file_available = 0; } client_set_queue (httpclient, NULL); httpclient->refbuf = refbuf_new (4096); if (m3u_requested && m3u_file_available == 0) { const char *host = httpp_getvar (httpclient->parser, "host"), *args = httpp_getvar (httpclient->parser, HTTPP_VAR_QUERYARGS), *at = "", *user = "", *pass =""; char *sourceuri = strdup (path); char *dot = strrchr (sourceuri, '.'); char *protocol = "http"; const char *agent = httpp_getvar (httpclient->parser, "user-agent"); int x; char scratch[1000]; if (agent) { if (strstr (agent, "QTS") || strstr (agent, "QuickTime")) protocol = "icy"; } /* at least a couple of players (fb2k/winamp) are reported to send a * host header but without the port number. So if we are missing the * port then lets treat it as if no host line was sent */ if (host && strchr (host, ':') == NULL) host = NULL; *dot = 0; if (httpclient->username && httpclient->password) { at = "@"; user = httpclient->username; pass = httpclient->password; } httpclient->respcode = 200; if (host == NULL) { config = config_get_config(); x = snprintf (scratch, sizeof scratch, "%s://%s%s%s%s%s:%d%s%s\r\n", protocol, user, at[0]?":":"", pass, at, config->hostname, config->port, sourceuri, args?args:""); config_release_config(); } else { x = snprintf (scratch, sizeof scratch, "%s://%s%s%s%s%s%s%s\r\n", protocol, user, at[0]?":":"", pass, at, host, sourceuri, args?args:""); } snprintf (httpclient->refbuf->data, BUFSIZE, "HTTP/1.0 200 OK\r\n" "Content-Length: %d\r\n" "%s\r\n" "Content-Type: audio/x-mpegurl\r\n\r\n%s", x, client_keepalive_header (httpclient), scratch); httpclient->refbuf->len = strlen (httpclient->refbuf->data); free (sourceuri); free (fullpath); return fserve_setup_client_fb (httpclient, NULL); } if (xspf_requested && xspf_file_available == 0) { xmlDocPtr doc; char *reference = strdup (path); char *eol = strrchr (reference, '.'); if (eol) *eol = '\0'; doc = stats_get_xml (0, reference); free (reference); free (fullpath); return admin_send_response (doc, httpclient, XSLT, "xspf.xsl"); } /* on demand file serving check */ config = config_get_config(); if (config->fileserve == 0) { config_release_config(); DEBUG1 ("on demand file \"%s\" refused", fullpath); free (fullpath); return client_send_404 (httpclient, "The file you requested could not be found"); } config_release_config(); if (S_ISREG (file_buf.st_mode) == 0) { WARN1 ("found requested file but there is no handler for it: %s", fullpath); free (fullpath); return client_send_404 (httpclient, "The file you requested could not be found"); } free (fullpath); finfo.flags = 0; finfo.mount = (char *)path; finfo.fallback = NULL; finfo.limit = 0; finfo.type = FORMAT_TYPE_UNDEFINED; snprintf (fsize, 20, "%" PRId64, (int64_t)file_buf.st_size); httpp_setvar (httpclient->parser, "__FILESIZE", fsize); stats_event_inc (NULL, "file_connections"); return fserve_setup_client_fb (httpclient, &finfo); }
static int disk_image_check_for_d81(disk_image_t *image) { unsigned int blk = 0; char *ext; size_t len; BYTE block[256]; fsimage_t *fsimage; int checkimage_errorinfo; unsigned int checkimage_blocks; fsimage = image->media.fsimage; if (!(IS_D81_LEN(util_file_length(fsimage->fd)))) { return 0; } /* .d1m images share the same sizes with .d81, so we reject based on the file extension what is likely a .d1m image */ ext = util_get_extension(fsimage->name); if ((ext[0]) && (ext[1] == '1') && (ext[2])) { return 0; } rewind(fsimage->fd); while ((len = fread(block, 1, 256, fsimage->fd)) == 256) { if (++blk > (MAX_BLOCKS_1581 + 13)) { log_error(disk_image_probe_log, "Disk image too large."); break; } } if (disk_image_check_min_block(blk, NUM_BLOCKS_1581) < 0) { return 0; } switch (blk) { case NUM_BLOCKS_1581: /* 80 tracks */ case NUM_BLOCKS_1581 + 12: /* 80 tracks, with errors */ image->tracks = NUM_TRACKS_1581; break; case NUM_BLOCKS_1581 + 40: /* 81 tracks */ case NUM_BLOCKS_1581 + 40 + 12: /* 81 tracks, with errors */ image->tracks = NUM_TRACKS_1581 + 1; break; case NUM_BLOCKS_1581 + 80: /* 82 tracks */ case NUM_BLOCKS_1581 + 80 + 12: /* 82 tracks, with errors */ image->tracks = NUM_TRACKS_1581 + 2; break; case NUM_BLOCKS_1581 + 120: /* 83 tracks */ case NUM_BLOCKS_1581 + 120 + 12: /* 83 tracks, with errors */ image->tracks = NUM_TRACKS_1581 + 3; break; default: return 0; } image->type = DISK_IMAGE_TYPE_D81; image->max_half_tracks = MAX_TRACKS_1581 * 2; switch (blk) { case NUM_BLOCKS_1581 + 12: /* 80 tracks, with errors */ case NUM_BLOCKS_1581 + 40 + 12: /* 81 tracks, with errors */ case NUM_BLOCKS_1581 + 80 + 12: /* 82 tracks, with errors */ case NUM_BLOCKS_1581 + 120 + 12: /* 83 tracks, with errors */ checkimage_errorinfo = 1; break; default: checkimage_errorinfo = 0; break; } if (checkimage_errorinfo) { checkimage_blocks = image->tracks * 40; fsimage->error_info.map = lib_calloc(1, checkimage_blocks); fsimage->error_info.len = checkimage_blocks; if (util_fpread(fsimage->fd, fsimage->error_info.map, checkimage_blocks, 256 * checkimage_blocks) < 0) { return 0; } } disk_image_check_log(image, "D81"); return 1; }
/* client has requested a file, so check for it and send the file. Do not * refer to the client_t afterwards. return 0 for success, -1 on error. */ int fserve_client_create (client_t *httpclient) { int bytes; struct stat file_buf; const char *range = NULL; off_t new_content_len = 0; off_t rangenumber = 0, content_length; int rangeproblem = 0; int ret = 0; char *fullpath; int m3u_requested = 0, m3u_file_available = 1; const char * xslt_playlist_requested = NULL; int xslt_playlist_file_available = 1; ice_config_t *config; FILE *file; fullpath = util_get_path_from_normalised_uri(httpclient->uri); ICECAST_LOG_INFO("checking for file %H (%H)", httpclient->uri, fullpath); if (strcmp (util_get_extension (fullpath), "m3u") == 0) m3u_requested = 1; if (strcmp (util_get_extension (fullpath), "xspf") == 0) xslt_playlist_requested = "xspf.xsl"; if (strcmp (util_get_extension (fullpath), "vclt") == 0) xslt_playlist_requested = "vclt.xsl"; /* check for the actual file */ if (stat (fullpath, &file_buf) != 0) { /* the m3u can be generated, but send an m3u file if available */ if (m3u_requested == 0 && xslt_playlist_requested == NULL) { ICECAST_LOG_WARN("req for file \"%H\" %s", fullpath, strerror (errno)); client_send_error_by_id(httpclient, ICECAST_ERROR_FSERV_FILE_NOT_FOUND); free (fullpath); return -1; } m3u_file_available = 0; xslt_playlist_file_available = 0; } httpclient->refbuf->len = PER_CLIENT_REFBUF_SIZE; if (m3u_requested && m3u_file_available == 0) { char *sourceuri = strdup(httpclient->uri); char *dot = strrchr(sourceuri, '.'); *dot = 0; httpclient->respcode = 200; ret = util_http_build_header (httpclient->refbuf->data, BUFSIZE, 0, 0, 200, NULL, "audio/x-mpegurl", NULL, "", NULL, httpclient); if (ret == -1 || ret >= (BUFSIZE - 512)) { /* we want at least 512 bytes left for the content of the playlist */ ICECAST_LOG_ERROR("Dropping client as we can not build response headers."); client_send_error_by_id(httpclient, ICECAST_ERROR_GEN_HEADER_GEN_FAILED); free(sourceuri); return -1; } client_get_baseurl(httpclient, NULL, httpclient->refbuf->data + ret, BUFSIZE - ret, NULL, NULL, NULL, sourceuri, "\r\n"); httpclient->refbuf->len = strlen (httpclient->refbuf->data); fserve_add_client (httpclient, NULL); free (sourceuri); free (fullpath); return 0; } if (xslt_playlist_requested && xslt_playlist_file_available == 0) { xmlDocPtr doc; char *reference = strdup(httpclient->uri); char *eol = strrchr (reference, '.'); if (eol) *eol = '\0'; doc = stats_get_xml (0, reference, httpclient); free (reference); admin_send_response (doc, httpclient, ADMIN_FORMAT_HTML, xslt_playlist_requested); xmlFreeDoc(doc); free (fullpath); return 0; } /* on demand file serving check */ config = config_get_config(); if (config->fileserve == 0) { ICECAST_LOG_DEBUG("on demand file \"%H\" refused. Serving static files has been disabled in the config", fullpath); client_send_error_by_id(httpclient, ICECAST_ERROR_FSERV_FILE_NOT_FOUND); config_release_config(); free(fullpath); return -1; } config_release_config(); if (S_ISREG (file_buf.st_mode) == 0) { client_send_error_by_id(httpclient, ICECAST_ERROR_FSERV_FILE_NOT_FOUND); ICECAST_LOG_WARN("found requested file but there is no handler for it: %H", fullpath); free (fullpath); return -1; } file = fopen (fullpath, "rb"); if (file == NULL) { ICECAST_LOG_WARN("Problem accessing file \"%H\"", fullpath); client_send_error_by_id(httpclient, ICECAST_ERROR_FSERV_FILE_NOT_READABLE); free (fullpath); return -1; } free (fullpath); content_length = file_buf.st_size; range = httpp_getvar (httpclient->parser, "range"); /* full http range handling is currently not done but we deal with the common case */ if (range != NULL) { ret = 0; if (strncasecmp (range, "bytes=", 6) == 0) ret = sscanf (range+6, "%" SCN_OFF_T "-", &rangenumber); if (ret != 1) { /* format not correct, so lets just assume we start from the beginning */ rangeproblem = 1; } if (rangenumber < 0) { rangeproblem = 1; } if (!rangeproblem) { ret = fseeko (file, rangenumber, SEEK_SET); if (ret != -1) { new_content_len = content_length - rangenumber; if (new_content_len < 0) { rangeproblem = 1; } } else { rangeproblem = 1; } if (!rangeproblem) { off_t endpos = rangenumber+new_content_len-1; char *type; if (endpos < 0) { endpos = 0; } httpclient->respcode = 206; type = fserve_content_type(httpclient->uri); bytes = util_http_build_header (httpclient->refbuf->data, BUFSIZE, 0, 0, 206, NULL, type, NULL, NULL, NULL, httpclient); if (bytes == -1 || bytes >= (BUFSIZE - 512)) { /* we want at least 512 bytes left */ ICECAST_LOG_ERROR("Dropping client as we can not build response headers."); client_send_error_by_id(httpclient, ICECAST_ERROR_GEN_HEADER_GEN_FAILED); return -1; } bytes += snprintf (httpclient->refbuf->data + bytes, BUFSIZE - bytes, "Accept-Ranges: bytes\r\n" "Content-Length: %" PRI_OFF_T "\r\n" "Content-Range: bytes %" PRI_OFF_T \ "-%" PRI_OFF_T "/%" PRI_OFF_T "\r\n\r\n", new_content_len, rangenumber, endpos, content_length); free (type); } else { goto fail; } } else { goto fail; } } else { char *type = fserve_content_type(httpclient->uri); httpclient->respcode = 200; bytes = util_http_build_header (httpclient->refbuf->data, BUFSIZE, 0, 0, 200, NULL, type, NULL, NULL, NULL, httpclient); if (bytes == -1 || bytes >= (BUFSIZE - 512)) { /* we want at least 512 bytes left */ ICECAST_LOG_ERROR("Dropping client as we can not build response headers."); client_send_error_by_id(httpclient, ICECAST_ERROR_GEN_HEADER_GEN_FAILED); fclose(file); return -1; } bytes += snprintf (httpclient->refbuf->data + bytes, BUFSIZE - bytes, "Accept-Ranges: bytes\r\n" "Content-Length: %" PRI_OFF_T "\r\n\r\n", content_length); free (type); } httpclient->refbuf->len = bytes; httpclient->pos = 0; stats_event_inc (NULL, "file_connections"); fserve_add_client (httpclient, file); return 0; fail: fclose (file); client_send_error_by_id(httpclient, ICECAST_ERROR_FSERV_REQUEST_RANGE_NOT_SATISFIABLE); return -1; }
/* client has requested a file, so check for it and send the file. Do not * refer to the client_t afterwards. return 0 for success, -1 on error. */ int fserve_client_create (client_t *httpclient, const char *path) { int bytes; struct stat file_buf; const char *range = NULL; off_t new_content_len = 0; off_t rangenumber = 0, content_length; int rangeproblem = 0; int ret = 0; char *fullpath; int m3u_requested = 0, m3u_file_available = 1; const char * xslt_playlist_requested = NULL; int xslt_playlist_file_available = 1; ice_config_t *config; FILE *file; fullpath = util_get_path_from_normalised_uri (path); INFO2 ("checking for file %H (%H)", path, fullpath); if (strcmp (util_get_extension (fullpath), "m3u") == 0) m3u_requested = 1; if (strcmp (util_get_extension (fullpath), "xspf") == 0) xslt_playlist_requested = "xspf.xsl"; if (strcmp (util_get_extension (fullpath), "vclt") == 0) xslt_playlist_requested = "vclt.xsl"; /* check for the actual file */ if (stat (fullpath, &file_buf) != 0) { /* the m3u can be generated, but send an m3u file if available */ if (m3u_requested == 0 && xslt_playlist_requested == NULL) { WARN2 ("req for file \"%H\" %s", fullpath, strerror (errno)); client_send_404 (httpclient, "The file you requested could not be found"); free (fullpath); return -1; } m3u_file_available = 0; xslt_playlist_file_available = 0; } httpclient->refbuf->len = PER_CLIENT_REFBUF_SIZE; if (m3u_requested && m3u_file_available == 0) { const char *host = httpp_getvar (httpclient->parser, "host"); char *sourceuri = strdup (path); char *dot = strrchr(sourceuri, '.'); /* at least a couple of players (fb2k/winamp) are reported to send a * host header but without the port number. So if we are missing the * port then lets treat it as if no host line was sent */ if (host && strchr (host, ':') == NULL) host = NULL; *dot = 0; httpclient->respcode = 200; if (host == NULL) { config = config_get_config(); snprintf (httpclient->refbuf->data, BUFSIZE, "HTTP/1.0 200 OK\r\n" "Content-Type: audio/x-mpegurl\r\n\r\n" "http://%s:%d%s\r\n", config->hostname, config->port, sourceuri ); config_release_config(); } else { snprintf (httpclient->refbuf->data, BUFSIZE, "HTTP/1.0 200 OK\r\n" "Content-Type: audio/x-mpegurl\r\n\r\n" "http://%s%s\r\n", host, sourceuri ); } httpclient->refbuf->len = strlen (httpclient->refbuf->data); fserve_add_client (httpclient, NULL); free (sourceuri); free (fullpath); return 0; } if (xslt_playlist_requested && xslt_playlist_file_available == 0) { xmlDocPtr doc; char *reference = strdup (path); char *eol = strrchr (reference, '.'); if (eol) *eol = '\0'; doc = stats_get_xml (0, reference); free (reference); admin_send_response (doc, httpclient, TRANSFORMED, xslt_playlist_requested); xmlFreeDoc(doc); return 0; } /* on demand file serving check */ config = config_get_config(); if (config->fileserve == 0) { DEBUG1 ("on demand file \"%H\" refused", fullpath); client_send_404 (httpclient, "The file you requested could not be found"); config_release_config(); free (fullpath); return -1; } config_release_config(); if (S_ISREG (file_buf.st_mode) == 0) { client_send_404 (httpclient, "The file you requested could not be found"); WARN1 ("found requested file but there is no handler for it: %H", fullpath); free (fullpath); return -1; } file = fopen (fullpath, "rb"); if (file == NULL) { WARN1 ("Problem accessing file \"%H\"", fullpath); client_send_404 (httpclient, "File not readable"); free (fullpath); return -1; } free (fullpath); content_length = file_buf.st_size; range = httpp_getvar (httpclient->parser, "range"); /* full http range handling is currently not done but we deal with the common case */ if (range != NULL) { ret = 0; if (strncasecmp (range, "bytes=", 6) == 0) ret = sscanf (range+6, "%" SCN_OFF_T "-", &rangenumber); if (ret != 1) { /* format not correct, so lets just assume we start from the beginning */ rangeproblem = 1; } if (rangenumber < 0) { rangeproblem = 1; } if (!rangeproblem) { ret = fseeko (file, rangenumber, SEEK_SET); if (ret != -1) { new_content_len = content_length - rangenumber; if (new_content_len < 0) { rangeproblem = 1; } } else { rangeproblem = 1; } if (!rangeproblem) { /* Date: is required on all HTTP1.1 responses */ char currenttime[50]; time_t now; int strflen; struct tm result; off_t endpos = rangenumber+new_content_len-1; char *type; if (endpos < 0) { endpos = 0; } time(&now); strflen = strftime(currenttime, 50, "%a, %d-%b-%Y %X GMT", gmtime_r(&now, &result)); httpclient->respcode = 206; type = fserve_content_type (path); bytes = snprintf (httpclient->refbuf->data, BUFSIZE, "HTTP/1.1 206 Partial Content\r\n" "Date: %s\r\n" "Accept-Ranges: bytes\r\n" "Content-Length: %" PRI_OFF_T "\r\n" "Content-Range: bytes %" PRI_OFF_T \ "-%" PRI_OFF_T "/%" PRI_OFF_T "\r\n" "Content-Type: %s\r\n\r\n", currenttime, new_content_len, rangenumber, endpos, content_length, type); free (type); } else { goto fail; } } else { goto fail; } } else { char *type = fserve_content_type(path); httpclient->respcode = 200; bytes = snprintf (httpclient->refbuf->data, BUFSIZE, "HTTP/1.0 200 OK\r\n" "Accept-Ranges: bytes\r\n" "Content-Length: %" PRI_OFF_T "\r\n" "Content-Type: %s\r\n\r\n", content_length, type); free (type); } httpclient->refbuf->len = bytes; httpclient->pos = 0; stats_event_inc (NULL, "file_connections"); fserve_add_client (httpclient, file); return 0; fail: fclose (file); httpclient->respcode = 416; sock_write (httpclient->con->sock, "HTTP/1.0 416 Request Range Not Satisfiable\r\n\r\n"); client_destroy (httpclient); return -1; }
int ui_screenshot_dialog(char *name, struct video_canvas_s *wid) { int res, i; char *fn, *tmp; const char *driver, *ext; if (screenshot_dialog) { gdk_window_show(screenshot_dialog->window); gdk_window_raise(screenshot_dialog->window); gtk_widget_show(screenshot_dialog); } else { screenshot_dialog = build_screenshot_dialog(); if (screenshot_dialog) g_signal_connect(G_OBJECT(screenshot_dialog), "destroy", G_CALLBACK(gtk_widget_destroyed), &screenshot_dialog); else return -1; } ui_popup(screenshot_dialog, _("Save Screenshot"), FALSE); res = gtk_dialog_run(GTK_DIALOG(screenshot_dialog)); ui_popdown(screenshot_dialog); if (res != GTK_RESPONSE_ACCEPT) return -1; fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileentry)); if (!fn) { ui_error(_("Invalid filename")); return -1; } i = gtk_combo_box_get_active(GTK_COMBO_BOX(drv_menu)); if (i < 0) return -1; driver = buttons[i].driver; ext = buttons[i].ext; #ifdef HAVE_FFMPEG if (strcmp(driver, "FFMPEG") == 0) { int audio_bitrate, video_bitrate; audio_bitrate = (int) gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ffmpg_audio)); resources_set_int("FFMPEGAudioBitrate", audio_bitrate); video_bitrate = (int) gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ffmpg_video)); resources_set_int("FFMPEGVideoBitrate", video_bitrate); resources_set_string("FFMPEGFormat", selected_driver); resources_set_int("FFMPEGAudioCodec", selected_ac); resources_set_int("FFMPEGVideoCodec", selected_vc); log_message(LOG_DEFAULT, "FFMPEG: Driver: %s, ac: %d, vc: %d\n", selected_driver, selected_ac, selected_vc); } #endif tmp = lib_stralloc(fn); lib_free(fn); if (!util_get_extension(tmp)) util_add_extension(&tmp, ext); if (screenshot_save(driver, tmp, wid) < 0) { ui_error(_("Couldn't write screenshot to `%s' with driver `%s'."), tmp, driver); lib_free(tmp); return -1; } else { if (screenshot_is_recording()) gtk_widget_show(video_ctrl_checkbox); ui_message(_("Successfully wrote `%s'"), tmp); lib_free(tmp); } return 0; }
static void _handle_get_request(connection_t *con, http_parser_t *parser, char *passed_uri) { char *fullpath; client_t *client; int bytes; struct stat statbuf; source_t *source; int fileserve; char *host; int port; int i; char *serverhost = NULL; int serverport = 0; aliases *alias; ice_config_t *config; int client_limit; int ret; char *uri = passed_uri; config = config_get_config(); fileserve = config->fileserve; host = config->hostname; port = config->port; for(i = 0; i < MAX_LISTEN_SOCKETS; i++) { if(global.serversock[i] == con->serversock) { serverhost = config->listeners[i].bind_address; serverport = config->listeners[i].port; break; } } alias = config->aliases; client_limit = config->client_limit; /* there are several types of HTTP GET clients ** media clients, which are looking for a source (eg, URI = /stream.ogg) ** stats clients, which are looking for /admin/stats.xml ** and directory server authorizers, which are looking for /GUID-xxxxxxxx ** (where xxxxxx is the GUID in question) - this isn't implemented yet. ** we need to handle the latter two before the former, as the latter two ** aren't subject to the limits. */ /* TODO: add GUID-xxxxxx */ /* Handle aliases */ while(alias) { if(strcmp(uri, alias->source) == 0 && (alias->port == -1 || alias->port == serverport) && (alias->bind_address == NULL || (serverhost != NULL && strcmp(alias->bind_address, serverhost) == 0))) { uri = strdup (alias->destination); DEBUG2 ("alias has made %s into %s", passed_uri, uri); break; } alias = alias->next; } config_release_config(); /* make a client */ client = client_create(con, parser); stats_event_inc(NULL, "client_connections"); /* Dispatch all admin requests */ if (strncmp(uri, "/admin/", 7) == 0) { admin_handle_request(client, uri); if (uri != passed_uri) free (uri); return; } /* Here we are parsing the URI request to see ** if the extension is .xsl, if so, then process ** this request as an XSLT request */ fullpath = util_get_path_from_normalised_uri(uri); if (util_check_valid_extension(fullpath) == XSLT_CONTENT) { /* If the file exists, then transform it, otherwise, write a 404 */ if (stat(fullpath, &statbuf) == 0) { DEBUG0("Stats request, sending XSL transformed stats"); client->respcode = 200; bytes = sock_write(client->con->sock, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"); if(bytes > 0) client->con->sent_bytes = bytes; stats_transform_xslt(client, fullpath); client_destroy(client); } else { client_send_404(client, "The file you requested could not be found"); } free(fullpath); if (uri != passed_uri) free (uri); return; } else if(fileserve && stat(fullpath, &statbuf) == 0 && #ifdef _WIN32 ((statbuf.st_mode) & _S_IFREG)) #else S_ISREG(statbuf.st_mode)) #endif { fserve_client_create(client, fullpath); free(fullpath); if (uri != passed_uri) free (uri); return; } free(fullpath); if(strcmp(util_get_extension(uri), "m3u") == 0) { char *sourceuri = strdup(uri); char *dot = strrchr(sourceuri, '.'); *dot = 0; client->respcode = 200; bytes = sock_write(client->con->sock, "HTTP/1.0 200 OK\r\n" "Content-Type: audio/x-mpegurl\r\n\r\n" "http://%s:%d%s\r\n", host, port, sourceuri ); if(bytes > 0) client->con->sent_bytes = bytes; client_destroy(client); free(sourceuri); if (uri != passed_uri) free (uri); return; } global_lock(); if (global.clients >= client_limit) { global_unlock(); client_send_404(client, "The server is already full. Try again later."); if (uri != passed_uri) free (uri); return; } global_unlock(); avl_tree_rlock(global.source_tree); source = source_find_mount(uri); if (source) { DEBUG0("Source found for client"); /* The source may not be the requested source - it might have gone * via one or more fallbacks. We only reject it for no-mount if it's * the originally requested source */ if(strcmp(uri, source->mount) == 0 && source->no_mount) { avl_tree_unlock(global.source_tree); client_send_404(client, "This mount is unavailable."); if (uri != passed_uri) free (uri); return; } if (source->running == 0) { avl_tree_unlock(global.source_tree); DEBUG0("inactive source, client dropped"); client_send_404(client, "This mount is unavailable."); if (uri != passed_uri) free (uri); return; } /* Check for any required authentication first */ if(source->authenticator != NULL) { ret = auth_check_client(source, client); if(ret != AUTH_OK) { avl_tree_unlock(global.source_tree); if (ret == AUTH_FORBIDDEN) { INFO1("Client attempted to log multiple times to source " "(\"%s\")", uri); client_send_403(client); } else { /* If not FORBIDDEN, default to 401 */ INFO1("Client attempted to log in to source (\"%s\")with " "incorrect or missing password", uri); client_send_401(client); } if (uri != passed_uri) free (uri); return; } } /* And then check that there's actually room in the server... */ global_lock(); if (global.clients >= client_limit) { global_unlock(); avl_tree_unlock(global.source_tree); client_send_404(client, "The server is already full. Try again later."); if (uri != passed_uri) free (uri); return; } /* Early-out for per-source max listeners. This gets checked again * by the source itself, later. This route gives a useful message to * the client, also. */ else if(source->max_listeners != -1 && source->listeners >= source->max_listeners) { global_unlock(); avl_tree_unlock(global.source_tree); client_send_404(client, "Too many clients on this mountpoint. Try again later."); if (uri != passed_uri) free (uri); return; } global.clients++; global_unlock(); source->format->create_client_data (source, client); source->format->client_send_headers(source->format, source, client); bytes = sock_write(client->con->sock, "\r\n"); if(bytes > 0) client->con->sent_bytes += bytes; sock_set_blocking(client->con->sock, SOCK_NONBLOCK); sock_set_nodelay(client->con->sock); avl_tree_wlock(source->pending_tree); avl_insert(source->pending_tree, (void *)client); avl_tree_unlock(source->pending_tree); } avl_tree_unlock(global.source_tree); if (!source) { DEBUG0("Source not found for client"); client_send_404(client, "The source you requested could not be found."); } if (uri != passed_uri) free (uri); }