diff options
author | mattab <matthieu.aubry@gmail.com> | 2016-10-03 00:08:02 +0300 |
---|---|---|
committer | mattab <matthieu.aubry@gmail.com> | 2016-10-03 00:08:02 +0300 |
commit | b27cbb96da5a6fd1f7ef1ef90c5c09ca1b875613 (patch) | |
tree | d721223ea9007a7de7031c99707bc1a6be7bffe0 | |
parent | bd5217287e84d8a2fdc457dd07ce63d78c5835b4 (diff) | |
parent | e692a36e11c65f9f302b650b67e859a4ded64ebe (diff) |
Merge remote-tracking branch 'origin/2.x-dev'2.16.3-rc2
Conflicts:
core/Version.php
-rw-r--r-- | core/Plugin/ControllerAdmin.php | 54 | ||||
-rw-r--r-- | core/Tracker/TrackerCodeGenerator.php | 16 | ||||
-rw-r--r-- | core/Updates/2.16.3-b3.php | 6 | ||||
-rw-r--r-- | core/Updates/2.16.3-rc2.php | 28 | ||||
-rw-r--r-- | core/Version.php | 2 | ||||
-rw-r--r-- | core/View.php | 26 | ||||
-rw-r--r-- | lang/en.json | 3 | ||||
-rw-r--r-- | plugins/CoreUpdater/Commands/Update.php | 8 | ||||
-rw-r--r-- | plugins/Dashboard/Dashboard.php | 23 | ||||
-rw-r--r-- | plugins/Morpheus/templates/javascriptCode.twig (renamed from plugins/Morpheus/templates/javascriptCode.tpl) | 7 | ||||
-rw-r--r-- | plugins/Referrers/Reports/GetReferrerType.php | 2 | ||||
-rw-r--r-- | tests/PHPUnit/Integration/Tracker/TrackerCodeGeneratorTest.php | 35 | ||||
-rw-r--r-- | tests/UI/expected-screenshots/DashboardManager_create_new.png | 4 | ||||
-rw-r--r-- | tests/UI/expected-screenshots/Dashboard_create_new.png | 4 | ||||
-rw-r--r-- | tests/UI/expected-screenshots/Dashboard_reset.png | 4 | ||||
-rw-r--r-- | tests/UI/expected-screenshots/UIIntegrationTest_dashboard2.png | 4 | ||||
-rw-r--r-- | tests/UI/expected-screenshots/UIIntegrationTest_dashboard3.png | 4 |
17 files changed, 174 insertions, 56 deletions
diff --git a/core/Plugin/ControllerAdmin.php b/core/Plugin/ControllerAdmin.php index e503a615e6..f24246944f 100644 --- a/core/Plugin/ControllerAdmin.php +++ b/core/Plugin/ControllerAdmin.php @@ -153,6 +153,42 @@ abstract class ControllerAdmin extends Controller Notification\Manager::notify('ControllerAdmin_EacceleratorIsUsed', $notification); } + /** + * PHP Version required by the next major Piwik version + * @return string + */ + private static function getNextRequiredMinimumPHP() + { + return '5.5.9'; + } + + private static function isUsingPhpVersionCompatibleWithNextPiwik() + { + return version_compare( PHP_VERSION, self::getNextRequiredMinimumPHP(), '>=' ); + } + + private static function notifyWhenPhpVersionIsNotCompatibleWithNextMajorPiwik() + { + if(self::isUsingPhpVersionCompatibleWithNextPiwik()) { + return; + } + + $youMustUpgradePHP = Piwik::translate('General_YouMustUpgradePhpVersionToReceiveLatestPiwik'); + $message = Piwik::translate('General_PiwikCannotBeUpgradedBecausePhpIsTooOld') + . ' ' + . sprintf(Piwik::translate('General_PleaseUpgradeYourPhpVersionSoYourPiwikDataStaysSecure'), self::getNextRequiredMinimumPHP()) + ; + + $notification = new Notification($message); + $notification->title = $youMustUpgradePHP; + $notification->priority = Notification::PRIORITY_LOW; + $notification->context = Notification::CONTEXT_WARNING; + $notification->type = Notification::TYPE_TRANSIENT; + $notification->flags = Notification::FLAG_NO_CLEAR; + NotificationManager::notify('PHPVersionTooOldForNewestPiwikCheck', $notification); + } + + private static function notifyWhenPhpVersionIsEOL() { $deprecatedMajorPhpVersion = null; @@ -167,9 +203,7 @@ abstract class ControllerAdmin extends Controller return; } - $nextRequiredMinimumPHP = '5.5'; - - $message = Piwik::translate('General_WarningPiwikWillStopSupportingPHPVersion', array($deprecatedMajorPhpVersion, $nextRequiredMinimumPHP)) + $message = Piwik::translate('General_WarningPiwikWillStopSupportingPHPVersion', array($deprecatedMajorPhpVersion, self::getNextRequiredMinimumPHP())) . "\n " . Piwik::translate('General_WarningPhpVersionXIsTooOld', $deprecatedMajorPhpVersion); @@ -243,10 +277,8 @@ abstract class ControllerAdmin extends Controller $view->isSuperUser = Piwik::hasUserSuperUserAccess(); self::notifyAnyInvalidPlugin(); - - self::checkPhpVersion($view); - self::notifyWhenPhpVersionIsEOL(); + self::notifyWhenPhpVersionIsNotCompatibleWithNextMajorPiwik(); self::notifyWhenDebugOnDemandIsEnabled('debug'); self::notifyWhenDebugOnDemandIsEnabled('debug_on_demand'); @@ -271,16 +303,6 @@ abstract class ControllerAdmin extends Controller return "Piwik " . Version::VERSION; } - /** - * Check if the current PHP version is >= 5.3. If not, a warning is displayed - * to the user. - */ - private static function checkPhpVersion($view) - { - $view->phpVersion = PHP_VERSION; - $view->phpIsNewEnough = version_compare($view->phpVersion, '5.3.0', '>='); - } - private static function isPhpVersion53() { return strpos(PHP_VERSION, '5.3') === 0; diff --git a/core/Tracker/TrackerCodeGenerator.php b/core/Tracker/TrackerCodeGenerator.php index ae1ef6d2e8..ffeea91b6a 100644 --- a/core/Tracker/TrackerCodeGenerator.php +++ b/core/Tracker/TrackerCodeGenerator.php @@ -12,6 +12,7 @@ use Piwik\Common; use Piwik\Piwik; use Piwik\Plugins\CustomVariables\CustomVariables; use Piwik\Plugins\SitesManager\API as APISitesManager; +use Piwik\View; /** * Generates the Javascript code to be inserted on every page of the website to track. @@ -46,8 +47,7 @@ class TrackerCodeGenerator $disableCookies = false ) { // changes made to this code should be mirrored in plugins/CoreAdminHome/javascripts/jsTrackingGenerator.js var generateJsCode - $jsCode = file_get_contents(PIWIK_INCLUDE_PATH . "/plugins/Morpheus/templates/javascriptCode.tpl"); - $jsCode = htmlentities($jsCode); + if (substr($piwikUrl, 0, 4) !== 'http') { $piwikUrl = 'http://' . $piwikUrl; } @@ -150,12 +150,6 @@ class TrackerCodeGenerator */ Piwik::postEvent('Piwik.getJavascriptCode', array(&$codeImpl, $parameters)); - if (!empty($codeImpl['loadAsync'])) { - $codeImpl['loadAsync'] = 'true'; - } else { - $codeImpl['loadAsync'] = 'false'; - } - $setTrackerUrl = 'var u="' . $codeImpl['protocol'] . '{$piwikUrl}/";'; if (!empty($codeImpl['httpsPiwikUrl'])) { @@ -164,6 +158,12 @@ class TrackerCodeGenerator } $codeImpl = array('setTrackerUrl' => htmlentities($setTrackerUrl)) + $codeImpl; + $view = new View('@Morpheus/javascriptCode'); + $view->disableCacheBuster(); + $view->loadAsync = $codeImpl['loadAsync']; + $jsCode = $view->render(); + $jsCode = htmlentities($jsCode); + foreach ($codeImpl as $keyToReplace => $replaceWith) { $jsCode = str_replace('{$' . $keyToReplace . '}', $replaceWith, $jsCode); } diff --git a/core/Updates/2.16.3-b3.php b/core/Updates/2.16.3-b3.php index a1175c9f4d..4d28615f6f 100644 --- a/core/Updates/2.16.3-b3.php +++ b/core/Updates/2.16.3-b3.php @@ -34,7 +34,11 @@ class Updates_2_16_3_b3 extends PiwikUpdates protected function adjustTimezoneBySite($hour, $idSite) { $timezone = Site::getTimezoneFor($idSite); - $dateTimeZone = new \DateTimeZone($timezone); + try { + $dateTimeZone = new \DateTimeZone($timezone); + } catch(\Exception $e) { + return; + } $timeZoneDifference = -ceil($dateTimeZone->getOffset(new \DateTime()) / 3600); return (24 + $hour + $timeZoneDifference) % 24; } diff --git a/core/Updates/2.16.3-rc2.php b/core/Updates/2.16.3-rc2.php new file mode 100644 index 0000000000..d2a394194e --- /dev/null +++ b/core/Updates/2.16.3-rc2.php @@ -0,0 +1,28 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Updates; + +use Piwik\Plugins\ScheduledReports\API as ScheduledReportsAPI; +use Piwik\Plugins\ScheduledReports\Model as ScheduledReportsModel; +use Piwik\Site; +use Piwik\Updater; +use Piwik\Updates as PiwikUpdates; + +/** + * Mark the upgrade as major as the field visit_entry_idaction_url was updated in https://github.com/piwik/piwik/pull/10510 + */ +class Updates_2_16_3_rc2 extends PiwikUpdates +{ + + public static function isMajorUpdate() + { + return true; + } + +} diff --git a/core/Version.php b/core/Version.php index 9206f9e905..15079e8aa7 100644 --- a/core/Version.php +++ b/core/Version.php @@ -20,7 +20,7 @@ final class Version * The current Piwik version. * @var string */ - const VERSION = '2.16.3-rc1'; + const VERSION = '2.16.3-rc2'; public function isStableVersion($version) { diff --git a/core/View.php b/core/View.php index 0a2cbabb67..0c9b379a67 100644 --- a/core/View.php +++ b/core/View.php @@ -116,6 +116,7 @@ class View implements ViewInterface protected $templateVars = array(); private $contentType = 'text/html; charset=utf-8'; private $xFrameOptions = null; + private $enableCacheBuster = true; /** * Constructor. @@ -146,6 +147,14 @@ class View implements ViewInterface } /** + * Disables the cache buster (adding of ?cb=...) to JavaScript and stylesheet files + */ + public function disableCacheBuster() + { + $this->enableCacheBuster = false; + } + + /** * Returns the template filename. * * @return string @@ -237,9 +246,8 @@ class View implements ViewInterface } else { $cacheBuster = UIAssetCacheBuster::getInstance()->piwikVersionBasedCacheBuster(); } - $this->cacheBuster = $cacheBuster; - + $this->loginModule = Piwik::getLoginPluginName(); $user = APIUsersManager::getInstance()->getUser($this->userLogin); @@ -260,6 +268,16 @@ class View implements ViewInterface return $this->renderTwigTemplate(); } + /** + * @internal + * @ignore + * @return Twig_Environment + */ + public function getTwig() + { + return $this->twig; + } + protected function renderTwigTemplate() { try { @@ -272,7 +290,9 @@ class View implements ViewInterface throw $ex; } - $output = $this->applyFilter_cacheBuster($output); + if ($this->enableCacheBuster) { + $output = $this->applyFilter_cacheBuster($output); + } $helper = new Theme; $output = $helper->rewriteAssetsPathToTheme($output); diff --git a/lang/en.json b/lang/en.json index a9856cc425..bbe45c2a77 100644 --- a/lang/en.json +++ b/lang/en.json @@ -395,6 +395,9 @@ "Warning": "Warning", "WarningPhpVersionXIsTooOld": "The PHP version %s you are using has reached its End of Life (EOL). You are strongly urged to upgrade to a current version, as using this version may expose you to security vulnerabilities and bugs that have been fixed in more recent versions of PHP.", "WarningPiwikWillStopSupportingPHPVersion": "Piwik will stop supporting PHP %1$s in the next major version. Upgrade your PHP to at least PHP %2$s, before it's too late!", + "YouMustUpgradePhpVersionToReceiveLatestPiwik": "You must upgrade your PHP version in order to receive the latest Piwik update.", + "PiwikCannotBeUpgradedBecausePhpIsTooOld": "Piwik cannot be upgraded to the latest major version because your PHP version is too old.", + "PleaseUpgradeYourPhpVersionSoYourPiwikDataStaysSecure": "Please upgrade your PHP version to at least PHP %s so your Piwik analytics data stays secure.", "WarningFileIntegrityNoManifest": "File integrity check could not be performed due to missing manifest.inc.php.", "WarningFileIntegrityNoManifestDeployingFromGit": "If you are deploying Piwik from Git, this message is normal.", "WarningFileIntegrityNoMd5file": "File integrity check could not be completed due to missing md5_file() function.", diff --git a/plugins/CoreUpdater/Commands/Update.php b/plugins/CoreUpdater/Commands/Update.php index 14865b6c33..4340f34e3e 100644 --- a/plugins/CoreUpdater/Commands/Update.php +++ b/plugins/CoreUpdater/Commands/Update.php @@ -163,6 +163,14 @@ class Update extends ConsoleCommand return; } + + if ($updater->hasMajorDbUpdate()) { + $output->writeln(array( + "", + sprintf("<comment>%s \n</comment>", Piwik::translate('CoreUpdater_MajorUpdateWarning1')) + )); + } + $output->writeln(array(" *** Note: this is a Dry Run ***", "")); foreach ($migrationQueries as $query) { diff --git a/plugins/Dashboard/Dashboard.php b/plugins/Dashboard/Dashboard.php index c25122bcea..2eaeea105f 100644 --- a/plugins/Dashboard/Dashboard.php +++ b/plugins/Dashboard/Dashboard.php @@ -62,37 +62,32 @@ class Dashboard extends \Piwik\Plugin $defaultLayout = $this->getLayoutForUser('', 1); if (empty($defaultLayout)) { - $topWidget = ''; + $advertisingWidget = ''; $advertising = StaticContainer::get('Piwik\ProfessionalServices\Advertising'); if ($advertising->areAdsForProfessionalServicesEnabled() && Plugin\Manager::getInstance()->isPluginActivated('ProfessionalServices')) { - $topWidget .= '{"uniqueId":"widgetProfessionalServicespromoServices",' - . '"parameters":{"module":"ProfessionalServices","action":"promoServices"}},'; + $advertisingWidget = '{"uniqueId":"widgetProfessionalServicespromoServices","parameters":{"module":"ProfessionalServices","action":"promoServices"}},'; } if (Piwik::hasUserSuperUserAccess()) { - $topWidget .= '{"uniqueId":"widgetCoreHomegetDonateForm",' - . '"parameters":{"module":"CoreHome","action":"getDonateForm"}},'; + $piwikPromoWidget = '{"uniqueId":"widgetCoreHomegetDonateForm","parameters":{"module":"CoreHome","action":"getDonateForm"}}'; } else { - $topWidget .= '{"uniqueId":"widgetCoreHomegetPromoVideo",' - . '"parameters":{"module":"CoreHome","action":"getPromoVideo"}},'; + $piwikPromoWidget = '{"uniqueId":"widgetCoreHomegetPromoVideo","parameters":{"module":"CoreHome","action":"getPromoVideo"}}'; } $defaultLayout = '[ [ - {"uniqueId":"widgetVisitsSummarygetEvolutionGraphcolumnsArray","parameters":{"module":"VisitsSummary","action":"getEvolutionGraph","columns":"nb_visits"}}, {"uniqueId":"widgetLivewidget","parameters":{"module":"Live","action":"widget"}}, - {"uniqueId":"widgetVisitorInterestgetNumberOfVisitsPerVisitDuration","parameters":{"module":"VisitorInterest","action":"getNumberOfVisitsPerVisitDuration"}} + ' . $piwikPromoWidget . ' ], [ - ' . $topWidget . ' - {"uniqueId":"widgetReferrersgetWebsites","parameters":{"module":"Referrers","action":"getWebsites"}}, - {"uniqueId":"widgetVisitTimegetVisitInformationPerServerTime","parameters":{"module":"VisitTime","action":"getVisitInformationPerServerTime"}} + {"uniqueId":"widgetVisitsSummarygetEvolutionGraphcolumnsArray","parameters":{"module":"VisitsSummary","action":"getEvolutionGraph","columns":"nb_visits"}}, + ' . $advertisingWidget . ' + {"uniqueId":"widgetVisitsSummarygetSparklines","parameters":{"module":"VisitsSummary","action":"getSparklines"}} ], [ {"uniqueId":"widgetUserCountryMapvisitorMap","parameters":{"module":"UserCountryMap","action":"visitorMap"}}, - {"uniqueId":"widgetDevicesDetectiongetBrowsers","parameters":{"module":"DevicesDetection","action":"getBrowsers"}}, - {"uniqueId":"widgetReferrersgetSearchEngines","parameters":{"module":"Referrers","action":"getSearchEngines"}}, + {"uniqueId":"widgetReferrersgetReferrerType","parameters":{"module":"Referrers","action":"getReferrerType"}}, {"uniqueId":"widgetExampleRssWidgetrssPiwik","parameters":{"module":"ExampleRssWidget","action":"rssPiwik"}} ] ]'; diff --git a/plugins/Morpheus/templates/javascriptCode.tpl b/plugins/Morpheus/templates/javascriptCode.twig index 1a9ea321c1..c18d850d34 100644 --- a/plugins/Morpheus/templates/javascriptCode.tpl +++ b/plugins/Morpheus/templates/javascriptCode.twig @@ -7,9 +7,12 @@ {$setTrackerUrl} {$optionsBeforeTrackerUrl}_paq.push(['setTrackerUrl', u+'piwik.php']); _paq.push(['setSiteId', '{$idSite}']); - var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; - g.type='text/javascript'; g.async={$loadAsync}; g.defer={$loadAsync}; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s); + {% if loadAsync %}var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; + g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);{% endif %} + })(); </script> +{% if not loadAsync %}<script type='text/javascript' src="{$protocol}{$piwikUrl}/piwik.js"> +{% endif %} <noscript><p><img src="{$protocol}{$piwikUrl}/piwik.php?idsite={$idSite}" style="border:0;" alt="" /></p></noscript> <!-- End Piwik Code --> diff --git a/plugins/Referrers/Reports/GetReferrerType.php b/plugins/Referrers/Reports/GetReferrerType.php index f5656bfa7f..c9e9fecb35 100644 --- a/plugins/Referrers/Reports/GetReferrerType.php +++ b/plugins/Referrers/Reports/GetReferrerType.php @@ -32,7 +32,7 @@ class GetReferrerType extends Base $this->constantRowsCount = true; $this->hasGoalMetrics = true; $this->order = 1; - $this->widgetTitle = 'General_Overview'; + $this->widgetTitle = 'Referrers_ReferrersOverview'; } public function getDefaultTypeViewDataTable() diff --git a/tests/PHPUnit/Integration/Tracker/TrackerCodeGeneratorTest.php b/tests/PHPUnit/Integration/Tracker/TrackerCodeGeneratorTest.php index 06f4bb5916..c8bce62d51 100644 --- a/tests/PHPUnit/Integration/Tracker/TrackerCodeGeneratorTest.php +++ b/tests/PHPUnit/Integration/Tracker/TrackerCodeGeneratorTest.php @@ -152,6 +152,41 @@ class TrackerCodeGeneratorTest extends IntegrationTestCase $this->assertEquals($expected, $jsTag); } + /** + * Tests the generated JS code with options before tracker url + */ + public function testJavascriptTrackingCode_loadSync() + { + $generator = new TrackerCodeGenerator(); + + Piwik::addAction('Piwik.getJavascriptCode', function (&$codeImpl) { + $codeImpl['loadAsync'] = false; + }); + + $jsTag = $generator->generate($idSite = 1, $piwikUrl = 'http://localhost/piwik', + $mergeSubdomains = true, $groupPageTitlesByDomain = true, $mergeAliasUrls = true); + + $expected = "<!-- Piwik --> +<script type="text/javascript"> + var _paq = _paq || []; + _paq.push([\"setDocumentTitle\", document.domain + \"/\" + document.title]); + _paq.push(['trackPageView']); + _paq.push(['enableLinkTracking']); + (function() { + var u="//localhost/piwik/"; + _paq.push(['setTrackerUrl', u+'piwik.php']); + _paq.push(['setSiteId', '1']); + + })(); +</script> +<script type='text/javascript' src="//localhost/piwik/piwik.js"> +<noscript><p><img src="//localhost/piwik/piwik.php?idsite=1" style="border:0;" alt="" /></p></noscript> +<!-- End Piwik Code --> +"; + + $this->assertEquals($expected, $jsTag); + } + public function testStringsAreEscaped() { $generator = new TrackerCodeGenerator(); diff --git a/tests/UI/expected-screenshots/DashboardManager_create_new.png b/tests/UI/expected-screenshots/DashboardManager_create_new.png index e36639ec0e..c486212492 100644 --- a/tests/UI/expected-screenshots/DashboardManager_create_new.png +++ b/tests/UI/expected-screenshots/DashboardManager_create_new.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e33d2b820fa52fc433162ef37f09e5795ad7c5ffe9d85bf434c535bd03cd65d -size 178449 +oid sha256:5a5b6ef6747ed60a4b02e18afea88445fac2fff1fa998d5323a63d0536f65dc0 +size 183133 diff --git a/tests/UI/expected-screenshots/Dashboard_create_new.png b/tests/UI/expected-screenshots/Dashboard_create_new.png index 1e998c1c6a..02e4f79baa 100644 --- a/tests/UI/expected-screenshots/Dashboard_create_new.png +++ b/tests/UI/expected-screenshots/Dashboard_create_new.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1ca5b84a4c179e17cd52e306257d6e2c09947183caf7070d70b9967c206128ce -size 177096 +oid sha256:1814baa7de7eea33713ce9763cc6324511e74e88da33480883ab414cf6c58207 +size 124794 diff --git a/tests/UI/expected-screenshots/Dashboard_reset.png b/tests/UI/expected-screenshots/Dashboard_reset.png index 0e0ada8bd5..5ea8ff141a 100644 --- a/tests/UI/expected-screenshots/Dashboard_reset.png +++ b/tests/UI/expected-screenshots/Dashboard_reset.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf73a7460b83bba451bfb2965967d0800e3fc65dc40c8193078a4a1d8f846bf9 -size 230592 +oid sha256:09a47f38d0145527bff138be2bf621b19221fd9d479e5e037dd76d66ae614591 +size 179942 diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_dashboard2.png b/tests/UI/expected-screenshots/UIIntegrationTest_dashboard2.png index f505ad79db..2db2e79d37 100644 --- a/tests/UI/expected-screenshots/UIIntegrationTest_dashboard2.png +++ b/tests/UI/expected-screenshots/UIIntegrationTest_dashboard2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:902f5b95d9722f593953f008d0513647345c390c79e24c3a0bf4e93637f208c7 -size 834058 +oid sha256:4f35d953200896f4d705672fc8a99e835b88a5c8a57cf36a9f14e6e7a97090d4 +size 798198 diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_dashboard3.png b/tests/UI/expected-screenshots/UIIntegrationTest_dashboard3.png index 2bc710e956..02edab4aaa 100644 --- a/tests/UI/expected-screenshots/UIIntegrationTest_dashboard3.png +++ b/tests/UI/expected-screenshots/UIIntegrationTest_dashboard3.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e8d41c09e18eb32654b1c10a55df388cee288ea4a15cb75c0a7ba0e5ed00c234 -size 471287 +oid sha256:c12087f2e99ce037b1303d15e9b101590719d5b8680b740eb759efe85d1d6729 +size 471911 |