diff options
| author | Carl Hetherington <cth@carlh.net> | 2014-03-25 15:24:13 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2014-03-25 15:24:13 +0000 |
| commit | 0a62857e4412d294712cfdf227fa38ae9ef371fe (patch) | |
| tree | a5e32cdc0fc69acf6b36ef84fb6a3f525f03ac14 /src | |
| parent | 68215e4e2dc313b74da7bde187917add138d3c9f (diff) | |
Add support for downloading Doremi server certificates.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/util.cc | 35 | ||||
| -rw-r--r-- | src/lib/util.h | 18 | ||||
| -rw-r--r-- | src/wx/progress.cc | 60 | ||||
| -rw-r--r-- | src/wx/progress.h | 38 | ||||
| -rw-r--r-- | src/wx/screen_dialog.cc | 134 | ||||
| -rw-r--r-- | src/wx/screen_dialog.h | 14 | ||||
| -rw-r--r-- | src/wx/wscript | 1 |
7 files changed, 286 insertions, 14 deletions
diff --git a/src/lib/util.cc b/src/lib/util.cc index 85c52b039..7a19790eb 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -1030,3 +1030,38 @@ divide_with_round (int64_t a, int64_t b) return a / b; } } + +ScopedTemporary::ScopedTemporary () + : _open (0) +{ + _file = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path (); +} + +ScopedTemporary::~ScopedTemporary () +{ + close (); + boost::system::error_code ec; + boost::filesystem::remove (_file, ec); +} + +char const * +ScopedTemporary::c_str () const +{ + return _file.string().c_str (); +} + +FILE* +ScopedTemporary::open (char const * params) +{ + _open = fopen (c_str(), params); + return _open; +} + +void +ScopedTemporary::close () +{ + if (_open) { + fclose (_open); + _open = 0; + } +} diff --git a/src/lib/util.h b/src/lib/util.h index c05680859..0bbab8305 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -176,6 +176,24 @@ private: char* _old; }; +class ScopedTemporary +{ +public: + ScopedTemporary (); + ~ScopedTemporary (); + + boost::filesystem::path file () const { + return _file; + } + + char const * c_str () const; + FILE* open (char const *); + void close (); + +private: + boost::filesystem::path _file; + FILE* _open; +}; #endif diff --git a/src/wx/progress.cc b/src/wx/progress.cc new file mode 100644 index 000000000..9e3da6c41 --- /dev/null +++ b/src/wx/progress.cc @@ -0,0 +1,60 @@ +/* + Copyright (C) 2014 Carl Hetherington <cth@carlh.net> + + This program 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. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <string> +#include "progress.h" +#include "wx_util.h" + +using std::string; + +Progress::Progress (wxWindow* parent) + : wxPanel (parent, wxID_ANY) +{ + wxBoxSizer* s = new wxBoxSizer (wxVERTICAL); + + _gauge = new wxGauge (this, wxID_ANY, 100); + s->Add (_gauge, 1, wxEXPAND); + _label = new wxStaticText (this, wxID_ANY, wxT ("")); + s->Add (_label, 1, wxEXPAND); + + SetSizerAndFit (s); +} + +void +Progress::set_value (int v) +{ + _gauge->SetValue (v); + run_gui_loop (); +} + +void +Progress::set_message (wxString s) +{ + _label->SetLabel (s); + run_gui_loop (); +} + +void +Progress::run_gui_loop () +{ + while (wxTheApp->Pending ()) { + wxTheApp->Dispatch (); + } +} + diff --git a/src/wx/progress.h b/src/wx/progress.h new file mode 100644 index 000000000..9ce3243fb --- /dev/null +++ b/src/wx/progress.h @@ -0,0 +1,38 @@ +/* + Copyright (C) 2014 Carl Hetherington <cth@carlh.net> + + This program 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. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <wx/wx.h> + +class Progress : public wxPanel +{ +public: + Progress (wxWindow* parent); + + /** Set progress value. + * @param v Progress from 0 to 100. + */ + void set_value (int v); + void set_message (wxString); + +private: + void run_gui_loop (); + + wxGauge* _gauge; + wxStaticText* _label; +}; diff --git a/src/wx/screen_dialog.cc b/src/wx/screen_dialog.cc index 32a0bce43..b077a9bf9 100644 --- a/src/wx/screen_dialog.cc +++ b/src/wx/screen_dialog.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,10 +19,14 @@ #include <wx/filepicker.h> #include <wx/validate.h> +#include <curl/curl.h> +#include <zip.h> #include <libdcp/exceptions.h> #include "lib/compose.hpp" +#include "lib/util.h" #include "screen_dialog.h" #include "wx_util.h" +#include "progress.h" using std::string; using std::cout; @@ -39,9 +43,25 @@ ScreenDialog::ScreenDialog (wxWindow* parent, string title, string name, shared_ _name = new wxTextCtrl (this, wxID_ANY, std_to_wx (name), wxDefaultPosition, wxSize (320, -1)); table->Add (_name, 1, wxEXPAND); + add_label_to_sizer (table, this, "Server manufacturer", true); + _manufacturer = new wxChoice (this, wxID_ANY); + table->Add (_manufacturer, 1, wxEXPAND); + + add_label_to_sizer (table, this, "Server serial number", true); + _serial = new wxTextCtrl (this, wxID_ANY); + table->Add (_serial, 1, wxEXPAND); + add_label_to_sizer (table, this, "Certificate", true); - _certificate_load = new wxButton (this, wxID_ANY, wxT ("Load from file...")); - table->Add (_certificate_load, 1, wxEXPAND); + wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); + _load_certificate = new wxButton (this, wxID_ANY, _("Load from file...")); + _download_certificate = new wxButton (this, wxID_ANY, _("Download")); + s->Add (_load_certificate, 1, wxEXPAND); + s->Add (_download_certificate, 1, wxEXPAND); + table->Add (s, 1, wxEXPAND); + + table->AddSpacer (0); + _progress = new Progress (this); + table->Add (_progress, 1, wxEXPAND); table->AddSpacer (0); _certificate_text = new wxTextCtrl (this, wxID_ANY, wxT (""), wxDefaultPosition, wxSize (320, 256), wxTE_MULTILINE | wxTE_READONLY); @@ -65,7 +85,15 @@ ScreenDialog::ScreenDialog (wxWindow* parent, string title, string name, shared_ overall_sizer->Layout (); overall_sizer->SetSizeHints (this); - _certificate_load->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&ScreenDialog::load_certificate, this)); + _manufacturer->Append (_("Unknown")); + _manufacturer->Append (_("Doremi")); + _manufacturer->Append (_("Other")); + _manufacturer->SetSelection (0); + + _load_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&ScreenDialog::select_certificate, this)); + _download_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&ScreenDialog::download_certificate, this)); + _manufacturer->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&ScreenDialog::setup_sensitivity, this)); + _serial->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&ScreenDialog::setup_sensitivity, this)); setup_sensitivity (); } @@ -83,17 +111,23 @@ ScreenDialog::certificate () const } void -ScreenDialog::load_certificate () +ScreenDialog::load_certificate (boost::filesystem::path file) +{ + try { + _certificate.reset (new libdcp::Certificate (file)); + _certificate_text->SetValue (_certificate->certificate ()); + } catch (libdcp::MiscError& e) { + error_dialog (this, String::compose ("Could not read certificate file (%1)", e.what())); + } +} + +void +ScreenDialog::select_certificate () { wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File")); if (d->ShowModal () == wxID_OK) { - try { - _certificate.reset (new libdcp::Certificate (boost::filesystem::path (wx_to_std (d->GetPath ())))); - _certificate_text->SetValue (_certificate->certificate ()); - } catch (libdcp::MiscError& e) { - error_dialog (this, String::compose ("Could not read certificate file (%1)", e.what())); - } + load_certificate (boost::filesystem::path (wx_to_std (d->GetPath ()))); } d->Destroy (); @@ -101,9 +135,87 @@ ScreenDialog::load_certificate () setup_sensitivity (); } +static size_t +ftp_data (void* buffer, size_t size, size_t nmemb, void* stream) +{ + FILE* f = reinterpret_cast<FILE*> (stream); + return fwrite (buffer, size, nmemb, f); +} + +void +ScreenDialog::download_certificate () +{ + if (_manufacturer->GetStringSelection() == _("Doremi")) { + string const serial = wx_to_std (_serial->GetValue ()); + if (serial.length() != 6) { + error_dialog (this, _("Doremi serial numbers must have 6 numbers")); + return; + } + + CURL* curl = curl_easy_init (); + if (!curl) { + error_dialog (this, N_("Could not set up libcurl")); + return; + } + + string const url = String::compose ( + "ftp://service:t3chn1c1an@ftp.doremilabs.com/Certificates/%1xxx/dcp2000-%2.dcicerts.zip", + serial.substr(0, 3), serial + ); + + curl_easy_setopt (curl, CURLOPT_URL, url.c_str ()); + + ScopedTemporary temp_zip; + FILE* f = temp_zip.open ("wb"); + curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ftp_data); + curl_easy_setopt (curl, CURLOPT_WRITEDATA, f); + _progress->set_message (_("Downloading certificate from Doremi")); + CURLcode const cr = curl_easy_perform (curl); + _progress->set_value (50); + temp_zip.close (); + curl_easy_cleanup (curl); + if (cr != CURLE_OK) { + _progress->set_message (wxString::Format (_("Certificate download failed (%d)"), cr)); + return; + } + + _progress->set_message (_("Unpacking")); + struct zip* zip = zip_open (temp_zip.c_str(), 0, 0); + if (!zip) { + _progress->set_message ("Could not open certificate ZIP file"); + return; + } + + string const name_in_zip = String::compose ("dcp2000-%1.cert.sha256.pem", serial); + struct zip_file* zip_file = zip_fopen (zip, name_in_zip.c_str(), 0); + if (!zip_file) { + _progress->set_message ("Could not find certificate in ZIP file"); + return; + } + + ScopedTemporary temp_cert; + f = temp_cert.open ("wb"); + char buffer[4096]; + while (1) { + int const N = zip_fread (zip_file, buffer, sizeof (buffer)); + fwrite (buffer, 1, N, f); + if (N < int (sizeof (buffer))) { + break; + } + } + temp_cert.close (); + + _progress->set_value (100); + _progress->set_message (_("OK")); + load_certificate (temp_cert.file ()); + } +} + void ScreenDialog::setup_sensitivity () { wxButton* ok = dynamic_cast<wxButton*> (FindWindowById (wxID_OK, this)); ok->Enable (_certificate); + + _download_certificate->Enable (_manufacturer->GetStringSelection() == _("Doremi") && !_serial->GetValue().IsEmpty ()); } diff --git a/src/wx/screen_dialog.h b/src/wx/screen_dialog.h index 271ae2055..1fcc8d564 100644 --- a/src/wx/screen_dialog.h +++ b/src/wx/screen_dialog.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,6 +21,8 @@ #include <boost/shared_ptr.hpp> #include <libdcp/certificates.h> +class Progress; + class ScreenDialog : public wxDialog { public: @@ -30,11 +32,17 @@ public: boost::shared_ptr<libdcp::Certificate> certificate () const; private: - void load_certificate (); + void select_certificate (); + void load_certificate (boost::filesystem::path); + void download_certificate (); void setup_sensitivity (); wxTextCtrl* _name; - wxButton* _certificate_load; + wxChoice* _manufacturer; + wxTextCtrl* _serial; + Progress* _progress; + wxButton* _load_certificate; + wxButton* _download_certificate; wxTextCtrl* _certificate_text; boost::shared_ptr<libdcp::Certificate> _certificate; diff --git a/src/wx/wscript b/src/wx/wscript index 1ffaa6097..56476c4ce 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -29,6 +29,7 @@ sources = """ kdm_dialog.cc new_film_dialog.cc preset_colour_conversion_dialog.cc + progress.cc properties_dialog.cc repeat_dialog.cc screen_dialog.cc |
