/*#*************************************************************************** # __ __ _____ _____ # Project | | | | | \ / ___| # | |__| | | |\ \ / / # | | | | ) ) ( ( # | /\ | | |/ / \ \___ # \_/ \_/ |_____/ \_____| # # Copyright (C) 2018, The WDC Project, , et al. # # This software is licensed as described in the file LICENSE, which # you should have received as part of this distribution. # # You may opt to use, copy, modify, merge, publish, distribute and/or sell # copies of the Software, and permit persons to whom the Software is # furnished to do so, under the terms of the LICENSE file. # # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY # KIND, either express or implied. # ############################################################################*/ #include "request.hpp" #include "fsinfo.hpp" #include "util.h" namespace Web { static int sockopt_callback(void *clientp, curl_socket_t curlfd, curlsocktype purpose) { int const size = 1048576; if (setsockopt(curlfd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) == -1) { return CURL_SOCKOPT_ERROR; } if (setsockopt(curlfd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) == -1) { return CURL_SOCKOPT_ERROR; } return CURL_SOCKOPT_OK; } auto inline get(const dict_t &options, const std::string &&name) -> std::string { auto it = options.find(name); if (it == options.end()) { return std::string{""}; } else { return it->second; } } Request::Request(dict_t &&options_) : options(options_) { auto hostname = get(options, "hostname"); auto username = get(options, "username"); auto password = get(options, "password"); auto timeout = get(options, "password"); auto proxy_hostname = get(options, "proxy_hostname"); auto proxy_username = get(options, "proxy_username"); auto proxy_password = get(options, "proxy_password"); auto cert_path = get(options, "cert_path"); auto key_path = get(options, "key_path"); this->handle = curl_easy_init(); this->set(CURLOPT_SSL_VERIFYHOST, 0); this->set(CURLOPT_SSL_VERIFYPEER, 0); #ifdef _DEBUG this->set(CURLOPT_VERBOSE, 1); #else this->set(CURLOPT_VERBOSE, 0); #endif if (this->cert_required()) { this->set(CURLOPT_SSLCERTTYPE, "PEM"); this->set(CURLOPT_SSLKEYTYPE, "PEM"); this->set(CURLOPT_SSLCERT, const_cast(cert_path.c_str())); this->set(CURLOPT_SSLKEY, const_cast(key_path.c_str())); } this->set(CURLOPT_URL, const_cast(hostname.c_str())); if (!username.empty()) { this->set(CURLOPT_HTTPAUTH, static_cast(CURLAUTH_BASIC)); auto token = username + ":" + password; this->set(CURLOPT_USERPWD, const_cast(token.c_str())); } this->set(CURLOPT_SOCKOPTFUNCTION, sockopt_callback); this->set(CURLOPT_FOLLOWLOCATION, 1); this->set(CURLOPT_COOKIEJAR, "/data/ps4-webdav-client/cookies.txt"); this->set(CURLOPT_COOKIEFILE, "/data/ps4-webdav-client/cookies.txt"); if (timeout.empty()) { this->set(CURLOPT_CONNECTTIMEOUT, 15L); } else { this->set(CURLOPT_CONNECTTIMEOUT, atoi(timeout.c_str())); } if (!this->proxy_enabled()) return; this->set(CURLOPT_PROXY, const_cast(proxy_hostname.c_str())); this->set(CURLOPT_PROXYAUTH, static_cast(CURLAUTH_BASIC)); if (proxy_username.empty()) return; if (proxy_password.empty()) { this->set(CURLOPT_PROXYUSERNAME, const_cast(proxy_username.c_str())); } else { if (!username.empty() && !password.empty()) { auto token = proxy_username + ":" + proxy_password; this->set(CURLOPT_PROXYUSERPWD, const_cast(token.c_str())); } } } Request::~Request() noexcept { if (this->handle != nullptr) curl_easy_cleanup(this->handle); } auto Request::swap(Request &other) noexcept -> void { using std::swap; swap(handle, other.handle); } Request::Request(Request &&other) noexcept : handle{ other.handle} { other.handle = nullptr; } auto Request::operator=(Request &&other) noexcept -> Request & { if (this != &other) { Request(std::move(other)).swap(*this); } return *this; } bool Request::perform() noexcept { if (this->handle == nullptr) return false; this->res = curl_easy_perform(this->handle); auto is_performed = this->res == CURLE_OK; if (!is_performed) return false; this->http_code = 0; curl_easy_getinfo(this->handle, CURLINFO_RESPONSE_CODE, &this->http_code); if (this->http_code < 200 || this->http_code > 299) return false; return true; } bool Request::proxy_enabled() const noexcept { auto proxy_hostname = get(options, "proxy_hostname"); auto proxy_username = get(options, "proxy_username"); auto proxy_password = get(options, "proxy_password"); bool proxy_hostname_presented = !proxy_hostname.empty(); if (!proxy_hostname_presented) return false; bool proxy_username_presented = !proxy_username.empty(); bool proxy_password_presented = !proxy_password.empty(); if (proxy_password_presented && !proxy_username_presented) return false; return true; } bool Request::cert_required() const noexcept { const auto cert_path = get(options, "cert_path"); const auto key_path = get(options, "key_path"); if (cert_path.empty()) return false; bool cert_is_existed = FileInfo::exists(cert_path); if (!cert_is_existed) return false; if (key_path.empty()) return false; return FileInfo::exists(key_path); } long Request::status_code() const noexcept { return this->http_code; } int Request::result() const noexcept { return this->res; } class Environment { public: Environment() { curl_global_init(CURL_GLOBAL_ALL); } ~Environment() { curl_global_cleanup(); } }; } // namespace Web static const Web::Environment env;