scratch – Rev 96

Subversion Repositories:
Rev:
<?php

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

require_once('php/pseudocrypt.php');
require_once('php/functions.php');
require_once('vendor/autoload.php');

### Load configuration.
$config = spyc_load_file('config.yaml');

#### Script restrictions.
session_start();
if (empty($_POST['token']) || !hash_equals($_SESSION['token'], $_POST['token'])) {
    http_response_code(403);
    die('Forbidden.');
}

#### Check if the fingerprint and action are set parameters.
if(!isset($_POST['fingerprint']) or empty($_POST['fingerprint']) or
    !preg_match('/^[A-Za-z0-9]{32}$/', $_POST['fingerprint']) or
    !isset($_POST['action']) or empty($_POST['action'])) {
    http_response_code(500);
    die('Internal server error.');
}

#### Check fingerprint consistency.
$fingerprint = strtoupper($_POST['fingerprint']);
if(strlen($fingerprint) !== 32) {
    http_response_code(500);
    die('Internal server error.');
}

$action = strtoupper($_POST['action']);

#### Data must be sent in order to save a file.
if($action === 'SAVE' and !isset($_POST['data'])) {
    http_response_code(500);
    die('Internal server error.');
}

#### Hash fingerprint.
$file = strtolower(
    PseudoCrypt::hash(
        preg_replace(
            '/\D/',
            '',
            hash(
                'sha512',
                $fingerprint
            )
        ),
        $config['ASSET_HASH_SIZE']
    )
);

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

#### Check for path traversals
$pathPart = pathinfo($userPath.'.html');
if (strcasecmp(
    realpath($pathPart['dirname']), realpath($config['STORE_FOLDER'])) != 0) {
    http_response_code(500);
    die('Internal server error.');
}

switch($action) {
    case 'SAVE':
        #### Store the file.
        atomized_put_contents($userPath.'.html', $_POST['data']);
        break;
    case 'LOAD':
        if(!file_exists($userPath.'.html')) {
            ### If the file does not exist, present an empty file instead of 404.
            echo '';
            return;
        }
        ### Set no-cache
        header('Content-Type: text/html; charset=utf-8');
        header('Cache-Control: no-cache, no-store, must-revalidate');
        header('Pragma: no-cache');
        header('Expires: 0');
        ### Open MIME info database and send the content type.
        header('Content-type: text/html');
        ### Send the file along with the inline content disposition.
        header('Content-length: '.(int)get_file_size($userPath.'.html'));
        header('Content-Disposition: inline; filename="' . basename($userPath.'.html') . '"');
        header('X-Sendfile: '.$userPath.'.html');
        break;
}