scratch – Blame information for rev 90

Subversion Repositories:
Rev:
Rev Author Line No. Line
7 office 1 <?php
2  
3 ###########################################################################
4 ## Copyright (C) Wizardry and Steamworks 2017 - License: GNU GPLv3 ##
5 ###########################################################################
6  
66 office 7 require_once('php/pseudocrypt.php');
8 require_once('php/functions.php');
87 office 9 require_once('vendor/autoload.php');
7 office 10  
67 office 11 ### Load configuration.
12 $config = spyc_load_file('config.yaml');
13  
52 office 14 #### POST -> upload / GET -> download
15 switch ($_SERVER['REQUEST_METHOD']) {
16 case 'POST':
17 #### Retrieve uploaded file.
18 if (!empty($_FILES['file']) and
19 is_uploaded_file($_FILES['file']['tmp_name'])) {
67 office 20 if($_FILES['file']['size'] > $config['ALLOWED_ASSET_SIZE'] * 1048576) {
81 office 21 http_response_code(403);
22 die('File size exceeds '.$config['ALLOWED_ASSET_SIZE'].'MiB.');
57 office 23 }
52 office 24 # Regular multipart/form-data upload.
25 $name = $_FILES['file']['name'];
57 office 26 $data = atomized_get_contents($_FILES['file']['tmp_name']);
52 office 27 } else {
67 office 28 if((int)get_file_size("php://input") > $config['ALLOWED_ASSET_SIZE'] * 1048576) {
81 office 29 http_response_code(403);
30 die('File size exceeds '.$config['ALLOWED_ASSET_SIZE'].'MiB.');
57 office 31 }
52 office 32 # Raw POST data.
33 $name = urldecode(@$_SERVER['HTTP_X_FILE_NAME']);
57 office 34 $data = atomized_get_contents("php://input");
52 office 35 }
7 office 36  
52 office 37 #### Grab the file extension.
38 $fileExtension = pathinfo($name, PATHINFO_EXTENSION);
11 office 39  
52 office 40 #### If the extension is not allowed then change it to a text extension.
41 if (!isset($fileExtension) ||
42 !in_array(strtoupper($fileExtension),
67 office 43 array_map('strtoupper', $config['ALLOWED_FILE_EXTENSIONS']))) {
81 office 44 http_response_code(403);
45 die('File extension not allowed.');
52 office 46 }
14 office 47  
52 office 48 #### Hash filename.
49 $file = strtolower(
50 PseudoCrypt::hash(
51 preg_replace(
52 '/\D/',
53 '',
54 hash(
55 'sha512',
56 $data
57 )
58 ),
67 office 59 $config['ASSET_HASH_SIZE']
7 office 60 )
52 office 61 );
14 office 62  
52 office 63 #### Build the user path.
64 $userPath = join(
65 DIRECTORY_SEPARATOR,
66 array(
67 office 67 $config['STORE_FOLDER'],
52 office 68 $file
69 )
70 );
11 office 71  
52 office 72 #### Check for path traversals
73 $pathPart = pathinfo($userPath.'.'.$fileExtension);
74 if (strcasecmp(
67 office 75 realpath($pathPart['dirname']), realpath($config['STORE_FOLDER'])) != 0) {
81 office 76 http_response_code(500);
77 die('Internal server error.');
52 office 78 }
7 office 79  
52 office 80 #### Store the file.
81 office 81 $timestamp = atomized_put_contents($userPath.'.'.$fileExtension, $data);
14 office 82  
90 office 83 ### Hook for various file extensions.
84 $opengraph = FALSE;
85 switch(strtoupper($fileExtension)) {
86 case 'GIF':
87 $opengraph = TRUE;
88 break;
89 }
90  
52 office 91 ### Return the URL to the file.
92 header('Content-Type: text/plain; charset=utf-8');
81 office 93 echo json_encode(
94 array(
95 "hash" => $file,
90 office 96 "timestamp" => $timestamp,
97 "opengraph" => $opengraph
81 office 98 )
99 );
52 office 100 break;
101 case 'GET':
83 office 102 ### Tell browser not to cache files.
103 header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
104 header("Cache-Control: post-check=0, pre-check=0", false);
105 header("Pragma: no-cache");
106  
52 office 107 ### If no file has been specified for download then return.
81 office 108 if (!isset($_GET['hash']) or empty($_GET['hash'])) {
109 http_response_code(404);
110 die('File not found.');
52 office 111 }
112  
53 office 113 ### Find the requested file.
52 office 114 $file = array_shift(
115 preg_grep(
81 office 116 '/'.$_GET['hash'].'/',
67 office 117 scandir($config['STORE_FOLDER'])
52 office 118 )
119 );
120  
81 office 121 if (!isset($file) or empty($file)) {
122 http_response_code(404);
123 die('File not found.');
124 }
53 office 125  
126 ### Check the path for path traversals.
127 $fileExtension = pathinfo($file, PATHINFO_EXTENSION);
52 office 128  
53 office 129 #### If the extension is not allowed then return.
130 if (!isset($fileExtension) ||
131 !in_array(strtoupper($fileExtension),
67 office 132 array_map('strtoupper', $config['ALLOWED_FILE_EXTENSIONS']))) {
81 office 133 http_response_code(403);
134 die('File extension not allowed.');
52 office 135 }
53 office 136  
137 #### Build the user path.
138 $userPath = join(
139 DIRECTORY_SEPARATOR,
140 array(
67 office 141 $config['STORE_FOLDER'],
53 office 142 $file
143 )
144 );
52 office 145  
53 office 146 #### Check for path traversals
147 $pathPart = pathinfo($userPath);
148 if (strcasecmp(
67 office 149 realpath($pathPart['dirname']), realpath($config['STORE_FOLDER'])) != 0) {
81 office 150 http_response_code(500);
151 die('Internal server error.');
53 office 152 }
153  
83 office 154 ### Hook for various file extensions.
53 office 155 switch(strtoupper($fileExtension)) {
156 case "HTML":
157 case "HTM":
158 header('Content-type: text/html');
159 break;
160 break;
83 office 161 case "URL":
162 if(preg_match("/URL=([^\n]*)\n/", file_get_contents($userPath), $matches)) {
163 header('Location: '.$matches[1]);
164 return;
165 }
166 break;
53 office 167 default:
168 ### Open MIME info database and send the content type.
169 $finfo = finfo_open(FILEINFO_MIME_TYPE);
170 if (!$finfo) {
81 office 171 http_response_code(500);
172 die('Internal server error.');
53 office 173 }
174 header('Content-type: '.finfo_file($finfo, $userPath));
175 finfo_close($finfo);
176 break;
177 }
178  
52 office 179 ### Send the file along with the inline content disposition.
53 office 180 header('Content-length: '.(int)get_file_size($userPath));
181 header('Content-Disposition: inline; filename="' . basename($userPath) . '"');
182 header('Content-Transfer-Encoding: binary');
183 header('X-Sendfile: '.$userPath);
52 office 184 break;
185 }