- <?php
- /**
- * Validates string for suitability as a Perforce key name.
- *
- * By default disallows:
- * - whitespace
- * - purely numeric names
- * - revision characters ('#', '@')
- * - wildcards ('*', '...')
- * - slashes ('/')
- * - non-printable characters
- * - leading minus ('-')
- *
- * By default allows, but can block:
- * - percent character ('%')
- * - positional specifiers ('%%x')
- *
- * @copyright 2011 Perforce Software. All rights reserved.
- * @license Please see LICENSE.txt in top-level folder of this distribution.
- * @version <release>/<patch>
- */
-
- namespace P4\Validate;
-
- class KeyName extends AbstractValidate
- {
- const INVALID_TYPE = 'invalidType';
- const IS_EMPTY = 'isEmpty';
- const IS_NUMERIC = 'isNumeric';
- const HAS_WHITESPACE = 'hasSpaces';
- const REVISION_CHARACTERS = 'revision';
- const WILDCARDS = 'wildcards';
- const LEADING_MINUS = 'leadingMinus';
- const UNPRINTABLE_CHARACTERS = 'unprintable';
- const SLASHES = 'slashes';
- const COMMAS = 'commas';
- const PERCENT = 'percent';
- const POSITIONAL_SPECIFIERS = 'positional';
- const RELATIVE = 'relative';
-
- protected $allowLeadingDash = false; // DASHNUM
- protected $allowPurelyNumeric = false; // NNEGNUM
- protected $allowRevSpec = false; // REV
- protected $allowSlashes = false; // SLASH
- protected $allowRelative = true; // REL
- protected $allowWildcard = false; // WILD
- protected $allowPercent = true; // !NOTAPERCENT
- protected $allowPositional = true; // !NOPERCENT
- protected $allowCommas = true; // !NOCOMMA
- protected $messageTemplates = array(
- self::INVALID_TYPE => "Invalid type given.",
- self::IS_EMPTY => "Is an empty string.",
- self::IS_NUMERIC => "Purely numeric values are not allowed.",
- self::HAS_WHITESPACE => "Whitespace is not permitted.",
- self::REVISION_CHARACTERS => "Revision characters ('#', '@') are not permitted.",
- self::WILDCARDS => "Wildcards ('*', '...') are not permitted.",
- self::LEADING_MINUS => "First character cannot be minus ('-').",
- self::UNPRINTABLE_CHARACTERS => "Unprintable characters are not permitted.",
- self::SLASHES => "Slashes ('/') are not permitted.",
- self::COMMAS => "Commas (',') are not permitted.",
- self::PERCENT => "Percent ('%') is not permitted.",
- self::POSITIONAL_SPECIFIERS => "Positional specifiers ('%%x') are not permitted.",
- self::RELATIVE => "Relative paths are not permitted."
- );
-
- /**
- * Checks if the given string is a valid perforce spec name.
- *
- * @param string|int $value spec name value to validate.
- * @return boolean true if value is a valid spec name, false otherwise.
- */
- public function isValid($value)
- {
- $this->set($value);
-
- // permit ints if allowPurelyNumeric is true.
- if ($this->allowPurelyNumeric && is_int($value)) {
- $value = (string) $value;
- }
-
- // test for valid type.
- if (!is_string($value)) {
- $this->error(static::INVALID_TYPE);
- return false;
- }
-
- // test for empty value.
- if ($value === '') {
- $this->error(static::IS_EMPTY);
- return false;
- }
-
- // test for leading minus ('-') character.
- if (!$this->allowLeadingDash && $value[0] === "-") {
- $this->error(static::LEADING_MINUS);
- return false;
- }
-
- // test for purely numeric name.
- if (!$this->allowPurelyNumeric && preg_match('/^[0-9]+$/', $value)) {
- $this->error(static::IS_NUMERIC);
- return false;
- }
-
- // test for unprintable characters.
- // 'isprint' defines printing characters an ASCII code greater than 0x1f, except 0x7f (DEL).
- // technically, that would mean 0x80+ is invalid but the server explicitly lets high-bitted values pass.
- if (preg_match('/[\x00-\x1F\x7f]/', $value)) {
- $this->error(static::UNPRINTABLE_CHARACTERS);
- return false;
- }
-
- // test for whitespace.
- if (preg_match('/\s/', $value)) {
- $this->error(static::HAS_WHITESPACE);
- return false;
- }
-
- // test for revision characters.
- if (!$this->allowRevSpec && preg_match('/@|#/', $value)) {
- $this->error(static::REVISION_CHARACTERS);
- return false;
- }
-
- // test for forward slash character.
- if (!$this->allowSlashes && strpos($value, '/') !== false) {
- $this->error(static::SLASHES);
- return false;
- }
-
- // If relative paths aren't allowed the following are blocked:
- // two or more slashes after the first character
- // containing '/./'
- // containing '/../'
- // ending in a slash (in 2+ character string)
- // ending in '/.'
- // ending in '/..'
- if (!$this->allowRelative && preg_match('#.+/$|.+//|/\./|/\.\./|.+/$|/\.$|/\.\.$#', $value)) {
- $this->error(static::RELATIVE);
- return false;
- }
-
- // test for wildcard characters.
- if (!$this->allowWildcard && preg_match('/\*|\.\.\./', $value)) {
- $this->error(static::WILDCARDS);
- return false;
- }
-
- // test for percent character
- if (!$this->allowPercent && strpos($value, '%') !== false) {
- $this->error(static::PERCENT);
- return false;
- }
-
- // test for positional specifiers.
- if (!$this->allowPositional && strpos($value, '%%') !== false) {
- $this->error(static::POSITIONAL_SPECIFIERS);
- return false;
- }
-
- // test for comma character
- if (!$this->allowCommas && strpos($value, ',') !== false) {
- $this->error(static::COMMAS);
- return false;
- }
-
- return true;
- }
-
- /**
- * Control if a leading - character is permitted.
- * Alias DASHNUM.
- *
- * @param bool $allowed pass true to allow leading dash, false (default) to disallow.
- */
- public function allowLeadingDash($allowed)
- {
- $this->allowLeadingDash = (bool) $allowed;
- }
-
- /**
- * Control if purely numeric key names are permitted
- * (values consisting of only characters 0-9).
- * Alias NNEGNUM.
- *
- * @param bool $allowed pass true to allow purely numeric names, false (default) to disallow.
- */
- public function allowPurelyNumeric($allowed)
- {
- $this->allowPurelyNumeric = (bool) $allowed;
- }
-
- /**
- * Control if revision specifiers are permitted (@ and # characters).
- * Alias REV.
- *
- * @param bool $allowed pass true to allow rev specifiers, false (default) to disallow.
- */
- public function allowRevSpec($allowed)
- {
- $this->allowRevSpec = (bool) $allowed;
- }
-
- /**
- * Control if forward slashes '/' are permitted.
- * Alias SLASH.
- *
- * @param bool $allowed pass true to allow forward slashes, false (default) to disallow.
- */
- public function allowSlashes($allowed)
- {
- $this->allowSlashes = (bool) $allowed;
- }
-
- /**
- * Control if forward relative paths are permitted (//, /., /./, /../, /.., trailing /)
- * Alias REL.
- *
- * @param bool $allowed pass true (default) to allow relative, false to disallow.
- */
- public function allowRelative($allowed)
- {
- $this->allowRelative = (bool) $allowed;
- }
-
- /**
- * Control if wildcard sequences (* or ...) are permitted
- * Alias WILD.
- *
- * @param bool $allowed pass true to allow positional specifiers, false (default) to disallow.
- */
- public function allowWildcard($allowed)
- {
- $this->allowWildcard = (bool) $allowed;
- }
-
- /**
- * Control if percent character '%' is permitted
- * Alias !NOTAPERCENT.
- *
- * @param bool $allowed pass true (default) to allow percent '%', false to disallow.
- */
- public function allowPercent($allowed)
- {
- $this->allowPercent = (bool) $allowed;
- }
-
- /**
- * Control if positional sequence '%%' is permitted
- * Alias !NOPERCENT.
- *
- * @param bool $allowed pass true (default) to allow percent '%%', false to disallow.
- */
- public function allowPositional($allowed)
- {
- $this->allowPositional = (bool) $allowed;
- }
-
- /**
- * Control if comma character ',' is permitted
- * Alias !NOCOMMA.
- *
- * @param bool $allowed pass true (default) to allow commas ',', false to disallow.
- */
- public function allowCommas($allowed)
- {
- $this->allowCommas = (bool) $allowed;
- }
- }