Page MenuHomePhabricator

D9187.id21818.diff
No OneTemporary

D9187.id21818.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -32,6 +32,7 @@
'ArcanistCSharpLinter' => 'lint/linter/ArcanistCSharpLinter.php',
'ArcanistCallConduitWorkflow' => 'workflow/ArcanistCallConduitWorkflow.php',
'ArcanistCapabilityNotSupportedException' => 'workflow/exception/ArcanistCapabilityNotSupportedException.php',
+ 'ArcanistChmodLinter' => 'lint/linter/ArcanistChmodLinter.php',
'ArcanistChooseInvalidRevisionException' => 'exception/ArcanistChooseInvalidRevisionException.php',
'ArcanistChooseNoRevisionsException' => 'exception/ArcanistChooseNoRevisionsException.php',
'ArcanistCloseRevisionWorkflow' => 'workflow/ArcanistCloseRevisionWorkflow.php',
@@ -222,6 +223,7 @@
'ArcanistCSharpLinter' => 'ArcanistLinter',
'ArcanistCallConduitWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistCapabilityNotSupportedException' => 'Exception',
+ 'ArcanistChmodLinter' => 'ArcanistLinter',
'ArcanistChooseInvalidRevisionException' => 'Exception',
'ArcanistChooseNoRevisionsException' => 'Exception',
'ArcanistCloseRevisionWorkflow' => 'ArcanistBaseWorkflow',
diff --git a/src/lint/linter/ArcanistChmodLinter.php b/src/lint/linter/ArcanistChmodLinter.php
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/ArcanistChmodLinter.php
@@ -0,0 +1,116 @@
+<?php
+
+/**
+ * Ensures that files are not executable unnecessarily.
+ */
+final class ArcanistChmodLinter extends ArcanistLinter {
+
+ const LINT_INVALID_EXECUTABLE = 1;
+ const LINT_MISSING_SHEBANG = 2;
+
+ public function getInfoName() {
+ return 'Chmod';
+ }
+
+ public function getInfoDescription() {
+ return pht(
+ 'Checks the permissions on files and ensures that files are not made to
+ be executable unnecessarily.');
+ }
+
+ public function getLinterName() {
+ return 'CHMOD';
+ }
+
+ public function getLinterConfigurationName() {
+ return 'chmod';
+ }
+
+ public function shouldLintBinaryFiles() {
+ return true;
+ }
+
+ public function getLintNameMap() {
+ return array(
+ self::LINT_INVALID_EXECUTABLE => pht('Invalid Executable'),
+ self::LINT_MISSING_SHEBANG => pht('Missing Shebang'),
+ );
+ }
+
+ public function getLintSeverityMap() {
+ return array(
+ self::LINT_INVALID_EXECUTABLE => ArcanistLintSeverity::SEVERITY_WARNING,
+ self::LINT_MISSING_SHEBANG => ArcanistLintSeverity::SEVERITY_WARNING,
+ );
+ }
+
+ public function lintPath($path) {
+ if (is_executable($path)) {
+ $mime = Filesystem::getMimeType($path);
+
+ if (in_array($mime, $this->getExecutableMimeTypes())) {
+ // Path is a valid executable.
+ return;
+ } else if (in_array($mime, $this->getScriptMimeTypes())) {
+ // Path is a script, which //can// be an executable but should contain
+ // a shebang.
+ if ($this->getShebang($path)) {
+ return;
+ } else {
+ $this->raiseLintAtPath(
+ self::LINT_MISSING_SHEBANG,
+ pht("'%s' files should have a valid shebang.", $mime));
+ }
+ } else {
+ $this->raiseLintAtPath(
+ self::LINT_INVALID_EXECUTABLE,
+ pht("'%s' files should not be executable.", $mime));
+ }
+ }
+ }
+
+ /**
+ * Returns the path's shebang.
+ *
+ * @param string
+ * @return string|null
+ */
+ private function getShebang($path) {
+ $line = head(phutil_split_lines($this->getEngine()->loadData($path), true));
+
+ $matches = array();
+ if (preg_match('/^#!(.*)$/', $line, $matches)) {
+ return $matches[1];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns an array which contains mime types which are executable.
+ *
+ * @return list<string>
+ */
+ private function getExecutableMimeTypes() {
+ return array(
+ 'text/x-executable',
+ );
+ }
+
+ /**
+ * Returns an array which contains mime types which are executable when the
+ * file contains a shebang.
+ *
+ * @return list<string>
+ */
+ private function getScriptMimeTypes() {
+ return array(
+ 'application/javascript',
+ 'text/plain',
+ 'text/x-perl',
+ 'text/x-php',
+ 'text/x-python',
+ 'text/x-shellscript',
+ );
+ }
+}

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 20, 9:49 AM (3 d, 4 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7712922
Default Alt Text
D9187.id21818.diff (4 KB)

Event Timeline