-$dir = $subdir if $dir eq ''; # Use subdir instead of $HOME
-$dir =~ s%^/%%; # Don't allow absolute paths
-$dir = "$subdir/$dir" unless $dir eq $subdir or $dir =~ m%^\Q$subdir/%;
-$dir =~ s%/\.\.(?=/)%__%g; # Don't allow foo/../../etc
-$dir =~ tr|-_/a-zA-Z0-9.,|_|c; # Don't allow ;|][}{*?
+my @dirs;
+$dir =~ s/^"(.*?)"$/$1/;
+$dir =~ s/^\s+//;
+$dir =~ s/\s+$//;
+foreach (split(/(?<!\\)\s+/, $dir)) {
+ s/\\(\s)/$1/g; # Unescape any escaped whitespace
+ if ($subdir eq '/') { # Less checking for '/' access
+ $dir = '/' if $dir eq '';
+ } else {
+ s#^/##; # Don't allow absolute paths
+ $_ = "$subdir/$_" unless m#^\Q$subdir\E(/|$)#;
+ 1 while s#/\.\.(/|$)#/__/#g; # Don't allow foo/../../etc
+ }
+ tr#-_/a-zA-Z0-9.,+@^%: #_#c; # Don't allow '"&;|!=()[]{}<>*?#\$
+ s/(\s)/\\$1/g; # Re-escape whitespace
+ push(@dirs, $_);
+}
+push(@dirs, $subdir) unless @dirs;
+$dir = join(' ', @dirs);