2015-01-01 22:08:06 +08:00
require 'hbc/checkable'
require 'hbc/download'
2013-03-14 02:03:12 +08:00
2015-01-01 22:08:06 +08:00
class Hbc :: Audit
include Hbc :: Checkable
2012-11-19 13:12:21 +08:00
2015-12-28 11:27:01 +08:00
attr_reader :cask , :download
2015-12-28 05:29:57 +08:00
2015-12-28 11:27:01 +08:00
def initialize ( cask , download = false )
2012-11-19 13:12:21 +08:00
@cask = cask
2015-12-28 11:27:01 +08:00
@download = download
2012-11-19 13:12:21 +08:00
end
2015-12-28 11:27:01 +08:00
def run!
2015-12-28 05:29:57 +08:00
check_required_stanzas
2015-12-29 06:20:05 +08:00
check_version
2015-12-28 07:45:59 +08:00
check_sha256
check_appcast
2015-12-29 06:20:05 +08:00
check_url
check_download
2015-12-28 11:27:01 +08:00
self
end
def success?
! ( errors? || warnings? )
2012-11-19 13:12:21 +08:00
end
2013-03-14 02:03:12 +08:00
def summary_header
" audit for #{ cask } "
2012-11-19 13:12:21 +08:00
end
2015-12-28 05:29:57 +08:00
private
2013-07-06 18:35:14 +08:00
2015-12-28 05:29:57 +08:00
def check_required_stanzas
2014-12-21 00:34:49 +08:00
odebug " Auditing required stanzas "
2014-12-24 00:08:45 +08:00
% i { version sha256 url homepage } . each do | sym |
2014-12-21 00:34:49 +08:00
add_error " a #{ sym } stanza is required " unless cask . send ( sym )
end
2015-12-28 11:27:01 +08:00
add_error 'a license stanza is required (:unknown is OK)' unless cask . license
2016-01-06 18:24:40 +08:00
add_error 'at least one name stanza is required' if cask . name . empty?
2014-12-21 00:34:49 +08:00
# todo: specific DSL knowledge should not be spread around in various files like this
# todo: nested_container should not still be a pseudo-artifact at this point
installable_artifacts = cask . artifacts . reject { | k , v | [ :uninstall , :zap , :nested_container ] . include? ( k ) }
add_error 'at least one activatable artifact stanza is required' unless installable_artifacts . size > 0
2012-11-19 13:12:21 +08:00
end
2013-04-08 03:28:42 +08:00
2015-12-29 06:20:05 +08:00
def check_version
return unless cask . version
check_no_string_version_latest
end
2015-12-28 05:29:57 +08:00
def check_no_string_version_latest
2014-09-17 19:22:33 +08:00
odebug " Verifying version :latest does not appear as a string ('latest') "
2015-12-29 06:16:34 +08:00
if cask . version . raw_version == 'latest'
2014-09-17 19:22:33 +08:00
add_error " you should use version :latest instead of version 'latest' "
end
end
2015-12-28 07:45:59 +08:00
def check_sha256
return unless cask . sha256
check_sha256_no_check_if_latest
check_sha256_actually_256
check_sha256_invalid
end
2015-12-28 05:29:57 +08:00
def check_sha256_no_check_if_latest
2014-09-17 19:22:33 +08:00
odebug " Verifying sha256 :no_check with version :latest "
2015-12-29 06:16:34 +08:00
if cask . version . latest? && cask . sha256 != :no_check
2014-09-17 19:22:33 +08:00
add_error " you should use sha256 :no_check when version is :latest "
2014-06-13 04:28:11 +08:00
end
2013-12-29 11:27:32 +08:00
end
2015-12-28 07:45:59 +08:00
def check_sha256_actually_256 ( sha256 : cask . sha256 , stanza : 'sha256' )
odebug " Verifying #{ stanza } string is a legal SHA-256 digest "
if sha256 . kind_of? ( String )
unless sha256 . length == 64 && sha256 [ / ^[0-9a-f]+$ /i ]
2015-02-26 05:26:12 +08:00
add_error " sha256 string must be of 64 hexadecimal characters "
end
end
end
2015-12-28 07:45:59 +08:00
def check_sha256_invalid ( sha256 : cask . sha256 , stanza : 'sha256' )
odebug " Verifying #{ stanza } is not a known invalid value "
2015-01-02 23:30:26 +08:00
empty_sha256 = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
2015-12-28 07:45:59 +08:00
if sha256 == empty_sha256
2015-01-02 23:30:26 +08:00
add_error " cannot use the sha256 for an empty string: #{ empty_sha256 } "
end
end
2015-12-28 07:45:59 +08:00
def check_appcast
return unless cask . appcast
odebug 'Auditing appcast'
2016-01-13 07:39:10 +08:00
check_appcast_has_checkpoint
return unless cask . appcast . checkpoint
check_sha256_actually_256 ( sha256 : cask . appcast . checkpoint , stanza : 'appcast :checkpoint' )
check_sha256_invalid ( sha256 : cask . appcast . checkpoint , stanza : 'appcast :checkpoint' )
2015-12-28 07:45:59 +08:00
end
2016-01-13 07:39:10 +08:00
def check_appcast_has_checkpoint
2015-12-28 07:45:59 +08:00
odebug 'Verifying appcast has :sha256 key'
2016-01-13 07:39:10 +08:00
add_error 'a checkpoint sha256 is required for appcast' unless cask . appcast . checkpoint
2015-12-28 07:45:59 +08:00
end
2015-12-29 06:20:05 +08:00
def check_url
return unless cask . url
2016-01-01 02:13:58 +08:00
check_download_url_format
2013-07-06 18:35:14 +08:00
end
2015-12-31 21:07:45 +08:00
def check_download_url_format
2014-01-23 07:29:00 +08:00
odebug " Auditing URL format "
2015-12-28 05:29:57 +08:00
if bad_sourceforge_url?
2016-02-21 01:06:59 +08:00
add_warning " SourceForge URL format incorrect. See https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/url.md # sourceforgeosdn-urls "
2015-12-31 21:07:45 +08:00
elsif bad_osdn_url?
2016-02-21 01:06:59 +08:00
add_warning " OSDN URL format incorrect. See https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/url.md # sourceforgeosdn-urls "
2013-04-20 12:16:57 +08:00
end
end
2013-11-06 12:07:11 +08:00
2015-12-31 22:38:39 +08:00
def bad_url_format? ( regex , valid_formats_array )
return false unless cask . url . to_s =~ regex
valid_formats_array . none? { | format | cask . url . to_s =~ format }
end
2015-12-28 05:29:57 +08:00
def bad_sourceforge_url?
2015-12-31 22:38:39 +08:00
bad_url_format? ( / sourceforge / , [
2014-11-17 23:06:24 +08:00
%r{ \ Ahttps?://sourceforge \ .net/projects/[^/]+/files/latest/download \ Z } ,
%r{ \ Ahttps?://downloads \ .sourceforge \ .net/ } ,
2014-12-03 01:24:36 +08:00
%r{ \ Ahttps?://[^/]+ \ .sourceforge \ .jp/ } ,
2014-11-17 23:06:24 +08:00
# special cases: cannot find canonical format URL
%r{ \ Ahttps?://brushviewer \ .sourceforge \ .net/brushviewql \ .zip \ Z } ,
%r{ \ Ahttps?://doublecommand \ .sourceforge \ .net/files/ } ,
2014-11-17 23:06:01 +08:00
%r{ \ Ahttps?://excalibur \ .sourceforge \ .net/get \ .php \ ?id= } ,
2015-12-31 22:38:39 +08:00
] )
2013-11-06 12:07:11 +08:00
end
2015-12-31 21:07:45 +08:00
def bad_osdn_url?
2015-12-31 22:38:39 +08:00
bad_url_format? ( / osd / , [
2015-12-31 21:07:45 +08:00
%r{ \ Ahttps?://[^/]+ \ .osdn \ .jp/ } ,
2015-12-31 22:38:39 +08:00
] )
2015-12-31 21:07:45 +08:00
end
2015-12-29 06:20:05 +08:00
def check_download
return unless download
odebug " Auditing download "
downloaded_path = download . perform
Hbc :: Verify . all ( cask , downloaded_path )
rescue = > e
add_error " download not possible: #{ e . message } "
end
2012-11-19 13:12:21 +08:00
end