helpers.php
Helper functions for CreaCaptcha.
Table of Contents
Constants
- CREATIONELL_CAPTCHA_LOCALE_MAP = [ // Deutsch 'de_DE' => 'de', 'de_DE_formal' => 'de', 'de_AT' => 'de', 'de_CH' => 'de', 'de_CH_informal' => 'de', // Englisch 'en_US' => 'en', 'en_GB' => 'en', 'en_AU' => 'en', 'en_CA' => 'en', 'en_NZ' => 'en', 'en_ZA' => 'en', // Französisch 'fr_FR' => 'fr-fr', 'fr_BE' => 'fr-fr', 'fr_LU' => 'fr-fr', 'fr_CH' => 'fr-fr', 'fr_CA' => 'fr-ca', // Spanisch (Europa) 'es_ES' => 'es-es', // Spanisch (LatAm — alle nach es-419) 'es_AR' => 'es-419', 'es_CL' => 'es-419', 'es_CO' => 'es-419', 'es_CR' => 'es-419', 'es_DO' => 'es-419', 'es_EC' => 'es-419', 'es_GT' => 'es-419', 'es_HN' => 'es-419', 'es_MX' => 'es-419', 'es_PA' => 'es-419', 'es_PE' => 'es-419', 'es_PR' => 'es-419', 'es_UY' => 'es-419', 'es_VE' => 'es-419', // Portugiesisch 'pt_PT' => 'pt-pt', 'pt_AO' => 'pt-pt', 'pt_BR' => 'pt-br', // Italienisch / Niederländisch / Polnisch 'it_IT' => 'it', 'nl_NL' => 'nl', 'nl_BE' => 'nl', 'pl_PL' => 'pl', // Tschechisch / Slowakisch 'cs_CZ' => 'cs', 'sk_SK' => 'sk', // Nordisch 'da_DK' => 'da', 'sv_SE' => 'sv', 'fi' => 'fi', 'nb_NO' => 'nb', 'nn_NO' => 'nb', // Sonstige EU 'hu_HU' => 'hu', 'ro_RO' => 'ro', 'el' => 'el', ]
- Maps WordPress locales to the matching ALTCHA i18n locale bundle.
Functions
- creationell_captcha_resolve_widget_locale() : string|null
- Resolves the active WordPress locale to a vendored ALTCHA locale code.
- creationell_captcha_get_default_settings() : array<string, mixed>
- Default plugin settings.
- creationell_captcha_get_settings() : array<string, mixed>
- Current plugin settings, merged over the defaults.
- creationell_captcha_invalidate_settings_cache() : void
- Drops the in-request settings cache. Wired to the option-change hooks below so callers that read settings after an update see the fresh value.
- creationell_captcha_is_disabled() : bool
- Whether the captcha is globally disabled via the wp-config constant.
- creationell_captcha_sodium_available() : bool
- Whether ext-sodium (required for Argon2id) is available.
- creationell_captcha_generate_secrets() : array{signature: string, key_signature: string}
- Generates both HMAC secrets and persists them (non-autoloaded).
- creationell_captcha_get_secret() : string
- Returns a stored HMAC secret, generating + persisting it on first use.
- creationell_captcha_get_hmac_secret() : string
- The HMAC signature secret (signs each challenge).
- creationell_captcha_get_hmac_key_secret() : string
- The HMAC key-signature secret (enables the fast verification path).
- creationell_captcha_engine() : Engine
- Shared captcha engine instance.
- creationell_captcha_log() : void
- Write a message to the debug log when CREATIONELL_CAPTCHA_DEBUG is active.
- creationell_captcha_get_client_ip() : string
- Resolves the client IP address.
- creationell_captcha_ip_in_list() : bool
- Whether an IP matches any entry in a list of IPs or CIDR ranges.
- creationell_captcha_ip_in_cidr() : bool
- Whether an IP falls within a CIDR range. Supports IPv4 and IPv6.
- creationell_captcha_is_valid_ip_or_cidr() : bool
- Whether a string is a valid IP address or CIDR range (IPv4 or IPv6).
- creationell_captcha_wildcard_match() : bool
- Whether a subject matches any of the given wildcard patterns (case-insensitive).
- creationell_captcha_private_ranges() : array<string|int, string>
- Returns the canonical list of private/loopback CIDR ranges used when the `firewall_trust_private_ranges` toggle is active.
- creationell_captcha_trusted_proxies_constant() : array<string|int, string>
- Reads the optional `CREATIONELL_CAPTCHA_TRUSTED_PROXIES` wp-config constant as a list. Accepts either a string array or a comma/whitespace-separated scalar; invalid entries are dropped.
- creationell_captcha_is_trusted_proxy() : bool
- Whether the given IP belongs to a trusted upstream proxy.
- creationell_captcha_evaluate_bypass() : array{reason: string, source: string}|false
- Pure bypass evaluator — checks the three bypass sources against the supplied inputs without touching $_SERVER, $_COOKIE or any static cache. The caller is responsible for providing the values.
- creationell_captcha_request_bypassed() : array{reason: string, source: string}|false
- Whether the current request is allowed to bypass captcha, under-attack and firewall protections. Reads $_SERVER, $_COOKIE and the request's client IP, then delegates to `creationell_captcha_evaluate_bypass()`.
- creationell_captcha_validate_action_pattern() : string|null
- Validates a single interceptor-action pattern.
- creationell_captcha_validate_cookie_entry() : string|null
- Validates a single bypass-cookie entry of the form `name=value`.
- creationell_captcha_anonymize_ip() : string
- Truncates an IP for DSGVO-compliant storage. IPv4 → last octet zeroed, IPv6 → last 80 bits zeroed. Invalid IPs return ''.
- creationell_captcha_request_body_fingerprint() : string
- Returns a JSON-encoded fingerprint of $_POST: { field-name: value-byte-length }.
- creationell_captcha_block_response() : void
- Sends a fail-closed block response and terminates the request.
- creationell_captcha_base64url_encode() : string
- Base64URL encoder (RFC 4648 §5) — strips standard-base64 padding and replaces +/ with -_ so the value is URL-safe.
- creationell_captcha_base64url_decode() : string
- Base64URL decoder — accepts unpadded URL-safe input and returns the raw bytes. Returns the empty string on malformed input (no exceptions).
- creationell_captcha_ratelimit_current_count() : int
- Reads the current rate-limit counter for an IP without incrementing it.
Constants
CREATIONELL_CAPTCHA_LOCALE_MAP
Maps WordPress locales to the matching ALTCHA i18n locale bundle.
public
mixed
CREATIONELL_CAPTCHA_LOCALE_MAP
= [
// Deutsch
'de_DE' => 'de',
'de_DE_formal' => 'de',
'de_AT' => 'de',
'de_CH' => 'de',
'de_CH_informal' => 'de',
// Englisch
'en_US' => 'en',
'en_GB' => 'en',
'en_AU' => 'en',
'en_CA' => 'en',
'en_NZ' => 'en',
'en_ZA' => 'en',
// Französisch
'fr_FR' => 'fr-fr',
'fr_BE' => 'fr-fr',
'fr_LU' => 'fr-fr',
'fr_CH' => 'fr-fr',
'fr_CA' => 'fr-ca',
// Spanisch (Europa)
'es_ES' => 'es-es',
// Spanisch (LatAm — alle nach es-419)
'es_AR' => 'es-419',
'es_CL' => 'es-419',
'es_CO' => 'es-419',
'es_CR' => 'es-419',
'es_DO' => 'es-419',
'es_EC' => 'es-419',
'es_GT' => 'es-419',
'es_HN' => 'es-419',
'es_MX' => 'es-419',
'es_PA' => 'es-419',
'es_PE' => 'es-419',
'es_PR' => 'es-419',
'es_UY' => 'es-419',
'es_VE' => 'es-419',
// Portugiesisch
'pt_PT' => 'pt-pt',
'pt_AO' => 'pt-pt',
'pt_BR' => 'pt-br',
// Italienisch / Niederländisch / Polnisch
'it_IT' => 'it',
'nl_NL' => 'nl',
'nl_BE' => 'nl',
'pl_PL' => 'pl',
// Tschechisch / Slowakisch
'cs_CZ' => 'cs',
'sk_SK' => 'sk',
// Nordisch
'da_DK' => 'da',
'sv_SE' => 'sv',
'fi' => 'fi',
'nb_NO' => 'nb',
'nn_NO' => 'nb',
// Sonstige EU
'hu_HU' => 'hu',
'ro_RO' => 'ro',
'el' => 'el',
]
Keys are values returned by get_locale() — including the formal /
informal variants WP exposes (de_DE_formal, de_CH_informal). Values
are the exact locale codes used by the vendored ALTCHA bundles under
assets/js/altcha-i18n/<code>.js. Locales not in the map fall through
to the widget's own auto-detection (which itself falls back to English
since only the bundles enqueued by this plugin are registered).
Extend via the creationell_captcha_widget_locale_map filter rather
than patching this constant.
Functions
creationell_captcha_resolve_widget_locale()
Resolves the active WordPress locale to a vendored ALTCHA locale code.
creationell_captcha_resolve_widget_locale() : string|null
Returns the locale string (e.g. "de", "fr-fr", "pt-br") if a mapping exists, or null when the WP locale is not in the vendor set — in which case the widget renderer skips both the language attribute and the i18n script enqueue, letting the widget fall through to its own detection (which has only the EN built-in available).
Two filters are applied: creationell_captcha_widget_locale_map to
extend / override the lookup table, and
creationell_captcha_widget_locale for last-mile overrides after
lookup.
Tags
Return values
string|null —Vendored ALTCHA locale code or null.
creationell_captcha_get_default_settings()
Default plugin settings.
creationell_captcha_get_default_settings() : array<string, mixed>
Return values
array<string, mixed>creationell_captcha_get_settings()
Current plugin settings, merged over the defaults.
creationell_captcha_get_settings([bool $force_refresh = false ]) : array<string, mixed>
Memoised for the duration of the request — get_option() itself is cheap thanks to WP's object cache, but the defaults-merge over ~70 keys adds up across the 10+ call sites per request (Interceptor, Firewall, Rate- Limiter, Under-Attack, every form integration). The cache is invalidated automatically when the option is added, updated or deleted.
Parameters
- $force_refresh : bool = false
-
Re-read from the DB even if a cached copy exists. Used by the invalidation hook.
Return values
array<string, mixed>creationell_captcha_invalidate_settings_cache()
Drops the in-request settings cache. Wired to the option-change hooks below so callers that read settings after an update see the fresh value.
creationell_captcha_invalidate_settings_cache() : void
creationell_captcha_is_disabled()
Whether the captcha is globally disabled via the wp-config constant.
creationell_captcha_is_disabled() : bool
Return values
boolcreationell_captcha_sodium_available()
Whether ext-sodium (required for Argon2id) is available.
creationell_captcha_sodium_available() : bool
Return values
boolcreationell_captcha_generate_secrets()
Generates both HMAC secrets and persists them (non-autoloaded).
creationell_captcha_generate_secrets() : array{signature: string, key_signature: string}
Return values
array{signature: string, key_signature: string}creationell_captcha_get_secret()
Returns a stored HMAC secret, generating + persisting it on first use.
creationell_captcha_get_secret(string $which) : string
Parameters
- $which : string
-
Either 'signature' or 'key_signature'.
Return values
stringcreationell_captcha_get_hmac_secret()
The HMAC signature secret (signs each challenge).
creationell_captcha_get_hmac_secret() : string
A wp-config constant takes precedence over the stored option.
Return values
stringcreationell_captcha_get_hmac_key_secret()
The HMAC key-signature secret (enables the fast verification path).
creationell_captcha_get_hmac_key_secret() : string
A wp-config constant takes precedence over the stored option.
Return values
stringcreationell_captcha_engine()
Shared captcha engine instance.
creationell_captcha_engine() : Engine
Return values
Enginecreationell_captcha_log()
Write a message to the debug log when CREATIONELL_CAPTCHA_DEBUG is active.
creationell_captcha_log(string $message) : void
Parameters
- $message : string
-
Message to log.
creationell_captcha_get_client_ip()
Resolves the client IP address.
creationell_captcha_get_client_ip() : string
Returns the validated REMOTE_ADDR by default. When the firewall_behind_proxy
setting is on, the configured forwarded header is used instead — falling back
to REMOTE_ADDR if it yields no valid IP.
Return values
stringcreationell_captcha_ip_in_list()
Whether an IP matches any entry in a list of IPs or CIDR ranges.
creationell_captcha_ip_in_list(string $ip, mixed $list) : bool
Parameters
- $ip : string
-
The client IP.
- $list : mixed
-
A list of IPs / CIDR ranges (non-arrays are ignored).
Return values
boolcreationell_captcha_ip_in_cidr()
Whether an IP falls within a CIDR range. Supports IPv4 and IPv6.
creationell_captcha_ip_in_cidr(string $ip, string $cidr) : bool
Parameters
- $ip : string
-
The client IP.
- $cidr : string
-
A CIDR range, e.g. "203.0.113.0/24".
Return values
boolcreationell_captcha_is_valid_ip_or_cidr()
Whether a string is a valid IP address or CIDR range (IPv4 or IPv6).
creationell_captcha_is_valid_ip_or_cidr(string $entry) : bool
Parameters
- $entry : string
-
The candidate string.
Return values
boolcreationell_captcha_wildcard_match()
Whether a subject matches any of the given wildcard patterns (case-insensitive).
creationell_captcha_wildcard_match(string $subject, mixed $patterns) : bool
The pattern alphabet is the same as the firewall UA-blocklist: * is the
single wildcard, everything else is matched literally.
Parameters
- $subject : string
-
The string to test.
- $patterns : mixed
-
A list of patterns; non-arrays return false.
Return values
boolcreationell_captcha_private_ranges()
Returns the canonical list of private/loopback CIDR ranges used when the `firewall_trust_private_ranges` toggle is active.
creationell_captcha_private_ranges() : array<string|int, string>
Return values
array<string|int, string>creationell_captcha_trusted_proxies_constant()
Reads the optional `CREATIONELL_CAPTCHA_TRUSTED_PROXIES` wp-config constant as a list. Accepts either a string array or a comma/whitespace-separated scalar; invalid entries are dropped.
creationell_captcha_trusted_proxies_constant() : array<string|int, string>
Return values
array<string|int, string>creationell_captcha_is_trusted_proxy()
Whether the given IP belongs to a trusted upstream proxy.
creationell_captcha_is_trusted_proxy(string $ip) : bool
Sources are checked in this order; the first match wins:
- firewall_trusted_proxies (the explicit textarea list)
- CREATIONELL_CAPTCHA_TRUSTED_PROXIES (wp-config constant)
- firewall_trust_private_ranges (when on): the private/loopback ranges
- firewall_trust_cloudflare (when on): the cached/bundled CF ranges
Parameters
- $ip : string
-
A validated client IP address.
Return values
boolcreationell_captcha_evaluate_bypass()
Pure bypass evaluator — checks the three bypass sources against the supplied inputs without touching $_SERVER, $_COOKIE or any static cache. The caller is responsible for providing the values.
creationell_captcha_evaluate_bypass(string|null $ip, string|null $ua, array<string, string> $cookies) : array{reason: string, source: string}|false
Sources are checked in this order; the first match wins:
- firewall_ip_allow vs $ip
- bypass_ua_allow vs $ua
- bypass_cookies vs $cookies (strict name=value)
Parameters
- $ip : string|null
-
Client IP, or null to skip the IP check.
- $ua : string|null
-
User-Agent, or null to skip the UA check.
- $cookies : array<string, string>
-
Cookie map (name => value).
Return values
array{reason: string, source: string}|falsecreationell_captcha_request_bypassed()
Whether the current request is allowed to bypass captcha, under-attack and firewall protections. Reads $_SERVER, $_COOKIE and the request's client IP, then delegates to `creationell_captcha_evaluate_bypass()`.
creationell_captcha_request_bypassed() : array{reason: string, source: string}|false
Result is memoised for the request — settings, IP and cookies do not change
within a single PHP request. Only reason flows into the event-log context;
source is exposed for diagnostic logging by callers.
Return values
array{reason: string, source: string}|falsecreationell_captcha_validate_action_pattern()
Validates a single interceptor-action pattern.
creationell_captcha_validate_action_pattern(string $entry) : string|null
Allowed: lowercase/uppercase letters, digits, _, -, * (wildcard),
with an optional leading ! for exclusion patterns. Empty input or
patterns of only ! are rejected.
Parameters
- $entry : string
-
Raw entry (already trimmed by the caller).
Return values
string|null —Normalised entry, or null if invalid.
creationell_captcha_validate_cookie_entry()
Validates a single bypass-cookie entry of the form `name=value`.
creationell_captcha_validate_cookie_entry(string $entry) : string|null
Name must be alphanumeric, _ or -. Value may be empty and is
length-capped to 200 bytes. The returned entry has the value passed
through sanitize_text_field().
Parameters
- $entry : string
-
Raw entry (already trimmed by the caller).
Return values
string|null —Normalised name=value entry, or null if invalid.
creationell_captcha_anonymize_ip()
Truncates an IP for DSGVO-compliant storage. IPv4 → last octet zeroed, IPv6 → last 80 bits zeroed. Invalid IPs return ''.
creationell_captcha_anonymize_ip(string $ip) : string
Parameters
- $ip : string
-
A validated client IP address.
Return values
stringcreationell_captcha_request_body_fingerprint()
Returns a JSON-encoded fingerprint of $_POST: { field-name: value-byte-length }.
creationell_captcha_request_body_fingerprint() : string
No values are recorded — only structural metadata for attack-pattern
diagnosis. Field names that contain known sensitive substrings (password,
iban, api_key, …) are replaced with [masked:<8-char-sha256>] so the
fingerprint does not leak custom-form schema (e.g. bank_iban_input).
Output is length-capped to 2048 bytes; if longer, the JSON is collapsed
to "}" rather than truncated mid-entry.
Return values
stringcreationell_captcha_block_response()
Sends a fail-closed block response and terminates the request.
creationell_captcha_block_response(int $status, string $message[, int $retry_after = 0 ]) : void
Parameters
- $status : int
-
HTTP status code (403 firewall, 429 rate limit).
- $message : string
-
The message shown to the client.
- $retry_after : int = 0
-
Optional Retry-After value in seconds.
creationell_captcha_base64url_encode()
Base64URL encoder (RFC 4648 §5) — strips standard-base64 padding and replaces +/ with -_ so the value is URL-safe.
creationell_captcha_base64url_encode(string $bytes) : string
Parameters
- $bytes : string
-
Raw bytes to encode.
Return values
stringcreationell_captcha_base64url_decode()
Base64URL decoder — accepts unpadded URL-safe input and returns the raw bytes. Returns the empty string on malformed input (no exceptions).
creationell_captcha_base64url_decode(string $encoded) : string
Parameters
- $encoded : string
-
URL-safe base64 string.
Return values
stringcreationell_captcha_ratelimit_current_count()
Reads the current rate-limit counter for an IP without incrementing it.
creationell_captcha_ratelimit_current_count(string $ip) : int
Uses the same bucket key as Creationell\Captcha\RateLimiter::run() so the
value matches what the run-loop would see. Returns 0 if no transient exists
for the current window.
Parameters
- $ip : string
-
Client IP (call
creationell_captcha_get_client_ip()).