init III
This commit is contained in:
1229
Perl OTRS/Kernel/System/Web/InterfaceAgent.pm
Normal file
1229
Perl OTRS/Kernel/System/Web/InterfaceAgent.pm
Normal file
File diff suppressed because it is too large
Load Diff
1475
Perl OTRS/Kernel/System/Web/InterfaceCustomer.pm
Normal file
1475
Perl OTRS/Kernel/System/Web/InterfaceCustomer.pm
Normal file
File diff suppressed because it is too large
Load Diff
171
Perl OTRS/Kernel/System/Web/InterfaceInstaller.pm
Normal file
171
Perl OTRS/Kernel/System/Web/InterfaceInstaller.pm
Normal file
@@ -0,0 +1,171 @@
|
||||
# --
|
||||
# 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::System::Web::InterfaceInstaller;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Kernel::Language qw(Translatable);
|
||||
|
||||
our @ObjectDependencies = (
|
||||
'Kernel::Config',
|
||||
'Kernel::Output::HTML::Layout',
|
||||
'Kernel::System::Log',
|
||||
'Kernel::System::Main',
|
||||
'Kernel::System::Web::Request',
|
||||
);
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::System::Web::InterfaceInstaller - the installer web interface
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
the global installer web interface
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
create installer web interface object
|
||||
|
||||
use Kernel::System::Web::InterfaceInstaller;
|
||||
|
||||
my $Debug = 0;
|
||||
my $Interface = Kernel::System::Web::InterfaceInstaller->new( Debug => $Debug );
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
# allocate new hash for object
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
# get debug level
|
||||
$Self->{Debug} = $Param{Debug} || 0;
|
||||
|
||||
$Kernel::OM->ObjectParamAdd(
|
||||
'Kernel::System::Log' => {
|
||||
LogPrefix => $Kernel::OM->Get('Kernel::Config')->Get('CGILogPrefix') || 'Installer',
|
||||
},
|
||||
'Kernel::Output::HTML::Layout' => {
|
||||
InstallerOnly => 1,
|
||||
},
|
||||
'Kernel::System::Web::Request' => {
|
||||
WebRequest => $Param{WebRequest} || 0,
|
||||
},
|
||||
);
|
||||
|
||||
# debug info
|
||||
if ( $Self->{Debug} ) {
|
||||
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'debug',
|
||||
Message => 'Global handle started...',
|
||||
);
|
||||
}
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
execute the object
|
||||
|
||||
$Interface->Run();
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my $Self = shift;
|
||||
|
||||
# get common framework params
|
||||
my %Param;
|
||||
|
||||
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
|
||||
|
||||
$Param{Action} = $ParamObject->GetParam( Param => 'Action' ) || 'Installer';
|
||||
$Param{Subaction} = $ParamObject->GetParam( Param => 'Subaction' ) || '';
|
||||
$Param{NextScreen} = $ParamObject->GetParam( Param => 'NextScreen' ) || '';
|
||||
|
||||
$Kernel::OM->ObjectParamAdd(
|
||||
'Kernel::Output::HTML::Layout' => {
|
||||
%Param,
|
||||
},
|
||||
);
|
||||
|
||||
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
||||
|
||||
# check secure mode
|
||||
if ( $Kernel::OM->Get('Kernel::Config')->Get('SecureMode') ) {
|
||||
print $LayoutObject->Header();
|
||||
print $LayoutObject->Error(
|
||||
Message => Translatable('SecureMode active!'),
|
||||
Comment => Translatable(
|
||||
'If you want to re-run the Installer, disable the SecureMode in the SysConfig.'
|
||||
),
|
||||
);
|
||||
print $LayoutObject->Footer();
|
||||
}
|
||||
|
||||
# run modules if a version value exists
|
||||
elsif ( $Kernel::OM->Get('Kernel::System::Main')->Require("Kernel::Modules::$Param{Action}") ) {
|
||||
|
||||
# proof of concept! - create $GenericObject
|
||||
my $GenericObject = ( 'Kernel::Modules::' . $Param{Action} )->new(
|
||||
%Param,
|
||||
Debug => $Self->{Debug},
|
||||
);
|
||||
|
||||
print $GenericObject->Run();
|
||||
}
|
||||
|
||||
# else print an error screen
|
||||
else {
|
||||
|
||||
# create new LayoutObject with '%Param'
|
||||
print $LayoutObject->Header();
|
||||
print $LayoutObject->Error(
|
||||
Message => $LayoutObject->{LanguageObject}->Translate( 'Action "%s" not found!', $Param{Action} ),
|
||||
Comment => Translatable('Please contact the administrator.'),
|
||||
);
|
||||
print $LayoutObject->Footer();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub DESTROY {
|
||||
my $Self = shift;
|
||||
|
||||
# debug info
|
||||
if ( $Self->{Debug} ) {
|
||||
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'debug',
|
||||
Message => 'Global handle stopped.',
|
||||
);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 TERMS AND CONDITIONS
|
||||
|
||||
This software is part of the OTRS project (L<https://otrs.org/>).
|
||||
|
||||
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 L<https://www.gnu.org/licenses/gpl-3.0.txt>.
|
||||
|
||||
=cut
|
||||
297
Perl OTRS/Kernel/System/Web/InterfacePublic.pm
Normal file
297
Perl OTRS/Kernel/System/Web/InterfacePublic.pm
Normal file
@@ -0,0 +1,297 @@
|
||||
# --
|
||||
# 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::System::Web::InterfacePublic;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Kernel::Language qw(Translatable);
|
||||
|
||||
our @ObjectDependencies = (
|
||||
'Kernel::Config',
|
||||
'Kernel::Output::HTML::Layout',
|
||||
'Kernel::System::DB',
|
||||
'Kernel::System::Log',
|
||||
'Kernel::System::Main',
|
||||
'Kernel::System::Web::Request',
|
||||
);
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::System::Web::InterfacePublic - the public web interface
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
the global public web interface
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
create public web interface object
|
||||
|
||||
use Kernel::System::Web::InterfacePublic;
|
||||
|
||||
my $Debug = 0;
|
||||
my $Interface = Kernel::System::Web::InterfacePublic->new(
|
||||
Debug => $Debug,
|
||||
WebRequest => CGI::Fast->new(), # optional, e. g. if fast cgi is used, the CGI object is already provided
|
||||
);
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
# allocate new hash for object
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
# get debug level
|
||||
$Self->{Debug} = $Param{Debug} || 0;
|
||||
|
||||
# performance log
|
||||
$Self->{PerformanceLogStart} = time();
|
||||
|
||||
$Kernel::OM->ObjectParamAdd(
|
||||
'Kernel::System::Log' => {
|
||||
LogPrefix => $Kernel::OM->Get('Kernel::Config')->Get('CGILogPrefix'),
|
||||
},
|
||||
'Kernel::System::Web::Request' => {
|
||||
WebRequest => $Param{WebRequest} || 0,
|
||||
},
|
||||
);
|
||||
|
||||
# debug info
|
||||
if ( $Self->{Debug} ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'debug',
|
||||
Message => 'Global handle started...',
|
||||
);
|
||||
}
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Run()
|
||||
|
||||
execute the object
|
||||
|
||||
$Interface->Run();
|
||||
|
||||
=cut
|
||||
|
||||
sub Run {
|
||||
my $Self = shift;
|
||||
|
||||
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
||||
|
||||
my $QueryString = $ENV{QUERY_STRING} || '';
|
||||
|
||||
# Check if https forcing is active, and redirect if needed.
|
||||
if ( $ConfigObject->Get('HTTPSForceRedirect') ) {
|
||||
|
||||
# Some web servers do not set HTTPS environment variable, so it's not possible to easily know if we are using
|
||||
# https protocol. Look also for similarly named keys in environment hash, since this should prevent loops in
|
||||
# certain cases.
|
||||
if (
|
||||
(
|
||||
!defined $ENV{HTTPS}
|
||||
&& !grep {/^HTTPS(?:_|$)/} keys %ENV
|
||||
)
|
||||
|| $ENV{HTTPS} ne 'on'
|
||||
)
|
||||
{
|
||||
my $Host = $ENV{HTTP_HOST} || $ConfigObject->Get('FQDN');
|
||||
|
||||
# Redirect with 301 code. Add two new lines at the end, so HTTP headers are validated correctly.
|
||||
print "Status: 301 Moved Permanently\nLocation: https://$Host$ENV{REQUEST_URI}\n\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
|
||||
|
||||
my %Param;
|
||||
|
||||
# get session id
|
||||
$Param{SessionName} = $ConfigObject->Get('CustomerPanelSessionName') || 'CSID';
|
||||
$Param{SessionID} = $ParamObject->GetParam( Param => $Param{SessionName} ) || '';
|
||||
|
||||
# drop old session id (if exists)
|
||||
$QueryString =~ s/(\?|&|;|)$Param{SessionName}(=&|=;|=.+?&|=.+?$)/;/g;
|
||||
|
||||
# define framework params
|
||||
my $FrameworkParams = {
|
||||
Lang => '',
|
||||
Action => '',
|
||||
Subaction => '',
|
||||
RequestedURL => $QueryString,
|
||||
};
|
||||
for my $Key ( sort keys %{$FrameworkParams} ) {
|
||||
$Param{$Key} = $ParamObject->GetParam( Param => $Key )
|
||||
|| $FrameworkParams->{$Key};
|
||||
}
|
||||
|
||||
# validate language
|
||||
if ( $Param{Lang} && $Param{Lang} !~ m{\A[a-z]{2}(?:_[A-Z]{2})?\z}xms ) {
|
||||
delete $Param{Lang};
|
||||
}
|
||||
|
||||
# Check if the browser sends the SessionID cookie and set the SessionID-cookie
|
||||
# as SessionID! GET or POST SessionID have the lowest priority.
|
||||
if ( $ConfigObject->Get('SessionUseCookie') ) {
|
||||
$Param{SessionIDCookie} = $ParamObject->GetCookie( Key => $Param{SessionName} );
|
||||
if ( $Param{SessionIDCookie} ) {
|
||||
$Param{SessionID} = $Param{SessionIDCookie};
|
||||
}
|
||||
}
|
||||
|
||||
# get common application and add-on application params
|
||||
# Important!
|
||||
# This must be done before creating the layout object,
|
||||
# because otherwise the action parameter is not passed and then
|
||||
# the loader can not load module specific JavaScript and CSS
|
||||
# For details see bug: http://bugs.otrs.org/show_bug.cgi?id=6471
|
||||
my %CommonObjectParam = %{ $ConfigObject->Get('PublicFrontend::CommonParam') };
|
||||
for my $Key ( sort keys %CommonObjectParam ) {
|
||||
$Param{$Key} = $ParamObject->GetParam( Param => $Key ) || $CommonObjectParam{$Key};
|
||||
}
|
||||
|
||||
# security check Action Param (replace non-word chars)
|
||||
$Param{Action} =~ s/\W//g;
|
||||
|
||||
$Kernel::OM->ObjectParamAdd(
|
||||
'Kernel::Output::HTML::Layout' => {
|
||||
%Param,
|
||||
SessionIDCookie => 1,
|
||||
Debug => $Self->{Debug},
|
||||
},
|
||||
);
|
||||
|
||||
my $DBCanConnect = $Kernel::OM->Get('Kernel::System::DB')->Connect();
|
||||
|
||||
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
||||
|
||||
if ( !$DBCanConnect ) {
|
||||
$LayoutObject->CustomerFatalError(
|
||||
Comment => Translatable('Please contact the administrator.'),
|
||||
);
|
||||
}
|
||||
if ( $ParamObject->Error() ) {
|
||||
$LayoutObject->CustomerFatalError(
|
||||
Message => $ParamObject->Error(),
|
||||
Comment => Translatable('Please contact the administrator.'),
|
||||
);
|
||||
}
|
||||
|
||||
# run modules if a version value exists
|
||||
if ( !$Kernel::OM->Get('Kernel::System::Main')->Require("Kernel::Modules::$Param{Action}") ) {
|
||||
$LayoutObject->CustomerFatalError(
|
||||
Comment => Translatable('Please contact the administrator.'),
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# module registry
|
||||
my $ModuleReg = $ConfigObject->Get('PublicFrontend::Module')->{ $Param{Action} };
|
||||
if ( !$ModuleReg ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message =>
|
||||
"Module Kernel::Modules::$Param{Action} not registered in Kernel/Config.pm!",
|
||||
);
|
||||
$LayoutObject->CustomerFatalError(
|
||||
Comment => Translatable('Please contact the administrator.'),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
# debug info
|
||||
if ( $Self->{Debug} ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'debug',
|
||||
Message => 'Kernel::Modules::' . $Param{Action} . '->new',
|
||||
);
|
||||
}
|
||||
|
||||
my $FrontendObject = ( 'Kernel::Modules::' . $Param{Action} )->new(
|
||||
UserID => 1,
|
||||
%Param,
|
||||
Debug => $Self->{Debug},
|
||||
);
|
||||
|
||||
# debug info
|
||||
if ( $Self->{Debug} ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'debug',
|
||||
Message => 'Kernel::Modules::' . $Param{Action} . '->run',
|
||||
);
|
||||
}
|
||||
|
||||
# ->Run $Action with $FrontendObject
|
||||
$LayoutObject->Print( Output => \$FrontendObject->Run() );
|
||||
|
||||
# log request time
|
||||
if ( $ConfigObject->Get('PerformanceLog') ) {
|
||||
if ( ( !$QueryString && $Param{Action} ) || $QueryString !~ /Action=/ ) {
|
||||
$QueryString = 'Action=' . $Param{Action} . '&Subaction=' . $Param{Subaction};
|
||||
}
|
||||
my $File = $ConfigObject->Get('PerformanceLog::File');
|
||||
## no critic
|
||||
if ( open my $Out, '>>', $File ) {
|
||||
## use critic
|
||||
print $Out time()
|
||||
. '::Public::'
|
||||
. ( time() - $Self->{PerformanceLogStart} )
|
||||
. "::-::$QueryString\n";
|
||||
close $Out;
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'debug',
|
||||
Message => 'Response::Public: '
|
||||
. ( time() - $Self->{PerformanceLogStart} )
|
||||
. "s taken (URL:$QueryString)",
|
||||
);
|
||||
}
|
||||
else {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => "Can't write $File: $!",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub DESTROY {
|
||||
my $Self = shift;
|
||||
|
||||
# debug info
|
||||
if ( $Self->{Debug} ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'debug',
|
||||
Message => 'Global handle stopped.',
|
||||
);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 TERMS AND CONDITIONS
|
||||
|
||||
This software is part of the OTRS project (L<https://otrs.org/>).
|
||||
|
||||
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 L<https://www.gnu.org/licenses/gpl-3.0.txt>.
|
||||
|
||||
=cut
|
||||
570
Perl OTRS/Kernel/System/Web/Request.pm
Normal file
570
Perl OTRS/Kernel/System/Web/Request.pm
Normal 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::System::Web::Request;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use CGI ();
|
||||
use CGI::Carp;
|
||||
use File::Path qw();
|
||||
|
||||
use Kernel::System::VariableCheck qw(:all);
|
||||
|
||||
our @ObjectDependencies = (
|
||||
'Kernel::Config',
|
||||
'Kernel::System::CheckItem',
|
||||
'Kernel::System::Encode',
|
||||
'Kernel::System::Web::UploadCache',
|
||||
'Kernel::System::FormDraft',
|
||||
'Kernel::System::Main',
|
||||
);
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::System::Web::Request - global CGI interface
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
All cgi param functions.
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
create param object. Do not use it directly, instead use:
|
||||
|
||||
use Kernel::System::ObjectManager;
|
||||
local $Kernel::OM = Kernel::System::ObjectManager->new(
|
||||
'Kernel::System::Web::Request' => {
|
||||
WebRequest => CGI::Fast->new(), # optional, e. g. if fast cgi is used
|
||||
}
|
||||
);
|
||||
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
|
||||
|
||||
If Kernel::System::Web::Request is instantiated several times, they will share the
|
||||
same CGI data (this can be helpful in filters which do not have access to the
|
||||
ParamObject, for example.
|
||||
|
||||
If you need to reset the CGI data before creating a new instance, use
|
||||
|
||||
CGI::initialize_globals();
|
||||
|
||||
before calling Kernel::System::Web::Request->new();
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
# allocate new hash for object
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
# get config object
|
||||
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
||||
|
||||
# max 5 MB posts
|
||||
$CGI::POST_MAX = $ConfigObject->Get('WebMaxFileUpload') || 1024 * 1024 * 5; ## no critic
|
||||
|
||||
# query object (in case use already existing WebRequest, e. g. fast cgi)
|
||||
$Self->{Query} = $Param{WebRequest} || CGI->new();
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
=head2 Error()
|
||||
|
||||
to get the error back
|
||||
|
||||
if ( $ParamObject->Error() ) {
|
||||
print STDERR $ParamObject->Error() . "\n";
|
||||
}
|
||||
|
||||
=cut
|
||||
|
||||
sub Error {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# Workaround, do not check cgi_error() with perlex, CGI module is not
|
||||
# working with perlex.
|
||||
if ( $ENV{'GATEWAY_INTERFACE'} && $ENV{'GATEWAY_INTERFACE'} =~ /^CGI-PerlEx/ ) {
|
||||
return;
|
||||
}
|
||||
|
||||
return if !$Self->{Query}->cgi_error();
|
||||
## no critic
|
||||
return $Self->{Query}->cgi_error() . ' - POST_MAX=' . ( $CGI::POST_MAX / 1024 ) . 'KB';
|
||||
## use critic
|
||||
}
|
||||
|
||||
=head2 GetParam()
|
||||
|
||||
to get single request parameters. By default, trimming is performed on the data.
|
||||
|
||||
my $Param = $ParamObject->GetParam(
|
||||
Param => 'ID',
|
||||
Raw => 1, # optional, input data is not changed
|
||||
);
|
||||
|
||||
=cut
|
||||
|
||||
sub GetParam {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $Value = $Self->{Query}->param( $Param{Param} );
|
||||
|
||||
# Fallback to query string for mixed requests.
|
||||
my $RequestMethod = $Self->{Query}->request_method() // '';
|
||||
if ( $RequestMethod eq 'POST' && !defined $Value ) {
|
||||
$Value = $Self->{Query}->url_param( $Param{Param} );
|
||||
}
|
||||
|
||||
$Kernel::OM->Get('Kernel::System::Encode')->EncodeInput( \$Value );
|
||||
|
||||
my $Raw = defined $Param{Raw} ? $Param{Raw} : 0;
|
||||
|
||||
if ( !$Raw ) {
|
||||
|
||||
# If it is a plain string, perform trimming
|
||||
if ( ref \$Value eq 'SCALAR' ) {
|
||||
$Kernel::OM->Get('Kernel::System::CheckItem')->StringClean(
|
||||
StringRef => \$Value,
|
||||
TrimLeft => 1,
|
||||
TrimRight => 1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $Value;
|
||||
}
|
||||
|
||||
=head2 GetParamNames()
|
||||
|
||||
to get names of all parameters passed to the script.
|
||||
|
||||
my @ParamNames = $ParamObject->GetParamNames();
|
||||
|
||||
Example:
|
||||
|
||||
Called URL: index.pl?Action=AdminSystemConfiguration;Subaction=Save;Name=Config::Option::Valid
|
||||
|
||||
my @ParamNames = $ParamObject->GetParamNames();
|
||||
print join " :: ", @ParamNames;
|
||||
#prints Action :: Subaction :: Name
|
||||
|
||||
=cut
|
||||
|
||||
sub GetParamNames {
|
||||
my $Self = shift;
|
||||
|
||||
# fetch all names
|
||||
my @ParamNames = $Self->{Query}->param();
|
||||
|
||||
# Fallback to query string for mixed requests.
|
||||
my $RequestMethod = $Self->{Query}->request_method() // '';
|
||||
if ( $RequestMethod eq 'POST' ) {
|
||||
my %POSTNames;
|
||||
@POSTNames{@ParamNames} = @ParamNames;
|
||||
my @GetNames = $Self->{Query}->url_param();
|
||||
GETNAME:
|
||||
for my $GetName (@GetNames) {
|
||||
next GETNAME if !defined $GetName;
|
||||
push @ParamNames, $GetName if !exists $POSTNames{$GetName};
|
||||
}
|
||||
}
|
||||
|
||||
for my $Name (@ParamNames) {
|
||||
$Kernel::OM->Get('Kernel::System::Encode')->EncodeInput( \$Name );
|
||||
}
|
||||
|
||||
return @ParamNames;
|
||||
}
|
||||
|
||||
=head2 GetArray()
|
||||
|
||||
to get array request parameters.
|
||||
By default, trimming is performed on the data.
|
||||
|
||||
my @Param = $ParamObject->GetArray(
|
||||
Param => 'ID',
|
||||
Raw => 1, # optional, input data is not changed
|
||||
);
|
||||
|
||||
=cut
|
||||
|
||||
sub GetArray {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my @Values = $Self->{Query}->multi_param( $Param{Param} );
|
||||
|
||||
# Fallback to query string for mixed requests.
|
||||
my $RequestMethod = $Self->{Query}->request_method() // '';
|
||||
if ( $RequestMethod eq 'POST' && !@Values ) {
|
||||
@Values = $Self->{Query}->url_param( $Param{Param} );
|
||||
}
|
||||
|
||||
$Kernel::OM->Get('Kernel::System::Encode')->EncodeInput( \@Values );
|
||||
|
||||
my $Raw = defined $Param{Raw} ? $Param{Raw} : 0;
|
||||
|
||||
if ( !$Raw ) {
|
||||
|
||||
# get check item object
|
||||
my $CheckItemObject = $Kernel::OM->Get('Kernel::System::CheckItem');
|
||||
|
||||
VALUE:
|
||||
for my $Value (@Values) {
|
||||
|
||||
# don't validate CGI::File::Temp objects from file uploads
|
||||
next VALUE if !$Value || ref \$Value ne 'SCALAR';
|
||||
|
||||
$CheckItemObject->StringClean(
|
||||
StringRef => \$Value,
|
||||
TrimLeft => 1,
|
||||
TrimRight => 1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return @Values;
|
||||
}
|
||||
|
||||
=head2 GetUploadAll()
|
||||
|
||||
gets file upload data.
|
||||
|
||||
my %File = $ParamObject->GetUploadAll(
|
||||
Param => 'FileParam', # the name of the request parameter containing the file data
|
||||
);
|
||||
|
||||
returns (
|
||||
Filename => 'abc.txt',
|
||||
ContentType => 'text/plain',
|
||||
Content => 'Some text',
|
||||
);
|
||||
|
||||
=cut
|
||||
|
||||
sub GetUploadAll {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# get upload
|
||||
my $Upload = $Self->{Query}->upload( $Param{Param} );
|
||||
return if !$Upload;
|
||||
|
||||
# get real file name
|
||||
my $UploadFilenameOrig = $Self->GetParam( Param => $Param{Param} ) || 'unknown';
|
||||
|
||||
my $NewFileName = "$UploadFilenameOrig"; # use "" to get filename of anony. object
|
||||
$Kernel::OM->Get('Kernel::System::Encode')->EncodeInput( \$NewFileName );
|
||||
|
||||
# replace all devices like c: or d: and dirs for IE!
|
||||
$NewFileName =~ s/.:\\(.*)/$1/g;
|
||||
$NewFileName =~ s/.*\\(.+?)/$1/g;
|
||||
|
||||
# return a string
|
||||
my $Content = '';
|
||||
while (<$Upload>) {
|
||||
$Content .= $_;
|
||||
}
|
||||
close $Upload;
|
||||
|
||||
my $ContentType = $Self->_GetUploadInfo(
|
||||
Filename => $UploadFilenameOrig,
|
||||
Header => 'Content-Type',
|
||||
);
|
||||
|
||||
return (
|
||||
Filename => $NewFileName,
|
||||
Content => $Content,
|
||||
ContentType => $ContentType,
|
||||
);
|
||||
}
|
||||
|
||||
sub _GetUploadInfo {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# get file upload info
|
||||
my $FileInfo = $Self->{Query}->uploadInfo( $Param{Filename} );
|
||||
|
||||
# return if no upload info exists
|
||||
return 'application/octet-stream' if !$FileInfo;
|
||||
|
||||
# return if no content type of upload info exists
|
||||
return 'application/octet-stream' if !$FileInfo->{ $Param{Header} };
|
||||
|
||||
# return content type of upload info
|
||||
return $FileInfo->{ $Param{Header} };
|
||||
}
|
||||
|
||||
=head2 SetCookie()
|
||||
|
||||
set a cookie
|
||||
|
||||
$ParamObject->SetCookie(
|
||||
Key => ID,
|
||||
Value => 123456,
|
||||
Expires => '+3660s',
|
||||
Path => 'otrs/', # optional, only allow cookie for given path
|
||||
Secure => 1, # optional, set secure attribute to disable cookie on HTTP (HTTPS only)
|
||||
HTTPOnly => 1, # optional, sets HttpOnly attribute of cookie to prevent access via JavaScript
|
||||
);
|
||||
|
||||
=cut
|
||||
|
||||
sub SetCookie {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
$Param{Path} ||= '';
|
||||
|
||||
return $Self->{Query}->cookie(
|
||||
-name => $Param{Key},
|
||||
-value => $Param{Value},
|
||||
-expires => $Param{Expires},
|
||||
-secure => $Param{Secure} || '',
|
||||
-httponly => $Param{HTTPOnly} || '',
|
||||
-path => '/' . $Param{Path},
|
||||
);
|
||||
}
|
||||
|
||||
=head2 GetCookie()
|
||||
|
||||
get a cookie
|
||||
|
||||
my $String = $ParamObject->GetCookie(
|
||||
Key => ID,
|
||||
);
|
||||
|
||||
=cut
|
||||
|
||||
sub GetCookie {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
return $Self->{Query}->cookie( $Param{Key} );
|
||||
}
|
||||
|
||||
=head2 IsAJAXRequest()
|
||||
|
||||
checks if the current request was sent by AJAX
|
||||
|
||||
my $IsAJAXRequest = $ParamObject->IsAJAXRequest();
|
||||
|
||||
=cut
|
||||
|
||||
sub IsAJAXRequest {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
return ( $Self->{Query}->http('X-Requested-With') // '' ) eq 'XMLHttpRequest' ? 1 : 0;
|
||||
}
|
||||
|
||||
=head2 LoadFormDraft()
|
||||
|
||||
Load specified draft.
|
||||
This will read stored draft data and inject it into the param object
|
||||
for transparent use by frontend module.
|
||||
|
||||
my $FormDraftID = $ParamObject->LoadFormDraft(
|
||||
FormDraftID => 123,
|
||||
UserID => 1,
|
||||
);
|
||||
|
||||
=cut
|
||||
|
||||
sub LoadFormDraft {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
return if !$Param{FormDraftID} || !$Param{UserID};
|
||||
|
||||
# get draft data
|
||||
my $FormDraft = $Kernel::OM->Get('Kernel::System::FormDraft')->FormDraftGet(
|
||||
FormDraftID => $Param{FormDraftID},
|
||||
UserID => $Param{UserID},
|
||||
);
|
||||
return if !IsHashRefWithData($FormDraft);
|
||||
|
||||
# Verify action.
|
||||
my $Action = $Self->GetParam( Param => 'Action' );
|
||||
return if $FormDraft->{Action} ne $Action;
|
||||
|
||||
# add draft name to form data
|
||||
$FormDraft->{FormData}->{FormDraftTitle} = $FormDraft->{Title};
|
||||
|
||||
# create FormID and add to form data
|
||||
my $FormID = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDCreate();
|
||||
$FormDraft->{FormData}->{FormID} = $FormID;
|
||||
|
||||
# set form data to param object, depending on type
|
||||
KEY:
|
||||
for my $Key ( sort keys %{ $FormDraft->{FormData} } ) {
|
||||
my $Value = $FormDraft->{FormData}->{$Key} // '';
|
||||
|
||||
# array value
|
||||
if ( IsArrayRefWithData($Value) ) {
|
||||
$Self->{Query}->param(
|
||||
-name => $Key,
|
||||
-values => $Value,
|
||||
);
|
||||
next KEY;
|
||||
}
|
||||
|
||||
# scalar value
|
||||
$Self->{Query}->param(
|
||||
-name => $Key,
|
||||
-value => $Value,
|
||||
);
|
||||
}
|
||||
|
||||
# add UploadCache data
|
||||
my $UploadCacheObject = $Kernel::OM->Get('Kernel::System::Web::UploadCache');
|
||||
for my $File ( @{ $FormDraft->{FileData} } ) {
|
||||
return if !$UploadCacheObject->FormIDAddFile(
|
||||
%{$File},
|
||||
FormID => $FormID,
|
||||
);
|
||||
}
|
||||
|
||||
return $Param{FormDraftID};
|
||||
}
|
||||
|
||||
=head2 SaveFormDraft()
|
||||
|
||||
Create or replace draft using data from param object and upload cache.
|
||||
Specified params can be overwritten if necessary.
|
||||
|
||||
my $FormDraftID = $ParamObject->SaveFormDraft(
|
||||
UserID => 1
|
||||
ObjectType => 'Ticket',
|
||||
ObjectID => 123,
|
||||
OverrideParams => { # optional, can contain strings and array references
|
||||
Subaction => undef,
|
||||
UserID => 1,
|
||||
CustomParam => [ 1, 2, 3, ],
|
||||
...
|
||||
},
|
||||
);
|
||||
|
||||
=cut
|
||||
|
||||
sub SaveFormDraft {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# check params
|
||||
return if !$Param{UserID} || !$Param{ObjectType} || !IsInteger( $Param{ObjectID} );
|
||||
|
||||
# gather necessary data for backend
|
||||
my %MetaParams;
|
||||
for my $Param (qw(Action FormDraftID FormDraftTitle FormID)) {
|
||||
$MetaParams{$Param} = $Self->GetParam(
|
||||
Param => $Param,
|
||||
);
|
||||
}
|
||||
return if !$MetaParams{Action};
|
||||
|
||||
# determine session name param (SessionUseCookie = 0) for exclusion
|
||||
my $SessionName = $Kernel::OM->Get('Kernel::Config')->Get('SessionName') || 'SessionID';
|
||||
|
||||
# compile override list
|
||||
my %OverrideParams = IsHashRefWithData( $Param{OverrideParams} ) ? %{ $Param{OverrideParams} } : ();
|
||||
|
||||
# these params must always be excluded for safety, they take precedence
|
||||
for my $Name (
|
||||
qw(Action ChallengeToken FormID FormDraftID FormDraftTitle FormDraftAction LoadFormDraftID),
|
||||
$SessionName
|
||||
)
|
||||
{
|
||||
$OverrideParams{$Name} = undef;
|
||||
}
|
||||
|
||||
# Gather all params.
|
||||
# Exclude, add or override by using OverrideParams if necessary.
|
||||
my @ParamNames = $Self->GetParamNames();
|
||||
my %ParamSeen;
|
||||
my %FormData;
|
||||
PARAM:
|
||||
for my $Param ( @ParamNames, sort keys %OverrideParams ) {
|
||||
next PARAM if $ParamSeen{$Param}++;
|
||||
my $Value;
|
||||
|
||||
# check for overrides first
|
||||
if ( exists $OverrideParams{$Param} ) {
|
||||
|
||||
# allow only strings and array references as value
|
||||
if (
|
||||
IsStringWithData( $OverrideParams{$Param} )
|
||||
|| IsArrayRefWithData( $OverrideParams{$Param} )
|
||||
)
|
||||
{
|
||||
$Value = $OverrideParams{$Param};
|
||||
}
|
||||
|
||||
# skip all other parameters (including those specified to be excluded by using 'undef')
|
||||
else {
|
||||
next PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
# get other values from param object
|
||||
if ( !defined $Value ) {
|
||||
my @Values = $Self->GetArray( Param => $Param );
|
||||
next PARAM if !IsArrayRefWithData( \@Values );
|
||||
|
||||
# store single occurances as string
|
||||
if ( scalar @Values == 1 ) {
|
||||
$Value = $Values[0];
|
||||
}
|
||||
|
||||
# store multiple occurances as array reference
|
||||
else {
|
||||
$Value = \@Values;
|
||||
}
|
||||
}
|
||||
|
||||
$FormData{$Param} = $Value;
|
||||
}
|
||||
|
||||
# get files from upload cache
|
||||
my @FileData = $Kernel::OM->Get('Kernel::System::Web::UploadCache')->FormIDGetAllFilesData(
|
||||
FormID => $MetaParams{FormID},
|
||||
);
|
||||
|
||||
# prepare data to add or update draft
|
||||
my %FormDraft = (
|
||||
FormData => \%FormData,
|
||||
FileData => \@FileData,
|
||||
FormDraftID => $MetaParams{FormDraftID},
|
||||
ObjectType => $Param{ObjectType},
|
||||
ObjectID => $Param{ObjectID},
|
||||
Action => $MetaParams{Action},
|
||||
Title => $MetaParams{FormDraftTitle},
|
||||
UserID => $Param{UserID},
|
||||
);
|
||||
|
||||
# update draft
|
||||
if ( $MetaParams{FormDraftID} ) {
|
||||
return if !$Kernel::OM->Get('Kernel::System::FormDraft')->FormDraftUpdate(%FormDraft);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# create new draft
|
||||
return if !$Kernel::OM->Get('Kernel::System::FormDraft')->FormDraftAdd(%FormDraft);
|
||||
return 1;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 TERMS AND CONDITIONS
|
||||
|
||||
This software is part of the OTRS project (L<https://otrs.org/>).
|
||||
|
||||
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 L<https://www.gnu.org/licenses/gpl-3.0.txt>.
|
||||
|
||||
=cut
|
||||
193
Perl OTRS/Kernel/System/Web/UploadCache.pm
Normal file
193
Perl OTRS/Kernel/System/Web/UploadCache.pm
Normal file
@@ -0,0 +1,193 @@
|
||||
# --
|
||||
# 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::System::Web::UploadCache;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our @ObjectDependencies = (
|
||||
'Kernel::Config',
|
||||
);
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Kernel::System::Web::UploadCache - an upload file system cache
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
All upload cache functions.
|
||||
|
||||
=head1 PUBLIC INTERFACE
|
||||
|
||||
=head2 new()
|
||||
|
||||
Don't use the constructor directly, use the ObjectManager instead:
|
||||
|
||||
my $WebUploadCacheObject = $Kernel::OM->Get('Kernel::System::Web::UploadCache');
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
# allocate new hash for object
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
my $GenericModule = $Kernel::OM->Get('Kernel::Config')->Get('WebUploadCacheModule')
|
||||
|| 'Kernel::System::Web::UploadCache::DB';
|
||||
|
||||
# load generator auth module
|
||||
$Self->{Backend} = $Kernel::OM->Get($GenericModule);
|
||||
|
||||
return $Self if $Self->{Backend};
|
||||
return;
|
||||
}
|
||||
|
||||
=head2 FormIDCreate()
|
||||
|
||||
create a new Form ID
|
||||
|
||||
my $FormID = $UploadCacheObject->FormIDCreate();
|
||||
|
||||
=cut
|
||||
|
||||
sub FormIDCreate {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
return $Self->{Backend}->FormIDCreate(%Param);
|
||||
}
|
||||
|
||||
=head2 FormIDRemove()
|
||||
|
||||
remove all data for a provided Form ID
|
||||
|
||||
$UploadCacheObject->FormIDRemove( FormID => 123456 );
|
||||
|
||||
=cut
|
||||
|
||||
sub FormIDRemove {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
return $Self->{Backend}->FormIDRemove(%Param);
|
||||
}
|
||||
|
||||
=head2 FormIDAddFile()
|
||||
|
||||
add a file to a Form ID
|
||||
|
||||
$UploadCacheObject->FormIDAddFile(
|
||||
FormID => 12345,
|
||||
Filename => 'somefile.html',
|
||||
Content => $FileInString,
|
||||
ContentType => 'text/html',
|
||||
Disposition => 'inline', # optional
|
||||
);
|
||||
|
||||
ContentID is optional (automatically generated if not given on disposition = inline)
|
||||
|
||||
$UploadCacheObject->FormIDAddFile(
|
||||
FormID => 12345,
|
||||
Filename => 'somefile.html',
|
||||
Content => $FileInString,
|
||||
ContentID => 'some_id@example.com',
|
||||
ContentType => 'text/html',
|
||||
Disposition => 'inline', # optional
|
||||
);
|
||||
|
||||
=cut
|
||||
|
||||
sub FormIDAddFile {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
return $Self->{Backend}->FormIDAddFile(%Param);
|
||||
}
|
||||
|
||||
=head2 FormIDRemoveFile()
|
||||
|
||||
removes a file from a form id
|
||||
|
||||
$UploadCacheObject->FormIDRemoveFile(
|
||||
FormID => 12345,
|
||||
FileID => 1,
|
||||
);
|
||||
|
||||
=cut
|
||||
|
||||
sub FormIDRemoveFile {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
return $Self->{Backend}->FormIDRemoveFile(%Param);
|
||||
}
|
||||
|
||||
=head2 FormIDGetAllFilesData()
|
||||
|
||||
returns an array with a hash ref of all files for a Form ID
|
||||
|
||||
my @Data = $UploadCacheObject->FormIDGetAllFilesData(
|
||||
FormID => 12345,
|
||||
);
|
||||
|
||||
Return data of on hash is Content, ContentType, ContentID, Filename, Filesize, FileID;
|
||||
|
||||
=cut
|
||||
|
||||
sub FormIDGetAllFilesData {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
return @{ $Self->{Backend}->FormIDGetAllFilesData(%Param) };
|
||||
}
|
||||
|
||||
=head2 FormIDGetAllFilesMeta()
|
||||
|
||||
returns an array with a hash ref of all files for a Form ID
|
||||
|
||||
Note: returns no content, only meta data.
|
||||
|
||||
my @Data = $UploadCacheObject->FormIDGetAllFilesMeta(
|
||||
FormID => 12345,
|
||||
);
|
||||
|
||||
Return data of hash is ContentType, ContentID, Filename, Filesize, FileID;
|
||||
|
||||
=cut
|
||||
|
||||
sub FormIDGetAllFilesMeta {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
return @{ $Self->{Backend}->FormIDGetAllFilesMeta(%Param) };
|
||||
}
|
||||
|
||||
=head2 FormIDCleanUp()
|
||||
|
||||
Removed no longer needed temporary files.
|
||||
|
||||
Each file older than 1 day will be removed.
|
||||
|
||||
$UploadCacheObject->FormIDCleanUp();
|
||||
|
||||
=cut
|
||||
|
||||
sub FormIDCleanUp {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
return $Self->{Backend}->FormIDCleanUp(%Param);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 TERMS AND CONDITIONS
|
||||
|
||||
This software is part of the OTRS project (L<https://otrs.org/>).
|
||||
|
||||
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 L<https://www.gnu.org/licenses/gpl-3.0.txt>.
|
||||
|
||||
=cut
|
||||
268
Perl OTRS/Kernel/System/Web/UploadCache/DB.pm
Normal file
268
Perl OTRS/Kernel/System/Web/UploadCache/DB.pm
Normal file
@@ -0,0 +1,268 @@
|
||||
# --
|
||||
# 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::System::Web::UploadCache::DB;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use MIME::Base64;
|
||||
|
||||
our @ObjectDependencies = (
|
||||
'Kernel::Config',
|
||||
'Kernel::System::DB',
|
||||
'Kernel::System::Encode',
|
||||
'Kernel::System::Log',
|
||||
'Kernel::System::Main',
|
||||
);
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
# allocate new hash for object
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
sub FormIDCreate {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# return requested form id
|
||||
return time() . '.' . rand(12341241);
|
||||
}
|
||||
|
||||
sub FormIDRemove {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
for (qw(FormID)) {
|
||||
if ( !$Param{$_} ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => "Need $_!"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
|
||||
SQL => '
|
||||
DELETE FROM web_upload_cache
|
||||
WHERE form_id = ?',
|
||||
Bind => [ \$Param{FormID} ],
|
||||
);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub FormIDAddFile {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
for (qw(FormID Filename ContentType)) {
|
||||
if ( !$Param{$_} ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => "Need $_!"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$Param{Content} = '' if !defined( $Param{Content} );
|
||||
|
||||
# get file size
|
||||
$Param{Filesize} = bytes::length( $Param{Content} );
|
||||
|
||||
# get database object
|
||||
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
||||
|
||||
# encode attachment if it's a postgresql backend!!!
|
||||
if ( !$DBObject->GetDatabaseFunction('DirectBlob') ) {
|
||||
|
||||
$Kernel::OM->Get('Kernel::System::Encode')->EncodeOutput( \$Param{Content} );
|
||||
|
||||
$Param{Content} = encode_base64( $Param{Content} );
|
||||
}
|
||||
|
||||
# create content id
|
||||
my $ContentID = $Param{ContentID};
|
||||
my $Disposition = $Param{Disposition} || '';
|
||||
if ( !$ContentID && lc $Disposition eq 'inline' ) {
|
||||
|
||||
my $Random = rand 999999;
|
||||
my $FQDN = $Kernel::OM->Get('Kernel::Config')->Get('FQDN');
|
||||
|
||||
$ContentID = "$Disposition$Random.$Param{FormID}\@$FQDN";
|
||||
}
|
||||
|
||||
# write attachment to db
|
||||
my $Time = time();
|
||||
|
||||
return if !$DBObject->Do(
|
||||
SQL => '
|
||||
INSERT INTO web_upload_cache (form_id, filename, content_type, content_size, content,
|
||||
create_time_unix, content_id, disposition)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
|
||||
Bind => [
|
||||
\$Param{FormID}, \$Param{Filename}, \$Param{ContentType}, \$Param{Filesize},
|
||||
\$Param{Content}, \$Time, \$ContentID, \$Param{Disposition}
|
||||
],
|
||||
);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub FormIDRemoveFile {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
for (qw(FormID FileID)) {
|
||||
if ( !$Param{$_} ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => "Need $_!"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
my @Index = @{ $Self->FormIDGetAllFilesMeta(%Param) };
|
||||
|
||||
# finish if files have been already removed by other process
|
||||
return if !@Index;
|
||||
|
||||
my $ID = $Param{FileID} - 1;
|
||||
$Param{Filename} = $Index[$ID]->{Filename};
|
||||
|
||||
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
|
||||
SQL => '
|
||||
DELETE FROM web_upload_cache
|
||||
WHERE form_id = ?
|
||||
AND filename = ?',
|
||||
Bind => [ \$Param{FormID}, \$Param{Filename} ],
|
||||
);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub FormIDGetAllFilesData {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $Counter = 0;
|
||||
my @Data;
|
||||
for (qw(FormID)) {
|
||||
if ( !$Param{$_} ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => "Need $_!"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
# get database object
|
||||
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
||||
|
||||
$DBObject->Prepare(
|
||||
SQL => '
|
||||
SELECT filename, content_type, content_size, content, content_id, disposition
|
||||
FROM web_upload_cache
|
||||
WHERE form_id = ?
|
||||
ORDER BY create_time_unix',
|
||||
Bind => [ \$Param{FormID} ],
|
||||
Encode => [ 1, 1, 1, 0, 1, 1 ],
|
||||
);
|
||||
|
||||
while ( my @Row = $DBObject->FetchrowArray() ) {
|
||||
$Counter++;
|
||||
|
||||
# encode attachment if it's a postgresql backend!!!
|
||||
if ( !$DBObject->GetDatabaseFunction('DirectBlob') ) {
|
||||
$Row[3] = decode_base64( $Row[3] );
|
||||
}
|
||||
|
||||
# add the info
|
||||
push(
|
||||
@Data,
|
||||
{
|
||||
Content => $Row[3],
|
||||
ContentID => $Row[4],
|
||||
ContentType => $Row[1],
|
||||
Filename => $Row[0],
|
||||
Filesize => $Row[2],
|
||||
Disposition => $Row[5],
|
||||
FileID => $Counter,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return \@Data;
|
||||
}
|
||||
|
||||
sub FormIDGetAllFilesMeta {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $Counter = 0;
|
||||
my @Data;
|
||||
for (qw(FormID)) {
|
||||
if ( !$Param{$_} ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => "Need $_!"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
# get database object
|
||||
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
|
||||
|
||||
$DBObject->Prepare(
|
||||
SQL => '
|
||||
SELECT filename, content_type, content_size, content_id, disposition
|
||||
FROM web_upload_cache
|
||||
WHERE form_id = ?
|
||||
ORDER BY create_time_unix',
|
||||
Bind => [ \$Param{FormID} ],
|
||||
);
|
||||
|
||||
while ( my @Row = $DBObject->FetchrowArray() ) {
|
||||
$Counter++;
|
||||
|
||||
# add the info
|
||||
push(
|
||||
@Data,
|
||||
{
|
||||
ContentID => $Row[3],
|
||||
ContentType => $Row[1],
|
||||
Filename => $Row[0],
|
||||
Filesize => $Row[2],
|
||||
Disposition => $Row[4],
|
||||
FileID => $Counter,
|
||||
}
|
||||
);
|
||||
}
|
||||
return \@Data;
|
||||
}
|
||||
|
||||
sub FormIDCleanUp {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
my $CurrentTile = time() - ( 60 * 60 * 24 * 1 );
|
||||
|
||||
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
|
||||
SQL => '
|
||||
DELETE FROM web_upload_cache
|
||||
WHERE create_time_unix < ?',
|
||||
Bind => [ \$CurrentTile ],
|
||||
);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
1;
|
||||
485
Perl OTRS/Kernel/System/Web/UploadCache/FS.pm
Normal file
485
Perl OTRS/Kernel/System/Web/UploadCache/FS.pm
Normal file
@@ -0,0 +1,485 @@
|
||||
# --
|
||||
# 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::System::Web::UploadCache::FS;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our @ObjectDependencies = (
|
||||
'Kernel::Config',
|
||||
'Kernel::System::Log',
|
||||
'Kernel::System::Main',
|
||||
);
|
||||
|
||||
sub new {
|
||||
my ( $Type, %Param ) = @_;
|
||||
|
||||
# allocate new hash for object
|
||||
my $Self = {};
|
||||
bless( $Self, $Type );
|
||||
|
||||
$Self->{TempDir} = $Kernel::OM->Get('Kernel::Config')->Get('TempDir') . '/upload_cache';
|
||||
|
||||
if ( !-d $Self->{TempDir} ) {
|
||||
mkdir $Self->{TempDir};
|
||||
}
|
||||
|
||||
return $Self;
|
||||
}
|
||||
|
||||
sub FormIDCreate {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# return requested form id
|
||||
return time() . '.' . rand(12341241);
|
||||
}
|
||||
|
||||
sub FormIDRemove {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
if ( !$Param{FormID} ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => 'Need FormID!'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
return if !$Self->_FormIDValidate( $Param{FormID} );
|
||||
|
||||
my $Directory = $Self->{TempDir} . '/' . $Param{FormID};
|
||||
|
||||
if ( !-d $Directory ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
# get main object
|
||||
my $MainObject = $Kernel::OM->Get('Kernel::System::Main');
|
||||
|
||||
my @List = $MainObject->DirectoryRead(
|
||||
Directory => $Directory,
|
||||
Filter => "*",
|
||||
);
|
||||
|
||||
my @Data;
|
||||
for my $File (@List) {
|
||||
$MainObject->FileDelete(
|
||||
Location => $File,
|
||||
);
|
||||
}
|
||||
|
||||
if ( !rmdir($Directory) ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => "Can't remove: $Directory: $!!",
|
||||
);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub FormIDAddFile {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
for (qw(FormID Filename ContentType)) {
|
||||
if ( !$Param{$_} ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => "Need $_!"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return if !$Self->_FormIDValidate( $Param{FormID} );
|
||||
|
||||
$Param{Content} = '' if !defined( $Param{Content} );
|
||||
|
||||
# create content id
|
||||
my $ContentID = $Param{ContentID};
|
||||
my $Disposition = $Param{Disposition} || '';
|
||||
if ( !$ContentID && lc $Disposition eq 'inline' ) {
|
||||
|
||||
my $Random = rand 999999;
|
||||
my $FQDN = $Kernel::OM->Get('Kernel::Config')->Get('FQDN');
|
||||
|
||||
$ContentID = "$Disposition$Random.$Param{FormID}\@$FQDN";
|
||||
}
|
||||
|
||||
# create cache subdirectory if not exist
|
||||
my $Directory = $Self->{TempDir} . '/' . $Param{FormID};
|
||||
if ( !-d $Directory ) {
|
||||
|
||||
# Create directory. This could fail if another process creates the
|
||||
# same directory, so don't use the return value.
|
||||
File::Path::mkpath( $Directory, 0, 0770 ); ## no critic
|
||||
|
||||
if ( !-d $Directory ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => "Can't create directory '$Directory': $!",
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
# get main object
|
||||
my $MainObject = $Kernel::OM->Get('Kernel::System::Main');
|
||||
|
||||
# files must readable for creator
|
||||
return if !$MainObject->FileWrite(
|
||||
Directory => $Directory,
|
||||
Filename => "$Param{Filename}",
|
||||
Content => \$Param{Content},
|
||||
Mode => 'binmode',
|
||||
Permission => '640',
|
||||
NoReplace => 1,
|
||||
);
|
||||
return if !$MainObject->FileWrite(
|
||||
Directory => $Directory,
|
||||
Filename => "$Param{Filename}.ContentType",
|
||||
Content => \$Param{ContentType},
|
||||
Mode => 'binmode',
|
||||
Permission => '640',
|
||||
NoReplace => 1,
|
||||
);
|
||||
return if !$MainObject->FileWrite(
|
||||
Directory => $Directory,
|
||||
Filename => "$Param{Filename}.ContentID",
|
||||
Content => \$ContentID,
|
||||
Mode => 'binmode',
|
||||
Permission => '640',
|
||||
NoReplace => 1,
|
||||
);
|
||||
return if !$MainObject->FileWrite(
|
||||
Directory => $Directory,
|
||||
Filename => "$Param{Filename}.Disposition",
|
||||
Content => \$Disposition,
|
||||
Mode => 'binmode',
|
||||
Permission => '644',
|
||||
NoReplace => 1,
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub FormIDRemoveFile {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
for (qw(FormID FileID)) {
|
||||
if ( !$Param{$_} ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => "Need $_!"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return if !$Self->_FormIDValidate( $Param{FormID} );
|
||||
|
||||
my @Index = @{ $Self->FormIDGetAllFilesMeta(%Param) };
|
||||
|
||||
# finish if files have been already removed by other process
|
||||
return if !@Index;
|
||||
|
||||
my $ID = $Param{FileID} - 1;
|
||||
my %File = %{ $Index[$ID] };
|
||||
|
||||
my $Directory = $Self->{TempDir} . '/' . $Param{FormID};
|
||||
|
||||
if ( !-d $Directory ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
# get main object
|
||||
my $MainObject = $Kernel::OM->Get('Kernel::System::Main');
|
||||
|
||||
$MainObject->FileDelete(
|
||||
Directory => $Directory,
|
||||
Filename => "$File{Filename}",
|
||||
NoReplace => 1,
|
||||
);
|
||||
$MainObject->FileDelete(
|
||||
Directory => $Directory,
|
||||
Filename => "$File{Filename}.ContentType",
|
||||
NoReplace => 1,
|
||||
);
|
||||
$MainObject->FileDelete(
|
||||
Directory => $Directory,
|
||||
Filename => "$File{Filename}.ContentID",
|
||||
NoReplace => 1,
|
||||
);
|
||||
$MainObject->FileDelete(
|
||||
Directory => $Directory,
|
||||
Filename => "$File{Filename}.Disposition",
|
||||
NoReplace => 1,
|
||||
);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub FormIDGetAllFilesData {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
if ( !$Param{FormID} ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => 'Need FormID!'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
my @Data;
|
||||
|
||||
return \@Data if !$Self->_FormIDValidate( $Param{FormID} );
|
||||
|
||||
my $Directory = $Self->{TempDir} . '/' . $Param{FormID};
|
||||
|
||||
if ( !-d $Directory ) {
|
||||
return \@Data;
|
||||
}
|
||||
|
||||
# get main object
|
||||
my $MainObject = $Kernel::OM->Get('Kernel::System::Main');
|
||||
|
||||
my @List = $MainObject->DirectoryRead(
|
||||
Directory => $Directory,
|
||||
Filter => "*",
|
||||
);
|
||||
|
||||
my $Counter = 0;
|
||||
|
||||
FILE:
|
||||
for my $File (@List) {
|
||||
|
||||
# ignore meta files
|
||||
next FILE if $File =~ /\.ContentType$/;
|
||||
next FILE if $File =~ /\.ContentID$/;
|
||||
next FILE if $File =~ /\.Disposition$/;
|
||||
|
||||
$Counter++;
|
||||
my $FileSize = -s $File;
|
||||
|
||||
# human readable file size
|
||||
if ( defined $FileSize ) {
|
||||
|
||||
# remove meta data in files
|
||||
if ( $FileSize > 30 ) {
|
||||
$FileSize = $FileSize - 30;
|
||||
}
|
||||
}
|
||||
my $Content = $MainObject->FileRead(
|
||||
Location => $File,
|
||||
Mode => 'binmode', # optional - binmode|utf8
|
||||
);
|
||||
next FILE if !$Content;
|
||||
|
||||
my $ContentType = $MainObject->FileRead(
|
||||
Location => "$File.ContentType",
|
||||
Mode => 'binmode', # optional - binmode|utf8
|
||||
);
|
||||
next FILE if !$ContentType;
|
||||
|
||||
my $ContentID = $MainObject->FileRead(
|
||||
Location => "$File.ContentID",
|
||||
Mode => 'binmode', # optional - binmode|utf8
|
||||
);
|
||||
next FILE if !$ContentID;
|
||||
|
||||
# verify if content id is empty, set to undef
|
||||
if ( !${$ContentID} ) {
|
||||
${$ContentID} = undef;
|
||||
}
|
||||
|
||||
my $Disposition = $MainObject->FileRead(
|
||||
Location => "$File.Disposition",
|
||||
Mode => 'binmode', # optional - binmode|utf8
|
||||
);
|
||||
next FILE if !$Disposition;
|
||||
|
||||
# strip filename
|
||||
$File =~ s/^.*\/(.+?)$/$1/;
|
||||
push(
|
||||
@Data,
|
||||
{
|
||||
Content => ${$Content},
|
||||
ContentID => ${$ContentID},
|
||||
ContentType => ${$ContentType},
|
||||
Filename => $File,
|
||||
Filesize => $FileSize,
|
||||
FileID => $Counter,
|
||||
Disposition => ${$Disposition},
|
||||
},
|
||||
);
|
||||
}
|
||||
return \@Data;
|
||||
|
||||
}
|
||||
|
||||
sub FormIDGetAllFilesMeta {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
if ( !$Param{FormID} ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => 'Need FormID!'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
my @Data;
|
||||
|
||||
return \@Data if !$Self->_FormIDValidate( $Param{FormID} );
|
||||
|
||||
my $Directory = $Self->{TempDir} . '/' . $Param{FormID};
|
||||
|
||||
if ( !-d $Directory ) {
|
||||
return \@Data;
|
||||
}
|
||||
|
||||
# get main object
|
||||
my $MainObject = $Kernel::OM->Get('Kernel::System::Main');
|
||||
|
||||
my @List = $MainObject->DirectoryRead(
|
||||
Directory => $Directory,
|
||||
Filter => "*",
|
||||
);
|
||||
|
||||
my $Counter = 0;
|
||||
|
||||
FILE:
|
||||
for my $File (@List) {
|
||||
|
||||
# ignore meta files
|
||||
next FILE if $File =~ /\.ContentType$/;
|
||||
next FILE if $File =~ /\.ContentID$/;
|
||||
next FILE if $File =~ /\.Disposition$/;
|
||||
|
||||
$Counter++;
|
||||
my $FileSize = -s $File;
|
||||
|
||||
# human readable file size
|
||||
if ( defined $FileSize ) {
|
||||
|
||||
# remove meta data in files
|
||||
if ( $FileSize > 30 ) {
|
||||
$FileSize = $FileSize - 30;
|
||||
}
|
||||
}
|
||||
|
||||
my $ContentType = $MainObject->FileRead(
|
||||
Location => "$File.ContentType",
|
||||
Mode => 'binmode', # optional - binmode|utf8
|
||||
);
|
||||
next FILE if !$ContentType;
|
||||
|
||||
my $ContentID = $MainObject->FileRead(
|
||||
Location => "$File.ContentID",
|
||||
Mode => 'binmode', # optional - binmode|utf8
|
||||
);
|
||||
next FILE if !$ContentID;
|
||||
|
||||
# verify if content id is empty, set to undef
|
||||
if ( !${$ContentID} ) {
|
||||
${$ContentID} = undef;
|
||||
}
|
||||
|
||||
my $Disposition = $MainObject->FileRead(
|
||||
Location => "$File.Disposition",
|
||||
Mode => 'binmode', # optional - binmode|utf8
|
||||
);
|
||||
next FILE if !$Disposition;
|
||||
|
||||
# strip filename
|
||||
$File =~ s/^.*\/(.+?)$/$1/;
|
||||
push(
|
||||
@Data,
|
||||
{
|
||||
ContentID => ${$ContentID},
|
||||
ContentType => ${$ContentType},
|
||||
Filename => $File,
|
||||
Filesize => $FileSize,
|
||||
FileID => $Counter,
|
||||
Disposition => ${$Disposition},
|
||||
},
|
||||
);
|
||||
}
|
||||
return \@Data;
|
||||
}
|
||||
|
||||
sub FormIDCleanUp {
|
||||
my ( $Self, %Param ) = @_;
|
||||
|
||||
# get main object
|
||||
my $MainObject = $Kernel::OM->Get('Kernel::System::Main');
|
||||
|
||||
my $RetentionTime = int( time() - 86400 ); # remove subdirs older than 24h
|
||||
my @List = $MainObject->DirectoryRead(
|
||||
Directory => $Self->{TempDir},
|
||||
Filter => '*'
|
||||
);
|
||||
|
||||
SUBDIR:
|
||||
for my $Subdir (@List) {
|
||||
my $SubdirTime = $Subdir;
|
||||
|
||||
if ( $SubdirTime =~ /^.*\/\d+\..+$/ ) {
|
||||
$SubdirTime =~ s/^.*\/(\d+?)\..+$/$1/;
|
||||
}
|
||||
else {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message =>
|
||||
"Won't delete upload cache directory $Subdir: timestamp in directory name not found! Please fix it manually.",
|
||||
);
|
||||
next SUBDIR;
|
||||
}
|
||||
|
||||
if ( $RetentionTime > $SubdirTime ) {
|
||||
my @Sublist = $MainObject->DirectoryRead(
|
||||
Directory => $Subdir,
|
||||
Filter => "*",
|
||||
);
|
||||
|
||||
for my $File (@Sublist) {
|
||||
$MainObject->FileDelete(
|
||||
Location => $File,
|
||||
);
|
||||
}
|
||||
|
||||
if ( !rmdir($Subdir) ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => "Can't remove: $Subdir: $!!",
|
||||
);
|
||||
next SUBDIR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub _FormIDValidate {
|
||||
my ( $Self, $FormID ) = @_;
|
||||
|
||||
return if !$FormID;
|
||||
|
||||
if ( $FormID !~ m{^ \d+ \. \d+ \. \d+ $}xms ) {
|
||||
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
||||
Priority => 'error',
|
||||
Message => 'Invalid FormID!',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
1;
|
||||
Reference in New Issue
Block a user