diff options
Diffstat (limited to 'storage-backend')
-rw-r--r-- | storage-backend/.htaccess | 3 | ||||
-rw-r--r-- | storage-backend/index.php | 139 |
2 files changed, 142 insertions, 0 deletions
diff --git a/storage-backend/.htaccess b/storage-backend/.htaccess new file mode 100644 index 0000000..6655c30 --- /dev/null +++ b/storage-backend/.htaccess @@ -0,0 +1,3 @@ +RewriteEngine on +RewriteCond %{REQUEST_METHOD} =PUT +RewriteRule ^(.*)$ index.php?uri=$1 [L,QSA] diff --git a/storage-backend/index.php b/storage-backend/index.php new file mode 100644 index 0000000..3a2668a --- /dev/null +++ b/storage-backend/index.php @@ -0,0 +1,139 @@ +<?php +/* + * This script serves as storing backend for the xmpp extension + * XEP-0313 Http Upload + */ + +$method = $_SERVER['REQUEST_METHOD']; + +// Load configuration +$config = require('config.php'); + +switch ($method) { + case 'POST': + // parse post parameters + // check if all parameters are present - return 400 (bad request) if a parameter is missing / empty + $xmppServerKey = getMandatoryPostParameter('xmpp_server_key'); + $filename = getMandatoryPostParameter('filename'); + $filesize = getMandatoryPostParameter('size'); + $type = getMandatoryPostParameter('content_type'); + $userJid = getMandatoryPostParameter('user_jid'); + // check file size - return 406 (not acceptable) if file too large + if ($filesize > $config['max_upload_file_size']) { + sendHttpErrorCodeAndMessage(406, 'File too large. Maximum file size: '.$config['max_upload_file_size']); + } + // check file name - return 406 (not acceptable) if file contains invalid characters + foreach ($config['invalid_characters_in_filename'] as $invalidCharacter) { + if (stripos($filename, $invalidCharacter) !== false) { + sendHttpErrorCodeAndMessage(406, 'Invalid character found in filename.'); + } + } + // generate slot uuid, register slot uuid and expected file size and expected mime type + $basePath = $config['storage_base_path']; + $slotUUID = generate_uuid(); + registerSlot($slotUUID, $filename, $filesize, $type, $userJid, $config); + if (!mkdir(getUploadFilePath($slotUUID, $config))) { + sendHttpErrorCodeAndMessage(500, "Could not create directory for upload."); + } + // return 200 for success and get / put url Json formatted ( ['get'=>url, 'put'=>url] ) + $result = array('put' => $config['base_url_put'].$slotUUID.'/'.$filename, + 'get' => $config['base_url_get'].$slotUUID.'/'.$filename); + echo json_encode($result); + break; + case 'PUT': + // check slot uuid - return 403 if not existing + $uri = $_SERVER["REQUEST_URI"]; + $slotUUID = getUUIDFromUri($uri); + $filename = getFilenameFromUri($uri); + $uploadFilePath = getUploadFilePath($slotUUID, $config, $filename); + if (file_exists($uploadFilePath)) { + sendHttpErrorCodeAndMessage(403, "The slot was already used."); + } + if (!slotExists($slotUUID, $config)) { + sendHttpErrorCodeAndMessage(403, "The slot does not exist."); + } + $slotParameters = require(getSlotFilePath($slotUUID, $config)); + // save file + $incomingFileStream = fopen("php://input", "r"); + $targetFileStream = fopen($uploadFilePath, "w"); + $uploadedFilesize = stream_copy_to_stream($incomingFileStream, $targetFileStream); + fclose($targetFileStream); + // check actual file size with registered file size - return 413 + if ($uploadedFilesize != $slotParameters['filesize']) { + unlink($uploadedFilePath); + sendHttpErrorCodeAndMessage(403, "Uploaded file size differs from requestes slot size."); + } + // check actual mime type with registered mime type + if (mime_content_type($uploadFilePath) != $slotParameters['content_type']) { + unlink($uploadedFilePath); + sendHttpErrorCodeAndMessage(403, "Uploaded file content type differs from requestes slot content type."); + } + // return 500 in case of any error + // return 201 for success + sendHttpErrorCodeAndMessage(201); + break; + case 'GET': // better use really apache to serve files... + break; +} + +function getMandatoryPostParameter($parameterName) { + $parameter = $_POST[$parameterName]; + if (!isset($parameter) || is_null($parameter) || empty($parameter)) { + sendHttpErrorCodeAndMessage(400, 'Missing parameter "'.$parameterName.'"'); + } + return $parameter; +} + +function sendHttpErrorCodeAndMessage($code, $text = '') { + http_response_code($code); + exit($text); +} + +function getUUIDFromUri($uri) { + $pattern = "/[a-f0-9]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/"; + preg_match($pattern, $uri, $matches); + return $matches[0]; +} + +function getFilenameFromUri($uri) { + $lastSlash = strrpos($uri, '/'); + return substr($uri, $lastSlash); +} + +function registerSlot($slotUUID, $filename, $filesize, $contentType, $userJid, $config) { + $contents = "<?php\n/*\n * This is an autogenerated file - do not edit\n */\n\n"; + $contents .= 'return array(\'filename\' => \''.$filename.'\', \'filesize\' => \''.$filesize.'\', '; + $contents .= '\'content_type\' => \''.$contentType.'\', \'user_jid\' => \''.$userJid.'\');'; + if (!file_put_contents(getSlotFilePath($slotUUID, $config), $contents)) { + sendHttpErrorCodeAndMessage(500, "Could not create slot registry entry."); + } +} + +function slotExists($slotUUID, $config) { + return file_exists(getSlotFilePath($slotUUID, $config)); +} + +function getSlotFilePath($slotUUID, $config) { + return $config['slot_registry_dir'].$slotUUID; +} + +function getUploadFilePath($slotUUID, $config, $filename = NULL) { + $path = $config['storage_base_path'].$slotUUID; + if (!is_null($filename)) { + $path .= '/'.$filename; + } + return $path; +} + +/** + * Copied from http://rogerstringer.com/2013/11/15/generate-uuids-php/ + */ +function generate_uuid() { + return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', + mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), + mt_rand( 0, 0xffff ), + mt_rand( 0, 0x0fff ) | 0x4000, + mt_rand( 0, 0x3fff ) | 0x8000, + mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ) + ); +} |