aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/Repair/RepairMimeTypes.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private/Repair/RepairMimeTypes.php')
-rw-r--r--lib/private/Repair/RepairMimeTypes.php285
1 files changed, 223 insertions, 62 deletions
diff --git a/lib/private/Repair/RepairMimeTypes.php b/lib/private/Repair/RepairMimeTypes.php
index 103ce9c13fc..3c9720b9e91 100644
--- a/lib/private/Repair/RepairMimeTypes.php
+++ b/lib/private/Repair/RepairMimeTypes.php
@@ -1,38 +1,48 @@
<?php
/**
- * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
- * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Repair;
+use OC\Migration\NullOutput;
+use OCP\DB\Exception;
+use OCP\DB\IResult;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IAppConfig;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;
class RepairMimeTypes implements IRepairStep {
- /** @var IConfig */
- protected $config;
- /** @var IDBConnection */
- protected $connection;
+ private bool $dryRun = false;
+ private int $changeCount = 0;
/** @var int */
- protected $folderMimeTypeId;
+ protected int $folderMimeTypeId;
- public function __construct(IConfig $config,
- IDBConnection $connection) {
- $this->config = $config;
- $this->connection = $connection;
+ public function __construct(
+ protected IConfig $config,
+ protected IAppConfig $appConfig,
+ protected IDBConnection $connection,
+ ) {
}
- public function getName() {
+ public function getName(): string {
return 'Repair mime types';
}
- private function updateMimetypes($updatedMimetypes) {
+ /**
+ * @throws Exception
+ */
+ private function updateMimetypes($updatedMimetypes): IResult|int|null {
+ if ($this->dryRun) {
+ $this->changeCount += count($updatedMimetypes);
+ return null;
+ }
+
$query = $this->connection->getQueryBuilder();
$query->select('id')
->from('mimetypes')
@@ -50,6 +60,7 @@ class RepairMimeTypes implements IRepairStep {
$update = $this->connection->getQueryBuilder();
$update->update('filecache')
+ ->runAcrossAllShards()
->set('mimetype', $update->createParameter('mimetype'))
->where($update->expr()->neq('mimetype', $update->createParameter('mimetype'), IQueryBuilder::PARAM_INT))
->andWhere($update->expr()->neq('mimetype', $update->createParameter('folder'), IQueryBuilder::PARAM_INT))
@@ -80,16 +91,11 @@ class RepairMimeTypes implements IRepairStep {
return $count;
}
- private function introduceAsciidocType() {
- $updatedMimetypes = [
- 'adoc' => 'text/asciidoc',
- 'asciidoc' => 'text/asciidoc',
- ];
-
- return $this->updateMimetypes($updatedMimetypes);
- }
-
- private function introduceImageTypes() {
+ /**
+ * @throws Exception
+ * @since 12.0.0.14
+ */
+ private function introduceImageTypes(): IResult|int|null {
$updatedMimetypes = [
'jp2' => 'image/jp2',
'webp' => 'image/webp',
@@ -98,7 +104,11 @@ class RepairMimeTypes implements IRepairStep {
return $this->updateMimetypes($updatedMimetypes);
}
- private function introduceWindowsProgramTypes() {
+ /**
+ * @throws Exception
+ * @since 12.0.0.13
+ */
+ private function introduceWindowsProgramTypes(): IResult|int|null {
$updatedMimetypes = [
'htaccess' => 'text/plain',
'bat' => 'application/x-msdos-program',
@@ -108,7 +118,11 @@ class RepairMimeTypes implements IRepairStep {
return $this->updateMimetypes($updatedMimetypes);
}
- private function introduceLocationTypes() {
+ /**
+ * @throws Exception
+ * @since 13.0.0.0
+ */
+ private function introduceLocationTypes(): IResult|int|null {
$updatedMimetypes = [
'gpx' => 'application/gpx+xml',
'kml' => 'application/vnd.google-earth.kml+xml',
@@ -119,7 +133,11 @@ class RepairMimeTypes implements IRepairStep {
return $this->updateMimetypes($updatedMimetypes);
}
- private function introduceInternetShortcutTypes() {
+ /**
+ * @throws Exception
+ * @since 13.0.0.3
+ */
+ private function introduceInternetShortcutTypes(): IResult|int|null {
$updatedMimetypes = [
'url' => 'application/internet-shortcut',
'webloc' => 'application/internet-shortcut'
@@ -128,7 +146,11 @@ class RepairMimeTypes implements IRepairStep {
return $this->updateMimetypes($updatedMimetypes);
}
- private function introduceStreamingTypes() {
+ /**
+ * @throws Exception
+ * @since 13.0.0.6
+ */
+ private function introduceStreamingTypes(): IResult|int|null {
$updatedMimetypes = [
'm3u' => 'audio/mpegurl',
'm3u8' => 'audio/mpegurl',
@@ -138,7 +160,11 @@ class RepairMimeTypes implements IRepairStep {
return $this->updateMimetypes($updatedMimetypes);
}
- private function introduceVisioTypes() {
+ /**
+ * @throws Exception
+ * @since 14.0.0.8
+ */
+ private function introduceVisioTypes(): IResult|int|null {
$updatedMimetypes = [
'vsdm' => 'application/vnd.visio',
'vsdx' => 'application/vnd.visio',
@@ -151,7 +177,11 @@ class RepairMimeTypes implements IRepairStep {
return $this->updateMimetypes($updatedMimetypes);
}
- private function introduceComicbookTypes() {
+ /**
+ * @throws Exception
+ * @since 14.0.0.10
+ */
+ private function introduceComicbookTypes(): IResult|int|null {
$updatedMimetypes = [
'cb7' => 'application/comicbook+7z',
'cba' => 'application/comicbook+ace',
@@ -164,7 +194,11 @@ class RepairMimeTypes implements IRepairStep {
return $this->updateMimetypes($updatedMimetypes);
}
- private function introduceOpenDocumentTemplates() {
+ /**
+ * @throws Exception
+ * @since 20.0.0.5
+ */
+ private function introduceOpenDocumentTemplates(): IResult|int|null {
$updatedMimetypes = [
'ott' => 'application/vnd.oasis.opendocument.text-template',
'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
@@ -175,35 +209,64 @@ class RepairMimeTypes implements IRepairStep {
return $this->updateMimetypes($updatedMimetypes);
}
- private function introduceFlatOpenDocumentType() {
+ /**
+ * @throws Exception
+ * @since 21.0.0.7
+ */
+ private function introduceOrgModeType(): IResult|int|null {
$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",
+ 'org' => 'text/org'
];
return $this->updateMimetypes($updatedMimetypes);
}
- private function introduceOrgModeType() {
+ /**
+ * @throws Exception
+ * @since 23.0.0.2
+ */
+ private function introduceFlatOpenDocumentType(): IResult|int|null {
$updatedMimetypes = [
- 'org' => 'text/org'
+ '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->updateMimetypes($updatedMimetypes);
}
- private function introduceOnlyofficeFormType() {
+ /**
+ * @throws Exception
+ * @since 25.0.0.2
+ */
+ private function introduceOnlyofficeFormType(): IResult|int|null {
$updatedMimetypes = [
- "oform" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform",
- "docxf" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf",
+ 'oform' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform',
+ 'docxf' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf',
];
return $this->updateMimetypes($updatedMimetypes);
}
- private function introduceEnhancedMetafileFormatType() {
+ /**
+ * @throws Exception
+ * @since 26.0.0.1
+ */
+ private function introduceAsciidocType(): IResult|int|null {
+ $updatedMimetypes = [
+ 'adoc' => 'text/asciidoc',
+ 'asciidoc' => 'text/asciidoc',
+ ];
+
+ return $this->updateMimetypes($updatedMimetypes);
+ }
+
+ /**
+ * @throws Exception
+ * @since 28.0.0.5
+ */
+ private function introduceEnhancedMetafileFormatType(): IResult|int|null {
$updatedMimetypes = [
'emf' => 'image/emf',
];
@@ -211,7 +274,11 @@ class RepairMimeTypes implements IRepairStep {
return $this->updateMimetypes($updatedMimetypes);
}
- private function introduceEmlAndMsgFormatType() {
+ /**
+ * @throws Exception
+ * @since 29.0.0.2
+ */
+ private function introduceEmlAndMsgFormatType(): IResult|int|null {
$updatedMimetypes = [
'eml' => 'message/rfc822',
'msg' => 'application/vnd.ms-outlook',
@@ -220,7 +287,11 @@ class RepairMimeTypes implements IRepairStep {
return $this->updateMimetypes($updatedMimetypes);
}
- private function introduceAacAudioType() {
+ /**
+ * @throws Exception
+ * @since 29.0.0.6
+ */
+ private function introduceAacAudioType(): IResult|int|null {
$updatedMimetypes = [
'aac' => 'audio/aac',
];
@@ -228,7 +299,11 @@ class RepairMimeTypes implements IRepairStep {
return $this->updateMimetypes($updatedMimetypes);
}
- private function introduceReStructuredTextFormatType() {
+ /**
+ * @throws Exception
+ * @since 29.0.10
+ */
+ private function introduceReStructuredTextFormatType(): IResult|int|null {
$updatedMimetypes = [
'rst' => 'text/x-rst',
];
@@ -237,76 +312,162 @@ class RepairMimeTypes implements IRepairStep {
}
/**
+ * @throws Exception
+ * @since 30.0.0
+ */
+ private function introduceExcalidrawType(): IResult|int|null {
+ $updatedMimetypes = [
+ 'excalidraw' => 'application/vnd.excalidraw+json',
+ ];
+
+ return $this->updateMimetypes($updatedMimetypes);
+ }
+
+
+ /**
+ * @throws Exception
+ * @since 31.0.0
+ */
+ private function introduceZstType(): IResult|int|null {
+ $updatedMimetypes = [
+ 'zst' => 'application/zstd',
+ 'nfo' => 'text/x-nfo',
+ ];
+
+ return $this->updateMimetypes($updatedMimetypes);
+ }
+
+ /**
+ * @throws Exception
+ * @since 32.0.0
+ */
+ private function introduceMusicxmlType(): IResult|int|null {
+ $updatedMimetypes = [
+ 'mxl' => 'application/vnd.recordare.musicxml',
+ 'musicxml' => 'application/vnd.recordare.musicxml+xml',
+ ];
+
+ return $this->updateMimetypes($updatedMimetypes);
+ }
+
+
+
+ /**
+ * Check if there are any migrations available
+ *
+ * @throws Exception
+ */
+ public function migrationsAvailable(): bool {
+ $this->dryRun = true;
+ $this->run(new NullOutput());
+ $this->dryRun = false;
+ return $this->changeCount > 0;
+ }
+
+ /**
+ * Get the current mimetype version
+ */
+ private function getMimeTypeVersion(): string {
+ $serverVersion = $this->config->getSystemValueString('version', '0.0.0');
+ // 29.0.0.10 is the last version with a mimetype migration before it was moved to a separate version number
+ if (version_compare($serverVersion, '29.0.0.10', '>')) {
+ return $this->appConfig->getValueString('files', 'mimetype_version', '29.0.0.10');
+ }
+
+ return $serverVersion;
+ }
+
+ /**
* Fix mime types
+ *
+ * @throws Exception
*/
- public function run(IOutput $out) {
- $ocVersionFromBeforeUpdate = $this->config->getSystemValueString('version', '0.0.0');
+ public function run(IOutput $out): void {
+ $serverVersion = $this->config->getSystemValueString('version', '0.0.0');
+ $mimeTypeVersion = $this->getMimeTypeVersion();
// NOTE TO DEVELOPERS: when adding new mime types, please make sure to
// add a version comparison to avoid doing it every time
+ // PLEASE ALSO KEEP THE LIST SORTED BY VERSION NUMBER
- if (version_compare($ocVersionFromBeforeUpdate, '12.0.0.14', '<') && $this->introduceImageTypes()) {
+ if (version_compare($mimeTypeVersion, '12.0.0.14', '<') && $this->introduceImageTypes()) {
$out->info('Fixed image mime types');
}
- if (version_compare($ocVersionFromBeforeUpdate, '12.0.0.13', '<') && $this->introduceWindowsProgramTypes()) {
+ if (version_compare($mimeTypeVersion, '12.0.0.13', '<') && $this->introduceWindowsProgramTypes()) {
$out->info('Fixed windows program mime types');
}
- if (version_compare($ocVersionFromBeforeUpdate, '13.0.0.0', '<') && $this->introduceLocationTypes()) {
+ if (version_compare($mimeTypeVersion, '13.0.0.0', '<') && $this->introduceLocationTypes()) {
$out->info('Fixed geospatial mime types');
}
- if (version_compare($ocVersionFromBeforeUpdate, '13.0.0.3', '<') && $this->introduceInternetShortcutTypes()) {
+ if (version_compare($mimeTypeVersion, '13.0.0.3', '<') && $this->introduceInternetShortcutTypes()) {
$out->info('Fixed internet-shortcut mime types');
}
- if (version_compare($ocVersionFromBeforeUpdate, '13.0.0.6', '<') && $this->introduceStreamingTypes()) {
+ if (version_compare($mimeTypeVersion, '13.0.0.6', '<') && $this->introduceStreamingTypes()) {
$out->info('Fixed streaming mime types');
}
- if (version_compare($ocVersionFromBeforeUpdate, '14.0.0.8', '<') && $this->introduceVisioTypes()) {
+ if (version_compare($mimeTypeVersion, '14.0.0.8', '<') && $this->introduceVisioTypes()) {
$out->info('Fixed visio mime types');
}
- if (version_compare($ocVersionFromBeforeUpdate, '14.0.0.10', '<') && $this->introduceComicbookTypes()) {
+ if (version_compare($mimeTypeVersion, '14.0.0.10', '<') && $this->introduceComicbookTypes()) {
$out->info('Fixed comicbook mime types');
}
- if (version_compare($ocVersionFromBeforeUpdate, '20.0.0.5', '<') && $this->introduceOpenDocumentTemplates()) {
+ if (version_compare($mimeTypeVersion, '20.0.0.5', '<') && $this->introduceOpenDocumentTemplates()) {
$out->info('Fixed OpenDocument template mime types');
}
- if (version_compare($ocVersionFromBeforeUpdate, '21.0.0.7', '<') && $this->introduceOrgModeType()) {
+ if (version_compare($mimeTypeVersion, '21.0.0.7', '<') && $this->introduceOrgModeType()) {
$out->info('Fixed orgmode mime types');
}
- if (version_compare($ocVersionFromBeforeUpdate, '23.0.0.2', '<') && $this->introduceFlatOpenDocumentType()) {
+ if (version_compare($mimeTypeVersion, '23.0.0.2', '<') && $this->introduceFlatOpenDocumentType()) {
$out->info('Fixed Flat OpenDocument mime types');
}
- if (version_compare($ocVersionFromBeforeUpdate, '25.0.0.2', '<') && $this->introduceOnlyofficeFormType()) {
+ if (version_compare($mimeTypeVersion, '25.0.0.2', '<') && $this->introduceOnlyofficeFormType()) {
$out->info('Fixed ONLYOFFICE Forms OpenXML mime types');
}
- if (version_compare($ocVersionFromBeforeUpdate, '26.0.0.1', '<') && $this->introduceAsciidocType()) {
+ if (version_compare($mimeTypeVersion, '26.0.0.1', '<') && $this->introduceAsciidocType()) {
$out->info('Fixed AsciiDoc mime types');
}
- if (version_compare($ocVersionFromBeforeUpdate, '28.0.0.5', '<') && $this->introduceEnhancedMetafileFormatType()) {
+ if (version_compare($mimeTypeVersion, '28.0.0.5', '<') && $this->introduceEnhancedMetafileFormatType()) {
$out->info('Fixed Enhanced Metafile Format mime types');
}
- if (version_compare($ocVersionFromBeforeUpdate, '29.0.0.2', '<') && $this->introduceEmlAndMsgFormatType()) {
+ if (version_compare($mimeTypeVersion, '29.0.0.2', '<') && $this->introduceEmlAndMsgFormatType()) {
$out->info('Fixed eml and msg mime type');
}
- if (version_compare($ocVersionFromBeforeUpdate, '29.0.0.6', '<') && $this->introduceAacAudioType()) {
+ if (version_compare($mimeTypeVersion, '29.0.0.6', '<') && $this->introduceAacAudioType()) {
$out->info('Fixed aac mime type');
}
- if (version_compare($ocVersionFromBeforeUpdate, '29.0.0.10', '<') && $this->introduceReStructuredTextFormatType()) {
+ if (version_compare($mimeTypeVersion, '29.0.0.10', '<') && $this->introduceReStructuredTextFormatType()) {
$out->info('Fixed ReStructured Text mime type');
}
+
+ if (version_compare($mimeTypeVersion, '30.0.0.0', '<') && $this->introduceExcalidrawType()) {
+ $out->info('Fixed Excalidraw mime type');
+ }
+
+ if (version_compare($mimeTypeVersion, '31.0.0.0', '<') && $this->introduceZstType()) {
+ $out->info('Fixed zst mime type');
+ }
+
+ if (version_compare($mimeTypeVersion, '32.0.0.0', '<') && $this->introduceMusicxmlType()) {
+ $out->info('Fixed musicxml mime type');
+ }
+
+ if (!$this->dryRun) {
+ $this->appConfig->setValueString('files', 'mimetype_version', $serverVersion);
+ }
}
}