Don't use full log file names in the UI

This commit is contained in:
Corey McKrill 2023-10-27 17:55:32 -07:00
parent daaab7acc8
commit 2fe04da8f4
No known key found for this signature in database
GPG Key ID: 84BBFE669C4D97B8
4 changed files with 84 additions and 29 deletions

View File

@ -138,6 +138,28 @@ class File {
return $this->hash;
}
/**
* Get the file's public ID.
*
* The file ID is the basename of the file without the hash part. It allows us to identify a file without revealing
* its full name in the filesystem, so that it's difficult to access the file directly with an HTTP request.
*
* @return string
*/
public function get_file_id(): string {
$file_id = $this->get_source();
if ( ! is_null( $this->get_rotation() ) ) {
$file_id .= '.' . $this->get_rotation();
}
if ( $this->get_source() !== $this->get_hash() ) {
$file_id .= '-' . gmdate( 'Y-m-d', $this->get_created_timestamp() );
}
return $file_id;
}
/**
* Get the file's created property.
*

View File

@ -57,9 +57,9 @@ class FileController {
$args = wp_parse_args( $args, self::DEFAULTS_GET_FILES );
$pattern = $args['source'] . '*.log';
$files = glob( $this->log_directory . $pattern );
$paths = glob( $this->log_directory . $pattern );
if ( false === $files ) {
if ( false === $paths ) {
return new WP_Error(
'wc_log_directory_error',
__( 'Could not access the log file directory.', 'woocommerce' )
@ -67,20 +67,10 @@ class FileController {
}
if ( true === $count_only ) {
return count( $files );
return count( $paths );
}
$files = array_map(
function( $file_path ) {
if ( ! is_readable( $file_path ) ) {
return null;
}
return new File( $file_path );
},
$files
);
$files = array_filter( $files );
$files = $this->convert_paths_to_objects( $paths );
$multi_sorter = function( $sort_sets, $order_sets ) {
$comparison = 0;
@ -155,14 +145,57 @@ class FileController {
return array_slice( $files, $args['offset'], $args['per_page'] );
}
/**
* Get one or more File instances from an array of file IDs.
*
* @param array $file_ids An array of file IDs (file basename without the hash).
*
* @return File[]
*/
public function get_files_by_id( array $file_ids ): array {
$paths = array();
foreach ( $file_ids as $file_id ) {
$glob = glob( $this->log_directory . $file_id . '*.log' );
$paths = array_merge( $paths, $glob );
}
$files = $this->convert_paths_to_objects( $paths );
return $files;
}
/**
* Helper method to get an array of File instances.
*
* @param array $paths An array of absolute file paths.
*
* @return File[]
*/
private function convert_paths_to_objects( array $paths ): array {
$files = array_map(
function( $path ) {
if ( ! is_readable( $path ) ) {
return null;
}
return new File( $path );
},
$paths
);
return array_filter( $files );
}
/**
* Get a list of sources for existing log files.
*
* @return array|WP_Error
*/
public function get_file_sources() {
$files = glob( $this->log_directory . '*.log' );
if ( false === $files ) {
$paths = glob( $this->log_directory . '*.log' );
if ( false === $paths ) {
return new WP_Error(
'wc_log_directory_error',
__( 'Could not access the log file directory.', 'woocommerce' )
@ -174,7 +207,7 @@ class FileController {
$file = new File( $path );
return $file->get_source();
},
$files
$paths
);
return array_unique( $all_sources );
@ -183,15 +216,15 @@ class FileController {
/**
* Delete one or more files from the filesystem.
*
* @param array $files An array of file basenames (filename without the path).
* @param array $file_ids An array of file IDs (file basename without the hash).
*
* @return int
*/
public function delete_files( array $files ): int {
public function delete_files( array $file_ids ): int {
$deleted = 0;
foreach ( $files as $basename ) {
$file = new File( $this->log_directory . $basename );
$files = $this->get_files_by_id( $file_ids );
foreach ( $files as $file ) {
$result = $file->delete();
if ( true === $result ) {

View File

@ -227,10 +227,10 @@ class ListTable extends WP_List_Table {
ob_start();
?>
<input
id="cb-select-<?php echo esc_attr( $item->get_hash() ); ?>"
id="cb-select-<?php echo esc_attr( $item->get_file_id() ); ?>"
type="checkbox"
name="file[]"
value="<?php echo esc_attr( $item->get_basename() ); ?>"
value="<?php echo esc_attr( $item->get_file_id() ); ?>"
/>
<label for="cb-select-<?php echo esc_attr( $item->get_hash() ); ?>">
<span class="screen-reader-text">
@ -256,7 +256,7 @@ class ListTable extends WP_List_Table {
* @return string
*/
public function column_source( $item ): string {
$log_file = sanitize_title( $item->get_basename() );
$log_file = $item->get_file_id();
$single_file_url = add_query_arg(
array(
'view' => 'single_file',
@ -274,8 +274,8 @@ class ListTable extends WP_List_Table {
return sprintf(
'<a class="row-title" href="%1$s">%2$s</a>%3$s',
$single_file_url,
$item->get_source(),
esc_url( $single_file_url ),
esc_html( $item->get_source() ),
$rotation
);
}

View File

@ -274,7 +274,7 @@ class PageController {
$sendback = remove_query_arg( array( 'deleted' ), wp_get_referer() );
// Multiple file[] params will be filtered separately, but assigned to $files as an array.
$files = filter_input(
$file_ids = filter_input(
INPUT_GET,
'file',
FILTER_CALLBACK,
@ -285,14 +285,14 @@ class PageController {
)
);
if ( ! is_array( $files ) || count( $files ) < 1 ) {
if ( ! is_array( $file_ids ) || count( $file_ids ) < 1 ) {
wp_safe_redirect( $sendback );
exit;
}
switch ( $action ) {
case 'delete':
$deleted = $this->file_controller->delete_files( $files );
$deleted = $this->file_controller->delete_files( $file_ids );
$sendback = add_query_arg( 'deleted', $deleted, $sendback );
break;
}