1
2#----------------------------------------------------------------------------
3#   Common utility functions included in all XDG wrapper scripts
4#----------------------------------------------------------------------------
5
6DEBUG()
7{
8  [ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && return 0;
9  [ ${XDG_UTILS_DEBUG_LEVEL} -lt $1 ] && return 0;
10  shift
11  echo "$@" >&2
12}
13
14# This handles backslashes but not quote marks.
15first_word()
16{
17    read first rest
18    echo "$first"
19}
20
21#-------------------------------------------------------------
22# map a binary to a .desktop file
23binary_to_desktop_file()
24{
25    search="${XDG_DATA_HOME:-$HOME/.local/share}:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
26    binary="`which "$1"`"
27    binary="`readlink -f "$binary"`"
28    base="`basename "$binary"`"
29    IFS=:
30    for dir in $search; do
31        unset IFS
32        [ "$dir" ] || continue
33        [ -d "$dir/applications" -o -d "$dir/applnk" ] || continue
34        for file in "$dir"/applications/*.desktop "$dir"/applications/*/*.desktop "$dir"/applnk/*.desktop "$dir"/applnk/*/*.desktop; do
35            [ -r "$file" ] || continue
36            # Check to make sure it's worth the processing.
37            grep -q "^Exec.*$base" "$file" || continue
38            # Make sure it's a visible desktop file (e.g. not "preferred-web-browser.desktop").
39            grep -Eq "^(NoDisplay|Hidden)=true" "$file" && continue
40            command="`grep -E "^Exec(\[[^]=]*])?=" "$file" | cut -d= -f 2- | first_word`"
41            command="`which "$command"`"
42            if [ x"`readlink -f "$command"`" = x"$binary" ]; then
43                # Fix any double slashes that got added path composition
44                echo "$file" | sed -e 's,//*,/,g'
45                return
46            fi
47        done
48    done
49}
50
51#-------------------------------------------------------------
52# map a .desktop file to a binary
53## FIXME: handle vendor dir case
54desktop_file_to_binary()
55{
56    search="${XDG_DATA_HOME:-$HOME/.local/share}:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
57    desktop="`basename "$1"`"
58    IFS=:
59    for dir in $search; do
60        unset IFS
61        [ "$dir" -a -d "$dir/applications" ] || continue
62        file="$dir/applications/$desktop"
63        [ -r "$file" ] || continue
64        # Remove any arguments (%F, %f, %U, %u, etc.).
65        command="`grep -E "^Exec(\[[^]=]*])?=" "$file" | cut -d= -f 2- | first_word`"
66        command="`which "$command"`"
67        readlink -f "$command"
68        return
69    done
70}
71
72#-------------------------------------------------------------
73# Exit script on successfully completing the desired operation
74
75exit_success()
76{
77    if [ $# -gt 0 ]; then
78        echo "$@"
79        echo
80    fi
81
82    exit 0
83}
84
85
86#-----------------------------------------
87# Exit script on malformed arguments, not enough arguments
88# or missing required option.
89# prints usage information
90
91exit_failure_syntax()
92{
93    if [ $# -gt 0 ]; then
94        echo "@NAME@: $@" >&2
95        echo "Try '@NAME@ --help' for more information." >&2
96    else
97        usage
98        echo "Use 'man @NAME@' or '@NAME@ --manual' for additional info."
99    fi
100
101    exit 1
102}
103
104#-------------------------------------------------------------
105# Exit script on missing file specified on command line
106
107exit_failure_file_missing()
108{
109    if [ $# -gt 0 ]; then
110        echo "@NAME@: $@" >&2
111    fi
112
113    exit 2
114}
115
116#-------------------------------------------------------------
117# Exit script on failure to locate necessary tool applications
118
119exit_failure_operation_impossible()
120{
121    if [ $# -gt 0 ]; then
122        echo "@NAME@: $@" >&2
123    fi
124
125    exit 3
126}
127
128#-------------------------------------------------------------
129# Exit script on failure returned by a tool application
130
131exit_failure_operation_failed()
132{
133    if [ $# -gt 0 ]; then
134        echo "@NAME@: $@" >&2
135    fi
136
137    exit 4
138}
139
140#------------------------------------------------------------
141# Exit script on insufficient permission to read a specified file
142
143exit_failure_file_permission_read()
144{
145    if [ $# -gt 0 ]; then
146        echo "@NAME@: $@" >&2
147    fi
148
149    exit 5
150}
151
152#------------------------------------------------------------
153# Exit script on insufficient permission to write a specified file
154
155exit_failure_file_permission_write()
156{
157    if [ $# -gt 0 ]; then
158        echo "@NAME@: $@" >&2
159    fi
160
161    exit 6
162}
163
164check_input_file()
165{
166    if [ ! -e "$1" ]; then
167        exit_failure_file_missing "file '$1' does not exist"
168    fi
169    if [ ! -r "$1" ]; then
170        exit_failure_file_permission_read "no permission to read file '$1'"
171    fi
172}
173
174check_vendor_prefix()
175{
176    file_label="$2"
177    [ -n "$file_label" ] || file_label="filename"
178    file=`basename "$1"`
179    case "$file" in
180       [a-zA-Z]*-*)
181         return
182         ;;
183    esac
184
185    echo "@NAME@: $file_label '$file' does not have a proper vendor prefix" >&2
186    echo 'A vendor prefix consists of alpha characters ([a-zA-Z]) and is terminated' >&2
187    echo 'with a dash ("-"). An example '"$file_label"' is '"'example-$file'" >&2
188    echo "Use --novendor to override or '@NAME@ --manual' for additional info." >&2
189    exit 1
190}
191
192check_output_file()
193{
194    # if the file exists, check if it is writeable
195    # if it does not exists, check if we are allowed to write on the directory
196    if [ -e "$1" ]; then
197        if [ ! -w "$1" ]; then
198            exit_failure_file_permission_write "no permission to write to file '$1'"
199        fi
200    else
201        DIR=`dirname "$1"`
202        if [ ! -w "$DIR" -o ! -x "$DIR" ]; then
203            exit_failure_file_permission_write "no permission to create file '$1'"
204        fi
205    fi
206}
207
208#----------------------------------------
209# Checks for shared commands, e.g. --help
210
211check_common_commands()
212{
213    while [ $# -gt 0 ] ; do
214        parm="$1"
215        shift
216
217        case "$parm" in
218            --help)
219            usage
220            echo "Use 'man @NAME@' or '@NAME@ --manual' for additional info."
221            exit_success
222            ;;
223
224            --manual)
225            manualpage
226            exit_success
227            ;;
228
229            --version)
230            echo "@NAME@ 1.1.0 rc1"
231            exit_success
232            ;;
233        esac
234    done
235}
236
237check_common_commands "$@"
238
239[ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && unset XDG_UTILS_DEBUG_LEVEL;
240if [ ${XDG_UTILS_DEBUG_LEVEL-0} -lt 1 ]; then
241    # Be silent
242    xdg_redirect_output=" > /dev/null 2> /dev/null"
243else
244    # All output to stderr
245    xdg_redirect_output=" >&2"
246fi
247
248#--------------------------------------
249# Checks for known desktop environments
250# set variable DE to the desktop environments name, lowercase
251
252detectDE()
253{
254    # see https://bugs.freedesktop.org/show_bug.cgi?id=34164
255    unset GREP_OPTIONS
256
257    if [ -n "${XDG_CURRENT_DESKTOP}" ]; then
258      case "${XDG_CURRENT_DESKTOP}" in
259         GNOME)
260           DE=gnome;
261           ;;
262         KDE)
263           DE=kde;
264           ;;
265         LXDE)
266           DE=lxde;
267           ;;
268         XFCE)
269           DE=xfce
270      esac
271    fi
272
273    if [ x"$DE" = x"" ]; then
274      # classic fallbacks
275      if [ x"$KDE_FULL_SESSION" = x"true" ]; then DE=kde;
276      elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then DE=gnome;
277      elif `dbus-send --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.GetNameOwner string:org.gnome.SessionManager > /dev/null 2>&1` ; then DE=gnome;
278      elif xprop -root _DT_SAVE_MODE 2> /dev/null | grep ' = \"xfce4\"$' >/dev/null 2>&1; then DE=xfce;
279      elif xprop -root 2> /dev/null | grep -i '^xfce_desktop_window' >/dev/null 2>&1; then DE=xfce
280      fi
281    fi
282
283    if [ x"$DE" = x"" ]; then
284      # fallback to checking $DESKTOP_SESSION
285      case "$DESKTOP_SESSION" in
286         gnome)
287           DE=gnome;
288           ;;
289         LXDE)
290           DE=lxde;
291           ;;
292         xfce|xfce4)
293           DE=xfce;
294           ;;
295      esac
296    fi
297
298    if [ x"$DE" = x"" ]; then
299      # fallback to uname output for other platforms
300      case "$(uname 2>/dev/null)" in
301        Darwin)
302          DE=darwin;
303          ;;
304      esac
305    fi
306
307    if [ x"$DE" = x"gnome" ]; then
308      # gnome-default-applications-properties is only available in GNOME 2.x
309      # but not in GNOME 3.x
310      which gnome-default-applications-properties > /dev/null 2>&1  || DE="gnome3"
311    fi
312}
313
314#----------------------------------------------------------------------------
315# kfmclient exec/openURL can give bogus exit value in KDE <= 3.5.4
316# It also always returns 1 in KDE 3.4 and earlier
317# Simply return 0 in such case
318
319kfmclient_fix_exit_code()
320{
321    version=`LC_ALL=C.UTF-8 kde-config --version 2>/dev/null | grep '^KDE'`
322    major=`echo $version | sed 's/KDE.*: \([0-9]\).*/\1/'`
323    minor=`echo $version | sed 's/KDE.*: [0-9]*\.\([0-9]\).*/\1/'`
324    release=`echo $version | sed 's/KDE.*: [0-9]*\.[0-9]*\.\([0-9]\).*/\1/'`
325    test "$major" -gt 3 && return $1
326    test "$minor" -gt 5 && return $1
327    test "$release" -gt 4 && return $1
328    return 0
329}
330