Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
kmgalanakis committed Mar 24, 2023
1 parent 85ccd6b commit 292e8c9
Show file tree
Hide file tree
Showing 10 changed files with 621 additions and 194 deletions.
1 change: 1 addition & 0 deletions config/webpack.settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
module.exports = {
entries: {
// JS files.
admin: './src/js/admin.js',
gutenberg: './src/js/gutenberg.js',
'classic-editor': './src/js/classic-editor.js',

Expand Down
54 changes: 54 additions & 0 deletions includes/admin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
/**
* Insecure Content Warning assets
*
* @package ICW
*/

namespace ICW\Admin;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

/**
* Setup actions and filters
*/
function setup() {
add_action( 'admin_menu', __NAMESPACE__ . '\\admin_menu' );
}

function admin_menu() {
$hook = add_management_page(
__( 'Insecure Content Warning Admin', 'insecure-content-warning' ),
__( 'Insecure Content Warning', 'insecure-content-warning' ),
'install_plugins',
'insecure-content-warning',
__NAMESPACE__ . '\\admin_page'
);

// add_action( "load-$hook", __NAMESPACE__ . '\\admin_page_load' );

add_action( 'admin_print_scripts-' . $hook, 'ICW\Assets\admin_scripts' );
}


//function admin_page_load() {
// echo 'test';
//}

function admin_page() {
require_once __DIR__ . '/partials/admin-page.php';
}


function admin_js() {
$asset = require_once $asset_file;
wp_enqueue_script(
'insecure-content-admin',
INSECURE_CONTENT_URL . 'dist/js/admin.js',
[],
$asset['version'],
true
);
};
24 changes: 24 additions & 0 deletions includes/assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,30 @@ function enqueue_scripts( $hook = '' ) {
}
}

/**
* Enqueue admin-only JavaScript/CSS
*/
function admin_scripts() {
$asset_file = INSECURE_CONTENT_PATH . 'dist/js/admin.asset.php';
if ( file_exists( $asset_file ) ) {
$asset = require_once $asset_file;
wp_enqueue_script(
'insecure-content-admin',
INSECURE_CONTENT_URL . 'dist/js/admin.js',
$asset['dependencies'],
$asset['version'],
true
);

wp_enqueue_style(
'insecure-content-admin',
INSECURE_CONTENT_URL . 'dist/css/admin-style.css',
false,
$asset['version'],
);
}
}

/**
* Display a notice about JS and CSS assets missing
*
Expand Down
276 changes: 276 additions & 0 deletions includes/classes/FixInsecureContent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
<?php

namespace ICW\FIX;

use WP_CLI;
use WP_CLI\Utils;
use WP_CLI_Command;

class FixInsecureContent {

/**
* Is current run a dry run?
*
* @var bool
*/
private $dry_run;

/**
* Total number of posts scanned for URLs.
*
* @var int
*/
private $total_post_count = 1;

/**
* Data of posts where 1 or more URLs were found to be insecure and command fixed summary.
*
* @var array
*/
private $fixed_post_count;

/**
* Lorem.
*
* @var array
*/
private $warning_count = [];

/**
* Class instance
*
* @var FixInsecureContent
*/
protected static $instance = null;

/**
* Get class instance
*
* @return FixInsecureContent
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}

return self::$instance;
}

/**
* Test
*
* @param bool|string $include
* @param string $all
* @param string $post_type
* @param int $posts_per_page
* @param int $post_offset
* @param bool $dry_run
* @param array $args
*
* @return array|void
*/
public function fix( $include, $all, $post_type, $posts_per_page, $post_offset, $dry_run, $args = [] ) {
$this->dry_run = $dry_run;

if ( defined( 'WP_CLI' ) && WP_CLI ) {
WP_CLI::log( __( 'Checking post content...', 'insecure-content-warning' ) );
}

if ( false === $all && ! empty( $args[0] ) ) {
$this->fix_insecure_content( $args[0] );
} elseif ( false === $all && empty( $args ) && false !== $include ) {
$post_ids_list = explode( ',', $include );
foreach ( $post_ids_list as $icw_post_id ) {
$this->fix_insecure_content( trim( $icw_post_id ) );
}
$this->total_post_count = count( $post_ids_list );
} else {
$total = 0;

// Loop through all posts and fix content.
while ( true ) {
$args = [
'posts_per_page' => $posts_per_page,
'post_type' => $post_type,
'post_status' => 'publish',
'offset' => $post_offset,
];
$query = new \WP_Query( $args );

if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
$this->fix_insecure_content( get_the_ID() );
}
} else {
break;
}

// Set offset for next page.
$post_offset += $posts_per_page;
$total += $query->post_count;

// Wait for a while before fixing the rest.
usleep( 1000 );
}

$this->total_post_count = $total;
}

// translators: Lala
$message = PHP_EOL . sprintf( __( 'Total posts checked for insecure URL(s): %s', 'insecure-content-warning' ), $this->total_post_count ) . PHP_EOL;
if ( defined( 'WP_CLI' ) && WP_CLI ) {
WP_CLI::log( WP_CLI::colorize( "%c{$message}%n " ) );
Utils\format_items( 'table', $this->fixed_post_count, [ 'URL(s) fixed summary' ] );
} else {
if ( null === $this->fixed_post_count ) {
return __( 'No post(s) found', 'insecure-content-warning' );
}
$output = '';

foreach ( $this->warning_count as $warning ) {
$warning_message = array_shift( $warning );
$output .= '<span class="warning">' . __( 'Warning', 'insecure-content-warning' ) . '</span>: ' . $warning_message . PHP_EOL;
}

$output .= '<span class="info">' . $message . '</span>' . PHP_EOL;

foreach ( $this->fixed_post_count as $fixed_post ) {
$output .= array_shift( $fixed_post ) . PHP_EOL;
}
return $output;
}
}

/**
* Fix insecure content for given Post ID.
*
* @param int $post_id Post ID.
*
* @return array|string
*/
protected function fix_insecure_content( $post_id ) {
$current_post = get_post( $post_id );

// Check and make sure post exists.
if ( empty( $current_post ) ) {
// translators: Message to show when the system is unable to fetch details for the post.
$message = sprintf( __( 'Unable to fetch details for post %s', 'insecure-content-warning' ), $post_id );
if ( defined( 'WP_CLI' ) && WP_CLI ) {
// translators: Message to show when the system is unable to fetch details for the post.
WP_CLI::warning( $message );
} else {
$this->warning_count[] = [ __( 'Warning', 'insecure-content-warning' ) => $message ];
}
return '';
}

// Loop through post content and get HTTPS URLs wherever possible.
$post_content = $current_post->post_content;
$urls = $this->parse_content_for_insecure_urls( $post_content );
$count = 0;

// Check if post content has insecure URLs.
if ( empty( $urls ) ) {
// translators: Message to show when no insecure content URL found in the post.
$message = sprintf( __( 'No insecure content URL found in post %s', 'insecure-content-warning' ), $post_id );
if ( defined( 'WP_CLI' ) && WP_CLI ) {
WP_CLI::warning( $message );
} else {
$this->warning_count[] = [ __( 'Warning', 'insecure-content-warning' ) => $message ];
}

if ( $this->dry_run ) {
// translators: Summary to show on dry run fix.
$this->fixed_post_count[] = [ __( 'URL(s) fixed summary', 'insecure-content-warning' ) => sprintf( __( '0/0 URL(s) will be fixed in post %s', 'insecure-content-warning' ), $post_id ) ];
} else {
// translators: Summary to show on fix.
$this->fixed_post_count[] = [ __( 'URL(s) fixed summary', 'insecure-content-warning' ) => sprintf( __( '0/0 URL(s) fixed in post %s', 'insecure-content-warning' ), $post_id ) ];
}

return '';
}

foreach ( $urls as $url ) {
if ( $this->does_secure_content_exist( $url ) ) {
$ssl_url = preg_replace( '/^http:/i', 'https:', $url );
$post_content = str_replace( $url, $ssl_url, $post_content );
$count ++;
}
}

if ( false === $this->dry_run ) {
// Update post content with HTTPS URLs.
wp_update_post(
[
'ID' => $post_id,
'post_content' => $post_content,
]
);
}

if ( $this->dry_run ) {
// translators: Summary to show on dry run fix.
$dry_run_message = sprintf( __( '%1$s/%2$s insecure URLs will be fixed in post %3$s.', 'insecure-content-warning' ), $count, count( $urls ), $post_id );
if ( defined( 'WP_CLI' ) && WP_CLI ) {
WP_CLI::debug( $dry_run_message );
}
$this->fixed_post_count[] = [ 'URL(s) fixed summary' => $dry_run_message ];
} else {
// translators: Summary to show on fix.
$success_message = sprintf( __( '%1$s/%2$s insecure URLs fixed in post %3$s.', 'insecure-content-warning' ), $count, count( $urls ), $post_id );
if ( defined( 'WP_CLI' ) && WP_CLI ) {
WP_CLI::debug( $success_message );
}
$this->fixed_post_count[] = [ 'URL(s) fixed summary' => $success_message ];
}
}

/**
* Check if a SSL version of the URL exists.
*
* @param string $url URL to check for SSL version.
*
* @return bool
*/
protected function does_secure_content_exist( $url ) {
// Check if a https version of the URL exists.
$secure_version_exists = false;
$ssl = preg_replace( '/^http:/i', 'https:', $url );
$response = wp_remote_get( $ssl );
$response_code = wp_remote_retrieve_response_code( $response );

if ( 200 === $response_code ) {
$secure_version_exists = true;
}

return $secure_version_exists;
}

/**
* Create list of URLs.
*
* @param string $post_content Post Content.
*
* @return array
*/
protected function parse_content_for_insecure_urls( $post_content ) {
// Check all src and create an array of URLs to check https URL availability.
$src_urls = [];
$src_regex = '/src="([^"]+)"/';
preg_match_all( $src_regex, $post_content, $matches, PREG_SET_ORDER, 0 );

// If we have matches, loop through and get clean URL.
if ( ! empty( $matches ) ) {
foreach ( $matches as $match ) {
$matched_url = $match[1];
$base_url = explode( '?', $matched_url )[0];
if ( 'https://' !== substr( $base_url, 0, 8 ) ) {
$src_urls[] = $base_url;
}
}
}

return $src_urls;
}
}
Loading

0 comments on commit 292e8c9

Please sign in to comment.