xmpp4r_facebook 0.1 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/xmpp4r_facebook.rb +145 -0
  2. metadata +5 -4
@@ -0,0 +1,145 @@
1
+ #coding:utf-8
2
+ require 'xmpp4r'
3
+
4
+ module Jabber
5
+ module SASL
6
+ class XFacebookPlatform < Base
7
+ def initialize(stream, api_key, access_token, secret_key)
8
+ super(stream)
9
+ challenge = {}
10
+ error = nil
11
+ @stream.send(generate_auth('X-FACEBOOK-PLATFORM')) { |reply|
12
+ if reply.name == 'challenge' and reply.namespace == NS_SASL
13
+ challenge = decode_challenge(reply.text)
14
+ else
15
+ error = reply.first_element(nil).name
16
+ end
17
+ true
18
+ }
19
+ raise error if error
20
+
21
+ @nonce = challenge['nonce']
22
+ @realm = challenge['realm']
23
+ @method = challenge['method']
24
+ @api_key = api_key
25
+ @access_token = access_token
26
+ @secret_key = secret_key
27
+ end
28
+
29
+ def decode_challenge(challenge)
30
+ text = Base64::decode64(challenge)
31
+ res = {}
32
+ state = :key
33
+ key = ''
34
+ value = ''
35
+ text.scan(/./) do |ch|
36
+ if state == :key
37
+ if ch == '='
38
+ state = :value
39
+ else
40
+ key += ch
41
+ end
42
+ elsif state == :value
43
+ if ch == '&'
44
+ # due to our home-made parsing of the challenge, the key could have
45
+ # leading whitespace. strip it, or that would break jabberd2 support.
46
+ key = key.strip
47
+ res[key] = value
48
+ key = ''
49
+ value = ''
50
+ state = :key
51
+ elsif ch == '"' and value == ''
52
+ state = :quote
53
+ else
54
+ value += ch
55
+ end
56
+ elsif state == :quote
57
+ if ch == '"'
58
+ state = :value
59
+ else
60
+ value += ch
61
+ end
62
+ end
63
+ end
64
+ # due to our home-made parsing of the challenge, the key could have
65
+ # leading whitespace. strip it, or that would break jabberd2 support.
66
+ key = key.strip
67
+ res[key] = value unless key == ''
68
+ Jabber::debuglog("SASL DIGEST-MD5 challenge:\n#{text}\n#{res.inspect}")
69
+ res
70
+ end
71
+
72
+ ##
73
+ # * Send a response
74
+ # * Wait for the server's challenge (which aren't checked)
75
+ # * Send a blind response to the server's challenge
76
+ def auth(password)
77
+ response2 = {}
78
+ response2['api_key'] = @api_key
79
+ response2['call_id'] = Time.new.tv_sec
80
+ response2['method'] = @method
81
+ response2['nonce'] = @nonce
82
+ response2['access_token'] = @access_token
83
+ response2['v'] ='1.0'
84
+
85
+ response_text = response2.collect { |k,v| "#{k}=#{v}" }.join('&')
86
+ #Jabber::debuglog("SASL DIGEST-MD5 response:\n#{response_text}\n#{response.inspect}")
87
+
88
+ r = REXML::Element.new('response')
89
+ r.add_namespace NS_SASL
90
+ r.text = Base64::encode64(response_text)
91
+ success_already = false
92
+ error = nil
93
+ @stream.send(r) { |reply|
94
+ if reply.name == 'success'
95
+ success_already = true
96
+ elsif reply.name != 'challenge'
97
+ error = reply.first_element(nil).name
98
+ end
99
+ true
100
+ }
101
+
102
+ return if success_already
103
+ raise error if error
104
+
105
+ # TODO: check the challenge from the server
106
+
107
+ r.text = nil
108
+ @stream.send(r) { |reply|
109
+ if reply.name != 'success'
110
+ error = reply.first_element(nil).name
111
+ end
112
+ true
113
+ }
114
+
115
+ raise error if error
116
+ end
117
+
118
+ private
119
+
120
+ ##
121
+ # Function from RFC2831
122
+ def h(s); Digest::MD5.digest(s); end
123
+
124
+ ##
125
+ # Function from RFC2831
126
+ def hh(s); Digest::MD5.hexdigest(s); end
127
+
128
+ ##
129
+ # Calculate the value for the response field
130
+ def response_value(username, realm, digest_uri, passwd, nonce, cnonce, qop, authzid)
131
+ a1_h = h("#{username}:#{realm}:#{passwd}")
132
+ a1 = "#{a1_h}:#{nonce}:#{cnonce}"
133
+ if authzid
134
+ a1 += ":#{authzid}"
135
+ end
136
+ if qop == 'auth-int' || qop == 'auth-conf'
137
+ a2 = "AUTHENTICATE:#{digest_uri}:00000000000000000000000000000000"
138
+ else
139
+ a2 = "AUTHENTICATE:#{digest_uri}"
140
+ end
141
+ hh("#{hh(a1)}:#{nonce}:00000001:#{cnonce}:#{qop}:#{hh(a2)}")
142
+ end
143
+ end
144
+ end
145
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xmpp4r_facebook
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.1'
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-02-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: xmpp4r
16
- requirement: &84115460 !ruby/object:Gem::Requirement
16
+ requirement: &83866630 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,13 +21,14 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *84115460
24
+ version_requirements: *83866630
25
25
  description: Expansion XMPP4R to authenticate with Facebook Connect in Ruby
26
26
  email: kissrobber@gmail.com
27
27
  executables: []
28
28
  extensions: []
29
29
  extra_rdoc_files: []
30
- files: []
30
+ files:
31
+ - lib/xmpp4r_facebook.rb
31
32
  homepage: https://github.com/kissrobber
32
33
  licenses: []
33
34
  post_install_message: