summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2021-05-27 14:21:35 +0200
committerCarl Hetherington <cth@carlh.net>2021-05-27 14:25:17 +0200
commita6a1294944d4ce02cbb429ca1aec07ca78d79a88 (patch)
tree0122b12b7488a7471a0764a3f1e857c0cc3584b8 /src
parent8c27355abdac31c38c2fd5f41e36097dd5360422 (diff)
Tidy handling of _raw_xml.
Before this if we tried to get the XML of an encrypted asset we would just get an empty string. Now we get a boost::none which means the verifier can avoid trying to check details of the XML (and instead raise a warning that you are trying to verify data that it cannot decrypt).
Diffstat (limited to 'src')
-rw-r--r--src/interop_subtitle_asset.cc4
-rw-r--r--src/smpte_subtitle_asset.cc17
-rw-r--r--src/subtitle_asset.h10
-rw-r--r--src/verify.cc34
-rw-r--r--src/verify.h2
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)