1<?php 2 3/* 4 * jQuery File Upload Plugin PHP Example 5.2.9 5 * https://github.com/blueimp/jQuery-File-Upload 6 * 7 * Copyright 2010, Sebastian Tschan 8 * https://blueimp.net 9 * 10 * Licensed under the MIT license: 11 * http://creativecommons.org/licenses/MIT/ 12 */ 13 14define('OFFSET_PATH', 3); 15require_once(dirname(dirname(dirname(__FILE__))) . '/admin-globals.php'); 16 17$_zp_loggedin = NULL; 18if (isset($_POST['auth'])) { 19 $hash = sanitize($_POST['auth']); 20 $id = sanitize($_POST['id']); 21 $_zp_loggedin = $_zp_authority->checkAuthorization($hash, $id); 22} 23 24admin_securityChecks(UPLOAD_RIGHTS, $return = currentRelativeURL()); 25 26$folder = zp_apply_filter('admin_upload_process', sanitize_path($_POST['folder'])); 27$types = array_keys($_zp_extra_filetypes); 28if (function_exists('zip_open')) { 29 $types[] = 'ZIP'; 30} 31$types = array_merge($_zp_supported_images, $types); 32$types = zp_apply_filter('upload_filetypes', $types); 33 34$options = array( 35 'upload_dir' => $targetPath = ALBUM_FOLDER_SERVERPATH . internalToFilesystem($folder) . '/', 36 'upload_url' => imgSrcURI(ALBUM_FOLDER_WEBPATH . $folder) . '/', 37 'accept_file_types' => '/(' . implode('|\.', $types) . ')$/i' 38); 39 40$new = !is_dir($targetPath); 41if (!empty($folder)) { 42 if ($new) { 43 $rightsalbum = newAlbum(dirname($folder), true, true); 44 } else { 45 $rightsalbum = newAlbum($folder, true, true); 46 } 47 if ($rightsalbum->exists) { 48 if (!$rightsalbum->isMyItem(UPLOAD_RIGHTS)) { 49 if (!zp_apply_filter('admin_managed_albums_access', false, $return)) { 50 redirectURL(FULLWEBPATH . '/' . ZENFOLDER . '/admin.php'); 51 } 52 } 53 } else { 54 // upload to the root 55 if (!zp_loggedin(MANAGE_ALL_ALBUM_RIGHTS)) { 56 redirectURL(FULLWEBPATH . '/' . ZENFOLDER . '/admin.php'); 57 } 58 } 59 if ($new) { 60 mkdir_recursive($targetPath, FOLDER_MOD); 61 $album = newAlbum($folder); 62 $album->setShow((int) !empty($_POST['publishalbum'])); 63 $album->setTitle(sanitize($_POST['albumtitle'])); 64 $album->setOwner($_zp_current_admin_obj->getUser()); 65 $album->save(); 66 } 67 @chmod($targetPath, FOLDER_MOD); 68} 69 70class UploadHandler { 71 72 private $options; 73 74 function __construct($options = null) { 75 $this->options = array( 76 'script_url' => $_SERVER['PHP_SELF'], 77 'upload_dir' => dirname(__FILE__) . '/files/', 78 'upload_url' => dirname($_SERVER['PHP_SELF']) . '/files/', 79 'param_name' => 'files', 80 // The php.ini settings upload_max_filesize and post_max_size 81 // take precedence over the following max_file_size setting: 82 'max_file_size' => null, 83 'min_file_size' => 1, 84 'accept_file_types' => '/.+$/i', 85 'max_number_of_files' => null, 86 'discard_aborted_uploads' => true, 87 'image_versions' => array( 88 // Uncomment the following version to restrict the size of 89 // uploaded images. You can also add additional versions with 90 // their own upload directories: 91 /* 92 'large' => array( 93 'upload_dir' => dirname(__FILE__).'/files/', 94 'upload_url' => dirname($_SERVER['PHP_SELF']).'/files/', 95 'max_width' => 1920, 96 'max_height' => 1200 97 ), 98 99 'thumbnail' => array( 100 'upload_dir' => dirname(__FILE__).'/thumbnails/', 101 'upload_url' => dirname($_SERVER['PHP_SELF']).'/thumbnails/', 102 'max_width' => 80, 103 'max_height' => 80 104 ) 105 */ 106 ) 107 ); 108 if ($options) { 109 $this->options = array_replace_recursive($this->options, $options); 110 } 111 } 112 113 private function get_file_object($file_name) { 114 $file_path = $this->options['upload_dir'] . $file_name; 115 if (is_file($file_path) && $file_name[0] !== '.') { 116 $file = new stdClass(); 117 $file->name = $file_name; 118 $file->size = filesize($file_path); 119 $file->url = $this->options['upload_url'] . rawurlencode($file->name); 120 foreach ($this->options['image_versions'] as $version => $options) { 121 if (is_file($options['upload_dir'] . $file_name)) { 122 $file->{$version . '_url'} = $options['upload_url'] 123 . rawurlencode($file->name); 124 } 125 } 126 $file->delete_url = $this->options['script_url'] 127 . '?file=' . rawurlencode($file->name); 128 $file->delete_type = 'DELETE'; 129 return $file; 130 } 131 return null; 132 } 133 134 private function get_file_objects() { 135 return array_values(array_filter(array_map( 136 array($this, 'get_file_object'), scandir($this->options['upload_dir']) 137 ))); 138 } 139 140 private function create_scaled_image($file_name, $options) { 141 $file_path = $this->options['upload_dir'] . $file_name; 142 $new_file_path = $options['upload_dir'] . $file_name; 143 list($img_width, $img_height) = @getimagesize($file_path); 144 if (!$img_width || !$img_height) { 145 return false; 146 } 147 $scale = min( 148 $options['max_width'] / $img_width, $options['max_height'] / $img_height 149 ); 150 if ($scale > 1) { 151 $scale = 1; 152 } 153 $new_width = $img_width * $scale; 154 $new_height = $img_height * $scale; 155 $new_img = @imagecreatetruecolor($new_width, $new_height); 156 switch (strtolower(substr(strrchr($file_name, '.'), 1))) { 157 case 'jpg': 158 case 'jpeg': 159 $src_img = @imagecreatefromjpeg($file_path); 160 $write_image = 'imagejpeg'; 161 break; 162 case 'gif': 163 @imagecolortransparent($new_img, @imagecolorallocate($new_img, 0, 0, 0)); 164 $src_img = @imagecreatefromgif($file_path); 165 $write_image = 'imagegif'; 166 break; 167 case 'png': 168 @imagecolortransparent($new_img, @imagecolorallocate($new_img, 0, 0, 0)); 169 @imagealphablending($new_img, false); 170 @imagesavealpha($new_img, true); 171 $src_img = @imagecreatefrompng($file_path); 172 $write_image = 'imagepng'; 173 break; 174 default: 175 $src_img = $image_method = null; 176 } 177 $success = $src_img && @imagecopyresampled( 178 $new_img, $src_img, 0, 0, 0, 0, $new_width, $new_height, $img_width, $img_height 179 ) && $write_image($new_img, $new_file_path); 180 // Free up memory (imagedestroy does not delete files): 181 @imagedestroy($src_img); 182 @imagedestroy($new_img); 183 return $success; 184 } 185 186 private function has_error($uploaded_file, $file, $error) { 187 if ($error) { 188 return $error; 189 } 190 if (!preg_match($this->options['accept_file_types'], $file->name)) { 191 return 'acceptFileTypes'; 192 } 193 if ($uploaded_file && is_uploaded_file($uploaded_file)) { 194 $file_size = filesize($uploaded_file); 195 } else { 196 $file_size = $_SERVER['CONTENT_LENGTH']; 197 } 198 if ($this->options['max_file_size'] && ( 199 $file_size > $this->options['max_file_size'] || 200 $file->size > $this->options['max_file_size']) 201 ) { 202 return 'maxFileSize'; 203 } 204 if ($this->options['min_file_size'] && 205 $file_size < $this->options['min_file_size']) { 206 return 'minFileSize'; 207 } 208 if (is_int($this->options['max_number_of_files']) && ( 209 count($this->get_file_objects()) >= $this->options['max_number_of_files']) 210 ) { 211 return 'maxNumberOfFiles'; 212 } 213 return $error; 214 } 215 216 private function trim_file_name($name, $type) { 217 // Remove path information and dots around the filename, to prevent uploading 218 // into different directories or replacing hidden system files. 219 // Also remove control characters and spaces (\x00..\x20) around the filename: 220 $file_name = trim(basename(stripslashes($name)), ".\x00..\x20"); 221 // Add missing file extension for known image types: 222 if (strpos($file_name, '.') === false && 223 preg_match('/^image\/(gif|jpe?g|png)/', $type, $matches)) { 224 $file_name .= '.' . $matches[1]; 225 } 226 return $file_name; 227 } 228 229 private function handle_file_upload($uploaded_file, $name, $size, $type, $error) { 230 global $folder, $targetPath, $_zp_current_admin_obj; 231 $file = new stdClass(); 232 $name = $this->trim_file_name($name, $type); 233 $seoname = seoFriendly($name); 234 if (strrpos($seoname, '.') === 0) 235 $seoname = sha1($name) . $seoname; // soe stripped out all the name. 236 $targetFile = $targetPath . '/' . internalToFilesystem($seoname); 237 if (file_exists($targetFile)) { 238 $append = '_' . time(); 239 $seoname = stripSuffix($seoname) . $append . '.' . getSuffix($seoname); 240 $targetFile = $targetPath . '/' . internalToFilesystem($seoname); 241 } 242 $file->name = $seoname; 243 244 $file->size = intval($size); 245 $file->type = $type; 246 $error = $this->has_error($uploaded_file, $file, $error); 247 if (!$error && $file->name) { 248 $file_path = $this->options['upload_dir'] . $file->name; 249 $append_file = !$this->options['discard_aborted_uploads'] && 250 is_file($file_path) && $file->size > filesize($file_path); 251 clearstatcache(); 252 if ($uploaded_file && is_uploaded_file($uploaded_file)) { 253 // multipart/formdata uploads (POST method uploads) 254 if ($append_file) { 255 file_put_contents($file_path, fopen($uploaded_file, 'r'), FILE_APPEND); 256 } else { 257 move_uploaded_file($uploaded_file, $file_path); 258 if (Gallery::validImage($name) || Gallery::validImageAlt($name)) { 259 @chmod($targetFile, FILE_MOD); 260 $album = newAlbum($folder); 261 $image = newImage($album, $seoname); 262 $image->setOwner($_zp_current_admin_obj->getUser()); 263 if ($name != $seoname && $image->getTitle() == substr($seoname, 0, strrpos($seoname, '.'))) { 264 $image->setTitle(stripSuffix($name, '.')); 265 } 266 $image->save(); 267 } else if (is_zip($targetFile)) { 268 unzip($targetFile, $targetPath); 269 unlink($targetFile); 270 } else { 271 $file->error = $error = UPLOAD_ERR_EXTENSION; // invalid file uploaded 272 } 273 } 274 } else { 275 // Non-multipart uploads (PUT method support) 276 file_put_contents( 277 $file_path, fopen('php://input', 'r'), $append_file ? FILE_APPEND : 0); 278 } 279 $file_size = filesize($file_path); 280 if ($file_size === $file->size) { 281 $file->url = $this->options['upload_url'] . rawurlencode($file->name); 282 foreach ($this->options['image_versions'] as $version => $options) { 283 if ($this->create_scaled_image($file->name, $options)) { 284 $file->{$version . '_url'} = $options['upload_url'] . rawurlencode($file->name); 285 } 286 } 287 } else if ($this->options['discard_aborted_uploads']) { 288 @chmod($file_path, 0777); 289 unlink($file_path); 290 $file->error = 'abort'; 291 } 292 $file->size = $file_size; 293 $file->delete_url = $this->options['script_url'] . '?file=' . rawurlencode($file->name); 294 $file->delete_type = 'DELETE'; 295 } else { 296 $file->error = $error; 297 } 298 return $file; 299 } 300 301 public function get() { 302 $file_name = isset($_REQUEST['file']) ? 303 basename(stripslashes($_REQUEST['file'])) : null; 304 if ($file_name) { 305 $info = $this->get_file_object($file_name); 306 } else { 307 $info = $this->get_file_objects(); 308 } 309 header('Content-type: application/json'); 310 echo json_encode($info); 311 } 312 313 public function post() { 314 $upload = isset($_FILES[$this->options['param_name']]) ? 315 $_FILES[$this->options['param_name']] : null; 316 $info = array(); 317 if ($upload && is_array($upload['tmp_name'])) { 318 foreach ($upload['tmp_name'] as $index => $value) { 319 $info[] = $this->handle_file_upload( 320 $upload['tmp_name'][$index], isset($_SERVER['HTTP_X_FILE_NAME']) ? 321 $_SERVER['HTTP_X_FILE_NAME'] : $upload['name'][$index], isset($_SERVER['HTTP_X_FILE_SIZE']) ? 322 $_SERVER['HTTP_X_FILE_SIZE'] : $upload['size'][$index], isset($_SERVER['HTTP_X_FILE_TYPE']) ? 323 $_SERVER['HTTP_X_FILE_TYPE'] : $upload['type'][$index], $upload['error'][$index] 324 ); 325 } 326 } elseif ($upload) { 327 $info[] = $this->handle_file_upload( 328 $upload['tmp_name'], isset($_SERVER['HTTP_X_FILE_NAME']) ? 329 $_SERVER['HTTP_X_FILE_NAME'] : $upload['name'], isset($_SERVER['HTTP_X_FILE_SIZE']) ? 330 $_SERVER['HTTP_X_FILE_SIZE'] : $upload['size'], isset($_SERVER['HTTP_X_FILE_TYPE']) ? 331 $_SERVER['HTTP_X_FILE_TYPE'] : $upload['type'], $upload['error'] 332 ); 333 } 334 header('Vary: Accept'); 335 if (isset($_SERVER['HTTP_ACCEPT']) && (strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false)) { 336 header('Content-type: application/json'); 337 } else { 338 header('Content-type: text/plain'); 339 } 340 echo json_encode($info); 341 } 342 343} 344 345$upload_handler = new UploadHandler($options); 346 347header('Pragma: no-cache'); 348header('Cache-Control: private, no-cache'); 349header('Content-Disposition: inline; filename="files.json"'); 350header('X-Content-Type-Options: nosniff'); 351 352switch ($_SERVER['REQUEST_METHOD']) { 353 case 'POST': 354 $upload_handler->post(); 355 break; 356 case 'OPTIONS': 357 break; 358 default: 359 header('HTTP/1.0 405 Method Not Allowed'); 360} 361?>