/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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;
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 {
}
protected:
- R* _reader;
+ R* _reader = nullptr;
std::shared_ptr<DecryptionContext> _crypto_context;
};
+
}
+
#endif
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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.
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 ()
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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 ();
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;
};
/*
- Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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"
#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)
{
lines.push_back (line);
}
- list<string>::iterator i = lines.begin ();
+ auto i = lines.begin ();
/* BEGIN */
while (i != lines.end() && *i != begin_certificate) {
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");
}
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)
{
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");
}
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)
{
return u;
}
+
string
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");
}
{
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)
return t;
}
+
struct tm
Certificate::not_before () const
{
#endif
}
+
struct tm
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);
return st;
}
-/** @return thumbprint of the to-be-signed portion of this certificate */
+
string
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
{
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");
}
return _public_key;
}
+
static bool string_is_utf8 (X509_NAME* n, int nid)
{
int p = -1;
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)
{
/*
- Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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
{
, _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;
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;
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
/*
- Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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"
#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).
*/
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;
}
}
+
/** 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).
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");
}
return dig;
}
+
CertificateChain::CertificateChain (
boost::filesystem::path openssl,
string organisation,
/* 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() + "\"";
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) {
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)
{
}
}
-/** 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;
}
}
+
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
{
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");
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
{
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;
return valid;
}
+
bool
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)) {
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());
/* <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) {
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"
);
}
-/** 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
{
xmlSecDSigCtxDestroy (signature_context);
}
+
string
CertificateChain::chain () const
{
/*
- Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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;
struct certificates_validation7;
struct certificates_validation8;
+
namespace dcp {
+
/** @class CertificateChain
* @brief A chain of any number of certificates, from root to leaf.
*/
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 {
boost::optional<std::string> _key;
};
+
}
+
#endif
/** @file src/cpl.h
- * @brief CPL class.
+ * @brief CPL class
*/
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
+
using std::string;
using std::list;
using std::vector;
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)
{
_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)
{
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:
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;
}
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") {
}
}
+
void
DCP::resolve_refs (vector<shared_ptr<Asset>> assets)
{
}
}
+
bool
DCP::equals (DCP const & other, EqualityOptions opt, NoteHandler note) const
{
return r;
}
+
void
DCP::add (std::shared_ptr<CPL> cpl)
{
}
-/** 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)
{
}
}
+
/** Write the VOLINDEX file.
* @param standard DCP standard to use (INTEROP or SMPTE)
*/
doc.write_to_file_formatted (p.string (), "UTF-8");
}
+
void
DCP::write_assetmap (
Standard standard, string pkl_uuid, boost::filesystem::path pkl_path,
_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,
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
{
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)
/*
- Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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"
#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;
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
*/
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.
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")
);
boost::optional<Standard> _standard;
};
+
}
+
#endif
/*
- Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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
*/
int _number;
};
+
/** @class MXFFileError
* @brief An exception related to an MXF file
*/
{}
};
+
/** @class MiscError
* @brief A miscellaneous exception
*/
/** @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
{
/** @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
{
BadContentKindError (std::string content_kind);
};
+
/** @class XMLError
* @brief An XML error
*/
{}
};
+
/** @class UnresolvedRefError
* @brief An exception caused by a reference (by UUID) to something which is not known
*/
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
{
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
{
~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
{
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:
NoReelsError ();
};
+
}
+
#endif
/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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)
/* 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 ();
std::shared_ptr<B> _buffer;
};
+
}
+
#endif
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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
{
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;
}
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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
{
double _gamma;
};
+
}
/*
- Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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>
#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)
rng.FillRandom (_value, _length);
}
+
Key::Key (uint8_t const * value, int length)
: _value (new uint8_t[length])
, _length (length)
memcpy (_value, value, _length);
}
+
Key::Key (string value)
: _value (new uint8_t[value.length() / 2])
, _length (value.length() / 2)
Kumu::hex2bin (value.c_str(), _value, _length, &length_done);
}
+
Key::Key (Key const & other)
: _value (new uint8_t[other._length])
, _length (other._length)
memcpy (_value, other._value, _length);
}
+
Key::~Key ()
{
delete[] _value;
}
+
Key &
Key::operator= (Key const & other)
{
return *this;
}
+
string
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)
{
/*
- Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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
{
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
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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;
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;
/*
- Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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)
{
/*
- Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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;
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;
}
friend struct ::write_smpte_subtitle_test3;
friend struct ::sync_test2;
- /** ID */
std::string _id;
};
/*
- Copyright (C) 2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2018-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
#include "pkl.h"
#include "exceptions.h"
#include "util.h"
#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)
{
}
}
+
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
{
_file = file;
}
+
optional<string>
PKL::hash (string id) const
{
return {};
}
+
optional<string>
PKL::type (string id) const
{
/*
- Copyright (C) 2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2018-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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"
#include <libcxml/cxml.h>
#include <boost/filesystem.hpp>
+
namespace dcp {
+
class PKL : public Object
{
public:
private:
boost::optional<std::string> _annotation_text;
std::string _hash;
- int64_t _size;
+ int64_t _size = 0;
std::string _type;
};
private:
- Standard _standard;
+ Standard _standard = dcp::Standard::SMPTE;
boost::optional<std::string> _annotation_text;
std::string _issue_date;
std::string _issuer;
/*
- Copyright (C) 2014-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
files in the program, then also delete it here.
*/
+
#include "reel.h"
#include "util.h"
#include "picture_asset.h"
#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;
using std::vector;
using namespace dcp;
+
Reel::Reel (std::shared_ptr<const cxml::Node> node)
: Object (remove_urn_uuid (node->string_child ("Id")))
{
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 */
node->done ();
}
+
xmlpp::Element *
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
{
return true;
}
+
bool
Reel::any_encrypted () const
{
);
}
+
void
Reel::add (DecryptedKDM const & kdm)
{
}
}
+
void
Reel::add (shared_ptr<ReelAsset> asset)
{
}
}
+
vector<shared_ptr<ReelAsset>>
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()) {
}
}
+
int64_t
Reel::duration () const
{
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;
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
{
/*
- Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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"
#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)
}
+
ReelMXF::ReelMXF (shared_ptr<const cxml::Node> node)
: _asset_ref (remove_urn_uuid(node->string_child("Id")))
, _key_id (node->optional_string_child ("KeyId"))
}
}
+
bool
ReelMXF::mxf_equals (shared_ptr<const ReelMXF> other, EqualityOptions opt, NoteHandler note) const
{
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());
}
}
/*
- Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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
{
boost::optional<std::string> _hash;
};
+
}
+
#endif
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)
{
/*
- Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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
_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 */
}
/** @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) {
}
/** 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) {
std::shared_ptr<Asset> _asset; ///< shared_ptr to the thing, may be null.
};
+
}
+
#endif
files in the program, then also delete it here.
*/
+
#include "stereo_picture_frame.h"
#include "exceptions.h"
#include "util.h"
#include <asdcp/AS_DCP.h>
#include <asdcp/KM_fileio.h>
+
using std::string;
using std::shared_ptr;
using std::make_shared;
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);
}
{
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 {};
}
/*
- Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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;
class AESDecContext;
}
+
namespace dcp {
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
std::shared_ptr<ASDCP::JP2K::SFrameBuffer> _buffer;
};
+
}
+
#endif
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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 */
mutable boost::mutex _mutex;
};
+
}
+
#endif
/*
- Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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"
#include <iostream>
#include <iomanip>
+
using std::string;
using std::wstring;
using std::cout;
/* 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 ()
{
return string (buffer);
}
+
string
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;
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);
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)
{
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)
{
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);
}
}
- 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);
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)
{
#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)
{
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);
}
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)
{
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;
}
return *i;
}
+
string
dcp::remove_urn_uuid (string raw)
{
return raw.substr (9);
}
+
string
dcp::openjpeg_version ()
{
return opj_version ();
}
+
string
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) {
}
}
-/** @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)
{
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)
{
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)
{
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"
#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;
#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>
list<XMLValidationError> _errors;
};
-class StringToXMLCh : public boost::noncopyable
+class StringToXMLCh
{
public:
StringToXMLCh (string a)
_buffer = XMLString::transcode(a.c_str());
}
+ StringToXMLCh (StringToXMLCh const&) = delete;
+ StringToXMLCh& operator= (StringToXMLCh const&) = delete;
+
~StringToXMLCh ()
{
XMLString::release (&_buffer);
/*
- Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of libdcp.
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;
+
}
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)
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)
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)
return r;
}
+
template <class T>
std::vector<std::shared_ptr<T>>
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)
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)
}
+
#endif