aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller
diff options
context:
space:
mode:
authorMarcel Molina <marcel@vernix.org>2005-10-15 14:39:29 +0000
committerMarcel Molina <marcel@vernix.org>2005-10-15 14:39:29 +0000
commit48fd667bda20b899c8c2f0c68a403476f083effc (patch)
tree7ef50bcc0a06ecac3eb4adfa5ed0c8a9f6aaa88c /actionpack/lib/action_controller
parent6a8b9484a7398f3b500cd1f056cbe46fd7d6301c (diff)
downloadrails-48fd667bda20b899c8c2f0c68a403476f083effc.tar.gz
rails-48fd667bda20b899c8c2f0c68a403476f083effc.tar.bz2
rails-48fd667bda20b899c8c2f0c68a403476f083effc.zip
Raise an exception if an attempt is made to insert more session data into the ActiveRecordStore data column than the column can hold. Closes #2234.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@2612 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionpack/lib/action_controller')
-rwxr-xr-xactionpack/lib/action_controller/base.rb3
-rw-r--r--actionpack/lib/action_controller/session/active_record_store.rb32
2 files changed, 31 insertions, 4 deletions
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index a019a4e1fc..6b9456cf1f 100755
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -25,6 +25,9 @@ module ActionController #:nodoc:
end
class MissingFile < ActionControllerError #:nodoc:
end
+ class SessionOverflowError < ActionControllerError #:nodoc:
+ DEFAULT_MESSAGE = 'Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data.'
+ end
class DoubleRenderError < ActionControllerError #:nodoc:
DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and only once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\". Finally, note that to cause a before filter to halt execution of the rest of the filter chain, the filter must return false, explicitly, so \"render(...) and return false\"."
diff --git a/actionpack/lib/action_controller/session/active_record_store.rb b/actionpack/lib/action_controller/session/active_record_store.rb
index 130ce12150..90d9f3fbe1 100644
--- a/actionpack/lib/action_controller/session/active_record_store.rb
+++ b/actionpack/lib/action_controller/session/active_record_store.rb
@@ -33,13 +33,23 @@ class CGI
#
# The fast SqlBypass class is a generic SQL session store. You may
# use it as a basis for high-performance database-specific stores.
+ #
+ # If the data you are attempting to write to the +data+ column is larger
+ # than the column's size limit, ActionController::SessionOverflowError
+ # will be raised.
class ActiveRecordStore
# The default Active Record class.
class Session < ActiveRecord::Base
before_save :marshal_data!
+ before_save :ensure_data_not_too_big
before_update :data_changed?
class << self
+
+ def data_column_size_limit
+ connection.columns(table_name).find {|column| column.name == 'data'}.limit
+ end
+
# Hook to set up sessid compatibility.
def find_by_session_id(session_id)
setup_sessid_compatibility!
@@ -55,7 +65,7 @@ class CGI
CREATE TABLE #{table_name} (
id INTEGER PRIMARY KEY,
#{connection.quote_column_name('session_id')} TEXT UNIQUE,
- #{connection.quote_column_name('data')} TEXT
+ #{connection.quote_column_name('data')} TEXT(255)
)
end_sql
end
@@ -109,6 +119,15 @@ class CGI
old_fingerprint, @fingerprint = @fingerprint, self.class.fingerprint(read_attribute('data'))
old_fingerprint != @fingerprint
end
+
+ # Ensures that the data about to be stored in the database is not
+ # larger than the data storage column. Raises
+ # ActionController::SessionOverflowError.
+ def ensure_data_not_too_big
+ return unless limit = self.class.data_column_size_limit
+ raise ActionController::SessionOverflowError, ActionController::SessionOverflowError::DEFAULT_MESSAGE if read_attribute('data').size > limit
+ end
+
end
# A barebones session store which duck-types with the default session
@@ -126,9 +145,6 @@ class CGI
class SqlBypass
# Use the ActiveRecord::Base.connection by default.
cattr_accessor :connection
- def self.connection
- @@connection ||= ActiveRecord::Base.connection
- end
# The table name defaults to 'sessions'.
cattr_accessor :table_name
@@ -143,6 +159,11 @@ class CGI
@@data_column = 'data'
class << self
+
+ def connection
+ @@connection ||= ActiveRecord::Base.connection
+ end
+
# Look up a session by id and unmarshal its data if found.
def find_by_session_id(session_id)
if record = @@connection.select_one("SELECT * FROM #{@@table_name} WHERE #{@@session_id_column}=#{@@connection.quote(session_id)}")
@@ -201,6 +222,7 @@ class CGI
def save
marshaled_data = self.class.marshal(data)
+
if @new_record
@new_record = false
@@connection.update <<-end_sql, 'Create session'
@@ -231,6 +253,7 @@ class CGI
end_sql
end
end
+
end
# The class used for session storage. Defaults to
@@ -278,6 +301,7 @@ class CGI
@session = nil
end
end
+
end
end
end