add piwik installation
This commit is contained in:
parent
90aa4ef157
commit
8c5d4f0c31
3197 changed files with 563902 additions and 0 deletions
861
www/analytics/core/Tracker.php
Normal file
861
www/analytics/core/Tracker.php
Normal file
|
|
@ -0,0 +1,861 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Tracker\Cache;
|
||||
use Piwik\Tracker\Db\DbException;
|
||||
use Piwik\Tracker\Db\Mysqli;
|
||||
use Piwik\Tracker\Db\Pdo\Mysql;
|
||||
use Piwik\Tracker\Request;
|
||||
use Piwik\Tracker\Visit;
|
||||
use Piwik\Tracker\VisitInterface;
|
||||
use Piwik\Plugins\PrivacyManager\Config as PrivacyManagerConfig;
|
||||
|
||||
/**
|
||||
* Class used by the logging script piwik.php called by the javascript tag.
|
||||
* Handles the visitor & his/her actions on the website, saves the data in the DB,
|
||||
* saves information in the cookie, etc.
|
||||
*
|
||||
* We try to include as little files as possible (no dependency on 3rd party modules).
|
||||
*
|
||||
*/
|
||||
class Tracker
|
||||
{
|
||||
protected $stateValid = self::STATE_NOTHING_TO_NOTICE;
|
||||
/**
|
||||
* @var Db
|
||||
*/
|
||||
protected static $db = null;
|
||||
|
||||
const STATE_NOTHING_TO_NOTICE = 1;
|
||||
const STATE_LOGGING_DISABLE = 10;
|
||||
const STATE_EMPTY_REQUEST = 11;
|
||||
const STATE_NOSCRIPT_REQUEST = 13;
|
||||
|
||||
// We use hex ID that are 16 chars in length, ie. 64 bits IDs
|
||||
const LENGTH_HEX_ID_STRING = 16;
|
||||
const LENGTH_BINARY_ID = 8;
|
||||
|
||||
static protected $forcedDateTime = null;
|
||||
static protected $forcedIpString = null;
|
||||
static protected $forcedVisitorId = null;
|
||||
|
||||
static protected $pluginsNotToLoad = array();
|
||||
static protected $pluginsToLoad = array();
|
||||
|
||||
/**
|
||||
* The set of visits to track.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $requests = array();
|
||||
|
||||
/**
|
||||
* The token auth supplied with a bulk visits POST.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $tokenAuth = null;
|
||||
|
||||
/**
|
||||
* Whether we're currently using bulk tracking or not.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $usingBulkTracking = false;
|
||||
|
||||
/**
|
||||
* The number of requests that have been successfully logged.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $countOfLoggedRequests = 0;
|
||||
|
||||
protected function outputAccessControlHeaders()
|
||||
{
|
||||
$requestMethod = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
|
||||
if ($requestMethod !== 'GET') {
|
||||
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '*';
|
||||
Common::sendHeader('Access-Control-Allow-Origin: ' . $origin);
|
||||
Common::sendHeader('Access-Control-Allow-Credentials: true');
|
||||
}
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
self::$forcedIpString = null;
|
||||
self::$forcedDateTime = null;
|
||||
self::$forcedVisitorId = null;
|
||||
$this->stateValid = self::STATE_NOTHING_TO_NOTICE;
|
||||
}
|
||||
|
||||
public static function setForceIp($ipString)
|
||||
{
|
||||
self::$forcedIpString = $ipString;
|
||||
}
|
||||
|
||||
public static function setForceDateTime($dateTime)
|
||||
{
|
||||
self::$forcedDateTime = $dateTime;
|
||||
}
|
||||
|
||||
public static function setForceVisitorId($visitorId)
|
||||
{
|
||||
self::$forcedVisitorId = $visitorId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not load the specified plugins (used during testing, to disable Provider plugin)
|
||||
* @param array $plugins
|
||||
*/
|
||||
static public function setPluginsNotToLoad($plugins)
|
||||
{
|
||||
self::$pluginsNotToLoad = $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of plugins to not load
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function getPluginsNotToLoad()
|
||||
{
|
||||
return self::$pluginsNotToLoad;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Tracker config
|
||||
*
|
||||
* @param string $name Setting name
|
||||
* @param mixed $value Value
|
||||
*/
|
||||
static private function updateTrackerConfig($name, $value)
|
||||
{
|
||||
$section = Config::getInstance()->Tracker;
|
||||
$section[$name] = $value;
|
||||
Config::getInstance()->Tracker = $section;
|
||||
}
|
||||
|
||||
protected function initRequests($args)
|
||||
{
|
||||
$rawData = self::getRawBulkRequest();
|
||||
if (!empty($rawData)) {
|
||||
$this->usingBulkTracking = strpos($rawData, '"requests"') || strpos($rawData, "'requests'");
|
||||
if ($this->usingBulkTracking) {
|
||||
return $this->authenticateBulkTrackingRequests($rawData);
|
||||
}
|
||||
}
|
||||
|
||||
// Not using bulk tracking
|
||||
$this->requests = $args ? $args : (!empty($_GET) || !empty($_POST) ? array($_GET + $_POST) : array());
|
||||
}
|
||||
|
||||
private static function getRequestsArrayFromBulkRequest($rawData)
|
||||
{
|
||||
$rawData = trim($rawData);
|
||||
$rawData = Common::sanitizeLineBreaks($rawData);
|
||||
|
||||
// POST data can be array of string URLs or array of arrays w/ visit info
|
||||
$jsonData = json_decode($rawData, $assoc = true);
|
||||
|
||||
$tokenAuth = Common::getRequestVar('token_auth', false, 'string', $jsonData);
|
||||
|
||||
$requests = array();
|
||||
if (isset($jsonData['requests'])) {
|
||||
$requests = $jsonData['requests'];
|
||||
}
|
||||
|
||||
return array( $requests, $tokenAuth);
|
||||
}
|
||||
|
||||
private function authenticateBulkTrackingRequests($rawData)
|
||||
{
|
||||
list($this->requests, $tokenAuth) = $this->getRequestsArrayFromBulkRequest($rawData);
|
||||
|
||||
if (empty($tokenAuth)) {
|
||||
throw new Exception( "token_auth must be specified when using Bulk Tracking Import. "
|
||||
." See <a href='http://developer.piwik.org/api-reference/tracking-api'>Tracking Doc</a>");
|
||||
}
|
||||
if (!empty($this->requests)) {
|
||||
|
||||
foreach ($this->requests as &$request) {
|
||||
// if a string is sent, we assume its a URL and try to parse it
|
||||
if (is_string($request)) {
|
||||
$params = array();
|
||||
|
||||
$url = @parse_url($request);
|
||||
if (!empty($url)) {
|
||||
@parse_str($url['query'], $params);
|
||||
$request = $params;
|
||||
}
|
||||
}
|
||||
|
||||
$requestObj = new Request($request, $tokenAuth);
|
||||
$this->loadTrackerPlugins($requestObj);
|
||||
|
||||
// a Bulk Tracking request that is not authenticated should fail
|
||||
if (!$requestObj->isAuthenticated()) {
|
||||
throw new Exception(sprintf("token_auth specified does not have Admin permission for idsite=%s",
|
||||
$requestObj->getIdSite()));
|
||||
}
|
||||
|
||||
$request = $requestObj;
|
||||
}
|
||||
}
|
||||
|
||||
return $tokenAuth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main - tracks the visit/action
|
||||
*
|
||||
* @param array $args Optional Request Array
|
||||
*/
|
||||
public function main($args = null)
|
||||
{
|
||||
try {
|
||||
$tokenAuth = $this->initRequests($args);
|
||||
} catch (Exception $ex) {
|
||||
$this->exitWithException($ex, true);
|
||||
}
|
||||
|
||||
$this->initOutputBuffer();
|
||||
|
||||
if (!empty($this->requests)) {
|
||||
|
||||
try {
|
||||
foreach ($this->requests as $params) {
|
||||
$isAuthenticated = $this->trackRequest($params, $tokenAuth);
|
||||
}
|
||||
$this->runScheduledTasksIfAllowed($isAuthenticated);
|
||||
} catch(DbException $e) {
|
||||
Common::printDebug($e->getMessage());
|
||||
}
|
||||
} else {
|
||||
$this->handleEmptyRequest(new Request($_GET + $_POST));
|
||||
}
|
||||
$this->end();
|
||||
|
||||
$this->flushOutputBuffer();
|
||||
}
|
||||
|
||||
protected function initOutputBuffer()
|
||||
{
|
||||
ob_start();
|
||||
}
|
||||
|
||||
protected function flushOutputBuffer()
|
||||
{
|
||||
ob_end_flush();
|
||||
}
|
||||
|
||||
protected function getOutputBuffer()
|
||||
{
|
||||
return ob_get_contents();
|
||||
}
|
||||
|
||||
|
||||
protected function shouldRunScheduledTasks()
|
||||
{
|
||||
// don't run scheduled tasks in CLI mode from Tracker, this is the case
|
||||
// where we bulk load logs & don't want to lose time with tasks
|
||||
return !Common::isPhpCliMode()
|
||||
&& $this->getState() != self::STATE_LOGGING_DISABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracker requests will automatically trigger the Scheduled tasks.
|
||||
* This is useful for users who don't setup the cron,
|
||||
* but still want daily/weekly/monthly PDF reports emailed automatically.
|
||||
*
|
||||
* This is similar to calling the API CoreAdminHome.runScheduledTasks (see misc/cron/archive.php)
|
||||
*/
|
||||
protected static function runScheduledTasks()
|
||||
{
|
||||
$now = time();
|
||||
|
||||
// Currently, there are no hourly tasks. When there are some,
|
||||
// this could be too aggressive minimum interval (some hours would be skipped in case of low traffic)
|
||||
$minimumInterval = Config::getInstance()->Tracker['scheduled_tasks_min_interval'];
|
||||
|
||||
// If the user disabled browser archiving, he has already setup a cron
|
||||
// To avoid parallel requests triggering the Scheduled Tasks,
|
||||
// Get last time tasks started executing
|
||||
$cache = Cache::getCacheGeneral();
|
||||
|
||||
if ($minimumInterval <= 0
|
||||
|| empty($cache['isBrowserTriggerEnabled'])
|
||||
) {
|
||||
Common::printDebug("-> Scheduled tasks not running in Tracker: Browser archiving is disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
$nextRunTime = $cache['lastTrackerCronRun'] + $minimumInterval;
|
||||
|
||||
if ((isset($GLOBALS['PIWIK_TRACKER_DEBUG_FORCE_SCHEDULED_TASKS']) && $GLOBALS['PIWIK_TRACKER_DEBUG_FORCE_SCHEDULED_TASKS'])
|
||||
|| $cache['lastTrackerCronRun'] === false
|
||||
|| $nextRunTime < $now
|
||||
) {
|
||||
$cache['lastTrackerCronRun'] = $now;
|
||||
Cache::setCacheGeneral($cache);
|
||||
self::initCorePiwikInTrackerMode();
|
||||
Option::set('lastTrackerCronRun', $cache['lastTrackerCronRun']);
|
||||
Common::printDebug('-> Scheduled Tasks: Starting...');
|
||||
|
||||
// save current user privilege and temporarily assume Super User privilege
|
||||
$isSuperUser = Piwik::hasUserSuperUserAccess();
|
||||
|
||||
// Scheduled tasks assume Super User is running
|
||||
Piwik::setUserHasSuperUserAccess();
|
||||
|
||||
// While each plugins should ensure that necessary languages are loaded,
|
||||
// we ensure English translations at least are loaded
|
||||
Translate::loadEnglishTranslation();
|
||||
|
||||
ob_start();
|
||||
CronArchive::$url = SettingsPiwik::getPiwikUrl();
|
||||
$cronArchive = new CronArchive();
|
||||
$cronArchive->runScheduledTasksInTrackerMode();
|
||||
|
||||
$resultTasks = ob_get_contents();
|
||||
ob_clean();
|
||||
|
||||
// restore original user privilege
|
||||
Piwik::setUserHasSuperUserAccess($isSuperUser);
|
||||
|
||||
foreach (explode('</pre>', $resultTasks) as $resultTask) {
|
||||
Common::printDebug(str_replace('<pre>', '', $resultTask));
|
||||
}
|
||||
|
||||
Common::printDebug('Finished Scheduled Tasks.');
|
||||
} else {
|
||||
Common::printDebug("-> Scheduled tasks not triggered.");
|
||||
}
|
||||
Common::printDebug("Next run will be from: " . date('Y-m-d H:i:s', $nextRunTime) . ' UTC');
|
||||
}
|
||||
|
||||
static public $initTrackerMode = false;
|
||||
|
||||
/**
|
||||
* Used to initialize core Piwik components on a piwik.php request
|
||||
* Eg. when cache is missed and we will be calling some APIs to generate cache
|
||||
*/
|
||||
static public function initCorePiwikInTrackerMode()
|
||||
{
|
||||
if (SettingsServer::isTrackerApiRequest()
|
||||
&& self::$initTrackerMode === false
|
||||
) {
|
||||
self::$initTrackerMode = true;
|
||||
require_once PIWIK_INCLUDE_PATH . '/core/Loader.php';
|
||||
require_once PIWIK_INCLUDE_PATH . '/core/Option.php';
|
||||
|
||||
$access = Access::getInstance();
|
||||
$config = Config::getInstance();
|
||||
|
||||
try {
|
||||
Db::get();
|
||||
} catch (Exception $e) {
|
||||
Db::createDatabaseObject();
|
||||
}
|
||||
|
||||
\Piwik\Plugin\Manager::getInstance()->loadCorePluginsDuringTracker();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Echos an error message & other information, then exits.
|
||||
*
|
||||
* @param Exception $e
|
||||
* @param bool $authenticated
|
||||
*/
|
||||
protected function exitWithException($e, $authenticated = false)
|
||||
{
|
||||
if ($this->usingBulkTracking) {
|
||||
// when doing bulk tracking we return JSON so the caller will know how many succeeded
|
||||
$result = array(
|
||||
'status' => 'error',
|
||||
'tracked' => $this->countOfLoggedRequests
|
||||
);
|
||||
// send error when in debug mode or when authenticated (which happens when doing log importing,
|
||||
if ((isset($GLOBALS['PIWIK_TRACKER_DEBUG']) && $GLOBALS['PIWIK_TRACKER_DEBUG'])
|
||||
|| $authenticated
|
||||
) {
|
||||
$result['message'] = $this->getMessageFromException($e);
|
||||
}
|
||||
Common::sendHeader('Content-Type: application/json');
|
||||
echo Common::json_encode($result);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($GLOBALS['PIWIK_TRACKER_DEBUG']) && $GLOBALS['PIWIK_TRACKER_DEBUG']) {
|
||||
Common::sendHeader('Content-Type: text/html; charset=utf-8');
|
||||
$trailer = '<span style="color: #888888">Backtrace:<br /><pre>' . $e->getTraceAsString() . '</pre></span>';
|
||||
$headerPage = file_get_contents(PIWIK_INCLUDE_PATH . '/plugins/Zeitgeist/templates/simpleLayoutHeader.tpl');
|
||||
$footerPage = file_get_contents(PIWIK_INCLUDE_PATH . '/plugins/Zeitgeist/templates/simpleLayoutFooter.tpl');
|
||||
$headerPage = str_replace('{$HTML_TITLE}', 'Piwik › Error', $headerPage);
|
||||
|
||||
echo $headerPage . '<p>' . $this->getMessageFromException($e) . '</p>' . $trailer . $footerPage;
|
||||
} // If not debug, but running authenticated (eg. during log import) then we display raw errors
|
||||
elseif ($authenticated) {
|
||||
Common::sendHeader('Content-Type: text/html; charset=utf-8');
|
||||
echo $this->getMessageFromException($e);
|
||||
} else {
|
||||
$this->outputTransparentGif();
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the date in the "Y-m-d H:i:s" PHP format
|
||||
*
|
||||
* @param int $timestamp
|
||||
* @return string
|
||||
*/
|
||||
public static function getDatetimeFromTimestamp($timestamp)
|
||||
{
|
||||
return date("Y-m-d H:i:s", $timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization
|
||||
*/
|
||||
protected function init(Request $request)
|
||||
{
|
||||
$this->loadTrackerPlugins($request);
|
||||
$this->handleTrackingApi($request);
|
||||
$this->handleDisabledTracker();
|
||||
$this->handleEmptyRequest($request);
|
||||
|
||||
Common::printDebug("Current datetime: " . date("Y-m-d H:i:s", $request->getCurrentTimestamp()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup
|
||||
*/
|
||||
protected function end()
|
||||
{
|
||||
if ($this->usingBulkTracking) {
|
||||
$result = array(
|
||||
'status' => 'success',
|
||||
'tracked' => $this->countOfLoggedRequests
|
||||
);
|
||||
Common::sendHeader('Content-Type: application/json');
|
||||
echo Common::json_encode($result);
|
||||
exit;
|
||||
}
|
||||
switch ($this->getState()) {
|
||||
case self::STATE_LOGGING_DISABLE:
|
||||
$this->outputTransparentGif();
|
||||
Common::printDebug("Logging disabled, display transparent logo");
|
||||
break;
|
||||
|
||||
case self::STATE_EMPTY_REQUEST:
|
||||
Common::printDebug("Empty request => Piwik page");
|
||||
echo "<a href='/'>Piwik</a> is a free open source web <a href='http://piwik.org'>analytics</a> that lets you keep control of your data.";
|
||||
break;
|
||||
|
||||
case self::STATE_NOSCRIPT_REQUEST:
|
||||
case self::STATE_NOTHING_TO_NOTICE:
|
||||
default:
|
||||
$this->outputTransparentGif();
|
||||
Common::printDebug("Nothing to notice => default behaviour");
|
||||
break;
|
||||
}
|
||||
Common::printDebug("End of the page.");
|
||||
|
||||
if ($GLOBALS['PIWIK_TRACKER_DEBUG'] === true) {
|
||||
if (isset(self::$db)) {
|
||||
self::$db->recordProfiling();
|
||||
Profiler::displayDbTrackerProfile(self::$db);
|
||||
}
|
||||
}
|
||||
|
||||
self::disconnectDatabase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory to create database objects
|
||||
*
|
||||
* @param array $configDb Database configuration
|
||||
* @throws Exception
|
||||
* @return \Piwik\Tracker\Db\Mysqli|\Piwik\Tracker\Db\Pdo\Mysql
|
||||
*/
|
||||
public static function factory($configDb)
|
||||
{
|
||||
/**
|
||||
* Triggered before a connection to the database is established by the Tracker.
|
||||
*
|
||||
* This event can be used to change the database connection settings used by the Tracker.
|
||||
*
|
||||
* @param array $dbInfos Reference to an array containing database connection info,
|
||||
* including:
|
||||
*
|
||||
* - **host**: The host name or IP address to the MySQL database.
|
||||
* - **username**: The username to use when connecting to the
|
||||
* database.
|
||||
* - **password**: The password to use when connecting to the
|
||||
* database.
|
||||
* - **dbname**: The name of the Piwik MySQL database.
|
||||
* - **port**: The MySQL database port to use.
|
||||
* - **adapter**: either `'PDO_MYSQL'` or `'MYSQLI'`
|
||||
* - **type**: The MySQL engine to use, for instance 'InnoDB'
|
||||
*/
|
||||
Piwik::postEvent('Tracker.getDatabaseConfig', array(&$configDb));
|
||||
|
||||
switch ($configDb['adapter']) {
|
||||
case 'PDO\MYSQL':
|
||||
case 'PDO_MYSQL': // old format pre Piwik 2
|
||||
require_once PIWIK_INCLUDE_PATH . '/core/Tracker/Db/Pdo/Mysql.php';
|
||||
return new Mysql($configDb);
|
||||
|
||||
case 'MYSQLI':
|
||||
require_once PIWIK_INCLUDE_PATH . '/core/Tracker/Db/Mysqli.php';
|
||||
return new Mysqli($configDb);
|
||||
}
|
||||
|
||||
throw new Exception('Unsupported database adapter ' . $configDb['adapter']);
|
||||
}
|
||||
|
||||
public static function connectPiwikTrackerDb()
|
||||
{
|
||||
$db = null;
|
||||
$configDb = Config::getInstance()->database;
|
||||
|
||||
if (!isset($configDb['port'])) {
|
||||
// before 0.2.4 there is no port specified in config file
|
||||
$configDb['port'] = '3306';
|
||||
}
|
||||
|
||||
$db = Tracker::factory($configDb);
|
||||
$db->connect();
|
||||
|
||||
return $db;
|
||||
}
|
||||
|
||||
protected static function connectDatabaseIfNotConnected()
|
||||
{
|
||||
if (!is_null(self::$db)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
self::$db = self::connectPiwikTrackerDb();
|
||||
} catch (Exception $e) {
|
||||
throw new DbException($e->getMessage(), $e->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Db
|
||||
*/
|
||||
public static function getDatabase()
|
||||
{
|
||||
self::connectDatabaseIfNotConnected();
|
||||
return self::$db;
|
||||
}
|
||||
|
||||
public static function disconnectDatabase()
|
||||
{
|
||||
if (isset(self::$db)) {
|
||||
self::$db->disconnect();
|
||||
self::$db = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Tracker_Visit object.
|
||||
* This method can be overwritten to use a different Tracker_Visit object
|
||||
*
|
||||
* @throws Exception
|
||||
* @return \Piwik\Tracker\Visit
|
||||
*/
|
||||
protected function getNewVisitObject()
|
||||
{
|
||||
$visit = null;
|
||||
|
||||
/**
|
||||
* Triggered before a new **visit tracking object** is created. Subscribers to this
|
||||
* event can force the use of a custom visit tracking object that extends from
|
||||
* {@link Piwik\Tracker\VisitInterface}.
|
||||
*
|
||||
* @param \Piwik\Tracker\VisitInterface &$visit Initialized to null, but can be set to
|
||||
* a new visit object. If it isn't modified
|
||||
* Piwik uses the default class.
|
||||
*/
|
||||
Piwik::postEvent('Tracker.makeNewVisitObject', array(&$visit));
|
||||
|
||||
if (is_null($visit)) {
|
||||
$visit = new Visit();
|
||||
} elseif (!($visit instanceof VisitInterface)) {
|
||||
throw new Exception("The Visit object set in the plugin must implement VisitInterface");
|
||||
}
|
||||
return $visit;
|
||||
}
|
||||
|
||||
protected function outputTransparentGif()
|
||||
{
|
||||
if (isset($GLOBALS['PIWIK_TRACKER_DEBUG'])
|
||||
&& $GLOBALS['PIWIK_TRACKER_DEBUG']
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen($this->getOutputBuffer()) > 0) {
|
||||
// If there was an error during tracker, return so errors can be flushed
|
||||
return;
|
||||
}
|
||||
$transGifBase64 = "R0lGODlhAQABAIAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==";
|
||||
Common::sendHeader('Content-Type: image/gif');
|
||||
|
||||
$this->outputAccessControlHeaders();
|
||||
|
||||
print(base64_decode($transGifBase64));
|
||||
}
|
||||
|
||||
protected function isVisitValid()
|
||||
{
|
||||
return $this->stateValid !== self::STATE_LOGGING_DISABLE
|
||||
&& $this->stateValid !== self::STATE_EMPTY_REQUEST;
|
||||
}
|
||||
|
||||
protected function getState()
|
||||
{
|
||||
return $this->stateValid;
|
||||
}
|
||||
|
||||
protected function setState($value)
|
||||
{
|
||||
$this->stateValid = $value;
|
||||
}
|
||||
|
||||
protected function loadTrackerPlugins(Request $request)
|
||||
{
|
||||
// Adding &dp=1 will disable the provider plugin, if token_auth is used (used to speed up bulk imports)
|
||||
$disableProvider = $request->getParam('dp');
|
||||
if (!empty($disableProvider)) {
|
||||
Tracker::setPluginsNotToLoad(array('Provider'));
|
||||
}
|
||||
|
||||
try {
|
||||
$pluginsTracker = \Piwik\Plugin\Manager::getInstance()->loadTrackerPlugins();
|
||||
Common::printDebug("Loading plugins: { " . implode(",", $pluginsTracker) . " }");
|
||||
} catch (Exception $e) {
|
||||
Common::printDebug("ERROR: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleEmptyRequest(Request $request)
|
||||
{
|
||||
$countParameters = $request->getParamsCount();
|
||||
if ($countParameters == 0) {
|
||||
$this->setState(self::STATE_EMPTY_REQUEST);
|
||||
}
|
||||
if ($countParameters == 1) {
|
||||
$this->setState(self::STATE_NOSCRIPT_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleDisabledTracker()
|
||||
{
|
||||
$saveStats = Config::getInstance()->Tracker['record_statistics'];
|
||||
if ($saveStats == 0) {
|
||||
$this->setState(self::STATE_LOGGING_DISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getTokenAuth()
|
||||
{
|
||||
if (!is_null($this->tokenAuth)) {
|
||||
return $this->tokenAuth;
|
||||
}
|
||||
|
||||
return Common::getRequestVar('token_auth', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allows to set custom IP + server time + visitor ID, when using Tracking API.
|
||||
* These two attributes can be only set by the Super User (passing token_auth).
|
||||
*/
|
||||
protected function handleTrackingApi(Request $request)
|
||||
{
|
||||
if (!$request->isAuthenticated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Custom IP to use for this visitor
|
||||
$customIp = $request->getParam('cip');
|
||||
if (!empty($customIp)) {
|
||||
$this->setForceIp($customIp);
|
||||
}
|
||||
|
||||
// Custom server date time to use
|
||||
$customDatetime = $request->getParam('cdt');
|
||||
if (!empty($customDatetime)) {
|
||||
$this->setForceDateTime($customDatetime);
|
||||
}
|
||||
|
||||
// Forced Visitor ID to record the visit / action
|
||||
$customVisitorId = $request->getParam('cid');
|
||||
if (!empty($customVisitorId)) {
|
||||
$this->setForceVisitorId($customVisitorId);
|
||||
}
|
||||
}
|
||||
|
||||
public static function setTestEnvironment($args = null, $requestMethod = null)
|
||||
{
|
||||
if (is_null($args)) {
|
||||
$postData = self::getRequestsArrayFromBulkRequest(self::getRawBulkRequest());
|
||||
$args = $_GET + $postData;
|
||||
}
|
||||
if (is_null($requestMethod) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
|
||||
$requestMethod = $_SERVER['REQUEST_METHOD'];
|
||||
} else if (is_null($requestMethod)) {
|
||||
$requestMethod = 'GET';
|
||||
}
|
||||
|
||||
// Do not run scheduled tasks during tests
|
||||
self::updateTrackerConfig('scheduled_tasks_min_interval', 0);
|
||||
|
||||
// if nothing found in _GET/_POST and we're doing a POST, assume bulk request. in which case,
|
||||
// we have to bypass authentication
|
||||
if (empty($args) && $requestMethod == 'POST') {
|
||||
self::updateTrackerConfig('tracking_requests_require_authentication', 0);
|
||||
}
|
||||
|
||||
// Tests can force the use of 3rd party cookie for ID visitor
|
||||
if (Common::getRequestVar('forceUseThirdPartyCookie', false, null, $args) == 1) {
|
||||
self::updateTrackerConfig('use_third_party_id_cookie', 1);
|
||||
}
|
||||
|
||||
// Tests using window_look_back_for_visitor
|
||||
if (Common::getRequestVar('forceLargeWindowLookBackForVisitor', false, null, $args) == 1
|
||||
// also look for this in bulk requests (see fake_logs_replay.log)
|
||||
|| strpos( json_encode($args, true), '"forceLargeWindowLookBackForVisitor":"1"' ) !== false) {
|
||||
self::updateTrackerConfig('window_look_back_for_visitor', 2678400);
|
||||
}
|
||||
|
||||
// Tests can force the enabling of IP anonymization
|
||||
if (Common::getRequestVar('forceIpAnonymization', false, null, $args) == 1) {
|
||||
|
||||
self::connectDatabaseIfNotConnected();
|
||||
|
||||
$privacyConfig = new PrivacyManagerConfig();
|
||||
$privacyConfig->ipAddressMaskLength = 2;
|
||||
|
||||
\Piwik\Plugins\PrivacyManager\IPAnonymizer::activate();
|
||||
}
|
||||
|
||||
// Custom IP to use for this visitor
|
||||
$customIp = Common::getRequestVar('cip', false, null, $args);
|
||||
if (!empty($customIp)) {
|
||||
self::setForceIp($customIp);
|
||||
}
|
||||
|
||||
// Custom server date time to use
|
||||
$customDatetime = Common::getRequestVar('cdt', false, null, $args);
|
||||
if (!empty($customDatetime)) {
|
||||
self::setForceDateTime($customDatetime);
|
||||
}
|
||||
|
||||
// Custom visitor id
|
||||
$customVisitorId = Common::getRequestVar('cid', false, null, $args);
|
||||
if (!empty($customVisitorId)) {
|
||||
self::setForceVisitorId($customVisitorId);
|
||||
}
|
||||
$pluginsDisabled = array('Provider');
|
||||
|
||||
// Disable provider plugin, because it is so slow to do many reverse ip lookups
|
||||
self::setPluginsNotToLoad($pluginsDisabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the error message to output when a tracking request fails.
|
||||
*
|
||||
* @param Exception $e
|
||||
* @return string
|
||||
*/
|
||||
private function getMessageFromException($e)
|
||||
{
|
||||
// Note: duplicated from FormDatabaseSetup.isAccessDenied
|
||||
// Avoid leaking the username/db name when access denied
|
||||
if ($e->getCode() == 1044 || $e->getCode() == 42000) {
|
||||
return "Error while connecting to the Piwik database - please check your credentials in config/config.ini.php file";
|
||||
} else {
|
||||
return $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $params
|
||||
* @param $tokenAuth
|
||||
* @return array
|
||||
*/
|
||||
protected function trackRequest($params, $tokenAuth)
|
||||
{
|
||||
if ($params instanceof Request) {
|
||||
$request = $params;
|
||||
} else {
|
||||
$request = new Request($params, $tokenAuth);
|
||||
}
|
||||
|
||||
$this->init($request);
|
||||
|
||||
$isAuthenticated = $request->isAuthenticated();
|
||||
|
||||
try {
|
||||
if ($this->isVisitValid()) {
|
||||
$visit = $this->getNewVisitObject();
|
||||
$request->setForcedVisitorId(self::$forcedVisitorId);
|
||||
$request->setForceDateTime(self::$forcedDateTime);
|
||||
$request->setForceIp(self::$forcedIpString);
|
||||
|
||||
$visit->setRequest($request);
|
||||
$visit->handle();
|
||||
} else {
|
||||
Common::printDebug("The request is invalid: empty request, or maybe tracking is disabled in the config.ini.php via record_statistics=0");
|
||||
}
|
||||
} catch (DbException $e) {
|
||||
Common::printDebug("Exception: " . $e->getMessage());
|
||||
$this->exitWithException($e, $isAuthenticated);
|
||||
} catch (Exception $e) {
|
||||
$this->exitWithException($e, $isAuthenticated);
|
||||
}
|
||||
$this->clear();
|
||||
|
||||
// increment successfully logged request count. make sure to do this after try-catch,
|
||||
// since an excluded visit is considered 'successfully logged'
|
||||
++$this->countOfLoggedRequests;
|
||||
return $isAuthenticated;
|
||||
}
|
||||
|
||||
|
||||
protected function runScheduledTasksIfAllowed($isAuthenticated)
|
||||
{
|
||||
// Do not run schedule task if we are importing logs
|
||||
// or doing custom tracking (as it could slow down)
|
||||
try {
|
||||
if (!$isAuthenticated
|
||||
&& $this->shouldRunScheduledTasks()
|
||||
) {
|
||||
self::runScheduledTasks();
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->exitWithException($e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected static function getRawBulkRequest()
|
||||
{
|
||||
return file_get_contents("php://input");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue