diff --git a/Sources/Actions/Admin/Server.php b/Sources/Actions/Admin/Server.php index e092d4aabd..cbf5e20d2f 100644 --- a/Sources/Actions/Admin/Server.php +++ b/Sources/Actions/Admin/Server.php @@ -27,6 +27,7 @@ use SMF\Menu; use SMF\Sapi; use SMF\SecurityToken; +use SMF\Statistics; use SMF\Theme; use SMF\Url; use SMF\User; @@ -252,13 +253,17 @@ public function general(): void // Are we saving the stat collection? if (!empty($_POST['enable_sm_stats']) && empty(Config::$modSettings['sm_stats_key'])) { - $registerSMStats = $this->registerSMStats(); + $registerSMStats = Statistics::register(); // Failed to register, disable it again. if (empty($registerSMStats)) { $_POST['enable_sm_stats'] = 0; } } + // Clear the registration. + elseif (empty($_POST['enable_sm_stats']) && !empty(Config::$modSettings['sm_stats_key'])) { + Statistics::clear(); + } // Ensure all URLs are aligned with the new force_ssl setting // Treat unset like 0 @@ -1606,67 +1611,4 @@ protected function boardurlMatch(string $url = ''): bool return $result === false || $result != 0 ? false : true; } - - /** - * Registers the site with the Simple Machines Stat collection. This function - * purposely does not use Config::updateModSettings() as it will be called shortly after - * this process completes by the saveSettings() function. - * - * @see SMStats() for more information. - * @link https://www.simplemachines.org/about/stats.php for more info. - * @return bool Returns true if we are registered or successfully registered, otherwise false. - */ - protected function registerSMStats(): bool - { - // Already have a key? Can't register again. - if (!empty(Config::$modSettings['sm_stats_key'])) { - return true; - } - - $fp = @fsockopen('www.simplemachines.org', 443, $errno, $errstr); - - if (!$fp) { - $fp = @fsockopen('www.simplemachines.org', 80, $errno, $errstr); - } - - if ($fp) { - $out = 'GET /smf/stats/register_stats.php?site=' . base64_encode(Config::$boardurl) . ' HTTP/1.1' . "\r\n"; - $out .= 'Host: www.simplemachines.org' . "\r\n"; - $out .= 'Connection: Close' . "\r\n\r\n"; - fwrite($fp, $out); - - $return_data = ''; - - while (!feof($fp)) { - $return_data .= fgets($fp, 128); - } - - fclose($fp); - - // Get the unique site ID. - preg_match('~SITE-ID:\s(\w{10})~', $return_data, $ID); - - if (!empty($ID[1])) { - Db::$db->insert( - 'replace', - '{db_prefix}settings', - [ - 'variable' => 'string', - 'value' => 'string', - ], - [ - [ - 'sm_stats_key', - $ID[1], - ], - ], - ['variable'], - ); - - return true; - } - } - - return false; - } } diff --git a/Sources/Actions/SmStats.php b/Sources/Actions/SmStats.php index ca33d6e094..af8abffd96 100644 --- a/Sources/Actions/SmStats.php +++ b/Sources/Actions/SmStats.php @@ -17,10 +17,10 @@ use SMF\ActionInterface; use SMF\ActionRouter; -use SMF\Actions\Admin\ACP; use SMF\ActionTrait; use SMF\Config; use SMF\Routable; +use SMF\Statistics; use SMF\User; use SMF\WebFetch\WebFetchApi; @@ -71,50 +71,25 @@ public function execute(): void } // Verify the referer... - if (!User::$me->is_admin && (!isset($_SERVER['HTTP_REFERER']) || md5($_SERVER['HTTP_REFERER']) != '746cb59a1a0d5cf4bd240e5a67c73085')) { + if (!User::$me->is_admin && (!isset($_SERVER['HTTP_REFERER']) || md5($_SERVER['HTTP_REFERER']) != Statistics::$referer_check)) { die(); } - // Get some server versions. - $checkFor = [ - 'php', - 'db_server', - ]; - $serverVersions = ACP::getServerVersions($checkFor); - - // Get the actual stats. - $stats_to_send = [ - 'UID' => Config::$modSettings['sm_stats_key'], - 'time_added' => time(), - 'members' => Config::$modSettings['totalMembers'], - 'messages' => Config::$modSettings['totalMessages'], - 'topics' => Config::$modSettings['totalTopics'], - 'boards' => 0, - 'php_version' => $serverVersions['php']['version'], - 'database_type' => strtolower($serverVersions['db_engine']['version']), - 'database_version' => $serverVersions['db_server']['version'], - 'smf_version' => SMF_FULL_VERSION, - 'smfd_version' => Config::$modSettings['smfVersion'], - ]; - - // Encode all the data, for security. - foreach ($stats_to_send as $k => $v) { - $stats_to_send[$k] = urlencode($k) . '=' . urlencode($v); - } + $stats_to_send = Statistics::collect(); // Turn this into the query string! - $stats_to_send = implode('&', $stats_to_send); + $stats_to_send = http_build_query($stats_to_send); // If we're an admin, just plonk them out. if (User::$me->is_admin) { echo $stats_to_send; } else { // Connect to the collection script. - $res = WebFetchApi::fetch('https://www.simplemachines.org/smf/stats/collect_stats.php', $stats_to_send); + $res = WebFetchApi::fetch(Statistics::$collection_url, $stats_to_send); // Try one more time, this time without https. if ($res !== '1') { - WebFetchApi::fetch('http://www.simplemachines.org/smf/stats/collect_stats.php', $stats_to_send); + WebFetchApi::fetch(str_replace('https://', 'http://', Statistics::$collection_url), $stats_to_send); } } diff --git a/Sources/Maintenance/Tools/Install.php b/Sources/Maintenance/Tools/Install.php index 457bc6e923..a68c2909f8 100644 --- a/Sources/Maintenance/Tools/Install.php +++ b/Sources/Maintenance/Tools/Install.php @@ -27,6 +27,7 @@ use SMF\Maintenance\Step; use SMF\Sapi; use SMF\Security; +use SMF\Statistics; use SMF\TaskRunner; use SMF\Themes\default\MaintenanceTemplate; use SMF\Time; @@ -1507,35 +1508,10 @@ private function toggleSmStats(array &$settings): void ) { Utils::$context['allow_sm_stats'] = true; - // Attempt to register the site etc. - $fp = @fsockopen('www.simplemachines.org', 443, $errno, $errstr); + $uid = Statistics::register(); - if (!$fp) { - $fp = @fsockopen('www.simplemachines.org', 80, $errno, $errstr); - } - - if (!$fp) { - return; - } - - $out = 'GET /smf/stats/register_stats.php?site=' . base64_encode(Config::$boardurl) . ' HTTP/1.1' . "\r\n"; - $out .= 'Host: www.simplemachines.org' . "\r\n"; - $out .= 'Connection: Close' . "\r\n\r\n"; - fwrite($fp, $out); - - $return_data = ''; - - while (!feof($fp)) { - $return_data .= fgets($fp, 128); - } - - fclose($fp); - - // Get the unique site ID. - preg_match('~SITE-ID:\s(\w{10})~', $return_data, $ID); - - if (!empty($ID[1])) { - $settings['sm_stats_key'] = $ID[1]; + if (!empty($uid)) { + $settings['sm_stats_key'] = $uid; $settings['enable_sm_stats'] = 1; } } diff --git a/Sources/Maintenance/Tools/Upgrade.php b/Sources/Maintenance/Tools/Upgrade.php index b612262d28..e65d670dd0 100644 --- a/Sources/Maintenance/Tools/Upgrade.php +++ b/Sources/Maintenance/Tools/Upgrade.php @@ -31,6 +31,7 @@ use SMF\Sapi; use SMF\SecurityToken; use SMF\Session; +use SMF\Statistics; use SMF\Tasks\FetchSMFiles; use SMF\Tasks\UpdateSpoofDetectorNames; use SMF\Themes\default\MaintenanceTemplate; @@ -1576,35 +1577,10 @@ private function toggleSmStats(array &$settings): void ) { Utils::$context['allow_sm_stats'] = true; - // Attempt to register the site etc. - $fp = @fsockopen('www.simplemachines.org', 443, $errno, $errstr); + $uid = Statistics::register(); - if (!$fp) { - $fp = @fsockopen('www.simplemachines.org', 80, $errno, $errstr); - } - - if (!$fp) { - return; - } - - $out = 'GET /smf/stats/register_stats.php?site=' . base64_encode(Config::$boardurl) . ' HTTP/1.1' . "\r\n"; - $out .= 'Host: www.simplemachines.org' . "\r\n"; - $out .= 'Connection: Close' . "\r\n\r\n"; - fwrite($fp, $out); - - $return_data = ''; - - while (!feof($fp)) { - $return_data .= fgets($fp, 128); - } - - fclose($fp); - - // Get the unique site ID. - preg_match('~SITE-ID:\s(\w{10})~', $return_data, $ID); - - if (!empty($ID[1])) { - $settings['sm_stats_key'] = $ID[1]; + if (!empty($uid)) { + $settings['sm_stats_key'] = $uid; $settings['enable_sm_stats'] = 1; } } diff --git a/Sources/Statistics.php b/Sources/Statistics.php new file mode 100644 index 0000000000..1adbcb510a --- /dev/null +++ b/Sources/Statistics.php @@ -0,0 +1,176 @@ + Config::$modSettings['sm_stats_key'], + 'time_added' => time(), + 'members' => Config::$modSettings['totalMembers'], + 'messages' => Config::$modSettings['totalMessages'], + 'topics' => Config::$modSettings['totalTopics'], + 'boards' => 0, + 'php_version' => $serverVersions['php']['version'], + 'database_type' => strtolower($serverVersions['db_engine']['version']), + 'database_version' => $serverVersions['db_server']['version'], + 'smf_version' => SMF_FULL_VERSION, + 'smfd_version' => Config::$modSettings['smfVersion'], + ]; + + return $stats_to_send; + } + + /** + * Registers the site with the Simple Machines Stat collection. This function + * purposely does not use Config::updateModSettings() as it will be called shortly after + * this process completes by the saveSettings() function. + * + * This will send a request home and grab the UID for this + * installation. Only upon success will this return true. + * + * Lan based forums and those without DNS resolution will not register. + * + * @return bool Returns true if we are registered or successfully registered, otherwise false. + */ + public static function register(): bool + { + // Already have a key? Can't register again. + if (!empty(Config::$modSettings['sm_stats_key'])) { + return true; + } + + // If this is a local forum, registration will fail anyways. + if (!(new Url(Config::$boardurl))->isFetchSafe(['https', 'http'])) { + return false; + } + + $data = WebFetchApi::fetch(static::$register_url . base64_encode(Config::$boardurl)); + + // Try one more time, this time without https. + if (empty($data)) { + $data = WebFetchApi::fetch(str_replace('https://', 'http://', static::$register_url) . base64_encode(Config::$boardurl)); + } + + // Get the unique site ID. + preg_match('~SITE-ID:\s(\w{10})~', $data, $ID); + + if (!empty($ID[1])) { + Db::$db->insert( + 'replace', + '{db_prefix}settings', + [ + 'variable' => 'string', + 'value' => 'string', + ], + [ + [ + 'sm_stats_key', + $ID[1], + ], + ], + ['variable'], + ); + + return true; + } + + return false; + } + + /** + * Clears out the UID. + * + * No call home is made. + * Collection attempts will be made occastionally and + * will automatically stop after a period of time. + * + * @return bool True in all cases. + */ + public static function clear(): bool + { + Db::$db->query( + 'DELETE FROM {db_prefix}settings + WHERE variable = {literal:sm_stats_key}', + ); + + return true; + } +}