scratch – Rev 52

Subversion Repositories:
Rev:
<?php

###########################################################################
##  Copyright (C) Wizardry and Steamworks 2017 - License: GNU GPLv3      ##
###########################################################################

require_once('inc/pseudocrypt.php');
require_once('inc/functions.php');
require_once('config.php');

#### POST -> upload / GET -> download
switch ($_SERVER['REQUEST_METHOD']) {
    case 'POST':
        #### Retrieve uploaded file.
        if (!empty($_FILES['file']) and
            is_uploaded_file($_FILES['file']['tmp_name'])) {
            # Regular multipart/form-data upload.
            $name = $_FILES['file']['name'];
            $data = file_get_contents($_FILES['file']['tmp_name']);
        } else {
            # Raw POST data.
            $name = urldecode(@$_SERVER['HTTP_X_FILE_NAME']);
            $data = file_get_contents("php://input");
        }

        #### Grab the file extension.
        $fileExtension = pathinfo($name, PATHINFO_EXTENSION);

        #### If the extension is not allowed then change it to a text extension.
        if (!isset($fileExtension) ||
            !in_array(strtoupper($fileExtension),
                array_map('strtoupper', $ALLOWED_FILE_EXTENSIONS))) {
            header("HTTP/1.1 500 Internal Server Error", true, 500);
            return;
        }
    
        #### Hash filename.
        $file = strtolower(
            PseudoCrypt::hash(
                preg_replace(
                    '/\D/',
                    '',
                    hash(
                        'sha512',
                        $data
                    )
                ),
                $ASSET_HASH_SIZE
            )
        );

        #### Build the user path.
        $userPath = join(
            DIRECTORY_SEPARATOR,
            array(
                $STORE_FOLDER,
                $file
            )
        );

        #### Check for path traversals
        $pathPart = pathinfo($userPath.'.'.$fileExtension);
        if (strcasecmp(
            realpath($pathPart['dirname']), realpath($STORE_FOLDER)) != 0) {
            return;
        }

        #### Store the file.
        atomized_put_contents($userPath.'.'.$fileExtension, $data);

        ### Return the URL to the file.
        header('Content-Type: text/plain; charset=utf-8');
        echo sprintf('%s/%s', trim($URL_PATH, '/'), $file);
    break;
    case 'GET':
        ### If no file has been specified for download then return.
        if (!isset($_GET['o']) or empty($_GET['o'])) {
            http_response_code(404);
            return;
        }

        $file = array_shift(
            preg_grep(
                "/$_GET[o]/",
                scandir($STORE_FOLDER)
            )
        );

        if (!isset($file) or empty($file))
            return;

        ### Open MIME info database and send the content type.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        if (!$finfo) {
            http_response_code(500);
            return;
        }
    
        header('Content-type: '.finfo_file($finfo, $STORE_FOLDER.'/'.$file));
        finfo_close($finfo);

        ### Send the file along with the inline content disposition.
        header('Content-length: '.(int)get_file_size($STORE_FOLDER.'/'.$file));
        header('Content-Disposition: inline; filename="' . basename($STORE_FOLDER.'/'.$file) . '"');
        header('X-Sendfile: '.$STORE_FOLDER.'/'.$file);
    break;
}