Check major session file format version.
authorRobin Gareus <robin@gareus.org>
Thu, 17 Aug 2017 16:32:49 +0000 (18:32 +0200)
committerRobin Gareus <robin@gareus.org>
Thu, 17 Aug 2017 16:32:49 +0000 (18:32 +0200)
Don't allow to load sessions created with a newer version of Ardour
with an old one (no forward compatibility).

libs/ardour/ardour/session.h
libs/ardour/session_state.cc

index f1cb739673318590a1b6e0d6cced42eb3f0ae5b0..aec229e11d44d7abe6446b5b0b061b92a5746974 100644 (file)
@@ -1421,8 +1421,9 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        Glib::Threads::Mutex save_state_lock;
        Glib::Threads::Mutex peak_cleanup_lock;
 
-       int      load_options (const XMLNode&);
-       int      load_state (std::string snapshot_name);
+       int        load_options (const XMLNode&);
+       int        load_state (std::string snapshot_name);
+       static int parse_stateful_loading_version (const std::string&);
 
        framepos_t _last_roll_location;
        /** the session frame time at which we last rolled, located, or changed transport direction */
index 051eca4b688d6ed2cab5b331f11b772e03dd4ac3..ecd8071215df054f1f0dbfbc7c16e5fdcaaec90e 100644 (file)
@@ -954,20 +954,12 @@ Session::load_state (string snapshot_name)
        }
 
        std::string version;
-       if (root.get_property ("version", version)) {
-               if (version.find ('.') != string::npos) {
-                       /* old school version format */
-                       if (version[0] == '2') {
-                               Stateful::loading_state_version = 2000;
-                       } else {
-                               Stateful::loading_state_version = 3000;
-                       }
-               } else {
-                       Stateful::loading_state_version = string_to<int32_t>(version);
-               }
-       } else {
-               /* no version implies very old version of Ardour */
-               Stateful::loading_state_version = 1000;
+       root.get_property ("version", version);
+       Stateful::loading_state_version = parse_stateful_loading_version (version);
+
+       if ((Stateful::loading_state_version / 1000L) > (CURRENT_SESSION_FILE_VERSION / 1000L)) {
+               cerr << "Session-version: " << Stateful::loading_state_version << " is not supported. Current: " << CURRENT_SESSION_FILE_VERSION << "\n";
+               throw SessionException (string_compose (_("Incomatible Session Version. That session was created with a newer version of %1"), PROGRAM_NAME));
        }
 
        if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
@@ -4487,11 +4479,32 @@ Session::rename (const std::string& new_name)
        return 0;
 }
 
+int
+Session::parse_stateful_loading_version (const std::string& version)
+{
+       if (version.empty ()) {
+               /* no version implies very old version of Ardour */
+               return 1000;
+       }
+
+       if (version.find ('.') != string::npos) {
+               /* old school version format */
+               if (version[0] == '2') {
+                       return 2000;
+               } else {
+                       return 3000;
+               }
+       } else {
+               return string_to<int32_t>(version);
+       }
+}
+
 int
 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format, std::string& program_version)
 {
        bool found_sr = false;
        bool found_data_format = false;
+       std::string version;
        program_version = "";
 
        if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
@@ -4517,16 +4530,24 @@ Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFo
                return -1;
        }
 
-       /* sample rate */
+       /* sample rate & version*/
 
        xmlAttrPtr attr;
        for (attr = node->properties; attr; attr = attr->next) {
+               if (!strcmp ((const char*)attr->name, "version") && attr->children) {
+                       version = std::string ((char*)attr->children->content);
+               }
                if (!strcmp ((const char*)attr->name, "sample-rate") && attr->children) {
                        sample_rate = atoi ((char*)attr->children->content);
                        found_sr = true;
                }
        }
 
+       if ((parse_stateful_loading_version(version) / 1000L) > (CURRENT_SESSION_FILE_VERSION / 1000L)) {
+               return -1;
+       }
+
+
        node = node->children;
        while (node != NULL) {
                 if (!strcmp((const char*) node->name, "ProgramVersion")) {
@@ -4565,7 +4586,7 @@ Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFo
        xmlFreeParserCtxt(ctxt);
        xmlFreeDoc (doc);
 
-       return !(found_sr && found_data_format); // zero if they are both found
+       return (found_sr && found_data_format) ? 0 : 1;
 }
 
 std::string