2 Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
21 #include "config_dialog.h"
22 #include "nag_dialog.h"
26 using boost::optional;
27 using boost::shared_ptr;
36 Page::Page (wxSize panel_size, int border)
39 , _panel_size (panel_size)
40 , _window_exists (false)
42 _config_connection = Config::instance()->Changed.connect (boost::bind (&Page::config_changed_wrapper, this));
46 Page::create_window (wxWindow* parent)
48 _panel = new wxPanel (parent, wxID_ANY, wxDefaultPosition, _panel_size);
49 wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
53 _window_exists = true;
56 _panel->Bind (wxEVT_DESTROY, boost::bind (&Page::window_destroyed, this));
62 Page::config_changed_wrapper ()
70 Page::window_destroyed ()
72 _window_exists = false;
76 StockPage::StockPage (Kind kind, wxSize panel_size, int border)
77 : wxStockPreferencesPage (kind)
78 , Page (panel_size, border)
84 StockPage::CreateWindow (wxWindow* parent)
86 return create_window (parent);
89 StandardPage::StandardPage (wxSize panel_size, int border)
90 : Page (panel_size, border)
96 StandardPage::CreateWindow (wxWindow* parent)
98 return create_window (parent);
101 GeneralPage::GeneralPage (wxSize panel_size, int border)
102 : StockPage (Kind_General, panel_size, border)
108 GeneralPage::add_language_controls (wxGridBagSizer* table, int& r)
110 _set_language = new wxCheckBox (_panel, wxID_ANY, _("Set language"));
111 table->Add (_set_language, wxGBPosition (r, 0));
112 _language = new wxChoice (_panel, wxID_ANY);
113 std::vector<std::pair<std::string, std::string> > languages;
114 languages.push_back (std::make_pair ("Čeština", "cs_CZ"));
115 languages.push_back (std::make_pair ("汉语/漢語", "zh_CN"));
116 languages.push_back (std::make_pair ("Dansk", "da_DK"));
117 languages.push_back (std::make_pair ("Deutsch", "de_DE"));
118 languages.push_back (std::make_pair ("English", "en_GB"));
119 languages.push_back (std::make_pair ("Español", "es_ES"));
120 languages.push_back (std::make_pair ("Français", "fr_FR"));
121 languages.push_back (std::make_pair ("Italiano", "it_IT"));
122 languages.push_back (std::make_pair ("Nederlands", "nl_NL"));
123 languages.push_back (std::make_pair ("Русский", "ru_RU"));
124 languages.push_back (std::make_pair ("Polski", "pl_PL"));
125 languages.push_back (std::make_pair ("Português europeu", "pt_PT"));
126 languages.push_back (std::make_pair ("Português do Brasil", "pt_BR"));
127 languages.push_back (std::make_pair ("Svenska", "sv_SE"));
128 languages.push_back (std::make_pair ("Slovenský jazyk", "sk_SK"));
129 languages.push_back (std::make_pair ("українська мова", "uk_UA"));
130 checked_set (_language, languages);
131 table->Add (_language, wxGBPosition (r, 1));
134 wxStaticText* restart = add_label_to_sizer (
135 table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2)
137 wxFont font = restart->GetFont();
138 font.SetStyle (wxFONTSTYLE_ITALIC);
139 font.SetPointSize (font.GetPointSize() - 1);
140 restart->SetFont (font);
143 _set_language->Bind (wxEVT_CHECKBOX, boost::bind (&GeneralPage::set_language_changed, this));
144 _language->Bind (wxEVT_CHOICE, boost::bind (&GeneralPage::language_changed, this));
148 GeneralPage::add_play_sound_controls (wxGridBagSizer* table, int& r)
150 _sound = new wxCheckBox (_panel, wxID_ANY, _("Play sound via"));
151 table->Add (_sound, wxGBPosition (r, 0));
152 _sound_output = new wxChoice (_panel, wxID_ANY);
153 table->Add (_sound_output, wxGBPosition (r, 1));
156 RtAudio audio (DCPOMATIC_RTAUDIO_API);
157 for (unsigned int i = 0; i < audio.getDeviceCount(); ++i) {
158 RtAudio::DeviceInfo dev = audio.getDeviceInfo (i);
159 if (dev.probed && dev.outputChannels > 0) {
160 _sound_output->Append (std_to_wx (dev.name));
164 _sound->Bind (wxEVT_CHECKBOX, boost::bind (&GeneralPage::sound_changed, this));
165 _sound_output->Bind (wxEVT_CHOICE, boost::bind (&GeneralPage::sound_output_changed, this));
169 GeneralPage::add_update_controls (wxGridBagSizer* table, int& r)
171 _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
172 table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
175 _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
176 table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
179 _check_for_updates->Bind (wxEVT_CHECKBOX, boost::bind (&GeneralPage::check_for_updates_changed, this));
180 _check_for_test_updates->Bind (wxEVT_CHECKBOX, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
184 GeneralPage::config_changed ()
186 Config* config = Config::instance ();
188 checked_set (_set_language, static_cast<bool>(config->language()));
190 /* Backwards compatibility of config file */
192 std::map<std::string, std::string> compat_map;
193 compat_map["fr"] = "fr_FR";
194 compat_map["it"] = "it_IT";
195 compat_map["es"] = "es_ES";
196 compat_map["sv"] = "sv_SE";
197 compat_map["de"] = "de_DE";
198 compat_map["nl"] = "nl_NL";
199 compat_map["ru"] = "ru_RU";
200 compat_map["pl"] = "pl_PL";
201 compat_map["da"] = "da_DK";
202 compat_map["pt"] = "pt_PT";
203 compat_map["sk"] = "sk_SK";
204 compat_map["cs"] = "cs_CZ";
205 compat_map["uk"] = "uk_UA";
207 std::string lang = config->language().get_value_or ("en_GB");
208 if (compat_map.find (lang) != compat_map.end ()) {
209 lang = compat_map[lang];
212 checked_set (_language, lang);
214 checked_set (_check_for_updates, config->check_for_updates ());
215 checked_set (_check_for_test_updates, config->check_for_test_updates ());
217 checked_set (_sound, config->sound ());
219 boost::optional<std::string> const current_so = get_sound_output ();
220 boost::optional<std::string> configured_so;
222 if (config->sound_output()) {
223 configured_so = config->sound_output().get();
225 /* No configured output means we should use the default */
226 RtAudio audio (DCPOMATIC_RTAUDIO_API);
228 configured_so = audio.getDeviceInfo(audio.getDefaultOutputDevice()).name;
229 } catch (RtAudioError& e) {
230 /* Probably no audio devices at all */
234 if (configured_so && current_so != configured_so) {
235 /* Update _sound_output with the configured value */
237 while (i < _sound_output->GetCount()) {
238 if (_sound_output->GetString(i) == std_to_wx(*configured_so)) {
239 _sound_output->SetSelection (i);
246 setup_sensitivity ();
250 GeneralPage::setup_sensitivity ()
252 _language->Enable (_set_language->GetValue ());
253 _check_for_test_updates->Enable (_check_for_updates->GetValue ());
254 _sound_output->Enable (_sound->GetValue ());
257 /** @return Currently-selected preview sound output in the dialogue */
258 boost::optional<std::string>
259 GeneralPage::get_sound_output ()
261 int const sel = _sound_output->GetSelection ();
262 if (sel == wxNOT_FOUND) {
263 return boost::optional<std::string> ();
266 return wx_to_std (_sound_output->GetString (sel));
270 GeneralPage::set_language_changed ()
272 setup_sensitivity ();
273 if (_set_language->GetValue ()) {
276 Config::instance()->unset_language ();
281 GeneralPage::language_changed ()
283 int const sel = _language->GetSelection ();
285 Config::instance()->set_language (string_client_data (_language->GetClientObject (sel)));
287 Config::instance()->unset_language ();
292 GeneralPage::check_for_updates_changed ()
294 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
298 GeneralPage::check_for_test_updates_changed ()
300 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
304 GeneralPage::sound_changed ()
306 Config::instance()->set_sound (_sound->GetValue ());
310 GeneralPage::sound_output_changed ()
312 RtAudio audio (DCPOMATIC_RTAUDIO_API);
313 boost::optional<std::string> const so = get_sound_output();
314 if (!so || *so == audio.getDeviceInfo(audio.getDefaultOutputDevice()).name) {
315 Config::instance()->unset_sound_output ();
317 Config::instance()->set_sound_output (*so);
321 CertificateChainEditor::CertificateChainEditor (
325 boost::function<void (boost::shared_ptr<dcp::CertificateChain>)> set,
326 boost::function<boost::shared_ptr<const dcp::CertificateChain> (void)> get,
327 boost::function<void (void)> nag_remake
329 : wxDialog (parent, wxID_ANY, title)
332 , _nag_remake (nag_remake)
334 wxFont subheading_font (*wxNORMAL_FONT);
335 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
337 _sizer = new wxBoxSizer (wxVERTICAL);
340 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
341 m->SetFont (subheading_font);
342 _sizer->Add (m, 0, wxALL, border);
345 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
346 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
348 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
353 ip.SetText (_("Type"));
355 _certificates->InsertColumn (0, ip);
361 ip.SetText (_("Thumbprint"));
364 wxFont font = ip.GetFont ();
365 font.SetFamily (wxFONTFAMILY_TELETYPE);
368 _certificates->InsertColumn (1, ip);
371 certificates_sizer->Add (_certificates, 1, wxEXPAND);
374 wxSizer* s = new wxBoxSizer (wxVERTICAL);
375 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
376 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
377 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
378 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
379 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
380 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
381 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
384 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
385 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
388 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
389 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
390 wxFont font = _private_key->GetFont ();
391 font.SetFamily (wxFONTFAMILY_TELETYPE);
392 _private_key->SetFont (font);
393 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
394 _import_private_key = new wxButton (this, wxID_ANY, _("Import..."));
395 table->Add (_import_private_key, wxGBPosition (r, 2));
396 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
397 table->Add (_export_private_key, wxGBPosition (r, 3));
400 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
401 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
402 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
403 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
406 _private_key_bad = new wxStaticText (this, wxID_ANY, _("Leaf private key does not match leaf certificate!"));
407 font = *wxSMALL_FONT;
408 font.SetWeight (wxFONTWEIGHT_BOLD);
409 _private_key_bad->SetFont (font);
410 table->Add (_private_key_bad, wxGBPosition (r, 0), wxGBSpan (1, 3));
413 _add_certificate->Bind (wxEVT_BUTTON, boost::bind (&CertificateChainEditor::add_certificate, this));
414 _remove_certificate->Bind (wxEVT_BUTTON, boost::bind (&CertificateChainEditor::remove_certificate, this));
415 _export_certificate->Bind (wxEVT_BUTTON, boost::bind (&CertificateChainEditor::export_certificate, this));
416 _certificates->Bind (wxEVT_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
417 _certificates->Bind (wxEVT_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
418 _remake_certificates->Bind (wxEVT_BUTTON, boost::bind (&CertificateChainEditor::remake_certificates, this));
419 _import_private_key->Bind (wxEVT_BUTTON, boost::bind (&CertificateChainEditor::import_private_key, this));
420 _export_private_key->Bind (wxEVT_BUTTON, boost::bind (&CertificateChainEditor::export_private_key, this));
422 wxSizer* buttons = CreateSeparatedButtonSizer (wxCLOSE);
424 _sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
427 SetSizerAndFit (_sizer);
429 update_certificate_list ();
430 update_private_key ();
431 update_sensitivity ();
435 CertificateChainEditor::add_button (wxWindow* button)
437 _button_sizer->Add (button, 0, wxLEFT | wxRIGHT, DCPOMATIC_SIZER_X_GAP);
442 CertificateChainEditor::add_certificate ()
444 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
446 if (d->ShowModal() == wxID_OK) {
451 extra = c.read_string (dcp::file_to_string (wx_to_std (d->GetPath ())));
452 } catch (boost::filesystem::filesystem_error& e) {
453 error_dialog (this, wxString::Format (_("Could not import certificate (%s)"), d->GetPath().data()));
458 if (!extra.empty ()) {
461 _("This file contains other certificates (or other data) after its first certificate. "
462 "Only the first certificate will be used.")
465 shared_ptr<dcp::CertificateChain> chain(new dcp::CertificateChain(*_get().get()));
467 if (!chain->chain_valid ()) {
470 _("Adding this certificate would make the chain inconsistent, so it will not be added. "
471 "Add certificates in order from root to intermediate to leaf.")
476 update_certificate_list ();
478 } catch (dcp::MiscError& e) {
479 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
485 update_sensitivity ();
489 CertificateChainEditor::remove_certificate ()
491 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
496 _certificates->DeleteItem (i);
497 shared_ptr<dcp::CertificateChain> chain(new dcp::CertificateChain(*_get().get()));
501 update_sensitivity ();
505 CertificateChainEditor::export_certificate ()
507 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
512 wxFileDialog* d = new wxFileDialog (
513 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
514 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
517 dcp::CertificateChain::List all = _get()->root_to_leaf ();
518 dcp::CertificateChain::List::iterator j = all.begin ();
519 for (int k = 0; k < i; ++k) {
523 if (d->ShowModal () == wxID_OK) {
524 FILE* f = fopen_boost (path_from_file_dialog (d, "pem"), "w");
526 throw OpenFileError (wx_to_std (d->GetPath ()), errno, false);
529 std::string const s = j->certificate (true);
530 fwrite (s.c_str(), 1, s.length(), f);
537 CertificateChainEditor::update_certificate_list ()
539 _certificates->DeleteAllItems ();
541 dcp::CertificateChain::List certs = _get()->root_to_leaf ();
542 BOOST_FOREACH (dcp::Certificate const & i, certs) {
545 _certificates->InsertItem (item);
546 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
549 _certificates->SetItem (n, 0, _("Root"));
550 } else if (n == (certs.size() - 1)) {
551 _certificates->SetItem (n, 0, _("Leaf"));
553 _certificates->SetItem (n, 0, _("Intermediate"));
559 static wxColour normal = _private_key_bad->GetForegroundColour ();
561 if (_get()->private_key_valid()) {
562 _private_key_bad->Hide ();
563 _private_key_bad->SetForegroundColour (normal);
565 _private_key_bad->Show ();
566 _private_key_bad->SetForegroundColour (wxColour (255, 0, 0));
571 CertificateChainEditor::remake_certificates ()
573 boost::shared_ptr<const dcp::CertificateChain> chain = _get();
575 std::string subject_organization_name;
576 std::string subject_organizational_unit_name;
577 std::string root_common_name;
578 std::string intermediate_common_name;
579 std::string leaf_common_name;
581 dcp::CertificateChain::List all = chain->root_to_leaf ();
583 if (all.size() >= 1) {
585 subject_organization_name = chain->root().subject_organization_name ();
586 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
587 root_common_name = chain->root().subject_common_name ();
590 if (all.size() >= 2) {
592 leaf_common_name = chain->leaf().subject_common_name ();
595 if (all.size() >= 3) {
596 /* Have an intermediate */
597 dcp::CertificateChain::List::iterator i = all.begin ();
599 intermediate_common_name = i->subject_common_name ();
604 MakeChainDialog* d = new MakeChainDialog (
606 subject_organization_name,
607 subject_organizational_unit_name,
609 intermediate_common_name,
613 if (d->ShowModal () == wxID_OK) {
615 shared_ptr<dcp::CertificateChain> (
616 new dcp::CertificateChain (
619 d->organisational_unit (),
620 d->root_common_name (),
621 d->intermediate_common_name (),
622 d->leaf_common_name ()
627 update_certificate_list ();
628 update_private_key ();
635 CertificateChainEditor::update_sensitivity ()
637 /* We can only remove the leaf certificate */
638 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) == (_certificates->GetItemCount() - 1));
639 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
643 CertificateChainEditor::update_private_key ()
645 checked_set (_private_key, dcp::private_key_fingerprint (_get()->key().get()));
650 CertificateChainEditor::import_private_key ()
652 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
654 if (d->ShowModal() == wxID_OK) {
656 boost::filesystem::path p (wx_to_std (d->GetPath ()));
657 if (boost::filesystem::file_size (p) > 8192) {
660 wxString::Format (_("Could not read key file; file is too long (%s)"), std_to_wx (p.string ()))
665 shared_ptr<dcp::CertificateChain> chain(new dcp::CertificateChain(*_get().get()));
666 chain->set_key (dcp::file_to_string (p));
668 update_private_key ();
669 } catch (dcp::MiscError& e) {
670 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
676 update_sensitivity ();
680 CertificateChainEditor::export_private_key ()
682 boost::optional<std::string> key = _get()->key();
687 wxFileDialog* d = new wxFileDialog (
688 this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
689 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
692 if (d->ShowModal () == wxID_OK) {
693 FILE* f = fopen_boost (path_from_file_dialog (d, "pem"), "w");
695 throw OpenFileError (wx_to_std (d->GetPath ()), errno, false);
698 std::string const s = _get()->key().get ();
699 fwrite (s.c_str(), 1, s.length(), f);
706 KeysPage::GetName () const
714 wxFont subheading_font (*wxNORMAL_FONT);
715 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
717 wxSizer* sizer = _panel->GetSizer();
720 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Decrypting KDMs"));
721 m->SetFont (subheading_font);
722 sizer->Add (m, 0, wxALL, _border);
725 wxButton* export_decryption_certificate = new wxButton (_panel, wxID_ANY, _("Export KDM decryption certificate..."));
726 sizer->Add (export_decryption_certificate, 0, wxLEFT, _border);
727 wxButton* export_decryption_chain = new wxButton (_panel, wxID_ANY, _("Export KDM decryption chain..."));
728 sizer->Add (export_decryption_chain, 0, wxLEFT, _border);
729 wxButton* export_settings = new wxButton (_panel, wxID_ANY, _("Export all KDM decryption settings..."));
730 sizer->Add (export_settings, 0, wxLEFT, _border);
731 wxButton* import_settings = new wxButton (_panel, wxID_ANY, _("Import all KDM decryption settings..."));
732 sizer->Add (import_settings, 0, wxLEFT, _border);
733 wxButton* decryption_advanced = new wxButton (_panel, wxID_ANY, _("Advanced..."));
734 sizer->Add (decryption_advanced, 0, wxALL, _border);
736 export_decryption_certificate->Bind (wxEVT_BUTTON, bind (&KeysPage::export_decryption_certificate, this));
737 export_decryption_chain->Bind (wxEVT_BUTTON, bind (&KeysPage::export_decryption_chain, this));
738 export_settings->Bind (wxEVT_BUTTON, bind (&KeysPage::export_decryption_chain_and_key, this));
739 import_settings->Bind (wxEVT_BUTTON, bind (&KeysPage::import_decryption_chain_and_key, this));
740 decryption_advanced->Bind (wxEVT_BUTTON, bind (&KeysPage::decryption_advanced, this));
743 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Signing DCPs and KDMs"));
744 m->SetFont (subheading_font);
745 sizer->Add (m, 0, wxALL, _border);
748 wxButton* signing_advanced = new wxButton (_panel, wxID_ANY, _("Advanced..."));
749 sizer->Add (signing_advanced, 0, wxLEFT, _border);
750 signing_advanced->Bind (wxEVT_BUTTON, bind (&KeysPage::signing_advanced, this));
754 KeysPage::decryption_advanced ()
756 CertificateChainEditor* c = new CertificateChainEditor (
757 _panel, _("Decrypting KDMs"), _border,
758 bind (&Config::set_decryption_chain, Config::instance (), _1),
759 bind (&Config::decryption_chain, Config::instance ()),
760 bind (&KeysPage::nag_remake_decryption_chain, this)
767 KeysPage::signing_advanced ()
769 CertificateChainEditor* c = new CertificateChainEditor (
770 _panel, _("Signing DCPs and KDMs"), _border,
771 bind (&Config::set_signer_chain, Config::instance (), _1),
772 bind (&Config::signer_chain, Config::instance ()),
780 KeysPage::export_decryption_chain_and_key ()
782 wxFileDialog* d = new wxFileDialog (
783 _panel, _("Select Export File"), wxEmptyString, wxEmptyString, wxT ("DOM files (*.dom)|*.dom"),
784 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
787 if (d->ShowModal () == wxID_OK) {
788 FILE* f = fopen_boost (path_from_file_dialog (d, "dom"), "w");
790 throw OpenFileError (wx_to_std (d->GetPath ()), errno, false);
793 string const chain = Config::instance()->decryption_chain()->chain();
794 fwrite (chain.c_str(), 1, chain.length(), f);
795 optional<string> const key = Config::instance()->decryption_chain()->key();
796 DCPOMATIC_ASSERT (key);
797 fwrite (key->c_str(), 1, key->length(), f);
805 KeysPage::import_decryption_chain_and_key ()
807 wxFileDialog* d = new wxFileDialog (
808 _panel, _("Select File To Import"), wxEmptyString, wxEmptyString, wxT ("DOM files (*.dom)|*.dom")
811 if (d->ShowModal () == wxID_OK) {
812 shared_ptr<dcp::CertificateChain> new_chain(new dcp::CertificateChain());
814 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "r");
816 throw OpenFileError (wx_to_std (d->GetPath ()), errno, false);
822 if (fgets (buffer, 128, f) == 0) {
826 if (strncmp (buffer, "-----END CERTIFICATE-----", 25) == 0) {
827 new_chain->add (dcp::Certificate (current));
829 } else if (strncmp (buffer, "-----END RSA PRIVATE KEY-----", 29) == 0) {
830 std::cout << "the key is " << current << "\n";
831 new_chain->set_key (current);
837 if (new_chain->chain_valid() && new_chain->private_key_valid()) {
838 Config::instance()->set_decryption_chain (new_chain);
840 error_dialog (_panel, _("Invalid DCP-o-matic export file"));
847 KeysPage::nag_remake_decryption_chain ()
849 NagDialog::maybe_nag (
851 Config::NAG_REMAKE_DECRYPTION_CHAIN,
852 _("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!")
857 KeysPage::export_decryption_chain ()
859 wxFileDialog* d = new wxFileDialog (
860 _panel, _("Select Chain File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
861 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
864 if (d->ShowModal () == wxID_OK) {
865 FILE* f = fopen_boost (path_from_file_dialog (d, "pem"), "w");
867 throw OpenFileError (wx_to_std (d->GetPath ()), errno, false);
870 std::string const s = Config::instance()->decryption_chain()->chain();
871 fwrite (s.c_str(), 1, s.length(), f);
878 KeysPage::export_decryption_certificate ()
880 wxFileDialog* d = new wxFileDialog (
881 _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
882 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
885 if (d->ShowModal () == wxID_OK) {
886 FILE* f = fopen_boost (path_from_file_dialog (d, "pem"), "w");
888 throw OpenFileError (wx_to_std (d->GetPath ()), errno, false);
891 std::string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
892 fwrite (s.c_str(), 1, s.length(), f);