| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | <?php |
| 2 | - | |
| 3 | 2 | if (!defined('ABSPATH')) exit; |
| 4 | 3 | if (!class_exists('BVFSWriteCallback')) : |
| 5 | 4 | |
| 6 | 5 | class BVFSWriteCallback extends BVCallbackBase { |
| @@ -5,9 +4,9 @@ | ||
| 5 | 4 | |
| 6 | 5 | class BVFSWriteCallback extends BVCallbackBase { |
| 7 | 6 | |
| 8 | 7 | const MEGABYTE = 1048576; |
| 9 | - const FS_WRITE_WING_VERSION = 1.0; | |
| 8 | + const FS_WRITE_WING_VERSION = 1.1; | |
| 10 | 9 | |
| 11 | 10 | public function __construct() { |
| 12 | 11 | } |
| 13 | 12 | |
| @@ -52,9 +51,9 @@ | ||
| 52 | 51 | $dir_result['error'] = "FILE_PRESENT_IN_PLACE_OF_DIR"; |
| 53 | 52 | } |
| 54 | 53 | |
| 55 | 54 | } else { |
| 56 | - | |
| 55 | + // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_mkdir -- Using mkdir() directly as there is no direct suport for recursion | |
| 57 | 56 | $dir_result['status'] = mkdir($dir, $permissions, $recursive); |
| 58 | 57 | if ($dir_result['status'] === false) { |
| 59 | 58 | $dir_result['error'] = "MKDIR_FAILED"; |
| 60 | 59 | } |
| @@ -70,31 +69,31 @@ | ||
| 70 | 69 | |
| 71 | 70 | public function removeDirs($dirs) { |
| 72 | 71 | $result = array(); |
| 73 | 72 | |
| 74 | - foreach($dirs as $dir) { | |
| 73 | + foreach ($dirs as $dir) { | |
| 75 | 74 | $dir_result = array(); |
| 76 | 75 | |
| 77 | - if (is_dir($dir) && !is_link($dir)) { | |
| 78 | - | |
| 76 | + if ((WPRWPFileSystem::getInstance()->isDir($dir) === true) && !is_link($dir)) { | |
| 79 | 77 | if ($this->isEmptyDir($dir)) { |
| 80 | - | |
| 81 | - $dir_result['status'] = rmdir($dir); | |
| 78 | + $dir_result['status'] = WPRWPFileSystem::getInstance()->rmdir($dir); | |
| 82 | 79 | if ($dir_result['status'] === false) { |
| 83 | 80 | $dir_result['error'] = "RMDIR_FAILED"; |
| 81 | + $fs_error = WPRWPFileSystem::getInstance()->checkForErrors(); | |
| 82 | + if (isset($fs_error)) { | |
| 83 | + $dir_result['fs_error'] = $fs_error; | |
| 84 | + } | |
| 84 | 85 | } |
| 85 | - | |
| 86 | 86 | } else { |
| 87 | 87 | $dir_result['status'] = false; |
| 88 | 88 | $dir_result['error'] = "NOT_EMPTY"; |
| 89 | 89 | } |
| 90 | - | |
| 91 | 90 | } else { |
| 92 | 91 | $dir_result['status'] = false; |
| 93 | 92 | $dir_result['error'] = "NOT_DIR"; |
| 94 | 93 | } |
| 95 | 94 | |
| 96 | - $result[$dir] = $dir_result; | |
| 95 | + $result[$dir] = $dir_result; | |
| 97 | 96 | } |
| 98 | 97 | |
| 99 | 98 | $result['status'] = true; |
| 100 | 99 | return $result; |
| @@ -116,18 +115,20 @@ | ||
| 116 | 115 | |
| 117 | 116 | public function doChmod($path_infos) { |
| 118 | 117 | $result = array(); |
| 119 | 118 | |
| 120 | - foreach($path_infos as $path => $mode) { | |
| 119 | + foreach ($path_infos as $path => $mode) { | |
| 121 | 120 | $path_result = array(); |
| 122 | 121 | |
| 123 | - if (file_exists($path)) { | |
| 124 | - | |
| 125 | - $path_result['status'] = chmod($path, $mode); | |
| 122 | + if (WPRWPFileSystem::getInstance()->exists($path) === true) { | |
| 123 | + $path_result['status'] = WPRWPFileSystem::getInstance()->chmod($path, $mode); | |
| 126 | 124 | if ($path_result['status'] === false) { |
| 127 | 125 | $path_result['error'] = "CHMOD_FAILED"; |
| 126 | + $fs_error = WPRWPFileSystem::getInstance()->checkForErrors(); | |
| 127 | + if (isset($fs_error)) { | |
| 128 | + $path_result['fs_error'] = $fs_error; | |
| 129 | + } | |
| 128 | 130 | } |
| 129 | - | |
| 130 | 131 | } else { |
| 131 | 132 | $path_result['status'] = false; |
| 132 | 133 | $path_result['error'] = "NOT_FOUND"; |
| 133 | 134 | } |
| @@ -138,8 +139,12 @@ | ||
| 138 | 139 | $result['status'] = true; |
| 139 | 140 | return $result; |
| 140 | 141 | } |
| 141 | 142 | |
| 143 | + // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fopen | |
| 144 | + // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fread | |
| 145 | + // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fwrite | |
| 146 | + // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fclose | |
| 142 | 147 | public function concatFiles($ifiles, $ofile, $bsize, $offset) { |
| 143 | 148 | if (($offset !== 0) && (!file_exists($ofile))) { |
| 144 | 149 | return array( |
| 145 | 150 | 'status' => false, |
| @@ -216,23 +221,29 @@ | ||
| 216 | 221 | } |
| 217 | 222 | |
| 218 | 223 | return $result; |
| 219 | 224 | } |
| 225 | + // phpcs:enable | |
| 220 | 226 | |
| 221 | 227 | public function renameFiles($path_infos) { |
| 222 | 228 | $result = array(); |
| 223 | 229 | |
| 224 | - foreach($path_infos as $oldpath => $newpath) { | |
| 230 | + foreach ($path_infos as $oldpath => $newpath) { | |
| 225 | 231 | $action_result = array(); |
| 226 | - $failed = array(); | |
| 227 | 232 | |
| 228 | - if (file_exists($oldpath)) { | |
| 229 | - | |
| 230 | - $action_result['status'] = rename($oldpath, $newpath); | |
| 233 | + if (WPRWPFileSystem::getInstance()->exists($oldpath)) { | |
| 234 | + $action_result['status'] = WPRWPFileSystem::getInstance()->move($oldpath, $newpath, true); | |
| 231 | 235 | if ($action_result['status'] === false) { |
| 232 | 236 | $action_result['error'] = "RENAME_FAILED"; |
| 237 | + $fs_error = WPRWPFileSystem::getInstance()->checkForErrors(); | |
| 238 | + if (isset($fs_error)) { | |
| 239 | + $action_result['fs_error'] = $fs_error; | |
| 240 | + } | |
| 241 | + } else { | |
| 242 | + if (function_exists('opcache_invalidate')) { | |
| 243 | + $action_result['opcache'] = opcache_invalidate($newpath, true); | |
| 244 | + } | |
| 233 | 245 | } |
| 234 | - | |
| 235 | 246 | } else { |
| 236 | 247 | $action_result['status'] = false; |
| 237 | 248 | $action_result['error'] = "NOT_FOUND"; |
| 238 | 249 | } |
| @@ -244,8 +255,9 @@ | ||
| 244 | 255 | return $result; |
| 245 | 256 | } |
| 246 | 257 | |
| 247 | 258 | public function curlFile($ifile_url, $ofile, $timeout) { |
| 259 | + // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen | |
| 248 | 260 | $fp = fopen($ofile, "wb+"); |
| 249 | 261 | if ($fp === false) { |
| 250 | 262 | return array( |
| 251 | 263 | 'error' => 'FOPEN_FAILED_FOR_TEMP_OFILE' |
| @@ -252,10 +264,11 @@ | ||
| 252 | 264 | ); |
| 253 | 265 | } |
| 254 | 266 | |
| 255 | 267 | $result = array(); |
| 268 | + | |
| 269 | + // phpcs:disable WordPress.WP.AlternativeFunctions.curl_curl_init, WordPress.WP.AlternativeFunctions.curl_curl_exec, WordPress.WP.AlternativeFunctions.curl_curl_setopt, WordPress.WP.AlternativeFunctions.curl_curl_close, WordPress.WP.AlternativeFunctions.curl_curl_error, WordPress.WP.AlternativeFunctions.curl_curl_errno | |
| 256 | 270 | $ch = curl_init($ifile_url); |
| 257 | - curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); | |
| 258 | 271 | curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); |
| 259 | 272 | curl_setopt($ch, CURLOPT_HEADER, 0); |
| 260 | 273 | curl_setopt($ch, CURLOPT_FILE, $fp); |
| 261 | 274 | |
| @@ -264,15 +277,21 @@ | ||
| 264 | 277 | $result['errorno'] = curl_errno($ch); |
| 265 | 278 | } |
| 266 | 279 | |
| 267 | 280 | curl_close($ch); |
| 281 | + | |
| 282 | + // phpcs:enable WordPress.WP.AlternativeFunctions.curl_curl_init, WordPress.WP.AlternativeFunctions.curl_curl_exec, WordPress.WP.AlternativeFunctions.curl_curl_setopt, WordPress.WP.AlternativeFunctions.curl_curl_close, WordPress.WP.AlternativeFunctions.curl_curl_error, WordPress.WP.AlternativeFunctions.curl_curl_errno | |
| 283 | + | |
| 284 | + // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose | |
| 268 | 285 | fclose($fp); |
| 269 | 286 | |
| 287 | + | |
| 270 | 288 | return $result; |
| 271 | 289 | } |
| 272 | 290 | |
| 273 | 291 | public function streamCopyFile($ifile_url, $ofile) { |
| 274 | 292 | $result = array(); |
| 293 | + // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen | |
| 275 | 294 | $handle = fopen($ifile_url, "rb"); |
| 276 | 295 | |
| 277 | 296 | if ($handle === false) { |
| 278 | 297 | return array( |
| @@ -279,11 +298,12 @@ | ||
| 279 | 298 | 'error' => "UNABLE_TO_OPEN_REMOTE_FILE_STREAM" |
| 280 | 299 | ); |
| 281 | 300 | } |
| 282 | 301 | |
| 302 | + // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen | |
| 283 | 303 | $fp = fopen($ofile, "wb+"); |
| 284 | 304 | if ($fp === false) { |
| 285 | - fclose($handle); | |
| 305 | + fclose($handle); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose | |
| 286 | 306 | |
| 287 | 307 | return array( |
| 288 | 308 | 'error' => 'FOPEN_FAILED_FOR_OFILE' |
| 289 | 309 | ); |
| @@ -292,10 +312,10 @@ | ||
| 292 | 312 | if (stream_copy_to_stream($handle, $fp) === false) { |
| 293 | 313 | $result['error'] = "UNABLE_TO_WRITE_TO_TMP_OFILE"; |
| 294 | 314 | } |
| 295 | 315 | |
| 296 | - fclose($handle); | |
| 297 | - fclose($fp); | |
| 316 | + fclose($handle); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose | |
| 317 | + fclose($fp); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose | |
| 298 | 318 | |
| 299 | 319 | return $result; |
| 300 | 320 | } |
| 301 | 321 | |
| @@ -301,20 +321,16 @@ | ||
| 301 | 321 | |
| 302 | 322 | public function writeContentToFile($content, $ofile) { |
| 303 | 323 | $result = array(); |
| 304 | 324 | |
| 305 | - $fp = fopen($ofile, "wb+"); | |
| 306 | - if ($fp === false) { | |
| 307 | - return array( | |
| 308 | - 'error' => 'FOPEN_FAILED_FOR_TEMP_OFILE' | |
| 309 | - ); | |
| 325 | + if (WPRWPFileSystem::getInstance()->putContents($ofile, $content) === false) { | |
| 326 | + $result['error'] = 'UNABLE_TO_WRITE_TO_TMP_OFILE'; | |
| 327 | + $fs_error = WPRWPFileSystem::getInstance()->checkForErrors(); | |
| 328 | + if (isset($fs_error)) { | |
| 329 | + $result['fs_error'] = $fs_error; | |
| 330 | + } | |
| 310 | 331 | } |
| 311 | 332 | |
| 312 | - if (fwrite($fp, $content) === false) { | |
| 313 | - $result['error'] = "UNABLE_TO_WRITE_TO_TMP_OFILE"; | |
| 314 | - } | |
| 315 | - fclose($fp); | |
| 316 | - | |
| 317 | 333 | return $result; |
| 318 | 334 | } |
| 319 | 335 | |
| 320 | 336 | public function moveUploadedFile($ofile) { |
| @@ -319,12 +335,17 @@ | ||
| 319 | 335 | |
| 320 | 336 | public function moveUploadedFile($ofile) { |
| 321 | 337 | $result = array(); |
| 322 | 338 | |
| 339 | + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing | |
| 323 | 340 | if (isset($_FILES['myfile'])) { |
| 341 | + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing -- tmp_name is a path and nonce is ignored here | |
| 324 | 342 | $myfile = $_FILES['myfile']; |
| 325 | 343 | $is_upload_ok = false; |
| 326 | 344 | |
| 345 | + // Validate PHP upload errors manually | |
| 346 | + // This approach handles any file type (PHP, ZIP, SQL, etc.) without MIME restrictions | |
| 347 | + // Uses WordPress Filesystem API instead of wp_handle_upload() which is designed for media uploads | |
| 327 | 348 | switch ($myfile['error']) { |
| 328 | 349 | case UPLOAD_ERR_OK: |
| 329 | 350 | $is_upload_ok = true; |
| 330 | 351 | break; |
| @@ -344,10 +365,28 @@ | ||
| 344 | 365 | $is_upload_ok = false; |
| 345 | 366 | } |
| 346 | 367 | |
| 347 | 368 | if ($is_upload_ok) { |
| 348 | - if (move_uploaded_file($myfile['tmp_name'], $ofile) === false) { | |
| 369 | + $tmp_name = $myfile['tmp_name']; | |
| 370 | + | |
| 371 | + // Ensure target directory exists | |
| 372 | + $target_dir = dirname($ofile); | |
| 373 | + if (!file_exists($target_dir)) { | |
| 374 | + // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_mkdir -- Using mkdir() directly as there is no direct support for recursion | |
| 375 | + if (!mkdir($target_dir, 0777, true)) { | |
| 376 | + $result['error'] = 'MKDIR_FAILED_FOR_TARGET'; | |
| 377 | + return $result; | |
| 378 | + } | |
| 379 | + } | |
| 380 | + | |
| 381 | + // Use WordPress Filesystem API to move the uploaded file | |
| 382 | + // This is WordPress.org compliant and handles any file type | |
| 383 | + if (WPRWPFileSystem::getInstance()->move($tmp_name, $ofile, true) === false) { | |
| 349 | 384 | $result['error'] = 'MOVE_UPLOAD_FILE_FAILED'; |
| 385 | + $fs_error = WPRWPFileSystem::getInstance()->checkForErrors(); | |
| 386 | + if (isset($fs_error)) { | |
| 387 | + $result['fs_error'] = $fs_error; | |
| 388 | + } | |
| 350 | 389 | } |
| 351 | 390 | } |
| 352 | 391 | |
| 353 | 392 | } else { |