$field Normalized provider field. * @return array Either allowed=true and a Field, or allowed=false and reason. */ public function evaluate( array $field ) { $name = isset( $field['name'] ) ? (string) $field['name'] : ''; $type = isset( $field['type'] ) ? (string) $field['type'] : ''; if ( '' === $name || ! preg_match( '/^[A-Za-z][A-Za-z0-9_-]*$/', $name ) ) { return $this->blocked( $name, $type, 'Field name is missing or not a simple user-control name.' ); } if ( $this->is_sensitive_name( $name ) ) { return $this->blocked( $name, $type, 'Sensitive field names are never exposed.' ); } if ( ! in_array( $type, $this->supported_types, true ) ) { return $this->blocked( $name, $type, 'Control type is unsupported or provider-internal.' ); } $options = isset( $field['options'] ) && is_array( $field['options'] ) ? $field['options'] : array(); if ( in_array( $type, array( 'select', 'radio' ), true ) && empty( $options ) ) { return $this->blocked( $name, $type, 'Choice controls must declare at least one option.' ); } return array( 'allowed' => true, 'field' => new Field( $name, $type, isset( $field['label'] ) ? (string) $field['label'] : $name, ! empty( $field['required'] ), array_map( 'strval', $options ), isset( $field['provider_type'] ) ? (string) $field['provider_type'] : $type ), ); } /** * Perform the documented operation. * * @param string $name Field name. * @param string $type Field type. * @param string $reason Block reason. * @return array */ private function blocked( $name, $type, $reason ) { return array( 'allowed' => false, 'blocked' => array( 'name' => (string) $name, 'provider_type' => (string) $type, 'reason' => (string) $reason, ), ); } /** * Match names that commonly carry credentials, anti-spam material, or * security/payment data. Matching is intentionally conservative. * * @param string $name Field name. * @return bool */ private function is_sensitive_name( $name ) { $normalized = strtolower( str_replace( array( '-', '_' ), '', $name ) ); $tokens = array( 'password', 'passwd', 'passcode', 'secret', 'token', 'nonce', 'csrf', 'captcha', 'recaptcha', 'turnstile', 'honeypot', 'antispam', 'spam', 'otp', 'verification', 'credential', 'apikey', 'privatekey', 'auth', 'cvv', 'cvc', 'cardnumber', 'creditcard', 'ssn', 'socialsecurity', 'upload', 'file', 'wpcf7', ); foreach ( $tokens as $token ) { if ( false !== strpos( $normalized, $token ) ) { return true; } } return false; } }