From e63bdcdb56539bed3e4789721a764f719be2d663 Mon Sep 17 00:00:00 2001
From: Sebastian Riedel <sri@cpan.org>
Date: Tue, 23 Jul 2019 13:48:16 +0200
Subject: [PATCH 1/3] Abstract out markdown handling into a new class
---
lib/OpenQA/Markdown.pm | 52 +++++++++++++++++++++
lib/OpenQA/Schema/Result/Comments.pm | 32 +------------
lib/OpenQA/Schema/Result/JobGroupParents.pm | 9 ++--
lib/OpenQA/Schema/Result/JobGroups.pm | 11 ++---
t/16-markdown.t | 42 +++++++++++++++++
5 files changed, 104 insertions(+), 42 deletions(-)
create mode 100644 lib/OpenQA/Markdown.pm
create mode 100644 t/16-markdown.t
diff --git a/lib/OpenQA/Markdown.pm b/lib/OpenQA/Markdown.pm
new file mode 100644
index 000000000..b63806a2c
--- /dev/null
+++ b/lib/OpenQA/Markdown.pm
@@ -0,0 +1,52 @@
+# Copyright (C) 2019 SUSE Linux Products GmbH
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, see <http://www.gnu.org/licenses/>.
+package OpenQA::Markdown;
+use Mojo::Base -strict;
+
+require Text::Markdown;
+our @ISA = qw(Text::Markdown);
+
+use Exporter 'import';
+use Regexp::Common 'URI';
+use OpenQA::Utils 'bugref_to_href';
+
+our @EXPORT_OK = qw(markdown_to_html);
+
+sub markdown_to_html {
+ my $text = shift;
+ my $m = __PACKAGE__->new;
+ my $html = $m->markdown($text);
+ return $html;
+}
+
+# TODO: Kill it with fire
+sub _DoAutoLinks {
+ my ($self, $text) = @_;
+
+ # auto-replace bugrefs with 'a href...'
+ $text = bugref_to_href($text);
+
+ # auto-replace every http(s) reference which is not already either html
+ # 'a href...' or markdown link '[link](url)' or enclosed by Text::Markdown
+ # URL markers '<>'
+ $text =~ s@(?<!['"(<>])($RE{URI})@<$1>@gi;
+
+ # For tests make sure that references into test modules and needling steps also work
+ $text =~ s{\b(t#([\w/]+))}{<a href="/tests/$2">$1</a>}gi;
+
+ return $self->SUPER::_DoAutoLinks($text);
+}
+
+1;
diff --git a/lib/OpenQA/Schema/Result/Comments.pm b/lib/OpenQA/Schema/Result/Comments.pm
index ca09bf5e2..48288a6ca 100644
--- a/lib/OpenQA/Schema/Result/Comments.pm
+++ b/lib/OpenQA/Schema/Result/Comments.pm
@@ -21,6 +21,7 @@ use warnings;
use base 'DBIx::Class::Core';
use OpenQA::Utils qw(find_bugref find_bugrefs);
+use OpenQA::Markdown qw(markdown_to_html);
__PACKAGE__->load_components(qw(Core));
__PACKAGE__->load_components(qw(InflateColumn::DateTime Timestamps));
@@ -144,12 +145,7 @@ sub tag {
return $+{build}, $+{type}, $+{description}, $+{version};
}
-sub rendered_markdown {
- my ($self) = @_;
-
- my $m = CommentsMarkdownParser->new;
- return Mojo::ByteStream->new($m->markdown($self->text));
-}
+sub rendered_markdown { Mojo::ByteStream->new(markdown_to_html(shift->text)) }
sub hash {
my ($self) = @_;
@@ -174,28 +170,4 @@ sub extended_hash {
};
}
-package CommentsMarkdownParser;
-require Text::Markdown;
-our @ISA = qw(Text::Markdown);
-use Regexp::Common 'URI';
-use OpenQA::Utils 'bugref_to_href';
-
-sub _DoAutoLinks {
- my ($self, $text) = @_;
-
- # auto-replace bugrefs with 'a href...'
- $text = bugref_to_href($text);
-
- # auto-replace every http(s) reference which is not already either html
- # 'a href...' or markdown link '[link](url)' or enclosed by Text::Markdown
- # URL markers '<>'
- $text =~ s@(?<!['"(<>])($RE{URI})@<$1>@gi;
-
- # For tests make sure that references into test modules and needling steps also work
- $text =~ s{\b(t#([\w/]+))}{<a href="/tests/$2">$1</a>}gi;
-
- $text =~ s{(http://\S*\.gif$)}{<img src="$1"/>}gi;
- $self->SUPER::_DoAutoLinks($text);
-}
-
1;
diff --git a/lib/OpenQA/Schema/Result/JobGroupParents.pm b/lib/OpenQA/Schema/Result/JobGroupParents.pm
index 4ee040678..18656e3b2 100644
--- a/lib/OpenQA/Schema/Result/JobGroupParents.pm
+++ b/lib/OpenQA/Schema/Result/JobGroupParents.pm
@@ -21,6 +21,7 @@ use warnings;
use base 'DBIx::Class::Core';
+use OpenQA::Markdown 'markdown_to_html';
use OpenQA::Schema::JobGroupDefaults;
use OpenQA::Utils 'parse_tags_from_comments';
use Class::Method::Modifiers;
@@ -157,11 +158,9 @@ sub jobs {
}
sub rendered_description {
- my ($self) = @_;
-
- return unless $self->description;
- my $m = CommentsMarkdownParser->new;
- return Mojo::ByteStream->new($m->markdown($self->description));
+ my $self = shift;
+ return undef unless my $desc = $self->description;
+ return Mojo::ByteStream->new(markdown_to_html($desc));
}
sub tags {
diff --git a/lib/OpenQA/Schema/Result/JobGroups.pm b/lib/OpenQA/Schema/Result/JobGroups.pm
index 1e5073386..4ba138ea7 100644
--- a/lib/OpenQA/Schema/Result/JobGroups.pm
+++ b/lib/OpenQA/Schema/Result/JobGroups.pm
@@ -20,6 +20,7 @@ use warnings;
use base 'DBIx::Class::Core';
+use OpenQA::Markdown 'markdown_to_html';
use OpenQA::Schema::JobGroupDefaults;
use Class::Method::Modifiers;
use OpenQA::Utils qw(log_debug parse_tags_from_comments);
@@ -153,13 +154,9 @@ around 'carry_over_bugrefs' => sub {
};
sub rendered_description {
- my ($self) = @_;
-
- if ($self->description) {
- my $m = CommentsMarkdownParser->new;
- return Mojo::ByteStream->new($m->markdown($self->description));
- }
- return;
+ my $self = shift;
+ return undef unless my $desc = $self->description;
+ return Mojo::ByteStream->new(markdown_to_html($desc));
}
sub full_name {
diff --git a/t/16-markdown.t b/t/16-markdown.t
new file mode 100644
index 000000000..99b1b8db8
--- /dev/null
+++ b/t/16-markdown.t
@@ -0,0 +1,42 @@
+#!/usr/bin/env perl -w
+
+# Copyright (C) 2016 SUSE LLC
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+use Mojo::Base -strict;
+
+use Test::More;
+use OpenQA::Markdown 'markdown_to_html';
+
+subtest 'standard markdown' => sub {
+ is markdown_to_html('Test'), "<p>Test</p>\n", 'HTML rendered';
+ is markdown_to_html("Test\n123\n\n456 789 tset\n"), qq{<p>Test\n123</p>\n\n<p>456 789 tset</p>\n}, 'HTML rendered';
+ is markdown_to_html('*Test*'), "<p><em>Test</em></p>\n", 'HTML rendered';
+ is markdown_to_html('[Test](http://test.com)'), qq{<p><a href="http://test.com">Test</a></p>\n}, 'HTML rendered';
+};
+
+subtest 'bugrefs' => sub {
+ is markdown_to_html('boo#123'),
+ qq{<p><a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a></p>\n}, 'bugref expanded';
+};
+
+subtest 'openQA additions' => sub {
+ is markdown_to_html('https://example.com'),
+ qq{<p><a href="https://example.com">https://example.com</a></p>\n}, 'URL turned into a link';
+ is markdown_to_html('t#123'), qq{<p><a href="/tests/123">t#123</a></p>\n}, 'testref expanded';
+};
+
+done_testing;
From cb3b0fce08be64503362271fa31d12621c8ff806 Mon Sep 17 00:00:00 2001
From: Sebastian Riedel <sri@cpan.org>
Date: Thu, 25 Jul 2019 17:49:57 +0200
Subject: [PATCH 2/3] Scrub dangerous HTML from comments
---
cpanfile | 1 +
docker/travis_test/Dockerfile | 1 +
lib/OpenQA/Markdown.pm | 53 +++++++++++++++++++++----------
openQA.spec | 2 +-
t/16-markdown.t | 60 +++++++++++++++++++++++++++++++----
5 files changed, 92 insertions(+), 25 deletions(-)
diff --git a/cpanfile b/cpanfile
index 2596a6980..8159d6554 100644
--- a/cpanfile
+++ b/cpanfile
@@ -77,6 +77,7 @@ requires 'Sub::Install';
requires 'Sub::Name';
requires 'Text::Diff';
requires 'Text::Markdown';
+requires 'HTML::Restrict';
requires 'CommonMark';
requires 'Time::HiRes';
requires 'Time::ParseDate';
diff --git a/docker/travis_test/Dockerfile b/docker/travis_test/Dockerfile
index 8f11a62f6..1e14c0679 100644
--- a/docker/travis_test/Dockerfile
+++ b/docker/travis_test/Dockerfile
@@ -122,6 +122,7 @@ RUN zypper in -y -C \
'perl(Test::Warnings)' \
'perl(Text::Diff)' \
'perl(Text::Markdown)' \
+ 'perl(HTML::Restrict)' \
'perl(CommonMark)' \
'perl(Time::ParseDate)' \
'perl(XSLoader) >= 0.24' \
diff --git a/lib/OpenQA/Markdown.pm b/lib/OpenQA/Markdown.pm
index b63806a2c..ddbcf0913 100644
--- a/lib/OpenQA/Markdown.pm
+++ b/lib/OpenQA/Markdown.pm
@@ -15,38 +15,57 @@
package OpenQA::Markdown;
use Mojo::Base -strict;
-require Text::Markdown;
-our @ISA = qw(Text::Markdown);
-
use Exporter 'import';
use Regexp::Common 'URI';
use OpenQA::Utils 'bugref_to_href';
+use Text::Markdown;
+use HTML::Restrict;
our @EXPORT_OK = qw(markdown_to_html);
+# Limit tags to a safe subset
+my $RULES = {
+ a => [qw(href)],
+ blockquote => [],
+ code => [],
+ em => [],
+ img => [qw(src alt)],
+ h1 => [],
+ h2 => [],
+ h3 => [],
+ h4 => [],
+ h5 => [],
+ h6 => [],
+ hr => [],
+ li => [],
+ ol => [],
+ p => [],
+ strong => [],
+ ul => []};
+
+# Only allow "href=/...", "href=http://..." and "href=https://..."
+my $SCHEMES = [undef, 'http', 'https'];
+
+my $RESTRICT = HTML::Restrict->new(rules => $RULES, uri_schemes => $SCHEMES);
+my $MARKDOWN = Text::Markdown->new;
+
sub markdown_to_html {
my $text = shift;
- my $m = __PACKAGE__->new;
- my $html = $m->markdown($text);
- return $html;
-}
-
-# TODO: Kill it with fire
-sub _DoAutoLinks {
- my ($self, $text) = @_;
- # auto-replace bugrefs with 'a href...'
+ # Replace bugrefs with links
$text = bugref_to_href($text);
- # auto-replace every http(s) reference which is not already either html
- # 'a href...' or markdown link '[link](url)' or enclosed by Text::Markdown
- # URL markers '<>'
+ # Turn all remaining URLs into links
$text =~ s@(?<!['"(<>])($RE{URI})@<$1>@gi;
- # For tests make sure that references into test modules and needling steps also work
+ # Turn references to test modules and needling steps into links
$text =~ s{\b(t#([\w/]+))}{<a href="/tests/$2">$1</a>}gi;
- return $self->SUPER::_DoAutoLinks($text);
+ # Markdown -> HTML
+ my $html = $MARKDOWN->markdown($text);
+
+ # Unsafe -> safe
+ return $RESTRICT->process($html);
}
1;
diff --git a/openQA.spec b/openQA.spec
index 4a92f2766..1f61418e2 100644
--- a/openQA.spec
+++ b/openQA.spec
@@ -45,7 +45,7 @@
%else
%define python_scripts_requires %{nil}
%endif
-%define t_requires perl(DBD::Pg) perl(DBIx::Class) perl(Config::IniFiles) perl(SQL::Translator) perl(Date::Format) perl(File::Copy::Recursive) perl(DateTime::Format::Pg) perl(Net::OpenID::Consumer) perl(Mojolicious::Plugin::RenderFile) perl(Mojolicious::Plugin::AssetPack) perl(aliased) perl(Config::Tiny) perl(DBIx::Class::DeploymentHandler) perl(DBIx::Class::DynamicDefault) perl(DBIx::Class::Schema::Config) perl(DBIx::Class::Storage::Statistics) perl(IO::Socket::SSL) perl(Data::Dump) perl(DBIx::Class::OptimisticLocking) perl(Module::Pluggable) perl(Text::Diff) perl(Text::Markdown) perl(CommonMark) perl(JSON::Validator) perl(YAML::XS) perl(IPC::Run) perl(Archive::Extract) perl(CSS::Minifier::XS) perl(JavaScript::Minifier::XS) perl(Time::ParseDate) perl(Sort::Versions) perl(Mojo::RabbitMQ::Client) perl(BSD::Resource) perl(Cpanel::JSON::XS) perl(Pod::POM) perl(Mojo::IOLoop::ReadWriteProcess) perl(Minion) perl(Mojo::Pg) perl(Mojo::SQLite) perl(Minion::Backend::SQLite) %python_scripts_requires
+%define t_requires perl(DBD::Pg) perl(DBIx::Class) perl(Config::IniFiles) perl(SQL::Translator) perl(Date::Format) perl(File::Copy::Recursive) perl(DateTime::Format::Pg) perl(Net::OpenID::Consumer) perl(Mojolicious::Plugin::RenderFile) perl(Mojolicious::Plugin::AssetPack) perl(aliased) perl(Config::Tiny) perl(DBIx::Class::DeploymentHandler) perl(DBIx::Class::DynamicDefault) perl(DBIx::Class::Schema::Config) perl(DBIx::Class::Storage::Statistics) perl(IO::Socket::SSL) perl(Data::Dump) perl(DBIx::Class::OptimisticLocking) perl(Module::Pluggable) perl(Text::Diff) perl(Text::Markdown) perl(HTML::Restrict) perl(CommonMark) perl(JSON::Validator) perl(YAML::XS) perl(IPC::Run) perl(Archive::Extract) perl(CSS::Minifier::XS) perl(JavaScript::Minifier::XS) perl(Time::ParseDate) perl(Sort::Versions) perl(Mojo::RabbitMQ::Client) perl(BSD::Resource) perl(Cpanel::JSON::XS) perl(Pod::POM) perl(Mojo::IOLoop::ReadWriteProcess) perl(Minion) perl(Mojo::Pg) perl(Mojo::SQLite) perl(Minion::Backend::SQLite) %python_scripts_requires
Name: openQA
Version: 4.6
Release: 0
diff --git a/t/16-markdown.t b/t/16-markdown.t
index 99b1b8db8..d6839cd7a 100644
--- a/t/16-markdown.t
+++ b/t/16-markdown.t
@@ -22,21 +22,67 @@ use Test::More;
use OpenQA::Markdown 'markdown_to_html';
subtest 'standard markdown' => sub {
- is markdown_to_html('Test'), "<p>Test</p>\n", 'HTML rendered';
- is markdown_to_html("Test\n123\n\n456 789 tset\n"), qq{<p>Test\n123</p>\n\n<p>456 789 tset</p>\n}, 'HTML rendered';
- is markdown_to_html('*Test*'), "<p><em>Test</em></p>\n", 'HTML rendered';
- is markdown_to_html('[Test](http://test.com)'), qq{<p><a href="http://test.com">Test</a></p>\n}, 'HTML rendered';
+ is markdown_to_html('Test'), '<p>Test</p>', 'HTML rendered';
+ is markdown_to_html('# Test'), '<h1>Test</h1>', 'HTML rendered';
+ is markdown_to_html('## Test'), '<h2>Test</h2>', 'HTML rendered';
+ is markdown_to_html('### Test'), '<h3>Test</h3>', 'HTML rendered';
+ is markdown_to_html('#### Test'), '<h4>Test</h4>', 'HTML rendered';
+ is markdown_to_html('##### Test'), '<h5>Test</h5>', 'HTML rendered';
+ is markdown_to_html('###### Test'), '<h6>Test</h6>', 'HTML rendered';
+ is markdown_to_html("Test\n123\n\n456 789 tset\n"), qq{<p>Test\n123</p>\n\n<p>456 789 tset</p>}, 'HTML rendered';
+ is markdown_to_html('*Test*'), '<p><em>Test</em></p>', 'HTML rendered';
+ is markdown_to_html('**Test**'), '<p><strong>Test</strong></p>', 'HTML rendered';
+ is markdown_to_html("1. a\n2. b\n3. c\n"), qq{<ol>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n</ol>}, 'HTML rendered';
+ is markdown_to_html("* a\n* b\n* c\n"), qq{<ul>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n</ul>}, 'HTML rendered';
+ is markdown_to_html('[Test](http://test.com)'), qq{<p><a href="http://test.com">Test</a></p>}, 'HTML rendered';
+ is markdown_to_html('[Test](/test.html)'), qq{<p><a href="/test.html">Test</a></p>}, 'HTML rendered';
+ is markdown_to_html('![Test](http://test.com)'), qq{<p><img src="http://test.com" alt="Test"></p>}, 'HTML rendered';
+ is markdown_to_html('Test `123` 123'), '<p>Test <code>123</code> 123</p>', 'HTML rendered';
+ is markdown_to_html("> test\n> 123"), "<blockquote>\n <p>test\n 123</p>\n</blockquote>", 'HTML rendered';
+ is markdown_to_html('---'), '<hr>', 'HTML rendered';
};
subtest 'bugrefs' => sub {
is markdown_to_html('boo#123'),
- qq{<p><a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a></p>\n}, 'bugref expanded';
+ qq{<p><a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a></p>}, 'bugref expanded';
+ is markdown_to_html('testing boo#123 123'),
+ qq{<p>testing <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a> 123</p>},
+ 'bugref expanded';
+ is markdown_to_html('testing boo#123 123 boo#321'),
+ qq{<p>testing <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a> 123}
+ . qq{ <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=321">boo#321</a></p>},
+ 'bugref expanded';
+ is markdown_to_html("testing boo#123 \n123\n boo#321"),
+ qq{<p>testing <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a> \n123\n}
+ . qq{ <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=321">boo#321</a></p>},
+ 'bugref expanded';
+ is markdown_to_html("boo\ntesting boo#123 123\n123"),
+ qq{<p>boo\ntesting <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a> 123\n123</p>},
+ 'bugref expanded';
};
subtest 'openQA additions' => sub {
is markdown_to_html('https://example.com'),
- qq{<p><a href="https://example.com">https://example.com</a></p>\n}, 'URL turned into a link';
- is markdown_to_html('t#123'), qq{<p><a href="/tests/123">t#123</a></p>\n}, 'testref expanded';
+ qq{<p><a href="https://example.com">https://example.com</a></p>}, 'URL turned into a link';
+ is markdown_to_html('testing https://example.com 123'),
+ qq{<p>testing <a href="https://example.com">https://example.com</a> 123</p>}, 'URL turned into a link';
+ is markdown_to_html("t\ntesting https://example.com 123\n123"),
+ qq{<p>t\ntesting <a href="https://example.com">https://example.com</a> 123\n123</p>}, 'URL turned into a link';
+ is markdown_to_html('t#123'), qq{<p><a href="/tests/123">t#123</a></p>}, 'testref expanded';
+ is markdown_to_html('testing t#123 123'), qq{<p>testing <a href="/tests/123">t#123</a> 123</p>}, 'testref expanded';
+ is markdown_to_html("t\ntesting t#123 123\n123"), qq{<p>t\ntesting <a href="/tests/123">t#123</a> 123\n123</p>},
+ 'testref expanded';
+};
+
+subtest 'unsafe HTML filtered out' => sub {
+ is markdown_to_html('Test <script>alert("boom!");</script> 123'), '<p>Test 123</p>', 'unsafe HTML filtered';
+ is markdown_to_html('<font>Test</font>'), '<p>Test</p>', 'unsafe HTML filtered';
+ is markdown_to_html('Test [Boom!](javascript:alert("boom!")) 123'), '<p>Test <a>Boom!</a> 123</p>',
+ 'unsafe HTML filtered';
+ is markdown_to_html('<a href="/" onclick="someFunction()">Totally safe</a>'),
+ '<p><a href="/">Totally safe</a></p>', 'unsafe HTML filtered';
+ is markdown_to_html(qq{> hello <a name="n"\n> href="javascript:alert('boom!')">*you*</a>}),
+ qq{<blockquote>\n <p>hello <a><em>you</em></a></p>\n</blockquote>}, 'unsafe HTML filtered';
};
done_testing;
From 044392c9c4ee12cdeddb7c9c2a301ddd9ac11c4e Mon Sep 17 00:00:00 2001
From: Sebastian Riedel <sri@cpan.org>
Date: Fri, 26 Jul 2019 17:31:15 +0200
Subject: [PATCH 3/3] Replace Text::Markdown and HTML::Restrict with CommonMark
for much better comment rendering speed and security
---
cpanfile | 2 -
docker/travis_test/Dockerfile | 2 -
lib/OpenQA/Markdown.pm | 69 ++++++++---------
lib/OpenQA/Utils.pm | 1 +
openQA.spec | 2 +-
t/16-markdown.t | 142 +++++++++++++++++++++++++---------
t/api/10-jobgroups.t | 2 +-
t/fixtures/01-jobs.pl | 2 +-
t/ui/15-comments.t | 49 ++++++------
9 files changed, 166 insertions(+), 105 deletions(-)
diff --git a/cpanfile b/cpanfile
index 8159d6554..5dad876f9 100644
--- a/cpanfile
+++ b/cpanfile
@@ -76,8 +76,6 @@ requires 'Scalar::Util';
requires 'Sub::Install';
requires 'Sub::Name';
requires 'Text::Diff';
-requires 'Text::Markdown';
-requires 'HTML::Restrict';
requires 'CommonMark';
requires 'Time::HiRes';
requires 'Time::ParseDate';
diff --git a/docker/travis_test/Dockerfile b/docker/travis_test/Dockerfile
index 1e14c0679..e2a6d53a2 100644
--- a/docker/travis_test/Dockerfile
+++ b/docker/travis_test/Dockerfile
@@ -121,8 +121,6 @@ RUN zypper in -y -C \
'perl(Socket::MsgHdr)' \
'perl(Test::Warnings)' \
'perl(Text::Diff)' \
- 'perl(Text::Markdown)' \
- 'perl(HTML::Restrict)' \
'perl(CommonMark)' \
'perl(Time::ParseDate)' \
'perl(XSLoader) >= 0.24' \
diff --git a/lib/OpenQA/Markdown.pm b/lib/OpenQA/Markdown.pm
index ddbcf0913..cf6745ce0 100644
--- a/lib/OpenQA/Markdown.pm
+++ b/lib/OpenQA/Markdown.pm
@@ -17,55 +17,54 @@ use Mojo::Base -strict;
use Exporter 'import';
use Regexp::Common 'URI';
-use OpenQA::Utils 'bugref_to_href';
-use Text::Markdown;
-use HTML::Restrict;
+use OpenQA::Utils qw(bugref_regex bugurl);
+use CommonMark;
-our @EXPORT_OK = qw(markdown_to_html);
+our @EXPORT_OK = qw(bugref_to_markdown is_light_color markdown_to_html);
-# Limit tags to a safe subset
-my $RULES = {
- a => [qw(href)],
- blockquote => [],
- code => [],
- em => [],
- img => [qw(src alt)],
- h1 => [],
- h2 => [],
- h3 => [],
- h4 => [],
- h5 => [],
- h6 => [],
- hr => [],
- li => [],
- ol => [],
- p => [],
- strong => [],
- ul => []};
+my $RE = bugref_regex;
-# Only allow "href=/...", "href=http://..." and "href=https://..."
-my $SCHEMES = [undef, 'http', 'https'];
+sub bugref_to_markdown {
+ my $text = shift;
+ $text =~ s/$RE/"[$+{match}](" . bugurl($+{match}) . ')'/geio;
+ return $text;
+}
-my $RESTRICT = HTML::Restrict->new(rules => $RULES, uri_schemes => $SCHEMES);
-my $MARKDOWN = Text::Markdown->new;
+sub is_light_color {
+ my $color = shift;
+ return undef unless $color =~ m/^#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})$/;
+ my ($red, $green, $blue) = ($1, $2, $3);
+ my $sum = hex($red) + hex($green) + hex($blue);
+ return $sum > 380;
+}
sub markdown_to_html {
my $text = shift;
- # Replace bugrefs with links
- $text = bugref_to_href($text);
+ $text = bugref_to_markdown($text);
# Turn all remaining URLs into links
- $text =~ s@(?<!['"(<>])($RE{URI})@<$1>@gi;
+ $text =~ s/(?<!['"(<>])($RE{URI})/<$1>/gio;
# Turn references to test modules and needling steps into links
- $text =~ s{\b(t#([\w/]+))}{<a href="/tests/$2">$1</a>}gi;
+ $text =~ s!\b(t#([\w/]+))![$1](/tests/$2)!gi;
- # Markdown -> HTML
- my $html = $MARKDOWN->markdown($text);
+ my $html = CommonMark->markdown_to_html($text);
+
+ # Custom markup "{{color:#ff0000|Some text}}"
+ $html =~ s/(\{\{([^|]+?)\|(.*?)\}\})/_custom($1, $2, $3)/ge;
+
+ return $html;
+}
- # Unsafe -> safe
- return $RESTRICT->process($html);
+sub _custom {
+ my ($full, $rules, $text) = @_;
+ if ($rules =~ /^color:(#[a-fA-F0-9]{6})$/) {
+ my $color = $1;
+ my $bg = is_light_color($color) ? 'black' : 'white';
+ return qq{<span style="color:$color;background-color:$bg">$text</span>};
+ }
+ return $full;
}
1;
diff --git a/lib/OpenQA/Utils.pm b/lib/OpenQA/Utils.pm
index d1ac1fa2f..0dc27766f 100644
--- a/lib/OpenQA/Utils.pm
+++ b/lib/OpenQA/Utils.pm
@@ -63,6 +63,7 @@ our @EXPORT = qw(
&parse_assets_from_settings
&find_bugref
&find_bugrefs
+ bugref_regex
&bugurl
&bugref_to_href
&href_to_bugref
diff --git a/openQA.spec b/openQA.spec
index 1f61418e2..5984ed027 100644
--- a/openQA.spec
+++ b/openQA.spec
@@ -45,7 +45,7 @@
%else
%define python_scripts_requires %{nil}
%endif
-%define t_requires perl(DBD::Pg) perl(DBIx::Class) perl(Config::IniFiles) perl(SQL::Translator) perl(Date::Format) perl(File::Copy::Recursive) perl(DateTime::Format::Pg) perl(Net::OpenID::Consumer) perl(Mojolicious::Plugin::RenderFile) perl(Mojolicious::Plugin::AssetPack) perl(aliased) perl(Config::Tiny) perl(DBIx::Class::DeploymentHandler) perl(DBIx::Class::DynamicDefault) perl(DBIx::Class::Schema::Config) perl(DBIx::Class::Storage::Statistics) perl(IO::Socket::SSL) perl(Data::Dump) perl(DBIx::Class::OptimisticLocking) perl(Module::Pluggable) perl(Text::Diff) perl(Text::Markdown) perl(HTML::Restrict) perl(CommonMark) perl(JSON::Validator) perl(YAML::XS) perl(IPC::Run) perl(Archive::Extract) perl(CSS::Minifier::XS) perl(JavaScript::Minifier::XS) perl(Time::ParseDate) perl(Sort::Versions) perl(Mojo::RabbitMQ::Client) perl(BSD::Resource) perl(Cpanel::JSON::XS) perl(Pod::POM) perl(Mojo::IOLoop::ReadWriteProcess) perl(Minion) perl(Mojo::Pg) perl(Mojo::SQLite) perl(Minion::Backend::SQLite) %python_scripts_requires
+%define t_requires perl(DBD::Pg) perl(DBIx::Class) perl(Config::IniFiles) perl(SQL::Translator) perl(Date::Format) perl(File::Copy::Recursive) perl(DateTime::Format::Pg) perl(Net::OpenID::Consumer) perl(Mojolicious::Plugin::RenderFile) perl(Mojolicious::Plugin::AssetPack) perl(aliased) perl(Config::Tiny) perl(DBIx::Class::DeploymentHandler) perl(DBIx::Class::DynamicDefault) perl(DBIx::Class::Schema::Config) perl(DBIx::Class::Storage::Statistics) perl(IO::Socket::SSL) perl(Data::Dump) perl(DBIx::Class::OptimisticLocking) perl(Module::Pluggable) perl(Text::Diff) perl(CommonMark) perl(JSON::Validator) perl(YAML::XS) perl(IPC::Run) perl(Archive::Extract) perl(CSS::Minifier::XS) perl(JavaScript::Minifier::XS) perl(Time::ParseDate) perl(Sort::Versions) perl(Mojo::RabbitMQ::Client) perl(BSD::Resource) perl(Cpanel::JSON::XS) perl(Pod::POM) perl(Mojo::IOLoop::ReadWriteProcess) perl(Minion) perl(Mojo::Pg) perl(Mojo::SQLite) perl(Minion::Backend::SQLite) %python_scripts_requires
Name: openQA
Version: 4.6
Release: 0
diff --git a/t/16-markdown.t b/t/16-markdown.t
index d6839cd7a..e0804169e 100644
--- a/t/16-markdown.t
+++ b/t/16-markdown.t
@@ -1,6 +1,6 @@
#!/usr/bin/env perl -w
-# Copyright (C) 2016 SUSE LLC
+# Copyright (C) 2019 SUSE LLC
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -18,71 +18,137 @@
use Mojo::Base -strict;
+BEGIN { unshift @INC, 'lib' }
+
use Test::More;
-use OpenQA::Markdown 'markdown_to_html';
+use OpenQA::Markdown qw(bugref_to_markdown is_light_color markdown_to_html);
subtest 'standard markdown' => sub {
- is markdown_to_html('Test'), '<p>Test</p>', 'HTML rendered';
- is markdown_to_html('# Test'), '<h1>Test</h1>', 'HTML rendered';
- is markdown_to_html('## Test'), '<h2>Test</h2>', 'HTML rendered';
- is markdown_to_html('### Test'), '<h3>Test</h3>', 'HTML rendered';
- is markdown_to_html('#### Test'), '<h4>Test</h4>', 'HTML rendered';
- is markdown_to_html('##### Test'), '<h5>Test</h5>', 'HTML rendered';
- is markdown_to_html('###### Test'), '<h6>Test</h6>', 'HTML rendered';
- is markdown_to_html("Test\n123\n\n456 789 tset\n"), qq{<p>Test\n123</p>\n\n<p>456 789 tset</p>}, 'HTML rendered';
- is markdown_to_html('*Test*'), '<p><em>Test</em></p>', 'HTML rendered';
- is markdown_to_html('**Test**'), '<p><strong>Test</strong></p>', 'HTML rendered';
- is markdown_to_html("1. a\n2. b\n3. c\n"), qq{<ol>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n</ol>}, 'HTML rendered';
- is markdown_to_html("* a\n* b\n* c\n"), qq{<ul>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n</ul>}, 'HTML rendered';
- is markdown_to_html('[Test](http://test.com)'), qq{<p><a href="http://test.com">Test</a></p>}, 'HTML rendered';
- is markdown_to_html('[Test](/test.html)'), qq{<p><a href="/test.html">Test</a></p>}, 'HTML rendered';
- is markdown_to_html('![Test](http://test.com)'), qq{<p><img src="http://test.com" alt="Test"></p>}, 'HTML rendered';
- is markdown_to_html('Test `123` 123'), '<p>Test <code>123</code> 123</p>', 'HTML rendered';
- is markdown_to_html("> test\n> 123"), "<blockquote>\n <p>test\n 123</p>\n</blockquote>", 'HTML rendered';
- is markdown_to_html('---'), '<hr>', 'HTML rendered';
+ is markdown_to_html('Test'), "<p>Test</p>\n", 'HTML rendered';
+ is markdown_to_html('# Test #'), "<h1>Test</h1>\n", 'HTML rendered';
+ is markdown_to_html('# Test'), "<h1>Test</h1>\n", 'HTML rendered';
+ is markdown_to_html('## Test'), "<h2>Test</h2>\n", 'HTML rendered';
+ is markdown_to_html('### Test'), "<h3>Test</h3>\n", 'HTML rendered';
+ is markdown_to_html('#### Test'), "<h4>Test</h4>\n", 'HTML rendered';
+ is markdown_to_html('##### Test'), "<h5>Test</h5>\n", 'HTML rendered';
+ is markdown_to_html('###### Test'), "<h6>Test</h6>\n", 'HTML rendered';
+ is markdown_to_html("Test\n123\n\n456 789 tset\n"), qq{<p>Test\n123</p>\n<p>456 789 tset</p>\n}, 'HTML rendered';
+ is markdown_to_html('*Test*'), "<p><em>Test</em></p>\n", 'HTML rendered';
+ is markdown_to_html('**Test**'), "<p><strong>Test</strong></p>\n", 'HTML rendered';
+ is markdown_to_html("1. a\n2. b\n3. c\n"), qq{<ol>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n</ol>\n}, 'HTML rendered';
+ is markdown_to_html("* a\n* b\n* c\n"), qq{<ul>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n</ul>\n}, 'HTML rendered';
+ is markdown_to_html('[Test](http://test.com)'), qq{<p><a href="http://test.com">Test</a></p>\n}, 'HTML rendered';
+ is markdown_to_html('[Test](/test.html)'), qq{<p><a href="/test.html">Test</a></p>\n}, 'HTML rendered';
+ is markdown_to_html('![Test](http://test.com)'), qq{<p><img src="http://test.com" alt="Test" /></p>\n},
+ 'HTML rendered';
+ is markdown_to_html('Test `123` 123'), "<p>Test <code>123</code> 123</p>\n", 'HTML rendered';
+ is markdown_to_html("> test\n> 123"), "<blockquote>\n<p>test\n123</p>\n</blockquote>\n", 'HTML rendered';
+ is markdown_to_html('---'), "<hr />\n", 'HTML rendered';
};
subtest 'bugrefs' => sub {
is markdown_to_html('boo#123'),
- qq{<p><a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a></p>}, 'bugref expanded';
+ qq{<p><a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a></p>\n}, 'bugref expanded';
is markdown_to_html('testing boo#123 123'),
- qq{<p>testing <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a> 123</p>},
+ qq{<p>testing <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a> 123</p>\n},
'bugref expanded';
is markdown_to_html('testing boo#123 123 boo#321'),
qq{<p>testing <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a> 123}
- . qq{ <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=321">boo#321</a></p>},
+ . qq{ <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=321">boo#321</a></p>\n},
'bugref expanded';
- is markdown_to_html("testing boo#123 \n123\n boo#321"),
- qq{<p>testing <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a> \n123\n}
- . qq{ <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=321">boo#321</a></p>},
+ is markdown_to_html("testing boo#123\n123\n boo#321"),
+ qq{<p>testing <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a>\n123\n}
+ . qq{<a href="https://bugzilla.opensuse.org/show_bug.cgi?id=321">boo#321</a></p>\n},
'bugref expanded';
is markdown_to_html("boo\ntesting boo#123 123\n123"),
- qq{<p>boo\ntesting <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a> 123\n123</p>},
+ qq{<p>boo\ntesting <a href="https://bugzilla.opensuse.org/show_bug.cgi?id=123">boo#123</a> 123\n123</p>\n},
'bugref expanded';
};
subtest 'openQA additions' => sub {
is markdown_to_html('https://example.com'),
- qq{<p><a href="https://example.com">https://example.com</a></p>}, 'URL turned into a link';
+ qq{<p><a href="https://example.com">https://example.com</a></p>\n}, 'URL turned into a link';
is markdown_to_html('testing https://example.com 123'),
- qq{<p>testing <a href="https://example.com">https://example.com</a> 123</p>}, 'URL turned into a link';
+ qq{<p>testing <a href="https://example.com">https://example.com</a> 123</p>\n}, 'URL turned into a link';
is markdown_to_html("t\ntesting https://example.com 123\n123"),
- qq{<p>t\ntesting <a href="https://example.com">https://example.com</a> 123\n123</p>}, 'URL turned into a link';
- is markdown_to_html('t#123'), qq{<p><a href="/tests/123">t#123</a></p>}, 'testref expanded';
- is markdown_to_html('testing t#123 123'), qq{<p>testing <a href="/tests/123">t#123</a> 123</p>}, 'testref expanded';
- is markdown_to_html("t\ntesting t#123 123\n123"), qq{<p>t\ntesting <a href="/tests/123">t#123</a> 123\n123</p>},
+ qq{<p>t\ntesting <a href="https://example.com">https://example.com</a> 123\n123</p>\n}, 'URL turned into a link';
+
+ is markdown_to_html('t#123'), qq{<p><a href="/tests/123">t#123</a></p>\n}, 'testref expanded';
+ is markdown_to_html('testing t#123 123'), qq{<p>testing <a href="/tests/123">t#123</a> 123</p>\n},
+ 'testref expanded';
+ is markdown_to_html("t\ntesting t#123 123\n123"), qq{<p>t\ntesting <a href="/tests/123">t#123</a> 123\n123</p>\n},
'testref expanded';
+
+ is markdown_to_html(qq{{{color:#ffffff|"Text"}}}),
+ qq{<p><span style="color:#ffffff;background-color:black">"Text"</span></p>\n},
+ 'White text';
+ is markdown_to_html("test {{color:#ff0000|Text}} 123"),
+ qq{<p>test <span style="color:#ff0000;background-color:white">Text</span> 123</p>\n}, 'Red text';
+ is markdown_to_html("test {{color:#FFFFFF|Text}} 123"),
+ qq{<p>test <span style="color:#FFFFFF;background-color:black">Text</span> 123</p>\n}, 'White text';
+ is markdown_to_html("test {{color:#00ff00|Some Text}} 123"),
+ qq{<p>test <span style="color:#00ff00;background-color:white">Some Text</span> 123</p>\n}, 'Green text';
+ is markdown_to_html("test {{color:#00ff00|Some Text}} 123 {{color:#0000ff|Also {w}orks}}"),
+ qq{<p>test <span style="color:#00ff00;background-color:white">Some Text</span> 123}
+ . qq{ <span style="color:#0000ff;background-color:white">Also {w}orks</span></p>\n},
+ 'Green and blue text';
+ is markdown_to_html("test {{ color: #00ff00 | Some Text }} 123"),
+ "<p>test {{ color: #00ff00 | Some Text }} 123</p>\n", 'Extra whitespace is not allowed';
+ is markdown_to_html("test {{color:javascript|Text}} 123"),
+ qq{<p>test {{color:javascript|Text}} 123</p>\n}, 'Invalid custom tag';
+ is markdown_to_html(qq{test {{javascript:alert("test")|Text}} 123}),
+ qq{<p>test {{javascript:alert("test")|Text}} 123</p>\n}, 'Invalid custom tag';
};
subtest 'unsafe HTML filtered out' => sub {
- is markdown_to_html('Test <script>alert("boom!");</script> 123'), '<p>Test 123</p>', 'unsafe HTML filtered';
- is markdown_to_html('<font>Test</font>'), '<p>Test</p>', 'unsafe HTML filtered';
- is markdown_to_html('Test [Boom!](javascript:alert("boom!")) 123'), '<p>Test <a>Boom!</a> 123</p>',
+ is markdown_to_html('Test <script>alert("boom!");</script> 123'),
+ "<p>Test <!-- raw HTML omitted -->alert("boom!");<!-- raw HTML omitted --> 123</p>\n",
+ 'unsafe HTML filtered';
+ is markdown_to_html('<font>Test</font>'), "<p><!-- raw HTML omitted -->Test<!-- raw HTML omitted --></p>\n",
+ 'unsafe HTML filtered';
+ is markdown_to_html('Test [Boom!](javascript:alert("boom!")) 123'), qq{<p>Test <a href="">Boom!</a> 123</p>\n},
'unsafe HTML filtered';
is markdown_to_html('<a href="/" onclick="someFunction()">Totally safe</a>'),
- '<p><a href="/">Totally safe</a></p>', 'unsafe HTML filtered';
+ "<p><!-- raw HTML omitted -->Totally safe<!-- raw HTML omitted --></p>\n", 'unsafe HTML filtered';
is markdown_to_html(qq{> hello <a name="n"\n> href="javascript:alert('boom!')">*you*</a>}),
- qq{<blockquote>\n <p>hello <a><em>you</em></a></p>\n</blockquote>}, 'unsafe HTML filtered';
+ qq{<blockquote>\n<p>hello <!-- raw HTML omitted --><em>you</em><!-- raw HTML omitted --></p>\n</blockquote>\n},
+ 'unsafe HTML filtered';
+ is markdown_to_html('{{color:#0000ff|<a>Test</a>}}'),
+ qq{<p><span style="color:#0000ff;background-color:white">}
+ . qq{<!-- raw HTML omitted -->Test<!-- raw HTML omitted --></span></p>\n},
+ 'unsafe HTML filtered';
+};
+
+subtest 'bugrefs to markdown' => sub {
+ is bugref_to_markdown('bnc#9876'), '[bnc#9876](https://bugzilla.suse.com/show_bug.cgi?id=9876)', 'right markdown';
+ is bugref_to_markdown('bsc#9876'), '[bsc#9876](https://bugzilla.suse.com/show_bug.cgi?id=9876)', 'right markdown';
+ is bugref_to_markdown('boo#9876'), '[boo#9876](https://bugzilla.opensuse.org/show_bug.cgi?id=9876)',
+ 'right markdown';
+ is bugref_to_markdown('bgo#9876'), '[bgo#9876](https://bugzilla.gnome.org/show_bug.cgi?id=9876)', 'right markdown';
+ is bugref_to_markdown('brc#9876'), '[brc#9876](https://bugzilla.redhat.com/show_bug.cgi?id=9876)', 'right markdown';
+ is bugref_to_markdown('bko#9876'), '[bko#9876](https://bugzilla.kernel.org/show_bug.cgi?id=9876)', 'right markdown';
+ is bugref_to_markdown('poo#9876'), '[poo#9876](https://progress.opensuse.org/issues/9876)', 'right markdown';
+ is bugref_to_markdown('gh#foo/bar#1234'), '[gh#foo/bar#1234](https://github.com/foo/bar/issues/1234)',
+ 'right markdown';
+ is bugref_to_markdown('kde#9876'), '[kde#9876](https://bugs.kde.org/show_bug.cgi?id=9876)', 'right markdown';
+ is bugref_to_markdown('fdo#9876'), '[fdo#9876](https://bugs.freedesktop.org/show_bug.cgi?id=9876)',
+ 'right markdown';
+ is bugref_to_markdown('jsc#9876'), '[jsc#9876](https://jira.suse.de/browse/9876)', 'right markdown';
+ is bugref_to_markdown("boo#9876\n\ntest boo#211\n"),
+ "[boo#9876](https://bugzilla.opensuse.org/show_bug.cgi?id=9876)\n\n"
+ . "test [boo#211](https://bugzilla.opensuse.org/show_bug.cgi?id=211)\n",
+ 'right markdown';
+};
+
+subtest 'color detection' => sub {
+ ok !is_light_color('#000000'), 'dark';
+ ok !is_light_color('#ff0000'), 'dark';
+ ok !is_light_color('#00ff00'), 'dark';
+ ok !is_light_color('#0000ff'), 'dark';
+ ok !is_light_color('#0000FF'), 'dark';
+ ok is_light_color('#ffffff'), 'light';
+ ok is_light_color('#FFFFFF'), 'light';
+ ok !is_light_color('test'), 'not a color at all';
};
done_testing;
diff --git a/t/api/10-jobgroups.t b/t/api/10-jobgroups.t
index f45b8fd39..6240638b0 100644
--- a/t/api/10-jobgroups.t
+++ b/t/api/10-jobgroups.t
@@ -70,7 +70,7 @@ subtest 'list job groups' => sub() {
keep_important_logs_in_days => 120,
default_priority => 50,
carry_over_bugrefs => 1,
- description => "##Test description\n\nwith bugref bsc#1234",
+ description => "## Test description\n\nwith bugref bsc#1234",
template => undef,
keep_results_in_days => 365,
keep_important_results_in_days => 0,
diff --git a/t/fixtures/01-jobs.pl b/t/fixtures/01-jobs.pl
index c7b27b840..f7e07a409 100644
--- a/t/fixtures/01-jobs.pl
+++ b/t/fixtures/01-jobs.pl
@@ -32,7 +32,7 @@
id => 1001,
name => 'opensuse',
sort_order => 0,
- description => "##Test description\n\nwith bugref bsc#1234",
+ description => "## Test description\n\nwith bugref bsc#1234",
},
JobGroups => {
id => 1002,
diff --git a/t/ui/15-comments.t b/t/ui/15-comments.t
index 30aa9aca4..bd841f418 100644
--- a/t/ui/15-comments.t
+++ b/t/ui/15-comments.t
@@ -194,26 +194,29 @@ subtest 'commenting in the group overview' => sub {
};
subtest 'URL auto-replace' => sub {
- $driver->find_element_by_id('text')->send_keys('
- foo@bar foo#bar should not be detected as bugref
- bsc#2436346bla should not be detected, too
- bsc#2436347bla2
- <a href="https://openqa.example.com/foo/bar">https://openqa.example.com/foo/bar</a>: http://localhost:9562
- https://openqa.example.com/tests/181148 (reference http://localhost/foo/bar )
- bsc#1234 boo#2345,poo#3456 t#4567 "some quotes suff should not cause problems"
- t#5678/modules/welcome/steps/1
- https://progress.opensuse.org/issues/6789
- https://bugzilla.novell.com/show_bug.cgi?id=7890
- [bsc#1000629](https://bugzilla.suse.com/show_bug.cgi?id=1000629)
- <a href="https://bugzilla.suse.com/show_bug.cgi?id=1000630">bsc#1000630</a>
- bnc#1246
- gh#os-autoinst/openQA#1234
- https://github.com/os-autoinst/os-autoinst/pull/960
- bgo#768954 brc#1401123
- https://bugzilla.gnome.org/show_bug.cgi?id=690345
- https://bugzilla.redhat.com/show_bug.cgi?id=343098
- [bsc#1043970](https://bugzilla.suse.com/show_bug.cgi?id=1043970 "Bugref at end of title: bsc#1043760")'
- );
+ my $build_url = $driver->get_current_url();
+ $build_url =~ s/\?.*//;
+ OpenQA::Utils::log_debug('build_url: ' . $build_url);
+ $driver->find_element_by_id('text')->send_keys(<<'EOF');
+foo@bar foo#bar should not be detected as bugref
+bsc#2436346bla should not be detected, too
+bsc#2436347bla2
+<a href="https://openqa.example.com/foo/bar">https://openqa.example.com/foo/bar</a>: http://localhost:9562
+https://openqa.example.com/tests/181148 (reference http://localhost/foo/bar )
+bsc#1234 boo#2345,poo#3456 t#4567 "some quotes suff should not cause problems"
+t#5678/modules/welcome/steps/1
+https://progress.opensuse.org/issues/6789
+https://bugzilla.novell.com/show_bug.cgi?id=7890
+[bsc#1000629](https://bugzilla.suse.com/show_bug.cgi?id=1000629)
+<a href="https://bugzilla.suse.com/show_bug.cgi?id=1000630">bsc#1000630</a>
+bnc#1246
+gh#os-autoinst/openQA#1234
+https://github.com/os-autoinst/os-autoinst/pull/960
+bgo#768954 brc#1401123
+https://bugzilla.gnome.org/show_bug.cgi?id=690345
+https://bugzilla.redhat.com/show_bug.cgi?id=343098
+[bsc#1043970](https://bugzilla.suse.com/show_bug.cgi?id=1043970 "Bugref at end of title: bsc#1043760")
+EOF
$driver->find_element_by_id('submitComment')->click();
wait_for_ajax;
@@ -226,8 +229,7 @@ subtest 'URL auto-replace' => sub {
qr(bsc#1234 boo#2345,poo#3456 t#4567 .*poo#6789 bsc#7890 bsc#1000629 bsc#1000630 bnc#1246 gh#os-autoinst/openQA#1234 gh#os-autoinst/os-autoinst#960 bgo#768954 brc#1401123)
);
my @urls = $driver->find_elements('div.media-comment a', 'css');
- is(scalar @urls, 21);
- is((shift @urls)->get_text(), 'https://openqa.example.com/foo/bar', "url1");
+ is(scalar @urls, 19);
is((shift @urls)->get_text(), 'http://localhost:9562', "url2");
is((shift @urls)->get_text(), 'https://openqa.example.com/tests/181148', "url3");
is((shift @urls)->get_text(), 'http://localhost/foo/bar', "url4");
@@ -239,7 +241,6 @@ qr(bsc#1234 boo#2345,poo#3456 t#4567 .*poo#6789 bsc#7890 bsc#1000629 bsc#1000630
is((shift @urls)->get_text(), 'poo#6789', "url10");
is((shift @urls)->get_text(), 'bsc#7890', "url11");
is((shift @urls)->get_text(), 'bsc#1000629', "url12");
- is((shift @urls)->get_text(), 'bsc#1000630', "url13");
is((shift @urls)->get_text(), 'bnc#1246', "url14");
is((shift @urls)->get_text(), 'gh#os-autoinst/openQA#1234', "url15");
is((shift @urls)->get_text(), 'gh#os-autoinst/os-autoinst#960', "url16");
@@ -250,7 +251,6 @@ qr(bsc#1234 boo#2345,poo#3456 t#4567 .*poo#6789 bsc#7890 bsc#1000629 bsc#1000630
is((shift @urls)->get_text(), 'bsc#1043970', "url21");
my @urls2 = $driver->find_elements('div.media-comment a', 'css');
- is((shift @urls2)->get_attribute('href'), 'https://openqa.example.com/foo/bar', "url1-href");
is((shift @urls2)->get_attribute('href'), 'http://localhost:9562/', "url2-href");
is((shift @urls2)->get_attribute('href'), 'https://openqa.example.com/tests/181148', "url3-href");
is((shift @urls2)->get_attribute('href'), 'http://localhost/foo/bar', "url4-href");
@@ -262,7 +262,6 @@ qr(bsc#1234 boo#2345,poo#3456 t#4567 .*poo#6789 bsc#7890 bsc#1000629 bsc#1000630
is((shift @urls2)->get_attribute('href'), 'https://progress.opensuse.org/issues/6789', "url10-href");
is((shift @urls2)->get_attribute('href'), 'https://bugzilla.suse.com/show_bug.cgi?id=7890', "url11-href");
is((shift @urls2)->get_attribute('href'), 'https://bugzilla.suse.com/show_bug.cgi?id=1000629', "url12-href");
- is((shift @urls2)->get_attribute('href'), 'https://bugzilla.suse.com/show_bug.cgi?id=1000630', "url13-href");
is((shift @urls2)->get_attribute('href'), 'https://bugzilla.suse.com/show_bug.cgi?id=1246', "url14-href");
is((shift @urls2)->get_attribute('href'), 'https://github.com/os-autoinst/openQA/issues/1234', "url15-href");
is((shift @urls2)->get_attribute('href'), 'https://github.com/os-autoinst/os-autoinst/issues/960', "url16-href");