1493 lines
50 KiB
Perl
1493 lines
50 KiB
Perl
# --
|
|
# Copyright (C) 2001-2019 OTRS AG, https://otrs.com/
|
|
# --
|
|
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
|
|
# the enclosed file COPYING for license information (GPL). If you
|
|
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
|
|
# --
|
|
|
|
package Kernel::Modules::Installer;
|
|
## nofilter(TidyAll::Plugin::OTRS::Perl::DBObject)
|
|
## nofilter(TidyAll::Plugin::OTRS::Perl::Print)
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use DBI;
|
|
use Net::Domain qw(hostfqdn);
|
|
use Kernel::Language qw(Translatable);
|
|
|
|
our $ObjectManagerDisabled = 1;
|
|
|
|
use vars qw(%INC);
|
|
|
|
sub new {
|
|
my ( $Type, %Param ) = @_;
|
|
|
|
# Allocate new hash for object.
|
|
my $Self = {%Param};
|
|
bless( $Self, $Type );
|
|
|
|
return $Self;
|
|
}
|
|
|
|
sub Run {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
|
|
if ( $Kernel::OM->Get('Kernel::Config')->Get('SecureMode') ) {
|
|
$LayoutObject->FatalError(
|
|
Message => Translatable('SecureMode active!'),
|
|
Comment => Translatable(
|
|
'If you want to re-run the Installer, disable the SecureMode in the SysConfig.'
|
|
),
|
|
);
|
|
}
|
|
|
|
# Check environment directories.
|
|
$Self->{Path} = $ConfigObject->Get('Home');
|
|
if ( !-d $Self->{Path} ) {
|
|
$LayoutObject->FatalError(
|
|
Message => $LayoutObject->{LanguageObject}->Translate( 'Directory "%s" doesn\'t exist!', $Self->{Path} ),
|
|
Comment => Translatable('Configure "Home" in Kernel/Config.pm first!'),
|
|
);
|
|
}
|
|
if ( !-f "$Self->{Path}/Kernel/Config.pm" ) {
|
|
$LayoutObject->FatalError(
|
|
Message =>
|
|
$LayoutObject->{LanguageObject}->Translate( 'File "%s/Kernel/Config.pm" not found!', $Self->{Path} ),
|
|
Comment => Translatable('Please contact the administrator.'),
|
|
);
|
|
}
|
|
|
|
# Check/get SQL schema directory
|
|
my $DirOfSQLFiles = $Self->{Path} . '/scripts/database';
|
|
if ( !-d $DirOfSQLFiles ) {
|
|
$LayoutObject->FatalError(
|
|
Message => $LayoutObject->{LanguageObject}->Translate( 'Directory "%s" not found!', $DirOfSQLFiles ),
|
|
Comment => Translatable('Please contact the administrator.'),
|
|
);
|
|
}
|
|
|
|
my $MainObject = $Kernel::OM->Get('Kernel::System::Main');
|
|
|
|
# TODO: This seams to be deprecated now
|
|
# Read installer.json if it exists.
|
|
# It contains options set by Windows Installer
|
|
if ( -f "$Self->{Path}/var/tmp/installer.json" ) {
|
|
my $JSONString = $MainObject->FileRead(
|
|
Location => "$Self->{Path}/var/tmp/installer.json",
|
|
);
|
|
$Self->{Options} = $Kernel::OM->Get('Kernel::System::JSON')->Decode(
|
|
Data => $$JSONString,
|
|
);
|
|
}
|
|
|
|
# Check if License option needs to be skipped.
|
|
if ( $Self->{Subaction} eq 'License' && $Self->{Options}->{SkipLicense} ) {
|
|
$Self->{Subaction} = 'Start';
|
|
}
|
|
|
|
# Check if Database option needs to be skipped.
|
|
if ( $Self->{Subaction} eq 'Start' && $Self->{Options}->{DBType} ) {
|
|
$Self->{Subaction} = 'DBCreate';
|
|
}
|
|
|
|
$Self->{Subaction} = 'Intro' if !$Self->{Subaction};
|
|
|
|
# Build steps.
|
|
my @Steps = qw(License Database General Finish);
|
|
my $StepCounter;
|
|
|
|
# TODO: This seams to be deprecated now
|
|
# No license step needed if defined in .json file.
|
|
shift @Steps if $Self->{Options}->{SkipLicense};
|
|
|
|
# Build header - but only if we're not in AJAX mode.
|
|
if ( $Self->{Subaction} ne 'CheckRequirements' ) {
|
|
$LayoutObject->Block(
|
|
Name => 'Steps',
|
|
Data => {
|
|
Steps => scalar @Steps,
|
|
},
|
|
);
|
|
|
|
# Mapping of sub-actions to steps.
|
|
my %Steps = (
|
|
Intro => 'Intro',
|
|
License => 'License',
|
|
Start => 'Database',
|
|
DB => 'Database',
|
|
DBCreate => 'Database',
|
|
ConfigureMail => 'General',
|
|
System => 'General',
|
|
Finish => 'Finish',
|
|
);
|
|
|
|
# On the intro screen no steps should be highlighted.
|
|
my $Highlight = ( $Self->{Subaction} eq 'Intro' ) ? '' : 'Highlighted NoLink';
|
|
|
|
my $Counter;
|
|
|
|
for my $Step (@Steps) {
|
|
$Counter++;
|
|
|
|
# Is the current step active?
|
|
my $Active = ( $Steps{ $Self->{Subaction} } eq $Step ) ? 'Active' : '';
|
|
$LayoutObject->Block(
|
|
Name => 'Step' . $Step,
|
|
Data => {
|
|
Step => $Counter,
|
|
Highlight => $Highlight,
|
|
Active => $Active,
|
|
},
|
|
);
|
|
|
|
# If this is the actual step.
|
|
if ( $Steps{ $Self->{Subaction} } eq $Step ) {
|
|
|
|
# No more highlights from now on.
|
|
$Highlight = '';
|
|
|
|
# Step calculation: 2/5 etc.
|
|
$StepCounter = $Counter . "/" . scalar @Steps;
|
|
}
|
|
}
|
|
}
|
|
|
|
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
|
|
|
|
# Print intro form.
|
|
my $Title = $LayoutObject->{LanguageObject}->Translate('Install OTRS');
|
|
if ( $Self->{Subaction} eq 'Intro' ) {
|
|
my $Output =
|
|
$LayoutObject->Header(
|
|
Title => "$Title - "
|
|
. $LayoutObject->{LanguageObject}->Translate('Intro')
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'Intro',
|
|
Data => {}
|
|
);
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => 'Installer',
|
|
Data => {},
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
|
|
# Print license from.
|
|
elsif ( $Self->{Subaction} eq 'License' ) {
|
|
my $Output =
|
|
$LayoutObject->Header(
|
|
Title => "$Title - "
|
|
. $LayoutObject->{LanguageObject}->Translate('License')
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'License',
|
|
Data => {
|
|
Item => Translatable('License'),
|
|
Step => $StepCounter,
|
|
},
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'LicenseText',
|
|
Data => {},
|
|
);
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => 'Installer',
|
|
Data => {},
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
|
|
# Database selection screen.
|
|
elsif ( $Self->{Subaction} eq 'Start' ) {
|
|
if ( !-w "$Self->{Path}/Kernel/Config.pm" ) {
|
|
my $Output =
|
|
$LayoutObject->Header(
|
|
Title => "$Title - "
|
|
. $LayoutObject->{LanguageObject}->Translate('Error')
|
|
);
|
|
$Output .= $LayoutObject->Warning(
|
|
Message => Translatable('Kernel/Config.pm isn\'t writable!'),
|
|
Comment => Translatable(
|
|
'If you want to use the installer, set the Kernel/Config.pm writable for the webserver user!'
|
|
),
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
|
|
my %Databases = (
|
|
mysql => "MySQL",
|
|
postgresql => "PostgreSQL",
|
|
oracle => "Oracle",
|
|
);
|
|
|
|
# Build the select field for the InstallerDBStart.tt.
|
|
$Param{SelectDBType} = $LayoutObject->BuildSelection(
|
|
Data => \%Databases,
|
|
Name => 'DBType',
|
|
Class => 'Modernize',
|
|
Size => scalar keys %Databases,
|
|
SelectedID => 'mysql',
|
|
);
|
|
|
|
my $Output =
|
|
$LayoutObject->Header(
|
|
Title => "$Title - "
|
|
. $LayoutObject->{LanguageObject}->Translate('Database Selection')
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseStart',
|
|
Data => {
|
|
Item => Translatable('Database Selection'),
|
|
Step => $StepCounter,
|
|
SelectDBType => $Param{SelectDBType},
|
|
},
|
|
);
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => 'Installer',
|
|
Data => {},
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
|
|
# Check different requirements (AJAX).
|
|
elsif ( $Self->{Subaction} eq 'CheckRequirements' ) {
|
|
my $CheckMode = $ParamObject->GetParam( Param => 'CheckMode' );
|
|
my %Result;
|
|
|
|
# Check DB requirements.
|
|
if ( $CheckMode eq 'DB' ) {
|
|
my %DBCredentials;
|
|
for my $Param (
|
|
qw(DBUser DBPassword DBHost DBType DBPort DBSID DBName InstallType OTRSDBUser OTRSDBPassword)
|
|
)
|
|
{
|
|
$DBCredentials{$Param} = $ParamObject->GetParam( Param => $Param ) || '';
|
|
}
|
|
|
|
%Result = $Self->CheckDBRequirements(
|
|
%DBCredentials,
|
|
);
|
|
}
|
|
|
|
# Check mail configuration.
|
|
elsif ( $CheckMode eq 'Mail' ) {
|
|
%Result = $Self->CheckMailConfiguration();
|
|
}
|
|
|
|
# No adequate check method found.
|
|
else {
|
|
%Result = (
|
|
Successful => 0,
|
|
Message => Translatable('Unknown Check!'),
|
|
Comment => $LayoutObject->{LanguageObject}->Translate( 'The check "%s" doesn\'t exist!', $CheckMode ),
|
|
);
|
|
}
|
|
|
|
# Return JSON-String because of AJAX-Mode.
|
|
my $OutputJSON = $LayoutObject->JSONEncode( Data => \%Result );
|
|
|
|
return $LayoutObject->Attachment(
|
|
ContentType => 'application/json; charset='
|
|
. $LayoutObject->{Charset},
|
|
Content => $OutputJSON,
|
|
Type => 'inline',
|
|
NoCache => 1,
|
|
);
|
|
}
|
|
|
|
elsif ( $Self->{Subaction} eq 'DB' ) {
|
|
|
|
my $DBType = $ParamObject->GetParam( Param => 'DBType' );
|
|
my $DBInstallType = $ParamObject->GetParam( Param => 'DBInstallType' );
|
|
|
|
# Use MainObject to generate a password.
|
|
my $GeneratedPassword = $MainObject->GenerateRandomString();
|
|
|
|
if ( $DBType eq 'mysql' ) {
|
|
my $PasswordExplanation = $DBInstallType eq 'CreateDB'
|
|
? $LayoutObject->{LanguageObject}->Translate(
|
|
'If you have set a root password for your database, it must be entered here. If not, leave this field empty.',
|
|
)
|
|
: $LayoutObject->{LanguageObject}->Translate('Enter the password for the database user.');
|
|
my $Output =
|
|
$LayoutObject->Header(
|
|
Title => "$Title - "
|
|
. $LayoutObject->{LanguageObject}->Translate( 'Database %s', 'MySQL' )
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseMySQL',
|
|
Data => {
|
|
Item => Translatable('Configure MySQL'),
|
|
Step => $StepCounter,
|
|
InstallType => $DBInstallType,
|
|
DefaultDBUser => $DBInstallType eq 'CreateDB' ? 'root' : 'otrs',
|
|
PasswordExplanation => $PasswordExplanation,
|
|
},
|
|
);
|
|
if ( $DBInstallType eq 'CreateDB' ) {
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseMySQLCreate',
|
|
Data => {
|
|
Password => $GeneratedPassword,
|
|
},
|
|
);
|
|
}
|
|
else {
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseMySQLUseExisting',
|
|
);
|
|
}
|
|
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => 'Installer',
|
|
Data => {
|
|
Item => Translatable('Configure MySQL'),
|
|
Step => $StepCounter,
|
|
},
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
elsif ( $DBType eq 'postgresql' ) {
|
|
my $PasswordExplanation = $DBInstallType eq 'CreateDB'
|
|
? $LayoutObject->{LanguageObject}->Translate('Enter the password for the administrative database user.')
|
|
: $LayoutObject->{LanguageObject}->Translate('Enter the password for the database user.');
|
|
my $Output =
|
|
$LayoutObject->Header(
|
|
Title => "$Title - "
|
|
. $LayoutObject->{LanguageObject}->Translate( 'Database %s', 'PostgreSQL' )
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'DatabasePostgreSQL',
|
|
Data => {
|
|
Item => Translatable('Database'),
|
|
Step => $StepCounter,
|
|
InstallType => $DBInstallType,
|
|
DefaultDBUser => $DBInstallType eq 'CreateDB' ? 'postgres' : 'otrs',
|
|
},
|
|
);
|
|
if ( $DBInstallType eq 'CreateDB' ) {
|
|
$LayoutObject->Block(
|
|
Name => 'DatabasePostgreSQLCreate',
|
|
Data => {
|
|
Password => $GeneratedPassword,
|
|
},
|
|
);
|
|
}
|
|
else {
|
|
$LayoutObject->Block(
|
|
Name => 'DatabasePostgreSQLUseExisting',
|
|
);
|
|
}
|
|
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => 'Installer',
|
|
Data => {
|
|
Item => Translatable('Configure PostgreSQL'),
|
|
Step => $StepCounter,
|
|
},
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
elsif ( $DBType eq 'oracle' ) {
|
|
my $Output =
|
|
$LayoutObject->Header(
|
|
Title => "$Title - "
|
|
. $LayoutObject->{LanguageObject}->Translate( 'Database %s', 'Oracle' )
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseOracle',
|
|
Data => {
|
|
Item => Translatable('Database'),
|
|
Step => $StepCounter,
|
|
},
|
|
);
|
|
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => 'Installer',
|
|
Data => {
|
|
Item => Translatable('Configure Oracle'),
|
|
Step => $StepCounter,
|
|
},
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
else {
|
|
$LayoutObject->FatalError(
|
|
Message => $LayoutObject->{LanguageObject}->Translate( 'Unknown database type "%s".', $DBType ),
|
|
Comment => Translatable('Please go back.'),
|
|
);
|
|
}
|
|
}
|
|
|
|
# Do database settings.
|
|
elsif ( $Self->{Subaction} eq 'DBCreate' ) {
|
|
|
|
my %DBCredentials;
|
|
for my $Param (
|
|
qw(DBUser DBPassword DBHost DBType DBName DBSID DBPort InstallType OTRSDBUser OTRSDBPassword)
|
|
)
|
|
{
|
|
$DBCredentials{$Param} = $ParamObject->GetParam( Param => $Param ) || '';
|
|
}
|
|
%DBCredentials = %{ $Self->{Options} } if $Self->{Options}->{DBType};
|
|
|
|
# Get and check params and connect to DB.
|
|
my %Result = $Self->ConnectToDB(%DBCredentials);
|
|
|
|
my %DB;
|
|
my $DBH;
|
|
if ( ref $Result{DB} ne 'HASH' || !$Result{DBH} ) {
|
|
$LayoutObject->FatalError(
|
|
Message => $Result{Message},
|
|
Comment => $Result{Comment},
|
|
);
|
|
}
|
|
else {
|
|
%DB = %{ $Result{DB} };
|
|
$DBH = $Result{DBH};
|
|
}
|
|
|
|
my $Output = $LayoutObject->Header(
|
|
Title => $Title . '-'
|
|
. $LayoutObject->{LanguageObject}->Translate(
|
|
'Create Database'
|
|
),
|
|
);
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseResult',
|
|
Data => {
|
|
Item => Translatable('Create Database'),
|
|
Step => $StepCounter,
|
|
},
|
|
);
|
|
|
|
my @Statements;
|
|
|
|
# Create database, add user.
|
|
if ( $DB{DBType} eq 'mysql' ) {
|
|
|
|
if ( $DB{InstallType} eq 'CreateDB' ) {
|
|
|
|
# Determine current host for MySQL account.
|
|
my $ConnectionID;
|
|
my $StatementHandle = $DBH->prepare("select connection_id()");
|
|
$StatementHandle->execute();
|
|
while ( my @Row = $StatementHandle->fetchrow_array() ) {
|
|
$ConnectionID = $Row[0];
|
|
}
|
|
|
|
$StatementHandle = $DBH->prepare("show processlist");
|
|
$StatementHandle->execute();
|
|
PROCESSLIST:
|
|
while ( my @Row = $StatementHandle->fetchrow_array() ) {
|
|
if ( $Row[0] eq $ConnectionID ) {
|
|
$DB{Host} = $Row[2];
|
|
last PROCESSLIST;
|
|
}
|
|
}
|
|
|
|
# Strip off port, i.e. 'localhost:14962' should become 'localhost'.
|
|
$DB{Host} =~ s{:\d*\z}{}xms;
|
|
|
|
@Statements = (
|
|
"CREATE DATABASE `$DB{DBName}` charset utf8",
|
|
"GRANT ALL PRIVILEGES ON `$DB{DBName}`.* TO `$DB{OTRSDBUser}`\@`$DB{Host}` IDENTIFIED BY '$DB{OTRSDBPassword}' WITH GRANT OPTION",
|
|
"FLUSH PRIVILEGES",
|
|
);
|
|
}
|
|
|
|
# Set DSN for Config.pm.
|
|
$DB{ConfigDSN} = 'DBI:mysql:database=$Self->{Database};host=$Self->{DatabaseHost}';
|
|
$DB{DSN} = "DBI:mysql:database=$DB{DBName};host=$DB{DBHost}";
|
|
}
|
|
elsif ( $DB{DBType} eq 'postgresql' ) {
|
|
|
|
if ( $DB{InstallType} eq 'CreateDB' ) {
|
|
@Statements = (
|
|
"CREATE ROLE \"$DB{OTRSDBUser}\" WITH LOGIN PASSWORD '$DB{OTRSDBPassword}'",
|
|
"CREATE DATABASE \"$DB{DBName}\" OWNER=\"$DB{OTRSDBUser}\" ENCODING 'utf-8'",
|
|
);
|
|
}
|
|
|
|
# Set DSN for Config.pm.
|
|
$DB{ConfigDSN} = 'DBI:Pg:dbname=$Self->{Database};host=$Self->{DatabaseHost}';
|
|
$DB{DSN} = "DBI:Pg:dbname=$DB{DBName};host=$DB{DBHost}";
|
|
}
|
|
elsif ( $DB{DBType} eq 'oracle' ) {
|
|
|
|
# Set DSN for Config.pm.
|
|
$DB{ConfigDSN} = 'DBI:Oracle://$Self->{DatabaseHost}:' . $DB{DBPort} . '/$Self->{Database}';
|
|
$DB{DSN} = "DBI:Oracle://$DB{DBHost}:$DB{DBPort}/$DB{DBSID}";
|
|
$ConfigObject->Set(
|
|
Key => 'Database::Connect',
|
|
Value => "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'",
|
|
);
|
|
}
|
|
|
|
# Execute database statements.
|
|
for my $Statement (@Statements) {
|
|
my @Description = split( ' ', $Statement );
|
|
|
|
# Prevent uninitialized variables.
|
|
for my $Index ( 0 .. 2 ) {
|
|
$Description[$Index] //= '';
|
|
}
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseResultItem',
|
|
Data => { Item => "$Description[0] $Description[1] $Description[2]" },
|
|
);
|
|
if ( !$DBH->do($Statement) ) {
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseResultItemFalse',
|
|
Data => {},
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseResultItemMessage',
|
|
Data => {
|
|
Message => $DBI::errstr,
|
|
},
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseResultBack',
|
|
Data => {},
|
|
);
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => 'Installer',
|
|
Data => {},
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
else {
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseResultItemDone',
|
|
Data => {},
|
|
);
|
|
}
|
|
}
|
|
|
|
# ReConfigure Config.pm.
|
|
my $ReConfigure;
|
|
if ( $DB{DBType} eq 'oracle' ) {
|
|
$ReConfigure = $Self->ReConfigure(
|
|
DatabaseDSN => $DB{ConfigDSN},
|
|
DatabaseHost => $DB{DBHost},
|
|
Database => $DB{DBSID},
|
|
DatabaseUser => $DB{OTRSDBUser},
|
|
DatabasePw => $DB{OTRSDBPassword},
|
|
);
|
|
}
|
|
else {
|
|
$ReConfigure = $Self->ReConfigure(
|
|
DatabaseDSN => $DB{ConfigDSN},
|
|
DatabaseHost => $DB{DBHost},
|
|
Database => $DB{DBName},
|
|
DatabaseUser => $DB{OTRSDBUser},
|
|
DatabasePw => $DB{OTRSDBPassword},
|
|
);
|
|
}
|
|
|
|
if ($ReConfigure) {
|
|
my $Output =
|
|
$LayoutObject->Header(
|
|
Title => Translatable('Install OTRS - Error')
|
|
);
|
|
$Output .= $LayoutObject->Warning(
|
|
Message => Translatable('Kernel/Config.pm isn\'t writable!'),
|
|
Comment => Translatable(
|
|
'If you want to use the installer, set the Kernel/Config.pm writable for the webserver user!'
|
|
),
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
|
|
$Kernel::OM->ObjectsDiscard( Objects => ['Kernel::System::DB'] );
|
|
|
|
# We need a database object to be able to parse the XML
|
|
# connect to database using given credentials.
|
|
$Kernel::OM->ObjectParamAdd(
|
|
'Kernel::System::DB' => {
|
|
DatabaseDSN => $DB{DSN},
|
|
DatabaseUser => $DB{OTRSDBUser},
|
|
DatabasePw => $DB{OTRSDBPassword},
|
|
Type => $DB{DBType},
|
|
},
|
|
);
|
|
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
|
|
|
# Create database tables and insert initial values.
|
|
my @SQLPost;
|
|
for my $SchemaFile (qw(otrs-schema otrs-initial_insert)) {
|
|
if ( !-f "$DirOfSQLFiles/$SchemaFile.xml" ) {
|
|
$LayoutObject->FatalError(
|
|
Message => $LayoutObject->{LanguageObject}
|
|
->Translate( 'File "%s/%s.xml" not found!', $DirOfSQLFiles, $SchemaFile ),
|
|
Comment => Translatable('Contact your Admin!'),
|
|
);
|
|
}
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseResultItem',
|
|
Data => { Item => "Processing $SchemaFile" },
|
|
);
|
|
|
|
my $XML = $MainObject->FileRead(
|
|
Directory => $DirOfSQLFiles,
|
|
Filename => $SchemaFile . '.xml',
|
|
);
|
|
my @XMLArray = $Kernel::OM->Get('Kernel::System::XML')->XMLParse(
|
|
String => $XML,
|
|
);
|
|
|
|
my @SQL = $DBObject->SQLProcessor(
|
|
Database => \@XMLArray,
|
|
);
|
|
|
|
# If we parsed the schema, catch post instructions.
|
|
@SQLPost = $DBObject->SQLProcessorPost() if $SchemaFile eq 'otrs-schema';
|
|
|
|
for my $SQL (@SQL) {
|
|
$DBObject->Do( SQL => $SQL );
|
|
}
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseResultItemDone',
|
|
);
|
|
}
|
|
|
|
# Execute post SQL statements (indexes, constraints).
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseResultItem',
|
|
Data => { Item => "Processing post statements" },
|
|
);
|
|
|
|
for my $SQL (@SQLPost) {
|
|
$DBObject->Do( SQL => $SQL );
|
|
}
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseResultItemDone',
|
|
);
|
|
|
|
# If running under PerlEx, reload the application (and thus the configuration).
|
|
if (
|
|
exists $ENV{'GATEWAY_INTERFACE'}
|
|
&& $ENV{'GATEWAY_INTERFACE'} eq "CGI-PerlEx"
|
|
)
|
|
{
|
|
PerlEx::ReloadAll();
|
|
}
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseResultSuccess',
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'DatabaseResultNext',
|
|
);
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => 'Installer',
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
|
|
# Show system settings page, pre-install packages.
|
|
elsif ( $Self->{Subaction} eq 'System' ) {
|
|
|
|
if ( !$Kernel::OM->Get('Kernel::System::DB') ) {
|
|
$LayoutObject->FatalError();
|
|
}
|
|
|
|
# Take care that default config is in the database.
|
|
if ( !$Self->_CheckConfig() ) {
|
|
return $LayoutObject->FatalError();
|
|
}
|
|
|
|
# Install default files.
|
|
if ( $MainObject->Require('Kernel::System::Package') ) {
|
|
my $PackageObject = Kernel::System::Package->new( %{$Self} );
|
|
if ($PackageObject) {
|
|
$PackageObject->PackageInstallDefaultFiles();
|
|
}
|
|
}
|
|
|
|
my @SystemIDs = map { sprintf "%02d", $_ } ( 0 .. 99 );
|
|
|
|
$Param{SystemIDString} = $LayoutObject->BuildSelection(
|
|
Data => \@SystemIDs,
|
|
Name => 'SystemID',
|
|
Class => 'Modernize',
|
|
SelectedID => $SystemIDs[ int( rand(100) ) ], # random system ID
|
|
);
|
|
$Param{LanguageString} = $LayoutObject->BuildSelection(
|
|
Data => $ConfigObject->Get('DefaultUsedLanguages'),
|
|
Name => 'DefaultLanguage',
|
|
Class => 'Modernize',
|
|
HTMLQuote => 0,
|
|
SelectedID => $LayoutObject->{UserLanguage},
|
|
);
|
|
|
|
# Build the selection field for the MX check.
|
|
$Param{SelectCheckMXRecord} = $LayoutObject->BuildSelection(
|
|
Data => {
|
|
1 => Translatable('Yes'),
|
|
0 => Translatable('No'),
|
|
},
|
|
Name => 'CheckMXRecord',
|
|
Class => 'Modernize',
|
|
SelectedID => '1',
|
|
);
|
|
|
|
# Read FQDN using Net::Domain and pre-populate the field.
|
|
$Param{FQDN} = hostfqdn();
|
|
|
|
my $Output =
|
|
$LayoutObject->Header(
|
|
Title => "$Title - "
|
|
. $LayoutObject->{LanguageObject}->Translate('System Settings'),
|
|
);
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'System',
|
|
Data => {
|
|
Item => Translatable('System Settings'),
|
|
Step => $StepCounter,
|
|
%Param,
|
|
},
|
|
);
|
|
|
|
if ( !$Self->{Options}->{SkipLog} ) {
|
|
$Param{LogModuleString} = $LayoutObject->BuildSelection(
|
|
Data => {
|
|
'Kernel::System::Log::SysLog' => Translatable('Syslog'),
|
|
'Kernel::System::Log::File' => Translatable('File'),
|
|
},
|
|
Name => 'LogModule',
|
|
Class => 'Modernize',
|
|
HTMLQuote => 0,
|
|
SelectedID => $ConfigObject->Get('LogModule'),
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'LogModule',
|
|
Data => \%Param,
|
|
);
|
|
}
|
|
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => 'Installer',
|
|
Data => {},
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
|
|
# Do system settings action.
|
|
elsif ( $Self->{Subaction} eq 'ConfigureMail' ) {
|
|
|
|
if ( !$Kernel::OM->Get('Kernel::System::DB') ) {
|
|
$LayoutObject->FatalError();
|
|
}
|
|
|
|
# Take care that default config is in the database.
|
|
if ( !$Self->_CheckConfig() ) {
|
|
return $LayoutObject->FatalError();
|
|
}
|
|
|
|
my $SysConfigObject = $Kernel::OM->Get('Kernel::System::SysConfig');
|
|
|
|
my $ExclusiveLockGUID = $SysConfigObject->SettingLock(
|
|
LockAll => 1,
|
|
Force => 1,
|
|
UserID => 1,
|
|
);
|
|
|
|
for my $SettingName (
|
|
qw(SystemID FQDN AdminEmail Organization LogModule LogModule::LogFile
|
|
DefaultLanguage CheckMXRecord)
|
|
)
|
|
{
|
|
my $EffectiveValue = $ParamObject->GetParam( Param => $SettingName );
|
|
|
|
# Update config item via sys config object.
|
|
$SysConfigObject->SettingUpdate(
|
|
Name => $SettingName,
|
|
IsValid => 1,
|
|
EffectiveValue => $EffectiveValue,
|
|
ExclusiveLockGUID => $ExclusiveLockGUID,
|
|
UserID => 1,
|
|
);
|
|
}
|
|
|
|
my $Success = $SysConfigObject->SettingUnlock(
|
|
UnlockAll => 1,
|
|
);
|
|
|
|
# Get mail account object and check available back-ends.
|
|
my $MailAccount = $Kernel::OM->Get('Kernel::System::MailAccount');
|
|
my %MailBackends = $MailAccount->MailAccountBackendList();
|
|
|
|
my $OutboundMailTypeSelection = $LayoutObject->BuildSelection(
|
|
Data => {
|
|
sendmail => 'Sendmail',
|
|
smtp => 'SMTP',
|
|
smtps => 'SMTPS',
|
|
smtptls => 'SMTPTLS',
|
|
},
|
|
Name => 'OutboundMailType',
|
|
Class => 'Modernize',
|
|
);
|
|
my $OutboundMailDefaultPorts = $LayoutObject->BuildSelection(
|
|
Class => 'Hidden',
|
|
Data => {
|
|
sendmail => '25',
|
|
smtp => '25',
|
|
smtps => '465',
|
|
smtptls => '587',
|
|
},
|
|
Name => 'OutboundMailDefaultPorts',
|
|
);
|
|
|
|
my $InboundMailTypeSelection = $LayoutObject->BuildSelection(
|
|
Data => \%MailBackends,
|
|
Name => 'InboundMailType',
|
|
Class => 'Modernize',
|
|
);
|
|
|
|
my $Output =
|
|
$LayoutObject->Header(
|
|
Title => "$Title - "
|
|
. $LayoutObject->{LanguageObject}->Translate('Configure Mail')
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'ConfigureMail',
|
|
Data => {
|
|
Item => $LayoutObject->{LanguageObject}->Translate('Mail Configuration'),
|
|
Step => $StepCounter,
|
|
InboundMailType => $InboundMailTypeSelection,
|
|
OutboundMailType => $OutboundMailTypeSelection,
|
|
OutboundPorts => $OutboundMailDefaultPorts,
|
|
},
|
|
);
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => 'Installer',
|
|
Data => {},
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
|
|
elsif ( $Self->{Subaction} eq 'Finish' ) {
|
|
|
|
# Take care that default config is in the database.
|
|
if ( !$Self->_CheckConfig() ) {
|
|
return $LayoutObject->FatalError();
|
|
}
|
|
|
|
my $SysConfigObject = $Kernel::OM->Get('Kernel::System::SysConfig');
|
|
|
|
my $SettingName = 'SecureMode';
|
|
|
|
my $ExclusiveLockGUID = $SysConfigObject->SettingLock(
|
|
Name => $SettingName,
|
|
Force => 1,
|
|
UserID => 1,
|
|
);
|
|
|
|
# Update config item via SysConfig object.
|
|
my $Result = $SysConfigObject->SettingUpdate(
|
|
Name => $SettingName,
|
|
IsValid => 1,
|
|
EffectiveValue => 1,
|
|
ExclusiveLockGUID => $ExclusiveLockGUID,
|
|
UserID => 1,
|
|
);
|
|
|
|
if ( !$Result ) {
|
|
$LayoutObject->FatalError(
|
|
Message => Translatable('Can\'t write Config file!'),
|
|
);
|
|
}
|
|
|
|
# There is no need to unlock the setting as it was already unlocked in the update.
|
|
|
|
# 'Rebuild' the configuration.
|
|
$SysConfigObject->ConfigurationDeploy(
|
|
Comments => "Installer deployment",
|
|
AllSettings => 1,
|
|
Force => 1,
|
|
UserID => 1,
|
|
);
|
|
|
|
# If running under PerlEx, reload the application (and thus the configuration).
|
|
if (
|
|
exists $ENV{'GATEWAY_INTERFACE'}
|
|
&& $ENV{'GATEWAY_INTERFACE'} eq "CGI-PerlEx"
|
|
)
|
|
{
|
|
PerlEx::ReloadAll();
|
|
}
|
|
|
|
# Set a generated password for the 'root@localhost' account.
|
|
my $UserObject = $Kernel::OM->Get('Kernel::System::User');
|
|
my $Password = $UserObject->GenerateRandomPassword( Size => 16 );
|
|
$UserObject->SetPassword(
|
|
UserLogin => 'root@localhost',
|
|
PW => $Password,
|
|
);
|
|
|
|
# TODO: This seams to be deprecated now.
|
|
# Remove installer file with pre-configured options.
|
|
if ( -f "$Self->{Path}/var/tmp/installer.json" ) {
|
|
unlink "$Self->{Path}/var/tmp/installer.json";
|
|
}
|
|
|
|
# check web server - is a restart needed?
|
|
my $Webserver;
|
|
|
|
# Only if we have mod_perl we have to restart.
|
|
if ( exists $ENV{MOD_PERL} ) {
|
|
eval 'require mod_perl'; ## no critic
|
|
if ( defined $mod_perl::VERSION ) { ## no critic
|
|
$Webserver = 'Apache2 + mod_perl';
|
|
if ( -f '/etc/SuSE-release' ) {
|
|
$Webserver = 'rcapache2 restart';
|
|
}
|
|
elsif ( -f '/etc/redhat-release' ) {
|
|
$Webserver = 'service httpd restart';
|
|
}
|
|
}
|
|
}
|
|
|
|
# Check if Apache::Reload is loaded.
|
|
for my $Module ( sort keys %INC ) {
|
|
$Module =~ s/\//::/g;
|
|
$Module =~ s/\.pm$//g;
|
|
|
|
if ( $Module eq 'Apache2::Reload' ) {
|
|
$Webserver = '';
|
|
}
|
|
}
|
|
|
|
my $OTRSHandle = $ENV{SCRIPT_NAME};
|
|
$OTRSHandle =~ s/\/(.*)\/installer\.pl/$1/;
|
|
my $Output =
|
|
$LayoutObject->Header(
|
|
Title => "$Title - "
|
|
. $LayoutObject->{LanguageObject}->Translate('Finished')
|
|
);
|
|
$LayoutObject->Block(
|
|
Name => 'Finish',
|
|
Data => {
|
|
Item => Translatable('Finished'),
|
|
Step => $StepCounter,
|
|
Host => $ENV{HTTP_HOST} || $ConfigObject->Get('FQDN'),
|
|
OTRSHandle => $OTRSHandle,
|
|
Webserver => $Webserver,
|
|
Password => $Password,
|
|
},
|
|
);
|
|
if ($Webserver) {
|
|
$LayoutObject->Block(
|
|
Name => 'Restart',
|
|
Data => {
|
|
Webserver => $Webserver,
|
|
},
|
|
);
|
|
}
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => 'Installer',
|
|
Data => {},
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
return $Output;
|
|
}
|
|
|
|
# Else error!
|
|
return $LayoutObject->FatalError(
|
|
Message => $LayoutObject->{LanguageObject}->Translate( 'Unknown Subaction %s!', $Self->{Subaction} ),
|
|
Comment => Translatable('Please contact the administrator.'),
|
|
);
|
|
}
|
|
|
|
sub ReConfigure {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# Perl quote and set via ConfigObject.
|
|
for my $Key ( sort keys %Param ) {
|
|
$Kernel::OM->Get('Kernel::Config')->Set(
|
|
Key => $Key,
|
|
Value => $Param{$Key},
|
|
);
|
|
if ( $Param{$Key} ) {
|
|
$Param{$Key} =~ s/'/\\'/g;
|
|
}
|
|
}
|
|
|
|
# Read config file.
|
|
my $ConfigFile = "$Self->{Path}/Kernel/Config.pm";
|
|
## no critic
|
|
open( my $In, '<', $ConfigFile )
|
|
|| return "Can't open $ConfigFile: $!";
|
|
## use critic
|
|
my $Config = '';
|
|
while (<$In>) {
|
|
|
|
# Skip empty lines or comments.
|
|
if ( !$_ || $_ =~ /^\s*#/ || $_ =~ /^\s*$/ ) {
|
|
$Config .= $_;
|
|
}
|
|
else {
|
|
my $NewConfig = $_;
|
|
|
|
# Replace config with %Param.
|
|
for my $Key ( sort keys %Param ) {
|
|
|
|
# Database passwords can contain characters like '@' or '$' and should be single-quoted
|
|
# same goes for database hosts which can be like 'myserver\instance name' for MS SQL.
|
|
if ( $Key eq 'DatabasePw' || $Key eq 'DatabaseHost' ) {
|
|
$NewConfig =~
|
|
s/(\$Self->\{("|'|)$Key("|'|)} =.+?('|"));/\$Self->{'$Key'} = '$Param{$Key}';/g;
|
|
}
|
|
else {
|
|
$NewConfig =~
|
|
s/(\$Self->\{("|'|)$Key("|'|)} =.+?('|"));/\$Self->{'$Key'} = "$Param{$Key}";/g;
|
|
}
|
|
}
|
|
$Config .= $NewConfig;
|
|
}
|
|
}
|
|
close $In;
|
|
|
|
# Write new config file.
|
|
## no critic
|
|
open( my $Out, '>:utf8', $ConfigFile )
|
|
|| return "Can't open $ConfigFile: $!";
|
|
print $Out $Config;
|
|
## use critic
|
|
close $Out;
|
|
|
|
return;
|
|
}
|
|
|
|
sub ConnectToDB {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# Check params.
|
|
my @NeededKeys = qw(DBType DBHost DBUser DBPassword);
|
|
|
|
if ( $Param{InstallType} eq 'CreateDB' ) {
|
|
push @NeededKeys, qw(OTRSDBUser OTRSDBPassword);
|
|
}
|
|
|
|
# For Oracle we require DBSID and DBPort.
|
|
if ( $Param{DBType} eq 'oracle' ) {
|
|
push @NeededKeys, qw(DBSID DBPort);
|
|
}
|
|
|
|
# For existing databases we require the database name.
|
|
if ( $Param{DBType} ne 'oracle' && $Param{InstallType} eq 'UseDB' ) {
|
|
push @NeededKeys, 'DBName';
|
|
}
|
|
|
|
for my $Key (@NeededKeys) {
|
|
if ( !$Param{$Key} && $Key !~ /^(DBPassword)$/ ) {
|
|
return (
|
|
Successful => 0,
|
|
Message => "You need '$Key'!!",
|
|
DB => undef,
|
|
DBH => undef,
|
|
);
|
|
}
|
|
}
|
|
|
|
# If we do not need to create a database for OTRS OTRSDBuser equals DBUser.
|
|
if ( $Param{InstallType} ne 'CreateDB' ) {
|
|
$Param{OTRSDBUser} = $Param{DBUser};
|
|
$Param{OTRSDBPassword} = $Param{DBPassword};
|
|
}
|
|
|
|
# Create DSN string for backend.
|
|
if ( $Param{DBType} eq 'mysql' && $Param{InstallType} eq 'CreateDB' ) {
|
|
$Param{DSN} = "DBI:mysql:database=;host=$Param{DBHost};";
|
|
}
|
|
elsif ( $Param{DBType} eq 'mysql' && $Param{InstallType} eq 'UseDB' ) {
|
|
$Param{DSN} = "DBI:mysql:database=;host=$Param{DBHost};database=$Param{DBName}";
|
|
}
|
|
elsif ( $Param{DBType} eq 'postgresql' && $Param{InstallType} eq 'CreateDB' ) {
|
|
$Param{DSN} = "DBI:Pg:host=$Param{DBHost};";
|
|
}
|
|
elsif ( $Param{DBType} eq 'postgresql' && $Param{InstallType} eq 'UseDB' ) {
|
|
$Param{DSN} = "DBI:Pg:host=$Param{DBHost};dbname=$Param{DBName}";
|
|
}
|
|
elsif ( $Param{DBType} eq 'oracle' ) {
|
|
$Param{DSN} = "DBI:Oracle://$Param{DBHost}:$Param{DBPort}/$Param{DBSID}";
|
|
}
|
|
|
|
# Extract driver to load for install test.
|
|
my ($Driver) = ( $Param{DSN} =~ /^DBI:(.*?):/ );
|
|
if ( !$Kernel::OM->Get('Kernel::System::Main')->Require( 'DBD::' . $Driver ) ) {
|
|
return (
|
|
Successful => 0,
|
|
Message => $Kernel::OM->Get('Kernel::Output::HTML::Layout')->{LanguageObject}
|
|
->Translate( "Can't connect to database, Perl module DBD::%s not installed!", $Driver ),
|
|
Comment => "",
|
|
DB => undef,
|
|
DBH => undef,
|
|
);
|
|
}
|
|
|
|
my $DBH = DBI->connect(
|
|
$Param{DSN}, $Param{DBUser}, $Param{DBPassword},
|
|
);
|
|
|
|
if ( !$DBH ) {
|
|
return (
|
|
Successful => 0,
|
|
Message => $Kernel::OM->Get('Kernel::Output::HTML::Layout')->{LanguageObject}
|
|
->Translate("Can't connect to database, read comment!"),
|
|
Comment => "$DBI::errstr",
|
|
DB => undef,
|
|
DBH => undef,
|
|
);
|
|
}
|
|
|
|
# If we use an existing database, check if it already contains tables.
|
|
if ( $Param{InstallType} ne 'CreateDB' ) {
|
|
|
|
my $Data = $DBH->selectall_arrayref('SELECT * FROM valid');
|
|
if ($Data) {
|
|
return (
|
|
Successful => 0,
|
|
Message => $Kernel::OM->Get('Kernel::Output::HTML::Layout')->{LanguageObject}
|
|
->Translate("Database already contains data - it should be empty!"),
|
|
Comment => "",
|
|
DB => undef,
|
|
DBH => undef,
|
|
);
|
|
}
|
|
}
|
|
|
|
return (
|
|
Successful => 1,
|
|
Message => '',
|
|
Comment => '',
|
|
DB => \%Param,
|
|
DBH => $DBH,
|
|
);
|
|
}
|
|
|
|
sub CheckDBRequirements {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my %Result = $Self->ConnectToDB(
|
|
%Param,
|
|
);
|
|
|
|
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
|
|
|
# If mysql, check some more values.
|
|
if ( $Param{DBType} eq 'mysql' && $Result{Successful} == 1 ) {
|
|
|
|
# Set max_allowed_packet.
|
|
my $MySQLMaxAllowedPacket = 0;
|
|
my $MySQLMaxAllowedPacketRecommended = 64;
|
|
|
|
my $Data = $Result{DBH}->selectall_arrayref("SHOW variables WHERE Variable_name = 'max_allowed_packet'");
|
|
$MySQLMaxAllowedPacket = $Data->[0]->[1] / 1024 / 1024;
|
|
|
|
if ( $MySQLMaxAllowedPacket < $MySQLMaxAllowedPacketRecommended ) {
|
|
$Result{Successful} = 0;
|
|
$Result{Message} = $LayoutObject->{LanguageObject}->Translate(
|
|
"Error: Please make sure your database accepts packages over %s MB in size (it currently only accepts packages up to %s MB). Please adapt the max_allowed_packet setting of your database in order to avoid errors.",
|
|
$MySQLMaxAllowedPacketRecommended, $MySQLMaxAllowedPacket
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( $Param{DBType} eq 'mysql' && $Result{Successful} == 1 ) {
|
|
|
|
# Set innodb_log_file_size.
|
|
my $MySQLInnoDBLogFileSize = 0;
|
|
my $MySQLInnoDBLogFileSizeMinimum = 256;
|
|
my $MySQLInnoDBLogFileSizeRecommended = 512;
|
|
|
|
# Default storage engine variable has changed its name in MySQL 5.5.3, we need to support both of them for now.
|
|
# <= 5.5.2 storage_engine
|
|
# >= 5.5.3 default_storage_engine
|
|
my $DataOld = $Result{DBH}->selectall_arrayref("SHOW variables WHERE Variable_name = 'storage_engine'");
|
|
my $DataNew = $Result{DBH}->selectall_arrayref("SHOW variables WHERE Variable_name = 'default_storage_engine'");
|
|
my $DefaultStorageEngine = ( $DataOld->[0] && $DataOld->[0]->[1] ? $DataOld->[0]->[1] : undef )
|
|
// ( $DataNew->[0] && $DataNew->[0]->[1] ? $DataNew->[0]->[1] : '' );
|
|
|
|
if ( lc $DefaultStorageEngine eq 'innodb' ) {
|
|
|
|
my $Data = $Result{DBH}->selectall_arrayref("SHOW variables WHERE Variable_name = 'innodb_log_file_size'");
|
|
$MySQLInnoDBLogFileSize = $Data->[0]->[1] / 1024 / 1024;
|
|
|
|
if ( $MySQLInnoDBLogFileSize < $MySQLInnoDBLogFileSizeMinimum ) {
|
|
$Result{Successful} = 0;
|
|
$Result{Message} = $LayoutObject->{LanguageObject}->Translate(
|
|
"Error: Please set the value for innodb_log_file_size on your database to at least %s MB (current: %s MB, recommended: %s MB). For more information, please have a look at %s.",
|
|
$MySQLInnoDBLogFileSizeMinimum,
|
|
$MySQLInnoDBLogFileSize,
|
|
$MySQLInnoDBLogFileSizeRecommended,
|
|
'http://dev.mysql.com/doc/refman/5.6/en/innodb-data-log-reconfiguration.html',
|
|
);
|
|
}
|
|
}
|
|
|
|
# Check character_set_database value.
|
|
my $Charset = $Result{DBH}->selectall_arrayref("SHOW variables LIKE 'character_set_database'");
|
|
|
|
if ( $Charset->[0]->[1] =~ /utf8mb4/i ) {
|
|
$Result{Successful} = 0;
|
|
$Result{Message} = $LayoutObject->{LanguageObject}->Translate(
|
|
"Wrong database collation (%s is %s, but it needs to be utf8).",
|
|
'character_set_database',
|
|
$Charset->[0]->[1],
|
|
);
|
|
}
|
|
elsif ( $Charset->[0]->[1] !~ /utf8/i ) {
|
|
$Result{Successful} = 0;
|
|
$Result{Message} = $LayoutObject->{LanguageObject}->Translate(
|
|
"Wrong database collation (%s is %s, but it needs to be utf8).",
|
|
'character_set_database',
|
|
$Charset->[0]->[1],
|
|
);
|
|
}
|
|
}
|
|
|
|
# Delete not necessary key/value pairs.
|
|
delete $Result{DB};
|
|
delete $Result{DBH};
|
|
|
|
return %Result;
|
|
}
|
|
|
|
sub CheckMailConfiguration {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
|
|
|
|
# First check outbound mail config.
|
|
my $OutboundMailType =
|
|
$ParamObject->GetParam( Param => 'OutboundMailType' );
|
|
my $SMTPHost = $ParamObject->GetParam( Param => 'SMTPHost' );
|
|
my $SMTPPort = $ParamObject->GetParam( Param => 'SMTPPort' );
|
|
my $SMTPAuthUser =
|
|
$ParamObject->GetParam( Param => 'SMTPAuthUser' );
|
|
my $SMTPAuthPassword =
|
|
$ParamObject->GetParam( Param => 'SMTPAuthPassword' );
|
|
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
|
|
# If chosen config option is SMTP, set some Config params.
|
|
if ( $OutboundMailType && $OutboundMailType ne 'sendmail' ) {
|
|
$ConfigObject->Set(
|
|
Key => 'SendmailModule',
|
|
Value => 'Kernel::System::Email::' . uc($OutboundMailType),
|
|
);
|
|
$ConfigObject->Set(
|
|
Key => 'SendmailModule::Host',
|
|
Value => $SMTPHost,
|
|
);
|
|
$ConfigObject->Set(
|
|
Key => 'SendmailModule::Port',
|
|
Value => $SMTPPort,
|
|
);
|
|
if ($SMTPAuthUser) {
|
|
$ConfigObject->Set(
|
|
Key => 'SendmailModule::AuthUser',
|
|
Value => $SMTPAuthUser,
|
|
);
|
|
}
|
|
if ($SMTPAuthPassword) {
|
|
$ConfigObject->Set(
|
|
Key => 'SendmailModule::AuthPassword',
|
|
Value => $SMTPAuthPassword,
|
|
);
|
|
}
|
|
}
|
|
|
|
# If sendmail, set config to sendmail.
|
|
else {
|
|
$ConfigObject->Set(
|
|
Key => 'SendmailModule',
|
|
Value => 'Kernel::System::Email::Sendmail',
|
|
);
|
|
}
|
|
|
|
# If config option SMTP and no SMTP host given, return with error.
|
|
if ( $OutboundMailType ne 'sendmail' && !$SMTPHost ) {
|
|
return (
|
|
Successful => 0,
|
|
Message => 'No SMTP Host given!'
|
|
);
|
|
}
|
|
|
|
# Check outbound mail configuration.
|
|
my $SendObject = $Kernel::OM->Get('Kernel::System::Email');
|
|
my %Result = $SendObject->Check();
|
|
|
|
my $SysConfigObject = $Kernel::OM->Get('Kernel::System::SysConfig');
|
|
|
|
my $ExclusiveLockGUID = $SysConfigObject->SettingLock(
|
|
LockAll => 1,
|
|
Force => 1,
|
|
UserID => 1,
|
|
);
|
|
|
|
# If SMTP check was successful, write data into config.
|
|
my $SendmailModule = $ConfigObject->Get('SendmailModule');
|
|
if (
|
|
$Result{Successful}
|
|
&& $SendmailModule ne 'Kernel::System::Email::Sendmail'
|
|
)
|
|
{
|
|
my %NewConfigs = (
|
|
'SendmailModule' => $SendmailModule,
|
|
'SendmailModule::Host' => $SMTPHost,
|
|
'SendmailModule::Port' => $SMTPPort,
|
|
);
|
|
|
|
for my $SettingName ( sort keys %NewConfigs ) {
|
|
$SysConfigObject->SettingUpdate(
|
|
Name => $SettingName,
|
|
IsValid => 1,
|
|
EffectiveValue => $NewConfigs{$SettingName},
|
|
ExclusiveLockGUID => $ExclusiveLockGUID,
|
|
UserID => 1,
|
|
);
|
|
}
|
|
|
|
if ( $SMTPAuthUser && $SMTPAuthPassword ) {
|
|
%NewConfigs = (
|
|
'SendmailModule::AuthUser' => $SMTPAuthUser,
|
|
'SendmailModule::AuthPassword' => $SMTPAuthPassword,
|
|
);
|
|
|
|
for my $SettingName ( sort keys %NewConfigs ) {
|
|
$SysConfigObject->SettingUpdate(
|
|
Name => $SettingName,
|
|
IsValid => 1,
|
|
EffectiveValue => $NewConfigs{$SettingName},
|
|
ExclusiveLockGUID => $ExclusiveLockGUID,
|
|
UserID => 1,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
# If sendmail check was successful, write data into config.
|
|
elsif (
|
|
$Result{Successful}
|
|
&& $SendmailModule eq 'Kernel::System::Email::Sendmail'
|
|
)
|
|
{
|
|
$SysConfigObject->SettingUpdate(
|
|
Name => 'SendmailModule',
|
|
IsValid => 1,
|
|
EffectiveValue => $ConfigObject->Get('SendmailModule'),
|
|
ExclusiveLockGUID => $ExclusiveLockGUID,
|
|
UserID => 1,
|
|
);
|
|
}
|
|
|
|
# Now check inbound mail config. return if the outbound config threw an error.
|
|
if ( !$Result{Successful} ) {
|
|
return %Result;
|
|
}
|
|
|
|
# Check inbound mail config.
|
|
my $MailAccount = $Kernel::OM->Get('Kernel::System::MailAccount');
|
|
|
|
for (qw(InboundUser InboundPassword InboundHost)) {
|
|
if ( !$ParamObject->GetParam( Param => $_ ) ) {
|
|
return (
|
|
Successful => 0,
|
|
Message => "Missing parameter: $_!"
|
|
);
|
|
}
|
|
}
|
|
|
|
my $InboundUser = $ParamObject->GetParam( Param => 'InboundUser' );
|
|
my $InboundPassword =
|
|
$ParamObject->GetParam( Param => 'InboundPassword' );
|
|
my $InboundHost = $ParamObject->GetParam( Param => 'InboundHost' );
|
|
my $InboundMailType =
|
|
$ParamObject->GetParam( Param => 'InboundMailType' );
|
|
|
|
%Result = $MailAccount->MailAccountCheck(
|
|
Login => $InboundUser,
|
|
Password => $InboundPassword,
|
|
Host => $InboundHost,
|
|
Type => $InboundMailType,
|
|
Timeout => '60',
|
|
Debug => '0',
|
|
);
|
|
|
|
# If successful, add mail account to DB.
|
|
if ( $Result{Successful} ) {
|
|
my $ID = $MailAccount->MailAccountAdd(
|
|
Login => $InboundUser,
|
|
Password => $InboundPassword,
|
|
Host => $InboundHost,
|
|
Type => $InboundMailType,
|
|
ValidID => 1,
|
|
Trusted => 0,
|
|
DispatchingBy => 'From',
|
|
QueueID => 1,
|
|
UserID => 1,
|
|
);
|
|
|
|
if ( !$ID ) {
|
|
return (
|
|
Successful => 0,
|
|
Message => 'Error while adding mail account!'
|
|
);
|
|
}
|
|
}
|
|
|
|
return %Result;
|
|
}
|
|
|
|
sub _CheckConfig {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $SysConfigObject = $Kernel::OM->Get('Kernel::System::SysConfig');
|
|
|
|
my @Result = $SysConfigObject->ConfigurationSearch(
|
|
Search => 'ProductName',
|
|
);
|
|
|
|
return 1 if @Result;
|
|
|
|
my $Home = $Kernel::OM->Get('Kernel::Config')->Get('Home');
|
|
|
|
return $SysConfigObject->ConfigurationXML2DB(
|
|
UserID => 1,
|
|
Directory => "$Home/Kernel/Config/Files/XML",
|
|
Force => 1,
|
|
CleanUp => 1,
|
|
);
|
|
}
|
|
|
|
1;
|