foco-contacts 1.2.18

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,78 @@
1
+ class Contacts
2
+ class Seznam < Base
3
+ DETECTED_DOMAINS = [ /seznam\.cz/i, /email\.cz/i, /post\.cz/i, /spoluzaci\.cz/i, /stream\.cz/i, /firmy\.cz/i, ]
4
+ LOGIN_URL = "https://login.szn.cz/loginProcess"
5
+ ADDRESS_BOOK_URL = "http://email.seznam.cz/abookCsvExport?sessionId=&charset=utf-8&eof=windows&export=nameLast&export=nameFirst&export=nick&export=email"
6
+
7
+ attr_accessor :cookies
8
+
9
+ def real_connect
10
+ postdata = "disableSSL=0&domain=%s&forceRelogin=0&forceSSL=0&lang=cz&loginType=seznam&returnURL=%s&serviceId=email&username=%s&password=%s" % [
11
+ CGI.escape(domain),
12
+ CGI.escape('http://email.seznam.cz/ticket'),
13
+ CGI.escape(username),
14
+ CGI.escape(password)
15
+ ]
16
+
17
+ data, resp, self.cookies, forward = post(LOGIN_URL, postdata, "")
18
+
19
+ if !forward.nil? && forward.match("badLogin")
20
+ raise AuthenticationError, "Username and password do not match"
21
+ end
22
+
23
+ doc = Nokogiri(data)
24
+
25
+ a = doc.at('body>a')
26
+ forward = a['href'].to_s
27
+
28
+ data, resp, self.cookies, forward = get(forward, self.cookies)
29
+
30
+ doc = Nokogiri(data)
31
+
32
+ a = doc.at('body>a')
33
+ forward = a['href'].to_s
34
+
35
+ data, resp, self.cookies, forward = get(forward, self.cookies)
36
+
37
+ doc = Nokogiri(data)
38
+
39
+ a = doc.at('body>a')
40
+ forward = a['href'].to_s
41
+
42
+ data, resp, self.cookies, forward = get(forward, self.cookies)
43
+ end
44
+
45
+ def contacts
46
+ @contacts = []
47
+
48
+ data, resp, self.cookies, forward = get(ADDRESS_BOOK_URL, self.cookies)
49
+
50
+ CSV.parse(data, { :col_sep => ';' }) do |row|
51
+ last_name, first_name, unknown, email = row
52
+
53
+ name = "#{first_name} #{last_name}".strip
54
+ email.strip!
55
+
56
+ @contacts << [name, email] unless email.empty?
57
+ end
58
+
59
+ @contacts
60
+ end
61
+
62
+ def skip_gzip?
63
+ false
64
+ end
65
+
66
+ private
67
+
68
+ def username
69
+ @login.split('@').first
70
+ end
71
+
72
+ def domain
73
+ @login.split('@').last
74
+ end
75
+ end
76
+
77
+ TYPES[:seznam] = Seznam
78
+ end
@@ -0,0 +1,79 @@
1
+ class Contacts
2
+ class TonlineDe < Base
3
+ DETECTED_DOMAINS = [ /t-mobile\.de/i, /t-online\.de/i ]
4
+ URL = "https://email.t-online.de/V4-0-4-0/srv-bin/aaa?method=deliverLoginBox"
5
+ ADDRESS_BOOK_URL = "https://email.t-online.de/V4-0-4-0/srv-bin/addressbook?method=exportAdressbook&p%5Bformat%5D=CSV&p%5Bliid%5D="
6
+ PROTOCOL_ERROR = "t-online.de has changed its protocols"
7
+
8
+ attr_accessor :cookies, :tid
9
+
10
+ def real_connect
11
+ data, resp, self.cookies, forward = get(URL, "")
12
+
13
+ doc = Nokogiri(data)
14
+ meta = doc.at('meta[http-equiv=refresh]')
15
+
16
+ if meta.nil?
17
+ raise ConnectionError, PROTOCOL_ERROR
18
+ end
19
+
20
+ forward = meta['content'].split('URL=').last
21
+
22
+ data, resp, self.cookies, forward = get(forward, self.cookies)
23
+
24
+ doc = Nokogiri(data)
25
+
26
+ self.tid = doc.at('input[name=tid]')['value']
27
+ url = doc.at('form[name=login]')['action']
28
+
29
+ postdata = "appid=0158&lang=de&login=Login&pwd=%s&skinid=30&tid=%s&usr=%s" % [
30
+ CGI.escape(password),
31
+ CGI.escape(self.tid),
32
+ CGI.escape(username)
33
+ ]
34
+
35
+ data, resp, self.cookies, forward = post(url, postdata, self.cookies)
36
+
37
+ if forward.nil? || !forward.match("loadUser")
38
+ raise AuthenticationError, "Username and password do not match"
39
+ end
40
+
41
+ data, resp, self.cookies, forward = get(forward, self.cookies)
42
+ end
43
+
44
+ def contacts
45
+ @contacts = []
46
+
47
+ data, resp, self.cookies, forward = get(ADDRESS_BOOK_URL, self.cookies)
48
+
49
+ CSV.parse(data) do |row|
50
+ other, first_name, last_name, email = row
51
+
52
+ name = "#{first_name} #{last_name}".strip
53
+ email.strip!
54
+
55
+ next unless email.include?('@')
56
+
57
+ @contacts << [name, email]
58
+ end
59
+
60
+ @contacts
61
+ end
62
+
63
+ def skip_gzip?
64
+ false
65
+ end
66
+
67
+ private
68
+
69
+ def username
70
+ @login.split('@').first
71
+ end
72
+
73
+ def domain
74
+ @login.split('@').last
75
+ end
76
+ end
77
+
78
+ TYPES[:tonline_de] = TonlineDe
79
+ end
@@ -0,0 +1,79 @@
1
+ class Contacts
2
+ class WebDe < Base
3
+ DETECTED_DOMAINS = [ /web\.de/i ]
4
+ LOGIN_URL = "https://uas2.uilogin.de/centrallogin-3.1/login"
5
+ ADDRESS_BOOK_URL = "https://mm.web.de/contacts"
6
+
7
+
8
+ attr_accessor :cookies
9
+
10
+ def real_connect
11
+ postdata = "serviceID=%s&username=%s&password=%s" % [
12
+ CGI.escape('mobile.web.mail.webde.live'),
13
+ CGI.escape(login),
14
+ CGI.escape(password)
15
+ ]
16
+
17
+ data, resp, self.cookies, forward = post(LOGIN_URL, postdata, "")
18
+
19
+ if !forward.index("/success")
20
+ raise AuthenticationError, "Username and password do not match"
21
+ end
22
+
23
+ data, resp, self.cookies, forward = get(forward, self.cookies)
24
+
25
+ end
26
+
27
+ def contacts
28
+ url = ADDRESS_BOOK_URL
29
+ @contacts = []
30
+
31
+ begin
32
+ data, resp, self.cookies, forward = get(url, self.cookies)
33
+ data, resp, cookies, forward = get(forward, self.cookies)
34
+
35
+ doc = Nokogiri(data)
36
+
37
+ (doc/'ul[id=addressLines]/li').each do |li|
38
+ links = (li/'a')
39
+
40
+ name = links[0].text.strip
41
+ name = name.split(', ').reverse.join(' ')
42
+
43
+ next if links[1].nil?
44
+
45
+ match = links[1]['href'].match('to=([^&]+)')
46
+
47
+ next if !match
48
+
49
+ email = match[1].strip
50
+
51
+ @contacts << [ name, email ]
52
+ end
53
+
54
+ a_next = doc.at('a[id=go-next]')
55
+
56
+ unless a_next.nil?
57
+ url = ADDRESS_BOOK_URL + '?' + a_next[:href].split('?')[1]
58
+ else
59
+ url = nil
60
+ end
61
+
62
+ end while !url.nil?
63
+
64
+ @contacts
65
+ end
66
+
67
+ def skip_gzip?
68
+ false
69
+ end
70
+
71
+ private
72
+
73
+ def header_row?(row)
74
+ row[0] == 'Last Name'
75
+ end
76
+ end
77
+
78
+ TYPES[:web_de] = WebDe
79
+ end
@@ -0,0 +1,106 @@
1
+ class Contacts
2
+ class Yahoo < Base
3
+ DETECTED_DOMAINS = [ /yahoo/i, /ymail/i, /rocketmail/i ]
4
+ URL = "http://mail.yahoo.com/"
5
+ LOGIN_URL = "https://login.yahoo.com/config/login"
6
+ ADDRESS_BOOK_URL = "http://address.mail.yahoo.com/?.rand=430244936"
7
+ CONTACT_LIST_URL = "http://address.mail.yahoo.com/?_src=&_crumb=crumb&sortfield=3&bucket=1&scroll=1&VPC=social_list&.r=time"
8
+ 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"
9
+
10
+ def real_connect
11
+ postdata = ".tries=2&.src=ym&.md5=&.hash=&.js=&.last=&promo=&.intl=us&.bypass="
12
+ postdata += "&.partner=&.u=4eo6isd23l8r3&.v=0&.challenge=gsMsEcoZP7km3N3NeI4mX"
13
+ postdata += "kGB7zMV&.yplus=&.emailCode=&pkg=&stepid=&.ev=&hasMsgr=1&.chkP=Y&."
14
+ postdata += "done=#{CGI.escape(URL)}&login=#{CGI.escape(login)}&passwd=#{CGI.escape(password)}"
15
+
16
+ data, resp, cookies, forward = post(LOGIN_URL, postdata)
17
+
18
+ if data.index("Invalid ID or password") || data.index("This ID is not yet taken")
19
+ # raise AuthenticationError, "Username and password do not match"
20
+ elsif data.index("Sign in") && data.index("to Yahoo!")
21
+ # raise AuthenticationError, "Required field must not be blank"
22
+ elsif !data.match(/uncompressed\/chunked/)
23
+ # raise ConnectionError, PROTOCOL_ERROR
24
+ elsif cookies == ""
25
+ # raise ConnectionError, PROTOCOL_ERROR
26
+ end
27
+
28
+ data, resp, cookies, forward = get(forward, cookies, LOGIN_URL)
29
+
30
+ if resp.code_type != Net::HTTPOK
31
+ # raise ConnectionError, PROTOCOL_ERROR
32
+ end
33
+
34
+ @cookies = cookies
35
+ end
36
+
37
+ def contacts
38
+ return @contacts if @contacts
39
+ @contacts = []
40
+
41
+ if connected?
42
+ # first, get the addressbook site with the new crumb parameter
43
+ url = URI.parse(address_book_url)
44
+ http = open_http(url)
45
+ resp = http.get("#{url.path}?#{url.query}",
46
+ "Cookie" => @cookies
47
+ )
48
+
49
+ if resp.code_type != Net::HTTPOK
50
+ # raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
51
+ end
52
+
53
+ crumb = resp.body.to_s[/dotCrumb: '(.*?)'/][13...-1]
54
+
55
+ # now proceed with the new ".crumb" parameter to get the csv data
56
+ url = URI.parse(contact_list_url.sub("_crumb=crumb","_crumb=#{crumb}").sub("time", Time.now.to_f.to_s.sub(".","")[0...-2]))
57
+ http = open_http(url)
58
+ resp = http.get("#{url.path}?#{url.query}",
59
+ "Cookie" => @cookies,
60
+ "X-Requested-With" => "XMLHttpRequest",
61
+ "Referer" => address_book_url
62
+ )
63
+
64
+ if resp.code_type != Net::HTTPOK
65
+ # raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
66
+ end
67
+
68
+ if resp.body =~ /"TotalABContacts":(\d+)/
69
+ total = $1.to_i
70
+ ((total / 50.0).ceil).times do |i|
71
+ # now proceed with the new ".crumb" parameter to get the csv data
72
+ 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]))
73
+ http = open_http(url)
74
+ resp = http.get("#{url.path}?#{url.query}",
75
+ "Cookie" => @cookies,
76
+ "X-Requested-With" => "XMLHttpRequest",
77
+ "Referer" => address_book_url
78
+ )
79
+
80
+ if resp.code_type != Net::HTTPOK
81
+ # raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
82
+ end
83
+
84
+ parse resp.body
85
+ end
86
+ end
87
+
88
+ @contacts
89
+ end
90
+ end
91
+
92
+ private
93
+
94
+ def parse(data, options={})
95
+ @contacts ||= []
96
+ @contacts += Contacts.parse_json(data)["response"]["ResultSet"]["Contacts"].to_a.select{|contact|!contact["email"].to_s.empty?}.map do |contact|
97
+ name = contact["contactName"].split(",")
98
+ [[name.pop, name.join(",")].join(" ").strip, contact["email"]]
99
+ end if data =~ /^\{"response":/
100
+ @contacts
101
+ end
102
+
103
+ end
104
+
105
+ TYPES[:yahoo] = Yahoo
106
+ end