Download core/Tracker/Failures.php from Leon4gr45/matomo: direct link, hf CLI and curl.
- Browser
- Download file 7.48 kB
-
https://huggingface.co/spaces/Leon4gr45/matomo/resolve/main/core/Tracker/Failures.php
- Command line
-
hf download hf://spaces/Leon4gr45/matomo/core/Tracker/Failures.php
-
curl -L -o Failures.php https://huggingface.co/spaces/Leon4gr45/matomo/resolve/main/core/Tracker/Failures.php
7.48 kB
| /** | |
| * Matomo - free/libre analytics platform | |
| * | |
| * @link https://matomo.org | |
| * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later | |
| */ | |
| namespace Piwik\Tracker; | |
| use Piwik\Common; | |
| use Piwik\Date; | |
| use Piwik\Exception\InvalidRequestParameterException; | |
| use Piwik\Exception\UnexpectedWebsiteFoundException; | |
| use Piwik\Piwik; | |
| use Piwik\Site; | |
| use Piwik\Db as PiwikDb; | |
| use Piwik\Url; | |
| class Failures | |
| { | |
| public const CLEANUP_OLD_FAILURES_DAYS = 2; | |
| public const FAILURE_ID_INVALID_SITE = 1; | |
| public const FAILURE_ID_NOT_AUTHENTICATED = 2; | |
| private $table = 'tracking_failure'; | |
| private $tablePrefixed; | |
| private $now; | |
| public function __construct() | |
| { | |
| $this->tablePrefixed = Common::prefixTable($this->table); | |
| } | |
| public function setNow(Date $now) | |
| { | |
| $this->now = $now; | |
| } | |
| private function getNow() | |
| { | |
| if (isset($this->now)) { | |
| return $this->now; | |
| } | |
| return Date::now(); | |
| } | |
| public function logFailure($idFailure, Request $request) | |
| { | |
| $isVisitExcluded = $request->getMetadata('CoreHome', 'isVisitExcluded'); | |
| if ($isVisitExcluded === null) { | |
| try { | |
| $visitExcluded = new VisitExcluded($request); | |
| $isVisitExcluded = $visitExcluded->isExcluded(); | |
| } catch (InvalidRequestParameterException $e) { | |
| // we ignore this error and assume visit is not excluded... happens eg when using `cip` and request was | |
| // not authenticated... | |
| $isVisitExcluded = false; | |
| } | |
| } | |
| if ($isVisitExcluded) { | |
| return; | |
| } | |
| $idSite = (int) $request->getIdSiteUnverified(); | |
| $idFailure = (int) $idFailure; | |
| if ($idSite > 9999999 || $idSite < 0 || $this->hasLoggedFailure($idSite, $idFailure)) { | |
| return; // we prevent creating huge amount of entries in the cache | |
| } | |
| $params = $this->getParamsWithTokenAnonymized($request); | |
| $sql = sprintf('INSERT INTO `%s` (`idsite`, `idfailure`, `date_first_occurred`, `request_url`) VALUES(?,?,?,?) ON DUPLICATE KEY UPDATE idsite=idsite;', $this->tablePrefixed); | |
| PiwikDb::get()->query($sql, array($idSite, $idFailure, $this->getNow()->getDatetime(), http_build_query($params))); | |
| } | |
| private function hasLoggedFailure($idSite, $idFailure) | |
| { | |
| $sql = sprintf('SELECT idsite FROM `%s` WHERE idsite = ? and idfailure = ?', $this->tablePrefixed); | |
| $row = PiwikDb::fetchRow($sql, array($idSite, $idFailure)); | |
| return !empty($row); | |
| } | |
| private function getParamsWithTokenAnonymized(Request $request) | |
| { | |
| // eg if there is a typo in the token auth we want to replace it as well to not accidentally leak a token | |
| // eg imagine a super user tries to issue an API request for a site and sending the wrong parameter for a token... | |
| // an admin may have view access for this and can see the super users token | |
| $token = $request->getTokenAuth(); | |
| $params = $request->getRawParams(); | |
| foreach (array('token_auth', 'token', 'tokenauth', 'token__auth') as $key) { | |
| if (isset($params[$key])) { | |
| $params[$key] = '__TOKEN_AUTH__'; | |
| } | |
| } | |
| foreach ($params as $key => $value) { | |
| if (!empty($token) && $value === $token) { | |
| $params[$key] = '__TOKEN_AUTH__'; // user accidentally posted the token in a wrong field | |
| } elseif ( | |
| !empty($value) && is_string($value) | |
| && mb_strlen($value) >= 29 && mb_strlen($value) <= 36 | |
| && ctype_xdigit($value) | |
| ) { | |
| $params[$key] = '__TOKEN_AUTH__'; // user maybe posted a token in a different field... it looks like it might be a token | |
| } | |
| } | |
| return $params; | |
| } | |
| public function removeFailuresOlderThanDays($days) | |
| { | |
| $minutesAgo = $this->getNow()->subDay($days)->getDatetime(); | |
| PiwikDb::query(sprintf('DELETE FROM `%s` WHERE date_first_occurred < ?', $this->tablePrefixed), [$minutesAgo]); | |
| } | |
| public function getAllFailures() | |
| { | |
| $failures = PiwikDb::fetchAll(sprintf('SELECT * FROM `%s`', $this->tablePrefixed)); | |
| return $this->enrichFailures($failures); | |
| } | |
| public function getFailuresForSites($idSites) | |
| { | |
| if (empty($idSites)) { | |
| return array(); | |
| } | |
| $idSites = array_map('intval', $idSites); | |
| $idSites = implode(',', $idSites); | |
| $failures = PiwikDb::fetchAll(sprintf('SELECT * FROM `%s` WHERE idsite IN (%s)', $this->tablePrefixed, $idSites)); | |
| return $this->enrichFailures($failures); | |
| } | |
| public function deleteTrackingFailure($idSite, $idFailure) | |
| { | |
| PiwikDb::query(sprintf('DELETE FROM `%s` WHERE idsite = ? and idfailure = ?', $this->tablePrefixed), [$idSite, $idFailure]); | |
| } | |
| public function deleteTrackingFailures($idSites) | |
| { | |
| if (!empty($idSites)) { | |
| $idSites = array_map('intval', $idSites); | |
| $idSites = implode(',', $idSites); | |
| PiwikDb::query(sprintf('DELETE FROM `%s` WHERE idsite IN(%s)', $this->tablePrefixed, $idSites)); | |
| } | |
| } | |
| public function deleteAllTrackingFailures() | |
| { | |
| PiwikDb::query(sprintf('DELETE FROM `%s`', $this->tablePrefixed)); | |
| } | |
| private function enrichFailures($failures) | |
| { | |
| foreach ($failures as &$failure) { | |
| try { | |
| $failure['site_name'] = Site::getNameFor($failure['idsite']); | |
| } catch (UnexpectedWebsiteFoundException $e) { | |
| $failure['site_name'] = Piwik::translate('General_Unknown'); | |
| } | |
| $failure['pretty_date_first_occurred'] = Date::factory($failure['date_first_occurred'])->getLocalized(Date::DATETIME_FORMAT_SHORT); | |
| parse_str($failure['request_url'], $params); | |
| if (empty($params['url'])) { | |
| $params['url'] = ' ';// workaround it using the default provider in request constructor | |
| } | |
| $request = new Request($params); | |
| $failure['url'] = trim($request->getParam('url')); | |
| $failure['problem'] = ''; | |
| $failure['solution'] = ''; | |
| $failure['solution_url'] = ''; | |
| switch ($failure['idfailure']) { | |
| case self::FAILURE_ID_INVALID_SITE: | |
| $failure['problem'] = Piwik::translate('CoreAdminHome_TrackingFailureInvalidSiteProblem'); | |
| $failure['solution'] = Piwik::translate('CoreAdminHome_TrackingFailureInvalidSiteSolution'); | |
| $failure['solution_url'] = Url::addCampaignParametersToMatomoLink('https://matomo.org/faq/how-to/faq_30838/'); | |
| break; | |
| case self::FAILURE_ID_NOT_AUTHENTICATED: | |
| $failure['problem'] = Piwik::translate('CoreAdminHome_TrackingFailureAuthenticationProblem'); | |
| $failure['solution'] = Piwik::translate('CoreAdminHome_TrackingFailureAuthenticationSolution'); | |
| $failure['solution_url'] = Url::addCampaignParametersToMatomoLink('https://matomo.org/faq/how-to/faq_30835/'); | |
| break; | |
| } | |
| } | |
| /** | |
| * @ignore | |
| * internal use only | |
| */ | |
| Piwik::postEvent('Tracking.makeFailuresHumanReadable', array(&$failures)); | |
| return $failures; | |
| } | |
| } | |