From c1d0fe75d267f33724c38af95efc7b1c050dc160 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 17 Jun 2021 08:54:00 +0200 Subject: Temporary abort on fail to read file.. if its being modified while reading --- src/plugins/Youtube.cpp | 79 ++++++++++++++++++++------------------- src/plugins/youtube/Signature.cpp | 33 ++++++++++++++-- 2 files changed, 70 insertions(+), 42 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp index ed30aec..d9d9239 100644 --- a/src/plugins/Youtube.cpp +++ b/src/plugins/Youtube.cpp @@ -472,11 +472,37 @@ R"END( return "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8"; } + static std::string cpn; + + static bool generate_random_characters(char *buffer, int buffer_size, const char *alphabet, size_t alphabet_size) { + int fd = open("/dev/urandom", O_RDONLY); + if(fd == -1) { + perror("/dev/urandom"); + return false; + } + + if(read(fd, buffer, buffer_size) < buffer_size) { + fprintf(stderr, "Failed to read %d bytes from /dev/urandom\n", buffer_size); + close(fd); + return false; + } + + for(int i = 0; i < buffer_size; ++i) { + unsigned char c = *(unsigned char*)&buffer[i]; + buffer[i] = alphabet[c % alphabet_size]; + } + close(fd); + return true; + } + static std::vector get_cookies() { std::lock_guard lock(cookies_mutex); if(cookies_filepath.empty()) { YoutubeSignatureDecryptor::get_instance(); + cpn.resize(16); + generate_random_characters(cpn.data(), cpn.size(), "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_", 64); + Path cookies_filepath_p; if(get_cookies_filepath(cookies_filepath_p, "youtube") != 0) { show_notification("QuickMedia", "Failed to create youtube cookies file", Urgency::CRITICAL); @@ -1331,14 +1357,20 @@ R"END( std::unordered_set channel_ids; std::string subscriptions_str; - if(file_get_content(subscriptions_path, subscriptions_str) == 0) { - string_split(subscriptions_str, '\n', [&channel_ids](const char *str, size_t size) { - std::string line(str, size); - line = strip(line); - if(!line.empty()) - channel_ids.insert(std::move(line)); - return true; - }); + FileType file_type = get_file_type(subscriptions_path); + if(file_type == FileType::REGULAR) { + if(file_get_content(subscriptions_path, subscriptions_str) == 0) { + string_split(subscriptions_str, '\n', [&channel_ids](const char *str, size_t size) { + std::string line(str, size); + line = strip(line); + if(!line.empty()) + channel_ids.insert(std::move(line)); + return true; + }); + } else { + show_notification("QuickMedia", "Failed to read " + subscriptions_path.data, Urgency::CRITICAL); + abort(); + } } auto it = channel_ids.find(channel_id); @@ -2044,27 +2076,6 @@ R"END( return PluginResult::OK; } - static bool generate_random_characters(char *buffer, int buffer_size, const char *alphabet, size_t alphabet_size) { - int fd = open("/dev/urandom", O_RDONLY); - if(fd == -1) { - perror("/dev/urandom"); - return false; - } - - if(read(fd, buffer, buffer_size) < buffer_size) { - fprintf(stderr, "Failed to read %d bytes from /dev/urandom\n", buffer_size); - close(fd); - return false; - } - - for(int i = 0; i < buffer_size; ++i) { - unsigned char c = *(unsigned char*)&buffer[i]; - buffer[i] = alphabet[c % alphabet_size]; - } - close(fd); - return true; - } - void YoutubeVideoPage::mark_watched() { if(playback_url.empty()) { fprintf(stderr, "Failed to mark video as watched because playback_url is empty\n"); @@ -2079,10 +2090,6 @@ R"END( std::vector cookies = get_cookies(); additional_args.insert(additional_args.end(), cookies.begin(), cookies.end()); - std::string cpn; - cpn.resize(16); - generate_random_characters(cpn.data(), cpn.size(), "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_", 64); - std::string response; DownloadResult download_result = download_to_string(playback_url + "&ver=2&cpn=" + cpn, response, std::move(additional_args), true); if(download_result != DownloadResult::OK) { @@ -2106,12 +2113,8 @@ R"END( if(cipher_params.empty() || url.empty()) return false; - std::string cpn; - cpn.resize(16); - generate_random_characters(cpn.data(), cpn.size(), "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_", 64); - std::string url_decoded = url_param_decode(url); - url_decoded += "&alr=yes&cver=2.20210615.01.00&altitags=395,394&cpn=" + cpn; + url_decoded += "&alr=yes&cver=2.20210615.01.00&cpn=" + cpn; const std::string &s = cipher_params["s"]; const std::string &sp = cipher_params["sp"]; diff --git a/src/plugins/youtube/Signature.cpp b/src/plugins/youtube/Signature.cpp index 8c87817..7631182 100644 --- a/src/plugins/youtube/Signature.cpp +++ b/src/plugins/youtube/Signature.cpp @@ -4,6 +4,7 @@ #include "../../../include/DownloadUtils.hpp" #include "../../../include/StringUtils.hpp" #include "../../../include/Program.hpp" +#include "../../../include/NetUtils.hpp" #include #include #include @@ -18,6 +19,26 @@ namespace QuickMedia { static std::mutex update_signature_mutex; static const int timeout_default_sec = 60 * 5; // 5 minutes + static bool is_whitespace(char c) { + switch(c) { + case ' ': + case '\r': + case '\n': + case '\t': + return true; + } + return false; + } + + static std::string remove_whitespaces(const std::string &str) { + std::string result; + for(char c : str) { + if(!is_whitespace(c)) + result += c; + } + return result; + } + bool YoutubeSignatureDecryptor::js_code_to_operations(const std::string &function_body_str, const std::string &var_body_str, std::vector &new_func_calls, std::map &new_func_decls) { std::vector function_body; string_split(function_body_str, ';', [&function_body](const char *str, size_t size) { @@ -77,7 +98,7 @@ namespace QuickMedia { std::string func_name = func_decl_str.substr(0, func_name_split_index); func_name = strip(func_name); std::string function_body = func_decl_str.substr(func_start_index + 1); - function_body = strip(function_body); + function_body = strip(remove_whitespaces(function_body)); if(!function_body.empty() && function_body.back() == '}') function_body.pop_back(); @@ -86,8 +107,12 @@ namespace QuickMedia { decrypt_function = DecryptFunction::REVERSE; else if(function_body == "a.splice(0,b)") decrypt_function = DecryptFunction::SPLICE; - else + else if(function_body.find("a[0]=a[b%a.length]") != std::string::npos) decrypt_function = DecryptFunction::SWAP; + else { + fprintf(stderr, "Unexpected decryption function body: |%s|\n", function_body.c_str()); + return false; + } //fprintf(stderr, "declared function: %s, body: |%s|\n", func_name.c_str(), function_body.c_str()); new_func_decls[std::move(func_name)] = decrypt_function; } @@ -216,7 +241,7 @@ namespace QuickMedia { break; } case DecryptFunction::SWAP: { - if(sig.empty()) { + if(sig.empty() || func_call.arg < 0) { fprintf(stderr, "YoutubeSignatureDecryptor: sig unexpectedly empty in swap\n"); } else { char c = sig[0]; @@ -229,7 +254,7 @@ namespace QuickMedia { } sig_key = sp; - sig_value = sig; + sig_value = url_param_encode(sig); return true; } -- cgit v1.2.3