aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-05-11 14:57:45 +0200
committerdec05eba <dec05eba@protonmail.com>2021-05-11 14:57:45 +0200
commit8d08b8f3d4a627c3190c485bf43690e414862d83 (patch)
tree0cc2ec792fe5fcf80051f7cd6f9dffc868e0eb0c
parent93484ecf081fcb57313fa5d161cd90dccee0dc9e (diff)
Youtube-dl cant properly extract remote file name, use our own extraction code when not using mpv. Fix close button not working for download menu
-rw-r--r--include/DownloadUtils.hpp2
-rw-r--r--src/DownloadUtils.cpp73
-rw-r--r--src/QuickMedia.cpp63
3 files changed, 111 insertions, 27 deletions
diff --git a/include/DownloadUtils.hpp b/include/DownloadUtils.hpp
index 964e74b..620b936 100644
--- a/include/DownloadUtils.hpp
+++ b/include/DownloadUtils.hpp
@@ -22,6 +22,8 @@ namespace QuickMedia {
using DownloadErrorHandler = std::function<bool(std::string&)>;
DownloadResult download_head_to_string(const std::string &url, std::string &result, bool use_browser_useragent = false, bool fail_on_error = true);
+ // Returns the remote name from the content-disposition header or tries to extract the file name from url. Can return empty name
+ DownloadResult url_get_remote_name(const std::string &url, std::string &result, bool use_browser_useragent);
DownloadResult download_to_string(const std::string &url, std::string &result, const std::vector<CommandArg> &additional_args, bool use_browser_useragent = false, bool fail_on_error = true);
// Note: This function saves the content to the file atomically
DownloadResult download_to_string_cache(const std::string &url, std::string &result, const std::vector<CommandArg> &additional_args, bool use_browser_useragent = false, DownloadErrorHandler error_handler = nullptr, Path cache_path = "");
diff --git a/src/DownloadUtils.cpp b/src/DownloadUtils.cpp
index 248fda0..a054454 100644
--- a/src/DownloadUtils.cpp
+++ b/src/DownloadUtils.cpp
@@ -49,6 +49,79 @@ namespace QuickMedia {
return DownloadResult::OK;
}
+ DownloadResult url_get_remote_name(const std::string &url, std::string &result, bool use_browser_useragent) {
+ sf::Clock timer;
+ std::vector<const char*> args;
+ args.insert(args.end(), { "curl", "-I", "-g", "-H", "Accept-Language: en-US,en;q=0.5", "-H", "Connection: keep-alive", "--compressed", "-s" });
+ if(use_browser_useragent) {
+ args.push_back("-H");
+ args.push_back(useragent_str);
+ }
+ args.push_back("--");
+ args.push_back(url.c_str());
+ args.push_back(nullptr);
+ if(debug_download) {
+ for(const char *arg : args) {
+ if(arg)
+ fprintf(stderr, "'%s' ", arg);
+ }
+ fprintf(stderr, "\n");
+ }
+ std::string header;
+ if(exec_program(args.data(), accumulate_string, &header) != 0)
+ return DownloadResult::NET_ERR;
+ fprintf(stderr, "Download duration for %s: %d ms\n", url.c_str(), timer.getElapsedTime().asMilliseconds());
+
+ std::string content_disposition = header_extract_value(header, "content-disposition");
+ if(content_disposition.empty()) {
+ size_t filename_start = url.rfind('/');
+ if(filename_start == std::string::npos) {
+ result = "";
+ return DownloadResult::OK;
+ }
+
+ ++filename_start;
+ size_t filename_end = url.size();
+ for(size_t i = filename_start; i < url.size(); ++i) {
+ char c = url[i];
+ if(c == '/' || c == '&' || c == '?') {
+ filename_end = i;
+ break;
+ }
+ }
+
+ result = url.substr(filename_start, filename_end - filename_start);
+ return DownloadResult::OK;
+ } else {
+ size_t filename_start = content_disposition.find("filename=");
+ if(filename_start == std::string::npos) {
+ result = "";
+ return DownloadResult::OK;
+ }
+
+ filename_start += 9;
+ for(size_t i = filename_start; i < content_disposition.size(); ++i) {
+ char c = content_disposition[i];
+ if(c != '"' && c != ' ') {
+ filename_start = i;
+ break;
+ }
+ }
+
+ size_t filename_end = content_disposition.size();
+ for(int i = filename_end - 1; i >= (int)filename_start; --i) {
+ char c = content_disposition[i];
+ if(c != '"' && c != ' ' && c != '\n' && c != '\r') {
+ filename_end = i + 1;
+ break;
+ }
+ }
+
+ result = content_disposition.substr(filename_start, filename_end - filename_start);
+ return DownloadResult::OK;
+ }
+ }
+
// TODO: Add timeout
DownloadResult download_to_string(const std::string &url, std::string &result, const std::vector<CommandArg> &additional_args, bool use_browser_useragent, bool fail_on_error) {
sf::Clock timer;
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 79b9207..c515719 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -5945,37 +5945,44 @@ namespace QuickMedia {
window.setTitle("QuickMedia - Select where you want to save " + std::string(url));
std::string filename;
- TaskResult task_result = run_task_with_loading_screen([this, url, &filename]{
- std::string json_str;
- std::vector<const char*> args = { "youtube-dl", "--skip-download", "--print-json", "--no-warnings" };
- if(no_video)
- args.push_back("-x");
- args.insert(args.end(), { "--", url, nullptr });
- if(exec_program(args.data(), accumulate_string, &json_str) != 0)
- return false;
+ TaskResult task_result;
+ if(download_use_youtube_dl) {
+ task_result = run_task_with_loading_screen([this, url, &filename]{
+ std::string json_str;
+ std::vector<const char*> args = { "youtube-dl", "--skip-download", "--print-json", "--no-warnings" };
+ if(no_video)
+ args.push_back("-x");
+ args.insert(args.end(), { "--", url, nullptr });
+ if(exec_program(args.data(), accumulate_string, &json_str) != 0)
+ return false;
- Json::Value result;
- Json::CharReaderBuilder json_builder;
- std::unique_ptr<Json::CharReader> json_reader(json_builder.newCharReader());
- std::string json_errors;
- if(!json_reader->parse(json_str.data(), json_str.data() + json_str.size(), &result, &json_errors)) {
- fprintf(stderr, "Failed to json response, error: %s\n", json_errors.c_str());
- return false;
- }
+ Json::Value result;
+ Json::CharReaderBuilder json_builder;
+ std::unique_ptr<Json::CharReader> json_reader(json_builder.newCharReader());
+ std::string json_errors;
+ if(!json_reader->parse(json_str.data(), json_str.data() + json_str.size(), &result, &json_errors)) {
+ fprintf(stderr, "Failed to json response, error: %s\n", json_errors.c_str());
+ return false;
+ }
- const Json::Value &title_json = result["title"];
- const Json::Value &ext_json = result["ext"];
- if(title_json.isString())
- filename = title_json.asString();
+ const Json::Value &title_json = result["title"];
+ const Json::Value &ext_json = result["ext"];
+ if(title_json.isString())
+ filename = title_json.asString();
- if(ext_json.isString()) {
- if(ext_json.asCString()[0] != '.' && (filename.empty() || filename.back() != '.'))
- filename += ".";
- filename += ext_json.asString();
- }
+ if(ext_json.isString()) {
+ if(ext_json.asCString()[0] != '.' && (filename.empty() || filename.back() != '.'))
+ filename += ".";
+ filename += ext_json.asString();
+ }
- return !filename.empty();
- });
+ return !filename.empty();
+ });
+ } else {
+ task_result = run_task_with_loading_screen([url, &filename]{
+ return url_get_remote_name(url, filename, true) == DownloadResult::OK;
+ });
+ }
if(task_result == TaskResult::CANCEL) {
exit_code = 1;
@@ -6304,6 +6311,8 @@ namespace QuickMedia {
std::string save_path = save_file();
if(!save_path.empty())
return save_path;
+ } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) {
+ window.close();
}
}