-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Expand file tree
/
Copy pathContentDisposition.php
More file actions
67 lines (58 loc) · 1.94 KB
/
ContentDisposition.php
File metadata and controls
67 lines (58 loc) · 1.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Http;
use Symfony\Component\HttpFoundation\HeaderUtils;
/**
* Centralized Content-Disposition header value generation.
*
* Thin wrapper around Symfony's HeaderUtils::makeDisposition() that
* auto-generates a multibyte-safe ASCII fallback filename.
*
* Fallback generation is adapted from Symfony's BinaryFileResponse::setContentDisposition().
* @see https://github.com/symfony/symfony/blob/7.4/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php
*/
class ContentDisposition {
/**
* Generate a Content-Disposition header value.
*
* @param string $disposition 'attachment' or 'inline'
* @param string $filename The desired filename (UTF-8)
* @return string The complete header value, e.g. 'attachment; filename="report.pdf"'
*/
public static function make(string $disposition, string $filename): string {
$fallback = self::toAsciiFallback($filename);
return HeaderUtils::makeDisposition($disposition, $filename, $fallback);
}
/**
* Generate an ASCII-safe fallback filename.
*
* Uses multibyte-aware iteration so that one logical character
* (even if multi-byte) maps to exactly one '_' replacement.
*
* @param string $filename UTF-8 filename
* @return string ASCII-only fallback filename
*/
private static function toAsciiFallback(string $filename): string {
// Pure ASCII and no '%' — usable as-is
if (preg_match('/^[\x20-\x7E]*$/', $filename) && !str_contains($filename, '%')) {
return $filename;
}
$fallback = '';
$length = mb_strlen($filename, 'UTF-8');
for ($i = 0; $i < $length; ++$i) {
$char = mb_substr($filename, $i, 1, 'UTF-8');
if ($char === '%') {
$fallback .= '_';
} elseif (preg_match('/^[\x20-\x7E]$/', $char) === 1) {
$fallback .= $char;
} else {
$fallback .= '_';
}
}
return $fallback;
}
}