diff options
Diffstat (limited to 'src/lib/kdm_cli.cc')
| -rw-r--r-- | src/lib/kdm_cli.cc | 161 |
1 files changed, 96 insertions, 65 deletions
diff --git a/src/lib/kdm_cli.cc b/src/lib/kdm_cli.cc index 2d3a021b5..21e8c75d3 100644 --- a/src/lib/kdm_cli.cc +++ b/src/lib/kdm_cli.cc @@ -32,6 +32,7 @@ #include "film.h" #include "kdm_with_metadata.h" #include "screen.h" +#include "variant.h" #include <dcp/certificate.h> #include <dcp/decrypted_kdm.h> #include <dcp/encrypted_kdm.h> @@ -57,13 +58,18 @@ using namespace dcpomatic; static void help (std::function<void (string)> out) { - out (String::compose("Syntax: %1 [OPTION] <FILM|CPL-ID|DKDM>", program_name)); + out (String::compose("Syntax: %1 [OPTION] [COMMAND] <FILM|CPL-ID|DKDM>", program_name)); + out ("Commands:"); + out ("create create KDMs; default if no other command is specified"); + out (variant::insert_dcpomatic("list-cinemas list known cinemas from %1 settings")); + out (variant::insert_dcpomatic("list-dkdm-cpls list CPLs for which %1 has DKDMs")); + out (variant::insert_dcpomatic("add-dkdm add DKDM to %1's list")); out (" -h, --help show this help"); out (" -o, --output <path> output file or directory"); out (" -K, --filename-format <format> filename format for KDMs"); out (" -Z, --container-name-format <format> filename format for ZIP containers"); - out (" -f, --valid-from <time> valid from time (in local time zone of the cinema) (e.g. \"2013-09-28 01:41:51\") or \"now\""); - out (" -t, --valid-to <time> valid to time (in local time zone of the cinema) (e.g. \"2014-09-28 01:41:51\")"); + out (" -f, --valid-from <time> valid from time (e.g. \"2013-09-28T01:41:51+04:00\", \"2018-01-01T12:00:30\") or \"now\""); + out (" -t, --valid-to <time> valid to time (e.g. \"2014-09-28T01:41:51\")"); out (" -d, --valid-duration <duration> valid duration (e.g. \"1 day\", \"4 hours\", \"2 weeks\")"); out (" -F, --formulation <formulation> modified-transitional-1, multiple-modified-transitional-1, dci-any or dci-specific [default modified-transitional-1]"); out (" -p, --disable-forensic-marking-picture disable forensic marking of pictures essences"); @@ -73,18 +79,18 @@ help (std::function<void (string)> out) out (" -v, --verbose be verbose"); out (" -c, --cinema <name|email> cinema name (when using -C) or name/email (to filter cinemas)"); out (" -S, --screen <name> screen name (when using -C) or screen name (to filter screens when using -c)"); - out (" -C, --certificate <file> file containing projector certificate"); - out (" -T, --trusted-device <file> file containing a trusted device's certificate"); + out (" -C, --projector-certificate <file> file containing projector certificate"); + out (" -T, --trusted-device-certificate <file> file containing a trusted device's certificate"); + out (" --decryption-key <file> file containing the private key which can decrypt the given DKDM"); + out (variant::insert_dcpomatic(" (%1's configured private key will be used otherwise)")); out (" --cinemas-file <file> use the given file as a list of cinemas instead of the current configuration"); - out (" --list-cinemas list known cinemas from the DCP-o-matic settings"); - out (" --list-dkdm-cpls list CPLs for which DCP-o-matic has DKDMs"); out (""); - out ("CPL-ID must be the ID of a CPL that is mentioned in DCP-o-matic's DKDM list."); + out (variant::insert_dcpomatic("CPL-ID must be the ID of a CPL that is mentioned in %1's DKDM list.")); out (""); out ("For example:"); out (""); out ("Create KDMs for my_great_movie to play in all of Fred's Cinema's screens for the next two weeks and zip them up."); - out ("(Fred's Cinema must have been set up in DCP-o-matic's KDM window)"); + out (variant::insert_dcpomatic("(Fred's Cinema must have been set up in %1's KDM window)")); out (""); out (String::compose("\t%1 -c \"Fred's Cinema\" -f now -d \"2 weeks\" -z my_great_movie", program_name)); } @@ -99,17 +105,6 @@ public: }; -static boost::posix_time::ptime -time_from_string (string t) -{ - if (t == "now") { - return boost::posix_time::second_clock::local_time (); - } - - return boost::posix_time::time_from_string (t); -} - - static boost::posix_time::time_duration duration_from_string (string d) { @@ -211,8 +206,8 @@ from_film ( boost::filesystem::path output, dcp::NameFormat container_name_format, dcp::NameFormat filename_format, - boost::posix_time::ptime valid_from, - boost::posix_time::ptime valid_to, + dcp::LocalTime valid_from, + dcp::LocalTime valid_to, dcp::Formulation formulation, bool disable_forensic_marking_picture, optional<int> disable_forensic_marking_audio, @@ -256,7 +251,6 @@ from_film ( } } - if (find_if( period_checks.begin(), period_checks.end(), @@ -362,8 +356,8 @@ from_dkdm ( boost::filesystem::path output, dcp::NameFormat container_name_format, dcp::NameFormat filename_format, - boost::posix_time::ptime valid_from, - boost::posix_time::ptime valid_to, + dcp::LocalTime valid_from, + dcp::LocalTime valid_to, dcp::Formulation formulation, bool disable_forensic_marking_picture, optional<int> disable_forensic_marking_audio, @@ -381,18 +375,12 @@ from_dkdm ( continue; } - int const offset_hour = i->cinema ? i->cinema->utc_offset_hour() : 0; - int const offset_minute = i->cinema ? i->cinema->utc_offset_minute() : 0; - - dcp::LocalTime begin(valid_from, dcp::UTCOffset(offset_hour, offset_minute)); - dcp::LocalTime end(valid_to, dcp::UTCOffset(offset_hour, offset_minute)); - auto const kdm = kdm_from_dkdm( dkdm, i->recipient.get(), i->trusted_device_thumbprints(), - begin, - end, + valid_from, + valid_to, formulation, disable_forensic_marking_picture, disable_forensic_marking_audio @@ -402,8 +390,8 @@ from_dkdm ( name_values['c'] = i->cinema ? i->cinema->name : ""; name_values['s'] = i->name; name_values['f'] = kdm.content_title_text(); - name_values['b'] = begin.date() + " " + begin.time_of_day(true, false); - name_values['e'] = end.date() + " " + end.time_of_day(true, false); + name_values['b'] = valid_from.date() + " " + valid_from.time_of_day(true, false); + name_values['e'] = valid_to.date() + " " + valid_to.time_of_day(true, false); name_values['i'] = kdm.cpl_id(); kdms.push_back(make_shared<KDMWithMetadata>(name_values, i->cinema.get(), i->cinema ? i->cinema->emails : vector<string>(), kdm)); @@ -440,6 +428,22 @@ dump_dkdm_group (shared_ptr<DKDMGroup> group, int indent, std::function<void (st } +static +dcp::LocalTime +time_from_string(string time) +{ + if (time == "now") { + return {}; + } + + if (time.length() > 10 && time[10] == ' ') { + time[10] = 'T'; + } + + return dcp::LocalTime(time); +} + + optional<string> kdm_cli (int argc, char* argv[], std::function<void (string)> out) try @@ -449,15 +453,15 @@ try auto filename_format = Config::instance()->kdm_filename_format(); optional<string> cinema_name; shared_ptr<Cinema> cinema; - optional<boost::filesystem::path> certificate; + optional<boost::filesystem::path> projector_certificate; + optional<boost::filesystem::path> decryption_key; optional<string> screen; vector<shared_ptr<Screen>> screens; optional<dcp::EncryptedKDM> dkdm; - optional<boost::posix_time::ptime> valid_from; - optional<boost::posix_time::ptime> valid_to; + optional<dcp::LocalTime> valid_from; + optional<dcp::LocalTime> valid_to; bool zip = false; - bool list_cinemas = false; - bool list_dkdm_cpls = false; + string command = "create"; optional<string> duration_string; bool verbose = false; dcp::Formulation formulation = dcp::Formulation::MODIFIED_TRANSITIONAL_1; @@ -489,15 +493,14 @@ try { "verbose", no_argument, 0, 'v' }, { "cinema", required_argument, 0, 'c' }, { "screen", required_argument, 0, 'S' }, - { "certificate", required_argument, 0, 'C' }, - { "trusted-device", required_argument, 0, 'T' }, - { "list-cinemas", no_argument, 0, 'B' }, - { "list-dkdm-cpls", no_argument, 0, 'D' }, + { "projector-certificate", required_argument, 0, 'C' }, + { "trusted-device-certificate", required_argument, 0, 'T' }, + { "decryption-key", required_argument, 0, 'G' }, { "cinemas-file", required_argument, 0, 'E' }, { 0, 0, 0, 0 } }; - int c = getopt_long (argc, argv, "ho:K:Z:f:t:d:F:pae::zvc:S:C:T:BDE:", long_options, &option_index); + int c = getopt_long (argc, argv, "ho:K:Z:f:t:d:F:pae::zvc:S:C:T:E:G:", long_options, &option_index); if (c == -1) { break; @@ -517,10 +520,10 @@ try container_name_format = dcp::NameFormat (optarg); break; case 'f': - valid_from = time_from_string (optarg); + valid_from = time_from_string(optarg); break; case 't': - valid_to = time_from_string (optarg); + valid_to = dcp::LocalTime(optarg); break; case 'd': duration_string = optarg; @@ -564,7 +567,7 @@ try (for lookup) and by creating a Cinema which the next Screen will be added to. */ cinema_name = optarg; - cinema = make_shared<Cinema>(optarg, vector<string>(), "", 0, 0); + cinema = make_shared<Cinema>(optarg, vector<string>(), "", dcp::UTCOffset()); break; case 'S': /* Similarly, this could be the name of a new (temporary) screen or the name of a screen @@ -573,7 +576,7 @@ try screen = optarg; break; case 'C': - certificate = optarg; + projector_certificate = optarg; break; case 'T': /* A trusted device ends up in the last screen we made */ @@ -581,11 +584,8 @@ try screens.back()->trusted_devices.push_back(TrustedDevice(dcp::Certificate(dcp::file_to_string(optarg)))); } break; - case 'B': - list_cinemas = true; - break; - case 'D': - list_dkdm_cpls = true; + case 'G': + decryption_key = optarg; break; case 'E': cinemas_file = optarg; @@ -593,13 +593,34 @@ try } } + vector<string> commands = { + "create", + "list-cinemas", + "list-dkdm-cpls", + "add-dkdm" + }; + + if (optind < argc - 1) { + /* Command with some KDM / CPL / whever specified afterwards */ + command = argv[optind++]; + } else if (optind < argc) { + /* Look for a valid command, hoping that it's not the name of the KDM / CPL / whatever */ + if (std::find(commands.begin(), commands.end(), argv[optind]) != commands.end()) { + command = argv[optind++]; + } + } + + if (std::find(commands.begin(), commands.end(), command) == commands.end()) { + throw KDMCLIError(String::compose("Unrecognised command %1", command)); + } + if (cinemas_file) { Config::instance()->set_cinemas_file(*cinemas_file); } - if (certificate) { + if (projector_certificate) { /* Make a new screen and add it to the current cinema */ - dcp::CertificateChain chain(dcp::file_to_string(*certificate)); + dcp::CertificateChain chain(dcp::file_to_string(*projector_certificate)); auto screen_to_add = std::make_shared<Screen>(screen.get_value_or(""), "", chain.leaf(), boost::none, vector<TrustedDevice>()); if (cinema) { cinema->add_screen(screen_to_add); @@ -607,7 +628,7 @@ try screens.push_back(screen_to_add); } - if (list_cinemas) { + if (command == "list-cinemas") { auto cinemas = Config::instance()->cinemas (); for (auto i: cinemas) { out (String::compose("%1 (%2)", i->name, Email::address_list(i->emails))); @@ -615,11 +636,22 @@ try return {}; } - if (list_dkdm_cpls) { + if (command == "list-dkdm-cpls") { dump_dkdm_group (Config::instance()->dkdms(), 0, out); return {}; } + if (optind >= argc) { + throw KDMCLIError("no film, CPL ID or DKDM specified"); + } + + if (command == "add-dkdm") { + auto dkdms = Config::instance()->dkdms(); + dkdms->add(make_shared<DKDM>(dcp::EncryptedKDM(dcp::file_to_string(argv[optind])))); + Config::instance()->write_config(); + return {}; + } + if (!duration_string && !valid_to) { throw KDMCLIError ("you must specify a --valid-duration or --valid-to"); } @@ -628,10 +660,6 @@ try throw KDMCLIError ("you must specify --valid-from"); } - if (optind >= argc) { - throw KDMCLIError ("no film, CPL ID or DKDM specified"); - } - if (screens.empty()) { if (!cinema_name) { throw KDMCLIError ("you must specify either a cinema or one or more screens using certificate files"); @@ -644,11 +672,12 @@ try } if (duration_string) { - valid_to = valid_from.get() + duration_from_string (*duration_string); + valid_to = valid_from.get(); + valid_to->add(duration_from_string(*duration_string)); } if (verbose) { - out (String::compose("Making KDMs valid from %1 to %2", boost::posix_time::to_simple_string(valid_from.get()), boost::posix_time::to_simple_string(valid_to.get()))); + out(String::compose("Making KDMs valid from %1 to %2", valid_from->as_string(), valid_to->as_string())); } string const thing = argv[optind]; @@ -680,9 +709,11 @@ try throw KDMCLIError ("could not find film or CPL ID corresponding to " + thing); } + string const key = decryption_key ? dcp::file_to_string(*decryption_key) : Config::instance()->decryption_chain()->key().get(); + from_dkdm ( screens, - dcp::DecryptedKDM (*dkdm, Config::instance()->decryption_chain()->key().get()), + dcp::DecryptedKDM(*dkdm, key), verbose, output, container_name_format, |
