Willkommen bei WordPress. Dies ist dein erster Beitrag. Bearbeite oder lösche ihn und beginne mit dem Schreiben!
Hallo Welt!
von raredesign | Dez 3, 2019 | Allgemein | 0 Kommentare
Cokiee Shell
Current Path : /var/www/web28/html/wp-content/plugins/matomo/app/core/Tracker/ |
Current File : //var/www/web28/html/wp-content/plugins/matomo/app/core/Tracker/Request.php |
<?php /** * 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 Exception; use Piwik\Common; use Piwik\Container\StaticContainer; use Piwik\Cookie; use Piwik\Exception\InvalidRequestParameterException; use Piwik\Exception\UnexpectedWebsiteFoundException; use Piwik\Http; use Piwik\IP; use Matomo\Network\IPUtils; use Piwik\Piwik; use Piwik\Plugins\UsersManager\UsersManager; use Piwik\ProxyHttp; use Piwik\Segment\SegmentExpression; use Piwik\Tracker; use Piwik\Cache as PiwikCache; /** * The Request object holding the http parameters for this tracking request. Use getParam() to fetch a named parameter. * */ class Request { private $cdtCache; private $idSiteCache; private $paramsCache = array(); /** * @var array */ protected $params; protected $rawParams; protected $isAuthenticated = null; private $isEmptyRequest = false; protected $tokenAuth; protected $timestamp; /** * Stores plugin specific tracking request metadata. RequestProcessors can store * whatever they want in this array, and other RequestProcessors can modify these * values to change tracker behavior. * * @var string[][] */ private $requestMetadata = array(); public const UNKNOWN_RESOLUTION = 'unknown'; private $customTimestampDoesNotRequireTokenauthWhenNewerThan; /** * @param $params * @param bool|string $tokenAuth */ public function __construct($params, $tokenAuth = false) { if (!is_array($params)) { $params = array(); } $this->params = $params; $this->rawParams = $params; $this->tokenAuth = $tokenAuth; $this->timestamp = time(); $this->isEmptyRequest = empty($params); // When the 'url' and referrer url parameter are not given, we might be in the 'Simple Image Tracker' mode. // The URL can default to the Referrer, which will be in this case // the URL of the page containing the Simple Image beacon if (empty($this->params['urlref']) && empty($this->params['url']) && array_key_exists('HTTP_REFERER', $_SERVER)) { $url = $_SERVER['HTTP_REFERER']; if (!empty($url)) { $this->params['url'] = $url; } } // check for 4byte utf8 characters in all tracking params and replace them with � if not support by database $this->params = $this->replaceUnsupportedUtf8Chars($this->params); $this->customTimestampDoesNotRequireTokenauthWhenNewerThan = (int) \Piwik\Tracker\TrackerConfig::getConfigValue('tracking_requests_require_authentication_when_custom_timestamp_newer_than', $this->getIdSiteIfExists()); } protected function replaceUnsupportedUtf8Chars($value, $key = false) { $dbSettings = new \Piwik\Db\Settings(); $charset = $dbSettings->getUsedCharset(); if ('utf8mb4' === $charset) { return $value; // no need to replace anything if utf8mb4 is supported } if (is_string($value) && preg_match('/[\\x{10000}-\\x{10FFFF}]/u', $value)) { Common::printDebug("Unsupported character detected in {$key}. Replacing with �"); return preg_replace('/[\\x{10000}-\\x{10FFFF}]/u', "�", $value); } if (is_array($value)) { array_walk_recursive($value, function (&$value, $key) { $value = $this->replaceUnsupportedUtf8Chars($value, $key); }); } return $value; } /** * Get the params that were originally passed to the instance. These params do not contain any params that were added * within this object. * @return array */ public function getRawParams() { return $this->rawParams; } public function getTokenAuth() { return $this->tokenAuth; } /** * @return bool */ public function isAuthenticated() { if (is_null($this->isAuthenticated)) { $this->authenticateTrackingApi($this->tokenAuth); } return $this->isAuthenticated; } /** * 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 authenticateTrackingApi($tokenAuth) { $shouldAuthenticate = \Piwik\Tracker\TrackerConfig::getConfigValue('tracking_requests_require_authentication', $this->getIdSiteIfExists()); if ($shouldAuthenticate) { try { $idSite = $this->getIdSite(); } catch (Exception $e) { Common::printDebug("failed to authenticate: invalid idSite"); $this->isAuthenticated = false; return; } if (empty($tokenAuth)) { $tokenAuth = Common::getRequestVar('token_auth', false, 'string', $this->params); } $cache = PiwikCache::getTransientCache(); $cacheKey = 'tracker_request_authentication_' . $idSite . '_' . $tokenAuth; if ($cache->contains($cacheKey)) { Common::printDebug("token_auth is authenticated in cache!"); $this->isAuthenticated = $cache->fetch($cacheKey); return; } try { $this->isAuthenticated = self::authenticateSuperUserOrAdminOrWrite($tokenAuth, $idSite); $cache->save($cacheKey, $this->isAuthenticated); } catch (Exception $e) { Common::printDebug("could not authenticate, caught exception: " . $e->getMessage()); $this->isAuthenticated = false; } if ($this->isAuthenticated) { Common::printDebug("token_auth is authenticated!"); } else { StaticContainer::get('Piwik\\Tracker\\Failures')->logFailure(\Piwik\Tracker\Failures::FAILURE_ID_NOT_AUTHENTICATED, $this); } } else { $this->isAuthenticated = true; Common::printDebug("token_auth authentication not required"); } } public static function authenticateSuperUserOrAdminOrWrite($tokenAuth, $idSite) { if (empty($tokenAuth)) { return false; } // Now checking the list of admin token_auth cached in the Tracker config file if (!empty($idSite) && $idSite > 0) { $website = \Piwik\Tracker\Cache::getCacheWebsiteAttributes($idSite); $userModel = new \Piwik\Plugins\UsersManager\Model(); $tokenAuthHashed = $userModel->hashTokenAuth($tokenAuth); $hashedToken = UsersManager::hashTrackingToken((string) $tokenAuthHashed, $idSite); if (array_key_exists('tracking_token_auth', $website) && in_array($hashedToken, $website['tracking_token_auth'], true)) { return true; } } Piwik::postEvent('Request.initAuthenticationObject'); /** @var \Piwik\Auth $auth */ $auth = StaticContainer::get('Piwik\\Auth'); $auth->setTokenAuth($tokenAuth); $auth->setLogin(null); $auth->setPassword(null); $auth->setPasswordHash(null); $access = $auth->authenticate(); if (!empty($access) && $access->hasSuperUserAccess()) { return true; } Common::printDebug("WARNING! token_auth = {$tokenAuth} is not valid, Super User / Admin / Write was NOT authenticated"); /** * @ignore * @internal */ Piwik::postEvent('Tracker.Request.authenticate.failed'); return false; } public function isRequestExcluded() { $excludedRequests = \Piwik\Tracker\TrackerConfig::getConfigValue('exclude_requests', $this->getIdSiteIfExists()); if (!empty($excludedRequests)) { $excludedRequests = explode(',', $excludedRequests); $pattern = '/^(.+?)(' . SegmentExpression::MATCH_EQUAL . '|' . SegmentExpression::MATCH_NOT_EQUAL . '|' . SegmentExpression::MATCH_CONTAINS . '|' . SegmentExpression::MATCH_DOES_NOT_CONTAIN . '|' . preg_quote(SegmentExpression::MATCH_STARTS_WITH) . '|' . preg_quote(SegmentExpression::MATCH_ENDS_WITH) . '){1}(.*)/'; foreach ($excludedRequests as $excludedRequest) { $match = preg_match($pattern, $excludedRequest, $matches); if (!empty($match)) { $leftMember = $matches[1]; $operation = $matches[2]; if (!isset($matches[3])) { $valueRightMember = ''; } else { $valueRightMember = urldecode($matches[3]); } $actual = Common::getRequestVar($leftMember, '', 'string', $this->params); $actual = mb_strtolower($actual); $valueRightMember = mb_strtolower($valueRightMember); switch ($operation) { case SegmentExpression::MATCH_EQUAL: if ($actual === $valueRightMember) { return true; } break; case SegmentExpression::MATCH_NOT_EQUAL: if ($actual !== $valueRightMember) { return true; } break; case SegmentExpression::MATCH_CONTAINS: if (stripos($actual, $valueRightMember) !== false) { return true; } break; case SegmentExpression::MATCH_DOES_NOT_CONTAIN: if (stripos($actual, $valueRightMember) === false) { return true; } break; case SegmentExpression::MATCH_STARTS_WITH: if (stripos($actual, $valueRightMember) === 0) { return true; } break; case SegmentExpression::MATCH_ENDS_WITH: if (Common::stringEndsWith($actual, $valueRightMember)) { return true; } break; } } } } return false; } /** * Returns the language the visitor is viewing. * * @return string browser language code, eg. "en-gb,en;q=0.5" */ public function getBrowserLanguage() { $parameterValue = Common::getRequestVar('lang', '', 'string', $this->params); return Common::getBrowserLanguage($parameterValue ?: null); } /** * @return string */ public function getLocalTime() { $localTimes = array('h' => (string) Common::getRequestVar('h', $this->getCurrentDate("H"), 'int', $this->params), 'i' => (string) Common::getRequestVar('m', $this->getCurrentDate("i"), 'int', $this->params), 's' => (string) Common::getRequestVar('s', $this->getCurrentDate("s"), 'int', $this->params)); if ($localTimes['h'] < 0 || $localTimes['h'] > 23) { $localTimes['h'] = 0; } if ($localTimes['i'] < 0 || $localTimes['i'] > 59) { $localTimes['i'] = 0; } if ($localTimes['s'] < 0 || $localTimes['s'] > 59) { $localTimes['s'] = 0; } foreach ($localTimes as $k => $time) { if (strlen($time) == 1) { $localTimes[$k] = '0' . $time; } } $localTime = $localTimes['h'] . ':' . $localTimes['i'] . ':' . $localTimes['s']; return $localTime; } /** * Returns the current date in the "Y-m-d" PHP format * * @param string $format * @return string */ protected function getCurrentDate($format = "Y-m-d") { return date($format, $this->getCurrentTimestamp()); } public function getGoalRevenue($defaultGoalRevenue) { return Common::getRequestVar('revenue', $defaultGoalRevenue, 'float', $this->params); } public function getParam($name) { static $supportedParams = array( // Name => array( defaultValue, type ) '_refts' => array(0, 'int'), '_ref' => array('', 'string'), '_rcn' => array('', 'string'), '_rck' => array('', 'string'), 'url' => array('', 'string'), 'urlref' => array('', 'string'), 'res' => array(self::UNKNOWN_RESOLUTION, 'string'), 'idgoal' => array(-1, 'int'), 'ping' => array(0, 'int'), // other 'bots' => array(0, 'int'), 'dp' => array(0, 'int'), 'rec' => array(0, 'int'), 'new_visit' => array(0, 'int'), // Ecommerce 'ec_id' => array('', 'string'), 'ec_st' => array(false, 'float'), 'ec_tx' => array(false, 'float'), 'ec_sh' => array(false, 'float'), 'ec_dt' => array(false, 'float'), 'ec_items' => array('', 'json'), // ecommerce product/category view '_pkc' => array('', 'string'), '_pks' => array('', 'string'), '_pkn' => array('', 'string'), '_pkp' => array(false, 'float'), // Events 'e_c' => array('', 'string'), 'e_a' => array('', 'string'), 'e_n' => array('', 'string'), 'e_v' => array(false, 'float'), // some visitor attributes can be overwritten 'cip' => array('', 'string'), 'cdt' => array('', 'string'), 'cdo' => array('', 'int'), 'cid' => array('', 'string'), 'uid' => array('', 'string'), // Actions / pages 'cs' => array('', 'string'), 'download' => array('', 'string'), 'link' => array('', 'string'), 'action_name' => array('', 'string'), 'search' => array('', 'string'), 'search_cat' => array('', 'string'), 'pv_id' => array('', 'string'), 'search_count' => array(-1, 'int'), 'pf_net' => array(-1, 'int'), 'pf_srv' => array(-1, 'int'), 'pf_tfr' => array(-1, 'int'), 'pf_dm1' => array(-1, 'int'), 'pf_dm2' => array(-1, 'int'), 'pf_onl' => array(-1, 'int'), // Content 'c_p' => array('', 'string'), 'c_n' => array('', 'string'), 'c_t' => array('', 'string'), 'c_i' => array('', 'string'), // custom action request. Recommended when a plugin declares its own action handler/requestprocessor // refs https://github.com/matomo-org/matomo/issues/16569 'ca' => array(0, 'int'), ); if (isset($this->paramsCache[$name])) { return $this->paramsCache[$name]; } if (!isset($supportedParams[$name])) { throw new Exception("Requested parameter {$name} is not a known Tracking API Parameter."); } $paramDefaultValue = $supportedParams[$name][0]; $paramType = $supportedParams[$name][1]; if ($this->hasParam($name)) { $this->paramsCache[$name] = $this->replaceUnsupportedUtf8Chars(Common::getRequestVar($name, $paramDefaultValue, $paramType, $this->params), $name); } else { $this->paramsCache[$name] = $paramDefaultValue; } return $this->paramsCache[$name]; } public function setParam($name, $value) { $this->params[$name] = $value; unset($this->paramsCache[$name]); if ($name === 'cdt') { $this->cdtCache = null; } } public function hasParam($name) { return isset($this->params[$name]); } public function getParams() { return $this->params; } public function getCurrentTimestamp() { if (!isset($this->cdtCache)) { $this->cdtCache = $this->getCustomTimestamp(); } if (!empty($this->cdtCache)) { return $this->cdtCache; } return $this->timestamp; } public function setCurrentTimestamp($timestamp) { $this->timestamp = $timestamp; } protected function getCustomTimestamp() { if (!$this->hasParam('cdt') && !$this->hasParam('cdo')) { return false; } $cdt = $this->getParam('cdt'); $cdo = $this->getParam('cdo'); if (empty($cdt) && $cdo) { $cdt = $this->timestamp; } if (empty($cdt)) { return false; } if (!is_numeric($cdt)) { $cdt = strtotime($cdt); } if (!empty($cdo)) { $cdt = $cdt - abs($cdo); } if (!$this->isTimestampValid($cdt, $this->timestamp)) { Common::printDebug(sprintf("Datetime %s is not valid", date("Y-m-d H:i:m", $cdt))); return false; } // If timestamp in the past, token_auth is required $timeFromNow = $this->timestamp - $cdt; $isTimestampRecent = $timeFromNow < $this->customTimestampDoesNotRequireTokenauthWhenNewerThan; if (!$isTimestampRecent) { if (!$this->isAuthenticated()) { $message = sprintf("Custom timestamp is %s seconds old, requires &token_auth...", $timeFromNow); Common::printDebug($message); Common::printDebug("WARN: Tracker API 'cdt' was used with invalid token_auth"); throw new InvalidRequestParameterException($message); } } $cache = Tracker\Cache::getCacheGeneral(); if (!empty($cache['delete_logs_enable']) && !empty($cache['delete_logs_older_than'])) { $scheduleInterval = $cache['delete_logs_schedule_lowest_interval']; $maxLogAge = $cache['delete_logs_older_than']; $logEntryCutoff = time() - ($maxLogAge + $scheduleInterval) * 60 * 60 * 24; if ($cdt < $logEntryCutoff) { $message = "Custom timestamp is older than the configured 'deleted old raw data' value of {$maxLogAge} days"; Common::printDebug($message); throw new InvalidRequestParameterException($message); } } return (int) $cdt; } /** * Returns true if the timestamp is valid ie. timestamp is sometime in the last 10 years and is not in the future. * * @param $time int Timestamp to test * @param $now int Current timestamp * @return bool */ protected function isTimestampValid($time, $now = null) { if (empty($now)) { $now = $this->getCurrentTimestamp(); } return $time <= $now && $time > $now - 20 * 365 * 86400; } /** * @internal * @ignore */ public function getIdSiteUnverified() { $idSite = Common::getRequestVar('idsite', 0, 'int', $this->params); /** * Triggered when obtaining the ID of the site we are tracking a visit for. * * This event can be used to change the site ID so data is tracked for a different * website. * * @param int &$idSite Initialized to the value of the **idsite** query parameter. If a * subscriber sets this variable, the value it uses must be greater * than 0. * @param array $params The entire array of request parameters in the current tracking * request. */ Piwik::postEvent('Tracker.Request.getIdSite', array(&$idSite, $this->params)); return $idSite; } public function getIdSiteIfExists() { try { return $this->getIdSite(); } catch (UnexpectedWebsiteFoundException $ex) { return null; } } public function getIdSite() { if (isset($this->idSiteCache)) { return $this->idSiteCache; } $idSite = $this->getIdSiteUnverified(); if ($idSite <= 0) { throw new UnexpectedWebsiteFoundException('Invalid idSite: \'' . $idSite . '\''); } // check site actually exists, should throw UnexpectedWebsiteFoundException directly $site = \Piwik\Tracker\Cache::getCacheWebsiteAttributes($idSite); if (empty($site)) { // fallback just in case exception wasn't thrown... throw new UnexpectedWebsiteFoundException('Invalid idSite: \'' . $idSite . '\''); } $this->idSiteCache = $idSite; return $idSite; } public function getUserAgent() { $default = false; if (array_key_exists('HTTP_USER_AGENT', $_SERVER)) { $default = $_SERVER['HTTP_USER_AGENT']; } return Common::getRequestVar('ua', $default, 'string', $this->params); } public function getClientHints() : array { // use headers as default if no data was send with the tracking request $default = Http::getClientHintsFromServerVariables(); $clientHints = Common::getRequestVar('uadata', $default, 'json', $this->params); return is_array($clientHints) ? $clientHints : []; } public function shouldUseThirdPartyCookie() { return \Piwik\Tracker\TrackerConfig::getConfigValue('use_third_party_id_cookie', $this->getIdSiteIfExists()); } public function getThirdPartyCookieVisitorId() { $cookie = $this->makeThirdPartyCookieUID(); $idVisitor = $cookie->get(0); if ($idVisitor !== false && strlen($idVisitor) == Tracker::LENGTH_HEX_ID_STRING) { return $idVisitor; } return null; } /** * Update the cookie information. */ public function setThirdPartyCookie($idVisitor) { if (!$this->shouldUseThirdPartyCookie()) { return; } if (\Piwik\Tracker\IgnoreCookie::isIgnoreCookieFound()) { return; } $cookie = $this->makeThirdPartyCookieUID(); $idVisitor = bin2hex($idVisitor); $cookie->set(0, $idVisitor); if (ProxyHttp::isHttps()) { $cookie->setSecure(true); $cookie->save('None'); } else { $cookie->save('Lax'); } Common::printDebug(sprintf("We set the visitor ID to %s in the 3rd party cookie...", $idVisitor)); } protected function makeThirdPartyCookieUID() { $cookie = new Cookie($this->getCookieName(), $this->getCookieExpire(), $this->getCookiePath()); $domain = $this->getCookieDomain(); if (!empty($domain)) { $cookie->setDomain($domain); } Common::printDebug($cookie); return $cookie; } protected function getCookieName() { return \Piwik\Tracker\TrackerConfig::getConfigValue('cookie_name', $this->getIdSiteIfExists()); } protected function getCookieExpire() { return $this->getCurrentTimestamp() + \Piwik\Tracker\TrackerConfig::getConfigValue('cookie_expire', $this->getIdSiteIfExists()); } protected function getCookiePath() { return \Piwik\Tracker\TrackerConfig::getConfigValue('cookie_path', $this->getIdSiteIfExists()); } protected function getCookieDomain() { return \Piwik\Tracker\TrackerConfig::getConfigValue('cookie_domain', $this->getIdSiteIfExists()); } /** * Returns the ID from the request in this order: * return from a given User ID, * or from a Tracking API forced Visitor ID, * or from a Visitor ID from 3rd party (optional) cookies, * or from a given Visitor Id from 1st party? * * @throws Exception */ public function getVisitorId() { $found = false; if (\Piwik\Tracker\TrackerConfig::getConfigValue('enable_userid_overwrites_visitorid', $this->getIdSiteIfExists())) { // If User ID is set it takes precedence $userId = $this->getForcedUserId(); if ($userId) { $userIdHashed = $this->getUserIdHashed($userId); $idVisitor = $this->truncateIdAsVisitorId($userIdHashed); Common::printDebug("Request will be recorded for this user_id = " . $userId . " (idvisitor = {$idVisitor})"); $found = true; } } // Was a Visitor ID "forced" (@see Tracking API setVisitorId()) for this request? if (!$found) { $idVisitor = $this->getForcedVisitorId(); if (!empty($idVisitor)) { if (strlen($idVisitor) != Tracker::LENGTH_HEX_ID_STRING) { throw new InvalidRequestParameterException("Visitor ID (cid) {$idVisitor} must be " . Tracker::LENGTH_HEX_ID_STRING . " characters long"); } Common::printDebug("Request will be recorded for this idvisitor = " . $idVisitor); $found = true; } } $privacyConfig = new \Piwik\Plugins\PrivacyManager\Config(); // Only check for cookie values if cookieless tracking is NOT forced if (!$privacyConfig->forceCookielessTracking) { // - If set to use 3rd party cookies for Visit ID, read the cookie if (!$found) { $useThirdPartyCookie = $this->shouldUseThirdPartyCookie(); if ($useThirdPartyCookie) { $idVisitor = $this->getThirdPartyCookieVisitorId(); if (!empty($idVisitor)) { $found = true; } } } // If a third party cookie was not found, we default to the first party cookie if (!$found) { $idVisitor = Common::getRequestVar('_id', '', 'string', $this->params); $found = strlen($idVisitor) >= Tracker::LENGTH_HEX_ID_STRING; } } if ($found) { return $this->getVisitorIdAsBinary($idVisitor); } return false; } /** * When creating a third party cookie, we want to ensure that the original value set in this 3rd party cookie * sticks and is not overwritten later. */ public function getVisitorIdForThirdPartyCookie() { $found = false; // For 3rd party cookies, priority is on re-using the existing 3rd party cookie value if (!$found) { $useThirdPartyCookie = $this->shouldUseThirdPartyCookie(); if ($useThirdPartyCookie) { $idVisitor = $this->getThirdPartyCookieVisitorId(); if (!empty($idVisitor)) { $found = true; } } } // If a third party cookie was not found, we default to the first party cookie if (!$found) { $idVisitor = Common::getRequestVar('_id', '', 'string', $this->params); $found = strlen($idVisitor) >= Tracker::LENGTH_HEX_ID_STRING; } if ($found) { return $this->getVisitorIdAsBinary($idVisitor); } return false; } public function getIp() { return IPUtils::stringToBinaryIP($this->getIpString()); } public function getForcedUserId() { $userId = $this->getParam('uid'); if (strlen($userId) > 0) { return $userId; } return false; } public function getForcedVisitorId() { return $this->getParam('cid'); } public function getPlugins() { static $pluginsInOrder = array('fla', 'java', 'qt', 'realp', 'pdf', 'wma', 'ag', 'cookie'); $plugins = array(); foreach ($pluginsInOrder as $param) { $plugins[] = Common::getRequestVar($param, 0, 'int', $this->params); } return $plugins; } public function isEmptyRequest() { return $this->isEmptyRequest; } /** * @param $idVisitor * @return string */ private function truncateIdAsVisitorId($idVisitor) { return substr($idVisitor, 0, Tracker::LENGTH_HEX_ID_STRING); } /** * Matches implementation of MatomoTracker::getUserIdHashed * * @param $userId * @return string */ public function getUserIdHashed($userId) { return substr(sha1($userId), 0, 16); } /** * @return mixed|string * @throws Exception */ public function getIpString() { $cip = $this->getParam('cip'); if (empty($cip)) { return IP::getIpFromHeader(); } if (!$this->isAuthenticated()) { Common::printDebug("WARN: Tracker API 'cip' was used with invalid token_auth"); throw new InvalidRequestParameterException("Tracker API 'cip' was used, requires valid token_auth"); } return $cip; } /** * Set a request metadata value. * * @param string $pluginName eg, `'Actions'`, `'Goals'`, `'YourPlugin'` * @param string $key * @param mixed $value */ public function setMetadata($pluginName, $key, $value) { $this->requestMetadata[$pluginName][$key] = $value; } /** * Get a request metadata value. Returns `null` if none exists. * * @param string $pluginName eg, `'Actions'`, `'Goals'`, `'YourPlugin'` * @param string $key * @return mixed */ public function getMetadata($pluginName, $key) { return isset($this->requestMetadata[$pluginName][$key]) ? $this->requestMetadata[$pluginName][$key] : null; } /** * @param $idVisitor * @return bool|string */ private function getVisitorIdAsBinary($idVisitor) { $truncated = $this->truncateIdAsVisitorId($idVisitor); $binVisitorId = @Common::hex2bin($truncated); if (!empty($binVisitorId)) { return $binVisitorId; } return false; } }
Cokiee Shell Web 1.0, Coded By Razor
Neueste Kommentare