]>
jfr.im git - uguu.git/blob - src/Classes/Upload.php
6 * @copyright Copyright (c) 2022 Go Johansson (nokonoko) <neku@pomf.se>
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Pomf\Uguu\Classes
;
26 class Upload
extends Response
28 public array $FILE_INFO ;
29 public array $fingerPrintInfo ;
30 private mixed $Connector ;
33 * Takes an array of files, and returns an array of arrays containing the file's temporary name, name, size, SHA1 hash, extension, and MIME type
35 * @param $files array The files array from the $_FILES superglobal.
37 * @return array An array of arrays.
40 public function reFiles ( array $files ): array
42 $this- > Connector
= new Connector ();
43 $this- > Connector
-> setDB ( $this- > Connector
-> DB
);
45 $files = $this- > diverseArray ( $files );
46 foreach ( $files as $file ) {
47 $hash = sha1_file ( $file [ 'tmp_name' ]);
49 'TEMP_NAME' => $file [ 'tmp_name' ],
50 'NAME' => strip_tags ( $file [ 'name' ]),
51 'SIZE' => $file [ 'size' ],
53 'EXTENSION' => $this- > fileExtension ( $file ),
54 'MIME' => $this- > fileMIME ( $file ),
55 'NEW_NAME' => $this- > generateName ( $this- > fileExtension ( $file ), $hash )
58 $this- > FILE_INFO
[ 'TEMP_NAME' ],
59 $this- > FILE_INFO
[ 'NAME' ],
60 $this- > FILE_INFO
[ 'SIZE' ],
61 $this- > FILE_INFO
[ 'SHA1' ],
62 $this- > FILE_INFO
[ 'EXTENSION' ],
63 $this- > FILE_INFO
[ 'MIME' ]
69 * Takes an array of arrays and returns an array of arrays with the keys and values swapped
71 * @param $files array an array of arrays
76 * 'TEMP_NAME' => 'example'
80 * 'EXTENSION' => 'example'
85 * 'TEMP_NAME' => 'example'
89 * 'EXTENSION' => 'example'
95 public function diverseArray ( array $files ): array
98 foreach ( $files as $key1 => $value1 ) {
99 foreach ( $value1 as $key2 => $value2 ) {
100 $result [ $key2 ][ $key1 ] = $value2 ;
107 * Takes a file, checks if it's blacklisted, moves it to the file storage, and then logs it to the database
109 * @return array An array containing the hash, name, url, and size of the file.
112 public function uploadFile (): array
115 if ( $this- > Connector
-> CONFIG
[ 'RATE_LIMIT' ]) {
116 $this- > Connector
-> checkRateLimit ( $this- > fingerPrintInfo
);
119 if ( $this- > Connector
-> CONFIG
[ 'BLACKLIST_DB' ]) {
120 $this- > Connector
-> checkFileBlacklist ( $this- > FILE_INFO
);
123 if ( $this- > Connector
-> CONFIG
[ 'FILTER_MODE' ] && empty ( $this- > FILE_INFO
[ 'EXTENSION' ])) {
124 $this- > checkMimeBlacklist ();
127 if ( $this- > Connector
-> CONFIG
[ 'FILTER_MODE' ] && ! empty ( $this- > FILE_INFO
[ 'EXTENSION' ])) {
128 $this- > checkMimeBlacklist ();
129 $this- > checkExtensionBlacklist ();
132 if (! is_dir ( $this- > Connector
-> CONFIG
[ 'FILES_ROOT' ])) {
133 throw new Exception ( 'File storage path not accessible.' , 500 );
137 ! move_uploaded_file ( $this- > FILE_INFO
[ 'TEMP_NAME' ], $this- > Connector
-> CONFIG
[ 'FILES_ROOT' ] .
138 $this- > FILE_INFO
[ 'NEW_NAME' ])
140 throw new Exception ( 'Failed to move file to destination' , 500 );
143 if (! chmod ( $this- > Connector
-> CONFIG
[ 'FILES_ROOT' ] . $this- > FILE_INFO
[ 'NEW_NAME' ], 0644 )) {
144 throw new Exception ( 'Failed to change file permissions' , 500 );
147 if (! $this- > Connector
-> CONFIG
[ 'LOG_IP' ]) {
148 $this- > fingerPrintInfo
[ 'ip' ] = null ;
151 $this- > Connector
-> newIntoDB ( $this- > FILE_INFO
, $this- > fingerPrintInfo
);
154 'hash' => $this- > FILE_INFO
[ 'SHA1' ],
155 'name' => $this- > FILE_INFO
[ 'NAME' ],
156 'url' => $this- > Connector
-> CONFIG
[ 'FILES_URL' ] . '/' . $this- > FILE_INFO
[ 'NEW_NAME' ],
157 'size' => $this- > FILE_INFO
[ 'SIZE' ]
162 * Takes the amount of files that are being uploaded, and creates a fingerprint of the user's IP address, user agent, and the amount of files being uploaded
164 * @param $files_amount int The amount of files that are being uploaded.
168 public function fingerPrint ( int $files_amount ): void
170 if (! empty ( $_SERVER [ 'HTTP_USER_AGENT' ])) {
171 $USER_AGENT = filter_var ( $_SERVER [ 'HTTP_USER_AGENT' ], FILTER_SANITIZE_ENCODED
);
172 $this- > fingerPrintInfo
= [
173 'timestamp' => time (),
174 'useragent' => $USER_AGENT ,
175 'ip' => $_SERVER [ 'REMOTE_ADDR' ],
176 'ip_hash' => hash ( 'sha1' , $_SERVER [ 'REMOTE_ADDR' ] . $USER_AGENT ),
177 'files_amount' => $files_amount
180 throw new Exception ( 'Invalid user agent.' , 500 );
186 * Returns the MIME type of a file
188 * @param $file array The file to be checked.
190 * @return string The MIME type of the file.
192 public function fileMIME ( array $file ): string
194 $FILE_INFO = finfo_open ( FILEINFO_MIME_TYPE
);
195 return finfo_file ( $FILE_INFO , $file [ 'tmp_name' ]);
199 * Takes a file and returns the file extension
201 * @param $file array The file you want to get the extension from.
203 * @return ?string The file extension of the file.
205 public function fileExtension ( array $file ): ? string
207 $extension = explode ( '.' , $file [ 'name' ]);
208 if ( substr_count ( $file [ 'name' ], '.' ) > 0 ) {
209 return end ( $extension );
216 * > Check if the file's MIME type is in the blacklist
220 public function checkMimeBlacklist (): void
222 if ( in_array ( $this- > FILE_INFO
[ 'MIME' ], $this- > Connector
-> CONFIG
[ 'BLOCKED_MIME' ])) {
223 throw new Exception ( 'Filetype not allowed.' , 415 );
228 * > Check if the file extension is in the blacklist
232 public function checkExtensionBlacklist (): void
234 if ( in_array ( $this- > FILE_INFO
[ 'EXTENSION' ], $this- > Connector
-> CONFIG
[ 'BLOCKED_EXTENSIONS' ])) {
235 throw new Exception ( 'Filetype not allowed.' , 415 );
240 * Generates a random string of characters, checks if it exists in the database, and if it does, it generates another one
242 * @param $extension string The file extension.
243 * @param $hash string The hash of the file.
245 * @return string A string
248 public function generateName ( string $extension , string $hash ): string
250 if ( $this- > Connector
-> antiDupe ( $hash )) {
252 if ( $this- > Connector
-> CONFIG
[ 'FILES_RETRIES' ] === 0 ) {
253 throw new Exception ( 'Gave up trying to find an unused name!' , 500 );
257 for ( $i = 0 ; $i < $this- > Connector
-> CONFIG
[ 'NAME_LENGTH' ]; ++
$i ) {
258 $NEW_NAME .= $this- > Connector
-> CONFIG
[ 'ID_CHARSET' ]
259 [ mt_rand ( 0 , strlen ( $this- > Connector
-> CONFIG
[ 'ID_CHARSET' ]))];
262 if (! empty ( $extension )) {
263 $NEW_NAME .= '.' . $extension ;
265 } while ( $this- > Connector
-> dbCheckNameExists ( $NEW_NAME ) > 0 );
268 return $this- > Connector
-> antiDupe ( $hash );