HTML
1 year ago
views
5 months ago
Apply.php
6 months ago
Cron.php
1 year ago
CronJob.php
7 months ago
CronJobs.php
2 months ago
Crypt.php
1 month ago
DownloadStats.php
5 months ago
Email.php
4 days ago
EmailCron.php
1 year ago
FileSystem.php
1 year ago
Installer.php
4 hours ago
Messages.php
1 year ago
Query.php
4 months ago
Session.php
4 hours ago
Settings.php
4 years ago
SimpleMath.php
4 years ago
TempStorage.php
4 hours ago
Template.php
5 months ago
UI.php
6 months ago
Updater.php
4 years ago
UserAgent.php
2 years ago
__.php
1 month ago
__MailUI.php
3 years ago
FileSystem.php
1403 lines
| 1 | <?php |
| 2 | |
| 3 | /** |
| 4 | * Manages file operations<br/> |
| 5 | * Version: 6|32 |
| 6 | * *** DO NOT CHANGE *** |
| 7 | */ |
| 8 | |
| 9 | namespace WPDM\__; |
| 10 | |
| 11 | use WPDM\AssetManager\AssetManager; |
| 12 | |
| 13 | class FileSystem { |
| 14 | function __construct() { |
| 15 | |
| 16 | } |
| 17 | |
| 18 | public static function mime_type( $filename ) { |
| 19 | $filetype = wp_check_filetype( $filename ); |
| 20 | |
| 21 | return $filetype['type']; |
| 22 | } |
| 23 | |
| 24 | public static function uploadFile( $FILE ) { |
| 25 | |
| 26 | } |
| 27 | |
| 28 | /** |
| 29 | * @usage Download Given File |
| 30 | * |
| 31 | * @param $filepath |
| 32 | * @param $filename |
| 33 | * @param int $speed |
| 34 | * @param int $resume_support |
| 35 | * @param array $extras |
| 36 | */ |
| 37 | public static function downloadFile( $filepath, $filename, $speed = 1024, $resume_support = 1, $extras = array() ) { |
| 38 | |
| 39 | |
| 40 | if ( headers_sent( $_filename, $_linenum ) ) { |
| 41 | Messages::error( "Headers already sent in $_filename on line $_linenum", 1 ); |
| 42 | } |
| 43 | |
| 44 | if ( substr_count( $filepath, "../" ) > 0 ) { |
| 45 | Messages::error( "Please, no funny business, however, good try though!", 1 ); |
| 46 | } |
| 47 | |
| 48 | if ( __::is_url( $filepath ) ) { |
| 49 | do_action( "wpdm_download_url_redirect", $filepath, $extras ); |
| 50 | header( "location: " . $filepath ); |
| 51 | die(); |
| 52 | } |
| 53 | $type = self::fileExt( $filepath ); |
| 54 | if ( WPDM()->fileSystem->isBlocked( $filepath ) ) { |
| 55 | Messages::error( "Invalid File Type (*.{$type})!", 1 ); |
| 56 | } |
| 57 | |
| 58 | $content_type = function_exists( 'mime_content_type' ) ? mime_content_type( $filepath ) : self::mime_type( $filepath ); |
| 59 | |
| 60 | $speed = $speed * 1024; // to bits |
| 61 | |
| 62 | $buffer = 1024 * 8; // to bits |
| 63 | |
| 64 | $bandwidth = 0; |
| 65 | |
| 66 | if ( function_exists( 'ini_set' ) ) { |
| 67 | @ini_set( 'display_errors', 0 ); |
| 68 | } |
| 69 | |
| 70 | @session_write_close(); |
| 71 | |
| 72 | if ( function_exists( 'apache_setenv' ) ) { |
| 73 | @apache_setenv( 'no-gzip', 1 ); |
| 74 | } |
| 75 | |
| 76 | if ( function_exists( 'ini_set' ) ) { |
| 77 | @ini_set( 'zlib.output_compression', 'Off' ); |
| 78 | } |
| 79 | |
| 80 | |
| 81 | @set_time_limit( 0 ); |
| 82 | @session_cache_limiter( 'none' ); |
| 83 | |
| 84 | if ( get_option( '__wpdm_support_output_buffer', 1 ) == 1 ) { |
| 85 | $pcl = ob_get_level(); |
| 86 | do { |
| 87 | @ob_end_clean(); |
| 88 | if ( ob_get_level() == $pcl ) { |
| 89 | break; |
| 90 | } |
| 91 | $pcl = ob_get_level(); |
| 92 | } while ( ob_get_level() > 0 ); |
| 93 | } |
| 94 | |
| 95 | if ( ! file_exists( $filepath ) ) { |
| 96 | Messages::fullPage( '404', esc_attr__( 'File not found!', WPDM_TEXT_DOMAIN ) ); |
| 97 | } |
| 98 | |
| 99 | $file_size = filesize( $filepath ); |
| 100 | |
| 101 | $org_size = $file_size; |
| 102 | $end_byte = $file_size - 1; |
| 103 | |
| 104 | $start_range = 0; |
| 105 | $end_range = $end_byte; |
| 106 | |
| 107 | nocache_headers(); |
| 108 | if(!(int)get_option('__wpdm_allow_index')) { |
| 109 | header( "X-Robots-Tag: noindex, nofollow", true ); |
| 110 | header( "Robots: none" ); |
| 111 | } |
| 112 | header( 'Content-Description: File Transfer' ); |
| 113 | |
| 114 | header( "Content-type: $content_type" ); |
| 115 | |
| 116 | $filename = apply_filters( "wpdm_download_filename", $filename, $filepath, $extras ); |
| 117 | |
| 118 | $filename = rawurlencode( $filename ); |
| 119 | |
| 120 | $parallel_download = (int) get_option( '__wpdm_parallel_download', 1 ); |
| 121 | if ( $parallel_download === 0 ) { |
| 122 | TempStorage::set( "download." . __::get_client_ip(), 1, 15 ); |
| 123 | } |
| 124 | |
| 125 | if ( ! isset( $extras['play'] ) ) { |
| 126 | if ( get_option( '__wpdm_open_in_browser', 0 ) || wpdm_query_var( 'open' ) == 1 ) { |
| 127 | header( "Content-disposition: inline;filename=\"{$filename}\"" ); |
| 128 | } else { |
| 129 | header( "Content-disposition: attachment;filename=\"{$filename}\"" ); |
| 130 | } |
| 131 | |
| 132 | header( "Content-Transfer-Encoding: binary" ); |
| 133 | } |
| 134 | |
| 135 | if ( (int) get_option( '__wpdm_download_resume', 1 ) === 2 ) { |
| 136 | header( "Content-Length: " . $file_size ); |
| 137 | header( "Content-disposition: attachment;filename=\"{$filename}\"" ); |
| 138 | readfile( $filepath ); |
| 139 | |
| 140 | return; |
| 141 | } |
| 142 | |
| 143 | $file = @fopen( $filepath, "rb" ); |
| 144 | |
| 145 | $proto = isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1'; |
| 146 | |
| 147 | //check if http_range is sent by browser (or download manager) |
| 148 | if ( isset( $_SERVER['HTTP_RANGE'] ) && $file_size > 0 ) { |
| 149 | |
| 150 | list( $rangeUnit, $http_range ) = explode( "=", $_SERVER['HTTP_RANGE'], 2 ); |
| 151 | |
| 152 | if ( substr_count( $http_range, ',' ) > 0 ) { |
| 153 | header( $proto.' 416 Requested Range Not Satisfiable' ); |
| 154 | header( "Content-Range: bytes $start_range-$end_byte/$org_size" ); |
| 155 | exit; |
| 156 | } |
| 157 | if ( $rangeUnit == 'bytes' ) { |
| 158 | if ( $http_range === '-' ) { |
| 159 | $start_range = $file_size - substr( $http_range, 1 ); |
| 160 | } else { |
| 161 | $http_range = explode( '-', $http_range ); |
| 162 | $start_range = $http_range[0]; |
| 163 | $end_range = wpdm_valueof( $http_range, 1, [ 'validate' => 'int' ] ) > 0 ? wpdm_valueof( $http_range, 1, [ 'validate' => 'int' ] ) : $end_byte; |
| 164 | //file_put_contents(ABSPATH.'/server.txt', print_r($http_range, 1)); |
| 165 | } |
| 166 | } else { |
| 167 | header( $proto.' 416 Requested Range Not Satisfiable' ); |
| 168 | exit; |
| 169 | } |
| 170 | $end_range = $end_range > $end_byte ? $end_byte : $end_range; |
| 171 | |
| 172 | header( "Accept-Ranges: bytes" ); |
| 173 | //header( "Accept-Ranges: 0-$end_byte" ); |
| 174 | header( "{$proto} 206 Partial Content" ); |
| 175 | |
| 176 | $content_length = $end_range - $start_range + 1; |
| 177 | header( "Content-Length: $content_length" ); |
| 178 | header( "Content-Range: bytes $start_range-$end_range/$org_size" ); |
| 179 | |
| 180 | fseek( $file, $start_range ); |
| 181 | |
| 182 | } else { |
| 183 | header( "Content-Length: " . $file_size ); |
| 184 | } |
| 185 | $packet = 1; |
| 186 | |
| 187 | if ( $file ) { |
| 188 | $speed_chunk = 0; |
| 189 | while ( ! ( connection_aborted() || connection_status() == 1 ) && $file_size > 0 ) { |
| 190 | |
| 191 | if ( $file_size > $buffer ) { |
| 192 | echo fread( $file, $buffer ); |
| 193 | } else { |
| 194 | echo fread( $file, $file_size ); |
| 195 | } |
| 196 | if ( function_exists( 'ob_get_level' ) && ob_get_level() > 0 ) { |
| 197 | @ob_flush(); |
| 198 | } |
| 199 | @flush(); |
| 200 | //Remaining file size to transfer |
| 201 | $file_size -= $buffer; |
| 202 | // |
| 203 | $bandwidth += $buffer; |
| 204 | |
| 205 | //Calculating download speed |
| 206 | $speed_chunk += $buffer; |
| 207 | //Condition for download speed control |
| 208 | if ( $speed > 0 && ( $speed_chunk >= $speed ) ) { |
| 209 | sleep( 1 ); |
| 210 | $speed_chunk = 0; |
| 211 | $packet ++; |
| 212 | } |
| 213 | |
| 214 | |
| 215 | } |
| 216 | $package['downloaded_file_size'] = $file_size; |
| 217 | //add_action('wpdm_download_completed', $package); |
| 218 | @fclose( $file ); |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | |
| 223 | static function chunkDownload( $file ) { |
| 224 | $fp = @fopen( $file, 'rb' ); |
| 225 | $size = filesize( $file ); |
| 226 | $length = $size; |
| 227 | $start = 0; |
| 228 | $end = $size - 1; |
| 229 | header( "Accept-Ranges: bytes" ); |
| 230 | if ( isset( $_SERVER['HTTP_RANGE'] ) ) { |
| 231 | $c_start = $start; |
| 232 | $c_end = $end; |
| 233 | list( , $range ) = explode( '=', $_SERVER['HTTP_RANGE'], 2 ); |
| 234 | if ( strpos( $range, ',' ) !== false ) { |
| 235 | header( 'HTTP/1.1 416 Requested range is not valid' ); |
| 236 | header( "Content-Range: bytes $start-$end/$size" ); |
| 237 | exit; |
| 238 | } |
| 239 | |
| 240 | if ( $range == '-' ) { |
| 241 | $c_start = $size - substr( $range, 1 ); |
| 242 | } else { |
| 243 | $range = explode( '-', $range ); |
| 244 | $c_start = $range[0]; |
| 245 | $c_end = ( isset( $range[1] ) && is_numeric( $range[1] ) ) ? $range[1] : $size; |
| 246 | } |
| 247 | $c_end = ( $c_end > $end ) ? $end : $c_end; |
| 248 | |
| 249 | if ( $c_start > $c_end || $c_start > $size - 1 || $c_end >= $size ) { |
| 250 | header( 'HTTP/1.1 416 Requested range is not valid' ); |
| 251 | header( "Content-Range: bytes $start-$end/$size" ); |
| 252 | exit; |
| 253 | } |
| 254 | $start = $c_start; |
| 255 | $end = $c_end; |
| 256 | $length = $end - $start + 1; |
| 257 | fseek( $fp, $start ); |
| 258 | header( 'HTTP/1.1 206 Partial Content' ); |
| 259 | } |
| 260 | header( "Content-Range: bytes $start-$end/$size" ); |
| 261 | header( "Content-Length: " . $length ); |
| 262 | $buffer = 1024 * 8; |
| 263 | while ( ! feof( $fp ) && ( $p = ftell( $fp ) ) <= $end ) { |
| 264 | if ( $p + $buffer > $end ) { |
| 265 | $buffer = $end - $p + 1; |
| 266 | } |
| 267 | set_time_limit( 0 ); |
| 268 | echo fread( $fp, $buffer ); |
| 269 | flush(); |
| 270 | } |
| 271 | fclose( $fp ); |
| 272 | die(); |
| 273 | } |
| 274 | |
| 275 | /** |
| 276 | * @usage Download any content as a file |
| 277 | * |
| 278 | * @param $filename |
| 279 | * @param $content |
| 280 | */ |
| 281 | public function downloadData( $filename, $content ) { |
| 282 | @ob_end_clean(); |
| 283 | nocache_headers(); |
| 284 | $filetype = wp_check_filetype( $filename ); |
| 285 | if(!(int)get_option('__wpdm_allow_index')) { |
| 286 | header( "X-Robots-Tag: noindex, nofollow", true ); |
| 287 | header( "Robots: none" ); |
| 288 | } |
| 289 | header( "Content-Description: File Transfer" ); |
| 290 | header( "Content-Type: {$filetype['type']}" ); |
| 291 | header( "Content-disposition: attachment;filename=\"$filename\"" ); |
| 292 | header( "Content-Transfer-Encoding: Binary" ); |
| 293 | header( "Content-Length: " . strlen( $content ) ); |
| 294 | echo $content; |
| 295 | } |
| 296 | |
| 297 | /** |
| 298 | * @usage Sends download headers only |
| 299 | * |
| 300 | * @param $filename |
| 301 | * @param int $size |
| 302 | */ |
| 303 | public function downloadHeaders( $filename, $size = null ) { |
| 304 | @ob_end_clean(); |
| 305 | $filetype = wp_check_filetype( $filename ); |
| 306 | header( "Content-Description: File Transfer" ); |
| 307 | header( "Content-Type: {$filetype['type']}" ); |
| 308 | header( "Content-disposition: attachment;filename=\"$filename\"" ); |
| 309 | header( "Content-Transfer-Encoding: Binary" ); |
| 310 | if ( $size ) { |
| 311 | header( "Content-Length: " . $size ); |
| 312 | } |
| 313 | } |
| 314 | |
| 315 | |
| 316 | /** |
| 317 | * @usage Download any content as a file |
| 318 | * |
| 319 | * @param $filename |
| 320 | * @param $content |
| 321 | */ |
| 322 | public static function mkDir( $path, $mode = 0777, $recur = false ) { |
| 323 | $success = true; |
| 324 | if ( ! file_exists( $path ) ) { |
| 325 | $success = @mkdir( $path, $mode, $recur ); |
| 326 | } |
| 327 | |
| 328 | return $success; |
| 329 | } |
| 330 | |
| 331 | /** |
| 332 | * @usage Create ZIP from given file list |
| 333 | * |
| 334 | * @param $files |
| 335 | * @param $zipname |
| 336 | * |
| 337 | * @return bool|string |
| 338 | */ |
| 339 | public static function zipFiles( $files, $zipname ) { |
| 340 | |
| 341 | if ( ! class_exists( 'ZipArchive' ) ) { |
| 342 | Messages::fullPage( 'Error!', "<div class='card bg-danger text-white p-4'>" . __( "<b>Zlib</b> is not active! Failed to initiate <b>ZipArchive</b>", "download-manager" ) . "</div>", 'error' ); |
| 343 | } |
| 344 | |
| 345 | |
| 346 | $zipped = ( basename( $zipname ) === $zipname ) ? WPDM_CACHE_DIR . sanitize_file_name( $zipname ) : $zipname; |
| 347 | |
| 348 | if ( substr_count( $zipname, '.zip' ) <= 0 ) { |
| 349 | $zipped .= '.zip'; |
| 350 | } |
| 351 | |
| 352 | if ( file_exists( $zipped ) ) { |
| 353 | unlink( $zipped ); |
| 354 | } |
| 355 | |
| 356 | if ( count( $files ) < 1 ) { |
| 357 | return false; |
| 358 | } |
| 359 | |
| 360 | $zip = new \ZipArchive(); |
| 361 | if ( $zip->open( $zipped, \ZIPARCHIVE::CREATE ) !== true ) { |
| 362 | return false; |
| 363 | } |
| 364 | foreach ( $files as $file ) { |
| 365 | $file = trim( $file ); |
| 366 | $filename = wp_basename( $file ); |
| 367 | $file = WPDM()->fileSystem->absPath( $file ); |
| 368 | if ( $file ) { |
| 369 | $zip->addFile( $file, $filename ); |
| 370 | } |
| 371 | } |
| 372 | $zip->close(); |
| 373 | |
| 374 | return $zipped; |
| 375 | } |
| 376 | |
| 377 | /** |
| 378 | * @usage Create ZIP from given dir path |
| 379 | * |
| 380 | * @param $files |
| 381 | * @param $zipname |
| 382 | * |
| 383 | * @return bool|string |
| 384 | */ |
| 385 | public static function zipDir( $dir, $zipname = '' ) { |
| 386 | |
| 387 | if ( $zipname === '' ) { |
| 388 | $zipname = basename( $dir ); |
| 389 | } |
| 390 | |
| 391 | $zipped = WPDM_CACHE_DIR . sanitize_file_name( $zipname ) . '.zip'; |
| 392 | |
| 393 | $base_folder = sanitize_file_name( $zipname ); |
| 394 | |
| 395 | $rootPath = realpath( $dir ); |
| 396 | |
| 397 | $zip = new \ZipArchive(); |
| 398 | $zip->open( $zipped, \ZipArchive::CREATE | \ZipArchive::OVERWRITE ); |
| 399 | |
| 400 | |
| 401 | $files = new \RecursiveIteratorIterator( |
| 402 | new \RecursiveDirectoryIterator( $rootPath, \RecursiveDirectoryIterator::SKIP_DOTS ), |
| 403 | \RecursiveIteratorIterator::LEAVES_ONLY |
| 404 | ); |
| 405 | foreach ( $files as $name => $file ) { |
| 406 | if ( ! $file->isDir() && ! strstr( $file->getRealPath(), ".git" ) && ! strstr( $file->getRealPath(), ".DS" ) ) { |
| 407 | $filePath = $file->getRealPath(); |
| 408 | $relativePath = substr( $filePath, strlen( $rootPath ) + 1 ); |
| 409 | $zip->addFile( $filePath, $base_folder . "/" . $relativePath ); |
| 410 | } |
| 411 | } |
| 412 | |
| 413 | $zip->close(); |
| 414 | |
| 415 | return $zipped; |
| 416 | } |
| 417 | |
| 418 | /** |
| 419 | * UnZip a zip file |
| 420 | * |
| 421 | * @param $zip_file |
| 422 | * @param string $dir |
| 423 | * |
| 424 | * @return bool |
| 425 | */ |
| 426 | public static function unZip( $zip_file, $dir = '' ) { |
| 427 | $zip = new \ZipArchive(); |
| 428 | $res = $zip->open( $zip_file ); |
| 429 | if ( $dir === '' ) { |
| 430 | $dir = str_replace( ".zip", "", $zip_file ); |
| 431 | } |
| 432 | if ( ! file_exists( $dir ) ) { |
| 433 | mkdir( $dir, 0755, true ); |
| 434 | } |
| 435 | if ( $res === true ) { |
| 436 | $zip->extractTo( $dir ); |
| 437 | $zip->close(); |
| 438 | |
| 439 | return true; |
| 440 | } else { |
| 441 | return false; |
| 442 | } |
| 443 | } |
| 444 | |
| 445 | /** |
| 446 | * @param $dir |
| 447 | * @param bool|true $recur |
| 448 | * |
| 449 | * @return array |
| 450 | */ |
| 451 | public static function scanDir( $dir, $recur = true, $abspath = true, $filter = null, $md5_index = false ) { |
| 452 | $dir = trailingslashit( realpath( $dir ) ); |
| 453 | if ( $dir === '/' || $dir === '' ) { |
| 454 | return array(); |
| 455 | } |
| 456 | $tmpfiles = file_exists( $dir ) ? array_diff( scandir( $dir ), array( ".", "..", ".DS_Store", ".htaccess" ) ) : array(); |
| 457 | $files = array(); |
| 458 | foreach ( $tmpfiles as $file ) { |
| 459 | if ( is_dir( $dir . $file ) && $recur == true ) { |
| 460 | $files = array_merge( $files, self::scanDir( $dir . $file, true, $abspath, $filter, $md5_index ) ); |
| 461 | } else { |
| 462 | if ( ! $filter || substr_count( $file, $filter ) > 0 ) { |
| 463 | $path = $abspath ? realpath( $dir . $file ) : $file; |
| 464 | $path = str_replace( "\\", "/", $path ); |
| 465 | if ( $md5_index ) { |
| 466 | $files[ md5( $path ) ] = $path; |
| 467 | } else { |
| 468 | $files[] = $path; |
| 469 | } |
| 470 | } |
| 471 | } |
| 472 | } |
| 473 | |
| 474 | return $files; |
| 475 | } |
| 476 | |
| 477 | |
| 478 | /** |
| 479 | * Get formatted file size |
| 480 | * |
| 481 | * @param $dir |
| 482 | * |
| 483 | * @return string |
| 484 | */ |
| 485 | function fileSize( $filepath ) { |
| 486 | if ( __::is_url( $filepath ) ) { |
| 487 | return '0 KB'; |
| 488 | } |
| 489 | $filepath = WPDM()->fileSystem->locateFile( $filepath ); |
| 490 | if ( ! $filepath ) { |
| 491 | return '0 KB'; |
| 492 | } |
| 493 | |
| 494 | return __::formatBytes( filesize( $filepath ) ); |
| 495 | } |
| 496 | |
| 497 | /** |
| 498 | * Calculate directory size |
| 499 | * |
| 500 | * @param $dir |
| 501 | * |
| 502 | * @return string |
| 503 | */ |
| 504 | function dirSize( $dir ) { |
| 505 | $bytestotal = 0; |
| 506 | $path = realpath( $dir ); |
| 507 | if ( $path !== false ) { |
| 508 | foreach ( new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator( $path, \FilesystemIterator::SKIP_DOTS ) ) as $object ) { |
| 509 | try { |
| 510 | $bytestotal += $object->getSize(); |
| 511 | } catch ( \Exception $e ) { |
| 512 | |
| 513 | } |
| 514 | } |
| 515 | } |
| 516 | $bytestotal = $bytestotal / 1024; |
| 517 | $bytestotal = $bytestotal / 1024; |
| 518 | |
| 519 | return number_format( $bytestotal, 2 ); |
| 520 | } |
| 521 | |
| 522 | /** |
| 523 | * @param $dir |
| 524 | * @param bool|true $recur |
| 525 | * |
| 526 | * @return array |
| 527 | */ |
| 528 | public static function listFiles( $dir, $recur = true, $abspath = true ) { |
| 529 | $dir = realpath( $dir ) . "/"; |
| 530 | if ( $dir == '/' || $dir == '' ) { |
| 531 | return array(); |
| 532 | } |
| 533 | $tmpfiles = file_exists( $dir ) ? array_diff( scandir( $dir ), array( ".", ".." ) ) : array(); |
| 534 | $files = array(); |
| 535 | foreach ( $tmpfiles as $file ) { |
| 536 | if ( is_dir( $dir . $file ) && $recur == true ) { |
| 537 | $files = array_merge( $files, self::scanDir( $dir . $file, true ) ); |
| 538 | } else if ( ! is_dir( $dir . $file ) ) { |
| 539 | $files[] = $abspath ? $dir . $file : $file; |
| 540 | } |
| 541 | } |
| 542 | |
| 543 | return $files; |
| 544 | } |
| 545 | |
| 546 | /** |
| 547 | * @param $dir |
| 548 | * @param bool|true $recur |
| 549 | * |
| 550 | * @return array |
| 551 | */ |
| 552 | public static function subDirs( $dir, $abspath = true ) { |
| 553 | $dir = realpath( $dir ) . "/"; |
| 554 | $dir = str_replace( "\\", "/", $dir ); |
| 555 | if ( $dir == '/' || $dir == '' ) { |
| 556 | return array(); |
| 557 | } |
| 558 | $tmpfiles = file_exists( $dir ) ? array_diff( scandir( $dir ), array( ".", ".." ) ) : array(); |
| 559 | $subdirs = array(); |
| 560 | foreach ( $tmpfiles as $file ) { |
| 561 | if ( is_dir( $dir . $file ) ) { |
| 562 | $subdirs[] = $abspath ? $dir . $file : $file; |
| 563 | } |
| 564 | |
| 565 | } |
| 566 | |
| 567 | return $subdirs; |
| 568 | } |
| 569 | |
| 570 | |
| 571 | /** |
| 572 | * @param $dir |
| 573 | * @param bool|true $recur |
| 574 | * |
| 575 | * @return array|bool |
| 576 | */ |
| 577 | public static function deleteFiles( $dir, $recur = true, $filter = '*' ) { |
| 578 | $dir = realpath( $dir ) . "/"; |
| 579 | if ( $dir == '/' || $dir == '' ) { |
| 580 | return array(); |
| 581 | } |
| 582 | $tmpfiles = file_exists( $dir ) ? array_diff( scandir( $dir ), array( ".", ".." ) ) : array(); |
| 583 | $files = array(); |
| 584 | foreach ( $tmpfiles as $file ) { |
| 585 | if ( is_dir( $dir . $file ) && $recur == true ) { |
| 586 | $files = array_merge( $files, self::scanDir( $dir . $file, true ) ); |
| 587 | } else { |
| 588 | if ( is_array( $filter ) ) { |
| 589 | $ext = isset( $filter['ext'] ) ? $filter['ext'] : '*'; |
| 590 | $expiretime = isset( $filter['filetime'] ) ? $filter['filetime'] : null; |
| 591 | $delete = true; |
| 592 | $filetime = filectime( $dir . $file ); |
| 593 | if ( ! $filetime || ! $expiretime || $filetime < $expiretime ) { |
| 594 | if ( $ext === '*' || substr_count( $file, $ext ) > 0 ) { |
| 595 | @unlink( $dir . $file ); |
| 596 | } |
| 597 | } |
| 598 | } else { |
| 599 | if ( $filter === '*' || substr_count( $file, $filter ) > 0 ) { |
| 600 | @unlink( $dir . $file ); |
| 601 | } |
| 602 | } |
| 603 | } |
| 604 | } |
| 605 | |
| 606 | return true; |
| 607 | } |
| 608 | |
| 609 | /** |
| 610 | * @param $src |
| 611 | * @param $dst |
| 612 | */ |
| 613 | public static function copyDir( $src, $dst ) { |
| 614 | $src = realpath( $src ); |
| 615 | $dir = opendir( $src ); |
| 616 | |
| 617 | $dst = realpath( $dst ) . '/' . basename( $src ); |
| 618 | @mkdir( $dst ); |
| 619 | |
| 620 | while ( false !== ( $file = readdir( $dir ) ) ) { |
| 621 | if ( ( $file != '.' ) && ( $file != '..' ) ) { |
| 622 | if ( is_dir( $src . '/' . $file ) ) { |
| 623 | self::copyDir( $src . '/' . $file, $dst . '/' . $file ); |
| 624 | } else { |
| 625 | copy( $src . '/' . $file, $dst . '/' . $file ); |
| 626 | } |
| 627 | } |
| 628 | } |
| 629 | closedir( $dir ); |
| 630 | } |
| 631 | |
| 632 | /** |
| 633 | * Generates image thumbnail |
| 634 | * |
| 635 | * @param $path |
| 636 | * @param $width |
| 637 | * @param $height |
| 638 | * @param |null $crop |
| 639 | * @param bool $usecache |
| 640 | * |
| 641 | * @return string|string[] |
| 642 | */ |
| 643 | public static function imageThumbnail( $path, $width, $height, $crop = WPDM_USE_GLOBAL, $usecache = true ) { |
| 644 | $original_path = $path; |
| 645 | |
| 646 | if ( ! function_exists( 'get_home_path' ) ) { |
| 647 | require_once ABSPATH . 'wp-admin/includes/file.php'; |
| 648 | } |
| 649 | $abspath = get_home_path(); |
| 650 | |
| 651 | $abspath = str_replace( "\\", "/", ABSPATH ); |
| 652 | $cachedir = str_replace( "\\", "/", WPDM_CACHE_DIR ); |
| 653 | $path = str_replace( "\\", "/", $path ); |
| 654 | if ( is_ssl() ) { |
| 655 | $path = str_replace( "http://", "https://", $path ); |
| 656 | } else { |
| 657 | $path = str_replace( "https://", "http://", $path ); |
| 658 | } |
| 659 | $path = str_replace( site_url( '/' ), $abspath, $path ); |
| 660 | |
| 661 | $crop = $crop === WPDM_USE_GLOBAL ? get_option( '__wpdm_crop_thumbs', false ) : $crop; |
| 662 | |
| 663 | if ( strpos( $path, '.wp.com' ) ) { |
| 664 | $path = explode( "?", $path ); |
| 665 | $path = $path[0] . "?resize={$width},{$height}"; |
| 666 | |
| 667 | return $path; |
| 668 | } |
| 669 | |
| 670 | if ( strpos( $path, '://' ) ) { |
| 671 | return $path; |
| 672 | } |
| 673 | if ( ! file_exists( $path ) && wpdm_is_url( $original_path ) ) { |
| 674 | return $original_path; |
| 675 | } |
| 676 | if ( ! file_exists( $path ) ) { |
| 677 | return WPDM_BASE_URL . 'assets/images/404.jpg'; |
| 678 | } |
| 679 | |
| 680 | |
| 681 | $thumbname = md5( $path.$width.$height ); |
| 682 | $name_p = explode( ".", $path ); |
| 683 | $ext = "." . end( $name_p ); |
| 684 | $filename = basename( $path ); |
| 685 | //$thumbpath = $cachedir . str_replace( $ext, "-{$width}x{$height}" . $ext, $filename ); |
| 686 | $thumbpath = $cachedir . $thumbname.$ext; |
| 687 | //wpdmdd($thumbpath); |
| 688 | |
| 689 | if ( file_exists( $thumbpath ) && $usecache ) { |
| 690 | $thumbpath = str_replace( $cachedir, WPDM_CACHE_URL, $thumbpath ); |
| 691 | return $thumbpath; |
| 692 | } |
| 693 | |
| 694 | try { |
| 695 | $image = wp_get_image_editor( $path ); |
| 696 | $fullurl = str_replace( $cachedir, WPDM_CACHE_URL, $path ); |
| 697 | if ( ! is_wp_error( $image ) ) { |
| 698 | //if ( is_wp_error( $image->resize( $width, $height, true ) ) ) return $fullurl; |
| 699 | try { |
| 700 | $image->resize( $width, $height, $crop ); |
| 701 | $image->save( $thumbpath ); |
| 702 | } catch ( \Exception $e ) { |
| 703 | return "https://fakeimg.pl/600x400?text=x&font=museo"; |
| 704 | } |
| 705 | |
| 706 | } else { |
| 707 | return str_replace( ABSPATH, home_url( '/' ), $path ); |
| 708 | } |
| 709 | |
| 710 | $thumb_size = $image->get_size(); |
| 711 | if ( $thumb_size['width'] < $width || $thumb_size['height'] < $height ) { |
| 712 | if ( $height == 0 ) { |
| 713 | $height = $thumb_size['height']; |
| 714 | } |
| 715 | $_image_back = imagecreatetruecolor( $width, $height ); |
| 716 | $color = imagecolorallocatealpha( $_image_back, 255, 255, 255, 127 ); |
| 717 | imagefill( $_image_back, 0, 0, $color ); |
| 718 | if ( strstr( $thumbpath, ".png" ) ) { |
| 719 | $_image_top = imagecreatefrompng( $thumbpath ); |
| 720 | } |
| 721 | if ( strstr( $thumbpath, ".gif" ) ) { |
| 722 | $_image_top = imagecreatefromgif( $thumbpath ); |
| 723 | } |
| 724 | if ( strstr( $thumbpath, ".jpg" ) || strstr( $thumbpath, ".jpeg" ) ) { |
| 725 | $_image_top = imagecreatefromjpeg( $thumbpath ); |
| 726 | } |
| 727 | if ( ! isset( $_image_top ) || ! $_image_top ) { |
| 728 | return $thumbpath; |
| 729 | } |
| 730 | $imgw = imagesx( $_image_top ); |
| 731 | $imgh = imagesy( $_image_top ); |
| 732 | $posx = (int) ( ( $width - $imgw ) / 2 ); |
| 733 | $posy = (int) ( ( $height - $imgh ) / 2 ); |
| 734 | imagecopy( $_image_back, $_image_top, $posx, $posy, 0, 0, $imgw, $imgh ); |
| 735 | imagepng( $_image_back, $thumbpath ); |
| 736 | imagedestroy( $_image_back ); |
| 737 | } |
| 738 | |
| 739 | $thumbpath = str_replace( "\\", "/", $thumbpath ); |
| 740 | $thumbpath = str_replace( $cachedir, WPDM_CACHE_URL, $thumbpath ); |
| 741 | } catch ( \Exception $e ) { |
| 742 | wpdmdd($e->getMessage()); |
| 743 | } |
| 744 | |
| 745 | return $thumbpath; |
| 746 | } |
| 747 | |
| 748 | /** |
| 749 | * @param $pdf |
| 750 | * @param $id |
| 751 | * |
| 752 | * @return string |
| 753 | * @usage Generates thumbnail from PDF file. [ From v4.1.3 ] |
| 754 | */ |
| 755 | public static function pdfThumbnail( $pdf, $id ) { |
| 756 | $pdfurl = ''; |
| 757 | if ( strpos( $pdf, "://" ) ) { |
| 758 | $pdfurl = $pdf; |
| 759 | $pdf = str_replace( home_url( '/' ), ABSPATH, $pdf ); |
| 760 | } |
| 761 | if ( $pdf == $pdfurl ) { |
| 762 | return ''; |
| 763 | } |
| 764 | if ( file_exists( $pdf ) ) { |
| 765 | $source = $pdf; |
| 766 | } else { |
| 767 | $source = UPLOAD_DIR . $pdf; |
| 768 | } |
| 769 | if ( ! file_exists( WPDM_CACHE_DIR . "pdfthumbs/" ) ) { |
| 770 | @mkdir( WPDM_CACHE_DIR . "pdfthumbs/", 0755 ); |
| 771 | @chmod( WPDM_CACHE_DIR . "pdfthumbs/", 0755 ); |
| 772 | } |
| 773 | $dest = WPDM_CACHE_DIR . "pdfthumbs/{$id}.png"; |
| 774 | $durl = WPDM_CACHE_URL . "pdfthumbs/{$id}.png"; |
| 775 | $ext = explode( ".", $source ); |
| 776 | $ext = end( $ext ); |
| 777 | $colors = WPDM()->setting->ui_colors; |
| 778 | $color = is_array( $colors['secondary'] ) && isset( $colors['secondary'] ) ? str_replace( "#", "", $colors['secondary'] ) : '6c757d'; |
| 779 | if ( $ext != 'pdf' ) { |
| 780 | return ''; |
| 781 | } |
| 782 | if ( file_exists( $dest ) ) { |
| 783 | return $durl; |
| 784 | } |
| 785 | if ( ! file_exists( $source ) ) { |
| 786 | $source = utf8_encode( $source ); |
| 787 | } |
| 788 | $source = $source . '[0]'; |
| 789 | if ( ! class_exists( '\Imagick' ) ) { |
| 790 | return "https://via.placeholder.com/600x900/{$color}/FFFFFF?text=[+Imagick+Missing+]"; |
| 791 | } // "Error: Imagick is not installed properly"; |
| 792 | try { |
| 793 | $image = new \imagick( $source ); |
| 794 | $image->setResolution( 1200, 0 ); |
| 795 | $image->setImageFormat( "png" ); |
| 796 | $image->writeImage( $dest ); |
| 797 | } catch ( \Exception $e ) { |
| 798 | return "https://via.placeholder.com/600x900/{$color}/FFFFFF?text=" . urlencode( $e->getMessage() ); |
| 799 | //return ''; |
| 800 | } |
| 801 | |
| 802 | return $durl; |
| 803 | } |
| 804 | |
| 805 | function filePreview( $file, $width = 150, $height = 150, $pid = 0) { |
| 806 | if(!__::is_url($file)) { |
| 807 | $ext = self::fileExt( $file ); |
| 808 | if ( $ext === 'pdf' ) { |
| 809 | return self::pdfThumbnail( $file, md5( $file ) ); |
| 810 | } |
| 811 | if ( in_array( $ext, [ 'png', 'jpg', 'jpeg' ] ) ) { |
| 812 | return self::imageThumbnail( $file, $width, $height, true ); |
| 813 | } |
| 814 | |
| 815 | return self::fileTypeIcon( $ext ); |
| 816 | } else { |
| 817 | $ext = self::fileExt( $file ); |
| 818 | $preview = self::fileTypeIcon( $ext ); |
| 819 | $preview = apply_filters( 'wpdm_remote_file_preview', $preview, $file, $width, $height, $pid ); |
| 820 | return $preview; |
| 821 | } |
| 822 | } |
| 823 | |
| 824 | /** |
| 825 | * @usgae Block http access to a dir |
| 826 | * |
| 827 | * @param $dir |
| 828 | */ |
| 829 | public static function blockHTTPAccess( $dir, $fileType = '*' ) { |
| 830 | $cont = "RewriteEngine On\r\n<Files {$fileType}>\r\nDeny from all\r\n</Files>\r\n"; |
| 831 | @file_put_contents( $dir . '/.htaccess', $cont ); |
| 832 | file_put_contents($dir . '/index.php', '<?php // ?>'); |
| 833 | } |
| 834 | |
| 835 | /** |
| 836 | * @usage Google Doc Preview Embed |
| 837 | * |
| 838 | * @param $url |
| 839 | * |
| 840 | * @return string |
| 841 | */ |
| 842 | public static function docViewer( $url, $ID, $ext = '' ) { |
| 843 | |
| 844 | $doc_preview_html = ""; |
| 845 | if ( $ext == 'pdf' ) { |
| 846 | $doc_preview_html = '<iframe src="https://docs.google.com/viewer?url=' . urlencode( $url ) . '&embedded=true" width="100%" height="600" style="border: none;"></iframe>'; |
| 847 | } else { |
| 848 | $doc_preview_html = '<iframe src="https://view.officeapps.live.com/op/view.aspx?src=' . urlencode( $url ) . '&embedded=true" width="100%" height="600" style="border: none;"></iframe>'; |
| 849 | } |
| 850 | $doc_preview_html = apply_filters( 'wpdm_doc_viewer', $doc_preview_html, $ID, $url, $ext ); |
| 851 | |
| 852 | return $doc_preview_html; |
| 853 | } |
| 854 | |
| 855 | /** |
| 856 | * Retrieve absolute path of the given file ( $file ) assiciated with the given package id ( $pid ) |
| 857 | * |
| 858 | * @param $file |
| 859 | * @param $pid |
| 860 | * |
| 861 | * @return string |
| 862 | */ |
| 863 | public static function fullPath( $file, $pid ) { |
| 864 | $post = get_post( $pid ); |
| 865 | $user = get_user_by( 'id', $post->post_author ); |
| 866 | $user_upload_dir = UPLOAD_DIR . $user->user_login . '/'; |
| 867 | if ( file_exists( UPLOAD_DIR . $file ) ) { |
| 868 | $fullpath = UPLOAD_DIR . $file; |
| 869 | } else if ( file_exists( $user_upload_dir . $file ) ) { |
| 870 | $fullpath = $user_upload_dir . $file; |
| 871 | } else if ( file_exists( $file ) ) { |
| 872 | $fullpath = $file; |
| 873 | } else { |
| 874 | $fullpath = ''; |
| 875 | } |
| 876 | |
| 877 | return $fullpath; |
| 878 | } |
| 879 | |
| 880 | /** |
| 881 | * Get the file extension |
| 882 | * |
| 883 | * @param $file |
| 884 | * |
| 885 | * @return string |
| 886 | */ |
| 887 | public static function fileExt( $file ) { |
| 888 | $ext = pathinfo( $file, PATHINFO_EXTENSION ); |
| 889 | $ext = strtolower( $ext ); |
| 890 | if ( $ext === '' ) { |
| 891 | $ext = "|=|"; |
| 892 | } |
| 893 | |
| 894 | return $ext; |
| 895 | } |
| 896 | |
| 897 | public static function mimeTypes( $ext = false ) { |
| 898 | $mimeTypes = [ |
| 899 | // Images |
| 900 | 'jpg' => ['image/jpeg', 'image/pjpeg'], |
| 901 | 'jpeg' => ['image/jpeg', 'image/pjpeg'], |
| 902 | 'png' => ['image/png'], |
| 903 | 'gif' => ['image/gif'], |
| 904 | 'bmp' => ['image/bmp', 'image/x-windows-bmp'], |
| 905 | 'svg' => ['image/svg+xml'], |
| 906 | 'webp' => ['image/webp'], |
| 907 | 'ico' => ['image/x-icon', 'image/vnd.microsoft.icon'], |
| 908 | |
| 909 | // Documents |
| 910 | 'pdf' => ['application/pdf'], |
| 911 | 'doc' => ['application/msword'], |
| 912 | 'docx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'], |
| 913 | 'xls' => ['application/vnd.ms-excel'], |
| 914 | 'xlsx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], |
| 915 | 'ppt' => ['application/vnd.ms-powerpoint'], |
| 916 | 'pptx' => ['application/vnd.openxmlformats-officedocument.presentationml.presentation'], |
| 917 | 'odt' => ['application/vnd.oasis.opendocument.text'], |
| 918 | 'ods' => ['application/vnd.oasis.opendocument.spreadsheet'], |
| 919 | 'txt' => ['text/plain'], |
| 920 | 'rtf' => ['application/rtf', 'text/rtf'], |
| 921 | |
| 922 | // Archives |
| 923 | 'zip' => ['application/zip', 'application/x-zip-compressed'], |
| 924 | 'rar' => ['application/x-rar-compressed', 'application/vnd.rar'], |
| 925 | 'tar' => ['application/x-tar'], |
| 926 | 'gz' => ['application/gzip'], |
| 927 | '7z' => ['application/x-7z-compressed'], |
| 928 | |
| 929 | // Audio |
| 930 | 'mp3' => ['audio/mpeg', 'audio/mp3'], |
| 931 | 'wav' => ['audio/wav', 'audio/x-wav'], |
| 932 | 'ogg' => ['audio/ogg', 'application/ogg'], |
| 933 | 'flac' => ['audio/flac'], |
| 934 | 'm4a' => ['audio/mp4', 'audio/x-m4a'], |
| 935 | |
| 936 | // Video |
| 937 | 'mp4' => ['video/mp4'], |
| 938 | 'avi' => ['video/x-msvideo'], |
| 939 | 'mov' => ['video/quicktime'], |
| 940 | 'wmv' => ['video/x-ms-wmv'], |
| 941 | 'mkv' => ['video/x-matroska'], |
| 942 | 'webm' => ['video/webm'], |
| 943 | |
| 944 | // Web |
| 945 | 'html' => ['text/html'], |
| 946 | 'htm' => ['text/html'], |
| 947 | 'css' => ['text/css'], |
| 948 | 'js' => ['application/javascript', 'text/javascript'], |
| 949 | 'json' => ['application/json'], |
| 950 | 'xml' => ['application/xml', 'text/xml'], |
| 951 | |
| 952 | // Programming |
| 953 | 'php' => ['text/x-php', 'application/x-httpd-php', 'text/php'], |
| 954 | 'py' => ['text/x-python', 'application/x-python'], |
| 955 | 'java' => ['text/x-java-source', 'text/java'], |
| 956 | 'c' => ['text/x-c'], |
| 957 | 'cpp' => ['text/x-c++', 'text/x-c++src'], |
| 958 | 'cs' => ['text/x-csharp'], |
| 959 | 'rb' => ['text/x-ruby'], |
| 960 | 'go' => ['text/x-go'], |
| 961 | 'pl' => ['text/x-perl'], |
| 962 | 'sh' => ['text/x-shellscript', 'application/x-sh'], |
| 963 | |
| 964 | // Fonts |
| 965 | 'ttf' => ['application/x-font-ttf', 'font/ttf'], |
| 966 | 'otf' => ['application/x-font-opentype', 'font/otf'], |
| 967 | 'woff' => ['application/font-woff', 'font/woff'], |
| 968 | 'woff2' => ['application/font-woff2', 'font/woff2'], |
| 969 | 'eot' => ['application/vnd.ms-fontobject'], |
| 970 | |
| 971 | // Other |
| 972 | 'csv' => ['text/csv'], |
| 973 | 'sql' => ['application/sql', 'text/x-sql'], |
| 974 | 'apk' => ['application/vnd.android.package-archive'], |
| 975 | 'exe' => ['application/x-msdownload', 'application/x-executable'], |
| 976 | 'dll' => ['application/x-msdownload'], |
| 977 | 'bin' => ['application/octet-stream'], |
| 978 | 'iso' => ['application/x-iso9660-image'], |
| 979 | 'dmg' => ['application/x-apple-diskimage'], |
| 980 | 'torrent' => ['application/x-bittorrent'], |
| 981 | 'srt' => ['application/x-subrip'], |
| 982 | ]; |
| 983 | $mimeTypes = apply_filters( 'wpdm_mime_types', $mimeTypes ); |
| 984 | $foundMimeTypes = $ext === false ? $mimeTypes : wpdm_valueof($mimeTypes, $ext); |
| 985 | return is_array($foundMimeTypes) ? $foundMimeTypes : ['application/octet-stream']; |
| 986 | } |
| 987 | |
| 988 | public static function getMimeType($file) { |
| 989 | if(!class_exists( '\finfo' )) { |
| 990 | if(function_exists('mime_content_type')) |
| 991 | return mime_content_type( $file ); |
| 992 | error_log("WPDM: Enable file info extension to use mime type detection. See: https://www.php.net/manual/en/book.finfo.php"); |
| 993 | return false; |
| 994 | } |
| 995 | $finfo = new \finfo(FILEINFO_MIME_TYPE); |
| 996 | if($finfo) { |
| 997 | $mimeType = $finfo->file( $file ); |
| 998 | return $mimeType; |
| 999 | } else { |
| 1000 | return false; |
| 1001 | } |
| 1002 | } |
| 1003 | |
| 1004 | /** |
| 1005 | * Validates if a file's actual type matches its extension |
| 1006 | * |
| 1007 | * This function examines the file content to determine its actual type |
| 1008 | * and compares it with the expected type based on the file extension. |
| 1009 | * It helps prevent security issues like XSS by ensuring users cannot |
| 1010 | * upload unauthorized file types by simply changing the extension. |
| 1011 | * |
| 1012 | * @param string $filePath Path to the file to be validated |
| 1013 | * @return array Returns an array with the following keys: |
| 1014 | * - 'valid' (bool): Whether the file type matches the extension |
| 1015 | * - 'message' (string): Detailed explanation of the result |
| 1016 | * - 'actual_type' (string): The detected MIME type |
| 1017 | * - 'expected_type' (string): The expected MIME type based on extension |
| 1018 | * - 'extension' (string): The file extension |
| 1019 | */ |
| 1020 | public static function validateFileType($filePath) { |
| 1021 | // Initialize the result array |
| 1022 | $result = [ |
| 1023 | 'valid' => false, |
| 1024 | 'message' => '', |
| 1025 | 'actual_type' => '', |
| 1026 | 'expected_type' => '', |
| 1027 | 'extension' => '' |
| 1028 | ]; |
| 1029 | |
| 1030 | // Check if file exists |
| 1031 | if (!file_exists($filePath)) { |
| 1032 | $result['message'] = 'Error: File does not exist'; |
| 1033 | return $result; |
| 1034 | } |
| 1035 | |
| 1036 | // Check if file is readable |
| 1037 | if (!is_readable($filePath)) { |
| 1038 | $result['message'] = 'Error: File is not readable'; |
| 1039 | return $result; |
| 1040 | } |
| 1041 | |
| 1042 | // Get file extension |
| 1043 | $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); |
| 1044 | $result['extension'] = $extension; |
| 1045 | |
| 1046 | // If no extension, we can't validate |
| 1047 | if (empty($extension)) { |
| 1048 | $result['message'] = 'Error: File has no extension'; |
| 1049 | return $result; |
| 1050 | } |
| 1051 | |
| 1052 | // Get actual MIME type using finfo |
| 1053 | $actualType = self::getMimeType($filePath); |
| 1054 | $result['actual_type'] = $actualType; |
| 1055 | |
| 1056 | // Get expected MIME type based on extension |
| 1057 | $expectedTypes = self::mimeTypes($extension); |
| 1058 | |
| 1059 | $result['expected_type'] = implode(' or ', $expectedTypes); |
| 1060 | |
| 1061 | // Check if actual type matches any of the expected types |
| 1062 | $isValid = in_array($actualType, $expectedTypes); |
| 1063 | |
| 1064 | // Set result values |
| 1065 | $result['valid'] = $isValid; |
| 1066 | |
| 1067 | // Set appropriate message if not already set |
| 1068 | if (empty($result['message'])) { |
| 1069 | if ($isValid) { |
| 1070 | $result['message'] = 'File type matches the extension'; |
| 1071 | } else { |
| 1072 | $result['message'] = 'File type does not match the extension'; |
| 1073 | } |
| 1074 | } |
| 1075 | |
| 1076 | return $result; |
| 1077 | } |
| 1078 | |
| 1079 | public static function validateMimeType($file, $ext) { |
| 1080 | $actualMimeType = self::getMimeType( $file ); |
| 1081 | $extMimeType = self::mimeTypes( $ext ); |
| 1082 | return in_array($actualMimeType, $extMimeType); |
| 1083 | } |
| 1084 | |
| 1085 | public static function validateUploadMimeType($tmp_file, $file_name) { |
| 1086 | if (function_exists('extension_loaded') && !extension_loaded('fileinfo')) { |
| 1087 | error_log("WPDM: Enable file info extension to use mime type detection. See: https://www.php.net/manual/en/book.finfo.php"); |
| 1088 | return true; |
| 1089 | } |
| 1090 | $ext = self::fileExt( $file_name ); |
| 1091 | $actualMimeType = self::getMimeType( $tmp_file ); |
| 1092 | $extMimeType = self::mimeTypes( $ext ); |
| 1093 | $isValidMimeType = in_array($actualMimeType, $extMimeType); |
| 1094 | if(!$isValidMimeType) |
| 1095 | error_log("Actual Mime Type: {$actualMimeType}. File Extension: {$ext}. Expected Mime Type: ".implode(" or ", $extMimeType)."."); |
| 1096 | $isValidMimeType = apply_filters("wpdm_is_valid_mime_type", $isValidMimeType, $actualMimeType, $extMimeType); |
| 1097 | return $isValidMimeType; |
| 1098 | } |
| 1099 | |
| 1100 | public static function mediaURL( $pid, $fileID, $fileName = '' ) { |
| 1101 | if ( $fileName == '' ) { |
| 1102 | $files = WPDM()->package->getFiles( $pid ); |
| 1103 | $fileName = wpdm_basename( $files[ $fileID ] ); |
| 1104 | } |
| 1105 | |
| 1106 | return WPDM()->package->expirableDownloadLink( $pid, 5, 1800 ) . "&ind={$fileID}&file={$fileName}"; |
| 1107 | } |
| 1108 | |
| 1109 | /** |
| 1110 | * Find or generate file type icon and returns the url |
| 1111 | * |
| 1112 | * @param $filename_or_ext |
| 1113 | * @param string $color |
| 1114 | * @param bool $return |
| 1115 | * |
| 1116 | * @return string File Type Icon URL |
| 1117 | */ |
| 1118 | static function fileTypeIcon( $filename_or_ext, $color = '#269def|#26bdef', $return = true ) { |
| 1119 | $ext = $filename_or_ext; |
| 1120 | if ( substr_count( $ext, '.' ) ) { |
| 1121 | $ext = self::fileExt( $ext ); |
| 1122 | } |
| 1123 | $upload_dir = wp_upload_dir(); |
| 1124 | $_upload_dir = $upload_dir['basedir']; |
| 1125 | $_upload_url = $upload_dir['baseurl']; |
| 1126 | $file_type_icon_url = ''; |
| 1127 | if ( file_exists( $_upload_dir . "/wpdm-file-type-icons/" . $ext . ".svg" ) ) { |
| 1128 | $file_type_icon_url = $_upload_url . "/wpdm-file-type-icons/" . $ext . ".svg"; |
| 1129 | } else if ( file_exists( WPDM_BASE_DIR . "assets/file-type-icons/" . $ext . ".svg" ) ) { |
| 1130 | $file_type_icon_url = WPDM_BASE_URL . "assets/file-type-icons/" . $ext . ".svg"; |
| 1131 | } |
| 1132 | if ( $file_type_icon_url === '' ) { |
| 1133 | ob_start(); |
| 1134 | $id = uniqid(); |
| 1135 | $ext = strtoupper( $ext ); |
| 1136 | $color = explode("|", $color); |
| 1137 | $ext = substr( $ext, 0, 3 ); |
| 1138 | ?> |
| 1139 | |
| 1140 | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"> |
| 1141 | <defs> |
| 1142 | <linearGradient id="gradient" x1="0" y1="0" x2="0" y2="1"> |
| 1143 | <stop stop-color="#269def" offset="0"/> |
| 1144 | <stop stop-color="#26bdef" offset="1"/> |
| 1145 | </linearGradient> |
| 1146 | </defs> |
| 1147 | <g> |
| 1148 | <rect fill="url(#gradient)" x="0" y="0" width="40" height="40" rx="3" ry="3"/> |
| 1149 | <text x="5" y="19" font-family="Arial, Helvetica, sans-serif" font-size="13px" letter-spacing="1" fill="#FFFFFF"> |
| 1150 | <tspan><?php echo $ext; ?></tspan> |
| 1151 | <tspan x="6" y="28">_</tspan> |
| 1152 | </text> |
| 1153 | </g> |
| 1154 | </svg> |
| 1155 | |
| 1156 | <?php |
| 1157 | $file_type_icon_url = ob_get_clean(); |
| 1158 | $file_type_icon_url = "data:image/svg+xml;base64," . base64_encode( $file_type_icon_url ); |
| 1159 | } |
| 1160 | $file_type_icon_url = apply_filters( "wpdm_file_type_icon", $file_type_icon_url, $filename_or_ext ); |
| 1161 | if ( $return ) { |
| 1162 | return $file_type_icon_url; |
| 1163 | } |
| 1164 | echo $file_type_icon_url; |
| 1165 | } |
| 1166 | |
| 1167 | /** |
| 1168 | * Generates a quick download url for the given file |
| 1169 | * |
| 1170 | * @param $file |
| 1171 | * @param int $expire |
| 1172 | * |
| 1173 | * @return string|void |
| 1174 | */ |
| 1175 | public static function instantDownloadURL( $file, $expire = 3600 ) { |
| 1176 | $id = uniqid(); |
| 1177 | TempStorage::set( "__wpdm_instant_download_{$id}", $file, $expire ); |
| 1178 | |
| 1179 | return home_url( "/?wpdmidl={$id}" ); |
| 1180 | } |
| 1181 | |
| 1182 | /** |
| 1183 | * Get allowed file type for upload |
| 1184 | * |
| 1185 | * @param bool $ARRAY |
| 1186 | * |
| 1187 | * @return array|false|int[]|mixed|string|string[]|void |
| 1188 | */ |
| 1189 | function getAllowedFileTypes( $ARRAY = true ) { |
| 1190 | $allowed_file_types = get_option( "__wpdm_allowed_file_types", '' ); |
| 1191 | if ( $allowed_file_types === '' || ! $allowed_file_types ) { |
| 1192 | $wp_allowed_file_types = get_allowed_mime_types(); |
| 1193 | $wp_allowed_file_exts = array_keys( $wp_allowed_file_types ); |
| 1194 | $wp_allowed_file_exts = implode( ",", $wp_allowed_file_exts ); |
| 1195 | $wp_allowed_file_exts = str_replace( "|", ",", $wp_allowed_file_exts ); |
| 1196 | $allowed_file_types = $wp_allowed_file_exts; |
| 1197 | } |
| 1198 | $wp_allowed_file_types_array = explode( ",", $allowed_file_types ); |
| 1199 | $wp_allowed_file_types_array = array_map( "trim", $wp_allowed_file_types_array ); |
| 1200 | |
| 1201 | return $ARRAY ? $wp_allowed_file_types_array : $allowed_file_types; |
| 1202 | } |
| 1203 | |
| 1204 | /** |
| 1205 | * Check for blocked file types |
| 1206 | * |
| 1207 | * @param $filename |
| 1208 | * @param string $abspath |
| 1209 | * |
| 1210 | * @return bool |
| 1211 | */ |
| 1212 | function isBlocked( $filename, $abspath = '' ) { |
| 1213 | if ( $filename === '' ) { |
| 1214 | return true; |
| 1215 | } |
| 1216 | |
| 1217 | $types = $this->getAllowedFileTypes(); |
| 1218 | |
| 1219 | if ( in_array( '*', $types ) ) { |
| 1220 | return false; |
| 1221 | } |
| 1222 | $ext = null; |
| 1223 | if ( $abspath && file_exists( $abspath ) ) { |
| 1224 | $mimes = wp_get_mime_types(); |
| 1225 | foreach ( $types as $type ) { |
| 1226 | if ( ! isset( $mimes[ $type ] ) ) { |
| 1227 | $mimes[ $type ] = 'application/' . $type; |
| 1228 | } |
| 1229 | } |
| 1230 | $fileinfo = wp_check_filetype_and_ext( $abspath, $filename, $mimes ); |
| 1231 | $ext = wpdm_valueof( $fileinfo, 'ext' ); |
| 1232 | } |
| 1233 | |
| 1234 | if ( ! $ext ) { |
| 1235 | $ext = self::fileExt( $filename ); |
| 1236 | } |
| 1237 | |
| 1238 | $ext = strtolower( $ext ); |
| 1239 | |
| 1240 | return ! in_array( $ext, $types ); |
| 1241 | } |
| 1242 | |
| 1243 | /** |
| 1244 | * Convert absolute path to relative path |
| 1245 | * |
| 1246 | * @param $abs_path |
| 1247 | * |
| 1248 | * @return array|string|string[] |
| 1249 | */ |
| 1250 | function relPath( $abs_path ) { |
| 1251 | $abs_path = str_replace( "\\", "/", $abs_path ); |
| 1252 | $up_root = str_replace( "\\", "/", UPLOAD_DIR ); |
| 1253 | $rel_path = str_replace( $up_root, "", $abs_path ); |
| 1254 | $abs_root = str_replace( "\\", "/", ABSPATH ); |
| 1255 | $rel_path = str_replace( $abs_root, "", $rel_path ); |
| 1256 | return $rel_path; |
| 1257 | } |
| 1258 | |
| 1259 | /** |
| 1260 | * <p>Resolve absolute file path from the given relative path, check file in all possible wpdm upload dirs</p> |
| 1261 | * <p>Returns absolute path if file is found, returns false if file is not found</p> |
| 1262 | * |
| 1263 | * @param $rel_path |
| 1264 | * @param null $pid |
| 1265 | * |
| 1266 | * @return bool|string |
| 1267 | */ |
| 1268 | function absPath( $rel_path, $pid = null ) { |
| 1269 | $abs_path = false; |
| 1270 | |
| 1271 | if(!$rel_path) return false; |
| 1272 | |
| 1273 | $upload_dir = wp_upload_dir(); |
| 1274 | $upload_base_url = $upload_dir['baseurl']; |
| 1275 | $upload_dir = $upload_dir['basedir']; |
| 1276 | |
| 1277 | //Covert media library url to file path |
| 1278 | if ( __::is_url( $rel_path ) ) { |
| 1279 | $abs_path = str_replace( $upload_base_url, $upload_dir, $rel_path ); |
| 1280 | if ( __::is_url( $abs_path ) ) { |
| 1281 | return $rel_path; |
| 1282 | } |
| 1283 | } |
| 1284 | |
| 1285 | if ( substr_count( $rel_path, './' ) ) { |
| 1286 | return false; |
| 1287 | } |
| 1288 | |
| 1289 | $fixed_abs_path = false; |
| 1290 | if ( substr_count( $rel_path, 'wp-content' ) > 0 && substr_count( $rel_path, WP_CONTENT_DIR ) === 0 ) { |
| 1291 | $rel_rel_path = explode( "wp-content", $rel_path ); |
| 1292 | $rel_rel_path = end( $rel_rel_path ); |
| 1293 | $fixed_abs_path = WP_CONTENT_DIR . $rel_rel_path; |
| 1294 | } |
| 1295 | |
| 1296 | $file_browser_root = get_option( '_wpdm_file_browser_root', '' ); |
| 1297 | $network_upload_dir = explode( "sites", UPLOAD_DIR ); |
| 1298 | $network_upload_dir = $network_upload_dir[0]; |
| 1299 | $network_upload_dir = $network_upload_dir . "download-manager-files/"; |
| 1300 | |
| 1301 | if ( file_exists( $rel_path ) ) { |
| 1302 | $abs_path = $rel_path; |
| 1303 | } else if ( file_exists( UPLOAD_DIR . $rel_path ) ) { |
| 1304 | $abs_path = UPLOAD_DIR . $rel_path; |
| 1305 | } else if ( file_exists( $network_upload_dir . $rel_path ) ) { |
| 1306 | $abs_path = $network_upload_dir . $rel_path; |
| 1307 | } else if ( file_exists( ABSPATH . $rel_path ) ) { |
| 1308 | $abs_path = ABSPATH . $rel_path; |
| 1309 | } else if ( file_exists( trailingslashit( $file_browser_root ) . $rel_path ) ) { |
| 1310 | $abs_path = trailingslashit( $file_browser_root ) . $rel_path; |
| 1311 | } else if ( $fixed_abs_path && file_exists( $fixed_abs_path ) ) { |
| 1312 | $abs_path = $fixed_abs_path; |
| 1313 | } else if ( $pid ) { |
| 1314 | $user_upload_dir = null; |
| 1315 | $package = get_post( $pid ); |
| 1316 | if ( is_object( $package ) ) { |
| 1317 | $author = get_user_by( 'id', $package->post_author ); |
| 1318 | if ( $author ) { |
| 1319 | $user_upload_dir = UPLOAD_DIR . $author->user_login . '/'; |
| 1320 | } |
| 1321 | } |
| 1322 | if ( $user_upload_dir && file_exists( $user_upload_dir . $rel_path ) ) { |
| 1323 | $abs_path = $user_upload_dir . $rel_path; |
| 1324 | } |
| 1325 | } |
| 1326 | |
| 1327 | $abs_path = str_replace( '\\', '/', $abs_path ); |
| 1328 | if ( ! $abs_path ) { |
| 1329 | return null; |
| 1330 | } |
| 1331 | $real_path = realpath( $abs_path ); |
| 1332 | |
| 1333 | return $real_path; |
| 1334 | } |
| 1335 | |
| 1336 | /** |
| 1337 | * Count pages in a PDF file |
| 1338 | * |
| 1339 | * @param $path |
| 1340 | * |
| 1341 | * @return int|string |
| 1342 | */ |
| 1343 | function countPDFPages( $path ) { |
| 1344 | if ( self::fileExt( $path ) !== 'pdf' ) { |
| 1345 | return 1; |
| 1346 | } |
| 1347 | $fp = @fopen( preg_replace( "/\[(.*?)\]/i", "", $path ), "r" ); |
| 1348 | $max = 0; |
| 1349 | if ( ! $fp ) { |
| 1350 | return "Could not open file: $path"; |
| 1351 | } else { |
| 1352 | while ( ! @feof( $fp ) ) { |
| 1353 | $line = @fgets( $fp, 255 ); |
| 1354 | if ( preg_match( '/\/Count [0-9]+/', $line, $matches ) ) { |
| 1355 | preg_match( '/[0-9]+/', $matches[0], $matches2 ); |
| 1356 | if ( $max < $matches2[0] ) { |
| 1357 | $max = trim( $matches2[0] ); |
| 1358 | break; |
| 1359 | } |
| 1360 | } |
| 1361 | } |
| 1362 | @fclose( $fp ); |
| 1363 | } |
| 1364 | |
| 1365 | return $max; |
| 1366 | } |
| 1367 | |
| 1368 | function filePermissions( $path, $parsed = true ) { |
| 1369 | $perm = substr( sprintf( '%o', fileperms( $path ) ), - 3 ); |
| 1370 | $perms = [ 'user' => $perm[0], 'group' => $perm[1], 'world' => $perm[2] ]; |
| 1371 | if ( ! $parsed ) { |
| 1372 | return $perm; |
| 1373 | } |
| 1374 | |
| 1375 | return $perms; |
| 1376 | } |
| 1377 | |
| 1378 | function locateFile( $file ) { |
| 1379 | return $this->absPath( $file ); |
| 1380 | } |
| 1381 | |
| 1382 | function allowedPath( $absPath ) { |
| 1383 | if ( ! $absPath ) { |
| 1384 | return false; |
| 1385 | } |
| 1386 | $absPath = str_replace( "\\", "/", $absPath ); |
| 1387 | $upload_dir = str_replace( "\\", "/", UPLOAD_DIR ); |
| 1388 | $upload_dir_real = realpath($upload_dir); |
| 1389 | $asset_root = str_replace( "\\", "/", AssetManager::root() ); |
| 1390 | $allowedPathCheck = apply_filters( "wpdm_allowed_path_check", true ); |
| 1391 | if ( substr_count( $absPath, $upload_dir ) || substr_count( $absPath, $upload_dir_real ) || substr_count( $absPath, $asset_root ) || ! $allowedPathCheck ) { |
| 1392 | return true; |
| 1393 | } |
| 1394 | |
| 1395 | return false; |
| 1396 | } |
| 1397 | |
| 1398 | function fileHash( $filePath ) { |
| 1399 | return hash_file('sha256', $filePath); |
| 1400 | } |
| 1401 | } |
| 1402 | |
| 1403 |