Bump version
[libdcp.git] / src / signer_chain.cc
index 78a8f2843d8adcc886ecd53fb76f197cb0fcb3da..f35e4ff61732c8f8d957455144d26f1e4ab2ab9b 100644 (file)
@@ -35,16 +35,48 @@ using std::ifstream;
 using std::stringstream;
 using std::cout;
 
-static void command (string c)
+static void command (string cmd)
 {
-       int const r = system (c.c_str ());
-#ifdef LIBDCP_WINDOWS  
-       if (r) {
+#ifdef LIBDCP_WINDOWS
+       /* We need to use CreateProcessW on Windows so that the UTF-8/16 mess
+          is handled correctly.
+       */
+       int const wn = MultiByteToWideChar (CP_UTF8, 0, cmd.c_str(), -1, 0, 0);
+       wchar_t* buffer = new wchar_t[wn];
+       if (MultiByteToWideChar (CP_UTF8, 0, cmd.c_str(), -1, buffer, wn) == 0) {
+               delete[] buffer;
+               return;
+       }
+
+       int code = 1;
+
+       STARTUPINFOW startup_info;
+       memset (&startup_info, 0, sizeof (startup_info));
+       startup_info.cb = sizeof (startup_info);
+       PROCESS_INFORMATION process_info;
+
+       /* XXX: this doesn't actually seem to work; failing commands end up with
+          a return code of 0
+       */
+       if (CreateProcessW (0, buffer, 0, 0, FALSE, CREATE_NO_WINDOW, 0, 0, &startup_info, &process_info)) {
+               WaitForSingleObject (process_info.hProcess, INFINITE);
+               DWORD c;
+               if (GetExitCodeProcess (process_info.hProcess, &c)) {
+                       code = c;
+               }
+               CloseHandle (process_info.hProcess);
+               CloseHandle (process_info.hThread);
+       }
+
+       delete[] buffer;
 #else
-       if (WEXITSTATUS (r)) {
-#endif         
+       cmd += " 2> /dev/null";
+       int const r = system (cmd.c_str ());
+       int const code = WEXITSTATUS (r);
+#endif
+       if (code) {
                stringstream s;
-               s << "error in " << c << "\n";
+               s << "error " << code << " in " << cmd << " within " << boost::filesystem::current_path();
                throw libdcp::MiscError (s.str());
        }
 }
@@ -59,19 +91,22 @@ static string
 public_key_digest (boost::filesystem::path private_key, boost::filesystem::path openssl)
 {
        boost::filesystem::path public_name = private_key.string() + ".public";
-       
+
        /* Create the public key from the private key */
        stringstream s;
-       s << openssl.string() << " rsa -outform PEM -pubout -in " << private_key.string() << " > " << public_name.string ();
+       s << "\"" << openssl.string() << "\" rsa -outform PEM -pubout -in " << private_key.string() << " -out " << public_name.string ();
        command (s.str().c_str ());
 
        /* Read in the public key from the file */
 
        string pub;
        ifstream f (public_name.string().c_str ());
+       if (!f.good ()) {
+               throw libdcp::MiscError ("public key not found");
+       }
 
        bool read = false;
-       while (1) {
+       while (f.good ()) {
                string line;
                getline (f, line);
                if (line.length() >= 10 && line.substr(0, 10) == "-----BEGIN") {
@@ -119,8 +154,10 @@ libdcp::make_signer_chain (boost::filesystem::path directory, boost::filesystem:
 {
        boost::filesystem::path const cwd = boost::filesystem::current_path ();
 
+       string quoted_openssl = "\"" + openssl.string() + "\"";
+
        boost::filesystem::current_path (directory);
-       command (openssl.string() + " genrsa -out ca.key 2048");
+       command (quoted_openssl + " genrsa -out ca.key 2048");
 
        {
                ofstream f ("ca.cnf");
@@ -142,13 +179,13 @@ libdcp::make_signer_chain (boost::filesystem::path directory, boost::filesystem:
 
        {
                stringstream c;
-               c << openssl.string()
+               c << quoted_openssl
                  << " req -new -x509 -sha256 -config ca.cnf -days 3650 -set_serial 5"
                  << " -subj " << ca_subject << " -key ca.key -outform PEM -out ca.self-signed.pem";
                command (c.str().c_str());
        }
 
-       command (openssl.string() + " genrsa -out intermediate.key 2048");
+       command (quoted_openssl + " genrsa -out intermediate.key 2048");
 
        {
                ofstream f ("intermediate.cnf");
@@ -171,18 +208,19 @@ libdcp::make_signer_chain (boost::filesystem::path directory, boost::filesystem:
 
        {
                stringstream s;
-               s << openssl.string() << " req -new -config intermediate.cnf -days 3649 -subj " << inter_subject << " -key intermediate.key -out intermediate.csr";
+               s << quoted_openssl
+                 << " req -new -config intermediate.cnf -days 3649 -subj " << inter_subject << " -key intermediate.key -out intermediate.csr";
                command (s.str().c_str());
        }
 
        
        command (
-               openssl.string() +
+               quoted_openssl +
                " x509 -req -sha256 -days 3649 -CA ca.self-signed.pem -CAkey ca.key -set_serial 6"
                " -in intermediate.csr -extfile intermediate.cnf -extensions v3_ca -out intermediate.signed.pem"
                );
 
-       command (openssl.string() + " genrsa -out leaf.key 2048");
+       command (quoted_openssl + " genrsa -out leaf.key 2048");
 
        {
                ofstream f ("leaf.cnf");
@@ -205,12 +243,12 @@ libdcp::make_signer_chain (boost::filesystem::path directory, boost::filesystem:
 
        {
                stringstream s;
-               s << openssl.string() << " req -new -config leaf.cnf -days 3648 -subj " << leaf_subject << " -key leaf.key -outform PEM -out leaf.csr";
+               s << quoted_openssl << " req -new -config leaf.cnf -days 3648 -subj " << leaf_subject << " -key leaf.key -outform PEM -out leaf.csr";
                command (s.str().c_str());
        }
 
        command (
-               openssl.string() +
+               quoted_openssl +
                " x509 -req -sha256 -days 3648 -CA intermediate.signed.pem -CAkey intermediate.key"
                " -set_serial 7 -in leaf.csr -extfile leaf.cnf -extensions v3_ca -out leaf.signed.pem"
                );