]>
Commit | Line | Data |
---|---|---|
d8c46ff7 GJ |
1 | <?php |
2 | /** | |
3 | * Require the settings and DB files. | |
4 | */ | |
5 | require_once 'classes/Response.class.php'; | |
6 | require_once 'classes/UploadException.class.php'; | |
7 | require_once 'classes/UploadedFile.class.php'; | |
8 | require_once 'includes/database.inc.php'; | |
9 | ||
10 | /** | |
11 | * Generates name and checks in DB | |
12 | * Also adds to DB. | |
13 | */ | |
14 | function generateName($file) | |
15 | { | |
16 | global $db; | |
17 | global $doubledots; | |
18 | ||
19 | // We start at N retries, and --N until we give up | |
b1d3139a GJ |
20 | $tries = UGUU_FILES_RETRIES; |
21 | $length = UGUU_FILES_LENGTH; | |
d8c46ff7 GJ |
22 | //Get EXT |
23 | $ext = pathinfo($file->name, PATHINFO_EXTENSION); | |
24 | //Get mime | |
25 | $finfo = finfo_open(FILEINFO_MIME_TYPE); | |
26 | $type_mime = finfo_file($finfo, $file->tempfile); | |
27 | finfo_close($finfo); | |
28 | ||
29 | // Check if extension is a double-dot extension and, if true, override $ext | |
30 | $revname = strrev($file->name); | |
31 | foreach ($doubledots as $ddot) { | |
32 | if (stripos($revname, $ddot) === 0) { | |
33 | $ext = strrev($ddot); | |
34 | } | |
35 | } | |
36 | ||
37 | do { | |
38 | // Iterate until we reach the maximum number of retries | |
39 | if ($tries-- === 0) { | |
40 | throw new Exception( | |
41 | 'Gave up trying to find an unused name', | |
42 | 500 | |
43 | ); // HTTP status code "500 Internal Server Error" | |
44 | } | |
45 | ||
46 | $chars = ID_CHARSET; | |
47 | $name = ''; | |
48 | for ($i = 0; $i < $length; ++$i) { | |
49 | $name .= $chars[mt_rand(0, strlen($chars))]; | |
50 | } | |
51 | ||
52 | // Add the extension to the file name | |
53 | if (isset($ext) && $ext !== '') { | |
54 | $name .= '.'.$ext; | |
55 | } | |
56 | ||
57 | //Check if mime is blacklisted | |
58 | if (in_array($type_mime, unserialize(CONFIG_BLOCKED_MIME))) { | |
4b7727f7 | 59 | http_response_code(415); |
180e8018 | 60 | throw new Exception('Filetype not allowed!'); |
d8c46ff7 GJ |
61 | exit(0); |
62 | } | |
63 | ||
64 | //Check if EXT is blacklisted | |
65 | if (in_array($ext, unserialize(CONFIG_BLOCKED_EXTENSIONS))) { | |
4b7727f7 | 66 | http_response_code(415); |
180e8018 | 67 | throw new Exception('Filetype not allowed!'); |
d8c46ff7 GJ |
68 | exit(0); |
69 | } | |
70 | ||
71 | // Check if a file with the same name does already exist in the database | |
72 | $q = $db->prepare('SELECT COUNT(filename) FROM files WHERE filename = (:name)'); | |
73 | $q->bindValue(':name', $name, PDO::PARAM_STR); | |
74 | $q->execute(); | |
75 | $result = $q->fetchColumn(); | |
76 | // If it does, generate a new name | |
77 | } while ($result > 0); | |
78 | ||
79 | return $name; | |
80 | } | |
81 | ||
82 | /** | |
83 | * Handles the uploading and db entry for a file. | |
84 | * | |
85 | * @param UploadedFile $file | |
86 | * | |
87 | * @return array | |
88 | */ | |
89 | function uploadFile($file) | |
90 | { | |
91 | global $db; | |
92 | global $FILTER_MODE; | |
93 | global $FILTER_MIME; | |
94 | ||
95 | // Handle file errors | |
96 | if ($file->error) { | |
97 | throw new UploadException($file->error); | |
98 | } | |
99 | ||
100 | // Generate a name for the file | |
101 | $newname = generateName($file); | |
102 | ||
103 | // Store the file's full file path in memory | |
b1d3139a | 104 | $uploadFile = UGUU_FILES_ROOT.$newname; |
d8c46ff7 GJ |
105 | |
106 | // Attempt to move it to the static directory | |
107 | if (!move_uploaded_file($file->tempfile, $uploadFile)) { | |
108 | throw new Exception( | |
109 | 'Failed to move file to destination', | |
110 | 500 | |
111 | ); // HTTP status code "500 Internal Server Error" | |
112 | } | |
113 | ||
114 | // Need to change permissions for the new file to make it world readable | |
115 | if (!chmod($uploadFile, 0644)) { | |
116 | throw new Exception( | |
117 | 'Failed to change file permissions', | |
118 | 500 | |
119 | ); // HTTP status code "500 Internal Server Error" | |
120 | } | |
121 | ||
122 | // Add it to the database | |
123 | $q = $db->prepare('INSERT INTO files (hash, originalname, filename, size, date) VALUES (:hash, :orig, :name, :size, :date)'); | |
124 | ||
125 | // Common parameters binding | |
126 | $q->bindValue(':hash', $file->getSha1(), PDO::PARAM_STR); | |
127 | $q->bindValue(':orig', strip_tags($file->name), PDO::PARAM_STR); | |
128 | $q->bindValue(':name', $newname, PDO::PARAM_STR); | |
129 | $q->bindValue(':size', $file->size, PDO::PARAM_INT); | |
130 | $q->bindValue(':date', time(), PDO::PARAM_INT); | |
131 | $q->execute(); | |
132 | ||
133 | return [ | |
134 | 'hash' => $file->getSha1(), | |
135 | 'name' => $file->name, | |
b1d3139a | 136 | 'url' => UGUU_URL.rawurlencode($newname), |
d8c46ff7 GJ |
137 | 'size' => $file->size, |
138 | ]; | |
139 | } | |
140 | ||
141 | /** | |
142 | * Reorder files array by file. | |
143 | * | |
144 | * @return array | |
145 | */ | |
146 | function diverseArray($files) | |
147 | { | |
148 | $result = []; | |
149 | ||
150 | foreach ($files as $key1 => $value1) { | |
151 | foreach ($value1 as $key2 => $value2) { | |
152 | $result[$key2][$key1] = $value2; | |
153 | } | |
154 | } | |
155 | ||
156 | return $result; | |
157 | } | |
158 | ||
159 | /** | |
160 | * Reorganize the $_FILES array into something saner. | |
161 | * | |
162 | * @return array | |
163 | */ | |
164 | function refiles($files) | |
165 | { | |
166 | $result = []; | |
167 | $files = diverseArray($files); | |
168 | ||
169 | foreach ($files as $file) { | |
170 | $f = new UploadedFile(); | |
171 | $f->name = $file['name']; | |
172 | $f->mime = $file['type']; | |
173 | $f->size = $file['size']; | |
174 | $f->tempfile = $file['tmp_name']; | |
175 | $f->error = $file['error']; | |
176 | $result[] = $f; | |
177 | } | |
178 | ||
179 | return $result; | |
180 | } | |
181 | ||
182 | $type = isset($_GET['output']) ? $_GET['output'] : 'json'; | |
183 | $response = new Response($type); | |
184 | ||
185 | if (isset($_FILES['files'])) { | |
186 | $uploads = refiles($_FILES['files']); | |
187 | ||
188 | try { | |
189 | foreach ($uploads as $upload) { | |
190 | $res[] = uploadFile($upload); | |
191 | } | |
192 | $response->send($res); | |
193 | } catch (Exception $e) { | |
194 | $response->error($e->getCode(), $e->getMessage()); | |
195 | } | |
196 | } else { | |
197 | $response->error(400, 'No input file(s)'); | |
198 | } |