xmpp4r_facebook 0.1 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: