\n\tRequire all denied\n\n" . "\n\tOrder allow,deny\n\tDeny from all\n\n" . "\n" . "\t\n\t\tRequire all denied\n\t\n" . "\t\n\t\tOrder allow,deny\n\t\tDeny from all\n\t\n" . "\n", LOCK_EX ); } if ( ! file_exists( $web_config ) ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged @file_put_contents( $web_config, "\n" . "\n" . " \n" . " \n" . " \n" . " \n" . " \n" . "\n", LOCK_EX ); } if ( ! file_exists( $index ) ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged @file_put_contents( $index, "\n", LOCK_EX ); } } /** * Atomically replace the contents of a file. * * @param string $path Target path. * @param string $content Payload. * @return bool */ public static function atomic_put( string $path, string $content ): bool { $temp = $path . '.' . Str::random( 6 ) . '.tmp'; // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged if ( false === @file_put_contents( $temp, $content, LOCK_EX ) ) { return false; } // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged if ( ! @rename( $temp, $path ) ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged @unlink( $temp ); return false; } return true; } /** * Delete a file if it exists. * * @param string $path Absolute path. * @return bool */ public static function delete( string $path ): bool { if ( ! file_exists( $path ) ) { return true; } if ( function_exists( 'wp_delete_file' ) ) { wp_delete_file( $path ); if ( ! file_exists( $path ) ) { return true; } } // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged return (bool) @unlink( $path ); } /** * Recursively delete a directory. * * @param string $dir Absolute path. * @return bool */ public static function delete_dir( string $dir ): bool { if ( ! is_dir( $dir ) ) { return self::delete( $dir ); } $items = scandir( $dir ); if ( false === $items ) { return false; } foreach ( $items as $item ) { if ( '.' === $item || '..' === $item ) { continue; } $path = $dir . '/' . $item; if ( is_dir( $path ) && ! is_link( $path ) ) { self::delete_dir( $path ); } else { self::delete( $path ); } } // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged return (bool) @rmdir( $dir ); } /** * Size of a file in bytes, `0` when it cannot be read. * * @param string $path Absolute path. * @return int */ public static function size( string $path ): int { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged $size = is_file( $path ) ? @filesize( $path ) : 0; return false === $size ? 0 : (int) $size; } /** * Free disk space for the volume that contains a path. * * @param string $path Absolute path. * @return int Bytes, `-1` when unknown. */ public static function free_space( string $path ): int { $probe = $path; while ( $probe && ! file_exists( $probe ) ) { $parent = dirname( $probe ); if ( $parent === $probe ) { break; } $probe = $parent; } if ( ! function_exists( 'disk_free_space' ) ) { return -1; } // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged $free = @\disk_free_space( $probe ); return false === $free ? -1 : (int) $free; } /** * Whether a directory is writable. * * @param string $dir Absolute path. * @return bool */ public static function is_writable_dir( string $dir ): bool { return is_dir( $dir ) && is_writable( $dir ); } /** * Normalize a path to forward slashes without duplicate separators. * * @param string $path Path. * @return string */ public static function normalize( string $path ): string { $path = str_replace( '\\', '/', $path ); return (string) preg_replace( '#/+#', '/', $path ); } /** * Stream a file to the browser and stop execution. * * Uses a plain readfile loop so that large archives never hit memory limits. * * @param string $path Absolute path. * @param string $download_name Optional custom filename for the Content-Disposition header. * @return void */ /** * Stream in-memory string content as an attachment download and stop execution. * * @param string $content File content. * @param string $filename Filename for Content-Disposition header. * @return void */ public static function stream_string_download( string $content, string $filename ): void { $filename = str_replace( array( '"', "\r", "\n" ), '', $filename ); nocache_headers(); header( 'Content-Type: application/octet-stream' ); header( 'Content-Disposition: attachment; filename="' . $filename . '"' ); header( 'Content-Length: ' . (string) strlen( $content ) ); header( 'X-Accel-Buffering: no' ); while ( ob_get_level() > 0 ) { ob_end_flush(); } echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped exit; } public static function stream_download( string $path, string $download_name = '' ): void { if ( ! is_readable( $path ) ) { wp_die( esc_html__( 'The requested file does not exist.', 'backupino' ), '', array( 'response' => 404 ) ); } $filename = '' !== $download_name ? $download_name : basename( $path ); $filename = str_replace( array( '"', "\r", "\n" ), '', $filename ); nocache_headers(); header( 'Content-Type: application/octet-stream' ); header( 'Content-Disposition: attachment; filename="' . $filename . '"' ); header( 'Content-Length: ' . (string) self::size( $path ) ); header( 'X-Accel-Buffering: no' ); while ( ob_get_level() > 0 ) { ob_end_flush(); } // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_readfile, WordPress.WP.AlternativeFunctions.file_system_read_readfile readfile( $path ); exit; } }