2014-10-17 13:46:13 +00:00
|
|
|
# -*- coding: binary -*-
|
|
|
|
require 'msf/core'
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
2014-11-26 19:54:23 +00:00
|
|
|
# An author of a piece of code in either the framework, a module, a script,
|
|
|
|
# or something entirely unrelated.
|
2014-10-17 13:46:13 +00:00
|
|
|
#
|
|
|
|
###
|
|
|
|
class Msf::Author
|
|
|
|
|
2014-11-26 19:54:23 +00:00
|
|
|
#
|
|
|
|
# Constants
|
|
|
|
#
|
|
|
|
|
|
|
|
# A hash that maps known author names to email addresses
|
|
|
|
KNOWN = {
|
|
|
|
'amaloteaux' => 'alex_maloteaux' + 0x40.chr + 'metasploit.com',
|
|
|
|
'anonymous' => 'Unknown',
|
|
|
|
'bannedit' => 'bannedit' + 0x40.chr + 'metasploit.com',
|
|
|
|
'Carlos Perez' => 'carlos_perez' + 0x40.chr + 'darkoperator.com',
|
|
|
|
'cazz' => 'bmc' + 0x40.chr + 'shmoo.com',
|
|
|
|
'CG' => 'cg' + 0x40.chr + 'carnal0wnage.com',
|
|
|
|
'ddz' => 'ddz' + 0x40.chr + 'theta44.org',
|
|
|
|
'egypt' => 'egypt' + 0x40.chr + 'metasploit.com',
|
|
|
|
'et' => 'et' + 0x40.chr + 'metasploit.com',
|
|
|
|
'Christian Mehlmauer' => 'FireFart' + 0x40.chr + 'gmail.com',
|
|
|
|
'hdm' => 'hdm' + 0x40.chr + 'metasploit.com',
|
|
|
|
'I)ruid' => 'druid' + 0x40.chr + 'caughq.org',
|
|
|
|
'jcran' => 'jcran' + 0x40.chr + 'metasploit.com',
|
|
|
|
'jduck' => 'jduck' + 0x40.chr + 'metasploit.com',
|
|
|
|
'joev' => 'joev' + 0x40.chr + 'metasploit.com',
|
|
|
|
'juan vazquez' => 'juan.vazquez' + 0x40.chr + 'metasploit.com',
|
|
|
|
'kf' => 'kf_list' + 0x40.chr + 'digitalmunition.com',
|
|
|
|
'kris katterjohn' => 'katterjohn' + 0x40.chr + 'gmail.com',
|
|
|
|
'MC' => 'mc' + 0x40.chr + 'metasploit.com',
|
|
|
|
'Ben Campbell' => 'eat_meatballs' + 0x40.chr + 'hotmail.co.uk',
|
|
|
|
'msmith' => 'msmith' + 0x40.chr + 'metasploit.com',
|
|
|
|
'mubix' => 'mubix' + 0x40.chr + 'hak5.org',
|
|
|
|
'natron' => 'natron' + 0x40.chr + 'metasploit.com',
|
|
|
|
'optyx' => 'optyx' + 0x40.chr + 'no$email.com',
|
|
|
|
'patrick' => 'patrick' + 0x40.chr + 'osisecurity.com.au',
|
|
|
|
'pusscat' => 'pusscat' + 0x40.chr + 'metasploit.com',
|
|
|
|
'Ramon de C Valle' => 'rcvalle' + 0x40.chr + 'metasploit.com',
|
|
|
|
'sf' => 'stephen_fewer' + 0x40.chr + 'harmonysecurity.com',
|
|
|
|
'sinn3r' => 'sinn3r' + 0x40.chr + 'metasploit.com',
|
|
|
|
'skape' => 'mmiller' + 0x40.chr + 'hick.org',
|
|
|
|
'skylined' => 'skylined' + 0x40.chr + 'edup.tudelft.nl',
|
|
|
|
'spoonm' => 'spoonm' + 0x40.chr + 'no$email.com',
|
|
|
|
'stinko' => 'vinnie' + 0x40.chr + 'metasploit.com',
|
|
|
|
'theLightCosine' => 'theLightCosine' + 0x40.chr + 'metasploit.com',
|
|
|
|
'todb' => 'todb' + 0x40.chr + 'metasploit.com',
|
|
|
|
'vlad902' => 'vlad902' + 0x40.chr + 'gmail.com',
|
|
|
|
'wvu' => 'wvu' + 0x40.chr + 'metasploit.com'
|
|
|
|
}
|
2014-10-17 13:46:13 +00:00
|
|
|
|
|
|
|
#
|
2014-11-26 19:54:23 +00:00
|
|
|
# Class Methods
|
|
|
|
#
|
|
|
|
|
|
|
|
# Parses an {Author} instance from the specified string.
|
2014-10-17 13:46:13 +00:00
|
|
|
#
|
2014-11-26 19:54:23 +00:00
|
|
|
# @param str [String] the String to parse an Author instance from
|
|
|
|
# @return [Author] a valid {Author} instance
|
|
|
|
# @return nil if `str` is not the correct format
|
2014-10-17 13:46:13 +00:00
|
|
|
def self.from_s(str)
|
|
|
|
instance = self.new
|
|
|
|
|
|
|
|
# If the serialization fails...
|
2014-11-26 19:54:23 +00:00
|
|
|
if instance.from_s(str) == true
|
|
|
|
instance
|
|
|
|
else
|
|
|
|
nil
|
2014-10-17 13:46:13 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-11-26 19:54:23 +00:00
|
|
|
# Normalizes a single {Author} reference or an Array of {Author} references
|
|
|
|
# to an Array of {Author} references.
|
2014-10-17 13:46:13 +00:00
|
|
|
#
|
2014-11-26 19:54:23 +00:00
|
|
|
# @param src [Author, Array<Author>] a single {Author} or an Array of {Author} instances
|
|
|
|
# @return [Array<Author>] an Array of {Author} instances
|
2014-10-17 13:46:13 +00:00
|
|
|
def self.transform(src)
|
|
|
|
Rex::Transformer.transform(src, Array, [ self ], 'Author')
|
|
|
|
end
|
|
|
|
|
2014-11-26 19:54:23 +00:00
|
|
|
# Constructs an {Author} from a given `name` and `email`
|
|
|
|
#
|
|
|
|
# @param name [String] the author's name
|
|
|
|
# @param email [String] the author's email
|
2014-10-17 13:46:13 +00:00
|
|
|
def initialize(name = nil, email = nil)
|
|
|
|
self.name = name
|
2014-11-26 19:54:23 +00:00
|
|
|
self.email = email || KNOWN[name]
|
2014-10-17 13:46:13 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
2014-11-26 19:54:23 +00:00
|
|
|
# Instance Attributes
|
2014-10-17 13:46:13 +00:00
|
|
|
#
|
|
|
|
|
2014-11-26 19:54:23 +00:00
|
|
|
# @!attribute email
|
|
|
|
# An optional email associated with this {Author}.
|
|
|
|
#
|
|
|
|
# @return [String, nil]
|
|
|
|
attr_accessor :email
|
|
|
|
|
|
|
|
# @!attribute name
|
|
|
|
# The name associated with this {Author}.
|
2014-10-17 13:46:13 +00:00
|
|
|
#
|
2014-11-26 19:54:23 +00:00
|
|
|
# @return [String]
|
|
|
|
attr_reader :name
|
|
|
|
|
2014-10-17 13:46:13 +00:00
|
|
|
#
|
2014-11-26 19:54:23 +00:00
|
|
|
# Instance Methods
|
2014-10-17 13:46:13 +00:00
|
|
|
#
|
2014-11-26 19:54:23 +00:00
|
|
|
|
|
|
|
# @return [Boolean] whether the {Author} instances are equal
|
|
|
|
def ==(tgt)
|
|
|
|
tgt.to_s == to_s
|
|
|
|
end
|
|
|
|
|
|
|
|
# Serialize the {Author} instance to a string of the form `name` or `name <a@b.com>`
|
|
|
|
#
|
|
|
|
# @return [String] serialized {Author}
|
2014-10-17 13:46:13 +00:00
|
|
|
def to_s
|
|
|
|
str = "#{name}"
|
|
|
|
if (email and not email.empty?)
|
|
|
|
str += " <#{email}>"
|
|
|
|
end
|
2014-11-26 19:54:23 +00:00
|
|
|
str
|
2014-10-17 13:46:13 +00:00
|
|
|
end
|
|
|
|
|
2014-11-26 19:54:23 +00:00
|
|
|
|
|
|
|
# Parses {Author} details from the supplied string which may
|
|
|
|
# be of the form `name` or `name <a@b.com>`
|
2014-10-17 13:46:13 +00:00
|
|
|
#
|
2014-11-26 19:54:23 +00:00
|
|
|
# @param str [String] the String to parse from
|
|
|
|
# @return [Boolean] the translation succeeded
|
2014-10-17 13:46:13 +00:00
|
|
|
def from_s(str)
|
|
|
|
|
|
|
|
# Supported formats:
|
|
|
|
# known_name
|
|
|
|
# user [at/@] host [dot/.] tld
|
|
|
|
# Name <user [at/@] host [dot/.] tld>
|
|
|
|
|
2014-11-26 19:54:23 +00:00
|
|
|
if str.present?
|
|
|
|
if ((m = str.match(/^\s*([^<]+)<([^>]+)>\s*$/)))
|
|
|
|
self.name = m[1].sub(/<.*/, '')
|
|
|
|
self.email = m[2].sub(/\s*\[at\]\s*/, '@').sub(/\s*\[dot\]\s*/, '.')
|
2014-10-17 13:46:13 +00:00
|
|
|
else
|
2014-11-26 19:54:23 +00:00
|
|
|
if (KNOWN[str])
|
|
|
|
self.email = KNOWN[str]
|
|
|
|
self.name = str
|
|
|
|
else
|
|
|
|
self.email = str.sub(/\s*\[at\]\s*/, '@').sub(/\s*\[dot\]\s*/, '.').gsub(/^<|>$/, '')
|
|
|
|
m = self.email.match(/([^@]+)@/)
|
|
|
|
self.name = m ? m[1] : nil
|
|
|
|
if !(self.email and self.email.index('@'))
|
|
|
|
self.name = self.email
|
|
|
|
self.email = ''
|
|
|
|
end
|
2014-10-17 13:46:13 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-11-26 19:54:23 +00:00
|
|
|
self.name.strip! if self.name.present?
|
2014-10-17 13:46:13 +00:00
|
|
|
|
2014-11-26 19:54:23 +00:00
|
|
|
# The parse succeeds only when a name is found
|
|
|
|
self.name.present?
|
2014-10-17 13:46:13 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# Sets the name of the author and updates the email if it's a known author.
|
2014-11-26 19:54:23 +00:00
|
|
|
# @param name [String] the name to set
|
2014-10-17 13:46:13 +00:00
|
|
|
def name=(name)
|
2014-11-26 19:54:23 +00:00
|
|
|
if KNOWN.has_key?(name)
|
|
|
|
self.email = KNOWN[name]
|
|
|
|
end
|
2014-10-17 13:46:13 +00:00
|
|
|
@name = name
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|