public function testUpdateApp() { $pathOfOldTestApp = __DIR__; $pathOfOldTestApp .= '/../data/'; $pathOfOldTestApp .= 'testapp.zip'; $oldTmp = \OC::$server->getTempManager()->getTemporaryFile('.zip'); \OC_Helper::copyr($pathOfOldTestApp, $oldTmp); $oldData = array('path' => $oldTmp, 'source' => 'path', 'appdata' => ['id' => 'Bar', 'level' => 100]); $pathOfNewTestApp = __DIR__; $pathOfNewTestApp .= '/../data/'; $pathOfNewTestApp .= 'testapp2.zip'; $newTmp = \OC::$server->getTempManager()->getTemporaryFile('.zip'); \OC_Helper::copyr($pathOfNewTestApp, $newTmp); $newData = array('path' => $newTmp, 'source' => 'path', 'appdata' => ['id' => 'Bar', 'level' => 100]); Installer::installApp($oldData); $oldVersionNumber = \OC_App::getAppVersion(self::$appid); Installer::updateApp($newData); $newVersionNumber = \OC_App::getAppVersion(self::$appid); $this->assertNotEquals($oldVersionNumber, $newVersionNumber); }
/** * @param array $disabledApps * @throws \Exception */ private function upgradeAppStoreApps(array $disabledApps) { foreach ($disabledApps as $app) { try { if (Installer::isUpdateAvailable($app)) { $ocsId = \OC::$server->getConfig()->getAppValue($app, 'ocsid', ''); $this->emit('\\OC\\Updater', 'upgradeAppStoreApp', array($app)); Installer::updateAppByOCSId($ocsId); } } catch (\Exception $ex) { $this->log->logException($ex, ['app' => 'core']); } } }
/** * @param $options * @return array */ public function install($options) { $l = $this->l10n; $error = array(); $dbType = $options['dbtype']; if (empty($options['adminlogin'])) { $error[] = $l->t('Set an admin username.'); } if (empty($options['adminpass'])) { $error[] = $l->t('Set an admin password.'); } if (empty($options['directory'])) { $options['directory'] = \OC::$SERVERROOT . "/data"; } if (!isset(self::$dbSetupClasses[$dbType])) { $dbType = 'sqlite'; } $username = htmlspecialchars_decode($options['adminlogin']); $password = htmlspecialchars_decode($options['adminpass']); $dataDir = htmlspecialchars_decode($options['directory']); $class = self::$dbSetupClasses[$dbType]; /** @var \OC\Setup\AbstractDatabase $dbSetup */ $dbSetup = new $class($l, 'db_structure.xml', $this->config, $this->logger, $this->random); $error = array_merge($error, $dbSetup->validate($options)); // validate the data directory if (!is_dir($dataDir) and !mkdir($dataDir) or !is_writable($dataDir)) { $error[] = $l->t("Can't create or write into the data directory %s", array($dataDir)); } if (count($error) != 0) { return $error; } $request = \OC::$server->getRequest(); //no errors, good if (isset($options['trusted_domains']) && is_array($options['trusted_domains'])) { $trustedDomains = $options['trusted_domains']; } else { $trustedDomains = [$request->getInsecureServerHost()]; } if (\OC_Util::runningOnWindows()) { $dataDir = rtrim(realpath($dataDir), '\\'); } //use sqlite3 when available, otherwise sqlite2 will be used. if ($dbType == 'sqlite' and class_exists('SQLite3')) { $dbType = 'sqlite3'; } //generate a random salt that is used to salt the local user passwords $salt = $this->random->generate(30); // generate a secret $secret = $this->random->generate(48); //write the config file $this->config->setSystemValues(['passwordsalt' => $salt, 'secret' => $secret, 'trusted_domains' => $trustedDomains, 'datadirectory' => $dataDir, 'overwrite.cli.url' => $request->getServerProtocol() . '://' . $request->getInsecureServerHost() . \OC::$WEBROOT, 'dbtype' => $dbType, 'version' => implode('.', \OCP\Util::getVersion())]); try { $dbSetup->initialize($options); $dbSetup->setupDatabase($username); } catch (\OC\DatabaseSetupException $e) { $error[] = array('error' => $e->getMessage(), 'hint' => $e->getHint()); return $error; } catch (Exception $e) { $error[] = array('error' => 'Error while trying to create admin user: '******'hint' => ''); return $error; } //create the user and group $user = null; try { $user = \OC::$server->getUserManager()->createUser($username, $password); if (!$user) { $error[] = "User <{$username}> could not be created."; } } catch (Exception $exception) { $error[] = $exception->getMessage(); } if (count($error) == 0) { $config = \OC::$server->getConfig(); $config->setAppValue('core', 'installedat', microtime(true)); $config->setAppValue('core', 'lastupdatedat', microtime(true)); $group = \OC::$server->getGroupManager()->createGroup('admin'); $group->addUser($user); // Create a session token for the newly created user // The token provider requires a working db, so it's not injected on setup /* @var $userSession User\Session */ $userSession = \OC::$server->getUserSession(); $defaultTokenProvider = \OC::$server->query('OC\\Authentication\\Token\\DefaultTokenProvider'); $userSession->setTokenProvider($defaultTokenProvider); $userSession->login($username, $password); $userSession->createSessionToken($request, $userSession->getUser()->getUID(), $username, $password); //guess what this does Installer::installShippedApps(); // create empty file in data dir, so we can later find // out that this is indeed an ownCloud data directory file_put_contents($config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', ''); // Update .htaccess files Setup::updateHtaccess(); Setup::protectDataDirectory(); //try to write logtimezone if (date_default_timezone_get()) { $config->setSystemValue('logtimezone', date_default_timezone_get()); } self::installBackgroundJobs(); //and we are done $config->setSystemValue('installed', true); } return $error; }
OCP\JSON::checkAdminUser(); OCP\JSON::callCheck(); if (!array_key_exists('appid', $_POST)) { OCP\JSON::error(array('message' => 'No AppId given!')); return; } $appId = (string) $_POST['appid']; if (!is_numeric($appId)) { $appId = \OC::$server->getAppConfig()->getValue($appId, 'ocsid', null); if ($appId === null) { OCP\JSON::error(array('message' => 'No OCS-ID found for app!')); exit; } } $appId = OC_App::cleanAppId($appId); $config = \OC::$server->getConfig(); $config->setSystemValue('maintenance', true); try { $result = \OC\Installer::updateAppByOCSId($appId); $config->setSystemValue('maintenance', false); } catch (Exception $ex) { $config->setSystemValue('maintenance', false); OC_JSON::error(array("data" => array("message" => $ex->getMessage()))); return; } if ($result !== false) { OC_JSON::success(array('data' => array('appid' => $appId))); } else { $l = \OC::$server->getL10N('settings'); OC_JSON::error(array("data" => array("message" => $l->t("Couldn't update app.")))); }
/** * @param string $app * @return bool * @throws Exception if app is not compatible with this version of ownCloud * @throws Exception if no app-name was specified */ public static function installApp($app) { $l = \OC::$server->getL10N('core'); $config = \OC::$server->getConfig(); $ocsClient = new OCSClient(\OC::$server->getHTTPClientService(), $config, \OC::$server->getLogger()); $appData = $ocsClient->getApplication($app, \OCP\Util::getVersion()); // check if app is a shipped app or not. OCS apps have an integer as id, shipped apps use a string if (!is_numeric($app)) { $shippedVersion = self::getAppVersion($app); if ($appData && version_compare($shippedVersion, $appData['version'], '<')) { $app = self::downloadApp($app); } else { $app = Installer::installShippedApp($app); } } else { // Maybe the app is already installed - compare the version in this // case and use the local already installed one. // FIXME: This is a horrible hack. I feel sad. The god of code cleanness may forgive me. $internalAppId = self::getInternalAppIdByOcs($app); if ($internalAppId !== false) { if ($appData && version_compare(\OC_App::getAppVersion($internalAppId), $appData['version'], '<')) { $app = self::downloadApp($app); } else { self::enable($internalAppId); $app = $internalAppId; } } else { $app = self::downloadApp($app); } } if ($app !== false) { // check if the app is compatible with this version of ownCloud $info = self::getAppInfo($app); if (!is_array($info)) { throw new \Exception($l->t('App "%s" cannot be installed because appinfo file cannot be read.', [$info['name']])); } $version = \OCP\Util::getVersion(); if (!self::isAppCompatible($version, $info)) { throw new \Exception($l->t('App "%s" cannot be installed because it is not compatible with this version of ownCloud.', array($info['name']))); } // check for required dependencies $dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l); $missing = $dependencyAnalyzer->analyze($info); if (!empty($missing)) { $missingMsg = join(PHP_EOL, $missing); throw new \Exception($l->t('App "%s" cannot be installed because the following dependencies are not fulfilled: %s', array($info['name'], $missingMsg))); } $config->setAppValue($app, 'enabled', 'yes'); if (isset($appData['id'])) { $config->setAppValue($app, 'ocsid', $appData['id']); } \OC_Hook::emit('OC_App', 'post_enable', array('app' => $app)); } else { throw new \Exception($l->t("No app name specified")); } return $app; }
/** * Installs shipped apps * * This function installs all apps found in the 'apps' directory that should be enabled by default; * @param bool $softErrors When updating we ignore errors and simply log them, better to have a * working ownCloud at the end instead of an aborted update. * @return array Array of error messages (appid => Exception) */ public static function installShippedApps($softErrors = false) { $errors = []; foreach (\OC::$APPSROOTS as $app_dir) { if ($dir = opendir($app_dir['path'])) { while (false !== ($filename = readdir($dir))) { if (substr($filename, 0, 1) != '.' and is_dir($app_dir['path'] . "/{$filename}")) { if (file_exists($app_dir['path'] . "/{$filename}/appinfo/info.xml")) { if (!Installer::isInstalled($filename)) { $info = OC_App::getAppInfo($filename); $enabled = isset($info['default_enable']); if (($enabled || in_array($filename, \OC::$server->getAppManager()->getAlwaysEnabledApps())) && \OC::$server->getConfig()->getAppValue($filename, 'enabled') !== 'no') { if ($softErrors) { try { Installer::installShippedApp($filename); } catch (\Doctrine\DBAL\Exception\TableExistsException $e) { $errors[$filename] = $e; continue; } } else { Installer::installShippedApp($filename); } \OC::$server->getConfig()->setAppValue($filename, 'enabled', 'yes'); } } } } } closedir($dir); } } return $errors; }
/** * @param string $app * @return string|false */ protected function isUpdateAvailable($app) { return Installer::isUpdateAvailable($app); }