Files
ps4-ezremote-client/source/web/request.cpp
T
2023-02-15 01:30:36 -08:00

205 lines
5.9 KiB
C++

/*#***************************************************************************
# __ __ _____ _____
# Project | | | | | \ / ___|
# | |__| | | |\ \ / /
# | | | | ) ) ( (
# | /\ | | |/ / \ \___
# \_/ \_/ |_____/ \_____|
#
# Copyright (C) 2018, The WDC Project, <rusdevops@gmail.com>, 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 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<char *>(cert_path.c_str()));
this->set(CURLOPT_SSLKEY, const_cast<char *>(key_path.c_str()));
}
this->set(CURLOPT_URL, const_cast<char *>(hostname.c_str()));
if (!username.empty())
{
this->set(CURLOPT_HTTPAUTH, static_cast<int>(CURLAUTH_BASIC));
auto token = username + ":" + password;
this->set(CURLOPT_USERPWD, const_cast<char *>(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");
this->set(CURLOPT_CONNECTTIMEOUT, 15L);
if (!this->proxy_enabled())
return;
this->set(CURLOPT_PROXY, const_cast<char *>(proxy_hostname.c_str()));
this->set(CURLOPT_PROXYAUTH, static_cast<int>(CURLAUTH_BASIC));
if (proxy_username.empty())
return;
if (proxy_password.empty())
{
this->set(CURLOPT_PROXYUSERNAME, const_cast<char *>(proxy_username.c_str()));
}
else
{
if (!username.empty() && !password.empty())
{
auto token = proxy_username + ":" + proxy_password;
this->set(CURLOPT_PROXYUSERPWD, const_cast<char *>(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;
}
} // namespace Web