Use more ScopeGuards.
[dcpomatic.git] / src / wx / config_dialog.cc
index d9563f1b670c2620e425b6f28f8850326b621329..bf7e295ee3c809ba14060c223d5a18d51654cbf2 100644 (file)
 
 */
 
-#include "config_dialog.h"
-#include "static_text.h"
+
+#include "audio_mapping_view.h"
 #include "check_box.h"
-#include "nag_dialog.h"
+#include "config_dialog.h"
 #include "dcpomatic_button.h"
-#include "audio_mapping_view.h"
+#include "nag_dialog.h"
+#include "static_text.h"
+#include "lib/constants.h"
+#include <dcp/file.h>
 #include <dcp/raw_convert.h>
-#include <iostream>
 
-using std::string;
-using std::vector;
-using std::pair;
+
+using std::function;
 using std::make_pair;
-using std::map;
 using std::make_shared;
+using std::map;
+using std::pair;
+using std::shared_ptr;
+using std::string;
+using std::vector;
 using boost::bind;
 using boost::optional;
-using std::shared_ptr;
-using boost::function;
 #if BOOST_VERSION >= 106100
 using namespace boost::placeholders;
 #endif
 
+
 static
 bool
 do_nothing ()
@@ -131,9 +135,11 @@ GeneralPage::add_language_controls (wxGridBagSizer* table, int& r)
        languages.push_back (make_pair("Português europeu", "pt_PT"));
        languages.push_back (make_pair("Português do Brasil", "pt_BR"));
        languages.push_back (make_pair("Svenska", "sv_SE"));
+       languages.push_back (make_pair("Slovenščina", "sl_SI"));
        languages.push_back (make_pair("Slovenský jazyk", "sk_SK"));
-       languages.push_back (make_pair("Türkçe", "tr_TR"));
+       // languages.push_back (make_pair("Türkçe", "tr_TR"));
        languages.push_back (make_pair("українська мова", "uk_UA"));
+       languages.push_back (make_pair("Magyar nyelv", "hu_HU"));
        checked_set (_language, languages);
        table->Add (_language, wxGBPosition (r, 1));
        ++r;
@@ -147,7 +153,7 @@ GeneralPage::add_language_controls (wxGridBagSizer* table, int& r)
        restart->SetFont (font);
        ++r;
 
-       _set_language->Bind (wxEVT_CHECKBOX, bind (&GeneralPage::set_language_changed, this));
+       _set_language->bind(&GeneralPage::set_language_changed, this);
        _language->Bind     (wxEVT_CHOICE,   bind (&GeneralPage::language_changed,     this));
 }
 
@@ -162,8 +168,8 @@ GeneralPage::add_update_controls (wxGridBagSizer* table, int& r)
        table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
        ++r;
 
-       _check_for_updates->Bind (wxEVT_CHECKBOX, bind (&GeneralPage::check_for_updates_changed, this));
-       _check_for_test_updates->Bind (wxEVT_CHECKBOX, bind (&GeneralPage::check_for_test_updates_changed, this));
+       _check_for_updates->bind(&GeneralPage::check_for_updates_changed, this);
+       _check_for_test_updates->bind(&GeneralPage::check_for_test_updates_changed, this);
 }
 
 void
@@ -362,6 +368,7 @@ void
 CertificateChainEditor::add_certificate ()
 {
        auto d = new wxFileDialog (this, _("Select Certificate File"));
+       ScopeGuard sg = [d]() { d->Destroy(); };
 
        if (d->ShowModal() == wxID_OK) {
                try {
@@ -371,7 +378,6 @@ CertificateChainEditor::add_certificate ()
                                extra = c.read_string (dcp::file_to_string (wx_to_std (d->GetPath ())));
                        } catch (boost::filesystem::filesystem_error& e) {
                                error_dialog (this, _("Could not import certificate (%s)"), d->GetPath());
-                               d->Destroy ();
                                return;
                        }
 
@@ -400,8 +406,6 @@ CertificateChainEditor::add_certificate ()
                }
        }
 
-       d->Destroy ();
-
        update_sensitivity ();
 }
 
@@ -450,53 +454,54 @@ CertificateChainEditor::export_certificate ()
                this, _("Select Certificate File"), wxEmptyString, default_name, wxT ("PEM files (*.pem)|*.pem"),
                wxFD_SAVE | wxFD_OVERWRITE_PROMPT
                );
+       ScopeGuard sg = [d]() { d->Destroy(); };
 
        auto j = all.begin ();
        for (int k = 0; k < i; ++k) {
                ++j;
        }
 
-       if (d->ShowModal () == wxID_OK) {
-               boost::filesystem::path path (wx_to_std(d->GetPath()));
-               if (path.extension() != ".pem") {
-                       path += ".pem";
-               }
-               auto f = fopen_boost (path, "w");
-               if (!f) {
-                       throw OpenFileError (path, errno, OpenFileError::WRITE);
-               }
+       if (d->ShowModal() != wxID_OK) {
+               return;
+       }
 
-               string const s = j->certificate (true);
-               checked_fwrite (s.c_str(), s.length(), f, path);
-               fclose (f);
+       boost::filesystem::path path(wx_to_std(d->GetPath()));
+       if (path.extension() != ".pem") {
+               path += ".pem";
+       }
+       dcp::File f(path, "w");
+       if (!f) {
+               throw OpenFileError(path, errno, OpenFileError::WRITE);
        }
-       d->Destroy ();
+
+       string const s = j->certificate(true);
+       f.checked_write(s.c_str(), s.length());
 }
 
 void
 CertificateChainEditor::export_chain ()
 {
        auto d = new wxFileDialog (
-               this, _("Select Chain File"), wxEmptyString, _("certificate_chain.pem"), wxT("PEM files (*.pem)|*.pem"),
+               this, _("Select Chain File"), wxEmptyString, wxT("certificate_chain.pem"), wxT("PEM files (*.pem)|*.pem"),
                wxFD_SAVE | wxFD_OVERWRITE_PROMPT
                );
+       ScopeGuard sg = [d]() { d->Destroy(); };
 
-       if (d->ShowModal () == wxID_OK) {
-               boost::filesystem::path path (wx_to_std(d->GetPath()));
-               if (path.extension() != ".pem") {
-                       path += ".pem";
-               }
-               auto f = fopen_boost (path, "w");
-               if (!f) {
-                       throw OpenFileError (path, errno, OpenFileError::WRITE);
-               }
+       if (d->ShowModal() != wxID_OK) {
+               return;
+       }
 
-               auto const s = _get()->chain();
-               checked_fwrite (s.c_str(), s.length(), f, path);
-               fclose (f);
+       boost::filesystem::path path(wx_to_std(d->GetPath()));
+       if (path.extension() != ".pem") {
+               path += ".pem";
+       }
+       dcp::File f(path, "w");
+       if (!f) {
+               throw OpenFileError(path, errno, OpenFileError::WRITE);
        }
 
-       d->Destroy ();
+       auto const s = _get()->chain();
+       f.checked_write(s.c_str(), s.length());
 }
 
 void
@@ -536,66 +541,19 @@ CertificateChainEditor::update_certificate_list ()
 void
 CertificateChainEditor::remake_certificates ()
 {
-       auto chain = _get();
-
-       string subject_organization_name;
-       string subject_organizational_unit_name;
-       string root_common_name;
-       string intermediate_common_name;
-       string leaf_common_name;
-
-       auto all = chain->root_to_leaf ();
-
-       if (all.size() >= 1) {
-               /* Have a root */
-               subject_organization_name = chain->root().subject_organization_name ();
-               subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
-               root_common_name = chain->root().subject_common_name ();
-       }
-
-       if (all.size() >= 2) {
-               /* Have a leaf */
-               leaf_common_name = chain->leaf().subject_common_name ();
-       }
-
-       if (all.size() >= 3) {
-               /* Have an intermediate */
-               dcp::CertificateChain::List::iterator i = all.begin ();
-               ++i;
-               intermediate_common_name = i->subject_common_name ();
-       }
-
        if (_nag_alter()) {
                /* Cancel was clicked */
                return;
        }
 
-       auto d = new MakeChainDialog (
-               this,
-               subject_organization_name,
-               subject_organizational_unit_name,
-               root_common_name,
-               intermediate_common_name,
-               leaf_common_name
-               );
+       auto d = new MakeChainDialog (this, _get());
+       ScopeGuard sg = [d]() { d->Destroy(); };
 
        if (d->ShowModal () == wxID_OK) {
-               _set (
-                       make_shared<dcp::CertificateChain> (
-                               openssl_path (),
-                               d->organisation (),
-                               d->organisational_unit (),
-                               d->root_common_name (),
-                               d->intermediate_common_name (),
-                               d->leaf_common_name ()
-                               )
-                       );
-
+               _set (d->get());
                update_certificate_list ();
                update_private_key ();
        }
-
-       d->Destroy ();
 }
 
 void
@@ -617,6 +575,7 @@ void
 CertificateChainEditor::import_private_key ()
 {
        auto d = new wxFileDialog (this, _("Select Key File"));
+       ScopeGuard sg = [d]() { d->Destroy(); };
 
        if (d->ShowModal() == wxID_OK) {
                try {
@@ -633,13 +592,11 @@ CertificateChainEditor::import_private_key ()
                        chain->set_key (dcp::file_to_string (p));
                        _set (chain);
                        update_private_key ();
-               } catch (dcp::MiscError& e) {
+               } catch (std::exception& e) {
                        error_dialog (this, _("Could not read certificate file."), std_to_wx(e.what()));
                }
        }
 
-       d->Destroy ();
-
        update_sensitivity ();
 }
 
@@ -652,25 +609,24 @@ CertificateChainEditor::export_private_key ()
        }
 
        auto d = new wxFileDialog (
-               this, _("Select Key File"), wxEmptyString, _("private_key.pem"), wxT ("PEM files (*.pem)|*.pem"),
+               this, _("Select Key File"), wxEmptyString, wxT("private_key.pem"), wxT("PEM files (*.pem)|*.pem"),
                wxFD_SAVE | wxFD_OVERWRITE_PROMPT
                );
+       ScopeGuard sg = [d]() { d->Destroy(); };
 
        if (d->ShowModal () == wxID_OK) {
                boost::filesystem::path path (wx_to_std(d->GetPath()));
                if (path.extension() != ".pem") {
                        path += ".pem";
                }
-               auto f = fopen_boost (path, "w");
+               dcp::File f(path, "w");
                if (!f) {
                        throw OpenFileError (path, errno, OpenFileError::WRITE);
                }
 
                auto const s = _get()->key().get ();
-               checked_fwrite (s.c_str(), s.length(), f, path);
-               fclose (f);
+               f.checked_write(s.c_str(), s.length());
        }
-       d->Destroy ();
 }
 
 wxString
@@ -690,21 +646,21 @@ KeysPage::setup ()
        {
                auto m = new StaticText (_panel, _("Decrypting KDMs"));
                m->SetFont (subheading_font);
-               sizer->Add (m, 0, wxALL, _border);
+               sizer->Add (m, 0, wxALL | wxEXPAND, _border);
        }
 
-       auto buttons = new wxBoxSizer (wxVERTICAL);
+       auto kdm_buttons = new wxBoxSizer (wxVERTICAL);
 
        auto export_decryption_certificate = new Button (_panel, _("Export KDM decryption leaf certificate..."));
-       buttons->Add (export_decryption_certificate, 0, wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
+       kdm_buttons->Add (export_decryption_certificate, 0, wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
        auto export_settings = new Button (_panel, _("Export all KDM decryption settings..."));
-       buttons->Add (export_settings, 0, wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
+       kdm_buttons->Add (export_settings, 0, wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
        auto import_settings = new Button (_panel, _("Import all KDM decryption settings..."));
-       buttons->Add (import_settings, 0, wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
+       kdm_buttons->Add (import_settings, 0, wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
        auto decryption_advanced = new Button (_panel, _("Advanced..."));
-       buttons->Add (decryption_advanced, 0);
+       kdm_buttons->Add (decryption_advanced, 0);
 
-       sizer->Add (buttons, 0, wxLEFT, _border);
+       sizer->Add (kdm_buttons, 0, wxLEFT, _border);
 
        export_decryption_certificate->Bind (wxEVT_BUTTON, bind (&KeysPage::export_decryption_certificate, this));
        export_settings->Bind (wxEVT_BUTTON, bind (&KeysPage::export_decryption_chain_and_key, this));
@@ -714,14 +670,34 @@ KeysPage::setup ()
        {
                auto m = new StaticText (_panel, _("Signing DCPs and KDMs"));
                m->SetFont (subheading_font);
-               sizer->Add (m, 0, wxALL, _border);
+               sizer->Add (m, 0, wxALL | wxEXPAND, _border);
        }
 
+       auto signing_buttons = new wxBoxSizer (wxVERTICAL);
+
        auto signing_advanced = new Button (_panel, _("Advanced..."));
-       sizer->Add (signing_advanced, 0, wxLEFT | wxBOTTOM, _border);
+       signing_buttons->Add (signing_advanced, 0, wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
+       auto remake_signing = new Button (_panel, _("Re-make certificates and key..."));
+       signing_buttons->Add (remake_signing, 0, wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
+
+       sizer->Add (signing_buttons, 0, wxLEFT, _border);
+
        signing_advanced->Bind (wxEVT_BUTTON, bind (&KeysPage::signing_advanced, this));
+       remake_signing->Bind (wxEVT_BUTTON, bind(&KeysPage::remake_signing, this));
 }
 
+
+void
+KeysPage::remake_signing ()
+{
+       auto d = new MakeChainDialog (_panel, Config::instance()->signer_chain());
+
+       if (d->ShowModal () == wxID_OK) {
+               Config::instance()->set_signer_chain(d->get());
+       }
+}
+
+
 void
 KeysPage::decryption_advanced ()
 {
@@ -755,23 +731,23 @@ KeysPage::export_decryption_chain_and_key ()
                _panel, _("Select Export File"), wxEmptyString, wxEmptyString, wxT ("DOM files (*.dom)|*.dom"),
                wxFD_SAVE | wxFD_OVERWRITE_PROMPT
                );
+       ScopeGuard sg = [d]() { d->Destroy(); };
 
-       if (d->ShowModal () == wxID_OK) {
-               boost::filesystem::path path (wx_to_std(d->GetPath()));
-               auto f = fopen_boost (path, "w");
-               if (!f) {
-                       throw OpenFileError (path, errno, OpenFileError::WRITE);
-               }
+       if (d->ShowModal() != wxID_OK) {
+               return;
+       }
 
-               auto const chain = Config::instance()->decryption_chain()->chain();
-               checked_fwrite (chain.c_str(), chain.length(), f, path);
-               optional<string> const key = Config::instance()->decryption_chain()->key();
-               DCPOMATIC_ASSERT (key);
-               checked_fwrite (key->c_str(), key->length(), f, path);
-               fclose (f);
+       boost::filesystem::path path(wx_to_std(d->GetPath()));
+       dcp::File f(path, "w");
+       if (!f) {
+               throw OpenFileError(path, errno, OpenFileError::WRITE);
        }
-       d->Destroy ();
 
+       auto const chain = Config::instance()->decryption_chain()->chain();
+       f.checked_write(chain.c_str(), chain.length());
+       auto const key = Config::instance()->decryption_chain()->key();
+       DCPOMATIC_ASSERT(key);
+       f.checked_write(key->c_str(), key->length());
 }
 
 void
@@ -789,39 +765,40 @@ KeysPage::import_decryption_chain_and_key ()
        auto d = new wxFileDialog (
                _panel, _("Select File To Import"), wxEmptyString, wxEmptyString, wxT ("DOM files (*.dom)|*.dom")
                );
+       ScopeGuard sg = [d]() { d->Destroy(); };
 
-       if (d->ShowModal () == wxID_OK) {
-               auto new_chain = make_shared<dcp::CertificateChain>();
+       if (d->ShowModal() != wxID_OK) {
+               return;
+       }
 
-               FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "r");
-               if (!f) {
-                       throw OpenFileError (wx_to_std (d->GetPath ()), errno, OpenFileError::WRITE);
-               }
+       auto new_chain = make_shared<dcp::CertificateChain>();
 
-               string current;
-               while (!feof (f)) {
-                       char buffer[128];
-                       if (fgets (buffer, 128, f) == 0) {
-                               break;
-                       }
-                       current += buffer;
-                       if (strncmp (buffer, "-----END CERTIFICATE-----", 25) == 0) {
-                               new_chain->add (dcp::Certificate (current));
-                               current = "";
-                       } else if (strncmp (buffer, "-----END RSA PRIVATE KEY-----", 29) == 0) {
-                               new_chain->set_key (current);
-                               current = "";
-                       }
-               }
-               fclose (f);
+       dcp::File f(wx_to_std(d->GetPath()), "r");
+       if (!f) {
+               throw OpenFileError(f.path(), errno, OpenFileError::WRITE);
+       }
 
-               if (new_chain->chain_valid() && new_chain->private_key_valid()) {
-                       Config::instance()->set_decryption_chain (new_chain);
-               } else {
-                       error_dialog (_panel, _("Invalid DCP-o-matic export file"));
+       string current;
+       while (!f.eof()) {
+               char buffer[128];
+               if (f.gets(buffer, 128) == 0) {
+                       break;
+               }
+               current += buffer;
+               if (strncmp (buffer, "-----END CERTIFICATE-----", 25) == 0) {
+                       new_chain->add(dcp::Certificate(current));
+                       current = "";
+               } else if (strncmp (buffer, "-----END RSA PRIVATE KEY-----", 29) == 0) {
+                       new_chain->set_key(current);
+                       current = "";
                }
        }
-       d->Destroy ();
+
+       if (new_chain->chain_valid() && new_chain->private_key_valid()) {
+               Config::instance()->set_decryption_chain(new_chain);
+       } else {
+               error_dialog(_panel, _("Invalid DCP-o-matic export file"));
+       }
 }
 
 bool
@@ -838,27 +815,37 @@ KeysPage::nag_alter_decryption_chain ()
 void
 KeysPage::export_decryption_certificate ()
 {
-       wxFileDialog* d = new wxFileDialog (
-               _panel, _("Select Certificate File"), wxEmptyString, _("dcpomatic_kdm_decryption_cert.pem"), wxT ("PEM files (*.pem)|*.pem"),
+       auto config = Config::instance();
+       wxString default_name = "dcpomatic";
+       if (!config->dcp_creator().empty()) {
+               default_name += "_" + std_to_wx(careful_string_filter(config->dcp_creator()));
+       }
+       if (!config->dcp_issuer().empty()) {
+               default_name += "_" + std_to_wx(careful_string_filter(config->dcp_issuer()));
+       }
+       default_name += wxT("_kdm_decryption_cert.pem");
+
+       auto d = new wxFileDialog (
+               _panel, _("Select Certificate File"), wxEmptyString, default_name, wxT("PEM files (*.pem)|*.pem"),
                wxFD_SAVE | wxFD_OVERWRITE_PROMPT
                );
+       ScopeGuard sg = [d]() { d->Destroy(); };
 
-       if (d->ShowModal () == wxID_OK) {
-               boost::filesystem::path path (wx_to_std(d->GetPath()));
-               if (path.extension() != ".pem") {
-                       path += ".pem";
-               }
-               auto f = fopen_boost (path, "w");
-               if (!f) {
-                       throw OpenFileError (path, errno, OpenFileError::WRITE);
-               }
+       if (d->ShowModal() != wxID_OK) {
+               return;
+       }
 
-               auto const s = Config::instance()->decryption_chain()->leaf().certificate (true);
-               checked_fwrite (s.c_str(), s.length(), f, path);
-               fclose (f);
+       boost::filesystem::path path(wx_to_std(d->GetPath()));
+       if (path.extension() != ".pem") {
+               path += ".pem";
+       }
+       dcp::File f(path, "w");
+       if (!f) {
+               throw OpenFileError(path, errno, OpenFileError::WRITE);
        }
 
-       d->Destroy ();
+       auto const s = Config::instance()->decryption_chain()->leaf().certificate (true);
+       f.checked_write(s.c_str(), s.length());
 }
 
 wxString
@@ -887,7 +874,7 @@ SoundPage::setup ()
 
        add_label_to_sizer (table, _panel, _("Mapping"), true, wxGBPosition(r, 0));
        _map = new AudioMappingView (_panel, _("DCP"), _("DCP"), _("Output"), _("output"));
-       _map->SetSize (-1, 600);
+       _map->SetSize (-1, 400);
        table->Add (_map, wxGBPosition(r, 1), wxDefaultSpan, wxEXPAND);
        ++r;
 
@@ -912,7 +899,7 @@ SoundPage::setup ()
                }
        }
 
-       _sound->Bind        (wxEVT_CHECKBOX, bind(&SoundPage::sound_changed, this));
+       _sound->bind(&SoundPage::sound_changed, this);
        _sound_output->Bind (wxEVT_CHOICE,   bind(&SoundPage::sound_output_changed, this));
        _map->Changed.connect (bind(&SoundPage::map_changed, this, _1));
        _reset_to_default->Bind (wxEVT_BUTTON,   bind(&SoundPage::reset_to_default, this));
@@ -1071,7 +1058,7 @@ LocationsPage::GetName () const
 wxBitmap
 LocationsPage::GetLargeIcon () const
 {
-       return wxBitmap ("locations", wxBITMAP_TYPE_PNG_RESOURCE);
+       return wxBitmap(icon_path("locations"), wxBITMAP_TYPE_PNG);
 }
 #endif