Merge branch 'develop'
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Switched from curlpp to POCO, modernized cmake recipes.
This commit is contained in:
commit
2b265a5831
47
.drone.yml
47
.drone.yml
@ -27,12 +27,9 @@ steps:
|
||||
commands:
|
||||
- rm /etc/apt/apt.conf.d/docker-clean
|
||||
- rm /var/cache/apt/archives/lock
|
||||
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
|
||||
- echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
|
||||
- apt-get update -q
|
||||
- apt-get install -qy build-essential cmake pkg-config
|
||||
- apt-get install -qy libcurl4-openssl-dev libjsoncpp-dev doxygen catch
|
||||
- apt-get install -qy -t sid libcurlpp-dev
|
||||
- apt-get install -qy build-essential cmake
|
||||
- apt-get install -qy libpoco-dev libjsoncpp-dev doxygen catch
|
||||
- rm -rf build && mkdir -p build && cd build
|
||||
- cmake -DWITH_EXAMPLES=YES -DWITH_TESTS=YES -DEXTRA_TEST_ARGS="~[api]" ..
|
||||
- make VERBOSE=1
|
||||
@ -55,16 +52,14 @@ steps:
|
||||
- rm /var/cache/apt/archives/lock
|
||||
- apt-get update -q
|
||||
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
|
||||
- echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
|
||||
- echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main" >> /etc/apt/sources.list.d/ubuntu-toolchain-r.list
|
||||
- apt-get install -qy gnupg
|
||||
- gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 0x60c317803a41ba51845e371a1e9377a2ba9ef27f
|
||||
- gpg --armor --export 0x60c317803a41ba51845e371a1e9377a2ba9ef27f | apt-key add -
|
||||
- apt-get update -q
|
||||
- apt-get install -qy build-essential cmake pkg-config
|
||||
- apt-get install -qy build-essential cmake
|
||||
- apt-get install -qy -t xenial g++-9
|
||||
- apt-get install -qy libcurl4-openssl-dev libjsoncpp-dev doxygen catch
|
||||
- apt-get install -qy -t sid libcurlpp-dev
|
||||
- apt-get install -qy libpoco-dev libjsoncpp-dev doxygen catch
|
||||
- rm -rf build && mkdir -p build && cd build
|
||||
- cmake -DWITH_EXAMPLES=YES ..
|
||||
- make VERBOSE=1
|
||||
@ -87,12 +82,10 @@ steps:
|
||||
- apt-get update -q
|
||||
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
|
||||
- echo "deb http://deb.debian.org/debian stretch-backports main" >> /etc/apt/sources.list.d/stretch.list
|
||||
- echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
|
||||
- apt-get update -q
|
||||
- apt-get install -qy build-essential cmake pkg-config
|
||||
- apt-get install -qy build-essential cmake
|
||||
- apt-get install -qy -t stretch-backports clang-5.0
|
||||
- apt-get install -qy libcurl4-openssl-dev libjsoncpp-dev doxygen catch
|
||||
- apt-get install -qy -t sid libcurlpp-dev
|
||||
- apt-get install -qy libpoco-dev libjsoncpp-dev doxygen catch
|
||||
- rm -rf build && mkdir -p build && cd build
|
||||
- cmake -DWITH_EXAMPLES=YES ..
|
||||
- make VERBOSE=1
|
||||
@ -101,12 +94,12 @@ steps:
|
||||
- name: debian-package-cache
|
||||
path: /var/cache/apt/archives
|
||||
|
||||
- name: clang6
|
||||
image: debian:stretch-slim
|
||||
- name: clang7
|
||||
image: debian:buster-slim
|
||||
pull: true
|
||||
environment:
|
||||
LANG: C.utf8
|
||||
CXX: clang++-6.0
|
||||
CXX: clang++
|
||||
CXXFLAGS: -pipe -O2
|
||||
MASTODON_CPP_ACCESS_TOKEN:
|
||||
from_secret: mastodon_cpp_access_token
|
||||
@ -114,14 +107,9 @@ steps:
|
||||
- rm /etc/apt/apt.conf.d/docker-clean
|
||||
- rm /var/cache/apt/archives/lock
|
||||
- apt-get update -q
|
||||
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
|
||||
- echo "deb http://deb.debian.org/debian stretch-backports main" >> /etc/apt/sources.list.d/stretch.list
|
||||
- echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
|
||||
- apt-get update -q
|
||||
- apt-get install -qy build-essential cmake pkg-config
|
||||
- apt-get install -qy -t stretch-backports clang-6.0
|
||||
- apt-get install -qy libcurl4-openssl-dev libjsoncpp-dev doxygen catch
|
||||
- apt-get install -qy -t sid libcurlpp-dev
|
||||
- apt-get install -qy build-essential cmake clang
|
||||
- apt-get install -qy libpoco-dev libjsoncpp-dev doxygen catch
|
||||
- rm -rf build && mkdir -p build && cd build
|
||||
- cmake -DWITH_EXAMPLES=YES ..
|
||||
- make VERBOSE=1
|
||||
@ -173,13 +161,9 @@ steps:
|
||||
commands:
|
||||
- rm /etc/apt/apt.conf.d/docker-clean
|
||||
- rm /var/cache/apt/archives/lock
|
||||
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
|
||||
- echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
|
||||
- apt-get update -q
|
||||
- apt-get install -qy build-essential cmake pkg-config
|
||||
- apt-get install -qy libcurl4-openssl-dev libjsoncpp-dev doxygen
|
||||
- apt-get install -qy -t sid libcurlpp-dev
|
||||
- apt-get install -qy file
|
||||
- apt-get install -qy build-essential cmake
|
||||
- apt-get install -qy libpoco-dev libjsoncpp-dev doxygen file
|
||||
- rm -rf build && mkdir -p build && cd build
|
||||
- cmake -DWITH_EXAMPLES=NO -DWITH_TESTS=NO ..
|
||||
- make package
|
||||
@ -204,11 +188,8 @@ steps:
|
||||
- yum install -qy centos-release-scl
|
||||
- yum install -qy devtoolset-6
|
||||
- scl enable devtoolset-6 bash
|
||||
- yum install -qy libcurl-devel doxygen rpm-build
|
||||
- yum install -qy libcurl-devel poco-devel doxygen rpm-build
|
||||
- yum --enablerepo=epel install -qy cmake3 jsoncpp-devel
|
||||
- curl -s -o /var/cache/yum/curlpp-devel-0.7.3-5.el6.x86_64.rpm https://download.fedoraproject.org/pub/epel/6/x86_64/Packages/c/curlpp-devel-0.7.3-5.el6.x86_64.rpm
|
||||
- curl -s -o /var/cache/yum/curlpp-0.7.3-5.el6.x86_64.rpm https://download.fedoraproject.org/pub/epel/6/x86_64/Packages/c/curlpp-0.7.3-5.el6.x86_64.rpm
|
||||
- yum localinstall -qy /var/cache/yum/curlpp-*
|
||||
- rm -rf build && mkdir -p build && cd build
|
||||
- cmake3 -DWITH_EXAMPLES=NO -DWITH_TESTS=NO ..
|
||||
- make package
|
||||
|
150
CMakeLists.txt
150
CMakeLists.txt
@ -1,124 +1,86 @@
|
||||
cmake_minimum_required (VERSION 3.6)
|
||||
project (mastodon-cpp
|
||||
VERSION 0.106.0
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
||||
set(WITH_EASY "YES" CACHE STRING "WITH_EASY defaults to \"YES\"")
|
||||
set(WITH_EXAMPLES "NO" CACHE STRING "WITH_EXAMPLES defaults to \"NO\"")
|
||||
set(WITH_TESTS "NO" CACHE STRING "WITH_TESTS defaults to \"NO\"")
|
||||
set(WITH_DOC "YES" CACHE STRING "WITH_DOC defaults to \"YES\"")
|
||||
set(WITH_DEB "NO" CACHE STRING "WITH_DEB defaults to \"NO\"")
|
||||
set(WITH_RPM "NO" CACHE STRING "WITH_RPM defaults to \"NO\"")
|
||||
# Support version 3.6 and above, but use policy settings up to 3.14.
|
||||
# 3.6 is needed because of IMPORTED_TARGET in pkg_check_modules().
|
||||
cmake_minimum_required(VERSION 3.6...3.14)
|
||||
# Ranges are supported from 3.12, set policy to current for < 3.12.
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.12)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(CURLPP REQUIRED curlpp)
|
||||
if(WITH_EASY)
|
||||
pkg_check_modules(JSONCPP REQUIRED jsoncpp)
|
||||
|
||||
project (mastodon-cpp
|
||||
VERSION 0.110.0
|
||||
LANGUAGES CXX)
|
||||
|
||||
# DESCRIPTION was introduced in version 3.9.
|
||||
if(NOT (${CMAKE_VERSION} VERSION_LESS 3.9))
|
||||
set(PROJECT_DESCRIPTION
|
||||
"C++ wrapper for the Mastodon API.")
|
||||
endif()
|
||||
|
||||
option(WITH_EASY "Compile Easy interface." YES)
|
||||
option(WITH_EXAMPLES "Compile examples." NO)
|
||||
option(WITH_TESTS "Compile tests." NO)
|
||||
option(WITH_DOC "Generate HTML documentation." YES)
|
||||
option(WITH_DEB "Prepare for the building of .deb packages." NO)
|
||||
option(WITH_RPM "Prepare for the building of .rpm packages." NO)
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries." YES)
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type, Release or Debug.")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra -Wpedantic -ftrapv -fsanitize=undefined -g -Og -fno-omit-frame-pointer")
|
||||
|
||||
# Do not complain about compatibility-wrapper
|
||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")
|
||||
set(DEBUG_CXXFLAGS
|
||||
"-Wall"
|
||||
"-Wextra"
|
||||
"-Wpedantic"
|
||||
"-ftrapv"
|
||||
"-fsanitize=undefined"
|
||||
"-g"
|
||||
"-Og"
|
||||
"-fno-omit-frame-pointer"
|
||||
"-Wno-deprecated-declarations")
|
||||
set(DEBUG_LDFLAGS
|
||||
"-fsanitize=undefined")
|
||||
add_compile_options("$<$<CONFIG:Debug>:${DEBUG_CXXFLAGS}>")
|
||||
# add_link_options was introduced in version 3.13.
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.13)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${DEBUG_LDFLAGS}")
|
||||
else()
|
||||
add_link_options("$<$<CONFIG:Debug>:${DEBUG_LDFLAGS}>")
|
||||
endif()
|
||||
|
||||
include_directories(${PROJECT_SOURCE_DIR}/src)
|
||||
include_directories(${PROJECT_BINARY_DIR})
|
||||
|
||||
include_directories(${CURL_INCLUDE_DIRS})
|
||||
include_directories(${CURLPP_INCLUDE_DIRS})
|
||||
include_directories(${JSONCPP_INCLUDE_DIRS})
|
||||
|
||||
link_directories(${CURL_LIBRARY_DIRS})
|
||||
link_directories(${CURLPP_LIBRARY_DIRS})
|
||||
link_directories(${JSONCPP_LIBRARY_DIRS})
|
||||
|
||||
# Write version in header
|
||||
configure_file (
|
||||
"${PROJECT_SOURCE_DIR}/src/version.hpp.in"
|
||||
"${PROJECT_BINARY_DIR}/version.hpp"
|
||||
)
|
||||
|
||||
# Turn on debug output.
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_definitions(-DDEBUG=1)
|
||||
add_definitions("-DDEBUG=1")
|
||||
endif()
|
||||
|
||||
if(NOT WITH_EASY)
|
||||
add_definitions(-DWITHOUT_EASY=1)
|
||||
add_definitions("-DWITHOUT_EASY=1")
|
||||
endif()
|
||||
|
||||
# Compile library
|
||||
if(WITH_EASY)
|
||||
file(GLOB sources src/*.cpp src/api/*.cpp
|
||||
src/easy/*.cpp src/easy/entities/*.cpp)
|
||||
else()
|
||||
file(GLOB sources src/*.cpp src/api/*.cpp)
|
||||
endif()
|
||||
add_library(${PROJECT_NAME} SHARED ${sources})
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${${PROJECT_NAME}_VERSION_MAJOR}
|
||||
)
|
||||
add_subdirectory("src")
|
||||
|
||||
if(WITH_EASY)
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
${CURLPP_LIBRARIES} pthread ${JSONCPP_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
${CURLPP_LIBRARIES} pthread)
|
||||
endif()
|
||||
|
||||
# Compile examples
|
||||
if(WITH_EXAMPLES)
|
||||
file(GLOB sources_examples examples/*.cpp)
|
||||
foreach(src ${sources_examples})
|
||||
get_filename_component(bin ${src} NAME_WE)
|
||||
add_executable(${bin} ${src})
|
||||
target_link_libraries(${bin} pthread ${JSONCPP_LIBRARIES} ${PROJECT_NAME})
|
||||
endforeach()
|
||||
add_subdirectory("examples")
|
||||
endif()
|
||||
|
||||
# Compile tests
|
||||
if(WITH_TESTS)
|
||||
configure_file("tests/test.gif" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
|
||||
add_subdirectory(tests)
|
||||
add_subdirectory("tests")
|
||||
endif()
|
||||
|
||||
# Install library and header files
|
||||
install(TARGETS ${PROJECT_NAME} LIBRARY
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(FILES src/mastodon-cpp.hpp src/return_types.hpp src/types.hpp
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME})
|
||||
if(WITH_EASY)
|
||||
file(GLOB easy_header src/easy/*.hpp)
|
||||
install(FILES ${easy_header}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/easy)
|
||||
file(GLOB easy_entities_header src/easy/entities/*.hpp)
|
||||
install(FILES ${easy_entities_header}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/easy/entities)
|
||||
endif()
|
||||
|
||||
# Compile & install documentation
|
||||
if(WITH_DOC)
|
||||
add_custom_command(OUTPUT ${PROJECT_SOURCE_DIR}/doc/html
|
||||
COMMAND ./build_doc.sh WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
|
||||
COMMAND "./build_doc.sh" WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
|
||||
add_custom_target(doc DEPENDS doc/html)
|
||||
add_dependencies(${PROJECT_NAME} doc)
|
||||
|
||||
install(DIRECTORY ${PROJECT_SOURCE_DIR}/doc/html
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}-${PROJECT_VERSION})
|
||||
file(GLOB examples examples/example*.cpp)
|
||||
install(FILES ${examples}
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}-${PROJECT_VERSION}/examples)
|
||||
DESTINATION "${CMAKE_INSTALL_DOCDIR}")
|
||||
endif()
|
||||
|
||||
# Packages
|
||||
include(packages.CMakeLists.txt)
|
||||
add_subdirectory("cmake")
|
||||
add_subdirectory("pkg-config")
|
||||
|
||||
include("cmake/packages.cmake")
|
||||
|
33
README.adoc
33
README.adoc
@ -105,14 +105,13 @@ Not included in this list are entities.
|
||||
|===================================================
|
||||
| Code | Explanation
|
||||
| 0 | No error
|
||||
| 22 | Invalid argument
|
||||
| 78 | URL changed (HTTP 301 or 308)
|
||||
| 110 | Connection timed out
|
||||
| 111 | Connection refused (check http_error_code)
|
||||
| 113 | No route to host / Could not resolve host
|
||||
| 192 | curlpp runtime error
|
||||
| 193 | curlpp logic error
|
||||
| 255 | Unknown error
|
||||
| 1 | Invalid argument
|
||||
| 10 | URL changed (HTTP 301 or 308)
|
||||
| 11 | Connection timed out
|
||||
| 12 | Connection refused (check http_error_code)
|
||||
| 13 | No route to host / Could not resolve host
|
||||
| 14 | Encryption error
|
||||
| 127 | Unknown error
|
||||
|===================================================
|
||||
|
||||
If you use a debug build, you get more verbose error messages.
|
||||
@ -157,23 +156,15 @@ Prebuilt DEB and RPM packages for x86_64(amd64) are provided with each release.
|
||||
`.deb` packages are built on Debian stretch and `.rpm` packages are built on
|
||||
CentOS 7. These packages are automatically built and not tested.
|
||||
|
||||
To use the `.deb` package on Debian stretch, you will need
|
||||
https://packages.debian.org/libcurlpp0[libcurlpp0] from sid.
|
||||
|
||||
To use the `.rpm` package on CentOS 7, you will need
|
||||
https://download.fedoraproject.org/pub/epel/6/x86_64/Packages/c/[curlpp]
|
||||
from EPEL 6.
|
||||
|
||||
=== From source
|
||||
|
||||
==== Dependencies
|
||||
|
||||
* Tested OS: Linux
|
||||
* C++ compiler (tested: https://gcc.gnu.org/[gcc] 6/8/9,
|
||||
https://llvm.org/[clang] 5/6)
|
||||
https://llvm.org/[clang] 5/7)
|
||||
* https://cmake.org/[cmake] (at least: 3.6)
|
||||
* https://pkgconfig.freedesktop.org/wiki/[pkgconfig] (tested: 0.29 / 0.27)
|
||||
* http://www.curlpp.org/[curlpp] (tested: 0.8)
|
||||
* https://pocoproject.org/[POCO] (tested: 1.9 / 1.7)
|
||||
* Optional
|
||||
** Easy interface & Examples:
|
||||
https://github.com/open-source-parsers/jsoncpp[jsoncpp] (tested: 1.8 / 1.7)
|
||||
@ -186,11 +177,7 @@ from EPEL 6.
|
||||
====
|
||||
[source,shell]
|
||||
----
|
||||
echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
|
||||
echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
|
||||
apt-get update
|
||||
apt-get install build-essential cmake pkg-config libcurl4-openssl-dev libjsoncpp-dev doxygen file
|
||||
apt-get install -t sid libcurlpp-dev
|
||||
apt-get install build-essential cmake libpoco-dev libjsoncpp-dev doxygen
|
||||
----
|
||||
====
|
||||
|
||||
|
19
cmake/CMakeLists.txt
Normal file
19
cmake/CMakeLists.txt
Normal file
@ -0,0 +1,19 @@
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
|
||||
VERSION ${PACKAGE_VERSION}
|
||||
COMPATIBILITY ExactVersion) # TODO: Set to SameMajorVersion when stable.
|
||||
|
||||
install(EXPORT ${PROJECT_NAME}Targets
|
||||
FILE "${PROJECT_NAME}Targets.cmake"
|
||||
NAMESPACE "${PROJECT_NAME}::"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
||||
|
||||
configure_file("${PROJECT_NAME}Config.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" @ONLY)
|
||||
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
7
cmake/mastodon-cppConfig.cmake.in
Normal file
7
cmake/mastodon-cppConfig.cmake.in
Normal file
@ -0,0 +1,7 @@
|
||||
include(CMakeFindDependencyMacro)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
find_depencency(jsoncpp CONFIG REQUIRED)
|
||||
find_package(Poco COMPONENTS Foundation Net NetSSL CONFIG REQUIRED)
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
40
cmake/packages.cmake
Normal file
40
cmake/packages.cmake
Normal file
@ -0,0 +1,40 @@
|
||||
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${${PROJECT_NAME}_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${${PROJECT_NAME}_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${${PROJECT_NAME}_VERSION_PATCH})
|
||||
set(CPACK_PACKAGE_VERSION ${mastodon-cpp_VERSION})
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_DESCRIPTION}")
|
||||
set(CPACK_PACKAGE_CONTACT "tastytea <tastytea@tastytea.de>")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
|
||||
set(CPACK_RESOURCE_FILE_README "${PROJECT_SOURCE_DIR}/README.adoc")
|
||||
|
||||
execute_process(COMMAND uname -m
|
||||
OUTPUT_VARIABLE CPACK_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(CPACK_PACKAGE_FILE_NAME
|
||||
"${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}_${CPACK_PACKAGE_ARCHITECTURE}")
|
||||
set(CPACK_GENERATOR "TGZ")
|
||||
|
||||
if (WITH_DEB)
|
||||
set(CPACK_PACKAGE_NAME "lib${PROJECT_NAME}")
|
||||
set(CPACK_GENERATOR "DEB")
|
||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE
|
||||
"https://schlomp.space/tastytea/${PROJECT_NAME}")
|
||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||
execute_process(COMMAND dpkg --print-architecture
|
||||
OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(CPACK_PACKAGE_FILE_NAME
|
||||
"${CPACK_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}-0_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
|
||||
endif()
|
||||
|
||||
if (WITH_RPM)
|
||||
set(CPACK_PACKAGE_NAME "lib${PROJECT_NAME}")
|
||||
set(CPACK_GENERATOR "RPM")
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "AGPL-3")
|
||||
set(CPACK_RPM_PACKAGE_URL "https://schlomp.space/tastytea/${PROJECT_NAME}")
|
||||
set(CPACK_RPM_PACKAGE_REQUIRES "poco-netssl >= 1.6, jsoncpp >= 1.7.4")
|
||||
set(CPACK_PACKAGE_FILE_NAME
|
||||
"${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-0.${CPACK_PACKAGE_ARCHITECTURE}")
|
||||
endif()
|
||||
|
||||
include(CPack)
|
11
examples/CMakeLists.txt
Normal file
11
examples/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
file(GLOB sources_examples *.cpp)
|
||||
foreach(src ${sources_examples})
|
||||
get_filename_component(bin ${src} NAME_WE)
|
||||
add_executable(${bin} ${src})
|
||||
target_link_libraries(${bin} PRIVATE ${PROJECT_NAME})
|
||||
endforeach()
|
||||
|
||||
if(WITH_DOC)
|
||||
install(FILES ${sources_examples}
|
||||
DESTINATION "${CMAKE_INSTALL_DOCDIR}/examples")
|
||||
endif()
|
@ -1,54 +0,0 @@
|
||||
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${${PROJECT_NAME}_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${${PROJECT_NAME}_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${${PROJECT_NAME}_VERSION_PATCH})
|
||||
set(CPACK_PACKAGE_VERSION ${mastodon-cpp_VERSION})
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "C++ wrapper for the Mastodon API")
|
||||
set(CPACK_PACKAGE_CONTACT "tastytea <tastytea@tastytea.de>")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
|
||||
set(CPACK_RESOURCE_FILE_README "${PROJECT_SOURCE_DIR}/README.adoc")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "/\\\\.git"
|
||||
"/.gitignore"
|
||||
"/build/"
|
||||
"/doc/"
|
||||
"\\\\.sublime-"
|
||||
"/update_doc.sh"
|
||||
"/.drone.yml"
|
||||
"/ISSUE_TEMPLATE.md$")
|
||||
execute_process(COMMAND uname -m
|
||||
OUTPUT_VARIABLE CPACK_PACKAGE_ARCHITECTURE
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(CPACK_PACKAGE_FILE_NAME
|
||||
"${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}_${CPACK_PACKAGE_ARCHITECTURE}")
|
||||
set(CPACK_GENERATOR "TGZ")
|
||||
set(CPACK_SOURCE_GENERATOR "TGZ")
|
||||
|
||||
if (WITH_DEB)
|
||||
set(CPACK_PACKAGE_NAME "lib${PROJECT_NAME}")
|
||||
set(CPACK_GENERATOR "DEB")
|
||||
set(CPACK_SOURCE_GENERATOR "DEB")
|
||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://schlomp.space/tastytea/mastodon-cpp")
|
||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||
execute_process(COMMAND dpkg --print-architecture
|
||||
OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(CPACK_PACKAGE_FILE_NAME
|
||||
"${CPACK_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}-0_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME
|
||||
"${CPACK_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}-0_src")
|
||||
endif()
|
||||
|
||||
if (WITH_RPM)
|
||||
set(CPACK_PACKAGE_NAME "lib${PROJECT_NAME}")
|
||||
set(CPACK_GENERATOR "RPM")
|
||||
set(CPACK_SOURCE_GENERATOR "RPM")
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "GPL-3")
|
||||
set(CPACK_RPM_PACKAGE_URL "https://schlomp.space/tastytea/mastodon-cpp")
|
||||
set(CPACK_RPM_PACKAGE_REQUIRES "curlpp >= 0.8.1 jsoncpp, >= 1.7.4")
|
||||
set(CPACK_PACKAGE_FILE_NAME
|
||||
"${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-0.${CPACK_PACKAGE_ARCHITECTURE}")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME
|
||||
"${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-0.src")
|
||||
endif()
|
||||
|
||||
include(CPack)
|
7
pkg-config/CMakeLists.txt
Normal file
7
pkg-config/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
include(GNUInstallDirs)
|
||||
|
||||
configure_file("${PROJECT_NAME}.pc.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" @ONLY)
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
12
pkg-config/mastodon-cpp.pc.in
Normal file
12
pkg-config/mastodon-cpp.pc.in
Normal file
@ -0,0 +1,12 @@
|
||||
name=@PROJECT_NAME@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
|
||||
Name: ${name}
|
||||
Description: @PROJECT_DESCRIPTION@
|
||||
Version: @PROJECT_VERSION@
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -l${name} -lpthread -lPocoNet
|
||||
Requires: jsoncpp
|
||||
Libs.private: -lPocoFoundation -lPocoNetSSL
|
71
src/CMakeLists.txt
Normal file
71
src/CMakeLists.txt
Normal file
@ -0,0 +1,71 @@
|
||||
include(GNUInstallDirs)
|
||||
|
||||
if(WITH_EASY)
|
||||
find_package(jsoncpp CONFIG REQUIRED)
|
||||
endif()
|
||||
# Some distributions do not contain Poco*Config.cmake recipes.
|
||||
find_package(Poco COMPONENTS Foundation Net NetSSL CONFIG)
|
||||
|
||||
if(WITH_EASY)
|
||||
file(GLOB_RECURSE sources *.cpp *.hpp)
|
||||
else()
|
||||
file(GLOB sources *.cpp api/*.cpp *.hpp api/*.hpp)
|
||||
endif()
|
||||
|
||||
# Write version in header
|
||||
configure_file ("version.hpp.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/version.hpp")
|
||||
|
||||
add_library(${PROJECT_NAME} ${sources})
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${${PROJECT_NAME}_VERSION_MAJOR})
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
"$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>"
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>"
|
||||
PUBLIC
|
||||
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>"
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||
|
||||
if(WITH_EASY)
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
PUBLIC pthread jsoncpp_lib)
|
||||
endif()
|
||||
|
||||
# If no Poco*Config.cmake recipes are found, look for headers in standard dirs.
|
||||
if(PocoNetSSL_FOUND)
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
PRIVATE Poco::Foundation Poco::Net Poco::NetSSL)
|
||||
else()
|
||||
find_file(Poco_h NAMES "Poco/Poco.h"
|
||||
PATHS "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
|
||||
if("${Poco_h}" STREQUAL "Poco_h-NOTFOUND")
|
||||
message(FATAL_ERROR "Could not find POCO.")
|
||||
else()
|
||||
message(WARNING
|
||||
"Your distribution of POCO doesn't contain the *Config.cmake recipes, "
|
||||
"but the files seem to be in the standard directories. "
|
||||
"Let's hope this works.")
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
PRIVATE PocoFoundation PocoNet PocoNetSSL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
EXPORT "${PROJECT_NAME}Targets"
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
|
||||
install(FILES mastodon-cpp.hpp return_types.hpp types.hpp
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME})
|
||||
if(WITH_EASY)
|
||||
file(GLOB easy_header easy/*.hpp)
|
||||
install(FILES ${easy_header}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/easy)
|
||||
file(GLOB easy_entities_header easy/entities/*.hpp)
|
||||
install(FILES ${easy_entities_header}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/easy/entities)
|
||||
endif()
|
@ -78,7 +78,7 @@ return_call API::del(const Mastodon::API::v1 &call,
|
||||
default:
|
||||
{
|
||||
ttdebug << "ERROR: Invalid argument.\n";
|
||||
return { 22, "Invalid argument", 0, "" };
|
||||
return { error::INVALID_ARGUMENT, "Invalid argument", 0, "" };
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,5 +88,5 @@ return_call API::del(const Mastodon::API::v1 &call,
|
||||
return_call API::del(const std::string &call, const parameters ¶ms)
|
||||
{
|
||||
|
||||
return _http.request(http_method::DELETE, call, maptoformdata(params));
|
||||
return _http.request(http_method::DELETE, call, *maptoformdata(params));
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ const return_call API::get(const Mastodon::API::v1 &call,
|
||||
else
|
||||
{
|
||||
ttdebug << "ERROR: Invalid argument.\n";
|
||||
return { 22, "Invalid argument", 0, "" };
|
||||
return { error::INVALID_ARGUMENT, "Invalid argument", 0, "" };
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -239,7 +239,7 @@ const return_call API::get(const Mastodon::API::v1 &call,
|
||||
default:
|
||||
{
|
||||
ttdebug << "ERROR: Invalid argument.\n";
|
||||
return { 22, "Invalid argument", 0, "" };
|
||||
return { error::INVALID_ARGUMENT, "Invalid argument", 0, "" };
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,7 +276,7 @@ const return_call API::get(const Mastodon::API::v2 &call,
|
||||
default:
|
||||
{
|
||||
ttdebug << "ERROR: Invalid argument.\n";
|
||||
return { 22, "Invalid argument", 0, "" };
|
||||
return { error::INVALID_ARGUMENT, "Invalid argument", 0, "" };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
using namespace Mastodon;
|
||||
using std::cerr;
|
||||
using std::to_string;
|
||||
|
||||
void API::get_stream(const Mastodon::API::v1 &call,
|
||||
const parameters ¶ms,
|
||||
@ -57,8 +58,10 @@ void API::get_stream(const Mastodon::API::v1 &call,
|
||||
}
|
||||
default:
|
||||
{
|
||||
const uint8_t err = static_cast<uint8_t>(error::INVALID_ARGUMENT);
|
||||
ttdebug << "ERROR: Invalid call.\n";
|
||||
stream = "event: ERROR\ndata: {\"error_code\":22}\n";
|
||||
stream = "event: ERROR\ndata: "
|
||||
"{\"error_code\":" + to_string(err) + "}\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -32,10 +32,9 @@ return_call API::patch(const Mastodon::API::v1 &call,
|
||||
break;
|
||||
default:
|
||||
ttdebug << "ERROR: Invalid argument.\n";
|
||||
return { 22, "Invalid argument", 0, "" };
|
||||
return { error::INVALID_ARGUMENT, "Invalid argument", 0, "" };
|
||||
break;
|
||||
}
|
||||
|
||||
return _http.request(http_method::PATCH,
|
||||
strcall, maptoformdata(params));
|
||||
return _http.request(http_method::PATCH, strcall, *maptoformdata(params));
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ return_call API::post(const Mastodon::API::v1 &call,
|
||||
default:
|
||||
{
|
||||
ttdebug << "ERROR: Invalid argument.\n";
|
||||
return { 22, "Invalid argument", 0, ""};
|
||||
return { error::INVALID_ARGUMENT, "Invalid argument", 0, ""};
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,5 +214,5 @@ return_call API::post(const Mastodon::API::v1 &call)
|
||||
return_call API::post(const string &call, const parameters ¶ms)
|
||||
{
|
||||
|
||||
return _http.request(http_method::POST, call, maptoformdata(params));
|
||||
return _http.request(http_method::POST, call, *maptoformdata(params));
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ return_call API::put(const Mastodon::API::v1 &call,
|
||||
default:
|
||||
{
|
||||
ttdebug << "ERROR: Invalid argument.\n";
|
||||
return { 22, "Invalid argument", 0, "" };
|
||||
return { error::INVALID_ARGUMENT, "Invalid argument", 0, "" };
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,5 +68,5 @@ return_call API::put(const Mastodon::API::v1 &call,
|
||||
return_call API::put(const string &call, const parameters ¶ms)
|
||||
{
|
||||
|
||||
return _http.request(http_method::PUT, call, maptoformdata(params));
|
||||
return _http.request(http_method::PUT, call, *maptoformdata(params));
|
||||
}
|
||||
|
@ -51,6 +51,16 @@ Easy::return_entity<T>::return_entity(const uint8_t ec, const string &em,
|
||||
http_error_code = hec;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Easy::return_entity<T>::return_entity(const error ec, const string &em,
|
||||
const uint16_t hec, const T &ent)
|
||||
: entity(ent)
|
||||
{
|
||||
error_code = static_cast<uint8_t>(ec);
|
||||
error_message = em;
|
||||
http_error_code = hec;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Easy::return_entity<T>::return_entity::operator const T() const
|
||||
{
|
||||
|
@ -61,6 +61,19 @@ namespace Easy
|
||||
return_entity(const uint8_t ec, const string &em,
|
||||
const uint16_t hec, const T &ent);
|
||||
|
||||
/*!
|
||||
* @brief Return type for easy Mastodon::Easy::API.
|
||||
*
|
||||
* @param ec Error code
|
||||
* @param em Error message
|
||||
* @param hec HTTP error code
|
||||
* @param ent Answer
|
||||
*
|
||||
* @since 0.110.0
|
||||
*/
|
||||
return_entity(const error ec, const string &em,
|
||||
const uint16_t hec, const T &ent);
|
||||
|
||||
/*!
|
||||
* @brief Same as return_entity::entity.
|
||||
*
|
||||
|
@ -39,7 +39,8 @@ const return_entity<Status> API::send_post(const Status &status)
|
||||
else
|
||||
{
|
||||
ttdebug << "ERROR: Easy::Status::content can not be empty.\n";
|
||||
return { 22, "Easy::Status::content can not be empty", 0, Status() };
|
||||
return { error::INVALID_ARGUMENT,
|
||||
"Easy::Status::content can not be empty", 0, Status() };
|
||||
}
|
||||
|
||||
if (!status.in_reply_to_id().empty())
|
||||
@ -94,8 +95,9 @@ const return_entity<Status> API::send_post(const Status &status)
|
||||
else
|
||||
{
|
||||
ttdebug << "ERROR: Easy::Attachment::file can not be empty.\n";
|
||||
return { 22, "Easy::Attachment::file can not be empty",
|
||||
0, Status() };
|
||||
return { error::INVALID_ARGUMENT,
|
||||
"Easy::Attachment::file can not be empty", 0,
|
||||
Status() };
|
||||
}
|
||||
if (!att.description().empty())
|
||||
{
|
||||
|
383
src/http.cpp
383
src/http.cpp
@ -16,19 +16,35 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <functional> // std::bind
|
||||
#include <list>
|
||||
#include <cstring> // std::strncmp
|
||||
#include <exception>
|
||||
#include <thread>
|
||||
#include <curlpp/Options.hpp>
|
||||
#include <curlpp/Exception.hpp>
|
||||
#include <curlpp/Infos.hpp>
|
||||
#include <regex>
|
||||
#include <Poco/Net/HTTPSClientSession.h>
|
||||
#include <Poco/Net/HTTPRequest.h>
|
||||
#include <Poco/Net/HTTPResponse.h>
|
||||
#include <Poco/StreamCopier.h>
|
||||
#include <Poco/URI.h>
|
||||
#include <Poco/Environment.h>
|
||||
#include <Poco/Exception.h>
|
||||
#include <Poco/Net/NetException.h>
|
||||
#include <Poco/Net/SSLException.h>
|
||||
#include "debug.hpp"
|
||||
#include "mastodon-cpp.hpp"
|
||||
|
||||
using namespace Mastodon;
|
||||
namespace curlopts = curlpp::options;
|
||||
using std::cerr;
|
||||
using std::istream;
|
||||
using std::make_unique;
|
||||
using std::move;
|
||||
using std::regex;
|
||||
using std::regex_search;
|
||||
using std::smatch;
|
||||
using Poco::Net::HTTPSClientSession;
|
||||
using Poco::Net::HTTPRequest;
|
||||
using Poco::Net::HTTPResponse;
|
||||
using Poco::Net::HTTPMessage;
|
||||
using Poco::StreamCopier;
|
||||
using Poco::Environment;
|
||||
|
||||
API::http::http(const API &api, const string &instance,
|
||||
const string &access_token)
|
||||
@ -37,21 +53,95 @@ API::http::http(const API &api, const string &instance,
|
||||
, _access_token(access_token)
|
||||
, _cancel_stream(false)
|
||||
{
|
||||
curlpp::initialize();
|
||||
Poco::Net::initializeSSL();
|
||||
|
||||
try
|
||||
{
|
||||
string env_proxy = Environment::get("http_proxy");
|
||||
size_t pos;
|
||||
|
||||
// Only keep text between // and /.
|
||||
if ((pos = env_proxy.find("//")) != string::npos)
|
||||
{
|
||||
env_proxy = env_proxy.substr(pos + 2);
|
||||
}
|
||||
if ((pos = env_proxy.find('/')) != string::npos)
|
||||
{
|
||||
env_proxy = env_proxy.substr(0, pos);
|
||||
}
|
||||
|
||||
if ((pos = env_proxy.find('@')) != string::npos)
|
||||
{
|
||||
string hostport = env_proxy.substr(pos + 1);
|
||||
string userpw = env_proxy.substr(0, pos);
|
||||
set_proxy(hostport, userpw);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_proxy(env_proxy);
|
||||
}
|
||||
}
|
||||
catch (const std::exception &)
|
||||
{
|
||||
// No proxy found, no problem.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
API::http::~http()
|
||||
{
|
||||
curlpp::terminate();
|
||||
Poco::Net::uninitializeSSL();
|
||||
}
|
||||
|
||||
void API::http::set_proxy(const string &hostport, const string &userpw)
|
||||
{
|
||||
try
|
||||
{
|
||||
HTTPSClientSession::ProxyConfig proxyconfig;
|
||||
size_t pos = hostport.find(':');
|
||||
|
||||
proxyconfig.host = hostport.substr(0, pos);
|
||||
if (pos != string::npos)
|
||||
{
|
||||
proxyconfig.port = std::stoi(hostport.substr(pos + 1));
|
||||
}
|
||||
|
||||
if (!userpw.empty())
|
||||
{
|
||||
string username;
|
||||
|
||||
pos = userpw.find(':');
|
||||
Poco::URI::decode(userpw.substr(0, pos), username);
|
||||
proxyconfig.username = username;
|
||||
|
||||
if (pos != string::npos)
|
||||
{
|
||||
string password;
|
||||
Poco::URI::decode(userpw.substr(pos + 1), password);
|
||||
proxyconfig.password = password;
|
||||
}
|
||||
}
|
||||
|
||||
HTTPSClientSession::setGlobalProxyConfig(proxyconfig);
|
||||
ttdebug << "Set proxy to " << hostport << ".\n";
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
if (parent.exceptions())
|
||||
{
|
||||
std::rethrow_exception(std::current_exception());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return_call API::http::request(const http_method &meth, const string &path)
|
||||
{
|
||||
return request(meth, path, curlpp::Forms());
|
||||
HTMLForm form;
|
||||
return request(meth, path, form);
|
||||
}
|
||||
|
||||
return_call API::http::request(const http_method &meth, const string &path,
|
||||
const curlpp::Forms &formdata)
|
||||
HTMLForm &formdata)
|
||||
{
|
||||
string answer;
|
||||
return request_common(meth, path, formdata, answer);
|
||||
@ -63,8 +153,9 @@ void API::http::request_stream(const string &path, string &stream)
|
||||
_streamthread = std::thread(
|
||||
[&, path] // path is captured by value because it may be
|
||||
{ // deleted before we access it.
|
||||
HTMLForm form;
|
||||
ret = request_common(http_method::GET_STREAM, path,
|
||||
curlpp::Forms(), stream);
|
||||
form, stream);
|
||||
ttdebug << "Remaining content of the stream: " << stream << '\n';
|
||||
if (!ret)
|
||||
{
|
||||
@ -78,177 +169,185 @@ void API::http::request_stream(const string &path, string &stream)
|
||||
|
||||
return_call API::http::request_common(const http_method &meth,
|
||||
const string &path,
|
||||
const curlpp::Forms &formdata,
|
||||
HTMLForm &formdata,
|
||||
string &answer)
|
||||
{
|
||||
using namespace std::placeholders; // _1, _2, _3
|
||||
|
||||
ttdebug << "Path is: " << path << '\n';
|
||||
|
||||
try
|
||||
{
|
||||
curlpp::Easy request;
|
||||
std::list<string> headers;
|
||||
|
||||
request.setOpt<curlopts::Url>("https://" + _instance + path);
|
||||
ttdebug << "User-Agent: " << parent.get_useragent() << "\n";
|
||||
request.setOpt<curlopts::UserAgent>(parent.get_useragent());
|
||||
|
||||
{
|
||||
string proxy;
|
||||
string userpw;
|
||||
parent.get_proxy(proxy, userpw);
|
||||
if (!proxy.empty())
|
||||
{
|
||||
request.setOpt<curlopts::Proxy>(proxy);
|
||||
if (!userpw.empty())
|
||||
{
|
||||
request.setOpt<curlopts::ProxyUserPwd>(userpw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_access_token.empty())
|
||||
{
|
||||
headers.push_back("Authorization: Bearer " + _access_token);
|
||||
}
|
||||
if (meth != http_method::GET_STREAM)
|
||||
{
|
||||
headers.push_back("Connection: close");
|
||||
// Get headers from server
|
||||
request.setOpt<curlpp::options::Header>(true);
|
||||
}
|
||||
|
||||
request.setOpt<curlopts::HttpHeader>(headers);
|
||||
request.setOpt<curlopts::FollowLocation>(true);
|
||||
request.setOpt<curlopts::WriteFunction>
|
||||
(std::bind(&http::callback_write, this, _1, _2, _3, &answer));
|
||||
request.setOpt<curlopts::ProgressFunction>
|
||||
(std::bind(&http::callback_progress, this, _1, _2, _3, _4));
|
||||
request.setOpt<curlopts::NoProgress>(0);
|
||||
if (!formdata.empty())
|
||||
{
|
||||
request.setOpt<curlopts::HttpPost>(formdata);
|
||||
}
|
||||
string method;
|
||||
|
||||
switch (meth)
|
||||
{
|
||||
case http_method::GET:
|
||||
case http_method::GET_STREAM:
|
||||
break;
|
||||
case http_method::PATCH:
|
||||
request.setOpt<curlopts::CustomRequest>("PATCH");
|
||||
break;
|
||||
case http_method::POST:
|
||||
request.setOpt<curlopts::CustomRequest>("POST");
|
||||
break;
|
||||
case http_method::PUT:
|
||||
request.setOpt<curlopts::CustomRequest>("PUT");
|
||||
break;
|
||||
case http_method::DELETE:
|
||||
request.setOpt<curlopts::CustomRequest>("DELETE");
|
||||
{
|
||||
method = HTTPRequest::HTTP_GET;
|
||||
break;
|
||||
}
|
||||
case http_method::PUT:
|
||||
{
|
||||
method = HTTPRequest::HTTP_PUT;
|
||||
break;
|
||||
}
|
||||
case http_method::POST:
|
||||
{
|
||||
method = HTTPRequest::HTTP_POST;
|
||||
break;
|
||||
}
|
||||
case http_method::PATCH:
|
||||
{
|
||||
method = HTTPRequest::HTTP_PATCH;
|
||||
break;
|
||||
}
|
||||
case http_method::DELETE:
|
||||
{
|
||||
method = HTTPRequest::HTTP_DELETE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//request.setOpt<curlopts::Verbose>(true);
|
||||
HTTPSClientSession session(_instance);
|
||||
HTTPRequest request(method, path, HTTPMessage::HTTP_1_1);
|
||||
request.set("User-Agent", parent.get_useragent());
|
||||
|
||||
if (!_access_token.empty())
|
||||
{
|
||||
request.set("Authorization", " Bearer " + _access_token);
|
||||
}
|
||||
|
||||
if (!formdata.empty())
|
||||
{
|
||||
ttdebug << "Size of HTMLForm is " << formdata.size() << '\n';
|
||||
formdata.prepareSubmit(request);
|
||||
formdata.write(session.sendRequest(request));
|
||||
}
|
||||
else
|
||||
{
|
||||
session.sendRequest(request);
|
||||
}
|
||||
|
||||
HTTPResponse response;
|
||||
istream &rs = session.receiveResponse(response);
|
||||
|
||||
const uint16_t http_code = response.getStatus();
|
||||
ttdebug << "Response code: " << http_code << '\n';
|
||||
|
||||
answer.clear();
|
||||
request.perform();
|
||||
uint16_t http_code = curlpp::infos::ResponseCode::get(request);
|
||||
ttdebug << "Response code: " << http_code << '\n';
|
||||
// Work around "HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 200 OK"
|
||||
size_t pos = answer.find("\r\n\r\n", 25);
|
||||
_headers = answer.substr(0, pos);
|
||||
// Only return body
|
||||
answer = answer.substr(pos + 4);
|
||||
StreamCopier::copyToString(rs, answer);
|
||||
|
||||
if (http_code == 200 || http_code == 302 || http_code == 307)
|
||||
{ // OK or Found or Temporary Redirect
|
||||
return { 0, "", http_code, answer };
|
||||
}
|
||||
else if (http_code == 301 || http_code == 308)
|
||||
{ // Moved Permanently or Permanent Redirect
|
||||
// return new URL
|
||||
answer = curlpp::infos::EffectiveUrl::get(request);
|
||||
return { 78, "Remote address changed", http_code, answer };
|
||||
}
|
||||
else if (http_code == 0)
|
||||
switch (http_code)
|
||||
{
|
||||
return { 255, "Unknown error", http_code, answer };
|
||||
}
|
||||
else
|
||||
case HTTPResponse::HTTP_OK:
|
||||
{
|
||||
return { 111, "Connection refused", http_code, answer };
|
||||
return { error::OK, "", http_code, answer };
|
||||
}
|
||||
// Not using the constants because some are too new for Debian stretch.
|
||||
case 301: // HTTPResponse::HTTP_MOVED_PERMANENTLY
|
||||
case 308: // HTTPResponse::HTTP_PERMANENT_REDIRECT
|
||||
case 302: // HTTPResponse::HTTP_FOUND
|
||||
case 303: // HTTPResponse::HTTP_SEE_OTHER
|
||||
case 307: // HTTPResponse::HTTP_TEMPORARY_REDIRECT
|
||||
{
|
||||
ttdebug << "HTTP redirect.\n";
|
||||
string location = response.get("Location");
|
||||
|
||||
if (location.substr(0, 4) == "http")
|
||||
{ // Remove protocol and instance from path.
|
||||
size_t pos1 = location.find("//") + 2;
|
||||
size_t pos2 = location.find('/', pos1);
|
||||
|
||||
if (location.substr(pos1, pos2 - pos1) != _instance)
|
||||
{ // Return new location if the domain changed.
|
||||
ttdebug << "New location is on another domain.\n";
|
||||
return { error::URL_CHANGED, "Remote address changed",
|
||||
http_code, location };
|
||||
}
|
||||
|
||||
location = location.substr(pos2);
|
||||
}
|
||||
|
||||
if (http_code == 301 || http_code == 308)
|
||||
{ // Return new location for permanent redirects.
|
||||
return { error::URL_CHANGED, "Remote address changed",
|
||||
http_code, location };
|
||||
}
|
||||
else
|
||||
{
|
||||
ttdebug << "Following temporary redirect: " << location << '\n';
|
||||
return request_common(meth, location, formdata, answer);
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
return { error::CONNECTION_REFUSED, "Connection refused",
|
||||
http_code, answer };
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (curlpp::RuntimeError &e)
|
||||
catch (const Poco::Net::DNSException &e)
|
||||
{
|
||||
const string what = e.what();
|
||||
// This error is thrown if http.cancel_stream() is used.
|
||||
if ((what.compare(0, 16, "Callback aborted") == 0) ||
|
||||
(what.compare(0, 19, "Failed writing body") == 0))
|
||||
{
|
||||
ttdebug << "Request was cancelled by user\n";
|
||||
return { 0, "Request was cancelled by user", 0, "" };
|
||||
}
|
||||
else if (what.compare(what.size() - 20, 20, "Connection timed out") == 0)
|
||||
{
|
||||
ttdebug << what << "\n";
|
||||
return { 110, "Connection timed out", 0, "" };
|
||||
}
|
||||
else if (what.compare(0, 23, "Could not resolve host:") == 0)
|
||||
{
|
||||
ttdebug << what << "\n";
|
||||
return { 113, "Could not resolve host", 0, "" };
|
||||
}
|
||||
|
||||
if (parent.exceptions())
|
||||
{
|
||||
std::rethrow_exception(std::current_exception());
|
||||
}
|
||||
else
|
||||
{
|
||||
ttdebug << "curlpp::RuntimeError: " << e.what() << std::endl;
|
||||
return { 192, e.what(), 0, "" };
|
||||
e.rethrow();
|
||||
}
|
||||
|
||||
ttdebug << e.displayText() << "\n";
|
||||
return { error::DNS, e.displayText(), 0, "" };
|
||||
}
|
||||
catch (curlpp::LogicError &e)
|
||||
catch (const Poco::Net::ConnectionRefusedException &e)
|
||||
{
|
||||
if (parent.exceptions())
|
||||
{
|
||||
e.rethrow();
|
||||
}
|
||||
|
||||
ttdebug << e.displayText() << "\n";
|
||||
return { error::CONNECTION_REFUSED, e.displayText(), 0, "" };
|
||||
}
|
||||
catch (const Poco::Net::SSLException &e)
|
||||
{
|
||||
if (parent.exceptions())
|
||||
{
|
||||
e.rethrow();
|
||||
}
|
||||
|
||||
ttdebug << e.displayText() << "\n";
|
||||
return { error::ENCRYPTION, e.displayText(), 0, "" };
|
||||
}
|
||||
catch (const Poco::Net::NetException &e)
|
||||
{
|
||||
if (parent.exceptions())
|
||||
{
|
||||
e.rethrow();
|
||||
}
|
||||
|
||||
ttdebug << "Unknown network error: " << e.displayText() << std::endl;
|
||||
return { error::UNKNOWN, e.displayText(), 0, "" };
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
if (parent.exceptions())
|
||||
{
|
||||
std::rethrow_exception(std::current_exception());
|
||||
}
|
||||
|
||||
ttdebug << "curlpp::LogicError: " << e.what() << std::endl;
|
||||
return { 193, e.what(), 0, "" };
|
||||
ttdebug << "Unknown error: " << e.what() << std::endl;
|
||||
return { error::UNKNOWN, e.what(), 0, "" };
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: get_headers() doesn't work anymore.
|
||||
void API::http::get_headers(string &headers) const
|
||||
{
|
||||
headers = _headers;
|
||||
}
|
||||
|
||||
size_t API::http::callback_write(char* data, size_t size, size_t nmemb,
|
||||
string *str)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
str->append(data, size * nmemb);
|
||||
// ttdebug << "Received " << size * nmemb << " Bytes\n";
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
double API::http::callback_progress(double /* dltotal */, double /* dlnow */,
|
||||
double /* ultotal */, double /* ulnow */)
|
||||
{
|
||||
if (_cancel_stream)
|
||||
{
|
||||
// This throws the runtime error: Callback aborted
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void API::http::cancel_stream()
|
||||
{
|
||||
_cancel_stream = true;
|
||||
|
@ -14,20 +14,21 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
#include <regex>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include <utility>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <exception>
|
||||
#include <Poco/Net/FilePartSource.h>
|
||||
#include <Poco/URI.h>
|
||||
#include "version.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "mastodon-cpp.hpp"
|
||||
|
||||
using namespace Mastodon;
|
||||
using std::make_unique;
|
||||
using Poco::Net::FilePartSource;
|
||||
|
||||
API::API(const string &instance, const string &access_token)
|
||||
: _instance(instance)
|
||||
@ -35,8 +36,6 @@ API::API(const string &instance, const string &access_token)
|
||||
, _useragent(string("mastodon-cpp/") + global::version)
|
||||
, _http(*this, instance, access_token)
|
||||
, _exceptions(false)
|
||||
, _proxy("")
|
||||
, _proxy_userpw("")
|
||||
{
|
||||
bool fash = false;
|
||||
const std::regex re_gab("(?:\\.|^)gab\\.[^\\.]+$");
|
||||
@ -111,9 +110,12 @@ const string API::maptostr(const parameters &map, const bool &firstparam)
|
||||
return result;
|
||||
}
|
||||
|
||||
const curlpp::Forms API::maptoformdata(const parameters &map)
|
||||
unique_ptr<HTMLForm> API::maptoformdata(const parameters &map)
|
||||
{
|
||||
curlpp::Forms formdata;
|
||||
ttdebug << "Transforming Mastodon::parameters to Poco::Net::HTMLForm.\n";
|
||||
|
||||
unique_ptr<HTMLForm> formdata =
|
||||
make_unique<HTMLForm>(HTMLForm::ENCODING_MULTIPART);
|
||||
|
||||
if (map.size() == 0)
|
||||
{
|
||||
@ -122,51 +124,58 @@ const curlpp::Forms API::maptoformdata(const parameters &map)
|
||||
|
||||
for (const auto &it : map)
|
||||
{
|
||||
string key = it.key;
|
||||
ttdebug << "Processing \"" + key + "\".\n";
|
||||
|
||||
// TODO: Test nested parameters.
|
||||
if (const size_t pos = key.find('.') != string::npos)
|
||||
{ // Nested parameters.
|
||||
key.replace(pos, 1, "[");
|
||||
key += ']';
|
||||
}
|
||||
|
||||
if (it.values.size() == 1)
|
||||
{ // If the file is not base64-encoded, treat as filename.
|
||||
if ((it.key == "avatar" ||
|
||||
it.key == "header" ||
|
||||
it.key == "file") &&
|
||||
if ((key == "avatar" ||
|
||||
key == "header" ||
|
||||
key == "file") &&
|
||||
it.values.front().substr(0, 5) != "data:")
|
||||
{
|
||||
ttdebug << it.key << ": Filename detected.\n";
|
||||
std::ifstream testfile(it.values.front());
|
||||
if (testfile.good())
|
||||
{
|
||||
ttdebug << key << ": Filename detected.\n";
|
||||
|
||||
try
|
||||
{
|
||||
testfile.close();
|
||||
formdata.push_back(
|
||||
new curlpp::FormParts::File(it.key, it.values.front()));
|
||||
formdata->addPart(key,
|
||||
new FilePartSource(it.values.front()));
|
||||
}
|
||||
else
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
std::cerr << "Error: File not found: " << it.values.front()
|
||||
<< std::endl;
|
||||
if (exceptions())
|
||||
{
|
||||
std::rethrow_exception(std::current_exception());
|
||||
}
|
||||
|
||||
// TODO: Proper error handling without exceptions.
|
||||
std::cerr << "Error: Could not open file: "
|
||||
<< it.values.front() << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string key = it.key;
|
||||
// Append [] to array keys.
|
||||
if (key == "account_ids"
|
||||
}
|
||||
else if (key == "account_ids"
|
||||
|| key == "exclude_types"
|
||||
|| key == "media_ids"
|
||||
|| key == "context")
|
||||
{
|
||||
key += "[]";
|
||||
}
|
||||
formdata.push_back(
|
||||
new curlpp::FormParts::Content(key, it.values.front()));
|
||||
{
|
||||
key += "[]";
|
||||
}
|
||||
|
||||
formdata->add(key, it.values.front());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::transform(it.values.begin(), it.values.end(),
|
||||
std::back_inserter(formdata),
|
||||
[&it](const string &s)
|
||||
{
|
||||
return new curlpp::FormParts::Content
|
||||
(it.key + "[]", s);
|
||||
});
|
||||
for (const string &value : it.values)
|
||||
{
|
||||
formdata->add(key + "[]", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,22 +291,9 @@ bool API::exceptions() const
|
||||
return _exceptions;
|
||||
}
|
||||
|
||||
void API::set_proxy(const string &proxy, const string &userpw)
|
||||
void API::set_proxy(const string &hostport, const string &userpw)
|
||||
{
|
||||
_proxy = proxy;
|
||||
_proxy_userpw = userpw;
|
||||
}
|
||||
|
||||
void API::get_proxy(string &proxy, string &userpw) const
|
||||
{
|
||||
if (!_proxy.empty())
|
||||
{
|
||||
proxy = _proxy;
|
||||
if (!_proxy_userpw.empty())
|
||||
{
|
||||
userpw = _proxy_userpw;
|
||||
}
|
||||
}
|
||||
_http.set_proxy(hostport, userpw);
|
||||
}
|
||||
|
||||
const parameters API::delete_params(const parameters ¶ms,
|
||||
@ -323,11 +319,16 @@ const parameters API::delete_params(const parameters ¶ms,
|
||||
|
||||
const string Mastodon::urlencode(const std::string &str)
|
||||
{
|
||||
return curlpp::escape(str);
|
||||
string out;
|
||||
Poco::URI::encode(str, "", out);
|
||||
return out;
|
||||
}
|
||||
|
||||
const string Mastodon::urldecode(const std::string &str)
|
||||
{
|
||||
return curlpp::unescape(str);
|
||||
string out;
|
||||
Poco::URI::decode(str, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
const string Mastodon::unescape_html(const string &html)
|
||||
|
@ -25,14 +25,15 @@
|
||||
#include <ostream>
|
||||
#include <thread>
|
||||
#include <cstdint>
|
||||
#include <curlpp/cURLpp.hpp>
|
||||
#include <curlpp/Easy.hpp>
|
||||
#include <Poco/Net/HTMLForm.h>
|
||||
|
||||
#include "return_types.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
using std::string;
|
||||
using std::uint8_t;
|
||||
using std::unique_ptr;
|
||||
using Poco::Net::HTMLForm;
|
||||
|
||||
/*!
|
||||
* @example example01_get_public_timeline.cpp
|
||||
@ -55,14 +56,13 @@ namespace Mastodon
|
||||
* | Code | Explanation |
|
||||
* | --------: |:-------------------------------------------|
|
||||
* | 0 | No error |
|
||||
* | 22 | Invalid argument |
|
||||
* | 78 | URL changed (HTTP 301 or 308) |
|
||||
* | 110 | Connection timed out |
|
||||
* | 111 | Connection refused (check http_error_code) |
|
||||
* | 113 | No route to host / Could not resolve host |
|
||||
* | 192 | curlpp runtime error |
|
||||
* | 193 | curlpp logic error |
|
||||
* | 255 | Unknown error |
|
||||
* | 1 | Invalid argument |
|
||||
* | 10 | URL changed (HTTP 301 or 308) |
|
||||
* | 11 | Connection timed out |
|
||||
* | 12 | Connection refused (check http_error_code) |
|
||||
* | 13 | No route to host / Could not resolve host |
|
||||
* | 14 | Encryption error |
|
||||
* | 127 | Unknown error |
|
||||
*
|
||||
* @since before 0.11.0
|
||||
*/
|
||||
@ -102,7 +102,7 @@ namespace Mastodon
|
||||
*/
|
||||
return_call request(const http_method &meth,
|
||||
const string &path,
|
||||
const curlpp::Forms &formdata);
|
||||
HTMLForm &formdata);
|
||||
|
||||
/*!
|
||||
* @brief HTTP Request for streams.
|
||||
@ -142,6 +142,16 @@ namespace Mastodon
|
||||
*/
|
||||
std::mutex &get_mutex();
|
||||
|
||||
/*!
|
||||
* @brief Set proxy. Do not call this directly.
|
||||
*
|
||||
* @param hostport host[:port]
|
||||
* @param userpw user[:password] (optional)
|
||||
*
|
||||
* @since 0.110.0
|
||||
*/
|
||||
void set_proxy(const string &hostport, const string &userpw = "");
|
||||
|
||||
private:
|
||||
const API &parent;
|
||||
const string _instance;
|
||||
@ -153,7 +163,7 @@ namespace Mastodon
|
||||
|
||||
return_call request_common(const http_method &meth,
|
||||
const string &path,
|
||||
const curlpp::Forms &formdata,
|
||||
HTMLForm &formdata,
|
||||
string &answer);
|
||||
size_t callback_write(char* data, size_t size, size_t nmemb,
|
||||
string *oss);
|
||||
@ -412,8 +422,7 @@ namespace Mastodon
|
||||
/*!
|
||||
* @brief Turn exceptions on or off. Defaults to off.
|
||||
*
|
||||
* This applies to exceptions from curlpp. curlpp::RuntimeError
|
||||
* and curlpp::LogicError.
|
||||
* Most exceptions will be thrown at you to handle if on.
|
||||
*
|
||||
* @param value true for on, false for off
|
||||
*
|
||||
@ -439,25 +448,15 @@ namespace Mastodon
|
||||
/*!
|
||||
* @brief Sets the proxy.
|
||||
*
|
||||
* Since mastodon-cpp is built on libcurl, it respects the same
|
||||
* proxy environment variables. See `man curl`.
|
||||
* Both the username and the password will be URL decoded
|
||||
* before use.
|
||||
*
|
||||
* @param proxy See `man 3 CURLOPT_PROXY`
|
||||
* @param userpw See `man 3 CURLOPT_PROXYUSERPWD` (optional)
|
||||
* @param hostport host[:port]
|
||||
* @param userpw username[:password] (optional)
|
||||
*
|
||||
* @since 0.15.0
|
||||
*/
|
||||
void set_proxy(const string &proxy, const string &userpw = "");
|
||||
|
||||
/*!
|
||||
* @brief For internal use
|
||||
*
|
||||
* @param proxy URL
|
||||
* @param userpw username:password
|
||||
*
|
||||
* @since 0.15.1
|
||||
*/
|
||||
void get_proxy(string &proxy, string &userpw) const;
|
||||
void set_proxy(const string &hostport, const string &userpw = "");
|
||||
|
||||
/*!
|
||||
* @brief Make a GET request that doesn't require parameters.
|
||||
@ -514,7 +513,7 @@ namespace Mastodon
|
||||
*/
|
||||
void get_stream(const Mastodon::API::v1 &call,
|
||||
const parameters ¶meters,
|
||||
std::unique_ptr<Mastodon::API::http> &ptr,
|
||||
unique_ptr<Mastodon::API::http> &ptr,
|
||||
string &stream);
|
||||
|
||||
/*!
|
||||
@ -527,7 +526,7 @@ namespace Mastodon
|
||||
* @since 0.100.0
|
||||
*/
|
||||
void get_stream(const Mastodon::API::v1 &call,
|
||||
std::unique_ptr<Mastodon::API::http> &ptr,
|
||||
unique_ptr<Mastodon::API::http> &ptr,
|
||||
string &stream);
|
||||
|
||||
/*!
|
||||
@ -540,7 +539,7 @@ namespace Mastodon
|
||||
* @since 0.100.0
|
||||
*/
|
||||
void get_stream(const string &call,
|
||||
std::unique_ptr<Mastodon::API::http> &ptr,
|
||||
unique_ptr<Mastodon::API::http> &ptr,
|
||||
string &stream);
|
||||
|
||||
/*!
|
||||
@ -646,8 +645,6 @@ namespace Mastodon
|
||||
string _useragent;
|
||||
http _http;
|
||||
bool _exceptions;
|
||||
string _proxy;
|
||||
string _proxy_userpw;
|
||||
|
||||
/*!
|
||||
* @brief Converts map of parameters into a string.
|
||||
@ -665,9 +662,9 @@ namespace Mastodon
|
||||
*
|
||||
* @param map Map of parameters
|
||||
*
|
||||
* @return Form data as curlpp::Forms
|
||||
* @return Form data as Poco::Net::HTMLForm.
|
||||
*/
|
||||
const curlpp::Forms maptoformdata(const parameters &map);
|
||||
unique_ptr<HTMLForm> maptoformdata(const parameters &map);
|
||||
|
||||
/*!
|
||||
* @brief Delete Mastodon::param from Mastodon::parameters.
|
||||
@ -684,13 +681,12 @@ namespace Mastodon
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Percent-encodes a string. This is done automatically, unless
|
||||
* you make a custom request.
|
||||
* @brief Percent-encodes a string.
|
||||
*
|
||||
* Calls curlpp::escape(str).
|
||||
*
|
||||
* The only time you should use this, is if you use
|
||||
* get(const string &call, string &answer).
|
||||
* This is done automatically where necessary. The only time you
|
||||
* should use this, is if you use get(const string &call, string
|
||||
* &answer).
|
||||
*
|
||||
* See RFC 3986 section 2.1 for more info.
|
||||
*
|
||||
@ -705,8 +701,6 @@ namespace Mastodon
|
||||
/*!
|
||||
* @brief Decodes a percent-encoded string.
|
||||
*
|
||||
* Calls curlpp::unescape(str).
|
||||
*
|
||||
* See RFC 3986 section 2.1 for more info.
|
||||
*
|
||||
* @param str The string to decode.
|
||||
|
@ -57,4 +57,13 @@ namespace Mastodon
|
||||
error_message = em;
|
||||
http_error_code = hec;
|
||||
}
|
||||
|
||||
return_call::return_call(const error ec, const string &em,
|
||||
const uint16_t hec, const string &a)
|
||||
: answer(a)
|
||||
{
|
||||
error_code = static_cast<uint8_t>(ec);
|
||||
error_message = em;
|
||||
http_error_code = hec;
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include "types.hpp"
|
||||
|
||||
using std::uint8_t;
|
||||
using std::uint16_t;
|
||||
@ -113,6 +114,19 @@ namespace Mastodon
|
||||
return_call(const uint8_t ec, const string &em,
|
||||
const uint16_t hec, const string &a);
|
||||
|
||||
/*!
|
||||
* @brief Return type for Mastodon::API.
|
||||
*
|
||||
* @param ec Error code
|
||||
* @param em Error message
|
||||
* @param hec HTTP error code
|
||||
* @param a Answer
|
||||
*
|
||||
* @since 0.110.0
|
||||
*/
|
||||
return_call(const error ec, const string &em,
|
||||
const uint16_t hec, const string &a);
|
||||
|
||||
/*!
|
||||
* @brief Same es return_call::answer.
|
||||
*
|
||||
|
@ -93,6 +93,18 @@ namespace Mastodon
|
||||
DELETE,
|
||||
GET_STREAM
|
||||
};
|
||||
|
||||
enum class error
|
||||
{
|
||||
OK = 0,
|
||||
INVALID_ARGUMENT = 1,
|
||||
URL_CHANGED = 10,
|
||||
CONNECTION_TIMEOUT = 11,
|
||||
CONNECTION_REFUSED = 12,
|
||||
DNS = 13,
|
||||
ENCRYPTION = 14,
|
||||
UNKNOWN = 127
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MASTODON_CPP_TYPES_HPP
|
||||
|
@ -1,20 +1,23 @@
|
||||
include(CTest)
|
||||
file(GLOB sources_tests test_*.cpp */test_*.cpp)
|
||||
|
||||
file(GLOB_RECURSE sources_tests test_*.cpp)
|
||||
|
||||
configure_file("test.gif" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
|
||||
|
||||
find_package(Catch2)
|
||||
if(Catch2_FOUND) # Catch 2.x
|
||||
if(Catch2_FOUND) # Catch 2.x
|
||||
include(Catch)
|
||||
add_executable(all_tests main.cpp ${sources_tests})
|
||||
target_link_libraries(all_tests ${PROJECT_NAME} Catch2::Catch2)
|
||||
target_link_libraries(all_tests PRIVATE ${PROJECT_NAME} Catch2::Catch2)
|
||||
target_include_directories(all_tests PRIVATE "/usr/include/catch2")
|
||||
catch_discover_tests(all_tests EXTRA_ARGS "${EXTRA_TEST_ARGS}")
|
||||
else() # Catch 1.x
|
||||
else() # Catch 1.x
|
||||
if(EXISTS "/usr/include/catch.hpp")
|
||||
message(STATUS "Catch 1.x found.")
|
||||
foreach(src ${sources_tests})
|
||||
get_filename_component(bin ${src} NAME_WE)
|
||||
add_executable(${bin} main.cpp ${src})
|
||||
target_link_libraries(${bin} ${PROJECT_NAME})
|
||||
target_link_libraries(${bin} PRIVATE ${PROJECT_NAME})
|
||||
add_test(${bin} ${bin} "${EXTRA_TEST_ARGS}")
|
||||
endforeach()
|
||||
else()
|
||||
|
Reference in New Issue
Block a user