diff options
| -rw-r--r-- | src/interop_subtitle_asset.cc | 4 | ||||
| -rw-r--r-- | src/smpte_subtitle_asset.cc | 17 | ||||
| -rw-r--r-- | src/subtitle_asset.h | 10 | ||||
| -rw-r--r-- | src/verify.cc | 34 | ||||
| -rw-r--r-- | src/verify.h | 2 |
5 files changed, 48 insertions, 19 deletions
diff --git a/src/interop_subtitle_asset.cc b/src/interop_subtitle_asset.cc index 453cad8b..a7be5d1a 100644 --- a/src/interop_subtitle_asset.cc +++ b/src/interop_subtitle_asset.cc @@ -199,9 +199,9 @@ InteropSubtitleAsset::write (boost::filesystem::path p) const throw FileError ("Could not open file for writing", p, -1); } - auto const s = xml_as_string (); + _raw_xml = xml_as_string (); /* length() here gives bytes not characters */ - fwrite (s.c_str(), 1, s.length(), f); + fwrite (_raw_xml->c_str(), 1, _raw_xml->length(), f); fclose (f); _file = p; diff --git a/src/smpte_subtitle_asset.cc b/src/smpte_subtitle_asset.cc index dc8acf51..d0fbc0eb 100644 --- a/src/smpte_subtitle_asset.cc +++ b/src/smpte_subtitle_asset.cc @@ -103,8 +103,10 @@ SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file) _id = read_writer_info (info); if (!_key_id) { /* Not encrypted; read it in now */ - reader->ReadTimedTextResource (_raw_xml); - xml->read_string (_raw_xml); + string xml_string; + reader->ReadTimedTextResource (xml_string); + _raw_xml = xml_string; + xml->read_string (xml_string); parse_xml (xml); read_mxf_descriptor (reader); read_mxf_resources (reader, make_shared<DecryptionContext>(optional<Key>(), Standard::SMPTE)); @@ -307,9 +309,11 @@ SMPTESubtitleAsset::set_key (Key key) } auto dec = make_shared<DecryptionContext>(key, Standard::SMPTE); - reader->ReadTimedTextResource (_raw_xml, dec->context(), dec->hmac()); + string xml_string; + reader->ReadTimedTextResource (xml_string, dec->context(), dec->hmac()); + _raw_xml = xml_string; auto xml = make_shared<cxml::Document>("SubtitleReel"); - xml->read_string (_raw_xml); + xml->read_string (xml_string); parse_xml (xml); read_mxf_resources (reader, dec); } @@ -431,7 +435,9 @@ SMPTESubtitleAsset::write (boost::filesystem::path p) const boost::throw_exception (FileError ("could not open subtitle MXF for writing", p.string(), r)); } - r = writer.WriteTimedTextResource (xml_as_string (), enc.context(), enc.hmac()); + _raw_xml = xml_as_string (); + + r = writer.WriteTimedTextResource (*_raw_xml, enc.context(), enc.hmac()); if (ASDCP_FAILURE (r)) { boost::throw_exception (MXFFileError ("could not write XML to timed text resource", p.string(), r)); } @@ -569,3 +575,4 @@ SMPTESubtitleAsset::add (shared_ptr<Subtitle> s) SubtitleAsset::add (s); _intrinsic_duration = latest_subtitle_out().as_editable_units_ceil(_edit_rate.numerator / _edit_rate.denominator); } + diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h index 2c542b6e..8ec57fce 100644 --- a/src/subtitle_asset.h +++ b/src/subtitle_asset.h @@ -120,7 +120,11 @@ public: virtual int time_code_rate () const = 0; - std::string raw_xml () const { + /** @return Raw XML loaded from, or written to, an on-disk asset, or boost::none if + * - this object was not created from an existing on-disk asset and has not been written to one, or + * - this asset is encrypted and no key is available. + */ + virtual boost::optional<std::string> raw_xml () const { return _raw_xml; } @@ -193,8 +197,8 @@ protected: /** TTF font data that we need */ std::vector<Font> _fonts; - /** The raw XML data that we read from our asset; useful for validation */ - std::string _raw_xml; + /** The raw XML data that we read from or wrote to our asset; useful for validation */ + mutable boost::optional<std::string> _raw_xml; private: friend struct ::pull_fonts_test1; diff --git a/src/verify.cc b/src/verify.cc index 623794cc..40f7c0b6 100644 --- a/src/verify.cc +++ b/src/verify.cc @@ -728,7 +728,11 @@ verify_subtitle_asset ( /* Note: we must not use SubtitleAsset::xml_as_string() here as that will mean the data on disk * gets passed through libdcp which may clean up and therefore hide errors. */ - validate_xml (asset->raw_xml(), xsd_dtd_directory, notes); + if (asset->raw_xml()) { + validate_xml (asset->raw_xml().get(), xsd_dtd_directory, notes); + } else { + notes.push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED}); + } auto smpte = dynamic_pointer_cast<const SMPTESubtitleAsset>(asset); if (smpte) { @@ -752,16 +756,20 @@ verify_closed_caption_asset ( /* Note: we must not use SubtitleAsset::xml_as_string() here as that will mean the data on disk * gets passed through libdcp which may clean up and therefore hide errors. */ - validate_xml (asset->raw_xml(), xsd_dtd_directory, notes); + auto raw_xml = asset->raw_xml(); + if (raw_xml) { + validate_xml (*raw_xml, xsd_dtd_directory, notes); + if (raw_xml->size() > 256 * 1024) { + notes.push_back ({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES, raw_convert<string>(raw_xml->size()), *asset->file()}); + } + } else { + notes.push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED}); + } auto smpte = dynamic_pointer_cast<const SMPTESubtitleAsset>(asset); if (smpte) { verify_smpte_timed_text_asset (smpte, reel_asset_duration, notes); } - - if (asset->raw_xml().size() > 256 * 1024) { - notes.push_back ({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES, raw_convert<string>(asset->raw_xml().size()), *asset->file()}); - } } @@ -772,7 +780,7 @@ verify_text_timing ( int edit_rate, vector<VerificationNote>& notes, std::function<bool (shared_ptr<Reel>)> check, - std::function<string (shared_ptr<Reel>)> xml, + std::function<optional<string> (shared_ptr<Reel>)> xml, std::function<int64_t (shared_ptr<Reel>)> duration ) { @@ -823,6 +831,12 @@ verify_text_timing ( continue; } + auto reel_xml = xml(reels[i]); + if (!reel_xml) { + notes.push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED}); + continue; + } + /* We need to look at <Subtitle> instances in the XML being checked, so we can't use the subtitles * read in by libdcp's parser. */ @@ -832,7 +846,7 @@ verify_text_timing ( optional<Time> start_time; try { doc = make_shared<cxml::Document>("SubtitleReel"); - doc->read_string (xml(reels[i])); + doc->read_string (*reel_xml); tcr = doc->number_child<int>("TimeCodeRate"); auto start_time_string = doc->optional_string_child("StartTime"); if (start_time_string) { @@ -840,7 +854,7 @@ verify_text_timing ( } } catch (...) { doc = make_shared<cxml::Document>("DCSubtitle"); - doc->read_string (xml(reels[i])); + doc->read_string (*reel_xml); } parse (doc, tcr, start_time, edit_rate, i == 0); auto end = reel_offset + duration(reels[i]); @@ -1605,6 +1619,8 @@ dcp::note_to_string (VerificationNote note) DCP_ASSERT (parts.size() == 2); return String::compose("The reel duration of some timed text (%1) is not the same as the ContainerDuration of its MXF (%2).", parts[0], parts[1]); } + case VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED: + return "Some aspect of this DCP could not be checked because it is encrypted."; } return ""; diff --git a/src/verify.h b/src/verify.h index 372da764..c0491422 100644 --- a/src/verify.h +++ b/src/verify.h @@ -379,6 +379,8 @@ public: * file contains the asset filename */ MISMATCHED_TIMED_TEXT_DURATION, + /** Something could not be verified because content is encrypted and no key is available */ + MISSED_CHECK_OF_ENCRYPTED, }; VerificationNote (Type type, Code code) |
