Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
feat: Move mimetype repair to background jobs
Signed-off-by: Julius Härtl <[email protected]>
  • Loading branch information
juliusknorr committed Jul 10, 2023
commit a617f1ef3437934265b74a4a97659e68fedf4368
2 changes: 2 additions & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -1499,6 +1499,7 @@
'OC\\RepairException' => $baseDir . '/lib/private/RepairException.php',
'OC\\Repair\\AddBruteForceCleanupJob' => $baseDir . '/lib/private/Repair/AddBruteForceCleanupJob.php',
'OC\\Repair\\AddCleanupUpdaterBackupsJob' => $baseDir . '/lib/private/Repair/AddCleanupUpdaterBackupsJob.php',
'OC\\Repair\\AddRepairMimeTypeJob' => $baseDir . '/lib/private/Repair/AddRepairMimeTypeJob.php',
'OC\\Repair\\CleanTags' => $baseDir . '/lib/private/Repair/CleanTags.php',
'OC\\Repair\\CleanUpAbandonedApps' => $baseDir . '/lib/private/Repair/CleanUpAbandonedApps.php',
'OC\\Repair\\ClearFrontendCaches' => $baseDir . '/lib/private/Repair/ClearFrontendCaches.php',
Expand Down Expand Up @@ -1540,6 +1541,7 @@
'OC\\Repair\\RemoveLinkShares' => $baseDir . '/lib/private/Repair/RemoveLinkShares.php',
'OC\\Repair\\RepairDavShares' => $baseDir . '/lib/private/Repair/RepairDavShares.php',
'OC\\Repair\\RepairInvalidShares' => $baseDir . '/lib/private/Repair/RepairInvalidShares.php',
'OC\\Repair\\RepairMimeTypeJob' => $baseDir . '/lib/private/Repair/RepairMimeTypeJob.php',
'OC\\Repair\\RepairMimeTypes' => $baseDir . '/lib/private/Repair/RepairMimeTypes.php',
'OC\\Repair\\SqliteAutoincrement' => $baseDir . '/lib/private/Repair/SqliteAutoincrement.php',
'OC\\RichObjectStrings\\Validator' => $baseDir . '/lib/private/RichObjectStrings/Validator.php',
Expand Down
2 changes: 2 additions & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -1532,6 +1532,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\RepairException' => __DIR__ . '/../../..' . '/lib/private/RepairException.php',
'OC\\Repair\\AddBruteForceCleanupJob' => __DIR__ . '/../../..' . '/lib/private/Repair/AddBruteForceCleanupJob.php',
'OC\\Repair\\AddCleanupUpdaterBackupsJob' => __DIR__ . '/../../..' . '/lib/private/Repair/AddCleanupUpdaterBackupsJob.php',
'OC\\Repair\\AddRepairMimeTypeJob' => __DIR__ . '/../../..' . '/lib/private/Repair/AddRepairMimeTypeJob.php',
'OC\\Repair\\CleanTags' => __DIR__ . '/../../..' . '/lib/private/Repair/CleanTags.php',
'OC\\Repair\\CleanUpAbandonedApps' => __DIR__ . '/../../..' . '/lib/private/Repair/CleanUpAbandonedApps.php',
'OC\\Repair\\ClearFrontendCaches' => __DIR__ . '/../../..' . '/lib/private/Repair/ClearFrontendCaches.php',
Expand Down Expand Up @@ -1573,6 +1574,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Repair\\RemoveLinkShares' => __DIR__ . '/../../..' . '/lib/private/Repair/RemoveLinkShares.php',
'OC\\Repair\\RepairDavShares' => __DIR__ . '/../../..' . '/lib/private/Repair/RepairDavShares.php',
'OC\\Repair\\RepairInvalidShares' => __DIR__ . '/../../..' . '/lib/private/Repair/RepairInvalidShares.php',
'OC\\Repair\\RepairMimeTypeJob' => __DIR__ . '/../../..' . '/lib/private/Repair/RepairMimeTypeJob.php',
'OC\\Repair\\RepairMimeTypes' => __DIR__ . '/../../..' . '/lib/private/Repair/RepairMimeTypes.php',
'OC\\Repair\\SqliteAutoincrement' => __DIR__ . '/../../..' . '/lib/private/Repair/SqliteAutoincrement.php',
'OC\\RichObjectStrings\\Validator' => __DIR__ . '/../../..' . '/lib/private/RichObjectStrings/Validator.php',
Expand Down
8 changes: 5 additions & 3 deletions lib/private/Repair.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
*/
namespace OC;

use OC\Repair\AddRepairMimeTypeJob;
use OC\Repair\CleanUpAbandonedApps;
use OCP\AppFramework\QueryException;
use OCP\AppFramework\Utility\ITimeFactory;
Expand Down Expand Up @@ -174,7 +175,7 @@ public function addStep($repairStep) {
public static function getRepairSteps(): array {
return [
new Collation(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class), \OC::$server->getDatabaseConnection(), false),
new RepairMimeTypes(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()),
\OCP\Server::get(AddRepairMimeTypeJob::class),
new CleanTags(\OC::$server->getDatabaseConnection(), \OC::$server->getUserManager()),
new RepairInvalidShares(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()),
new MoveUpdaterStepFile(\OC::$server->getConfig()),
Expand Down Expand Up @@ -221,8 +222,9 @@ public static function getRepairSteps(): array {
*/
public static function getExpensiveRepairSteps() {
return [
new OldGroupMembershipShares(\OC::$server->getDatabaseConnection(), \OC::$server->getGroupManager()),
\OC::$server->get(ValidatePhoneNumber::class),
\OCP\Server::get(OldGroupMembershipShares::class),
\OCP\Server::get(ValidatePhoneNumber::class),
\OCP\Server::get(RepairMimeTypes::class),
];
}

Expand Down
257 changes: 257 additions & 0 deletions lib/private/Repair/AddRepairMimeTypeJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Arthur Schiwon <[email protected]>
* @author Christoph Wurst <[email protected]>
* @author Joas Schilling <[email protected]>
* @author Julius Härtl <[email protected]>
* @author Morris Jobke <[email protected]>
* @author nik gaffney <[email protected]>
* @author Olivier Paroz <[email protected]>
* @author Rello <[email protected]>
* @author Roeland Jago Douma <[email protected]>
* @author Stefan Weil <[email protected]>
* @author Thomas Ebert <[email protected]>
* @author Thomas Müller <[email protected]>
* @author Vincent Petry <[email protected]>
*
* @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 OCP\BackgroundJob\IJobList;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;

class AddRepairMimeTypeJob implements IRepairStep {
protected $config;
protected $connection;
protected $jobList;
public function __construct(IConfig $config,
IDBConnection $connection, IJobList $jobList) {
$this->config = $config;
$this->connection = $connection;
$this->jobList = $jobList;
}

public function getName() {
return 'Repair mime types through scheduling background jobs';
}

private function scheduleMimeTypeUpdateJob(array $updatedMimetypes): int {
$qb = $this->connection->getQueryBuilder();
$result = $qb
->select('numeric_id')
->from('storages')
->execute();

$jobCount = 0;
while ($row = $result->fetch()) {
$this->jobList->add(RepairMimeTypeJob::class, [
'storageId' => $row['numeric_id'],
'mimetypes' => $updatedMimetypes,
]);
$jobCount++;
}

return $jobCount;
}

private function introduceAsciidocType() {
$updatedMimetypes = [
'adoc' => 'text/asciidoc',
'asciidoc' => 'text/asciidoc',
];

return $this->scheduleMimeTypeUpdateJob($updatedMimetypes);
}

private function introduceImageTypes() {
$updatedMimetypes = [
'jp2' => 'image/jp2',
'webp' => 'image/webp',
];

return $this->scheduleMimeTypeUpdateJob($updatedMimetypes);
}

private function introduceWindowsProgramTypes() {
$updatedMimetypes = [
'htaccess' => 'text/plain',
'bat' => 'application/x-msdos-program',
'cmd' => 'application/cmd',
];

return $this->scheduleMimeTypeUpdateJob($updatedMimetypes);
}

private function introduceLocationTypes() {
$updatedMimetypes = [
'gpx' => 'application/gpx+xml',
'kml' => 'application/vnd.google-earth.kml+xml',
'kmz' => 'application/vnd.google-earth.kmz',
'tcx' => 'application/vnd.garmin.tcx+xml',
];

return $this->scheduleMimeTypeUpdateJob($updatedMimetypes);
}

private function introduceInternetShortcutTypes() {
$updatedMimetypes = [
'url' => 'application/internet-shortcut',
'webloc' => 'application/internet-shortcut'
];

return $this->scheduleMimeTypeUpdateJob($updatedMimetypes);
}

private function introduceStreamingTypes() {
$updatedMimetypes = [
'm3u' => 'audio/mpegurl',
'm3u8' => 'audio/mpegurl',
'pls' => 'audio/x-scpls'
];

return $this->scheduleMimeTypeUpdateJob($updatedMimetypes);
}

private function introduceVisioTypes() {
$updatedMimetypes = [
'vsdm' => 'application/vnd.visio',
'vsdx' => 'application/vnd.visio',
'vssm' => 'application/vnd.visio',
'vssx' => 'application/vnd.visio',
'vstm' => 'application/vnd.visio',
'vstx' => 'application/vnd.visio',
];

return $this->scheduleMimeTypeUpdateJob($updatedMimetypes);
}

private function introduceComicbookTypes() {
$updatedMimetypes = [
'cb7' => 'application/comicbook+7z',
'cba' => 'application/comicbook+ace',
'cbr' => 'application/comicbook+rar',
'cbt' => 'application/comicbook+tar',
'cbtc' => 'application/comicbook+truecrypt',
'cbz' => 'application/comicbook+zip',
];

return $this->scheduleMimeTypeUpdateJob($updatedMimetypes);
}

private function introduceOpenDocumentTemplates() {
$updatedMimetypes = [
'ott' => 'application/vnd.oasis.opendocument.text-template',
'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
'otp' => 'application/vnd.oasis.opendocument.presentation-template',
'otg' => 'application/vnd.oasis.opendocument.graphics-template',
];

return $this->scheduleMimeTypeUpdateJob($updatedMimetypes);
}

private function introduceFlatOpenDocumentType() {
$updatedMimetypes = [
"fodt" => "application/vnd.oasis.opendocument.text-flat-xml",
"fods" => "application/vnd.oasis.opendocument.spreadsheet-flat-xml",
"fodg" => "application/vnd.oasis.opendocument.graphics-flat-xml",
"fodp" => "application/vnd.oasis.opendocument.presentation-flat-xml",
];

return $this->scheduleMimeTypeUpdateJob($updatedMimetypes);
}

private function introduceOrgModeType() {
$updatedMimetypes = [
'org' => 'text/org'
];

return $this->scheduleMimeTypeUpdateJob($updatedMimetypes);
}

private function introduceOnlyofficeFormType() {
$updatedMimetypes = [
"oform" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform",
"docxf" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf",
];

return $this->scheduleMimeTypeUpdateJob($updatedMimetypes);
}


/**
* Fix mime types
*/
public function run(IOutput $out) {

Check failure

Code scanning / Psalm

ParamNameMismatch

Argument 1 of OC\Repair\AddRepairMimeTypeJob::run has wrong name $out, expecting $output as defined by OCP\Migration\IRepairStep::run
$ocVersionFromBeforeUpdate = $this->config->getSystemValueString('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

if (version_compare($ocVersionFromBeforeUpdate, '12.0.0.14', '<') && $this->introduceImageTypes()) {
$out->info('Fixed image mime types');
}

if (version_compare($ocVersionFromBeforeUpdate, '12.0.0.13', '<') && $this->introduceWindowsProgramTypes()) {
$out->info('Fixed windows program mime types');
}

if (version_compare($ocVersionFromBeforeUpdate, '13.0.0.0', '<') && $this->introduceLocationTypes()) {
$out->info('Fixed geospatial mime types');
}

if (version_compare($ocVersionFromBeforeUpdate, '13.0.0.3', '<') && $this->introduceInternetShortcutTypes()) {
$out->info('Fixed internet-shortcut mime types');
}

if (version_compare($ocVersionFromBeforeUpdate, '13.0.0.6', '<') && $this->introduceStreamingTypes()) {
$out->info('Fixed streaming mime types');
}

if (version_compare($ocVersionFromBeforeUpdate, '14.0.0.8', '<') && $this->introduceVisioTypes()) {
$out->info('Fixed visio mime types');
}

if (version_compare($ocVersionFromBeforeUpdate, '14.0.0.10', '<') && $this->introduceComicbookTypes()) {
$out->info('Fixed comicbook mime types');
}

if (version_compare($ocVersionFromBeforeUpdate, '20.0.0.5', '<') && $this->introduceOpenDocumentTemplates()) {
$out->info('Fixed OpenDocument template mime types');
}

if (version_compare($ocVersionFromBeforeUpdate, '21.0.0.7', '<') && $this->introduceOrgModeType()) {
$out->info('Fixed orgmode mime types');
}

if (version_compare($ocVersionFromBeforeUpdate, '23.0.0.2', '<') && $this->introduceFlatOpenDocumentType()) {
$out->info('Fixed Flat OpenDocument mime types');
}

if (version_compare($ocVersionFromBeforeUpdate, '25.0.0.2', '<') && $this->introduceOnlyofficeFormType()) {
$out->info('Fixed ONLYOFFICE Forms OpenXML mime types');
}

if (version_compare($ocVersionFromBeforeUpdate, '26.0.0.1', '<') && $this->introduceAsciidocType()) {
$out->info('Fixed AsciiDoc mime types');
}
}
}
75 changes: 75 additions & 0 deletions lib/private/Repair/RepairMimeTypeJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

namespace OC\Repair;

use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\QueuedJob;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use Psr\Log\LoggerInterface;

class RepairMimeTypeJob extends QueuedJob {
private IDBConnection $connection;
private LoggerInterface $logger;

public function __construct(ITimeFactory $time, IDBConnection $connection, LoggerInterface $logger) {
parent::__construct($time);
$this->connection = $connection;
$this->logger = $logger;
}

protected function run($argument) {
$storageId = (int)$argument['storageId'];
$mimetypes = $argument['mimetypes'];
$this->updateMimetypesForStorage($storageId, $mimetypes);
}

private function updateMimetypesForStorage(int $storageId, array $updatedMimetypes) {
$query = $this->connection->getQueryBuilder();
$query->select('id')
->from('mimetypes')
->where($query->expr()->eq('mimetype', $query->createParameter('mimetype'), IQueryBuilder::PARAM_INT));
$insert = $this->connection->getQueryBuilder();
$insert->insert('mimetypes')
->setValue('mimetype', $insert->createParameter('mimetype'));

if (empty($this->folderMimeTypeId)) {
$query->setParameter('mimetype', 'httpd/unix-directory');
$result = $query->execute();
$this->folderMimeTypeId = (int)$result->fetchOne();

Check failure

Code scanning / Psalm

UndefinedThisPropertyAssignment

Instance property OC\Repair\RepairMimeTypeJob::$folderMimeTypeId is not defined
$result->closeCursor();
}

$update = $this->connection->getQueryBuilder();
$update->update('filecache')
->set('mimetype', $update->createParameter('mimetype'))
->where($update->expr()->eq('storage', $update->createParameter('storage'), IQueryBuilder::PARAM_INT))
->andWhere($update->expr()->neq('mimetype', $update->createParameter('mimetype'), IQueryBuilder::PARAM_INT))
->andWhere($update->expr()->neq('mimetype', $update->createParameter('folder'), IQueryBuilder::PARAM_INT))
->andWhere($update->expr()->iLike('name', $update->createParameter('name')))
->setParameter('folder', $this->folderMimeTypeId)
->setParameter('storage', $storageId);

$count = 0;
foreach ($updatedMimetypes as $extension => $mimetype) {
// get target mimetype id
$query->setParameter('mimetype', $mimetype);
$result = $query->execute();
$mimetypeId = (int)$result->fetchOne();
$result->closeCursor();

if (!$mimetypeId) {
// insert mimetype
$insert->setParameter('mimetype', $mimetype);
$insert->execute();
$mimetypeId = $insert->getLastInsertId();
}

// change mimetype for files with x extension
$update->setParameter('mimetype', $mimetypeId)
->setParameter('name', '%' . $this->connection->escapeLikeParameter('.' . $extension));
$count = $update->execute();
$this->logger->info('Updated storage ' . $storageId . ' with ' . $count . ' file entry mimetypes for ' . $extension . ' to ' . $mimetype);
}
}
}