mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-03-19 07:44:23 +01:00
Merge branch 'master' of github.com:jeremylong/DependencyCheck
This commit is contained in:
@@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-core.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* © Copyright IBM Corporation 2016.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.analyzer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileFilter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.owasp.dependencycheck.Engine;
|
||||||
|
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||||
|
import org.owasp.dependencycheck.dependency.Confidence;
|
||||||
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
|
import org.owasp.dependencycheck.dependency.EvidenceCollection;
|
||||||
|
import org.owasp.dependencycheck.utils.FileFilterBuilder;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This analyzer is used to analyze SWIFT and Objective-C packages by collecting
|
||||||
|
* information from .podspec files. CocoaPods dependency manager see https://cocoapods.org/.
|
||||||
|
*
|
||||||
|
* @author Bianca Jiang (https://twitter.com/biancajiang)
|
||||||
|
*/
|
||||||
|
@Experimental
|
||||||
|
public class CocoaPodsAnalyzer extends AbstractFileTypeAnalyzer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logger.
|
||||||
|
*/
|
||||||
|
// private static final Logger LOGGER = LoggerFactory.getLogger(CocoaPodsAnalyzer.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the analyzer.
|
||||||
|
*/
|
||||||
|
private static final String ANALYZER_NAME = "CocoaPods Package Analyzer";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The phase that this analyzer is intended to run in.
|
||||||
|
*/
|
||||||
|
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The file name to scan.
|
||||||
|
*/
|
||||||
|
public static final String PODSPEC = "podspec";
|
||||||
|
/**
|
||||||
|
* Filter that detects files named "*.podspec".
|
||||||
|
*/
|
||||||
|
private static final FileFilter PODSPEC_FILTER = FileFilterBuilder.newInstance().addExtensions(PODSPEC).build();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The capture group #1 is the block variable.
|
||||||
|
* e.g. "Pod::Spec.new do |spec|"
|
||||||
|
*/
|
||||||
|
private static final Pattern PODSPEC_BLOCK_PATTERN
|
||||||
|
= Pattern.compile("Pod::Spec\\.new\\s+?do\\s+?\\|(.+?)\\|");
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the FileFilter
|
||||||
|
*
|
||||||
|
* @return the FileFilter
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected FileFilter getFileFilter() {
|
||||||
|
return PODSPEC_FILTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initializeFileTypeAnalyzer() {
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the analyzer.
|
||||||
|
*
|
||||||
|
* @return the name of the analyzer.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return ANALYZER_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the phase that the analyzer is intended to run in.
|
||||||
|
*
|
||||||
|
* @return the phase that the analyzer is intended to run in.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AnalysisPhase getAnalysisPhase() {
|
||||||
|
return ANALYSIS_PHASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the key used in the properties file to reference the analyzer's enabled property.
|
||||||
|
*
|
||||||
|
* @return the analyzer's enabled property setting key
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String getAnalyzerEnabledSettingKey() {
|
||||||
|
return Settings.KEYS.ANALYZER_COCOAPODS_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void analyzeFileType(Dependency dependency, Engine engine)
|
||||||
|
throws AnalysisException {
|
||||||
|
|
||||||
|
String contents;
|
||||||
|
try {
|
||||||
|
contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new AnalysisException(
|
||||||
|
"Problem occurred while reading dependency file.", e);
|
||||||
|
}
|
||||||
|
final Matcher matcher = PODSPEC_BLOCK_PATTERN.matcher(contents);
|
||||||
|
if (matcher.find()) {
|
||||||
|
contents = contents.substring(matcher.end());
|
||||||
|
final String blockVariable = matcher.group(1);
|
||||||
|
|
||||||
|
final EvidenceCollection vendor = dependency.getVendorEvidence();
|
||||||
|
final EvidenceCollection product = dependency.getProductEvidence();
|
||||||
|
final EvidenceCollection version = dependency.getVersionEvidence();
|
||||||
|
|
||||||
|
final String name = addStringEvidence(product, contents, blockVariable, "name", "name", Confidence.HIGHEST);
|
||||||
|
if (!name.isEmpty()) {
|
||||||
|
vendor.addEvidence(PODSPEC, "name_project", name, Confidence.HIGHEST);
|
||||||
|
}
|
||||||
|
addStringEvidence(product, contents, blockVariable, "summary", "summary", Confidence.HIGHEST);
|
||||||
|
|
||||||
|
addStringEvidence(vendor, contents, blockVariable, "author", "authors?", Confidence.HIGHEST);
|
||||||
|
addStringEvidence(vendor, contents, blockVariable, "homepage", "homepage", Confidence.HIGHEST);
|
||||||
|
addStringEvidence(vendor, contents, blockVariable, "license", "licen[cs]es?", Confidence.HIGHEST);
|
||||||
|
|
||||||
|
addStringEvidence(version, contents, blockVariable, "version", "version", Confidence.HIGHEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
setPackagePath(dependency);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String addStringEvidence(EvidenceCollection evidences, String contents,
|
||||||
|
String blockVariable, String field, String fieldPattern, Confidence confidence) {
|
||||||
|
String value = "";
|
||||||
|
|
||||||
|
//capture array value between [ ]
|
||||||
|
final Matcher arrayMatcher = Pattern.compile(
|
||||||
|
String.format("\\s*?%s\\.%s\\s*?=\\s*?\\{\\s*?(.*?)\\s*?\\}", blockVariable, fieldPattern), Pattern.CASE_INSENSITIVE).matcher(contents);
|
||||||
|
if(arrayMatcher.find()) {
|
||||||
|
value = arrayMatcher.group(1);
|
||||||
|
}
|
||||||
|
//capture single value between quotes
|
||||||
|
else {
|
||||||
|
final Matcher matcher = Pattern.compile(
|
||||||
|
String.format("\\s*?%s\\.%s\\s*?=\\s*?(['\"])(.*?)\\1", blockVariable, fieldPattern), Pattern.CASE_INSENSITIVE).matcher(contents);
|
||||||
|
if (matcher.find()) {
|
||||||
|
value = matcher.group(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(value.length() > 0)
|
||||||
|
evidences.addEvidence(PODSPEC, field, value, confidence);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPackagePath(Dependency dep) {
|
||||||
|
File file = new File(dep.getFilePath());
|
||||||
|
String parent = file.getParent();
|
||||||
|
if(parent != null)
|
||||||
|
dep.setPackagePath(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -117,6 +117,7 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
|||||||
final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
|
final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
|
||||||
while (subIterator.hasNext()) {
|
while (subIterator.hasNext()) {
|
||||||
final Dependency nextDependency = subIterator.next();
|
final Dependency nextDependency = subIterator.next();
|
||||||
|
Dependency main = null;
|
||||||
if (hashesMatch(dependency, nextDependency) && !containedInWar(dependency.getFilePath())
|
if (hashesMatch(dependency, nextDependency) && !containedInWar(dependency.getFilePath())
|
||||||
&& !containedInWar(nextDependency.getFilePath())) {
|
&& !containedInWar(nextDependency.getFilePath())) {
|
||||||
if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) {
|
if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) {
|
||||||
@@ -143,8 +144,14 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
|||||||
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||||
break; //since we merged into the next dependency - skip forward to the next in mainIterator
|
break; //since we merged into the next dependency - skip forward to the next in mainIterator
|
||||||
}
|
}
|
||||||
} else if (isSameRubyGem(dependency, nextDependency)) {
|
} else if ( (main = getMainGemspecDependency(dependency, nextDependency)) != null ) {
|
||||||
final Dependency main = getMainGemspecDependency(dependency, nextDependency);
|
if (main == dependency) {
|
||||||
|
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||||
|
} else {
|
||||||
|
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
|
||||||
|
break; //since we merged into the next dependency - skip forward to the next in mainIterator
|
||||||
|
}
|
||||||
|
} else if ( (main = getMainSwiftDependency(dependency, nextDependency)) != null) {
|
||||||
if (main == dependency) {
|
if (main == dependency) {
|
||||||
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
|
||||||
} else {
|
} else {
|
||||||
@@ -376,6 +383,33 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bundling same swift dependencies with the same packagePath but identified by different analyzers.
|
||||||
|
*/
|
||||||
|
private boolean isSameSwiftPackage(Dependency dependency1, Dependency dependency2) {
|
||||||
|
if (dependency1 == null || dependency2 == null ||
|
||||||
|
(!dependency1.getFileName().endsWith(".podspec") &&
|
||||||
|
!dependency1.getFileName().equals("Package.swift")) ||
|
||||||
|
(!dependency2.getFileName().endsWith(".podspec") &&
|
||||||
|
!dependency2.getFileName().equals("Package.swift")) ||
|
||||||
|
dependency1.getPackagePath() == null ||
|
||||||
|
dependency2.getPackagePath() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
private Dependency getMainSwiftDependency(Dependency dependency1, Dependency dependency2) {
|
||||||
|
if (isSameSwiftPackage(dependency1, dependency2)) {
|
||||||
|
if(dependency1.getFileName().endsWith(".podspec"))
|
||||||
|
return dependency1;
|
||||||
|
return dependency2;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is likely a very broken attempt at determining if the 'left'
|
* This is likely a very broken attempt at determining if the 'left'
|
||||||
* dependency is the 'core' library in comparison to the 'right' library.
|
* dependency is the 'core' library in comparison to the 'right' library.
|
||||||
|
|||||||
@@ -93,26 +93,27 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
|
|||||||
|
|
||||||
//add version evidence
|
//add version evidence
|
||||||
final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName);
|
final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName);
|
||||||
|
final String packageName = DependencyVersionUtil.parsePreVersion(fileName);
|
||||||
if (version != null) {
|
if (version != null) {
|
||||||
// If the version number is just a number like 2 or 23, reduce the confidence
|
// If the version number is just a number like 2 or 23, reduce the confidence
|
||||||
// a shade. This should hopefully correct for cases like log4j.jar or
|
// a shade. This should hopefully correct for cases like log4j.jar or
|
||||||
// struts2-core.jar
|
// struts2-core.jar
|
||||||
if (version.getVersionParts() == null || version.getVersionParts().size() < 2) {
|
if (version.getVersionParts() == null || version.getVersionParts().size() < 2) {
|
||||||
dependency.getVersionEvidence().addEvidence("file", "name",
|
dependency.getVersionEvidence().addEvidence("file", "version",
|
||||||
version.toString(), Confidence.MEDIUM);
|
version.toString(), Confidence.MEDIUM);
|
||||||
} else {
|
} else {
|
||||||
dependency.getVersionEvidence().addEvidence("file", "version",
|
dependency.getVersionEvidence().addEvidence("file", "version",
|
||||||
version.toString(), Confidence.HIGHEST);
|
version.toString(), Confidence.HIGHEST);
|
||||||
}
|
}
|
||||||
dependency.getVersionEvidence().addEvidence("file", "name",
|
dependency.getVersionEvidence().addEvidence("file", "name",
|
||||||
fileName, Confidence.MEDIUM);
|
packageName, Confidence.MEDIUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IGNORED_FILES.accept(f)) {
|
if (!IGNORED_FILES.accept(f)) {
|
||||||
dependency.getProductEvidence().addEvidence("file", "name",
|
dependency.getProductEvidence().addEvidence("file", "name",
|
||||||
fileName, Confidence.HIGH);
|
packageName, Confidence.HIGH);
|
||||||
dependency.getVendorEvidence().addEvidence("file", "name",
|
dependency.getVendorEvidence().addEvidence("file", "name",
|
||||||
fileName, Confidence.HIGH);
|
packageName, Confidence.HIGH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -685,7 +685,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
foundSomething = true;
|
foundSomething = true;
|
||||||
versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
||||||
} else if ("specification-version".equalsIgnoreCase(key)) {
|
} else if ("specification-version".equalsIgnoreCase(key)) {
|
||||||
specificationVersion = key;
|
specificationVersion = value;
|
||||||
} else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
|
} else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
|
||||||
foundSomething = true;
|
foundSomething = true;
|
||||||
vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
||||||
|
|||||||
@@ -23,25 +23,26 @@ import java.io.FileFilter;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.owasp.dependencycheck.Engine;
|
import org.owasp.dependencycheck.Engine;
|
||||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
import org.owasp.dependencycheck.dependency.Confidence;
|
import org.owasp.dependencycheck.dependency.Confidence;
|
||||||
import org.owasp.dependencycheck.dependency.Dependency;
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
import org.owasp.dependencycheck.dependency.Reference;
|
import org.owasp.dependencycheck.dependency.Reference;
|
||||||
import org.owasp.dependencycheck.dependency.Vulnerability;
|
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||||
|
import org.owasp.dependencycheck.exception.InitializationException;
|
||||||
import org.owasp.dependencycheck.utils.FileFilterBuilder;
|
import org.owasp.dependencycheck.utils.FileFilterBuilder;
|
||||||
import org.owasp.dependencycheck.utils.Settings;
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
|
||||||
import org.owasp.dependencycheck.exception.InitializationException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to analyze Ruby Bundler Gemspec.lock files utilizing the 3rd party
|
* Used to analyze Ruby Bundler Gemspec.lock files utilizing the 3rd party
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016 Bianca Jiang. All Rights Reserved.
|
* © Copyright IBM Corporation 2016.
|
||||||
*/
|
*/
|
||||||
package org.owasp.dependencycheck.analyzer;
|
package org.owasp.dependencycheck.analyzer;
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ import org.owasp.dependencycheck.dependency.Dependency;
|
|||||||
* {@link RubyGemspecAnalyzer}, so it will enabled/disabled with
|
* {@link RubyGemspecAnalyzer}, so it will enabled/disabled with
|
||||||
* {@link RubyGemspecAnalyzer}.
|
* {@link RubyGemspecAnalyzer}.
|
||||||
*
|
*
|
||||||
* @author Bianca Jiang (biancajiang@gmail.com)
|
* @author Bianca Jiang (https://twitter.com/biancajiang)
|
||||||
*/
|
*/
|
||||||
@Experimental
|
@Experimental
|
||||||
public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer {
|
public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer {
|
||||||
|
|||||||
@@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-core.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* © Copyright IBM Corporation 2016.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.analyzer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileFilter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.owasp.dependencycheck.Engine;
|
||||||
|
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||||
|
import org.owasp.dependencycheck.dependency.Confidence;
|
||||||
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
|
import org.owasp.dependencycheck.dependency.EvidenceCollection;
|
||||||
|
import org.owasp.dependencycheck.utils.FileFilterBuilder;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This analyzer is used to analyze the SWIFT Package Manager (https://swift.org/package-manager/).
|
||||||
|
* It collects information about a package from Package.swift files.
|
||||||
|
*
|
||||||
|
* @author Bianca Jiang (https://twitter.com/biancajiang)
|
||||||
|
*/
|
||||||
|
@Experimental
|
||||||
|
public class SwiftPackageManagerAnalyzer extends AbstractFileTypeAnalyzer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the analyzer.
|
||||||
|
*/
|
||||||
|
private static final String ANALYZER_NAME = "SWIFT Package Manager Analyzer";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The phase that this analyzer is intended to run in.
|
||||||
|
*/
|
||||||
|
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The file name to scan.
|
||||||
|
*/
|
||||||
|
public static final String SPM_FILE_NAME = "Package.swift";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter that detects files named "package.json".
|
||||||
|
*/
|
||||||
|
private static final FileFilter SPM_FILE_FILTER = FileFilterBuilder.newInstance().addFilenames(SPM_FILE_NAME).build();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The capture group #1 is the block variable.
|
||||||
|
* e.g.
|
||||||
|
* "import PackageDescription
|
||||||
|
* let package = Package(
|
||||||
|
* name: "Gloss"
|
||||||
|
* )"
|
||||||
|
*/
|
||||||
|
private static final Pattern SPM_BLOCK_PATTERN
|
||||||
|
= Pattern.compile("let[^=]+=\\s*Package\\s*\\(\\s*([^)]*)\\s*\\)", Pattern.DOTALL);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the FileFilter
|
||||||
|
*
|
||||||
|
* @return the FileFilter
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected FileFilter getFileFilter() {
|
||||||
|
return SPM_FILE_FILTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initializeFileTypeAnalyzer() {
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the analyzer.
|
||||||
|
*
|
||||||
|
* @return the name of the analyzer.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return ANALYZER_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the phase that the analyzer is intended to run in.
|
||||||
|
*
|
||||||
|
* @return the phase that the analyzer is intended to run in.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AnalysisPhase getAnalysisPhase() {
|
||||||
|
return ANALYSIS_PHASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the key used in the properties file to reference the analyzer's enabled property.
|
||||||
|
*
|
||||||
|
* @return the analyzer's enabled property setting key
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String getAnalyzerEnabledSettingKey() {
|
||||||
|
return Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void analyzeFileType(Dependency dependency, Engine engine)
|
||||||
|
throws AnalysisException {
|
||||||
|
|
||||||
|
String contents;
|
||||||
|
try {
|
||||||
|
contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new AnalysisException(
|
||||||
|
"Problem occurred while reading dependency file.", e);
|
||||||
|
}
|
||||||
|
final Matcher matcher = SPM_BLOCK_PATTERN.matcher(contents);
|
||||||
|
if (matcher.find()) {
|
||||||
|
contents = contents.substring(matcher.end());
|
||||||
|
final String packageDescription = matcher.group(1);
|
||||||
|
if(packageDescription.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
final EvidenceCollection product = dependency.getProductEvidence();
|
||||||
|
final EvidenceCollection vendor = dependency.getVendorEvidence();
|
||||||
|
|
||||||
|
//SPM is currently under development for SWIFT 3. Its current metadata includes package name and dependencies.
|
||||||
|
//Future interesting metadata: version, license, homepage, author, summary, etc.
|
||||||
|
final String name = addStringEvidence(product, packageDescription, "name", "name", Confidence.HIGHEST);
|
||||||
|
if (!name.isEmpty()) {
|
||||||
|
vendor.addEvidence(SPM_FILE_NAME, "name_project", name, Confidence.HIGHEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setPackagePath(dependency);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String addStringEvidence(EvidenceCollection evidences,
|
||||||
|
String packageDescription, String field, String fieldPattern, Confidence confidence) {
|
||||||
|
String value = "";
|
||||||
|
|
||||||
|
final Matcher matcher = Pattern.compile(
|
||||||
|
String.format("%s *:\\s*\"([^\"]*)", fieldPattern), Pattern.DOTALL).matcher(packageDescription);
|
||||||
|
if(matcher.find()) {
|
||||||
|
value = matcher.group(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(value != null) {
|
||||||
|
value = value.trim();
|
||||||
|
if(value.length() > 0)
|
||||||
|
evidences.addEvidence (SPM_FILE_NAME, field, value, confidence);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPackagePath(Dependency dep) {
|
||||||
|
File file = new File(dep.getFilePath());
|
||||||
|
String parent = file.getParent();
|
||||||
|
if(parent != null)
|
||||||
|
dep.setPackagePath(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,6 +40,11 @@ public final class DependencyVersionUtil {
|
|||||||
*/
|
*/
|
||||||
private static final Pattern RX_SINGLE_VERSION = Pattern.compile("\\d+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?");
|
private static final Pattern RX_SINGLE_VERSION = Pattern.compile("\\d+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regular expression to extract the part before the version numbers if there are any based on RX_VERSION. In most cases, this part represents a more accurate name.
|
||||||
|
*/
|
||||||
|
private static final Pattern RX_PRE_VERSION = Pattern.compile("^(.+)[_-](\\d+\\.\\d{1,6})+");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private constructor for utility class.
|
* Private constructor for utility class.
|
||||||
*/
|
*/
|
||||||
@@ -95,4 +100,27 @@ public final class DependencyVersionUtil {
|
|||||||
}
|
}
|
||||||
return new DependencyVersion(version);
|
return new DependencyVersion(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* A utility class to extract the part before version numbers from file names (or other strings containing version numbers.
|
||||||
|
* In most cases, this part represents a more accurate name than the full file name.</p>
|
||||||
|
* <pre>
|
||||||
|
* Example:
|
||||||
|
* Give the file name: library-name-1.4.1r2-release.jar
|
||||||
|
* This function would return: library-name</pre>
|
||||||
|
*
|
||||||
|
* @param text the text being analyzed
|
||||||
|
* @return the part before the version numbers if any, otherwise return the text itself.
|
||||||
|
*/
|
||||||
|
public static String parsePreVersion(String text) {
|
||||||
|
if(parseVersion(text) == null)
|
||||||
|
return text;
|
||||||
|
|
||||||
|
Matcher matcher = RX_PRE_VERSION.matcher(text);
|
||||||
|
if (matcher.find()) {
|
||||||
|
return matcher.group(1);
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,3 +22,5 @@ org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzer
|
|||||||
org.owasp.dependencycheck.analyzer.RubyBundlerAnalyzer
|
org.owasp.dependencycheck.analyzer.RubyBundlerAnalyzer
|
||||||
org.owasp.dependencycheck.analyzer.RubyBundleAuditAnalyzer
|
org.owasp.dependencycheck.analyzer.RubyBundleAuditAnalyzer
|
||||||
org.owasp.dependencycheck.analyzer.ComposerLockAnalyzer
|
org.owasp.dependencycheck.analyzer.ComposerLockAnalyzer
|
||||||
|
org.owasp.dependencycheck.analyzer.CocoaPodsAnalyzer
|
||||||
|
org.owasp.dependencycheck.analyzer.SwiftPackageManagerAnalyzer
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ analyzer.nuspec.enabled=true
|
|||||||
analyzer.openssl.enabled=true
|
analyzer.openssl.enabled=true
|
||||||
analyzer.central.enabled=true
|
analyzer.central.enabled=true
|
||||||
analyzer.nexus.enabled=false
|
analyzer.nexus.enabled=false
|
||||||
|
analyzer.cocoapods.enabled=true
|
||||||
|
analyzer.swift.package.manager.enabled=true
|
||||||
#whether the nexus analyzer uses the proxy
|
#whether the nexus analyzer uses the proxy
|
||||||
analyzer.nexus.proxy=true
|
analyzer.nexus.proxy=true
|
||||||
|
|
||||||
|
|||||||
@@ -117,7 +117,6 @@ public class RubyBundleAuditAnalyzerTest extends BaseDBTestCase {
|
|||||||
final Engine engine = new Engine();
|
final Engine engine = new Engine();
|
||||||
analyzer.analyze(result, engine);
|
analyzer.analyze(result, engine);
|
||||||
int size = engine.getDependencies().size();
|
int size = engine.getDependencies().size();
|
||||||
|
|
||||||
assertTrue(size >= 1);
|
assertTrue(size >= 1);
|
||||||
|
|
||||||
Dependency dependency = engine.getDependencies().get(0);
|
Dependency dependency = engine.getDependencies().get(0);
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
package org.owasp.dependencycheck.analyzer;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.owasp.dependencycheck.BaseTest;
|
||||||
|
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||||
|
import org.owasp.dependencycheck.dependency.Dependency;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for CocoaPodsAnalyzer.
|
||||||
|
*
|
||||||
|
* @author Bianca Jiang
|
||||||
|
*/
|
||||||
|
public class SwiftAnalyzersTest extends BaseTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The analyzer to test.
|
||||||
|
*/
|
||||||
|
CocoaPodsAnalyzer podsAnalyzer;
|
||||||
|
SwiftPackageManagerAnalyzer spmAnalyzer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correctly setup the analyzer for testing.
|
||||||
|
*
|
||||||
|
* @throws Exception thrown if there is a problem
|
||||||
|
*/
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
podsAnalyzer = new CocoaPodsAnalyzer();
|
||||||
|
podsAnalyzer.setFilesMatched(true);
|
||||||
|
podsAnalyzer.initialize();
|
||||||
|
|
||||||
|
spmAnalyzer = new SwiftPackageManagerAnalyzer();
|
||||||
|
spmAnalyzer.setFilesMatched(true);
|
||||||
|
spmAnalyzer.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup the analyzer's temp files, etc.
|
||||||
|
*
|
||||||
|
* @throws Exception thrown if there is a problem
|
||||||
|
*/
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
podsAnalyzer.close();
|
||||||
|
podsAnalyzer = null;
|
||||||
|
|
||||||
|
spmAnalyzer.close();
|
||||||
|
spmAnalyzer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of getName method, of class CocoaPodsAnalyzer.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testPodsGetName() {
|
||||||
|
assertThat(podsAnalyzer.getName(), is("CocoaPods Package Analyzer"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of getName method, of class SwiftPackageManagerAnalyzer.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSPMGetName() {
|
||||||
|
assertThat(spmAnalyzer.getName(), is("SWIFT Package Manager Analyzer"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of supportsFiles method, of class CocoaPodsAnalyzer.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testPodsSupportsFiles() {
|
||||||
|
assertThat(podsAnalyzer.accept(new File("test.podspec")), is(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of supportsFiles method, of class SwiftPackageManagerAnalyzer.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSPMSupportsFiles() {
|
||||||
|
assertThat(spmAnalyzer.accept(new File("Package.swift")), is(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of analyze method, of class CocoaPodsAnalyzer.
|
||||||
|
*
|
||||||
|
* @throws AnalysisException is thrown when an exception occurs.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCocoaPodsAnalyzer() throws AnalysisException {
|
||||||
|
final Dependency result = new Dependency(BaseTest.getResourceAsFile(this,
|
||||||
|
"swift/cocoapods/EasyPeasy.podspec"));
|
||||||
|
podsAnalyzer.analyze(result, null);
|
||||||
|
final String vendorString = result.getVendorEvidence().toString();
|
||||||
|
|
||||||
|
assertThat(vendorString, containsString("Carlos Vidal"));
|
||||||
|
assertThat(vendorString, containsString("https://github.com/nakiostudio/EasyPeasy"));
|
||||||
|
assertThat(vendorString, containsString("MIT"));
|
||||||
|
assertThat(result.getProductEvidence().toString(), containsString("EasyPeasy"));
|
||||||
|
assertThat(result.getVersionEvidence().toString(), containsString("0.2.3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of analyze method, of class SwiftPackageManagerAnalyzer.
|
||||||
|
*
|
||||||
|
* @throws AnalysisException is thrown when an exception occurs.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSPMAnalyzer() throws AnalysisException {
|
||||||
|
final Dependency result = new Dependency(BaseTest.getResourceAsFile(this,
|
||||||
|
"swift/Gloss/Package.swift"));
|
||||||
|
spmAnalyzer.analyze(result, null);
|
||||||
|
|
||||||
|
assertThat(result.getProductEvidence().toString(), containsString("Gloss"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
Pod::Spec.new do |s|
|
||||||
|
s.name = "Gloss"
|
||||||
|
s.version = "0.7.2"
|
||||||
|
s.summary = "A shiny JSON parsing library in Swift"
|
||||||
|
s.description = "A shiny JSON parsing library in Swift. Features include mapping JSON to objects, mapping objects to JSON, handling of nested objects and custom transformations."
|
||||||
|
s.homepage = "https://github.com/hkellaway/Gloss"
|
||||||
|
s.license = { :type => "MIT", :file => "LICENSE" }
|
||||||
|
s.author = { "Harlan Kellaway" => "hello@harlankellaway.com" }
|
||||||
|
s.social_media_url = "http://twitter.com/HarlanKellaway"
|
||||||
|
s.source = { :git => "https://github.com/hkellaway/Gloss.git", :tag => s.version.to_s }
|
||||||
|
|
||||||
|
s.platforms = { :ios => "8.0", :osx => "10.9", :tvos => "9.0", :watchos => "2.0" }
|
||||||
|
s.requires_arc = true
|
||||||
|
|
||||||
|
s.source_files = 'Sources/*.{swift}'
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// Package.swift
|
||||||
|
// Gloss
|
||||||
|
//
|
||||||
|
// Copyright (c) 2015 Harlan Kellaway
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
import PackageDescription
|
||||||
|
|
||||||
|
let package = Package(
|
||||||
|
name: "Gloss"
|
||||||
|
)
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
Pod::Spec.new do |s|
|
||||||
|
s.name = "EasyPeasy"
|
||||||
|
s.version = "0.2.3"
|
||||||
|
s.summary = "EasyPeasy is a Swift framework that eases the creation of
|
||||||
|
Autolayout constraints programmatically"
|
||||||
|
s.description = <<-DESC
|
||||||
|
EasyPeasy is a Swift framework that lets you create Autolayout constraints
|
||||||
|
programmatically without headaches and never ending boilerplate code. Besides the
|
||||||
|
basics, **EasyPeasy** resolves most of the constraint conflicts for you and lets
|
||||||
|
you attach to a constraint conditional closures that are evaluated before applying
|
||||||
|
a constraint, this lets you apply (or not) a constraint depending on platform, size
|
||||||
|
classes, orientation... or the state of your controller, easy peasy!
|
||||||
|
DESC
|
||||||
|
s.homepage = "https://github.com/nakiostudio/EasyPeasy"
|
||||||
|
s.license = 'MIT'
|
||||||
|
s.author = { "Carlos Vidal" => "nakioparkour@gmail.com" }
|
||||||
|
s.source = { :git => "https://github.com/nakiostudio/EasyPeasy.git", :tag => s.version.to_s }
|
||||||
|
s.social_media_url = 'https://twitter.com/carlostify'
|
||||||
|
|
||||||
|
s.platform = :ios, '8.0'
|
||||||
|
s.requires_arc = true
|
||||||
|
|
||||||
|
s.source_files = 'EasyPeasy/**/*'
|
||||||
|
s.frameworks = 'UIKit'
|
||||||
|
end
|
||||||
@@ -288,6 +288,14 @@ public final class Settings {
|
|||||||
* The properties key for whether the OpenSSL analyzer is enabled.
|
* The properties key for whether the OpenSSL analyzer is enabled.
|
||||||
*/
|
*/
|
||||||
public static final String ANALYZER_OPENSSL_ENABLED = "analyzer.openssl.enabled";
|
public static final String ANALYZER_OPENSSL_ENABLED = "analyzer.openssl.enabled";
|
||||||
|
/**
|
||||||
|
* The properties key for whether the cocoapods analyzer is enabled.
|
||||||
|
*/
|
||||||
|
public static final String ANALYZER_COCOAPODS_ENABLED = "analyzer.cocoapods.enabled";
|
||||||
|
/**
|
||||||
|
* The properties key for whether the SWIFT package manager analyzer is enabled.
|
||||||
|
*/
|
||||||
|
public static final String ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED = "analyzer.swift.package.manager.enabled";
|
||||||
/**
|
/**
|
||||||
* The properties key for the Central search URL.
|
* The properties key for the Central search URL.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user