Bug 86340

Summary: xdg-open does not handle x-schemes with no URL correctly (suggested PATCH)
Product: Portland Reporter: aayla.secura.1138
Component: xdg-utilsAssignee: Portland Bugs <portland-bugs>
Status: RESOLVED MOVED QA Contact:
Severity: normal    
Priority: medium    
Version: 1.1.0 rc2   
Hardware: All   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:
Bug Depends on:    
Bug Blocks: 23105    
Attachments: patch for xdg-utils v1.1.1

Description aayla.secura.1138 2014-11-16 11:20:55 UTC
I want tp use xdg-open to open my default browser or email-client by doing e.g.
xdg-open http: or xdg-open mailto:
If I do that, (in the former case) it opens the browser an empty page with the http:// URL and the error 'Page not found' (of course)
Here follows the fix, it needed some fixing on argument quoting (since of the arg is empty, it must not be quoted at all). I took the opportunity to fix bug 66670 and change the quoting around the user's argument to single rather than double (it also takes care of single quotes present in it).
Also, first_word was defined twice (once in the beginning and once later one along with last_word) - moved definition of both to the beginning
And lastly, binary_to_desktop_file handled the deprecated applnk location, but nowhere else in the script was this supported - added it to all the other functions

--- xdg-open	2014-11-16 12:14:06.587351388 +0200
+++ xdg-open.fix	2014-11-16 13:08:47.224959973 +0200
@@ -132,6 +132,12 @@
     echo "$first"
 }
 
+last_word()
+{
+    read first rest
+    echo "$rest"
+}
+
 #-------------------------------------------------------------
 # map a binary to a .desktop file
 binary_to_desktop_file()
@@ -172,14 +178,16 @@
     IFS=:
     for dir in $search; do
         unset IFS
-        [ "$dir" ] && [ -d "$dir/applications" ] || continue
-        file="$dir/applications/$desktop"
-        [ -r "$file" ] || continue
-        # Remove any arguments (%F, %f, %U, %u, etc.).
-        command="`grep -E "^Exec(\[[^]=]*])?=" "$file" | cut -d= -f 2- | first_word`"
-        command="`which "$command"`"
-        readlink -f "$command"
-        return
+        [ "$dir" ] || continue
+        [ -d "$dir/applications" ] || [ -d "$dir/applnk" ] || continue
+        for file in "$dir"/applications/*.desktop "$dir"/applications/*/*.desktop "$dir"/applnk/*.desktop "$dir"/applnk/*/*.desktop; do
+            [ -r "$file" ] || continue
+            # Remove any arguments (%F, %f, %U, %u, etc.).
+            command="`grep -E "^Exec(\[[^]=]*])?=" "$file" | cut -d= -f 2- | first_word`"
+            command="`which "$command"`"
+            readlink -f "$command"
+            return
+	done
     done
 }
 
@@ -454,19 +462,6 @@
     return 0
 }
 
-# This handles backslashes but not quote marks.
-first_word()
-{
-    read first rest
-    echo "$first"
-}
-
-last_word()
-{
-    read first rest
-    echo "$rest"
-}
-
 open_darwin()
 {
     open "$1"
@@ -572,10 +567,12 @@
         command_exec=`which $command 2>/dev/null`
         arguments="`grep -E "^Exec(\[[^]=]*])?=" "$file" | cut -d= -f 2- | last_word`"
         arg_one="`echo "$arg" | sed 's/[&*\\]/\\\\&/g'`"
-        arguments_exec="`echo "$arguments" | sed -e 's*%[fFuU]*"'"$arg_one"'"*g'`"
+        arg_one="`echo "$arg" | sed \"s/'/'\\\"'\\\"'/g\"`"
+	[ -n "$arg_one" ] && arg_one="'$arg_one'"
+	arguments_exec="`echo "$arguments" | sed -e 's*%[fFuU]*'"$arg_one"'*g'`"
 
         if [ -x "$command_exec" ] ; then
-            if echo "$arguments" | grep -iq '%[fFuU]' ; then
+            if echo "$arguments" | grep -iq '%[fu]' ; then
                 echo START "$command_exec" "$arguments_exec"
                 eval "$command_exec" "$arguments_exec"
             else
@@ -600,15 +597,13 @@
     filetype="$2"
     default=`xdg-mime query default "$filetype"`
     if [ -n "$default" ] ; then
-        xdg_user_dir="$XDG_DATA_HOME"
-        [ -n "$xdg_user_dir" ] || xdg_user_dir="$HOME/.local/share"
-
-        xdg_system_dirs="$XDG_DATA_DIRS"
-        [ -n "$xdg_system_dirs" ] || xdg_system_dirs=/usr/local/share/:/usr/share/
+        [ -n "$XDG_DATA_HOME" ] && xdg_user_dir="$XDG_DATA_HOME" || xdg_user_dir="$HOME/.local/share"
+        [ -n "$XDG_DATA_DIRS" ] && xdg_system_dirs="$XDG_DATA_DIRS" || xdg_system_dirs=/usr/local/share/:/usr/share/
 
 DEBUG 3 "$xdg_user_dir:$xdg_system_dirs"
         for x in `echo "$xdg_user_dir:$xdg_system_dirs" | sed 's/:/ /g'`; do
-            search_desktop_file "$default" "$x/applications/" "$1"
+            [ -d "$x/applications/" ] && search_desktop_file "$default" "$x/applications/" "$1"
+            [ -d "$x/applnk/" ] && search_desktop_file "$default" "$x/applnk/" "$1"
         done
     fi
 }
@@ -622,9 +617,11 @@
 open_generic_xdg_x_scheme_handler()
 {
     scheme="`echo $1 | sed -n 's/\(^[[:alnum:]+\.-]*\):.*$/\1/p'`"
+    uri="`echo $1 | sed -n 's/^[[:alnum:]+\.-]*:\/\{1,\}//p'`"
     if [ -n $scheme ]; then
         filetype="x-scheme-handler/$scheme"
-        open_generic_xdg_mime "$1" "$filetype"
+        [ -n "$uri" ] && open_generic_xdg_mime "$1" "$filetype"
+        open_generic_xdg_mime "" "$filetype"
     fi
 }
Comment 1 Rex Dieter 2014-11-16 15:42:02 UTC
Re: legacy/applnk support

I'd rather you not conflate that here, to deal with it in a separate patch.  In doing so, I'd also opt for dropping applnk support rather than adding it. 

And, let's deal with quoting separately too please.  Is there some reason you opted for this approach rather than what I proposed in bug #66670 already?

While you're at it, please add patches as attachments rather than inline

And, thanks.
Comment 2 aayla.secura.1138 2014-11-16 15:54:54 UTC
(In reply to Rex Dieter from comment #1)
> Re: legacy/applnk support
> 
> I'd rather you not conflate that here, to deal with it in a separate patch. 
> In doing so, I'd also opt for dropping applnk support rather than adding it. 
> 
> And, let's deal with quoting separately too please.  Is there some reason
> you opted for this approach rather than what I proposed in bug #66670
> already?
> 
> While you're at it, please add patches as attachments rather than inline
> 
> And, thanks.

Sorry, I wasn't sure if I should post separate patches, my main idea was to fix the handling of schemes with empty URLs.
As for the applnk - I wasn't sure if it should be dropped completely, but it bugged me that it was supported in one function and not the rest.

As for the quoting - as far as I could see, you wrapped all the arguments in single quotes at the point of evaluation - that causes several problems:
some of those arguments (that are specified in the desktop file) may be options to the programs (for example --writer in libreoffice's dekstop file) and if they are put in single quotes it causes an error; that's why I only wrapped the argument provided by the user in single quotes;
secondly, if that argument (path to file or url or whatever) contains a single quote, it is not escaped (hence I replace any single quote with '"'"' before wrapping the whole arg in single quotes)
Your code does however fix the issue with %i and %c, which I forgot to adress.

Sorry, new to bugzilla in general, will post patches as attachments from now on :) (is there a way to edit my comment to remove the patch?)
Comment 3 aayla.secura.1138 2016-05-02 00:01:13 UTC
Created attachment 123399 [details] [review]
patch for xdg-utils v1.1.1
Comment 4 aayla.secura.1138 2016-05-02 00:02:04 UTC
This still hasn't been resolved, so I posted a minimal patch that fixes the problem.
Comment 5 GitLab Migration User 2019-02-16 13:36:13 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/xdg/xdg-utils/issues/75.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.