Skip to content
Permalink
Browse files

Fixed: External images are automatically loaded in forward screen (bu…

…g#14398).
  • Loading branch information...
milanrakic authored and zilibasic committed May 9, 2019
1 parent d317f61 commit 4e06ef439c33e7d90af16451719415c780e0c29c
@@ -1,4 +1,6 @@
#6.0.19 ????-??-??
- 2019-05-09 Fixed bug#[14398](https://bugs.otrs.org/show_bug.cgi?id=14398) - External images are automatically loaded in forward screen.
New config 'Ticket::Frontend::BlockLoadingRemoteContent' is added. It controls if externnal content should be loaded, by default it is disabled.
- 2019-05-09 Fixed bug#[14500](https://bugs.otrs.org/show_bug.cgi?id=14500) - Webservice base64 contents line feed does not comply with RFC 4648.
- 2019-05-08 Fixed bug#[14532](https://bugs.otrs.org/show_bug.cgi?id=14532) - Wrong comment / documentation for Daemon::SchedulerCronTaskManager::Task###GeneticInterfaceDebugLogCleanup in Docs and SystemConfiguration.
- 2019-05-08 Fixed bug#[14455](https://bugs.otrs.org/show_bug.cgi?id=14455) - OTRS tags '<OTRS_CUSTOMER_DATA_*>' don't work in 'Create' template.
@@ -1743,6 +1743,13 @@
</Item>
</Value>
</Setting>
<Setting Name="Ticket::Frontend::BlockLoadingRemoteContent" Required="1" Valid="1">
<Description Translatable="1">Makes the application block external content loading.</Description>
<Navigation>Frontend::Agent</Navigation>
<Value>
<Item ValueType="Checkbox">0</Item>
</Value>
</Setting>
<Setting Name="Ticket::Frontend::CustomerInfoCompose" Required="1" Valid="1">
<Description Translatable="1">Shows the customer user information (phone and email) in the compose screen.</Description>
<Navigation>Frontend::Agent</Navigation>
@@ -1626,6 +1626,15 @@ sub Run {
# set Body var to calculated content
$GetParam{Body} = $Body;

# Strip out external content if BlockLoadingRemoteContent is enabled.
if ( $ConfigObject->Get('Ticket::Frontend::BlockLoadingRemoteContent') ) {
my %SafetyCheckResult = $Kernel::OM->Get('Kernel::System::HTMLUtils')->Safety(
String => $GetParam{Body},
NoExtSrcLoad => 1,
);
$GetParam{Body} = $SafetyCheckResult{String};
}

if ( $Self->{ReplyToArticle} ) {
my $TicketSubjectRe = $ConfigObject->Get('Ticket::SubjectRe') || 'Re';
$GetParam{Subject} = $TicketSubjectRe . ': ' . $Self->{ReplyToArticleContent}{Subject};
@@ -114,15 +114,6 @@ sub Run {
# set filename for inline viewing
$Data{Filename} = "Ticket-$TicketNumber-ArticleID-$Article{ArticleID}.html";

my $LoadExternalImages = $ParamObject->GetParam(
Param => 'LoadExternalImages'
) || 0;

# safety check only on customer article
if ( !$LoadExternalImages && $Article{SenderType} ne 'customer' ) {
$LoadExternalImages = 1;
}

# generate base url
my $URL = 'Action=AgentTicketAttachment;Subaction=HTMLView'
. ";TicketID=$TicketID;ArticleID=$ArticleID;FileID=";
@@ -132,6 +123,22 @@ sub Run {
ArticleID => $ArticleID,
);

# Do not load external images if 'BlockLoadingRemoteContent' is enabled.
my $LoadExternalImages;
if ( $ConfigObject->Get('Ticket::Frontend::BlockLoadingRemoteContent') ) {
$LoadExternalImages = 0;
}
else {
$LoadExternalImages = $ParamObject->GetParam(
Param => 'LoadExternalImages'
) || 0;

# Safety check only on customer article.
if ( !$LoadExternalImages && $Article{SenderType} ne 'customer' ) {
$LoadExternalImages = 1;
}
}

# reformat rich text document to have correct charset and links to
# inline documents
%Data = $LayoutObject->RichTextDocumentServe(
@@ -1413,6 +1413,15 @@ sub Run {
UploadCacheObject => $UploadCacheObject,
);

# Strip out external content if BlockLoadingRemoteContent is enabled.
if ( $ConfigObject->Get('Ticket::Frontend::BlockLoadingRemoteContent') ) {
my %SafetyCheckResult = $Kernel::OM->Get('Kernel::System::HTMLUtils')->Safety(
String => $Data{Body},
NoExtSrcLoad => 1,
);
$Data{Body} = $SafetyCheckResult{String};
}

# restrict number of body lines if configured
if (
$Data{Body}
@@ -462,6 +462,15 @@ sub Run {
$Article{ContentType} = 'text/plain';
}

# Strip out external content if BlockLoadingRemoteContent is enabled.
if ( $ConfigObject->Get('Ticket::Frontend::BlockLoadingRemoteContent') ) {
my %SafetyCheckResult = $Kernel::OM->Get('Kernel::System::HTMLUtils')->Safety(
String => $Article{Body},
NoExtSrcLoad => 1,
);
$Article{Body} = $SafetyCheckResult{String};
}

# show customer info
if ( $ConfigObject->Get('Ticket::Frontend::CustomerInfoCompose') ) {
if ( $Article{CustomerUserID} ) {
@@ -352,6 +352,15 @@ sub Form {
AttachmentsInclude => 1,
);

# Strip out external content if BlockLoadingRemoteContent is enabled.
if ( $ConfigObject->Get('Ticket::Frontend::BlockLoadingRemoteContent') ) {
my %SafetyCheckResult = $Kernel::OM->Get('Kernel::System::HTMLUtils')->Safety(
String => $Data{Body},
NoExtSrcLoad => 1,
);
$Data{Body} = $SafetyCheckResult{String};
}

# If article is not a MIMEBase article, include sender name for correct quoting.
if ( !$Data{From} ) {
my %ArticleFields = $LayoutObject->ArticleFields(
@@ -366,6 +366,15 @@ sub Run {
$Article{ContentType} = 'text/plain';
}

# Strip out external content if BlockLoadingRemoteContent is enabled.
if ( $ConfigObject->Get('Ticket::Frontend::BlockLoadingRemoteContent') ) {
my %SafetyCheckResult = $Kernel::OM->Get('Kernel::System::HTMLUtils')->Safety(
String => $Article{Body},
NoExtSrcLoad => 1,
);
$Article{Body} = $SafetyCheckResult{String};
}

# show customer info
if ( $ConfigObject->Get('Ticket::Frontend::CustomerInfoCompose') ) {
if ( $SplitTicketData{CustomerUserID} ) {
@@ -2650,8 +2650,8 @@ sub _RenderTitle {
sub _RenderArticle {
my ( $Self, %Param ) = @_;

# get layout object
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');

for my $Needed (qw(FormID Ticket)) {
if ( !$Param{$Needed} ) {
@@ -2690,6 +2690,15 @@ sub _RenderArticle {
UploadCacheObject => $Kernel::OM->Get('Kernel::System::Web::UploadCache'),
AttachmentsInclude => 1,
);

# Strip out external content if BlockLoadingRemoteContent is enabled.
if ( $ConfigObject->Get('Ticket::Frontend::BlockLoadingRemoteContent') ) {
my %SafetyCheckResult = $Kernel::OM->Get('Kernel::System::HTMLUtils')->Safety(
String => $Param{GetParam}->{Body},
NoExtSrcLoad => 1,
);
$Param{GetParam}->{Body} = $SafetyCheckResult{String};
}
}

# get all attachments meta data
@@ -2823,9 +2832,6 @@ sub _RenderArticle {
$Param{TimeUnitsInvalid} = 'ServerError';
}

# get config object
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');

# show time units
if (
$ConfigObject->Get('Ticket::Frontend::AccountTime')
@@ -156,14 +156,6 @@ sub Run {
# unset filename for inline viewing
$Data{Filename} = "Ticket-$TicketNumber-ArticleID-$Article{ArticleID}.html";

# safety check only on customer article
my $LoadExternalImages = $ParamObject->GetParam(
Param => 'LoadExternalImages'
) || 0;
if ( !$LoadExternalImages && $Article{SenderType} ne 'customer' ) {
$LoadExternalImages = 1;
}

# generate base url
my $URL = 'Action=CustomerTicketAttachment;Subaction=HTMLView'
. ";TicketID=$TicketID;ArticleID=$ArticleID;FileID=";
@@ -173,6 +165,22 @@ sub Run {
ArticleID => $ArticleID,
);

# Do not load external images if 'BlockLoadingRemoteContent' is enabled.
my $LoadExternalImages;
if ( $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Frontend::BlockLoadingRemoteContent') ) {
$LoadExternalImages = 0;
}
else {
$LoadExternalImages = $ParamObject->GetParam(
Param => 'LoadExternalImages'
) || 0;

# Safety check only on customer article.
if ( !$LoadExternalImages && $Article{SenderType} ne 'customer' ) {
$LoadExternalImages = 1;
}
}

# reformat rich text document to have correct charset and links to
# inline documents
%Data = $LayoutObject->RichTextDocumentServe(
@@ -5047,8 +5047,7 @@ sub RichTextDocumentServe {

if ( !$Param{LoadExternalImages} ) {

# Strip out external images, but show a confirmation button to
# load them explicitly.
# Strip out external content.
my %SafetyCheckResult = $Kernel::OM->Get('Kernel::System::HTMLUtils')->Safety(
String => $Param{Data}->{Content},
NoApplet => 1,
@@ -5063,7 +5062,12 @@ sub RichTextDocumentServe {

$Param{Data}->{Content} = $SafetyCheckResult{String};

if ( $SafetyCheckResult{Replace} ) {
# Show confirmation button to load external content explicitly only if BlockLoadingRemoteContent is disabled.
if (
$SafetyCheckResult{Replace}
&& !$Kernel::OM->Get('Kernel::Config')->Get('Ticket::Frontend::BlockLoadingRemoteContent')
)
{

# Generate blocker message.
my $Message = $Self->Output( TemplateFile => 'AttachmentBlocker' );
@@ -24,6 +24,13 @@ $Kernel::OM->ObjectParamAdd(
);
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');

# Disable global external content blocking.
$Helper->ConfigSettingChange(
Valid => 1,
Key => 'Ticket::Frontend::BlockLoadingRemoteContent',
Value => 0,
);

my @Tests = (
{
Name => '',
@@ -44,6 +44,13 @@ $Selenium->RunTest(
Value => 0
);

# Disable global external content blocking.
$Helper->ConfigSettingChange(
Valid => 1,
Key => 'Ticket::Frontend::BlockLoadingRemoteContent',
Value => 0,
);

# Create test ticket.
my $TicketID = $TicketObject->TicketCreate(
Title => 'Selenium ticket',
@@ -119,47 +126,34 @@ $Selenium->RunTest(

my $ScriptAlias = $Kernel::OM->Get('Kernel::Config')->Get('ScriptAlias');

# Navigate to created test ticket in AgentTicketZoom page.
$Selenium->VerifiedGet("${ScriptAlias}index.pl?Action=AgentTicketZoom;TicketID=$TicketID");

# Click on forward.
$Selenium->find_element("//a[contains(\@href, \'Action=AgentTicketForward;TicketID=$TicketID;' )]")->click();

# Switch to forward window.
$Selenium->WaitFor( WindowCount => 2 );
my $Handles = $Selenium->get_window_handles();
$Selenium->switch_to_window( $Handles->[1] );

# Wait until page has loaded, if necessary.
$Selenium->WaitFor( JavaScript => 'return typeof($) === "function" && $("#ToCustomer").length' );
# Navigate to AgentTicketForward page.
$Selenium->VerifiedGet(
"${ScriptAlias}index.pl?Action=AgentTicketForward;TicketID=$TicketID;ArticleID=$ArticleID"
);

# Check AgentTicketFoward page.
for my $ID (
qw(ToCustomer CcCustomer BccCustomer Subject RichText
FileUpload ComposeStateID IsVisibleForCustomer submitRichText)
)
{
$Selenium->WaitFor( JavaScript => "return typeof(\$) === 'function' && \$('#$ID').length;" );
my $Element = $Selenium->find_element( "#$ID", 'css' );
$Element->is_enabled();
$Element->is_displayed();
}

# Input fields and send forward.
$Selenium->find_element( "#ToCustomer", 'css' )->send_keys($TestCustomer);

$Selenium->WaitFor( JavaScript => 'return typeof($) === "function" && $("li.ui-menu-item:visible").length' );
$Selenium->execute_script("\$('li.ui-menu-item:contains($TestCustomer)').click()");
$Selenium->WaitFor( JavaScript => 'return typeof($) === "function" && $("li.ui-menu-item:visible").length;' );
$Selenium->execute_script("\$('li.ui-menu-item:contains($TestCustomer)').click();");

$Selenium->InputFieldValueSet(
Element => '#ComposeStateID',
Value => '4',
);

$Selenium->find_element( "#submitRichText", 'css' )->click();

# Return back to AgentTicketZoom.
$Selenium->WaitFor( WindowCount => 1 );
$Selenium->switch_to_window( $Handles->[0] );
$Selenium->find_element( "#submitRichText", 'css' )->VerifiedClick();

# Navigate to AgentTicketHistory of created test ticket.
$Selenium->VerifiedGet("${ScriptAlias}index.pl?Action=AgentTicketHistory;TicketID=$TicketID");
@@ -170,6 +164,71 @@ $Selenium->RunTest(
'Action Forward executed correctly'
);

# Test external content loading depends on BlockLoadingRemoteContent setting (see bug#14398).
# Enable RichText.
$Helper->ConfigSettingChange(
Valid => 1,
Key => 'Frontend::RichText',
Value => 1,
);

my $RandomID = $Helper->GetRandomID();

# Create another email article.
my $ImgSource = 'http://example.com/image.png';
my $ArticleIDExtContent = $ArticleBackendObject->ArticleCreate(
TicketID => $TicketID,
SenderType => 'customer',
IsVisibleForCustomer => 1,
Subject => 'some short description',
Body => '<!DOCTYPE html><html><body>' . $RandomID . '<br /><img src="' . $ImgSource . '"/></body></html>',
Charset => 'utf-8',
MimeType => 'text/html',
HistoryType => 'EmailCustomer',
HistoryComment => 'Some free text!',
UserID => 1,
);
$Self->True(
$ArticleID,
"ArticleID $ArticleIDExtContent is created",
);

# Navigate to AgentTicketForward page of article with external content.
$Selenium->VerifiedGet(
"${ScriptAlias}index.pl?Action=AgentTicketForward;TicketID=$TicketID;ArticleID=$ArticleIDExtContent"
);

# Wait until CKEditor content is updated.
$Selenium->WaitFor(
JavaScript => "return CKEDITOR.instances.RichText.getData().indexOf('$ImgSource') > -1;",
);

# Verify external content is loaded due to disabled BlockLoadingRemoteContent.
$Self->True(
$Selenium->execute_script("return CKEDITOR.instances.RichText.getData().indexOf('$ImgSource') > -1;"),
"BlockLoadingRemoteContent is disabled - external content is loaded"
);

# Enable global external content blocking.
$Helper->ConfigSettingChange(
Valid => 1,
Key => 'Ticket::Frontend::BlockLoadingRemoteContent',
Value => 1,
);

$Selenium->VerifiedRefresh();

# Wait until CKEditor content is updated.
$Selenium->WaitFor(
JavaScript => "return CKEDITOR.instances.RichText.getData().indexOf('$RandomID') > -1;",
);

# Verify external content is not loaded due to enabled BlockLoadingRemoteContent.
$Self->False(
$Selenium->execute_script("return CKEDITOR.instances.RichText.getData().indexOf('$ImgSource') > -1;"),
"BlockLoadingRemoteContent is enabled - external content is not loaded"
);

# Delete created test ticket.
my $Success = $TicketObject->TicketDelete(
TicketID => $TicketID,

0 comments on commit 4e06ef4

Please sign in to comment.
You can’t perform that action at this time.