scratch – Diff between revs 83 and 87

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