]> source.dussan.org Git - nextcloud-server.git/commitdiff
Move lib/repair to lib/private/repair
authorMorris Jobke <hey@morrisjobke.de>
Thu, 7 Jan 2016 08:14:35 +0000 (09:14 +0100)
committerMorris Jobke <hey@morrisjobke.de>
Thu, 7 Jan 2016 08:14:35 +0000 (09:14 +0100)
36 files changed:
lib/autoloader.php
lib/private/repair/assetcache.php [new file with mode: 0644]
lib/private/repair/cleantags.php [new file with mode: 0644]
lib/private/repair/collation.php [new file with mode: 0644]
lib/private/repair/dropoldjobs.php [new file with mode: 0644]
lib/private/repair/dropoldtables.php [new file with mode: 0644]
lib/private/repair/filletags.php [new file with mode: 0644]
lib/private/repair/innodb.php [new file with mode: 0644]
lib/private/repair/oldgroupmembershipshares.php [new file with mode: 0644]
lib/private/repair/preview.php [new file with mode: 0644]
lib/private/repair/removegetetagentries.php [new file with mode: 0644]
lib/private/repair/repairinvalidshares.php [new file with mode: 0644]
lib/private/repair/repairlegacystorages.php [new file with mode: 0644]
lib/private/repair/repairmimetypes.php [new file with mode: 0644]
lib/private/repair/searchlucenetables.php [new file with mode: 0644]
lib/private/repair/sqliteautoincrement.php [new file with mode: 0644]
lib/private/repair/updatecertificatestore.php [new file with mode: 0644]
lib/private/repair/updateoutdatedocsids.php [new file with mode: 0644]
lib/repair/assetcache.php [deleted file]
lib/repair/cleantags.php [deleted file]
lib/repair/collation.php [deleted file]
lib/repair/dropoldjobs.php [deleted file]
lib/repair/dropoldtables.php [deleted file]
lib/repair/filletags.php [deleted file]
lib/repair/innodb.php [deleted file]
lib/repair/oldgroupmembershipshares.php [deleted file]
lib/repair/preview.php [deleted file]
lib/repair/removegetetagentries.php [deleted file]
lib/repair/repairinvalidshares.php [deleted file]
lib/repair/repairlegacystorages.php [deleted file]
lib/repair/repairmimetypes.php [deleted file]
lib/repair/searchlucenetables.php [deleted file]
lib/repair/sqliteautoincrement.php [deleted file]
lib/repair/updatecertificatestore.php [deleted file]
lib/repair/updateoutdatedocsids.php [deleted file]
tests/lib/autoloader.php

index f0fbd9e9f27cff3bdd7c6ae02d8738aeb0e6cd35..10cd5a8016a2c087b190ec638e92ed888848c2e4 100644 (file)
@@ -112,9 +112,6 @@ class Autoloader {
                                        $paths[] = \OC::$SERVERROOT . '/core/' . strtolower(str_replace('\\', '/', $split[2])) . '.php';
                                } else if ($split[1] === 'settings') {
                                        $paths[] = \OC::$SERVERROOT . '/settings/' . strtolower(str_replace('\\', '/', $split[2])) . '.php';
-                               } else if ($split[1] === 'repair') {
-                                       $paths[] = \OC::$SERVERROOT . '/lib/repair/' . strtolower(str_replace('\\', '/', $split[2])) . '.php';
-
                                } else {
                                        $paths[] = \OC::$SERVERROOT . '/lib/private/' . $split[1] . '/' . strtolower(str_replace('\\', '/', $split[2])) . '.php';
                                }
diff --git a/lib/private/repair/assetcache.php b/lib/private/repair/assetcache.php
new file mode 100644 (file)
index 0000000..c46aa63
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/**
+ * @author Adam Williamson <awilliam@redhat.com>
+ * @author Morris Jobke <hey@morrisjobke.de>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+use Doctrine\DBAL\Platforms\MySqlPlatform;
+use OC\Hooks\BasicEmitter;
+
+class AssetCache extends BasicEmitter implements \OC\RepairStep {
+
+       public function getName() {
+               return 'Clear asset cache after upgrade';
+       }
+
+       public function run() {
+               if (!\OC_Template::isAssetPipelineEnabled()) {
+                       $this->emit('\OC\Repair', 'info', array('Asset pipeline disabled -> nothing to do'));
+                       return;
+               }
+               $assetDir = \OC::$server->getConfig()->getSystemValue('assetdirectory', \OC::$SERVERROOT) . '/assets';
+               \OC_Helper::rmdirr($assetDir, false);
+               $this->emit('\OC\Repair', 'info', array('Asset cache cleared.'));
+       }
+}
+
diff --git a/lib/private/repair/cleantags.php b/lib/private/repair/cleantags.php
new file mode 100644 (file)
index 0000000..d16a49f
--- /dev/null
@@ -0,0 +1,146 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ * @author Morris Jobke <hey@morrisjobke.de>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+use OC\Hooks\BasicEmitter;
+use OC\RepairStep;
+use OCP\IDBConnection;
+
+/**
+ * Class RepairConfig
+ *
+ * @package OC\Repair
+ */
+class CleanTags extends BasicEmitter implements RepairStep {
+
+       /** @var IDBConnection */
+       protected $connection;
+
+       /**
+        * @param IDBConnection $connection
+        */
+       public function __construct(IDBConnection $connection) {
+               $this->connection = $connection;
+       }
+
+       /**
+        * @return string
+        */
+       public function getName() {
+               return 'Clean tags and favorites';
+       }
+
+       /**
+        * Updates the configuration after running an update
+        */
+       public function run() {
+               $this->deleteOrphanFileEntries();
+               $this->deleteOrphanTagEntries();
+               $this->deleteOrphanCategoryEntries();
+       }
+
+       /**
+        * Delete tag entries for deleted files
+        */
+       protected function deleteOrphanFileEntries() {
+               $this->deleteOrphanEntries(
+                       '%d tags for delete files have been removed.',
+                       'vcategory_to_object', 'objid',
+                       'filecache', 'fileid', 'path_hash'
+               );
+       }
+
+       /**
+        * Delete tag entries for deleted tags
+        */
+       protected function deleteOrphanTagEntries() {
+               $this->deleteOrphanEntries(
+                       '%d tag entries for deleted tags have been removed.',
+                       'vcategory_to_object', 'categoryid',
+                       'vcategory', 'id', 'uid'
+               );
+       }
+
+       /**
+        * Delete tags that have no entries
+        */
+       protected function deleteOrphanCategoryEntries() {
+               $this->deleteOrphanEntries(
+                       '%d tags with no entries have been removed.',
+                       'vcategory', 'id',
+                       'vcategory_to_object', 'categoryid', 'type'
+               );
+       }
+
+       /**
+        * 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($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, \Doctrine\DBAL\Connection::PARAM_INT_ARRAY);
+                               $qb->execute();
+                       }
+               }
+
+               if ($repairInfo) {
+                       $this->emit('\OC\Repair', 'info', array(sprintf($repairInfo, sizeof($orphanItems))));
+               }
+       }
+}
diff --git a/lib/private/repair/collation.php b/lib/private/repair/collation.php
new file mode 100644 (file)
index 0000000..7eb14f0
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/**
+ * @author Morris Jobke <hey@morrisjobke.de>
+ * @author Robin Appelman <icewind@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+use Doctrine\DBAL\Platforms\MySqlPlatform;
+use OC\Hooks\BasicEmitter;
+
+class Collation extends BasicEmitter implements \OC\RepairStep {
+       /**
+        * @var \OCP\IConfig
+        */
+       protected $config;
+
+       /**
+        * @var \OC\DB\Connection
+        */
+       protected $connection;
+
+       /**
+        * @param \OCP\IConfig $config
+        * @param \OC\DB\Connection $connection
+        */
+       public function __construct($config, $connection) {
+               $this->connection = $connection;
+               $this->config = $config;
+       }
+
+       public function getName() {
+               return 'Repair MySQL collation';
+       }
+
+       /**
+        * Fix mime types
+        */
+       public function run() {
+               if (!$this->connection->getDatabasePlatform() instanceof MySqlPlatform) {
+                       $this->emit('\OC\Repair', 'info', array('Not a mysql database -> nothing to no'));
+                       return;
+               }
+
+               $tables = $this->getAllNonUTF8BinTables($this->connection);
+               foreach ($tables as $table) {
+                       $this->emit('\OC\Repair', 'info', array("Change collation for $table ..."));
+                       $query = $this->connection->prepare('ALTER TABLE `' . $table . '` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;');
+                       $query->execute();
+               }
+       }
+
+       /**
+        * @param \Doctrine\DBAL\Connection $connection
+        * @return string[]
+        */
+       protected function getAllNonUTF8BinTables($connection) {
+               $dbName = $this->config->getSystemValue("dbname");
+               $rows = $connection->fetchAll(
+                       "SELECT DISTINCT(TABLE_NAME) AS `table`" .
+                       "       FROM INFORMATION_SCHEMA . COLUMNS" .
+                       "       WHERE TABLE_SCHEMA = ?" .
+                       "       AND (COLLATION_NAME <> 'utf8_bin' OR CHARACTER_SET_NAME <> 'utf8')" .
+                       "       AND TABLE_NAME LIKE \"*PREFIX*%\"",
+                       array($dbName)
+               );
+               $result = array();
+               foreach ($rows as $row) {
+                       $result[] = $row['table'];
+               }
+               return $result;
+       }
+}
+
diff --git a/lib/private/repair/dropoldjobs.php b/lib/private/repair/dropoldjobs.php
new file mode 100644 (file)
index 0000000..89d7f96
--- /dev/null
@@ -0,0 +1,78 @@
+<?php
+/**
+ * @author Arthur Schiwon <blizzz@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+use OC\Hooks\BasicEmitter;
+use OC\RepairStep;
+use OCP\BackgroundJob\IJobList;
+
+class DropOldJobs extends BasicEmitter implements RepairStep {
+
+       /** @var IJobList */
+       protected $jobList;
+
+       /**
+        * @param IJobList $jobList
+        */
+       public function __construct(IJobList $jobList) {
+               $this->jobList = $jobList;
+       }
+
+       /**
+        * Returns the step's name
+        *
+        * @return string
+        */
+       public function getName() {
+               return 'Drop old background jobs';
+       }
+
+       /**
+        * Run repair step.
+        * Must throw exception on error.
+        *
+        * @throws \Exception in case of failure
+        */
+       public function run() {
+               $oldJobs = $this->oldJobs();
+               foreach($oldJobs as $job) {
+                       if($this->jobList->has($job['class'], $job['arguments'])) {
+                               $this->jobList->remove($job['class'], $job['arguments']);
+                       }
+               }
+       }
+
+       /**
+        * returns a list of old jobs as an associative array with keys 'class' and
+        * 'arguments'.
+        *
+        * @return array
+        */
+       public function oldJobs() {
+               return [
+                       ['class' => 'OC_Cache_FileGlobalGC', 'arguments' => null],
+                       ['class' => 'OC\Cache\FileGlobalGC', 'arguments' => null],
+               ];
+       }
+
+
+}
diff --git a/lib/private/repair/dropoldtables.php b/lib/private/repair/dropoldtables.php
new file mode 100644 (file)
index 0000000..2d7fc83
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+
+use OC\Hooks\BasicEmitter;
+use OC\RepairStep;
+use OCP\IDBConnection;
+
+class DropOldTables extends BasicEmitter implements RepairStep {
+
+       /** @var IDBConnection */
+       protected $connection;
+
+       /**
+        * @param IDBConnection $connection
+        */
+       public function __construct(IDBConnection $connection) {
+               $this->connection = $connection;
+       }
+
+       /**
+        * Returns the step's name
+        *
+        * @return string
+        */
+       public function getName() {
+               return 'Drop old database tables';
+       }
+
+       /**
+        * Run repair step.
+        * Must throw exception on error.
+        *
+        * @throws \Exception in case of failure
+        */
+       public function run() {
+               foreach ($this->oldDatabaseTables() as $tableName) {
+                       if ($this->connection->tableExists($tableName)){
+                               $this->emit('\OC\Repair', 'info', [
+                                       sprintf('Table %s has been deleted', $tableName)
+                               ]);
+                               $this->connection->dropTable($tableName);
+                       }
+               }
+       }
+
+       /**
+        * Returns a list of outdated tables which are not used anymore
+        * @return array
+        */
+       protected function oldDatabaseTables() {
+               return [
+                       'calendar_calendars',
+                       'calendar_objects',
+                       'calendar_share_calendar',
+                       'calendar_share_event',
+                       'file_map',
+                       'foldersize',
+                       'fscache',
+                       'gallery_sharing',
+                       'locks',
+                       'log',
+                       'media_albums',
+                       'media_artists',
+                       'media_sessions',
+                       'media_songs',
+                       'media_users',
+                       'permissions',
+                       'pictures_images_cache',
+                       'principalgroups',
+                       'principals',
+                       'queuedtasks',
+                       'sharing',
+               ];
+       }
+}
diff --git a/lib/private/repair/filletags.php b/lib/private/repair/filletags.php
new file mode 100644 (file)
index 0000000..8cfc4a7
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ * @author Morris Jobke <hey@morrisjobke.de>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+use OC\Hooks\BasicEmitter;
+
+class FillETags extends BasicEmitter implements \OC\RepairStep {
+
+       /** @var \OCP\IDBConnection */
+       protected $connection;
+
+       /**
+        * @param \OCP\IDBConnection $connection
+        */
+       public function __construct($connection) {
+               $this->connection = $connection;
+       }
+
+       public function getName() {
+               return 'Generate ETags for file where no ETag is present.';
+       }
+
+       public function run() {
+               $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();
+               $this->emit('\OC\Repair', 'info', array("ETags have been fixed for $result files/folders."));
+       }
+}
+
diff --git a/lib/private/repair/innodb.php b/lib/private/repair/innodb.php
new file mode 100644 (file)
index 0000000..ab94c79
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+/**
+ * @author Jörn Friedrich Dreyer <jfd@butonic.de>
+ * @author Morris Jobke <hey@morrisjobke.de>
+ * @author Robin Appelman <icewind@owncloud.com>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+use Doctrine\DBAL\Platforms\MySqlPlatform;
+use OC\Hooks\BasicEmitter;
+
+class InnoDB extends BasicEmitter implements \OC\RepairStep {
+
+       public function getName() {
+               return 'Repair MySQL database engine';
+       }
+
+       /**
+        * Fix mime types
+        */
+       public function run() {
+               $connection = \OC_DB::getConnection();
+               if (!$connection->getDatabasePlatform() instanceof MySqlPlatform) {
+                       $this->emit('\OC\Repair', 'info', array('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;");
+                               $this->emit('\OC\Repair', 'info', array("Fixed $table"));
+                       }
+               }
+       }
+
+       /**
+        * @param \Doctrine\DBAL\Connection $connection
+        * @return string[]
+        */
+       private function getAllMyIsamTables($connection) {
+               $dbName = \OC::$server->getConfig()->getSystemValue("dbname");
+               $result = $connection->fetchArray(
+                       "SELECT table_name FROM information_schema.tables WHERE table_schema = ? AND engine = 'MyISAM' AND TABLE_NAME LIKE \"*PREFIX*%\"",
+                       array($dbName)
+               );
+
+               return $result;
+       }
+}
+
diff --git a/lib/private/repair/oldgroupmembershipshares.php b/lib/private/repair/oldgroupmembershipshares.php
new file mode 100644 (file)
index 0000000..2d701ac
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+
+use OC\Hooks\BasicEmitter;
+use OC\RepairStep;
+use OCP\IDBConnection;
+use OCP\IGroupManager;
+use OCP\Share;
+
+class OldGroupMembershipShares extends BasicEmitter implements RepairStep {
+
+       /** @var \OCP\IDBConnection */
+       protected $connection;
+
+       /** @var \OCP\IGroupManager */
+       protected $groupManager;
+
+       /**
+        * @var array [gid => [uid => (bool)]]
+        */
+       protected $memberships;
+
+       /**
+        * @param IDBConnection $connection
+        * @param IGroupManager $groupManager
+        */
+       public function __construct(IDBConnection $connection, IGroupManager $groupManager) {
+               $this->connection = $connection;
+               $this->groupManager = $groupManager;
+       }
+
+       /**
+        * Returns the step's name
+        *
+        * @return string
+        */
+       public function getName() {
+               return 'Remove shares of old group memberships';
+       }
+
+       /**
+        * Run repair step.
+        * Must throw exception on error.
+        *
+        * @throws \Exception in case of failure
+        */
+       public function run() {
+               $deletedEntries = 0;
+
+               $query = $this->connection->getQueryBuilder();
+               $query->select(['s1.id', $query->createFunction('s1.`share_with` AS `user`'), $query->createFunction('s2.`share_with` AS `group`')])
+                       ->from('share', 's1')
+                       ->where($query->expr()->isNotNull('s1.parent'))
+                               // \OC\Share\Constant::$shareTypeGroupUserUnique === 2
+                               ->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) {
+                       $this->emit('\OC\Repair', 'info', array('Removed ' . $deletedEntries . ' shares where user is not a member of the group anymore'));
+               }
+       }
+
+       /**
+        * @param string $gid
+        * @param string $uid
+        * @return bool
+        */
+       protected function isMember($gid, $uid) {
+               if (isset($this->memberships[$gid][$uid])) {
+                       return $this->memberships[$gid][$uid];
+               }
+
+               $isMember = $this->groupManager->isInGroup($uid, $gid);
+               if (!isset($this->memberships[$gid])) {
+                       $this->memberships[$gid] = [];
+               }
+               $this->memberships[$gid][$uid] = $isMember;
+
+               return $isMember;
+       }
+}
diff --git a/lib/private/repair/preview.php b/lib/private/repair/preview.php
new file mode 100644 (file)
index 0000000..2284da9
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/**
+ * @author Georg Ehrke <georg@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+namespace OC\Repair;
+
+use OC\Files\View;
+use OC\Hooks\BasicEmitter;
+
+class Preview extends BasicEmitter implements \OC\RepairStep {
+
+       public function getName() {
+               return 'Cleaning-up broken previews';
+       }
+
+       public function run() {
+               $view = new View('/');
+               $children = $view->getDirectoryContent('/');
+
+               foreach ($children as $child) {
+                       if ($view->is_dir($child->getPath())) {
+                               $thumbnailsFolder = $child->getPath() . '/thumbnails';
+                               if ($view->is_dir($thumbnailsFolder)) {
+                                       $view->rmdir($thumbnailsFolder);
+                               }
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/lib/private/repair/removegetetagentries.php b/lib/private/repair/removegetetagentries.php
new file mode 100644 (file)
index 0000000..4004076
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/**
+ * @author Morris Jobke <hey@morrisjobke.de>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+use OC\Hooks\BasicEmitter;
+use OCP\IDBConnection;
+
+class RemoveGetETagEntries extends BasicEmitter {
+
+       /**
+        * @var IDBConnection
+        */
+       protected $connection;
+
+       /**
+        * @param IDBConnection $connection
+        */
+       public function __construct(IDBConnection $connection) {
+               $this->connection = $connection;
+       }
+
+       public function getName() {
+               return 'Remove getetag entries in properties table';
+       }
+
+       /**
+        * Removes all entries with the key "{DAV:}getetag" from the table properties
+        */
+       public function run() {
+               $sql = 'DELETE FROM `*PREFIX*properties`'
+                       . ' WHERE `propertyname` = ?';
+               $deletedRows = $this->connection->executeUpdate($sql, ['{DAV:}getetag']);
+
+               $this->emit(
+                       '\OC\Repair',
+                       'info',
+                       ['Removed ' . $deletedRows . ' unneeded "{DAV:}getetag" entries from properties table.']
+               );
+       }
+}
diff --git a/lib/private/repair/repairinvalidshares.php b/lib/private/repair/repairinvalidshares.php
new file mode 100644 (file)
index 0000000..5a4cb44
--- /dev/null
@@ -0,0 +1,112 @@
+<?php
+/**
+ * @author Morris Jobke <hey@morrisjobke.de>
+ * @author Vincent Petry <pvince81@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+use OC\Hooks\BasicEmitter;
+
+/**
+ * Repairs shares with invalid data
+ */
+class RepairInvalidShares extends BasicEmitter implements \OC\RepairStep {
+
+       /**
+        * @var \OCP\IConfig
+        */
+       protected $config;
+
+       /**
+        * @var \OCP\IDBConnection
+        */
+       protected $connection;
+
+       /**
+        * @param \OCP\IConfig $config
+        * @param \OCP\IDBConnection $connection
+        */
+       public function __construct($config, $connection) {
+               $this->connection = $connection;
+               $this->config = $config;
+       }
+
+       public function getName() {
+               return 'Repair invalid shares';
+       }
+
+       /**
+        * Past bugs would make it possible to set an expiration date on user shares even
+        * though it is not supported. This functions removes the expiration date from such entries.
+        */
+       private function removeExpirationDateFromNonLinkShares() {
+               $builder = $this->connection->getQueryBuilder();
+               $builder
+                       ->update('share')
+                       ->set('expiration', 'null')
+                       ->where($builder->expr()->isNotNull('expiration'))
+                       ->andWhere($builder->expr()->neq('share_type', $builder->expr()->literal(\OC\Share\Constants::SHARE_TYPE_LINK)));
+
+               $updatedEntries = $builder->execute();
+               if ($updatedEntries > 0) {
+                       $this->emit('\OC\Repair', 'info', array('Removed invalid expiration date from ' . $updatedEntries . ' shares'));
+               }
+       }
+
+       /**
+        * Remove shares where the parent share does not exist anymore
+        */
+       private function removeSharesNonExistingParent() {
+               $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');
+
+               $deleteQuery = $this->connection->getQueryBuilder();
+               $deleteQuery->delete('share')
+                       ->where($query->expr()->eq('parent', $deleteQuery->createParameter('parent')));
+
+               $result = $query->execute();
+               while ($row = $result->fetch()) {
+                       $deletedEntries += $deleteQuery->setParameter('parent', (int) $row['parent'])
+                               ->execute();
+               }
+               $result->closeCursor();
+
+               if ($deletedEntries) {
+                       $this->emit('\OC\Repair', 'info', array('Removed ' . $deletedEntries . ' shares where the parent did not exist'));
+               }
+       }
+
+       public function run() {
+               $ocVersionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0');
+               if (version_compare($ocVersionFromBeforeUpdate, '8.2.0.7', '<')) {
+                       // this situation was only possible before 8.2
+                       $this->removeExpirationDateFromNonLinkShares();
+               }
+
+               $this->removeSharesNonExistingParent();
+       }
+}
diff --git a/lib/private/repair/repairlegacystorages.php b/lib/private/repair/repairlegacystorages.php
new file mode 100644 (file)
index 0000000..5ba452c
--- /dev/null
@@ -0,0 +1,263 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ * @author Morris Jobke <hey@morrisjobke.de>
+ * @author Vincent Petry <pvince81@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+use OC\Files\Cache\Storage;
+use OC\Hooks\BasicEmitter;
+use OC\RepairException;
+
+class RepairLegacyStorages extends BasicEmitter {
+       /**
+        * @var \OCP\IConfig
+        */
+       protected $config;
+
+       /**
+        * @var \OCP\IDBConnection
+        */
+       protected $connection;
+
+       protected $findStorageInCacheStatement;
+       protected $renameStorageStatement;
+
+       /**
+        * @param \OCP\IConfig $config
+        * @param \OCP\IDBConnection $connection
+        */
+       public function __construct($config, $connection) {
+               $this->connection = $connection;
+               $this->config = $config;
+
+               $this->findStorageInCacheStatement = $this->connection->prepare(
+                       'SELECT DISTINCT `storage` FROM `*PREFIX*filecache`'
+                       . ' WHERE `storage` in (?, ?)'
+               );
+               $this->renameStorageStatement = $this->connection->prepare(
+                       'UPDATE `*PREFIX*storages`'
+                       . ' SET `id` = ?'
+                       . ' WHERE `id` = ?'
+               );
+       }
+
+       public function getName() {
+               return 'Repair legacy storages';
+       }
+
+       /**
+        * Extracts the user id from a legacy storage id
+        *
+        * @param string $storageId legacy storage id in the
+        * format "local::/path/to/datadir/userid"
+        * @return string user id extracted from the storage id
+        */
+       private function extractUserId($storageId) {
+               $storageId = rtrim($storageId, '/');
+               $pos = strrpos($storageId, '/');
+               return substr($storageId, $pos + 1);
+       }
+
+       /**
+        * Fix the given legacy storage by renaming the old id
+        * to the new id. If the new id already exists, whichever
+        * storage that has data in the file cache will be used.
+        * If both have data, nothing will be done and false is
+        * returned.
+        *
+        * @param string $oldId old storage id
+        * @param int $oldNumericId old storage numeric id
+        * @param string $userId
+        * @return bool true if fixed, false otherwise
+        * @throws RepairException
+        */
+       private function fixLegacyStorage($oldId, $oldNumericId, $userId = null) {
+               // check whether the new storage already exists
+               if (is_null($userId)) {
+                       $userId = $this->extractUserId($oldId);
+               }
+               $newId = 'home::' . $userId;
+
+               // check if target id already exists
+               $newNumericId = Storage::getNumericStorageId($newId);
+               if (!is_null($newNumericId)) {
+                       $newNumericId = (int)$newNumericId;
+                       // try and resolve the conflict
+                       // check which one of "local::" or "home::" needs to be kept
+                       $this->findStorageInCacheStatement->execute(array($oldNumericId, $newNumericId));
+                       $row1 = $this->findStorageInCacheStatement->fetch();
+                       $row2 = $this->findStorageInCacheStatement->fetch();
+                       $this->findStorageInCacheStatement->closeCursor();
+                       if ($row2 !== false) {
+                               // two results means both storages have data, not auto-fixable
+                               throw new RepairException(
+                                       'Could not automatically fix legacy storage '
+                                       . '"' . $oldId . '" => "' . $newId . '"'
+                                       . ' because they both have data.'
+                               );
+                       }
+                       if ($row1 === false || (int)$row1['storage'] === $oldNumericId) {
+                               // old storage has data, then delete the empty new id
+                               $toDelete = $newId;
+                       } else if ((int)$row1['storage'] === $newNumericId) {
+                               // new storage has data, then delete the empty old id
+                               $toDelete = $oldId;
+                       } else {
+                               // unknown case, do not continue
+                               return false;
+                       }
+
+                       // delete storage including file cache
+                       Storage::remove($toDelete);
+
+                       // if we deleted the old id, the new id will be used
+                       // automatically
+                       if ($toDelete === $oldId) {
+                               // nothing more to do
+                               return true;
+                       }
+               }
+
+               // rename old id to new id
+               $newId = Storage::adjustStorageId($newId);
+               $oldId = Storage::adjustStorageId($oldId);
+               $rowCount = $this->renameStorageStatement->execute(array($newId, $oldId));
+               $this->renameStorageStatement->closeCursor();
+               return ($rowCount === 1);
+       }
+
+       /**
+        * Converts legacy home storage ids in the format
+        * "local::/data/dir/path/userid/" to the new format "home::userid"
+        */
+       public function run() {
+               // 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;
+                               $this->emit(
+                                       '\OC\Repair',
+                                       'warning',
+                                       array('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;
+                                                       $this->emit(
+                                                               '\OC\Repair',
+                                                               'warning',
+                                                               array('Could not repair legacy storage ' . $storageId . ' automatically.')
+                                                       );
+                                               }
+                                       }
+                               }
+                               $offset += $limit;
+                       } while (count($results) >= $limit);
+               }
+
+               $this->emit('\OC\Repair', 'info', array('Updated ' . $count . ' legacy home storage ids'));
+
+               $this->connection->commit();
+
+               if ($hasWarnings) {
+                       $this->emit(
+                               '\OC\Repair',
+                               'warning',
+                               array('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');
+               }
+       }
+}
diff --git a/lib/private/repair/repairmimetypes.php b/lib/private/repair/repairmimetypes.php
new file mode 100644 (file)
index 0000000..e687dbd
--- /dev/null
@@ -0,0 +1,360 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ * @author Morris Jobke <hey@morrisjobke.de>
+ * @author Normal Ra <normalraw@gmail.com>
+ * @author Olivier Paroz <github@oparoz.com>
+ * @author Roeland Jago Douma <rullzer@owncloud.com>
+ * @author Victor Dubiniuk <dubiniuk@owncloud.com>
+ * @author Vincent Petry <pvince81@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+use OC\Hooks\BasicEmitter;
+
+class RepairMimeTypes extends BasicEmitter implements \OC\RepairStep {
+       /**
+        * @var \OCP\IConfig
+        */
+       protected $config;
+
+       /**
+        * @var int
+        */
+       protected $folderMimeTypeId;
+
+       /**
+        * @param \OCP\IConfig $config
+        */
+       public function __construct($config) {
+               $this->config = $config;
+       }
+
+       public function getName() {
+               return 'Repair mime types';
+       }
+
+       private static function existsStmt() {
+               return \OC_DB::prepare('
+                       SELECT count(`mimetype`)
+                       FROM   `*PREFIX*mimetypes`
+                       WHERE  `mimetype` = ?
+               ');
+       }
+
+       private static function getIdStmt() {
+               return \OC_DB::prepare('
+                       SELECT `id`
+                       FROM   `*PREFIX*mimetypes`
+                       WHERE  `mimetype` = ?
+               ');
+       }
+
+       private static function insertStmt() {
+               return \OC_DB::prepare('
+                       INSERT INTO `*PREFIX*mimetypes` ( `mimetype` )
+                       VALUES ( ? )
+               ');
+       }
+
+       private static function updateWrongStmt() {
+               return \OC_DB::prepare('
+                       UPDATE `*PREFIX*filecache`
+                       SET `mimetype` = (
+                               SELECT `id`
+                               FROM `*PREFIX*mimetypes`
+                               WHERE `mimetype` = ?
+                       ) WHERE `mimetype` = ?
+               ');
+       }
+
+       private static function deleteStmt() {
+               return \OC_DB::prepare('
+                       DELETE FROM `*PREFIX*mimetypes`
+                       WHERE `id` = ?
+               ');
+       }
+
+       private static function updateByNameStmt() {
+               return \OC_DB::prepare('
+                       UPDATE `*PREFIX*filecache`
+                       SET `mimetype` = ?
+                       WHERE `mimetype` <> ? AND `mimetype` <> ? AND `name` ILIKE ?
+               ');
+       }
+
+       private function repairMimetypes($wrongMimetypes) {
+               foreach ($wrongMimetypes as $wrong => $correct) {
+                       // do we need to remove a wrong mimetype?
+                       $result = \OC_DB::executeAudited(self::getIdStmt(), array($wrong));
+                       $wrongId = $result->fetchOne();
+
+                       if ($wrongId !== false) {
+                               // do we need to insert the correct mimetype?
+                               $result = \OC_DB::executeAudited(self::existsStmt(), array($correct));
+                               $exists = $result->fetchOne();
+
+                               if (!is_null($correct)) {
+                                       if (!$exists) {
+                                               // insert mimetype
+                                               \OC_DB::executeAudited(self::insertStmt(), array($correct));
+                                       }
+
+                                       // change wrong mimetype to correct mimetype in filecache
+                                       \OC_DB::executeAudited(self::updateWrongStmt(), array($correct, $wrongId));
+                               }
+
+                               // delete wrong mimetype
+                               \OC_DB::executeAudited(self::deleteStmt(), array($wrongId));
+
+                       }
+               }
+       }
+
+       private function updateMimetypes($updatedMimetypes) {
+               if (empty($this->folderMimeTypeId)) {
+                       $result = \OC_DB::executeAudited(self::getIdStmt(), array('httpd/unix-directory'));
+                       $this->folderMimeTypeId = (int)$result->fetchOne();
+               }
+
+               foreach ($updatedMimetypes as $extension => $mimetype) {
+                       $result = \OC_DB::executeAudited(self::existsStmt(), array($mimetype));
+                       $exists = $result->fetchOne();
+
+                       if (!$exists) {
+                               // insert mimetype
+                               \OC_DB::executeAudited(self::insertStmt(), array($mimetype));
+                       }
+                       
+                       // get target mimetype id
+                       $result = \OC_DB::executeAudited(self::getIdStmt(), array($mimetype));
+                       $mimetypeId = $result->fetchOne();
+
+                       // change mimetype for files with x extension
+                       \OC_DB::executeAudited(self::updateByNameStmt(), array($mimetypeId, $this->folderMimeTypeId, $mimetypeId, '%.' . $extension));
+               }
+       }
+
+       private function fixOfficeMimeTypes() {
+               // update wrong mimetypes
+               $wrongMimetypes = array(
+                       'application/mspowerpoint' => 'application/vnd.ms-powerpoint',
+                       'application/msexcel' => 'application/vnd.ms-excel',
+               );
+
+               self::repairMimetypes($wrongMimetypes);
+
+               $updatedMimetypes = array(
+                       'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+                       'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+                       'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+               );
+
+
+               // separate doc from docx etc
+               self::updateMimetypes($updatedMimetypes);
+
+       }
+
+       private function fixApkMimeType() {
+               $updatedMimetypes = array(
+                       'apk' => 'application/vnd.android.package-archive',
+               );
+
+               self::updateMimetypes($updatedMimetypes);
+       }
+
+       private function fixFontsMimeTypes() {
+               // update wrong mimetypes
+               $wrongMimetypes = array(
+                       'font' => null,
+                       'font/opentype' => 'application/font-sfnt',
+                       'application/x-font-ttf' => 'application/font-sfnt',
+               );
+
+               self::repairMimetypes($wrongMimetypes);
+
+               $updatedMimetypes = array(
+                       'ttf' => 'application/font-sfnt',
+                       'otf' => 'application/font-sfnt',
+                       'pfb' => 'application/x-font',
+               );
+
+               self::updateMimetypes($updatedMimetypes);
+       }
+
+       private function fixPostscriptMimeType() {
+               $updatedMimetypes = array(
+                       'eps' => 'application/postscript',
+                       'ps' => 'application/postscript',
+               );
+
+               self::updateMimetypes($updatedMimetypes);
+       }
+
+       private function introduceRawMimeType() {
+               $updatedMimetypes = array(
+                       'arw' => 'image/x-dcraw',
+                       'cr2' => 'image/x-dcraw',
+                       'dcr' => 'image/x-dcraw',
+                       'dng' => 'image/x-dcraw',
+                       'erf' => 'image/x-dcraw',
+                       'iiq' => 'image/x-dcraw',
+                       'k25' => 'image/x-dcraw',
+                       'kdc' => 'image/x-dcraw',
+                       'mef' => 'image/x-dcraw',
+                       'nef' => 'image/x-dcraw',
+                       'orf' => 'image/x-dcraw',
+                       'pef' => 'image/x-dcraw',
+                       'raf' => 'image/x-dcraw',
+                       'rw2' => 'image/x-dcraw',
+                       'srf' => 'image/x-dcraw',
+                       'sr2' => 'image/x-dcraw',
+                       'xrf' => 'image/x-dcraw',
+               );
+
+               self::updateMimetypes($updatedMimetypes);
+       }
+
+       private function introduce3dImagesMimeType() {
+               $updatedMimetypes = array(
+                       'jps' => 'image/jpeg',
+                       'mpo' => 'image/jpeg',
+               );
+
+               self::updateMimetypes($updatedMimetypes);
+       }
+
+       private function introduceConfMimeType() {
+               $updatedMimetypes = array(
+                       'conf' => 'text/plain',
+                       'cnf' => 'text/plain',
+               );
+
+               self::updateMimetypes($updatedMimetypes);
+       }
+
+       private function introduceYamlMimeType() {
+               $updatedMimetypes = array(
+                       'yaml' => 'application/yaml',
+                       'yml' => 'application/yaml',
+               );
+
+               self::updateMimetypes($updatedMimetypes);
+       }
+
+       private function introduceJavaMimeType() {
+               $updatedMimetypes = array(
+                       'class' => 'application/java',
+                       'java' => 'text/x-java-source',
+               );
+
+               self::updateMimetypes($updatedMimetypes);
+       }
+
+       private function introduceHppMimeType() {
+               $updatedMimetypes = array(
+                       'hpp' => 'text/x-h',
+               );
+
+               self::updateMimetypes($updatedMimetypes);
+       }
+
+       private function introduceRssMimeType() {
+               $updatedMimetypes = array(
+                       'rss' => 'application/rss+xml',
+               );
+
+               self::updateMimetypes($updatedMimetypes);
+       }
+
+       private function introduceRtfMimeType() {
+               $updatedMimetypes = array(
+                       'rtf' => 'text/rtf',
+               );
+
+               self::updateMimetypes($updatedMimetypes);
+       }
+
+       /**
+        * Fix mime types
+        */
+       public function run() {
+
+               $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()) {
+                               $this->emit('\OC\Repair', 'info', array('Fixed office mime types'));
+                       }
+
+                       if ($this->fixApkMimeType()) {
+                               $this->emit('\OC\Repair', 'info', array('Fixed APK mime type'));
+                       }
+
+                       if ($this->fixFontsMimeTypes()) {
+                               $this->emit('\OC\Repair', 'info', array('Fixed fonts mime types'));
+                       }
+
+                       if ($this->fixPostscriptMimeType()) {
+                               $this->emit('\OC\Repair', 'info', array('Fixed Postscript mime types'));
+                       }
+
+                       if ($this->introduceRawMimeType()) {
+                               $this->emit('\OC\Repair', 'info', array('Fixed Raw mime types'));
+                       }
+
+                       if ($this->introduce3dImagesMimeType()) {
+                               $this->emit('\OC\Repair', 'info', array('Fixed 3D images mime types'));
+                       }
+
+                       if ($this->introduceConfMimeType()) {
+                               $this->emit('\OC\Repair', 'info', array('Fixed Conf/cnf mime types'));
+                       }
+
+                       if ($this->introduceYamlMimeType()) {
+                               $this->emit('\OC\Repair', 'info', array('Fixed Yaml/Yml mime types'));
+                       }
+               }
+
+               // Mimetype updates from #19272
+               if (version_compare($ocVersionFromBeforeUpdate, '8.2.0.8', '<')) {
+                       if ($this->introduceJavaMimeType()) {
+                               $this->emit('\OC\Repair', 'info', array('Fixed java/class mime types'));
+                       }
+
+                       if ($this->introduceHppMimeType()) {
+                               $this->emit('\OC\Repair', 'info', array('Fixed hpp mime type'));
+                       }
+
+                       if ($this->introduceRssMimeType()) {
+                               $this->emit('\OC\Repair', 'info', array('Fixed rss mime type'));
+                       }
+
+                       if ($this->introduceRtfMimeType()) {
+                               $this->emit('\OC\Repair', 'info', array('Fixed rtf mime type'));
+                       }
+               }
+       }
+}
diff --git a/lib/private/repair/searchlucenetables.php b/lib/private/repair/searchlucenetables.php
new file mode 100644 (file)
index 0000000..5ae8a30
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+/**
+ * @author Jörn Friedrich Dreyer <jfd@butonic.de>
+ * @author Morris Jobke <hey@morrisjobke.de>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+use OC\Hooks\BasicEmitter;
+
+class SearchLuceneTables extends BasicEmitter implements \OC\RepairStep {
+
+       public function getName() {
+               return 'Repair duplicate entries in oc_lucene_status';
+       }
+
+       /**
+        * 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() {
+               if (\OC_DB::tableExists('lucene_status')) {
+                       $this->emit('\OC\Repair', 'info', array('removing duplicate entries from lucene_status'));
+
+                       $connection = \OC_DB::getConnection();
+                       $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 {
+                       $this->emit('\OC\Repair', 'info', array('lucene_status table does not exist -> nothing to do'));
+               }
+       }
+
+}
+
diff --git a/lib/private/repair/sqliteautoincrement.php b/lib/private/repair/sqliteautoincrement.php
new file mode 100644 (file)
index 0000000..70d0ada
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+/**
+ * @author Vincent Petry <pvince81@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+use Doctrine\DBAL\Platforms\SqlitePlatform;
+use Doctrine\DBAL\Schema\SchemaException;
+use Doctrine\DBAL\Schema\SchemaDiff;
+use Doctrine\DBAL\Schema\TableDiff;
+use Doctrine\DBAL\Schema\ColumnDiff;
+use OC\Hooks\BasicEmitter;
+
+/**
+ * Fixes Sqlite autoincrement by forcing the SQLite table schemas to be
+ * altered in order to retrigger SQL schema generation through OCSqlitePlatform.
+ */
+class SqliteAutoincrement extends BasicEmitter implements \OC\RepairStep {
+       /**
+        * @var \OC\DB\Connection
+        */
+       protected $connection;
+
+       /**
+        * @param \OC\DB\Connection $connection
+        */
+       public function __construct($connection) {
+               $this->connection = $connection;
+       }
+
+       public function getName() {
+               return 'Repair SQLite autoincrement';
+       }
+
+       /**
+        * Fix mime types
+        */
+       public function run() {
+               if (!$this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
+                       return;
+               }
+
+               $sourceSchema = $this->connection->getSchemaManager()->createSchema();
+
+               $schemaDiff = new SchemaDiff();
+
+               foreach ($sourceSchema->getTables() as $tableSchema) {
+                       $primaryKey = $tableSchema->getPrimaryKey();
+                       if (!$primaryKey) {
+                               continue;
+                       }
+
+                       $columnNames = $primaryKey->getColumns();
+
+                       // add a column diff for every primary key column,
+                       // but do not actually change anything, this will
+                       // force the generation of SQL statements to alter
+                       // those tables, which will then trigger the
+                       // specific SQL code from OCSqlitePlatform
+                       try {
+                               $tableDiff = new TableDiff($tableSchema->getName());
+                               $tableDiff->fromTable = $tableSchema;
+                               foreach ($columnNames as $columnName) {
+                                       $columnSchema = $tableSchema->getColumn($columnName);
+                                       $columnDiff = new ColumnDiff($columnSchema->getName(), $columnSchema);
+                                       $tableDiff->changedColumns[] = $columnDiff;
+                                       $schemaDiff->changedTables[] = $tableDiff;
+                               }
+                       } catch (SchemaException $e) {
+                               // ignore
+                       }
+               }
+
+               $this->connection->beginTransaction();
+               foreach ($schemaDiff->toSql($this->connection->getDatabasePlatform()) as $sql) {
+                       $this->connection->query($sql);
+               }
+               $this->connection->commit();
+       }
+}
+
diff --git a/lib/private/repair/updatecertificatestore.php b/lib/private/repair/updatecertificatestore.php
new file mode 100644 (file)
index 0000000..5fad309
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+use OC\Files\View;
+use OC\Hooks\BasicEmitter;
+use OC\RepairStep;
+use OC\Server;
+use OCP\IConfig;
+
+/**
+ * Class UpdateCertificateStore rewrites the user specific certificate store after
+ * an update has been performed. This is done because a new root certificate file
+ * might have been added.
+ *
+ * @package OC\Repair
+ */
+class UpdateCertificateStore extends BasicEmitter implements RepairStep {
+       /**
+        * FIXME: The certificate manager does only allow specifying the user
+        *        within the constructor. This makes DI impossible.
+        * @var Server
+        */
+       protected $server;
+       /** @var IConfig */
+       protected $config;
+
+       /**
+        * @param Server $server
+        * @param IConfig $config
+        */
+       public function __construct(Server $server,
+                                                               IConfig $config) {
+               $this->server = $server;
+               $this->config = $config;
+       }
+
+       /** {@inheritDoc} */
+       public function getName() {
+               return 'Update user certificate stores with new root certificates';
+       }
+
+       /** {@inheritDoc} */
+       public function run() {
+               $rootView = new View();
+               $dataDirectory = $this->config->getSystemValue('datadirectory', null);
+               if(is_null($dataDirectory)) {
+                       throw new \Exception('No data directory specified');
+               }
+
+               $pathToRootCerts = '/files_external/rootcerts.crt';
+
+               foreach($rootView->getDirectoryContent('', 'httpd/unix-directory') as $fileInfo) {
+                       $uid = trim($fileInfo->getPath(), '/');
+                       if($rootView->file_exists($uid . $pathToRootCerts)) {
+                               // Delete the existing root certificate
+                               $rootView->unlink($uid . $pathToRootCerts);
+
+                               /**
+                                * FIXME: The certificate manager does only allow specifying the user
+                                *        within the constructor. This makes DI impossible.
+                                */
+                               // Regenerate the certificates
+                               $certificateManager = $this->server->getCertificateManager($uid);
+                               $certificateManager->createCertificateBundle();
+                       }
+               }
+       }
+}
diff --git a/lib/private/repair/updateoutdatedocsids.php b/lib/private/repair/updateoutdatedocsids.php
new file mode 100644 (file)
index 0000000..5f6ee02
--- /dev/null
@@ -0,0 +1,108 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+use OC\Hooks\BasicEmitter;
+use OC\RepairStep;
+use OCP\IConfig;
+
+/**
+ * Class UpdateOutdatedOcsIds is used to update invalid outdated OCS IDs, this is
+ * for example the case when an application has had another OCS ID in the past such
+ * as for contacts and calendar when apps.owncloud.com migrated to a unified identifier
+ * for multiple versions.
+ *
+ * @package OC\Repair
+ */
+class UpdateOutdatedOcsIds extends BasicEmitter implements RepairStep {
+       /** @var IConfig */
+       private $config;
+
+       /**
+        * @param IConfig $config
+        */
+       public function __construct(IConfig $config) {
+               $this->config = $config;
+       }
+
+       /**
+        * {@inheritdoc}
+        */
+       public function getName() {
+               return 'Repair outdated OCS IDs';
+       }
+
+       /**
+        * @param string $appName
+        * @param string $oldId
+        * @param string $newId
+        * @return bool True if updated, false otherwise
+        */
+       public function fixOcsId($appName, $oldId, $newId) {
+               $existingId = $this->config->getAppValue($appName, 'ocsid');
+
+               if($existingId === $oldId) {
+                       $this->config->setAppValue($appName, 'ocsid', $newId);
+                       return true;
+               }
+
+               return false;
+       }
+
+       /**
+        * {@inheritdoc}
+        */
+       public function run() {
+               $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'])) {
+                               $this->emit(
+                                       '\OC\Repair',
+                                       'info',
+                                       [sprintf('Fixed invalid %s OCS id', $appName)]
+                               );
+                       }
+               }
+       }
+}
diff --git a/lib/repair/assetcache.php b/lib/repair/assetcache.php
deleted file mode 100644 (file)
index c46aa63..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-/**
- * @author Adam Williamson <awilliam@redhat.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-use Doctrine\DBAL\Platforms\MySqlPlatform;
-use OC\Hooks\BasicEmitter;
-
-class AssetCache extends BasicEmitter implements \OC\RepairStep {
-
-       public function getName() {
-               return 'Clear asset cache after upgrade';
-       }
-
-       public function run() {
-               if (!\OC_Template::isAssetPipelineEnabled()) {
-                       $this->emit('\OC\Repair', 'info', array('Asset pipeline disabled -> nothing to do'));
-                       return;
-               }
-               $assetDir = \OC::$server->getConfig()->getSystemValue('assetdirectory', \OC::$SERVERROOT) . '/assets';
-               \OC_Helper::rmdirr($assetDir, false);
-               $this->emit('\OC\Repair', 'info', array('Asset cache cleared.'));
-       }
-}
-
diff --git a/lib/repair/cleantags.php b/lib/repair/cleantags.php
deleted file mode 100644 (file)
index d16a49f..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-<?php
-/**
- * @author Joas Schilling <nickvergessen@owncloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-use OC\Hooks\BasicEmitter;
-use OC\RepairStep;
-use OCP\IDBConnection;
-
-/**
- * Class RepairConfig
- *
- * @package OC\Repair
- */
-class CleanTags extends BasicEmitter implements RepairStep {
-
-       /** @var IDBConnection */
-       protected $connection;
-
-       /**
-        * @param IDBConnection $connection
-        */
-       public function __construct(IDBConnection $connection) {
-               $this->connection = $connection;
-       }
-
-       /**
-        * @return string
-        */
-       public function getName() {
-               return 'Clean tags and favorites';
-       }
-
-       /**
-        * Updates the configuration after running an update
-        */
-       public function run() {
-               $this->deleteOrphanFileEntries();
-               $this->deleteOrphanTagEntries();
-               $this->deleteOrphanCategoryEntries();
-       }
-
-       /**
-        * Delete tag entries for deleted files
-        */
-       protected function deleteOrphanFileEntries() {
-               $this->deleteOrphanEntries(
-                       '%d tags for delete files have been removed.',
-                       'vcategory_to_object', 'objid',
-                       'filecache', 'fileid', 'path_hash'
-               );
-       }
-
-       /**
-        * Delete tag entries for deleted tags
-        */
-       protected function deleteOrphanTagEntries() {
-               $this->deleteOrphanEntries(
-                       '%d tag entries for deleted tags have been removed.',
-                       'vcategory_to_object', 'categoryid',
-                       'vcategory', 'id', 'uid'
-               );
-       }
-
-       /**
-        * Delete tags that have no entries
-        */
-       protected function deleteOrphanCategoryEntries() {
-               $this->deleteOrphanEntries(
-                       '%d tags with no entries have been removed.',
-                       'vcategory', 'id',
-                       'vcategory_to_object', 'categoryid', 'type'
-               );
-       }
-
-       /**
-        * 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($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, \Doctrine\DBAL\Connection::PARAM_INT_ARRAY);
-                               $qb->execute();
-                       }
-               }
-
-               if ($repairInfo) {
-                       $this->emit('\OC\Repair', 'info', array(sprintf($repairInfo, sizeof($orphanItems))));
-               }
-       }
-}
diff --git a/lib/repair/collation.php b/lib/repair/collation.php
deleted file mode 100644 (file)
index 7eb14f0..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-/**
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <icewind@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-use Doctrine\DBAL\Platforms\MySqlPlatform;
-use OC\Hooks\BasicEmitter;
-
-class Collation extends BasicEmitter implements \OC\RepairStep {
-       /**
-        * @var \OCP\IConfig
-        */
-       protected $config;
-
-       /**
-        * @var \OC\DB\Connection
-        */
-       protected $connection;
-
-       /**
-        * @param \OCP\IConfig $config
-        * @param \OC\DB\Connection $connection
-        */
-       public function __construct($config, $connection) {
-               $this->connection = $connection;
-               $this->config = $config;
-       }
-
-       public function getName() {
-               return 'Repair MySQL collation';
-       }
-
-       /**
-        * Fix mime types
-        */
-       public function run() {
-               if (!$this->connection->getDatabasePlatform() instanceof MySqlPlatform) {
-                       $this->emit('\OC\Repair', 'info', array('Not a mysql database -> nothing to no'));
-                       return;
-               }
-
-               $tables = $this->getAllNonUTF8BinTables($this->connection);
-               foreach ($tables as $table) {
-                       $this->emit('\OC\Repair', 'info', array("Change collation for $table ..."));
-                       $query = $this->connection->prepare('ALTER TABLE `' . $table . '` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;');
-                       $query->execute();
-               }
-       }
-
-       /**
-        * @param \Doctrine\DBAL\Connection $connection
-        * @return string[]
-        */
-       protected function getAllNonUTF8BinTables($connection) {
-               $dbName = $this->config->getSystemValue("dbname");
-               $rows = $connection->fetchAll(
-                       "SELECT DISTINCT(TABLE_NAME) AS `table`" .
-                       "       FROM INFORMATION_SCHEMA . COLUMNS" .
-                       "       WHERE TABLE_SCHEMA = ?" .
-                       "       AND (COLLATION_NAME <> 'utf8_bin' OR CHARACTER_SET_NAME <> 'utf8')" .
-                       "       AND TABLE_NAME LIKE \"*PREFIX*%\"",
-                       array($dbName)
-               );
-               $result = array();
-               foreach ($rows as $row) {
-                       $result[] = $row['table'];
-               }
-               return $result;
-       }
-}
-
diff --git a/lib/repair/dropoldjobs.php b/lib/repair/dropoldjobs.php
deleted file mode 100644 (file)
index 89d7f96..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-<?php
-/**
- * @author Arthur Schiwon <blizzz@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-use OC\Hooks\BasicEmitter;
-use OC\RepairStep;
-use OCP\BackgroundJob\IJobList;
-
-class DropOldJobs extends BasicEmitter implements RepairStep {
-
-       /** @var IJobList */
-       protected $jobList;
-
-       /**
-        * @param IJobList $jobList
-        */
-       public function __construct(IJobList $jobList) {
-               $this->jobList = $jobList;
-       }
-
-       /**
-        * Returns the step's name
-        *
-        * @return string
-        */
-       public function getName() {
-               return 'Drop old background jobs';
-       }
-
-       /**
-        * Run repair step.
-        * Must throw exception on error.
-        *
-        * @throws \Exception in case of failure
-        */
-       public function run() {
-               $oldJobs = $this->oldJobs();
-               foreach($oldJobs as $job) {
-                       if($this->jobList->has($job['class'], $job['arguments'])) {
-                               $this->jobList->remove($job['class'], $job['arguments']);
-                       }
-               }
-       }
-
-       /**
-        * returns a list of old jobs as an associative array with keys 'class' and
-        * 'arguments'.
-        *
-        * @return array
-        */
-       public function oldJobs() {
-               return [
-                       ['class' => 'OC_Cache_FileGlobalGC', 'arguments' => null],
-                       ['class' => 'OC\Cache\FileGlobalGC', 'arguments' => null],
-               ];
-       }
-
-
-}
diff --git a/lib/repair/dropoldtables.php b/lib/repair/dropoldtables.php
deleted file mode 100644 (file)
index 2d7fc83..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-<?php
-/**
- * @author Joas Schilling <nickvergessen@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-
-use OC\Hooks\BasicEmitter;
-use OC\RepairStep;
-use OCP\IDBConnection;
-
-class DropOldTables extends BasicEmitter implements RepairStep {
-
-       /** @var IDBConnection */
-       protected $connection;
-
-       /**
-        * @param IDBConnection $connection
-        */
-       public function __construct(IDBConnection $connection) {
-               $this->connection = $connection;
-       }
-
-       /**
-        * Returns the step's name
-        *
-        * @return string
-        */
-       public function getName() {
-               return 'Drop old database tables';
-       }
-
-       /**
-        * Run repair step.
-        * Must throw exception on error.
-        *
-        * @throws \Exception in case of failure
-        */
-       public function run() {
-               foreach ($this->oldDatabaseTables() as $tableName) {
-                       if ($this->connection->tableExists($tableName)){
-                               $this->emit('\OC\Repair', 'info', [
-                                       sprintf('Table %s has been deleted', $tableName)
-                               ]);
-                               $this->connection->dropTable($tableName);
-                       }
-               }
-       }
-
-       /**
-        * Returns a list of outdated tables which are not used anymore
-        * @return array
-        */
-       protected function oldDatabaseTables() {
-               return [
-                       'calendar_calendars',
-                       'calendar_objects',
-                       'calendar_share_calendar',
-                       'calendar_share_event',
-                       'file_map',
-                       'foldersize',
-                       'fscache',
-                       'gallery_sharing',
-                       'locks',
-                       'log',
-                       'media_albums',
-                       'media_artists',
-                       'media_sessions',
-                       'media_songs',
-                       'media_users',
-                       'permissions',
-                       'pictures_images_cache',
-                       'principalgroups',
-                       'principals',
-                       'queuedtasks',
-                       'sharing',
-               ];
-       }
-}
diff --git a/lib/repair/filletags.php b/lib/repair/filletags.php
deleted file mode 100644 (file)
index 8cfc4a7..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-/**
- * @author Joas Schilling <nickvergessen@owncloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-use OC\Hooks\BasicEmitter;
-
-class FillETags extends BasicEmitter implements \OC\RepairStep {
-
-       /** @var \OCP\IDBConnection */
-       protected $connection;
-
-       /**
-        * @param \OCP\IDBConnection $connection
-        */
-       public function __construct($connection) {
-               $this->connection = $connection;
-       }
-
-       public function getName() {
-               return 'Generate ETags for file where no ETag is present.';
-       }
-
-       public function run() {
-               $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();
-               $this->emit('\OC\Repair', 'info', array("ETags have been fixed for $result files/folders."));
-       }
-}
-
diff --git a/lib/repair/innodb.php b/lib/repair/innodb.php
deleted file mode 100644 (file)
index ab94c79..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-<?php
-/**
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <icewind@owncloud.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-use Doctrine\DBAL\Platforms\MySqlPlatform;
-use OC\Hooks\BasicEmitter;
-
-class InnoDB extends BasicEmitter implements \OC\RepairStep {
-
-       public function getName() {
-               return 'Repair MySQL database engine';
-       }
-
-       /**
-        * Fix mime types
-        */
-       public function run() {
-               $connection = \OC_DB::getConnection();
-               if (!$connection->getDatabasePlatform() instanceof MySqlPlatform) {
-                       $this->emit('\OC\Repair', 'info', array('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;");
-                               $this->emit('\OC\Repair', 'info', array("Fixed $table"));
-                       }
-               }
-       }
-
-       /**
-        * @param \Doctrine\DBAL\Connection $connection
-        * @return string[]
-        */
-       private function getAllMyIsamTables($connection) {
-               $dbName = \OC::$server->getConfig()->getSystemValue("dbname");
-               $result = $connection->fetchArray(
-                       "SELECT table_name FROM information_schema.tables WHERE table_schema = ? AND engine = 'MyISAM' AND TABLE_NAME LIKE \"*PREFIX*%\"",
-                       array($dbName)
-               );
-
-               return $result;
-       }
-}
-
diff --git a/lib/repair/oldgroupmembershipshares.php b/lib/repair/oldgroupmembershipshares.php
deleted file mode 100644 (file)
index 2d701ac..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-<?php
-/**
- * @author Joas Schilling <nickvergessen@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-
-use OC\Hooks\BasicEmitter;
-use OC\RepairStep;
-use OCP\IDBConnection;
-use OCP\IGroupManager;
-use OCP\Share;
-
-class OldGroupMembershipShares extends BasicEmitter implements RepairStep {
-
-       /** @var \OCP\IDBConnection */
-       protected $connection;
-
-       /** @var \OCP\IGroupManager */
-       protected $groupManager;
-
-       /**
-        * @var array [gid => [uid => (bool)]]
-        */
-       protected $memberships;
-
-       /**
-        * @param IDBConnection $connection
-        * @param IGroupManager $groupManager
-        */
-       public function __construct(IDBConnection $connection, IGroupManager $groupManager) {
-               $this->connection = $connection;
-               $this->groupManager = $groupManager;
-       }
-
-       /**
-        * Returns the step's name
-        *
-        * @return string
-        */
-       public function getName() {
-               return 'Remove shares of old group memberships';
-       }
-
-       /**
-        * Run repair step.
-        * Must throw exception on error.
-        *
-        * @throws \Exception in case of failure
-        */
-       public function run() {
-               $deletedEntries = 0;
-
-               $query = $this->connection->getQueryBuilder();
-               $query->select(['s1.id', $query->createFunction('s1.`share_with` AS `user`'), $query->createFunction('s2.`share_with` AS `group`')])
-                       ->from('share', 's1')
-                       ->where($query->expr()->isNotNull('s1.parent'))
-                               // \OC\Share\Constant::$shareTypeGroupUserUnique === 2
-                               ->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) {
-                       $this->emit('\OC\Repair', 'info', array('Removed ' . $deletedEntries . ' shares where user is not a member of the group anymore'));
-               }
-       }
-
-       /**
-        * @param string $gid
-        * @param string $uid
-        * @return bool
-        */
-       protected function isMember($gid, $uid) {
-               if (isset($this->memberships[$gid][$uid])) {
-                       return $this->memberships[$gid][$uid];
-               }
-
-               $isMember = $this->groupManager->isInGroup($uid, $gid);
-               if (!isset($this->memberships[$gid])) {
-                       $this->memberships[$gid] = [];
-               }
-               $this->memberships[$gid][$uid] = $isMember;
-
-               return $isMember;
-       }
-}
diff --git a/lib/repair/preview.php b/lib/repair/preview.php
deleted file mode 100644 (file)
index 2284da9..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-/**
- * @author Georg Ehrke <georg@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-namespace OC\Repair;
-
-use OC\Files\View;
-use OC\Hooks\BasicEmitter;
-
-class Preview extends BasicEmitter implements \OC\RepairStep {
-
-       public function getName() {
-               return 'Cleaning-up broken previews';
-       }
-
-       public function run() {
-               $view = new View('/');
-               $children = $view->getDirectoryContent('/');
-
-               foreach ($children as $child) {
-                       if ($view->is_dir($child->getPath())) {
-                               $thumbnailsFolder = $child->getPath() . '/thumbnails';
-                               if ($view->is_dir($thumbnailsFolder)) {
-                                       $view->rmdir($thumbnailsFolder);
-                               }
-                       }
-               }
-       }
-}
\ No newline at end of file
diff --git a/lib/repair/removegetetagentries.php b/lib/repair/removegetetagentries.php
deleted file mode 100644 (file)
index 4004076..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-/**
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-use OC\Hooks\BasicEmitter;
-use OCP\IDBConnection;
-
-class RemoveGetETagEntries extends BasicEmitter {
-
-       /**
-        * @var IDBConnection
-        */
-       protected $connection;
-
-       /**
-        * @param IDBConnection $connection
-        */
-       public function __construct(IDBConnection $connection) {
-               $this->connection = $connection;
-       }
-
-       public function getName() {
-               return 'Remove getetag entries in properties table';
-       }
-
-       /**
-        * Removes all entries with the key "{DAV:}getetag" from the table properties
-        */
-       public function run() {
-               $sql = 'DELETE FROM `*PREFIX*properties`'
-                       . ' WHERE `propertyname` = ?';
-               $deletedRows = $this->connection->executeUpdate($sql, ['{DAV:}getetag']);
-
-               $this->emit(
-                       '\OC\Repair',
-                       'info',
-                       ['Removed ' . $deletedRows . ' unneeded "{DAV:}getetag" entries from properties table.']
-               );
-       }
-}
diff --git a/lib/repair/repairinvalidshares.php b/lib/repair/repairinvalidshares.php
deleted file mode 100644 (file)
index 5a4cb44..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-<?php
-/**
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-use OC\Hooks\BasicEmitter;
-
-/**
- * Repairs shares with invalid data
- */
-class RepairInvalidShares extends BasicEmitter implements \OC\RepairStep {
-
-       /**
-        * @var \OCP\IConfig
-        */
-       protected $config;
-
-       /**
-        * @var \OCP\IDBConnection
-        */
-       protected $connection;
-
-       /**
-        * @param \OCP\IConfig $config
-        * @param \OCP\IDBConnection $connection
-        */
-       public function __construct($config, $connection) {
-               $this->connection = $connection;
-               $this->config = $config;
-       }
-
-       public function getName() {
-               return 'Repair invalid shares';
-       }
-
-       /**
-        * Past bugs would make it possible to set an expiration date on user shares even
-        * though it is not supported. This functions removes the expiration date from such entries.
-        */
-       private function removeExpirationDateFromNonLinkShares() {
-               $builder = $this->connection->getQueryBuilder();
-               $builder
-                       ->update('share')
-                       ->set('expiration', 'null')
-                       ->where($builder->expr()->isNotNull('expiration'))
-                       ->andWhere($builder->expr()->neq('share_type', $builder->expr()->literal(\OC\Share\Constants::SHARE_TYPE_LINK)));
-
-               $updatedEntries = $builder->execute();
-               if ($updatedEntries > 0) {
-                       $this->emit('\OC\Repair', 'info', array('Removed invalid expiration date from ' . $updatedEntries . ' shares'));
-               }
-       }
-
-       /**
-        * Remove shares where the parent share does not exist anymore
-        */
-       private function removeSharesNonExistingParent() {
-               $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');
-
-               $deleteQuery = $this->connection->getQueryBuilder();
-               $deleteQuery->delete('share')
-                       ->where($query->expr()->eq('parent', $deleteQuery->createParameter('parent')));
-
-               $result = $query->execute();
-               while ($row = $result->fetch()) {
-                       $deletedEntries += $deleteQuery->setParameter('parent', (int) $row['parent'])
-                               ->execute();
-               }
-               $result->closeCursor();
-
-               if ($deletedEntries) {
-                       $this->emit('\OC\Repair', 'info', array('Removed ' . $deletedEntries . ' shares where the parent did not exist'));
-               }
-       }
-
-       public function run() {
-               $ocVersionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0');
-               if (version_compare($ocVersionFromBeforeUpdate, '8.2.0.7', '<')) {
-                       // this situation was only possible before 8.2
-                       $this->removeExpirationDateFromNonLinkShares();
-               }
-
-               $this->removeSharesNonExistingParent();
-       }
-}
diff --git a/lib/repair/repairlegacystorages.php b/lib/repair/repairlegacystorages.php
deleted file mode 100644 (file)
index 5ba452c..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-<?php
-/**
- * @author Joas Schilling <nickvergessen@owncloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-use OC\Files\Cache\Storage;
-use OC\Hooks\BasicEmitter;
-use OC\RepairException;
-
-class RepairLegacyStorages extends BasicEmitter {
-       /**
-        * @var \OCP\IConfig
-        */
-       protected $config;
-
-       /**
-        * @var \OCP\IDBConnection
-        */
-       protected $connection;
-
-       protected $findStorageInCacheStatement;
-       protected $renameStorageStatement;
-
-       /**
-        * @param \OCP\IConfig $config
-        * @param \OCP\IDBConnection $connection
-        */
-       public function __construct($config, $connection) {
-               $this->connection = $connection;
-               $this->config = $config;
-
-               $this->findStorageInCacheStatement = $this->connection->prepare(
-                       'SELECT DISTINCT `storage` FROM `*PREFIX*filecache`'
-                       . ' WHERE `storage` in (?, ?)'
-               );
-               $this->renameStorageStatement = $this->connection->prepare(
-                       'UPDATE `*PREFIX*storages`'
-                       . ' SET `id` = ?'
-                       . ' WHERE `id` = ?'
-               );
-       }
-
-       public function getName() {
-               return 'Repair legacy storages';
-       }
-
-       /**
-        * Extracts the user id from a legacy storage id
-        *
-        * @param string $storageId legacy storage id in the
-        * format "local::/path/to/datadir/userid"
-        * @return string user id extracted from the storage id
-        */
-       private function extractUserId($storageId) {
-               $storageId = rtrim($storageId, '/');
-               $pos = strrpos($storageId, '/');
-               return substr($storageId, $pos + 1);
-       }
-
-       /**
-        * Fix the given legacy storage by renaming the old id
-        * to the new id. If the new id already exists, whichever
-        * storage that has data in the file cache will be used.
-        * If both have data, nothing will be done and false is
-        * returned.
-        *
-        * @param string $oldId old storage id
-        * @param int $oldNumericId old storage numeric id
-        * @param string $userId
-        * @return bool true if fixed, false otherwise
-        * @throws RepairException
-        */
-       private function fixLegacyStorage($oldId, $oldNumericId, $userId = null) {
-               // check whether the new storage already exists
-               if (is_null($userId)) {
-                       $userId = $this->extractUserId($oldId);
-               }
-               $newId = 'home::' . $userId;
-
-               // check if target id already exists
-               $newNumericId = Storage::getNumericStorageId($newId);
-               if (!is_null($newNumericId)) {
-                       $newNumericId = (int)$newNumericId;
-                       // try and resolve the conflict
-                       // check which one of "local::" or "home::" needs to be kept
-                       $this->findStorageInCacheStatement->execute(array($oldNumericId, $newNumericId));
-                       $row1 = $this->findStorageInCacheStatement->fetch();
-                       $row2 = $this->findStorageInCacheStatement->fetch();
-                       $this->findStorageInCacheStatement->closeCursor();
-                       if ($row2 !== false) {
-                               // two results means both storages have data, not auto-fixable
-                               throw new RepairException(
-                                       'Could not automatically fix legacy storage '
-                                       . '"' . $oldId . '" => "' . $newId . '"'
-                                       . ' because they both have data.'
-                               );
-                       }
-                       if ($row1 === false || (int)$row1['storage'] === $oldNumericId) {
-                               // old storage has data, then delete the empty new id
-                               $toDelete = $newId;
-                       } else if ((int)$row1['storage'] === $newNumericId) {
-                               // new storage has data, then delete the empty old id
-                               $toDelete = $oldId;
-                       } else {
-                               // unknown case, do not continue
-                               return false;
-                       }
-
-                       // delete storage including file cache
-                       Storage::remove($toDelete);
-
-                       // if we deleted the old id, the new id will be used
-                       // automatically
-                       if ($toDelete === $oldId) {
-                               // nothing more to do
-                               return true;
-                       }
-               }
-
-               // rename old id to new id
-               $newId = Storage::adjustStorageId($newId);
-               $oldId = Storage::adjustStorageId($oldId);
-               $rowCount = $this->renameStorageStatement->execute(array($newId, $oldId));
-               $this->renameStorageStatement->closeCursor();
-               return ($rowCount === 1);
-       }
-
-       /**
-        * Converts legacy home storage ids in the format
-        * "local::/data/dir/path/userid/" to the new format "home::userid"
-        */
-       public function run() {
-               // 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;
-                               $this->emit(
-                                       '\OC\Repair',
-                                       'warning',
-                                       array('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;
-                                                       $this->emit(
-                                                               '\OC\Repair',
-                                                               'warning',
-                                                               array('Could not repair legacy storage ' . $storageId . ' automatically.')
-                                                       );
-                                               }
-                                       }
-                               }
-                               $offset += $limit;
-                       } while (count($results) >= $limit);
-               }
-
-               $this->emit('\OC\Repair', 'info', array('Updated ' . $count . ' legacy home storage ids'));
-
-               $this->connection->commit();
-
-               if ($hasWarnings) {
-                       $this->emit(
-                               '\OC\Repair',
-                               'warning',
-                               array('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');
-               }
-       }
-}
diff --git a/lib/repair/repairmimetypes.php b/lib/repair/repairmimetypes.php
deleted file mode 100644 (file)
index e687dbd..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-<?php
-/**
- * @author Joas Schilling <nickvergessen@owncloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Normal Ra <normalraw@gmail.com>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Roeland Jago Douma <rullzer@owncloud.com>
- * @author Victor Dubiniuk <dubiniuk@owncloud.com>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-use OC\Hooks\BasicEmitter;
-
-class RepairMimeTypes extends BasicEmitter implements \OC\RepairStep {
-       /**
-        * @var \OCP\IConfig
-        */
-       protected $config;
-
-       /**
-        * @var int
-        */
-       protected $folderMimeTypeId;
-
-       /**
-        * @param \OCP\IConfig $config
-        */
-       public function __construct($config) {
-               $this->config = $config;
-       }
-
-       public function getName() {
-               return 'Repair mime types';
-       }
-
-       private static function existsStmt() {
-               return \OC_DB::prepare('
-                       SELECT count(`mimetype`)
-                       FROM   `*PREFIX*mimetypes`
-                       WHERE  `mimetype` = ?
-               ');
-       }
-
-       private static function getIdStmt() {
-               return \OC_DB::prepare('
-                       SELECT `id`
-                       FROM   `*PREFIX*mimetypes`
-                       WHERE  `mimetype` = ?
-               ');
-       }
-
-       private static function insertStmt() {
-               return \OC_DB::prepare('
-                       INSERT INTO `*PREFIX*mimetypes` ( `mimetype` )
-                       VALUES ( ? )
-               ');
-       }
-
-       private static function updateWrongStmt() {
-               return \OC_DB::prepare('
-                       UPDATE `*PREFIX*filecache`
-                       SET `mimetype` = (
-                               SELECT `id`
-                               FROM `*PREFIX*mimetypes`
-                               WHERE `mimetype` = ?
-                       ) WHERE `mimetype` = ?
-               ');
-       }
-
-       private static function deleteStmt() {
-               return \OC_DB::prepare('
-                       DELETE FROM `*PREFIX*mimetypes`
-                       WHERE `id` = ?
-               ');
-       }
-
-       private static function updateByNameStmt() {
-               return \OC_DB::prepare('
-                       UPDATE `*PREFIX*filecache`
-                       SET `mimetype` = ?
-                       WHERE `mimetype` <> ? AND `mimetype` <> ? AND `name` ILIKE ?
-               ');
-       }
-
-       private function repairMimetypes($wrongMimetypes) {
-               foreach ($wrongMimetypes as $wrong => $correct) {
-                       // do we need to remove a wrong mimetype?
-                       $result = \OC_DB::executeAudited(self::getIdStmt(), array($wrong));
-                       $wrongId = $result->fetchOne();
-
-                       if ($wrongId !== false) {
-                               // do we need to insert the correct mimetype?
-                               $result = \OC_DB::executeAudited(self::existsStmt(), array($correct));
-                               $exists = $result->fetchOne();
-
-                               if (!is_null($correct)) {
-                                       if (!$exists) {
-                                               // insert mimetype
-                                               \OC_DB::executeAudited(self::insertStmt(), array($correct));
-                                       }
-
-                                       // change wrong mimetype to correct mimetype in filecache
-                                       \OC_DB::executeAudited(self::updateWrongStmt(), array($correct, $wrongId));
-                               }
-
-                               // delete wrong mimetype
-                               \OC_DB::executeAudited(self::deleteStmt(), array($wrongId));
-
-                       }
-               }
-       }
-
-       private function updateMimetypes($updatedMimetypes) {
-               if (empty($this->folderMimeTypeId)) {
-                       $result = \OC_DB::executeAudited(self::getIdStmt(), array('httpd/unix-directory'));
-                       $this->folderMimeTypeId = (int)$result->fetchOne();
-               }
-
-               foreach ($updatedMimetypes as $extension => $mimetype) {
-                       $result = \OC_DB::executeAudited(self::existsStmt(), array($mimetype));
-                       $exists = $result->fetchOne();
-
-                       if (!$exists) {
-                               // insert mimetype
-                               \OC_DB::executeAudited(self::insertStmt(), array($mimetype));
-                       }
-                       
-                       // get target mimetype id
-                       $result = \OC_DB::executeAudited(self::getIdStmt(), array($mimetype));
-                       $mimetypeId = $result->fetchOne();
-
-                       // change mimetype for files with x extension
-                       \OC_DB::executeAudited(self::updateByNameStmt(), array($mimetypeId, $this->folderMimeTypeId, $mimetypeId, '%.' . $extension));
-               }
-       }
-
-       private function fixOfficeMimeTypes() {
-               // update wrong mimetypes
-               $wrongMimetypes = array(
-                       'application/mspowerpoint' => 'application/vnd.ms-powerpoint',
-                       'application/msexcel' => 'application/vnd.ms-excel',
-               );
-
-               self::repairMimetypes($wrongMimetypes);
-
-               $updatedMimetypes = array(
-                       'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
-                       'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
-                       'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
-               );
-
-
-               // separate doc from docx etc
-               self::updateMimetypes($updatedMimetypes);
-
-       }
-
-       private function fixApkMimeType() {
-               $updatedMimetypes = array(
-                       'apk' => 'application/vnd.android.package-archive',
-               );
-
-               self::updateMimetypes($updatedMimetypes);
-       }
-
-       private function fixFontsMimeTypes() {
-               // update wrong mimetypes
-               $wrongMimetypes = array(
-                       'font' => null,
-                       'font/opentype' => 'application/font-sfnt',
-                       'application/x-font-ttf' => 'application/font-sfnt',
-               );
-
-               self::repairMimetypes($wrongMimetypes);
-
-               $updatedMimetypes = array(
-                       'ttf' => 'application/font-sfnt',
-                       'otf' => 'application/font-sfnt',
-                       'pfb' => 'application/x-font',
-               );
-
-               self::updateMimetypes($updatedMimetypes);
-       }
-
-       private function fixPostscriptMimeType() {
-               $updatedMimetypes = array(
-                       'eps' => 'application/postscript',
-                       'ps' => 'application/postscript',
-               );
-
-               self::updateMimetypes($updatedMimetypes);
-       }
-
-       private function introduceRawMimeType() {
-               $updatedMimetypes = array(
-                       'arw' => 'image/x-dcraw',
-                       'cr2' => 'image/x-dcraw',
-                       'dcr' => 'image/x-dcraw',
-                       'dng' => 'image/x-dcraw',
-                       'erf' => 'image/x-dcraw',
-                       'iiq' => 'image/x-dcraw',
-                       'k25' => 'image/x-dcraw',
-                       'kdc' => 'image/x-dcraw',
-                       'mef' => 'image/x-dcraw',
-                       'nef' => 'image/x-dcraw',
-                       'orf' => 'image/x-dcraw',
-                       'pef' => 'image/x-dcraw',
-                       'raf' => 'image/x-dcraw',
-                       'rw2' => 'image/x-dcraw',
-                       'srf' => 'image/x-dcraw',
-                       'sr2' => 'image/x-dcraw',
-                       'xrf' => 'image/x-dcraw',
-               );
-
-               self::updateMimetypes($updatedMimetypes);
-       }
-
-       private function introduce3dImagesMimeType() {
-               $updatedMimetypes = array(
-                       'jps' => 'image/jpeg',
-                       'mpo' => 'image/jpeg',
-               );
-
-               self::updateMimetypes($updatedMimetypes);
-       }
-
-       private function introduceConfMimeType() {
-               $updatedMimetypes = array(
-                       'conf' => 'text/plain',
-                       'cnf' => 'text/plain',
-               );
-
-               self::updateMimetypes($updatedMimetypes);
-       }
-
-       private function introduceYamlMimeType() {
-               $updatedMimetypes = array(
-                       'yaml' => 'application/yaml',
-                       'yml' => 'application/yaml',
-               );
-
-               self::updateMimetypes($updatedMimetypes);
-       }
-
-       private function introduceJavaMimeType() {
-               $updatedMimetypes = array(
-                       'class' => 'application/java',
-                       'java' => 'text/x-java-source',
-               );
-
-               self::updateMimetypes($updatedMimetypes);
-       }
-
-       private function introduceHppMimeType() {
-               $updatedMimetypes = array(
-                       'hpp' => 'text/x-h',
-               );
-
-               self::updateMimetypes($updatedMimetypes);
-       }
-
-       private function introduceRssMimeType() {
-               $updatedMimetypes = array(
-                       'rss' => 'application/rss+xml',
-               );
-
-               self::updateMimetypes($updatedMimetypes);
-       }
-
-       private function introduceRtfMimeType() {
-               $updatedMimetypes = array(
-                       'rtf' => 'text/rtf',
-               );
-
-               self::updateMimetypes($updatedMimetypes);
-       }
-
-       /**
-        * Fix mime types
-        */
-       public function run() {
-
-               $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()) {
-                               $this->emit('\OC\Repair', 'info', array('Fixed office mime types'));
-                       }
-
-                       if ($this->fixApkMimeType()) {
-                               $this->emit('\OC\Repair', 'info', array('Fixed APK mime type'));
-                       }
-
-                       if ($this->fixFontsMimeTypes()) {
-                               $this->emit('\OC\Repair', 'info', array('Fixed fonts mime types'));
-                       }
-
-                       if ($this->fixPostscriptMimeType()) {
-                               $this->emit('\OC\Repair', 'info', array('Fixed Postscript mime types'));
-                       }
-
-                       if ($this->introduceRawMimeType()) {
-                               $this->emit('\OC\Repair', 'info', array('Fixed Raw mime types'));
-                       }
-
-                       if ($this->introduce3dImagesMimeType()) {
-                               $this->emit('\OC\Repair', 'info', array('Fixed 3D images mime types'));
-                       }
-
-                       if ($this->introduceConfMimeType()) {
-                               $this->emit('\OC\Repair', 'info', array('Fixed Conf/cnf mime types'));
-                       }
-
-                       if ($this->introduceYamlMimeType()) {
-                               $this->emit('\OC\Repair', 'info', array('Fixed Yaml/Yml mime types'));
-                       }
-               }
-
-               // Mimetype updates from #19272
-               if (version_compare($ocVersionFromBeforeUpdate, '8.2.0.8', '<')) {
-                       if ($this->introduceJavaMimeType()) {
-                               $this->emit('\OC\Repair', 'info', array('Fixed java/class mime types'));
-                       }
-
-                       if ($this->introduceHppMimeType()) {
-                               $this->emit('\OC\Repair', 'info', array('Fixed hpp mime type'));
-                       }
-
-                       if ($this->introduceRssMimeType()) {
-                               $this->emit('\OC\Repair', 'info', array('Fixed rss mime type'));
-                       }
-
-                       if ($this->introduceRtfMimeType()) {
-                               $this->emit('\OC\Repair', 'info', array('Fixed rtf mime type'));
-                       }
-               }
-       }
-}
diff --git a/lib/repair/searchlucenetables.php b/lib/repair/searchlucenetables.php
deleted file mode 100644 (file)
index 5ae8a30..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-/**
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-use OC\Hooks\BasicEmitter;
-
-class SearchLuceneTables extends BasicEmitter implements \OC\RepairStep {
-
-       public function getName() {
-               return 'Repair duplicate entries in oc_lucene_status';
-       }
-
-       /**
-        * 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() {
-               if (\OC_DB::tableExists('lucene_status')) {
-                       $this->emit('\OC\Repair', 'info', array('removing duplicate entries from lucene_status'));
-
-                       $connection = \OC_DB::getConnection();
-                       $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 {
-                       $this->emit('\OC\Repair', 'info', array('lucene_status table does not exist -> nothing to do'));
-               }
-       }
-
-}
-
diff --git a/lib/repair/sqliteautoincrement.php b/lib/repair/sqliteautoincrement.php
deleted file mode 100644 (file)
index 70d0ada..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-<?php
-/**
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-use Doctrine\DBAL\Platforms\SqlitePlatform;
-use Doctrine\DBAL\Schema\SchemaException;
-use Doctrine\DBAL\Schema\SchemaDiff;
-use Doctrine\DBAL\Schema\TableDiff;
-use Doctrine\DBAL\Schema\ColumnDiff;
-use OC\Hooks\BasicEmitter;
-
-/**
- * Fixes Sqlite autoincrement by forcing the SQLite table schemas to be
- * altered in order to retrigger SQL schema generation through OCSqlitePlatform.
- */
-class SqliteAutoincrement extends BasicEmitter implements \OC\RepairStep {
-       /**
-        * @var \OC\DB\Connection
-        */
-       protected $connection;
-
-       /**
-        * @param \OC\DB\Connection $connection
-        */
-       public function __construct($connection) {
-               $this->connection = $connection;
-       }
-
-       public function getName() {
-               return 'Repair SQLite autoincrement';
-       }
-
-       /**
-        * Fix mime types
-        */
-       public function run() {
-               if (!$this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
-                       return;
-               }
-
-               $sourceSchema = $this->connection->getSchemaManager()->createSchema();
-
-               $schemaDiff = new SchemaDiff();
-
-               foreach ($sourceSchema->getTables() as $tableSchema) {
-                       $primaryKey = $tableSchema->getPrimaryKey();
-                       if (!$primaryKey) {
-                               continue;
-                       }
-
-                       $columnNames = $primaryKey->getColumns();
-
-                       // add a column diff for every primary key column,
-                       // but do not actually change anything, this will
-                       // force the generation of SQL statements to alter
-                       // those tables, which will then trigger the
-                       // specific SQL code from OCSqlitePlatform
-                       try {
-                               $tableDiff = new TableDiff($tableSchema->getName());
-                               $tableDiff->fromTable = $tableSchema;
-                               foreach ($columnNames as $columnName) {
-                                       $columnSchema = $tableSchema->getColumn($columnName);
-                                       $columnDiff = new ColumnDiff($columnSchema->getName(), $columnSchema);
-                                       $tableDiff->changedColumns[] = $columnDiff;
-                                       $schemaDiff->changedTables[] = $tableDiff;
-                               }
-                       } catch (SchemaException $e) {
-                               // ignore
-                       }
-               }
-
-               $this->connection->beginTransaction();
-               foreach ($schemaDiff->toSql($this->connection->getDatabasePlatform()) as $sql) {
-                       $this->connection->query($sql);
-               }
-               $this->connection->commit();
-       }
-}
-
diff --git a/lib/repair/updatecertificatestore.php b/lib/repair/updatecertificatestore.php
deleted file mode 100644 (file)
index 5fad309..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-<?php
-/**
- * @author Lukas Reschke <lukas@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-use OC\Files\View;
-use OC\Hooks\BasicEmitter;
-use OC\RepairStep;
-use OC\Server;
-use OCP\IConfig;
-
-/**
- * Class UpdateCertificateStore rewrites the user specific certificate store after
- * an update has been performed. This is done because a new root certificate file
- * might have been added.
- *
- * @package OC\Repair
- */
-class UpdateCertificateStore extends BasicEmitter implements RepairStep {
-       /**
-        * FIXME: The certificate manager does only allow specifying the user
-        *        within the constructor. This makes DI impossible.
-        * @var Server
-        */
-       protected $server;
-       /** @var IConfig */
-       protected $config;
-
-       /**
-        * @param Server $server
-        * @param IConfig $config
-        */
-       public function __construct(Server $server,
-                                                               IConfig $config) {
-               $this->server = $server;
-               $this->config = $config;
-       }
-
-       /** {@inheritDoc} */
-       public function getName() {
-               return 'Update user certificate stores with new root certificates';
-       }
-
-       /** {@inheritDoc} */
-       public function run() {
-               $rootView = new View();
-               $dataDirectory = $this->config->getSystemValue('datadirectory', null);
-               if(is_null($dataDirectory)) {
-                       throw new \Exception('No data directory specified');
-               }
-
-               $pathToRootCerts = '/files_external/rootcerts.crt';
-
-               foreach($rootView->getDirectoryContent('', 'httpd/unix-directory') as $fileInfo) {
-                       $uid = trim($fileInfo->getPath(), '/');
-                       if($rootView->file_exists($uid . $pathToRootCerts)) {
-                               // Delete the existing root certificate
-                               $rootView->unlink($uid . $pathToRootCerts);
-
-                               /**
-                                * FIXME: The certificate manager does only allow specifying the user
-                                *        within the constructor. This makes DI impossible.
-                                */
-                               // Regenerate the certificates
-                               $certificateManager = $this->server->getCertificateManager($uid);
-                               $certificateManager->createCertificateBundle();
-                       }
-               }
-       }
-}
diff --git a/lib/repair/updateoutdatedocsids.php b/lib/repair/updateoutdatedocsids.php
deleted file mode 100644 (file)
index 5f6ee02..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-<?php
-/**
- * @author Lukas Reschke <lukas@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\Repair;
-
-use OC\Hooks\BasicEmitter;
-use OC\RepairStep;
-use OCP\IConfig;
-
-/**
- * Class UpdateOutdatedOcsIds is used to update invalid outdated OCS IDs, this is
- * for example the case when an application has had another OCS ID in the past such
- * as for contacts and calendar when apps.owncloud.com migrated to a unified identifier
- * for multiple versions.
- *
- * @package OC\Repair
- */
-class UpdateOutdatedOcsIds extends BasicEmitter implements RepairStep {
-       /** @var IConfig */
-       private $config;
-
-       /**
-        * @param IConfig $config
-        */
-       public function __construct(IConfig $config) {
-               $this->config = $config;
-       }
-
-       /**
-        * {@inheritdoc}
-        */
-       public function getName() {
-               return 'Repair outdated OCS IDs';
-       }
-
-       /**
-        * @param string $appName
-        * @param string $oldId
-        * @param string $newId
-        * @return bool True if updated, false otherwise
-        */
-       public function fixOcsId($appName, $oldId, $newId) {
-               $existingId = $this->config->getAppValue($appName, 'ocsid');
-
-               if($existingId === $oldId) {
-                       $this->config->setAppValue($appName, 'ocsid', $newId);
-                       return true;
-               }
-
-               return false;
-       }
-
-       /**
-        * {@inheritdoc}
-        */
-       public function run() {
-               $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'])) {
-                               $this->emit(
-                                       '\OC\Repair',
-                                       'info',
-                                       [sprintf('Fixed invalid %s OCS id', $appName)]
-                               );
-                       }
-               }
-       }
-}
index 9fb717c4f6347e910d4023388509493da663581a..6443d87a2e508060336773513163a32c08779379 100644 (file)
@@ -90,7 +90,7 @@ class AutoLoader extends TestCase {
 
        public function testLoadCoreNamespaceRepair() {
                $this->assertEquals([
-                       \OC::$SERVERROOT . '/lib/repair/foo/bar.php', 
+                       \OC::$SERVERROOT . '/lib/private/repair/foo/bar.php',
                ], $this->loader->findClass('OC\Repair\Foo\Bar'));
        }
 }