| (* is_main.pas: Pascal Scripts routines for Inno Setup Windows installer. |
| * ==================================================================== |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * ==================================================================== |
| *) |
| |
| // **************************************************************************** |
| // Global variables |
| var |
| // Required dlls |
| g_bMsVcpNotFound: Boolean; // Visual C++ 6.0 Runtimes |
| g_bShFolderNotFound: Boolean; // shfolder.dll |
| |
| // Apache |
| g_bHandleApache: Boolean; |
| g_sApachePath: String; |
| g_sApachePathBin: String; |
| g_sApachePathConf: String; |
| |
| |
| const |
| // Visual C++ 6.0 Runtime file related |
| FILE_MSVCPDLL = 'msvcp60.dll'; |
| URL_VCREDIST = 'http://support.microsoft.com/support/kb/articles/Q259/4/03.ASP'; |
| |
| // shfolder.dll related |
| FILE_SHFOLDERDLL = 'shfolder.dll'; |
| URL_SHFREDIST = 'http://download.microsoft.com/download/platformsdk/Redist/5.50.4027.300/W9XNT4/EN-US/shfinst.EXE'; |
| |
| // Apache |
| REG_KEY_APACHE_SERVICE = 'SYSTEM\CurrentControlSet\Services\Apache2'; |
| APACHE_VER_MIN = '{#= apache_ver_min}'; |
| |
| // Status codes for modules in httpd.conf |
| STATUS_NONE = 0; |
| STATUS_DISABLED = 1; |
| STATUS_ENABLED = 2; |
| |
| // **************************************************************************** |
| // Name: BackslashToSlash |
| // Purpose: Turning back slashes into slashes. This function is stolen |
| // shamelessly from the Inno help file. |
| // NOTE: For some unknown reason, this function has to stay here before |
| // other functions in order to avoid compile errors from the setup |
| // program. I don't not why, ..anyone? |
| function BackslashToSlash(const S: String): String; |
| var |
| I: Integer; |
| begin |
| Result := S; |
| I := 1; |
| while I <= Length(Result) do |
| begin |
| if Result[I] = '\' then |
| Result[I] := '/'; |
| // Go to the next character. But do not simply increment I by 1. |
| // Increment by CharLength() in case Result[I] is a double-byte character. |
| I := I + CharLength(Result, I); |
| end; |
| end; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // APACHE related stuff |
| |
| // **************************************************************************** |
| // Name: ApachePathParent |
| // Purpose: Returns the path of Apache parent folder. |
| function ApachePathParent(): String; |
| var |
| sApachePathParent: String; |
| iLengthString: Integer; |
| iPosK: Integer; |
| begin |
| |
| if RegKeyExists(HKLM, REG_KEY_APACHE_SERVICE) and UsingWinNT then |
| begin |
| // Set g_sApachePathBin |
| RegQueryStringValue(HKLM, REG_KEY_APACHE_SERVICE, |
| 'ImagePath', sApachePathParent); |
| |
| // Remove the run command and strip quotes away from g_sApachePathBin |
| iPosK := Pos('-k', sApachePathParent); |
| iLengthString := Length(sApachePathParent); |
| Delete(sApachePathParent, iLengthString - (iLengthString - iPosK), iPosK); |
| sApachePathParent := RemoveQuotes(sApachePathParent); |
| |
| // Strip basename twice so only the Apache parent path is left |
| sApachePathParent := ExtractFileDir(sApachePathParent); |
| sApachePathParent := ExtractFileDir(sApachePathParent); |
| end; |
| |
| // Function variables |
| Result := sApachePathParent; |
| end; |
| |
| // **************************************************************************** |
| // Name: ApacheTask |
| // Purpose: Decide if we should handle the Apache Server or not |
| function ApacheTask(): Boolean; |
| begin |
| Result:= UsingWinNT and not (ApachePathParent = ''); |
| end; |
| |
| // **************************************************************************** |
| // Name: ApacheBinFound |
| // Purpose: Checks if bin\apache.exe excists in Apache's parent folder. |
| // Returns True if Yes and False if No |
| function ApacheBinFound(): Boolean; |
| var |
| sApacheBinary: String; |
| begin |
| sApacheBinary := ApachePathParent() + '\bin\apache.exe'; |
| |
| if FileExists(sApacheBinary) then |
| begin |
| Result:= True; |
| end else begin |
| Result:= False; |
| end; |
| end; |
| |
| // **************************************************************************** |
| // Name: ApacheServiceStop |
| // Purpose: Stopping the Apache Service |
| procedure ApacheServiceStop(); |
| var |
| bRetVal: Boolean; |
| ErrorCode: Integer; |
| begin |
| bRetVal := Exec('cmd.exe', '/C apache -k stop', g_sApachePathBin, |
| SW_HIDE, ewWaitUntilTerminated, ErrorCode); |
| end; |
| |
| // **************************************************************************** |
| // Name: ApacheServiceStart |
| // Purpose: Starting the Apache Service |
| procedure ApacheServiceStart(); |
| var |
| bRetVal: Boolean; |
| ErrorCode: Integer; |
| begin |
| bRetVal := Exec('cmd.exe', '/C apache -k start', g_sApachePathBin, |
| SW_HIDE, ewWaitUntilTerminated, ErrorCode); |
| end; |
| |
| |
| // **************************************************************************** |
| // Name: ApacheModuleStatus |
| // Purpose: Identifying if a module is in a string and returning its status |
| Function ApacheModuleStatus(sLine: String): Integer; |
| var |
| iStatus: Integer; |
| iPosSharp, iPosModule: Integer; |
| begin |
| iStatus:= STATUS_NONE; |
| iPosSharp := Pos('#', sLine); |
| iPosModule := Pos('LoadModule ', sLine); |
| |
| if Pos('foo_module ', sLine) = 0 then |
| begin |
| if (iPosSharp > 0) and (iPosModule > iPosSharp) then |
| begin |
| iStatus := STATUS_DISABLED; |
| end else |
| begin |
| iStatus := STATUS_ENABLED; |
| end; |
| end; |
| |
| Result := iStatus; |
| end; |
| |
| // **************************************************************************** |
| // Name: ApacheModuleName |
| // Purpose: Extracting and returning a module name from a string |
| Function ApacheModuleName(sLine: String): String; |
| var |
| iPosModNameStart, iPosModNameEnd: Integer; |
| iCharNum: Integer; |
| sModuleName : String; |
| begin |
| iPosModNameStart := (Pos('modules/mod_', sLine) + 12); |
| iPosModNameEnd := (Pos('.so', sLine) - 1); |
| |
| sModuleName := ''; |
| iCharNum := iPosModNameStart; |
| |
| for iCharNum := iPosModNameStart to iPosModNameEnd do |
| begin |
| sModuleName := sModuleName + StrGet(sLine, iCharNum); |
| end; |
| |
| sModuleName := sModuleName + '_module'; |
| |
| Result := sModuleName; |
| end; |
| |
| // **************************************************************************** |
| // Name: ApacheConfFileEdit |
| // Purpose: Checking if the httpd.conf (Subversion related modules) file |
| // if needed. |
| procedure ApacheConfFileEdit(aHttpdConf: TArrayOfString; |
| iPosFileModules, iPosFileModulesPost, |
| iPosModDav, iStatusModDav, |
| iPosModDavSvn, iStatusModDavSvn, |
| iPosModAuthzSvn, iStatusModAuthzSvn: Integer); |
| var |
| sConfFileName, sTimeString: String; |
| sModuleDir, sLoadModDav, sLoadModDavSvn, sLoadModAuthzSvn: String; |
| |
| begin |
| sConfFileName := g_sApachePathConf + '\httpd.conf'; |
| sTimeString := GetDateTimeString('yyyy/mm/dd hh:mm:ss', '-', ':'); |
| |
| sModuleDir := ExpandConstant('{app}'); |
| sModuleDir := sModuleDir + '\bin'; |
| sModuleDir := BackslashToSlash(sModuleDir); |
| |
| sLoadModDav := 'LoadModule dav_module modules/mod_dav.so'; |
| sLoadModDavSvn := 'LoadModule dav_svn_module "' + sModuleDir + '/mod_dav_svn.so"'; |
| sLoadModAuthzSvn := 'LoadModule authz_svn_module "' + sModuleDir + '/mod_authz_svn.so"'; |
| |
| //Backup the current httpd.conf |
| FileCopy (sConfFileName, sConfFileName + '-svn-' + sTimeString + '.bak', False); |
| |
| // Add the modules if they're not there |
| if (iStatusModDav = STATUS_NONE) then |
| begin |
| if iPosModDav = 0 then |
| begin |
| iPosModDav := iPosFileModules + 10; |
| end; |
| |
| aHttpdConf[iPosModDav] := aHttpdConf[iPosModDav] + #13#10 + sLoadModDav; |
| end; |
| |
| if (iStatusModDavSvn = STATUS_NONE) then |
| aHttpdConf[iPosFileModulesPost -1] := aHttpdConf[iPosFileModulesPost -1] + #13#10 + |
| sLoadModDavSvn; |
| |
| if (iStatusModAuthzSvn = STATUS_NONE) then |
| aHttpdConf[iPosFileModulesPost -1] := aHttpdConf[iPosFileModulesPost -1] + #13#10 + |
| sLoadModAuthzSvn; |
| |
| // Enable modules if disabled ******************************** |
| if (iStatusModDav = STATUS_DISABLED) then |
| aHttpdConf[iPosModDav] := sLoadModDav; |
| |
| if (iStatusModDavSvn = STATUS_DISABLED) then |
| aHttpdConf[iPosModDavSvn] := sLoadModDavSvn; |
| |
| if (iStatusModAuthzSvn = STATUS_DISABLED) then |
| aHttpdConf[iPosModAuthzSvn] := sLoadModAuthzSvn; |
| |
| SaveStringsToFile(sConfFileName, aHttpdConf, False); |
| end; |
| |
| // **************************************************************************** |
| // Name: ApacheConfFileHandle |
| // Purpose: Checking if the httpd.conf (Subversion related modules) file should |
| // be edited and sets some data for further proccessing if needed. |
| procedure ApacheConfFileHandle(); |
| var |
| aHttpdConf : TArrayOfString; |
| |
| sConfFileName: String; |
| sCurrentLine: String; |
| |
| iLineNum, iArrayLen: Integer; |
| |
| iPosFileModules, iPosFileModulesPost : Integer; |
| iPosModDav, iPosModDavSvn, iPosModAuthzSvn: Integer; |
| iStatusModDav, iStatusModDavSvn, iStatusModAuthzSvn: Integer; |
| begin |
| iStatusModDav := STATUS_NONE; |
| iStatusModDavSvn := STATUS_NONE; |
| iStatusModAuthzSvn := STATUS_NONE; |
| |
| sConfFileName:= g_sApachePathConf + '\httpd.conf'; |
| |
| //Load the httpd.conf to the aHttpdConf array and init vars |
| LoadStringsFromFile(sConfFileName, aHttpdConf); |
| |
| iArrayLen := GetArrayLength(aHttpdConf)-1; |
| |
| // Check httpd.conf line by line |
| for iLineNum := 0 to iArrayLen do |
| begin |
| sCurrentLine := aHttpdConf[iLineNum]; |
| |
| // Get module status and file data with help of the modules |
| if (Pos('LoadModule ', sCurrentLine) > 0 ) then |
| begin |
| if (ApacheModuleStatus(sCurrentLine) > 0) then |
| begin |
| if iPosFileModules = 0 then |
| begin |
| iPosFileModules := iLineNum; |
| end; |
| |
| iPosFileModulesPost := iLineNum + 1; |
| end; |
| |
| //Decide placements and status of modules -------- |
| |
| // dav_module: If we (for some reason) don't find dav_module then |
| // we'll try to set the placement with help of cgi_module and make |
| // sure that we do it _before_ a dav_fs_module. |
| if ApacheModuleName(sCurrentLine) = 'dav_module' then |
| begin |
| iPosModDav := iLineNum; |
| iStatusModDav := ApacheModuleStatus(sCurrentLine); |
| end; |
| |
| if (ApacheModuleName(sCurrentLine) = 'cgi_module') and |
| ((iStatusModDav = STATUS_NONE) and (iPosModDav = 0)) then |
| iPosModDav := iLineNum + 1; |
| |
| if (ApacheModuleName(sCurrentLine) = 'dav_fs_module') and |
| (iStatusModDav = STATUS_NONE) then |
| iPosModDav := iLineNum - 1; |
| |
| // dav_svn_module: |
| if ApacheModuleName(sCurrentLine) = 'dav_svn_module' then |
| begin |
| iPosModDavSvn := iLineNum; |
| iStatusModDavSvn := ApacheModuleStatus(sCurrentLine); |
| end; |
| |
| // authz_svn_module: |
| if ApacheModuleName(sCurrentLine) = 'authz_svn_module' then |
| begin |
| iPosModAuthzSvn := iLineNum; |
| iStatusModAuthzSvn := ApacheModuleStatus(sCurrentLine); |
| end; |
| end; |
| end; |
| |
| // Edit httpd.conf if needed. |
| if (iStatusModDav + iStatusModDavSvn + iStatusModAuthzSvn) <> |
| (STATUS_ENABLED * 3) then |
| begin |
| ApacheConfFileEdit (aHttpdConf, |
| iPosFileModules, iPosFileModulesPost, |
| iPosModDav, iStatusModDav, |
| iPosModDavSvn, iStatusModDavSvn, |
| iPosModAuthzSvn, iStatusModAuthzSvn); |
| end; |
| end; |
| |
| // **************************************************************************** |
| // Name: ApacheVersion |
| // Purpose: Returns apache.exe's version with the last number stripped. |
| function ApacheVersion(): String; |
| var |
| sApacheVersion: String; |
| begin |
| GetVersionNumbersString(g_sApachePathBin + '\apache.exe' ,sApacheVersion); |
| Delete(sApacheVersion, 7, 2); |
| Result := sApacheVersion; |
| end; |
| |
| // **************************************************************************** |
| // Name: VerifyApache |
| // Purpose: Finding/Setting Apache paths and version info |
| procedure VerifyApache(); |
| var |
| sMsg: String; |
| sApacheVersion: String; |
| begin |
| g_bHandleApache := True; |
| |
| // Set/check the Apache paths |
| g_sApachePath := ApachePathParent; |
| |
| // apache.exe |
| if g_sApachePathBin = '' then |
| g_sApachePathBin := g_sApachePath + '\bin'; |
| |
| if not FileExists(g_sApachePathBin + '\apache.exe') then |
| begin |
| sMsg := 'Could not find ''apache.exe'' in the system. Please, browse' + |
| ' to the folder where the Apache binary is.'; |
| BrowseForFolder(sMsg , g_sApachePathBin, false); |
| end; |
| |
| // httpd.conf |
| if g_sApachePathConf = '' then |
| g_sApachePathConf := g_sApachePath + '\conf'; |
| |
| if not FileExists(g_sApachePathConf + '\httpd.conf') then |
| begin |
| sMsg := 'Could not find ''httpd.conf'' in the system. Please, browse' + |
| ' to the folder where configuration file is.'; |
| BrowseForFolder(sMsg, g_sApachePathConf, false); |
| end; |
| |
| // Check that we have the required Apache version and warn the user if |
| // needed |
| sApacheVersion := ApacheVersion; |
| |
| if CompareStr(sApacheVersion, APACHE_VER_MIN) < 0 then |
| begin |
| sMsg := |
| 'WARNING: Apache http server version ' + sApacheVersion + ' is detected and the' + #13#10 + |
| 'Subversion modules are built for the ' + APACHE_VER_MIN + ' version of the server.' + #13#10#13#10 + |
| 'You are strongly encouraged to quit this setup and upgrade your' + #13#10 + |
| 'apache server first, or go back to this setup''s ''Additional Tasks''' + #13#10 + |
| 'dialog box and uncheck the task of installing the Apache modules.' + #13#10; |
| |
| MsgBox(sMsg, mbError, MB_OK); |
| end; |
| end; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Misc. funtions used by the setup |
| |
| // **************************************************************************** |
| // Name: ComponentList |
| // Purpose: In use for UninsHs when the user wants to uninstall/repair the |
| // installation, |
| function ComponentList(Default: string):string; |
| begin |
| Result := WizardSelectedComponents(False); |
| end; |
| |
| // **************************************************************************** |
| // Name: ShFolderDllNotFound |
| // Purpose: Checks if FILE_SHFOLDERDLL does not exist. |
| // Returns True if missing and False if present. |
| function ShFolderDllNotFound(): Boolean; |
| var |
| sSysDir: String; |
| begin |
| sSysDir := ExpandConstant('{sys}'); |
| |
| if FileExists(sSysDir + '\' + FILE_SHFOLDERDLL) then |
| begin |
| g_bShFolderNotFound := False; |
| end else begin |
| g_bShFolderNotFound := True; |
| end; |
| |
| Result:= g_bShFolderNotFound; |
| end; |
| |
| // **************************************************************************** |
| // Name: SysFilesDownLoadInfo |
| // Purpose: Informs the user about missing Windows system file(s). |
| Procedure SysFilesDownLoadInfo; |
| var |
| sSysFiles: String; |
| sItThem: String; |
| sFile: string; |
| sDocument: string; |
| sMsg: String; |
| begin |
| sItThem := ' it'; |
| sFile := ' file'; |
| sDocument := ' document'; |
| |
| if (g_bMsVcpNotFound and g_bShFolderNotFound) then |
| begin |
| sSysfiles := FILE_MSVCPDLL + ' and ' + FILE_SHFOLDERDLL; |
| sItThem := ' them'; |
| sFile := ' files'; |
| sDocument := ' documents'; |
| end; |
| |
| if (g_bMsVcpNotFound and not g_bShFolderNotFound) then |
| sSysfiles := FILE_MSVCPDLL; |
| |
| if (g_bShFolderNotFound and not g_bMsVcpNotFound) then |
| sSysfiles := FILE_SHFOLDERDLL; |
| |
| sMsg :='The' + sFile + ' ' + sSysFiles + ' was not found in the system.' + #13#10#13#10 + |
| 'Please, go to the Subversion entry in the Start Menu after the installation and' + #13#10 + |
| 'read the ''Download and install''' + sDocument + ' for ' + sSysfiles + '.' + #13#10#13#10 + |
| 'Subversion will not work without this' + sFile + '.' + #13#10#13#10; |
| |
| MsgBox(sMsg, mbInformation, MB_OK); |
| end; |
| |
| // **************************************************************************** |
| // Name: VCRuntimeNotFound |
| // Purpose: Checks if FILE_MSVCPDLL does not exist. |
| // Returns True if missing and False if present. |
| function VCRuntimeNotFound(): Boolean; |
| var |
| sSysDir: String; |
| begin |
| sSysDir := ExpandConstant('{sys}'); |
| |
| if FileExists(sSysDir + '\' + FILE_MSVCPDLL) then |
| begin |
| g_bMsVcpNotFound := False; |
| end else begin |
| g_bMsVcpNotFound := True; |
| end; |
| |
| Result:= g_bMsVcpNotFound; |
| end; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Build in Inno Setup Pascal functions |
| // See Inno help file for usage about this functions. |
| |
| // **************************************************************************** |
| // Name: InitializeSetup |
| // Purpose: Called during Setup's initialization. |
| // Return False to abort Setup, True otherwise. |
| function InitializeSetup(): Boolean; |
| begin |
| //Initialize some global variables |
| g_bMsVcpNotFound := VCRuntimeNotFound; |
| g_bShFolderNotFound := ShFolderDllNotFound; |
| g_bHandleApache:= False; |
| Result := True; |
| end; |
| |
| // **************************************************************************** |
| // Name: CurPageChanged |
| // Purpose: Called after a new wizard page (specified by CurPageID) is shown. |
| procedure CurPageChanged(CurStep: Integer); |
| begin |
| case CurStep of |
| wpReady: // Event after selected tasks |
| if IsTaskSelected('apachehandler') then |
| VerifyApache; |
| wpInstalling: // Event before setup is copying destination files |
| if g_bHandleApache then |
| begin |
| ApacheServiceStop; |
| //ApacheCopyModules; |
| end; |
| end; |
| end; |
| |
| // **************************************************************************** |
| // Name: CurStepChanged |
| // Purpose: Event function to perform pre- and post-install tasks. |
| procedure CurStepChanged(CurStep: TSetupStep); |
| begin |
| if (CurStep = ssPostInstall) and g_bHandleApache then |
| begin; |
| ApacheConfFileHandle; |
| ApacheServiceStart; |
| end; |
| end; |
| |
| // **************************************************************************** |
| // Name: NextButtonClick |
| // Purpose: Called when the user clicks the Next button. |
| // If you return True, the wizard will move to the next page; if you |
| // return False, it will remain on the current page (specified by |
| // CurPageID). |
| function NextButtonClick(CurPage: Integer): Boolean; |
| begin |
| if (CurPage = wpSelectComponents) then |
| if (g_bMsVcpNotFound or g_bShFolderNotFound) then |
| SysFilesDownLoadInfo(); |
| |
| Result := True; |
| end; |
| |
| // **************************************************************************** |
| // Name: ShouldSkipPage |
| // Purpose: Event function to determine whether or not a particular page |
| // (specified by PageID) should be shown at all. |
| function ShouldSkipPage(CurPage: Integer): Boolean; |
| begin |
| // START In use by UninsHs |
| if Pos('/SP-', UpperCase(GetCmdTail)) > 0 then |
| case CurPage of |
| wpWelcome, wpLicense, wpPassword, wpInfoBefore, wpUserInfo, |
| wpSelectDir, wpSelectProgramGroup, wpInfoAfter: |
| Result := True; |
| end; |
| // END In use by UninsHs |
| end; |