Repository: conan-io/conan-center-index

Issue:
[package] cpr/1.5.2: Add option for `USE_WINSSL`
<!-- 
  Please don't forget to update the issue title.
  Include all applicable information to help us reproduce your problem.
-->

### Package and Environment Details (include every applicable attribute)
  * Package Name/Version: **cpr/1.5.2**
  * Operating System+version: **Windows 10**
  * Compiler+version: **MSVC 16**
  * Conan version: **conan 1.32**
  * Python version: **Python 3.9.0**


### Conan profile (output of `conan profile show default` or `conan profile show <profile>` if custom profile is in use)
```
[settings]
arch=x86
arch_build=x86
build_type=Release
compiler=Visual Studio
compiler.runtime=MDd
compiler.version=16
os=Windows
os_build=Windows
[options]
[build_requires]
[env]
```

### Steps to reproduce (Include if Applicable)
Just running the example from the CPR readme.
```
#include <cpr/cpr.h>

int main(int argc, char** argv) {
    cpr::Response r = cpr::Get(cpr::Url{"https://api.github.com/repos/whoshuu/cpr/contributors"},
                      cpr::Authentication{"user", "pass"},
                      cpr::Parameters{{"anon", "true"}, {"key", "value"}});
    r.status_code;                  // 200
    r.header["content-type"];       // application/json; charset=utf-8
    r.text;                         // JSON text string
}
```

returned result contains error "SSL certificate problem: unable to get local issuer certificate"  
[Related issue in CPR](https://github.com/whoshuu/cpr/issues/485)


### Suggested Fix
To options add `with_winssl` as a mutually exclusive option next to `with_openssl`  
enable that option later with `cmake.definitions["CMAKE_USE_WINSSL"] = self.options.with_winssl`

Fix CURL ssl option for CPR recipe
Specify library name and version:  **cpr/1.3.0**

fixes #3206

/cc @FohlenAFK

- [ ] I've read the [guidelines](https://github.com/conan-io/conan-center-index/blob/master/docs/how_to_add_packages.md) for contributing.
- [ ] I've followed the [PEP8](https://www.python.org/dev/peps/pep-0008/) style guides for Python code in the recipes.
- [ ] I've used the [latest](https://github.com/conan-io/conan/releases/latest) Conan client version.
- [ ] I've tried at least one configuration locally with the
      [conan-center hook](https://github.com/conan-io/hooks.git) activated.

CPR is no longer compatible with libcurl

The CPR package is no longer compatible with the libcurl package because the following changes: 27c119a06fc0303efa89c2d8cbbace35f32db1b6

Building CPR e.g 1.4.0 fails on this line: https://github.com/conan-io/conan-center-index/blob/7fafb4675b4af4a9af227fdb3f9d660e044a2a0a/recipes/cpr/all/conanfile.py#L39 with

```
$ conan install .. cpr/1.4.0
Configuration:
[settings]
arch=x86_64
arch_build=x86_64
build_type=Release
compiler=clang
compiler.libcxx=libc++
compiler.version=10
os=Macos
os_build=Macos
[options]
[build_requires]
[env]
libcurl/7.71.1: WARN: with_openssl, with_winssl, darwin_ssl and with_wolfssl options are deprecated. Use with_ssl option instead.
cpr/1.4.0: WARN: OpenSSL support is not stable yet. whoshuu/cpr#31
WARN: cpr/1.4.0: requirement libcurl/7.67.0 overridden by your conanfile to libcurl/7.71.1
ERROR: option 'with_openssl' doesn't exist
Possible options are ['shared', 'fPIC', 'with_ssl', 'with_ldap', 'with_libssh2', 'with_libidn', 'with_librtmp', 'with_libmetalink', 'with_libpsl', 'with_largemaxwritesize', 'with_nghttp2', 'with_zlib', 'with_brotli']
```

because the option on this line is deleted:

https://github.com/conan-io/conan-center-index/blob/7fafb4675b4af4a9af227fdb3f9d660e044a2a0a/recipes/libcurl/all/conanfile.py#L125


Discussion:

Failure in build 2 (`f20cf6ac63c05c275a95f9609c31a37c1902d6b0`):
-   **Error processing recipe (ref 'cpr/1.4.0'): Windows x86_64, Debug, Visual Studio 15,  MTd. Options:  cpr:shared-True**
Unexpected error happened: 


```
cpr/1.4.0: WARN: OpenSSL support is not stable yet. whoshuu/cpr#31
libcurl/7.67.0: WARN: with_openssl, with_winssl, darwin_ssl and with_wolfssl options are deprecated. Use with_ssl option instead.
openssl/1.1.1g: ERROR: Error downloading binary package: 'openssl/1.1.1g:963bb116781855de98dbb23aaac41621e5d312d8'
ERROR: 503: Service Temporarily Unavailable. [Remote: central]

```

All green in build 3 (`f20cf6ac63c05c275a95f9609c31a37c1902d6b0`)! :blush:
- `cpr/1.3.0`: Generated 124 packages (+ 12 invalid config from `build()`). [All logs here](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/3/cpr/1.3.0/) 
- `cpr/1.4.0`: Generated 124 packages (+ 12 invalid config from `build()`). [All logs here](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/3/cpr/1.4.0/) 
- `cpr/1.5.0`: Generated 124 packages (+ 12 invalid config from `build()`). [All logs here](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/3/cpr/1.5.0/) 

After looking a little bit cpr source code and build files, I'm wondering if this option `with_openssl` makes sense. It doesn't change cpr binaries nor interface definitions. it's just a redundant option trying to control libcurl option.
> After looking a little bit cpr source code and build files, I'm wondering if this option `with_openssl` makes sense. It doesn't change cpr binaries nor interface definitions. it's just a redundant option trying to control libcurl option.

I vote for removing
> I vote for removing

Same,
@SpaceIm Thanks for checking this
Some configurations of 'cpr/1.3.0' failed in build 5 (`9aef944dee975d2ed709585396f6c86860f71a0e`):
-   **Macos x86_64, Release, apple-clang 11.0, libc++ . Options:  cpr:shared-False**
    - [Log download](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/b40e446798f18a5008bdd52070b13b12750a9126/create_stdout.txt)
    - [Log error Download](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/b40e446798f18a5008bdd52070b13b12750a9126/create_stderr.txt)
    - [Profile](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/b40e446798f18a5008bdd52070b13b12750a9126/profile.txt)
- [Access to all the logs](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/)
-   **Macos x86_64, Debug, apple-clang 10.0, libc++ . Options:  cpr:shared-False**
    - [Log download](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/654df92126b86965d08c481786f1e4db0f59fa60/create_stdout.txt)
    - [Log error Download](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/654df92126b86965d08c481786f1e4db0f59fa60/create_stderr.txt)
    - [Profile](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/654df92126b86965d08c481786f1e4db0f59fa60/profile.txt)
- [Access to all the logs](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/)
-   **Macos x86_64, Debug, apple-clang 11.0, libc++ . Options:  cpr:shared-False**
    - [Log download](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/9d99d0014387ffd571457024ce42a409c7b75eb7/create_stdout.txt)
    - [Log error Download](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/9d99d0014387ffd571457024ce42a409c7b75eb7/create_stderr.txt)
    - [Profile](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/9d99d0014387ffd571457024ce42a409c7b75eb7/profile.txt)
- [Access to all the logs](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/)
-   **Macos x86_64, Release, apple-clang 10.0, libc++ . Options:  cpr:shared-False**
    - [Log download](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/ed2427e620946c29c54ffd059bed68131ed0a8e2/create_stdout.txt)
    - [Log error Download](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/ed2427e620946c29c54ffd059bed68131ed0a8e2/create_stderr.txt)
    - [Profile](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/ed2427e620946c29c54ffd059bed68131ed0a8e2/profile.txt)
- [Access to all the logs](https://c3i.jfrog.io/c3i/misc/logs/pr/3207/5/cpr/1.3.0/)
Could you provide more information? conan version? What is your conanfile? I guess that it fails only if libcurl is also a direct dependency in your own conanfile.

Maybe deprecated options should be removed in package_id, not configure.

Resolving patch:
diff --git a/recipes/cpr/all/conanfile.py b/recipes/cpr/all/conanfile.py
--- a/recipes/cpr/all/conanfile.py
+++ b/recipes/cpr/all/conanfile.py
@@ -1,5 +1,4 @@
 from conans import ConanFile, CMake, tools
-from conans.tools import Version
 from conans.errors import ConanInvalidConfiguration
 import os
 
@@ -18,14 +17,36 @@ class CprConan(ConanFile):
         "shared": [True, False],
         "fPIC": [True, False],
         "with_openssl": [True, False],
+        "with_winssl": [True, False],
     }
     default_options = {
         "shared": False,
         "fPIC": True,
         "with_openssl": True,
+        "with_winssl": False,
     }
-    _source_subfolder = "source_subfolder"
-    _build_subfolder = "build_subfolder"
+
+    _cmake = None
+
+    @property
+    def _source_subfolder(self):
+        return "source_subfolder"
+
+    @property
+    def _build_subfolder(self):
+        return "build_subfolder"
+
+    @property
+    def _supports_openssl(self):
+        # https://github.com/whoshuu/cpr/commit/b036a3279ba62720d1e43362d32202bf412ea152
+        # https://github.com/whoshuu/cpr/releases/tag/1.5.0
+        return tools.Version(self.version) >= "1.5.0"
+
+    @property
+    def _supports_winssl(self):
+        # https://github.com/whoshuu/cpr/commit/18e1fc5c3fc0ffc07695f1d78897fb69e7474ea9
+        # https://github.com/whoshuu/cpr/releases/tag/1.5.1
+        return tools.Version(self.version) >= "1.5.1"
 
     def config_options(self):
         if self.settings.os == "Windows":
@@ -34,38 +55,64 @@ def config_options(self):
     def configure(self):
         if self.options.shared:
             del self.options.fPIC
+        if not self._supports_openssl:
+            del self.options.with_openssl
+        if not self._supports_winssl:
+            del self.options.with_winssl
+
+        if self._supports_openssl and tools.is_apple_os(self.settings.os):
+            self.options.with_openssl = False # Default libcurl in CCI is `with_ssl="darwin"` which is unclear if cpr supports this
+            
+        # Make sure libcurl uses the same SSL implementation
+        if self.options.get_safe("with_openssl", False):
+            # self.options["libcurl"].with_openssl = True # deprecated in https://github.com/conan-io/conan-center-index/pull/2880
+            self.options["libcurl"].with_ssl = "openssl"
+        if self.options.get_safe("with_winssl", False):
+            # self.options["libcurl"].with_winssl = True # deprecated in https://github.com/conan-io/conan-center-index/pull/2880
+            self.options["libcurl"].with_ssl = "schannel"
+
+        if self.options.get_safe("with_winssl", False) and self.settings.os != "Windows":
+            raise ConanInvalidConfiguration("cpr only supports winssl on Windows")
+
+        if self.options.get_safe("with_openssl", False) and self.options.get_safe("with_winssl", False):
+            raise ConanInvalidConfiguration("cpr can not be built with both openssl and winssl")
+            
+        if self.settings.compiler == "Visual Studio" and self.options.shared and "MT" in self.settings.compiler.runtime:
+            raise ConanInvalidConfiguration("Visual Studio build for shared library with MT runtime is not supported")
 
     def source(self):
         tools.get(**self.conan_data["sources"][self.version])
         os.rename("cpr-{}".format(self.version), self._source_subfolder)
 
     def requirements(self):
-        if Version(self.version) < "1.5.0":
-            self.requires("libcurl/7.67.0")
-        else:
-            self.requires("libcurl/7.69.1")
-        if self.options.with_openssl:
-            self.output.warn("OpenSSL support is not stable yet. whoshuu/cpr#31")
+        self.requires("libcurl/{}".format("7.67.0" if not self._supports_openssl else "7.69.1"))
 
     def _patch_sources(self):
-        for patch in self.conan_data["patches"][self.version]:
+        for patch in self.conan_data.get("patches", {}).get(self.version, []):
             tools.patch(**patch)
 
     def _configure_cmake(self):
-        cmake = CMake(self)
-        cmake.definitions["USE_SYSTEM_CURL"] = True
-        cmake.definitions["BUILD_CPR_TESTS"] = False
-        cmake.definitions["GENERATE_COVERAGE"] = False
-        cmake.definitions["USE_SYSTEM_GTEST"] = False
-        cmake.definitions["CMAKE_USE_OPENSSL"] = self.options.with_openssl
-        if self.settings.os == "Windows" and self.settings.compiler == "Visual Studio" and self.options.shared:
-            cmake.definitions["CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS"] = True
-        cmake.configure(build_folder=self._build_subfolder)
-        return cmake
+        if not self._cmake:
+            self._cmake = CMake(self)
+            self._cmake.definitions["USE_SYSTEM_CURL"] = True
+            self._cmake.definitions["BUILD_CPR_TESTS"] = False
+            self._cmake.definitions["GENERATE_COVERAGE"] = False
+            self._cmake.definitions["USE_SYSTEM_GTEST"] = False
+            if self._supports_openssl:
+                self._cmake.definitions["CMAKE_USE_OPENSSL"] = self.options.get_safe("with_openssl", False)
+            if self._supports_winssl: # The CMake options changed
+                # https://github.com/whoshuu/cpr/commit/18e1fc5c3fc0ffc07695f1d78897fb69e7474ea9#diff-1e7de1ae2d059d21e1dd75d5812d5a34b0222cef273b7c3a2af62eb747f9d20aR39-R40
+                self._cmake.definitions["USE_OPENSSL"] = self.options.get_safe("with_openssl", False)
+                self._cmake.definitions["USE_WINSSL"] = self.options.get_safe("with_winssl", False)
+            self._cmake.configure(build_folder=self._build_subfolder)
+        return self._cmake
 
     def build(self):
-        if self.options.with_openssl and self.options["libcurl"].with_ssl != "openssl":
-            raise ConanInvalidConfiguration("cpr requires libcurl to be built with the option with_ssl=\"openssl\".")
+        if self.options.get_safe("with_openssl", False) and self.options["libcurl"].with_ssl != "openssl":
+            raise ConanInvalidConfiguration("cpr requires libcurl to be built with the option with_ssl='openssl'.")
+        if self.options.get_safe("with_winssl", False) and self.options["libcurl"].with_ssl != "openssl":
+            raise ConanInvalidConfiguration("cpr requires libcurl to be built with the option with_ssl='schannel'.")
+
         self._patch_sources()
         cmake = self._configure_cmake()
         cmake.build()


Test patch:
diff --git a/recipes/cpr/all/test_package/test_package.cpp b/recipes/cpr/all/test_package/test_package.cpp
--- a/recipes/cpr/all/test_package/test_package.cpp
+++ b/recipes/cpr/all/test_package/test_package.cpp
@@ -3,7 +3,7 @@
 #include <iostream>
 
 int main(int argc, char** argv) {
-    auto r = cpr::Get(cpr::Url{"https://jsonplaceholder.typicode.com/todos/1"},
+    auto r = cpr::Get(cpr::Url{"http://jsonplaceholder.typicode.com/todos/1"}, // https available after 1.5.0 (not windows by default)
         cpr::Parameters{{"Accept", "application/json"}});
     std::cout << "status code: " << r.status_code << '\n';                  // 200
     std::cout << "headers:     " << r.header["content-type"] << '\n';       // application/json; charset=utf-8