im_contacts 1.2.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,125 @@
1
+ class Contacts
2
+ class Hotmail < Base
3
+ URL = "https://login.live.com/login.srf?id=2"
4
+ OLD_CONTACT_LIST_URL = "http://%s/cgi-bin/addresses"
5
+ NEW_CONTACT_LIST_URL = "http://%s/mail/GetContacts.aspx"
6
+ CONTACT_LIST_URL = "http://mpeople.live.com/default.aspx?pg=0"
7
+ COMPOSE_URL = "http://%s/cgi-bin/compose?"
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"
9
+ PWDPAD = "IfYouAreReadingThisYouHaveTooMuchFreeTime"
10
+ MAX_HTTP_THREADS = 8
11
+
12
+ def real_connect
13
+ data, resp, cookies, forward = get(URL)
14
+ old_url = URL
15
+ until forward.nil?
16
+ data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
17
+ end
18
+
19
+ postdata = "PPSX=%s&PwdPad=%s&login=%s&passwd=%s&LoginOptions=2&PPFT=%s" % [
20
+ CGI.escape(data.split("><").grep(/PPSX/).first[/=\S+$/][2..-3]),
21
+ PWDPAD[0...(PWDPAD.length-@password.length)],
22
+ CGI.escape(login),
23
+ CGI.escape(password),
24
+ CGI.escape(data.split("><").grep(/PPFT/).first[/=\S+$/][2..-3])
25
+ ]
26
+
27
+ form_url = data.split("><").grep(/form/).first.split[5][8..-2]
28
+ data, resp, cookies, forward = post(form_url, postdata, cookies)
29
+
30
+ old_url = form_url
31
+ until cookies =~ /; PPAuth=/ || forward.nil?
32
+ data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
33
+ end
34
+
35
+ if data.index("The e-mail address or password is incorrect")
36
+ raise AuthenticationError, "Username and password do not match"
37
+ elsif data != ""
38
+ raise AuthenticationError, "Required field must not be blank"
39
+ elsif cookies == ""
40
+ raise ConnectionError, PROTOCOL_ERROR
41
+ end
42
+
43
+ data, resp, cookies, forward = get("http://mail.live.com/mail", cookies)
44
+ until forward.nil?
45
+ data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
46
+ end
47
+
48
+ @domain = URI.parse(old_url).host
49
+ @cookies = cookies
50
+ rescue AuthenticationError => m
51
+ if @attempt == 1
52
+ retry
53
+ else
54
+ raise m
55
+ end
56
+ end
57
+
58
+ def contacts(options = {})
59
+ if connected?
60
+ url = URI.parse(contact_list_url)
61
+ data, resp, cookies, forward = get( contact_list_url, @cookies )
62
+
63
+ if resp.code_type != Net::HTTPOK
64
+ raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
65
+ end
66
+
67
+ @contacts = []
68
+ build_contacts = []
69
+ go = true
70
+ index = 0
71
+
72
+ while(go) do
73
+ go = false
74
+ url = URI.parse(get_contact_list_url(index))
75
+ http = open_http(url)
76
+ resp, data = http.get(get_contact_list_url(index), "Cookie" => @cookies)
77
+
78
+ email_match_text_beginning = Regexp.escape("http://m.mail.live.com/?rru=compose&amp;to=")
79
+ email_match_text_end = Regexp.escape("&amp;")
80
+
81
+ raw_html = resp.body.split("
82
+ ").grep(/(?:e|dn)lk[0-9]+/)
83
+ raw_html.inject(-1) do |memo, row|
84
+ c_info = row.match(/(e|dn)lk([0-9])+/)
85
+
86
+ # Same contact, or different?
87
+ build_contacts << [] if memo != c_info[2]
88
+
89
+ # Grab info
90
+ case c_info[1]
91
+ when "e" # Email
92
+ build_contacts.last[1] = row.match(/#{email_match_text_beginning}(.*)#{email_match_text_end}/)[1]
93
+ when "dn" # Name
94
+ build_contacts.last[0] = row.match(/<a[^>]*>(.+)<\/a>/)[1]
95
+ end
96
+
97
+ # Set memo to contact id
98
+ c_info[2]
99
+ end
100
+
101
+ go = resp.body.include?("ContactList_next")
102
+ index += 1
103
+ end
104
+
105
+ build_contacts.each do |contact|
106
+ unless contact[1].nil?
107
+ # Only return contacts with email addresses
108
+ contact[1] = CGI::unescape(contact[1])
109
+ @contacts << contact
110
+ end
111
+ end
112
+
113
+ return @contacts
114
+ end
115
+ end
116
+
117
+ def get_contact_list_url(index)
118
+ "http://mpeople.live.com/default.aspx?pg=#{index}"
119
+ end
120
+
121
+ private
122
+
123
+ TYPES[:hotmail] = Hotmail
124
+ end
125
+ end
@@ -0,0 +1,16 @@
1
+ if !Object.const_defined?('ActiveSupport')
2
+ require 'json'
3
+ end
4
+
5
+ class Contacts
6
+ def self.parse_json( string )
7
+ if Object.const_defined?('ActiveSupport') and
8
+ ActiveSupport.const_defined?('JSON')
9
+ ActiveSupport::JSON.decode( string )
10
+ elsif Object.const_defined?('JSON')
11
+ JSON.parse( string )
12
+ else
13
+ raise 'Contacts requires JSON or Rails (with ActiveSupport::JSON)'
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,117 @@
1
+ class Contacts
2
+ class NetEase < Base
3
+ URL = "http://www.163.com"
4
+ LOGIN_URL = "https://reg.163.com/logins.jsp"
5
+ LoginData = {
6
+ :url2 => {
7
+ :wy163 => 'http://mail.163.com/errorpage/err_163.htm',
8
+ :wy126 => 'http://mail.126.com/errorpage/err_126.htm',
9
+ :yeah => 'http://mail.yeah.net/errorpage/err_yeah.htm'
10
+ },
11
+ :url => {
12
+ :wy163 => 'http://entry.mail.163.com/coremail/fcg/ntesdoor2?lightweight=1&verifycookie=1&language=-1&style=-1&username=%s',
13
+ :wy126 => 'http://entry.mail.126.com/cgi/ntesdoor?hid=10010102&lightweight=1&verifycookie=1&language=0&style=-1&username=%s',
14
+ :yeah => 'http://entry.mail.yeah.net/cgi/ntesdoor?lightweight=1&verifycookie=1&style=-1&username=%s'
15
+ },
16
+ :product => {
17
+ :wy163 => 'mail163',
18
+ :wy126 => 'mail126',
19
+ :yeah => 'mailyeah'
20
+ }
21
+ }
22
+ ENTER_MAIL_URL = {
23
+ :wy163 => "http://entry.mail.163.com/coremail/fcg/ntesdoor2?lightweight=1&verifycookie=1&language=-1&style=-1&username=%s",
24
+ :wy126 => "http://entry.mail.126.com/cgi/ntesdoor?hid=10010102&lightweight=1&verifycookie=1&language=0&style=-1&username=%s",
25
+ :yeah => "http://entry.mail.yeah.net/cgi/ntesdoor?lightweight=1&verifycookie=1&style=-1&username=%s"
26
+ }
27
+
28
+ CONTACT_LIST_URL = "%ss?sid=%s&func=global:sequential"
29
+ PROTOCOL_ERROR = "netease has changed its protocols, please upgrade this library first. you can also contact kamechb@gmail.com"
30
+
31
+ def initialize(login, password, options={})
32
+ @mail_type = get_mail_type(login)
33
+ super(login,password,options)
34
+ end
35
+
36
+ def real_connect
37
+ login_for_cookies
38
+ enter_mail_server
39
+ end
40
+
41
+ def contacts
42
+ return @contacts if @contacts
43
+ if connected?
44
+ url = URI.parse(CONTACT_LIST_URL % [@mail_server,@sid])
45
+ http = open_http(url)
46
+ postdata = '<?xml version="1.0"?><object><array name="items"><object><string name="func">pab:searchContacts</string><object name="var"><array name="order"><object><string name="field">FN</string><boolean name="ignoreCase">true</boolean></object></array></object></object><object><string name="func">user:getSignatures</string></object><object><string name="func">pab:getAllGroups</string></object></array></object>'
47
+ set_header = {"Cookie" => @cookies,'Accept' => 'text/javascript','Content-Type' => 'application/xml; charset=UTF-8'}
48
+ resp, data = http.post("#{url.path}?#{url.query}",postdata,set_header)
49
+ if resp.code_type != Net::HTTPOK
50
+ raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
51
+ end
52
+ parse(data)
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def get_mail_type(username)
59
+ if username.include?("@126.com")
60
+ :wy126
61
+ elsif username.include?("@163.com")
62
+ :wy163
63
+ elsif username.include?("@yeah.net")
64
+ :yeah
65
+ else
66
+ raise MailServerError, "there are only three mail servers that 126.com, 163.com and yeah.net. please add domain after username"
67
+ end
68
+ end
69
+
70
+ def parse(data)
71
+ json_data = Contacts.parse_json(data)
72
+ json_data['var'][0]['var'].map{|contactor|
73
+ [contactor['FN'],contactor['EMAIL;PREF']]
74
+ }
75
+ end
76
+
77
+ def login_for_cookies
78
+ data = {
79
+ :type => '1',
80
+ :url => LoginData[:url][@mail_type],
81
+ :username => @login,
82
+ :password => @password,
83
+ :selType => '-1',
84
+ :remUser => '1',
85
+ :secure => 'on',
86
+ :verifycookie => '1',
87
+ :style => '-1',
88
+ :product => LoginData[:product][@mail_type],
89
+ :savelogin => '',
90
+ :url2 => LoginData[:url2][@mail_type]
91
+ }
92
+ postdata = data.to_query_string
93
+ #login and get cookie
94
+ data, resp, cookies, forward = post(LOGIN_URL,postdata)
95
+ @cookies = cookies
96
+ if data.index(LoginData[:url2][@mail_type])
97
+ raise AuthenticationError, "Username or password error"
98
+ end
99
+ end
100
+
101
+ def enter_mail_server
102
+ #get mail server and sid
103
+ enter_mail_url = ENTER_MAIL_URL[@mail_type] % @login
104
+ data, resp, cookies, forward = get(enter_mail_url,@cookies)
105
+ location = resp['Location']
106
+ data_reg = /<a.*?(http.*?)main.jsp\?sid=(.*?)\">/
107
+ location_reg = /(http.*?)main.jsp\?sid=(.*)/
108
+ unless data.match(data_reg) || location.match(location_reg)
109
+ raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
110
+ end
111
+ @cookies = cookies
112
+ @mail_server = $1
113
+ @sid = $2
114
+ end
115
+ TYPES[:net_ease] = NetEase
116
+ end
117
+ end
@@ -0,0 +1,130 @@
1
+ require 'rexml/document'
2
+
3
+ class Contacts
4
+ class Plaxo < Base
5
+ URL = "http://www.plaxo.com/"
6
+ LOGIN_URL = "https://www.plaxo.com/signin"
7
+ ADDRESS_BOOK_URL = "http://www.plaxo.com/po3/?module=ab&operation=viewFull&mode=normal"
8
+ CONTACT_LIST_URL = "http://www.plaxo.com/axis/soap/contact?_action=getContacts&_format=xml"
9
+ PROTOCOL_ERROR = "Plaxo has changed its protocols, please upgrade this library first. If that does not work, dive into the code and submit a patch at http://github.com/cardmagic/contacts"
10
+
11
+ def real_connect
12
+
13
+ end # real_connect
14
+
15
+ def contacts
16
+ getdata = "&authInfo.authByEmail.email=%s" % CGI.escape(login)
17
+ getdata += "&authInfo.authByEmail.password=%s" % CGI.escape(password)
18
+ data, resp, cookies, forward = get(CONTACT_LIST_URL + getdata)
19
+
20
+ if resp.code_type != Net::HTTPOK
21
+ raise ConnectionError, PROTOCOL_ERROR
22
+ end
23
+
24
+ parse data
25
+ end # contacts
26
+
27
+ private
28
+ def parse(data, options={})
29
+ doc = REXML::Document.new(data)
30
+ code = doc.elements['//response/code'].text
31
+
32
+ if code == '401'
33
+ raise AuthenticationError, "Username and password do not match"
34
+ elsif code == '200'
35
+ @contacts = []
36
+ doc.elements.each('//contact') do |cont|
37
+ name = if cont.elements['fullName']
38
+ cont.elements['fullName'].text
39
+ elsif cont.elements['displayName']
40
+ cont.elements['displayName'].text
41
+ end
42
+ email = if cont.elements['email1']
43
+ cont.elements['email1'].text
44
+ end
45
+ if name || email
46
+ @contacts << [name, email]
47
+ end
48
+ end
49
+ @contacts
50
+ else
51
+ raise ConnectionError, PROTOCOL_ERROR
52
+ end
53
+
54
+ end # parse
55
+
56
+ end # Plaxo
57
+
58
+ TYPES[:plaxo] = Plaxo
59
+
60
+ end # Contacts
61
+
62
+
63
+ # sample contacts responses
64
+ =begin
65
+ Bad email
66
+ =========
67
+ <?xml version="1.0" encoding="utf-8" ?>
68
+ <ns1:GetContactsResponse xmlns:ns1="Plaxo">
69
+ <response>
70
+ <code>401</code>
71
+ <subCode>1</subCode>
72
+ <message>User not found.</message>
73
+ </response>
74
+ </ns1:GetContactsResponse>
75
+
76
+
77
+ Bad password
78
+ ============
79
+ <?xml version="1.0" encoding="utf-8" ?>
80
+ <ns1:GetContactsResponse xmlns:ns1="Plaxo">
81
+ <response>
82
+ <code>401</code>
83
+ <subCode>4</subCode>
84
+ <message>Bad password or security token.</message>
85
+ </response>
86
+ </ns1:GetContactsResponse>
87
+
88
+
89
+ Success
90
+ =======
91
+ <?xml version="1.0" encoding="utf-8" ?>
92
+ <ns1:GetContactsResponse xmlns:ns1="Plaxo">
93
+
94
+ <response>
95
+ <code>200</code>
96
+ <message>OK</message>
97
+ <userId>77311236242</userId>
98
+ </response>
99
+
100
+ <contacts>
101
+
102
+ <contact>
103
+ <itemId>61312569</itemId>
104
+ <displayName>Joe Blow1</displayName>
105
+ <fullName>Joe Blow1</fullName>
106
+ <firstName>Joe</firstName>
107
+ <lastName>Blow1</lastName>
108
+ <homeEmail1>joeblow1@mailinator.com</homeEmail1>
109
+ <email1>joeblow1@mailinator.com</email1>
110
+ <folderId>5291351</folderId>
111
+ </contact>
112
+
113
+ <contact>
114
+ <itemId>61313159</itemId>
115
+ <displayName>Joe Blow2</displayName>
116
+ <fullName>Joe Blow2</fullName>
117
+ <firstName>Joe</firstName>
118
+ <lastName>Blow2</lastName>
119
+ <homeEmail1>joeblow2@mailinator.com</homeEmail1>
120
+ <email1>joeblow2@mailinator.com</email1>
121
+ <folderId>5291351</folderId>
122
+ </contact>
123
+
124
+ </contacts>
125
+
126
+ <totalCount>2</totalCount>
127
+ <editCounter>3</editCounter>
128
+
129
+ </ns1:GetContactsResponse>
130
+ =end
@@ -0,0 +1,91 @@
1
+ class Contacts
2
+ class Sina < Base
3
+ URL = "http://mail.sina.com.cn"
4
+ LOGIN_URL = {
5
+ :sina_cn => "https://mail.sina.com.cn/cgi-bin/cnlogin.php",
6
+ :sina_com => "https://mail.sina.com.cn/cgi-bin/login.php"
7
+ }
8
+ LOGIN_COOKIE = {
9
+ :sina_cn => "sina_cn_mail_id=nonobo_t; sina_cn_mail_recid=true",
10
+ :sina_com => "sina_free_mail_id=fangs2; sina_free_mail_recid=true; sina_free_mail_ltype=uid; sina_vip_mail_recid=false"
11
+ }
12
+ DOMAIN = {
13
+ :sina_cn => 'sina.cn',
14
+ :sina_com => 'sina.com'
15
+ }
16
+ PROTOCOL_ERROR = "sina has changed its protocols, please upgrade this library first. you can also contact kamechb@gmail.com"
17
+
18
+ def initialize(login, password, options={})
19
+ @mail_type = get_mail_type(login)
20
+ super(login,password,options)
21
+ end
22
+
23
+ def real_connect
24
+ login_for_cookies
25
+ redirect_for_location
26
+ end
27
+
28
+ def contacts
29
+ return @contacts if @contacts
30
+ if connected?
31
+ data, resp, cookies, forward = get(@mail_url,@cookies)
32
+ if resp.code_type != Net::HTTPOK
33
+ raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
34
+ end
35
+ parse(data)
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def get_mail_type(username)
42
+ if username.include?("@sina.com")
43
+ :sina_com
44
+ elsif username.include?("@sina.cn")
45
+ :sina_cn
46
+ else
47
+ raise MailServerError, "there are only two mail servers that sina.com and sina.cn. please add domain after username"
48
+ end
49
+ end
50
+
51
+ def parse(data)
52
+ data =~ /conf.*?contacts:.*?(\{.*?\}),\s*groups:/m
53
+ contacts = $1.gsub("&quot;",'')
54
+ contacts = ActiveSupport::JSON.decode(contacts)
55
+ contacts['contact'].map{|contactor|
56
+ [contactor['name'],contactor['email']]
57
+ }
58
+ end
59
+
60
+ def login_for_cookies
61
+ data = {
62
+ :domain => DOMAIN[@mail_type],
63
+ :logintype => 'uid',
64
+ :u => @login,
65
+ :psw => @password,
66
+ :savelogin => 'on',
67
+ :sshchk => 'on',
68
+ :ssl => 'on'
69
+ }
70
+ data, resp, cookies, forward = post(LOGIN_URL[@mail_type],data.to_query_string,LOGIN_COOKIE[@mail_type])
71
+ login_faile_flag = %r{form.*?action.*?http.*?mail.sina.com.cn/cgi-bin/.*?login.php}m
72
+ if data.match(login_faile_flag)
73
+ raise AuthenticationError, "Username or password error"
74
+ end
75
+ data.match(/URL=(http:\/\/.*?)'>/)
76
+ @redirect_url = $1
77
+ @mail_server = @redirect_url.match(/(http:\/\/.*\..*?)\//)
78
+ @cookies = cookies
79
+ end
80
+
81
+ def redirect_for_location
82
+ data, resp, cookies, forward = get(@redirect_url,@cookies)
83
+ location = resp['Location']
84
+ @mail_url = location.index("http://") ? location : "#{@mail_server}#{location}"
85
+ @cookies = cookies
86
+ end
87
+
88
+ TYPES[:sina] = Sina
89
+ end
90
+
91
+ end
@@ -0,0 +1,59 @@
1
+ class Contacts
2
+ class Sohu < Base
3
+ URL = "http://mail.sohu.com"
4
+ DOMAIN = "sohu.com"
5
+ LOGIN_URL = "https://passport.sohu.com/sso/login.jsp"
6
+ LOGIN_COOKIE = "IPLOC=CN3301; SUV=1008301317090277"
7
+ MAIL_URL = "http://mail.sohu.com/bapp/81/main"
8
+ PROTOCOL_ERROR = "sohu has changed its protocols, please upgrade this library first. you can also contact kamechb@gmail.com"
9
+
10
+ def real_connect
11
+ login_for_cookies
12
+ end
13
+
14
+ def contacts
15
+ return @contacts if @contacts
16
+ if connected?
17
+ data, resp, cookies, forward = get(MAIL_URL,@cookies)
18
+ if resp.code_type != Net::HTTPOK
19
+ raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
20
+ end
21
+ parse(data)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+
28
+ def parse(data)
29
+ data.match(/ADDRESSES.*?'(\{.*?\})';/m)
30
+ contacts = ActiveSupport::JSON.decode($1)
31
+ contacts['contact'].map{|contactor|
32
+ [contactor['nickname'],contactor['email']]
33
+ }
34
+ end
35
+
36
+ def login_for_cookies
37
+ data = {
38
+ :userid => @login,
39
+ :password => @password,
40
+ :appid => '1000',
41
+ :persistentcookie => '0',
42
+ :s => '1283173792650',
43
+ :b => '2',
44
+ :w => '1280',
45
+ :pwdtype => '0',
46
+ :v => '26'
47
+ }
48
+ data, resp, cookies, forward = get("#{LOGIN_URL}?#{data.to_query_string}",LOGIN_COOKIE)
49
+ login_faile_flag = %r{login_status.*?error}
50
+ if data.match(login_faile_flag)
51
+ raise AuthenticationError, "Username or password error"
52
+ end
53
+ @cookies = cookies
54
+ end
55
+
56
+ TYPES[:sohu] = Sohu
57
+ end
58
+
59
+ end
@@ -0,0 +1,103 @@
1
+ class Contacts
2
+ class Yahoo < Base
3
+ URL = "http://mail.yahoo.com/"
4
+ LOGIN_URL = "https://login.yahoo.com/config/login"
5
+ ADDRESS_BOOK_URL = "http://address.mail.yahoo.com/?.rand=430244936"
6
+ CONTACT_LIST_URL = "http://address.mail.yahoo.com/?_src=&_crumb=crumb&sortfield=3&bucket=1&scroll=1&VPC=social_list&.r=time"
7
+ PROTOCOL_ERROR = "Yahoo has changed its protocols, please upgrade this library first. If that does not work, dive into the code and submit a patch at http://github.com/cardmagic/contacts"
8
+
9
+ def real_connect
10
+ postdata = ".tries=2&.src=ym&.md5=&.hash=&.js=&.last=&promo=&.intl=us&.bypass="
11
+ postdata += "&.partner=&.u=4eo6isd23l8r3&.v=0&.challenge=gsMsEcoZP7km3N3NeI4mX"
12
+ postdata += "kGB7zMV&.yplus=&.emailCode=&pkg=&stepid=&.ev=&hasMsgr=1&.chkP=Y&."
13
+ postdata += "done=#{CGI.escape(URL)}&login=#{CGI.escape(login)}&passwd=#{CGI.escape(password)}"
14
+
15
+ data, resp, cookies, forward = post(LOGIN_URL, postdata)
16
+
17
+ if data.index("Invalid ID or password") || data.index("This ID is not yet taken")
18
+ raise AuthenticationError, "Username and password do not match"
19
+ elsif data.index("Sign in") && data.index("to Yahoo!")
20
+ raise AuthenticationError, "Required field must not be blank"
21
+ elsif !data.match(/uncompressed\/chunked/)
22
+ raise ConnectionError, PROTOCOL_ERROR
23
+ elsif cookies == ""
24
+ raise ConnectionError, PROTOCOL_ERROR
25
+ end
26
+
27
+ data, resp, cookies, forward = get(forward, cookies, LOGIN_URL)
28
+
29
+ if resp.code_type != Net::HTTPOK
30
+ raise ConnectionError, PROTOCOL_ERROR
31
+ end
32
+
33
+ @cookies = cookies
34
+ end
35
+
36
+ def contacts
37
+ return @contacts if @contacts
38
+ if connected?
39
+ # first, get the addressbook site with the new crumb parameter
40
+ url = URI.parse(address_book_url)
41
+ http = open_http(url)
42
+ resp, data = http.get("#{url.path}?#{url.query}",
43
+ "Cookie" => @cookies
44
+ )
45
+
46
+ if resp.code_type != Net::HTTPOK
47
+ raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
48
+ end
49
+
50
+ crumb = data.to_s[/dotCrumb: '(.*?)'/][13...-1]
51
+
52
+ # now proceed with the new ".crumb" parameter to get the csv data
53
+ url = URI.parse(contact_list_url.sub("_crumb=crumb","_crumb=#{crumb}").sub("time", Time.now.to_f.to_s.sub(".","")[0...-2]))
54
+ http = open_http(url)
55
+ resp, more_data = http.get("#{url.path}?#{url.query}",
56
+ "Cookie" => @cookies,
57
+ "X-Requested-With" => "XMLHttpRequest",
58
+ "Referer" => address_book_url
59
+ )
60
+
61
+ if resp.code_type != Net::HTTPOK
62
+ raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
63
+ end
64
+
65
+ if more_data =~ /"TotalABContacts":(\d+)/
66
+ total = $1.to_i
67
+ ((total / 50.0).ceil).times do |i|
68
+ # now proceed with the new ".crumb" parameter to get the csv data
69
+ url = URI.parse(contact_list_url.sub("bucket=1","bucket=#{i}").sub("_crumb=crumb","_crumb=#{crumb}").sub("time", Time.now.to_f.to_s.sub(".","")[0...-2]))
70
+ http = open_http(url)
71
+ resp, more_data = http.get("#{url.path}?#{url.query}",
72
+ "Cookie" => @cookies,
73
+ "X-Requested-With" => "XMLHttpRequest",
74
+ "Referer" => address_book_url
75
+ )
76
+
77
+ if resp.code_type != Net::HTTPOK
78
+ raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
79
+ end
80
+
81
+ parse more_data
82
+ end
83
+ end
84
+
85
+ @contacts
86
+ end
87
+ end
88
+
89
+ private
90
+
91
+ def parse(data, options={})
92
+ @contacts ||= []
93
+ @contacts += Contacts.parse_json(data)["response"]["ResultSet"]["Contacts"].to_a.select{|contact|!contact["email"].to_s.empty?}.map do |contact|
94
+ name = contact["contactName"].split(",")
95
+ [[name.pop, name.join(",")].join(" ").strip, contact["email"]]
96
+ end if data =~ /^\{"response":/
97
+ @contacts
98
+ end
99
+
100
+ end
101
+
102
+ TYPES[:yahoo] = Yahoo
103
+ end
@@ -0,0 +1,17 @@
1
+ $:.unshift(File.dirname(__FILE__)+"/contacts/")
2
+
3
+ require 'rubygems'
4
+ unless Object.const_defined?('ActiveSupport')
5
+ require 'active_support'
6
+ end
7
+ require 'base'
8
+ require 'gmail'
9
+ require 'hotmail'
10
+ require 'yahoo'
11
+ require 'plaxo'
12
+ require 'aol'
13
+ require 'net_ease'
14
+ require 'sina'
15
+ require 'sohu'
16
+ require 'json_picker'
17
+ require 'hash_ext'