Skip to content

Trashbin truncate filename unicode - #62698

Open
icewind1991 wants to merge 2 commits into
masterfrom
trashbin-truncate-filename-unicode
Open

Trashbin truncate filename unicode#62698
icewind1991 wants to merge 2 commits into
masterfrom
trashbin-truncate-filename-unicode

Conversation

@icewind1991

@icewind1991 icewind1991 commented Jul 30, 2026

Copy link
Copy Markdown
Member
  • Resolves: #

Summary

The old logic can cut right in the middle of multi-byte unicode codepoints.

TODO

  • ...

Checklist

AI (if applicable)

  • The content of this PR was partly or fully generated using AI

@icewind1991 icewind1991 added this to the Nextcloud 35 milestone Jul 30, 2026
@icewind1991
icewind1991 requested a review from a team as a code owner July 30, 2026 14:01
@icewind1991 icewind1991 added the 3. to review Waiting for reviews label Jul 30, 2026
@icewind1991
icewind1991 requested review from Altahrim, come-nc, leftybournes and salmart-dev and removed request for a team July 30, 2026 14:01
@icewind1991

Copy link
Copy Markdown
Member Author

/backport to stable34

@icewind1991

Copy link
Copy Markdown
Member Author

/backport to stable33

@icewind1991

Copy link
Copy Markdown
Member Author

/backport to stable32

ShGKme
ShGKme previously approved these changes Jul 30, 2026
Comment thread apps/files_trashbin/lib/Trashbin.php Outdated
Comment thread apps/files_trashbin/lib/Trashbin.php Outdated
Comment thread apps/files_trashbin/lib/Trashbin.php
@ShGKme
ShGKme dismissed their stale review July 30, 2026 21:52

Outdated

@ShGKme ShGKme left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To remove the middle instead of "after the middle"

Comment on lines +1215 to +1220

$charsToRemove = $length - $maxLength + 1;
$charLength = mb_strlen($trashFilename);
$start = mb_substr($trashFilename, 0, floor(($charLength / 2) - $charsToRemove));
$end = mb_substr($trashFilename, floor($charLength / 2));
return $start . '_' . $end;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$charsToRemove = $length - $maxLength + 1;
$charLength = mb_strlen($trashFilename);
$start = mb_substr($trashFilename, 0, floor(($charLength / 2) - $charsToRemove));
$end = mb_substr($trashFilename, floor($charLength / 2));
return $start . '_' . $end;
$half = intdiv($maxLength - 1, 2); // One char for _
return mb_substr($trashFilename, 0, $half)
. '_'
. mb_substr($trashFilename, -$half);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That doesn't work with multibyte codepoints, mb_substr($foo, 0, $length) can have a byte length > $length.

By using mb_strlen as the starting point for determining the mb_substr codepoint length, we take that into account.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but we can still remove the middle instead of from/to the middle.

@icewind1991
icewind1991 force-pushed the trashbin-truncate-filename-unicode branch from 6f8fdab to 3f4310f Compare July 31, 2026 14:48
Signed-off-by: Robin Appelman <robin@icewind.nl>
Signed-off-by: Robin Appelman <robin@icewind.nl>
@icewind1991
icewind1991 force-pushed the trashbin-truncate-filename-unicode branch from 3f4310f to b9d7662 Compare July 31, 2026 15:40
Comment on lines +1216 to +1218
$charsToRemove = $length - $maxLength + 1;
$charLength = mb_strlen($trashFilename);
$start = mb_substr($trashFilename, 0, intdiv($charLength, 2) - $charsToRemove);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original filename is bound to the same 500 byte limit, so we can't get into that situation.

$length = 500 (can even be longer due to '.d' . $timestamp)
$maxLength = 250
$charsToRemove = 500 - 250 + 1 = 251
intdiv($charLength, 2) - $charsToRemove = 500 / 2 - 251 = -1
Start is a suffix instead of a prefix?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems very indirect to rely on the 500 limit here - this is not visible from the code.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not remove in the middle instead of using the middle as the boundary?
Then we don't need to worry about a half being too big.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a mistake in an earlier comment, the $filename has a max-length of 250

This was referenced Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants