Spaces:
Running
Running
#!/bin/sh | |
#--------------------------------------------- | |
# xdg-mime | |
# | |
# Utility script to manipulate MIME related information | |
# on XDG compliant systems. | |
# | |
# Refer to the usage() function below for usage. | |
# | |
# Copyright 2009-2010, Fathi Boudra <fabo@freedesktop.org> | |
# Copyright 2009-2010, Rex Dieter <rdieter@fedoraproject.org> | |
# Copyright 2006, Kevin Krammer <kevin.krammer@gmx.at> | |
# Copyright 2006, Jeremy White <jwhite@codeweavers.com> | |
# | |
# LICENSE: | |
# | |
# Permission is hereby granted, free of charge, to any person obtaining a | |
# copy of this software and associated documentation files (the "Software"), | |
# to deal in the Software without restriction, including without limitation | |
# the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
# and/or sell copies of the Software, and to permit persons to whom the | |
# Software is furnished to do so, subject to the following conditions: | |
# | |
# The above copyright notice and this permission notice shall be included | |
# in all copies or substantial portions of the Software. | |
# | |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
# OTHER DEALINGS IN THE SOFTWARE. | |
# | |
#--------------------------------------------- | |
manualpage() | |
{ | |
cat << _MANUALPAGE | |
Name | |
xdg-mime - command line tool for querying information about file type handling | |
and adding descriptions for new file types | |
Synopsis | |
xdg-mime query { filetype | default } ... | |
xdg-mime default application mimetype(s) | |
xdg-mime install [--mode mode] [--novendor] mimetypes-file | |
xdg-mime uninstall [--mode mode] mimetypes-file | |
xdg-mime { --help | --manual | --version } | |
Description | |
The xdg-mime program can be used to query information about file types and to | |
add descriptions for new file types. | |
Commands | |
query | |
Returns information related to file types. | |
The query option is for use inside a desktop session only. It is not | |
recommended to use xdg-mime query as root. | |
The following queries are supported: | |
query filetype FILE: Returns the file type of FILE in the form of a MIME | |
type. | |
query default mimetype: Returns the default application that the desktop | |
environment uses for opening files of type mimetype. The default | |
application is identified by its *.desktop file. | |
default | |
Ask the desktop environment to make application the default application for | |
opening files of type mimetype. An application can be made the default for | |
several file types by specifying multiple mimetypes. | |
application is the desktop file id of the application and has the form | |
vendor-name.desktop application must already be installed in the desktop | |
menu before it can be made the default handler. The aplication's desktop | |
file must list support for all the MIME types that it wishes to be the | |
default handler for. | |
Requests to make an application a default handler may be subject to system | |
policy or approval by the end-user. xdg-mime query can be used to verify | |
whether an application is the actual default handler for a specific file | |
type. | |
The default option is for use inside a desktop session only. It is not | |
recommended to use xdg-mime default as root. | |
install | |
Adds the file type descriptions provided in mimetypes-file to the desktop | |
environment. mimetypes-file must be a XML file that follows the | |
freedesktop.org Shared MIME-info Database specification and that has a | |
mime-info element as its document root. For each new file type one or more | |
icons with name type-subtype must be installed with the xdg-icon-resource | |
command in the mimetypes context. For example the filetype application/ | |
vnd.oasis.opendocument.text requires an icon named | |
application-vnd.oasis.opendocument.text to be installed (unless the file | |
type recommends another icon name). | |
uninstall | |
Removes the file type descriptions provided in mimetypes-file and | |
previously added with xdg-mime install from the desktop environment. | |
mimetypes-file must be a XML file that follows the freedesktop.org Shared | |
MIME-info Database specification and that has a mime-info element as its | |
document root. | |
Options | |
--mode mode | |
mode can be user or system. In user mode the file is (un)installed for the | |
current user only. In system mode the file is (un)installed for all users | |
on the system. Usually only root is allowed to install in system mode. | |
The default is to use system mode when called by root and to use user mode | |
when called by a non-root user. | |
--novendor | |
Normally, xdg-mime checks to ensure that the mimetypes-file to be installed | |
has a proper vendor prefix. This option can be used to disable that check. | |
A vendor prefix consists of alpha characters ([a-zA-Z]) and is terminated | |
with a dash ("-"). Companies and organizations are encouraged to use a word | |
or phrase, preferably the organizations name, for which they hold a | |
trademark as their vendor prefix. The purpose of the vendor prefix is to | |
prevent name conflicts. | |
--help | |
Show command synopsis. | |
--manual | |
Show this manualpage. | |
--version | |
Show the xdg-utils version information. | |
Environment Variables | |
xdg-mime honours the following environment variables: | |
XDG_UTILS_DEBUG_LEVEL | |
Setting this environment variable to a non-zero numerical value makes | |
xdg-mime do more verbose reporting on stderr. Setting a higher value | |
increases the verbosity. | |
XDG_UTILS_INSTALL_MODE | |
This environment variable can be used by the user or administrator to | |
override the installation mode. Valid values are user and system. | |
Exit Codes | |
An exit code of 0 indicates success while a non-zero exit code indicates | |
failure. The following failure codes can be returned: | |
1 | |
Error in command line syntax. | |
2 | |
One of the files passed on the command line did not exist. | |
3 | |
A required tool could not be found. | |
4 | |
The action failed. | |
5 | |
No permission to read one of the files passed on the command line. | |
See Also | |
xdg-icon-resource(1), xdg-desktop-menu(1) | |
Examples | |
xdg-mime query filetype /tmp/foobar.png | |
Prints the MIME type of the file /tmp/foobar.png, in this case image/png | |
xdg-mime query default image/png | |
Prints the .desktop filename of the application which is registered to open PNG | |
files. | |
xdg-mime install shinythings-shiny.xml | |
Adds a file type description for "shiny"-files. "shinythings-" is used as the | |
vendor prefix. The file type description could look as folows. | |
shinythings-shiny.xml: | |
<?xml version="1.0"?> | |
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'> | |
<mime-type type="text/x-shiny"> | |
<comment>Shiny new file type</comment> | |
<glob pattern="*.shiny"/> | |
<glob pattern="*.shi"/> | |
</mime-type> | |
</mime-info> | |
An icon for this new file type must also be installed, for example with: | |
xdg-icon-resource install --context mimetypes --size 64 shiny-file-icon.png text-x-shiny | |
_MANUALPAGE | |
} | |
usage() | |
{ | |
cat << _USAGE | |
xdg-mime - command line tool for querying information about file type handling | |
and adding descriptions for new file types | |
Synopsis | |
xdg-mime query { filetype | default } ... | |
xdg-mime default application mimetype(s) | |
xdg-mime install [--mode mode] [--novendor] mimetypes-file | |
xdg-mime uninstall [--mode mode] mimetypes-file | |
xdg-mime { --help | --manual | --version } | |
_USAGE | |
} | |
#@xdg-utils-common@ | |
#---------------------------------------------------------------------------- | |
# Common utility functions included in all XDG wrapper scripts | |
#---------------------------------------------------------------------------- | |
DEBUG() | |
{ | |
[ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && return 0; | |
[ ${XDG_UTILS_DEBUG_LEVEL} -lt $1 ] && return 0; | |
shift | |
echo "$@" >&2 | |
} | |
# This handles backslashes but not quote marks. | |
first_word() | |
{ | |
read first rest | |
echo "$first" | |
} | |
#------------------------------------------------------------- | |
# map a binary to a .desktop file | |
binary_to_desktop_file() | |
{ | |
search="${XDG_DATA_HOME:-$HOME/.local/share}:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}" | |
binary="`which "$1"`" | |
binary="`readlink -f "$binary"`" | |
base="`basename "$binary"`" | |
IFS=: | |
for dir in $search; do | |
unset IFS | |
[ "$dir" ] || continue | |
[ -d "$dir/applications" -o -d "$dir/applnk" ] || continue | |
for file in "$dir"/applications/*.desktop "$dir"/applications/*/*.desktop "$dir"/applnk/*.desktop "$dir"/applnk/*/*.desktop; do | |
[ -r "$file" ] || continue | |
# Check to make sure it's worth the processing. | |
grep -q "^Exec.*$base" "$file" || continue | |
# Make sure it's a visible desktop file (e.g. not "preferred-web-browser.desktop"). | |
grep -Eq "^(NoDisplay|Hidden)=true" "$file" && continue | |
command="`grep -E "^Exec(\[[^]=]*])?=" "$file" | cut -d= -f 2- | first_word`" | |
command="`which "$command"`" | |
if [ x"`readlink -f "$command"`" = x"$binary" ]; then | |
# Fix any double slashes that got added path composition | |
echo "$file" | sed -e 's,//*,/,g' | |
return | |
fi | |
done | |
done | |
} | |
#------------------------------------------------------------- | |
# map a .desktop file to a binary | |
## FIXME: handle vendor dir case | |
desktop_file_to_binary() | |
{ | |
search="${XDG_DATA_HOME:-$HOME/.local/share}:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}" | |
desktop="`basename "$1"`" | |
IFS=: | |
for dir in $search; do | |
unset IFS | |
[ "$dir" -a -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 | |
done | |
} | |
#------------------------------------------------------------- | |
# Exit script on successfully completing the desired operation | |
exit_success() | |
{ | |
if [ $# -gt 0 ]; then | |
echo "$@" | |
echo | |
fi | |
exit 0 | |
} | |
#----------------------------------------- | |
# Exit script on malformed arguments, not enough arguments | |
# or missing required option. | |
# prints usage information | |
exit_failure_syntax() | |
{ | |
if [ $# -gt 0 ]; then | |
echo "xdg-mime: $@" >&2 | |
echo "Try 'xdg-mime --help' for more information." >&2 | |
else | |
usage | |
echo "Use 'man xdg-mime' or 'xdg-mime --manual' for additional info." | |
fi | |
exit 1 | |
} | |
#------------------------------------------------------------- | |
# Exit script on missing file specified on command line | |
exit_failure_file_missing() | |
{ | |
if [ $# -gt 0 ]; then | |
echo "xdg-mime: $@" >&2 | |
fi | |
exit 2 | |
} | |
#------------------------------------------------------------- | |
# Exit script on failure to locate necessary tool applications | |
exit_failure_operation_impossible() | |
{ | |
if [ $# -gt 0 ]; then | |
echo "xdg-mime: $@" >&2 | |
fi | |
exit 3 | |
} | |
#------------------------------------------------------------- | |
# Exit script on failure returned by a tool application | |
exit_failure_operation_failed() | |
{ | |
if [ $# -gt 0 ]; then | |
echo "xdg-mime: $@" >&2 | |
fi | |
exit 4 | |
} | |
#------------------------------------------------------------ | |
# Exit script on insufficient permission to read a specified file | |
exit_failure_file_permission_read() | |
{ | |
if [ $# -gt 0 ]; then | |
echo "xdg-mime: $@" >&2 | |
fi | |
exit 5 | |
} | |
#------------------------------------------------------------ | |
# Exit script on insufficient permission to write a specified file | |
exit_failure_file_permission_write() | |
{ | |
if [ $# -gt 0 ]; then | |
echo "xdg-mime: $@" >&2 | |
fi | |
exit 6 | |
} | |
check_input_file() | |
{ | |
if [ ! -e "$1" ]; then | |
exit_failure_file_missing "file '$1' does not exist" | |
fi | |
if [ ! -r "$1" ]; then | |
exit_failure_file_permission_read "no permission to read file '$1'" | |
fi | |
} | |
check_vendor_prefix() | |
{ | |
file_label="$2" | |
[ -n "$file_label" ] || file_label="filename" | |
file=`basename "$1"` | |
case "$file" in | |
[a-zA-Z]*-*) | |
return | |
;; | |
esac | |
echo "xdg-mime: $file_label '$file' does not have a proper vendor prefix" >&2 | |
echo 'A vendor prefix consists of alpha characters ([a-zA-Z]) and is terminated' >&2 | |
echo 'with a dash ("-"). An example '"$file_label"' is '"'example-$file'" >&2 | |
echo "Use --novendor to override or 'xdg-mime --manual' for additional info." >&2 | |
exit 1 | |
} | |
check_output_file() | |
{ | |
# if the file exists, check if it is writeable | |
# if it does not exists, check if we are allowed to write on the directory | |
if [ -e "$1" ]; then | |
if [ ! -w "$1" ]; then | |
exit_failure_file_permission_write "no permission to write to file '$1'" | |
fi | |
else | |
DIR=`dirname "$1"` | |
if [ ! -w "$DIR" -o ! -x "$DIR" ]; then | |
exit_failure_file_permission_write "no permission to create file '$1'" | |
fi | |
fi | |
} | |
#---------------------------------------- | |
# Checks for shared commands, e.g. --help | |
check_common_commands() | |
{ | |
while [ $# -gt 0 ] ; do | |
parm="$1" | |
shift | |
case "$parm" in | |
--help) | |
usage | |
echo "Use 'man xdg-mime' or 'xdg-mime --manual' for additional info." | |
exit_success | |
;; | |
--manual) | |
manualpage | |
exit_success | |
;; | |
--version) | |
echo "xdg-mime 1.1.0 rc1" | |
exit_success | |
;; | |
esac | |
done | |
} | |
check_common_commands "$@" | |
[ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && unset XDG_UTILS_DEBUG_LEVEL; | |
if [ ${XDG_UTILS_DEBUG_LEVEL-0} -lt 1 ]; then | |
# Be silent | |
xdg_redirect_output=" > /dev/null 2> /dev/null" | |
else | |
# All output to stderr | |
xdg_redirect_output=" >&2" | |
fi | |
#-------------------------------------- | |
# Checks for known desktop environments | |
# set variable DE to the desktop environments name, lowercase | |
detectDE() | |
{ | |
# see https://bugs.freedesktop.org/show_bug.cgi?id=34164 | |
unset GREP_OPTIONS | |
if [ -n "${XDG_CURRENT_DESKTOP}" ]; then | |
case "${XDG_CURRENT_DESKTOP}" in | |
GNOME) | |
DE=gnome; | |
;; | |
KDE) | |
DE=kde; | |
;; | |
LXDE) | |
DE=lxde; | |
;; | |
XFCE) | |
DE=xfce | |
esac | |
fi | |
if [ x"$DE" = x"" ]; then | |
# classic fallbacks | |
if [ x"$KDE_FULL_SESSION" = x"true" ]; then DE=kde; | |
elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then DE=gnome; | |
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 | |
fi | |
fi | |
if [ x"$DE" = x"" ]; then | |
# fallback to checking $DESKTOP_SESSION | |
case "$DESKTOP_SESSION" in | |
gnome) | |
DE=gnome; | |
;; | |
LXDE) | |
DE=lxde; | |
;; | |
xfce|xfce4) | |
DE=xfce; | |
;; | |
esac | |
fi | |
if [ x"$DE" = x"" ]; then | |
# fallback to uname output for other platforms | |
case "$(uname 2>/dev/null)" in | |
Darwin) | |
DE=darwin; | |
;; | |
esac | |
fi | |
if [ x"$DE" = x"gnome" ]; then | |
# gnome-default-applications-properties is only available in GNOME 2.x | |
# but not in GNOME 3.x | |
which gnome-default-applications-properties > /dev/null 2>&1 || DE="gnome3" | |
fi | |
} | |
#---------------------------------------------------------------------------- | |
# kfmclient exec/openURL can give bogus exit value in KDE <= 3.5.4 | |
# It also always returns 1 in KDE 3.4 and earlier | |
# Simply return 0 in such case | |
kfmclient_fix_exit_code() | |
{ | |
version=`LC_ALL=C.UTF-8 kde-config --version 2>/dev/null | grep '^KDE'` | |
major=`echo $version | sed 's/KDE.*: \([0-9]\).*/\1/'` | |
minor=`echo $version | sed 's/KDE.*: [0-9]*\.\([0-9]\).*/\1/'` | |
release=`echo $version | sed 's/KDE.*: [0-9]*\.[0-9]*\.\([0-9]\).*/\1/'` | |
test "$major" -gt 3 && return $1 | |
test "$minor" -gt 5 && return $1 | |
test "$release" -gt 4 && return $1 | |
return 0 | |
} | |
update_mime_database() | |
{ | |
if [ x"$mode" = x"user" -a -n "$DISPLAY" ] ; then | |
detectDE | |
if [ x"$DE" = x"kde" ] ; then | |
DEBUG 1 "Running kbuildsycoca" | |
if [ x"$KDE_SESSION_VERSION" = x"4" ]; then | |
eval 'kbuildsycoca4'$xdg_redirect_output | |
else | |
eval 'kbuildsycoca'$xdg_redirect_output | |
fi | |
fi | |
fi | |
for x in `echo "$PATH:/opt/gnome/bin" | sed 's/:/ /g'`; do | |
if [ -x $x/update-mime-database ] ; then | |
DEBUG 1 "Running $x/update-mime-database $1" | |
eval '$x/update-mime-database $1'$xdg_redirect_output | |
return | |
fi | |
done | |
} | |
info_kde() | |
{ | |
if [ x"$KDE_SESSION_VERSION" = x"4" ]; then | |
DEBUG 1 "Running kmimetypefinder \"$1\"" | |
kmimetypefinder "$1" 2>/dev/null | head -n 1 | |
else | |
DEBUG 1 "Running kfile \"$1\"" | |
kfile "$1" 2> /dev/null | head -n 1 | cut -d "(" -f 2 | cut -d ")" -f 1 | |
fi | |
if [ $? -eq 0 ]; then | |
exit_success | |
else | |
exit_failure_operation_failed | |
fi | |
} | |
info_gnome() | |
{ | |
if gvfs-info --help 2>/dev/null 1>&2; then | |
DEBUG 1 "Running gvfs-info \"$1\"" | |
gvfs-info "$1" 2> /dev/null | grep standard::content-type | cut -d' ' -f4 | |
elif gnomevfs-info --help 2>/dev/null 1>&2; then | |
DEBUG 1 "Running gnomevfs-info \"$1\"" | |
gnomevfs-info --slow-mime "$1" 2> /dev/null | grep "^MIME" | cut -d ":" -f 2 | sed s/"^ "// | |
else | |
# according to https://bugs.freedesktop.org/show_bug.cgi?id=33094#c5 | |
# neither gvfs-info or gnomevfs-info are present in a default Ubuntu Natty | |
# install, so fallback to info_generic | |
info_generic "$1" | |
fi | |
if [ $? -eq 0 ]; then | |
exit_success | |
else | |
exit_failure_operation_failed | |
fi | |
} | |
info_generic() | |
{ | |
if mimetype --version >/dev/null 2>&1; then | |
DEBUG 1 "Running mimetype -b \"$1\"" | |
mimetype -b "$1" | |
else | |
DEBUG 1 "Running file --mime-type \"$1\"" | |
/usr/bin/file --mime-type "$1" 2> /dev/null | cut -d ":" -f 2 | sed s/"^ "// | |
fi | |
if [ $? -eq 0 ]; then | |
exit_success | |
else | |
exit_failure_operation_failed | |
fi | |
} | |
make_default_kde() | |
{ | |
# $1 is vendor-name.desktop | |
# $2 is mime/type | |
# | |
# On KDE 3, add to $KDE_CONFIG_PATH/profilerc: | |
# [$2 - 1] | |
# Application=$1 | |
# | |
# Remove all [$2 - *] sections, or even better, | |
# renumber [$2 - *] sections and remove duplicate | |
# | |
# On KDE 4, add $2=$1 to $XDG_DATA_APPS/mimeapps.list | |
# | |
# Example file: | |
# | |
# [Added Associations] | |
# text/plain=kde4-kate.desktop;kde4-kwrite.desktop; | |
# | |
# [Removed Associations] | |
# text/plain=gnome-gedit.desktop;gnu-emacs.desktop; | |
vendor="$1" | |
mimetype="$2" | |
if [ x"$KDE_SESSION_VERSION" = x"4" ]; then | |
default_dir=`kde4-config --path xdgdata-apps 2> /dev/null | cut -d ':' -f 1` | |
default_file="$default_dir/mimeapps.list" | |
else | |
default_dir=`kde-config --path config 2> /dev/null | cut -d ':' -f 1` | |
default_file="$default_dir/profilerc" | |
fi | |
if [ -z "$default_dir" ]; then | |
DEBUG 2 "make_default_kde: No kde runtime detected" | |
return | |
fi | |
DEBUG 2 "make_default_kde $vendor $mimetype" | |
DEBUG 1 "Updating $default_file" | |
mkdir -p "$default_dir" | |
[ -f "$default_file" ] || touch "$default_file" | |
if [ x"$KDE_SESSION_VERSION" = x"4" ]; then | |
[ -f "$default_file" ] || touch "$default_file" | |
awk -v application="$vendor" -v mimetype="$mimetype" ' | |
BEGIN { | |
prefix=mimetype "=" | |
associations=0 | |
found=0 | |
blanks=0 | |
} | |
{ | |
suppress=0 | |
if (index($0, "[Added Associations]") == 1) { | |
associations=1 | |
} else if (index($0, "[") == 1) { | |
if (associations && !found) { | |
print prefix application | |
found=1 | |
} | |
associations=0 | |
} else if ($0 == "") { | |
blanks++ | |
suppress=1 | |
} else if (associations && index($0, prefix) == 1) { | |
value=substr($0, length(prefix) + 1, length) | |
split(value, apps, ";") | |
value=application ";" | |
count=0 | |
for (i in apps) { | |
count++ | |
} | |
for (i=0; i < count; i++) { | |
if (apps[i] != application && apps[i] != "") { | |
value=value apps[i] ";" | |
} | |
} | |
$0=prefix value | |
found=1 | |
} | |
if (!suppress) { | |
while (blanks > 0) { | |
print "" | |
blanks-- | |
} | |
print $0 | |
} | |
} | |
END { | |
if (!found) { | |
if (!associations) { | |
print "[Added Associations]" | |
} | |
print prefix application | |
} | |
while (blanks > 0) { | |
print "" | |
blanks-- | |
} | |
} | |
' "$default_file" > "${default_file}.new" && mv "${default_file}.new" "$default_file" | |
eval 'kbuildsycoca4'$xdg_redirect_output | |
else | |
awk -v application="$vendor" -v mimetype="$mimetype" ' | |
BEGIN { | |
header_start="[" mimetype " - " | |
suppress=0 | |
} | |
{ | |
if (index($0, header_start) == 1 ) | |
suppress=1 | |
else | |
if (/^\[/) { suppress=0 } | |
if (!suppress) { | |
print $0 | |
} | |
} | |
END { | |
print "" | |
print "[" mimetype " - 1]" | |
print "Application=" application | |
print "AllowAsDefault=true" | |
print "GenericServiceType=Application" | |
print "Preference=1" | |
print "ServiceType=" mimetype | |
} | |
' "$default_file" > "${default_file}.new" && mv "${default_file}.new" "$default_file" | |
fi | |
} | |
make_default_generic() | |
{ | |
# $1 is vendor-name.desktop | |
# $2 is mime/type | |
# Add $2=$1 to XDG_DATA_HOME/applications/mimeapps.list | |
xdg_user_dir="$XDG_DATA_HOME" | |
[ -n "$xdg_user_dir" ] || xdg_user_dir="$HOME/.local/share" | |
default_file="$xdg_user_dir/applications/mimeapps.list" | |
DEBUG 2 "make_default_generic $1 $2" | |
DEBUG 1 "Updating $default_file" | |
[ -f "$default_file" ] || touch "$default_file" | |
awk -v mimetype="$2" -v application="$1" ' | |
BEGIN { | |
prefix=mimetype "=" | |
indefault=0 | |
added=0 | |
blanks=0 | |
found=0 | |
} | |
{ | |
suppress=0 | |
if (index($0, "[Default Applications]") == 1) { | |
indefault=1 | |
found=1 | |
} else if (index($0, "[") == 1) { | |
if (!added && indefault) { | |
print prefix application | |
added=1 | |
} | |
indefault=0 | |
} else if ($0 == "") { | |
suppress=1 | |
blanks++ | |
} else if (indefault && !added && index($0, prefix) == 1) { | |
$0=prefix application | |
added=1 | |
} | |
if (!suppress) { | |
while (blanks > 0) { | |
print "" | |
blanks-- | |
} | |
print $0 | |
} | |
} | |
END { | |
if (!added) { | |
if (!found) { | |
print "" | |
print "[Default Applications]" | |
} | |
print prefix application | |
} | |
while (blanks > 0) { | |
print "" | |
blanks-- | |
} | |
} | |
' "$default_file" > "${default_file}.new" && mv "${default_file}.new" "$default_file" | |
} | |
defapp_generic() | |
{ | |
MIME="$1" | |
xdg_user_dir="$XDG_DATA_HOME" | |
[ -n "$xdg_user_dir" ] || xdg_user_dir="$HOME/.local/share" | |
xdg_user_dir="$xdg_user_dir/$xdg_dir_name" | |
xdg_system_dirs="$XDG_DATA_DIRS" | |
[ -n "$xdg_system_dirs" ] || xdg_system_dirs=/usr/local/share/:/usr/share/ | |
for x in `echo "$xdg_user_dir" | sed 's/:/ /g'`; do | |
mimeapps_list="$x/applications/mimeapps.list" | |
if [ -f "$mimeapps_list" ] ; then | |
DEBUG 2 "Checking $mimeapps_list" | |
trader_result=`awk -v mimetype="$MIME" ' | |
BEGIN { | |
prefix=mimetype "=" | |
indefault=0 | |
found=0 | |
} | |
{ | |
if (index($0, "[Default Applications]") == 1) { | |
indefault=1 | |
} else if (index($0, "[") == 1) { | |
indefault=0 | |
} else if (!found && indefault && index($0, prefix) == 1) { | |
print substr($0, length(prefix) +1, length) | |
found=1 | |
} | |
} | |
' $mimeapps_list` | |
if [ -n "$trader_result" ] ; then | |
echo $trader_result | |
exit_success | |
fi | |
fi | |
done | |
for x in `echo "$xdg_system_dirs" | sed 's/:/ /g'`; do | |
DEBUG 2 "Checking $x/applications/defaults.list" | |
trader_result=`grep "$MIME=" $x/applications/defaults.list 2> /dev/null | cut -d '=' -f 2 | cut -d ';' -f 1` | |
if [ -n "$trader_result" ] ; then | |
echo $trader_result | |
exit_success | |
fi | |
done | |
exit_success | |
} | |
defapp_kde() | |
{ | |
MIME="$1" | |
if [ x"$KDE_SESSION_VERSION" = x"4" ]; then | |
KTRADER=`which ktraderclient 2> /dev/null` | |
MIMETYPE="--mimetype" | |
SERVICETYPE="--servicetype" | |
else | |
KTRADER=`which ktradertest 2> /dev/null` | |
fi | |
if [ -n "$KTRADER" ] ; then | |
DEBUG 1 "Running KDE trader query \"$MIME\" mimetype and \"Application\" servicetype" | |
trader_result=`$KTRADER $MIMETYPE "$MIME" $SERVICETYPE Application 2>/dev/null \ | |
| grep DesktopEntryPath | head -n 1 | cut -d ':' -f 2 | cut -d \' -f 2` | |
if [ -n "$trader_result" ] ; then | |
basename "$trader_result" | |
exit_success | |
else | |
exit_failure_operation_failed | |
fi | |
else | |
defapp_generic "$1" | |
fi | |
} | |
[ x"$1" != x"" ] || exit_failure_syntax | |
mode= | |
action= | |
filename= | |
mimetype= | |
case $1 in | |
install) | |
action=install | |
;; | |
uninstall) | |
action=uninstall | |
;; | |
query) | |
shift | |
if [ -z "$1" ] ; then | |
exit_failure_syntax "query type argument missing" | |
fi | |
case $1 in | |
filetype) | |
action=info | |
filename="$2" | |
if [ -z "$filename" ] ; then | |
exit_failure_syntax "FILE argument missing" | |
fi | |
case $filename in | |
-*) | |
exit_failure_syntax "unexpected option '$filename'" | |
;; | |
esac | |
check_input_file "$filename" | |
filename=`readlink -f -- "$filename"` | |
;; | |
default) | |
action=defapp | |
mimetype="$2" | |
if [ -z "$mimetype" ] ; then | |
exit_failure_syntax "mimetype argument missing" | |
fi | |
case $mimetype in | |
-*) | |
exit_failure_syntax "unexpected option '$mimetype'" | |
;; | |
*/*) | |
# Ok | |
;; | |
*) | |
exit_failure_syntax "mimetype '$mimetype' is not in the form 'minor/major'" | |
;; | |
esac | |
;; | |
*) | |
exit_failure_syntax "unknown query type '$1'" | |
;; | |
esac | |
;; | |
default) | |
action=makedefault | |
shift | |
if [ -z "$1" ] ; then | |
exit_failure_syntax "application argument missing" | |
fi | |
case $1 in | |
-*) | |
exit_failure_syntax "unexpected option '$1'" | |
;; | |
*.desktop) | |
filename="$1" | |
;; | |
*) | |
exit_failure_syntax "malformed argument '$1', expected *.desktop" | |
;; | |
esac | |
;; | |
*) | |
exit_failure_syntax "unknown command '$1'" | |
;; | |
esac | |
shift | |
if [ "$action" = "makedefault" ]; then | |
if [ -z "$1" ] ; then | |
exit_failure_syntax "mimetype argument missing" | |
fi | |
while [ $# -gt 0 ] ; do | |
case $1 in | |
-*) | |
exit_failure_syntax "unexpected option '$1'" | |
;; | |
esac | |
mimetype="$1" | |
shift | |
make_default_kde "$filename" "$mimetype" | |
make_default_generic "$filename" "$mimetype" | |
done | |
exit_success | |
fi | |
if [ "$action" = "info" ]; then | |
detectDE | |
if [ x"$DE" = x"" ]; then | |
if [ -x /usr/bin/file ]; then | |
DE=generic | |
fi | |
fi | |
case "$DE" in | |
kde) | |
info_kde "$filename" | |
;; | |
gnome*) | |
info_gnome "$filename" | |
;; | |
*) | |
info_generic "$filename" | |
;; | |
esac | |
exit_failure_operation_impossible "no method available for quering MIME type of '$filename'" | |
fi | |
if [ "$action" = "defapp" ]; then | |
detectDE | |
case "$DE" in | |
kde) | |
defapp_kde "$mimetype" | |
;; | |
*) | |
defapp_generic "$mimetype" | |
;; | |
esac | |
exit_failure_operation_impossible "no method available for quering default application for '$mimetype'" | |
fi | |
vendor=true | |
while [ $# -gt 0 ] ; do | |
parm="$1" | |
shift | |
case $parm in | |
--mode) | |
if [ -z "$1" ] ; then | |
exit_failure_syntax "mode argument missing for --mode" | |
fi | |
case "$1" in | |
user) | |
mode="user" | |
;; | |
system) | |
mode="system" | |
;; | |
*) | |
exit_failure_syntax "unknown mode '$1'" | |
;; | |
esac | |
shift | |
;; | |
--novendor) | |
vendor=false | |
;; | |
-*) | |
exit_failure_syntax "unexpected option '$parm'" | |
;; | |
*) | |
if [ -n "$filename" ] ; then | |
exit_failure_syntax "unexpected argument '$parm'" | |
fi | |
filename="$parm" | |
check_input_file "$filename" | |
;; | |
esac | |
done | |
if [ -z "$action" ] ; then | |
exit_failure_syntax "command argument missing" | |
fi | |
if [ -n "$XDG_UTILS_INSTALL_MODE" ] ; then | |
if [ "$XDG_UTILS_INSTALL_MODE" = "system" ] ; then | |
mode="system" | |
elif [ "$XDG_UTILS_INSTALL_MODE" = "user" ] ; then | |
mode="user" | |
fi | |
fi | |
if [ -z "$mode" ] ; then | |
if [ `whoami` = "root" ] ; then | |
mode="system" | |
else | |
mode="user" | |
fi | |
fi | |
if [ -z "$filename" ] ; then | |
exit_failure_syntax "mimetypes-file argument missing" | |
fi | |
if [ "$vendor" = "true" -a "$action" = "install" ] ; then | |
check_vendor_prefix "$filename" | |
fi | |
xdg_base_dir= | |
xdg_dir_name=mime/packages/ | |
xdg_user_dir="$XDG_DATA_HOME" | |
[ -n "$xdg_user_dir" ] || xdg_user_dir="$HOME/.local/share" | |
[ x"$mode" = x"user" ] && xdg_base_dir="$xdg_user_dir/mime" | |
xdg_user_dir="$xdg_user_dir/$xdg_dir_name" | |
xdg_system_dirs="$XDG_DATA_DIRS" | |
[ -n "$xdg_system_dirs" ] || xdg_system_dirs=/usr/local/share/:/usr/share/ | |
for x in `echo $xdg_system_dirs | sed 's/:/ /g'`; do | |
if [ -w $x/$xdg_dir_name ] ; then | |
[ x"$mode" = x"system" ] && xdg_base_dir="$x/mime" | |
xdg_global_dir="$x/$xdg_dir_name" | |
break | |
fi | |
done | |
[ -w $xdg_global_dir ] || xdg_global_dir= | |
DEBUG 3 "xdg_user_dir: $xdg_user_dir" | |
DEBUG 3 "xdg_global_dir: $xdg_global_dir" | |
# Find KDE3 mimelnk directory | |
kde_user_dir= | |
kde_global_dir= | |
kde_global_dirs=`kde${KDE_SESSION_VERSION}-config --path mime 2> /dev/null` | |
DEBUG 3 "kde_global_dirs: $kde_global_dirs" | |
first= | |
for x in `echo $kde_global_dirs | sed 's/:/ /g'` ; do | |
if [ -z "$first" ] ; then | |
first=false | |
kde_user_dir="$x" | |
elif [ -w $x ] ; then | |
kde_global_dir="$x" | |
fi | |
done | |
DEBUG 3 "kde_user_dir: $kde_user_dir" | |
DEBUG 3 "kde_global_dir: $kde_global_dir" | |
# TODO: Gnome legacy support | |
# See http://forums.fedoraforum.org/showthread.php?t=26875 | |
gnome_user_dir="$HOME/.gnome/apps" | |
gnome_global_dir=/usr/share/gnome/apps | |
[ -w $gnome_global_dir ] || gnome_global_dir= | |
DEBUG 3 "gnome_user_dir: $gnome_user_dir" | |
DEBUG 3 "gnome_global_dir: $gnome_global_dir" | |
if [ x"$mode" = x"user" ] ; then | |
xdg_dir="$xdg_user_dir" | |
kde_dir="$kde_user_dir" | |
gnome_dir="$gnome_user_dir" | |
my_umask=077 | |
else | |
xdg_dir="$xdg_global_dir" | |
kde_dir="$kde_global_dir" | |
gnome_dir="$gnome_global_dir" | |
my_umask=022 | |
if [ -z "${xdg_dir}${kde_dir}${gnome_dir}" ] ; then | |
exit_failure_operation_impossible "No writable system mimetype directory found." | |
fi | |
fi | |
# echo "[xdg|$xdg_user_dir|$xdg_global_dir]" | |
# echo "[kde|$kde_user_dir|$kde_global_dir]" | |
# echo "[gnome|$gnome_user_dir|$gnome_global_dir]" | |
# echo "[using|$xdg_dir|$kde_dir|$gnome_dir]" | |
basefile=`basename "$filename"` | |
#[ -z $vendor ] || basefile="$vendor-$basefile" | |
mimetypes= | |
if [ -n "$kde_dir" ] ; then | |
DEBUG 2 "KDE3 mimelnk directory found, extracting mimetypes from XML file" | |
mimetypes=`awk < "$filename" ' | |
# Strip XML comments | |
BEGIN { | |
suppress=0 | |
} | |
{ | |
do | |
if (suppress) { | |
if (match($0,/-->/)) { | |
$0=substr($0,RSTART+RLENGTH) | |
suppress=0 | |
} | |
else { | |
break | |
} | |
} | |
else { | |
if (match($0,/<!--/)) { | |
if (RSTART>1) print substr($0,0,RSTART) | |
$0=substr($0,RSTART+RLENGTH) | |
suppress=1 | |
} | |
else { | |
if ($0) print $0 | |
break | |
} | |
} | |
while(1) | |
} | |
' | awk ' | |
# List MIME types listed in <mime-type> tags | |
BEGIN { | |
RS="<" | |
} | |
/^mime-info/, /^\/mime-info/ { | |
if (match($0,/^mime-type/)) { | |
if (match($0,/type="[^"]*/) || match($0,/type='"'"'[^'"'"']*/)) { | |
print substr($0,RSTART+6,RLENGTH-6) | |
} | |
} | |
}'` | |
fi | |
DEBUG 1 "$action mimetype in $xdg_dir" | |
case $action in | |
install) | |
save_umask=`umask` | |
umask $my_umask | |
for x in $xdg_dir ; do | |
mkdir -p $x | |
eval 'cp $filename $x/$basefile'$xdg_redirect_output | |
done | |
if [ -n "$mimetypes" ] ; then | |
# No quotes around $mimetypes | |
for x in $mimetypes ; do | |
DEBUG 1 "Installing $kde_dir/$x.desktop (KDE 3.x support)" | |
mkdir -p `dirname $kde_dir/$x.desktop` | |
awk < "$filename" ' | |
# Strip XML comments | |
BEGIN { | |
suppress=0 | |
} | |
{ | |
do | |
if (suppress) { | |
if (match($0,/-->/)) { | |
$0=substr($0,RSTART+RLENGTH) | |
suppress=0 | |
} | |
else { | |
break | |
} | |
} | |
else { | |
if (match($0,/<!--/)) { | |
if (RSTART>1) print substr($0,0,RSTART) | |
$0=substr($0,RSTART+RLENGTH) | |
suppress=1 | |
} | |
else { | |
if ($0) print $0 | |
break | |
} | |
} | |
while(1) | |
} | |
' | awk > $kde_dir/$x.desktop ' | |
# Extract mimetype $x from the XML file $filename | |
# Note that bash requires us to escape a single quote as '"'"' | |
BEGIN { | |
the_type=ARGV[1] | |
the_source=ARGV[2] | |
ARGC=1 | |
RS="<" | |
found=0 | |
glob_patterns="" | |
} | |
/^mime-info/, /^\/mime-info/ { | |
if (match($0,/^mime-type/)) { | |
if (match($0,/type="[^"]*/) || match($0,/type='"'"'[^'"'"']*/)) { | |
if (substr($0,RSTART+6,RLENGTH-6) == the_type) { | |
found=1 | |
print "[Desktop Entry]" | |
print "# Installed by xdg-mime from " the_source | |
print "Type=MimeType" | |
print "MimeType=" the_type | |
the_icon=the_type | |
sub("/", "-", the_icon) | |
print "Icon=" the_icon | |
} | |
} | |
} | |
else if (found) { | |
if (match($0,/^\/mime-type/)) { | |
if (glob_patterns) | |
print "Patterns=" glob_patterns | |
exit 0 | |
} | |
if (match($0,/^sub-class-of/)) { | |
if (match($0,/type="[^"]*/) || match($0,/type='"'"'[^'"'"']*/)) { | |
print "X-KDE-IsAlso=" substr($0,RSTART+6,RLENGTH-6) | |
} | |
else { | |
print "Error: '"'"'type'"'"' argument missing in " RS $0 | |
exit 1 | |
} | |
} | |
if (match($0,/^glob/)) { | |
if (match($0,/pattern="[^"]*/) || match($0,/pattern='"'"'[^'"'"']*/)) { | |
glob_patterns = glob_patterns substr($0,RSTART+9,RLENGTH-9) ";" | |
} | |
else { | |
print "Error: '"'"'pattern'"'"' argument missing in " RS $0 | |
exit 1 | |
} | |
} | |
if (match($0,/^comment/)) { | |
if (match($0,/xml:lang="[^"]*/) || match($0,/xml:lang='"'"'[^'"'"']*/)) { | |
lang=substr($0,RSTART+10,RLENGTH-10) | |
} | |
else { | |
lang="" | |
} | |
if (match($0,/>/)) { | |
comment=substr($0,RSTART+1) | |
sub("<", "<", comment) | |
sub(">", ">", comment) | |
sub("&", "\\&", comment) | |
if (lang) | |
print "Comment[" lang "]=" comment | |
else | |
print "Comment=" comment | |
} | |
} | |
} | |
} | |
END { | |
if (!found) { | |
print "Error: Mimetype '"'"'" the_type "'"'"' not found" | |
exit 1 | |
} | |
} | |
' $x $basefile | |
if [ "$?" = "1" ] ; then | |
grep -A 10 "^Error:" $kde_dir/$x.desktop >&2 | |
rm $kde_dir/$x.desktop | |
exit 1 | |
fi | |
done | |
fi | |
umask $save_umask | |
;; | |
uninstall) | |
for x in $xdg_dir ; do | |
rm -f $x/$basefile | |
done | |
# No quotes around $mimetypes | |
for x in $mimetypes ; do | |
if grep '^# Installed by xdg-mime' $kde_dir/$x.desktop >/dev/null 2>&1; then | |
DEBUG 1 "Removing $kde_dir/$x.desktop (KDE 3.x support)" | |
rm -f $kde_dir/$x.desktop | |
fi | |
done | |
;; | |
esac | |
update_mime_database $xdg_base_dir | |
exit_success | |