lib/cpe.rb in cpe-0.3.1 vs lib/cpe.rb in cpe-0.4.0
- old
+ new
@@ -1,112 +1,134 @@
-# = cpe.rb
+# Public: CPE is a lightweight library built to simplify working with the
+# Common Platform Enumeration spec managed by Mitre. See http://cpe.mitre.org/
+# for further details.
#
-# Copyright (c) Chris Wuest <chris@chriswuest.com>
-# Expectr is freely distributable under the terms of an MIT-style license.
-# See LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
+# Examples
#
-
-# Fixes for Ruby pre-1.9
-if RUBY_VERSION =~ /^1.[^9]/
- #
- # Ruby does not implement KeyError before 1.9
- #
- class KeyError < IndexError
- def initialize message = nil
- super message || "Key not found"
- end
- end
-end
-
-# == Description
-# Cpe is a small library built to simplify working with the Common Platform
-# Enumeration spec managed by Mitre. See http://cpe.mitre.org/ for further
-# details.
+# # Parse a CPE string
+# cpe = Cpe.parse("cpe:/o:microsoft:windows_xp:::pro")
+# cpe.vendor
+# # => "microsoft"
+# cpe.language
+# # => ""
#
-# == Examples
-# === Parsing CPE
-#
-# cpe = Cpe.parse "cpe:/o:microsoft:windows_xp:::pro"
-# cpe.vendor # => "microsoft"
-# cpe.generate # => "cpe:/o:microsoft:windows_xp:::pro:"
-#
-# === Generating CPE string
-# cpe = Cpe.new :part => Cpe::OS
+# # Generate a CPE String
+# cpe = Cpe.new(part: Cpe::OS)
# cpe.vendor = "microsoft"
# cpe.product = "windows_xp"
-# cpe.generate # => "cpe:/o:microsoft:windows_xp::::"
-class Cpe
- # Part type. Can be /o (Cpe::OS), /a (Cpe::Application), /h (Cpe::Hardware)
- attr_accessor :part
- # Vendor
- attr_accessor :vendor
- # Product
- attr_accessor :product
- # Version
- attr_accessor :version
- # Update/patch level
- attr_accessor :update
- # Edition
- attr_accessor :edition
- # Language
- attr_accessor :language
+# cpe.language = "en_US"
+# cpe.generate # => "cpe:/o:microsoft:windows_xp::::en_US"
+class CPE
+ # Public: Gets/sets the part type String. Can be '/o' (Cpe::OS),
+ # '/a' (Cpe::Application), or '/h' (Cpe::Hardware)
+ attr_accessor :part
+ # Public: Gets/sets the vendor String
+ attr_accessor :vendor
+ # Public: Gets/sets the product String
+ attr_accessor :product
+ # Public: Gets/sets the version String
+ attr_accessor :version
+ # Public: Gets/sets the Update or patch level String
+ attr_accessor :update
+ # Public: Gets/sets the part edition String
+ attr_accessor :edition
+ # Public: Gets/sets the language String
+ attr_accessor :language
- #
- # Create a new Cpe object, initializing all relevent variables to known
- # values, or else an empty string. Part must be one of /o, /a, /h or else
- # be nil.
- #
- def initialize args={}
- raise ArgumentError unless args.kind_of? Hash
- raise ArgumentError unless /\/[oah]/.match args[:part].to_s or args[:part].nil?
- @part = args[:part] || ""
- @vendor = args[:vendor] || ""
- @product = args[:product] || ""
- @version = args[:version] || ""
- @update = args[:update] || ""
- @edition = args[:edition] || ""
- @language = args[:language] || ""
- end
+ # Public: String to give easier readability for "/o"
+ OS = "/o"
+ # Public: String to give easier readability for "/a"
+ Application = "/a"
+ # Public: String to give easier readability for "/h"
+ Hardware = "/h"
- #
- # Check that at least Part and one other piece of information have been
- # collected, and return generated CPE string.
- #
- def generate
- raise KeyError unless /\/[oah]/.match @part
- 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?
- return ["cpe", @part, @vendor, @product, @version, @update, @edition, @language].join(":").downcase
- end
+ # Public: Initialize a new CPE Object, initializing all relevent variables to
+ # passed values, or else an empty string. Part must be one of CPE::OS,
+ # CPE::Application, CPE::Hardware, or else be nil.
+ #
+ # args - Hash containing values to set the CPE (default: {}):
+ # :part - String describing the part. Must be one of CPE::OS,
+ # CPE::Application or CPE::Hardware, or nil.
+ # :vendor - String containing the name of the vendor of the part.
+ # :product - String containing the name of the part described by the
+ # CPE.
+ # :version - String containing the version of the part.
+ # :update - String describing the update/patch level of the part.
+ # :edition - String containing any relevant edition text for the
+ # part.
+ # :language - String describing the language the part targets.
+ #
+ # Raises ArgumentError if anything other than a Hash is passed.
+ # Raises ArgumentError if anything but '/o', '/a', or '/h' are set as the
+ # part.
+ def initialize(args={})
+ raise ArgumentError unless args.kind_of?(Hash)
+ unless /\/[oah]/.match(args[:part].to_s) || args[:part].nil?
+ raise ArgumentError
+ end
- #
- # Test for equality of generated CPE strings
- def == cpe
- raise ArgumentError unless cpe.kind_of? Cpe
- self.generate == cpe.generate
- end
+ @part = args[:part] || ""
+ @vendor = args[:vendor] || ""
+ @product = args[:product] || ""
+ @version = args[:version] || ""
+ @update = args[:update] || ""
+ @edition = args[:edition] || ""
+ @language = args[:language] || ""
+ end
- #
- # Parse pre-existing CPE string and return new Cpe object
- #
- # String parsing is permissive regarding the number of trailing colons and whitespace
- # provided, filling in empty strings if needed.
- #
- def Cpe.parse cpe
- raise ArgumentError unless cpe.kind_of? String or cpe.kind_of? File
- cpe = cpe.read if cpe.kind_of? File
- cpe = cpe.downcase.chomp
- raise ArgumentError, "CPE malformed" unless /^cpe:\/[hoa]:/.match cpe and !/[\s\n]/.match cpe
+ # Public: Check that at least Part and one other piece of information have
+ # been set, and return generated CPE string.
+ #
+ # Returns a valid CPE string.
+ # Raises KeyError if the part specified is invalid.
+ # Raises KeyError if at least one piece of information is not set aside from
+ # the part type.
+ def generate
+ raise KeyError unless /\/[oah]/.match(@part.downcase)
+ if @vendor.to_s.empty? && @product.to_s.empty? && @version.to_s.empty? &&
+ @update.to_s.empty? && @edition.to_s.empty? && @language.to_s.empty?
+ raise KeyError
+ end
- data = Hash.new
- discard, data[:part], data[:vendor], data[:product], data[:version],
- data[:update], data[:edition], data[:language] = cpe.split(/:/, 8)
+ ["cpe", @part, @vendor, @product, @version, @update, @edition,
+ @language].join(":").downcase
+ end
- return self.new data
- end
-end
+ # Public: Test for equality of two CPE strings.
+ #
+ # cpe - CPE object to compare against, or String containing CPE data
+ #
+ # Returns a boolean value depending on whether the CPEs are equivalent.
+ # Raises ArgumentError if data passed isn't either a String or CPE Object.
+ def ==(cpe)
+ cpe = cpe.generate if cpe.kind_of?(CPE)
+ raise ArgumentError unless cpe.kind_of?(String)
-# Variable for readability for "/o"
-Cpe::OS = "/o"
-# Variable for readability for "/a"
-Cpe::Application = "/a"
-# Variable for readability for "/h"
-Cpe::Hardware = "/h"
+ self.generate == cpe
+ end
+
+ # Public: Parse a pre-existing CPE from a String or contained in a File.
+ # Attempt to be permissive regarding the number of trailing colons and
+ # whitespace.
+ #
+ # cpe - A String or File object containing the CPE string to parse.
+ #
+ # Returns a new CPE object.
+ # Raises ArgumentError if given anything other than a File or String object.
+ # Raises ArgumentError if the string doesn't begin with "cpe:" and a valid
+ # part type indicator.
+ def CPE.parse(cpe)
+ raise ArgumentError unless cpe.kind_of? String or cpe.kind_of? File
+
+ cpe = cpe.read if cpe.kind_of? File
+ cpe = cpe.to_s.downcase.strip
+ raise ArgumentError, "CPE malformed" unless /^cpe:\/[hoa]:/.match cpe and !/[\s\n]/.match cpe
+
+ data = Hash.new
+ discard, data[:part], data[:vendor], data[:product], data[:version],
+ data[:update], data[:edition], data[:language] = cpe.split(/:/, 8)
+
+ return self.new data
+ end
+
+ alias :to_s :generate
+end