rest-more 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/.gitignore +6 -0
  2. data/.gitmodules +3 -0
  3. data/.travis.yml +13 -0
  4. data/CHANGES.md +7 -0
  5. data/Gemfile +26 -0
  6. data/LICENSE +201 -0
  7. data/README.md +72 -0
  8. data/Rakefile +63 -0
  9. data/TODO.md +14 -0
  10. data/example/rails2/Gemfile +21 -0
  11. data/example/rails2/README +4 -0
  12. data/example/rails2/Rakefile +11 -0
  13. data/example/rails2/app/controllers/application_controller.rb +134 -0
  14. data/example/rails2/app/views/application/helper.html.erb +2 -0
  15. data/example/rails2/config/boot.rb +130 -0
  16. data/example/rails2/config/environment.rb +15 -0
  17. data/example/rails2/config/environments/development.rb +17 -0
  18. data/example/rails2/config/environments/production.rb +28 -0
  19. data/example/rails2/config/environments/test.rb +30 -0
  20. data/example/rails2/config/initializers/cookie_verification_secret.rb +7 -0
  21. data/example/rails2/config/initializers/new_rails_defaults.rb +21 -0
  22. data/example/rails2/config/initializers/session_store.rb +15 -0
  23. data/example/rails2/config/preinitializer.rb +23 -0
  24. data/example/rails2/config/rest-core.yaml +16 -0
  25. data/example/rails2/config/routes.rb +43 -0
  26. data/example/rails2/log +0 -0
  27. data/example/rails2/test/functional/application_controller_test.rb +219 -0
  28. data/example/rails2/test/test_helper.rb +18 -0
  29. data/example/rails2/test/unit/rails_util_test.rb +44 -0
  30. data/example/rails3/Gemfile +20 -0
  31. data/example/rails3/README +4 -0
  32. data/example/rails3/Rakefile +7 -0
  33. data/example/rails3/app/controllers/application_controller.rb +134 -0
  34. data/example/rails3/app/views/application/helper.html.erb +2 -0
  35. data/example/rails3/config.ru +4 -0
  36. data/example/rails3/config/application.rb +23 -0
  37. data/example/rails3/config/boot.rb +6 -0
  38. data/example/rails3/config/environment.rb +5 -0
  39. data/example/rails3/config/environments/development.rb +23 -0
  40. data/example/rails3/config/environments/production.rb +49 -0
  41. data/example/rails3/config/environments/test.rb +30 -0
  42. data/example/rails3/config/initializers/secret_token.rb +7 -0
  43. data/example/rails3/config/initializers/session_store.rb +8 -0
  44. data/example/rails3/config/rest-core.yaml +16 -0
  45. data/example/rails3/config/routes.rb +5 -0
  46. data/example/rails3/test/functional/application_controller_test.rb +219 -0
  47. data/example/rails3/test/test_helper.rb +18 -0
  48. data/example/rails3/test/unit/rails_util_test.rb +44 -0
  49. data/example/sinatra/config.ru +16 -0
  50. data/lib/rest-core/client/facebook.rb +265 -0
  51. data/lib/rest-core/client/facebook/rails_util.rb +334 -0
  52. data/lib/rest-core/client/flurry.rb +107 -0
  53. data/lib/rest-core/client/flurry/rails_util.rb +74 -0
  54. data/lib/rest-core/client/github.rb +18 -0
  55. data/lib/rest-core/client/linkedin.rb +59 -0
  56. data/lib/rest-core/client/mixi.rb +47 -0
  57. data/lib/rest-core/client/simple.rb +2 -0
  58. data/lib/rest-core/client/twitter.rb +101 -0
  59. data/lib/rest-core/client/universal.rb +18 -0
  60. data/lib/rest-more.rb +11 -0
  61. data/lib/rest-more/version.rb +4 -0
  62. data/rest-more.gemspec +127 -0
  63. data/task/.gitignore +1 -0
  64. data/task/gemgem.rb +265 -0
  65. data/test/client/facebook/config/rest-core.yaml +8 -0
  66. data/test/client/facebook/test_api.rb +97 -0
  67. data/test/client/facebook/test_cache.rb +58 -0
  68. data/test/client/facebook/test_default.rb +23 -0
  69. data/test/client/facebook/test_error.rb +65 -0
  70. data/test/client/facebook/test_handler.rb +84 -0
  71. data/test/client/facebook/test_load_config.rb +39 -0
  72. data/test/client/facebook/test_misc.rb +72 -0
  73. data/test/client/facebook/test_oauth.rb +38 -0
  74. data/test/client/facebook/test_old.rb +114 -0
  75. data/test/client/facebook/test_page.rb +106 -0
  76. data/test/client/facebook/test_parse.rb +166 -0
  77. data/test/client/facebook/test_serialize.rb +43 -0
  78. data/test/client/facebook/test_timeout.rb +22 -0
  79. data/test/client/flurry/test_metrics.rb +83 -0
  80. data/test/client/twitter/test_api.rb +37 -0
  81. metadata +155 -0
@@ -0,0 +1,16 @@
1
+
2
+ require 'sinatra'
3
+ require 'rest-core'
4
+
5
+ app_id = '123'
6
+ secret = 'abc'
7
+ config = {:app_id => app_id,
8
+ :secret => secret}
9
+
10
+ post '/' do
11
+ fb = RestCore::Facebook.new(config)
12
+ fb.parse_signed_request!(params['signed_request'])
13
+ "#{fb.get('me').inspect.gsub('<', '&lt;')}\n"
14
+ end
15
+
16
+ run Sinatra::Application
@@ -0,0 +1,265 @@
1
+
2
+ require 'rest-core'
3
+ require 'rest-core/util/hmac'
4
+
5
+ RestCore::Facebook = RestCore::Builder.client(
6
+ :data, :app_id, :secret, :old_site) do
7
+
8
+ s = self.class # this is only for ruby 1.8!
9
+ use s::Timeout , 10
10
+
11
+ use s::DefaultSite , 'https://graph.facebook.com/'
12
+ use s::DefaultHeaders, {'Accept' => 'application/json',
13
+ 'Accept-Language' => 'en-us'}
14
+ use s::Oauth2Query , nil
15
+
16
+ use s::CommonLogger , nil
17
+ use s::Cache , nil, 600 do
18
+ use s::ErrorHandler, lambda{ |env|
19
+ raise ::RestCore::Facebook::Error.call(env) }
20
+ use s::ErrorDetector, lambda{ |env|
21
+ if env[s::RESPONSE_BODY].kind_of?(Hash)
22
+ env[s::RESPONSE_BODY]['error'] ||
23
+ env[s::RESPONSE_BODY]['error_code']
24
+ end}
25
+
26
+ use s::JsonDecode , true
27
+ end
28
+
29
+ use s::Defaults , :data => lambda{{}},
30
+ :old_site => 'https://api.facebook.com/'
31
+ end
32
+
33
+ class RestCore::Facebook::Error < RestCore::Error
34
+ include RestCore
35
+ class AccessToken < Facebook::Error; end
36
+ class InvalidAccessToken < AccessToken ; end
37
+ class MissingAccessToken < AccessToken ; end
38
+
39
+ attr_reader :error, :url
40
+ def initialize error, url=''
41
+ @error, @url = error, url
42
+ super("#{error.inspect} from #{url}")
43
+ end
44
+
45
+ def self.call env
46
+ error, url = env[RESPONSE_BODY], Middleware.request_uri(env)
47
+ return new(env[FAIL], url) unless error.kind_of?(Hash)
48
+ if invalid_token?(error)
49
+ InvalidAccessToken.new(error, url)
50
+ elsif missing_token?(error)
51
+ MissingAccessToken.new(error, url)
52
+ else
53
+ new(error, url)
54
+ end
55
+ end
56
+
57
+ def self.invalid_token? error
58
+ (%w[OAuthInvalidTokenException
59
+ OAuthException].include?((error['error'] || {})['type'])) ||
60
+ (error['error_code'] == 190) # Invalid OAuth 2.0 Access Token
61
+ end
62
+
63
+ def self.missing_token? error
64
+ (error['error'] || {})['message'] =~ /^An active access token/ ||
65
+ (error['error_code'] == 104) # Requires valid signature
66
+ end
67
+ end
68
+
69
+ module RestCore::Facebook::Client
70
+ include RestCore
71
+
72
+ def access_token
73
+ data['access_token'] || data['oauth_token'] if data.kind_of?(Hash)
74
+ end
75
+
76
+ def access_token= token
77
+ data['access_token'] = token if data.kind_of?(Hash)
78
+ end
79
+
80
+ def secret_access_token; "#{app_id}|#{secret}" ; end
81
+ def accept ; headers['Accept'] ; end
82
+ def accept= val; headers['Accept'] = val; end
83
+ def lang ; headers['Accept-Language'] ; end
84
+ def lang= val; headers['Accept-Language'] = val; end
85
+
86
+ def authorized? ; !!access_token ; end
87
+
88
+ def next_page hash, opts={}, &cb
89
+ if hash['paging'].kind_of?(Hash) && hash['paging']['next']
90
+ get(hash['paging']['next'], {}, opts, &cb)
91
+ else
92
+ yield(nil) if block_given?
93
+ end
94
+ end
95
+
96
+ def prev_page hash, opts={}, &cb
97
+ if hash['paging'].kind_of?(Hash) && hash['paging']['previous']
98
+ get(hash['paging']['previous'], {}, opts, &cb)
99
+ else
100
+ yield(nil) if block_given?
101
+ end
102
+ end
103
+ alias_method :previous_page, :prev_page
104
+
105
+ def for_pages hash, pages=1, opts={}, kind=:next_page, &cb
106
+ if pages > 1
107
+ merge_data(send(kind, hash, opts){ |result|
108
+ yield(result.freeze) if block_given?
109
+ for_pages(result, pages - 1, opts, kind, &cb) if result
110
+ }, hash)
111
+ else
112
+ yield(nil) if block_given?
113
+ hash
114
+ end
115
+ end
116
+
117
+ # cookies, app_id, secrect related below
118
+
119
+ def parse_rack_env! env
120
+ env['HTTP_COOKIE'].to_s =~ /fbs_#{app_id}=([^\;]+)/
121
+ self.data = parse_fbs!($1)
122
+ end
123
+
124
+ def parse_cookies! cookies
125
+ self.data = if fbsr = cookies["fbsr_#{app_id}"]
126
+ parse_fbsr!(fbsr)
127
+ else fbs = cookies["fbs_#{app_id}"]
128
+ parse_fbs!(fbs)
129
+ end
130
+ end
131
+
132
+ def parse_fbs! fbs
133
+ self.data = check_sig_and_return_data(
134
+ # take out facebook sometimes there but sometimes not quotes in cookies
135
+ Vendor.parse_query(fbs.to_s.sub(/^"/, '').sub(/"$/, '')))
136
+ end
137
+
138
+ def parse_fbsr! fbsr
139
+ old_data = parse_signed_request!(fbsr)
140
+ # beware! maybe facebook would take out the code someday
141
+ return self.data = old_data unless old_data && old_data['code']
142
+ # passing empty redirect_uri is needed!
143
+ authorize!(:code => old_data['code'], :redirect_uri => '')
144
+ self.data = old_data.merge(data)
145
+ end
146
+
147
+ def parse_json! json
148
+ self.data = json &&
149
+ check_sig_and_return_data(JsonDecode.json_decode(json))
150
+ rescue JsonDecode::ParseError
151
+ self.data = nil
152
+ end
153
+
154
+ def fbs
155
+ "#{fbs_without_sig(data).join('&')}&sig=#{calculate_sig(data)}"
156
+ end
157
+
158
+ # facebook's new signed_request...
159
+
160
+ def parse_signed_request! request
161
+ sig_encoded, json_encoded = request.split('.')
162
+ return self.data = nil unless sig_encoded && json_encoded
163
+ sig, json = [sig_encoded, json_encoded].map{ |str|
164
+ "#{str.tr('-_', '+/')}==".unpack('m').first
165
+ }
166
+ self.data = check_sig_and_return_data(
167
+ JsonDecode.json_decode(json).merge('sig' => sig)){
168
+ Hmac.sha256(secret, json_encoded)
169
+ }
170
+ rescue JsonDecode::ParseError
171
+ self.data = nil
172
+ end
173
+
174
+ # oauth related
175
+
176
+ def authorize_url opts={}
177
+ url('oauth/authorize',
178
+ {:client_id => app_id, :access_token => nil}.merge(opts))
179
+ end
180
+
181
+ def authorize! opts={}
182
+ query = {:client_id => app_id, :client_secret => secret}.merge(opts)
183
+ self.data = Vendor.parse_query(
184
+ get(url('oauth/access_token'), query,
185
+ {:json_decode => false}.merge(opts)))
186
+ end
187
+
188
+ # old rest facebook api, i will definitely love to remove them someday
189
+
190
+ def old_rest path, query={}, opts={}, &cb
191
+ uri = url("method/#{path}", {:format => 'json'}.merge(query),
192
+ {:site => old_site}.merge(opts))
193
+ if opts[:post]
194
+ post(url("method/#{path}", {:format => 'json'},
195
+ {:site => old_site}.merge(opts)),
196
+ query,
197
+ {} ,
198
+ opts.merge('cache.key' => uri, 'cache.post' => true),
199
+ &cb)
200
+ else
201
+ get(uri, {}, opts, &cb)
202
+ end
203
+ end
204
+
205
+ def secret_old_rest path, query={}, opts={}, &cb
206
+ old_rest(path, query, {:secret => true}.merge(opts), &cb)
207
+ end
208
+
209
+ def fql code, query={}, opts={}, &cb
210
+ old_rest('fql.query', {:query => code}.merge(query), opts, &cb)
211
+ end
212
+
213
+ def fql_multi codes, query={}, opts={}, &cb
214
+ old_rest('fql.multiquery',
215
+ {:queries => JsonDecode.json_encode(codes)}.merge(query), opts, &cb)
216
+ end
217
+
218
+ def exchange_sessions query={}, opts={}, &cb
219
+ q = {:client_id => app_id, :client_secret => secret,
220
+ :type => 'client_cred'}.merge(query)
221
+ post(url('oauth/exchange_sessions', q),
222
+ {}, {}, opts, &cb)
223
+ end
224
+
225
+ protected
226
+ def build_env env={}
227
+ super(env.inject({}){ |r, (k, v)|
228
+ case k.to_s
229
+ when 'secret' ; r['access_token'] = secret_access_token
230
+ when 'cache' ; r['cache.update'] = !!!v
231
+ else ; r[k.to_s] = v
232
+ end
233
+ r
234
+ })
235
+ end
236
+
237
+ def check_sig_and_return_data cookies
238
+ cookies if secret && if block_given?
239
+ yield
240
+ else
241
+ calculate_sig(cookies)
242
+ end == cookies['sig']
243
+ end
244
+
245
+ def calculate_sig cookies
246
+ Digest::MD5.hexdigest(fbs_without_sig(cookies).join + secret)
247
+ end
248
+
249
+ def fbs_without_sig cookies
250
+ cookies.reject{ |(k, v)| k == 'sig' }.sort.map{ |a| a.join('=') }
251
+ end
252
+
253
+ def merge_data lhs, rhs
254
+ [lhs, rhs].each{ |hash|
255
+ return rhs.reject{ |k, v| k == 'paging' } if
256
+ !hash.kind_of?(Hash) || !hash['data'].kind_of?(Array)
257
+ }
258
+ lhs['data'].unshift(*rhs['data'])
259
+ lhs
260
+ end
261
+ end
262
+
263
+ RestCore::Facebook.send(:include, RestCore::Facebook::Client)
264
+ require 'rest-core/client/facebook/rails_util' if
265
+ Object.const_defined?(:Rails)
@@ -0,0 +1,334 @@
1
+
2
+ require 'rest-core/util/rails_util_util'
3
+
4
+ require 'cgi'
5
+ require 'uri'
6
+
7
+ module RestCore::Facebook::DefaultAttributes
8
+ def default_log_method ; Rails.logger.method(:debug); end
9
+ def default_cache ; Rails.cache ; end
10
+ def default_canvas ; '' ; end
11
+ def default_iframe ; false ; end
12
+ def default_auto_authorize ; false ; end
13
+ def default_auto_authorize_options; {} ; end
14
+ def default_auto_authorize_scope ; '' ; end
15
+ def default_ensure_authorized ; false ; end
16
+ def default_write_session ; false ; end
17
+ def default_write_cookies ; false ; end
18
+ def default_write_handler ; nil ; end
19
+ def default_check_handler ; nil ; end
20
+ end
21
+
22
+ module RestCore::Facebook::RailsUtil
23
+ def self.init app=Rails
24
+ RestCore::Config.load_for_rails(RestCore::Facebook, 'facebook', app)
25
+ end
26
+
27
+ module Helper
28
+ def rc_facebook
29
+ controller.send(:rc_facebook)
30
+ end
31
+ end
32
+
33
+ def self.included controller
34
+ # skip if included already, any better way to detect this?
35
+ return if controller.respond_to?(:rc_facebook, true)
36
+
37
+ controller.rescue_from(RestCore::Facebook::Error::AccessToken,
38
+ :with => :rc_facebook_on_access_token_error)
39
+ controller.helper(RestCore::Facebook::RailsUtil::Helper)
40
+ controller.instance_methods.select{ |method|
41
+ method.to_s =~ /^rc_facebook/
42
+ }.each{ |method| controller.send(:protected, method) }
43
+ end
44
+
45
+ def rc_facebook_setup options={}
46
+ rc_facebook_options_ctl.merge!(
47
+ RestCore::RailsUtilUtil.extract_options(
48
+ RestCore::Facebook.members, options, :reject))
49
+ rc_facebook_options_new.merge!(
50
+ RestCore::RailsUtilUtil.extract_options(
51
+ RestCore::Facebook.members, options, :select))
52
+
53
+ # we'll need to reinitialize rc_facebook with the new options,
54
+ # otherwise if you're calling rc_facebook before rc_facebook_setup,
55
+ # you'll end up with default options without the ones you've passed
56
+ # into rc_facebook_setup.
57
+ rc_facebook.send(:initialize, rc_facebook_options_new)
58
+
59
+ rc_facebook_check_params_signed_request # canvas
60
+ rc_facebook_check_params_session # i think it would be deprecated
61
+ rc_facebook_check_cookie # for js sdk (canvas or not)
62
+ rc_facebook_check_code # oauth api
63
+
64
+ # there are above 4 ways to check the user identity!
65
+ # if nor of them passed, then we can suppose the user
66
+ # didn't authorize for us, but we can check if user has authorized
67
+ # before, in that case, the fbs would be inside session,
68
+ # as we just saved it there
69
+
70
+ rc_facebook_check_rg_fbs # check rc_facebook storage
71
+
72
+ if rc_facebook_oget(:ensure_authorized) && !rc_facebook.authorized?
73
+ rc_facebook_authorize('ensure authorized')
74
+ false # action halt, redirect to do authorize,
75
+ # eagerly, as opposed to auto_authorize
76
+ else
77
+ true # keep going
78
+ end
79
+ end
80
+
81
+ # override this if you need different app_id and secret
82
+ def rc_facebook
83
+ @rc_facebook ||= RestCore::Facebook.new(rc_facebook_options_new)
84
+ end
85
+
86
+ def rc_facebook_on_access_token_error error=nil
87
+ rc_facebook_authorize(error, false)
88
+ end
89
+
90
+ def rc_facebook_authorize error=nil, force_redirect=true
91
+ logger.warn("WARN: Facebook: #{error.inspect}")
92
+
93
+ if force_redirect || rc_facebook_auto_authorize?
94
+ @rc_facebook_authorize_url = rc_facebook.authorize_url(
95
+ {:redirect_uri => rc_facebook_normalized_request_uri,
96
+ :scope => rc_facebook_oget(:auto_authorize_scope)}.
97
+ merge(rc_facebook_oget(:auto_authorize_options)))
98
+
99
+ logger.debug(
100
+ "DEBUG: Facebook: redirect to #{@rc_facebook_authorize_url}")
101
+
102
+ cookies.delete("fbs_#{rc_facebook.app_id}")
103
+ rc_facebook_authorize_redirect
104
+ end
105
+ end
106
+
107
+ # override this if you want the simple redirect_to
108
+ def rc_facebook_authorize_redirect
109
+ unless rc_facebook_in_canvas?
110
+ redirect_to @rc_facebook_authorize_url
111
+ else
112
+ rc_facebook_js_redirect(@rc_facebook_authorize_url,
113
+ rc_facebook_authorize_body)
114
+ end
115
+ end
116
+
117
+ def rc_facebook_js_redirect redirect_url, body=''
118
+ render :inline => <<-HTML
119
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
120
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
121
+ <html>
122
+ <head>
123
+ <script type="text/javascript">
124
+ window.top.location.href = '#{redirect_url}'
125
+ </script>
126
+ <noscript>
127
+ <meta http-equiv="refresh" content="0;url=#{
128
+ CGI.escapeHTML(redirect_url)}"/>
129
+ <meta http-equiv="window-target" content="_top"/>
130
+ </noscript>
131
+ </head>
132
+ <body>
133
+ #{body}
134
+ </bodt>
135
+ </html>
136
+ HTML
137
+ end
138
+
139
+ def rc_facebook_authorize_body redirect_url=@rc_facebook_authorize_url
140
+ <<-HTML
141
+ <div>
142
+ Please
143
+ <a href="#{CGI.escapeHTML(redirect_url)}" target="_top">authorize</a>
144
+ if this page is not automatically redirected.
145
+ </div>
146
+ HTML
147
+ end
148
+
149
+ module_function
150
+
151
+ # ==================== begin options utility =======================
152
+ def rc_facebook_oget key
153
+ if rc_facebook_options_ctl.has_key?(key)
154
+ rc_facebook_options_ctl[key]
155
+ else
156
+ RestCore::Facebook.send("default_#{key}")
157
+ end
158
+ end
159
+
160
+ def rc_facebook_options_ctl
161
+ @rc_facebook_options_ctl ||= {}
162
+ end
163
+
164
+ def rc_facebook_options_new
165
+ @rc_facebook_options_new ||= {}
166
+ end
167
+ # ==================== end options utility =======================
168
+
169
+
170
+
171
+ # ==================== begin facebook check ======================
172
+ def rc_facebook_check_params_signed_request
173
+ return if rc_facebook.authorized? || !params[:signed_request]
174
+
175
+ rc_facebook.parse_signed_request!(params[:signed_request])
176
+ logger.debug("DEBUG: Facebook: detected signed_request," \
177
+ " parsed: #{rc_facebook.data.inspect}")
178
+
179
+ if rc_facebook.authorized?
180
+ rc_facebook_write_rg_fbs
181
+ else
182
+ logger.warn(
183
+ "WARN: Facebook: bad signed_request: #{params[:signed_request]}")
184
+ end
185
+ end
186
+
187
+ # if the code is bad or not existed,
188
+ # check if there's one in session,
189
+ # meanwhile, there the sig and access_token is correct,
190
+ # that means we're in the context of canvas
191
+ def rc_facebook_check_params_session
192
+ return if rc_facebook.authorized? || !params[:session]
193
+
194
+ rc_facebook.parse_json!(params[:session])
195
+ logger.debug("DEBUG: Facebook: detected session, parsed:" \
196
+ " #{rc_facebook.data.inspect}")
197
+
198
+ if rc_facebook.authorized?
199
+ rc_facebook_write_rg_fbs
200
+ else
201
+ logger.warn("WARN: Facebook: bad session: #{params[:session]}")
202
+ end
203
+ end
204
+
205
+ # if we're not in canvas nor code passed,
206
+ # we could check out cookies as well.
207
+ def rc_facebook_check_cookie
208
+ return if rc_facebook.authorized? ||
209
+ (!cookies["fbsr_#{rc_facebook.app_id}"] &&
210
+ !cookies["fbs_#{rc_facebook.app_id}"])
211
+
212
+ rc_facebook.parse_cookies!(cookies)
213
+ logger.debug("DEBUG: Facebook: detected cookies, parsed:" \
214
+ " #{rc_facebook.data.inspect}")
215
+ end
216
+
217
+ # exchange the code with access_token
218
+ def rc_facebook_check_code
219
+ return if rc_facebook.authorized? || !params[:code]
220
+
221
+ rc_facebook.authorize!(
222
+ :code => params[:code],
223
+ :redirect_uri => rc_facebook_normalized_request_uri)
224
+
225
+ logger.debug(
226
+ "DEBUG: Facebook: detected code with " \
227
+ "#{rc_facebook_normalized_request_uri}," \
228
+ " parsed: #{rc_facebook.data.inspect}")
229
+
230
+ rc_facebook_write_rg_fbs if rc_facebook.authorized?
231
+ end
232
+ # ==================== end facebook check ======================
233
+
234
+
235
+
236
+ # ==================== begin check ================================
237
+ def rc_facebook_storage_key
238
+ "rc_facebook_fbs_#{rc_facebook_oget(:app_id)}"
239
+ end
240
+
241
+ def rc_facebook_check_rg_fbs
242
+ rc_facebook_check_rg_handler # custom method to store fbs
243
+ rc_facebook_check_rg_session # prefered way to store fbs
244
+ rc_facebook_check_rg_cookies # in canvas, session might not work..
245
+ end
246
+
247
+ def rc_facebook_check_rg_handler handler=rc_facebook_oget(:check_handler)
248
+ return if rc_facebook.authorized? || !handler
249
+ rc_facebook.parse_fbs!(handler.call)
250
+ logger.debug("DEBUG: Facebook: called check_handler, parsed:" \
251
+ " #{rc_facebook.data.inspect}")
252
+ end
253
+
254
+ def rc_facebook_check_rg_session
255
+ return if rc_facebook.authorized? || !rc_facebook_oget(:write_session) ||
256
+ !(fbs = session[rc_facebook_storage_key])
257
+ rc_facebook.parse_fbs!(fbs)
258
+ logger.debug("DEBUG: Facebook: detected rc_facebook session, parsed:" \
259
+ " #{rc_facebook.data.inspect}")
260
+ end
261
+
262
+ def rc_facebook_check_rg_cookies
263
+ return if rc_facebook.authorized? || !rc_facebook_oget(:write_cookies) ||
264
+ !(fbs = cookies[rc_facebook_storage_key])
265
+ rc_facebook.parse_fbs!(fbs)
266
+ logger.debug("DEBUG: Facebook: detected rc_facebook cookies, parsed:" \
267
+ " #{rc_facebook.data.inspect}")
268
+ end
269
+ # ==================== end check ================================
270
+ # ==================== begin write ================================
271
+ def rc_facebook_write_rg_fbs
272
+ cookies.delete("fbs_#{rc_facebook.app_id}")
273
+ rc_facebook_write_rg_handler
274
+ rc_facebook_write_rg_session
275
+ rc_facebook_write_rg_cookies
276
+ end
277
+
278
+ def rc_facebook_write_rg_handler handler=rc_facebook_oget(:write_handler)
279
+ return if !handler
280
+ handler.call(fbs = rc_facebook.fbs)
281
+ logger.debug("DEBUG: Facebook: called write_handler: fbs => #{fbs}")
282
+ end
283
+
284
+ def rc_facebook_write_rg_session
285
+ return if !rc_facebook_oget(:write_session)
286
+ session[rc_facebook_storage_key] = fbs = rc_facebook.fbs
287
+ logger.debug("DEBUG: Facebook: wrote session: fbs => #{fbs}")
288
+ end
289
+
290
+ def rc_facebook_write_rg_cookies
291
+ return if !rc_facebook_oget(:write_cookies)
292
+ cookies[rc_facebook_storage_key] = fbs = rc_facebook.fbs
293
+ logger.debug("DEBUG: Facebook: wrote cookies: fbs => #{fbs}")
294
+ end
295
+ # ==================== end write ================================
296
+
297
+
298
+
299
+ # ==================== begin misc ================================
300
+ def rc_facebook_normalized_request_uri
301
+ uri = if rc_facebook_in_canvas?
302
+ # rails 3 uses newer rack which has fullpath
303
+ "http://apps.facebook.com/#{rc_facebook_oget(:canvas)}" +
304
+ (request.respond_to?(:fullpath) ?
305
+ request.fullpath : request.request_uri)
306
+ else
307
+ request.url
308
+ end
309
+
310
+ rc_facebook_filter_uri(uri)
311
+ end
312
+
313
+ def rc_facebook_filter_uri uri
314
+ URI.parse(URI.encode(uri)).tap{ |uri|
315
+ uri.query = uri.query.split('&').reject{ |q|
316
+ q =~ /^(code|session|signed_request)\=/
317
+ }.join('&') if uri.query
318
+ uri.query = nil if uri.query.blank?
319
+ }.to_s
320
+ end
321
+
322
+ def rc_facebook_in_canvas?
323
+ !rc_facebook_oget(:canvas).blank?
324
+ end
325
+
326
+ def rc_facebook_auto_authorize?
327
+ !rc_facebook_oget(:auto_authorize_scope) .blank? ||
328
+ !rc_facebook_oget(:auto_authorize_options).blank? ||
329
+ rc_facebook_oget(:auto_authorize)
330
+ end
331
+ # ==================== end misc ================================
332
+ end
333
+
334
+ RestCore::Facebook::RailsUtil.init(Rails)