#!/bin/sh
#---------------------------------------------
#   xdg-mime
#
#   Utility script to manipulate MIME related information
#   on XDG compliant systems.
#
#   Refer to the usage() function below for usage.
#
#   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.
#
#---------------------------------------------

examples()
{
cat << _EXAMPLES
Examples

 xdg-mime --info /tmp/foobar.png

   Prints the MIME type of the file /tmp/foobar.png

 xdg-mime --defapp /tmp/foobar.png

   Prints the name of the .desktop file of the application which is
   registered to open files of the MIME type the file /tmp/foobar.png has

 xdg-mime --system --install diff.xml

   Adds a file type description for "diff"-files for all users on the system.
   The file type description could look as folows.

 diff.xml:

 <?xml version="1.0"?>
 <mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
   <mime-type type="text/x-diff">
     <comment>Differences between files</comment>
     <glob pattern="*.diff"/>
     <glob pattern="*.patch"/>
   </mime-type>
 </mime-info>
_EXAMPLES
}

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 [--help] [--version] [ --info FILE | --defapp FILE ] { --user |
   --system } { --install mimetypes-file | --uninstall mimeypes-file }

_USAGE
}

#@xdg-utils-common@

#----------------------------------------------------------------------------
#   Common utility functions included in all XDG wrapper scripts
#----------------------------------------------------------------------------

#-------------------------------------------------------------
# Exit script on successfully completing the desired operation

exit_success()
{
    if [ $# -gt 0 ]; then
        echo "$@"
        echo
    fi

    exit 0
}


#-----------------------------------------
# Exit script on wrong number of arguments
# prints usage information

exit_failure_arg_count()
{
    if [ $# -gt 0 ]; then
        echo "$@"
        echo
    fi

    usage

    exit 1
}


#-----------------------------------
# Exit script on malformed arguments
# prints usage information

exit_failure_arg_malformed()
{
    if [ $# -gt 0 ]; then
        echo "$@"
        echo
    fi

    usage

    exit 2
}

#-------------------------------------------------------------
# Exit script on failure to locate necessary tool applications

exit_failure_operation_impossible()
{
    if [ $# -gt 0 ]; then
        echo "$@"
        echo
    fi

    exit 3
}

#-------------------------------------------------------------
# Exit script on failure returned by a tool application

exit_failure_operation_failed()
{
    if [ $# -gt 0 ]; then
        echo "$@"
        echo
    fi

    exit 4
}

#----------------------------------------
# Checks for shared commands, e.g. --help

check_common_commands()
{
    while [ $# -gt 0 ] ; do
        parm=$1
        shift

        case $parm in
            --help)
            usage
            examples
            exit_success
            ;;

            --version)
            echo "xdg-utils technical-preview"
            exit_success
            ;;
        esac
    done
}

check_common_commands "$@"

#--------------------------------------
# Checks for known desktop environments
# set variable DE to the desktop environments name, lowercase

detectDE()
{
    if [ x"$KDE_FULL_SESSION" = x"true" ]; then DE=kde;
    elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then DE=gnome;
    elif xprop -root _DT_SAVE_MODE | grep ' = \"xfce4\"$' >/dev/null 2>&1; then DE=xfce;
    fi
}

detectDE

#----------------------------------------------------------------------------



update_mime_database()
{
   for x in `echo $PATH | sed 's/:/ /g'` /opt/gnome/bin; do
      if [ -x $x/update-mime-database ] ; then
         echo Running $x/update-mime-database $1
         $x/update-mime-database $1
         return
      fi
   done
}

info_kde()
{
    kfile "$1" 2> /dev/null | head -n 1 | cut -d "(" -f 2 | cut -d ")" -f 1

    exit_success
}

info_gnome()
{
    gnomevfs-info "$1" 2> /dev/null | grep MIME | cut -d ":" -f 2 | sed s/"^ "//

    exit_success
}

info_generic()
{
    /usr/bin/file -i "$1" 2> /dev/null | cut -d ":" -f 2 | sed s/"^ "//

    exit_success
}

defapp_kde()
{
    MIME=`kfile "$1" 2> /dev/null | head -n 1 | cut -d "(" -f 2 | cut -d ")" -f 1`

    if [ x"$MIME" != x"" ]; then
        ktradertest "$MIME" Application 2>/dev/null | grep DesktopEntryPath \
            | head -n 1 | cut -d ':' -f 2 | cut -d \' -f 2 | xargs basename
        exit_success
    else
        exit_failure_operation_failed
    fi
}

defapp_gnome()
{
    gnomevfs-info "$1" 2> /dev/null | grep "Default app" | cut -d ":" -f 2 \
        | cut -d " " -f 2

    exit_success
}

[ x"$1" != x"" ] || exit_failure_arg_count

mode=
action=
mimetypes_file=
info_file=
while [ $# -gt 0 ] ; do
    parm=$1
    shift

    case $parm in
      --install)
        if [ -n "$action" ] ; then
            exit_failure_arg_count "Error:  Too many options:" $parm $1
        fi
        if [ ! -f "$1" ] ; then
            exit_failure_arg_count "Error:  You must specify an existing file to install."
        fi

        action=install
        mimetypes_file=$1
        shift
        ;;

      --uninstall)
        if [ -n "$action" ] ; then
            exit_failure_arg_count "Error:  Too many options:" $parm $1
        fi
        if [ -z "$1" ] ; then
            exit_failure_arg_count "Error:  You must specify a file to uninstall."
        fi
        action=uninstall
        mimetypes_file=$1
        shift
        ;;

      --info)
        if [ -n "$action" ] ; then
            exit_failure_arg_count "Error:  Too many options:" $parm $1
        fi
        if [ -z "$1" ] ; then
            exit_failure_arg_count "Error:  You must specify a file with --info."
        fi
        action=info
        info_file=$1
        shift
        ;;

      --defapp)
        if [ -n "$action" ] ; then
            exit_failure_arg_count "Error:  Too many options:" $parm $1
        fi
        if [ -z "$1" ] ; then
            exit_failure_arg_count "Error:  You must specify a file with --defapp."
        fi
        action=defapp
        info_file=$1
        shift
        ;;

      --user)
        mode=user
        ;;

      --system)
        mode=system
        ;;

      *)
        exit_failure_arg_malformed "$parm:  Invalid parameter/option"
        ;;
    esac
done


if [ -z "$action" ] ; then
    exit_failure_arg_count
fi


if [ "$action" = "info" ]; then
    if [ -n "$mode" ] ; then
        exit_failure_arg_count "Error:  Too many options: --$mode"
    fi

    if [ x"$DE" = x"" ]; then
        if [ -x /usr/bin/file ]; then
            DE=generic
        fi
    fi

    case "$DE" in
        kde)
        info_kde "$info_file"
        ;;

        gnome)
        info_gnome "$info_file"
        ;;

        generic)
        info_generic "$info_file"
        ;;
    esac
    exit_failure_operation_impossible "Sorry, no method available for quering MIME type of" "$info_file"
fi

if [ "$action" = "defapp" ]; then
    if [ -n "$mode" ] ; then
        exit_failure_arg_count "Error:  Too many options: --$mode"
    fi

    case "$DE" in
        kde)
        defapp_kde "$info_file"
        ;;

        gnome)
        defapp_gnome "$info_file"
        ;;
    esac
    exit_failure_operation_impossible "Sorry, no method available for quering default application for file" "$info_file"
fi

if [ -z "$mode" ] ; then
    exit_failure_arg_malformed "Error:  You must specify either --user or --system"
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=

# TODO: KDE legacy support
kde_user_dir=$HOME/.kde/share/mimelnk
kde_global_dir=/usr/share/mimelnk
[ -w $kde_global_dir ] || kde_global_dir=

# TODO: Gnome legacy support
gnome_user_dir=$HOME/.gnome/apps
gnome_global_dir=/usr/share/gnome/apps
[ -w $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
        [ `whoami` = "root" ] || rootmsg="Try as root or use --user."
        exit_failure_operation_impossible "No writable system mimetype directory found. $rootmsg"
    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 $mimetypes_file`
#[ -z $vendor ] || basefile=$vendor-$basefile

case $action in
    install)
        save_umask=`umask`
        umask $my_umask

        for x in $xdg_dir ; do
            mkdir -p $x
            cp $mimetypes_file $x/$basefile
        done

        umask $save_umask
        ;;

    uninstall)
        for x in $xdg_dir ; do
            rm -f $x/$basefile
        done

        ;;
esac

update_mime_database $xdg_base_dir

exit_success

