diff --git a/lib/common/models/wp_item/infos.rb b/lib/common/models/wp_item/infos.rb index df9b92b2..1724b695 100644 --- a/lib/common/models/wp_item/infos.rb +++ b/lib/common/models/wp_item/infos.rb @@ -10,11 +10,6 @@ class WpItem !readme_url.nil? end - # @return [ Boolean ] - def outdated?(installed_version, latest_version) - installed_version < latest_version - end - # @return [ String,nil ] The url to the readme file, nil if not found def readme_url # See https://github.com/wpscanteam/wpscan/pull/737#issuecomment-66375445 diff --git a/lib/common/models/wp_item/output.rb b/lib/common/models/wp_item/output.rb index b6cccd8e..10c51cdd 100644 --- a/lib/common/models/wp_item/output.rb +++ b/lib/common/models/wp_item/output.rb @@ -5,14 +5,16 @@ class WpItem # @return [ Void ] def output(verbose = false) + outdated = VersionCompare.lesser?(version, latest_version) if latest_version + puts puts info("Name: #{self}") #this will also output the version number if detected - puts " | Latest version: #{latest_version} (up to date)" if latest_version && !outdated?(version, latest_version) + puts " | Latest version: #{latest_version} (up to date)" if latest_version && !outdated puts " | Last updated: #{last_updated}" if last_updated puts " | Location: #{url}" puts " | Readme: #{readme_url}" if has_readme? puts " | Changelog: #{changelog_url}" if has_changelog? - puts warning("The version is out of date, the latest version is #{latest_version}") if latest_version && outdated?(version, latest_version) + puts warning("The version is out of date, the latest version is #{latest_version}") if latest_version && outdated puts warning("Directory listing is enabled: #{url}") if has_directory_listing? puts warning("An error_log file has been found: #{error_log_url}") if has_error_log? diff --git a/lib/common/version_compare.rb b/lib/common/version_compare.rb index 3e0ded85..301388ec 100644 --- a/lib/common/version_compare.rb +++ b/lib/common/version_compare.rb @@ -11,8 +11,8 @@ class VersionCompare # @return [ Boolean ] def self.lesser_or_equal?(version1, version2) # Prepend a '0' if the version starts with a '.' - version1 = "0#{version1}" if version1 && version1[0,1] == '.' - version2 = "0#{version2}" if version2 && version2[0,1] == '.' + version1 = prepend_zero(version1) + version2 = prepend_zero(version2) return true if (version1 == version2) # Both versions must be set @@ -27,4 +27,36 @@ class VersionCompare end return false end + + # Compares two version strings. Returns true if version1 < version2 + # and false otherwise + # + # @param [ String ] version1 + # @param [ String ] version2 + # + # @return [ Boolean ] + def self.lesser?(version1, version2) + # Prepend a '0' if the version starts with a '.' + version1 = prepend_zero(version1) + version2 = prepend_zero(version2) + + return false if (version1 == version2) + # Both versions must be set + return false unless (version1 and version2) + return false if (version1.empty? or version2.empty?) + begin + return true if (Gem::Version.new(version1) < Gem::Version.new(version2)) + rescue ArgumentError => e + # Example: ArgumentError: Malformed version number string a + return false if e.message =~ /Malformed version number string/ + raise + end + return false + end + + # @return [ String ] + def self.prepend_zero(version) + return nil if version.nil? + version[0,1] == '.' ? "0#{version}" : version + end end diff --git a/spec/lib/common/version_compare_spec.rb b/spec/lib/common/version_compare_spec.rb index 0a62b74f..80382179 100644 --- a/spec/lib/common/version_compare_spec.rb +++ b/spec/lib/common/version_compare_spec.rb @@ -121,4 +121,122 @@ describe 'VersionCompare' do end end + + describe '::lesser?' do + context 'version checked is newer' do + after { expect(VersionCompare::lesser?(@version1, @version2)).to be_truthy } + + it 'returns true' do + @version1 = '1.0' + @version2 = '2.0' + end + + it 'returns true' do + @version1 = '1.0' + @version2 = '1.1' + end + + it 'returns true' do + @version1 = '1.0a' + @version2 = '1.0b' + end + + it 'returns true' do + @version1 = '1.0' + @version2 = '5000000' + end + + it 'returns true' do + @version1 = '0' + @version2 = '1' + end + + it 'returns true' do + @version1 = '0.4.2b' + @version2 = '2.3.3' + end + + it 'returns true' do + @version1 = '.47' + @version2 = '.50.3' + end + end + + context 'version checked is older' do + after { expect(VersionCompare::lesser?(@version1, @version2)).to be_falsey } + + it 'returns false' do + @version1 = '1' + @version2 = '0' + end + + it 'returns false' do + @version1 = '1.0' + @version2 = '0.5' + end + + it 'returns false' do + @version1 = '500000' + @version2 = '1' + end + + it 'returns false' do + @version1 = '1.6.3.7.3.4' + @version2 = '1.2.4.567.679.8.e' + end + + it 'returns false' do + @version1 = '.47' + @version2 = '.46.3' + end + end + + context 'version checked is the same' do + after { expect(VersionCompare::lesser?(@version1, @version2)).to be_falsey } + + it 'returns true' do + @version1 = '1' + @version2 = '1' + end + + it 'returns true' do + @version1 = 'a' + @version2 = 'a' + end + + end + + context 'version number causes Gem::Version new Exception' do + after { expect(VersionCompare::lesser?(@version1, @version2)).to be_falsey } + + it 'returns false' do + @version1 = 'a' + @version2 = 'b' + end + end + + context 'one version number is not set' do + after { expect(VersionCompare::lesser?(@version1, @version2)).to be_falsey } + + it 'returns false (version2 nil)' do + @version1 = '1' + @version2 = nil + end + + it 'returns false (version1 nil)' do + @version1 = nil + @version2 = '1' + end + + it 'returns false (version2 empty)' do + @version1 = '1' + @version2 = '' + end + + it 'returns false (version1 empty)' do + @version1 = '' + @version2 = '1' + end + end + end end diff --git a/spec/shared_examples/wp_item_infos.rb b/spec/shared_examples/wp_item_infos.rb index 4bf56269..1be9d8b0 100644 --- a/spec/shared_examples/wp_item_infos.rb +++ b/spec/shared_examples/wp_item_infos.rb @@ -53,22 +53,6 @@ shared_examples 'WpItem::Infos' do end end - describe '#outdated?' do - it 'returns true if outdated' do - latest_version = '1.0' - installed_version = '0.1' - - expect(subject.outdated?(installed_version, latest_version)).to be true - end - - it 'returns false if not outdated' do - latest_version = '1.0' - installed_version = '1.0' - - expect(subject.outdated?(installed_version, latest_version)).to be false - end - end - describe '#has_changelog?' do after :each do stub_request(:get, subject.changelog_url).to_return(status: @status)