Lots of #include <iostream>s for Arch.
[dcpomatic.git] / src / wx / dolby_certificate_dialog.cc
index d44c9e737816a61c8069fd6a2f383bbf51ef2da3..58ad73e0d2a25c0635ac7e208e78719a89e893f0 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2014-2015 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
 
 */
 
-#include <curl/curl.h>
-#include "lib/compose.hpp"
 #include "dolby_certificate_dialog.h"
 #include "wx_util.h"
+#include "lib/compose.hpp"
+#include "lib/internet.h"
+#include "lib/signal_manager.h"
+#include <curl/curl.h>
+#include <boost/algorithm/string.hpp>
+#include <boost/foreach.hpp>
+#include <iostream>
 
 using std::list;
 using std::string;
-using std::stringstream;
+using std::vector;
 using std::cout;
+using boost::optional;
+using boost::algorithm::split;
+using boost::algorithm::is_any_of;
 
 DolbyCertificateDialog::DolbyCertificateDialog (wxWindow* parent, boost::function<void (boost::filesystem::path)> load)
        : DownloadCertificateDialog (parent, load)
 {
-       wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
-
-       _country = new wxChoice (this, wxID_ANY);
-       add_label_to_sizer (table, this, _("Country"), true);
-       table->Add (_country, 1, wxEXPAND | wxLEFT | wxRIGHT, DCPOMATIC_SIZER_X_GAP);
+       add (_("Country"), true);
+       _country = add (new wxChoice (this, wxID_ANY));
        _country->Append (N_("Hashemite Kingdom of Jordan"));
-       
-       _cinema = new wxChoice (this, wxID_ANY);
-       add_label_to_sizer (table, this, _("Cinema"), true);
-       table->Add (_cinema, 1, wxEXPAND | wxLEFT | wxRIGHT, DCPOMATIC_SIZER_X_GAP);
-       _cinema->Append (N_("Wometco Dominicana Palacio Del Cine"));
-       _overall_sizer->Add (table);
+
+       add (_("Cinema"), true);
+       _cinema = add (new wxChoice (this, wxID_ANY));
+       _cinema->Append (N_("Motion Picture Solutions London Mobile & QC"));
+
+       add (_("Serial number"), true);
+       _serial = add (new wxChoice (this, wxID_ANY));
 
        add_common_widgets ();
 
        _country->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DolbyCertificateDialog::country_selected, this));
        _cinema->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DolbyCertificateDialog::cinema_selected, this));
+       _serial->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DolbyCertificateDialog::serial_selected, this));
+       Bind (wxEVT_IDLE, boost::bind (&DolbyCertificateDialog::setup_countries, this));
 
        _country->Clear ();
        _cinema->Clear ();
 }
 
-static size_t
-ftp_data_ls (void* buffer, size_t size, size_t nmemb, void* data)
-{
-       string* s = reinterpret_cast<string *> (data);
-       uint8_t* b = reinterpret_cast<uint8_t *> (buffer);
-       for (size_t i = 0; i < (size * nmemb); ++i) {
-               *s += b[i];
-       }
-       return nmemb;
-}
-
 list<string>
-DolbyCertificateDialog::ftp_ls (string dir) const
+DolbyCertificateDialog::get_dir (string dir) const
 {
-       CURL* curl = curl_easy_init ();
-       if (!curl) {
-               _message->SetLabel (N_("Could not set up libcurl"));
-               return list<string> ();
-       }
-
        string url = String::compose ("ftp://dolbyrootcertificates:houro61l@ftp.dolby.co.uk/SHA256/%1", dir);
-       if (url.substr (url.length() - 1, 1) != "/") {
-               url += "/";
-       }
-       curl_easy_setopt (curl, CURLOPT_URL, url.c_str ());
-
-       string ls_raw;
-       struct curl_slist* commands = 0;
-       commands = curl_slist_append (commands, "NLST");
-       curl_easy_setopt (curl, CURLOPT_POSTQUOTE, commands);
-       curl_easy_setopt (curl, CURLOPT_WRITEDATA, &ls_raw);
-       curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ftp_data_ls);
-       curl_easy_setopt (curl, CURLOPT_FTP_USE_EPSV, 0);
-       CURLcode const r = curl_easy_perform (curl);
-       if (r != CURLE_OK) {
-               _message->SetLabel (_("Problem occurred when contacting Dolby."));
-               return list<string> ();
-       }
+       return ftp_ls (url);
+}
 
-       stringstream s (ls_raw);
-       string line;
-       list<string> ls;
-       while (s.good ()) {
-               getline (s, line);
-               if (line.length() > 55) {
-                       string const file = line.substr (55);
-                       if (file != "." && file != "..") {
-                               ls.push_back (file);
-                       }
-               }
+void
+DolbyCertificateDialog::setup_countries ()
+{
+       if (_country->GetCount() > 0) {
+               /* Already set up */
+               return;
        }
 
-       curl_easy_cleanup (curl);
+       _country->Append (_("Fetching..."));
+       _country->SetSelection (0);
 
-       return ls;
+#ifdef DCPOMATIC_OSX
+       /* See DoremiCertificateDialog for discussion about this daft delay */
+       wxMilliSleep (200);
+#endif
+       signal_manager->when_idle (boost::bind (&DolbyCertificateDialog::finish_setup_countries, this));
 }
 
 void
-DolbyCertificateDialog::setup ()
+DolbyCertificateDialog::finish_setup_countries ()
 {
-       _message->SetLabel (_("Fetching available countries"));
-       run_gui_loop ();
-       list<string> const countries = ftp_ls ("");
-       for (list<string>::const_iterator i = countries.begin(); i != countries.end(); ++i) {
-               _country->Append (std_to_wx (*i));
+       _country->Clear ();
+       BOOST_FOREACH (string i, get_dir ("")) {
+               _country->Append (std_to_wx (i));
        }
-       _message->SetLabel ("");
 }
 
 void
 DolbyCertificateDialog::country_selected ()
 {
-       _message->SetLabel (_("Fetching available cinemas"));
-       run_gui_loop ();
-       list<string> const cinemas = ftp_ls (wx_to_std (_country->GetStringSelection()));
        _cinema->Clear ();
-       for (list<string>::const_iterator i = cinemas.begin(); i != cinemas.end(); ++i) {
-               _cinema->Append (std_to_wx (*i));
+       _cinema->Append (_("Fetching..."));
+       _cinema->SetSelection (0);
+
+#ifdef DCPOMATIC_OSX
+       wxMilliSleep (200);
+#endif
+       signal_manager->when_idle (boost::bind (&DolbyCertificateDialog::finish_country_selected, this));
+}
+
+void
+DolbyCertificateDialog::finish_country_selected ()
+{
+       _cinema->Clear ();
+       BOOST_FOREACH (string i, get_dir (wx_to_std (_country->GetStringSelection()))) {
+               _cinema->Append (std_to_wx (i));
        }
-       _message->SetLabel ("");
 }
 
 void
 DolbyCertificateDialog::cinema_selected ()
+{
+       _serial->Clear ();
+       _serial->Append (_("Fetching..."));
+       _serial->SetSelection (0);
+
+#ifdef DCPOMATIC_OSX
+       wxMilliSleep (200);
+#endif
+       signal_manager->when_idle (boost::bind (&DolbyCertificateDialog::finish_cinema_selected, this));
+}
+
+void
+DolbyCertificateDialog::finish_cinema_selected ()
+{
+       string const dir = String::compose ("%1/%2", wx_to_std (_country->GetStringSelection()), wx_to_std (_cinema->GetStringSelection()));
+
+       _serial->Clear ();
+       BOOST_FOREACH (string i, get_dir (dir)) {
+               vector<string> a;
+               split (a, i, is_any_of ("-_"));
+               if (a.size() >= 4) {
+                       _serial->Append (std_to_wx (a[3]), new wxStringClientData (std_to_wx (i)));
+               }
+       }
+}
+
+void
+DolbyCertificateDialog::serial_selected ()
 {
        _download->Enable (true);
 }
@@ -143,5 +153,42 @@ DolbyCertificateDialog::cinema_selected ()
 void
 DolbyCertificateDialog::download ()
 {
+       downloaded (false);
+       _message->SetLabel (_("Downloading certificate"));
+
+#ifdef DCPOMATIC_OSX
+       wxMilliSleep (200);
+#endif
+
+       signal_manager->when_idle (boost::bind (&DolbyCertificateDialog::finish_download, this));
+}
 
+void
+DolbyCertificateDialog::finish_download ()
+{
+       string const zip = string_client_data (_serial->GetClientObject (_serial->GetSelection ()));
+
+       string const file = String::compose (
+               "ftp://dolbyrootcertificates:houro61l@ftp.dolby.co.uk/SHA256/%1/%2/%3",
+               wx_to_std (_country->GetStringSelection()),
+               wx_to_std (_cinema->GetStringSelection()),
+               zip
+               );
+
+       /* Work out the certificate file name inside the zip */
+       vector<string> b;
+       split (b, zip, is_any_of ("_"));
+       if (b.size() < 2) {
+               _message->SetLabel (_("Unexpected certificate filename form"));
+               return;
+       }
+       string const cert = b[0] + "_" + b[1] + ".pem.crt";
+
+       optional<string> error = get_from_zip_url (file, cert, _load);
+       if (error) {
+               _message->SetLabel (std_to_wx (error.get ()));
+       } else {
+               _message->SetLabel (_("Certificate downloaded"));
+               downloaded (true);
+       }
 }