From 611a2434479fe0a9b20426eeb323ce15d94f506c Mon Sep 17 00:00:00 2001
From: tamasmeszaros <meszaros.q@gmail.com>
Date: Wed, 22 Apr 2020 17:14:09 +0200
Subject: [PATCH] Add question box on PrusaSlicer start to accept detected CA
 store..

Fix compile
---
 src/slic3r/GUI/GUI_App.cpp | 32 ++++++++++++++++---
 src/slic3r/Utils/Http.cpp  | 65 ++++++++++++++++++++++++++++++--------
 src/slic3r/Utils/Http.hpp  |  4 +++
 3 files changed, 83 insertions(+), 18 deletions(-)

diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index 794226520..aee71f16e 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -24,6 +24,7 @@
 #include <wx/filefn.h>
 #include <wx/sysopt.h>
 #include <wx/msgdlg.h>
+#include <wx/richmsgdlg.h>
 #include <wx/log.h>
 #include <wx/intl.h>
 
@@ -321,20 +322,41 @@ bool GUI_App::on_init_inner()
         set_data_dir(wxStandardPaths::Get().GetUserDataDir().ToUTF8().data());
 
     app_config = new AppConfig();
-    preset_bundle = new PresetBundle();
-
-    // just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory
-    // supplied as argument to --datadir; in that case we should still run the wizard
-    preset_bundle->setup_directories();
 
     // load settings
     app_conf_exists = app_config->exists();
     if (app_conf_exists) {
         app_config->load();
     }
+    
+    std::string msg = Http::tls_global_init();
+    wxRichMessageDialog
+        dlg(nullptr,
+            wxString::Format(_(L("%s\nDo you want to continue?")), _(msg)),
+            "PrusaSlicer", wxICON_QUESTION | wxYES_NO);
+    
+    bool ssl_accept = app_config->get("tls_cert_store_accepted") == "yes";
+    std::string ssl_cert_store = app_config->get("tls_accepted_cert_store_location");
+    ssl_accept = ssl_accept && ssl_cert_store == Http::tls_system_cert_store();
+    
+    dlg.ShowCheckBox(_(L("Remember my choice")));
+    if (!msg.empty() && !ssl_accept) {
+        if (dlg.ShowModal() != wxID_YES) return false;
 
+        app_config->set("tls_cert_store_accepted",
+                        dlg.IsCheckBoxChecked() ? "yes" : "no");
+        app_config->set("tls_accepted_cert_store_location",
+                        dlg.IsCheckBoxChecked() ? Http::tls_system_cert_store() : "");
+    }
+    
     app_config->set("version", SLIC3R_VERSION);
     app_config->save();
+    
+    preset_bundle = new PresetBundle();
+    
+    // just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory
+    // supplied as argument to --datadir; in that case we should still run the wizard
+    preset_bundle->setup_directories();
 
 #ifdef __WXMSW__
     associate_3mf_files();
diff --git a/src/slic3r/Utils/Http.cpp b/src/slic3r/Utils/Http.cpp
index 30e25abe2..101654c56 100644
--- a/src/slic3r/Utils/Http.cpp
+++ b/src/slic3r/Utils/Http.cpp
@@ -18,6 +18,8 @@
 #include <openssl/x509.h>
 #endif
 
+#define L(s) s
+
 #include "libslic3r/libslic3r.h"
 #include "libslic3r/Utils.hpp"
 
@@ -32,7 +34,8 @@ namespace Slic3r {
 struct CurlGlobalInit
 {
     static std::unique_ptr<CurlGlobalInit> instance;
-
+    std::string message;
+    
 	CurlGlobalInit()
     {
 #ifdef OPENSSL_CERT_OVERRIDE // defined if SLIC3R_STATIC=ON
@@ -57,21 +60,39 @@ struct CurlGlobalInit
             ssl_cafile = X509_get_default_cert_file();
         
         int replace = true;
-        
-        if (!ssl_cafile || !fs::exists(fs::path(ssl_cafile)))
-            for (const char * bundle : CA_BUNDLES) {
-                if (fs::exists(fs::path(bundle))) {
-                    ::setenv(SSL_CA_FILE, bundle, replace);
+        if (!ssl_cafile || !fs::exists(fs::path(ssl_cafile))) {
+            const char * bundle = nullptr;
+            for (const char * b : CA_BUNDLES) {
+                if (fs::exists(fs::path(b))) {
+                    ::setenv(SSL_CA_FILE, bundle = b, replace);
                     break;
                 }
             }
 
-        BOOST_LOG_TRIVIAL(info)
-            << "Detected OpenSSL root CA store: " << ::getenv(SSL_CA_FILE);
+            if (!bundle)
+                message = L("Could not detect system SSL certificate store. "
+                            "PrusaSlicer will be unable to establish secure "
+                            "network connections.");
+            else
+                message = string_printf(
+                    L("PrusaSlicer detected system SSL certificate store in: %s"),
+                    bundle);
 
-#endif
+            message += string_printf(
+                L("\nTo specify the system certificate store manually, please "
+                  "set the %s environment variable to the correct CA bundle "
+                  "and restart the application."),
+                SSL_CA_FILE);
+        }
+
+#endif // OPENSSL_CERT_OVERRIDE
         
-        ::curl_global_init(CURL_GLOBAL_DEFAULT);
+        if (CURLcode ec = ::curl_global_init(CURL_GLOBAL_DEFAULT)) {
+            message = L("CURL init has failed. PrusaSlicer will be unable to establish "
+                        "network connections. See logs for additional details.");
+            
+            BOOST_LOG_TRIVIAL(error) << ::curl_easy_strerror(ec);
+        }
     }
     
 	~CurlGlobalInit() { ::curl_global_cleanup(); }
@@ -132,8 +153,7 @@ Http::priv::priv(const std::string &url)
 	, limit(0)
 	, cancel(false)
 {
-    if (!CurlGlobalInit::instance)
-        CurlGlobalInit::instance = std::make_unique<CurlGlobalInit>();
+    Http::tls_global_init();
     
 	if (curl == nullptr) {
 		throw std::runtime_error(std::string("Could not construct Curl object"));
@@ -494,7 +514,26 @@ bool Http::ca_file_supported()
 	::CURL *curl = ::curl_easy_init();
 	bool res = priv::ca_file_supported(curl);
 	if (curl != nullptr) { ::curl_easy_cleanup(curl); }
-	return res;
+    return res;
+}
+
+std::string Http::tls_global_init()
+{
+    if (!CurlGlobalInit::instance)
+        CurlGlobalInit::instance = std::make_unique<CurlGlobalInit>();
+    
+    return CurlGlobalInit::instance->message;
+}
+
+std::string Http::tls_system_cert_store()
+{
+    std::string ret;
+
+#ifdef OPENSSL_CERT_OVERRIDE
+    ret = ::getenv(X509_get_default_cert_file_env());
+#endif
+    
+    return ret;
 }
 
 std::string Http::url_encode(const std::string &str)
diff --git a/src/slic3r/Utils/Http.hpp b/src/slic3r/Utils/Http.hpp
index 076fa4a0c..f16236279 100644
--- a/src/slic3r/Utils/Http.hpp
+++ b/src/slic3r/Utils/Http.hpp
@@ -100,6 +100,10 @@ public:
 
 	// Tells whether current backend supports seting up a CA file using ca_file()
 	static bool ca_file_supported();
+    
+    // Return empty string on success or error message on fail.
+    static std::string tls_global_init();
+    static std::string tls_system_cert_store();
 
 	// converts the given string to an url_encoded_string
 	static std::string url_encode(const std::string &str);