diff --git a/src/main/java/com/bartek/esa/EsaMain.java b/src/main/java/com/bartek/esa/EsaMain.java index ad51531..d686239 100644 --- a/src/main/java/com/bartek/esa/EsaMain.java +++ b/src/main/java/com/bartek/esa/EsaMain.java @@ -17,7 +17,6 @@ import javax.inject.Inject; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; -import java.io.IOException; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; diff --git a/src/main/java/com/bartek/esa/analyser/apk/ApkAnalyser.java b/src/main/java/com/bartek/esa/analyser/apk/ApkAnalyser.java index 41fd4ce..a9d07d0 100644 --- a/src/main/java/com/bartek/esa/analyser/apk/ApkAnalyser.java +++ b/src/main/java/com/bartek/esa/analyser/apk/ApkAnalyser.java @@ -1,6 +1,7 @@ package com.bartek.esa.analyser.apk; import com.bartek.esa.analyser.core.Analyser; +import com.bartek.esa.context.constructor.ContextConstructor; import com.bartek.esa.core.archetype.Plugin; import com.bartek.esa.core.executor.PluginExecutor; import com.bartek.esa.decompiler.archetype.Decompiler; @@ -19,8 +20,8 @@ public class ApkAnalyser extends Analyser { private final FileCleaner fileCleaner; private final GlobMatcher globMatcher; - public ApkAnalyser(PluginExecutor pluginExecutor, Set plugins, FileProvider fileProvider, Decompiler decompiler, FileCleaner fileCleaner, GlobMatcher globMatcher) { - super(pluginExecutor, plugins, fileProvider); + public ApkAnalyser(PluginExecutor pluginExecutor, Set plugins, FileProvider fileProvider, Decompiler decompiler, FileCleaner fileCleaner, GlobMatcher globMatcher, ContextConstructor contextConstructor) { + super(pluginExecutor, plugins, fileProvider, contextConstructor); this.decompiler = decompiler; this.fileCleaner = fileCleaner; this.globMatcher = globMatcher; diff --git a/src/main/java/com/bartek/esa/analyser/core/Analyser.java b/src/main/java/com/bartek/esa/analyser/core/Analyser.java index f571697..b824349 100644 --- a/src/main/java/com/bartek/esa/analyser/core/Analyser.java +++ b/src/main/java/com/bartek/esa/analyser/core/Analyser.java @@ -1,5 +1,7 @@ package com.bartek.esa.analyser.core; +import com.bartek.esa.context.constructor.ContextConstructor; +import com.bartek.esa.context.model.Context; import com.bartek.esa.core.archetype.Plugin; import com.bartek.esa.core.executor.PluginExecutor; import com.bartek.esa.core.model.object.Issue; @@ -7,31 +9,34 @@ import com.bartek.esa.error.EsaException; import com.bartek.esa.file.provider.FileProvider; import java.io.File; -import java.util.Collections; import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; -import java.util.stream.Stream; public abstract class Analyser { private final PluginExecutor pluginExecutor; private final Set plugins; private final FileProvider fileProvider; + private final ContextConstructor contextConstructor; - public Analyser(PluginExecutor pluginExecutor, Set plugins, FileProvider fileProvider) { + public Analyser(PluginExecutor pluginExecutor, Set plugins, FileProvider fileProvider, ContextConstructor contextConstructor) { this.pluginExecutor = pluginExecutor; this.plugins = plugins; this.fileProvider = fileProvider; + this.contextConstructor = contextConstructor; } public Set analyse(String source, Set pluginCodes, Set excludeCodes, boolean debug) { String newSource = prepareSources(source, debug); File manifest = getManifest(newSource); - Set files = getFiles(newSource); - Set selectedPlugins = getPlugins(pluginCodes, excludeCodes); + Set javaSources = getJavaSources(newSource); + Set layoutFiles = getLayoutFiles(newSource); + Context context = contextConstructor.construct(manifest, javaSources, layoutFiles); + + Set selectedPlugins = getPlugins(pluginCodes, excludeCodes); + Set issues = pluginExecutor.executeForContext(context, selectedPlugins, debug); - Set issues = pluginExecutor.executeForFiles(manifest, files, selectedPlugins, debug); performCleaning(newSource, debug); return issues; } @@ -60,14 +65,12 @@ public abstract class Analyser { return (File) (manifests.toArray())[0]; } - private Set getFiles(String source) { - Set javaFiles = fileProvider.getGlobMatchedFiles(source, getJavaGlob()); - Set layoutFiles = fileProvider.getGlobMatchedFiles(source, getLayoutGlob()); - Set androidManifest = Collections.singleton(getManifest(source)); + private Set getJavaSources(String source) { + return fileProvider.getGlobMatchedFiles(source, getJavaGlob()); + } - return Stream.of(javaFiles, androidManifest, layoutFiles) - .flatMap(Set::stream) - .collect(Collectors.toSet()); + private Set getLayoutFiles(String source) { + return fileProvider.getGlobMatchedFiles(source, getLayoutGlob()); } private Set getPlugins(Set pluginCodes, Set excludeCodes) { diff --git a/src/main/java/com/bartek/esa/analyser/di/AnalyserModule.java b/src/main/java/com/bartek/esa/analyser/di/AnalyserModule.java index e8a3b0e..10a9d98 100644 --- a/src/main/java/com/bartek/esa/analyser/di/AnalyserModule.java +++ b/src/main/java/com/bartek/esa/analyser/di/AnalyserModule.java @@ -2,6 +2,7 @@ package com.bartek.esa.analyser.di; import com.bartek.esa.analyser.apk.ApkAnalyser; import com.bartek.esa.analyser.source.SourceAnalyser; +import com.bartek.esa.context.constructor.ContextConstructor; import com.bartek.esa.core.archetype.Plugin; import com.bartek.esa.core.executor.PluginExecutor; import com.bartek.esa.decompiler.archetype.Decompiler; @@ -17,12 +18,12 @@ import java.util.Set; public class AnalyserModule { @Provides - public SourceAnalyser sourceAnalyser(PluginExecutor pluginExecutor, Set plugins, FileProvider fileProvider) { - return new SourceAnalyser(pluginExecutor, plugins, fileProvider); + public SourceAnalyser sourceAnalyser(PluginExecutor pluginExecutor, Set plugins, FileProvider fileProvider, ContextConstructor contextConstructor) { + return new SourceAnalyser(pluginExecutor, plugins, fileProvider, contextConstructor); } @Provides - public ApkAnalyser apkAnalyser(PluginExecutor pluginExecutor, Set plugins, FileProvider fileProvider, Decompiler decompiler, FileCleaner fileCleaner, GlobMatcher globMatcher) { - return new ApkAnalyser(pluginExecutor, plugins, fileProvider, decompiler, fileCleaner, globMatcher); + public ApkAnalyser apkAnalyser(PluginExecutor pluginExecutor, Set plugins, FileProvider fileProvider, Decompiler decompiler, FileCleaner fileCleaner, GlobMatcher globMatcher, ContextConstructor contextConstructor) { + return new ApkAnalyser(pluginExecutor, plugins, fileProvider, decompiler, fileCleaner, globMatcher, contextConstructor); } } diff --git a/src/main/java/com/bartek/esa/analyser/source/SourceAnalyser.java b/src/main/java/com/bartek/esa/analyser/source/SourceAnalyser.java index f55650a..d26e4d7 100644 --- a/src/main/java/com/bartek/esa/analyser/source/SourceAnalyser.java +++ b/src/main/java/com/bartek/esa/analyser/source/SourceAnalyser.java @@ -1,6 +1,7 @@ package com.bartek.esa.analyser.source; import com.bartek.esa.analyser.core.Analyser; +import com.bartek.esa.context.constructor.ContextConstructor; import com.bartek.esa.core.archetype.Plugin; import com.bartek.esa.core.executor.PluginExecutor; import com.bartek.esa.error.EsaException; @@ -14,8 +15,8 @@ public class SourceAnalyser extends Analyser { private static final String JAVA_GLOB = "**/*.java"; private static final String LAYOUT_GLOB = "**/res/layout*/*.xml"; - public SourceAnalyser(PluginExecutor pluginExecutor, Set plugins, FileProvider fileProvider) { - super(pluginExecutor, plugins, fileProvider); + public SourceAnalyser(PluginExecutor pluginExecutor, Set plugins, FileProvider fileProvider, ContextConstructor contextConstructor) { + super(pluginExecutor, plugins, fileProvider, contextConstructor); } @Override diff --git a/src/main/java/com/bartek/esa/context/constructor/ContextConstructor.java b/src/main/java/com/bartek/esa/context/constructor/ContextConstructor.java new file mode 100644 index 0000000..47030fc --- /dev/null +++ b/src/main/java/com/bartek/esa/context/constructor/ContextConstructor.java @@ -0,0 +1,116 @@ +package com.bartek.esa.context.constructor; + +import com.bartek.esa.context.model.Context; +import com.bartek.esa.context.model.Source; +import com.bartek.esa.core.xml.XmlHelper; +import com.bartek.esa.error.EsaException; +import com.bartek.esa.file.matcher.GlobMatcher; +import com.github.javaparser.ParseProblemException; +import com.github.javaparser.Problem; +import com.github.javaparser.StaticJavaParser; +import com.github.javaparser.TokenRange; +import com.github.javaparser.ast.CompilationUnit; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import javax.inject.Inject; +import javax.xml.xpath.XPathConstants; +import java.io.File; +import java.util.Optional; +import java.util.Set; +import java.util.function.Predicate; + +import static java.lang.String.format; +import static java.util.stream.Collectors.toSet; + +public class ContextConstructor { + private final XmlHelper xmlHelper; + private final GlobMatcher globMatcher; + + @Inject + public ContextConstructor(XmlHelper xmlHelper, GlobMatcher globMatcher) { + this.xmlHelper = xmlHelper; + this.globMatcher = globMatcher; + } + + public Context construct(File androidManifestFile, Set javaFiles, Set layoutFiles) { + Document manifest = xmlHelper.parseXml(androidManifestFile); + String packageName = getPackageName(manifest); + + return Context.builder() + .packageName(packageName) + .minSdkVersion(getUsesSdkVersion(manifest, "android:minSdkVersion")) + .targetSdkVersion(getUsesSdkVersion(manifest, "android:targetSdkVersion")) + .maxSdkVersion(getUsesSdkVersion(manifest, "android:maxSdkVersion")) + .manifest(new Source<>(androidManifestFile, manifest)) + .javaSources(parseJavaFiles(javaFiles, packageName)) + .layouts(parseLayoutFiles(layoutFiles)) + .build(); + } + + private String getPackageName(Document androidManifest) { + return Optional.ofNullable(xmlHelper.xPath(androidManifest, "/manifest", XPathConstants.NODE)) + .map(n -> (Node) n) + .map(Node::getAttributes) + .map(attr -> attr.getNamedItem("package")) + .map(Node::getNodeValue) + .orElseThrow(() -> new EsaException("No 'package' attribute found in manifest file. Interrupting...")); + } + + private Integer getUsesSdkVersion(Document manifest, String attribute) { + return Optional.ofNullable(xmlHelper.xPath(manifest, "/manifest/uses-sdk", XPathConstants.NODE)) + .map(n -> (Node) n) + .map(Node::getAttributes) + .map(attr -> attr.getNamedItem(attribute)) + .map(Node::getNodeValue) + .map(Integer::parseInt) + .orElse(null); + + } + + private Set> parseLayoutFiles(Set layoutFiles) { + return layoutFiles.stream() + .map(file -> new Source<>(file, xmlHelper.parseXml(file))) + .collect(toSet()); + } + + private Set> parseJavaFiles(Set javaFiles, String packageName) { + return javaFiles.stream() + .filter(isApplicationPackageFile(packageName)) + .map(file -> new Source<>(file, parseJava(file))) + .filter(s -> s.getModel() != null) + .collect(toSet()); + } + + private Predicate isApplicationPackageFile(String packageName) { + return file -> { + String path = packageName.replaceAll("\\.", "/"); + return globMatcher.fileMatchesGlobPattern(file, format("**/%s/**", path)); + }; + } + + private CompilationUnit parseJava(File javaFile) { + try { + return StaticJavaParser.parse(javaFile); + } catch (ParseProblemException e) { + printParsingErrorToStderr(e, javaFile); + } catch (Exception e) { + throw new EsaException(e); + } + + return null; + } + + private void printParsingErrorToStderr(ParseProblemException e, File file) { + e.getProblems().stream() + .map(p -> format("%s%s:\n%s\nIgnoring file...\n", file.getAbsolutePath(), getProblemRange(p), p.getMessage())) + .forEach(System.err::println); + } + + private String getProblemRange(Problem problem) { + return problem.getLocation() + .flatMap(TokenRange::toRange) + .map(range -> format(" (line %d, col %d)", range.begin.line, range.begin.column)) + .orElse(""); + } +} diff --git a/src/main/java/com/bartek/esa/context/di/ContextModule.java b/src/main/java/com/bartek/esa/context/di/ContextModule.java new file mode 100644 index 0000000..5015333 --- /dev/null +++ b/src/main/java/com/bartek/esa/context/di/ContextModule.java @@ -0,0 +1,15 @@ +package com.bartek.esa.context.di; + +import com.bartek.esa.context.constructor.ContextConstructor; +import com.bartek.esa.core.xml.XmlHelper; +import com.bartek.esa.file.matcher.GlobMatcher; +import dagger.Module; + +@Module +public class ContextModule { + + public ContextConstructor contextConstructor(XmlHelper xmlHelper, GlobMatcher globMatcher) { + return new ContextConstructor(xmlHelper, globMatcher); + } + +} diff --git a/src/main/java/com/bartek/esa/context/model/Context.java b/src/main/java/com/bartek/esa/context/model/Context.java new file mode 100644 index 0000000..2cbc21c --- /dev/null +++ b/src/main/java/com/bartek/esa/context/model/Context.java @@ -0,0 +1,25 @@ +package com.bartek.esa.context.model; + +import com.github.javaparser.ast.CompilationUnit; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import org.w3c.dom.Document; + +import java.util.Set; + + +@Getter +@Builder +@ToString +@EqualsAndHashCode +public class Context { + private String packageName; + private Integer minSdkVersion; + private Integer targetSdkVersion; + private Integer maxSdkVersion; + private Source manifest; + private Set> javaSources; + private Set> layouts; +} diff --git a/src/main/java/com/bartek/esa/context/model/Source.java b/src/main/java/com/bartek/esa/context/model/Source.java new file mode 100644 index 0000000..73c2e5b --- /dev/null +++ b/src/main/java/com/bartek/esa/context/model/Source.java @@ -0,0 +1,17 @@ +package com.bartek.esa.context.model; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.ToString; + +import java.io.File; + +@Getter +@ToString +@EqualsAndHashCode +@RequiredArgsConstructor +public class Source { + private final File file; + private final M model; +} diff --git a/src/main/java/com/bartek/esa/core/archetype/AndroidManifestPlugin.java b/src/main/java/com/bartek/esa/core/archetype/AndroidManifestPlugin.java index b01718e..0091856 100644 --- a/src/main/java/com/bartek/esa/core/archetype/AndroidManifestPlugin.java +++ b/src/main/java/com/bartek/esa/core/archetype/AndroidManifestPlugin.java @@ -1,20 +1,15 @@ package com.bartek.esa.core.archetype; -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; +import com.bartek.esa.context.model.Context; +import com.bartek.esa.context.model.Source; +import org.w3c.dom.Document; -import java.io.File; - -public abstract class AndroidManifestPlugin extends XmlPlugin { - private final GlobMatcher globMatcher; - - public AndroidManifestPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); - this.globMatcher = globMatcher; - } +public abstract class AndroidManifestPlugin extends BasePlugin { @Override - public boolean supports(File file) { - return globMatcher.fileMatchesGlobPattern(file, "**/AndroidManifest.xml"); + protected void run(Context context) { + run(context.getManifest()); } + + protected abstract void run(Source manifest); } diff --git a/src/main/java/com/bartek/esa/core/archetype/BasePlugin.java b/src/main/java/com/bartek/esa/core/archetype/BasePlugin.java index ed3465d..944e646 100644 --- a/src/main/java/com/bartek/esa/core/archetype/BasePlugin.java +++ b/src/main/java/com/bartek/esa/core/archetype/BasePlugin.java @@ -1,49 +1,92 @@ package com.bartek.esa.core.archetype; +import com.bartek.esa.context.model.Context; import com.bartek.esa.core.model.enumeration.Severity; import com.bartek.esa.core.model.object.Issue; -import org.w3c.dom.Document; +import com.github.javaparser.ast.expr.Expression; +import org.w3c.dom.Node; import java.io.File; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.util.stream.Collectors; + +import static java.lang.String.format; public abstract class BasePlugin implements Plugin { - private Set issues = new HashSet<>(); - private Document manifest; - private File file; + private Set issues; @Override - public void update(File file, Document manifest) { - this.file = file; - this.manifest = manifest; - this.issues.clear(); - } - - @Override - public Set runForIssues() { - run(file); + public Set runForIssues(Context context) { + issues = new HashSet<>(); + run(context); return issues; } - protected abstract void run(File file); + protected abstract void run(Context context); - protected void addIssue(Severity severity, Integer lineNumber, String line) { - addIssue(severity, "", lineNumber, line); + protected void addJavaIssue(Severity severity, File file, Expression expression) { + addIssue(severity, file, getLineNumberFromExpression(expression), expression.toString()); } - protected void addIssue(Severity severity, Map descriptionModel, Integer lineNumber, String line) { - addIssue(severity, "", descriptionModel, lineNumber, line); + private Integer getLineNumberFromExpression(Expression expression) { + return expression.getRange().map(r -> r.begin.line).orElse(null); + } + + protected void addJavaIssue(Severity severity, Map descriptionModel, File file, Expression expression) { + addIssue(severity, "", descriptionModel, file, getLineNumberFromExpression(expression), expression.toString()); } - protected void addIssue(Severity severity, String descriptionCode, Integer lineNumber, String line) { - addIssue(severity, descriptionCode, new HashMap<>(), lineNumber, line); + protected void addJavaIssue(Severity severity, String descriptionCode, File file, Expression expression) { + addIssue(severity, descriptionCode, new HashMap<>(), file, getLineNumberFromExpression(expression), expression.toString()); } - protected void addIssue(Severity severity, String descriptionCode, Map descriptionModel, Integer lineNumber, String line) { + protected void addJavaIssue(Severity severity, String descriptionCode, Map descriptionModel, File file, Expression expression) { + addIssue(severity, descriptionCode, descriptionModel, file, getLineNumberFromExpression(expression), expression.toString()); + } + + protected void addXmlIssue(Severity severity, File file, Node node) { + addIssue(severity, file, null, tagString(node)); + } + + protected void addXmlIssue(Severity severity, Map descriptionModel, File file, Node node) { + addIssue(severity, descriptionModel, file, null, tagString(node)); + } + + protected void addXmlIssue(Severity severity, String descriptionCode, File file, Node node) { + addIssue(severity, descriptionCode, file, null, tagString(node)); + } + + protected void addXmlIssue(Severity severity, String descriptionCode, Map descriptionModel, File file, Node node) { + addIssue(severity, descriptionCode, descriptionModel, file, null, tagString(node)); + } + + protected String tagString(Node node) { + Node[] attributes = new Node[node.getAttributes().getLength()]; + for (int i = 0; i < attributes.length; ++i) { + attributes[i] = node.getAttributes().item(i); + } + + String attributesString = Arrays.stream(attributes) + .map(n -> format("%s=\"%s\"", n.getNodeName(), n.getNodeValue())) + .collect(Collectors.joining(" ")); + + return format("<%s %s ...", node.getNodeName(), attributesString); + } + + protected void addIssue(Severity severity, File file, Integer lineNumber, String line) { + addIssue(severity, "", file, lineNumber, line); + } + + protected void addIssue(Severity severity, Map descriptionModel, File file, Integer lineNumber, String line) { + addIssue(severity, "", descriptionModel, file, lineNumber, line); + } + + protected void addIssue(Severity severity, String descriptionCode, File file, Integer lineNumber, String line) { + addIssue(severity, descriptionCode, new HashMap<>(), file, lineNumber, line); + } + + protected void addIssue(Severity severity, String descriptionCode, Map descriptionModel, File file, Integer lineNumber, String line) { Issue issue = Issue.builder() .severity(severity) .issuer(this.getClass()) @@ -54,18 +97,10 @@ public abstract class BasePlugin implements Plugin { .line(line) .build(); - issues.add(issue); + addIssue(issue); } protected void addIssue(Issue issue) { issues.add(issue); } - - protected File getOriginalFile() { - return file; - } - - protected Document getManifest() { - return manifest; - } } diff --git a/src/main/java/com/bartek/esa/core/archetype/JavaPlugin.java b/src/main/java/com/bartek/esa/core/archetype/JavaPlugin.java index f7f31a4..72c35f6 100644 --- a/src/main/java/com/bartek/esa/core/archetype/JavaPlugin.java +++ b/src/main/java/com/bartek/esa/core/archetype/JavaPlugin.java @@ -1,92 +1,15 @@ package com.bartek.esa.core.archetype; -import com.bartek.esa.core.model.enumeration.Severity; -import com.bartek.esa.core.model.object.Issue; -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; -import com.github.javaparser.ParseProblemException; -import com.github.javaparser.Problem; -import com.github.javaparser.StaticJavaParser; -import com.github.javaparser.TokenRange; +import com.bartek.esa.context.model.Context; +import com.bartek.esa.context.model.Source; import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.expr.Expression; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import javax.xml.xpath.XPathConstants; -import java.io.File; -import java.util.HashMap; - -import static java.lang.String.format; public abstract class JavaPlugin extends BasePlugin { - private final GlobMatcher globMatcher; - private final XmlHelper xmlHelper; - - public JavaPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - this.globMatcher = globMatcher; - this.xmlHelper = xmlHelper; - } @Override - public boolean supports(File file) { - return globMatcher.fileMatchesGlobPattern(file, "**/*.java"); + protected void run(Context context) { + context.getJavaSources().forEach(this::run); } - @Override - protected void run(File file) { - if(!isApplicationPackageFile(file)) { - return; - } - - try { - CompilationUnit compilationUnit = StaticJavaParser.parse(file); - run(compilationUnit); - } catch (ParseProblemException e) { - printParsingErrorToStderr(e, file); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void printParsingErrorToStderr(ParseProblemException e, File file) { - e.getProblems().stream() - .map(p -> format("%s%s:\n%s\nIgnoring file...\n", file.getAbsolutePath(), getRange(p), p.getMessage())) - .forEach(System.err::println); - } - - private String getRange(Problem problem) { - return problem.getLocation() - .flatMap(TokenRange::toRange) - .map(range -> format(" (line %d, col %d)", range.begin.line, range.begin.column)) - .orElse(""); - } - - private boolean isApplicationPackageFile(File file) { - Document manifest = getManifest(); - Node root = (Node) xmlHelper.xPath(manifest, "/manifest", XPathConstants.NODE); - Node packageValue = root.getAttributes().getNamedItem("package"); - - if(packageValue == null) { - Issue issue = Issue.builder() - .issuer(JavaPlugin.class) - .descriptionCode(".NO_PACKAGE") - .descriptionModel(new HashMap<>()) - .severity(Severity.ERROR) - .build(); - - addIssue(issue); - - return false; - } - - String path = packageValue.getNodeValue().replaceAll("\\.", "/"); - return globMatcher.fileMatchesGlobPattern(file, format("**/%s/**", path)); - } - - protected Integer getLineNumberFromExpression(Expression expression) { - return expression.getRange().map(r -> r.begin.line).orElse(null); - } - - public abstract void run(CompilationUnit compilationUnit); + protected abstract void run(Source compilationUnit); } diff --git a/src/main/java/com/bartek/esa/core/archetype/Plugin.java b/src/main/java/com/bartek/esa/core/archetype/Plugin.java index ffbd990..5de9758 100644 --- a/src/main/java/com/bartek/esa/core/archetype/Plugin.java +++ b/src/main/java/com/bartek/esa/core/archetype/Plugin.java @@ -1,13 +1,10 @@ package com.bartek.esa.core.archetype; +import com.bartek.esa.context.model.Context; import com.bartek.esa.core.model.object.Issue; -import org.w3c.dom.Document; -import java.io.File; import java.util.Set; public interface Plugin { - boolean supports(File file); - void update(File file, Document manifest); - Set runForIssues(); + Set runForIssues(Context context); } diff --git a/src/main/java/com/bartek/esa/core/archetype/ResourceLayoutPlugin.java b/src/main/java/com/bartek/esa/core/archetype/ResourceLayoutPlugin.java index aa924e7..43d8c03 100644 --- a/src/main/java/com/bartek/esa/core/archetype/ResourceLayoutPlugin.java +++ b/src/main/java/com/bartek/esa/core/archetype/ResourceLayoutPlugin.java @@ -1,20 +1,15 @@ package com.bartek.esa.core.archetype; -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; +import com.bartek.esa.context.model.Context; +import com.bartek.esa.context.model.Source; +import org.w3c.dom.Document; -import java.io.File; - -public abstract class ResourceLayoutPlugin extends XmlPlugin { - private final GlobMatcher globMatcher; - - public ResourceLayoutPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); - this.globMatcher = globMatcher; - } +public abstract class ResourceLayoutPlugin extends BasePlugin { @Override - public boolean supports(File file) { - return globMatcher.fileMatchesGlobPattern(file, "**/res/layout*/*.xml"); + protected void run(Context context) { + context.getLayouts().forEach(this::run); } + + protected abstract void run(Source layout); } diff --git a/src/main/java/com/bartek/esa/core/archetype/XmlPlugin.java b/src/main/java/com/bartek/esa/core/archetype/XmlPlugin.java deleted file mode 100644 index 19b41a0..0000000 --- a/src/main/java/com/bartek/esa/core/archetype/XmlPlugin.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.bartek.esa.core.archetype; - -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import javax.xml.namespace.QName; -import java.io.File; -import java.util.Arrays; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static java.lang.String.format; - -public abstract class XmlPlugin extends BasePlugin { - private final GlobMatcher globMatcher; - private final XmlHelper xmlHelper; - - public XmlPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - this.globMatcher = globMatcher; - this.xmlHelper = xmlHelper; - } - - @Override - public boolean supports(File file) { - return globMatcher.fileMatchesGlobPattern(file, "**/*.xml"); - } - - @Override - protected void run(File file) { - Document xml = xmlHelper.parseXml(file); - run(xml); - } - - protected abstract void run(Document xml); - - protected Object xPath(Document xml, String expression, QName returnType) { - return xmlHelper.xPath(xml, expression, returnType); - } - - protected Stream stream(NodeList nodeList) { - return xmlHelper.stream(nodeList); - } - - protected String tagString(Node node) { - Node[] attributes = new Node[node.getAttributes().getLength()]; - for(int i=0; i format("%s=\"%s\"", n.getNodeName(), n.getNodeValue())) - .collect(Collectors.joining(" ")); - - return format("<%s %s ...", node.getNodeName(), attributesString); - } -} diff --git a/src/main/java/com/bartek/esa/core/di/CoreModule.java b/src/main/java/com/bartek/esa/core/di/CoreModule.java index 8a9d141..11285a2 100644 --- a/src/main/java/com/bartek/esa/core/di/CoreModule.java +++ b/src/main/java/com/bartek/esa/core/di/CoreModule.java @@ -4,6 +4,7 @@ import com.bartek.esa.core.desc.provider.DescriptionProvider; import com.bartek.esa.core.executor.PluginExecutor; import com.bartek.esa.core.helper.ParentNodeFinder; import com.bartek.esa.core.helper.StaticScopeHelper; +import com.bartek.esa.core.helper.StringConcatenationChecker; import com.bartek.esa.core.java.JavaSyntaxRegexProvider; import com.bartek.esa.core.xml.XmlHelper; import dagger.Module; @@ -13,8 +14,8 @@ import dagger.Provides; public class CoreModule { @Provides - public PluginExecutor pluginExecutor(XmlHelper xmlHelper) { - return new PluginExecutor(xmlHelper); + public PluginExecutor pluginExecutor() { + return new PluginExecutor(); } @Provides @@ -37,6 +38,11 @@ public class CoreModule { return new StaticScopeHelper(); } + @Provides + public StringConcatenationChecker stringConcatenationChecker(StaticScopeHelper staticScopeHelper) { + return new StringConcatenationChecker(staticScopeHelper); + } + @Provides public ParentNodeFinder parentNodeFinder() { return new ParentNodeFinder(); diff --git a/src/main/java/com/bartek/esa/core/di/PluginModule.java b/src/main/java/com/bartek/esa/core/di/PluginModule.java index b218fbc..8117ed9 100644 --- a/src/main/java/com/bartek/esa/core/di/PluginModule.java +++ b/src/main/java/com/bartek/esa/core/di/PluginModule.java @@ -3,10 +3,10 @@ package com.bartek.esa.core.di; import com.bartek.esa.core.archetype.Plugin; import com.bartek.esa.core.helper.ParentNodeFinder; import com.bartek.esa.core.helper.StaticScopeHelper; +import com.bartek.esa.core.helper.StringConcatenationChecker; import com.bartek.esa.core.java.JavaSyntaxRegexProvider; import com.bartek.esa.core.plugin.*; import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import dagger.Module; import dagger.Provides; import dagger.multibindings.ElementsIntoSet; @@ -26,127 +26,127 @@ public class PluginModule { @Provides @IntoSet - public Plugin loggingPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper, StaticScopeHelper staticScopeHelper) { - return new LoggingPlugin(globMatcher, xmlHelper, staticScopeHelper); + public Plugin loggingPlugin(StaticScopeHelper staticScopeHelper, StringConcatenationChecker stringConcatenationChecker) { + return new LoggingPlugin(staticScopeHelper, stringConcatenationChecker); } @Provides @IntoSet - public Plugin debuggablePlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new DebuggablePlugin(globMatcher, xmlHelper); + public Plugin debuggablePlugin(XmlHelper xmlHelper) { + return new DebuggablePlugin(xmlHelper); } @Provides @IntoSet - public Plugin allowBackupPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new AllowBackupPlugin(globMatcher, xmlHelper); + public Plugin allowBackupPlugin(XmlHelper xmlHelper) { + return new AllowBackupPlugin(xmlHelper); } @Provides @IntoSet - public Plugin permissionRaceConditionPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new PermissionsRaceConditionPlugin(globMatcher, xmlHelper); + public Plugin permissionRaceConditionPlugin(XmlHelper xmlHelper) { + return new PermissionsRaceConditionPlugin(xmlHelper); } @Provides @IntoSet - public Plugin secureRandomPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new SecureRandomPlugin(globMatcher, xmlHelper); + public Plugin secureRandomPlugin() { + return new SecureRandomPlugin(); } @Provides @IntoSet - public Plugin implicitIntentsPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper, JavaSyntaxRegexProvider javaSyntaxRegexProvider) { - return new ImplicitIntentsPlugin(globMatcher, xmlHelper, javaSyntaxRegexProvider); + public Plugin implicitIntentsPlugin(JavaSyntaxRegexProvider javaSyntaxRegexProvider) { + return new ImplicitIntentsPlugin(javaSyntaxRegexProvider); } @Provides @IntoSet - public Plugin sharedUidPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new SharedUidPlugin(globMatcher, xmlHelper); + public Plugin sharedUidPlugin(XmlHelper xmlHelper) { + return new SharedUidPlugin(xmlHelper); } @Provides @IntoSet - public Plugin usesSdkPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new UsesSdkPlugin(globMatcher, xmlHelper); + public Plugin usesSdkPlugin(XmlHelper xmlHelper) { + return new UsesSdkPlugin(xmlHelper); } @Provides @IntoSet - public Plugin cipherInstancePlugin(GlobMatcher globMatcher, XmlHelper xmlHelper, StaticScopeHelper staticScopeHelper) { - return new CipherInstancePlugin(globMatcher, xmlHelper, staticScopeHelper); + public Plugin cipherInstancePlugin(StaticScopeHelper staticScopeHelper) { + return new CipherInstancePlugin(staticScopeHelper); } @Provides @IntoSet - public Plugin strictModePlugin(GlobMatcher globMatcher, XmlHelper xmlHelper, StaticScopeHelper staticScopeHelper) { - return new StrictModePlugin(globMatcher, xmlHelper, staticScopeHelper); + public Plugin strictModePlugin(StaticScopeHelper staticScopeHelper) { + return new StrictModePlugin(staticScopeHelper); } @Provides @IntoSet - public Plugin externalStoragePlugin(GlobMatcher globMatcher, XmlHelper xmlHelper, ParentNodeFinder parentNodeFinder) { - return new ExternalStoragePlugin(globMatcher, xmlHelper, parentNodeFinder); + public Plugin externalStoragePlugin(ParentNodeFinder parentNodeFinder) { + return new ExternalStoragePlugin(parentNodeFinder); } @Provides @IntoSet - public Plugin suppressWarningsPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new SuppressWarningsPlugin(globMatcher, xmlHelper); + public Plugin suppressWarningsPlugin() { + return new SuppressWarningsPlugin(); } @Provides @IntoSet - public Plugin exportedComponentsPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new ExportedComponentsPlugin(globMatcher, xmlHelper); + public Plugin exportedComponentsPlugin(XmlHelper xmlHelper) { + return new ExportedComponentsPlugin(xmlHelper); } @Provides @IntoSet - public Plugin dangerousPermissionPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new DangerousPermissionPlugin(globMatcher, xmlHelper); + public Plugin dangerousPermissionPlugin(XmlHelper xmlHelper) { + return new DangerousPermissionPlugin(xmlHelper); } @Provides @IntoSet - public Plugin textInputValidationPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new TextInputValidationPlugin(globMatcher, xmlHelper); + public Plugin textInputValidationPlugin(XmlHelper xmlHelper) { + return new TextInputValidationPlugin(xmlHelper); } @Provides @IntoSet - public Plugin intentFilterPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new IntentFilterPlugin(globMatcher, xmlHelper); + public Plugin intentFilterPlugin(XmlHelper xmlHelper) { + return new IntentFilterPlugin(xmlHelper); } @Provides @IntoSet - public Plugin sqlInjectionPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new SqlInjectionPlugin(globMatcher, xmlHelper); + public Plugin sqlInjectionPlugin(StringConcatenationChecker stringConcatenationChecker) { + return new SqlInjectionPlugin( stringConcatenationChecker); } @Provides @IntoSet - public Plugin worldAccessPermissionsPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new WorldAccessPermissionsPlugin(globMatcher, xmlHelper); + public Plugin worldAccessPermissionsPlugin() { + return new WorldAccessPermissionsPlugin(); } @Provides @IntoSet - public Plugin orderedAndStickyBroadcastPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new OrderedBroadcastPlugin(globMatcher, xmlHelper); + public Plugin orderedAndStickyBroadcastPlugin() { + return new OrderedBroadcastPlugin(); } @Provides @IntoSet - public Plugin webViewPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new WebViewPlugin(globMatcher, xmlHelper); + public Plugin webViewPlugin() { + return new WebViewPlugin(); } @Provides @IntoSet - public Plugin telephonyManagerPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - return new TelephonyManagerPlugin(globMatcher, xmlHelper); + public Plugin telephonyManagerPlugin() { + return new TelephonyManagerPlugin(); } } diff --git a/src/main/java/com/bartek/esa/core/executor/PluginExecutor.java b/src/main/java/com/bartek/esa/core/executor/PluginExecutor.java index d0cd00a..1cc1509 100644 --- a/src/main/java/com/bartek/esa/core/executor/PluginExecutor.java +++ b/src/main/java/com/bartek/esa/core/executor/PluginExecutor.java @@ -1,40 +1,30 @@ package com.bartek.esa.core.executor; +import com.bartek.esa.context.model.Context; import com.bartek.esa.core.archetype.Plugin; import com.bartek.esa.core.model.object.Issue; -import com.bartek.esa.core.xml.XmlHelper; -import org.w3c.dom.Document; -import javax.inject.Inject; -import java.io.File; import java.util.Set; +import java.util.function.Consumer; import static java.util.stream.Collectors.toSet; public class PluginExecutor { - private final XmlHelper xmlHelper; - @Inject - public PluginExecutor(XmlHelper xmlHelper) { - this.xmlHelper = xmlHelper; - } - - public Set executeForFiles(File manifest, Set files, Set plugins, boolean debug) { - return files.stream() - .peek(file -> { if(debug) System.out.printf("File: %s\n", file.getAbsolutePath()); }) - .map(file -> executeForFile(manifest, file, plugins, debug)) - .flatMap(Set::stream) - .collect(toSet()); - } - - private Set executeForFile(File manifest, File file, Set plugins, boolean debug) { - Document xmlManifest = xmlHelper.parseXml(manifest); + public Set executeForContext(Context context, Set plugins, boolean debug) { return plugins.stream() - .peek(plugin -> { if(debug) System.out.printf(" Plugin: %s\n", plugin.getClass().getCanonicalName()); }) - .peek(plugin -> plugin.update(file, xmlManifest)) - .filter(plugin -> plugin.supports(file)) - .map(Plugin::runForIssues) + .peek(logPlugin(debug)) + .map(plugin -> plugin.runForIssues(context)) .flatMap(Set::stream) .collect(toSet()); + + } + + private Consumer logPlugin(boolean debug) { + return plugin -> { + if(debug) { + System.out.printf(" Plugin: %s\n", plugin.getClass().getCanonicalName()); + } + }; } } diff --git a/src/main/java/com/bartek/esa/core/helper/StringConcatenationChecker.java b/src/main/java/com/bartek/esa/core/helper/StringConcatenationChecker.java new file mode 100644 index 0000000..89c0bff --- /dev/null +++ b/src/main/java/com/bartek/esa/core/helper/StringConcatenationChecker.java @@ -0,0 +1,45 @@ +package com.bartek.esa.core.helper; + +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.expr.Expression; +import com.github.javaparser.ast.expr.MethodCallExpr; + +import javax.inject.Inject; +import java.util.function.Predicate; + +public class StringConcatenationChecker { + private final StaticScopeHelper staticScopeHelper; + + @Inject + public StringConcatenationChecker(StaticScopeHelper staticScopeHelper) { + + this.staticScopeHelper = staticScopeHelper; + } + + public boolean isStringConcatenation(CompilationUnit unit, Expression expr) { + Predicate isStringFormatMethod = staticScopeHelper.isFromScope(unit, "format", "String", "java.lang"); + if(expr.isMethodCallExpr() && isStringFormatMethod.test(expr.asMethodCallExpr())) { + return true; + } + + return isStringConcatenation(expr); + } + + private boolean isStringConcatenation(Expression expr) { + if(expr.isBinaryExpr() && expr.asBinaryExpr().getOperator().asString().equals("+")) { + return isLiteralStringOrConcatenation(expr); + } + + return false; + } + + private boolean isLiteralStringOrConcatenation(Expression expr) { + if(expr.isBinaryExpr() && expr.asBinaryExpr().getOperator().asString().equals("+")) { + boolean isLeftArgumentString = isLiteralStringOrConcatenation(expr.asBinaryExpr().getLeft()); + boolean isRightArgumentString = isLiteralStringOrConcatenation(expr.asBinaryExpr().getRight()); + return isLeftArgumentString || isRightArgumentString; + } + + return expr.isStringLiteralExpr(); + } +} diff --git a/src/main/java/com/bartek/esa/core/model/object/Issue.java b/src/main/java/com/bartek/esa/core/model/object/Issue.java index 355dfcb..9a402c1 100644 --- a/src/main/java/com/bartek/esa/core/model/object/Issue.java +++ b/src/main/java/com/bartek/esa/core/model/object/Issue.java @@ -23,7 +23,6 @@ public class Issue implements Comparable { public int compareTo(Object o) { Issue another = (Issue) o; int compByFile = file.compareTo(another.file); - if(compByFile != 0) { return compByFile; } diff --git a/src/main/java/com/bartek/esa/core/plugin/AllowBackupPlugin.java b/src/main/java/com/bartek/esa/core/plugin/AllowBackupPlugin.java index 87c21a6..f66233c 100644 --- a/src/main/java/com/bartek/esa/core/plugin/AllowBackupPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/AllowBackupPlugin.java @@ -1,9 +1,9 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.AndroidManifestPlugin; import com.bartek.esa.core.model.enumeration.Severity; import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -12,19 +12,20 @@ import javax.xml.xpath.XPathConstants; import java.util.Optional; public class AllowBackupPlugin extends AndroidManifestPlugin { + private final XmlHelper xmlHelper; @Inject - public AllowBackupPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); + public AllowBackupPlugin(XmlHelper xmlHelper) { + this.xmlHelper = xmlHelper; } @Override - protected void run(Document xml) { - Node applicationNode = (Node) xPath(xml, "/manifest/application", XPathConstants.NODE); + protected void run(Source manifest) { + Node applicationNode = (Node) xmlHelper.xPath(manifest.getModel(), "/manifest/application", XPathConstants.NODE); Optional.ofNullable(applicationNode.getAttributes().getNamedItem("android:allowBackup")).ifPresentOrElse(n -> { if (!n.getNodeValue().equals("false")) { - addIssue(Severity.WARNING, ".NO_FALSE", null, n.toString()); + addIssue(Severity.WARNING, ".NO_FALSE", manifest.getFile(), null, n.toString()); } - }, () -> addIssue(Severity.ERROR, ".NO_ATTR", null, null)); + }, () -> addIssue(Severity.ERROR, ".NO_ATTR", manifest.getFile(), null, null)); } } diff --git a/src/main/java/com/bartek/esa/core/plugin/CipherInstancePlugin.java b/src/main/java/com/bartek/esa/core/plugin/CipherInstancePlugin.java index 4567ced..0c35664 100644 --- a/src/main/java/com/bartek/esa/core/plugin/CipherInstancePlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/CipherInstancePlugin.java @@ -1,10 +1,9 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.JavaPlugin; import com.bartek.esa.core.helper.StaticScopeHelper; import com.bartek.esa.core.model.enumeration.Severity; -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.expr.MethodCallExpr; @@ -16,19 +15,18 @@ public class CipherInstancePlugin extends JavaPlugin { private final StaticScopeHelper staticScopeHelper; @Inject - public CipherInstancePlugin(GlobMatcher globMatcher, XmlHelper xmlHelper, StaticScopeHelper staticScopeHelper) { - super(globMatcher, xmlHelper); + public CipherInstancePlugin(StaticScopeHelper staticScopeHelper) { this.staticScopeHelper = staticScopeHelper; } @Override - public void run(CompilationUnit compilationUnit) { - compilationUnit.findAll(MethodCallExpr.class).stream() + public void run(Source java) { + java.getModel().findAll(MethodCallExpr.class).stream() .filter(expr -> expr.getName().getIdentifier().equals("getInstance")) - .filter(staticScopeHelper.isFromScope(compilationUnit, "getInstance", "Cipher", "javax.crypto")) + .filter(staticScopeHelper.isFromScope(java.getModel(), "getInstance", "Cipher", "javax.crypto")) .filter(expr -> expr.getArguments().isNonEmpty()) .filter(expr -> !isFullCipherQualifier(expr.getArguments().get(0).toString())) - .forEach(expr -> addIssue(Severity.ERROR, getLineNumberFromExpression(expr), expr.toString())); + .forEach(expr -> addJavaIssue(Severity.ERROR, java.getFile(), expr)); } private boolean isFullCipherQualifier(String qualifier) { diff --git a/src/main/java/com/bartek/esa/core/plugin/DangerousPermissionPlugin.java b/src/main/java/com/bartek/esa/core/plugin/DangerousPermissionPlugin.java index 381a09b..dbc5573 100644 --- a/src/main/java/com/bartek/esa/core/plugin/DangerousPermissionPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/DangerousPermissionPlugin.java @@ -1,9 +1,9 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.AndroidManifestPlugin; import com.bartek.esa.core.model.enumeration.Severity; import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -13,19 +13,20 @@ import javax.xml.xpath.XPathConstants; import java.util.Optional; public class DangerousPermissionPlugin extends AndroidManifestPlugin { + private final XmlHelper xmlHelper; @Inject - public DangerousPermissionPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); + public DangerousPermissionPlugin(XmlHelper xmlHelper) { + this.xmlHelper = xmlHelper; } @Override - protected void run(Document xml) { - NodeList customPermissions = (NodeList) xPath(xml, "/manifest/permission", XPathConstants.NODESET); - stream(customPermissions) + protected void run(Source manifest) { + NodeList customPermissions = (NodeList) xmlHelper.xPath(manifest.getModel(), "/manifest/permission", XPathConstants.NODESET); + xmlHelper.stream(customPermissions) .filter(this::isDangerousPermission) .filter(this::doesNotHaveDescription) - .forEach(permission -> addIssue(Severity.WARNING, null, tagString(permission))); + .forEach(permission -> addXmlIssue(Severity.WARNING, manifest.getFile(), permission)); } private boolean isDangerousPermission(Node permission) { diff --git a/src/main/java/com/bartek/esa/core/plugin/DebuggablePlugin.java b/src/main/java/com/bartek/esa/core/plugin/DebuggablePlugin.java index e198352..e436b10 100644 --- a/src/main/java/com/bartek/esa/core/plugin/DebuggablePlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/DebuggablePlugin.java @@ -1,9 +1,9 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.AndroidManifestPlugin; import com.bartek.esa.core.model.enumeration.Severity; import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -12,19 +12,20 @@ import javax.xml.xpath.XPathConstants; import java.util.Optional; public class DebuggablePlugin extends AndroidManifestPlugin { + private final XmlHelper xmlHelper; @Inject - public DebuggablePlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); + public DebuggablePlugin(XmlHelper xmlHelper) { + this.xmlHelper = xmlHelper; } @Override - protected void run(Document xml) { - Node applicationNode = (Node) xPath(xml, "/manifest/application", XPathConstants.NODE); + protected void run(Source manifest) { + Node applicationNode = (Node) xmlHelper.xPath(manifest.getModel(), "/manifest/application", XPathConstants.NODE); Optional.ofNullable(applicationNode.getAttributes().getNamedItem("android:debuggable")).ifPresentOrElse(n -> { if(!n.getNodeValue().equals("false")) { - addIssue(Severity.WARNING, ".NO_FALSE", null, n.toString()); + addIssue(Severity.WARNING, ".NO_FALSE", manifest.getFile(),null, n.toString()); } - }, () -> addIssue(Severity.ERROR, ".NO_ATTR",null, null)); + }, () -> addIssue(Severity.ERROR, ".NO_ATTR", manifest.getFile(), null, null)); } } diff --git a/src/main/java/com/bartek/esa/core/plugin/ExportedComponentsPlugin.java b/src/main/java/com/bartek/esa/core/plugin/ExportedComponentsPlugin.java index 01410fa..febefab 100644 --- a/src/main/java/com/bartek/esa/core/plugin/ExportedComponentsPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/ExportedComponentsPlugin.java @@ -1,9 +1,9 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.AndroidManifestPlugin; import com.bartek.esa.core.model.enumeration.Severity; import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -16,26 +16,27 @@ import java.util.Optional; import static java.lang.String.format; public class ExportedComponentsPlugin extends AndroidManifestPlugin { + private final XmlHelper xmlHelper; @Inject - public ExportedComponentsPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); + public ExportedComponentsPlugin(XmlHelper xmlHelper) { + this.xmlHelper = xmlHelper; } @Override - protected void run(Document xml) { - findExportedComponents(xml, "activity"); - findExportedComponents(xml, "service"); - findExportedComponents(xml, "receiver"); - findExportedProviders(xml); + protected void run(Source manifest) { + findExportedComponents(manifest, "activity"); + findExportedComponents(manifest, "service"); + findExportedComponents(manifest, "receiver"); + findExportedProviders(manifest); } - private void findExportedComponents(Document xml, String component) { - NodeList exportedActivities = (NodeList) xPath(xml, format("/manifest/application/%s", component), XPathConstants.NODESET); - stream(exportedActivities) + private void findExportedComponents(Source manifest, String component) { + NodeList exportedActivities = (NodeList) xmlHelper.xPath(manifest.getModel(), format("/manifest/application/%s", component), XPathConstants.NODESET); + xmlHelper.stream(exportedActivities) .filter(this::isExported) .filter(node -> doesNotHavePermission(node, "android:permission")) - .forEach(node -> addIssue(Severity.WARNING, ".NO_PERMISSION", getModel(node), null, null)); + .forEach(node -> addIssue(Severity.WARNING, ".NO_PERMISSION", getModel(node), manifest.getFile(), null, null)); } private Map getModel(Node node) { @@ -45,13 +46,13 @@ public class ExportedComponentsPlugin extends AndroidManifestPlugin { ); } - private void findExportedProviders(Document xml) { - NodeList exportedProviders = (NodeList) xPath(xml, "/manifest/application/provider", XPathConstants.NODESET); - stream(exportedProviders) + private void findExportedProviders(Source manifest) { + NodeList exportedProviders = (NodeList) xmlHelper.xPath(manifest.getModel(), "/manifest/application/provider", XPathConstants.NODESET); + xmlHelper.stream(exportedProviders) .filter(this::isExported) .filter(node -> doesNotHavePermission(node, "android:writePermission") || doesNotHavePermission(node, "android:readPermission")) - .forEach(node -> addIssue(Severity.WARNING, ".NO_PERMISSION", getModel(node), null, null)); + .forEach(node -> addIssue(Severity.WARNING, ".NO_PERMISSION", getModel(node), manifest.getFile(), null, null)); } private boolean doesNotHavePermission(Node node, String permissionAttribute) { @@ -69,6 +70,7 @@ public class ExportedComponentsPlugin extends AndroidManifestPlugin { .orElse(false); } + // todo remove it! private String nodeToString(Node node) { String nodeName = Optional.ofNullable(node.getAttributes().getNamedItem("android:name")) .map(Node::getNodeValue) diff --git a/src/main/java/com/bartek/esa/core/plugin/ExternalStoragePlugin.java b/src/main/java/com/bartek/esa/core/plugin/ExternalStoragePlugin.java index 2241c37..3b38627 100644 --- a/src/main/java/com/bartek/esa/core/plugin/ExternalStoragePlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/ExternalStoragePlugin.java @@ -1,44 +1,45 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.JavaPlugin; import com.bartek.esa.core.helper.ParentNodeFinder; import com.bartek.esa.core.model.enumeration.Severity; -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.expr.MethodCallExpr; import javax.inject.Inject; +import java.util.function.Consumer; public class ExternalStoragePlugin extends JavaPlugin { private final ParentNodeFinder parentNodeFinder; @Inject - public ExternalStoragePlugin(GlobMatcher globMatcher, XmlHelper xmlHelper, ParentNodeFinder parentNodeFinder) { - super(globMatcher, xmlHelper); + public ExternalStoragePlugin(ParentNodeFinder parentNodeFinder) { this.parentNodeFinder = parentNodeFinder; } @Override - public void run(CompilationUnit compilationUnit) { - compilationUnit.findAll(MethodCallExpr.class).stream() + public void run(Source java) { + java.getModel().findAll(MethodCallExpr.class).stream() .filter(expr -> expr.getName().getIdentifier().matches("getExternalStorageDirectory|getExternalStoragePublicDirectory")) - .forEach(this::findCheckingStorageStateForAccessingExternalStorage); + .forEach(findCheckingStorageStateForAccessingExternalStorage(java)); } - private void findCheckingStorageStateForAccessingExternalStorage(MethodCallExpr accessingToExternalStorage) { - parentNodeFinder.findParentNode(accessingToExternalStorage, MethodDeclaration.class).ifPresent(methodDeclaration -> - findCheckingStorageStateInMethodDeclaration(accessingToExternalStorage, methodDeclaration) - ); + private Consumer findCheckingStorageStateForAccessingExternalStorage(Source java) { + return accessingToExternalStorage -> parentNodeFinder + .findParentNode(accessingToExternalStorage, MethodDeclaration.class) + .ifPresent(methodDeclaration -> + findCheckingStorageStateInMethodDeclaration(java, accessingToExternalStorage, methodDeclaration) + ); } - private void findCheckingStorageStateInMethodDeclaration(MethodCallExpr accessingToExternalStorage, MethodDeclaration methodDeclaration) { + private void findCheckingStorageStateInMethodDeclaration(Source java, MethodCallExpr accessingToExternalStorage, MethodDeclaration methodDeclaration) { boolean isStateBeingChecked = methodDeclaration.findAll(MethodCallExpr.class).stream() .anyMatch(e -> e.getName().getIdentifier().equals("getExternalStorageState")); if (!isStateBeingChecked) { - addIssue(Severity.WARNING, getLineNumberFromExpression(accessingToExternalStorage), accessingToExternalStorage.toString()); + addJavaIssue(Severity.WARNING, java.getFile(), accessingToExternalStorage); } } } diff --git a/src/main/java/com/bartek/esa/core/plugin/ImplicitIntentsPlugin.java b/src/main/java/com/bartek/esa/core/plugin/ImplicitIntentsPlugin.java index 92b8f4d..abfccb5 100644 --- a/src/main/java/com/bartek/esa/core/plugin/ImplicitIntentsPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/ImplicitIntentsPlugin.java @@ -1,10 +1,9 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.JavaPlugin; import com.bartek.esa.core.java.JavaSyntaxRegexProvider; import com.bartek.esa.core.model.enumeration.Severity; -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; @@ -17,27 +16,26 @@ import java.util.Optional; import java.util.stream.Collectors; public class ImplicitIntentsPlugin extends JavaPlugin { - private final JavaSyntaxRegexProvider java; + private final JavaSyntaxRegexProvider javaSyntax; @Inject - public ImplicitIntentsPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper, JavaSyntaxRegexProvider javaSyntaxRegexProvider) { - super(globMatcher, xmlHelper); - this.java = javaSyntaxRegexProvider; + public ImplicitIntentsPlugin(JavaSyntaxRegexProvider javaSyntaxRegexProvider) { + this.javaSyntax = javaSyntaxRegexProvider; } @Override - public void run(CompilationUnit compilationUnit) { - checkCreatingImplicitIntents(compilationUnit); - checkCreatingPendingIntentsWithoutIntentVariable(compilationUnit); - checkCreatingPendingIntentsWithIntentVariables(compilationUnit); - checkCreatingPendingIntentsWithIntentsArraysVariables(compilationUnit); + public void run(Source java) { + checkCreatingImplicitIntents(java); + checkCreatingPendingIntentsWithoutIntentVariable(java); + checkCreatingPendingIntentsWithIntentVariables(java); + checkCreatingPendingIntentsWithIntentsArraysVariables(java); } // Works for: // Intent[] myIntents = { new Intent(...), ... } // getActivities(this, 0, myIntents, 0); - private void checkCreatingPendingIntentsWithIntentsArraysVariables(CompilationUnit compilationUnit) { - List implicitIntentsArraysVariables = compilationUnit.findAll(ObjectCreationExpr.class).stream() + private void checkCreatingPendingIntentsWithIntentsArraysVariables(Source java) { + List implicitIntentsArraysVariables = java.getModel().findAll(ObjectCreationExpr.class).stream() .filter(expr -> expr.getType().getName().getIdentifier().equals("Intent")) .filter(this::isCreatingImplicitIntent) .map(Node::getParentNode) @@ -49,31 +47,31 @@ public class ImplicitIntentsPlugin extends JavaPlugin { .map(VariableDeclarator::getName) .map(SimpleName::getIdentifier) .collect(Collectors.toList()); - compilationUnit.findAll(MethodCallExpr.class).stream() + java.getModel().findAll(MethodCallExpr.class).stream() .filter(expr -> expr.getName().getIdentifier().matches("getActivities")) .filter(expr -> expr.getArguments().size() >= 4) .filter(expr -> expr.getArguments().get(2).isNameExpr()) .filter(expr -> implicitIntentsArraysVariables.contains(expr.getArguments().get(2).asNameExpr().getName().getIdentifier())) - .forEach(expr -> addIssue(Severity.VULNERABILITY, ".PENDING_INTENT", getLineNumberFromExpression(expr), expr.toString())); + .forEach(expr -> addJavaIssue(Severity.VULNERABILITY, ".PENDING_INTENT", java.getFile(), expr)); } - private void checkCreatingImplicitIntents(CompilationUnit compilationUnit) { - List intentVariables = getIntentVariables(compilationUnit); - checkAllSetActionMethodInvocations(compilationUnit, intentVariables); - checkCreatingImplicitIntentsUsingConstructor(compilationUnit); + private void checkCreatingImplicitIntents(Source java) { + List intentVariables = getIntentVariables(java); + checkAllSetActionMethodInvocations(java, intentVariables); + checkCreatingImplicitIntentsUsingConstructor(java); } // Works for: new Intent(Intent.ABC), new Intent(ABC) - private void checkCreatingImplicitIntentsUsingConstructor(CompilationUnit compilationUnit) { - compilationUnit.findAll(ObjectCreationExpr.class).stream() + private void checkCreatingImplicitIntentsUsingConstructor(Source java) { + java.getModel().findAll(ObjectCreationExpr.class).stream() .filter(expr -> expr.getType().getName().getIdentifier().equals("Intent")) .filter(this::isCreatingImplicitIntent) - .forEach(objectCreation -> addIssue(Severity.INFO, ".IMPLICIT_INTENT", getLineNumberFromExpression(objectCreation), objectCreation.toString())); + .forEach(objectCreation -> addJavaIssue(Severity.INFO, ".IMPLICIT_INTENT", java.getFile(), objectCreation)); } // Returns: i for: Intent i = new Intent(...) - private List getIntentVariables(CompilationUnit compilationUnit) { - return compilationUnit.findAll(VariableDeclarationExpr.class).stream() + private List getIntentVariables(Source java) { + return java.getModel().findAll(VariableDeclarationExpr.class).stream() .filter(expr -> expr.getElementType().toString().equals("Intent")) .map(VariableDeclarationExpr::getVariables) .flatMap(NodeList::stream) @@ -90,7 +88,7 @@ public class ImplicitIntentsPlugin extends JavaPlugin { // Works for: new Intent(CONSTANT, ...) if (arguments.size() == 1) { Expression argument = arguments.get(0); - isImplicit = java.isConstant(argument); + isImplicit = javaSyntax.isConstant(argument); } // Not works for: new Intent(this, ...) @@ -107,14 +105,14 @@ public class ImplicitIntentsPlugin extends JavaPlugin { } // Works for: i.setAction(...) - private void checkAllSetActionMethodInvocations(CompilationUnit compilationUnit, List intentVariables) { - compilationUnit.findAll(MethodCallExpr.class).forEach(methodCall -> { + private void checkAllSetActionMethodInvocations(Source java, List intentVariables) { + java.getModel().findAll(MethodCallExpr.class).forEach(methodCall -> { boolean isCalledOnIntentObject = methodCall.getScope() .map(Expression::toString) .filter(intentVariables::contains) .isPresent(); if(isCalledOnIntentObject && methodCall.getName().getIdentifier().equals("setAction")) { - addIssue(Severity.INFO, ".IMPLICIT_INTENT", getLineNumberFromExpression(methodCall), methodCall.toString()); + addJavaIssue(Severity.INFO, ".IMPLICIT_INTENT", java.getFile(), methodCall); } }); } @@ -122,8 +120,8 @@ public class ImplicitIntentsPlugin extends JavaPlugin { // Works for: // Intent myIntent = new Intent(...) // getActivity(this, 0, myIntent, 0); - private void checkCreatingPendingIntentsWithIntentVariables(CompilationUnit compilationUnit) { - List implicitIntentsVariables = compilationUnit.findAll(ObjectCreationExpr.class).stream() + private void checkCreatingPendingIntentsWithIntentVariables(Source java) { + List implicitIntentsVariables = java.getModel().findAll(ObjectCreationExpr.class).stream() .filter(expr -> expr.getType().getName().getIdentifier().equals("Intent")) .filter(this::isCreatingImplicitIntent) .map(Node::getParentNode) @@ -133,30 +131,30 @@ public class ImplicitIntentsPlugin extends JavaPlugin { .map(VariableDeclarator::getName) .map(SimpleName::getIdentifier) .collect(Collectors.toList()); - compilationUnit.findAll(MethodCallExpr.class).stream() + java.getModel().findAll(MethodCallExpr.class).stream() .filter(expr -> expr.getName().getIdentifier().matches("getActivity|getBroadcast|getService")) .filter(expr -> expr.getArguments().size() >= 4) .filter(expr -> expr.getArguments().get(2).isNameExpr()) .filter(expr -> implicitIntentsVariables.contains(expr.getArguments().get(2).asNameExpr().getName().getIdentifier())) - .forEach(expr -> addIssue(Severity.VULNERABILITY, ".PENDING_INTENT", getLineNumberFromExpression(expr), expr.toString())); + .forEach(expr -> addJavaIssue(Severity.VULNERABILITY, ".PENDING_INTENT", java.getFile(), expr)); } - private void checkCreatingPendingIntentsWithoutIntentVariable(CompilationUnit compilationUnit) { + private void checkCreatingPendingIntentsWithoutIntentVariable(Source java) { // Works for: getActivity(this, 0, new Intent(...), 0) - compilationUnit.findAll(MethodCallExpr.class).stream() + java.getModel().findAll(MethodCallExpr.class).stream() .filter(expr -> expr.getName().getIdentifier().matches("getActivity|getBroadcast|getService")) .filter(expr -> expr.getArguments().size() >= 4) .filter(expr -> expr.getArguments().get(2).isObjectCreationExpr()) .filter(expr -> isCreatingImplicitIntent(expr.getArguments().get(2).asObjectCreationExpr())) - .forEach(expr -> addIssue(Severity.VULNERABILITY, ".PENDING_INTENT", getLineNumberFromExpression(expr), expr.toString())); + .forEach(expr -> addJavaIssue(Severity.VULNERABILITY, ".PENDING_INTENT", java.getFile(), expr)); // Works for: getActivities(this, 0, new Intent[] { new Intent(...), ...}, 0) - compilationUnit.findAll(MethodCallExpr.class).stream() + java.getModel().findAll(MethodCallExpr.class).stream() .filter(expr -> expr.getName().getIdentifier().matches("getActivities")) .filter(expr -> expr.getArguments().size() >= 4) .filter(expr -> expr.getArguments().get(2).isArrayCreationExpr()) .filter(expr -> isCreatingImplicitIntentsArray(expr.getArguments().get(2).asArrayCreationExpr())) - .forEach(expr -> addIssue(Severity.VULNERABILITY, ".PENDING_INTENT", getLineNumberFromExpression(expr), expr.toString())); + .forEach(expr -> addJavaIssue(Severity.VULNERABILITY, ".PENDING_INTENT", java.getFile(), expr)); } private boolean isCreatingImplicitIntentsArray(ArrayCreationExpr arrayCreationExpr) { diff --git a/src/main/java/com/bartek/esa/core/plugin/IntentFilterPlugin.java b/src/main/java/com/bartek/esa/core/plugin/IntentFilterPlugin.java index 3272674..69ed261 100644 --- a/src/main/java/com/bartek/esa/core/plugin/IntentFilterPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/IntentFilterPlugin.java @@ -1,9 +1,9 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.AndroidManifestPlugin; import com.bartek.esa.core.model.enumeration.Severity; import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -12,19 +12,20 @@ import javax.inject.Inject; import java.util.Map; public class IntentFilterPlugin extends AndroidManifestPlugin { + private final XmlHelper xmlHelper; @Inject - public IntentFilterPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); + public IntentFilterPlugin(XmlHelper xmlHelper) { + this.xmlHelper = xmlHelper; } @Override - protected void run(Document xml) { - NodeList filters = xml.getElementsByTagName("intent-filter"); - stream(filters) + protected void run(Source manifest) { + NodeList filters = manifest.getModel().getElementsByTagName("intent-filter"); + xmlHelper.stream(filters) .filter(this::isNotMainActivity) .map(Node::getParentNode) - .forEach(n -> addIssue(Severity.INFO, getModel(n), null, null)); + .forEach(n -> addIssue(Severity.INFO, getModel(n), manifest.getFile(), null, null)); } private Map getModel(Node node) { @@ -35,14 +36,14 @@ public class IntentFilterPlugin extends AndroidManifestPlugin { } private boolean isNotMainActivity(Node filter) { - long mainActivityIntentFilters = stream(filter.getChildNodes()) + long mainActivityIntentFilters = xmlHelper.stream(filter.getChildNodes()) .filter(n -> n.getNodeName().matches("action|category")) .map(n -> n.getAttributes().getNamedItem("android:name")) .map(Node::getNodeValue) .filter(v -> v.equals("android.intent.action.MAIN") || v.equals("android.intent.category.LAUNCHER")) .count(); - long currentIntentFilters = stream(filter.getChildNodes()) + long currentIntentFilters = xmlHelper.stream(filter.getChildNodes()) .filter(n -> n.getNodeName().matches("action|category")) .count(); diff --git a/src/main/java/com/bartek/esa/core/plugin/LoggingPlugin.java b/src/main/java/com/bartek/esa/core/plugin/LoggingPlugin.java index 5359fd1..133c468 100644 --- a/src/main/java/com/bartek/esa/core/plugin/LoggingPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/LoggingPlugin.java @@ -1,10 +1,10 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.JavaPlugin; import com.bartek.esa.core.helper.StaticScopeHelper; +import com.bartek.esa.core.helper.StringConcatenationChecker; import com.bartek.esa.core.model.enumeration.Severity; -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.expr.MethodCallExpr; @@ -12,18 +12,21 @@ import javax.inject.Inject; public class LoggingPlugin extends JavaPlugin { private final StaticScopeHelper staticScopeHelper; + private final StringConcatenationChecker stringConcatenationChecker; @Inject - public LoggingPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper, StaticScopeHelper staticScopeHelper) { - super(globMatcher, xmlHelper); + public LoggingPlugin(StaticScopeHelper staticScopeHelper, StringConcatenationChecker stringConcatenationChecker) { this.staticScopeHelper = staticScopeHelper; + this.stringConcatenationChecker = stringConcatenationChecker; } @Override - public void run(CompilationUnit compilationUnit) { - compilationUnit.findAll(MethodCallExpr.class).stream() + public void run(Source java) { + java.getModel().findAll(MethodCallExpr.class).stream() .filter(expr -> expr.getName().getIdentifier().matches("v|d|i|w|e|wtf")) - .filter(staticScopeHelper.isFromScope(compilationUnit, "v|d|i|w|e|wtf", "Log", "android.util")) - .forEach(expr -> addIssue(Severity.INFO, getLineNumberFromExpression(expr), expr.toString())); + .filter(staticScopeHelper.isFromScope(java.getModel(), "v|d|i|w|e|wtf", "Log", "android.util")) + .filter(expr -> expr.getArguments().size() >= 2) + .filter(expr -> stringConcatenationChecker.isStringConcatenation(java.getModel(), expr.getArguments().get(1))) + .forEach(expr -> addJavaIssue(Severity.INFO, java.getFile(), expr)); } } diff --git a/src/main/java/com/bartek/esa/core/plugin/OrderedBroadcastPlugin.java b/src/main/java/com/bartek/esa/core/plugin/OrderedBroadcastPlugin.java index 89a91fd..71f41dc 100644 --- a/src/main/java/com/bartek/esa/core/plugin/OrderedBroadcastPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/OrderedBroadcastPlugin.java @@ -1,25 +1,17 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.JavaPlugin; import com.bartek.esa.core.model.enumeration.Severity; -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.expr.MethodCallExpr; -import javax.inject.Inject; - public class OrderedBroadcastPlugin extends JavaPlugin { - @Inject - public OrderedBroadcastPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); - } - @Override - public void run(CompilationUnit compilationUnit) { - compilationUnit.findAll(MethodCallExpr.class).stream() + public void run(Source java) { + java.getModel().findAll(MethodCallExpr.class).stream() .filter(expr -> expr.getName().getIdentifier().matches("sendOrderedBroadcast|sendOrderedBroadcastAsUser|sendStickyOrderedBroadcast|sendStickyOrderedBroadcastAsUser")) - .forEach(expr -> addIssue(Severity.WARNING, getLineNumberFromExpression(expr), expr.toString())); + .forEach(expr -> addJavaIssue(Severity.WARNING, java.getFile(), expr)); } } diff --git a/src/main/java/com/bartek/esa/core/plugin/PermissionsRaceConditionPlugin.java b/src/main/java/com/bartek/esa/core/plugin/PermissionsRaceConditionPlugin.java index 138521c..e4c8b3e 100644 --- a/src/main/java/com/bartek/esa/core/plugin/PermissionsRaceConditionPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/PermissionsRaceConditionPlugin.java @@ -1,9 +1,9 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.AndroidManifestPlugin; import com.bartek.esa.core.model.enumeration.Severity; import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -15,21 +15,22 @@ import java.util.Map; import static java.lang.Integer.parseInt; public class PermissionsRaceConditionPlugin extends AndroidManifestPlugin { + private final XmlHelper xmlHelper; @Inject - public PermissionsRaceConditionPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); + public PermissionsRaceConditionPlugin(XmlHelper xmlHelper) { + this.xmlHelper = xmlHelper; } @Override - protected void run(Document xml) { - boolean isAnyPermissionDefined = ((NodeList) xPath(xml, "/manifest/permission", XPathConstants.NODESET)).getLength() > 0; + protected void run(Source manifest) { + boolean isAnyPermissionDefined = ((NodeList) xmlHelper.xPath(manifest.getModel(), "/manifest/permission", XPathConstants.NODESET)).getLength() > 0; if(isAnyPermissionDefined) { - Node usesSdkNode = (Node) xPath(xml, "/manifest/uses-sdk", XPathConstants.NODE); + Node usesSdkNode = (Node) xmlHelper.xPath(manifest.getModel(), "/manifest/uses-sdk", XPathConstants.NODE); Node minSdkVersionNode = usesSdkNode.getAttributes().getNamedItem("android:minSdkVersion"); int minSdkVersion = parseInt(minSdkVersionNode.getNodeValue()); if(minSdkVersion < 21) { - addIssue(Severity.VULNERABILITY, getModel(minSdkVersion), null, minSdkVersionNode.toString()); + addIssue(Severity.VULNERABILITY, getModel(minSdkVersion), manifest.getFile(), null, minSdkVersionNode.toString()); } } } diff --git a/src/main/java/com/bartek/esa/core/plugin/SecureRandomPlugin.java b/src/main/java/com/bartek/esa/core/plugin/SecureRandomPlugin.java index 0587539..4dbf696 100644 --- a/src/main/java/com/bartek/esa/core/plugin/SecureRandomPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/SecureRandomPlugin.java @@ -1,26 +1,18 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.JavaPlugin; import com.bartek.esa.core.model.enumeration.Severity; -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.expr.ObjectCreationExpr; -import javax.inject.Inject; - public class SecureRandomPlugin extends JavaPlugin { - @Inject - public SecureRandomPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); - } - @Override - public void run(CompilationUnit compilationUnit) { - compilationUnit.findAll(ObjectCreationExpr.class).stream() + public void run(Source java) { + java.getModel().findAll(ObjectCreationExpr.class).stream() .filter(expr -> expr.getType().getName().getIdentifier().equals("SecureRandom")) .filter(expr -> expr.getArguments().isNonEmpty()) - .forEach(expr -> addIssue(Severity.VULNERABILITY, getLineNumberFromExpression(expr), expr.toString())); + .forEach(expr -> addJavaIssue(Severity.VULNERABILITY, java.getFile(), expr)); } } diff --git a/src/main/java/com/bartek/esa/core/plugin/SharedUidPlugin.java b/src/main/java/com/bartek/esa/core/plugin/SharedUidPlugin.java index b0754ad..97181bd 100644 --- a/src/main/java/com/bartek/esa/core/plugin/SharedUidPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/SharedUidPlugin.java @@ -1,9 +1,9 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.AndroidManifestPlugin; import com.bartek.esa.core.model.enumeration.Severity; import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -12,17 +12,18 @@ import javax.xml.xpath.XPathConstants; import java.util.Optional; public class SharedUidPlugin extends AndroidManifestPlugin { + private final XmlHelper xmlHelper; @Inject - public SharedUidPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); + public SharedUidPlugin(XmlHelper xmlHelper) { + this.xmlHelper = xmlHelper; } @Override - protected void run(Document xml) { - Node manifestNode = (Node) xPath(xml, "/manifest", XPathConstants.NODE); + protected void run(Source manifest) { + Node manifestNode = (Node) xmlHelper.xPath(manifest.getModel(), "/manifest", XPathConstants.NODE); Optional.ofNullable(manifestNode.getAttributes().getNamedItem("android:sharedUserId")).ifPresent(node -> { - addIssue(Severity.VULNERABILITY, null, node.toString()); + addIssue(Severity.VULNERABILITY, manifest.getFile(), null, node.toString()); }); } } diff --git a/src/main/java/com/bartek/esa/core/plugin/SqlInjectionPlugin.java b/src/main/java/com/bartek/esa/core/plugin/SqlInjectionPlugin.java index 670fc30..9b94f37 100644 --- a/src/main/java/com/bartek/esa/core/plugin/SqlInjectionPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/SqlInjectionPlugin.java @@ -1,41 +1,28 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.JavaPlugin; +import com.bartek.esa.core.helper.StringConcatenationChecker; import com.bartek.esa.core.model.enumeration.Severity; -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.MethodCallExpr; import javax.inject.Inject; public class SqlInjectionPlugin extends JavaPlugin { + private final StringConcatenationChecker stringConcatenationChecker; @Inject - public SqlInjectionPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); + public SqlInjectionPlugin(StringConcatenationChecker stringConcatenationChecker) { + this.stringConcatenationChecker = stringConcatenationChecker; } @Override - public void run(CompilationUnit compilationUnit) { - compilationUnit.findAll(MethodCallExpr.class).stream() + public void run(Source java) { + java.getModel().findAll(MethodCallExpr.class).stream() .filter(expr -> expr.getName().getIdentifier().equals("rawQuery")) .filter(expr -> expr.getArguments().size() >= 2) - .filter(this::isConcatenationOrMethodCall) - .filter(this::ifMethodIsStringFormat) - .forEach(expr -> addIssue(Severity.VULNERABILITY, getLineNumberFromExpression(expr), expr.toString())); - } - - private boolean isConcatenationOrMethodCall(MethodCallExpr expr) { - return expr.getArguments().get(0).isBinaryExpr() || expr.getArguments().get(0).isMethodCallExpr(); - } - - private boolean ifMethodIsStringFormat(MethodCallExpr expr) { - if(expr.getArguments().get(0).isMethodCallExpr()) { - return expr.getArguments().get(0).asMethodCallExpr().getName().getIdentifier().equals("format"); - } - - return true; + .filter(expr -> stringConcatenationChecker.isStringConcatenation(java.getModel(), expr.getArguments().get(0))) + .forEach(expr -> addJavaIssue(Severity.VULNERABILITY, java.getFile(), expr)); } } diff --git a/src/main/java/com/bartek/esa/core/plugin/StrictModePlugin.java b/src/main/java/com/bartek/esa/core/plugin/StrictModePlugin.java index 273f2af..89aa2cd 100644 --- a/src/main/java/com/bartek/esa/core/plugin/StrictModePlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/StrictModePlugin.java @@ -1,10 +1,9 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.JavaPlugin; import com.bartek.esa.core.helper.StaticScopeHelper; import com.bartek.esa.core.model.enumeration.Severity; -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.expr.MethodCallExpr; @@ -14,16 +13,15 @@ public class StrictModePlugin extends JavaPlugin { private final StaticScopeHelper staticScopeHelper; @Inject - public StrictModePlugin(GlobMatcher globMatcher, XmlHelper xmlHelper, StaticScopeHelper staticScopeHelper) { - super(globMatcher, xmlHelper); + public StrictModePlugin(StaticScopeHelper staticScopeHelper) { this.staticScopeHelper = staticScopeHelper; } @Override - public void run(CompilationUnit compilationUnit) { - compilationUnit.findAll(MethodCallExpr.class).stream() + public void run(Source java) { + java.getModel().findAll(MethodCallExpr.class).stream() .filter(expr -> expr.getName().getIdentifier().equals("setThreadPolicy")) - .filter(staticScopeHelper.isFromScope(compilationUnit, "setThreadPolicy", "StrictMode", "android.os")) - .forEach(expr -> addIssue(Severity.WARNING, getLineNumberFromExpression(expr), expr.toString())); + .filter(staticScopeHelper.isFromScope(java.getModel(), "setThreadPolicy", "StrictMode", "android.os")) + .forEach(expr -> addJavaIssue(Severity.WARNING, java.getFile(), expr)); } } diff --git a/src/main/java/com/bartek/esa/core/plugin/SuppressWarningsPlugin.java b/src/main/java/com/bartek/esa/core/plugin/SuppressWarningsPlugin.java index ad4f7fc..e053743 100644 --- a/src/main/java/com/bartek/esa/core/plugin/SuppressWarningsPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/SuppressWarningsPlugin.java @@ -1,25 +1,17 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.JavaPlugin; import com.bartek.esa.core.model.enumeration.Severity; -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.expr.AnnotationExpr; -import javax.inject.Inject; - public class SuppressWarningsPlugin extends JavaPlugin { - @Inject - public SuppressWarningsPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); - } - @Override - public void run(CompilationUnit compilationUnit) { - compilationUnit.findAll(AnnotationExpr.class).stream() + public void run(Source java) { + java.getModel().findAll(AnnotationExpr.class).stream() .filter(expr -> expr.getName().getIdentifier().equals("SuppressWarnings")) - .forEach(expr -> addIssue(Severity.WARNING, getLineNumberFromExpression(expr), expr.toString())); + .forEach(expr -> addJavaIssue(Severity.WARNING, java.getFile(), expr)); } } diff --git a/src/main/java/com/bartek/esa/core/plugin/TelephonyManagerPlugin.java b/src/main/java/com/bartek/esa/core/plugin/TelephonyManagerPlugin.java index 86b88a1..22e4128 100644 --- a/src/main/java/com/bartek/esa/core/plugin/TelephonyManagerPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/TelephonyManagerPlugin.java @@ -1,26 +1,18 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.JavaPlugin; import com.bartek.esa.core.model.enumeration.Severity; -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.expr.CastExpr; -import javax.inject.Inject; - public class TelephonyManagerPlugin extends JavaPlugin { - @Inject - public TelephonyManagerPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); - } - @Override - public void run(CompilationUnit compilationUnit) { - compilationUnit.findAll(CastExpr.class).stream() + public void run(Source java) { + java.getModel().findAll(CastExpr.class).stream() .filter(expr -> expr.getType().isClassOrInterfaceType()) .filter(expr -> expr.getType().asClassOrInterfaceType().getName().getIdentifier().equals("TelephonyManager")) - .forEach(expr -> addIssue(Severity.INFO, getLineNumberFromExpression(expr), expr.toString())); + .forEach(expr -> addJavaIssue(Severity.INFO, java.getFile(), expr)); } } diff --git a/src/main/java/com/bartek/esa/core/plugin/TextInputValidationPlugin.java b/src/main/java/com/bartek/esa/core/plugin/TextInputValidationPlugin.java index f9c5054..6337afd 100644 --- a/src/main/java/com/bartek/esa/core/plugin/TextInputValidationPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/TextInputValidationPlugin.java @@ -1,9 +1,9 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.ResourceLayoutPlugin; import com.bartek.esa.core.model.enumeration.Severity; import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -12,18 +12,19 @@ import javax.inject.Inject; import java.util.Optional; public class TextInputValidationPlugin extends ResourceLayoutPlugin { + private final XmlHelper xmlHelper; @Inject - public TextInputValidationPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); + public TextInputValidationPlugin(XmlHelper xmlHelper) { + this.xmlHelper = xmlHelper; } @Override - protected void run(Document xml) { - NodeList editTextNodes = xml.getElementsByTagName("EditText"); - stream(editTextNodes) + protected void run(Source layout) { + NodeList editTextNodes = layout.getModel().getElementsByTagName("EditText"); + xmlHelper.stream(editTextNodes) .filter(this::doesNotHaveInputType) - .forEach(n -> addIssue(Severity.WARNING, null, tagString(n))); + .forEach(n -> addXmlIssue(Severity.WARNING, layout.getFile(), n)); } private boolean doesNotHaveInputType(Node editText) { diff --git a/src/main/java/com/bartek/esa/core/plugin/UsesSdkPlugin.java b/src/main/java/com/bartek/esa/core/plugin/UsesSdkPlugin.java index b65a4f2..e93a542 100644 --- a/src/main/java/com/bartek/esa/core/plugin/UsesSdkPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/UsesSdkPlugin.java @@ -1,9 +1,9 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.AndroidManifestPlugin; import com.bartek.esa.core.model.enumeration.Severity; import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -13,22 +13,23 @@ import java.util.Map; import java.util.Optional; public class UsesSdkPlugin extends AndroidManifestPlugin { + private final XmlHelper xmlHelper; @Inject - public UsesSdkPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); + public UsesSdkPlugin(XmlHelper xmlHelper) { + this.xmlHelper = xmlHelper; } @Override - protected void run(Document xml) { - Optional.ofNullable((Node) xPath(xml, "/manifest/uses-sdk", XPathConstants.NODE)).ifPresentOrElse(usesSdkNode -> { + protected void run(Source manifest) { + Optional.ofNullable((Node) xmlHelper.xPath(manifest.getModel(), "/manifest/uses-sdk", XPathConstants.NODE)).ifPresentOrElse(usesSdkNode -> { if(usesSdkNode.getAttributes().getNamedItem("android:minSdkVersion") == null) { - addIssue(Severity.ERROR, ".USES_SDK.NO_MIN_SDK_VERSION", null, null); + addIssue(Severity.ERROR, ".USES_SDK.NO_MIN_SDK_VERSION", manifest.getFile(), null, null); } Optional.ofNullable(usesSdkNode.getAttributes().getNamedItem("android:maxSdkVersion")).ifPresent(maxSdkVersion -> - addIssue(Severity.ERROR, ".USES_SDK.MAX_SDK_VERSION", Map.of("maxSdkVersion", maxSdkVersion.getNodeValue()),null, maxSdkVersion.toString()) + addIssue(Severity.ERROR, ".USES_SDK.MAX_SDK_VERSION", Map.of("maxSdkVersion", maxSdkVersion.getNodeValue()), manifest.getFile(), null, maxSdkVersion.toString()) ); - }, () -> addIssue(Severity.ERROR, ".NO_USES_SDK", null, null)); + }, () -> addIssue(Severity.ERROR, ".NO_USES_SDK", manifest.getFile(), null, null)); } } diff --git a/src/main/java/com/bartek/esa/core/plugin/WebViewPlugin.java b/src/main/java/com/bartek/esa/core/plugin/WebViewPlugin.java index 07de49b..8f336a0 100644 --- a/src/main/java/com/bartek/esa/core/plugin/WebViewPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/WebViewPlugin.java @@ -1,51 +1,47 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.JavaPlugin; import com.bartek.esa.core.model.enumeration.Severity; -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.MethodCallExpr; -import javax.inject.Inject; +import java.util.function.Consumer; public class WebViewPlugin extends JavaPlugin { private static final String SETTINGS_METHODS = "addJavascriptInterface|setJavaScriptEnabled|setWebContentsDebuggingEnabled|setAllowFileAccess|setDomStorageEnabled"; - @Inject - public WebViewPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); - } - @Override - public void run(CompilationUnit compilationUnit) { - compilationUnit.findAll(MethodCallExpr.class).stream() + public void run(Source java) { + java.getModel().findAll(MethodCallExpr.class).stream() .filter(expr -> expr.getName().getIdentifier().matches(SETTINGS_METHODS)) - .forEach(this::issueMethod); + .forEach(issueMethod(java)); } - private void issueMethod(MethodCallExpr methodCall) { - switch (methodCall.getName().getIdentifier()) { - case "addJavascriptInterface": - addIssue(Severity.VULNERABILITY, ".JS_INTERFACE", getLineNumberFromExpression(methodCall), methodCall.toString()); - break; - case "setJavaScriptEnabled": - issueSettingsMethod(methodCall, ".JS_ENABLED"); - break; - case "setWebContentsDebuggingEnabled": - issueSettingsMethod(methodCall, ".DEBUGGING_ENABLED"); - break; - case "setAllowFileAccess": - issueSettingsMethod(methodCall, ".ALLOW_FILE_ACCESS"); - break; - } + private Consumer issueMethod(Source java) { + return methodCall -> { + switch (methodCall.getName().getIdentifier()) { + case "addJavascriptInterface": + addJavaIssue(Severity.VULNERABILITY, ".JS_INTERFACE", java.getFile(), methodCall); + break; + case "setJavaScriptEnabled": + issueSettingsMethod(java, methodCall, ".JS_ENABLED"); + break; + case "setWebContentsDebuggingEnabled": + issueSettingsMethod(java, methodCall, ".DEBUGGING_ENABLED"); + break; + case "setAllowFileAccess": + issueSettingsMethod(java, methodCall, ".ALLOW_FILE_ACCESS"); + break; + } + }; } - private void issueSettingsMethod(MethodCallExpr methodCall, String descriptionCode) { + private void issueSettingsMethod(Source java, MethodCallExpr methodCall, String descriptionCode) { Expression firstArg = methodCall.getArguments().get(0); if (firstArg.isBooleanLiteralExpr() && firstArg.asBooleanLiteralExpr().getValue()) { - addIssue(Severity.WARNING, descriptionCode, getLineNumberFromExpression(methodCall), methodCall.toString()); + addJavaIssue(Severity.WARNING, descriptionCode, java.getFile(), methodCall); } } } diff --git a/src/main/java/com/bartek/esa/core/plugin/WorldAccessPermissionsPlugin.java b/src/main/java/com/bartek/esa/core/plugin/WorldAccessPermissionsPlugin.java index fb1c8d1..45d00d8 100644 --- a/src/main/java/com/bartek/esa/core/plugin/WorldAccessPermissionsPlugin.java +++ b/src/main/java/com/bartek/esa/core/plugin/WorldAccessPermissionsPlugin.java @@ -1,32 +1,25 @@ package com.bartek.esa.core.plugin; +import com.bartek.esa.context.model.Source; import com.bartek.esa.core.archetype.JavaPlugin; import com.bartek.esa.core.model.enumeration.Severity; -import com.bartek.esa.core.xml.XmlHelper; -import com.bartek.esa.file.matcher.GlobMatcher; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.expr.FieldAccessExpr; import com.github.javaparser.ast.expr.NameExpr; -import javax.inject.Inject; import java.util.Map; public class WorldAccessPermissionsPlugin extends JavaPlugin { - @Inject - public WorldAccessPermissionsPlugin(GlobMatcher globMatcher, XmlHelper xmlHelper) { - super(globMatcher, xmlHelper); - } - @Override - public void run(CompilationUnit compilationUnit) { - compilationUnit.findAll(NameExpr.class).stream() + public void run(Source java) { + java.getModel().findAll(NameExpr.class).stream() .filter(expr -> expr.getName().getIdentifier().matches("MODE_WORLD_(READABLE|WRITEABLE)")) - .forEach(expr -> addIssue(Severity.ERROR, getModel(expr), getLineNumberFromExpression(expr), expr.toString())); + .forEach(expr -> addJavaIssue(Severity.ERROR, getModel(expr), java.getFile(), expr)); - compilationUnit.findAll(FieldAccessExpr.class).stream() + java.getModel().findAll(FieldAccessExpr.class).stream() .filter(expr -> expr.getName().getIdentifier().matches("MODE_WORLD_(READABLE|WRITEABLE)")) - .forEach(expr -> addIssue(Severity.ERROR, getModel(expr), getLineNumberFromExpression(expr), expr.toString())); + .forEach(expr -> addJavaIssue(Severity.ERROR, getModel(expr), java.getFile(), expr)); } private Map getModel(NameExpr expression) { diff --git a/src/main/java/com/bartek/esa/di/DependencyInjector.java b/src/main/java/com/bartek/esa/di/DependencyInjector.java index da0baaa..c74cec1 100644 --- a/src/main/java/com/bartek/esa/di/DependencyInjector.java +++ b/src/main/java/com/bartek/esa/di/DependencyInjector.java @@ -3,6 +3,7 @@ package com.bartek.esa.di; import com.bartek.esa.EsaMain; import com.bartek.esa.analyser.di.AnalyserModule; import com.bartek.esa.cli.di.CliModule; +import com.bartek.esa.context.di.ContextModule; import com.bartek.esa.core.di.CoreModule; import com.bartek.esa.core.di.PluginModule; import com.bartek.esa.decompiler.di.DecompilerModule; @@ -19,7 +20,8 @@ import dagger.Component; CoreModule.class, PluginModule.class, AnalyserModule.class, - FormatterModule.class + FormatterModule.class, + ContextModule.class }) public interface DependencyInjector { EsaMain esa();