summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorJoas Schilling <nickvergessen@gmx.de>2015-07-20 08:39:53 +0200
committerJoas Schilling <nickvergessen@gmx.de>2015-07-20 08:39:53 +0200
commit0dd1a785fe56177b13885e94cf49031493195f8a (patch)
treeb9f40bde5ba4bdbf8bd3484f01745e3052778a10 /lib
parent83a13c0635fa5c8ca25a23d3996b62c5f2d82a2b (diff)
parent3566dcf246d122bbc4010aeb42c5b2d9259f8ea5 (diff)
downloadnextcloud-server-0dd1a785fe56177b13885e94cf49031493195f8a.tar.gz
nextcloud-server-0dd1a785fe56177b13885e94cf49031493195f8a.zip
Merge pull request #16935 from owncloud/allow-app-check-code-for-deprecated-classes
Allow app check code for deprecated classes
Diffstat (limited to 'lib')
-rw-r--r--lib/private/app/codechecker/abstractcheck.php139
-rw-r--r--lib/private/app/codechecker/codechecker.php (renamed from lib/private/app/codechecker.php)42
-rw-r--r--lib/private/app/codechecker/deprecationcheck.php147
-rw-r--r--lib/private/app/codechecker/emptycheck.php67
-rw-r--r--lib/private/app/codechecker/icheck.php55
-rw-r--r--lib/private/app/codechecker/nodevisitor.php306
-rw-r--r--lib/private/app/codechecker/privatecheck.php86
-rw-r--r--lib/private/app/codechecker/strongcomparisoncheck.php80
-rw-r--r--lib/private/app/codecheckvisitor.php133
9 files changed, 889 insertions, 166 deletions
diff --git a/lib/private/app/codechecker/abstractcheck.php b/lib/private/app/codechecker/abstractcheck.php
new file mode 100644
index 00000000000..c1c6524e42f
--- /dev/null
+++ b/lib/private/app/codechecker/abstractcheck.php
@@ -0,0 +1,139 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\App\CodeChecker;
+
+abstract class AbstractCheck implements ICheck {
+ /** @var ICheck */
+ protected $check;
+
+ /**
+ * @param ICheck $check
+ */
+ public function __construct(ICheck $check) {
+ $this->check = $check;
+ }
+
+ /**
+ * @param int $errorCode
+ * @param string $errorObject
+ * @return string
+ */
+ public function getDescription($errorCode, $errorObject) {
+ switch ($errorCode) {
+ case CodeChecker::STATIC_CALL_NOT_ALLOWED:
+ $functions = $this->getLocalFunctions();
+ $functions = array_change_key_case($functions, CASE_LOWER);
+ if (isset($functions[$errorObject])) {
+ return $this->getLocalDescription();
+ }
+ // no break;
+ case CodeChecker::CLASS_EXTENDS_NOT_ALLOWED:
+ case CodeChecker::CLASS_IMPLEMENTS_NOT_ALLOWED:
+ case CodeChecker::CLASS_NEW_NOT_ALLOWED:
+ case CodeChecker::CLASS_USE_NOT_ALLOWED:
+ $classes = $this->getLocalClasses();
+ $classes = array_change_key_case($classes, CASE_LOWER);
+ if (isset($classes[$errorObject])) {
+ return $this->getLocalDescription();
+ }
+ break;
+
+ case CodeChecker::CLASS_CONST_FETCH_NOT_ALLOWED:
+ $constants = $this->getLocalConstants();
+ $constants = array_change_key_case($constants, CASE_LOWER);
+ if (isset($constants[$errorObject])) {
+ return $this->getLocalDescription();
+ }
+ break;
+
+ case CodeChecker::CLASS_METHOD_CALL_NOT_ALLOWED:
+ $methods = $this->getLocalMethods();
+ $methods = array_change_key_case($methods, CASE_LOWER);
+ if (isset($methods[$errorObject])) {
+ return $this->getLocalDescription();
+ }
+ break;
+ }
+
+ return $this->check->getDescription($errorCode, $errorObject);
+ }
+
+ /**
+ * @return string
+ */
+ abstract protected function getLocalDescription();
+
+ /**
+ * @return array
+ */
+ abstract protected function getLocalClasses();
+
+ /**
+ * @return array
+ */
+ abstract protected function getLocalConstants();
+
+ /**
+ * @return array
+ */
+ abstract protected function getLocalFunctions();
+
+ /**
+ * @return array
+ */
+ abstract protected function getLocalMethods();
+
+ /**
+ * @return array E.g.: `'ClassName' => 'oc version',`
+ */
+ public function getClasses() {
+ return array_merge($this->getLocalClasses(), $this->check->getClasses());
+ }
+
+ /**
+ * @return array E.g.: `'ClassName::CONSTANT_NAME' => 'oc version',`
+ */
+ public function getConstants() {
+ return array_merge($this->getLocalConstants(), $this->check->getConstants());
+ }
+
+ /**
+ * @return array E.g.: `'functionName' => 'oc version',`
+ */
+ public function getFunctions() {
+ return array_merge($this->getLocalFunctions(), $this->check->getFunctions());
+ }
+
+ /**
+ * @return array E.g.: `'ClassName::methodName' => 'oc version',`
+ */
+ public function getMethods() {
+ return array_merge($this->getLocalMethods(), $this->check->getMethods());
+ }
+
+ /**
+ * @return bool
+ */
+ public function checkStrongComparisons() {
+ return $this->check->checkStrongComparisons();
+ }
+}
diff --git a/lib/private/app/codechecker.php b/lib/private/app/codechecker/codechecker.php
index 3f6cd19d6b4..ef7dc7f3e4d 100644
--- a/lib/private/app/codechecker.php
+++ b/lib/private/app/codechecker/codechecker.php
@@ -21,14 +21,13 @@
*
*/
-namespace OC\App;
+namespace OC\App\CodeChecker;
use OC\Hooks\BasicEmitter;
use PhpParser\Lexer;
use PhpParser\Node;
use PhpParser\Node\Name;
use PhpParser\NodeTraverser;
-use PhpParser\NodeVisitorAbstract;
use PhpParser\Parser;
use RecursiveCallbackFilterIterator;
use RecursiveDirectoryIterator;
@@ -42,43 +41,20 @@ class CodeChecker extends BasicEmitter {
const CLASS_IMPLEMENTS_NOT_ALLOWED = 1001;
const STATIC_CALL_NOT_ALLOWED = 1002;
const CLASS_CONST_FETCH_NOT_ALLOWED = 1003;
- const CLASS_NEW_FETCH_NOT_ALLOWED = 1004;
+ const CLASS_NEW_NOT_ALLOWED = 1004;
const OP_OPERATOR_USAGE_DISCOURAGED = 1005;
+ const CLASS_USE_NOT_ALLOWED = 1006;
+ const CLASS_METHOD_CALL_NOT_ALLOWED = 1007;
/** @var Parser */
private $parser;
- /** @var string[] */
- private $blackListedClassNames;
+ /** @var ICheck */
+ protected $checkList;
- public function __construct() {
+ public function __construct(ICheck $checkList) {
+ $this->checkList = $checkList;
$this->parser = new Parser(new Lexer);
- $this->blackListedClassNames = [
- // classes replaced by the public api
- 'OC_API',
- 'OC_App',
- 'OC_AppConfig',
- 'OC_Avatar',
- 'OC_BackgroundJob',
- 'OC_Config',
- 'OC_DB',
- 'OC_Files',
- 'OC_Helper',
- 'OC_Hook',
- 'OC_Image',
- 'OC_JSON',
- 'OC_L10N',
- 'OC_Log',
- 'OC_Mail',
- 'OC_Preferences',
- 'OC_Search_Provider',
- 'OC_Search_Result',
- 'OC_Request',
- 'OC_Response',
- 'OC_Template',
- 'OC_User',
- 'OC_Util',
- ];
}
/**
@@ -138,7 +114,7 @@ class CodeChecker extends BasicEmitter {
$code = file_get_contents($file);
$statements = $this->parser->parse($code);
- $visitor = new CodeCheckVisitor($this->blackListedClassNames);
+ $visitor = new NodeVisitor($this->checkList);
$traverser = new NodeTraverser;
$traverser->addVisitor($visitor);
diff --git a/lib/private/app/codechecker/deprecationcheck.php b/lib/private/app/codechecker/deprecationcheck.php
new file mode 100644
index 00000000000..3b6dc968bb5
--- /dev/null
+++ b/lib/private/app/codechecker/deprecationcheck.php
@@ -0,0 +1,147 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\App\CodeChecker;
+
+class DeprecationCheck extends AbstractCheck implements ICheck {
+ /**
+ * @return string
+ */
+ protected function getLocalDescription() {
+ return 'deprecated';
+ }
+
+ /**
+ * @return array E.g.: `'ClassName' => 'oc version',`
+ */
+ protected function getLocalClasses() {
+ return [
+ 'OCP\Config' => '8.0.0',
+ 'OCP\Contacts' => '8.1.0',
+ 'OCP\DB' => '8.1.0',
+ 'OCP\IHelper' => '8.1.0',
+ 'OCP\JSON' => '8.1.0',
+ 'OCP\Response' => '8.1.0',
+ 'OCP\AppFramework\IApi' => '8.0.0',
+ ];
+ }
+
+ /**
+ * @return array E.g.: `'ClassName::CONSTANT_NAME' => 'oc version',`
+ */
+ protected function getLocalConstants() {
+ return [
+ 'OCP::PERMISSION_CREATE' => '8.0.0',
+ 'OCP::PERMISSION_READ' => '8.0.0',
+ 'OCP::PERMISSION_UPDATE' => '8.0.0',
+ 'OCP::PERMISSION_DELETE' => '8.0.0',
+ 'OCP::PERMISSION_SHARE' => '8.0.0',
+ 'OCP::PERMISSION_ALL' => '8.0.0',
+ 'OCP::FILENAME_INVALID_CHARS' => '8.0.0',
+ ];
+ }
+
+ /**
+ * @return array E.g.: `'functionName' => 'oc version',`
+ */
+ protected function getLocalFunctions() {
+ return [
+ 'OCP::image_path' => '8.0.0',
+ 'OCP::mimetype_icon' => '8.0.0',
+ 'OCP::preview_icon' => '8.0.0',
+ 'OCP::publicPreview_icon' => '8.0.0',
+ 'OCP::human_file_size' => '8.0.0',
+ 'OCP::relative_modified_date' => '8.0.0',
+ 'OCP::simple_file_size' => '8.0.0',
+ 'OCP::html_select_options' => '8.0.0',
+ ];
+ }
+
+ /**
+ * @return array E.g.: `'ClassName::methodName' => 'oc version',`
+ */
+ protected function getLocalMethods() {
+ return [
+ 'OCP\App::register' => '8.1.0',
+ 'OCP\App::addNavigationEntry' => '8.1.0',
+ 'OCP\App::setActiveNavigationEntry' => '8.1.0',
+
+ 'OCP\AppFramework\Controller::params' => '7.0.0',
+ 'OCP\AppFramework\Controller::getParams' => '7.0.0',
+ 'OCP\AppFramework\Controller::method' => '7.0.0',
+ 'OCP\AppFramework\Controller::getUploadedFile' => '7.0.0',
+ 'OCP\AppFramework\Controller::env' => '7.0.0',
+ 'OCP\AppFramework\Controller::cookie' => '7.0.0',
+ 'OCP\AppFramework\Controller::render' => '7.0.0',
+
+ 'OCP\AppFramework\IAppContainer::getCoreApi' => '8.0.0',
+ 'OCP\AppFramework\IAppContainer::isLoggedIn' => '8.0.0',
+ 'OCP\AppFramework\IAppContainer::isAdminUser' => '8.0.0',
+ 'OCP\AppFramework\IAppContainer::log' => '8.0.0',
+
+ 'OCP\BackgroundJob::addQueuedTask' => '6.0.0',
+ 'OCP\BackgroundJob::addRegularTask' => '6.0.0',
+ 'OCP\BackgroundJob::allQueuedTasks' => '6.0.0',
+ 'OCP\BackgroundJob::allRegularTasks' => '6.0.0',
+ 'OCP\BackgroundJob::deleteQueuedTask' => '6.0.0',
+ 'OCP\BackgroundJob::findQueuedTask' => '6.0.0',
+ 'OCP\BackgroundJob::queuedTaskWhereAppIs' => '6.0.0',
+ 'OCP\BackgroundJob::registerJob' => '8.1.0',
+
+ 'OCP\Files::tmpFile' => '8.1.0',
+ 'OCP\Files::tmpFolder' => '8.1.0',
+
+ 'OCP\IAppConfig::getValue' => '8.0.0',
+ 'OCP\IAppConfig::deleteKey' => '8.0.0',
+ 'OCP\IAppConfig::getKeys' => '8.0.0',
+ 'OCP\IAppConfig::setValue' => '8.0.0',
+ 'OCP\IAppConfig::deleteApp' => '8.0.0',
+
+ 'OCP\ISearch::search' => '8.0.0',
+
+ 'OCP\IServerContainer::getDb' => '8.1.0',
+ 'OCP\IServerContainer::getHTTPHelper' => '8.1.0',
+
+ 'OCP\User::getUser' => '8.0.0',
+ 'OCP\User::getUsers' => '8.1.0',
+ 'OCP\User::getDisplayName' => '8.1.0',
+ 'OCP\User::getDisplayNames' => '8.1.0',
+ 'OCP\User::userExists' => '8.1.0',
+ 'OCP\User::logout' => '8.1.0',
+ 'OCP\User::checkPassword' => '8.1.0',
+
+ 'OCP\Util::sendMail' => '8.1.0',
+ 'OCP\Util::formatDate' => '8.0.0',
+ 'OCP\Util::encryptedFiles' => '8.1.0',
+ 'OCP\Util::linkToRoute' => '8.1.0',
+ 'OCP\Util::linkTo' => '8.1.0',
+ 'OCP\Util::getServerHost' => '8.1.0',
+ 'OCP\Util::getServerProtocol' => '8.1.0',
+ 'OCP\Util::getRequestUri' => '8.1.0',
+ 'OCP\Util::getScriptName' => '8.1.0',
+ 'OCP\Util::imagePath' => '8.1.0',
+ 'OCP\Util::isValidFileName' => '8.1.0',
+ 'OCP\Util::generateRandomBytes' => '8.1.0',
+ 'OCP\Util::mb_str_replace' => '8.2.0',
+ 'OCP\Util::mb_substr_replace' => '8.2.0',
+ ];
+ }
+}
diff --git a/lib/private/app/codechecker/emptycheck.php b/lib/private/app/codechecker/emptycheck.php
new file mode 100644
index 00000000000..0e5df55d090
--- /dev/null
+++ b/lib/private/app/codechecker/emptycheck.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+namespace OC\App\CodeChecker;
+
+class EmptyCheck implements ICheck {
+ /**
+ * @param int $errorCode
+ * @param string $errorObject
+ * @return string
+ */
+ public function getDescription($errorCode, $errorObject) {
+ return '';
+ }
+
+ /**
+ * @return array E.g.: `'ClassName' => 'oc version',`
+ */
+ public function getClasses() {
+ return [];
+ }
+
+ /**
+ * @return array E.g.: `'ClassName::CONSTANT_NAME' => 'oc version',`
+ */
+ public function getConstants() {
+ return [];
+ }
+
+ /**
+ * @return array E.g.: `'functionName' => 'oc version',`
+ */
+ public function getFunctions() {
+ return [];
+ }
+
+ /**
+ * @return array E.g.: `'ClassName::methodName' => 'oc version',`
+ */
+ public function getMethods() {
+ return [];
+ }
+
+ /**
+ * @return bool
+ */
+ public function checkStrongComparisons() {
+ return false;
+ }
+}
diff --git a/lib/private/app/codechecker/icheck.php b/lib/private/app/codechecker/icheck.php
new file mode 100644
index 00000000000..a00e0d8fa13
--- /dev/null
+++ b/lib/private/app/codechecker/icheck.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+namespace OC\App\CodeChecker;
+
+interface ICheck {
+ /**
+ * @param int $errorCode
+ * @param string $errorObject
+ * @return string
+ */
+ public function getDescription($errorCode, $errorObject);
+
+ /**
+ * @return array E.g.: `'ClassName' => 'oc version',`
+ */
+ public function getClasses();
+
+ /**
+ * @return array E.g.: `'ClassName::CONSTANT_NAME' => 'oc version',`
+ */
+ public function getConstants();
+
+ /**
+ * @return array E.g.: `'functionName' => 'oc version',`
+ */
+ public function getFunctions();
+
+ /**
+ * @return array E.g.: `'ClassName::methodName' => 'oc version',`
+ */
+ public function getMethods();
+
+ /**
+ * @return bool
+ */
+ public function checkStrongComparisons();
+}
diff --git a/lib/private/app/codechecker/nodevisitor.php b/lib/private/app/codechecker/nodevisitor.php
new file mode 100644
index 00000000000..a22f852f36a
--- /dev/null
+++ b/lib/private/app/codechecker/nodevisitor.php
@@ -0,0 +1,306 @@
+<?php
+/**
+ * @author Morris Jobke <hey@morrisjobke.de>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\App\CodeChecker;
+
+use PhpParser\Node;
+use PhpParser\Node\Name;
+use PhpParser\NodeVisitorAbstract;
+
+class NodeVisitor extends NodeVisitorAbstract {
+ /** @var ICheck */
+ protected $list;
+
+ /** @var string */
+ protected $blackListDescription;
+ /** @var string[] */
+ protected $blackListedClassNames;
+ /** @var string[] */
+ protected $blackListedConstants;
+ /** @var string[] */
+ protected $blackListedFunctions;
+ /** @var string[] */
+ protected $blackListedMethods;
+ /** @var bool */
+ protected $checkEqualOperatorUsage;
+ /** @var string[] */
+ protected $errorMessages;
+
+ /**
+ * @param ICheck $list
+ */
+ public function __construct(ICheck $list) {
+ $this->list = $list;
+
+ $this->blackListedClassNames = [];
+ foreach ($list->getClasses() as $class => $blackListInfo) {
+ if (is_numeric($class) && is_string($blackListInfo)) {
+ $class = $blackListInfo;
+ $blackListInfo = null;
+ }
+
+ $class = strtolower($class);
+ $this->blackListedClassNames[$class] = $class;
+ }
+
+ $this->blackListedConstants = [];
+ foreach ($list->getConstants() as $constantName => $blackListInfo) {
+ $constantName = strtolower($constantName);
+ $this->blackListedConstants[$constantName] = $constantName;
+ }
+
+ $this->blackListedFunctions = [];
+ foreach ($list->getFunctions() as $functionName => $blackListInfo) {
+ $functionName = strtolower($functionName);
+ $this->blackListedFunctions[$functionName] = $functionName;
+ }
+
+ $this->blackListedMethods = [];
+ foreach ($list->getMethods() as $functionName => $blackListInfo) {
+ $functionName = strtolower($functionName);
+ $this->blackListedMethods[$functionName] = $functionName;
+ }
+
+ $this->checkEqualOperatorUsage = $list->checkStrongComparisons();
+
+ $this->errorMessages = [
+ CodeChecker::CLASS_EXTENDS_NOT_ALLOWED => "%s class must not be extended",
+ CodeChecker::CLASS_IMPLEMENTS_NOT_ALLOWED => "%s interface must not be implemented",
+ CodeChecker::STATIC_CALL_NOT_ALLOWED => "Static method of %s class must not be called",
+ CodeChecker::CLASS_CONST_FETCH_NOT_ALLOWED => "Constant of %s class must not not be fetched",
+ CodeChecker::CLASS_NEW_NOT_ALLOWED => "%s class must not be instantiated",
+ CodeChecker::CLASS_USE_NOT_ALLOWED => "%s class must not be imported with a use statement",
+ CodeChecker::CLASS_METHOD_CALL_NOT_ALLOWED => "Method of %s class must not be called",
+
+ CodeChecker::OP_OPERATOR_USAGE_DISCOURAGED => "is discouraged",
+ ];
+ }
+
+ /** @var array */
+ public $errors = [];
+
+ public function enterNode(Node $node) {
+ if ($this->checkEqualOperatorUsage && $node instanceof Node\Expr\BinaryOp\Equal) {
+ $this->errors[]= [
+ 'disallowedToken' => '==',
+ 'errorCode' => CodeChecker::OP_OPERATOR_USAGE_DISCOURAGED,
+ 'line' => $node->getLine(),
+ 'reason' => $this->buildReason('==', CodeChecker::OP_OPERATOR_USAGE_DISCOURAGED)
+ ];
+ }
+ if ($this->checkEqualOperatorUsage && $node instanceof Node\Expr\BinaryOp\NotEqual) {
+ $this->errors[]= [
+ 'disallowedToken' => '!=',
+ 'errorCode' => CodeChecker::OP_OPERATOR_USAGE_DISCOURAGED,
+ 'line' => $node->getLine(),
+ 'reason' => $this->buildReason('!=', CodeChecker::OP_OPERATOR_USAGE_DISCOURAGED)
+ ];
+ }
+ if ($node instanceof Node\Stmt\Class_) {
+ if (!is_null($node->extends)) {
+ $this->checkBlackList($node->extends->toString(), CodeChecker::CLASS_EXTENDS_NOT_ALLOWED, $node);
+ }
+ foreach ($node->implements as $implements) {
+ $this->checkBlackList($implements->toString(), CodeChecker::CLASS_IMPLEMENTS_NOT_ALLOWED, $node);
+ }
+ }
+ if ($node instanceof Node\Expr\StaticCall) {
+ if (!is_null($node->class)) {
+ if ($node->class instanceof Name) {
+ $this->checkBlackList($node->class->toString(), CodeChecker::STATIC_CALL_NOT_ALLOWED, $node);
+
+ $this->checkBlackListFunction($node->class->toString(), $node->name, $node);
+ $this->checkBlackListMethod($node->class->toString(), $node->name, $node);
+ }
+
+ if ($node->class instanceof Node\Expr\Variable) {
+ /**
+ * TODO: find a way to detect something like this:
+ * $c = "OC_API";
+ * $n = $c::call();
+ */
+ // $this->checkBlackListMethod($node->class->..., $node->name, $node);
+ }
+ }
+ }
+ if ($node instanceof Node\Expr\MethodCall) {
+ if (!is_null($node->var)) {
+ if ($node->var instanceof Node\Expr\Variable) {
+ /**
+ * TODO: find a way to detect something like this:
+ * $c = new OC_API();
+ * $n = $c::call();
+ * $n = $c->call();
+ */
+ // $this->checkBlackListMethod($node->var->..., $node->name, $node);
+ }
+ }
+ }
+ if ($node instanceof Node\Expr\ClassConstFetch) {
+ if (!is_null($node->class)) {
+ if ($node->class instanceof Name) {
+ $this->checkBlackList($node->class->toString(), CodeChecker::CLASS_CONST_FETCH_NOT_ALLOWED, $node);
+ }
+ if ($node->class instanceof Node\Expr\Variable) {
+ /**
+ * TODO: find a way to detect something like this:
+ * $c = "OC_API";
+ * $n = $i::ADMIN_AUTH;
+ */
+ }
+
+ $this->checkBlackListConstant($node->class->toString(), $node->name, $node);
+ }
+ }
+ if ($node instanceof Node\Expr\New_) {
+ if (!is_null($node->class)) {
+ if ($node->class instanceof Name) {
+ $this->checkBlackList($node->class->toString(), CodeChecker::CLASS_NEW_NOT_ALLOWED, $node);
+ }
+ if ($node->class instanceof Node\Expr\Variable) {
+ /**
+ * TODO: find a way to detect something like this:
+ * $c = "OC_API";
+ * $n = new $i;
+ */
+ }
+ }
+ }
+ if ($node instanceof Node\Stmt\UseUse) {
+ $this->checkBlackList($node->name->toString(), CodeChecker::CLASS_USE_NOT_ALLOWED, $node);
+ if ($node->alias) {
+ $this->addUseNameToBlackList($node->name->toString(), $node->alias);
+ } else {
+ $this->addUseNameToBlackList($node->name->toString(), $node->name->getLast());
+ }
+ }
+ }
+
+ /**
+ * Check whether an alias was introduced for a namespace of a blacklisted class
+ *
+ * Example:
+ * - Blacklist entry: OCP\AppFramework\IApi
+ * - Name: OCP\AppFramework
+ * - Alias: OAF
+ * => new blacklist entry: OAF\IApi
+ *
+ * @param string $name
+ * @param string $alias
+ */
+ private function addUseNameToBlackList($name, $alias) {
+ $name = strtolower($name);
+ $alias = strtolower($alias);
+
+ foreach ($this->blackListedClassNames as $blackListedAlias => $blackListedClassName) {
+ if (strpos($blackListedClassName, $name . '\\') === 0) {
+ $aliasedClassName = str_replace($name, $alias, $blackListedClassName);
+ $this->blackListedClassNames[$aliasedClassName] = $blackListedClassName;
+ }
+ }
+
+ foreach ($this->blackListedConstants as $blackListedAlias => $blackListedConstant) {
+ if (strpos($blackListedConstant, $name . '\\') === 0 || strpos($blackListedConstant, $name . '::') === 0) {
+ $aliasedConstantName = str_replace($name, $alias, $blackListedConstant);
+ $this->blackListedConstants[$aliasedConstantName] = $blackListedConstant;
+ }
+ }
+
+ foreach ($this->blackListedFunctions as $blackListedAlias => $blackListedFunction) {
+ if (strpos($blackListedFunction, $name . '\\') === 0 || strpos($blackListedFunction, $name . '::') === 0) {
+ $aliasedFunctionName = str_replace($name, $alias, $blackListedFunction);
+ $this->blackListedFunctions[$aliasedFunctionName] = $blackListedFunction;
+ }
+ }
+
+ foreach ($this->blackListedMethods as $blackListedAlias => $blackListedMethod) {
+ if (strpos($blackListedMethod, $name . '\\') === 0 || strpos($blackListedMethod, $name . '::') === 0) {
+ $aliasedMethodName = str_replace($name, $alias, $blackListedMethod);
+ $this->blackListedMethods[$aliasedMethodName] = $blackListedMethod;
+ }
+ }
+ }
+
+ private function checkBlackList($name, $errorCode, Node $node) {
+ $lowerName = strtolower($name);
+
+ if (isset($this->blackListedClassNames[$lowerName])) {
+ $this->errors[]= [
+ 'disallowedToken' => $name,
+ 'errorCode' => $errorCode,
+ 'line' => $node->getLine(),
+ 'reason' => $this->buildReason($this->blackListedClassNames[$lowerName], $errorCode)
+ ];
+ }
+ }
+
+ private function checkBlackListConstant($class, $constantName, Node $node) {
+ $name = $class . '::' . $constantName;
+ $lowerName = strtolower($name);
+
+ if (isset($this->blackListedConstants[$lowerName])) {
+ $this->errors[]= [
+ 'disallowedToken' => $name,
+ 'errorCode' => CodeChecker::CLASS_CONST_FETCH_NOT_ALLOWED,
+ 'line' => $node->getLine(),
+ 'reason' => $this->buildReason($this->blackListedConstants[$lowerName], CodeChecker::CLASS_CONST_FETCH_NOT_ALLOWED)
+ ];
+ }
+ }
+
+ private function checkBlackListFunction($class, $functionName, Node $node) {
+ $name = $class . '::' . $functionName;
+ $lowerName = strtolower($name);
+
+ if (isset($this->blackListedFunctions[$lowerName])) {
+ $this->errors[]= [
+ 'disallowedToken' => $name,
+ 'errorCode' => CodeChecker::STATIC_CALL_NOT_ALLOWED,
+ 'line' => $node->getLine(),
+ 'reason' => $this->buildReason($this->blackListedFunctions[$lowerName], CodeChecker::STATIC_CALL_NOT_ALLOWED)
+ ];
+ }
+ }
+
+ private function checkBlackListMethod($class, $functionName, Node $node) {
+ $name = $class . '::' . $functionName;
+ $lowerName = strtolower($name);
+
+ if (isset($this->blackListedMethods[$lowerName])) {
+ $this->errors[]= [
+ 'disallowedToken' => $name,
+ 'errorCode' => CodeChecker::CLASS_METHOD_CALL_NOT_ALLOWED,
+ 'line' => $node->getLine(),
+ 'reason' => $this->buildReason($this->blackListedMethods[$lowerName], CodeChecker::CLASS_METHOD_CALL_NOT_ALLOWED)
+ ];
+ }
+ }
+
+ private function buildReason($name, $errorCode) {
+ if (isset($this->errorMessages[$errorCode])) {
+ $desc = $this->list->getDescription($errorCode, $name);
+ return sprintf($this->errorMessages[$errorCode], $desc);
+ }
+
+ return "$name usage not allowed - error: $errorCode";
+ }
+}
diff --git a/lib/private/app/codechecker/privatecheck.php b/lib/private/app/codechecker/privatecheck.php
new file mode 100644
index 00000000000..d6f4eb06981
--- /dev/null
+++ b/lib/private/app/codechecker/privatecheck.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ * @author Morris Jobke <hey@morrisjobke.de>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\App\CodeChecker;
+
+class PrivateCheck extends AbstractCheck implements ICheck {
+ /**
+ * @return string
+ */
+ protected function getLocalDescription() {
+ return 'private';
+ }
+
+ /**
+ * @return array
+ */
+ public function getLocalClasses() {
+ return [
+ // classes replaced by the public api
+ 'OC_API' => '6.0.0',
+ 'OC_App' => '6.0.0',
+ 'OC_AppConfig' => '6.0.0',
+ 'OC_Avatar' => '6.0.0',
+ 'OC_BackgroundJob' => '6.0.0',
+ 'OC_Config' => '6.0.0',
+ 'OC_DB' => '6.0.0',
+ 'OC_Files' => '6.0.0',
+ 'OC_Helper' => '6.0.0',
+ 'OC_Hook' => '6.0.0',
+ 'OC_Image' => '6.0.0',
+ 'OC_JSON' => '6.0.0',
+ 'OC_L10N' => '6.0.0',
+ 'OC_Log' => '6.0.0',
+ 'OC_Mail' => '6.0.0',
+ 'OC_Preferences' => '6.0.0',
+ 'OC_Search_Provider' => '6.0.0',
+ 'OC_Search_Result' => '6.0.0',
+ 'OC_Request' => '6.0.0',
+ 'OC_Response' => '6.0.0',
+ 'OC_Template' => '6.0.0',
+ 'OC_User' => '6.0.0',
+ 'OC_Util' => '6.0.0',
+ ];
+ }
+
+ /**
+ * @return array
+ */
+ public function getLocalConstants() {
+ return [];
+ }
+
+ /**
+ * @return array
+ */
+ public function getLocalFunctions() {
+ return [];
+ }
+
+ /**
+ * @return array
+ */
+ public function getLocalMethods() {
+ return [];
+ }
+}
diff --git a/lib/private/app/codechecker/strongcomparisoncheck.php b/lib/private/app/codechecker/strongcomparisoncheck.php
new file mode 100644
index 00000000000..7de0fe3e5c3
--- /dev/null
+++ b/lib/private/app/codechecker/strongcomparisoncheck.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ * @author Morris Jobke <hey@morrisjobke.de>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\App\CodeChecker;
+
+class StrongComparisonCheck implements ICheck {
+ /** @var ICheck */
+ protected $check;
+
+ /**
+ * @param ICheck $check
+ */
+ public function __construct(ICheck $check) {
+ $this->check = $check;
+ }
+
+ /**
+ * @param int $errorCode
+ * @param string $errorObject
+ * @return string
+ */
+ public function getDescription($errorCode, $errorObject) {
+ return $this->check->getDescription($errorCode, $errorObject);
+ }
+
+ /**
+ * @return array
+ */
+ public function getClasses() {
+ return $this->check->getClasses();
+ }
+
+ /**
+ * @return array
+ */
+ public function getConstants() {
+ return $this->check->getConstants();
+ }
+
+ /**
+ * @return array
+ */
+ public function getFunctions() {
+ return $this->check->getFunctions();
+ }
+
+ /**
+ * @return array
+ */
+ public function getMethods() {
+ return $this->check->getMethods();
+ }
+
+ /**
+ * @return bool
+ */
+ public function checkStrongComparisons() {
+ return true;
+ }
+}
diff --git a/lib/private/app/codecheckvisitor.php b/lib/private/app/codecheckvisitor.php
deleted file mode 100644
index e983bd8630b..00000000000
--- a/lib/private/app/codecheckvisitor.php
+++ /dev/null
@@ -1,133 +0,0 @@
-<?php
-/**
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OC\App;
-
-use PhpParser\Node;
-use PhpParser\Node\Name;
-use PhpParser\NodeVisitorAbstract;
-
-class CodeCheckVisitor extends NodeVisitorAbstract {
-
- public function __construct($blackListedClassNames) {
- $this->blackListedClassNames = array_map('strtolower', $blackListedClassNames);
- }
-
- public $errors = [];
-
- public function enterNode(Node $node) {
- if ($node instanceof Node\Expr\BinaryOp\Equal) {
- $this->errors[]= [
- 'disallowedToken' => '==',
- 'errorCode' => CodeChecker::OP_OPERATOR_USAGE_DISCOURAGED,
- 'line' => $node->getLine(),
- 'reason' => $this->buildReason('==', CodeChecker::OP_OPERATOR_USAGE_DISCOURAGED)
- ];
- }
- if ($node instanceof Node\Expr\BinaryOp\NotEqual) {
- $this->errors[]= [
- 'disallowedToken' => '!=',
- 'errorCode' => CodeChecker::OP_OPERATOR_USAGE_DISCOURAGED,
- 'line' => $node->getLine(),
- 'reason' => $this->buildReason('!=', CodeChecker::OP_OPERATOR_USAGE_DISCOURAGED)
- ];
- }
- if ($node instanceof Node\Stmt\Class_) {
- if (!is_null($node->extends)) {
- $this->checkBlackList($node->extends->toString(), CodeChecker::CLASS_EXTENDS_NOT_ALLOWED, $node);
- }
- foreach ($node->implements as $implements) {
- $this->checkBlackList($implements->toString(), CodeChecker::CLASS_IMPLEMENTS_NOT_ALLOWED, $node);
- }
- }
- if ($node instanceof Node\Expr\StaticCall) {
- if (!is_null($node->class)) {
- if ($node->class instanceof Name) {
- $this->checkBlackList($node->class->toString(), CodeChecker::STATIC_CALL_NOT_ALLOWED, $node);
- }
- if ($node->class instanceof Node\Expr\Variable) {
- /**
- * TODO: find a way to detect something like this:
- * $c = "OC_API";
- * $n = $i::call();
- */
- }
- }
- }
- if ($node instanceof Node\Expr\ClassConstFetch) {
- if (!is_null($node->class)) {
- if ($node->class instanceof Name) {
- $this->checkBlackList($node->class->toString(), CodeChecker::CLASS_CONST_FETCH_NOT_ALLOWED, $node);
- }
- if ($node->class instanceof Node\Expr\Variable) {
- /**
- * TODO: find a way to detect something like this:
- * $c = "OC_API";
- * $n = $i::ADMIN_AUTH;
- */
- }
- }
- }
- if ($node instanceof Node\Expr\New_) {
- if (!is_null($node->class)) {
- if ($node->class instanceof Name) {
- $this->checkBlackList($node->class->toString(), CodeChecker::CLASS_NEW_FETCH_NOT_ALLOWED, $node);
- }
- if ($node->class instanceof Node\Expr\Variable) {
- /**
- * TODO: find a way to detect something like this:
- * $c = "OC_API";
- * $n = new $i;
- */
- }
- }
- }
- }
-
- private function checkBlackList($name, $errorCode, Node $node) {
- if (in_array(strtolower($name), $this->blackListedClassNames)) {
- $this->errors[]= [
- 'disallowedToken' => $name,
- 'errorCode' => $errorCode,
- 'line' => $node->getLine(),
- 'reason' => $this->buildReason($name, $errorCode)
- ];
- }
- }
-
- private function buildReason($name, $errorCode) {
- static $errorMessages= [
- CodeChecker::CLASS_EXTENDS_NOT_ALLOWED => "used as base class",
- CodeChecker::CLASS_IMPLEMENTS_NOT_ALLOWED => "used as interface",
- CodeChecker::STATIC_CALL_NOT_ALLOWED => "static method call on private class",
- CodeChecker::CLASS_CONST_FETCH_NOT_ALLOWED => "used to fetch a const from",
- CodeChecker::CLASS_NEW_FETCH_NOT_ALLOWED => "is instanciated",
- CodeChecker::OP_OPERATOR_USAGE_DISCOURAGED => "is discouraged"
- ];
-
- if (isset($errorMessages[$errorCode])) {
- return $errorMessages[$errorCode];
- }
-
- return "$name usage not allowed - error: $errorCode";
- }
-}