Control: tags -1 + patch

 ❦  3 janvier 2015 23:22 +0100, Vincent Bernat <ber...@debian.org> :

> However, the whole stuff is quite fragile. I can't say for sure if
> spaces would do something good or bad, but a star would not work. Here
> is an improved version which is easier to understand.

I have found a way to be even more concise and don't rely on any "magic"
(other that "$@" being the only array in a POSIX shell). Here is a
patch.

The first change is to let the shell do the splitting of the command in
the .desktop file (set -- $(sed ...)).

The second change is to use "$@" behaving like an array. We cannot
modify this array but we can append to it (with set -- "$@"
"$newarg"). Basically, we take $command_exec and then shift. Then, we
iterate on each argument using a counter and if the argument needs to be
modified (because this is the place holder), we append the modified
version, otherwise, we append it unmodified. At the end, "$@" is the
array of arguments to be passed to "$command_exec". If no replacement
has happened, we also append the target file.

No magic quoting is done, no evaluation. I think this is a safe
alternative to the current script. I can also push it upstream.

Per, I see that you committed to git yesterday. Would you take the patch
as is or do you want me to do an NMU?

--- /usr/bin/xdg-open	2015-01-03 22:22:18.513474060 +0100
+++ ./xdg-open	2015-01-08 08:42:47.513093876 +0100
@@ -526,6 +526,7 @@
 
 open_generic_xdg_mime()
 {
+    target="$1"
     filetype="$2"
     default=`xdg-mime query default "$filetype"`
     if [ -n "$default" ] ; then
@@ -546,17 +547,34 @@
             fi
 
             if [ -r "$file" ] ; then
-                command="`grep -E "^Exec(\[[^]=]*])?=" "$file" | cut -d= -f 2- | first_word`"
-                command_exec=`which $command 2>/dev/null`
-                arguments="`grep -E "^Exec(\[[^]=]*])?=" "$file" | cut -d= -f 2- | last_word`"
-                local sed_escaped_url="$(echo "$1" | sed -e 's/[&\\]/\\&/g')"
-                arguments_exec="$(echo "$arguments" | sed -e 's*%[fFuU]*'"$sed_escaped_url"'*g')"
+                set -- $(sed -n 's/^Exec\(\[[^]]*\]\)\{0,1\}=//p' "$file")
+                command_exec="$(which "$1" 2> /dev/null)"
                 if [ -x "$command_exec" ] ; then
-                    if echo $arguments | grep -iq '%[fFuU]' ; then
-                        eval '$command_exec' '$arguments_exec'
-                    else
-                        eval '$command_exec' '$arguments_exec' '"$1"'
-                    fi
+                    shift
+                    # We need to replace any occurrence of "%f", "%F" and
+                    # the like by the target file. We examine each
+                    # argument and append the modified argument to the
+                    # end then shift.
+                    args=$#
+                    replaced=0
+                    while [ $args -gt 0 ]; do
+                        case $1 in
+                            %[fFuU])
+                                replaced=1
+                                arg="$target"
+                                shift
+                                set -- "$@" "$arg"
+                                ;;
+                            *)
+                                arg="$1"
+                                shift
+                                set -- "$@" "$arg"
+                                ;;
+                        esac
+                        args=$(( $args - 1 ))
+                    done
+                    [ $replaced -eq 1 ] || set -- "$@" "$target"
+                    "$command_exec" "$@"
 
                     if [ $? -eq 0 ]; then
                         exit_success
-- 
Make sure all variables are initialised before use.
            - The Elements of Programming Style (Kernighan & Plauger)

Attachment: signature.asc
Description: PGP signature

Reply via email to