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