module Roda::RodaPlugins::Sessions::RequestMethods

def _deserialize_session(data)

Interpret given cookie data as a Rack::Session::Cookie
def _deserialize_session(data)
  opts = roda_class.opts[:sessions]
  begin
    data = Base64.urlsafe_decode64(data)
  rescue ArgumentError
    return _session_serialization_error("Unable to decode session: invalid base64")
  end
  length = data.bytesize
  if data.length < 61
    # minimum length (1+16+12+32) (version+cipher_iv+minimum session+hmac)
    # 1 : version
    # 16 : cipher_iv
    # 12 : minimum_session
    #      2 : bitmap for gzip + padding info
    #      4 : creation time
    #      4 : update time
    #      2 : data
    # 32 : HMAC-SHA-256
    return _session_serialization_error("Unable to decode session: data too short")
  end
  unless data.getbyte(0) == 0
    # version marker
    return _session_serialization_error("Unable to decode session: version marker unsupported")
  end
  encrypted_data = data.slice!(0, length-32)
  unless Rack::Utils.secure_compare(data, OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, opts[:hmac_secret], encrypted_data+opts[:key]))
    if opts[:old_hmac_secret] && Rack::Utils.secure_compare(data, OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, opts[:old_hmac_secret], encrypted_data+opts[:key]))
      use_old_cipher_secret = true
    else
      return _session_serialization_error("Not decoding session: HMAC invalid")
    end
  end
  encrypted_data.slice!(0)
  cipher = OpenSSL::Cipher.new("aes-256-ctr")
  # Not rescuing cipher errors.  If there is an error in the decryption, that's
  # either a bug in the plugin that needs to be fixed, or an attacker is already
  # able to forge a valid HMAC, in which case the error should be raised to
  # alert the application owner about the problem.
  cipher.decrypt
  cipher.key = opts[use_old_cipher_secret ? :old_cipher_secret : :cipher_secret]
  cipher_iv = cipher.iv = encrypted_data.slice!(0, 16)
  data = cipher.update(encrypted_data) << cipher.final
  bitmap, created_at, updated_at = data.unpack('vVV')
  padding_bytes = bitmap & PADDING_MASK
  if (max = opts[:max_seconds]) && Time.now.to_i > created_at + max
    return _session_serialization_error("Not returning session: maximum session time expired")
  end
  if (max = opts[:max_idle_seconds]) && Time.now.to_i > updated_at + max
    return _session_serialization_error("Not returning session: maximum session idle time expired")
  end
  data = data.slice(10+padding_bytes, data.bytesize)
  if bitmap & DEFLATE_BIT > 0
    data = Zlib::Inflate.inflate(data)
  end
  env = @env
  env[SESSION_CREATED_AT] = created_at
  env[SESSION_UPDATED_AT] = updated_at
  env[SESSION_SERIALIZED] = data
  opts[:parser].call(data)
end