lib/evercookie/controller.rb
module Evercookie
# defines controller helpers
module ControllerHelpers
# Get value of evercookie by key
# == Examples:
# evercookie_get_value(:key)
#
def evercookie_get_value(key)
if session[Evercookie.hash_name_for_saved].present?
session[Evercookie.hash_name_for_saved][key]
else
nil
end
end
# Set evercookie value to session
# == Examples:
# set_evercookie(:key, :value)
#
def set_evercookie(key, value)
session[Evercookie.hash_name_for_saved] = {} unless
session[Evercookie.hash_name_for_saved].present?
session[Evercookie.hash_name_for_saved][key] = value
end
# Checks whether the evercookie with specific key was defined
# == Examples:
# evercookie_is_set?(:key)
# evercookie_is_set?(:key, :value)
#
def evercookie_is_set?(key, value = nil)
if session[Evercookie.hash_name_for_saved].blank?
false
elsif value.nil?
session[Evercookie.hash_name_for_saved][key].present?
else
session[Evercookie.hash_name_for_saved][key].present? \
&& session[Evercookie.hash_name_for_saved][key] == value
end
end
end
# controller class defines evercookie actions
class EvercookieController < ::ActionController::Base
before_filter :basic_auth, only: [ :ec_auth ]
# Renders javascript with evercookie set script
def set
@data = session[Evercookie.hash_name_for_set] || {key: '', value: ''}
end
# Renders javascript with evercookie get script
def get
@data = session[Evercookie.hash_name_for_get] || {key: '', value: ''}
end
# Saves current evercookie value to session
def save
if data = session[Evercookie.hash_name_for_get]
if data[:key] && cookies[data[:key]]
session[Evercookie.hash_name_for_saved] =
{ data[:key] => cookies[data[:key]] }
end
end
render nothing: true
end
# Renders png image with encoded evercookie value in it
def ec_png
if not cookies[Evercookie.cookie_png].present?
render :nothing => true, :status => 304
return true
end
response.headers["Content-Type"] = "image/png"
response.headers["Last-Modified"] = "Wed, 30 Jun 2010 21:36:48 GMT"
response.headers["Expires"] = "Tue, 31 Dec 2030 23:30:45 GMT"
response.headers["Cache-Control"] = "private, max-age=630720000"
render text: get_blob_png, status: 200, content_type: 'image/png'
end
# Renders page with etag header for evercookie js script
def ec_etag
if not cookies[Evercookie.cookie_etag].present?
render :text => request.headers['If-None-Match'] || '', :status => 304
return true
end
puts "cache value (#{Evercookie.cookie_etag}): #{cookies[Evercookie.cookie_etag]}"
response.headers["Etag"] = cookies[Evercookie.cookie_etag]
render text: cookies[Evercookie.cookie_etag]
end
# Renders page with cache header for evercookie js script
def ec_cache
if not cookies[Evercookie.cookie_cache].present?
render :nothing => true, :status => 304
return true
end
puts "cache value (#{Evercookie.cookie_cache}): #{cookies[Evercookie.cookie_cache]}"
response.headers["Content-Type"] = "text/html"
response.headers["Last-Modified"] = "Wed, 30 Jun 2010 21:36:48 GMT"
response.headers["Expires"] = "Tue, 31 Dec 2030 23:30:45 GMT"
response.headers["Cache-Control"] = "private, max-age=630720000"
render text: cookies[Evercookie.cookie_cache]
end
# Renders evercookie value for basic authentication if it was set
def ec_auth
render text: @username
end
private
def basic_auth
authenticate_with_http_basic do |username, password|
@username = username
true
end
end
def get_blob_png
value = cookies[Evercookie.cookie_png]
puts "png value (#{Evercookie.cookie_png}): #{value}"
require 'chunky_png'
image = ChunkyPNG::Image.new(200, 1, ChunkyPNG::Color::BLACK)
(0..value.length).step(3) do |index|
image[(index / 3).round, 0] = get_pixel_by_index(value, index)
end
image.to_blob(
{color_mode: ChunkyPNG::COLOR_TRUECOLOR,
compression: Zlib::DEFAULT_COMPRESSION}
)
end
def get_pixel_by_index(value, index)
red = value[index] ? value[index].ord : 0
green = value[index + 1] ? value[index + 1].ord : 0
blue = value[index + 2] ? value[index + 2].ord : 0
ChunkyPNG::Color.rgb(red, green, blue)
end
end
end