From 43f8112f0bb424f99057106d57d32276d7d422a6 Mon Sep 17 00:00:00 2001 From: Dominik Csapak Date: Wed, 9 Mar 2022 09:21:28 +0100 Subject: [PATCH] storage plugins: en/decode volume notes as UTF-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When writing into the file, explicitly utf8 encode it, and then try to utf8 decode it on read. If the notes are not valid utf8, we assume they were iso-8859 encoded and return as is. Technically this is a breaking change, since there are iso-8859 comments that would successfully decode as utf8, for example: the byte sequence "C2 A9" would be "£" in iso, but would decode to "£". From what i can tell though, this is rather unlikely to happen for "real world" notes, because the first byte would be in the range of C0-F7 (which are mostly language dependent characters like "Â") and the following bytes would have to be in the range of 80-BF, which are only special characters like "£" (or undefined) Signed-off-by: Dominik Csapak --- PVE/Storage/DirPlugin.pm | 9 +++++++-- PVE/Storage/Plugin.pm | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/PVE/Storage/DirPlugin.pm b/PVE/Storage/DirPlugin.pm index 1baad63..53eb642 100644 --- a/PVE/Storage/DirPlugin.pm +++ b/PVE/Storage/DirPlugin.pm @@ -4,6 +4,7 @@ use strict; use warnings; use Cwd; +use Encode qw(decode encode); use File::Path; use IO::File; use POSIX; @@ -104,7 +105,10 @@ sub get_volume_notes { my $path = $class->filesystem_path($scfg, $volname); $path .= $class->SUPER::NOTES_EXT; - return PVE::Tools::file_get_contents($path) if -f $path; + if (-f $path) { + my $data = PVE::Tools::file_get_contents($path); + return eval { decode('UTF-8', $data, 1) } // $data; + } return ''; } @@ -121,7 +125,8 @@ sub update_volume_notes { $path .= $class->SUPER::NOTES_EXT; if (defined($notes) && $notes ne '') { - PVE::Tools::file_set_contents($path, $notes); + my $encoded = encode('UTF-8', $notes); + PVE::Tools::file_set_contents($path, $encoded); } else { unlink $path or $! == ENOENT or die "could not delete notes - $!\n"; } diff --git a/PVE/Storage/Plugin.pm b/PVE/Storage/Plugin.pm index d2974ee..0a100b7 100644 --- a/PVE/Storage/Plugin.pm +++ b/PVE/Storage/Plugin.pm @@ -3,6 +3,7 @@ package PVE::Storage::Plugin; use strict; use warnings; +use Encode qw(decode); use Fcntl ':mode'; use File::chdir; use File::Path; @@ -1197,7 +1198,7 @@ my $get_subdir_files = sub { my $notes_fn = $original.NOTES_EXT; if (-f $notes_fn) { my $notes = PVE::Tools::file_read_firstline($notes_fn); - $info->{notes} = $notes if defined($notes); + $info->{notes} = eval { decode('UTF-8', $notes, 1) } // $notes if defined($notes); } $info->{protected} = 1 if -e PVE::Storage::protection_file_path($original);