Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7ab2238b6a | |||
| 150c225933 | |||
| c260003b50 | |||
| d71c91a00c | |||
| f1fd8bbba6 | |||
| 34c91a2767 | |||
| 0727930103 | |||
| 1dab94d577 | |||
| edf96ce418 | |||
| c3768ac232 | |||
| 04dec46ba9 | |||
| 0f6e5c565b | |||
| fa4575836b | |||
| 8a3c617cb5 | |||
| 8adf7b73f5 | |||
| dff3fee9f2 | |||
| 1c6d28f034 | |||
| c9c9ea77a9 | |||
| 1fd167e6f4 | |||
| f1fcd03cc5 | |||
| ca0be4eb80 | |||
| 6901bfbeb7 | |||
| eef028e632 | |||
| e7b2d26d2f |
@@ -1,68 +0,0 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Apply rector changes
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# At 14:30 on Sundays
|
||||
- cron: '30 14 * * 0'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
name: rector-apply
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
id: checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: ${{ github.event.repository.default_branch }}
|
||||
|
||||
- name: Get php version
|
||||
id: versions
|
||||
uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1
|
||||
|
||||
- name: Set up php${{ steps.versions.outputs.php-min }}
|
||||
uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # v2.36.0
|
||||
with:
|
||||
php-version: ${{ steps.versions.outputs.php-min }}
|
||||
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
|
||||
coverage: none
|
||||
ini-file: development
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
composer remove nextcloud/ocp --dev --no-scripts
|
||||
composer i
|
||||
|
||||
- name: Rector
|
||||
run: composer run rector
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
|
||||
with:
|
||||
token: ${{ secrets.COMMAND_BOT_PAT }}
|
||||
commit-message: 'refactor: Apply rector changes'
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: nextcloud-command <nextcloud-command@users.noreply.github.com>
|
||||
signoff: true
|
||||
branch: automated/noid/rector-changes
|
||||
title: 'Apply rector changes'
|
||||
labels: |
|
||||
technical debt
|
||||
3. to review
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
OC.L10N.register(
|
||||
"cloud_federation_api",
|
||||
{
|
||||
"Cloud Federation API" : "Jamg'armaning bulutli APIsi",
|
||||
"Cloud Federation API" : "Asl faylni o'chirishda kutilmagan xatolik yuz berdi.",
|
||||
"Enable clouds to communicate with each other and exchange data" : "Bulutlar bir-biri bilan aloqa qilish va ma'lumot almashish imkonini beradi",
|
||||
"The Cloud Federation API enables various Nextcloud instances to communicate with each other and to exchange data." : "Cloud Jamoada API turli xil Nextcloud misollariga bir-biri bilan muloqot qilish va ma'lumotlarni almashish imkonini beradi."
|
||||
"The Cloud Federation API enables various Nextcloud instances to communicate with each other and to exchange data." : "Cloud Federation API turli xil Nextcloud misollariga bir-biri bilan muloqot qilish va ma'lumotlarni almashish imkonini beradi."
|
||||
},
|
||||
"nplurals=1; plural=0;");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{ "translations": {
|
||||
"Cloud Federation API" : "Jamg'armaning bulutli APIsi",
|
||||
"Cloud Federation API" : "Asl faylni o'chirishda kutilmagan xatolik yuz berdi.",
|
||||
"Enable clouds to communicate with each other and exchange data" : "Bulutlar bir-biri bilan aloqa qilish va ma'lumot almashish imkonini beradi",
|
||||
"The Cloud Federation API enables various Nextcloud instances to communicate with each other and to exchange data." : "Cloud Jamoada API turli xil Nextcloud misollariga bir-biri bilan muloqot qilish va ma'lumotlarni almashish imkonini beradi."
|
||||
"The Cloud Federation API enables various Nextcloud instances to communicate with each other and to exchange data." : "Cloud Federation API turli xil Nextcloud misollariga bir-biri bilan muloqot qilish va ma'lumotlarni almashish imkonini beradi."
|
||||
},"pluralForm" :"nplurals=1; plural=0;"
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
OC.L10N.register(
|
||||
"comments",
|
||||
{
|
||||
"Comments" : "Izohlar",
|
||||
"You commented" : "Siz fikr bildirgansiz",
|
||||
"{author} commented" : "{author} izoh qoldirdi",
|
||||
"You commented on %1$s" : "Siz %1$s haqida fikr bildirdingiz",
|
||||
"You commented on {file}" : "Siz {file} ga izoh qoldirdingiz",
|
||||
"%1$s commented on %2$s" : "%1$s %2$s haqida fikr bildirdi",
|
||||
"{author} commented on {file}" : "{author} {file} ga izoh qoldirdi",
|
||||
"<strong>Comments</strong> for files" : "Fayllar uchun <strong>Izohlar</strong>",
|
||||
"Files" : "Fayllar",
|
||||
"You were mentioned on \"{file}\", in a comment by an account that has since been deleted" : "Siz \"{file}\"da, keyinchalik o'chirilgan hisob tomonidan izohda tilga olingansiz",
|
||||
"{user} mentioned you in a comment on \"{file}\"" : "{user} sizni \"{file}\" dagi izohda tilga oldi",
|
||||
"Files app plugin to add comments to files" : "Fayllarga izohlar qo'shish ilova plagini",
|
||||
"Edit comment" : "Izohni tahrirlash",
|
||||
"Delete comment" : "Izohni o'chirish",
|
||||
"Cancel edit" : "Tahrirni bekor qilish",
|
||||
"New comment" : "Yangi izoh",
|
||||
"Write a comment …" : "Fikr yozing…",
|
||||
"Post comment" : "Fikr qoldirish",
|
||||
"@ for mentions, : for emoji, / for smart picker" : "@ eslatmalar uchun, : emojilar uchun, / aqlli tanlovclar uchun",
|
||||
"Could not reload comments" : "Izohlarni qayta yuklab bo'lmadi",
|
||||
"Failed to mark comments as read" : "Izohlarni o'qilgan deb belgilashda xatolik yuz berdi",
|
||||
"Unable to load the comments list" : "Izohlar ro'yxatini yuklab bo'lmadi",
|
||||
"No comments yet, start the conversation!" : "Hali izohlar yo'q, suhbatni boshlang!",
|
||||
"No more messages" : "Boshqa xabarlar yo'q",
|
||||
"Retry" : "Qayta urinish",
|
||||
"_1 new comment_::_{unread} new comments_" : ["{unread} ta yangi izoh"],
|
||||
"Comment" : "Izoh",
|
||||
"An error occurred while trying to edit the comment" : "Izohni tahrirlashda xatolik yuz berdi",
|
||||
"Comment deleted" : "Izoh o'chirildi",
|
||||
"An error occurred while trying to delete the comment" : "Izohni o'chirishda xatolik yuz berdi",
|
||||
"An error occurred while trying to create the comment" : "Izoh yaratishda xatolik yuz berdi",
|
||||
"Write a comment …" : "Izoh yozing..."
|
||||
},
|
||||
"nplurals=1; plural=0;");
|
||||
@@ -1,35 +0,0 @@
|
||||
{ "translations": {
|
||||
"Comments" : "Izohlar",
|
||||
"You commented" : "Siz fikr bildirgansiz",
|
||||
"{author} commented" : "{author} izoh qoldirdi",
|
||||
"You commented on %1$s" : "Siz %1$s haqida fikr bildirdingiz",
|
||||
"You commented on {file}" : "Siz {file} ga izoh qoldirdingiz",
|
||||
"%1$s commented on %2$s" : "%1$s %2$s haqida fikr bildirdi",
|
||||
"{author} commented on {file}" : "{author} {file} ga izoh qoldirdi",
|
||||
"<strong>Comments</strong> for files" : "Fayllar uchun <strong>Izohlar</strong>",
|
||||
"Files" : "Fayllar",
|
||||
"You were mentioned on \"{file}\", in a comment by an account that has since been deleted" : "Siz \"{file}\"da, keyinchalik o'chirilgan hisob tomonidan izohda tilga olingansiz",
|
||||
"{user} mentioned you in a comment on \"{file}\"" : "{user} sizni \"{file}\" dagi izohda tilga oldi",
|
||||
"Files app plugin to add comments to files" : "Fayllarga izohlar qo'shish ilova plagini",
|
||||
"Edit comment" : "Izohni tahrirlash",
|
||||
"Delete comment" : "Izohni o'chirish",
|
||||
"Cancel edit" : "Tahrirni bekor qilish",
|
||||
"New comment" : "Yangi izoh",
|
||||
"Write a comment …" : "Fikr yozing…",
|
||||
"Post comment" : "Fikr qoldirish",
|
||||
"@ for mentions, : for emoji, / for smart picker" : "@ eslatmalar uchun, : emojilar uchun, / aqlli tanlovclar uchun",
|
||||
"Could not reload comments" : "Izohlarni qayta yuklab bo'lmadi",
|
||||
"Failed to mark comments as read" : "Izohlarni o'qilgan deb belgilashda xatolik yuz berdi",
|
||||
"Unable to load the comments list" : "Izohlar ro'yxatini yuklab bo'lmadi",
|
||||
"No comments yet, start the conversation!" : "Hali izohlar yo'q, suhbatni boshlang!",
|
||||
"No more messages" : "Boshqa xabarlar yo'q",
|
||||
"Retry" : "Qayta urinish",
|
||||
"_1 new comment_::_{unread} new comments_" : ["{unread} ta yangi izoh"],
|
||||
"Comment" : "Izoh",
|
||||
"An error occurred while trying to edit the comment" : "Izohni tahrirlashda xatolik yuz berdi",
|
||||
"Comment deleted" : "Izoh o'chirildi",
|
||||
"An error occurred while trying to delete the comment" : "Izohni o'chirishda xatolik yuz berdi",
|
||||
"An error occurred while trying to create the comment" : "Izoh yaratishda xatolik yuz berdi",
|
||||
"Write a comment …" : "Izoh yozing..."
|
||||
},"pluralForm" :"nplurals=1; plural=0;"
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -12,6 +12,7 @@ use OCP\App\IAppManager;
|
||||
use OCP\Comments\CommentsEvent;
|
||||
use OCP\Files\Config\IMountProviderCollection;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\Files\Node;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserSession;
|
||||
use OCP\Share\IShareHelper;
|
||||
@@ -46,8 +47,10 @@ class Listener {
|
||||
foreach ($mounts as $mount) {
|
||||
$owner = $mount->getUser()->getUID();
|
||||
$ownerFolder = $this->rootFolder->getUserFolder($owner);
|
||||
$node = $ownerFolder->getFirstNodeById((int)$event->getComment()->getObjectId());
|
||||
if ($node !== null) {
|
||||
$nodes = $ownerFolder->getById((int)$event->getComment()->getObjectId());
|
||||
if (!empty($nodes)) {
|
||||
/** @var Node $node */
|
||||
$node = array_shift($nodes);
|
||||
$al = $this->shareHelper->getPathsForAccessList($node);
|
||||
$users += $al['users'];
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -70,11 +70,11 @@ class NotificationsController extends Controller {
|
||||
return new NotFoundResponse();
|
||||
}
|
||||
$userFolder = $this->rootFolder->getUserFolder($currentUser->getUID());
|
||||
$file = $userFolder->getFirstNodeById((int)$comment->getObjectId());
|
||||
$files = $userFolder->getById((int)$comment->getObjectId());
|
||||
|
||||
$this->markProcessed($comment, $currentUser);
|
||||
|
||||
if ($file === null) {
|
||||
if (empty($files)) {
|
||||
return new NotFoundResponse();
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ class CommentsEntityEventListener implements IEventListener {
|
||||
}
|
||||
|
||||
$event->addEntityCollection('files', function ($name): bool {
|
||||
$node = $this->rootFolder->getUserFolder($this->userId)->getFirstNodeById((int)$name);
|
||||
return $node !== null;
|
||||
$nodes = $this->rootFolder->getUserFolder($this->userId)->getById((int)$name);
|
||||
return !empty($nodes);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,10 +84,11 @@ class Notifier implements INotifier {
|
||||
throw new UnknownNotificationException('Unsupported comment object');
|
||||
}
|
||||
$userFolder = $this->rootFolder->getUserFolder($notification->getUser());
|
||||
$node = $userFolder->getFirstNodeById((int)$parameters[1]);
|
||||
if ($node === null) {
|
||||
$nodes = $userFolder->getById((int)$parameters[1]);
|
||||
if (empty($nodes)) {
|
||||
throw new AlreadyProcessedException();
|
||||
}
|
||||
$node = $nodes[0];
|
||||
|
||||
$path = rtrim($node->getPath(), '/');
|
||||
if (str_starts_with($path, '/' . $notification->getUser() . '/files/')) {
|
||||
|
||||
@@ -116,11 +116,11 @@ class CommentsSearchProvider implements IProvider {
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
protected function getFileForComment(Folder $userFolder, IComment $comment): Node {
|
||||
$node = $userFolder->getFirstNodeById((int)$comment->getObjectId());
|
||||
if ($node === null) {
|
||||
$nodes = $userFolder->getById((int)$comment->getObjectId());
|
||||
if (empty($nodes)) {
|
||||
throw new NotFoundException('File not found');
|
||||
}
|
||||
|
||||
return $node;
|
||||
return array_shift($nodes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*!
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { IFolder, IView } from '@nextcloud/files'
|
||||
import type { Folder, View } from '@nextcloud/files'
|
||||
|
||||
import { File, Permission } from '@nextcloud/files'
|
||||
import { File, FileAction, Permission } from '@nextcloud/files'
|
||||
import { describe, expect, test, vi } from 'vitest'
|
||||
import logger from '../logger.js'
|
||||
import { action } from './inlineUnreadCommentsAction.ts'
|
||||
@@ -13,7 +13,7 @@ import { action } from './inlineUnreadCommentsAction.ts'
|
||||
const view = {
|
||||
id: 'files',
|
||||
name: 'Files',
|
||||
} as IView
|
||||
} as View
|
||||
|
||||
describe('Inline unread comments action display name tests', () => {
|
||||
test('Default values', () => {
|
||||
@@ -29,35 +29,36 @@ describe('Inline unread comments action display name tests', () => {
|
||||
root: '/files/admin',
|
||||
})
|
||||
|
||||
expect(action).toBeInstanceOf(FileAction)
|
||||
expect(action.id).toBe('comments-unread')
|
||||
expect(action.displayName({
|
||||
nodes: [file],
|
||||
view,
|
||||
folder: {} as IFolder,
|
||||
folder: {} as Folder,
|
||||
contents: [],
|
||||
})).toBe('')
|
||||
expect(action.title!({
|
||||
nodes: [file],
|
||||
view,
|
||||
folder: {} as IFolder,
|
||||
folder: {} as Folder,
|
||||
contents: [],
|
||||
})).toBe('1 new comment')
|
||||
expect(action.iconSvgInline({
|
||||
nodes: [file],
|
||||
view,
|
||||
folder: {} as IFolder,
|
||||
folder: {} as Folder,
|
||||
contents: [],
|
||||
})).toMatch(/<svg.+<\/svg>/)
|
||||
expect(action.enabled!({
|
||||
nodes: [file],
|
||||
view,
|
||||
folder: {} as IFolder,
|
||||
folder: {} as Folder,
|
||||
contents: [],
|
||||
})).toBe(true)
|
||||
expect(action.inline!({
|
||||
nodes: [file],
|
||||
view,
|
||||
folder: {} as IFolder,
|
||||
folder: {} as Folder,
|
||||
contents: [],
|
||||
})).toBe(true)
|
||||
expect(action.default).toBeUndefined()
|
||||
@@ -80,13 +81,13 @@ describe('Inline unread comments action display name tests', () => {
|
||||
expect(action.displayName({
|
||||
nodes: [file],
|
||||
view,
|
||||
folder: {} as IFolder,
|
||||
folder: {} as Folder,
|
||||
contents: [],
|
||||
})).toBe('')
|
||||
expect(action.title!({
|
||||
nodes: [file],
|
||||
view,
|
||||
folder: {} as IFolder,
|
||||
folder: {} as Folder,
|
||||
contents: [],
|
||||
})).toBe('2 new comments')
|
||||
})
|
||||
@@ -107,7 +108,7 @@ describe('Inline unread comments action enabled tests', () => {
|
||||
expect(action.enabled!({
|
||||
nodes: [file],
|
||||
view,
|
||||
folder: {} as IFolder,
|
||||
folder: {} as Folder,
|
||||
contents: [],
|
||||
})).toBe(false)
|
||||
})
|
||||
@@ -128,7 +129,7 @@ describe('Inline unread comments action enabled tests', () => {
|
||||
expect(action.enabled!({
|
||||
nodes: [file],
|
||||
view,
|
||||
folder: {} as IFolder,
|
||||
folder: {} as Folder,
|
||||
contents: [],
|
||||
})).toBe(false)
|
||||
})
|
||||
@@ -149,7 +150,7 @@ describe('Inline unread comments action enabled tests', () => {
|
||||
expect(action.enabled!({
|
||||
nodes: [file],
|
||||
view,
|
||||
folder: {} as IFolder,
|
||||
folder: {} as Folder,
|
||||
contents: [],
|
||||
})).toBe(true)
|
||||
})
|
||||
@@ -170,7 +171,7 @@ describe('Inline unread comments action enabled tests', () => {
|
||||
expect(action.enabled!({
|
||||
nodes: [file],
|
||||
view,
|
||||
folder: {} as IFolder,
|
||||
folder: {} as Folder,
|
||||
contents: [],
|
||||
})).toBe(true)
|
||||
})
|
||||
@@ -203,7 +204,7 @@ describe('Inline unread comments action execute tests', () => {
|
||||
const result = await action.exec!({
|
||||
nodes: [file],
|
||||
view,
|
||||
folder: {} as IFolder,
|
||||
folder: {} as Folder,
|
||||
contents: [],
|
||||
})
|
||||
|
||||
@@ -240,7 +241,7 @@ describe('Inline unread comments action execute tests', () => {
|
||||
const result = await action.exec!({
|
||||
nodes: [file],
|
||||
view,
|
||||
folder: {} as IFolder,
|
||||
folder: {} as Folder,
|
||||
contents: [],
|
||||
})
|
||||
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { IFileAction } from '@nextcloud/files'
|
||||
|
||||
import CommentProcessingSvg from '@mdi/svg/svg/comment-processing.svg?raw'
|
||||
import { getSidebar } from '@nextcloud/files'
|
||||
import { FileAction, getSidebar } from '@nextcloud/files'
|
||||
import { n, t } from '@nextcloud/l10n'
|
||||
import logger from '../logger.js'
|
||||
|
||||
export const action: IFileAction = {
|
||||
export const action = new FileAction({
|
||||
id: 'comments-unread',
|
||||
|
||||
title({ nodes }) {
|
||||
@@ -49,4 +47,4 @@ export const action: IFileAction = {
|
||||
inline: () => true,
|
||||
|
||||
order: -140,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -92,11 +92,12 @@ class ListenerTest extends TestCase {
|
||||
->willReturn($userMountCache);
|
||||
|
||||
$node = $this->createMock(Node::class);
|
||||
$nodes = [ $node ];
|
||||
|
||||
$ownerFolder = $this->createMock(Folder::class);
|
||||
$ownerFolder->expects($this->any())
|
||||
->method('getFirstNodeById')
|
||||
->willReturn($node);
|
||||
->method('getById')
|
||||
->willReturn($nodes);
|
||||
|
||||
$this->rootFolder->expects($this->any())
|
||||
->method('getUserFolder')
|
||||
|
||||
@@ -107,8 +107,8 @@ class NotificationsTest extends TestCase {
|
||||
->willReturn($folder);
|
||||
|
||||
$folder->expects($this->once())
|
||||
->method('getFirstNodeById')
|
||||
->willReturn($file);
|
||||
->method('getById')
|
||||
->willReturn([$file]);
|
||||
|
||||
$this->session->expects($this->once())
|
||||
->method('getUser')
|
||||
@@ -183,8 +183,8 @@ class NotificationsTest extends TestCase {
|
||||
->willReturn($folder);
|
||||
|
||||
$folder->expects($this->once())
|
||||
->method('getFirstNodeById')
|
||||
->willReturn(null);
|
||||
->method('getById')
|
||||
->willReturn([]);
|
||||
|
||||
$user = $this->createMock(IUser::class);
|
||||
|
||||
|
||||
@@ -86,9 +86,9 @@ class NotifierTest extends TestCase {
|
||||
->with('you')
|
||||
->willReturn($userFolder);
|
||||
$userFolder->expects($this->once())
|
||||
->method('getFirstNodeById')
|
||||
->method('getById')
|
||||
->with('678')
|
||||
->willReturn($node);
|
||||
->willReturn([$node]);
|
||||
|
||||
$this->notification->expects($this->exactly(2))
|
||||
->method('getUser')
|
||||
@@ -202,9 +202,9 @@ class NotifierTest extends TestCase {
|
||||
->with('you')
|
||||
->willReturn($userFolder);
|
||||
$userFolder->expects($this->once())
|
||||
->method('getFirstNodeById')
|
||||
->method('getById')
|
||||
->with('678')
|
||||
->willReturn($node);
|
||||
->willReturn([$node]);
|
||||
|
||||
$this->notification->expects($this->exactly(2))
|
||||
->method('getUser')
|
||||
@@ -301,7 +301,7 @@ class NotifierTest extends TestCase {
|
||||
|
||||
$this->folder
|
||||
->expects($this->never())
|
||||
->method('getFirstNodeById');
|
||||
->method('getById');
|
||||
|
||||
$this->notification
|
||||
->expects($this->once())
|
||||
@@ -338,7 +338,7 @@ class NotifierTest extends TestCase {
|
||||
|
||||
$this->folder
|
||||
->expects($this->never())
|
||||
->method('getFirstNodeById');
|
||||
->method('getById');
|
||||
|
||||
$this->notification
|
||||
->expects($this->once())
|
||||
@@ -378,7 +378,7 @@ class NotifierTest extends TestCase {
|
||||
|
||||
$this->folder
|
||||
->expects($this->never())
|
||||
->method('getFirstNodeById');
|
||||
->method('getById');
|
||||
|
||||
$this->notification
|
||||
->expects($this->once())
|
||||
@@ -435,7 +435,7 @@ class NotifierTest extends TestCase {
|
||||
|
||||
$this->folder
|
||||
->expects($this->never())
|
||||
->method('getFirstNodeById');
|
||||
->method('getById');
|
||||
|
||||
$this->notification
|
||||
->expects($this->once())
|
||||
@@ -497,9 +497,9 @@ class NotifierTest extends TestCase {
|
||||
->with('you')
|
||||
->willReturn($userFolder);
|
||||
$userFolder->expects($this->once())
|
||||
->method('getFirstNodeById')
|
||||
->method('getById')
|
||||
->with('678')
|
||||
->willReturn(null);
|
||||
->willReturn([]);
|
||||
|
||||
$this->notification->expects($this->once())
|
||||
->method('getUser')
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -89,7 +89,6 @@ use OCP\Contacts\IManager as IContactsManager;
|
||||
use OCP\DB\Events\AddMissingIndicesEvent;
|
||||
use OCP\Federation\Events\TrustedServerRemovedEvent;
|
||||
use OCP\Federation\ICloudFederationProviderManager;
|
||||
use OCP\Group\Events\GroupDeletedEvent;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUserSession;
|
||||
use OCP\Server;
|
||||
@@ -206,7 +205,6 @@ class Application extends App implements IBootstrap {
|
||||
$context->registerEventListener(UserCreatedEvent::class, UserEventsListener::class);
|
||||
$context->registerEventListener(UserChangedEvent::class, UserEventsListener::class);
|
||||
$context->registerEventListener(UserUpdatedEvent::class, UserEventsListener::class);
|
||||
$context->registerEventListener(GroupDeletedEvent::class, UserEventsListener::class);
|
||||
|
||||
$context->registerEventListener(SabrePluginAuthInitEvent::class, SabrePluginAuthInitListener::class);
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -67,7 +67,7 @@ class CalendarProvider implements ICalendarProvider {
|
||||
$user = str_replace('principals/users/', '', $calendarInfo['principaluri']);
|
||||
$path = 'calendars/' . $user . '/' . $calendarInfo['uri'];
|
||||
if (isset($additionalFederatedProps[$path])) {
|
||||
$calendarInfo = array_merge($calendarInfo, $additionalFederatedProps[$path]);
|
||||
$calendarInfo = array_merge($calendarInfo, $additionalProperties[$path]);
|
||||
}
|
||||
|
||||
$iCalendars[] = new FederatedCalendarImpl($calendarInfo, $this->calDavBackend);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -24,14 +24,17 @@ use function explode;
|
||||
|
||||
class RateLimitingPlugin extends ServerPlugin {
|
||||
|
||||
private Limiter $limiter;
|
||||
|
||||
public function __construct(
|
||||
private Limiter $limiter,
|
||||
Limiter $limiter,
|
||||
private IUserManager $userManager,
|
||||
private CalDavBackend $calDavBackend,
|
||||
private LoggerInterface $logger,
|
||||
private IAppConfig $config,
|
||||
private ?string $userId,
|
||||
) {
|
||||
$this->limiter = $limiter;
|
||||
}
|
||||
|
||||
public function initialize(DAV\Server $server): void {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud GmbH
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
namespace OCA\DAV\Connector\Sabre;
|
||||
|
||||
class MtimeSanitizer {
|
||||
|
||||
@@ -42,6 +42,9 @@ class Principal implements BackendInterface {
|
||||
/** @var bool */
|
||||
private $hasCircles;
|
||||
|
||||
/** @var KnownUserService */
|
||||
private $knownUserService;
|
||||
|
||||
public function __construct(
|
||||
private IUserManager $userManager,
|
||||
private IGroupManager $groupManager,
|
||||
@@ -50,13 +53,14 @@ class Principal implements BackendInterface {
|
||||
private IUserSession $userSession,
|
||||
private IAppManager $appManager,
|
||||
private ProxyMapper $proxyMapper,
|
||||
private KnownUserService $knownUserService,
|
||||
KnownUserService $knownUserService,
|
||||
private IConfig $config,
|
||||
private IFactory $languageFactory,
|
||||
string $principalPrefix = 'principals/users/',
|
||||
) {
|
||||
$this->principalPrefix = trim($principalPrefix, '/');
|
||||
$this->hasGroups = $this->hasCircles = ($principalPrefix === 'principals/users/');
|
||||
$this->knownUserService = $knownUserService;
|
||||
}
|
||||
|
||||
use PrincipalProxyTrait {
|
||||
|
||||
@@ -49,7 +49,11 @@ class TagsPlugin extends \Sabre\DAV\ServerPlugin {
|
||||
* @var \Sabre\DAV\Server
|
||||
*/
|
||||
private $server;
|
||||
private ?ITags $tagger = null;
|
||||
|
||||
/**
|
||||
* @var ITags
|
||||
*/
|
||||
private $tagger;
|
||||
|
||||
/**
|
||||
* Array of file id to tags array
|
||||
@@ -101,17 +105,11 @@ class TagsPlugin extends \Sabre\DAV\ServerPlugin {
|
||||
*
|
||||
* @return ITags tagger
|
||||
*/
|
||||
private function getTagger(): ITags {
|
||||
if ($this->tagger) {
|
||||
return $this->tagger;
|
||||
private function getTagger() {
|
||||
if (!$this->tagger) {
|
||||
$this->tagger = $this->tagManager->load('files');
|
||||
}
|
||||
|
||||
$tagger = $this->tagManager->load('files');
|
||||
if ($tagger === null) {
|
||||
throw new \RuntimeException('Tagger not found for files');
|
||||
}
|
||||
$this->tagger = $tagger;
|
||||
return $tagger;
|
||||
return $this->tagger;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -113,34 +113,6 @@ class CustomPropertiesBackend implements BackendInterface {
|
||||
'{http://owncloud.org/ns}calendar-enabled' => '1',
|
||||
];
|
||||
|
||||
/**
|
||||
* Allowed classes for deserialization
|
||||
*
|
||||
* @var class-string[]
|
||||
*/
|
||||
private const ALLOWED_SERIALIZED_CLASSES = [
|
||||
\Sabre\CalDAV\Xml\Property\AllowedSharingModes::class,
|
||||
\Sabre\CalDAV\Xml\Property\EmailAddressSet::class,
|
||||
\Sabre\CalDAV\Xml\Property\Invite::class,
|
||||
\Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp::class,
|
||||
\Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet::class,
|
||||
\Sabre\CalDAV\Xml\Property\SupportedCalendarData::class,
|
||||
\Sabre\CalDAV\Xml\Property\SupportedCollationSet::class,
|
||||
\Sabre\CardDAV\Xml\Property\SupportedAddressData::class,
|
||||
\Sabre\CardDAV\Xml\Property\SupportedCollationSet::class,
|
||||
\Sabre\DAV\Xml\Property\Complex::class,
|
||||
\Sabre\DAV\Xml\Property\GetLastModified::class,
|
||||
\Sabre\DAV\Xml\Property\Href::class,
|
||||
\Sabre\DAV\Xml\Property\Invite::class,
|
||||
\Sabre\DAV\Xml\Property\LocalHref::class,
|
||||
\Sabre\DAV\Xml\Property\LockDiscovery::class,
|
||||
\Sabre\DAV\Xml\Property\ResourceType::class,
|
||||
\Sabre\DAV\Xml\Property\ShareAccess::class,
|
||||
\Sabre\DAV\Xml\Property\SupportedLock::class,
|
||||
\Sabre\DAV\Xml\Property\SupportedMethodSet::class,
|
||||
\Sabre\DAV\Xml\Property\SupportedReportSet::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Properties cache
|
||||
*/
|
||||
@@ -648,7 +620,10 @@ class CustomPropertiesBackend implements BackendInterface {
|
||||
"Property \"$name\" has an invalid value of type " . gettype($value),
|
||||
);
|
||||
} else {
|
||||
if (!in_array($value::class, self::ALLOWED_SERIALIZED_CLASSES)) {
|
||||
if (!str_starts_with($value::class, 'Sabre\\DAV\\Xml\\Property\\')
|
||||
&& !str_starts_with($value::class, 'Sabre\\CalDAV\\Xml\\Property\\')
|
||||
&& !str_starts_with($value::class, 'Sabre\\CardDAV\\Xml\\Property\\')
|
||||
&& !str_starts_with($value::class, 'OCA\\DAV\\')) {
|
||||
throw new DavException(
|
||||
"Property \"$name\" has an invalid value of class " . $value::class,
|
||||
);
|
||||
@@ -672,10 +647,16 @@ class CustomPropertiesBackend implements BackendInterface {
|
||||
case self::PROPERTY_TYPE_HREF:
|
||||
return new Href($value);
|
||||
case self::PROPERTY_TYPE_OBJECT:
|
||||
return unserialize(
|
||||
str_replace('\x00', chr(0), $value),
|
||||
['allowed_classes' => self::ALLOWED_SERIALIZED_CLASSES]
|
||||
);
|
||||
if (preg_match('/^a:/', $value)) {
|
||||
// Array, unserialize only scalar values
|
||||
return unserialize(str_replace('\x00', chr(0), $value), ['allowed_classes' => false]);
|
||||
}
|
||||
if (!preg_match('/^O\:\d+\:\"(OCA\\\\DAV\\\\|Sabre\\\\(Cal|Card)?DAV\\\\Xml\\\\Property\\\\)/', $value)) {
|
||||
throw new \LogicException('Found an object class serialized in DB that is not allowed');
|
||||
}
|
||||
// some databases can not handel null characters, these are custom encoded during serialization
|
||||
// this custom encoding needs to be first reversed before unserializing
|
||||
return unserialize(str_replace('\x00', chr(0), $value));
|
||||
default:
|
||||
return $value;
|
||||
};
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -69,8 +69,9 @@ class ViewOnlyPlugin extends ServerPlugin {
|
||||
// The version source file is relative to the owner storage.
|
||||
// But we need the node from the current user perspective.
|
||||
if ($node->getOwner()->getUID() !== $currentUserId) {
|
||||
$node = $this->userFolder->getFirstNodeById($node->getId());
|
||||
if ($node === null) {
|
||||
$nodes = $this->userFolder->getById($node->getId());
|
||||
$node = array_pop($nodes);
|
||||
if (!$node) {
|
||||
throw new NotFoundException('Version file not accessible by current user');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -20,8 +20,6 @@ use OCP\BackgroundJob\IJobList;
|
||||
use OCP\Defaults;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\Group\Events\BeforeGroupDeletedEvent;
|
||||
use OCP\Group\Events\GroupDeletedEvent;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
use OCP\User\Events\BeforeUserDeletedEvent;
|
||||
@@ -34,7 +32,7 @@ use OCP\User\Events\UserIdAssignedEvent;
|
||||
use OCP\User\Events\UserIdUnassignedEvent;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/** @template-implements IEventListener<UserFirstTimeLoggedInEvent|UserIdAssignedEvent|BeforeUserIdUnassignedEvent|UserIdUnassignedEvent|BeforeUserDeletedEvent|UserDeletedEvent|UserCreatedEvent|UserChangedEvent|UserUpdatedEvent|BeforeGroupDeletedEvent|GroupDeletedEvent> */
|
||||
/** @template-implements IEventListener<UserFirstTimeLoggedInEvent|UserIdAssignedEvent|BeforeUserIdUnassignedEvent|UserIdUnassignedEvent|BeforeUserDeletedEvent|UserDeletedEvent|UserCreatedEvent|UserChangedEvent|UserUpdatedEvent> */
|
||||
class UserEventsListener implements IEventListener {
|
||||
|
||||
/** @var IUser[] */
|
||||
@@ -79,8 +77,6 @@ class UserEventsListener implements IEventListener {
|
||||
$this->firstLogin($event->getUser());
|
||||
} elseif ($event instanceof UserUpdatedEvent) {
|
||||
$this->updateUser($event->getUser());
|
||||
} elseif ($event instanceof GroupDeletedEvent) {
|
||||
$this->postDeleteGroup($event->getGroup()->getGID());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,12 +135,6 @@ class UserEventsListener implements IEventListener {
|
||||
unset($this->addressBooksToDelete[$uid]);
|
||||
}
|
||||
|
||||
public function postDeleteGroup(string $gid): void {
|
||||
$encodedGid = urlencode($gid);
|
||||
$this->calDav->deleteAllSharesByUser('principals/groups/' . $encodedGid);
|
||||
$this->cardDav->deleteAllSharesByUser('principals/groups/' . $encodedGid);
|
||||
}
|
||||
|
||||
public function changeUser(IUser $user, string $feature): void {
|
||||
// This case is already covered by the account manager firing up a signal
|
||||
// later on
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -16,16 +16,27 @@ class RemoveObjectProperties implements IRepairStep {
|
||||
private const ME_CARD_PROPERTY = '{http://calendarserver.org/ns/}me-card';
|
||||
private const CALENDAR_TRANSP_PROPERTY = '{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp';
|
||||
|
||||
/**
|
||||
* RemoveObjectProperties constructor.
|
||||
*
|
||||
* @param IDBConnection $connection
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly IDBConnection $connection,
|
||||
private IDBConnection $connection,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getName(): string {
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getName() {
|
||||
return 'Remove invalid object properties';
|
||||
}
|
||||
|
||||
public function run(IOutput $output): void {
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function run(IOutput $output) {
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
$updated = $query->delete('properties')
|
||||
->where($query->expr()->in('propertyname', $query->createNamedParameter([self::RESOURCE_TYPE_PROPERTY, self::ME_CARD_PROPERTY, self::CALENDAR_TRANSP_PROPERTY], IQueryBuilder::PARAM_STR_ARRAY)))
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
@@ -24,17 +22,23 @@ class AppleProvisioningPlugin extends ServerPlugin {
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
/**
|
||||
* @var \OC_Defaults
|
||||
*/
|
||||
protected $themingDefaults;
|
||||
|
||||
/**
|
||||
* AppleProvisioningPlugin constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
protected IUserSession $userSession,
|
||||
protected IURLGenerator $urlGenerator,
|
||||
protected \OC_Defaults $themingDefaults,
|
||||
\OC_Defaults $themingDefaults,
|
||||
protected IRequest $request,
|
||||
protected IL10N $l10n,
|
||||
protected \Closure $uuidClosure,
|
||||
) {
|
||||
$this->themingDefaults = $themingDefaults;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
@@ -22,15 +22,18 @@ use Sabre\DAV\Exception\NotFound;
|
||||
use Sabre\DAV\SimpleCollection;
|
||||
|
||||
class SystemTagsInUseCollection extends SimpleCollection {
|
||||
protected SystemTagsInFilesDetector $systemTagsInFilesDetector;
|
||||
|
||||
/** @noinspection PhpMissingParentConstructorInspection */
|
||||
public function __construct(
|
||||
protected IUserSession $userSession,
|
||||
protected IRootFolder $rootFolder,
|
||||
protected ISystemTagManager $systemTagManager,
|
||||
protected ISystemTagObjectMapper $tagMapper,
|
||||
protected SystemTagsInFilesDetector $systemTagsInFilesDetector,
|
||||
SystemTagsInFilesDetector $systemTagsInFilesDetector,
|
||||
protected string $mediaType = '',
|
||||
) {
|
||||
$this->systemTagsInFilesDetector = $systemTagsInFilesDetector;
|
||||
$this->name = 'systemtags-assigned';
|
||||
if ($this->mediaType != '') {
|
||||
$this->name .= '/' . $this->mediaType;
|
||||
|
||||
@@ -15,12 +15,16 @@ use OCP\Security\Bruteforce\IThrottler;
|
||||
use OCP\Share\Exceptions\ShareNotFound;
|
||||
use OCP\Share\IManager;
|
||||
use OCP\Share\IShare;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Test\TestCase;
|
||||
|
||||
#[Group(name: 'DB')]
|
||||
class LegacyPublicAuthTest extends TestCase {
|
||||
/**
|
||||
* Class LegacyPublicAuthTest
|
||||
*
|
||||
*
|
||||
* @package OCA\DAV\Tests\unit\Connector
|
||||
*/
|
||||
#[\PHPUnit\Framework\Attributes\Group(name: 'DB')]
|
||||
class LegacyPublicAuthTest extends \Test\TestCase {
|
||||
private ISession&MockObject $session;
|
||||
private IRequest&MockObject $request;
|
||||
private IManager&MockObject $shareManager;
|
||||
@@ -51,7 +55,7 @@ class LegacyPublicAuthTest extends TestCase {
|
||||
\OC_User::setIncognitoMode(false);
|
||||
|
||||
// Set old user
|
||||
\OC_User::setUserId($this->oldUser ?: null);
|
||||
\OC_User::setUserId($this->oldUser);
|
||||
if ($this->oldUser !== false) {
|
||||
\OC_Util::setupFS($this->oldUser);
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ class PrincipalTest extends TestCase {
|
||||
}
|
||||
|
||||
public function testGetPrincipalsByPrefixWithUsers(): void {
|
||||
$fooUser = $this->createMock(IUser::class);
|
||||
$fooUser = $this->createMock(User::class);
|
||||
$fooUser
|
||||
->expects($this->once())
|
||||
->method('getUID')
|
||||
@@ -91,7 +91,7 @@ class PrincipalTest extends TestCase {
|
||||
->expects($this->once())
|
||||
->method('getSystemEMailAddress')
|
||||
->willReturn('');
|
||||
$barUser = $this->createMock(IUser::class);
|
||||
$barUser = $this->createMock(User::class);
|
||||
$barUser
|
||||
->expects($this->once())
|
||||
->method('getUID')
|
||||
@@ -183,7 +183,7 @@ class PrincipalTest extends TestCase {
|
||||
}
|
||||
|
||||
public function testGetPrincipalsByPathWithoutMail(): void {
|
||||
$fooUser = $this->createMock(IUser::class);
|
||||
$fooUser = $this->createMock(User::class);
|
||||
$fooUser
|
||||
->expects($this->once())
|
||||
->method('getUID')
|
||||
@@ -211,7 +211,7 @@ class PrincipalTest extends TestCase {
|
||||
}
|
||||
|
||||
public function testGetPrincipalsByPathWithMail(): void {
|
||||
$fooUser = $this->createMock(IUser::class);
|
||||
$fooUser = $this->createMock(User::class);
|
||||
$fooUser
|
||||
->expects($this->once())
|
||||
->method('getSystemEMailAddress')
|
||||
|
||||
@@ -182,15 +182,4 @@ class UserEventsListenerTest extends TestCase {
|
||||
$this->userEventsListener->preDeleteUser($user);
|
||||
$this->userEventsListener->postDeleteUser('newUser');
|
||||
}
|
||||
|
||||
public function testDeleteGroup(): void {
|
||||
$this->calDavBackend->expects($this->once())
|
||||
->method('deleteAllSharesByUser')
|
||||
->with('principals/groups/testGroup');
|
||||
$this->cardDavBackend->expects($this->once())
|
||||
->method('deleteAllSharesByUser')
|
||||
->with('principals/groups/testGroup');
|
||||
|
||||
$this->userEventsListener->postDeleteGroup('testGroup');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,6 @@ class ViewOnlyPluginTest extends TestCase {
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'providesDataForCanGet')]
|
||||
public function testCanGet(bool $isVersion, ?bool $attrEnabled, bool $expectCanDownloadFile, bool $allowViewWithoutDownload): void {
|
||||
$nodeInfo = $this->createMock(File::class);
|
||||
$nodeInfo->method('getId')->willReturn(42);
|
||||
if ($isVersion) {
|
||||
$davPath = 'versions/alice/versions/117/123456';
|
||||
$version = $this->createMock(IVersion::class);
|
||||
@@ -123,9 +122,8 @@ class ViewOnlyPluginTest extends TestCase {
|
||||
->method('getUID')
|
||||
->willReturn('bob');
|
||||
$this->userFolder->expects($this->once())
|
||||
->method('getFirstNodeById')
|
||||
->with(42)
|
||||
->willReturn($nodeInfo);
|
||||
->method('getById')
|
||||
->willReturn([$nodeInfo]);
|
||||
$this->userFolder->expects($this->once())
|
||||
->method('getOwner')
|
||||
->willReturn($owner);
|
||||
|
||||
@@ -22,20 +22,19 @@ OC.L10N.register(
|
||||
"Private key password successfully updated." : "Kişisel anahtar parolası güncellendi.",
|
||||
"Invalid private key for encryption app. Please update your private key password in your personal settings to recover access to your encrypted files." : "Şifreleme uygulaması kişisel anahtarı geçersiz. Şifrelenmiş dosyalarınıza erişebilmek için kişisel ayarlarınızdaki kişisel anahtar parolanızı güncelleyin.",
|
||||
"Encryption App is enabled, but your keys are not initialized. Please log-out and log-in again." : "Şifreleme uygulaması kullanıma alınmış ancak anahtarlarınız hazırlanmamış. Lütfen oturumunuzu kapatıp yeniden açın.",
|
||||
"Please enable server side encryption in the admin settings in order to use the encryption module." : "Şifreleme modülünü kullanabilmek için yönetici ayarlarından sunucuda şifreleme seçeneğini açın.",
|
||||
"Please enable server side encryption in the admin settings in order to use the encryption module." : "Şifreleme modülünü kullanabilmek için yönetici ayarlarından sunucu tarafında şifreleme seçeneğini açın.",
|
||||
"Encryption app is enabled and ready" : "Şifreleme uygulaması kullanıma alındı ve hazır",
|
||||
"Bad Signature" : "İmza bozuk",
|
||||
"Missing Signature" : "İmza eksik",
|
||||
"one-time password for server-side-encryption" : "sunucuda şifreleme için tek kullanımlık parola",
|
||||
"one-time password for server-side-encryption" : "sunucu tarafında şifreleme için tek kullanımlık parola",
|
||||
"Encryption password" : "Şifreleme parolası",
|
||||
"The administration enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>." : "Yönetici, sunucuda şifreleme özelliğini açmış. Dosyalarınız <strong>%s</strong> parolası ile şifrelendi.",
|
||||
"The administration enabled server-side-encryption. Your files were encrypted using the password \"%s\"." : "Yönetici, sunucuda şifreleme özelliğini açmış. Dosyalarınız \"%s\" parolası ile şifrelendi.",
|
||||
"The administration enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>." : "Yönetici, sunucu tarafında şifreleme özelliğini açmış. Dosyalarınız <strong>%s</strong> parolası ile şifrelendi.",
|
||||
"The administration enabled server-side-encryption. Your files were encrypted using the password \"%s\"." : "Yönetici, sunucu tarafında şifreleme özelliğini açmış. Dosyalarınız \"%s\" parolası ile şifrelendi.",
|
||||
"Please login to the web interface, go to the \"Security\" section of your personal settings and update your encryption password by entering this password into the \"Old login password\" field and your current login password." : "Lütfen yönetim bölümünden oturum açarak kişisel ayarlarınızdaki \"Güvenlik\" bölümüne gidin ve \"Eski oturum açma parolası\" alanına bu parolayı ve geçerli oturum açma parolanızı yazarak şifreleme parolanızı güncelleyin.",
|
||||
"Cannot decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Bu dosyanın şifresi çözülemedi ve büyük olasılıkla paylaşılan bir dosya. Lütfen dosya sahibi ile görüşerek sizinle yeniden paylaşmasını isteyin.",
|
||||
"Cannot read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Bu dosya okunamadı ve büyük olasılıkla paylaşılan bir dosya. Lütfen dosya sahibi ile görüşerek sizinle yeniden paylaşmasını isteyin.",
|
||||
"Default Encryption Module" : "Varsayılan şifreleme modülü",
|
||||
"Default encryption module for Nextcloud Server-side Encryption (SSE)" : "Nextcloud sunucuda şifreleme (SSE) için varsayılan şifreleme modülü",
|
||||
"This app provides the (default) cryptography implementation for Nextcloud's Server-side Encryption (SSE) feature.\n\n\t\t\t**Encryption Details**\n\t\t\t* **Cipher Mode:** AES-256-CTR (default)\n\t\t\t* **Authentication:** HMAC-SHA256\n\n\t\t\t**Important Warnings**\n\t\t\t* **DANGER:** Do not disable this application until all files have been decrypted (`occ encryption:decrypt-all`).\n\t\t\t* **WARNING**: Reverting to non-encrypted file storage after activation requires command-line access. The action is permanent via the Web UI.\"\n\n\t\t\t**Notes for Existing Files**\n\t\t\t* By default, enabling SSE does not encrypt existing files; only new files will be encrypted.\n\t\t\t* To encrypt all existing files, use the command `occ encryption:encrypt-all`.\n\n\t\t\t**Before You Begin**\n\t\t\t* **Read the Documentation:** Before you enable SSE, encrypt existing files, or disable SSE, it is critical to\n\t\t\t\tread the documentation to understand implications and the appropriate procedures to avoid data loss." : "Bu uygulama, Nextcloud sunucuda şifreleme (SSE) özelliği için (varsayılan) şifreleme uygulamasını sağlar.\n\n\t\t\t**Şifreleme ayrıntıları**\n\t\t\t* **Şifreleme kipi:** AES-256-CTR (varsayılan)\n\t\t\t* **Kimlik doğrulaması:** HMAC-SHA256\n\n\t\t\t**Önemli uyarılar**\n\t\t\t* **DİKKAT:** Tüm dosyaların şifresi çözülene kadar bu uygulamayı kapatmayın (`occ encryption:decrypt-all`).\n\t\t\t* **UYARI**: Açtıktan sonra şifrelenmemiş dosya depolama alanına geri dönmek için komut satırına erişim gerekir. İşlem, internet kullanıcı arayüzünden kalıcıdır.\"\n\n\t\t\t**Var olan dosyalar için notlar**\n\t\t\t* Varsayılan olarak, sunucuda şifrelemeyi açmak var olan dosyaları şifrelemez. Yalnızca yeni dosyalar şifrelenir.\n\t\t\t* Var olan tüm dosyaları şifrelemek için şu komutu kullanın: `occ encryption:encrypt-all`.\n\n\t\t\t**Başlamadan önce**\n\t\t\t* **Belgeleri okuyun:** Açmadan önce var olan dosyaları şifreleyin ya da sunucuda şifrelemeyi kapatın. \n\t\t\t\tVeri kaybını önlemek için, sonuçları ve uygun prosedürleri anlamak amacıyla belgeleri okumak çok önemlidir.",
|
||||
"Default encryption module for Nextcloud Server-side Encryption (SSE)" : "Nextcloud sunucu tarafında şifreleme (SSE) için varsayılan şifreleme modülü",
|
||||
"Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Bu seçenek açıldığında, ana depolama alanındaki tüm dosyalar şifrelenir. Kapatıldığında, yalnızca dış depolama alanındaki dosyalar şifrelenir",
|
||||
"Encrypt the home storage" : "Ana depolama şifrelensin",
|
||||
"Disable recovery key" : "Kurtarma anahtarını kullanımdan kaldır",
|
||||
@@ -64,7 +63,7 @@ OC.L10N.register(
|
||||
"Basic encryption module" : "Temel şifreleme modülü",
|
||||
"Missing parameters" : "Parametreler eksik",
|
||||
"Default encryption module for server-side encryption" : "Sunucu tarafında şifreleme için varsayılan şifreleme modülü",
|
||||
"In order to use this encryption module you need to enable server-side encryption in the admin settings. Once enabled this module will encrypt all your files transparently. The encryption is based on AES 256 keys.\nThe module will not touch existing files, only new files will be encrypted after server-side encryption was enabled. It is also not possible to disable the encryption again and switch back to an unencrypted system.\nPlease read the documentation to know all implications before you decide to enable server-side encryption." : "Bu şifreleme modülünün kullanılması için sunucuda yönetim bölümünden şifreleme seçeneği açılmalıdır. Bu modül kullanıma alındıktan sonra tüm dosyalarınızı size farkettirmeden şifreler. Şifreleme AES 256 anahtarları ile yapılır. \nModül var olan dosyaları değiştirmez, yalnızca sunucuda şifreleme açıldıktan sonra eklenen yeni dosyalar şifrelenir. Şifreleme açıldıktan sonra kapatılamaz ve şifreleme olmayan sisteme geri dönülemez.\nLütfen sunucuda şifrelemeyi açmadan önce belgeleri okuyun ve uygulamadan doğacak tüm sonuçlarını öğrenin.",
|
||||
"In order to use this encryption module you need to enable server-side encryption in the admin settings. Once enabled this module will encrypt all your files transparently. The encryption is based on AES 256 keys.\nThe module will not touch existing files, only new files will be encrypted after server-side encryption was enabled. It is also not possible to disable the encryption again and switch back to an unencrypted system.\nPlease read the documentation to know all implications before you decide to enable server-side encryption." : "Bu şifreleme modülünün kullanılması için sunucu tarafında yönetim bölümünden şifreleme seçeneği açılmalıdır. Bu modül kullanıma alındıktan sonra tüm dosyalarınızı size farkettirmeden şifreler. Şifreleme AES 256 anahtarları ile yapılır. \nModül var olan dosyaları değiştirmez, yalnızca sunucu tarafında şifreleme açıldıktan sonra eklenen yeni dosyalar şifrelenir. Şifreleme açıldıktan sonra kapatılamaz ve şifreleme olmayan sisteme geri dönülemez.\nLütfen sunucu tarafı şifrelemeyi açmadan önce belgeleri okuyun ve uygulamadan doğacak tüm sonuçlarını öğrenin.",
|
||||
"Change recovery key password:" : "Kurtarma anahtarı parolasını değiştir:",
|
||||
"Change Password" : "Parolayı değiştir",
|
||||
"Your private key password no longer matches your log-in password." : "Kişisel anahtar parolanız artık oturum açma parolanız ile eşleşmiyor.",
|
||||
@@ -73,6 +72,6 @@ OC.L10N.register(
|
||||
"Enable password recovery:" : "Parola kurtarma özelliğini aç:",
|
||||
"Enabled" : "Açık",
|
||||
"Disabled" : "Kapalı",
|
||||
"This app provides the (default) cryptography implementation for Nextcloud's Server-side Encryption (SSE) feature.\n\n\t\t\t**Encryption Details**\n\t\t\t* **Cipher Mode:** AES-256-CTR (default)\n\t\t\t* **Authentication:** HMAC-SHA256\n\n\t\t\t**Important Warnings**\n\t\t\t* **DANGER:** Do not disable this application until all files have been decrypted (`occ encryption:decrypt-all`).\n\t\t\t* **WARNING**: Reverting to non-encrypted file storage after activation requires command-line access. The action is permanent via the Web UI.\"\n\n\t\t\t**Notes for Existing Files**\n\t\t\t* By default, enabling SSE does not encrypt existing files; only new files will be encrypted.\n\t\t\t* To encrypt all existing files, use the command `occ encryption:encrypt-all`.\n\n\t\t\t**Before You Begin**\n\t\t\t* **Read the Documentation:** Before you enable SSE, encrypt existing files, or disable SSE, it is critical to \n\t\t\t\tread the documentation to understand implications and the appropriate procedures to avoid data loss." : "Bu uygulama, Nextcloud sunucuda şifreleme (SSE) özelliği için (varsayılan) şifreleme uygulamasını sağlar.\n\n\t\t\t**Şifreleme ayrıntıları**\n\t\t\t* **Şifreleme kipi:** AES-256-CTR (varsayılan)\n\t\t\t* **Kimlik doğrulaması:** HMAC-SHA256\n\n\t\t\t**Önemli uyarılar**\n\t\t\t* **DİKKAT:** Tüm dosyaların şifresi çözülene kadar bu uygulamayı kapatmayın (`occ encryption:decrypt-all`).\n\t\t\t* **UYARI**: Açıldıktan sonra şifrelenmemiş dosya depolama alanına geri dönmek için komut satırına erişim gerekir. İşlem, internet kullanıcı arayüzünden kalıcıdır.\"\n\n\t\t\t**Var olan dosyalar için notlar**\n\t\t\t* Varsayılan olarak, sunucuda şifrelemeyi açmak var olan dosyaları şifrelemez. Yalnızca yeni dosyalar şifrelenir.\n\t\t\t* Var olan tüm dosyaları şifrelemek için şu komutu kullanın: `occ encryption:encrypt-all`.\n\n\t\t\t**Başlamadan önce**\n\t\t\t* **Belgeleri okuyun:** Açmadan önce var olan dosyaları şifreleyin ya da sunucuda şifrelemeyi kapatın. \n\t\t\t\tVeri kaybını önlemek için sonuçları ve uygun prosedürleri anlamak amacıyla belgeleri okumak çok önemlidir."
|
||||
"This app provides the (default) cryptography implementation for Nextcloud's Server-side Encryption (SSE) feature.\n\n\t\t\t**Encryption Details**\n\t\t\t* **Cipher Mode:** AES-256-CTR (default)\n\t\t\t* **Authentication:** HMAC-SHA256\n\n\t\t\t**Important Warnings**\n\t\t\t* **DANGER:** Do not disable this application until all files have been decrypted (`occ encryption:decrypt-all`).\n\t\t\t* **WARNING**: Reverting to non-encrypted file storage after activation requires command-line access. The action is permanent via the Web UI.\"\n\n\t\t\t**Notes for Existing Files**\n\t\t\t* By default, enabling SSE does not encrypt existing files; only new files will be encrypted.\n\t\t\t* To encrypt all existing files, use the command `occ encryption:encrypt-all`.\n\n\t\t\t**Before You Begin**\n\t\t\t* **Read the Documentation:** Before you enable SSE, encrypt existing files, or disable SSE, it is critical to \n\t\t\t\tread the documentation to understand implications and the appropriate procedures to avoid data loss." : "Bu uygulama, Nextcloud sunucu tarafı şifreleme (SSE) özelliği için (varsayılan) şifreleme uygulamasını sağlar.\n\n\t\t\t**Şifreleme ayrıntıları**\n\t\t\t* **Şifreleme kipi:** AES-256-CTR (varsayılan)\n\t\t\t* **Kimlik doğrulaması:** HMAC-SHA256\n\n\t\t\t**Önemli uyarılar**\n\t\t\t* **DİKKAT:** Tüm dosyaların şifresi çözülene kadar bu uygulamayı etkisizleştirmeyin (`occ encryption:decrypt-all`).\n\t\t\t* **UYARI**: Etkinleştirildikten sonra şifrelenmemiş dosya depolama alanına geri dönmek için komut satırına erişim gerekir. İşlem, internet kullanıcı arayüzünden kalıcıdır.\"\n\n\t\t\t**Var olan dosyalar için notlar**\n\t\t\t* Varsayılan olarak, sunucu tarafı şifrelemeyi etkinleştirmek var olan dosyaları şifrelemez. Yalnızca yeni dosyalar şifrelenir.\n\t\t\t* Var olan tüm dosyaları şifrelemek için şu komutu kullanın: `occ encryption:encrypt-all`.\n\n\t\t\t**Başlamadan önce**\n\t\t\t* **Belgeleri okuyun:** Sunucu tarafı şifrelemeyi etkinleştirmeden önce var olan dosyaları şifreleyin ya da sunucu tarafı şifrelemeyi etkisizleştirin. \n\t\t\t\tVeri kaybını önlemek için sonuçları ve uygun prosedürleri anlamak üzere belgeleri okumak çok önemlidir."
|
||||
},
|
||||
"nplurals=2; plural=(n > 1);");
|
||||
|
||||
@@ -20,20 +20,19 @@
|
||||
"Private key password successfully updated." : "Kişisel anahtar parolası güncellendi.",
|
||||
"Invalid private key for encryption app. Please update your private key password in your personal settings to recover access to your encrypted files." : "Şifreleme uygulaması kişisel anahtarı geçersiz. Şifrelenmiş dosyalarınıza erişebilmek için kişisel ayarlarınızdaki kişisel anahtar parolanızı güncelleyin.",
|
||||
"Encryption App is enabled, but your keys are not initialized. Please log-out and log-in again." : "Şifreleme uygulaması kullanıma alınmış ancak anahtarlarınız hazırlanmamış. Lütfen oturumunuzu kapatıp yeniden açın.",
|
||||
"Please enable server side encryption in the admin settings in order to use the encryption module." : "Şifreleme modülünü kullanabilmek için yönetici ayarlarından sunucuda şifreleme seçeneğini açın.",
|
||||
"Please enable server side encryption in the admin settings in order to use the encryption module." : "Şifreleme modülünü kullanabilmek için yönetici ayarlarından sunucu tarafında şifreleme seçeneğini açın.",
|
||||
"Encryption app is enabled and ready" : "Şifreleme uygulaması kullanıma alındı ve hazır",
|
||||
"Bad Signature" : "İmza bozuk",
|
||||
"Missing Signature" : "İmza eksik",
|
||||
"one-time password for server-side-encryption" : "sunucuda şifreleme için tek kullanımlık parola",
|
||||
"one-time password for server-side-encryption" : "sunucu tarafında şifreleme için tek kullanımlık parola",
|
||||
"Encryption password" : "Şifreleme parolası",
|
||||
"The administration enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>." : "Yönetici, sunucuda şifreleme özelliğini açmış. Dosyalarınız <strong>%s</strong> parolası ile şifrelendi.",
|
||||
"The administration enabled server-side-encryption. Your files were encrypted using the password \"%s\"." : "Yönetici, sunucuda şifreleme özelliğini açmış. Dosyalarınız \"%s\" parolası ile şifrelendi.",
|
||||
"The administration enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>." : "Yönetici, sunucu tarafında şifreleme özelliğini açmış. Dosyalarınız <strong>%s</strong> parolası ile şifrelendi.",
|
||||
"The administration enabled server-side-encryption. Your files were encrypted using the password \"%s\"." : "Yönetici, sunucu tarafında şifreleme özelliğini açmış. Dosyalarınız \"%s\" parolası ile şifrelendi.",
|
||||
"Please login to the web interface, go to the \"Security\" section of your personal settings and update your encryption password by entering this password into the \"Old login password\" field and your current login password." : "Lütfen yönetim bölümünden oturum açarak kişisel ayarlarınızdaki \"Güvenlik\" bölümüne gidin ve \"Eski oturum açma parolası\" alanına bu parolayı ve geçerli oturum açma parolanızı yazarak şifreleme parolanızı güncelleyin.",
|
||||
"Cannot decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Bu dosyanın şifresi çözülemedi ve büyük olasılıkla paylaşılan bir dosya. Lütfen dosya sahibi ile görüşerek sizinle yeniden paylaşmasını isteyin.",
|
||||
"Cannot read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Bu dosya okunamadı ve büyük olasılıkla paylaşılan bir dosya. Lütfen dosya sahibi ile görüşerek sizinle yeniden paylaşmasını isteyin.",
|
||||
"Default Encryption Module" : "Varsayılan şifreleme modülü",
|
||||
"Default encryption module for Nextcloud Server-side Encryption (SSE)" : "Nextcloud sunucuda şifreleme (SSE) için varsayılan şifreleme modülü",
|
||||
"This app provides the (default) cryptography implementation for Nextcloud's Server-side Encryption (SSE) feature.\n\n\t\t\t**Encryption Details**\n\t\t\t* **Cipher Mode:** AES-256-CTR (default)\n\t\t\t* **Authentication:** HMAC-SHA256\n\n\t\t\t**Important Warnings**\n\t\t\t* **DANGER:** Do not disable this application until all files have been decrypted (`occ encryption:decrypt-all`).\n\t\t\t* **WARNING**: Reverting to non-encrypted file storage after activation requires command-line access. The action is permanent via the Web UI.\"\n\n\t\t\t**Notes for Existing Files**\n\t\t\t* By default, enabling SSE does not encrypt existing files; only new files will be encrypted.\n\t\t\t* To encrypt all existing files, use the command `occ encryption:encrypt-all`.\n\n\t\t\t**Before You Begin**\n\t\t\t* **Read the Documentation:** Before you enable SSE, encrypt existing files, or disable SSE, it is critical to\n\t\t\t\tread the documentation to understand implications and the appropriate procedures to avoid data loss." : "Bu uygulama, Nextcloud sunucuda şifreleme (SSE) özelliği için (varsayılan) şifreleme uygulamasını sağlar.\n\n\t\t\t**Şifreleme ayrıntıları**\n\t\t\t* **Şifreleme kipi:** AES-256-CTR (varsayılan)\n\t\t\t* **Kimlik doğrulaması:** HMAC-SHA256\n\n\t\t\t**Önemli uyarılar**\n\t\t\t* **DİKKAT:** Tüm dosyaların şifresi çözülene kadar bu uygulamayı kapatmayın (`occ encryption:decrypt-all`).\n\t\t\t* **UYARI**: Açtıktan sonra şifrelenmemiş dosya depolama alanına geri dönmek için komut satırına erişim gerekir. İşlem, internet kullanıcı arayüzünden kalıcıdır.\"\n\n\t\t\t**Var olan dosyalar için notlar**\n\t\t\t* Varsayılan olarak, sunucuda şifrelemeyi açmak var olan dosyaları şifrelemez. Yalnızca yeni dosyalar şifrelenir.\n\t\t\t* Var olan tüm dosyaları şifrelemek için şu komutu kullanın: `occ encryption:encrypt-all`.\n\n\t\t\t**Başlamadan önce**\n\t\t\t* **Belgeleri okuyun:** Açmadan önce var olan dosyaları şifreleyin ya da sunucuda şifrelemeyi kapatın. \n\t\t\t\tVeri kaybını önlemek için, sonuçları ve uygun prosedürleri anlamak amacıyla belgeleri okumak çok önemlidir.",
|
||||
"Default encryption module for Nextcloud Server-side Encryption (SSE)" : "Nextcloud sunucu tarafında şifreleme (SSE) için varsayılan şifreleme modülü",
|
||||
"Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Bu seçenek açıldığında, ana depolama alanındaki tüm dosyalar şifrelenir. Kapatıldığında, yalnızca dış depolama alanındaki dosyalar şifrelenir",
|
||||
"Encrypt the home storage" : "Ana depolama şifrelensin",
|
||||
"Disable recovery key" : "Kurtarma anahtarını kullanımdan kaldır",
|
||||
@@ -62,7 +61,7 @@
|
||||
"Basic encryption module" : "Temel şifreleme modülü",
|
||||
"Missing parameters" : "Parametreler eksik",
|
||||
"Default encryption module for server-side encryption" : "Sunucu tarafında şifreleme için varsayılan şifreleme modülü",
|
||||
"In order to use this encryption module you need to enable server-side encryption in the admin settings. Once enabled this module will encrypt all your files transparently. The encryption is based on AES 256 keys.\nThe module will not touch existing files, only new files will be encrypted after server-side encryption was enabled. It is also not possible to disable the encryption again and switch back to an unencrypted system.\nPlease read the documentation to know all implications before you decide to enable server-side encryption." : "Bu şifreleme modülünün kullanılması için sunucuda yönetim bölümünden şifreleme seçeneği açılmalıdır. Bu modül kullanıma alındıktan sonra tüm dosyalarınızı size farkettirmeden şifreler. Şifreleme AES 256 anahtarları ile yapılır. \nModül var olan dosyaları değiştirmez, yalnızca sunucuda şifreleme açıldıktan sonra eklenen yeni dosyalar şifrelenir. Şifreleme açıldıktan sonra kapatılamaz ve şifreleme olmayan sisteme geri dönülemez.\nLütfen sunucuda şifrelemeyi açmadan önce belgeleri okuyun ve uygulamadan doğacak tüm sonuçlarını öğrenin.",
|
||||
"In order to use this encryption module you need to enable server-side encryption in the admin settings. Once enabled this module will encrypt all your files transparently. The encryption is based on AES 256 keys.\nThe module will not touch existing files, only new files will be encrypted after server-side encryption was enabled. It is also not possible to disable the encryption again and switch back to an unencrypted system.\nPlease read the documentation to know all implications before you decide to enable server-side encryption." : "Bu şifreleme modülünün kullanılması için sunucu tarafında yönetim bölümünden şifreleme seçeneği açılmalıdır. Bu modül kullanıma alındıktan sonra tüm dosyalarınızı size farkettirmeden şifreler. Şifreleme AES 256 anahtarları ile yapılır. \nModül var olan dosyaları değiştirmez, yalnızca sunucu tarafında şifreleme açıldıktan sonra eklenen yeni dosyalar şifrelenir. Şifreleme açıldıktan sonra kapatılamaz ve şifreleme olmayan sisteme geri dönülemez.\nLütfen sunucu tarafı şifrelemeyi açmadan önce belgeleri okuyun ve uygulamadan doğacak tüm sonuçlarını öğrenin.",
|
||||
"Change recovery key password:" : "Kurtarma anahtarı parolasını değiştir:",
|
||||
"Change Password" : "Parolayı değiştir",
|
||||
"Your private key password no longer matches your log-in password." : "Kişisel anahtar parolanız artık oturum açma parolanız ile eşleşmiyor.",
|
||||
@@ -71,6 +70,6 @@
|
||||
"Enable password recovery:" : "Parola kurtarma özelliğini aç:",
|
||||
"Enabled" : "Açık",
|
||||
"Disabled" : "Kapalı",
|
||||
"This app provides the (default) cryptography implementation for Nextcloud's Server-side Encryption (SSE) feature.\n\n\t\t\t**Encryption Details**\n\t\t\t* **Cipher Mode:** AES-256-CTR (default)\n\t\t\t* **Authentication:** HMAC-SHA256\n\n\t\t\t**Important Warnings**\n\t\t\t* **DANGER:** Do not disable this application until all files have been decrypted (`occ encryption:decrypt-all`).\n\t\t\t* **WARNING**: Reverting to non-encrypted file storage after activation requires command-line access. The action is permanent via the Web UI.\"\n\n\t\t\t**Notes for Existing Files**\n\t\t\t* By default, enabling SSE does not encrypt existing files; only new files will be encrypted.\n\t\t\t* To encrypt all existing files, use the command `occ encryption:encrypt-all`.\n\n\t\t\t**Before You Begin**\n\t\t\t* **Read the Documentation:** Before you enable SSE, encrypt existing files, or disable SSE, it is critical to \n\t\t\t\tread the documentation to understand implications and the appropriate procedures to avoid data loss." : "Bu uygulama, Nextcloud sunucuda şifreleme (SSE) özelliği için (varsayılan) şifreleme uygulamasını sağlar.\n\n\t\t\t**Şifreleme ayrıntıları**\n\t\t\t* **Şifreleme kipi:** AES-256-CTR (varsayılan)\n\t\t\t* **Kimlik doğrulaması:** HMAC-SHA256\n\n\t\t\t**Önemli uyarılar**\n\t\t\t* **DİKKAT:** Tüm dosyaların şifresi çözülene kadar bu uygulamayı kapatmayın (`occ encryption:decrypt-all`).\n\t\t\t* **UYARI**: Açıldıktan sonra şifrelenmemiş dosya depolama alanına geri dönmek için komut satırına erişim gerekir. İşlem, internet kullanıcı arayüzünden kalıcıdır.\"\n\n\t\t\t**Var olan dosyalar için notlar**\n\t\t\t* Varsayılan olarak, sunucuda şifrelemeyi açmak var olan dosyaları şifrelemez. Yalnızca yeni dosyalar şifrelenir.\n\t\t\t* Var olan tüm dosyaları şifrelemek için şu komutu kullanın: `occ encryption:encrypt-all`.\n\n\t\t\t**Başlamadan önce**\n\t\t\t* **Belgeleri okuyun:** Açmadan önce var olan dosyaları şifreleyin ya da sunucuda şifrelemeyi kapatın. \n\t\t\t\tVeri kaybını önlemek için sonuçları ve uygun prosedürleri anlamak amacıyla belgeleri okumak çok önemlidir."
|
||||
"This app provides the (default) cryptography implementation for Nextcloud's Server-side Encryption (SSE) feature.\n\n\t\t\t**Encryption Details**\n\t\t\t* **Cipher Mode:** AES-256-CTR (default)\n\t\t\t* **Authentication:** HMAC-SHA256\n\n\t\t\t**Important Warnings**\n\t\t\t* **DANGER:** Do not disable this application until all files have been decrypted (`occ encryption:decrypt-all`).\n\t\t\t* **WARNING**: Reverting to non-encrypted file storage after activation requires command-line access. The action is permanent via the Web UI.\"\n\n\t\t\t**Notes for Existing Files**\n\t\t\t* By default, enabling SSE does not encrypt existing files; only new files will be encrypted.\n\t\t\t* To encrypt all existing files, use the command `occ encryption:encrypt-all`.\n\n\t\t\t**Before You Begin**\n\t\t\t* **Read the Documentation:** Before you enable SSE, encrypt existing files, or disable SSE, it is critical to \n\t\t\t\tread the documentation to understand implications and the appropriate procedures to avoid data loss." : "Bu uygulama, Nextcloud sunucu tarafı şifreleme (SSE) özelliği için (varsayılan) şifreleme uygulamasını sağlar.\n\n\t\t\t**Şifreleme ayrıntıları**\n\t\t\t* **Şifreleme kipi:** AES-256-CTR (varsayılan)\n\t\t\t* **Kimlik doğrulaması:** HMAC-SHA256\n\n\t\t\t**Önemli uyarılar**\n\t\t\t* **DİKKAT:** Tüm dosyaların şifresi çözülene kadar bu uygulamayı etkisizleştirmeyin (`occ encryption:decrypt-all`).\n\t\t\t* **UYARI**: Etkinleştirildikten sonra şifrelenmemiş dosya depolama alanına geri dönmek için komut satırına erişim gerekir. İşlem, internet kullanıcı arayüzünden kalıcıdır.\"\n\n\t\t\t**Var olan dosyalar için notlar**\n\t\t\t* Varsayılan olarak, sunucu tarafı şifrelemeyi etkinleştirmek var olan dosyaları şifrelemez. Yalnızca yeni dosyalar şifrelenir.\n\t\t\t* Var olan tüm dosyaları şifrelemek için şu komutu kullanın: `occ encryption:encrypt-all`.\n\n\t\t\t**Başlamadan önce**\n\t\t\t* **Belgeleri okuyun:** Sunucu tarafı şifrelemeyi etkinleştirmeden önce var olan dosyaları şifreleyin ya da sunucu tarafı şifrelemeyi etkisizleştirin. \n\t\t\t\tVeri kaybını önlemek için sonuçları ve uygun prosedürleri anlamak üzere belgeleri okumak çok önemlidir."
|
||||
},"pluralForm" :"nplurals=2; plural=(n > 1);"
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
@@ -21,42 +23,32 @@ use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Default file content encryption module.
|
||||
*
|
||||
* Implements block-based encryption, decryption, key management,
|
||||
* and access control for user data storage.
|
||||
*
|
||||
* @see \OCP\Encryption\IEncryptionModule for detailed method documentation and contract.
|
||||
*/
|
||||
class Encryption implements IEncryptionModule {
|
||||
public const ID = 'OC_DEFAULT_MODULE';
|
||||
public const DISPLAY_NAME = 'Default encryption module';
|
||||
|
||||
/** @var string */
|
||||
private $cipher;
|
||||
|
||||
/** @var string */
|
||||
private $path;
|
||||
|
||||
/** @var string */
|
||||
private $user;
|
||||
|
||||
private string $cipher;
|
||||
private string $path;
|
||||
private ?string $user;
|
||||
private array $owner;
|
||||
|
||||
/** @var string */
|
||||
private $fileKey;
|
||||
|
||||
/** @var string */
|
||||
private $writeCache;
|
||||
|
||||
/** @var array */
|
||||
private $accessList;
|
||||
|
||||
/** @var boolean */
|
||||
private $isWriteOperation;
|
||||
|
||||
private string $fileKey;
|
||||
private string $writeCache;
|
||||
private array $accessList;
|
||||
private bool $isWriteOperation;
|
||||
private bool $useMasterPassword;
|
||||
|
||||
private bool $useLegacyBase64Encoding = false;
|
||||
|
||||
/** @var int Current version of the file */
|
||||
// Current version of the file
|
||||
private int $version = 0;
|
||||
|
||||
/** @var array remember encryption signature version */
|
||||
private static $rememberVersion = [];
|
||||
// Remember encryption signature version
|
||||
private static array $rememberVersion = [];
|
||||
|
||||
public function __construct(
|
||||
private Crypt $crypt,
|
||||
@@ -72,38 +64,15 @@ class Encryption implements IEncryptionModule {
|
||||
$this->useMasterPassword = $this->util->isMasterKeyEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string defining the technical unique id
|
||||
*/
|
||||
public function getId() {
|
||||
public function getId(): string {
|
||||
return self::ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* In comparison to getKey() this function returns a human readable (maybe translated) name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDisplayName() {
|
||||
public function getDisplayName(): string {
|
||||
return self::DISPLAY_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* start receiving chunks from a file. This is the place where you can
|
||||
* perform some initial step before starting encrypting/decrypting the
|
||||
* chunks
|
||||
*
|
||||
* @param string $path to the file
|
||||
* @param string $user who read/write the file
|
||||
* @param string $mode php stream open mode
|
||||
* @param array $header contains the header data read from the file
|
||||
* @param array $accessList who has access to the file contains the key 'users' and 'public'
|
||||
*
|
||||
* @return array $header contain data as key-value pairs which should be
|
||||
* written to the header, in case of a write operation
|
||||
* or if no additional data is needed return a empty array
|
||||
*/
|
||||
public function begin($path, $user, $mode, array $header, array $accessList) {
|
||||
public function begin(string $path, ?string $user, string $mode, array $header, array $accessList): array {
|
||||
$this->path = $this->getPathToRealFile($path);
|
||||
$this->accessList = $accessList;
|
||||
$this->user = $user;
|
||||
@@ -111,7 +80,6 @@ class Encryption implements IEncryptionModule {
|
||||
$this->writeCache = '';
|
||||
$this->useLegacyBase64Encoding = true;
|
||||
|
||||
|
||||
if (isset($header['encoding'])) {
|
||||
$this->useLegacyBase64Encoding = $header['encoding'] !== Crypt::BINARY_ENCODING_FORMAT;
|
||||
}
|
||||
@@ -124,7 +92,7 @@ class Encryption implements IEncryptionModule {
|
||||
}
|
||||
}
|
||||
|
||||
/* If useLegacyFileKey is not specified in header, auto-detect, to be safe */
|
||||
// If useLegacyFileKey is not specified in header, auto-detect, to be safe
|
||||
$useLegacyFileKey = (($header['useLegacyFileKey'] ?? '') == 'false' ? false : null);
|
||||
|
||||
$this->fileKey = $this->keyManager->getFileKey($this->path, $useLegacyFileKey, $this->session->decryptAllModeActivated());
|
||||
@@ -178,19 +146,10 @@ class Encryption implements IEncryptionModule {
|
||||
}
|
||||
|
||||
/**
|
||||
* last chunk received. This is the place where you can perform some final
|
||||
* operation and return some remaining data if something is left in your
|
||||
* buffer.
|
||||
*
|
||||
* @param string $path to the file
|
||||
* @param string $position
|
||||
* @return string remained data which should be written to the file in case
|
||||
* of a write operation
|
||||
* @throws PublicKeyMissingException
|
||||
* @throws \Exception
|
||||
* @throws MultiKeyEncryptException
|
||||
*/
|
||||
public function end($path, $position = '0') {
|
||||
public function end(string $path, string $blockId = '0'): string {
|
||||
$result = '';
|
||||
if ($this->isWriteOperation) {
|
||||
// in case of a part file we remember the new signature versions
|
||||
@@ -201,7 +160,7 @@ class Encryption implements IEncryptionModule {
|
||||
self::$rememberVersion[$this->stripPartFileExtension($path)] = $this->version + 1;
|
||||
}
|
||||
if (!empty($this->writeCache)) {
|
||||
$result = $this->crypt->symmetricEncryptFileContent($this->writeCache, $this->fileKey, $this->version + 1, $position);
|
||||
$result = $this->crypt->symmetricEncryptFileContent($this->writeCache, $this->fileKey, $this->version + 1, $blockId);
|
||||
$this->writeCache = '';
|
||||
}
|
||||
$publicKeys = [];
|
||||
@@ -239,22 +198,12 @@ class Encryption implements IEncryptionModule {
|
||||
return $result ?: '';
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* encrypt data
|
||||
*
|
||||
* @param string $data you want to encrypt
|
||||
* @param int $position
|
||||
* @return string encrypted data
|
||||
*/
|
||||
public function encrypt($data, $position = 0) {
|
||||
public function encrypt(string $data, string $blockId = '0'): string {
|
||||
// If extra data is left over from the last round, make sure it
|
||||
// is integrated into the next block
|
||||
if ($this->writeCache) {
|
||||
// Concat writeCache to start of $data
|
||||
$data = $this->writeCache . $data;
|
||||
|
||||
// Clear the write cache, ready for reuse - it has been
|
||||
// flushed and its old contents processed
|
||||
$this->writeCache = '';
|
||||
@@ -286,7 +235,12 @@ class Encryption implements IEncryptionModule {
|
||||
// Read the chunk from the start of $data
|
||||
$chunk = substr($data, 0, $this->getUnencryptedBlockSize(true));
|
||||
|
||||
$encrypted .= $this->crypt->symmetricEncryptFileContent($chunk, $this->fileKey, $this->version + 1, (string)$position);
|
||||
$encrypted .= $this->crypt->symmetricEncryptFileContent(
|
||||
$chunk,
|
||||
$this->fileKey,
|
||||
$this->version + 1,
|
||||
$blockId
|
||||
);
|
||||
|
||||
// Remove the chunk we just processed from
|
||||
// $data, leaving only unprocessed data in $data
|
||||
@@ -298,15 +252,7 @@ class Encryption implements IEncryptionModule {
|
||||
return $encrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* decrypt data
|
||||
*
|
||||
* @param string $data you want to decrypt
|
||||
* @param int|string $position
|
||||
* @return string decrypted data
|
||||
* @throws DecryptionFailedException
|
||||
*/
|
||||
public function decrypt($data, $position = 0) {
|
||||
public function decrypt(string $data, string $blockId = '0'): string {
|
||||
if (empty($this->fileKey)) {
|
||||
$msg = 'Cannot decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you.';
|
||||
$hint = $this->l->t('Cannot decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you.');
|
||||
@@ -315,18 +261,17 @@ class Encryption implements IEncryptionModule {
|
||||
throw new DecryptionFailedException($msg, $hint);
|
||||
}
|
||||
|
||||
return $this->crypt->symmetricDecryptFileContent($data, $this->fileKey, $this->cipher, $this->version, $position, !$this->useLegacyBase64Encoding);
|
||||
return $this->crypt->symmetricDecryptFileContent(
|
||||
$data,
|
||||
$this->fileKey,
|
||||
$this->cipher,
|
||||
$this->version,
|
||||
$blockId,
|
||||
!$this->useLegacyBase64Encoding
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* update encrypted file, e.g. give additional users access to the file
|
||||
*
|
||||
* @param string $path path to the file which should be updated
|
||||
* @param string $uid ignored
|
||||
* @param array $accessList who has access to the file contains the key 'users' and 'public'
|
||||
* @return bool
|
||||
*/
|
||||
public function update($path, $uid, array $accessList) {
|
||||
public function update(string $path, ?string $uid, array $accessList): bool {
|
||||
if (empty($accessList)) {
|
||||
if (isset(self::$rememberVersion[$path])) {
|
||||
$this->keyManager->setVersion($path, self::$rememberVersion[$path], new View());
|
||||
@@ -370,13 +315,7 @@ class Encryption implements IEncryptionModule {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* should the file be encrypted or not
|
||||
*
|
||||
* @param string $path
|
||||
* @return boolean
|
||||
*/
|
||||
public function shouldEncrypt($path) {
|
||||
public function shouldEncrypt(string $path): bool {
|
||||
if ($this->util->shouldEncryptHomeStorage() === false) {
|
||||
$storage = $this->util->getStorage($path);
|
||||
if ($storage && $storage->instanceOfStorage('\OCP\Files\IHomeStorage')) {
|
||||
@@ -402,25 +341,20 @@ class Encryption implements IEncryptionModule {
|
||||
}
|
||||
|
||||
/**
|
||||
* get size of the unencrypted payload per block.
|
||||
* Nextcloud read/write files with a block size of 8192 byte
|
||||
* Get size of the unencrypted payload per block.
|
||||
* Nextcloud reads/writes files with a block size of 8192 byte.
|
||||
*
|
||||
* Encrypted blocks have a 22-byte IV and 2 bytes of padding, encrypted and
|
||||
* Encrypted blocks have a 22-byte IV and 2 bytes of padding; encrypted and
|
||||
* signed blocks have also a 71-byte signature and 1 more byte of padding,
|
||||
* resulting respectively in:
|
||||
*
|
||||
* 8192 - 22 - 2 = 8168 bytes in each unsigned unencrypted block
|
||||
* 8192 - 22 - 2 - 71 - 1 = 8096 bytes in each signed unencrypted block
|
||||
* 8192 - 22 - 2 = 8168 bytes (in each unsigned unencrypted block
|
||||
* 8192 - 22 - 2 - 71 - 1 = 8096 bytes (in each signed unencrypted block)
|
||||
*
|
||||
* Legacy base64 encoding then reduces the available size by a 3/4 factor:
|
||||
*
|
||||
* 8168 * (3/4) = 6126 bytes in each base64-encoded unsigned unencrypted block
|
||||
* 8096 * (3/4) = 6072 bytes in each base64-encoded signed unencrypted block
|
||||
*
|
||||
* @param bool $signed
|
||||
* @return int
|
||||
* 8168 * (3/4) = 6126 bytes (in each base64-encoded unsigned unencrypted block)
|
||||
* 8096 * (3/4) = 6072 bytes (in each base64-encoded signed unencrypted block)
|
||||
*/
|
||||
public function getUnencryptedBlockSize($signed = false) {
|
||||
public function getUnencryptedBlockSize(bool $signed = false): int {
|
||||
if ($this->useLegacyBase64Encoding) {
|
||||
return $signed ? 6072 : 6126;
|
||||
} else {
|
||||
@@ -428,16 +362,7 @@ class Encryption implements IEncryptionModule {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the encryption module is able to read the file,
|
||||
* e.g. if all encryption keys exists
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $uid user for whom we want to check if they can read the file
|
||||
* @return bool
|
||||
* @throws DecryptionFailedException
|
||||
*/
|
||||
public function isReadable($path, $uid) {
|
||||
public function isReadable(string $path, ?string $uid): bool {
|
||||
$fileKey = $this->keyManager->getFileKey($path, null);
|
||||
if (empty($fileKey)) {
|
||||
$owner = $this->util->getOwner($path);
|
||||
@@ -458,37 +383,36 @@ class Encryption implements IEncryptionModule {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initial encryption of all files
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output write some status information to the terminal during encryption
|
||||
*/
|
||||
public function encryptAll(InputInterface $input, OutputInterface $output) {
|
||||
public function encryptAll(InputInterface $input, OutputInterface $output): void {
|
||||
$this->encryptAll->encryptAll($input, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* prepare module to perform decrypt all operation
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @param string $user
|
||||
* @return bool
|
||||
*/
|
||||
public function prepareDecryptAll(InputInterface $input, OutputInterface $output, $user = '') {
|
||||
public function prepareDecryptAll(InputInterface $input, OutputInterface $output, string $user = ''): bool {
|
||||
return $this->decryptAll->prepare($input, $output, $user);
|
||||
}
|
||||
|
||||
public function isReadyForUser(string $user): bool {
|
||||
if ($this->util->isMasterKeyEnabled()) {
|
||||
return true;
|
||||
}
|
||||
return $this->keyManager->userHasKeys($user);
|
||||
}
|
||||
|
||||
public function needDetailedAccessList(): bool {
|
||||
return !$this->util->isMasterKeyEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @return string
|
||||
* Converts a versions file path to its canonical user file path.
|
||||
*
|
||||
* @param string $path File path (may be a versions path)
|
||||
* @return string Canonical file path
|
||||
*/
|
||||
protected function getPathToRealFile($path) {
|
||||
protected function getPathToRealFile(string $path): string {
|
||||
$realPath = $path;
|
||||
$parts = explode('/', $path);
|
||||
if ($parts[2] === 'files_versions') {
|
||||
// e.g., "/user/files_versions/document.txt.v1234567890" --> "/user/files/document.txt"
|
||||
$realPath = '/' . $parts[1] . '/files/' . implode('/', array_slice($parts, 3));
|
||||
$length = strrpos($realPath, '.');
|
||||
$realPath = substr($realPath, 0, $length);
|
||||
@@ -498,13 +422,13 @@ class Encryption implements IEncryptionModule {
|
||||
}
|
||||
|
||||
/**
|
||||
* remove .part file extension and the ocTransferId from the file to get the
|
||||
* original file name
|
||||
* Removes the .part extension and ocTransferId from a part file path,
|
||||
* returning the original file name.
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
* @param string $path File path, possibly with .part extension and ocTransferId
|
||||
* @return string Original file path without temporary upload markers
|
||||
*/
|
||||
protected function stripPartFileExtension($path) {
|
||||
protected function stripPartFileExtension(string $path): string {
|
||||
if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
|
||||
$pos = strrpos($path, '.', -6);
|
||||
$path = substr($path, 0, $pos);
|
||||
@@ -514,41 +438,15 @@ class Encryption implements IEncryptionModule {
|
||||
}
|
||||
|
||||
/**
|
||||
* get owner of a file
|
||||
* Returns and caches the storage owner for a given file path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
* @param string $path File path
|
||||
* @return string User id of file owner
|
||||
*/
|
||||
protected function getOwner($path) {
|
||||
protected function getOwner(string $path): string {
|
||||
if (!isset($this->owner[$path])) {
|
||||
$this->owner[$path] = $this->util->getOwner($path);
|
||||
}
|
||||
return $this->owner[$path];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module is ready to be used by that specific user.
|
||||
* In case a module is not ready - because e.g. key pairs have not been generated
|
||||
* upon login this method can return false before any operation starts and might
|
||||
* cause issues during operations.
|
||||
*
|
||||
* @param string $user
|
||||
* @return boolean
|
||||
* @since 9.1.0
|
||||
*/
|
||||
public function isReadyForUser($user) {
|
||||
if ($this->util->isMasterKeyEnabled()) {
|
||||
return true;
|
||||
}
|
||||
return $this->keyManager->userHasKeys($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* We only need a detailed access list if the master key is not enabled
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function needDetailedAccessList() {
|
||||
return !$this->util->isMasterKeyEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -95,8 +95,48 @@ class EncryptionTest extends TestCase {
|
||||
->method('decryptAllModeActivated')
|
||||
->willReturn(false);
|
||||
|
||||
// Mocks for methods needed before begin()
|
||||
$this->keyManagerMock->expects($this->any())
|
||||
->method('getFileKey')
|
||||
->willReturn('fileKey');
|
||||
$this->cryptMock->expects($this->any())
|
||||
->method('getCipher')
|
||||
->willReturn('AES-256-CTR');
|
||||
$this->cryptMock->expects($this->any())
|
||||
->method('getLegacyCipher')
|
||||
->willReturn('AES-128-CFB');
|
||||
$this->cryptMock->expects($this->any())
|
||||
->method('useLegacyBase64Encoding')
|
||||
->willReturn(false);
|
||||
$this->cryptMock->expects($this->any())
|
||||
->method('generateFileKey')
|
||||
->willReturn('fileKey');
|
||||
|
||||
// Prepare the post-begin mocks for end() phase
|
||||
$this->keyManagerMock->expects($this->any())
|
||||
->method('getPublicKey')
|
||||
->willReturnCallback([$this, 'getPublicKeyCallback']);
|
||||
$this->keyManagerMock->expects($this->any())
|
||||
->method('addSystemKeys')
|
||||
->willReturnCallback([$this, 'addSystemKeysCallback']);
|
||||
$this->cryptMock->expects($this->any())
|
||||
->method('multiKeyEncrypt')
|
||||
->willReturn([
|
||||
'user1' => 'encForUser1',
|
||||
'user3' => 'encForUser3',
|
||||
]);
|
||||
|
||||
$this->utilMock->expects($this->any())
|
||||
->method('getOwner')
|
||||
->willReturn('user1');
|
||||
|
||||
// Begin the encryption process as user1, with user2 missing their public key
|
||||
$this->instance->begin('/foo/bar', 'user1', 'r', [], ['users' => ['user1', 'user2', 'user3']]);
|
||||
$this->endTest();
|
||||
|
||||
// Set internal state to simulate write and call end()
|
||||
self::invokePrivate($this->instance, 'isWriteOperation', [true]);
|
||||
self::invokePrivate($this->instance, 'writeCache', ['']);
|
||||
$this->instance->end('/foo/bar');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,36 +148,43 @@ class EncryptionTest extends TestCase {
|
||||
->method('decryptAllModeActivated')
|
||||
->willReturn(false);
|
||||
|
||||
$this->expectException(PublicKeyMissingException::class);
|
||||
|
||||
$this->instance->begin('/foo/bar', 'user2', 'r', [], ['users' => ['user1', 'user2', 'user3']]);
|
||||
$this->endTest();
|
||||
}
|
||||
|
||||
/**
|
||||
* common part of testEndUser1 and testEndUser2
|
||||
*
|
||||
* @throws PublicKeyMissingException
|
||||
*/
|
||||
public function endTest() {
|
||||
// prepare internal variables
|
||||
self::invokePrivate($this->instance, 'isWriteOperation', [true]);
|
||||
self::invokePrivate($this->instance, 'writeCache', ['']);
|
||||
// Mocks for methods needed before begin()
|
||||
$this->keyManagerMock->expects($this->any())
|
||||
->method('getFileKey')
|
||||
->willReturn('fileKey');
|
||||
$this->cryptMock->expects($this->any())
|
||||
->method('getCipher')
|
||||
->willReturn('AES-256-CTR');
|
||||
$this->cryptMock->expects($this->any())
|
||||
->method('getLegacyCipher')
|
||||
->willReturn('AES-128-CFB');
|
||||
$this->cryptMock->expects($this->any())
|
||||
->method('useLegacyBase64Encoding')
|
||||
->willReturn(false);
|
||||
$this->cryptMock->expects($this->any())
|
||||
->method('generateFileKey')
|
||||
->willReturn('fileKey');
|
||||
|
||||
// Prepare the post-begin mocks for end() phase
|
||||
$this->keyManagerMock->expects($this->any())
|
||||
->method('getPublicKey')
|
||||
->willReturnCallback([$this, 'getPublicKeyCallback']);
|
||||
$this->keyManagerMock->expects($this->any())
|
||||
->method('addSystemKeys')
|
||||
->willReturnCallback([$this, 'addSystemKeysCallback']);
|
||||
$this->cryptMock->expects($this->any())
|
||||
->method('multiKeyEncrypt')
|
||||
->willReturn([]);
|
||||
$this->cryptMock->expects($this->never())
|
||||
->method('multiKeyEncrypt');
|
||||
|
||||
$this->expectException(PublicKeyMissingException::class);
|
||||
|
||||
$this->instance->begin('/foo/bar', 'user2', 'r', [], ['users' => ['user1', 'user2', 'user3']]);
|
||||
|
||||
// Set internal state to simulate write and call end()
|
||||
self::invokePrivate($this->instance, 'isWriteOperation', [true]);
|
||||
self::invokePrivate($this->instance, 'writeCache', ['']);
|
||||
$this->instance->end('/foo/bar');
|
||||
}
|
||||
|
||||
|
||||
public function getPublicKeyCallback($uid) {
|
||||
if ($uid === 'user2') {
|
||||
throw new PublicKeyMissingException($uid);
|
||||
@@ -235,6 +282,13 @@ class EncryptionTest extends TestCase {
|
||||
->with($path, null, true)
|
||||
->willReturn($fileKey);
|
||||
|
||||
$this->cryptMock->expects($this->any())
|
||||
->method('getCipher')
|
||||
->willReturn('AES-256-CTR');
|
||||
$this->cryptMock->expects($this->any())
|
||||
->method('getLegacyCipher')
|
||||
->willReturn('AES-128-CFB');
|
||||
|
||||
$this->instance->begin($path, 'user', 'r', [], []);
|
||||
|
||||
$this->assertSame($fileKey,
|
||||
@@ -252,10 +306,18 @@ class EncryptionTest extends TestCase {
|
||||
->method('decryptAllModeActivated')
|
||||
->willReturn(false);
|
||||
|
||||
$this->sessionMock->expects($this->once())->method('isReady')->willReturn(false);
|
||||
$this->utilMock->expects($this->once())->method('isMasterKeyEnabled')
|
||||
$this->sessionMock->expects($this->once())
|
||||
->method('isReady')
|
||||
->willReturn(false);
|
||||
$this->utilMock->expects($this->once())
|
||||
->method('isMasterKeyEnabled')
|
||||
->willReturn(true);
|
||||
$this->keyManagerMock->expects($this->once())->method('init')->with('', '');
|
||||
$this->keyManagerMock->expects($this->once())
|
||||
->method('init')
|
||||
->with('', '');
|
||||
$this->cryptMock->expects($this->any())
|
||||
->method('getLegacyCipher')
|
||||
->willReturn('anyWillDo');
|
||||
|
||||
$this->instance->begin('/user/files/welcome.txt', 'user', 'r', [], []);
|
||||
}
|
||||
@@ -282,6 +344,10 @@ class EncryptionTest extends TestCase {
|
||||
$this->keyManagerMock->expects($this->never())->method('getVersion');
|
||||
$this->keyManagerMock->expects($this->never())->method('setVersion');
|
||||
|
||||
$this->utilMock->expects($this->any())
|
||||
->method('getOwner')
|
||||
->willReturn('user1');
|
||||
|
||||
$this->assertSame($expected,
|
||||
$this->instance->update('path', 'user1', ['users' => ['user1']])
|
||||
);
|
||||
@@ -342,6 +408,10 @@ class EncryptionTest extends TestCase {
|
||||
$this->keyManagerMock->expects($this->never())->method('getVersion');
|
||||
$this->keyManagerMock->expects($this->never())->method('setVersion');
|
||||
|
||||
$this->utilMock->expects($this->any())
|
||||
->method('getOwner')
|
||||
->willReturn('user1');
|
||||
|
||||
$this->assertTrue(
|
||||
$this->instance->update('path', 'user1', ['users' => ['user1']])
|
||||
);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
namespace OCA\FederatedFileSharing;
|
||||
|
||||
use OC\ServerNotAvailableException;
|
||||
use OCA\FederatedFileSharing\Events\FederatedShareAddedEvent;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\BackgroundJob\IJobList;
|
||||
@@ -48,7 +47,7 @@ class Notifications {
|
||||
* @param int $shareType (can be a remote user or group share)
|
||||
* @return bool
|
||||
* @throws HintException
|
||||
* @throws ServerNotAvailableException
|
||||
* @throws \OC\ServerNotAvailableException
|
||||
*/
|
||||
public function sendRemoteShare($token, $shareWith, $name, $remoteId, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId, $shareType) {
|
||||
[$user, $remote] = $this->addressHandler->splitUserRemote($shareWith);
|
||||
@@ -107,7 +106,7 @@ class Notifications {
|
||||
* @param string $filename
|
||||
* @return array|false
|
||||
* @throws HintException
|
||||
* @throws ServerNotAvailableException
|
||||
* @throws \OC\ServerNotAvailableException
|
||||
*/
|
||||
public function requestReShare($token, $id, $shareId, $remote, $shareWith, $permission, $filename, $shareType) {
|
||||
$fields = [
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*!
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
@@ -7,18 +7,22 @@
|
||||
*/
|
||||
namespace OCA\Federation;
|
||||
|
||||
use OC\OCS\DiscoveryService;
|
||||
use OCA\DAV\CardDAV\SyncService;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\OCS\IDiscoveryService;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class SyncFederationAddressBooks {
|
||||
private DiscoveryService $ocsDiscoveryService;
|
||||
|
||||
public function __construct(
|
||||
protected DbHandler $dbHandler,
|
||||
private SyncService $syncService,
|
||||
private IDiscoveryService $ocsDiscoveryService,
|
||||
IDiscoveryService $ocsDiscoveryService,
|
||||
private LoggerInterface $logger,
|
||||
) {
|
||||
$this->ocsDiscoveryService = $ocsDiscoveryService;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
|
||||
@@ -182,8 +182,6 @@ OC.L10N.register(
|
||||
"Removing the file extension \"{old}\" may render the file unreadable." : "إزالة الامتداد \"{old}\" من اسم الملف يمكن أن يتسبب في تغيير طريقة تناول و عرض الملف أو يجعله غير قابل للعرض.",
|
||||
"Adding the file extension \"{new}\" may render the file unreadable." : "إضافة الامتداد \"{new}\" لاسم الملف يمكن أن يتسبب في تغيير طريقة تناول و عرض الملف أو أن يجعله غير قابل للعرض.",
|
||||
"Do not show this dialog again." : "لا تُظهِر هذه النافذة مرة أخرى",
|
||||
"Cancel" : "إلغاء",
|
||||
"Rename" : "إعادة التسمية",
|
||||
"Select file or folder to link to" : "اختر ملف أو مجلد للربط معه",
|
||||
"Choose {file}" : "إختر {file}",
|
||||
"Files settings" : "إعدادات الملفات",
|
||||
@@ -238,22 +236,25 @@ OC.L10N.register(
|
||||
"_You are about to permanently delete {count} item_::_You are about to permanently delete {count} items_" : ["أنت على وشك أن تحذف نهائياً {count} عنصراً","أنت على وشك أن تحذف نهائياً {count} عنصراً","أنت على وشك أن تحذف نهائياً {count} عنصراً","أنت على وشك أن تحذف نهائياً {count} عناصر","أنت على وشك أن تحذف نهائياً {count} عناصر","أنت على وشك حذف {count} عنصر بشكل نهائي "],
|
||||
"_You are about to delete {count} item_::_You are about to delete {count} items_" : ["أنت على وشك أن تحذف {count} عنصراً","أنت على وشك أن تحذف {count} عنصراً","أنت على وشك أن تحذف {count} عنصراً","أنت على وشك أن تحذف {count} عناصر","أنت على وشك أن تحذف {count} عناصر","أنت على وشك أن تحذف {count} عنصراً"],
|
||||
"Confirm deletion" : "تأكيد الحذف",
|
||||
"Cancel" : "إلغاء",
|
||||
"Download" : "تنزيل",
|
||||
"Add to favorites" : "إضافة إلى المفضلة",
|
||||
"Remove from favorites" : "إزالة من المفضلة",
|
||||
"Move" : "نقل",
|
||||
"Copy" : "نسخ",
|
||||
"Move or copy" : "نقل أو نسخ",
|
||||
"Destination is not a folder" : "الوجهة ليست مجلد",
|
||||
"This file/folder is already in that directory" : "هذا الملف/المجلد موجود سلفاً في ذلك المجلد",
|
||||
"You cannot move a file/folder onto itself or into a subfolder of itself" : "لا يمكنك نقل ملف/مجلد إلى نفسه أو إلى مجلد فرعي منه",
|
||||
"(copy)" : "(نسخ)",
|
||||
"(copy %n)" : "(نسخ %n)",
|
||||
"A file or folder with that name already exists in this folder" : "ملف أو مجلد بنفس ذاك الاسم موجود سلفاً في هذا المجلد",
|
||||
"The files are locked" : "الملفات مقفلة",
|
||||
"The file does not exist anymore" : "الملف لم يعد موجوداً",
|
||||
"Choose destination" : "تحديد الوجهة",
|
||||
"Copy to {target}" : "نسخ إلى {target}",
|
||||
"Copy" : "نسخ",
|
||||
"Move to {target}" : "نقل إلى {target}",
|
||||
"Move" : "نقل",
|
||||
"Move or copy operation failed" : "عملية النسخ أو النقل فشلت",
|
||||
"Move or copy" : "نقل أو نسخ",
|
||||
"Open folder" : "فتح المجلد",
|
||||
"Open folder {displayName}" : "فتح المجلد {displayName}",
|
||||
"Open in Files" : "فتح في \"الملفات\"",
|
||||
@@ -263,6 +264,7 @@ OC.L10N.register(
|
||||
"The file should now open on your device. If it doesn't, please check that you have the desktop app installed." : "يجب أن يفتح الملف الآن على جهازك. إذا لم يحدث ذلك، فيرجى التأكد من تثبيت تطبيق سطح المكتب.",
|
||||
"Retry and close" : "أعِد المحاولة ثم أغلِق",
|
||||
"Open online" : "إفتَح مُتَّصِلاً بالإنترنت",
|
||||
"Rename" : "إعادة التسمية",
|
||||
"Details" : "التفاصيل",
|
||||
"Unfavorite" : "إبعادٌ من المُفضّلة",
|
||||
"View in folder" : "عرض في المجلد",
|
||||
@@ -281,10 +283,10 @@ OC.L10N.register(
|
||||
"Some files could not be uploaded" : "بعض الملفات لم يمكن رفعها",
|
||||
"Files uploaded successfully" : "تمّ رفع الملفات بنجاح",
|
||||
"No files to process" : "لا توجد ملفات لمعالجتها",
|
||||
"Files copied successfully" : "تمّ نسخ الملفات بنجاح",
|
||||
"Files moved successfully" : "تمّ نقل الملفات بنجاح",
|
||||
"Some files could not be copied" : "بعض الملفات لا يمكن نسخها",
|
||||
"Some files could not be moved" : "تعذر نقل بعض الملفات",
|
||||
"Files copied successfully" : "تمّ نسخ الملفات بنجاح",
|
||||
"Files moved successfully" : "تمّ نقل الملفات بنجاح",
|
||||
"Conflicts resolution skipped" : "تمّ تخطّي حلّ التعارضات",
|
||||
"Upload cancelled" : "تمّ إلغاء الرفع",
|
||||
"Could not rename \"{oldName}\", it does not exist any more" : "تعذر إعادة تسمية \"{oldName}\"، لم يعد موجودًا",
|
||||
@@ -369,8 +371,6 @@ OC.L10N.register(
|
||||
"Edit locally" : "تحرير الملف محلياً",
|
||||
"Moving \"{source}\" to \"{destination}\" …" : "نقل \"{source}\" إلى \"{destination}\" …",
|
||||
"Copying \"{source}\" to \"{destination}\" …" : "نسخ \"{source}\" إلى \"{destination}\" …",
|
||||
"(copy)" : "(نسخ)",
|
||||
"(copy %n)" : "(نسخ %n)",
|
||||
"Move cancelled" : "تمّ إلغاء النقل",
|
||||
"Cancelled move or copy of \"{filename}\"." : "تمّ إلغاء عملية حذف أو نقل الملف \"{filename}\".",
|
||||
"Cancelled move or copy operation" : ".عملية النسخ أو النقل تمّ إلغاؤها",
|
||||
|
||||
@@ -180,8 +180,6 @@
|
||||
"Removing the file extension \"{old}\" may render the file unreadable." : "إزالة الامتداد \"{old}\" من اسم الملف يمكن أن يتسبب في تغيير طريقة تناول و عرض الملف أو يجعله غير قابل للعرض.",
|
||||
"Adding the file extension \"{new}\" may render the file unreadable." : "إضافة الامتداد \"{new}\" لاسم الملف يمكن أن يتسبب في تغيير طريقة تناول و عرض الملف أو أن يجعله غير قابل للعرض.",
|
||||
"Do not show this dialog again." : "لا تُظهِر هذه النافذة مرة أخرى",
|
||||
"Cancel" : "إلغاء",
|
||||
"Rename" : "إعادة التسمية",
|
||||
"Select file or folder to link to" : "اختر ملف أو مجلد للربط معه",
|
||||
"Choose {file}" : "إختر {file}",
|
||||
"Files settings" : "إعدادات الملفات",
|
||||
@@ -236,22 +234,25 @@
|
||||
"_You are about to permanently delete {count} item_::_You are about to permanently delete {count} items_" : ["أنت على وشك أن تحذف نهائياً {count} عنصراً","أنت على وشك أن تحذف نهائياً {count} عنصراً","أنت على وشك أن تحذف نهائياً {count} عنصراً","أنت على وشك أن تحذف نهائياً {count} عناصر","أنت على وشك أن تحذف نهائياً {count} عناصر","أنت على وشك حذف {count} عنصر بشكل نهائي "],
|
||||
"_You are about to delete {count} item_::_You are about to delete {count} items_" : ["أنت على وشك أن تحذف {count} عنصراً","أنت على وشك أن تحذف {count} عنصراً","أنت على وشك أن تحذف {count} عنصراً","أنت على وشك أن تحذف {count} عناصر","أنت على وشك أن تحذف {count} عناصر","أنت على وشك أن تحذف {count} عنصراً"],
|
||||
"Confirm deletion" : "تأكيد الحذف",
|
||||
"Cancel" : "إلغاء",
|
||||
"Download" : "تنزيل",
|
||||
"Add to favorites" : "إضافة إلى المفضلة",
|
||||
"Remove from favorites" : "إزالة من المفضلة",
|
||||
"Move" : "نقل",
|
||||
"Copy" : "نسخ",
|
||||
"Move or copy" : "نقل أو نسخ",
|
||||
"Destination is not a folder" : "الوجهة ليست مجلد",
|
||||
"This file/folder is already in that directory" : "هذا الملف/المجلد موجود سلفاً في ذلك المجلد",
|
||||
"You cannot move a file/folder onto itself or into a subfolder of itself" : "لا يمكنك نقل ملف/مجلد إلى نفسه أو إلى مجلد فرعي منه",
|
||||
"(copy)" : "(نسخ)",
|
||||
"(copy %n)" : "(نسخ %n)",
|
||||
"A file or folder with that name already exists in this folder" : "ملف أو مجلد بنفس ذاك الاسم موجود سلفاً في هذا المجلد",
|
||||
"The files are locked" : "الملفات مقفلة",
|
||||
"The file does not exist anymore" : "الملف لم يعد موجوداً",
|
||||
"Choose destination" : "تحديد الوجهة",
|
||||
"Copy to {target}" : "نسخ إلى {target}",
|
||||
"Copy" : "نسخ",
|
||||
"Move to {target}" : "نقل إلى {target}",
|
||||
"Move" : "نقل",
|
||||
"Move or copy operation failed" : "عملية النسخ أو النقل فشلت",
|
||||
"Move or copy" : "نقل أو نسخ",
|
||||
"Open folder" : "فتح المجلد",
|
||||
"Open folder {displayName}" : "فتح المجلد {displayName}",
|
||||
"Open in Files" : "فتح في \"الملفات\"",
|
||||
@@ -261,6 +262,7 @@
|
||||
"The file should now open on your device. If it doesn't, please check that you have the desktop app installed." : "يجب أن يفتح الملف الآن على جهازك. إذا لم يحدث ذلك، فيرجى التأكد من تثبيت تطبيق سطح المكتب.",
|
||||
"Retry and close" : "أعِد المحاولة ثم أغلِق",
|
||||
"Open online" : "إفتَح مُتَّصِلاً بالإنترنت",
|
||||
"Rename" : "إعادة التسمية",
|
||||
"Details" : "التفاصيل",
|
||||
"Unfavorite" : "إبعادٌ من المُفضّلة",
|
||||
"View in folder" : "عرض في المجلد",
|
||||
@@ -279,10 +281,10 @@
|
||||
"Some files could not be uploaded" : "بعض الملفات لم يمكن رفعها",
|
||||
"Files uploaded successfully" : "تمّ رفع الملفات بنجاح",
|
||||
"No files to process" : "لا توجد ملفات لمعالجتها",
|
||||
"Files copied successfully" : "تمّ نسخ الملفات بنجاح",
|
||||
"Files moved successfully" : "تمّ نقل الملفات بنجاح",
|
||||
"Some files could not be copied" : "بعض الملفات لا يمكن نسخها",
|
||||
"Some files could not be moved" : "تعذر نقل بعض الملفات",
|
||||
"Files copied successfully" : "تمّ نسخ الملفات بنجاح",
|
||||
"Files moved successfully" : "تمّ نقل الملفات بنجاح",
|
||||
"Conflicts resolution skipped" : "تمّ تخطّي حلّ التعارضات",
|
||||
"Upload cancelled" : "تمّ إلغاء الرفع",
|
||||
"Could not rename \"{oldName}\", it does not exist any more" : "تعذر إعادة تسمية \"{oldName}\"، لم يعد موجودًا",
|
||||
@@ -367,8 +369,6 @@
|
||||
"Edit locally" : "تحرير الملف محلياً",
|
||||
"Moving \"{source}\" to \"{destination}\" …" : "نقل \"{source}\" إلى \"{destination}\" …",
|
||||
"Copying \"{source}\" to \"{destination}\" …" : "نسخ \"{source}\" إلى \"{destination}\" …",
|
||||
"(copy)" : "(نسخ)",
|
||||
"(copy %n)" : "(نسخ %n)",
|
||||
"Move cancelled" : "تمّ إلغاء النقل",
|
||||
"Cancelled move or copy of \"{filename}\"." : "تمّ إلغاء عملية حذف أو نقل الملف \"{filename}\".",
|
||||
"Cancelled move or copy operation" : ".عملية النسخ أو النقل تمّ إلغاؤها",
|
||||
|
||||
@@ -134,8 +134,6 @@ OC.L10N.register(
|
||||
"Choose file or folder to transfer" : "Escoyer el ficheru o carpeta a tresferir",
|
||||
"Change" : "Camudar",
|
||||
"New owner" : "Propietariu nuevu",
|
||||
"Cancel" : "Encaboxar",
|
||||
"Rename" : "Renomar",
|
||||
"Select file or folder to link to" : "Seleicionar un ficheru o una carpeta a la qu'enllaciar",
|
||||
"Choose {file}" : "Escoyer «{file}»",
|
||||
"Files settings" : "Configuración de Ficheros",
|
||||
@@ -174,27 +172,31 @@ OC.L10N.register(
|
||||
"Delete folder" : "Desaniciar la carpeta",
|
||||
"Delete folders" : "Desaniciar les carpetes",
|
||||
"Confirm deletion" : "Confirmar el desaniciu",
|
||||
"Cancel" : "Encaboxar",
|
||||
"Download" : "Baxar",
|
||||
"Add to favorites" : "Meter en Favoritos",
|
||||
"Remove from favorites" : "Quitar de Favoritos",
|
||||
"Move" : "Mover",
|
||||
"Copy" : "Copiar",
|
||||
"Move or copy" : "Mover o copiar",
|
||||
"Destination is not a folder" : "El destín nun ye una carpeta",
|
||||
"This file/folder is already in that directory" : "Esti ficheru o esta carpeta yá ta nel direutoriu",
|
||||
"You cannot move a file/folder onto itself or into a subfolder of itself" : "Nun pues mover un ficheru/carpeta a sigo mesma o la mesma socarpeta de la mesma carpeta",
|
||||
"(copy)" : "(copia)",
|
||||
"(copy %n)" : "(copia %n)",
|
||||
"A file or folder with that name already exists in this folder" : "Nesta carpeta, yá estie un ficheru o una carpeta con esi nome",
|
||||
"The files are locked" : "Los ficheros tán bloquiaos",
|
||||
"The file does not exist anymore" : "El ficheru yá nun esiste",
|
||||
"Choose destination" : "Escoyer el destín",
|
||||
"Copy to {target}" : "Copiar a {target}",
|
||||
"Copy" : "Copiar",
|
||||
"Move to {target}" : "Mover a {target}",
|
||||
"Move" : "Mover",
|
||||
"Move or copy operation failed" : "La operación de mover o copiar falló",
|
||||
"Move or copy" : "Mover o copiar",
|
||||
"Open folder" : "Abrir la carpeta",
|
||||
"Open folder {displayName}" : "Abrir la carpeta «{displayName}»",
|
||||
"Open in Files" : "Abrir en Ficheros",
|
||||
"Open locally" : "Abrir llocalmente",
|
||||
"Failed to redirect to client" : "Nun se pue redirixir al veceru",
|
||||
"Rename" : "Renomar",
|
||||
"Details" : "Detalles",
|
||||
"View in folder" : "Ver na carpeta",
|
||||
"Type" : "Tipu",
|
||||
@@ -211,10 +213,10 @@ OC.L10N.register(
|
||||
"Some files could not be uploaded" : "Nun se pudieron xubir dalgunos ficheros",
|
||||
"Files uploaded successfully" : "Los ficheros xubiéronse correutamente",
|
||||
"No files to process" : "Nun hai nengún ficheru pa procesar",
|
||||
"Files copied successfully" : "Los ficheros copiáronse correutamente",
|
||||
"Files moved successfully" : "Los ficheros copiáronse correutamente",
|
||||
"Some files could not be copied" : "Nun se pudieron copiar dalgunos ficheros",
|
||||
"Some files could not be moved" : "Nun se pudieron copiar dalgunos ficheros",
|
||||
"Files copied successfully" : "Los ficheros copiáronse correutamente",
|
||||
"Files moved successfully" : "Los ficheros copiáronse correutamente",
|
||||
"Conflicts resolution skipped" : "Saltóse la resolución de conflictos",
|
||||
"Upload cancelled" : "Encaboxóse la busca",
|
||||
"Could not rename \"{oldName}\", it does not exist any more" : "Nun se pue renomar «{oldName}». Yá nun esiste",
|
||||
@@ -260,8 +262,6 @@ OC.L10N.register(
|
||||
"Tags" : "Etiquetes",
|
||||
"Deletion cancelled" : "Anulóse'l desaniciu",
|
||||
"Edit locally" : "Editar llocalmente",
|
||||
"(copy)" : "(copia)",
|
||||
"(copy %n)" : "(copia %n)",
|
||||
"Move cancelled" : "Anulóse la operación de mover",
|
||||
"Cancelled move or copy operation" : "Anulóse la operación de mover o copiar",
|
||||
"Open details" : "Abrir los detalles",
|
||||
|
||||
@@ -132,8 +132,6 @@
|
||||
"Choose file or folder to transfer" : "Escoyer el ficheru o carpeta a tresferir",
|
||||
"Change" : "Camudar",
|
||||
"New owner" : "Propietariu nuevu",
|
||||
"Cancel" : "Encaboxar",
|
||||
"Rename" : "Renomar",
|
||||
"Select file or folder to link to" : "Seleicionar un ficheru o una carpeta a la qu'enllaciar",
|
||||
"Choose {file}" : "Escoyer «{file}»",
|
||||
"Files settings" : "Configuración de Ficheros",
|
||||
@@ -172,27 +170,31 @@
|
||||
"Delete folder" : "Desaniciar la carpeta",
|
||||
"Delete folders" : "Desaniciar les carpetes",
|
||||
"Confirm deletion" : "Confirmar el desaniciu",
|
||||
"Cancel" : "Encaboxar",
|
||||
"Download" : "Baxar",
|
||||
"Add to favorites" : "Meter en Favoritos",
|
||||
"Remove from favorites" : "Quitar de Favoritos",
|
||||
"Move" : "Mover",
|
||||
"Copy" : "Copiar",
|
||||
"Move or copy" : "Mover o copiar",
|
||||
"Destination is not a folder" : "El destín nun ye una carpeta",
|
||||
"This file/folder is already in that directory" : "Esti ficheru o esta carpeta yá ta nel direutoriu",
|
||||
"You cannot move a file/folder onto itself or into a subfolder of itself" : "Nun pues mover un ficheru/carpeta a sigo mesma o la mesma socarpeta de la mesma carpeta",
|
||||
"(copy)" : "(copia)",
|
||||
"(copy %n)" : "(copia %n)",
|
||||
"A file or folder with that name already exists in this folder" : "Nesta carpeta, yá estie un ficheru o una carpeta con esi nome",
|
||||
"The files are locked" : "Los ficheros tán bloquiaos",
|
||||
"The file does not exist anymore" : "El ficheru yá nun esiste",
|
||||
"Choose destination" : "Escoyer el destín",
|
||||
"Copy to {target}" : "Copiar a {target}",
|
||||
"Copy" : "Copiar",
|
||||
"Move to {target}" : "Mover a {target}",
|
||||
"Move" : "Mover",
|
||||
"Move or copy operation failed" : "La operación de mover o copiar falló",
|
||||
"Move or copy" : "Mover o copiar",
|
||||
"Open folder" : "Abrir la carpeta",
|
||||
"Open folder {displayName}" : "Abrir la carpeta «{displayName}»",
|
||||
"Open in Files" : "Abrir en Ficheros",
|
||||
"Open locally" : "Abrir llocalmente",
|
||||
"Failed to redirect to client" : "Nun se pue redirixir al veceru",
|
||||
"Rename" : "Renomar",
|
||||
"Details" : "Detalles",
|
||||
"View in folder" : "Ver na carpeta",
|
||||
"Type" : "Tipu",
|
||||
@@ -209,10 +211,10 @@
|
||||
"Some files could not be uploaded" : "Nun se pudieron xubir dalgunos ficheros",
|
||||
"Files uploaded successfully" : "Los ficheros xubiéronse correutamente",
|
||||
"No files to process" : "Nun hai nengún ficheru pa procesar",
|
||||
"Files copied successfully" : "Los ficheros copiáronse correutamente",
|
||||
"Files moved successfully" : "Los ficheros copiáronse correutamente",
|
||||
"Some files could not be copied" : "Nun se pudieron copiar dalgunos ficheros",
|
||||
"Some files could not be moved" : "Nun se pudieron copiar dalgunos ficheros",
|
||||
"Files copied successfully" : "Los ficheros copiáronse correutamente",
|
||||
"Files moved successfully" : "Los ficheros copiáronse correutamente",
|
||||
"Conflicts resolution skipped" : "Saltóse la resolución de conflictos",
|
||||
"Upload cancelled" : "Encaboxóse la busca",
|
||||
"Could not rename \"{oldName}\", it does not exist any more" : "Nun se pue renomar «{oldName}». Yá nun esiste",
|
||||
@@ -258,8 +260,6 @@
|
||||
"Tags" : "Etiquetes",
|
||||
"Deletion cancelled" : "Anulóse'l desaniciu",
|
||||
"Edit locally" : "Editar llocalmente",
|
||||
"(copy)" : "(copia)",
|
||||
"(copy %n)" : "(copia %n)",
|
||||
"Move cancelled" : "Anulóse la operación de mover",
|
||||
"Cancelled move or copy operation" : "Anulóse la operación de mover o copiar",
|
||||
"Open details" : "Abrir los detalles",
|
||||
|
||||
+11
-11
@@ -226,8 +226,6 @@ OC.L10N.register(
|
||||
"Removing the file extension \"{old}\" may render the file unreadable." : "Выдаленне пашырэння файла \"{old}\" можа зрабіць файл нечытэльным.",
|
||||
"Adding the file extension \"{new}\" may render the file unreadable." : "Даданне пашырэння файла \"{new}\" можа зрабіць файл нечытэльным.",
|
||||
"Do not show this dialog again." : "Больш не паказваць гэта дыялогавае акно.",
|
||||
"Cancel" : "Скасаваць",
|
||||
"Rename" : "Перайменаваць",
|
||||
"Select file or folder to link to" : "Выберыце файл або каталог, на які трэба зрабіць спасылку",
|
||||
"Choose {file}" : "Выбраць {file}",
|
||||
"Files settings" : "Налады Файлаў",
|
||||
@@ -288,27 +286,30 @@ OC.L10N.register(
|
||||
"_You are about to permanently delete {count} item_::_You are about to permanently delete {count} items_" : ["Вы збіраецеся назаўжды выдаліць {count} элемент","Вы збіраецеся назаўжды выдаліць {count} элементы","Вы збіраецеся назаўжды выдаліць {count} элементаў","Вы збіраецеся назаўжды выдаліць {count} элементаў"],
|
||||
"_You are about to delete {count} item_::_You are about to delete {count} items_" : ["Вы збіраецеся выдаліць {count} элемент","Вы збіраецеся выдаліць {count} элементы","Вы збіраецеся выдаліць {count} элементаў","Вы збіраецеся выдаліць {count} элементаў"],
|
||||
"Confirm deletion" : "Пацвердзіць выдаленне",
|
||||
"Cancel" : "Скасаваць",
|
||||
"Download" : "Спампаваць",
|
||||
"The requested file is not available." : "Запытаны файл недаступны.",
|
||||
"The requested files are not available." : "Запытаныя файлы недаступны.",
|
||||
"Add to favorites" : "У абранае",
|
||||
"Remove from favorites" : "Выдаліць з абранага",
|
||||
"Add or remove favorite" : "Дадаць або выдаліць з абранага",
|
||||
"Move" : "Перамясціць",
|
||||
"Copy" : "Капіяваць",
|
||||
"Move or copy" : "Перамясціць або капіяваць",
|
||||
"Moving \"{source}\" to \"{destination}\" …" : "Перамяшчэнне \"{source}\" у \"{destination}\" …",
|
||||
"Copying \"{source}\" to \"{destination}\" …" : "Капіяванне \"{source}\" у \"{destination}\" …",
|
||||
"Destination is not a folder" : "Месца прызначэння не з'яўляецца папкай",
|
||||
"This file/folder is already in that directory" : "Гэты файл/папка ўжо знаходзіцца ў гэтым каталогу",
|
||||
"You cannot move a file/folder onto itself or into a subfolder of itself" : "Нельга перамясціць файл/папку ў сябе або ў падпапку самой сябе",
|
||||
"(copy)" : "(копія)",
|
||||
"(copy %n)" : "(копія %n)",
|
||||
"A file or folder with that name already exists in this folder" : "Файл або папка з такой назвай ужо існуе ў гэтай папцы",
|
||||
"The files are locked" : "Файлы заблакіраваны",
|
||||
"The file does not exist anymore" : "Файл больш не існуе",
|
||||
"Moving \"{source}\" to \"{destination}\" …" : "Перамяшчэнне \"{source}\" у \"{destination}\" …",
|
||||
"Copying \"{source}\" to \"{destination}\" …" : "Капіяванне \"{source}\" у \"{destination}\" …",
|
||||
"Choose destination" : "Выберыце прызначэнне",
|
||||
"Copy to {target}" : "Капіяваць у {target}",
|
||||
"Copy" : "Капіяваць",
|
||||
"Move to {target}" : "Перамясціць у {target}",
|
||||
"Move" : "Перамясціць",
|
||||
"Move or copy operation failed" : "Не ўдалося перамясціць або скапіяваць",
|
||||
"Move or copy" : "Перамясціць або капіяваць",
|
||||
"Open folder {displayName}" : "Адкрыць папку {displayName}",
|
||||
"Open in Files" : "Адкрыць у Файлах",
|
||||
"Open locally" : "Адкрыць лакальна",
|
||||
@@ -317,6 +318,7 @@ OC.L10N.register(
|
||||
"The file should now open on your device. If it doesn't, please check that you have the desktop app installed." : "Файл павінен адкрыцца на вашай прыладзе. Калі не, праверце, ці ўсталявана ў вас праграма для ПК.",
|
||||
"Retry and close" : "Паўтарыць спробу і закрыць",
|
||||
"Open online" : "Адкрыць анлайн",
|
||||
"Rename" : "Перайменаваць",
|
||||
"Details" : "Падрабязнасці",
|
||||
"View in folder" : "Праглядзець у папцы",
|
||||
"Type" : "Тып",
|
||||
@@ -335,10 +337,10 @@ OC.L10N.register(
|
||||
"Some files could not be uploaded" : "Некаторыя файлы не ўдалося запампаваць",
|
||||
"Files uploaded successfully" : "Файлы паспяхова запампаваныя",
|
||||
"No files to process" : "Няма файлаў для апрацоўкі",
|
||||
"Files copied successfully" : "Файлы паспяхова скапіяваны",
|
||||
"Files moved successfully" : "Файлы паспяхова перамешчаны",
|
||||
"Some files could not be copied" : "Некаторыя файлы не ўдалося скапіяваць",
|
||||
"Some files could not be moved" : "Некаторыя файлы не ўдалося перамясціць",
|
||||
"Files copied successfully" : "Файлы паспяхова скапіяваны",
|
||||
"Files moved successfully" : "Файлы паспяхова перамешчаны",
|
||||
"Conflicts resolution skipped" : "Рашэнне канфліктаў прапушчана",
|
||||
"Upload cancelled" : "Запампоўванне скасавана",
|
||||
"Could not rename \"{oldName}\", it does not exist any more" : "Не атрымалася перайменаваць \"{oldName}\", ён больш не існуе",
|
||||
@@ -428,8 +430,6 @@ OC.L10N.register(
|
||||
"Edit locally" : "Рэдагаваць лакальна",
|
||||
"Moving \"{source}\" to \"{destination}\" …" : "Перамяшчэнне \"{source}\" у \"{destination}\" …",
|
||||
"Copying \"{source}\" to \"{destination}\" …" : "Капіяванне \"{source}\" у \"{destination}\" …",
|
||||
"(copy)" : "(копія)",
|
||||
"(copy %n)" : "(копія %n)",
|
||||
"Move cancelled" : "Перамяшчэнне скасавана",
|
||||
"Cancelled move or copy of \"{filename}\"." : "Аперацыя перамяшчэння або капіявання \"{filename}\" скасавана.",
|
||||
"Cancelled move or copy operation" : "Аперацыя перамяшчэння або капіявання скасавана",
|
||||
|
||||
+11
-11
@@ -224,8 +224,6 @@
|
||||
"Removing the file extension \"{old}\" may render the file unreadable." : "Выдаленне пашырэння файла \"{old}\" можа зрабіць файл нечытэльным.",
|
||||
"Adding the file extension \"{new}\" may render the file unreadable." : "Даданне пашырэння файла \"{new}\" можа зрабіць файл нечытэльным.",
|
||||
"Do not show this dialog again." : "Больш не паказваць гэта дыялогавае акно.",
|
||||
"Cancel" : "Скасаваць",
|
||||
"Rename" : "Перайменаваць",
|
||||
"Select file or folder to link to" : "Выберыце файл або каталог, на які трэба зрабіць спасылку",
|
||||
"Choose {file}" : "Выбраць {file}",
|
||||
"Files settings" : "Налады Файлаў",
|
||||
@@ -286,27 +284,30 @@
|
||||
"_You are about to permanently delete {count} item_::_You are about to permanently delete {count} items_" : ["Вы збіраецеся назаўжды выдаліць {count} элемент","Вы збіраецеся назаўжды выдаліць {count} элементы","Вы збіраецеся назаўжды выдаліць {count} элементаў","Вы збіраецеся назаўжды выдаліць {count} элементаў"],
|
||||
"_You are about to delete {count} item_::_You are about to delete {count} items_" : ["Вы збіраецеся выдаліць {count} элемент","Вы збіраецеся выдаліць {count} элементы","Вы збіраецеся выдаліць {count} элементаў","Вы збіраецеся выдаліць {count} элементаў"],
|
||||
"Confirm deletion" : "Пацвердзіць выдаленне",
|
||||
"Cancel" : "Скасаваць",
|
||||
"Download" : "Спампаваць",
|
||||
"The requested file is not available." : "Запытаны файл недаступны.",
|
||||
"The requested files are not available." : "Запытаныя файлы недаступны.",
|
||||
"Add to favorites" : "У абранае",
|
||||
"Remove from favorites" : "Выдаліць з абранага",
|
||||
"Add or remove favorite" : "Дадаць або выдаліць з абранага",
|
||||
"Move" : "Перамясціць",
|
||||
"Copy" : "Капіяваць",
|
||||
"Move or copy" : "Перамясціць або капіяваць",
|
||||
"Moving \"{source}\" to \"{destination}\" …" : "Перамяшчэнне \"{source}\" у \"{destination}\" …",
|
||||
"Copying \"{source}\" to \"{destination}\" …" : "Капіяванне \"{source}\" у \"{destination}\" …",
|
||||
"Destination is not a folder" : "Месца прызначэння не з'яўляецца папкай",
|
||||
"This file/folder is already in that directory" : "Гэты файл/папка ўжо знаходзіцца ў гэтым каталогу",
|
||||
"You cannot move a file/folder onto itself or into a subfolder of itself" : "Нельга перамясціць файл/папку ў сябе або ў падпапку самой сябе",
|
||||
"(copy)" : "(копія)",
|
||||
"(copy %n)" : "(копія %n)",
|
||||
"A file or folder with that name already exists in this folder" : "Файл або папка з такой назвай ужо існуе ў гэтай папцы",
|
||||
"The files are locked" : "Файлы заблакіраваны",
|
||||
"The file does not exist anymore" : "Файл больш не існуе",
|
||||
"Moving \"{source}\" to \"{destination}\" …" : "Перамяшчэнне \"{source}\" у \"{destination}\" …",
|
||||
"Copying \"{source}\" to \"{destination}\" …" : "Капіяванне \"{source}\" у \"{destination}\" …",
|
||||
"Choose destination" : "Выберыце прызначэнне",
|
||||
"Copy to {target}" : "Капіяваць у {target}",
|
||||
"Copy" : "Капіяваць",
|
||||
"Move to {target}" : "Перамясціць у {target}",
|
||||
"Move" : "Перамясціць",
|
||||
"Move or copy operation failed" : "Не ўдалося перамясціць або скапіяваць",
|
||||
"Move or copy" : "Перамясціць або капіяваць",
|
||||
"Open folder {displayName}" : "Адкрыць папку {displayName}",
|
||||
"Open in Files" : "Адкрыць у Файлах",
|
||||
"Open locally" : "Адкрыць лакальна",
|
||||
@@ -315,6 +316,7 @@
|
||||
"The file should now open on your device. If it doesn't, please check that you have the desktop app installed." : "Файл павінен адкрыцца на вашай прыладзе. Калі не, праверце, ці ўсталявана ў вас праграма для ПК.",
|
||||
"Retry and close" : "Паўтарыць спробу і закрыць",
|
||||
"Open online" : "Адкрыць анлайн",
|
||||
"Rename" : "Перайменаваць",
|
||||
"Details" : "Падрабязнасці",
|
||||
"View in folder" : "Праглядзець у папцы",
|
||||
"Type" : "Тып",
|
||||
@@ -333,10 +335,10 @@
|
||||
"Some files could not be uploaded" : "Некаторыя файлы не ўдалося запампаваць",
|
||||
"Files uploaded successfully" : "Файлы паспяхова запампаваныя",
|
||||
"No files to process" : "Няма файлаў для апрацоўкі",
|
||||
"Files copied successfully" : "Файлы паспяхова скапіяваны",
|
||||
"Files moved successfully" : "Файлы паспяхова перамешчаны",
|
||||
"Some files could not be copied" : "Некаторыя файлы не ўдалося скапіяваць",
|
||||
"Some files could not be moved" : "Некаторыя файлы не ўдалося перамясціць",
|
||||
"Files copied successfully" : "Файлы паспяхова скапіяваны",
|
||||
"Files moved successfully" : "Файлы паспяхова перамешчаны",
|
||||
"Conflicts resolution skipped" : "Рашэнне канфліктаў прапушчана",
|
||||
"Upload cancelled" : "Запампоўванне скасавана",
|
||||
"Could not rename \"{oldName}\", it does not exist any more" : "Не атрымалася перайменаваць \"{oldName}\", ён больш не існуе",
|
||||
@@ -426,8 +428,6 @@
|
||||
"Edit locally" : "Рэдагаваць лакальна",
|
||||
"Moving \"{source}\" to \"{destination}\" …" : "Перамяшчэнне \"{source}\" у \"{destination}\" …",
|
||||
"Copying \"{source}\" to \"{destination}\" …" : "Капіяванне \"{source}\" у \"{destination}\" …",
|
||||
"(copy)" : "(копія)",
|
||||
"(copy %n)" : "(копія %n)",
|
||||
"Move cancelled" : "Перамяшчэнне скасавана",
|
||||
"Cancelled move or copy of \"{filename}\"." : "Аперацыя перамяшчэння або капіявання \"{filename}\" скасавана.",
|
||||
"Cancelled move or copy operation" : "Аперацыя перамяшчэння або капіявання скасавана",
|
||||
|
||||
+11
-11
@@ -229,8 +229,6 @@ OC.L10N.register(
|
||||
"Removing the file extension \"{old}\" may render the file unreadable." : "Премахването на файловото разширение \"{old}\" може да направи файла нечетлив.",
|
||||
"Adding the file extension \"{new}\" may render the file unreadable." : "Добавянето на файловото разширение \"{new}\" може да направи файла нечетлив.",
|
||||
"Do not show this dialog again." : "Не показвай този диалогов прозорец отново.",
|
||||
"Cancel" : "Отказ",
|
||||
"Rename" : "Преименувай",
|
||||
"Select file or folder to link to" : "Избор на файл или папка, към които да поставите връзка",
|
||||
"Choose {file}" : "Изберете {file}",
|
||||
"Files settings" : "Настройки на файловете",
|
||||
@@ -294,27 +292,30 @@ OC.L10N.register(
|
||||
"_You are about to permanently delete {count} item_::_You are about to permanently delete {count} items_" : ["На път сте да изтриете елемента {count} за постоянно","На път сте да изтриете елементите {count} за постоянно"],
|
||||
"_You are about to delete {count} item_::_You are about to delete {count} items_" : ["На път сте да изтриете {count} елемент","На път сте да изтриете {count} елементи"],
|
||||
"Confirm deletion" : "Потвърдете изтриването",
|
||||
"Cancel" : "Отказ",
|
||||
"Download" : "Изтегли",
|
||||
"The requested file is not available." : "Заявеният файл не е наличен.",
|
||||
"The requested files are not available." : "Заявените файлове не са налични.",
|
||||
"Add to favorites" : "Добави към любимите",
|
||||
"Remove from favorites" : "Премахни от любимите",
|
||||
"Add or remove favorite" : "Добавете или премахнете любими",
|
||||
"Move" : "Преместване",
|
||||
"Copy" : "Копирай",
|
||||
"Move or copy" : "Премести или копирай",
|
||||
"Moving \"{source}\" to \"{destination}\" …" : "Преместване на \"{source}“ към “{destination}\"…",
|
||||
"Copying \"{source}\" to \"{destination}\" …" : "Копиране на \"{source}“ в “{destination}\"…",
|
||||
"Destination is not a folder" : "Предназначчението не е папка",
|
||||
"This file/folder is already in that directory" : "Този файл/папка вече е в тази директория",
|
||||
"You cannot move a file/folder onto itself or into a subfolder of itself" : "Не можете да преместите файл/папка в папка или в подпапка",
|
||||
"(copy)" : "(копие)",
|
||||
"(copy %n)" : "(копирай %n)",
|
||||
"A file or folder with that name already exists in this folder" : "В тази папка вече съществува файл или папка с това име",
|
||||
"The files are locked" : "Файловете са заключени",
|
||||
"The file does not exist anymore" : "Файлът вече не съществува",
|
||||
"Moving \"{source}\" to \"{destination}\" …" : "Преместване на \"{source}“ към “{destination}\"…",
|
||||
"Copying \"{source}\" to \"{destination}\" …" : "Копиране на \"{source}“ в “{destination}\"…",
|
||||
"Choose destination" : "Изберете дестинация",
|
||||
"Copy to {target}" : "Копиране в {target}",
|
||||
"Copy" : "Копирай",
|
||||
"Move to {target}" : "Преместване на {target}",
|
||||
"Move" : "Преместване",
|
||||
"Move or copy operation failed" : "Операцията за преместване или копиране не бе успешна",
|
||||
"Move or copy" : "Премести или копирай",
|
||||
"Open folder" : "Отвори папката",
|
||||
"Open folder {displayName}" : "Отворете папка {displayName}",
|
||||
"Open in Files" : "Отворете във Файлове",
|
||||
@@ -324,6 +325,7 @@ OC.L10N.register(
|
||||
"The file should now open on your device. If it doesn't, please check that you have the desktop app installed." : "Файлът вече би трябвало да се отвори на вашето устройство. Ако не се отвори, моля, проверете дали имате инсталирано настолното приложение.",
|
||||
"Retry and close" : "Опитайте отново и затворете",
|
||||
"Open online" : "Отворете онлайн",
|
||||
"Rename" : "Преименувай",
|
||||
"Details" : "Подробности",
|
||||
"View in folder" : "Преглед в папката",
|
||||
"Type" : "Тип",
|
||||
@@ -342,10 +344,10 @@ OC.L10N.register(
|
||||
"Some files could not be uploaded" : "Някои файлове не можаха да бъдат качени",
|
||||
"Files uploaded successfully" : "Файловете са качени успешно",
|
||||
"No files to process" : "Няма файлове за обработка",
|
||||
"Files copied successfully" : "Файловете са успешно копирани",
|
||||
"Files moved successfully" : "Файловете са преместени успешно",
|
||||
"Some files could not be copied" : "Някои файлове не можаха да бъдат копирани",
|
||||
"Some files could not be moved" : "Някои файлове не могат да бъдат преместени",
|
||||
"Files copied successfully" : "Файловете са успешно копирани",
|
||||
"Files moved successfully" : "Файловете са преместени успешно",
|
||||
"Conflicts resolution skipped" : "Разрешаването на конфликти е пропуснато",
|
||||
"Upload cancelled" : "Качването е отменено",
|
||||
"Could not rename \"{oldName}\", it does not exist any more" : "Файлът \"{oldName}\" не може да бъде преименуван защото не съществува",
|
||||
@@ -435,8 +437,6 @@ OC.L10N.register(
|
||||
"Edit locally" : "Локално редактиране",
|
||||
"Moving \"{source}\" to \"{destination}\" …" : "Преместване на \"{source}\" към \"{destination}\" …",
|
||||
"Copying \"{source}\" to \"{destination}\" …" : "Копиране на \"{source}\" в \"{destination}\" …",
|
||||
"(copy)" : "(копие)",
|
||||
"(copy %n)" : "(копирай %n)",
|
||||
"Move cancelled" : "Преместването е отменено",
|
||||
"Cancelled move or copy of \"{filename}\"." : "Преместването или копирането на \"{filename}\" е отменено.",
|
||||
"Cancelled move or copy operation" : "Операцията за преместване или копиране е отменена",
|
||||
|
||||
+11
-11
@@ -227,8 +227,6 @@
|
||||
"Removing the file extension \"{old}\" may render the file unreadable." : "Премахването на файловото разширение \"{old}\" може да направи файла нечетлив.",
|
||||
"Adding the file extension \"{new}\" may render the file unreadable." : "Добавянето на файловото разширение \"{new}\" може да направи файла нечетлив.",
|
||||
"Do not show this dialog again." : "Не показвай този диалогов прозорец отново.",
|
||||
"Cancel" : "Отказ",
|
||||
"Rename" : "Преименувай",
|
||||
"Select file or folder to link to" : "Избор на файл или папка, към които да поставите връзка",
|
||||
"Choose {file}" : "Изберете {file}",
|
||||
"Files settings" : "Настройки на файловете",
|
||||
@@ -292,27 +290,30 @@
|
||||
"_You are about to permanently delete {count} item_::_You are about to permanently delete {count} items_" : ["На път сте да изтриете елемента {count} за постоянно","На път сте да изтриете елементите {count} за постоянно"],
|
||||
"_You are about to delete {count} item_::_You are about to delete {count} items_" : ["На път сте да изтриете {count} елемент","На път сте да изтриете {count} елементи"],
|
||||
"Confirm deletion" : "Потвърдете изтриването",
|
||||
"Cancel" : "Отказ",
|
||||
"Download" : "Изтегли",
|
||||
"The requested file is not available." : "Заявеният файл не е наличен.",
|
||||
"The requested files are not available." : "Заявените файлове не са налични.",
|
||||
"Add to favorites" : "Добави към любимите",
|
||||
"Remove from favorites" : "Премахни от любимите",
|
||||
"Add or remove favorite" : "Добавете или премахнете любими",
|
||||
"Move" : "Преместване",
|
||||
"Copy" : "Копирай",
|
||||
"Move or copy" : "Премести или копирай",
|
||||
"Moving \"{source}\" to \"{destination}\" …" : "Преместване на \"{source}“ към “{destination}\"…",
|
||||
"Copying \"{source}\" to \"{destination}\" …" : "Копиране на \"{source}“ в “{destination}\"…",
|
||||
"Destination is not a folder" : "Предназначчението не е папка",
|
||||
"This file/folder is already in that directory" : "Този файл/папка вече е в тази директория",
|
||||
"You cannot move a file/folder onto itself or into a subfolder of itself" : "Не можете да преместите файл/папка в папка или в подпапка",
|
||||
"(copy)" : "(копие)",
|
||||
"(copy %n)" : "(копирай %n)",
|
||||
"A file or folder with that name already exists in this folder" : "В тази папка вече съществува файл или папка с това име",
|
||||
"The files are locked" : "Файловете са заключени",
|
||||
"The file does not exist anymore" : "Файлът вече не съществува",
|
||||
"Moving \"{source}\" to \"{destination}\" …" : "Преместване на \"{source}“ към “{destination}\"…",
|
||||
"Copying \"{source}\" to \"{destination}\" …" : "Копиране на \"{source}“ в “{destination}\"…",
|
||||
"Choose destination" : "Изберете дестинация",
|
||||
"Copy to {target}" : "Копиране в {target}",
|
||||
"Copy" : "Копирай",
|
||||
"Move to {target}" : "Преместване на {target}",
|
||||
"Move" : "Преместване",
|
||||
"Move or copy operation failed" : "Операцията за преместване или копиране не бе успешна",
|
||||
"Move or copy" : "Премести или копирай",
|
||||
"Open folder" : "Отвори папката",
|
||||
"Open folder {displayName}" : "Отворете папка {displayName}",
|
||||
"Open in Files" : "Отворете във Файлове",
|
||||
@@ -322,6 +323,7 @@
|
||||
"The file should now open on your device. If it doesn't, please check that you have the desktop app installed." : "Файлът вече би трябвало да се отвори на вашето устройство. Ако не се отвори, моля, проверете дали имате инсталирано настолното приложение.",
|
||||
"Retry and close" : "Опитайте отново и затворете",
|
||||
"Open online" : "Отворете онлайн",
|
||||
"Rename" : "Преименувай",
|
||||
"Details" : "Подробности",
|
||||
"View in folder" : "Преглед в папката",
|
||||
"Type" : "Тип",
|
||||
@@ -340,10 +342,10 @@
|
||||
"Some files could not be uploaded" : "Някои файлове не можаха да бъдат качени",
|
||||
"Files uploaded successfully" : "Файловете са качени успешно",
|
||||
"No files to process" : "Няма файлове за обработка",
|
||||
"Files copied successfully" : "Файловете са успешно копирани",
|
||||
"Files moved successfully" : "Файловете са преместени успешно",
|
||||
"Some files could not be copied" : "Някои файлове не можаха да бъдат копирани",
|
||||
"Some files could not be moved" : "Някои файлове не могат да бъдат преместени",
|
||||
"Files copied successfully" : "Файловете са успешно копирани",
|
||||
"Files moved successfully" : "Файловете са преместени успешно",
|
||||
"Conflicts resolution skipped" : "Разрешаването на конфликти е пропуснато",
|
||||
"Upload cancelled" : "Качването е отменено",
|
||||
"Could not rename \"{oldName}\", it does not exist any more" : "Файлът \"{oldName}\" не може да бъде преименуван защото не съществува",
|
||||
@@ -433,8 +435,6 @@
|
||||
"Edit locally" : "Локално редактиране",
|
||||
"Moving \"{source}\" to \"{destination}\" …" : "Преместване на \"{source}\" към \"{destination}\" …",
|
||||
"Copying \"{source}\" to \"{destination}\" …" : "Копиране на \"{source}\" в \"{destination}\" …",
|
||||
"(copy)" : "(копие)",
|
||||
"(copy %n)" : "(копирай %n)",
|
||||
"Move cancelled" : "Преместването е отменено",
|
||||
"Cancelled move or copy of \"{filename}\"." : "Преместването или копирането на \"{filename}\" е отменено.",
|
||||
"Cancelled move or copy operation" : "Операцията за преместване или копиране е отменена",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user