diff --git a/.gitignore b/.gitignore index 2cecc15bdcf..d955392fe97 100644 --- a/.gitignore +++ b/.gitignore @@ -13,12 +13,14 @@ /build_* /build-* /docs/build +/docs/publish /docs/edit /docs/tools/venv/ -/docs/en/development/build/ -/docs/ru/development/build/ /docs/en/single.md /docs/ru/single.md +/docs/zh/single.md +/docs/ja/single.md +/docs/fa/single.md # callgrind files callgrind.out.* diff --git a/README.md b/README.md index 21498a22912..61b676262b5 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,4 @@ ClickHouse is an open-source column-oriented database management system that all ## Upcoming Events * [ClickHouse Meetup in San Francisco](https://www.eventbrite.com/e/clickhouse-february-meetup-registration-88496227599) on February 5. +* [ClickHouse Meetup in New York](https://www.meetup.com/Uber-Engineering-Events-New-York/events/268328663/) on February 11. diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index 7c9db5bb06f..999d1e96c9a 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -306,7 +306,7 @@ if (USE_INTERNAL_AWS_S3_LIBRARY) # The library is large - avoid bloat. target_compile_options (aws_s3 PRIVATE -g0) target_compile_options (aws_s3_checksums PRIVATE -g0) - target_compile_options (libcurl PRIVATE -g0) + target_compile_options (curl PRIVATE -g0) endif () if (USE_BASE64) diff --git a/contrib/aws-s3-cmake/CMakeLists.txt b/contrib/aws-s3-cmake/CMakeLists.txt index ef9107e0d4f..6ed6434dcfd 100644 --- a/contrib/aws-s3-cmake/CMakeLists.txt +++ b/contrib/aws-s3-cmake/CMakeLists.txt @@ -102,4 +102,4 @@ if (OPENSSL_FOUND) target_link_libraries(aws_s3 PRIVATE ${OPENSSL_LIBRARIES}) endif() -target_link_libraries(aws_s3 PRIVATE aws_s3_checksums libcurl) +target_link_libraries(aws_s3 PRIVATE aws_s3_checksums curl) diff --git a/contrib/curl-cmake/CMake/CurlSymbolHiding.cmake b/contrib/curl-cmake/CMake/CurlSymbolHiding.cmake deleted file mode 100644 index 224755a314c..00000000000 --- a/contrib/curl-cmake/CMake/CurlSymbolHiding.cmake +++ /dev/null @@ -1,61 +0,0 @@ -include(CheckCSourceCompiles) - -option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide all symbols that aren't officially external)." ON) -mark_as_advanced(CURL_HIDDEN_SYMBOLS) - -if(CURL_HIDDEN_SYMBOLS) - set(SUPPORTS_SYMBOL_HIDING FALSE) - - if(CMAKE_C_COMPILER_ID MATCHES "Clang") - set(SUPPORTS_SYMBOL_HIDING TRUE) - set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))") - set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden") - elseif(CMAKE_COMPILER_IS_GNUCC) - if(NOT CMAKE_VERSION VERSION_LESS 2.8.10) - set(GCC_VERSION ${CMAKE_C_COMPILER_VERSION}) - else() - execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion - OUTPUT_VARIABLE GCC_VERSION) - endif() - if(NOT GCC_VERSION VERSION_LESS 3.4) - # note: this is considered buggy prior to 4.0 but the autotools don't care, so let's ignore that fact - set(SUPPORTS_SYMBOL_HIDING TRUE) - set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))") - set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden") - endif() - elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.0) - set(SUPPORTS_SYMBOL_HIDING TRUE) - set(_SYMBOL_EXTERN "__global") - set(_CFLAG_SYMBOLS_HIDE "-xldscope=hidden") - elseif(CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.0) - # note: this should probably just check for version 9.1.045 but I'm not 100% sure - # so let's do it the same way autotools do. - set(SUPPORTS_SYMBOL_HIDING TRUE) - set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))") - set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden") - check_c_source_compiles("#include - int main (void) { printf(\"icc fvisibility bug test\"); return 0; }" _no_bug) - if(NOT _no_bug) - set(SUPPORTS_SYMBOL_HIDING FALSE) - set(_SYMBOL_EXTERN "") - set(_CFLAG_SYMBOLS_HIDE "") - endif() - elseif(MSVC) - set(SUPPORTS_SYMBOL_HIDING TRUE) - endif() - - set(HIDES_CURL_PRIVATE_SYMBOLS ${SUPPORTS_SYMBOL_HIDING}) -elseif(MSVC) - if(NOT CMAKE_VERSION VERSION_LESS 3.7) - set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) #present since 3.4.3 but broken - set(HIDES_CURL_PRIVATE_SYMBOLS FALSE) - else() - message(WARNING "Hiding private symbols regardless CURL_HIDDEN_SYMBOLS being disabled.") - set(HIDES_CURL_PRIVATE_SYMBOLS TRUE) - endif() -else() - set(HIDES_CURL_PRIVATE_SYMBOLS FALSE) -endif() - -set(CURL_CFLAG_SYMBOLS_HIDE ${_CFLAG_SYMBOLS_HIDE}) -set(CURL_EXTERN_SYMBOL ${_SYMBOL_EXTERN}) diff --git a/contrib/curl-cmake/CMake/CurlTests.c b/contrib/curl-cmake/CMake/CurlTests.c deleted file mode 100644 index 3ef35f02535..00000000000 --- a/contrib/curl-cmake/CMake/CurlTests.c +++ /dev/null @@ -1,617 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -#ifdef TIME_WITH_SYS_TIME -/* Time with sys/time test */ - -#include -#include -#include - -int -main () -{ -if ((struct tm *) 0) -return 0; - ; - return 0; -} - -#endif - -#ifdef HAVE_FCNTL_O_NONBLOCK - -/* headers for FCNTL_O_NONBLOCK test */ -#include -#include -#include -/* */ -#if defined(sun) || defined(__sun__) || \ - defined(__SUNPRO_C) || defined(__SUNPRO_CC) -# if defined(__SVR4) || defined(__srv4__) -# define PLATFORM_SOLARIS -# else -# define PLATFORM_SUNOS4 -# endif -#endif -#if (defined(_AIX) || defined(__xlC__)) && !defined(_AIX41) -# define PLATFORM_AIX_V3 -#endif -/* */ -#if defined(PLATFORM_SUNOS4) || defined(PLATFORM_AIX_V3) || defined(__BEOS__) -#error "O_NONBLOCK does not work on this platform" -#endif - -int -main () -{ - /* O_NONBLOCK source test */ - int flags = 0; - if(0 != fcntl(0, F_SETFL, flags | O_NONBLOCK)) - return 1; - return 0; -} -#endif - -/* tests for gethostbyaddr_r or gethostbyname_r */ -#if defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT) || \ - defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT) || \ - defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT) || \ - defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) || \ - defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) || \ - defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT) -# define _REENTRANT - /* no idea whether _REENTRANT is always set, just invent a new flag */ -# define TEST_GETHOSTBYFOO_REENTRANT -#endif -#if defined(HAVE_GETHOSTBYADDR_R_5) || \ - defined(HAVE_GETHOSTBYADDR_R_7) || \ - defined(HAVE_GETHOSTBYADDR_R_8) || \ - defined(HAVE_GETHOSTBYNAME_R_3) || \ - defined(HAVE_GETHOSTBYNAME_R_5) || \ - defined(HAVE_GETHOSTBYNAME_R_6) || \ - defined(TEST_GETHOSTBYFOO_REENTRANT) -#include -#include -int main(void) -{ - char *address = "example.com"; - int length = 0; - int type = 0; - struct hostent h; - int rc = 0; -#if defined(HAVE_GETHOSTBYADDR_R_5) || \ - defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT) || \ - \ - defined(HAVE_GETHOSTBYNAME_R_3) || \ - defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) - struct hostent_data hdata; -#elif defined(HAVE_GETHOSTBYADDR_R_7) || \ - defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT) || \ - defined(HAVE_GETHOSTBYADDR_R_8) || \ - defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT) || \ - \ - defined(HAVE_GETHOSTBYNAME_R_5) || \ - defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) || \ - defined(HAVE_GETHOSTBYNAME_R_6) || \ - defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT) - char buffer[8192]; - int h_errnop; - struct hostent *hp; -#endif - -#ifndef gethostbyaddr_r - (void)gethostbyaddr_r; -#endif - -#if defined(HAVE_GETHOSTBYADDR_R_5) || \ - defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT) - rc = gethostbyaddr_r(address, length, type, &h, &hdata); - (void)rc; -#elif defined(HAVE_GETHOSTBYADDR_R_7) || \ - defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT) - hp = gethostbyaddr_r(address, length, type, &h, buffer, 8192, &h_errnop); - (void)hp; -#elif defined(HAVE_GETHOSTBYADDR_R_8) || \ - defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT) - rc = gethostbyaddr_r(address, length, type, &h, buffer, 8192, &hp, &h_errnop); - (void)rc; -#endif - -#if defined(HAVE_GETHOSTBYNAME_R_3) || \ - defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) - rc = gethostbyname_r(address, &h, &hdata); -#elif defined(HAVE_GETHOSTBYNAME_R_5) || \ - defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) - rc = gethostbyname_r(address, &h, buffer, 8192, &h_errnop); - (void)hp; /* not used for test */ -#elif defined(HAVE_GETHOSTBYNAME_R_6) || \ - defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT) - rc = gethostbyname_r(address, &h, buffer, 8192, &hp, &h_errnop); -#endif - - (void)length; - (void)type; - (void)rc; - return 0; -} -#endif - -#ifdef HAVE_SOCKLEN_T -#ifdef _WIN32 -#include -#else -#include -#include -#endif -int -main () -{ -if ((socklen_t *) 0) - return 0; -if (sizeof (socklen_t)) - return 0; - ; - return 0; -} -#endif -#ifdef HAVE_IN_ADDR_T -#include -#include -#include - -int -main () -{ -if ((in_addr_t *) 0) - return 0; -if (sizeof (in_addr_t)) - return 0; - ; - return 0; -} -#endif - -#ifdef HAVE_BOOL_T -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_STDBOOL_H -#include -#endif -int -main () -{ -if (sizeof (bool *) ) - return 0; - ; - return 0; -} -#endif - -#ifdef STDC_HEADERS -#include -#include -#include -#include -int main() { return 0; } -#endif -#ifdef RETSIGTYPE_TEST -#include -#include -#ifdef signal -# undef signal -#endif -#ifdef __cplusplus -extern "C" void (*signal (int, void (*)(int)))(int); -#else -void (*signal ()) (); -#endif - -int -main () -{ - return 0; -} -#endif -#ifdef HAVE_INET_NTOA_R_DECL -#include - -typedef void (*func_type)(); - -int main() -{ -#ifndef inet_ntoa_r - func_type func; - func = (func_type)inet_ntoa_r; - (void)func; -#endif - return 0; -} -#endif -#ifdef HAVE_INET_NTOA_R_DECL_REENTRANT -#define _REENTRANT -#include - -typedef void (*func_type)(); - -int main() -{ -#ifndef inet_ntoa_r - func_type func; - func = (func_type)&inet_ntoa_r; - (void)func; -#endif - return 0; -} -#endif -#ifdef HAVE_GETADDRINFO -#include -#include -#include - -int main(void) { - struct addrinfo hints, *ai; - int error; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; -#ifndef getaddrinfo - (void)getaddrinfo; -#endif - error = getaddrinfo("127.0.0.1", "8080", &hints, &ai); - if (error) { - return 1; - } - return 0; -} -#endif -#ifdef HAVE_FILE_OFFSET_BITS -#ifdef _FILE_OFFSET_BITS -#undef _FILE_OFFSET_BITS -#endif -#define _FILE_OFFSET_BITS 64 -#include - /* Check that off_t can represent 2**63 - 1 correctly. - We can't simply define LARGE_OFF_T to be 9223372036854775807, - since some C++ compilers masquerading as C compilers - incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) - int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 - && LARGE_OFF_T % 2147483647 == 1) - ? 1 : -1]; -int main () { ; return 0; } -#endif -#ifdef HAVE_IOCTLSOCKET -/* includes start */ -#ifdef HAVE_WINDOWS_H -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# include -# ifdef HAVE_WINSOCK2_H -# include -# else -# ifdef HAVE_WINSOCK_H -# include -# endif -# endif -#endif - -int -main () -{ - -/* ioctlsocket source code */ - int socket; - unsigned long flags = ioctlsocket(socket, FIONBIO, &flags); - - ; - return 0; -} - -#endif -#ifdef HAVE_IOCTLSOCKET_CAMEL -/* includes start */ -#ifdef HAVE_WINDOWS_H -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# include -# ifdef HAVE_WINSOCK2_H -# include -# else -# ifdef HAVE_WINSOCK_H -# include -# endif -# endif -#endif - -int -main () -{ - -/* IoctlSocket source code */ - if(0 != IoctlSocket(0, 0, 0)) - return 1; - ; - return 0; -} -#endif -#ifdef HAVE_IOCTLSOCKET_CAMEL_FIONBIO -/* includes start */ -#ifdef HAVE_WINDOWS_H -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# include -# ifdef HAVE_WINSOCK2_H -# include -# else -# ifdef HAVE_WINSOCK_H -# include -# endif -# endif -#endif - -int -main () -{ - -/* IoctlSocket source code */ - long flags = 0; - if(0 != ioctlsocket(0, FIONBIO, &flags)) - return 1; - ; - return 0; -} -#endif -#ifdef HAVE_IOCTLSOCKET_FIONBIO -/* includes start */ -#ifdef HAVE_WINDOWS_H -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# include -# ifdef HAVE_WINSOCK2_H -# include -# else -# ifdef HAVE_WINSOCK_H -# include -# endif -# endif -#endif - -int -main () -{ - - int flags = 0; - if(0 != ioctlsocket(0, FIONBIO, &flags)) - return 1; - - ; - return 0; -} -#endif -#ifdef HAVE_IOCTL_FIONBIO -/* headers for FIONBIO test */ -/* includes start */ -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_SYS_IOCTL_H -# include -#endif -#ifdef HAVE_STROPTS_H -# include -#endif - -int -main () -{ - - int flags = 0; - if(0 != ioctl(0, FIONBIO, &flags)) - return 1; - - ; - return 0; -} -#endif -#ifdef HAVE_IOCTL_SIOCGIFADDR -/* headers for FIONBIO test */ -/* includes start */ -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_SYS_IOCTL_H -# include -#endif -#ifdef HAVE_STROPTS_H -# include -#endif -#include - -int -main () -{ - struct ifreq ifr; - if(0 != ioctl(0, SIOCGIFADDR, &ifr)) - return 1; - - ; - return 0; -} -#endif -#ifdef HAVE_SETSOCKOPT_SO_NONBLOCK -/* includes start */ -#ifdef HAVE_WINDOWS_H -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# include -# ifdef HAVE_WINSOCK2_H -# include -# else -# ifdef HAVE_WINSOCK_H -# include -# endif -# endif -#endif -/* includes start */ -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -/* includes end */ - -int -main () -{ - if(0 != setsockopt(0, SOL_SOCKET, SO_NONBLOCK, 0, 0)) - return 1; - ; - return 0; -} -#endif -#ifdef HAVE_GLIBC_STRERROR_R -#include -#include - -void check(char c) {} - -int -main () { - char buffer[1024]; - /* This will not compile if strerror_r does not return a char* */ - check(strerror_r(EACCES, buffer, sizeof(buffer))[0]); - return 0; -} -#endif -#ifdef HAVE_POSIX_STRERROR_R -#include -#include - -/* float, because a pointer can't be implicitly cast to float */ -void check(float f) {} - -int -main () { - char buffer[1024]; - /* This will not compile if strerror_r does not return an int */ - check(strerror_r(EACCES, buffer, sizeof(buffer))); - return 0; -} -#endif -#ifdef HAVE_FSETXATTR_6 -#include /* header from libc, not from libattr */ -int -main() { - fsetxattr(0, 0, 0, 0, 0, 0); - return 0; -} -#endif -#ifdef HAVE_FSETXATTR_5 -#include /* header from libc, not from libattr */ -int -main() { - fsetxattr(0, 0, 0, 0, 0); - return 0; -} -#endif -#ifdef HAVE_CLOCK_GETTIME_MONOTONIC -#include -int -main() { - struct timespec ts = {0, 0}; - clock_gettime(CLOCK_MONOTONIC, &ts); - return 0; -} -#endif -#ifdef HAVE_BUILTIN_AVAILABLE -int -main() { - if(__builtin_available(macOS 10.12, *)) {} - return 0; -} -#endif -#ifdef HAVE_VARIADIC_MACROS_C99 -#define c99_vmacro3(first, ...) fun3(first, __VA_ARGS__) -#define c99_vmacro2(first, ...) fun2(first, __VA_ARGS__) - -int fun3(int arg1, int arg2, int arg3); -int fun2(int arg1, int arg2); - -int fun3(int arg1, int arg2, int arg3) { - return arg1 + arg2 + arg3; -} -int fun2(int arg1, int arg2) { - return arg1 + arg2; -} - -int -main() { - int res3 = c99_vmacro3(1, 2, 3); - int res2 = c99_vmacro2(1, 2); - (void)res3; - (void)res2; - return 0; -} -#endif -#ifdef HAVE_VARIADIC_MACROS_GCC -#define gcc_vmacro3(first, args...) fun3(first, args) -#define gcc_vmacro2(first, args...) fun2(first, args) - -int fun3(int arg1, int arg2, int arg3); -int fun2(int arg1, int arg2); - -int fun3(int arg1, int arg2, int arg3) { - return arg1 + arg2 + arg3; -} -int fun2(int arg1, int arg2) { - return arg1 + arg2; -} - -int -main() { - int res3 = gcc_vmacro3(1, 2, 3); - int res2 = gcc_vmacro2(1, 2); - (void)res3; - (void)res2; - return 0; -} -#endif diff --git a/contrib/curl-cmake/CMake/Macros.cmake b/contrib/curl-cmake/CMake/Macros.cmake deleted file mode 100644 index 39a60b04df9..00000000000 --- a/contrib/curl-cmake/CMake/Macros.cmake +++ /dev/null @@ -1,84 +0,0 @@ -#File defines convenience macros for available feature testing - -# This macro checks if the symbol exists in the library and if it -# does, it prepends library to the list. It is intended to be called -# multiple times with a sequence of possibly dependent libraries in -# order of least-to-most-dependent. Some libraries depend on others -# to link correctly. -macro(check_library_exists_concat LIBRARY SYMBOL VARIABLE) - check_library_exists("${LIBRARY};${CURL_LIBS}" ${SYMBOL} "${CMAKE_LIBRARY_PATH}" - ${VARIABLE}) - if(${VARIABLE}) - set(CURL_LIBS ${LIBRARY} ${CURL_LIBS}) - endif() -endmacro() - -# Check if header file exists and add it to the list. -# This macro is intended to be called multiple times with a sequence of -# possibly dependent header files. Some headers depend on others to be -# compiled correctly. -macro(check_include_file_concat FILE VARIABLE) - check_include_files("${CURL_INCLUDES};${FILE}" ${VARIABLE}) - if(${VARIABLE}) - set(CURL_INCLUDES ${CURL_INCLUDES} ${FILE}) - set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D${VARIABLE}") - endif() -endmacro() - -# For other curl specific tests, use this macro. -macro(curl_internal_test CURL_TEST) - if(NOT DEFINED "${CURL_TEST}") - set(MACRO_CHECK_FUNCTION_DEFINITIONS - "-D${CURL_TEST} ${CURL_TEST_DEFINES} ${CMAKE_REQUIRED_FLAGS}") - if(CMAKE_REQUIRED_LIBRARIES) - set(CURL_TEST_ADD_LIBRARIES - "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") - endif() - - try_compile(${CURL_TEST} - ${CMAKE_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c - CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} - "${CURL_TEST_ADD_LIBRARIES}" - OUTPUT_VARIABLE OUTPUT) - if(${CURL_TEST}) - set(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}") - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Performing Curl Test ${CURL_TEST} passed with the following output:\n" - "${OUTPUT}\n") - else() - set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}") - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Performing Curl Test ${CURL_TEST} failed with the following output:\n" - "${OUTPUT}\n") - endif() - endif() -endmacro() - -macro(curl_nroff_check) - find_program(NROFF NAMES gnroff nroff) - if(NROFF) - # Need a way to write to stdin, this will do - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt" "test") - # Tests for a valid nroff option to generate a manpage - foreach(_MANOPT "-man" "-mandoc") - execute_process(COMMAND "${NROFF}" ${_MANOPT} - OUTPUT_VARIABLE NROFF_MANOPT_OUTPUT - INPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt" - ERROR_QUIET) - # Save the option if it was valid - if(NROFF_MANOPT_OUTPUT) - set(NROFF_MANOPT ${_MANOPT}) - set(NROFF_USEFUL ON) - break() - endif() - endforeach() - # No need for the temporary file - file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt") - if(NOT NROFF_USEFUL) - message(WARNING "Found no *nroff option to get plaintext from man pages") - endif() - else() - message(WARNING "Found no *nroff program") - endif() -endmacro() diff --git a/contrib/curl-cmake/CMake/OtherTests.cmake b/contrib/curl-cmake/CMake/OtherTests.cmake deleted file mode 100644 index 5ad70a62fb2..00000000000 --- a/contrib/curl-cmake/CMake/OtherTests.cmake +++ /dev/null @@ -1,260 +0,0 @@ -include(CheckCSourceCompiles) -# The begin of the sources (macros and includes) -set(_source_epilogue "#undef inline") - -macro(add_header_include check header) - if(${check}) - set(_source_epilogue "${_source_epilogue}\n#include <${header}>") - endif() -endmacro() - -set(signature_call_conv) -if(HAVE_WINDOWS_H) - add_header_include(HAVE_WINSOCK2_H "winsock2.h") - add_header_include(HAVE_WINDOWS_H "windows.h") - add_header_include(HAVE_WINSOCK_H "winsock.h") - set(_source_epilogue - "${_source_epilogue}\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif") - set(signature_call_conv "PASCAL") - if(HAVE_LIBWS2_32) - set(CMAKE_REQUIRED_LIBRARIES ws2_32) - endif() -else() - add_header_include(HAVE_SYS_TYPES_H "sys/types.h") - add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h") -endif() - -set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) - -check_c_source_compiles("${_source_epilogue} -int main(void) { - recv(0, 0, 0, 0); - return 0; -}" curl_cv_recv) -if(curl_cv_recv) - if(NOT DEFINED curl_cv_func_recv_args OR "${curl_cv_func_recv_args}" STREQUAL "unknown") - foreach(recv_retv "int" "ssize_t" ) - foreach(recv_arg1 "SOCKET" "int" ) - foreach(recv_arg2 "char *" "void *" ) - foreach(recv_arg3 "int" "size_t" "socklen_t" "unsigned int") - foreach(recv_arg4 "int" "unsigned int") - if(NOT curl_cv_func_recv_done) - unset(curl_cv_func_recv_test CACHE) - check_c_source_compiles(" - ${_source_epilogue} - extern ${recv_retv} ${signature_call_conv} - recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4}); - int main(void) { - ${recv_arg1} s=0; - ${recv_arg2} buf=0; - ${recv_arg3} len=0; - ${recv_arg4} flags=0; - ${recv_retv} res = recv(s, buf, len, flags); - (void) res; - return 0; - }" - curl_cv_func_recv_test) - if(curl_cv_func_recv_test) - set(curl_cv_func_recv_args - "${recv_arg1},${recv_arg2},${recv_arg3},${recv_arg4},${recv_retv}") - set(RECV_TYPE_ARG1 "${recv_arg1}") - set(RECV_TYPE_ARG2 "${recv_arg2}") - set(RECV_TYPE_ARG3 "${recv_arg3}") - set(RECV_TYPE_ARG4 "${recv_arg4}") - set(RECV_TYPE_RETV "${recv_retv}") - set(HAVE_RECV 1) - set(curl_cv_func_recv_done 1) - endif() - endif() - endforeach() - endforeach() - endforeach() - endforeach() - endforeach() - else() - string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG1 "${curl_cv_func_recv_args}") - string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG2 "${curl_cv_func_recv_args}") - string(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG3 "${curl_cv_func_recv_args}") - string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" RECV_TYPE_ARG4 "${curl_cv_func_recv_args}") - string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" RECV_TYPE_RETV "${curl_cv_func_recv_args}") - endif() - - if("${curl_cv_func_recv_args}" STREQUAL "unknown") - message(FATAL_ERROR "Cannot find proper types to use for recv args") - endif() -else() - message(FATAL_ERROR "Unable to link function recv") -endif() -set(curl_cv_func_recv_args "${curl_cv_func_recv_args}" CACHE INTERNAL "Arguments for recv") -set(HAVE_RECV 1) - -check_c_source_compiles("${_source_epilogue} -int main(void) { - send(0, 0, 0, 0); - return 0; -}" curl_cv_send) -if(curl_cv_send) - if(NOT DEFINED curl_cv_func_send_args OR "${curl_cv_func_send_args}" STREQUAL "unknown") - foreach(send_retv "int" "ssize_t" ) - foreach(send_arg1 "SOCKET" "int" "ssize_t" ) - foreach(send_arg2 "const char *" "const void *" "void *" "char *") - foreach(send_arg3 "int" "size_t" "socklen_t" "unsigned int") - foreach(send_arg4 "int" "unsigned int") - if(NOT curl_cv_func_send_done) - unset(curl_cv_func_send_test CACHE) - check_c_source_compiles(" - ${_source_epilogue} - extern ${send_retv} ${signature_call_conv} - send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4}); - int main(void) { - ${send_arg1} s=0; - ${send_arg2} buf=0; - ${send_arg3} len=0; - ${send_arg4} flags=0; - ${send_retv} res = send(s, buf, len, flags); - (void) res; - return 0; - }" - curl_cv_func_send_test) - if(curl_cv_func_send_test) - string(REGEX REPLACE "(const) .*" "\\1" send_qual_arg2 "${send_arg2}") - string(REGEX REPLACE "const (.*)" "\\1" send_arg2 "${send_arg2}") - set(curl_cv_func_send_args - "${send_arg1},${send_arg2},${send_arg3},${send_arg4},${send_retv},${send_qual_arg2}") - set(SEND_TYPE_ARG1 "${send_arg1}") - set(SEND_TYPE_ARG2 "${send_arg2}") - set(SEND_TYPE_ARG3 "${send_arg3}") - set(SEND_TYPE_ARG4 "${send_arg4}") - set(SEND_TYPE_RETV "${send_retv}") - set(HAVE_SEND 1) - set(curl_cv_func_send_done 1) - endif() - endif() - endforeach() - endforeach() - endforeach() - endforeach() - endforeach() - else() - string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG1 "${curl_cv_func_send_args}") - string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG2 "${curl_cv_func_send_args}") - string(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG3 "${curl_cv_func_send_args}") - string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG4 "${curl_cv_func_send_args}") - string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" SEND_TYPE_RETV "${curl_cv_func_send_args}") - string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" SEND_QUAL_ARG2 "${curl_cv_func_send_args}") - endif() - - if("${curl_cv_func_send_args}" STREQUAL "unknown") - message(FATAL_ERROR "Cannot find proper types to use for send args") - endif() - set(SEND_QUAL_ARG2 "const") -else() - message(FATAL_ERROR "Unable to link function send") -endif() -set(curl_cv_func_send_args "${curl_cv_func_send_args}" CACHE INTERNAL "Arguments for send") -set(HAVE_SEND 1) - -check_c_source_compiles("${_source_epilogue} - int main(void) { - int flag = MSG_NOSIGNAL; - (void)flag; - return 0; - }" HAVE_MSG_NOSIGNAL) - -if(NOT HAVE_WINDOWS_H) - add_header_include(HAVE_SYS_TIME_H "sys/time.h") - add_header_include(TIME_WITH_SYS_TIME "time.h") - add_header_include(HAVE_TIME_H "time.h") -endif() -check_c_source_compiles("${_source_epilogue} -int main(void) { - struct timeval ts; - ts.tv_sec = 0; - ts.tv_usec = 0; - (void)ts; - return 0; -}" HAVE_STRUCT_TIMEVAL) - -set(HAVE_SIG_ATOMIC_T 1) -set(CMAKE_REQUIRED_FLAGS) -if(HAVE_SIGNAL_H) - set(CMAKE_REQUIRED_FLAGS "-DHAVE_SIGNAL_H") - set(CMAKE_EXTRA_INCLUDE_FILES "signal.h") -endif() -check_type_size("sig_atomic_t" SIZEOF_SIG_ATOMIC_T) -if(HAVE_SIZEOF_SIG_ATOMIC_T) - check_c_source_compiles(" - #ifdef HAVE_SIGNAL_H - # include - #endif - int main(void) { - static volatile sig_atomic_t dummy = 0; - (void)dummy; - return 0; - }" HAVE_SIG_ATOMIC_T_NOT_VOLATILE) - if(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE) - set(HAVE_SIG_ATOMIC_T_VOLATILE 1) - endif() -endif() - -if(HAVE_WINDOWS_H) - set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h) -else() - set(CMAKE_EXTRA_INCLUDE_FILES) - if(HAVE_SYS_SOCKET_H) - set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h) - endif() -endif() - -check_type_size("struct sockaddr_storage" SIZEOF_STRUCT_SOCKADDR_STORAGE) -if(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE) - set(HAVE_STRUCT_SOCKADDR_STORAGE 1) -endif() - -unset(CMAKE_TRY_COMPILE_TARGET_TYPE) - -if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) - # if not cross-compilation... - include(CheckCSourceRuns) - set(CMAKE_REQUIRED_FLAGS "") - if(HAVE_SYS_POLL_H) - set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H") - elseif(HAVE_POLL_H) - set(CMAKE_REQUIRED_FLAGS "-DHAVE_POLL_H") - endif() - check_c_source_runs(" - #include - #include - - #ifdef HAVE_SYS_POLL_H - # include - #elif HAVE_POLL_H - # include - #endif - - int main(void) - { - if(0 != poll(0, 0, 10)) { - return 1; /* fail */ - } - else { - /* detect the 10.12 poll() breakage */ - struct timeval before, after; - int rc; - size_t us; - - gettimeofday(&before, NULL); - rc = poll(NULL, 0, 500); - gettimeofday(&after, NULL); - - us = (after.tv_sec - before.tv_sec) * 1000000 + - (after.tv_usec - before.tv_usec); - - if(us < 400000) { - return 1; - } - } - return 0; - }" HAVE_POLL_FINE) -endif() - diff --git a/contrib/curl-cmake/CMake/README.md b/contrib/curl-cmake/CMake/README.md deleted file mode 100644 index a96fe6849ed..00000000000 --- a/contrib/curl-cmake/CMake/README.md +++ /dev/null @@ -1,28 +0,0 @@ -#*************************************************************************** -# _ _ ____ _ -# Project ___| | | | _ \| | -# / __| | | | |_) | | -# | (__| |_| | _ <| |___ -# \___|\___/|_| \_\_____| -# -# Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. -# -# This software is licensed as described in the file COPYING, which -# you should have received as part of this distribution. The terms -# are also available at https://curl.haxx.se/docs/copyright.html. -# -# You may opt to use, copy, modify, merge, publish, distribute and/or sell -# copies of the Software, and permit persons to whom the Software is -# furnished to do so, under the terms of the COPYING file. -# -# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -# KIND, either express or implied. -# -########################################################################### - -CMake files under this directory were reused from project curl. -Here are links to original source files: -https://github.com/curl/curl/blob/master/CMake/CurlSymbolHiding.cmake -https://github.com/curl/curl/blob/master/CMake/CurlTests,c -https://github.com/curl/curl/blob/master/CMake/Macros.cmake -https://github.com/curl/curl/blob/master/CMake/OtherTests.cmake diff --git a/contrib/curl-cmake/CMakeLists.patch b/contrib/curl-cmake/CMakeLists.patch deleted file mode 100644 index 3b4ef3bf9ab..00000000000 --- a/contrib/curl-cmake/CMakeLists.patch +++ /dev/null @@ -1,1509 +0,0 @@ ---- ../curl/CMakeLists.txt 2019-12-09 13:33:38.140856959 +0300 -+++ CMakeLists.txt 2019-12-12 19:50:48.001094425 +0300 -@@ -19,220 +19,100 @@ - # KIND, either express or implied. - # - ########################################################################### --# curl/libcurl CMake script --# by Tetetest and Sukender (Benoit Neil) -- --# TODO: --# The output .so file lacks the soname number which we currently have within the lib/Makefile.am file --# Add full (4 or 5 libs) SSL support --# Add INSTALL target (EXTRA_DIST variables in Makefile.am may be moved to Makefile.inc so that CMake/CPack is aware of what's to include). --# Add CTests(?) --# Check on all possible platforms --# Test with as many configurations possible (With or without any option) --# Create scripts that help keeping the CMake build system up to date (to reduce maintenance). According to Tetetest: --# - lists of headers that 'configure' checks for; --# - curl-specific tests (the ones that are in m4/curl-*.m4 files); --# - (most obvious thing:) curl version numbers. --# Add documentation subproject --# --# To check: --# (From Daniel Stenberg) The cmake build selected to run gcc with -fPIC on my box while the plain configure script did not. --# (From Daniel Stenberg) The gcc command line use neither -g nor any -O options. As a developer, I also treasure our configure scripts's --enable-debug option that sets a long range of "picky" compiler options. -+# This file is mostly copy-pasted from original curl CMakeLists.txt - cmake_minimum_required(VERSION 3.0 FATAL_ERROR) -+ -+SET(CURL_SOURCE_DIR ${ClickHouse_SOURCE_DIR}/contrib/curl) -+SET(CURL_LIBRARY_DIR ${CURL_SOURCE_DIR}/lib) - set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}") --include(Utilities) - include(Macros) - include(CMakeDependentOption) - include(CheckCCompilerFlag) - --project(CURL C) -- --message(WARNING "the curl cmake build system is poorly maintained. Be aware") -- - file(READ ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS) - string(REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*" -- CURL_VERSION ${CURL_VERSION_H_CONTENTS}) -+ CURL_VERSION ${CURL_VERSION_H_CONTENTS}) - string(REGEX REPLACE "[^\"]+\"" "" CURL_VERSION ${CURL_VERSION}) - string(REGEX MATCH "#define LIBCURL_VERSION_NUM 0x[0-9a-fA-F]+" -- CURL_VERSION_NUM ${CURL_VERSION_H_CONTENTS}) -+ CURL_VERSION_NUM ${CURL_VERSION_H_CONTENTS}) - string(REGEX REPLACE "[^0]+0x" "" CURL_VERSION_NUM ${CURL_VERSION_NUM}) - -- --# Setup package meta-data --# SET(PACKAGE "curl") --message(STATUS "curl version=[${CURL_VERSION}]") --# SET(PACKAGE_TARNAME "curl") --# SET(PACKAGE_NAME "curl") --# SET(PACKAGE_VERSION "-") --# SET(PACKAGE_STRING "curl-") --# SET(PACKAGE_BUGREPORT "a suitable curl mailing list => https://curl.haxx.se/mail/") -+message(STATUS "Use curl version=[${CURL_VERSION}]") - set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}") - set(OS "\"${CMAKE_SYSTEM_NAME}\"") - --include_directories(${CURL_SOURCE_DIR}/include) -- --option(CURL_WERROR "Turn compiler warnings into errors" OFF) - option(PICKY_COMPILER "Enable picky compiler options" ON) --option(BUILD_CURL_EXE "Set to ON to build curl executable." ON) --option(BUILD_SHARED_LIBS "Build shared libraries" ON) --option(ENABLE_ARES "Set to ON to enable c-ares support" OFF) --if(WIN32) -- option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF) -- option(ENABLE_INET_PTON "Set to OFF to prevent usage of inet_pton when building against modern SDKs while still requiring compatibility with older Windows versions, such as Windows XP, Windows Server 2003 etc." ON) --endif() -- --cmake_dependent_option(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded DNS lookup" -- ON "NOT ENABLE_ARES" -- OFF) -- --option(ENABLE_DEBUG "Set to ON to enable curl debug features" OFF) --option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" OFF) -+option(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded DNS lookup" ON) - - if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) -- if(PICKY_COMPILER) -- foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wvla -Wdouble-promotion -Wno-system-headers -Wno-pedantic-ms-format) -- # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new -- # test result in. -- check_c_compiler_flag(${_CCOPT} OPT${_CCOPT}) -- if(OPT${_CCOPT}) -- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}") -- endif() -- endforeach() -- endif() --endif() -- --if(ENABLE_DEBUG) -- # DEBUGBUILD will be defined only for Debug builds -- set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$:DEBUGBUILD>) -- set(ENABLE_CURLDEBUG ON) --endif() -- --if(ENABLE_CURLDEBUG) -- set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS CURLDEBUG) -+ if(PICKY_COMPILER) -+ foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wvla -Wdouble-promotion -Wno-system-headers -Wno-pedantic-ms-format) -+ # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new -+ # test result in. -+ check_c_compiler_flag(${_CCOPT} OPT${_CCOPT}) -+ if(OPT${_CCOPT}) -+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}") -+ endif() -+ endforeach() -+ endif() - endif() - - # For debug libs and exes, add "-d" postfix - if(NOT DEFINED CMAKE_DEBUG_POSTFIX) -- set(CMAKE_DEBUG_POSTFIX "-d") -+ set(CMAKE_DEBUG_POSTFIX "-d") - endif() - - # initialize CURL_LIBS - set(CURL_LIBS "") - --if(ENABLE_ARES) -- set(USE_ARES 1) -- find_package(CARES REQUIRED) -- list(APPEND CURL_LIBS ${CARES_LIBRARY}) -- set(CURL_LIBS ${CURL_LIBS} ${CARES_LIBRARY}) --endif() -- - include(CurlSymbolHiding) - --option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" OFF) --mark_as_advanced(HTTP_ONLY) --option(CURL_DISABLE_FTP "disables FTP" OFF) --mark_as_advanced(CURL_DISABLE_FTP) --option(CURL_DISABLE_LDAP "disables LDAP" OFF) --mark_as_advanced(CURL_DISABLE_LDAP) --option(CURL_DISABLE_TELNET "disables Telnet" OFF) --mark_as_advanced(CURL_DISABLE_TELNET) --option(CURL_DISABLE_DICT "disables DICT" OFF) --mark_as_advanced(CURL_DISABLE_DICT) --option(CURL_DISABLE_FILE "disables FILE" OFF) --mark_as_advanced(CURL_DISABLE_FILE) --option(CURL_DISABLE_TFTP "disables TFTP" OFF) --mark_as_advanced(CURL_DISABLE_TFTP) --option(CURL_DISABLE_HTTP "disables HTTP" OFF) --mark_as_advanced(CURL_DISABLE_HTTP) -- --option(CURL_DISABLE_LDAPS "to disable LDAPS" OFF) --mark_as_advanced(CURL_DISABLE_LDAPS) -- --option(CURL_DISABLE_RTSP "to disable RTSP" OFF) --mark_as_advanced(CURL_DISABLE_RTSP) --option(CURL_DISABLE_PROXY "to disable proxy" OFF) --mark_as_advanced(CURL_DISABLE_PROXY) --option(CURL_DISABLE_POP3 "to disable POP3" OFF) --mark_as_advanced(CURL_DISABLE_POP3) --option(CURL_DISABLE_IMAP "to disable IMAP" OFF) --mark_as_advanced(CURL_DISABLE_IMAP) --option(CURL_DISABLE_SMTP "to disable SMTP" OFF) --mark_as_advanced(CURL_DISABLE_SMTP) --option(CURL_DISABLE_GOPHER "to disable Gopher" OFF) --mark_as_advanced(CURL_DISABLE_GOPHER) -- --if(HTTP_ONLY) -- set(CURL_DISABLE_FTP ON) -- set(CURL_DISABLE_LDAP ON) -- set(CURL_DISABLE_LDAPS ON) -- set(CURL_DISABLE_TELNET ON) -- set(CURL_DISABLE_DICT ON) -- set(CURL_DISABLE_FILE ON) -- set(CURL_DISABLE_TFTP ON) -- set(CURL_DISABLE_RTSP ON) -- set(CURL_DISABLE_POP3 ON) -- set(CURL_DISABLE_IMAP ON) -- set(CURL_DISABLE_SMTP ON) -- set(CURL_DISABLE_GOPHER ON) --endif() -+# Http only -+set(CURL_DISABLE_FTP ON) -+set(CURL_DISABLE_LDAP ON) -+set(CURL_DISABLE_LDAPS ON) -+set(CURL_DISABLE_TELNET ON) -+set(CURL_DISABLE_DICT ON) -+set(CURL_DISABLE_FILE ON) -+set(CURL_DISABLE_TFTP ON) -+set(CURL_DISABLE_RTSP ON) -+set(CURL_DISABLE_POP3 ON) -+set(CURL_DISABLE_IMAP ON) -+set(CURL_DISABLE_SMTP ON) -+set(CURL_DISABLE_GOPHER ON) - - option(CURL_DISABLE_COOKIES "to disable cookies support" OFF) - mark_as_advanced(CURL_DISABLE_COOKIES) - - option(CURL_DISABLE_CRYPTO_AUTH "to disable cryptographic authentication" OFF) - mark_as_advanced(CURL_DISABLE_CRYPTO_AUTH) -+ - option(CURL_DISABLE_VERBOSE_STRINGS "to disable verbose strings" OFF) - mark_as_advanced(CURL_DISABLE_VERBOSE_STRINGS) -+ - option(ENABLE_IPV6 "Define if you want to enable IPv6 support" ON) - mark_as_advanced(ENABLE_IPV6) -+ - if(ENABLE_IPV6 AND NOT WIN32) -- include(CheckStructHasMember) -- check_struct_has_member("struct sockaddr_in6" sin6_addr "netinet/in.h" -- HAVE_SOCKADDR_IN6_SIN6_ADDR) -- check_struct_has_member("struct sockaddr_in6" sin6_scope_id "netinet/in.h" -- HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) -- if(NOT HAVE_SOCKADDR_IN6_SIN6_ADDR) -- message(WARNING "struct sockaddr_in6 not available, disabling IPv6 support") -- # Force the feature off as this name is used as guard macro... -- set(ENABLE_IPV6 OFF -- CACHE BOOL "Define if you want to enable IPv6 support" FORCE) -- endif() -+ include(CheckStructHasMember) -+ check_struct_has_member("struct sockaddr_in6" sin6_addr "netinet/in.h" -+ HAVE_SOCKADDR_IN6_SIN6_ADDR) -+ check_struct_has_member("struct sockaddr_in6" sin6_scope_id "netinet/in.h" -+ HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) -+ if(NOT HAVE_SOCKADDR_IN6_SIN6_ADDR) -+ message(WARNING "struct sockaddr_in6 not available, disabling IPv6 support") -+ # Force the feature off as this name is used as guard macro... -+ set(ENABLE_IPV6 OFF -+ CACHE BOOL "Define if you want to enable IPv6 support" FORCE) -+ endif() - endif() - - curl_nroff_check() --find_package(Perl) -- --cmake_dependent_option(ENABLE_MANUAL "to provide the built-in manual" -- ON "NROFF_USEFUL;PERL_FOUND" -- OFF) -- --if(NOT PERL_FOUND) -- message(STATUS "Perl not found, testing disabled.") -- set(BUILD_TESTING OFF) --endif() --if(ENABLE_MANUAL) -- set(USE_MANUAL ON) --endif() - - # We need ansi c-flags, especially on HP - set(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}") - set(CMAKE_REQUIRED_FLAGS ${CMAKE_ANSI_CFLAGS}) - --if(CURL_STATIC_CRT) -- set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT") -- set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd") --endif() -- --# Disable warnings on Borland to avoid changing 3rd party code. --if(BORLAND) -- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-") --endif() -- --# If we are on AIX, do the _ALL_SOURCE magic --if(${CMAKE_SYSTEM_NAME} MATCHES AIX) -- set(_ALL_SOURCE 1) --endif() -- - # Include all the necessary files for macros - include(CheckFunctionExists) - include(CheckIncludeFile) -@@ -242,21 +122,15 @@ - include(CheckTypeSize) - include(CheckCSourceCompiles) - --# On windows preload settings --if(WIN32) -- set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_=") -- include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake) --endif() -- - if(ENABLE_THREADED_RESOLVER) -- find_package(Threads REQUIRED) -- if(WIN32) -- set(USE_THREADS_WIN32 ON) -- else() -- set(USE_THREADS_POSIX ${CMAKE_USE_PTHREADS_INIT}) -- set(HAVE_PTHREAD_H ${CMAKE_USE_PTHREADS_INIT}) -- endif() -- set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT}) -+ find_package(Threads REQUIRED) -+ if(WIN32) -+ set(USE_THREADS_WIN32 ON) -+ else() -+ set(USE_THREADS_POSIX ${CMAKE_USE_PTHREADS_INIT}) -+ set(HAVE_PTHREAD_H ${CMAKE_USE_PTHREADS_INIT}) -+ endif() -+ set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT}) - endif() - - # Check for all needed libraries -@@ -264,245 +138,24 @@ - check_library_exists_concat("socket" connect HAVE_LIBSOCKET) - check_library_exists("c" gethostbyname "" NOT_NEED_LIBNSL) - --# Yellowtab Zeta needs different libraries than BeOS 5. --if(BEOS) -- set(NOT_NEED_LIBNSL 1) -- check_library_exists_concat("bind" gethostbyname HAVE_LIBBIND) -- check_library_exists_concat("bnetapi" closesocket HAVE_LIBBNETAPI) --endif() -- --if(NOT NOT_NEED_LIBNSL) -- check_library_exists_concat("nsl" gethostbyname HAVE_LIBNSL) --endif() -- - check_function_exists(gethostname HAVE_GETHOSTNAME) - --if(WIN32) -- check_library_exists_concat("ws2_32" getch HAVE_LIBWS2_32) -- check_library_exists_concat("winmm" getch HAVE_LIBWINMM) -- list(APPEND CURL_LIBS "advapi32") --endif() -- --# check SSL libraries --# TODO support GNUTLS, NSS, POLARSSL, CYASSL -- --if(APPLE) -- option(CMAKE_USE_SECTRANSP "enable Apple OS native SSL/TLS" OFF) --endif() --if(WIN32) -- option(CMAKE_USE_WINSSL "enable Windows native SSL/TLS" OFF) -- cmake_dependent_option(CURL_WINDOWS_SSPI "Use windows libraries to allow NTLM authentication without openssl" ON -- CMAKE_USE_WINSSL OFF) --endif() --option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF) --option(CMAKE_USE_BEARSSL "Enable BearSSL for SSL/TLS" OFF) -- --set(openssl_default ON) --if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS) -- set(openssl_default OFF) --endif() --option(CMAKE_USE_OPENSSL "Use OpenSSL code. Experimental" ${openssl_default}) -- --count_true(enabled_ssl_options_count -- CMAKE_USE_WINSSL -- CMAKE_USE_SECTRANSP -- CMAKE_USE_OPENSSL -- CMAKE_USE_MBEDTLS -- CMAKE_USE_BEARSSL --) --if(enabled_ssl_options_count GREATER "1") -- set(CURL_WITH_MULTI_SSL ON) --endif() -- --if(CMAKE_USE_WINSSL) -- set(SSL_ENABLED ON) -- set(USE_SCHANNEL ON) # Windows native SSL/TLS support -- set(USE_WINDOWS_SSPI ON) # CMAKE_USE_WINSSL implies CURL_WINDOWS_SSPI -- list(APPEND CURL_LIBS "crypt32") --endif() --if(CURL_WINDOWS_SSPI) -- set(USE_WINDOWS_SSPI ON) -- set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DSECURITY_WIN32") --endif() -+# From cmake/find/ssl.cmake -+if (OPENSSL_FOUND) -+ set(SSL_ENABLED ON) -+ set(USE_OPENSSL ON) - --if(CMAKE_USE_DARWINSSL) -- message(FATAL_ERROR "The cmake option CMAKE_USE_DARWINSSL was renamed to CMAKE_USE_SECTRANSP.") --endif() -- --if(CMAKE_USE_SECTRANSP) -- find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation") -- if(NOT COREFOUNDATION_FRAMEWORK) -- message(FATAL_ERROR "CoreFoundation framework not found") -- endif() -- -- find_library(SECURITY_FRAMEWORK "Security") -- if(NOT SECURITY_FRAMEWORK) -- message(FATAL_ERROR "Security framework not found") -- endif() -- -- set(SSL_ENABLED ON) -- set(USE_SECTRANSP ON) -- list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}") --endif() -- --if(CMAKE_USE_OPENSSL) -- find_package(OpenSSL REQUIRED) -- set(SSL_ENABLED ON) -- set(USE_OPENSSL ON) -- -- # Depend on OpenSSL via imported targets if supported by the running -- # version of CMake. This allows our dependents to get our dependencies -- # transitively. -- if(NOT CMAKE_VERSION VERSION_LESS 3.4) -- list(APPEND CURL_LIBS OpenSSL::SSL OpenSSL::Crypto) -- else() - list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES}) -- include_directories(${OPENSSL_INCLUDE_DIR}) -- endif() -- -- set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) -- check_include_file("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H) -- check_include_file("openssl/err.h" HAVE_OPENSSL_ERR_H) -- check_include_file("openssl/pem.h" HAVE_OPENSSL_PEM_H) -- check_include_file("openssl/rsa.h" HAVE_OPENSSL_RSA_H) -- check_include_file("openssl/ssl.h" HAVE_OPENSSL_SSL_H) -- check_include_file("openssl/x509.h" HAVE_OPENSSL_X509_H) -- check_include_file("openssl/rand.h" HAVE_OPENSSL_RAND_H) -- check_symbol_exists(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS) -- check_symbol_exists(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN) -- check_symbol_exists(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD) --endif() -- --if(CMAKE_USE_MBEDTLS) -- find_package(MbedTLS REQUIRED) -- set(SSL_ENABLED ON) -- set(USE_MBEDTLS ON) -- list(APPEND CURL_LIBS ${MBEDTLS_LIBRARIES}) -- include_directories(${MBEDTLS_INCLUDE_DIRS}) --endif() -- --if(CMAKE_USE_BEARSSL) -- find_package(BearSSL REQUIRED) -- set(SSL_ENABLED ON) -- set(USE_BEARSSL ON) -- list(APPEND CURL_LIBS ${BEARSSL_LIBRARY}) -- include_directories(${BEARSSL_INCLUDE_DIRS}) --endif() -- --option(USE_NGHTTP2 "Use Nghttp2 library" OFF) --if(USE_NGHTTP2) -- find_package(NGHTTP2 REQUIRED) -- include_directories(${NGHTTP2_INCLUDE_DIRS}) -- list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES}) --endif() -- --if(NOT CURL_DISABLE_LDAP) -- if(WIN32) -- option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON) -- if(USE_WIN32_LDAP) -- check_library_exists_concat("wldap32" cldap_open HAVE_WLDAP32) -- if(NOT HAVE_WLDAP32) -- set(USE_WIN32_LDAP OFF) -- endif() -- endif() -- endif() -- -- option(CMAKE_USE_OPENLDAP "Use OpenLDAP code." OFF) -- mark_as_advanced(CMAKE_USE_OPENLDAP) -- set(CMAKE_LDAP_LIB "ldap" CACHE STRING "Name or full path to ldap library") -- set(CMAKE_LBER_LIB "lber" CACHE STRING "Name or full path to lber library") -- -- if(CMAKE_USE_OPENLDAP AND USE_WIN32_LDAP) -- message(FATAL_ERROR "Cannot use USE_WIN32_LDAP and CMAKE_USE_OPENLDAP at the same time") -- endif() -- -- # Now that we know, we're not using windows LDAP... -- if(USE_WIN32_LDAP) -- check_include_file_concat("winldap.h" HAVE_WINLDAP_H) -- check_include_file_concat("winber.h" HAVE_WINBER_H) -- else() -- # Check for LDAP -- set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES}) -- check_library_exists_concat(${CMAKE_LDAP_LIB} ldap_init HAVE_LIBLDAP) -- check_library_exists_concat(${CMAKE_LBER_LIB} ber_init HAVE_LIBLBER) -- -- set(CMAKE_REQUIRED_INCLUDES_BAK ${CMAKE_REQUIRED_INCLUDES}) -- set(CMAKE_LDAP_INCLUDE_DIR "" CACHE STRING "Path to LDAP include directory") -- if(CMAKE_LDAP_INCLUDE_DIR) -- list(APPEND CMAKE_REQUIRED_INCLUDES ${CMAKE_LDAP_INCLUDE_DIR}) -- endif() -- check_include_file_concat("ldap.h" HAVE_LDAP_H) -- check_include_file_concat("lber.h" HAVE_LBER_H) -- -- if(NOT HAVE_LDAP_H) -- message(STATUS "LDAP_H not found CURL_DISABLE_LDAP set ON") -- set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE) -- set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_BAK}) #LDAP includes won't be used -- elseif(NOT HAVE_LIBLDAP) -- message(STATUS "LDAP library '${CMAKE_LDAP_LIB}' not found CURL_DISABLE_LDAP set ON") -- set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE) -- set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_BAK}) #LDAP includes won't be used -- else() -- if(CMAKE_USE_OPENLDAP) -- set(USE_OPENLDAP ON) -- endif() -- if(CMAKE_LDAP_INCLUDE_DIR) -- include_directories(${CMAKE_LDAP_INCLUDE_DIR}) -- endif() -- set(NEED_LBER_H ON) -- set(_HEADER_LIST) -- if(HAVE_WINDOWS_H) -- list(APPEND _HEADER_LIST "windows.h") -- endif() -- if(HAVE_SYS_TYPES_H) -- list(APPEND _HEADER_LIST "sys/types.h") -- endif() -- list(APPEND _HEADER_LIST "ldap.h") -- -- set(_SRC_STRING "") -- foreach(_HEADER ${_HEADER_LIST}) -- set(_INCLUDE_STRING "${_INCLUDE_STRING}#include <${_HEADER}>\n") -- endforeach() -- -- set(_SRC_STRING -- " -- ${_INCLUDE_STRING} -- int main(int argc, char ** argv) -- { -- BerValue *bvp = NULL; -- BerElement *bep = ber_init(bvp); -- ber_free(bep, 1); -- return 0; -- }" -- ) -- set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DLDAP_DEPRECATED=1") -- list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LDAP_LIB}) -- if(HAVE_LIBLBER) -- list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB}) -- endif() -- check_c_source_compiles("${_SRC_STRING}" NOT_NEED_LBER_H) -- unset(CMAKE_REQUIRED_LIBRARIES) -- -- if(NOT_NEED_LBER_H) -- set(NEED_LBER_H OFF) -- else() -- set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DNEED_LBER_H") -- endif() -- endif() -- endif() --endif() -- --# No ldap, no ldaps. --if(CURL_DISABLE_LDAP) -- if(NOT CURL_DISABLE_LDAPS) -- message(STATUS "LDAP needs to be enabled to support LDAPS") -- set(CURL_DISABLE_LDAPS ON CACHE BOOL "" FORCE) -- endif() --endif() -- --if(NOT CURL_DISABLE_LDAPS) -- check_include_file_concat("ldap_ssl.h" HAVE_LDAP_SSL_H) -- check_include_file_concat("ldapssl.h" HAVE_LDAPSSL_H) -+ check_include_file("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H) -+ check_include_file("openssl/err.h" HAVE_OPENSSL_ERR_H) -+ check_include_file("openssl/pem.h" HAVE_OPENSSL_PEM_H) -+ check_include_file("openssl/rsa.h" HAVE_OPENSSL_RSA_H) -+ check_include_file("openssl/ssl.h" HAVE_OPENSSL_SSL_H) -+ check_include_file("openssl/x509.h" HAVE_OPENSSL_X509_H) -+ check_include_file("openssl/rand.h" HAVE_OPENSSL_RAND_H) -+ check_symbol_exists(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS) -+ check_symbol_exists(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN) -+ check_symbol_exists(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD) - endif() - - # Check for idn -@@ -511,224 +164,30 @@ - # Check for symbol dlopen (same as HAVE_LIBDL) - check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN) - --option(CURL_ZLIB "Set to ON to enable building curl with zlib support." ON) --set(HAVE_LIBZ OFF) --set(HAVE_ZLIB_H OFF) --set(USE_ZLIB OFF) --if(CURL_ZLIB) -- find_package(ZLIB QUIET) -- if(ZLIB_FOUND) -+# From /cmake/find/zlib.cmake -+if (ZLIB_FOUND) - set(HAVE_ZLIB_H ON) - set(HAVE_LIBZ ON) - set(USE_ZLIB ON) - -- # Depend on ZLIB via imported targets if supported by the running -- # version of CMake. This allows our dependents to get our dependencies -- # transitively. -- if(NOT CMAKE_VERSION VERSION_LESS 3.4) -- list(APPEND CURL_LIBS ZLIB::ZLIB) -- else() -- list(APPEND CURL_LIBS ${ZLIB_LIBRARIES}) -- include_directories(${ZLIB_INCLUDE_DIRS}) -- endif() -- list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS}) -- endif() --endif() -- --option(CURL_BROTLI "Set to ON to enable building curl with brotli support." OFF) --set(HAVE_BROTLI OFF) --if(CURL_BROTLI) -- find_package(Brotli QUIET) -- if(BROTLI_FOUND) -- set(HAVE_BROTLI ON) -- list(APPEND CURL_LIBS ${BROTLI_LIBRARIES}) -- include_directories(${BROTLI_INCLUDE_DIRS}) -- list(APPEND CMAKE_REQUIRED_INCLUDES ${BROTLI_INCLUDE_DIRS}) -- endif() --endif() -- --#libSSH2 --option(CMAKE_USE_LIBSSH2 "Use libSSH2" ON) --mark_as_advanced(CMAKE_USE_LIBSSH2) --set(USE_LIBSSH2 OFF) --set(HAVE_LIBSSH2 OFF) --set(HAVE_LIBSSH2_H OFF) -- --if(CMAKE_USE_LIBSSH2) -- find_package(LibSSH2) -- if(LIBSSH2_FOUND) -- list(APPEND CURL_LIBS ${LIBSSH2_LIBRARY}) -- set(CMAKE_REQUIRED_LIBRARIES ${LIBSSH2_LIBRARY}) -- list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBSSH2_INCLUDE_DIR}") -- include_directories("${LIBSSH2_INCLUDE_DIR}") -- set(HAVE_LIBSSH2 ON) -- set(USE_LIBSSH2 ON) -- -- # find_package has already found the headers -- set(HAVE_LIBSSH2_H ON) -- set(CURL_INCLUDES ${CURL_INCLUDES} "${LIBSSH2_INCLUDE_DIR}/libssh2.h") -- set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DHAVE_LIBSSH2_H") -- -- # now check for specific libssh2 symbols as they were added in different versions -- set(CMAKE_EXTRA_INCLUDE_FILES "libssh2.h") -- check_function_exists(libssh2_version HAVE_LIBSSH2_VERSION) -- check_function_exists(libssh2_init HAVE_LIBSSH2_INIT) -- check_function_exists(libssh2_exit HAVE_LIBSSH2_EXIT) -- check_function_exists(libssh2_scp_send64 HAVE_LIBSSH2_SCP_SEND64) -- check_function_exists(libssh2_session_handshake HAVE_LIBSSH2_SESSION_HANDSHAKE) -- set(CMAKE_EXTRA_INCLUDE_FILES "") -- unset(CMAKE_REQUIRED_LIBRARIES) -- endif() --endif() -- --option(CMAKE_USE_GSSAPI "Use GSSAPI implementation (right now only Heimdal is supported with CMake build)" OFF) --mark_as_advanced(CMAKE_USE_GSSAPI) -- --if(CMAKE_USE_GSSAPI) -- find_package(GSS) -- -- set(HAVE_GSSAPI ${GSS_FOUND}) -- if(GSS_FOUND) -- -- message(STATUS "Found ${GSS_FLAVOUR} GSSAPI version: \"${GSS_VERSION}\"") -- -- list(APPEND CMAKE_REQUIRED_INCLUDES ${GSS_INCLUDE_DIR}) -- check_include_file_concat("gssapi/gssapi.h" HAVE_GSSAPI_GSSAPI_H) -- check_include_file_concat("gssapi/gssapi_generic.h" HAVE_GSSAPI_GSSAPI_GENERIC_H) -- check_include_file_concat("gssapi/gssapi_krb5.h" HAVE_GSSAPI_GSSAPI_KRB5_H) -- -- if(GSS_FLAVOUR STREQUAL "Heimdal") -- set(HAVE_GSSHEIMDAL ON) -- else() # MIT -- set(HAVE_GSSMIT ON) -- set(_INCLUDE_LIST "") -- if(HAVE_GSSAPI_GSSAPI_H) -- list(APPEND _INCLUDE_LIST "gssapi/gssapi.h") -- endif() -- if(HAVE_GSSAPI_GSSAPI_GENERIC_H) -- list(APPEND _INCLUDE_LIST "gssapi/gssapi_generic.h") -- endif() -- if(HAVE_GSSAPI_GSSAPI_KRB5_H) -- list(APPEND _INCLUDE_LIST "gssapi/gssapi_krb5.h") -- endif() -- -- string(REPLACE ";" " " _COMPILER_FLAGS_STR "${GSS_COMPILER_FLAGS}") -- string(REPLACE ";" " " _LINKER_FLAGS_STR "${GSS_LINKER_FLAGS}") -- -- foreach(_dir ${GSS_LINK_DIRECTORIES}) -- set(_LINKER_FLAGS_STR "${_LINKER_FLAGS_STR} -L\"${_dir}\"") -- endforeach() -- -- set(CMAKE_REQUIRED_FLAGS "${_COMPILER_FLAGS_STR} ${_LINKER_FLAGS_STR}") -- set(CMAKE_REQUIRED_LIBRARIES ${GSS_LIBRARIES}) -- check_symbol_exists("GSS_C_NT_HOSTBASED_SERVICE" ${_INCLUDE_LIST} HAVE_GSS_C_NT_HOSTBASED_SERVICE) -- if(NOT HAVE_GSS_C_NT_HOSTBASED_SERVICE) -- set(HAVE_OLD_GSSMIT ON) -- endif() -- unset(CMAKE_REQUIRED_LIBRARIES) -- -- endif() -- -- include_directories(${GSS_INCLUDE_DIR}) -- link_directories(${GSS_LINK_DIRECTORIES}) -- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_COMPILER_FLAGS}") -- set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GSS_LINKER_FLAGS}") -- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GSS_LINKER_FLAGS}") -- list(APPEND CURL_LIBS ${GSS_LIBRARIES}) -- -- else() -- message(WARNING "GSSAPI support has been requested but no supporting libraries found. Skipping.") -- endif() -+ list(APPEND CURL_LIBS ${ZLIB_LIBRARIES}) - endif() - - option(ENABLE_UNIX_SOCKETS "Define if you want Unix domain sockets support" ON) - if(ENABLE_UNIX_SOCKETS) -- include(CheckStructHasMember) -- check_struct_has_member("struct sockaddr_un" sun_path "sys/un.h" USE_UNIX_SOCKETS) -+ include(CheckStructHasMember) -+ check_struct_has_member("struct sockaddr_un" sun_path "sys/un.h" USE_UNIX_SOCKETS) - else() -- unset(USE_UNIX_SOCKETS CACHE) -+ unset(USE_UNIX_SOCKETS CACHE) - endif() - --# - # CA handling --# --set(CURL_CA_BUNDLE "auto" CACHE STRING -- "Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.") --set(CURL_CA_FALLBACK OFF CACHE BOOL -- "Set ON to use built-in CA store of TLS backend. Defaults to OFF") --set(CURL_CA_PATH "auto" CACHE STRING -- "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.") -- --if("${CURL_CA_BUNDLE}" STREQUAL "") -- message(FATAL_ERROR "Invalid value of CURL_CA_BUNDLE. Use 'none', 'auto' or file path.") --elseif("${CURL_CA_BUNDLE}" STREQUAL "none") -- unset(CURL_CA_BUNDLE CACHE) --elseif("${CURL_CA_BUNDLE}" STREQUAL "auto") -- unset(CURL_CA_BUNDLE CACHE) -- set(CURL_CA_BUNDLE_AUTODETECT TRUE) --else() -- set(CURL_CA_BUNDLE_SET TRUE) --endif() -- --if("${CURL_CA_PATH}" STREQUAL "") -- message(FATAL_ERROR "Invalid value of CURL_CA_PATH. Use 'none', 'auto' or directory path.") --elseif("${CURL_CA_PATH}" STREQUAL "none") -- unset(CURL_CA_PATH CACHE) --elseif("${CURL_CA_PATH}" STREQUAL "auto") -- unset(CURL_CA_PATH CACHE) -- set(CURL_CA_PATH_AUTODETECT TRUE) --else() -- set(CURL_CA_PATH_SET TRUE) --endif() -- --if(CURL_CA_BUNDLE_SET AND CURL_CA_PATH_AUTODETECT) -- # Skip autodetection of unset CA path because CA bundle is set explicitly --elseif(CURL_CA_PATH_SET AND CURL_CA_BUNDLE_AUTODETECT) -- # Skip autodetection of unset CA bundle because CA path is set explicitly --elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT) -- # first try autodetecting a CA bundle, then a CA path -- -- if(CURL_CA_BUNDLE_AUTODETECT) -- set(SEARCH_CA_BUNDLE_PATHS -- /etc/ssl/certs/ca-certificates.crt -- /etc/pki/tls/certs/ca-bundle.crt -- /usr/share/ssl/certs/ca-bundle.crt -- /usr/local/share/certs/ca-root-nss.crt -- /etc/ssl/cert.pem) -- -- foreach(SEARCH_CA_BUNDLE_PATH ${SEARCH_CA_BUNDLE_PATHS}) -- if(EXISTS "${SEARCH_CA_BUNDLE_PATH}") -- message(STATUS "Found CA bundle: ${SEARCH_CA_BUNDLE_PATH}") -- set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}") -- set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set") -- break() -- endif() -- endforeach() -- endif() -- -- if(CURL_CA_PATH_AUTODETECT AND (NOT CURL_CA_PATH_SET)) -- if(EXISTS "/etc/ssl/certs") -- set(CURL_CA_PATH "/etc/ssl/certs") -- set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set") -- endif() -- endif() --endif() -- --if(CURL_CA_PATH_SET AND NOT USE_OPENSSL AND NOT USE_MBEDTLS) -- message(FATAL_ERROR -- "CA path only supported by OpenSSL, GnuTLS or mbed TLS. " -- "Set CURL_CA_PATH=none or enable one of those TLS backends.") --endif() -- --# Check for header files --if(NOT UNIX) -- check_include_file_concat("windows.h" HAVE_WINDOWS_H) -- check_include_file_concat("winsock.h" HAVE_WINSOCK_H) -- check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H) -- check_include_file_concat("winsock2.h" HAVE_WINSOCK2_H) -- if(NOT CURL_WINDOWS_SSPI AND USE_OPENSSL) -- set(CURL_LIBS ${CURL_LIBS} "crypt32") -- endif() -+# Explicitly set to most common case -+if (OPENSSL_FOUND) -+ set(CURL_CA_BUNDLE "/etc/ssl/certs/ca-certificates.crt") -+ set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set") -+ set(CURL_CA_PATH "/etc/ssl/certs") -+ set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set") - endif() - - check_include_file_concat("stdio.h" HAVE_STDIO_H) -@@ -810,18 +269,18 @@ - check_type_size("long double" SIZEOF_LONG_DOUBLE) - check_type_size("time_t" SIZEOF_TIME_T) - if(NOT HAVE_SIZEOF_SSIZE_T) -- if(SIZEOF_LONG EQUAL SIZEOF_SIZE_T) -- set(ssize_t long) -- endif() -- if(NOT ssize_t AND SIZEOF___INT64 EQUAL SIZEOF_SIZE_T) -- set(ssize_t __int64) -- endif() -+ if(SIZEOF_LONG EQUAL SIZEOF_SIZE_T) -+ set(ssize_t long) -+ endif() -+ if(NOT ssize_t AND SIZEOF___INT64 EQUAL SIZEOF_SIZE_T) -+ set(ssize_t __int64) -+ endif() - endif() - # off_t is sized later, after the HAVE_FILE_OFFSET_BITS test - - if(HAVE_SIZEOF_LONG_LONG) -- set(HAVE_LONGLONG 1) -- set(HAVE_LL 1) -+ set(HAVE_LONGLONG 1) -+ set(HAVE_LL 1) - endif() - - find_file(RANDOM_FILE urandom /dev) -@@ -829,9 +288,9 @@ - - # Check for some functions that are used - if(HAVE_LIBWS2_32) -- set(CMAKE_REQUIRED_LIBRARIES ws2_32) -+ set(CMAKE_REQUIRED_LIBRARIES ws2_32) - elseif(HAVE_LIBSOCKET) -- set(CMAKE_REQUIRED_LIBRARIES socket) -+ set(CMAKE_REQUIRED_LIBRARIES socket) - endif() - - check_symbol_exists(basename "${CURL_INCLUDES}" HAVE_BASENAME) -@@ -849,7 +308,7 @@ - check_symbol_exists(strncmpi "${CURL_INCLUDES}" HAVE_STRNCMPI) - check_symbol_exists(alarm "${CURL_INCLUDES}" HAVE_ALARM) - if(NOT HAVE_STRNCMPI) -- set(HAVE_STRCMPI) -+ set(HAVE_STRCMPI) - endif() - check_symbol_exists(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR) - check_symbol_exists(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R) -@@ -879,7 +338,7 @@ - check_symbol_exists(signal "${CURL_INCLUDES}" HAVE_SIGNAL_FUNC) - check_symbol_exists(SIGALRM "${CURL_INCLUDES}" HAVE_SIGNAL_MACRO) - if(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO) -- set(HAVE_SIGNAL 1) -+ set(HAVE_SIGNAL 1) - endif() - check_symbol_exists(uname "${CURL_INCLUDES}" HAVE_UNAME) - check_symbol_exists(strtoll "${CURL_INCLUDES}" HAVE_STRTOLL) -@@ -906,89 +365,75 @@ - check_symbol_exists(setsockopt "${CURL_INCLUDES}" HAVE_SETSOCKOPT) - check_function_exists(mach_absolute_time HAVE_MACH_ABSOLUTE_TIME) - --# symbol exists in win32, but function does not. --if(WIN32) -- if(ENABLE_INET_PTON) -- check_function_exists(inet_pton HAVE_INET_PTON) -- # _WIN32_WINNT_VISTA (0x0600) -- add_definitions(-D_WIN32_WINNT=0x0600) -- else() -- # _WIN32_WINNT_WINXP (0x0501) -- add_definitions(-D_WIN32_WINNT=0x0501) -- endif() --else() -- check_function_exists(inet_pton HAVE_INET_PTON) --endif() -- - check_symbol_exists(fsetxattr "${CURL_INCLUDES}" HAVE_FSETXATTR) - if(HAVE_FSETXATTR) -- foreach(CURL_TEST HAVE_FSETXATTR_5 HAVE_FSETXATTR_6) -- curl_internal_test(${CURL_TEST}) -- endforeach() -+ foreach(CURL_TEST HAVE_FSETXATTR_5 HAVE_FSETXATTR_6) -+ curl_internal_test(${CURL_TEST}) -+ endforeach() - endif() - - # sigaction and sigsetjmp are special. Use special mechanism for - # detecting those, but only if previous attempt failed. - if(HAVE_SIGNAL_H) -- check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION) -+ check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION) - endif() - - if(NOT HAVE_SIGSETJMP) -- if(HAVE_SETJMP_H) -- check_symbol_exists(sigsetjmp "setjmp.h" HAVE_MACRO_SIGSETJMP) -- if(HAVE_MACRO_SIGSETJMP) -- set(HAVE_SIGSETJMP 1) -+ if(HAVE_SETJMP_H) -+ check_symbol_exists(sigsetjmp "setjmp.h" HAVE_MACRO_SIGSETJMP) -+ if(HAVE_MACRO_SIGSETJMP) -+ set(HAVE_SIGSETJMP 1) -+ endif() - endif() -- endif() - endif() - - # If there is no stricmp(), do not allow LDAP to parse URLs - if(NOT HAVE_STRICMP) -- set(HAVE_LDAP_URL_PARSE 1) -+ set(HAVE_LDAP_URL_PARSE 1) - endif() - - # Do curl specific tests - foreach(CURL_TEST -- HAVE_FCNTL_O_NONBLOCK -- HAVE_IOCTLSOCKET -- HAVE_IOCTLSOCKET_CAMEL -- HAVE_IOCTLSOCKET_CAMEL_FIONBIO -- HAVE_IOCTLSOCKET_FIONBIO -- HAVE_IOCTL_FIONBIO -- HAVE_IOCTL_SIOCGIFADDR -- HAVE_SETSOCKOPT_SO_NONBLOCK -- HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID -- TIME_WITH_SYS_TIME -- HAVE_O_NONBLOCK -- HAVE_GETHOSTBYADDR_R_5 -- HAVE_GETHOSTBYADDR_R_7 -- HAVE_GETHOSTBYADDR_R_8 -- HAVE_GETHOSTBYADDR_R_5_REENTRANT -- HAVE_GETHOSTBYADDR_R_7_REENTRANT -- HAVE_GETHOSTBYADDR_R_8_REENTRANT -- HAVE_GETHOSTBYNAME_R_3 -- HAVE_GETHOSTBYNAME_R_5 -- HAVE_GETHOSTBYNAME_R_6 -- HAVE_GETHOSTBYNAME_R_3_REENTRANT -- HAVE_GETHOSTBYNAME_R_5_REENTRANT -- HAVE_GETHOSTBYNAME_R_6_REENTRANT -- HAVE_IN_ADDR_T -- HAVE_BOOL_T -- STDC_HEADERS -- RETSIGTYPE_TEST -- HAVE_INET_NTOA_R_DECL -- HAVE_INET_NTOA_R_DECL_REENTRANT -- HAVE_GETADDRINFO -- HAVE_FILE_OFFSET_BITS -- HAVE_VARIADIC_MACROS_C99 -- HAVE_VARIADIC_MACROS_GCC -- ) -- curl_internal_test(${CURL_TEST}) -+ HAVE_FCNTL_O_NONBLOCK -+ HAVE_IOCTLSOCKET -+ HAVE_IOCTLSOCKET_CAMEL -+ HAVE_IOCTLSOCKET_CAMEL_FIONBIO -+ HAVE_IOCTLSOCKET_FIONBIO -+ HAVE_IOCTL_FIONBIO -+ HAVE_IOCTL_SIOCGIFADDR -+ HAVE_SETSOCKOPT_SO_NONBLOCK -+ HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID -+ TIME_WITH_SYS_TIME -+ HAVE_O_NONBLOCK -+ HAVE_GETHOSTBYADDR_R_5 -+ HAVE_GETHOSTBYADDR_R_7 -+ HAVE_GETHOSTBYADDR_R_8 -+ HAVE_GETHOSTBYADDR_R_5_REENTRANT -+ HAVE_GETHOSTBYADDR_R_7_REENTRANT -+ HAVE_GETHOSTBYADDR_R_8_REENTRANT -+ HAVE_GETHOSTBYNAME_R_3 -+ HAVE_GETHOSTBYNAME_R_5 -+ HAVE_GETHOSTBYNAME_R_6 -+ HAVE_GETHOSTBYNAME_R_3_REENTRANT -+ HAVE_GETHOSTBYNAME_R_5_REENTRANT -+ HAVE_GETHOSTBYNAME_R_6_REENTRANT -+ HAVE_IN_ADDR_T -+ HAVE_BOOL_T -+ STDC_HEADERS -+ RETSIGTYPE_TEST -+ HAVE_INET_NTOA_R_DECL -+ HAVE_INET_NTOA_R_DECL_REENTRANT -+ HAVE_GETADDRINFO -+ HAVE_FILE_OFFSET_BITS -+ HAVE_VARIADIC_MACROS_C99 -+ HAVE_VARIADIC_MACROS_GCC -+ ) -+ curl_internal_test(${CURL_TEST}) - endforeach() - - if(HAVE_FILE_OFFSET_BITS) -- set(_FILE_OFFSET_BITS 64) -- set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64") -+ set(_FILE_OFFSET_BITS 64) -+ set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64") - endif() - check_type_size("off_t" SIZEOF_OFF_T) - -@@ -998,49 +443,47 @@ - check_type_size("curl_off_t" SIZEOF_CURL_OFF_T) - set(CMAKE_EXTRA_INCLUDE_FILES "") - --set(CMAKE_REQUIRED_FLAGS) -- - foreach(CURL_TEST -- HAVE_GLIBC_STRERROR_R -- HAVE_POSIX_STRERROR_R -- ) -- curl_internal_test(${CURL_TEST}) -+ HAVE_GLIBC_STRERROR_R -+ HAVE_POSIX_STRERROR_R -+ ) -+ curl_internal_test(${CURL_TEST}) - endforeach() - - # Check for reentrant - foreach(CURL_TEST -- HAVE_GETHOSTBYADDR_R_5 -- HAVE_GETHOSTBYADDR_R_7 -- HAVE_GETHOSTBYADDR_R_8 -- HAVE_GETHOSTBYNAME_R_3 -- HAVE_GETHOSTBYNAME_R_5 -- HAVE_GETHOSTBYNAME_R_6 -- HAVE_INET_NTOA_R_DECL_REENTRANT) -- if(NOT ${CURL_TEST}) -- if(${CURL_TEST}_REENTRANT) -- set(NEED_REENTRANT 1) -+ HAVE_GETHOSTBYADDR_R_5 -+ HAVE_GETHOSTBYADDR_R_7 -+ HAVE_GETHOSTBYADDR_R_8 -+ HAVE_GETHOSTBYNAME_R_3 -+ HAVE_GETHOSTBYNAME_R_5 -+ HAVE_GETHOSTBYNAME_R_6 -+ HAVE_INET_NTOA_R_DECL_REENTRANT) -+ if(NOT ${CURL_TEST}) -+ if(${CURL_TEST}_REENTRANT) -+ set(NEED_REENTRANT 1) -+ endif() - endif() -- endif() - endforeach() - - if(NEED_REENTRANT) -- foreach(CURL_TEST -- HAVE_GETHOSTBYADDR_R_5 -- HAVE_GETHOSTBYADDR_R_7 -- HAVE_GETHOSTBYADDR_R_8 -- HAVE_GETHOSTBYNAME_R_3 -- HAVE_GETHOSTBYNAME_R_5 -- HAVE_GETHOSTBYNAME_R_6) -- set(${CURL_TEST} 0) -- if(${CURL_TEST}_REENTRANT) -- set(${CURL_TEST} 1) -- endif() -- endforeach() -+ foreach(CURL_TEST -+ HAVE_GETHOSTBYADDR_R_5 -+ HAVE_GETHOSTBYADDR_R_7 -+ HAVE_GETHOSTBYADDR_R_8 -+ HAVE_GETHOSTBYNAME_R_3 -+ HAVE_GETHOSTBYNAME_R_5 -+ HAVE_GETHOSTBYNAME_R_6) -+ set(${CURL_TEST} 0) -+ if(${CURL_TEST}_REENTRANT) -+ set(${CURL_TEST} 1) -+ endif() -+ endforeach() - endif() - - if(HAVE_INET_NTOA_R_DECL_REENTRANT) -- set(HAVE_INET_NTOA_R_DECL 1) -- set(NEED_REENTRANT 1) -+ set(HAVE_INET_NTOA_R_DECL 1) -+ set(NEED_REENTRANT 1) - endif() - - # Check clock_gettime(CLOCK_MONOTONIC, x) support -@@ -1052,323 +495,132 @@ - # Some other minor tests - - if(NOT HAVE_IN_ADDR_T) -- set(in_addr_t "unsigned long") --endif() -- --# Fix libz / zlib.h -- --if(NOT CURL_SPECIAL_LIBZ) -- if(NOT HAVE_LIBZ) -- set(HAVE_ZLIB_H 0) -- endif() -- -- if(NOT HAVE_ZLIB_H) -- set(HAVE_LIBZ 0) -- endif() -+ set(in_addr_t "unsigned long") - endif() - - # Check for nonblocking - set(HAVE_DISABLED_NONBLOCKING 1) - if(HAVE_FIONBIO OR -- HAVE_IOCTLSOCKET OR -- HAVE_IOCTLSOCKET_CASE OR -- HAVE_O_NONBLOCK) -- set(HAVE_DISABLED_NONBLOCKING) --endif() -- --if(RETSIGTYPE_TEST) -- set(RETSIGTYPE void) --else() -- set(RETSIGTYPE int) --endif() -- --if(CMAKE_COMPILER_IS_GNUCC AND APPLE) -- include(CheckCCompilerFlag) -- check_c_compiler_flag(-Wno-long-double HAVE_C_FLAG_Wno_long_double) -- if(HAVE_C_FLAG_Wno_long_double) -- # The Mac version of GCC warns about use of long double. Disable it. -- get_source_file_property(MPRINTF_COMPILE_FLAGS mprintf.c COMPILE_FLAGS) -- if(MPRINTF_COMPILE_FLAGS) -- set(MPRINTF_COMPILE_FLAGS "${MPRINTF_COMPILE_FLAGS} -Wno-long-double") -- else() -- set(MPRINTF_COMPILE_FLAGS "-Wno-long-double") -- endif() -- set_source_files_properties(mprintf.c PROPERTIES -- COMPILE_FLAGS ${MPRINTF_COMPILE_FLAGS}) -- endif() -+ HAVE_IOCTLSOCKET OR -+ HAVE_IOCTLSOCKET_CASE OR -+ HAVE_O_NONBLOCK) -+ set(HAVE_DISABLED_NONBLOCKING) - endif() - --# TODO test which of these headers are required --if(WIN32) -- set(CURL_PULL_WS2TCPIP_H ${HAVE_WS2TCPIP_H}) --else() -- set(CURL_PULL_SYS_TYPES_H ${HAVE_SYS_TYPES_H}) -- set(CURL_PULL_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H}) -- set(CURL_PULL_SYS_POLL_H ${HAVE_SYS_POLL_H}) --endif() -+set(CURL_PULL_SYS_TYPES_H ${HAVE_SYS_TYPES_H}) -+set(CURL_PULL_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H}) -+set(CURL_PULL_SYS_POLL_H ${HAVE_SYS_POLL_H}) - set(CURL_PULL_STDINT_H ${HAVE_STDINT_H}) - set(CURL_PULL_INTTYPES_H ${HAVE_INTTYPES_H}) - - include(CMake/OtherTests.cmake) - --add_definitions(-DHAVE_CONFIG_H) -+SET(LIB_VAUTH_CFILES -+ "${CURL_LIBRARY_DIR}/vauth/vauth.c" "${CURL_LIBRARY_DIR}/vauth/cleartext.c" "${CURL_LIBRARY_DIR}/vauth/cram.c" -+ "${CURL_LIBRARY_DIR}/vauth/digest.c" "${CURL_LIBRARY_DIR}/vauth/digest_sspi.c" "${CURL_LIBRARY_DIR}/vauth/krb5_gssapi.c" -+ "${CURL_LIBRARY_DIR}/vauth/krb5_sspi.c" "${CURL_LIBRARY_DIR}/vauth/ntlm.c" "${CURL_LIBRARY_DIR}/vauth/ntlm_sspi.c" "${CURL_LIBRARY_DIR}/vauth/oauth2.c" -+ "${CURL_LIBRARY_DIR}/vauth/spnego_gssapi.c" "${CURL_LIBRARY_DIR}/vauth/spnego_sspi.c") -+ -+SET(LIB_VAUTH_HFILES "${CURL_LIBRARY_DIR}/vauth/vauth.h" "${CURL_LIBRARY_DIR}/vauth/digest.h" "${CURL_LIBRARY_DIR}/vauth/ntlm.h") -+ -+SET(LIB_VTLS_CFILES "${CURL_LIBRARY_DIR}/vtls/openssl.c" "${CURL_LIBRARY_DIR}/vtls/gtls.c" "${CURL_LIBRARY_DIR}/vtls/vtls.c" "${CURL_LIBRARY_DIR}/vtls/nss.c" -+ "${CURL_LIBRARY_DIR}/vtls/polarssl.c" "${CURL_LIBRARY_DIR}/vtls/polarssl_threadlock.c" -+ "${CURL_LIBRARY_DIR}/vtls/wolfssl.c" "${CURL_LIBRARY_DIR}/vtls/schannel.c" "${CURL_LIBRARY_DIR}/vtls/schannel_verify.c" -+ "${CURL_LIBRARY_DIR}/vtls/sectransp.c" "${CURL_LIBRARY_DIR}/vtls/gskit.c" "${CURL_LIBRARY_DIR}/vtls/mbedtls.c" "${CURL_LIBRARY_DIR}/vtls/mesalink.c" -+ "${CURL_LIBRARY_DIR}/vtls/bearssl.c") -+ -+SET(LIB_VTLS_HFILES "${CURL_LIBRARY_DIR}/vtls/openssl.h" "${CURL_LIBRARY_DIR}/vtls/vtls.h" "${CURL_LIBRARY_DIR}/vtls/gtls.h" -+ "${CURL_LIBRARY_DIR}/vtls/nssg.h" "${CURL_LIBRARY_DIR}/vtls/polarssl.h" "${CURL_LIBRARY_DIR}/vtls/polarssl_threadlock.h" -+ "${CURL_LIBRARY_DIR}/vtls/wolfssl.h" "${CURL_LIBRARY_DIR}/vtls/schannel.h" "${CURL_LIBRARY_DIR}/vtls/sectransp.h" "${CURL_LIBRARY_DIR}/vtls/gskit.h" -+ "${CURL_LIBRARY_DIR}/vtls/mbedtls.h" "${CURL_LIBRARY_DIR}/vtls/mesalink.h" "${CURL_LIBRARY_DIR}/vtls/bearssl.h") -+ -+SET(LIB_VQUIC_CFILES "${CURL_LIBRARY_DIR}/vquic/ngtcp2.c" "${CURL_LIBRARY_DIR}/vquic/quiche.c") -+ -+SET(LIB_VQUIC_HFILES "${CURL_LIBRARY_DIR}/vquic/ngtcp2.h" "${CURL_LIBRARY_DIR}/vquic/quiche.h") -+ -+SET(LIB_VSSH_CFILES "${CURL_LIBRARY_DIR}/vssh/libssh2.c" "${CURL_LIBRARY_DIR}/vssh/libssh.c") -+ -+SET(LIB_VSSH_HFILES "${CURL_LIBRARY_DIR}/vssh/ssh.h") -+ -+SET(LIB_CFILES "${CURL_LIBRARY_DIR}/file.c" -+ "${CURL_LIBRARY_DIR}/timeval.c" "${CURL_LIBRARY_DIR}/base64.c" "${CURL_LIBRARY_DIR}/hostip.c" "${CURL_LIBRARY_DIR}/progress.c" "${CURL_LIBRARY_DIR}/formdata.c" -+ "${CURL_LIBRARY_DIR}/cookie.c" "${CURL_LIBRARY_DIR}/http.c" "${CURL_LIBRARY_DIR}/sendf.c" "${CURL_LIBRARY_DIR}/url.c" "${CURL_LIBRARY_DIR}/dict.c" "${CURL_LIBRARY_DIR}/if2ip.c" "${CURL_LIBRARY_DIR}/speedcheck.c" -+ "${CURL_LIBRARY_DIR}/ldap.c" "${CURL_LIBRARY_DIR}/version.c" "${CURL_LIBRARY_DIR}/getenv.c" "${CURL_LIBRARY_DIR}/escape.c" "${CURL_LIBRARY_DIR}/mprintf.c" "${CURL_LIBRARY_DIR}/telnet.c" "${CURL_LIBRARY_DIR}/netrc.c" -+ "${CURL_LIBRARY_DIR}/getinfo.c" "${CURL_LIBRARY_DIR}/transfer.c" "${CURL_LIBRARY_DIR}/strcase.c" "${CURL_LIBRARY_DIR}/easy.c" "${CURL_LIBRARY_DIR}/security.c" "${CURL_LIBRARY_DIR}/curl_fnmatch.c" -+ "${CURL_LIBRARY_DIR}/fileinfo.c" "${CURL_LIBRARY_DIR}/wildcard.c" "${CURL_LIBRARY_DIR}/krb5.c" "${CURL_LIBRARY_DIR}/memdebug.c" "${CURL_LIBRARY_DIR}/http_chunks.c" -+ "${CURL_LIBRARY_DIR}/strtok.c" "${CURL_LIBRARY_DIR}/connect.c" "${CURL_LIBRARY_DIR}/llist.c" "${CURL_LIBRARY_DIR}/hash.c" "${CURL_LIBRARY_DIR}/multi.c" "${CURL_LIBRARY_DIR}/content_encoding.c" "${CURL_LIBRARY_DIR}/share.c" -+ "${CURL_LIBRARY_DIR}/http_digest.c" "${CURL_LIBRARY_DIR}/md4.c" "${CURL_LIBRARY_DIR}/md5.c" "${CURL_LIBRARY_DIR}/http_negotiate.c" "${CURL_LIBRARY_DIR}/inet_pton.c" "${CURL_LIBRARY_DIR}/strtoofft.c" -+ "${CURL_LIBRARY_DIR}/strerror.c" "${CURL_LIBRARY_DIR}/amigaos.c" "${CURL_LIBRARY_DIR}/hostasyn.c" "${CURL_LIBRARY_DIR}/hostip4.c" "${CURL_LIBRARY_DIR}/hostip6.c" "${CURL_LIBRARY_DIR}/hostsyn.c" -+ "${CURL_LIBRARY_DIR}/inet_ntop.c" "${CURL_LIBRARY_DIR}/parsedate.c" "${CURL_LIBRARY_DIR}/select.c" "${CURL_LIBRARY_DIR}/splay.c" "${CURL_LIBRARY_DIR}/strdup.c" "${CURL_LIBRARY_DIR}/socks.c" -+ "${CURL_LIBRARY_DIR}/curl_addrinfo.c" "${CURL_LIBRARY_DIR}/socks_gssapi.c" "${CURL_LIBRARY_DIR}/socks_sspi.c" -+ "${CURL_LIBRARY_DIR}/curl_sspi.c" "${CURL_LIBRARY_DIR}/slist.c" "${CURL_LIBRARY_DIR}/nonblock.c" "${CURL_LIBRARY_DIR}/curl_memrchr.c" "${CURL_LIBRARY_DIR}/imap.c" "${CURL_LIBRARY_DIR}/pop3.c" "${CURL_LIBRARY_DIR}/smtp.c" -+ "${CURL_LIBRARY_DIR}/pingpong.c" "${CURL_LIBRARY_DIR}/rtsp.c" "${CURL_LIBRARY_DIR}/curl_threads.c" "${CURL_LIBRARY_DIR}/warnless.c" "${CURL_LIBRARY_DIR}/hmac.c" "${CURL_LIBRARY_DIR}/curl_rtmp.c" -+ "${CURL_LIBRARY_DIR}/openldap.c" "${CURL_LIBRARY_DIR}/curl_gethostname.c" "${CURL_LIBRARY_DIR}/gopher.c" "${CURL_LIBRARY_DIR}/idn_win32.c" -+ "${CURL_LIBRARY_DIR}/http_proxy.c" "${CURL_LIBRARY_DIR}/non-ascii.c" "${CURL_LIBRARY_DIR}/asyn-ares.c" "${CURL_LIBRARY_DIR}/asyn-thread.c" "${CURL_LIBRARY_DIR}/curl_gssapi.c" -+ "${CURL_LIBRARY_DIR}/http_ntlm.c" "${CURL_LIBRARY_DIR}/curl_ntlm_wb.c" "${CURL_LIBRARY_DIR}/curl_ntlm_core.c" "${CURL_LIBRARY_DIR}/curl_sasl.c" "${CURL_LIBRARY_DIR}/rand.c" -+ "${CURL_LIBRARY_DIR}/curl_multibyte.c" "${CURL_LIBRARY_DIR}/hostcheck.c" "${CURL_LIBRARY_DIR}/conncache.c" "${CURL_LIBRARY_DIR}/dotdot.c" -+ "${CURL_LIBRARY_DIR}/x509asn1.c" "${CURL_LIBRARY_DIR}/http2.c" "${CURL_LIBRARY_DIR}/smb.c" "${CURL_LIBRARY_DIR}/curl_endian.c" "${CURL_LIBRARY_DIR}/curl_des.c" "${CURL_LIBRARY_DIR}/system_win32.c" -+ "${CURL_LIBRARY_DIR}/mime.c" "${CURL_LIBRARY_DIR}/sha256.c" "${CURL_LIBRARY_DIR}/setopt.c" "${CURL_LIBRARY_DIR}/curl_path.c" "${CURL_LIBRARY_DIR}/curl_ctype.c" "${CURL_LIBRARY_DIR}/curl_range.c" "${CURL_LIBRARY_DIR}/psl.c" -+ "${CURL_LIBRARY_DIR}/doh.c" "${CURL_LIBRARY_DIR}/urlapi.c" "${CURL_LIBRARY_DIR}/curl_get_line.c" "${CURL_LIBRARY_DIR}/altsvc.c" "${CURL_LIBRARY_DIR}/socketpair.c") -+ -+SET(LIB_HFILES "${CURL_LIBRARY_DIR}/arpa_telnet.h" "${CURL_LIBRARY_DIR}/netrc.h" "${CURL_LIBRARY_DIR}/file.h" "${CURL_LIBRARY_DIR}/timeval.h" "${CURL_LIBRARY_DIR}/hostip.h" "${CURL_LIBRARY_DIR}/progress.h" -+ "${CURL_LIBRARY_DIR}/formdata.h" "${CURL_LIBRARY_DIR}/cookie.h" "${CURL_LIBRARY_DIR}/http.h" "${CURL_LIBRARY_DIR}/sendf.h" "${CURL_LIBRARY_DIR}/url.h" "${CURL_LIBRARY_DIR}/dict.h" "${CURL_LIBRARY_DIR}/if2ip.h" -+ "${CURL_LIBRARY_DIR}/speedcheck.h" "${CURL_LIBRARY_DIR}/urldata.h" "${CURL_LIBRARY_DIR}/curl_ldap.h" "${CURL_LIBRARY_DIR}/escape.h" "${CURL_LIBRARY_DIR}/telnet.h" "${CURL_LIBRARY_DIR}/getinfo.h" -+ "${CURL_LIBRARY_DIR}/strcase.h" "${CURL_LIBRARY_DIR}/curl_sec.h" "${CURL_LIBRARY_DIR}/memdebug.h" "${CURL_LIBRARY_DIR}/http_chunks.h" "${CURL_LIBRARY_DIR}/curl_fnmatch.h" -+ "${CURL_LIBRARY_DIR}/wildcard.h" "${CURL_LIBRARY_DIR}/fileinfo.h" "${CURL_LIBRARY_DIR}/strtok.h" "${CURL_LIBRARY_DIR}/connect.h" "${CURL_LIBRARY_DIR}/llist.h" -+ "${CURL_LIBRARY_DIR}/hash.h" "${CURL_LIBRARY_DIR}/content_encoding.h" "${CURL_LIBRARY_DIR}/share.h" "${CURL_LIBRARY_DIR}/curl_md4.h" "${CURL_LIBRARY_DIR}/curl_md5.h" "${CURL_LIBRARY_DIR}/http_digest.h" -+ "${CURL_LIBRARY_DIR}/http_negotiate.h" "${CURL_LIBRARY_DIR}/inet_pton.h" "${CURL_LIBRARY_DIR}/amigaos.h" "${CURL_LIBRARY_DIR}/strtoofft.h" "${CURL_LIBRARY_DIR}/strerror.h" -+ "${CURL_LIBRARY_DIR}/inet_ntop.h" "${CURL_LIBRARY_DIR}/curlx.h" "${CURL_LIBRARY_DIR}/curl_memory.h" "${CURL_LIBRARY_DIR}/curl_setup.h" "${CURL_LIBRARY_DIR}/transfer.h" "${CURL_LIBRARY_DIR}/select.h" -+ "${CURL_LIBRARY_DIR}/easyif.h" "${CURL_LIBRARY_DIR}/multiif.h" "${CURL_LIBRARY_DIR}/parsedate.h" "${CURL_LIBRARY_DIR}/sockaddr.h" "${CURL_LIBRARY_DIR}/splay.h" "${CURL_LIBRARY_DIR}/strdup.h" -+ "${CURL_LIBRARY_DIR}/socks.h" "${CURL_LIBRARY_DIR}/curl_base64.h" "${CURL_LIBRARY_DIR}/curl_addrinfo.h" "${CURL_LIBRARY_DIR}/curl_sspi.h" -+ "${CURL_LIBRARY_DIR}/slist.h" "${CURL_LIBRARY_DIR}/nonblock.h" "${CURL_LIBRARY_DIR}/curl_memrchr.h" "${CURL_LIBRARY_DIR}/imap.h" "${CURL_LIBRARY_DIR}/pop3.h" "${CURL_LIBRARY_DIR}/smtp.h" "${CURL_LIBRARY_DIR}/pingpong.h" -+ "${CURL_LIBRARY_DIR}/rtsp.h" "${CURL_LIBRARY_DIR}/curl_threads.h" "${CURL_LIBRARY_DIR}/warnless.h" "${CURL_LIBRARY_DIR}/curl_hmac.h" "${CURL_LIBRARY_DIR}/curl_rtmp.h" -+ "${CURL_LIBRARY_DIR}/curl_gethostname.h" "${CURL_LIBRARY_DIR}/gopher.h" "${CURL_LIBRARY_DIR}/http_proxy.h" "${CURL_LIBRARY_DIR}/non-ascii.h" "${CURL_LIBRARY_DIR}/asyn.h" -+ "${CURL_LIBRARY_DIR}/http_ntlm.h" "${CURL_LIBRARY_DIR}/curl_gssapi.h" "${CURL_LIBRARY_DIR}/curl_ntlm_wb.h" "${CURL_LIBRARY_DIR}/curl_ntlm_core.h" -+ "${CURL_LIBRARY_DIR}/curl_sasl.h" "${CURL_LIBRARY_DIR}/curl_multibyte.h" "${CURL_LIBRARY_DIR}/hostcheck.h" "${CURL_LIBRARY_DIR}/conncache.h" -+ "${CURL_LIBRARY_DIR}/multihandle.h" "${CURL_LIBRARY_DIR}/setup-vms.h" "${CURL_LIBRARY_DIR}/dotdot.h" -+ "${CURL_LIBRARY_DIR}/x509asn1.h" "${CURL_LIBRARY_DIR}/http2.h" "${CURL_LIBRARY_DIR}/sigpipe.h" "${CURL_LIBRARY_DIR}/smb.h" "${CURL_LIBRARY_DIR}/curl_endian.h" "${CURL_LIBRARY_DIR}/curl_des.h" -+ "${CURL_LIBRARY_DIR}/curl_printf.h" "${CURL_LIBRARY_DIR}/system_win32.h" "${CURL_LIBRARY_DIR}/rand.h" "${CURL_LIBRARY_DIR}/mime.h" "${CURL_LIBRARY_DIR}/curl_sha256.h" "${CURL_LIBRARY_DIR}/setopt.h" -+ "${CURL_LIBRARY_DIR}/curl_path.h" "${CURL_LIBRARY_DIR}/curl_ctype.h" "${CURL_LIBRARY_DIR}/curl_range.h" "${CURL_LIBRARY_DIR}/psl.h" "${CURL_LIBRARY_DIR}/doh.h" "${CURL_LIBRARY_DIR}/urlapi-int.h" -+ "${CURL_LIBRARY_DIR}/curl_get_line.h" "${CURL_LIBRARY_DIR}/altsvc.h" "${CURL_LIBRARY_DIR}/quic.h" "${CURL_LIBRARY_DIR}/socketpair.h") -+ -+SET(LIB_RCFILES "${CURL_LIBRARY_DIR}/libcurl.rc") -+ -+SET(CSOURCES ${LIB_CFILES} ${LIB_VAUTH_CFILES} ${LIB_VTLS_CFILES} -+ ${LIB_VQUIC_CFILES} ${LIB_VSSH_CFILES}) -+SET(HHEADERS ${LIB_HFILES} ${LIB_VAUTH_HFILES} ${LIB_VTLS_HFILES} -+ ${LIB_VQUIC_HFILES} ${LIB_VSSH_HFILES}) -+ -+configure_file(${CURL_SOURCE_DIR}/lib/curl_config.h.cmake -+ ${CMAKE_CURRENT_BINARY_DIR}/curl/curl_config.h) -+ -+list(APPEND HHEADERS -+ ${CMAKE_CURRENT_BINARY_DIR}/curl/curl_config.h -+ ) -+ -+add_library(libcurl ${HHEADERS} ${CSOURCES}) -+ -+if(NOT BUILD_SHARED_LIBS) -+ set_target_properties(libcurl PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB) -+endif() -+ -+if(HIDES_CURL_PRIVATE_SYMBOLS) -+ set_property(TARGET libcurl APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS") -+ set_property(TARGET libcurl APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE}) -+endif() -+ -+if(OPENSSL_FOUND) -+ target_include_directories(libcurl PUBLIC ${OPENSSL_INCLUDE_DIR}) -+ message("-- Including openssl ${OPENSSL_INCLUDE_DIR} to curl") -+endif() -+ -+if(ZLIB_FOUND) -+ target_include_directories(libcurl PUBLIC ${ZLIB_INCLUDE_DIRS}}) -+ message("-- Including zlib ${ZLIB_INCLUDE_DIRS} to curl") -+endif() -+ -+target_compile_definitions(libcurl PUBLIC -DHAVE_CONFIG_H) -+target_compile_definitions(libcurl PUBLIC -DBUILDING_LIBCURL) -+target_include_directories(libcurl PUBLIC "${CURL_SOURCE_DIR}/include" "${CURL_LIBRARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/curl") - --# For Windows, all compilers used by CMake should support large files --if(WIN32) -- set(USE_WIN32_LARGE_FILES ON) -- -- # Use the manifest embedded in the Windows Resource -- set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -DCURL_EMBED_MANIFEST") --endif() -- --if(MSVC) -- # Disable default manifest added by CMake -- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO") -- -- add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) -- if(CMAKE_C_FLAGS MATCHES "/W[0-4]") -- string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") -- else() -- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4") -- endif() --endif() -- --if(CURL_WERROR) -- if(MSVC_VERSION) -- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") -- else() -- # this assumes clang or gcc style options -- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") -- endif() --endif() -- --# Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it). --function(transform_makefile_inc INPUT_FILE OUTPUT_FILE) -- file(READ ${INPUT_FILE} MAKEFILE_INC_TEXT) -- string(REPLACE "$(top_srcdir)" "\${CURL_SOURCE_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) -- string(REPLACE "$(top_builddir)" "\${CURL_BINARY_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) -- -- string(REGEX REPLACE "\\\\\n" "!π!α!" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) -- string(REGEX REPLACE "([a-zA-Z_][a-zA-Z0-9_]*)[\t ]*=[\t ]*([^\n]*)" "SET(\\1 \\2)" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) -- string(REPLACE "!π!α!" "\n" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) -- -- string(REGEX REPLACE "\\$\\(([a-zA-Z_][a-zA-Z0-9_]*)\\)" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) # Replace $() with ${} -- string(REGEX REPLACE "@([a-zA-Z_][a-zA-Z0-9_]*)@" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) # Replace @@ with ${}, even if that may not be read by CMake scripts. -- file(WRITE ${OUTPUT_FILE} ${MAKEFILE_INC_TEXT}) -- --endfunction() -- --include(GNUInstallDirs) -- --set(CURL_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) --set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") --set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated") --set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake") --set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake") -- --if(USE_MANUAL) -- add_subdirectory(docs) --endif() -- --add_subdirectory(lib) -- --if(BUILD_CURL_EXE) -- add_subdirectory(src) --endif() -- --include(CTest) --if(BUILD_TESTING) -- add_subdirectory(tests) --endif() -- --# Helper to populate a list (_items) with a label when conditions (the remaining --# args) are satisfied --function(_add_if label) -- # TODO need to disable policy CMP0054 (CMake 3.1) to allow this indirection -- if(${ARGN}) -- set(_items ${_items} "${label}" PARENT_SCOPE) -- endif() --endfunction() -- --# Clear list and try to detect available features --set(_items) --_add_if("SSL" SSL_ENABLED) --_add_if("IPv6" ENABLE_IPV6) --_add_if("unix-sockets" USE_UNIX_SOCKETS) --_add_if("libz" HAVE_LIBZ) --_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32) --_add_if("IDN" HAVE_LIBIDN2) --_add_if("Largefile" (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND -- ((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES)) --# TODO SSP1 (WinSSL) check is missing --_add_if("SSPI" USE_WINDOWS_SSPI) --_add_if("GSS-API" HAVE_GSSAPI) --# TODO SSP1 missing for SPNEGO --_add_if("SPNEGO" NOT CURL_DISABLE_CRYPTO_AUTH AND -- (HAVE_GSSAPI OR USE_WINDOWS_SSPI)) --_add_if("Kerberos" NOT CURL_DISABLE_CRYPTO_AUTH AND -- (HAVE_GSSAPI OR USE_WINDOWS_SSPI)) --# NTLM support requires crypto function adaptions from various SSL libs --# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS --if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_SECTRANSP OR USE_MBEDTLS)) -- _add_if("NTLM" 1) -- # TODO missing option (autoconf: --enable-ntlm-wb) -- _add_if("NTLM_WB" NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED) --endif() --# TODO missing option (--enable-tls-srp), depends on GNUTLS_SRP/OPENSSL_SRP --_add_if("TLS-SRP" USE_TLS_SRP) --# TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header --_add_if("HTTP2" USE_NGHTTP2) --string(REPLACE ";" " " SUPPORT_FEATURES "${_items}") --message(STATUS "Enabled features: ${SUPPORT_FEATURES}") -- --# Clear list and try to detect available protocols --set(_items) --_add_if("HTTP" NOT CURL_DISABLE_HTTP) --_add_if("HTTPS" NOT CURL_DISABLE_HTTP AND SSL_ENABLED) --_add_if("FTP" NOT CURL_DISABLE_FTP) --_add_if("FTPS" NOT CURL_DISABLE_FTP AND SSL_ENABLED) --_add_if("FILE" NOT CURL_DISABLE_FILE) --_add_if("TELNET" NOT CURL_DISABLE_TELNET) --_add_if("LDAP" NOT CURL_DISABLE_LDAP) --# CURL_DISABLE_LDAP implies CURL_DISABLE_LDAPS --# TODO check HAVE_LDAP_SSL (in autoconf this is enabled with --enable-ldaps) --_add_if("LDAPS" NOT CURL_DISABLE_LDAPS AND -- ((USE_OPENLDAP AND SSL_ENABLED) OR -- (NOT USE_OPENLDAP AND HAVE_LDAP_SSL))) --_add_if("DICT" NOT CURL_DISABLE_DICT) --_add_if("TFTP" NOT CURL_DISABLE_TFTP) --_add_if("GOPHER" NOT CURL_DISABLE_GOPHER) --_add_if("POP3" NOT CURL_DISABLE_POP3) --_add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED) --_add_if("IMAP" NOT CURL_DISABLE_IMAP) --_add_if("IMAPS" NOT CURL_DISABLE_IMAP AND SSL_ENABLED) --_add_if("SMTP" NOT CURL_DISABLE_SMTP) --_add_if("SMTPS" NOT CURL_DISABLE_SMTP AND SSL_ENABLED) --_add_if("SCP" USE_LIBSSH2) --_add_if("SFTP" USE_LIBSSH2) --_add_if("RTSP" NOT CURL_DISABLE_RTSP) --_add_if("RTMP" USE_LIBRTMP) --if(_items) -- list(SORT _items) --endif() --string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}") --message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}") -- --# Clear list and collect SSL backends --set(_items) --_add_if("WinSSL" SSL_ENABLED AND USE_WINDOWS_SSPI) --_add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL) --_add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP) --_add_if("mbedTLS" SSL_ENABLED AND USE_MBEDTLS) --_add_if("BearSSL" SSL_ENABLED AND USE_BEARSSL) --if(_items) -- list(SORT _items) --endif() --string(REPLACE ";" " " SSL_BACKENDS "${_items}") --message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}") -- --# curl-config needs the following options to be set. --set(CC "${CMAKE_C_COMPILER}") --# TODO probably put a -D... options here? --set(CONFIGURE_OPTIONS "") --# TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB? --set(CPPFLAG_CURL_STATICLIB "") --set(CURLVERSION "${CURL_VERSION}") --if(BUILD_SHARED_LIBS) -- set(ENABLE_SHARED "yes") -- set(ENABLE_STATIC "no") --else() -- set(ENABLE_SHARED "no") -- set(ENABLE_STATIC "yes") --endif() --set(exec_prefix "\${prefix}") --set(includedir "\${prefix}/include") --set(LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}") --set(LIBCURL_LIBS "") --set(libdir "${CMAKE_INSTALL_PREFIX}/lib") --foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS}) -- if(_lib MATCHES ".*/.*" OR _lib MATCHES "^-") -- set(LIBCURL_LIBS "${LIBCURL_LIBS} ${_lib}") -- else() -- set(LIBCURL_LIBS "${LIBCURL_LIBS} -l${_lib}") -- endif() --endforeach() --# "a" (Linux) or "lib" (Windows) --string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}") --set(prefix "${CMAKE_INSTALL_PREFIX}") --# Set this to "yes" to append all libraries on which -lcurl is dependent --set(REQUIRE_LIB_DEPS "no") --# SUPPORT_FEATURES --# SUPPORT_PROTOCOLS --set(VERSIONNUM "${CURL_VERSION_NUM}") -- --# Finally generate a "curl-config" matching this config --# Use: --# * ENABLE_SHARED --# * ENABLE_STATIC --configure_file("${CURL_SOURCE_DIR}/curl-config.in" -- "${CURL_BINARY_DIR}/curl-config" @ONLY) --install(FILES "${CURL_BINARY_DIR}/curl-config" -- DESTINATION ${CMAKE_INSTALL_BINDIR} -- PERMISSIONS -- OWNER_READ OWNER_WRITE OWNER_EXECUTE -- GROUP_READ GROUP_EXECUTE -- WORLD_READ WORLD_EXECUTE) -- --# Finally generate a pkg-config file matching this config --configure_file("${CURL_SOURCE_DIR}/libcurl.pc.in" -- "${CURL_BINARY_DIR}/libcurl.pc" @ONLY) --install(FILES "${CURL_BINARY_DIR}/libcurl.pc" -- DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) -- --# install headers --install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl" -- DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -- FILES_MATCHING PATTERN "*.h") -- --include(CMakePackageConfigHelpers) --write_basic_package_version_file( -- "${version_config}" -- VERSION ${CURL_VERSION} -- COMPATIBILITY SameMajorVersion --) -- --# Use: --# * TARGETS_EXPORT_NAME --# * PROJECT_NAME --configure_package_config_file(CMake/curl-config.cmake.in -- "${project_config}" -- INSTALL_DESTINATION ${CURL_INSTALL_CMAKE_DIR} --) -- --install( -- EXPORT "${TARGETS_EXPORT_NAME}" -- NAMESPACE "${PROJECT_NAME}::" -- DESTINATION ${CURL_INSTALL_CMAKE_DIR} --) -- --install( -- FILES ${version_config} ${project_config} -- DESTINATION ${CURL_INSTALL_CMAKE_DIR} --) -- --# Workaround for MSVS10 to avoid the Dialog Hell --# FIXME: This could be removed with future version of CMake. --if(MSVC_VERSION EQUAL 1600) -- set(CURL_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/CURL.sln") -- if(EXISTS "${CURL_SLN_FILENAME}") -- file(APPEND "${CURL_SLN_FILENAME}" "\n# This should be regenerated!\n") -- endif() --endif() -- --if(NOT TARGET uninstall) -- configure_file( -- ${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in -- ${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake -- IMMEDIATE @ONLY) -- -- add_custom_target(uninstall -- COMMAND ${CMAKE_COMMAND} -P -- ${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake) --endif() -+target_link_libraries(libcurl ${CURL_LIBS}) diff --git a/contrib/curl-cmake/CMakeLists.txt b/contrib/curl-cmake/CMakeLists.txt index 53a255c7d8b..07a689adb6d 100644 --- a/contrib/curl-cmake/CMakeLists.txt +++ b/contrib/curl-cmake/CMakeLists.txt @@ -1,605 +1,148 @@ -#*************************************************************************** -# _ _ ____ _ -# Project ___| | | | _ \| | -# / __| | | | |_) | | -# | (__| |_| | _ <| |___ -# \___|\___/|_| \_\_____| -# -# Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. -# -# This software is licensed as described in the file COPYING, which -# you should have received as part of this distribution. The terms -# are also available at https://curl.haxx.se/docs/copyright.html. -# -# You may opt to use, copy, modify, merge, publish, distribute and/or sell -# copies of the Software, and permit persons to whom the Software is -# furnished to do so, under the terms of the COPYING file. -# -# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -# KIND, either express or implied. -# -########################################################################### - -# NOTE: -# This file is shrinked and reworked version of original curl CMakeLists.txt -# Original file link https://github.com/curl/curl/blob/3b8bbbbd1609c638a3d3d0acb148a33dedb67be3/CMakeLists.txt -# If you need to update curl building you can find patch file in this directory -# and apply it to fresh original CMakeLists.txt file. -cmake_minimum_required(VERSION 3.0 FATAL_ERROR) - -SET(CURL_SOURCE_DIR ${ClickHouse_SOURCE_DIR}/contrib/curl) -SET(CURL_LIBRARY_DIR ${CURL_SOURCE_DIR}/lib) -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}") -# Disable status messages when perform checks -set(CMAKE_REQUIRED_QUIET TRUE) - -include(Macros) -include(CMakeDependentOption) -include(CheckCCompilerFlag) - -file(READ ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS) -string(REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*" - CURL_VERSION ${CURL_VERSION_H_CONTENTS}) -string(REGEX REPLACE "[^\"]+\"" "" CURL_VERSION ${CURL_VERSION}) -string(REGEX MATCH "#define LIBCURL_VERSION_NUM 0x[0-9a-fA-F]+" - CURL_VERSION_NUM ${CURL_VERSION_H_CONTENTS}) -string(REGEX REPLACE "[^0]+0x" "" CURL_VERSION_NUM ${CURL_VERSION_NUM}) - -message(STATUS "Use curl version=[${CURL_VERSION}]") -set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}") -set(OS "\"${CMAKE_SYSTEM_NAME}\"") - -option(PICKY_COMPILER "Enable picky compiler options" ON) -option(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded DNS lookup" ON) - -if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) - if(PICKY_COMPILER) - foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wvla -Wdouble-promotion -Wno-system-headers -Wno-pedantic-ms-format) - # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new - # test result in. - check_c_compiler_flag(${_CCOPT} OPT${_CCOPT}) - if(OPT${_CCOPT}) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}") - endif() - endforeach() - endif() -endif() - -# initialize CURL_LIBS -set(CURL_LIBS "") - -include(CurlSymbolHiding) - -# Http only -set(CURL_DISABLE_FTP ON) -set(CURL_DISABLE_LDAP ON) -set(CURL_DISABLE_LDAPS ON) -set(CURL_DISABLE_TELNET ON) -set(CURL_DISABLE_DICT ON) -set(CURL_DISABLE_FILE ON) -set(CURL_DISABLE_TFTP ON) -set(CURL_DISABLE_RTSP ON) -set(CURL_DISABLE_POP3 ON) -set(CURL_DISABLE_IMAP ON) -set(CURL_DISABLE_SMTP ON) -set(CURL_DISABLE_GOPHER ON) - -option(CURL_DISABLE_COOKIES "to disable cookies support" OFF) -mark_as_advanced(CURL_DISABLE_COOKIES) - -option(CURL_DISABLE_CRYPTO_AUTH "to disable cryptographic authentication" OFF) -mark_as_advanced(CURL_DISABLE_CRYPTO_AUTH) - -option(CURL_DISABLE_VERBOSE_STRINGS "to disable verbose strings" OFF) -mark_as_advanced(CURL_DISABLE_VERBOSE_STRINGS) - -option(ENABLE_IPV6 "Define if you want to enable IPv6 support" ON) -mark_as_advanced(ENABLE_IPV6) - -if(ENABLE_IPV6 AND NOT WIN32) - include(CheckStructHasMember) - check_struct_has_member("struct sockaddr_in6" sin6_addr "netinet/in.h" - HAVE_SOCKADDR_IN6_SIN6_ADDR) - check_struct_has_member("struct sockaddr_in6" sin6_scope_id "netinet/in.h" - HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) - if(NOT HAVE_SOCKADDR_IN6_SIN6_ADDR) - message(WARNING "struct sockaddr_in6 not available, disabling IPv6 support") - # Force the feature off as this name is used as guard macro... - set(ENABLE_IPV6 OFF - CACHE BOOL "Define if you want to enable IPv6 support" FORCE) - endif() -endif() - -# We need ansi c-flags, especially on HP -set(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}") -set(CMAKE_REQUIRED_FLAGS ${CMAKE_ANSI_CFLAGS}) - -# Include all the necessary files for macros -include(CheckFunctionExists) -include(CheckIncludeFile) -include(CheckIncludeFiles) -include(CheckLibraryExists) -include(CheckSymbolExists) -include(CheckTypeSize) -include(CheckCSourceCompiles) - -if(ENABLE_THREADED_RESOLVER) - find_package(Threads REQUIRED) - set(USE_THREADS_POSIX ${CMAKE_USE_PTHREADS_INIT}) - set(HAVE_PTHREAD_H ${CMAKE_USE_PTHREADS_INIT}) - set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT}) -endif() - -# Check for all needed libraries - -# We don't want any plugin loading at runtime. It is harmful. -#check_library_exists_concat("${CMAKE_DL_LIBS}" dlopen HAVE_LIBDL) - -# This is unneeded. -#check_library_exists_concat("socket" connect HAVE_LIBSOCKET) - -set (NOT_NEED_LIBNSL 1) -set (gethostname HAVE_GETHOSTNAME 1) - -# From cmake/find/ssl.cmake -if (OPENSSL_FOUND) - set(SSL_ENABLED ON) - set(USE_OPENSSL ON) - - list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES}) - check_include_file("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H) - check_include_file("openssl/err.h" HAVE_OPENSSL_ERR_H) - check_include_file("openssl/pem.h" HAVE_OPENSSL_PEM_H) - check_include_file("openssl/rsa.h" HAVE_OPENSSL_RSA_H) - check_include_file("openssl/ssl.h" HAVE_OPENSSL_SSL_H) - check_include_file("openssl/x509.h" HAVE_OPENSSL_X509_H) - check_include_file("openssl/rand.h" HAVE_OPENSSL_RAND_H) - check_symbol_exists(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS) - check_symbol_exists(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN) - check_symbol_exists(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD) -endif() - -# Check for idn -# No, we don't need that. -# check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2) - -# Check for symbol dlopen (same as HAVE_LIBDL) -# We don't want any plugin loading at runtime. It is harmful. -# check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN) - -# From /cmake/find/zlib.cmake -if (ZLIB_FOUND) - set(HAVE_ZLIB_H ON) - set(HAVE_LIBZ ON) - set(USE_ZLIB ON) - - list(APPEND CURL_LIBS ${ZLIB_LIBRARIES}) -endif() - -option(ENABLE_UNIX_SOCKETS "Define if you want Unix domain sockets support" OFF) -if(ENABLE_UNIX_SOCKETS) - include(CheckStructHasMember) - check_struct_has_member("struct sockaddr_un" sun_path "sys/un.h" USE_UNIX_SOCKETS) -else() - unset(USE_UNIX_SOCKETS CACHE) -endif() - -# CA handling -# Explicitly set to most common case -if (OPENSSL_FOUND) - set(CURL_CA_BUNDLE "/etc/ssl/certs/ca-certificates.crt") - set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set") - set(CURL_CA_PATH "/etc/ssl/certs") - set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set") -endif() - -check_include_file_concat("stdio.h" HAVE_STDIO_H) -check_include_file_concat("inttypes.h" HAVE_INTTYPES_H) -check_include_file_concat("sys/filio.h" HAVE_SYS_FILIO_H) -check_include_file_concat("sys/ioctl.h" HAVE_SYS_IOCTL_H) -check_include_file_concat("sys/param.h" HAVE_SYS_PARAM_H) -check_include_file_concat("sys/poll.h" HAVE_SYS_POLL_H) -check_include_file_concat("sys/resource.h" HAVE_SYS_RESOURCE_H) -check_include_file_concat("sys/select.h" HAVE_SYS_SELECT_H) -check_include_file_concat("sys/socket.h" HAVE_SYS_SOCKET_H) -check_include_file_concat("sys/sockio.h" HAVE_SYS_SOCKIO_H) -check_include_file_concat("sys/stat.h" HAVE_SYS_STAT_H) -check_include_file_concat("sys/time.h" HAVE_SYS_TIME_H) -check_include_file_concat("sys/types.h" HAVE_SYS_TYPES_H) -check_include_file_concat("sys/uio.h" HAVE_SYS_UIO_H) -check_include_file_concat("sys/un.h" HAVE_SYS_UN_H) -check_include_file_concat("sys/utime.h" HAVE_SYS_UTIME_H) -check_include_file_concat("sys/xattr.h" HAVE_SYS_XATTR_H) -check_include_file_concat("alloca.h" HAVE_ALLOCA_H) -check_include_file_concat("arpa/inet.h" HAVE_ARPA_INET_H) -#check_include_file_concat("arpa/tftp.h" HAVE_ARPA_TFTP_H) -check_include_file_concat("assert.h" HAVE_ASSERT_H) -check_include_file_concat("crypto.h" HAVE_CRYPTO_H) -check_include_file_concat("des.h" HAVE_DES_H) -check_include_file_concat("err.h" HAVE_ERR_H) -check_include_file_concat("errno.h" HAVE_ERRNO_H) -check_include_file_concat("fcntl.h" HAVE_FCNTL_H) -#check_include_file_concat("idn2.h" HAVE_IDN2_H) -check_include_file_concat("ifaddrs.h" HAVE_IFADDRS_H) -check_include_file_concat("io.h" HAVE_IO_H) -check_include_file_concat("krb.h" HAVE_KRB_H) -check_include_file_concat("libgen.h" HAVE_LIBGEN_H) -check_include_file_concat("locale.h" HAVE_LOCALE_H) -check_include_file_concat("net/if.h" HAVE_NET_IF_H) -check_include_file_concat("netdb.h" HAVE_NETDB_H) -check_include_file_concat("netinet/in.h" HAVE_NETINET_IN_H) -check_include_file_concat("netinet/tcp.h" HAVE_NETINET_TCP_H) - -check_include_file_concat("pem.h" HAVE_PEM_H) -check_include_file_concat("poll.h" HAVE_POLL_H) -check_include_file_concat("pwd.h" HAVE_PWD_H) -check_include_file_concat("rsa.h" HAVE_RSA_H) -check_include_file_concat("setjmp.h" HAVE_SETJMP_H) -check_include_file_concat("sgtty.h" HAVE_SGTTY_H) -check_include_file_concat("signal.h" HAVE_SIGNAL_H) -check_include_file_concat("ssl.h" HAVE_SSL_H) -check_include_file_concat("stdbool.h" HAVE_STDBOOL_H) -check_include_file_concat("stdint.h" HAVE_STDINT_H) -check_include_file_concat("stdio.h" HAVE_STDIO_H) -check_include_file_concat("stdlib.h" HAVE_STDLIB_H) -check_include_file_concat("string.h" HAVE_STRING_H) -check_include_file_concat("strings.h" HAVE_STRINGS_H) -check_include_file_concat("stropts.h" HAVE_STROPTS_H) -check_include_file_concat("termio.h" HAVE_TERMIO_H) -check_include_file_concat("termios.h" HAVE_TERMIOS_H) -check_include_file_concat("time.h" HAVE_TIME_H) -check_include_file_concat("unistd.h" HAVE_UNISTD_H) -check_include_file_concat("utime.h" HAVE_UTIME_H) -check_include_file_concat("x509.h" HAVE_X509_H) - -check_include_file_concat("process.h" HAVE_PROCESS_H) -check_include_file_concat("stddef.h" HAVE_STDDEF_H) -#check_include_file_concat("dlfcn.h" HAVE_DLFCN_H) -check_include_file_concat("malloc.h" HAVE_MALLOC_H) -check_include_file_concat("memory.h" HAVE_MEMORY_H) -check_include_file_concat("netinet/if_ether.h" HAVE_NETINET_IF_ETHER_H) -check_include_file_concat("stdint.h" HAVE_STDINT_H) -check_include_file_concat("sockio.h" HAVE_SOCKIO_H) -check_include_file_concat("sys/utsname.h" HAVE_SYS_UTSNAME_H) - -check_type_size(size_t SIZEOF_SIZE_T) -check_type_size(ssize_t SIZEOF_SSIZE_T) -check_type_size("long long" SIZEOF_LONG_LONG) -check_type_size("long" SIZEOF_LONG) -check_type_size("short" SIZEOF_SHORT) -check_type_size("int" SIZEOF_INT) -check_type_size("__int64" SIZEOF___INT64) -check_type_size("long double" SIZEOF_LONG_DOUBLE) -check_type_size("time_t" SIZEOF_TIME_T) - -set(HAVE_LONGLONG 1) -set(HAVE_LL 1) - -set(RANDOM_FILE /dev/urandom) - -check_symbol_exists(basename "${CURL_INCLUDES}" HAVE_BASENAME) -check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET) -check_symbol_exists(select "${CURL_INCLUDES}" HAVE_SELECT) -check_symbol_exists(poll "${CURL_INCLUDES}" HAVE_POLL) -check_symbol_exists(strdup "${CURL_INCLUDES}" HAVE_STRDUP) -check_symbol_exists(strstr "${CURL_INCLUDES}" HAVE_STRSTR) -check_symbol_exists(strtok_r "${CURL_INCLUDES}" HAVE_STRTOK_R) -check_symbol_exists(strftime "${CURL_INCLUDES}" HAVE_STRFTIME) -check_symbol_exists(uname "${CURL_INCLUDES}" HAVE_UNAME) -check_symbol_exists(strcasecmp "${CURL_INCLUDES}" HAVE_STRCASECMP) -#check_symbol_exists(stricmp "${CURL_INCLUDES}" HAVE_STRICMP) -#check_symbol_exists(strcmpi "${CURL_INCLUDES}" HAVE_STRCMPI) -#check_symbol_exists(strncmpi "${CURL_INCLUDES}" HAVE_STRNCMPI) -check_symbol_exists(alarm "${CURL_INCLUDES}" HAVE_ALARM) -#check_symbol_exists(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR) -check_symbol_exists(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R) -check_symbol_exists(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY) -check_symbol_exists(inet_addr "${CURL_INCLUDES}" HAVE_INET_ADDR) -#check_symbol_exists(inet_ntoa "${CURL_INCLUDES}" HAVE_INET_NTOA) -check_symbol_exists(inet_ntoa_r "${CURL_INCLUDES}" HAVE_INET_NTOA_R) -check_symbol_exists(tcsetattr "${CURL_INCLUDES}" HAVE_TCSETATTR) -check_symbol_exists(tcgetattr "${CURL_INCLUDES}" HAVE_TCGETATTR) -check_symbol_exists(perror "${CURL_INCLUDES}" HAVE_PERROR) -check_symbol_exists(closesocket "${CURL_INCLUDES}" HAVE_CLOSESOCKET) -check_symbol_exists(setvbuf "${CURL_INCLUDES}" HAVE_SETVBUF) -check_symbol_exists(sigsetjmp "${CURL_INCLUDES}" HAVE_SIGSETJMP) -check_symbol_exists(getpass_r "${CURL_INCLUDES}" HAVE_GETPASS_R) -#check_symbol_exists(strlcat "${CURL_INCLUDES}" HAVE_STRLCAT) -#check_symbol_exists(getpwuid "${CURL_INCLUDES}" HAVE_GETPWUID) -check_symbol_exists(getpwuid_r "${CURL_INCLUDES}" HAVE_GETPWUID_R) -check_symbol_exists(geteuid "${CURL_INCLUDES}" HAVE_GETEUID) -check_symbol_exists(usleep "${CURL_INCLUDES}" HAVE_USLEEP) -check_symbol_exists(utime "${CURL_INCLUDES}" HAVE_UTIME) -check_symbol_exists(gmtime_r "${CURL_INCLUDES}" HAVE_GMTIME_R) -check_symbol_exists(localtime_r "${CURL_INCLUDES}" HAVE_LOCALTIME_R) - -#check_symbol_exists(gethostbyname "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME) -check_symbol_exists(gethostbyname_r "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R) - -check_symbol_exists(signal "${CURL_INCLUDES}" HAVE_SIGNAL_FUNC) -check_symbol_exists(SIGALRM "${CURL_INCLUDES}" HAVE_SIGNAL_MACRO) -set(HAVE_SIGNAL 1) -check_symbol_exists(uname "${CURL_INCLUDES}" HAVE_UNAME) -check_symbol_exists(strtoll "${CURL_INCLUDES}" HAVE_STRTOLL) -#check_symbol_exists(_strtoi64 "${CURL_INCLUDES}" HAVE__STRTOI64) -check_symbol_exists(strerror_r "${CURL_INCLUDES}" HAVE_STRERROR_R) -check_symbol_exists(siginterrupt "${CURL_INCLUDES}" HAVE_SIGINTERRUPT) -check_symbol_exists(perror "${CURL_INCLUDES}" HAVE_PERROR) -check_symbol_exists(fork "${CURL_INCLUDES}" HAVE_FORK) -check_symbol_exists(getaddrinfo "${CURL_INCLUDES}" HAVE_GETADDRINFO) -check_symbol_exists(freeaddrinfo "${CURL_INCLUDES}" HAVE_FREEADDRINFO) -check_symbol_exists(freeifaddrs "${CURL_INCLUDES}" HAVE_FREEIFADDRS) -check_symbol_exists(pipe "${CURL_INCLUDES}" HAVE_PIPE) -check_symbol_exists(ftruncate "${CURL_INCLUDES}" HAVE_FTRUNCATE) -check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME) -check_symbol_exists(getpeername "${CURL_INCLUDES}" HAVE_GETPEERNAME) -check_symbol_exists(getsockname "${CURL_INCLUDES}" HAVE_GETSOCKNAME) -check_symbol_exists(if_nametoindex "${CURL_INCLUDES}" HAVE_IF_NAMETOINDEX) -check_symbol_exists(getrlimit "${CURL_INCLUDES}" HAVE_GETRLIMIT) -check_symbol_exists(setlocale "${CURL_INCLUDES}" HAVE_SETLOCALE) -check_symbol_exists(setmode "${CURL_INCLUDES}" HAVE_SETMODE) -check_symbol_exists(setrlimit "${CURL_INCLUDES}" HAVE_SETRLIMIT) -check_symbol_exists(fcntl "${CURL_INCLUDES}" HAVE_FCNTL) -check_symbol_exists(ioctl "${CURL_INCLUDES}" HAVE_IOCTL) -check_symbol_exists(setsockopt "${CURL_INCLUDES}" HAVE_SETSOCKOPT) -check_function_exists(mach_absolute_time HAVE_MACH_ABSOLUTE_TIME) - -check_symbol_exists(fsetxattr "${CURL_INCLUDES}" HAVE_FSETXATTR) -if(HAVE_FSETXATTR) - foreach(CURL_TEST HAVE_FSETXATTR_5 HAVE_FSETXATTR_6) - curl_internal_test(${CURL_TEST}) - endforeach() -endif() - -# sigaction and sigsetjmp are special. Use special mechanism for -# detecting those, but only if previous attempt failed. -if(HAVE_SIGNAL_H) - check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION) -endif() - -if(NOT HAVE_SIGSETJMP) - if(HAVE_SETJMP_H) - check_symbol_exists(sigsetjmp "setjmp.h" HAVE_MACRO_SIGSETJMP) - if(HAVE_MACRO_SIGSETJMP) - set(HAVE_SIGSETJMP 1) - endif() - endif() -endif() - -# If there is no stricmp(), do not allow LDAP to parse URLs -if(NOT HAVE_STRICMP) - set(HAVE_LDAP_URL_PARSE 1) -endif() - -# Do curl specific tests -foreach(CURL_TEST - HAVE_FCNTL_O_NONBLOCK - HAVE_IOCTLSOCKET - HAVE_IOCTLSOCKET_CAMEL - HAVE_IOCTLSOCKET_CAMEL_FIONBIO - HAVE_IOCTLSOCKET_FIONBIO - HAVE_IOCTL_FIONBIO - HAVE_IOCTL_SIOCGIFADDR - HAVE_SETSOCKOPT_SO_NONBLOCK - HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID - TIME_WITH_SYS_TIME - HAVE_O_NONBLOCK - HAVE_GETHOSTBYADDR_R_5 - HAVE_GETHOSTBYADDR_R_7 - HAVE_GETHOSTBYADDR_R_8 - HAVE_GETHOSTBYADDR_R_5_REENTRANT - HAVE_GETHOSTBYADDR_R_7_REENTRANT - HAVE_GETHOSTBYADDR_R_8_REENTRANT - HAVE_GETHOSTBYNAME_R_3 - HAVE_GETHOSTBYNAME_R_5 - HAVE_GETHOSTBYNAME_R_6 - HAVE_GETHOSTBYNAME_R_3_REENTRANT - HAVE_GETHOSTBYNAME_R_5_REENTRANT - HAVE_GETHOSTBYNAME_R_6_REENTRANT - HAVE_IN_ADDR_T - HAVE_BOOL_T - STDC_HEADERS - RETSIGTYPE_TEST - HAVE_INET_NTOA_R_DECL - HAVE_INET_NTOA_R_DECL_REENTRANT - HAVE_GETADDRINFO - HAVE_FILE_OFFSET_BITS - HAVE_VARIADIC_MACROS_C99 - HAVE_VARIADIC_MACROS_GCC - ) - curl_internal_test(${CURL_TEST}) -endforeach() - -if(HAVE_FILE_OFFSET_BITS) - set(_FILE_OFFSET_BITS 64) - set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64") -endif() -check_type_size("off_t" SIZEOF_OFF_T) - -# include this header to get the type -set(CMAKE_REQUIRED_INCLUDES "${CURL_SOURCE_DIR}/include") -set(CMAKE_EXTRA_INCLUDE_FILES "curl/system.h") -check_type_size("curl_off_t" SIZEOF_CURL_OFF_T) -set(CMAKE_EXTRA_INCLUDE_FILES "") - -foreach(CURL_TEST - HAVE_GLIBC_STRERROR_R - HAVE_POSIX_STRERROR_R - ) - curl_internal_test(${CURL_TEST}) -endforeach() - -# Check for reentrant -foreach(CURL_TEST - HAVE_GETHOSTBYADDR_R_5 - HAVE_GETHOSTBYADDR_R_7 - HAVE_GETHOSTBYADDR_R_8 - HAVE_GETHOSTBYNAME_R_3 - HAVE_GETHOSTBYNAME_R_5 - HAVE_GETHOSTBYNAME_R_6 - HAVE_INET_NTOA_R_DECL_REENTRANT) - if(NOT ${CURL_TEST}) - if(${CURL_TEST}_REENTRANT) - set(NEED_REENTRANT 1) - endif() - endif() -endforeach() - -if(NEED_REENTRANT) - foreach(CURL_TEST - HAVE_GETHOSTBYADDR_R_5 - HAVE_GETHOSTBYADDR_R_7 - HAVE_GETHOSTBYADDR_R_8 - HAVE_GETHOSTBYNAME_R_3 - HAVE_GETHOSTBYNAME_R_5 - HAVE_GETHOSTBYNAME_R_6) - set(${CURL_TEST} 0) - if(${CURL_TEST}_REENTRANT) - set(${CURL_TEST} 1) - endif() - endforeach() -endif() - -if(HAVE_INET_NTOA_R_DECL_REENTRANT) - set(HAVE_INET_NTOA_R_DECL 1) - set(NEED_REENTRANT 1) -endif() - -# Check clock_gettime(CLOCK_MONOTONIC, x) support -curl_internal_test(HAVE_CLOCK_GETTIME_MONOTONIC) - -# Check compiler support of __builtin_available() -curl_internal_test(HAVE_BUILTIN_AVAILABLE) - -# Some other minor tests - -if(NOT HAVE_IN_ADDR_T) - set(in_addr_t "unsigned long") -endif() - -# Check for nonblocking -set(HAVE_DISABLED_NONBLOCKING 1) -if(HAVE_FIONBIO OR - HAVE_IOCTLSOCKET OR - HAVE_IOCTLSOCKET_CASE OR - HAVE_O_NONBLOCK) - set(HAVE_DISABLED_NONBLOCKING) -endif() - -set(CURL_PULL_SYS_TYPES_H ${HAVE_SYS_TYPES_H}) -set(CURL_PULL_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H}) -set(CURL_PULL_SYS_POLL_H ${HAVE_SYS_POLL_H}) -set(CURL_PULL_STDINT_H ${HAVE_STDINT_H}) -set(CURL_PULL_INTTYPES_H ${HAVE_INTTYPES_H}) - -include(CMake/OtherTests.cmake) - -SET(LIB_VAUTH_CFILES - "${CURL_LIBRARY_DIR}/vauth/vauth.c" "${CURL_LIBRARY_DIR}/vauth/cleartext.c" "${CURL_LIBRARY_DIR}/vauth/cram.c" - "${CURL_LIBRARY_DIR}/vauth/digest.c" "${CURL_LIBRARY_DIR}/vauth/digest_sspi.c" "${CURL_LIBRARY_DIR}/vauth/krb5_gssapi.c" - "${CURL_LIBRARY_DIR}/vauth/krb5_sspi.c" "${CURL_LIBRARY_DIR}/vauth/ntlm.c" "${CURL_LIBRARY_DIR}/vauth/ntlm_sspi.c" "${CURL_LIBRARY_DIR}/vauth/oauth2.c" - "${CURL_LIBRARY_DIR}/vauth/spnego_gssapi.c" "${CURL_LIBRARY_DIR}/vauth/spnego_sspi.c") - -SET(LIB_VAUTH_HFILES "${CURL_LIBRARY_DIR}/vauth/vauth.h" "${CURL_LIBRARY_DIR}/vauth/digest.h" "${CURL_LIBRARY_DIR}/vauth/ntlm.h") - -SET(LIB_VTLS_CFILES "${CURL_LIBRARY_DIR}/vtls/openssl.c" "${CURL_LIBRARY_DIR}/vtls/gtls.c" "${CURL_LIBRARY_DIR}/vtls/vtls.c" "${CURL_LIBRARY_DIR}/vtls/nss.c" - "${CURL_LIBRARY_DIR}/vtls/polarssl.c" "${CURL_LIBRARY_DIR}/vtls/polarssl_threadlock.c" - "${CURL_LIBRARY_DIR}/vtls/wolfssl.c" "${CURL_LIBRARY_DIR}/vtls/schannel.c" "${CURL_LIBRARY_DIR}/vtls/schannel_verify.c" - "${CURL_LIBRARY_DIR}/vtls/sectransp.c" "${CURL_LIBRARY_DIR}/vtls/gskit.c" "${CURL_LIBRARY_DIR}/vtls/mbedtls.c" "${CURL_LIBRARY_DIR}/vtls/mesalink.c" - "${CURL_LIBRARY_DIR}/vtls/bearssl.c") - -SET(LIB_VTLS_HFILES "${CURL_LIBRARY_DIR}/vtls/openssl.h" "${CURL_LIBRARY_DIR}/vtls/vtls.h" "${CURL_LIBRARY_DIR}/vtls/gtls.h" - "${CURL_LIBRARY_DIR}/vtls/nssg.h" "${CURL_LIBRARY_DIR}/vtls/polarssl.h" "${CURL_LIBRARY_DIR}/vtls/polarssl_threadlock.h" - "${CURL_LIBRARY_DIR}/vtls/wolfssl.h" "${CURL_LIBRARY_DIR}/vtls/schannel.h" "${CURL_LIBRARY_DIR}/vtls/sectransp.h" "${CURL_LIBRARY_DIR}/vtls/gskit.h" - "${CURL_LIBRARY_DIR}/vtls/mbedtls.h" "${CURL_LIBRARY_DIR}/vtls/mesalink.h" "${CURL_LIBRARY_DIR}/vtls/bearssl.h") - -SET(LIB_VQUIC_CFILES "${CURL_LIBRARY_DIR}/vquic/ngtcp2.c" "${CURL_LIBRARY_DIR}/vquic/quiche.c") - -SET(LIB_VQUIC_HFILES "${CURL_LIBRARY_DIR}/vquic/ngtcp2.h" "${CURL_LIBRARY_DIR}/vquic/quiche.h") - -SET(LIB_VSSH_CFILES "${CURL_LIBRARY_DIR}/vssh/libssh2.c" "${CURL_LIBRARY_DIR}/vssh/libssh.c") - -SET(LIB_VSSH_HFILES "${CURL_LIBRARY_DIR}/vssh/ssh.h") - -SET(LIB_CFILES "${CURL_LIBRARY_DIR}/file.c" - "${CURL_LIBRARY_DIR}/timeval.c" "${CURL_LIBRARY_DIR}/base64.c" "${CURL_LIBRARY_DIR}/hostip.c" "${CURL_LIBRARY_DIR}/progress.c" "${CURL_LIBRARY_DIR}/formdata.c" - "${CURL_LIBRARY_DIR}/cookie.c" "${CURL_LIBRARY_DIR}/http.c" "${CURL_LIBRARY_DIR}/sendf.c" "${CURL_LIBRARY_DIR}/url.c" "${CURL_LIBRARY_DIR}/dict.c" "${CURL_LIBRARY_DIR}/if2ip.c" "${CURL_LIBRARY_DIR}/speedcheck.c" - "${CURL_LIBRARY_DIR}/ldap.c" "${CURL_LIBRARY_DIR}/version.c" "${CURL_LIBRARY_DIR}/getenv.c" "${CURL_LIBRARY_DIR}/escape.c" "${CURL_LIBRARY_DIR}/mprintf.c" "${CURL_LIBRARY_DIR}/telnet.c" "${CURL_LIBRARY_DIR}/netrc.c" - "${CURL_LIBRARY_DIR}/getinfo.c" "${CURL_LIBRARY_DIR}/transfer.c" "${CURL_LIBRARY_DIR}/strcase.c" "${CURL_LIBRARY_DIR}/easy.c" "${CURL_LIBRARY_DIR}/security.c" "${CURL_LIBRARY_DIR}/curl_fnmatch.c" - "${CURL_LIBRARY_DIR}/fileinfo.c" "${CURL_LIBRARY_DIR}/wildcard.c" "${CURL_LIBRARY_DIR}/krb5.c" "${CURL_LIBRARY_DIR}/memdebug.c" "${CURL_LIBRARY_DIR}/http_chunks.c" - "${CURL_LIBRARY_DIR}/strtok.c" "${CURL_LIBRARY_DIR}/connect.c" "${CURL_LIBRARY_DIR}/llist.c" "${CURL_LIBRARY_DIR}/hash.c" "${CURL_LIBRARY_DIR}/multi.c" "${CURL_LIBRARY_DIR}/content_encoding.c" "${CURL_LIBRARY_DIR}/share.c" - "${CURL_LIBRARY_DIR}/http_digest.c" "${CURL_LIBRARY_DIR}/md4.c" "${CURL_LIBRARY_DIR}/md5.c" "${CURL_LIBRARY_DIR}/http_negotiate.c" "${CURL_LIBRARY_DIR}/inet_pton.c" "${CURL_LIBRARY_DIR}/strtoofft.c" - "${CURL_LIBRARY_DIR}/strerror.c" "${CURL_LIBRARY_DIR}/amigaos.c" "${CURL_LIBRARY_DIR}/hostasyn.c" "${CURL_LIBRARY_DIR}/hostip4.c" "${CURL_LIBRARY_DIR}/hostip6.c" "${CURL_LIBRARY_DIR}/hostsyn.c" - "${CURL_LIBRARY_DIR}/inet_ntop.c" "${CURL_LIBRARY_DIR}/parsedate.c" "${CURL_LIBRARY_DIR}/select.c" "${CURL_LIBRARY_DIR}/splay.c" "${CURL_LIBRARY_DIR}/strdup.c" "${CURL_LIBRARY_DIR}/socks.c" - "${CURL_LIBRARY_DIR}/curl_addrinfo.c" "${CURL_LIBRARY_DIR}/socks_gssapi.c" "${CURL_LIBRARY_DIR}/socks_sspi.c" - "${CURL_LIBRARY_DIR}/curl_sspi.c" "${CURL_LIBRARY_DIR}/slist.c" "${CURL_LIBRARY_DIR}/nonblock.c" "${CURL_LIBRARY_DIR}/curl_memrchr.c" "${CURL_LIBRARY_DIR}/imap.c" "${CURL_LIBRARY_DIR}/pop3.c" "${CURL_LIBRARY_DIR}/smtp.c" - "${CURL_LIBRARY_DIR}/pingpong.c" "${CURL_LIBRARY_DIR}/rtsp.c" "${CURL_LIBRARY_DIR}/curl_threads.c" "${CURL_LIBRARY_DIR}/warnless.c" "${CURL_LIBRARY_DIR}/hmac.c" "${CURL_LIBRARY_DIR}/curl_rtmp.c" - "${CURL_LIBRARY_DIR}/openldap.c" "${CURL_LIBRARY_DIR}/curl_gethostname.c" "${CURL_LIBRARY_DIR}/gopher.c" "${CURL_LIBRARY_DIR}/idn_win32.c" - "${CURL_LIBRARY_DIR}/http_proxy.c" "${CURL_LIBRARY_DIR}/non-ascii.c" "${CURL_LIBRARY_DIR}/asyn-ares.c" "${CURL_LIBRARY_DIR}/asyn-thread.c" "${CURL_LIBRARY_DIR}/curl_gssapi.c" - "${CURL_LIBRARY_DIR}/http_ntlm.c" "${CURL_LIBRARY_DIR}/curl_ntlm_wb.c" "${CURL_LIBRARY_DIR}/curl_ntlm_core.c" "${CURL_LIBRARY_DIR}/curl_sasl.c" "${CURL_LIBRARY_DIR}/rand.c" - "${CURL_LIBRARY_DIR}/curl_multibyte.c" "${CURL_LIBRARY_DIR}/hostcheck.c" "${CURL_LIBRARY_DIR}/conncache.c" "${CURL_LIBRARY_DIR}/dotdot.c" - "${CURL_LIBRARY_DIR}/x509asn1.c" "${CURL_LIBRARY_DIR}/http2.c" "${CURL_LIBRARY_DIR}/smb.c" "${CURL_LIBRARY_DIR}/curl_endian.c" "${CURL_LIBRARY_DIR}/curl_des.c" "${CURL_LIBRARY_DIR}/system_win32.c" - "${CURL_LIBRARY_DIR}/mime.c" "${CURL_LIBRARY_DIR}/sha256.c" "${CURL_LIBRARY_DIR}/setopt.c" "${CURL_LIBRARY_DIR}/curl_path.c" "${CURL_LIBRARY_DIR}/curl_ctype.c" "${CURL_LIBRARY_DIR}/curl_range.c" "${CURL_LIBRARY_DIR}/psl.c" - "${CURL_LIBRARY_DIR}/doh.c" "${CURL_LIBRARY_DIR}/urlapi.c" "${CURL_LIBRARY_DIR}/curl_get_line.c" "${CURL_LIBRARY_DIR}/altsvc.c" "${CURL_LIBRARY_DIR}/socketpair.c") - -SET(LIB_HFILES "${CURL_LIBRARY_DIR}/arpa_telnet.h" "${CURL_LIBRARY_DIR}/netrc.h" "${CURL_LIBRARY_DIR}/file.h" "${CURL_LIBRARY_DIR}/timeval.h" "${CURL_LIBRARY_DIR}/hostip.h" "${CURL_LIBRARY_DIR}/progress.h" - "${CURL_LIBRARY_DIR}/formdata.h" "${CURL_LIBRARY_DIR}/cookie.h" "${CURL_LIBRARY_DIR}/http.h" "${CURL_LIBRARY_DIR}/sendf.h" "${CURL_LIBRARY_DIR}/url.h" "${CURL_LIBRARY_DIR}/dict.h" "${CURL_LIBRARY_DIR}/if2ip.h" - "${CURL_LIBRARY_DIR}/speedcheck.h" "${CURL_LIBRARY_DIR}/urldata.h" "${CURL_LIBRARY_DIR}/curl_ldap.h" "${CURL_LIBRARY_DIR}/escape.h" "${CURL_LIBRARY_DIR}/telnet.h" "${CURL_LIBRARY_DIR}/getinfo.h" - "${CURL_LIBRARY_DIR}/strcase.h" "${CURL_LIBRARY_DIR}/curl_sec.h" "${CURL_LIBRARY_DIR}/memdebug.h" "${CURL_LIBRARY_DIR}/http_chunks.h" "${CURL_LIBRARY_DIR}/curl_fnmatch.h" - "${CURL_LIBRARY_DIR}/wildcard.h" "${CURL_LIBRARY_DIR}/fileinfo.h" "${CURL_LIBRARY_DIR}/strtok.h" "${CURL_LIBRARY_DIR}/connect.h" "${CURL_LIBRARY_DIR}/llist.h" - "${CURL_LIBRARY_DIR}/hash.h" "${CURL_LIBRARY_DIR}/content_encoding.h" "${CURL_LIBRARY_DIR}/share.h" "${CURL_LIBRARY_DIR}/curl_md4.h" "${CURL_LIBRARY_DIR}/curl_md5.h" "${CURL_LIBRARY_DIR}/http_digest.h" - "${CURL_LIBRARY_DIR}/http_negotiate.h" "${CURL_LIBRARY_DIR}/inet_pton.h" "${CURL_LIBRARY_DIR}/amigaos.h" "${CURL_LIBRARY_DIR}/strtoofft.h" "${CURL_LIBRARY_DIR}/strerror.h" - "${CURL_LIBRARY_DIR}/inet_ntop.h" "${CURL_LIBRARY_DIR}/curlx.h" "${CURL_LIBRARY_DIR}/curl_memory.h" "${CURL_LIBRARY_DIR}/curl_setup.h" "${CURL_LIBRARY_DIR}/transfer.h" "${CURL_LIBRARY_DIR}/select.h" - "${CURL_LIBRARY_DIR}/easyif.h" "${CURL_LIBRARY_DIR}/multiif.h" "${CURL_LIBRARY_DIR}/parsedate.h" "${CURL_LIBRARY_DIR}/sockaddr.h" "${CURL_LIBRARY_DIR}/splay.h" "${CURL_LIBRARY_DIR}/strdup.h" - "${CURL_LIBRARY_DIR}/socks.h" "${CURL_LIBRARY_DIR}/curl_base64.h" "${CURL_LIBRARY_DIR}/curl_addrinfo.h" "${CURL_LIBRARY_DIR}/curl_sspi.h" - "${CURL_LIBRARY_DIR}/slist.h" "${CURL_LIBRARY_DIR}/nonblock.h" "${CURL_LIBRARY_DIR}/curl_memrchr.h" "${CURL_LIBRARY_DIR}/imap.h" "${CURL_LIBRARY_DIR}/pop3.h" "${CURL_LIBRARY_DIR}/smtp.h" "${CURL_LIBRARY_DIR}/pingpong.h" - "${CURL_LIBRARY_DIR}/rtsp.h" "${CURL_LIBRARY_DIR}/curl_threads.h" "${CURL_LIBRARY_DIR}/warnless.h" "${CURL_LIBRARY_DIR}/curl_hmac.h" "${CURL_LIBRARY_DIR}/curl_rtmp.h" - "${CURL_LIBRARY_DIR}/curl_gethostname.h" "${CURL_LIBRARY_DIR}/gopher.h" "${CURL_LIBRARY_DIR}/http_proxy.h" "${CURL_LIBRARY_DIR}/non-ascii.h" "${CURL_LIBRARY_DIR}/asyn.h" - "${CURL_LIBRARY_DIR}/http_ntlm.h" "${CURL_LIBRARY_DIR}/curl_gssapi.h" "${CURL_LIBRARY_DIR}/curl_ntlm_wb.h" "${CURL_LIBRARY_DIR}/curl_ntlm_core.h" - "${CURL_LIBRARY_DIR}/curl_sasl.h" "${CURL_LIBRARY_DIR}/curl_multibyte.h" "${CURL_LIBRARY_DIR}/hostcheck.h" "${CURL_LIBRARY_DIR}/conncache.h" - "${CURL_LIBRARY_DIR}/multihandle.h" "${CURL_LIBRARY_DIR}/setup-vms.h" "${CURL_LIBRARY_DIR}/dotdot.h" - "${CURL_LIBRARY_DIR}/x509asn1.h" "${CURL_LIBRARY_DIR}/http2.h" "${CURL_LIBRARY_DIR}/sigpipe.h" "${CURL_LIBRARY_DIR}/smb.h" "${CURL_LIBRARY_DIR}/curl_endian.h" "${CURL_LIBRARY_DIR}/curl_des.h" - "${CURL_LIBRARY_DIR}/curl_printf.h" "${CURL_LIBRARY_DIR}/system_win32.h" "${CURL_LIBRARY_DIR}/rand.h" "${CURL_LIBRARY_DIR}/mime.h" "${CURL_LIBRARY_DIR}/curl_sha256.h" "${CURL_LIBRARY_DIR}/setopt.h" - "${CURL_LIBRARY_DIR}/curl_path.h" "${CURL_LIBRARY_DIR}/curl_ctype.h" "${CURL_LIBRARY_DIR}/curl_range.h" "${CURL_LIBRARY_DIR}/psl.h" "${CURL_LIBRARY_DIR}/doh.h" "${CURL_LIBRARY_DIR}/urlapi-int.h" - "${CURL_LIBRARY_DIR}/curl_get_line.h" "${CURL_LIBRARY_DIR}/altsvc.h" "${CURL_LIBRARY_DIR}/quic.h" "${CURL_LIBRARY_DIR}/socketpair.h") - -SET(LIB_RCFILES "${CURL_LIBRARY_DIR}/libcurl.rc") - -SET(CSOURCES ${LIB_CFILES} ${LIB_VAUTH_CFILES} ${LIB_VTLS_CFILES} - ${LIB_VQUIC_CFILES} ${LIB_VSSH_CFILES}) -SET(HHEADERS ${LIB_HFILES} ${LIB_VAUTH_HFILES} ${LIB_VTLS_HFILES} - ${LIB_VQUIC_HFILES} ${LIB_VSSH_HFILES}) - -configure_file(${CURL_SOURCE_DIR}/lib/curl_config.h.cmake - ${CMAKE_CURRENT_BINARY_DIR}/curl/curl_config.h) - -list(APPEND HHEADERS - ${CMAKE_CURRENT_BINARY_DIR}/curl/curl_config.h - ) - -add_library(libcurl ${HHEADERS} ${CSOURCES}) - -if(NOT BUILD_SHARED_LIBS) - set_target_properties(libcurl PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB) -endif() - -if(HIDES_CURL_PRIVATE_SYMBOLS) - set_property(TARGET libcurl APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS") - set_property(TARGET libcurl APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE}) -endif() - -if(OPENSSL_FOUND) - target_include_directories(libcurl PUBLIC ${OPENSSL_INCLUDE_DIR}) - message("-- Including openssl ${OPENSSL_INCLUDE_DIR} to curl") -endif() - -if(ZLIB_FOUND) - target_include_directories(libcurl PUBLIC ${ZLIB_INCLUDE_DIRS}}) - message("-- Including zlib ${ZLIB_INCLUDE_DIRS} to curl") -endif() - -target_compile_definitions(libcurl PUBLIC -DHAVE_CONFIG_H) -target_compile_definitions(libcurl PUBLIC -DBUILDING_LIBCURL) -target_include_directories(libcurl PUBLIC "${CURL_SOURCE_DIR}/include" "${CURL_LIBRARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/curl") - -target_link_libraries(libcurl ${CURL_LIBS}) +set (CURL_DIR ${ClickHouse_SOURCE_DIR}/contrib/curl) + +set (SRCS + ${CURL_DIR}/lib/file.c + ${CURL_DIR}/lib/timeval.c + ${CURL_DIR}/lib/base64.c + ${CURL_DIR}/lib/hostip.c + ${CURL_DIR}/lib/progress.c + ${CURL_DIR}/lib/formdata.c + ${CURL_DIR}/lib/cookie.c + ${CURL_DIR}/lib/http.c + ${CURL_DIR}/lib/sendf.c + ${CURL_DIR}/lib/url.c + ${CURL_DIR}/lib/dict.c + ${CURL_DIR}/lib/if2ip.c + ${CURL_DIR}/lib/speedcheck.c + ${CURL_DIR}/lib/ldap.c + ${CURL_DIR}/lib/version.c + ${CURL_DIR}/lib/getenv.c + ${CURL_DIR}/lib/escape.c + ${CURL_DIR}/lib/mprintf.c + ${CURL_DIR}/lib/telnet.c + ${CURL_DIR}/lib/netrc.c + ${CURL_DIR}/lib/getinfo.c + ${CURL_DIR}/lib/transfer.c + ${CURL_DIR}/lib/strcase.c + ${CURL_DIR}/lib/easy.c + ${CURL_DIR}/lib/security.c + ${CURL_DIR}/lib/curl_fnmatch.c + ${CURL_DIR}/lib/fileinfo.c + ${CURL_DIR}/lib/wildcard.c + ${CURL_DIR}/lib/krb5.c + ${CURL_DIR}/lib/memdebug.c + ${CURL_DIR}/lib/http_chunks.c + ${CURL_DIR}/lib/strtok.c + ${CURL_DIR}/lib/connect.c + ${CURL_DIR}/lib/llist.c + ${CURL_DIR}/lib/hash.c + ${CURL_DIR}/lib/multi.c + ${CURL_DIR}/lib/content_encoding.c + ${CURL_DIR}/lib/share.c + ${CURL_DIR}/lib/http_digest.c + ${CURL_DIR}/lib/md4.c + ${CURL_DIR}/lib/md5.c + ${CURL_DIR}/lib/http_negotiate.c + ${CURL_DIR}/lib/inet_pton.c + ${CURL_DIR}/lib/strtoofft.c + ${CURL_DIR}/lib/strerror.c + ${CURL_DIR}/lib/amigaos.c + ${CURL_DIR}/lib/hostasyn.c + ${CURL_DIR}/lib/hostip4.c + ${CURL_DIR}/lib/hostip6.c + ${CURL_DIR}/lib/hostsyn.c + ${CURL_DIR}/lib/inet_ntop.c + ${CURL_DIR}/lib/parsedate.c + ${CURL_DIR}/lib/select.c + ${CURL_DIR}/lib/splay.c + ${CURL_DIR}/lib/strdup.c + ${CURL_DIR}/lib/socks.c + ${CURL_DIR}/lib/curl_addrinfo.c + ${CURL_DIR}/lib/socks_gssapi.c + ${CURL_DIR}/lib/socks_sspi.c + ${CURL_DIR}/lib/curl_sspi.c + ${CURL_DIR}/lib/slist.c + ${CURL_DIR}/lib/nonblock.c + ${CURL_DIR}/lib/curl_memrchr.c + ${CURL_DIR}/lib/imap.c + ${CURL_DIR}/lib/pop3.c + ${CURL_DIR}/lib/smtp.c + ${CURL_DIR}/lib/pingpong.c + ${CURL_DIR}/lib/rtsp.c + ${CURL_DIR}/lib/curl_threads.c + ${CURL_DIR}/lib/warnless.c + ${CURL_DIR}/lib/hmac.c + ${CURL_DIR}/lib/curl_rtmp.c + ${CURL_DIR}/lib/openldap.c + ${CURL_DIR}/lib/curl_gethostname.c + ${CURL_DIR}/lib/gopher.c + ${CURL_DIR}/lib/idn_win32.c + ${CURL_DIR}/lib/http_proxy.c + ${CURL_DIR}/lib/non-ascii.c + ${CURL_DIR}/lib/asyn-thread.c + ${CURL_DIR}/lib/curl_gssapi.c + ${CURL_DIR}/lib/http_ntlm.c + ${CURL_DIR}/lib/curl_ntlm_wb.c + ${CURL_DIR}/lib/curl_ntlm_core.c + ${CURL_DIR}/lib/curl_sasl.c + ${CURL_DIR}/lib/rand.c + ${CURL_DIR}/lib/curl_multibyte.c + ${CURL_DIR}/lib/hostcheck.c + ${CURL_DIR}/lib/conncache.c + ${CURL_DIR}/lib/dotdot.c + ${CURL_DIR}/lib/x509asn1.c + ${CURL_DIR}/lib/http2.c + ${CURL_DIR}/lib/smb.c + ${CURL_DIR}/lib/curl_endian.c + ${CURL_DIR}/lib/curl_des.c + ${CURL_DIR}/lib/system_win32.c + ${CURL_DIR}/lib/mime.c + ${CURL_DIR}/lib/sha256.c + ${CURL_DIR}/lib/setopt.c + ${CURL_DIR}/lib/curl_path.c + ${CURL_DIR}/lib/curl_ctype.c + ${CURL_DIR}/lib/curl_range.c + ${CURL_DIR}/lib/psl.c + ${CURL_DIR}/lib/doh.c + ${CURL_DIR}/lib/urlapi.c + ${CURL_DIR}/lib/curl_get_line.c + ${CURL_DIR}/lib/altsvc.c + ${CURL_DIR}/lib/socketpair.c + ${CURL_DIR}/lib/vauth/vauth.c + ${CURL_DIR}/lib/vauth/cleartext.c + ${CURL_DIR}/lib/vauth/cram.c + ${CURL_DIR}/lib/vauth/digest.c + ${CURL_DIR}/lib/vauth/digest_sspi.c + ${CURL_DIR}/lib/vauth/krb5_gssapi.c + ${CURL_DIR}/lib/vauth/krb5_sspi.c + ${CURL_DIR}/lib/vauth/ntlm.c + ${CURL_DIR}/lib/vauth/ntlm_sspi.c + ${CURL_DIR}/lib/vauth/oauth2.c + ${CURL_DIR}/lib/vauth/spnego_gssapi.c + ${CURL_DIR}/lib/vauth/spnego_sspi.c + ${CURL_DIR}/lib/vtls/openssl.c + ${CURL_DIR}/lib/vtls/gtls.c + ${CURL_DIR}/lib/vtls/vtls.c + ${CURL_DIR}/lib/vtls/nss.c + ${CURL_DIR}/lib/vtls/polarssl.c + ${CURL_DIR}/lib/vtls/polarssl_threadlock.c + ${CURL_DIR}/lib/vtls/wolfssl.c + ${CURL_DIR}/lib/vtls/schannel.c + ${CURL_DIR}/lib/vtls/schannel_verify.c + ${CURL_DIR}/lib/vtls/sectransp.c + ${CURL_DIR}/lib/vtls/gskit.c + ${CURL_DIR}/lib/vtls/mbedtls.c + ${CURL_DIR}/lib/vtls/mesalink.c + ${CURL_DIR}/lib/vtls/bearssl.c + ${CURL_DIR}/lib/vquic/ngtcp2.c + ${CURL_DIR}/lib/vquic/quiche.c + ${CURL_DIR}/lib/vssh/libssh2.c + ${CURL_DIR}/lib/vssh/libssh.c +) + +add_library (curl ${SRCS}) + +target_compile_definitions(curl PRIVATE HAVE_CONFIG_H BUILDING_LIBCURL CURL_HIDDEN_SYMBOLS libcurl_EXPORTS) +target_include_directories(curl PUBLIC ${CURL_DIR}/include ${CURL_DIR}/lib .) + +target_compile_definitions(curl PRIVATE OS="${CMAKE_SYSTEM_NAME}") diff --git a/contrib/curl-cmake/curl_config.h b/contrib/curl-cmake/curl_config.h new file mode 100644 index 00000000000..c8f8e1b658f --- /dev/null +++ b/contrib/curl-cmake/curl_config.h @@ -0,0 +1,38 @@ +#define CURL_DISABLE_FTP +#define CURL_DISABLE_TFTP +#define CURL_DISABLE_LDAP +#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default"))) + +#define SIZEOF_SHORT 2 +#define SIZEOF_INT 4 +#define SIZEOF_LONG 8 +#define SIZEOF_CURL_OFF_T 8 +#define SIZEOF_SIZE_T 8 + +#define HAVE_FCNTL_O_NONBLOCK +#define HAVE_LONGLONG +#define HAVE_POLL_FINE +#define HAVE_SOCKET +#define HAVE_STRUCT_TIMEVAL + +#define HAVE_RECV +#define RECV_TYPE_ARG1 int +#define RECV_TYPE_ARG2 void* +#define RECV_TYPE_ARG3 size_t +#define RECV_TYPE_ARG4 int +#define RECV_TYPE_RETV ssize_t + +#define HAVE_SEND +#define SEND_TYPE_ARG1 int +#define SEND_TYPE_ARG2 void* +#define SEND_QUAL_ARG2 const +#define SEND_TYPE_ARG3 size_t +#define SEND_TYPE_ARG4 int +#define SEND_TYPE_RETV ssize_t + +#define HAVE_ARPA_INET_H +#define HAVE_ERRNO_H +#define HAVE_FCNTL_H +#define HAVE_NETDB_H +#define HAVE_SYS_STAT_H +#define HAVE_UNISTD_H diff --git a/dbms/programs/obfuscator/Obfuscator.cpp b/dbms/programs/obfuscator/Obfuscator.cpp index 49c6fabd435..83aa43ab2d2 100644 --- a/dbms/programs/obfuscator/Obfuscator.cpp +++ b/dbms/programs/obfuscator/Obfuscator.cpp @@ -1070,7 +1070,7 @@ try if (!silent) std::cerr << "Generating data\n"; - file_in.seek(0); + file_in.seek(0, SEEK_SET); BlockInputStreamPtr input = context.getInputFormat(input_format, file_in, header, max_block_size); BlockOutputStreamPtr output = context.getOutputFormat(output_format, file_out, header); diff --git a/dbms/src/Access/AccessControlManager.cpp b/dbms/src/Access/AccessControlManager.cpp index 249dc54fb09..b2e31bcac1f 100644 --- a/dbms/src/Access/AccessControlManager.cpp +++ b/dbms/src/Access/AccessControlManager.cpp @@ -2,8 +2,10 @@ #include #include #include +#include #include #include +#include namespace DB @@ -33,6 +35,49 @@ AccessControlManager::~AccessControlManager() } +UserPtr AccessControlManager::getUser(const String & user_name) const +{ + return getUser(user_name, {}, nullptr); +} + +UserPtr AccessControlManager::getUser( + const String & user_name, const std::function & on_change, ext::scope_guard * subscription) const +{ + UUID id = getID(user_name); + if (on_change && subscription) + { + *subscription = subscribeForChanges(id, [on_change](const UUID &, const AccessEntityPtr & user) + { + if (user) + on_change(typeid_cast(user)); + }); + } + return read(id); +} + + +UserPtr AccessControlManager::authorizeAndGetUser( + const String & user_name, + const String & password, + const Poco::Net::IPAddress & address) const +{ + return authorizeAndGetUser(user_name, password, address, {}, nullptr); +} + +UserPtr AccessControlManager::authorizeAndGetUser( + const String & user_name, + const String & password, + const Poco::Net::IPAddress & address, + const std::function & on_change, + ext::scope_guard * subscription) const +{ + auto user = getUser(user_name, on_change, subscription); + user->allowed_client_hosts.checkContains(address, user_name); + user->authentication.checkPassword(password, user_name); + return user; +} + + void AccessControlManager::loadFromConfig(const Poco::Util::AbstractConfiguration & users_config) { auto & users_config_access_storage = dynamic_cast(getStorageByIndex(1)); @@ -40,6 +85,12 @@ void AccessControlManager::loadFromConfig(const Poco::Util::AbstractConfiguratio } +std::shared_ptr AccessControlManager::getAccessRightsContext(const ClientInfo & client_info, const AccessRights & granted_to_user, const Settings & settings, const String & current_database) +{ + return std::make_shared(client_info, granted_to_user, settings, current_database); +} + + std::shared_ptr AccessControlManager::createQuotaContext( const String & user_name, const Poco::Net::IPAddress & address, const String & custom_quota_key) { diff --git a/dbms/src/Access/AccessControlManager.h b/dbms/src/Access/AccessControlManager.h index 9658dc7161d..538ad174bc2 100644 --- a/dbms/src/Access/AccessControlManager.h +++ b/dbms/src/Access/AccessControlManager.h @@ -2,6 +2,7 @@ #include #include +#include #include @@ -19,11 +20,17 @@ namespace Poco namespace DB { +struct User; +using UserPtr = std::shared_ptr; class QuotaContext; class QuotaContextFactory; struct QuotaUsageInfo; class RowPolicyContext; class RowPolicyContextFactory; +class AccessRights; +class AccessRightsContext; +class ClientInfo; +struct Settings; /// Manages access control entities. @@ -35,6 +42,13 @@ public: void loadFromConfig(const Poco::Util::AbstractConfiguration & users_config); + UserPtr getUser(const String & user_name) const; + UserPtr getUser(const String & user_name, const std::function & on_change, ext::scope_guard * subscription) const; + UserPtr authorizeAndGetUser(const String & user_name, const String & password, const Poco::Net::IPAddress & address) const; + UserPtr authorizeAndGetUser(const String & user_name, const String & password, const Poco::Net::IPAddress & address, const std::function & on_change, ext::scope_guard * subscription) const; + + std::shared_ptr getAccessRightsContext(const ClientInfo & client_info, const AccessRights & granted_to_user, const Settings & settings, const String & current_database); + std::shared_ptr createQuotaContext(const String & user_name, const Poco::Net::IPAddress & address, const String & custom_quota_key); diff --git a/dbms/src/Access/AccessFlags.h b/dbms/src/Access/AccessFlags.h new file mode 100644 index 00000000000..e547a95bdc6 --- /dev/null +++ b/dbms/src/Access/AccessFlags.h @@ -0,0 +1,498 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + + +namespace DB +{ +/// Represents a combination of access types which can be granted globally, on databases, tables, columns, etc. +/// For example "SELECT, CREATE USER" is an access type. +class AccessFlags +{ +public: + AccessFlags(AccessType type); + + /// The same as AccessFlags(AccessType::NONE). + AccessFlags() = default; + + /// Constructs from a string like "SELECT". + AccessFlags(const std::string_view & keyword); + + /// Constructs from a list of strings like "SELECT, UPDATE, INSERT". + AccessFlags(const std::vector & keywords); + AccessFlags(const Strings & keywords); + + AccessFlags(const AccessFlags & src) = default; + AccessFlags(AccessFlags && src) = default; + AccessFlags & operator =(const AccessFlags & src) = default; + AccessFlags & operator =(AccessFlags && src) = default; + + /// Returns the access type which contains two specified access types. + AccessFlags & operator |=(const AccessFlags & other) { flags |= other.flags; return *this; } + friend AccessFlags operator |(const AccessFlags & left, const AccessFlags & right) { return AccessFlags(left) |= right; } + + /// Returns the access type which contains the common part of two access types. + AccessFlags & operator &=(const AccessFlags & other) { flags &= other.flags; return *this; } + friend AccessFlags operator &(const AccessFlags & left, const AccessFlags & right) { return AccessFlags(left) &= right; } + + /// Returns the access type which contains only the part of the first access type which is not the part of the second access type. + /// (lhs - rhs) is the same as (lhs & ~rhs). + AccessFlags & operator -=(const AccessFlags & other) { flags &= ~other.flags; return *this; } + friend AccessFlags operator -(const AccessFlags & left, const AccessFlags & right) { return AccessFlags(left) -= right; } + + AccessFlags operator ~() const { AccessFlags res; res.flags = ~flags; return res; } + + bool isEmpty() const { return flags.none(); } + explicit operator bool() const { return !isEmpty(); } + bool contains(const AccessFlags & other) const { return (flags & other.flags) == other.flags; } + + friend bool operator ==(const AccessFlags & left, const AccessFlags & right) { return left.flags == right.flags; } + friend bool operator !=(const AccessFlags & left, const AccessFlags & right) { return !(left == right); } + + void clear() { flags.reset(); } + + /// Returns a comma-separated list of keywords, like "SELECT, CREATE USER, UPDATE". + String toString() const; + + /// Returns a list of keywords. + std::vector toKeywords() const; + + /// Returns the access types which could be granted on the database level. + /// For example, SELECT can be granted on the database level, but CREATE_USER cannot. + static AccessFlags databaseLevel(); + + /// Returns the access types which could be granted on the table/dictionary level. + static AccessFlags tableLevel(); + + /// Returns the access types which could be granted on the column/attribute level. + static AccessFlags columnLevel(); + +private: + static constexpr size_t NUM_FLAGS = 128; + using Flags = std::bitset; + Flags flags; + + AccessFlags(const Flags & flags_) : flags(flags_) {} + + template + class Impl; +}; + + +namespace ErrorCodes +{ + extern const int UNKNOWN_ACCESS_TYPE; +} + +template +class AccessFlags::Impl +{ +public: + static const Impl & instance() + { + static const Impl res; + return res; + } + + Flags accessTypeToFlags(AccessType type) const + { + return access_type_to_flags_mapping[static_cast(type)]; + } + + Flags keywordToFlags(const std::string_view & keyword) const + { + auto it = keyword_to_flags_map.find(keyword); + if (it == keyword_to_flags_map.end()) + { + String uppercased_keyword{keyword}; + boost::to_upper(uppercased_keyword); + it = keyword_to_flags_map.find(uppercased_keyword); + if (it == keyword_to_flags_map.end()) + throw Exception("Unknown access type: " + String(keyword), ErrorCodes::UNKNOWN_ACCESS_TYPE); + } + return it->second; + } + + Flags keywordsToFlags(const std::vector & keywords) const + { + Flags res; + for (const auto & keyword : keywords) + res |= keywordToFlags(keyword); + return res; + } + + Flags keywordsToFlags(const Strings & keywords) const + { + Flags res; + for (const auto & keyword : keywords) + res |= keywordToFlags(keyword); + return res; + } + + std::vector flagsToKeywords(const Flags & flags_) const + { + std::vector keywords; + flagsToKeywordsRec(flags_, keywords, *flags_to_keyword_tree); + + if (keywords.empty()) + keywords.push_back("USAGE"); + + return keywords; + } + + String flagsToString(const Flags & flags_) const + { + String str; + for (const auto & keyword : flagsToKeywords(flags_)) + { + if (!str.empty()) + str += ", "; + str += keyword; + } + return str; + } + + const Flags & getDatabaseLevelFlags() const { return all_grantable_on_level[DATABASE_LEVEL]; } + const Flags & getTableLevelFlags() const { return all_grantable_on_level[TABLE_LEVEL]; } + const Flags & getColumnLevelFlags() const { return all_grantable_on_level[COLUMN_LEVEL]; } + +private: + enum Level + { + UNKNOWN_LEVEL = -1, + GLOBAL_LEVEL = 0, + DATABASE_LEVEL = 1, + TABLE_LEVEL = 2, + VIEW_LEVEL = 2, + DICTIONARY_LEVEL = 2, + COLUMN_LEVEL = 3, + }; + + struct Node; + using NodePtr = std::unique_ptr; + using Nodes = std::vector; + + template + static Nodes nodes(Args&& ... args) + { + Nodes res; + ext::push_back(res, std::move(args)...); + return res; + } + + struct Node + { + std::string_view keyword; + std::vector aliases; + Flags flags; + Level level = UNKNOWN_LEVEL; + Nodes children; + + Node(std::string_view keyword_, size_t flag_, Level level_) + : keyword(keyword_), level(level_) + { + flags.set(flag_); + } + + Node(std::string_view keyword_, Nodes children_) + : keyword(keyword_), children(std::move(children_)) + { + for (const auto & child : children) + flags |= child->flags; + } + + template + Node(std::string_view keyword_, NodePtr first_child, Args &&... other_children) + : Node(keyword_, nodes(std::move(first_child), std::move(other_children)...)) {} + }; + + static void flagsToKeywordsRec(const Flags & flags_, std::vector & keywords, const Node & start_node) + { + Flags matching_flags = (flags_ & start_node.flags); + if (matching_flags.any()) + { + if (matching_flags == start_node.flags) + { + keywords.push_back(start_node.keyword); + } + else + { + for (const auto & child : start_node.children) + flagsToKeywordsRec(flags_, keywords, *child); + } + } + } + + static void makeFlagsToKeywordTree(NodePtr & flags_to_keyword_tree_) + { + size_t next_flag = 0; + Nodes all; + + auto show = std::make_unique("SHOW", next_flag++, COLUMN_LEVEL); + auto exists = std::make_unique("EXISTS", next_flag++, COLUMN_LEVEL); + ext::push_back(all, std::move(show), std::move(exists)); + + auto select = std::make_unique("SELECT", next_flag++, COLUMN_LEVEL); + auto insert = std::make_unique("INSERT", next_flag++, COLUMN_LEVEL); + ext::push_back(all, std::move(select), std::move(insert)); + + auto update = std::make_unique("UPDATE", next_flag++, COLUMN_LEVEL); + ext::push_back(update->aliases, "ALTER UPDATE"); + auto delet = std::make_unique("DELETE", next_flag++, TABLE_LEVEL); + ext::push_back(delet->aliases, "ALTER DELETE"); + + auto add_column = std::make_unique("ADD COLUMN", next_flag++, COLUMN_LEVEL); + add_column->aliases.push_back("ALTER ADD COLUMN"); + auto modify_column = std::make_unique("MODIFY COLUMN", next_flag++, COLUMN_LEVEL); + modify_column->aliases.push_back("ALTER MODIFY COLUMN"); + auto drop_column = std::make_unique("DROP COLUMN", next_flag++, COLUMN_LEVEL); + drop_column->aliases.push_back("ALTER DROP COLUMN"); + auto comment_column = std::make_unique("COMMENT COLUMN", next_flag++, COLUMN_LEVEL); + comment_column->aliases.push_back("ALTER COMMENT COLUMN"); + auto clear_column = std::make_unique("CLEAR COLUMN", next_flag++, COLUMN_LEVEL); + clear_column->aliases.push_back("ALTER CLEAR COLUMN"); + auto alter_column = std::make_unique("ALTER COLUMN", std::move(add_column), std::move(modify_column), std::move(drop_column), std::move(comment_column), std::move(clear_column)); + + auto alter_order_by = std::make_unique("ALTER ORDER BY", next_flag++, TABLE_LEVEL); + alter_order_by->aliases.push_back("MODIFY ORDER BY"); + alter_order_by->aliases.push_back("ALTER MODIFY ORDER BY"); + auto add_index = std::make_unique("ADD INDEX", next_flag++, TABLE_LEVEL); + add_index->aliases.push_back("ALTER ADD INDEX"); + auto drop_index = std::make_unique("DROP INDEX", next_flag++, TABLE_LEVEL); + drop_index->aliases.push_back("ALTER DROP INDEX"); + auto materialize_index = std::make_unique("MATERIALIZE INDEX", next_flag++, TABLE_LEVEL); + materialize_index->aliases.push_back("ALTER MATERIALIZE INDEX"); + auto clear_index = std::make_unique("CLEAR INDEX", next_flag++, TABLE_LEVEL); + clear_index->aliases.push_back("ALTER CLEAR INDEX"); + auto index = std::make_unique("INDEX", std::move(alter_order_by), std::move(add_index), std::move(drop_index), std::move(materialize_index), std::move(clear_index)); + index->aliases.push_back("ALTER INDEX"); + + auto add_constraint = std::make_unique("ADD CONSTRAINT", next_flag++, TABLE_LEVEL); + add_constraint->aliases.push_back("ALTER ADD CONSTRAINT"); + auto drop_constraint = std::make_unique("DROP CONSTRAINT", next_flag++, TABLE_LEVEL); + drop_constraint->aliases.push_back("ALTER DROP CONSTRAINT"); + auto alter_constraint = std::make_unique("CONSTRAINT", std::move(add_constraint), std::move(drop_constraint)); + alter_constraint->aliases.push_back("ALTER CONSTRAINT"); + + auto modify_ttl = std::make_unique("MODIFY TTL", next_flag++, TABLE_LEVEL); + modify_ttl->aliases.push_back("ALTER MODIFY TTL"); + + auto modify_setting = std::make_unique("MODIFY SETTING", next_flag++, TABLE_LEVEL); + modify_setting->aliases.push_back("ALTER MODIFY SETTING"); + + auto move_partition = std::make_unique("MOVE PARTITION", next_flag++, TABLE_LEVEL); + ext::push_back(move_partition->aliases, "ALTER MOVE PARTITION", "MOVE PART", "ALTER MOVE PART"); + auto fetch_partition = std::make_unique("FETCH PARTITION", next_flag++, TABLE_LEVEL); + ext::push_back(fetch_partition->aliases, "ALTER FETCH PARTITION"); + auto freeze_partition = std::make_unique("FREEZE PARTITION", next_flag++, TABLE_LEVEL); + ext::push_back(freeze_partition->aliases, "ALTER FREEZE PARTITION"); + + auto alter_table = std::make_unique("ALTER TABLE", std::move(update), std::move(delet), std::move(alter_column), std::move(index), std::move(alter_constraint), std::move(modify_ttl), std::move(modify_setting), std::move(move_partition), std::move(fetch_partition), std::move(freeze_partition)); + + auto refresh_view = std::make_unique("REFRESH VIEW", next_flag++, VIEW_LEVEL); + ext::push_back(refresh_view->aliases, "ALTER LIVE VIEW REFRESH"); + auto modify_view_query = std::make_unique("MODIFY VIEW QUERY", next_flag++, VIEW_LEVEL); + auto alter_view = std::make_unique("ALTER VIEW", std::move(refresh_view), std::move(modify_view_query)); + + auto alter = std::make_unique("ALTER", std::move(alter_table), std::move(alter_view)); + ext::push_back(all, std::move(alter)); + + auto create_database = std::make_unique("CREATE DATABASE", next_flag++, DATABASE_LEVEL); + ext::push_back(create_database->aliases, "ATTACH DATABASE"); + auto create_table = std::make_unique("CREATE TABLE", next_flag++, TABLE_LEVEL); + ext::push_back(create_table->aliases, "ATTACH TABLE"); + auto create_view = std::make_unique("CREATE VIEW", next_flag++, VIEW_LEVEL); + ext::push_back(create_view->aliases, "ATTACH VIEW"); + auto create_dictionary = std::make_unique("CREATE DICTIONARY", next_flag++, DICTIONARY_LEVEL); + ext::push_back(create_dictionary->aliases, "ATTACH DICTIONARY"); + auto create = std::make_unique("CREATE", std::move(create_database), std::move(create_table), std::move(create_view), std::move(create_dictionary)); + ext::push_back(create->aliases, "ATTACH"); + ext::push_back(all, std::move(create)); + + auto create_temporary_table = std::make_unique("CREATE TEMPORARY TABLE", next_flag++, GLOBAL_LEVEL); + ext::push_back(all, std::move(create_temporary_table)); + + auto drop_database = std::make_unique("DROP DATABASE", next_flag++, DATABASE_LEVEL); + auto drop_table = std::make_unique("DROP TABLE", next_flag++, TABLE_LEVEL); + auto drop_view = std::make_unique("DROP VIEW", next_flag++, VIEW_LEVEL); + auto drop_dictionary = std::make_unique("DROP DICTIONARY", next_flag++, DICTIONARY_LEVEL); + auto drop = std::make_unique("DROP", std::move(drop_database), std::move(drop_table), std::move(drop_view), std::move(drop_dictionary)); + ext::push_back(all, std::move(drop)); + + auto detach_database = std::make_unique("DETACH DATABASE", next_flag++, DATABASE_LEVEL); + auto detach_table = std::make_unique("DETACH TABLE", next_flag++, TABLE_LEVEL); + auto detach_view = std::make_unique("DETACH VIEW", next_flag++, VIEW_LEVEL); + auto detach_dictionary = std::make_unique("DETACH DICTIONARY", next_flag++, DICTIONARY_LEVEL); + auto detach = std::make_unique("DETACH", std::move(detach_database), std::move(detach_table), std::move(detach_view), std::move(detach_dictionary)); + ext::push_back(all, std::move(detach)); + + auto truncate_table = std::make_unique("TRUNCATE TABLE", next_flag++, TABLE_LEVEL); + auto truncate_view = std::make_unique("TRUNCATE VIEW", next_flag++, VIEW_LEVEL); + auto truncate = std::make_unique("TRUNCATE", std::move(truncate_table), std::move(truncate_view)); + ext::push_back(all, std::move(truncate)); + + auto optimize = std::make_unique("OPTIMIZE", next_flag++, TABLE_LEVEL); + optimize->aliases.push_back("OPTIMIZE TABLE"); + ext::push_back(all, std::move(optimize)); + + auto kill_query = std::make_unique("KILL QUERY", next_flag++, GLOBAL_LEVEL); + auto kill_mutation = std::make_unique("KILL MUTATION", next_flag++, TABLE_LEVEL); + auto kill = std::make_unique("KILL", std::move(kill_query), std::move(kill_mutation)); + ext::push_back(all, std::move(kill)); + + auto create_user = std::make_unique("CREATE USER", next_flag++, GLOBAL_LEVEL); + ext::push_back(create_user->aliases, "ALTER USER", "DROP USER", "CREATE ROLE", "DROP ROLE", "CREATE POLICY", "ALTER POLICY", "DROP POLICY", "CREATE QUOTA", "ALTER QUOTA", "DROP QUOTA"); + ext::push_back(all, std::move(create_user)); + + auto shutdown = std::make_unique("SHUTDOWN", next_flag++, GLOBAL_LEVEL); + ext::push_back(shutdown->aliases, "SYSTEM SHUTDOWN", "SYSTEM KILL"); + auto drop_cache = std::make_unique("DROP CACHE", next_flag++, GLOBAL_LEVEL); + ext::push_back(drop_cache->aliases, "SYSTEM DROP CACHE", "DROP DNS CACHE", "SYSTEM DROP DNS CACHE", "DROP MARK CACHE", "SYSTEM DROP MARK CACHE", "DROP UNCOMPRESSED CACHE", "SYSTEM DROP UNCOMPRESSED CACHE", "DROP COMPILED EXPRESSION CACHE", "SYSTEM DROP COMPILED EXPRESSION CACHE"); + auto reload_config = std::make_unique("RELOAD CONFIG", next_flag++, GLOBAL_LEVEL); + ext::push_back(reload_config->aliases, "SYSTEM RELOAD CONFIG"); + auto reload_dictionary = std::make_unique("RELOAD DICTIONARY", next_flag++, GLOBAL_LEVEL); + ext::push_back(reload_dictionary->aliases, "SYSTEM RELOAD DICTIONARY", "RELOAD DICTIONARIES", "SYSTEM RELOAD DICTIONARIES", "RELOAD EMBEDDED DICTIONARIES", "SYSTEM RELOAD EMBEDDED DICTIONARIES"); + auto stop_merges = std::make_unique("STOP MERGES", next_flag++, TABLE_LEVEL); + ext::push_back(stop_merges->aliases, "SYSTEM STOP MERGES", "START MERGES", "SYSTEM START MERGES"); + auto stop_ttl_merges = std::make_unique("STOP TTL MERGES", next_flag++, TABLE_LEVEL); + ext::push_back(stop_ttl_merges->aliases, "SYSTEM STOP TTL MERGES", "START TTL MERGES", "SYSTEM START TTL MERGES"); + auto stop_fetches = std::make_unique("STOP FETCHES", next_flag++, TABLE_LEVEL); + ext::push_back(stop_fetches->aliases, "SYSTEM STOP FETCHES", "START FETCHES", "SYSTEM START FETCHES"); + auto stop_moves = std::make_unique("STOP MOVES", next_flag++, TABLE_LEVEL); + ext::push_back(stop_moves->aliases, "SYSTEM STOP MOVES", "START MOVES", "SYSTEM START MOVES"); + auto stop_distributed_sends = std::make_unique("STOP DISTRIBUTED SENDS", next_flag++, TABLE_LEVEL); + ext::push_back(stop_distributed_sends->aliases, "SYSTEM STOP DISTRIBUTED SENDS", "START DISTRIBUTED SENDS", "SYSTEM START DISTRIBUTED SENDS"); + auto stop_replicated_sends = std::make_unique("STOP REPLICATED SENDS", next_flag++, TABLE_LEVEL); + ext::push_back(stop_replicated_sends->aliases, "SYSTEM STOP REPLICATED SENDS", "START REPLICATED SENDS", "SYSTEM START REPLICATED SENDS"); + auto stop_replication_queues = std::make_unique("STOP REPLICATION QUEUES", next_flag++, TABLE_LEVEL); + ext::push_back(stop_replication_queues->aliases, "SYSTEM STOP REPLICATION QUEUES", "START REPLICATION QUEUES", "SYSTEM START REPLICATION QUEUES"); + auto sync_replica = std::make_unique("SYNC REPLICA", next_flag++, TABLE_LEVEL); + ext::push_back(sync_replica->aliases, "SYSTEM SYNC REPLICA"); + auto restart_replica = std::make_unique("RESTART REPLICA", next_flag++, TABLE_LEVEL); + ext::push_back(restart_replica->aliases, "SYSTEM RESTART REPLICA"); + auto flush_distributed = std::make_unique("FLUSH DISTRIBUTED", next_flag++, TABLE_LEVEL); + ext::push_back(flush_distributed->aliases, "SYSTEM FLUSH DISTRIBUTED"); + auto flush_logs = std::make_unique("FLUSH LOGS", next_flag++, GLOBAL_LEVEL); + ext::push_back(flush_logs->aliases, "SYSTEM FLUSH LOGS"); + auto system = std::make_unique("SYSTEM", std::move(shutdown), std::move(drop_cache), std::move(reload_config), std::move(reload_dictionary), std::move(stop_merges), std::move(stop_ttl_merges), std::move(stop_fetches), std::move(stop_moves), std::move(stop_distributed_sends), std::move(stop_replicated_sends), std::move(stop_replication_queues), std::move(sync_replica), std::move(restart_replica), std::move(flush_distributed), std::move(flush_logs)); + ext::push_back(all, std::move(system)); + + auto dict_get = std::make_unique("dictGet()", next_flag++, DICTIONARY_LEVEL); + dict_get->aliases.push_back("dictHas()"); + dict_get->aliases.push_back("dictGetHierarchy()"); + dict_get->aliases.push_back("dictIsIn()"); + ext::push_back(all, std::move(dict_get)); + + auto address_to_line = std::make_unique("addressToLine()", next_flag++, GLOBAL_LEVEL); + auto address_to_symbol = std::make_unique("addressToSymbol()", next_flag++, GLOBAL_LEVEL); + auto demangle = std::make_unique("demangle()", next_flag++, GLOBAL_LEVEL); + auto introspection = std::make_unique("INTROSPECTION", std::move(address_to_line), std::move(address_to_symbol), std::move(demangle)); + ext::push_back(introspection->aliases, "INTROSPECTION FUNCTIONS"); + ext::push_back(all, std::move(introspection)); + + auto file = std::make_unique("file()", next_flag++, GLOBAL_LEVEL); + auto url = std::make_unique("url()", next_flag++, GLOBAL_LEVEL); + auto input = std::make_unique("input()", next_flag++, GLOBAL_LEVEL); + auto values = std::make_unique("values()", next_flag++, GLOBAL_LEVEL); + auto numbers = std::make_unique("numbers()", next_flag++, GLOBAL_LEVEL); + auto merge = std::make_unique("merge()", next_flag++, DATABASE_LEVEL); + auto remote = std::make_unique("remote()", next_flag++, GLOBAL_LEVEL); + ext::push_back(remote->aliases, "remoteSecure()", "cluster()"); + auto mysql = std::make_unique("mysql()", next_flag++, GLOBAL_LEVEL); + auto odbc = std::make_unique("odbc()", next_flag++, GLOBAL_LEVEL); + auto jdbc = std::make_unique("jdbc()", next_flag++, GLOBAL_LEVEL); + auto hdfs = std::make_unique("hdfs()", next_flag++, GLOBAL_LEVEL); + auto s3 = std::make_unique("s3()", next_flag++, GLOBAL_LEVEL); + auto table_functions = std::make_unique("TABLE FUNCTIONS", std::move(file), std::move(url), std::move(input), std::move(values), std::move(numbers), std::move(merge), std::move(remote), std::move(mysql), std::move(odbc), std::move(jdbc), std::move(hdfs), std::move(s3)); + ext::push_back(all, std::move(table_functions)); + + flags_to_keyword_tree_ = std::make_unique("ALL", std::move(all)); + flags_to_keyword_tree_->aliases.push_back("ALL PRIVILEGES"); + } + + void makeKeywordToFlagsMap(std::unordered_map & keyword_to_flags_map_, Node * start_node = nullptr) + { + if (!start_node) + { + start_node = flags_to_keyword_tree.get(); + keyword_to_flags_map_["USAGE"] = {}; + keyword_to_flags_map_["NONE"] = {}; + keyword_to_flags_map_["NO PRIVILEGES"] = {}; + } + start_node->aliases.emplace_back(start_node->keyword); + for (auto & alias : start_node->aliases) + { + boost::to_upper(alias); + keyword_to_flags_map_[alias] = start_node->flags; + } + for (auto & child : start_node->children) + makeKeywordToFlagsMap(keyword_to_flags_map_, child.get()); + } + + void makeAccessTypeToFlagsMapping(std::vector & access_type_to_flags_mapping_) + { + access_type_to_flags_mapping_.resize(MAX_ACCESS_TYPE); + for (auto access_type : ext::range_with_static_cast(0, MAX_ACCESS_TYPE)) + { + auto str = toKeyword(access_type); + auto it = keyword_to_flags_map.find(str); + if (it == keyword_to_flags_map.end()) + { + String uppercased{str}; + boost::to_upper(uppercased); + it = keyword_to_flags_map.find(uppercased); + } + access_type_to_flags_mapping_[static_cast(access_type)] = it->second; + } + } + + void collectAllGrantableOnLevel(std::vector & all_grantable_on_level_, const Node * start_node = nullptr) + { + if (!start_node) + { + start_node = flags_to_keyword_tree.get(); + all_grantable_on_level.resize(COLUMN_LEVEL + 1); + } + for (int i = 0; i <= start_node->level; ++i) + all_grantable_on_level_[i] |= start_node->flags; + for (const auto & child : start_node->children) + collectAllGrantableOnLevel(all_grantable_on_level_, child.get()); + } + + Impl() + { + makeFlagsToKeywordTree(flags_to_keyword_tree); + makeKeywordToFlagsMap(keyword_to_flags_map); + makeAccessTypeToFlagsMapping(access_type_to_flags_mapping); + collectAllGrantableOnLevel(all_grantable_on_level); + } + + std::unique_ptr flags_to_keyword_tree; + std::unordered_map keyword_to_flags_map; + std::vector access_type_to_flags_mapping; + std::vector all_grantable_on_level; +}; + + +inline AccessFlags::AccessFlags(AccessType type) : flags(Impl<>::instance().accessTypeToFlags(type)) {} +inline AccessFlags::AccessFlags(const std::string_view & keyword) : flags(Impl<>::instance().keywordToFlags(keyword)) {} +inline AccessFlags::AccessFlags(const std::vector & keywords) : flags(Impl<>::instance().keywordsToFlags(keywords)) {} +inline AccessFlags::AccessFlags(const Strings & keywords) : flags(Impl<>::instance().keywordsToFlags(keywords)) {} +inline String AccessFlags::toString() const { return Impl<>::instance().flagsToString(flags); } +inline std::vector AccessFlags::toKeywords() const { return Impl<>::instance().flagsToKeywords(flags); } +inline AccessFlags AccessFlags::databaseLevel() { return Impl<>::instance().getDatabaseLevelFlags(); } +inline AccessFlags AccessFlags::tableLevel() { return Impl<>::instance().getTableLevelFlags(); } +inline AccessFlags AccessFlags::columnLevel() { return Impl<>::instance().getColumnLevelFlags(); } + +inline AccessFlags operator |(AccessType left, AccessType right) { return AccessFlags(left) | right; } +inline AccessFlags operator &(AccessType left, AccessType right) { return AccessFlags(left) & right; } +inline AccessFlags operator -(AccessType left, AccessType right) { return AccessFlags(left) - right; } +inline AccessFlags operator ~(AccessType x) { return ~AccessFlags(x); } + +} diff --git a/dbms/src/Access/AccessRights.cpp b/dbms/src/Access/AccessRights.cpp new file mode 100644 index 00000000000..7d4964eb43c --- /dev/null +++ b/dbms/src/Access/AccessRights.cpp @@ -0,0 +1,729 @@ +#include +#include +#include +#include + + +namespace DB +{ +namespace ErrorCodes +{ + extern const int INVALID_GRANT; + extern const int LOGICAL_ERROR; +} + + +namespace +{ + enum Level + { + GLOBAL_LEVEL, + DATABASE_LEVEL, + TABLE_LEVEL, + COLUMN_LEVEL, + }; + + enum RevokeMode + { + NORMAL_REVOKE_MODE, /// for AccessRights::revoke() + PARTIAL_REVOKE_MODE, /// for AccessRights::partialRevoke() + FULL_REVOKE_MODE, /// for AccessRights::fullRevoke() + }; + + struct Helper + { + static const Helper & instance() + { + static const Helper res; + return res; + } + + const AccessFlags database_level_flags = AccessFlags::databaseLevel(); + const AccessFlags table_level_flags = AccessFlags::tableLevel(); + const AccessFlags column_level_flags = AccessFlags::columnLevel(); + const AccessFlags show_flag = AccessType::SHOW; + const AccessFlags exists_flag = AccessType::EXISTS; + const AccessFlags create_table_flag = AccessType::CREATE_TABLE; + const AccessFlags create_temporary_table_flag = AccessType::CREATE_TEMPORARY_TABLE; + }; +} + + +struct AccessRights::Node +{ +public: + std::shared_ptr node_name; + Level level = GLOBAL_LEVEL; + AccessFlags explicit_grants; + AccessFlags partial_revokes; + AccessFlags inherited_access; /// the access inherited from the parent node + AccessFlags raw_access; /// raw_access = (inherited_access - partial_revokes) | explicit_grants + AccessFlags access; /// access = raw_access | implicit_access + AccessFlags min_access; /// min_access = access & child[0].access & ... | child[N-1].access + AccessFlags max_access; /// max_access = access | child[0].access | ... | child[N-1].access + std::unique_ptr> children; + + Node() = default; + Node(const Node & src) { *this = src; } + + Node & operator =(const Node & src) + { + node_name = src.node_name; + level = src.level; + inherited_access = src.inherited_access; + explicit_grants = src.explicit_grants; + partial_revokes = src.partial_revokes; + access = src.access; + min_access = src.min_access; + max_access = src.max_access; + if (src.children) + children = std::make_unique>(*src.children); + else + children = nullptr; + return *this; + } + + void grant(AccessFlags access_to_grant, const Helper & helper) + { + if (!access_to_grant) + return; + + if (level == GLOBAL_LEVEL) + { + /// Everything can be granted on the global level. + } + else if (level == DATABASE_LEVEL) + { + AccessFlags grantable = access_to_grant & helper.database_level_flags; + if (!grantable) + throw Exception(access_to_grant.toString() + " cannot be granted on the database level", ErrorCodes::INVALID_GRANT); + access_to_grant = grantable; + } + else if (level == TABLE_LEVEL) + { + AccessFlags grantable = access_to_grant & helper.table_level_flags; + if (!grantable) + throw Exception(access_to_grant.toString() + " cannot be granted on the table level", ErrorCodes::INVALID_GRANT); + access_to_grant = grantable; + } + else if (level == COLUMN_LEVEL) + { + AccessFlags grantable = access_to_grant & helper.column_level_flags; + if (!grantable) + throw Exception(access_to_grant.toString() + " cannot be granted on the column level", ErrorCodes::INVALID_GRANT); + access_to_grant = grantable; + } + + explicit_grants |= access_to_grant - partial_revokes; + partial_revokes -= access_to_grant; + calculateAllAccessRec(helper); + } + + template + void grant(const AccessFlags & access_to_grant, const Helper & helper, const std::string_view & name, const Args &... subnames) + { + auto & child = getChild(name); + child.grant(access_to_grant, helper, subnames...); + eraseChildIfEmpty(child); + calculateImplicitAccess(helper); + calculateMinAndMaxAccess(); + } + + template + void grant(const AccessFlags & access_to_grant, const Helper & helper, const std::vector & names) + { + for (const auto & name : names) + { + auto & child = getChild(name); + child.grant(access_to_grant, helper); + eraseChildIfEmpty(child); + } + calculateImplicitAccess(helper); + calculateMinAndMaxAccess(); + } + + template + void revoke(const AccessFlags & access_to_revoke, const Helper & helper) + { + if constexpr (mode == NORMAL_REVOKE_MODE) + { + explicit_grants -= access_to_revoke; + } + else if constexpr (mode == PARTIAL_REVOKE_MODE) + { + partial_revokes |= access_to_revoke - explicit_grants; + explicit_grants -= access_to_revoke; + } + else /// mode == FULL_REVOKE_MODE + { + fullRevokeRec(access_to_revoke); + } + calculateAllAccessRec(helper); + } + + template + void revoke(const AccessFlags & access_to_revoke, const Helper & helper, const std::string_view & name, const Args &... subnames) + { + Node * child; + if (mode == NORMAL_REVOKE_MODE) + { + if (!(child = tryGetChild(name))) + return; + } + else + child = &getChild(name); + + child->revoke(access_to_revoke, helper, subnames...); + eraseChildIfEmpty(*child); + calculateImplicitAccess(helper); + calculateMinAndMaxAccess(); + } + + template + void revoke(const AccessFlags & access_to_revoke, const Helper & helper, const std::vector & names) + { + Node * child; + for (const auto & name : names) + { + if (mode == NORMAL_REVOKE_MODE) + { + if (!(child = tryGetChild(name))) + continue; + } + else + child = &getChild(name); + + child->revoke(access_to_revoke, helper); + eraseChildIfEmpty(*child); + } + calculateImplicitAccess(helper); + calculateMinAndMaxAccess(); + } + + bool isGranted(const AccessFlags & flags) const + { + return min_access.contains(flags); + } + + template + bool isGranted(AccessFlags flags, const std::string_view & name, const Args &... subnames) const + { + if (min_access.contains(flags)) + return true; + if (!max_access.contains(flags)) + return false; + + const Node * child = tryGetChild(name); + if (child) + return child->isGranted(flags, subnames...); + else + return access.contains(flags); + } + + template + bool isGranted(AccessFlags flags, const std::vector & names) const + { + if (min_access.contains(flags)) + return true; + if (!max_access.contains(flags)) + return false; + + for (const auto & name : names) + { + const Node * child = tryGetChild(name); + if (child) + { + if (!child->isGranted(flags, name)) + return false; + } + else + { + if (!access.contains(flags)) + return false; + } + } + return true; + } + + friend bool operator ==(const Node & left, const Node & right) + { + if ((left.explicit_grants != right.explicit_grants) || (left.partial_revokes != right.partial_revokes)) + return false; + + if (!left.children) + return !right.children; + + if (!right.children) + return false; + return *left.children == *right.children; + } + + friend bool operator!=(const Node & left, const Node & right) { return !(left == right); } + + bool isEmpty() const + { + return !explicit_grants && !partial_revokes && !children; + } + + void merge(const Node & other, const Helper & helper) + { + mergeRawAccessRec(other); + calculateGrantsAndPartialRevokesRec(); + calculateAllAccessRec(helper); + } + +private: + Node * tryGetChild(const std::string_view & name) + { + if (!children) + return nullptr; + auto it = children->find(name); + if (it == children->end()) + return nullptr; + return &it->second; + } + + const Node * tryGetChild(const std::string_view & name) const + { + if (!children) + return nullptr; + auto it = children->find(name); + if (it == children->end()) + return nullptr; + return &it->second; + } + + Node & getChild(const std::string_view & name) + { + auto * child = tryGetChild(name); + if (child) + return *child; + if (!children) + children = std::make_unique>(); + auto new_child_name = std::make_shared(name); + Node & new_child = (*children)[*new_child_name]; + new_child.node_name = std::move(new_child_name); + new_child.level = static_cast(level + 1); + new_child.inherited_access = raw_access; + new_child.raw_access = raw_access; + return new_child; + } + + void eraseChildIfEmpty(Node & child) + { + if (!child.isEmpty()) + return; + auto it = children->find(*child.node_name); + children->erase(it); + if (children->empty()) + children = nullptr; + } + + void calculateImplicitAccess(const Helper & helper) + { + access = raw_access; + if (access & helper.database_level_flags) + access |= helper.show_flag | helper.exists_flag; + else if ((level >= DATABASE_LEVEL) && children) + access |= helper.exists_flag; + + if ((level == GLOBAL_LEVEL) && (access & helper.create_table_flag)) + access |= helper.create_temporary_table_flag; + } + + void calculateMinAndMaxAccess() + { + min_access = access; + max_access = access; + if (children) + { + for (const auto & child : *children | boost::adaptors::map_values) + { + min_access &= child.min_access; + max_access |= child.max_access; + } + } + } + + void calculateAllAccessRec(const Helper & helper) + { + partial_revokes &= inherited_access; + raw_access = (inherited_access - partial_revokes) | explicit_grants; + + /// Traverse tree. + if (children) + { + for (auto it = children->begin(); it != children->end();) + { + auto & child = it->second; + child.inherited_access = raw_access; + child.calculateAllAccessRec(helper); + if (child.isEmpty()) + it = children->erase(it); + else + ++it; + } + if (children->empty()) + children = nullptr; + } + + calculateImplicitAccess(helper); + calculateMinAndMaxAccess(); + } + + void fullRevokeRec(const AccessFlags & access_to_revoke) + { + explicit_grants -= access_to_revoke; + partial_revokes |= access_to_revoke; + if (children) + { + for (auto & child : *children | boost::adaptors::map_values) + child.fullRevokeRec(access_to_revoke); + } + } + + void mergeRawAccessRec(const Node & rhs) + { + if (rhs.children) + { + for (const auto & [rhs_childname, rhs_child] : *rhs.children) + getChild(rhs_childname).mergeRawAccessRec(rhs_child); + } + raw_access |= rhs.raw_access; + if (children) + { + for (auto & [lhs_childname, lhs_child] : *children) + { + lhs_child.inherited_access = raw_access; + if (!rhs.tryGetChild(lhs_childname)) + lhs_child.raw_access |= rhs.raw_access; + } + } + } + + void calculateGrantsAndPartialRevokesRec() + { + explicit_grants = raw_access - inherited_access; + partial_revokes = inherited_access - raw_access; + if (children) + { + for (auto & child : *children | boost::adaptors::map_values) + child.calculateGrantsAndPartialRevokesRec(); + } + } +}; + + +AccessRights::AccessRights() = default; +AccessRights::~AccessRights() = default; +AccessRights::AccessRights(AccessRights && src) = default; +AccessRights & AccessRights::operator =(AccessRights && src) = default; + + +AccessRights::AccessRights(const AccessRights & src) +{ + *this = src; +} + + +AccessRights & AccessRights::operator =(const AccessRights & src) +{ + if (src.root) + root = std::make_unique(*src.root); + else + root = nullptr; + return *this; +} + + +AccessRights::AccessRights(const AccessFlags & access) +{ + grant(access); +} + + +bool AccessRights::isEmpty() const +{ + return !root; +} + + +void AccessRights::clear() +{ + root = nullptr; +} + + +template +void AccessRights::grantImpl(const AccessFlags & access, const Args &... args) +{ + if (!root) + root = std::make_unique(); + root->grant(access, Helper::instance(), args...); + if (root->isEmpty()) + root = nullptr; +} + +void AccessRights::grantImpl(const AccessRightsElement & element, std::string_view current_database) +{ + if (element.any_database) + { + grantImpl(element.access_flags); + } + else if (element.any_table) + { + if (element.database.empty()) + grantImpl(element.access_flags, current_database); + else + grantImpl(element.access_flags, element.database); + } + else if (element.any_column) + { + if (element.database.empty()) + grantImpl(element.access_flags, current_database, element.table); + else + grantImpl(element.access_flags, element.database, element.table); + } + else + { + if (element.database.empty()) + grantImpl(element.access_flags, current_database, element.table, element.columns); + else + grantImpl(element.access_flags, element.database, element.table, element.columns); + } +} + +void AccessRights::grantImpl(const AccessRightsElements & elements, std::string_view current_database) +{ + for (const auto & element : elements) + grantImpl(element, current_database); +} + +void AccessRights::grant(const AccessFlags & access) { grantImpl(access); } +void AccessRights::grant(const AccessFlags & access, const std::string_view & database) { grantImpl(access, database); } +void AccessRights::grant(const AccessFlags & access, const std::string_view & database, const std::string_view & table) { grantImpl(access, database, table); } +void AccessRights::grant(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column) { grantImpl(access, database, table, column); } +void AccessRights::grant(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns) { grantImpl(access, database, table, columns); } +void AccessRights::grant(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns) { grantImpl(access, database, table, columns); } +void AccessRights::grant(const AccessRightsElement & element, std::string_view current_database) { grantImpl(element, current_database); } +void AccessRights::grant(const AccessRightsElements & elements, std::string_view current_database) { grantImpl(elements, current_database); } + +template +void AccessRights::revokeImpl(const AccessFlags & access, const Args &... args) +{ + if (!root) + return; + root->revoke(access, Helper::instance(), args...); + if (root->isEmpty()) + root = nullptr; +} + +template +void AccessRights::revokeImpl(const AccessRightsElement & element, std::string_view current_database) +{ + if (element.any_database) + { + revokeImpl(element.access_flags); + } + else if (element.any_table) + { + if (element.database.empty()) + revokeImpl(element.access_flags, current_database); + else + revokeImpl(element.access_flags, element.database); + } + else if (element.any_column) + { + if (element.database.empty()) + revokeImpl(element.access_flags, current_database, element.table); + else + revokeImpl(element.access_flags, element.database, element.table); + } + else + { + if (element.database.empty()) + revokeImpl(element.access_flags, current_database, element.table, element.columns); + else + revokeImpl(element.access_flags, element.database, element.table, element.columns); + } +} + +template +void AccessRights::revokeImpl(const AccessRightsElements & elements, std::string_view current_database) +{ + for (const auto & element : elements) + revokeImpl(element, current_database); +} + +void AccessRights::revoke(const AccessFlags & access) { revokeImpl(access); } +void AccessRights::revoke(const AccessFlags & access, const std::string_view & database) { revokeImpl(access, database); } +void AccessRights::revoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table) { revokeImpl(access, database, table); } +void AccessRights::revoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column) { revokeImpl(access, database, table, column); } +void AccessRights::revoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns) { revokeImpl(access, database, table, columns); } +void AccessRights::revoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns) { revokeImpl(access, database, table, columns); } +void AccessRights::revoke(const AccessRightsElement & element, std::string_view current_database) { revokeImpl(element, current_database); } +void AccessRights::revoke(const AccessRightsElements & elements, std::string_view current_database) { revokeImpl(elements, current_database); } + +void AccessRights::partialRevoke(const AccessFlags & access) { revokeImpl(access); } +void AccessRights::partialRevoke(const AccessFlags & access, const std::string_view & database) { revokeImpl(access, database); } +void AccessRights::partialRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table) { revokeImpl(access, database, table); } +void AccessRights::partialRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column) { revokeImpl(access, database, table, column); } +void AccessRights::partialRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns) { revokeImpl(access, database, table, columns); } +void AccessRights::partialRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns) { revokeImpl(access, database, table, columns); } +void AccessRights::partialRevoke(const AccessRightsElement & element, std::string_view current_database) { revokeImpl(element, current_database); } +void AccessRights::partialRevoke(const AccessRightsElements & elements, std::string_view current_database) { revokeImpl(elements, current_database); } + +void AccessRights::fullRevoke(const AccessFlags & access) { revokeImpl(access); } +void AccessRights::fullRevoke(const AccessFlags & access, const std::string_view & database) { revokeImpl(access, database); } +void AccessRights::fullRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table) { revokeImpl(access, database, table); } +void AccessRights::fullRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column) { revokeImpl(access, database, table, column); } +void AccessRights::fullRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns) { revokeImpl(access, database, table, columns); } +void AccessRights::fullRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns) { revokeImpl(access, database, table, columns); } +void AccessRights::fullRevoke(const AccessRightsElement & element, std::string_view current_database) { revokeImpl(element, current_database); } +void AccessRights::fullRevoke(const AccessRightsElements & elements, std::string_view current_database) { revokeImpl(elements, current_database); } + + +AccessRights::Elements AccessRights::getElements() const +{ + if (!root) + return {}; + Elements res; + if (root->explicit_grants) + res.grants.push_back({root->explicit_grants}); + if (root->children) + { + for (const auto & [db_name, db_node] : *root->children) + { + if (db_node.partial_revokes) + res.partial_revokes.push_back({db_node.partial_revokes, db_name}); + if (db_node.explicit_grants) + res.grants.push_back({db_node.explicit_grants, db_name}); + if (db_node.children) + { + for (const auto & [table_name, table_node] : *db_node.children) + { + if (table_node.partial_revokes) + res.partial_revokes.push_back({table_node.partial_revokes, db_name, table_name}); + if (table_node.explicit_grants) + res.grants.push_back({table_node.explicit_grants, db_name, table_name}); + if (table_node.children) + { + for (const auto & [column_name, column_node] : *table_node.children) + { + if (column_node.partial_revokes) + res.partial_revokes.push_back({column_node.partial_revokes, db_name, table_name, column_name}); + if (column_node.explicit_grants) + res.grants.push_back({column_node.explicit_grants, db_name, table_name, column_name}); + } + } + } + } + } + } + return res; +} + + +String AccessRights::toString() const +{ + auto elements = getElements(); + String res; + if (!elements.grants.empty()) + { + res += "GRANT "; + res += elements.grants.toString(); + } + if (!elements.partial_revokes.empty()) + { + if (!res.empty()) + res += ", "; + res += "REVOKE "; + res += elements.partial_revokes.toString(); + } + if (res.empty()) + res = "GRANT USAGE ON *.*"; + return res; +} + + +template +bool AccessRights::isGrantedImpl(const AccessFlags & access, const Args &... args) const +{ + if (!root) + return access.isEmpty(); + return root->isGranted(access, args...); +} + +bool AccessRights::isGrantedImpl(const AccessRightsElement & element, std::string_view current_database) const +{ + if (element.any_database) + { + return isGrantedImpl(element.access_flags); + } + else if (element.any_table) + { + if (element.database.empty()) + return isGrantedImpl(element.access_flags, current_database); + else + return isGrantedImpl(element.access_flags, element.database); + } + else if (element.any_column) + { + if (element.database.empty()) + return isGrantedImpl(element.access_flags, current_database, element.table); + else + return isGrantedImpl(element.access_flags, element.database, element.table); + } + else + { + if (element.database.empty()) + return isGrantedImpl(element.access_flags, current_database, element.table, element.columns); + else + return isGrantedImpl(element.access_flags, element.database, element.table, element.columns); + } +} + +bool AccessRights::isGrantedImpl(const AccessRightsElements & elements, std::string_view current_database) const +{ + for (const auto & element : elements) + if (!isGrantedImpl(element, current_database)) + return false; + return true; +} + +bool AccessRights::isGranted(const AccessFlags & access) const { return isGrantedImpl(access); } +bool AccessRights::isGranted(const AccessFlags & access, const std::string_view & database) const { return isGrantedImpl(access, database); } +bool AccessRights::isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table) const { return isGrantedImpl(access, database, table); } +bool AccessRights::isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column) const { return isGrantedImpl(access, database, table, column); } +bool AccessRights::isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns) const { return isGrantedImpl(access, database, table, columns); } +bool AccessRights::isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns) const { return isGrantedImpl(access, database, table, columns); } +bool AccessRights::isGranted(const AccessRightsElement & element, std::string_view current_database) const { return isGrantedImpl(element, current_database); } +bool AccessRights::isGranted(const AccessRightsElements & elements, std::string_view current_database) const { return isGrantedImpl(elements, current_database); } + + +bool operator ==(const AccessRights & left, const AccessRights & right) +{ + if (!left.root) + return !right.root; + if (!right.root) + return false; + return *left.root == *right.root; +} + + +void AccessRights::merge(const AccessRights & other) +{ + if (!root) + { + *this = other; + return; + } + if (other.root) + { + root->merge(*other.root, Helper::instance()); + if (root->isEmpty()) + root = nullptr; + } +} + +} diff --git a/dbms/src/Access/AccessRights.h b/dbms/src/Access/AccessRights.h new file mode 100644 index 00000000000..4eefcb0d6d3 --- /dev/null +++ b/dbms/src/Access/AccessRights.h @@ -0,0 +1,137 @@ +#pragma once + +#include +#include +#include +#include + + +namespace DB +{ +/// Represents a set of access types granted on databases, tables, columns, etc. +/// For example, "GRANT SELECT, UPDATE ON db.*, GRANT INSERT ON db2.mytbl2" are access rights. +class AccessRights +{ +public: + AccessRights(); + AccessRights(const AccessFlags & access); + ~AccessRights(); + AccessRights(const AccessRights & src); + AccessRights & operator =(const AccessRights & src); + AccessRights(AccessRights && src); + AccessRights & operator =(AccessRights && src); + + bool isEmpty() const; + + /// Revokes everything. It's the same as fullRevoke(AccessType::ALL). + void clear(); + + /// Grants access on a specified database/table/column. + /// Does nothing if the specified access has been already granted. + void grant(const AccessFlags & access); + void grant(const AccessFlags & access, const std::string_view & database); + void grant(const AccessFlags & access, const std::string_view & database, const std::string_view & table); + void grant(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column); + void grant(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns); + void grant(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns); + void grant(const AccessRightsElement & access, std::string_view current_database = {}); + void grant(const AccessRightsElements & access, std::string_view current_database = {}); + + /// Revokes a specified access granted earlier on a specified database/table/column. + /// Does nothing if the specified access is not granted. + /// If the specified access is granted but on upper level (e.g. database for table, table for columns) + /// or lower level, the function also does nothing. + /// This function implements the standard SQL REVOKE behaviour. + void revoke(const AccessFlags & access); + void revoke(const AccessFlags & access, const std::string_view & database); + void revoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table); + void revoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column); + void revoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns); + void revoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns); + void revoke(const AccessRightsElement & access, std::string_view current_database = {}); + void revoke(const AccessRightsElements & access, std::string_view current_database = {}); + + /// Revokes a specified access granted earlier on a specified database/table/column or on lower levels. + /// The function also restricts access if it's granted on upper level. + /// For example, an access could be granted on a database and then revoked on a table in this database. + /// This function implements the MySQL REVOKE behaviour with partial_revokes is ON. + void partialRevoke(const AccessFlags & access); + void partialRevoke(const AccessFlags & access, const std::string_view & database); + void partialRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table); + void partialRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column); + void partialRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns); + void partialRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns); + void partialRevoke(const AccessRightsElement & access, std::string_view current_database = {}); + void partialRevoke(const AccessRightsElements & access, std::string_view current_database = {}); + + /// Revokes a specified access granted earlier on a specified database/table/column or on lower levels. + /// The function also restricts access if it's granted on upper level. + /// For example, fullRevoke(AccessType::ALL) revokes all grants at all, just like clear(); + /// fullRevoke(AccessType::SELECT, db) means it's not allowed to execute SELECT in that database anymore (from any table). + void fullRevoke(const AccessFlags & access); + void fullRevoke(const AccessFlags & access, const std::string_view & database); + void fullRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table); + void fullRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column); + void fullRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns); + void fullRevoke(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns); + void fullRevoke(const AccessRightsElement & access, std::string_view current_database = {}); + void fullRevoke(const AccessRightsElements & access, std::string_view current_database = {}); + + /// Returns the information about all the access granted. + struct Elements + { + AccessRightsElements grants; + AccessRightsElements partial_revokes; + }; + Elements getElements() const; + + /// Returns the information about all the access granted as a string. + String toString() const; + + /// Whether a specified access granted. + bool isGranted(const AccessFlags & access) const; + bool isGranted(const AccessFlags & access, const std::string_view & database) const; + bool isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table) const; + bool isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column) const; + bool isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns) const; + bool isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns) const; + bool isGranted(const AccessRightsElement & access, std::string_view current_database = {}) const; + bool isGranted(const AccessRightsElements & access, std::string_view current_database = {}) const; + + friend bool operator ==(const AccessRights & left, const AccessRights & right); + friend bool operator !=(const AccessRights & left, const AccessRights & right) { return !(left == right); } + + /// Merges two sets of access rights together. + /// It's used to combine access rights from multiple roles. + void merge(const AccessRights & other); + +private: + template + void grantImpl(const AccessFlags & access, const Args &... args); + + void grantImpl(const AccessRightsElement & access, std::string_view current_database); + void grantImpl(const AccessRightsElements & access, std::string_view current_database); + + template + void revokeImpl(const AccessFlags & access, const Args &... args); + + template + void revokeImpl(const AccessRightsElement & access, std::string_view current_database); + + template + void revokeImpl(const AccessRightsElements & access, std::string_view current_database); + + template + bool isGrantedImpl(const AccessFlags & access, const Args &... args) const; + + bool isGrantedImpl(const AccessRightsElement & access, std::string_view current_database) const; + bool isGrantedImpl(const AccessRightsElements & access, std::string_view current_database) const; + + template + AccessFlags getAccessImpl(const Args &... args) const; + + struct Node; + std::unique_ptr root; +}; + +} diff --git a/dbms/src/Access/AccessRightsContext.cpp b/dbms/src/Access/AccessRightsContext.cpp new file mode 100644 index 00000000000..c672c7a8f5f --- /dev/null +++ b/dbms/src/Access/AccessRightsContext.cpp @@ -0,0 +1,288 @@ +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace DB +{ +namespace ErrorCodes +{ + extern const int ACCESS_DENIED; + extern const int READONLY; + extern const int QUERY_IS_PROHIBITED; + extern const int FUNCTION_NOT_ALLOWED; +} + + +namespace +{ + enum CheckAccessRightsMode + { + RETURN_FALSE_IF_ACCESS_DENIED, + LOG_WARNING_IF_ACCESS_DENIED, + THROW_IF_ACCESS_DENIED, + }; + + + String formatSkippedMessage() + { + return ""; + } + + String formatSkippedMessage(const std::string_view & database) + { + return ". Skipped database " + backQuoteIfNeed(database); + } + + String formatSkippedMessage(const std::string_view & database, const std::string_view & table) + { + String str = ". Skipped table "; + if (!database.empty()) + str += backQuoteIfNeed(database) + "."; + str += backQuoteIfNeed(table); + return str; + } + + String formatSkippedMessage(const std::string_view & database, const std::string_view & table, const std::string_view & column) + { + String str = ". Skipped column " + backQuoteIfNeed(column) + " ON "; + if (!database.empty()) + str += backQuoteIfNeed(database) + "."; + str += backQuoteIfNeed(table); + return str; + } + + template + String formatSkippedMessage(const std::string_view & database, const std::string_view & table, const std::vector & columns) + { + if (columns.size() == 1) + return formatSkippedMessage(database, table, columns[0]); + + String str = ". Skipped columns "; + bool need_comma = false; + for (const auto & column : columns) + { + if (std::exchange(need_comma, true)) + str += ", "; + str += backQuoteIfNeed(column); + } + str += " ON "; + if (!database.empty()) + str += backQuoteIfNeed(database) + "."; + str += backQuoteIfNeed(table); + return str; + } +} + + +AccessRightsContext::AccessRightsContext() +{ + auto everything_granted = boost::make_shared(); + everything_granted->grant(AccessType::ALL); + result_access_cache[0] = std::move(everything_granted); +} + + +AccessRightsContext::AccessRightsContext(const ClientInfo & client_info_, const AccessRights & granted_to_user_, const Settings & settings, const String & current_database_) + : user_name(client_info_.current_user) + , granted_to_user(granted_to_user_) + , readonly(settings.readonly) + , allow_ddl(settings.allow_ddl) + , allow_introspection(settings.allow_introspection_functions) + , current_database(current_database_) + , interface(client_info_.interface) + , http_method(client_info_.http_method) + , trace_log(&Poco::Logger::get("AccessRightsContext (" + user_name + ")")) +{ +} + + +template +bool AccessRightsContext::checkImpl(Poco::Logger * log_, const AccessFlags & access, const Args &... args) const +{ + auto result_access = calculateResultAccess(); + bool is_granted = result_access->isGranted(access, args...); + + if (trace_log) + LOG_TRACE(trace_log, "Access " << (is_granted ? "granted" : "denied") << ": " << (AccessRightsElement{access, args...}.toString())); + + if (is_granted) + return true; + + if constexpr (mode == RETURN_FALSE_IF_ACCESS_DENIED) + return false; + + if constexpr (mode == LOG_WARNING_IF_ACCESS_DENIED) + { + if (!log_) + return false; + } + + auto show_error = [&](const String & msg, [[maybe_unused]] int error_code) + { + if constexpr (mode == THROW_IF_ACCESS_DENIED) + throw Exception(msg, error_code); + else if constexpr (mode == LOG_WARNING_IF_ACCESS_DENIED) + LOG_WARNING(log_, msg + formatSkippedMessage(args...)); + }; + + if (readonly && calculateResultAccess(false, allow_ddl, allow_introspection)->isGranted(access, args...)) + { + if (interface == ClientInfo::Interface::HTTP && http_method == ClientInfo::HTTPMethod::GET) + show_error( + "Cannot execute query in readonly mode. " + "For queries over HTTP, method GET implies readonly. You should use method POST for modifying queries", + ErrorCodes::READONLY); + else + show_error("Cannot execute query in readonly mode", ErrorCodes::READONLY); + } + else if (!allow_ddl && calculateResultAccess(readonly, true, allow_introspection)->isGranted(access, args...)) + { + show_error("Cannot execute query. DDL queries are prohibited for the user", ErrorCodes::QUERY_IS_PROHIBITED); + } + else if (!allow_introspection && calculateResultAccess(readonly, allow_ddl, true)->isGranted(access, args...)) + { + show_error("Introspection functions are disabled, because setting 'allow_introspection_functions' is set to 0", ErrorCodes::FUNCTION_NOT_ALLOWED); + } + else + { + show_error( + user_name + ": Not enough privileges. To perform this operation you should have grant " + + AccessRightsElement{access, args...}.toString(), + ErrorCodes::ACCESS_DENIED); + } + + return false; +} + +template +bool AccessRightsContext::checkImpl(Poco::Logger * log_, const AccessRightsElement & element) const +{ + if (element.any_database) + { + return checkImpl(log_, element.access_flags); + } + else if (element.any_table) + { + if (element.database.empty()) + return checkImpl(log_, element.access_flags, current_database); + else + return checkImpl(log_, element.access_flags, element.database); + } + else if (element.any_column) + { + if (element.database.empty()) + return checkImpl(log_, element.access_flags, current_database, element.table); + else + return checkImpl(log_, element.access_flags, element.database, element.table); + } + else + { + if (element.database.empty()) + return checkImpl(log_, element.access_flags, current_database, element.table, element.columns); + else + return checkImpl(log_, element.access_flags, element.database, element.table, element.columns); + } +} + + +template +bool AccessRightsContext::checkImpl(Poco::Logger * log_, const AccessRightsElements & elements) const +{ + for (const auto & element : elements) + if (!checkImpl(log_, element)) + return false; + return true; +} + + +void AccessRightsContext::check(const AccessFlags & access) const { checkImpl(nullptr, access); } +void AccessRightsContext::check(const AccessFlags & access, const std::string_view & database) const { checkImpl(nullptr, access, database); } +void AccessRightsContext::check(const AccessFlags & access, const std::string_view & database, const std::string_view & table) const { checkImpl(nullptr, access, database, table); } +void AccessRightsContext::check(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column) const { checkImpl(nullptr, access, database, table, column); } +void AccessRightsContext::check(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns) const { checkImpl(nullptr, access, database, table, columns); } +void AccessRightsContext::check(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns) const { checkImpl(nullptr, access, database, table, columns); } +void AccessRightsContext::check(const AccessRightsElement & access) const { checkImpl(nullptr, access); } +void AccessRightsContext::check(const AccessRightsElements & access) const { checkImpl(nullptr, access); } + +bool AccessRightsContext::isGranted(const AccessFlags & access) const { return checkImpl(nullptr, access); } +bool AccessRightsContext::isGranted(const AccessFlags & access, const std::string_view & database) const { return checkImpl(nullptr, access, database); } +bool AccessRightsContext::isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table) const { return checkImpl(nullptr, access, database, table); } +bool AccessRightsContext::isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column) const { return checkImpl(nullptr, access, database, table, column); } +bool AccessRightsContext::isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns) const { return checkImpl(nullptr, access, database, table, columns); } +bool AccessRightsContext::isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns) const { return checkImpl(nullptr, access, database, table, columns); } +bool AccessRightsContext::isGranted(const AccessRightsElement & access) const { return checkImpl(nullptr, access); } +bool AccessRightsContext::isGranted(const AccessRightsElements & access) const { return checkImpl(nullptr, access); } + +bool AccessRightsContext::isGranted(Poco::Logger * log_, const AccessFlags & access) const { return checkImpl(log_, access); } +bool AccessRightsContext::isGranted(Poco::Logger * log_, const AccessFlags & access, const std::string_view & database) const { return checkImpl(log_, access, database); } +bool AccessRightsContext::isGranted(Poco::Logger * log_, const AccessFlags & access, const std::string_view & database, const std::string_view & table) const { return checkImpl(log_, access, database, table); } +bool AccessRightsContext::isGranted(Poco::Logger * log_, const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column) const { return checkImpl(log_, access, database, table, column); } +bool AccessRightsContext::isGranted(Poco::Logger * log_, const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns) const { return checkImpl(log_, access, database, table, columns); } +bool AccessRightsContext::isGranted(Poco::Logger * log_, const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns) const { return checkImpl(log_, access, database, table, columns); } +bool AccessRightsContext::isGranted(Poco::Logger * log_, const AccessRightsElement & access) const { return checkImpl(log_, access); } +bool AccessRightsContext::isGranted(Poco::Logger * log_, const AccessRightsElements & access) const { return checkImpl(log_, access); } + + +boost::shared_ptr AccessRightsContext::calculateResultAccess() const +{ + auto res = result_access_cache[0].load(); + if (res) + return res; + return calculateResultAccess(readonly, allow_ddl, allow_introspection); +} + + +boost::shared_ptr AccessRightsContext::calculateResultAccess(UInt64 readonly_, bool allow_ddl_, bool allow_introspection_) const +{ + size_t cache_index = static_cast(readonly_ != readonly) + + static_cast(allow_ddl_ != allow_ddl) * 2 + + + static_cast(allow_introspection_ != allow_introspection) * 3; + assert(cache_index < std::size(result_access_cache)); + auto cached = result_access_cache[cache_index].load(); + if (cached) + return cached; + + std::lock_guard lock{mutex}; + cached = result_access_cache[cache_index].load(); + if (cached) + return cached; + + auto result_ptr = boost::make_shared(); + auto & result = *result_ptr; + + result = granted_to_user; + + static const AccessFlags table_ddl = AccessType::CREATE_DATABASE | AccessType::CREATE_TABLE | AccessType::CREATE_VIEW + | AccessType::ALTER_TABLE | AccessType::ALTER_VIEW | AccessType::DROP_DATABASE | AccessType::DROP_TABLE | AccessType::DROP_VIEW + | AccessType::DETACH_DATABASE | AccessType::DETACH_TABLE | AccessType::DETACH_VIEW | AccessType::TRUNCATE; + static const AccessFlags dictionary_ddl = AccessType::CREATE_DICTIONARY | AccessType::DROP_DICTIONARY | AccessType::DETACH_DICTIONARY; + static const AccessFlags table_and_dictionary_ddl = table_ddl | dictionary_ddl; + static const AccessFlags write_table_access = AccessType::INSERT | AccessType::OPTIMIZE; + + if (readonly_) + result.fullRevoke(write_table_access | AccessType::SYSTEM); + + if (readonly_ || !allow_ddl_) + result.fullRevoke(table_and_dictionary_ddl); + + if (readonly_ == 1) + { + /// Table functions are forbidden in readonly mode. + /// For example, for readonly = 2 - allowed. + result.fullRevoke(AccessType::CREATE_TEMPORARY_TABLE | AccessType::TABLE_FUNCTIONS); + } + + if (!allow_introspection_) + result.fullRevoke(AccessType::INTROSPECTION); + + result_access_cache[cache_index].store(result_ptr); + return std::move(result_ptr); +} + +} diff --git a/dbms/src/Access/AccessRightsContext.h b/dbms/src/Access/AccessRightsContext.h new file mode 100644 index 00000000000..ed32f120e8f --- /dev/null +++ b/dbms/src/Access/AccessRightsContext.h @@ -0,0 +1,81 @@ +#pragma once + +#include +#include +#include +#include + + +namespace Poco { class Logger; } + +namespace DB +{ +struct Settings; + + +class AccessRightsContext +{ +public: + /// Default constructor creates access rights' context which allows everything. + AccessRightsContext(); + + AccessRightsContext(const ClientInfo & client_info_, const AccessRights & granted_to_user, const Settings & settings, const String & current_database_); + + /// Checks if a specified access granted, and throws an exception if not. + /// Empty database means the current database. + void check(const AccessFlags & access) const; + void check(const AccessFlags & access, const std::string_view & database) const; + void check(const AccessFlags & access, const std::string_view & database, const std::string_view & table) const; + void check(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column) const; + void check(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns) const; + void check(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns) const; + void check(const AccessRightsElement & access) const; + void check(const AccessRightsElements & access) const; + + /// Checks if a specified access granted. + bool isGranted(const AccessFlags & access) const; + bool isGranted(const AccessFlags & access, const std::string_view & database) const; + bool isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table) const; + bool isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column) const; + bool isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns) const; + bool isGranted(const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns) const; + bool isGranted(const AccessRightsElement & access) const; + bool isGranted(const AccessRightsElements & access) const; + + /// Checks if a specified access granted, and logs a warning if not. + bool isGranted(Poco::Logger * log_, const AccessFlags & access) const; + bool isGranted(Poco::Logger * log_, const AccessFlags & access, const std::string_view & database) const; + bool isGranted(Poco::Logger * log_, const AccessFlags & access, const std::string_view & database, const std::string_view & table) const; + bool isGranted(Poco::Logger * log_, const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::string_view & column) const; + bool isGranted(Poco::Logger * log_, const AccessFlags & access, const std::string_view & database, const std::string_view & table, const std::vector & columns) const; + bool isGranted(Poco::Logger * log_, const AccessFlags & access, const std::string_view & database, const std::string_view & table, const Strings & columns) const; + bool isGranted(Poco::Logger * log_, const AccessRightsElement & access) const; + bool isGranted(Poco::Logger * log_, const AccessRightsElements & access) const; + +private: + template + bool checkImpl(Poco::Logger * log_, const AccessFlags & access, const Args &... args) const; + + template + bool checkImpl(Poco::Logger * log_, const AccessRightsElement & access) const; + + template + bool checkImpl(Poco::Logger * log_, const AccessRightsElements & access) const; + + boost::shared_ptr calculateResultAccess() const; + boost::shared_ptr calculateResultAccess(UInt64 readonly_, bool allow_ddl_, bool allow_introspection_) const; + + const String user_name; + const AccessRights granted_to_user; + const UInt64 readonly = 0; + const bool allow_ddl = true; + const bool allow_introspection = true; + const String current_database; + const ClientInfo::Interface interface = ClientInfo::Interface::TCP; + const ClientInfo::HTTPMethod http_method = ClientInfo::HTTPMethod::UNKNOWN; + Poco::Logger * const trace_log = nullptr; + mutable boost::atomic_shared_ptr result_access_cache[4]; + mutable std::mutex mutex; +}; + +} diff --git a/dbms/src/Access/AccessRightsElement.cpp b/dbms/src/Access/AccessRightsElement.cpp new file mode 100644 index 00000000000..b99cffc191c --- /dev/null +++ b/dbms/src/Access/AccessRightsElement.cpp @@ -0,0 +1,86 @@ +#include +#include +#include + + +namespace DB +{ +void AccessRightsElement::setDatabase(const String & new_database) +{ + database = new_database; + any_database = false; +} + + +void AccessRightsElement::replaceEmptyDatabase(const String & new_database) +{ + if (isEmptyDatabase()) + setDatabase(new_database); +} + + +bool AccessRightsElement::isEmptyDatabase() const +{ + return !any_database && database.empty(); +} + + +String AccessRightsElement::toString() const +{ + String columns_in_parentheses; + if (!any_column) + { + for (const auto & column : columns) + { + columns_in_parentheses += columns_in_parentheses.empty() ? "(" : ", "; + columns_in_parentheses += backQuoteIfNeed(column); + } + columns_in_parentheses += ")"; + } + + String msg; + for (const std::string_view & keyword : access_flags.toKeywords()) + { + if (!msg.empty()) + msg += ", "; + msg += String{keyword} + columns_in_parentheses; + } + + msg += " ON "; + + if (any_database) + msg += "*."; + else if (!database.empty() && (database != IDictionary::NO_DATABASE_TAG)) + msg += backQuoteIfNeed(database) + "."; + + if (any_table) + msg += "*"; + else + msg += backQuoteIfNeed(table); + return msg; +} + + +void AccessRightsElements::replaceEmptyDatabase(const String & new_database) +{ + for (auto & element : *this) + element.replaceEmptyDatabase(new_database); +} + + +String AccessRightsElements::toString() const +{ + String res; + bool need_comma = false; + for (auto & element : *this) + { + if (std::exchange(need_comma, true)) + res += ", "; + res += element.toString(); + } + + if (res.empty()) + res = "USAGE ON *.*"; + return res; +} +} diff --git a/dbms/src/Access/AccessRightsElement.h b/dbms/src/Access/AccessRightsElement.h new file mode 100644 index 00000000000..3894b6f5157 --- /dev/null +++ b/dbms/src/Access/AccessRightsElement.h @@ -0,0 +1,100 @@ +#pragma once + +#include + + +namespace DB +{ +/// An element of access rights which can be represented by single line +/// GRANT ... ON ... +struct AccessRightsElement +{ + AccessFlags access_flags; + String database; + String table; + Strings columns; + bool any_database = true; + bool any_table = true; + bool any_column = true; + + AccessRightsElement() = default; + AccessRightsElement(const AccessRightsElement &) = default; + AccessRightsElement & operator=(const AccessRightsElement &) = default; + AccessRightsElement(AccessRightsElement &&) = default; + AccessRightsElement & operator=(AccessRightsElement &&) = default; + + AccessRightsElement(AccessFlags access_flags_) : access_flags(access_flags_) {} + + AccessRightsElement(AccessFlags access_flags_, const std::string_view & database_) + : access_flags(access_flags_), database(database_), any_database(false) + { + } + + AccessRightsElement(AccessFlags access_flags_, const std::string_view & database_, const std::string_view & table_) + : access_flags(access_flags_), database(database_), table(table_), any_database(false), any_table(false) + { + } + + AccessRightsElement( + AccessFlags access_flags_, const std::string_view & database_, const std::string_view & table_, const std::string_view & column_) + : access_flags(access_flags_) + , database(database_) + , table(table_) + , columns({String{column_}}) + , any_database(false) + , any_table(false) + , any_column(false) + { + } + + AccessRightsElement( + AccessFlags access_flags_, + const std::string_view & database_, + const std::string_view & table_, + const std::vector & columns_) + : access_flags(access_flags_), database(database_), table(table_), any_database(false), any_table(false), any_column(false) + { + columns.resize(columns_.size()); + for (size_t i = 0; i != columns_.size(); ++i) + columns[i] = String{columns_[i]}; + } + + AccessRightsElement( + AccessFlags access_flags_, const std::string_view & database_, const std::string_view & table_, const Strings & columns_) + : access_flags(access_flags_) + , database(database_) + , table(table_) + , columns(columns_) + , any_database(false) + , any_table(false) + , any_column(false) + { + } + + /// Sets the database. + void setDatabase(const String & new_database); + + /// If the database is empty, replaces it with `new_database`. Otherwise does nothing. + void replaceEmptyDatabase(const String & new_database); + + bool isEmptyDatabase() const; + + /// Returns a human-readable representation like "SELECT, UPDATE(x, y) ON db.table". + /// The returned string isn't prefixed with the "GRANT" keyword. + String toString() const; +}; + + +/// Multiple elements of access rights. +class AccessRightsElements : public std::vector +{ +public: + /// Replaces the empty database with `new_database`. + void replaceEmptyDatabase(const String & new_database); + + /// Returns a human-readable representation like "SELECT, UPDATE(x, y) ON db.table". + /// The returned string isn't prefixed with the "GRANT" keyword. + String toString() const; +}; + +} diff --git a/dbms/src/Access/AccessType.h b/dbms/src/Access/AccessType.h new file mode 100644 index 00000000000..5b96524997e --- /dev/null +++ b/dbms/src/Access/AccessType.h @@ -0,0 +1,328 @@ +#pragma once + +#include +#include +#include +#include + + +namespace DB +{ +/// Represents an access type which can be granted on databases, tables, columns, etc. +enum class AccessType +{ + NONE, /// no access + ALL, /// full access + + SHOW, /// allows to execute SHOW TABLES, SHOW CREATE TABLE, SHOW DATABASES and so on + /// (granted implicitly with any other grant) + + EXISTS, /// allows to execute EXISTS, USE, i.e. to check existence + /// (granted implicitly on the database level with any other grant on the database and lower levels, + /// e.g. "GRANT SELECT(x) ON db.table" also grants EXISTS on db.*) + + SELECT, + INSERT, + UPDATE, /// allows to execute ALTER UPDATE + DELETE, /// allows to execute ALTER DELETE + + ADD_COLUMN, + DROP_COLUMN, + MODIFY_COLUMN, + COMMENT_COLUMN, + CLEAR_COLUMN, + ALTER_COLUMN, /// allow to execute ALTER {ADD|DROP|MODIFY...} COLUMN + + ALTER_ORDER_BY, + ADD_INDEX, + DROP_INDEX, + MATERIALIZE_INDEX, + CLEAR_INDEX, + INDEX, /// allows to execute ALTER ORDER BY or ALTER {ADD|DROP...} INDEX + + ADD_CONSTRAINT, + DROP_CONSTRAINT, + ALTER_CONSTRAINT, /// allows to execute ALTER {ADD|DROP} CONSTRAINT + + MODIFY_TTL, /// allows to execute ALTER MODIFY TTL + MODIFY_SETTING, /// allows to execute ALTER MODIFY SETTING + + MOVE_PARTITION, + FETCH_PARTITION, + FREEZE_PARTITION, + + ALTER_TABLE, /// allows to execute ALTER TABLE ... + + REFRESH_VIEW, /// allows to execute ALTER LIVE VIEW REFRESH + MODIFY_VIEW_QUERY, /// allows to execute ALTER TABLE MODIFY QUERY + ALTER_VIEW, /// allows to execute ALTER LIVE VIEW REFRESH, ALTER TABLE MODIFY QUERY + + ALTER, /// allows to execute ALTER {TABLE|LIVE VIEW} ... + + CREATE_DATABASE, /// allows to execute {CREATE|ATTACH} DATABASE + CREATE_TABLE, /// allows to execute {CREATE|ATTACH} TABLE + CREATE_VIEW, /// allows to execute {CREATE|ATTACH} VIEW + CREATE_DICTIONARY, /// allows to execute {CREATE|ATTACH} DICTIONARY + CREATE_TEMPORARY_TABLE, /// allows to create and manipulate temporary tables and views. + CREATE, /// allows to execute {CREATE|ATTACH} [TEMPORARY] {DATABASE|TABLE|VIEW|DICTIONARY} + + ATTACH_DATABASE, /// allows to execute {CREATE|ATTACH} DATABASE + ATTACH_TABLE, /// allows to execute {CREATE|ATTACH} TABLE + ATTACH_VIEW, /// allows to execute {CREATE|ATTACH} VIEW + ATTACH_DICTIONARY, /// allows to execute {CREATE|ATTACH} DICTIONARY + ATTACH, /// allows to execute {CREATE|ATTACH} {DATABASE|TABLE|VIEW|DICTIONARY} + + DROP_DATABASE, + DROP_TABLE, + DROP_VIEW, + DROP_DICTIONARY, + DROP, /// allows to execute DROP {DATABASE|TABLE|VIEW|DICTIONARY} + + DETACH_DATABASE, + DETACH_TABLE, + DETACH_VIEW, + DETACH_DICTIONARY, + DETACH, /// allows to execute DETACH {DATABASE|TABLE|VIEW|DICTIONARY} + + TRUNCATE_TABLE, + TRUNCATE_VIEW, + TRUNCATE, /// allows to execute TRUNCATE {TABLE|VIEW} + + OPTIMIZE, /// allows to execute OPTIMIZE TABLE + + KILL_QUERY, /// allows to kill a query started by another user (anyone can kill his own queries) + KILL_MUTATION, /// allows to kill a mutation + KILL, /// allows to execute KILL {MUTATION|QUERY} + + CREATE_USER, /// allows to create, alter and drop users, roles, quotas, row policies. + ALTER_USER, + DROP_USER, + CREATE_ROLE, + DROP_ROLE, + CREATE_POLICY, + ALTER_POLICY, + DROP_POLICY, + CREATE_QUOTA, + ALTER_QUOTA, + DROP_QUOTA, + + SHUTDOWN, + DROP_CACHE, + RELOAD_CONFIG, + RELOAD_DICTIONARY, + STOP_MERGES, + STOP_TTL_MERGES, + STOP_FETCHES, + STOP_MOVES, + STOP_DISTRIBUTED_SENDS, + STOP_REPLICATED_SENDS, + STOP_REPLICATION_QUEUES, + SYNC_REPLICA, + RESTART_REPLICA, + FLUSH_DISTRIBUTED, + FLUSH_LOGS, + SYSTEM, /// allows to execute SYSTEM {SHUTDOWN|RELOAD CONFIG|...} + + dictGet, /// allows to execute functions dictGet, dictHas, dictGetHierarchy, dictIsIn + dictHas, /// allows to execute functions dictGet, dictHas, dictGetHierarchy, dictIsIn + dictGetHierarchy, /// allows to execute functions dictGet, dictHas, dictGetHierarchy, dictIsIn + dictIsIn, /// allows to execute functions dictGet, dictHas, dictGetHierarchy, dictIsIn + + addressToLine, /// allows to execute function addressToLine + addressToSymbol, /// allows to execute function addressToSymbol + demangle, /// allows to execute function demangle + INTROSPECTION, /// allows to execute functions addressToLine, addressToSymbol, demangle + + file, + url, + input, + values, + numbers, + merge, + remote, + mysql, + odbc, + jdbc, + hdfs, + s3, + TABLE_FUNCTIONS, /// allows to execute any table function +}; + +constexpr size_t MAX_ACCESS_TYPE = static_cast(AccessType::TABLE_FUNCTIONS) + 1; + +std::string_view toString(AccessType type); + + +namespace impl +{ + template + class AccessTypeToKeywordConverter + { + public: + static const AccessTypeToKeywordConverter & instance() + { + static const AccessTypeToKeywordConverter res; + return res; + } + + std::string_view convert(AccessType type) const + { + return access_type_to_keyword_mapping[static_cast(type)]; + } + + private: + void addToMapping(AccessType type, const std::string_view & str) + { + String str2{str}; + boost::replace_all(str2, "_", " "); + if (islower(str2[0])) + str2 += "()"; + access_type_to_keyword_mapping[static_cast(type)] = str2; + } + + AccessTypeToKeywordConverter() + { +#define ACCESS_TYPE_TO_KEYWORD_CASE(type) \ + addToMapping(AccessType::type, #type) + + ACCESS_TYPE_TO_KEYWORD_CASE(NONE); + ACCESS_TYPE_TO_KEYWORD_CASE(ALL); + ACCESS_TYPE_TO_KEYWORD_CASE(SHOW); + ACCESS_TYPE_TO_KEYWORD_CASE(EXISTS); + + ACCESS_TYPE_TO_KEYWORD_CASE(SELECT); + ACCESS_TYPE_TO_KEYWORD_CASE(INSERT); + ACCESS_TYPE_TO_KEYWORD_CASE(UPDATE); + ACCESS_TYPE_TO_KEYWORD_CASE(DELETE); + + ACCESS_TYPE_TO_KEYWORD_CASE(ADD_COLUMN); + ACCESS_TYPE_TO_KEYWORD_CASE(DROP_COLUMN); + ACCESS_TYPE_TO_KEYWORD_CASE(MODIFY_COLUMN); + ACCESS_TYPE_TO_KEYWORD_CASE(COMMENT_COLUMN); + ACCESS_TYPE_TO_KEYWORD_CASE(CLEAR_COLUMN); + ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_COLUMN); + + ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_ORDER_BY); + ACCESS_TYPE_TO_KEYWORD_CASE(ADD_INDEX); + ACCESS_TYPE_TO_KEYWORD_CASE(DROP_INDEX); + ACCESS_TYPE_TO_KEYWORD_CASE(MATERIALIZE_INDEX); + ACCESS_TYPE_TO_KEYWORD_CASE(CLEAR_INDEX); + ACCESS_TYPE_TO_KEYWORD_CASE(INDEX); + + ACCESS_TYPE_TO_KEYWORD_CASE(ADD_CONSTRAINT); + ACCESS_TYPE_TO_KEYWORD_CASE(DROP_CONSTRAINT); + ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_CONSTRAINT); + + ACCESS_TYPE_TO_KEYWORD_CASE(MODIFY_TTL); + ACCESS_TYPE_TO_KEYWORD_CASE(MODIFY_SETTING); + + ACCESS_TYPE_TO_KEYWORD_CASE(MOVE_PARTITION); + ACCESS_TYPE_TO_KEYWORD_CASE(FETCH_PARTITION); + ACCESS_TYPE_TO_KEYWORD_CASE(FREEZE_PARTITION); + + ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_TABLE); + + ACCESS_TYPE_TO_KEYWORD_CASE(REFRESH_VIEW); + ACCESS_TYPE_TO_KEYWORD_CASE(MODIFY_VIEW_QUERY); + ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_VIEW); + + ACCESS_TYPE_TO_KEYWORD_CASE(ALTER); + + ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_DATABASE); + ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_TABLE); + ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_VIEW); + ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_DICTIONARY); + ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_TEMPORARY_TABLE); + ACCESS_TYPE_TO_KEYWORD_CASE(CREATE); + + ACCESS_TYPE_TO_KEYWORD_CASE(ATTACH_DATABASE); + ACCESS_TYPE_TO_KEYWORD_CASE(ATTACH_TABLE); + ACCESS_TYPE_TO_KEYWORD_CASE(ATTACH_VIEW); + ACCESS_TYPE_TO_KEYWORD_CASE(ATTACH_DICTIONARY); + ACCESS_TYPE_TO_KEYWORD_CASE(ATTACH); + + ACCESS_TYPE_TO_KEYWORD_CASE(DROP_DATABASE); + ACCESS_TYPE_TO_KEYWORD_CASE(DROP_TABLE); + ACCESS_TYPE_TO_KEYWORD_CASE(DROP_VIEW); + ACCESS_TYPE_TO_KEYWORD_CASE(DROP_DICTIONARY); + ACCESS_TYPE_TO_KEYWORD_CASE(DROP); + + ACCESS_TYPE_TO_KEYWORD_CASE(DETACH_DATABASE); + ACCESS_TYPE_TO_KEYWORD_CASE(DETACH_TABLE); + ACCESS_TYPE_TO_KEYWORD_CASE(DETACH_VIEW); + ACCESS_TYPE_TO_KEYWORD_CASE(DETACH_DICTIONARY); + ACCESS_TYPE_TO_KEYWORD_CASE(DETACH); + + ACCESS_TYPE_TO_KEYWORD_CASE(TRUNCATE_TABLE); + ACCESS_TYPE_TO_KEYWORD_CASE(TRUNCATE_VIEW); + ACCESS_TYPE_TO_KEYWORD_CASE(TRUNCATE); + + ACCESS_TYPE_TO_KEYWORD_CASE(OPTIMIZE); + + ACCESS_TYPE_TO_KEYWORD_CASE(KILL_QUERY); + ACCESS_TYPE_TO_KEYWORD_CASE(KILL_MUTATION); + ACCESS_TYPE_TO_KEYWORD_CASE(KILL); + + ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_USER); + ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_USER); + ACCESS_TYPE_TO_KEYWORD_CASE(DROP_USER); + ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_ROLE); + ACCESS_TYPE_TO_KEYWORD_CASE(DROP_ROLE); + ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_POLICY); + ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_POLICY); + ACCESS_TYPE_TO_KEYWORD_CASE(DROP_POLICY); + ACCESS_TYPE_TO_KEYWORD_CASE(CREATE_QUOTA); + ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_QUOTA); + ACCESS_TYPE_TO_KEYWORD_CASE(DROP_QUOTA); + + ACCESS_TYPE_TO_KEYWORD_CASE(SHUTDOWN); + ACCESS_TYPE_TO_KEYWORD_CASE(DROP_CACHE); + ACCESS_TYPE_TO_KEYWORD_CASE(RELOAD_CONFIG); + ACCESS_TYPE_TO_KEYWORD_CASE(RELOAD_DICTIONARY); + ACCESS_TYPE_TO_KEYWORD_CASE(STOP_MERGES); + ACCESS_TYPE_TO_KEYWORD_CASE(STOP_TTL_MERGES); + ACCESS_TYPE_TO_KEYWORD_CASE(STOP_FETCHES); + ACCESS_TYPE_TO_KEYWORD_CASE(STOP_MOVES); + ACCESS_TYPE_TO_KEYWORD_CASE(STOP_DISTRIBUTED_SENDS); + ACCESS_TYPE_TO_KEYWORD_CASE(STOP_REPLICATED_SENDS); + ACCESS_TYPE_TO_KEYWORD_CASE(STOP_REPLICATION_QUEUES); + ACCESS_TYPE_TO_KEYWORD_CASE(SYNC_REPLICA); + ACCESS_TYPE_TO_KEYWORD_CASE(RESTART_REPLICA); + ACCESS_TYPE_TO_KEYWORD_CASE(FLUSH_DISTRIBUTED); + ACCESS_TYPE_TO_KEYWORD_CASE(FLUSH_LOGS); + ACCESS_TYPE_TO_KEYWORD_CASE(SYSTEM); + + ACCESS_TYPE_TO_KEYWORD_CASE(dictGet); + ACCESS_TYPE_TO_KEYWORD_CASE(dictHas); + ACCESS_TYPE_TO_KEYWORD_CASE(dictGetHierarchy); + ACCESS_TYPE_TO_KEYWORD_CASE(dictIsIn); + + ACCESS_TYPE_TO_KEYWORD_CASE(addressToLine); + ACCESS_TYPE_TO_KEYWORD_CASE(addressToSymbol); + ACCESS_TYPE_TO_KEYWORD_CASE(demangle); + ACCESS_TYPE_TO_KEYWORD_CASE(INTROSPECTION); + + ACCESS_TYPE_TO_KEYWORD_CASE(file); + ACCESS_TYPE_TO_KEYWORD_CASE(url); + ACCESS_TYPE_TO_KEYWORD_CASE(input); + ACCESS_TYPE_TO_KEYWORD_CASE(values); + ACCESS_TYPE_TO_KEYWORD_CASE(numbers); + ACCESS_TYPE_TO_KEYWORD_CASE(merge); + ACCESS_TYPE_TO_KEYWORD_CASE(remote); + ACCESS_TYPE_TO_KEYWORD_CASE(mysql); + ACCESS_TYPE_TO_KEYWORD_CASE(odbc); + ACCESS_TYPE_TO_KEYWORD_CASE(jdbc); + ACCESS_TYPE_TO_KEYWORD_CASE(hdfs); + ACCESS_TYPE_TO_KEYWORD_CASE(s3); + ACCESS_TYPE_TO_KEYWORD_CASE(TABLE_FUNCTIONS); + +#undef ACCESS_TYPE_TO_KEYWORD_CASE + } + + std::array access_type_to_keyword_mapping; + }; +} + +inline std::string_view toKeyword(AccessType type) { return impl::AccessTypeToKeywordConverter<>::instance().convert(type); } + +} diff --git a/dbms/src/Access/IAccessEntity.cpp b/dbms/src/Access/IAccessEntity.cpp index 9b203a74148..361946863b2 100644 --- a/dbms/src/Access/IAccessEntity.cpp +++ b/dbms/src/Access/IAccessEntity.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -8,6 +9,8 @@ namespace DB { String IAccessEntity::getTypeName(std::type_index type) { + if (type == typeid(User)) + return "User"; if (type == typeid(Quota)) return "Quota"; if (type == typeid(RowPolicy)) diff --git a/dbms/src/Access/IAccessStorage.cpp b/dbms/src/Access/IAccessStorage.cpp index 4283ec9e6dc..9120d626d09 100644 --- a/dbms/src/Access/IAccessStorage.cpp +++ b/dbms/src/Access/IAccessStorage.cpp @@ -299,44 +299,24 @@ std::vector IAccessStorage::tryUpdate(const std::vector & ids, const } -IAccessStorage::SubscriptionPtr IAccessStorage::subscribeForChanges(std::type_index type, const OnChangedHandler & handler) const +ext::scope_guard IAccessStorage::subscribeForChanges(std::type_index type, const OnChangedHandler & handler) const { return subscribeForChangesImpl(type, handler); } -IAccessStorage::SubscriptionPtr IAccessStorage::subscribeForChanges(const UUID & id, const OnChangedHandler & handler) const +ext::scope_guard IAccessStorage::subscribeForChanges(const UUID & id, const OnChangedHandler & handler) const { return subscribeForChangesImpl(id, handler); } -IAccessStorage::SubscriptionPtr IAccessStorage::subscribeForChanges(const std::vector & ids, const OnChangedHandler & handler) const +ext::scope_guard IAccessStorage::subscribeForChanges(const std::vector & ids, const OnChangedHandler & handler) const { - if (ids.empty()) - return nullptr; - if (ids.size() == 1) - return subscribeForChangesImpl(ids[0], handler); - - std::vector subscriptions; - subscriptions.reserve(ids.size()); + ext::scope_guard subscriptions; for (const auto & id : ids) - { - auto subscription = subscribeForChangesImpl(id, handler); - if (subscription) - subscriptions.push_back(std::move(subscription)); - } - - class SubscriptionImpl : public Subscription - { - public: - SubscriptionImpl(std::vector subscriptions_) - : subscriptions(std::move(subscriptions_)) {} - private: - std::vector subscriptions; - }; - - return std::make_unique(std::move(subscriptions)); + subscriptions.join(subscribeForChangesImpl(id, handler)); + return subscriptions; } diff --git a/dbms/src/Access/IAccessStorage.h b/dbms/src/Access/IAccessStorage.h index b4153bce87d..d0be38caf07 100644 --- a/dbms/src/Access/IAccessStorage.h +++ b/dbms/src/Access/IAccessStorage.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -109,26 +110,19 @@ public: /// Updates multiple entities in the storage. Returns the list of successfully updated. std::vector tryUpdate(const std::vector & ids, const UpdateFunc & update_func); - class Subscription - { - public: - virtual ~Subscription() {} - }; - - using SubscriptionPtr = std::unique_ptr; using OnChangedHandler = std::function; /// Subscribes for all changes. /// Can return nullptr if cannot subscribe (identifier not found) or if it doesn't make sense (the storage is read-only). - SubscriptionPtr subscribeForChanges(std::type_index type, const OnChangedHandler & handler) const; + ext::scope_guard subscribeForChanges(std::type_index type, const OnChangedHandler & handler) const; template - SubscriptionPtr subscribeForChanges(OnChangedHandler handler) const { return subscribeForChanges(typeid(EntityType), handler); } + ext::scope_guard subscribeForChanges(OnChangedHandler handler) const { return subscribeForChanges(typeid(EntityType), handler); } /// Subscribes for changes of a specific entry. /// Can return nullptr if cannot subscribe (identifier not found) or if it doesn't make sense (the storage is read-only). - SubscriptionPtr subscribeForChanges(const UUID & id, const OnChangedHandler & handler) const; - SubscriptionPtr subscribeForChanges(const std::vector & ids, const OnChangedHandler & handler) const; + ext::scope_guard subscribeForChanges(const UUID & id, const OnChangedHandler & handler) const; + ext::scope_guard subscribeForChanges(const std::vector & ids, const OnChangedHandler & handler) const; bool hasSubscription(std::type_index type) const; bool hasSubscription(const UUID & id) const; @@ -142,8 +136,8 @@ protected: virtual UUID insertImpl(const AccessEntityPtr & entity, bool replace_if_exists) = 0; virtual void removeImpl(const UUID & id) = 0; virtual void updateImpl(const UUID & id, const UpdateFunc & update_func) = 0; - virtual SubscriptionPtr subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const = 0; - virtual SubscriptionPtr subscribeForChangesImpl(std::type_index type, const OnChangedHandler & handler) const = 0; + virtual ext::scope_guard subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const = 0; + virtual ext::scope_guard subscribeForChangesImpl(std::type_index type, const OnChangedHandler & handler) const = 0; virtual bool hasSubscriptionImpl(const UUID & id) const = 0; virtual bool hasSubscriptionImpl(std::type_index type) const = 0; diff --git a/dbms/src/Access/MemoryAccessStorage.cpp b/dbms/src/Access/MemoryAccessStorage.cpp index ed42acca1a7..310f4b97fda 100644 --- a/dbms/src/Access/MemoryAccessStorage.cpp +++ b/dbms/src/Access/MemoryAccessStorage.cpp @@ -6,7 +6,7 @@ namespace DB { MemoryAccessStorage::MemoryAccessStorage(const String & storage_name_) - : IAccessStorage(storage_name_), shared_ptr_to_this{std::make_shared(this)} + : IAccessStorage(storage_name_) { } @@ -256,85 +256,38 @@ void MemoryAccessStorage::prepareNotifications(const Entry & entry, bool remove, } -IAccessStorage::SubscriptionPtr MemoryAccessStorage::subscribeForChangesImpl(std::type_index type, const OnChangedHandler & handler) const +ext::scope_guard MemoryAccessStorage::subscribeForChangesImpl(std::type_index type, const OnChangedHandler & handler) const { - class SubscriptionImpl : public Subscription + std::lock_guard lock{mutex}; + auto handler_it = handlers_by_type.emplace(type, handler); + + return [this, handler_it] { - public: - SubscriptionImpl( - const MemoryAccessStorage & storage_, - std::type_index type_, - const OnChangedHandler & handler_) - : storage_weak(storage_.shared_ptr_to_this) - { - std::lock_guard lock{storage_.mutex}; - handler_it = storage_.handlers_by_type.emplace(type_, handler_); - } - - ~SubscriptionImpl() override - { - auto storage = storage_weak.lock(); - if (storage) - { - std::lock_guard lock{(*storage)->mutex}; - (*storage)->handlers_by_type.erase(handler_it); - } - } - - private: - std::weak_ptr storage_weak; - std::unordered_multimap::iterator handler_it; + std::lock_guard lock2{mutex}; + handlers_by_type.erase(handler_it); }; - - return std::make_unique(*this, type, handler); } -IAccessStorage::SubscriptionPtr MemoryAccessStorage::subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const +ext::scope_guard MemoryAccessStorage::subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const { - class SubscriptionImpl : public Subscription + std::lock_guard lock{mutex}; + auto it = entries.find(id); + if (it == entries.end()) + return {}; + const Entry & entry = it->second; + auto handler_it = entry.handlers_by_id.insert(entry.handlers_by_id.end(), handler); + + return [this, id, handler_it] { - public: - SubscriptionImpl( - const MemoryAccessStorage & storage_, - const UUID & id_, - const OnChangedHandler & handler_) - : storage_weak(storage_.shared_ptr_to_this), - id(id_) + std::lock_guard lock2{mutex}; + auto it2 = entries.find(id); + if (it2 != entries.end()) { - std::lock_guard lock{storage_.mutex}; - auto it = storage_.entries.find(id); - if (it == storage_.entries.end()) - { - storage_weak.reset(); - return; - } - const Entry & entry = it->second; - handler_it = entry.handlers_by_id.insert(entry.handlers_by_id.end(), handler_); + const Entry & entry2 = it2->second; + entry2.handlers_by_id.erase(handler_it); } - - ~SubscriptionImpl() override - { - auto storage = storage_weak.lock(); - if (storage) - { - std::lock_guard lock{(*storage)->mutex}; - auto it = (*storage)->entries.find(id); - if (it != (*storage)->entries.end()) - { - const Entry & entry = it->second; - entry.handlers_by_id.erase(handler_it); - } - } - } - - private: - std::weak_ptr storage_weak; - UUID id; - std::list::iterator handler_it; }; - - return std::make_unique(*this, id, handler); } diff --git a/dbms/src/Access/MemoryAccessStorage.h b/dbms/src/Access/MemoryAccessStorage.h index 51c55487ca7..93d1b24e9da 100644 --- a/dbms/src/Access/MemoryAccessStorage.h +++ b/dbms/src/Access/MemoryAccessStorage.h @@ -29,8 +29,8 @@ private: UUID insertImpl(const AccessEntityPtr & entity, bool replace_if_exists) override; void removeImpl(const UUID & id) override; void updateImpl(const UUID & id, const UpdateFunc & update_func) override; - SubscriptionPtr subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const override; - SubscriptionPtr subscribeForChangesImpl(std::type_index type, const OnChangedHandler & handler) const override; + ext::scope_guard subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const override; + ext::scope_guard subscribeForChangesImpl(std::type_index type, const OnChangedHandler & handler) const override; bool hasSubscriptionImpl(const UUID & id) const override; bool hasSubscriptionImpl(std::type_index type) const override; @@ -60,6 +60,5 @@ private: std::unordered_map entries; /// We want to search entries both by ID and by the pair of name and type. std::unordered_map names; /// and by the pair of name and type. mutable std::unordered_multimap handlers_by_type; - std::shared_ptr shared_ptr_to_this; /// We need weak pointers to `this` to implement subscriptions. }; } diff --git a/dbms/src/Access/MultipleAccessStorage.cpp b/dbms/src/Access/MultipleAccessStorage.cpp index f3db0b0fbbc..9306e2bfff7 100644 --- a/dbms/src/Access/MultipleAccessStorage.cpp +++ b/dbms/src/Access/MultipleAccessStorage.cpp @@ -185,41 +185,21 @@ void MultipleAccessStorage::updateImpl(const UUID & id, const UpdateFunc & updat } -IAccessStorage::SubscriptionPtr MultipleAccessStorage::subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const +ext::scope_guard MultipleAccessStorage::subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const { auto storage = findStorage(id); if (!storage) - return nullptr; + return {}; return storage->subscribeForChanges(id, handler); } -IAccessStorage::SubscriptionPtr MultipleAccessStorage::subscribeForChangesImpl(std::type_index type, const OnChangedHandler & handler) const +ext::scope_guard MultipleAccessStorage::subscribeForChangesImpl(std::type_index type, const OnChangedHandler & handler) const { - std::vector subscriptions; + ext::scope_guard subscriptions; for (const auto & nested_storage : nested_storages) - { - auto subscription = nested_storage->subscribeForChanges(type, handler); - if (subscription) - subscriptions.emplace_back(std::move(subscription)); - } - - if (subscriptions.empty()) - return nullptr; - - if (subscriptions.size() == 1) - return std::move(subscriptions[0]); - - class SubscriptionImpl : public Subscription - { - public: - SubscriptionImpl(std::vector subscriptions_) - : subscriptions(std::move(subscriptions_)) {} - private: - std::vector subscriptions; - }; - - return std::make_unique(std::move(subscriptions)); + subscriptions.join(nested_storage->subscribeForChanges(type, handler)); + return subscriptions; } diff --git a/dbms/src/Access/MultipleAccessStorage.h b/dbms/src/Access/MultipleAccessStorage.h index 42e500a1851..de617063e31 100644 --- a/dbms/src/Access/MultipleAccessStorage.h +++ b/dbms/src/Access/MultipleAccessStorage.h @@ -38,8 +38,8 @@ protected: UUID insertImpl(const AccessEntityPtr & entity, bool replace_if_exists) override; void removeImpl(const UUID & id) override; void updateImpl(const UUID & id, const UpdateFunc & update_func) override; - SubscriptionPtr subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const override; - SubscriptionPtr subscribeForChangesImpl(std::type_index type, const OnChangedHandler & handler) const override; + ext::scope_guard subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const override; + ext::scope_guard subscribeForChangesImpl(std::type_index type, const OnChangedHandler & handler) const override; bool hasSubscriptionImpl(const UUID & id) const override; bool hasSubscriptionImpl(std::type_index type) const override; diff --git a/dbms/src/Access/QuotaContextFactory.h b/dbms/src/Access/QuotaContextFactory.h index 159ffe1fa09..611a25059f6 100644 --- a/dbms/src/Access/QuotaContextFactory.h +++ b/dbms/src/Access/QuotaContextFactory.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include #include @@ -56,7 +56,7 @@ private: mutable std::mutex mutex; std::unordered_map all_quotas; bool all_quotas_read = false; - IAccessStorage::SubscriptionPtr subscription; + ext::scope_guard subscription; std::vector> contexts; }; } diff --git a/dbms/src/Access/RowPolicyContextFactory.h b/dbms/src/Access/RowPolicyContextFactory.h index 02019c468a9..b04244a1d99 100644 --- a/dbms/src/Access/RowPolicyContextFactory.h +++ b/dbms/src/Access/RowPolicyContextFactory.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include #include @@ -46,7 +46,7 @@ private: const AccessControlManager & access_control_manager; std::unordered_map all_policies; bool all_policies_read = false; - IAccessStorage::SubscriptionPtr subscription; + ext::scope_guard subscription; std::vector> contexts; std::mutex mutex; }; diff --git a/dbms/src/Access/User.cpp b/dbms/src/Access/User.cpp new file mode 100644 index 00000000000..af84e14d9d8 --- /dev/null +++ b/dbms/src/Access/User.cpp @@ -0,0 +1,16 @@ +#include + + +namespace DB +{ + +bool User::equal(const IAccessEntity & other) const +{ + if (!IAccessEntity::equal(other)) + return false; + const auto & other_user = typeid_cast(other); + return (authentication == other_user.authentication) && (allowed_client_hosts == other_user.allowed_client_hosts) + && (access == other_user.access) && (profile == other_user.profile); +} + +} diff --git a/dbms/src/Access/User.h b/dbms/src/Access/User.h new file mode 100644 index 00000000000..3c93661a440 --- /dev/null +++ b/dbms/src/Access/User.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include +#include +#include + + +namespace DB +{ +/** User and ACL. + */ +struct User : public IAccessEntity +{ + Authentication authentication; + AllowedClientHosts allowed_client_hosts; + AccessRights access; + String profile; + + bool equal(const IAccessEntity & other) const override; + std::shared_ptr clone() const override { return cloneImpl(); } +}; + +using UserPtr = std::shared_ptr; +} diff --git a/dbms/src/Access/UsersConfigAccessStorage.cpp b/dbms/src/Access/UsersConfigAccessStorage.cpp index 033e8f557b7..070dea8d3c8 100644 --- a/dbms/src/Access/UsersConfigAccessStorage.cpp +++ b/dbms/src/Access/UsersConfigAccessStorage.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include #include #include @@ -10,10 +12,19 @@ namespace DB { +namespace ErrorCodes +{ + extern const int BAD_ARGUMENTS; + extern const int UNKNOWN_ADDRESS_PATTERN_TYPE; +} + + namespace { char getTypeChar(std::type_index type) { + if (type == typeid(User)) + return 'U'; if (type == typeid(Quota)) return 'Q'; if (type == typeid(RowPolicy)) @@ -37,6 +48,139 @@ namespace UUID generateID(const IAccessEntity & entity) { return generateID(entity.getType(), entity.getFullName()); } + UserPtr parseUser(const Poco::Util::AbstractConfiguration & config, const String & user_name) + { + auto user = std::make_shared(); + user->setName(user_name); + + String user_config = "users." + user_name; + + bool has_password = config.has(user_config + ".password"); + bool has_password_sha256_hex = config.has(user_config + ".password_sha256_hex"); + bool has_password_double_sha1_hex = config.has(user_config + ".password_double_sha1_hex"); + + if (has_password + has_password_sha256_hex + has_password_double_sha1_hex > 1) + throw Exception("More than one field of 'password', 'password_sha256_hex', 'password_double_sha1_hex' is used to specify password for user " + user_name + ". Must be only one of them.", + ErrorCodes::BAD_ARGUMENTS); + + if (!has_password && !has_password_sha256_hex && !has_password_double_sha1_hex) + throw Exception("Either 'password' or 'password_sha256_hex' or 'password_double_sha1_hex' must be specified for user " + user_name + ".", ErrorCodes::BAD_ARGUMENTS); + + if (has_password) + { + user->authentication = Authentication{Authentication::PLAINTEXT_PASSWORD}; + user->authentication.setPassword(config.getString(user_config + ".password")); + } + else if (has_password_sha256_hex) + { + user->authentication = Authentication{Authentication::SHA256_PASSWORD}; + user->authentication.setPasswordHashHex(config.getString(user_config + ".password_sha256_hex")); + } + else if (has_password_double_sha1_hex) + { + user->authentication = Authentication{Authentication::DOUBLE_SHA1_PASSWORD}; + user->authentication.setPasswordHashHex(config.getString(user_config + ".password_double_sha1_hex")); + } + + user->profile = config.getString(user_config + ".profile"); + + /// Fill list of allowed hosts. + const auto networks_config = user_config + ".networks"; + if (config.has(networks_config)) + { + Poco::Util::AbstractConfiguration::Keys keys; + config.keys(networks_config, keys); + for (const String & key : keys) + { + String value = config.getString(networks_config + "." + key); + if (key.starts_with("ip")) + user->allowed_client_hosts.addSubnet(value); + else if (key.starts_with("host_regexp")) + user->allowed_client_hosts.addHostRegexp(value); + else if (key.starts_with("host")) + user->allowed_client_hosts.addHostName(value); + else + throw Exception("Unknown address pattern type: " + key, ErrorCodes::UNKNOWN_ADDRESS_PATTERN_TYPE); + } + } + + /// Fill list of allowed databases. + const auto databases_config = user_config + ".allow_databases"; + std::optional databases; + if (config.has(databases_config)) + { + Poco::Util::AbstractConfiguration::Keys keys; + config.keys(databases_config, keys); + databases.emplace(); + databases->reserve(keys.size()); + for (const auto & key : keys) + { + const auto database_name = config.getString(databases_config + "." + key); + databases->push_back(database_name); + } + } + + /// Fill list of allowed dictionaries. + const auto dictionaries_config = user_config + ".allow_dictionaries"; + std::optional dictionaries; + if (config.has(dictionaries_config)) + { + Poco::Util::AbstractConfiguration::Keys keys; + config.keys(dictionaries_config, keys); + dictionaries.emplace(); + dictionaries->reserve(keys.size()); + for (const auto & key : keys) + { + const auto dictionary_name = config.getString(dictionaries_config + "." + key); + dictionaries->push_back(dictionary_name); + } + } + + user->access.grant(AccessType::ALL); /// By default all databases are accessible. + + if (databases) + { + user->access.fullRevoke(AccessFlags::databaseLevel()); + for (const String & database : *databases) + user->access.grant(AccessFlags::databaseLevel(), database); + user->access.grant(AccessFlags::databaseLevel(), "system"); /// Anyone has access to the "system" database. + } + + if (dictionaries) + { + user->access.fullRevoke(AccessType::dictGet, IDictionary::NO_DATABASE_TAG); + for (const String & dictionary : *dictionaries) + user->access.grant(AccessType::dictGet, IDictionary::NO_DATABASE_TAG, dictionary); + } + else if (databases) + user->access.grant(AccessType::dictGet, IDictionary::NO_DATABASE_TAG); + + return user; + } + + + std::vector parseUsers(const Poco::Util::AbstractConfiguration & config, Poco::Logger * log) + { + Poco::Util::AbstractConfiguration::Keys user_names; + config.keys("users", user_names); + + std::vector users; + users.reserve(user_names.size()); + for (const auto & user_name : user_names) + { + try + { + users.push_back(parseUser(config, user_name)); + } + catch (...) + { + tryLogCurrentException(log, "Could not parse user " + backQuote(user_name)); + } + } + return users; + } + + QuotaPtr parseQuota(const Poco::Util::AbstractConfiguration & config, const String & quota_name, const Strings & user_names) { auto quota = std::make_shared(); @@ -192,6 +336,8 @@ UsersConfigAccessStorage::~UsersConfigAccessStorage() {} void UsersConfigAccessStorage::loadFromConfig(const Poco::Util::AbstractConfiguration & config) { std::vector> all_entities; + for (const auto & entity : parseUsers(config, getLogger())) + all_entities.emplace_back(generateID(*entity), entity); for (const auto & entity : parseQuotas(config, getLogger())) all_entities.emplace_back(generateID(*entity), entity); for (const auto & entity : parseRowPolicies(config, getLogger())) @@ -250,13 +396,13 @@ void UsersConfigAccessStorage::updateImpl(const UUID & id, const UpdateFunc &) } -IAccessStorage::SubscriptionPtr UsersConfigAccessStorage::subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const +ext::scope_guard UsersConfigAccessStorage::subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const { return memory_storage.subscribeForChanges(id, handler); } -IAccessStorage::SubscriptionPtr UsersConfigAccessStorage::subscribeForChangesImpl(std::type_index type, const OnChangedHandler & handler) const +ext::scope_guard UsersConfigAccessStorage::subscribeForChangesImpl(std::type_index type, const OnChangedHandler & handler) const { return memory_storage.subscribeForChanges(type, handler); } diff --git a/dbms/src/Access/UsersConfigAccessStorage.h b/dbms/src/Access/UsersConfigAccessStorage.h index 9b0bf2ed17c..45b46c8c179 100644 --- a/dbms/src/Access/UsersConfigAccessStorage.h +++ b/dbms/src/Access/UsersConfigAccessStorage.h @@ -32,8 +32,8 @@ private: UUID insertImpl(const AccessEntityPtr & entity, bool replace_if_exists) override; void removeImpl(const UUID & id) override; void updateImpl(const UUID & id, const UpdateFunc & update_func) override; - SubscriptionPtr subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const override; - SubscriptionPtr subscribeForChangesImpl(std::type_index type, const OnChangedHandler & handler) const override; + ext::scope_guard subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const override; + ext::scope_guard subscribeForChangesImpl(std::type_index type, const OnChangedHandler & handler) const override; bool hasSubscriptionImpl(const UUID & id) const override; bool hasSubscriptionImpl(std::type_index type) const override; diff --git a/dbms/src/AggregateFunctions/AggregateFunctionSumMap.cpp b/dbms/src/AggregateFunctions/AggregateFunctionSumMap.cpp index cf5c8254887..41150799815 100644 --- a/dbms/src/AggregateFunctions/AggregateFunctionSumMap.cpp +++ b/dbms/src/AggregateFunctions/AggregateFunctionSumMap.cpp @@ -83,6 +83,8 @@ AggregateFunctionPtr createAggregateFunctionSumMap(const std::string & name, con AggregateFunctionPtr res(createWithNumericBasedType(*keys_type, keys_type, values_types, arguments)); if (!res) res.reset(createWithDecimalType(*keys_type, keys_type, values_types, arguments)); + if (!res) + res.reset(createWithStringType(*keys_type, keys_type, values_types, arguments)); if (!res) throw Exception("Illegal type of argument for aggregate function " + name, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); @@ -106,6 +108,8 @@ AggregateFunctionPtr createAggregateFunctionSumMapFiltered(const std::string & n AggregateFunctionPtr res(createWithNumericBasedType(*keys_type, keys_type, values_types, keys_to_keep, arguments, params)); if (!res) res.reset(createWithDecimalType(*keys_type, keys_type, values_types, keys_to_keep, arguments, params)); + if (!res) + res.reset(createWithStringType(*keys_type, keys_type, values_types, keys_to_keep, arguments, params)); if (!res) throw Exception("Illegal type of argument for aggregate function " + name, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); diff --git a/dbms/src/AggregateFunctions/AggregateFunctionSumMap.h b/dbms/src/AggregateFunctions/AggregateFunctionSumMap.h index c201e8e3370..9b1f164bdd2 100644 --- a/dbms/src/AggregateFunctions/AggregateFunctionSumMap.h +++ b/dbms/src/AggregateFunctions/AggregateFunctionSumMap.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -56,8 +57,6 @@ class AggregateFunctionSumMapBase : public IAggregateFunctionDataHelper< AggregateFunctionSumMapData>, Derived> { private: - using ColVecType = std::conditional_t, ColumnDecimal, ColumnVector>; - DataTypePtr keys_type; DataTypes values_types; @@ -84,9 +83,10 @@ public: void add(AggregateDataPtr place, const IColumn ** columns, const size_t row_num, Arena *) const override { // Column 0 contains array of keys of known type + Field key_field; const ColumnArray & array_column0 = assert_cast(*columns[0]); const IColumn::Offsets & offsets0 = array_column0.getOffsets(); - const auto & keys_vec = static_cast(array_column0.getData()); + const IColumn & key_column = array_column0.getData(); const size_t keys_vec_offset = offsets0[row_num - 1]; const size_t keys_vec_size = (offsets0[row_num] - keys_vec_offset); @@ -111,7 +111,8 @@ public: using IteratorType = typename MapType::iterator; array_column.getData().get(values_vec_offset + i, value); - const auto & key = keys_vec.getElement(keys_vec_offset + i); + key_column.get(keys_vec_offset + i, key_field); + auto && key = key_field.get(); if (!keepKey(key)) { @@ -121,7 +122,7 @@ public: IteratorType it; if constexpr (IsDecimalNumber) { - UInt32 scale = keys_vec.getData().getScale(); + UInt32 scale = static_cast &>(key_column).getData().getScale(); it = merged_maps.find(DecimalField(key, scale)); } else @@ -139,7 +140,7 @@ public: if constexpr (IsDecimalNumber) { - UInt32 scale = keys_vec.getData().getScale(); + UInt32 scale = static_cast &>(key_column).getData().getScale(); merged_maps.emplace(DecimalField(key, scale), std::move(new_values)); } else diff --git a/dbms/src/AggregateFunctions/Helpers.h b/dbms/src/AggregateFunctions/Helpers.h index 8d42654811a..6c03d25e0b1 100644 --- a/dbms/src/AggregateFunctions/Helpers.h +++ b/dbms/src/AggregateFunctions/Helpers.h @@ -149,4 +149,13 @@ static IAggregateFunction * createWithTwoNumericTypes(const IDataType & first_ty return nullptr; } +template