diff --git a/src/classes/api/endpoints/class-tainacan-rest-background-processes-controller.php b/src/classes/api/endpoints/class-tainacan-rest-background-processes-controller.php index 425dc190e..ffb435a58 100644 --- a/src/classes/api/endpoints/class-tainacan-rest-background-processes-controller.php +++ b/src/classes/api/endpoints/class-tainacan-rest-background-processes-controller.php @@ -84,7 +84,6 @@ class REST_Background_Processes_Controller extends REST_Controller { ), )); register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P[0-9]+)', array( - array( 'methods' => \WP_REST_Server::READABLE, 'callback' => array($this, 'get_item'), @@ -93,7 +92,6 @@ class REST_Background_Processes_Controller extends REST_Controller { )); register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P[0-9]+)', array( - array( 'methods' => \WP_REST_Server::EDITABLE, 'callback' => array($this, 'update_item'), @@ -112,7 +110,6 @@ class REST_Background_Processes_Controller extends REST_Controller { )); register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P[0-9]+)', array( - array( 'methods' => \WP_REST_Server::DELETABLE, 'callback' => array($this, 'delete_item'), @@ -121,6 +118,14 @@ class REST_Background_Processes_Controller extends REST_Controller { ), )); + register_rest_route($this->namespace, '/' . $this->rest_base . '/file', array( + array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => array($this, 'get_file'), + 'permission_callback' => array($this, 'bg_processes_permissions_check'), + ), + + )); } @@ -131,7 +136,7 @@ class REST_Background_Processes_Controller extends REST_Controller { * @return bool|\WP_Error * @throws \Exception */ - public function bg_processes_permissions_check($request){ + public function bg_processes_permissions_check($request) { // TODO return current_user_can('read'); } @@ -246,6 +251,8 @@ class REST_Background_Processes_Controller extends REST_Controller { public function prepare_item_for_response($item, $request) { $item->log = $this->get_log_url($item->ID, $item->action); $item->error_log = $this->get_log_url($item->ID, $item->action, 'error'); + $nonce = wp_create_nonce( 'wp_rest' ); + $item->output = str_replace("&_wpnonce=[nonce]", "&_wpnonce=$nonce", $item->output); return $item; } @@ -353,11 +360,33 @@ class REST_Background_Processes_Controller extends REST_Controller { if (!file_exists( $upload_url['basedir'] . '/tainacan/' . $filename )) { return null; } - - $upload_url = trailingslashit( $upload_url['baseurl'] ); - $logs_url = $upload_url . 'tainacan/' . $filename; - + $nonce = wp_create_nonce( 'wp_rest' ); + $logs_url = esc_url_raw( rest_url() ) . "tainacan/v2/bg-processes/file?guid=$filename&_wpnonce=$nonce"; return $logs_url; } + public function get_file( $request ) { + if( !isset($request['guid']) ) { + return new \WP_REST_Response([ + 'error_message' => __('guid must be specified', 'tainacan' ) + ], 400); + } + $guid = $request['guid']; + $upload_url = wp_upload_dir(); + $path = $upload_url['basedir'] . '/tainacan/' . $guid; + if ( file_exists( $path ) ) { + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $mime_type = finfo_file($finfo, $path); + $file_name = basename($path); + http_response_code(200); + header('Content-Description: File Transfer'); + header("Content-Disposition: attachment; filename=$file_name"); + header("Content-Type: $mime_type"); + header("Content-Length: " . filesize( $path )); + \readfile($path); + } else { + return new \WP_REST_Response("file not found", 404, array('content-type' => 'text/html; charset=utf-8')); + } + } + } diff --git a/src/classes/exporter/class-tainacan-exporter.php b/src/classes/exporter/class-tainacan-exporter.php index ef6d4634f..91846aab3 100644 --- a/src/classes/exporter/class-tainacan-exporter.php +++ b/src/classes/exporter/class-tainacan-exporter.php @@ -695,7 +695,7 @@ abstract class Exporter { $upload_dir_info = wp_upload_dir(); $prefix = $this->get_id(); $upload_dir = trailingslashit( $upload_dir_info['basedir'] ); - $upload_url = trailingslashit( $upload_dir_info['baseurl'] ); + // $upload_url = trailingslashit( $upload_dir_info['baseurl'] ); $exporter_folder = 'tainacan/exporter'; $file_suffix = "{$exporter_folder}/{$prefix}_{$key}"; @@ -705,7 +705,8 @@ abstract class Exporter { } } $file_name = "{$upload_dir}{$file_suffix}"; - $file_url = "{$upload_url}{$file_suffix}"; + $guid = "exporter/{$prefix}_{$key}"; + $file_url = esc_url_raw( rest_url() ) . "tainacan/v2/bg-processes/file?guid=$guid&_wpnonce=[nonce]"; $this->output_files[$key] = [ 'filename' => $file_name, 'url' => $file_url @@ -781,7 +782,10 @@ abstract class Exporter { $user = get_userdata( (int) $author ); if ($user instanceof \WP_User) { $msg = $this->get_output(); - $this->add_log('Sending email to ' . $user->user_email); + $email_parts = explode('@', $user->user_email); + $first_letter = substr($email_parts[0], 0, 1); + $anonymized_email = $first_letter . '*****@' . $email_parts[1]; + $this->add_log('Sending email to ' . $anonymized_email); wp_mail($user->user_email, __('Finished export.', 'tainacan'), $msg); } diff --git a/src/readme.txt b/src/readme.txt index 45016e972..4f50e8a45 100644 --- a/src/readme.txt +++ b/src/readme.txt @@ -4,7 +4,7 @@ Tags: museums, libraries, archives, GLAM, collections, repository Requires at least: 5.9 Tested up to: 6.4 Requires PHP: 7.0 -Stable tag: 0.20.6 +Stable tag: 0.20.7 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-3.0.html diff --git a/src/tainacan.php b/src/tainacan.php index 753dc4daf..87b9b204e 100644 --- a/src/tainacan.php +++ b/src/tainacan.php @@ -5,17 +5,17 @@ Plugin URI: https://tainacan.org/ Description: Open source, powerful and flexible repository platform for WordPress. Manage and publish you digital collections as easily as publishing a post to your blog, while having all the tools of a professional repository platform. Author: Tainacan.org Author URI: https://tainacan.org/ -Version: 0.20.6 +Version: 0.20.7 Requires at least: 5.9 Tested up to: 6.4 Requires PHP: 7.0 -Stable tag: 0.20.6 +Stable tag: 0.20.7 Text Domain: tainacan License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-3.0.html */ -const TAINACAN_VERSION = '0.20.6'; +const TAINACAN_VERSION = '0.20.7'; defined( 'ABSPATH' ) or die( 'No script kiddies please!' ); $TAINACAN_BASE_URL = plugins_url('', __FILE__); @@ -159,4 +159,32 @@ add_filter('wp_kses_allowed_html', function($allowedposttags, $context) { default: return $allowedposttags; } -}, 10, 2); \ No newline at end of file +}, 10, 2); + + +// Function to add rules to [upload_dir]/tainacan/.htaccess +function tainacan_add_htaccess_rules() { + if( function_exists('insert_with_markers') ) { + $uploads_dir = wp_upload_dir(); // Uploads directory + $htaccess_dir = trailingslashit($uploads_dir['basedir']) . 'tainacan'; // Path to the tainacan folder + $htaccess_file = trailingslashit($htaccess_dir) . '.htaccess'; // Path to the .htaccess file + + // If the folder doesn't exist, create it + if (!file_exists($htaccess_dir)) { + wp_mkdir_p($htaccess_dir); + } + + $marker = 'Tainacan [/tainacan] rules'; // Marker name for identification + $rules = array( + '# Prevent direct access to files', + 'Order deny,allow', + 'Deny from all' + ); // Rules to be added + + // Add rules to the .htaccess file + insert_with_markers($htaccess_file, $marker, $rules); + } +} + +// Hook to execute the function when the plugin is activated +register_activation_hook(__FILE__, 'tainacan_add_htaccess_rules'); \ No newline at end of file