Beispiel #1
0
 public function run(IOutput $output)
 {
     $qb = $this->connection->getQueryBuilder();
     $qb->update('filecache')->set('etag', $qb->expr()->literal('xxx'))->where($qb->expr()->eq('etag', $qb->expr()->literal('')))->orWhere($qb->expr()->isNull('etag'));
     $result = $qb->execute();
     $output->info("ETags have been fixed for {$result} files/folders.");
 }
 /**
  * @inheritdoc
  */
 public function run(IOutput $output)
 {
     $output->startProgress();
     $output->advance(1, "Migrate states");
     $this->convStateMapper->migrate();
     $output->finishProgress();
 }
 /**
  * @param IOutput $output
  */
 public function run(IOutput $output)
 {
     $output->startProgress(2);
     $this->fixUserRootPermissions();
     $output->advance();
     $this->fixAvatarPermissions();
     $output->finishProgress();
 }
 public function run(\OCP\Migration\IOutput $out)
 {
     if ($this->warning) {
         $out->warning('Simulated warning');
     } else {
         $out->info('Simulated info');
     }
 }
 /**
  * {@inheritdoc}
  */
 public function run(IOutput $output)
 {
     $appsToUpdate = ['contacts' => ['old' => '166044', 'new' => '168708'], 'calendar' => ['old' => '166043', 'new' => '168707'], 'bookmarks' => ['old' => '166042', 'new' => '168710'], 'search_lucene' => ['old' => '166057', 'new' => '168709'], 'documents' => ['old' => '166045', 'new' => '168711']];
     foreach ($appsToUpdate as $appName => $ids) {
         if ($this->fixOcsId($appName, $ids['old'], $ids['new'])) {
             $output->info("Fixed invalid {$appName} OCS id");
         }
     }
 }
Beispiel #6
0
 public function run(IOutput $output)
 {
     if (!\OC_Template::isAssetPipelineEnabled()) {
         $output->info('Asset pipeline disabled -> nothing to do');
         return;
     }
     $assetDir = \OC::$server->getConfig()->getSystemValue('assetdirectory', \OC::$SERVERROOT) . '/assets';
     \OC_Helper::rmdirr($assetDir, false);
     $output->info('Asset cache cleared.');
 }
 /**
  * @inheritdoc
  */
 public function run(IOutput $output)
 {
     $output->startProgress();
     $this->userManager->callForAllUsers(function ($user) use($output) {
         /** @var IUser $user */
         $output->advance(1, $user->getDisplayName());
         $this->birthdayService->syncUser($user->getUID());
     });
     $output->finishProgress();
 }
 /**
  * @param IOutput $output
  */
 private function removeContactShares(IOutput $output)
 {
     $qb = $this->connection->getQueryBuilder();
     $qb->delete('share')->where($qb->expr()->eq('item_type', $qb->createNamedParameter('contact')));
     $qb->execute();
     $output->advance();
     $qb = $this->connection->getQueryBuilder();
     $qb->delete('share')->where($qb->expr()->eq('item_type', $qb->createNamedParameter('addressbook')));
     $qb->execute();
     $output->advance();
 }
Beispiel #9
0
 /**
  * Run repair step.
  * Must throw exception on error.
  *
  * @throws \Exception in case of failure
  */
 public function run(IOutput $output)
 {
     $tables = $this->oldDatabaseTables();
     $output->startProgress(count($tables));
     foreach ($this->oldDatabaseTables() as $tableName) {
         if ($this->connection->tableExists($tableName)) {
             $this->connection->dropTable($tableName);
         }
         $output->advance(1, "Drop old database table: {$tableName}");
     }
     $output->finishProgress();
 }
Beispiel #10
0
 /**
  * Fix mime types
  */
 public function run(IOutput $output)
 {
     if (!$this->connection->getDatabasePlatform() instanceof MySqlPlatform) {
         $output->info('Not a mysql database -> nothing to no');
         return;
     }
     $tables = $this->getAllNonUTF8BinTables($this->connection);
     foreach ($tables as $table) {
         $output->info("Change collation for {$table} ...");
         $query = $this->connection->prepare('ALTER TABLE `' . $table . '` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;');
         $query->execute();
     }
 }
Beispiel #11
0
 /**
  * Fix mime types
  */
 public function run(IOutput $output)
 {
     $connection = \OC::$server->getDatabaseConnection();
     if (!$connection->getDatabasePlatform() instanceof MySqlPlatform) {
         $output->info('Not a mysql database -> nothing to do');
         return;
     }
     $tables = $this->getAllMyIsamTables($connection);
     if (is_array($tables)) {
         foreach ($tables as $table) {
             $connection->exec("ALTER TABLE {$table} ENGINE=InnoDB;");
             $output->info("Fixed {$table}");
         }
     }
 }
 /**
  * @param IOutput $output
  */
 private function removeRootShares(IOutput $output)
 {
     $function = function (IUser $user) use($output) {
         $userFolder = $this->rootFolder->getUserFolder($user->getUID());
         $fileId = $userFolder->getId();
         $qb = $this->connection->getQueryBuilder();
         $qb->delete('share')->where($qb->expr()->eq('file_source', $qb->createNamedParameter($fileId)))->andWhere($qb->expr()->orX($qb->expr()->eq('item_type', $qb->expr()->literal('file')), $qb->expr()->eq('item_type', $qb->expr()->literal('folder'))));
         $qb->execute();
         $output->advance();
     };
     $userCount = $this->countUsers();
     $output->startProgress($userCount);
     $this->userManager->callForAllUsers($function);
     $output->finishProgress();
 }
 /**
  * Run repair step.
  * Must throw exception on error.
  *
  * @throws \Exception in case of failure
  */
 public function run(IOutput $output)
 {
     $deletedEntries = 0;
     $query = $this->connection->getQueryBuilder();
     $query->select('s1.id')->selectAlias('s1.share_with', 'user')->selectAlias('s2.share_with', 'group')->from('share', 's1')->where($query->expr()->isNotNull('s1.parent'))->andWhere($query->expr()->eq('s1.share_type', $query->expr()->literal(2)))->andWhere($query->expr()->isNotNull('s2.id'))->andWhere($query->expr()->eq('s2.share_type', $query->expr()->literal(Share::SHARE_TYPE_GROUP)))->leftJoin('s1', 'share', 's2', $query->expr()->eq('s1.parent', 's2.id'));
     $deleteQuery = $this->connection->getQueryBuilder();
     $deleteQuery->delete('share')->where($query->expr()->eq('id', $deleteQuery->createParameter('share')));
     $result = $query->execute();
     while ($row = $result->fetch()) {
         if (!$this->isMember($row['group'], $row['user'])) {
             $deletedEntries += $deleteQuery->setParameter('share', (int) $row['id'])->execute();
         }
     }
     $result->closeCursor();
     if ($deletedEntries) {
         $output->info('Removed ' . $deletedEntries . ' shares where user is not a member of the group anymore');
     }
 }
    /**
     * Fix duplicate entries in oc_lucene_status
     *
     * search_lucene prior to v0.5.0 did not have a primary key on the lucene_status table. Newer versions do, which
     * causes the migration check to fail because it tries to insert duplicate rows into the new schema.
     *
     * FIXME Currently, apps don't have a way of repairing anything before the migration check:
     * @link https://github.com/owncloud/core/issues/10980
     *
     * As a result this repair step needs to live in the core repo, although it belongs into search_lucene:
     * @link https://github.com/owncloud/core/issues/10205#issuecomment-54957557
     *
     * It will completely remove any rows that make a file id have more than one status:
     *  fileid | status                       fileid | status
     * --------+--------     will become     --------+--------
     *     2   |   E                             3   |   E
     *     2   |   I
     *     3   |   E
     *
     * search_lucene will then reindex the fileids without a status when the next indexing job is executed
     */
    public function run(IOutput $out)
    {
        $connection = \OC::$server->getDatabaseConnection();
        if ($connection->tableExists('lucene_status')) {
            $out->info('removing duplicate entries from lucene_status');
            $query = $connection->prepare('
				DELETE FROM `*PREFIX*lucene_status`
				WHERE `fileid` IN (
					SELECT `fileid`
					FROM (
						SELECT `fileid`
						FROM `*PREFIX*lucene_status`
						GROUP BY `fileid`
						HAVING count(`fileid`) > 1
					) AS `mysqlerr1093hack`
				)');
            $query->execute();
        } else {
            $out->info('lucene_status table does not exist -> nothing to do');
        }
    }
 /**
  * Remove shares where the parent share does not exist anymore
  */
 private function removeSharesNonExistingParent(IOutput $out)
 {
     $deletedEntries = 0;
     $query = $this->connection->getQueryBuilder();
     $query->select('s1.parent')->from('share', 's1')->where($query->expr()->isNotNull('s1.parent'))->andWhere($query->expr()->isNull('s2.id'))->leftJoin('s1', 'share', 's2', $query->expr()->eq('s1.parent', 's2.id'))->groupBy('s1.parent')->setMaxResults(self::CHUNK_SIZE);
     $deleteQuery = $this->connection->getQueryBuilder();
     $deleteQuery->delete('share')->where($deleteQuery->expr()->eq('parent', $deleteQuery->createParameter('parent')));
     $deletedInLastChunk = self::CHUNK_SIZE;
     while ($deletedInLastChunk === self::CHUNK_SIZE) {
         $deletedInLastChunk = 0;
         $result = $query->execute();
         while ($row = $result->fetch()) {
             $deletedInLastChunk++;
             $deletedEntries += $deleteQuery->setParameter('parent', (int) $row['parent'])->execute();
         }
         $result->closeCursor();
     }
     if ($deletedEntries) {
         $out->info('Removed ' . $deletedEntries . ' shares where the parent did not exist');
     }
 }
 /**
  * Converts legacy home storage ids in the format
  * "local::/data/dir/path/userid/" to the new format "home::userid"
  */
 public function run(IOutput $out)
 {
     // only run once
     if ($this->config->getAppValue('core', 'repairlegacystoragesdone') === 'yes') {
         return;
     }
     $dataDir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
     $dataDir = rtrim($dataDir, '/') . '/';
     $dataDirId = 'local::' . $dataDir;
     $count = 0;
     $hasWarnings = false;
     $this->connection->beginTransaction();
     // note: not doing a direct UPDATE with the REPLACE function
     // because regexp search/extract is needed and it is not guaranteed
     // to work on all database types
     $sql = 'SELECT `id`, `numeric_id` FROM `*PREFIX*storages`' . ' WHERE `id` LIKE ?' . ' ORDER BY `id`';
     $result = $this->connection->executeQuery($sql, array($dataDirId . '%'));
     while ($row = $result->fetch()) {
         $currentId = $row['id'];
         // one entry is the datadir itself
         if ($currentId === $dataDirId) {
             continue;
         }
         try {
             if ($this->fixLegacyStorage($currentId, (int) $row['numeric_id'])) {
                 $count++;
             }
         } catch (RepairException $e) {
             $hasWarnings = true;
             $out->warning('Could not repair legacy storage ' . $currentId . ' automatically.');
         }
     }
     // check for md5 ids, not in the format "prefix::"
     $sql = 'SELECT COUNT(*) AS "c" FROM `*PREFIX*storages`' . ' WHERE `id` NOT LIKE \'%::%\'';
     $result = $this->connection->executeQuery($sql);
     $row = $result->fetch();
     // find at least one to make sure it's worth
     // querying the user list
     if ((int) $row['c'] > 0) {
         $userManager = \OC::$server->getUserManager();
         // use chunks to avoid caching too many users in memory
         $limit = 30;
         $offset = 0;
         do {
             // query the next page of users
             $results = $userManager->search('', $limit, $offset);
             $storageIds = array();
             foreach ($results as $uid => $userObject) {
                 $storageId = $dataDirId . $uid . '/';
                 if (strlen($storageId) <= 64) {
                     // skip short storage ids as they were handled in the previous section
                     continue;
                 }
                 $storageIds[$uid] = $storageId;
             }
             if (count($storageIds) > 0) {
                 // update the storages of these users
                 foreach ($storageIds as $uid => $storageId) {
                     $numericId = Storage::getNumericStorageId($storageId);
                     try {
                         if (!is_null($numericId) && $this->fixLegacyStorage($storageId, (int) $numericId)) {
                             $count++;
                         }
                     } catch (RepairException $e) {
                         $hasWarnings = true;
                         $out->warning('Could not repair legacy storage ' . $storageId . ' automatically.');
                     }
                 }
             }
             $offset += $limit;
         } while (count($results) >= $limit);
     }
     $out->info('Updated ' . $count . ' legacy home storage ids');
     $this->connection->commit();
     if ($hasWarnings) {
         $out->warning('Some legacy storages could not be repaired. Please manually fix them then re-run ./occ maintenance:repair');
     } else {
         // if all were done, no need to redo the repair during next upgrade
         $this->config->setAppValue('core', 'repairlegacystoragesdone', 'yes');
     }
 }
 /**
  * Removes all entries with the key "{DAV:}getetag" from the table properties
  */
 public function run(IOutput $out)
 {
     $sql = 'DELETE FROM `*PREFIX*properties`' . ' WHERE `propertyname` = ?';
     $deletedRows = $this->connection->executeUpdate($sql, ['{DAV:}getetag']);
     $out->info('Removed ' . $deletedRows . ' unneeded "{DAV:}getetag" entries from properties table.');
 }
 /**
  * Fix mime types
  */
 public function run(IOutput $out)
 {
     $ocVersionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0');
     // NOTE TO DEVELOPERS: when adding new mime types, please make sure to
     // add a version comparison to avoid doing it every time
     // only update mime types if necessary as it can be expensive
     if (version_compare($ocVersionFromBeforeUpdate, '8.2.0', '<')) {
         if ($this->fixOfficeMimeTypes()) {
             $out->info('Fixed office mime types');
         }
         if ($this->fixApkMimeType()) {
             $out->info('Fixed APK mime type');
         }
         if ($this->fixFontsMimeTypes()) {
             $out->info('Fixed fonts mime types');
         }
         if ($this->fixPostscriptMimeType()) {
             $out->info('Fixed Postscript mime types');
         }
         if ($this->introduceRawMimeType()) {
             $out->info('Fixed Raw mime types');
         }
         if ($this->introduce3dImagesMimeType()) {
             $out->info('Fixed 3D images mime types');
         }
         if ($this->introduceConfMimeType()) {
             $out->info('Fixed Conf/cnf mime types');
         }
         if ($this->introduceYamlMimeType()) {
             $out->info('Fixed Yaml/Yml mime types');
         }
     }
     // Mimetype updates from #19272
     if (version_compare($ocVersionFromBeforeUpdate, '8.2.0.8', '<')) {
         if ($this->introduceJavaMimeType()) {
             $out->info('Fixed java/class mime types');
         }
         if ($this->introduceHppMimeType()) {
             $out->info('Fixed hpp mime type');
         }
         if ($this->introduceRssMimeType()) {
             $out->info('Fixed rss mime type');
         }
         if ($this->introduceRtfMimeType()) {
             $out->info('Fixed rtf mime type');
         }
     }
     if (version_compare($ocVersionFromBeforeUpdate, '9.0.0.10', '<')) {
         if ($this->introduceRichDocumentsMimeTypes()) {
             $out->info('Fixed richdocuments additional office mime types');
         }
     }
 }
Beispiel #19
0
 /**
  * Deletes all entries from $deleteTable that do not have a matching entry in $sourceTable
  *
  * A query joins $deleteTable.$deleteId = $sourceTable.$sourceId and checks
  * whether $sourceNullColumn is null. If it is null, the entry in $deleteTable
  * is being deleted.
  *
  * @param string $repairInfo
  * @param string $deleteTable
  * @param string $deleteId
  * @param string $sourceTable
  * @param string $sourceId
  * @param string $sourceNullColumn	If this column is null in the source table,
  * 								the entry is deleted in the $deleteTable
  */
 protected function deleteOrphanEntries(IOutput $output, $repairInfo, $deleteTable, $deleteId, $sourceTable, $sourceId, $sourceNullColumn)
 {
     $qb = $this->connection->getQueryBuilder();
     $qb->select('d.' . $deleteId)->from($deleteTable, 'd')->leftJoin('d', $sourceTable, 's', $qb->expr()->eq('d.' . $deleteId, ' s.' . $sourceId))->where($qb->expr()->eq('d.type', $qb->expr()->literal('files')))->andWhere($qb->expr()->isNull('s.' . $sourceNullColumn));
     $result = $qb->execute();
     $orphanItems = array();
     while ($row = $result->fetch()) {
         $orphanItems[] = (int) $row[$deleteId];
     }
     if (!empty($orphanItems)) {
         $orphanItemsBatch = array_chunk($orphanItems, 200);
         foreach ($orphanItemsBatch as $items) {
             $qb->delete($deleteTable)->where($qb->expr()->eq('type', $qb->expr()->literal('files')))->andWhere($qb->expr()->in($deleteId, $qb->createParameter('ids')));
             $qb->setParameter('ids', $items, IQueryBuilder::PARAM_INT_ARRAY);
             $qb->execute();
         }
     }
     if ($repairInfo) {
         $output->info(sprintf($repairInfo, sizeof($orphanItems)));
     }
 }