571 lines
18 KiB
Perl
571 lines
18 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::AdminSupportDataCollector;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Kernel::System::SupportDataCollector::PluginBase;
|
|
|
|
use Kernel::System::VariableCheck qw(:all);
|
|
|
|
our $ObjectManagerDisabled = 1;
|
|
|
|
sub new {
|
|
my ( $Type, %Param ) = @_;
|
|
|
|
# allocate new hash for object
|
|
my $Self = {%Param};
|
|
bless( $Self, $Type );
|
|
|
|
return $Self;
|
|
}
|
|
|
|
sub Run {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
# ------------------------------------------------------------ #
|
|
# Send Support Data Update
|
|
# ------------------------------------------------------------ #
|
|
|
|
if ( $Self->{Subaction} eq 'SendUpdate' ) {
|
|
|
|
my %Result = $Kernel::OM->Get('Kernel::System::Registration')->RegistrationUpdateSend();
|
|
|
|
return $Kernel::OM->Get('Kernel::Output::HTML::Layout')->Attachment(
|
|
ContentType => 'text/html',
|
|
Content => $Result{Success},
|
|
Type => 'inline',
|
|
NoCache => 1,
|
|
);
|
|
}
|
|
elsif ( $Self->{Subaction} eq 'GenerateSupportBundle' ) {
|
|
return $Self->_GenerateSupportBundle();
|
|
}
|
|
elsif ( $Self->{Subaction} eq 'DownloadSupportBundle' ) {
|
|
return $Self->_DownloadSupportBundle();
|
|
}
|
|
elsif ( $Self->{Subaction} eq 'SendSupportBundle' ) {
|
|
return $Self->_SendSupportBundle();
|
|
}
|
|
return $Self->_SupportDataCollectorView(%Param);
|
|
}
|
|
|
|
sub _SupportDataCollectorView {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $SystemDataObject = $Kernel::OM->Get('Kernel::System::SystemData');
|
|
my $RegistrationState = $SystemDataObject->SystemDataGet(
|
|
Key => 'Registration::State',
|
|
) || '';
|
|
my $SupportDataSending = $SystemDataObject->SystemDataGet(
|
|
Key => 'Registration::SupportDataSending',
|
|
) || 'No';
|
|
|
|
my %SupportData = $Kernel::OM->Get('Kernel::System::SupportDataCollector')->Collect(
|
|
UseCache => 1,
|
|
);
|
|
|
|
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
|
|
|
# check if cloud services are disabled
|
|
my $CloudServicesDisabled = $Kernel::OM->Get('Kernel::Config')->Get('CloudServices::Disabled') || 0;
|
|
|
|
if ( !$SupportData{Success} ) {
|
|
$LayoutObject->Block(
|
|
Name => 'SupportDataCollectionFailed',
|
|
Data => \%SupportData,
|
|
);
|
|
}
|
|
else {
|
|
if ($CloudServicesDisabled) {
|
|
$LayoutObject->Block(
|
|
Name => 'CloudServicesWarning',
|
|
);
|
|
}
|
|
elsif (
|
|
$RegistrationState ne 'registered'
|
|
|| $SupportDataSending ne 'Yes'
|
|
)
|
|
{
|
|
$LayoutObject->Block(
|
|
Name => 'NoteNotRegisteredNotSending',
|
|
);
|
|
}
|
|
else {
|
|
$LayoutObject->Block(
|
|
Name => 'NoteRegisteredSending',
|
|
);
|
|
}
|
|
$LayoutObject->Block(
|
|
Name => 'NoteSupportBundle',
|
|
);
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'SupportData',
|
|
);
|
|
my ( $LastGroup, $LastSubGroup ) = ( '', '' );
|
|
|
|
for my $Entry ( @{ $SupportData{Result} || [] } ) {
|
|
|
|
$Entry->{StatusName} = $Kernel::System::SupportDataCollector::PluginBase::Status2Name{
|
|
$Entry->{Status}
|
|
};
|
|
|
|
# get the display path, display type and additional information for the output
|
|
my ( $DisplayPath, $DisplayType, $DisplayAdditional ) = split( m{[\@\:]}, $Entry->{DisplayPath} // '' );
|
|
|
|
my ( $Group, $SubGroup ) = split( m{/}, $DisplayPath );
|
|
if ( $Group ne $LastGroup ) {
|
|
$LayoutObject->Block(
|
|
Name => 'SupportDataGroup',
|
|
Data => {
|
|
Group => $Group,
|
|
},
|
|
);
|
|
}
|
|
$LastGroup = $Group // '';
|
|
|
|
if ( !$SubGroup || $SubGroup ne $LastSubGroup ) {
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'SupportDataRow',
|
|
Data => $Entry,
|
|
);
|
|
}
|
|
|
|
if ( $SubGroup && $SubGroup ne $LastSubGroup ) {
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'SupportDataSubGroup',
|
|
Data => {
|
|
%{$Entry},
|
|
SubGroup => $SubGroup,
|
|
},
|
|
);
|
|
}
|
|
$LastSubGroup = $SubGroup // '';
|
|
|
|
if ( $DisplayType && $DisplayType eq 'Table' && ref $Entry->{Value} eq 'ARRAY' ) {
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'SupportDataEntryTable',
|
|
Data => $Entry,
|
|
);
|
|
|
|
if ( IsArrayRefWithData( $Entry->{Value} ) ) {
|
|
|
|
# get the table columns
|
|
my @TableColumns = split( m{,}, $DisplayAdditional // '' );
|
|
|
|
my @Identifiers;
|
|
my @Labels;
|
|
|
|
COLUMN:
|
|
for my $Column (@TableColumns) {
|
|
|
|
next COLUMN if !$Column;
|
|
|
|
# get the identifier and label
|
|
my ( $Identifier, $Label ) = split( m{\|}, $Column );
|
|
|
|
# set the identifier as default label
|
|
$Label ||= $Identifier;
|
|
|
|
push @Identifiers, $Identifier;
|
|
push @Labels, $Label;
|
|
}
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'SupportDataEntryTableDetails',
|
|
Data => {
|
|
Identifiers => \@Identifiers,
|
|
Labels => \@Labels,
|
|
%{$Entry},
|
|
},
|
|
);
|
|
}
|
|
}
|
|
elsif ( !$SubGroup ) {
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'SupportDataEntry',
|
|
Data => $Entry,
|
|
);
|
|
if ( defined $Entry->{Value} && length $Entry->{Value} ) {
|
|
if ( $Entry->{Value} =~ m{\n} ) {
|
|
$LayoutObject->Block(
|
|
Name => 'SupportDataEntryValueMultiLine',
|
|
Data => $Entry,
|
|
);
|
|
}
|
|
else {
|
|
$LayoutObject->Block(
|
|
Name => 'SupportDataEntryValueSingleLine',
|
|
Data => $Entry,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'SupportDataSubEntry',
|
|
Data => $Entry,
|
|
);
|
|
|
|
if ( $Entry->{Message} || $Entry->{MessageFormatted} ) {
|
|
$LayoutObject->Block(
|
|
Name => 'SupportDataSubEntryMessage',
|
|
Data => {
|
|
Message => $Entry->{Message},
|
|
MessageFormatted => $Entry->{MessageFormatted},
|
|
},
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# get user data
|
|
my %User = $Kernel::OM->Get('Kernel::System::User')->GetUserData(
|
|
UserID => $Self->{UserID},
|
|
Cached => 1,
|
|
);
|
|
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
|
|
# get sender email address
|
|
if ( $User{UserEmail} && $User{UserEmail} !~ /root\@localhost/ ) {
|
|
$Param{SenderAddress} = $User{UserEmail};
|
|
}
|
|
elsif (
|
|
|
|
$ConfigObject->Get('AdminEmail')
|
|
&& $ConfigObject->Get('AdminEmail') !~ /root\@localhost/
|
|
&& $ConfigObject->Get('AdminEmail') !~ /admin\@example.com/
|
|
)
|
|
{
|
|
$Param{SenderAddress} = $ConfigObject->Get('AdminEmail');
|
|
}
|
|
$Param{SenderName} = $User{UserFullname};
|
|
|
|
# verify if the email is valid, set it to empty string if not, this will be checked on client
|
|
# side
|
|
if (
|
|
$Param{SenderAddress} &&
|
|
!$Kernel::OM->Get('Kernel::System::CheckItem')->CheckEmail( Address => $Param{SenderAddress} )
|
|
)
|
|
{
|
|
$Param{SenderAddress} = '';
|
|
}
|
|
|
|
my $Output = $LayoutObject->Header();
|
|
$Output .= $LayoutObject->NavigationBar();
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => 'AdminSupportDataCollector',
|
|
Data => \%Param,
|
|
);
|
|
$Output .= $LayoutObject->Footer();
|
|
|
|
return $Output;
|
|
}
|
|
|
|
sub _GenerateSupportBundle {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
$Kernel::OM->Get('Kernel::Output::HTML::Layout')->ChallengeTokenCheck();
|
|
|
|
my $MainObject = $Kernel::OM->Get('Kernel::System::Main');
|
|
my $RandomID = $MainObject->GenerateRandomString(
|
|
Length => 8,
|
|
Dictionary => [ 0 .. 9, 'a' .. 'f' ],
|
|
);
|
|
|
|
# remove any older file
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
my $TempDir = $ConfigObject->Get('TempDir') . '/SupportBundleDownloadCache';
|
|
|
|
if ( !-d $TempDir ) {
|
|
mkdir $TempDir;
|
|
}
|
|
|
|
$TempDir = $ConfigObject->Get('TempDir') . '/SupportBundleDownloadCache/' . $RandomID;
|
|
|
|
if ( !-d $TempDir ) {
|
|
mkdir $TempDir;
|
|
}
|
|
|
|
# remove all files
|
|
my @ListOld = glob( $TempDir . '/*' );
|
|
for my $File (@ListOld) {
|
|
unlink $File;
|
|
}
|
|
|
|
# create the support bundle
|
|
my $Result = $Kernel::OM->Get('Kernel::System::SupportBundleGenerator')->Generate();
|
|
|
|
if ( !$Result->{Success} ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => $Result->{Message},
|
|
);
|
|
}
|
|
else {
|
|
|
|
# save support bundle in the FS (temporary)
|
|
my $FileLocation = $MainObject->FileWrite(
|
|
Location => $TempDir . '/' . $Result->{Data}->{Filename},
|
|
Content => $Result->{Data}->{Filecontent},
|
|
Mode => 'binmode',
|
|
Type => 'Local',
|
|
Permission => '644',
|
|
);
|
|
}
|
|
|
|
my $JSONString = $Kernel::OM->Get('Kernel::System::JSON')->Encode(
|
|
Data => {
|
|
Success => $Result->{Success},
|
|
Message => $Result->{Message} || '',
|
|
Filesize => $Result->{Data}->{Filesize} || '',
|
|
Filename => $Result->{Data}->{Filename} || '',
|
|
RandomID => $RandomID,
|
|
},
|
|
);
|
|
|
|
return $Kernel::OM->Get('Kernel::Output::HTML::Layout')->Attachment(
|
|
ContentType => 'text/html',
|
|
Content => $JSONString,
|
|
Type => 'inline',
|
|
NoCache => 1,
|
|
);
|
|
}
|
|
|
|
sub _DownloadSupportBundle {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
|
|
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
|
|
|
$LayoutObject->ChallengeTokenCheck();
|
|
|
|
my $Filename = $ParamObject->GetParam( Param => 'Filename' ) || '';
|
|
my $RandomID = $ParamObject->GetParam( Param => 'RandomID' ) || '';
|
|
|
|
# Validate simple file name.
|
|
if ( !$Filename || $Filename !~ m{^[a-z0-9._-]+$}smxi ) {
|
|
return $LayoutObject->ErrorScreen(
|
|
Message => "Need Filename or Filename invalid!",
|
|
);
|
|
}
|
|
|
|
# Validate simple RandomID.
|
|
if ( !$RandomID || $RandomID !~ m{^[a-f0-9]+$}smx ) {
|
|
return $LayoutObject->ErrorScreen(
|
|
Message => "Need RandomID or RandomID invalid!",
|
|
);
|
|
}
|
|
|
|
my $TempDir = $Kernel::OM->Get('Kernel::Config')->Get('TempDir') . '/SupportBundleDownloadCache/' . $RandomID;
|
|
my $Location = $TempDir . '/' . $Filename;
|
|
|
|
my $MainObject = $Kernel::OM->Get('Kernel::System::Main');
|
|
my $Content = $MainObject->FileRead(
|
|
Location => $Location,
|
|
Mode => 'binmode',
|
|
Type => 'Local',
|
|
Result => 'SCALAR',
|
|
);
|
|
|
|
if ( !$Content ) {
|
|
return $LayoutObject->ErrorScreen(
|
|
Message => $LayoutObject->{LanguageObject}->Translate( 'File %s could not be read!', $Location ),
|
|
);
|
|
}
|
|
|
|
my $Success = $MainObject->FileDelete(
|
|
Location => $Location,
|
|
Type => 'Local',
|
|
);
|
|
|
|
if ( !$Success ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Priority => 'error',
|
|
Message => "File $Location could not be deleted!",
|
|
);
|
|
}
|
|
|
|
rmdir $TempDir;
|
|
|
|
return $LayoutObject->Attachment(
|
|
Filename => $Filename,
|
|
ContentType => 'application/octet-stream; charset=' . $LayoutObject->{UserCharset},
|
|
Content => $$Content,
|
|
);
|
|
}
|
|
|
|
sub _SendSupportBundle {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
|
|
my $LogObject = $Kernel::OM->Get('Kernel::System::Log');
|
|
my $Filename = $ParamObject->GetParam( Param => 'Filename' ) || '';
|
|
my $RandomID = $ParamObject->GetParam( Param => 'RandomID' ) || '';
|
|
my $Success;
|
|
|
|
if ($Filename) {
|
|
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
|
|
my $TempDir = $ConfigObject->Get('TempDir')
|
|
. '/SupportBundleDownloadCache/'
|
|
. $RandomID;
|
|
my $Location = $TempDir . '/' . $Filename;
|
|
|
|
my $MainObject = $Kernel::OM->Get('Kernel::System::Main');
|
|
|
|
my $Content = $MainObject->FileRead(
|
|
Location => $Location,
|
|
Mode => 'binmode',
|
|
Type => 'Local',
|
|
Result => 'SCALAR',
|
|
);
|
|
|
|
if ($Content) {
|
|
|
|
$Success = $MainObject->FileDelete(
|
|
Location => $Location,
|
|
Type => 'Local',
|
|
);
|
|
|
|
if ( !$Success ) {
|
|
$LogObject->Log(
|
|
Priority => 'error',
|
|
Message => "File $Location could not be deleted!",
|
|
);
|
|
}
|
|
|
|
rmdir $TempDir;
|
|
|
|
my %RegistrationInfo = $Kernel::OM->Get('Kernel::System::Registration')->RegistrationDataGet(
|
|
Extended => 1,
|
|
);
|
|
|
|
my %Data;
|
|
|
|
if (%RegistrationInfo) {
|
|
my $State = $RegistrationInfo{State} || '';
|
|
if ( $State && lc $State eq 'registered' ) {
|
|
$State = 'active';
|
|
}
|
|
|
|
%Data = (
|
|
%{ $RegistrationInfo{System} },
|
|
State => $State,
|
|
APIVersion => $RegistrationInfo{APIVersion},
|
|
APIKey => $RegistrationInfo{APIKey},
|
|
LastUpdateID => $RegistrationInfo{LastUpdateID},
|
|
RegistrationKey => $RegistrationInfo{UniqueID},
|
|
SupportDataSending => $RegistrationInfo{SupportDataSending},
|
|
Type => $RegistrationInfo{Type},
|
|
Description => $RegistrationInfo{Description},
|
|
);
|
|
}
|
|
|
|
# get user data
|
|
my %User = $Kernel::OM->Get('Kernel::System::User')->GetUserData(
|
|
UserID => $Self->{UserID},
|
|
Cached => 1,
|
|
);
|
|
|
|
# get sender email address
|
|
my $SenderAddress = '';
|
|
if ( $User{UserEmail} && $User{UserEmail} !~ /root\@localhost/ ) {
|
|
$SenderAddress = $User{UserEmail};
|
|
}
|
|
elsif (
|
|
$ConfigObject->Get('AdminEmail')
|
|
&& $ConfigObject->Get('AdminEmail') !~ /root\@localhost/
|
|
&& $ConfigObject->Get('AdminEmail') !~ /admin\@example.com/
|
|
)
|
|
{
|
|
$SenderAddress = $ConfigObject->Get('AdminEmail');
|
|
}
|
|
|
|
my $SenderName = $User{UserFullname};
|
|
|
|
my $Body;
|
|
|
|
$Body = "Sender:$SenderName\n";
|
|
$Body .= "Email:$SenderAddress\n";
|
|
|
|
if (%Data) {
|
|
for my $Key ( sort keys %Data ) {
|
|
my $ItemValue = $Data{$Key} || '';
|
|
$Body .= "$Key:$ItemValue\n";
|
|
}
|
|
}
|
|
else {
|
|
$Body .= "Not registered\n";
|
|
}
|
|
|
|
my $Result = $Kernel::OM->Get('Kernel::System::Email')->Send(
|
|
From => $SenderAddress,
|
|
To => 'SupportBundle@otrs.com',
|
|
Subject => 'Support::Bundle::Email',
|
|
Type => 'text/plain',
|
|
Charset => 'utf-8',
|
|
Body => $Body,
|
|
CustomHeaders => {
|
|
'X-OTRS-RegistrationKey' => $Data{'RegistrationKey'} || 'Not registered',
|
|
},
|
|
Attachment => [
|
|
{
|
|
Filename => $Filename,
|
|
Content => $Content,
|
|
ContentType => 'application/octet-stream',
|
|
Disposition => 'attachment',
|
|
},
|
|
],
|
|
);
|
|
|
|
if ( $Result->{Success} ) {
|
|
$Success = 1;
|
|
}
|
|
}
|
|
else {
|
|
$LogObject->Log(
|
|
Priority => 'error',
|
|
Message => "$Filename could not be read!",
|
|
);
|
|
}
|
|
}
|
|
else {
|
|
$LogObject->Log(
|
|
Priority => 'error',
|
|
Message => "Need Filename",
|
|
);
|
|
}
|
|
|
|
my $JSONString = $Kernel::OM->Get('Kernel::System::JSON')->Encode(
|
|
Data => {
|
|
Success => $Success || '',
|
|
},
|
|
);
|
|
|
|
return $Kernel::OM->Get('Kernel::Output::HTML::Layout')->Attachment(
|
|
ContentType => 'text/html',
|
|
Content => $JSONString,
|
|
Type => 'inline',
|
|
NoCache => 1,
|
|
);
|
|
}
|
|
|
|
1;
|