Coverage Report - org.owasp.dependencycheck.analyzer.SwiftPackageManagerAnalyzer
 
Classes in this File Line Coverage Branch Coverage Complexity
SwiftPackageManagerAnalyzer
92%
37/40
50%
8/16
2.375
 
 1  
 /*
 2  
  * This file is part of dependency-check-core.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  *
 16  
  * Copyright (c) 2016 IBM Corporation. All Rights Reserved.
 17  
  */
 18  
 package org.owasp.dependencycheck.analyzer;
 19  
 
 20  
 import java.io.File;
 21  
 import java.io.FileFilter;
 22  
 import java.io.IOException;
 23  
 import java.nio.charset.Charset;
 24  
 import java.util.regex.Matcher;
 25  
 import java.util.regex.Pattern;
 26  
 
 27  
 import org.apache.commons.io.FileUtils;
 28  
 import org.owasp.dependencycheck.Engine;
 29  
 import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
 30  
 import org.owasp.dependencycheck.dependency.Confidence;
 31  
 import org.owasp.dependencycheck.dependency.Dependency;
 32  
 import org.owasp.dependencycheck.dependency.EvidenceCollection;
 33  
 import org.owasp.dependencycheck.utils.FileFilterBuilder;
 34  
 import org.owasp.dependencycheck.utils.Settings;
 35  
 
 36  
 /**
 37  
  * This analyzer is used to analyze the SWIFT Package Manager
 38  
  * (https://swift.org/package-manager/). It collects information about a package
 39  
  * from Package.swift files.
 40  
  *
 41  
  * @author Bianca Jiang (https://twitter.com/biancajiang)
 42  
  */
 43  
 @Experimental
 44  14
 public class SwiftPackageManagerAnalyzer extends AbstractFileTypeAnalyzer {
 45  
 
 46  
     /**
 47  
      * The name of the analyzer.
 48  
      */
 49  
     private static final String ANALYZER_NAME = "SWIFT Package Manager Analyzer";
 50  
 
 51  
     /**
 52  
      * The phase that this analyzer is intended to run in.
 53  
      */
 54  1
     private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
 55  
 
 56  
     /**
 57  
      * The file name to scan.
 58  
      */
 59  
     public static final String SPM_FILE_NAME = "Package.swift";
 60  
 
 61  
     /**
 62  
      * Filter that detects files named "package.json".
 63  
      */
 64  1
     private static final FileFilter SPM_FILE_FILTER = FileFilterBuilder.newInstance().addFilenames(SPM_FILE_NAME).build();
 65  
 
 66  
     /**
 67  
      * The capture group #1 is the block variable. e.g. "import
 68  
      * PackageDescription let package = Package( name: "Gloss" )"
 69  
      */
 70  1
     private static final Pattern SPM_BLOCK_PATTERN = Pattern.compile("let[^=]+=\\s*Package\\s*\\(\\s*([^)]*)\\s*\\)", Pattern.DOTALL);
 71  
 
 72  
     /**
 73  
      * Returns the FileFilter
 74  
      *
 75  
      * @return the FileFilter
 76  
      */
 77  
     @Override
 78  
     protected FileFilter getFileFilter() {
 79  859
         return SPM_FILE_FILTER;
 80  
     }
 81  
 
 82  
     @Override
 83  
     protected void initializeFileTypeAnalyzer() {
 84  
         // NO-OP
 85  6
     }
 86  
 
 87  
     /**
 88  
      * Returns the name of the analyzer.
 89  
      *
 90  
      * @return the name of the analyzer.
 91  
      */
 92  
     @Override
 93  
     public String getName() {
 94  17
         return ANALYZER_NAME;
 95  
     }
 96  
 
 97  
     /**
 98  
      * Returns the phase that the analyzer is intended to run in.
 99  
      *
 100  
      * @return the phase that the analyzer is intended to run in.
 101  
      */
 102  
     @Override
 103  
     public AnalysisPhase getAnalysisPhase() {
 104  6
         return ANALYSIS_PHASE;
 105  
     }
 106  
 
 107  
     /**
 108  
      * Returns the key used in the properties file to reference the analyzer's
 109  
      * enabled property.
 110  
      *
 111  
      * @return the analyzer's enabled property setting key
 112  
      */
 113  
     @Override
 114  
     protected String getAnalyzerEnabledSettingKey() {
 115  8
         return Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED;
 116  
     }
 117  
 
 118  
     @Override
 119  
     protected void analyzeDependency(Dependency dependency, Engine engine)
 120  
             throws AnalysisException {
 121  
 
 122  
         String contents;
 123  
         try {
 124  1
             contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
 125  0
         } catch (IOException e) {
 126  0
             throw new AnalysisException(
 127  
                     "Problem occurred while reading dependency file.", e);
 128  1
         }
 129  1
         final Matcher matcher = SPM_BLOCK_PATTERN.matcher(contents);
 130  1
         if (matcher.find()) {
 131  1
             final String packageDescription = matcher.group(1);
 132  1
             if (packageDescription.isEmpty()) {
 133  0
                 return;
 134  
             }
 135  
 
 136  1
             final EvidenceCollection product = dependency.getProductEvidence();
 137  1
             final EvidenceCollection vendor = dependency.getVendorEvidence();
 138  
 
 139  
             //SPM is currently under development for SWIFT 3. Its current metadata includes package name and dependencies.
 140  
             //Future interesting metadata: version, license, homepage, author, summary, etc.
 141  1
             final String name = addStringEvidence(product, packageDescription, "name", "name", Confidence.HIGHEST);
 142  1
             if (name != null && !name.isEmpty()) {
 143  1
                 vendor.addEvidence(SPM_FILE_NAME, "name_project", name, Confidence.HIGHEST);
 144  
             }
 145  
         }
 146  1
         setPackagePath(dependency);
 147  1
     }
 148  
 
 149  
     /**
 150  
      * Extracts evidence from the package description and adds it to the given
 151  
      * evidence collection.
 152  
      *
 153  
      * @param evidences the evidence collection to update
 154  
      * @param packageDescription the text to extract evidence from
 155  
      * @param field the name of the field being searched for
 156  
      * @param fieldPattern the field pattern within the contents to search for
 157  
      * @param confidence the confidence level of the evidence if found
 158  
      * @return the string that was added as evidence
 159  
      */
 160  
     private String addStringEvidence(EvidenceCollection evidences,
 161  
             String packageDescription, String field, String fieldPattern, Confidence confidence) {
 162  1
         String value = "";
 163  
 
 164  2
         final Matcher matcher = Pattern.compile(
 165  2
                 String.format("%s *:\\s*\"([^\"]*)", fieldPattern), Pattern.DOTALL).matcher(packageDescription);
 166  1
         if (matcher.find()) {
 167  1
             value = matcher.group(1);
 168  
         }
 169  
 
 170  1
         if (value != null) {
 171  1
             value = value.trim();
 172  1
             if (value.length() > 0) {
 173  1
                 evidences.addEvidence(SPM_FILE_NAME, field, value, confidence);
 174  
             }
 175  
         }
 176  
 
 177  1
         return value;
 178  
     }
 179  
 
 180  
     /**
 181  
      * Sets the package path on the given dependency.
 182  
      *
 183  
      * @param dep the dependency to update
 184  
      */
 185  
     private void setPackagePath(Dependency dep) {
 186  1
         final File file = new File(dep.getFilePath());
 187  1
         final String parent = file.getParent();
 188  1
         if (parent != null) {
 189  1
             dep.setPackagePath(parent);
 190  
         }
 191  1
     }
 192  
 }