Check for multiple asset IDs in a PKL during verify.
authorCarl Hetherington <cth@carlh.net>
Sat, 31 Dec 2022 21:47:05 +0000 (22:47 +0100)
committerCarl Hetherington <cth@carlh.net>
Sat, 7 Jan 2023 21:44:55 +0000 (22:44 +0100)
src/verify.cc
src/verify.h
test/verify_test.cc

index 9068e9cca06d84ff248844e91fda68c4e2fa9ad9..a797813a526adb0736e1e03c3f0d44fdbfb8a245 100644 (file)
@@ -79,6 +79,7 @@
 #include <boost/algorithm/string.hpp>
 #include <iostream>
 #include <map>
+#include <set>
 #include <vector>
 
 
@@ -88,6 +89,7 @@ using std::list;
 using std::make_shared;
 using std::map;
 using std::max;
+using std::set;
 using std::shared_ptr;
 using std::string;
 using std::vector;
@@ -1616,6 +1618,7 @@ verify_pkl(
        )
 {
        validate_xml(pkl->file().get(), xsd_dtd_directory, notes);
+
        if (pkl_has_encrypted_assets(dcp, pkl)) {
                cxml::Document doc("PackingList");
                doc.read_file(pkl->file().get());
@@ -1623,6 +1626,14 @@ verify_pkl(
                        notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::UNSIGNED_PKL_WITH_ENCRYPTED_CONTENT, pkl->id(), pkl->file().get()});
                }
        }
+
+       set<string> uuid_set;
+       for (auto asset: pkl->asset_list()) {
+               if (!uuid_set.insert(asset->id()).second) {
+                       notes.push_back({VerificationNote::Type::ERROR, VerificationNote::Code::DUPLICATE_ASSET_ID_IN_PKL, pkl->id(), pkl->file().get()});
+                       break;
+               }
+       }
 }
 
 
@@ -1899,6 +1910,8 @@ dcp::note_to_string (VerificationNote note)
                return String::compose("<ContentKind> has an invalid value %1.", note.note().get());
        case VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA:
                return String::compose("<MainPictureActiveaArea> has an invalid value: %1", note.note().get());
+       case VerificationNote::Code::DUPLICATE_ASSET_ID_IN_PKL:
+               return String::compose("The PKL %1 has more than one asset with the same ID", note.note().get());
        }
 
        return "";
index 5e2c3c1fc093a6d81ca3ec4e99680881d264515b..d565abfa6f3b7230cbf11b66eefeb8c347374728 100644 (file)
@@ -401,6 +401,11 @@ public:
                 *  file contains the CPL filename
                 */
                INVALID_MAIN_PICTURE_ACTIVE_AREA,
+               /** A PKL has more than one asset with the same ID
+                *  note contains the PKL ID
+                *  file contains the PKL filename
+                */
+               DUPLICATE_ASSET_ID_IN_PKL
        };
 
        VerificationNote (Type type, Code code)
index d1319810293c0d901f24018c52b9f0c73543198e..7791f8b574c97b0be768ed405b9a85ff1e3ee1c2 100644 (file)
@@ -3343,3 +3343,26 @@ BOOST_AUTO_TEST_CASE(verify_invalid_main_picture_active_area_2)
 }
 
 
+BOOST_AUTO_TEST_CASE(verify_duplicate_pkl_asset_ids)
+{
+       RNGFixer rg;
+
+       path dir = "build/test/verify_duplicate_pkl_asset_ids";
+       prepare_directory(dir);
+       auto dcp = make_simple(dir, 1, 24);
+       dcp->write_xml();
+
+       {
+               Editor e(find_pkl(dir));
+               e.replace("urn:uuid:5407b210-4441-4e97-8b16-8bdc7c12da54", "urn:uuid:6affb8ee-0020-4dff-a53c-17652f6358ab");
+       }
+
+       dcp::PKL pkl(find_pkl(dir));
+
+       check_verify_result(
+               { dir },
+               {
+                       { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::DUPLICATE_ASSET_ID_IN_PKL, pkl.id(), canonical(find_pkl(dir)) },
+               });
+}
+