Single quotes have to be quoted in the protocol, but were forgotten.
This is easy enough to fix but isn't helped by the fact that there
are three different copies of this bug on the perl side, so let's
split out that function into a new module and fix it there.
--- /dev/null
+#!/usr/bin/perl
+#
+# Copyright © 2008,2010,2012,2019-2020 Nick Bowler
+#
+# License GPLv3+: GNU General Public License version 3 or any later version.
+# This is free software: you are free to change and redistribute it.
+# There is NO WARRANTY, to the extent permitted by law.
+
+package MPD;
+
+use strict;
+
+use Exporter;
+our ($VERSION, @ISA, @EXPORT);
+
+$VERSION = 0;
+@ISA = qw(Exporter);
+@EXPORT = qw();
+
+# Returns the argument (or $_ if no arguments are supplied) quoted so that it
+# can be presented as a single command argument to MPD at the protocol level.
+sub escape {
+ my $s = @_[0] // $_;
+
+ # No way to encode literal newlines in the protocol, so we convert
+ # any newlines in the arguments into a space, which can help with
+ # shell quoting.
+ $s =~ s/\n/ /g;
+
+ if ($s =~ /[ \t\\"']/) {
+ $s =~ s/[\\"]/\\$&/g;
+ return "\"$s\"";
+ }
+
+ $s =~ s/^\s*$/"$&"/;
+ return $s;
+}
+
+1;
#!/usr/bin/env perl
#
-# Copyright © 2012,2019 Nick Bowler
+# Copyright © 2012,2019-2020 Nick Bowler
#
# Send commands to MPD. Each command-line argument is quoted as necessary
# so it appears as a single argument at the protocol level. The result is
use Getopt::Long qw(:config gnu_getopt);
+use FindBin;
+use lib "$FindBin::Bin";
+use MPDHacks;
+
my $host = $ENV{MPD_HOST} // "localhost";
my $port = $ENV{MPD_PORT} // 6600;
my ($quiet, $binary, $ignore_errors, $download);
die "MPD failed to announce version: $!";
}
-sub mpd_escape {
- ($_) = @_;
-
- # No way to encode literal newlines in the protocol, so we convert
- # any newlines in the arguments into a space, which can help with
- # shell quoting.
- s/\n/ /g;
-
- if (/[ \t\\"]/) {
- s/[\\"]/\\$&/g;
- return "\"$_\"";
- }
- return $_;
-}
-
sub read_binary {
my ($count) = @_;
my $buf;
}
if (@ARGV) {
- mpd_exec(map { mpd_escape($_) } @ARGV)
+ mpd_exec(map { MPD::escape($_) } @ARGV)
} else {
while (<>) {
chomp;
#!/usr/bin/perl
#
-# Copyright © 2008,2010,2012,2019 Nick Bowler
+# Copyright © 2008,2010,2012,2020 Nick Bowler
#
# Silly little script to generate an FVWM menu with various bits of MPD
# status information and controls.
use List::Util qw(any max);
use FindBin;
+use lib "$FindBin::Bin";
+use MPDHacks;
+
use constant {
MPD_MJR_MIN => 0,
MPD_MNR_MIN => 21,
my $mode = "top";
my %artistids;
-# Quotes the argument so that it is presented as a single argument to MPD
-# at the protocol level. This also works OK for most FVWM arguments.
-sub escape {
- my $s = @_[0] // $_;
-
- # No way to encode literal newlines in the protocol, so we
- # convert any newlines in the arguments into a space, which
- # can help with quoting.
- $s =~ s/\n/ /g;
-
- if (/[ \t\\"]/) {
- $s =~ s/[\\"]/\\$&/g;
- return "\"$s\"";
- }
-
- $s =~ s/^\s*$/"$&"/;
- return $s;
-}
-
# Submit a command to the MPD server; each argument to this function
# is quoted and sent as a single argument to MPD.
sub mpd_exec {
- my $cmd = join(' ', map { escape } @_);
+ my $cmd = join(' ', map { MPD::escape } @_);
print $sock "$cmd\n";
}
}
sub fvwm_cmd {
- fvwm_cmd_unquoted(map { escape } @_);
+ fvwm_cmd_unquoted(map { MPD::escape } @_);
}
# Quotes the argument in such a way that it is passed unadulterated by
my $cover = mpd_cover_filename($file);
$cover = fvwm_shell_literal($cover // $file);
- fvwm_cmd_unquoted("AddToMenu", escape($menu),
- escape($entry->{thumb}),
+ fvwm_cmd_unquoted("AddToMenu", MPD::escape($menu),
+ MPD::escape($entry->{thumb}),
"Exec", "exec", "geeqie", $cover);
}
}
#!/usr/bin/env perl
#
-# Copyright © 2019 Nick Bowler
+# Copyright © 2019-2020 Nick Bowler
#
# Replace the current MPD play queue with a saved playlist, by rearranging
# existing queue entries when possible. This avoids losing the current
use Getopt::Long qw(:config gnu_getopt);
+use FindBin;
+use lib "$FindBin::Bin";
+use MPDHacks;
+
my $host = $ENV{MPD_HOST} // "localhost";
my $port = $ENV{MPD_PORT} // 6600;
my $sock;
-# Quotes the argument so that it is presented as a single argument to MPD
-# at the protocol level.
-sub escape {
- my $s = @_[0] // $_;
-
- # No way to encode literal newlines in the protocol, so we
- # convert any newlines in the arguments into a space, which
- # can help with quoting.
- $s =~ s/\n/ /g;
-
- if (/[ \t\\"]/) {
- $s =~ s/[\\"]/\\$&/g;
- return "\"$s\"";
- }
-
- $s =~ s/^\s*$/"$&"/;
- return $s;
-}
-
# Submit a command to the MPD server; each argument to this function
# is quoted and sent as a single argument to MPD.
sub mpd_exec {
- my $cmd = join(' ', map { escape } @_);
+ my $cmd = join(' ', map { MPD::escape } @_);
print $sock "$cmd\n";
}
while (<$sock>) {
last if /^OK/;
die($_) if /^ACK/;
-
+
if (/^(\w+): (.*)$/) {
if ($1 eq "file") {
if (exists($matches{$2})) {
#!/bin/sh
#
-# Copyright © 2019 Nick Bowler
+# Copyright © 2019-2020 Nick Bowler
#
# Generate thumbnails for cover art retrieved from MPD.
#
arg=${arg%/*}/
shift; set x "$@" "$arg"; shift
- printf '%s\n' "$arg" | sed '/[ \\"]/ {
+ printf '%s\n' "$arg" | sed '/[ \\"'\'']/ {
s/[\\"]/\\&/g
s/.*/"&"/
}