This commit is contained in:
2024-10-14 00:08:40 +02:00
parent dbfba56f66
commit 1462d52e13
4572 changed files with 2658864 additions and 0 deletions

View File

@@ -0,0 +1,570 @@
# --
# 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;