FreedomCoder-esearchy 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +24 -2
- data/lib/esearchy.rb +14 -2
- data/lib/esearchy/bing.rb +3 -2
- data/lib/esearchy/google.rb +3 -2
- data/lib/esearchy/googlegroups.rb +3 -2
- data/lib/esearchy/linkedin.rb +69 -19
- data/lib/esearchy/yahoo.rb +2 -2
- metadata +1 -1
data/README.rdoc
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
= Esearch
|
2
2
|
|
3
3
|
== DESCRIPTION
|
4
|
-
Esearchy is a small library capable of searching the internet for email addresses. Currently,
|
4
|
+
Esearchy is a small library capable of searching the internet for email addresses. Currently, the supported search methods are engines such as Google, Bing, Yahoo, PGP servers, GoogleGroups, Linkedin, etc , but I intend to add many more.
|
5
5
|
|
6
6
|
Also, the library searches inside .pdf, .docx, .xlsx, .pptx, asn and .txt files for emails addresses and adds them to the list of found accounts. Finally, we have support for .docs files but for now only in Windows Platforms.
|
7
7
|
|
8
|
-
NOTE:
|
8
|
+
NOTE: THIS IS STILL BEING DEVELOPED CODE IS SUBMITTED DAILY SO BE AWARE THAT CODE MIGHT NOT WORK PROPERLY AL THE TIME. IF SOMETHING GOES WRONG PLEASE RAISE AN ISSUE.
|
9
|
+
|
10
|
+
In order to work Bing and Yahoo need an appid, for which you will have to create one for each and place them in fles so the library will be able to work properly.
|
9
11
|
* data/yahoo.key
|
10
12
|
* data/bing.key
|
11
13
|
|
@@ -35,23 +37,43 @@ For thouse who want to integrate this to their application you can use it in "th
|
|
35
37
|
domain.save_to_file "~/emails.txt"
|
36
38
|
end
|
37
39
|
|
40
|
+
|
38
41
|
or in the more classic way in which you can create an Esearchy objetc and work on it
|
39
42
|
|
40
43
|
domain = Esearchy.new :query => "domain.com", :maxhits => 500
|
41
44
|
domain.search
|
42
45
|
domain.save_to_file "~/emails.txt"
|
43
46
|
|
47
|
+
We now also have a LinkedIn search which looks for Names in the site. With those names it
|
48
|
+
* creates emails based on those emails.
|
49
|
+
* searches Google and Yahoo for emails related to those people.
|
50
|
+
|
51
|
+
ESearchy.create "domain.co" do |d|
|
52
|
+
d.engines = { "LinkedIn" => Linkedin.new}
|
53
|
+
d.company_name "Domain Corp"
|
54
|
+
d.linkedin_credentials "myuser@linkedin.com", "12345"
|
55
|
+
d.maxhits = 100
|
56
|
+
d.search
|
57
|
+
d.save_to_file "linkedin_emails.txt"
|
58
|
+
end
|
59
|
+
|
44
60
|
== REQUIREMENTS:
|
45
61
|
|
46
62
|
* ruby 1.8 or 1.9
|
47
63
|
* cgi
|
48
64
|
* pdf/reader
|
49
65
|
* json
|
66
|
+
* rubyzip
|
50
67
|
|
51
68
|
== INSTALL:
|
52
69
|
|
53
70
|
* sudo gem install freedomcoder-esearchy
|
54
71
|
|
72
|
+
== THANKS:
|
73
|
+
|
74
|
+
* http://www.penetrationtests.com/ [Penetration Testing Directory]
|
75
|
+
* http://www.mundoruby.com.ar/ [Ruby's News Aggregator]
|
76
|
+
|
55
77
|
== LICENSE:
|
56
78
|
|
57
79
|
(The MIT License)
|
data/lib/esearchy.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
local_path = "#{File.dirname(__FILE__) + '/esearchy/'}"
|
2
|
-
%w{google bing yahoo PGP keys}.each { |lib| require local_path + lib }
|
2
|
+
%w{google bing yahoo PGP keys linkedin}.each { |lib| require local_path + lib }
|
3
3
|
|
4
4
|
class ESearchy
|
5
5
|
def initialize(options={}, &block)
|
@@ -9,7 +9,8 @@ class ESearchy
|
|
9
9
|
@engines = options[:engines] || {"Google" => Google,
|
10
10
|
"Bing" => Bing,
|
11
11
|
"Yahoo" => Yahoo,
|
12
|
-
"PGP" => PGP
|
12
|
+
"PGP" => PGP,
|
13
|
+
"LinkedIn" => Linkedin }
|
13
14
|
@engines.each {|n,e| @engines[n] = e.new(@maxhits)}
|
14
15
|
@emails = Array.new
|
15
16
|
@threads = Array.new
|
@@ -54,6 +55,17 @@ class ESearchy
|
|
54
55
|
@engines['Bing'].appid = value
|
55
56
|
end
|
56
57
|
|
58
|
+
def linkedin_credentials(user, pass)
|
59
|
+
@engines['LinkedIn'].username = user
|
60
|
+
@engines['LinkedIn'].password = pass
|
61
|
+
end
|
62
|
+
alias_method :linkedin_credentials=, :linkedin_credentials
|
63
|
+
|
64
|
+
def company_name (company)
|
65
|
+
@engines['LinkedIn'].company_name = company
|
66
|
+
end
|
67
|
+
alias_method :company_name=, :company_name
|
68
|
+
|
57
69
|
def save_to_file(file)
|
58
70
|
open(file,"a") do |f|
|
59
71
|
emails.each { |e| f << e + "\n" }
|
data/lib/esearchy/bing.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
%w{rubygems json cgi net/http}.each { |lib| require lib }
|
2
2
|
local_path = "#{File.dirname(__FILE__)}/"
|
3
|
-
%w{searchy keys}.each {|lib| require local_path + lib}
|
3
|
+
%w{searchy keys useragent}.each {|lib| require local_path + lib}
|
4
4
|
|
5
5
|
class Bing
|
6
6
|
include Searchy
|
@@ -27,7 +27,8 @@ class Bing
|
|
27
27
|
http.start do |http|
|
28
28
|
request = Net::HTTP::Get.new("/json.aspx" + "?Appid="+ @appid +
|
29
29
|
"&query=" + CGI.escape(query) +
|
30
|
-
"&sources=web&web.count=50&start=#{@start}"
|
30
|
+
"&sources=web&web.count=50&start=#{@start}",
|
31
|
+
{'Cookie' => UserAgent::fetch})
|
31
32
|
response = http.request(request)
|
32
33
|
case response
|
33
34
|
when Net::HTTPSuccess, Net::HTTPRedirection
|
data/lib/esearchy/google.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
%w{rubygems cgi net/http}.each { |lib| require lib }
|
2
2
|
local_path = "#{File.dirname(__FILE__)}/"
|
3
|
-
%w{searchy keys}.each {|lib| require local_path + lib}
|
3
|
+
%w{searchy keys useragent}.each {|lib| require local_path + lib}
|
4
4
|
|
5
5
|
class Google
|
6
6
|
include Searchy
|
@@ -27,7 +27,8 @@ class Google
|
|
27
27
|
http.start do |http|
|
28
28
|
request = Net::HTTP::Get.new( "/cse?&safe=off&num=100&site=" +
|
29
29
|
"&q=" + CGI.escape(query) +
|
30
|
-
"&btnG=Search&start=#{@start}"
|
30
|
+
"&btnG=Search&start=#{@start}",
|
31
|
+
{'Cookie' => UserAgent::fetch})
|
31
32
|
response = http.request(request)
|
32
33
|
case response
|
33
34
|
when Net::HTTPSuccess, Net::HTTPRedirection
|
@@ -1,6 +1,6 @@
|
|
1
1
|
%w{rubygems cgi net/http}.each { |lib| require lib }
|
2
2
|
local_path = "#{File.dirname(__FILE__)}/"
|
3
|
-
%w{searchy keys}.each {|lib| require local_path + lib}
|
3
|
+
%w{searchy keys useragent}.each {|lib| require local_path + lib}
|
4
4
|
|
5
5
|
class GoogleGroups
|
6
6
|
include Searchy
|
@@ -25,7 +25,8 @@ class GoogleGroups
|
|
25
25
|
http.start do |http|
|
26
26
|
request = Net::HTTP::Get.new( "/groups/search?&safe=off&num=100" +
|
27
27
|
"&q=" + CGI.escape(query) +
|
28
|
-
"&btnG=Search&start=#{@start}"
|
28
|
+
"&btnG=Search&start=#{@start}",
|
29
|
+
{'Cookie' => UserAgent::fetch})
|
29
30
|
response = http.request(request)
|
30
31
|
case response
|
31
32
|
when Net::HTTPSuccess, Net::HTTPRedirection
|
data/lib/esearchy/linkedin.rb
CHANGED
@@ -1,31 +1,71 @@
|
|
1
|
-
%w{rubygems cgi net/http}.each { |lib| require lib }
|
1
|
+
%w{rubygems cgi net/http net/https}.each { |lib| require lib }
|
2
2
|
local_path = "#{File.dirname(__FILE__)}/"
|
3
|
-
%w{yahoo google}.each {|lib| require local_path + lib}
|
3
|
+
%w{yahoo google useragent}.each {|lib| require local_path + lib}
|
4
4
|
|
5
5
|
# http:///
|
6
6
|
class Linkedin
|
7
7
|
include Searchy
|
8
8
|
|
9
|
-
def initialize(maxhits=nil
|
9
|
+
def initialize(maxhits=nil)
|
10
10
|
@totalhits = maxhits || 0
|
11
11
|
@pages = 1
|
12
12
|
@emails = []
|
13
13
|
@lock = Mutex.new
|
14
|
-
@start =
|
14
|
+
@start = 0
|
15
15
|
@threads = []
|
16
16
|
@lock = Mutex.new
|
17
|
+
@username = String.new
|
18
|
+
@password = String.new
|
19
|
+
@company_name = nil
|
20
|
+
@cookie = nil
|
21
|
+
end
|
22
|
+
attr_accessor :emails, :username, :password, :company_name
|
23
|
+
|
24
|
+
def login
|
25
|
+
begin
|
26
|
+
http = Net::HTTP.new("www.linkedin.com",443)
|
27
|
+
http.use_ssl = true
|
28
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
29
|
+
http.start do |http|
|
30
|
+
request = Net::HTTP::Post.new("/secure/login",
|
31
|
+
{'Content-Type' => "application/x-www-form-urlencoded"})
|
32
|
+
request.body = "session_key=#{@username}" +
|
33
|
+
"&session_password=#{@password}" +
|
34
|
+
"&session_login=Sign+In&session_login=&session_rikey="
|
35
|
+
response = http.request(request)
|
36
|
+
case response
|
37
|
+
when Net::HTTPSuccess, Net::HTTPRedirection
|
38
|
+
return response['Set-Cookie']
|
39
|
+
else
|
40
|
+
return response.error!
|
41
|
+
end
|
42
|
+
end
|
43
|
+
rescue Net::HTTPFatalError
|
44
|
+
puts "Error: Something went wrong with the HTTP request"
|
45
|
+
end
|
17
46
|
end
|
18
|
-
attr_accessor :emails, :appid
|
19
47
|
|
20
48
|
def search(query)
|
21
49
|
@query = query
|
50
|
+
begin
|
51
|
+
@cookie = login
|
52
|
+
rescue
|
53
|
+
puts "Unable to parse Linkedin. Something went Wrong with the Credentials"
|
54
|
+
return nil
|
55
|
+
end
|
22
56
|
begin
|
23
57
|
http = Net::HTTP.new("www.linkedin.com",80)
|
24
58
|
http.start do |http|
|
25
|
-
request = Net::HTTP::Get.new("search?search=&
|
59
|
+
#request = Net::HTTP::Get.new("/search?search=&viewCriteria=1¤tCompany=co" +
|
60
|
+
# "&searchLocationType=Y&newnessType=Y" +
|
61
|
+
# "&proposalType=Y&pplSearchOrigin=ADVS&company=#{CGI.escape(@company_name)}" +
|
62
|
+
# "&sortCriteria=Relevance&page_num=#{@pages}", {'Cookie' => @cookie} )
|
63
|
+
headers = {'Cookie' => @cookie, 'User-Agent' => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; en-us) AppleWebKit/530.19.2 (KHTML, like Gecko) Version/4.0.2 Safari/530.19"}
|
64
|
+
request = Net::HTTP::Get.new("/search?search=&company=" +
|
65
|
+
CGI.escape(@company_name) +
|
26
66
|
"¤tCompany=currentCompany" +
|
27
67
|
"&trk=coprofile_in_network_see_more" +
|
28
|
-
"&page_num=" + @pages)
|
68
|
+
"&page_num=" + @pages.to_s, headers)
|
29
69
|
response = http.request(request)
|
30
70
|
case response
|
31
71
|
when Net::HTTPSuccess, Net::HTTPRedirection
|
@@ -34,12 +74,14 @@ class Linkedin
|
|
34
74
|
if @totalhits > @start
|
35
75
|
@pages = @pages + 1
|
36
76
|
puts "Searching in: #{self.class} up to point #{@start}"
|
37
|
-
|
77
|
+
search_people(response.body)
|
78
|
+
create_emails
|
38
79
|
sleep(4)
|
39
80
|
search(@query)
|
40
81
|
else
|
41
82
|
puts "Searching in: #{self.class} up to point #{@start}"
|
42
|
-
|
83
|
+
search_people(response.body)
|
84
|
+
create_emails
|
43
85
|
end
|
44
86
|
else
|
45
87
|
return response.error!
|
@@ -51,25 +93,33 @@ class Linkedin
|
|
51
93
|
end
|
52
94
|
|
53
95
|
def parse(string)
|
54
|
-
@totalhits = string.scan(/<p class="summary>"<strong>(
|
96
|
+
@totalhits = string.scan(/<p class="summary>"<strong>(.*)<\/strong>/) if @totalhits == 0
|
55
97
|
end
|
56
98
|
|
57
99
|
def search_people(string)
|
58
|
-
@people = string.scan(
|
100
|
+
@people = string.scan(/span class="given-name">(.*)<\/span>[\n\s]+<span class="family-name">(.*)<\/span>/)
|
59
101
|
end
|
60
102
|
def search_person(name,last)
|
61
|
-
|
62
|
-
|
103
|
+
email = []
|
104
|
+
# Search Yahoo
|
105
|
+
y = Yahoo.new(50)
|
106
|
+
y.search("first:\"#{name}\" last:\"#{last}\"")
|
107
|
+
emails.concat(y.emails).uniq!
|
108
|
+
# Search Google
|
109
|
+
#g = Google.new(50)
|
110
|
+
#g.search("#{name} #{last}")
|
111
|
+
#emails.concat(g.emails).uniq!
|
112
|
+
return emails
|
63
113
|
end
|
64
114
|
|
65
115
|
def create_emails
|
66
|
-
@domain =
|
116
|
+
@domain = @query.match(/@/) ? @query : ("@" + @query)
|
67
117
|
@people.each do |person|
|
68
|
-
name = person
|
69
|
-
|
70
|
-
@emails << name
|
71
|
-
|
72
|
-
@emails.
|
118
|
+
name,last = person
|
119
|
+
@emails << "#{name.split(' ')[0]}.#{last.split(' ')[0]}#{@domain}"
|
120
|
+
@emails << "#{name.first}#{last.split(' ')[0]}#{@domain}"
|
121
|
+
#@emails.concat(fix(search_person(name,last)))
|
122
|
+
@emails.uniq!
|
73
123
|
end
|
74
124
|
print_emails(@emails)
|
75
125
|
end
|
data/lib/esearchy/yahoo.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
%w{rubygems json cgi net/http}.each { |lib| require lib }
|
2
2
|
local_path = "#{File.dirname(__FILE__)}/"
|
3
|
-
%w{searchy keys}.each {|lib| require local_path + lib}
|
3
|
+
%w{searchy keys useragent}.each {|lib| require local_path + lib}
|
4
4
|
|
5
5
|
class Yahoo
|
6
6
|
include Searchy
|
@@ -28,7 +28,7 @@ class Yahoo
|
|
28
28
|
request = Net::HTTP::Get.new("/ysearch/web/v1/" + CGI.escape(query) +
|
29
29
|
"?appid="+ @appid +
|
30
30
|
"&format=json&count=50"+
|
31
|
-
"&start=#{@start}" )
|
31
|
+
"&start=#{@start}", {'Cookie' => UserAgent::fetch} )
|
32
32
|
response = http.request(request)
|
33
33
|
case response
|
34
34
|
when Net::HTTPSuccess, Net::HTTPRedirection
|