* * @author Julius Härtl * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * */ namespace OCA\Support\Sections; use OC\SystemConfig; use OCA\Files_External\Lib\StorageConfig; use OCA\Files_External\Service\GlobalStoragesService; use OCA\Support\IDetail; use OCA\User_LDAP\Configuration; use OCA\User_LDAP\Helper; use OCP\IConfig; use OC\IntegrityCheck\Checker; use OCP\App\IAppManager; use OCP\IDBConnection; use OCA\Support\Section; use OCA\Files_External\Service\BackendService; use OCP\IUserManager; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Output\BufferedOutput; class ServerSection extends Section { /** @var IConfig */ private $config; /** @var Checker */ private $checker; /** @var IAppManager */ private $appManager; /** @var SystemConfig */ private $systemConfig; /** @var IDBConnection */ private $connection; /** @var IUserManager */ private $userManager; public function __construct(IConfig $config, Checker $checker, IAppManager $appManager, IDBConnection $connection, IUserManager $userManager) { parent::__construct('server-detail', 'Server configuration detail'); $this->config = $config; $this->checker = $checker; $this->appManager = $appManager; $this->systemConfig = \OC::$server->query('SystemConfig'); $this->connection = $connection; $this->userManager = $userManager; $this->createDetail('Operating system', $this->getOsVersion()); $this->createDetail('Webserver', $this->getWebserver()); $this->createDetail('Database', $this->getDatabaseInfo()); $this->createDetail('PHP version', $this->getPhpVersion()); $this->createDetail('Nextcloud version', $this->getNextcloudVersion()); $this->createDetail('Updated from an older Nextcloud/ownCloud or fresh install', ''); $this->createDetail('Where did you install Nextcloud from', $this->getInstallMethod()); $this->createDetail('Signing status', $this->getIntegrityResults(), IDetail::TYPE_COLLAPSIBLE); $this->createDetail('List of activated apps', $this->renderAppList(), IDetail::TYPE_COLLAPSIBLE_PREFORMAT); $this->createDetail('Configuration (config/config.php)', print_r(json_encode($this->getConfig(), JSON_PRETTY_PRINT), true), IDetail::TYPE_COLLAPSIBLE_PREFORMAT); $externalStorageEnabled = $this->appManager->isEnabledForUser('files_external'); $this->createDetail('External storages', $externalStorageEnabled ? 'yes' : 'files_external is disabled'); if($externalStorageEnabled) { $this->createDetail('External storage configuration', $this->getExternalStorageInfo(), IDetail::TYPE_COLLAPSIBLE_PREFORMAT); } $this->createDetail('Encryption', $this->getEncryptionInfo()); $this->createDetail('User-backends', $this->getUserBackendInfo()); if ($this->isLDAPEnabled()) { $this->createDetail('LDAP configuration', $this->getLDAPInfo(), IDetail::TYPE_COLLAPSIBLE_PREFORMAT); } $this->createDetail('Browser', $this->getBrowser()); } private function getWebserver() { return $_SERVER['SERVER_SOFTWARE'] . ' (' . PHP_SAPI . ')'; } private function getNextcloudVersion() { return \OC_Util::getHumanVersion() . ' - ' . $this->config->getSystemValue('version'); } private function getOsVersion() { return function_exists('php_uname') ? php_uname('s') . ' ' . php_uname('r') . ' ' . php_uname('v') . ' ' . php_uname('m') : PHP_OS; } private function getPhpVersion() { return PHP_VERSION . "\n\nModules loaded: " . implode(', ', get_loaded_extensions()); } protected function getDatabaseInfo() { return $this->config->getSystemValue('dbtype') . ' ' . $this->getDatabaseVersion(); } /** * original source from nextcloud/survey_client * @link https://github.com/nextcloud/survey_client/blob/master/lib/Categories/Database.php#L80-L107 * * @copyright Copyright (c) 2016, ownCloud, Inc. * @author Joas Schilling * @license AGPL-3.0 */ private function getDatabaseVersion() { switch ($this->config->getSystemValue('dbtype')) { case 'sqlite': case 'sqlite3': $sql = 'SELECT sqlite_version() AS version'; break; case 'oci': $sql = 'SELECT version FROM v$instance'; break; case 'mysql': case 'pgsql': default: $sql = 'SELECT VERSION() AS version'; break; } $result = $this->connection->executeQuery($sql); $row = $result->fetch(); $result->closeCursor(); if ($row) { return $this->cleanVersion($row['version']); } return 'N/A'; } /** * Try to strip away additional information * * @copyright Copyright (c) 2016, ownCloud, Inc. * @author Joas Schilling * @license AGPL-3.0 * * @param string $version E.g. `5.6.27-0ubuntu0.14.04.1` * @return string `5.6.27` */ protected function cleanVersion($version) { $matches = []; preg_match('/^(\d+)(\.\d+)(\.\d+)/', $version, $matches); if (isset($matches[0])) { return $matches[0]; } return $version; } private function getIntegrityResults() { if(!$this->checker->isCodeCheckEnforced()) { return 'Integrity checker has been disabled. Integrity cannot be verified.'; } return $this->checker->getResults(); } private function getInstallMethod() { $base = \OC::$SERVERROOT; if(file_exists($base . '/.git')) { return 'git'; } return 'unknown'; } private function renderAppList() { $apps = $this->getAppList(); $result = "Enabled:\n"; foreach ($apps['enabled'] as $name => $version) { $result .= ' - ' . $name . ': ' . $version . "\n"; } $result .= "Disabled:\n"; foreach ($apps['disabled'] as $name => $version) { $result .= ' - ' . $name . "\n"; } return $result; } /** * @return string[][] */ private function getAppList() { $apps = \OC_App::getAllApps(); $enabledApps = $disabledApps = []; $versions = \OC_App::getAppVersions(); //sort enabled apps above disabled apps foreach ($apps as $app) { if ($this->appManager->isInstalled($app)) { $enabledApps[] = $app; } else { $disabledApps[] = $app; } } $apps = ['enabled' => [], 'disabled' => []]; sort($enabledApps); foreach ($enabledApps as $app) { $apps['enabled'][$app] = isset($versions[$app]) ? $versions[$app] : true; } sort($disabledApps); foreach ($disabledApps as $app) { $apps['disabled'][$app] = null; } return $apps; } protected function getEncryptionInfo() { return $this->config->getAppValue('core', 'encryption_enabled', 'no'); } protected function getExternalStorageInfo() { $globalService = \OC::$server->query(GlobalStoragesService::class); $mounts = $globalService->getStorageForAllUsers(); // copy of OCA\Files_External\Command\ListCommand::listMounts if ($mounts === null || count($mounts) === 0) { return 'No mounts configured'; } $headers = ['Mount ID', 'Mount Point', 'Storage', 'Authentication Type', 'Configuration', 'Options']; $headers[] = 'Applicable Users'; $headers[] = 'Applicable Groups'; $headers[] = 'Type'; $hideKeys = ['password', 'refresh_token', 'token', 'client_secret', 'public_key', 'private_key']; /** @var StorageConfig $mount */ foreach ($mounts as $mount) { $config = $mount->getBackendOptions(); foreach ($config as $key => $value) { if (in_array($key, $hideKeys)) { $mount->setBackendOption($key, '***'); } } } $defaultMountOptions = [ 'encrypt' => true, 'previews' => true, 'filesystem_check_changes' => 1, 'enable_sharing' => false, 'encoding_compatibility' => false ]; $rows = array_map(function (StorageConfig $config) use ($defaultMountOptions) { $storageConfig = $config->getBackendOptions(); $keys = array_keys($storageConfig); $values = array_values($storageConfig); $configStrings = array_map(function ($key, $value) { return $key . ': ' . json_encode($value); }, $keys, $values); $configString = implode(', ', $configStrings); $mountOptions = $config->getMountOptions(); // hide defaults foreach ($mountOptions as $key => $value) { if ($value === $defaultMountOptions[$key]) { unset($mountOptions[$key]); } } $keys = array_keys($mountOptions); $values = array_values($mountOptions); $optionsStrings = array_map(function ($key, $value) { return $key . ': ' . json_encode($value); }, $keys, $values); $optionsString = implode(', ', $optionsStrings); $values = [ $config->getId(), $config->getMountPoint(), $config->getBackend()->getText(), $config->getAuthMechanism()->getText(), $configString, $optionsString ]; $applicableUsers = implode(', ', $config->getApplicableUsers()); $applicableGroups = implode(', ', $config->getApplicableGroups()); if ($applicableUsers === '' && $applicableGroups === '') { $applicableUsers = 'All'; } $values[] = $applicableUsers; $values[] = $applicableGroups; $values[] = $config->getType() === StorageConfig::MOUNT_TYPE_ADMIN ? 'Admin' : 'Personal'; return $values; }, $mounts); $output = new BufferedOutput(); $table = new Table($output); $table->setHeaders($headers); $table->setRows($rows); $table->render(); return $output->fetch(); } private function getConfig() { $keys = $this->systemConfig->getKeys(); $configs = []; foreach ($keys as $key) { $value = $this->systemConfig->getFilteredValue($key, serialize(null)); if ($value !== 'N;') { $configs[$key] = $value; } } return $configs; } private function getBrowser() { $browser = @get_browser(null, true); $browserString = ''; if($browser) { if(array_key_exists('browser', $browser)) { $browserString .= $browser['browser'] . ' '; } if(array_key_exists('version', $browser)) { $browserString .= $browser['version'] . ' '; } if(array_key_exists('plattform', $browser)) { $browserString .= $browser['plattform'] . ' '; } } if(empty($browserString)) { return $_SERVER['HTTP_USER_AGENT']; } return $browserString; } private function getUserBackendInfo() { $backends = $this->userManager->getBackends(); $output = PHP_EOL; foreach ($backends as $backend) { $output .= ' * ' . get_class($backend) . PHP_EOL; } return $output; } private function isLDAPEnabled() { $backends = $this->userManager->getBackends(); foreach ($backends as $backend) { if ($backend instanceof \OCA\User_LDAP\User_Proxy) { return true; } } return false; } private function getLDAPInfo() { /** @var Helper $helper */ $helper = \OC::$server->query(Helper::class); $output = new BufferedOutput(); // copy of OCA\User_LDAP\Command\ShowConfig::renderConfigs $configIDs = $helper->getServerConfigurationPrefixes(); foreach($configIDs as $id) { $configHolder = new Configuration($id); $configuration = $configHolder->getConfiguration(); ksort($configuration); $table = new Table($output); $table->setHeaders(array('Configuration', $id)); $rows = array(); foreach($configuration as $key => $value) { if($key === 'ldapAgentPassword') { $value = '***'; } if(is_array($value)) { $value = implode(';', $value); } $rows[] = array($key, $value); } $table->setRows($rows); $table->render(); } return $output->fetch(); } }