diff options
| author | Carl Hetherington <cth@carlh.net> | 2019-12-09 00:44:07 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2019-12-22 01:21:00 +0100 |
| commit | 66bd89f87412736ba2488f5b3ca4aec9dea8ef94 (patch) | |
| tree | 05e961c0b4ca0f90f376e63f5adf6d8b03a1985b | |
| parent | 84d01dde2fb2520572d122d53e1ffebefed48157 (diff) | |
Check ASSETMAP; add a PKL test; tidy up calls to validate_xml().
| -rw-r--r-- | src/dcp.cc | 8 | ||||
| -rw-r--r-- | src/dcp.h | 11 | ||||
| -rw-r--r-- | src/verify.cc | 49 | ||||
| -rw-r--r-- | test/verify_test.cc | 39 | ||||
| -rw-r--r-- | xsd/SMPTE-429-9-2007-AM.xsd | 71 |
5 files changed, 143 insertions, 35 deletions
@@ -112,18 +112,17 @@ DCP::read (list<dcp::VerificationNote>* notes, bool ignore_incorrect_picture_mxf { /* Read the ASSETMAP and PKL */ - boost::filesystem::path asset_map_file; if (boost::filesystem::exists (_directory / "ASSETMAP")) { - asset_map_file = _directory / "ASSETMAP"; + _asset_map = _directory / "ASSETMAP"; } else if (boost::filesystem::exists (_directory / "ASSETMAP.xml")) { - asset_map_file = _directory / "ASSETMAP.xml"; + _asset_map = _directory / "ASSETMAP.xml"; } else { boost::throw_exception (DCPReadError (String::compose ("could not find ASSETMAP nor ASSETMAP.xml in `%1'", _directory.string()))); } cxml::Document asset_map ("AssetMap"); - asset_map.read_file (asset_map_file); + asset_map.read_file (_asset_map.get()); if (asset_map.namespace_uri() == assetmap_interop_ns) { _standard = INTEROP; } else if (asset_map.namespace_uri() == assetmap_smpte_ns) { @@ -436,6 +435,7 @@ DCP::write_assetmap (Standard standard, string pkl_uuid, boost::filesystem::path } doc.write_to_file_formatted (p.string (), "UTF-8"); + _asset_map = p; } /** Write all the XML files for this DCP. @@ -134,6 +134,10 @@ public: return _pkls; } + boost::optional<boost::filesystem::path> asset_map_path () { + return _asset_map; + } + static std::vector<boost::filesystem::path> directories_from_files (std::vector<boost::filesystem::path> files); private: @@ -146,11 +150,14 @@ private: */ void write_assetmap (Standard standard, std::string pkl_uuid, boost::filesystem::path pkl_path, XMLMetadata metadata) const; - /** the directory that we are writing to */ + /** The directory that we are writing to */ boost::filesystem::path _directory; - /** the CPLs that make up this DCP */ + /** The CPLs that make up this DCP */ std::list<boost::shared_ptr<CPL> > _cpls; + /** The PKLs that make up this DCP */ std::list<boost::shared_ptr<PKL> > _pkls; + /** File that the ASSETMAP was read from or last written to */ + mutable boost::optional<boost::filesystem::path> _asset_map; /** Standard of DCP that was read in */ boost::optional<Standard> _standard; diff --git a/src/verify.cc b/src/verify.cc index 9a2b0f70..cb2b1287 100644 --- a/src/verify.cc +++ b/src/verify.cc @@ -229,8 +229,8 @@ private: }; static -list<XMLValidationError> -validate_xml (boost::filesystem::path xml_file, boost::filesystem::path xsd_dtd_directory) +void +validate_xml (boost::filesystem::path xml_file, boost::filesystem::path xsd_dtd_directory, list<VerificationNote>& notes) { try { XMLPlatformUtils::Initialize (); @@ -252,6 +252,7 @@ validate_xml (boost::filesystem::path xml_file, boost::filesystem::path xsd_dtd_ schema["http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd"] = "xmldsig-core-schema.xsd"; schema["http://www.smpte-ra.org/schemas/429-7/2006/CPL"] = "SMPTE-429-7-2006-CPL.xsd"; schema["http://www.smpte-ra.org/schemas/429-8/2006/PKL"] = "SMPTE-429-8-2006-PKL.xsd"; + schema["http://www.smpte-ra.org/schemas/429-9/2007/AM"] = "SMPTE-429-9-2007-AM.xsd"; schema["http://www.w3.org/2001/03/xml.xsd"] = "xml.xsd"; string locations; @@ -283,7 +284,17 @@ validate_xml (boost::filesystem::path xml_file, boost::filesystem::path xsd_dtd_ XMLPlatformUtils::Terminate (); - return error_handler.errors (); + BOOST_FOREACH (XMLValidationError i, error_handler.errors()) { + notes.push_back ( + VerificationNote( + VerificationNote::VERIFY_ERROR, + VerificationNote::Code::XML_VALIDATION_ERROR, + i.message(), + xml_file, + i.line() + ) + ); + } } static Result @@ -349,19 +360,7 @@ dcp::verify ( BOOST_FOREACH (shared_ptr<CPL> cpl, dcp->cpls()) { stage ("Checking CPL", cpl->file()); - - list<XMLValidationError> errors = validate_xml (cpl->file().get(), xsd_dtd_directory); - BOOST_FOREACH (XMLValidationError i, errors) { - notes.push_back ( - VerificationNote( - VerificationNote::VERIFY_ERROR, - VerificationNote::Code::XML_VALIDATION_ERROR, - i.message(), - cpl->file().get(), - i.line() - ) - ); - } + validate_xml (cpl->file().get(), xsd_dtd_directory, notes); /* Check that the CPL's hash corresponds to the PKL */ BOOST_FOREACH (shared_ptr<PKL> i, dcp->pkls()) { @@ -437,20 +436,12 @@ dcp::verify ( BOOST_FOREACH (shared_ptr<PKL> pkl, dcp->pkls()) { stage ("Checking PKL", pkl->file()); - - list<XMLValidationError> errors = validate_xml (pkl->file().get(), xsd_dtd_directory); - BOOST_FOREACH (XMLValidationError i, errors) { - notes.push_back ( - VerificationNote( - VerificationNote::VERIFY_ERROR, - VerificationNote::Code::XML_VALIDATION_ERROR, - i.message(), - pkl->file().get(), - i.line() - ) - ); - } + validate_xml (pkl->file().get(), xsd_dtd_directory, notes); } + + stage ("Checking ASSETMAP", dcp->asset_map_path().get()); + validate_xml (dcp->asset_map_path().get(), xsd_dtd_directory, notes); + } return notes; diff --git a/test/verify_test.cc b/test/verify_test.cc index f23e54c4..9ac19ada 100644 --- a/test/verify_test.cc +++ b/test/verify_test.cc @@ -120,6 +120,7 @@ BOOST_AUTO_TEST_CASE (verify_test1) boost::filesystem::path const cpl_file = "build/test/verify_test1/cpl_81fb54df-e1bf-4647-8788-ea7ba154375b.xml"; boost::filesystem::path const pkl_file = "build/test/verify_test1/pkl_ae8a9818-872a-4f86-8493-11dfdea03e09.xml"; + boost::filesystem::path const assetmap_file = "build/test/verify_test1/ASSETMAP.xml"; list<pair<string, optional<boost::filesystem::path> > >::const_iterator st = stages.begin(); BOOST_CHECK_EQUAL (st->first, "Checking DCP"); @@ -145,6 +146,10 @@ BOOST_AUTO_TEST_CASE (verify_test1) BOOST_REQUIRE (st->second); BOOST_CHECK_EQUAL (st->second.get(), boost::filesystem::canonical(pkl_file)); ++st; + BOOST_CHECK_EQUAL (st->first, "Checking ASSETMAP"); + BOOST_REQUIRE (st->second); + BOOST_CHECK_EQUAL (st->second.get(), boost::filesystem::canonical(assetmap_file)); + ++st; BOOST_REQUIRE (st == stages.end()); dump_notes (notes); @@ -240,6 +245,20 @@ cpl (int n) } static +boost::filesystem::path +pkl (int n) +{ + return dcp::String::compose("build/test/verify_test%1/pkl_ae8a9818-872a-4f86-8493-11dfdea03e09.xml", n); +} + +static +boost::filesystem::path +asset_map (int n) +{ + return dcp::String::compose("build/test/verify_test%1/ASSETMAP.xml", n); +} + +static void check_after_replace (int n, boost::function<boost::filesystem::path (int)> file, string from, string to, dcp::VerificationNote::Code code1) { vector<boost::filesystem::path> directories = setup (n); @@ -380,3 +399,23 @@ BOOST_AUTO_TEST_CASE (verify_test10) dcp::VerificationNote::Code::CPL_HASH_INCORRECT ); } + +/* Badly-formatted <Id> in PKL */ +BOOST_AUTO_TEST_CASE (verify_test11) +{ + check_after_replace ( + 11, &pkl, + "<Id>urn:uuid:ae8", "<Id>urn:uuid:xe8", + dcp::VerificationNote::Code::XML_VALIDATION_ERROR + ); +} + +/* Badly-formatted <Id> in ASSETMAP */ +BOOST_AUTO_TEST_CASE (verify_test12) +{ + check_after_replace ( + 12, &asset_map, + "<Id>urn:uuid:74e", "<Id>urn:uuid:x4e", + dcp::VerificationNote::Code::XML_VALIDATION_ERROR + ); +} diff --git a/xsd/SMPTE-429-9-2007-AM.xsd b/xsd/SMPTE-429-9-2007-AM.xsd new file mode 100644 index 00000000..a4432fee --- /dev/null +++ b/xsd/SMPTE-429-9-2007-AM.xsd @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema targetNamespace="http://www.smpte-ra.org/schemas/429-9/2007/AM" xmlns:am="http://www.smpte-ra.org/schemas/429-9/2007/AM" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> + + <xs:simpleType name="UUID"> + <xs:restriction base="xs:anyURI"> + <xs:pattern value="urn:uuid:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"/> + </xs:restriction> + </xs:simpleType> + + <xs:complexType name="UserText"> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute name="language" type="xs:language" use="optional" default="en"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + + <xs:complexType name="ChunkType"> + <xs:sequence> + <xs:element name="Path" type="xs:anyURI"/> + <xs:element name="VolumeIndex" type="xs:positiveInteger" minOccurs="0"/> + <xs:element name="Offset" type="xs:nonNegativeInteger" minOccurs="0"/> + <xs:element name="Length" type="xs:positiveInteger" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="AssetType"> + <xs:sequence> + <xs:element name="Id" type="am:UUID"/> + <xs:element name="AnnotationText" type="am:UserText" minOccurs="0"/> + <xs:element name="PackingList" type="xs:boolean" minOccurs="0"/> + <xs:element name="ChunkList"> + <xs:complexType> + <xs:sequence> + <xs:element name="Chunk" type="am:ChunkType" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="AssetMapType"> + <xs:sequence> + <xs:element name="Id" type="am:UUID"/> + <xs:element name="AnnotationText" type="am:UserText" minOccurs="0"/> + <xs:element name="Creator" type="am:UserText"/> + <xs:element name="VolumeCount" type="xs:positiveInteger"/> + <xs:element name="IssueDate" type="xs:dateTime"/> + <xs:element name="Issuer" type="am:UserText"/> + <xs:element name="AssetList"> + <xs:complexType> + <xs:sequence> + <xs:element name="Asset" type="am:AssetType" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + + <xs:element name="AssetMap" type="am:AssetMapType"/> + + <xs:complexType name="VolumeIndexType"> + <xs:sequence> + <xs:element name="Index" type="xs:positiveInteger"/> + </xs:sequence> + </xs:complexType> + + <xs:element name="VolumeIndex" type="am:VolumeIndexType"/> + +</xs:schema> + |
