summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2019-12-06 16:37:17 +0100
committerCarl Hetherington <cth@carlh.net>2019-12-22 01:21:00 +0100
commite975e945a5520654db949324de7992ea70d442ee (patch)
tree756e139ca04b38520ac10ccf2089d78e010446a6
parent87567d63d23360a2f0570b96a136d2100094b31b (diff)
Check for badly-formed CPL <Id>
-rw-r--r--src/verify.cc93
-rw-r--r--src/verify.h2
-rw-r--r--test/verify_test.cc41
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 (&notes);
} 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
+ );
+}
+