-
Notifications
You must be signed in to change notification settings - Fork 0
/
Util.php
171 lines (141 loc) · 4.62 KB
/
Util.php
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php
namespace Devture\Bundle\StorerBundle;
class Util {
/**
* Makes a filename safe for filesystem use.
*
* Source: https://stackoverflow.com/a/42058764
*/
static public function filterFileName(string $fileName, bool $beautify = true): string {
// sanitize filename
$fileName = preg_replace(
'~
[<>:"/\\|?*]| # file system reserved https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words
[\x00-\x1F]| # control characters http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
[\x7F\xA0\xAD]| # non-printing characters DEL, NO-BREAK SPACE, SOFT HYPHEN
[#\[\]@!$&\'()+,;=]| # URI reserved https://tools.ietf.org/html/rfc3986#section-2.2
[{}^\~`] # URL unsafe characters https://www.ietf.org/rfc/rfc1738.txt
~x',
'-',
$fileName
);
// avoids ".", ".." or ".hiddenFiles"
$fileName = ltrim($fileName, '.-');
// optional beautification
if ($beautify) {
$fileName = static::beautifyFileName($fileName);
}
// maximize filename length to 255 bytes http://serverfault.com/a/9548/44086
$ext = pathinfo($fileName, PATHINFO_EXTENSION);
$fileName = mb_strcut(pathinfo($fileName, PATHINFO_FILENAME), 0, 255 - ($ext ? strlen($ext) + 1 : 0), mb_detect_encoding($fileName)) . ($ext ? '.' . $ext : '');
return $fileName;
}
/**
* Makes a filename prettier/cleaner.
*
* Source: https://stackoverflow.com/a/42058764
*/
static public function beautifyFileName(string $fileName): string {
// reduce consecutive characters
$fileName = preg_replace(
[
// "file name.zip" becomes "file-name.zip"
'/ +/',
// "file___name.zip" becomes "file-name.zip"
'/_+/',
// "file---name.zip" becomes "file-name.zip"
'/-+/'
],
'-',
$fileName
);
$fileName = preg_replace(
[
// "file--.--.-.--name.zip" becomes "file.name.zip"
'/-*\.-*/',
// "file...name..zip" becomes "file.name.zip"
'/\.{2,}/'
],
'.',
$fileName
);
// lowercase for windows/unix interoperability http://support.microsoft.com/kb/100625
$fileName = mb_strtolower($fileName, mb_detect_encoding($fileName));
// ".file-name.-" becomes "file-name"
$fileName = trim($fileName, '.-');
return $fileName;
}
static public function getExtensionByFileName(string $fileName): ?string {
$parts = explode('.', $fileName);
if (count($parts) === 1) {
return null;
}
$lastPart = array_pop($parts);
if ($lastPart === null) {
// We don't expect this to happen.
// After all, we had already done a check and know `$parts` has at least 1 element.
// To keep static-analyzers happy though, we're having this extra check.
return null;
}
$extension = strtolower($lastPart);
$extension = preg_replace('/([^a-z0-9])/', '', $extension);
if ($extension === '') {
return null;
}
if (count($parts) > 1) {
//If there are more parts (besides the actual name),
//consider the possibility that we're dealing with a "something.tar.gz" kind of
//situation.
$lastPart = array_pop($parts);
if ($lastPart === null) {
// We don't expect this to happen.
// After all, we had already done a check and know `$parts` has more than 1 element.
// To keep static-analyzers happy though, we're having this extra check.
return null;
}
$extensionNext = strtolower($lastPart);
if ($extensionNext === 'tar') {
$extension = sprintf('%s.%s', $extensionNext, $extension);
}
}
if ($extension === 'jpeg') {
//Normalize
$extension = 'jpg';
}
return $extension;
}
static public function getContentTypeByFileName(string $fileName): ?string {
static $mimeTypeRepository;
if ($mimeTypeRepository === null) {
$mimeTypeRepository = new \Dflydev\ApacheMimeTypes\PhpRepository();
}
$extension = self::getExtensionByFileName($fileName);
if ($extension === null) {
return 'application/octet-stream';
}
$type = $mimeTypeRepository->findType($extension);
if ($type === null) {
return 'application/octet-stream';
}
return $type;
}
static public function generateFullStorageKey(string $storagePrefix, string $originalName): string {
$extension = self::getExtensionByFileName($originalName);
$extensionSuffix = ($extension ? sprintf('.%s', $extension) : '');
$bareFileName = \Ramsey\Uuid\Uuid::uuid4()->toString();
return sprintf(
'%s/%s/%s%s',
trim($storagePrefix, '/'),
date('Y/m/d'),
$bareFileName,
$extensionSuffix
);
}
static public function getThumbnailExtensionByFileName(string $fileName): ?string {
$extension = self::getExtensionByFileName($fileName);
if ($extension === 'png') {
return 'png';
}
return 'jpg';
}
}