diff --git a/.github/workflows/phpunit-32bits.yml b/.github/workflows/phpunit-32bits.yml
new file mode 100644
index 0000000000000..1f91281bf1613
--- /dev/null
+++ b/.github/workflows/phpunit-32bits.yml
@@ -0,0 +1,58 @@
+name: PHPUnit
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: "15 1 * * 1-6"
+
+permissions:
+ contents: read
+
+concurrency:
+ group: phpunit-32bits-${{ github.head_ref || github.run_id }}
+ cancel-in-progress: true
+
+jobs:
+ phpunit-32bits:
+ runs-on: ubuntu-latest
+ container: shivammathur/node:latest-i386
+
+ strategy:
+ matrix:
+ php-versions: ['8.0']
+
+ steps:
+ - name: Checkout server
+ uses: actions/checkout@v3
+ with:
+ submodules: true
+
+ - name: Install tools
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y ffmpeg imagemagick libmagickcore-6.q16-3-extra
+
+ - name: Set up php ${{ matrix.php-versions }}
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php-versions }}
+ extensions: ctype, curl, dom, fileinfo, gd, imagick, intl, json, mbstring, openssl, pdo_sqlite, posix, sqlite, xml, zip, apcu
+ tools: phpunit:9
+ coverage: none
+ ini-values:
+ apc.enabled=on,
+ apc.enable_cli=on
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Set up Nextcloud
+ env:
+ DB_PORT: 4444
+ run: |
+ mkdir data
+ ./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=autotest --database-pass=rootpassword --admin-user admin --admin-pass admin
+ php -f index.php
+
+ - name: PHPUnit
+ working-directory: tests
+ run: phpunit --configuration phpunit-autotest.xml --exclude-group PRIMARY-azure,PRIMARY-s3,PRIMARY-swift,Memcached,Redis,RoutingWeirdness
diff --git a/.github/workflows/smb-kerberos.yml b/.github/workflows/smb-kerberos.yml
index f47a06fbed794..1cb8ae973ca88 100644
--- a/.github/workflows/smb-kerberos.yml
+++ b/.github/workflows/smb-kerberos.yml
@@ -6,15 +6,17 @@ on:
- stable*
paths:
- 'apps/files_external/**'
+ - '.github/workflows/smb-kerberos.yml'
pull_request:
paths:
- 'apps/files_external/**'
+ - '.github/workflows/smb-kerberos.yml'
jobs:
smb-kerberos-tests:
runs-on: ubuntu-latest
- name: kerberos
+ name: smb-kerberos-sso
steps:
- name: Checkout server
@@ -28,9 +30,12 @@ jobs:
docker pull icewind1991/samba-krb-test-client
- name: Setup AD-DC
run: |
+ cp apps/files_external/tests/*.sh .
mkdir data
sudo chown -R 33 data apps config
- apps/files_external/tests/setup-krb.sh
+ DC_IP=$(./start-dc.sh)
+ ./start-apache.sh $DC_IP $PWD
+ echo "DC_IP=$DC_IP" >> $GITHUB_ENV
- name: Set up Nextcloud
run: |
docker exec --user 33 apache ./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
@@ -39,7 +44,8 @@ jobs:
# setup user_saml
docker exec --user 33 apache ./occ app:enable user_saml --force
docker exec --user 33 apache ./occ config:app:set user_saml type --value 'environment-variable'
- docker exec --user 33 apache ./occ config:app:set user_saml general-uid_mapping --value REMOTE_USER
+ docker exec --user 33 apache ./occ saml:config:create
+ docker exec --user 33 apache ./occ saml:config:set 1 --general-uid_mapping=REMOTE_USER
# setup external storage
docker exec --user 33 apache ./occ app:enable files_external --force
@@ -49,16 +55,18 @@ jobs:
docker exec --user 33 apache ./occ files_external:list
- name: Test SSO
run: |
- mkdir cookies
- chmod 0777 cookies
+ mkdir /tmp/shared/cookies
+ chmod 0777 /tmp/shared/cookies
- DC_IP=$(docker inspect dc --format '{{.NetworkSettings.IPAddress}}')
echo "SAML login"
- docker run --rm --name client -v $PWD/cookies:/cookies -v /tmp/shared:/shared --dns $DC_IP --hostname client.domain.test icewind1991/samba-krb-test-client \
- curl -c /cookies/jar --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/index.php/apps/user_saml/saml/login
+ ./client-cmd.sh ${{ env.DC_IP }} curl -c /shared/cookies/jar -s --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/index.php/apps/user_saml/saml/login
echo "Check we are logged in"
- CONTENT=$(docker run --rm --name client -v $PWD/cookies:/cookies -v /tmp/shared:/shared --dns $DC_IP --hostname client.domain.test icewind1991/samba-krb-test-client \
- curl -b /cookies/jar -s --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/remote.php/webdav/smb/test.txt)
- echo $CONTENT
- CONTENT=$(echo $CONTENT | tr -d '[:space:]')
+ CONTENT=$(./client-cmd.sh ${{ env.DC_IP }} curl -b /shared/cookies/jar -s --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/remote.php/webdav/smb/test.txt)
+ CONTENT=$(echo $CONTENT | head -n 1 | tr -d '[:space:]')
[[ $CONTENT == "testfile" ]]
+ - name: Show logs
+ if: failure()
+ run: |
+ docker exec --user 33 apache ./occ log:file
+ FILEPATH=$(docker exec --user 33 apache ./occ log:file | grep "Log file:" | cut -d' ' -f3)
+ docker exec --user 33 apache cat $FILEPATH
diff --git a/apps/dav/l10n/cs.js b/apps/dav/l10n/cs.js
index 26470e05ec90d..869065e72cda4 100644
--- a/apps/dav/l10n/cs.js
+++ b/apps/dav/l10n/cs.js
@@ -72,8 +72,11 @@ OC.L10N.register(
"Where: %s" : "Kde: %s",
"%1$s via %2$s" : "%1$s prostřednictvím %2$s",
"Cancelled: %1$s" : "Zrušeno: %1$s",
+ "\"%1$s\" has been canceled" : "„%1$s“ bylo zrušeno",
"Re: %1$s" : "Odp.: %1$s",
+ "%1$s has responded your invitation" : "%1$s odpověděl(a) na vaši pozvánku",
"Invitation: %1$s" : "Pozvánka: %1$s",
+ "%1$s would like to invite you to \"%2$s\"" : "%1$s by vás ráda pozval(a) na „%2$s“",
"Organizer:" : "Organizátor:",
"Attendees:" : "Účastníci:",
"Title:" : "Název:",
diff --git a/apps/dav/l10n/cs.json b/apps/dav/l10n/cs.json
index 71fda38722697..d19552b583754 100644
--- a/apps/dav/l10n/cs.json
+++ b/apps/dav/l10n/cs.json
@@ -70,8 +70,11 @@
"Where: %s" : "Kde: %s",
"%1$s via %2$s" : "%1$s prostřednictvím %2$s",
"Cancelled: %1$s" : "Zrušeno: %1$s",
+ "\"%1$s\" has been canceled" : "„%1$s“ bylo zrušeno",
"Re: %1$s" : "Odp.: %1$s",
+ "%1$s has responded your invitation" : "%1$s odpověděl(a) na vaši pozvánku",
"Invitation: %1$s" : "Pozvánka: %1$s",
+ "%1$s would like to invite you to \"%2$s\"" : "%1$s by vás ráda pozval(a) na „%2$s“",
"Organizer:" : "Organizátor:",
"Attendees:" : "Účastníci:",
"Title:" : "Název:",
diff --git a/apps/dav/lib/CalDAV/BirthdayService.php b/apps/dav/lib/CalDAV/BirthdayService.php
index df351a475524a..70b2e859f89a4 100644
--- a/apps/dav/lib/CalDAV/BirthdayService.php
+++ b/apps/dav/lib/CalDAV/BirthdayService.php
@@ -207,33 +207,26 @@ public function buildDateFromContact(string $cardData,
} catch (InvalidDataException $e) {
return null;
}
+ if ($dateParts['year'] !== null) {
+ $parameters = $birthday->parameters();
+ $omitYear = (isset($parameters['X-APPLE-OMIT-YEAR'])
+ && $parameters['X-APPLE-OMIT-YEAR'] === $dateParts['year']);
+ // 'X-APPLE-OMIT-YEAR' is not always present, at least iOS 12.4 uses the hard coded date of 1604 (the start of the gregorian calendar) when the year is unknown
+ if ($omitYear || (int)$dateParts['year'] === 1604) {
+ $dateParts['year'] = null;
+ }
+ }
- $unknownYear = false;
$originalYear = null;
- if (!$dateParts['year']) {
- $birthday = '1970-' . $dateParts['month'] . '-' . $dateParts['date'];
+ if ($dateParts['year'] !== null) {
+ $originalYear = (int)$dateParts['year'];
+ }
- $unknownYear = true;
- } else {
- $parameters = $birthday->parameters();
- if (isset($parameters['X-APPLE-OMIT-YEAR'])) {
- $omitYear = $parameters['X-APPLE-OMIT-YEAR'];
- if ($dateParts['year'] === $omitYear) {
- $birthday = '1970-' . $dateParts['month'] . '-' . $dateParts['date'];
- $unknownYear = true;
- }
- } else {
- $originalYear = (int)$dateParts['year'];
- // 'X-APPLE-OMIT-YEAR' is not always present, at least iOS 12.4 uses the hard coded date of 1604 (the start of the gregorian calendar) when the year is unknown
- if ($originalYear == 1604) {
- $originalYear = null;
- $unknownYear = true;
- $birthday = '1970-' . $dateParts['month'] . '-' . $dateParts['date'];
- }
- if ($originalYear < 1970) {
- $birthday = '1970-' . $dateParts['month'] . '-' . $dateParts['date'];
- }
- }
+ $leapDay = ((int)$dateParts['month'] === 2
+ && (int)$dateParts['date'] === 29);
+ if ($dateParts['year'] === null || $originalYear < 1970) {
+ $birthday = ($leapDay ? '1972-' : '1970-')
+ . $dateParts['month'] . '-' . $dateParts['date'];
}
try {
@@ -268,10 +261,15 @@ public function buildDateFromContact(string $cardData,
$vEvent->DTEND['VALUE'] = 'DATE';
$vEvent->{'UID'} = $doc->UID . $postfix;
$vEvent->{'RRULE'} = 'FREQ=YEARLY';
+ if ($leapDay) {
+ /* Sabre\VObject supports BYMONTHDAY only if BYMONTH
+ * is also set */
+ $vEvent->{'RRULE'} = 'FREQ=YEARLY;BYMONTH=2;BYMONTHDAY=-1';
+ }
$vEvent->{'SUMMARY'} = $summary;
$vEvent->{'TRANSP'} = 'TRANSPARENT';
$vEvent->{'X-NEXTCLOUD-BC-FIELD-TYPE'} = $dateField;
- $vEvent->{'X-NEXTCLOUD-BC-UNKNOWN-YEAR'} = $unknownYear ? '1' : '0';
+ $vEvent->{'X-NEXTCLOUD-BC-UNKNOWN-YEAR'} = $dateParts['year'] === null ? '1' : '0';
if ($originalYear !== null) {
$vEvent->{'X-NEXTCLOUD-BC-YEAR'} = (string) $originalYear;
}
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php
index 909a582805996..51eb505124e38 100644
--- a/apps/dav/lib/CalDAV/CalDavBackend.php
+++ b/apps/dav/lib/CalDAV/CalDavBackend.php
@@ -72,7 +72,6 @@
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IGroupManager;
-use OCP\IUser;
use OCP\IUserManager;
use OCP\Security\ISecureRandom;
use Psr\Log\LoggerInterface;
@@ -120,7 +119,6 @@
* @package OCA\DAV\CalDAV
*/
class CalDavBackend extends AbstractBackend implements SyncSupport, SubscriptionSupport, SchedulingSupport {
-
use TTransactional;
public const CALENDAR_TYPE_CALENDAR = 0;
@@ -346,7 +344,7 @@ public function getCalendarsForUser($principalUri) {
$row['principaluri'] = (string) $row['principaluri'];
$components = [];
if ($row['components']) {
- $components = explode(',',$row['components']);
+ $components = explode(',', $row['components']);
}
$calendar = [
@@ -420,7 +418,7 @@ public function getCalendarsForUser($principalUri) {
$row['displayname'] = $row['displayname'] . ' (' . ($this->userManager->getDisplayName($name) ?? ($name ?? '')) . ')';
$components = [];
if ($row['components']) {
- $components = explode(',',$row['components']);
+ $components = explode(',', $row['components']);
}
$calendar = [
'id' => $row['id'],
@@ -469,7 +467,7 @@ public function getUsersOwnCalendars($principalUri) {
$row['principaluri'] = (string) $row['principaluri'];
$components = [];
if ($row['components']) {
- $components = explode(',',$row['components']);
+ $components = explode(',', $row['components']);
}
$calendar = [
'id' => $row['id'],
@@ -521,7 +519,7 @@ public function getPublicCalendars() {
$row['displayname'] = $row['displayname'] . "($name)";
$components = [];
if ($row['components']) {
- $components = explode(',',$row['components']);
+ $components = explode(',', $row['components']);
}
$calendar = [
'id' => $row['id'],
@@ -586,7 +584,7 @@ public function getPublicCalendar($uri) {
$row['displayname'] = $row['displayname'] . ' ' . "($name)";
$components = [];
if ($row['components']) {
- $components = explode(',',$row['components']);
+ $components = explode(',', $row['components']);
}
$calendar = [
'id' => $row['id'],
@@ -639,7 +637,7 @@ public function getCalendarByUri($principal, $uri) {
$row['principaluri'] = (string) $row['principaluri'];
$components = [];
if ($row['components']) {
- $components = explode(',',$row['components']);
+ $components = explode(',', $row['components']);
}
$calendar = [
@@ -687,7 +685,7 @@ public function getCalendarById(int $calendarId): ?array {
$row['principaluri'] = (string) $row['principaluri'];
$components = [];
if ($row['components']) {
- $components = explode(',',$row['components']);
+ $components = explode(',', $row['components']);
}
$calendar = [
@@ -779,7 +777,7 @@ public function createCalendar($principalUri, $calendarUri, array $properties) {
if (!($properties[$sccs] instanceof SupportedCalendarComponentSet)) {
throw new DAV\Exception('The ' . $sccs . ' property must be of type: \Sabre\CalDAV\Property\SupportedCalendarComponentSet');
}
- $values['components'] = implode(',',$properties[$sccs]->getValue());
+ $values['components'] = implode(',', $properties[$sccs]->getValue());
} elseif (isset($properties['components'])) {
// Allow to provide components internally without having
// to create a SupportedCalendarComponentSet object
@@ -797,7 +795,7 @@ public function createCalendar($principalUri, $calendarUri, array $properties) {
}
}
- [$calendarId, $calendarData] = $this->atomic(function() use ($values) {
+ [$calendarId, $calendarData] = $this->atomic(function () use ($values) {
$query = $this->db->getQueryBuilder();
$query->insert('calendars');
foreach ($values as $column => $value) {
@@ -1712,7 +1710,7 @@ public function calendarSearch($principalUri, array $filters, $limit = null, $of
$query->expr()->eq('c.calendarid',
$query->createNamedParameter($id)),
$query->expr()->eq('c.calendartype',
- $query->createNamedParameter(self::CALENDAR_TYPE_CALENDAR)));
+ $query->createNamedParameter(self::CALENDAR_TYPE_CALENDAR)));
}
foreach ($sharedCalendars as $id) {
$calendarExpressions[] = $query->expr()->andX(
@@ -1860,7 +1858,7 @@ public function search(array $calendarInfo, $pattern, array $searchProperties,
}
}
- if(isset($options['uid'])) {
+ if (isset($options['uid'])) {
$outerQuery->andWhere($outerQuery->expr()->eq('uid', $outerQuery->createNamedParameter($options['uid'])));
}
@@ -2435,7 +2433,7 @@ public function createSubscription($principalUri, $uri, array $properties) {
}
}
- [$subscriptionId, $subscriptionRow] = $this->atomic(function() use ($values) {
+ [$subscriptionId, $subscriptionRow] = $this->atomic(function () use ($values) {
$valuesToInsert = [];
$query = $this->db->getQueryBuilder();
foreach (array_keys($values) as $name) {
diff --git a/apps/dav/lib/Connector/Sabre/Auth.php b/apps/dav/lib/Connector/Sabre/Auth.php
index 1610c554b9bba..69821c63c211e 100644
--- a/apps/dav/lib/Connector/Sabre/Auth.php
+++ b/apps/dav/lib/Connector/Sabre/Auth.php
@@ -104,14 +104,11 @@ protected function validateUserPass($username, $password) {
if ($this->userSession->isLoggedIn() &&
$this->isDavAuthenticated($this->userSession->getUser()->getUID())
) {
- \OC_Util::setupFS($this->userSession->getUser()->getUID());
$this->session->close();
return true;
} else {
- \OC_Util::setupFS(); //login hooks may need early access to the filesystem
try {
if ($this->userSession->logClientIn($username, $password, $this->request, $this->throttler)) {
- \OC_Util::setupFS($this->userSession->getUser()->getUID());
$this->session->set(self::DAV_AUTHENTICATED, $this->userSession->getUser()->getUID());
$this->session->close();
return true;
diff --git a/apps/dav/lib/Connector/Sabre/File.php b/apps/dav/lib/Connector/Sabre/File.php
index fd8a643722237..b0f17417d2195 100644
--- a/apps/dav/lib/Connector/Sabre/File.php
+++ b/apps/dav/lib/Connector/Sabre/File.php
@@ -138,7 +138,7 @@ public function __construct(View $view, FileInfo $info, IManager $shareManager =
public function put($data) {
try {
$exists = $this->fileView->file_exists($this->path);
- if ($this->info && $exists && !$this->info->isUpdateable()) {
+ if ($exists && !$this->info->isUpdateable()) {
throw new Forbidden();
}
} catch (StorageNotAvailableException $e) {
@@ -759,9 +759,6 @@ private function convertToSabreException(\Exception $e) {
* @return string|null
*/
public function getChecksum() {
- if (!$this->info) {
- return null;
- }
return $this->info->getChecksum();
}
diff --git a/apps/dav/lib/Connector/Sabre/FilesPlugin.php b/apps/dav/lib/Connector/Sabre/FilesPlugin.php
index f53c62afba27e..a6c9b8b4ebe4e 100644
--- a/apps/dav/lib/Connector/Sabre/FilesPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/FilesPlugin.php
@@ -53,10 +53,8 @@
use Sabre\DAV\Tree;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
-use Sabre\Uri;
class FilesPlugin extends ServerPlugin {
-
// namespace
public const NS_OWNCLOUD = 'http://owncloud.org/ns';
public const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
@@ -352,7 +350,7 @@ public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node)
$propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function () use ($node) {
return json_encode($this->previewManager->isAvailable($node->getFileInfo()), JSON_THROW_ON_ERROR);
});
- $propFind->handle(self::SIZE_PROPERTYNAME, function () use ($node): ?int {
+ $propFind->handle(self::SIZE_PROPERTYNAME, function () use ($node): int|float {
return $node->getSize();
});
$propFind->handle(self::MOUNT_TYPE_PROPERTYNAME, function () use ($node) {
@@ -382,7 +380,7 @@ public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node)
});
/**
* Return file/folder name as displayname. The primary reason to
- * implement it this way is to avoid costly fallback to
+ * implement it this way is to avoid costly fallback to
* CustomPropertiesBackend (esp. visible when querying all files
* in a folder).
*/
diff --git a/apps/dav/lib/Connector/Sabre/Node.php b/apps/dav/lib/Connector/Sabre/Node.php
index 1e32e74c325b6..ee159cef1d607 100644
--- a/apps/dav/lib/Connector/Sabre/Node.php
+++ b/apps/dav/lib/Connector/Sabre/Node.php
@@ -44,14 +44,12 @@
use OCP\Files\FileInfo;
use OCP\Files\IRootFolder;
use OCP\Files\StorageNotAvailableException;
-use OCP\Share\IShare;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
abstract class Node implements \Sabre\DAV\INode {
-
/**
- * @var \OC\Files\View
+ * @var View
*/
protected $fileView;
@@ -69,10 +67,7 @@ abstract class Node implements \Sabre\DAV\INode {
*/
protected $property_cache = null;
- /**
- * @var \OCP\Files\FileInfo
- */
- protected $info;
+ protected FileInfo $info;
/**
* @var IManager
@@ -83,10 +78,6 @@ abstract class Node implements \Sabre\DAV\INode {
/**
* Sets up the node, expects a full path name
- *
- * @param \OC\Files\View $view
- * @param \OCP\Files\FileInfo $info
- * @param IManager $shareManager
*/
public function __construct(View $view, FileInfo $info, IManager $shareManager = null) {
$this->fileView = $view;
@@ -109,8 +100,12 @@ public function __construct(View $view, FileInfo $info, IManager $shareManager =
}
}
- protected function refreshInfo() {
- $this->info = $this->fileView->getFileInfo($this->path);
+ protected function refreshInfo(): void {
+ $info = $this->fileView->getFileInfo($this->path);
+ if ($info === false) {
+ throw new \Sabre\DAV\Exception('Failed to get fileinfo for '. $this->path);
+ }
+ $this->info = $info;
$root = \OC::$server->get(IRootFolder::class);
if ($this->info->getType() === FileInfo::TYPE_FOLDER) {
$this->node = new Folder($root, $this->fileView, $this->path, $this->info);
@@ -145,7 +140,6 @@ public function getPath() {
* @throws \Sabre\DAV\Exception\Forbidden
*/
public function setName($name) {
-
// rename is only allowed if the update privilege is granted
if (!($this->info->isUpdateable() || ($this->info->getMountPoint() instanceof MoveableMount && $this->info->getInternalPath() === ''))) {
throw new \Sabre\DAV\Exception\Forbidden();
@@ -233,9 +227,10 @@ public function setUploadTime(int $time) {
/**
* Returns the size of the node, in bytes
*
- * @return integer
+ * @psalm-suppress ImplementedReturnTypeMismatch \Sabre\DAV\IFile::getSize signature does not support 32bit
+ * @return int|float
*/
- public function getSize() {
+ public function getSize(): int|float {
return $this->info->getSize();
}
@@ -271,7 +266,6 @@ public function getInternalFileId() {
* @return int
*/
public function getSharePermissions($user) {
-
// check of we access a federated share
if ($user !== null) {
try {
diff --git a/apps/dav/lib/Connector/Sabre/QuotaPlugin.php b/apps/dav/lib/Connector/Sabre/QuotaPlugin.php
index ff7396a0825e5..ddf4b2773e0b1 100644
--- a/apps/dav/lib/Connector/Sabre/QuotaPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/QuotaPlugin.php
@@ -178,7 +178,7 @@ public function beforeCopy(string $sourcePath, string $destinationPath): bool {
* This method is called before any HTTP method and validates there is enough free space to store the file
*
* @param string $path relative to the users home
- * @param int $length
+ * @param int|float|null $length
* @throws InsufficientStorage
* @return bool
*/
diff --git a/apps/dav/lib/Direct/DirectFile.php b/apps/dav/lib/Direct/DirectFile.php
index a4a1999aca715..45c2114747eb7 100644
--- a/apps/dav/lib/Direct/DirectFile.php
+++ b/apps/dav/lib/Direct/DirectFile.php
@@ -77,6 +77,10 @@ public function getETag() {
return $this->file->getEtag();
}
+ /**
+ * @psalm-suppress ImplementedReturnTypeMismatch \Sabre\DAV\IFile::getSize signature does not support 32bit
+ * @return int|float
+ */
public function getSize() {
$this->getFile();
diff --git a/apps/dav/lib/Upload/UploadFile.php b/apps/dav/lib/Upload/UploadFile.php
index 49a2fadecf6c8..023d17955c1d8 100644
--- a/apps/dav/lib/Upload/UploadFile.php
+++ b/apps/dav/lib/Upload/UploadFile.php
@@ -29,7 +29,6 @@
use Sabre\DAV\IFile;
class UploadFile implements IFile {
-
/** @var File */
private $file;
@@ -53,6 +52,10 @@ public function getETag() {
return $this->file->getETag();
}
+ /**
+ * @psalm-suppress ImplementedReturnTypeMismatch \Sabre\DAV\IFile::getSize signature does not support 32bit
+ * @return int|float
+ */
public function getSize() {
return $this->file->getSize();
}
diff --git a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
index cfdf82e9b4f89..69096d0cfbb90 100644
--- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
@@ -125,7 +125,6 @@ public function providesSharingData() {
* @dataProvider providesSharingData
*/
public function testCalendarSharing($userCanRead, $userCanWrite, $groupCanRead, $groupCanWrite, $add): void {
-
/** @var IL10N|\PHPUnit\Framework\MockObject\MockObject $l10n */
$l10n = $this->createMock(IL10N::class);
$l10n
@@ -423,7 +422,12 @@ public function testCalendarQuery($expectedEventsInResult, $propFilters, $compFi
$events[0] = $this->createEvent($calendarId, '20130912T130000Z', '20130912T140000Z');
$events[1] = $this->createEvent($calendarId, '20130912T150000Z', '20130912T170000Z');
$events[2] = $this->createEvent($calendarId, '20130912T173000Z', '20130912T220000Z');
- $events[3] = $this->createEvent($calendarId, '21130912T130000Z', '22130912T130000Z');
+ if (PHP_INT_SIZE > 8) {
+ $events[3] = $this->createEvent($calendarId, '21130912T130000Z', '22130912T130000Z');
+ } else {
+ /* On 32bit we do not support events after 2038 */
+ $events[3] = $this->createEvent($calendarId, '20370912T130000Z', '20370912T130000Z');
+ }
$result = $this->backend->calendarQuery($calendarId, [
'name' => '',
@@ -471,7 +475,7 @@ public function providesCalendarQueryParameters() {
'only-events' => [[0, 1, 2, 3], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => null, 'end' => null], 'prop-filters' => []]],],
'start' => [[1, 2, 3], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => new DateTime('2013-09-12 14:00:00', new DateTimeZone('UTC')), 'end' => null], 'prop-filters' => []]],],
'end' => [[0], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => null, 'end' => new DateTime('2013-09-12 14:00:00', new DateTimeZone('UTC'))], 'prop-filters' => []]],],
- 'future' => [[3], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => new DateTime('2099-09-12 14:00:00', new DateTimeZone('UTC')), 'end' => null], 'prop-filters' => []]],],
+ 'future' => [[3], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => new DateTime('2036-09-12 14:00:00', new DateTimeZone('UTC')), 'end' => null], 'prop-filters' => []]],],
];
}
@@ -648,8 +652,15 @@ public function testScheduling($objectData): void {
* @dataProvider providesCalDataForGetDenormalizedData
*/
public function testGetDenormalizedData($expected, $key, $calData): void {
- $actual = $this->backend->getDenormalizedData($calData);
- $this->assertEquals($expected, $actual[$key]);
+ try {
+ $actual = $this->backend->getDenormalizedData($calData);
+ $this->assertEquals($expected, $actual[$key]);
+ } catch (\ValueError $e) {
+ if (($e->getMessage() === 'Epoch doesn\'t fit in a PHP integer') && (PHP_INT_SIZE < 8)) {
+ $this->markTestSkipped('This fail on 32bits because of PHP limitations in DateTime');
+ }
+ throw $e;
+ }
}
public function providesCalDataForGetDenormalizedData() {
diff --git a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
index 6cca861f6cca9..c3e27bf3dc9a6 100644
--- a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
+++ b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
@@ -78,13 +78,14 @@ protected function setUp(): void {
* @dataProvider providesVCards
* @param string $expectedSummary
* @param string $expectedDTStart
+ * @param string $expectedRrule
* @param string $expectedFieldType
* @param string $expectedUnknownYear
* @param string $expectedOriginalYear
* @param string|null $expectedReminder
* @param string | null $data
*/
- public function testBuildBirthdayFromContact($expectedSummary, $expectedDTStart, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $expectedReminder, $data, $fieldType, $prefix, $supports4Bytes, $configuredReminder): void {
+ public function testBuildBirthdayFromContact($expectedSummary, $expectedDTStart, $expectedRrule, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $expectedReminder, $data, $fieldType, $prefix, $supports4Bytes, $configuredReminder): void {
$this->dbConnection->method('supports4ByteText')->willReturn($supports4Bytes);
$cal = $this->service->buildDateFromContact($data, $fieldType, $prefix, $configuredReminder);
@@ -94,7 +95,7 @@ public function testBuildBirthdayFromContact($expectedSummary, $expectedDTStart,
$this->assertInstanceOf('Sabre\VObject\Component\VCalendar', $cal);
$this->assertEquals('-//IDN nextcloud.com//Birthday calendar//EN', $cal->PRODID->getValue());
$this->assertTrue(isset($cal->VEVENT));
- $this->assertEquals('FREQ=YEARLY', $cal->VEVENT->RRULE->getValue());
+ $this->assertEquals($expectedRrule, $cal->VEVENT->RRULE->getValue());
$this->assertEquals($expectedSummary, $cal->VEVENT->SUMMARY->getValue());
$this->assertEquals($expectedDTStart, $cal->VEVENT->DTSTART->getValue());
$this->assertEquals($expectedFieldType, $cal->VEVENT->{'X-NEXTCLOUD-BC-FIELD-TYPE'}->getValue());
@@ -410,35 +411,36 @@ public function providesCardChanges() {
public function providesVCards() {
return [
- // $expectedSummary, $expectedDTStart, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $expectedReminder, $data, $fieldType, $prefix, $supports4Byte, $configuredReminder
- [null, null, null, null, null, null, 'yasfewf', '', '', true, null],
- [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
- [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
- [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:someday\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
- ['🎂 12345 (1900)', '19700101', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
- ['🎂 12345 (1900)', '19701231', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
- ['Death of 12345 (1900)', '19701231', 'DEATHDATE', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', true, null],
- ['Death of 12345 (1900)', '19701231', 'DEATHDATE', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', false, null],
- ['💍 12345 (1900)', '19701231', 'ANNIVERSARY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', true, null],
- ['12345 (⚭1900)', '19701231', 'ANNIVERSARY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', false, null],
- ['🎂 12345', '19701231', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:--1231\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
- ['🎂 12345', '19701231', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY;X-APPLE-OMIT-YEAR=1604:16041231\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
- [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:;VALUE=text:circa 1800\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
- [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nN:12345;;;;\r\nBDAY:20031231\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
- ['🎂 12345 (900)', '19701231', 'BDAY', '0', '900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:09001231\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
- ['12345 (*1900)', '19700101', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
- ['12345 (*1900)', '19701231', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
- ['12345 *', '19701231', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:--1231\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
- ['12345 *', '19701231', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY;X-APPLE-OMIT-YEAR=1604:16041231\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
- [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:;VALUE=text:circa 1800\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
- [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nN:12345;;;;\r\nBDAY:20031231\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
- ['12345 (*900)', '19701231', 'BDAY', '0', '900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:09001231\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
- ['12345 (*1900)', '19701231', 'BDAY', '0', '1900', 'PT9H', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, 'PT9H'],
- ['12345 (*1900)', '19701231', 'BDAY', '0', '1900', '-PT15H', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, '-PT15H'],
- ['12345 (*1900)', '19701231', 'BDAY', '0', '1900', '-P6DT15H', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, '-P6DT15H'],
- [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nX-NC-EXCLUDE-FROM-BIRTHDAY-CALENDAR;TYPE=boolean:true\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
- [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nX-NC-EXCLUDE-FROM-BIRTHDAY-CALENDAR;TYPE=boolean:true\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', true, null],
- [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nX-NC-EXCLUDE-FROM-BIRTHDAY-CALENDAR;TYPE=boolean:true\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', true, null],
+ // $expectedSummary, $expectedDTStart, $expectedRrule, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $expectedReminder, $data, $fieldType, $prefix, $supports4Byte, $configuredReminder
+ [null, null, null, null, null, null, null, 'yasfewf', '', '', true, null],
+ [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:someday\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ ['🎂 12345 (1900)', '19700101', 'FREQ=YEARLY', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ ['🎂 12345 (1900)', '19701231', 'FREQ=YEARLY', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ ['Death of 12345 (1900)', '19701231', 'FREQ=YEARLY', 'DEATHDATE', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', true, null],
+ ['Death of 12345 (1900)', '19701231', 'FREQ=YEARLY', 'DEATHDATE', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', false, null],
+ ['💍 12345 (1900)', '19701231', 'FREQ=YEARLY', 'ANNIVERSARY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', true, null],
+ ['12345 (⚭1900)', '19701231', 'FREQ=YEARLY', 'ANNIVERSARY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', false, null],
+ ['🎂 12345', '19701231', 'FREQ=YEARLY', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:--1231\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ ['🎂 12345', '19701231', 'FREQ=YEARLY', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY;X-APPLE-OMIT-YEAR=1604:16041231\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:;VALUE=text:circa 1800\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nN:12345;;;;\r\nBDAY:20031231\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ ['🎂 12345 (900)', '19701231', 'FREQ=YEARLY', 'BDAY', '0', '900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:09001231\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ ['12345 (*1900)', '19700101', 'FREQ=YEARLY', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
+ ['12345 (*1900)', '19701231', 'FREQ=YEARLY', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
+ ['12345 *', '19701231', 'FREQ=YEARLY', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:--1231\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
+ ['12345 *', '19701231', 'FREQ=YEARLY', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY;X-APPLE-OMIT-YEAR=1604:16041231\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
+ [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:;VALUE=text:circa 1800\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
+ [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nN:12345;;;;\r\nBDAY:20031231\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
+ ['12345 (*900)', '19701231', 'FREQ=YEARLY', 'BDAY', '0', '900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:09001231\r\nEND:VCARD\r\n", 'BDAY', '', false, null],
+ ['12345 (*1900)', '19701231', 'FREQ=YEARLY', 'BDAY', '0', '1900', 'PT9H', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, 'PT9H'],
+ ['12345 (*1900)', '19701231', 'FREQ=YEARLY', 'BDAY', '0', '1900', '-PT15H', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, '-PT15H'],
+ ['12345 (*1900)', '19701231', 'FREQ=YEARLY', 'BDAY', '0', '1900', '-P6DT15H', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, '-P6DT15H'],
+ [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nX-NC-EXCLUDE-FROM-BIRTHDAY-CALENDAR;TYPE=boolean:true\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
+ [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nX-NC-EXCLUDE-FROM-BIRTHDAY-CALENDAR;TYPE=boolean:true\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', true, null],
+ [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nX-NC-EXCLUDE-FROM-BIRTHDAY-CALENDAR;TYPE=boolean:true\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', true, null],
+ ['🎂 12345 (1902)', '19720229', 'FREQ=YEARLY;BYMONTH=2;BYMONTHDAY=-1', 'BDAY', '0', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19020229\r\nEND:VCARD\r\n", 'BDAY', '', true, null],
];
}
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/AuthTest.php b/apps/dav/tests/unit/Connector/Sabre/AuthTest.php
index 72800b842535f..be841295f0b80 100644
--- a/apps/dav/tests/unit/Connector/Sabre/AuthTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/AuthTest.php
@@ -117,7 +117,7 @@ public function testValidateUserPassOfAlreadyDAVAuthenticatedUser(): void {
$user = $this->getMockBuilder(IUser::class)
->disableOriginalConstructor()
->getMock();
- $user->expects($this->exactly(2))
+ $user->expects($this->exactly(1))
->method('getUID')
->willReturn('MyTestUser');
$this->userSession
@@ -125,7 +125,7 @@ public function testValidateUserPassOfAlreadyDAVAuthenticatedUser(): void {
->method('isLoggedIn')
->willReturn(true);
$this->userSession
- ->expects($this->exactly(2))
+ ->expects($this->exactly(1))
->method('getUser')
->willReturn($user);
$this->session
@@ -171,7 +171,7 @@ public function testValidateUserPassOfInvalidDAVAuthenticatedUserWithValidPasswo
$user = $this->getMockBuilder(IUser::class)
->disableOriginalConstructor()
->getMock();
- $user->expects($this->exactly(3))
+ $user->expects($this->exactly(2))
->method('getUID')
->willReturn('MyTestUser');
$this->userSession
@@ -179,7 +179,7 @@ public function testValidateUserPassOfInvalidDAVAuthenticatedUserWithValidPasswo
->method('isLoggedIn')
->willReturn(true);
$this->userSession
- ->expects($this->exactly(3))
+ ->expects($this->exactly(2))
->method('getUser')
->willReturn($user);
$this->session
@@ -660,11 +660,11 @@ public function testAuthenticateValidCredentials(): void {
$user = $this->getMockBuilder(IUser::class)
->disableOriginalConstructor()
->getMock();
- $user->expects($this->exactly(3))
+ $user->expects($this->exactly(2))
->method('getUID')
->willReturn('MyTestUser');
$this->userSession
- ->expects($this->exactly(4))
+ ->expects($this->exactly(3))
->method('getUser')
->willReturn($user);
$response = $this->auth->check($server->httpRequest, $server->httpResponse);
diff --git a/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
index dfff9493762fb..5e638bbcd89f8 100644
--- a/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
@@ -228,13 +228,13 @@ public function testGetPropertiesForFile(): void {
$this->assertEquals('00000123instanceid', $propFind->get(self::FILEID_PROPERTYNAME));
$this->assertEquals('123', $propFind->get(self::INTERNAL_FILEID_PROPERTYNAME));
$this->assertEquals('1973-11-29T21:33:09+00:00', $propFind->get(self::CREATIONDATE_PROPERTYNAME));
- $this->assertEquals(null, $propFind->get(self::SIZE_PROPERTYNAME));
+ $this->assertEquals(0, $propFind->get(self::SIZE_PROPERTYNAME));
$this->assertEquals('DWCKMSR', $propFind->get(self::PERMISSIONS_PROPERTYNAME));
$this->assertEquals('http://example.com/', $propFind->get(self::DOWNLOADURL_PROPERTYNAME));
$this->assertEquals('foo', $propFind->get(self::OWNER_ID_PROPERTYNAME));
$this->assertEquals('M. Foo', $propFind->get(self::OWNER_DISPLAY_NAME_PROPERTYNAME));
$this->assertEquals('my_fingerprint', $propFind->get(self::DATA_FINGERPRINT_PROPERTYNAME));
- $this->assertEquals([self::SIZE_PROPERTYNAME], $propFind->get404Properties());
+ $this->assertEquals([], $propFind->get404Properties());
}
public function testGetPropertiesStorageNotAvailable(): void {
diff --git a/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php
index d38031b03d467..3119d715bec90 100644
--- a/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php
@@ -261,6 +261,8 @@ public function testOnReport(): void {
$filesNode2 = $this->getMockBuilder(File::class)
->disableOriginalConstructor()
->getMock();
+ $filesNode2->method('getSize')
+ ->willReturn(10);
$this->userFolder->expects($this->exactly(2))
->method('getById')
diff --git a/apps/files/appinfo/routes.php b/apps/files/appinfo/routes.php
index dabbeab978e5b..e4af2367906a4 100644
--- a/apps/files/appinfo/routes.php
+++ b/apps/files/appinfo/routes.php
@@ -40,12 +40,12 @@
use OCA\Files\Controller\OpenLocalEditorController;
// Legacy routes above
-/** @var $this \OC\Route\Router */
+/** @var \OC\Route\Router $this */
$this->create('files_ajax_download', 'apps/files/ajax/download.php')
->actionInclude('files/ajax/download.php');
/** @var Application $application */
-$application = \OC::$server->query(Application::class);
+$application = \OC::$server->get(Application::class);
$application->registerRoutes(
$this,
[
diff --git a/apps/files/js/files.js b/apps/files/js/files.js
index 0ae049360b492..b0c3824818309 100644
--- a/apps/files/js/files.js
+++ b/apps/files/js/files.js
@@ -481,6 +481,11 @@ var dragOptions={
$('.crumbmenu').removeClass('canDropChildren');
},
drag: function(event, ui) {
+ // Prevent scrolling when hovering .files-controls
+ if ($(event.originalEvent.target).parents('.files-controls').length > 0) {
+ return
+ }
+
/** @type {JQuery
\Sabre\Uri\split($path)
- $vevent->LOCATION
- $vevent->SUMMARY
- string
- $lang->getValue()
- getDateTime
- getDateTime
- getDateTime
- getDateTime
- getDateTime
- hasTime
- hasTime
- isFloating
- isFloating
- isFloating
- $iTipMessage->message->VEVENT->SUMMARY
- [$aclPlugin, 'propFind']
@@ -894,25 +867,11 @@
(int)$share['id']
string
- null
- $files_list
$this
- $this
- $this->fileEncrypted[$fileId]
@@ -1086,12 +1045,6 @@
$files_list
$maxUploadFilesize
- null
- $quota
- $groupid === null
$groupid === null
@@ -2360,9 +2310,6 @@
$exception->getCode()
null
- wrap
$storage->scanner
copy
- copyFromStorage
- file_exists
- file_get_contents
- file_put_contents
- filemtime
- filesize
- filetype
- fopen
- free_space
- getDirectDownload
- getETag
- getLocalFile
- getMimeType
- getOwner
- getPermissions
- hash
- isCreatable
- isDeletable
- isReadable
- isSharable
- isUpdatable
- is_dir
- is_file
- mkdir
- moveFromStorage
- opendir
- rename
- rmdir
- search
- stat
- touch
- unlink
- \Traversable
- \Normalizer::FORM_C
@@ -2730,18 +2637,17 @@
$result
$this->copyFromStorage($sourceStorage, $sourceInternalPath . '/' . $file, $targetInternalPath . '/' . $file, false, $isRename)
- $newUnencryptedSize
$result
$this->storage->file_get_contents($path)
- $this->storage->filesize($path)
bool
int
string
$lastChunkPos
$newUnencryptedSize
$size
@@ -2764,9 +2670,8 @@
string
$free
- 'ext'
string[]
- $failedRecipients
- getSubject
- getSwiftMessage
- getTo
- apcu_add($this->getPrefix() . $key, $value, $ttl)
@@ -3537,9 +3429,6 @@
mt_rand()
- $getType === self::ZIP_DIR
$getType === self::ZIP_DIR
@@ -3553,17 +3442,8 @@
$matches[1][$last_match][0]
(INF > 0)? INF: PHP_INT_MAX
- INF
- int
- $includeExtStorage ? 'ext' : false
+ $path
- 'ext'
count($obd_values) > 0
diff --git a/core/Command/Log/File.php b/core/Command/Log/File.php
index f2c77e20174c4..6d6e530fe9aed 100644
--- a/core/Command/Log/File.php
+++ b/core/Command/Log/File.php
@@ -115,14 +115,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}
/**
- * @param mixed $rotateSize
* @throws \InvalidArgumentException
*/
- protected function validateRotateSize(&$rotateSize) {
+ protected function validateRotateSize(false|int|float $rotateSize): void {
if ($rotateSize === false) {
throw new \InvalidArgumentException('Error parsing log rotation file size');
}
- $rotateSize = (int) $rotateSize;
if ($rotateSize < 0) {
throw new \InvalidArgumentException('Log rotation file size must be non-negative');
}
diff --git a/core/js/login/authpicker.js b/core/js/login/authpicker.js
index 8aaaf3d7361c1..1a94b02d72f95 100644
--- a/core/js/login/authpicker.js
+++ b/core/js/login/authpicker.js
@@ -10,4 +10,6 @@ jQuery(document).ready(function() {
e.preventDefault();
document.location.href = e.target.attributes.action.value
})
+
+ $('#login-form input').removeAttr('disabled');
})
diff --git a/core/js/setupchecks.js b/core/js/setupchecks.js
index 67f8d70bd31ab..73896f9fc9156 100644
--- a/core/js/setupchecks.js
+++ b/core/js/setupchecks.js
@@ -421,7 +421,7 @@
messages.push({
msg: t(
'core',
- 'It seems like you are running a 32-bit PHP version. Nextcloud 26 and higher require 64-bit. Please upgrade your OS and PHP to 64-bit! For further details read {linkstart}the documentation page ↗{linkend} about this.'
+ 'It seems like you are running a 32-bit PHP version. Nextcloud needs 64-bit to run well. Please upgrade your OS and PHP to 64-bit! For further details read {linkstart}the documentation page ↗{linkend} about this.'
.replace('{linkstart}', '')
.replace('{linkend}', ''),
),
diff --git a/core/js/tests/specs/setupchecksSpec.js b/core/js/tests/specs/setupchecksSpec.js
index 6df1659d7d3f1..4532ac457b69c 100644
--- a/core/js/tests/specs/setupchecksSpec.js
+++ b/core/js/tests/specs/setupchecksSpec.js
@@ -1234,7 +1234,7 @@ describe('OC.SetupChecks tests', function() {
});
});
-
+
it('should return an error if imagick is not enabled', function(done) {
var async = OC.SetupChecks.checkSetup();
@@ -1293,7 +1293,7 @@ describe('OC.SetupChecks tests', function() {
});
});
-
+
it('should return an error if gmp or bcmath are not enabled', function(done) {
var async = OC.SetupChecks.checkSetup();
@@ -1403,7 +1403,7 @@ describe('OC.SetupChecks tests', function() {
async.done(function( data, s, x ){
expect(data).toEqual([{
- msg: 'It seems like you are running a 32-bit PHP version. Nextcloud 26 and higher require 64-bit. Please upgrade your OS and PHP to 64-bit! For further details read the documentation page ↗ about this.',
+ msg: 'It seems like you are running a 32-bit PHP version. Nextcloud needs 64-bit to run well. Please upgrade your OS and PHP to 64-bit! For further details read the documentation page ↗ about this.',
type: OC.SetupChecks.MESSAGE_TYPE_WARNING
}]);
done();
diff --git a/core/l10n/cs.js b/core/l10n/cs.js
index 9e70da8eaf66f..666f6d7d38450 100644
--- a/core/l10n/cs.js
+++ b/core/l10n/cs.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"State token does not match" : "Stavový token se neshoduje",
"Invalid app password" : "Neplatné heslo pro aplikaci",
"Could not complete login" : "Přihlášení se nedaří dokončit",
+ "State token missing" : "Chybí stavový token",
"Your login token is invalid or has expired" : "Váš přihlašovací token není platný nebo jeho platnost skončila",
"This community release of Nextcloud is unsupported and push notifications are limited." : "Toto komunitní vydání Nextcloud není podporováno a push oznámení jsou proto omezená.",
"Login" : "Přihlásit",
diff --git a/core/l10n/cs.json b/core/l10n/cs.json
index 7c05b9a790e30..4461f2582d563 100644
--- a/core/l10n/cs.json
+++ b/core/l10n/cs.json
@@ -23,6 +23,7 @@
"State token does not match" : "Stavový token se neshoduje",
"Invalid app password" : "Neplatné heslo pro aplikaci",
"Could not complete login" : "Přihlášení se nedaří dokončit",
+ "State token missing" : "Chybí stavový token",
"Your login token is invalid or has expired" : "Váš přihlašovací token není platný nebo jeho platnost skončila",
"This community release of Nextcloud is unsupported and push notifications are limited." : "Toto komunitní vydání Nextcloud není podporováno a push oznámení jsou proto omezená.",
"Login" : "Přihlásit",
diff --git a/core/l10n/de_DE.js b/core/l10n/de_DE.js
index 11c2050679ac5..3446ccdf6629e 100644
--- a/core/l10n/de_DE.js
+++ b/core/l10n/de_DE.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"State token does not match" : "Status-Token stimmen nicht überein",
"Invalid app password" : "Ungültiges App-Passwort",
"Could not complete login" : "Anmeldung konnte nicht abgeschlossen werden",
+ "State token missing" : "Zustandstoken fehlt",
"Your login token is invalid or has expired" : "Ihr Anmelde-Token ist ungültig oder abgelaufen",
"This community release of Nextcloud is unsupported and push notifications are limited." : "Diese Community-Version von Nextcloud wird nicht unterstützt und sofortige Benachrichtigungen sind nur begrenzt verfügbar.",
"Login" : "Anmelden",
diff --git a/core/l10n/de_DE.json b/core/l10n/de_DE.json
index 83a3f15a92c0a..c0f6e6874ca6f 100644
--- a/core/l10n/de_DE.json
+++ b/core/l10n/de_DE.json
@@ -23,6 +23,7 @@
"State token does not match" : "Status-Token stimmen nicht überein",
"Invalid app password" : "Ungültiges App-Passwort",
"Could not complete login" : "Anmeldung konnte nicht abgeschlossen werden",
+ "State token missing" : "Zustandstoken fehlt",
"Your login token is invalid or has expired" : "Ihr Anmelde-Token ist ungültig oder abgelaufen",
"This community release of Nextcloud is unsupported and push notifications are limited." : "Diese Community-Version von Nextcloud wird nicht unterstützt und sofortige Benachrichtigungen sind nur begrenzt verfügbar.",
"Login" : "Anmelden",
diff --git a/core/l10n/en_GB.js b/core/l10n/en_GB.js
index 6e85299142292..209b82238e657 100644
--- a/core/l10n/en_GB.js
+++ b/core/l10n/en_GB.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"State token does not match" : "State token does not match",
"Invalid app password" : "Invalid app password",
"Could not complete login" : "Could not complete login",
+ "State token missing" : "State token missing",
"Your login token is invalid or has expired" : "Your login token is invalid or has expired",
"This community release of Nextcloud is unsupported and push notifications are limited." : "This community release of Nextcloud is unsupported and push notifications are limited.",
"Login" : "Login",
diff --git a/core/l10n/en_GB.json b/core/l10n/en_GB.json
index b34b209c73f59..ae229225a4248 100644
--- a/core/l10n/en_GB.json
+++ b/core/l10n/en_GB.json
@@ -23,6 +23,7 @@
"State token does not match" : "State token does not match",
"Invalid app password" : "Invalid app password",
"Could not complete login" : "Could not complete login",
+ "State token missing" : "State token missing",
"Your login token is invalid or has expired" : "Your login token is invalid or has expired",
"This community release of Nextcloud is unsupported and push notifications are limited." : "This community release of Nextcloud is unsupported and push notifications are limited.",
"Login" : "Login",
diff --git a/core/l10n/es.js b/core/l10n/es.js
index abfcae3902e2e..41560bc0b6f6f 100644
--- a/core/l10n/es.js
+++ b/core/l10n/es.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"State token does not match" : "El token dado no coincide",
"Invalid app password" : "Contraseña de la app no válida",
"Could not complete login" : "No se ha podido completar el inicio de sesión",
+ "State token missing" : "No se encontró token de estado",
"Your login token is invalid or has expired" : "Tu token de login no es válido o ha caducado",
"This community release of Nextcloud is unsupported and push notifications are limited." : "Esta versión comunitaria de Nextcloud ya no está soportada y las notificaciones push son limitadas.",
"Login" : "Iniciar sesión",
diff --git a/core/l10n/es.json b/core/l10n/es.json
index 2e44acb3a0489..40dfad4ecdf22 100644
--- a/core/l10n/es.json
+++ b/core/l10n/es.json
@@ -23,6 +23,7 @@
"State token does not match" : "El token dado no coincide",
"Invalid app password" : "Contraseña de la app no válida",
"Could not complete login" : "No se ha podido completar el inicio de sesión",
+ "State token missing" : "No se encontró token de estado",
"Your login token is invalid or has expired" : "Tu token de login no es válido o ha caducado",
"This community release of Nextcloud is unsupported and push notifications are limited." : "Esta versión comunitaria de Nextcloud ya no está soportada y las notificaciones push son limitadas.",
"Login" : "Iniciar sesión",
diff --git a/core/l10n/fr.js b/core/l10n/fr.js
index 77c6b06ec8ccb..e13a6c79852a2 100644
--- a/core/l10n/fr.js
+++ b/core/l10n/fr.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"State token does not match" : "Les jetons de statut ne correspondent pas",
"Invalid app password" : "Mot de passe d'application non valide",
"Could not complete login" : "Impossible de terminer la connexion",
+ "State token missing" : "Jeton d'état manquant",
"Your login token is invalid or has expired" : "Votre jeton de connexion est invalide ou a expiré",
"This community release of Nextcloud is unsupported and push notifications are limited." : "Cette version communautaire de Nextcloud n'est pas prise en charge et les notifications push sont limitées.",
"Login" : "S'identifier",
diff --git a/core/l10n/fr.json b/core/l10n/fr.json
index 8174e450c769e..4ff9cdf1ddd73 100644
--- a/core/l10n/fr.json
+++ b/core/l10n/fr.json
@@ -23,6 +23,7 @@
"State token does not match" : "Les jetons de statut ne correspondent pas",
"Invalid app password" : "Mot de passe d'application non valide",
"Could not complete login" : "Impossible de terminer la connexion",
+ "State token missing" : "Jeton d'état manquant",
"Your login token is invalid or has expired" : "Votre jeton de connexion est invalide ou a expiré",
"This community release of Nextcloud is unsupported and push notifications are limited." : "Cette version communautaire de Nextcloud n'est pas prise en charge et les notifications push sont limitées.",
"Login" : "S'identifier",
diff --git a/core/l10n/pt_BR.js b/core/l10n/pt_BR.js
index e1621f75a939e..c21a01c2369f1 100644
--- a/core/l10n/pt_BR.js
+++ b/core/l10n/pt_BR.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"State token does not match" : "O estado do token não coincide",
"Invalid app password" : "Senha do aplicativo inválida",
"Could not complete login" : "Não foi possível concluir o login",
+ "State token missing" : "State token missing",
"Your login token is invalid or has expired" : "Seu token de login é inválido ou expirou",
"This community release of Nextcloud is unsupported and push notifications are limited." : "Esta versão da comunidade do Nextcloud não é compatível e as notificações por push são limitadas.",
"Login" : "Entrar",
diff --git a/core/l10n/pt_BR.json b/core/l10n/pt_BR.json
index 837a19f9858f3..4fb62d1b1b243 100644
--- a/core/l10n/pt_BR.json
+++ b/core/l10n/pt_BR.json
@@ -23,6 +23,7 @@
"State token does not match" : "O estado do token não coincide",
"Invalid app password" : "Senha do aplicativo inválida",
"Could not complete login" : "Não foi possível concluir o login",
+ "State token missing" : "State token missing",
"Your login token is invalid or has expired" : "Seu token de login é inválido ou expirou",
"This community release of Nextcloud is unsupported and push notifications are limited." : "Esta versão da comunidade do Nextcloud não é compatível e as notificações por push são limitadas.",
"Login" : "Entrar",
diff --git a/core/l10n/tr.js b/core/l10n/tr.js
index bc7d4bd3962d8..7e37270156a54 100644
--- a/core/l10n/tr.js
+++ b/core/l10n/tr.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"State token does not match" : "Durum kodu eşleşmiyor",
"Invalid app password" : "Uygulama parolası geçersiz",
"Could not complete login" : "Oturum açılamadı",
+ "State token missing" : "Durum kodu eksik",
"Your login token is invalid or has expired" : "Oturum açma kodunuz geçersiz ya da geçerlilik süresi dolmuş",
"This community release of Nextcloud is unsupported and push notifications are limited." : "Bu Nextcloud topluluk sürümü desteklenmiyor ve anlık bildirimler sınırlı şekilde kullanılabiliyor.",
"Login" : "Oturum aç",
diff --git a/core/l10n/tr.json b/core/l10n/tr.json
index 40e131f91cf2a..a5501e7709ce0 100644
--- a/core/l10n/tr.json
+++ b/core/l10n/tr.json
@@ -23,6 +23,7 @@
"State token does not match" : "Durum kodu eşleşmiyor",
"Invalid app password" : "Uygulama parolası geçersiz",
"Could not complete login" : "Oturum açılamadı",
+ "State token missing" : "Durum kodu eksik",
"Your login token is invalid or has expired" : "Oturum açma kodunuz geçersiz ya da geçerlilik süresi dolmuş",
"This community release of Nextcloud is unsupported and push notifications are limited." : "Bu Nextcloud topluluk sürümü desteklenmiyor ve anlık bildirimler sınırlı şekilde kullanılabiliyor.",
"Login" : "Oturum aç",
diff --git a/core/l10n/zh_HK.js b/core/l10n/zh_HK.js
index eec324801950a..e12a25f8bad31 100644
--- a/core/l10n/zh_HK.js
+++ b/core/l10n/zh_HK.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"State token does not match" : "狀態權杖不相符",
"Invalid app password" : "無效的應用程式密碼",
"Could not complete login" : "無法完成登錄",
+ "State token missing" : "找不到狀態權杖",
"Your login token is invalid or has expired" : "您的登入權杖無效或已過期",
"This community release of Nextcloud is unsupported and push notifications are limited." : "不支援 Nextcloud 的這個社群版本,且推播通知有所限制。",
"Login" : "登入",
diff --git a/core/l10n/zh_HK.json b/core/l10n/zh_HK.json
index d619a2d13c425..5c1a3cbc09252 100644
--- a/core/l10n/zh_HK.json
+++ b/core/l10n/zh_HK.json
@@ -23,6 +23,7 @@
"State token does not match" : "狀態權杖不相符",
"Invalid app password" : "無效的應用程式密碼",
"Could not complete login" : "無法完成登錄",
+ "State token missing" : "找不到狀態權杖",
"Your login token is invalid or has expired" : "您的登入權杖無效或已過期",
"This community release of Nextcloud is unsupported and push notifications are limited." : "不支援 Nextcloud 的這個社群版本,且推播通知有所限制。",
"Login" : "登入",
diff --git a/core/l10n/zh_TW.js b/core/l10n/zh_TW.js
index 6f5a76d85c696..06af77863ea1a 100644
--- a/core/l10n/zh_TW.js
+++ b/core/l10n/zh_TW.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"State token does not match" : "狀態權杖不相符",
"Invalid app password" : "無效的應用程式密碼",
"Could not complete login" : "嘗試登入時發生錯誤",
+ "State token missing" : "狀態權杖遺失",
"Your login token is invalid or has expired" : "您的登入權杖無效或已過期",
"This community release of Nextcloud is unsupported and push notifications are limited." : "不支援 Nextcloud 的這個社群版本,且推播通知有所限制。",
"Login" : "登入",
diff --git a/core/l10n/zh_TW.json b/core/l10n/zh_TW.json
index 7a29343ec6786..9ac3c2688ef16 100644
--- a/core/l10n/zh_TW.json
+++ b/core/l10n/zh_TW.json
@@ -23,6 +23,7 @@
"State token does not match" : "狀態權杖不相符",
"Invalid app password" : "無效的應用程式密碼",
"Could not complete login" : "嘗試登入時發生錯誤",
+ "State token missing" : "狀態權杖遺失",
"Your login token is invalid or has expired" : "您的登入權杖無效或已過期",
"This community release of Nextcloud is unsupported and push notifications are limited." : "不支援 Nextcloud 的這個社群版本,且推播通知有所限制。",
"Login" : "登入",
diff --git a/core/src/OC/dialogs.js b/core/src/OC/dialogs.js
index 286f98482908d..f49d5cd4fa029 100644
--- a/core/src/OC/dialogs.js
+++ b/core/src/OC/dialogs.js
@@ -427,7 +427,7 @@ const Dialogs = {
if (checkInput()) {
var newname = $input.val()
self.filepicker.filesClient.createDirectory(self.$filePicker.data('path') + "/" + newname).always(function (status) {
- self._fillFilePicker(self.$filePicker.data('path') + "/" + newname)
+ self._fillFilePicker(self.$filePicker.data('path') + "/" + newname, type)
})
OC.hideMenus()
self.$filePicker.ocdialog('unsetEnterCallback')
@@ -459,10 +459,10 @@ const Dialogs = {
var dir = self.$filePicker.data('path')
self.filepicker.sortField = $(event.currentTarget).data('sort')
self.filepicker.sortOrder = self.filepicker.sortOrder === 'asc' ? 'desc' : 'asc'
- self._fillFilePicker(dir)
+ self._fillFilePicker(dir, type)
}
})
- self._fillFilePicker(path)
+ self._fillFilePicker(path, type)
})
// build buttons
@@ -1120,7 +1120,7 @@ const Dialogs = {
/**
* fills the filepicker with files
*/
- _fillFilePicker: async function(dir) {
+ _fillFilePicker: async function(dir, type) {
var self = this
this.$filelist.empty()
this.$filePicker.find('.emptycontent').hide()
@@ -1155,6 +1155,7 @@ const Dialogs = {
console.error('Requested path does not exists, falling back to root')
var files = await getFolderContents('/')
this.$filePicker.data('path', '/')
+ this._changeButtonsText(type, '')
}
self.filelist = files
@@ -1320,7 +1321,7 @@ const Dialogs = {
_handleTreeListSelect: function(event, type) {
var self = event.data
var dir = $(event.target).closest('.crumb').data('dir')
- self._fillFilePicker(dir)
+ self._fillFilePicker(dir, type)
var getOcDialog = (event.target).closest('.oc-dialog')
var buttonEnableDisable = $('.primary', getOcDialog)
this._changeButtonsText(type, dir.split(/[/]+/).pop())
@@ -1343,7 +1344,7 @@ const Dialogs = {
$element.toggleClass('filepicker_element_selected')
buttonEnableDisable.prop('disabled', false)
} else if ($element.data('type') === 'dir') {
- this._fillFilePicker(this.$filePicker.data('path') + '/' + $element.data('entryname'))
+ this._fillFilePicker(this.$filePicker.data('path') + '/' + $element.data('entryname'), type)
this._changeButtonsText(type, $element.data('entryname'))
if (this.$filePicker.data('mimetype').indexOf('httpd/unix-directory') !== -1 || this.$filePicker.data('allowDirectoryChooser')) {
buttonEnableDisable.prop('disabled', false)
diff --git a/core/templates/loginflow/authpicker.php b/core/templates/loginflow/authpicker.php
index 68c53818a9236..3f78081921d3e 100644
--- a/core/templates/loginflow/authpicker.php
+++ b/core/templates/loginflow/authpicker.php
@@ -47,7 +47,7 @@
diff --git a/dist/core-login.js b/dist/core-login.js index f2a38ad17e8e2..c251330dff1f1 100644 --- a/dist/core-login.js +++ b/dist/core-login.js @@ -1,3 +1,3 @@ /*! For license information please see core-login.js.LICENSE.txt */ -!function(){var e,o={99458:function(e,o,r){"use strict";var i=r(20144),a=r(78595),s=r(19755),l=r.n(s),c=r(79753),u={},d=[],f=r(18181),p=r(26932),h={updatableNotification:null,getDefaultNotificationFunction:null,setDefault:function(t){this.getDefaultNotificationFunction=t},hide:function(t,e){f.ZP.isFunction(t)&&(e=t,t=void 0),t?(t.each((function(){l()(this)[0].toastify?l()(this)[0].toastify.hideToast():console.error("cannot hide toast because object is not set"),this===this.updatableNotification&&(this.updatableNotification=null)})),e&&e.call(),this.getDefaultNotificationFunction&&this.getDefaultNotificationFunction()):console.error("Missing argument $row in OC.Notification.hide() call, caller needs to be adjusted to only dismiss its own notification")},showHtml:function(t,e){(e=e||{}).isHTML=!0,e.timeout=e.timeout?e.timeout:p.Rl;var n=(0,p.PV)(t,e);return n.toastElement.toastify=n,l()(n.toastElement)},show:function(t,e){(e=e||{}).timeout=e.timeout?e.timeout:p.Rl;var n=(0,p.PV)(function(t){return t.toString().split("&").join("&").split("<").join("<").split(">").join(">").split('"').join(""").split("'").join("'")}(t),e);return n.toastElement.toastify=n,l()(n.toastElement)},showUpdate:function(t){return this.updatableNotification&&this.updatableNotification.hideToast(),this.updatableNotification=(0,p.PV)(t,{timeout:p.Rl}),this.updatableNotification.toastElement.toastify=this.updatableNotification,l()(this.updatableNotification.toastElement)},showTemporary:function(t,e){(e=e||{}).timeout=e.timeout||p.TN;var n=(0,p.PV)(t,e);return n.toastElement.toastify=n,l()(n.toastElement)},isHidden:function(){return!l()("#content").find(".toastify").length}},m=f.ZP.throttle((function(){h.showTemporary(t("core","Connection to server lost"))}),7e3,{trailing:!1}),g={enableDynamicSlideToggle:function(){},showAppSidebar:function(t){(t||l()("#app-sidebar")).removeClass("disappear").show(),l()("#app-content").trigger(new(l().Event)("appresized"))},hideAppSidebar:function(t){(t||l()("#app-sidebar")).hide().addClass("disappear"),l()("#app-content").trigger(new(l().Event)("appresized"))}};function v(t,e,n){"post"!==t&&"delete"!==t||!Mt.PasswordConfirmation.requiresPasswordConfirmation()?(n=n||{},l().ajax({type:t.toUpperCase(),url:(0,c.generateOcsUrl)("apps/provisioning_api/api/v1/config/apps")+e,data:n.data||{},success:n.success,error:n.error})):Mt.PasswordConfirmation.requirePasswordConfirmation(_.bind(v,this,t,e,n))}var y=window.oc_appconfig||{},w={getValue:function(t,e,n,o){!function(t,e,n,o){(o=o||{}).data={defaultValue:n},v("get","/"+t+"/"+e,o)}(t,e,n,{success:o})},setValue:function(t,e,n){!function(t,e,n,o){(o=o||{}).data={value:n},v("post","/"+t+"/"+e,o)}(t,e,n)},getApps:function(t){!function(t){v("get","",t)}({success:t})},getKeys:function(t,e){!function(t,e){v("get","/"+t,e)}(t,{success:e})},deleteKey:function(t,e){!function(t,e,n){v("delete","/"+t+"/"+e,void 0)}(t,e)}},b=void 0!==window._oc_appswebroots&&window._oc_appswebroots,P=r(72316),C=r.n(P),A=r(76591),k={create:"POST",update:"PROPPATCH",patch:"PROPPATCH",delete:"DELETE",read:"PROPFIND"};function x(t,e){if(f.ZP.isArray(t))return f.ZP.map(t,(function(t){return x(t,e)}));var n={href:t.href};return f.ZP.each(t.propStat,(function(t){if("HTTP/1.1 200 OK"===t.status)for(var o in t.properties){var r=o;o in e&&(r=e[o]),n[r]=t.properties[o]}})),n.id||(n.id=O(n.href)),n}function O(t){var e=t.indexOf("?");e>0&&(t=t.substr(0,e));var n,o=t.split("/");do{n=o[o.length-1],o.pop()}while(!n&&o.length>0);return n}function T(t){return t>=200&&t<=299}function j(t,e,n,o){return t.propPatch(e.url,function(t,e){var n,o={};for(n in t){var r=e[n],i=t[n];r||(console.warn('No matching DAV property for property "'+n),r=n),(f.ZP.isBoolean(i)||f.ZP.isNumber(i))&&(i=""+i),o[r]=i}return o}(n.changed,e.davProperties),o).then((function(t){T(t.status)?f.ZP.isFunction(e.success)&&e.success(n.toJSON()):f.ZP.isFunction(e.error)&&e.error(t)}))}var E=C().noConflict();Object.assign(E,{davCall:function(t,e){var n=new A.dav.Client({baseUrl:t.url,xmlNamespaces:f.ZP.extend({"DAV:":"d","http://owncloud.org/ns":"oc"},t.xmlNamespaces||{})});n.resolveUrl=function(){return t.url};var o=f.ZP.extend({"X-Requested-With":"XMLHttpRequest",requesttoken:OC.requestToken},t.headers);return"PROPFIND"===t.type?function(t,e,n,o){return t.propFind(e.url,f.ZP.values(e.davProperties)||[],e.depth,o).then((function(t){if(T(t.status)){if(f.ZP.isFunction(e.success)){var n=f.ZP.invert(e.davProperties),o=x(t.body,n);e.depth>0&&o.shift(),e.success(o)}}else f.ZP.isFunction(e.error)&&e.error(t)}))}(n,t,0,o):"PROPPATCH"===t.type?j(n,t,e,o):"MKCOL"===t.type?function(t,e,n,o){return t.request(e.type,e.url,o,null).then((function(r){T(r.status)?j(t,e,n,o):f.ZP.isFunction(e.error)&&e.error(r)}))}(n,t,e,o):function(t,e,n,o){return o["Content-Type"]="application/json",t.request(e.type,e.url,o,e.data).then((function(t){if(T(t.status)){if(f.ZP.isFunction(e.success)){if("PUT"===e.type||"POST"===e.type||"MKCOL"===e.type){var o=t.body||n.toJSON(),r=t.xhr.getResponseHeader("Content-Location");return"POST"===e.type&&r&&(o.id=O(r)),void e.success(o)}if(207===t.status){var i=f.ZP.invert(e.davProperties);e.success(x(t.body,i))}else e.success(t.body)}}else f.ZP.isFunction(e.error)&&e.error(t)}))}(n,t,e,o)},davSync:function(t){return function(e,n,o){var r={type:k[e]||e},i=n instanceof t.Collection;if("update"===e&&(n.hasInnerCollection?r.type="MKCOL":(n.usePUT||n.collection&&n.collection.usePUT)&&(r.type="PUT")),o.url||(r.url=f.ZP.result(n,"url")||function(){throw new Error('A "url" property or function must be specified')}()),null!=o.data||!n||"create"!==e&&"update"!==e&&"patch"!==e||(r.data=JSON.stringify(o.attrs||n.toJSON(o))),"PROPFIND"!==r.type&&(r.processData=!1),"PROPFIND"===r.type||"PROPPATCH"===r.type){var a=n.davProperties;!a&&n.model&&(a=n.model.prototype.davProperties),a&&(f.ZP.isFunction(a)?r.davProperties=a.call(n):r.davProperties=a),r.davProperties=f.ZP.extend(r.davProperties||{},o.davProperties),f.ZP.isUndefined(o.depth)&&(o.depth=i?1:0)}var s=o.error;o.error=function(t,e,n){o.textStatus=e,o.errorThrown=n,s&&s.call(o.context,t,e,n)};var l=o.xhr=t.davCall(f.ZP.extend(r,o),n);return n.trigger("request",n,l,o),l}}(E)});var S=E,L=r(65358),N=window._oc_config||{},I=P.Model.extend({defaults:{fullName:"",lastMessage:"",actions:[],hasOneAction:!1,hasTwoActions:!1,hasManyActions:!1},initialize:function(){0===this.get("actions").length?this.set("hasOneAction",!0):1===this.get("actions").length?(this.set("hasTwoActions",!0),this.set("secondAction",this.get("actions")[0])):this.set("hasManyActions",!0)}}),U=P.Collection.extend({model:I}),$=P.View.extend({_collection:void 0,_subViews:[],initialize:function(t){this._collection=t.collection},render:function(){var t=this;return t.$el.html(""),t._subViews=[],t._collection.forEach((function(e){var n=new F({model:e});n.render(),t.$el.append(n.$el),n.on("toggle:actionmenu",t._onChildActionMenuToggle,t),t._subViews.push(n)})),t},_onChildActionMenuToggle:function(t){this._subViews.forEach((function(e){e.trigger("parent:toggle:actionmenu",t)}))}}),F=P.View.extend({className:"contact",_template:void 0,_model:void 0,_actionMenuShown:!1,events:{"click .icon-more":"_onToggleActionsMenu"},contactTemplate:r(10944),template:function(t){return this.contactTemplate(t)},initialize:function(t){this._model=t.model,this.on("parent:toggle:actionmenu",this._onOtherActionMenuOpened,this)},render:function(){return this.$el.html(this.template({contact:this._model.toJSON()})),this.delegateEvents(),this.$("div.avatar").imageplaceholder(this._model.get("fullName")),this.$(".top-action").tooltip({placement:"left"}),this.$(".second-action").tooltip({placement:"left"}),this},_onToggleActionsMenu:function(){this._actionMenuShown=!this._actionMenuShown,this._actionMenuShown?this.$(".menu").show():this.$(".menu").hide(),this.trigger("toggle:actionmenu",this.$el)},_onOtherActionMenuOpened:function(t){this.$el.is(t)||(this._actionMenuShown=!1,this.$(".menu").hide())}}),R=P.View.extend({_loadingTemplate:void 0,_errorTemplate:void 0,_contentTemplate:void 0,_contactsTemplate:void 0,_contacts:void 0,_searchTerm:"",events:{"input #contactsmenu-search":"_onSearch"},templates:{loading:r(95386),error:r(20421),menu:r(66115),list:r(34083)},_onSearch:f.ZP.debounce((function(t){var e=this.$("#contactsmenu-search").val();e!==this._searchTerm&&(this.trigger("search",this.$("#contactsmenu-search").val()),this._searchTerm=e)}),700),loadingTemplate:function(t){return this.templates.loading(t)},errorTemplate:function(e){return this.templates.error(f.ZP.extend({couldNotLoadText:t("core","Could not load your contacts")},e))},contentTemplate:function(e){return this.templates.menu(f.ZP.extend({searchContactsText:t("core","Search contacts …")},e))},contactsTemplate:function(e){return this.templates.list(f.ZP.extend({noContactsFoundText:t("core","No contacts found"),showAllContactsText:t("core","Show all contacts …"),contactsAppMgmtText:t("core","Install the Contacts app")},e))},initialize:function(t){this.options=t},showLoading:function(t){this.render(),this._contacts=void 0,this.$(".content").html(this.loadingTemplate({loadingText:t}))},showError:function(){this.render(),this._contacts=void 0,this.$(".content").html(this.errorTemplate())},showContacts:function(t,e){this._contacts=t.contacts,this.render({contacts:t.contacts});var n=new $({collection:t.contacts});n.render(),this.$(".content").html(this.contactsTemplate({contacts:t.contacts,searchTerm:e,contactsAppEnabled:t.contactsAppEnabled,contactsAppURL:Mt.generateUrl("/apps/contacts"),canInstallApp:Mt.isUserAdmin(),contactsAppMgmtURL:Mt.generateUrl("/settings/apps/social/contacts")})),this.$("#contactsmenu-contacts").html(n.$el)},render:function(t){var e=this.$("#contactsmenu-search").val();return this.$el.html(this.contentTemplate(t)),this.$("#contactsmenu-search").val(e),this.$("#contactsmenu-search").focus(),this}}),M=function(t){this.initialize(t)};M.prototype={$el:void 0,_view:void 0,_contactsPromise:void 0,initialize:function(t){this.$el=l()(t.el),this._view=new R({el:this.$el}),this._view.on("search",(function(t){this.loadContacts(t)}),this)},_getContacts:function(t){var e=Mt.generateUrl("/contactsmenu/contacts");return Promise.resolve(l().ajax(e,{method:"POST",data:{filter:t}}))},loadContacts:function(e){var n=this;return n._contactsPromise||(n._contactsPromise=n._getContacts(e)),f.ZP.isUndefined(e)||""===e?n._view.showLoading(t("core","Loading your contacts …")):n._view.showLoading(t("core","Looking for {term} …",{term:e})),n._contactsPromise.then((function(t){t.contacts=new U(t.contacts),n._view.showContacts(t,e)}),(function(t){n._view.showError(),console.error("There was an error loading your contacts",t)})).then((function(){delete n._contactsPromise})).catch(console.error.bind(this))}};var z=M,B=document.getElementsByTagName("head")[0].getAttribute("data-user"),D=document.getElementsByTagName("head")[0].getAttribute("data-user-displayname"),Z=void 0!==B&&B;function q(t){return q="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},q(t)}function Y(t,e){for(var n=0;n
\n\t\t\t{{ t('core', 'Passwordless authentication is not supported in your browser.') }}\n\t\t
\n\t\n\t\t\t{{ t('core', 'Passwordless authentication is only available over a secure connection.') }}\n\t\t
\n\t\n\t\t\t{{ t('core', 'Passwordless authentication is not supported in your browser.') }}\n\t\t
\n\t\n\t\t\t{{ t('core', 'Passwordless authentication is only available over a secure connection.') }}\n\t\t
\n\t