diff options
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | commands/msg/unsubscribe.go | 2 | ||||
-rw-r--r-- | commands/msgview/open-link.go | 2 | ||||
-rw-r--r-- | commands/msgview/open.go | 4 | ||||
-rw-r--r-- | config/aerc.conf | 9 | ||||
-rw-r--r-- | config/openers.go | 13 | ||||
-rw-r--r-- | doc/aerc-config.5.scd | 9 | ||||
-rw-r--r-- | lib/open.go | 28 |
8 files changed, 30 insertions, 38 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index dd8e3259..4551909e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). *.default=true *.normal=true ``` +- Openers commands are not executed in with `sh -c`. ### Deprecated diff --git a/commands/msg/unsubscribe.go b/commands/msg/unsubscribe.go index a489b3b9..6fef16f5 100644 --- a/commands/msg/unsubscribe.go +++ b/commands/msg/unsubscribe.go @@ -180,7 +180,7 @@ func unsubscribeHTTP(u *url.URL) error { go func() { defer log.PanicHandler() mime := fmt.Sprintf("x-scheme-handler/%s", u.Scheme) - if err := lib.XDGOpenMime(u.String(), mime, nil); err != nil { + if err := lib.XDGOpenMime(u.String(), mime, ""); err != nil { app.PushError("Unsubscribe:" + err.Error()) } }() diff --git a/commands/msgview/open-link.go b/commands/msgview/open-link.go index ad2a7cc2..55aee08c 100644 --- a/commands/msgview/open-link.go +++ b/commands/msgview/open-link.go @@ -12,7 +12,7 @@ import ( type OpenLink struct { Url *url.URL `opt:"url" action:"ParseUrl"` - Cmd []string `opt:"..." required:"false"` + Cmd string `opt:"..." required:"false"` } func init() { diff --git a/commands/msgview/open.go b/commands/msgview/open.go index bab46bd7..0d6db5b0 100644 --- a/commands/msgview/open.go +++ b/commands/msgview/open.go @@ -13,8 +13,8 @@ import ( ) type Open struct { - Delete bool `opt:"-d"` - Cmd []string `opt:"..." required:"false"` + Delete bool `opt:"-d"` + Cmd string `opt:"..." required:"false"` } func init() { diff --git a/config/aerc.conf b/config/aerc.conf index 18c6decc..06cfb2d1 100644 --- a/config/aerc.conf +++ b/config/aerc.conf @@ -548,9 +548,10 @@ message/rfc822=colorize # actions on a per-MIME-type basis. The :open-link URL scheme is used to # determine the MIME type as follows: x-scheme-handler/<scheme>. # -# {} is expanded as the temporary filename to be opened. If it is not -# encountered in the command, the temporary filename will be appened to the end -# of the command. +# {} is expanded as the temporary filename or URL to be opened with proper +# shell quoting. If it is not encountered in the command, the filename/URL will +# be appended to the end of the command. The command will then be executed with +# `sh -c`. # # Like [filters], openers support basic shell globbing. The first opener which # matches the part's MIME type (or URL scheme handler MIME type) will be used, @@ -558,7 +559,7 @@ message/rfc822=colorize # # Examples: # x-scheme-handler/irc=hexchat -# x-scheme-handler/http*=firefox +# x-scheme-handler/http*=printf '%s' {} | wl-copy # text/html=surf -dfgms # text/plain=gvim {} +125 # message/rfc822=thunderbird diff --git a/config/openers.go b/config/openers.go index e246ea64..31d99e9c 100644 --- a/config/openers.go +++ b/config/openers.go @@ -1,17 +1,15 @@ package config import ( - "fmt" "strings" "git.sr.ht/~rjarry/aerc/log" "github.com/go-ini/ini" - "github.com/google/shlex" ) type Opener struct { Mime string - Args []string + Args string } var Openers []Opener @@ -24,14 +22,7 @@ func parseOpeners(file *ini.File) error { for _, key := range openers.Keys() { mime := strings.ToLower(key.Name()) - if args, err := shlex.Split(key.Value()); err != nil { - return err - } else { - if len(args) == 0 { - return fmt.Errorf("opener command empty for %s", mime) - } - Openers = append(Openers, Opener{Mime: mime, Args: args}) - } + Openers = append(Openers, Opener{Mime: mime, Args: key.Value()}) } out: diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd index 0e86e56b..a45e2443 100644 --- a/doc/aerc-config.5.scd +++ b/doc/aerc-config.5.scd @@ -900,9 +900,10 @@ actions on a per-MIME-type basis. The *:open-link* URL scheme is used to determine the MIME type as follows: _x-scheme-handler/<scheme>_. They are configured in the *[openers]* section of _aerc.conf_. -_{}_ is expanded as the temporary filename or URL to be opened. If it is not -encountered in the command, the filename/URL will be appened to the end of the -command. Environment variables are also expanded. Tilde is not expanded. +_{}_ is expanded as the temporary filename or URL to be opened with proper shell +quoting. If it is not encountered in the command, the filename/URL will be +appended to the end of the command. The command will then be executed with +_sh -c_. Like *[filters]*, openers support basic shell globbing. The first opener which matches the part's MIME type (or URL scheme handler MIME type) will be used, so @@ -913,7 +914,7 @@ Example: ``` [openers] x-scheme-handler/irc=hexchat -x-scheme-handler/http\*=firefox +x-scheme-handler/http\*=printf '%s' {} | wl-copy text/html=surf -dfgms text/plain=gvim {} +125 message/rfc822=thunderbird diff --git a/lib/open.go b/lib/open.go index b60c4165..21bee748 100644 --- a/lib/open.go +++ b/lib/open.go @@ -6,19 +6,21 @@ import ( "runtime" "strings" + "git.sr.ht/~rjarry/go-opt" + "github.com/danwakefield/fnmatch" + "git.sr.ht/~rjarry/aerc/config" "git.sr.ht/~rjarry/aerc/log" - "github.com/danwakefield/fnmatch" ) func XDGOpenMime( - uri string, mimeType string, args []string, + uri string, mimeType string, args string, ) error { if len(args) == 0 { // no explicit command provided, lookup opener from mime type for _, o := range config.Openers { if fnmatch.Match(o.Mime, mimeType, 0) { - args = append(args, o.Args...) + args = o.Args break } } @@ -26,28 +28,24 @@ func XDGOpenMime( if len(args) == 0 { // no opener defined in config, fallback to default if runtime.GOOS == "darwin" { - args = append(args, "open") + args = "open" } else { - args = append(args, "xdg-open") + args = "xdg-open" } } - i := 0 - for ; i < len(args); i++ { - if strings.Contains(args[i], "{}") { - break - } - } - if i < len(args) { + // Escape URI special characters + uri = opt.QuoteArg(uri) + if strings.Contains(args, "{}") { // found {} placeholder in args, replace with uri - args[i] = strings.Replace(args[i], "{}", uri, 1) + args = strings.Replace(args, "{}", uri, 1) } else { // no {} placeholder in args, add uri at the end - args = append(args, uri) + args = args + " " + uri } log.Tracef("running command: %v", args) - cmd := exec.Command(args[0], args[1:]...) + cmd := exec.Command("sh", "-c", args) out, err := cmd.CombinedOutput() log.Debugf("command: %v exited. err=%v out=%s", args, err, out) if err != nil { |