mirror of
https://gh.wpcy.net/https://github.com/secure-updates/secure-updates-server.git
synced 2026-05-27 04:48:44 +08:00
744 lines
No EOL
29 KiB
PHP
744 lines
No EOL
29 KiB
PHP
<?php
|
|
/*
|
|
Plugin Name: Secure Updates Server
|
|
Description: Provides secure plugin updates by allowing direct uploads and mirroring from repositories with Media Library integration.
|
|
Version: 4.0
|
|
Author: Secure Updates Foundation
|
|
Text Domain: secure-updates-server
|
|
Domain Path: /languages
|
|
*/
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit; // Exit if accessed directly
|
|
}
|
|
|
|
if (!class_exists('Secure_Updates_Server')) {
|
|
class Secure_Updates_Server
|
|
{
|
|
/**
|
|
* Constructor to initialize the plugin
|
|
*/
|
|
public function __construct()
|
|
{
|
|
// Load text domain for translations
|
|
add_action('plugins_loaded', [$this, 'load_textdomain']);
|
|
|
|
// Setup hooks
|
|
$this->setup_hooks();
|
|
}
|
|
|
|
/**
|
|
* Load plugin textdomain for translations
|
|
*/
|
|
public function load_textdomain()
|
|
{
|
|
load_plugin_textdomain('secure-updates-server', false, dirname(plugin_basename(__FILE__)) . '/languages');
|
|
}
|
|
|
|
/**
|
|
* Setup WordPress hooks
|
|
*/
|
|
private function setup_hooks()
|
|
{
|
|
// Admin Menu
|
|
add_action('admin_menu', [$this, 'setup_admin_menu']);
|
|
|
|
// Handle Direct Plugin Upload
|
|
add_action('admin_post_upload_plugin_to_server', [$this, 'upload_plugin_to_server']);
|
|
|
|
// Handle Mirror Plugin via standard form submission
|
|
add_action('admin_post_mirror_plugin', [$this, 'mirror_plugin']);
|
|
|
|
// Handle Delete Plugin via standard form submission
|
|
add_action('admin_post_delete_plugin', [$this, 'delete_plugin']);
|
|
|
|
// Scheduled Updates
|
|
add_action('secure_updates_server_check_updates', [$this, 'check_for_updates']);
|
|
|
|
// REST API Endpoints
|
|
add_action('rest_api_init', [$this, 'register_rest_routes']);
|
|
|
|
// Activation and Deactivation Hooks
|
|
register_activation_hook(__FILE__, [$this, 'activate_plugin']);
|
|
register_deactivation_hook(__FILE__, [$this, 'deactivate_plugin']);
|
|
}
|
|
|
|
/**
|
|
* Activate the plugin and schedule update checks
|
|
*/
|
|
public function activate_plugin()
|
|
{
|
|
if (!wp_next_scheduled('secure_updates_server_check_updates')) {
|
|
wp_schedule_event(time(), 'hourly', 'secure_updates_server_check_updates');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deactivate the plugin and clear scheduled hooks
|
|
*/
|
|
public function deactivate_plugin()
|
|
{
|
|
wp_clear_scheduled_hook('secure_updates_server_check_updates');
|
|
}
|
|
|
|
/**
|
|
* Setup the admin menu in WordPress dashboard
|
|
*/
|
|
public function setup_admin_menu()
|
|
{
|
|
add_menu_page(
|
|
__('Secure Updates Server', 'secure-updates-server'),
|
|
__('Secure Updates Server', 'secure-updates-server'),
|
|
'manage_options',
|
|
'secure-updates-server',
|
|
[$this, 'admin_page'],
|
|
'dashicons-update',
|
|
6
|
|
);
|
|
|
|
add_submenu_page(
|
|
'secure-updates-server',
|
|
__('API Keys', 'secure-updates-server'),
|
|
__('API Keys', 'secure-updates-server'),
|
|
'manage_options',
|
|
'secure-updates-server-api-keys',
|
|
[$this, 'api_keys_page']
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Display the admin page for managing plugins
|
|
*/
|
|
public function admin_page()
|
|
{
|
|
// Include the admin page content
|
|
include plugin_dir_path(__FILE__) . 'admin/admin-page.php';
|
|
}
|
|
|
|
/**
|
|
* Register REST API routes
|
|
*/
|
|
public function register_rest_routes()
|
|
{
|
|
// Existing Download Endpoint
|
|
register_rest_route('secure-updates-server/v1', '/download/(?P<slug>[a-zA-Z0-9-]+)', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'handle_download_request'],
|
|
'permission_callback' => '__return_true',
|
|
]);
|
|
|
|
// Existing Info Endpoint
|
|
register_rest_route('secure-updates-server/v1', '/info/(?P<slug>[a-zA-Z0-9-]+)', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'handle_info_request'],
|
|
'permission_callback' => '__return_true',
|
|
]);
|
|
|
|
// Existing Connected Endpoint
|
|
register_rest_route('secure-updates-server/v1', '/connected', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'handle_connected_request'],
|
|
'permission_callback' => '__return_true',
|
|
]);
|
|
|
|
// Existing Verify File Endpoint
|
|
register_rest_route('secure-updates-server/v1', '/verify_file/(?P<slug>[a-zA-Z0-9-]+)', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'handle_verify_file_request'],
|
|
'permission_callback' => '__return_true',
|
|
]);
|
|
|
|
// New Plugin List Endpoint
|
|
register_rest_route('secure-updates-server/v1', '/plugins', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'handle_plugin_list_request'],
|
|
'permission_callback' => [$this, 'verify_client_request'],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Verify client API key
|
|
*/
|
|
public function verify_client_request($request)
|
|
{
|
|
$headers = $request->get_headers();
|
|
if (isset($headers['authorization'])) {
|
|
$auth = $headers['authorization'][0];
|
|
if (strpos($auth, 'Bearer ') === 0) {
|
|
$api_key = substr($auth, 7);
|
|
$valid_api_keys = get_option('secure_updates_valid_api_keys', []);
|
|
if (in_array($api_key, $valid_api_keys, true)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Handle REST API request for plugin download
|
|
*/
|
|
public function handle_download_request($request)
|
|
{
|
|
$plugin_slug = sanitize_text_field($request['slug']);
|
|
|
|
// Get the latest version of the plugin
|
|
$secure_updates_plugins = get_option('secure_updates_plugins', []);
|
|
if (isset($secure_updates_plugins[$plugin_slug])) {
|
|
$latest_version = $secure_updates_plugins[$plugin_slug]['latest_version'];
|
|
$attachment_id = $secure_updates_plugins[$plugin_slug]['versions'][$latest_version]['attachment_id'];
|
|
$file_path = get_attached_file($attachment_id);
|
|
|
|
if ($file_path && file_exists($file_path)) {
|
|
// Serve the file for download
|
|
header('Content-Description: File Transfer');
|
|
header('Content-Type: application/zip');
|
|
header('Content-Disposition: attachment; filename="' . basename($file_path) . '"');
|
|
header('Content-Length: ' . filesize($file_path));
|
|
header('Pragma: public');
|
|
flush();
|
|
readfile($file_path);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
return new WP_Error('plugin_not_found', __('Plugin not found or file does not exist.', 'secure-updates-server'), ['status' => 404]);
|
|
}
|
|
|
|
/**
|
|
* Handle REST API request for plugin information
|
|
*/
|
|
public function handle_info_request($request)
|
|
{
|
|
$plugin_slug = sanitize_text_field($request['slug']);
|
|
|
|
// Get plugin information
|
|
$secure_updates_plugins = get_option('secure_updates_plugins', []);
|
|
if (isset($secure_updates_plugins[$plugin_slug])) {
|
|
// Retrieve plugin data
|
|
$plugin_info = [
|
|
'name' => ucfirst($plugin_slug),
|
|
'slug' => $plugin_slug,
|
|
'version' => $secure_updates_plugins[$plugin_slug]['latest_version'],
|
|
'author' => 'Your Name',
|
|
'homepage' => home_url(),
|
|
'download_link' => rest_url('secure-updates-server/v1/download/' . $plugin_slug),
|
|
'sections' => [
|
|
'description' => __('Plugin description here.', 'secure-updates-server'),
|
|
'installation' => __('Installation instructions here.', 'secure-updates-server'),
|
|
'changelog' => __('Changelog here.', 'secure-updates-server'),
|
|
],
|
|
];
|
|
|
|
return rest_ensure_response($plugin_info);
|
|
}
|
|
|
|
return new WP_Error('plugin_not_found', __('Plugin not found', 'secure-updates-server'), ['status' => 404]);
|
|
}
|
|
|
|
/**
|
|
* Handle REST API request to test connection
|
|
*/
|
|
public function handle_connected_request($request)
|
|
{
|
|
return rest_ensure_response(['status' => 'connected']);
|
|
}
|
|
|
|
/**
|
|
* Handle REST API request to verify plugin file
|
|
*/
|
|
public function handle_verify_file_request($request)
|
|
{
|
|
$plugin_slug = sanitize_text_field($request['slug']);
|
|
|
|
// Get the plugin information
|
|
$secure_updates_plugins = get_option('secure_updates_plugins', []);
|
|
if (isset($secure_updates_plugins[$plugin_slug])) {
|
|
$attachment_id = $secure_updates_plugins[$plugin_slug]['attachment_id'];
|
|
$file_path = get_attached_file($attachment_id);
|
|
|
|
if ($file_path && file_exists($file_path)) {
|
|
// Calculate checksum
|
|
$checksum = isset($secure_updates_plugins[$plugin_slug]['versions'][$secure_updates_plugins[$plugin_slug]['latest_version']]['checksum'])
|
|
? $secure_updates_plugins[$plugin_slug]['versions'][$secure_updates_plugins[$plugin_slug]['latest_version']]['checksum']
|
|
: '';
|
|
|
|
return rest_ensure_response([
|
|
'status' => 'success',
|
|
'message' => __('Plugin file is correctly hosted and accessible.', 'secure-updates-server'),
|
|
'file_exists' => true,
|
|
'file_path' => $file_path,
|
|
'checksum' => $checksum,
|
|
]);
|
|
} else {
|
|
return new WP_Error('file_not_found', __('Plugin file does not exist on the server.', 'secure-updates-server'), ['status' => 404]);
|
|
}
|
|
}
|
|
|
|
return new WP_Error('plugin_not_found', __('Plugin not found.', 'secure-updates-server'), ['status' => 404]);
|
|
}
|
|
|
|
/**
|
|
* Handle plugin list request
|
|
*/
|
|
public function handle_plugin_list_request($request)
|
|
{
|
|
$params = $request->get_json_params();
|
|
if (empty($params['plugins']) || !is_array($params['plugins'])) {
|
|
return new WP_Error('invalid_request', __('Invalid plugin list.', 'secure-updates-server'), ['status' => 400]);
|
|
}
|
|
|
|
$plugin_slugs = array_map('sanitize_text_field', $params['plugins']);
|
|
$responses = [];
|
|
|
|
foreach ($plugin_slugs as $slug) {
|
|
if ($this->is_plugin_mirrored($slug)) {
|
|
$responses[$slug] = 'already mirrored';
|
|
} else {
|
|
$result = $this->mirror_plugin_by_slug($slug);
|
|
if ($result) {
|
|
$responses[$slug] = 'mirrored successfully';
|
|
} else {
|
|
$responses[$slug] = 'failed to mirror';
|
|
}
|
|
}
|
|
}
|
|
|
|
return rest_ensure_response(['status' => 'success', 'plugins' => $responses]);
|
|
}
|
|
|
|
/**
|
|
* Mirror a plugin (Handles standard form submission)
|
|
*/
|
|
public function mirror_plugin()
|
|
{
|
|
// Verify nonce
|
|
if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'mirror_plugin_nonce')) {
|
|
wp_redirect(admin_url('admin.php?page=secure-updates-server&status=error&message=nonce_failed'));
|
|
exit;
|
|
}
|
|
|
|
// Capability check
|
|
if (!current_user_can('manage_options')) {
|
|
wp_redirect(admin_url('admin.php?page=secure-updates-server&status=error&message=insufficient_permissions'));
|
|
exit;
|
|
}
|
|
|
|
$plugin_slug = isset($_POST['plugin_slug']) ? sanitize_text_field($_POST['plugin_slug']) : '';
|
|
|
|
if (empty($plugin_slug)) {
|
|
wp_redirect(admin_url('admin.php?page=secure-updates-server&status=error&message=empty_slug'));
|
|
exit;
|
|
}
|
|
|
|
$this->log_message("Mirroring plugin: $plugin_slug");
|
|
|
|
if ($this->mirror_plugin_by_slug($plugin_slug)) {
|
|
wp_redirect(admin_url('admin.php?page=secure-updates-server&status=success'));
|
|
} else {
|
|
wp_redirect(admin_url('admin.php?page=secure-updates-server&status=error&message=mirror_failed'));
|
|
}
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Delete a mirrored or uploaded plugin (Handles standard form submission)
|
|
*/
|
|
public function delete_plugin()
|
|
{
|
|
// Verify nonce
|
|
if (!isset($_POST['delete_plugin_nonce_field']) || !wp_verify_nonce($_POST['delete_plugin_nonce_field'], 'delete_plugin_nonce')) {
|
|
wp_redirect(admin_url('admin.php?page=secure-updates-server&status=error&message=nonce_failed'));
|
|
exit;
|
|
}
|
|
|
|
// Capability check
|
|
if (!current_user_can('manage_options')) {
|
|
wp_redirect(admin_url('admin.php?page=secure-updates-server&status=error&message=insufficient_permissions'));
|
|
exit;
|
|
}
|
|
|
|
$plugin_slug = isset($_POST['plugin_slug']) ? sanitize_text_field($_POST['plugin_slug']) : '';
|
|
|
|
if (empty($plugin_slug)) {
|
|
wp_redirect(admin_url('admin.php?page=secure-updates-server&status=error&message=empty_slug'));
|
|
exit;
|
|
}
|
|
|
|
// Delete plugin data from the database
|
|
$secure_updates_plugins = get_option('secure_updates_plugins', []);
|
|
if (isset($secure_updates_plugins[$plugin_slug])) {
|
|
// Delete all attachments related to the plugin
|
|
foreach ($secure_updates_plugins[$plugin_slug]['versions'] as $version_info) {
|
|
wp_delete_attachment($version_info['attachment_id'], true);
|
|
}
|
|
|
|
unset($secure_updates_plugins[$plugin_slug]);
|
|
update_option('secure_updates_plugins', $secure_updates_plugins);
|
|
|
|
$this->log_message("Deleted plugin: $plugin_slug");
|
|
|
|
do_action('secure_updates_plugin_deleted', $plugin_slug);
|
|
|
|
wp_redirect(admin_url('admin.php?page=secure-updates-server&status=deleted'));
|
|
exit;
|
|
}
|
|
|
|
$this->log_message("Plugin not found: $plugin_slug");
|
|
wp_redirect(admin_url('admin.php?page=secure-updates-server&status=error&message=plugin_not_found'));
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Handle Direct Plugin Upload
|
|
*/
|
|
public function upload_plugin_to_server()
|
|
{
|
|
// Verify nonce
|
|
if (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'upload_plugin_nonce')) {
|
|
wp_die(__('Nonce verification failed', 'secure-updates-server'));
|
|
}
|
|
|
|
// Capability check
|
|
if (!current_user_can('manage_options')) {
|
|
wp_die(__('Insufficient permissions.', 'secure-updates-server'));
|
|
}
|
|
|
|
// Check for file upload
|
|
if (empty($_FILES['plugin_zip_file']) || $_FILES['plugin_zip_file']['error'] !== UPLOAD_ERR_OK) {
|
|
wp_die(__('Please select a valid ZIP file to upload.', 'secure-updates-server'));
|
|
}
|
|
|
|
// Handle file upload
|
|
$file = $_FILES['plugin_zip_file'];
|
|
$upload = wp_handle_upload($file, ['test_form' => false]);
|
|
|
|
if (isset($upload['error']) && !empty($upload['error'])) {
|
|
wp_die(__('Error uploading file: ', 'secure-updates-server') . esc_html($upload['error']));
|
|
}
|
|
|
|
// Insert the uploaded file into the WordPress Media Library
|
|
$filetype = wp_check_filetype(basename($upload['file']), null);
|
|
$attachment = [
|
|
'guid' => $upload['url'],
|
|
'post_mime_type' => $filetype['type'],
|
|
'post_title' => preg_replace('/\.[^.]+$/', '', basename($upload['file'])),
|
|
'post_content' => '',
|
|
'post_status' => 'inherit'
|
|
];
|
|
|
|
$attachment_id = wp_insert_attachment($attachment, $upload['file']);
|
|
require_once(ABSPATH . 'wp-admin/includes/image.php');
|
|
$attach_data = wp_generate_attachment_metadata($attachment_id, $upload['file']);
|
|
wp_update_attachment_metadata($attachment_id, $attach_data);
|
|
|
|
// Extract plugin slug from file name
|
|
$plugin_slug = sanitize_title(preg_replace('/\.[^.]+$/', '', basename($upload['file'])));
|
|
|
|
// Extract version from plugin data if possible
|
|
$plugin_data = $this->get_plugin_data_from_zip($upload['file']);
|
|
$version = isset($plugin_data['Version']) ? sanitize_text_field($plugin_data['Version']) : '1.0.0';
|
|
|
|
// Calculate checksum
|
|
$checksum = $this->calculate_checksum($upload['file']);
|
|
|
|
// Add plugin slug to served plugins list
|
|
$secure_updates_plugins = get_option('secure_updates_plugins', []);
|
|
if (!isset($secure_updates_plugins[$plugin_slug])) {
|
|
$secure_updates_plugins[$plugin_slug] = [
|
|
'attachment_id' => $attachment_id,
|
|
'type' => 'direct_upload',
|
|
'versions' => [
|
|
$version => [
|
|
'version' => $version,
|
|
'date' => current_time('mysql'),
|
|
'attachment_id' => $attachment_id,
|
|
'checksum' => $checksum,
|
|
]
|
|
],
|
|
'latest_version' => $version,
|
|
];
|
|
} else {
|
|
// Handle versioning for existing plugin
|
|
$secure_updates_plugins[$plugin_slug]['versions'][$version] = [
|
|
'version' => $version,
|
|
'date' => current_time('mysql'),
|
|
'attachment_id' => $attachment_id,
|
|
'checksum' => $checksum,
|
|
];
|
|
$secure_updates_plugins[$plugin_slug]['latest_version'] = $version;
|
|
$secure_updates_plugins[$plugin_slug]['attachment_id'] = $attachment_id;
|
|
}
|
|
|
|
update_option('secure_updates_plugins', $secure_updates_plugins);
|
|
|
|
$this->log_message("Uploaded plugin: $plugin_slug version: $version");
|
|
|
|
do_action('secure_updates_plugin_uploaded', $plugin_slug, $version);
|
|
|
|
// Redirect back with success message
|
|
wp_redirect(admin_url('admin.php?page=secure-updates-server&status=upload_success'));
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Check for updates (both mirrored and uploaded plugins)
|
|
*/
|
|
public function check_for_updates()
|
|
{
|
|
$secure_updates_plugins = get_option('secure_updates_plugins', []);
|
|
|
|
foreach ($secure_updates_plugins as $plugin_slug => $plugin_info) {
|
|
if ($plugin_info['type'] === 'mirror') {
|
|
$this->check_mirrored_plugin_update($plugin_slug, $plugin_info);
|
|
}
|
|
// For direct uploads, you might implement different update mechanisms if needed
|
|
}
|
|
|
|
$this->log_message('Checked for plugin updates.');
|
|
}
|
|
|
|
/**
|
|
* Check and update a mirrored plugin
|
|
*/
|
|
private function check_mirrored_plugin_update($plugin_slug, $plugin_info)
|
|
{
|
|
$plugin_data = $this->fetch_plugin_data($plugin_slug);
|
|
|
|
if ($plugin_data && version_compare($plugin_data['version'], $plugin_info['latest_version'], '>')) {
|
|
$version = sanitize_text_field($plugin_data['version']);
|
|
$attachment_id = $this->upload_plugin_zip_to_media_library($plugin_slug, $plugin_data['download_link'], $version);
|
|
|
|
if ($attachment_id) {
|
|
// Calculate checksum
|
|
$file_path = get_attached_file($attachment_id);
|
|
$checksum = $this->calculate_checksum($file_path);
|
|
|
|
// Update plugin information
|
|
$this->update_plugin_info($plugin_slug, $version, $attachment_id, 'mirror', $checksum);
|
|
|
|
$this->log_message("Updated mirrored plugin: $plugin_slug to version: $version");
|
|
|
|
do_action('secure_updates_plugin_updated', $plugin_slug, $version);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if a plugin is already mirrored
|
|
*/
|
|
private function is_plugin_mirrored($slug)
|
|
{
|
|
$secure_updates_plugins = get_option('secure_updates_plugins', []);
|
|
return isset($secure_updates_plugins[$slug]);
|
|
}
|
|
|
|
/**
|
|
* Mirror a plugin by slug
|
|
*/
|
|
private function mirror_plugin_by_slug($slug)
|
|
{
|
|
$plugin_data = $this->fetch_plugin_data($slug);
|
|
|
|
if ($plugin_data && isset($plugin_data['download_link'])) {
|
|
$version = sanitize_text_field($plugin_data['version']);
|
|
$attachment_id = $this->upload_plugin_zip_to_media_library($slug, $plugin_data['download_link'], $version);
|
|
|
|
if ($attachment_id) {
|
|
$file_path = get_attached_file($attachment_id);
|
|
$checksum = $this->calculate_checksum($file_path);
|
|
|
|
$this->update_plugin_info($slug, $version, $attachment_id, 'mirror', $checksum);
|
|
|
|
$this->log_message("Successfully mirrored plugin: $slug version: $version");
|
|
|
|
do_action('secure_updates_plugin_mirrored', $slug, $version);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
$this->log_message("Failed to mirror plugin: $slug");
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Display API keys management page
|
|
*/
|
|
public function api_keys_page()
|
|
{
|
|
// Handle form submission
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
|
if (!wp_verify_nonce($_POST['_wpnonce'], 'manage_api_keys')) {
|
|
wp_die(__('Security check failed', 'secure-updates-server'));
|
|
}
|
|
|
|
$valid_api_keys = get_option('secure_updates_valid_api_keys', []);
|
|
|
|
if ($_POST['action'] === 'add_key' && isset($_POST['new_api_key'])) {
|
|
$new_key = sanitize_text_field($_POST['new_api_key']);
|
|
if (!empty($new_key)) {
|
|
$valid_api_keys[] = $new_key;
|
|
update_option('secure_updates_valid_api_keys', array_unique($valid_api_keys));
|
|
}
|
|
} elseif ($_POST['action'] === 'delete_key' && isset($_POST['api_key'])) {
|
|
$key_to_delete = sanitize_text_field($_POST['api_key']);
|
|
$valid_api_keys = array_diff($valid_api_keys, [$key_to_delete]);
|
|
update_option('secure_updates_valid_api_keys', $valid_api_keys);
|
|
}
|
|
}
|
|
|
|
// Display the page
|
|
$valid_api_keys = get_option('secure_updates_valid_api_keys', []);
|
|
include plugin_dir_path(__FILE__) . 'admin/api-keys-page.php';
|
|
}
|
|
|
|
/**
|
|
* Fetch plugin data from WordPress.org
|
|
*/
|
|
private function fetch_plugin_data($slug)
|
|
{
|
|
$transient_key = 'plugin_data_' . $slug;
|
|
$plugin_data = get_transient($transient_key);
|
|
|
|
if ($plugin_data === false) {
|
|
$response = wp_remote_get("https://api.wordpress.org/plugins/info/1.2/?action=plugin_information&request[slug]=$slug");
|
|
|
|
if (is_wp_error($response)) {
|
|
$this->log_message("Error fetching data for plugin $slug: " . $response->get_error_message());
|
|
return false;
|
|
}
|
|
|
|
$plugin_data = json_decode(wp_remote_retrieve_body($response), true);
|
|
set_transient($transient_key, $plugin_data, HOUR_IN_SECONDS);
|
|
}
|
|
|
|
return $plugin_data;
|
|
}
|
|
|
|
/**
|
|
* Upload plugin ZIP to Media Library
|
|
*/
|
|
private function upload_plugin_zip_to_media_library($slug, $url, $version)
|
|
{
|
|
$tmp = download_url($url);
|
|
|
|
if (is_wp_error($tmp)) {
|
|
$this->log_message("Error downloading plugin $slug: " . $tmp->get_error_message());
|
|
return false;
|
|
}
|
|
|
|
$file_array = [
|
|
'name' => $slug . '-' . $version . '.zip',
|
|
'tmp_name' => $tmp,
|
|
];
|
|
|
|
// Handle the upload using WordPress's media library functions
|
|
$attachment_id = media_handle_sideload($file_array, 0);
|
|
|
|
// Check for errors during upload
|
|
if (is_wp_error($attachment_id)) {
|
|
$this->log_message("Error uploading plugin $slug to media library: " . $attachment_id->get_error_message());
|
|
@unlink($tmp); // Delete the temporary file
|
|
return false;
|
|
}
|
|
|
|
// Delete the temporary file
|
|
@unlink($tmp);
|
|
|
|
return $attachment_id;
|
|
}
|
|
|
|
/**
|
|
* Handle logging of messages
|
|
*/
|
|
private function log_message($message)
|
|
{
|
|
if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
error_log('[Secure Updates Server] ' . $message);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calculate SHA256 checksum of a file
|
|
*/
|
|
private function calculate_checksum($file_path)
|
|
{
|
|
return hash_file('sha256', $file_path);
|
|
}
|
|
|
|
/**
|
|
* Update plugin information in the database
|
|
*/
|
|
private function update_plugin_info($slug, $version, $attachment_id, $type, $checksum = '')
|
|
{
|
|
$secure_updates_plugins = get_option('secure_updates_plugins', []);
|
|
if (!isset($secure_updates_plugins[$slug])) {
|
|
$secure_updates_plugins[$slug] = [
|
|
'slug' => $slug,
|
|
'type' => $type,
|
|
'versions' => [],
|
|
];
|
|
}
|
|
|
|
$secure_updates_plugins[$slug]['versions'][$version] = [
|
|
'version' => $version,
|
|
'date' => current_time('mysql'),
|
|
'attachment_id' => $attachment_id,
|
|
'checksum' => $checksum,
|
|
];
|
|
|
|
$secure_updates_plugins[$slug]['latest_version'] = $version;
|
|
$secure_updates_plugins[$slug]['attachment_id'] = $attachment_id;
|
|
|
|
update_option('secure_updates_plugins', $secure_updates_plugins);
|
|
}
|
|
|
|
/**
|
|
* Extract plugin data from ZIP file
|
|
*/
|
|
private function get_plugin_data_from_zip($file_path)
|
|
{
|
|
$plugin_data = [];
|
|
$zip = new ZipArchive();
|
|
if ($zip->open($file_path) === true) {
|
|
// Look for main plugin file (assuming it has the same name as the folder)
|
|
$plugin_slug = basename($file_path, '.zip');
|
|
$main_plugin_file = "$plugin_slug.php";
|
|
|
|
if ($zip->locateName($main_plugin_file)) {
|
|
$plugin_content = $zip->getFromName($main_plugin_file);
|
|
if ($plugin_content !== false) {
|
|
$plugin_data = $this->parse_plugin_header($plugin_content);
|
|
}
|
|
}
|
|
$zip->close();
|
|
}
|
|
return $plugin_data;
|
|
}
|
|
|
|
/**
|
|
* Parse plugin header to get version and other data
|
|
*/
|
|
private function parse_plugin_header($plugin_content)
|
|
{
|
|
$plugin_data = [];
|
|
$headers = [
|
|
'Version' => 'Version',
|
|
'Plugin Name' => 'Name',
|
|
// Add more headers if needed
|
|
];
|
|
|
|
foreach ($headers as $field => $regex_field) {
|
|
if (preg_match('/' . $field . ':\s*(.+)/i', $plugin_content, $matches)) {
|
|
$plugin_data[$field] = trim($matches[1]);
|
|
}
|
|
}
|
|
|
|
return $plugin_data;
|
|
}
|
|
}
|
|
|
|
// Initialize the plugin
|
|
new Secure_Updates_Server();
|
|
} |