PluginProbe
FV Player 8 / 8.0.21
FV Player 8 v8.0.21
trunk 8.0.18 8.0.19 8.0.20 8.0.21 8.0.25 8.0.27 8.1 8.1.3
fv-player / controller / s3-upload.php

s3-upload.php in FV Player 8 8.0.21, at controller/s3-upload.php

366 lines 11.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class FV_Player_S3_Upload {
4
5 function sanitize_path($path) {
6 $path = str_replace( 'Home/', '', stripslashes($path) );
7 $path = preg_replace( '~/$~', '', $path ); // We need to remove trailing slash to keep the breadcrumbs working
8
9 return $path;
10 }
11
12 function remove_special_chars($string) {
13 // coconut doesnt like this characters, we need to remove them
14 $string = str_replace( ' ', '-', $string );
15 $string = str_replace( ',', '-', $string );
16 $string = str_replace( '?', '', $string );
17 $string = str_replace( '&', '', $string );
18 $string = str_replace( '#', '', $string );
19 $string = str_replace( '%', '', $string );
20 $string = str_replace( '^', '', $string );
21 $string = str_replace( '$', '', $string );
22 $string = str_replace( '\'', '', $string );
23 $string = str_replace( '"', '', $string );
24
25 return $string;
26 }
27
28 /**
29 * Easy wrapper around S3 API
30 * @param mixed $command the function to call
31 * @param mixed $args variable args to pass
32 * @return mixed
33 */
34 function s3( $command = null, $args = null) {
35 global $FV_Player_DigitalOcean_Spaces_Browser;
36
37 static $s3 = null;
38 if ( $s3 === null ) {
39 $FV_Player_DigitalOcean_Spaces_Browser->include_aws_sdk();
40 $s3 = $FV_Player_DigitalOcean_Spaces_Browser->get_s3_client();
41 }
42
43 if ( $command === null ) return $s3;
44
45 $args=func_get_args();
46 array_shift($args);
47 try {
48 return call_user_func_array( [$s3, $command ], $args );
49 } catch (AwsException $e) {
50 echo esc_html( $e->getMessage() ), PHP_EOL;
51 }
52
53 return null;
54 }
55
56 function file_exists($contents, $filename) {
57 if ( is_array( $contents ) ) {
58 foreach( $contents as $object ) {
59 if( isset($object['Key']) && $object['Key'] == $filename ) {
60 return true;
61 }
62 }
63 }
64
65 return false;
66 }
67
68 function create_multiupload() {
69 if( !isset($_POST['nonce']) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'fv_flowplayer_create_multiupload' ) ) {
70 wp_send_json( array( 'error' => 'Access denied, please reload the page and try again.' ) );
71 }
72
73 global $FV_Player_DigitalOcean_Spaces;
74
75 $filename = $this->sanitize_path($_POST['fileInfo']['name']);
76 $filename = $this->remove_special_chars($filename);
77
78 $filename = remove_accents( $filename );
79 $filename = str_replace('Ę', 'E', $filename);
80
81 $target = dirname($filename);
82
83 if( $target === '.' ) {
84 $target = '';
85 } else {
86 $target = trailingslashit($target);
87 }
88
89 $filename_parts = explode('.', $filename);
90
91 try {
92 $s3Client = $this->s3();
93
94 if ( ! $s3Client ) {
95 $message = "AWS S3 SDK Failed to load.";
96
97 if ( version_compare(phpversion(),'7.4') == -1 ) {
98 $message .= " You need to use PHP version 7.4 or above.";
99 }
100
101 if ( function_exists( 'FV_Player_Coconut' ) ) {
102 FV_Player_Coconut()->plugin_api->log( "create_multiupload: " . $message );
103 }
104
105 wp_send_json( array( 'error' => $message ) );
106 }
107
108 $bucket = $FV_Player_DigitalOcean_Spaces->get_space();
109
110 // get objects from source space
111 $objects = $s3Client->listObjects(array(
112 'Bucket' => $bucket,
113 'Prefix' => $target,
114 'ResponseCacheControl' => 'No-cache',
115 'ResponseExpires' => gmdate(DATE_RFC2822, time() + 3600),
116 ));
117
118 $contents = $objects->get('Contents');
119
120 $rename_suffix_counter = 2;
121
122 $filename_final = $filename;
123
124 // verify if file already exists and append -{number} to prevent overwriting in source space
125 while( $this->file_exists($contents, $filename_final) ) {
126 $filename_parts = explode('.', $filename);
127 $filename_parts[count($filename_parts) -2] .= '-' . $rename_suffix_counter; // add suffix to second last part of filename before extension
128 $filename_final = implode('.', $filename_parts);
129 $rename_suffix_counter++;
130 }
131
132 // TODO: Is this needed anywhere? If so do it properly!
133 $_POST['fileInfo']['name'] = $filename_final;
134
135 } catch( Aws\S3\Exception\S3Exception $e ) {
136 $message = "Error checking files, please check your DigitalOcean Spaces keys in FV Player -> Coconut -> Settings.";
137
138 if ( function_exists( 'FV_Player_Coconut' ) ) {
139 FV_Player_Coconut()->plugin_api->log( "create_multiupload: " . $message . " Details: " . $e->getMessage() );
140 }
141
142 wp_send_json( array( 'error' => $message ) );
143 }
144
145 /**
146 * Make sure we have correct CORS on the DOS bucket.
147 * But if this fails then just go on as we want to allow key without full privileges
148 * to succeed at the upload.
149 */
150 try {
151 $this->s3("putBucketCors",
152 array(
153 "Bucket" => $FV_Player_DigitalOcean_Spaces->get_space(),
154 "CORSConfiguration" => array(
155 "CORSRules" => array(
156 array(
157 'AllowedHeaders' => array(
158 'Access-Control-Allow-Methods',
159 'Access-Control-Allow-Origin',
160 'Origin',
161 'Range',
162 ),
163 'AllowedMethods'=> array('GET','HEAD','PUT'),
164 "AllowedOrigins"=> array("*"),
165 ),
166 ),
167 ),
168 )
169 );
170 } catch( Aws\S3\Exception\S3Exception $e ) {
171 if ( function_exists( 'FV_Player_Coconut' ) ) {
172 FV_Player_Coconut()->plugin_api->log( "create_multiupload: Error setting CORS: " . $e->getMessage() );
173 }
174 }
175
176 try {
177 $res = $this->s3( "createMultipartUpload", array(
178 'Bucket' => $FV_Player_DigitalOcean_Spaces->get_space(),
179 'Key' => $filename_final,
180 'ContentType' => sanitize_text_field( $_REQUEST['fileInfo']['type'] ),
181 'Metadata' => array(
182 'name' => sanitize_text_field( $_REQUEST['fileInfo']['name'] ),
183 'type' => sanitize_text_field( $_REQUEST['fileInfo']['type'] ),
184 'size' => intval( $_REQUEST['fileInfo']['size'] ),
185 )
186 ));
187
188 if ( function_exists( 'FV_Player_Coconut' ) ) {
189 FV_Player_Coconut()->plugin_api->log( "create_multiupload: uploadId: " . $res->get('UploadId') . " for key: " . $res->get('Key') );
190 }
191
192 wp_send_json( array(
193 'uploadId' => $res->get('UploadId'),
194 'key' => $res->get('Key'),
195 ));
196 } catch( Aws\S3\Exception\S3Exception $e ) {
197 $message = "Error creating upload, please check your DigitalOcean Spaces keys in FV Player -> Coconut -> Settings.";
198
199 if ( function_exists( 'FV_Player_Coconut' ) ) {
200 FV_Player_Coconut()->plugin_api->log( "create_multiupload: " . $message . " Details: " . $e->getMessage() );
201 }
202
203 wp_send_json( array( 'error' => $message ) );
204 }
205
206 wp_die();
207 }
208
209 function multiupload_send_part() {
210 if( !isset($_POST['nonce']) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'fv_flowplayer_multiupload_send_part' ) ) {
211 wp_send_json( array( 'error' => 'Access denied, please reload the page and try again.' ) );
212 }
213
214 global $FV_Player_DigitalOcean_Spaces;
215
216 $args = array(
217 'Bucket' => $FV_Player_DigitalOcean_Spaces->get_space(),
218 'Key' => sanitize_text_field( $_REQUEST['sendBackData']['key'] ),
219 'UploadId' => sanitize_text_field( $_REQUEST['sendBackData']['uploadId'] ),
220 'PartNumber' => intval( $_REQUEST['partNumber'] ),
221 'ContentLength' => intval( $_REQUEST['contentLength'] )
222 );
223
224 if ( function_exists( 'FV_Player_Coconut' ) ) {
225 FV_Player_Coconut()->plugin_api->log( "multiupload_send_part: S3 UploadPart: " . print_r( $args, true ) );
226 }
227
228 $command = $this->s3( "getCommand", "UploadPart", $args );
229
230 // Give it at least 24 hours for large uploads
231 $request = $this->s3( "createPresignedRequest" , $command, "+48 hours" );
232
233 wp_send_json( array(
234 'url' => (string) $request->getUri(),
235 ));
236 wp_die();
237 }
238
239 function multiupload_complete() {
240 if( !isset($_POST['nonce']) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'fv_flowplayer_multiupload_complete' ) ) {
241 wp_send_json( array( 'error' => 'Access denied, please reload the page and try again.' ) );
242 }
243
244 global $FV_Player_DigitalOcean_Spaces;
245
246 // Try to complete the upload 4 times
247 $attempt = 1;
248
249 while( 1 ) {
250
251 // Initial wait as these file parts may take a bit of time to really appear
252 sleep(5);
253
254 try {
255 $args = array(
256 'Bucket' => $FV_Player_DigitalOcean_Spaces->get_space(),
257 'Key' => sanitize_text_field( $_REQUEST['sendBackData']['key'] ),
258 'UploadId' => sanitize_text_field( $_REQUEST['sendBackData']['uploadId'] ),
259 );
260
261 if ( function_exists( 'FV_Player_Coconut' ) ) {
262 FV_Player_Coconut()->plugin_api->log( "multiupload_complete: S3 listParts: " . print_r( $args, true ) );
263 }
264
265 $partsModel = $this->s3("listParts", $args);
266
267 } catch ( Exception $e ) {
268 if ( function_exists( 'FV_Player_Coconut' ) ) {
269 FV_Player_Coconut()->plugin_api->log( "multiupload_complete: S3 listParts exception: " . $e->getMessage() );
270 }
271
272 wp_send_json( array(
273 'error' => true,
274 'message' => $e->getMessage(),
275 ) );
276 }
277
278 $parts = array();
279
280 if (isset($partsModel["Parts"]) ) {
281 $parts = $partsModel["Parts"];
282 } else if (isset($partsModel["data"]["Parts"]) ) {
283 $parts = $partsModel["data"]["Parts"];
284 }
285
286 try {
287 $args = array(
288 'Bucket' => $FV_Player_DigitalOcean_Spaces->get_space(),
289 'Key' => sanitize_text_field( $_REQUEST['sendBackData']['key'] ),
290 'UploadId' => sanitize_text_field( $_REQUEST['sendBackData']['uploadId'] ),
291 'MultipartUpload' => array(
292 "Parts" => $parts,
293 )
294 );
295
296 if ( function_exists( 'FV_Player_Coconut' ) ) {
297 FV_Player_Coconut()->plugin_api->log( "multiupload_complete: S3 completeMultipartUpload: " . print_r( $args, true ) );
298 }
299
300 $ret = $this->s3( "completeMultipartUpload", $args )->toArray();
301
302 // Do not try again if it succeeded!
303 break;
304
305 } catch ( Exception $e ) {
306 $attempt++;
307
308 if ( function_exists( 'FV_Player_Coconut' ) ) {
309 FV_Player_Coconut()->plugin_api->log( "multiupload_complete: S3 completeMultipartUpload exception: " . $e->getMessage() );
310 }
311
312 if ( $attempt > 4 ) {
313 wp_send_json( array(
314 'error' => true,
315 'message' => $e->getMessage(),
316 ) );
317 }
318
319 sleep(5);
320 }
321 }
322
323 wp_send_json( array(
324 'success' => true,
325 'url' => $ret['ObjectURL'],
326 'key' => $ret['Key'],
327 'nonce' => wp_create_nonce( 'fv_player_coconut' ),
328 'attempt' => $attempt
329 ));
330 wp_die();
331 }
332
333 function multiupload_abort() {
334 if( !isset($_POST['nonce']) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'fv_flowplayer_multiupload_abort' ) ) {
335 wp_send_json( array( 'error' => 'Access denied, please reload the page and try again.' ) );
336 }
337
338 global $FV_Player_DigitalOcean_Spaces;
339
340 // if initial pre-upload request fails, we'll have no sendBackData to abort
341 if ( !empty( $_REQUEST['sendBackData'] ) ) {
342
343 $args = array(
344 'Bucket' => $FV_Player_DigitalOcean_Spaces->get_space(),
345 'Key' => sanitize_text_field( $_REQUEST['sendBackData']['key'] ),
346 'UploadId' => sanitize_text_field( $_REQUEST['sendBackData']['uploadId'] )
347 );
348
349 if ( function_exists( 'FV_Player_Coconut' ) ) {
350 FV_Player_Coconut()->plugin_api->log( "multiupload_abort: S3 abortMultipartUpload: " . print_r( $args, true ) );
351 }
352
353 $this->s3("abortMultipartUpload", $args );
354 }
355
356 wp_send_json( array(
357 'success' => true
358 ));
359 wp_die();
360 }
361
362 }
363
364 global $FV_Player_S3_Upload;
365 $FV_Player_S3_Upload = new FV_Player_S3_Upload();
366