diff options
| author | Carl Hetherington <cth@carlh.net> | 2017-08-20 23:43:12 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2017-08-20 23:43:12 +0100 |
| commit | f8832c431b45e81523ec2ef70999e7e613d5001e (patch) | |
| tree | 3ba7308351a3c0bfd96ba1f31f32cb41103a0d87 /src/wx/config_dialog.cc | |
| parent | 35e9a698ba3ca35fd488b3622e441956632261cf (diff) | |
Add KDM decryption keys prefs to player.
Diffstat (limited to 'src/wx/config_dialog.cc')
| -rw-r--r-- | src/wx/config_dialog.cc | 797 |
1 files changed, 797 insertions, 0 deletions
diff --git a/src/wx/config_dialog.cc b/src/wx/config_dialog.cc new file mode 100644 index 000000000..30585f4e3 --- /dev/null +++ b/src/wx/config_dialog.cc @@ -0,0 +1,797 @@ +/* + Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "config_dialog.h" +#include "nag_dialog.h" + +using boost::bind; + +static +void +do_nothing () +{ + +} + +Page::Page (wxSize panel_size, int border) + : _border (border) + , _panel (0) + , _panel_size (panel_size) + , _window_exists (false) +{ + _config_connection = Config::instance()->Changed.connect (boost::bind (&Page::config_changed_wrapper, this)); +} + +wxWindow* +Page::create_window (wxWindow* parent) +{ + _panel = new wxPanel (parent, wxID_ANY, wxDefaultPosition, _panel_size); + wxBoxSizer* s = new wxBoxSizer (wxVERTICAL); + _panel->SetSizer (s); + + setup (); + _window_exists = true; + config_changed (); + + _panel->Bind (wxEVT_DESTROY, boost::bind (&Page::window_destroyed, this)); + + return _panel; +} + +void +Page::config_changed_wrapper () +{ + if (_window_exists) { + config_changed (); + } +} + +void +Page::window_destroyed () +{ + _window_exists = false; +} + + +StockPage::StockPage (Kind kind, wxSize panel_size, int border) + : wxStockPreferencesPage (kind) + , Page (panel_size, border) +{ + +} + +wxWindow* +StockPage::CreateWindow (wxWindow* parent) +{ + return create_window (parent); +} + +StandardPage::StandardPage (wxSize panel_size, int border) + : Page (panel_size, border) +{ + +} + +wxWindow* +StandardPage::CreateWindow (wxWindow* parent) +{ + return create_window (parent); +} + +GeneralPage::GeneralPage (wxSize panel_size, int border) + : StockPage (Kind_General, panel_size, border) +{ + +} + +void +GeneralPage::add_language_controls (wxGridBagSizer* table, int& r) +{ + _set_language = new wxCheckBox (_panel, wxID_ANY, _("Set language")); + table->Add (_set_language, wxGBPosition (r, 0)); + _language = new wxChoice (_panel, wxID_ANY); + std::vector<std::pair<std::string, std::string> > languages; + languages.push_back (std::make_pair ("Čeština", "cs_CZ")); + languages.push_back (std::make_pair ("汉语/漢語", "zh_CN")); + languages.push_back (std::make_pair ("Dansk", "da_DK")); + languages.push_back (std::make_pair ("Deutsch", "de_DE")); + languages.push_back (std::make_pair ("English", "en_GB")); + languages.push_back (std::make_pair ("Español", "es_ES")); + languages.push_back (std::make_pair ("Français", "fr_FR")); + languages.push_back (std::make_pair ("Italiano", "it_IT")); + languages.push_back (std::make_pair ("Nederlands", "nl_NL")); + languages.push_back (std::make_pair ("Русский", "ru_RU")); + languages.push_back (std::make_pair ("Polski", "pl_PL")); + languages.push_back (std::make_pair ("Português europeu", "pt_PT")); + languages.push_back (std::make_pair ("Português do Brasil", "pt_BR")); + languages.push_back (std::make_pair ("Svenska", "sv_SE")); + languages.push_back (std::make_pair ("Slovenský jazyk", "sk_SK")); + languages.push_back (std::make_pair ("українська мова", "uk_UA")); + checked_set (_language, languages); + table->Add (_language, wxGBPosition (r, 1)); + ++r; + + wxStaticText* restart = add_label_to_sizer ( + table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2) + ); + wxFont font = restart->GetFont(); + font.SetStyle (wxFONTSTYLE_ITALIC); + font.SetPointSize (font.GetPointSize() - 1); + restart->SetFont (font); + ++r; + + _set_language->Bind (wxEVT_CHECKBOX, boost::bind (&GeneralPage::set_language_changed, this)); + _language->Bind (wxEVT_CHOICE, boost::bind (&GeneralPage::language_changed, this)); +} + +void +GeneralPage::add_play_sound_controls (wxGridBagSizer* table, int& r) +{ + _sound = new wxCheckBox (_panel, wxID_ANY, _("Play sound via")); + table->Add (_sound, wxGBPosition (r, 0)); + _sound_output = new wxChoice (_panel, wxID_ANY); + table->Add (_sound_output, wxGBPosition (r, 1)); + ++r; + + RtAudio audio (DCPOMATIC_RTAUDIO_API); + for (unsigned int i = 0; i < audio.getDeviceCount(); ++i) { + RtAudio::DeviceInfo dev = audio.getDeviceInfo (i); + if (dev.probed && dev.outputChannels > 0) { + _sound_output->Append (std_to_wx (dev.name)); + } + } + + _sound->Bind (wxEVT_CHECKBOX, boost::bind (&GeneralPage::sound_changed, this)); + _sound_output->Bind (wxEVT_CHOICE, boost::bind (&GeneralPage::sound_output_changed, this)); +} + +void +GeneralPage::add_update_controls (wxGridBagSizer* table, int& r) +{ + _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup")); + table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2)); + ++r; + + _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup")); + table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2)); + ++r; + + _check_for_updates->Bind (wxEVT_CHECKBOX, boost::bind (&GeneralPage::check_for_updates_changed, this)); + _check_for_test_updates->Bind (wxEVT_CHECKBOX, boost::bind (&GeneralPage::check_for_test_updates_changed, this)); +} + +void +GeneralPage::config_changed () +{ + Config* config = Config::instance (); + + checked_set (_set_language, static_cast<bool>(config->language())); + + /* Backwards compatibility of config file */ + + std::map<std::string, std::string> compat_map; + compat_map["fr"] = "fr_FR"; + compat_map["it"] = "it_IT"; + compat_map["es"] = "es_ES"; + compat_map["sv"] = "sv_SE"; + compat_map["de"] = "de_DE"; + compat_map["nl"] = "nl_NL"; + compat_map["ru"] = "ru_RU"; + compat_map["pl"] = "pl_PL"; + compat_map["da"] = "da_DK"; + compat_map["pt"] = "pt_PT"; + compat_map["sk"] = "sk_SK"; + compat_map["cs"] = "cs_CZ"; + compat_map["uk"] = "uk_UA"; + + std::string lang = config->language().get_value_or ("en_GB"); + if (compat_map.find (lang) != compat_map.end ()) { + lang = compat_map[lang]; + } + + checked_set (_language, lang); + + checked_set (_check_for_updates, config->check_for_updates ()); + checked_set (_check_for_test_updates, config->check_for_test_updates ()); + + checked_set (_sound, config->sound ()); + + boost::optional<std::string> const current_so = get_sound_output (); + boost::optional<std::string> configured_so; + + if (config->sound_output()) { + configured_so = config->sound_output().get(); + } else { + /* No configured output means we should use the default */ + RtAudio audio (DCPOMATIC_RTAUDIO_API); + try { + configured_so = audio.getDeviceInfo(audio.getDefaultOutputDevice()).name; + } catch (RtAudioError& e) { + /* Probably no audio devices at all */ + } + } + + if (configured_so && current_so != configured_so) { + /* Update _sound_output with the configured value */ + unsigned int i = 0; + while (i < _sound_output->GetCount()) { + if (_sound_output->GetString(i) == std_to_wx(*configured_so)) { + _sound_output->SetSelection (i); + break; + } + ++i; + } + } + + setup_sensitivity (); +} + +void +GeneralPage::setup_sensitivity () +{ + _language->Enable (_set_language->GetValue ()); + _check_for_test_updates->Enable (_check_for_updates->GetValue ()); + _sound_output->Enable (_sound->GetValue ()); +} + +/** @return Currently-selected preview sound output in the dialogue */ +boost::optional<std::string> +GeneralPage::get_sound_output () +{ + int const sel = _sound_output->GetSelection (); + if (sel == wxNOT_FOUND) { + return boost::optional<std::string> (); + } + + return wx_to_std (_sound_output->GetString (sel)); +} + +void +GeneralPage::set_language_changed () +{ + setup_sensitivity (); + if (_set_language->GetValue ()) { + language_changed (); + } else { + Config::instance()->unset_language (); + } +} + +void +GeneralPage::language_changed () +{ + int const sel = _language->GetSelection (); + if (sel != -1) { + Config::instance()->set_language (string_client_data (_language->GetClientObject (sel))); + } else { + Config::instance()->unset_language (); + } +} + +void +GeneralPage::check_for_updates_changed () +{ + Config::instance()->set_check_for_updates (_check_for_updates->GetValue ()); +} + +void +GeneralPage::check_for_test_updates_changed () +{ + Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ()); +} + +void +GeneralPage::sound_changed () +{ + Config::instance()->set_sound (_sound->GetValue ()); +} + +void +GeneralPage::sound_output_changed () +{ + RtAudio audio (DCPOMATIC_RTAUDIO_API); + boost::optional<std::string> const so = get_sound_output(); + if (!so || *so == audio.getDeviceInfo(audio.getDefaultOutputDevice()).name) { + Config::instance()->unset_sound_output (); + } else { + Config::instance()->set_sound_output (*so); + } +} + +CertificateChainEditor::CertificateChainEditor ( + wxWindow* parent, + wxString title, + int border, + boost::function<void (boost::shared_ptr<dcp::CertificateChain>)> set, + boost::function<boost::shared_ptr<const dcp::CertificateChain> (void)> get, + boost::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); + + _sizer = new wxBoxSizer (wxVERTICAL); + + { + wxStaticText* m = new wxStaticText (this, wxID_ANY, title); + m->SetFont (subheading_font); + _sizer->Add (m, 0, wxALL, border); + } + + wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL); + _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border); + + _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL); + + { + wxListItem ip; + ip.SetId (0); + ip.SetText (_("Type")); + ip.SetWidth (100); + _certificates->InsertColumn (0, ip); + } + + { + wxListItem ip; + ip.SetId (1); + ip.SetText (_("Thumbprint")); + ip.SetWidth (340); + + wxFont font = ip.GetFont (); + font.SetFamily (wxFONTFAMILY_TELETYPE); + ip.SetFont (font); + + _certificates->InsertColumn (1, ip); + } + + certificates_sizer->Add (_certificates, 1, wxEXPAND); + + { + wxSizer* s = new wxBoxSizer (wxVERTICAL); + _add_certificate = new wxButton (this, wxID_ANY, _("Add...")); + s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); + _remove_certificate = new wxButton (this, wxID_ANY, _("Remove")); + s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); + _export_certificate = new wxButton (this, wxID_ANY, _("Export")); + s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); + certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP); + } + + wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP); + _sizer->Add (table, 1, wxALL | wxEXPAND, border); + int r = 0; + + add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0)); + _private_key = new wxStaticText (this, wxID_ANY, wxT ("")); + wxFont font = _private_key->GetFont (); + font.SetFamily (wxFONTFAMILY_TELETYPE); + _private_key->SetFont (font); + table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL); + _load_private_key = new wxButton (this, wxID_ANY, _("Load...")); + table->Add (_load_private_key, wxGBPosition (r, 2)); + _export_private_key = new wxButton (this, wxID_ANY, _("Export...")); + table->Add (_export_private_key, wxGBPosition (r, 3)); + ++r; + + _button_sizer = new wxBoxSizer (wxHORIZONTAL); + _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates\nand key...")); + _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border); + 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)); + _certificates->Bind (wxEVT_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this)); + _certificates->Bind (wxEVT_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this)); + _remake_certificates->Bind (wxEVT_BUTTON, boost::bind (&CertificateChainEditor::remake_certificates, this)); + _load_private_key->Bind (wxEVT_BUTTON, boost::bind (&CertificateChainEditor::load_private_key, this)); + _export_private_key->Bind (wxEVT_BUTTON, boost::bind (&CertificateChainEditor::export_private_key, this)); + + SetSizerAndFit (_sizer); +} + + +void +CertificateChainEditor::config_changed () +{ + _chain.reset (new dcp::CertificateChain (*_get().get ())); + + update_certificate_list (); + update_private_key (); + update_sensitivity (); +} + +void +CertificateChainEditor::add_button (wxWindow* button) +{ + _button_sizer->Add (button, 0, wxLEFT | wxRIGHT, DCPOMATIC_SIZER_X_GAP); + _sizer->Layout (); +} + +void +CertificateChainEditor::add_certificate () +{ + wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File")); + + if (d->ShowModal() == wxID_OK) { + try { + dcp::Certificate c; + std::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, + _("This file contains other certificates (or other data) after its first certificate. " + "Only the first certificate will be used.") + ); + } + _chain->add (c); + 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 ())); + } + } + + d->Destroy (); + + update_sensitivity (); +} + +void +CertificateChainEditor::remove_certificate () +{ + int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + if (i == -1) { + return; + } + + _certificates->DeleteItem (i); + _chain->remove (i); + _set (_chain); + + update_sensitivity (); +} + +void +CertificateChainEditor::export_certificate () +{ + int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + if (i == -1) { + return; + } + + wxFileDialog* d = new wxFileDialog ( + this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"), + wxFD_SAVE | wxFD_OVERWRITE_PROMPT + ); + + dcp::CertificateChain::List all = _chain->root_to_leaf (); + dcp::CertificateChain::List::iterator j = all.begin (); + for (int k = 0; k < i; ++k) { + ++j; + } + + if (d->ShowModal () == wxID_OK) { + FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w"); + if (!f) { + throw OpenFileError (wx_to_std (d->GetPath ()), errno, false); + } + + std::string const s = j->certificate (true); + fwrite (s.c_str(), 1, s.length(), f); + fclose (f); + } + d->Destroy (); +} + +void +CertificateChainEditor::update_certificate_list () +{ + _certificates->DeleteAllItems (); + size_t n = 0; + dcp::CertificateChain::List certs = _chain->root_to_leaf (); + BOOST_FOREACH (dcp::Certificate const & i, certs) { + wxListItem item; + item.SetId (n); + _certificates->InsertItem (item); + _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ())); + + if (n == 0) { + _certificates->SetItem (n, 0, _("Root")); + } else if (n == (certs.size() - 1)) { + _certificates->SetItem (n, 0, _("Leaf")); + } else { + _certificates->SetItem (n, 0, _("Intermediate")); + } + + ++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 +CertificateChainEditor::remake_certificates () +{ + boost::shared_ptr<const dcp::CertificateChain> chain = _get (); + + std::string subject_organization_name; + std::string subject_organizational_unit_name; + std::string root_common_name; + std::string intermediate_common_name; + std::string leaf_common_name; + + dcp::CertificateChain::List 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 (); + } + + _nag_remake (); + + MakeChainDialog* d = new MakeChainDialog ( + this, + subject_organization_name, + subject_organizational_unit_name, + root_common_name, + intermediate_common_name, + leaf_common_name + ); + + if (d->ShowModal () == wxID_OK) { + _chain.reset ( + new dcp::CertificateChain ( + openssl_path (), + d->organisation (), + d->organisational_unit (), + d->root_common_name (), + d->intermediate_common_name (), + d->leaf_common_name () + ) + ); + + _set (_chain); + update_certificate_list (); + update_private_key (); + } + + d->Destroy (); +} + +void +CertificateChainEditor::update_sensitivity () +{ + /* 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); +} + +void +CertificateChainEditor::update_private_key () +{ + checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ())); + _sizer->Layout (); +} + +void +CertificateChainEditor::load_private_key () +{ + wxFileDialog* d = new wxFileDialog (this, _("Select Key File")); + + if (d->ShowModal() == wxID_OK) { + try { + boost::filesystem::path p (wx_to_std (d->GetPath ())); + if (boost::filesystem::file_size (p) > 8192) { + error_dialog ( + this, + wxString::Format (_("Could not read key file; file is too long (%s)"), std_to_wx (p.string ())) + ); + return; + } + + _chain->set_key (dcp::file_to_string (p)); + _set (_chain); + update_private_key (); + } catch (dcp::MiscError& e) { + error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ())); + } + } + + d->Destroy (); + + update_sensitivity (); +} + +void +CertificateChainEditor::export_private_key () +{ + boost::optional<std::string> key = _chain->key (); + if (!key) { + return; + } + + wxFileDialog* d = new wxFileDialog ( + this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"), + wxFD_SAVE | wxFD_OVERWRITE_PROMPT + ); + + if (d->ShowModal () == wxID_OK) { + FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w"); + if (!f) { + throw OpenFileError (wx_to_std (d->GetPath ()), errno, false); + } + + std::string const s = _chain->key().get (); + fwrite (s.c_str(), 1, s.length(), f); + fclose (f); + } + d->Destroy (); +} + +wxString +KeysPage::GetName () const +{ + return _("Keys"); +} + +void +KeysPage::setup () +{ + if (_sign) { + _signer = new CertificateChainEditor ( + _panel, _("Signing DCPs and KDMs"), _border, + bind (&Config::set_signer_chain, Config::instance (), _1), + bind (&Config::signer_chain, Config::instance ()), + bind (&do_nothing) + ); + + _panel->GetSizer()->Add (_signer); + } + + _decryption = new CertificateChainEditor ( + _panel, _("Decrypting KDMs"), _border, + bind (&Config::set_decryption_chain, Config::instance (), _1), + bind (&Config::decryption_chain, Config::instance ()), + bind (&KeysPage::nag_remake_decryption_chain, this) + ); + + _panel->GetSizer()->Add (_decryption); + + _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export KDM decryption\ncertificate...")); + _decryption->add_button (_export_decryption_certificate); + _export_decryption_chain = new wxButton (_decryption, wxID_ANY, _("Export KDM decryption\nchain...")); + _decryption->add_button (_export_decryption_chain); + + _export_decryption_certificate->Bind (wxEVT_BUTTON, bind (&KeysPage::export_decryption_certificate, this)); + _export_decryption_chain->Bind (wxEVT_BUTTON, bind (&KeysPage::export_decryption_chain, this)); +} + +void +KeysPage::config_changed () +{ + if (_sign) { + _signer->config_changed (); + } + _decryption->config_changed (); +} + +void +KeysPage::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!") + ); +} + +void +KeysPage::export_decryption_chain () +{ + wxFileDialog* d = new wxFileDialog ( + _panel, _("Select Chain File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"), + wxFD_SAVE | wxFD_OVERWRITE_PROMPT + ); + + if (d->ShowModal () == wxID_OK) { + FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w"); + if (!f) { + throw OpenFileError (wx_to_std (d->GetPath ()), errno, false); + } + + std::string const s = Config::instance()->decryption_chain()->chain(); + fwrite (s.c_str(), 1, s.length(), f); + fclose (f); + } + d->Destroy (); +} + +void +KeysPage::export_decryption_certificate () +{ + wxFileDialog* d = new wxFileDialog ( + _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"), + wxFD_SAVE | wxFD_OVERWRITE_PROMPT + ); + + if (d->ShowModal () == wxID_OK) { + FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w"); + if (!f) { + throw OpenFileError (wx_to_std (d->GetPath ()), errno, false); + } + + std::string const s = Config::instance()->decryption_chain()->leaf().certificate (true); + fwrite (s.c_str(), 1, s.length(), f); + fclose (f); + } + d->Destroy (); +} |
