#!/bin/sh
#---------------------------------------------
#   xdg-menu
#
#   Utility script to install menu items on a Linux desktop.
#   Works on most XDG compliant systems; does
#   not work everywhere.
#
#   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

   The company ShinyThings Inc. has developed an application named
   "WebMirror" and would like to add it to the application menu. The company
   will use "shinythings" as its vendor id. In order to add the application
   to the menu there needs to be a .desktop file with a suitable Categories
   entry:

 webmirror.desktop:

   [Desktop Entry]
   Encoding=UTF-8
   Type=Application

   Exec=webmirror
   Icon=webmirror

   Name=WebMirror
   Name[nl]=WebSpiegel

   Categories=Network;WebDevelopment;

   Now the xdg-menu tool can be used to add the webmirror.desktop file to the
   desktop application menu:

 xdg-menu --system --vendor shinythings --install ./webmirror.desktop

   Note that for the purpose of this example the menu items are available in
   two languages, English and Dutch. The language code for Dutch is nl.

   In the next example the company ShinyThings Inc. wants to add its own
   submenu to the desktop application menu consisting of a "WebMirror" menu
   item and a "WebMirror Admin Tool" menu item.

   First the company needs to create two .desktop files that describe the two
   menu items, this time no Categories item is needed:

 webmirror.desktop:

   [Desktop Entry]
   Encoding=UTF-8
   Type=Application

   Exec=webmirror
   Icon=webmirror

   Name=WebMirror
   Name[nl]=WebSpiegel


 webmirror-admin.desktop:

   [Desktop Entry]
   Encoding=UTF-8
   Type=Application

   Exec=webmirror-admintool
   Icon=webmirror-admintool

   Name=WebMirror Admin Tool
   Name[nl]=WebSpiegel Administratie Tool

   The files can be installed with:

 xdg-menu --system --noupdate --vendor shinythings --install ./webmirror.desktop
 xdg-menu --system --noupdate --vendor shinythings --install ./webmirror-admin.desktop

   Because multiple items are added the --noupdate option has been used.

   In addition a .directory file needs to be created to provide a title and
   icon for the sub-menu itself:

 webmirror.directory:

   [Desktop Entry]
   Encoding=UTF-8

   Icon=webmirror

   Name=WebMirror
   Name[nl]=WebSpiegel

   This webmirror.directorty file can be installed with:

 xdg-menu --system --noupdate --vendor shinythings --install ./webmirror.directory

   The last step is to provide a .menu file that links it all togther:

 webmirror.menu:

   <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 0.8//EN"
      "http://www.freedesktop.org/standards/menu-spec/menu-0.8.dtd">
   <Menu>
     <Menu>
       <Name>WebMirror</Name>
       <Directory>shinythings-webmirror.directory</Directory>
       <Include>
         <Filename>shinythings-webmirror.desktop</Filename>
         <Filename>shinythings-webmirror-admin.desktop</Filename>
       </Include>
     </Menu>
   </Menu>

   The webmirror.menu file can be installed with:

 xdg-menu --system --noupdate --vendor shinythings --install ./webmirror.menu

   After installing multiple files with --noupdate make sure to force an
   update:

 xdg-menu --system --forceupdate
_EXAMPLES
}

usage()
{
cat << _USAGE
   xdg-menu -- command line tool for (un)installing desktop menu items

Synopsis

   xdg-menu [--help] [--version] [--vendor vendor-id] [--noupdate] { --user |
   --system } { --install desktop-file | --install directory-file | --install
   menu-file | --uninstall desktop-file | --uninstall directory-file |
   --uninstall menu-file | --forceupdate }

_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_desktop_database()
{
#    echo Update desktop database: $mode
    if [ "$mode" = "system" ] ; then
        for x in `echo $PATH | sed 's/:/ /g'` /opt/gnome/bin; do
           if [ -x $x/update-desktop-database ] ; then
              echo Running $x/update-desktop-database
              $x/update-desktop-database
              return
           fi
        done
    fi
}

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

mode=
action=
update=yes
desktop_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
        desktop_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
        desktop_file=$1
        shift
        ;;

      --forceupdate)
        if [ -n "$action" ] ; then
            exit_failure_arg_count "Error:  Too many options:" $parm $1
        fi

        action=forceupdate
        ;;

      --noupdate)
        update=no
        ;;

      --user)
        mode=user
        ;;

      --system)
        mode=system
        ;;

      --vendor)
        if [ -z "$1" ] ; then
            exit_failure_arg_count "Error:  You must specify a vendor-id."
        fi
        vendor=$1
        shift
        ;;

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

if [ -z "$mode" ] ; then
    exit_failure_arg_malformed "Error:  You must specify either --user or --system"
fi

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

if [ x"$action" = x"forceupdate" ] ; then
    update_desktop_database
    exit_success
fi

filetype=
xdg_dir_name=
case $desktop_file in
  *.desktop)
     filetype=desktop
     xdg_dir_name=applications
     ;;
  *.directory)
     fileype=directory
     xdg_dir_name=desktop-directories
     ;;
  *.menu)
     filetype=menu
     xdg_dir_name=menus/applications-merged
     ;;
  *)
     exit_failure_arg_malformed "Error: File to $action must be a *.desktop, *.directory or *.menu file"
     ;;
esac

if [ x"$filetype" = x"menu" ] ; then
    xdg_user_dir=$XDG_CONFIG_HOME
    [ -n "$xdg_user_dir" ] || xdg_user_dir=$HOME/.config
    xdg_user_dir=$xdg_user_dir/$xdg_dir_name

    xdg_system_dirs=$XDG_CONFIG_DIRS
    [ -n "$xdg_system_dirs" ] || xdg_system_dirs=/etc/xdg
    for x in `echo $xdg_system_dirs | sed 's/:/ /g'` ; do
        if [ -w $x/$xdg_dir_name ] ; then
            xdg_global_dir=$x/$xdg_dir_name
            break
        fi
    done
    [ -w $xdg_global_dir ] || xdg_global_dir=
else
    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_system_dirs | sed 's/:/ /g'` ; do
        if [ -w $x/$xdg_dir_name ] ; then
            xdg_global_dir=$x/$xdg_dir_name
            break
        fi
    done
    [ -w $xdg_global_dir ] || xdg_global_dir=

    if [ x"$filetype" = x"desktop" ] ; then
        kde_user_dir=$HOME/.kde/share/applnk
        kde_global_dir=/usr/share/applnk
        [ -w $kde_global_dir ] || kde_global_dir=

        gnome_user_dir=$HOME/.gnome/apps
        gnome_global_dir=/usr/share/gnome/apps
        [ -w $gnome_global_dir ] || gnome_global_dir=
    fi
fi


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 menu 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 $desktop_file`
[ -z $vendor ] || basefile=$vendor-$basefile

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

        for x in $xdg_dir $kde_dir $gnome_dir ; do
            mkdir -p $x
            cp $desktop_file $x/$basefile
        done

        if [ -f $kde_dir/$basefile ] ; then
            echo "OnlyShowIn=Old;" >> $kde_dir/$basefile
        fi

        if [ -f $gnome_dir/$basefile ] ; then
            echo "OnlyShowIn=Old;" >> $gnome_dir/$basefile
        fi

        umask $save_umask
        ;;

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

        ;;
esac

if [ x"$update" = x"yes" ] ; then
    update_desktop_database
fi

exit_success


