mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-01-14 15:53:36 +01:00
support cocoapods for swift
This commit is contained in:
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* 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 (c) 2015 Bianca Jiang. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.analyzer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.json.JsonObject;
|
||||
import javax.json.JsonString;
|
||||
import javax.json.JsonValue;
|
||||
|
||||
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;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author Bianca Xue Jiang
|
||||
*
|
||||
*/
|
||||
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 "package.json".
|
||||
*/
|
||||
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() throws Exception {
|
||||
// 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_NODE_PACKAGE_ENABLED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void analyzeFileType(Dependency dependency, Engine engine)
|
||||
throws AnalysisException {
|
||||
|
||||
String contents;
|
||||
try {
|
||||
contents = FileUtils.readFileToString(dependency.getActualFile());
|
||||
} 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.LOW);
|
||||
}
|
||||
addStringEvidence(product, contents, blockVariable, "summary", "summary", Confidence.LOW);
|
||||
|
||||
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);
|
||||
|
||||
// final File file = dependency.getActualFile();
|
||||
// JsonReader jsonReader;
|
||||
// try {
|
||||
// jsonReader = Json.createReader(FileUtils.openInputStream(file));
|
||||
// } catch (IOException e) {
|
||||
// throw new AnalysisException(
|
||||
// "Problem occurred while reading dependency file.", e);
|
||||
// }
|
||||
// try {
|
||||
// final JsonObject json = jsonReader.readObject();
|
||||
// final EvidenceCollection productEvidence = dependency.getProductEvidence();
|
||||
// final EvidenceCollection vendorEvidence = dependency.getVendorEvidence();
|
||||
// if (json.containsKey("name")) {
|
||||
// final Object value = json.get("name");
|
||||
// if (value instanceof JsonString) {
|
||||
// final String valueString = ((JsonString) value).getString();
|
||||
// productEvidence.addEvidence(PODSPEC, "name", valueString, Confidence.HIGHEST);
|
||||
// vendorEvidence.addEvidence(PODSPEC, "name_project", String.format("%s_project", valueString), Confidence.LOW);
|
||||
// } else {
|
||||
// LOGGER.warn("JSON value not string as expected: {}", value);
|
||||
// }
|
||||
// }
|
||||
// addToEvidence(json, productEvidence, "description");
|
||||
// addToEvidence(json, vendorEvidence, "author");
|
||||
// addToEvidence(json, dependency.getVersionEvidence(), "version");
|
||||
// dependency.setDisplayFileName(String.format("%s/%s", file.getParentFile().getName(), file.getName()));
|
||||
// } catch (JsonException e) {
|
||||
// LOGGER.warn("Failed to parse package.json file.", e);
|
||||
// } finally {
|
||||
// jsonReader.close();
|
||||
// }
|
||||
}
|
||||
|
||||
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*?\\[(.*?)\\]", blockVariable, fieldPattern), Pattern.CASE_INSENSITIVE).matcher(contents);
|
||||
if(arrayMatcher.find()) {
|
||||
String arrayValue = arrayMatcher.group(1);
|
||||
value = arrayValue.replaceAll("['\"]", "").trim(); //strip quotes
|
||||
}
|
||||
//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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds information to an evidence collection from the node json configuration.
|
||||
*
|
||||
* @param json information from node.js
|
||||
* @param collection a set of evidence about a dependency
|
||||
* @param key the key to obtain the data from the json information
|
||||
*/
|
||||
private void addToEvidence(JsonObject json, EvidenceCollection collection, String key) {
|
||||
if (json.containsKey(key)) {
|
||||
final JsonValue value = json.get(key);
|
||||
if (value instanceof JsonString) {
|
||||
collection.addEvidence(PODSPEC, key, ((JsonString) value).getString(), Confidence.HIGHEST);
|
||||
} else if (value instanceof JsonObject) {
|
||||
final JsonObject jsonObject = (JsonObject) value;
|
||||
for (final Map.Entry<String, JsonValue> entry : jsonObject.entrySet()) {
|
||||
final String property = entry.getKey();
|
||||
final JsonValue subValue = entry.getValue();
|
||||
if (subValue instanceof JsonString) {
|
||||
collection.addEvidence(PODSPEC,
|
||||
String.format("%s.%s", key, property),
|
||||
((JsonString) subValue).getString(),
|
||||
Confidence.HIGHEST);
|
||||
} else {
|
||||
LOGGER.warn("JSON sub-value not string as expected: {}", subValue);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOGGER.warn("JSON value not string or JSON object as expected: {}", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,3 +22,4 @@ org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzer
|
||||
org.owasp.dependencycheck.analyzer.RubyBundleInstallDeploymentAnalyzer
|
||||
org.owasp.dependencycheck.analyzer.RubyBundleAuditAnalyzer
|
||||
org.owasp.dependencycheck.analyzer.ComposerLockAnalyzer
|
||||
org.owasp.dependencycheck.analyzer.CocoaPodsAnalyzer
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
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 CocoaPodsAnalyzerTest extends BaseTest {
|
||||
|
||||
/**
|
||||
* The analyzer to test.
|
||||
*/
|
||||
CocoaPodsAnalyzer analyzer;
|
||||
|
||||
/**
|
||||
* Correctly setup the analyzer for testing.
|
||||
*
|
||||
* @throws Exception thrown if there is a problem
|
||||
*/
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
analyzer = new CocoaPodsAnalyzer();
|
||||
analyzer.setFilesMatched(true);
|
||||
analyzer.initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup the analyzer's temp files, etc.
|
||||
*
|
||||
* @throws Exception thrown if there is a problem
|
||||
*/
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
analyzer.close();
|
||||
analyzer = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getName method, of class PythonDistributionAnalyzer.
|
||||
*/
|
||||
@Test
|
||||
public void testGetName() {
|
||||
assertThat(analyzer.getName(), is("CocoaPods Package Analyzer"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of supportsExtension method, of class PythonDistributionAnalyzer.
|
||||
*/
|
||||
@Test
|
||||
public void testSupportsFiles() {
|
||||
assertThat(analyzer.accept(new File("test.podspec")), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of inspect method, of class PythonDistributionAnalyzer.
|
||||
*
|
||||
* @throws AnalysisException is thrown when an exception occurs.
|
||||
*/
|
||||
@Test
|
||||
public void testAnalyzePackageJson() throws AnalysisException {
|
||||
final Dependency result = new Dependency(BaseTest.getResourceAsFile(this,
|
||||
"swift/cocoapods/EasyPeasy.podspec"));
|
||||
analyzer.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"));
|
||||
|
||||
System.out.println("vendor: " + vendorString);
|
||||
System.out.println("product: " + result.getProductEvidence().toString());
|
||||
System.out.println("version: " + result.getVersionEvidence().toString());
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user