bool Client::create_directory(std::string remote_directory, bool recursive) noexcept { auto clientImpl = GetImpl(this); bool is_existed = this->check(remote_directory); if (is_existed) return true; bool resource_is_dir = true; Urn directory_urn(remote_directory, resource_is_dir); if (recursive) { auto remote_parent_directory = directory_urn.parent(); bool is_created = this->create_directory(remote_parent_directory, true); if (!is_created) return false; } Header header = { "Accept: */*", "Connection: Keep-Alive" }; auto target_urn = Urn(clientImpl->webdav_root, true) + remote_directory; target_urn = Urn(target_urn.path(), true); Request request(clientImpl->options()); auto url = clientImpl->webdav_hostname + target_urn.quote(request.handle); request.set(CURLOPT_CUSTOMREQUEST, "MKCOL"); request.set(CURLOPT_URL, url.c_str()); request.set(CURLOPT_HTTPHEADER, (struct curl_slist *)header.handle); return request.perform(); }
strings_t Client::list(std::string remote_directory) noexcept { auto clientImpl = GetImpl(this); bool is_existed = this->check(remote_directory); if (!is_existed) return strings_t(); bool is_directory = this->is_dir(remote_directory); if (!is_directory) return strings_t(); auto target_urn = Urn(clientImpl->webdav_root, true) + remote_directory; target_urn = Urn(target_urn.path(), true); Header header = { "Accept: */*", "Depth: 1" }; Data data = { 0, 0, 0 }; Request request(clientImpl->options()); auto url = clientImpl->webdav_hostname + target_urn.quote(request.handle); request.set(CURLOPT_CUSTOMREQUEST, "PROPFIND"); request.set(CURLOPT_URL, url.c_str()); request.set(CURLOPT_HTTPHEADER, (struct curl_slist *)header.handle); request.set(CURLOPT_HEADER, 0); request.set(CURLOPT_WRITEDATA, (size_t)&data); request.set(CURLOPT_WRITEFUNCTION, (size_t)Callback::Append::buffer); bool is_performed = request.perform(); if (!is_performed) return strings_t(); strings_t resources; pugi::xml_document document; document.load_buffer(data.buffer, (size_t)data.size); auto multistatus = document.select_single_node("d:multistatus").node(); auto responses = multistatus.select_nodes("d:response"); for(auto response : responses) { pugi::xml_node href = response.node().select_single_node("d:href").node(); std::string encode_file_name = href.first_child().value(); std::string resource_path = curl_unescape(encode_file_name.c_str(), (int) encode_file_name.length()); auto target_path = target_urn.path(); if (resource_path == target_path) continue; Urn resource_urn(resource_path); resources.push_back(resource_urn.name()); } return resources; }
Urn Urn::operator+(std::string resource_path) { bool is_directory = this->is_dir(); if (!is_directory) return *this; auto directory_path = this->path(); resource_path = directory_path + resource_path; return Urn(resource_path); }
bool Client::clean(std::string remote_resource) noexcept { auto clientImpl = GetImpl(this); bool is_existed = this->check(remote_resource); if (!is_existed) return true; auto root_urn = Urn(clientImpl->webdav_root, true); auto resource_urn = root_urn + remote_resource; Header header = { "Accept: */*", "Connection: Keep-Alive" }; Request request(clientImpl->options()); auto url = clientImpl->webdav_hostname + resource_urn.quote(request.handle); request.set(CURLOPT_CUSTOMREQUEST, "DELETE"); request.set(CURLOPT_URL, url.c_str()); request.set(CURLOPT_HTTPHEADER, (struct curl_slist *)header.handle); return request.perform(); }
bool ClientImpl::sync_download_to( std::string remote_file, std::ostream & stream, callback_t callback, progress_t progress ) noexcept { bool is_existed = this->check(remote_file); if (!is_existed) return false; auto root_urn = Urn(this->webdav_root, true); auto file_urn = root_urn + remote_file; Request request(this->options()); auto url = this->webdav_hostname + file_urn.quote(request.handle); request.set(CURLOPT_CUSTOMREQUEST, "GET"); request.set(CURLOPT_URL, url.c_str()); request.set(CURLOPT_HEADER, 0L); request.set(CURLOPT_WRITEDATA, (size_t)&stream); request.set(CURLOPT_WRITEFUNCTION, (size_t)Callback::Write::stream); if (progress != nullptr) { request.set(CURLOPT_XFERINFOFUNCTION, (size_t)progress.target<progress_funptr>()); request.set(CURLOPT_NOPROGRESS, 0L); } bool is_performed = request.perform(); if (callback != nullptr) callback(is_performed); if (!is_performed) return false; return true; }
bool Client::check(std::string remote_resource) noexcept { auto clientImpl = GetImpl(this); auto root_urn = Urn(clientImpl->webdav_root, true); auto resource_urn = root_urn + remote_resource; Header header = { "Accept: */*", "Depth: 1" }; Data data = { 0, 0, 0 }; Request request(clientImpl->options()); auto url = clientImpl->webdav_hostname + resource_urn.quote(request.handle); request.set(CURLOPT_CUSTOMREQUEST, "PROPFIND"); request.set(CURLOPT_URL, url.c_str()); request.set(CURLOPT_HTTPHEADER, (struct curl_slist *)header.handle); request.set(CURLOPT_WRITEDATA, (size_t)&data); request.set(CURLOPT_WRITEFUNCTION, (size_t)Callback::Append::buffer); return request.perform(); }
strings_t Client::list(std::string remote_directory) noexcept { auto clientImpl = GetImpl(this); bool is_existed = this->check(remote_directory); if (!is_existed) return strings_t(); bool is_directory = this->is_dir(remote_directory); if (!is_directory) return strings_t(); auto target_urn = Urn(clientImpl->ftps_root, true) + remote_directory; target_urn = Urn(target_urn.path(), true); Header header = { "Accept: */*", "Depth: 1" }; Data data = { 0, 0, 0 }; Request request(clientImpl->options()); auto url = clientImpl->ftps_hostname + target_urn.quote(request.handle); request.set(CURLOPT_CUSTOMREQUEST, "PROPFIND"); request.set(CURLOPT_URL, url.c_str()); request.set(CURLOPT_HTTPHEADER, (struct curl_slist *)header.handle); request.set(CURLOPT_HEADER, 0); request.set(CURLOPT_WRITEDATA, (size_t)&data); request.set(CURLOPT_WRITEFUNCTION, (size_t)Callback::Append::buffer); bool is_performed = request.perform(); if (!is_performed) return strings_t(); strings_t resources; // TODO return resources; }
bool ClientImpl::sync_upload( std::string remote_file, std::string local_file, callback_t callback, progress_t progress ) noexcept { bool is_existed = FileInfo::exists(local_file); if (!is_existed) return false; auto root_urn = Urn(this->webdav_root, true); auto file_urn = root_urn + remote_file; std::ifstream file_stream(local_file, std::ios::binary); auto size = FileInfo::size(local_file); Request request(this->options()); auto url = this->webdav_hostname + file_urn.quote(request.handle); Data response = { 0, 0, 0 }; request.set(CURLOPT_UPLOAD, 1L); request.set(CURLOPT_URL, url.c_str()); request.set(CURLOPT_READDATA, (size_t)&file_stream); request.set(CURLOPT_READFUNCTION, (size_t)Callback::Read::stream); request.set(CURLOPT_INFILESIZE_LARGE, (curl_off_t)size); request.set(CURLOPT_BUFFERSIZE, (long)Client::buffer_size); request.set(CURLOPT_WRITEDATA, (size_t)&response); request.set(CURLOPT_WRITEFUNCTION, (size_t)Callback::Append::buffer); if (progress != nullptr) { request.set(CURLOPT_XFERINFOFUNCTION, (size_t)progress.target<progress_funptr>()); request.set(CURLOPT_NOPROGRESS, 0L); } bool is_performed = request.perform(); if (callback != nullptr) callback(is_performed); return is_performed; }
bool ClientImpl::sync_download_to( std::string remote_file, char * & buffer_ptr, unsigned long long int & buffer_size, callback_t callback, progress_t progress ) noexcept { bool is_existed = this->check(remote_file); if (!is_existed) return false; auto root_urn = Urn(this->webdav_root, true); auto file_urn = root_urn + remote_file; Data data = { 0, 0, 0 }; Request request(this->options()); auto url = this->webdav_hostname + file_urn.quote(request.handle); request.set(CURLOPT_CUSTOMREQUEST, "GET"); request.set(CURLOPT_URL, url.c_str()); request.set(CURLOPT_HEADER, 0L); request.set(CURLOPT_WRITEDATA, (size_t)&data); request.set(CURLOPT_WRITEFUNCTION, (size_t)Callback::Append::buffer); if (progress != nullptr) { request.set(CURLOPT_XFERINFOFUNCTION, (size_t)progress.target<progress_funptr>()); request.set(CURLOPT_NOPROGRESS, 0L); } bool is_performed = request.perform(); if (callback != nullptr) callback(is_performed); if (!is_performed) return false; buffer_ptr = data.buffer; buffer_size = data.size; return true; }
bool ClientImpl::sync_upload_from( std::string remote_file, char * buffer, unsigned long long int buffer_size, callback_t callback, progress_t progress ) noexcept { auto root_urn = Urn(this->webdav_root, true); auto file_urn = root_urn + remote_file; Data data = { buffer, 0, buffer_size }; Request request(this->options()); auto url = this->webdav_hostname + file_urn.quote(request.handle); Data response = { 0, 0, 0 }; request.set(CURLOPT_UPLOAD, 1L); request.set(CURLOPT_URL, url.c_str()); request.set(CURLOPT_READDATA, (size_t)&data); request.set(CURLOPT_READFUNCTION, (size_t)Callback::Read::buffer); request.set(CURLOPT_INFILESIZE_LARGE, (curl_off_t)buffer_size); request.set(CURLOPT_BUFFERSIZE, (long)Client::buffer_size); request.set(CURLOPT_WRITEDATA, (size_t)&response); request.set(CURLOPT_WRITEFUNCTION, (size_t)Callback::Append::buffer); if (progress != nullptr) { request.set(CURLOPT_XFERINFOFUNCTION, (size_t)progress.target<progress_funptr>()); request.set(CURLOPT_NOPROGRESS, 0L); } bool is_performed = request.perform(); if (callback != nullptr) callback(is_performed); return is_performed; }
bool ClientImpl::sync_upload_from( std::string remote_file, std::istream & stream, callback_t callback, progress_t progress ) noexcept { auto root_urn = Urn(this->ftps_root, true); auto file_urn = root_urn + remote_file; Request request(this->options()); auto url = this->ftps_hostname + file_urn.quote(request.handle); stream.seekg(0, std::ios::end); size_t stream_size = stream.tellg(); stream.seekg(0, std::ios::beg); Data response = { 0, 0, 0 }; request.set(CURLOPT_UPLOAD, 1L); request.set(CURLOPT_URL, url.c_str()); request.set(CURLOPT_READDATA, (size_t)&stream); request.set(CURLOPT_READFUNCTION, (size_t)Callback::Read::stream); request.set(CURLOPT_INFILESIZE_LARGE, (curl_off_t)stream_size); request.set(CURLOPT_BUFFERSIZE, (long)Client::buffer_size); request.set(CURLOPT_WRITEDATA, (size_t)&response); request.set(CURLOPT_WRITEFUNCTION, (size_t)Callback::Append::buffer); if (progress != nullptr) { request.set(CURLOPT_XFERINFOFUNCTION, (size_t)progress.target<progress_funptr>()); request.set(CURLOPT_NOPROGRESS, 0L); } bool is_performed = request.perform(); if (callback != nullptr) callback(is_performed); return is_performed; }
dict_t Client::info(std::string remote_resource) noexcept { auto clientImpl = GetImpl(this); auto root_urn = Urn(clientImpl->webdav_root, true); auto target_urn = root_urn + remote_resource; Header header = { "Accept: */*", "Depth: 1" }; Data data = { 0, 0, 0 }; Request request(clientImpl->options()); auto url = clientImpl->webdav_hostname + target_urn.quote(request.handle); request.set(CURLOPT_CUSTOMREQUEST, "PROPFIND"); request.set(CURLOPT_URL, url.c_str()); request.set(CURLOPT_HTTPHEADER, (struct curl_slist *)header.handle); request.set(CURLOPT_WRITEDATA, (size_t)&data); request.set(CURLOPT_WRITEFUNCTION, (size_t)Callback::Append::buffer); bool is_performed = request.perform(); if (!is_performed) return dict_t(); pugi::xml_document document; document.load_buffer(data.buffer, (size_t)data.size); auto multistatus = document.select_single_node("d:multistatus").node(); auto responses = multistatus.select_nodes("d:response"); for (auto response : responses) { pugi::xml_node href = response.node().select_single_node("d:href").node(); std::string encode_file_name = href.first_child().value(); std::string resource_path = curl_unescape(encode_file_name.c_str(), (int)encode_file_name.length()); auto target_path = target_urn.path(); auto target_path_without_sep = std::string(target_path, 0, target_path.rfind("/")+1); auto resource_path_without_sep = std::string(resource_path, 0, resource_path.rfind("/")+1); if (resource_path_without_sep.compare(target_path_without_sep) == 0) { auto propstat = response.node().select_single_node("d:propstat").node(); auto prop = propstat.select_single_node("d:prop").node(); auto creation_date = prop.select_single_node("d:creationdate").node(); auto display_name = prop.select_single_node("d:displayname").node(); auto content_length = prop.select_single_node("d:getcontentlength").node(); auto modified_date = prop.select_single_node("d:getlastmodified").node(); auto resource_type = prop.select_single_node("d:resourcetype").node(); dict_t information = { {"created", creation_date.first_child().value()}, {"name", display_name.first_child().value()}, {"size", content_length.first_child().value()}, {"modified", modified_date.first_child().value()}, {"type", resource_type.first_child().name()} }; return information; } } return dict_t(); }