diff --git a/vendor/xdg-open b/vendor/xdg-open index 13caac1..c1b780b 100755 --- a/vendor/xdg-open +++ b/vendor/xdg-open @@ -38,7 +38,7 @@ manualpage() cat << _MANUALPAGE Name - xdg-open -- opens a file or URL in the user's preferred + xdg-open - opens a file or URL in the user's preferred application Synopsis @@ -87,6 +87,11 @@ Exit Codes 4 The action failed. +See Also + + xdg-mime(1), xdg-settings(1), MIME applications associations + specification + Examples xdg-open 'http://www.freedesktop.org/' @@ -104,7 +109,7 @@ _MANUALPAGE usage() { cat << _USAGE - xdg-open -- opens a file or URL in the user's preferred + xdg-open - opens a file or URL in the user's preferred application Synopsis @@ -296,7 +301,7 @@ check_vendor_prefix() [ -n "$file_label" ] || file_label="filename" file=`basename "$1"` case "$file" in - [a-zA-Z]*-*) + [[:alpha:]]*-*) return ;; esac @@ -346,7 +351,7 @@ check_common_commands() ;; --version) - echo "xdg-open 1.1.0 rc1" + echo "xdg-open 1.1.1" exit_success ;; esac @@ -375,7 +380,15 @@ detectDE() if [ -n "${XDG_CURRENT_DESKTOP}" ]; then case "${XDG_CURRENT_DESKTOP}" in - GNOME) + # only recently added to menu-spec, pre-spec X- still in use + Cinnamon|X-Cinnamon) + DE=cinnamon; + ;; + ENLIGHTENMENT) + DE=enlightenment; + ;; + # GNOME, GNOME-Classic:GNOME, or GNOME-Flashback:GNOME + GNOME*) DE=gnome; ;; KDE) @@ -384,19 +397,27 @@ detectDE() LXDE) DE=lxde; ;; + MATE) + DE=mate; + ;; XFCE) DE=xfce + ;; + X-Generic) + DE=generic + ;; esac fi if [ x"$DE" = x"" ]; then # classic fallbacks - if [ x"$KDE_FULL_SESSION" = x"true" ]; then DE=kde; + if [ x"$KDE_FULL_SESSION" != x"" ]; then DE=kde; elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then DE=gnome; elif [ x"$MATE_DESKTOP_SESSION_ID" != x"" ]; then DE=mate; 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; elif xprop -root _DT_SAVE_MODE 2> /dev/null | grep ' = \"xfce4\"$' >/dev/null 2>&1; then DE=xfce; elif xprop -root 2> /dev/null | grep -i '^xfce_desktop_window' >/dev/null 2>&1; then DE=xfce + elif echo $DESKTOP | grep -q '^Enlightenment'; then DE=enlightenment; fi fi @@ -407,7 +428,10 @@ detectDE() DE=gnome; ;; LXDE|Lubuntu) - DE=lxde; + DE=lxde; + ;; + MATE) + DE=mate; ;; xfce|xfce4|'Xfce Session') DE=xfce; @@ -417,7 +441,10 @@ detectDE() if [ x"$DE" = x"" ]; then # fallback to uname output for other platforms - case "$(uname 2>/dev/null)" in + case "$(uname 2>/dev/null)" in + CYGWIN*) + DE=cygwin; + ;; Darwin) DE=darwin; ;; @@ -449,16 +476,82 @@ kfmclient_fix_exit_code() } # This handles backslashes but not quote marks. -first_word() +last_word() { read first rest - echo "$first" + echo "$rest" } -last_word() +# Get the value of a key in a desktop file's Desktop Entry group. +# Example: Use get_key foo.desktop Exec +# to get the values of the Exec= key for the Desktop Entry group. +get_key() { - read first rest - echo "$rest" + local file="${1}" + local key="${2}" + local desktop_entry="" + + IFS_="${IFS}" + IFS="" + while read line + do + case "$line" in + "[Desktop Entry]") + desktop_entry="y" + ;; + # Reset match flag for other groups + "["*) + desktop_entry="" + ;; + "${key}="*) + # Only match Desktop Entry group + if [ -n "${desktop_entry}" ] + then + echo "${line}" | cut -d= -f 2- + fi + esac + done < "${file}" + IFS="${IFS_}" +} + +# Returns true if argument is a file:// URL or path +is_file_url_or_path() +{ + if echo "$1" | grep -q '^file://' \ + || ! echo "$1" | egrep -q '^[[:alpha:]+\.\-]+:'; then + return 0 + else + return 1 + fi +} + +# If argument is a file URL, convert it to a (percent-decoded) path. +# If not, leave it as it is. +file_url_to_path() +{ + local file="$1" + if echo "$file" | grep -q '^file:///'; then + file=${file#file://} + file=${file%%#*} + file=$(echo "$file" | sed -r 's/\?.*$//') + local printf=printf + if [ -x /usr/bin/printf ]; then + printf=/usr/bin/printf + fi + file=$($printf "$(echo "$file" | sed -e 's@%\([a-f0-9A-F]\{2\}\)@\\x\1@g')") + fi + echo "$file" +} + +open_cygwin() +{ + cygstart "$1" + + if [ $? -eq 0 ]; then + exit_success + else + exit_failure_operation_failed + fi } open_darwin() @@ -474,15 +567,18 @@ open_darwin() open_kde() { - if kde-open -v 2>/dev/null 1>&2; then - kde-open "$1" + if [ -n "${KDE_SESSION_VERSION}" ]; then + case "${KDE_SESSION_VERSION}" in + 4) + kde-open "$1" + ;; + 5) + kde-open${KDE_SESSION_VERSION} "$1" + ;; + esac else - if [ x"$KDE_SESSION_VERSION" = x"4" ]; then - kfmclient openURL "$1" - else - kfmclient exec "$1" - kfmclient_fix_exit_code $? - fi + kfmclient exec "$1" + kfmclient_fix_exit_code $? fi if [ $? -eq 0 ]; then @@ -492,12 +588,29 @@ open_kde() fi } -open_gnome() +open_gnome3() { - if gvfs-open --help 2>/dev/null 1>&2; then + if gvfs-open --help >/dev/null 2>&1; then gvfs-open "$1" else + open_generic "$1" + fi + + if [ $? -eq 0 ]; then + exit_success + else + exit_failure_operation_failed + fi +} + +open_gnome() +{ + if gvfs-open --help >/dev/null 2>&1; then + gvfs-open "$1" + elif gnome-open --help >/dev/null 2>&1; then gnome-open "$1" + else + open_generic "$1" fi if [ $? -eq 0 ]; then @@ -533,6 +646,17 @@ open_xfce() fi } +open_enlightenment() +{ + enlightenment_open "$1" + + if [ $? -eq 0 ]; then + exit_success + else + exit_failure_operation_failed + fi +} + #----------------------------------------- # Recursively search .desktop file @@ -540,7 +664,7 @@ search_desktop_file() { local default="$1" local dir="$2" - local arg="$3" + local target="$3" local file="" # look for both vendor-app.desktop, vendor/app.desktop @@ -551,29 +675,56 @@ search_desktop_file() fi if [ -r "$file" ] ; then - command="`grep -E "^Exec(\[[^]=]*])?=" "$file" | cut -d= -f 2- | first_word`" + command="$(get_key "${file}" "Exec" | first_word)" 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'`" - - if [ -x "$command_exec" ] ; then - if echo $arguments | grep -iq '%[fFuU]' ; then - echo START $command_exec $arguments_exec - eval $command_exec $arguments_exec - else - echo START $command_exec $arguments_exec "$arg" - eval $command_exec $arguments_exec "$arg" - fi + icon="$(get_key "${file}" "Icon")" + # FIXME: Actually LC_MESSAGES should be used as described in + # http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s04.html + localised_name="$(get_key "${file}" "Name")" + set -- $(get_key "${file}" "Exec" | last_word) + # 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. + local args=$# + local replaced=0 + while [ $args -gt 0 ]; do + case $1 in + %[c]) + replaced=1 + arg="${localised_name}" + shift + set -- "$@" "$arg" + ;; + %[fFuU]) + replaced=1 + arg="$target" + shift + set -- "$@" "$arg" + ;; + %[i]) + replaced=1 + shift + set -- "$@" "--icon" "$icon" + ;; + *) + arg="$1" + shift + set -- "$@" "$arg" + ;; + esac + args=$(( $args - 1 )) + done + [ $replaced -eq 1 ] || set -- "$@" "$target" + "$command_exec" "$@" - if [ $? -eq 0 ]; then - exit_success - fi + if [ $? -eq 0 ]; then + exit_success fi fi for d in $dir/*/; do - [ -d "$d" ] && search_desktop_file "$default" "$d" "$arg" + [ -d "$d" ] && search_desktop_file "$default" "$d" "$target" done } @@ -611,32 +762,51 @@ open_generic_xdg_x_scheme_handler() fi } -open_generic() +open_envvar() { - # Paths or file:// URLs - if (echo "$1" | grep -q '^file://' || - ! echo "$1" | egrep -q '^[[:alpha:]+\.\-]+:'); then + local oldifs="$IFS" + local browser browser_with_arg + + IFS=":" + for browser in $BROWSER; do + IFS="$oldifs" - local file="$1" + if [ -z "$browser" ]; then + continue + fi - # Decode URLs - if echo "$file" | grep -q '^file:///'; then - file=${file#file://} - file="$(printf "$(echo "$file" | sed -e 's@%\([a-f0-9A-F]\{2\}\)@\\x\1@g')")" + if echo "$browser" | grep -q %s; then + $(printf "$browser" "$1") + else + $browser "$1" fi + + if [ $? -eq 0 ]; then + exit_success + fi + done +} + +open_generic() +{ + if is_file_url_or_path "$1"; then + local file="$(file_url_to_path "$1")" + check_input_file "$file" - open_generic_xdg_file_mime "$file" + if [ -n "$DISPLAY" ]; then + filetype=`xdg-mime query filetype "$file" | sed "s/;.*//"` + open_generic_xdg_mime "$file" "$filetype" + fi - if [ -f /etc/debian_version ] && - which run-mailcap 2>/dev/null 1>&2; then + if which run-mailcap 2>/dev/null 1>&2; then run-mailcap --action=view "$file" if [ $? -eq 0 ]; then exit_success fi fi - if mimeopen -v 2>/dev/null 1>&2; then + if [ -n "$DISPLAY" ] && mimeopen -v 2>/dev/null 1>&2; then mimeopen -L -n "$file" if [ $? -eq 0 ]; then exit_success @@ -644,27 +814,23 @@ open_generic() fi fi - open_generic_xdg_x_scheme_handler "$1" - - IFS=":" - for browser in $BROWSER; do - if [ x"$browser" != x"" ]; then - - browser_with_arg=`printf "$browser" "$1" 2>/dev/null` - if [ $? -ne 0 ]; then - browser_with_arg=$browser; - fi + if [ -n "$BROWSER" ]; then + open_envvar "$1" + fi - if [ x"$browser_with_arg" = x"$browser" ]; then - eval '$browser $1'$xdg_redirect_output; - else eval '$browser_with_arg'$xdg_redirect_output; - fi + if [ -n "$DISPLAY" ]; then + open_generic_xdg_x_scheme_handler "$1" + fi - if [ $? -eq 0 ]; then - exit_success; - fi + # if BROWSER variable is not set, check some well known browsers instead + if [ x"$BROWSER" = x"" ]; then + BROWSER=www-browser:links2:elinks:links:lynx:w3m + if [ -n "$DISPLAY" ]; then + BROWSER=x-www-browser:firefox:iceweasel:seamonkey:mozilla:epiphany:konqueror:chromium-browser:google-chrome:$BROWSER fi - done + fi + + open_envvar "$1" exit_failure_operation_impossible "no method available for opening '$1'" } @@ -672,18 +838,15 @@ open_generic() open_lxde() { # pcmanfm only knows how to handle file:// urls and filepaths, it seems. - if (echo "$1" | grep -q '^file://' || - ! echo "$1" | egrep -q '^[[:alpha:]+\.\-]+:') - then - local file="$(echo "$1" | sed 's%^file://%%')" + if is_file_url_or_path "$1"; then + local file="$(file_url_to_path "$1")" # handle relative paths - if ! echo "$file" | grep -q '^/'; then + if ! echo "$file" | grep -q ^/; then file="$(pwd)/$file" fi pcmanfm "$file" - else open_generic "$1" fi @@ -728,20 +891,26 @@ fi DEBUG 2 "Selected DE $DE" -# if BROWSER variable is not set, check some well known browsers instead -if [ x"$BROWSER" = x"" ]; then - BROWSER=links2:elinks:links:lynx:w3m - if [ -n "$DISPLAY" ]; then - BROWSER=x-www-browser:firefox:seamonkey:mozilla:epiphany:konqueror:chromium-browser:google-chrome:$BROWSER - fi -fi +# sanitize BROWSER (avoid caling ourselves in particular) +case "${BROWSER}" in + *:"xdg-open"|"xdg-open":*) + BROWSER=$(echo $BROWSER | sed -e 's|:xdg-open||g' -e 's|xdg-open:||g') + ;; + "xdg-open") + BROWSER= + ;; +esac case "$DE" in kde) open_kde "$url" ;; - gnome*) + gnome3|cinnamon) + open_gnome3 "$url" + ;; + + gnome) open_gnome "$url" ;; @@ -757,6 +926,18 @@ case "$DE" in open_lxde "$url" ;; + enlightenment) + open_enlightenment "$url" + ;; + + cygwin) + open_cygwin "$url" + ;; + + darwin) + open_darwin "$url" + ;; + generic) open_generic "$url" ;;