mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 14:45:49 +01:00
[v3-linux] fileexplorer fix opening dir on Linux (#4521)
* convert file to use lf line-endings * fileexplorer fix opening dir on Linux * include update in unreleased changelog --------- Co-authored-by: Angus Dippenaar <angusdippenaar@gmail.com>
This commit is contained in:
parent
d58d4ba758
commit
a3a5d25d90
2 changed files with 108 additions and 97 deletions
|
|
@ -54,6 +54,7 @@ After processing, the content will be moved to the main changelog and this file
|
|||
**Fixed:**
|
||||
- Fix memory leak in event system during window close operations (#5678)
|
||||
- Fix crash when using context menus on Linux with Wayland
|
||||
- Fix on Linux, trying to open a file with the `fileexplorer` will open parent directory (#4521)
|
||||
|
||||
**Security:**
|
||||
- Update dependencies to address CVE-2024-12345 in third-party library
|
||||
|
|
|
|||
|
|
@ -1,97 +1,107 @@
|
|||
//go:build linux
|
||||
|
||||
package fileexplorer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
ini "gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
func explorerBinArgs(path string, selectFile bool) (string, []string, error) {
|
||||
// Map of field codes to their replacements
|
||||
var fieldCodes = map[string]string{
|
||||
"%d": "",
|
||||
"%D": "",
|
||||
"%n": "",
|
||||
"%N": "",
|
||||
"%v": "",
|
||||
"%m": "",
|
||||
"%f": path,
|
||||
"%F": path,
|
||||
"%u": pathToURI(path),
|
||||
"%U": pathToURI(path),
|
||||
}
|
||||
fileManagerQuery := exec.Command("xdg-mime", "query", "default", "inode/directory")
|
||||
buf := new(bytes.Buffer)
|
||||
fileManagerQuery.Stdout = buf
|
||||
fileManagerQuery.Stderr = nil
|
||||
|
||||
if err := fileManagerQuery.Run(); err != nil {
|
||||
return fallbackExplorerBinArgs(path, selectFile)
|
||||
}
|
||||
|
||||
desktopFile, err := findDesktopFile(strings.TrimSpace((buf.String())))
|
||||
if err != nil {
|
||||
return fallbackExplorerBinArgs(path, selectFile)
|
||||
}
|
||||
|
||||
cfg, err := ini.Load(desktopFile)
|
||||
if err != nil {
|
||||
// Opting to fallback rather than fail
|
||||
return fallbackExplorerBinArgs(path, selectFile)
|
||||
}
|
||||
|
||||
exec := cfg.Section("Desktop Entry").Key("Exec").String()
|
||||
for fieldCode, replacement := range fieldCodes {
|
||||
exec = strings.ReplaceAll(exec, fieldCode, replacement)
|
||||
}
|
||||
args := strings.Fields(exec)
|
||||
if !strings.Contains(strings.Join(args, " "), path) {
|
||||
args = append(args, path)
|
||||
}
|
||||
|
||||
return args[0], args[1:], nil
|
||||
}
|
||||
|
||||
func sysProcAttr(path string, selectFile bool) *syscall.SysProcAttr {
|
||||
return &syscall.SysProcAttr{}
|
||||
}
|
||||
|
||||
func fallbackExplorerBinArgs(path string, selectFile bool) (string, []string, error) {
|
||||
// NOTE: The linux fallback explorer opening is not supporting file selection
|
||||
path = filepath.Dir(path)
|
||||
return "xdg-open", []string{path}, nil
|
||||
}
|
||||
|
||||
func pathToURI(path string) string {
|
||||
absPath, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return path
|
||||
}
|
||||
return "file://" + url.PathEscape(absPath)
|
||||
}
|
||||
|
||||
func findDesktopFile(xdgFileName string) (string, error) {
|
||||
paths := []string{
|
||||
filepath.Join(os.Getenv("XDG_DATA_HOME"), "applications"),
|
||||
filepath.Join(os.Getenv("HOME"), ".local", "share", "applications"),
|
||||
"/usr/share/applications",
|
||||
}
|
||||
|
||||
for _, path := range paths {
|
||||
desktopFile := filepath.Join(path, xdgFileName)
|
||||
if _, err := os.Stat(desktopFile); err == nil {
|
||||
return desktopFile, nil
|
||||
}
|
||||
}
|
||||
err := fmt.Errorf("desktop file not found: %s", xdgFileName)
|
||||
return "", err
|
||||
}
|
||||
//go:build linux
|
||||
|
||||
package fileexplorer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
ini "gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
func explorerBinArgs(path string, selectFile bool) (string, []string, error) {
|
||||
// Map of field codes to their replacements
|
||||
var fieldCodes = map[string]string{
|
||||
"%d": "",
|
||||
"%D": "",
|
||||
"%n": "",
|
||||
"%N": "",
|
||||
"%v": "",
|
||||
"%m": "",
|
||||
"%f": path,
|
||||
"%F": path,
|
||||
"%u": pathToURI(path),
|
||||
"%U": pathToURI(path),
|
||||
}
|
||||
fileManagerQuery := exec.Command("xdg-mime", "query", "default", "inode/directory")
|
||||
buf := new(bytes.Buffer)
|
||||
fileManagerQuery.Stdout = buf
|
||||
fileManagerQuery.Stderr = nil
|
||||
|
||||
if err := fileManagerQuery.Run(); err != nil {
|
||||
return fallbackExplorerBinArgs(path, selectFile)
|
||||
}
|
||||
|
||||
desktopFile, err := findDesktopFile(strings.TrimSpace((buf.String())))
|
||||
if err != nil {
|
||||
return fallbackExplorerBinArgs(path, selectFile)
|
||||
}
|
||||
|
||||
cfg, err := ini.Load(desktopFile)
|
||||
if err != nil {
|
||||
// Opting to fallback rather than fail
|
||||
return fallbackExplorerBinArgs(path, selectFile)
|
||||
}
|
||||
|
||||
exec := cfg.Section("Desktop Entry").Key("Exec").String()
|
||||
for fieldCode, replacement := range fieldCodes {
|
||||
exec = strings.ReplaceAll(exec, fieldCode, replacement)
|
||||
}
|
||||
args := strings.Fields(exec)
|
||||
if !strings.Contains(strings.Join(args, " "), path) {
|
||||
args = append(args, path)
|
||||
}
|
||||
|
||||
return args[0], args[1:], nil
|
||||
}
|
||||
|
||||
func sysProcAttr(path string, selectFile bool) *syscall.SysProcAttr {
|
||||
return &syscall.SysProcAttr{}
|
||||
}
|
||||
|
||||
func fallbackExplorerBinArgs(path string, selectFile bool) (string, []string, error) {
|
||||
// NOTE: The linux fallback explorer opening does not support file selection
|
||||
|
||||
stat, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return "", []string{}, fmt.Errorf("stat path: %w", err)
|
||||
}
|
||||
|
||||
// If the path is a file, we want to open the directory containing the file
|
||||
if !stat.IsDir() {
|
||||
path = filepath.Dir(path)
|
||||
}
|
||||
|
||||
return "xdg-open", []string{path}, nil
|
||||
}
|
||||
|
||||
func pathToURI(path string) string {
|
||||
absPath, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return path
|
||||
}
|
||||
return "file://" + url.PathEscape(absPath)
|
||||
}
|
||||
|
||||
func findDesktopFile(xdgFileName string) (string, error) {
|
||||
paths := []string{
|
||||
filepath.Join(os.Getenv("XDG_DATA_HOME"), "applications"),
|
||||
filepath.Join(os.Getenv("HOME"), ".local", "share", "applications"),
|
||||
"/usr/share/applications",
|
||||
}
|
||||
|
||||
for _, path := range paths {
|
||||
desktopFile := filepath.Join(path, xdgFileName)
|
||||
if _, err := os.Stat(desktopFile); err == nil {
|
||||
return desktopFile, nil
|
||||
}
|
||||
}
|
||||
err := fmt.Errorf("desktop file not found: %s", xdgFileName)
|
||||
return "", err
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue