cpe 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/lib/cpe/version.rb +1 -1
  2. data/lib/cpe.rb +122 -100
  3. data/test/test_cpe.rb +36 -28
  4. metadata +2 -2
data/lib/cpe/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class CPE
2
- VERSION = '0.3.1'
2
+ VERSION = '0.4.0'
3
3
  end
data/lib/cpe.rb CHANGED
@@ -1,112 +1,134 @@
1
- # = cpe.rb
1
+ # Public: CPE is a lightweight library built to simplify working with the
2
+ # Common Platform Enumeration spec managed by Mitre. See http://cpe.mitre.org/
3
+ # for further details.
2
4
  #
3
- # Copyright (c) Chris Wuest <chris@chriswuest.com>
4
- # Expectr is freely distributable under the terms of an MIT-style license.
5
- # See LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
5
+ # Examples
6
6
  #
7
-
8
- # Fixes for Ruby pre-1.9
9
- if RUBY_VERSION =~ /^1.[^9]/
10
- #
11
- # Ruby does not implement KeyError before 1.9
12
- #
13
- class KeyError < IndexError
14
- def initialize message = nil
15
- super message || "Key not found"
16
- end
17
- end
18
- end
19
-
20
- # == Description
21
- # Cpe is a small library built to simplify working with the Common Platform
22
- # Enumeration spec managed by Mitre. See http://cpe.mitre.org/ for further
23
- # details.
7
+ # # Parse a CPE string
8
+ # cpe = Cpe.parse("cpe:/o:microsoft:windows_xp:::pro")
9
+ # cpe.vendor
10
+ # # => "microsoft"
11
+ # cpe.language
12
+ # # => ""
24
13
  #
25
- # == Examples
26
- # === Parsing CPE
27
- #
28
- # cpe = Cpe.parse "cpe:/o:microsoft:windows_xp:::pro"
29
- # cpe.vendor # => "microsoft"
30
- # cpe.generate # => "cpe:/o:microsoft:windows_xp:::pro:"
31
- #
32
- # === Generating CPE string
33
- # cpe = Cpe.new :part => Cpe::OS
14
+ # # Generate a CPE String
15
+ # cpe = Cpe.new(part: Cpe::OS)
34
16
  # cpe.vendor = "microsoft"
35
17
  # cpe.product = "windows_xp"
36
- # cpe.generate # => "cpe:/o:microsoft:windows_xp::::"
37
- class Cpe
38
- # Part type. Can be /o (Cpe::OS), /a (Cpe::Application), /h (Cpe::Hardware)
39
- attr_accessor :part
40
- # Vendor
41
- attr_accessor :vendor
42
- # Product
43
- attr_accessor :product
44
- # Version
45
- attr_accessor :version
46
- # Update/patch level
47
- attr_accessor :update
48
- # Edition
49
- attr_accessor :edition
50
- # Language
51
- attr_accessor :language
18
+ # cpe.language = "en_US"
19
+ # cpe.generate # => "cpe:/o:microsoft:windows_xp::::en_US"
20
+ class CPE
21
+ # Public: Gets/sets the part type String. Can be '/o' (Cpe::OS),
22
+ # '/a' (Cpe::Application), or '/h' (Cpe::Hardware)
23
+ attr_accessor :part
24
+ # Public: Gets/sets the vendor String
25
+ attr_accessor :vendor
26
+ # Public: Gets/sets the product String
27
+ attr_accessor :product
28
+ # Public: Gets/sets the version String
29
+ attr_accessor :version
30
+ # Public: Gets/sets the Update or patch level String
31
+ attr_accessor :update
32
+ # Public: Gets/sets the part edition String
33
+ attr_accessor :edition
34
+ # Public: Gets/sets the language String
35
+ attr_accessor :language
52
36
 
53
- #
54
- # Create a new Cpe object, initializing all relevent variables to known
55
- # values, or else an empty string. Part must be one of /o, /a, /h or else
56
- # be nil.
57
- #
58
- def initialize args={}
59
- raise ArgumentError unless args.kind_of? Hash
60
- raise ArgumentError unless /\/[oah]/.match args[:part].to_s or args[:part].nil?
61
- @part = args[:part] || ""
62
- @vendor = args[:vendor] || ""
63
- @product = args[:product] || ""
64
- @version = args[:version] || ""
65
- @update = args[:update] || ""
66
- @edition = args[:edition] || ""
67
- @language = args[:language] || ""
68
- end
37
+ # Public: String to give easier readability for "/o"
38
+ OS = "/o"
39
+ # Public: String to give easier readability for "/a"
40
+ Application = "/a"
41
+ # Public: String to give easier readability for "/h"
42
+ Hardware = "/h"
69
43
 
70
- #
71
- # Check that at least Part and one other piece of information have been
72
- # collected, and return generated CPE string.
73
- #
74
- def generate
75
- raise KeyError unless /\/[oah]/.match @part
76
- raise KeyError if @vendor.to_s.empty? and @product.to_s.empty? and @version.to_s.empty? and @update.to_s.empty? and @edition.to_s.empty? and @language.to_s.empty?
77
- return ["cpe", @part, @vendor, @product, @version, @update, @edition, @language].join(":").downcase
78
- end
44
+ # Public: Initialize a new CPE Object, initializing all relevent variables to
45
+ # passed values, or else an empty string. Part must be one of CPE::OS,
46
+ # CPE::Application, CPE::Hardware, or else be nil.
47
+ #
48
+ # args - Hash containing values to set the CPE (default: {}):
49
+ # :part - String describing the part. Must be one of CPE::OS,
50
+ # CPE::Application or CPE::Hardware, or nil.
51
+ # :vendor - String containing the name of the vendor of the part.
52
+ # :product - String containing the name of the part described by the
53
+ # CPE.
54
+ # :version - String containing the version of the part.
55
+ # :update - String describing the update/patch level of the part.
56
+ # :edition - String containing any relevant edition text for the
57
+ # part.
58
+ # :language - String describing the language the part targets.
59
+ #
60
+ # Raises ArgumentError if anything other than a Hash is passed.
61
+ # Raises ArgumentError if anything but '/o', '/a', or '/h' are set as the
62
+ # part.
63
+ def initialize(args={})
64
+ raise ArgumentError unless args.kind_of?(Hash)
65
+ unless /\/[oah]/.match(args[:part].to_s) || args[:part].nil?
66
+ raise ArgumentError
67
+ end
79
68
 
80
- #
81
- # Test for equality of generated CPE strings
82
- def == cpe
83
- raise ArgumentError unless cpe.kind_of? Cpe
84
- self.generate == cpe.generate
85
- end
69
+ @part = args[:part] || ""
70
+ @vendor = args[:vendor] || ""
71
+ @product = args[:product] || ""
72
+ @version = args[:version] || ""
73
+ @update = args[:update] || ""
74
+ @edition = args[:edition] || ""
75
+ @language = args[:language] || ""
76
+ end
86
77
 
87
- #
88
- # Parse pre-existing CPE string and return new Cpe object
89
- #
90
- # String parsing is permissive regarding the number of trailing colons and whitespace
91
- # provided, filling in empty strings if needed.
92
- #
93
- def Cpe.parse cpe
94
- raise ArgumentError unless cpe.kind_of? String or cpe.kind_of? File
95
- cpe = cpe.read if cpe.kind_of? File
96
- cpe = cpe.downcase.chomp
97
- raise ArgumentError, "CPE malformed" unless /^cpe:\/[hoa]:/.match cpe and !/[\s\n]/.match cpe
78
+ # Public: Check that at least Part and one other piece of information have
79
+ # been set, and return generated CPE string.
80
+ #
81
+ # Returns a valid CPE string.
82
+ # Raises KeyError if the part specified is invalid.
83
+ # Raises KeyError if at least one piece of information is not set aside from
84
+ # the part type.
85
+ def generate
86
+ raise KeyError unless /\/[oah]/.match(@part.downcase)
87
+ if @vendor.to_s.empty? && @product.to_s.empty? && @version.to_s.empty? &&
88
+ @update.to_s.empty? && @edition.to_s.empty? && @language.to_s.empty?
89
+ raise KeyError
90
+ end
98
91
 
99
- data = Hash.new
100
- discard, data[:part], data[:vendor], data[:product], data[:version],
101
- data[:update], data[:edition], data[:language] = cpe.split(/:/, 8)
92
+ ["cpe", @part, @vendor, @product, @version, @update, @edition,
93
+ @language].join(":").downcase
94
+ end
102
95
 
103
- return self.new data
104
- end
105
- end
96
+ # Public: Test for equality of two CPE strings.
97
+ #
98
+ # cpe - CPE object to compare against, or String containing CPE data
99
+ #
100
+ # Returns a boolean value depending on whether the CPEs are equivalent.
101
+ # Raises ArgumentError if data passed isn't either a String or CPE Object.
102
+ def ==(cpe)
103
+ cpe = cpe.generate if cpe.kind_of?(CPE)
104
+ raise ArgumentError unless cpe.kind_of?(String)
106
105
 
107
- # Variable for readability for "/o"
108
- Cpe::OS = "/o"
109
- # Variable for readability for "/a"
110
- Cpe::Application = "/a"
111
- # Variable for readability for "/h"
112
- Cpe::Hardware = "/h"
106
+ self.generate == cpe
107
+ end
108
+
109
+ # Public: Parse a pre-existing CPE from a String or contained in a File.
110
+ # Attempt to be permissive regarding the number of trailing colons and
111
+ # whitespace.
112
+ #
113
+ # cpe - A String or File object containing the CPE string to parse.
114
+ #
115
+ # Returns a new CPE object.
116
+ # Raises ArgumentError if given anything other than a File or String object.
117
+ # Raises ArgumentError if the string doesn't begin with "cpe:" and a valid
118
+ # part type indicator.
119
+ def CPE.parse(cpe)
120
+ raise ArgumentError unless cpe.kind_of? String or cpe.kind_of? File
121
+
122
+ cpe = cpe.read if cpe.kind_of? File
123
+ cpe = cpe.to_s.downcase.strip
124
+ raise ArgumentError, "CPE malformed" unless /^cpe:\/[hoa]:/.match cpe and !/[\s\n]/.match cpe
125
+
126
+ data = Hash.new
127
+ discard, data[:part], data[:vendor], data[:product], data[:version],
128
+ data[:update], data[:edition], data[:language] = cpe.split(/:/, 8)
129
+
130
+ return self.new data
131
+ end
132
+
133
+ alias :to_s :generate
134
+ end
data/test/test_cpe.rb CHANGED
@@ -1,55 +1,63 @@
1
1
  require 'helper'
2
2
 
3
- # CPE examples borrowed from CPE Spec document ver. 2.2
4
- class TestCpe < Test::Unit::TestCase
3
+ # CPE examples borrowed from CPE Spec document ver. 2.2:
4
+ # http://cpe.mitre.org/specification/
5
+ class TestCPE < Test::Unit::TestCase
5
6
  def setup
6
7
  @valid = "cpe:/o:microsoft:windows_xp:::pro"
7
8
  @invalid = ["cpe::", "cpe://redhat:enterprise_linux:3::as", "cpe:/o:redhat:Enterprise Linux:3::", ":/o:redhat:enterprise_linux:3", 4]
8
9
  end
9
10
 
10
11
  def test_parse_valid
11
- cpe = Cpe.parse(@valid)
12
- assert_equal "/o", cpe.part
13
- assert_equal "microsoft", cpe.vendor
14
- assert_equal "windows_xp", cpe.product
15
- assert_equal "", cpe.version
16
- assert_equal "", cpe.update
17
- assert_equal "pro", cpe.edition
18
- assert_equal "", cpe.language
12
+ cpe = CPE.parse(@valid)
13
+ assert_equal("/o", cpe.part)
14
+ assert_equal("microsoft", cpe.vendor)
15
+ assert_equal("windows_xp", cpe.product)
16
+ assert_equal("", cpe.version)
17
+ assert_equal("", cpe.update)
18
+ assert_equal("pro", cpe.edition)
19
+ assert_equal("", cpe.language)
19
20
  end
20
21
 
21
22
  def test_parse_invalid
22
23
  @invalid.each do |cpe|
23
- assert_raises(ArgumentError) { Cpe.parse(cpe) }
24
+ assert_raises(ArgumentError) { CPE.parse(cpe) }
24
25
  end
26
+
27
+ assert_raises(ArgumentError) { CPE.parse(1) }
25
28
  end
26
29
 
27
30
  def test_generation
28
- cpe = Cpe.new :part => Cpe::OS, :vendor => "microsoft", :product => "windows_xp", :edition => "pro"
29
- assert_equal cpe.generate, "cpe:/o:microsoft:windows_xp:::pro:"
31
+ cpe = CPE.new(part: CPE::OS, vendor: "microsoft",
32
+ product: "windows_xp", edition: "pro")
33
+ assert_equal("cpe:/o:microsoft:windows_xp:::pro:", cpe.generate)
30
34
 
31
- cpe = Cpe.new :part => Cpe::Application, :vendor => "ACME", :product => "Product", :version => "1.0", :update => "update2", :edition => "-", :language => "en-us"
32
- assert_equal cpe.generate, "cpe:/a:acme:product:1.0:update2:-:en-us"
35
+ cpe = CPE.new(part: CPE::Application, vendor: "ACME", product: "Product",
36
+ version: "1.0", update: "update2", edition: "-",
37
+ language: "en-us")
38
+ assert_equal("cpe:/a:acme:product:1.0:update2:-:en-us", cpe.generate)
33
39
 
34
- cpe = Cpe.new :part => Cpe::Hardware, :vendor => "cisco", :product => "router", :version => 3825
35
- assert_equal cpe.generate, "cpe:/h:cisco:router:3825:::"
40
+ cpe = CPE.new(part: CPE::Hardware, vendor: "cisco", product: "router",
41
+ version: 3825)
42
+ assert_equal("cpe:/h:cisco:router:3825:::", cpe.generate)
36
43
 
37
- assert_nothing_raised { Cpe.parse File.open('test/data/cpe-test-valid') }
38
- assert_raises(ArgumentError) { Cpe.parse File.open('test/data/cpe-test-invalid') }
44
+ assert_nothing_raised { CPE.parse(File.open('test/data/cpe-test-valid')) }
45
+ assert_raises(ArgumentError) { CPE.parse(File.open('test/data/cpe-test-invalid')) }
39
46
 
40
- assert_raises(ArgumentError) { Cpe.new :part => 2 }
41
- assert_nothing_raised { Cpe.new }
47
+ assert_raises(ArgumentError) { CPE.new(:part => 2) }
48
+ assert_nothing_raised { CPE.new }
42
49
 
43
- assert_raises(KeyError) { Cpe.new.generate }
44
- assert_raises(KeyError) { Cpe.new(:part => Cpe::OS).generate }
45
- assert_raises(KeyError) { Cpe.new(:vendor => "redhat").generate }
46
- assert_nothing_raised { Cpe.new(:vendor => "redhat", :part => Cpe::OS).generate }
50
+ assert_raises(KeyError) { CPE.new.generate }
51
+ assert_raises(KeyError) { CPE.new(part: CPE::OS).generate }
52
+ assert_raises(KeyError) { CPE.new(vendor: "redhat").generate }
53
+ assert_nothing_raised { CPE.new(vendor: "redhat", part: CPE::OS).generate }
47
54
  end
48
55
 
49
56
  def test_equality
50
- cpe_a = Cpe.new :part => Cpe::OS, :vendor => "redhat", :product => "enterprise_linux", :version => 3
51
- cpe_b = Cpe.parse "cpe:/o:redhat:enterprise_linux:3"
52
- cpe_c = Cpe.parse File.open('test/data/cpe-test-valid')
57
+ cpe_a = CPE.new(part: CPE::OS, vendor: "redhat",
58
+ product: "enterprise_linux", version: 3)
59
+ cpe_b = CPE.parse("cpe:/o:redhat:enterprise_linux:3")
60
+ cpe_c = CPE.parse(File.open('test/data/cpe-test-valid'))
53
61
 
54
62
  assert_equal cpe_a, cpe_b
55
63
  assert_equal cpe_a, cpe_c
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cpe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-08 00:00:00.000000000 Z
12
+ date: 2012-10-31 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Library for parsing and generating Common Platform Enumeration strings
15
15
  (see http://cpe.mitre.org)