134 lines
4.8 KiB
C++
134 lines
4.8 KiB
C++
/**
|
|
This file is a part of r0nk, atlas_moon, and rexy's matrix client
|
|
Copyright (C) 2019 rexy712
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "matrix/client_base.hpp"
|
|
#include "raii/rjp_ptr.hpp"
|
|
#include "raii/static_string.hpp"
|
|
#include <cstdlib> //size_t
|
|
#include <algorithm> //min, max
|
|
|
|
namespace matrix::internal{
|
|
|
|
client_base::client_base(void):
|
|
m_curl()
|
|
{
|
|
_set_curl_defaults(""_ss);
|
|
}
|
|
void client_base::_set_curl_useragent(const raii::string_base& useragent){
|
|
m_curl.setuseragent(useragent);
|
|
}
|
|
size_t client_base::_post_reply_curl_callback(char* ptr, size_t size, size_t nmemb, void* userdata){
|
|
raii::string* data = reinterpret_cast<raii::string*>(userdata);
|
|
(*data) += ptr;
|
|
return size*nmemb;
|
|
}
|
|
raii::string client_base::_get_curl(const raii::string_base& url)const{
|
|
raii::string reply;
|
|
m_curl.getreq();
|
|
m_curl.seturl(url);
|
|
m_curl.setheader(raii::curl_llist{});
|
|
m_curl.setopt(CURLOPT_WRITEFUNCTION, _post_reply_curl_callback);
|
|
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
|
CURLcode res = m_curl.perform();
|
|
if(res != CURLE_OK)
|
|
return {};
|
|
return reply;
|
|
}
|
|
raii::string client_base::_post_curl(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const{
|
|
raii::string reply;
|
|
m_curl.postreq();
|
|
m_curl.setopt(CURLOPT_POSTFIELDS, postdata.get());
|
|
m_curl.setopt(CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)postdata.length());
|
|
m_curl.seturl(url);
|
|
m_curl.setheader(header);
|
|
m_curl.setopt(CURLOPT_WRITEFUNCTION, _post_reply_curl_callback);
|
|
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
|
CURLcode res = m_curl.perform();
|
|
if(res != CURLE_OK)
|
|
return {};
|
|
return reply;
|
|
}
|
|
struct put_data{
|
|
const char* data;
|
|
size_t len;
|
|
};
|
|
static size_t _put_read_curl_callback(char* buffer, size_t size, size_t nmemb, void* userdata){
|
|
put_data* src = reinterpret_cast<put_data*>(userdata);
|
|
size_t curl_size = size*nmemb;
|
|
size_t to_copy = std::min(curl_size, src->len);
|
|
memcpy(buffer, src->data, to_copy);
|
|
src->len -= to_copy;
|
|
src->data += to_copy;
|
|
return to_copy;
|
|
}
|
|
raii::string client_base::_put_curl(const raii::string_base& putdata, const raii::string_base& url, const raii::curl_llist& header)const{
|
|
raii::string reply;
|
|
put_data data{putdata.get(), putdata.length()};
|
|
m_curl.putreq();
|
|
m_curl.setopt(CURLOPT_POSTFIELDS, putdata.get());
|
|
m_curl.setopt(CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)putdata.length());
|
|
m_curl.seturl(url);
|
|
m_curl.setheader(header);
|
|
m_curl.setopt(CURLOPT_WRITEFUNCTION, _post_reply_curl_callback);
|
|
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
|
m_curl.setopt(CURLOPT_READFUNCTION, _put_read_curl_callback);
|
|
m_curl.setopt(CURLOPT_READDATA, &data);
|
|
m_curl.setopt(CURLOPT_INFILESIZE, (curl_off_t)data.len);
|
|
CURLcode res = m_curl.perform();
|
|
m_curl.setopt(CURLOPT_READDATA, NULL);
|
|
m_curl.setopt(CURLOPT_READFUNCTION, NULL);
|
|
if(res != CURLE_OK)
|
|
return {};
|
|
return reply;
|
|
}
|
|
raii::rjp_string client_base::_post_and_find(const raii::string_base& data, const raii::string_base& url,
|
|
const raii::curl_llist& header, const raii::string_base& target)const
|
|
{
|
|
raii::string reply = _post_curl(data, url, header);
|
|
if(!reply)
|
|
return {};
|
|
return _curl_reply_search(reply, target);
|
|
}
|
|
raii::rjp_string client_base::_get_and_find(const raii::string_base& url, const raii::string_base& target)const{
|
|
raii::string reply = _get_curl(url);
|
|
if(!reply)
|
|
return {};
|
|
return _curl_reply_search(reply, target);
|
|
}
|
|
raii::rjp_string client_base::_curl_reply_search(const raii::string_base& reply, const raii::string_base& target)const{
|
|
raii::rjp_ptr root(rjp_parse(reply));
|
|
if(!root)
|
|
return {};
|
|
RJP_search_res res = rjp_search_member(root.get(), target.get(), 0);
|
|
if(rjp_value_type(res.value) != json_string)
|
|
return {};
|
|
return raii::rjp_string(res.value);
|
|
}
|
|
void client_base::_set_curl_defaults(const raii::string_base& useragent)const{
|
|
m_curl.setopt(CURLOPT_BUFFERSIZE, 102400L);
|
|
m_curl.setopt(CURLOPT_NOPROGRESS, 1L);
|
|
m_curl.setuseragent(useragent);
|
|
m_curl.setopt(CURLOPT_MAXREDIRS, 50L);
|
|
m_curl.setopt(CURLOPT_FOLLOWLOCATION, 1L);
|
|
m_curl.forcessl(CURL_SSLVERSION_TLSv1_2);
|
|
m_curl.setopt(CURLOPT_TCP_KEEPALIVE, 1L);
|
|
m_curl.setopt(CURLOPT_FAILONERROR, 1L);
|
|
}
|
|
|
|
}
|