scratch – Diff between revs 93 and 94

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