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
  case version = data.getbyte(0)
  when 1
    per_cookie_secret = true
    # minimum length (1+32+16+12+32) (version+random_data+cipher_iv+minimum session+hmac)
    # 1 : version
    # 32 : random_data (if per_cookie_cipher_secret)
    # 16 : cipher_iv
    # 12 : minimum_session
    #      2 : bitmap for gzip + padding info
    #      4 : creation time
    #      4 : update time
    #      2 : data
    # 32 : HMAC-SHA-256
    min_data_length = 93
  when 0
    per_cookie_secret = false
    # minimum length (1+16+12+32) (version+cipher_iv+minimum session+hmac)
    min_data_length = 61
  when nil
    return _session_serialization_error("Unable to decode session: no data")
  else
    return _session_serialization_error("Unable to decode session: version marker unsupported")
  end
  length = data.bytesize
  if data.length < min_data_length
    return _session_serialization_error("Unable to decode session: data too short")
  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
  # Remove version
  encrypted_data.slice!(0)
  cipher_secret = opts[use_old_cipher_secret ? :old_cipher_secret : :cipher_secret]
  if per_cookie_secret
    cipher_secret = OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, cipher_secret, encrypted_data.slice!(0, 32))
  end
  cipher_iv = encrypted_data.slice!(0, 16)
  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 = cipher_secret
  cipher.iv = cipher_iv
  data = cipher.update(encrypted_data) << cipher.final
  bitmap, created_at, updated_at = data.unpack('vVV')
  padding_bytes = bitmap & PADDING_MASK
  now = Time.now.to_i
  if (max = opts[:max_seconds]) && now > created_at + max
    return _session_serialization_error("Not returning session: maximum session time expired")
  end
  if (max = opts[:max_idle_seconds]) && now > 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
  env[SESSION_VERSION_NUM] = version
  opts[:parser].call(data)
end