· 9 years ago · Jun 23, 2017, 09:28 PM
1<?php
2##########################################
3# ImageUpload Class version: 0.1 Beta #
4# Created by: icecub #
5##########################################
6
7Class ImageUpload {
8 private $host = DB_HOST;
9 private $user = DB_USER;
10 private $pass = DB_PASS;
11 private $dbname = DB_NAME;
12 private $table = DB_TABLE;
13
14 private $dbh;
15 private $error = array();
16 private $info = array();
17 private $ids = array();
18 private $obj;
19
20 private $stmt;
21
22 private $mtype;
23
24 private $folder = F_PATH;
25 private $htaccess = H_FILE;
26 private $f_size = F_SIZE;
27
28 /* Set up a PDO instance */
29 public function __construct(){
30 // Set DSN
31 $dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
32 // Set options
33 $options = array(
34 PDO::ATTR_PERSISTENT => true,
35 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
36 );
37 // Create a new PDO instance
38 try{
39 $this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
40 }
41 // Catch any errors
42 catch(PDOException $e){
43 array_push($this->error, $e->getMessage());
44 $this->obj->error = $this->error;
45 return $this->obj;
46 }
47
48 $this->obj = new StdClass;
49 }
50
51 /* Custom bindParam function */
52 private function bind($param, $value, $type = null){
53 if (is_null($type)) {
54 switch (true) {
55 case is_int($value):
56 $type = PDO::PARAM_INT;
57 break;
58 case is_bool($value):
59 $type = PDO::PARAM_BOOL;
60 break;
61 case is_null($value):
62 $type = PDO::PARAM_NULL;
63 break;
64 default:
65 $type = PDO::PARAM_STR;
66 }
67 }
68 $this->stmt->bindValue($param, $value, $type);
69 }
70
71 /* Checks if the table already exists. If not, creates one */
72 private function createTable(){
73 // Check if table already exists
74 $this->stmt = $this->dbh->prepare("SHOW TABLES LIKE '". DB_TABLE ."'");
75
76 try{
77 $this->stmt->execute();
78 }
79 catch(PDOException $e){
80 array_push($this->error, $e->getMessage());
81 return false;
82 }
83
84 $cnt = $this->stmt->rowCount();
85
86 if($cnt > 0){
87 return true;
88 } else {
89 // Create table
90 $this->stmt = $this->dbh->prepare("
91 CREATE TABLE `". DB_TABLE ."` (
92 `id` INT(11) NOT NULL AUTO_INCREMENT,
93 `name` VARCHAR(64) NOT NULL,
94 `original_name` VARCHAR(64) NOT NULL,
95 `mime_type` VARCHAR(20) NOT NULL,
96 PRIMARY KEY (`id`)
97 ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;");
98 try{
99 $this->stmt->execute();
100 return true;
101 }
102 catch(PDOException $e){
103 array_push($this->error, $e->getMessage());
104 return false;
105 }
106 }
107 }
108
109 /* Checks if the htaccess file exists. If not, creates one */
110 private function createHtaccess(){
111 if (!file_exists($this->folder."/.htaccess")){
112 try {
113 $file = fopen($this->folder."/.htaccess","w");
114 $txt = "order deny,allow\n";
115 $txt .= "deny from all\n";
116 $txt .="allow from 127.0.0.1";
117 fwrite($file, $txt);
118 fclose($file);
119 return true;
120 } catch (Exception $e) {
121 return false;
122 }
123 } else {
124 return true;
125 }
126 }
127
128 /* Checks if required PHP extensions are loaded. Tries to load them if not */
129 private function check_phpExt(){
130 if (!extension_loaded('fileinfo')) {
131 // dl() is disabled in the PHP-FPM since php7 so we check if it's available first
132 if(function_exists('dl')){
133 if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
134 if (!dl('fileinfo.dll')) {
135 return false;
136 } else {
137 return true;
138 }
139 } else {
140 if (!dl('fileinfo.so')) {
141 return false;
142 } else {
143 return true;
144 }
145 }
146 } else {
147 return false;
148 }
149 } else {
150 return true;
151 }
152 }
153
154 /* Creates a file with a random name */
155 private function tempnam_sfx($path, $suffix){
156 do {
157 $file = $path."/".mt_rand().$suffix;
158 $fp = @fopen($file, 'x');
159 }
160 while(!$fp);
161
162 fclose($fp);
163 return $file;
164 }
165
166 /* Checks the true mime type of the given file */
167 private function check_img_mime($tmpname){
168 $finfo = finfo_open( FILEINFO_MIME_TYPE );
169 $mtype = finfo_file( $finfo, $tmpname );
170 $this->mtype = $mtype;
171 if(strpos($mtype, 'image/') === 0){
172 return true;
173 } else {
174 return false;
175 }
176 finfo_close( $finfo );
177 }
178
179 /* Checks if the image isn't to large */
180 private function check_img_size($tmpname){
181 $size_conf = substr(F_SIZE, -1);
182 $max_size = (int)substr(F_SIZE, 0, -1);
183
184 switch($size_conf){
185 case 'k':
186 case 'K':
187 $max_size *= 1024;
188 break;
189 case 'm':
190 case 'M':
191 $max_size *= 1024;
192 $max_size *= 1024;
193 break;
194 default:
195 $max_size = 1024000;
196 }
197
198 if(filesize($tmpname) > $max_size){
199 return false;
200 } else {
201 return true;
202 }
203 }
204
205 /* Re-arranges the $_FILES array */
206 private function reArrayFiles($files){
207 $file_ary = array();
208 $file_count = count($files['name']);
209 $file_keys = array_keys($files);
210
211 for ($i=0; $i<$file_count; $i++) {
212 foreach ($file_keys as $key) {
213 $file_ary[$i][$key] = $files[$key][$i];
214 }
215 }
216
217 return $file_ary;
218 }
219
220 /* Handles the uploading of images */
221 public function uploadImages($files){
222 // Checks if the required PHP extension(s) are loaded
223 if($this->check_phpExt()){
224 // Checks if db table exists. Creates it if nessesary
225 if($this->createTable()){
226 // Checks if a htaccess file should be created and creates one if needed
227 if($this->htaccess){
228 if(!$this->createHtaccess()){
229 array_push($this->error, "Unable to create htaccess file.");
230 $this->obj->error = $this->error;
231 return $this->obj;
232 }
233 }
234
235 // Re-arranges the $_FILES array
236 $files = $this->reArrayFiles($files);
237 foreach($files as $file){
238 // Checks if $file['tmp_name'] is empty. This occurs when a file is bigger than allowed by the 'post_max_size' and/or 'upload_max_filesize' settings in php.ini
239 if(!empty($file['tmp_name'])){
240 // Checks the true MIME type of the file
241 if($this->check_img_mime($file['tmp_name'])){
242 // Checks the size of the the image
243 if($this->check_img_size($file['tmp_name'])){
244 // Creates a file in the upload directory with a random name
245 $uploadfile = $this->tempnam_sfx($this->folder, ".tmp");
246
247 // Moves the image to the created file
248 if (move_uploaded_file($file['tmp_name'], $uploadfile)) {
249 // Inserts the file data into the db
250 $this->stmt = $this->dbh->prepare("INSERT INTO ". DB_TABLE ." (name, original_name, mime_type) VALUES (:name, :oriname, :mime)");
251
252 $this->bind(':name', basename($uploadfile));
253 $this->bind(':oriname', basename($file['name']));
254 $this->bind(':mime', $this->mtype);
255
256 try{
257 $this->stmt->execute();
258 }
259 catch(PDOException $e){
260 array_push($this->error, $e->getMessage());
261 $this->obj->error = $this->error;
262 return $this->obj;
263 }
264
265 array_push($this->ids, $this->dbh->lastInsertId());
266 array_push($this->info, "File: ". $file['name'] ." was succesfully uploaded!");
267
268 continue;
269 } else {
270 unlink($file['tmp_name']);
271 array_push($this->info, "Unable to move file: ". $file['name'] ." to target folder. The file is removed!");
272 }
273 } else {
274 array_push($this->info, "File: ". $file['name'] ." exceeds the maximum file size of: ". F_SIZE ."B. The file is removed!");
275 }
276 } else {
277 unlink($file['tmp_name']);
278 array_push($this->info, "File: ". $file['name'] ." is not an image. The file is removed!");
279 }
280 } else {
281 array_push($this->info, "File: ". $file['name'] ." exceeds the maximum file size that this server allowes to be uploaded!");
282 }
283 }
284 // Checks if the error array is empty
285 foreach ($this->error as $key => $value) {
286 if (empty($value)) {
287 unset($this->error[$key]);
288 }
289 }
290 if (empty($this->error)) {
291
292 $this->obj->info = $this->info;
293 $this->obj->ids = $this->ids;
294
295 return $this->obj;
296 } else {
297 $this->error = array_unique($this->error);
298 $this->obj->error = $this->error;
299 return $this->obj;
300 }
301 } else {
302 if($this->error !== NULL){
303 $this->obj->error = $this->error;
304 return $this->obj;
305 } else {
306 // This should never happen, but it's here just in case
307 array_push($this->error, "Unknown error! Failed to load ImageUpload class!");
308 $this->obj->error = $this->error;
309 return $this->obj;
310 }
311 }
312 } else {
313 array_push($this->error, "The PHP fileinfo extension isn't loaded and ImageUpload was unable to load it for you.");
314 $this->obj->error = $this->error;
315 return $this->obj;
316 }
317 }
318
319 /* Show the image in the browser */
320 public function showImage($id){
321 $this->stmt = $this->dbh->prepare("SELECT name, original_name, mime_type FROM ". DB_TABLE ." WHERE id=:id");
322
323 $this->bind(':id', $id);
324
325 try{
326 $this->stmt->execute();
327 $result = $this->stmt->fetch(PDO::FETCH_ASSOC);
328 }
329 catch(PDOException $e){
330 array_push($this->error, $e->getMessage());
331 $this->obj->error = $this->error;
332 return $this->obj;
333 }
334
335 $newfile = $result['original_name'];
336
337 /* Send headers and file to visitor for display */
338 header("Content-Type: " . $result['mime_type']);
339 readfile(F_PATH.'/'.$result['name']);
340 }
341
342 /* Force a download of the image */
343 public function downloadImage($id){
344 $this->stmt = $this->dbh->prepare("SELECT name, original_name, mime_type FROM ". DB_TABLE ." WHERE id=:id");
345
346 $this->bind(':id', $id);
347
348 try{
349 $this->stmt->execute();
350 $result = $this->stmt->fetch(PDO::FETCH_ASSOC);
351 }
352 catch(PDOException $e){
353 array_push($this->error, $e->getMessage());
354 $this->obj->error = $this->error;
355 return $this->obj;
356 }
357
358 $newfile = $result['original_name'];
359
360 /* Send headers and file to visitor for download */
361 header('Content-Description: File Transfer');
362 header('Content-Disposition: attachment; filename='.basename($newfile));
363 header('Expires: 0');
364 header('Cache-Control: must-revalidate');
365 header('Pragma: public');
366 header('Content-Length: ' . filesize(F_PATH.'/'.$result['name']));
367 header("Content-Type: " . $result['mime_type']);
368 readfile(F_PATH.'/'.$result['name']);
369 }
370
371 /* Delete an image */
372 public function deleteImage($id){
373 $this->stmt = $this->dbh->prepare("SELECT name, original_name, FROM ". DB_TABLE ." WHERE id=:id");
374
375 $this->bind(':id', $id);
376
377 try{
378 $this->stmt->execute();
379 $result = $this->stmt->fetch(PDO::FETCH_ASSOC);
380 }
381 catch(PDOException $e){
382 array_push($this->error, $e->getMessage());
383 $this->obj->error = $this->error;
384 return $this->obj;
385 }
386
387 unlink(F_PATH.'/'.$result['name']);
388
389 $this->stmt = $this->dbh->prepare("DELETE FROM ". DB_TABLE ." WHERE id=:id");
390
391 $this->bind(':id', $id);
392
393 try{
394 $this->stmt->execute();
395 }
396 catch(PDOException $e){
397 array_push($this->error, $e->getMessage());
398 $this->obj->error = $this->error;
399 return $this->obj;
400 }
401
402 array_push($this->info, "File: ". $result['original_name'] ." succesfully deleted.");
403 $this->obj->info = $this->info;
404 return $this->obj;
405 }
406}
407
408?>