PageRenderTime 49ms CodeModel.GetById 11ms app.highlight 21ms RepoModel.GetById 12ms app.codeStats 1ms

/inc/classes/upload.class.php

https://github.com/Laurelai/tsukiboards
PHP | 439 lines | 369 code | 34 blank | 36 comment | 104 complexity | da6f57dd94c9ebff7aa873c6ed6a4bab MD5 | raw file
  1<?php
  2/*
  3 * This file is part of arcNET
  4 *
  5 * arcNET uses core code from Kusaba X and Oneechan
  6 *
  7 * tsukihi.me kusabax.cultnet.net oneechan.org
  8 *
  9 * arcNET is free software; you can redistribute it and/or modify it under the
 10 * terms of the GNU General Public License as published by the Free Software
 11 * Foundation; either version 2 of the License, or (at your option) any later
 12 * version.
 13 *
 14 * kusaba is distributed in the hope that it will be useful, but WITHOUT ANY
 15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU General Public License along with
 19 * kusaba; if not, write to the Free Software Foundation, Inc.,
 20 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 21 *
 22 * credits to jmyeom for improving this
 23 *
 24 */
 25
 26class Upload {
 27	var $file_name			= '';
 28	var $original_file_name	= '';
 29	var $file_type			= '';
 30	var $file_md5			= '';
 31	var $file_location		= '';
 32	var $file_thumb_location = '';
 33	var $file_is_special	= false;
 34	var $imgWidth			= 0;
 35	var $imgHeight			= 0;
 36	var $file_size			= 0;
 37	var $imgWidth_thumb		= 0;
 38	var $imgHeight_thumb	= 0;
 39	var $isreply			= false;
 40
 41	function HandleUpload() {
 42		global $tc_db, $board_class, $is_oekaki, $oekaki, $posting_class;
 43
 44		if (!$is_oekaki) {
 45			if ($board_class->board['type'] == 0 || $board_class->board['type'] == 2 || $board_class->board['type'] == 3) {
 46				$imagefile_name = isset($_FILES['imagefile']) ? $_FILES['imagefile']['name'] : '';
 47				if ($imagefile_name != '') {
 48					if (strpos($_FILES['imagefile']['name'], ',') != false) {
 49						exitWithErrorPage(_gettext('Please select only one image to upload.'));
 50					}
 51
 52					if ($_FILES['imagefile']['size'] > $board_class->board['maximagesize']) {
 53						exitWithErrorPage(sprintf(_gettext('Please make sure your file is smaller than %dB'), $board_class->board['maximagesize']));
 54					}
 55
 56					switch ($_FILES['imagefile']['error']) {
 57					case UPLOAD_ERR_OK:
 58						break;
 59					case UPLOAD_ERR_INI_SIZE:
 60						exitWithErrorPage(sprintf(_gettext('The uploaded file exceeds the upload_max_filesize directive (%s) in php.ini.')), ini_get('upload_max_filesize'));
 61						break;
 62					case UPLOAD_ERR_FORM_SIZE:
 63						exitWithErrorPage(sprintf(_gettext('Please make sure your file is smaller than %dB'), $board_class->board['maximagesize']));
 64						break;
 65					case UPLOAD_ERR_PARTIAL:
 66						exitWithErrorPage(_gettext('The uploaded file was only partially uploaded.'));
 67						break;
 68					case UPLOAD_ERR_NO_FILE:
 69						exitWithErrorPage(_gettext('No file was uploaded.'));
 70						break;
 71					case UPLOAD_ERR_NO_TMP_DIR:
 72						exitWithErrorPage(_gettext('Missing a temporary folder.'));
 73						break;
 74					case UPLOAD_ERR_CANT_WRITE:
 75						exitWithErrorPage(_gettext('Failed to write file to disk'));
 76						break;
 77					default:
 78						exitWithErrorPage(_gettext('Unknown File Error'));
 79					}
 80
 81					$this->file_type = preg_replace('/.*(\..+)/','\1',$_FILES['imagefile']['name']);
 82					if ($this->file_type == '.jpeg') {
 83						/* Fix for the rarely used 4-char format */
 84						$this->file_type = '.jpg';
 85					}
 86
 87					$pass = true;
 88					if (!is_file($_FILES['imagefile']['tmp_name']) || !is_readable($_FILES['imagefile']['tmp_name'])) {
 89						$pass = false;
 90					} else {
 91						if ($this->file_type == '.jpg' || $this->file_type == '.gif' || $this->file_type == '.png') {
 92							if (!@getimagesize($_FILES['imagefile']['tmp_name'])) {
 93								$pass = false;
 94							}
 95						}
 96					}
 97					if (!$pass) {
 98						exitWithErrorPage(_gettext('File transfer failure. Please go back and try again.'));
 99					}
100
101					$this->file_name = substr(htmlspecialchars(preg_replace('/(.*)\..+/','\1',$_FILES['imagefile']['name']), ENT_QUOTES), 0, 50);
102					$this->file_name = str_replace('.','_',$this->file_name);
103					$this->original_file_name = $this->file_name;
104					$this->file_md5 = md5_file($_FILES['imagefile']['tmp_name']);
105
106					$exists_thread = checkMd5($this->file_md5, $board_class->board['name'], $board_class->board['id']);
107					if (is_array($exists_thread)) {
108						exitWithErrorPage(_gettext('Duplicate file entry detected.'), sprintf(_gettext('Already posted %shere%s.'),'<a href="' . KU_BOARDSPATH . '/' . $board_class->board['name'] . '/res/' . $exists_thread[0] . '.html#' . $exists_thread[1] . '">','</a>'));
109					}
110
111					if (strtolower($this->file_type) == 'svg') {
112						require_once 'svg.class.php';
113						$svg = new Svg($_FILES['imagefile']['tmp_name']);
114						$this->imgWidth = $svg->width;
115						$this->imgHeight = $svg->height;
116					} else {
117						$imageDim = getimagesize($_FILES['imagefile']['tmp_name']);
118						$this->imgWidth = $imageDim[0];
119						$this->imgHeight = $imageDim[1];
120					}
121
122					$this->file_type = strtolower($this->file_type);
123					$this->file_size = $_FILES['imagefile']['size'];
124
125					$filetype_forcethumb = $tc_db->GetOne("SELECT " . KU_DBPREFIX . "filetypes.force_thumb FROM " . KU_DBPREFIX . "boards, " . KU_DBPREFIX . "filetypes, " . KU_DBPREFIX . "board_filetypes WHERE " . KU_DBPREFIX . "boards.id = " . KU_DBPREFIX . "board_filetypes.boardid AND " . KU_DBPREFIX . "filetypes.id = " . KU_DBPREFIX . "board_filetypes.typeid AND " . KU_DBPREFIX . "boards.name = '" . $board_class->board['name'] . "' and " . KU_DBPREFIX . "filetypes.filetype = '" . substr($this->file_type, 1) . "';");
126					if ($filetype_forcethumb != '') {
127						if ($filetype_forcethumb == 0) {
128							$this->file_name = time() . mt_rand(1, 99);
129
130							/* If this board has a load balance url and password configured for it, attempt to use it */
131							if ($board_class->board['loadbalanceurl'] != '' && $board_class->board['loadbalancepassword'] != '') {
132								require_once KU_ROOTDIR . 'inc/classes/loadbalancer.class.php';
133								$loadbalancer = new Load_Balancer;
134
135								$loadbalancer->url = $board_class->board['loadbalanceurl'];
136								$loadbalancer->password = $board_class->board['loadbalancepassword'];
137
138								$response = $loadbalancer->Send('thumbnail', base64_encode(file_get_contents($_FILES['imagefile']['tmp_name'])), 'src/' . $this->file_name . $this->file_type, 'thumb/' . $this->file_name . 's' . $this->file_type, 'thumb/' . $this->file_name . 'c' . $this->file_type, '', $this->isreply, true);
139
140								if ($response != 'failure' && $response != '') {
141									$response_unserialized = unserialize($response);
142
143									$this->imgWidth_thumb = $response_unserialized['imgw_thumb'];
144									$this->imgHeight_thumb = $response_unserialized['imgh_thumb'];
145
146									$imageused = true;
147								} else {
148									exitWithErrorPage(_gettext('File was not properly thumbnailed').': ' . $response);
149								}
150							/* Otherwise, use this script alone */
151							} else {
152								$this->file_location = KU_BOARDSDIR . $board_class->board['name'] . '/src/' . $this->file_name . $this->file_type;
153								$this->file_thumb_location = KU_BOARDSDIR . $board_class->board['name'] . '/thumb/' . $this->file_name . 's' . $this->file_type;
154								$this->file_thumb_cat_location = KU_BOARDSDIR . $board_class->board['name'] . '/thumb/' . $this->file_name . 'c' . $this->file_type;
155
156								if (!move_uploaded_file($_FILES['imagefile']['tmp_name'], $this->file_location)) {
157									exitWithErrorPage(_gettext('Could not copy uploaded image.'));
158								}
159								chmod($this->file_location, 0644);
160
161								if ($_FILES['imagefile']['size'] == filesize($this->file_location)) {
162
163									if( $posting_class->IsSpoilerImage() )
164									{
165										// RH - Spoiler image thumbnailing. Really we should have a single static image path, but for now it's easier to stupidly
166										// create copies with the names other parts of arcNet expect ... I guess it should at least be small (optimised e.g. with pngcrush)
167										$spoiler = KU_ROOTDIR . 'spoiler.png';
168										$spoiler_catalog = KU_ROOTDIR . 'spoiler_catalog.png';
169										copy( $spoiler, $this->file_thumb_location );
170										copy( $spoiler_catalog, $this->file_thumb_cat_location );
171
172										if ( ! $this->isreply ) {
173											$this->imgWidth_thumb = 200;	// Spoiler posted fullsize, as OP of a thread
174											$this->imgHeight_thumb = 162;
175										} else {
176											$this->imgWidth_thumb = 125;	// In-thread images are smaller
177											$this->imgHeight_thumb =  101;
178										}
179										$imageused = true;
180									}
181									else
182									{
183										// Normal thumbnailing
184										if ((!$this->isreply && ($this->imgWidth > KU_THUMBWIDTH || $this->imgHeight > KU_THUMBHEIGHT)) || ($this->isreply && ($this->imgWidth > KU_REPLYTHUMBWIDTH || $this->imgHeight > KU_REPLYTHUMBHEIGHT))) {
185											if (!$this->isreply) {
186												if (!createThumbnail($this->file_location, $this->file_thumb_location, KU_THUMBWIDTH, KU_THUMBHEIGHT)) {
187													exitWithErrorPage(_gettext('Could not create thumbnail.'));
188												}
189											} else {
190												if (!createThumbnail($this->file_location, $this->file_thumb_location, KU_REPLYTHUMBWIDTH, KU_REPLYTHUMBHEIGHT)) {
191													exitWithErrorPage(_gettext('Could not create thumbnail.'));
192												}
193											}
194										} else {
195											if (!createThumbnail($this->file_location, $this->file_thumb_location, $this->imgWidth, $this->imgHeight)) {
196												exitWithErrorPage(_gettext('Could not create thumbnail.'));
197											}
198										}
199										if (!createThumbnail($this->file_location, $this->file_thumb_cat_location, KU_CATTHUMBWIDTH, KU_CATTHUMBHEIGHT)) {
200											exitWithErrorPage(_gettext('Could not create thumbnail.'));
201										}
202										$imageDim_thumb = getimagesize($this->file_thumb_location);
203										$this->imgWidth_thumb = $imageDim_thumb[0];
204										$this->imgHeight_thumb = $imageDim_thumb[1];
205										$imageused = true;
206									}
207								}
208								else
209								{
210									exitWithErrorPage(_gettext('File was not fully uploaded. Please go back and try again.'));
211								}
212							}
213						} else {
214							/* Fetch the mime requirement for this special filetype */
215							$filetype_required_mime = $tc_db->GetOne("SELECT `mime` FROM `" . KU_DBPREFIX . "filetypes` WHERE `filetype` = " . $tc_db->qstr(substr($this->file_type, 1)));
216
217							$this->file_name = htmlspecialchars_decode($this->file_name, ENT_QUOTES);
218							$this->file_name = stripslashes($this->file_name);
219							$this->file_name = str_replace("\x80", " ", $this->file_name);					
220							$this->file_name = str_replace(' ', '_', $this->file_name);
221							$this->file_name = str_replace('#', '(number)', $this->file_name);
222							$this->file_name = str_replace('@', '(at)', $this->file_name);
223							$this->file_name = str_replace('/', '(fwslash)', $this->file_name);
224							$this->file_name = str_replace('\\', '(bkslash)', $this->file_name);
225
226							/* If this board has a load balance url and password configured for it, attempt to use it */
227							if ($board_class->board['loadbalanceurl'] != '' && $board_class->board['loadbalancepassword'] != '') {
228								require_once KU_ROOTDIR . 'inc/classes/loadbalancer.class.php';
229								$loadbalancer = new Load_Balancer;
230
231								$loadbalancer->url = $board_class->board['loadbalanceurl'];
232								$loadbalancer->password = $board_class->board['loadbalancepassword'];
233
234								if ($filetype_required_mime != '') {
235									$checkmime = $filetype_required_mime;
236								} else {
237									$checkmime = '';
238								}
239
240								$response = $loadbalancer->Send('direct', $_FILES['imagefile']['tmp_name'], 'src/' . $this->file_name . $this->file_type, '', '', $checkmime, false, true);
241
242								$this->file_is_special = true;
243							/* Otherwise, use this script alone */
244							} else {
245								$this->file_location = KU_BOARDSDIR . $board_class->board['name'] . '/src/' . $this->file_name . $this->file_type;
246								
247								if (file_exists($this->file_location)) {
248									exitWithErrorPage(_gettext('A file by that name already exists'));
249									die();
250								}
251								
252								if($this->file_type == '.mp3') {
253									require_once(KU_ROOTDIR . 'lib/getid3/getid3.php');
254
255									$getID3 = new getID3;
256									$getID3->analyze($_FILES['imagefile']['tmp_name']);
257									if (isset($getID3->info['id3v2']['APIC'][0]['data']) && isset($getID3->info['id3v2']['APIC'][0]['image_mime'])) {
258										$source_data = $getID3->info['id3v2']['APIC'][0]['data'];
259										$mime = $getID3->info['id3v2']['APIC'][0]['image_mime'];
260									}
261									elseif (isset($getID3->info['id3v2']['PIC'][0]['data']) && isset($getID3->info['id3v2']['PIC'][0]['image_mime'])) {
262										$source_data = $getID3->info['id3v2']['PIC'][0]['data'];
263										$mime = $getID3->info['id3v2']['PIC'][0]['image_mime'];
264									}
265
266									if($source_data) {
267										$im = imagecreatefromstring($source_data);
268										if (preg_match("/png/", $mime)) {
269											$ext = ".png";
270											imagepng($im,$this->file_location.".tmp",0,PNG_ALL_FILTERS);
271										} else if (preg_match("/jpg|jpeg/", $mime)) {
272											$ext = ".jpg";
273											imagejpeg($im, $this->file_location.".tmp");
274										} else if (preg_match("/gif/", $mime)) {
275											$ext = ".gif";
276											imagegif($im, $this->file_location.".tmp");
277										}
278										$this->file_thumb_location = KU_BOARDSDIR . $board_class->board['name'] . '/thumb/' . $this->file_name .'s'. $ext;
279										if (!$this->isreply) {
280											if (!createThumbnail($this->file_location.".tmp", $this->file_thumb_location, KU_THUMBWIDTH, KU_THUMBHEIGHT)) {
281												exitWithErrorPage(_gettext('Could not create thumbnail.'));
282											}
283										} else {
284											if (!createThumbnail($this->file_location.".tmp", $this->file_thumb_location, KU_REPLYTHUMBWIDTH, KU_REPLYTHUMBHEIGHT)) {
285												exitWithErrorPage(_gettext('Could not create thumbnail.'));
286											}
287										}
288										$imageDim_thumb = getimagesize($this->file_thumb_location);
289										$this->imgWidth_thumb = $imageDim_thumb[0];
290										$this->imgHeight_thumb = $imageDim_thumb[1];
291										$imageused = true;
292										unlink($this->file_location.".tmp");
293									}
294
295
296								}
297
298								/* Move the file from the post data to the server */
299								if (!move_uploaded_file($_FILES['imagefile']['tmp_name'], $this->file_location)) {
300									exitWithErrorPage(_gettext('Could not copy uploaded image.'));
301								}
302
303								/* Check if the filetype provided comes with a MIME restriction */
304								if ($filetype_required_mime != '') {
305									/* Check if the MIMEs don't match up */
306									if (mime_content_type($this->file_location) != $filetype_required_mime) {
307										/* Delete the file we just uploaded and kill the script */
308										unlink($this->file_location);
309										exitWithErrorPage(_gettext('Invalid MIME type for this filetype.'));
310									}
311								}
312
313								/* Make sure the entire file was uploaded */
314								if ($_FILES['imagefile']['size'] == filesize($this->file_location)) {
315									$imageused = true;
316								} else {
317									exitWithErrorPage(_gettext('File transfer failure. Please go back and try again.'));
318								}
319
320								/* Flag that the file used isn't an internally supported type */
321								$this->file_is_special = true;
322							}
323						}
324					} else {
325						exitWithErrorPage(_gettext('Sorry, that filetype is not allowed on this board.'));
326					}
327				} elseif (isset($_POST['embed'])) {
328					if ($_POST['embed'] != '') {
329						$_POST['embed'] = strip_tags(substr($_POST['embed'], 0, 20));
330						$video_id = $_POST['embed'];
331						$this->file_name = $video_id;
332
333						if ($video_id != '' && strpos($video_id, '@') == false && strpos($video_id, '&') == false) {
334
335							$embeds = $tc_db->GetAll("SELECT HIGH_PRIORITY * FROM `" . KU_DBPREFIX . "embeds`");
336							$worked = false;
337
338							foreach ($embeds as $line) {
339								if ((strtolower($_POST['embedtype']) == strtolower($line['name'])) && in_array($line['filetype'], explode(',', $board_class->board['embeds_allowed']))) {
340									$worked = true;
341									$videourl_start = $line['videourl'];
342									$this->file_type = '.' . strtolower($line['filetype']);
343								}
344							}
345
346							if (!$worked) {
347								exitWithErrorPage(_gettext('Invalid video type.'));
348							}
349
350							$results = $tc_db->GetOne("SELECT COUNT(*) FROM `" . KU_DBPREFIX . "posts` WHERE `boardid` = " . $board_class->board['id'] . " AND `file` = " . $tc_db->qstr($video_id) . " AND `IS_DELETED` = 0");
351							if ($results[0] == 0) {
352								$video_check = check_link($videourl_start . $video_id);
353								switch ($video_check[1]) {
354									case 404:
355										exitWithErrorPage(_gettext('Unable to connect to') .': '. $videourl_start . $video_id);
356										break;
357									case 303:
358										exitWithErrorPage(_gettext('Invalid video ID.'));
359										break;
360									case 302:
361										// Continue
362										break;
363									case 301:
364										// Continue
365										break;
366									case 200:
367										// Continue
368										break;
369									default:
370										exitWithErrorPage(_gettext('Invalid response code ') .':'. $video_check[1]);
371										break;
372								}
373							} else {
374								$results = $tc_db->GetAll("SELECT `id`,`parentid` FROM `" . KU_DBPREFIX . "posts` WHERE `boardid` = " . $board_class->board['id'] . " AND `file` = " . $tc_db->qstr($video_id) . " AND `IS_DELETED` = 0 LIMIT 1");
375								foreach ($results as $line) {
376									$real_threadid = ($line[1] == 0) ? $line[0] : $line[1];
377									exitWithErrorPage(sprintf(_gettext('That video ID has already been posted %shere%s.'),'<a href="' . KU_BOARDSFOLDER . '/' . $board_class->board['name'] . '/res/' . $real_threadid . '.html#' . $line[1] . '">','</a>'));
378								}
379							}
380						} else {
381							exitWithErrorPage(_gettext('Invalid ID'));
382						}
383					}
384				}
385			}
386		} else {
387			$this->file_name = time() . mt_rand(1, 99);
388			$this->original_file_name = $this->file_name;
389			$this->file_md5 = md5_file($oekaki);
390			$this->file_type = '.png';
391			$this->file_size = filesize($oekaki);
392			$imageDim = getimagesize($oekaki);
393			$this->imgWidth = $imageDim[0];
394			$this->imgHeight = $imageDim[1];
395
396			if (!copy($oekaki, KU_BOARDSDIR . $board_class->board['name'] . '/src/' . $this->file_name . $this->file_type)) {
397				exitWithErrorPage(_gettext('Could not copy uploaded image.'));
398			}
399
400			$oekaki_animation = substr($oekaki, 0, -4) . '.pch';
401			if (file_exists($oekaki_animation)) {
402				if (!copy($oekaki_animation, KU_BOARDSDIR . $board_class->board['name'] . '/src/' . $this->file_name . '.pch')) {
403					exitWithErrorPage(_gettext('Could not copy animation.'));
404				}
405				unlink($oekaki_animation);
406			}
407
408			$thumbpath = KU_BOARDSDIR . $board_class->board['name'] . '/thumb/' . $this->file_name . 's' . $this->file_type;
409			$thumbpath_cat = KU_BOARDSDIR . $board_class->board['name'] . '/thumb/' . $this->file_name . 'c' . $this->file_type;
410			if (
411				(!$this->isreply && ($this->imgWidth > KU_THUMBWIDTH || $this->imgHeight > KU_THUMBHEIGHT)) ||
412				($this->isreply && ($this->imgWidth > KU_REPLYTHUMBWIDTH || $this->imgHeight > KU_REPLYTHUMBHEIGHT))
413			) {
414				if (!$this->isreply) {
415					if (!createThumbnail($oekaki, $thumbpath, KU_THUMBWIDTH, KU_THUMBHEIGHT)) {
416						exitWithErrorPage(_gettext('Could not create thumbnail.'));
417					}
418				} else {
419					if (!createThumbnail($oekaki, $thumbpath, KU_REPLYTHUMBWIDTH, KU_REPLYTHUMBHEIGHT)) {
420						exitWithErrorPage(_gettext('Could not create thumbnail.'));
421					}
422				}
423			} else {
424				if (!createThumbnail($oekaki, $thumbpath, $this->imgWidth, $this->imgHeight)) {
425					exitWithErrorPage(_gettext('Could not create thumbnail.'));
426				}
427			}
428			if (!createThumbnail($oekaki, $thumbpath_cat, KU_CATTHUMBWIDTH, KU_CATTHUMBHEIGHT)) {
429				exitWithErrorPage(_gettext('Could not create thumbnail.'));
430			}
431
432			$imgDim_thumb = getimagesize($thumbpath);
433			$this->imgWidth_thumb = $imgDim_thumb[0];
434			$this->imgHeight_thumb = $imgDim_thumb[1];
435			unlink($oekaki);
436		}
437	}
438}
439?>