diff options
author | Zoltan Flamis <flamisz@gmail.com> | 2021-03-28 22:06:59 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-28 22:06:59 +0300 |
commit | bdf47ae282cb51fa59f9e7c6a3f8bcf59d66757a (patch) | |
tree | 77666da01c36f8e5ef5ab1a3fa0ee9f46a9e3874 | |
parent | bcfc9833e5948fc8822ca72e7489ad841cb69cb8 (diff) |
not supported browser exception (#17258)
unsupported browser warning
12 files changed, 256 insertions, 4 deletions
diff --git a/core/Exception/NotSupportedBrowserException.php b/core/Exception/NotSupportedBrowserException.php new file mode 100644 index 0000000000..ebcd55f990 --- /dev/null +++ b/core/Exception/NotSupportedBrowserException.php @@ -0,0 +1,13 @@ +<?php +/** + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Exception; + +class NotSupportedBrowserException extends Exception +{ +} diff --git a/core/FrontController.php b/core/FrontController.php index d9c0a6b3f8..5be3a2ba4f 100644 --- a/core/FrontController.php +++ b/core/FrontController.php @@ -22,6 +22,7 @@ use Piwik\Http\Router; use Piwik\Plugins\CoreAdminHome\CustomLogo; use Piwik\Session\SessionAuth; use Piwik\Session\SessionInitializer; +use Piwik\SupportedBrowser; use Psr\Log\LoggerInterface; /** @@ -154,7 +155,7 @@ class FrontController extends Singleton if (self::$enableDispatch === false) { return; } - + $filter = new Router(); $redirection = $filter->filterUrl(Url::getCurrentUrl()); if ($redirection !== null) { @@ -418,6 +419,10 @@ class FrontController extends Singleton $this->makeAuthenticator($sessionAuth); // Piwik\Auth must be set to the correct Login plugin } + if ($this->isSupportedBrowserCheckNeeded()) { + SupportedBrowser::checkIfBrowserSupported(); + } + // Force the auth to use the token_auth if specified, so that embed dashboard // and all other non widgetized controller methods works fine if (Common::getRequestVar('token_auth', '', 'string') !== '' @@ -743,4 +748,44 @@ class FrontController extends Singleton $requestId = self::getUniqueRequestId(); Common::sendHeader("X-Matomo-Request-Id: $requestId"); } + + private function isSupportedBrowserCheckNeeded() + { + if (defined('PIWIK_ENABLE_DISPATCH') && !PIWIK_ENABLE_DISPATCH) { + return false; + } + + $userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; + if ($userAgent === '') { + return false; + } + + $isTestMode = defined('PIWIK_TEST_MODE') && PIWIK_TEST_MODE; + if (!$isTestMode && Common::isPhpCliMode() === true) { + return false; + } + + if (Piwik::getModule() === 'API' && (empty(Piwik::getAction()) || Piwik::getAction() === 'index' || Piwik::getAction() === 'glossary')) { + return false; + } + + if (Piwik::getModule() === 'Widgetize') { + return true; + } + + $generalConfig = Config::getInstance()->General; + if ($generalConfig['enable_framed_pages'] == '1' || $generalConfig['enable_framed_settings'] == '1') { + return true; + } + + if (Common::getRequestVar('token_auth', '', 'string') !== '') { + return true; + } + + if (Piwik::isUserIsAnonymous()) { + return true; + } + + return false; + } } diff --git a/core/SupportedBrowser.php b/core/SupportedBrowser.php new file mode 100644 index 0000000000..d1111fd6ba --- /dev/null +++ b/core/SupportedBrowser.php @@ -0,0 +1,73 @@ +<?php +/** + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ + +namespace Piwik; + +use Piwik\Http; +use Piwik\Piwik; +use Piwik\Container\StaticContainer; +use Piwik\DeviceDetector\DeviceDetectorFactory; +use Piwik\Exception\NotSupportedBrowserException; + +class SupportedBrowser +{ + /** + * A list of browsers with version numbers that are not supported. A browser + * is not supported if it's included in this array and the version number + * is smaller or equal to the number in this array. If the user's browser + * not included in this list or the version number is higher, then + * supported. + * + * Current version numbers are coming from this list: + * https://caniuse.com/rel-noreferrer + */ + private static $notSupportedBrowsers = [ + 'FF' => 32, + 'IE' => 10, + 'SF' => 4, + 'CH' => 15, + 'OP' => 12, + 'PS' => 12, + ]; + + public static function checkIfBrowserSupported() + { + $userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; + if ($userAgent === '') { + return; + } + + $ddFactory = StaticContainer::get(DeviceDetectorFactory::class); + /** @var \DeviceDetector\DeviceDetector */ + $deviceDetector = $ddFactory->makeInstance($userAgent); + + $deviceDetector->parse(); + $client = $deviceDetector->getClient(); + + if ($client['type'] === 'browser' && self::browserNotSupported($client['short_name'], (int)$client['version'])) { + self::throwException(); + } + } + + private static function browserNotSupported($shortName, $version) + { + return array_key_exists($shortName, self::$notSupportedBrowsers) && $version > 0 && $version <= self::$notSupportedBrowsers[$shortName]; + } + + private static function throwException() + { + $message = "<p><b>" . Piwik::translate('General_ExceptionNotSupportedBrowserTitle') . "</b></p>"; + $message .= "<p>" . Piwik::translate('General_ExceptionNotSupportedBrowserText') . "</p>"; + + $exception = new NotSupportedBrowserException($message); + $exception->setIsHtmlMessage(); + + throw $exception; + } +} diff --git a/lang/en.json b/lang/en.json index e563adac20..9b599f54d4 100644 --- a/lang/en.json +++ b/lang/en.json @@ -210,6 +210,8 @@ "ExceptionWidgetNotFound": "The requested widget does not exist.", "ExceptionReportNotEnabled": "The requested report is not enabled. This means usually either the plugin that defines the report is deactivated or you do not have enough permission to access this report.", "ExceptionWidgetNotEnabled": "The requested widget is not enabled. This means usually either the plugin that defines the widget is deactivated or you do not have enough permission to access this widget.", + "ExceptionNotSupportedBrowserTitle": "Your browser is not supported.", + "ExceptionNotSupportedBrowserText": "Due to security issues your browser is not supported. Please upgrade to a newer version.", "ExpandDataTableFooter": "Change the visualization or configure the report", "Export": "Export", "ExportAsImage": "Export as Image", diff --git a/tests/PHPUnit/Integration/FrontControllerTest.php b/tests/PHPUnit/Integration/FrontControllerTest.php index d9074f2cc6..b31af69882 100644 --- a/tests/PHPUnit/Integration/FrontControllerTest.php +++ b/tests/PHPUnit/Integration/FrontControllerTest.php @@ -48,7 +48,7 @@ FORMAT; $this->assertEquals('error', $response['result']); $expectedFormat = <<<FORMAT -test message on {includePath}/tests/resources/trigger-fatal-exception.php(23) #0 [internal function]: {closure}('CoreHome', 'index', Array) #1 {includePath}/core/EventDispatcher.php(141): call_user_func_array(Object(Closure), Array) #2 {includePath}/core/Piwik.php(809): Piwik\EventDispatcher->postEvent('Request.dispatc...', Array, false, Array) #3 {includePath}/core/FrontController.php(585): Piwik\Piwik::postEvent('Request.dispatc...', Array) #4 {includePath}/core/FrontController.php(166): Piwik\FrontController->doDispatch('CoreHome', 'index', Array) #5 {includePath}/tests/resources/trigger-fatal-exception.php(31): Piwik\FrontController->dispatch('CoreHome', 'index') #6 {main} +test message on {includePath}/tests/resources/trigger-fatal-exception.php(23) #0 [internal function]: {closure}('CoreHome', 'index', Array) #1 {includePath}/core/EventDispatcher.php(141): call_user_func_array(Object(Closure), Array) #2 {includePath}/core/Piwik.php(809): Piwik\EventDispatcher->postEvent('Request.dispatc...', Array, false, Array) #3 {includePath}/core/FrontController.php(590): Piwik\Piwik::postEvent('Request.dispatc...', Array) #4 {includePath}/core/FrontController.php(167): Piwik\FrontController->doDispatch('CoreHome', 'index', Array) #5 {includePath}/tests/resources/trigger-fatal-exception.php(31): Piwik\FrontController->dispatch('CoreHome', 'index') #6 {main} FORMAT; $this->assertStringMatchesFormat($expectedFormat, $response['message']); } @@ -88,4 +88,4 @@ FORMAT; parent::configureFixture($fixture); $fixture->createSuperUser = true; } -}
\ No newline at end of file +} diff --git a/tests/PHPUnit/Integration/SupportedBrowserTest.php b/tests/PHPUnit/Integration/SupportedBrowserTest.php new file mode 100644 index 0000000000..631df4f111 --- /dev/null +++ b/tests/PHPUnit/Integration/SupportedBrowserTest.php @@ -0,0 +1,53 @@ +<?php +/** + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +namespace Piwik\Tests\Integration; + +use Piwik\Http; +use Piwik\Site; +use Piwik\Piwik; +use Piwik\SupportedBrowser; +use Piwik\Tests\Framework\Fixture; +use Piwik\Plugins\SitesManager\API; +use Piwik\Exception\NotSupportedBrowserException; +use Piwik\Tests\Framework\TestCase\IntegrationTestCase; + +/** + * @group Core + */ +class SupportedBrowserTest extends IntegrationTestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + public function test_new_firefox_is_supported() + { + $firefoxUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 11.2; rv:85.0) Gecko/20100101 Firefox/85.0"; + $_SERVER['HTTP_USER_AGENT'] = $firefoxUserAgent; + + $this->assertNull(SupportedBrowser::checkIfBrowserSupported()); + } + + public function test_old_ie_is_not_supported() + { + $this->expectException(NotSupportedBrowserException::class); + + $ie10UserAgent = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"; + $_SERVER['HTTP_USER_AGENT'] = $ie10UserAgent; + + SupportedBrowser::checkIfBrowserSupported(); + } + + public function test_empty_user_agent_is_supported() + { + $_SERVER['HTTP_USER_AGENT'] = ''; + + $this->assertNull(SupportedBrowser::checkIfBrowserSupported()); + } +} diff --git a/tests/UI/expected-screenshots/SupportedBrowser_page_load_fails_when_browser_not_supported.png b/tests/UI/expected-screenshots/SupportedBrowser_page_load_fails_when_browser_not_supported.png new file mode 100644 index 0000000000..dc19084f6f --- /dev/null +++ b/tests/UI/expected-screenshots/SupportedBrowser_page_load_fails_when_browser_not_supported.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b097ccb4f1678fd1805df8180dc0c6b246fba36013b0c698ba0a98c20478bcf5 +size 53050 diff --git a/tests/UI/expected-screenshots/SupportedBrowser_page_loads_when_browser_supported.png b/tests/UI/expected-screenshots/SupportedBrowser_page_loads_when_browser_supported.png new file mode 100644 index 0000000000..17e14991b3 --- /dev/null +++ b/tests/UI/expected-screenshots/SupportedBrowser_page_loads_when_browser_supported.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:55ac98dd83533ee88ffb21322c56c61b671bce9b12a7479c771063e2bda3a0e0 +size 222526 diff --git a/tests/UI/expected-screenshots/SupportedBrowser_widget_load_fails_when_browser_not_supported.png b/tests/UI/expected-screenshots/SupportedBrowser_widget_load_fails_when_browser_not_supported.png new file mode 100644 index 0000000000..dc19084f6f --- /dev/null +++ b/tests/UI/expected-screenshots/SupportedBrowser_widget_load_fails_when_browser_not_supported.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b097ccb4f1678fd1805df8180dc0c6b246fba36013b0c698ba0a98c20478bcf5 +size 53050 diff --git a/tests/UI/expected-screenshots/SupportedBrowser_widget_loads_when_browser_supported.png b/tests/UI/expected-screenshots/SupportedBrowser_widget_loads_when_browser_supported.png new file mode 100644 index 0000000000..2224063300 --- /dev/null +++ b/tests/UI/expected-screenshots/SupportedBrowser_widget_loads_when_browser_supported.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:83902b2fd973fa560f0a354a226b6c5bb25ea60ec76e4081cae06d4fe80e814e +size 70647 diff --git a/tests/UI/specs/SupportedBrowser_spec.js b/tests/UI/specs/SupportedBrowser_spec.js new file mode 100644 index 0000000000..08df38602a --- /dev/null +++ b/tests/UI/specs/SupportedBrowser_spec.js @@ -0,0 +1,48 @@ +/*! + * Matomo - free/libre analytics platform + * + * Supported browser screenshot tests. + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +describe("SupportedBrowser", function () { + const widgetUrl = "?module=Widgetize&action=iframe&containerId=VisitOverviewWithGraph&disableLink=0&widget=1&moduleToWidgetize=CoreHome&actionToWidgetize=renderWidgetContainer&idSite=1&period=range&date=2012-01-12,2012-01-17&disableLink=1&widget=1"; + const generalParams = 'idSite=1&period=year&date=2009-01-04'; + const pageUrl = '?module=CoreHome&action=index&' + generalParams; + const ie10UserAgent = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"; + const firefoxUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 11.2; rv:85.0) Gecko/20100101 Firefox/85.0"; + + before(function () { + testEnvironment.testUseMockAuth = 1; + testEnvironment.idSitesViewAccess = [1]; + testEnvironment.save(); + }); + + it("should load widget when browser supported", async function () { + page.setUserAgent(firefoxUserAgent); + await page.goto(widgetUrl); + expect(await page.screenshot({ fullPage: true })).to.matchImage('widget_loads_when_browser_supported'); + }); + + it("should load page when browser supported", async function () { + page.setUserAgent(firefoxUserAgent); + await page.goto(pageUrl); + expect(await page.screenshot({ fullPage: true })).to.matchImage('page_loads_when_browser_supported'); + }); + + it("should fail load widget when browser not supported", async function () { + page.setUserAgent(ie10UserAgent); + await page.goto(widgetUrl); + expect(await page.screenshot({ fullPage: true })).to.matchImage('widget_load_fails_when_browser_not_supported'); + }); + + it("should fail load page when browser not supported", async function () { + testEnvironment.testUseMockAuth = 0; + testEnvironment.save(); + page.setUserAgent(ie10UserAgent); + await page.goto(pageUrl); + expect(await page.screenshot({ fullPage: true })).to.matchImage('page_load_fails_when_browser_not_supported'); + }); +}); diff --git a/tests/UI/specs/ViewDataTable_spec.js b/tests/UI/specs/ViewDataTable_spec.js index 40067be829..b32160ed01 100644 --- a/tests/UI/specs/ViewDataTable_spec.js +++ b/tests/UI/specs/ViewDataTable_spec.js @@ -9,6 +9,12 @@ describe("ViewDataTableTest", function () { // TODO: should remove Test suffix from images instead of naming suites ...Test // TODO: rename screenshot files, remove numbers + + before(function () { + const firefoxUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 11.2; rv:85.0) Gecko/20100101 Firefox/85.0"; + page.setUserAgent(firefoxUserAgent); + }); + var url = "?module=Widgetize&action=iframe&moduleToWidgetize=Referrers&idSite=1&period=year&date=2012-08-09&" + "actionToWidgetize=getKeywords&viewDataTable=table&filter_limit=5&isFooterExpandedInDashboard=1"; @@ -243,4 +249,4 @@ describe("ViewDataTableTest", function () { // TODO: should remove Test suffix f await page.waitForNetworkIdle(); expect(await page.screenshot({ fullPage: true })).to.matchImage('exclude_low_population'); }); -});
\ No newline at end of file +}); |