1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
# encoding: utf-8
module SimpleCaptcha
class Middleware
include SimpleCaptcha::ImageHelpers
include SimpleCaptcha::ViewHelper
DEFAULT_SEND_FILE_OPTIONS = {
:type => 'application/octet-stream'.freeze,
:disposition => 'attachment'.freeze,
}.freeze
REFRESH_FORMATS = {
:jquery => %Q{
$("#%{id}").attr('src', '%{url}');
$("#%{captcha_hidden_field_id}").attr('value', '%{key}');
}.freeze,
:plain_javascript => %Q{
var img = document.getElementById("%{id}");
if (img != null) {
img.src = "%{url}";
}
var hidden = document.getElementById("%{captcha_hidden_field_id}");
if (hidden != null) {
hidden.value = "%{key}";
}
}.freeze,
:prototype => %Q{
$("%{id}").setAttribute('src', '%{url}');
$("%{captcha_hidden_field_id}").setAttribute('value', '%{key}');
}.freeze,
}.freeze
def initialize(app, options={})
@app = app
self
end
def call(env) # :nodoc:
if env["REQUEST_METHOD"] == "GET" && captcha_path?(env['PATH_INFO'])
request = Rack::Request.new(env)
if request.params.present? && request.params['code'].present?
make_image(env)
else
refresh_code(env)
end
else
@app.call(env)
end
end
protected
def make_image(env, headers = {}, status = 404)
request = Rack::Request.new(env)
code = request.params["code"]
body = []
if Utils::simple_captcha_value(code)
#status, headers, body = @app.call(env)
#status = 200
#body = generate_simple_captcha_image(code)
#headers['Content-Type'] = 'image/jpeg'
send_data(generate_simple_captcha_image(code), :type => 'image/jpeg', :disposition => 'inline', :filename => 'simple_captcha.jpg')
else
[status, headers, body]
end
end
def captcha_path?(request_path)
request_path.include?('/simple_captcha')
end
def send_file(path, options = {})
raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path)
options[:filename] ||= File.basename(path) unless options[:url_based_filename]
status = options[:status] || 200
headers = {"Content-Disposition" => "#{options[:disposition]}; filename='#{options[:filename]}'", "Content-Type" => options[:type], 'Content-Transfer-Encoding' => 'binary', 'Cache-Control' => 'private'}
response_body = File.open(path, "rb")
[status, headers, response_body]
end
def send_data(response_body, options = {})
status = options[:status] || 200
headers = {"Content-Disposition" => "#{options[:disposition]}; filename='#{options[:filename]}'", "Content-Type" => options[:type], 'Content-Transfer-Encoding' => 'binary', 'Cache-Control' => 'private'}
[status, headers, [response_body]]
end
def refresh_code(env)
request = Rack::Request.new(env)
request.session.delete :captcha
key = simple_captcha_key(nil, request)
options = {}
options[:field_value] = set_simple_captcha_data(key, options)
url = simple_captcha_image_url(key, options)
status = 200
id = request.params['id']
captcha_hidden_field_id = simple_captch_hidden_field_id(id)
format = SimpleCaptcha.refresh_format.to_sym
raise ::ArgumentError, "Format adapter '#{format}' is not available" unless format.in?(REFRESH_FORMATS)
body = REFRESH_FORMATS[format] % {id: id, url: url, captcha_hidden_field_id: captcha_hidden_field_id, key: key}
headers = {'Content-Type' => 'text/javascript; charset=utf-8', "Content-Disposition" => "inline; filename='captcha.js'", "Content-Length" => body.length.to_s}.merge(SimpleCaptcha.extra_response_headers)
[status, headers, [body]]
end
end
end
|