aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--commands/msg/unsubscribe.go2
-rw-r--r--commands/msgview/open-link.go2
-rw-r--r--commands/msgview/open.go4
-rw-r--r--config/aerc.conf9
-rw-r--r--config/openers.go13
-rw-r--r--doc/aerc-config.5.scd9
-rw-r--r--lib/open.go28
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 {