diff options
author | Christoph Wurst <ChristophWurst@users.noreply.github.com> | 2023-11-16 19:48:06 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-16 19:48:06 +0100 |
commit | c9dc377ebcdda91d2e471a3c26c72ed94fecb9aa (patch) | |
tree | d36483514f248638c9e61d8ccd5da034985810d9 | |
parent | 23605d60dd7f1f4fca8609885f00036281f49ec6 (diff) | |
parent | 475dd6035435e326b0ffab6e74f961757896b97d (diff) | |
download | nextcloud-server-c9dc377ebcdda91d2e471a3c26c72ed94fecb9aa.tar.gz nextcloud-server-c9dc377ebcdda91d2e471a3c26c72ed94fecb9aa.zip |
Merge pull request #41395 from nextcloud/hello-emf
feat: add preview provider for emf files based on office
-rw-r--r-- | config/config.sample.php | 11 | ||||
-rw-r--r-- | core/js/mimetypelist.js | 3 | ||||
-rw-r--r-- | lib/composer/composer/autoload_classmap.php | 1 | ||||
-rw-r--r-- | lib/composer/composer/autoload_static.php | 1 | ||||
-rw-r--r-- | lib/private/Preview/EMF.php | 33 | ||||
-rw-r--r-- | lib/private/Preview/Office.php | 60 | ||||
-rw-r--r-- | lib/private/PreviewManager.php | 60 | ||||
-rw-r--r-- | lib/private/Repair/RepairMimeTypes.php | 11 | ||||
-rw-r--r-- | resources/config/mimetypealiases.dist.json | 3 | ||||
-rw-r--r-- | resources/config/mimetypemapping.dist.json | 1 | ||||
-rw-r--r-- | tests/data/integritycheck/mimetypeListModified/core/js/mimetypelist.js | 1 | ||||
-rw-r--r-- | tests/data/integritycheck/mimetypeListModified/core/signature.json | 4 |
12 files changed, 131 insertions, 58 deletions
diff --git a/config/config.sample.php b/config/config.sample.php index ab86feedb85..27b99636a22 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -1237,14 +1237,6 @@ $CONFIG = [ * Defaults to ``''`` (empty string) */ 'preview_libreoffice_path' => '/usr/bin/libreoffice', -/** - * Use this if LibreOffice/OpenOffice requires additional arguments. - * - * Defaults to ``''`` (empty string) - */ -'preview_office_cl_parameters' => - ' --headless --nologo --nofirststartwizard --invisible --norestore '. - '--convert-to png --outdir ', /** * custom path for ffmpeg binary @@ -1285,6 +1277,7 @@ $CONFIG = [ * - ``OC\Preview\StarOffice`` * - ``OC\Preview\SVG`` * - ``OC\Preview\TIFF`` + * - ``OC\Preview\EMF`` * * * Defaults to the following providers: @@ -1945,7 +1938,7 @@ $CONFIG = [ * * Example for windows systems: ``array('?', '<', '>', ':', '*', '|', '"', chr(0), "\n", "\r")`` * see https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits - * + * * Defaults to ``array()`` */ 'forbidden_chars' => [], diff --git a/core/js/mimetypelist.js b/core/js/mimetypelist.js index a2ca2c23d07..2e87ce756ba 100644 --- a/core/js/mimetypelist.js +++ b/core/js/mimetypelist.js @@ -113,7 +113,8 @@ OC.MimeTypeList={ "application/vnd.xmind.workbook": "mindmap", "image/targa": "image/tga", "application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform": "x-office/form", - "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf": "x-office/form-template" + "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf": "x-office/form-template", + "image/x-emf": "image/emf" }, files: [ "application", diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 39085325067..39a3f2638f4 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -1540,6 +1540,7 @@ return array( 'OC\\Preview\\BackgroundCleanupJob' => $baseDir . '/lib/private/Preview/BackgroundCleanupJob.php', 'OC\\Preview\\Bitmap' => $baseDir . '/lib/private/Preview/Bitmap.php', 'OC\\Preview\\Bundled' => $baseDir . '/lib/private/Preview/Bundled.php', + 'OC\\Preview\\EMF' => $baseDir . '/lib/private/Preview/EMF.php', 'OC\\Preview\\Font' => $baseDir . '/lib/private/Preview/Font.php', 'OC\\Preview\\GIF' => $baseDir . '/lib/private/Preview/GIF.php', 'OC\\Preview\\Generator' => $baseDir . '/lib/private/Preview/Generator.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 498f4d8c0b1..4a09a5db6da 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -1573,6 +1573,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Preview\\BackgroundCleanupJob' => __DIR__ . '/../../..' . '/lib/private/Preview/BackgroundCleanupJob.php', 'OC\\Preview\\Bitmap' => __DIR__ . '/../../..' . '/lib/private/Preview/Bitmap.php', 'OC\\Preview\\Bundled' => __DIR__ . '/../../..' . '/lib/private/Preview/Bundled.php', + 'OC\\Preview\\EMF' => __DIR__ . '/../../..' . '/lib/private/Preview/EMF.php', 'OC\\Preview\\Font' => __DIR__ . '/../../..' . '/lib/private/Preview/Font.php', 'OC\\Preview\\GIF' => __DIR__ . '/../../..' . '/lib/private/Preview/GIF.php', 'OC\\Preview\\Generator' => __DIR__ . '/../../..' . '/lib/private/Preview/Generator.php', diff --git a/lib/private/Preview/EMF.php b/lib/private/Preview/EMF.php new file mode 100644 index 00000000000..2b5f40e66af --- /dev/null +++ b/lib/private/Preview/EMF.php @@ -0,0 +1,33 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright 2023 Daniel Kesselberg <mail@danielkesselberg.de> + * + * @author Daniel Kesselberg <mail@danielkesselberg.de> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Preview; + +class EMF extends Office { + public function getMimeType(): string { + return '/image\/emf/'; + } +} diff --git a/lib/private/Preview/Office.php b/lib/private/Preview/Office.php index 3ba7c5a21a0..68499a6fea6 100644 --- a/lib/private/Preview/Office.php +++ b/lib/private/Preview/Office.php @@ -31,7 +31,8 @@ namespace OC\Preview; use OCP\Files\File; use OCP\Files\FileInfo; use OCP\IImage; -use Psr\Log\LoggerInterface; +use OCP\ITempManager; +use OCP\Server; abstract class Office extends ProviderV2 { /** @@ -49,51 +50,60 @@ abstract class Office extends ProviderV2 { return null; } - $absPath = $this->getLocalFile($file); - - $tmpDir = \OC::$server->getTempManager()->getTempBaseDir(); + $tempManager = Server::get(ITempManager::class); - $defaultParameters = ' -env:UserInstallation=file://' . escapeshellarg($tmpDir . '/owncloud-' . \OC_Util::getInstanceId() . '/') . ' --headless --nologo --nofirststartwizard --invisible --norestore --convert-to png --outdir '; - $clParameters = \OC::$server->getConfig()->getSystemValue('preview_office_cl_parameters', $defaultParameters); + // The file to generate the preview for. + $absPath = $this->getLocalFile($file); - $cmd = $this->options['officeBinary'] . $clParameters . escapeshellarg($tmpDir) . ' ' . escapeshellarg($absPath); + // The destination for the LibreOffice user profile. + // LibreOffice can rune once per user profile and therefore instance id and file id are included. + $profile = $tempManager->getTemporaryFolder( + 'nextcloud-office-profile-' . \OC_Util::getInstanceId() . '-' . $file->getId() + ); - exec($cmd, $output, $returnCode); + // The destination for the LibreOffice convert result. + $outdir = $tempManager->getTemporaryFolder( + 'nextcloud-office-preview-' . \OC_Util::getInstanceId() . '-' . $file->getId() + ); - if ($returnCode !== 0) { + if ($profile === false || $outdir === false) { $this->cleanTmpFiles(); return null; } - //create imagick object from png - $pngPreview = null; - try { - [$dirname, , , $filename] = array_values(pathinfo($absPath)); - $pngPreview = $tmpDir . '/' . $filename . '.png'; + $parameters = [ + $this->options['officeBinary'], + '-env:UserInstallation=file://' . escapeshellarg($profile), + '--headless', + '--nologo', + '--nofirststartwizard', + '--invisible', + '--norestore', + '--convert-to png', + '--outdir ' . escapeshellarg($outdir), + escapeshellarg($absPath), + ]; - $png = new \Imagick($pngPreview . '[0]'); - $png->setImageFormat('jpg'); - } catch (\Exception $e) { + $cmd = implode(' ', $parameters); + exec($cmd, $output, $returnCode); + + if ($returnCode !== 0) { $this->cleanTmpFiles(); - unlink($pngPreview); - \OC::$server->get(LoggerInterface::class)->error($e->getMessage(), [ - 'exception' => $e, - 'app' => 'core', - ]); return null; } + $preview = $outdir . pathinfo($absPath, PATHINFO_FILENAME) . '.png'; + $image = new \OCP\Image(); - $image->loadFromData((string) $png); + $image->loadFromFile($preview); $this->cleanTmpFiles(); - unlink($pngPreview); if ($image->valid()) { $image->scaleDownToFit($maxX, $maxY); - return $image; } + return null; } } diff --git a/lib/private/PreviewManager.php b/lib/private/PreviewManager.php index 3af6848686e..aedcbbce335 100644 --- a/lib/private/PreviewManager.php +++ b/lib/private/PreviewManager.php @@ -366,7 +366,7 @@ class PreviewManager implements IPreview { $this->registerCoreProvider(Preview\OpenDocument::class, '/application\/vnd.oasis.opendocument.*/'); $this->registerCoreProvider(Preview\Imaginary::class, Preview\Imaginary::supportedMimeTypes()); - // SVG, Office and Bitmap require imagick + // SVG and Bitmap require imagick if ($this->imagickSupport->hasExtension()) { $imagickProviders = [ 'SVG' => ['mimetype' => '/image\/svg\+xml/', 'class' => Preview\SVG::class], @@ -391,27 +391,10 @@ class PreviewManager implements IPreview { $this->registerCoreProvider($class, $provider['mimetype']); } } - - if ($this->imagickSupport->supportsFormat('PDF')) { - // Office requires openoffice or libreoffice - $officeBinary = $this->config->getSystemValue('preview_libreoffice_path', null); - if (!is_string($officeBinary)) { - $officeBinary = $this->binaryFinder->findBinaryPath('libreoffice'); - } - if (!is_string($officeBinary)) { - $officeBinary = $this->binaryFinder->findBinaryPath('openoffice'); - } - - if (is_string($officeBinary)) { - $this->registerCoreProvider(Preview\MSOfficeDoc::class, '/application\/msword/', ["officeBinary" => $officeBinary]); - $this->registerCoreProvider(Preview\MSOffice2003::class, '/application\/vnd.ms-.*/', ["officeBinary" => $officeBinary]); - $this->registerCoreProvider(Preview\MSOffice2007::class, '/application\/vnd.openxmlformats-officedocument.*/', ["officeBinary" => $officeBinary]); - $this->registerCoreProvider(Preview\OpenDocument::class, '/application\/vnd.oasis.opendocument.*/', ["officeBinary" => $officeBinary]); - $this->registerCoreProvider(Preview\StarOffice::class, '/application\/vnd.sun.xml.*/', ["officeBinary" => $officeBinary]); - } - } } + $this->registerCoreProvidersOffice(); + // Video requires avconv or ffmpeg if (in_array(Preview\Movie::class, $this->getEnabledDefaultProvider())) { $movieBinary = $this->config->getSystemValue('preview_ffmpeg_path', null); @@ -429,6 +412,43 @@ class PreviewManager implements IPreview { } } + private function registerCoreProvidersOffice(): void { + $officeProviders = [ + ['mimetype' => '/application\/msword/', 'class' => Preview\MSOfficeDoc::class], + ['mimetype' => '/application\/vnd.ms-.*/', 'class' => Preview\MSOffice2003::class], + ['mimetype' => '/application\/vnd.openxmlformats-officedocument.*/', 'class' => Preview\MSOffice2007::class], + ['mimetype' => '/application\/vnd.oasis.opendocument.*/', 'class' => Preview\OpenDocument::class], + ['mimetype' => '/application\/vnd.sun.xml.*/', 'class' => Preview\StarOffice::class], + ['mimetype' => '/image\/emf/', 'class' => Preview\EMF::class], + ]; + + $findBinary = true; + $officeBinary = false; + + foreach ($officeProviders as $provider) { + $class = $provider['class']; + if (!in_array(trim($class, '\\'), $this->getEnabledDefaultProvider())) { + continue; + } + + if ($findBinary) { + // Office requires openoffice or libreoffice + $officeBinary = $this->config->getSystemValue('preview_libreoffice_path', false); + if ($officeBinary === false) { + $officeBinary = $this->binaryFinder->findBinaryPath('libreoffice'); + } + if ($officeBinary === false) { + $officeBinary = $this->binaryFinder->findBinaryPath('openoffice'); + } + $findBinary = false; + } + + if ($officeBinary) { + $this->registerCoreProvider($class, $provider['mimetype'], ['officeBinary' => $officeBinary]); + } + } + } + private function registerBootstrapProviders(): void { $context = $this->bootstrapCoordinator->getRegistrationContext(); diff --git a/lib/private/Repair/RepairMimeTypes.php b/lib/private/Repair/RepairMimeTypes.php index ee5a84ad65c..cab8d8ca02a 100644 --- a/lib/private/Repair/RepairMimeTypes.php +++ b/lib/private/Repair/RepairMimeTypes.php @@ -229,6 +229,13 @@ class RepairMimeTypes implements IRepairStep { return $this->updateMimetypes($updatedMimetypes); } + private function introduceEnhancedMetafileFormatType() { + $updatedMimetypes = [ + 'emf' => 'image/emf', + ]; + + return $this->updateMimetypes($updatedMimetypes); + } /** * Fix mime types @@ -286,5 +293,9 @@ class RepairMimeTypes implements IRepairStep { if (version_compare($ocVersionFromBeforeUpdate, '26.0.0.1', '<') && $this->introduceAsciidocType()) { $out->info('Fixed AsciiDoc mime types'); } + + if (version_compare($ocVersionFromBeforeUpdate, '28.0.0.5', '<') && $this->introduceEnhancedMetafileFormatType()) { + $out->info('Fixed Enhanced Metafile Format mime types'); + } } } diff --git a/resources/config/mimetypealiases.dist.json b/resources/config/mimetypealiases.dist.json index 67e79a52283..6b0bcf3e59a 100644 --- a/resources/config/mimetypealiases.dist.json +++ b/resources/config/mimetypealiases.dist.json @@ -114,5 +114,6 @@ "application/vnd.xmind.workbook": "mindmap", "image/targa": "image/tga", "application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform": "x-office/form", - "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf": "x-office/form-template" + "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf": "x-office/form-template", + "image/x-emf": "image/emf" } diff --git a/resources/config/mimetypemapping.dist.json b/resources/config/mimetypemapping.dist.json index 7b631466972..88a09d0b928 100644 --- a/resources/config/mimetypemapping.dist.json +++ b/resources/config/mimetypemapping.dist.json @@ -51,6 +51,7 @@ "dot": ["application/msword"], "dotx": ["application/vnd.openxmlformats-officedocument.wordprocessingml.template"], "dv": ["video/dv"], + "emf": ["image/emf"], "eot": ["application/vnd.ms-fontobject"], "eps": ["application/postscript"], "epub": ["application/epub+zip"], diff --git a/tests/data/integritycheck/mimetypeListModified/core/js/mimetypelist.js b/tests/data/integritycheck/mimetypeListModified/core/js/mimetypelist.js index a8e98e786f5..ffcf5e1fb1c 100644 --- a/tests/data/integritycheck/mimetypeListModified/core/js/mimetypelist.js +++ b/tests/data/integritycheck/mimetypeListModified/core/js/mimetypelist.js @@ -115,6 +115,7 @@ OC.MimeTypeList={ "image/targa": "image/tga", "application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform": "x-office/form", "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf": "x-office/form-template", + "image/x-emf": "image/emf", "my-custom/mimetype": "custom" }, files: [ diff --git a/tests/data/integritycheck/mimetypeListModified/core/signature.json b/tests/data/integritycheck/mimetypeListModified/core/signature.json index 43f489f6d3f..4ee844b87f8 100644 --- a/tests/data/integritycheck/mimetypeListModified/core/signature.json +++ b/tests/data/integritycheck/mimetypeListModified/core/signature.json @@ -1,7 +1,7 @@ { "hashes": { - "core\/js\/mimetypelist.js": "2a6ab9af5353d464c0dd3bd651cfc13ba35009463949bc45bd8f7073828fa34fbdac7a81ba2b188e7e0c97fc63c2167825b069f61341e507ca33213b1e6e4593" + "core\/js\/mimetypelist.js": "e9e515c5eeb08b02971e5943640bef89b6d1c2d746d5883bf974c6ac753f810685c7a20bf0ed4d32d8c046cd2cef6c045682c7d89c6a3b7b6c33122f5fd2088f" }, - "signature": "A5JmjvGiWC9iDaDL0\/wzIBx1ovV6xW5pL134ZtzcFh6dCRoYVZFZvInb98zz4Js3Y4R+uAv4XYKFgclG9BXjoa+q7SmN4qV95o870OsX3MEAaPRHEJv7V6P19hinwC0\/c6XUtMUlTn2IqdoacmELV3v+vmXiU0bYpNfqkYDjt1mCfl3EWB+uMCn+W849k1hoRc\/nI3JuDzl3VtP4G6zzJ3NexsXJOHOb6\/GyGVnkOltN3Ep5wBqXtr28LLLWWYbgxUEQ5ZNBd98PCpRm3r\/3eGreREccUzh+Kfo1XK+Rbnf8U6z3DXOwZK4cP\/CJBAhtlUDyw+TY58jcOSLxF2I61jqYoa8En2ukcQdXUvyTcsN+RzAKo+yhAPw0CJvDzb9zuS7gJUpev6nZnJKQ6dNQApQQILtwgz9dDlVKToxgyyhV1giTqEEZDvH1t2MSjz8fbGlm1YY60YJSs2SA\/cAff+sQVmoGCpRtdHriCDAET+5gTuz0wEXnvn6Jvxqxta9IZ0fisKCjfRH5FFdjfBM8Cgk6HOhSAfHoSH+ZFUGy8+NICZXe7CGr40iIjFLSIS0RgclQZSjYK8bfjA43XFpXeJNGjIvxHTr4tzm8gJ3YbVqCyN45HBcxS3q7yJCie3brqCZvXfXyhoGY6WhPAkBLQ+8nNP\/qeWlV8DMX+ZUYxso=", + "signature": "iKEOaoY+lowIZrDjozpCqDFtag8qtANZ4AqnwZG1HrzuP3Yv7uaCUZbpsyr4FklKyyZFbh4w5K3x5bacKq\/h7tFVu5A56sunSZIMDjO\/ToGFYtZC59hTi0mKlmR+rIbAwmlm2Qad0uSD+\/4bkihL\/haPAtV8IbHXqxwjcYjkPmyi0W3rN1sOycgbH8Hmu7UlkdZORGTVVHdMpQuIljaBGBonQUTnqUb2BVsZ7YKW3Ls1AKMBam\/OGrB8rAJOht5b86qIE1jzzU\/BI7Qs+r8C+sh84LpLgz\/33njaBNANwfnvbrcb4f\/95BZCL4DcMGfwJ\/VNRVJrBjQSweYb+ypq5WMMOUvHHEg4CovoH\/XbdCAbRVet34vRZnZe5F4bXQOZXp0eqbqoY+STwQ5Ku2O7YUWwfppjxWMMfs1hDUrvvMBFRCd5mla\/aktV7ugishcZdKUFyDsyOEtT292Cb5f\/62RqnMniD9a+TOBE1qWH5DXYQqRO9TUdVtGQ3ITbLxEAzlfUmwYoXp+wgKbzOXC4KFzpxJnxHM+vuURkO5lUza68gqiG8\/uhNcPQufDT5CjasQVBTK5tdoL64UnXqATgU3rrD\/MByOXWlZvMsAS+NjPkF30UnvqgApEwytOlTZ27+ntZjfwhM3DlXNKE3mzUx+tvVfwBDmhEpBK\/Qpk6HLc=", "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----" }
\ No newline at end of file |