View Javadoc
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) 2013 Jeremy Long. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck.utils;
19  
20  import java.util.ArrayList;
21  import java.util.List;
22  import java.util.regex.Matcher;
23  import java.util.regex.Pattern;
24  
25  /**
26   * <p>
27   * A utility class to extract version numbers from file names (or other strings
28   * containing version numbers.</p>
29   *
30   * @author Jeremy Long
31   */
32  public final class DependencyVersionUtil {
33  
34      /**
35       * Regular expression to extract version numbers from file names.
36       */
37      private static final Pattern RX_VERSION = Pattern.compile("\\d+(\\.\\d{1,6})+(\\.?([_-](release|beta|alpha|\\d+)|[a-zA-Z_-]{1,3}\\d{0,8}))?");
38      /**
39       * Regular expression to extract a single version number without periods.
40       * This is a last ditch effort just to check in case we are missing a
41       * version number using the previous regex.
42       */
43      private static final Pattern RX_SINGLE_VERSION = Pattern.compile("\\d+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?");
44  
45      /**
46       * Regular expression to extract the part before the version numbers if
47       * there are any based on RX_VERSION. In most cases, this part represents a
48       * more accurate name.
49       */
50      private static final Pattern RX_PRE_VERSION = Pattern.compile("^(.+)[_-](\\d+\\.\\d{1,6})+");
51  
52      /**
53       * Private constructor for utility class.
54       */
55      private DependencyVersionUtil() {
56      }
57  
58      /**
59       * <p>
60       * A utility class to extract version numbers from file names (or other
61       * strings containing version numbers.</p>
62       * <pre>
63       * Example:
64       * Give the file name: library-name-1.4.1r2-release.jar
65       * This function would return: 1.4.1.r2</pre>
66       *
67       * @param text the text being analyzed
68       * @return a DependencyVersion containing the version
69       */
70      public static DependencyVersion parseVersion(String text) {
71          if (text == null) {
72              return null;
73          }
74          //'-' is a special case used within the CVE entries, just include it as the version.
75          if ("-".equals(text)) {
76              final DependencyVersion dv = new DependencyVersion();
77              final List<String> list = new ArrayList<String>();
78              list.add(text);
79              dv.setVersionParts(list);
80              return dv;
81          }
82          String version = null;
83          Matcher matcher = RX_VERSION.matcher(text);
84          if (matcher.find()) {
85              version = matcher.group();
86          }
87          //throw away the results if there are two things that look like version numbers
88          if (matcher.find()) {
89              return null;
90          }
91          if (version == null) {
92              matcher = RX_SINGLE_VERSION.matcher(text);
93              if (matcher.find()) {
94                  version = matcher.group();
95              } else {
96                  return null;
97              }
98              //throw away the results if there are two things that look like version numbers
99              if (matcher.find()) {
100                 return null;
101             }
102         }
103         if (version != null && version.endsWith("-py2") && version.length() > 4) {
104             version = version.substring(0, version.length() - 4);
105         }
106         return new DependencyVersion(version);
107     }
108 
109     /**
110      * <p>
111      * A utility class to extract the part before version numbers from file
112      * names (or other strings containing version numbers. In most cases, this
113      * part represents a more accurate name than the full file name.</p>
114      * <pre>
115      * Example:
116      * Give the file name: library-name-1.4.1r2-release.jar
117      * This function would return: library-name</pre>
118      *
119      * @param text the text being analyzed
120      * @return the part before the version numbers if any, otherwise return the
121      * text itself.
122      */
123     public static String parsePreVersion(String text) {
124         if (parseVersion(text) == null) {
125             return text;
126         }
127 
128         final Matcher matcher = RX_PRE_VERSION.matcher(text);
129         if (matcher.find()) {
130             return matcher.group(1);
131         }
132         return text;
133     }
134 }