PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / trunk
Matomo Analytics – Powerful, Privacy-First Insights for WordPress vtrunk
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / core / Tracker / Failures.php
matomo / app / core / Tracker Last commit date
Config 4 months ago Db 3 months ago Handler 2 years ago Visit 1 month ago Action.php 3 months ago ActionPageview.php 2 years ago BotRequest.php 3 months ago BotRequestProcessor.php 1 month ago Cache.php 6 months ago Db.php 1 year ago Failures.php 6 months ago FingerprintSalt.php 1 year ago GoalManager.php 1 month ago Handler.php 2 years ago IgnoreCookie.php 1 year ago LogTable.php 1 year ago Model.php 6 months ago PageUrl.php 3 weeks ago Request.php 1 month ago RequestHandlerTrait.php 4 months ago RequestProcessor.php 1 month ago RequestSet.php 6 months ago Response.php 3 months ago ScheduledTasksRunner.php 1 year ago Settings.php 3 months ago TableLogAction.php 6 months ago TrackerCodeGenerator.php 1 year ago TrackerConfig.php 1 month ago Visit.php 3 months ago VisitExcluded.php 3 months ago VisitInterface.php 3 months ago Visitor.php 1 month ago VisitorNotFoundInDb.php 1 month ago VisitorRecognizer.php 1 year ago
Failures.php
173 lines
1 <?php
2
3 /**
4 * Matomo - free/libre analytics platform
5 *
6 * @link https://matomo.org
7 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
8 */
9 namespace Piwik\Tracker;
10
11 use Piwik\Common;
12 use Piwik\Date;
13 use Piwik\Exception\InvalidRequestParameterException;
14 use Piwik\Exception\UnexpectedWebsiteFoundException;
15 use Piwik\Piwik;
16 use Piwik\Site;
17 use Piwik\Db as PiwikDb;
18 use Piwik\Url;
19 class Failures
20 {
21 public const CLEANUP_OLD_FAILURES_DAYS = 2;
22 public const FAILURE_ID_INVALID_SITE = 1;
23 public const FAILURE_ID_NOT_AUTHENTICATED = 2;
24 private $table = 'tracking_failure';
25 private $tablePrefixed;
26 private $now;
27 public function __construct()
28 {
29 $this->tablePrefixed = Common::prefixTable($this->table);
30 }
31 public function setNow(Date $now)
32 {
33 $this->now = $now;
34 }
35 private function getNow()
36 {
37 if (isset($this->now)) {
38 return $this->now;
39 }
40 return Date::now();
41 }
42 public function logFailure($idFailure, \Piwik\Tracker\Request $request)
43 {
44 $isVisitExcluded = $request->getMetadata('CoreHome', 'isVisitExcluded');
45 if ($isVisitExcluded === null) {
46 try {
47 $visitExcluded = new \Piwik\Tracker\VisitExcluded($request);
48 $isVisitExcluded = $visitExcluded->isExcluded();
49 } catch (InvalidRequestParameterException $e) {
50 // we ignore this error and assume visit is not excluded... happens eg when using `cip` and request was
51 // not authenticated...
52 $isVisitExcluded = \false;
53 }
54 }
55 if ($isVisitExcluded) {
56 return;
57 }
58 $idSite = (int) $request->getIdSiteUnverified();
59 $idFailure = (int) $idFailure;
60 if ($idSite > 9999999 || $idSite < 0 || $this->hasLoggedFailure($idSite, $idFailure)) {
61 return;
62 // we prevent creating huge amount of entries in the cache
63 }
64 $params = $this->getParamsWithTokenAnonymized($request);
65 $sql = sprintf('INSERT INTO `%s` (`idsite`, `idfailure`, `date_first_occurred`, `request_url`) VALUES(?,?,?,?) ON DUPLICATE KEY UPDATE idsite=idsite;', $this->tablePrefixed);
66 PiwikDb::get()->query($sql, array($idSite, $idFailure, $this->getNow()->getDatetime(), http_build_query($params)));
67 }
68 private function hasLoggedFailure($idSite, $idFailure)
69 {
70 $sql = sprintf('SELECT idsite FROM `%s` WHERE idsite = ? and idfailure = ?', $this->tablePrefixed);
71 $row = PiwikDb::fetchRow($sql, array($idSite, $idFailure));
72 return !empty($row);
73 }
74 private function getParamsWithTokenAnonymized(\Piwik\Tracker\Request $request)
75 {
76 // eg if there is a typo in the token auth we want to replace it as well to not accidentally leak a token
77 // eg imagine a super user tries to issue an API request for a site and sending the wrong parameter for a token...
78 // an admin may have view access for this and can see the super users token
79 $token = $request->getTokenAuth();
80 $params = $request->getRawParams();
81 foreach (array('token_auth', 'token', 'tokenauth', 'token__auth') as $key) {
82 if (isset($params[$key])) {
83 $params[$key] = '__TOKEN_AUTH__';
84 }
85 }
86 foreach ($params as $key => $value) {
87 if (!empty($token) && $value === $token) {
88 $params[$key] = '__TOKEN_AUTH__';
89 // user accidentally posted the token in a wrong field
90 } elseif (!empty($value) && is_string($value) && mb_strlen($value) >= 29 && mb_strlen($value) <= 36 && ctype_xdigit($value)) {
91 $params[$key] = '__TOKEN_AUTH__';
92 // user maybe posted a token in a different field... it looks like it might be a token
93 }
94 }
95 return $params;
96 }
97 public function removeFailuresOlderThanDays($days)
98 {
99 $minutesAgo = $this->getNow()->subDay($days)->getDatetime();
100 PiwikDb::query(sprintf('DELETE FROM `%s` WHERE date_first_occurred < ?', $this->tablePrefixed), [$minutesAgo]);
101 }
102 public function getAllFailures()
103 {
104 $failures = PiwikDb::fetchAll(sprintf('SELECT * FROM `%s`', $this->tablePrefixed));
105 return $this->enrichFailures($failures);
106 }
107 public function getFailuresForSites($idSites)
108 {
109 if (empty($idSites)) {
110 return array();
111 }
112 $idSites = array_map('intval', $idSites);
113 $idSites = implode(',', $idSites);
114 $failures = PiwikDb::fetchAll(sprintf('SELECT * FROM `%s` WHERE idsite IN (%s)', $this->tablePrefixed, $idSites));
115 return $this->enrichFailures($failures);
116 }
117 public function deleteTrackingFailure($idSite, $idFailure)
118 {
119 PiwikDb::query(sprintf('DELETE FROM `%s` WHERE idsite = ? and idfailure = ?', $this->tablePrefixed), [$idSite, $idFailure]);
120 }
121 public function deleteTrackingFailures($idSites)
122 {
123 if (!empty($idSites)) {
124 $idSites = array_map('intval', $idSites);
125 $idSites = implode(',', $idSites);
126 PiwikDb::query(sprintf('DELETE FROM `%s` WHERE idsite IN(%s)', $this->tablePrefixed, $idSites));
127 }
128 }
129 public function deleteAllTrackingFailures()
130 {
131 PiwikDb::query(sprintf('DELETE FROM `%s`', $this->tablePrefixed));
132 }
133 private function enrichFailures($failures)
134 {
135 foreach ($failures as &$failure) {
136 try {
137 $failure['site_name'] = Site::getNameFor($failure['idsite']);
138 } catch (UnexpectedWebsiteFoundException $e) {
139 $failure['site_name'] = Piwik::translate('General_Unknown');
140 }
141 $failure['pretty_date_first_occurred'] = Date::factory($failure['date_first_occurred'])->getLocalized(Date::DATETIME_FORMAT_SHORT);
142 parse_str($failure['request_url'], $params);
143 if (empty($params['url'])) {
144 $params['url'] = ' ';
145 // workaround it using the default provider in request constructor
146 }
147 $request = new \Piwik\Tracker\Request($params);
148 $failure['url'] = trim($request->getParam('url'));
149 $failure['problem'] = '';
150 $failure['solution'] = '';
151 $failure['solution_url'] = '';
152 switch ($failure['idfailure']) {
153 case self::FAILURE_ID_INVALID_SITE:
154 $failure['problem'] = Piwik::translate('CoreAdminHome_TrackingFailureInvalidSiteProblem');
155 $failure['solution'] = Piwik::translate('CoreAdminHome_TrackingFailureInvalidSiteSolution');
156 $failure['solution_url'] = Url::addCampaignParametersToMatomoLink('https://matomo.org/faq/how-to/faq_30838/');
157 break;
158 case self::FAILURE_ID_NOT_AUTHENTICATED:
159 $failure['problem'] = Piwik::translate('CoreAdminHome_TrackingFailureAuthenticationProblem');
160 $failure['solution'] = Piwik::translate('CoreAdminHome_TrackingFailureAuthenticationSolution');
161 $failure['solution_url'] = Url::addCampaignParametersToMatomoLink('https://matomo.org/faq/how-to/faq_30835/');
162 break;
163 }
164 }
165 /**
166 * @ignore
167 * internal use only
168 */
169 Piwik::postEvent('Tracking.makeFailuresHumanReadable', array(&$failures));
170 return $failures;
171 }
172 }
173