diff options
| author | Carl Hetherington <cth@carlh.net> | 2019-12-06 16:37:17 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2019-12-22 01:21:00 +0100 |
| commit | e975e945a5520654db949324de7992ea70d442ee (patch) | |
| tree | 756e139ca04b38520ac10ccf2089d78e010446a6 | |
| parent | 87567d63d23360a2f0570b96a136d2100094b31b (diff) | |
Check for badly-formed CPL <Id>
| -rw-r--r-- | src/verify.cc | 93 | ||||
| -rw-r--r-- | src/verify.h | 2 | ||||
| -rw-r--r-- | test/verify_test.cc | 41 |
3 files changed, 102 insertions, 34 deletions
diff --git a/src/verify.cc b/src/verify.cc index 279de556..f4b89afd 100644 --- a/src/verify.cc +++ b/src/verify.cc @@ -40,6 +40,7 @@ #include "exceptions.h" #include "compose.hpp" #include <boost/foreach.hpp> +#include <boost/algorithm/string.hpp> #include <list> #include <vector> #include <iostream> @@ -93,6 +94,42 @@ verify_asset (shared_ptr<DCP> dcp, shared_ptr<ReelMXF> reel_mxf, function<void ( return RESULT_GOOD; } +static +bool +hex (string s) +{ + for (size_t i = 0; i < s.length(); ++i) { + if (string("0123456789abcdef").find(s[i]) == string::npos) { + return false; + } + } + + return true; +} + +static +bool +good_urn_uuid (string id) +{ + if (id.length() != 45) { + return false; + } + + if (!boost::algorithm::starts_with(id, "urn:uuid:")) { + return false; + } + + if (id[17] != '-' || id[22] != '-' || id[27] != '-' || id[32] != '-') { + return false; + } + + if (!hex(id.substr(9, 8)) || !hex(id.substr(18, 4)) || !hex(id.substr(23, 4)) || !hex(id.substr(28, 4)) || !hex(id.substr(33, 8))) { + return false; + } + + return true; +} + list<VerificationNote> dcp::verify (vector<boost::filesystem::path> directories, function<void (string, optional<boost::filesystem::path>)> stage, function<void (float)> progress) { @@ -108,14 +145,20 @@ dcp::verify (vector<boost::filesystem::path> directories, function<void (string, try { dcp->read (¬es); } catch (DCPReadError& e) { - notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::GENERAL_READ, string(e.what()))); + notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::Code::GENERAL_READ, string(e.what()))); } catch (XMLError& e) { - notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::GENERAL_READ, string(e.what()))); + notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::Code::GENERAL_READ, string(e.what()))); } BOOST_FOREACH (shared_ptr<CPL> cpl, dcp->cpls()) { stage ("Checking CPL", cpl->file()); + cxml::Document cpl_doc ("CompositionPlaylist"); + cpl_doc.read_file (cpl->file().get()); + if (!good_urn_uuid(cpl_doc.string_child("Id"))) { + notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::Code::BAD_URN_UUID, string("CPL <Id> is malformed"))); + } + /* Check that the CPL's hash corresponds to the PKL */ BOOST_FOREACH (shared_ptr<PKL> i, dcp->pkls()) { optional<string> h = i->hash(cpl->id()); @@ -140,24 +183,24 @@ dcp::verify (vector<boost::filesystem::path> directories, function<void (string, notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::INVALID_PICTURE_FRAME_RATE)); } /* Check asset */ - if (reel->main_picture()->asset_ref().resolved()) { - stage ("Checking picture asset hash", reel->main_picture()->asset()->file()); - Result const r = verify_asset (dcp, reel->main_picture(), progress); - switch (r) { - case RESULT_BAD: - notes.push_back ( - VerificationNote( - VerificationNote::VERIFY_ERROR, VerificationNote::PICTURE_HASH_INCORRECT, *reel->main_picture()->asset()->file() - ) - ); - break; - case RESULT_CPL_PKL_DIFFER: - notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::PKL_CPL_PICTURE_HASHES_DISAGREE)); - break; - default: - break; - } - } + if (reel->main_picture()->asset_ref().resolved()) { + stage ("Checking picture asset hash", reel->main_picture()->asset()->file()); + Result const r = verify_asset (dcp, reel->main_picture(), progress); + switch (r) { + case RESULT_BAD: + notes.push_back ( + VerificationNote( + VerificationNote::VERIFY_ERROR, VerificationNote::PICTURE_HASH_INCORRECT, *reel->main_picture()->asset()->file() + ) + ); + break; + case RESULT_CPL_PKL_DIFFER: + notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::PKL_CPL_PICTURE_HASHES_DISAGREE)); + break; + default: + break; + } + } } if (reel->main_sound() && reel->main_sound()->asset_ref().resolved()) { stage ("Checking sound asset hash", reel->main_sound()->asset()->file()); @@ -165,10 +208,10 @@ dcp::verify (vector<boost::filesystem::path> directories, function<void (string, switch (r) { case RESULT_BAD: notes.push_back ( - VerificationNote( - VerificationNote::VERIFY_ERROR, VerificationNote::SOUND_HASH_INCORRECT, *reel->main_sound()->asset()->file() - ) - ); + VerificationNote( + VerificationNote::VERIFY_ERROR, VerificationNote::SOUND_HASH_INCORRECT, *reel->main_sound()->asset()->file() + ) + ); break; case RESULT_CPL_PKL_DIFFER: notes.push_back (VerificationNote (VerificationNote::VERIFY_ERROR, VerificationNote::PKL_CPL_SOUND_HASHES_DISAGREE)); @@ -208,6 +251,8 @@ dcp::note_to_string (dcp::VerificationNote note) return "The file for an asset in the asset map cannot be found."; case dcp::VerificationNote::MISMATCHED_STANDARD: return "The DCP contains both SMPTE and Interop parts."; + case dcp::VerificationNote::BAD_URN_UUID: + return "There is a badly formed urn:uuid."; } return ""; diff --git a/src/verify.h b/src/verify.h index e219c6ec..1403797c 100644 --- a/src/verify.h +++ b/src/verify.h @@ -75,6 +75,8 @@ public: MISSING_ASSET, /** The DCP contains both SMPTE and Interop-standard components */ MISMATCHED_STANDARD, + /** A urn:uuid ID is badly formed */ + BAD_URN_UUID, }; VerificationNote (Type type, Code code) diff --git a/test/verify_test.cc b/test/verify_test.cc index 3a6b31ee..4a28a877 100644 --- a/test/verify_test.cc +++ b/test/verify_test.cc @@ -206,12 +206,19 @@ BOOST_AUTO_TEST_CASE (verify_test4) } static -void check_after_replace (int n, boost::filesystem::path file, string from, string to, dcp::VerificationNote::Code code1) +boost::filesystem::path +cpl (int n) +{ + return dcp::String::compose("build/test/verify_test%1/cpl_81fb54df-e1bf-4647-8788-ea7ba154375b.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); { - Editor e (file); + Editor e (file(n)); e.replace (from, to); } @@ -222,12 +229,12 @@ void check_after_replace (int n, boost::filesystem::path file, string from, stri } static -void check_after_replace (int n, boost::filesystem::path file, string from, string to, dcp::VerificationNote::Code code1, dcp::VerificationNote::Code code2) +void check_after_replace (int n, boost::function<boost::filesystem::path (int)> file, string from, string to, dcp::VerificationNote::Code code1, dcp::VerificationNote::Code code2) { vector<boost::filesystem::path> directories = setup (n); { - Editor e (file); + Editor e (file(n)); e.replace (from, to); } @@ -242,8 +249,7 @@ void check_after_replace (int n, boost::filesystem::path file, string from, stri BOOST_AUTO_TEST_CASE (verify_test5) { check_after_replace ( - 5, - "build/test/verify_test5/cpl_81fb54df-e1bf-4647-8788-ea7ba154375b.xml", + 5, &cpl, "<FrameRate>24 1", "<FrameRate>99 1", dcp::VerificationNote::CPL_HASH_INCORRECT, dcp::VerificationNote::INVALID_PICTURE_FRAME_RATE @@ -263,12 +269,18 @@ BOOST_AUTO_TEST_CASE (verify_test6) BOOST_CHECK_EQUAL (notes.front().code(), dcp::VerificationNote::Code::MISSING_ASSET); } +static +boost::filesystem::path +assetmap (int n) +{ + return dcp::String::compose("build/test/verify_test%1/ASSETMAP.xml", n); +} + /* Empty asset filename in ASSETMAP */ BOOST_AUTO_TEST_CASE (verify_test7) { check_after_replace ( - 7, - "build/test/verify_test7/ASSETMAP.xml", + 7, &assetmap, "<Path>video.mxf</Path>", "<Path></Path>", dcp::VerificationNote::Code::EMPTY_ASSET_PATH ); @@ -278,11 +290,20 @@ BOOST_AUTO_TEST_CASE (verify_test7) BOOST_AUTO_TEST_CASE (verify_test8) { check_after_replace ( - 8, - "build/test/verify_test8/cpl_81fb54df-e1bf-4647-8788-ea7ba154375b.xml", + 8, &cpl, "http://www.smpte-ra.org/schemas/429-7/2006/CPL", "http://www.digicine.com/PROTO-ASDCP-CPL-20040511#", dcp::VerificationNote::Code::MISMATCHED_STANDARD, dcp::VerificationNote::Code::CPL_HASH_INCORRECT ); } +/* Badly formatted <Id> in CPL */ +BOOST_AUTO_TEST_CASE (verify_test9) +{ + check_after_replace ( + 9, &cpl, + "<Id>urn:uuid:81fb54df-e1bf-4647-8788-ea7ba154375b", "<Id>urn:uuid:81fb54df-e1bf-4647-8788-ea7ba154375", + dcp::VerificationNote::Code::BAD_URN_UUID + ); +} + |
