You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

699 lines
17 KiB
Bash

#!/bin/bash
# Creates a new blank OPSI package with install and remove scripts
function usage {
echo "Usage:"
echo " $0 <product-id>"
echo ""
echo "Optional parameters:"
echo " -d <Product Description> Adds a description to the package"
echo " -n <Product Name> Adds a product name instead of autogenerating one"
echo " -g yes Adds the Gruelag prefix to package ID and name, do not manually add Gruelag when using this!"
echo " -u <Program URL> Downloads an installer file from the specified URL"
echo " -i <Logo URL> Applies a logo to the package from the specified URL"
echo " -t <Package Type> Sets the type of package to create, see below"
echo " -v <Program version> Sets the version of the program (not the package)"
echo ""
echo "Package types:"
echo " winbatch Creates a blank WinBatch package"
echo " winbatch-inno Creates a blank INNO Installer WinBatch package"
echo " winbatch-nsis Creates a blank NSIS Installer WinBatch package"
echo " dosicon Creates a blank DosInAnIcon package"
echo " execps Creates a blank ExecWith Powershell package"
echo " zip Creates a blank ZIP based package"
echo " msi Creates a blank MSI installer package"
echo " weblinks Creates a weblink creator package"
echo ""
echo "Parameters for 'zip' type package:"
echo " -e <filename.exe> Optional, specifies the launcher executable inside the ZIP file"
echo ""
echo "Parameters for 'weblinks' type package:"
echo " -l <link name>;<target url>;[<where>] Can be used multiple times, specifies the URL and display name for one web link."
echo " <where> is optional and can hold one of the following values:"
echo " 'desktop' to create only desktop links on the public user desktop"
echo " 'startmenu' to create links only in the public user start menu"
echo " 'both' to create links at both places, this is the default"
}
if [[ "$1" = "" ]]; then
echo "Please specify the package name as first parameter."
usage
exit 1
else
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
usage
exit 0
else
productId="$1"
shift
fi
fi
# Defaults
programVersion="1.0"
pkgType="default"
weblinks=()
# Read command flags
while getopts ":d:g:n:t:e:u:i:v:l:h:" flag
do
case "${flag}" in
d) productDescription="${OPTARG}";;
g) productIdPrefix="gruelag-" && productNamePrefix="Gruelag ";;
n) productName=${OPTARG};;
t) pkgType=${OPTARG};;
e) zipExecutable="${OPTARG}";;
u) downloadUrl="${OPTARG}";;
i) imageUrl="${OPTARG}";;
v) programVersion="${OPTARG}";;
l) weblinks+=("${OPTARG}");;
h)
usage
exit 0
;;
*)
echo "Unrecognized option '${flag}'"
usage
exit 1
;;
esac
done
# Test if product ID was supplied empty
if [ "${productId}" = "" ]; then
echo "Product ID is empty, aborting!"
exit 1
fi
fullProductName="${productName}"
# Generate product name from ID if it is not set already
if [ "${productName}" = "" ]; then
# Replace dashes with spaces and uppercase first letter of every word
productName=$(echo "${productId//-/ }" | sed -r 's/\<./\U&/g')
fi
# Prepend optional prefixes to product name and ID if they aren't already
if [ "${productIdPrefix}" != "" ] && \
[ "${productId:0:${#productIdPrefix}}" != "${productIdPrefix}" ];
then
productId="${productIdPrefix}${productId}"
fullProductName="${productNamePrefix}${productName}"
fi
# Dump some package info
echo "-- Package info --"
echo "ID: ${productId}"
echo "Name: ${fullProductName}"
echo "Description: ${productDescription}"
echo "Type: ${pkgType}"
echo "-- --"
echo ""
echo "Creating package directory..."
if [ -d "${productId}" ]; then
echo "A folder with the package name already exists"
exit 1
elif ! mkdir "${productId}"; then
echo "Could not create the package directory"
exit 1
fi
pushd "${productId}" >/dev/null
echo "Creating control file..."
cat >control <<EOF
[Product]
type: localboot
id: ${productId}
name: ${fullProductName}
description: ${productDescription}
version: ${programVersion}
packageVersion: 1.0
setupScript: install.ins
uninstallScript: remove.ins
EOF
# Optionally download program file
if [ ! "${downloadUrl}" = "" ]; then
echo "Downloading program file..."
mkdir data
pushd data >/dev/null
_filename=$(curl -Lfsw "%{filename_effective}" -O "${downloadUrl}")
if [ $? -ne 0 ]; then
echo "Curl failed to download the file from ${downloadUrl}"
else
bytes=$(wc -c "${_filename}" | awk '{ print $1 }')
if [ ${bytes} -le 1 ]; then
echo "Program file was downloaded, but is ${bytes} bytes in size!"
else
echo "Program file downloaded to data/${_filename}, ${bytes} bytes in size"
filename="${_filename}"
fi
fi
popd >/dev/null
fi
# Some reusable code snippets as variables:
read -r -d '' Sub_HandleExitCode <<EOS
[Sub_HandleExitCode]
Set \$ExitCode\$ = GetLastExitCode
comment "GetLastExitCode: " + \$ExitCode\$
if not(\$ExitCode\$ = "0")
LogError "Fatal: script returned exit code " + \$ExitCode\$
IsFatalError
endif
EOS
read -r -d '' Sub_HandleExitCode_MSI <<EOS
[Sub_HandleExitCode_MSI]
; check return code
Set \$ExitCode\$ = GetLastExitCode
comment "GetLastExitCode: " + \$ExitCode\$
if not(\$ExitCode\$ = "0" or \$ExitCode\$ = "3010" or \$ExitCode\$ = "1605")
; 0 ERROR_SUCCESS
; 3010 ERROR_SUCCESS_REBOOT_REQUIRED
; 1605 ERROR_UNKNOWN_PRODUCT
LogError "Fatal: setup returned exit code " + \$ExitCode\$
IsFatalError
endif
EOS
echo "Creating install and remove script files for type ${pkgType}..."
case "${pkgType}" in
winbatch-nsis)
if [ "${filename}" = "" ]; then
_instFile="setup.exe"
else
_instFile="${filename}"
fi
cat >install.ins <<-EOF
[Initial]
Message=Installiere ${productName}...
DefVar \$ExitCode\$
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
WinBatch_Install
Sub_HandleExitCode
[WinBatch_Install]
"%ScriptPath%\\data\\${_instFile}" /S
${Sub_HandleExitCode}
EOF
cat >remove.ins <<-EOF
[Initial]
Message=Entferne ${productName}...
DefVar \$ExitCode\$
DefVar \$InstallPath\$
DefVar \$UninsFile\$
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
Sub_SetVars
Files_CopyUninstallerToTemp
WinBatch_Uninstall
Sub_HandleExitCode
Files_RemoveTempUninstaller
[Sub_SetVars]
Set \$InstallPath\$ = "%ProgramFilesDir%\\${productName}"
Set \$UninsFile\$ = "unins000.exe"
[Files_CopyUninstallerToTemp]
Copy "\$InstallPath\$\\\$UninsFile\$" "%opsiTmpDir%"
[WinBatch_Uninstall]
"%opsiTmpDir%\\\$UninsFile\$" /S _?=\$InstallPath\$
[Files_RemoveTempUninstaller]
Delete "%opsiTmpDir%\\\$UninsFile\$"
${Sub_HandleExitCode}
EOF
echo "Remember to change the path and uninstaller file name in remove.ins!"
;;
winbatch-inno)
if [ "${filename}" = "" ]; then
_instFile="setup.exe"
else
_instFile="${filename}"
fi
cat >install.ins <<-EOF
[Initial]
Message=Installiere ${productName}...
DefVar \$ExitCode\$
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
WinBatch_Install
Sub_HandleExitCode
[WinBatch_Install]
"%ScriptPath%\\data\\${_instFile}" /SILENT /NOCANCEL /NORESTART /FORCECLOSEAPPLICATIONS /NORESTARTAPPLICATIONS
${Sub_HandleExitCode}
EOF
cat >remove.ins <<-EOF
[Initial]
Message=Entferne ${productName}...
DefVar \$ExitCode\$
DefVar \$UninstallPath\$
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
WinBatch_Uninstall
Sub_HandleExitCode
[WinBatch_Uninstall]
"%ProgramFilesDir%\\${productName}\\unins000.exe" /SILENT
${Sub_HandleExitCode}
EOF
echo "Remember to change the uninstaller path in remove.ins!"
;;
winbatch)
if [ "${filename}" = "" ]; then
_instFile="setup.exe"
else
_instFile="${filename}"
fi
cat >install.ins <<-EOF
[Initial]
Message=Installiere ${productName}...
DefVar \$ExitCode\$
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
WinBatch_Install
Sub_HandleExitCode
[WinBatch_Install]
"%ScriptPath%\\data\\${_instFile}" /S
${Sub_HandleExitCode}
EOF
cat >remove.ins <<-EOF
[Initial]
Message=Entferne ${productName}...
DefVar \$ExitCode\$
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
WinBatch_Remove
Sub_HandleExitCode
[WinBatch_Remove]
"uninstall-exe-path-here" /S
${Sub_HandleExitCode}
EOF
echo "Remember to customize the executable paths in install.ins and remove.ins!"
;;
dosicon)
if [ "${filename}" = "" ]; then
_instCommand="your-setup-command-here"
else
_instCommand="%ScriptPath%\\data\\${filename}"
fi
cat >install.ins <<-EOF
[Initial]
Message=Installiere ${productName}...
DefVar \$ExitCode\$
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
WinBatch_Install
Sub_HandleExitCode
[DosInAnIcon_Install]
@echo off
${_instCommand}
${Sub_HandleExitCode}
EOF
cat >remove.ins <<-EOF
[Initial]
Message=Entferne ${productName}...
DefVar \$ExitCode\$
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
DosInAnIcon_Remove
Sub_HandleExitCode
[DosInAnIcon_Remove]
@echo off
your-uninstall-command-here
${Sub_HandleExitCode}
EOF
echo "Remember to customize the DosInAnIcon commands in install.ins and remove.ins!"
;;
execps)
if [ "${filename}" = "" ]; then
_instCommand="your-setup-command-here"
else
_instCommand="%ScriptPath%\\data\\${filename}"
fi
cat >install.ins <<-EOF
[Initial]
Message=Installiere ${productName}...
DefVar \$ExitCode\$
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
ExecWith_Install "powershell.exe" -ExecutionPolicy Bypass
Sub_HandleExitCode
[ExecWith_Install]
trap { "PS Error: \$_"; exit 1 }
${_instCommand}
if(-not (\$?)) { exit 1 }
${Sub_HandleExitCode}
EOF
cat >remove.ins <<-EOF
[Initial]
Message=Entferne ${productName}...
DefVar \$ExitCode\$
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
ExecWith_Remove "powershell.exe" -ExecutionPolicy Bypass
Sub_HandleExitCode
[ExecWith_Remove]
trap { "PS Error: $_"; exit 1 }
your-uninstall-command-here
if(-not (\$?)) { exit 1 }
${Sub_HandleExitCode}
EOF
echo "Remember to customize the PowerShell commands in install.ins and remove.ins!"
;;
zip)
if [ "${filename}" = "" ]; then
_zipFile="${productId}.zip"
else
_zipFile="${filename}"
fi
if [ "${zipExecutable}" = "" ]; then
_zipExe="start.exe"
else
_zipExec="${zipExecutable}"
fi
cat >install.ins <<-EOF
[Initial]
Message=Installiere ${productName}...
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
Sub "%ScriptPath%\\remove.inc.ins"
Files_UnzipPackage
LinkFolder_StartMenuEntry
[Files_UnzipPackage]
CheckTargetPath = "%ProgramFilesDir%\\${productId}"
UnzipFile "%ScriptPath%\\data\\${_zipFile}" "%ProgramFilesDir%\\${productId}"
[LinkFolder_StartMenuEntry]
Set_BaseFolder Common_Programs
Set_SubFolder "${productName}"
Set_Link
name: ${productName}
target: "%ProgramFilesDir%\\${productId}\\${_zipExe}"
parameters:
working_dir: "%ProgramFilesDir%\\${productId}"
icon_file: "%ProgramFilesDir%\\${productId}\\${_zipExe}"
icon_index: 0
shortcut:
End_Link
EOF
cat >remove.ins <<-EOF
[Initial]
Message=Entferne ${productName}...
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
Sub "%ScriptPath%\remove.inc.ins"
EOF
cat >remove.inc.ins <<-EOF
Files_RemoveProgramFolder
LinkFolder_RemoveStartMenuEntry
[Files_RemoveProgramFolder]
Del -sf "%ProgramFilesDir%\\${productId}"
[LinkFolder_RemoveStartMenuEntry]
Set_BaseFolder Common_Programs
Delete_Subfolder "${productName}"
EOF
echo "Make sure the names and paths in install.ins and remove.inc.ins are correct!"
;;
msi)
if [ "${filename}" = "" ]; then
_instFile="setup.msi"
else
_instFile="${filename}"
fi
cat >install.ins <<-EOF
[Initial]
Message=Installiere ${productName}...
DefVar \$ExitCode\$
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
WinBatch_Install
Sub_HandleExitCode_MSI
[WinBatch_Install]
msiexec /passive /i "%ScriptPath%\\data\\${_instFile}"
${Sub_HandleExitCode_MSI}
EOF
cat >remove.ins <<-EOF
[Initial]
Message=Entferne ${productName}...
DefVar \$ExitCode\$
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
WinBatch_Remove
Sub_HandleExitCode
[WinBatch_Remove]
"%ScriptDrive%\\tools\\autoit\\msiRemove_withLog.exe" "${productName}"
${Sub_HandleExitCode_MSI}
EOF
echo "Make sure the WinBatch_Remove section in remove.ins does the right things!"
;;
weblinks)
cat >install.ins <<-EOF
[Initial]
Message=Installiere ${productName}...
DefVar \$PkgDir\$
[Actions]
ShowBitmap "%ScriptPath%\logo.png" "${productName}"
Sub_SetVars
Files_CopyIcons
Sub "%ScriptPath%\install-desktop.inc.ins"
Sub "%ScriptPath%\install-startmenu.inc.ins"
[Sub_SetVars]
Set \$PkgDir\$ = "%ProgramFilesDir%\%installingProdName%"
[Files_CopyIcons]
CheckTargetPath = "\$PkgDir\$"
Copy -s "%ScriptPath%\data\icons\" "\$PkgDir\$"
EOF
cat >remove.ins <<-EOF
[Initial]
Message=Entferne ${productName}...
DefVar $PkgDir$
[Actions]
ShowBitmap "%ScriptPath%\logo.png" "${productName}"
Sub_SetVars
Files_DeleteIcons
Sub "%ScriptPath%\remove-desktop.inc.ins"
Sub "%ScriptPath%\remove-startmenu.inc.ins"
[Sub_SetVars]
Set \$PkgDir\$ = "%ProgramFilesDir%\%installingProdName%"
[Files_DeleteIcons]
Del -s -f "\$PkgDir\$"
EOF
source ../fetch-favicon.sh
mkdir -p data/icons
desktopLinkFolderList=$(mktemp)
startMenuLinkFolderList=$(mktemp)
desktopRemoveFolderList=$(mktemp)
startMenuRemoveFolderList=$(mktemp)
for (( i = 0; i < ${#weblinks[@]}; i++ )); do
link=${weblinks[${i}]}
linkName=$(echo "${link}" | awk -F';' '{ print $1 }')
linkInternalName=$(sed "s/[^a-zA-Z-]/_/g" <<< ${linkName})
linkTarget=$(echo "${link}" | awk -F';' '{ print $2 }')
linkLocation=$(echo "${link}" | awk -F';' '{ print $3 }')
# Desktop entries
if [ "${linkLocation}" = "desktop" ] || [ "${linkLocation}" = "both" ]; then
echo "LinkFolder_Desktop_${linkInternalName}" >> "install-desktop.inc.ins"
echo "LinkFolder_Remove_Desktop_${linkInternalName}" >> "remove-desktop.inc.ins"
cat >>"${desktopLinkFolderList}" <<EOP
[LinkFolder_Desktop_${linkInternalName}]
Set_BaseFolder Common_DesktopDirectory
Set_SubFolder ""
Set_Link
Name: ${linkName}
Target: "${linkTarget}"
Icon_File: "\$PkgDir\$\\${linkInternalName}.ico"
End_Link
EOP
cat >>"${desktopRemoveFolderList}" <<-EOP
[LinkFolder_Remove_Desktop_${linkInternalName}]
Set_BaseFolder Common_DesktopDirectory
Set_SubFolder ""
Delete_Element "${linkName}"
EOP
fi
# Start menu entries
if [ "${linkLocation}" = "startmenu" ] || [ "${linkLocation}" = "both" ]; then
echo "LinkFolder_StartMenu_${linkInternalName}" >> "install-startmenu.inc.ins"
echo "LinkFolder_Remove_StartMenu_${linkInternalName}" >> "remove-startmenu.inc.ins"
cat >>"${startMenuLinkFolderList}" <<EOP
[LinkFolder_StartMenu_${linkInternalName}]
Set_BaseFolder Common_StartMenu
Set_SubFolder ""
Set_Link
Name: ${linkName}
Target: "${linkTarget}"
Icon_File: "\$PkgDir\$\\${linkInternalName}.ico"
End_Link
EOP
cat >>"${startMenuRemoveFolderList}" <<-EOP
[LinkFolder_Remove_StartMenu_${linkInternalName}]
Set_BaseFolder Common_StartMenu
Set_SubFolder ""
Delete_Element "${linkName}"
EOP
fi
fetchFavicon "${linkTarget}" "data/icons/${linkInternalName}.ico"
done
echo >> "install-desktop.inc.ins"
cat "${desktopLinkFolderList}" >> "install-desktop.inc.ins"
echo >> "install-startmenu.inc.ins"
cat "${startMenuLinkFolderList}" >> "install-startmenu.inc.ins"
echo >> "remove-desktop.inc.ins"
cat "${desktopRemoveFolderList}" >> "remove-desktop.inc.ins"
echo >> "remove-startmenu.inc.ins"
cat "${startMenuRemoveFolderList}" >> "remove-startmenu.inc.ins"
rm "${desktopLinkFolderList}"
rm "${startMenuLinkFolderList}"
rm "${desktopRemoveFolderList}"
rm "${startMenuRemoveFolderList}"
;;
*)
cat >install.ins <<-EOF
[Initial]
Message=Installiere ${productName}...
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
Sub_Install
[Sub_Install]
EOF
cat >remove.ins <<-EOF
[Initial]
Message=Entferne ${productName}...
[Actions]
ShowBitmap "%ScriptPath%\\logo.png" "${productName}"
Sub_Remove
[Sub_Remove]
EOF
;;
esac
# Create logo if specified
if [ ! "${imageUrl}" = "" ]; then
_imgfilename="$(curl -s -w "%{filename_effective}" -O "${imageUrl}")"
if [ $? -ne 0 ]; then
echo "Couldn't fetch the specified image URL to build the logo!"
else
if ! convert "${_imgfilename}" -resize 160x160 ../logo-overlay-small.png -gravity SouthEast -geometry +3+3 -composite logo.png; then
echo "Couldn't convert the specified URL to logo.png, maybe it's not an image?"
else
echo "Logo successfully generated"
fi
rm "${_imgfilename}"
fi
else
echo "Copying placeholder logo to package, consider replacing it"
cp ../logo-placeholder.png logo.png
fi