Initial commit of 0.2.0

This commit is contained in:
Cooper Dalrymple
2025-07-22 15:53:23 -05:00
parent 58a5fbbcb2
commit 70a9adac4c
13 changed files with 775 additions and 3 deletions

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
vendor
lib
composer.lock
package-lock.json
node_modules
*.zip

25
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,25 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Package",
"type": "shell",
"command": "gulp package",
"group": "build",
"presentation": {
"reveal": "silent",
"panel": "shared",
}
},
{
"label": "Install",
"type": "shell",
"command": "make install",
"group": "build",
"presentation": {
"reveal": "silent",
"panel": "shared",
}
}
]
}

22
Makefile Normal file
View File

@@ -0,0 +1,22 @@
all: install
reinstall: clean install
clean: clean-composer clean-npm
clean-composer:
rm -rf vendor/* || true
rm -rf lib/* || true
rm composer.lock || true
composer clearcache
clean-npm:
rm -rf node_modules/* || true
rm package-lock.json || true
install:
composer install
npm install
package: install
gulp package

View File

@@ -1,3 +0,0 @@
# ogre-obfuscation
Want to remove email addresses from your site when viewed by a robot using client-side encryption techniques? Then this is the plugin for you. Obscuring your email address to pesky bots can help reduce spam while still providing your clients with a direct way to message you and your business.

65
assets/js/obfuscation.js Normal file
View File

@@ -0,0 +1,65 @@
/**
* @package ogre-obfuscation
* @author cleverogre
* @version 0.2.0
* @since 0.1.0
*/
(() => {
const reObfuscateElement = (element) => {
element.outerHTML = unEncodeEmailChars(reObfuscateCore(element.getAttribute('data-content')));
};
const reObfuscate = (str, id) => {
const el = document.getElementById(id);
const newEl = document.createTextNode('');
newEl.innerHTML = unEncodeEmailChars(reObfuscateCore(str));
el.parentNode.replaceChild(newEl, el);
};
const reObfuscateCore = (str) => {
let out = '';
for (let i = 0; i < str.length; i++) {
out = str.charAt(i) + out;
}
return out;
};
const unEncodeEmailChars = (str) => {
let i = 0;
let num = '';
let out = '';
while (i < str.length) {
if (str.charAt (i) == '&') {
num = '';
i += 2; /// skip &#
while (str.charAt(i) != ';' && i < str.length) {
num += str.charAt(i);
i++;
}
if (str.charAt(i) == ";") {
i++;
}
out += String.fromCharCode(parseInt(num));
} else {
out += str.charAt(i);
i++;
}
}
return out;
};
document.addEventListener('DOMContentLoaded', () => {
const elements = document.getElementsByClassName('obfuscate');
for (let i = elements.length - 1; i >= 0; i--) {
reObfuscateElement(elements[i]);
}
});
})();

48
composer.json Normal file
View File

@@ -0,0 +1,48 @@
{
"$schema": "https://getcomposer.org/schema.json",
"name": "cleverogre/ogre-obfuscation",
"version": "0.2.0",
"title": "Ogre Obfuscation",
"description": "Ogre Obfuscation is a plugin developed by CleverOgre in Pensacola, Florida.",
"author": "CleverOgre",
"license": "GPL-3.0+",
"keywords": [
"WordPress",
"Plugin",
"Obfuscation"
],
"homepage": "https://cleverogre.com",
"repositories": {
"cleverogre/plugin-framework": {
"type": "vcs",
"url": "git@git.cleverogre.com:cleverogre/plugin-framework.git"
},
"wp-package-updater": {
"type": "package",
"package": {
"name": "froger-me/wp-package-updater",
"version": "1.4.0",
"source": {
"url": "https://github.com/froger-me/wp-package-updater.git",
"type": "git",
"reference": "master"
}
}
}
},
"require": {
"cleverogre/plugin-framework": "dev-main",
"simplehtmldom/simplehtmldom": "dev-master"
},
"replace": {
"wpengine/advanced-custom-fields-pro": "*"
},
"scripts": {
"post-update-cmd": [
"php vendor/magicoli/wp-package-updater-lib/install.php"
]
},
"config": {
"optimize-autoloader": true
}
}

53
gulpfile.js Normal file
View File

@@ -0,0 +1,53 @@
const gulp = require('gulp'),
clean = require('gulp-clean'),
zip = require('gulp-zip').default;
// Clean Tasks
gulp.task('clean-package', () => {
return gulp.src('ogre-obfuscation.zip', {
read: false,
allowEmpty: true,
}).pipe(clean());
});
gulp.task(
'clean',
gulp.series(
'clean-package'
)
);
// Package Tasks
gulp.task('package-compress', () => {
return gulp.src([
'assets/**/*',
'inc/**/*',
'lib/**/*',
'vendor/**/*',
'LICENSE',
'ogre-obfuscation.php',
'readme.txt'
], { base: './' })
.pipe(zip('ogre-obfuscation.zip'))
.pipe(gulp.dest('./'));
});
gulp.task(
'package',
gulp.series(
'clean',
'package-compress'
)
);
// Default Tasks
gulp.task(
'default',
gulp.series(
'clean',
'package'
)
);

73
inc/filter.php Normal file
View File

@@ -0,0 +1,73 @@
<?php
/**
* @package ogre-obfuscation
* @author cleverogre
* @version 0.2.0
* @since 0.1.0
*/
namespace Ogre\Obfuscation;
use Ogre\Singleton;
use Ogre\Obfuscation;
defined('ABSPATH') || exit;
final class Filter {
use Singleton;
protected function __construct() {
add_action('wp', array($this, 'init'));
}
public function init() {
if (!email_enabled()) return;
add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));
add_action('the_content', array($this, 'filter_content'), 100, 1);
add_filter('wp_nav_menu_items', array($this, 'filter_content'), 100, 1);
add_filter('dynamic_sidebar_params', array($this, 'sidebar_params'), 100, 1);
add_filter('widget_output', array($this, 'filter_content'), 100, 1);
}
public function enqueue_scripts() {
wp_enqueue_script('obfuscation', Obfuscation::get_url('assets/js/obfuscation.js'), array(), Obfuscation::get_version(), true);
}
public function filter_content($content) {
if (!find_emails($content)) return $content;
return filter($content);
}
public function sidebar_params($params) {
global $wp_registered_widgets;
$widget_id = $params[0]['widget_id'];
$wp_registered_widgets[$widget_id]['_callback'] = $wp_registered_widgets[$widget_id]['callback'];
$wp_registered_widgets[$widget_id]['callback'] = array($this, 'widget_callback');
return $params;
}
public function widget_callback() {
global $wp_registered_widgets;
$params = func_get_args();
$widget_id = $params[0]['widget_id'];
$callback = $wp_registered_widgets[$widget_id]['_callback'];
$wp_registered_widgets[$widget_id]['callback'] = $callback;
$widget_id_base = $wp_registered_widgets[$widget_id]['callback'][0]->id_base;
if (is_callable($callback)) {
ob_start();
call_user_func_array($callback, $params);
$widget_output = ob_get_clean();
echo apply_filters('widget_output', $widget_output, $widget_id_base, $widget_id);
}
}
}
Filter::instance();

154
inc/global.php Normal file
View File

@@ -0,0 +1,154 @@
<?php
/**
* @package ogre-obfuscation
* @author cleverogre
* @version 0.2.0
* @since 0.1.0
*/
namespace Ogre\Obfuscation;
use simplehtmldom\HtmlDocument;
use function is_user_logged_in;
defined('ABSPATH') || exit;
function email_enabled() {
if (is_user_logged_in()) return false;
if (Settings::instance()->email_enabled != '1') return false;
return true;
}
function obfuscate($str) {
static $obfuscate_id = 0;
$out = '';
for ($i = 0; $i < strlen($str); $i++) {
$out .= '&#' . ord(substr($str, $i, 1)) . ';';
}
$out2 = '';
for ($i = 0; $i < strlen($out); $i++) {
$out2 = substr($out, $i, 1) . $out2;
}
$output = "<span class=\"obfuscate\" id=\"obfuscate-{$obfuscate_id}\" data-content=\"{$out2}\"></span>";
$obfuscate_id++;
return $output;
}
function _obfuscate_element($element) {
return obfuscate($element->outertext);
}
function find_emails($str) {
preg_match_all('/[a-zA-Z0-9_\-\+\.]+@[a-zA-Z0-9\-]+\.([a-z]{2,4})(?:\.[a-z]{2})?/i', $str, $matches, PREG_OFFSET_CAPTURE);
if (!is_array($matches) || empty($matches)) return false;
$return = array();
foreach ($matches[0] as $match) {
$return[] = array(
'text' => $match[0],
'pos' => $match[1],
'len' => strlen($match[0]),
);
}
return $return;
}
function filter($content) {
// Parse content
$html = new HtmlDocument();
$html->load('<div id="dom_root">' . $content . '</div>');
//_filter_html($html->find('div[id=dom_root]', 0));
$html->find('div[id=dom_root]', 0)->outertext = _filter_html($html->find('div[id=dom_root]', 0));
$html->find('div[id=dom_root]', 0)->outertext = $html->find('div[id=dom_root]', 0)->innertext; // remove root div wrapper
$content = $html->save();
// Clean up memory
$html->clear();
unset($html);
return $content;
}
function _filter_html($element) {
if ($element == null) return false;
switch ($element->tag) {
case 'a':
if (_test_anchor($element)) {
return _obfuscate_element($element);
} else {
return $element->outertext;
}
default:
$node = _get_text_node($element);
$node['text'] = _filter_text($node['text']);
foreach ($node['tags'] as &$tag) {
$tag['content'] = _filter_html($tag['element']);
}
$element->outertext = _set_text_node($node);
return $element->outertext;
}
}
function _filter_text($text) {
$emails = find_emails($text);
if (!$emails) return $text;
for ($i = count($emails) - 1; $i >= 0; $i--) {
$text = substr($text, 0, $emails[$i]['pos']) . obfuscate($emails[$i]['text']) . substr($text, $emails[$i]['pos'] + $emails[$i]['len']);
}
return $text;
}
function _get_text_node($element) {
//$tag_pattern = '/<\s*[a-zA-Z]+[^>]*>.*?<\s*\/\s*[a-zA-Z]+>/is'
$text = $element->outertext;
$return = array(
'raw' => $text,
'text' => '',
'tags' => array(),
);
$i = 0;
foreach ($element->children() as $child) {
$return['tags'][$i] = array(
'element' => $child,
'index' => $i,
'key' => "[[{$i}]]",
'content' => $child->outertext,
'pos' => strpos($text, $child->outertext),
'len' => strlen($child->outertext),
);
$text = str_replace($child->outertext, "[[{$i}]]", $text);
$i++;
}
$return['text'] = $text;
return $return;
}
function _set_text_node($node) {
$text = $node['text'];
foreach ($node['tags'] as $tag) {
$text = str_replace($tag['key'], $tag['content'], $text);
}
return $text;
}
function _test_anchor($element) {
if ($element->tag != 'a') return false;
return preg_match('/<a.*>[a-zA-Z0-9_\-\+\.]+@[a-zA-Z0-9\-]+\.([a-z]{2,4})(?:\.[a-z]{2})?<\/a>/i', $element->outertext) == 1;
}

208
inc/settings.php Normal file
View File

@@ -0,0 +1,208 @@
<?php
/**
* @package ogre-obfuscation
* @author cleverogre
* @version 0.2.0
* @since 0.1.0
*/
namespace Ogre\Obfuscation;
use Ogre\Singleton;
defined('ABSPATH') || exit;
final class Settings {
use Singleton;
private $defaults; // Value set in get function
// Admin Settings
public $email_enabled;
protected function __construct() {
// Use getter/setter if not set
foreach ($this as $key => $value) {
unset($this->$key);
}
}
public function __set($key, $value) {
if (property_exists($this, $key)) {
switch ($key) {
/* // Read-only properties
case 'readonly':
break;
*/
default:
$options = get_option('obfuscation_options');
$options['obfuscation_settings_' . $key] = $value;
update_option('obfuscation_options', $options);
break;
}
}
return $this;
}
public function __get($key) {
if (property_exists($this, $key)) {
switch ($key) {
// Constant properties
case 'defaults':
return array(
'email_enabled' => '1',
);
break;
default:
$options = get_option('obfuscation_options');
if (isset($options['obfuscation_settings_' . $key]) && !empty($options['obfuscation_settings_' . $key])) {
return $options['obfuscation_settings_' . $key];
} else if (isset($this->defaults[$key])) {
return $this->defaults[$key];
} else {
return false;
}
break;
}
}
return null;
}
}
final class SettingsPage {
use Singleton;
protected function __construct() {
add_action('admin_init', array($this, 'init'));
add_action('admin_menu', array($this, 'menu'));
}
public function menu() {
if (!current_user_can('manage_options')) return;
$page = add_options_page(__('Ogre Obfuscation Settings', 'obfuscation'), __('Ogre Obfuscation', 'obfuscation'), 'manage_options', 'obfuscation_settings', array($this, 'page'));
add_action('load-' . $page, array($this, 'load'));
}
public function load() {
if (!current_user_can('manage_options')) return;
add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'));
}
public function admin_enqueue_scripts() {
//wp_enqueue_script('obfuscation-admin', Settings::instance()->dir . 'assets/js/obfuscation.admin.js', array('jquery'), Settings::instance()->version, true);
}
public function init() {
register_setting('obfuscation', 'obfuscation_options'); //, array($this, 'validate_options'));
// Message Settings
add_settings_section('obfuscation_section_obfuscation', __('Obfuscation', 'obfuscation'), array($this, 'section'), 'obfuscation');
add_settings_field('obfuscation_email_enabled', __('Email Obfuscation Enabled', 'obfuscation'), array($this, 'field_checkbox'), 'obfuscation', 'obfuscation_section_obfuscation', array(
'id' => 'obfuscation_settings_email_enabled',
'default' => Settings::instance()->defaults['email_enabled'],
));
}
public function page() {
if (!current_user_can('manage_options')) return;
// Check if the user has submitted the settings
if (isset($_GET['settings-updated'])) {
// Show update message
//add_settings_error('obfuscation_messages', 'obfuscation_message', __('Settings Saved', 'obfuscation'), 'updated');
}
// Show error/update messages
settings_errors('obfuscation_messages');
?>
<div class="wrap">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<form action="options.php" method="post"><?php
settings_fields('obfuscation');
do_settings_sections('obfuscation');
submit_button(__('Save Settings', 'obfuscation'));
?></form>
</div>
<?php
}
// Sections
public function section($args) {
// <p>Description</p>
}
// Fields
public function field_text($args) {
$value = '';
$options = get_option('obfuscation_options');
if (isset($args['default'])) $value = $args['default'];
if (isset($args['id']) && !empty($args['id']) && isset($options[$args['id']]) && !empty($options[$args['id']])) $value = $options[$args['id']];
$type = 'text';
if (isset($args['type']) && !empty($args['type'])) {
$type = $args['type'];
}
echo '<input class="regular-text" type="' . $type . '" value="' . esc_attr($value) . '"';
if (isset($args['id']) && !empty($args['id'])) {
echo ' id="' . esc_attr($args['id']) . '"';
echo ' name="obfuscation_options[' . esc_attr($args['id']) . ']"';
}
if (isset($args['placeholder']) && !empty($args['placeholder'])) {
echo ' placeholder="' . esc_attr($args['placeholder']) . '"';
}
echo ' />';
if (isset($args['description']) && !empty($args['description'])) {
echo '<p class="description">';
_e($args['description'], 'obfuscation');
echo '</p>';
}
}
public function field_checkbox($args) {
$value = false;
$options = get_option('obfuscation_options');
if (isset($args['default'])) $value = $args['default'];
if (isset($args['id']) && !empty($args['id']) && isset($options[$args['id']]) && !empty($options[$args['id']])) $value = $options[$args['id']];
echo '<input type="checkbox" value="1" type="checkbox" ' . checked($value, 1, false);
if (isset($args['id']) && !empty($args['id'])) {
echo ' id="' . esc_attr($args['id']) . '"';
echo ' name="obfuscation_options[' . esc_attr($args['id']) . ']"';
}
echo ' />';
if (isset($args['description']) && !empty($args['description'])) {
echo '<p class="description">';
esc_html_e($args['description'], 'obfuscation');
echo '</p>';
}
}
public function validate_options($fields) {
$valid_fields = array();
foreach ($fields as $id => $field) {
if (!isset($input[$id])) continue;
}
return apply_filters('validate_options', $valid_fields, $fields);
}
}
SettingsPage::instance();

56
ogre-obfuscation.php Normal file
View File

@@ -0,0 +1,56 @@
<?php
/*
Plugin Name: Ogre Obfuscation
Plugin URI: https://plugins.cleverogre.com/plugin/ogre-obfuscation/
Description: Ogre Obfuscation is a plugin developed by CleverOgre in Pensacola, Florida.
Version: 0.2.0
Author: CleverOgre
Author URI: http://cleverogre.com/
Text Domain: obfuscation
License: GPLv3 or later
License URI: http://www.gnu.org/licenses/gpl-3.0.html
Copyright: CleverOgre, Inc.
*/
namespace Ogre;
defined('ABSPATH') || exit;
require_once 'vendor/autoload.php';
final class Obfuscation extends Plugin {
protected function __construct() {
parent::__construct();
$this->add_files([
'inc/settings.php',
'inc/global.php', // Global Functions
'inc/filter.php', // Content and navigation filters
]);
}
protected function enable():void {
parent::enable();
add_filter('plugin_action_links_' . self::get_basename(), [$this, 'action_links']);
}
protected function disable():void {
parent::disable();
remove_filter('plugin_action_links_' . self::get_basename(), [$this, 'action_links']);
}
public function action_links($links) {
if (current_user_can('manage_options')) {
array_unshift($links, sprintf(
'<a href="%s">%s</a>',
esc_url(admin_url('options-general.php?page=obfuscation_settings')),
esc_html(self::__('Settings'))
));
}
return $links;
}
}
Obfuscation::instance();

25
package.json Normal file
View File

@@ -0,0 +1,25 @@
{
"$schema": "https://getcomposer.org/schema.json",
"name": "cleverogre/ogre-obfuscation",
"version": "0.2.0",
"title": "Ogre Obfuscation",
"description": "Ogre Obfuscation is a plugin developed by CleverOgre in Pensacola, Florida.",
"author": "CleverOgre",
"license": "GPL-3.0+",
"keywords": [
"WordPress",
"Plugin",
"Obfuscation"
],
"homepage": "https://cleverogre.com",
"engines": {
"node": ">=21.1.0",
"npm": ">=10.2.3"
},
"devDependencies": {
"gulp": "^5.0.0",
"gulp-clean": "^0.4.0",
"gulp-cli": "^2.3.0",
"gulp-zip": "^6.1.0"
}
}

40
readme.txt Normal file
View File

@@ -0,0 +1,40 @@
=== Ogre Obfuscation ===
Contributors: ogrecooper, cleverogre
Tested up to: 6.8
Requires at least: 5.0
Requires PHP: 8.0
Version: 0.2.0
License: GPLv3 or later
License URI: https://www.gnu.org/licenses/gpl-3.0.html
Copyright: CleverOgre
Donate link: https://cleverogre.com/
Tags: wordpress, plugin, obfuscation, email, phone
Ogre Obfuscation is a plugin developed by CleverOgre in Pensacola, Florida.
== Description ==
TODO
== Installation ==
The required libraries can be installed using the following command:
composer install
You can install the optional development tools using the following command:
npm install
== FAQ ==
= What is this plugin? =
If you don't know what plugin you have downloaded, please contact [CleverOgre](team@cleverogre.com) for more information. This plugin is only developed for a small, private audience.
== Changelog ==
= 0.2.0 - 2025-07-22 =
* DEV: Implemented `cleverogre/plugin-framework`
* DEV: Code rewritten for PHP 8.0+
= 0.1.0 =
* Initial release