pot/merge.
[dcpomatic.git] / src / wx / config_dialog.cc
index 7d999e14bbe12b7c7f6a2ce503445e7e8c28d521..8dd6cab68503a7cdd4d7e1781a89585e8b594300 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
@@ -33,6 +33,7 @@
 #include "make_chain_dialog.h"
 #include "email_dialog.h"
 #include "name_format_editor.h"
+#include "nag_dialog.h"
 #include "lib/config.h"
 #include "lib/ratio.h"
 #include "lib/filter.h"
@@ -66,6 +67,13 @@ using boost::function;
 using boost::optional;
 using dcp::locale_convert;
 
+static
+void
+do_nothing ()
+{
+
+}
+
 class Page
 {
 public:
@@ -321,21 +329,25 @@ private:
                checked_set (_preview_sound, config->preview_sound());
 
                 optional<string> const current_so = get_preview_sound_output ();
-                string configured_so;
+                optional<string> configured_so;
 
                 if (config->preview_sound_output()) {
                         configured_so = config->preview_sound_output().get();
                 } else {
                         /* No configured output means we should use the default */
                         RtAudio audio (DCPOMATIC_RTAUDIO_API);
-                        configured_so = audio.getDeviceInfo(audio.getDefaultOutputDevice()).name;
+                       try {
+                               configured_so = audio.getDeviceInfo(audio.getDefaultOutputDevice()).name;
+                       } catch (RtAudioError& e) {
+                               /* Probably no audio devices at all */
+                       }
                 }
 
-                if (!current_so || *current_so != configured_so) {
+                if (configured_so && current_so != configured_so) {
                         /* Update _preview_sound_output with the configured value */
                         unsigned int i = 0;
                         while (i < _preview_sound_output->GetCount()) {
-                                if (_preview_sound_output->GetString(i) == std_to_wx(configured_so)) {
+                                if (_preview_sound_output->GetString(i) == std_to_wx(*configured_so)) {
                                         _preview_sound_output->SetSelection (i);
                                         break;
                                 }
@@ -565,24 +577,22 @@ private:
 
                _isdcf_metadata_button->Bind (wxEVT_BUTTON, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
 
-               vector<Ratio const *> ratios = Ratio::all ();
-               for (size_t i = 0; i < ratios.size(); ++i) {
-                       _container->Append (std_to_wx (ratios[i]->nickname ()));
+               BOOST_FOREACH (Ratio const * i, Ratio::containers()) {
+                       _container->Append (std_to_wx(i->container_nickname()));
                }
 
                _container->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::container_changed, this));
 
                _scale_to->Append (_("Guess from content"));
 
-               for (size_t i = 0; i < ratios.size(); ++i) {
-                       _scale_to->Append (std_to_wx (ratios[i]->nickname ()));
+               BOOST_FOREACH (Ratio const * i, Ratio::all()) {
+                       _scale_to->Append (std_to_wx(i->image_nickname()));
                }
 
                _scale_to->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::scale_to_changed, this));
 
-               vector<DCPContentType const *> const ct = DCPContentType::all ();
-               for (size_t i = 0; i < ct.size(); ++i) {
-                       _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
+               BOOST_FOREACH (DCPContentType const * i, DCPContentType::all()) {
+                       _dcp_content_type->Append (std_to_wx (i->pretty_name ()));
                }
 
                setup_audio_channels_choice (_dcp_audio_channels, 2);
@@ -793,11 +803,13 @@ public:
                wxString title,
                int border,
                function<void (shared_ptr<dcp::CertificateChain>)> set,
-               function<shared_ptr<const dcp::CertificateChain> (void)> get
+               function<shared_ptr<const dcp::CertificateChain> (void)> get,
+               function<void (void)> nag_remake
                )
                : wxPanel (parent)
                , _set (set)
                , _get (get)
+               , _nag_remake (nag_remake)
        {
                wxFont subheading_font (*wxNORMAL_FONT);
                subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
@@ -871,6 +883,13 @@ public:
                table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
                ++r;
 
+               _private_key_bad = new wxStaticText (this, wxID_ANY, _("Leaf private key does not match leaf certificate!"));
+               font = *wxSMALL_FONT;
+               font.SetWeight (wxFONTWEIGHT_BOLD);
+               _private_key_bad->SetFont (font);
+               table->Add (_private_key_bad, wxGBPosition (r, 0), wxGBSpan (1, 3));
+               ++r;
+
                _add_certificate->Bind     (wxEVT_BUTTON,       boost::bind (&CertificateChainEditor::add_certificate, this));
                _remove_certificate->Bind  (wxEVT_BUTTON,       boost::bind (&CertificateChainEditor::remove_certificate, this));
                _export_certificate->Bind  (wxEVT_BUTTON,       boost::bind (&CertificateChainEditor::export_certificate, this));
@@ -906,7 +925,15 @@ private:
                if (d->ShowModal() == wxID_OK) {
                        try {
                                dcp::Certificate c;
-                               string const extra = c.read_string (dcp::file_to_string (wx_to_std (d->GetPath ())));
+                               string extra;
+                               try {
+                                       extra = c.read_string (dcp::file_to_string (wx_to_std (d->GetPath ())));
+                               } catch (boost::filesystem::filesystem_error& e) {
+                                       error_dialog (this, wxString::Format (_("Could not load certificate (%s)"), d->GetPath().data()));
+                                       d->Destroy ();
+                                       return;
+                               }
+
                                if (!extra.empty ()) {
                                        message_dialog (
                                                this,
@@ -915,8 +942,17 @@ private:
                                                );
                                }
                                _chain->add (c);
-                               _set (_chain);
-                               update_certificate_list ();
+                               if (!_chain->chain_valid ()) {
+                                       error_dialog (
+                                               this,
+                                               _("Adding this certificate would make the chain inconsistent, so it will not be added. "
+                                                 "Add certificates in order from root to intermediate to leaf.")
+                                               );
+                                       _chain->remove (c);
+                               } else {
+                                       _set (_chain);
+                                       update_certificate_list ();
+                               }
                        } catch (dcp::MiscError& e) {
                                error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
                        }
@@ -993,6 +1029,16 @@ private:
 
                        ++n;
                }
+
+               static wxColour normal = _private_key_bad->GetForegroundColour ();
+
+               if (_chain->private_key_valid ()) {
+                       _private_key_bad->Hide ();
+                       _private_key_bad->SetForegroundColour (normal);
+               } else {
+                       _private_key_bad->Show ();
+                       _private_key_bad->SetForegroundColour (wxColour (255, 0, 0));
+               }
        }
 
        void remake_certificates ()
@@ -1026,6 +1072,8 @@ private:
                        intermediate_common_name = i->subject_common_name ();
                }
 
+               _nag_remake ();
+
                MakeChainDialog* d = new MakeChainDialog (
                        this,
                        subject_organization_name,
@@ -1057,7 +1105,8 @@ private:
 
        void update_sensitivity ()
        {
-               _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
+               /* We can only remove the leaf certificate */
+               _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) == (_certificates->GetItemCount() - 1));
                _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
        }
 
@@ -1128,11 +1177,13 @@ private:
        wxStaticText* _private_key;
        wxButton* _load_private_key;
        wxButton* _export_private_key;
+       wxStaticText* _private_key_bad;
        wxSizer* _sizer;
        wxBoxSizer* _button_sizer;
        shared_ptr<dcp::CertificateChain> _chain;
        boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
        boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
+       boost::function<void (void)> _nag_remake;
 };
 
 class KeysPage : public StandardPage
@@ -1161,7 +1212,8 @@ private:
                _signer = new CertificateChainEditor (
                        _panel, _("Signing DCPs and KDMs"), _border,
                        boost::bind (&Config::set_signer_chain, Config::instance (), _1),
-                       boost::bind (&Config::signer_chain, Config::instance ())
+                       boost::bind (&Config::signer_chain, Config::instance ()),
+                       boost::bind (&do_nothing)
                        );
 
                _panel->GetSizer()->Add (_signer);
@@ -1169,7 +1221,8 @@ private:
                _decryption = new CertificateChainEditor (
                        _panel, _("Decrypting KDMs"), _border,
                        boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
-                       boost::bind (&Config::decryption_chain, Config::instance ())
+                       boost::bind (&Config::decryption_chain, Config::instance ()),
+                       boost::bind (&KeysPage::nag_remake_decryption_chain, this)
                        );
 
                _panel->GetSizer()->Add (_decryption);
@@ -1229,6 +1282,15 @@ private:
                _decryption->config_changed ();
        }
 
+       void nag_remake_decryption_chain ()
+       {
+               NagDialog::maybe_nag (
+                       _panel,
+                       Config::NAG_REMAKE_DECRYPTION_CHAIN,
+                       _("If you continue with this operation you will no longer be able to use any DKDMs that you have created.  Also, any KDMs that have been sent to you will become useless.  Proceed with caution!")
+                       );
+       }
+
        CertificateChainEditor* _signer;
        CertificateChainEditor* _decryption;
        wxButton* _export_decryption_certificate;