added additional plugins
This commit is contained in:
parent
c85895d306
commit
00e60ec1b7
132 changed files with 27514 additions and 0 deletions
286
native/wordpress/maple-code-blocks/maple-code-blocks.php
Normal file
286
native/wordpress/maple-code-blocks/maple-code-blocks.php
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
<?php
|
||||
/**
|
||||
* Plugin Name: Maple Code Blocks
|
||||
* Plugin URI: https://sspmedia.ca/wordpress/
|
||||
* Description: Display code files from GitHub, GitLab, Bitbucket, and Codeberg repositories in a beautiful, safe terminal/IDE-style view
|
||||
* Version: 2.0.0
|
||||
* Author: SSP Media
|
||||
* Author URI: https://sspmedia.ca/wordpress/
|
||||
* License: GPL v2 or later
|
||||
* Text Domain: maple-code-blocks
|
||||
*/
|
||||
|
||||
// Prevent direct access
|
||||
if (!defined('WPINC')) {
|
||||
die('Direct access not permitted.');
|
||||
}
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Define plugin constants
|
||||
define('MCB_PLUGIN_URL', plugin_dir_url(__FILE__));
|
||||
define('MCB_PLUGIN_PATH', plugin_dir_path(__FILE__));
|
||||
define('MCB_PLUGIN_VERSION', '2.0.0');
|
||||
define('MCB_PLUGIN_BASENAME', plugin_basename(__FILE__));
|
||||
|
||||
// Include required files
|
||||
require_once MCB_PLUGIN_PATH . 'includes/class-security.php';
|
||||
require_once MCB_PLUGIN_PATH . 'includes/class-security-fixes.php';
|
||||
require_once MCB_PLUGIN_PATH . 'includes/class-privacy-manager.php';
|
||||
require_once MCB_PLUGIN_PATH . 'includes/class-github-api.php';
|
||||
require_once MCB_PLUGIN_PATH . 'includes/class-code-renderer.php';
|
||||
require_once MCB_PLUGIN_PATH . 'includes/class-shortcode.php';
|
||||
require_once MCB_PLUGIN_PATH . 'includes/class-simple-block.php';
|
||||
require_once MCB_PLUGIN_PATH . 'includes/basic-block.php';
|
||||
// require_once MCB_PLUGIN_PATH . 'includes/class-block-editor.php';
|
||||
// require_once MCB_PLUGIN_PATH . 'includes/class-block-patterns.php';
|
||||
|
||||
// Initialize plugin
|
||||
class Maple_Code_Blocks {
|
||||
|
||||
private static $instance = null;
|
||||
|
||||
public static function get_instance() {
|
||||
if (null === self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
private function __construct() {
|
||||
add_action('init', array($this, 'init'));
|
||||
add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));
|
||||
add_action('wp_ajax_mcb_load_file', array($this, 'ajax_load_file'));
|
||||
add_action('wp_ajax_nopriv_mcb_load_file', array($this, 'ajax_load_file'));
|
||||
add_action('wp_ajax_mcb_get_repo_files', array($this, 'ajax_get_repo_files'));
|
||||
add_action('wp_ajax_nopriv_mcb_get_repo_files', array($this, 'ajax_get_repo_files'));
|
||||
}
|
||||
|
||||
public function init() {
|
||||
// Initialize shortcode
|
||||
MCB_Shortcode::init();
|
||||
|
||||
// Simple block is self-initializing via class-simple-block.php
|
||||
|
||||
// Add admin menu if needed
|
||||
if (is_admin()) {
|
||||
add_action('admin_menu', array($this, 'add_admin_menu'));
|
||||
}
|
||||
}
|
||||
|
||||
public function enqueue_scripts() {
|
||||
// Load styles
|
||||
wp_enqueue_style('prism-css', MCB_PLUGIN_URL . 'assets/css/prism.css', array(), MCB_PLUGIN_VERSION);
|
||||
wp_enqueue_style('mcb-styles', MCB_PLUGIN_URL . 'assets/css/mcb-styles.css', array(), MCB_PLUGIN_VERSION);
|
||||
|
||||
// Load scripts
|
||||
wp_enqueue_script('prism-core', MCB_PLUGIN_URL . 'assets/js/prism.js', array(), MCB_PLUGIN_VERSION, true);
|
||||
wp_enqueue_script('mcb-script', MCB_PLUGIN_URL . 'assets/js/mcb-script.js', array('jquery'), MCB_PLUGIN_VERSION, true);
|
||||
|
||||
// Localize script for AJAX
|
||||
wp_localize_script('mcb-script', 'mcb_ajax', array(
|
||||
'ajax_url' => admin_url('admin-ajax.php'),
|
||||
'nonce' => wp_create_nonce('mcb_ajax_nonce')
|
||||
));
|
||||
}
|
||||
|
||||
public function ajax_load_file() {
|
||||
// Check request method
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
wp_die('Invalid request method', 405);
|
||||
}
|
||||
|
||||
// Rate limiting check
|
||||
if (class_exists('MCB_Privacy_Manager') && MCB_Privacy_Manager::is_privacy_mode()) {
|
||||
// Use nonce-based rate limiting in privacy mode
|
||||
$rate_limit_key = 'mcb_rate_' . wp_get_current_user()->ID . '_' . wp_create_nonce('mcb_rate');
|
||||
} else {
|
||||
// IP-based rate limiting
|
||||
$user_ip = $this->get_client_ip();
|
||||
$rate_limit_key = 'mcb_rate_' . md5($user_ip);
|
||||
}
|
||||
|
||||
$requests = get_transient($rate_limit_key);
|
||||
|
||||
if ($requests !== false && $requests > 30) { // 30 requests per minute
|
||||
wp_die('Rate limit exceeded. Please try again later.', 429);
|
||||
}
|
||||
|
||||
set_transient($rate_limit_key, ($requests ? $requests + 1 : 1), 60);
|
||||
|
||||
// Verify nonce
|
||||
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'mcb_ajax_nonce')) {
|
||||
wp_die('Security check failed', 403);
|
||||
}
|
||||
|
||||
// Note: We allow public viewing of public repositories by default
|
||||
// Site admins can restrict access if needed via filter
|
||||
$require_login = apply_filters('mcb_require_login_for_viewing', false);
|
||||
|
||||
if ($require_login && !is_user_logged_in()) {
|
||||
wp_die('Please log in to view code repositories', 403);
|
||||
}
|
||||
|
||||
$repo = isset($_POST['repo']) ? sanitize_text_field($_POST['repo']) : '';
|
||||
$file_path = isset($_POST['file_path']) ? sanitize_text_field($_POST['file_path']) : '';
|
||||
|
||||
// Additional validation using security class
|
||||
if (!MCB_Security::validate_repo_format($repo)) {
|
||||
MCB_Security::log_security_event('invalid_repo_format', array('repo' => $repo));
|
||||
wp_send_json_error('Invalid repository format');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MCB_Security::validate_file_path($file_path)) {
|
||||
MCB_Security::log_security_event('invalid_file_path', array('path' => $file_path));
|
||||
wp_send_json_error('Invalid file path');
|
||||
return;
|
||||
}
|
||||
|
||||
$github_api = new MCB_GitHub_API();
|
||||
$content = $github_api->get_file_content($repo, $file_path);
|
||||
|
||||
if (is_wp_error($content)) {
|
||||
wp_send_json_error($content->get_error_message());
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate content before sending
|
||||
$renderer = new MCB_Code_Renderer();
|
||||
$validation = $renderer->validate_content($content);
|
||||
|
||||
if (is_wp_error($validation)) {
|
||||
wp_send_json_error($validation->get_error_message());
|
||||
return;
|
||||
}
|
||||
|
||||
// Return raw content - JavaScript will handle escaping and rendering
|
||||
// This is more secure as it avoids double-escaping issues
|
||||
wp_send_json_success(array(
|
||||
'content' => $content, // Send raw content, not rendered HTML
|
||||
'filename' => basename($file_path)
|
||||
));
|
||||
}
|
||||
|
||||
public function ajax_get_repo_files() {
|
||||
// Check request method
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
wp_die('Invalid request method', 405);
|
||||
}
|
||||
|
||||
// Rate limiting check
|
||||
$user_ip = $this->get_client_ip();
|
||||
$rate_limit_key = 'mcb_rate_' . md5($user_ip);
|
||||
$requests = get_transient($rate_limit_key);
|
||||
|
||||
if ($requests !== false && $requests > 30) { // 30 requests per minute
|
||||
wp_die('Rate limit exceeded. Please try again later.', 429);
|
||||
}
|
||||
|
||||
set_transient($rate_limit_key, ($requests ? $requests + 1 : 1), 60);
|
||||
|
||||
// Verify nonce
|
||||
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'mcb_ajax_nonce')) {
|
||||
wp_die('Security check failed', 403);
|
||||
}
|
||||
|
||||
// Note: We allow public viewing of public repositories by default
|
||||
// Site admins can restrict access if needed via filter
|
||||
$require_login = apply_filters('mcb_require_login_for_viewing', false);
|
||||
|
||||
if ($require_login && !is_user_logged_in()) {
|
||||
wp_die('Please log in to view code repositories', 403);
|
||||
}
|
||||
|
||||
$repo = isset($_POST['repo']) ? sanitize_text_field($_POST['repo']) : '';
|
||||
$path = isset($_POST['path']) ? sanitize_text_field($_POST['path']) : '';
|
||||
|
||||
// Validate repository format
|
||||
if (!MCB_Security::validate_repo_format($repo)) {
|
||||
wp_send_json_error('Invalid repository format');
|
||||
return;
|
||||
}
|
||||
|
||||
$github_api = new MCB_GitHub_API();
|
||||
$files = $github_api->get_repository_files($repo, $path);
|
||||
|
||||
if (is_wp_error($files)) {
|
||||
wp_send_json_error($files->get_error_message());
|
||||
return;
|
||||
}
|
||||
|
||||
wp_send_json_success($files);
|
||||
}
|
||||
|
||||
public function add_admin_menu() {
|
||||
add_options_page(
|
||||
'GitHub Code Viewer Settings',
|
||||
'GitHub Code Viewer',
|
||||
'manage_options',
|
||||
'maple-code-blocks',
|
||||
array($this, 'admin_page')
|
||||
);
|
||||
}
|
||||
|
||||
public function admin_page() {
|
||||
include MCB_PLUGIN_PATH . 'admin/settings-page.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get client IP address for rate limiting
|
||||
*/
|
||||
private function get_client_ip() {
|
||||
$ip_keys = array('HTTP_CF_CONNECTING_IP', 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR');
|
||||
foreach ($ip_keys as $key) {
|
||||
if (array_key_exists($key, $_SERVER) === true) {
|
||||
$ips = explode(',', $_SERVER[$key]);
|
||||
foreach ($ips as $ip) {
|
||||
$ip = trim($ip);
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP,
|
||||
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
|
||||
return $ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the plugin
|
||||
Maple_Code_Blocks::get_instance();
|
||||
|
||||
// Register deactivation hook to clean up scheduled events
|
||||
register_deactivation_hook(__FILE__, 'mcb_deactivate');
|
||||
function mcb_deactivate() {
|
||||
// Remove scheduled cleanup event
|
||||
$timestamp = wp_next_scheduled('mcb_privacy_cleanup');
|
||||
if ($timestamp) {
|
||||
wp_unschedule_event($timestamp, 'mcb_privacy_cleanup');
|
||||
}
|
||||
|
||||
// Clear all MCB transients
|
||||
global $wpdb;
|
||||
$wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_mcb_%'");
|
||||
$wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_mcb_%'");
|
||||
}
|
||||
|
||||
// Register uninstall hook for complete cleanup
|
||||
register_uninstall_hook(__FILE__, 'mcb_uninstall');
|
||||
function mcb_uninstall() {
|
||||
// Remove all plugin options
|
||||
delete_option('mcb_settings');
|
||||
delete_option('mcb_github_token_encrypted');
|
||||
delete_option('mcb_gitlab_token_encrypted');
|
||||
delete_option('mcb_bitbucket_token_encrypted');
|
||||
delete_option('mcb_codeberg_token_encrypted');
|
||||
|
||||
// Clear all transients
|
||||
global $wpdb;
|
||||
$wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_mcb_%'");
|
||||
$wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_mcb_%'");
|
||||
$wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_site_transient_mcb_%'");
|
||||
$wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_site_transient_timeout_mcb_%'");
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue