180 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			180 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?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;
 | 
						|
    }
 | 
						|
} |