aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
m---------3rdparty0
-rw-r--r--apps/files/js/filelist.js2
-rw-r--r--apps/files/templates/fileexists.html8
-rw-r--r--apps/files/templates/list.php2
-rw-r--r--apps/files_sharing/lib/activity.php8
-rw-r--r--apps/files_trashbin/tests/expiration.php1
-rw-r--r--apps/files_versions/lib/storage.php3
-rw-r--r--apps/files_versions/tests/expirationtest.php1
-rw-r--r--apps/files_versions/tests/versions.php37
-rw-r--r--config/config.sample.php15
-rw-r--r--core/ajax/share.php31
-rw-r--r--core/command/app/checkcode.php66
-rw-r--r--core/command/config/listconfigs.php43
-rw-r--r--core/css/apps.css1
-rw-r--r--core/css/fixes.css5
-rw-r--r--core/css/styles.css20
-rw-r--r--core/js/multiselect.js3
-rw-r--r--core/register_command.php3
-rw-r--r--core/templates/login.php2
-rw-r--r--lib/base.php69
-rw-r--r--lib/private/allconfig.php11
-rw-r--r--lib/private/app/codechecker/infochecker.php146
-rw-r--r--lib/private/log.php15
-rw-r--r--lib/private/preview.php7
-rw-r--r--lib/private/server.php1
-rw-r--r--lib/private/share/share.php1
-rw-r--r--lib/private/systemconfig.php54
-rw-r--r--lib/private/template.php117
-rw-r--r--lib/private/util.php53
-rw-r--r--lib/public/iconfig.php15
-rw-r--r--lib/public/iservercontainer.php6
-rw-r--r--settings/js/users/users.js29
-rw-r--r--settings/templates/users/main.php15
-rw-r--r--settings/users.php7
-rw-r--r--tests/apps/testapp-infoxml-version-different/appinfo/info.xml9
-rw-r--r--tests/apps/testapp-infoxml-version-different/appinfo/version1
-rw-r--r--tests/apps/testapp-infoxml-version/appinfo/info.xml9
-rw-r--r--tests/apps/testapp-infoxml-version/appinfo/version1
-rw-r--r--tests/apps/testapp-infoxml/appinfo/info.xml9
-rw-r--r--tests/apps/testapp-name-missing/appinfo/info.xml8
-rw-r--r--tests/apps/testapp-version-missing/appinfo/info.xml8
-rw-r--r--tests/apps/testapp-version/appinfo/info.xml8
-rw-r--r--tests/apps/testapp-version/appinfo/version1
-rw-r--r--tests/core/command/config/listconfigstest.php25
-rw-r--r--tests/lib/app/codechecker/infocheckertest.php73
-rw-r--r--tests/lib/share/share.php37
46 files changed, 815 insertions, 171 deletions
diff --git a/3rdparty b/3rdparty
-Subproject 338ab170afcb4770e79cc4427a9803cb29a0a23
+Subproject 3cd7b7048e33e0076c1f94cf2ed721934e0c497
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 4b1b38d783c..ad3dce19778 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -925,7 +925,7 @@
if (this._allowSelection) {
td.append(
'<input id="select-' + this.id + '-' + fileData.id +
- '" type="checkbox" class="selectCheckBox"/><label for="select-' + this.id + '-' + fileData.id + '">' +
+ '" type="checkbox" class="selectCheckBox checkbox"/><label for="select-' + this.id + '-' + fileData.id + '">' +
'<div class="thumbnail" style="background-image:url(' + icon + '); background-size: 32px;"></div>' +
'<span class="hidden-visually">' + t('files', 'Select') + '</span>' +
'</label>'
diff --git a/apps/files/templates/fileexists.html b/apps/files/templates/fileexists.html
index c783f9a05c7..e3513237d2b 100644
--- a/apps/files/templates/fileexists.html
+++ b/apps/files/templates/fileexists.html
@@ -3,14 +3,14 @@
<span class="what">{what}<!-- If you select both versions, the copied file will have a number added to its name. --></span><br/>
<br/>
<table>
- <th><input id="checkbox-allnewfiles" class="allnewfiles" type="checkbox" /><label for="checkbox-allnewfiles">{allnewfiles}<span class="count"></span></label></th>
- <th><input id="checkbox-allexistingfiles" class="allexistingfiles" type="checkbox" /><label for="checkbox-allexistingfiles">{allexistingfiles}<span class="count"></span></label></th>
+ <th><input id="checkbox-allnewfiles" class="allnewfiles checkbox" type="checkbox" /><label for="checkbox-allnewfiles">{allnewfiles}<span class="count"></span></label></th>
+ <th><input id="checkbox-allexistingfiles" class="allexistingfiles checkbox" type="checkbox" /><label for="checkbox-allexistingfiles">{allexistingfiles}<span class="count"></span></label></th>
</table>
<div class="conflicts">
<div class="template">
<div class="filename"></div>
<div class="replacement">
- <input type="checkbox" class="u-left"/>
+ <input type="checkbox" class="checkbox u-left"/>
<label>
<span class="svg icon"></span>
<div class="mtime"></div>
@@ -18,7 +18,7 @@
</label>
</div>
<div class="original">
- <input type="checkbox" class="u-left" />
+ <input type="checkbox" class="checkbox u-left" />
<label>
<span class="svg icon"></span>
<div class="mtime"></div>
diff --git a/apps/files/templates/list.php b/apps/files/templates/list.php
index 15af1970dc3..bbbce8473de 100644
--- a/apps/files/templates/list.php
+++ b/apps/files/templates/list.php
@@ -56,7 +56,7 @@
<tr>
<th id='headerName' class="hidden column-name">
<div id="headerName-container">
- <input type="checkbox" id="select_all_files" class="select-all"/>
+ <input type="checkbox" id="select_all_files" class="select-all checkbox"/>
<label for="select_all_files">
<span class="hidden-visually"><?php p($l->t('Select all'))?></span>
</label>
diff --git a/apps/files_sharing/lib/activity.php b/apps/files_sharing/lib/activity.php
index 1257e7a445c..63ac2e90b2a 100644
--- a/apps/files_sharing/lib/activity.php
+++ b/apps/files_sharing/lib/activity.php
@@ -58,6 +58,7 @@ class Activity implements IExtension {
const SUBJECT_RESHARED_GROUP_BY = 'reshared_group_by';
const SUBJECT_RESHARED_LINK_BY = 'reshared_link_by';
const SUBJECT_RESHARED_USER_BY = 'reshared_user_by';
+ const SUBJECT_SHARED_EMAIL = 'shared_with_email';
const SUBJECT_SHARED_WITH_BY = 'shared_with_by';
/** @var IFactory */
@@ -182,6 +183,8 @@ class Activity implements IExtension {
return (string) $l->t('%2$s shared %1$s with you', $params);
case self::SUBJECT_SHARED_LINK_SELF:
return (string) $l->t('You shared %1$s via link', $params);
+ case self::SUBJECT_SHARED_EMAIL:
+ return (string) $l->t('You shared %1$s with %2$s', $params);
}
}
@@ -227,6 +230,11 @@ class Activity implements IExtension {
1 => 'username',
2 => '',
];
+ case self::SUBJECT_SHARED_EMAIL:
+ return array(
+ 0 => 'file',
+ 1 => '',// 'email' is neither supported nor planned for now
+ );
case self::SUBJECT_SHARED_USER_SELF:
case self::SUBJECT_SHARED_WITH_BY:
diff --git a/apps/files_trashbin/tests/expiration.php b/apps/files_trashbin/tests/expiration.php
index b3c6fcd95af..76fb24aa4df 100644
--- a/apps/files_trashbin/tests/expiration.php
+++ b/apps/files_trashbin/tests/expiration.php
@@ -207,6 +207,7 @@ class Expiration_Test extends \PHPUnit_Framework_TestCase {
'setSystemValues',
'setSystemValue',
'getSystemValue',
+ 'getFilteredSystemValue',
'deleteSystemValue',
'getAppKeys',
'setAppValue',
diff --git a/apps/files_versions/lib/storage.php b/apps/files_versions/lib/storage.php
index 6aa58c55e9b..bdf1811c5f9 100644
--- a/apps/files_versions/lib/storage.php
+++ b/apps/files_versions/lib/storage.php
@@ -315,6 +315,9 @@ class Storage {
if (self::copyFileContents($users_view, 'files_versions' . $filename . '.v' . $revision, 'files' . $filename)) {
$files_view->touch($file, $revision);
Storage::scheduleExpire($uid, $file);
+ \OC_Hook::emit('\OCP\Versions', 'rollback', array(
+ 'path' => $filename,
+ ));
return true;
} else if ($versionCreated) {
self::deleteVersion($users_view, $version);
diff --git a/apps/files_versions/tests/expirationtest.php b/apps/files_versions/tests/expirationtest.php
index 54024b85b78..11a4746c5e7 100644
--- a/apps/files_versions/tests/expirationtest.php
+++ b/apps/files_versions/tests/expirationtest.php
@@ -177,6 +177,7 @@ class Expiration_Test extends \Test\TestCase {
'setSystemValues',
'setSystemValue',
'getSystemValue',
+ 'getFilteredSystemValue',
'deleteSystemValue',
'getAppKeys',
'setAppValue',
diff --git a/apps/files_versions/tests/versions.php b/apps/files_versions/tests/versions.php
index da214ead60a..d4a85c8bffe 100644
--- a/apps/files_versions/tests/versions.php
+++ b/apps/files_versions/tests/versions.php
@@ -580,6 +580,35 @@ class Test_Files_Versioning extends \Test\TestCase {
$this->doTestRestore();
}
+ /**
+ * @param string $hookName name of hook called
+ * @param string $params variable to recieve parameters provided by hook
+ */
+ private function connectMockHooks($hookName, &$params) {
+ if ($hookName === null) {
+ return;
+ }
+
+ $eventHandler = $this->getMockBuilder('\stdclass')
+ ->setMethods(['callback'])
+ ->getMock();
+
+ $eventHandler->expects($this->any())
+ ->method('callback')
+ ->will($this->returnCallback(
+ function($p) use (&$params) {
+ $params = $p;
+ }
+ ));
+
+ \OCP\Util::connectHook(
+ '\OCP\Versions',
+ $hookName,
+ $eventHandler,
+ 'callback'
+ );
+ }
+
private function doTestRestore() {
$filePath = self::TEST_VERSIONS_USER . '/files/sub/test.txt';
$this->rootView->file_put_contents($filePath, 'test file');
@@ -608,7 +637,15 @@ class Test_Files_Versioning extends \Test\TestCase {
$this->assertEquals('test file', $this->rootView->file_get_contents($filePath));
$info1 = $this->rootView->getFileInfo($filePath);
+ $params = array();
+ $this->connectMockHooks('rollback', $params);
+
\OCA\Files_Versions\Storage::rollback('sub/test.txt', $t2);
+ $expectedParams = array(
+ 'path' => '/sub/test.txt',
+ );
+
+ $this->assertEquals($expectedParams, $params);
$this->assertEquals('version2', $this->rootView->file_get_contents($filePath));
$info2 = $this->rootView->getFileInfo($filePath);
diff --git a/config/config.sample.php b/config/config.sample.php
index 51529cdb0cc..e0c486d75c1 100644
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -806,6 +806,21 @@ $CONFIG = array(
*/
'ldapUserCleanupInterval' => 51,
+/**
+ * Enforce the existence of the home folder naming rule for all users
+ *
+ * Following scenario:
+ * * a home folder naming rule is set in LDAP advanced settings
+ * * a user doesn't have the home folder naming rule attribute set
+ *
+ * If this is set to **true** (default) it will NOT fallback to the core's
+ * default naming rule of using the internal user ID as home folder name.
+ *
+ * If this is set to **false** it will fallback for the users without the
+ * attribute set to naming the home folder like the internal user ID.
+ *
+ */
+'enforce_home_folder_naming_rule' => true,
/**
* Maintenance
diff --git a/core/ajax/share.php b/core/ajax/share.php
index 4546217def3..50c99cb56b4 100644
--- a/core/ajax/share.php
+++ b/core/ajax/share.php
@@ -183,6 +183,37 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo
$result = $mailNotification->sendLinkShareMail($to_address, $file, $link, $expiration);
if(empty($result)) {
+ // Get the token from the link
+ $linkParts = explode('/', $link);
+ $token = array_pop($linkParts);
+
+ // Get the share for the token
+ $share = \OCP\Share::getShareByToken($token, false);
+ if ($share !== false) {
+ $currentUser = \OC::$server->getUserSession()->getUser()->getUID();
+ $file = '/' . ltrim($file, '/');
+
+ // Check whether share belongs to the user and whether the file is the same
+ if ($share['file_target'] === $file && $share['uid_owner'] === $currentUser) {
+
+ // Get the path for the user
+ $view = new \OC\Files\View('/' . $currentUser . '/files');
+ $fileId = (int) $share['item_source'];
+ $path = $view->getPath((int) $share['item_source']);
+
+ if ($path !== null) {
+ $event = \OC::$server->getActivityManager()->generateEvent();
+ $event->setApp(\OCA\Files_Sharing\Activity::FILES_SHARING_APP)
+ ->setType(\OCA\Files_Sharing\Activity::TYPE_SHARED)
+ ->setAuthor($currentUser)
+ ->setAffectedUser($currentUser)
+ ->setObject('files', $fileId, $path)
+ ->setSubject(\OCA\Files_Sharing\Activity::SUBJECT_SHARED_EMAIL, [$path, $to_address]);
+ \OC::$server->getActivityManager()->publish($event);
+ }
+ }
+ }
+
\OCP\JSON::success();
} else {
$l = \OC::$server->getL10N('core');
diff --git a/core/command/app/checkcode.php b/core/command/app/checkcode.php
index a4e7322460f..9f6e0729ce9 100644
--- a/core/command/app/checkcode.php
+++ b/core/command/app/checkcode.php
@@ -26,6 +26,8 @@ namespace OC\Core\Command\App;
use OC\App\CodeChecker\CodeChecker;
use OC\App\CodeChecker\EmptyCheck;
+use OC\App\CodeChecker\InfoChecker;
+use OC\App\InfoParser;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@@ -33,12 +35,21 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class CheckCode extends Command {
+
+ /** @var InfoParser */
+ private $infoParser;
+
protected $checkers = [
'private' => '\OC\App\CodeChecker\PrivateCheck',
'deprecation' => '\OC\App\CodeChecker\DeprecationCheck',
'strong-comparison' => '\OC\App\CodeChecker\StrongComparisonCheck',
];
+ public function __construct(InfoParser $infoParser) {
+ parent::__construct();
+ $this->infoParser = $infoParser;
+ }
+
protected function configure() {
$this
->setName('app:check-code')
@@ -54,6 +65,12 @@ class CheckCode extends Command {
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'enable the specified checker(s)',
[ 'private', 'deprecation', 'strong-comparison' ]
+ )
+ ->addOption(
+ '--skip-validate-info',
+ null,
+ InputOption::VALUE_NONE,
+ 'skips the info.xml/version check'
);
}
@@ -84,7 +101,7 @@ class CheckCode extends Command {
$output->writeln("<info>Analysing {$filename}</info>");
}
- // show error count if there are errros present or the verbosity is high
+ // show error count if there are errors present or the verbosity is high
if($count > 0 || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
$output->writeln(" {$count} errors");
}
@@ -98,6 +115,53 @@ class CheckCode extends Command {
}
});
$errors = $codeChecker->analyse($appId);
+
+ if(!$input->getOption('skip-validate-info')) {
+ $infoChecker = new InfoChecker($this->infoParser);
+
+ $infoChecker->listen('InfoChecker', 'mandatoryFieldMissing', function($key) use ($output) {
+ $output->writeln("<error>Mandatory field missing: $key</error>");
+ });
+
+ $infoChecker->listen('InfoChecker', 'deprecatedFieldFound', function($key, $value) use ($output) {
+ if($value === [] || is_null($value) || $value === '') {
+ $output->writeln("<info>Deprecated field available: $key</info>");
+ } else {
+ $output->writeln("<info>Deprecated field available: $key => $value</info>");
+ }
+ });
+
+ $infoChecker->listen('InfoChecker', 'differentVersions', function($versionFile, $infoXML) use ($output) {
+ $output->writeln("<error>Different versions provided (appinfo/version: $versionFile - appinfo/info.xml: $infoXML)</error>");
+ });
+
+ $infoChecker->listen('InfoChecker', 'sameVersions', function($path) use ($output) {
+ $output->writeln("<info>Version file isn't needed anymore and can be safely removed ($path)</info>");
+ });
+
+ $infoChecker->listen('InfoChecker', 'migrateVersion', function($version) use ($output) {
+ $output->writeln("<info>Migrate the app version to appinfo/info.xml (add <version>$version</version> to appinfo/info.xml and remove appinfo/version)</info>");
+ });
+
+ if(OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
+ $infoChecker->listen('InfoChecker', 'mandatoryFieldFound', function($key, $value) use ($output) {
+ $output->writeln("<info>Mandatory field available: $key => $value</info>");
+ });
+
+ $infoChecker->listen('InfoChecker', 'optionalFieldFound', function($key, $value) use ($output) {
+ $output->writeln("<info>Optional field available: $key => $value</info>");
+ });
+
+ $infoChecker->listen('InfoChecker', 'unusedFieldFound', function($key, $value) use ($output) {
+ $output->writeln("<info>Unused field available: $key => $value</info>");
+ });
+ }
+
+ $infoErrors = $infoChecker->analyse($appId);
+
+ $errors = array_merge($errors, $infoErrors);
+ }
+
if (empty($errors)) {
$output->writeln('<info>App is compliant - awesome job!</info>');
return 0;
diff --git a/core/command/config/listconfigs.php b/core/command/config/listconfigs.php
index 5796362f2fc..37aeb53c6f5 100644
--- a/core/command/config/listconfigs.php
+++ b/core/command/config/listconfigs.php
@@ -32,20 +32,6 @@ use Symfony\Component\Console\Output\OutputInterface;
class ListConfigs extends Base {
protected $defaultOutputFormat = self::OUTPUT_FORMAT_JSON_PRETTY;
- /** @var array */
- protected $sensitiveValues = [
- 'dbpassword' => true,
- 'dbuser' => true,
- 'mail_smtpname' => true,
- 'mail_smtppassword' => true,
- 'passwordsalt' => true,
- 'secret' => true,
- 'ldap_agent_password' => true,
- 'objectstore' => ['arguments' => ['password' => true]],
- ];
-
- const SENSITIVE_VALUE = '***REMOVED SENSITIVE VALUE***';
-
/** * @var SystemConfig */
protected $systemConfig;
@@ -127,10 +113,10 @@ class ListConfigs extends Base {
$configs = [];
foreach ($keys as $key) {
- $value = $this->systemConfig->getValue($key, serialize(null));
-
- if ($noSensitiveValues && isset($this->sensitiveValues[$key])) {
- $value = $this->removeSensitiveValue($this->sensitiveValues[$key], $value);
+ if ($noSensitiveValues) {
+ $value = $this->systemConfig->getFilteredValue($key, serialize(null));
+ } else {
+ $value = $this->systemConfig->getValue($key, serialize(null));
}
if ($value !== 'N;') {
@@ -140,25 +126,4 @@ class ListConfigs extends Base {
return $configs;
}
-
- /**
- * @param bool|array $keysToRemove
- * @param mixed $value
- * @return mixed
- */
- protected function removeSensitiveValue($keysToRemove, $value) {
- if ($keysToRemove === true) {
- return self::SENSITIVE_VALUE;
- }
-
- if (is_array($value)) {
- foreach ($keysToRemove as $keyToRemove => $valueToRemove) {
- if (isset($value[$keyToRemove])) {
- $value[$keyToRemove] = $this->removeSensitiveValue($valueToRemove, $value[$keyToRemove]);
- }
- }
- }
-
- return $value;
- }
}
diff --git a/core/css/apps.css b/core/css/apps.css
index 6dd7e63bb69..23e0c519d00 100644
--- a/core/css/apps.css
+++ b/core/css/apps.css
@@ -417,7 +417,6 @@
position: relative;
height: 100%;
overflow-y: auto;
- -webkit-overflow-scrolling: touch;
}
#app-content-wrapper {
diff --git a/core/css/fixes.css b/core/css/fixes.css
index e5dbeb137ab..7ef44ba6909 100644
--- a/core/css/fixes.css
+++ b/core/css/fixes.css
@@ -115,8 +115,3 @@ select {
line-height: 38px;
}
-.lte8 input[type="checkbox"] + label:before { background-image: url('../img/actions/checkbox.png'); }
-.lte8 input[type="checkbox"].white + label:before { background-image: url('../img/actions/checkbox-white.png'); }
-.lte8 input[type="checkbox"]:checked + label:before { background-image: url('../img/actions/checkbox-checked.png'); }
-.lte8 input[type="checkbox"].white:checked + label:before { background-image: url('../img/actions/checkbox-checked-white.png'); }
-
diff --git a/core/css/styles.css b/core/css/styles.css
index aefc0ff755a..d952a33c24a 100644
--- a/core/css/styles.css
+++ b/core/css/styles.css
@@ -158,7 +158,9 @@ textarea:hover, textarea:focus, textarea:active {
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
opacity: 1;
}
-input[type="checkbox"] {
+
+/* ie8 doesn't support :checked */
+html:not(.ie8) input[type="checkbox"].checkbox {
margin:0;
padding:0;
height:auto;
@@ -166,7 +168,7 @@ input[type="checkbox"] {
display: none;
}
-input[type="checkbox"] + label:before {
+html:not(.ie8) input[type="checkbox"].checkbox + label:before {
content: "";
display: inline-block;
@@ -174,27 +176,27 @@ input[type="checkbox"] + label:before {
width: 20px;
vertical-align: middle;
- background: url('../img/actions/checkbox.svg') left center no-repeat;
+ background: url('../img/actions/checkbox.svg') left top no-repeat;
opacity: 0.7;
}
-input[type="checkbox"]:disabled +label:before { opacity: .6; }
+html:not(.ie8) input[type="checkbox"].checkbox:disabled +label:before { opacity: .6; }
-input[type="checkbox"].u-left +label:before { float: left; }
+html:not(.ie8) input[type="checkbox"].checkbox.u-left +label:before { float: left; }
-input[type="checkbox"].white + label:before {
+html:not(.ie8) input[type="checkbox"].checkbox--white + label:before {
background-image: url('../img/actions/checkbox-white.svg');
}
-input[type="checkbox"]:checked + label:before {
+html:not(.ie8) input[type="checkbox"].checkbox:checked + label:before {
background-image: url('../img/actions/checkbox-checked.svg');
}
-input[type="checkbox"].white:checked + label:before {
+html:not(.ie8) input[type="checkbox"].checkbox--white:checked + label:before {
background-image: url('../img/actions/checkbox-checked-white.svg');
}
-input[type="checkbox"]:hover+label:before, input[type="checkbox"]:focus+label:before {
+html:not(.ie8) input[type="checkbox"].checkbox:hover+label:before, input[type="checkbox"]:focus+label:before {
color:#111 !important;
}
diff --git a/core/js/multiselect.js b/core/js/multiselect.js
index 41dc68ac051..6d5c54ac0f5 100644
--- a/core/js/multiselect.js
+++ b/core/js/multiselect.js
@@ -109,6 +109,9 @@
var id='ms'+multiSelectId+'-option-'+item;
var input=$('<input type="' + inputType + '"/>');
input.attr('id',id);
+ if(inputType === 'checkbox') {
+ input.addClass('checkbox');
+ }
if(settings.singleSelect) {
input.attr('name', 'ms'+multiSelectId+'-option');
}
diff --git a/core/register_command.php b/core/register_command.php
index 114e115c491..878542f72c9 100644
--- a/core/register_command.php
+++ b/core/register_command.php
@@ -28,7 +28,8 @@
/** @var $application Symfony\Component\Console\Application */
$application->add(new OC\Core\Command\Status);
$application->add(new OC\Core\Command\Check(\OC::$server->getConfig()));
-$application->add(new OC\Core\Command\App\CheckCode());
+$infoParser = new \OC\App\InfoParser(\OC::$server->getHTTPHelper(), \OC::$server->getURLGenerator());
+$application->add(new OC\Core\Command\App\CheckCode($infoParser));
$application->add(new OC\Core\Command\L10n\CreateJs());
if (\OC::$server->getConfig()->getSystemValue('installed', false)) {
diff --git a/core/templates/login.php b/core/templates/login.php
index 2057b1034d0..db77f63bbd0 100644
--- a/core/templates/login.php
+++ b/core/templates/login.php
@@ -65,7 +65,7 @@ script('core', [
<?php endif; ?>
<?php if ($_['rememberLoginAllowed'] === true) : ?>
<div class="remember-login-container">
- <input type="checkbox" name="remember_login" value="1" id="remember_login" class="white">
+ <input type="checkbox" name="remember_login" value="1" id="remember_login" class="checkbox checkbox--white">
<label for="remember_login"><?php p($l->t('remember')); ?></label>
</div>
<?php endif; ?>
diff --git a/lib/base.php b/lib/base.php
index 3624a3fbaf9..32b90cad1fa 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -376,63 +376,6 @@ class OC {
$tmpl->printPage();
}
- public static function initTemplateEngine() {
- // Add the stuff we need always
- // following logic will import all vendor libraries that are
- // specified in core/js/core.json
- $fileContent = file_get_contents(OC::$SERVERROOT . '/core/js/core.json');
- if($fileContent !== false) {
- $coreDependencies = json_decode($fileContent, true);
- foreach($coreDependencies['vendor'] as $vendorLibrary) {
- // remove trailing ".js" as addVendorScript will append it
- OC_Util::addVendorScript(
- substr($vendorLibrary, 0, strlen($vendorLibrary) - 3));
- }
- } else {
- throw new \Exception('Cannot read core/js/core.json');
- }
-
- OC_Util::addScript("placeholders");
- OC_Util::addScript("compatibility");
- OC_Util::addScript("jquery.ocdialog");
- OC_Util::addScript("oc-dialogs");
- OC_Util::addScript("js");
- OC_Util::addScript("l10n");
- OC_Util::addTranslations("core");
- OC_Util::addScript("octemplate");
- OC_Util::addScript("eventsource");
- OC_Util::addScript("config");
- OC_Util::addScript('search', 'search');
- OC_Util::addScript("oc-requesttoken");
- OC_Util::addScript("apps");
- OC_Util::addScript('mimetype');
- OC_Util::addScript('mimetypelist');
- OC_Util::addVendorScript('snapjs/dist/latest/snap');
- OC_Util::addVendorScript('core', 'backbone/backbone');
- OC_Util::addScript('oc-backbone');
-
- // avatars
- if (\OC::$server->getSystemConfig()->getValue('enable_avatars', true) === true) {
- \OC_Util::addScript('placeholder');
- \OC_Util::addVendorScript('blueimp-md5/js/md5');
- \OC_Util::addScript('jquery.avatar');
- \OC_Util::addScript('avatar');
- }
-
- OC_Util::addStyle("styles");
- OC_Util::addStyle("header");
- OC_Util::addStyle("mobile");
- OC_Util::addStyle("icons");
- OC_Util::addStyle("fonts");
- OC_Util::addStyle("apps");
- OC_Util::addStyle("fixes");
- OC_Util::addStyle("multiselect");
- OC_Util::addVendorStyle('jquery-ui/themes/base/jquery-ui');
- OC_Util::addStyle('jquery-ui-fixes');
- OC_Util::addStyle("tooltip");
- OC_Util::addStyle("jquery.ocdialog");
- }
-
public static function initSession() {
// prevents javascript from accessing php session cookies
ini_set('session.cookie_httponly', true);
@@ -611,7 +554,6 @@ class OC {
self::initSession();
}
\OC::$server->getEventLogger()->end('init_session');
- self::initTemplateEngine();
self::checkConfig();
self::checkInstalled();
@@ -673,7 +615,7 @@ class OC {
self::registerFilesystemHooks();
if ($systemConfig->getValue('enable_previews', true)) {
self::registerPreviewHooks();
- }
+ }
self::registerShareHooks();
self::registerLogRotate();
self::registerLocalAddressBook();
@@ -686,12 +628,6 @@ class OC {
$lockProvider = \OC::$server->getLockingProvider();
register_shutdown_function(array($lockProvider, 'releaseAll'));
- if ($systemConfig->getValue('installed', false) && !self::checkUpgrade(false)) {
- if (\OC::$server->getConfig()->getAppValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') {
- OC_Util::addScript('backgroundjobs');
- }
- }
-
// Check whether the sample configuration has been copied
if($systemConfig->getValue('copied_sample_config', false)) {
$l = \OC::$server->getL10N('lib');
@@ -803,8 +739,9 @@ class OC {
OC_Hook::connect('\OCP\Versions', 'preDelete', 'OC\Preview', 'prepare_delete');
OC_Hook::connect('\OCP\Trashbin', 'preDelete', 'OC\Preview', 'prepare_delete');
OC_Hook::connect('OC_Filesystem', 'post_delete', 'OC\Preview', 'post_delete_files');
- OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete');
+ OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete_versions');
OC_Hook::connect('\OCP\Trashbin', 'delete', 'OC\Preview', 'post_delete');
+ OC_Hook::connect('\OCP\Versions', 'rollback', 'OC\Preview', 'post_delete_versions');
}
/**
diff --git a/lib/private/allconfig.php b/lib/private/allconfig.php
index 63cc92601bb..7c2037e8048 100644
--- a/lib/private/allconfig.php
+++ b/lib/private/allconfig.php
@@ -119,6 +119,17 @@ class AllConfig implements \OCP\IConfig {
}
/**
+ * Looks up a system wide defined value and filters out sensitive data
+ *
+ * @param string $key the key of the value, under which it was saved
+ * @param mixed $default the default value to be returned if the value isn't set
+ * @return mixed the value or $default
+ */
+ public function getFilteredSystemValue($key, $default = '') {
+ return $this->systemConfig->getFilteredValue($key, $default);
+ }
+
+ /**
* Delete a system wide defined value
*
* @param string $key the key of the value, under which it was saved
diff --git a/lib/private/app/codechecker/infochecker.php b/lib/private/app/codechecker/infochecker.php
new file mode 100644
index 00000000000..91580bde07d
--- /dev/null
+++ b/lib/private/app/codechecker/infochecker.php
@@ -0,0 +1,146 @@
+<?php
+/**
+ * @author Morris Jobke <hey@morrisjobke.de>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\App\CodeChecker;
+
+use OC\App\InfoParser;
+use OC\Hooks\BasicEmitter;
+
+class InfoChecker extends BasicEmitter {
+
+ /** @var InfoParser */
+ private $infoParser;
+
+ private $mandatoryFields = [
+ 'author',
+ 'description',
+ 'id',
+ 'licence',
+ 'name',
+ ];
+ private $optionalFields = [
+ 'bugs',
+ 'category',
+ 'default_enable',
+ 'dependencies',
+ 'documentation',
+ 'namespace',
+ 'ocsid',
+ 'public',
+ 'remote',
+ 'repository',
+ 'require',
+ 'requiremin',
+ 'types',
+ 'version',
+ 'website',
+ ];
+ private $deprecatedFields = [
+ 'info',
+ 'shipped',
+ 'standalone',
+ ];
+
+ public function __construct(InfoParser $infoParser) {
+ $this->infoParser = $infoParser;
+ }
+
+ /**
+ * @param string $appId
+ * @return array
+ */
+ public function analyse($appId) {
+ $appPath = \OC_App::getAppPath($appId);
+ if ($appPath === false) {
+ throw new \RuntimeException("No app with given id <$appId> known.");
+ }
+
+ $errors = [];
+
+ $info = $this->infoParser->parse($appPath . '/appinfo/info.xml');
+
+ foreach ($info as $key => $value) {
+ if(is_array($value)) {
+ $value = json_encode($value);
+ }
+ if (in_array($key, $this->mandatoryFields)) {
+ $this->emit('InfoChecker', 'mandatoryFieldFound', [$key, $value]);
+ continue;
+ }
+
+ if (in_array($key, $this->optionalFields)) {
+ $this->emit('InfoChecker', 'optionalFieldFound', [$key, $value]);
+ continue;
+ }
+
+ if (in_array($key, $this->deprecatedFields)) {
+ // skip empty arrays - empty arrays for remote and public are always added
+ if($value === '[]' && in_array($key, ['public', 'remote', 'info'])) {
+ continue;
+ }
+ $this->emit('InfoChecker', 'deprecatedFieldFound', [$key, $value]);
+ continue;
+ }
+
+ $this->emit('InfoChecker', 'unusedFieldFound', [$key, $value]);
+ }
+
+ foreach ($this->mandatoryFields as $key) {
+ if(!isset($info[$key])) {
+ $this->emit('InfoChecker', 'mandatoryFieldMissing', [$key]);
+ $errors[] = [
+ 'type' => 'mandatoryFieldMissing',
+ 'field' => $key,
+ ];
+ }
+ }
+
+ $versionFile = $appPath . '/appinfo/version';
+ if (is_file($versionFile)) {
+ $version = trim(file_get_contents($versionFile));
+ if(isset($info['version'])) {
+ if($info['version'] !== $version) {
+ $this->emit('InfoChecker', 'differentVersions',
+ [$version, $info['version']]);
+ $errors[] = [
+ 'type' => 'differentVersions',
+ 'message' => 'appinfo/version: ' . $version .
+ ' - appinfo/info.xml: ' . $info['version'],
+ ];
+ } else {
+ $this->emit('InfoChecker', 'sameVersions', [$versionFile]);
+ }
+ } else {
+ $this->emit('InfoChecker', 'migrateVersion', [$version]);
+ }
+ } else {
+ if(!isset($info['version'])) {
+ $this->emit('InfoChecker', 'mandatoryFieldMissing', ['version']);
+ $errors[] = [
+ 'type' => 'mandatoryFieldMissing',
+ 'field' => 'version',
+ ];
+ }
+ }
+
+ return $errors;
+ }
+}
diff --git a/lib/private/log.php b/lib/private/log.php
index 1b26ece7624..4a0a34b7113 100644
--- a/lib/private/log.php
+++ b/lib/private/log.php
@@ -3,6 +3,7 @@
* @author Bart Visscher <bartv@thisnet.nl>
* @author Bernhard Posselt <dev@bernhard-posselt.com>
* @author Morris Jobke <hey@morrisjobke.de>
+ * @author Olivier Paroz <owncloud@oparoz.com>
* @author Robin Appelman <icewind@owncloud.com>
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Victor Dubiniuk <dubiniuk@owncloud.com>
@@ -26,6 +27,8 @@
namespace OC;
+use InterfaSys\LogNormalizer\Normalizer;
+
use \OCP\ILogger;
use OCP\Security\StringUtils;
@@ -48,12 +51,15 @@ class Log implements ILogger {
/** @var boolean|null cache the result of the log condition check for the request */
private $logConditionSatisfied = null;
+ /** @var Normalizer */
+ private $normalizer;
/**
* @param string $logger The logger that should be used
* @param SystemConfig $config the system config object
+ * @param null $normalizer
*/
- public function __construct($logger=null, SystemConfig $config=null) {
+ public function __construct($logger=null, SystemConfig $config=null, $normalizer = null) {
// FIXME: Add this for backwards compatibility, should be fixed at some point probably
if($config === null) {
$config = \OC::$server->getSystemConfig();
@@ -68,6 +74,11 @@ class Log implements ILogger {
} else {
$this->logger = $logger;
}
+ if ($normalizer === null) {
+ $this->normalizer = new Normalizer();
+ } else {
+ $this->normalizer = $normalizer;
+ }
}
@@ -175,6 +186,8 @@ class Log implements ILogger {
$minLevel = min($this->config->getValue('loglevel', \OCP\Util::WARN), \OCP\Util::ERROR);
$logCondition = $this->config->getValue('log.condition', []);
+ array_walk($context, [$this->normalizer, 'format']);
+
if (isset($context['app'])) {
$app = $context['app'];
diff --git a/lib/private/preview.php b/lib/private/preview.php
index 978da1161c2..de964b72df2 100644
--- a/lib/private/preview.php
+++ b/lib/private/preview.php
@@ -1296,6 +1296,13 @@ class Preview {
/**
* @param array $args
+ */
+ public static function post_delete_versions($args) {
+ self::post_delete($args, 'files/');
+ }
+
+ /**
+ * @param array $args
* @param string $prefix
*/
public static function post_delete($args, $prefix = '') {
diff --git a/lib/private/server.php b/lib/private/server.php
index 9f99ead849b..26eb99927fc 100644
--- a/lib/private/server.php
+++ b/lib/private/server.php
@@ -1098,4 +1098,5 @@ class Server extends SimpleContainer implements IServerContainer {
public function getUserStoragesService() {
return \OC_Mount_Config::$app->getContainer()->query('OCA\\Files_External\\Service\\UserStoragesService');
}
+
}
diff --git a/lib/private/share/share.php b/lib/private/share/share.php
index 07c7f31a853..32389f34868 100644
--- a/lib/private/share/share.php
+++ b/lib/private/share/share.php
@@ -1998,7 +1998,6 @@ class Share extends Constants {
$suggestedItemTarget = $result['suggestedItemTarget'];
$suggestedFileTarget = $result['suggestedFileTarget'];
$filePath = $result['filePath'];
- $expirationDate = $result['expirationDate'];
}
$isGroupShare = false;
diff --git a/lib/private/systemconfig.php b/lib/private/systemconfig.php
index 13b0959768a..94b815aebd7 100644
--- a/lib/private/systemconfig.php
+++ b/lib/private/systemconfig.php
@@ -22,12 +22,28 @@
namespace OC;
+
+use OCP\IConfig;
+
/**
* Class which provides access to the system config values stored in config.php
* Internal class for bootstrap only.
* fixes cyclic DI: AllConfig needs AppConfig needs Database needs AllConfig
*/
class SystemConfig {
+
+ /** @var array */
+ protected $sensitiveValues = [
+ 'dbpassword' => true,
+ 'dbuser' => true,
+ 'mail_smtpname' => true,
+ 'mail_smtppassword' => true,
+ 'passwordsalt' => true,
+ 'secret' => true,
+ 'ldap_agent_password' => true,
+ 'objectstore' => ['arguments' => ['password' => true]],
+ ];
+
/**
* Lists all available config keys
* @return array an array of key names
@@ -68,6 +84,23 @@ class SystemConfig {
}
/**
+ * Looks up a system wide defined value and filters out sensitive data
+ *
+ * @param string $key the key of the value, under which it was saved
+ * @param mixed $default the default value to be returned if the value isn't set
+ * @return mixed the value or $default
+ */
+ public function getFilteredValue($key, $default = '') {
+ $value = $this->getValue($key, $default);
+
+ if (isset($this->sensitiveValues[$key])) {
+ $value = $this->removeSensitiveValue($this->sensitiveValues[$key], $value);
+ }
+
+ return $value;
+ }
+
+ /**
* Delete a system wide defined value
*
* @param string $key the key of the value, under which it was saved
@@ -75,4 +108,25 @@ class SystemConfig {
public function deleteValue($key) {
\OC_Config::deleteKey($key);
}
+
+ /**
+ * @param bool|array $keysToRemove
+ * @param mixed $value
+ * @return mixed
+ */
+ protected function removeSensitiveValue($keysToRemove, $value) {
+ if ($keysToRemove === true) {
+ return IConfig::SENSITIVE_VALUE;
+ }
+
+ if (is_array($value)) {
+ foreach ($keysToRemove as $keyToRemove => $valueToRemove) {
+ if (isset($value[$keyToRemove])) {
+ $value[$keyToRemove] = $this->removeSensitiveValue($valueToRemove, $value[$keyToRemove]);
+ }
+ }
+ }
+
+ return $value;
+ }
}
diff --git a/lib/private/template.php b/lib/private/template.php
index 920be71abbf..0300e43edea 100644
--- a/lib/private/template.php
+++ b/lib/private/template.php
@@ -37,27 +37,40 @@ require_once __DIR__.'/template/functions.php';
* This class provides the templates for ownCloud.
*/
class OC_Template extends \OC\Template\Base {
- private $renderas; // Create a full page?
+
+ /** @var string */
+ private $renderAs; // Create a full page?
+
+ /** @var string */
private $path; // The path to the template
+
+ /** @var array */
private $headers = array(); //custom headers
+
+ /** @var string */
protected $app; // app id
/**
* Constructor
* @param string $app app providing the template
* @param string $name of the template file (without suffix)
- * @param string $renderas = ""; produce a full page
+ * @param string $renderAs = ""; produce a full page
* @param bool $registerCall = true
* @return OC_Template object
*
* This function creates an OC_Template object.
*
- * If $renderas is set, OC_Template will try to produce a full page in the
- * according layout. For now, renderas can be set to "guest", "user" or
+ * If $renderAs is set, OC_Template will try to produce a full page in the
+ * according layout. For now, $renderAs can be set to "guest", "user" or
* "admin".
*/
- public function __construct( $app, $name, $renderas = "", $registerCall = true ) {
+
+ protected static $initTemplateEngineFirstRun = true;
+
+ public function __construct( $app, $name, $renderAs = "", $registerCall = true ) {
// Read the selected theme from the config file
+ self::initTemplateEngine();
+
$theme = OC_Util::getTheme();
$requesttoken = (OC::$server->getSession() and $registerCall) ? OC_Util::callRegister() : '';
@@ -69,13 +82,85 @@ class OC_Template extends \OC\Template\Base {
list($path, $template) = $this->findTemplate($theme, $app, $name);
// Set the private data
- $this->renderas = $renderas;
+ $this->renderAs = $renderAs;
$this->path = $path;
$this->app = $app;
parent::__construct($template, $requesttoken, $l10n, $themeDefaults);
}
+ public static function initTemplateEngine() {
+ if (self::$initTemplateEngineFirstRun){
+
+ //apps that started before the template initialization can load their own scripts/styles
+ //so to make sure this scripts/styles here are loaded first we use OC_Util::addScript() with $prepend=true
+ //meaning the last script/style in this list will be loaded first
+ if (\OC::$server->getSystemConfig ()->getValue ( 'installed', false ) && ! \OCP\Util::needUpgrade ()) {
+ if (\OC::$server->getConfig ()->getAppValue ( 'core', 'backgroundjobs_mode', 'ajax' ) == 'ajax') {
+ OC_Util::addScript ( 'backgroundjobs', null, true );
+ }
+ }
+
+ OC_Util::addStyle("tooltip",null,true);
+ OC_Util::addStyle('jquery-ui-fixes',null,true);
+ OC_Util::addVendorStyle('jquery-ui/themes/base/jquery-ui',null,true);
+ OC_Util::addStyle("multiselect",null,true);
+ OC_Util::addStyle("fixes",null,true);
+ OC_Util::addStyle("apps",null,true);
+ OC_Util::addStyle("fonts",null,true);
+ OC_Util::addStyle("icons",null,true);
+ OC_Util::addStyle("mobile",null,true);
+ OC_Util::addStyle("header",null,true);
+ OC_Util::addStyle("styles",null,true);
+
+ // avatars
+ if (\OC::$server->getSystemConfig()->getValue('enable_avatars', true) === true) {
+ \OC_Util::addScript('avatar', null, true);
+ \OC_Util::addScript('jquery.avatar', null, true);
+ \OC_Util::addScript('placeholder', null, true);
+ }
+
+ OC_Util::addScript('oc-backbone', null, true);
+ OC_Util::addVendorScript('core', 'backbone/backbone', true);
+ OC_Util::addVendorScript('snapjs/dist/latest/snap', null, true);
+ OC_Util::addScript('mimetypelist', null, true);
+ OC_Util::addScript('mimetype', null, true);
+ OC_Util::addScript("apps", null, true);
+ OC_Util::addScript("oc-requesttoken", null, true);
+ OC_Util::addScript('search', 'search', true);
+ OC_Util::addScript("config", null, true);
+ OC_Util::addScript("eventsource", null, true);
+ OC_Util::addScript("octemplate", null, true);
+ OC_Util::addTranslations("core", null, true);
+ OC_Util::addScript("l10n", null, true);
+ OC_Util::addScript("js", null, true);
+ OC_Util::addScript("oc-dialogs", null, true);
+ OC_Util::addScript("jquery.ocdialog", null, true);
+ OC_Util::addStyle("jquery.ocdialog");
+ OC_Util::addScript("compatibility", null, true);
+ OC_Util::addScript("placeholders", null, true);
+
+ // Add the stuff we need always
+ // following logic will import all vendor libraries that are
+ // specified in core/js/core.json
+ $fileContent = file_get_contents(OC::$SERVERROOT . '/core/js/core.json');
+ if($fileContent !== false) {
+ $coreDependencies = json_decode($fileContent, true);
+ foreach(array_reverse($coreDependencies['vendor']) as $vendorLibrary) {
+ // remove trailing ".js" as addVendorScript will append it
+ OC_Util::addVendorScript(
+ substr($vendorLibrary, 0, strlen($vendorLibrary) - 3),null,true);
+ }
+ } else {
+ throw new \Exception('Cannot read core/js/core.json');
+ }
+
+ self::$initTemplateEngineFirstRun = false;
+ }
+
+ }
+
+
/**
* find the template with the given name
* @param string $name of the template file (without suffix)
@@ -118,14 +203,14 @@ class OC_Template extends \OC\Template\Base {
* Process the template
* @return boolean|string
*
- * This function process the template. If $this->renderas is set, it
+ * This function process the template. If $this->renderAs is set, it
* will produce a full page.
*/
public function fetchPage() {
$data = parent::fetchPage();
- if( $this->renderas ) {
- $page = new OC_TemplateLayout($this->renderas, $this->app);
+ if( $this->renderAs ) {
+ $page = new OC_TemplateLayout($this->renderAs, $this->app);
// Add custom headers
$headers = '';
@@ -141,18 +226,20 @@ class OC_Template extends \OC\Template\Base {
}
}
- $page->assign('headers', $headers, false);
+ $page->assign('headers', $headers);
- $page->assign('content', $data, false );
+ $page->assign('content', $data);
return $page->fetchPage();
}
- else{
- return $data;
- }
+
+ return $data;
}
/**
* Include template
+ *
+ * @param string $file
+ * @param array|null $additionalParams
* @return string returns content of included template
*
* Includes another template. use <?php echo $this->inc('template'); ?> to
@@ -222,7 +309,7 @@ class OC_Template extends \OC\Template\Base {
/**
* print error page using Exception details
- * @param Exception|Error $exception
+ * @param Exception $exception
*/
public static function printExceptionErrorPage($exception) {
$request = \OC::$server->getRequest();
diff --git a/lib/private/util.php b/lib/private/util.php
index 667d358655f..9abaef71a68 100644
--- a/lib/private/util.php
+++ b/lib/private/util.php
@@ -439,16 +439,23 @@ class OC_Util {
*
* @param string $application application id
* @param string|null $file filename
+ * @param bool $prepend prepend the Script to the beginning of the list
* @return void
*/
- public static function addScript($application, $file = null) {
+ public static function addScript($application, $file = null, $prepend = false) {
$path = OC_Util::generatePath($application, 'js', $file);
+ //TODO eliminate double code
if (!in_array($path, self::$scripts)) {
// core js files need separate handling
if ($application !== 'core' && $file !== null) {
self::addTranslations($application);
}
- self::$scripts[] = $path;
+ if ($prepend===true) {
+ array_unshift(self::$scripts, $path);
+ }
+ else {
+ self::$scripts[] = $path;
+ }
}
}
@@ -457,12 +464,18 @@ class OC_Util {
*
* @param string $application application id
* @param string|null $file filename
+ * @param bool $prepend prepend the Script to the beginning of the list
* @return void
*/
- public static function addVendorScript($application, $file = null) {
+ public static function addVendorScript($application, $file = null, $prepend = false) {
$path = OC_Util::generatePath($application, 'vendor', $file);
- if (!in_array($path, self::$scripts)) {
- self::$scripts[] = $path;
+ //TODO eliminate double code
+ if (! in_array ( $path, self::$scripts )) {
+ if ($prepend === true) {
+ array_unshift ( self::$scripts, $path );
+ } else {
+ self::$scripts [] = $path;
+ }
}
}
@@ -471,8 +484,9 @@ class OC_Util {
*
* @param string $application application id
* @param string $languageCode language code, defaults to the current language
+ * @param bool $prepend prepend the Script to the beginning of the list
*/
- public static function addTranslations($application, $languageCode = null) {
+ public static function addTranslations($application, $languageCode = null, $prepend = false) {
if (is_null($languageCode)) {
$languageCode = \OC_L10N::findLanguage($application);
}
@@ -481,8 +495,13 @@ class OC_Util {
} else {
$path = "l10n/$languageCode";
}
+ //TODO eliminate double code
if (!in_array($path, self::$scripts)) {
- self::$scripts[] = $path;
+ if ($prepend === true) {
+ array_unshift ( self::$scripts, $path );
+ } else {
+ self::$scripts [] = $path;
+ }
}
}
@@ -491,12 +510,18 @@ class OC_Util {
*
* @param string $application application id
* @param string|null $file filename
+ * @param bool $prepend prepend the Style to the beginning of the list
* @return void
*/
- public static function addStyle($application, $file = null) {
+ public static function addStyle($application, $file = null, $prepend = false) {
$path = OC_Util::generatePath($application, 'css', $file);
+ //TODO eliminate double code
if (!in_array($path, self::$styles)) {
- self::$styles[] = $path;
+ if ($prepend === true) {
+ array_unshift ( self::$styles, $path );
+ } else {
+ self::$styles[] = $path;
+ }
}
}
@@ -505,12 +530,18 @@ class OC_Util {
*
* @param string $application application id
* @param string|null $file filename
+ * @param bool $prepend prepend the Style to the beginning of the list
* @return void
*/
- public static function addVendorStyle($application, $file = null) {
+ public static function addVendorStyle($application, $file = null, $prepend = false) {
$path = OC_Util::generatePath($application, 'vendor', $file);
+ //TODO eliminate double code
if (!in_array($path, self::$styles)) {
- self::$styles[] = $path;
+ if ($prepend === true) {
+ array_unshift ( self::$styles, $path );
+ } else {
+ self::$styles[] = $path;
+ }
}
}
diff --git a/lib/public/iconfig.php b/lib/public/iconfig.php
index ff0b6c6a5b0..933eef97ae1 100644
--- a/lib/public/iconfig.php
+++ b/lib/public/iconfig.php
@@ -41,6 +41,11 @@ namespace OCP;
*/
interface IConfig {
/**
+ * @since 8.2.0
+ */
+ const SENSITIVE_VALUE = '***REMOVED SENSITIVE VALUE***';
+
+ /**
* Sets and deletes system wide values
*
* @param array $configs Associative array with `key => value` pairs
@@ -69,6 +74,16 @@ interface IConfig {
public function getSystemValue($key, $default = '');
/**
+ * Looks up a system wide defined value and filters out sensitive data
+ *
+ * @param string $key the key of the value, under which it was saved
+ * @param mixed $default the default value to be returned if the value isn't set
+ * @return mixed the value or $default
+ * @since 8.2.0
+ */
+ public function getFilteredSystemValue($key, $default = '');
+
+ /**
* Delete a system wide defined value
*
* @param string $key the key of the value, under which it was saved
diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php
index 8be23dff214..e37652c1adc 100644
--- a/lib/public/iservercontainer.php
+++ b/lib/public/iservercontainer.php
@@ -194,6 +194,12 @@ interface IServerContainer {
public function getAppConfig();
/**
+ * @return \OCP\L10N\IFactory
+ * @since 8.2.0
+ */
+ public function getL10NFactory();
+
+ /**
* get an L10N instance
* @param string $app appid
* @param string $lang
diff --git a/settings/js/users/users.js b/settings/js/users/users.js
index 5b12366ad40..47d63c11b95 100644
--- a/settings/js/users/users.js
+++ b/settings/js/users/users.js
@@ -813,44 +813,73 @@ $(document).ready(function () {
});
});
+ if ($('#CheckboxStorageLocation').is(':checked')) {
+ $("#userlist .storageLocation").show();
+ }
// Option to display/hide the "Storage location" column
$('#CheckboxStorageLocation').click(function() {
if ($('#CheckboxStorageLocation').is(':checked')) {
$("#userlist .storageLocation").show();
+ OC.AppConfig.setValue('core', 'umgmt_show_storage_location', 'true');
} else {
$("#userlist .storageLocation").hide();
+ OC.AppConfig.setValue('core', 'umgmt_show_storage_location', 'false');
}
});
+
+ if ($('#CheckboxLastLogin').is(':checked')) {
+ $("#userlist .lastLogin").show();
+ }
// Option to display/hide the "Last Login" column
$('#CheckboxLastLogin').click(function() {
if ($('#CheckboxLastLogin').is(':checked')) {
$("#userlist .lastLogin").show();
+ OC.AppConfig.setValue('core', 'umgmt_show_last_login', 'true');
} else {
$("#userlist .lastLogin").hide();
+ OC.AppConfig.setValue('core', 'umgmt_show_last_login', 'false');
}
});
+
+ if ($('#CheckboxEmailAddress').is(':checked')) {
+ $("#userlist .mailAddress").show();
+ }
// Option to display/hide the "Mail Address" column
$('#CheckboxEmailAddress').click(function() {
if ($('#CheckboxEmailAddress').is(':checked')) {
$("#userlist .mailAddress").show();
+ OC.AppConfig.setValue('core', 'umgmt_show_email', 'true');
} else {
$("#userlist .mailAddress").hide();
+ OC.AppConfig.setValue('core', 'umgmt_show_email', 'false');
}
});
+
+ if ($('#CheckboxUserBackend').is(':checked')) {
+ $("#userlist .userBackend").show();
+ }
// Option to display/hide the "User Backend" column
$('#CheckboxUserBackend').click(function() {
if ($('#CheckboxUserBackend').is(':checked')) {
$("#userlist .userBackend").show();
+ OC.AppConfig.setValue('core', 'umgmt_show_backend', 'true');
} else {
$("#userlist .userBackend").hide();
+ OC.AppConfig.setValue('core', 'umgmt_show_backend', 'false');
}
});
+
+ if ($('#CheckboxMailOnUserCreate').is(':checked')) {
+ $("#newemail").show();
+ }
// Option to display/hide the "E-Mail" input field
$('#CheckboxMailOnUserCreate').click(function() {
if ($('#CheckboxMailOnUserCreate').is(':checked')) {
$("#newemail").show();
+ OC.AppConfig.setValue('core', 'umgmt_send_email', 'true');
} else {
$("#newemail").hide();
+ OC.AppConfig.setValue('core', 'umgmt_send_email', 'false');
}
});
diff --git a/settings/templates/users/main.php b/settings/templates/users/main.php
index 73552f8ad2e..0abe31f4a59 100644
--- a/settings/templates/users/main.php
+++ b/settings/templates/users/main.php
@@ -45,31 +45,36 @@ translation('settings');
<div id="userlistoptions">
<p>
- <input type="checkbox" name="StorageLocation" value="StorageLocation" id="CheckboxStorageLocation">
+ <input type="checkbox" name="StorageLocation" value="StorageLocation" id="CheckboxStorageLocation"
+ <?php if ($_['show_storage_location'] === 'true') print_unescaped('checked="checked"'); ?> />
<label for="CheckboxStorageLocation">
<?php p($l->t('Show storage location')) ?>
</label>
</p>
<p>
- <input type="checkbox" name="LastLogin" value="LastLogin" id="CheckboxLastLogin">
+ <input type="checkbox" name="LastLogin" value="LastLogin" id="CheckboxLastLogin"
+ <?php if ($_['show_last_login'] === 'true') print_unescaped('checked="checked"'); ?> />
<label for="CheckboxLastLogin">
<?php p($l->t('Show last log in')) ?>
</label>
</p>
<p>
- <input type="checkbox" name="UserBackend" value="UserBackend" id="CheckboxUserBackend">
+ <input type="checkbox" name="UserBackend" value="UserBackend" id="CheckboxUserBackend"
+ <?php if ($_['show_backend'] === 'true') print_unescaped('checked="checked"'); ?> />
<label for="CheckboxUserBackend">
<?php p($l->t('Show user backend')) ?>
</label>
</p>
<p>
- <input type="checkbox" name="MailOnUserCreate" value="MailOnUserCreate" id="CheckboxMailOnUserCreate">
+ <input type="checkbox" name="MailOnUserCreate" value="MailOnUserCreate" id="CheckboxMailOnUserCreate"
+ <?php if ($_['send_email'] === 'true') print_unescaped('checked="checked"'); ?> />
<label for="CheckboxMailOnUserCreate">
<?php p($l->t('Send email to new user')) ?>
</label>
</p>
<p>
- <input type="checkbox" name="EmailAddress" value="EmailAddress" id="CheckboxEmailAddress">
+ <input type="checkbox" name="EmailAddress" value="EmailAddress" id="CheckboxEmailAddress"
+ <?php if ($_['show_email'] === 'true') print_unescaped('checked="checked"'); ?> />
<label for="CheckboxEmailAddress">
<?php p($l->t('Show email address')) ?>
</label>
diff --git a/settings/users.php b/settings/users.php
index 843995a57f9..e0ef56f15c5 100644
--- a/settings/users.php
+++ b/settings/users.php
@@ -99,4 +99,11 @@ $tmpl->assign('default_quota', $defaultQuota);
$tmpl->assign('defaultQuotaIsUserDefined', $defaultQuotaIsUserDefined);
$tmpl->assign('recoveryAdminEnabled', $recoveryAdminEnabled);
$tmpl->assign('enableAvatars', \OC::$server->getConfig()->getSystemValue('enable_avatars', true));
+
+$tmpl->assign('show_storage_location', $config->getAppValue('core', 'umgmt_show_storage_location', 'false'));
+$tmpl->assign('show_last_login', $config->getAppValue('core', 'umgmt_show_last_login', 'false'));
+$tmpl->assign('show_email', $config->getAppValue('core', 'umgmt_show_email', 'false'));
+$tmpl->assign('show_backend', $config->getAppValue('core', 'umgmt_show_backend', 'false'));
+$tmpl->assign('send_email', $config->getAppValue('core', 'umgmt_send_email', 'false'));
+
$tmpl->printPage();
diff --git a/tests/apps/testapp-infoxml-version-different/appinfo/info.xml b/tests/apps/testapp-infoxml-version-different/appinfo/info.xml
new file mode 100644
index 00000000000..c765400a76f
--- /dev/null
+++ b/tests/apps/testapp-infoxml-version-different/appinfo/info.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<info>
+ <id>testapp-infoxml-version</id>
+ <version>1.2.3</version>
+ <author>Jane</author>
+ <description>A b c</description>
+ <licence>Abc</licence>
+ <name>Test app</name>
+</info>
diff --git a/tests/apps/testapp-infoxml-version-different/appinfo/version b/tests/apps/testapp-infoxml-version-different/appinfo/version
new file mode 100644
index 00000000000..e8ea05db814
--- /dev/null
+++ b/tests/apps/testapp-infoxml-version-different/appinfo/version
@@ -0,0 +1 @@
+1.2.4
diff --git a/tests/apps/testapp-infoxml-version/appinfo/info.xml b/tests/apps/testapp-infoxml-version/appinfo/info.xml
new file mode 100644
index 00000000000..c765400a76f
--- /dev/null
+++ b/tests/apps/testapp-infoxml-version/appinfo/info.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<info>
+ <id>testapp-infoxml-version</id>
+ <version>1.2.3</version>
+ <author>Jane</author>
+ <description>A b c</description>
+ <licence>Abc</licence>
+ <name>Test app</name>
+</info>
diff --git a/tests/apps/testapp-infoxml-version/appinfo/version b/tests/apps/testapp-infoxml-version/appinfo/version
new file mode 100644
index 00000000000..0495c4a88ca
--- /dev/null
+++ b/tests/apps/testapp-infoxml-version/appinfo/version
@@ -0,0 +1 @@
+1.2.3
diff --git a/tests/apps/testapp-infoxml/appinfo/info.xml b/tests/apps/testapp-infoxml/appinfo/info.xml
new file mode 100644
index 00000000000..cb63a0fc76e
--- /dev/null
+++ b/tests/apps/testapp-infoxml/appinfo/info.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<info>
+ <id>testapp-infoxml</id>
+ <version>1.2.3</version>
+ <author>Jane</author>
+ <description>A b c</description>
+ <licence>Abc</licence>
+ <name>Test app</name>
+</info>
diff --git a/tests/apps/testapp-name-missing/appinfo/info.xml b/tests/apps/testapp-name-missing/appinfo/info.xml
new file mode 100644
index 00000000000..f0a62b8d380
--- /dev/null
+++ b/tests/apps/testapp-name-missing/appinfo/info.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<info>
+ <id>testapp-version</id>
+ <version>1.1.1</version>
+ <author>Jane</author>
+ <description>A b c</description>
+ <licence>Abc</licence>
+</info>
diff --git a/tests/apps/testapp-version-missing/appinfo/info.xml b/tests/apps/testapp-version-missing/appinfo/info.xml
new file mode 100644
index 00000000000..d7da3e07e36
--- /dev/null
+++ b/tests/apps/testapp-version-missing/appinfo/info.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<info>
+ <id>testapp-version</id>
+ <author>Jane</author>
+ <description>A b c</description>
+ <licence>Abc</licence>
+ <name>Test app</name>
+</info>
diff --git a/tests/apps/testapp-version/appinfo/info.xml b/tests/apps/testapp-version/appinfo/info.xml
new file mode 100644
index 00000000000..d7da3e07e36
--- /dev/null
+++ b/tests/apps/testapp-version/appinfo/info.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<info>
+ <id>testapp-version</id>
+ <author>Jane</author>
+ <description>A b c</description>
+ <licence>Abc</licence>
+ <name>Test app</name>
+</info>
diff --git a/tests/apps/testapp-version/appinfo/version b/tests/apps/testapp-version/appinfo/version
new file mode 100644
index 00000000000..0495c4a88ca
--- /dev/null
+++ b/tests/apps/testapp-version/appinfo/version
@@ -0,0 +1 @@
+1.2.3
diff --git a/tests/core/command/config/listconfigstest.php b/tests/core/command/config/listconfigstest.php
index 7492701cce3..bde6a1b0db3 100644
--- a/tests/core/command/config/listconfigstest.php
+++ b/tests/core/command/config/listconfigstest.php
@@ -23,6 +23,7 @@ namespace Tests\Core\Command\Config;
use OC\Core\Command\Config\ListConfigs;
+use OCP\IConfig;
use Test\TestCase;
class ListConfigsTest extends TestCase {
@@ -66,7 +67,7 @@ class ListConfigsTest extends TestCase {
'overwrite.cli.url',
],
[
- ['secret', 'N;', 'my secret'],
+ ['secret', 'N;', IConfig::SENSITIVE_VALUE],
['overwrite.cli.url', 'N;', 'http://localhost'],
],
// app config
@@ -81,7 +82,7 @@ class ListConfigsTest extends TestCase {
false,
json_encode([
'system' => [
- 'secret' => ListConfigs::SENSITIVE_VALUE,
+ 'secret' => IConfig::SENSITIVE_VALUE,
'overwrite.cli.url' => 'http://localhost',
],
'apps' => [
@@ -139,12 +140,12 @@ class ListConfigsTest extends TestCase {
'overwrite.cli.url',
],
[
- ['secret', 'N;', 'my secret'],
+ ['secret', 'N;', IConfig::SENSITIVE_VALUE],
['objectstore', 'N;', [
'class' => 'OC\\Files\\ObjectStore\\Swift',
'arguments' => [
'username' => 'facebook100000123456789',
- 'password' => 'Secr3tPaSSWoRdt7',
+ 'password' => IConfig::SENSITIVE_VALUE,
],
]],
['overwrite.cli.url', 'N;', 'http://localhost'],
@@ -161,12 +162,12 @@ class ListConfigsTest extends TestCase {
false,
json_encode([
'system' => [
- 'secret' => ListConfigs::SENSITIVE_VALUE,
+ 'secret' => IConfig::SENSITIVE_VALUE,
'objectstore' => [
'class' => 'OC\\Files\\ObjectStore\\Swift',
'arguments' => [
'username' => 'facebook100000123456789',
- 'password' => ListConfigs::SENSITIVE_VALUE,
+ 'password' => IConfig::SENSITIVE_VALUE,
],
],
'overwrite.cli.url' => 'http://localhost',
@@ -276,9 +277,15 @@ class ListConfigsTest extends TestCase {
$this->systemConfig->expects($this->any())
->method('getKeys')
->willReturn($systemConfigs);
- $this->systemConfig->expects($this->any())
- ->method('getValue')
- ->willReturnMap($systemConfigMap);
+ if ($private) {
+ $this->systemConfig->expects($this->any())
+ ->method('getValue')
+ ->willReturnMap($systemConfigMap);
+ } else {
+ $this->systemConfig->expects($this->any())
+ ->method('getFilteredValue')
+ ->willReturnMap($systemConfigMap);
+ }
$this->appConfig->expects($this->any())
->method('getApps')
diff --git a/tests/lib/app/codechecker/infocheckertest.php b/tests/lib/app/codechecker/infocheckertest.php
new file mode 100644
index 00000000000..59c1316b769
--- /dev/null
+++ b/tests/lib/app/codechecker/infocheckertest.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * @author Morris Jobke <hey@morrisjobke.de>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\App\CodeChecker;
+
+use OC\App\InfoParser;
+use Test\TestCase;
+
+class InfoCheckerTest extends TestCase {
+ /** @var InfoChecker */
+ protected $infoChecker;
+
+ public static function setUpBeforeClass() {
+ \OC::$APPSROOTS[] = [
+ 'path' => \OC::$SERVERROOT . '/tests/apps',
+ 'url' => '/apps-test',
+ 'writable' => false,
+ ];
+ }
+
+ public static function tearDownAfterClass() {
+ // remove last element
+ array_pop(\OC::$APPSROOTS);
+ }
+
+ protected function setUp() {
+ parent::setUp();
+ $infoParser = new InfoParser(\OC::$server->getHTTPHelper(), \OC::$server->getURLGenerator());
+
+ $this->infoChecker = new InfoChecker($infoParser);
+ }
+
+ public function appInfoData() {
+ return [
+ ['testapp-infoxml', []],
+ ['testapp-version', []],
+ ['testapp-infoxml-version', []],
+ ['testapp-infoxml-version-different', [['type' => 'differentVersions', 'message' => 'appinfo/version: 1.2.4 - appinfo/info.xml: 1.2.3']]],
+ ['testapp-version-missing', [['type' => 'mandatoryFieldMissing', 'field' => 'version']]],
+ ['testapp-name-missing', [['type' => 'mandatoryFieldMissing', 'field' => 'name']]],
+ ];
+ }
+
+ /**
+ * @dataProvider appInfoData
+ *
+ * @param $appId
+ * @param $expectedErrors
+ */
+ public function testApps($appId, $expectedErrors) {
+ $errors = $this->infoChecker->analyse($appId);
+
+ $this->assertEquals($expectedErrors, $errors);
+ }
+}
diff --git a/tests/lib/share/share.php b/tests/lib/share/share.php
index ef0d9822085..58a76470afa 100644
--- a/tests/lib/share/share.php
+++ b/tests/lib/share/share.php
@@ -1567,6 +1567,43 @@ class Test_Share extends \Test\TestCase {
$this->setHttpHelper($oldHttpHelper);
}
+ /**
+ * Test case for #19119
+ */
+ public function testReshareWithLinkDefaultExpirationDate() {
+ $config = \OC::$server->getConfig();
+ $config->setAppValue('core', 'shareapi_default_expire_date', 'yes');
+ $config->setAppValue('core', 'shareapi_expire_after_n_days', '2');
+
+ // Expiration date
+ $expireAt = time() + 2 * 24*60*60;
+ $date = new DateTime();
+ $date->setTimestamp($expireAt);
+ $date->setTime(0, 0, 0);
+
+ //Share a file from user 1 to user 2
+ $this->shareUserTestFileWithUser($this->user1, $this->user2);
+
+ //User 2 shares as link
+ OC_User::setUserId($this->user2);
+ $result = OCP\Share::shareItem('test', 'test.txt', OCP\Share::SHARE_TYPE_LINK, null, \OCP\Constants::PERMISSION_READ);
+ $this->assertTrue(is_string($result));
+
+ //Check if expire date is correct
+ $result = OCP\Share::getItemShared('test', 'test.txt');
+ $this->assertCount(1, $result);
+ $result = reset($result);
+ $this->assertNotEmpty($result['expiration']);
+ $expireDate = new DateTime($result['expiration']);
+ $this->assertEquals($date, $expireDate);
+
+ //Unshare
+ $this->assertTrue(OCP\Share::unshareAll('test', 'test.txt'));
+
+ //Reset config
+ $config->deleteAppValue('core', 'shareapi_default_expire_date');
+ $config->deleteAppValue('core', 'shareapi_expire_after_n_days');
+ }
}
class DummyShareClass extends \OC\Share\Share {