(* is_main.pas: Pascal Scripts routines for Inno Setup Windows installer.
* ====================================================================
* Copyright (c) 2000-2005 CollabNet. All rights reserved.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://subversion.tigris.org/license-1.html.
* If newer versions of this license are posted there, you may use a
* newer version instead, at your option.
*
* This software consists of voluntary contributions made by many
* individuals. For exact contribution history, see the revision
* history and logs, available at http://subversion.tigris.org/.
* ====================================================================
*)
// ****************************************************************************
// 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 it's 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;
syntax highlighted by Code2HTML, v. 0.9.1