diff options
| author | Carl Hetherington <cth@carlh.net> | 2021-01-23 15:35:24 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2021-01-23 15:35:24 +0100 |
| commit | 6c37cc1979b2a01205a888c4c98f3334685ee8dd (patch) | |
| tree | 9de52a3053e57bdf79a7986319cb097b33e46b5c /src | |
| parent | b75d977a38f039fd68ed5d4055ae70b4bf631603 (diff) | |
Tidying.
Diffstat (limited to 'src')
| -rw-r--r-- | src/asset_reader.h | 30 | ||||
| -rw-r--r-- | src/asset_writer.cc | 16 | ||||
| -rw-r--r-- | src/asset_writer.h | 22 | ||||
| -rw-r--r-- | src/certificate.cc | 95 | ||||
| -rw-r--r-- | src/certificate.h | 39 | ||||
| -rw-r--r-- | src/certificate_chain.cc | 117 | ||||
| -rw-r--r-- | src/certificate_chain.h | 55 | ||||
| -rw-r--r-- | src/cpl.h | 2 | ||||
| -rw-r--r-- | src/dcp.cc | 43 | ||||
| -rw-r--r-- | src/dcp.h | 57 | ||||
| -rw-r--r-- | src/exceptions.h | 37 | ||||
| -rw-r--r-- | src/frame.h | 16 | ||||
| -rw-r--r-- | src/gamma_transfer_function.cc | 14 | ||||
| -rw-r--r-- | src/gamma_transfer_function.h | 13 | ||||
| -rw-r--r-- | src/key.cc | 14 | ||||
| -rw-r--r-- | src/key.h | 17 | ||||
| -rw-r--r-- | src/mono_picture_frame.h | 17 | ||||
| -rw-r--r-- | src/object.cc | 15 | ||||
| -rw-r--r-- | src/object.h | 26 | ||||
| -rw-r--r-- | src/pkl.cc | 10 | ||||
| -rw-r--r-- | src/pkl.h | 10 | ||||
| -rw-r--r-- | src/reel.cc | 32 | ||||
| -rw-r--r-- | src/reel.h | 7 | ||||
| -rw-r--r-- | src/reel_mxf.cc | 14 | ||||
| -rw-r--r-- | src/reel_mxf.h | 14 | ||||
| -rw-r--r-- | src/ref.cc | 11 | ||||
| -rw-r--r-- | src/ref.h | 20 | ||||
| -rw-r--r-- | src/stereo_picture_frame.cc | 13 | ||||
| -rw-r--r-- | src/stereo_picture_frame.h | 23 | ||||
| -rw-r--r-- | src/transfer_function.h | 19 | ||||
| -rw-r--r-- | src/util.cc | 113 | ||||
| -rw-r--r-- | src/util.h | 71 | ||||
| -rw-r--r-- | src/verify.cc | 6 | ||||
| -rw-r--r-- | src/version.h | 10 | ||||
| -rw-r--r-- | src/xml.h | 16 |
35 files changed, 688 insertions, 346 deletions
diff --git a/src/asset_reader.h b/src/asset_reader.h index d1e0f10e..859c88f3 100644 --- a/src/asset_reader.h +++ b/src/asset_reader.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,34 +31,40 @@ files in the program, then also delete it here. */ + #ifndef LIBDCP_ASSET_READER_H #define LIBDCP_ASSET_READER_H -#include "dcp_assert.h" + #include "asset.h" #include "crypto_context.h" +#include "dcp_assert.h" #include <asdcp/AS_DCP.h> -#include <boost/noncopyable.hpp> #include <memory> + namespace dcp { + template <class R, class F> -class AssetReader : public boost::noncopyable +class AssetReader { public: explicit AssetReader (Asset const * asset, boost::optional<Key> key, Standard standard) - : _crypto_context (new DecryptionContext (key, standard)) + : _crypto_context (new DecryptionContext(key, standard)) { _reader = new R (); - DCP_ASSERT (asset->file ()); - Kumu::Result_t const r = _reader->OpenRead (asset->file()->string().c_str()); - if (ASDCP_FAILURE (r)) { + DCP_ASSERT (asset->file()); + auto const r = _reader->OpenRead (asset->file()->string().c_str()); + if (ASDCP_FAILURE(r)) { delete _reader; - boost::throw_exception (FileError ("could not open MXF file for reading", asset->file().get(), r)); + boost::throw_exception (FileError("could not open MXF file for reading", asset->file().get(), r)); } } + AssetReader (AssetReader const&) = delete; + AssetReader& operator== (AssetReader const&) = delete; + ~AssetReader () { delete _reader; @@ -66,7 +72,7 @@ public: std::shared_ptr<const F> get_frame (int n) const { - return std::shared_ptr<const F> (new F (_reader, n, _crypto_context)); + return std::shared_ptr<const F> (new F(_reader, n, _crypto_context)); } R* reader () const { @@ -74,10 +80,12 @@ public: } protected: - R* _reader; + R* _reader = nullptr; std::shared_ptr<DecryptionContext> _crypto_context; }; + } + #endif diff --git a/src/asset_writer.cc b/src/asset_writer.cc index c4302f4a..73fc2046 100644 --- a/src/asset_writer.cc +++ b/src/asset_writer.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,19 +31,23 @@ files in the program, then also delete it here. */ + /** @file src/asset_writer.h * @brief AssetWriter class. */ + #include "asset_writer.h" -#include "mxf.h" -#include "dcp_assert.h" #include "crypto_context.h" +#include "dcp_assert.h" +#include "mxf.h" #include <asdcp/AS_DCP.h> #include <asdcp/KM_prng.h> + using namespace dcp; + /** Create an AssetWriter. * @param mxf MXF that we are writing. * @param file File to write to. @@ -51,14 +55,12 @@ using namespace dcp; AssetWriter::AssetWriter (MXF* mxf, boost::filesystem::path file) : _mxf (mxf) , _file (file) - , _frames_written (0) - , _finalized (false) - , _started (false) - , _crypto_context (new EncryptionContext (mxf->key(), mxf->standard())) + , _crypto_context(new EncryptionContext (mxf->key(), mxf->standard())) { } + /** @return true if anything was written by this writer */ bool AssetWriter::finalize () diff --git a/src/asset_writer.h b/src/asset_writer.h index 8842917a..7eecc03f 100644 --- a/src/asset_writer.h +++ b/src/asset_writer.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,31 +31,39 @@ files in the program, then also delete it here. */ + /** @file src/asset_writer.h * @brief AssetWriter class. */ + #ifndef LIBDCP_ASSET_WRITER_H #define LIBDCP_ASSET_WRITER_H + #include "types.h" #include "crypto_context.h" #include <boost/filesystem.hpp> -#include <boost/noncopyable.hpp> + namespace dcp { + class MXF; + /** @class AssetWriter * @brief Parent class for classes which can write MXF-based assets. * * The AssetWriter lasts for the duration of the write and is then discarded. * They can only be created by calling start_write() on an appropriate Asset object. */ -class AssetWriter : public boost::noncopyable +class AssetWriter { public: + AssetWriter (AssetWriter const&) = delete; + AssetWriter& operator= (AssetWriter const&) = delete; + virtual ~AssetWriter () {} virtual bool finalize (); @@ -67,17 +75,17 @@ protected: AssetWriter (MXF* mxf, boost::filesystem::path file); /** MXF that we are writing */ - MXF* _mxf; + MXF* _mxf = nullptr; /** File that we are writing to */ boost::filesystem::path _file; /** Number of `frames' written so far; the definition of a frame * varies depending on the subclass. */ - int64_t _frames_written; + int64_t _frames_written = 0; /** true if finalize() has been called on this object */ - bool _finalized; + bool _finalized = false; /** true if something has been written to this asset */ - bool _started; + bool _started = false; std::shared_ptr<EncryptionContext> _crypto_context; }; diff --git a/src/certificate.cc b/src/certificate.cc index 2e33907d..b285df5f 100644 --- a/src/certificate.cc +++ b/src/certificate.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ files in the program, then also delete it here. */ + /** @file src/certificate.cc * @brief Certificate class. */ + #include "certificate.h" #include "compose.hpp" #include "exceptions.h" @@ -51,52 +53,42 @@ #include <iostream> #include <algorithm> + using std::list; using std::string; using std::ostream; using std::min; using namespace dcp; + static string const begin_certificate = "-----BEGIN CERTIFICATE-----"; static string const end_certificate = "-----END CERTIFICATE-----"; -/** @param c X509 certificate, which this object will take ownership of */ + Certificate::Certificate (X509* c) : _certificate (c) - , _public_key (0) { } -/** Load an X509 certificate from a string. - * @param cert String to read from. - */ + Certificate::Certificate (string cert) - : _certificate (0) - , _public_key (0) { - string const s = read_string (cert); - if (!s.empty ()) { + auto const s = read_string (cert); + if (!s.empty()) { throw MiscError ("unexpected data after certificate"); } } -/** Copy constructor. - * @param other Certificate to copy. - */ + Certificate::Certificate (Certificate const & other) - : _certificate (0) - , _public_key (0) { if (other._certificate) { read_string (other.certificate (true)); } } -/** Read a certificate from a string. - * @param cert String to read. - * @return remaining part of the input string after the certificate which was read. - */ + string Certificate::read_string (string cert) { @@ -121,7 +113,7 @@ Certificate::read_string (string cert) lines.push_back (line); } - list<string>::iterator i = lines.begin (); + auto i = lines.begin (); /* BEGIN */ while (i != lines.end() && *i != begin_certificate) { @@ -165,7 +157,7 @@ Certificate::read_string (string cert) fixed += end_certificate; - BIO* bio = BIO_new_mem_buf (const_cast<char *> (fixed.c_str ()), -1); + auto bio = BIO_new_mem_buf (const_cast<char *> (fixed.c_str ()), -1); if (!bio) { throw MiscError ("could not create memory BIO"); } @@ -189,16 +181,14 @@ Certificate::read_string (string cert) return extra; } -/** Destructor */ + Certificate::~Certificate () { X509_free (_certificate); RSA_free (_public_key); } -/** operator= for Certificate. - * @param other Certificate to read from. - */ + Certificate & Certificate::operator= (Certificate const & other) { @@ -211,21 +201,18 @@ Certificate::operator= (Certificate const & other) RSA_free (_public_key); _public_key = 0; - read_string (other.certificate (true)); + read_string (other.certificate(true)); return *this; } -/** Return the certificate as a string. - * @param with_begin_end true to include the -----BEGIN CERTIFICATE--- / -----END CERTIFICATE----- markers. - * @return Certificate string. - */ + string Certificate::certificate (bool with_begin_end) const { DCP_ASSERT (_certificate); - BIO* bio = BIO_new (BIO_s_mem ()); + auto bio = BIO_new (BIO_s_mem()); if (!bio) { throw MiscError ("could not create memory BIO"); } @@ -249,17 +236,15 @@ Certificate::certificate (bool with_begin_end) const return s; } -/** @return Certificate's issuer, in the form - * dnqualifier=<dnQualififer>,CN=<commonName>,OU=<organizationalUnitName>,O=<organizationName> - * and with + signs escaped to \+ - */ + string Certificate::issuer () const { DCP_ASSERT (_certificate); - return name_for_xml (X509_get_issuer_name (_certificate)); + return name_for_xml (X509_get_issuer_name(_certificate)); } + string Certificate::asn_to_utf8 (ASN1_STRING* s) { @@ -270,6 +255,7 @@ Certificate::asn_to_utf8 (ASN1_STRING* s) return u; } + string Certificate::get_name_part (X509_NAME* n, int nid) { @@ -278,15 +264,16 @@ Certificate::get_name_part (X509_NAME* n, int nid) if (p == -1) { return ""; } - return asn_to_utf8 (X509_NAME_ENTRY_get_data (X509_NAME_get_entry (n, p))); + return asn_to_utf8 (X509_NAME_ENTRY_get_data(X509_NAME_get_entry(n, p))); } + string Certificate::name_for_xml (X509_NAME* name) { assert (name); - BIO* bio = BIO_new (BIO_s_mem ()); + auto bio = BIO_new (BIO_s_mem ()); if (!bio) { throw MiscError ("could not create memory BIO"); } @@ -310,33 +297,37 @@ Certificate::subject () const { DCP_ASSERT (_certificate); - return name_for_xml (X509_get_subject_name (_certificate)); + return name_for_xml (X509_get_subject_name(_certificate)); } + string Certificate::subject_common_name () const { DCP_ASSERT (_certificate); - return get_name_part (X509_get_subject_name (_certificate), NID_commonName); + return get_name_part (X509_get_subject_name(_certificate), NID_commonName); } + string Certificate::subject_organization_name () const { DCP_ASSERT (_certificate); - return get_name_part (X509_get_subject_name (_certificate), NID_organizationName); + return get_name_part (X509_get_subject_name(_certificate), NID_organizationName); } + string Certificate::subject_organizational_unit_name () const { DCP_ASSERT (_certificate); - return get_name_part (X509_get_subject_name (_certificate), NID_organizationalUnitName); + return get_name_part (X509_get_subject_name(_certificate), NID_organizationalUnitName); } + static struct tm convert_time (ASN1_TIME const * time) @@ -359,6 +350,7 @@ convert_time (ASN1_TIME const * time) return t; } + struct tm Certificate::not_before () const { @@ -370,6 +362,7 @@ Certificate::not_before () const #endif } + struct tm Certificate::not_after () const { @@ -381,15 +374,16 @@ Certificate::not_after () const #endif } + string Certificate::serial () const { DCP_ASSERT (_certificate); - ASN1_INTEGER* s = X509_get_serialNumber (_certificate); + auto s = X509_get_serialNumber (_certificate); DCP_ASSERT (s); - BIGNUM* b = ASN1_INTEGER_to_BN (s, 0); + auto b = ASN1_INTEGER_to_BN (s, 0); char* c = BN_bn2dec (b); BN_free (b); @@ -399,7 +393,7 @@ Certificate::serial () const return st; } -/** @return thumbprint of the to-be-signed portion of this certificate */ + string Certificate::thumbprint () const { @@ -428,7 +422,7 @@ Certificate::thumbprint () const return Kumu::base64encode (digest, 20, digest_base64, 64); } -/** @return RSA public key from this Certificate. Caller must not free the returned value. */ + RSA * Certificate::public_key () const { @@ -438,7 +432,7 @@ Certificate::public_key () const return _public_key; } - EVP_PKEY* key = X509_get_pubkey (_certificate); + auto key = X509_get_pubkey (_certificate); if (!key) { throw MiscError ("could not get public key from certificate"); } @@ -451,6 +445,7 @@ Certificate::public_key () const return _public_key; } + static bool string_is_utf8 (X509_NAME* n, int nid) { int p = -1; @@ -458,27 +453,31 @@ static bool string_is_utf8 (X509_NAME* n, int nid) return p != -1 && X509_NAME_ENTRY_get_data(X509_NAME_get_entry(n, p))->type == V_ASN1_UTF8STRING; } + bool Certificate::has_utf8_strings () const { - X509_NAME* n = X509_get_subject_name (_certificate); + auto n = X509_get_subject_name (_certificate); return string_is_utf8(n, NID_commonName) || string_is_utf8(n, NID_organizationName) || string_is_utf8(n, NID_organizationalUnitName); } + bool dcp::operator== (Certificate const & a, Certificate const & b) { return a.certificate() == b.certificate(); } + bool dcp::operator< (Certificate const & a, Certificate const & b) { return a.certificate() < b.certificate(); } + ostream& dcp::operator<< (ostream& s, Certificate const & c) { diff --git a/src/certificate.h b/src/certificate.h index 4be673cc..7a8c2a44 100644 --- a/src/certificate.h +++ b/src/certificate.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,29 +31,35 @@ files in the program, then also delete it here. */ + /** @file src/certificate.h * @brief Certificate class. */ + #ifndef LIBDCP_CERTIFICATE_H #define LIBDCP_CERTIFICATE_H + #undef X509_NAME #include <openssl/x509.h> #include <boost/filesystem.hpp> #include <string> #include <list> + namespace xmlpp { class Element; } + namespace dcp { + /** @class Certificate - * @brief A wrapper for an X509 certificate. + * @brief A wrapper for an X509 certificate * - * This class can take a Certificate from a string or an OpenSSL X509 object. + * This class can take a Certificate from a string or an OpenSSL X509 object */ class Certificate { @@ -63,18 +69,37 @@ public: , _public_key (0) {} + /** Load an X509 certificate from a string + * @param cert String to read from + */ explicit Certificate (std::string); + + /** @param c X509 certificate, which this object will take ownership of */ explicit Certificate (X509 *); + Certificate (Certificate const &); ~Certificate (); Certificate& operator= (Certificate const &); + /** Read a certificate from a string. + * @param cert String to read. + * @return remaining part of the input string after the certificate which was read. + */ std::string read_string (std::string); + /** Return the certificate as a string + * @param with_begin_end true to include the -----BEGIN CERTIFICATE--- / -----END CERTIFICATE----- markers + * @return Certificate string + */ std::string certificate (bool with_begin_end = false) const; + std::string serial () const; + /** @return Certificate's issuer, in the form + * dnqualifier=<dnQualififer>,CN=<commonName>,OU=<organizationalUnitName>,O=<organizationName> + * and with + signs escaped to \+ + */ std::string issuer () const; std::string subject () const; @@ -88,8 +113,10 @@ public: return _certificate; } + /** @return RSA public key from this Certificate. Caller must not free the returned value. */ RSA* public_key () const; + /** @return thumbprint of the to-be-signed portion of this certificate */ std::string thumbprint () const; bool has_utf8_strings () const; @@ -100,14 +127,16 @@ private: static std::string asn_to_utf8 (ASN1_STRING *); static std::string get_name_part (X509_NAME *, int); - X509* _certificate; - mutable RSA* _public_key; + X509* _certificate = nullptr; + mutable RSA* _public_key = nullptr; }; + bool operator== (Certificate const & a, Certificate const & b); bool operator< (Certificate const & a, Certificate const & b); std::ostream& operator<< (std::ostream&s, Certificate const & c); + } #endif diff --git a/src/certificate_chain.cc b/src/certificate_chain.cc index 9f4c5ea7..fbea9ccd 100644 --- a/src/certificate_chain.cc +++ b/src/certificate_chain.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ files in the program, then also delete it here. */ -/** @file src/signer_chain.cc - * @brief Functions to make signer chains. + +/** @file src/certificate_chain.cc + * @brief CertificateChain class */ + #include "certificate_chain.h" #include "exceptions.h" #include "util.h" @@ -57,12 +59,14 @@ #include <fstream> #include <iostream> + using std::string; using std::ofstream; using std::ifstream; using std::runtime_error; using namespace dcp; + /** Run a shell command. * @param cmd Command to run (UTF8-encoded). */ @@ -74,7 +78,7 @@ command (string cmd) is handled correctly. */ int const wn = MultiByteToWideChar (CP_UTF8, 0, cmd.c_str(), -1, 0, 0); - wchar_t* buffer = new wchar_t[wn]; + char buffer = new wchar_t[wn]; if (MultiByteToWideChar (CP_UTF8, 0, cmd.c_str(), -1, buffer, wn) == 0) { delete[] buffer; return; @@ -111,6 +115,7 @@ command (string cmd) } } + /** Extract a public key from a private key and create a SHA1 digest of it. * @param private_key Private key * @param openssl openssl binary name (or full path if openssl is not on the system path). @@ -122,12 +127,12 @@ public_key_digest (boost::filesystem::path private_key, boost::filesystem::path boost::filesystem::path public_name = private_key.string() + ".public"; /* Create the public key from the private key */ - command (String::compose("\"%1\" rsa -outform PEM -pubout -in %2 -out %3", openssl.string(), private_key.string(), public_name.string ())); + command (String::compose("\"%1\" rsa -outform PEM -pubout -in %2 -out %3", openssl.string(), private_key.string(), public_name.string())); /* Read in the public key from the file */ string pub; - ifstream f (public_name.string().c_str ()); + ifstream f (public_name.string().c_str()); if (!f.good ()) { throw dcp::MiscError ("public key not found"); } @@ -176,6 +181,7 @@ public_key_digest (boost::filesystem::path private_key, boost::filesystem::path return dig; } + CertificateChain::CertificateChain ( boost::filesystem::path openssl, string organisation, @@ -188,10 +194,10 @@ CertificateChain::CertificateChain ( /* Valid for 40 years */ int const days = 365 * 40; - boost::filesystem::path directory = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path (); + auto directory = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path (); boost::filesystem::create_directories (directory); - boost::filesystem::path const cwd = boost::filesystem::current_path (); + auto const cwd = boost::filesystem::current_path (); boost::filesystem::current_path (directory); string quoted_openssl = "\"" + openssl.string() + "\""; @@ -314,15 +320,16 @@ CertificateChain::CertificateChain ( boost::filesystem::current_path (cwd); - _certificates.push_back (dcp::Certificate (dcp::file_to_string (directory / "ca.self-signed.pem"))); - _certificates.push_back (dcp::Certificate (dcp::file_to_string (directory / "intermediate.signed.pem"))); - _certificates.push_back (dcp::Certificate (dcp::file_to_string (directory / "leaf.signed.pem"))); + _certificates.push_back (dcp::Certificate(dcp::file_to_string(directory / "ca.self-signed.pem"))); + _certificates.push_back (dcp::Certificate(dcp::file_to_string(directory / "intermediate.signed.pem"))); + _certificates.push_back (dcp::Certificate(dcp::file_to_string(directory / "leaf.signed.pem"))); _key = dcp::file_to_string (directory / "leaf.key"); boost::filesystem::remove_all (directory); } + CertificateChain::CertificateChain (string s) { while (true) { @@ -340,49 +347,46 @@ CertificateChain::CertificateChain (string s) leaf_to_root (); } -/** @return Root certificate */ + Certificate CertificateChain::root () const { DCP_ASSERT (!_certificates.empty()); - return root_to_leaf().front (); + return root_to_leaf().front(); } -/** @return Leaf certificate */ + Certificate CertificateChain::leaf () const { DCP_ASSERT (!_certificates.empty()); - return root_to_leaf().back (); + return root_to_leaf().back(); } -/** @return Certificates in order from leaf to root */ + CertificateChain::List CertificateChain::leaf_to_root () const { - List l = root_to_leaf (); + auto l = root_to_leaf (); std::reverse (l.begin(), l.end()); return l; } + CertificateChain::List CertificateChain::unordered () const { return _certificates; } -/** Add a certificate to the chain. - * @param c Certificate to add. - */ + void CertificateChain::add (Certificate c) { _certificates.push_back (c); } -/** Remove a certificate from the chain. - * @param c Certificate to remove. - */ + void CertificateChain::remove (Certificate c) { @@ -392,13 +396,11 @@ CertificateChain::remove (Certificate c) } } -/** Remove the i'th certificate in the list, as listed - * from root to leaf. - */ + void CertificateChain::remove (int i) { - List::iterator j = _certificates.begin (); + auto j = _certificates.begin (); while (j != _certificates.end () && i > 0) { --i; ++j; @@ -409,17 +411,14 @@ CertificateChain::remove (int i) } } + bool CertificateChain::chain_valid () const { return chain_valid (_certificates); } -/** Check to see if a chain is valid (i.e. root signs the intermediate, intermediate - * signs the leaf and so on) and that the private key (if there is one) matches the - * leaf certificate. - * @return true if it's ok, false if not. - */ + bool CertificateChain::chain_valid (List const & chain) const { @@ -430,29 +429,29 @@ CertificateChain::chain_valid (List const & chain) const any time soon. */ - X509_STORE* store = X509_STORE_new (); + auto store = X509_STORE_new (); if (!store) { throw MiscError ("could not create X509 store"); } /* Put all the certificates into the store */ - for (List::const_iterator i = chain.begin(); i != chain.end(); ++i) { - if (!X509_STORE_add_cert (store, i->x509 ())) { - X509_STORE_free (store); + for (auto const& i: chain) { + if (!X509_STORE_add_cert(store, i.x509())) { + X509_STORE_free(store); return false; } } /* Verify each one */ - for (List::const_iterator i = chain.begin(); i != chain.end(); ++i) { + for (auto i = chain.begin(); i != chain.end(); ++i) { - List::const_iterator j = i; + auto j = i; ++j; if (j == chain.end ()) { break; } - X509_STORE_CTX* ctx = X509_STORE_CTX_new (); + auto ctx = X509_STORE_CTX_new (); if (!ctx) { X509_STORE_free (store); throw MiscError ("could not create X509 store context"); @@ -489,9 +488,7 @@ CertificateChain::chain_valid (List const & chain) const return true; } -/** Check that there is a valid private key for the leaf certificate. - * Will return true if there are no certificates. - */ + bool CertificateChain::private_key_valid () const { @@ -503,17 +500,17 @@ CertificateChain::private_key_valid () const return false; } - BIO* bio = BIO_new_mem_buf (const_cast<char *> (_key->c_str ()), -1); + auto bio = BIO_new_mem_buf (const_cast<char *> (_key->c_str ()), -1); if (!bio) { throw MiscError ("could not create memory BIO"); } - RSA* private_key = PEM_read_bio_RSAPrivateKey (bio, 0, 0, 0); + auto private_key = PEM_read_bio_RSAPrivateKey (bio, 0, 0, 0); if (!private_key) { return false; } - RSA* public_key = leaf().public_key (); + auto public_key = leaf().public_key (); #if OPENSSL_VERSION_NUMBER > 0x10100000L BIGNUM const * private_key_n; @@ -532,6 +529,7 @@ CertificateChain::private_key_valid () const return valid; } + bool CertificateChain::valid (string* reason) const { @@ -554,11 +552,11 @@ CertificateChain::valid (string* reason) const return true; } -/** @return Certificates in order from root to leaf */ + CertificateChain::List CertificateChain::root_to_leaf () const { - List rtl = _certificates; + auto rtl = _certificates; std::sort (rtl.begin(), rtl.end()); do { if (chain_valid (rtl)) { @@ -569,20 +567,17 @@ CertificateChain::root_to_leaf () const throw CertificateChainError ("certificate chain is not consistent"); } -/** Add a <Signer> and <ds:Signature> nodes to an XML node. - * @param parent XML node to add to. - * @param standard INTEROP or SMPTE. - */ + void CertificateChain::sign (xmlpp::Element* parent, Standard standard) const { /* <Signer> */ parent->add_child_text(" "); - xmlpp::Element* signer = parent->add_child("Signer"); + auto signer = parent->add_child("Signer"); signer->set_namespace_declaration ("http://www.w3.org/2000/09/xmldsig#", "dsig"); - xmlpp::Element* data = signer->add_child("X509Data", "dsig"); - xmlpp::Element* serial_element = data->add_child("X509IssuerSerial", "dsig"); + auto data = signer->add_child("X509Data", "dsig"); + auto serial_element = data->add_child("X509IssuerSerial", "dsig"); serial_element->add_child("X509IssuerName", "dsig")->add_child_text (leaf().issuer()); serial_element->add_child("X509SerialNumber", "dsig")->add_child_text (leaf().serial()); data->add_child("X509SubjectName", "dsig")->add_child_text (leaf().subject()); @@ -592,12 +587,12 @@ CertificateChain::sign (xmlpp::Element* parent, Standard standard) const /* <Signature> */ parent->add_child_text("\n "); - xmlpp::Element* signature = parent->add_child("Signature"); + auto signature = parent->add_child("Signature"); signature->set_namespace_declaration ("http://www.w3.org/2000/09/xmldsig#", "dsig"); signature->set_namespace ("dsig"); parent->add_child_text("\n"); - xmlpp::Element* signed_info = signature->add_child ("SignedInfo", "dsig"); + auto signed_info = signature->add_child ("SignedInfo", "dsig"); signed_info->add_child("CanonicalizationMethod", "dsig")->set_attribute ("Algorithm", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"); if (standard == Standard::INTEROP) { @@ -606,10 +601,10 @@ CertificateChain::sign (xmlpp::Element* parent, Standard standard) const signed_info->add_child("SignatureMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"); } - xmlpp::Element* reference = signed_info->add_child("Reference", "dsig"); + auto reference = signed_info->add_child("Reference", "dsig"); reference->set_attribute ("URI", ""); - xmlpp::Element* transforms = reference->add_child("Transforms", "dsig"); + auto transforms = reference->add_child("Transforms", "dsig"); transforms->add_child("Transform", "dsig")->set_attribute ( "Algorithm", "http://www.w3.org/2000/09/xmldsig#enveloped-signature" ); @@ -624,11 +619,6 @@ CertificateChain::sign (xmlpp::Element* parent, Standard standard) const } -/** Sign an XML node. - * - * @param parent Node to sign. - * @param ns Namespace to use for the signature XML nodes. - */ void CertificateChain::add_signature_value (xmlpp::Element* parent, string ns, bool add_indentation) const { @@ -672,6 +662,7 @@ CertificateChain::add_signature_value (xmlpp::Element* parent, string ns, bool a xmlSecDSigCtxDestroy (signature_context); } + string CertificateChain::chain () const { diff --git a/src/certificate_chain.h b/src/certificate_chain.h index c74bc6e2..56523a68 100644 --- a/src/certificate_chain.h +++ b/src/certificate_chain.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,22 +31,27 @@ files in the program, then also delete it here. */ -/** @file src/signer_chain.h - * @brief Functions to make signer chains. + +/** @file src/certificate_chain.h + * @brief CertificateChain class */ + #ifndef LIBDCP_CERTIFICATE_CHAIN_H #define LIBDCP_CERTIFICATE_CHAIN_H + #include "certificate.h" #include "types.h" #include <boost/filesystem.hpp> #include <boost/optional.hpp> + namespace xmlpp { class Node; } + struct certificates_validation1; struct certificates_validation2; struct certificates_validation3; @@ -56,8 +61,10 @@ struct certificates_validation6; struct certificates_validation7; struct certificates_validation8; + namespace dcp { + /** @class CertificateChain * @brief A chain of any number of certificates, from root to leaf. */ @@ -85,24 +92,60 @@ public: explicit CertificateChain (std::string); + /** Add a certificate to the chain. + * @param c Certificate to add. + */ void add (Certificate c); + + /** Remove a certificate from the chain. + * @param c Certificate to remove. + */ void remove (Certificate c); - void remove (int); + /** Remove the i'th certificate in the chain, as listed + * from root to leaf. + */ + void remove (int i); + + /** @return Root certificate */ Certificate root () const; + + /** @return Leaf certificate */ Certificate leaf () const; typedef std::vector<Certificate> List; + /** @return Certificates in order from leaf to root */ List leaf_to_root () const; + /** @return Certificates in order from root to leaf */ List root_to_leaf () const; List unordered () const; - bool valid (std::string* reason = 0) const; + bool valid (std::string* reason = nullptr) const; + + /** Check to see if the chain is valid (i.e. root signs the intermediate, intermediate + * signs the leaf and so on) and that the private key (if there is one) matches the + * leaf certificate. + * @return true if it's ok, false if not. + */ bool chain_valid () const; + + /** Check that there is a valid private key for the leaf certificate. + * Will return true if there are no certificates. + */ bool private_key_valid () const; + /** Add a <Signer> and <ds:Signature> nodes to an XML node. + * @param parent XML node to add to. + * @param standard INTEROP or SMPTE. + */ void sign (xmlpp::Element* parent, Standard standard) const; + + /** Sign an XML node. + * + * @param parent Node to sign. + * @param ns Namespace to use for the signature XML nodes. + */ void add_signature_value (xmlpp::Element* parent, std::string ns, bool add_indentation) const; boost::optional<std::string> key () const { @@ -133,6 +176,8 @@ private: boost::optional<std::string> _key; }; + } + #endif @@ -33,7 +33,7 @@ /** @file src/cpl.h - * @brief CPL class. + * @brief CPL class */ @@ -66,6 +66,7 @@ #include <boost/filesystem.hpp> #include <boost/algorithm/string.hpp> + using std::string; using std::list; using std::vector; @@ -81,11 +82,13 @@ using boost::optional; using boost::algorithm::starts_with; using namespace dcp; + static string const assetmap_interop_ns = "http://www.digicine.com/PROTO-ASDCP-AM-20040311#"; static string const assetmap_smpte_ns = "http://www.smpte-ra.org/schemas/429-9/2007/AM"; static string const volindex_interop_ns = "http://www.digicine.com/PROTO-ASDCP-VL-20040311#"; static string const volindex_smpte_ns = "http://www.smpte-ra.org/schemas/429-9/2007/AM"; + DCP::DCP (boost::filesystem::path directory) : _directory (directory) { @@ -96,17 +99,7 @@ DCP::DCP (boost::filesystem::path directory) _directory = boost::filesystem::canonical (_directory); } -/** Read a DCP. This method does not do any deep checking of the DCP's validity, but - * if it comes across any bad things it will do one of two things. - * - * Errors that are so serious that they prevent the method from working will result - * in an exception being thrown. For example, a missing ASSETMAP means that the DCP - * can't be read without a lot of guesswork, so this will throw. - * - * Errors that are not fatal will be added to notes, if it's non-0. For example, - * if the DCP contains a mixture of Interop and SMPTE elements this will result - * in a note being added to the vector. - */ + void DCP::read (vector<dcp::VerificationNote>* notes, bool ignore_incorrect_picture_mxf_type) { @@ -147,7 +140,7 @@ DCP::read (vector<dcp::VerificationNote>* notes, bool ignore_incorrect_picture_m if (i->optional_node_child("PackingList")) { pkl_paths.push_back (p); } else { - paths.insert (make_pair (remove_urn_uuid (i->string_child ("Id")), p)); + paths.insert (make_pair(remove_urn_uuid(i->string_child("Id")), p)); } break; case Standard::SMPTE: @@ -156,7 +149,7 @@ DCP::read (vector<dcp::VerificationNote>* notes, bool ignore_incorrect_picture_m if (pkl_bool && *pkl_bool == "true") { pkl_paths.push_back (p); } else { - paths.insert (make_pair (remove_urn_uuid (i->string_child ("Id")), p)); + paths.insert (make_pair(remove_urn_uuid(i->string_child("Id")), p)); } break; } @@ -229,7 +222,7 @@ DCP::read (vector<dcp::VerificationNote>* notes, bool ignore_incorrect_picture_m throw ReadError(String::compose("XML error in %1", path.string()), e.what()); } - auto const root = p->get_document()->get_root_node()->get_name (); + auto const root = p->get_document()->get_root_node()->get_name(); delete p; if (root == "CompositionPlaylist") { @@ -275,6 +268,7 @@ DCP::read (vector<dcp::VerificationNote>* notes, bool ignore_incorrect_picture_m } } + void DCP::resolve_refs (vector<shared_ptr<Asset>> assets) { @@ -283,6 +277,7 @@ DCP::resolve_refs (vector<shared_ptr<Asset>> assets) } } + bool DCP::equals (DCP const & other, EqualityOptions opt, NoteHandler note) const { @@ -310,6 +305,7 @@ DCP::equals (DCP const & other, EqualityOptions opt, NoteHandler note) const return r; } + void DCP::add (std::shared_ptr<CPL> cpl) { @@ -343,10 +339,6 @@ DCP::all_encrypted () const } -/** Add a KDM to decrypt this DCP. This method must be called after DCP::read() - * or the KDM you specify will be ignored. - * @param kdm KDM to use. - */ void DCP::add (DecryptedKDM const & kdm) { @@ -361,6 +353,7 @@ DCP::add (DecryptedKDM const & kdm) } } + /** Write the VOLINDEX file. * @param standard DCP standard to use (INTEROP or SMPTE) */ @@ -397,6 +390,7 @@ DCP::write_volindex (Standard standard) const doc.write_to_file_formatted (p.string (), "UTF-8"); } + void DCP::write_assetmap ( Standard standard, string pkl_uuid, boost::filesystem::path pkl_path, @@ -470,11 +464,7 @@ DCP::write_assetmap ( _asset_map = p; } -/** Write all the XML files for this DCP. - * @param standand INTEROP or SMPTE. - * @param metadata Metadata to use for PKL and asset map files. - * @param signer Signer to use, or 0. - */ + void DCP::write_xml ( Standard standard, @@ -513,16 +503,14 @@ DCP::write_xml ( write_assetmap (standard, pkl->id(), pkl_path, issuer, creator, issue_date, annotation_text); } + vector<shared_ptr<CPL>> DCP::cpls () const { return _cpls; } -/** @param ignore_unresolved true to silently ignore unresolved assets, otherwise - * an exception is thrown if they are found. - * @return All assets (including CPLs). - */ + vector<shared_ptr<Asset>> DCP::assets (bool ignore_unresolved) const { @@ -557,6 +545,7 @@ DCP::assets (bool ignore_unresolved) const return assets; } + /** Given a list of files that make up 1 or more DCPs, return the DCP directories */ vector<boost::filesystem::path> DCP::directories_from_files (vector<boost::filesystem::path> files) @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,13 +31,16 @@ files in the program, then also delete it here. */ + /** @file src/dcp.h * @brief DCP class. */ + #ifndef LIBDCP_DCP_H #define LIBDCP_DCP_H + #include "compose.hpp" #include "types.h" #include "util.h" @@ -46,20 +49,23 @@ #include "name_format.h" #include "verify.h" #include "version.h" -#include <memory> #include <boost/signals2.hpp> +#include <memory> #include <string> #include <vector> + namespace xmlpp { class Document; class Element; } + /** @brief Namespace for everything in libdcp */ namespace dcp { + class PKL; class Content; class Reel; @@ -69,11 +75,11 @@ class DecryptedKDM; class Asset; class ReadError; + /** @class DCP - * @brief A class to create or read a DCP. + * @brief A class to create or read a DCP */ - -class DCP : public boost::noncopyable +class DCP { public: /** Construct a DCP. You can pass an existing DCP's directory @@ -85,13 +91,28 @@ public: */ explicit DCP (boost::filesystem::path directory); - /** Read the DCP's structure into this object. + DCP (DCP const&) = delete; + DCP& operator= (DCP const&) = delete; + + /** Read a DCP. This method does not do any deep checking of the DCP's validity, but + * if it comes across any bad things it will do one of two things. + * + * Errors that are so serious that they prevent the method from working will result + * in an exception being thrown. For example, a missing ASSETMAP means that the DCP + * can't be read without a lot of guesswork, so this will throw. + * + * Errors that are not fatal will be added to notes, if it's non-null. For example, + * if the DCP contains a mixture of Interop and SMPTE elements this will result + * in a note being added to the vector. + * + * For more thorough checking of a DCP's contents, see dcp::verify(). + * * @param notes List of notes that will be added to if non-0. * @param ignore_incorrect_picture_mxf_type true to try loading MXF files marked as monoscopic * as stereoscopic if the monoscopic load fails; fixes problems some 3D DCPs that (I think) * have an incorrect descriptor in their MXF. */ - void read (std::vector<VerificationNote>* notes = 0, bool ignore_incorrect_picture_mxf_type = false); + void read (std::vector<VerificationNote>* notes = nullptr, bool ignore_incorrect_picture_mxf_type = false); /** Compare this DCP with another, according to various options. * @param other DCP to compare this one to. @@ -104,20 +125,38 @@ public: void add (std::shared_ptr<CPL> cpl); std::vector<std::shared_ptr<CPL>> cpls () const; + + /** @param ignore_unresolved true to silently ignore unresolved assets, otherwise + * an exception is thrown if they are found. + * @return All assets (including CPLs). + */ std::vector<std::shared_ptr<Asset>> assets (bool ignore_unresolved = false) const; bool any_encrypted () const; bool all_encrypted () const; + /** Add a KDM to decrypt this DCP. This method must be called after DCP::read() + * or the KDM you specify will be ignored. + * @param kdm KDM to use. + */ void add (DecryptedKDM const &); + /** Write all the XML files for this DCP + * @param standand INTEROP or SMPTE + * @param issuer Value for the PKL and AssetMap <Issuer> tags + * @param creator Value for the PKL and AssetMap <Creator> tags + * @param issue_date Value for the CPL <IssueDate> tags + * @param annotation_text Value for the CPL <AnnotationText> tags + * @param signer Signer to use + * @param name_format Name format to use for the CPL and PKL filenames + */ void write_xml ( Standard standard, std::string issuer = String::compose("libdcp %1", dcp::version), std::string creator = String::compose("libdcp %1", dcp::version), std::string issue_date = LocalTime().as_string(), std::string annotation_text = String::compose("Created by libdcp %1", dcp::version), - std::shared_ptr<const CertificateChain> signer = std::shared_ptr<const CertificateChain> (), + std::shared_ptr<const CertificateChain> signer = std::shared_ptr<const CertificateChain>(), NameFormat name_format = NameFormat("%t") ); @@ -171,6 +210,8 @@ private: boost::optional<Standard> _standard; }; + } + #endif diff --git a/src/exceptions.h b/src/exceptions.h index 76a66808..48961073 100644 --- a/src/exceptions.h +++ b/src/exceptions.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,19 +31,24 @@ files in the program, then also delete it here. */ + +/** @file src/exceptions.h + * @brief Exceptions thrown by libdcp + */ + + #ifndef LIBDCP_EXCEPTIONS_H #define LIBDCP_EXCEPTIONS_H + #include <boost/filesystem.hpp> #include <boost/optional.hpp> -/** @file src/exceptions.h - * @brief Exceptions thrown by libdcp. - */ namespace dcp { + /** @class FileError * @brief An exception related to a file */ @@ -69,6 +74,7 @@ private: int _number; }; + /** @class MXFFileError * @brief An exception related to an MXF file */ @@ -80,6 +86,7 @@ public: {} }; + /** @class MiscError * @brief A miscellaneous exception */ @@ -93,7 +100,7 @@ public: /** @class ReadError - * @brief Any error that occurs when reading data from a DCP. + * @brief Any error that occurs when reading data from a DCP */ class ReadError : public std::runtime_error { @@ -122,7 +129,7 @@ private: /** @class J2KDecompressionError - * @brief An error that occurs during decompression of JPEG2000 data. + * @brief An error that occurs during decompression of JPEG2000 data */ class J2KDecompressionError : public ReadError { @@ -139,6 +146,7 @@ public: BadContentKindError (std::string content_kind); }; + /** @class XMLError * @brief An XML error */ @@ -150,6 +158,7 @@ public: {} }; + /** @class UnresolvedRefError * @brief An exception caused by a reference (by UUID) to something which is not known */ @@ -159,8 +168,9 @@ public: explicit UnresolvedRefError (std::string id); }; + /** @class TimeFormatError - * @brief A an error with a string passed to LocalTime. + * @brief A an error with a string passed to LocalTime */ class TimeFormatError : public std::runtime_error { @@ -168,9 +178,10 @@ public: explicit TimeFormatError (std::string bad_time); }; + /** @class NotEncryptedError * @brief An error raised when creating a DecryptedKDM object for assets that are not - * encrypted. + * encrypted */ class NotEncryptedError : public std::runtime_error { @@ -179,8 +190,9 @@ public: ~NotEncryptedError () throw () {} }; + /** @class ProgrammingError - * @brief An exception thrown when a DCP_ASSERT fails; something that should not happen. + * @brief An exception thrown when a DCP_ASSERT fails; something that should not happen */ class ProgrammingError : public std::runtime_error { @@ -188,30 +200,35 @@ public: ProgrammingError (std::string file, int line); }; + class KDMDecryptionError : public std::runtime_error { public: KDMDecryptionError (std::string message, int cipher_length, int modulus_dmax); }; + class KDMFormatError : public std::runtime_error { public: KDMFormatError (std::string message); }; + class CertificateChainError : public std::runtime_error { public: CertificateChainError (std::string message); }; + class MissingSubtitleImageError : public std::runtime_error { public: MissingSubtitleImageError (std::string id); }; + class BadKDMDateError : public std::runtime_error { public: @@ -289,6 +306,8 @@ public: NoReelsError (); }; + } + #endif diff --git a/src/frame.h b/src/frame.h index 7aa471fd..328b22b8 100644 --- a/src/frame.h +++ b/src/frame.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,19 +31,22 @@ files in the program, then also delete it here. */ + #ifndef LIBDCP_FRAME_H #define LIBDCP_FRAME_H + #include "crypto_context.h" #include "exceptions.h" #include <asdcp/KM_fileio.h> #include <asdcp/AS_DCP.h> -#include <boost/noncopyable.hpp> + namespace dcp { + template <class R, class B> -class Frame : public boost::noncopyable +class Frame { public: Frame (R* reader, int n, std::shared_ptr<const DecryptionContext> c) @@ -51,11 +54,14 @@ public: /* XXX: unfortunate guesswork on this buffer size */ _buffer.reset(new B(Kumu::Megabyte)); - if (ASDCP_FAILURE (reader->ReadFrame (n, *_buffer, c->context(), c->hmac()))) { + if (ASDCP_FAILURE(reader->ReadFrame(n, *_buffer, c->context(), c->hmac()))) { boost::throw_exception (ReadError ("could not read frame")); } } + Frame (Frame const&) = delete; + Frame& operator= (Frame const&) = delete; + uint8_t const * data () const { return _buffer->RoData (); @@ -70,6 +76,8 @@ private: std::shared_ptr<B> _buffer; }; + } + #endif diff --git a/src/gamma_transfer_function.cc b/src/gamma_transfer_function.cc index c7c16f24..34501d98 100644 --- a/src/gamma_transfer_function.cc +++ b/src/gamma_transfer_function.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,24 +31,29 @@ files in the program, then also delete it here. */ + /** @file src/gamma_transfer_function.cc - * @brief GammaTransferFunction class. + * @brief GammaTransferFunction class */ + #include "gamma_transfer_function.h" #include <cmath> + using std::pow; using std::shared_ptr; using std::dynamic_pointer_cast; using namespace dcp; + GammaTransferFunction::GammaTransferFunction (double gamma) : _gamma (gamma) { } + double * GammaTransferFunction::make_lut (int bit_depth, bool inverse) const { @@ -62,13 +67,14 @@ GammaTransferFunction::make_lut (int bit_depth, bool inverse) const return lut; } + bool GammaTransferFunction::about_equal (shared_ptr<const TransferFunction> other, double epsilon) const { - shared_ptr<const GammaTransferFunction> o = dynamic_pointer_cast<const GammaTransferFunction> (other); + auto o = dynamic_pointer_cast<const GammaTransferFunction>(other); if (!o) { return false; } - return fabs (_gamma - o->_gamma) < epsilon; + return fabs(_gamma - o->_gamma) < epsilon; } diff --git a/src/gamma_transfer_function.h b/src/gamma_transfer_function.h index f1a1c13b..a7bdd44d 100644 --- a/src/gamma_transfer_function.h +++ b/src/gamma_transfer_function.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,16 +31,20 @@ files in the program, then also delete it here. */ + /** @file src/gamma_transfer_function.h - * @brief GammaTransferFunction class. + * @brief GammaTransferFunction class */ + #include "transfer_function.h" + namespace dcp { -/** A description of a gamma function of the f(x) = x^g where - * g is the gamma. + +/** @class GammaTransferFunction + * @brief A description of a gamma function of the f(x) = x^g where g is the gamma */ class GammaTransferFunction : public TransferFunction { @@ -60,4 +64,5 @@ private: double _gamma; }; + } @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ files in the program, then also delete it here. */ + /** @file src/key.cc * @brief Key class. */ + #include "key.h" #include "dcp_assert.h" #include <asdcp/AS_DCP.h> @@ -43,11 +45,13 @@ #include <string> #include <iomanip> + using std::string; using std::setw; using std::setfill; using namespace dcp; + Key::Key (int length) : _value (new uint8_t[length]) , _length (length) @@ -56,6 +60,7 @@ Key::Key (int length) rng.FillRandom (_value, _length); } + Key::Key (uint8_t const * value, int length) : _value (new uint8_t[length]) , _length (length) @@ -63,6 +68,7 @@ Key::Key (uint8_t const * value, int length) memcpy (_value, value, _length); } + Key::Key (string value) : _value (new uint8_t[value.length() / 2]) , _length (value.length() / 2) @@ -71,6 +77,7 @@ Key::Key (string value) Kumu::hex2bin (value.c_str(), _value, _length, &length_done); } + Key::Key (Key const & other) : _value (new uint8_t[other._length]) , _length (other._length) @@ -78,11 +85,13 @@ Key::Key (Key const & other) memcpy (_value, other._value, _length); } + Key::~Key () { delete[] _value; } + Key & Key::operator= (Key const & other) { @@ -95,6 +104,7 @@ Key::operator= (Key const & other) return *this; } + string Key::hex () const { @@ -113,12 +123,14 @@ Key::hex () const return buffer; } + bool dcp::operator== (Key const & a, Key const & b) { return a.length() == b.length() && memcmp(a.value(), b.value(), a.length()) == 0; } + bool dcp::operator!= (Key const & a, Key const & b) { @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,21 +31,26 @@ files in the program, then also delete it here. */ + /** @file src/key.h - * @brief Key class. + * @brief Key class */ + #ifndef LIBDCP_KEY_H #define LIBDCP_KEY_H + #include <asdcp/AS_DCP.h> #include <stdint.h> #include <string> + namespace dcp { + /** @class Key - * @brief A key for decrypting/encrypting assets. + * @brief A key for decrypting/encrypting assets */ class Key { @@ -78,13 +83,15 @@ public: private: /** Raw key value */ - uint8_t* _value; - int _length; + uint8_t* _value = nullptr; + int _length = 0; }; + extern bool operator== (Key const & a, Key const & b); extern bool operator!= (Key const & a, Key const & b); + } #endif diff --git a/src/mono_picture_frame.h b/src/mono_picture_frame.h index 67784509..d6774aef 100644 --- a/src/mono_picture_frame.h +++ b/src/mono_picture_frame.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,22 +31,25 @@ files in the program, then also delete it here. */ + #ifndef LIBDCP_MONO_PICTURE_FRAME_H #define LIBDCP_MONO_PICTURE_FRAME_H + /** @file src/mono_picture_frame.h - * @brief MonoPictureFrame class. + * @brief MonoPictureFrame class */ + #include "types.h" #include "asset_reader.h" #include <memory> -#include <boost/noncopyable.hpp> #include <boost/filesystem.hpp> #include <boost/optional.hpp> #include <string> #include <stdint.h> + namespace ASDCP { namespace JP2K { class FrameBuffer; @@ -55,19 +58,25 @@ namespace ASDCP { class AESDecContext; } + namespace dcp { + class OpenJPEGImage; + /** @class MonoPictureFrame * @brief A single frame of a 2D (monoscopic) picture asset. */ -class MonoPictureFrame : public Data, public boost::noncopyable +class MonoPictureFrame : public Data { public: explicit MonoPictureFrame (boost::filesystem::path path); MonoPictureFrame (uint8_t const * data, int size); + MonoPictureFrame (MonoPictureFrame const&) = delete; + MonoPictureFrame& operator= (MonoPictureFrame const&) = delete; + std::shared_ptr<OpenJPEGImage> xyz_image (int reduce = 0) const; uint8_t const * data () const; diff --git a/src/object.cc b/src/object.cc index 08268f18..c3bccd06 100644 --- a/src/object.cc +++ b/src/object.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,27 +31,28 @@ files in the program, then also delete it here. */ + /** @file src/object.cc - * @brief Object class. + * @brief Object class */ + #include "object.h" #include "dcp_assert.h" #include "util.h" + using std::string; using namespace dcp; -/** Create an Object with a random ID. */ + Object::Object () - : _id (make_uuid ()) + : _id (make_uuid()) { } -/** Create an Object with a given ID. - * @param id ID to use. - */ + Object::Object (string id) : _id (id) { diff --git a/src/object.h b/src/object.h index aa0fe6b3..d1d476c8 100644 --- a/src/object.h +++ b/src/object.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,16 +31,19 @@ files in the program, then also delete it here. */ + /** @file src/object.h - * @brief Object class. + * @brief Object class */ + #ifndef LIBDCP_OBJECT_H #define LIBDCP_OBJECT_H -#include <boost/noncopyable.hpp> + #include <string> + struct write_interop_subtitle_test; struct write_interop_subtitle_test2; struct write_interop_subtitle_test3; @@ -49,19 +52,29 @@ struct write_smpte_subtitle_test2; struct write_smpte_subtitle_test3; struct sync_test2; + namespace dcp { + /** @class Object - * @brief Some part of a DCP that has a UUID. + * @brief Some part of a DCP that has a UUID */ -class Object : public boost::noncopyable +class Object { public: + /** Create an Object with a random ID */ Object (); + + /** Create an Object with a given ID. + * @param id ID to use. + */ explicit Object (std::string id); + + Object (Object const&) = delete; + Object& operator= (Object const&) = delete; + virtual ~Object () {} - /** @return ID */ std::string id () const { return _id; } @@ -75,7 +88,6 @@ protected: friend struct ::write_smpte_subtitle_test3; friend struct ::sync_test2; - /** ID */ std::string _id; }; @@ -1,5 +1,5 @@ /* - Copyright (C) 2018 Carl Hetherington <cth@carlh.net> + Copyright (C) 2018-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,6 +31,7 @@ files in the program, then also delete it here. */ + #include "pkl.h" #include "exceptions.h" #include "util.h" @@ -39,15 +40,18 @@ #include <libxml++/libxml++.h> #include <iostream> + using std::string; using std::shared_ptr; using std::make_shared; using boost::optional; using namespace dcp; + static string const pkl_interop_ns = "http://www.digicine.com/PROTO-ASDCP-PKL-20040311#"; static string const pkl_smpte_ns = "http://www.smpte-ra.org/schemas/429-8/2007/PKL"; + PKL::PKL (boost::filesystem::path file) : _file (file) { @@ -73,12 +77,14 @@ PKL::PKL (boost::filesystem::path file) } } + void PKL::add_asset (std::string id, boost::optional<std::string> annotation_text, std::string hash, int64_t size, std::string type) { _asset_list.push_back (make_shared<Asset>(id, annotation_text, hash, size, type)); } + void PKL::write (boost::filesystem::path file, shared_ptr<const CertificateChain> signer) const { @@ -120,6 +126,7 @@ PKL::write (boost::filesystem::path file, shared_ptr<const CertificateChain> sig _file = file; } + optional<string> PKL::hash (string id) const { @@ -132,6 +139,7 @@ PKL::hash (string id) const return {}; } + optional<string> PKL::type (string id) const { @@ -1,5 +1,5 @@ /* - Copyright (C) 2018 Carl Hetherington <cth@carlh.net> + Copyright (C) 2018-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,9 +31,11 @@ files in the program, then also delete it here. */ + #ifndef LIBDCP_PKL_H #define LIBDCP_PKL_H + #include "object.h" #include "types.h" #include "util.h" @@ -41,8 +43,10 @@ #include <libcxml/cxml.h> #include <boost/filesystem.hpp> + namespace dcp { + class PKL : public Object { public: @@ -113,7 +117,7 @@ public: private: boost::optional<std::string> _annotation_text; std::string _hash; - int64_t _size; + int64_t _size = 0; std::string _type; }; @@ -123,7 +127,7 @@ public: private: - Standard _standard; + Standard _standard = dcp::Standard::SMPTE; boost::optional<std::string> _annotation_text; std::string _issue_date; std::string _issuer; diff --git a/src/reel.cc b/src/reel.cc index 25019d35..16316487 100644 --- a/src/reel.cc +++ b/src/reel.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,6 +31,7 @@ files in the program, then also delete it here. */ + #include "reel.h" #include "util.h" #include "picture_asset.h" @@ -52,10 +53,6 @@ #include <libxml++/nodes/element.h> #include <stdint.h> -/* Centos 6 does not have this */ -#ifndef INT64_MAX -#define INT64_MAX 0x7fffffffffffffff -#endif using std::string; using std::cout; @@ -66,6 +63,7 @@ using std::dynamic_pointer_cast; using std::vector; using namespace dcp; + Reel::Reel (std::shared_ptr<const cxml::Node> node) : Object (remove_urn_uuid (node->string_child ("Id"))) { @@ -73,27 +71,27 @@ Reel::Reel (std::shared_ptr<const cxml::Node> node) auto main_picture = asset_list->optional_node_child ("MainPicture"); if (main_picture) { - _main_picture.reset (new ReelMonoPictureAsset (main_picture)); + _main_picture = make_shared<ReelMonoPictureAsset>(main_picture); } auto main_stereoscopic_picture = asset_list->optional_node_child ("MainStereoscopicPicture"); if (main_stereoscopic_picture) { - _main_picture.reset (new ReelStereoPictureAsset (main_stereoscopic_picture)); + _main_picture = make_shared<ReelStereoPictureAsset>(main_stereoscopic_picture); } auto main_sound = asset_list->optional_node_child ("MainSound"); if (main_sound) { - _main_sound.reset (new ReelSoundAsset (main_sound)); + _main_sound = make_shared<ReelSoundAsset>(main_sound); } auto main_subtitle = asset_list->optional_node_child ("MainSubtitle"); if (main_subtitle) { - _main_subtitle.reset (new ReelSubtitleAsset (main_subtitle)); + _main_subtitle = make_shared<ReelSubtitleAsset>(main_subtitle); } auto main_markers = asset_list->optional_node_child ("MainMarkers"); if (main_markers) { - _main_markers.reset (new ReelMarkersAsset (main_markers)); + _main_markers = make_shared<ReelMarkersAsset>(main_markers); } /* XXX: it's not ideal that we silently tolerate Interop or SMPTE nodes here */ @@ -115,6 +113,7 @@ Reel::Reel (std::shared_ptr<const cxml::Node> node) node->done (); } + xmlpp::Element * Reel::write_to_cpl (xmlpp::Element* node, Standard standard) const { @@ -155,6 +154,7 @@ Reel::write_to_cpl (xmlpp::Element* node, Standard standard) const return asset_list; } + bool Reel::equals (std::shared_ptr<const Reel> other, EqualityOptions opt, NoteHandler note) const { @@ -221,6 +221,7 @@ Reel::equals (std::shared_ptr<const Reel> other, EqualityOptions opt, NoteHandle return true; } + bool Reel::any_encrypted () const { @@ -260,6 +261,7 @@ Reel::all_encrypted () const ); } + void Reel::add (DecryptedKDM const & kdm) { @@ -292,6 +294,7 @@ Reel::add (DecryptedKDM const & kdm) } } + void Reel::add (shared_ptr<ReelAsset> asset) { @@ -316,6 +319,7 @@ Reel::add (shared_ptr<ReelAsset> asset) } } + vector<shared_ptr<ReelAsset>> Reel::assets () const { @@ -336,19 +340,20 @@ Reel::assets () const return a; } + void Reel::resolve_refs (vector<shared_ptr<Asset>> assets) { if (_main_picture) { - _main_picture->asset_ref().resolve (assets); + _main_picture->asset_ref().resolve(assets); } if (_main_sound) { - _main_sound->asset_ref().resolve (assets); + _main_sound->asset_ref().resolve(assets); } if (_main_subtitle) { - _main_subtitle->asset_ref().resolve (assets); + _main_subtitle->asset_ref().resolve(assets); /* Interop subtitle handling is all special cases */ if (_main_subtitle->asset_ref().resolved()) { @@ -376,6 +381,7 @@ Reel::resolve_refs (vector<shared_ptr<Asset>> assets) } } + int64_t Reel::duration () const { @@ -31,25 +31,31 @@ files in the program, then also delete it here. */ + #ifndef LIBDCP_REEL_H #define LIBDCP_REEL_H + #include "key.h" #include "types.h" #include "ref.h" #include <memory> #include <boost/function.hpp> + namespace cxml { class Node; } + namespace xmlpp { class Element; } + namespace dcp { + class DecryptedKDM; class ReelAsset; class ReelPictureAsset; @@ -60,6 +66,7 @@ class ReelClosedCaptionAsset; class ReelAtmosAsset; class Content; + /** @brief A reel within a DCP; the part which actually refers to picture, sound, subtitle, marker and Atmos data */ class Reel : public Object { diff --git a/src/reel_mxf.cc b/src/reel_mxf.cc index 24442691..1e7d9474 100644 --- a/src/reel_mxf.cc +++ b/src/reel_mxf.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,6 +31,12 @@ files in the program, then also delete it here. */ + +/** @file src/reel_mxf.cc + * @brief ReelMXF class + */ + + #include "reel_mxf.h" #include "util.h" #include "mxf.h" @@ -38,11 +44,13 @@ #include <libcxml/cxml.h> #include <libxml++/libxml++.h> + using std::string; using std::shared_ptr; using boost::optional; using namespace dcp; + ReelMXF::ReelMXF (shared_ptr<Asset> asset, optional<string> key_id) : _asset_ref (asset) , _key_id (key_id) @@ -51,6 +59,7 @@ ReelMXF::ReelMXF (shared_ptr<Asset> asset, optional<string> key_id) } + ReelMXF::ReelMXF (shared_ptr<const cxml::Node> node) : _asset_ref (remove_urn_uuid(node->string_child("Id"))) , _key_id (node->optional_string_child ("KeyId")) @@ -61,6 +70,7 @@ ReelMXF::ReelMXF (shared_ptr<const cxml::Node> node) } } + bool ReelMXF::mxf_equals (shared_ptr<const ReelMXF> other, EqualityOptions opt, NoteHandler note) const { @@ -85,7 +95,7 @@ void ReelMXF::write_to_cpl_mxf (xmlpp::Node* node) const { if (key_id ()) { - xmlpp::Node* hash = find_child (node, "Hash"); + auto hash = find_child (node, "Hash"); node->add_child_before(hash, "KeyId")->add_child_text("urn:uuid:" + key_id().get()); } } diff --git a/src/reel_mxf.h b/src/reel_mxf.h index 07514189..099ddfeb 100644 --- a/src/reel_mxf.h +++ b/src/reel_mxf.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,26 +31,32 @@ files in the program, then also delete it here. */ + /** @file src/reel_mxf.h - * @brief ReelMXF + * @brief ReelMXF class */ + #ifndef LIBDCP_REEL_MXF_H #define LIBDCP_REEL_MXF_H + #include "ref.h" #include <boost/optional.hpp> #include <memory> #include <string> + namespace cxml { class Node; } + namespace dcp { + /** @class ReelMXF - * @brief Part of a Reel's description which refers to an asset which can be encrypted. + * @brief Part of a Reel's description which refers to an asset which can be encrypted */ class ReelMXF { @@ -124,6 +130,8 @@ private: boost::optional<std::string> _hash; }; + } + #endif @@ -31,15 +31,20 @@ files in the program, then also delete it here. */ + +/** @file src/ref.cc + * @brief Ref class + */ + + #include "ref.h" + using std::shared_ptr; using std::vector; using namespace dcp; -/** Look through a list of assets and copy a shared_ptr to any asset - * which matches the ID of this one. - */ + void Ref::resolve (vector<shared_ptr<Asset>> assets) { @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,23 +31,28 @@ files in the program, then also delete it here. */ + /** @file src/ref.h - * @brief Ref class. + * @brief Ref class */ + #ifndef LIBDCP_REF_H #define LIBDCP_REF_H + #include "exceptions.h" #include "asset.h" #include "util.h" #include <memory> #include <string> + namespace dcp { + /** @class Ref - * @brief A reference to an asset which is identified by a universally-unique identifier (UUID). + * @brief A reference to an asset which is identified by a universally-unique identifier (UUID) * * This class is a `pointer' to a thing. It will always know the * UUID of the thing, and it may have a shared_ptr to the C++ object @@ -77,6 +82,9 @@ public: _id = id; } + /** Look through a list of assets and copy a shared_ptr to any asset + * which matches the ID of this one + */ void resolve (std::vector<std::shared_ptr<Asset>> assets); /** @return the ID of the thing that we are pointing to */ @@ -85,7 +93,7 @@ public: } /** @return a shared_ptr to the thing; an UnresolvedRefError is thrown - * if the shared_ptr is not known. + * if the shared_ptr is not known */ std::shared_ptr<Asset> asset () const { if (!_asset) { @@ -96,7 +104,7 @@ public: } /** operator-> to access the shared_ptr; an UnresolvedRefError is thrown - * if the shared_ptr is not known. + * if the shared_ptr is not known */ Asset * operator->() const { if (!_asset) { @@ -116,6 +124,8 @@ private: std::shared_ptr<Asset> _asset; ///< shared_ptr to the thing, may be null. }; + } + #endif diff --git a/src/stereo_picture_frame.cc b/src/stereo_picture_frame.cc index 8508dc3e..8df4fcc2 100644 --- a/src/stereo_picture_frame.cc +++ b/src/stereo_picture_frame.cc @@ -31,6 +31,7 @@ files in the program, then also delete it here. */ + #include "stereo_picture_frame.h" #include "exceptions.h" #include "util.h" @@ -42,6 +43,7 @@ #include <asdcp/AS_DCP.h> #include <asdcp/KM_fileio.h> + using std::string; using std::shared_ptr; using std::make_shared; @@ -91,16 +93,17 @@ StereoPictureFrame::Part::size () const StereoPictureFrame::StereoPictureFrame (ASDCP::JP2K::MXFSReader* reader, int n, shared_ptr<DecryptionContext> c) { /* XXX: unfortunate guesswork on this buffer size */ - _buffer.reset(new ASDCP::JP2K::SFrameBuffer(4 * Kumu::Megabyte)); + _buffer = make_shared<ASDCP::JP2K::SFrameBuffer>(4 * Kumu::Megabyte); if (ASDCP_FAILURE (reader->ReadFrame (n, *_buffer, c->context(), c->hmac()))) { boost::throw_exception (ReadError (String::compose ("could not read video frame %1 of %2", n))); } } + StereoPictureFrame::StereoPictureFrame () { - _buffer.reset(new ASDCP::JP2K::SFrameBuffer(4 * Kumu::Megabyte)); + _buffer = make_shared<ASDCP::JP2K::SFrameBuffer>(4 * Kumu::Megabyte); } @@ -114,12 +117,12 @@ StereoPictureFrame::xyz_image (Eye eye, int reduce) const { switch (eye) { case Eye::LEFT: - return decompress_j2k (const_cast<uint8_t*> (_buffer->Left.RoData()), _buffer->Left.Size(), reduce); + return decompress_j2k (const_cast<uint8_t*>(_buffer->Left.RoData()), _buffer->Left.Size(), reduce); case Eye::RIGHT: - return decompress_j2k (const_cast<uint8_t*> (_buffer->Right.RoData()), _buffer->Right.Size(), reduce); + return decompress_j2k (const_cast<uint8_t*>(_buffer->Right.RoData()), _buffer->Right.Size(), reduce); } - return shared_ptr<OpenJPEGImage> (); + return {}; } diff --git a/src/stereo_picture_frame.h b/src/stereo_picture_frame.h index 3d334d34..c499b8fe 100644 --- a/src/stereo_picture_frame.h +++ b/src/stereo_picture_frame.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,17 +31,24 @@ files in the program, then also delete it here. */ + +/** @file src/stereo_picture_frame.h + * @brief StereoPictureFrame class + */ + + #ifndef LIBDCP_STEREO_PICTURE_FRAME_H #define LIBDCP_STEREO_PICTURE_FRAME_H + #include "types.h" #include "asset_reader.h" #include <memory> -#include <boost/noncopyable.hpp> #include <boost/filesystem.hpp> #include <stdint.h> #include <string> + namespace ASDCP { namespace JP2K { struct SFrameBuffer; @@ -50,6 +57,7 @@ namespace ASDCP { class AESDecContext; } + namespace dcp { @@ -57,12 +65,17 @@ class OpenJPEGImage; class StereoPictureFrame; -/** A single frame of a 3D (stereoscopic) picture asset */ -class StereoPictureFrame : public boost::noncopyable +/** @class StereoPictureFrame + * @brief A single frame of a 3D (stereoscopic) picture asset + */ +class StereoPictureFrame { public: StereoPictureFrame (); + StereoPictureFrame (StereoPictureFrame const &) = delete; + StereoPictureFrame& operator= (StereoPictureFrame const &) = delete; + std::shared_ptr<OpenJPEGImage> xyz_image (Eye eye, int reduce = 0) const; class Part : public Data @@ -97,6 +110,8 @@ private: std::shared_ptr<ASDCP::JP2K::SFrameBuffer> _buffer; }; + } + #endif diff --git a/src/transfer_function.h b/src/transfer_function.h index 52624c66..508ff934 100644 --- a/src/transfer_function.h +++ b/src/transfer_function.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,26 +31,35 @@ files in the program, then also delete it here. */ + /** @file src/transfer_function.h * @brief TransferFunction class. */ + #ifndef LIBDCP_TRANSFER_FUNCTION_H #define LIBDCP_TRANSFER_FUNCTION_H -#include <boost/noncopyable.hpp> -#include <memory> + #include <boost/thread/mutex.hpp> #include <map> +#include <memory> + namespace dcp { + /** @class TransferFunction * @brief A transfer function represented by a lookup table. */ -class TransferFunction : public boost::noncopyable +class TransferFunction { public: + TransferFunction () {} + + TransferFunction (TransferFunction const&) = delete; + TransferFunction& operator= (TransferFunction const&) = delete; + virtual ~TransferFunction (); /** @return A look-up table (of size 2^bit_depth) whose values range from 0 to 1 */ @@ -68,6 +77,8 @@ private: mutable boost::mutex _mutex; }; + } + #endif diff --git a/src/util.cc b/src/util.cc index 2aaeddb5..7c21c889 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,12 @@ files in the program, then also delete it here. */ + /** @file src/util.cc - * @brief Utility methods. + * @brief Utility methods and classes */ + #include "util.h" #include "language_tag.h" #include "exceptions.h" @@ -60,6 +62,7 @@ #include <iostream> #include <iomanip> + using std::string; using std::wstring; using std::cout; @@ -80,12 +83,9 @@ using namespace dcp; /* Some ASDCP objects store this as a *&, for reasons which are not * at all clear, so we have to keep this around forever. */ -ASDCP::Dictionary const* dcp::asdcp_smpte_dict = 0; +ASDCP::Dictionary const* dcp::asdcp_smpte_dict = nullptr; -/** Create a UUID. - * @return UUID. - */ string dcp::make_uuid () { @@ -96,6 +96,7 @@ dcp::make_uuid () return string (buffer); } + string dcp::make_digest (ArrayData data) { @@ -108,19 +109,14 @@ dcp::make_digest (ArrayData data) return Kumu::base64encode (byte_buffer, SHA_DIGEST_LENGTH, digest, 64); } -/** Create a digest for a file. - * @param filename File name. - * @param progress Optional progress reporting function. The function will be called - * with a progress value between 0 and 1. - * @return Digest. - */ + string dcp::make_digest (boost::filesystem::path filename, function<void (float)> progress) { Kumu::FileReader reader; - Kumu::Result_t r = reader.OpenRead (filename.string().c_str ()); - if (ASDCP_FAILURE (r)) { - boost::throw_exception (FileError ("could not open file to compute digest", filename, r)); + auto r = reader.OpenRead (filename.string().c_str ()); + if (ASDCP_FAILURE(r)) { + boost::throw_exception (FileError("could not open file to compute digest", filename, r)); } SHA_CTX sha; @@ -131,14 +127,14 @@ dcp::make_digest (boost::filesystem::path filename, function<void (float)> progr Kumu::fsize_t done = 0; Kumu::fsize_t const size = reader.Size (); - while (1) { + while (true) { ui32_t read = 0; - Kumu::Result_t r = reader.Read (read_buffer.Data(), read_buffer.Capacity(), &read); + auto r = reader.Read (read_buffer.Data(), read_buffer.Capacity(), &read); if (r == Kumu::RESULT_ENDOFFILE) { break; } else if (ASDCP_FAILURE (r)) { - boost::throw_exception (FileError ("could not read file to compute digest", filename, r)); + boost::throw_exception (FileError("could not read file to compute digest", filename, r)); } SHA1_Update (&sha, read_buffer.Data(), read); @@ -156,9 +152,7 @@ dcp::make_digest (boost::filesystem::path filename, function<void (float)> progr return Kumu::base64encode (byte_buffer, SHA_DIGEST_LENGTH, digest, 64); } -/** @param s A string. - * @return true if the string contains only space, newline or tab characters, or is empty. - */ + bool dcp::empty_or_white_space (string s) { @@ -171,13 +165,7 @@ dcp::empty_or_white_space (string s) return true; } -/** Set up various bits that the library needs. Should be called once - * by client applications. - * - * @param tags_directory Path to a copy of the tags directory from the source code; - * if none is specified libdcp will look for a tags directory inside the environment - * variable LIBDCP_SHARE_PREFIX or the LIBDCP_SHARE_PREFIX #defined during the build. - */ + void dcp::init (optional<boost::filesystem::path> tags_directory) { @@ -215,19 +203,11 @@ dcp::init (optional<boost::filesystem::path> tags_directory) load_language_tag_lists (*tags_directory); } -/** Decode a base64 string. The base64 decode routine in KM_util.cpp - * gives different values to both this and the command-line base64 - * for some inputs. Not sure why. - * - * @param in base64-encoded string. - * @param out Output buffer. - * @param out_length Length of output buffer. - * @return Number of characters written to the output buffer. - */ + int dcp::base64_decode (string const & in, unsigned char* out, int out_length) { - BIO* b64 = BIO_new (BIO_f_base64 ()); + auto b64 = BIO_new (BIO_f_base64()); /* This means the input should have no newlines */ BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL); @@ -241,7 +221,7 @@ dcp::base64_decode (string const & in, unsigned char* out, int out_length) } } - BIO* bmem = BIO_new_mem_buf (in_buffer, p - in_buffer); + auto bmem = BIO_new_mem_buf (in_buffer, p - in_buffer); bmem = BIO_push (b64, bmem); int const N = BIO_read (bmem, out, out_length); BIO_free_all (bmem); @@ -249,14 +229,7 @@ dcp::base64_decode (string const & in, unsigned char* out, int out_length) return N; } -/** @param p Path to open. - * @param t mode flags, as for fopen(3). - * @return FILE pointer or 0 on error. - * - * Apparently there is no way to create an ofstream using a UTF-8 - * filename under Windows. We are hence reduced to using fopen - * with this wrapper. - */ + FILE * dcp::fopen_boost (boost::filesystem::path p, string t) { @@ -269,29 +242,31 @@ dcp::fopen_boost (boost::filesystem::path p, string t) #endif } + optional<boost::filesystem::path> dcp::relative_to_root (boost::filesystem::path root, boost::filesystem::path file) { - boost::filesystem::path::const_iterator i = root.begin (); - boost::filesystem::path::const_iterator j = file.begin (); + auto i = root.begin (); + auto j = file.begin (); while (i != root.end() && j != file.end() && *i == *j) { ++i; ++j; } - if (i != root.end ()) { - return optional<boost::filesystem::path> (); + if (i != root.end()) { + return {}; } boost::filesystem::path rel; - while (j != file.end ()) { + while (j != file.end()) { rel /= *j++; } return rel; } + bool dcp::ids_equal (string a, string b) { @@ -302,15 +277,16 @@ dcp::ids_equal (string a, string b) return a == b; } + string dcp::file_to_string (boost::filesystem::path p, uintmax_t max_length) { - uintmax_t len = boost::filesystem::file_size (p); + auto len = boost::filesystem::file_size (p); if (len > max_length) { - throw MiscError (String::compose ("Unexpectedly long file (%1)", p.string())); + throw MiscError (String::compose("Unexpectedly long file (%1)", p.string())); } - FILE* f = fopen_boost (p, "r"); + auto f = fopen_boost (p, "r"); if (!f) { throw FileError ("could not open file", p, errno); } @@ -326,9 +302,7 @@ dcp::file_to_string (boost::filesystem::path p, uintmax_t max_length) return s; } -/** @param key RSA private key in PEM format (optionally with -----BEGIN... / -----END...) - * @return SHA1 fingerprint of key - */ + string dcp::private_key_fingerprint (string key) { @@ -348,11 +322,12 @@ dcp::private_key_fingerprint (string key) return Kumu::base64encode (digest, 20, digest_base64, 64); } + xmlpp::Node * dcp::find_child (xmlpp::Node const * node, string name) { - xmlpp::Node::NodeList c = node->get_children (); - xmlpp::Node::NodeList::iterator i = c.begin(); + auto c = node->get_children (); + auto i = c.begin(); while (i != c.end() && (*i)->get_name() != name) { ++i; } @@ -361,6 +336,7 @@ dcp::find_child (xmlpp::Node const * node, string name) return *i; } + string dcp::remove_urn_uuid (string raw) { @@ -368,12 +344,14 @@ dcp::remove_urn_uuid (string raw) return raw.substr (9); } + string dcp::openjpeg_version () { return opj_version (); } + string dcp::spaces (int n) { @@ -384,10 +362,11 @@ dcp::spaces (int n) return s; } + void dcp::indent (xmlpp::Element* element, int initial) { - xmlpp::Node* last = 0; + xmlpp::Node* last = nullptr; for (auto n: element->get_children()) { auto e = dynamic_cast<xmlpp::Element*>(n); if (e) { @@ -401,9 +380,7 @@ dcp::indent (xmlpp::Element* element, int initial) } } -/** @return true if the day represented by \ref a is less than or - * equal to the one represented by \ref b, ignoring the time parts. - */ + bool dcp::day_less_than_or_equal (LocalTime a, LocalTime b) { @@ -418,9 +395,7 @@ dcp::day_less_than_or_equal (LocalTime a, LocalTime b) return a.day() <= b.day(); } -/** @return true if the day represented by \ref a is greater than or - * equal to the one represented by \ref b, ignoring the time parts. - */ + bool dcp::day_greater_than_or_equal (LocalTime a, LocalTime b) { @@ -435,9 +410,7 @@ dcp::day_greater_than_or_equal (LocalTime a, LocalTime b) return a.day() >= b.day(); } -/** Try quite hard to find a string which starts with \ref base and is - * not in \ref existing. - */ + string dcp::unique_string (vector<string> existing, string base) { @@ -31,14 +31,16 @@ files in the program, then also delete it here. */ -#ifndef LIBDCP_UTIL_H -#define LIBDCP_UTIL_H /** @file src/util.h - * @brief Utility methods. + * @brief Utility methods and classes */ +#ifndef LIBDCP_UTIL_H +#define LIBDCP_UTIL_H + + #include "array_data.h" #include "types.h" #include "local_time.h" @@ -50,39 +52,102 @@ #include <string> #include <stdint.h> + #define LIBDCP_UNUSED(x) (void)(x) + namespace xmlpp { class Element; class Node; } + namespace dcp { + class CertificateChain; class GammaLUT; class OpenJPEGImage; + extern std::string make_uuid (); + +/** Create a digest for a file + * @param filename File name + * @param progress Optional progress reporting function. The function will be called + * with a progress value between 0 and 1 + * @return Digest + */ extern std::string make_digest (boost::filesystem::path filename, boost::function<void (float)>); + extern std::string make_digest (ArrayData data); + +/** @param s A string + * @return true if the string contains only space, newline or tab characters, or is empty + */ extern bool empty_or_white_space (std::string s); + extern bool ids_equal (std::string a, std::string b); extern std::string remove_urn_uuid (std::string raw); + +/** Set up various bits that the library needs. Should be called once + * by client applications. + * + * @param tags_directory Path to a copy of the tags directory from the source code; + * if none is specified libdcp will look for a tags directory inside the environment + * variable LIBDCP_SHARE_PREFIX or the LIBDCP_SHARE_PREFIX #defined during the build. + */ extern void init (boost::optional<boost::filesystem::path> tags_directory = boost::optional<boost::filesystem::path>()); +/** Decode a base64 string. The base64 decode routine in KM_util.cpp + * gives different values to both this and the command-line base64 + * for some inputs. Not sure why. + * + * @param in base64-encoded string + * @param out Output buffer + * @param out_length Length of output buffer + * @return Number of characters written to the output buffer + */ extern int base64_decode (std::string const & in, unsigned char* out, int out_length); + extern boost::optional<boost::filesystem::path> relative_to_root (boost::filesystem::path root, boost::filesystem::path file); + +/** @param p Path to open + * @param t mode flags, as for fopen(3) + * @return FILE pointer or 0 on error + * + * Apparently there is no way to create an ofstream using a UTF-8 + * filename under Windows. We are hence reduced to using fopen + * with this wrapper. + */ extern FILE * fopen_boost (boost::filesystem::path, std::string); + extern std::string file_to_string (boost::filesystem::path, uintmax_t max_length = 1048576); + +/** @param key RSA private key in PEM format (optionally with -----BEGIN... / -----END...) + * @return SHA1 fingerprint of key + */ extern std::string private_key_fingerprint (std::string key); extern xmlpp::Node* find_child (xmlpp::Node const * node, std::string name); extern std::string openjpeg_version(); extern std::string spaces (int n); extern void indent (xmlpp::Element* element, int initial); + +/** @return true if the day represented by \ref a is less than or + * equal to the one represented by \ref b, ignoring the time parts + */ extern bool day_less_than_or_equal (LocalTime a, LocalTime b); + +/** @return true if the day represented by \ref a is greater than or + * equal to the one represented by \ref b, ignoring the time parts + */ extern bool day_greater_than_or_equal (LocalTime a, LocalTime b); + +/** Try quite hard to find a string which starts with \ref base and is + * not in \ref existing + */ extern std::string unique_string (std::vector<std::string> existing, std::string base); + extern ASDCP::Dictionary const* asdcp_smpte_dict; diff --git a/src/verify.cc b/src/verify.cc index fe071b48..6f6a48f1 100644 --- a/src/verify.cc +++ b/src/verify.cc @@ -67,7 +67,6 @@ #include <xercesc/dom/DOMErrorHandler.hpp> #include <xercesc/framework/LocalFileInputSource.hpp> #include <xercesc/framework/MemBufInputSource.hpp> -#include <boost/noncopyable.hpp> #include <boost/algorithm/string.hpp> #include <map> #include <vector> @@ -184,7 +183,7 @@ private: list<XMLValidationError> _errors; }; -class StringToXMLCh : public boost::noncopyable +class StringToXMLCh { public: StringToXMLCh (string a) @@ -192,6 +191,9 @@ public: _buffer = XMLString::transcode(a.c_str()); } + StringToXMLCh (StringToXMLCh const&) = delete; + StringToXMLCh& operator= (StringToXMLCh const&) = delete; + ~StringToXMLCh () { XMLString::release (&_buffer); diff --git a/src/version.h b/src/version.h index 79258dba..12e36b2c 100644 --- a/src/version.h +++ b/src/version.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -31,10 +31,18 @@ files in the program, then also delete it here. */ + +/** @file src/version.h + * @brief Versioning variables that are written by the build system + */ + + namespace dcp { + extern char const * version; extern char const * git_commit; extern bool const built_with_debug; + } @@ -31,15 +31,24 @@ files in the program, then also delete it here. */ + +/** @file src/xml.h + * @brief Helpers for XML reading with libcxml + */ + + #ifndef LIBDCP_XML_H #define LIBDCP_XML_H + #include "exceptions.h" #include <libcxml/cxml.h> + namespace dcp { + template <class T> std::shared_ptr<T> optional_type_child (cxml::Node const & node, std::string name) @@ -54,11 +63,13 @@ optional_type_child (cxml::Node const & node, std::string name) return std::make_shared<T>(n.front()); } + template <class T> std::shared_ptr<T> type_child (std::shared_ptr<const cxml::Node> node, std::string name) { return std::make_shared<T>(node->node_child(name)); } + template <class T> std::shared_ptr<T> optional_type_child (std::shared_ptr<const cxml::Node> node, std::string name) @@ -66,6 +77,7 @@ optional_type_child (std::shared_ptr<const cxml::Node> node, std::string name) return optional_type_child<T> (*node.get(), name); } + template <class T> std::vector<std::shared_ptr<T>> type_children (cxml::Node const & node, std::string name) @@ -77,6 +89,7 @@ type_children (cxml::Node const & node, std::string name) return r; } + template <class T> std::vector<std::shared_ptr<T>> type_children (std::shared_ptr<const cxml::Node> node, std::string name) @@ -84,6 +97,7 @@ type_children (std::shared_ptr<const cxml::Node> node, std::string name) return type_children<T> (*node.get(), name); } + template <class T> std::vector<std::shared_ptr<T>> type_grand_children (cxml::Node const & node, std::string name, std::string sub) @@ -91,6 +105,7 @@ type_grand_children (cxml::Node const & node, std::string name, std::string sub) return type_children<T> (node.node_child(name), sub); } + template <class T> std::vector<std::shared_ptr<T>> type_grand_children (std::shared_ptr<const cxml::Node> node, std::string name, std::string sub) @@ -100,4 +115,5 @@ type_grand_children (std::shared_ptr<const cxml::Node> node, std::string name, s } + #endif |
