; NSIS Modern User Interface ; Ejabberd installation script ;-------------------------------- ;Include Modern UI !include "MUI.nsh" !include "ejabberd.nsh" ; All release specific parameters come from this ;-------------------------------- ;General ;Name and file !define PRODUCT "Ejabberd" Name ${PRODUCT} OutFile "${OUTFILEDIR}\${PRODUCT}-${VERSION}.exe" ShowInstDetails show ShowUninstDetails show !define MUI_ICON "ejabberd.ico" !define MUI_UNICON "ejabberd.ico" ;-------------------------------- ;Configuration SetCompressor lzma ;-------------------------------- ;Reserve Files !ifdef HACKED_INSTALLOPTIONS ReserveFile "CheckUserH.ini" !else ReserveFile "CheckUser.ini" !endif ReserveFile "CheckReqs.ini" !insertmacro MUI_RESERVEFILE_INSTALLOPTIONS ;-------------------------------- ;Variables Var MUI_TEMP Var STARTMENU_FOLDER Var ADMIN Var ERLANG_PATH Var ERLANG_VERSION Var REQUIRED_ERLANG_VERSION Var ERLSRV ;---------------------------------------------------------- ;.onInit uses UserInfo plugin, so it's as high as possible Function .onInit StrCpy $REQUIRED_ERLANG_VERSION "5.3" ;Default installation folder StrCpy $INSTDIR "$PROGRAMFILES\${PRODUCT}" ;Get installation folder from registry if available ClearErrors ReadRegStr $0 HKLM "SOFTWARE\${PRODUCT}" "" IfErrors 0 copydir ReadRegStr $0 HKCU "SOFTWARE\${PRODUCT}" "" IfErrors skipdir copydir: StrCpy $INSTDIR "$0" skipdir: ;Extract InstallOptions INI files !ifdef HACKED_INSTALLOPTIONS !insertmacro MUI_INSTALLOPTIONS_EXTRACT "CheckUserH.ini" !else !insertmacro MUI_INSTALLOPTIONS_EXTRACT "CheckUser.ini" !endif !insertmacro MUI_INSTALLOPTIONS_EXTRACT "CheckReqs.ini" ClearErrors UserInfo::GetName IfErrors admin Pop $0 UserInfo::GetAccountType Pop $1 StrCmp $1 "Admin" admin user admin: StrCpy $ADMIN 1 Goto skip user: StrCpy $ADMIN 0 skip: FunctionEnd ;-------------------------------- ;Interface Settings !define MUI_ABORTWARNING ;-------------------------------- ;Pages !insertmacro MUI_PAGE_WELCOME Page custom CheckUser LeaveCheckUser !insertmacro MUI_PAGE_LICENSE "..\..\COPYING" Page custom CheckReqs LeaveCheckReqs ;!insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_STARTMENU ${PRODUCT} $STARTMENU_FOLDER !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_UNPAGE_WELCOME !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES ;-------------------------------- ;Languages !insertmacro MUI_LANGUAGE "English" ;-------------------------------- ;Language Strings ;Description LangString DESC_SecEjabberd ${LANG_ENGLISH} "Erlang jabber server." ;-------------------------------- ;Installer Sections Section "Ejabberd" SecEjabberd SectionIn 1 RO SetOutPath "$INSTDIR" File /r "${TESTDIR}\doc" File /r "${TESTDIR}\ebin" File /r "${TESTDIR}\priv" File /r "${TESTDIR}\win32" File "${TESTDIR}\libeay32.dll" File "${TESTDIR}\ssleay32.dll" SetOverwrite off File "${TESTDIR}\ejabberd.cfg" SetOverwrite on ;File /r "${TESTDIR}\src" CreateDirectory "$INSTDIR\log" ;The startmenu stuff !insertmacro MUI_STARTMENU_WRITE_BEGIN ${PRODUCT} ;Create shortcuts StrCpy $0 "$SMPROGRAMS\$STARTMENU_FOLDER" CreateDirectory "$0" CreateShortCut "$0\Start Ejabberd.lnk" "$ERLANG_PATH\bin\werl.exe" \ '-sname ejabberd -pa ebin -pa win32/$ERLANG_VERSION \ -env EJABBERD_SO_PATH priv/lib -env EJABBERD_MSGS_PATH msgs \ -env EJABBERD_LOG_PATH log/ejabberd.log \ -s ejabberd -ejabberd config \"ejabberd.cfg\" -mnesia dir \"spool\"' \ $INSTDIR\win32\ejabberd.ico CreateShortCut "$0\Edit Config.lnk" "%SystemRoot%\system32\notepad.exe" \ "$INSTDIR\ejabberd.cfg" CreateShortCut "$0\Read Docs.lnk" "$INSTDIR\doc\guide.html" CreateShortCut "$0\Uninstall.lnk" "$INSTDIR\Uninstall.exe" !insertmacro MUI_STARTMENU_WRITE_END ;Create Windows service StrCmp $ADMIN 1 0 skipservice StrCpy $ERLSRV "" Push $ERLANG_PATH Push erlsrv.exe GetFunctionAddress $0 FFCallback Push $0 Call FindFiles StrCmp $ERLSRV "" skipservice nsExec::Exec '"$ERLSRV" list ejabberd' Pop $0 StrCmp $0 "error" skipservice StrCmp $0 "0" 0 installsrv nsExec::ExecToLog '"$ERLSRV" remove ejabberd' Pop $0 installsrv: nsExec::ExecToLog '"$ERLSRV" add ejabberd -stopaction "init:stop()." \ -onfail reboot -workdir "$INSTDIR" \ -args "-s ejabberd -pa ebin -pa win32/$ERLANG_VERSION \ -ejabberd config \\\"ejabberd.cfg\\\" \ -env EJABBERD_SO_PATH priv/lib -env EJABBERD_MSGS_PATH msgs \ -env EJABBERD_LOG_PATH log/ejabberd.log \ -sasl sasl_error_logger {file,\\\"log/sasl.log\\\"} \ -mnesia dir \\\"spool\\\"" -d' Pop $0 ;nsExec::ExecToLog '"$ERLSRV" disable ejabberd' ;Pop $0 skipservice: ;Create uninstaller WriteUninstaller "$INSTDIR\Uninstall.exe" StrCpy $1 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT}" StrCmp $ADMIN 1 admin2 WriteRegStr HKCU "Software\${PRODUCT}" "" "$INSTDIR" WriteRegStr HKCU "$1" "DisplayName" "${PRODUCT} ${VERSION}" WriteRegStr HKCU "$1" "UninstallString" "$INSTDIR\Uninstall.exe" WriteRegDWORD HKCU "$1" "NoModify" 1 WriteRegDWORD HKCU "$1" "NoRepair" 1 Goto done2 admin2: WriteRegStr HKLM "Software\${PRODUCT}" "" "$INSTDIR" WriteRegStr HKLM "Software\${PRODUCT}" "Erlsrv" "$ERLSRV" WriteRegStr HKLM "$1" "DisplayName" "${PRODUCT} ${VERSION}" WriteRegStr HKLM "$1" "UninstallString" "$INSTDIR\Uninstall.exe" WriteRegDWORD HKLM "$1" "NoModify" 1 WriteRegDWORD HKLM "$1" "NoRepair" 1 done2: SectionEnd ; SecEjabberd Function FFCallback Exch $0 StrCpy $ERLSRV $0 Pop $0 Push "stop" FunctionEnd ;-------------------------------- ;Descriptions !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN !insertmacro MUI_DESCRIPTION_TEXT ${SecEjabberd} $(DESC_SecEjabberd) !insertmacro MUI_FUNCTION_DESCRIPTION_END ;-------------------------------- ;Uninstaller Section Section "Uninstall" ClearErrors UserInfo::GetName IfErrors admin Pop $0 UserInfo::GetAccountType Pop $1 StrCmp $1 "Admin" admin StrCpy $ADMIN 0 Goto skipservice admin: StrCpy $ADMIN 1 ReadRegStr $ERLSRV HKLM "Software\${PRODUCT}" "Erlsrv" nsExec::Exec '"$ERLSRV" list ejabberd' Pop $0 StrCmp $0 "error" skipservice StrCmp $0 "0" 0 skipservice nsExec::ExecToLog '"$ERLSRV" remove ejabberd' Pop $0 skipservice: RMDir /r "$INSTDIR\doc" RMDir /r "$INSTDIR\ebin" RMDir /r "$INSTDIR\priv" RMDir /r "$INSTDIR\win32" ;RMDir /r "$INSTDIR\src" RMDir /r "$INSTDIR\log" Delete "$INSTDIR\libeay32.dll" Delete "$INSTDIR\ssleay32.dll" Delete "$INSTDIR\Uninstall.exe" RMDir "$INSTDIR" !insertmacro MUI_STARTMENU_GETFOLDER ${PRODUCT} $MUI_TEMP Delete "$SMPROGRAMS\$MUI_TEMP\Start Ejabberd.lnk" Delete "$SMPROGRAMS\$MUI_TEMP\Edit Config.lnk" Delete "$SMPROGRAMS\$MUI_TEMP\Read Docs.lnk" Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" ;Delete empty start menu parent diretories StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" startMenuDeleteLoop: RMDir $MUI_TEMP GetFullPathName $MUI_TEMP "$MUI_TEMP\.." IfErrors startMenuDeleteLoopDone StrCmp $MUI_TEMP $SMPROGRAMS startMenuDeleteLoopDone startMenuDeleteLoop startMenuDeleteLoopDone: StrCpy $1 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT}" StrCmp $ADMIN 1 admin1 DeleteRegKey HKCU "Software\${PRODUCT}" DeleteRegKey HKCU $1 Goto done admin1: DeleteRegKey HKLM "Software\${PRODUCT}" DeleteRegKey HKLM $1 done: SectionEnd LangString TEXT_CU_TITLE ${LANG_ENGLISH} "Checking User Privileges" LangString TEXT_CU_SUBTITLE ${LANG_ENGLISH} "Checking user privileged required to install Ejabberd." Function CheckUser StrCmp $ADMIN 1 0 showpage Abort showpage: !insertmacro MUI_HEADER_TEXT $(TEXT_CU_TITLE) $(TEXT_CU_SUBTITLE) !ifdef HACKED_INSTALLOPTIONS !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "CheckUserH.ini" !insertmacro MUI_INSTALLOPTIONS_READ $0 "CheckUserH.ini" "Field 2" "State" GetDlgItem $1 $HWNDPARENT 1 EnableWindow $1 $0 !else !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "CheckUser.ini" !endif !insertmacro MUI_INSTALLOPTIONS_SHOW FunctionEnd Function LeaveCheckUser !ifdef HACKED_INSTALLOPTIONS !insertmacro MUI_INSTALLOPTIONS_READ $0 "CheckUserH.ini" "Settings" "State" StrCmp $0 0 validate ;Next button? StrCmp $0 2 checkbox ;checkbox? Abort ;Return to the page checkbox: !insertmacro MUI_INSTALLOPTIONS_READ $0 "CheckUserH.ini" "Field 2" "State" GetDlgItem $1 $HWNDPARENT 1 EnableWindow $1 $0 Abort validate: !endif FunctionEnd LangString TEXT_CR_TITLE ${LANG_ENGLISH} "Unsatisfied Requirements" LangString TEXT_CR_SUBTITLE ${LANG_ENGLISH} "Unsatisfied Ejabberd requirements found." Function CheckReqs Push "HKLM" Call FindErlang Pop $ERLANG_PATH Pop $ERLANG_VERSION StrCmp $ERLANG_PATH "" 0 abort Push "HKCU" Call FindErlang Pop $ERLANG_PATH Pop $ERLANG_VERSION StrCmp $ERLANG_PATH "" 0 abort !insertmacro MUI_HEADER_TEXT $(TEXT_CR_TITLE) $(TEXT_CR_SUBTITLE) !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "CheckReqs.ini" GetDlgItem $R0 $HWNDPARENT 1 EnableWindow $R0 0 !insertmacro MUI_INSTALLOPTIONS_SHOW abort: Abort FunctionEnd Function LeaveCheckReqs Abort FunctionEnd Function FindErlang Exch $R0 Push $R1 Push $R2 Push $R3 Push $R4 Push $R5 StrCpy $R1 0 StrCpy $R2 "SOFTWARE\Ericsson\Erlang" loop: StrCmp $R0 HKLM h1 EnumRegKey $R3 HKCU $R2 $R1 Goto l1 h1: EnumRegKey $R3 HKLM $R2 $R1 l1: IntOp $R1 $R1 + 1 StrCmp $R3 "" endloop ClearErrors StrCmp $R0 HKLM h2 ReadRegStr $R4 HKCU "$R2\$R3" "" Goto l2 h2: ReadRegStr $R4 HKLM "$R2\$R3" "" l2: IfFileExists "$R4\bin\erl.exe" 0 loop Push $REQUIRED_ERLANG_VERSION Push $R3 Call CompareVersions Pop $R5 StrCmp $R5 1 get Goto loop endloop: StrCpy $R4 "" get: StrCpy $R0 $R4 StrCpy $R1 $R3 Pop $R5 Pop $R4 Pop $R3 Pop $R2 Exch $R1 Exch Exch $R0 FunctionEnd ;---------------------------------------------------------------------- ; CompareVersions ; input: ; top of stack = existing version ; top of stack-1 = needed version ; output: ; top of stack = 1 if current version => neded version, else 0 ; version is a string in format "xx.xx.xx.xx" (number of interger sections ; can be different in needed and existing versions) Function CompareVersions ; stack: existing ver | needed ver Exch $R0 Exch Exch $R1 ; stack: $R1|$R0 Push $R1 Push $R0 ; stack: e|n|$R1|$R0 ClearErrors loop: IfErrors VersionNotFound Strcmp $R0 "" VersionTestEnd Call ParseVersion Pop $R0 Exch Call ParseVersion Pop $R1 Exch IntCmp $R1 $R0 +1 VersionOk VersionNotFound Pop $R0 Push $R0 goto loop VersionTestEnd: Pop $R0 Pop $R1 Push $R1 Push $R0 StrCmp $R0 $R1 VersionOk VersionNotFound VersionNotFound: StrCpy $R0 "0" Goto end VersionOk: StrCpy $R0 "1" end: ; stack: e|n|$R1|$R0 Exch $R0 Pop $R0 Exch $R0 ; stack: res|$R1|$R0 Exch ; stack: $R1|res|$R0 Pop $R1 ; stack: res|$R0 Exch Pop $R0 ; stack: res FunctionEnd ;----------------------------------------------------------------------- ; ParseVersion ; input: ; top of stack = version string ("xx.xx.xx.xx") ; output: ; top of stack = first number in version ("xx") ; top of stack-1 = rest of the version string ("xx.xx.xx") Function ParseVersion Exch $R1 ; version Push $R2 Push $R3 StrCpy $R2 1 loop: StrCpy $R3 $R1 1 $R2 StrCmp $R3 "." loopend StrLen $R3 $R1 IntCmp $R3 $R2 loopend loopend IntOp $R2 $R2 + 1 Goto loop loopend: Push $R1 StrCpy $R1 $R1 $R2 Exch $R1 StrLen $R3 $R1 IntOp $R3 $R3 - $R2 IntOp $R2 $R2 + 1 StrCpy $R1 $R1 $R3 $R2 Push $R1 Exch 2 Pop $R3 Exch 2 Pop $R2 Exch 2 Pop $R1 FunctionEnd Function FindFiles Exch $R5 # callback function Exch Exch $R4 # file name Exch 2 Exch $R0 # directory Push $R1 Push $R2 Push $R3 Push $R6 Push $R0 # first dir to search StrCpy $R3 1 nextDir: Pop $R0 IntOp $R3 $R3 - 1 ClearErrors FindFirst $R1 $R2 "$R0\*.*" nextFile: StrCmp $R2 "." gotoNextFile StrCmp $R2 ".." gotoNextFile StrCmp $R2 $R4 0 isDir Push "$R0\$R2" Call $R5 Pop $R6 StrCmp $R6 "stop" 0 isDir loop: StrCmp $R3 0 done Pop $R0 IntOp $R3 $R3 - 1 Goto loop isDir: IfFileExists "$R0\$R2\*.*" 0 gotoNextFile IntOp $R3 $R3 + 1 Push "$R0\$R2" gotoNextFile: FindNext $R1 $R2 IfErrors 0 nextFile done: FindClose $R1 StrCmp $R3 0 0 nextDir Pop $R6 Pop $R3 Pop $R2 Pop $R1 Pop $R0 Pop $R5 Pop $R4 FunctionEnd