diff options
-rw-r--r-- | application/bookmark/BookmarkInitializer.php | 4 | ||||
-rw-r--r-- | application/bookmark/LinkUtils.php | 8 | ||||
-rw-r--r-- | application/front/controller/visitor/ErrorController.php | 11 | ||||
-rw-r--r-- | assets/default/scss/shaarli.scss | 6 | ||||
-rw-r--r-- | inc/languages/fr/LC_MESSAGES/shaarli.po | 14 | ||||
-rw-r--r-- | tests/bookmark/LinkUtilsTest.php | 30 | ||||
-rw-r--r-- | tests/front/controller/visitor/ErrorControllerTest.php | 29 | ||||
-rw-r--r-- | tpl/default/error.html | 8 |
8 files changed, 94 insertions, 16 deletions
diff --git a/application/bookmark/BookmarkInitializer.php b/application/bookmark/BookmarkInitializer.php index 04b996f3..98dd3f1c 100644 --- a/application/bookmark/BookmarkInitializer.php +++ b/application/bookmark/BookmarkInitializer.php | |||
@@ -36,8 +36,8 @@ class BookmarkInitializer | |||
36 | public function initialize(): void | 36 | public function initialize(): void |
37 | { | 37 | { |
38 | $bookmark = new Bookmark(); | 38 | $bookmark = new Bookmark(); |
39 | $bookmark->setTitle('quicksilver (loop) on Vimeo ' . t('(private bookmark with thumbnail demo)')); | 39 | $bookmark->setTitle('Calm Jazz Music - YouTube ' . t('(private bookmark with thumbnail demo)')); |
40 | $bookmark->setUrl('https://vimeo.com/153493904'); | 40 | $bookmark->setUrl('https://www.youtube.com/watch?v=DVEUcbPkb-c'); |
41 | $bookmark->setDescription(t( | 41 | $bookmark->setDescription(t( |
42 | 'Shaarli will automatically pick up the thumbnail for links to a variety of websites. | 42 | 'Shaarli will automatically pick up the thumbnail for links to a variety of websites. |
43 | 43 | ||
diff --git a/application/bookmark/LinkUtils.php b/application/bookmark/LinkUtils.php index 9493b0aa..cf97e3b0 100644 --- a/application/bookmark/LinkUtils.php +++ b/application/bookmark/LinkUtils.php | |||
@@ -68,16 +68,16 @@ function html_extract_tag($tag, $html) | |||
68 | $properties = implode('|', $propertiesKey); | 68 | $properties = implode('|', $propertiesKey); |
69 | // We need a OR here to accept either 'property=og:noquote' or 'property="og:unrelated og:my-tag"' | 69 | // We need a OR here to accept either 'property=og:noquote' or 'property="og:unrelated og:my-tag"' |
70 | $orCondition = '["\']?(?:og:)?'. $tag .'["\']?|["\'][^\'"]*?(?:og:)?' . $tag . '[^\'"]*?[\'"]'; | 70 | $orCondition = '["\']?(?:og:)?'. $tag .'["\']?|["\'][^\'"]*?(?:og:)?' . $tag . '[^\'"]*?[\'"]'; |
71 | // Try to retrieve OpenGraph image. | 71 | // Try to retrieve OpenGraph tag. |
72 | $ogRegex = '#<meta[^>]+(?:'. $properties .')=(?:'. $orCondition .')[^>]*content=["\'](.*?)["\'].*?>#'; | 72 | $ogRegex = '#<meta[^>]+(?:'. $properties .')=(?:'. $orCondition .')[^>]*content=(["\'])([^\1]*?)\1.*?>#'; |
73 | // If the attributes are not in the order property => content (e.g. Github) | 73 | // If the attributes are not in the order property => content (e.g. Github) |
74 | // New regex to keep this readable... more or less. | 74 | // New regex to keep this readable... more or less. |
75 | $ogRegexReverse = '#<meta[^>]+content=["\'](.*?)["\'][^>]+(?:'. $properties .')=(?:'. $orCondition .').*?>#'; | 75 | $ogRegexReverse = '#<meta[^>]+content=(["\'])([^\1]*?)\1[^>]+(?:'. $properties .')=(?:'. $orCondition .').*?>#'; |
76 | 76 | ||
77 | if (preg_match($ogRegex, $html, $matches) > 0 | 77 | if (preg_match($ogRegex, $html, $matches) > 0 |
78 | || preg_match($ogRegexReverse, $html, $matches) > 0 | 78 | || preg_match($ogRegexReverse, $html, $matches) > 0 |
79 | ) { | 79 | ) { |
80 | return $matches[1]; | 80 | return $matches[2]; |
81 | } | 81 | } |
82 | 82 | ||
83 | return false; | 83 | return false; |
diff --git a/application/front/controller/visitor/ErrorController.php b/application/front/controller/visitor/ErrorController.php index 8da11172..428e8254 100644 --- a/application/front/controller/visitor/ErrorController.php +++ b/application/front/controller/visitor/ErrorController.php | |||
@@ -26,8 +26,14 @@ class ErrorController extends ShaarliVisitorController | |||
26 | $response = $response->withStatus($throwable->getCode()); | 26 | $response = $response->withStatus($throwable->getCode()); |
27 | } else { | 27 | } else { |
28 | // Internal error (any other Throwable) | 28 | // Internal error (any other Throwable) |
29 | if ($this->container->conf->get('dev.debug', false)) { | 29 | if ($this->container->conf->get('dev.debug', false) || $this->container->loginManager->isLoggedIn()) { |
30 | $this->assignView('message', $throwable->getMessage()); | 30 | $this->assignView('message', t('Error: ') . $throwable->getMessage()); |
31 | $this->assignView( | ||
32 | 'text', | ||
33 | '<a href="https://github.com/shaarli/Shaarli/issues/new">' | ||
34 | . t('Please report it on Github.') | ||
35 | . '</a>' | ||
36 | ); | ||
31 | $this->assignView('stacktrace', exception2text($throwable)); | 37 | $this->assignView('stacktrace', exception2text($throwable)); |
32 | } else { | 38 | } else { |
33 | $this->assignView('message', t('An unexpected error occurred.')); | 39 | $this->assignView('message', t('An unexpected error occurred.')); |
@@ -36,7 +42,6 @@ class ErrorController extends ShaarliVisitorController | |||
36 | $response = $response->withStatus(500); | 42 | $response = $response->withStatus(500); |
37 | } | 43 | } |
38 | 44 | ||
39 | |||
40 | return $response->write($this->render('error')); | 45 | return $response->write($this->render('error')); |
41 | } | 46 | } |
42 | } | 47 | } |
diff --git a/assets/default/scss/shaarli.scss b/assets/default/scss/shaarli.scss index ed774a9d..cc8ccc1e 100644 --- a/assets/default/scss/shaarli.scss +++ b/assets/default/scss/shaarli.scss | |||
@@ -1276,11 +1276,15 @@ form { | |||
1276 | margin: 70px 0 25px; | 1276 | margin: 70px 0 25px; |
1277 | } | 1277 | } |
1278 | 1278 | ||
1279 | a { | ||
1280 | color: var(--main-color); | ||
1281 | } | ||
1282 | |||
1279 | pre { | 1283 | pre { |
1280 | margin: 0 20%; | 1284 | margin: 0 20%; |
1281 | padding: 20px 0; | 1285 | padding: 20px 0; |
1282 | text-align: left; | 1286 | text-align: left; |
1283 | line-height: .7em; | 1287 | line-height: 1em; |
1284 | } | 1288 | } |
1285 | } | 1289 | } |
1286 | 1290 | ||
diff --git a/inc/languages/fr/LC_MESSAGES/shaarli.po b/inc/languages/fr/LC_MESSAGES/shaarli.po index 4c363fa8..51bef6c7 100644 --- a/inc/languages/fr/LC_MESSAGES/shaarli.po +++ b/inc/languages/fr/LC_MESSAGES/shaarli.po | |||
@@ -1,8 +1,8 @@ | |||
1 | msgid "" | 1 | msgid "" |
2 | msgstr "" | 2 | msgstr "" |
3 | "Project-Id-Version: Shaarli\n" | 3 | "Project-Id-Version: Shaarli\n" |
4 | "POT-Creation-Date: 2020-11-05 16:47+0100\n" | 4 | "POT-Creation-Date: 2020-11-05 19:43+0100\n" |
5 | "PO-Revision-Date: 2020-11-05 16:48+0100\n" | 5 | "PO-Revision-Date: 2020-11-05 19:44+0100\n" |
6 | "Last-Translator: \n" | 6 | "Last-Translator: \n" |
7 | "Language-Team: Shaarli\n" | 7 | "Language-Team: Shaarli\n" |
8 | "Language: fr_FR\n" | 8 | "Language: fr_FR\n" |
@@ -501,7 +501,15 @@ msgstr "mois" | |||
501 | msgid "Monthly" | 501 | msgid "Monthly" |
502 | msgstr "Mensuel" | 502 | msgstr "Mensuel" |
503 | 503 | ||
504 | #: application/front/controller/visitor/ErrorController.php:33 | 504 | #: application/front/controller/visitor/ErrorController.php:30 |
505 | msgid "Error: " | ||
506 | msgstr "Erreur : " | ||
507 | |||
508 | #: application/front/controller/visitor/ErrorController.php:34 | ||
509 | msgid "Please report it on Github." | ||
510 | msgstr "Merci de la rapporter sur Github." | ||
511 | |||
512 | #: application/front/controller/visitor/ErrorController.php:39 | ||
505 | msgid "An unexpected error occurred." | 513 | msgid "An unexpected error occurred." |
506 | msgstr "Une erreur inattendue s'est produite." | 514 | msgstr "Une erreur inattendue s'est produite." |
507 | 515 | ||
diff --git a/tests/bookmark/LinkUtilsTest.php b/tests/bookmark/LinkUtilsTest.php index c2f9f930..ddab4e3c 100644 --- a/tests/bookmark/LinkUtilsTest.php +++ b/tests/bookmark/LinkUtilsTest.php | |||
@@ -169,6 +169,36 @@ class LinkUtilsTest extends TestCase | |||
169 | } | 169 | } |
170 | 170 | ||
171 | /** | 171 | /** |
172 | * Test html_extract_tag() with double quoted content containing single quote, and the opposite. | ||
173 | */ | ||
174 | public function testHtmlExtractExistentNameTagWithMixedQuotes(): void | ||
175 | { | ||
176 | $description = 'Bob and Alice share M&M\'s.'; | ||
177 | |||
178 | $html = '<meta property="og:description" content="' . $description . '">'; | ||
179 | $this->assertEquals($description, html_extract_tag('description', $html)); | ||
180 | |||
181 | $html = '<meta tag1="content1" property="og:unrelated1 og:description og:unrelated2" '. | ||
182 | 'tag2="content2" content="' . $description . '" tag3="content3">'; | ||
183 | $this->assertEquals($description, html_extract_tag('description', $html)); | ||
184 | |||
185 | $html = '<meta property="og:description" name="description" content="' . $description . '">'; | ||
186 | $this->assertEquals($description, html_extract_tag('description', $html)); | ||
187 | |||
188 | $description = 'Bob and Alice share "cookies".'; | ||
189 | |||
190 | $html = '<meta property="og:description" content=\'' . $description . '\'>'; | ||
191 | $this->assertEquals($description, html_extract_tag('description', $html)); | ||
192 | |||
193 | $html = '<meta tag1="content1" property="og:unrelated1 og:description og:unrelated2" '. | ||
194 | 'tag2="content2" content=\'' . $description . '\' tag3="content3">'; | ||
195 | $this->assertEquals($description, html_extract_tag('description', $html)); | ||
196 | |||
197 | $html = '<meta property="og:description" name="description" content=\'' . $description . '\'>'; | ||
198 | $this->assertEquals($description, html_extract_tag('description', $html)); | ||
199 | } | ||
200 | |||
201 | /** | ||
172 | * Test html_extract_tag() when the tag <meta name= is not found. | 202 | * Test html_extract_tag() when the tag <meta name= is not found. |
173 | */ | 203 | */ |
174 | public function testHtmlExtractNonExistentNameTag() | 204 | public function testHtmlExtractNonExistentNameTag() |
diff --git a/tests/front/controller/visitor/ErrorControllerTest.php b/tests/front/controller/visitor/ErrorControllerTest.php index 75408cf4..e18a6fa2 100644 --- a/tests/front/controller/visitor/ErrorControllerTest.php +++ b/tests/front/controller/visitor/ErrorControllerTest.php | |||
@@ -50,7 +50,31 @@ class ErrorControllerTest extends TestCase | |||
50 | } | 50 | } |
51 | 51 | ||
52 | /** | 52 | /** |
53 | * Test displaying error with any exception (no debug): only display an error occurred with HTTP 500. | 53 | * Test displaying error with any exception (no debug) while logged in: |
54 | * display full error details | ||
55 | */ | ||
56 | public function testDisplayAnyExceptionErrorNoDebugLoggedIn(): void | ||
57 | { | ||
58 | $request = $this->createMock(Request::class); | ||
59 | $response = new Response(); | ||
60 | |||
61 | // Save RainTPL assigned variables | ||
62 | $assignedVariables = []; | ||
63 | $this->assignTemplateVars($assignedVariables); | ||
64 | |||
65 | $this->container->loginManager->method('isLoggedIn')->willReturn(true); | ||
66 | |||
67 | $result = ($this->controller)($request, $response, new \Exception('abc')); | ||
68 | |||
69 | static::assertSame(500, $result->getStatusCode()); | ||
70 | static::assertSame('Error: abc', $assignedVariables['message']); | ||
71 | static::assertContainsPolyfill('Please report it on Github', $assignedVariables['text']); | ||
72 | static::assertArrayHasKey('stacktrace', $assignedVariables); | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * Test displaying error with any exception (no debug) while logged out: | ||
77 | * display standard error without detail | ||
54 | */ | 78 | */ |
55 | public function testDisplayAnyExceptionErrorNoDebug(): void | 79 | public function testDisplayAnyExceptionErrorNoDebug(): void |
56 | { | 80 | { |
@@ -61,10 +85,13 @@ class ErrorControllerTest extends TestCase | |||
61 | $assignedVariables = []; | 85 | $assignedVariables = []; |
62 | $this->assignTemplateVars($assignedVariables); | 86 | $this->assignTemplateVars($assignedVariables); |
63 | 87 | ||
88 | $this->container->loginManager->method('isLoggedIn')->willReturn(false); | ||
89 | |||
64 | $result = ($this->controller)($request, $response, new \Exception('abc')); | 90 | $result = ($this->controller)($request, $response, new \Exception('abc')); |
65 | 91 | ||
66 | static::assertSame(500, $result->getStatusCode()); | 92 | static::assertSame(500, $result->getStatusCode()); |
67 | static::assertSame('An unexpected error occurred.', $assignedVariables['message']); | 93 | static::assertSame('An unexpected error occurred.', $assignedVariables['message']); |
94 | static::assertArrayNotHasKey('text', $assignedVariables); | ||
68 | static::assertArrayNotHasKey('stacktrace', $assignedVariables); | 95 | static::assertArrayNotHasKey('stacktrace', $assignedVariables); |
69 | } | 96 | } |
70 | } | 97 | } |
diff --git a/tpl/default/error.html b/tpl/default/error.html index c3e0c3c1..34f9707d 100644 --- a/tpl/default/error.html +++ b/tpl/default/error.html | |||
@@ -9,13 +9,17 @@ | |||
9 | <div id="pageError" class="page-error-container center"> | 9 | <div id="pageError" class="page-error-container center"> |
10 | <h2>{$message}</h2> | 10 | <h2>{$message}</h2> |
11 | 11 | ||
12 | <img src="{$asset_path}/img/sad_star.png#" alt=""> | ||
13 | |||
14 | {if="!empty($text)"} | ||
15 | <p>{$text}</p> | ||
16 | {/if} | ||
17 | |||
12 | {if="!empty($stacktrace)"} | 18 | {if="!empty($stacktrace)"} |
13 | <pre> | 19 | <pre> |
14 | {$stacktrace} | 20 | {$stacktrace} |
15 | </pre> | 21 | </pre> |
16 | {/if} | 22 | {/if} |
17 | |||
18 | <img src="{$asset_path}/img/sad_star.png#" alt=""> | ||
19 | </div> | 23 | </div> |
20 | {include="page.footer"} | 24 | {include="page.footer"} |
21 | </body> | 25 | </body> |