If a value is specified, the next token of the specified type(s)
containing the specified value will be returned.
Returns false if no token can be found.
public findNext ( integer | array $types, integer $start, integer $end = null, boolean $exclude = false, string $value = null, boolean $local = false ) : integer | boolean | ||
$types | integer | array | The type(s) of tokens to search for. |
$start | integer | The position to start searching from in the token stack. |
$end | integer | The end position to fail if no token is found. if not specified or null, end will default to the end of the token stack. |
$exclude | boolean | If true, find the next token that is NOT of a type specified in $types. |
$value | string | The value that the token(s) must be equal to. If value is omitted, tokens with any value will be returned. |
$local | boolean | If true, tokens outside the current statement will not be checked. i.e., checking will stop at the next semi-colon found. |
return | integer | boolean |
/** * Processes the tokens that this sniff is interested in. * * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param int $stackPtr The position in the stack where * the token was found. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $utils = Security_Sniffs_UtilsFactory::getInstance(); $tokens = $phpcsFile->getTokens(); if ($tokens[$stackPtr]['content'] == "'#value'" || $tokens[$stackPtr]['content'] == '"#value"') { $closer = $phpcsFile->findNext(T_SEMICOLON, $stackPtr); $next = $phpcsFile->findNext(array_merge(PHP_CodeSniffer_Tokens::$bracketTokens, PHP_CodeSniffer_Tokens::$emptyTokens, PHP_CodeSniffer_Tokens::$assignmentTokens), $stackPtr + 1, $closer + 1, true); if ($next == $closer && $tokens[$next]['code'] == T_SEMICOLON) { // Case of $label = $element['#value']; $next = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$assignmentTokens, $next); $next = $phpcsFile->findPrevious(T_VARIABLE, $next); $phpcsFile->addWarning('Potential XSS found with #value on ' . $tokens[$next]['content'], $next, 'D7XSSWarFormValue'); } elseif ($next && $utils::is_token_user_input($tokens[$next])) { $phpcsFile->addError('XSS found with #value on ' . $tokens[$next]['content'], $next, 'D7XSSErrFormValue'); } elseif ($next && PHP_CodeSniffer::getConfigData('ParanoiaMode')) { if (in_array($tokens[$next]['content'], $utils::getXSSMitigationFunctions())) { $n = $phpcsFile->findNext($utils::getVariableTokens(), $next + 1, $closer); if ($n) { $phpcsFile->addWarning('Potential XSS found with #value on ' . $tokens[$n]['content'], $n, 'D7XSSWarFormValue'); } } else { $phpcsFile->addWarning('Potential XSS found with #value on ' . $tokens[$next]['content'], $next, 'D7XSSWarFormValue'); } } } }
/** * Processes the tokens that this sniff is interested in. * * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param int $stackPtr The position in the stack where * the token was found. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); // Find the content of each style definition name. $end = $tokens[$stackPtr]['bracket_closer']; $next = $phpcsFile->findNext(T_STYLE, $stackPtr + 1, $end); if ($next === false) { // Class definition is empty. return; } $styleNames = array(); while ($next !== false) { $name = $tokens[$next]['content']; if (isset($styleNames[$name]) === true) { $first = $styleNames[$name]; $error = 'Duplicate style definition found; first defined on line %s'; $data = array($tokens[$first]['line']); $phpcsFile->addError($error, $next, 'Found', $data); } else { $styleNames[$name] = $next; } $next = $phpcsFile->findNext(T_STYLE, $next + 1, $end); } //end while }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); // Check if the next non whitespace token is a string. $index = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($tokens[$index]['code'] !== T_CONSTANT_ENCAPSED_STRING) { return; } // Make sure it is the only thing in the square brackets. $next = $phpcsFile->findNext(T_WHITESPACE, $index + 1, null, true); if ($tokens[$next]['code'] !== T_CLOSE_SQUARE_BRACKET) { return; } // Allow indexes that have dots in them because we can't write // them in dot notation. $content = trim($tokens[$index]['content'], '"\' '); if (strpos($content, '.') !== false) { return; } // Also ignore reserved words. if ($content === 'super') { return; } // Token before the opening square bracket cannot be a var name. $prev = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if ($tokens[$prev]['code'] === T_STRING) { $error = 'Object indexes must be written in dot notation'; $phpcsFile->addError($error, $prev, 'Found'); } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); // Check for global input variable if (!in_array($tokens[$stackPtr]['content'], array('$_GET', '$_POST', '$_REQUEST'))) { return; } $varName = $tokens[$stackPtr]['content']; // If we're overriding a superglobal with an assignment, no need to test $semicolon_position = $phpcsFile->findNext(array(T_SEMICOLON), $stackPtr + 1, null, null, null, true); $assignment_position = $phpcsFile->findNext(array(T_EQUAL), $stackPtr + 1, null, null, null, true); if ($semicolon_position !== false && $assignment_position !== false && $assignment_position < $semicolon_position) { return; } // Check for whitelisting comment $currentLine = $tokens[$stackPtr]['line']; $nextPtr = $stackPtr; while (isset($tokens[$nextPtr + 1]['line']) && $tokens[$nextPtr + 1]['line'] == $currentLine) { $nextPtr++; // Do nothing, we just want the last token of the line } $is_whitelisted = $tokens[$nextPtr]['code'] === T_COMMENT && preg_match('#input var okay#i', $tokens[$nextPtr]['content']) > 0; if (!$is_whitelisted) { $phpcsFile->addWarning('Detected access of super global var %s, probably need manual inspection.', $stackPtr, null, array($varName)); } }
/** * Processes the tokens that this sniff is interested in. * * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param int $stackPtr The position in the stack where * the token was found. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $utils = Security_Sniffs_UtilsFactory::getInstance(); $tokens = $phpcsFile->getTokens(); if ($tokens[$stackPtr]['content'] == 'preg_replace') { $s = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr); $closer = $tokens[$s]['parenthesis_closer']; $s = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $s + 1, $closer, true); if ($tokens[$s]['code'] == T_CONSTANT_ENCAPSED_STRING) { $pattern = $tokens[$s]['content']; if (substr($pattern, 1, 1) === '/') { // $pattern is a regex if (preg_match('/(\\/|\\))\\w*e\\w*"$/', $pattern)) { $phpcsFile->addWarning("Usage of preg_replace with /e modifier is not recommended.", $stackPtr, 'PregReplaceE'); $s = $phpcsFile->findNext(array(T_COMMA, T_WHITESPACE, T_COMMENT, T_DOC_COMMENT), $s + 1, $closer, true); if ($utils::is_token_user_input($tokens[$s])) { $phpcsFile->addError("User input and /e modifier found in preg_replace, remote code execution possible.", $stackPtr, 'PregReplaceUserInputE'); } } } else { $phpcsFile->addWarning("Weird usage of preg_replace, please check manually for /e modifier.", $stackPtr, 'PregReplaceWeird'); } } elseif ($tokens[$s]['code'] == T_VARIABLE && $utils::is_token_user_input($tokens[$s])) { $phpcsFile->addError("User input found in preg_replace, /e modifier could be used for malicious intent.", $stackPtr, 'PregReplaceUserInput'); } else { $phpcsFile->addWarning("Dynamic usage of preg_replace, please check manually for /e modifier or user input.", $stackPtr, 'PregReplaceDyn'); } } }
/** * Processes single-line calls. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * @param int $openBracket The position of the opening bracket * in the stack passed in $tokens. * @param array $tokens The stack of tokens that make up * the file. * * @return void */ public function isMultiLineCall(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $openBracket, $tokens) { // If the first argument is on a new line, this is a multi-line // function call, even if there is only one argument. $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $openBracket + 1, null, true); if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { return true; } $closeBracket = $tokens[$openBracket]['parenthesis_closer']; $end = $phpcsFile->findEndOfStatement($openBracket + 1); while ($tokens[$end]['code'] === T_COMMA) { // If the next bit of code is not on the same line, this is a // multi-line function call. $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $end + 1, $closeBracket, true); if ($next === false) { return false; } if ($tokens[$next]['line'] !== $tokens[$end]['line']) { return true; } $end = $phpcsFile->findEndOfStatement($next); } // We've reached the last argument, so see if the next content // (should be the close bracket) is also on the same line. $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $end + 1, $closeBracket, true); if ($next !== false && $tokens[$next]['line'] !== $tokens[$end]['line']) { return true; } return false; }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token in the * stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); if ($tokens[$stackPtr]['code'] === T_CASE && isset($tokens[$stackPtr]['scope_closer'])) { // $internalCase = $phpcsFile->findNext(T_CASE, $stackPtr + 1, $tokens[$stackPtr]['scope_closer']); // if ($internalCase !== false) { // $comment = $phpcsFile->findNext(T_COMMENT, $stackPtr + 1, $internalCase - 1); // if ($comment === false) { // $phpcsFile->addError($this->getReqPrefix('REQ.PHP.2.5.12') . '"case" has not break and has not any comment', $stackPtr); // } // } $switch = $phpcsFile->findPrevious(T_SWITCH, $stackPtr - 1); if ($switch !== false) { $nextCase = $phpcsFile->findNext(array(T_CASE, T_DEFAULT), $stackPtr + 1, $tokens[$switch]['scope_closer']); if ($nextCase !== false) { $prevBreak = $phpcsFile->findPrevious(T_BREAK, $nextCase - 1, $stackPtr); if ($prevBreak !== false) { $breakWS = $phpcsFile->findNext(T_WHITESPACE, $prevBreak + 1, $nextCase - 1); if ($breakWS !== false) { $str = $phpcsFile->getTokensAsString($breakWS, $nextCase - $breakWS - 1); if (!preg_match("/^\n\n[ ]*\$/Ss", $str)) { $breakWS = false; } } if ($breakWS === false) { $phpcsFile->addError($this->getReqPrefix('REQ.PHP.2.5.14') . '"case" must has empty line between current "case" and previous "break"', $stackPtr); } } } } } elseif ($tokens[$stackPtr]['code'] === T_DEFAULT) { } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token in the * stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { if ($this->supportsAbove('5.4')) { $tokens = $phpcsFile->getTokens(); $nextSemicolonToken = $phpcsFile->findNext(T_SEMICOLON, $stackPtr, null, false); for ($curToken = $stackPtr + 1; $curToken < $nextSemicolonToken; $curToken++) { $gotError = false; if ($tokens[$curToken]['type'] == 'T_STRING') { // If the next non-whitespace token after the string // is an opening parenthesis then it's a function call. $openBracket = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $curToken + 1, null, true); if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { continue; } else { $gotError = true; } } switch ($tokens[$curToken]['type']) { case 'T_VARIABLE': case 'T_FUNCTION': $gotError = true; break; } if ($gotError === true) { $error = 'Using a variable argument on break or continue is forbidden since PHP 5.4'; $phpcsFile->addError($error, $stackPtr); } } } }
/** * Processes the tokens that this sniff is interested in. * * @param PHP_CodeSniffer_File $phpcs_file The file where the token was found. * @param int $stack_ptr The position in the stack where the token was found. * * @return void */ public function process(\PHP_CodeSniffer_File $phpcs_file, $stack_ptr) { // only check for use statements that are before the first class declaration // classes can have use statements for traits, for which we are not interested in this sniff $first_class_occurence = $phpcs_file->findPrevious([T_CLASS, T_TRAIT], $stack_ptr); if ($first_class_occurence > 0 && $stack_ptr > $first_class_occurence) { return; } $tokens = $phpcs_file->getTokens(); // Reach the end of the current statement $stack_ptr = $phpcs_file->findNext([T_SEMICOLON], $stack_ptr + 1); $end_stmt = $stack_ptr; // if there is another 'use' statement, it should be at $stack_ptr + 1 $next_use = $phpcs_file->findNext([T_USE], $stack_ptr + 1); $next_class = $phpcs_file->findNext([T_CLASS, T_TRAIT], $stack_ptr + 1); //There is a class and the next use statement is afte the class definition. skipp it if ($next_class && $next_use > $next_class) { return; } //Loop from the end of the use statement (;) untill the next use statement for ($i = $end_stmt + 1; $i <= $next_use; $i++) { //the current token ($i) contains an end of line //And it's on the next line than the end of the use satement if (stristr($tokens[$i]['content'], "\n") !== false && $tokens[$i]['line'] != $tokens[$end_stmt]['line']) { $this->checkForNewlineOrComments($phpcs_file, $i); } } }
/** * Processes the tokens that this sniff is interested in. * * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param int $stackPtr The position in the stack where * the token was found. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $utils = Security_Sniffs_UtilsFactory::getInstance(); $tokens = $phpcsFile->getTokens(); if (in_array($tokens[$stackPtr]['content'], $utils::getFilesystemFunctions())) { if ($tokens[$stackPtr]['content'] == 'symlink') { $phpcsFile->addWarning('Allowing symlink() while open_basedir is used is actually a security risk. Disabled by default in Suhosin >= 0.9.6', $stackPtr, 'WarnSymlink'); } $s = $stackPtr + 1; $opener = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr, null, false, null, true); if (!$opener) { // No opener found, so it's probably not a function call if (PHP_CodeSniffer::getConfigData('ParanoiaMode')) { $phpcsFile->addWarning('Filesystem function ' . $tokens[$stackPtr]['content'] . ' used but not as a function', $stackPtr, 'WarnWeirdFilesystem'); } return; } $closer = $tokens[$opener]['parenthesis_closer']; $s = $phpcsFile->findNext(array_merge(PHP_CodeSniffer_Tokens::$emptyTokens, PHP_CodeSniffer_Tokens::$bracketTokens, Security_Sniffs_Utils::$staticTokens), $s, $closer, true); if ($s) { $msg = 'Filesystem function ' . $tokens[$stackPtr]['content'] . '() detected with dynamic parameter'; if ($utils::is_token_user_input($tokens[$s])) { $phpcsFile->addError($msg . ' directly from user input', $stackPtr, 'ErrFilesystem'); } else { $phpcsFile->addWarning($msg, $stackPtr, 'WarnFilesystem'); } } } }
/** * Processes the tokens that this sniff is interested in. * * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param int $stackPtr The position in the stack where * the token was found. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $next_var = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($next_var && $tokens[$next_var]["type"] == "T_STRING") { $name_var = $tokens[$next_var]["content"]; $var_line = $tokens[$next_var]["line"]; $next = $phpcsFile->findNext(T_WHITESPACE, $next_var + 1, null, true); $error = false; $only_one = "'Var' statement must contain only one variable"; if ($tokens[$stackPtr]["line"] != $var_line) { $error = "'Var' statement must be on one line"; } elseif ($tokens[$next]["type"] == "T_SEMICOLON") { $error = "Variable '{$name_var}' must be initialized"; } elseif ($tokens[$next]["type"] == "T_COMMA") { $error = $only_one; } if ($error === false) { do { $next_var = $phpcsFile->findNext(T_WHITESPACE, $next_var + 1, null, true); $token = $tokens[$next_var]; } while ($token["line"] == $var_line && !in_array($token["type"], array("T_COMMA", "T_SEMICOLON", "T_OPEN_SQUARE_BRACKET"))); if ($token["type"] == "T_COMMA") { $error = $only_one; } } if ($error !== false) { $phpcsFile->addError($this->getReqPrefix('REQ.JS.3.7') . $error, $stackPtr); } } return; }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { // If short open tags are off, then any short open tags will be converted // to inline_html tags so we can just ignore them. // If its on, then we want to ban the use of them. $option = ini_get('short_open_tag'); // Ini_get returns a string "0" if short open tags is off. if ($option === '0') { return; } if (!isset($this->files_cache[$phpcsFile->getFilename()]) && !$phpcsFile->findNext(T_OPEN_TAG, $stackPtr + 1) && !$phpcsFile->findNext(T_OPEN_TAG_WITH_ECHO, $stackPtr + 1) && $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr)) { $error = 'Файл имеет только один открывающий PHP-тэг, но имеет закрывающий PHP-тэг.'; $phpcsFile->addError($this->getReqPrefix('REQ.PHP.2.1.1') . $error, $stackPtr); } $this->files_cache[$phpcsFile->getFilename()] = true; $tokens = $phpcsFile->getTokens(); $openTag = $tokens[$stackPtr]; if ($openTag['content'] === '<?') { $error = 'Short PHP opening tag used. Found "' . $openTag['content'] . '" Expected "<?php".'; $phpcsFile->addError($this->getReqPrefix('REQ.PHP.2.1.2') . $error, $stackPtr); } if ($openTag['code'] === T_OPEN_TAG_WITH_ECHO) { $nextVar = $tokens[$phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr + 1, null, true)]; $error = 'Short PHP opening tag used with echo. Found "'; $error .= $openTag['content'] . ' ' . $nextVar['content'] . ' ..." but expected "<?php echo ' . $nextVar['content'] . ' ...".'; $phpcsFile->addError($this->getReqPrefix('REQ.PHP.2.1.2') . $error, $stackPtr); } }
/** * Processes the tokens that this sniff is interested in. * * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param int $stackPtr The position in the stack where * the token was found. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $style = $tokens[$stackPtr]['content']; $start = $phpcsFile->findNext(T_COLON, $stackPtr); $end = $phpcsFile->findNext(T_SEMICOLON, $stackPtr); if (!$start || !$end) { return; } # Get the full description value $value = ''; for ($i = $start + 1; $i < $end; $i++) { if ($tokens[$i]['code'] === T_LNUMBER) { # Next to number follows the dimension if ($tokens[$i + 1]['code'] === T_WHITESPACE || $tokens[$i + 1]['code'] === T_SEMICOLON) { continue; } $dim = $tokens[$i + 1]['content']; if (!in_array($dim, $this->allowedDims)) { $error = 'Запрещены к использованию размерности, кроме px, em, ex, %'; $phpcsFile->addError($this->getReqPrefix('REQ.CSS.3.0.1') . $error, $i); } elseif (in_array($style, $this->relativeDimsStyles) && !in_array($dim, array('em', 'ex', '%'))) { /* TODO - research $error = 'Размерность шрифта требуется задавать в em/ex'; $phpcsFile->addError($this->getReqPrefix('REQ.CSS.3.0.1') . $error, $i); */ } } } }
/** * @inheritdoc */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $classScopeStart = $tokens[$stackPtr]['scope_opener']; $classScopeEnd = $tokens[$stackPtr]['scope_closer']; $classPosition = $stackPtr; $stackPtr = $phpcsFile->findNext(T_STRING, $stackPtr + 1); $className = $tokens[$stackPtr]['content']; if (false === ($stackPtr = $phpcsFile->findNext(T_EXTENDS, $stackPtr + 1))) { // the currently tested class hasn't extended any class return; } $stackPtr = $phpcsFile->findNext(T_STRING, $stackPtr + 1); $parentClassName = $tokens[$stackPtr]['content']; if ($parentClassName == self::PARENT_CLASS_NAME) { while (false !== ($stackPtr = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $classScopeStart + 1, $classScopeEnd - 1, true, 'function'))) { $stackPtr = $phpcsFile->findNext(T_STRING, $stackPtr + 1); $methodName = $tokens[$stackPtr]['content']; $classScopeStart = $stackPtr; if ($methodName == self::REQUIRED_ACL_METHOD_NAME) { // the currently tested class has implemented the required ACL method return; } } $phpcsFile->addError('Missing the %s() ACL method in the %s class.', $classPosition, 'MissingAclMethod', array(self::REQUIRED_ACL_METHOD_NAME, $className)); } }
/** * Process this function definition. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the function name in the stack. * name in the stack. * @param int $functionPtr The position of the function keyword in the stack. * keyword in the stack. * * @return void */ public function processFunction(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $functionPtr) { $fileExtension = strtolower(substr($phpcsFile->getFilename(), -6)); // Only check in *.module files. if ($fileExtension !== 'module') { return; } $fileName = substr(basename($phpcsFile->getFilename()), 0, -7); $tokens = $phpcsFile->getTokens(); if ($tokens[$stackPtr]['content'] !== $fileName . '_menu') { return; } // Search in the function body for t() calls. $string = $phpcsFile->findNext(T_STRING, $tokens[$functionPtr]['scope_opener'], $tokens[$functionPtr]['scope_closer']); while ($string !== false) { if ($tokens[$string]['content'] === 't') { $opener = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $string + 1, null, true); if ($opener !== false && $tokens[$opener]['code'] === T_OPEN_PARENTHESIS) { $error = 'Do not use t() in hook_menu()'; $phpcsFile->addError($error, $string, 'TFound'); } } $string = $phpcsFile->findNext(T_STRING, $string + 1, $tokens[$functionPtr]['scope_closer']); } //end while }
/** * Processes the tokens that this sniff is interested in. * * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param int $stackPtr The position in the stack where * the token was found. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $utils = Security_Sniffs_UtilsFactory::getInstance(); if ($this->forceParanoia >= 0) { $parano = $this->forceParanoia ? 1 : 0; } else { $parano = PHP_CodeSniffer::getConfigData('ParanoiaMode') ? 1 : 0; } $tokens = $phpcsFile->getTokens(); $s = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr, null, true, null, true); if ($tokens[$stackPtr]['code'] == T_OPEN_TAG_WITH_ECHO) { $closer = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr); } elseif ($tokens[$s]['code'] == T_OPEN_PARENTHESIS) { $closer = $tokens[$s]['parenthesis_closer']; } else { $closer = $phpcsFile->findNext(array(T_SEMICOLON, T_CLOSE_TAG), $stackPtr); $s = $stackPtr; } $warn = false; while ($s) { $s = $phpcsFile->findNext(array_merge(PHP_CodeSniffer_Tokens::$emptyTokens, PHP_CodeSniffer_Tokens::$bracketTokens, Security_Sniffs_Utils::$staticTokens), $s + 1, $closer, true); if ($s && $utils::is_token_user_input($tokens[$s])) { $phpcsFile->addError('Easy XSS detected because of direct user input with ' . $tokens[$s]['content'] . ' on ' . $tokens[$stackPtr]['content'], $s, 'EasyXSSerr'); } elseif ($s && $utils::is_XSS_mitigation($tokens[$s]['content'])) { $s = $tokens[$s + 1]['parenthesis_closer']; } elseif ($s && $parano && !$warn) { $warn = $s; } } if ($warn) { $phpcsFile->addWarning('Possible XSS detected with ' . $tokens[$warn]['content'] . ' on ' . $tokens[$stackPtr]['content'], $warn, 'EasyXSSwarn'); } }
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $nameIndex = $phpcsFile->findNext(T_VARIABLE, $stackPtr + 1); $semicolonIndex = $phpcsFile->findNext(T_SEMICOLON, $stackPtr + 1); while ($nameIndex < $semicolonIndex) { if ($tokens[$nameIndex]['code'] !== T_WHITESPACE && $tokens[$nameIndex]['code'] !== T_COMMA) { $globalName = $tokens[$nameIndex]['content']; if (in_array($globalName, $this->ignoreList) || in_array($globalName, self::$PHPReserved)) { return; } // Skip '$' and forge a valid global variable name $expected = '$wg' . ucfirst(substr($globalName, 1)); // Verify global is prefixed with wg if (strpos($globalName, '$wg') !== 0) { $phpcsFile->addError('Global variable "%s" is lacking \'wg\' prefix. Should be "%s".', $stackPtr, 'wgPrefix', array($globalName, $expected)); } else { // Verify global is probably CamelCase $val = ord(substr($globalName, 3, 1)); if (!($val >= 65 && $val <= 90)) { $phpcsFile->addError('Global variable "%s" should use CamelCase: "%s"', $stackPtr, 'CamelCase', array($globalName, $expected)); } } } $nameIndex++; } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile All the tokens found in the document. * @param int $stackPtr The position of the current token in * the stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $line = $tokens[$stackPtr]['line']; while ($tokens[$stackPtr]['line'] == $line) { /* * Suffix traits with Trait; */ if ('T_TRAIT' == $tokens[$stackPtr]['type']) { $name = $phpcsFile->findNext(T_STRING, $stackPtr); if ($name && substr($tokens[$name]['content'], -5) != 'Trait') { $phpcsFile->addError('Trait name is not suffixed with "Trait"', $stackPtr, 'InvalidTraitName'); } break; } /* * Suffix exceptions with Exception; */ if ('T_EXTENDS' == $tokens[$stackPtr]['type']) { $extend = $phpcsFile->findNext(T_STRING, $stackPtr); if ($extend && substr($tokens[$extend]['content'], -9) == 'Exception') { $class = $phpcsFile->findPrevious(T_CLASS, $stackPtr); $name = $phpcsFile->findNext(T_STRING, $class); if ($name && substr($tokens[$name]['content'], -9) != 'Exception') { $phpcsFile->addError('Exception name is not suffixed with "Exception"', $stackPtr, 'InvalidExceptionName'); } } break; } $stackPtr++; } return; }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $namespace = ''; $stackPtr = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE, T_NAMESPACE), 0); while ($stackPtr !== false) { // Keep track of what namespace we are in. if ($tokens[$stackPtr]['code'] === T_NAMESPACE) { $nsEnd = $phpcsFile->findNext(array(T_NS_SEPARATOR, T_STRING, T_WHITESPACE), $stackPtr + 1, null, true); $namespace = trim($phpcsFile->getTokensAsString($stackPtr + 1, $nsEnd - $stackPtr - 1)); $stackPtr = $nsEnd; } else { $nameToken = $phpcsFile->findNext(T_STRING, $stackPtr); $name = $tokens[$nameToken]['content']; if ($namespace !== '') { $name = $namespace . '\\' . $name; } $compareName = strtolower($name); if (isset($this->foundClasses[$compareName]) === true) { $type = strtolower($tokens[$stackPtr]['content']); $file = $this->foundClasses[$compareName]['file']; $line = $this->foundClasses[$compareName]['line']; $error = 'Duplicate %s name "%s" found; first defined in %s on line %s'; $data = array($type, $name, $file, $line); $phpcsFile->addWarning($error, $stackPtr, 'Found', $data); } else { $this->foundClasses[$compareName] = array('file' => $phpcsFile->getFilename(), 'line' => $tokens[$stackPtr]['line']); } } $stackPtr = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE, T_NAMESPACE), $stackPtr + 1); } //end while }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token in the * stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { if (is_null(PHP_CodeSniffer::getConfigData('testVersion')) || !is_null(PHP_CodeSniffer::getConfigData('testVersion')) && version_compare(PHP_CodeSniffer::getConfigData('testVersion'), '5.4') >= 0) { $tokens = $phpcsFile->getTokens(); if (in_array($tokens[$stackPtr]['content'], $this->algoFunctions) === true) { $openBracket = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr + 1, null, true); if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { return; } $firstParam = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $openBracket + 1, null, true); /** * Algorithm is a T_CONSTANT_ENCAPSED_STRING, so we need to remove the quotes */ $algo = strtolower($tokens[$firstParam]['content']); $algo = substr($algo, 1, strlen($algo) - 2); switch ($algo) { case 'salsa10': case 'salsa20': $error = 'The Salsa10 and Salsa20 hash algorithms have been removed since PHP 5.4'; $phpcsFile->addError($error, $stackPtr); break; } } } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile * @param int $stackPtr */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $functionToken = $phpcsFile->findNext(T_FUNCTION, $stackPtr); if ($functionToken === false) { return; } $nameToken = $phpcsFile->findNext(T_STRING, $functionToken); if (in_array($tokens[$nameToken]['content'], $this->magicMethods) === false) { return; } $scopeToken = $phpcsFile->findPrevious(array(T_PUBLIC, T_PROTECTED, T_PRIVATE), $nameToken, $stackPtr); if ($scopeToken === false) { return; } if ($tokens[$scopeToken]['type'] != 'T_PUBLIC') { $error = "Magic methods must be public (since PHP 5.3) !"; $phpcsFile->addError($error, $stackPtr); } $staticToken = $phpcsFile->findPrevious(T_STATIC, $scopeToken, $scopeToken - 2); if ($staticToken === false) { return; } else { $error = "Magic methods can not be static (since PHP 5.3) !"; $phpcsFile->addError($error, $stackPtr); } }
/** * Process the tokens that this sniff is listening for. * * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param int $stackPtr The position in the stack where * the token was found. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); // Make sure there is a variable before it. $variable = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr - 1, null, true); if ($variable === false || $tokens[$variable]['code'] !== T_VARIABLE) { return; } $ignore = array('$_SERVER', '$_GET', '$_POST', '$_REQUEST'); $variableName = $tokens[$variable]['content']; if (in_array($variableName, $ignore) === true) { return; } // We are only interested in indexes that are single strings. $index = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr + 1, null, true); $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $index + 1, null, true); if ($next !== $tokens[$stackPtr]['bracket_closer']) { return; } $indexContent = trim($tokens[$index]['content'], "'"); if (preg_match('|^[a-zA-Z0-9_]+$|', $indexContent) === 1) { if (strtolower($indexContent) !== $indexContent) { $error = 'Array index "' . $indexContent . '" should not contain uppercase characters'; $phpcsFile->addError($error, $index); } } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param integer $stackPtr The position of the current token in * the token stack. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); if (isset($tokens[$stackPtr]['scope_closer']) === false) { return; } $className = $phpcsFile->getDeclarationName($stackPtr); $errorData = array(strtolower($tokens[$stackPtr]['content'])); $nextClass = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE, T_TRAIT), $tokens[$stackPtr]['scope_closer'] + 1); if ($nextClass !== false) { $nextClassName = $phpcsFile->getDeclarationName($nextClass); $extends = $phpcsFile->findExtendedClassName($nextClass); if ($className == $nextClassName && $extends != $className && substr($extends, -1 * (strlen($className) + 1)) == '\\' . $className) { // $nextClassName wraps $className in global namespace (probably) $phpcsFile->recordMetric($stackPtr, 'One class per file', 'yes'); } else { $error = 'Each %s must be in a file by itself'; $phpcsFile->addError($error, $nextClass, 'MultipleClasses', $errorData); $phpcsFile->recordMetric($stackPtr, 'One class per file', 'no'); } } else { $phpcsFile->recordMetric($stackPtr, 'One class per file', 'yes'); } if (version_compare(PHP_VERSION, '5.3.0') >= 0) { $namespace = $phpcsFile->findNext(array(T_NAMESPACE, T_CLASS, T_INTERFACE, T_TRAIT), 0); if ($tokens[$namespace]['code'] !== T_NAMESPACE) { $error = 'Each %s must be in a namespace of at least one level (a top-level vendor name)'; $phpcsFile->addWarning($error, $stackPtr, 'MissingNamespace', $errorData); $phpcsFile->recordMetric($stackPtr, 'Class defined in namespace', 'no'); } else { $phpcsFile->recordMetric($stackPtr, 'Class defined in namespace', 'yes'); } } }
/** * Process the sniff. Will be engaged when one of the tokens from ::register() is encountered. * * @param PHP_CodeSniffer_File $phpcsFile An instance of the current source file being scanned. * @param int $stackPtr The position of the encountered token in the provided file. * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); // Nothing to do if the file is already in the global namespace. if ($phpcsFile->findPrevious(T_NAMESPACE, $stackPtr) === false) { return; } // Only proceed with checking the matched namespaced string if is not part of a `namespace Vendor\Foo;` or a `use Vendor\Bar as Baz;` statement. if ($phpcsFile->findPrevious([T_NAMESPACE, T_USE], $stackPtr - 1, null, false, null, true) === false) { $nextNonClassSegment = $phpcsFile->findNext([T_NS_SEPARATOR, T_STRING], $stackPtr + 1, null, true); $lastNsSeperator = $phpcsFile->findPrevious(T_NS_SEPARATOR, $nextNonClassSegment); // Only report for the last backslash matched in a single namespace string. (This sniff will trigger on each slash from `new \Some\Vendor\Lib();`, so this makes sure we don't report 3 errors for that same statement.) if ($lastNsSeperator === $stackPtr) { $start = $phpcsFile->findPrevious([T_NS_SEPARATOR, T_STRING], $stackPtr - 1, null, true) + 1; $end = $phpcsFile->findNext([T_NS_SEPARATOR, T_STRING], $start + 1, null, true); $class = ''; for ($i = $start; $i < $end; $i++) { $class .= $tokens[$i]['content']; } $tClass = $phpcsFile->findPrevious(T_CLASS, $stackPtr - 1); // Check if the code is attempting to extend a class with the same name. if ($tClass !== false) { $newClass = $phpcsFile->findNext(T_STRING, $tClass); if ($tokens[$newClass]['content'] == $tokens[$end - 1]['content']) { return; } $err = 'Namespaced class (%s) must be imported before use.'; $data = [$class]; $phpcsFile->addError($err, $stackPtr, 'ClassMustBeImported', $data); } } } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token in the * stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $firstContent = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); // If the first non-whitespace token is not an opening parenthesis, then we are not concerned. if ($tokens[$firstContent]['code'] !== T_OPEN_PARENTHESIS) { $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no'); return; } $end = $phpcsFile->findNext(array(T_SEMICOLON, T_CLOSE_TAG), $stackPtr, null, false); // If the token before the semi-colon is not a closing parenthesis, then we are not concerned. $prev = $phpcsFile->findPrevious(T_WHITESPACE, $end - 1, null, true); if ($tokens[$prev]['code'] !== T_CLOSE_PARENTHESIS) { $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no'); return; } // If the parenthesis don't match, then we are not concerned. if ($tokens[$firstContent]['parenthesis_closer'] !== $prev) { $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no'); return; } $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'yes'); if ($phpcsFile->findNext(PHP_CodeSniffer_Tokens::$operators, $stackPtr, $end, false) === false) { // There are no arithmetic operators in this. $error = 'Echoed strings should not be bracketed'; $fix = $phpcsFile->addFixableError($error, $stackPtr, 'HasBracket'); if ($fix === true) { $phpcsFile->fixer->beginChangeset(); $phpcsFile->fixer->replaceToken($firstContent, ''); $phpcsFile->fixer->replaceToken($end - 1, ''); $phpcsFile->fixer->endChangeset(); } } }
/** * Processes the tokens that this sniff is interested in. * * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param int $stackPtr The position in the stack where * the token was found. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $utils = Security_Sniffs_UtilsFactory::getInstance(); $tokens = $phpcsFile->getTokens(); if (preg_match('/<|>/', $tokens[$stackPtr]['content'])) { $end = $phpcsFile->findNext(T_SEMICOLON, $stackPtr + 1); $next = $stackPtr; while ($next && ($next = $phpcsFile->findNext(array_merge(array(T_STRING_CONCAT), PHP_CodeSniffer_Tokens::$emptyTokens), $next + 1, $end, true))) { // Next token will be checked with this sniff, no need to go further if (in_array($tokens[$next]['code'], $this->register())) { return; } if ($next && !in_array($tokens[$next]['content'], $utils::getXSSMitigationFunctions())) { if ($utils::is_direct_user_input($tokens[$next]['content'])) { $phpcsFile->addError('HTML construction with direct user input ' . $tokens[$next]['content'] . ' detected.', $stackPtr, 'D7XSSHTMLConstructErr'); } elseif (PHP_CodeSniffer::getConfigData('ParanoiaMode') && !in_array($tokens[$next]['code'], array_merge(array(T_INLINE_ELSE, T_COMMA), PHP_CodeSniffer_Tokens::$booleanOperators))) { if ($tokens[$next]['code'] == T_CLOSE_PARENTHESIS) { $f = $phpcsFile->findPrevious(T_STRING, $next); if ($f) { $phpcsFile->addWarning('HTML construction with ' . $tokens[$f]['content'] . '() detected.', $stackPtr, 'D7XSSHTMLConstructWarnF'); } } else { $phpcsFile->addWarning('HTML construction with ' . $tokens[$next]['content'] . ' detected.', $stackPtr, 'D7XSSHTMLConstructWarn'); } } } $next = $phpcsFile->findNext(T_STRING_CONCAT, $next + 1, $end); } } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The current file being processed. * @param int $stackPtr The position of the current token in the * stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $start = $tokens[$stackPtr]['scope_opener']; $end = $tokens[$stackPtr]['scope_closer']; $properties = array(); $wantedTokens = array(T_PROPERTY, T_OPEN_CURLY_BRACKET); $next = $phpcsFile->findNext($wantedTokens, $start + 1, $end); while ($next !== false && $next < $end) { // Skip nested objects. if ($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET) { $next = $tokens[$next]['bracket_closer']; } else { $propName = $tokens[$next]['content']; if (isset($properties[$propName]) === true) { $line = $tokens[$properties[$propName]]['line']; $error = "Duplicate property definition found for \"{$propName}\"; previously defined on line {$line}"; $phpcsFile->addError($error, $next); } $properties[$propName] = $next; } //end if $next = $phpcsFile->findNext($wantedTokens, $next + 1, $end); } //end while }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param integer $stackPtr The position of the current token in * the token stack. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { if ($this->_phpVersion === null) { $this->_phpVersion = PHP_CodeSniffer::getConfigData('php_version'); if ($this->_phpVersion === null) { $this->_phpVersion = PHP_VERSION_ID; } } $tokens = $phpcsFile->getTokens(); if (isset($tokens[$stackPtr]['scope_closer']) === false) { return; } $errorData = array(strtolower($tokens[$stackPtr]['content'])); $nextClass = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE, T_TRAIT), $tokens[$stackPtr]['scope_closer'] + 1); if ($nextClass !== false) { $error = 'Each %s must be in a file by itself'; $phpcsFile->addError($error, $nextClass, 'MultipleClasses', $errorData); $phpcsFile->recordMetric($stackPtr, 'One class per file', 'no'); } else { $phpcsFile->recordMetric($stackPtr, 'One class per file', 'yes'); } if ($this->_phpVersion >= 50300) { $namespace = $phpcsFile->findNext(array(T_NAMESPACE, T_CLASS, T_INTERFACE, T_TRAIT), 0); if ($tokens[$namespace]['code'] !== T_NAMESPACE) { $error = 'Each %s must be in a namespace of at least one level (a top-level vendor name)'; $phpcsFile->addError($error, $stackPtr, 'MissingNamespace', $errorData); $phpcsFile->recordMetric($stackPtr, 'Class defined in namespace', 'no'); } else { $phpcsFile->recordMetric($stackPtr, 'Class defined in namespace', 'yes'); } } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The current file being processed. * @param int $stackPtr The position of the current token in the * stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); if (isset($tokens[$stackPtr]['scope_opener']) === false) { $error = 'Possible parse error: %s missing opening or closing brace'; $data = array($tokens[$stackPtr]['content']); $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $data); return; } // Determine the name of the class or interface. Note that we cannot // simply look for the first T_STRING because a class name // starting with the number will be multiple tokens. $opener = $tokens[$stackPtr]['scope_opener']; $nameStart = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, $opener, true); $nameEnd = $phpcsFile->findNext(T_WHITESPACE, $nameStart, $opener); $name = trim($phpcsFile->getTokensAsString($nameStart, $nameEnd - $nameStart)); // Check for camel caps format. $valid = PHP_CodeSniffer::isCamelCaps($name, true, true, false); if ($valid === false) { $type = ucfirst($tokens[$stackPtr]['content']); $error = '%s name "%s" is not in camel caps format'; $data = array($type, $name); $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data); } }
/** * Processes the tokens that this sniff is interested in. * * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param int $stackPtr The position in the stack where * the token was found. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); if ($tokens[$stackPtr - 1]['code'] !== T_WHITESPACE) { $error = 'Expected 1 space before opening brace of class definition; 0 found'; $phpcsFile->addError($error, $stackPtr, 'NoneBefore'); } else { $content = $tokens[$stackPtr - 1]['content']; if ($content !== ' ') { $length = strlen($content); if ($length === 1) { $length = 'tab'; } $error = 'Expected 1 space before opening brace of class definition; %s found'; $data = array($length); $phpcsFile->addError($error, $stackPtr, 'Before', $data); } } //end if $end = $tokens[$stackPtr]['bracket_closer']; // Do not check nested style definitions as, for example, in @media style rules. $nested = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, $stackPtr + 1, $end); if ($nested !== false) { return; } $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr + 1, null, true); if ($next !== false && $tokens[$next]['line'] !== $tokens[$stackPtr]['line'] + 1) { $error = 'Expected exactly one new line after opening brace of class definition'; $phpcsFile->addError($error, $stackPtr, 'After'); } }