Webdav-client-cpp - C++ WebDAV Client provides easy and convenient to work with WebDAV-servers.

Overview

WebDAV Client

version version Build Status Build status Join the chat at https://gitter.im/CloudPolis/webdav-client-cpp

Package WebDAV Client provides easy and convenient to work with WebDAV-servers:

  • Yandex.Disk
  • Dropbox
  • Google Drive
  • Box
  • 4shared
  • ownCloud
  • ...

Install old version

# via brew or homebrew
$ brew install wdc

Build

Building WebDAV Client from sources:

$ git clone --recursive https://github.com/CloudPolis/webdav-client-cpp
$ cd webdav-client-cpp
$ ./tools/polly/bin/polly --install

Building documentation:

$ doxygen docs/doxygen.conf
$ open docs/html/index.html

Running tests

For run tests you need to set environment variables WEBDAV_HOSTNAME, WEBDAV_USERNAME and WEBDAV_PASSWORD (optional WEBDAV_ROOT).

$ export WEBDAV_HOSTNAME=<your_webdav_hostname>
$ export WEBDAV_USERNAME=<your_webdav_username>
$ export WEBDAV_PASSWORD=<your_webdav_password>
$ ./tools/polly/bin/polly --test --reconfig --fwd BUILD_TESTS=yes

Usage

client{ new WebDAV::Client{ options } }; bool check_connection = client->check(); std::cout << "test connection with WebDAV drive is " << (check_connection ? "" : "not ") << "successful"<< std::endl; bool is_dir = client->is_directory("/path/to/remote/resource"); std::cout << "remote resource is " << (is_dir ? "" : "not ") << "directory" << std::endl; client->create_directory("/path/to/remote/directory/"); client->clean("/path/to/remote/directory/"); std::cout << "On WebDAV-disk available free space: " << client->free_size() << std::endl; std::cout << "remote_directory_name"; for (const auto& resource_name : client->list("/path/to/remote/directory/")) { std::cout << "\t" << "-" << resource_name; } std::cout << std::endl; client->download("/path/to/remote/file", "/path/to/local/file"); client->clean("/path/to/remote/file"); client->upload("/path/to/remote/file", "/path/to/local/file"); const auto meta_info = client->info("/path/to/remote/resource"); for (const auto& field : meta_info) { std::cout << field.first << ":" << "\t" << field.second; } std::cout << std::endl; client->copy("/path/to/remote/file1", "/path/to/remote/file2"); client->move("/path/to/remote/file1", "/path/to/remote/file3"); client->async_upload("/path/to/remote/file", "/path/to/local/file"); client->async_download("/path/to/remote/file", "/path/to/local/file"); }">
#include <webdav/client.hpp>

#include <iostream>
#include <map>
#include <memory>

int main()
{
  std::map
    options =
  {
    {
   "webdav_hostname", 
   "https://webdav.yandex.ru"},
    {
   "webdav_username", 
   "webdav_username"},
    {
   "webdav_password", 
   "webdav_password"}
  };
  
   // additional keys: 
  
   // - webdav_root
  
   // - cert_path, key_path
  
   // - proxy_hostname, proxy_username, proxy_password
            
  std::unique_ptr
   
     client{ 
    new WebDAV::Client{ options } };
  
  
    bool check_connection = client->
    check();
  std::cout << 
    "test connection with WebDAV drive is " 
            << (check_connection ? 
    "" : 
    "not ")
            << 
    "successful"<< std::endl;
  
  
    bool is_dir = client->
    is_directory(
    "/path/to/remote/resource");
  std::cout << 
    "remote resource is " 
            << (is_dir ? 
    "" : 
    "not ") 
            << 
    "directory" << std::endl;
  
  client->
    create_directory(
    "/path/to/remote/directory/");
  client->
    clean(
    "/path/to/remote/directory/");

  std::cout << 
    "On WebDAV-disk available free space: " 
            << client->
    free_size() 
            << std::endl;
  
  std::cout << 
    "remote_directory_name";
  
    for (
    const 
    auto& resource_name : client->
    list(
    "/path/to/remote/directory/"))
  {
    std::cout << 
    "\t" << 
    "-" << resource_name;
  }
  std::cout << std::endl;
  
  client->
    download(
    "/path/to/remote/file", 
    "/path/to/local/file");
  client->
    clean(
    "/path/to/remote/file");
  client->
    upload(
    "/path/to/remote/file", 
    "/path/to/local/file");

  
    const 
    auto meta_info = client->
    info(
    "/path/to/remote/resource");
  
    for (
    const 
    auto& field : meta_info) {
    std::cout << field.
    first << 
    ":" << 
    "\t" << field.
    second;
  }
  std::cout << std::endl;

  client->
    copy(
    "/path/to/remote/file1", 
    "/path/to/remote/file2");
  client->
    move(
    "/path/to/remote/file1", 
    "/path/to/remote/file3");

  client->
    async_upload(
    "/path/to/remote/file", 
    "/path/to/local/file");
  client->
    async_download(
    "/path/to/remote/file", 
    "/path/to/local/file");
}
   
  

CMakeLists.txt

cmake_minimum_required(VERSION 3.4)

HunterGate(
  URL "https://github.com/ruslo/hunter/archive/v0.23.83.tar.gz"
  SHA1 "12dec078717539eb7b03e6d2a17797cba9be9ba9"
)

project(example)

hunter_add_package(WDC)
find_package(WDC CONFIG REQUIRED)

add_executable(example example.cpp)
target_link_libraries(example WDC::libwdc)
Comments
  • 1.0.6 build failure on macOS

    1.0.6 build failure on macOS

    ==> cmake . -DPUGIXML_INCLUDE_DIR=/usr/local/opt/pugixml/include -DPUGIXML_LIBRARY=/usr/local/opt/pugixml/lib -DCMAKE_C_FLAGS_RELEASE=-DNDEBUG -DCMAKE_CXX_FLAGS_RELEASE=-DNDEBUG -DCMAKE_INSTALL_PREFIX=/usr/local/Cellar/wdc/1.0.2 -DCMAKE_BUILD_TYPE=Release -DCMAKE_FIND_FRAMEWORK=LAST -DCMAKE_VERBOSE_MAKEFILE=ON -Wno-dev
    -- [hunter] Initializing Hunter workspace (4ba5c303245faed28548d4a47f496cf645cf67ed)
    -- [hunter]   https://github.com/designerror/hunter/archive/v0.18.14.23.tar.gz
    -- [hunter]   -> /tmp/wdc-20170724-88622-1vd10v/webdav-client-cpp-1.0.2/.brew_home/.hunter/_Base/Download/Hunter/0.18.14/4ba5c30
    -- The C compiler identification is AppleClang 8.1.0.8020042
    -- The CXX compiler identification is AppleClang 8.1.0.8020042
    -- Check for working C compiler: /usr/local/Homebrew/Library/Homebrew/shims/super/clang
    -- Check for working C compiler: /usr/local/Homebrew/Library/Homebrew/shims/super/clang -- works
    -- Detecting C compiler ABI info
    -- Detecting C compiler ABI info - done
    -- Detecting C compile features
    -- Detecting C compile features - done
    -- Check for working CXX compiler: /usr/local/Homebrew/Library/Homebrew/shims/super/clang++
    -- Check for working CXX compiler: /usr/local/Homebrew/Library/Homebrew/shims/super/clang++ -- works
    -- Detecting CXX compiler ABI info
    -- Detecting CXX compiler ABI info - done
    -- Detecting CXX compile features
    -- Detecting CXX compile features - done
    -- [hunter] Calculating Config-SHA1
    -- [hunter] Calculating Toolchain-SHA1
    
    [hunter ** FATAL ERROR **] No toolchain info generated
    [hunter ** FATAL ERROR **] [Directory:/tmp/wdc-20170724-88622-1vd10v/webdav-client-cpp-1.0.2/_3rdParty/Hunter/toolchain]
    
    ------------------------------ WIKI -------------------------------
        https://github.com/ruslo/hunter/wiki/error.no.toolchain.info
    -------------------------------------------------------------------
    
    CMake Error at /tmp/wdc-20170724-88622-1vd10v/webdav-client-cpp-1.0.2/.brew_home/.hunter/_Base/Download/Hunter/0.18.14/4ba5c30/Unpacked/cmake/modules/hunter_wiki.cmake:12 (message):
    Call Stack (most recent call first):
      /tmp/wdc-20170724-88622-1vd10v/webdav-client-cpp-1.0.2/.brew_home/.hunter/_Base/Download/Hunter/0.18.14/4ba5c30/Unpacked/cmake/modules/hunter_fatal_error.cmake:20 (hunter_wiki)
      CMakeLists.txt:132 (hunter_fatal_error)
    
    
    
    [hunter ** INTERNAL **] Generate failed: exit with code 1
    [hunter ** INTERNAL **] [Directory:/tmp/wdc-20170724-88622-1vd10v/webdav-client-cpp-1.0.2]
    
    ------------------------------ WIKI -------------------------------
        https://github.com/ruslo/hunter/wiki/error.internal
    -------------------------------------------------------------------
    
    CMake Error at .brew_home/.hunter/_Base/Download/Hunter/0.18.14/4ba5c30/Unpacked/cmake/modules/hunter_wiki.cmake:12 (message):
    Call Stack (most recent call first):
      .brew_home/.hunter/_Base/Download/Hunter/0.18.14/4ba5c30/Unpacked/cmake/modules/hunter_internal_error.cmake:13 (hunter_wiki)
      .brew_home/.hunter/_Base/Download/Hunter/0.18.14/4ba5c30/Unpacked/cmake/modules/hunter_calculate_toolchain_sha1.cmake:98 (hunter_internal_error)
      .brew_home/.hunter/_Base/Download/Hunter/0.18.14/4ba5c30/Unpacked/cmake/modules/hunter_apply_gate_settings.cmake:106 (hunter_calculate_toolchain_sha1)
      .brew_home/.hunter/_Base/Download/Hunter/0.18.14/4ba5c30/Unpacked/cmake/modules/hunter_finalize.cmake:66 (hunter_apply_gate_settings)
      .brew_home/.hunter/_Base/Download/Hunter/0.18.14/4ba5c30/Unpacked/cmake/modules/hunter_add_package.cmake:23 (hunter_finalize)
      CMakeLists.txt:45 (hunter_add_package)
    
    
    -- Configuring incomplete, errors occurred!
    See also "/tmp/wdc-20170724-88622-1vd10v/webdav-client-cpp-1.0.2/CMakeFiles/CMakeOutput.log".
    

    https://jenkins.brew.sh/job/Homebrew%20Core%20Pull%20Requests/5205/version=sierra/console

    opened by ilovezfs 8
  • resource_pah and target_path differs in ::info when URL has subdirectory

    resource_pah and target_path differs in ::info when URL has subdirectory

    I'm using an URL with a subdirectory as webdav_hostname (http://mynas.../temp) There is a check in the ::info method (client.cpp:515) verifying that resource_path and target_path are equal: if (resource_path_without_sep.compare(target_path_without_sep) == 0) { They differ in my case: target_path_without_sep: /empty_directory/ resource_path_without_sep: /temp/empty_directory/ Hence ::info returns an empty dict_t.

    help wanted 
    opened by telkamp 3
  • 'Method

    'Method "free" not supported' error

    After making a backup, nothing appears in my Webdav share (running on a self-hosted FreeNAS). The octoprint.log says:

    
    TypeError: can only concatenate str (not "tuple") to str
    2021-03-02 19:58:18,187 - octoprint.plugins.backup - INFO - Creating backup zip at /home/pi/.octoprint/data/backup/.octoprint-backup-20210302-195818.zip (excluded: uploads)...
    2021-03-02 19:58:18,280 - octoprint.plugins.backup - INFO - ... done creating backup zip.
    2021-03-02 19:58:18,289 - octoprint.plugins.webdavbackup - INFO - Backup /home/pi/.octoprint/data/backup/octoprint-backup-20210302-195818.zip created, will now attempt to upload to http://192.168.50.59:8080/OctoPiBackup/
    2021-03-02 19:58:18,341 - octoprint.plugin - ERROR - Error while calling plugin webdavbackup
    Traceback (most recent call last):
      File "/home/pi/oprint/lib/python3.7/site-packages/octoprint_webdavbackup/__init__.py", line 78, in on_event
        dav_free = davclient.free()
      File "/home/pi/oprint/lib/python3.7/site-packages/webdav3/client.py", line 66, in _wrapper
        res = fn(self, *args, **kw)
      File "/home/pi/oprint/lib/python3.7/site-packages/webdav3/client.py", line 277, in free
        return WebDavXmlUtils.parse_free_space_response(response.content, self.webdav.hostname)
      File "/home/pi/oprint/lib/python3.7/site-packages/webdav3/client.py", line 946, in parse_free_space_response
        raise MethodNotSupported(name='free', server=hostname)
    webdav3.exceptions.MethodNotSupported: Method 'free' not supported for http://192.168.50.59:8080/OctoPiBackup
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "/home/pi/oprint/lib/python3.7/site-packages/octoprint/plugin/__init__.py", line 271, in call_plugin
        result = getattr(plugin, method)(*args, **kwargs)
      File "/home/pi/oprint/lib/python3.7/site-packages/octoprint/util/__init__.py", line 1890, in wrapper
        return f(*args, **kwargs)
      File "/home/pi/oprint/lib/python3.7/site-packages/octoprint_webdavbackup/__init__.py", line 106, in on_event
        self._logger.error("An unexpected WebDAV error was encountered: " + exception.args)
    TypeError: can only concatenate str (not "tuple") to str
    2021-03-02 19:59:05,441 - octoprint.server.util.sockjs - INFO - Client connection closed: ::ffff:192.168.50.123
    
    

    Any ideas what's causing this, or whether it's a problem with my Webdav config or the plugin? Thank you for your help!

    opened by Nawor3565 2
  • Probably unwanted behavior when cleaning path

    Probably unwanted behavior when cleaning path

    What's the intention for the code here: https://github.com/CloudPolis/webdav-client-cpp/blob/d1bbbf939b39cb7f17acaefe5e0ccce658325faa/sources/client.cpp#L453

    If target_path = /test/example/, target_path_without_sep will be equal to target_path. If target_path = /test/example, target_path_without_sep will be /test/. But I guess the intention was:

    auto target_path_without_sep = target_urn.path();
    if( !target_path_without_sep.empty() && target_path_without_sep.back() == '/' )
         target_path_without_sep.resize(target_path_without_sep.length() - 1);
    
    opened by horde3d 2
  • Wrong behavior if path ends with slash?

    Wrong behavior if path ends with slash?

    If a path ends with a slash the parent() method probably does not return what is expected. Example: Path("test/some_path/").parent().path() will return "test/some_path/".

    By changing https://github.com/CloudPolis/webdav-client-cpp/blob/3af8c9c7cec55be201c93f6bd4720818db6e7f50/sources/urn.cpp#L140

    to auto last_separate_position = m_path.rfind(Path::separate, m_path.length() - 2); it should be ok I guess.

    opened by horde3d 2
  • CMAKE_CXX_FLAGS: -pthread missing?

    CMAKE_CXX_FLAGS: -pthread missing?

    I needed to add "-pthread" to CMAKE_CXX_FLAGS in CMakeLists.txt to get the tests linking (tests/check): 'set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -pthread")' Without -pthread, I got the following error from the linker: libwdc.a(client.cpp.o): In functionstd::thread::thread<WebDAV::Client::async_download(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<void (bool)>, std::function<int (void*, unsigned long, unsigned long, unsigned long, unsigned long)>) const::{lambda()#1}>(WebDAV::Client::async_download(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<void (bool)>, std::function<int (void*, unsigned long, unsigned long, unsigned long, unsigned long)>) const::{lambda()#1}&&)': client.cpp:(.text+0x51a5): undefined reference topthread_create'

    -> I'm using Ubuntu 17.04 with gcc 6.3.0 See also https://stackoverflow.com/questions/34933042/undefined-reference-to-pthread-create-error-when-making-c11-application-with

    opened by telkamp 2
  • I found a little bug here

    I found a little bug here

    If m_path contains URL, which ends with '/', there is infinite recursion. Check.

    P.S. The second commit changes nothing, made only for starting tests. P.P.S. There is problem on 2 last tests (Mac OS) with "cmake .. -DBUILD_TESTS:BOOL=$BUILD_TESTS -DHOME_PUGIXML="/usr/local" && make", don't know why. P.P.P.S. Update mkdir.cpp - wrong names of variables.

    opened by CatInCosmicSpace 2
  • Dangerous code regarding parameter lifetime

    Dangerous code regarding parameter lifetime

    Passing the parameters by reference to the std::thread object probably will result in a crash for most users, if they don't take care that those parameters have to be valid and constant for the whole thread lifetime.

    https://github.com/CloudPolis/webdav-client-cpp/blob/5a92c825e84ba0a3d1907b8cbdaeee7fa3079bb5/sources/client.cpp#L556

    Instead of capturing the parameters with a lambda expression it would be probably better to pass the parameters as a thread local copy, e.g. by passing the function parameters as parameters to the thread instance.

    bug 
    opened by horde3d 1
  • ::list returns the name of the root directory

    ::list returns the name of the root directory

    I'm not sure if this is an issue of the ::list method or the tests. The tests checking the number of directory entries fails, because I'm getting 1 directory more than expected. E.g. tests/list.cpp returns 11 entries, and 10 is the expected value: /temp/dir_with_files_and_dirs/ /temp/dir_with_files_and_dirs/file5 /temp/dir_with_files_and_dirs/file2 /temp/dir_with_files_and_dirs/file4 /temp/dir_with_files_and_dirs/dir1/ /temp/dir_with_files_and_dirs/dir4/ /temp/dir_with_files_and_dirs/dir3/ /temp/dir_with_files_and_dirs/file1 /temp/dir_with_files_and_dirs/dir5/ /temp/dir_with_files_and_dirs/dir2/ /temp/dir_with_files_and_dirs/file3

    bug 
    opened by telkamp 1
  • Handling of XML namespaces in PROPFIND responds

    Handling of XML namespaces in PROPFIND responds

    Having a QNAP NAS as WebDAV server where Apache is installed. PROPFIND requests returns a respond like this: [...] <D:response xmlns:lp1="DAV:"> <D:href>/temp/dir_with_files_and_dirs/</D:href> <D:propstat> <D:prop> lp1:resourcetype<D:collection/></lp1:resourcetype> </D:prop> [...] So we get "D" instead of "d" and "lp1:resourcetype" instead of "d:resourcetype" This is not handled correctly by webdav-client-cpp, e.g. in the ::info method. For an example of a PROPFIND respond see also http://people.apache.org/~thorsten/proposal/docs/components/repository/webdav.html

    Nice code example here: https://stackoverflow.com/questions/21162186/pugixml-parse-namespace-with-prefix-mapping-and-without-prefix-mappig

    bug 
    opened by telkamp 1
  • Recursive loop when trying to create recursive folder with no internet connection

    Recursive loop when trying to create recursive folder with no internet connection

    When trying to create a directory recursively when there is no internet connection available, the call to create_directory runs in an endless loop. The check call will fail, because of the recursive flag being true, another call to create_directory will be done that again runs into create_directory and so on:

    https://github.com/CloudPolis/webdav-client-cpp/blob/fafcb660a79ff34079e6063b5abb3e8d13aa84bd/sources/client.cpp#L595

    By adding a check if the parent directory is unequal to the original directory this can be avoided:

    auto remote_parent_directory = directory_urn.parent().path();
    if( remote_parent_directory == remote_directory )
         return false;
    bool is_created = this->create_directory(remote_parent_directory, response, true);
    if (!is_created) return false;
    
    opened by horde3d 0
  • Invalid use of namespace 'progress_t'

    Invalid use of namespace 'progress_t'

    Hi. My name is Sinan I new Learn C++ Programing i use C++ Builder i work to your project webdav-client.cpp

    [bcc32 Error] client.hpp(34): E2070 Invalid use of namespace 'progress_t' Full parser context client.hpp(33): namespace WebDAV my little need your help thank you please help me

    opened by theSinan02 1
  • method info() not working

    method info() not working

    Returned 'dict_t' from Client::info() has always size zero. I am connecting to an owncload server and the rest seems to work (I can create directories and upload files).

    help wanted 
    opened by avocadochicken 11
Releases(v1.1.2)
BingBing 60 Nov 4, 2022
This repository provides a C++ client SDK for Unleash that meets the Unleash Client Specifications.

Unleash Client SDK for C++ This repository provides a C++ client SDK for Unleash that meets the Unleash Client Specifications. Features The below tabl

Antonio Ruiz 4 Jan 30, 2022
C++ networking library including UniConf and a convenient D-Bus API

This is wvstreams, a nominally platform-independent networking and utilities library for C++. Some documentation is in the Docs/ directory. If that

null 27 Dec 29, 2021
C library to create simple HTTP servers and Web Applications.

Onion http server library Travis status Coverity status Onion is a C library to create simple HTTP servers and Web Applications. master the developmen

David Moreno Montero 1.9k Nov 27, 2022
Husarnet is a Peer-to-Peer VPN to connect your laptops, servers and microcontrollers over the Internet with zero configuration.

Husarnet Client Husarnet is a Peer-to-Peer VPN to connect your laptops, servers and microcontrollers over the Internet with zero configuration. Key fe

Husarnet 170 Nov 30, 2022
Enabling services on your device 79 Nov 13, 2022
Provide translation, currency conversion, and voting services. First using telnet you create a connection to a TCP socket, then the server connects to 3 UDP sockets hosted on other servers to do tasks.

to run micro servers g++ translator.cpp -o translator ./translator <port 1> g++ voting.cpp -o voting ./voting <port 2> g++ currency_converter.cpp -o c

Jacob Artuso 1 Oct 29, 2021
Build a redis client by cpp:)

Redix A light redis client implement by c++. Develop Environment cmake:3.16.3 g++:9.3.0 os:ubuntu 20.04.01 reids:5.0.7 Welcome to see my talk. Benchma

null 3 Apr 15, 2022
Async & Concurrent Servers implemented in C

Concurrent servers in c Imlementation of concurrent severs in c from scratch using this awesome blog as a tutorial. Project Structure . ├── readme.md

Rupanshu Yadav 7 Jun 21, 2021
STARTTLS implementation for mail servers that don't have it.

smtpd-starttls-proxy - a STARTTLS implementation for mail servers ----------------------------------------------------------------- smtpd-starttls-p

Laurent Bercot 6 Dec 21, 2021
The tiniest chat servers on earth!

yoctochat The tiniest chat servers on earth! Here will be a collection of the simplest possible TCP chat servers, to demonstrate how to write multiuse

Rob N ★ 53 Nov 16, 2022
This repository to emulate the progression on World of Warcraft (AzerothCore) based servers, from the version 3.0 to 3.3.5a

WoltkProgression Author: Silker This repository contains all the files required to emulate the progression on World of Warcraft private servers runnin

Silker 15 Nov 27, 2022
An implementation of the Mobile Adapter GB protocol, to connect to custom game servers.

libmobile Library that implements the Mobile Adapter GB protocol, in a way that should be easy to integrate into a plethora of different emulators/har

REON Team 10 Nov 5, 2022
StateAFL: A Greybox Fuzzer for Stateful Network Servers

StateAFL: A Coverage-Driven (Greybox) Fuzzer for Stateful Network Protocols StateAFL is a fuzzer designed for network servers. It extends the original

null 116 Nov 26, 2022
Ole Christian Eidheim 740 Nov 26, 2022
an easy implementation of a multi-process tcp server and a multi-thread tcp client

一个TCP多进程服务器-多线程客户端的简单实现。 客户端类似Apache ab的测试功能,能够通过向某一个ip端口发送指定并发量和总数量的tcp短连接;服务端处理tcp短连接,每来一条消息就打印一条log。 使用cmake编译,建议在vscode里编译,或者命令行 # 终端进入目录 mkdir bu

adin 1 Nov 28, 2021
cpp-netlib URI

Deprecation warning This library is still missing some features (including full Unicode support), and does not work on some of the newest compiler ver

C++ Network Library 126 Jul 28, 2022
Easy to use client modifications for old Roblox

RbxHooks Easy to use client modifications for old Roblox Hooks These describe the included hooks with RbxHooks, but you can also add your own! RbxHook

ORC Free and Open Source Software 20 Oct 25, 2022