Add ability to download files from the homeserver
This commit is contained in:
parent
fc1885f9fe
commit
fa75e8f0d7
@ -131,7 +131,24 @@ namespace matrix{
|
||||
|
||||
bool create_thumbnail(uploaded_image& info)const;
|
||||
bool create_thumbnail(uploaded_video& video)const;
|
||||
|
||||
raii::binary download_file(const raii::string_base& url);
|
||||
template<class DLHandler>
|
||||
bool download_file(const raii::string_base& url, DLHandler&& dl){
|
||||
_get_curl_setup(m_ses->urls.file_download(m_ses->homeserver, url));
|
||||
m_curl.setwritefun(_download_dispatch<DLHandler>);
|
||||
m_curl.setwritedata(&dl);
|
||||
if(!_perform_curl())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
template<class DLHandler>
|
||||
void download_file(const raii::string_base& server, const raii::string_base& media_id, DLHandler&& dl);
|
||||
private:
|
||||
template<class DLHandler>
|
||||
static size_t _download_dispatch(char* ptr, size_t size, size_t nmemb, void* userdata){
|
||||
return reinterpret_cast<DLHandler*>(userdata)(ptr, size, nmemb, nullptr);
|
||||
}
|
||||
uploaded_file _upload_file(const file_details& file, const raii::curl_llist& header)const;
|
||||
};
|
||||
}
|
||||
|
||||
@ -52,6 +52,7 @@ namespace matrix{
|
||||
const raii::string& whoami(void)const;
|
||||
const raii::string& displayname(void)const;
|
||||
const raii::string& profile_picture(void)const;
|
||||
raii::string file_download(const raii::string_base& homeserver, const raii::string_base& mediaid);
|
||||
raii::string file_thumbnail(const raii::string_base& homeserver, const raii::string_base& fileurl, int width, int height, const raii::string_base& method)const;
|
||||
raii::string logout(const raii::string_base& homeserver, const raii::string_base& access_token)const;
|
||||
raii::string sync(const raii::string_base& homeserver, const raii::string_base& access_token, const raii::string_base& next_batch, const raii::string_base& timeout)const;
|
||||
@ -67,6 +68,7 @@ namespace matrix{
|
||||
|
||||
private:
|
||||
void _initial_populate(const raii::string_base& homeserver);
|
||||
static raii::string get_server_media_string(const raii::string_base& url);
|
||||
static constexpr const char* s_proto = "https://";
|
||||
static constexpr const char* s_revision = "r0";
|
||||
};
|
||||
|
||||
@ -66,13 +66,29 @@ namespace matrix{
|
||||
long http_status(void)const;
|
||||
|
||||
protected:
|
||||
struct put_data{
|
||||
const char* data;
|
||||
size_t len;
|
||||
};
|
||||
static size_t _reply_curl_callback(char* ptr, size_t size, size_t nmemb, void* userdata);
|
||||
static size_t _binary_reply_curl_callback(char* ptr, size_t size, size_t nmemb, void* userdata);
|
||||
void _get_curl_setup(const raii::string_base& url)const;
|
||||
void _post_curl_setup(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const;
|
||||
static size_t _put_read_curl_callback(char* buffer, size_t size, size_t nmemb, void* userdata);
|
||||
void _put_curl_setup(put_data& data, const raii::string_base& url, const raii::curl_llist& header)const;
|
||||
|
||||
protected:
|
||||
using binary_callback_fun = size_t(*)(char*, size_t, size_t, void*);
|
||||
using reply_callback_fun = size_t(*)(char*, size_t, size_t, void*);
|
||||
|
||||
void _set_curl_useragent(const raii::string_base& useragent);
|
||||
raii::string _get_curl(const raii::string_base& url)const;
|
||||
raii::binary _get_curl_binary(const raii::string_base& url)const;
|
||||
raii::string _post_curl(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const;
|
||||
raii::binary _post_curl_binary(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const;
|
||||
raii::string _put_curl(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const;
|
||||
raii::binary _put_curl_binary(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const;
|
||||
bool _perform_curl(void)const;
|
||||
raii::string _get_curl(const raii::string_base& url, reply_callback_fun fun = _reply_curl_callback)const;
|
||||
raii::binary _get_curl_binary(const raii::string_base& url, binary_callback_fun fun = _binary_reply_curl_callback)const;
|
||||
raii::string _post_curl(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header, reply_callback_fun = _reply_curl_callback)const;
|
||||
raii::binary _post_curl_binary(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header, binary_callback_fun = _binary_reply_curl_callback)const;
|
||||
raii::string _put_curl(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header, reply_callback_fun = _reply_curl_callback)const;
|
||||
raii::binary _put_curl_binary(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header, binary_callback_fun = _binary_reply_curl_callback)const;
|
||||
raii::rjp_string _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::rjp_string _get_and_find(const raii::string_base& url, const raii::string_base& search)const;
|
||||
raii::rjp_string _curl_reply_search(const raii::string_base& reply, const raii::string_base& search)const;
|
||||
|
||||
@ -39,7 +39,7 @@ namespace raii{
|
||||
protected:
|
||||
constexpr binary_base(void) = default;
|
||||
constexpr binary_base(char* data, size_t size):
|
||||
m_data(data), m_size(size){}
|
||||
m_data(data), m_cap(size){}
|
||||
template<class Allocator>
|
||||
binary_base(const binary_base& b):
|
||||
m_data(Allocator::copy(b.m_data, b.m_cap)),
|
||||
|
||||
@ -31,6 +31,10 @@ namespace raii{
|
||||
{
|
||||
private:
|
||||
CURL* m_curl;
|
||||
public:
|
||||
using write_function = size_t(*)(char*,size_t,size_t,void*);
|
||||
using read_function = size_t(*)(char*,size_t,size_t,void*);
|
||||
|
||||
public:
|
||||
curler(void);
|
||||
curler(const curler& c);
|
||||
@ -58,6 +62,10 @@ namespace raii{
|
||||
curler& setpostdata(const char* s, curl_off_t len = -1);
|
||||
curler& setpostdata(const string_base& s);
|
||||
curler& forcessl(long version = CURL_SSLVERSION_DEFAULT);
|
||||
curler& setwritefun(write_function);
|
||||
curler& setwritedata(void*);
|
||||
curler& setreadfun(read_function);
|
||||
curler& setreaddata(void*);
|
||||
void reset(void);
|
||||
decltype(curl_easy_perform(m_curl)) perform(void);
|
||||
|
||||
|
||||
@ -156,6 +156,9 @@ namespace matrix{
|
||||
bool client::create_thumbnail(uploaded_video& info)const{
|
||||
return create_thumbnail(static_cast<uploaded_image&>(info));
|
||||
}
|
||||
raii::binary client::download_file(const raii::string_base& url){
|
||||
return _get_curl_binary(m_ses->urls.file_download(m_ses->homeserver, url));
|
||||
}
|
||||
|
||||
/*******************************
|
||||
Internal functions
|
||||
@ -175,13 +178,6 @@ namespace matrix{
|
||||
return to_copy;
|
||||
}
|
||||
|
||||
static size_t _post_reply_curl_callback(char* ptr, size_t size, size_t nmemb, void* userdata){
|
||||
raii::string* data = reinterpret_cast<raii::string*>(userdata);
|
||||
size_t oldlen = data->length();
|
||||
data->resize(data->length() + (size*nmemb));
|
||||
memcpy(data->get()+oldlen, ptr, size*nmemb);
|
||||
return size*nmemb;
|
||||
}
|
||||
uploaded_file client::_upload_file(const file_details& file, const raii::curl_llist& header)const{
|
||||
raii::string fileurl;
|
||||
uploaded_file retval = {};
|
||||
@ -194,7 +190,7 @@ namespace matrix{
|
||||
m_curl.setopt(CURLOPT_INFILESIZE_LARGE, (curl_off_t)upload_data.len);
|
||||
m_curl.seturl(m_ses->urls.file_upload());
|
||||
m_curl.setheader(header);
|
||||
m_curl.setopt(CURLOPT_WRITEFUNCTION, _post_reply_curl_callback);
|
||||
m_curl.setopt(CURLOPT_WRITEFUNCTION, _reply_curl_callback);
|
||||
m_curl.setopt(CURLOPT_WRITEDATA, &fileurl);
|
||||
CURLcode cres = m_curl.perform();
|
||||
m_curl.setopt(CURLOPT_READDATA, NULL);
|
||||
|
||||
@ -78,11 +78,14 @@ namespace matrix{
|
||||
const raii::string& client_url_list::profile_picture(void)const{
|
||||
return m_profile_picture;
|
||||
}
|
||||
raii::string client_url_list::file_download(const raii::string_base& homeserver, const raii::string_base& fileurl){
|
||||
raii::string media = get_server_media_string(fileurl);
|
||||
if(!media) return {};
|
||||
return raii::string(s_proto + homeserver + "/_matrix/media/r0/download/" + media);
|
||||
}
|
||||
raii::string client_url_list::file_thumbnail(const raii::string_base& homeserver, const raii::string_base& fileurl, int width, int height, const raii::string_base& method)const{
|
||||
if(strncmp(fileurl.get(), "mxc://", 6))
|
||||
return {};
|
||||
|
||||
raii::string media(fileurl.get()+6, fileurl.length()-6);
|
||||
raii::string media = get_server_media_string(fileurl);
|
||||
if(!media) return {};
|
||||
return raii::string(s_proto + homeserver + "/_matrix/media/r0/thumbnail/" + media + "?width=" + raii::itostr(width) + "&height=" + raii::itostr(height) + "&method=" + method);
|
||||
}
|
||||
raii::string client_url_list::logout(const raii::string_base& homeserver, const raii::string_base& access_token)const{
|
||||
@ -102,5 +105,11 @@ namespace matrix{
|
||||
void client_url_list::_initial_populate(const raii::string_base& homeserver){
|
||||
m_alias_lookup = s_proto + homeserver + "/_matrix/client/r0/directory/room/";
|
||||
}
|
||||
raii::string client_url_list::get_server_media_string(const raii::string_base& url){
|
||||
if(!url || strncmp(url.get(), "mxc://", 6))
|
||||
return {};
|
||||
|
||||
return raii::string(url.get()+6, url.length()-6);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -44,75 +44,29 @@ namespace matrix{
|
||||
long connection::http_status(void)const{
|
||||
return m_curl.last_status();
|
||||
}
|
||||
void connection::_set_curl_useragent(const raii::string_base& useragent){
|
||||
m_curl.setuseragent(useragent);
|
||||
}
|
||||
static size_t _post_reply_curl_callback(char* ptr, size_t size, size_t nmemb, void* userdata){
|
||||
|
||||
size_t connection::_reply_curl_callback(char* ptr, size_t size, size_t nmemb, void* userdata){
|
||||
raii::string* data = reinterpret_cast<raii::string*>(userdata);
|
||||
data->append(ptr, size*nmemb);
|
||||
return size*nmemb;
|
||||
}
|
||||
static size_t _binary_reply_curl_callback(char* ptr, size_t size, size_t nmemb, void* userdata){
|
||||
size_t connection::_binary_reply_curl_callback(char* ptr, size_t size, size_t nmemb, void* userdata){
|
||||
raii::binary* data = reinterpret_cast<raii::binary*>(userdata);
|
||||
data->append(ptr, size*nmemb);
|
||||
return size*nmemb;
|
||||
}
|
||||
static void _get_curl_setup(const raii::string_base& url, raii::curler& curl){
|
||||
curl.getreq();
|
||||
curl.seturl(url);
|
||||
curl.setheader(raii::curl_llist{});
|
||||
void connection::_get_curl_setup(const raii::string_base& url)const{
|
||||
m_curl.getreq();
|
||||
m_curl.seturl(url);
|
||||
m_curl.setheader(raii::curl_llist{});
|
||||
}
|
||||
raii::string connection::_get_curl(const raii::string_base& url)const{
|
||||
raii::string reply;
|
||||
_get_curl_setup(url, m_curl);
|
||||
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;
|
||||
void connection::_post_curl_setup(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const{
|
||||
m_curl.postreq();
|
||||
m_curl.setpostdata(postdata.get(), postdata.length());
|
||||
m_curl.seturl(url);
|
||||
m_curl.setheader(header);
|
||||
}
|
||||
raii::binary connection::_get_curl_binary(const raii::string_base& url)const{
|
||||
raii::binary reply;
|
||||
_get_curl_setup(url, m_curl);
|
||||
m_curl.setopt(CURLOPT_WRITEFUNCTION, _binary_reply_curl_callback);
|
||||
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
||||
CURLcode res = m_curl.perform();
|
||||
if(res != CURLE_OK)
|
||||
return {};
|
||||
return reply;
|
||||
}
|
||||
static void _post_curl_setup(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header, raii::curler& curl){
|
||||
curl.postreq();
|
||||
curl.setpostdata(postdata.get(), postdata.length());
|
||||
curl.seturl(url);
|
||||
curl.setheader(header);
|
||||
}
|
||||
raii::string connection::_post_curl(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const{
|
||||
raii::string reply;
|
||||
_post_curl_setup(postdata, url, header, m_curl);
|
||||
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::binary connection::_post_curl_binary(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header)const{
|
||||
raii::binary reply;
|
||||
_post_curl_setup(postdata, url, header, m_curl);
|
||||
m_curl.setopt(CURLOPT_WRITEFUNCTION, _binary_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){
|
||||
size_t connection::_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);
|
||||
@ -121,39 +75,83 @@ namespace matrix{
|
||||
src->data += to_copy;
|
||||
return to_copy;
|
||||
}
|
||||
static void _put_curl_setup(put_data& data, const raii::string_base& url, const raii::curl_llist& header, raii::curler& curl){
|
||||
curl.putreq();
|
||||
curl.setopt(CURLOPT_POSTFIELDS, data.data);
|
||||
curl.setopt(CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)data.len);
|
||||
curl.seturl(url);
|
||||
curl.setheader(header);
|
||||
curl.setopt(CURLOPT_READFUNCTION, _put_read_curl_callback);
|
||||
curl.setopt(CURLOPT_READDATA, &data);
|
||||
curl.setopt(CURLOPT_INFILESIZE, (curl_off_t)data.len);
|
||||
void connection::_put_curl_setup(put_data& data, const raii::string_base& url, const raii::curl_llist& header)const{
|
||||
m_curl.putreq();
|
||||
m_curl.setopt(CURLOPT_POSTFIELDS, data.data);
|
||||
m_curl.setopt(CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)data.len);
|
||||
m_curl.seturl(url);
|
||||
m_curl.setheader(header);
|
||||
m_curl.setreadfun(_put_read_curl_callback);
|
||||
m_curl.setreaddata(&data);
|
||||
m_curl.setopt(CURLOPT_INFILESIZE, (curl_off_t)data.len);
|
||||
}
|
||||
raii::string connection::_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.setopt(CURLOPT_WRITEFUNCTION, _post_reply_curl_callback);
|
||||
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
||||
_put_curl_setup(data, url, header, m_curl);
|
||||
|
||||
void connection::_set_curl_useragent(const raii::string_base& useragent){
|
||||
m_curl.setuseragent(useragent);
|
||||
}
|
||||
bool connection::_perform_curl(void)const{
|
||||
CURLcode res = m_curl.perform();
|
||||
m_curl.setopt(CURLOPT_READDATA, NULL);
|
||||
m_curl.setopt(CURLOPT_READFUNCTION, NULL);
|
||||
if(res != CURLE_OK)
|
||||
return (res == CURLE_OK);
|
||||
}
|
||||
raii::string connection::_get_curl(const raii::string_base& url, reply_callback_fun fun)const{
|
||||
raii::string reply;
|
||||
_get_curl_setup(url);
|
||||
m_curl.setwritefun(fun);
|
||||
m_curl.setwritedata(&reply);
|
||||
if(!_perform_curl())
|
||||
return {};
|
||||
return reply;
|
||||
}
|
||||
raii::binary connection::_put_curl_binary(const raii::string_base& putdata, const raii::string_base& url, const raii::curl_llist& header)const{
|
||||
raii::binary connection::_get_curl_binary(const raii::string_base& url, binary_callback_fun fun)const{
|
||||
raii::binary reply;
|
||||
_get_curl_setup(url);
|
||||
m_curl.setwritefun(fun);
|
||||
m_curl.setwritedata(&reply);
|
||||
if(!_perform_curl())
|
||||
return {};
|
||||
return reply;
|
||||
}
|
||||
raii::string connection::_post_curl(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header, reply_callback_fun fun)const{
|
||||
raii::string reply;
|
||||
_post_curl_setup(postdata, url, header);
|
||||
m_curl.setwritefun(fun);
|
||||
m_curl.setwritedata(&reply);
|
||||
if(!_perform_curl())
|
||||
return {};
|
||||
return reply;
|
||||
}
|
||||
raii::binary connection::_post_curl_binary(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header, binary_callback_fun fun)const{
|
||||
raii::binary reply;
|
||||
_post_curl_setup(postdata, url, header);
|
||||
m_curl.setwritefun(fun);
|
||||
m_curl.setwritedata(&reply);
|
||||
if(!_perform_curl())
|
||||
return {};
|
||||
return reply;
|
||||
}
|
||||
raii::string connection::_put_curl(const raii::string_base& putdata, const raii::string_base& url, const raii::curl_llist& header, reply_callback_fun fun)const{
|
||||
raii::string reply;
|
||||
put_data data{putdata.get(), putdata.length()};
|
||||
m_curl.setwritefun(fun);
|
||||
m_curl.setwritedata(&reply);
|
||||
_put_curl_setup(data, url, header);
|
||||
bool succ = _perform_curl();
|
||||
m_curl.setreaddata(NULL);
|
||||
m_curl.setreadfun(NULL);
|
||||
if(!succ)
|
||||
return {};
|
||||
return reply;
|
||||
}
|
||||
raii::binary connection::_put_curl_binary(const raii::string_base& putdata, const raii::string_base& url, const raii::curl_llist& header, binary_callback_fun fun)const{
|
||||
raii::binary reply;
|
||||
put_data data{putdata.get(), putdata.length()};
|
||||
m_curl.setopt(CURLOPT_WRITEFUNCTION, _binary_reply_curl_callback);
|
||||
m_curl.setopt(CURLOPT_WRITEDATA, &reply);
|
||||
_put_curl_setup(data, url, header, m_curl);
|
||||
CURLcode res = m_curl.perform();
|
||||
m_curl.setopt(CURLOPT_READDATA, NULL);
|
||||
m_curl.setopt(CURLOPT_READFUNCTION, NULL);
|
||||
if(res != CURLE_OK)
|
||||
m_curl.setwritefun(fun);
|
||||
m_curl.setwritedata(&reply);
|
||||
_put_curl_setup(data, url, header);
|
||||
bool succ = _perform_curl();
|
||||
m_curl.setreaddata(NULL);
|
||||
m_curl.setreadfun(NULL);
|
||||
if(!succ)
|
||||
return {};
|
||||
return reply;
|
||||
}
|
||||
|
||||
@ -92,6 +92,18 @@ namespace raii{
|
||||
setopt(CURLOPT_SSLVERSION, version);
|
||||
return *this;
|
||||
}
|
||||
curler& curler::setwritefun(write_function w){
|
||||
return setopt(CURLOPT_WRITEFUNCTION, w);
|
||||
}
|
||||
curler& curler::setwritedata(void* data){
|
||||
return setopt(CURLOPT_WRITEDATA, data);
|
||||
}
|
||||
curler& curler::setreadfun(read_function r){
|
||||
return setopt(CURLOPT_READFUNCTION, r);
|
||||
}
|
||||
curler& curler::setreaddata(void* data){
|
||||
return setopt(CURLOPT_READDATA, data);
|
||||
}
|
||||
|
||||
void curler::reset(void){
|
||||
curl_easy_reset(m_curl);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user