aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2019-10-15 19:57:24 +0200
committerdec05eba <dec05eba@protonmail.com>2019-10-15 19:57:27 +0200
commit56acc142c6ef9a65147acdea6737acbfaeb7eca4 (patch)
tree1b9a955bec7ed74c16e3cf663b9acca5aef8c19e /src
parent2ba21aa9aa91b975fe0c8be630dde05d0d9b5366 (diff)
Add tor support
Diffstat (limited to 'src')
-rw-r--r--src/Body.cpp6
-rw-r--r--src/QuickMedia.cpp82
-rw-r--r--src/StringUtils.cpp17
-rw-r--r--src/VideoPlayer.cpp23
-rw-r--r--src/plugins/Plugin.cpp35
5 files changed, 118 insertions, 45 deletions
diff --git a/src/Body.cpp b/src/Body.cpp
index fb44929..7ed1a7f 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -1,4 +1,5 @@
#include "../include/Body.hpp"
+#include "../include/QuickMedia.hpp"
#include "../plugins/Plugin.hpp"
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Graphics/Sprite.hpp>
@@ -9,7 +10,8 @@ const sf::Color front_color(43, 45, 47);
const sf::Color back_color(33, 35, 37);
namespace QuickMedia {
- Body::Body(sf::Font &font) :
+ Body::Body(Program *program, sf::Font &font) :
+ program(program),
title_text("", font, 14),
progress_text("", font, 14),
selected_item(0),
@@ -96,7 +98,7 @@ namespace QuickMedia {
loading_thumbnail = true;
thumbnail_load_thread = std::thread([this, result, url]() {
std::string texture_data;
- if(download_to_string(url, texture_data) == DownloadResult::OK) {
+ if(program->get_current_plugin()->download_to_string(url, texture_data) == DownloadResult::OK) {
if(result->loadFromMemory(texture_data.data(), texture_data.size()))
result->generateMipmap();
}
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index f277f46..6ac47bf 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -6,6 +6,7 @@
#include "../include/Scale.hpp"
#include "../include/Program.h"
#include "../include/VideoPlayer.hpp"
+#include "../include/StringUtils.hpp"
#include <cppcodec/base64_rfc4648.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
@@ -52,7 +53,7 @@ namespace QuickMedia {
fprintf(stderr, "Failed to load font!\n");
abort();
}
- body = new Body(font);
+ body = new Body(this, font);
struct sigaction action;
action.sa_handler = sigpipe_handler;
@@ -83,9 +84,32 @@ namespace QuickMedia {
}
static void usage() {
- fprintf(stderr, "usage: QuickMedia <plugin>\n");
+ fprintf(stderr, "usage: QuickMedia <plugin> [--tor]\n");
fprintf(stderr, "OPTIONS:\n");
- fprintf(stderr, "plugin The plugin to use. Should be either manganelo, youtube or pornhub\n");
+ fprintf(stderr, "plugin The plugin to use. Should be either 4chan, manganelo, pornhub or youtube\n");
+ fprintf(stderr, "--tor Use tor. Disabled by default\n");
+ fprintf(stderr, "EXAMPLES:\n");
+ fprintf(stderr, "QuickMedia manganelo\n");
+ fprintf(stderr, "QuickMedia youtube --tor\n");
+ }
+
+ static bool is_program_executable_by_name(const char *name) {
+ // TODO: Implement for Windows. Windows also uses semicolon instead of colon as a separator
+ char *env = getenv("PATH");
+ std::unordered_set<std::string> paths;
+ string_split(env, ':', [&paths](const char *str, size_t size) {
+ paths.insert(std::string(str, size));
+ return true;
+ });
+
+ for(const std::string &path_str : paths) {
+ Path path(path_str);
+ path.join(name);
+ if(get_file_type(path) == FileType::REGULAR)
+ return true;
+ }
+
+ return false;
}
int Program::run(int argc, char **argv) {
@@ -94,24 +118,44 @@ namespace QuickMedia {
return -1;
}
+ current_plugin = nullptr;
std::string plugin_logo_path;
- if(strcmp(argv[1], "manganelo") == 0) {
- current_plugin = new Manganelo();
- plugin_logo_path = "../../../images/manganelo_logo.png";
- } else if(strcmp(argv[1], "youtube") == 0) {
- current_plugin = new Youtube();
- plugin_logo_path = "../../../images/yt_logo_rgb_dark_small.png";
- } else if(strcmp(argv[1], "pornhub") == 0) {
- current_plugin = new Pornhub();
- plugin_logo_path = "../../../images/pornhub_logo.png";
- } else if(strcmp(argv[1], "4chan") == 0) {
- current_plugin = new Fourchan();
- plugin_logo_path = "../../../images/4chan_logo.png";
- } else {
+ bool use_tor = false;
+
+ for(int i = 1; i < argc; ++i) {
+ if(!current_plugin) {
+ if(strcmp(argv[i], "manganelo") == 0) {
+ current_plugin = new Manganelo();
+ plugin_logo_path = "../../../images/manganelo_logo.png";
+ } else if(strcmp(argv[i], "youtube") == 0) {
+ current_plugin = new Youtube();
+ plugin_logo_path = "../../../images/yt_logo_rgb_dark_small.png";
+ } else if(strcmp(argv[i], "pornhub") == 0) {
+ current_plugin = new Pornhub();
+ plugin_logo_path = "../../../images/pornhub_logo.png";
+ } else if(strcmp(argv[i], "4chan") == 0) {
+ current_plugin = new Fourchan();
+ plugin_logo_path = "../../../images/4chan_logo.png";
+ }
+ }
+
+ if(strcmp(argv[i], "--tor") == 0) {
+ use_tor = true;
+ }
+ }
+
+ if(!current_plugin) {
usage();
return -1;
}
+ if(use_tor && !is_program_executable_by_name("torsocks")) {
+ fprintf(stderr, "torsocks needs to be installed (and accessible from PATH environment variable) when using the --tor option\n");
+ return -2;
+ }
+
+ current_plugin->use_tor = use_tor;
+
if(!plugin_logo_path.empty()) {
if(!plugin_logo.loadFromFile(plugin_logo_path)) {
fprintf(stderr, "Failed to load plugin logo, path: %s\n", plugin_logo_path.c_str());
@@ -532,7 +576,7 @@ namespace QuickMedia {
}
};
- video_player = std::make_unique<VideoPlayer>([this, &video_player, &seekable, &load_video_error_check](const char *event_name) {
+ video_player = std::make_unique<VideoPlayer>(current_plugin->use_tor, [this, &video_player, &seekable, &load_video_error_check](const char *event_name) {
bool end_of_file = false;
if(strcmp(event_name, "pause") == 0) {
double time_remaining = 0.0;
@@ -861,7 +905,7 @@ namespace QuickMedia {
return true;
std::string image_content;
- if(download_to_string(url, image_content) != DownloadResult::OK) {
+ if(current_plugin->download_to_string(url, image_content) != DownloadResult::OK) {
show_notification("Manganelo", "Failed to download image: " + url, Urgency::CRITICAL);
return false;
}
@@ -981,7 +1025,7 @@ namespace QuickMedia {
}
sf::Clock check_downloaded_timer;
- const sf::Int32 check_downloaded_timeout_ms = 1000;
+ const sf::Int32 check_downloaded_timeout_ms = 500;
// TODO: Show to user if a certain page is missing (by checking page name (number) and checking if some are skipped)
while (current_page == Page::IMAGES) {
diff --git a/src/StringUtils.cpp b/src/StringUtils.cpp
new file mode 100644
index 0000000..deb4949
--- /dev/null
+++ b/src/StringUtils.cpp
@@ -0,0 +1,17 @@
+#include "../include/StringUtils.hpp"
+
+namespace QuickMedia {
+ void string_split(const std::string &str, char delimiter, StringSplitCallback callback_func) {
+ size_t index = 0;
+ while(true) {
+ size_t new_index = str.find(delimiter, index);
+ if(new_index == std::string::npos)
+ break;
+
+ if(!callback_func(str.data() + index, new_index - index))
+ break;
+
+ index = new_index + 1;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/VideoPlayer.cpp b/src/VideoPlayer.cpp
index 2336367..dfe6603 100644
--- a/src/VideoPlayer.cpp
+++ b/src/VideoPlayer.cpp
@@ -14,11 +14,11 @@
const int RETRY_TIME_MS = 1000;
const int MAX_RETRIES_CONNECT = 5;
-const int MAX_RETRIES_FIND_WINDOW = 10;
const int READ_TIMEOUT_MS = 200;
namespace QuickMedia {
- VideoPlayer::VideoPlayer(EventCallbackFunc _event_callback, VideoPlayerWindowCreateCallback _window_create_callback) :
+ VideoPlayer::VideoPlayer(bool use_tor, EventCallbackFunc _event_callback, VideoPlayerWindowCreateCallback _window_create_callback) :
+ use_tor(use_tor),
video_process_id(-1),
ipc_socket(-1),
connected_to_ipc(false),
@@ -64,15 +64,18 @@ namespace QuickMedia {
}
const std::string parent_window_str = std::to_string(parent_window);
- const char *args[] = { "mpv", "--keep-open=yes", /*"--keep-open-pause=no",*/ "--input-ipc-server", ipc_server_path,
+ std::vector<const char*> args;
+ if(use_tor)
+ args.push_back("torsocks");
+ args.insert(args.end(), { "mpv", "--keep-open=yes", /*"--keep-open-pause=no",*/ "--input-ipc-server", ipc_server_path,
"--no-config", "--no-input-default-bindings", "--input-vo-keyboard=no", "--no-input-cursor",
"--cache-secs=120", "--demuxer-max-bytes=40M", "--demuxer-max-back-bytes=20M",
"--no-input-terminal",
"--no-osc",
"--profile=gpu-hq",
/*"--vo=gpu", "--hwdec=auto",*/
- "--wid", parent_window_str.c_str(), "--", path, nullptr };
- if(exec_program_async(args, &video_process_id) != 0)
+ "--wid", parent_window_str.c_str(), "--", path, nullptr });
+ if(exec_program_async(args.data(), &video_process_id) != 0)
return Error::FAIL_TO_LAUNCH_PROCESS;
printf("mpv input ipc server: %s\n", ipc_server_path);
@@ -125,13 +128,17 @@ namespace QuickMedia {
}
VideoPlayer::Error VideoPlayer::update() {
+ int max_retries_find_window = 10;
+ if(use_tor)
+ max_retries_find_window = 30;
+
if(ipc_socket == -1)
return Error::INIT_FAILED;
if(connect_tries == MAX_RETRIES_CONNECT)
return Error::FAIL_TO_CONNECT_TIMEOUT;
- if(find_window_tries == MAX_RETRIES_FIND_WINDOW)
+ if(find_window_tries == max_retries_find_window)
return Error::FAIL_TO_FIND_WINDOW;
if(!connected_to_ipc && retry_timer.getElapsedTime().asMilliseconds() >= RETRY_TIME_MS) {
@@ -153,8 +160,8 @@ namespace QuickMedia {
size_t num_children = child_windows.size();
if(num_children == 0) {
++find_window_tries;
- if(find_window_tries == MAX_RETRIES_FIND_WINDOW) {
- fprintf(stderr, "Failed to find mpv window after %d seconds\n", (RETRY_TIME_MS * MAX_RETRIES_FIND_WINDOW)/1000);
+ if(find_window_tries == max_retries_find_window) {
+ fprintf(stderr, "Failed to find mpv window after %d seconds\n", (RETRY_TIME_MS * max_retries_find_window)/1000);
return Error::FAIL_TO_FIND_WINDOW_TIMEOUT;
}
} else if(num_children == 1) {
diff --git a/src/plugins/Plugin.cpp b/src/plugins/Plugin.cpp
index c56ff67..d1490d5 100644
--- a/src/plugins/Plugin.cpp
+++ b/src/plugins/Plugin.cpp
@@ -28,22 +28,6 @@ namespace QuickMedia {
return {};
}
- DownloadResult download_to_string(const std::string &url, std::string &result, const std::vector<CommandArg> &additional_args) {
- sf::Clock timer;
- std::vector<const char*> args = { "curl", "-f", "-H", "Accept-Language: en-US,en;q=0.5", "--compressed", "-s", "-L" };
- for(const CommandArg &arg : additional_args) {
- args.push_back(arg.option.c_str());
- args.push_back(arg.value.c_str());
- }
- args.push_back("--");
- args.push_back(url.c_str());
- args.push_back(nullptr);
- if(exec_program(args.data(), accumulate_string, &result) != 0)
- return DownloadResult::NET_ERR;
- fprintf(stderr, "Download duration for %s: %d ms\n", url.c_str(), timer.getElapsedTime().asMilliseconds());
- return DownloadResult::OK;
- }
-
static bool is_whitespace(char c) {
return c == ' ' || c == '\n' || c == '\t' || c == '\v';
}
@@ -112,4 +96,23 @@ namespace QuickMedia {
return result.str();
}
+
+ DownloadResult Plugin::download_to_string(const std::string &url, std::string &result, const std::vector<CommandArg> &additional_args) {
+ sf::Clock timer;
+ std::vector<const char*> args;
+ if(use_tor)
+ args.push_back("torsocks");
+ args.insert(args.end(), { "curl", "-f", "-H", "Accept-Language: en-US,en;q=0.5", "--compressed", "-s", "-L" });
+ for(const CommandArg &arg : additional_args) {
+ args.push_back(arg.option.c_str());
+ args.push_back(arg.value.c_str());
+ }
+ args.push_back("--");
+ args.push_back(url.c_str());
+ args.push_back(nullptr);
+ if(exec_program(args.data(), accumulate_string, &result) != 0)
+ return DownloadResult::NET_ERR;
+ fprintf(stderr, "Download duration for %s: %d ms\n", url.c_str(), timer.getElapsedTime().asMilliseconds());
+ return DownloadResult::OK;
+ }
} \ No newline at end of file