diff options
Diffstat (limited to 'lib')
31 files changed, 597 insertions, 83 deletions
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 1c67fb9327f..44b7cd5244f 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -594,6 +594,7 @@ return array( 'OC\\Core\\Controller\\PreviewController' => $baseDir . '/core/Controller/PreviewController.php', 'OC\\Core\\Controller\\SearchController' => $baseDir . '/core/Controller/SearchController.php', 'OC\\Core\\Controller\\SetupController' => $baseDir . '/core/Controller/SetupController.php', + 'OC\\Core\\Controller\\SvgController' => $baseDir . '/core/Controller/SvgController.php', 'OC\\Core\\Controller\\TwoFactorChallengeController' => $baseDir . '/core/Controller/TwoFactorChallengeController.php', 'OC\\Core\\Controller\\UserController' => $baseDir . '/core/Controller/UserController.php', 'OC\\Core\\Controller\\WalledGardenController' => $baseDir . '/core/Controller/WalledGardenController.php', @@ -610,6 +611,8 @@ return array( 'OC\\Core\\Migrations\\Version14000Date20180518120534' => $baseDir . '/core/Migrations/Version14000Date20180518120534.php', 'OC\\Core\\Migrations\\Version14000Date20180522074438' => $baseDir . '/core/Migrations/Version14000Date20180522074438.php', 'OC\\Core\\Migrations\\Version14000Date20180626223656' => $baseDir . '/core/Migrations/Version14000Date20180626223656.php', + 'OC\\Core\\Migrations\\Version14000Date20180710092004' => $baseDir . '/core/Migrations/Version14000Date20180710092004.php', + 'OC\\Core\\Migrations\\Version14000Date20180712153140' => $baseDir . '/core/Migrations/Version14000Date20180712153140.php', 'OC\\DB\\Adapter' => $baseDir . '/lib/private/DB/Adapter.php', 'OC\\DB\\AdapterMySQL' => $baseDir . '/lib/private/DB/AdapterMySQL.php', 'OC\\DB\\AdapterOCI8' => $baseDir . '/lib/private/DB/AdapterOCI8.php', @@ -1016,6 +1019,7 @@ return array( 'OC\\TemplateLayout' => $baseDir . '/lib/private/TemplateLayout.php', 'OC\\Template\\Base' => $baseDir . '/lib/private/Template/Base.php', 'OC\\Template\\CSSResourceLocator' => $baseDir . '/lib/private/Template/CSSResourceLocator.php', + 'OC\\Template\\IconsCacher' => $baseDir . '/lib/private/Template/IconsCacher.php', 'OC\\Template\\JSCombiner' => $baseDir . '/lib/private/Template/JSCombiner.php', 'OC\\Template\\JSConfigHelper' => $baseDir . '/lib/private/Template/JSConfigHelper.php', 'OC\\Template\\JSResourceLocator' => $baseDir . '/lib/private/Template/JSResourceLocator.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index e40a5ea75db..815f94d5711 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -624,6 +624,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Core\\Controller\\PreviewController' => __DIR__ . '/../../..' . '/core/Controller/PreviewController.php', 'OC\\Core\\Controller\\SearchController' => __DIR__ . '/../../..' . '/core/Controller/SearchController.php', 'OC\\Core\\Controller\\SetupController' => __DIR__ . '/../../..' . '/core/Controller/SetupController.php', + 'OC\\Core\\Controller\\SvgController' => __DIR__ . '/../../..' . '/core/Controller/SvgController.php', 'OC\\Core\\Controller\\TwoFactorChallengeController' => __DIR__ . '/../../..' . '/core/Controller/TwoFactorChallengeController.php', 'OC\\Core\\Controller\\UserController' => __DIR__ . '/../../..' . '/core/Controller/UserController.php', 'OC\\Core\\Controller\\WalledGardenController' => __DIR__ . '/../../..' . '/core/Controller/WalledGardenController.php', @@ -640,6 +641,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Core\\Migrations\\Version14000Date20180518120534' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180518120534.php', 'OC\\Core\\Migrations\\Version14000Date20180522074438' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180522074438.php', 'OC\\Core\\Migrations\\Version14000Date20180626223656' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180626223656.php', + 'OC\\Core\\Migrations\\Version14000Date20180710092004' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180710092004.php', + 'OC\\Core\\Migrations\\Version14000Date20180712153140' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180712153140.php', 'OC\\DB\\Adapter' => __DIR__ . '/../../..' . '/lib/private/DB/Adapter.php', 'OC\\DB\\AdapterMySQL' => __DIR__ . '/../../..' . '/lib/private/DB/AdapterMySQL.php', 'OC\\DB\\AdapterOCI8' => __DIR__ . '/../../..' . '/lib/private/DB/AdapterOCI8.php', @@ -1046,6 +1049,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\TemplateLayout' => __DIR__ . '/../../..' . '/lib/private/TemplateLayout.php', 'OC\\Template\\Base' => __DIR__ . '/../../..' . '/lib/private/Template/Base.php', 'OC\\Template\\CSSResourceLocator' => __DIR__ . '/../../..' . '/lib/private/Template/CSSResourceLocator.php', + 'OC\\Template\\IconsCacher' => __DIR__ . '/../../..' . '/lib/private/Template/IconsCacher.php', 'OC\\Template\\JSCombiner' => __DIR__ . '/../../..' . '/lib/private/Template/JSCombiner.php', 'OC\\Template\\JSConfigHelper' => __DIR__ . '/../../..' . '/lib/private/Template/JSConfigHelper.php', 'OC\\Template\\JSResourceLocator' => __DIR__ . '/../../..' . '/lib/private/Template/JSResourceLocator.php', diff --git a/lib/l10n/cs.js b/lib/l10n/cs.js index f7dd8cd72cc..8de62521afc 100644 --- a/lib/l10n/cs.js +++ b/lib/l10n/cs.js @@ -231,6 +231,7 @@ OC.L10N.register( "Storage is temporarily not available" : "Úložiště je dočasně nedostupné", "Storage connection timeout. %s" : "Vypršení připojení k úložišti. %s", "Personal" : "Osobní", + "Admin" : "Správce", "APCu" : "APCu", "Redis" : "Redis", "Tips & tricks" : "Tipy a triky", diff --git a/lib/l10n/cs.json b/lib/l10n/cs.json index 228b06a682f..0c5c7309b03 100644 --- a/lib/l10n/cs.json +++ b/lib/l10n/cs.json @@ -229,6 +229,7 @@ "Storage is temporarily not available" : "Úložiště je dočasně nedostupné", "Storage connection timeout. %s" : "Vypršení připojení k úložišti. %s", "Personal" : "Osobní", + "Admin" : "Správce", "APCu" : "APCu", "Redis" : "Redis", "Tips & tricks" : "Tipy a triky", diff --git a/lib/l10n/fr.js b/lib/l10n/fr.js index eaeb1f50b1e..7a95348d341 100644 --- a/lib/l10n/fr.js +++ b/lib/l10n/fr.js @@ -229,6 +229,7 @@ OC.L10N.register( "Your data directory is invalid" : "Votre répertoire n'est pas valide", "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assurez-vous que le répertoire de données contient un fichier \".ocdata\" à sa racine.", "Action \"%s\" not supported or implemented." : "Action \"%s\" non supportée ou implémentée.", + "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Paramètres manquants pour compléter la requête. Paramètres manquants : \"%s\"", "Could not obtain lock type %d on \"%s\"." : "Impossible d'obtenir le verrouillage de type %d sur \"%s\".", "Storage unauthorized. %s" : "Espace de stockage non autorisé. %s", "Storage incomplete configuration. %s" : "Configuration de l'espace de stockage incomplète. %s", diff --git a/lib/l10n/fr.json b/lib/l10n/fr.json index 50416a619a8..77835280ed9 100644 --- a/lib/l10n/fr.json +++ b/lib/l10n/fr.json @@ -227,6 +227,7 @@ "Your data directory is invalid" : "Votre répertoire n'est pas valide", "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assurez-vous que le répertoire de données contient un fichier \".ocdata\" à sa racine.", "Action \"%s\" not supported or implemented." : "Action \"%s\" non supportée ou implémentée.", + "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Paramètres manquants pour compléter la requête. Paramètres manquants : \"%s\"", "Could not obtain lock type %d on \"%s\"." : "Impossible d'obtenir le verrouillage de type %d sur \"%s\".", "Storage unauthorized. %s" : "Espace de stockage non autorisé. %s", "Storage incomplete configuration. %s" : "Configuration de l'espace de stockage incomplète. %s", diff --git a/lib/l10n/pl.js b/lib/l10n/pl.js index 7f64cc6d33e..eb0e65e28f1 100644 --- a/lib/l10n/pl.js +++ b/lib/l10n/pl.js @@ -60,6 +60,9 @@ OC.L10N.register( "Log out" : "Wyloguj", "Users" : "Użytkownicy", "Unknown user" : "Nieznany użytkownik", + "Create" : "Utwórz", + "Change" : "Zmień", + "Delete" : "Usuń", "Basic settings" : "Ustawienia podstawowe", "Sharing" : "Udostępnianie", "Security" : "Bepieczeństwo", diff --git a/lib/l10n/pl.json b/lib/l10n/pl.json index 3e16ed67807..7c70d4dd1f5 100644 --- a/lib/l10n/pl.json +++ b/lib/l10n/pl.json @@ -58,6 +58,9 @@ "Log out" : "Wyloguj", "Users" : "Użytkownicy", "Unknown user" : "Nieznany użytkownik", + "Create" : "Utwórz", + "Change" : "Zmień", + "Delete" : "Usuń", "Basic settings" : "Ustawienia podstawowe", "Sharing" : "Udostępnianie", "Security" : "Bepieczeństwo", diff --git a/lib/private/Contacts/ContactsMenu/ContactsStore.php b/lib/private/Contacts/ContactsMenu/ContactsStore.php index bfce7deafa4..05ef9cca53a 100644 --- a/lib/private/Contacts/ContactsMenu/ContactsStore.php +++ b/lib/private/Contacts/ContactsMenu/ContactsStore.php @@ -155,7 +155,13 @@ class ContactsStore implements IContactsStore { } if ($ownGroupsOnly && $entry->getProperty('isLocalSystemBook') === true) { - $contactGroups = $this->groupManager->getUserGroupIds($this->userManager->get($entry->getProperty('UID'))); + $uid = $this->userManager->get($entry->getProperty('UID')); + + if ($uid === NULL) { + return false; + } + + $contactGroups = $this->groupManager->getUserGroupIds($uid); if (count(array_intersect($contactGroups, $selfGroups)) === 0) { // no groups in common, so shouldn't see the contact return false; diff --git a/lib/private/DB/MigrationService.php b/lib/private/DB/MigrationService.php index cc2889dae0c..6f5a74103a5 100644 --- a/lib/private/DB/MigrationService.php +++ b/lib/private/DB/MigrationService.php @@ -376,13 +376,14 @@ class MigrationService { * Applies all not yet applied versions up to $to * * @param string $to + * @param bool $schemaOnly * @throws \InvalidArgumentException */ - public function migrate($to = 'latest') { + public function migrate($to = 'latest', $schemaOnly = false) { // read known migrations $toBeExecuted = $this->getMigrationsToExecute($to); foreach ($toBeExecuted as $version) { - $this->executeStep($version); + $this->executeStep($version, $schemaOnly); } } @@ -432,14 +433,17 @@ class MigrationService { * Executes one explicit version * * @param string $version + * @param bool $schemaOnly * @throws \InvalidArgumentException */ - public function executeStep($version) { + public function executeStep($version, $schemaOnly = false) { $instance = $this->createInstance($version); - $instance->preSchemaChange($this->output, function() { - return new SchemaWrapper($this->connection); - }, ['tablePrefix' => $this->connection->getPrefix()]); + if (!$schemaOnly) { + $instance->preSchemaChange($this->output, function() { + return new SchemaWrapper($this->connection); + }, ['tablePrefix' => $this->connection->getPrefix()]); + } $toSchema = $instance->changeSchema($this->output, function() { return new SchemaWrapper($this->connection); @@ -450,9 +454,11 @@ class MigrationService { $toSchema->performDropTableCalls(); } - $instance->postSchemaChange($this->output, function() { - return new SchemaWrapper($this->connection); - }, ['tablePrefix' => $this->connection->getPrefix()]); + if (!$schemaOnly) { + $instance->postSchemaChange($this->output, function() { + return new SchemaWrapper($this->connection); + }, ['tablePrefix' => $this->connection->getPrefix()]); + } $this->markAsExecuted($version); } diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php index cc655018f8d..a6741652308 100644 --- a/lib/private/Files/Config/UserMountCache.php +++ b/lib/private/Files/Config/UserMountCache.php @@ -375,7 +375,7 @@ class UserMountCache implements IUserMountCache { ->innerJoin('m', 'filecache', 'f', $builder->expr()->andX( $builder->expr()->eq('m.storage_id', 'f.storage'), - $builder->expr()->eq('f.path', $builder->createNamedParameter('files')) + $builder->expr()->eq('f.path_hash', $builder->createNamedParameter(md5('files'))) )) ->where($builder->expr()->eq('m.mount_point', $mountPoint)) ->andWhere($builder->expr()->in('m.user_id', $builder->createNamedParameter($userIds, IQueryBuilder::PARAM_STR_ARRAY))); diff --git a/lib/private/Files/Utils/Scanner.php b/lib/private/Files/Utils/Scanner.php index fe2bf4ccb58..28921973fcf 100644 --- a/lib/private/Files/Utils/Scanner.php +++ b/lib/private/Files/Utils/Scanner.php @@ -151,11 +151,6 @@ class Scanner extends PublicEmitter { continue; } - // don't scan the root storage - if ($storage->instanceOfStorage('\OC\Files\Storage\Local') && $mount->getMountPoint() === '/') { - continue; - } - // don't scan received local shares, these can be scanned when scanning the owner's storage if ($storage->instanceOfStorage(SharedStorage::class)) { continue; diff --git a/lib/private/Log/ExceptionSerializer.php b/lib/private/Log/ExceptionSerializer.php index ecba043da44..768c6484963 100644 --- a/lib/private/Log/ExceptionSerializer.php +++ b/lib/private/Log/ExceptionSerializer.php @@ -82,7 +82,9 @@ class ExceptionSerializer { return $traceLine; }, $trace); return array_map(function (array $traceLine) use ($sensitiveValues) { - $traceLine['args'] = $this->removeValuesFromArgs($traceLine['args'], $sensitiveValues); + if (isset($traceLine['args'])) { + $traceLine['args'] = $this->removeValuesFromArgs($traceLine['args'], $sensitiveValues); + } return $traceLine; }, $trace); } @@ -101,7 +103,9 @@ class ExceptionSerializer { private function encodeTrace($trace) { $filteredTrace = $this->filterTrace($trace); return array_map(function (array $line) { - $line['args'] = array_map([$this, 'encodeArg'], $line['args']); + if (isset($line['args'])) { + $line['args'] = array_map([$this, 'encodeArg'], $line['args']); + } return $line; }, $filteredTrace); } @@ -138,4 +142,4 @@ class ExceptionSerializer { return $data; } -}
\ No newline at end of file +} diff --git a/lib/private/Log/File.php b/lib/private/Log/File.php index 597cb54e402..c881c6dd9de 100644 --- a/lib/private/Log/File.php +++ b/lib/private/Log/File.php @@ -145,6 +145,9 @@ class File implements IWriter, IFileBased { error_log($entry); } if (php_sapi_name() === 'cli-server') { + if (!\is_string($message)) { + $message = json_encode($message); + } error_log($message, 4); } } diff --git a/lib/private/Mail/EMailTemplate.php b/lib/private/Mail/EMailTemplate.php index 0ba411d6926..4c56a316042 100644 --- a/lib/private/Mail/EMailTemplate.php +++ b/lib/private/Mail/EMailTemplate.php @@ -229,13 +229,13 @@ EOF; <tr style="padding:0;text-align:left;vertical-align:top"> <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left"> <center data-parsed="" style="min-width:490px;width:100%%"> - <table class="button btn default primary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;margin-right:15px;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto"> + <table class="button btn default primary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;margin-right:15px;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto;background:%1\$s;background-color:%1\$s;color:#fefefe;"> <tr style="padding:0;text-align:left;vertical-align:top"> <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%%"> <tr style="padding:0;text-align:left;vertical-align:top"> - <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:%s;border:0 solid %s;border-collapse:collapse!important;color:#fefefe;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> - <a href="%s" style="Margin:0;border:0 solid %s;border-radius:2px;color:%s;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;padding:10px 25px 10px 25px;text-align:left;outline:1px solid %s;text-decoration:none">%s</a> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border:0 solid %2\$s;border-collapse:collapse!important;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <a href="%3\$s" style="Margin:0;border:0 solid %4\$s;border-radius:2px;color:%5\$s;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;padding:10px 25px 10px 25px;text-align:left;outline:1px solid %6\$s;text-decoration:none">%7\$s</a> </td> </tr> </table> @@ -248,7 +248,7 @@ EOF; <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%%"> <tr style="padding:0;text-align:left;vertical-align:top"> <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:#777;border:0 solid #777;border-collapse:collapse!important;color:#fefefe;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> - <a href="%s" style="Margin:0;background-color:#fff;border:0 solid #777;border-radius:2px;color:#6C6C6C!important;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;outline:1px solid #CBCBCB;padding:10px 25px 10px 25px;text-align:left;text-decoration:none">%s</a> + <a href="%8\$s" style="Margin:0;background-color:#fff;border:0 solid #777;border-radius:2px;color:#6C6C6C!important;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;outline:1px solid #CBCBCB;padding:10px 25px 10px 25px;text-align:left;text-decoration:none">%9\$s</a> </td> </tr> </table> @@ -282,13 +282,13 @@ EOF; <tr style="padding:0;text-align:left;vertical-align:top"> <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left"> <center data-parsed="" style="min-width:490px;width:100%%"> - <table class="button btn default primary float-center" style="Margin:0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0;max-height:40px;padding:0;text-align:center;vertical-align:top;width:auto"> + <table class="button btn default primary float-center" style="Margin:0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0;max-height:40px;padding:0;text-align:center;vertical-align:top;width:auto;background:%1\$s;color:#fefefe;background-color:%1\$s;"> <tr style="padding:0;text-align:left;vertical-align:top"> <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%%"> <tr style="padding:0;text-align:left;vertical-align:top"> - <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:%s;border:0 solid %s;border-collapse:collapse!important;color:#fefefe;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> - <a href="%s" style="Margin:0;border:0 solid %s;border-radius:2px;color:%s;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;padding:10px 25px 10px 25px;text-align:left;outline:1px solid %s;text-decoration:none">%s</a> + <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border:0 solid %2\$;border-collapse:collapse!important;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word"> + <a href="%3\$s" style="Margin:0;border:0 solid %4\$s;border-radius:2px;color:%5\$s;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;padding:10px 25px 10px 25px;text-align:left;outline:1px solid %5\$s;text-decoration:none">%7\$s</a> </td> </tr> </table> diff --git a/lib/private/NavigationManager.php b/lib/private/NavigationManager.php index 1c764f9c1ff..1874cd0e4ff 100644 --- a/lib/private/NavigationManager.php +++ b/lib/private/NavigationManager.php @@ -100,7 +100,7 @@ class NavigationManager implements INavigationManager { if(!isset($entry['type'])) { $entry['type'] = 'link'; } - $this->entries[] = $entry; + $this->entries[$entry['id']] = $entry; } /** @@ -133,7 +133,7 @@ class NavigationManager implements INavigationManager { * @return array */ private function proceedNavigation(array $list): array { - usort($list, function($a, $b) { + uasort($list, function($a, $b) { if (isset($a['order']) && isset($b['order'])) { return ($a['order'] < $b['order']) ? -1 : 1; } else if (isset($a['order']) || isset($b['order'])) { diff --git a/lib/private/Notification/Manager.php b/lib/private/Notification/Manager.php index bf0e8abadbb..4c3f7a2453c 100644 --- a/lib/private/Notification/Manager.php +++ b/lib/private/Notification/Manager.php @@ -53,6 +53,9 @@ class Manager implements IManager { /** @var \Closure[] */ protected $notifiersInfoClosures; + /** @var bool */ + protected $preparingPushNotification; + /** * Manager constructor. * @@ -66,6 +69,7 @@ class Manager implements IManager { $this->appsClosures = []; $this->notifiersClosures = []; $this->notifiersInfoClosures = []; + $this->preparingPushNotification = false; } /** @@ -95,7 +99,7 @@ class Manager implements IManager { /** * @return IApp[] */ - protected function getApps() { + protected function getApps(): array { if (!empty($this->apps)) { return $this->apps; } @@ -115,7 +119,7 @@ class Manager implements IManager { /** * @return INotifier[] */ - protected function getNotifiers() { + protected function getNotifiers(): array { if (!empty($this->notifiers)) { return $this->notifiers; } @@ -135,7 +139,7 @@ class Manager implements IManager { /** * @return array[] */ - public function listNotifiers() { + public function listNotifiers(): array { if (!empty($this->notifiersInfo)) { return $this->notifiersInfo; } @@ -143,7 +147,7 @@ class Manager implements IManager { $this->notifiersInfo = []; foreach ($this->notifiersInfoClosures as $closure) { $notifier = $closure(); - if (!is_array($notifier) || count($notifier) !== 2 || !isset($notifier['id']) || !isset($notifier['name'])) { + if (!\is_array($notifier) || \count($notifier) !== 2 || !isset($notifier['id'], $notifier['name'])) { throw new \InvalidArgumentException('The given notifier information is invalid'); } if (isset($this->notifiersInfo[$notifier['id']])) { @@ -159,7 +163,7 @@ class Manager implements IManager { * @return INotification * @since 8.2.0 */ - public function createNotification() { + public function createNotification(): INotification { return new Notification($this->validator); } @@ -167,11 +171,27 @@ class Manager implements IManager { * @return bool * @since 8.2.0 */ - public function hasNotifiers() { + public function hasNotifiers(): bool { return !empty($this->notifiersClosures); } /** + * @param bool $preparingPushNotification + * @since 14.0.0 + */ + public function setPreparingPushNotification($preparingPushNotification) { + $this->preparingPushNotification = $preparingPushNotification; + } + + /** + * @return bool + * @since 14.0.0 + */ + public function isPreparingPushNotification(): bool { + return $this->preparingPushNotification; + } + + /** * @param INotification $notification * @throws \InvalidArgumentException When the notification is not valid * @since 8.2.0 @@ -198,7 +218,7 @@ class Manager implements IManager { * @throws \InvalidArgumentException When the notification was not prepared by a notifier * @since 8.2.0 */ - public function prepare(INotification $notification, $languageCode) { + public function prepare(INotification $notification, $languageCode): INotification { $notifiers = $this->getNotifiers(); foreach ($notifiers as $notifier) { @@ -235,7 +255,7 @@ class Manager implements IManager { * @param INotification $notification * @return int */ - public function getCount(INotification $notification) { + public function getCount(INotification $notification): int { $apps = $this->getApps(); $count = 0; diff --git a/lib/private/Server.php b/lib/private/Server.php index c9f8001631e..0f406ebe9b7 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -116,6 +116,7 @@ use OC\Share20\ProviderFactory; use OC\Share20\ShareHelper; use OC\SystemTag\ManagerFactory as SystemTagManagerFactory; use OC\Tagging\TagMapper; +use OC\Template\IconsCacher; use OC\Template\JSCombiner; use OC\Template\SCSSCacher; use OCA\Theming\ImageManager; @@ -963,7 +964,8 @@ class Server extends ServerContainer implements IServerContainer { $c->getConfig(), $c->getThemingDefaults(), \OC::$SERVERROOT, - $this->getMemCacheFactory() + $this->getMemCacheFactory(), + $c->query(IconsCacher::class) ); }); $this->registerService(JSCombiner::class, function (Server $c) { diff --git a/lib/private/Settings/Manager.php b/lib/private/Settings/Manager.php index 82cb223bb9f..e9f2a6f5976 100644 --- a/lib/private/Settings/Manager.php +++ b/lib/private/Settings/Manager.php @@ -231,7 +231,7 @@ class Manager implements IManager { 5 => [new Section('sharing', $this->l->t('Sharing'), 0, $this->url->imagePath('core', 'actions/share.svg'))], 10 => [new Section('security', $this->l->t('Security'), 0, $this->url->imagePath('core', 'actions/password.svg'))], 45 => [new Section('encryption', $this->l->t('Encryption'), 0, $this->url->imagePath('core', 'actions/password.svg'))], - 50 => [new Section('groupware', $this->l->t('Groupware'), 0, $this->url->imagePath('core', 'places/contacts-dark.svg'))], + 50 => [new Section('groupware', $this->l->t('Groupware'), 0, $this->url->imagePath('core', 'places/contacts.svg'))], 98 => [new Section('additional', $this->l->t('Additional settings'), 0, $this->url->imagePath('core', 'actions/settings-dark.svg'))], ]; diff --git a/lib/private/Share/Share.php b/lib/private/Share/Share.php index 52e0628987b..0a9371d35b8 100644 --- a/lib/private/Share/Share.php +++ b/lib/private/Share/Share.php @@ -86,7 +86,6 @@ class Share extends Constants { ); if(count(self::$backendTypes) === 1) { Util::addScript('core', 'merged-share-backend'); - \OC_Util::addStyle('core', 'share'); } return true; } diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php index 5e52156d1d0..9c5d78a5958 100644 --- a/lib/private/Share20/DefaultShareProvider.php +++ b/lib/private/Share20/DefaultShareProvider.php @@ -30,8 +30,14 @@ namespace OC\Share20; use OC\Files\Cache\Cache; +use OCP\Defaults; use OCP\Files\Folder; +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\IUser; +use OCP\Mail\IMailer; use OCP\Share\IShare; +use OCP\Share\IShareHelper; use OCP\Share\IShareProvider; use OC\Share20\Exception\InvalidShare; use OC\Share20\Exception\ProviderException; @@ -67,6 +73,18 @@ class DefaultShareProvider implements IShareProvider { /** @var IRootFolder */ private $rootFolder; + /** @var IMailer */ + private $mailer; + + /** @var Defaults */ + private $defaults; + + /** @var IL10N */ + private $l; + + /** @var IURLGenerator */ + private $urlGenerator; + /** * DefaultShareProvider constructor. * @@ -74,16 +92,28 @@ class DefaultShareProvider implements IShareProvider { * @param IUserManager $userManager * @param IGroupManager $groupManager * @param IRootFolder $rootFolder + * @param IMailer $mailer ; + * @param Defaults $defaults + * @param IL10N $l + * @param IURLGenerator $urlGenerator */ public function __construct( IDBConnection $connection, IUserManager $userManager, IGroupManager $groupManager, - IRootFolder $rootFolder) { + IRootFolder $rootFolder, + IMailer $mailer, + Defaults $defaults, + IL10N $l, + IURLGenerator $urlGenerator) { $this->dbConn = $connection; $this->userManager = $userManager; $this->groupManager = $groupManager; $this->rootFolder = $rootFolder; + $this->mailer = $mailer; + $this->defaults = $defaults; + $this->l = $l; + $this->urlGenerator = $urlGenerator; } /** @@ -197,6 +227,9 @@ class DefaultShareProvider implements IShareProvider { * @return \OCP\Share\IShare The share object */ public function update(\OCP\Share\IShare $share) { + + $originalShare = $this->getShareById($share->getId()); + if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { /* * We allow updating the recipient on user shares. @@ -211,6 +244,7 @@ class DefaultShareProvider implements IShareProvider { ->set('item_source', $qb->createNamedParameter($share->getNode()->getId())) ->set('file_source', $qb->createNamedParameter($share->getNode()->getId())) ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE)) + ->set('note', $qb->createNamedParameter($share->getNote())) ->execute(); } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { $qb = $this->dbConn->getQueryBuilder(); @@ -222,6 +256,7 @@ class DefaultShareProvider implements IShareProvider { ->set('item_source', $qb->createNamedParameter($share->getNode()->getId())) ->set('file_source', $qb->createNamedParameter($share->getNode()->getId())) ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE)) + ->set('note', $qb->createNamedParameter($share->getNote())) ->execute(); /* @@ -235,6 +270,7 @@ class DefaultShareProvider implements IShareProvider { ->set('item_source', $qb->createNamedParameter($share->getNode()->getId())) ->set('file_source', $qb->createNamedParameter($share->getNode()->getId())) ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE)) + ->set('note', $qb->createNamedParameter($share->getNote())) ->execute(); /* @@ -259,9 +295,15 @@ class DefaultShareProvider implements IShareProvider { ->set('file_source', $qb->createNamedParameter($share->getNode()->getId())) ->set('token', $qb->createNamedParameter($share->getToken())) ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE)) + ->set('note', $qb->createNamedParameter($share->getNote())) ->execute(); } + if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') { + $this->propagateNote($share); + } + + return $share; } @@ -875,6 +917,7 @@ class DefaultShareProvider implements IShareProvider { ->setShareType((int)$data['share_type']) ->setPermissions((int)$data['permissions']) ->setTarget($data['file_target']) + ->setNote($data['note']) ->setMailSend((bool)$data['mail_send']); $shareTime = new \DateTime(); @@ -1227,4 +1270,96 @@ class DefaultShareProvider implements IShareProvider { return $best; } + + /** + * propagate notes to the recipients + * + * @param IShare $share + * @throws \OCP\Files\NotFoundException + */ + private function propagateNote(IShare $share) { + if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { + $user = $this->userManager->get($share->getSharedWith()); + $this->sendNote([$user], $share); + } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { + $group = $this->groupManager->get($share->getSharedWith()); + $groupMembers = $group->getUsers(); + $this->sendNote($groupMembers, $share); + } + } + + /** + * send note by mail + * + * @param array $recipients + * @param IShare $share + * @throws \OCP\Files\NotFoundException + */ + private function sendNote(array $recipients, IShare $share) { + + $toList = []; + + foreach ($recipients as $recipient) { + /** @var IUser $recipient */ + $email = $recipient->getEMailAddress(); + if ($email) { + $toList[$email] = $recipient->getDisplayName(); + } + } + + if (!empty($toList)) { + + $filename = $share->getNode()->getName(); + $initiator = $share->getSharedBy(); + $note = $share->getNote(); + + $initiatorUser = $this->userManager->get($initiator); + $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator; + $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null; + $plainHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]); + $htmlHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]); + $message = $this->mailer->createMessage(); + + $emailTemplate = $this->mailer->createEMailTemplate('defaultShareProvider.sendNote'); + + $emailTemplate->setSubject($this->l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName])); + $emailTemplate->addHeader(); + $emailTemplate->addHeading($htmlHeading, $plainHeading); + $emailTemplate->addBodyText(htmlspecialchars($note), $note); + + $link = $this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $share->getNode()->getId()]); + $emailTemplate->addBodyButton( + $this->l->t('Open »%s«', [$filename]), + $link + ); + + + // The "From" contains the sharers name + $instanceName = $this->defaults->getName(); + $senderName = $this->l->t( + '%1$s via %2$s', + [ + $initiatorDisplayName, + $instanceName + ] + ); + $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]); + if ($initiatorEmailAddress !== null) { + $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]); + $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan()); + } else { + $emailTemplate->addFooter(); + } + + if (count($toList) === 1) { + $message->setTo($toList); + } else { + $message->setTo([]); + $message->setBcc($toList); + } + $message->useTemplate($emailTemplate); + $this->mailer->send($message); + } + + } } diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index 76b523afd10..d0316b44c1a 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -827,10 +827,20 @@ class Manager implements IManager { $expirationDateUpdated = true; } } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) { + // The new password is not set again if it is the same as the old + // one, unless when switching from sending by Talk to sending by + // mail. $plainTextPassword = $share->getPassword(); - if (!$this->updateSharePasswordIfNeeded($share, $originalShare)) { + if (!empty($plainTextPassword) && !$this->updateSharePasswordIfNeeded($share, $originalShare) && + !($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk())) { $plainTextPassword = null; } + if (empty($plainTextPassword) && !$originalShare->getSendPasswordByTalk() && $share->getSendPasswordByTalk()) { + // If the same password was already sent by mail the recipient + // would already have access to the share without having to call + // the sharer to verify her identity + throw new \InvalidArgumentException('Can’t enable sending the password by Talk without setting a new password'); + } } $this->pathCreateChecks($share->getNode()); diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php index e4d34146911..0aacca409d1 100644 --- a/lib/private/Share20/ProviderFactory.php +++ b/lib/private/Share20/ProviderFactory.php @@ -81,7 +81,11 @@ class ProviderFactory implements IProviderFactory { $this->serverContainer->getDatabaseConnection(), $this->serverContainer->getUserManager(), $this->serverContainer->getGroupManager(), - $this->serverContainer->getLazyRootFolder() + $this->serverContainer->getLazyRootFolder(), + $this->serverContainer->getMailer(), + $this->serverContainer->query(Defaults::class), + $this->serverContainer->getL10N('sharing'), + $this->serverContainer->getURLGenerator() ); } diff --git a/lib/private/Share20/Share.php b/lib/private/Share20/Share.php index d7810165dac..71c0453d9e5 100644 --- a/lib/private/Share20/Share.php +++ b/lib/private/Share20/Share.php @@ -57,10 +57,14 @@ class Share implements \OCP\Share\IShare { private $shareOwner; /** @var int */ private $permissions; + /** @var string */ + private $note = ''; /** @var \DateTime */ private $expireDate; /** @var string */ private $password; + /** @var bool */ + private $sendPasswordByTalk = false; /** @var string */ private $token; /** @var int */ @@ -311,6 +315,24 @@ class Share implements \OCP\Share\IShare { /** * @inheritdoc */ + public function setNote($note) { + $this->note = $note; + return $this; + } + + /** + * @inheritdoc + */ + public function getNote() { + if (is_string($this->note)) { + return $this->note; + } + return ''; + } + + /** + * @inheritdoc + */ public function setExpirationDate($expireDate) { //TODO checks @@ -385,6 +407,21 @@ class Share implements \OCP\Share\IShare { /** * @inheritdoc */ + public function setSendPasswordByTalk(bool $sendPasswordByTalk) { + $this->sendPasswordByTalk = $sendPasswordByTalk; + return $this; + } + + /** + * @inheritdoc + */ + public function getSendPasswordByTalk(): bool { + return $this->sendPasswordByTalk; + } + + /** + * @inheritdoc + */ public function setToken($token) { $this->token = $token; return $this; diff --git a/lib/private/Template/IconsCacher.php b/lib/private/Template/IconsCacher.php new file mode 100644 index 00000000000..e5ebecaf169 --- /dev/null +++ b/lib/private/Template/IconsCacher.php @@ -0,0 +1,147 @@ +<?php +declare (strict_types = 1); +/** + * @copyright Copyright (c) 2018, John Molakvoæ (skjnldsv@protonmail.com) + * + * @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> + * + * @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\Template; + +use OCP\Files\IAppData; +use OCP\Files\NotFoundException; +use OCP\Files\SimpleFS\ISimpleFolder; +use OCP\Files\SimpleFS\ISimpleFile; +use OCP\ILogger; +use OCP\IURLGenerator; +use OC\Files\AppData\Factory; + +class IconsCacher { + + /** @var ILogger */ + protected $logger; + + /** @var IAppData */ + protected $appData; + + /** @var ISimpleFolder */ + private $folder; + + /** @var IURLGenerator */ + protected $urlGenerator; + + /** @var string */ + private $iconVarRE = '/--(icon-[a-zA-Z0-9-]+): url\(["\']([a-z0-9-_\~\/\.]+)[^;]+;/m'; + + /** @var string */ + private $fileName = 'icons-vars.css'; + + /** + * @param ILogger $logger + * @param Factory $appDataFactory + * @param IURLGenerator $urlGenerator + */ + public function __construct(ILogger $logger, + Factory $appDataFactory, + IURLGenerator $urlGenerator) { + $this->logger = $logger; + $this->appData = $appDataFactory->get('css'); + $this->urlGenerator = $urlGenerator; + + try { + $this->folder = $this->appData->getFolder('icons'); + } catch (NotFoundException $e) { + $this->folder = $this->appData->newFolder('icons'); + } + } + + private function getIconsFromCss(string $css): array{ + preg_match_all($this->iconVarRE, $css, $matches, PREG_SET_ORDER); + $icons = []; + foreach ($matches as $icon) { + $icons[$icon[1]] = $icon[2]; + } + + return $icons; + } + /** + * Parse and cache css + * + * @param string $css + */ + public function setIconsCss(string $css) { + + $cachedFile = $this->getCachedCSS(); + if (!$cachedFile) { + $currentData = ''; + } else { + $currentData = $cachedFile->getContent(); + } + + // remove :root + $currentData = str_replace([':root {', '}'], '', $currentData); + + $icons = $this->getIconsFromCss($currentData . $css); + + $data = ''; + foreach ($icons as $icon => $url) { + $data .= "--$icon: url('$url?v=1');"; + } + + if (strlen($data) > 0) { + if (!$cachedFile) { + $cachedFile = $this->folder->newFile($this->fileName); + } + + $data = ":root { + $data + }"; + $cachedFile->putContent($data); + } + + return preg_replace($this->iconVarRE, '', $css); + } + + /** + * Get icons css file + * @return ISimpleFile|boolean + */ + public function getCachedCSS() { + try { + return $this->folder->getFile($this->fileName); + } catch (NotFoundException $e) { + return false; + } + } + + public function injectCss() { + // Only inject once + foreach (\OC_Util::$headers as $header) { + if ( + array_key_exists('attributes', $header) && + array_key_exists('href', $header['attributes']) && + strpos($header['attributes']['href'], $this->fileName) !== false) { + return; + } + } + $linkToCSS = substr($this->urlGenerator->linkToRoute('core.Css.getCss', ['appName' => 'icons', 'fileName' => $this->fileName]), strlen(\OC::$WEBROOT)); + \OC_Util::addHeader('link', ['rel' => 'stylesheet', 'href' => $linkToCSS], null, true); + } + +}
\ No newline at end of file diff --git a/lib/private/Template/SCSSCacher.php b/lib/private/Template/SCSSCacher.php index 6e25e1fa5de..9dcedb94daf 100644 --- a/lib/private/Template/SCSSCacher.php +++ b/lib/private/Template/SCSSCacher.php @@ -32,7 +32,6 @@ use Leafo\ScssPhp\Compiler; use Leafo\ScssPhp\Exception\ParserException; use Leafo\ScssPhp\Formatter\Crunched; use Leafo\ScssPhp\Formatter\Expanded; -use OC\Files\AppData\Factory; use OCP\Files\IAppData; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; @@ -43,6 +42,8 @@ use OCP\ICacheFactory; use OCP\IConfig; use OCP\ILogger; use OCP\IURLGenerator; +use OC\Files\AppData\Factory; +use OC\Template\IconsCacher; class SCSSCacher { @@ -73,6 +74,9 @@ class SCSSCacher { /** @var ICacheFactory */ private $cacheFactory; + /** @var IconsCacher */ + private $iconsCacher; + /** * @param ILogger $logger * @param Factory $appDataFactory @@ -81,6 +85,7 @@ class SCSSCacher { * @param \OC_Defaults $defaults * @param string $serverRoot * @param ICacheFactory $cacheFactory + * @param IconsCacher $iconsCacher */ public function __construct(ILogger $logger, Factory $appDataFactory, @@ -88,15 +93,17 @@ class SCSSCacher { IConfig $config, \OC_Defaults $defaults, $serverRoot, - ICacheFactory $cacheFactory) { - $this->logger = $logger; - $this->appData = $appDataFactory->get('css'); + ICacheFactory $cacheFactory, + IconsCacher $iconsCacher) { + $this->logger = $logger; + $this->appData = $appDataFactory->get('css'); $this->urlGenerator = $urlGenerator; - $this->config = $config; - $this->defaults = $defaults; - $this->serverRoot = $serverRoot; + $this->config = $config; + $this->defaults = $defaults; + $this->serverRoot = $serverRoot; $this->cacheFactory = $cacheFactory; - $this->depsCache = $cacheFactory->createDistributed('SCSS-' . md5($this->urlGenerator->getBaseUrl())); + $this->depsCache = $cacheFactory->createDistributed('SCSS-' . md5($this->urlGenerator->getBaseUrl())); + $this->iconsCacher = $iconsCacher; } /** @@ -112,23 +119,34 @@ class SCSSCacher { $path = explode('/', $root . '/' . $file); $fileNameSCSS = array_pop($path); - $fileNameCSS = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS)), $app); + $fileNameCSS = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS)), $app); - $path = implode('/', $path); + $path = implode('/', $path); $webDir = $this->getWebDir($path, $app, $this->serverRoot, \OC::$WEBROOT); try { $folder = $this->appData->getFolder($app); - } catch(NotFoundException $e) { + } catch (NotFoundException $e) { // creating css appdata folder $folder = $this->appData->newFolder($app); } - - if(!$this->variablesChanged() && $this->isCached($fileNameCSS, $folder)) { + if (!$this->variablesChanged() && $this->isCached($fileNameCSS, $folder)) { + // Inject icons vars css if any + if ($this->iconsCacher->getCachedCSS() && $this->iconsCacher->getCachedCSS()->getSize() > 0) { + $this->iconsCacher->injectCss(); + } return true; } - return $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir); + + $cached = $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir); + + // Inject icons vars css if any + if ($this->iconsCacher->getCachedCSS() && $this->iconsCacher->getCachedCSS()->getSize() > 0) { + $this->iconsCacher->injectCss(); + } + + return $cached; } /** @@ -137,8 +155,9 @@ class SCSSCacher { * @return ISimpleFile */ public function getCachedCSS(string $appName, string $fileName): ISimpleFile { - $folder = $this->appData->getFolder($appName); + $folder = $this->appData->getFolder($appName); $cachedFileName = $this->prependVersionPrefix($this->prependBaseurlPrefix($fileName), $appName); + return $folder->getFile($cachedFileName); } @@ -153,24 +172,26 @@ class SCSSCacher { $cachedFile = $folder->getFile($fileNameCSS); if ($cachedFile->getSize() > 0) { $depFileName = $fileNameCSS . '.deps'; - $deps = $this->depsCache->get($folder->getName() . '-' . $depFileName); + $deps = $this->depsCache->get($folder->getName() . '-' . $depFileName); if ($deps === null) { $depFile = $folder->getFile($depFileName); - $deps = $depFile->getContent(); + $deps = $depFile->getContent(); //Set to memcache for next run $this->depsCache->set($folder->getName() . '-' . $depFileName, $deps); } $deps = json_decode($deps, true); - foreach ((array)$deps as $file=>$mtime) { + foreach ((array) $deps as $file => $mtime) { if (!file_exists($file) || filemtime($file) > $mtime) { return false; } } + return true; } + return false; - } catch(NotFoundException $e) { + } catch (NotFoundException $e) { return false; } } @@ -181,11 +202,13 @@ class SCSSCacher { */ private function variablesChanged(): bool { $injectedVariables = $this->getInjectedVariables(); - if($this->config->getAppValue('core', 'scss.variables') !== md5($injectedVariables)) { + if ($this->config->getAppValue('core', 'scss.variables') !== md5($injectedVariables)) { $this->resetCache(); $this->config->setAppValue('core', 'scss.variables', md5($injectedVariables)); + return true; } + return false; } @@ -204,11 +227,12 @@ class SCSSCacher { $scss = new Compiler(); $scss->setImportPaths([ $path, - $this->serverRoot . '/core/css/', + $this->serverRoot . '/core/css/' ]); + // Continue after throw $scss->setIgnoreErrors(true); - if($this->config->getSystemValue('debug')) { + if ($this->config->getSystemValue('debug')) { // Debug mode $scss->setFormatter(Expanded::class); $scss->setLineNumberStyle(Compiler::LINE_COMMENTS); @@ -219,7 +243,7 @@ class SCSSCacher { try { $cachedfile = $folder->getFile($fileNameCSS); - } catch(NotFoundException $e) { + } catch (NotFoundException $e) { $cachedfile = $folder->newFile($fileNameCSS); } @@ -233,14 +257,20 @@ class SCSSCacher { // Compile try { $compiledScss = $scss->compile( + '$webroot: \'' . $this->getRoutePrefix() . '\';' . '@import "variables.scss";' . + '@import "functions.scss";' . $this->getInjectedVariables() . - '@import "'.$fileNameSCSS.'";'); - } catch(ParserException $e) { + '@import "' . $fileNameSCSS . '";'); + } catch (ParserException $e) { $this->logger->error($e, ['app' => 'core']); + return false; } + // Parse Icons and create related css variables + $compiledScss = $this->iconsCacher->setIconsCss($compiledScss); + // Gzip file try { $gzipFile = $folder->getFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz @@ -255,10 +285,12 @@ class SCSSCacher { $depFile->putContent($deps); $this->depsCache->set($folder->getName() . '-' . $depFileName, $deps); $gzipFile->putContent(gzencode($data, 9)); - $this->logger->debug('SCSSCacher: '.$webDir.'/'.$fileNameSCSS.' compiled and successfully cached', ['app' => 'core']); + $this->logger->debug('SCSSCacher: ' . $webDir . '/' . $fileNameSCSS . ' compiled and successfully cached', ['app' => 'core']); + return true; - } catch(NotPermittedException $e) { + } catch (NotPermittedException $e) { $this->logger->error('SCSSCacher: unable to cache: ' . $fileNameSCSS); + return false; } } @@ -275,7 +307,7 @@ class SCSSCacher { foreach ($folder->getDirectoryListing() as $file) { try { $file->delete(); - } catch(NotPermittedException $e) { + } catch (NotPermittedException $e) { $this->logger->logException($e, ['message' => 'SCSSCacher: unable to delete file: ' . $file->getName()]); } } @@ -313,8 +345,9 @@ class SCSSCacher { * @return string */ private function rebaseUrls(string $css, string $webDir): string { - $re = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x'; - $subst = 'url(\''.$webDir.'/$1\')'; + $re = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x'; + $subst = 'url(\'' . $webDir . '/$1\')'; + return preg_replace($re, $subst, $css); } @@ -326,8 +359,8 @@ class SCSSCacher { */ public function getCachedSCSS(string $appName, string $fileName): string { $tmpfileLoc = explode('/', $fileName); - $fileName = array_pop($tmpfileLoc); - $fileName = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileName)), $appName); + $fileName = array_pop($tmpfileLoc); + $fileName = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileName)), $appName); return substr($this->urlGenerator->linkToRoute('core.Css.getCss', ['fileName' => $fileName, 'appName' => $appName]), strlen(\OC::$WEBROOT) + 1); } @@ -338,8 +371,16 @@ class SCSSCacher { * @return string */ private function prependBaseurlPrefix(string $cssFile): string { - $frontendController = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true'); - return substr(md5($this->urlGenerator->getBaseUrl() . $frontendController), 0, 4) . '-' . $cssFile; + return substr(md5($this->urlGenerator->getBaseUrl() . $this->getRoutePrefix()), 0, 4) . '-' . $cssFile; + } + + private function getRoutePrefix() { + $frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true'); + $prefix = \OC::$WEBROOT . '/index.php'; + if ($frontControllerActive) { + $prefix = \OC::$WEBROOT; + } + return $prefix; } /** @@ -354,6 +395,7 @@ class SCSSCacher { return substr(md5($appVersion), 0, 4) . '-' . $cssFile; } $coreVersion = \OC_Util::getVersionString(); + return substr(md5($coreVersion), 0, 4) . '-' . $cssFile; } @@ -367,12 +409,14 @@ class SCSSCacher { */ private function getWebDir(string $path, string $appName, string $serverRoot, string $webRoot): string { // Detect if path is within server root AND if path is within an app path - if ( strpos($path, $serverRoot) === false && $appWebPath = \OC_App::getAppWebPath($appName)) { + if (strpos($path, $serverRoot) === false && $appWebPath = \OC_App::getAppWebPath($appName)) { // Get the file path within the app directory $appDirectoryPath = explode($appName, $path)[1]; // Remove the webroot - return str_replace($webRoot, '', $appWebPath.$appDirectoryPath); + + return str_replace($webRoot, '', $appWebPath . $appDirectoryPath); } - return $webRoot.substr($path, strlen($serverRoot)); + + return $webRoot . substr($path, strlen($serverRoot)); } } diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php index 1efdf8b441c..fc2e5798e1c 100644 --- a/lib/private/TemplateLayout.php +++ b/lib/private/TemplateLayout.php @@ -42,6 +42,7 @@ use OC\Template\JSCombiner; use OC\Template\JSConfigHelper; use OC\Template\SCSSCacher; use OCP\Defaults; +use OC\AppFramework\Http\Request; class TemplateLayout extends \OC_Template { @@ -61,6 +62,9 @@ class TemplateLayout extends \OC_Template { // yes - should be injected .... $this->config = \OC::$server->getConfig(); + if(\OCP\Util::isIE()) { + \OC_Util::addStyle('ie'); + } // Decide which page we show if($renderAs == 'user') { diff --git a/lib/private/legacy/util.php b/lib/private/legacy/util.php index ab595d885cb..a581397212a 100644 --- a/lib/private/legacy/util.php +++ b/lib/private/legacy/util.php @@ -64,6 +64,7 @@ use OCP\IConfig; use OCP\IGroupManager; use OCP\ILogger; use OCP\IUser; +use OC\AppFramework\Http\Request; class OC_Util { public static $scripts = array(); @@ -687,13 +688,20 @@ class OC_Util { * @param string $tag tag name of the element * @param array $attributes array of attributes for the element * @param string $text the text content for the element + * @param bool $prepend prepend the header to the beginning of the list */ - public static function addHeader($tag, $attributes, $text=null) { - self::$headers[] = array( + public static function addHeader($tag, $attributes, $text = null, $prepend = false) { + $header = array( 'tag' => $tag, 'attributes' => $attributes, 'text' => $text ); + if ($prepend === true) { + array_unshift (self::$headers, $header); + + } else { + self::$headers[] = $header; + } } /** @@ -1371,7 +1379,7 @@ class OC_Util { } // Zend OpCache >= 7.0.0, PHP >= 5.5.0 if (function_exists('opcache_invalidate')) { - $ret = opcache_invalidate($path); + $ret = @opcache_invalidate($path); } } return $ret; @@ -1405,7 +1413,7 @@ class OC_Util { } // Opcache (PHP >= 5.5) if (function_exists('opcache_reset')) { - opcache_reset(); + @opcache_reset(); } } @@ -1521,4 +1529,13 @@ class OC_Util { } } + /** + * is this Internet explorer ? + * + * @return boolean + */ + public static function isIe() { + return preg_match(Request::USER_AGENT_IE, $_SERVER['HTTP_USER_AGENT']) === 1; + } + } diff --git a/lib/public/Notification/IManager.php b/lib/public/Notification/IManager.php index cbc48142cbb..003e5f1bad1 100644 --- a/lib/public/Notification/IManager.php +++ b/lib/public/Notification/IManager.php @@ -62,4 +62,16 @@ interface IManager extends IApp, INotifier { * @since 9.0.0 */ public function hasNotifiers(); + + /** + * @param bool $preparingPushNotification + * @since 14.0.0 + */ + public function setPreparingPushNotification($preparingPushNotification); + + /** + * @return bool + * @since 14.0.0 + */ + public function isPreparingPushNotification(); } diff --git a/lib/public/Share/IShare.php b/lib/public/Share/IShare.php index 870794d6536..43543fdad47 100644 --- a/lib/public/Share/IShare.php +++ b/lib/public/Share/IShare.php @@ -223,6 +223,24 @@ interface IShare { public function getPermissions(); /** + * Attach a note to a share + * + * @param string $note + * @return \OCP\Share\IShare The modified object + * @since 14.0.0 + */ + public function setNote($note); + + /** + * Get note attached to a share + * + * @return string + * @since 14.0.0 + */ + public function getNote(); + + + /** * Set the expiration date * * @param null|\DateTime $expireDate @@ -294,6 +312,29 @@ interface IShare { */ public function getPassword(); + + /** + * Set if the recipient can start a conversation with the owner to get the + * password using Nextcloud Talk. + * + * @param bool $sendPasswordByTalk + * @return \OCP\Share\IShare The modified object + * @since 14.0.0 + */ + public function setSendPasswordByTalk(bool $sendPasswordByTalk); + + /** + * Get if the recipient can start a conversation with the owner to get the + * password using Nextcloud Talk. + * The returned value does not take into account other factors, like Talk + * being enabled for the owner of the share or not; it just cover whether + * the option is enabled for the share itself or not. + * + * @return bool + * @since 14.0.0 + */ + public function getSendPasswordByTalk(): bool; + /** * Set the public link token. * diff --git a/lib/public/Util.php b/lib/public/Util.php index 27b703ea2d8..9892f4a1ecb 100644 --- a/lib/public/Util.php +++ b/lib/public/Util.php @@ -558,4 +558,14 @@ class Util { } return self::$needUpgradeCache; } + + /** + * is this Internet explorer ? + * + * @return boolean + * @since 14.0.0 + */ + public static function isIe() { + return \OC_Util::isIe(); + } } |