mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-11-05 14:57:30 +01:00
Add info -d to show module documentation in .md
This commit is contained in:
parent
95484c81fd
commit
b0cfb4aacf
2
Gemfile
2
Gemfile
@ -18,6 +18,8 @@ group :development do
|
|||||||
gem 'yard'
|
gem 'yard'
|
||||||
# for development and testing purposes
|
# for development and testing purposes
|
||||||
gem 'pry'
|
gem 'pry'
|
||||||
|
# module documentation
|
||||||
|
gem 'octokit', '~> 4.0'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
|
20
Gemfile.lock
20
Gemfile.lock
@ -57,9 +57,10 @@ GEM
|
|||||||
multi_json (~> 1.3)
|
multi_json (~> 1.3)
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
tzinfo (~> 0.3.37)
|
tzinfo (~> 0.3.37)
|
||||||
|
addressable (2.3.8)
|
||||||
arel (4.0.2)
|
arel (4.0.2)
|
||||||
arel-helpers (2.1.1)
|
arel-helpers (2.2.0)
|
||||||
activerecord (= 4.0.13)
|
activerecord (>= 3.1.0, < 5)
|
||||||
aruba (0.6.2)
|
aruba (0.6.2)
|
||||||
childprocess (>= 0.3.6)
|
childprocess (>= 0.3.6)
|
||||||
cucumber (>= 1.1.1)
|
cucumber (>= 1.1.1)
|
||||||
@ -95,6 +96,8 @@ GEM
|
|||||||
factory_girl_rails (4.5.0)
|
factory_girl_rails (4.5.0)
|
||||||
factory_girl (~> 4.5.0)
|
factory_girl (~> 4.5.0)
|
||||||
railties (>= 3.0.0)
|
railties (>= 3.0.0)
|
||||||
|
faraday (0.9.2)
|
||||||
|
multipart-post (>= 1.2, < 3)
|
||||||
ffi (1.9.8)
|
ffi (1.9.8)
|
||||||
filesize (0.1.1)
|
filesize (0.1.1)
|
||||||
fivemat (1.3.2)
|
fivemat (1.3.2)
|
||||||
@ -139,17 +142,20 @@ GEM
|
|||||||
mime-types (2.6.1)
|
mime-types (2.6.1)
|
||||||
mini_portile2 (2.0.0)
|
mini_portile2 (2.0.0)
|
||||||
minitest (4.7.5)
|
minitest (4.7.5)
|
||||||
msgpack (0.7.1)
|
msgpack (0.7.4)
|
||||||
multi_json (1.11.2)
|
multi_json (1.11.2)
|
||||||
multi_test (0.1.2)
|
multi_test (0.1.2)
|
||||||
|
multipart-post (2.0.0)
|
||||||
network_interface (0.0.1)
|
network_interface (0.0.1)
|
||||||
nokogiri (1.6.7.2)
|
nokogiri (1.6.7.2)
|
||||||
mini_portile2 (~> 2.0.0.rc2)
|
mini_portile2 (~> 2.0.0.rc2)
|
||||||
|
octokit (4.2.0)
|
||||||
|
sawyer (~> 0.6.0, >= 0.5.3)
|
||||||
openssl-ccm (1.2.1)
|
openssl-ccm (1.2.1)
|
||||||
packetfu (1.1.11)
|
packetfu (1.1.11)
|
||||||
network_interface (~> 0.0)
|
network_interface (~> 0.0)
|
||||||
pcaprub (~> 0.12)
|
pcaprub (~> 0.12)
|
||||||
pcaprub (0.12.0)
|
pcaprub (0.12.1)
|
||||||
pg (0.18.4)
|
pg (0.18.4)
|
||||||
pg_array_parser (0.0.9)
|
pg_array_parser (0.0.9)
|
||||||
postgres_ext (2.4.1)
|
postgres_ext (2.4.1)
|
||||||
@ -200,8 +206,11 @@ GEM
|
|||||||
rspec-mocks (~> 3.3.0)
|
rspec-mocks (~> 3.3.0)
|
||||||
rspec-support (~> 3.3.0)
|
rspec-support (~> 3.3.0)
|
||||||
rspec-support (3.3.0)
|
rspec-support (3.3.0)
|
||||||
rubyntlm (0.5.2)
|
rubyntlm (0.6.0)
|
||||||
rubyzip (1.1.7)
|
rubyzip (1.1.7)
|
||||||
|
sawyer (0.6.0)
|
||||||
|
addressable (~> 2.3.5)
|
||||||
|
faraday (~> 0.8, < 0.10)
|
||||||
shoulda-matchers (2.8.0)
|
shoulda-matchers (2.8.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
simplecov (0.9.2)
|
simplecov (0.9.2)
|
||||||
@ -238,6 +247,7 @@ DEPENDENCIES
|
|||||||
factory_girl_rails (~> 4.5.0)
|
factory_girl_rails (~> 4.5.0)
|
||||||
fivemat (~> 1.3.1)
|
fivemat (~> 1.3.1)
|
||||||
metasploit-framework!
|
metasploit-framework!
|
||||||
|
octokit (~> 4.0)
|
||||||
pry
|
pry
|
||||||
rake (>= 10.0.0)
|
rake (>= 10.0.0)
|
||||||
redcarpet
|
redcarpet
|
||||||
|
233
data/markdown.css
Normal file
233
data/markdown.css
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
p,
|
||||||
|
blockquote {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", Arial, sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 18px;
|
||||||
|
color: #737373;
|
||||||
|
margin: 10px 13px 10px 13px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #0069d6;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #0050a3;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
a img {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin-bottom: 9px;
|
||||||
|
}
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
color: #404040;
|
||||||
|
line-height: 36px;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
margin-bottom: 18px;
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
h4 {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
h5 {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
h6 {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
hr {
|
||||||
|
margin: 0 0 19px;
|
||||||
|
border: 0;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
padding: 13px 13px 21px 15px;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
font-family:georgia,serif;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
blockquote:before {
|
||||||
|
content:"\201C";
|
||||||
|
font-size:40px;
|
||||||
|
margin-left:-10px;
|
||||||
|
font-family:georgia,serif;
|
||||||
|
color:#eee;
|
||||||
|
}
|
||||||
|
blockquote p {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 18px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
code, pre {
|
||||||
|
font-family: Monaco, Andale Mono, Courier New, monospace;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
background-color: #fee9cc;
|
||||||
|
color: rgba(0, 0, 0, 0.75);
|
||||||
|
padding: 1px 3px;
|
||||||
|
font-size: 12px;
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
-moz-border-radius: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
display: block;
|
||||||
|
padding: 14px;
|
||||||
|
margin: 0 0 18px;
|
||||||
|
line-height: 16px;
|
||||||
|
font-size: 11px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
pre code {
|
||||||
|
background-color: #fff;
|
||||||
|
color:#737373;
|
||||||
|
font-size: 11px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
body {
|
||||||
|
width: 748px;
|
||||||
|
margin:10px auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Description: Foundation 4 docs style for highlight.js
|
||||||
|
Author: Dan Allen <dan.j.allen@gmail.com>
|
||||||
|
Website: http://foundation.zurb.com/docs/
|
||||||
|
Version: 1.0
|
||||||
|
Date: 2013-04-02
|
||||||
|
*/
|
||||||
|
|
||||||
|
pre code {
|
||||||
|
display: block; padding: 0.5em;
|
||||||
|
background: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .decorator,
|
||||||
|
pre .annotation {
|
||||||
|
color: #000077;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .attribute {
|
||||||
|
color: #070;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .value,
|
||||||
|
pre .string,
|
||||||
|
pre .scss .value .string {
|
||||||
|
color: #d14;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .comment {
|
||||||
|
color: #998;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .function .title {
|
||||||
|
color: #900;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .class {
|
||||||
|
color: #458;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .id,
|
||||||
|
pre .pseudo,
|
||||||
|
pre .constant,
|
||||||
|
pre .hexcolor {
|
||||||
|
color: teal;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .variable {
|
||||||
|
color: #336699;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .javadoc {
|
||||||
|
color: #997700;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .pi,
|
||||||
|
pre .doctype {
|
||||||
|
color: #3344bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .number {
|
||||||
|
color: #099;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .important {
|
||||||
|
color: #f00;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .label {
|
||||||
|
color: #970;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .preprocessor {
|
||||||
|
color: #579;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .reserved,
|
||||||
|
pre .keyword,
|
||||||
|
pre .scss .value {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .regexp {
|
||||||
|
background-color: #fff0ff;
|
||||||
|
color: #880088;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .symbol {
|
||||||
|
color: #990073;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .symbol .string {
|
||||||
|
color: #a60;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .tag {
|
||||||
|
color: #007700;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .at_rule,
|
||||||
|
pre .at_rule .keyword {
|
||||||
|
color: #088;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .at_rule .preprocessor {
|
||||||
|
color: #808;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre .scss .tag,
|
||||||
|
pre .scss .attribute {
|
||||||
|
color: #339;
|
||||||
|
}
|
@ -16,6 +16,7 @@ require 'msf/ui/console/command_dispatcher/nop'
|
|||||||
require 'msf/ui/console/command_dispatcher/payload'
|
require 'msf/ui/console/command_dispatcher/payload'
|
||||||
require 'msf/ui/console/command_dispatcher/auxiliary'
|
require 'msf/ui/console/command_dispatcher/auxiliary'
|
||||||
require 'msf/ui/console/command_dispatcher/post'
|
require 'msf/ui/console/command_dispatcher/post'
|
||||||
|
require 'msf/util/document_generator'
|
||||||
|
|
||||||
module Msf
|
module Msf
|
||||||
module Ui
|
module Ui
|
||||||
@ -743,7 +744,9 @@ class Core
|
|||||||
def cmd_info_help
|
def cmd_info_help
|
||||||
print_line "Usage: info <module name> [mod2 mod3 ...]"
|
print_line "Usage: info <module name> [mod2 mod3 ...]"
|
||||||
print_line
|
print_line
|
||||||
print_line "Optionally the flag '-j' will print the data in json format"
|
print_line "Options:"
|
||||||
|
print_line "* The flag '-j' will print the data in json format"
|
||||||
|
print_line "* The flag '-d' will show the markdown version with a browser"
|
||||||
print_line "Queries the supplied module or modules for information. If no module is given,"
|
print_line "Queries the supplied module or modules for information. If no module is given,"
|
||||||
print_line "show info for the currently active module."
|
print_line "show info for the currently active module."
|
||||||
print_line
|
print_line
|
||||||
@ -754,15 +757,24 @@ class Core
|
|||||||
#
|
#
|
||||||
def cmd_info(*args)
|
def cmd_info(*args)
|
||||||
dump_json = false
|
dump_json = false
|
||||||
|
show_doc = false
|
||||||
|
|
||||||
if args.include?('-j')
|
if args.include?('-j')
|
||||||
args.delete('-j')
|
args.delete('-j')
|
||||||
dump_json = true
|
dump_json = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if args.include?('-d')
|
||||||
|
args.delete('-d')
|
||||||
|
show_doc = true
|
||||||
|
end
|
||||||
|
|
||||||
if (args.length == 0)
|
if (args.length == 0)
|
||||||
if (active_module)
|
if (active_module)
|
||||||
if dump_json
|
if dump_json
|
||||||
print(Serializer::Json.dump_module(active_module) + "\n")
|
print(Serializer::Json.dump_module(active_module) + "\n")
|
||||||
|
elsif show_doc
|
||||||
|
Msf::Util::DocumentGenerator.get_module_document(active_module)
|
||||||
else
|
else
|
||||||
print(Serializer::ReadableText.dump_module(active_module))
|
print(Serializer::ReadableText.dump_module(active_module))
|
||||||
end
|
end
|
||||||
@ -783,6 +795,8 @@ class Core
|
|||||||
print_error("Invalid module: #{name}")
|
print_error("Invalid module: #{name}")
|
||||||
elsif dump_json
|
elsif dump_json
|
||||||
print(Serializer::Json.dump_module(mod) + "\n")
|
print(Serializer::Json.dump_module(mod) + "\n")
|
||||||
|
elsif show_doc
|
||||||
|
Msf::Util::DocumentGenerator.get_module_document(mod)
|
||||||
else
|
else
|
||||||
print(Serializer::ReadableText.dump_module(mod))
|
print(Serializer::ReadableText.dump_module(mod))
|
||||||
end
|
end
|
||||||
|
285
lib/msf/util/document_generator.rb
Normal file
285
lib/msf/util/document_generator.rb
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
###
|
||||||
|
#
|
||||||
|
# This provides methods to generate documentation for a module.
|
||||||
|
#
|
||||||
|
###
|
||||||
|
|
||||||
|
require 'octokit'
|
||||||
|
require 'nokogiri'
|
||||||
|
require 'redcarpet'
|
||||||
|
require 'net/http'
|
||||||
|
require 'erb'
|
||||||
|
|
||||||
|
module Redcarpet
|
||||||
|
module Render
|
||||||
|
class MsfMdHTML < Redcarpet::Render::HTML
|
||||||
|
def block_code(code, language)
|
||||||
|
"<pre>" \
|
||||||
|
"<code>#{code}</code>" \
|
||||||
|
"</pre>"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
module Util
|
||||||
|
module DocumentGenerator
|
||||||
|
|
||||||
|
class HTMLwithPygments < Redcarpet::Render::HTML
|
||||||
|
def block_code(code, language)
|
||||||
|
"Nope"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class DocumentNormalizer
|
||||||
|
|
||||||
|
CSS_BASE_PATH = File.expand_path(File.join(Msf::Config.data_directory, 'markdown.css' ))
|
||||||
|
|
||||||
|
def get_md_content(items)
|
||||||
|
md_to_html(ERB.new(%Q|## #{items[:mod_name]}
|
||||||
|
|
||||||
|
#{normalize_description(items[:mod_description])}
|
||||||
|
|
||||||
|
## Module Name
|
||||||
|
|
||||||
|
#{items[:mod_fullname]}
|
||||||
|
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
#{normalize_authors(items[:mod_authors])}
|
||||||
|
|
||||||
|
<% unless items[:mod_pull_requests].empty? %>
|
||||||
|
## Related Pull Requests
|
||||||
|
|
||||||
|
#{normalize_pull_requests(items[:mod_pull_requests])}
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% unless items[:mod_refs].empty? %>
|
||||||
|
## References
|
||||||
|
|
||||||
|
#{normalize_references(items[:mod_refs])}
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
## Platforms
|
||||||
|
#{normalize_platforms(items[:mod_platforms])}
|
||||||
|
|
||||||
|
## Reliability
|
||||||
|
#{normalize_rank(items[:mod_rank])}
|
||||||
|
|
||||||
|
## Demo
|
||||||
|
|
||||||
|
#{normalize_demo_output(items[:mod_demo])}
|
||||||
|
|).result(binding()))
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def md_to_html(md)
|
||||||
|
md.gsub!(/\x20{12}/, '')
|
||||||
|
r = Redcarpet::Markdown.new(Redcarpet::Render::MsfMdHTML, fenced_code_blocks: true)
|
||||||
|
css_path =
|
||||||
|
%Q|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="file://#{CSS_BASE_PATH}">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
#{r.render(md)}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize_pull_requests(pull_requests)
|
||||||
|
formatted_pr = []
|
||||||
|
|
||||||
|
pull_requests.each_pair do |number, pr|
|
||||||
|
formatted_pr << "* <a href=\"https://github.com/rapid7/metasploit-framework/pull/#{number}\">##{number}</a> - #{pr[:title]}"
|
||||||
|
end
|
||||||
|
|
||||||
|
formatted_pr * "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize_description(description)
|
||||||
|
Rex::Text.wordwrap(Rex::Text.compress(description))
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize_authors(authors)
|
||||||
|
if authors.kind_of?(Array)
|
||||||
|
authors.collect { |a| "* #{a}" } * "\n"
|
||||||
|
else
|
||||||
|
authors
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize_targets(targets)
|
||||||
|
targets.collect { |c| "* #{c.name}" } * "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize_references(refs)
|
||||||
|
refs.collect { |r| "* <a href=\"#{r}\">#{r}</a>" } * "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize_platforms(platforms)
|
||||||
|
if platforms.kind_of?(Array)
|
||||||
|
platforms.collect { |p| "* #{p}" } * "\n"
|
||||||
|
else
|
||||||
|
platforms
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize_rank(rank)
|
||||||
|
"[#{Msf::RankingName[rank].capitalize}](https://github.com/rapid7/metasploit-framework/wiki/Exploit-Ranking)"
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize_demo_output(mod)
|
||||||
|
%Q|```
|
||||||
|
msf > use #{mod.fullname}
|
||||||
|
msf #{mod.type}(#{mod.shortname}) > show targets
|
||||||
|
... a list of targets ...
|
||||||
|
msf #{mod.type}(#{mod.shortname}) > set TARGET <target-id>
|
||||||
|
msf #{mod.type}(#{mod.shortname}) > show options
|
||||||
|
... show and set options ...
|
||||||
|
msf #{mod.type}(#{mod.shortname}) > run
|
||||||
|
```|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
class PullRequestFinder
|
||||||
|
class Exception < RuntimeError; end
|
||||||
|
|
||||||
|
MANUAL_BASE_PATH = File.expand_path(File.join(Msf::Config.module_directory, '..', 'documentation', 'modules' ))
|
||||||
|
|
||||||
|
attr_accessor :git_client
|
||||||
|
attr_accessor :repository
|
||||||
|
attr_accessor :branch
|
||||||
|
attr_accessor :owner
|
||||||
|
attr_accessor :git_access_token
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
unless ENV.has_key?('GITHUB_OAUTH_TOKEN')
|
||||||
|
raise PullRequestFinder::Exception, 'GITHUB_OAUTH_TOKEN environment variable not set.'
|
||||||
|
end
|
||||||
|
|
||||||
|
self.owner = 'rapid7'
|
||||||
|
self.repository = "#{owner}/metasploit-framework"
|
||||||
|
self.branch = 'master'
|
||||||
|
self.git_access_token = ENV['GITHUB_OAUTH_TOKEN']
|
||||||
|
self.git_client = Octokit::Client.new(access_token: git_access_token)
|
||||||
|
end
|
||||||
|
|
||||||
|
def search(mod)
|
||||||
|
file_name = get_normalized_module_name(mod)
|
||||||
|
commits = get_commits_from_file(file_name)
|
||||||
|
get_pull_requests_from_commits(commits)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def get_normalized_module_name(mod)
|
||||||
|
source_fname = mod.method(:initialize).source_location.first
|
||||||
|
source_fname.scan(/(modules.+)/).flatten.first || ''
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_commits_from_file(path)
|
||||||
|
commits = git_client.commits(repository, branch, path: path)
|
||||||
|
if commits.empty?
|
||||||
|
# Possibly the path is wrong.
|
||||||
|
raise PullRequestFinder::Exception, 'No commits found.'
|
||||||
|
end
|
||||||
|
|
||||||
|
commits
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_author(commit)
|
||||||
|
if commit.author
|
||||||
|
return commit.author[:login].to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
''
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_author_blacklisted?(commit)
|
||||||
|
['tabassassin'].include?(get_author(commit))
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_pull_requests_from_commits(commits)
|
||||||
|
pull_requests = {}
|
||||||
|
|
||||||
|
commits.each do |commit|
|
||||||
|
next if is_author_blacklisted?(commit)
|
||||||
|
|
||||||
|
pr = get_pull_request_from_commit(commit)
|
||||||
|
unless pr.empty?
|
||||||
|
pull_requests[pr[:number]] = pr
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
pull_requests
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_pull_request_from_commit(commit)
|
||||||
|
sha = commit.sha
|
||||||
|
url = URI.parse("https://github.com/#{repository}/branch_commits/#{sha}")
|
||||||
|
cli = Net::HTTP.new(url.host, url.port)
|
||||||
|
cli.use_ssl = true
|
||||||
|
req = Net::HTTP::Get.new(url.request_uri)
|
||||||
|
res = cli.request(req)
|
||||||
|
n = Nokogiri::HTML(res.body)
|
||||||
|
found_pr_link = n.at('li[@class="pull-request"]//a')
|
||||||
|
|
||||||
|
# If there is no PR associated with this commit, it's probably from the SVN days.
|
||||||
|
return {} unless found_pr_link
|
||||||
|
|
||||||
|
href = found_pr_link.attributes['href'].text
|
||||||
|
title = found_pr_link.attributes['title'].text
|
||||||
|
|
||||||
|
# Filter out all the pull requests that do not belong to rapid7.
|
||||||
|
# If this happens, it's probably because the PR was submitted to somebody's fork.
|
||||||
|
return {} unless /^\/#{owner}\// === href
|
||||||
|
|
||||||
|
{ number: href.scan(/\d+$/).flatten.first, title: title }
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_module_document(mod)
|
||||||
|
manual_path = File.join(PullRequestFinder::MANUAL_BASE_PATH, mod.fullname)
|
||||||
|
|
||||||
|
if File.exists?(manual_path)
|
||||||
|
Rex::Compat.open_webrtc_browser("file://#{manual_path}")
|
||||||
|
else
|
||||||
|
pr_finder = PullRequestFinder.new
|
||||||
|
pr = pr_finder.search(mod)
|
||||||
|
n = DocumentNormalizer.new
|
||||||
|
items = {
|
||||||
|
mod_description: mod.description,
|
||||||
|
mod_authors: mod.send(:module_info)['Author'],
|
||||||
|
mod_fullname: mod.fullname,
|
||||||
|
mod_name: mod.name,
|
||||||
|
mod_pull_requests: pr,
|
||||||
|
mod_refs: mod.references,
|
||||||
|
mod_rank: mod.rank,
|
||||||
|
mod_platforms: mod.send(:module_info)['Platform'],
|
||||||
|
mod_options: mod.datastore,
|
||||||
|
mod_demo: mod
|
||||||
|
}
|
||||||
|
|
||||||
|
if mod.respond_to?(:targets) && mod.targets
|
||||||
|
items[:mod_targets] = mod.targets
|
||||||
|
end
|
||||||
|
|
||||||
|
md = n.get_md_content(items)
|
||||||
|
f = Rex::Quickfile.new(["#{mod.shortname}_doc", '.html'])
|
||||||
|
f.write(md)
|
||||||
|
f.close
|
||||||
|
Rex::Compat.open_webrtc_browser("file://#{f.path}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user