First Commit
This commit is contained in:
180
includes/class-wpdd-file-protection.php
Normal file
180
includes/class-wpdd-file-protection.php
Normal file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class WPDD_File_Protection {
|
||||
|
||||
public static function init() {
|
||||
add_action('template_redirect', array(__CLASS__, 'protect_direct_access'));
|
||||
add_filter('mod_rewrite_rules', array(__CLASS__, 'add_rewrite_rules'));
|
||||
add_action('init', array(__CLASS__, 'add_download_endpoint'));
|
||||
}
|
||||
|
||||
public static function protect_direct_access() {
|
||||
$request_uri = $_SERVER['REQUEST_URI'];
|
||||
$upload_dir = wp_upload_dir();
|
||||
$protected_dir = '/' . WPDD_UPLOADS_DIR . '/';
|
||||
|
||||
if (strpos($request_uri, $protected_dir) !== false) {
|
||||
wp_die(__('Direct access to this file is not allowed.', 'wp-digital-download'), 403);
|
||||
}
|
||||
}
|
||||
|
||||
public static function add_rewrite_rules($rules) {
|
||||
$upload_dir = wp_upload_dir();
|
||||
$protected_path = str_replace(ABSPATH, '', $upload_dir['basedir']) . '/' . WPDD_UPLOADS_DIR;
|
||||
|
||||
$new_rules = "# WP Digital Download Protection\n";
|
||||
$new_rules .= "<IfModule mod_rewrite.c>\n";
|
||||
$new_rules .= "RewriteRule ^" . $protected_path . "/.*$ - [F,L]\n";
|
||||
$new_rules .= "</IfModule>\n\n";
|
||||
|
||||
return $new_rules . $rules;
|
||||
}
|
||||
|
||||
public static function add_download_endpoint() {
|
||||
add_rewrite_endpoint('wpdd-download', EP_ROOT);
|
||||
}
|
||||
|
||||
public static function move_to_protected_directory($attachment_id) {
|
||||
$upload_dir = wp_upload_dir();
|
||||
$protected_dir = trailingslashit($upload_dir['basedir']) . WPDD_UPLOADS_DIR;
|
||||
|
||||
if (!file_exists($protected_dir)) {
|
||||
wp_mkdir_p($protected_dir);
|
||||
self::create_protection_files($protected_dir);
|
||||
}
|
||||
|
||||
$file_path = get_attached_file($attachment_id);
|
||||
|
||||
if (!file_exists($file_path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$filename = basename($file_path);
|
||||
$unique_filename = wp_unique_filename($protected_dir, $filename);
|
||||
$new_path = trailingslashit($protected_dir) . $unique_filename;
|
||||
|
||||
if (copy($file_path, $new_path)) {
|
||||
$protected_url = trailingslashit($upload_dir['baseurl']) . WPDD_UPLOADS_DIR . '/' . $unique_filename;
|
||||
|
||||
update_post_meta($attachment_id, '_wpdd_protected_file', $new_path);
|
||||
update_post_meta($attachment_id, '_wpdd_protected_url', $protected_url);
|
||||
|
||||
return array(
|
||||
'path' => $new_path,
|
||||
'url' => $protected_url
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function create_protection_files($directory) {
|
||||
$htaccess_content = "Options -Indexes\n";
|
||||
$htaccess_content .= "deny from all\n";
|
||||
|
||||
$htaccess_file = trailingslashit($directory) . '.htaccess';
|
||||
if (!file_exists($htaccess_file)) {
|
||||
file_put_contents($htaccess_file, $htaccess_content);
|
||||
}
|
||||
|
||||
$index_content = "<?php\n// Silence is golden.\n";
|
||||
$index_file = trailingslashit($directory) . 'index.php';
|
||||
if (!file_exists($index_file)) {
|
||||
file_put_contents($index_file, $index_content);
|
||||
}
|
||||
|
||||
$nginx_content = "location ~* ^/wp-content/uploads/" . WPDD_UPLOADS_DIR . " {\n";
|
||||
$nginx_content .= " deny all;\n";
|
||||
$nginx_content .= " return 403;\n";
|
||||
$nginx_content .= "}\n";
|
||||
|
||||
$nginx_file = trailingslashit($directory) . 'nginx.conf';
|
||||
if (!file_exists($nginx_file)) {
|
||||
file_put_contents($nginx_file, $nginx_content);
|
||||
}
|
||||
}
|
||||
|
||||
public static function get_protected_file_url($file_path) {
|
||||
$upload_dir = wp_upload_dir();
|
||||
$protected_dir = trailingslashit($upload_dir['basedir']) . WPDD_UPLOADS_DIR;
|
||||
|
||||
if (strpos($file_path, $protected_dir) === 0) {
|
||||
$relative_path = str_replace($protected_dir, '', $file_path);
|
||||
return trailingslashit($upload_dir['baseurl']) . WPDD_UPLOADS_DIR . $relative_path;
|
||||
}
|
||||
|
||||
return $file_path;
|
||||
}
|
||||
|
||||
public static function is_protected_file($file_path) {
|
||||
$upload_dir = wp_upload_dir();
|
||||
$protected_dir = trailingslashit($upload_dir['basedir']) . WPDD_UPLOADS_DIR;
|
||||
|
||||
return strpos($file_path, $protected_dir) === 0;
|
||||
}
|
||||
|
||||
public static function generate_secure_download_url($file_path, $order_id, $expiry_hours = 24) {
|
||||
$token = wp_hash($file_path . $order_id . time());
|
||||
$expiry = time() + ($expiry_hours * 3600);
|
||||
|
||||
set_transient('wpdd_download_' . $token, array(
|
||||
'file_path' => $file_path,
|
||||
'order_id' => $order_id,
|
||||
'expiry' => $expiry
|
||||
), $expiry_hours * 3600);
|
||||
|
||||
return add_query_arg(array(
|
||||
'wpdd_secure_download' => $token
|
||||
), home_url());
|
||||
}
|
||||
|
||||
public static function handle_secure_download() {
|
||||
if (!isset($_GET['wpdd_secure_download'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$token = sanitize_text_field($_GET['wpdd_secure_download']);
|
||||
$data = get_transient('wpdd_download_' . $token);
|
||||
|
||||
if (!$data) {
|
||||
wp_die(__('Invalid or expired download link.', 'wp-digital-download'));
|
||||
}
|
||||
|
||||
if ($data['expiry'] < time()) {
|
||||
delete_transient('wpdd_download_' . $token);
|
||||
wp_die(__('This download link has expired.', 'wp-digital-download'));
|
||||
}
|
||||
|
||||
if (!file_exists($data['file_path'])) {
|
||||
wp_die(__('File not found.', 'wp-digital-download'));
|
||||
}
|
||||
|
||||
delete_transient('wpdd_download_' . $token);
|
||||
|
||||
self::serve_download($data['file_path']);
|
||||
}
|
||||
|
||||
private static function serve_download($file_path) {
|
||||
$file_name = basename($file_path);
|
||||
$file_size = filesize($file_path);
|
||||
$file_type = wp_check_filetype($file_path);
|
||||
|
||||
nocache_headers();
|
||||
|
||||
header('Content-Type: ' . ($file_type['type'] ?: 'application/octet-stream'));
|
||||
header('Content-Disposition: attachment; filename="' . $file_name . '"');
|
||||
header('Content-Length: ' . $file_size);
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
|
||||
if (ob_get_level()) {
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
readfile($file_path);
|
||||
exit;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user