Display the filename / URL that a screen certificate was obtained from (#1894).
authorCarl Hetherington <cth@carlh.net>
Fri, 21 Jan 2022 22:39:03 +0000 (23:39 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 9 Mar 2022 16:04:02 +0000 (17:04 +0100)
20 files changed:
src/lib/dkdm_recipient.h
src/lib/internet.cc
src/lib/internet.h
src/lib/kdm_cli.cc
src/lib/kdm_recipient.cc
src/lib/kdm_recipient.h
src/lib/screen.h
src/wx/barco_alchemy_certificate_panel.cc
src/wx/christie_certificate_panel.cc
src/wx/dolby_doremi_certificate_panel.cc
src/wx/download_certificate_dialog.cc
src/wx/download_certificate_dialog.h
src/wx/download_certificate_panel.cc
src/wx/download_certificate_panel.h
src/wx/gdc_certificate_panel.cc
src/wx/qube_certificate_panel.cc
src/wx/screen_dialog.cc
src/wx/screen_dialog.h
src/wx/screens_panel.cc
test/kdm_naming_test.cc

index d08f82daafa0e618f5b63ffb71b4055099ed6f1f..50f2f3e15277ad6fba80d742c823aff35ff23508 100644 (file)
@@ -37,7 +37,7 @@ public:
                int utc_offset_hour_,
                int utc_offset_minute_
                )
-               : KDMRecipient (name_, notes_, recipient_)
+               : KDMRecipient (name_, notes_, recipient_, boost::none)
                , emails (emails_)
                , utc_offset_hour (utc_offset_hour_)
                , utc_offset_minute (utc_offset_minute_)
index 4fb6c7cb3132132c255042273f631a8e17bfb628..121d3524c7f4f83acbddd1df6d7cb3a8c6aba94a 100644 (file)
@@ -126,14 +126,14 @@ get_from_url (string url, bool pasv, bool skip_pasv_ip, ScopedTemporary& temp)
 
 
 optional<string>
-get_from_url (string url, bool pasv, bool skip_pasv_ip, function<optional<string> (boost::filesystem::path)> load)
+get_from_url (string url, bool pasv, bool skip_pasv_ip, function<optional<string> (boost::filesystem::path, string)> load)
 {
        ScopedTemporary temp;
        auto e = get_from_url (url, pasv, skip_pasv_ip, temp);
        if (e) {
                return e;
        }
-       return load (temp.file());
+       return load (temp.file(), url);
 }
 
 
@@ -142,7 +142,7 @@ get_from_url (string url, bool pasv, bool skip_pasv_ip, function<optional<string
  *  @param load Function passed a (temporary) filesystem path of the unpacked file.
  */
 optional<string>
-get_from_zip_url (string url, string file, bool pasv, bool skip_pasv_ip, function<optional<string> (boost::filesystem::path)> load)
+get_from_zip_url (string url, string file, bool pasv, bool skip_pasv_ip, function<optional<string> (boost::filesystem::path, string)> load)
 {
        /* Download the ZIP file to temp_zip */
        ScopedTemporary temp_zip;
@@ -199,5 +199,5 @@ get_from_zip_url (string url, string file, bool pasv, bool skip_pasv_ip, functio
        zip_close (zip);
        temp_cert.close ();
 
-       return load (temp_cert.file());
+       return load (temp_cert.file(), url);
 }
index f3cd2c6b4f908b63f6fba2c4331e643f8fb16c4c..041bb1bb13f4e48d1bc97b11ee7fabc3c2620cc6 100644 (file)
@@ -27,6 +27,20 @@ class ScopedTemporary;
 
 
 boost::optional<std::string> get_from_url (std::string url, bool pasv, bool skip_pasv_ip, ScopedTemporary& temp);
-boost::optional<std::string> get_from_url (std::string url, bool pasv, bool skip_pasv_ip, std::function<boost::optional<std::string> (boost::filesystem::path)> load);
-boost::optional<std::string> get_from_zip_url (std::string url, std::string file, bool pasv, bool skip_pasv_ip, std::function<boost::optional<std::string> (boost::filesystem::path)> load);
+
+boost::optional<std::string> get_from_url (
+       std::string url,
+       bool pasv,
+       bool skip_pasv_ip,
+       std::function<boost::optional<std::string> (boost::filesystem::path, std::string)> load
+       );
+
+boost::optional<std::string> get_from_zip_url (
+       std::string url,
+       std::string file,
+       bool pasv,
+       bool skip_pasv_ip,
+       std::function<boost::optional<std::string> (boost::filesystem::path, std::string)> load
+       );
+
 std::list<std::string> ls_url (std::string url);
index e6ba600f40121eeecc1857bb1aaee48fc19a64bc..0ec648e0489d1a9eb88db033fbfbe14e9d35731d 100644 (file)
@@ -540,7 +540,7 @@ try
                {
                        /* Make a new screen and add it to the current cinema */
                        dcp::CertificateChain chain (dcp::file_to_string(optarg));
-                       auto screen = make_shared<Screen>(screen_description, "", chain.leaf(), vector<TrustedDevice>());
+                       auto screen = std::make_shared<Screen>(screen_description, "", chain.leaf(), boost::none, vector<TrustedDevice>());
                        if (cinema) {
                                cinema->add_screen (screen);
                        }
index cde41e22d86162b158f6233a98a76141aa0a102a..671e9797c24cbfb40e2b9bdf509538d2cf1dc391 100644 (file)
@@ -31,6 +31,8 @@ KDMRecipient::KDMRecipient (cxml::ConstNodePtr node)
        } else if (node->optional_string_child("Recipient")) {
                recipient = dcp::Certificate (node->string_child("Recipient"));
        }
+
+       recipient_file = node->optional_string_child("RecipientFile");
 }
 
 
@@ -41,6 +43,9 @@ KDMRecipient::as_xml (xmlpp::Element* parent) const
        if (recipient) {
                parent->add_child("Recipient")->add_child_text(recipient->certificate(true));
        }
+       if (recipient_file) {
+               parent->add_child("RecipientFile")->add_child_text(*recipient_file);
+       }
 
        parent->add_child("Notes")->add_child_text(notes);
 }
index 85352f0ee7312bd6416c3303845efe241beccf41..90e9fd16dd079dc62df1e043e1d2aef71f8aaf01 100644 (file)
@@ -36,10 +36,11 @@ DCPOMATIC_ENABLE_WARNINGS
 class KDMRecipient
 {
 public:
-       KDMRecipient (std::string const& name_, std::string const& notes_, boost::optional<dcp::Certificate> recipient_)
+       KDMRecipient (std::string const& name_, std::string const& notes_, boost::optional<dcp::Certificate> recipient_, boost::optional<std::string> recipient_file_)
                : name (name_)
                , notes (notes_)
                , recipient (recipient_)
+               , recipient_file (recipient_file_)
        {}
 
        explicit KDMRecipient (cxml::ConstNodePtr);
@@ -51,6 +52,10 @@ public:
        std::string name;
        std::string notes;
        boost::optional<dcp::Certificate> recipient;
+       /** The pathname or URL that the recipient certificate was obtained from; purely
+        *  to inform the user.
+        */
+       boost::optional<std::string> recipient_file;
 };
 
 
index 15a0785d566c5292efa5e1ffff5c53a289ecb1b4..6103d207d9bffc0870edbd194cee96ab75d56936 100644 (file)
@@ -49,8 +49,14 @@ namespace dcpomatic {
 class Screen : public KDMRecipient
 {
 public:
-       Screen (std::string const & name_, std::string const & notes_, boost::optional<dcp::Certificate> recipient_, std::vector<TrustedDevice> trusted_devices_)
-               : KDMRecipient (name_, notes_, recipient_)
+       Screen (
+               std::string const & name_,
+               std::string const & notes_,
+               boost::optional<dcp::Certificate> recipient_,
+               boost::optional<std::string> recipient_file_,
+               std::vector<TrustedDevice> trusted_devices_
+              )
+               : KDMRecipient (name_, notes_, recipient_, recipient_file_)
                , trusted_devices (trusted_devices_)
        {}
 
index a1d6167aacf6ab553b85eda94c4806cc81f0b03c..981efee1f18990f5a6708794a99cdc3ba14b555c 100644 (file)
@@ -64,7 +64,7 @@ BarcoAlchemyCertificatePanel::do_download ()
                serial
                );
 
-       optional<string> error = get_from_url (url, true, false, boost::bind (&DownloadCertificatePanel::load_certificate, this, _1));
+       auto error = get_from_url (url, true, false, boost::bind (&DownloadCertificatePanel::load_certificate, this, _1, _2));
        if (error) {
                _dialog->message()->SetLabel(wxT(""));
                error_dialog (this, std_to_wx(*error));
index 4d9b1fcb71ab81961832a312519f13a5258f2576..77516fb8229d306f66c67345140ff217a0473868 100644 (file)
@@ -64,13 +64,13 @@ ChristieCertificatePanel::do_download ()
        optional<string> all_errors;
        bool ok = true;
 
-       optional<string> error = get_from_url (url, true, false, boost::bind(&DownloadCertificatePanel::load_certificate_from_chain, this, _1));
+       auto error = get_from_url (url, true, false, boost::bind(&DownloadCertificatePanel::load_certificate_from_chain, this, _1, _2));
        if (error) {
                all_errors = *error;
 
                auto const url = String::compose ("%1IMB-S2/IMB-S2_%2_sha256.pem", prefix, serial);
 
-               error = get_from_url (url, true, false, boost::bind(&DownloadCertificatePanel::load_certificate_from_chain, this, _1));
+               error = get_from_url (url, true, false, boost::bind(&DownloadCertificatePanel::load_certificate_from_chain, this, _1, _2));
                if (error) {
                        *all_errors += "\n" + *error;
                        ok = false;
index 817867cc108055bfb2d37d3747c6484047dbad24..db4cd9f6736be28cb0085385e307f83f52cb9eae 100644 (file)
@@ -199,7 +199,7 @@ DolbyDoremiCertificatePanel::do_download ()
        auto i = urls.begin ();
        auto j = files.begin ();
        while (!ok && i != urls.end ()) {
-               auto error = get_from_zip_url (*i++, *j++, true, true, boost::bind(&DownloadCertificatePanel::load_certificate, this, _1));
+               auto error = get_from_zip_url (*i++, *j++, true, true, boost::bind(&DownloadCertificatePanel::load_certificate, this, _1, _2));
                if (error) {
                        errors.push_back (error.get ());
                } else {
index 4a80dc9c03b0b4cb3e7ddaa22a9dd126e9ee6131..8f4720252f09975d0854b3cd614c682699335335 100644 (file)
@@ -30,6 +30,7 @@
 #include "wx_util.h"
 
 
+using std::string;
 using boost::optional;
 
 
@@ -102,6 +103,16 @@ DownloadCertificateDialog::certificate () const
        return *c;
 }
 
+
+string
+DownloadCertificateDialog::url () const
+{
+       auto u = _pages[_notebook->GetSelection()]->url();
+       DCPOMATIC_ASSERT (u);
+       return *u;
+}
+
+
 void
 DownloadCertificateDialog::setup_sensitivity ()
 {
index ef241a0cab5d046ba9b2edcfed25af74a6f34627..a5085e174fe2035945958b736719ba4004425dca 100644 (file)
@@ -34,6 +34,7 @@ public:
        ~DownloadCertificateDialog ();
 
        dcp::Certificate certificate () const;
+       std::string url () const;
 
        void setup_sensitivity ();
 
index c30b050081db913327807ff6ec36ae66fa075892..b3de4ca2c427e16aa8981dd78ff13432073adae7 100644 (file)
@@ -58,10 +58,11 @@ DownloadCertificatePanel::DownloadCertificatePanel (DownloadCertificateDialog* d
 
 
 optional<string>
-DownloadCertificatePanel::load_certificate (boost::filesystem::path file)
+DownloadCertificatePanel::load_certificate (boost::filesystem::path file, string url)
 {
        try {
                _certificate = dcp::Certificate (dcp::file_to_string(file));
+               _url = url;
        } catch (dcp::MiscError& e) {
                return String::compose(wx_to_std(_("Could not read certificate file (%1)")), e.what());
        }
@@ -70,10 +71,11 @@ DownloadCertificatePanel::load_certificate (boost::filesystem::path file)
 
 
 optional<string>
-DownloadCertificatePanel::load_certificate_from_chain (boost::filesystem::path file)
+DownloadCertificatePanel::load_certificate_from_chain (boost::filesystem::path file, string url)
 {
        try {
                _certificate = dcp::CertificateChain (dcp::file_to_string(file)).leaf();
+               _url = url;
        } catch (dcp::MiscError& e) {
                return String::compose(wx_to_std(_("Could not read certificate file (%1)")), e.what());
        }
@@ -88,6 +90,14 @@ DownloadCertificatePanel::certificate () const
 
 }
 
+
+optional<string>
+DownloadCertificatePanel::url () const
+{
+       return _url;
+
+}
+
 void
 DownloadCertificatePanel::download ()
 {
index 25271c7701dbb21ab26be7087f9c8bc23520e89f..0e7b2ab713198f6ffa5049027156874b24d94221 100644 (file)
@@ -44,9 +44,10 @@ public:
        virtual bool ready_to_download () const;
 
        void download ();
-       boost::optional<std::string> load_certificate (boost::filesystem::path);
-       boost::optional<std::string> load_certificate_from_chain (boost::filesystem::path);
+       boost::optional<std::string> load_certificate (boost::filesystem::path, std::string url);
+       boost::optional<std::string> load_certificate_from_chain (boost::filesystem::path, std::string url);
        boost::optional<dcp::Certificate> certificate () const;
+       boost::optional<std::string> url () const;
 
 protected:
        DownloadCertificateDialog* _dialog;
@@ -56,6 +57,7 @@ protected:
 
 private:
        boost::optional<dcp::Certificate> _certificate;
+       boost::optional<std::string> _url;
 };
 
 
index f7f86895df931eaaf307d0277a2b1c2914d74465..e670f01eb4815f543a07cf96ac061e88ef89f031 100644 (file)
@@ -61,7 +61,7 @@ GDCCertificatePanel::do_download ()
                serial
                );
 
-       optional<string> error = get_from_url (url, true, false, boost::bind(&DownloadCertificatePanel::load_certificate, this, _1));
+       auto error = get_from_url (url, true, false, boost::bind(&DownloadCertificatePanel::load_certificate, this, _1, _2));
 
        if (error) {
                _dialog->message()->SetLabel(wxT(""));
index e1c6bfb41ae2c4dca09c902efadc38d7544fc9aa..8e9662e7d3ae24508400df4b0173e7a4ad205eec 100644 (file)
@@ -71,7 +71,7 @@ QubeCertificatePanel::do_download ()
                return;
        }
 
-       auto error = get_from_url (String::compose("%1SMPTE-%2/%3", base, _type, *name), true, false, boost::bind(&DownloadCertificatePanel::load_certificate, this, _1));
+       auto error = get_from_url (String::compose("%1SMPTE-%2/%3", base, _type, *name), true, false, boost::bind(&DownloadCertificatePanel::load_certificate, this, _1, _2));
 
        if (error) {
                _dialog->message()->SetLabel(wxT(""));
index 3148d09d91218dc43c1bef4c36f573b2902681a0..af5e25f476ba19d1998f2561b7c909df439e9b51 100644 (file)
@@ -102,7 +102,13 @@ private:
 
 
 ScreenDialog::ScreenDialog (
-       wxWindow* parent, wxString title, string name, string notes, optional<dcp::Certificate> recipient, vector<TrustedDevice> trusted_devices
+       wxWindow* parent,
+       wxString title,
+       string name,
+       string notes,
+       optional<dcp::Certificate> recipient,
+       optional<string> recipient_file,
+       vector<TrustedDevice> trusted_devices
        )
        : wxDialog (parent, wxID_ANY, title)
        , _recipient (recipient)
@@ -136,15 +142,31 @@ ScreenDialog::ScreenDialog (
        _recipient_thumbprint = new StaticText (this, wxT (""), wxDefaultPosition, size);
        _recipient_thumbprint->SetFont (font);
        set_recipient (recipient);
+
        _get_recipient_from_file = new Button (this, _("Get from file..."));
        _download_recipient = new Button (this, _("Download..."));
-       s->Add (_recipient_thumbprint, 1, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_X_GAP);
+       s->Add (_recipient_thumbprint, 1, wxRIGHT | wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT, DCPOMATIC_SIZER_X_GAP);
        s->Add (_get_recipient_from_file, 0, wxLEFT | wxRIGHT | wxEXPAND, DCPOMATIC_SIZER_X_GAP);
        s->Add (_download_recipient, 0, wxLEFT | wxRIGHT | wxEXPAND, DCPOMATIC_SIZER_X_GAP);
        _sizer->Add (s, wxGBPosition (r, 1));
        ++r;
 
-       add_label_to_sizer (_sizer, this, _("Other trusted devices"), true, wxGBPosition (r, 0));
+       add_label_to_sizer (_sizer, this, _("Filename"), true, wxGBPosition(r, 0));
+       _recipient_file = new wxStaticText (this, wxID_ANY, wxT(""));
+       checked_set (_recipient_file, recipient_file.get_value_or(""));
+       _sizer->Add (_recipient_file, wxGBPosition(r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_Y_GAP);
+       ++r;
+
+       {
+               int flags = wxALIGN_CENTER_VERTICAL | wxTOP;
+#ifdef __WXOSX__
+               flags |= wxALIGN_RIGHT;
+               auto m = new StaticText (this, _("Other trusted devices") + wxT(":"));
+#else
+               auto m = new StaticText (this, _("Other trusted devices"));
+#endif
+               _sizer->Add (m, wxGBPosition(r, 0), wxDefaultSpan, flags, DCPOMATIC_SIZER_Y_GAP);
+       }
        ++r;
 
        vector<EditableListColumn> columns;
@@ -202,6 +224,17 @@ ScreenDialog::recipient () const
 }
 
 
+optional<string>
+ScreenDialog::recipient_file () const
+{
+       auto const f = wx_to_std(_recipient_file->GetLabel());
+       if (f.empty()) {
+               return {};
+       }
+       return f;
+}
+
+
 void
 ScreenDialog::load_recipient (boost::filesystem::path file)
 {
@@ -213,6 +246,7 @@ ScreenDialog::load_recipient (boost::filesystem::path file)
                        return;
                }
                set_recipient (c.leaf ());
+               checked_set (_recipient_file, file.string());
        } catch (dcp::MiscError& e) {
                error_dialog (this, _("Could not read certificate file."), std_to_wx(e.what()));
        }
@@ -238,6 +272,7 @@ ScreenDialog::download_recipient ()
        auto d = new DownloadCertificateDialog (this);
        if (d->ShowModal() == wxID_OK) {
                set_recipient (d->certificate());
+               checked_set (_recipient_file, d->url());
        }
        d->Destroy ();
        setup_sensitivity ();
index 49e4d092a6721a747fecd1f548c2850975c827d1..fcb3fba5d651b00c6f1adb0c220cb24724efa051 100644 (file)
@@ -38,13 +38,15 @@ public:
                wxString,
                std::string name = "",
                std::string notes = "",
-               boost::optional<dcp::Certificate> c = boost::optional<dcp::Certificate>(),
-               std::vector<TrustedDevice> d = std::vector<TrustedDevice>()
+               boost::optional<dcp::Certificate> c = {},
+               boost::optional<std::string> f = {},
+               std::vector<TrustedDevice> d = {}
                );
 
        std::string name () const;
        std::string notes () const;
        boost::optional<dcp::Certificate> recipient () const;
+       boost::optional<std::string> recipient_file () const;
        std::vector<TrustedDevice> trusted_devices () {
                return _trusted_devices;
        }
@@ -64,6 +66,7 @@ private:
        wxTextCtrl* _name;
        wxTextCtrl* _notes;
        wxStaticText* _recipient_thumbprint;
+       wxStaticText* _recipient_file;
        wxButton* _get_recipient_from_file;
        wxButton* _download_recipient;
        EditableList<TrustedDevice, TrustedDeviceDialog>* _trusted_device_list;
index 8d631ce905257d7ef625c34c74abc81459d19fb5..3c8d519312734649ff2dc4c5dad8f134d87e95a2 100644 (file)
@@ -261,7 +261,7 @@ ScreensPanel::add_screen_clicked ()
                }
        }
 
-       auto s = std::make_shared<Screen>(d->name(), d->notes(), d->recipient(), d->trusted_devices());
+       auto s = std::make_shared<Screen>(d->name(), d->notes(), d->recipient(), d->recipient_file(), d->trusted_devices());
        c->add_screen (s);
        auto id = add_screen (c, s);
        if (id) {
@@ -283,7 +283,7 @@ ScreensPanel::edit_screen_clicked ()
 
        auto s = *_selected_screens.begin();
 
-       auto d = new ScreenDialog (GetParent(), _("Edit screen"), s.second->name, s.second->notes, s.second->recipient, s.second->trusted_devices);
+       auto d = new ScreenDialog (GetParent(), _("Edit screen"), s.second->name, s.second->notes, s.second->recipient, s.second->recipient_file, s.second->trusted_devices);
        if (d->ShowModal() != wxID_OK) {
                d->Destroy ();
                return;
@@ -306,6 +306,7 @@ ScreensPanel::edit_screen_clicked ()
        s.second->name = d->name ();
        s.second->notes = d->notes ();
        s.second->recipient = d->recipient ();
+       s.second->recipient_file = d->recipient_file ();
        s.second->trusted_devices = d->trusted_devices ();
        _targets->SetItemText (s.first, std_to_wx (d->name()));
        Config::instance()->changed (Config::CINEMAS);
index 4e1f81b1c29060110bb7290afd18e8896e4b1136..c41d5c31513b481ecbe1dcaa08e151c77d6621db 100644 (file)
@@ -61,19 +61,19 @@ BOOST_AUTO_TEST_CASE (single_kdm_naming_test)
 
        /* Cinema A: UTC +4:30 */
        auto cinema_a = make_shared<Cinema>("Cinema A", list<string>(), "", 4, 30);
-       cinema_a_screen_1 = make_shared<dcpomatic::Screen>("Screen 1", "", crypt_cert, vector<TrustedDevice>());
+       cinema_a_screen_1 = std::make_shared<dcpomatic::Screen>("Screen 1", "", crypt_cert, boost::none, vector<TrustedDevice>());
        cinema_a->add_screen (cinema_a_screen_1);
-       cinema_a_screen_2 = make_shared<dcpomatic::Screen>("Screen 2", "", crypt_cert, vector<TrustedDevice>());
+       cinema_a_screen_2 = std::make_shared<dcpomatic::Screen>("Screen 2", "", crypt_cert, boost::none, vector<TrustedDevice>());
        cinema_a->add_screen (cinema_a_screen_2);
        c->add_cinema (cinema_a);
 
        /* Cinema B: UTC -1:00 */
        auto cinema_b = make_shared<Cinema>("Cinema B", list<string>(), "", -1, 0);
-       cinema_b_screen_x = make_shared<dcpomatic::Screen>("Screen X", "", crypt_cert, vector<TrustedDevice>());
+       cinema_b_screen_x = std::make_shared<dcpomatic::Screen>("Screen X", "", crypt_cert, boost::none, vector<TrustedDevice>());
        cinema_b->add_screen (cinema_b_screen_x);
-       cinema_b_screen_y = make_shared<dcpomatic::Screen>("Screen Y", "", crypt_cert, vector<TrustedDevice>());
+       cinema_b_screen_y = std::make_shared<dcpomatic::Screen>("Screen Y", "", crypt_cert, boost::none, vector<TrustedDevice>());
        cinema_b->add_screen (cinema_b_screen_y);
-       cinema_b_screen_z = make_shared<dcpomatic::Screen>("Screen Z", "", crypt_cert, vector<TrustedDevice>());
+       cinema_b_screen_z = std::make_shared<dcpomatic::Screen>("Screen Z", "", crypt_cert, boost::none, vector<TrustedDevice>());
        cinema_b->add_screen (cinema_b_screen_z);
        c->add_cinema (cinema_a);