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 containing version numbers.</p>
28 *
29 * @author Jeremy Long
30 */
31 public final class DependencyVersionUtil {
32
33 /**
34 * Regular expression to extract version numbers from file names.
35 */
36 private static final Pattern RX_VERSION = Pattern.compile("\\d+(\\.\\d{1,6})+(\\.?([_-](release|beta|alpha|\\d+)|[a-zA-Z_-]{1,3}\\d{0,8}))?");
37 /**
38 * Regular expression to extract a single version number without periods. This is a last ditch effort just to check in case we
39 * are missing a version number using the previous regex.
40 */
41 private static final Pattern RX_SINGLE_VERSION = Pattern.compile("\\d+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?");
42
43 /**
44 * Private constructor for utility class.
45 */
46 private DependencyVersionUtil() {
47 }
48
49 /**
50 * <p>
51 * A utility class to extract version numbers from file names (or other strings containing version numbers.</p>
52 * <pre>
53 * Example:
54 * Give the file name: library-name-1.4.1r2-release.jar
55 * This function would return: 1.4.1.r2</pre>
56 *
57 * @param text the text being analyzed
58 * @return a DependencyVersion containing the version
59 */
60 public static DependencyVersion parseVersion(String text) {
61 if (text == null) {
62 return null;
63 }
64 //'-' is a special case used within the CVE entries, just include it as the version.
65 if ("-".equals(text)) {
66 final DependencyVersion dv = new DependencyVersion();
67 final List<String> list = new ArrayList<String>();
68 list.add(text);
69 dv.setVersionParts(list);
70 return dv;
71 }
72 String version = null;
73 Matcher matcher = RX_VERSION.matcher(text);
74 if (matcher.find()) {
75 version = matcher.group();
76 }
77 //throw away the results if there are two things that look like version numbers
78 if (matcher.find()) {
79 return null;
80 }
81 if (version == null) {
82 matcher = RX_SINGLE_VERSION.matcher(text);
83 if (matcher.find()) {
84 version = matcher.group();
85 } else {
86 return null;
87 }
88 //throw away the results if there are two things that look like version numbers
89 if (matcher.find()) {
90 return null;
91 }
92 }
93 if (version != null && version.endsWith("-py2") && version.length() > 4) {
94 version = version.substring(0, version.length() - 4);
95 }
96 return new DependencyVersion(version);
97 }
98 }