From 6a7a868b71a2aaef60a5cb9d5b9eb044366deb90 Mon Sep 17 00:00:00 2001 From: Will Stranathan Date: Sat, 5 Sep 2015 12:57:07 -0400 Subject: [PATCH] Initial checkin of ComposerLockAnalyzer --- .../analyzer/ComposerLockAnalyzer.java | 161 ++ .../analyzer/HintAnalyzer.java | 27 + .../data/composer/ComposerDependency.java | 103 + .../data/composer/ComposerException.java | 52 + .../data/composer/ComposerLockParser.java | 115 ++ .../data/composer/package-info.java | 4 + ...rg.owasp.dependencycheck.analyzer.Analyzer | 1 + .../src/main/resources/composer.lock | 1746 +++++++++++++++++ .../main/resources/dependencycheck.properties | 1 + .../analyzer/ComposerLockAnalyzerTest.java | 101 + .../data/composer/ComposerLockParserTest.java | 68 + .../owasp/dependencycheck/utils/Settings.java | 8 + src/site/markdown/analyzers/composer-lock.md | 7 + src/site/markdown/analyzers/index.md | 1 + 14 files changed, 2395 insertions(+) create mode 100644 dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java create mode 100644 dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerDependency.java create mode 100644 dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerException.java create mode 100644 dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerLockParser.java create mode 100644 dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/package-info.java create mode 100644 dependency-check-core/src/main/resources/composer.lock create mode 100644 dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzerTest.java create mode 100644 dependency-check-core/src/test/java/org/owasp/dependencycheck/data/composer/ComposerLockParserTest.java create mode 100644 src/site/markdown/analyzers/composer-lock.md diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java new file mode 100644 index 000000000..35b0b5a2d --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java @@ -0,0 +1,161 @@ +/* + * 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) 2012 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.analyzer; + +import org.owasp.dependencycheck.Engine; +import org.owasp.dependencycheck.analyzer.exception.AnalysisException; +import org.owasp.dependencycheck.data.composer.ComposerDependency; +import org.owasp.dependencycheck.data.composer.ComposerException; +import org.owasp.dependencycheck.data.composer.ComposerLockParser; +import org.owasp.dependencycheck.dependency.Confidence; +import org.owasp.dependencycheck.dependency.Dependency; +import org.owasp.dependencycheck.utils.Checksum; +import org.owasp.dependencycheck.utils.FileFilterBuilder; +import org.owasp.dependencycheck.utils.Settings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.nio.charset.Charset; +import java.security.MessageDigest; + +/** + * Used to analyze a composer.lock file for a composer PHP app. + * + * @author colezlaw + */ +public class ComposerLockAnalyzer extends AbstractFileTypeAnalyzer { + /** + * The logger + */ + private static final Logger LOGGER = LoggerFactory.getLogger(ComposerLockAnalyzer.class); + + /** + * The analyzer name + */ + private static final String ANALYZER_NAME = "Composer.lock analyzer"; + + /** + * composer.json + */ + private static final String COMPOSER_LOCK = "composer.lock"; + + /** + * The FileFilter + */ + private static final FileFilter FILE_FILTER = FileFilterBuilder.newInstance().addFilenames(COMPOSER_LOCK).build(); + + /** + * Returns the FileFilter + * + * @return the FileFilter + */ + @Override + protected FileFilter getFileFilter() { + return FILE_FILTER; + } + + /** + * Initializes the analyzer + * + * @throws Exception + */ + @Override + protected void initializeFileTypeAnalyzer() throws Exception { + sha1 = MessageDigest.getInstance("SHA1"); + } + + /** + * The MessageDigest for calculating a new digest for the new dependencies added + */ + private MessageDigest sha1 = null; + + /** + * Entry point for the analyzer. + * + * @param dependency the dependency to analyze + * @param engine the engine scanning + * @throws AnalysisException if there's a failure during analysis + */ + @Override + protected void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { + FileInputStream fis = null; + try { + fis = new FileInputStream(dependency.getActualFile()); + final ComposerLockParser clp = new ComposerLockParser(fis); + LOGGER.info("Checking composer.lock file {}", dependency.getActualFilePath()); + clp.process(); + for (ComposerDependency dep : clp.getDependencies()) { + final Dependency d = new Dependency(dependency.getActualFile()); + d.setDisplayFileName(String.format("%s:%s/%s", dependency.getDisplayFileName(), dep.getGroup(), dep.getProject())); + final String filePath = String.format("%s:%s/%s", dependency.getFilePath(), dep.getGroup(), dep.getProject()); + d.setFilePath(filePath); + d.setSha1sum(Checksum.getHex(sha1.digest(filePath.getBytes(Charset.defaultCharset())))); + d.getVendorEvidence().addEvidence(COMPOSER_LOCK, "vendor", dep.getGroup(), Confidence.HIGHEST); + d.getProductEvidence().addEvidence(COMPOSER_LOCK, "product", dep.getProject(), Confidence.HIGHEST); + d.getVersionEvidence().addEvidence(COMPOSER_LOCK, "version", dep.getVersion(), Confidence.HIGHEST); + LOGGER.info("Adding dependency {}", d); + engine.getDependencies().add(d); + } + } catch (FileNotFoundException fnfe) { + LOGGER.warn("Error opening dependency {}", dependency.getActualFilePath()); + } catch (ComposerException ce) { + LOGGER.warn("Error parsing composer.json {}", dependency.getActualFilePath(), ce); + } finally { + if (fis != null) { + try { + fis.close(); + } catch (Exception e) { + LOGGER.debug("Unable to close file", e); + } + } + } + } + + /** + * Gets the key to determine whether the analyzer is enabled. + * + * @return the key specifying whether the analyzer is enabled + */ + @Override + protected String getAnalyzerEnabledSettingKey() { + return Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED; + } + + /** + * Returns the analyzer's name. + * + * @return the analyzer's name + */ + @Override + public String getName() { + return ANALYZER_NAME; + } + + /** + * Returns the phase this analyzer should run under. + * + * @return the analysis phase + */ + @Override + public AnalysisPhase getAnalysisPhase() { + return AnalysisPhase.INFORMATION_COLLECTION; + } +} diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java index fd9297ad5..bb9fa5a00 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java @@ -104,6 +104,21 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer { "spring-security-core", Confidence.HIGH); + final Evidence symfony = new Evidence("composer.lock", + "vendor", + "symfony", + Confidence.HIGHEST); + + final Evidence zendframeworkVendor = new Evidence("composer.lock", + "vendor", + "zendframework", + Confidence.HIGHEST); + + final Evidence zendframeworkProduct = new Evidence("composer.lock", + "product", + "zendframework", + Confidence.HIGHEST); + //springsource/vware problem final Set product = dependency.getProductEvidence().getEvidence(); final Set vendor = dependency.getVendorEvidence().getEvidence(); @@ -128,6 +143,18 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer { dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH); } + if (vendor.contains(symfony)) { + dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "sensiolabs", Confidence.HIGHEST); + } + + if (vendor.contains(zendframeworkVendor)) { + dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "zend", Confidence.HIGHEST); + } + + if (product.contains(zendframeworkProduct)) { + dependency.getProductEvidence().addEvidence("hint analyzer", "vendor", "zend_framework", Confidence.HIGHEST); + } + //sun/oracle problem final Iterator itr = dependency.getVendorEvidence().iterator(); final List newEntries = new ArrayList(); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerDependency.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerDependency.java new file mode 100644 index 000000000..a269567e8 --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerDependency.java @@ -0,0 +1,103 @@ +/* + * 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) 2012 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.data.composer; + +/** + * Reperesents a dependency (GAV, right now) from a Composer dependency. + * + * @author colezlaw + */ +public final class ComposerDependency { + /** The group */ + private final String group; + + /** The project */ + private final String project; + + /** The version */ + private final String version; + + /** + * Create a ComposerDependency from group, project, and version. + * + * @param group the group + * @param project the project + * @param version the version + */ + public ComposerDependency(String group, String project, String version) { + this.group = group; + this.project = project; + this.version = version; + } + + /** + * Get the group. + * + * @return the group + */ + public String getGroup() { + return group; + } + + /** + * Get the project. + * + * @return the project + */ + public String getProject() { + return project; + } + + /** + * Get the version. + * + * @return the version + */ + public String getVersion() { + return version; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ComposerDependency)) { + return false; + } + + final ComposerDependency that = (ComposerDependency) o; + + if (group != null ? !group.equals(that.group) : that.group != null) { + return false; + } + if (project != null ? !project.equals(that.project) : that.project != null) { + return false; + } + return !(version != null ? !version.equals(that.version) : that.version != null); + + } + + @Override + public int hashCode() { + int result = group != null ? group.hashCode() : 0; + result = 31 * result + (project != null ? project.hashCode() : 0); + result = 31 * result + (version != null ? version.hashCode() : 0); + return result; + } +} diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerException.java new file mode 100644 index 000000000..b83cafba0 --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerException.java @@ -0,0 +1,52 @@ +/* + * 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) 2012 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.data.composer; + +/** + * Represents an exception when handling a composer.json or composer.lock + * file. Generally used to wrap a downstream exception. + * + * @author colezlaw + */ +public class ComposerException extends RuntimeException { + /** + * Creates a ComposerException with default message. + */ + public ComposerException() { + super(); + } + + /** + * Creates a ComposerException with the specified message. + * + * @param message the exception message + */ + public ComposerException(String message) { + super(message); + } + + /** + * Creates a Composer exception with the specified message and cause. + * + * @param message the message + * @param cause the underlying cause + */ + public ComposerException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerLockParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerLockParser.java new file mode 100644 index 000000000..b832aa0ab --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerLockParser.java @@ -0,0 +1,115 @@ +/* + * 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) 2012 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.data.composer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonException; +import javax.json.JsonObject; +import javax.json.JsonReader; +import javax.json.stream.JsonParsingException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * Parses a Composer.lock file from an input stream. In a separate class so it can hopefully be injected. + * + * @author colezlaw + */ +public class ComposerLockParser { + /** The JsonReader for parsing JSON */ + private final JsonReader jsonReader; + + /** The input stream we'll read */ + private final InputStream inputStream; // NOPMD - it gets set in the constructor, read later + + /** The List of ComposerDependencies found */ + private final List composerDependencies; + + /** The LOGGER */ + private static final Logger LOGGER = LoggerFactory.getLogger(ComposerLockParser.class); + + /** + * Createas a ComposerLockParser from a JsonReader and an InputStream. + * + * @param inputStream the InputStream to parse + */ + public ComposerLockParser(InputStream inputStream) { + LOGGER.info("Creating a ComposerLockParser"); + this.inputStream = inputStream; + this.jsonReader = Json.createReader(inputStream); + this.composerDependencies = new ArrayList(); + } + + /** + * Process the input stream to create the list of dependencies. + */ + public void process() { + LOGGER.info("Beginning Composer lock processing"); + try { + final JsonObject composer = jsonReader.readObject(); + if (composer.containsKey("packages")) { + LOGGER.debug("Found packages"); + final JsonArray packages = composer.getJsonArray("packages"); + for (JsonObject pkg : packages.getValuesAs(JsonObject.class)) { + if (pkg.containsKey("name")) { + final String groupName = pkg.getString("name"); + if (groupName.indexOf('/') >= 0 && groupName.indexOf('/') <= groupName.length() - 1) { + if (pkg.containsKey("version")) { + final String group = groupName.substring(0, groupName.indexOf('/')); + final String project = groupName.substring(groupName.indexOf('/') + 1); + String version = pkg.getString("version"); + // Some version nubmers begin with v - which doesn't end up matching CPE's + if (version.startsWith("v")) { + version = version.substring(1); + } + LOGGER.debug("Got package {}/{}/{}", group, project, version); + composerDependencies.add(new ComposerDependency(group, project, version)); + } else { + LOGGER.debug("Group/package {} does not have a version", groupName); + } + } else { + LOGGER.debug("Got a dependency with no name"); + } + } + } + } + } catch (JsonParsingException jsonpe) { + throw new ComposerException("Error parsing stream", jsonpe); + } catch (JsonException jsone) { + throw new ComposerException("Error reading stream", jsone); + } catch (IllegalStateException ise) { + throw new ComposerException("Illegal state in composer stream", ise); + } catch (ClassCastException cce) { + throw new ComposerException("Not exactly composer lock", cce); + } + } + + /** + * Gets the list of dependencies. + * + * @return the list of dependencies + */ + public List getDependencies() { + return composerDependencies; + } +} diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/package-info.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/package-info.java new file mode 100644 index 000000000..42bd9f05a --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/package-info.java @@ -0,0 +1,4 @@ +/** + * Model elements for PHP Composer files + */ +package org.owasp.dependencycheck.data.composer; \ No newline at end of file diff --git a/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer b/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer index 7c5aedde9..15d74056a 100644 --- a/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer +++ b/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer @@ -19,3 +19,4 @@ org.owasp.dependencycheck.analyzer.OpenSSLAnalyzer org.owasp.dependencycheck.analyzer.CMakeAnalyzer org.owasp.dependencycheck.analyzer.NodePackageAnalyzer org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzer +org.owasp.dependencycheck.analyzer.ComposerLockAnalyzer diff --git a/dependency-check-core/src/main/resources/composer.lock b/dependency-check-core/src/main/resources/composer.lock new file mode 100644 index 000000000..29c47bb03 --- /dev/null +++ b/dependency-check-core/src/main/resources/composer.lock @@ -0,0 +1,1746 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "c0522252611c314f0e6914e872f42559", + "packages": [ + { + "name": "classpreloader/classpreloader", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/ClassPreloader/ClassPreloader.git", + "reference": "8c3c14b10309e3b40bce833913a6c0c0b8c8f962" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ClassPreloader/ClassPreloader/zipball/8c3c14b10309e3b40bce833913a6c0c0b8c8f962", + "reference": "8c3c14b10309e3b40bce833913a6c0c0b8c8f962", + "shasum": "" + }, + "require": { + "nikic/php-parser": "~1.3", + "php": ">=5.5.9" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "ClassPreloader\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com" + } + ], + "description": "Helps class loading performance by generating a single PHP file containing all of the autoloaded files for a specific use case", + "keywords": [ + "autoload", + "class", + "preload" + ], + "time": "2015-06-28 21:39:13" + }, + { + "name": "danielstjules/stringy", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/danielstjules/Stringy.git", + "reference": "4749c205db47ee5b32e8d1adf6d9aff8db6caf3b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/danielstjules/Stringy/zipball/4749c205db47ee5b32e8d1adf6d9aff8db6caf3b", + "reference": "4749c205db47ee5b32e8d1adf6d9aff8db6caf3b", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Stringy\\": "src/" + }, + "files": [ + "src/Create.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel St. Jules", + "email": "danielst.jules@gmail.com", + "homepage": "http://www.danielstjules.com" + } + ], + "description": "A string manipulation library with multibyte support", + "homepage": "https://github.com/danielstjules/Stringy", + "keywords": [ + "UTF", + "helpers", + "manipulation", + "methods", + "multibyte", + "string", + "utf-8", + "utility", + "utils" + ], + "time": "2015-07-23 00:54:12" + }, + { + "name": "dnoegel/php-xdg-base-dir", + "version": "0.1", + "source": { + "type": "git", + "url": "https://github.com/dnoegel/php-xdg-base-dir.git", + "reference": "265b8593498b997dc2d31e75b89f053b5cc9621a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/265b8593498b997dc2d31e75b89f053b5cc9621a", + "reference": "265b8593498b997dc2d31e75b89f053b5cc9621a", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "@stable" + }, + "type": "project", + "autoload": { + "psr-4": { + "XdgBaseDir\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "implementation of xdg base directory specification for php", + "time": "2014-10-24 07:27:01" + }, + { + "name": "doctrine/inflector", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "0bcb2e79d8571787f18b7eb036ed3d004908e604" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/0bcb2e79d8571787f18b7eb036ed3d004908e604", + "reference": "0bcb2e79d8571787f18b7eb036ed3d004908e604", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "4.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Inflector\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string" + ], + "time": "2014-12-20 21:24:13" + }, + { + "name": "jakub-onderka/php-console-color", + "version": "0.1", + "source": { + "type": "git", + "url": "https://github.com/JakubOnderka/PHP-Console-Color.git", + "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Color/zipball/e0b393dacf7703fc36a4efc3df1435485197e6c1", + "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "jakub-onderka/php-code-style": "1.0", + "jakub-onderka/php-parallel-lint": "0.*", + "jakub-onderka/php-var-dump-check": "0.*", + "phpunit/phpunit": "3.7.*", + "squizlabs/php_codesniffer": "1.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "JakubOnderka\\PhpConsoleColor": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Jakub Onderka", + "email": "jakub.onderka@gmail.com", + "homepage": "http://www.acci.cz" + } + ], + "time": "2014-04-08 15:00:19" + }, + { + "name": "jakub-onderka/php-console-highlighter", + "version": "v0.3.2", + "source": { + "type": "git", + "url": "https://github.com/JakubOnderka/PHP-Console-Highlighter.git", + "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Highlighter/zipball/7daa75df45242c8d5b75a22c00a201e7954e4fb5", + "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5", + "shasum": "" + }, + "require": { + "jakub-onderka/php-console-color": "~0.1", + "php": ">=5.3.0" + }, + "require-dev": { + "jakub-onderka/php-code-style": "~1.0", + "jakub-onderka/php-parallel-lint": "~0.5", + "jakub-onderka/php-var-dump-check": "~0.1", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~1.5" + }, + "type": "library", + "autoload": { + "psr-0": { + "JakubOnderka\\PhpConsoleHighlighter": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jakub Onderka", + "email": "acci@acci.cz", + "homepage": "http://www.acci.cz/" + } + ], + "time": "2015-04-20 18:58:01" + }, + { + "name": "jeremeamia/SuperClosure", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/jeremeamia/super_closure.git", + "reference": "b712f39c671e5ead60c7ebfe662545456aade833" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jeremeamia/super_closure/zipball/b712f39c671e5ead60c7ebfe662545456aade833", + "reference": "b712f39c671e5ead60c7ebfe662545456aade833", + "shasum": "" + }, + "require": { + "nikic/php-parser": "~1.0", + "php": ">=5.4" + }, + "require-dev": { + "codeclimate/php-test-reporter": "~0.1.2", + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "psr-4": { + "SuperClosure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia", + "role": "Developer" + } + ], + "description": "Serialize Closure objects, including their context and binding", + "homepage": "https://github.com/jeremeamia/super_closure", + "keywords": [ + "closure", + "function", + "lambda", + "parser", + "serializable", + "serialize", + "tokenizer" + ], + "time": "2015-03-11 20:06:43" + }, + { + "name": "laravel/framework", + "version": "v5.1.12", + "source": { + "type": "git", + "url": "https://github.com/laravel/framework.git", + "reference": "76a9816f37a58383f6ba093ccf08f253e5488555" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/framework/zipball/76a9816f37a58383f6ba093ccf08f253e5488555", + "reference": "76a9816f37a58383f6ba093ccf08f253e5488555", + "shasum": "" + }, + "require": { + "classpreloader/classpreloader": "~2.0", + "danielstjules/stringy": "~1.8", + "doctrine/inflector": "~1.0", + "ext-mbstring": "*", + "ext-openssl": "*", + "jeremeamia/superclosure": "~2.0", + "league/flysystem": "~1.0", + "monolog/monolog": "~1.11", + "mtdowling/cron-expression": "~1.0", + "nesbot/carbon": "~1.19", + "php": ">=5.5.9", + "psy/psysh": "~0.5.1", + "swiftmailer/swiftmailer": "~5.1", + "symfony/console": "2.7.*", + "symfony/css-selector": "2.7.*", + "symfony/debug": "2.7.*", + "symfony/dom-crawler": "2.7.*", + "symfony/finder": "2.7.*", + "symfony/http-foundation": "2.7.*", + "symfony/http-kernel": "2.7.*", + "symfony/process": "2.7.*", + "symfony/routing": "2.7.*", + "symfony/translation": "2.7.*", + "symfony/var-dumper": "2.7.*", + "vlucas/phpdotenv": "~1.0" + }, + "replace": { + "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", + "illuminate/bus": "self.version", + "illuminate/cache": "self.version", + "illuminate/config": "self.version", + "illuminate/console": "self.version", + "illuminate/container": "self.version", + "illuminate/contracts": "self.version", + "illuminate/cookie": "self.version", + "illuminate/database": "self.version", + "illuminate/encryption": "self.version", + "illuminate/events": "self.version", + "illuminate/exception": "self.version", + "illuminate/filesystem": "self.version", + "illuminate/foundation": "self.version", + "illuminate/hashing": "self.version", + "illuminate/http": "self.version", + "illuminate/log": "self.version", + "illuminate/mail": "self.version", + "illuminate/pagination": "self.version", + "illuminate/pipeline": "self.version", + "illuminate/queue": "self.version", + "illuminate/redis": "self.version", + "illuminate/routing": "self.version", + "illuminate/session": "self.version", + "illuminate/support": "self.version", + "illuminate/translation": "self.version", + "illuminate/validation": "self.version", + "illuminate/view": "self.version" + }, + "require-dev": { + "aws/aws-sdk-php": "~3.0", + "iron-io/iron_mq": "~2.0", + "mockery/mockery": "~0.9.1", + "pda/pheanstalk": "~3.0", + "phpunit/phpunit": "~4.0", + "predis/predis": "~1.0" + }, + "suggest": { + "aws/aws-sdk-php": "Required to use the SQS queue driver and SES mail driver (~3.0).", + "doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.4).", + "fzaninotto/faker": "Required to use the eloquent factory builder (~1.4).", + "guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers (~5.3|~6.0).", + "iron-io/iron_mq": "Required to use the iron queue driver (~2.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).", + "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (~3.0).", + "predis/predis": "Required to use the redis cache and queue drivers (~1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~2.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/Illuminate/Queue/IlluminateQueueClosure.php" + ], + "files": [ + "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Support/helpers.php" + ], + "psr-4": { + "Illuminate\\": "src/Illuminate/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylorotwell@gmail.com" + } + ], + "description": "The Laravel Framework.", + "homepage": "http://laravel.com", + "keywords": [ + "framework", + "laravel" + ], + "time": "2015-08-30 23:25:48" + }, + { + "name": "laravel/laravel", + "version": "v5.1.11", + "source": { + "type": "git", + "url": "https://github.com/laravel/laravel.git", + "reference": "716e65268ae088e5bd73e505acf9695c127aff66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/laravel/zipball/716e65268ae088e5bd73e505acf9695c127aff66", + "reference": "716e65268ae088e5bd73e505acf9695c127aff66", + "shasum": "" + }, + "require": { + "laravel/framework": "5.1.*", + "php": ">=5.5.9" + }, + "require-dev": { + "fzaninotto/faker": "~1.4", + "mockery/mockery": "0.9.*", + "phpspec/phpspec": "~2.1", + "phpunit/phpunit": "~4.0" + }, + "type": "project", + "autoload": { + "classmap": [ + "database" + ], + "psr-4": { + "App\\": "app/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The Laravel Framework.", + "keywords": [ + "framework", + "laravel" + ], + "time": "2015-08-30 11:31:33" + }, + { + "name": "league/flysystem", + "version": "1.0.11", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "c16222fdc02467eaa12cb6d6d0e65527741f6040" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/c16222fdc02467eaa12cb6d6d0e65527741f6040", + "reference": "c16222fdc02467eaa12cb6d6d0e65527741f6040", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "ext-fileinfo": "*", + "mockery/mockery": "~0.9", + "phpspec/phpspec": "^2.2", + "phpspec/prophecy-phpunit": "~1.0", + "phpunit/phpunit": "~4.1" + }, + "suggest": { + "ext-fileinfo": "Required for MimeType", + "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2", + "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3", + "league/flysystem-azure": "Allows you to use Windows Azure Blob storage", + "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching", + "league/flysystem-copy": "Allows you to use Copy.com storage", + "league/flysystem-dropbox": "Allows you to use Dropbox storage", + "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem", + "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files", + "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib", + "league/flysystem-webdav": "Allows you to use WebDAV storage", + "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Filesystem abstraction: Many filesystems, one API.", + "keywords": [ + "Cloud Files", + "WebDAV", + "abstraction", + "aws", + "cloud", + "copy.com", + "dropbox", + "file systems", + "files", + "filesystem", + "filesystems", + "ftp", + "rackspace", + "remote", + "s3", + "sftp", + "storage" + ], + "time": "2015-07-28 20:41:58" + }, + { + "name": "monolog/monolog", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "ec3961874c43840e96da3a8a1ed20d8c73d7e5aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/ec3961874c43840e96da3a8a1ed20d8c73d7e5aa", + "reference": "ec3961874c43840e96da3a8a1ed20d8c73d7e5aa", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "psr/log": "~1.0" + }, + "provide": { + "psr/log-implementation": "1.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "~2.4, >2.4.8", + "doctrine/couchdb": "~1.0@dev", + "graylog2/gelf-php": "~1.0", + "phpunit/phpunit": "~3.7.0", + "raven/raven": "~0.5", + "ruflin/elastica": "0.90.*", + "videlalvaro/php-amqplib": "~2.4" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-mongo": "Allow sending log messages to a MongoDB server", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "raven/raven": "Allow sending log messages to a Sentry server", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "videlalvaro/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.11.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "http://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "time": "2014-09-30 13:30:58" + }, + { + "name": "mtdowling/cron-expression", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/mtdowling/cron-expression.git", + "reference": "fd92e883195e5dfa77720b1868cf084b08be4412" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mtdowling/cron-expression/zipball/fd92e883195e5dfa77720b1868cf084b08be4412", + "reference": "fd92e883195e5dfa77720b1868cf084b08be4412", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "4.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "Cron": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "time": "2015-01-11 23:07:46" + }, + { + "name": "nesbot/carbon", + "version": "1.20.0", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "bfd3eaba109c9a2405c92174c8e17f20c2b9caf3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/bfd3eaba109c9a2405c92174c8e17f20c2b9caf3", + "reference": "bfd3eaba109c9a2405c92174c8e17f20c2b9caf3", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "symfony/translation": "~2.6|~3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Carbon": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "http://nesbot.com" + } + ], + "description": "A simple API extension for DateTime.", + "homepage": "http://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "time": "2015-06-25 04:19:39" + }, + { + "name": "nikic/php-parser", + "version": "v1.4.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "196f177cfefa0f1f7166c0a05d8255889be12418" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/196f177cfefa0f1f7166c0a05d8255889be12418", + "reference": "196f177cfefa0f1f7166c0a05d8255889be12418", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "files": [ + "lib/bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "time": "2015-07-14 17:31:05" + }, + { + "name": "psr/log", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2012-12-21 11:40:51" + }, + { + "name": "psy/psysh", + "version": "v0.5.2", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "aaf8772ade08b5f0f6830774a5d5c2f800415975" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/aaf8772ade08b5f0f6830774a5d5c2f800415975", + "reference": "aaf8772ade08b5f0f6830774a5d5c2f800415975", + "shasum": "" + }, + "require": { + "dnoegel/php-xdg-base-dir": "0.1", + "jakub-onderka/php-console-highlighter": "0.3.*", + "nikic/php-parser": "^1.2.1", + "php": ">=5.3.9", + "symfony/console": "~2.3.10|^2.4.2|~3.0", + "symfony/var-dumper": "~2.7|~3.0" + }, + "require-dev": { + "fabpot/php-cs-fixer": "~1.5", + "phpunit/phpunit": "~3.7|~4.0", + "squizlabs/php_codesniffer": "~2.0", + "symfony/finder": "~2.1|~3.0" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", + "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "0.6.x-dev" + } + }, + "autoload": { + "files": [ + "src/Psy/functions.php" + ], + "psr-0": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "time": "2015-07-16 15:26:57" + }, + { + "name": "swiftmailer/swiftmailer", + "version": "v5.4.1", + "source": { + "type": "git", + "url": "https://github.com/swiftmailer/swiftmailer.git", + "reference": "0697e6aa65c83edf97bb0f23d8763f94e3f11421" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/0697e6aa65c83edf97bb0f23d8763f94e3f11421", + "reference": "0697e6aa65c83edf97bb0f23d8763f94e3f11421", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "mockery/mockery": "~0.9.1,<0.9.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.4-dev" + } + }, + "autoload": { + "files": [ + "lib/swift_required.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Corbyn" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Swiftmailer, free feature-rich PHP mailer", + "homepage": "http://swiftmailer.org", + "keywords": [ + "email", + "mail", + "mailer" + ], + "time": "2015-06-06 14:19:39" + }, + { + "name": "symfony/console", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/Console.git", + "reference": "d6cf02fe73634c96677e428f840704bfbcaec29e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Console/zipball/d6cf02fe73634c96677e428f840704bfbcaec29e", + "reference": "d6cf02fe73634c96677e428f840704bfbcaec29e", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.1", + "symfony/phpunit-bridge": "~2.7", + "symfony/process": "~2.1" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2015-07-28 15:18:12" + }, + { + "name": "symfony/css-selector", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/CssSelector.git", + "reference": "0b5c07b516226b7dd32afbbc82fe547a469c5092" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/CssSelector/zipball/0b5c07b516226b7dd32afbbc82fe547a469c5092", + "reference": "0b5c07b516226b7dd32afbbc82fe547a469c5092", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony CssSelector Component", + "homepage": "https://symfony.com", + "time": "2015-05-15 13:33:16" + }, + { + "name": "symfony/debug", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/Debug.git", + "reference": "9daa1bf9f7e615fa2fba30357e479a90141222e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Debug/zipball/9daa1bf9f7e615fa2fba30357e479a90141222e3", + "reference": "9daa1bf9f7e615fa2fba30357e479a90141222e3", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/class-loader": "~2.2", + "symfony/http-foundation": "~2.1", + "symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2", + "symfony/phpunit-bridge": "~2.7" + }, + "suggest": { + "symfony/http-foundation": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2015-07-09 16:07:40" + }, + { + "name": "symfony/dom-crawler", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/DomCrawler.git", + "reference": "9dabece63182e95c42b06967a0d929a5df78bc35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/9dabece63182e95c42b06967a0d929a5df78bc35", + "reference": "9dabece63182e95c42b06967a0d929a5df78bc35", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/css-selector": "~2.3", + "symfony/phpunit-bridge": "~2.7" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DomCrawler Component", + "homepage": "https://symfony.com", + "time": "2015-07-09 16:07:40" + }, + { + "name": "symfony/event-dispatcher", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/EventDispatcher.git", + "reference": "9310b5f9a87ec2ea75d20fec0b0017c77c66dac3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/9310b5f9a87ec2ea75d20fec0b0017c77c66dac3", + "reference": "9310b5f9a87ec2ea75d20fec0b0017c77c66dac3", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.0,>=2.0.5", + "symfony/dependency-injection": "~2.6", + "symfony/expression-language": "~2.6", + "symfony/phpunit-bridge": "~2.7", + "symfony/stopwatch": "~2.3" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2015-06-18 19:21:56" + }, + { + "name": "symfony/finder", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/Finder.git", + "reference": "ae0f363277485094edc04c9f3cbe595b183b78e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Finder/zipball/ae0f363277485094edc04c9f3cbe595b183b78e4", + "reference": "ae0f363277485094edc04c9f3cbe595b183b78e4", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2015-07-09 16:07:40" + }, + { + "name": "symfony/http-foundation", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/HttpFoundation.git", + "reference": "863af6898081b34c65d42100c370b9f3c51b70ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/863af6898081b34c65d42100c370b9f3c51b70ca", + "reference": "863af6898081b34c65d42100c370b9f3c51b70ca", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/expression-language": "~2.4", + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com", + "time": "2015-07-22 10:11:00" + }, + { + "name": "symfony/http-kernel", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/HttpKernel.git", + "reference": "405d3e7a59ff7a28ec469441326a0ac79065ea98" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/405d3e7a59ff7a28ec469441326a0ac79065ea98", + "reference": "405d3e7a59ff7a28ec469441326a0ac79065ea98", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "psr/log": "~1.0", + "symfony/debug": "~2.6,>=2.6.2", + "symfony/event-dispatcher": "~2.6,>=2.6.7", + "symfony/http-foundation": "~2.5,>=2.5.4" + }, + "conflict": { + "symfony/config": "<2.7" + }, + "require-dev": { + "symfony/browser-kit": "~2.3", + "symfony/class-loader": "~2.1", + "symfony/config": "~2.7", + "symfony/console": "~2.3", + "symfony/css-selector": "~2.0,>=2.0.5", + "symfony/dependency-injection": "~2.2", + "symfony/dom-crawler": "~2.0,>=2.0.5", + "symfony/expression-language": "~2.4", + "symfony/finder": "~2.0,>=2.0.5", + "symfony/phpunit-bridge": "~2.7", + "symfony/process": "~2.0,>=2.0.5", + "symfony/routing": "~2.2", + "symfony/stopwatch": "~2.3", + "symfony/templating": "~2.2", + "symfony/translation": "~2.0,>=2.0.5", + "symfony/var-dumper": "~2.6" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/class-loader": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "", + "symfony/finder": "", + "symfony/var-dumper": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpKernel Component", + "homepage": "https://symfony.com", + "time": "2015-07-31 13:24:45" + }, + { + "name": "symfony/process", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/Process.git", + "reference": "48aeb0e48600321c272955132d7606ab0a49adb3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Process/zipball/48aeb0e48600321c272955132d7606ab0a49adb3", + "reference": "48aeb0e48600321c272955132d7606ab0a49adb3", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2015-07-01 11:25:50" + }, + { + "name": "symfony/routing", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/Routing.git", + "reference": "ea9134f277162b02e5f80ac058b75a77637b0d26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Routing/zipball/ea9134f277162b02e5f80ac058b75a77637b0d26", + "reference": "ea9134f277162b02e5f80ac058b75a77637b0d26", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "conflict": { + "symfony/config": "<2.7" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "doctrine/common": "~2.2", + "psr/log": "~1.0", + "symfony/config": "~2.7", + "symfony/expression-language": "~2.4", + "symfony/http-foundation": "~2.3", + "symfony/phpunit-bridge": "~2.7", + "symfony/yaml": "~2.0,>=2.0.5" + }, + "suggest": { + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/expression-language": "For using expression matching", + "symfony/yaml": "For using the YAML loader" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Routing Component", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "time": "2015-07-09 16:07:40" + }, + { + "name": "symfony/translation", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/Translation.git", + "reference": "c8dc34cc936152c609cdd722af317e4239d10dd6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Translation/zipball/c8dc34cc936152c609cdd722af317e4239d10dd6", + "reference": "c8dc34cc936152c609cdd722af317e4239d10dd6", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "conflict": { + "symfony/config": "<2.7" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.7", + "symfony/intl": "~2.3", + "symfony/phpunit-bridge": "~2.7", + "symfony/yaml": "~2.2" + }, + "suggest": { + "psr/log": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Translation\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Translation Component", + "homepage": "https://symfony.com", + "time": "2015-07-09 16:07:40" + }, + { + "name": "symfony/var-dumper", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "e8903ebba5eb019f5886ffce739ea9e3b7519579" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e8903ebba5eb019f5886ffce739ea9e3b7519579", + "reference": "e8903ebba5eb019f5886ffce739ea9e3b7519579", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "suggest": { + "ext-symfony_debug": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2015-07-28 15:18:12" + }, + { + "name": "vlucas/phpdotenv", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "0cac554ce06277e33ddf9f0b7ade4b8bbf2af3fa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/0cac554ce06277e33ddf9f0b7ade4b8bbf2af3fa", + "reference": "0cac554ce06277e33ddf9f0b7ade4b8bbf2af3fa", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Dotenv": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD" + ], + "authors": [ + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "http://www.vancelucas.com" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "homepage": "http://github.com/vlucas/phpdotenv", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "time": "2015-05-30 15:59:26" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/dependency-check-core/src/main/resources/dependencycheck.properties b/dependency-check-core/src/main/resources/dependencycheck.properties index ab178a0f3..9a45d8f3f 100644 --- a/dependency-check-core/src/main/resources/dependencycheck.properties +++ b/dependency-check-core/src/main/resources/dependencycheck.properties @@ -61,6 +61,7 @@ analyzer.archive.enabled=true analyzer.jar.enabled=true analyzer.nuspec.enabled=true analyzer.assembly.enabled=true +analyzer.composer.lock.enabled=true # the URL for searching Nexus for SHA-1 hashes and whether it's enabled analyzer.nexus.enabled=true diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzerTest.java new file mode 100644 index 000000000..647ab83b1 --- /dev/null +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzerTest.java @@ -0,0 +1,101 @@ +/* + * 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) 2012 Jeremy Long. All Rights Reserved. + */ +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.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.Evidence; + +import java.io.File; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +/** + * Unit tests for NodePackageAnalyzer. + * + * @author Dale Visser + */ +public class ComposerLockAnalyzerTest extends BaseTest { + + /** + * The analyzer to test. + */ + ComposerLockAnalyzer analyzer; + + /** + * Correctly setup the analyzer for testing. + * + * @throws Exception thrown if there is a problem + */ + @Before + public void setUp() throws Exception { + analyzer = new ComposerLockAnalyzer(); + 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 ComposerLockAnalyzer. + */ + @Test + public void testGetName() { + assertEquals("Composer.lock analyzer", analyzer.getName()); + } + + /** + * Test of supportsExtension method, of class ComposerLockAnalyzer. + */ + @Test + public void testSupportsFiles() { + assertTrue(analyzer.accept(new File("composer.lock"))); + } + + /** + * Test of inspect method, of class PythonDistributionAnalyzer. + * + * @throws AnalysisException is thrown when an exception occurs. + */ + @Test + public void testAnalyzePackageJson() throws Exception { + final Engine engine = new Engine(); + final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, + "composer.lock")); + analyzer.analyze(result, engine); + } +} diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/composer/ComposerLockParserTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/composer/ComposerLockParserTest.java new file mode 100644 index 000000000..64349eb0a --- /dev/null +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/composer/ComposerLockParserTest.java @@ -0,0 +1,68 @@ +/* + * 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) 2012 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.data.composer; + +import org.junit.Before; +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.Charset; + +import static org.junit.Assert.*; + +/** + * Created by colezlaw on 9/5/15. + */ +public class ComposerLockParserTest { + private InputStream inputStream; + + @Before + public void setUp() { + inputStream = this.getClass().getClassLoader().getResourceAsStream("composer.lock"); + } + + @Test + public void testValidComposerLock() { + ComposerLockParser clp = new ComposerLockParser(inputStream); + clp.process(); + assertEquals(30, clp.getDependencies().size()); + assertTrue(clp.getDependencies().contains(new ComposerDependency("symfony", "translation", "2.7.3"))); + } + + @Test(expected=ComposerException.class) + public void testNotJSON() throws Exception { + String input = "NOT VALID JSON"; + ComposerLockParser clp = new ComposerLockParser(new ByteArrayInputStream(input.getBytes(Charset.defaultCharset()))); + clp.process(); + } + + @Test(expected=ComposerException.class) + public void testNotComposer() throws Exception { + String input = "[\"ham\",\"eggs\"]"; + ComposerLockParser clp = new ComposerLockParser(new ByteArrayInputStream(input.getBytes(Charset.defaultCharset()))); + clp.process(); + } + + @Test(expected=ComposerException.class) + public void testNotPackagesArray() throws Exception { + String input = "{\"packages\":\"eleventy\"}"; + ComposerLockParser clp = new ComposerLockParser(new ByteArrayInputStream(input.getBytes(Charset.defaultCharset()))); + clp.process(); + } +} diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java index 5967c7b2e..fd565ac80 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java @@ -225,6 +225,14 @@ public final class Settings { * The properties key for whether the node.js package analyzer is enabled. */ public static final String ANALYZER_NODE_PACKAGE_ENABLED = "analyzer.node.package.enabled"; + /** + * The properties key for whether the composer json file analyzer is enabled. + */ + public static final String ANALYZER_COMPOSER_JSON_ENABLED = "analyzer.composer.json.enabled"; + /** + * The properties key for whether the composer lock file analyzer is enabled. + */ + public static final String ANALYZER_COMPOSER_LOCK_ENABLED = "analyzer.composer.lock.enabled"; /** * The properties key for the Nexus search URL. */ diff --git a/src/site/markdown/analyzers/composer-lock.md b/src/site/markdown/analyzers/composer-lock.md new file mode 100644 index 000000000..64c88808d --- /dev/null +++ b/src/site/markdown/analyzers/composer-lock.md @@ -0,0 +1,7 @@ +Composer Lock Analyzer +============== + +OWASP dependency-check includes an analyzer that scans composer.lock files to get exact dependency +version information from PHP projects which are managed with [Composer](http://getcomposer.org/). +If you're using Composer to manage your project, this will only analyze the `composer.lock` file +currently, so you'll need to run `composer install` to have Composer generate this file. diff --git a/src/site/markdown/analyzers/index.md b/src/site/markdown/analyzers/index.md index b2384f102..a4ffedb4b 100644 --- a/src/site/markdown/analyzers/index.md +++ b/src/site/markdown/analyzers/index.md @@ -10,6 +10,7 @@ to extract identification information from the files analyzed. | [Autoconf](./autoconf.html) | Autoconf project configuration files (configure, configure.in, configure.ac) | [Regex](https://en.wikipedia.org/wiki/Regular_expression) scan for AC_INIT metadata, including in generated configuration script. | | [Central](./central-analyzer.html) | Java archive files (\*.jar) | Searches Maven Central or a configured Nexus repository for the file's SHA1 hash. | | [CMake](./cmake.html) | CMake project files (CMakeLists.txt) and scripts (\*.cmake) | Regex scan for project initialization and version setting commands. | +| [Composer Lock](./composer-lock.html) | PHP [Composer](http://getcomposer.org) Lock files (composer.lock) | Parses PHP [Composer](http://getcomposer.org) lock files for exact versions of dependencies. | | [Jar](./jar-analyzer.html) | Java archive files (\*.jar); Web application archive (\*.war) | Examines archive manifest metadata, and Maven Project Object Model files (pom.xml). | | [Nexus](./nexus-analyzer.html) | Java archive files (\*.jar) | Searches Sonatype or a configured Nexus repository for the file's SHA1 hash. In most cases, superceded by Central . | | [Node.js](./nodejs.html) | NPM package specification files (package.json) | Parse JSON format for metadata. |