]> git.proxmox.com Git - pve-storage.git/commitdiff
ovf import: disks: allow whitespaces in file path
authorThomas Lamprecht <t.lamprecht@proxmox.com>
Mon, 18 Nov 2024 19:01:25 +0000 (20:01 +0100)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Mon, 18 Nov 2024 19:43:53 +0000 (20:43 +0100)
Add a SAFE_CHAR_WITH_WHITESPACE_CLASS_RE sister variant of the shared
SAFE_CHAR_CLASS_RE shared regex to the base storage module, this use
case exist is a generic one after all, and use swap the untaint method
that parses the file a disk references to it.

Note that this is only the disk file name from inside the archive and
thus during the extraction to a staging/working directory, from there
it will be imported as volume allocated by the common storage system,
and thus follow our ordinary volume name scheme.

Improves disk detection when importing, e.g., the from upstream
provided GNS3 OVA.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
src/PVE/GuestImport.pm
src/PVE/GuestImport/OVF.pm
src/PVE/Storage.pm
src/PVE/Storage/Plugin.pm
src/test/parse_volname_test.pm

index f7ebf9259ad3cbd9150a147edd099d4f97e57fdc..c473d889b21f3fa274461901602c373ae3705c94 100644 (file)
@@ -28,7 +28,7 @@ sub extract_disk_from_import_file {
     my $archive_volid;
     my $inner_file;
     my $inner_fmt;
-    if ($name =~ m!^(.*\.ova)/(${PVE::Storage::SAFE_CHAR_CLASS_RE}+)$!) {
+    if ($name =~ m!^(.*\.ova)/(${PVE::Storage::SAFE_CHAR_WITH_WHITESPACE_CLASS_RE}+)$!) {
        $archive_volid = "$source_storeid:import/$1";
        $inner_file = $2;
        ($inner_fmt) = $fmt =~ /^ova\+(.*)$/;
index 4a00039c74f9492ac55c86ef919fe9b36aecd54f..9e9f8b3f8a4dfe345a05e920438502fbf82be08f 100644 (file)
@@ -323,7 +323,7 @@ ovf:Item[rasd:InstanceID='%s']/rasd:ResourceType", $controller_id);
        }
        print "file path: $filepath\n" if $debug;
        my $original_filepath = $filepath;
-       ($filepath) = $filepath =~ m|^(${PVE::Storage::SAFE_CHAR_CLASS_RE}+)$|; # untaint & check no sub/parent dirs
+       ($filepath) = $filepath =~ m|^(${PVE::Storage::SAFE_CHAR_WITH_WHITESPACE_CLASS_RE}+)$|; # untaint & check no sub/parent dirs
        die "referenced path '$original_filepath' is invalid\n" if !$filepath || $filepath eq "." || $filepath eq "..";
 
        # resolve symlinks and relative path components
index 1e12b51404a8d7dbf243a86b3177df1c51557eba..230c57bdbdbcd5622ea885f69a4fa8e1d423f1ca 100755 (executable)
@@ -119,8 +119,9 @@ our $IMPORT_EXT_RE_1 = qr/\.(ova|ovf|qcow2|raw|vmdk)/;
 our $UPLOAD_IMPORT_EXT_RE_1 = qr/\.(ova)/;
 
 our $SAFE_CHAR_CLASS_RE = qr/[a-zA-Z0-9\-\.\+\=\_]/;
+our $SAFE_CHAR_WITH_WHITESPACE_CLASS_RE = qr/[ a-zA-Z0-9\-\.\+\=\_]/;
 
-our $OVA_CONTENT_RE_1 = qr/${SAFE_CHAR_CLASS_RE}+\.(qcow2|raw|vmdk)/;
+our $OVA_CONTENT_RE_1 = qr/${SAFE_CHAR_WITH_WHITESPACE_CLASS_RE}+\.(qcow2|raw|vmdk)/;
 
 # FIXME remove with PVE 9.0, add versioned breaks for pve-manager
 our $vztmpl_extension_re = $VZTMPL_EXT_RE_1;
index 2407ebad37819a064d810f0bdb97076442032588..25e2a4d75b151ebe34dfaf2c25d9904a8dcf9645 100644 (file)
@@ -663,11 +663,11 @@ sub parse_volname {
        return ('backup', $fn);
     } elsif ($volname =~ m!^snippets/([^/]+)$!) {
        return ('snippets', $1);
-    } elsif ($volname =~ m!^import/(${PVE::Storage::SAFE_CHAR_CLASS_RE}+\.ova\/${PVE::Storage::OVA_CONTENT_RE_1})$!) {
+    } elsif ($volname =~ m!^import/(${PVE::Storage::SAFE_CHAR_WITH_WHITESPACE_CLASS_RE}+\.ova\/${PVE::Storage::OVA_CONTENT_RE_1})$!) {
        my $packed_image = $1;
        my $format = $2;
        return ('import', $packed_image, undef, undef, undef, undef, "ova+$format");
-    } elsif ($volname =~ m!^import/(${PVE::Storage::SAFE_CHAR_CLASS_RE}+$PVE::Storage::IMPORT_EXT_RE_1)$!) {
+    } elsif ($volname =~ m!^import/(${PVE::Storage::SAFE_CHAR_WITH_WHITESPACE_CLASS_RE}+$PVE::Storage::IMPORT_EXT_RE_1)$!) {
        return ('import', $1, undef, undef, undef, undef, $2);
     }
 
index eecd7df566f4645358c1bdb060615a1151793c14..2739cf18f89593536ff926de82e07087bf5b2996 100644 (file)
@@ -108,6 +108,11 @@ my $tests = [
        volname     => 'import/import.ova/disk.vmdk',
        expected    => ['import', 'import.ova/disk.vmdk', undef, undef, undef, undef, 'ova+vmdk'],
     },
+    {
+       description => "Import, innner file of ova with whitespace in name",
+       volname     => 'import/import.ova/OS disk.vmdk',
+       expected    => ['import', 'import.ova/OS disk.vmdk', undef, undef, undef, undef, 'ova+vmdk'],
+    },
     {
        description => "Import, innner file of ova",
        volname     => 'import/import.ova/disk.raw',