1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
https://gitlab.freedesktop.org/xdg/xdg-utils/-/issues/252
https://gitlab.freedesktop.org/xdg/xdg-utils/-/commit/f113a8b997dcb9527b9694d31bddcfa05096aecf
From f113a8b997dcb9527b9694d31bddcfa05096aecf Mon Sep 17 00:00:00 2001
From: Slatian <baschdel@disroot.org>
Date: Tue, 21 May 2024 04:08:23 +0000
Subject: [PATCH] Make the desktop_file_to_binary function less likely to fall
over and do something unexpected.
* Uses a shell implementation ( !24) of `which` in the `desktop_file_to_binary` to avoid tripping over unexpected output from `command -v`
* In addition it also makes the parsing a bit more standards compliant than it previously was.
* Adds a developer script to easier test internal functions in the xdg-utils-common.in file
Fixes: #252
---
scripts/test-common-function | 13 ++++++++
scripts/xdg-utils-common.in | 64 +++++++++++++++++++++++++++++++-----
2 files changed, 68 insertions(+), 9 deletions(-)
create mode 100755 scripts/test-common-function
diff --git a/scripts/test-common-function b/scripts/test-common-function
new file mode 100755
index 0000000..c8af98d
--- /dev/null
+++ b/scripts/test-common-function
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# This script is for testing internal functions of the xdg-utils-common.in file
+#
+# Example ./test-common-function xdg_which echo
+
+XDG_UTILS_DEBUG_LEVEL="${XDG_UTILS_DEBUG_LEVEL:-99}"
+
+. ./xdg-utils-common.in
+
+"$@"
+
+exit $?
diff --git a/scripts/xdg-utils-common.in b/scripts/xdg-utils-common.in
index f0a1aac..adab368 100644
--- a/scripts/xdg-utils-common.in
+++ b/scripts/xdg-utils-common.in
@@ -51,19 +51,24 @@ binary_to_desktop_file()
}
#-------------------------------------------------------------
-# map a .desktop file to a binary
+# map a .desktop file name to its Exec binary
+# Returns the realpath resolved path to the binary or noting.
+
+# desktop_file_to_binary <desktop-file-name>
desktop_file_to_binary()
{
+ DEBUG 1 "desktop_file_to_binary '$1'"
search="${XDG_DATA_HOME:-$HOME/.local/share}:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
desktop="$(basename "$1")"
IFS=:
for dir in $search; do
+ DEBUG 2 "Searching in '$dir/{applications,applnk}'"
unset IFS
- [ "$dir" ] && [ -d "$dir/applications" ] || [ -d "$dir/applnk" ] || continue
+ [ -n "$dir" ] && [ -d "$dir/applications" ] || [ -d "$dir/applnk" ] || continue
# Check if desktop file contains -
if [ "${desktop#*-}" != "$desktop" ]; then
- vendor=${desktop%-*}
- app=${desktop#*-}
+ vendor="${desktop%-*}"
+ app="${desktop#*-}"
if [ -r "$dir/applications/$vendor/$app" ]; then
file_path="$dir/applications/$vendor/$app"
elif [ -r "$dir/applnk/$vendor/$app" ]; then
@@ -72,18 +77,31 @@ desktop_file_to_binary()
fi
if test -z "$file_path" ; then
for indir in "$dir"/applications/ "$dir"/applications/*/ "$dir"/applnk/ "$dir"/applnk/*/; do
+ DEBUG 4 "Does file exist? '$indir/$desktop'"
file="$indir/$desktop"
if [ -r "$file" ]; then
- file_path=$file
+ file_path="$file"
break
fi
done
fi
if [ -r "$file_path" ]; then
- # Remove any arguments (%F, %f, %U, %u, etc.).
- command="$(grep -E "^Exec(\[[^]=]*])?=" "$file_path" | cut -d= -f 2- | first_word)"
- command="$(command -v "$command")"
- xdg_realpath "$command"
+ DEBUG 2 "Checking desktop file '$file_path'"
+ # Get the command name from the correct Exec
+ # Note: Ignoring quoting and escape sequences here, see #253
+ binary="$(awk -F '=' '
+ /^\[/{ in_entry=0 }
+ $0 == "[Desktop Entry]"{ in_entry=1 }
+ in_entry && /^Exec\s*=/ {
+ sub(/^\s+/,"",$2);
+ match($2,/^[^ ]+/);
+ print substr($2,RSTART,RLENGTH)
+ }' \
+ < "$file_path" )"
+ DEBUG 2 "Found command: $binary"
+ binary="$(xdg_which "$binary")"
+ DEBUG 2 "Resolved to command to file: '$binary'"
+ [ -z "$binary" ] || xdg_realpath "$binary"
return
fi
done
@@ -461,3 +479,31 @@ xdg_realpath()
;;
esac
}
+
+#----------------------------------------------------------------------------
+# The `which` command but as a shell implementation.
+# Returns either the path of the resolved binary or nothing
+# because command -v does not always return the path of a command
+# (builtins, aliases, functions, etc.)
+
+# xdg_which <command>
+xdg_which()
+{
+ if [ -z "$1" ] ; then
+ return 1
+ elif [ -x "$1" ] ; then
+ printf "%s\n" "$1"
+ else
+ # this should be faster than the real thing because of shell builtins
+ old_ifs="$IFS"
+ IFS=:
+ for p in $PATH ; do
+ IFS="$old_ifs"
+ if [ -x "$p/$1" ] ; then
+ printf "%s\n" "$p/$1"
+ return
+ fi
+ done
+ return 1
+ fi
+}
--
GitLab
|