contacts 1.0.12 → 1.0.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,7 +8,7 @@ require "thread"
8
8
 
9
9
  class Contacts
10
10
  TYPES = {}
11
- VERSION = "1.0.12"
11
+ VERSION = "1.0.13"
12
12
 
13
13
  class Base
14
14
  def initialize(login, password)
@@ -136,6 +136,9 @@ class Contacts
136
136
  cookies = parse_cookies(resp.response['set-cookie'], cookies)
137
137
  forward = resp.response['Location']
138
138
  forward ||= (data =~ /<meta.*?url='([^']+)'/ ? CGI.unescapeHTML($1) : nil)
139
+ if (not forward.nil?) && URI.parse(forward).host.nil?
140
+ forward = url.scheme.to_s + "://" + url.host.to_s + forward
141
+ end
139
142
  return data, resp, cookies, forward
140
143
  end
141
144
 
@@ -151,6 +154,9 @@ class Contacts
151
154
  data = uncompress(resp, data)
152
155
  cookies = parse_cookies(resp.response['set-cookie'], cookies)
153
156
  forward = resp.response['Location']
157
+ if (not forward.nil?) && URI.parse(forward).host.nil?
158
+ forward = url.scheme.to_s + "://" + url.host.to_s + forward
159
+ end
154
160
  return data, resp, cookies, forward
155
161
  end
156
162
 
@@ -67,7 +67,9 @@ class Contacts
67
67
  if @contacts != nil
68
68
  @contacts = @contacts.delete_if {|c| c["Emails"].nil?}.map do |c|
69
69
  name, emails = c.values_at "Name", "Emails"
70
- emails = emails.first.values
70
+ # emails are returned in a form of
71
+ # [{"Address"=>"home.email@gmail.com"}, {"Type"=>{"Id"=>"WORK"}, "Address"=>"work.email@gmail.com"}]
72
+ emails = emails.collect{|a| a.values_at("Address")}
71
73
  [name, emails].flatten
72
74
  end
73
75
  else
@@ -3,6 +3,7 @@ class Contacts
3
3
  URL = "http://login.live.com/login.srf?id=2"
4
4
  OLD_CONTACT_LIST_URL = "http://%s/cgi-bin/addresses"
5
5
  NEW_CONTACT_LIST_URL = "http://%s/mail/GetContacts.aspx"
6
+ NEWEST_CONTACT_LIST_URL = "http://%s/mail/options.aspx?subsection=26"
6
7
  COMPOSE_URL = "http://%s/cgi-bin/compose?"
7
8
  PROTOCOL_ERROR = "Hotmail has changed its protocols, please upgrade this library first. If that does not work, report this error at http://rubyforge.org/forum/?group_id=2693"
8
9
  PWDPAD = "IfYouAreReadingThisYouHaveTooMuchFreeTime"
@@ -60,10 +61,32 @@ class Contacts
60
61
  end
61
62
  =end
62
63
 
63
- data, resp, cookies, forward, old_url = get("http://mail.live.com/mail", cookies)
64
- data, resp, cookies, forward, old_url = get(forward, cookies)
65
-
66
- @domain = URI.parse(forward).host
64
+ data, resp, cookies, forward = get("http://mail.live.com/mail", cookies)
65
+ until forward.nil?
66
+ data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
67
+ end
68
+
69
+ # click on 'Contiune' if presented with the Hotmail Listened page
70
+ # look for the Submit button with a "TakeMeToInbox" name (this should work for other languages)
71
+ if (not old_url.grep(/MessageAtLogin.aspx/).first.nil?)
72
+
73
+ viewState = data.split(/>\s*?</).grep(/__VIEWSTATE/).first[/value=\".+?\"/][7..-2]
74
+ eventValidation = data.split(/>\s*?</).grep(/__EVENTVALIDATION/).first[/value=\".+?\"/][7..-2]
75
+ continueValue = data.split(/>\s*?</).grep(/TakeMeToInbox/).first[/value=\".+?\"/][7..-2]
76
+
77
+ # post back to the same url
78
+ postdata = "%s=%s&%s=%s&%s=%s" % [
79
+ "__VIEWSTATE", CGI.escape(viewState),
80
+ "__EVENTVALIDATION", CGI.escape(eventValidation),
81
+ CGI.escape("TakeMeToInbox"), CGI.escape(continueValue)
82
+ ]
83
+ data, resp, cookies, forward = post( old_url, postdata, cookies, old_url )
84
+ until forward.nil?
85
+ data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
86
+ end
87
+ end
88
+
89
+ @domain = URI.parse(old_url).host
67
90
  @cookies = cookies
68
91
  rescue AuthenticationError => m
69
92
  if @attempt == 1
@@ -73,10 +96,51 @@ class Contacts
73
96
  end
74
97
  end
75
98
 
99
+ def contacts(options = {})
100
+ return @contacts if @contacts
101
+ if connected?
102
+ url = URI.parse(contact_list_url)
103
+ data, resp, cookies, forward = get( contact_list_url, @cookies )
104
+
105
+ if resp.code_type != Net::HTTPOK
106
+ raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
107
+ end
108
+
109
+ # we have to click on the Export Contacts button to get the csv:
110
+ # Search the content for __VIEWSTATE or __EVENTVALIDATION
111
+ viewState = data.split(/>\s*?</).grep(/__VIEWSTATE/).first[/value=\".+?\"/][7..-2]
112
+ eventValidation = data.split(/>\s*?</).grep(/__EVENTVALIDATION/).first[/value=\".+?\"/][7..-2]
113
+ exportValue = data.split(/>\s*?</).grep(/ctl02\$ExportButton/).first[/value=\".+?\"/][7..-2]
114
+ mt = cookies.split("; ").grep(/mt=/).first[3..-1]
115
+
116
+ # post back to the same url
117
+ postdata = "%s=%s&%s=%s&%s=%s&%s=%s" % [
118
+ "__VIEWSTATE", CGI.escape(viewState),
119
+ "__EVENTVALIDATION", CGI.escape(eventValidation),
120
+ CGI.escape("ctl02$ExportButton"), CGI.escape(exportValue),
121
+ "mt", CGI.escape( mt )
122
+ ]
123
+
124
+ url = URI.parse(contact_list_url)
125
+ http = open_http(url)
126
+ resp, data = http.post("#{url.path}?#{url.query}", postdata,
127
+ "User-Agent" => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0",
128
+ "Accept-Encoding" => "gzip",
129
+ "Cookie" => cookies,
130
+ "Referer" => contact_list_url,
131
+ "Content-Type" => 'application/x-www-form-urlencoded'
132
+ )
133
+
134
+ data = uncompress(resp, data)
135
+ parse(data, options)
136
+ end
137
+ end
138
+
139
+
76
140
  private
77
141
 
78
142
  def contact_list_url
79
- NEW_CONTACT_LIST_URL % @domain
143
+ NEWEST_CONTACT_LIST_URL % @domain
80
144
  end
81
145
 
82
146
  def follow_email(data, id, contacts_slot)
@@ -100,7 +164,7 @@ class Contacts
100
164
 
101
165
  def parse(data, options={})
102
166
  data = data.split("\r\n")
103
- data = CSV.parse(data.join("\r\n").gsub('"', ''), ';')
167
+ data = CSV.parse(data.join("\r\n").gsub('"', '').gsub(';', ','), ';')
104
168
  col_names = data.shift
105
169
 
106
170
  @contacts = data.delete_if{|person|person[0].nil?}.map do |person|
@@ -109,7 +173,6 @@ class Contacts
109
173
  [[person[1], person[2], person[3]].delete_if{|i|i.empty?}.join(" "), person[idx - 1]] unless person[idx - 1].nil?
110
174
  end.compact
111
175
  end
112
-
113
176
  end
114
177
 
115
178
  TYPES[:hotmail] = Hotmail
@@ -16,7 +16,7 @@ class Contacts
16
16
 
17
17
  data, resp, cookies, forward = post(LOGIN_URL, postdata)
18
18
 
19
- if data.index("Invalid ID or password")
19
+ if data.index("Invalid ID or password") || data.index("This ID is not yet taken")
20
20
  raise AuthenticationError, "Username and password do not match"
21
21
  elsif data.index("Sign in") && data.index("to Yahoo!")
22
22
  raise AuthenticationError, "Required field must not be blank"
metadata CHANGED
@@ -1,19 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contacts
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.12
5
- platform: ""
4
+ version: 1.0.13
5
+ platform: ruby
6
6
  authors:
7
7
  - Lucas Carlson
8
8
  autorequire: contacts
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-07-11 00:00:00 -07:00
12
+ date: 2009-01-08 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
17
+ type: :runtime
17
18
  version_requirement:
18
19
  version_requirements: !ruby/object:Gem::Requirement
19
20
  requirements:
@@ -63,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
63
64
  requirements:
64
65
  - A json parser
65
66
  rubyforge_project:
66
- rubygems_version: 0.9.5
67
+ rubygems_version: 1.3.1
67
68
  signing_key:
68
69
  specification_version: 2
69
70
  summary: Ridiculously easy contact list information from various providers including Yahoo, Gmail, and Hotmail