aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--storage-backend/.htaccess3
-rw-r--r--storage-backend/index.php139
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 )
+ );
+}