--- /dev/null
+<?php
+namespace wcf\action;
+use wcf\system\upload;
+
+/**
+ * Default implementation for file uploads using the AJAX-API.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2012 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage action
+ * @category Community Framework
+ */
+class AJAXUploadAction extends AJAXProxyAction {
+ /**
+ * @see wcf\action\IAction::readParameters()
+ */
+ public function readParameters() {
+ parent::readParameters();
+
+ $this->parameters['__files'] = UploadHandler::getUploadHandler('__files');
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\upload;
+
+/**
+ * Interface for file upload save strategies.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2012 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.upload
+ * @category Community Framework
+ */
+interface IUploadFileSaveStrategy {
+ /**
+ * Saves the given file.
+ *
+ * @param wcf\system\upload\UploadFile $uploadFile
+ */
+ public function save(UploadFile $uploadFile);
+}
--- /dev/null
+<?php
+namespace wcf\system\upload;
+
+/**
+ * Represents a file upload.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2012 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.upload
+ * @category Community Framework
+ */
+class UploadFile {
+ /**
+ * original file name
+ * @var string
+ */
+ protected $filename = '';
+
+ /**
+ * location of the uploaded file
+ * @var string
+ */
+ protected $location = '';
+
+ /**
+ * file size
+ * @var integer
+ */
+ protected $filesize = 0;
+
+ /**
+ * file upload error code
+ * @var integer
+ */
+ protected $errorCode = 0;
+
+ /**
+ * MIME type
+ * @var string
+ */
+ protected $mimeType = '';
+
+ /**
+ * validation error type
+ * @var string
+ */
+ protected $validationErrorType = '';
+
+ /**
+ * Creates a new UploadFile object.
+ *
+ * @param string $filename
+ * @param string $location
+ * @param integer $filesize
+ * @param integer $errorCode
+ * @param string $mimeType
+ */
+ public function __construct($filename, $location, $filesize, $errorCode = 0, $mimeType = '') {
+ $this->filename = $filename;
+ $this->location = $location;
+ $this->filesize = $filesize;
+ $this->errorCode = $errorCode;
+ $this->mimeType = $mimeType;
+ }
+
+ /**
+ * Returns the original file name.
+ *
+ * @return string
+ */
+ public function getFilename() {
+ return $this->name;
+ }
+
+ /**
+ * Returns the file location.
+ *
+ * @return string
+ */
+ public function getLocation() {
+ return $this->location;
+ }
+
+ /**
+ * Returns the file size.
+ *
+ * @return integer
+ */
+ public function getFilesize() {
+ return $this->filesize;
+ }
+
+ /**
+ * Returns the MIME type.
+ *
+ * @return string
+ */
+ public function getMimeType() {
+ return $this->mimeType;
+ }
+
+ /**
+ * Returns the error code.
+ *
+ * @return integer
+ */
+ public function getErrorCode() {
+ return $this->errorCode;
+ }
+
+ /**
+ * Validates the uploaded file. Returns true on success, otherwise false.
+ *
+ * @param integer $maxFilesize
+ * @param array<string> $fileExtensions
+ * @return boolean
+ */
+ public function validateFile($maxFilesize, array $fileExtensions) {
+
+ }
+
+ /**
+ * Returns the validation error type.
+ *
+ * @return string
+ */
+ public function getValidationErrorType() {
+ return $this->validationErrorType;
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\upload;
+
+/**
+ * Handles file uploads.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2012 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.upload
+ * @category Community Framework
+ */
+class UploadHandler {
+ /**
+ * list of uploaded files
+ * @var array<wcf\system\upload\UploadFile>
+ */
+ protected $files = array();
+
+ /**
+ * list of validation errors.
+ * @var array
+ */
+ protected $errors = array();
+
+ /**
+ * Creates a new UploadHandler object.
+ *
+ * @param array<mixed> $rawFileData
+ */
+ protected function __construct(array $rawFileData) {
+ if (is_array($rawFileData['name'])) {
+ // multiple uploads
+ for ($i = 0, $l = count($rawFileData['name']); $i < $l; $i++) {
+ $this->files[] = new UploadFile($rawFileData['name'][$i], $rawFileData['tmp_name'][$i], $rawFileData['filesize'][$i], $rawFileData['error'][$i], $rawFileData['type'][$i]);
+ }
+ }
+ else {
+ $this->files[] = new UploadFile($rawFileData['name'], $rawFileData['tmp_name'], $rawFileData['filesize'], $rawFileData['error'], $rawFileData['type']);
+ }
+ }
+
+ /**
+ * Returns the list of uploaded files.
+ *
+ * @return array<wcf\system\upload\UploadFile>
+ */
+ public function getFiles() {
+ return $this->files;
+ }
+
+ /**
+ * Validates the uploaded files. Returns true on success, otherwise false.
+ *
+ * @param integer $maxFilesize
+ * @param array<string> $fileExtensions
+ * @return boolean
+ */
+ public function validateFiles($maxFilesize, array $fileExtensions) {
+ $result = true;
+ foreach ($this->files as $file) {
+ if (!$file->validateFile($maxFilesize, $fileExtensions)) {
+ $this->errors[$file->getFilename()] = $file->getValidationErrorType();
+ $result = false;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Returns a list of validation errors.
+ *
+ * @return array
+ */
+ public function getErrors() {
+ return $this->errors;
+ }
+
+ /**
+ * Saves the uploaded files.
+ *
+ * @param wcf\system\upload\IUploadFileSaveStrategy $saveStrategy
+ */
+ public function saveFiles(IUploadFileSaveStrategy $saveStrategy) {
+ foreach ($this->files as $file) {
+ $saveStrategy->save($file);
+ }
+ }
+
+ /**
+ * Gets an upload handler instance.
+ *
+ * @param string $identifier
+ * @return wcf\system\upload\UploadHandler
+ */
+ public static function getUploadHandler($identifier) {
+ if (isset($_FILES[$identifier]) && is_array($_FILES[$identifier])) return new UploadHandler($_FILES[$identifier]);
+
+ return null;
+ }
+}