contacts 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/doc/classes/Contacts.html +1 -1
- data/doc/classes/Contacts.src/M000001.html +1 -1
- data/doc/classes/Contacts.src/M000002.html +1 -1
- data/doc/classes/Contacts/Base.src/M000005.html +2 -1
- data/doc/classes/Contacts/Base.src/M000006.html +1 -1
- data/doc/classes/Contacts/Base.src/M000007.html +1 -1
- data/doc/classes/Contacts/Base.src/M000008.html +2 -6
- data/doc/classes/Contacts/Hotmail.html +10 -0
- data/doc/classes/Contacts/Hotmail.src/M000011.html +1 -1
- data/doc/created.rid +1 -1
- data/doc/files/lib/contacts/base_rb.html +4 -1
- data/doc/files/lib/contacts/hotmail_rb.html +1 -1
- data/lib/contacts/base.rb +44 -16
- data/lib/contacts/hotmail.rb +50 -4
- metadata +2 -2
data/doc/classes/Contacts.html
CHANGED
@@ -137,7 +137,7 @@ Class <a href="Contacts/Yahoo.html" class="link">Contacts::Yahoo</a><br />
|
|
137
137
|
<tr class="top-aligned-row context-row">
|
138
138
|
<td class="context-item-name">VERSION</td>
|
139
139
|
<td>=</td>
|
140
|
-
<td class="context-item-value">"1.0.
|
140
|
+
<td class="context-item-value">"1.0.2"</td>
|
141
141
|
</tr>
|
142
142
|
</table>
|
143
143
|
</div>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
<link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
|
11
11
|
</head>
|
12
12
|
<body class="standalone-code">
|
13
|
-
<pre><span class="ruby-comment cmt"># File lib/contacts/base.rb, line
|
13
|
+
<pre><span class="ruby-comment cmt"># File lib/contacts/base.rb, line 182</span>
|
14
14
|
<span class="ruby-keyword kw">def</span> <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">type</span>, <span class="ruby-identifier">login</span>, <span class="ruby-identifier">password</span>)
|
15
15
|
<span class="ruby-keyword kw">if</span> <span class="ruby-constant">TYPES</span>.<span class="ruby-identifier">include?</span>(<span class="ruby-identifier">type</span>.<span class="ruby-identifier">to_s</span>.<span class="ruby-identifier">intern</span>)
|
16
16
|
<span class="ruby-constant">TYPES</span>[<span class="ruby-identifier">type</span>.<span class="ruby-identifier">to_s</span>.<span class="ruby-identifier">intern</span>].<span class="ruby-identifier">new</span>(<span class="ruby-identifier">login</span>, <span class="ruby-identifier">password</span>)
|
@@ -10,7 +10,7 @@
|
|
10
10
|
<link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
|
11
11
|
</head>
|
12
12
|
<body class="standalone-code">
|
13
|
-
<pre><span class="ruby-comment cmt"># File lib/contacts/base.rb, line
|
13
|
+
<pre><span class="ruby-comment cmt"># File lib/contacts/base.rb, line 190</span>
|
14
14
|
<span class="ruby-keyword kw">def</span> <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">guess</span>(<span class="ruby-identifier">login</span>, <span class="ruby-identifier">password</span>)
|
15
15
|
<span class="ruby-constant">TYPES</span>.<span class="ruby-identifier">inject</span>([]) <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">a</span>, <span class="ruby-identifier">t</span><span class="ruby-operator">|</span>
|
16
16
|
<span class="ruby-keyword kw">begin</span>
|
@@ -10,10 +10,11 @@
|
|
10
10
|
<link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
|
11
11
|
</head>
|
12
12
|
<body class="standalone-code">
|
13
|
-
<pre><span class="ruby-comment cmt"># File lib/contacts/base.rb, line
|
13
|
+
<pre><span class="ruby-comment cmt"># File lib/contacts/base.rb, line 14</span>
|
14
14
|
<span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">login</span>, <span class="ruby-identifier">password</span>)
|
15
15
|
<span class="ruby-ivar">@login</span> = <span class="ruby-identifier">login</span>
|
16
16
|
<span class="ruby-ivar">@password</span> = <span class="ruby-identifier">password</span>
|
17
|
+
<span class="ruby-ivar">@connections</span> = {}
|
17
18
|
<span class="ruby-identifier">connect</span>
|
18
19
|
<span class="ruby-keyword kw">end</span></pre>
|
19
20
|
</body>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
<link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
|
11
11
|
</head>
|
12
12
|
<body class="standalone-code">
|
13
|
-
<pre><span class="ruby-comment cmt"># File lib/contacts/base.rb, line
|
13
|
+
<pre><span class="ruby-comment cmt"># File lib/contacts/base.rb, line 21</span>
|
14
14
|
<span class="ruby-keyword kw">def</span> <span class="ruby-identifier">connect</span>
|
15
15
|
<span class="ruby-identifier">raise</span> <span class="ruby-constant">AuthenticationError</span>, <span class="ruby-node">"Login and password must not be nil, login: #{@login.inspect}, password: #{@password.inspect}"</span> <span class="ruby-keyword kw">if</span> <span class="ruby-ivar">@login</span>.<span class="ruby-identifier">nil?</span> <span class="ruby-operator">||</span> <span class="ruby-ivar">@password</span>.<span class="ruby-identifier">nil?</span>
|
16
16
|
<span class="ruby-identifier">real_connect</span>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
<link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
|
11
11
|
</head>
|
12
12
|
<body class="standalone-code">
|
13
|
-
<pre><span class="ruby-comment cmt"># File lib/contacts/base.rb, line
|
13
|
+
<pre><span class="ruby-comment cmt"># File lib/contacts/base.rb, line 26</span>
|
14
14
|
<span class="ruby-keyword kw">def</span> <span class="ruby-identifier">connected?</span>
|
15
15
|
<span class="ruby-ivar">@cookies</span> <span class="ruby-operator">&&</span> <span class="ruby-operator">!</span><span class="ruby-ivar">@cookies</span>.<span class="ruby-identifier">empty?</span>
|
16
16
|
<span class="ruby-keyword kw">end</span></pre>
|
@@ -10,16 +10,12 @@
|
|
10
10
|
<link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
|
11
11
|
</head>
|
12
12
|
<body class="standalone-code">
|
13
|
-
<pre><span class="ruby-comment cmt"># File lib/contacts/base.rb, line
|
13
|
+
<pre><span class="ruby-comment cmt"># File lib/contacts/base.rb, line 30</span>
|
14
14
|
<span class="ruby-keyword kw">def</span> <span class="ruby-identifier">contacts</span>
|
15
15
|
<span class="ruby-keyword kw">return</span> <span class="ruby-ivar">@contacts</span> <span class="ruby-keyword kw">if</span> <span class="ruby-ivar">@contacts</span>
|
16
16
|
<span class="ruby-keyword kw">if</span> <span class="ruby-identifier">connected?</span>
|
17
17
|
<span class="ruby-identifier">url</span> = <span class="ruby-constant">URI</span>.<span class="ruby-identifier">parse</span>(<span class="ruby-identifier">contact_list_url</span>)
|
18
|
-
<span class="ruby-identifier">http</span> = <span class="ruby-
|
19
|
-
<span class="ruby-keyword kw">if</span> <span class="ruby-identifier">url</span>.<span class="ruby-identifier">port</span> <span class="ruby-operator">==</span> <span class="ruby-value">443</span>
|
20
|
-
<span class="ruby-identifier">http</span>.<span class="ruby-identifier">use_ssl</span> = <span class="ruby-keyword kw">true</span>
|
21
|
-
<span class="ruby-identifier">http</span>.<span class="ruby-identifier">verify_mode</span> = <span class="ruby-constant">OpenSSL</span><span class="ruby-operator">::</span><span class="ruby-constant">SSL</span><span class="ruby-operator">::</span><span class="ruby-constant">VERIFY_NONE</span>
|
22
|
-
<span class="ruby-keyword kw">end</span>
|
18
|
+
<span class="ruby-identifier">http</span> = <span class="ruby-identifier">open_http</span>(<span class="ruby-identifier">url</span>)
|
23
19
|
<span class="ruby-identifier">resp</span>, <span class="ruby-identifier">data</span> = <span class="ruby-identifier">http</span>.<span class="ruby-identifier">get</span>(<span class="ruby-node">"#{url.path}?#{url.query}"</span>,
|
24
20
|
<span class="ruby-value str">"Cookie"</span> =<span class="ruby-operator">></span> <span class="ruby-ivar">@cookies</span>
|
25
21
|
)
|
@@ -115,6 +115,11 @@
|
|
115
115
|
<td>=</td>
|
116
116
|
<td class="context-item-value">"http://%s/cgi-bin/addresses"</td>
|
117
117
|
</tr>
|
118
|
+
<tr class="top-aligned-row context-row">
|
119
|
+
<td class="context-item-name">COMPOSE_URL</td>
|
120
|
+
<td>=</td>
|
121
|
+
<td class="context-item-value">"http://%s/cgi-bin/compose?"</td>
|
122
|
+
</tr>
|
118
123
|
<tr class="top-aligned-row context-row">
|
119
124
|
<td class="context-item-name">PROTOCOL_ERROR</td>
|
120
125
|
<td>=</td>
|
@@ -125,6 +130,11 @@
|
|
125
130
|
<td>=</td>
|
126
131
|
<td class="context-item-value">"IfYouAreReadingThisYouHaveTooMuchFreeTime"</td>
|
127
132
|
</tr>
|
133
|
+
<tr class="top-aligned-row context-row">
|
134
|
+
<td class="context-item-name">MAX_HTTP_THREADS</td>
|
135
|
+
<td>=</td>
|
136
|
+
<td class="context-item-value">8</td>
|
137
|
+
</tr>
|
128
138
|
</table>
|
129
139
|
</div>
|
130
140
|
</div>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
<link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
|
11
11
|
</head>
|
12
12
|
<body class="standalone-code">
|
13
|
-
<pre><span class="ruby-comment cmt"># File lib/contacts/hotmail.rb, line
|
13
|
+
<pre><span class="ruby-comment cmt"># File lib/contacts/hotmail.rb, line 10</span>
|
14
14
|
<span class="ruby-keyword kw">def</span> <span class="ruby-identifier">real_connect</span>
|
15
15
|
<span class="ruby-identifier">data</span>, <span class="ruby-identifier">resp</span>, <span class="ruby-identifier">cookies</span>, <span class="ruby-identifier">forward</span> = <span class="ruby-identifier">get</span>(<span class="ruby-constant">URL</span>)
|
16
16
|
<span class="ruby-identifier">data</span>, <span class="ruby-identifier">resp</span>, <span class="ruby-identifier">cookies</span>, <span class="ruby-identifier">forward</span> = <span class="ruby-identifier">get</span>(<span class="ruby-identifier">forward</span>, <span class="ruby-identifier">cookies</span>, <span class="ruby-constant">URL</span>)
|
data/doc/created.rid
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
Fri Mar 30 10:28:09 PDT 2007
|
@@ -56,7 +56,7 @@
|
|
56
56
|
</tr>
|
57
57
|
<tr class="top-aligned-row">
|
58
58
|
<td><strong>Last Update:</strong></td>
|
59
|
-
<td>
|
59
|
+
<td>Fri Mar 30 10:27:18 PDT 2007</td>
|
60
60
|
</tr>
|
61
61
|
</table>
|
62
62
|
</div>
|
@@ -77,6 +77,9 @@
|
|
77
77
|
net/http
|
78
78
|
net/https
|
79
79
|
uri
|
80
|
+
zlib
|
81
|
+
stringio
|
82
|
+
thread
|
80
83
|
</div>
|
81
84
|
</div>
|
82
85
|
|
data/lib/contacts/base.rb
CHANGED
@@ -2,15 +2,19 @@ require "cgi"
|
|
2
2
|
require "net/http"
|
3
3
|
require "net/https"
|
4
4
|
require "uri"
|
5
|
+
require "zlib"
|
6
|
+
require "stringio"
|
7
|
+
require "thread"
|
5
8
|
|
6
9
|
class Contacts
|
7
10
|
TYPES = {}
|
8
|
-
VERSION = "1.0.
|
11
|
+
VERSION = "1.0.2"
|
9
12
|
|
10
13
|
class Base
|
11
14
|
def initialize(login, password)
|
12
15
|
@login = login
|
13
16
|
@password = password
|
17
|
+
@connections = {}
|
14
18
|
connect
|
15
19
|
end
|
16
20
|
|
@@ -27,11 +31,7 @@ class Contacts
|
|
27
31
|
return @contacts if @contacts
|
28
32
|
if connected?
|
29
33
|
url = URI.parse(contact_list_url)
|
30
|
-
http =
|
31
|
-
if url.port == 443
|
32
|
-
http.use_ssl = true
|
33
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
34
|
-
end
|
34
|
+
http = open_http(url)
|
35
35
|
resp, data = http.get("#{url.path}?#{url.query}",
|
36
36
|
"Cookie" => @cookies
|
37
37
|
)
|
@@ -72,6 +72,21 @@ class Contacts
|
|
72
72
|
def contact_list_url
|
73
73
|
self.class.const_get(:CONTACT_LIST_URL)
|
74
74
|
end
|
75
|
+
|
76
|
+
def open_http(url)
|
77
|
+
c = @connections[Thread.current.object_id] ||= {}
|
78
|
+
http = c["#{url.host}:#{url.port}"]
|
79
|
+
unless http
|
80
|
+
http = Net::HTTP.new(url.host, url.port)
|
81
|
+
if url.port == 443
|
82
|
+
http.use_ssl = true
|
83
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
84
|
+
end
|
85
|
+
c["#{url.host}:#{url.port}"] = http
|
86
|
+
end
|
87
|
+
http.start unless http.started?
|
88
|
+
http
|
89
|
+
end
|
75
90
|
|
76
91
|
def parse_cookies(data, existing="")
|
77
92
|
return existing if data.nil?
|
@@ -105,17 +120,15 @@ class Contacts
|
|
105
120
|
|
106
121
|
def post(url, postdata, cookies="", referer="")
|
107
122
|
url = URI.parse(url)
|
108
|
-
http =
|
109
|
-
if url.port == 443
|
110
|
-
http.use_ssl = true
|
111
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
112
|
-
end
|
123
|
+
http = open_http(url)
|
113
124
|
resp, data = http.post(url.path, postdata,
|
114
125
|
"User-Agent" => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0",
|
126
|
+
"Accept-Encoding" => "gzip",
|
115
127
|
"Cookie" => cookies,
|
116
128
|
"Referer" => referer,
|
117
129
|
"Content-Type" => 'application/x-www-form-urlencoded'
|
118
130
|
)
|
131
|
+
data = uncompress(resp, data)
|
119
132
|
cookies = parse_cookies(resp.response['set-cookie'], cookies)
|
120
133
|
forward = resp.response['Location']
|
121
134
|
return data, resp, cookies, forward
|
@@ -123,20 +136,35 @@ class Contacts
|
|
123
136
|
|
124
137
|
def get(url, cookies="", referer="")
|
125
138
|
url = URI.parse(url)
|
126
|
-
http =
|
127
|
-
if url.port == 443
|
128
|
-
http.use_ssl = true
|
129
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
130
|
-
end
|
139
|
+
http = open_http(url)
|
131
140
|
resp, data = http.get("#{url.path}?#{url.query}",
|
132
141
|
"User-Agent" => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0",
|
142
|
+
"Accept-Encoding" => "gzip",
|
133
143
|
"Cookie" => cookies,
|
134
144
|
"Referer" => referer
|
135
145
|
)
|
146
|
+
data = uncompress(resp, data)
|
136
147
|
cookies = parse_cookies(resp.response['set-cookie'], cookies)
|
137
148
|
forward = resp.response['Location']
|
138
149
|
return data, resp, cookies, forward
|
139
150
|
end
|
151
|
+
|
152
|
+
def uncompress(resp, data)
|
153
|
+
case resp.response['content-encoding']
|
154
|
+
when 'gzip':
|
155
|
+
gz = Zlib::GzipReader.new(StringIO.new(data))
|
156
|
+
data = gz.read
|
157
|
+
gz.close
|
158
|
+
resp.response['content-encoding'] = nil
|
159
|
+
# FIXME: Not sure what Hotmail was feeding me with their 'deflate',
|
160
|
+
# but the headers definitely were not right
|
161
|
+
when 'deflate':
|
162
|
+
data = Zlib::Inflate.inflate(data)
|
163
|
+
resp.response['content-encoding'] = nil
|
164
|
+
end
|
165
|
+
|
166
|
+
data
|
167
|
+
end
|
140
168
|
end
|
141
169
|
|
142
170
|
class ContactsError < StandardError
|
data/lib/contacts/hotmail.rb
CHANGED
@@ -2,8 +2,10 @@ class Contacts
|
|
2
2
|
class Hotmail < Base
|
3
3
|
URL = "http://www.hotmail.com/"
|
4
4
|
CONTACT_LIST_URL = "http://%s/cgi-bin/addresses"
|
5
|
+
COMPOSE_URL = "http://%s/cgi-bin/compose?"
|
5
6
|
PROTOCOL_ERROR = "Hotmail has changed its protocols, please upgrade this library first. If that does not work, contact lucas@rufy.com with this error"
|
6
7
|
PWDPAD = "IfYouAreReadingThisYouHaveTooMuchFreeTime"
|
8
|
+
MAX_HTTP_THREADS = 8
|
7
9
|
|
8
10
|
def real_connect
|
9
11
|
data, resp, cookies, forward = get(URL)
|
@@ -60,15 +62,59 @@ class Contacts
|
|
60
62
|
CONTACT_LIST_URL % @domain
|
61
63
|
end
|
62
64
|
|
65
|
+
def follow_email(data, id, contacts_slot)
|
66
|
+
compose_url = COMPOSE_URL % @domain
|
67
|
+
postdata = "HrsTest=&to=#{id}&mailto=1&ref=addresses"
|
68
|
+
postdata += "&curmbox=00000000-0000-0000-0000-000000000001"
|
69
|
+
|
70
|
+
a = data.split(/>\s*<input\s+/i).grep(/\s+name="a"/i)
|
71
|
+
return nil if a.empty?
|
72
|
+
|
73
|
+
a = a[0].match(/\s+value="([a-f0-9]+)"/i) or return nil
|
74
|
+
postdata += "&a=#{a[1]}"
|
75
|
+
|
76
|
+
data, resp, @cookies, forward = post(compose_url, postdata, @cookies)
|
77
|
+
e = data.split(/>\s*<input\s+/i).grep(/\s+name="to"/i)
|
78
|
+
return nil if e.empty?
|
79
|
+
|
80
|
+
e = e[0].match(/\s+value="([^"]+)"/i) or return nil
|
81
|
+
@contacts[contacts_slot][1] = e[1] if e[1].match(/@/)
|
82
|
+
end
|
83
|
+
|
63
84
|
def parse(data)
|
64
85
|
chunks = data.split('id="hotmail"')
|
65
|
-
chunks.delete_at(0)
|
86
|
+
prev = chunks.delete_at(0)
|
66
87
|
|
67
|
-
|
88
|
+
queue = Queue.new
|
89
|
+
threads = []
|
90
|
+
@contacts = []
|
91
|
+
chunks.each do |chunk|
|
68
92
|
name = chunk.split('return false;">')[1].split('</a>')[0] rescue nil
|
69
93
|
email = chunk.split('return false;">')[2].split('</a>')[0] rescue nil
|
70
|
-
|
71
|
-
|
94
|
+
unless email && email != "more"
|
95
|
+
prev = chunk
|
96
|
+
next
|
97
|
+
end
|
98
|
+
next_slot = @contacts.size
|
99
|
+
@contacts[next_slot] = [name, email]
|
100
|
+
if email.match(/\.\.\.$/)
|
101
|
+
if m = prev.match(/\s+id="([A-Za-z0-9\-]+)"/)
|
102
|
+
queue.push([m[1], next_slot])
|
103
|
+
if threads.size < MAX_HTTP_THREADS
|
104
|
+
threads.push(Thread.new {
|
105
|
+
while x = queue.pop
|
106
|
+
follow_email(data, *x)
|
107
|
+
end
|
108
|
+
})
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
prev = chunk
|
113
|
+
end
|
114
|
+
|
115
|
+
threads.each { queue.push(nil) }
|
116
|
+
threads.each { |t| t.join }
|
117
|
+
@contacts
|
72
118
|
end
|
73
119
|
|
74
120
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: contacts
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.0.
|
7
|
-
date:
|
6
|
+
version: 1.0.2
|
7
|
+
date: 2007-03-30 00:00:00 -07:00
|
8
8
|
summary: Ridiculously easy contact list information from various providers including Yahoo, Gmail, and Hotmail
|
9
9
|
require_paths:
|
10
10
|
- lib
|