PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.6.0
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.6.0
5.13.0 5.12.1 5.12.0 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 / Response.php
matomo / app / core / Tracker Last commit date
Db 4 years ago Handler 5 years ago TableLogAction 5 years ago Visit 5 years ago Action.php 5 years ago ActionPageview.php 5 years ago Cache.php 5 years ago Db.php 4 years ago Failures.php 5 years ago FingerprintSalt.php 6 years ago GoalManager.php 5 years ago Handler.php 5 years ago IgnoreCookie.php 4 years ago LogTable.php 5 years ago Model.php 5 years ago PageUrl.php 5 years ago Request.php 5 years ago RequestProcessor.php 5 years ago RequestSet.php 4 years ago Response.php 4 years ago ScheduledTasksRunner.php 5 years ago Settings.php 5 years ago TableLogAction.php 5 years ago TrackerCodeGenerator.php 4 years ago TrackerConfig.php 5 years ago Visit.php 4 years ago VisitExcluded.php 5 years ago VisitInterface.php 5 years ago Visitor.php 5 years ago VisitorNotFoundInDb.php 5 years ago VisitorRecognizer.php 5 years ago
Response.php
235 lines
1 <?php
2 /**
3 * Matomo - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 *
8 */
9 namespace Piwik\Tracker;
10
11 use Exception;
12 use Piwik\Common;
13 use Piwik\Config;
14 use Piwik\Profiler;
15 use Piwik\Timer;
16 use Piwik\Tracker;
17 use Piwik\Tracker\Db as TrackerDb;
18
19 class Response
20 {
21 private $timer;
22
23 private $content;
24
25 public function init(Tracker $tracker)
26 {
27 ob_start(); // we use ob_start only because of Common::printDebug, we should actually not really use ob_start
28
29 if ($tracker->isDebugModeEnabled() && TrackerConfig::getConfigValue('enable_sql_profiler')) {
30 $this->timer = new Timer();
31
32 TrackerDb::enableProfiling();
33 }
34 }
35
36 public function getOutput()
37 {
38 $this->outputAccessControlHeaders();
39
40 if (is_null($this->content) && ob_get_level() > 0) {
41 $this->content = ob_get_clean();
42 }
43
44 return $this->content;
45 }
46
47 /**
48 * Echos an error message & other information, then exits.
49 *
50 * @param Tracker $tracker
51 * @param Exception $e
52 * @param int $statusCode eg 500
53 */
54 public function outputException(Tracker $tracker, Exception $e, $statusCode)
55 {
56 Common::sendResponseCode($statusCode);
57 $this->logExceptionToErrorLog($e);
58
59 if ($tracker->isDebugModeEnabled()) {
60 Common::sendHeader('Content-Type: text/html; charset=utf-8');
61 $trailer = '<span style="color: #888888">Backtrace:<br /><pre>' . $e->getTraceAsString() . '</pre></span>';
62 $headerPage = file_get_contents(PIWIK_INCLUDE_PATH . '/plugins/Morpheus/templates/simpleLayoutHeader.tpl');
63 $footerPage = file_get_contents(PIWIK_INCLUDE_PATH . '/plugins/Morpheus/templates/simpleLayoutFooter.tpl');
64 $headerPage = str_replace('{$HTML_TITLE}', 'Matomo &rsaquo; Error', $headerPage);
65
66 echo $headerPage . '<p>' . $this->getMessageFromException($e) . '</p>' . $trailer . $footerPage;
67 } else {
68 $this->outputApiResponse($tracker);
69 }
70 }
71
72 public function outputResponse(Tracker $tracker)
73 {
74 if (!$tracker->shouldRecordStatistics()) {
75 Common::sendResponseCode(503);
76 $this->outputApiResponse($tracker);
77 Common::printDebug("Logging disabled, display transparent logo");
78 } elseif (!$tracker->hasLoggedRequests()) {
79 if (!$this->isHttpGetRequest() || !empty($_GET) || !empty($_POST)) {
80 Common::sendResponseCode(400);
81 }
82 Common::printDebug("Empty request => Matomo page");
83 echo "This resource is part of Matomo. Keep full control of your data with the leading free and open source <a href='https://matomo.org' target='_blank' rel='noopener noreferrer nofollow'>web analytics & conversion optimisation platform</a>.<br>\n";
84 echo "This file is the endpoint for the Matomo tracking API. If you want to access the Matomo UI or use the Reporting API, please use <a href='index.php'>index.php</a> instead.";
85 } else {
86 $this->outputApiResponse($tracker);
87 Common::printDebug("Nothing to notice => default behaviour");
88 }
89
90 Common::printDebug("End of the page.");
91
92 if ($tracker->isDebugModeEnabled()
93 && $tracker->isDatabaseConnected()
94 && TrackerDb::isProfilingEnabled()
95 ) {
96 $db = Tracker::getDatabase();
97 $db->recordProfiling();
98 Profiler::displayDbTrackerProfile($db);
99 }
100
101 if ($tracker->isDebugModeEnabled()) {
102 Common::printDebug($_COOKIE);
103 Common::printDebug((string)$this->timer);
104 }
105 }
106
107 private function outputAccessControlHeaders()
108 {
109 if (!$this->isHttpGetRequest()) {
110 $origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '*';
111 Common::sendHeader('Access-Control-Allow-Origin: ' . $origin);
112 Common::sendHeader('Access-Control-Allow-Credentials: true');
113 }
114 }
115
116 private function isHttpGetRequest()
117 {
118 $requestMethod = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
119
120 return strtoupper($requestMethod) === 'GET';
121 }
122
123 private function getOutputBuffer()
124 {
125 return ob_get_contents();
126 }
127
128 protected function hasAlreadyPrintedOutput()
129 {
130 return strlen($this->getOutputBuffer()) > 0;
131 }
132
133 private function outputApiResponse(Tracker $tracker)
134 {
135 if ($tracker->isDebugModeEnabled()) {
136 return;
137 }
138
139 if ($this->hasAlreadyPrintedOutput()) {
140 return;
141 }
142
143 $request = $_GET + $_POST;
144
145 if ($this->isHttpGetRequest()) {
146 Common::sendHeader('Cache-Control: no-store');
147 }
148
149 if (array_key_exists('send_image', $request) && $request['send_image'] === '0') {
150 Common::sendResponseCode(204);
151 return;
152 }
153
154 // Check for a custom tracking image
155 $customImage = Config::getInstance()->Tracker['custom_image'];
156 if (!empty($customImage) && $this->outputCustomImage($customImage)) {
157 return;
158 }
159
160 // No custom image defined, so output the default 1x1 base64 transparent gif
161 $this->outputTransparentGif();
162 }
163
164 /**
165 * Output a 1px x 1px transparent gif
166 */
167 private function outputTransparentGif()
168 {
169 $transGifBase64 = "R0lGODlhAQABAIAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==";
170 Common::sendHeader('Content-Type: image/gif');
171
172 echo base64_decode($transGifBase64);
173 }
174
175 /**
176 * Output a custom tracking image
177 *
178 * @param string $customImage The custom image setting specified in the config
179 *
180 * @return bool True if the custom image was successfully output, else false
181 */
182 private function outputCustomImage(string $customImage): bool
183 {
184 $supportedMimeTypes = ['image/png', 'image/gif', 'image/jpeg'];
185
186 $img = null;
187 $size = null;
188
189 if (strlen($customImage) > 2 && substr($customImage, -2) == '==') {
190 // Base64 image string
191 $img = base64_decode($customImage);
192 $size = getimagesizefromstring($img);
193 } else if (is_file($customImage) && is_readable($customImage)) {
194 // Image file
195 $img = file_get_contents($customImage);
196 $size = getimagesize($customImage); // imagesize is used to get the mime type
197 }
198
199 // Must have valid image data and a valid mime type to proceed
200 if ($img && $size && isset($size['mime']) && in_array($size['mime'], $supportedMimeTypes)) {
201 Common::sendHeader('Content-Type: '.$size['mime']);
202 echo $img;
203 return true;
204 }
205
206 return false;
207 }
208
209 /**
210 * Gets the error message to output when a tracking request fails.
211 *
212 * @param Exception $e
213 * @return string
214 */
215 protected function getMessageFromException($e)
216 {
217 // Note: duplicated from FormDatabaseSetup.isAccessDenied
218 // Avoid leaking the username/db name when access denied
219 if ($e->getCode() == 1044 || $e->getCode() == 42000) {
220 return "Error while connecting to the Matomo database - please check your credentials in config/config.ini.php file";
221 }
222
223 if (Common::isPhpCliMode()) {
224 return $e->getMessage() . "\n" . $e->getTraceAsString();
225 }
226
227 return $e->getMessage();
228 }
229
230 protected function logExceptionToErrorLog($e)
231 {
232 error_log(sprintf("Error in Matomo (tracker): %s", str_replace("\n", " ", $this->getMessageFromException($e))));
233 }
234 }
235