public function check() { $user = KunenaUserHelper::get($this->userid); $message = KunenaForumMessageHelper::get($this->mesid); if ($this->userid != 0 && !$user->exists()) { $this->setError(JText::sprintf('COM_KUNENA_LIB_TABLE_ATTACHMENTS_ERROR_USER_INVALID', (int) $user->userid)); } if ($message->id && !$message->exists()) { $this->setError(JText::sprintf('COM_KUNENA_LIB_TABLE_ATTACHMENTS_ERROR_MESSAGE_INVALID', (int) $message->id)); } $this->folder = trim($this->folder, '/'); if (!$this->folder) { $this->setError(JText::_('COM_KUNENA_LIB_TABLE_ATTACHMENTS_ERROR_NO_FOLDER')); } if (!$this->filename) { $this->setError(JText::_('COM_KUNENA_LIB_TABLE_ATTACHMENTS_ERROR_NO_FILENAME')); } if (!$this->filename_real) { $this->filename_real = $this->filename; } $file = JPATH_ROOT . "/{$this->folder}/{$this->filename}"; if (!is_file($file)) { $this->setError(JText::sprintf('COM_KUNENA_LIB_TABLE_ATTACHMENTS_ERROR_FILE_MISSING', "{$this->folder}/{$this->filename}")); } else { if (!$this->hash) { $this->hash = md5_file($file); } if (!$this->size) { $this->size = filesize($file); } if (!$this->filetype) { $this->filetype = KunenaFile::getMime($file); } } return $this->getError() == ''; }
/** * Upload a file via AJAX, supports chunks and fallback to regular file upload. * * @param array $options Upload options. * * @return array Updated options. * @throws Exception|RuntimeException */ public function ajaxUpload(array $options) { static $defaults = array('completed' => false, 'filename' => null, 'size' => 0, 'mime' => null, 'hash' => null, 'chunkStart' => 0, 'chunkEnd' => 0); $options += $defaults; $config = KunenaConfig::getInstance(); $exception = null; $in = null; $out = null; $size = $bytes = 0; $outFile = null; // Look for the content type header if (isset($_SERVER['HTTP_CONTENT_TYPE'])) { $contentType = $_SERVER['HTTP_CONTENT_TYPE']; } elseif (isset($_SERVER['CONTENT_TYPE'])) { $contentType = $_SERVER['CONTENT_TYPE']; } else { $contentType = ''; } try { // Set filename for future queries. $this->filename = $options['filename']; $folder = $this->getFolder(); // Create target directory if it does not exist. if (!KunenaFolder::exists($folder) && !KunenaFolder::create($folder)) { throw new RuntimeException(JText::_('Failed to create upload directory.'), 500); } // Calculate temporary filename. $outFile = $this->getProtectedFile(); if ($options['chunkEnd'] > $options['size'] || $options['chunkStart'] > $options['chunkEnd']) { throw new RuntimeException(JText::_('COM_KUNENA_UPLOAD_ERROR_EXTRA_CHUNK'), 400); } if ($options['size'] > max($config->filesize, $config->imagesize) * 1024) { throw new RuntimeException(JText::sprintf('COM_KUNENA_UPLOAD_ERROR_SIZE_X', $this->bytes($options['size'])), 400); } if (strpos($contentType, 'multipart') !== false) { // Older WebKit browsers didn't support multi-part in HTML5. $exception = $this->checkUpload($_FILES['file']); if ($exception) { throw $exception; } $in = fopen($_FILES['file']['tmp_name'], 'rb'); } else { // Multi-part upload. $in = fopen('php://input', 'rb'); } if (!$in) { throw new RuntimeException(JText::_('Failed to open upload input stream.'), 500); } // Open temporary file. $out = fopen($outFile, !$options['chunkStart'] ? 'wb' : 'r+b'); if (!$out) { throw new RuntimeException(JText::_('Failed to open upload output stream.'), 500); } // Get current size for the file. $stat = fstat($out); if (!$stat) { throw new RuntimeException(JText::_('COM_KUNENA_UPLOAD_ERROR_STAT', $options['filename']), 500); } $size = $stat['size']; if ($options['chunkStart'] > $size) { throw new RuntimeException(JText::sprintf('Missing data chunk at location %d.', $size), 500); } fseek($out, $options['chunkStart']); while (!feof($in)) { // Set script execution time to 8 seconds in order to interrupt stalled file transfers (< 1kb/sec). // Not sure if it works, though, needs some testing. :) @set_time_limit(8); $buff = fread($in, 8192); if ($buff === false) { throw new RuntimeException(JText::_('Failed to read from upload input stream.'), 500); } $bytes = fwrite($out, $buff); if ($bytes === false) { throw new RuntimeException(JText::_('Failed to write into upload output stream.'), 500); } $size += $bytes; if ($size > max($config->filesize, $config->imagesize) * 1024) { throw new RuntimeException(JText::sprintf('COM_KUNENA_UPLOAD_ERROR_SIZE_X', $this->bytes($size)), 400); } } } catch (Exception $exception) { } // Reset script execution time. @set_time_limit(25); if ($in) { fclose($in); } if ($out) { fclose($out); } if ($exception instanceof Exception) { $this->cleanup(); throw $exception; } // Generate response. if (is_null($options['size']) && $size || $size === $options['size']) { $options['size'] = (int) $size; $options['completed'] = true; } $options['chunkStart'] = (int) $size; $options['chunkEnd'] = min($size + 1024 * 1024, $size + $this->getMaxSize(), max($size, $options['size'], is_null($options['size']) ? $this->getMaxSize() : 0)) - 1; if ($options['completed']) { $options['mime'] = KunenaFile::getMime($outFile); $options['hash'] = md5_file($outFile); } else { if ($size) { $options['mime'] = KunenaFile::getMime($outFile); } } return $options; }