Skip to content

Commit a43ce31

Browse files
Merge pull request #63812 from nextcloud/backport/62698/stable35
[stable35] Trashbin truncate filename unicode
2 parents 980e5ee + 7a99cb6 commit a43ce31

3 files changed

Lines changed: 36 additions & 8 deletions

File tree

apps/files_trashbin/lib/Trashbin.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,12 +1244,13 @@ public static function getTrashFilename(string $filename, int $timestamp): strin
12441244
// oc_filecache `name` column has a limit of 250 chars
12451245
$maxLength = 250;
12461246
if ($length > $maxLength) {
1247-
$trashFilename = substr_replace(
1248-
$trashFilename,
1249-
'',
1250-
$maxLength / 2,
1251-
$length - $maxLength
1252-
);
1247+
// truncate at the middle, since the last characters are fairly likely to have meaningful information such as version numbering
1248+
1249+
$charsToRemove = $length - $maxLength + 1;
1250+
$charLength = mb_strlen($trashFilename);
1251+
$start = mb_substr($trashFilename, 0, intdiv($charLength, 2) - $charsToRemove);
1252+
$end = mb_substr($trashFilename, intdiv($charLength, 2));
1253+
return $start . '_' . $end;
12531254
}
12541255
return $trashFilename;
12551256
}

apps/files_trashbin/tests/StorageTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ public function testSingleStorageDeleteFolder(): void {
226226
* Test that deleting a file with a long filename puts it into the trashbin.
227227
*/
228228
public function testSingleStorageDeleteLongFilename(): void {
229-
$truncatedFilename = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt';
229+
$truncatedFilename = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt';
230230

231231
$this->assertTrue($this->userView->file_exists(static::LONG_FILENAME));
232232
$this->userView->unlink(static::LONG_FILENAME);
@@ -245,7 +245,7 @@ public function testSingleStorageDeleteLongFilename(): void {
245245
* Test that deleting a file with the max filename length puts it into the trashbin.
246246
*/
247247
public function testSingleStorageDeleteMaxLengthFilename(): void {
248-
$truncatedFilename = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt';
248+
$truncatedFilename = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt';
249249

250250
$this->assertTrue($this->userView->file_exists(static::MAX_FILENAME));
251251
$this->userView->unlink(static::MAX_FILENAME);

apps/files_trashbin/tests/TrashbinTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
use OCP\IUserManager;
3333
use OCP\Server;
3434
use OCP\Share\IShare;
35+
use PHPUnit\Framework\Attributes\DataProvider;
3536

3637
/**
3738
* Class Test_Encryption
@@ -706,6 +707,32 @@ public static function loginHelper($user, $create = false) {
706707
\OC_Util::setupFS($user);
707708
Server::get(IRootFolder::class)->getUserFolder($user);
708709
}
710+
711+
public static function trashFilenameProvider(): array {
712+
return [
713+
['foo.txt', 'foo.txt.d1234'],
714+
[
715+
'a_very_long_filename_with_a_lot_a_characters_such_that_it_reaches_the_file_length_limit_and_would_cause_issues_if_we_just_appended_the_'
716+
. 'timestamp_because_then_the_combined_length_would_overflow_the_column_limit_of_the_filecache_and_truncate_in_db.txt',
717+
'a_very_long_filename_with_a_lot_a_characters_such_that_it_reaches_the_file_length_limit_and_would_cause_issues_if_we_just_ded_the_'
718+
. 'timestamp_because_then_the_combined_length_would_overflow_the_column_limit_of_the_filecache_and_truncate_in_db.txt.d1234'
719+
],
720+
[
721+
'a_very_long_filename_with_a_lot_a_characters_such_that_it_reaches_the_file_length_limit_and_would_cause_issues_if_we_just_äøšá_the_'
722+
. 'timestamp_because_then_the_combined_length_would_overflow_the_column_limit_of_the_filecache_and_truncate_in_db.txt',
723+
'a_very_long_filename_with_a_lot_a_characters_such_that_it_reaches_the_file_length_limit_and_would_cause_issues_if_we_ju_á_the_'
724+
. 'timestamp_because_then_the_combined_length_would_overflow_the_column_limit_of_the_filecache_and_truncate_in_db.txt.d1234'
725+
],
726+
];
727+
}
728+
729+
#[DataProvider(methodName: 'trashFilenameProvider')]
730+
public function testGetTrashFilename(string $filename, string $expected): void {
731+
$result = Trashbin::getTrashFilename($filename, 1234);
732+
$this->assertTrue(mb_check_encoding($result, 'UTF-8'));
733+
$this->assertEquals($expected, $result);
734+
$this->assertTrue(strlen($result) <= 250);
735+
}
709736
}
710737

711738
// just a dummy class to make protected methods available for testing

0 commit comments

Comments
 (0)