- Add .distignore (operator-private files excluded) - Add build.sh for WordPress-installable release ZIPs - Update CLAUDE.md references (now operator-private only)
605 lines
22 KiB
PHP
605 lines
22 KiB
PHP
<?php
|
||
/**
|
||
* Plugin Name: TigerStyle Scent
|
||
* Plugin URI: https://tigerstyle.com/scent-plugin
|
||
* Description: Enterprise OAuth2 authentication server - leave your digital scent trail for secure access control. Like cats authenticate each other through scent, TigerStyle Scent provides secure OAuth2 authentication for your WordPress territory.
|
||
* Version: 1.0.0
|
||
* Author: TigerStyle
|
||
* Author URI: https://tigerstyle.com
|
||
* License: GPL v2 or later
|
||
* Text Domain: tigerstyle-scent
|
||
* Domain Path: /languages
|
||
* Requires at least: 5.0
|
||
* Tested up to: 6.4
|
||
* Requires PHP: 7.4
|
||
* Network: false
|
||
*/
|
||
|
||
// Prevent direct access to maintain territory security
|
||
defined('ABSPATH') or die('🐯 Direct access to TigerStyle territory forbidden.');
|
||
|
||
// Plugin constants for scent trail management
|
||
define('TIGERSTYLE_SCENT_VERSION', '1.0.0');
|
||
define('TIGERSTYLE_SCENT_PLUGIN_FILE', __FILE__);
|
||
define('TIGERSTYLE_SCENT_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
||
define('TIGERSTYLE_SCENT_PLUGIN_URL', plugin_dir_url(__FILE__));
|
||
define('TIGERSTYLE_SCENT_PLUGIN_BASENAME', plugin_basename(__FILE__));
|
||
|
||
// Debug mode for scent trail tracking
|
||
if (!defined('TIGERSTYLE_SCENT_DEBUG')) {
|
||
define('TIGERSTYLE_SCENT_DEBUG', WP_DEBUG);
|
||
}
|
||
|
||
/**
|
||
* Main TigerStyle Scent Plugin Class
|
||
*
|
||
* Manages the entire OAuth2 authentication ecosystem like an alpha cat managing territory
|
||
*/
|
||
class TigerStyleScent {
|
||
|
||
/**
|
||
* Single instance of the plugin (singleton pattern like a territorial cat)
|
||
* @var TigerStyleScent|null
|
||
*/
|
||
private static $instance = null;
|
||
|
||
/**
|
||
* Plugin modules (like different scent detection systems)
|
||
* @var array
|
||
*/
|
||
private $modules = array();
|
||
|
||
/**
|
||
* Plugin settings
|
||
* @var array
|
||
*/
|
||
private $settings = array();
|
||
|
||
/**
|
||
* Scent server instance
|
||
* @var TigerStyleScent_ScentServer|null
|
||
*/
|
||
private $scent_server = null;
|
||
|
||
/**
|
||
* Get singleton instance (territorial control)
|
||
*
|
||
* @return TigerStyleScent
|
||
*/
|
||
public static function instance() {
|
||
if (is_null(self::$instance)) {
|
||
self::$instance = new self();
|
||
}
|
||
return self::$instance;
|
||
}
|
||
|
||
/**
|
||
* Constructor - Initialize the TigerStyle Scent territory
|
||
*/
|
||
private function __construct() {
|
||
$this->load_dependencies();
|
||
$this->init_hooks();
|
||
$this->load_settings();
|
||
$this->init_modules();
|
||
|
||
// Log plugin initialization
|
||
$this->log_scent_event('plugin_initialized', [
|
||
'version' => TIGERSTYLE_SCENT_VERSION,
|
||
'php_version' => PHP_VERSION,
|
||
'wp_version' => get_bloginfo('version')
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* Load plugin dependencies like gathering scent detection tools
|
||
*/
|
||
private function load_dependencies(): void {
|
||
// Load interface first
|
||
require_once TIGERSTYLE_SCENT_PLUGIN_DIR . 'includes/class-authenticator-interface.php';
|
||
|
||
// Load security components first
|
||
require_once TIGERSTYLE_SCENT_PLUGIN_DIR . 'includes/class-security-logger.php';
|
||
require_once TIGERSTYLE_SCENT_PLUGIN_DIR . 'includes/class-rate-limiter.php';
|
||
require_once TIGERSTYLE_SCENT_PLUGIN_DIR . 'includes/class-input-validator.php';
|
||
|
||
// Load core modules
|
||
require_once TIGERSTYLE_SCENT_PLUGIN_DIR . 'includes/modules/class-scent-server.php';
|
||
require_once TIGERSTYLE_SCENT_PLUGIN_DIR . 'includes/modules/class-scent-authenticator.php';
|
||
|
||
// Load admin components if in admin area
|
||
if (is_admin()) {
|
||
$this->load_admin_dependencies();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Load admin-specific dependencies
|
||
*/
|
||
private function load_admin_dependencies(): void {
|
||
// Admin components will be loaded here
|
||
// require_once TIGERSTYLE_SCENT_PLUGIN_DIR . 'admin/class-admin.php';
|
||
}
|
||
|
||
/**
|
||
* Initialize WordPress hooks like setting up scent detection points
|
||
*/
|
||
private function init_hooks(): void {
|
||
// Plugin lifecycle hooks
|
||
register_activation_hook(TIGERSTYLE_SCENT_PLUGIN_FILE, array($this, 'activate_territory'));
|
||
register_deactivation_hook(TIGERSTYLE_SCENT_PLUGIN_FILE, array($this, 'deactivate_territory'));
|
||
|
||
// Core WordPress hooks
|
||
add_action('init', array($this, 'init_oauth_endpoints'));
|
||
add_action('template_redirect', array($this, 'handle_oauth_requests'));
|
||
add_filter('determine_current_user', array($this, 'authenticate_user'), 20);
|
||
add_action('rest_api_init', array($this, 'setup_rest_authentication'));
|
||
|
||
// Admin hooks
|
||
if (is_admin()) {
|
||
add_action('admin_menu', array($this, 'add_admin_menu'));
|
||
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
|
||
}
|
||
|
||
// Custom post type for OAuth clients (scent profiles)
|
||
add_action('init', array($this, 'register_client_post_type'));
|
||
|
||
// AJAX hooks for admin interface
|
||
add_action('wp_ajax_tigerstyle_scent_test_auth', array($this, 'ajax_test_authentication'));
|
||
}
|
||
|
||
/**
|
||
* Load plugin settings from WordPress options
|
||
*/
|
||
private function load_settings(): void {
|
||
// 🔐 SECURITY: Secure-by-default configuration - WordPress community gold standard
|
||
$defaults = array(
|
||
// Core security settings
|
||
'enable_scent_authentication' => true,
|
||
'require_https' => true, // Mandatory HTTPS - no exceptions
|
||
'enforce_security_headers' => true, // Full security header suite
|
||
'enable_rate_limiting' => true, // Progressive rate limiting enabled
|
||
'enable_security_logging' => true, // Comprehensive threat monitoring
|
||
'enable_input_validation' => true, // Multi-layer validation framework
|
||
|
||
// Token security settings (conservative defaults)
|
||
'scent_token_lifetime' => 1800, // 30 minutes (reduced from 1 hour)
|
||
'refresh_scent_lifetime' => 604800, // 7 days (reduced from 30 days)
|
||
'territory_code_lifetime' => 300, // 5 minutes (reduced from 10)
|
||
'token_entropy_level' => 'maximum', // 384-512 bit tokens
|
||
|
||
// Client security settings
|
||
'require_client_secrets' => true, // Force confidential clients
|
||
'min_client_secret_length' => 32, // Strong secret requirements
|
||
'auto_block_attacks' => true, // Auto-block repeated violations
|
||
'client_secret_rotation_days' => 90, // Encourage regular rotation
|
||
|
||
// Validation & monitoring
|
||
'strict_parameter_validation' => true, // Zero tolerance for invalid input
|
||
'log_all_auth_attempts' => true, // Complete audit trail
|
||
'alert_on_security_events' => true, // Real-time admin alerts
|
||
'auto_cleanup_logs_days' => 90, // Automatic log management
|
||
|
||
// Development vs production
|
||
'debug_scent_trails' => false, // Disabled by default for security
|
||
'development_mode' => false, // Production-first approach
|
||
'detailed_error_messages' => false, // Generic errors by default
|
||
|
||
// Access control
|
||
'allowed_scent_origins' => array(), // Explicit allowlist required
|
||
'scent_strength' => 'high', // Maximum security level by default
|
||
'require_state_parameter' => true, // CSRF protection mandatory
|
||
'enforce_pkce' => true, // PKCE required for all public clients
|
||
|
||
// Security monitoring thresholds
|
||
'max_failed_attempts_per_hour' => 5, // Conservative limit
|
||
'suspicious_pattern_detection' => true, // ML-style pattern analysis
|
||
'geo_blocking_enabled' => false, // Optional geo-restrictions
|
||
'honeypot_endpoints' => true, // Decoy endpoints for threat intel
|
||
);
|
||
|
||
$this->settings = wp_parse_args(
|
||
get_option('tigerstyle_scent_settings', array()),
|
||
$defaults
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Initialize plugin modules like different scent detection systems
|
||
*/
|
||
private function init_modules(): void {
|
||
// Initialize scent server
|
||
$this->scent_server = new TigerStyleScent_ScentServer($this->settings);
|
||
|
||
// Initialize authenticator modules
|
||
$this->modules['scent_authenticator'] = new TigerStyleScent_ScentAuthenticator();
|
||
|
||
// Allow other plugins to add custom authenticators
|
||
$this->modules = apply_filters('tigerstyle_scent_authenticators', $this->modules);
|
||
|
||
// Sort by priority (like cat hierarchy)
|
||
uasort($this->modules, function($a, $b) {
|
||
return $b->get_priority() - $a->get_priority();
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Plugin activation - Set up territory
|
||
*/
|
||
public function activate_territory(): void {
|
||
// Create database tables for scent storage
|
||
$this->create_scent_tables();
|
||
|
||
// Set up rewrite rules for OAuth endpoints
|
||
$this->setup_rewrite_rules();
|
||
flush_rewrite_rules();
|
||
|
||
// Create default settings
|
||
if (!get_option('tigerstyle_scent_settings')) {
|
||
update_option('tigerstyle_scent_settings', $this->settings);
|
||
}
|
||
|
||
// Log activation
|
||
$this->log_scent_event('territory_activated', [
|
||
'version' => TIGERSTYLE_SCENT_VERSION,
|
||
'timestamp' => current_time('mysql')
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* Plugin deactivation - Secure territory
|
||
*/
|
||
public function deactivate_territory(): void {
|
||
// Remove rewrite rules
|
||
flush_rewrite_rules();
|
||
|
||
// Log deactivation
|
||
$this->log_scent_event('territory_deactivated', [
|
||
'version' => TIGERSTYLE_SCENT_VERSION,
|
||
'timestamp' => current_time('mysql')
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* Initialize OAuth endpoints like setting up scent detection points
|
||
*/
|
||
public function init_oauth_endpoints(): void {
|
||
// Add query vars for OAuth endpoints
|
||
add_rewrite_tag('%oauth_endpoint%', '([^&]+)');
|
||
|
||
// Setup rewrite rules
|
||
$this->setup_rewrite_rules();
|
||
}
|
||
|
||
/**
|
||
* Setup rewrite rules for OAuth endpoints (scent detection points)
|
||
*/
|
||
private function setup_rewrite_rules(): void {
|
||
// OAuth2 endpoints with TigerStyle branding
|
||
add_rewrite_rule('^oauth/authorize/?$', 'index.php?oauth_endpoint=authorize', 'top');
|
||
add_rewrite_rule('^oauth/token/?$', 'index.php?oauth_endpoint=token', 'top');
|
||
add_rewrite_rule('^oauth/introspect/?$', 'index.php?oauth_endpoint=introspect', 'top');
|
||
add_rewrite_rule('^oauth/revoke/?$', 'index.php?oauth_endpoint=revoke', 'top');
|
||
|
||
// OpenID Connect discovery
|
||
add_rewrite_rule('^\.well-known/openid_configuration/?$', 'index.php?oauth_endpoint=openid_config', 'top');
|
||
add_rewrite_rule('^well-known/openid_configuration/?$', 'index.php?oauth_endpoint=openid_config', 'top');
|
||
|
||
// TigerStyle specific endpoints
|
||
add_rewrite_rule('^tigerstyle/scent-analysis/?$', 'index.php?oauth_endpoint=introspect', 'top');
|
||
add_rewrite_rule('^tigerstyle/territory-status/?$', 'index.php?oauth_endpoint=status', 'top');
|
||
}
|
||
|
||
/**
|
||
* Handle OAuth requests like processing scent detection
|
||
*/
|
||
public function handle_oauth_requests(): void {
|
||
$oauth_endpoint = get_query_var('oauth_endpoint');
|
||
|
||
if ($oauth_endpoint && $this->scent_server) {
|
||
// Log request
|
||
$this->log_scent_event('oauth_request', [
|
||
'endpoint' => $oauth_endpoint,
|
||
'method' => $_SERVER['REQUEST_METHOD'],
|
||
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown'
|
||
]);
|
||
|
||
$this->scent_server->handle_scent_request();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Authenticate user via scent detection
|
||
*/
|
||
public function authenticate_user($user_id) {
|
||
// Don't override if user is already authenticated
|
||
if ($user_id) {
|
||
return $user_id;
|
||
}
|
||
|
||
// Try each authenticator in priority order
|
||
foreach ($this->modules as $authenticator) {
|
||
if ($authenticator->can_handle_request()) {
|
||
$authenticated_user = $authenticator->authenticate();
|
||
if ($authenticated_user) {
|
||
$this->log_scent_event('user_authenticated', [
|
||
'user_id' => $authenticated_user,
|
||
'authenticator' => $authenticator->get_type(),
|
||
'ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown'
|
||
]);
|
||
return $authenticated_user;
|
||
}
|
||
}
|
||
}
|
||
|
||
return $user_id;
|
||
}
|
||
|
||
/**
|
||
* Setup REST API authentication like territorial access control
|
||
*/
|
||
public function setup_rest_authentication(): void {
|
||
// Remove WordPress cookie authentication for REST if using scent tokens
|
||
remove_filter('rest_authentication_errors', 'rest_cookie_check_errors', 100);
|
||
|
||
// Add custom authentication error handling
|
||
add_filter('rest_authentication_errors', array($this, 'rest_authentication_errors'));
|
||
}
|
||
|
||
/**
|
||
* Handle REST authentication errors with cat-themed messages
|
||
*/
|
||
public function rest_authentication_errors($result): WP_Error {
|
||
if (!empty($result)) {
|
||
return $result;
|
||
}
|
||
|
||
if (!is_user_logged_in()) {
|
||
return new WP_Error(
|
||
'tigerstyle_scent_unauthorized',
|
||
'🐯 Territory access denied. Valid scent token required.',
|
||
array('status' => 401)
|
||
);
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* Register OAuth client custom post type (scent profiles)
|
||
*/
|
||
public function register_client_post_type(): void {
|
||
register_post_type('oauth2_client', array(
|
||
'labels' => array(
|
||
'name' => '🐾 Scent Profiles',
|
||
'singular_name' => '🐾 Scent Profile',
|
||
'add_new' => 'Add New Profile',
|
||
'add_new_item' => 'Add New Scent Profile',
|
||
'edit_item' => 'Edit Scent Profile',
|
||
'new_item' => 'New Scent Profile',
|
||
'view_item' => 'View Scent Profile',
|
||
'search_items' => 'Search Scent Profiles',
|
||
'not_found' => 'No scent profiles found',
|
||
'not_found_in_trash' => 'No scent profiles found in trash'
|
||
),
|
||
'public' => false,
|
||
'show_ui' => true,
|
||
'show_in_menu' => 'tigerstyle-scent',
|
||
'capability_type' => 'post',
|
||
'supports' => array('title'),
|
||
'menu_icon' => 'dashicons-shield'
|
||
));
|
||
}
|
||
|
||
/**
|
||
* Add admin menu for TigerStyle Scent
|
||
*/
|
||
public function add_admin_menu(): void {
|
||
add_menu_page(
|
||
'TigerStyle Scent',
|
||
'🐯 TigerStyle Scent',
|
||
'manage_options',
|
||
'tigerstyle-scent',
|
||
array($this, 'admin_page'),
|
||
'dashicons-shield-alt',
|
||
30
|
||
);
|
||
|
||
add_submenu_page(
|
||
'tigerstyle-scent',
|
||
'Territory Settings',
|
||
'⚙️ Territory Settings',
|
||
'manage_options',
|
||
'tigerstyle-scent',
|
||
array($this, 'admin_page')
|
||
);
|
||
|
||
add_submenu_page(
|
||
'tigerstyle-scent',
|
||
'Scent Analysis',
|
||
'👃 Scent Analysis',
|
||
'manage_options',
|
||
'tigerstyle-scent-analysis',
|
||
array($this, 'scent_analysis_page')
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Admin page content
|
||
*/
|
||
public function admin_page(): void {
|
||
?>
|
||
<div class="wrap">
|
||
<h1>🐯 TigerStyle Scent - Territory Control</h1>
|
||
<p>Welcome to your OAuth2 authentication territory! Manage your digital scent trails and access control.</p>
|
||
|
||
<div class="tigerstyle-dashboard">
|
||
<div class="tigerstyle-card">
|
||
<h2>🏰 Territory Status</h2>
|
||
<p><strong>Plugin Version:</strong> <?php echo TIGERSTYLE_SCENT_VERSION; ?></p>
|
||
<p><strong>Scent Detection:</strong> <?php echo $this->settings['enable_scent_authentication'] ? '✅ Active' : '❌ Inactive'; ?></p>
|
||
<p><strong>Territory Security:</strong> <?php echo $this->settings['scent_strength']; ?></p>
|
||
</div>
|
||
|
||
<div class="tigerstyle-card">
|
||
<h2>🐾 Quick Actions</h2>
|
||
<p><a href="<?php echo admin_url('post-new.php?post_type=oauth2_client'); ?>" class="button button-primary">➕ Add New Scent Profile</a></p>
|
||
<p><a href="<?php echo admin_url('admin.php?page=tigerstyle-scent-analysis'); ?>" class="button">👃 Analyze Scent Trails</a></p>
|
||
<p><button id="test-scent-auth" class="button">🧪 Test Scent Recognition</button></p>
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
.tigerstyle-dashboard { display: flex; gap: 20px; margin-top: 20px; }
|
||
.tigerstyle-card { background: white; padding: 20px; border: 1px solid #ccd0d4; border-radius: 8px; flex: 1; }
|
||
.tigerstyle-card h2 { margin-top: 0; color: #ff6b35; }
|
||
</style>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
/**
|
||
* Scent analysis page
|
||
*/
|
||
public function scent_analysis_page(): void {
|
||
?>
|
||
<div class="wrap">
|
||
<h1>👃 Scent Analysis - Territory Monitoring</h1>
|
||
<p>Monitor and analyze scent token activity in your territory.</p>
|
||
|
||
<div class="tigerstyle-analysis">
|
||
<h2>Recent Scent Activity</h2>
|
||
<p><em>Scent trail monitoring coming soon...</em></p>
|
||
</div>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
/**
|
||
* Enqueue admin assets
|
||
*/
|
||
public function enqueue_admin_assets($hook): void {
|
||
if (strpos($hook, 'tigerstyle-scent') !== false) {
|
||
wp_enqueue_script(
|
||
'tigerstyle-scent-admin',
|
||
TIGERSTYLE_SCENT_PLUGIN_URL . 'admin/js/admin.js',
|
||
array('jquery'),
|
||
TIGERSTYLE_SCENT_VERSION,
|
||
true
|
||
);
|
||
|
||
wp_localize_script('tigerstyle-scent-admin', 'tigerStyleScent', array(
|
||
'ajaxUrl' => admin_url('admin-ajax.php'),
|
||
'nonce' => wp_create_nonce('tigerstyle_scent_admin')
|
||
));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* AJAX test authentication
|
||
*/
|
||
public function ajax_test_authentication(): void {
|
||
check_ajax_referer('tigerstyle_scent_admin', 'nonce');
|
||
|
||
wp_send_json_success(array(
|
||
'message' => '🐯 Scent recognition system is operational!',
|
||
'territory' => 'secure',
|
||
'timestamp' => current_time('mysql')
|
||
));
|
||
}
|
||
|
||
/**
|
||
* Create database tables for scent storage
|
||
*/
|
||
private function create_scent_tables(): void {
|
||
global $wpdb;
|
||
|
||
$charset_collate = $wpdb->get_charset_collate();
|
||
|
||
// Access tokens (scent tokens)
|
||
$sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}oauth_access_tokens (
|
||
access_token varchar(255) NOT NULL,
|
||
client_id varchar(255) NOT NULL,
|
||
user_id int(11) NOT NULL,
|
||
expires datetime NOT NULL,
|
||
scope text,
|
||
PRIMARY KEY (access_token),
|
||
KEY client_id (client_id),
|
||
KEY user_id (user_id)
|
||
) $charset_collate;";
|
||
|
||
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
||
dbDelta($sql);
|
||
|
||
// Refresh tokens (scent memory)
|
||
$sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}oauth_refresh_tokens (
|
||
refresh_token varchar(255) NOT NULL,
|
||
client_id varchar(255) NOT NULL,
|
||
user_id int(11) NOT NULL,
|
||
expires datetime NOT NULL,
|
||
scope text,
|
||
PRIMARY KEY (refresh_token),
|
||
KEY client_id (client_id),
|
||
KEY user_id (user_id)
|
||
) $charset_collate;";
|
||
|
||
dbDelta($sql);
|
||
|
||
// Authorization codes (territory codes)
|
||
$sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}oauth_authorization_codes (
|
||
authorization_code varchar(255) NOT NULL,
|
||
client_id varchar(255) NOT NULL,
|
||
user_id int(11) NOT NULL,
|
||
redirect_uri text NOT NULL,
|
||
expires datetime NOT NULL,
|
||
scope text,
|
||
code_challenge varchar(255),
|
||
code_challenge_method varchar(10),
|
||
PRIMARY KEY (authorization_code),
|
||
KEY client_id (client_id),
|
||
KEY user_id (user_id)
|
||
) $charset_collate;";
|
||
|
||
dbDelta($sql);
|
||
}
|
||
|
||
/**
|
||
* Log scent events for debugging and monitoring
|
||
*/
|
||
private function log_scent_event(string $event, array $data = []): void {
|
||
if (TIGERSTYLE_SCENT_DEBUG) {
|
||
error_log(sprintf(
|
||
'[TigerStyle Scent] %s: %s',
|
||
$event,
|
||
json_encode($data)
|
||
));
|
||
}
|
||
|
||
// Fire action for external logging systems
|
||
do_action('tigerstyle_scent_event', $event, $data);
|
||
}
|
||
|
||
/**
|
||
* Get plugin settings
|
||
*/
|
||
public function get_settings(): array {
|
||
return $this->settings;
|
||
}
|
||
|
||
/**
|
||
* Get scent server instance
|
||
*/
|
||
public function get_scent_server(): ?TigerStyleScent_ScentServer {
|
||
return $this->scent_server;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Helper function to get main plugin instance
|
||
* Like calling an alpha cat
|
||
*/
|
||
function tigerstyle_scent(): TigerStyleScent {
|
||
return TigerStyleScent::instance();
|
||
}
|
||
|
||
// Initialize the TigerStyle Scent territory
|
||
tigerstyle_scent();
|