<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>app/views/admin/_publish_self_form.erb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/facebooker.gemspec</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/facebooker.gemspec.erb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook/facebook_generator.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook/templates/config/facebooker.yml</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook/templates/public/javascripts/facebooker.js</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_controller/USAGE</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_controller/facebook_controller_generator.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_controller/templates/controller.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_controller/templates/functional_test.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_controller/templates/helper.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_controller/templates/view.fbml.erb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_controller/templates/view.html.erb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_publisher/facebook_publisher_generator.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_publisher/templates/create_facebook_templates.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_publisher/templates/publisher.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/USAGE</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/facebook_scaffold_generator.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/templates/controller.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/templates/facebook_style.css</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/templates/functional_test.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/templates/helper.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/templates/layout.fbml.erb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/templates/layout.html.erb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/templates/style.css</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/templates/view_edit.fbml.erb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/templates/view_edit.html.erb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/templates/view_index.fbml.erb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/templates/view_index.html.erb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/templates/view_new.fbml.erb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/templates/view_new.html.erb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/templates/view_show.fbml.erb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/facebook_scaffold/templates/view_show.html.erb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/xd_receiver/templates/xd_receiver.html</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/generators/xd_receiver/xd_receiver_generator.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/lib/facebooker/adapters/adapter_base.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/lib/facebooker/logging.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/lib/facebooker/models/page.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/lib/facebooker/rails/facebook_url_helper.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/lib/facebooker/rails/helpers/fb_connect.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/rails/init.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/facebooker/test/logging_test.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -5,7 +5,7 @@
 # ENV['RAILS_ENV'] ||= 'production'
 
 # Specifies gem version of Rails to use when vendor/rails is not present
-RAILS_GEM_VERSION = '2.0.2' unless defined? RAILS_GEM_VERSION
+#RAILS_GEM_VERSION = '2.0.2' unless defined? RAILS_GEM_VERSION
 
 # Bootstrap the Rails environment, frameworks, and default configuration
 require File.join(File.dirname(__FILE__), 'boot')
@@ -60,29 +60,31 @@ end
 
 
 #MONKEY_PATCH_TAG
- module Facebooker
-   class Service   
-     def post_with_api_logging(params)  
-       unless(RAILS_ENV == &quot;production&quot;)
-         RAILS_DEFAULT_LOGGER.debug(&quot; Posting to #{url} #{params.inspect} &quot;)
-       end
-       return post_without_api_logging(params)     
-     end
-     alias_method_chain :post, :api_logging
-   end
-    
-   class Parser
-     class &lt;&lt;self
-       
-       def parse_with_logging(api_method,response)
-         unless(RAILS_ENV == &quot;production&quot;)
-           RAILS_DEFAULT_LOGGER.debug(&quot; Return value #{response.body}&quot;)
-         end
-         return parse_without_logging(api_method, response)     
-       end
-       alias_method_chain :parse, :logging
-     end
-   end
- end
+#
+#
+# module Facebooker
+#   class Service   
+#     def post_with_api_logging(params)  
+#       unless(RAILS_ENV == &quot;production&quot;)
+#         RAILS_DEFAULT_LOGGER.debug(&quot; Posting to #{url} #{params.inspect} &quot;)
+#       end
+#       return post_without_api_logging(params)     
+#     end
+#     alias_method_chain :post, :api_logging
+#   end
+#    
+#   class Parser
+#     class &lt;&lt;self
+#       
+#       def parse_with_logging(api_method,response)
+#         unless(RAILS_ENV == &quot;production&quot;)
+#           RAILS_DEFAULT_LOGGER.debug(&quot; Return value #{response.body}&quot;)
+#         end
+#         return parse_without_logging(api_method, response)     
+#       end
+#       alias_method_chain :parse, :logging
+#     end
+#   end
+# end
 #MONKEY_PATCH_TAG
                              
\ No newline at end of file</diff>
      <filename>config/environment.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,7 +12,6 @@ config.whiny_nils = true
 config.action_controller.consider_all_requests_local = true
 config.action_view.debug_rjs                         = true
 config.action_controller.perform_caching             = false
-config.action_view.cache_template_extensions         = false
 
 # Don't care if the mailer can't send
 config.action_mailer.raise_delivery_errors = false</diff>
      <filename>config/environments/development.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,7 +10,6 @@ config.cache_classes = true
 # Full error reports are disabled and caching is turned on
 config.action_controller.consider_all_requests_local = false
 config.action_controller.perform_caching             = true
-config.action_view.cache_template_loading            = true
 
 # Enable serving of images, stylesheets, and javascripts from an asset server
 # config.action_controller.asset_host                  = &quot;http://assets.example.com&quot;</diff>
      <filename>config/environments/production.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,11 +1,17 @@
-=== x.x.x / 2008-xx-xx
+=== x.x.x / 2009-xx-xx
 
+* Modified fql_query to return results as Hashes as a last resort [Alan Larkin]
 * fixed typo in set app properties parser [Andrew Grim, shane]
 * Removed actor_id param from templatized feed [shane]
 * Added admin.get_allocation [shane]
 * Added data.get_cookies and data.set_cookie [shane]
 * Added admin.get_app_properties and admin.set_app_properties [shane]
 
+=== 0.9.9 / 2008-09-08
+
+* Re-package as gem after reworking for new API
+
+
 === 0.9.5 / 2008-02-13
 
 * Next release of documentation</diff>
      <filename>vendor/plugins/facebooker/History.txt</filename>
    </modified>
    <modified>
      <diff>@@ -6,16 +6,50 @@ README
 README.txt
 Rakefile
 TODO.txt
-facebooker.yml.tpl
 generators/publisher/publisher_generator.rb
-generators/publisher/templates/publisher.rb
+generators/facebook/facebook_generator.rb
+generators/facebook/templates/config/facebooker.yml
+generators/facebook/templates/public/javascripts/facebooker.js
+generators/facebook_controller/USAGE
+generators/facebook_controller/facebook_controller_generator.rb
+generators/facebook_controller/templates/controller.rb
+generators/facebook_controller/templates/functional_test.rb
+generators/facebook_controller/templates/helper.rb
+generators/facebook_controller/templates/view.fbml.erb
+generators/facebook_controller/templates/view.html.erb
+generators/facebook_publisher/facebook_publisher_generator.rb
+generators/facebook_publisher/templates/create_facebook_templates.rb
+generators/facebook_publisher/templates/publisher.rb
+generators/facebook_scaffold/USAGE
+generators/facebook_scaffold/facebook_scaffold_generator.rb
+generators/facebook_scaffold/templates/controller.rb
+generators/facebook_scaffold/templates/facebook_style.css
+generators/facebook_scaffold/templates/functional_test.rb
+generators/facebook_scaffold/templates/helper.rb
+generators/facebook_scaffold/templates/layout.fbml.erb
+generators/facebook_scaffold/templates/layout.html.erb
+generators/facebook_scaffold/templates/style.css
+generators/facebook_scaffold/templates/view_edit.fbml.erb
+generators/facebook_scaffold/templates/view_edit.html.erb
+generators/facebook_scaffold/templates/view_index.fbml.erb
+generators/facebook_scaffold/templates/view_index.html.erb
+generators/facebook_scaffold/templates/view_new.fbml.erb
+generators/facebook_scaffold/templates/view_new.html.erb
+generators/facebook_scaffold/templates/view_show.fbml.erb
+generators/facebook_scaffold/templates/view_show.html.erb
+generators/xd_receiver/xd_receiver_generator.rb
+generators/xd_receiver/templates/xd_receiver.html
 init.rb
 install.rb
 lib/facebooker.rb
+lib/facebooker/adapters/adapter_base.rb
+lib/facebooker/adapters/bebo_adapter.rb
+lib/facebooker/adapters/facebook_adapter.rb
 lib/facebooker/admin.rb
 lib/facebooker/batch_request.rb
 lib/facebooker/data.rb
 lib/facebooker/feed.rb
+lib/facebooker/logging.rb
 lib/facebooker/model.rb
 lib/facebooker/models/affiliation.rb
 lib/facebooker/models/album.rb
@@ -23,9 +57,13 @@ lib/facebooker/models/applicationproperties.rb
 lib/facebooker/models/cookie.rb
 lib/facebooker/models/education_info.rb
 lib/facebooker/models/event.rb
+lib/facebooker/models/friend_list.rb
 lib/facebooker/models/group.rb
+lib/facebooker/models/info_item.rb
+lib/facebooker/models/info_section.rb
 lib/facebooker/models/location.rb
 lib/facebooker/models/notifications.rb
+lib/facebooker/models/page.rb
 lib/facebooker/models/photo.rb
 lib/facebooker/models/tag.rb
 lib/facebooker/models/user.rb
@@ -34,10 +72,14 @@ lib/facebooker/parser.rb
 lib/facebooker/rails/controller.rb
 lib/facebooker/rails/facebook_asset_path.rb
 lib/facebooker/rails/facebook_form_builder.rb
+lib/facebooker/rails/facebook_pretty_errors.rb
 lib/facebooker/rails/facebook_request_fix.rb
 lib/facebooker/rails/facebook_session_handling.rb
+lib/facebooker/rails/facebook_url_helper.rb
 lib/facebooker/rails/facebook_url_rewriting.rb
 lib/facebooker/rails/helpers.rb
+lib/facebooker/rails/helpers/fb_connect.rb
+lib/facebooker/rails/profile_publisher_extensions.rb
 lib/facebooker/rails/publisher.rb
 lib/facebooker/rails/routing.rb
 lib/facebooker/rails/test_helpers.rb
@@ -49,7 +91,10 @@ lib/facebooker/version.rb
 lib/net/http_multipart_post.rb
 lib/tasks/facebooker.rake
 lib/tasks/tunnel.rake
+rails/init.rb
 setup.rb
+templates/layout.erb
+test/adapters_test.rb
 test/batch_request_test.rb
 test/event_test.rb
 test/facebook_admin_test.rb
@@ -60,6 +105,7 @@ test/fixtures/multipart_post_body_with_only_parameters.txt
 test/fixtures/multipart_post_body_with_single_file.txt
 test/fixtures/multipart_post_body_with_single_file_that_has_nil_key.txt
 test/http_multipart_post_test.rb
+test/logging_test.rb
 test/model_test.rb
 test/publisher_test.rb
 test/rails_integration_test.rb</diff>
      <filename>vendor/plugins/facebooker/Manifest.txt</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@
 
 == DESCRIPTION:
 
-Facebooker is a Ruby wrapper over the Facebook[http://facebook.com] {REST API}[http://developer.facebook.com].  Its goals are:
+Facebooker is a Ruby wrapper over the Facebook[http://facebook.com] {REST API}[http://wiki.developers.facebook.com/index.php/API].  Its goals are:
 
 * Idiomatic Ruby
 * No dependencies outside of the Ruby standard library (This is true with Rails 2.1. Previous Rails versions require the JSON gem)
@@ -55,6 +55,22 @@ Your application users will need to have added the application in facebook to ac
 
 to your application controller.
 
+== using MemCache session
+
+Facebook uses some non alphanum characters in the session identifier which interfere with memcache stored sessions. If you want to use MemCache for storing sessions, you can override the valid session id method on memcache by placing the following code in an initializer:
+
+# add - as an okay key
+class CGI
+  class Session
+    class MemCacheStore
+      def check_id(id) #:nodoc:#
+        /[^0-9a-zA-Z\-\._]+/ =~ id.to_s ? false : true
+      end
+    end
+  end
+end
+
+
 == LICENSE:
 
 (The MIT License)</diff>
      <filename>vendor/plugins/facebooker/README.txt</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,7 @@ require './lib/facebooker.rb'
 
 Hoe.new('facebooker', Facebooker::VERSION::STRING) do |p|
   p.rubyforge_name = 'facebooker'
-  p.author = ['Chad Fowler', 'Patrick Ewing','Mike Mangino','Shane Vitarana']
+  p.author = ['Chad Fowler', 'Patrick Ewing', 'Mike Mangino', 'Shane Vitarana', 'Corey Innis']
   p.email = 'mmangino@elevatedrails.com'
   p.summary = 'Pure, idiomatic Ruby wrapper for the Facebook REST API.'
   p.description = p.paragraphs_of('README.txt', 2..5).join(&quot;\n\n&quot;)
@@ -34,6 +34,20 @@ namespace :test do
     t.verbose = true
   end
 end
+
+gem_spec_file = 'facebooker.gemspec'
+
+gem_spec = eval(File.read(gem_spec_file)) rescue nil
+
+desc &quot;Generate the gemspec file.&quot;
+task :gemspec do
+  require 'erb'
+
+  File.open(gem_spec_file, 'w') do |f|
+    f.write ERB.new(File.read(&quot;#{gem_spec_file}.erb&quot;)).result(binding)
+  end
+end
+
 # vim: syntax=Ruby
 # 
 # </diff>
      <filename>vendor/plugins/facebooker/Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,3 @@
-[ ] Remove facebook prefix from resource routes, making them worth with facebook and regular Rails controllers
-[ ] Use fb_sig_request_method to make facebook routes more Rails-like
 [ ] Refactor facebook form builder so erbout won't be deeply nested, causing erubis to break
 [ ] Support missing parameters on methods---most notably authentication-related parameters such as next and canvas
 [ ] Finish FQL Querying
@@ -8,3 +6,5 @@
 
 [x] Specify fields wanted when getting user info (defaults to all now) [shane]
 [x] Create facebooker.yml config file and merge with tunnel.yml [shane]
+[X] Remove facebook prefix from resource routes, making them worth with facebook and regular Rails controllers [mike]
+[X] Use fb_sig_request_method to make facebook routes more Rails-like [mike]</diff>
      <filename>vendor/plugins/facebooker/TODO.txt</filename>
    </modified>
    <modified>
      <diff>@@ -1,16 +1,14 @@
 class PublisherGenerator &lt; Rails::Generator::NamedBase
   def manifest
-    record do |m|
-      m.directory &quot;app/models&quot;
-      m.template &quot;publisher.rb&quot;, &quot;app/models/#{file_name}_publisher.rb&quot;
-      migration_file_name=&quot;create_facebook_templates&quot;
-      # unless  m.migration_exists?(migration_file_name)
-      # THis should work, but it doesn't. So we re-implement it instead
-      if Dir.glob(File.join(RAILS_ROOT,&quot;db&quot;,&quot;migrate&quot;,&quot;[0-9]*_*.rb&quot;)).grep(/[0-9]+_create_facebook_templates.rb$/).blank?
-        m.migration_template &quot;create_facebook_templates.rb&quot;, &quot;db/migrate&quot;, :migration_file_name=&gt;migration_file_name
-      end
-    end
+    puts banner
+    exit(1)
   end
   
+  def banner
+    &lt;&lt;-EOM
+    This generator has been renamed to facebook_publisher    
+    please run:  #{$0} facebook_publisher
+    EOM
+  end
   
 end
\ No newline at end of file</diff>
      <filename>vendor/plugins/facebooker/generators/publisher/publisher_generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,14 +2,11 @@
 # Config parsing needs to happen before files are required.
 facebook_config = &quot;#{RAILS_ROOT}/config/facebooker.yml&quot;
 
-if File.exist?(facebook_config)
-  FACEBOOKER = YAML.load_file(facebook_config)[RAILS_ENV] 
-  ENV['FACEBOOK_API_KEY'] = FACEBOOKER['api_key']
-  ENV['FACEBOOK_SECRET_KEY'] = FACEBOOKER['secret_key']
-  ENV['FACEBOOKER_RELATIVE_URL_ROOT'] = FACEBOOKER['canvas_page_name']
-  ENV['FACEBOOKER_API'] = FACEBOOKER['api']
-  ActionController::Base.asset_host = FACEBOOKER['callback_url'] if(ActionController::Base.asset_host.blank?)
-end
+require 'facebooker'
+FACEBOOKER = Facebooker.load_configuration(facebook_config)
+
+# enable logger before including everything else, in case we ever want to log initialization 
+Facebooker.logger = RAILS_DEFAULT_LOGGER if Object.const_defined? :RAILS_DEFAULT_LOGGER
 
 require 'net/http_multipart_post'
 require 'facebooker/rails/controller'
@@ -19,8 +16,7 @@ require 'facebooker/rails/facebook_asset_path'
 require 'facebooker/rails/facebook_request_fix'
 require 'facebooker/rails/routing'
 require 'facebooker/rails/facebook_pretty_errors' rescue nil
-require 'facebooker/adapters/facebook_adapter'
-require 'facebooker/adapters/bebo_adapter'
+require 'facebooker/rails/facebook_url_helper'
 module ::ActionController
   class Base
     def self.inherited_with_facebooker(subclass)
@@ -45,6 +41,22 @@ class ActionController::Routing::Route
   alias_method_chain :recognition_conditions, :facebooker
 end
 
+# When making get requests, Facebook sends fb_sig parameters both in the query string
+# and also in the post body. We want to ignore the query string ones because they are one
+# request out of date
+# We only do thise when there are POST parameters so that IFrame linkage still works
+class ActionController::AbstractRequest
+  def query_parameters_with_facebooker
+    if request_parameters.blank?
+      query_parameters_without_facebooker
+    else
+      (query_parameters_without_facebooker||{}).reject {|key,value| key.to_s =~ /^fb_sig/}
+    end
+  end
+  
+  alias_method_chain :query_parameters, :facebooker
+end
+
 # We turn off route optimization to make named routes use our code for figuring out if they should go to the session
 # If this fails, it means we're on rails 1.2, we can ignore it
 begin</diff>
      <filename>vendor/plugins/facebooker/init.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,12 @@
 require 'fileutils'
 require 'rubygems'
-facebook_config = File.join(RAILS_ROOT,&quot;config&quot;,&quot;facebooker.yml&quot;)
-facebook_js = File.join(RAILS_ROOT,&quot;public&quot;,&quot;javascripts&quot;,'facebooker.js')
-FileUtils.cp File.join(File.dirname(__FILE__) , 'facebooker.yml.tpl'), facebook_config unless File.exist?(facebook_config)
-FileUtils.cp File.join(File.dirname(__FILE__) , 'javascripts','facebooker.js'), facebook_js unless File.exist?(facebook_js)
-puts IO.read(File.join(File.dirname(__FILE__), 'README'))
+
+dir = File.dirname(__FILE__)
+templates = File.join(dir, 'generators', 'facebook', 'templates')
+config = File.join('config', 'facebooker.yml')
+script = File.join('public', 'javascripts', 'facebooker.js')
+
+[config, script].each do |path| 
+  FileUtils.cp File.join(templates, path), File.join(RAILS_ROOT, path) unless File.exist?(File.join(RAILS_ROOT, path))
+end
+puts IO.read(File.join(dir, 'README'))</diff>
      <filename>vendor/plugins/facebooker/install.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,41 +1,56 @@
 begin
-  unless ActiveSupport.const_defined?(&quot;JSON&quot;)
+  unless Object.const_defined?(&quot;ActiveSupport&quot;) and ActiveSupport.const_defined?(&quot;JSON&quot;)
     require 'json' 
+    module Facebooker
+      def self.json_decode(str)
+        JSON.parse(str)
+      end
+    end
+  else
+    module Facebooker
+      def self.json_decode(str)
+        ActiveSupport::JSON.decode(str)
+      end
+    end
   end 
 rescue
   require 'json' 
 end
-require 'facebooker/batch_request'
-require 'facebooker/feed'
-require 'facebooker/model'
-require 'facebooker/parser'
-require 'facebooker/service'
-require 'facebooker/server_cache'
-require 'facebooker/data'
-require 'facebooker/admin'
-require 'facebooker/session'
-require 'facebooker/version'
-require 'facebooker/models/location'
-require 'facebooker/models/affiliation'
-require 'facebooker/models/album'
-require 'facebooker/models/education_info'
-require 'facebooker/models/work_info'
-require 'facebooker/models/event'
-require 'facebooker/models/group'
-require 'facebooker/models/notifications'
-require 'facebooker/models/photo'
-require 'facebooker/models/cookie'
-require 'facebooker/models/applicationproperties'
-require 'facebooker/models/tag'
-require 'facebooker/models/user'
-require 'facebooker/models/info_item'
-require 'facebooker/models/info_section'
-require 'facebooker/adapters/facebook_adapter'
-require 'facebooker/adapters/bebo_adapter'
-require 'facebooker/models/friend_list'
+require 'zlib'
+require 'digest/md5'
+
+
 
 module Facebooker
-  class &lt;&lt; self
+      
+    class &lt;&lt; self
+    
+    def load_configuration(facebooker_yaml_file)
+      if File.exist?(facebooker_yaml_file)
+        if defined? RAILS_ENV
+          facebooker = YAML.load_file(facebooker_yaml_file)[RAILS_ENV] 
+        else
+          facebooker = YAML.load_file(facebooker_yaml_file)           
+        end
+        ENV['FACEBOOK_API_KEY'] = facebooker['api_key']
+        ENV['FACEBOOK_SECRET_KEY'] = facebooker['secret_key']
+        ENV['FACEBOOKER_RELATIVE_URL_ROOT'] = facebooker['canvas_page_name']
+        ENV['FACEBOOKER_API'] = facebooker['api']
+        if facebooker.has_key?('set_asset_host_to_callback_url')
+          Facebooker.set_asset_host_to_callback_url = facebooker['set_asset_host_to_callback_url'] 
+        end
+        Facebooker.timeout = facebooker['timeout']
+        if Object.const_defined?(&quot;ActionController&quot;)
+          ActionController::Base.asset_host = facebooker['callback_url'] if(ActionController::Base.asset_host.blank?)  &amp;&amp; Facebooker.set_asset_host_to_callback_url
+        end
+        @facebooker_configuration = facebooker
+      end
+    end
+    
+    def facebooker_config
+      @facebooker_configuration 
+    end
+    
      def current_adapter=(adapter_class)
       @current_adapter = adapter_class
     end
@@ -61,7 +76,29 @@ module Facebooker
       current_adapter.is_for?(application_container)
     end
     
-   
+    def set_asset_host_to_callback_url=(val)
+      @set_asset_host_to_callback_url=val
+    end
+    
+    def set_asset_host_to_callback_url
+      @set_asset_host_to_callback_url.nil? ? true : @set_asset_host_to_callback_url
+    end
+    
+    def use_curl=(val)
+      @use_curl=val
+    end
+    
+    def use_curl?
+      @use_curl
+    end
+    
+    def timeout=(val)
+      @timeout = val.to_i
+    end
+    
+    def timeout
+      @timeout
+    end
    
     [:api_key,:secret_key, :www_server_base_url,:login_url_base,:install_url_base,:api_rest_path,:api_server_base,:api_server_base_url,:canvas_server_base].each do |delegated_method|
       define_method(delegated_method){ return current_adapter.send(delegated_method)}
@@ -100,3 +137,35 @@ module Facebooker
     end
   end
 end
+
+require 'facebooker/batch_request'
+require 'facebooker/feed'
+require 'facebooker/logging'
+require 'facebooker/model'
+require 'facebooker/parser'
+require 'facebooker/service'
+require 'facebooker/server_cache'
+require 'facebooker/data'
+require 'facebooker/admin'
+require 'facebooker/session'
+require 'facebooker/version'
+require 'facebooker/models/location'
+require 'facebooker/models/affiliation'
+require 'facebooker/models/album'
+require 'facebooker/models/education_info'
+require 'facebooker/models/work_info'
+require 'facebooker/models/event'
+require 'facebooker/models/group'
+require 'facebooker/models/notifications'
+require 'facebooker/models/page'
+require 'facebooker/models/photo'
+require 'facebooker/models/cookie'
+require 'facebooker/models/applicationproperties'
+require 'facebooker/models/tag'
+require 'facebooker/models/user'
+require 'facebooker/models/info_item'
+require 'facebooker/models/info_section'
+require 'facebooker/adapters/adapter_base'
+require 'facebooker/adapters/facebook_adapter'
+require 'facebooker/adapters/bebo_adapter'
+require 'facebooker/models/friend_list'</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker.rb</filename>
    </modified>
    <modified>
      <diff>@@ -43,7 +43,8 @@ module Facebooker
         set_profile_fbml_without_bebo_adapter(profile_fbml,mobile_fbml, profile_action_fbml, profile_main)
       end
     end
-    alias_method_chain :set_profile_fbml, :bebo_adapter
+    alias_method :set_profile_fbml_without_bebo_adapter, :set_profile_fbml
+    alias_method :set_profile_fbml, :set_profile_fbml_with_bebo_adapter
     
     private
     
@@ -67,7 +68,8 @@ module Facebooker
          process_without_bebo_adapter(data)
        end
       end
-      alias_method_chain :process, :bebo_adapter
+      alias_method :process_without_bebo_adapter, :process
+      alias_method :process, :process_with_bebo_adapter
     end
   end
-end
\ No newline at end of file
+end</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/adapters/bebo_adapter.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,106 +1,18 @@
 module Facebooker
   
-  class AdapterBase
-    class UnableToLoadAdapter &lt; Exception; end
-    require 'active_support'
-    include  ActiveSupport::CoreExtensions::String::Inflections
-    def facebook_path_prefix
-      &quot;/&quot; + (@facebook_path_prefix || canvas_page_name || ENV['FACEBOOK_CANVAS_PATH'] || ENV['FACEBOOKER_RELATIVE_URL_ROOT'])
-    end
-          
-    def facebook_path_prefix=(prefix)
-      @facebook_path_prefix = prefix
-    end
-      
-    def  facebooker_config
-      @config
-    end
-      
-    def api_server_base_url
-      &quot;http://&quot; + api_server_base
-    end
-      
-    def is_for?(application_context)
-      raise &quot;SubClassShouldDefine&quot;
-    end
-       
-    def initialize(config)
-      @config = config
-    end
-       
-    # TODO: Get someone to look into this for desktop apps.  
-    def  self.facebooker_config
-      return @facebooker_config if @facebooker_config
-      facebook_config_file = &quot;#{RAILS_ROOT}/config/facebooker.yml&quot;
-      if File.exist?(facebook_config_file)
-        @facebooker_config = YAML.load_file(facebook_config_file)[RAILS_ENV]     
-      end
-    end
- 
-    def self.new_api?
-      (@facebooker_config &amp;&amp; @facebooker_config[&quot;use_new_api&quot;]) || (ENV[&quot;FACEBOOKER_API&quot;] == &quot;new&quot;) 
-    end 
-     
-    def self.load_adapter(params)
-      
-      config_key_base = params[:config_key_base] # This allows for loading of a aspecific adapter
-      config_key_base += &quot;_&quot; unless config_key_base.blank?
-      new_facebook = ( new_api? || (params[&quot;fb_sig_in_new_facebook&quot;] == &quot;1&quot;))
-      if(  ( api_key = ( params[:fb_sig_api_key] || facebooker_config[&quot;#{config_key_base}api_key&quot;])))
-      
-        if(  facebooker_config)
-          facebooker_config.each do |key,value|
-            if(value == api_key)
-              key_base = key.match(/(.*)[_]?api_key/)[1]
-              adapter_class_name = key_base.blank? ? ( new_facebook ? &quot;FacebookNewAdapter&quot; : &quot;FacebookAdapter&quot;) : facebooker_config[key_base + &quot;adapter&quot;]
-              adpater_class = &quot;Facebooker::#{adapter_class_name}&quot;.constantize
-              # Collect the rest of the configuration
-              adapter_config = {}
-              facebooker_config.each do |key,value|
-                next unless( match = key.match(/#{key_base}[_]?(.*)/))
-                adapter_config[match[1]] = value
-              end
-              return adpater_class.new(adapter_config)
-            end     
-          end
-        else
-          self.default_adapter(params)
-        end
-      else
-        raise Facebooker::AdapterBase::UnableToLoadAdapter
-      end
-    end
-     
-    def self.default_adapter(params = {})
-      new_facebook = ( new_api? || (params[&quot;fb_sig_in_new_facebook&quot;] == &quot;1&quot;))
-      if( facebooker_config.nil? || (facebooker_config.blank? rescue nil) )
-        config = { &quot;api_key&quot; =&gt; ENV['FACEBOOK_API_KEY'], &quot;secret_key&quot; =&gt;  ENV['FACEBOOK_SECRET_KEY']}
-      else
-        config = facebooker_config
-      end
-     (new_facebook ? FacebookNewAdapter : FacebookAdapter).new(config)
-    end
-     
-    [:canvas_page_name, :api_key,:secret_key].each do |key_method|
-      define_method(key_method){ return facebooker_config[key_method.to_s]}
-    end
-         
-  end
-  
-  
    
   class FacebookAdapter &lt; AdapterBase
       
     def canvas_server_base
-      FacebookAdapter.new_api? ? &quot;apps.new.facebook.com&quot; : &quot;apps.facebook.com&quot;
+      &quot;apps.facebook.com&quot;
     end
       
     def api_server_base
-       FacebookAdapter.new_api? ? &quot;api.new.facebook.com&quot; : &quot;api.facebook.com&quot;
+       &quot;api.facebook.com&quot;
     end
     
-      def www_server_base_url
-      FacebookAdapter.new_api? ? &quot;www.new.facebook.com&quot; : &quot;www.facebook.com&quot;
+    def www_server_base_url
+      &quot;www.facebook.com&quot;
     end
     
     def api_rest_path
@@ -131,19 +43,6 @@ module Facebooker
     
   end
   
-  class FacebookNewAdapter &lt; FacebookAdapter
-      def canvas_server_base
-      &quot;apps.new.facebook.com&quot; 
-    end
-      
-    def api_server_base
-       &quot;api.new.facebook.com&quot;
-    end
-    
-      def www_server_base_url
-     &quot;www.new.facebook.com&quot; 
-    end
-  end
 end
 
 </diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/adapters/facebook_adapter.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,7 +7,7 @@ module Facebooker
     # ** BETA ***
     # +properties+: Hash of properties you want to set
     def set_app_properties(properties)
-      properties.respond_to?(:to_json) ? properties.to_json : properties
+      properties = properties.respond_to?(:to_json) ? properties.to_json : properties
       (@session.post 'facebook.admin.setAppProperties', :properties =&gt; properties) == '1'
     end
     
@@ -25,4 +25,4 @@ module Facebooker
       @session.post('facebook.admin.getAllocation', :integration_point_name =&gt; integration_point.to_s).to_i
     end    
   end
-end
\ No newline at end of file
+end</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/admin.rb</filename>
    </modified>
    <modified>
      <diff>@@ -35,6 +35,23 @@ module Facebooker
             Cookie.from_hash(hash)
           end
       end
-    end    
+    end   
+    
+    ##
+    # ** BETA ***
+    # Gets a preference stored on Facebook
+    # +pref_id+	The id of the preference to get
+    def get_preference(pref_id)
+      @session.post('facebook.data.getUserPreference', :pref_id=&gt;pref_id)
+    end
+
+    ##
+    # ** BETA ***
+    # Sets a preference on Facebook
+    # +pref_id+	The id of the preference to set
+    # +value+ The value to set for this preference
+    def set_preference(pref_id, value)
+      @session.post('facebook.data.setUserPreference', :pref_id=&gt;pref_id, :value=&gt;value)
+    end
   end
 end
\ No newline at end of file</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/data.rb</filename>
    </modified>
    <modified>
      <diff>@@ -77,6 +77,18 @@ module Facebooker
           end)
         end
       end      
+
+      def id_is(attribute)
+        class_eval &lt;&lt;-EOS
+        def #{attribute}=(value)
+          @#{attribute} = value.to_i
+        end
+
+        attr_reader #{attribute.inspect}
+        alias :id #{attribute.inspect}
+        alias :id= #{&quot;#{attribute}=&quot;.to_sym.inspect}
+        EOS
+      end
     end
     
     ##
@@ -109,7 +121,12 @@ module Facebooker
     def populate_from_hash!(hash)
       unless hash.empty?
         hash.each do |key, value|
-          self.__send__(&quot;#{key}=&quot;, value)
+          set_attr_method = &quot;#{key}=&quot;
+          if respond_to?(set_attr_method)
+            self.__send__(set_attr_method, value) 
+          else
+            Facebooker::Logging.log_info(&quot;**Warning**, Attempt to set non-attribute: #{key}&quot;,hash)
+          end
         end
         @populated = true
       end      </diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/model.rb</filename>
    </modified>
    <modified>
      <diff>@@ -31,9 +31,9 @@ module Facebooker
                :uninstall_url, :ip_list, :email, :description, :use_iframe, :desktop, :is_mobile,
                :default_fbml, :default_column, :message_url, :message_action, :about_url,
                :private_install, :installable, :privacy_url, :help_url, :see_all_url, :tos_url,
-               :dev_mode, :preload_fql ]
+               :dev_mode, :preload_fql, :icon_url, :canvas_name, :logo_url, :connect_logo_url ]
     
     attr_accessor *FIELDS
          
   end
-end
\ No newline at end of file
+end</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/models/applicationproperties.rb</filename>
    </modified>
    <modified>
      <diff>@@ -22,5 +22,7 @@ module Facebooker
     
     include Model
     attr_accessor :eid, :pic, :pic_small, :pic_big, :name, :creator, :update_time, :description, :tagline, :venue, :host, :event_type, :nid, :location, :end_time, :start_time, :event_subtype
+
+    id_is :eid
   end
 end
\ No newline at end of file</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/models/event.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,14 +1,16 @@
 require 'facebooker/model'
 module Facebooker
   ##
-  # A simple representation of a photo album.
+  # A simple representation of a friend list.
   class FriendList
     include Model
     attr_accessor :flid, :name
     
+    id_is :flid
+
     # We need this to be an integer, so do the conversion
     def flid=(f)
       @flid= ( f.nil? ? nil : f.to_i)
     end
   end
-end
\ No newline at end of file
+end</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/models/friend_list.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,6 +10,7 @@ module Facebooker
     include Model
     attr_accessor :pic, :pic_small, :pic_big, :name, :creator, :recent_news, :gid, :update_time, :group_subtype, :group_type, :website, :office, :description, :venue, :nid
     
+    id_is :gid
     
     ##
     # Get the full list of members as populated User objects.  First time fetches group members via Facebook API call.  </diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/models/group.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,6 +4,9 @@ module Facebooker
     include Model
     attr_accessor :pid, :aid, :owner, :title,
                   :link, :caption, :created,
-                  :src, :src_big, :src_small
+                  :src, :src_big, :src_small,
+                  :story_fbid
+
+    id_is :pid
   end
 end
\ No newline at end of file</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/models/photo.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,6 @@
 require 'facebooker/model'
 require 'facebooker/models/affiliation'
 require 'facebooker/models/work_info'
-
 module Facebooker
   # 
   # Holds attributes and behavior for a Facebook User
@@ -9,10 +8,10 @@ module Facebooker
     include Model
     class Status
       include Model
-      attr_accessor :message, :time
+      attr_accessor :message, :time, :status_id
     end
-    FIELDS = [:status, :political, :pic_small, :name, :quotes, :is_app_user, :tv, :profile_update_time, :meeting_sex, :hs_info, :timezone, :relationship_status, :hometown_location, :about_me, :wall_count, :significant_other_id, :pic_big, :music, :uid, :work_history, :sex, :religion, :notes_count, :activities, :pic_square, :movies, :has_added_app, :education_history, :birthday, :first_name, :meeting_for, :last_name, :interests, :current_location, :pic, :books, :affiliations]
-    attr_accessor :id, :session
+    FIELDS = [:status, :political, :pic_small, :name, :quotes, :is_app_user, :tv, :profile_update_time, :meeting_sex, :hs_info, :timezone, :relationship_status, :hometown_location, :about_me, :wall_count, :significant_other_id, :pic_big, :music, :uid, :work_history, :sex, :religion, :notes_count, :activities, :pic_square, :movies, :has_added_app, :education_history, :birthday, :first_name, :meeting_for, :last_name, :interests, :current_location, :pic, :books, :affiliations, :locale, :profile_url, :proxied_email,:email_hashes]
+    STANDARD_FIELDS = [:uid, :first_name, :last_name, :name, :timezone, :birthday, :sex, :affiliations, :locale, :profile_url]
     populating_attr_accessor *FIELDS
     attr_reader :affiliations
     populating_hash_settable_accessor :current_location, Location
@@ -28,27 +27,35 @@ module Facebooker
     # attribute_hash
     def initialize(*args)
       if (args.first.kind_of?(String) || args.first.kind_of?(Integer)) &amp;&amp; args.size==1
-        @id=Integer(args.shift)
+        self.uid = args.shift
         @session = Session.current
       elsif (args.first.kind_of?(String) || args.first.kind_of?(Integer)) &amp;&amp; args[1].kind_of?(Session)
-        @id = Integer(args.shift)
+        self.uid = args.shift
         @session = args.shift
       end
       if args.last.kind_of?(Hash)
         populate_from_hash!(args.pop)
-      end      
+      end     
     end
 
+    id_is :uid
+    alias :facebook_id :id
+
     # Returns a user's events, params correspond to API call parameters (except UID):
     # http://wiki.developers.facebook.com/index.php/Events.get
     # E.g:
-    #  @user.events(:start_time =&gt; Time.now.to_i, :end_time =&gt; 1.month.from_now.to_i)
+    #  @user.events(:start_time =&gt; Time.now, :end_time =&gt; 1.month.from_now)
     #  # =&gt; Returns events betwen now and a month from now
     def events(params={})
-      @events ||= @session.post('facebook.events.get', {:uid =&gt; self.id}.merge(params)).map do |event|
+      @events ||= {}
+      [:start_time,:end_time].compact.each do |key|
+        params[key] = params[key].to_i
+      end
+#      puts @events[params.to_s].nil?
+      @events[params.to_s] ||= @session.post('facebook.events.get', {:uid =&gt; self.id}.merge(params)).map do |event|
         Event.from_hash(event)
       end
-    end
+    end    
     
     # 
     # Set the list of friends, given an array of User objects.  If the list has been retrieved previously, will not set
@@ -81,7 +88,9 @@ module Facebooker
       
      	#use __blank instead of nil so that this is cached
      	cache_key = flid||&quot;__blank&quot;
-     	@friends_hash[cache_key] ||= @session.post('facebook.friends.get', (flid.nil? ? {} : {:flid =&gt; flid})).map do |uid|
+     	options = {:uid=&gt;self.id}
+     	options[:flid] = flid unless flid.nil?
+     	@friends_hash[cache_key] ||= @session.post('facebook.friends.get', options,false).map do |uid|
           User.new(uid, @session)
       end
       @friends_hash[cache_key]
@@ -164,12 +173,39 @@ module Facebooker
       session.get_photos(nil, nil, profile_pic_album_id)
     end
     
-    def upload_photo(multipart_post_file)
-      Photo.from_hash(session.post_file('facebook.photos.upload', {nil =&gt; multipart_post_file}))
+    # Upload a photo to the user's profile.
+    #
+    # In your view, create a multipart form that posts directly to your application (not through canvas):
+    #
+    #   &lt;% form_tag photos_url(:canvas =&gt; false), :html =&gt; {:multipart =&gt; true, :promptpermission =&gt; 'photo_upload'} do %&gt;
+    #     Photo: &lt;%= file_field_tag 'photo' %&gt;
+    #     Caption: &lt;%= text_area_tag 'caption' %&gt;
+    #     &lt;%= submit_tag 'Upload Photo', :class =&gt; 'inputsubmit' %&gt;
+    #   &lt;% end %&gt;
+    # 
+    # And in your controller: 
+    #
+    #   class PhotosController &lt; ApplicationController
+    #     def create
+    #       file = Net::HTTP::MultipartPostFile.new(
+    #         params[:photo].original_filename,
+    #         params[:photo].content_type,
+    #         params[:photo].read
+    #       )
+    #     
+    #       @photo = facebook_session.user.upload_photo(file, :caption =&gt; params[:caption])
+    #       redirect_to photos_url(:canvas =&gt; true)
+    #     end
+    #   end
+    #
+    # Options correspond to http://wiki.developers.facebook.com/index.php/Photos.upload
+    def upload_photo(multipart_post_file, options = {})
+      Photo.from_hash(session.post_file('facebook.photos.upload',
+        options.merge(nil =&gt; multipart_post_file)))
     end
     
     def profile_fbml
-      session.post('facebook.profile.getFBML', :uid =&gt; @id)  
+      session.post('facebook.profile.getFBML', :uid =&gt; id)  
     end    
     
     ##
@@ -195,12 +231,12 @@ module Facebooker
     end
     
     def set_profile_fbml(profile_fbml, mobile_fbml, profile_action_fbml, profile_main = nil)
-      parameters = {:uid =&gt; @id}
+      parameters = {:uid =&gt; id}
       parameters[:profile] = profile_fbml if profile_fbml
       parameters[:profile_action] = profile_action_fbml if profile_action_fbml
       parameters[:mobile_profile] = mobile_fbml if mobile_fbml
       parameters[:profile_main] = profile_main if profile_main
-      session.post('facebook.profile.setFBML', parameters)
+      session.post('facebook.profile.setFBML', parameters,false)
     end
     
     ## ** NEW PROFILE DESIGN ***
@@ -209,27 +245,20 @@ module Facebooker
     # Note: using set_profile_info as I feel using user.set_info could be confused with the user.getInfo facebook method.
     #       Also, I feel it fits in line with user.set_profile_fbml.
     def set_profile_info(title, info_fields, format = :text)
-      session.post('facebook.profile.setInfo', :title =&gt; title, :uid =&gt; @id, 
+      session.post('facebook.profile.setInfo', :title =&gt; title, :uid =&gt; id, 
         :type =&gt; format.to_s == &quot;text&quot; ? 1 : 5, :info_fields =&gt; info_fields.to_json)
     end
     
     def get_profile_info
-      session.post('facebook.profile.getInfo', :uid =&gt; @id)
+      session.post('facebook.profile.getInfo', :uid =&gt; id)
     end
     
     ##
-    # Set the status of the user
-    #
-    # DOES NOT prepend &quot;is&quot; to the message
-    #
-    # requires extended permission. 
+    # This DOES NOT set the status of a user on Facebook
+    # Use the set_status method instead
     def status=(message)
       case message
-      when String
-        session.post('facebook.users.setStatus',:status=&gt;message,:status_includes_verb=&gt;1) do |ret|
-          ret
-        end
-      when Status
+      when String,Status
         @status = message
       when Hash
         @status = Status.from_hash(message)
@@ -237,21 +266,39 @@ module Facebooker
     end
     
     ##
+    # Set the status for a user
+    # DOES NOT prepend &quot;is&quot; to the message
+    #
+    # requires extended permission. 
+    def set_status(message)
+      self.status=message
+      session.post('facebook.users.setStatus',:status=&gt;message,:status_includes_verb=&gt;1) do |ret|
+        ret
+      end
+    end
+    
+    ##
+    # Checks to see if the user has enabled the given extended permission
+    def has_permission?(ext_perm) # ext_perm = email, offline_access, status_update, photo_upload, create_listing, create_event, rsvp_event, sms
+      session.post('facebook.users.hasAppPermission',:ext_perm=&gt;ext_perm) == &quot;1&quot;
+    end    
+    
+    ##
     # Convenience method to send email to the current user
     def send_email(subject, text=nil, fbml=nil)
-      session.send_email([@id], subject, text, fbml)
+      session.send_email([id], subject, text, fbml)
     end
     
     ##
     # Convenience method to set cookie for the current user
     def set_cookie(name, value, expires=nil, path=nil)
-      session.data.set_cookie(@id, name, value, expires, path)
+      session.data.set_cookie(id, name, value, expires, path)
     end
     
     ##
     # Convenience method to get cookies for the current user
     def get_cookies(name=nil)
-      session.data.get_cookies(@id, name)
+      session.data.get_cookies(id, name)
     end
     
     ##
@@ -271,6 +318,41 @@ module Facebooker
     end
     
     
+    # register a user with Facebook
+    # users should be a hast with at least an :email field
+    # you can optionally provide an :account_id field as well
+        
+    def self.register(users)
+      user_map={}
+      users=users.map do |h|
+        returning h.dup do |d|
+          if email=d.delete(:email)
+            hash = hash_email(email)
+            user_map[hash]=h
+            d[:email_hash]=hash
+          end
+        end
+      end
+      Facebooker::Session.create.post(&quot;facebook.connect.registerUsers&quot;,:accounts=&gt;users.to_json) do |ret|
+        ret.each do |hash|
+          user_map.delete(hash)
+        end
+        unless user_map.empty?
+          e=Facebooker::Session::UserRegistrationFailed.new
+          e.failed_users = user_map.values
+          raise e
+        end
+        ret
+      end
+    end
+    
+    def self.hash_email(email)
+      email = email.downcase.strip
+      crc=Zlib.crc32(email)
+      md5=Digest::MD5.hexdigest(email)
+      &quot;#{crc}_#{md5}&quot;
+    end
+    
     def self.cast_to_facebook_id(object)
       if object.respond_to?(:facebook_id)
         object.facebook_id
@@ -279,17 +361,29 @@ module Facebooker
       end
     end
     
+    def self.user_fields(fields = [])
+      valid_fields(fields)
+    end
+    
+    def self.standard_fields(fields = [])
+      valid_fields(fields,STANDARD_FIELDS)
+    end
+    
     private
     def publish(feed_story_or_action)
       session.post(Facebooker::Feed::METHODS[feed_story_or_action.class.name.split(/::/).last], feed_story_or_action.to_params) == &quot;1&quot; ? true : false
     end
     
-    def collect(fields)
-      FIELDS.reject{|field_name| !fields.empty? &amp;&amp; !fields.include?(field_name)}.join(',')
+    def self.valid_fields(fields, allowable=FIELDS)
+      allowable.reject{|field_name| !fields.empty? &amp;&amp; !fields.include?(field_name)}.join(',')
+    end
+    
+    def collect(fields, allowable=FIELDS)
+      allowable.reject{|field_name| !fields.empty? &amp;&amp; !fields.include?(field_name)}.join(',')
     end
     
     def profile_pic_album_id
-      merge_aid(-3, @id)
+      merge_aid(-3, id)
     end
     
     def merge_aid(aid, uid)</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/models/user.rb</filename>
    </modified>
    <modified>
      <diff>@@ -58,22 +58,23 @@ module Facebooker
     
     def self.hashinate(response_element)
       response_element.children.reject{|c| c.kind_of? REXML::Text}.inject({}) do |hash, child|
-        hash[child.name] = if child.children.size == 1 &amp;&amp; child.children.first.kind_of?(REXML::Text)
+        # If the node hasn't any child, and is not a list, we want empty strings, not empty hashes,
+        #   except if attributes['nil'] == true
+        hash[child.name] = 
+        if (child.attributes['nil'] == 'true')
+          nil 
+        elsif (child.children.size == 1 &amp;&amp; child.children.first.kind_of?(REXML::Text)) || (child.children.size == 0 &amp;&amp; child.attributes['list'] != 'true')
           anonymous_field_from(child, hash) || child.text_value
+        elsif child.attributes['list'] == 'true'
+          child.children.reject{|c| c.kind_of? REXML::Text}.map { |subchild| hash_or_value_for(subchild)}    
         else
-          if child.attributes['list'] == 'true'
-            child.children.reject{|c| c.kind_of? REXML::Text}.map do |subchild| 
-                hash_or_value_for(subchild)
-            end     
-          else
-            child.children.reject{|c| c.kind_of? REXML::Text}.inject({}) do |subhash, subchild|
-              subhash[subchild.name] = hash_or_value_for(subchild)
-              subhash
-            end
+          child.children.reject{|c| c.kind_of? REXML::Text}.inject({}) do |subhash, subchild|
+            subhash[subchild.name] = hash_or_value_for(subchild)
+            subhash
           end
-        end
+        end #if (child.attributes)
         hash
-      end      
+      end #do |hash, child|      
     end
     
     def self.anonymous_field_from(child, hash)
@@ -89,6 +90,12 @@ module Facebooker
       element('auth_createToken_response', data).text_value
     end
   end
+  
+  class RegisterUsers &lt; Parser
+    def self.process(data)
+      array_of_text_values(element(&quot;connect_registerUsers_response&quot;, data), &quot;connect_registerUsers_response_elt&quot;)
+    end
+  end
 
   class GetSession &lt; Parser#:nodoc:
     def self.process(data)      
@@ -114,18 +121,54 @@ module Facebooker
     end
   end
   
+  class UserStandardInfo &lt; Parser#:nodoc:
+    def self.process(data)
+      array_of_hashes(element('users_getStandardInfo_response', data), 'standard_user_info')
+    end
+  end
+  
+  class GetLoggedInUser &lt; Parser#:nodoc:
+    def self.process(data)
+      Integer(element('users_getLoggedInUser_response', data).text_value)
+    end
+  end
+
+  class PagesIsAdmin &lt; Parser#:nodoc:
+    def self.process(data)
+      element('pages_isAdmin_response', data).text_value == '1'
+    end
+  end
+
+  class PagesGetInfo &lt; Parser#:nodoc:
+    def self.process(data)
+      array_of_hashes(element('pages_getInfo_response', data), 'page')
+    end
+  end
+
   class PublishStoryToUser &lt; Parser#:nodoc:
     def self.process(data)
       element('feed_publishStoryToUser_response', data).text_value
     end
   end
-  
+
   class RegisterTemplateBundle &lt; Parser#:nodoc:
     def self.process(data)
       element('feed_registerTemplateBundle_response', data).text_value.to_i
-    end    
+    end
   end
-  
+
+  class GetRegisteredTemplateBundles &lt; Parser
+    def self.process(data)
+      array_of_hashes(element('feed_getRegisteredTemplateBundles_response',data), 'template_bundle')
+    end
+  end
+
+  class DeactivateTemplateBundleByID &lt; Parser#:nodoc:
+    def self.process(data)
+      element('feed_deactivateTemplateBundleByID_response', data).text_value == '1'
+    end
+  end
+
   class PublishUserAction &lt; Parser#:nodoc:
     def self.process(data)
       element('feed_publishUserAction_response', data).children[1].text_value == &quot;1&quot;
@@ -165,15 +208,15 @@ module Facebooker
   class BatchRun &lt; Parser #:nodoc:
     class &lt;&lt; self
       def current_batch=(current_batch)
-        @current_batch=current_batch
+        Thread.current[:facebooker_current_batch]=current_batch
       end
       def current_batch
-        @current_batch
+        Thread.current[:facebooker_current_batch]
       end
     end
     def self.process(data)
       array_of_text_values(element('batch_run_response',data),&quot;batch_run_response_elt&quot;).each_with_index do |response,i|
-        batch_request=@current_batch[i]
+        batch_request=current_batch[i]
         body=Struct.new(:body).new
         body.body=CGI.unescapeHTML(response)
         begin
@@ -358,8 +401,8 @@ module Facebooker
         memo
       end
     end
-    
-    private
+
+  private
     def self.are_friends?(raw_value)
       if raw_value == '1'
         true
@@ -373,10 +416,28 @@ module Facebooker
   
   class SetStatus &lt; Parser
     def self.process(data)
-      element('users_setStatus_response',data)=='1'
+      element('users_setStatus_response',data).text_value == '1'
+    end
+  end
+  
+  class GetPreference &lt; Parser#:nodoc:
+    def self.process(data)
+      element('data_getUserPreference_response', data).text_value
+    end
+  end
+  
+  class SetPreference &lt; Parser#:nodoc:
+    def self.process(data)
+      element('data_setUserPreference_response', data).text_value
     end
   end
     
+  class UserHasPermission &lt; Parser
+    def self.process(data)
+      element('users_hasAppPermission_response', data).text_value
+    end
+  end  
+
   class Errors &lt; Parser#:nodoc:
     EXCEPTIONS = {
       1 	=&gt; Facebooker::Session::UnknownError,
@@ -422,7 +483,8 @@ module Facebooker
       response_element = element('error_response', data) rescue nil
       if response_element
         hash = hashinate(response_element)
-        raise EXCEPTIONS[Integer(hash['error_code'])].new(hash['error_msg'])
+        exception = EXCEPTIONS[Integer(hash['error_code'])] || StandardError
+        raise exception.new(hash['error_msg'])
       end
     end
   end
@@ -431,8 +493,14 @@ module Facebooker
     PARSERS = {
       'facebook.auth.createToken' =&gt; CreateToken,
       'facebook.auth.getSession' =&gt; GetSession,
+      'facebook.connect.registerUsers' =&gt; RegisterUsers,
       'facebook.users.getInfo' =&gt; UserInfo,
+      'facebook.users.getStandardInfo' =&gt; UserStandardInfo,
       'facebook.users.setStatus' =&gt; SetStatus,
+      'facebook.users.getLoggedInUser' =&gt; GetLoggedInUser,
+      'facebook.users.hasAppPermission' =&gt; UserHasPermission,
+      'facebook.pages.isAdmin' =&gt; PagesIsAdmin,
+      'facebook.pages.getInfo' =&gt; PagesGetInfo,
       'facebook.friends.get' =&gt; GetFriends,
       'facebook.friends.getLists' =&gt; FriendListsGet,
       'facebook.friends.areFriends' =&gt; AreFriends,
@@ -441,6 +509,8 @@ module Facebooker
       'facebook.feed.publishActionOfUser' =&gt; PublishActionOfUser,
       'facebook.feed.publishTemplatizedAction' =&gt; PublishTemplatizedAction,
       'facebook.feed.registerTemplateBundle' =&gt; RegisterTemplateBundle,
+      'facebook.feed.deactivateTemplateBundleByID' =&gt; DeactivateTemplateBundleByID,
+      'facebook.feed.getRegisteredTemplateBundles' =&gt; GetRegisteredTemplateBundles,
       'facebook.feed.publishUserAction' =&gt; PublishUserAction,
       'facebook.notifications.get' =&gt; NotificationsGet,
       'facebook.notifications.send' =&gt; NotificationsSend,
@@ -469,7 +539,9 @@ module Facebooker
       'facebook.groups.get' =&gt; GroupsGet,
       'facebook.events.getMembers' =&gt; EventMembersGet,
       'facebook.groups.getMembers' =&gt; GroupGetMembers,
-      'facebook.notifications.sendEmail' =&gt; NotificationsSendEmail
+      'facebook.notifications.sendEmail' =&gt; NotificationsSendEmail,
+      'facebook.data.getUserPreference' =&gt; GetPreference,
+      'facebook.data.setUserPreference' =&gt; SetPreference
     }
   end
 end</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/parser.rb</filename>
    </modified>
    <modified>
      <diff>@@ -9,6 +9,7 @@ module Facebooker
         controller.before_filter :set_adapter
         controller.before_filter :set_fbml_format
         controller.helper_attr :facebook_session_parameters
+        controller.helper_method :request_comes_from_facebook?
       end
 
     
@@ -22,8 +23,7 @@ module Facebooker
       
       
       def set_facebook_session
-        
-        returning session_set = session_already_secured? ||  secure_with_facebook_params! ||secure_with_token!  do
+        returning session_set = session_already_secured? ||  secure_with_facebook_params! || secure_with_cookies! || secure_with_token!  do
           if session_set
             capture_facebook_friends_if_available! 
             Session.current = facebook_session
@@ -35,16 +35,75 @@ module Facebooker
         @facebook_params ||= verified_facebook_params
       end      
       
+      def redirect_to(*args)
+        if request_is_for_a_facebook_canvas? and !request_is_facebook_tab?
+          render :text =&gt; fbml_redirect_tag(*args)
+        else
+          super
+        end
+      end
+            
       private
       
       def session_already_secured?
         (@facebook_session = session[:facebook_session]) &amp;&amp; session[:facebook_session].secured? if valid_session_key_in_session?
       end
       
+      def user_has_deauthorized_application?
+        # if we're inside the facebook session and there is no session key,
+        # that means the user revoked our access
+        # we don't want to keep using the old expired key from the cookie. 
+        request_comes_from_facebook? and params[:fb_sig_session_key].blank?
+      end
+      
+      def clear_facebook_session_information
+        session[:facebook_session] = nil
+        @facebook_session=nil        
+      end
+      
       def valid_session_key_in_session?
-       !session[:facebook_session].blank? &amp;&amp; (facebook_params[:session_key].blank? || session[:facebook_session].session_key == facebook_params[:session_key])
+        #before we access the facebook_params, make sure we have the parameters
+        #otherwise we will blow up trying to access the secure parameters
+        if user_has_deauthorized_application?
+          clear_facebook_session_information
+          false
+        else
+          !session[:facebook_session].blank? &amp;&amp;  (params[:fb_sig_session_key].blank? || session[:facebook_session].session_key == facebook_params[:session_key])
+        end
       end
       
+      def clear_fb_cookies!
+        domain_cookie_tag = &quot;base_domain_#{Facebooker.api_key}&quot;
+        cookie_domain = &quot;.#{cookies[domain_cookie_tag]}&quot; if cookies[domain_cookie_tag]
+        fb_cookie_names.each {|name| cookies.delete(name, :domain=&gt;cookie_domain)}
+        cookies.delete Facebooker.api_key
+      end
+
+      def fb_cookie_prefix
+        Facebooker.api_key+&quot;_&quot;
+      end
+
+      def fb_cookie_names
+        fb_cookie_names = cookies.keys.select{|k| k.starts_with?(fb_cookie_prefix)}
+      end
+
+      def secure_with_cookies!
+          parsed = {}
+          
+          fb_cookie_names.each { |key| parsed[key[fb_cookie_prefix.size,key.size]] = cookies[key] }
+ 
+          #returning gracefully if the cookies aren't set or have expired
+          return unless parsed['session_key'] &amp;&amp; parsed['user'] &amp;&amp; parsed['expires'] &amp;&amp; parsed['ss'] 
+          return unless Time.at(parsed['expires'].to_f) &gt; Time.now || (parsed['expires'] == &quot;0&quot;)
+          
+          #if we have the unexpired cookies, we'll throw an exception if the sig doesn't verify
+          verify_signature(parsed,cookies[Facebooker.api_key])
+          
+          @facebook_session = new_facebook_session
+          @facebook_session.secure_with!(parsed['session_key'],parsed['user'],parsed['expires'],parsed['ss'])
+          session[:facebook_session] = @facebook_session
+      end
+    
       def secure_with_token!
         if params['auth_token']
           @facebook_session = new_facebook_session
@@ -55,7 +114,7 @@ module Facebooker
       end
       
       def secure_with_facebook_params!
-        return unless request_is_for_a_facebook_canvas?
+        return unless request_comes_from_facebook?
         
         if ['user', 'session_key'].all? {|element| facebook_params[element]}
           @facebook_session = new_facebook_session
@@ -64,9 +123,15 @@ module Facebooker
         end
       end
       
+      #override to specify where the user should be sent after logging in
+      def after_facebook_login_url
+        nil
+      end
+      
       def create_new_facebook_session_and_redirect!
         session[:facebook_session] = new_facebook_session
-        redirect_to session[:facebook_session].login_url unless @installation_required
+        url_params = after_facebook_login_url.nil? ? {} : {:next=&gt;after_facebook_login_url}
+        redirect_to session[:facebook_session].login_url(url_params) unless @installation_required
         false
       end
       
@@ -75,7 +140,7 @@ module Facebooker
       end
       
       def capture_facebook_friends_if_available!
-        return unless request_is_for_a_facebook_canvas?
+        return unless request_comes_from_facebook?
         if friends = facebook_params['friends']
           facebook_session.user.friends = friends.map do |friend_uid|
             User.new(friend_uid, facebook_session)
@@ -108,7 +173,7 @@ module Facebooker
         raw_string = facebook_sig_params.map{ |*args| args.join('=') }.sort.join
         actual_sig = Digest::MD5.hexdigest([raw_string, Facebooker::Session.secret_key].join)
         raise Facebooker::Session::IncorrectSignature if actual_sig != expected_signature
-        raise Facebooker::Session::SignatureTooOld if Time.at(facebook_sig_params['time'].to_f) &lt; earliest_valid_session
+        raise Facebooker::Session::SignatureTooOld if facebook_sig_params['time'] &amp;&amp; Time.at(facebook_sig_params['time'].to_f) &lt; earliest_valid_session
         true
       end
       
@@ -124,18 +189,18 @@ module Facebooker
         )
       end
       
-      def redirect_to(*args)
-        if request_is_for_a_facebook_canvas? and !request_is_facebook_tab?
-          render :text =&gt; fbml_redirect_tag(*args)
-        else
-          super
-        end
-      end
-      
       def fbml_redirect_tag(url)
         &quot;&lt;fb:redirect url=\&quot;#{url_for(url)}\&quot; /&gt;&quot;
       end
       
+      def request_comes_from_facebook?
+        request_is_for_a_facebook_canvas? || request_is_facebook_ajax? || request_is_fb_ping?
+      end
+
+      def request_is_fb_ping?
+        !params['fb_sig'].blank?
+      end
+      
       def request_is_for_a_facebook_canvas?
         !params['fb_sig_in_canvas'].blank?
       end
@@ -191,7 +256,7 @@ module Facebooker
       end
       
       def set_fbml_format
-        params[:format]=&quot;fbml&quot; if request_is_for_a_facebook_canvas? or request_is_facebook_ajax?
+        params[:format]=&quot;fbml&quot; if request_comes_from_facebook?
       end
       def set_adapter
         Facebooker.load_adapter(params) if(params[:fb_sig_api_key])
@@ -213,4 +278,4 @@ module Facebooker
       end
     end
   end
-end
\ No newline at end of file
+end</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/rails/controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -103,8 +103,8 @@ module Facebooker
       end
       
       def add_default_name_and_id(options,method)
-        options[:name] ||= &quot;#{object.class.name.downcase}[#{method}]&quot;
-        options[:id] ||= &quot;#{object.class.name.downcase}_#{method}&quot;
+        options[:name] ||= &quot;#{object.class.name.underscore}[#{method}]&quot;
+        options[:id] ||= &quot;#{object.class.name.underscore}_#{method}&quot;
       end
 
     end</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/rails/facebook_form_builder.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-if  RAILS_ENV==&quot;development&quot;
+if Facebooker.facebooker_config['pretty_errors'] || (Facebooker.facebooker_config['pretty_errors'].nil? &amp;&amp; RAILS_ENV==&quot;development&quot;)
   class ActionController::Base
     def rescues_path_with_facebooker(template_name)
       t=&quot;#{RAILS_ROOT}/vendor/plugins/facebooker/templates/#{template_name}.erb&quot;</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/rails/facebook_pretty_errors.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,6 +11,17 @@ module ActionController
   end 
 end
 
+module ActionController
+  class RackRequest &lt; AbstractRequest #:nodoc:
+    alias :initialize_aliased_by_facebooker :initialize
+
+    def initialize(cgi, session_options = {})
+      initialize_aliased_by_facebooker(cgi, session_options)
+      @cgi.instance_variable_set(&quot;@request_params&quot;, request_parameters.merge(query_parameters))
+    end
+  end 
+end
+
 class CGI  
   class Session
     private
@@ -20,7 +31,7 @@ class CGI
       def initialize(request, option={})
         @request = request
         @initialization_options = option
-        option['session_id'] = set_session_id
+        option['session_id'] ||= set_session_id
         initialize_aliased_by_facebooker(request, option)
       end
       </diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/rails/facebook_session_handling.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,6 +5,12 @@ module ::ActionController
     end                                         
   end
   
+  class Base
+    def self.relative_url_root
+      Facebooker.path_prefix
+    end
+  end  
+  
   class UrlRewriter
     RESERVED_OPTIONS &lt;&lt; :canvas
     def link_to_new_canvas?</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/rails/facebook_url_rewriting.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,6 +8,7 @@ module Facebooker
     #
     module Helpers
       
+      include Facebooker::Rails::Helpers::FbConnect
       
       # Create an fb:dialog
       # id must be a unique name e.g. &quot;my_dialog&quot;
@@ -49,11 +50,11 @@ module Facebooker
       #    Send a poke to: &lt;%= fb_friend_selector %&gt; &lt;br /&gt;
       #    &lt;%= fb_request_form_submit %&gt;
       #  &lt;% end %&gt;
-      def fb_request_form(type,message_param,url,&amp;block)
+      def fb_request_form(type,message_param,url,options={},&amp;block)
         content = capture(&amp;block)
         message = @template.instance_variable_get(&quot;@content_for_#{message_param}&quot;) 
         concat(content_tag(&quot;fb:request-form&quot;, content + token_tag,
-                  {:action=&gt;url,:method=&gt;&quot;post&quot;,:invite=&gt;true,:type=&gt;type,:content=&gt;message}),
+                  {:action=&gt;url,:method=&gt;&quot;post&quot;,:invite=&gt;true,:type=&gt;type,:content=&gt;message}.merge(options)),
               block.binding)
       end
 
@@ -111,7 +112,7 @@ module Facebooker
       # &lt;em&gt; Note: &lt;/em&gt; I don't think the block is used here.
       def fb_multi_friend_selector(message,options={},&amp;block)
         options = options.dup
-        tag(&quot;fb:multi-friend-selector&quot;,stringify_vals(options.merge(:showborder=&gt;false,:actiontext=&gt;message,:max=&gt;20)))
+        tag(&quot;fb:multi-friend-selector&quot;,stringify_vals({:showborder=&gt;false,:actiontext=&gt;message,:max=&gt;20}.merge(options)))
       end
 
       # Render a condensed &lt;fb:multi-friend-selector&gt; with the passed in welcome message 
@@ -196,7 +197,7 @@ module Facebooker
         options.transform_keys!(FB_NAME_OPTION_KEYS_TO_TRANSFORM)
         options.assert_valid_keys(FB_NAME_VALID_OPTION_KEYS)
         options.merge!(:uid =&gt; cast_to_facebook_id(user))
-        tag(&quot;fb:name&quot;, stringify_vals(options))
+        content_tag(&quot;fb:name&quot;,nil, stringify_vals(options))
       end
 
       FB_NAME_OPTION_KEYS_TO_TRANSFORM = {:first_name_only =&gt; :firstnameonly, 
@@ -217,7 +218,7 @@ module Facebooker
         options.transform_keys!(FB_PRONOUN_OPTION_KEYS_TO_TRANSFORM)
         options.assert_valid_keys(FB_PRONOUN_VALID_OPTION_KEYS)
         options.merge!(:uid =&gt; cast_to_facebook_id(user))
-        tag(&quot;fb:pronoun&quot;, stringify_vals(options))
+        content_tag(&quot;fb:pronoun&quot;,nil, stringify_vals(options))
       end
       
       FB_PRONOUN_OPTION_KEYS_TO_TRANSFORM = {:use_you =&gt; :useyou, :use_they =&gt; :usethey}
@@ -259,7 +260,7 @@ module Facebooker
         options = options.dup
         validate_fb_profile_pic_size(options)
         options.merge!(:uid =&gt; cast_to_facebook_id(user))
-        tag(&quot;fb:profile-pic&quot;, stringify_vals(options))
+        content_tag(&quot;fb:profile-pic&quot;, nil,stringify_vals(options))
       end
       
       # Render an fb:photo tag.
@@ -271,7 +272,7 @@ module Facebooker
         options.merge!(:pid =&gt; cast_to_photo_id(photo))
         validate_fb_photo_size(options)
         validate_fb_photo_align_value(options)
-        tag(&quot;fb:photo&quot;, stringify_vals(options))
+        content_tag(&quot;fb:photo&quot;,nil, stringify_vals(options))
       end
 
       FB_PHOTO_VALID_OPTION_KEYS = [:uid, :size, :align]
@@ -283,7 +284,7 @@ module Facebooker
       VALID_FB_SHARED_PHOTO_SIZES = [:thumb, :small, :normal, :square]
       VALID_FB_PHOTO_SIZES = VALID_FB_SHARED_PHOTO_SIZES      
       VALID_FB_PROFILE_PIC_SIZES = VALID_FB_SHARED_PHOTO_SIZES
-      VALID_PERMISSIONS=[:email, :offline_access, :status_update, :photo_upload, :create_listing]
+      VALID_PERMISSIONS=[:email, :offline_access, :status_update, :photo_upload, :create_listing, :create_event, :rsvp_event, :sms]
       
       # Render an fb:tabs tag containing some number of fb:tab_item tags.
       # Example:
@@ -467,10 +468,11 @@ module Facebooker
       # 			  Hey you haven't agreed to our terms.  &lt;%= link_to(&quot;Please accept our terms of service.&quot;, :action =&gt; &quot;terms_of_service&quot;) %&gt;
       # 			&lt;% end %&gt;
       #&lt;% end %&gt;       
-      def fb_if_is_app_user(user,options={},&amp;proc)
+      def fb_if_is_app_user(user=nil,options={},&amp;proc)
         content = capture(&amp;proc) 
         options = options.dup
-        concat(content_tag(&quot;fb:if-is-app-user&quot;,content,stringify_vals(options.merge(:uid=&gt;cast_to_facebook_id(user)))),proc.binding)
+        options.merge!(:uid=&gt;cast_to_facebook_id(user)) if user
+        concat(content_tag(&quot;fb:if-is-app-user&quot;,content,stringify_vals(options)),proc.binding)
       end
 
       # Render if-user-has-added-app tag
@@ -517,17 +519,57 @@ module Facebooker
       #
       # Return the URL for the about page of the application
       def fb_about_url
-        &quot;http://www.facebook.com/apps/application.php?api_key=#{Facebooker.api_key}&quot;
+        &quot;http://#{Facebooker.www_server_base_url}/apps/application.php?api_key=#{Facebooker.api_key}&quot;
       end
       
       #
       # Embed a discussion board named xid on the current page
-      # 
+      # &lt;em&gt;See&lt;/em http://wiki.developers.facebook.com/index.php/Fb:board for more details
+      # Options are:
+      #   * canpost
+      #   * candelete
+      #   * canmark
+      #   * cancreatet
+      #   * numtopics
+      #   * callbackurl
+      #   * returnurl
+      #
       def fb_board(xid,options={})
         options = options.dup
-        tag(&quot;fb:board&quot;,stringify_vals(options.merge(:xid=&gt;xid)))
+        title = (title = options.delete(:title)) ? fb_title(title) : nil
+        content_tag(&quot;fb:board&quot;, title, stringify_vals(options.merge(:xid=&gt;xid)))
+      end
+      
+      # Renders an 'Add to Profile' button
+      # The button allows a user to add condensed profile box to the main profile
+      def fb_add_profile_section
+        tag &quot;fb:add-section-button&quot;,:section=&gt;&quot;profile&quot;
+      end
+      
+      # Renders an 'Add to Info' button
+      # The button allows a user to add an application info section to her Info tab
+      def fb_add_info_section
+        tag &quot;fb:add-section-button&quot;,:section=&gt;&quot;info&quot;
       end
       
+      # Renders a link that, when clicked, initiates a dialog requesting the specified extended permission from the user.
+      # 
+      # You can prompt a user with the following permissions:
+      #   * email
+      #   * offline_access
+      #   * status_update
+      #   * photo_upload
+      #   * create_listing
+      #   * create_event
+      #   * rsvp_event
+      #   * sms
+      # 
+      # Example:
+      # &lt;%= fb_prompt_permission('email', &quot;Would you like to receive email from our application?&quot; ) %&gt;
+      #
+      # See http://wiki.developers.facebook.com/index.php/Fb:prompt-permission for 
+      # more details
+      #
       def fb_prompt_permission(permission,message,callback=nil)
         raise(ArgumentError, &quot;Unknown value for permission: #{permission}&quot;) unless VALID_PERMISSIONS.include?(permission.to_sym)
         args={:perms=&gt;permission}
@@ -535,6 +577,39 @@ module Facebooker
         content_tag(&quot;fb:prompt-permission&quot;,message,args)
       end
       
+      # Renders an &lt;fb:eventlink /&gt; tag that displays the event name and links to the event's page. 
+      def fb_eventlink(eid)
+        content_tag &quot;fb:eventlink&quot;,nil,:eid=&gt;eid
+      end
+      
+      # Renders an &lt;fb:grouplink /&gt; tag that displays the group name and links to the group's page. 
+      def fb_grouplink(gid)
+        content_tag &quot;fb:grouplink&quot;,nil,:gid=&gt;gid
+      end
+      
+      # Returns the status of the user
+      def fb_user_status(user,linked=true)
+        content_tag &quot;fb:user-status&quot;,nil,stringify_vals(:uid=&gt;cast_to_facebook_id(user), :linked=&gt;linked)
+      end
+      
+      # Renders a standard 'Share' button for the specified URL.
+      def fb_share_button(url)
+        content_tag &quot;fb:share-button&quot;,nil,:class=&gt;&quot;url&quot;,:href=&gt;url
+      end
+      
+      # Renders the FBML on a Facebook server inside an iframe.
+      #
+      # Meant to be used for a Facebook Connect site or an iframe application
+      def fb_serverfbml(options={},&amp;proc)
+        inner = capture(&amp;proc)
+        concat(content_tag(&quot;fb:serverfbml&quot;,inner,options),&amp;proc.binding)
+      end
+
+      def fb_container(options={},&amp;proc)
+        inner = capture(&amp;proc)
+        concat(content_tag(&quot;fb:container&quot;,inner,options),&amp;proc.binding)
+      end
+      
       protected
       
       def cast_to_facebook_id(object)</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/rails/helpers.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,20 +4,12 @@ module Facebooker
     # 
     # To use, create a subclass and define methods
     # Each method should start by calling send_as to specify the type of message
-    # Valid options are :action, :templatized_action, :story, :email and :notification
+    # Valid options are  :email and :notification, :user_action, :profile, :ref
     # 
     #
     # Below is an example of each type
     #
     #   class TestPublisher &lt; Facebooker::Rails::Publisher
-    #     # Action is published using the session of the from user
-    #     def action(f)
-    #       send_as :action
-    #       from f
-    #       title &quot;Action Title&quot;
-    #       body &quot;Body FBML here #{fb_name(f)} #{link_to &quot;text&quot;,new_invitation_url}&quot;
-    #     end
-    #
     #     # The new message templates are supported as well
     #     # First, create a method that contains your templates:
     #     # You may include multiple one line story templates and short story templates
@@ -34,6 +26,7 @@ module Facebooker
     #       short_story_template &quot;{*actor*} has a title {*friend*}&quot;, render(:partial=&gt;&quot;short_body&quot;)
     #       short_story_template &quot;{*actor*} has a title&quot;, render(:partial=&gt;&quot;short_body&quot;)
     #       full_story_template &quot;{*actor*} has a title {*friend*}&quot;, render(:partial=&gt;&quot;full_body&quot;)    
+    #       action_links action_link(&quot;My text {*template_var*}&quot;,&quot;{*link_url*}&quot;)
     #     end
     #
     #     # To send a registered template, you need to create a method to set the data
@@ -41,22 +34,10 @@ module Facebooker
     #     def publish_action(f)
     #       send_as :user_action
     #       from f
+    #       story_size SHORT # or ONE_LINE or FULL
     #       data :friend=&gt;&quot;Mike&quot;
     #     end
     #   
-    #     # Templatized Action uses From
-    #     def templatized_action(f)
-    #       send_as :templatized_action
-    #       from f
-    #       title_template &quot;Templatized Action Title {name}&quot;
-    #       title_data :name=&gt;&quot;Mike&quot;
-    #     end
-    #     # story is published to the story of the to user
-    #     def story(to)
-    #       send_as :story
-    #       recipients to
-    #       title 'Story Title'
-    #     end
     #  
     #     # Provide a from user to send a general notification
     #     # if from is nil, this will send an announcement
@@ -108,20 +89,106 @@ module Facebooker
     # Publisher makes many helpers available, including the linking and asset helpers
     class Publisher
       
+      #story sizes from the Facebooker API
+      ONE_LINE=1
+      SHORT=2
+      FULL=4
+      
+      def initialize
+        @controller = PublisherController.new        
+      end
+      
+      # use facebook options everywhere
+      def request_comes_from_facebook?
+        true
+      end
+      
       class FacebookTemplate &lt; ::ActiveRecord::Base
-        def self.register(t_id,name)
-          t=find_or_initialize_by_template_name(name)
-          t.update_attribute(:bundle_id,t_id)
-          t
+        
+        
+        cattr_accessor :template_cache
+        self.template_cache = {}
+        
+        def self.inspect(*args)
+          &quot;FacebookTemplate&quot;
         end
-
-        def self.for(name)
-          find_by_template_name(name).bundle_id rescue nil
+        
+        def template_changed?(hash)
+          if respond_to?(:content_hash)
+            content_hash != hash 
+          else
+            false
+          end
+        end
+        
+        class &lt;&lt; self
+          
+          def register(klass,method)
+            publisher = setup_publisher(klass,method)            
+            template_id = Facebooker::Session.create.register_template_bundle(publisher.one_line_story_templates,publisher.short_story_templates,publisher.full_story_template,publisher.action_links)
+            template = find_or_initialize_by_template_name(template_name(klass,method))
+            template.bundle_id = template_id
+            template.content_hash = hashed_content(klass,method) if template.respond_to?(:content_hash)
+            template.save!
+            cache(klass,method,template)
+            template
+          end
+          
+          def for_class_and_method(klass,method)
+            find_cached(klass,method) 
+          end
+          def bundle_id_for_class_and_method(klass,method)
+            for_class_and_method(klass,method).bundle_id
+          end
+          
+          def cache(klass,method,template)
+            template_cache[template_name(klass,method)] = template
+          end
+          
+          def clear_cache!
+            self.template_cache = {}
+          end
+          
+          def find_cached(klass,method)
+            template_cache[template_name(klass,method)] || find_in_db(klass,method)
+          end
+          
+          def find_in_db(klass,method)
+            template = find_by_template_name(template_name(klass,method))
+            if template and template.template_changed?(hashed_content(klass,method))
+              template.destroy
+              template = nil
+            end
+            
+            if template.nil?
+              template = register(klass,method)
+            end
+            template
+          end
+          
+          def setup_publisher(klass,method)
+            publisher = klass.new
+            publisher.send method + '_template'
+            publisher
+          end
+          
+          def hashed_content(klass, method)
+            publisher = setup_publisher(klass,method)
+            # sort the Hash elements (in the short_story and full_story) before generating MD5
+            Digest::MD5.hexdigest [publisher.one_line_story_templates,
+               (publisher.short_story_templates and publisher.short_story_templates.collect{|ss| ss.to_a.sort_by{|e| e[0].to_s}}),
+               (publisher.full_story_template and publisher.full_story_template.to_a.sort_by{|e| e[0].to_s})
+               ].to_json
+          end
+          
+          def template_name(klass,method)
+            &quot;#{klass.name}::#{method}&quot;
+          end
         end
       end
       
       class_inheritable_accessor :master_helper_module
-      attr_accessor :one_line_story_templates, :short_story_templates
+      attr_accessor :one_line_story_templates, :short_story_templates, :action_links
       
       cattr_accessor :skip_registry
       self.skip_registry = false
@@ -156,21 +223,18 @@ module Facebooker
         attr_accessor :body_general
         attr_accessor :template_id
         attr_accessor :template_name
-        
-        def template_id
-          @template_id || FacebookTemplate.for(template_name)
-        end
-
+        attr_accessor :story_size
         def target_ids=(val)
           @target_ids = val.is_a?(Array) ? val.join(&quot;,&quot;) : val
         end
-        
+        def data_hash
+          default_data = story_size.nil? ? {} : {:story_size=&gt;story_size}
+          default_data.merge(data||{})
+        end
       end
       
       cattr_accessor :ignore_errors
       attr_accessor :_body
-    
-  
 
       def recipients(*args)
         if args.size==0
@@ -230,6 +294,14 @@ module Facebooker
         @short_story_templates &lt;&lt; params.merge(:template_title=&gt;title, :template_body=&gt;body)
       end
       
+      def action_links(*links)
+        if links.blank?
+          @action_links
+        else
+          @action_links = links
+        end
+      end
+      
       def method_missing(name,*args)
         if args.size==1 and self._body.respond_to?(&quot;#{name}=&quot;)
           self._body.send(&quot;#{name}=&quot;,*args)
@@ -240,8 +312,24 @@ module Facebooker
         end
       end
       
-      def image(src,url)
-        {:src=&gt;image_path(src),:href=&gt;url}
+      def image(src,target)
+        {:src=&gt;image_path(src),:href=&gt; target.respond_to?(:to_str) ? target : url_for(target)}
+      end
+      
+      def action_link(text,target)
+        {:text=&gt;text, :href=&gt;target}
+      end
+  
+      def requires_from_user?(from,body)
+        ! (announcement_notification?(from,body) or ref_update?(body) or profile_update?(body))
+      end
+      
+      def profile_update?(body)
+        body.is_a?(Profile)
+      end
+      
+      def ref_update?(body)
+        body.is_a?(Ref)
       end
   
       def announcement_notification?(from,body)
@@ -250,12 +338,12 @@ module Facebooker
       
       def send_message(method)
         @recipients = @recipients.is_a?(Array) ? @recipients : [@recipients]
-        if from.nil? and @recipients.size==1 and ! announcement_notification?(from,_body)
+        if from.nil? and @recipients.size==1 and requires_from_user?(from,_body)
           @from = @recipients.first
         end
         # notifications can 
         # omit the from address
-        raise InvalidSender.new(&quot;Sender must be a Facebooker::User&quot;) unless from.is_a?(Facebooker::User) || announcement_notification?(from,_body)
+        raise InvalidSender.new(&quot;Sender must be a Facebooker::User&quot;) unless from.is_a?(Facebooker::User) || !requires_from_user?(from,_body)
         case _body
         when Facebooker::Feed::TemplatizedAction,Facebooker::Feed::Action
           from.publish_action(_body)
@@ -271,14 +359,12 @@ module Facebooker
         when Profile
          # If recipient and from aren't the same person, create a new user object using the
          # userid from recipient and the session from from
-         if @from != @recipients.first
-           @from = Facebooker::User.new(Facebooker::User.cast_to_facebook_id(@recipients.first),from.session) 
-         end
-         from.set_profile_fbml(_body.profile, _body.mobile_profile, _body.profile_action, _body.profile_main)
+         @from = Facebooker::User.new(Facebooker::User.cast_to_facebook_id(@recipients.first),Facebooker::Session.create) 
+         @from.set_profile_fbml(_body.profile, _body.mobile_profile, _body.profile_action, _body.profile_main)
         when Ref
-          @from.session.server_cache.set_ref_handle(_body.handle,_body.fbml)
+          Facebooker::Session.create.server_cache.set_ref_handle(_body.handle,_body.fbml)
         when UserAction
-          @from.session.publish_user_action(_body.template_id || FacebookTemplate.for(method) ,_body.data,_body.target_ids,_body.body_general)
+          @from.session.publish_user_action(_body.template_id,_body.data_hash,_body.target_ids,_body.body_general)
         else
           raise UnspecifiedBodyType.new(&quot;You must specify a valid send_as&quot;)
         end
@@ -310,6 +396,9 @@ module Facebooker
         returning ActionView::Base.new([template_root,controller_root], assigns, self) do |template|
           template.controller=self
           template.extend(self.class.master_helper_module)
+          def template.request_comes_from_facebook?
+            true
+          end
         end
       end
   
@@ -331,11 +420,14 @@ module Facebooker
         def protect_against_forgery?
           @paf ||= ActionController::Base.new.send(:protect_against_forgery?)
         end
+        
+        # url_for calls in publishers tend to want full paths
+        def url_for(options = {})
+          super(options.kind_of?(Hash) ? {:only_path =&gt; false}.update(options) : options)
+        end
       end
       ActionController::Routing::Routes.named_routes.install(self.master_helper_module)
       include self.master_helper_module
-      # Publisher is the controller, it should do the rewriting
-      include ActionController::UrlWriter
       class &lt;&lt;self
         
         def register_all_templates
@@ -348,18 +440,15 @@ module Facebooker
         end
         
         def method_missing(name,*args)
-          should_send=false
-          method=&quot;&quot;
-          if md=/^create_(.*)$/.match(name.to_s)
-            method=md[1]
-          elsif md=/^deliver_(.*)$/.match(name.to_s)
-            method=md[1]
-            should_send=true
-          elsif md=/^register_(.*)$/.match(name.to_s)
-            (publisher=new).send(md[1]+&quot;_template&quot;)
-            template_id = Facebooker::Session.create.register_template_bundle(publisher.one_line_story_templates,publisher.short_story_templates,publisher.full_story_template)
-            FacebookTemplate.register(template_id,md[1]) unless skip_registry
-            return template_id
+          should_send = false
+          method = ''
+          if md = /^create_(.*)$/.match(name.to_s)
+            method = md[1]
+          elsif md = /^deliver_(.*)$/.match(name.to_s)
+            method = md[1]
+            should_send = true            
+          elsif md = /^register_(.*)$/.match(name.to_s)
+            return FacebookTemplate.register(self, md[1])
           else
             super
           end
@@ -368,7 +457,8 @@ module Facebooker
           (publisher=new).send(method,*args)
           case publisher._body
           when UserAction
-            publisher._body.template_name=method
+            publisher._body.template_name = method
+            publisher._body.template_id = FacebookTemplate.bundle_id_for_class_and_method(self,method)
           end
           
           should_send ? publisher.send_message(method) : publisher._body
@@ -402,11 +492,22 @@ module Facebooker
         def inherited(child)
           super          
           child.master_helper_module=Module.new
-          child.master_helper_module.send!(:include,self.master_helper_module)
-          child.send(:include, child.master_helper_module)      
+          child.master_helper_module.__send__(:include,self.master_helper_module)
+          child.send(:include, child.master_helper_module)
+          FacebookTemplate.clear_cache!
         end
     
       end
+      class PublisherController
+        include Facebooker::Rails::Publisher.master_helper_module
+        include ActionController::UrlWriter
+        
+        def self.default_url_options(*args)
+          Facebooker::Rails::Publisher.default_url_options(*args)
+        end
+        
+      end
+      
     end
   end
 end</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/rails/publisher.rb</filename>
    </modified>
    <modified>
      <diff>@@ -34,11 +34,6 @@ module Facebooker
         send verb, path, params
       end
       
-      def facebook_post(path, params={}, fb_params=facebook_parameters)
-        params = fb_params.merge(:canvas =&gt; true).merge(params)
-        post path, params    
-      end
-      
       def facebook_parameters(overrides=nil)
         overrides ||= {}
         params = default_facebook_parameters.merge(overrides)</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/rails/test_helpers.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,17 +8,17 @@ module Facebooker
     # Stores an FBML reference on the server for use 
     # across multiple users in FBML
     def set_ref_handle(handle_name, fbml_source)
-      (@session.post 'facebook.fbml.setRefHandle', :handle =&gt; handle_name, :fbml =&gt; fbml_source) == '1'
+      (@session.post 'facebook.fbml.setRefHandle', {:handle =&gt; handle_name, :fbml =&gt; fbml_source},false) == '1'
     end
     
     ##
     # Fetches and re-caches the content stored at the given URL, for use in a fb:ref FBML tag.
     def refresh_ref_url(url)
-      (@session.post 'facebook.fbml.refreshRefUrl', :url =&gt; url) == '1'
+      (@session.post 'facebook.fbml.refreshRefUrl', {:url =&gt; url},false) == '1'
     end
     
     def refresh_img_src(url)
-      (@session.post 'facebook.fbml.refreshImgSrc', :url =&gt; url) == '1'
+      (@session.post 'facebook.fbml.refreshImgSrc', {:url =&gt; url},false) == '1'
     end
   end
 end
\ No newline at end of file</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/server_cache.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,10 @@
-require 'net/http'
+begin
+  require 'curb'
+  Facebooker.use_curl = true
+rescue LoadError
+  $stderr.puts &quot;Curb not found. Using Net::HTTP.&quot;
+  require 'net/http'
+end
 require 'facebooker/parser'
 module Facebooker
   class Service
@@ -10,16 +16,77 @@ module Facebooker
     
     # TODO: support ssl 
     def post(params)
-      Parser.parse(params[:method], Net::HTTP.post_form(url, params))
+      attempt = 0
+      Parser.parse(params[:method], post_form(url,params) )
+    rescue Errno::ECONNRESET, EOFError
+      if attempt == 0
+        attempt += 1
+        retry
+      end
+    end
+    
+    def post_form(url,params)
+      if Facebooker.use_curl?
+        post_form_with_curl(url,params)
+      else
+        post_form_with_net_http(url,params)
+      end
+    end
+    
+    def post_form_with_net_http(url,params)
+      Net::HTTP.post_form(url, params)
+    end
+    
+    def post_form_with_curl(url,params,multipart=false)
+      response = Curl::Easy.http_post(url.to_s, *to_curb_params(params)) do |c|
+        c.multipart_form_post = multipart
+        c.timeout = Facebooker.timeout 
+      end
+      response.body_str
+    end
+    
+    def post_multipart_form(url,params)
+      if Facebooker.use_curl?
+        post_form_with_curl(url,params,true)
+      else
+        post_multipart_form_with_net_http(url,params)
+      end
+    end
+    
+    def post_multipart_form_with_net_http(url,params)
+      Net::HTTP.post_multipart_form(url, params)
     end
     
     def post_file(params)
-      Parser.parse(params[:method], Net::HTTP.post_multipart_form(url, params))
+      Parser.parse(params[:method], post_multipart_form(url, params))
     end
     
     private
     def url
       URI.parse('http://'+ @api_base + @api_path)
     end
+    
+    # Net::HTTP::MultipartPostFile
+    def multipart_post_file?(object)
+      object.respond_to?(:content_type) &amp;&amp;
+      object.respond_to?(:data) &amp;&amp;
+      object.respond_to?(:filename)
+    end
+    
+    def to_curb_params(params)
+      parray = []
+      params.each_pair do |k,v|
+        if multipart_post_file?(v)
+          # Curl doesn't like blank field names
+          field = Curl::PostField.file((k.blank? ? 'xxx' : k.to_s), nil, File.basename(v.filename))
+          field.content_type = v.content_type
+          field.content = v.data
+          parray &lt;&lt; field
+        else
+          parray &lt;&lt; Curl::PostField.content(k.to_s, v.to_s)
+        end
+      end
+      parray
+    end
   end
 end
\ No newline at end of file</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/service.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,3 @@
-require 'digest/md5'
 require 'cgi'
 
 module Facebooker
@@ -49,6 +48,9 @@ module Facebooker
     class TooManyUnapprovedPhotosPending &lt; StandardError; end
     class ExtendedPermissionRequired &lt; StandardError; end
     class InvalidFriendList &lt; StandardError; end
+    class UserRegistrationFailed &lt; StandardError
+      attr_accessor :failed_users
+    end
     
     API_SERVER_BASE_URL       = ENV[&quot;FACEBOOKER_API&quot;] == &quot;new&quot; ? &quot;api.new.facebook.com&quot; : &quot;api.facebook.com&quot;
     API_PATH_REST             = &quot;/restserver.php&quot;
@@ -76,11 +78,11 @@ module Facebooker
     end
     
     def self.current
-      @current_session
+      Thread.current['facebook_session']
     end
     
     def self.current=(session)
-      @current_session=session
+      Thread.current['facebook_session'] = session
     end
     
     def login_url(options={})
@@ -154,9 +156,9 @@ module Facebooker
       secure_with!(response['session_key'], response['uid'], response['expires'], response['secret'])
     end    
     
-    def secure_with!(session_key, uid, expires, secret_from_session = nil)
+    def secure_with!(session_key, uid = nil, expires = nil, secret_from_session = nil)
       @session_key = session_key
-      @uid = Integer(uid)
+      @uid = uid ? Integer(uid) : post('facebook.users.getLoggedInUser', :session_key =&gt; session_key)
       @expires = Integer(expires)
       @secret_from_session = secret_from_session
     end
@@ -176,8 +178,10 @@ module Facebooker
             Photo.from_hash(hash)
           when 'event_member'
             Event::Attendance.from_hash(hash)
+          else
+            hash
           end
-        end        
+        end
       end
     end
     
@@ -207,7 +211,29 @@ module Facebooker
         end
       end
     end
-    
+
+    def users_standard(user_ids, fields=[])
+      post(&quot;facebook.users.getStandardInfo&quot;,:uids=&gt;user_ids.join(&quot;,&quot;),:fields=&gt;User.standard_fields(fields)) do |users|
+        users.map { |u| User.new(u)}
+      end
+    end
+
+    def users(user_ids, fields=[])
+      post(&quot;facebook.users.getInfo&quot;,:uids=&gt;user_ids.join(&quot;,&quot;),:fields=&gt;User.user_fields(fields)) do |users|
+        users.map { |u| User.new(u)}
+      end
+    end
+
+    def pages(options = {})
+      raise ArgumentError, 'fields option is mandatory' unless options.has_key?(:fields)
+      @pages ||= {}
+      @pages[options] ||= post('facebook.pages.getInfo', options) do |response|
+        response.map do |hash|
+          Page.from_hash(hash)
+        end
+      end
+    end
+
     #
     # Returns a proxy object for handling calls to Facebook cached items
     # such as images and FBML ref handles
@@ -235,10 +261,10 @@ module Facebooker
       uids1 = []
       uids2 = []
       array_of_pairs_of_users.each do |pair|
-        uids1 = pair.first
-        uids2 = pair.last
+        uids1 &lt;&lt; pair.first
+        uids2 &lt;&lt; pair.last
       end
-      post('facebook.friends.areFriends', :uids1 =&gt; uids1, :uids2 =&gt; uids2)
+      post('facebook.friends.areFriends', :uids1 =&gt; uids1.join(','), :uids2 =&gt; uids2.join(','))
     end
     
     def get_photos(pids = nil, subj_id = nil,  aid = nil)
@@ -280,10 +306,10 @@ module Facebooker
       if email_fbml
         params[:email] = email_fbml
       end
-      params[:type]=&quot;general&quot;
+      params[:type]=&quot;user_to_user&quot;
       # if there is no uid, this is an announcement
       unless uid?
-        params[:type]=&quot;announcement&quot;
+        params[:type]=&quot;app_to_user&quot;
       end
       
       post 'facebook.notifications.send', params,uid?
@@ -292,23 +318,16 @@ module Facebooker
     ##
     # Register a template bundle with Facebook.
     # returns the template id to use to send using this template
-    def register_template_bundle(one_line_story_templates,short_story_templates=nil,full_story_template=nil)
-
-      if !one_line_story_templates.is_a?(Array)
-        one_line_story_templates = [one_line_story_templates]
-      end
-      parameters = {:one_line_story_templates=&gt;one_line_story_templates.to_json}
-
+    def register_template_bundle(one_line_story_templates,short_story_templates=nil,full_story_template=nil, action_links=nil)
+      parameters = {:one_line_story_templates =&gt; Array(one_line_story_templates).to_json}
       
-      if !short_story_templates.blank?
-        short_story_templates = [short_story_templates] unless short_story_templates.is_a?(Array)
-        parameters[:short_story_templates]= short_story_templates.to_json
-      end
+      parameters[:action_links] = action_links.to_json unless action_links.blank?
+      
+      parameters[:short_story_templates] = Array(short_story_templates).to_json unless short_story_templates.blank?
 
-      if !full_story_template.blank?
-        parameters[:full_story_template]= full_story_template.to_json
-      end
-      post(&quot;facebook.feed.registerTemplateBundle&quot;, parameters,false)
+      parameters[:full_story_template] = full_story_template.to_json unless full_story_template.blank?
+
+      post(&quot;facebook.feed.registerTemplateBundle&quot;, parameters, false)
     end
     
     ##
@@ -374,7 +393,7 @@ module Facebooker
         secret
       end
       
-      def post(method, params = {})
+      def post(method, params = {},use_session=false)
         if method == 'facebook.profile.getFBML' || method == 'facebook.profile.setFBML'
           raise NonSessionUser.new(&quot;User #{@uid} is not the logged in user.&quot;) unless @uid == params[:uid]
         end
@@ -392,7 +411,7 @@ module Facebooker
     
     def add_to_batch(req,&amp;proc)
       batch_request = BatchRequest.new(req,proc)
-      @batch_queue&lt;&lt;batch_request
+      Thread.current[:facebooker_current_batch_queue]&lt;&lt;batch_request
       batch_request
     end
     
@@ -433,34 +452,46 @@ module Facebooker
     #
     def batch(serial_only=false)
       @batch_request=true
-      @batch_queue=[]
+      Thread.current[:facebooker_current_batch_queue]=[]
       yield
       # Set the batch request to false so that post will execute the batch job
       @batch_request=false
-      BatchRun.current_batch=@batch_queue
-      post(&quot;facebook.batch.run&quot;,:method_feed=&gt;@batch_queue.map{|q| q.uri}.to_json,:serial_only=&gt;serial_only.to_s)
+      BatchRun.current_batch=Thread.current[:facebooker_current_batch_queue]
+      post(&quot;facebook.batch.run&quot;,:method_feed=&gt;BatchRun.current_batch.map{|q| q.uri}.to_json,:serial_only=&gt;serial_only.to_s)
     ensure
       @batch_request=false
       BatchRun.current_batch=nil
     end
     
-    def post(method, params = {},use_session_key=true,&amp;proc)
+    def post_without_logging(method, params = {}, use_session_key = true, &amp;proc)
       add_facebook_params(params, method)
       use_session_key &amp;&amp; @session_key &amp;&amp; params[:session_key] ||= @session_key
       final_params=params.merge(:sig =&gt; signature_for(params))
       if batch_request?
         add_to_batch(final_params,&amp;proc)
       else
-        result=service.post(final_params)
+        result = service.post(final_params)
         result = yield result if block_given?
         result
       end
     end
     
+    def post(method, params = {}, use_session_key = true, &amp;proc)
+      if batch_request?
+        post_without_logging(method, params, use_session_key, &amp;proc)
+      else
+        Logging.log_fb_api(method, params) do
+          post_without_logging(method, params, use_session_key, &amp;proc)
+        end
+      end
+    end
+    
     def post_file(method, params = {})
-      add_facebook_params(params, method)
-      @session_key &amp;&amp; params[:session_key] ||= @session_key
-      service.post_file(params.merge(:sig =&gt; signature_for(params.reject{|key, value| key.nil?})))
+      Logging.log_fb_api(method, params) do
+        add_facebook_params(params, method)
+        @session_key &amp;&amp; params[:session_key] ||= @session_key
+        service.post_file(params.merge(:sig =&gt; signature_for(params.reject{|key, value| key.nil?})))
+      end
     end
     
     
@@ -506,7 +537,7 @@ module Facebooker
       end
       
       def uid?
-        ! @uid.nil?
+        !! @uid
       end
       
       def signature_for(params)</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/session.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,7 +2,7 @@ module Facebooker #:nodoc:
   module VERSION #:nodoc:
     MAJOR = 0
     MINOR = 9
-    TINY  = 5
+    TINY  = 9
 
     STRING = [MAJOR, MINOR, TINY].join('.')
   end</diff>
      <filename>vendor/plugins/facebooker/lib/facebooker/version.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,6 +7,7 @@ namespace :facebooker do
     facebook_config = File.join(RAILS_ROOT,&quot;config&quot;,&quot;facebooker.yml&quot;)
     unless File.exist?(facebook_config)
       FileUtils.cp File.join(RAILS_ROOT,&quot;vendor&quot;, &quot;plugins&quot;, &quot;facebooker&quot;, &quot;facebooker.yml.tpl&quot;), facebook_config 
+      puts &quot;Ensure 'GatewayPorts yes' is enabled in the remote development server's sshd config when using any of the facebooker:tunnel:*' rake tasks&quot;
       puts &quot;Configuration created in #{RAILS_ROOT}/config/facebooker.yml&quot;
     else
       puts &quot;#{RAILS_ROOT}/config/facebooker.yml already exists&quot;</diff>
      <filename>vendor/plugins/facebooker/lib/tasks/facebooker.rake</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 namespace :facebooker do
   
-  namespace :tunnel do 
+  tunnel_ns = namespace :tunnel do 
     # Courtesy of Christopher Haupt
     # http://www.BuildingWebApps.com
     # http://www.LearningRails.com
@@ -37,7 +37,10 @@ namespace :facebooker do
      @ssh_port = FACEBOOKER['tunnel']['ssh_port'] || 22
      @notification = &quot;Starting tunnel #{@public_host}:#{@public_port} to 0.0.0.0:#{@local_port}&quot;
      @notification &lt;&lt; &quot; using SSH port #{@ssh_port}&quot; unless @ssh_port == 22
-     @ssh_command = &quot;ssh -p #{@ssh_port} -nNT -g -R *:#{@public_port}:0.0.0.0:#{@local_port} #{@public_host_username}@#{@public_host}&quot; 
+     # &quot;GatewayPorts yes&quot; needs to be enabled in the remote's sshd config
+     @ssh_command = &quot;ssh -v -p #{@ssh_port} -nNT4 -R *:#{@public_port}:localhost:#{@local_port} #{@public_host_username}@#{@public_host}&quot; 
     end
-  end
-end
\ No newline at end of file
+  end  
+  desc &quot;Create a reverse ssh tunnel from a public server to a private development server.&quot;
+  task :tunnel =&gt; tunnel_ns[:start]
+end</diff>
      <filename>vendor/plugins/facebooker/lib/tasks/tunnel.rake</filename>
    </modified>
    <modified>
      <diff>@@ -3,6 +3,7 @@ require File.dirname(__FILE__) + '/test_helper.rb'
 class FacebookAdminTest &lt; Test::Unit::TestCase
   def setup
     @session = Facebooker::Session.create('apikey', 'secretkey')
+    Facebooker.use_curl=false
   end
   
   def test_can_ask_facebook_to_set_app_properties
@@ -10,6 +11,12 @@ class FacebookAdminTest &lt; Test::Unit::TestCase
     properties = { :application_name =&gt; &quot;Video Jukebox&quot;, :dev_mode =&gt; 0 }    
     assert(@session.admin.set_app_properties(properties))
   end
+
+  def test_set_app_properties_json_conversion
+    properties = { :application_name =&gt; &quot;Video Jukebox&quot;, :dev_mode =&gt; 0 }
+    flexmock(@session).should_receive(:post).with('facebook.admin.setAppProperties', :properties =&gt; properties.to_json).and_return('1').once
+    assert(@session.admin.set_app_properties(properties))
+  end
     
   def test_can_ask_facebook_to_get_app_properties
     expect_http_posts_with_responses(example_get_properties_xml)
@@ -20,9 +27,10 @@ class FacebookAdminTest &lt; Test::Unit::TestCase
   def test_can_get_properties
     mock_http = establish_session
     mock_http.should_receive(:post_form).and_return(example_get_properties_xml).once.ordered(:posts)
-    p = @session.admin.get_app_properties(:application_name, :dev_mode)
+    p = @session.admin.get_app_properties(:application_name, :dev_mode, :canvas_name)
     assert_equal 'Video Jukebox', p.application_name
     assert_equal 0, p.dev_mode
+    assert_equal 'my_canvas', p.canvas_name
   end
 
   def test_can_get_allocation
@@ -48,7 +56,7 @@ class FacebookAdminTest &lt; Test::Unit::TestCase
       xmlns=&quot;http://api.facebook.com/1.0/&quot;
       xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
       xsi:schemaLocation=&quot;http://api.facebook.com/1.0/http://api.facebook.com/1.0/facebook.xsd&quot;&gt;
-        {&amp;quot;application_name&amp;quot;:&amp;quot;Video Jukebox&amp;quot;,&amp;quot;callback_url&amp;quot;:&amp;quot;http:\/\/67.207.144.245\/&amp;quot;,&amp;quot;dev_mode&amp;quot;:0}
+        {&amp;quot;application_name&amp;quot;:&amp;quot;Video Jukebox&amp;quot;,&amp;quot;callback_url&amp;quot;:&amp;quot;http:\/\/67.207.144.245\/&amp;quot;,&amp;quot;dev_mode&amp;quot;:0,&amp;quot;canvas_name&amp;quot;:&amp;quot;my_canvas&amp;quot;}
     &lt;/admin_getAppProperties_response&gt;
     XML
   end
@@ -65,4 +73,4 @@ class FacebookAdminTest &lt; Test::Unit::TestCase
     XML
   end
     
-end
\ No newline at end of file
+end</diff>
      <filename>vendor/plugins/facebooker/test/facebook_admin_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,6 +3,7 @@ require File.dirname(__FILE__) + '/test_helper.rb'
 class FacebookCacheTest &lt; Test::Unit::TestCase
   def setup
     @session = Facebooker::Session.create('apikey', 'secretkey')
+    Facebooker.use_curl=false
   end
   
   def test_can_ask_facebook_to_store_fbml_in_a_named_reference</diff>
      <filename>vendor/plugins/facebooker/test/facebook_cache_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,6 +3,8 @@ require File.dirname(__FILE__) + '/test_helper.rb'
 class FacebookDataTest &lt; Test::Unit::TestCase
   def setup
     @session = Facebooker::Session.create('apikey', 'secretkey')
+    #make sure we use net::http since that's what the tests expect
+    Facebooker.use_curl=false
   end
   
   def test_can_ask_facebook_to_set_a_cookies
@@ -22,6 +24,22 @@ class FacebookDataTest &lt; Test::Unit::TestCase
     assert_equal 'Foo', cookies.first.name
     assert_equal 'Bar', cookies.first.value
   end
+  
+  def test_can_ask_facebook_to_set_a_preference
+    expect_http_posts_with_responses(example_set_preference_xml)
+    assert(@session.data.set_preference(0, 'hello'))
+  end
+    
+  def test_can_ask_facebook_to_get_preference
+    expect_http_posts_with_responses(example_get_preference_xml)
+    assert(@session.data.get_preference(0))
+  end
+  
+  def test_can_get_preference
+    mock_http = establish_session
+    mock_http.should_receive(:post_form).and_return(example_get_preference_xml).once.ordered(:posts)
+    assert_equal 'hello', @session.data.get_preference(0) 
+  end
 
   private
   def example_set_cookie_xml
@@ -47,4 +65,22 @@ class FacebookDataTest &lt; Test::Unit::TestCase
     &lt;/data_getCookie_response&gt;
     XML
   end
+  
+  def example_set_preference_xml
+    &lt;&lt;-XML
+    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+    &lt;data_setUserPreference_response xmlns=&quot;http://api.facebook.com/1.0/&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; 
+    xsi:schemaLocation=&quot;http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd&quot;/&gt;
+    XML
+  end
+
+  def example_get_preference_xml
+    &lt;&lt;-XML
+    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+    &lt;data_getUserPreference_response xmlns=&quot;http://api.facebook.com/1.0/&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; 
+    xsi:schemaLocation=&quot;http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd&quot;&gt;
+      hello
+    &lt;/data_getUserPreference_response&gt;
+    XML
+  end
 end
\ No newline at end of file</diff>
      <filename>vendor/plugins/facebooker/test/facebook_data_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -61,14 +61,12 @@ class TestFacebooker &lt; Test::Unit::TestCase
   end
 
   def test_can_get_current_users_friends
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_friends_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_friends_xml)
     assert_equal([222333, 1240079], @session.user.friends.map{|friend| friend.id})
   end
   
   def test_can_get_current_users_friend_lists
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_friend_lists_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_friend_lists_xml)
     assert_equal([12089150545, 16361710545], @session.user.friend_lists.map{|friend_list| friend_list.flid})
   end
   
@@ -99,10 +97,16 @@ class TestFacebooker &lt; Test::Unit::TestCase
     assert_equal('I rule', friend.status.message)
     assert_equal(nil, friend.hometown_location)
   end
-
+  
+  def test_can_handle_nil_data
+    friends = populate_session_friends_with_nil_data
+    friend = friends.detect{|f| f.id ==  222333}
+    assert_equal(nil,friend.current_location)
+    assert_equal(nil,friend.pic) 
+  end
+  
   def test_session_can_expire_on_server_and_client_handles_appropriately
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_session_expired_error_response).once.ordered(:posts)
+    expect_http_posts_with_responses(example_session_expired_error_response)
     assert_raises(Facebooker::Session::SessionExpired) {
       @session.user.friends
     }
@@ -110,8 +114,7 @@ class TestFacebooker &lt; Test::Unit::TestCase
 
   
   def test_can_publish_story_to_users_feed
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_publish_story_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_publish_story_xml)
     assert_nothing_raised {
       assert(@session.user.publish_story((s = Facebooker::Feed::Story.new; s.title = 'o hai'; s.body = '4srsly'; s)))
     }
@@ -119,21 +122,19 @@ class TestFacebooker &lt; Test::Unit::TestCase
   
   
   def test_can_publish_action_to_users_feed
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_publish_action_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_publish_action_xml)
     assert_nothing_raised {
       assert(@session.user.publish_action((s = Facebooker::Feed::Action.new; s.title = 'o hai'; s.body = '4srsly'; s)))
     }
   end
   
   def test_can_publish_templatized_action_to_users_feed
-     mock_http = establish_session
-     mock_http.should_receive(:post_form).and_return(example_publish_templatized_action_xml).once.ordered(:posts)
-     assert_nothing_raised {
-       action = Facebooker::Feed::TemplatizedAction.new
-       action.title_template = &quot;{actor} did something&quot;
-       assert(@session.user.publish_templatized_action(action))
-     }
+    expect_http_posts_with_responses(example_publish_templatized_action_xml)
+    assert_nothing_raised {
+      action = Facebooker::Feed::TemplatizedAction.new
+      action.title_template = &quot;{actor} did something&quot;
+      assert(@session.user.publish_templatized_action(action))
+    }
   end
   
   def test_can_publish_templatized_action_to_users_feed_with_params_as_string
@@ -153,41 +154,42 @@ class TestFacebooker &lt; Test::Unit::TestCase
     action.title_data=hash
     assert_equal action.to_params[:title_data],json_data
   end
-  
+
+  def test_can_deactivate_template_bundle_by_id
+    expect_http_posts_with_responses(example_deactivate_template_bundle_by_id_xml)
+    assert_equal true, @session.post('facebook.feed.deactivateTemplateBundleByID', :template_bundle_id =&gt; 123)
+  end
+
   def test_can_get_notifications_for_logged_in_user
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_notifications_get_xml).once.ordered(:posts)
-    assert_equal(&quot;1&quot;, @session.user.notifications.messages.unread)  
-    assert_equal(&quot;0&quot;, @session.user.notifications.pokes.unread)    
-    assert_equal(&quot;1&quot;, @session.user.notifications.shares.unread)        
+    expect_http_posts_with_responses(example_notifications_get_xml)
+    assert_equal(&quot;1&quot;, @session.user.notifications.messages.unread)
+    assert_equal(&quot;0&quot;, @session.user.notifications.pokes.unread)
+    assert_equal(&quot;1&quot;, @session.user.notifications.shares.unread)
   end
   
   def test_can_send_notifications
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_notifications_send_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_notifications_send_xml)
     assert_nothing_raised {
       user_ids = [123, 321]
       notification_fbml = &quot;O HAI!!!&quot;
       optional_email_fbml = &quot;This would be in the email.  If this is not passed, facebook sends no mailz!&quot;
       assert_equal('http://www.facebook.com/send_email.php?from=211031&amp;id=52', @session.send_notification(user_ids, notification_fbml, optional_email_fbml))
     }
-  end   
+  end
 
   def test_can_send_emails
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_notifications_send_email_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_notifications_send_email_xml)
     assert_nothing_raised {
       user_ids = [123, 321]
       text = &quot;Hi I am the text part of the email.&quot;
-      fbml = &quot;Hi I am the fbml version of the &lt;b&gt;email&lt;/a&gt;&quot;   
+      fbml = &quot;Hi I am the fbml version of the &lt;b&gt;email&lt;/a&gt;&quot;
       subject = &quot;Somethign you should really pay attention to.&quot;
       assert_equal('123,321', @session.send_email(user_ids, subject,text,fbml ))
     }
   end
   
   def test_can_find_friends_who_have_installed_app
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_app_users_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_app_users_xml)
     assert_equal(2, @session.user.friends_with_this_app.size)
     assert_equal([222333, 1240079], @session.user.friends_with_this_app.map{|f| f.id})
   end
@@ -200,7 +202,7 @@ class TestFacebooker &lt; Test::Unit::TestCase
       assert_not_nil(reloaded_session.instance_variable_get(iv_name))
     end
     assert_nil(reloaded_session.user.instance_variable_get(&quot;@friends&quot;))
-  end 
+  end
   
   def test_sessions_can_be_infinite_or_can_expire
     establish_session
@@ -213,22 +215,21 @@ class TestFacebooker &lt; Test::Unit::TestCase
   def test_session_can_tell_you_if_it_has_been_secured
     mock = flexmock(Net::HTTP).should_receive(:post_form).and_return(example_auth_token_xml).once.ordered(:posts)
     mock.should_receive(:post_form).and_return(example_get_session_xml.sub(/1173309298/, (Time.now + 60).to_i.to_s)).once.ordered(:posts)
-    @session.secure!    
+    @session.secure!
     assert(@session.secured?)
   end
   
-  def test_can_get_photos_by_pids    
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_get_photo_xml).once.ordered(:posts)
-    photos = @session.get_photos([97503428461115590, 97503428461115573])    
+  def test_can_get_photos_by_pids
+    expect_http_posts_with_responses(example_get_photo_xml)
+    photos = @session.get_photos([97503428461115590, 97503428461115573])
     assert_equal 2, photos.size
     assert_equal &quot;Rooftop barbecues make me act funny&quot;, photos.first.caption
+    assert_equal 97503428461115590, photos[0].id
   end
   
   def test_can_get_photos_by_subject_and_album
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_get_photo_xml).once.ordered(:posts)
-    photos = @session.get_photos(nil, 22701786, 97503428432802022 )    
+    expect_http_posts_with_responses(example_get_photo_xml)
+    photos = @session.get_photos(nil, 22701786, 97503428432802022 )
     assert_equal '97503428432802022', photos.first.aid
   end
   
@@ -238,43 +239,38 @@ class TestFacebooker &lt; Test::Unit::TestCase
   end
   
   def test_can_get_albums_for_user
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_user_albums_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_user_albums_xml)
     assert_equal('Summertime is Best', @session.user.albums.first.name)
     assert_equal(2, @session.user.albums.size)
   end
   
   def test_can_get_albums_by_album_ids
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_user_albums_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_user_albums_xml)
     albums = @session.get_albums([97503428432802022, 97503428432797817] )
     assert_equal('Summertime is Best', albums[0].name)
     assert_equal('Bonofon\'s Recital', albums[1].name)
   end
   
   def test_can_create_album
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_new_album_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_new_album_xml)
     assert_equal &quot;My Empty Album&quot;, @session.user.create_album(:name =&gt; &quot;My Empty Album&quot;, :location =&gt; &quot;Limboland&quot;).name
-  end  
+  end
   
   def test_can_upload_photo
     mock_http = establish_session
     mock_http.should_receive(:post_multipart_form).and_return(example_upload_photo_xml).once.ordered(:posts)
     f = Net::HTTP::MultipartPostFile.new(&quot;image.jpg&quot;, &quot;image/jpeg&quot;, &quot;RAW DATA&quot;)
     assert_equal &quot;Under the sunset&quot;, @session.user.upload_photo(f).caption
-  end  
+  end
   
   def test_can_get_photo_tags
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_photo_tags_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_photo_tags_xml)
     assert_instance_of Facebooker::Tag, @session.get_tags(:pids =&gt; 97503428461115571 ).first
   end
   
   # TODO: how to test that tags were created properly? Response doesn't contain much
   def test_can_tag_a_user_in_a_photo
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_add_tag_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_add_tag_xml)
     assert !@session.add_tags(pid = 97503428461115571, x= 30.0, y = 62.5, tag_uid = 1234567890).nil?
   end
   
@@ -282,26 +278,59 @@ class TestFacebooker &lt; Test::Unit::TestCase
   end
   
   def test_can_get_coordinates_for_photo_tags
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_photo_tags_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_photo_tags_xml)
     tag = @session.get_tags([97503428461115571]).first
     assert_equal ['65.4248', '16.8627'], tag.coordinates
   end
   
   def test_can_get_app_profile_fbml_for_user
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_get_fbml_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_get_fbml_xml)
     assert_match(/My profile!/, @session.user.profile_fbml)
   end
   
   def test_can_set_app_profile_fbml_for_user
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_set_fbml_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_set_fbml_xml)
     assert_nothing_raised {
       @session.user.profile_fbml = 'aha!'
     }
   end
   
+  def test_get_logged_in_user
+    expect_http_posts_with_responses(example_get_logged_in_user_xml)
+    assert_equal 1240077, @session.post('facebook.users.getLoggedInUser', :session_key =&gt; @session.session_key)
+  end
+
+  def test_pages_get_info
+    expect_http_posts_with_responses(example_pages_get_info_xml)
+    info = {
+      'page_id' =&gt; '4846711747',
+      'name' =&gt; 'Kronos Quartet',
+      'website' =&gt; 'http://www.kronosquartet.org',
+      'company_overview' =&gt; &quot;&quot;
+    }
+    assert_equal [info], @session.post('facebook.pages.getInfo', :fields =&gt; ['company_overview', 'website', 'name', 'page_id'].join(','), :page_ids =&gt; [4846711747].join(','))
+  end
+
+  def test_pages_is_admin_true
+    expect_http_posts_with_responses(example_pages_is_admin_true_xml)
+    assert_equal true, @session.post('facebook.pages.isAdmin', :page_id =&gt; 123)
+  end
+
+  def test_pages_is_admin_false
+    expect_http_posts_with_responses(example_pages_is_admin_false_xml)
+    assert_equal false, @session.post('facebook.pages.isAdmin', :page_id =&gt; 123)
+  end
+
+  def test_users_set_status_true
+    expect_http_posts_with_responses(example_users_set_status_true_xml)
+    assert_equal true, @session.post('facebook.users.setStatus', :uid =&gt; 123, :status =&gt; 'message')
+  end
+
+  def test_users_set_status_false
+    expect_http_posts_with_responses(example_users_set_status_false_xml)
+    assert_equal false, @session.post('facebook.users.setStatus', :uid =&gt; 123, :status =&gt; 'message')
+  end
+
   def test_desktop_apps_cannot_request_to_get_or_set_profile_fbml_for_any_user_other_than_logged_in_user
     mock_http = establish_session(@desktop_session)
     mock_http.should_receive(:post_form).and_return(example_friends_xml).once.ordered(:posts)
@@ -321,29 +350,71 @@ class TestFacebooker &lt; Test::Unit::TestCase
   end
 
   def populate_user_info_with_limited_fields
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_limited_user_info_xml).once.ordered(:posts)
+    expect_http_posts_with_responses(example_limited_user_info_xml)
     @session.user.populate(:affiliations, :status, :meeting_for)
   end
   
   def populate_session_friends
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_friends_xml).once.ordered(:posts)
-    mock_http.should_receive(:post_form).and_return(example_user_info_xml).once.ordered(:posts)
-    @session.user.friends!    
+    expect_http_posts_with_responses(example_friends_xml, example_user_info_xml)
+    @session.user.friends!
   end
   
   def populate_session_friends_with_limited_fields
-    mock_http = establish_session
-    mock_http.should_receive(:post_form).and_return(example_friends_xml).once.ordered(:posts)
-    mock_http.should_receive(:post_form).and_return(example_limited_user_info_xml).once.ordered(:posts)
-    @session.user.friends!(:affiliations, :status, :meeting_for)    
+    expect_http_posts_with_responses(example_friends_xml, example_limited_user_info_xml)
+    @session.user.friends!(:affiliations, :status, :meeting_for)
   end
-  
+     
+  def populate_session_friends_with_nil_data
+    expect_http_posts_with_responses(example_friends_xml, example_nil_user_info_xml)
+    @session.user.friends!(:name, :current_location, :pic)
+  end
+    
   def sample_args_to_post
     {:method=&gt;&quot;facebook.auth.createToken&quot;, :sig=&gt;&quot;18b3dc4f5258a63c0ad641eebd3e3930&quot;}
-  end  
+  end
+
+  def example_pages_get_info_xml
+    &lt;&lt;-XML
+    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+    &lt;pages_getInfo_response xmlns=&quot;http://api.facebook.com/1.0/&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd&quot; list=&quot;true&quot;&gt;
+      &lt;page&gt;
+        &lt;page_id&gt;4846711747&lt;/page_id&gt;
+        &lt;name&gt;Kronos Quartet&lt;/name&gt;
+        &lt;website&gt;http://www.kronosquartet.org&lt;/website&gt;
+        &lt;company_overview/&gt;
+      &lt;/page&gt;
+    &lt;/pages_getInfo_response&gt;
+    XML
+  end
   
+  def example_pages_is_admin_true_xml
+    &lt;&lt;-XML
+    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+      &lt;pages_isAdmin_response xmlns=&quot;http://api.facebook.com/1.0/&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd&quot;&gt;1&lt;/pages_isAdmin_response&gt;
+    XML
+  end
+
+  def example_pages_is_admin_false_xml
+    &lt;&lt;-XML
+    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+      &lt;pages_isAdmin_response xmlns=&quot;http://api.facebook.com/1.0/&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd&quot;&gt;0&lt;/pages_isAdmin_response&gt;
+    XML
+  end
+
+  def example_users_set_status_true_xml
+    &lt;&lt;-XML
+    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+      &lt;users_setStatus_response xmlns=&quot;http://api.facebook.com/1.0/&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd&quot;&gt;1&lt;/users_setStatus_response&gt;
+    XML
+  end
+
+  def example_users_set_status_false_xml
+    &lt;&lt;-XML
+    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+      &lt;users_setStatus_response xmlns=&quot;http://api.facebook.com/1.0/&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd&quot;&gt;0&lt;/users_setStatus_response&gt;
+    XML
+  end
+
   def example_set_fbml_xml
     &lt;&lt;-XML
     &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
@@ -432,7 +503,14 @@ class TestFacebooker &lt; Test::Unit::TestCase
     &lt;/feed_publishTemplatizedAction_response&gt;
     XML
   end
-  
+
+  def example_deactivate_template_bundle_by_id_xml
+    &lt;&lt;-XML
+    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+    &lt;feed_deactivateTemplateBundleByID_response xmlns=&quot;http://api.facebook.com/1.0/&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://api.facebook.com/1.0/&quot;&gt;1&lt;/feed_deactivateTemplateBundleByID_response&gt;
+    XML
+  end
+
   def example_user_info_xml
     &lt;&lt;-XML
     &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
@@ -571,6 +649,21 @@ class TestFacebooker &lt; Test::Unit::TestCase
   end
 
   
+  def example_nil_user_info_xml
+    &lt;&lt;-XML
+    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+    &lt;users_getInfo_response xmlns=&quot;http://api.facebook.com/1.0/&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd&quot; list=&quot;true&quot;&gt;
+      &lt;user&gt;
+        &lt;uid&gt;222333&lt;/uid&gt;
+        &lt;name&gt;Kevin Lochner&lt;/name&gt;
+        &lt;current_location xsi:nil=&quot;true&quot;/&gt;
+        &lt;pic xsi:nil=&quot;true&quot;/&gt;
+      &lt;/user&gt;
+    &lt;/users_getInfo_response&gt;    
+    XML
+  end
+
+  
   def example_friends_xml
     &lt;&lt;-XML
     &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</diff>
      <filename>vendor/plugins/facebooker/test/facebooker_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -26,6 +26,18 @@ class TestFacebooker &lt; Test::Unit::TestCase
     assert_equal(&quot;Blob&quot;, Thing.from_hash(h).name)
   end
   
+  def test_ignores_non_model_keys
+    h = {:name =&gt; &quot;Blob&quot;, :job =&gt; &quot;Monster&quot;, :not_there=&gt;true}
+    assert_equal(&quot;Blob&quot;, Thing.from_hash(h).name)    
+  end
+  
+  def test_logs_non_model_keys
+    flexmock(Facebooker::Logging).should_receive(:log_info)
+    h = {:name =&gt; &quot;Blob&quot;, :job =&gt; &quot;Monster&quot;, :not_there=&gt;true}
+    Thing.from_hash(h)
+  end
+    
+  
   def test_if_no_hash_is_given_to_model_constructor_no_attributes_are_set
     assert_nothing_raised {
       t = Thing.new</diff>
      <filename>vendor/plugins/facebooker/test/model_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,6 +6,7 @@ require 'action_controller/test_process'
 require 'active_record'
 require File.dirname(__FILE__)+'/../init'
 require 'facebooker/rails/controller'
+require 'facebooker/rails/helpers/fb_connect'
 require 'facebooker/rails/helpers'
 require 'facebooker/rails/publisher'
 
@@ -74,7 +75,6 @@ class TestPublisher &lt; Facebooker::Rails::Publisher
   def profile_update(to,f)
     send_as :profile
     recipients to
-    from f
     profile &quot;profile&quot;
     profile_action &quot;profile_action&quot;
     mobile_profile &quot;mobile_profile&quot;
@@ -93,7 +93,6 @@ class TestPublisher &lt; Facebooker::Rails::Publisher
   
   def ref_update(user)
     send_as :ref
-    from user
     fbml &quot;fbml&quot;
     handle &quot;handle&quot;
   end
@@ -104,11 +103,34 @@ class TestPublisher &lt; Facebooker::Rails::Publisher
     full_story_template &quot;{*actor*} did a lot&quot;,&quot;This is the full body&quot;,:img=&gt;{:some_params=&gt;true}
   end
   
+  def simple_user_action_template
+    one_line_story_template &quot;{*actor*} did stuff with {*friend*}&quot;    
+  end
+  
+  def user_action_with_action_links_template
+    one_line_story_template &quot;{*actor*} did stuff with {*friend*}&quot;
+    short_story_template &quot;{*actor*} has a title {*friend*}&quot;, render(:inline=&gt;&quot;This is a test render&quot;)
+    full_story_template &quot;{*actor*} did a lot&quot;,&quot;This is the full body&quot;,:img=&gt;{:some_params=&gt;true}
+    action_links action_link(&quot;Source&quot;,&quot;HREF&quot;)
+  end
+  
   def user_action(user)
     send_as :user_action
     from user
     data :friend=&gt;&quot;Mike&quot;
   end
+  def user_action_with_story_size(user)
+    send_as :user_action
+    from user
+    story_size ONE_LINE
+    story_size FULL
+    story_size SHORT
+    data :friend=&gt;&quot;Mike&quot;
+  end
+  def user_action_no_data(user)
+    send_as :user_action
+    from user
+  end
   
   def no_send_as(to)
     recipients to
@@ -121,16 +143,85 @@ class TestPublisher &lt; Facebooker::Rails::Publisher
   
 end
 
+class FacebookTemplateTest &lt; Test::Unit::TestCase
+  FacebookTemplate = Facebooker::Rails::Publisher::FacebookTemplate
+  
+  def setup
+    super
+    @template = mock(&quot;facebook template&quot;)
+    FacebookTemplate.stubs(:register).returns(@template)
+    FacebookTemplate.clear_cache!
+  end
+  
+  def test_find_or_register_calls_find_cached
+    FacebookTemplate.expects(:find_cached).with(TestPublisher,&quot;simple_user_action&quot;).returns(@template)
+    assert_equal FacebookTemplate.for_class_and_method(TestPublisher,&quot;simple_user_action&quot;),@template
+  end  
+  
+  def test_find_cached_should_use_cached_if_it_exists
+    FacebookTemplate.cache(TestPublisher,&quot;simple_user_action&quot;,@template)
+    assert_equal FacebookTemplate.find_cached(TestPublisher,&quot;simple_user_action&quot;), @template
+    
+  end
+  
+  def test_find_cached_should_call_find_in_db_if_not_in_cache
+    FacebookTemplate.expects(:find_in_db).with(TestPublisher,&quot;simple_user_action&quot;).returns(@template)
+    assert_equal FacebookTemplate.find_cached(TestPublisher,&quot;simple_user_action&quot;), @template
+  end
+  
+  def test_find_in_db_should_run_find
+    FacebookTemplate.expects(:find_by_template_name).with(&quot;TestPublisher::simple_user_action&quot;).returns(@template)
+    @template.stubs(:template_changed?).returns(false)
+    assert_equal FacebookTemplate.find_in_db(TestPublisher,&quot;simple_user_action&quot;), @template
+  end
+  
+  def test_find_in_db_should_register_if_not_found
+    FacebookTemplate.expects(:find_by_template_name).with(&quot;TestPublisher::simple_user_action&quot;).returns(nil)
+    FacebookTemplate.expects(:register).with(TestPublisher,&quot;simple_user_action&quot;).returns(@template)
+    FacebookTemplate.find_cached(TestPublisher,&quot;simple_user_action&quot;)
+    
+  end
+  
+  def test_find_in_db_should_check_for_change_if_found
+    FacebookTemplate.stubs(:find_by_template_name).returns(@template)
+    FacebookTemplate.stubs(:hashed_content).returns(&quot;MY CONTENT&quot;)
+    @template.expects(:template_changed?).with(&quot;MY CONTENT&quot;).returns(false)
+    FacebookTemplate.find_in_db(TestPublisher,&quot;simple_user_action&quot;)  
+  end
+  
+  def test_find_in_db_should_destroy_old_record_if_changed
+    FacebookTemplate.stubs(:find_by_template_name).returns(@template)
+    FacebookTemplate.stubs(:hashed_content).returns(&quot;MY CONTENT&quot;)
+    @template.stubs(:template_changed?).returns(true)
+    @template.expects(:destroy)
+    FacebookTemplate.find_in_db(TestPublisher,&quot;simple_user_action&quot;)  
+  end
+  
+  def test_find_in_db_should_re_register_if_changed
+    FacebookTemplate.stubs(:find_by_template_name).with(&quot;TestPublisher::simple_user_action&quot;).returns(@template)
+    FacebookTemplate.stubs(:hashed_content).returns(&quot;MY CONTENT&quot;)
+    @template.stubs(:template_changed?).returns(true)
+    @template.stubs(:destroy)
+    FacebookTemplate.expects(:register).with(TestPublisher,&quot;simple_user_action&quot;).returns(@template)
+    FacebookTemplate.find_in_db(TestPublisher,&quot;simple_user_action&quot;)    
+  end
+end
 
 class PublisherTest &lt; Test::Unit::TestCase
+  FacebookTemplate = Facebooker::Rails::Publisher::FacebookTemplate
   
   def setup
+    super
     @user = Facebooker::User.new
     @user.id=4
     @session = &quot;session&quot;
     @user.stubs(:session).returns(@session)
   end
   
+  def teardown
+    super
+  end
+  
   def test_create_action
     action=TestPublisher.create_action(@user)
     assert_equal Facebooker::Feed::Action,action.class
@@ -208,29 +299,17 @@ class PublisherTest &lt; Test::Unit::TestCase
   
   
   def test_deliver_profile
+    Facebooker::User.stubs(:new).returns(@user)
     @user.expects(:set_profile_fbml).with('profile', 'mobile_profile', 'profile_action',nil)
     TestPublisher.deliver_profile_update(@user,@user)    
   end
   
    def test_deliver_profile_with_main
+    Facebooker::User.stubs(:new).returns(@user)
     @user.expects(:set_profile_fbml).with('profile', 'mobile_profile', 'profile_action','profile_main')
     TestPublisher.deliver_profile_update_with_profile_main(@user,@user)    
   end
   
-  def test_deliver_profile_update_same_session
-    @user.expects(:set_profile_fbml)
-    TestPublisher.deliver_profile_update(@user,@user)
-  end
-  def test_deliver_profile_update_same_session
-    @from_user = Facebooker::User.new
-    @new_user = Facebooker::User.new
-    @from_user.id =7
-    @session2 = Facebooker::Session.new(&quot;&quot;,&quot;&quot;)
-    @from_user.stubs(:session).returns(@session2)
-    Facebooker::User.expects(:new).with(@user,@from_user.session).returns(@new_user)
-    @new_user.expects(:set_profile_fbml)
-    TestPublisher.deliver_profile_update(@user,@from_user)
-  end
   
   def test_create_ref_update
     p=TestPublisher.create_ref_update(@user)
@@ -240,6 +319,7 @@ class PublisherTest &lt; Test::Unit::TestCase
   end
   
   def test_deliver_ref_update
+    Facebooker::Session.stubs(:create).returns(@session)
     @server_cache=&quot;server_cache&quot;
     @session.expects(:server_cache).returns(@server_cache)
     @server_cache.expects(:set_ref_handle).with(&quot;handle&quot;,&quot;fbml&quot;)
@@ -247,28 +327,63 @@ class PublisherTest &lt; Test::Unit::TestCase
   end
   
   def test_register_user_action
+   Facebooker::Rails::Publisher::FacebookTemplate.expects(:register)
+    TestPublisher.register_user_action
+  end
+  def test_register_user_action_with_action_links
     ActionController::Base.append_view_path(&quot;./test/../../app/views&quot;)
-    Facebooker::Session.any_instance.expects(:register_template_bundle)
     Facebooker::Rails::Publisher::FacebookTemplate.expects(:register)
-    TestPublisher.register_user_action
+    TestPublisher.register_user_action_with_action_links
   end
   
   def test_create_user_action
-      @from_user = Facebooker::User.new
-      @session = Facebooker::Session.new(&quot;&quot;,&quot;&quot;)
-      @from_user.stubs(:session).returns(@session)
-      ua=TestPublisher.create_user_action(@from_user)
-      assert_equal &quot;user_action&quot;,ua.template_name
-    end
+    @from_user = Facebooker::User.new
+    @session = Facebooker::Session.new(&quot;&quot;,&quot;&quot;)
+    @from_user.stubs(:session).returns(@session)
+    Facebooker::Rails::Publisher::FacebookTemplate.expects(:bundle_id_for_class_and_method).
+                                                   with(TestPublisher,'user_action').
+                                                   returns(20309041537)
+    ua = TestPublisher.create_user_action(@from_user)
+    assert_equal &quot;user_action&quot;, ua.template_name
+  end
   
   def test_publisher_user_action
     @from_user = Facebooker::User.new
     @session = Facebooker::Session.new(&quot;&quot;,&quot;&quot;)
     @from_user.stubs(:session).returns(@session)
     @session.expects(:publish_user_action).with(20309041537,{:friend=&gt;&quot;Mike&quot;},nil,nil)
-    Facebooker::Rails::Publisher::FacebookTemplate.expects(:for).returns(20309041537)
+    
+    Facebooker::Rails::Publisher::FacebookTemplate.expects(:bundle_id_for_class_and_method).
+                                                   with(TestPublisher, 'user_action').
+                                                   returns(20309041537)
+    # pseudo_template = Struct.new(:bundle_id, :content_hash).new(20309041537, '')
+    # pseudo_template.expects(:matches_content?).returns(true)
+    # Facebooker::Rails::Publisher::FacebookTemplate.expects(:for).returns(pseudo_template)
     TestPublisher.deliver_user_action(@from_user)
   end
+  
+  def test_publish_user_action_with_story_size
+    @from_user = Facebooker::User.new
+    @session = Facebooker::Session.new(&quot;&quot;,&quot;&quot;)
+    @from_user.stubs(:session).returns(@session)
+    @session.expects(:publish_user_action).with(20309041537,{:friend=&gt;&quot;Mike&quot;, :story_size=&gt;2},nil,nil)
+    
+    Facebooker::Rails::Publisher::FacebookTemplate.expects(:bundle_id_for_class_and_method).
+                                                   with(TestPublisher, 'user_action_with_story_size').
+                                                   returns(20309041537)
+    TestPublisher.deliver_user_action_with_story_size(@from_user)
+    
+  end
+  
+  def test_publishing_user_data_no_action_gives_nil_hash
+    @from_user = Facebooker::User.new
+    @session = Facebooker::Session.new(&quot;&quot;,&quot;&quot;)
+    @from_user.stubs(:session).returns(@session)
+    @session.expects(:publish_user_action).with(20309041537,{},nil,nil)
+    
+    Facebooker::Rails::Publisher::FacebookTemplate.stubs(:bundle_id_for_class_and_method).returns(20309041537)
+    TestPublisher.deliver_user_action_no_data(@from_user)
+  end
   def test_no_sends_as_raises
     assert_raises(Facebooker::Rails::Publisher::UnspecifiedBodyType) {
       TestPublisher.deliver_no_send_as(@user)
@@ -281,6 +396,7 @@ class PublisherTest &lt; Test::Unit::TestCase
     }
   end
   
+  
   def test_keeps_class_method_missing
     assert_raises(NoMethodError) {
       TestPublisher.fake
@@ -292,6 +408,18 @@ class PublisherTest &lt; Test::Unit::TestCase
     }
   end
   
+  def test_image_urls
+    Facebooker.expects(:facebook_path_prefix).returns(&quot;/mike&quot;)
+    assert_equal({:src =&gt; '/images/image.png', :href =&gt; 'raw_string' },
+        TestPublisher.new.image('image.png', 'raw_string'))
+    assert_equal({:src =&gt; '/images/image.png', :href =&gt; 'http://apps.facebook.com/mike/pokes/do/1' },
+        TestPublisher.new.image('image.png', {:controller =&gt; :pokes, :action =&gt; :do, :id =&gt; 1}))
+  end
+  
+  def test_action_link
+    assert_equal({:text=&gt;&quot;text&quot;, :href=&gt;&quot;href&quot;}, TestPublisher.new.action_link(&quot;text&quot;,&quot;href&quot;))
+  end
+  
   def test_default_url_options
     Facebooker.expects(:facebook_path_prefix).returns(&quot;/mike&quot;)
     assert_equal({:host=&gt;&quot;apps.facebook.com/mike&quot;},TestPublisher.default_url_options)
@@ -328,4 +456,3 @@ class PublisherTest &lt; Test::Unit::TestCase
     assert_equal &quot;true&quot;,notification.fbml
   end
 end
-  
\ No newline at end of file</diff>
      <filename>vendor/plugins/facebooker/test/publisher_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,9 @@
 require File.dirname(__FILE__) + '/test_helper.rb'
-require 'ruby-debug'
 begin
   require 'action_controller'
   require 'action_controller/test_process'
   require 'facebooker/rails/controller'
+  require 'facebooker/rails/helpers/fb_connect'
   require 'facebooker/rails/helpers'
   require 'facebooker/rails/facebook_form_builder'
   require File.dirname(__FILE__)+'/../init'
@@ -113,6 +113,15 @@ begin
     end
   end
   
+  class ControllerWhichFails &lt; ActionController::Base
+    def pass
+      render :text=&gt;''
+    end
+    def fail
+      raise &quot;I'm failing&quot;
+    end
+  end
+  
   # you can't use asset_recognize, because it can't pass parameters in to the requests
   class UrlRecognitionTests &lt; Test::Unit::TestCase
     def test_detects_in_canvas
@@ -261,7 +270,7 @@ class RailsIntegrationTest &lt; Test::Unit::TestCase
   
    def test_named_route_includes_new_canvas_path_when_in_new_canvas
       get :named_route_test, example_rails_params_including_fb.merge(&quot;fb_sig_in_new_facebook&quot;=&gt;&quot;1&quot;)
-      assert_equal &quot;http://apps.new.facebook.com/root/comments&quot;,@response.body
+      assert_equal &quot;http://apps.facebook.com/root/comments&quot;,@response.body
     end
 
   def test_if_controller_requires_facebook_authentication_unauthenticated_requests_will_redirect
@@ -326,11 +335,20 @@ class RailsIntegrationTest &lt; Test::Unit::TestCase
     assert_equal(744961110, @controller.facebook_session.user.id)
   end
 
-  def test_existing_secured_session_is_used_if_available_and_facebook_params_session_key_is_nil
+  def test_existing_secured_session_is_NOT_used_if_available_and_facebook_params_session_key_is_nil_and_in_canvas
     session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
     session.secure_with!(&quot;a session key&quot;, &quot;1111111&quot;, Time.now.to_i + 60)
     get :index, example_rails_params_including_fb.merge(&quot;fb_sig_session_key&quot; =&gt; ''), {:facebook_session =&gt; session}
     
+    assert_equal(744961110, @controller.facebook_session.user.id)
+  end
+
+  def test_existing_secured_session_IS_used_if_available_and_facebook_params_session_key_is_nil_and_NOT_in_canvas
+    @contoller = PlainOldRailsController.new
+    session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
+    session.secure_with!(&quot;a session key&quot;, &quot;1111111&quot;, Time.now.to_i + 60)
+    get :index,{}, {:facebook_session =&gt; session}
+    
     assert_equal(1111111, @controller.facebook_session.user.id)
   end
 
@@ -340,11 +358,38 @@ class RailsIntegrationTest &lt; Test::Unit::TestCase
     modified_params.delete('fb_sig_session_key')
     modified_params['auth_token'] = auth_token
     session_mock = flexmock(session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY']))
-    session_mock.should_receive(:post).with('facebook.auth.getSession', :auth_token =&gt; auth_token).once.and_return({}).ordered
+    session_params = { 'session_key' =&gt; '123', 'uid' =&gt; '321' }
+    session_mock.should_receive(:post).with('facebook.auth.getSession', :auth_token =&gt; auth_token).once.and_return(session_params).ordered
     flexmock(@controller).should_receive(:new_facebook_session).once.and_return(session).ordered
     get :index, modified_params
   end
   
+  def test_session_secured_with_auth_token_if_cookies_expired
+      auth_token = 'ohaiauthtokenhere111'
+      modified_params = example_rails_params_including_fb
+      modified_params.delete('fb_sig_session_key')
+      modified_params['auth_token'] = auth_token
+      session_mock = flexmock(session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY']))
+      session_params = { 'session_key' =&gt; '123', 'uid' =&gt; '321' }
+      session_mock.should_receive(:post).with('facebook.auth.getSession', :auth_token =&gt; auth_token).once.and_return(session_params).ordered
+      flexmock(@controller).should_receive(:new_facebook_session).once.and_return(session).ordered
+      expired_cookie_hash_for_auth.each {|k,v| @request.cookies[ENV['FACEBOOK_API_KEY']+k] = CGI::Cookie.new(ENV['FACEBOOK_API_KEY']+k,v)} 
+      get :index, modified_params
+      assert_equal(321, @controller.facebook_session.user.id)
+  end
+          
+  def test_session_can_be_secured_with_cookies
+    cookie_hash_for_auth.each {|k,v| @request.cookies[ENV['FACEBOOK_API_KEY']+k] = CGI::Cookie.new(ENV['FACEBOOK_API_KEY']+k,v)} 
+    get :index, example_rails_params_for_fb_connect
+    assert_equal(77777, @controller.facebook_session.user.id)
+    end
+  
+  def test_session_does_NOT_secure_with_expired_cookies
+    expired_cookie_hash_for_auth.each {|k,v| @request.cookies[ENV['FACEBOOK_API_KEY']+k] = CGI::Cookie.new(ENV['FACEBOOK_API_KEY']+k,v)} 
+    get :index, example_rails_params_for_fb_connect
+    assert_nil(@controller.facebook_session)
+  end
+      
   def test_user_friends_can_be_populated_from_facebook_params_if_available
     get :index, example_rails_params_including_fb
     assert_not_nil(friends = @controller.facebook_session.user.friends)
@@ -403,21 +448,33 @@ class RailsIntegrationTest &lt; Test::Unit::TestCase
   
   def test_publisher_test_error
     get :publisher_test_error, example_rails_params_including_fb
-    assert_equal &quot;{\&quot;errorCode\&quot;: 1, \&quot;errorTitle\&quot;: \&quot;Title\&quot;, \&quot;errorMessage\&quot;: \&quot;Body\&quot;}&quot;,@response.body
+    assert_equal JSON.parse(&quot;{\&quot;errorCode\&quot;: 1, \&quot;errorTitle\&quot;: \&quot;Title\&quot;, \&quot;errorMessage\&quot;: \&quot;Body\&quot;}&quot;), JSON.parse(@response.body)
   end
   
   def test_publisher_test_interface
     get :publisher_test_interface, example_rails_params_including_fb
-    assert_equal &quot;{\&quot;method\&quot;: \&quot;publisher_getInterface\&quot;, \&quot;content\&quot;: {\&quot;fbml\&quot;: \&quot;This is a test\&quot;, \&quot;publishEnabled\&quot;: false, \&quot;commentEnabled\&quot;: true}}&quot;,@response.body
+    assert_equal JSON.parse(&quot;{\&quot;method\&quot;: \&quot;publisher_getInterface\&quot;, \&quot;content\&quot;: {\&quot;fbml\&quot;: \&quot;This is a test\&quot;, \&quot;publishEnabled\&quot;: false, \&quot;commentEnabled\&quot;: true}}&quot;), JSON.parse(@response.body)
   end
   
   def test_publisher_test_reponse
     get :publisher_test_response, example_rails_params_including_fb
-    assert_equal &quot;{\&quot;method\&quot;: \&quot;publisher_getFeedStory\&quot;, \&quot;content\&quot;: {\&quot;feed\&quot;: {\&quot;template_data\&quot;: {\&quot;params\&quot;: true}, \&quot;template_id\&quot;: 1234}}}&quot;,@response.body
+    assert_equal JSON.parse(&quot;{\&quot;method\&quot;: \&quot;publisher_getFeedStory\&quot;, \&quot;content\&quot;: {\&quot;feed\&quot;: {\&quot;template_data\&quot;: {\&quot;params\&quot;: true}, \&quot;template_id\&quot;: 1234}}}&quot;), JSON.parse(@response.body)
     
   end
   
   private
+  def example_rails_params_for_fb_connect
+    {&quot;action&quot;=&gt;&quot;index&quot;, &quot;controller&quot;=&gt;&quot;controller_which_requires_facebook_authentication&quot;}
+  end
+
+  def expired_cookie_hash_for_auth
+    {&quot;_ss&quot; =&gt; &quot;not_used&quot;, &quot;_session_key&quot;=&gt; &quot;whatever&quot;, &quot;_user&quot;=&gt;&quot;77777&quot;, &quot;_expires&quot;=&gt;&quot;#{1.day.ago.to_i}&quot;}
+  end
+
+  def cookie_hash_for_auth
+    {&quot;_ss&quot; =&gt; &quot;not_used&quot;, &quot;_session_key&quot;=&gt; &quot;whatever&quot;, &quot;_user&quot;=&gt;&quot;77777&quot;, &quot;_expires&quot;=&gt;&quot;#{1.day.from_now.to_i}&quot;}
+  end
+   
   def example_rails_params_including_fb_for_user_not_logged_into_application
     {&quot;fb_sig_time&quot;=&gt;&quot;1186588275.5988&quot;, &quot;fb_sig&quot;=&gt;&quot;7371a6400329b229f800a5ecafe03b0a&quot;, &quot;action&quot;=&gt;&quot;index&quot;, &quot;fb_sig_in_canvas&quot;=&gt;&quot;1&quot;, &quot;controller&quot;=&gt;&quot;controller_which_requires_facebook_authentication&quot;, &quot;fb_sig_added&quot;=&gt;&quot;0&quot;, &quot;fb_sig_api_key&quot;=&gt;&quot;b6c9c857ac543ca806f4d3187cd05e09&quot;}
   end
@@ -472,21 +529,26 @@ class RailsHelperTest &lt; Test::Unit::TestCase
     include ActionView::Helpers::CaptureHelper
     include ActionView::Helpers::TagHelper
     include ActionView::Helpers::AssetTagHelper
+    include ActionView::Helpers::JavaScriptHelper
     include Facebooker::Rails::Helpers
-    attr_accessor :flash
+    attr_accessor :flash, :output_buffer
     def initialize
       @flash={}
       @template = self
       @content_for_test_param=&quot;Test Param&quot;
+      @output_buffer = &quot;&quot;
     end
     #used for stubbing out the form builder
     def url_for(arg)
       arg
     end
+    def request
+      ActionController::TestRequest.new
+    end
     def fields_for(*args)
       &quot;&quot;
     end
-    
+        
   end 
 
   # used for capturing the contents of some of the helper tests
@@ -505,11 +567,11 @@ class RailsHelperTest &lt; Test::Unit::TestCase
   end
   
   def test_fb_profile_pic
-    assert_equal &quot;&lt;fb:profile-pic uid=\&quot;1234\&quot; /&gt;&quot;, @h.fb_profile_pic(&quot;1234&quot;)
+    assert_equal &quot;&lt;fb:profile-pic uid=\&quot;1234\&quot;&gt;&lt;/fb:profile-pic&gt;&quot;, @h.fb_profile_pic(&quot;1234&quot;)
   end
 
   def test_fb_profile_pic_with_valid_size
-    assert_equal &quot;&lt;fb:profile-pic size=\&quot;small\&quot; uid=\&quot;1234\&quot; /&gt;&quot;, @h.fb_profile_pic(&quot;1234&quot;, :size =&gt; :small)
+    assert_equal &quot;&lt;fb:profile-pic size=\&quot;small\&quot; uid=\&quot;1234\&quot;&gt;&lt;/fb:profile-pic&gt;&quot;, @h.fb_profile_pic(&quot;1234&quot;, :size =&gt; :small)
   end
 
   def test_fb_profile_pic_with_invalid_size
@@ -517,12 +579,12 @@ class RailsHelperTest &lt; Test::Unit::TestCase
   end
 
   def test_fb_photo
-    assert_equal &quot;&lt;fb:photo pid=\&quot;1234\&quot; /&gt;&quot;,@h.fb_photo(&quot;1234&quot;)
+    assert_equal &quot;&lt;fb:photo pid=\&quot;1234\&quot;&gt;&lt;/fb:photo&gt;&quot;,@h.fb_photo(&quot;1234&quot;)
   end
 
   def test_fb_photo_with_object_responding_to_photo_id
     photo = flexmock(&quot;photo&quot;, :photo_id =&gt; &quot;5678&quot;)
-    assert_equal &quot;&lt;fb:photo pid=\&quot;5678\&quot; /&gt;&quot;, @h.fb_photo(photo)
+    assert_equal &quot;&lt;fb:photo pid=\&quot;5678\&quot;&gt;&lt;/fb:photo&gt;&quot;, @h.fb_photo(photo)
   end
 
   def test_fb_photo_with_invalid_size
@@ -538,14 +600,14 @@ class RailsHelperTest &lt; Test::Unit::TestCase
   end
 
   def test_fb_photo_with_valid_align_value
-    assert_equal &quot;&lt;fb:photo align=\&quot;right\&quot; pid=\&quot;1234\&quot; /&gt;&quot;,@h.fb_photo(&quot;1234&quot;, :align =&gt; :right)
+    assert_equal &quot;&lt;fb:photo align=\&quot;right\&quot; pid=\&quot;1234\&quot;&gt;&lt;/fb:photo&gt;&quot;,@h.fb_photo(&quot;1234&quot;, :align =&gt; :right)
   end
 
   def test_fb_photo_with_class
-    assert_equal &quot;&lt;fb:photo class=\&quot;picky\&quot; pid=\&quot;1234\&quot; /&gt;&quot;,@h.fb_photo(&quot;1234&quot;, :class =&gt; :picky)
+    assert_equal &quot;&lt;fb:photo class=\&quot;picky\&quot; pid=\&quot;1234\&quot;&gt;&lt;/fb:photo&gt;&quot;,@h.fb_photo(&quot;1234&quot;, :class =&gt; :picky)
   end
   def test_fb_photo_with_style
-    assert_equal &quot;&lt;fb:photo pid=\&quot;1234\&quot; style=\&quot;some=css;put=here;\&quot; /&gt;&quot;,@h.fb_photo(&quot;1234&quot;, :style =&gt; &quot;some=css;put=here;&quot;)
+    assert_equal &quot;&lt;fb:photo pid=\&quot;1234\&quot; style=\&quot;some=css;put=here;\&quot;&gt;&lt;/fb:photo&gt;&quot;,@h.fb_photo(&quot;1234&quot;, :style =&gt; &quot;some=css;put=here;&quot;)
   end
   
   def test_fb_prompt_permission_valid_no_callback
@@ -560,22 +622,30 @@ class RailsHelperTest &lt; Test::Unit::TestCase
     assert_raises(ArgumentError) {@h.fb_prompt_permission(&quot;invliad&quot;, &quot;a message&quot;)}
     
   end
+  
+  def test_fb_add_profile_section
+    assert_equal &quot;&lt;fb:add-section-button section=\&quot;profile\&quot; /&gt;&quot;,@h.fb_add_profile_section
+  end
+
+  def test_fb_add_info_section
+    assert_equal &quot;&lt;fb:add-section-button section=\&quot;info\&quot; /&gt;&quot;,@h.fb_add_info_section
+  end
 
   def test_fb_name_with_invalid_key
     assert_raises(ArgumentError) {@h.fb_name(1234, :sizee =&gt; false)}
   end
 
   def test_fb_name
-    assert_equal &quot;&lt;fb:name uid=\&quot;1234\&quot; /&gt;&quot;,@h.fb_name(&quot;1234&quot;)
+    assert_equal &quot;&lt;fb:name uid=\&quot;1234\&quot;&gt;&lt;/fb:name&gt;&quot;,@h.fb_name(&quot;1234&quot;)
   end
     
   def test_fb_name_with_transformed_key
-    assert_equal &quot;&lt;fb:name uid=\&quot;1234\&quot; useyou=\&quot;true\&quot; /&gt;&quot;, @h.fb_name(1234, :use_you =&gt; true)
+    assert_equal &quot;&lt;fb:name uid=\&quot;1234\&quot; useyou=\&quot;true\&quot;&gt;&lt;/fb:name&gt;&quot;, @h.fb_name(1234, :use_you =&gt; true)
   end
   
   def test_fb_name_with_user_responding_to_facebook_id
     user = flexmock(&quot;user&quot;, :facebook_id =&gt; &quot;5678&quot;)
-    assert_equal &quot;&lt;fb:name uid=\&quot;5678\&quot; /&gt;&quot;, @h.fb_name(user)
+    assert_equal &quot;&lt;fb:name uid=\&quot;5678\&quot;&gt;&lt;/fb:name&gt;&quot;, @h.fb_name(user)
   end
   
   def test_fb_name_with_invalid_key
@@ -671,16 +741,16 @@ class RailsHelperTest &lt; Test::Unit::TestCase
   end
   
   def test_fb_pronoun
-    assert_equal &quot;&lt;fb:pronoun uid=\&quot;1234\&quot; /&gt;&quot;, @h.fb_pronoun(1234)
+    assert_equal &quot;&lt;fb:pronoun uid=\&quot;1234\&quot;&gt;&lt;/fb:pronoun&gt;&quot;, @h.fb_pronoun(1234)
   end
   
   def test_fb_pronoun_with_transformed_key
-    assert_equal &quot;&lt;fb:pronoun uid=\&quot;1234\&quot; usethey=\&quot;true\&quot; /&gt;&quot;, @h.fb_pronoun(1234, :use_they =&gt; true)
+    assert_equal &quot;&lt;fb:pronoun uid=\&quot;1234\&quot; usethey=\&quot;true\&quot;&gt;&lt;/fb:pronoun&gt;&quot;, @h.fb_pronoun(1234, :use_they =&gt; true)
   end
   
   def test_fb_pronoun_with_user_responding_to_facebook_id
     user = flexmock(&quot;user&quot;, :facebook_id =&gt; &quot;5678&quot;)
-    assert_equal &quot;&lt;fb:pronoun uid=\&quot;5678\&quot; /&gt;&quot;, @h.fb_pronoun(user)
+    assert_equal &quot;&lt;fb:pronoun uid=\&quot;5678\&quot;&gt;&lt;/fb:pronoun&gt;&quot;, @h.fb_pronoun(user)
   end
   
   def test_fb_pronoun_with_invalid_key
@@ -691,7 +761,7 @@ class RailsHelperTest &lt; Test::Unit::TestCase
     @h.expects(:capture).returns(&quot;wall content&quot;)
     @h.fb_wall do 
     end
-    assert_equal &quot;&lt;fb:wall&gt;wall content&lt;/fb:wall&gt;&quot;,_erbout
+    assert_equal &quot;&lt;fb:wall&gt;wall content&lt;/fb:wall&gt;&quot;,@h.output_buffer
   end
   
   def test_fb_multi_friend_request
@@ -717,7 +787,7 @@ class RailsHelperTest &lt; Test::Unit::TestCase
     @h.expects(:capture).returns(&quot;dialog content&quot;)
     @h.fb_dialog( &quot;my_dialog&quot;, &quot;1&quot; ) do
     end
-    assert_equal '&lt;fb:dialog cancel_button=&quot;1&quot; id=&quot;my_dialog&quot;&gt;dialog content&lt;/fb:dialog&gt;', _erbout
+    assert_equal '&lt;fb:dialog cancel_button=&quot;1&quot; id=&quot;my_dialog&quot;&gt;dialog content&lt;/fb:dialog&gt;', @h.output_buffer
   end
   def test_fb_dialog_title
     assert_equal '&lt;fb:dialog-title&gt;My Little Dialog&lt;/fb:dialog-title&gt;', @h.fb_dialog_title(&quot;My Little Dialog&quot;)
@@ -726,7 +796,7 @@ class RailsHelperTest &lt; Test::Unit::TestCase
     @h.expects(:capture).returns(&quot;dialog content content&quot;)
     @h.fb_dialog_content do
     end
-    assert_equal '&lt;fb:dialog-content&gt;dialog content content&lt;/fb:dialog-content&gt;', _erbout
+    assert_equal '&lt;fb:dialog-content&gt;dialog content content&lt;/fb:dialog-content&gt;', @h.output_buffer
   end
   def test_fb_dialog_button
     assert_equal '&lt;fb:dialog-button clickrewriteform=&quot;my_form&quot; clickrewriteid=&quot;my_dialog&quot; clickrewriteurl=&quot;http://www.some_url_here.com/dialog_return.php&quot; type=&quot;submit&quot; value=&quot;Yes&quot; /&gt;',
@@ -827,14 +897,17 @@ class RailsHelperTest &lt; Test::Unit::TestCase
     assert_equal &quot;&lt;fb:comments candelete=\&quot;false\&quot; canpost=\&quot;true\&quot; numposts=\&quot;4\&quot; optional=\&quot;false\&quot; xid=\&quot;xxx\&quot;&gt;&lt;fb:title&gt;TITLE&lt;/fb:title&gt;&lt;/fb:comments&gt;&quot;, @h.fb_comments(&quot;xxx&quot;,true,false,4,:optional=&gt;false, :title =&gt; &quot;TITLE&quot;) 
   end
   def test_fb_board
-    assert_equal &quot;&lt;fb:board optional=\&quot;false\&quot; xid=\&quot;xxx\&quot; /&gt;&quot;, @h.fb_board(&quot;xxx&quot;,:optional =&gt; false) 
+    assert_equal &quot;&lt;fb:board optional=\&quot;false\&quot; xid=\&quot;xxx\&quot;&gt;&lt;/fb:board&gt;&quot;, @h.fb_board(&quot;xxx&quot;,:optional =&gt; false) 
+  end
+  def test_fb_board_with_title
+    assert_equal &quot;&lt;fb:board optional=\&quot;false\&quot; xid=\&quot;xxx\&quot;&gt;&lt;fb:title&gt;TITLE&lt;/fb:title&gt;&lt;/fb:board&gt;&quot;, @h.fb_board(&quot;xxx&quot;,:optional=&gt;false, :title =&gt; &quot;TITLE&quot;) 
   end
   
   def test_fb_dashboard
     @h.expects(:capture).returns(&quot;dashboard content&quot;)
     @h.fb_dashboard do 
     end
-    assert_equal &quot;&lt;fb:dashboard&gt;dashboard content&lt;/fb:dashboard&gt;&quot;, _erbout
+    assert_equal &quot;&lt;fb:dashboard&gt;dashboard content&lt;/fb:dashboard&gt;&quot;, @h.output_buffer
   end
   def test_fb_dashboard_non_block
     assert_equal &quot;&lt;fb:dashboard&gt;&lt;/fb:dashboard&gt;&quot;, @h.fb_dashboard
@@ -844,15 +917,67 @@ class RailsHelperTest &lt; Test::Unit::TestCase
     @h.expects(:capture).returns(&quot;wide profile content&quot;)
     @h.fb_wide do
     end
-    assert_equal &quot;&lt;fb:wide&gt;wide profile content&lt;/fb:wide&gt;&quot;, _erbout
+    assert_equal &quot;&lt;fb:wide&gt;wide profile content&lt;/fb:wide&gt;&quot;, @h.output_buffer
   end
   
   def test_fb_narrow
     @h.expects(:capture).returns(&quot;narrow profile content&quot;)
     @h.fb_narrow do
     end
-    assert_equal &quot;&lt;fb:narrow&gt;narrow profile content&lt;/fb:narrow&gt;&quot;, _erbout
+    assert_equal &quot;&lt;fb:narrow&gt;narrow profile content&lt;/fb:narrow&gt;&quot;, @h.output_buffer
   end  
+  
+  def test_fb_login_button
+    assert_equal &quot;&lt;fb:login-button onlogin=\&quot;somejs\&quot;&gt;&lt;/fb:login-button&gt;&quot;,@h.fb_login_button(&quot;somejs&quot;)
+  end
+  
+  def test_init_fb_connect_no_features
+    assert ! @h.init_fb_connect.match(/XFBML/)
+  end
+  
+  def test_init_fb_connect_with_features
+    assert @h.init_fb_connect(&quot;XFBML&quot;).match(/XFBML/)
+  end
+  
+  def test_fb_connect_javascript_tag
+    assert_equal &quot;&lt;script src=\&quot;http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php\&quot; type=\&quot;text/javascript\&quot;&gt;&lt;/script&gt;&quot;,
+      @h.fb_connect_javascript_tag
+  end
+  
+  def test_fb_container
+    @h.expects(:capture).returns(&quot;Inner Stuff&quot;)
+    @h.fb_container(:condition=&gt;&quot;somejs&quot;) do
+    end
+    assert_equal &quot;&lt;fb:container condition=\&quot;somejs\&quot;&gt;Inner Stuff&lt;/fb:container&gt;&quot;,@h.output_buffer
+  end
+  
+  def test_fb_eventlink
+    assert_equal '&lt;fb:eventlink eid=&quot;21150032416&quot;&gt;&lt;/fb:eventlink&gt;',@h.fb_eventlink(&quot;21150032416&quot;)
+  end
+  
+  def test_fb_grouplink
+    assert_equal '&lt;fb:grouplink gid=&quot;2541896821&quot;&gt;&lt;/fb:grouplink&gt;',@h.fb_grouplink(&quot;2541896821&quot;)
+  end
+  
+  def test_fb_serverfbml
+    @h.expects(:capture).returns(&quot;Inner Stuff&quot;)
+    @h.fb_serverfbml(:condition=&gt;&quot;somejs&quot;) do
+    end
+    assert_equal &quot;&lt;fb:serverfbml condition=\&quot;somejs\&quot;&gt;Inner Stuff&lt;/fb:serverfbml&gt;&quot;,@h.output_buffer
+  end
+  
+  def test_fb_share_button
+    assert_equal &quot;&lt;fb:share-button class=\&quot;url\&quot; href=\&quot;http://www.elevatedrails.com\&quot;&gt;&lt;/fb:share-button&gt;&quot;,@h.fb_share_button(&quot;http://www.elevatedrails.com&quot;)
+  end
+  
+  def test_fb_unconnected_friends_count_without_condition
+    assert_equal &quot;&lt;fb:unconnected-friends-count&gt;&lt;/fb:unconnected-friends-count&gt;&quot;,@h.fb_unconnected_friends_count
+  end
+  
+  def test_fb_user_status
+    user=flexmock(&quot;user&quot;, :facebook_id =&gt; &quot;5678&quot;)
+    assert_equal '&lt;fb:user-status linked=&quot;false&quot; uid=&quot;5678&quot;&gt;&lt;/fb:user-status&gt;',@h.fb_user_status(user,false)
+  end
 end
 class TestModel
   attr_accessor :name,:facebook_id
@@ -864,9 +989,9 @@ class RailsFacebookFormbuilderTest &lt; Test::Unit::TestCase
     include ActionView::Helpers::CaptureHelper
     include ActionView::Helpers::TagHelper
     include Facebooker::Rails::Helpers
-    attr_accessor :_erbout
+    attr_accessor :output_buffer
     def initialize
-      @_erbout=&quot;&quot;
+      @output_buffer=&quot;&quot;
     end
   end
   def setup
@@ -883,11 +1008,11 @@ class RailsFacebookFormbuilderTest &lt; Test::Unit::TestCase
   end
   
   def test_text_field
-    assert_equal &quot;&lt;fb:editor-text id=\&quot;testmodel_name\&quot; label=\&quot;Name\&quot; name=\&quot;testmodel[name]\&quot; value=\&quot;Mike\&quot;&gt;&lt;/fb:editor-text&gt;&quot;,
+    assert_equal &quot;&lt;fb:editor-text id=\&quot;test_model_name\&quot; label=\&quot;Name\&quot; name=\&quot;test_model[name]\&quot; value=\&quot;Mike\&quot;&gt;&lt;/fb:editor-text&gt;&quot;,
         @form_builder.text_field(:name)
   end
   def test_text_area
-    assert_equal &quot;&lt;fb:editor-textarea id=\&quot;testmodel_name\&quot; label=\&quot;Name\&quot; name=\&quot;testmodel[name]\&quot;&gt;Mike&lt;/fb:editor-textarea&gt;&quot;,
+    assert_equal &quot;&lt;fb:editor-textarea id=\&quot;test_model_name\&quot; label=\&quot;Name\&quot; name=\&quot;test_model[name]\&quot;&gt;Mike&lt;/fb:editor-textarea&gt;&quot;,
         @form_builder.text_area(:name)    
   end
   
@@ -904,7 +1029,7 @@ class RailsFacebookFormbuilderTest &lt; Test::Unit::TestCase
   end
   
   def test_collection_typeahead_internal
-    assert_equal &quot;&lt;fb:typeahead-input id=\&quot;testmodel_name\&quot; name=\&quot;testmodel[name]\&quot; value=\&quot;Mike\&quot;&gt;&lt;fb:typeahead-option value=\&quot;3\&quot;&gt;ABC&lt;/fb:typeahead-option&gt;&lt;/fb:typeahead-input&gt;&quot;,
+    assert_equal &quot;&lt;fb:typeahead-input id=\&quot;test_model_name\&quot; name=\&quot;test_model[name]\&quot; value=\&quot;Mike\&quot;&gt;&lt;fb:typeahead-option value=\&quot;3\&quot;&gt;ABC&lt;/fb:typeahead-option&gt;&lt;/fb:typeahead-input&gt;&quot;,
       @form_builder.collection_typeahead_internal(:name,[&quot;ABC&quot;],:size,:to_s)        
   end
   
@@ -921,7 +1046,7 @@ class RailsFacebookFormbuilderTest &lt; Test::Unit::TestCase
   
   def test_custom
     @template.expects(:password_field).returns(&quot;password_field&quot;)
-    assert_equal &quot;&lt;fb:editor-custom label=\&quot;Name\&quot;&gt;&lt;/fb:editor-custom&gt;&quot;,@form_builder.password_field(:name)
+    assert_equal &quot;&lt;fb:editor-custom label=\&quot;Name\&quot;&gt;password_field&lt;/fb:editor-custom&gt;&quot;,@form_builder.password_field(:name)
   end
   
   def test_text
@@ -929,9 +1054,184 @@ class RailsFacebookFormbuilderTest &lt; Test::Unit::TestCase
   end
   
   def test_multi_friend_input
-    assert_equal &quot;&lt;fb:editor-custom label=\&quot;Friends\&quot;&gt;&lt;/fb:editor-custom&gt;&quot;,@form_builder.multi_friend_input
+    assert_equal &quot;&lt;fb:editor-custom label=\&quot;Friends\&quot;&gt;&lt;fb:multi-friend-input&gt;&lt;/fb:multi-friend-input&gt;&lt;/fb:editor-custom&gt;&quot;,@form_builder.multi_friend_input
+  end
+  
+
+end
+
+class RailsPrettyErrorsTest &lt; Test::Unit::TestCase
+  def setup
+    ENV['FACEBOOK_API_KEY'] = '1234567'
+    ENV['FACEBOOK_SECRET_KEY'] = '7654321'
+    @controller = ControllerWhichFails.new
+    @request    = ActionController::TestRequest.new
+    @response   = ActionController::TestResponse.new
+    @controller.stubs(:verify_signature).returns(true)
+  end
+  
+  def test_pretty_errors
+    Facebooker.facebooker_config.stubs(:pretty_errors).returns(false)
+    post :pass, example_rails_params_including_fb
+    assert_response :success    
+    post :fail, example_rails_params_including_fb
+    assert_response :error
+    Facebooker.facebooker_config.stubs(:pretty_errors).returns(true)
+    post :pass, example_rails_params_including_fb
+    assert_response :success    
+    post :fail, example_rails_params_including_fb
+    assert_response :error
+  end
+  private
+    def example_rails_params_including_fb
+      {&quot;fb_sig_time&quot;=&gt;&quot;1186588275.5988&quot;, &quot;fb_sig&quot;=&gt;&quot;7371a6400329b229f800a5ecafe03b0a&quot;, &quot;action&quot;=&gt;&quot;index&quot;, &quot;fb_sig_in_canvas&quot;=&gt;&quot;1&quot;, &quot;fb_sig_session_key&quot;=&gt;&quot;c452b5d5d60cbd0a0da82021-744961110&quot;, &quot;controller&quot;=&gt;&quot;controller_which_requires_facebook_authentication&quot;, &quot;fb_sig_expires&quot;=&gt;&quot;0&quot;, &quot;fb_sig_friends&quot;=&gt;&quot;417358,702720,1001170,1530839,3300204,3501584,6217936,9627766,9700907,22701786,33902768,38914148,67400422,135301144,157200364,500103523,500104930,500870819,502149612,502664898,502694695,502852293,502985816,503254091,504510130,504611551,505421674,509229747,511075237,512548373,512830487,517893818,517961878,518890403,523589362,523826914,525812984,531555098,535310228,539339781,541137089,549405288,552706617,564393355,564481279,567640762,568091401,570201702,571469972,573863097,574415114,575543081,578129427,578520568,582262836,582561201,586550659,591631962,592318318,596269347,596663221,597405464,599764847,602995438,606661367,609761260,610544224,620049417,626087078,628803637,632686250,641422291,646763898,649678032,649925863,653288975,654395451,659079771,661794253,665861872,668960554,672481514,675399151,678427115,685772348,686821151,687686894,688506532,689275123,695551670,710631572,710766439,712406081,715741469,718976395,719246649,722747311,725327717,725683968,725831016,727580320,734151780,734595181,737944528,748881410,752244947,763868412,768578853,776596978,789728437,873695441&quot;, &quot;fb_sig_added&quot;=&gt;&quot;0&quot;, &quot;fb_sig_api_key&quot;=&gt;&quot;b6c9c857ac543ca806f4d3187cd05e09&quot;, &quot;fb_sig_user&quot;=&gt;&quot;744961110&quot;, &quot;fb_sig_profile_update_time&quot;=&gt;&quot;1180712453&quot;}
+    end
+  
+end
+
+class RailsUrlHelperExtensionsTest &lt; Test::Unit::TestCase
+  class UrlHelperExtensionsClass
+    include ActionView::Helpers::UrlHelper
+    include ActionView::Helpers::TagHelper
+    def initialize(controller)
+      @controller = controller
+    end
+
+    def protect_against_forgery?
+       false
+    end
+    
+    def request_comes_from_facebook?
+      @request_comes_from_facebook
+    end
+    
+    def request_comes_from_facebook=(val)
+      @request_comes_from_facebook = val
+    end
+
+  end 
+  class UrlHelperExtensionsController &lt; NoisyController    
+    def index
+      render :nothing =&gt; true
+    end
+    def do_it
+      render :nothing =&gt; true
+    end
+  end
+
+  class FacebookRequest &lt; ActionController::TestRequest  
+  end
+
+  def setup
+    @controller = UrlHelperExtensionsController.new
+    @request    = FacebookRequest.new
+    @response   = ActionController::TestResponse.new
+
+    @u = UrlHelperExtensionsClass.new(@controller)
+    @u.request_comes_from_facebook = true
+    
+    @non_canvas_u = UrlHelperExtensionsClass.new(@controller)
+    @non_canvas_u.request_comes_from_facebook = false
+    
+    @label = &quot;Testing&quot;
+    @url = &quot;test.host&quot;
+    @prompt = &quot;Are you sure?&quot;
+    @default_title = &quot;Please Confirm&quot;
+    @title = &quot;Confirm Request&quot;
+    @style = {:color =&gt; 'black', :background =&gt; 'white'}
+    @verbose_style = &quot;{background: 'white', color: 'black'}&quot;
+    @default_okay = &quot;Okay&quot;
+    @default_cancel = &quot;Cancel&quot;
+    @default_style = &quot;&quot; #&quot;'width','200px'&quot;
+  end
+
+  def test_link_to
+    assert_equal &quot;&lt;a href=\&quot;#{@url}\&quot;&gt;Testing&lt;/a&gt;&quot;, @u.link_to(@label, @url)
   end
+
+  def test_link_to_with_popup
+    assert_raises(ActionView::ActionViewError) {@u.link_to(@label,@url, :popup=&gt;true)}
+  end
+
+  def test_link_to_with_confirm
+    assert_dom_equal( &quot;&lt;a href=\&quot;#{@url}\&quot; onclick=\&quot;var dlg = new Dialog().showChoice(\'#{@default_title}\',\'#{@prompt}\',\'#{@default_okay}\',\'#{@default_cancel}\').setStyle(#{@default_style});&quot;+
+                 &quot;var a=this;dlg.onconfirm = function() { &quot; + 
+                 &quot;document.setLocation(a.getHref()); };return false;\&quot;&gt;#{@label}&lt;/a&gt;&quot;,
+                  @u.link_to(@label, @url, :confirm =&gt; @prompt) )
+  end
+  def test_link_to_with_confirm_with_title
+    assert_dom_equal( &quot;&lt;a href=\&quot;#{@url}\&quot; onclick=\&quot;var dlg = new Dialog().showChoice(\'#{@title}\',\'#{@prompt}\',\'#{@default_okay}\',\'#{@default_cancel}\').setStyle(#{@default_style});&quot;+
+                 &quot;var a=this;dlg.onconfirm = function() { &quot; + 
+                 &quot;document.setLocation(a.getHref()); };return false;\&quot;&gt;#{@label}&lt;/a&gt;&quot;,
+                  @u.link_to(@label, @url, :confirm =&gt; {:title=&gt;@title,:content=&gt;@prompt}) )
+  end
+  def test_link_to_with_confirm_with_title_and_style
+    assert_dom_equal( &quot;&lt;a href=\&quot;#{@url}\&quot; onclick=\&quot;var dlg = new Dialog().showChoice(\'#{@title}\',\'#{@prompt}\',\'#{@default_okay}\',\'#{@default_cancel}\').setStyle(#{@verbose_style});&quot;+
+                 &quot;var a=this;dlg.onconfirm = function() { &quot; + 
+                 &quot;document.setLocation(a.getHref()); };return false;\&quot;&gt;#{@label}&lt;/a&gt;&quot;,
+                  @u.link_to(@label, @url, :confirm =&gt; {:title=&gt;@title,:content=&gt;@prompt}.merge!(@style)) )
+  end
+
+  def test_link_to_with_method
+    assert_dom_equal( &quot;&lt;a href=\&quot;#{@url}\&quot; onclick=\&quot;var a=this;var f = document.createElement('form'); f.setStyle('display','none'); &quot;+
+                 &quot;a.getParentNode().appendChild(f); f.setMethod('POST'); f.setAction(a.getHref());&quot; +
+                 &quot;var m = document.createElement('input'); m.setType('hidden'); &quot;+
+                 &quot;m.setName('_method'); m.setValue('delete'); f.appendChild(m);&quot;+
+                 &quot;f.submit();return false;\&quot;&gt;#{@label}&lt;/a&gt;&quot;, @u.link_to(@label,@url, :method=&gt;:delete))
+  end
+
+  def test_link_to_with_confirm_and_method
+    assert_dom_equal( &quot;&lt;a href=\&quot;#{@url}\&quot; onclick=\&quot;var dlg = new Dialog().showChoice(\'#{@default_title}\',\'#{@prompt}\',\'#{@default_okay}\',\'#{@default_cancel}\').setStyle(#{@default_style});&quot;+
+                 &quot;var a=this;dlg.onconfirm = function() { &quot; + 
+                 &quot;var f = document.createElement('form'); f.setStyle('display','none'); &quot;+
+                 &quot;a.getParentNode().appendChild(f); f.setMethod('POST'); f.setAction(a.getHref());&quot; +
+                 &quot;var m = document.createElement('input'); m.setType('hidden'); &quot;+
+                 &quot;m.setName('_method'); m.setValue('delete'); f.appendChild(m);&quot;+
+                 &quot;f.submit(); };return false;\&quot;&gt;#{@label}&lt;/a&gt;&quot;, @u.link_to(@label,@url, :confirm=&gt;@prompt, :method=&gt;:delete) )
+  end
+  def test_link_to_with_confirm_and_method_for_non_canvas_page
+    assert_dom_equal( &quot;&lt;a href=\&quot;#{@url}\&quot; onclick=\&quot;if (confirm(\'#{@prompt}\')) { var f = document.createElement('form'); f.style.display = 'none'; &quot;+
+                      &quot;this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); &quot;+
+                      &quot;m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); &quot;+
+                      &quot;f.appendChild(m);f.submit(); };return false;\&quot;&gt;#{@label}&lt;/a&gt;&quot;,
+                      @non_canvas_u.link_to(@label,@url, :confirm=&gt;@prompt, :method=&gt;:delete) )
+  end
+
+  def test_button_to
+    assert_equal &quot;&lt;form method=\&quot;post\&quot; action=\&quot;#{@url}\&quot; class=\&quot;button-to\&quot;&gt;&lt;div&gt;&quot; +
+                 &quot;&lt;input type=\&quot;submit\&quot; value=\&quot;#{@label}\&quot; /&gt;&lt;/div&gt;&lt;/form&gt;&quot;, @u.button_to(@label,@url)
+  end
+
+  def test_button_to_with_confirm
+    assert_equal &quot;&lt;form method=\&quot;post\&quot; action=\&quot;#{@url}\&quot; class=\&quot;button-to\&quot;&gt;&lt;div&gt;&quot; +
+                 &quot;&lt;input onclick=\&quot;var dlg = new Dialog().showChoice(\'#{@default_title}\',\'#{@prompt}\',\'#{@default_okay}\',\'#{@default_cancel}\').setStyle(#{@default_style});&quot;+
+                 &quot;var a=this;dlg.onconfirm = function() { &quot;+
+                 &quot;a.getForm().submit(); };return false;\&quot; type=\&quot;submit\&quot; value=\&quot;#{@label}\&quot; /&gt;&lt;/div&gt;&lt;/form&gt;&quot;, 
+                 @u.button_to(@label,@url, :confirm=&gt;@prompt)
+  end
+  def test_button_to_with_confirm_for_non_canvas_page
+    assert_equal &quot;&lt;form method=\&quot;post\&quot; action=\&quot;#{@url}\&quot; class=\&quot;button-to\&quot;&gt;&lt;div&gt;&quot;+
+                 &quot;&lt;input onclick=\&quot;return confirm(\'#{@prompt}\');\&quot; type=\&quot;submit\&quot; value=\&quot;#{@label}\&quot; /&gt;&lt;/div&gt;&lt;/form&gt;&quot;,
+                 @non_canvas_u.button_to(@label,@url, :confirm=&gt;@prompt)
+  end
+
+  def test_link_to_unless_with_true
+       assert_equal @label, @u.link_to_unless(true,@label,@url)
+  end
+  def test_link_to_unless_with_false
+       assert_equal @u.link_to(@label,@url), @u.link_to_unless(false,@label,@url)
+  end
+
+  def test_link_to_if_with_true
+       assert_equal @u.link_to(@label,@url), @u.link_to_if(true,@label,@url)
+  end
+  def test_link_to_if_with_false
+       assert_equal @label, @u.link_to_if(false,@label,@url)
+  end
+  
 end
+
+
 # rescue LoadError
 #   $stderr.puts &quot;Couldn't find action controller.  That's OK.  We'll skip it.&quot;
 end</diff>
      <filename>vendor/plugins/facebooker/test/rails_integration_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,10 +8,12 @@ class SessionTest &lt; Test::Unit::TestCase
     ENV['FACEBOOK_SECRET_KEY'] = '7654321'   
     Facebooker.current_adapter = nil 
     @session = Facebooker::Session.create('whatever', 'doesnotmatterintest')   
+    Facebooker.use_curl=false
   end
 
   def teardown
-    flexmock_close
+    Facebooker::Session.configuration_file_path = nil
+    super    
   end
   
   def test_install_url_escapes_optional_next_parameter
@@ -59,6 +61,17 @@ class SessionTest &lt; Test::Unit::TestCase
     session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
     session.secure_with!(&quot;a session key&quot;, &quot;123456&quot;, Time.now.to_i + 60)
     assert(session.secured?)
+    assert_equal 'a session key', session.session_key
+    assert_equal 123456, session.user.to_i
+  end
+
+  def test_session_can_be_secured_with_existing_values_and_a_nil_uid
+    flexmock(session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY']))
+    session.should_receive(:post).with('facebook.users.getLoggedInUser', :session_key =&gt; 'a session key').returns(321)
+    session.secure_with!(&quot;a session key&quot;, nil, Time.now.to_i + 60)
+    assert(session.secured?)
+    assert_equal 'a session key', session.session_key
+    assert_equal 321, session.user.to_i
   end
   
   # The Facebook API for this is hideous.  Oh well.
@@ -149,7 +162,7 @@ class SessionTest &lt; Test::Unit::TestCase
   
   def test_can_send_notification_with_object
     @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
-    @session.expects(:post).with('facebook.notifications.send',{:to_ids=&gt;&quot;1&quot;,:notification=&gt;&quot;a&quot;,:type=&gt;&quot;general&quot;},true)
+    @session.expects(:post).with('facebook.notifications.send',{:to_ids=&gt;&quot;1&quot;,:notification=&gt;&quot;a&quot;,:type=&gt;&quot;user_to_user&quot;},true)
     @session.send(:instance_variable_set,&quot;@uid&quot;,3)
     user=flexmock(&quot;user&quot;)
     user.should_receive(:facebook_id).and_return(&quot;1&quot;).once
@@ -158,13 +171,13 @@ class SessionTest &lt; Test::Unit::TestCase
   def test_can_send_notification_with_string
     @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
     @session.send(:instance_variable_set,&quot;@uid&quot;,3)
-    @session.expects(:post).with('facebook.notifications.send',{:to_ids=&gt;&quot;1&quot;,:notification=&gt;&quot;a&quot;, :type=&gt;&quot;general&quot;},true)
+    @session.expects(:post).with('facebook.notifications.send',{:to_ids=&gt;&quot;1&quot;,:notification=&gt;&quot;a&quot;, :type=&gt;&quot;user_to_user&quot;},true)
     @session.send_notification([&quot;1&quot;],&quot;a&quot;)
   end
   
   def test_can_send_announcement_notification
     @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
-    @session.expects(:post).with('facebook.notifications.send',{:to_ids=&gt;&quot;1&quot;,:notification=&gt;&quot;a&quot;, :type=&gt;&quot;announcement&quot;},false)
+    @session.expects(:post).with('facebook.notifications.send',{:to_ids=&gt;&quot;1&quot;,:notification=&gt;&quot;a&quot;, :type=&gt;&quot;app_to_user&quot;},false)
     @session.send_notification([&quot;1&quot;],&quot;a&quot;)
   end
   
@@ -174,13 +187,26 @@ class SessionTest &lt; Test::Unit::TestCase
     assert_equal 17876842716, @session.register_template_bundle(&quot;{*actor*} did something&quot;)
   end
   
-  
+  def test_can_register_template_bundle_with_action_links
+    expect_http_posts_with_responses(example_register_template_bundle_return_xml)
+    @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
+    assert_equal 17876842716, @session.register_template_bundle(&quot;{*actor*} did something&quot;,nil,nil,[{:text=&gt;&quot;text&quot;,:href=&gt;&quot;href&quot;}])
+  end
   def test_can_publish_user_action
     expect_http_posts_with_responses(publish_user_action_return_xml)
     @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
     assert @session.publish_user_action(17876842716,{})
   end
   
+  def test_logs_api_calls
+    call_name = 'sample.api.call'
+    params = { :param1 =&gt; true, :param2 =&gt; 'value' }
+    flexmock(Facebooker::Logging, :Logging).should_receive(:log_fb_api).once.with(
+       call_name, params, Proc)
+    @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
+    @session.post(call_name, params)
+  end
+  
   def test_requests_inside_batch_are_added_to_batch
     @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
     @session.send(:service).expects(:post).once
@@ -218,10 +244,41 @@ class SessionTest &lt; Test::Unit::TestCase
     assert_equal 4,Facebooker::BatchRun.current_batch
   end
   
-  def teardown
-    Facebooker::Session.configuration_file_path = nil
+  def test_can_get_stanard_info
+    expect_http_posts_with_responses(standard_info_xml)
+    result = @session.users_standard([4])
+    assert_equal &quot;Mike Mangino&quot;,result.first.name
   end
-  
+
+  def test_can_query_for_pages
+    expect_http_posts_with_responses(example_pages_xml)
+    example_page = Facebooker::Page.new(
+      :page_id =&gt; 4846711747,
+      :name =&gt; &quot;Kronos Quartet&quot;,
+      :website =&gt; &quot;http://www.kronosquartet.org&quot;,
+      :company_overview =&gt; &quot;&quot;,
+      :session =&gt; @session)
+    pages = @session.pages(:fields =&gt; %w[ page_id name website company_overview ])
+
+    assert_equal 1, pages.size
+
+    page = pages.first
+    assert_equal &quot;4846711747&quot;, page.page_id
+    assert_equal &quot;Kronos Quartet&quot;, page.name
+    assert_equal &quot;http://www.kronosquartet.org&quot;, page.website
+    
+    # TODO we really need a way to differentiate between hash/list and text attributes
+    # assert_equal({}, page.company_overview)
+    
+    # sakkaoui : as a fix to the parser, I replace empty text node by &quot;&quot; instead of {}
+    # we have child.attributes['list'] == 'true' that let us know that we have a hash/list.
+    assert_equal(&quot;&quot;, page.company_overview)
+    
+    genre = page.genre
+    assert_equal false, genre.dance
+    assert_equal true, genre.party
+  end
+    
   private
   
   def example_groups_get_xml
@@ -475,6 +532,24 @@ class SessionTest &lt; Test::Unit::TestCase
     &lt;/feed_registerTemplateBundle_response&gt;
     XML
   end
+
+  def example_pages_xml
+    &lt;&lt;-XML
+    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+    &lt;pages_getInfo_response xmlns=&quot;http://api.facebook.com/1.0/&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd&quot; list=&quot;true&quot;&gt;
+      &lt;page&gt;
+        &lt;page_id&gt;4846711747&lt;/page_id&gt;
+        &lt;name&gt;Kronos Quartet&lt;/name&gt;
+        &lt;website&gt;http://www.kronosquartet.org&lt;/website&gt;
+        &lt;company_overview/&gt;
+        &lt;genre&gt;
+          &lt;dance&gt;0&lt;/dance&gt;
+          &lt;party&gt;1&lt;/party&gt;
+        &lt;/genre&gt;
+      &lt;/page&gt;
+    &lt;/pages_getInfo_response&gt;
+    XML
+  end
   
   def publish_user_action_return_xml
     &lt;&lt;-XML
@@ -485,6 +560,44 @@ class SessionTest &lt; Test::Unit::TestCase
     XML
   end
   
+  def standard_info_xml
+    &lt;&lt;-XML
+    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+
+    &lt;users_getStandardInfo_response xmlns=&quot;http://api.facebook.com/1.0/&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd&quot; list=&quot;true&quot;&gt;
+      &lt;standard_user_info&gt;
+        &lt;uid&gt;12451752&lt;/uid&gt;
+        &lt;name&gt;Mike Mangino&lt;/name&gt;
+      &lt;/standard_user_info&gt;
+    &lt;/users_getStandardInfo_response&gt;
+    XML
+  end
+end
+
+class PostMethodTest &lt; Test::Unit::TestCase
+  
+  def setup
+    Facebooker.use_curl = true
+    Facebooker::Parser.stubs(:parse)
+    @uri = URI.parse(&quot;http://api.facebook.com/api&quot;)
+    @service = Facebooker::Service.new(&quot;a&quot;,&quot;b&quot;,&quot;c&quot;)
+    @service.stubs(&quot;url&quot;).returns(@uri)
+  end
+  
+  def teardown
+    Facebooker.use_curl = false
+  end
+  
+  def test_use_curl_makes_post_with_curl
+    @service.expects(:post_form_with_curl).with(@uri,{:method=&gt;&quot;a&quot;})
+    @service.post(:method=&gt;&quot;a&quot;)
+  end
+  
+  def test_use_curl_makes_post_file_use_curl_with_multipart
+    @service.expects(:post_form_with_curl).with(@uri,{:method=&gt;&quot;a&quot;},true)
+    @service.post_file(:method=&gt;&quot;a&quot;)    
+  end
 end
 
 class CanvasSessionTest &lt; Test::Unit::TestCase</diff>
      <filename>vendor/plugins/facebooker/test/session_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,7 +7,13 @@ require File.dirname(__FILE__)+'/../lib/facebooker/rails/test_helpers'
 
 $: &lt;&lt; File.join(File.dirname(__FILE__), '..', 'lib')
 
-RAILS_ROOT=File.join(File.dirname(__FILE__),'..','..')
+rails_root = File.join(File.dirname(__FILE__),'..','..')
+if defined? RAILS_ROOT
+  RAILS_ROOT.replace(rails_root)
+else
+  RAILS_ROOT = rails_root
+end
+
 require 'facebooker'
 
 class Test::Unit::TestCase</diff>
      <filename>vendor/plugins/facebooker/test/test_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,9 +8,18 @@ class UserTest &lt; Test::Unit::TestCase
     @session = Facebooker::Session.create('apikey', 'secretkey')
     @user = Facebooker::User.new(1234, @session)
     @other_user = Facebooker::User.new(4321, @session)
+    ENV['FACEBOOK_CANVAS_PATH'] ='facebook_app_name'
+    ENV['FACEBOOK_API_KEY'] = '1234567'
+    ENV['FACEBOOK_SECRET_KEY'] = '7654321'
+    
     @user.friends = [@other_user]
   end
   
+  def test_has_permission
+    expect_http_posts_with_responses(has_app_permission_response_xml)
+    assert @user.has_permission?(&quot;status_update&quot;)
+  end
+  
   def test_can_ask_user_if_he_or_she_is_friends_with_another_user
     assert(@user.friends_with?(@other_user))
   end
@@ -18,6 +27,22 @@ class UserTest &lt; Test::Unit::TestCase
   def test_can_ask_user_if_he_or_she_is_friends_with_another_user_by_user_id
     assert(@user.friends_with?(@other_user.id))
   end
+
+  def test_does_not_query_facebook_for_uid
+    @session.expects(:post).never
+    assert_equal 1234, Facebooker::User.new(1234, @session).uid
+  end
+
+  def test_uid_is_always_an_integer
+    assert_equal 1234, Facebooker::User.new(:uid =&gt; &quot;1234&quot;).uid
+    assert_equal 1234, Facebooker::User.new(:id  =&gt; &quot;1234&quot;).uid
+    
+    assert_equal 1234, Facebooker::User.new(:uid =&gt; &quot;1234&quot;).id
+    assert_equal 1234, Facebooker::User.new(:id  =&gt; &quot;1234&quot;).id
+    
+    assert_equal 1234, Facebooker::User.new(:uid =&gt; &quot;1234&quot;).facebook_id
+    assert_equal 1234, Facebooker::User.new(:id  =&gt; &quot;1234&quot;).facebook_id
+  end
   
   def test_cast_to_friend_list_id_with_nil
     assert_nil @user.cast_to_friend_list_id(nil)
@@ -46,6 +71,10 @@ class UserTest &lt; Test::Unit::TestCase
     user=Facebooker::User.new(1)
     assert_equal(&quot;current&quot;,user.session)
   end
+
+  def test_raises_when_no_session_bound
+    assert_raises(Facebooker::Model::UnboundSessionException) { Facebooker::User.new(1, nil).populate }
+  end
   
   def test_can_set_mobile_fbml
     @user.expects(:set_profile_fbml).with(nil,&quot;test&quot;,nil)
@@ -66,12 +95,12 @@ class UserTest &lt; Test::Unit::TestCase
   end
   
   def test_can_call_set_profile_fbml
-    @session.expects(:post).with('facebook.profile.setFBML', :uid=&gt;1234,:profile=&gt;&quot;profile&quot;,:profile_action=&gt;&quot;action&quot;,:mobile_profile=&gt;&quot;mobile&quot;)
+    @session.expects(:post).with('facebook.profile.setFBML', {:uid=&gt;1234,:profile=&gt;&quot;profile&quot;,:profile_action=&gt;&quot;action&quot;,:mobile_profile=&gt;&quot;mobile&quot;},false)
     @user.set_profile_fbml(&quot;profile&quot;,&quot;mobile&quot;,&quot;action&quot;)
   end
   
   def test_can_call_set_profile_fbml_with_profile_main
-    @session.expects(:post).with('facebook.profile.setFBML', :uid=&gt;1234,:profile=&gt;&quot;profile&quot;,:profile_action=&gt;&quot;action&quot;,:mobile_profile=&gt;&quot;mobile&quot;, :profile_main =&gt; 'profile_main')
+    @session.expects(:post).with('facebook.profile.setFBML', {:uid=&gt;1234,:profile=&gt;&quot;profile&quot;,:profile_action=&gt;&quot;action&quot;,:mobile_profile=&gt;&quot;mobile&quot;, :profile_main =&gt; 'profile_main'},false)
     @user.set_profile_fbml(&quot;profile&quot;,&quot;mobile&quot;,&quot;action&quot;,'profile_main')
   end
   
@@ -105,23 +134,33 @@ class UserTest &lt; Test::Unit::TestCase
     @user.send_email(&quot;subject&quot;, nil, &quot;body fbml&quot;)
   end
   
+  def test_doesnt_post_to_facebook_when_assigning_status
+    @session.expects(:post).never
+    @user.status=&quot;my status&quot;
+  end
   def test_can_set_status_with_string
     @session.expects(:post).with('facebook.users.setStatus', :status=&gt;&quot;my status&quot;,:status_includes_verb=&gt;1)
-    @user.status=&quot;my status&quot;
+    @user.set_status(&quot;my status&quot;)
   end
   
   def test_get_events
     @user = Facebooker::User.new(9507801, @session)
     expect_http_posts_with_responses(example_events_get_xml)
     events = @user.events
-    assert_equal &quot;29511517904&quot;, events.first.eid
+    assert_equal 29511517904, events.first.eid
   end
-  
-  def test_can_get_events
-    @user.expects(:events)
-    @user.events
+
+  def test_events_caching_honors_params
+    @user = Facebooker::User.new(9507801, @session)
+    @session.expects(:post).returns([{:eid=&gt;1}])
+    assert_equal 1,@user.events.first.eid
+    @session.expects(:post).returns([{:eid=&gt;2}])
+    assert_equal 2,@user.events(:start_time=&gt;1.day.ago).first.eid
+    @session.expects(:post).never
+    assert_equal 1,@user.events.first.eid
   end
   
+  
   def test_to_s
     assert_equal(&quot;1234&quot;,@user.to_s)
   end
@@ -130,6 +169,38 @@ class UserTest &lt; Test::Unit::TestCase
     assert_equal @user, @user.dup
   end
   
+  def test_hash_email
+    assert_equal &quot;4228600737_c96da02bba97aedfd26136e980ae3761&quot;, Facebooker::User.hash_email(&quot;mary@example.com&quot;)
+  end
+  def test_hash_email_not_normalized
+    assert_equal &quot;4228600737_c96da02bba97aedfd26136e980ae3761&quot;, Facebooker::User.hash_email(&quot; MaRy@example.com  &quot;)
+  end
+  
+  def test_register_with_array
+    expect_http_posts_with_responses(register_response_xml)
+    assert_equal [&quot;4228600737_c96da02bba97aedfd26136e980ae3761&quot;],Facebooker::User.register([{:email=&gt;&quot;mary@example.com&quot;,:account_id=&gt;1}])
+  end
+  
+  def test_register_with_array_raises_if_not_all_success
+    expect_http_posts_with_responses(register_response_xml)
+    assert_equal [&quot;4228600737_c96da02bba97aedfd26136e980ae3761&quot;],Facebooker::User.register([{:email=&gt;&quot;mary@example.com&quot;,:account_id=&gt;1},{:email=&gt;&quot;mike@example.com&quot;,:account_id=&gt;2}])
+    fail &quot;Should have raised Facebooker::Session::UserRegistrationFailed&quot;
+  rescue Facebooker::Session::UserRegistrationFailed =&gt; e
+    assert_equal({:email=&gt;&quot;mike@example.com&quot;,:account_id=&gt;2},e.failed_users.first)
+  end
+  
+  def test_get_locale
+    @user = Facebooker::User.new(9507801, @session)
+    expect_http_posts_with_responses(example_users_get_info_xml)
+    assert_equal &quot;en_US&quot;, @user.locale
+  end
+  
+  def test_get_profile_url
+    @user = Facebooker::User.new(8055, @session)
+    expect_http_posts_with_responses(example_users_get_info_xml)
+    assert_equal &quot;http://www.facebook.com/profile.php?id=8055&quot;, @user.profile_url
+  end
+  
   private
   def example_profile_photos_get_xml
     &quot;&lt;?xml version=\&quot;1.0\&quot; encoding=\&quot;UTF-8\&quot;?&gt;
@@ -192,4 +263,28 @@ class UserTest &lt; Test::Unit::TestCase
       &lt;/event&gt;
     &lt;/events_get_response&gt;&quot;
   end
-end
\ No newline at end of file
+  
+  def example_users_get_info_xml
+    &lt;&lt;-XML
+    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &lt;users_getInfo_response xmlns=&quot;http://api.facebook.com/1.0/&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd&quot; list=&quot;true&quot;&gt; &lt;user&gt; &lt;uid&gt;8055&lt;/uid&gt; &lt;about_me&gt;This field perpetuates the glorification of the ego. Also, it has a character limit.&lt;/about_me&gt; &lt;activities&gt;Here: facebook, etc. There: Glee Club, a capella, teaching.&lt;/activities&gt; &lt;affiliations list=&quot;true&quot;&gt; &lt;affiliation&gt; &lt;nid&gt;50453093&lt;/nid&gt; &lt;name&gt;Facebook Developers&lt;/name&gt; &lt;type&gt;work&lt;/type&gt; &lt;status/&gt; &lt;year/&gt; &lt;/affiliation&gt; &lt;/affiliations&gt; &lt;birthday&gt;November 3&lt;/birthday&gt; &lt;books&gt;The Brothers K, GEB, Ken Wilber, Zen and the Art, Fitzgerald, The Emporer's New Mind, The Wonderful Story of Henry Sugar&lt;/books&gt; &lt;current_location&gt; &lt;city&gt;Palo Alto&lt;/city&gt; &lt;state&gt;CA&lt;/state&gt; &lt;country&gt;United States&lt;/country&gt; &lt;zip&gt;94303&lt;/zip&gt; &lt;/current_location&gt; &lt;education_history list=&quot;true&quot;&gt; &lt;education_info&gt; &lt;name&gt;Harvard&lt;/name&gt; &lt;year&gt;2003&lt;/year&gt; &lt;concentrations list=&quot;true&quot;&gt; &lt;concentration&gt;Applied Mathematics&lt;/concentration&gt; &lt;concentration&gt;Computer Science&lt;/concentration&gt; &lt;/concentrations&gt; &lt;/education_info&gt; &lt;/education_history&gt; &lt;first_name&gt;Dave&lt;/first_name&gt; &lt;hometown_location&gt; &lt;city&gt;York&lt;/city&gt; &lt;state&gt;PA&lt;/state&gt; &lt;country&gt;United States&lt;/country&gt; &lt;/hometown_location&gt; &lt;hs_info&gt; &lt;hs1_name&gt;Central York High School&lt;/hs1_name&gt; &lt;hs2_name/&gt; &lt;grad_year&gt;1999&lt;/grad_year&gt; &lt;hs1_id&gt;21846&lt;/hs1_id&gt; &lt;hs2_id&gt;0&lt;/hs2_id&gt; &lt;/hs_info&gt; &lt;is_app_user&gt;1&lt;/is_app_user&gt; &lt;has_added_app&gt;1&lt;/has_added_app&gt; &lt;interests&gt;coffee, computers, the funny, architecture, code breaking,snowboarding, philosophy, soccer, talking to strangers&lt;/interests&gt; &lt;last_name&gt;Fetterman&lt;/last_name&gt; &lt;locale&gt;en_US&lt;/locale&gt; &lt;meeting_for list=&quot;true&quot;&gt; &lt;seeking&gt;Friendship&lt;/seeking&gt; &lt;/meeting_for&gt; &lt;meeting_sex list=&quot;true&quot;&gt; &lt;sex&gt;female&lt;/sex&gt; &lt;/meeting_sex&gt; &lt;movies&gt;Tommy Boy, Billy Madison, Fight Club, Dirty Work, Meet the Parents, My Blue Heaven, Office Space &lt;/movies&gt; &lt;music&gt;New Found Glory, Daft Punk, Weezer, The Crystal Method, Rage, the KLF, Green Day, Live, Coldplay, Panic at the Disco, Family Force 5&lt;/music&gt; &lt;name&gt;Dave Fetterman&lt;/name&gt; &lt;notes_count&gt;0&lt;/notes_count&gt; &lt;pic&gt;http://photos-055.facebook.com/ip007/profile3/1271/65/s8055_39735.jpg&lt;/pic&gt; &lt;pic_big&gt;http://photos-055.facebook.com/ip007/profile3/1271/65/n8055_39735.jpg&lt;/pic_big&gt; &lt;pic_small&gt;http://photos-055.facebook.com/ip007/profile3/1271/65/t8055_39735.jpg&lt;/pic_small&gt; &lt;pic_square&gt;http://photos-055.facebook.com/ip007/profile3/1271/65/q8055_39735.jpg&lt;/pic_square&gt; &lt;political&gt;Moderate&lt;/political&gt; &lt;profile_update_time&gt;1170414620&lt;/profile_update_time&gt; &lt;profile_url&gt;http://www.facebook.com/profile.php?id=8055&lt;/profile_url&gt; &lt;quotes/&gt; &lt;relationship_status&gt;In a Relationship&lt;/relationship_status&gt; &lt;religion/&gt; &lt;sex&gt;male&lt;/sex&gt; &lt;significant_other_id xsi:nil=&quot;true&quot;/&gt; &lt;status&gt; &lt;message&gt;Fast Company, November issue, page 84&lt;/message&gt; &lt;time&gt;1193075616&lt;/time&gt; &lt;/status&gt; &lt;timezone&gt;-8&lt;/timezone&gt; &lt;tv&gt;cf. Bob Trahan&lt;/tv&gt; &lt;wall_count&gt;121&lt;/wall_count&gt; &lt;work_history list=&quot;true&quot;&gt; &lt;work_info&gt; &lt;location&gt; &lt;city&gt;Palo Alto&lt;/city&gt; &lt;state&gt;CA&lt;/state&gt; &lt;country&gt;United States&lt;/country&gt; &lt;/location&gt; &lt;company_name&gt;Facebook&lt;/company_name&gt; &lt;position&gt;Software Engineer&lt;/position&gt; &lt;description&gt;Tech Lead, Facebook Platform&lt;/description&gt; &lt;start_date&gt;2006-01&lt;/start_date&gt; &lt;end_date/&gt; &lt;/work_info&gt; &lt;/work_history&gt; &lt;/user&gt; &lt;/users_getInfo_response&gt;
+    XML
+  end
+  
+  def register_response_xml
+    &lt;&lt;-XML
+    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; 
+    &lt;connect_registerUsers_response xmlns=&quot;http://api.facebook.com/1.0/&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://api.facebook.com/1.0/facebook.xsd&quot; list=&quot;true&quot;&gt; 
+      &lt;connect_registerUsers_response_elt&gt;4228600737_c96da02bba97aedfd26136e980ae3761&lt;/connect_registerUsers_response_elt&gt; 
+    &lt;/connect_registerUsers_response&gt;
+    XML
+  end
+  
+  def has_app_permission_response_xml
+    &lt;&lt;-XML
+    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+    &lt;users_hasAppPermission_response xmlns=&quot;http://api.facebook.com/1.0/&quot;
+      xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
+      xsi:schemaLocation=&quot;http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd&quot;&gt;1&lt;/users_hasAppPermission_response&gt;
+    XML
+  end
+end</diff>
      <filename>vendor/plugins/facebooker/test/user_test.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>vendor/plugins/facebooker/facebooker.yml.tpl</filename>
    </removed>
    <removed>
      <filename>vendor/plugins/facebooker/generators/publisher/templates/create_facebook_templates.rb</filename>
    </removed>
    <removed>
      <filename>vendor/plugins/facebooker/generators/publisher/templates/publisher.rb</filename>
    </removed>
    <removed>
      <filename>vendor/plugins/facebooker/javascripts/facebooker.js</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>16cd7aa62020b1f16ada5d9fb1aca7913bb51f6a</id>
    </parent>
  </parents>
  <author>
    <name>David Clements</name>
    <email>digidigo@gmail.com</email>
  </author>
  <url>http://github.com/digidigo/ruby_footprints/commit/e3f013e502337d13934284fe8cb3869a1473605e</url>
  <id>e3f013e502337d13934284fe8cb3869a1473605e</id>
  <committed-date>2009-01-28T16:54:40-08:00</committed-date>
  <authored-date>2009-01-28T16:54:40-08:00</authored-date>
  <message>Updating to latest facebooker source.  Removing the rails 2.0.2 requirement.</message>
  <tree>7d31c2511be0b89bd6e706b5795f2bf466e474f9</tree>
  <committer>
    <name>David Clements</name>
    <email>digidigo@gmail.com</email>
  </committer>
</commit>
