function getIp() { if (isset($this->details['location_ip'])) { return Piwik_IP::N2P($this->details['location_ip']); } return false; }
/** * send email to Piwik team and display nice thanks */ function sendFeedback() { $email = Piwik_Common::getRequestVar('email', '', 'string'); $body = Piwik_Common::getRequestVar('body', '', 'string'); $category = Piwik_Common::getRequestVar('category', '', 'string'); $nonce = Piwik_Common::getRequestVar('nonce', '', 'string'); $view = Piwik_View::factory('sent'); $view->feedbackEmailAddress = Piwik_Config::getInstance()->General['feedback_email_address']; try { $minimumBodyLength = 40; if (strlen($body) < $minimumBodyLength || strpos($email, 'probe@') !== false || strpos($body, '<probe') !== false) { throw new Exception(Piwik_TranslateException('Feedback_ExceptionBodyLength', array($minimumBodyLength))); } if (!Piwik::isValidEmailString($email)) { throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidEmail')); } if (preg_match('/https?:/i', $body)) { throw new Exception(Piwik_TranslateException('Feedback_ExceptionNoUrls')); } if (!Piwik_Nonce::verifyNonce('Piwik_Feedback.sendFeedback', $nonce)) { throw new Exception(Piwik_TranslateException('General_ExceptionNonceMismatch')); } Piwik_Nonce::discardNonce('Piwik_Feedback.sendFeedback'); $mail = new Piwik_Mail(); $mail->setFrom(Piwik_Common::unsanitizeInputValue($email)); $mail->addTo($view->feedbackEmailAddress, 'Piwik Team'); $mail->setSubject('[ Feedback form - Piwik ] ' . $category); $mail->setBodyText(Piwik_Common::unsanitizeInputValue($body) . "\n" . 'Piwik ' . Piwik_Version::VERSION . "\n" . 'IP: ' . Piwik_IP::getIpFromHeader() . "\n" . 'URL: ' . Piwik_Url::getReferer() . "\n"); @$mail->send(); } catch (Exception $e) { $view->ErrorString = $e->getMessage(); $view->message = $body; } echo $view->render(); }
/** * Uses a GeoIP database to get a visitor's location based on their IP address. * * This function will return different results based on the data used and based * on how the GeoIP module is configured. * * If a region database is used, it may return the country code, region code, * city name, area code, latitude, longitude and postal code of the visitor. * * Alternatively, only the country code may be returned for another database. * * If your HTTP server is not configured to include all GeoIP information, some * information will not be available to Piwik. * * @param array $info Must have an 'ip' field. * @return array */ public function getLocation($info) { $ip = $this->getIpFromInfo($info); // geoip modules that are built into servers can't use a forced IP. in this case we try // to fallback to another version. $myIP = Piwik_IP::getIpFromHeader(); if (!self::isSameOrAnonymizedIp($ip, $myIP) && (!isset($info['disable_fallbacks']) || !$info['disable_fallbacks'])) { printDebug("The request is for IP address: " . $info['ip'] . " but your IP is: {$myIP}. GeoIP Server Module (apache/nginx) does not support this use case... "); $fallbacks = array(Piwik_UserCountry_LocationProvider_GeoIp_Pecl::ID, Piwik_UserCountry_LocationProvider_GeoIp_Php::ID); foreach ($fallbacks as $fallbackProviderId) { $otherProvider = Piwik_UserCountry_LocationProvider::getProviderById($fallbackProviderId); if ($otherProvider) { printDebug("Used {$fallbackProviderId} to detect this visitor IP"); return $otherProvider->getLocation($info); } } printDebug("FAILED to lookup the geo location of this IP address, as no fallback location providers is configured. We recommend to configure Geolocation PECL module to fix this error."); return false; } $result = array(); foreach (self::$geoIpServerVars as $resultKey => $geoipVarName) { if (!empty($_SERVER[$geoipVarName])) { $result[$resultKey] = $_SERVER[$geoipVarName]; } } foreach (self::$geoIpUtfServerVars as $resultKey => $geoipVarName) { if (!empty($_SERVER[$geoipVarName])) { $result[$resultKey] = utf8_encode($_SERVER[$geoipVarName]); } } $this->completeLocationResult($result); return $result; }
function index() { Piwik::checkUserIsNotAnonymous(); $view = Piwik_View::factory('Settings'); $view->isSuperUser = Piwik::isUserIsSuperUser(); $mobileMessagingAPI = Piwik_MobileMessaging_API::getInstance(); $view->delegatedManagement = $mobileMessagingAPI->getDelegatedManagement(); $view->credentialSupplied = $mobileMessagingAPI->areSMSAPICredentialProvided(); $view->accountManagedByCurrentUser = $view->isSuperUser || $view->delegatedManagement; $view->strHelpAddPhone = Piwik_Translate('MobileMessaging_Settings_PhoneNumbers_HelpAdd', array(Piwik_Translate('UserSettings_SubmenuSettings'), Piwik_Translate('MobileMessaging_SettingsMenu'))); if ($view->credentialSupplied && $view->accountManagedByCurrentUser) { $view->provider = $mobileMessagingAPI->getSMSProvider(); $view->creditLeft = $mobileMessagingAPI->getCreditLeft(); } $view->smsProviders = Piwik_MobileMessaging_SMSProvider::$availableSMSProviders; // construct the list of countries from the lang files $countries = array(); foreach (Piwik_Common::getCountriesList() as $countryCode => $continentCode) { if (isset(Piwik_MobileMessaging_CountryCallingCodes::$countryCallingCodes[$countryCode])) { $countries[$countryCode] = array('countryName' => Piwik_CountryTranslate($countryCode), 'countryCallingCode' => Piwik_MobileMessaging_CountryCallingCodes::$countryCallingCodes[$countryCode]); } } $view->countries = $countries; $view->defaultCountry = Piwik_Common::getCountry(Piwik_LanguagesManager::getLanguageCodeForCurrentUser(), true, Piwik_IP::getIpFromHeader()); $view->phoneNumbers = $mobileMessagingAPI->getPhoneNumbers(); $this->setBasicVariablesView($view); $view->menu = Piwik_GetAdminMenu(); echo $view->render(); }
function index() { $view = Piwik_View::factory('SitesManager'); if (Piwik::isUserIsSuperUser()) { $sites = Piwik_SitesManager_API::getInstance()->getAllSites(); Piwik_Site::setSites($sites); $sites = array_values($sites); } else { $sites = Piwik_SitesManager_API::getInstance()->getSitesWithAdminAccess(); Piwik_Site::setSitesFromArray($sites); } foreach ($sites as &$site) { $site['alias_urls'] = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($site['idsite']); $site['excluded_ips'] = str_replace(',', '<br/>', $site['excluded_ips']); $site['excluded_parameters'] = str_replace(',', '<br/>', $site['excluded_parameters']); } $view->adminSites = $sites; $view->adminSitesCount = count($sites); $timezones = Piwik_SitesManager_API::getInstance()->getTimezonesList(); $view->timezoneSupported = Piwik::isTimezoneSupportEnabled(); $view->timezones = Piwik_Common::json_encode($timezones); $view->defaultTimezone = Piwik_SitesManager_API::getInstance()->getDefaultTimezone(); $view->currencies = Piwik_Common::json_encode(Piwik_SitesManager_API::getInstance()->getCurrencyList()); $view->defaultCurrency = Piwik_SitesManager_API::getInstance()->getDefaultCurrency(); $view->utcTime = Piwik_Date::now()->getDatetime(); $excludedIpsGlobal = Piwik_SitesManager_API::getInstance()->getExcludedIpsGlobal(); $view->globalExcludedIps = str_replace(',', "\n", $excludedIpsGlobal); $excludedQueryParametersGlobal = Piwik_SitesManager_API::getInstance()->getExcludedQueryParametersGlobal(); $view->globalExcludedQueryParameters = str_replace(',', "\n", $excludedQueryParametersGlobal); $view->currentIpAddress = Piwik_IP::getIpFromHeader(); $view->showAddSite = (bool) Piwik_Common::getRequestVar('showaddsite', false); $this->setBasicVariablesView($view); $view->menu = Piwik_GetAdminMenu(); echo $view->render(); }
/** * Constructor */ function __construct() { $logToFileFilename = self::ID; $logToDatabaseTableName = self::ID; $logToDatabaseColumnMapping = array('class_name' => 'class_name', 'method_name' => 'method_name', 'parameter_names_default_values' => 'parameter_names_default_values', 'parameter_values' => 'parameter_values', 'execution_time' => 'execution_time', 'caller_ip' => 'caller_ip', 'timestamp' => 'timestamp', 'returned_value' => 'returned_value'); $screenFormatter = new Piwik_Log_APICall_Formatter_ScreenFormatter(); $fileFormatter = new Piwik_Log_Formatter_FileFormatter(); parent::__construct($logToFileFilename, $fileFormatter, $screenFormatter, $logToDatabaseTableName, $logToDatabaseColumnMapping); $this->setEventItem('caller_ip', Piwik_IP::P2N(Piwik_IP::getIpFromHeader())); }
function __construct() { $logToFileFilename = self::ID; $logToDatabaseTableName = self::ID; $logToDatabaseColumnMapping = null; $screenFormatter = new Piwik_Log_APICall_Formatter_ScreenFormatter(); $fileFormatter = new Piwik_Log_Formatter_FileFormatter(); parent::__construct($logToFileFilename, $fileFormatter, $screenFormatter, $logToDatabaseTableName, $logToDatabaseColumnMapping); $this->setEventItem('caller_ip', Piwik_IP::P2N(Piwik_IP::getIpFromHeader())); }
/** * @group Core * @group Tracker * @group Tracker_Visit * @dataProvider getExcludedIpTestData */ public function testIsVisitorIpExcluded($excludedIp, $tests) { $visit = new Test_Piwik_TrackerVisit_public(); $idsite = Piwik_SitesManager_API::getInstance()->addSite("name", "http://piwik.net/", $ecommerce = 0, $excludedIp); $visit->setRequest(array('idsite' => $idsite)); // test that IPs within the range, or the given IP, are excluded foreach ($tests as $ip => $expected) { $testIpIsExcluded = Piwik_IP::P2N($ip); $this->assertSame($expected, $visit->public_isVisitorIpExcluded($testIpIsExcluded)); } }
function test_isVisitorIpExcluded() { $excludedIps = array('12.12.12.12' => array('12.12.12.12' => true, '12.12.12.11' => false, '12.12.12.13' => false, '0.0.0.0' => false, '255.255.255.255' => false), '12.12.12.12/32' => array('12.12.12.12' => true, '12.12.12.11' => false, '12.12.12.13' => false, '0.0.0.0' => false, '255.255.255.255' => false), '12.12.12.*' => array('12.12.12.0' => true, '12.12.12.255' => true, '12.12.12.12' => true, '12.12.11.255' => false, '12.12.13.0' => false, '0.0.0.0' => false, '255.255.255.255' => false), '12.12.12.0/24' => array('12.12.12.0' => true, '12.12.12.255' => true, '12.12.12.12' => true, '12.12.11.255' => false, '12.12.13.0' => false, '0.0.0.0' => false, '255.255.255.255' => false)); $visit = new Test_Piwik_TrackerVisit_public(); foreach ($excludedIps as $excludedIp => $tests) { $idsite = Piwik_SitesManager_API::getInstance()->addSite("name", "http://piwik.net/", $ecommerce = 0, $excludedIp); $visit->setRequest(array('idsite' => $idsite)); // test that IPs within the range, or the given IP, are excluded foreach ($tests as $ip => $expected) { $testIpIsExcluded = Piwik_IP::P2N($ip); $this->assertTrue($visit->public_isVisitorIpExcluded($testIpIsExcluded) === $expected, $ip . " is not excluded in " . $excludedIp); } } }
/** * @dataProvider getipv4Addresses * @group Plugins * @group AnonymizeIP */ public function testApplyIPMask($ip, $expected) { // each IP is tested with 0 to 4 octets masked for ($maskLength = 0; $maskLength <= 4; $maskLength++) { $res = Piwik_AnonymizeIP::applyIPMask(Piwik_IP::P2N($ip), $maskLength); $this->assertEquals($expected[$maskLength], $res, "Got " . bin2hex($res) . ", Expected " . bin2hex($expected[$maskLength])); } // edge case (bounds check) $this->assertEquals("", Piwik_AnonymizeIP::applyIPMask(Piwik_IP::P2N($ip), 5)); // mask IPv4 mapped addresses for ($maskLength = 0; $maskLength <= 4; $maskLength++) { $res = Piwik_AnonymizeIP::applyIPMask(Piwik_IP::P2N('::ffff:' . $ip), $maskLength); $this->assertEquals($res, "ÿÿ" . $expected[$maskLength], "Got " . bin2hex($res) . ", Expected " . bin2hex($expected[$maskLength])); } $this->assertEquals("ÿ", Piwik_AnonymizeIP::applyIPMask(Piwik_IP::P2N('::ffff:' . $ip), 5)); // edge case (bounds check) $this->assertEquals("", Piwik_AnonymizeIP::applyIPMask(Piwik_IP::P2N('2001::ffff:' . $ip), 17)); }
function index() { $view = Piwik_View::factory('SitesManager'); $sites = Piwik_SitesManager_API::getInstance()->getSitesWithAdminAccess(); $sitesIndexedById = array(); foreach($sites as $site) { $sitesIndexedById[$site['idsite']] = $site; } Piwik_Site::setSites($sitesIndexedById); foreach($sites as &$site) { $site['alias_urls'] = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($site['idsite']); $site['excluded_ips'] = str_replace(',','<br/>', $site['excluded_ips']); $site['excluded_parameters'] = str_replace(',','<br/>', $site['excluded_parameters']); } $view->adminSites = $sites; $view->adminSitesCount = count($sites); $timezones = Piwik_SitesManager_API::getInstance()->getTimezonesList(); $view->timezoneSupported = Piwik::isTimezoneSupportEnabled(); $view->timezones = json_encode($timezones); $view->defaultTimezone = Piwik_SitesManager_API::getInstance()->getDefaultTimezone(); $view->currencies = json_encode(Piwik_SitesManager_API::getInstance()->getCurrencyList()); $view->defaultCurrency = Piwik_SitesManager_API::getInstance()->getDefaultCurrency(); $view->utcTime = Piwik_Date::now()->getDatetime(); $excludedIpsGlobal = Piwik_SitesManager_API::getInstance()->getExcludedIpsGlobal(); $view->globalExcludedIps = str_replace(',',"\n", $excludedIpsGlobal); $excludedQueryParametersGlobal = Piwik_SitesManager_API::getInstance()->getExcludedQueryParametersGlobal(); $view->globalExcludedQueryParameters = str_replace(',',"\n", $excludedQueryParametersGlobal); $view->currentIpAddress = Piwik_IP::getIpFromHeader(); $this->setBasicVariablesView($view); $view->menu = Piwik_GetAdminMenu(); echo $view->render(); }
/** * Echo's a pretty formatted location using a specific LocationProvider. * * Input: * The 'id' query parameter must be set to the ID of the LocationProvider to use. * * Output: * The pretty formatted location that was obtained. Will be HTML. */ public function getLocationUsingProvider() { $providerId = Piwik_Common::getRequestVar('id'); $provider = $provider = Piwik_UserCountry_LocationProvider::getProviderById($providerId); if ($provider === false) { throw new Exception("Invalid provider ID: '{$providerId}'."); } $location = $provider->getLocation(array('ip' => Piwik_IP::getIpFromHeader(), 'lang' => Piwik_Common::getBrowserLanguage(), 'disable_fallbacks' => true)); $location = Piwik_UserCountry_LocationProvider::prettyFormatLocation($location, $newline = '<br/>', $includeExtra = true); echo $location; }
/** * Returns an IP address from an array that was passed into getLocation. This * will return an IPv4 address or false if the address is IPv6 (IPv6 is not * supported yet). * * @param array $ip Must have 'ip' key. * @return string|bool */ protected function getIpFromInfo($info) { $ip = $info['ip']; if (Piwik_IP::isMappedIPv4($ip)) { return Piwik_IP::getIPv4FromMappedIPv6($ip); } else { if (Piwik_IP::isIPv6($ip)) { return false; } else { return $ip; } } }
/** * Tests if the IP is a valid IP, allowing wildcards, except in the first octet. * Wildcards can only be used from right to left, ie. 1.1.*.* is allowed, but 1.1.*.1 is not. * * @param string $ip IP address * @return bool */ private function isValidIp( $ip ) { return Piwik_IP::getIpsForRange($ip) !== false; }
/** * @group Core * @group IP */ public function testGetHostByAddr() { $hosts = array('localhost', strtolower(@php_uname('n')), '127.0.0.1'); $this->assertTrue(in_array(strtolower(Piwik_IP::getHostByAddr('127.0.0.1')), $hosts), '127.0.0.1 -> localhost'); if (!Piwik_Common::isWindows() || PHP_VERSION >= '5.3') { $hosts = array('ip6-localhost', strtolower(@php_uname('n')), '::1'); $this->assertTrue(in_array(strtolower(Piwik_IP::getHostByAddr('::1')), $hosts), '::1 -> ip6-localhost'); } }
/** * Logs the IntranetSubNetwork in the log_visit table */ public function logIntranetSubNetworkInfo($notification) { $visitorInfo =& $notification->getNotificationObject(); $ip = Piwik_IP::N2P($visitorInfo['location_ip']); // by default, we want the network name to be the IP address: $networkName = $ip; /** ********************************************************************************************* ****************** adopt the following lines according to your subnets ********************** **/ // Some default subnets: if (Piwik_IP::isIpInRange($visitorInfo['location_ip'], array('0.0.0.0/0'))) { $networkName = 'Global IPv4'; } // all IPv4 addresses if (Piwik_IP::isIpInRange($visitorInfo['location_ip'], array('::/0'))) { $networkName = 'Global IPv6'; } // IPv6 addresses if (Piwik_IP::isIpInRange($visitorInfo['location_ip'], array('::ffff:0:0/96'))) { $networkName = 'Global IPv4'; } // IPv4 mapped IPv6 addresses // You may include your custom subnets: //if (Piwik_IP::isIpInRange($visitorInfo['location_ip'], array('141.2.0.0/16'))) { $networkName = 'University Frankfurt'; } //if (Piwik_IP::isIpInRange($visitorInfo['location_ip'], array('192.0.2.0/24'))) { $networkName = 'TEST-NET'; } //if (Piwik_IP::isIpInRange($visitorInfo['location_ip'], array('198.51.100.0/24'))) { $networkName = 'TEST-NET-2'; } //if (Piwik_IP::isIpInRange($visitorInfo['location_ip'], array('2001:db8::/33', // '2001:db8:8000::/33'))) { $networkName = 'Doc-IPv6'; } /** ******************* end adopt here to your subnets ***************************************** ********************************************************************************************* **/ // add the IntranetSubNetwork value in the table log_visit $visitorInfo['location_IntranetSubNetwork'] = substr($networkName, 0, 100); }
/** * Is the URL on the same host? * * @param string $url * @return bool True if local; false otherwise. */ public static function isLocalUrl($url) { if (empty($url)) { return true; } // handle host name mangling $requestUri = isset($_SERVER['SCRIPT_URI']) ? $_SERVER['SCRIPT_URI'] : ''; $parseRequest = @parse_url($requestUri); $hosts = array(self::getHost(), self::getCurrentHost()); if (!empty($parseRequest['host'])) { $hosts[] = $parseRequest['host']; } // drop port numbers from hostnames and IP addresses $hosts = array_map(array('Piwik_IP', 'sanitizeIp'), $hosts); $disableHostCheck = Piwik_Config::getInstance()->General['enable_trusted_host_check'] == 0; // compare scheme and host $parsedUrl = @parse_url($url); $host = Piwik_IP::sanitizeIp(@$parsedUrl['host']); return !empty($host) && ($disableHostCheck || in_array($host, $hosts)) && !empty($parsedUrl['scheme']) && in_array($parsedUrl['scheme'], array('http', 'https')); }
/** * Checks if the visitor ip is in the excluded list * * @param string $ip Long IP * @return bool */ protected function isVisitorIpExcluded($ip) { $websiteAttributes = Piwik_Common::getCacheWebsiteAttributes($this->idsite); if (!empty($websiteAttributes['excluded_ips'])) { if (Piwik_IP::isIpInRange($ip, $websiteAttributes['excluded_ips'])) { printDebug('Visitor IP ' . Piwik_IP::N2P($ip) . ' is excluded from being tracked'); return true; } } return false; }
/** * Is the URL on the same host? * * @param string $url * @return bool True if local; false otherwise. */ public static function isLocalUrl($url) { if (empty($url)) { return true; } // handle host name mangling $requestUri = isset($_SERVER['SCRIPT_URI']) ? $_SERVER['SCRIPT_URI'] : ''; $parseRequest = @parse_url($requestUri); $hosts = array(self::getHost(), self::getCurrentHost()); if (isset($parseRequest['host'])) { $hosts[] = $parseRequest['host']; } // drop port numbers from hostnames and IP addresses $hosts = array_map(array('Piwik_IP', 'sanitizeIp'), $hosts); // compare scheme and host $parsedUrl = @parse_url($url); $scheme = $parsedUrl['scheme']; $host = Piwik_IP::sanitizeIp($parsedUrl['host']); return in_array($scheme, array('http', 'https')) && in_array($host, $hosts); }
$rows = Piwik_FetchAll("SELECT idvisit, location_ip, " . implode(',', array_keys($logVisitFieldsToUpdate)) . "\n\t\t\t\t\t\tFROM " . Piwik_Common::prefixTable('log_visit') . " \n\t\t\t\t\t\tLIMIT {$start}, {$limit}"); if (!count($rows)) { continue; } foreach ($rows as $i => $row) { $fieldsToSet = array(); foreach ($logVisitFieldsToUpdate as $field => $ignore) { if (empty($fieldsToSet[$field])) { $fieldsToSet[] = $field; } } // skip if it already has a location if (empty($fieldsToSet)) { continue; } $ip = Piwik_IP::N2P($row['location_ip']); $location = $provider->getLocation(array('ip' => $ip)); if (!empty($location[Piwik_UserCountry_LocationProvider::COUNTRY_CODE_KEY])) { $location[Piwik_UserCountry_LocationProvider::COUNTRY_CODE_KEY] = strtolower($location[Piwik_UserCountry_LocationProvider::COUNTRY_CODE_KEY]); } $row['location_country'] = strtolower($row['location_country']); $columnsToSet = array(); $bind = array(); foreach ($logVisitFieldsToUpdate as $column => $locationKey) { if (!empty($location[$locationKey]) && $location[$locationKey] != $row[$column]) { $columnsToSet[] = $column . ' = ?'; $bind[] = $location[$locationKey]; } } if (empty($columnsToSet)) { continue;
/** * Convert IP address (in network address format) to presentation format. * This is a backward compatibility function for code that only expects * IPv4 addresses (i.e., doesn't support IPv6). * * @see Piwik_IP::N2P() * * This function does not support the long (or its string representation) * returned by the built-in ip2long() function, from Piwik 1.3 and earlier. * * @deprecated 1.4 * * @param string $ip IP address in network address format * @return string */ public static function long2ip($ip) { return Piwik_IP::long2ip($ip); }
/** * Validate user (by username or email address). * * @param string $loginMail user name or email address * @return string failure message if unable to validate */ protected function lostPasswordFormValidated($loginMail) { if ($loginMail === 'anonymous') { return Piwik_Translate('Login_InvalidUsernameEmail'); } $user = self::getUserInformation($loginMail); if ($user === null) { return Piwik_Translate('Login_InvalidUsernameEmail'); } $view = Piwik_View::factory('passwordsent'); $login = $user['login']; $email = $user['email']; // construct a password reset token from user information $resetToken = self::generatePasswordResetToken($user); $ip = Piwik_IP::getIpFromHeader(); $url = Piwik_Url::getCurrentUrlWithoutQueryString() . "?module=Login&action=resetPassword&token={$resetToken}"; // send email with new password try { $mail = new Piwik_Mail(); $mail->addTo($email, $login); $mail->setSubject(Piwik_Translate('Login_MailTopicPasswordRecovery')); $bodyText = str_replace('\\n', "\n", sprintf(Piwik_Translate('Login_MailPasswordRecoveryBody'), $login, $ip, $url, $resetToken)) . "\n"; $mail->setBodyText($bodyText); $fromEmailName = Piwik_Config::getInstance()->General['login_password_recovery_email_name']; $fromEmailAddress = Piwik_Config::getInstance()->General['login_password_recovery_email_address']; $mail->setFrom($fromEmailAddress, $fromEmailName); @$mail->send(); } catch (Exception $e) { $view->ErrorString = $e->getMessage(); } $this->configureView($view); echo $view->render(); exit; }
/** * Sends http request using the specified transport method * * @param string $method * @param string $aUrl * @param int $timeout * @param string $userAgent * @param string $destinationPath * @param resource $file * @param int $followDepth * @param bool|string $acceptLanguage Accept-language header * @param bool $acceptInvalidSslCertificate Only used with $method == 'curl'. If set to true (NOT recommended!) the SSL certificate will not be checked * @throws Exception * @return bool true (or string) on success; false on HTTP response error code (1xx or 4xx) */ public static function sendHttpRequestBy($method = 'socket', $aUrl, $timeout, $userAgent = null, $destinationPath = null, $file = null, $followDepth = 0, $acceptLanguage = false, $acceptInvalidSslCertificate = false) { if ($followDepth > 5) { throw new Exception('Too many redirects (' . $followDepth . ')'); } $contentLength = 0; $fileLength = 0; // Piwik services behave like a proxy, so we should act like one. $xff = 'X-Forwarded-For: ' . (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] . ',' : '') . Piwik_IP::getIpFromHeader(); if (empty($userAgent)) { $userAgent = self::getUserAgent(); } $via = 'Via: ' . (isset($_SERVER['HTTP_VIA']) && !empty($_SERVER['HTTP_VIA']) ? $_SERVER['HTTP_VIA'] . ', ' : '') . Piwik_Version::VERSION . ' ' . ($userAgent ? " ({$userAgent})" : ''); // proxy configuration $proxyHost = Piwik_Config::getInstance()->proxy['host']; $proxyPort = Piwik_Config::getInstance()->proxy['port']; $proxyUser = Piwik_Config::getInstance()->proxy['username']; $proxyPassword = Piwik_Config::getInstance()->proxy['password']; if ($method == 'socket') { // initialization $url = @parse_url($aUrl); if ($url === false || !isset($url['scheme'])) { throw new Exception('Malformed URL: ' . $aUrl); } if ($url['scheme'] != 'http') { throw new Exception('Invalid protocol/scheme: ' . $url['scheme']); } $host = $url['host']; $port = isset($url['port)']) ? $url['port'] : 80; $path = isset($url['path']) ? $url['path'] : '/'; if (isset($url['query'])) { $path .= '?' . $url['query']; } $errno = null; $errstr = null; $proxyAuth = null; if (!empty($proxyHost) && !empty($proxyPort)) { $connectHost = $proxyHost; $connectPort = $proxyPort; if (!empty($proxyUser) && !empty($proxyPassword)) { $proxyAuth = 'Proxy-Authorization: Basic ' . base64_encode("{$proxyUser}:{$proxyPassword}") . "\r\n"; } $requestHeader = "GET {$aUrl} HTTP/1.1\r\n"; } else { $connectHost = $host; $connectPort = $port; $requestHeader = "GET {$path} HTTP/1.0\r\n"; } // connection attempt if (($fsock = @fsockopen($connectHost, $connectPort, $errno, $errstr, $timeout)) === false || !is_resource($fsock)) { if (is_resource($file)) { @fclose($file); } throw new Exception("Error while connecting to: {$host}. Please try again later. {$errstr}"); } // send HTTP request header $requestHeader .= "Host: {$host}" . ($port != 80 ? ':' . $port : '') . "\r\n" . ($proxyAuth ? $proxyAuth : '') . 'User-Agent: ' . $userAgent . "\r\n" . ($acceptLanguage ? $acceptLanguage . "\r\n" : '') . $xff . "\r\n" . $via . "\r\n" . "Connection: close\r\n" . "\r\n"; fwrite($fsock, $requestHeader); $streamMetaData = array('timed_out' => false); @stream_set_blocking($fsock, true); if (function_exists('stream_set_timeout')) { @stream_set_timeout($fsock, $timeout); } elseif (function_exists('socket_set_timeout')) { @socket_set_timeout($fsock, $timeout); } // process header $status = null; $expectRedirect = false; while (!feof($fsock)) { $line = fgets($fsock, 4096); $streamMetaData = @stream_get_meta_data($fsock); if ($streamMetaData['timed_out']) { if (is_resource($file)) { @fclose($file); } @fclose($fsock); throw new Exception('Timed out waiting for server response'); } // a blank line marks the end of the server response header if (rtrim($line, "\r\n") == '') { break; } // parse first line of server response header if (!$status) { // expect first line to be HTTP response status line, e.g., HTTP/1.1 200 OK if (!preg_match('~^HTTP/(\\d\\.\\d)\\s+(\\d+)(\\s*.*)?~', $line, $m)) { if (is_resource($file)) { @fclose($file); } @fclose($fsock); throw new Exception('Expected server response code. Got ' . rtrim($line, "\r\n")); } $status = (int) $m[2]; // Informational 1xx or Client Error 4xx if ($status < 200 || $status >= 400) { if (is_resource($file)) { @fclose($file); } @fclose($fsock); return false; } continue; } // handle redirect if (preg_match('/^Location:\\s*(.+)/', rtrim($line, "\r\n"), $m)) { if (is_resource($file)) { @fclose($file); } @fclose($fsock); // Successful 2xx vs Redirect 3xx if ($status < 300) { throw new Exception('Unexpected redirect to Location: ' . rtrim($line) . ' for status code ' . $status); } return self::sendHttpRequestBy($method, trim($m[1]), $timeout, $userAgent, $destinationPath, $file, $followDepth + 1, $acceptLanguage); } // save expected content length for later verification if (preg_match('/^Content-Length:\\s*(\\d+)/', $line, $m)) { $contentLength = (int) $m[1]; } } if (feof($fsock)) { throw new Exception('Unexpected end of transmission'); } // process content/body $response = ''; while (!feof($fsock)) { $line = fread($fsock, 8192); $streamMetaData = @stream_get_meta_data($fsock); if ($streamMetaData['timed_out']) { if (is_resource($file)) { @fclose($file); } @fclose($fsock); throw new Exception('Timed out waiting for server response'); } $fileLength += Piwik_Common::strlen($line); if (is_resource($file)) { // save to file fwrite($file, $line); } else { // concatenate to response string $response .= $line; } } // determine success or failure @fclose(@$fsock); } else { if ($method == 'fopen') { $response = false; // we make sure the request takes less than a few seconds to fail // we create a stream_context (works in php >= 5.2.1) // we also set the socket_timeout (for php < 5.2.1) $default_socket_timeout = @ini_get('default_socket_timeout'); @ini_set('default_socket_timeout', $timeout); $ctx = null; if (function_exists('stream_context_create')) { $stream_options = array('http' => array('header' => 'User-Agent: ' . $userAgent . "\r\n" . ($acceptLanguage ? $acceptLanguage . "\r\n" : '') . $xff . "\r\n" . $via . "\r\n", 'max_redirects' => 5, 'timeout' => $timeout)); if (!empty($proxyHost) && !empty($proxyPort)) { $stream_options['http']['proxy'] = 'tcp://' . $proxyHost . ':' . $proxyPort; $stream_options['http']['request_fulluri'] = true; // required by squid proxy if (!empty($proxyUser) && !empty($proxyPassword)) { $stream_options['http']['header'] .= 'Proxy-Authorization: Basic ' . base64_encode("{$proxyUser}:{$proxyPassword}") . "\r\n"; } } $ctx = stream_context_create($stream_options); } // save to file if (is_resource($file)) { $handle = fopen($aUrl, 'rb', false, $ctx); while (!feof($handle)) { $response = fread($handle, 8192); $fileLength += Piwik_Common::strlen($response); fwrite($file, $response); } fclose($handle); } else { $response = @file_get_contents($aUrl, 0, $ctx); $fileLength = Piwik_Common::strlen($response); } // restore the socket_timeout value if (!empty($default_socket_timeout)) { @ini_set('default_socket_timeout', $default_socket_timeout); } } else { if ($method == 'curl') { $ch = @curl_init(); if (!empty($proxyHost) && !empty($proxyPort)) { @curl_setopt($ch, CURLOPT_PROXY, $proxyHost . ':' . $proxyPort); if (!empty($proxyUser) && !empty($proxyPassword)) { // PROXYAUTH defaults to BASIC @curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyUser . ':' . $proxyPassword); } } $curl_options = array(CURLOPT_BINARYTRANSFER => is_resource($file), CURLOPT_URL => $aUrl, CURLOPT_USERAGENT => $userAgent, CURLOPT_HTTPHEADER => array($xff, $via, $acceptLanguage), CURLOPT_HEADER => false, CURLOPT_CONNECTTIMEOUT => $timeout); // Case archive.php is triggering archiving on https:// and the certificate is not valid if ($acceptInvalidSslCertificate) { $curl_options += array(CURLOPT_SSL_VERIFYHOST => false, CURLOPT_SSL_VERIFYPEER => false); } @curl_setopt_array($ch, $curl_options); self::configCurlCertificate($ch); /* * as of php 5.2.0, CURLOPT_FOLLOWLOCATION can't be set if * in safe_mode or open_basedir is set */ if ((string) ini_get('safe_mode') == '' && ini_get('open_basedir') == '') { $curl_options = array(CURLOPT_FOLLOWLOCATION => true, CURLOPT_MAXREDIRS => 5); @curl_setopt_array($ch, $curl_options); } if (is_resource($file)) { // write output directly to file @curl_setopt($ch, CURLOPT_FILE, $file); } else { // internal to ext/curl @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); } ob_start(); $response = @curl_exec($ch); ob_end_clean(); if ($response === true) { $response = ''; } else { if ($response === false) { $errstr = curl_error($ch); if ($errstr != '') { throw new Exception('curl_exec: ' . $errstr); } $response = ''; } } $contentLength = @curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD); $fileLength = is_resource($file) ? @curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD) : Piwik_Common::strlen($response); @curl_close($ch); unset($ch); } else { throw new Exception('Invalid request method: ' . $method); } } } if (is_resource($file)) { fflush($file); @fclose($file); $fileSize = filesize($destinationPath); if ($contentLength > 0 && $fileLength != $contentLength || $fileSize != $fileLength) { throw new Exception('File size error: ' . $destinationPath . '; expected ' . $contentLength . ' bytes; received ' . $fileLength . ' bytes; saved ' . $fileSize . ' bytes to file'); } return true; } if ($contentLength > 0 && $fileLength != $contentLength) { throw new Exception('Content length error: expected ' . $contentLength . ' bytes; received ' . $fileLength . ' bytes'); } return trim($response); }
} if (is_resource($f)) { $logMe = true; if (isset($_COOKIE['clickheat-admin'])) { echo 'OK, but click not logged as you selected it in the admin panel ("Log my clicks/Enregistrer mes clics")'; $logMe = false; } elseif (IS_PIWIK_MODULE === true) { $site = (string) (int) $site; // prevents path injection if (file_exists(PIWIK_INCLUDE_PATH . '/tmp/cache/tracker/' . $site . '.php')) { include PIWIK_INCLUDE_PATH . '/tmp/cache/tracker/' . $site . '.php'; if (isset($content['excluded_ips'])) { include PIWIK_INCLUDE_PATH . '/core/Common.php'; include PIWIK_INCLUDE_PATH . '/core/IP.php'; $ip = Piwik_IP::P2N(isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']); if (Piwik_IP::isIpInRange($ip, $content['excluded_ips']) === true) { echo 'OK, but click not logged as you prevent this IP to be tracked in Piwik\'s configuration'; $logMe = false; } } } } if ($logMe === true) { echo 'OK'; fputs($f, (int) $_GET['x'] . '|' . (int) $_GET['y'] . '|' . (int) $_GET['w'] . '|' . $browser . '|' . (int) $_GET['c'] . "\n"); } fclose($f); } else { echo 'KO, file not writable'; } /* Temporary debug for Labsmedia.com, don't worry about this :-) */
/** * Returns the hostname given the IP address string * * @param string $ip IP Address * @return string hostname (or human-readable IP address) */ private function getHost($ip) { return trim(strtolower(@Piwik_IP::getHostByAddr($ip))); }
/** * Sends email confirmation link for a password reset request. * * @param array $user User info for the requested password reset. */ private function sendEmailConfirmationLink($user) { $login = $user['login']; $email = $user['email']; // construct a password reset token from user information $resetToken = self::generatePasswordResetToken($user); $ip = Piwik_IP::getIpFromHeader(); $url = Piwik_Url::getCurrentUrlWithoutQueryString() . "?module=Login&action=confirmResetPassword&login="******"&resetToken=" . urlencode($resetToken); // send email with new password $mail = new Piwik_Mail(); $mail->addTo($email, $login); $mail->setSubject(Piwik_Translate('Login_MailTopicPasswordChange')); $bodyText = str_replace('\\n', "\n", sprintf(Piwik_Translate('Login_MailPasswordChangeBody'), $login, $ip, $url)) . "\n"; $mail->setBodyText($bodyText); $fromEmailName = Piwik_Config::getInstance()->General['login_password_recovery_email_name']; $fromEmailAddress = Piwik_Config::getInstance()->General['login_password_recovery_email_address']; $mail->setFrom($fromEmailAddress, $fromEmailName); @$mail->send(); }