simple_captcha2-0.5.0/0000755000004100000410000000000013576031220014601 5ustar www-datawww-datasimple_captcha2-0.5.0/README.md0000644000004100000410000002203713576031220016064 0ustar www-datawww-data# SimpleCaptcha2 [![Build Status](https://travis-ci.org/pludoni/simple-captcha.png?branch=master)](https://travis-ci.org/pludoni/simple-captcha) [![Gem Version](https://badge.fury.io/rb/simple_captcha2.svg)](https://badge.fury.io/rb/simple_captcha2) SimpleCaptcha(2) is the simplest and a robust captcha plugin. Its implementation requires adding up a single line in views and in controllers/models. SimpleCaptcha2 is available to be used with Rails 3 + 4. This is a fork of the popular Rubygem ``simple_captcha`` which got abandoned. ## Features * Zero FileSystem usage (secret code moved to db-store and image storage removed). * Provides various image styles. * Provides three level of complexity of images. * Works absolutely fine in distributed environment(session and db based implementation works fine in distributed environment). * Implementation is as easy as just writing a single line in your view. ```<%= show_simple_captcha %>``` within the 'form' tags. * Flexible DOM and CSS handling(There is a separate view partial for rendering SimpleCaptcha DOM elements). * Automated removal of 1 hour old unmatched simple_captcha data. ## Requirements * Ruby >= 1.9.3 * Rails >= 3.2 * ImageMagick should be installed on your machine to use this plugin. visit http://www.imagemagick.org/script/index.php for more details. ## Installation You might need to install Ghostscript on a Mac-System or a Debian-System: ``` brew install ghostscript ``` ``` apt-get install ghostscript ``` The default font, that imagemagick uses is Arial. Make sure that font is available (``apt install ttf-mscorefonts-installer``) or change the font in the SimpleCaptcha config. Put this into your Gemfile ```ruby gem 'simple_captcha2', require: 'simple_captcha' ``` and run ``bundle install``. ## Setup After installation, follow these simple steps to setup the plugin. The setup will depend on the version of rails your application is using. ```bash rails generate simple_captcha [template_format] # Available options erb, haml. Default: erb rake db:migrate # Mongoid: skip this step and remove the migration ``` ## Usage There are two usage scenarios: ### Controller Based Add the following line in the file "app/controllers/application.rb" ```ruby ApplicationController < ActionController::Base include SimpleCaptcha::ControllerHelpers end ``` In the view file within the form tags add this code ```erb <%= show_simple_captcha %> ``` and in the controller's action authenticate it as ```ruby if simple_captcha_valid? do this else do that end ``` ### Model Based This is suggested, if you want to integrate the error message into the normal form validation flow. In the view file within the form tags write this code ```erb <%= show_simple_captcha(:object=>"user") %> ``` and in the model class add this code ```ruby class User < ActiveRecord::Base apply_simple_captcha end ``` Mongoid: ```ruby class User include SimpleCaptcha::ModelHelpers apply_simple_captcha end ``` #### Strong parameters (Rails 4.x) Must add them: ```ruby :captcha, :captcha_key ``` #### Form-Builder helper ```erb <%= form_for @user do |form| -%> ... <%= form.simple_captcha :label => "Enter numbers.." %> ... <% end -%> ``` #### Validating with captcha NOTE: @user.valid? will still work as it should, it will not validate the captcha code. ```ruby @user.valid_with_captcha? ``` #### Saving with captcha NOTE: @user.save will still work as it should, it will not validate the captcha code. ```ruby @user.save_with_captcha ``` ### Formtastic integration SimpleCaptcha detects if you are using Formtastic: ```erb <%= form.input :captcha, :as => :simple_captcha %> ``` ### Tests You can make the Captcha always pass with a initializer file: config/initializers/simple_captcha.rb ```ruby SimpleCaptcha.always_pass = Rails.env.test? ``` You can also ask for the value, e.g. Acceptance Tests/Features: ```ruby visit '/pages/form_tag' assert_equal 1, SimpleCaptcha::SimpleCaptchaData.count fill_in 'captcha', with: SimpleCaptcha::SimpleCaptchaData.first.value ``` ## ORM support simple-captcha2 supports 3 type of ORM: ActiveRecord, Sequel and Mongoid. Selection of ORM is base on loaded classes. If `ActiveRecord` is loaded then it will be used for the simple captcha data model. If `ActiveRecord` is undefined, `Sequel` presence is tested. If `Sequel` is defined it will used for the simple captcha data model. If not, `Mongoid` is used. For instance if your application is using Sequel as an ORM just make sure you require `sequel-rails` gem before `simple-captcha2` in your Gemfile and respective model will be selected automatically. ## Options & Examples ### View Options * ``:label`` - provides the custom text b/w the image and the text field, the default is "type the code from the image" * ``:object`` - the name of the object of the model class, to implement the model based captcha. * ``:code_type`` - return numeric only if set to 'numeric' * ``:multiple`` - allow to use the same captcha in multiple forms in one page. True for the first appaerance and false for the rest. ### Global options * ``:image_style`` - provides the specific image style for the captcha image. There are eight different styles available with the plugin as... 1. simply_blue 2. simply_red 3. simply_green 4. charcoal_grey 5. embosed_silver 6. all_black 7. distorted_black 8. almost_invisible Default style is 'simply_blue'. You can also specify 'random' to select the random image style. * ``:distortion`` - handles the complexity of the image. The :distortion can be set to 'low', 'medium' or 'high'. Default is 'low'. * ``:implode`` - handles the complexity of the image. The :implode can be set to 'none', 'low', 'medium' or 'high'. Default is 'medium'. Create "./config/initializers/simple_captcha.rb" ```ruby SimpleCaptcha.setup do |sc| # default: 100x28 sc.image_size = '120x40' # default: 5 sc.length = 6 # default: simply_blue # possible values: # 'embosed_silver', # 'simply_red', # 'simply_green', # 'simply_blue', # 'distorted_black', # 'all_black', # 'charcoal_grey', # 'almost_invisible' # 'random' sc.image_style = 'simply_green' # default: low # possible values: 'low', 'medium', 'high', 'random' sc.distortion = 'medium' # default: medium # possible values: 'none', 'low', 'medium', 'high' sc.implode = 'low' end ``` You can add your own style: ```ruby SimpleCaptcha.setup do |sc| sc.image_style = 'mycaptha' sc.add_image_style('mycaptha', [ "-background '#F4F7F8'", "-fill '#86818B'", "-border 1", "-bordercolor '#E0E2E3'"]) end ``` You can provide the path where image_magick is installed as well: ```ruby SimpleCaptcha.setup do |sc| sc.image_magick_path = '/usr/bin' # you can check this from console by running: which convert end ``` You can setup in which format the reload of the captcha is executed: ```ruby SimpleCaptcha.setup do |sc| sc.refresh_format = :prototype # or :jquery, or :plain_javascript default is :jquery end ``` If needed, you can explicitly state the font used for generating the captcha: ```ruby SimpleCaptcha.setup do |sc| sc.font = "DejaVu-Sans" end ``` ### How to change the CSS for SimpleCaptcha DOM elements? You can change the CSS of the SimpleCaptcha DOM elements as per your need in this file. ``app/views/simple_captcha/_simple_captcha.erb`` ### View's Examples #### Controller Based Example ```erb <%= show_simple_captcha %> <%= show_simple_captcha(:label => "human authentication") %> ``` #### Model Based Example ```erb <%= show_simple_captcha(:object => 'user', :label => "human authentication") %> ``` #### Model Options * ``:message`` - provides the custom message on failure of captcha authentication the default is "Secret Code did not match with the Image" * ``:add_to_base`` - if set to true, appends the error message to the base. ##### Model's Example ```ruby class User < ActiveRecord::Base apply_simple_captcha end class User < ActiveRecord::Base apply_simple_captcha :message => "The secret Image and code were different", :add_to_base => true end ``` ## I18n ```yaml en: simple_captcha: placeholder: "Enter the image value" label: "Enter the code in the box:" refresh_button_text: "Refresh" message: default: "Secret Code did not match with the Image" user: "The secret Image and code were different" ``` ## Contributing For testing, generate a temporary Rails dummy app inside test: ```bash bundle bundle exec rake dummy:setup bundle exec rake app:db:migrate bundle exec rake app:db:migrate RAILS_ENV=test bundle exec rake test ``` Please add test cases when adding new functionality. I started with some basic example integration tests for a very basic coverage. The tests will be run on [Travis-CI](https://travis-ci.org/pludoni/simple-captcha). ## Who's who? Enjoy the simplest captcha implementation. Original Author of the Version for Rails 2: Author: Sur, Blog: http://expressica.com, Contact: sur.max@gmail.com Plugin Homepage: http://expressica.com/simple_captcha Plugin update for rails 3: http://github.com/galetahub update for Rails 4, tests and forked by Stefan Wienert (pludoni GmbH) simple_captcha2-0.5.0/Rakefile0000644000004100000410000000310013576031220016240 0ustar www-datawww-databegin require 'bundler/setup' rescue LoadError puts 'You must `gem install bundler` and `bundle install` to run rake tasks' end require 'rdoc/task' RDoc::Task.new(:rdoc) do |rdoc| rdoc.rdoc_dir = 'rdoc' rdoc.title = 'SimpleCaptcha' rdoc.options << '--line-numbers' rdoc.rdoc_files.include('README.rdoc') rdoc.rdoc_files.include('lib/**/*.rb') end APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__) if File.exist? APP_RAKEFILE load 'rails/tasks/engine.rake' end namespace :dummy do desc 'Setup dummy Rails app for test purpose' task :setup do require 'rails' require 'simple_captcha' if ENV["SEQUEL"].nil? require File.expand_path('../test/lib/generators/simple_captcha/dummy/dummy_generator', __FILE__) generator_class = SimpleCaptcha::DummyGenerator else require File.expand_path('../test/lib/generators/simple_captcha/dummy/dummy_generator_sequel', __FILE__) generator_class = SimpleCaptcha::DummyGeneratorSequel end generator_class.start %w(--quiet) end desc 'destroy dummy Rails app under test/dummy' task :destroy do FileUtils.rm_rf "test/dummy" if File.exist?("test/dummy") end desc 'redo' task :redo do sh 'rake dummy:destroy' sh 'rake dummy:setup' sh 'rake app:db:migrate' sh 'rake app:db:migrate RAILS_ENV=test' end end Bundler::GemHelper.install_tasks :name => 'simple_captcha2' require 'rake/testtask' Rake::TestTask.new(:test) do |t| t.libs << 'lib' t.libs << 'test' t.pattern = 'test/**/*_test.rb' t.verbose = false end task default: :test simple_captcha2-0.5.0/lib/0000755000004100000410000000000013576031220015347 5ustar www-datawww-datasimple_captcha2-0.5.0/lib/simple_captcha.rb0000644000004100000410000000417013576031220020652 0ustar www-datawww-data# encoding: utf-8 module SimpleCaptcha class << self attr_accessor :always_pass end self.always_pass = Rails.env.test? autoload :Utils, 'simple_captcha/utils' autoload :ImageHelpers, 'simple_captcha/image' autoload :ViewHelper, 'simple_captcha/view' autoload :ControllerHelpers, 'simple_captcha/controller' autoload :FormBuilder, 'simple_captcha/form_builder' autoload :CustomFormBuilder, 'simple_captcha/formtastic' autoload :ModelHelpers, 'simple_captcha/model_helpers' if defined?(ActiveRecord) autoload :SimpleCaptchaData, 'simple_captcha/simple_captcha_data' elsif defined?(Sequel) autoload :SimpleCaptchaData, 'simple_captcha/simple_captcha_data_sequel' else autoload :SimpleCaptchaData, 'simple_captcha/simple_captcha_data_mongoid.rb' end autoload :Middleware, 'simple_captcha/middleware' mattr_accessor :image_size @@image_size = "100x28" mattr_accessor :length @@length = 5 # 'embosed_silver', # 'simply_red', # 'simply_green', # 'simply_blue', # 'distorted_black', # 'all_black', # 'charcoal_grey', # 'almost_invisible' # 'random' mattr_accessor :image_style @@image_style = 'simply_blue' # 'low', 'medium', 'high', 'random' mattr_accessor :distortion @@distortion = 'low' # 'none', 'low', 'medium', 'high' mattr_accessor :implode @@implode = SimpleCaptcha::ImageHelpers::DEFAULT_IMPLODE # 'jquery', 'prototype' mattr_accessor :refresh_format @@refresh_format = :jquery # command path mattr_accessor :image_magick_path @@image_magick_path = '' # tmp directory mattr_accessor :tmp_path @@tmp_path = nil # additive noise mattr_accessor :noise @@noise = 0 # used font mattr_accessor :font @@font = '' mattr_accessor :extra_response_headers @@extra_response_headers = {} mattr_accessor :partial_path @@partial_path = 'simple_captcha/simple_captcha' def self.add_image_style(name, params = []) SimpleCaptcha::ImageHelpers.image_styles.update(name.to_s => params) end def self.setup yield self end end require 'simple_captcha/engine' if defined?(Rails) simple_captcha2-0.5.0/lib/simple_captcha2.rb0000644000004100000410000000003113576031220020724 0ustar www-datawww-datarequire 'simple_captcha' simple_captcha2-0.5.0/lib/generators/0000755000004100000410000000000013576031220017520 5ustar www-datawww-datasimple_captcha2-0.5.0/lib/generators/templates/0000755000004100000410000000000013576031220021516 5ustar www-datawww-datasimple_captcha2-0.5.0/lib/generators/templates/migration5.rb0000644000004100000410000000053313576031220024122 0ustar www-datawww-dataclass CreateSimpleCaptchaData < ActiveRecord::Migration[4.2] def self.up create_table :simple_captcha_data do |t| t.string :key, :limit => 40 t.string :value, :limit => 6 t.timestamps end add_index :simple_captcha_data, :key, :name => "idx_key" end def self.down drop_table :simple_captcha_data end end simple_captcha2-0.5.0/lib/generators/templates/partial.haml0000644000004100000410000000162413576031220024020 0ustar www-datawww-data:css .simple_captcha{border: 1px solid #ccc; padding: 5px !important;} .simple_captcha, .simple_captcha div{display: table;} .simple_captcha .simple_captcha_field, .simple_captcha .simple_captcha_image{ border: 1px solid #ccc; margin: 0px 0px 2px 0px !important; padding: 0px !important; } .simple_captcha .simple_captcha_image img{ margin: 0px !important; padding: 0px !important; width: 110px !important; } .simple_captcha .simple_captcha_label{font-size: 12px;} .simple_captcha .simple_captcha_field input{ width: 150px !important; font-size: 16px; border: none; background-color: #efefef; } .simple_captcha .simple_captcha_image= simple_captcha_options[:image] .simple_captcha_field= simple_captcha_options[:field] .simple_captcha_label= simple_captcha_options[:label] .simple_captcha_refresh_button= simple_captcha_options[:refresh_button] simple_captcha2-0.5.0/lib/generators/templates/migration.rb0000644000004100000410000000053213576031220024034 0ustar www-datawww-dataclass CreateSimpleCaptchaData < ActiveRecord::Migration def self.up create_table :simple_captcha_data do |t| t.string :key, :limit => 40 t.string :value, :limit => 6 t.timestamps end add_index :simple_captcha_data, :key, :name => "idx_key" end def self.down drop_table :simple_captcha_data end end simple_captcha2-0.5.0/lib/generators/templates/migration_sequel.rb0000644000004100000410000000046413576031220025416 0ustar www-datawww-dataSequel.migration do up do create_table :simple_captcha_data do primary_key :id String :key, size: 40 String :value, size: 6 DateTime :created_at DateTime :updated_at index :key, name: "idx_key" end end down do drop_table :simple_captcha_data end end simple_captcha2-0.5.0/lib/generators/templates/partial.erb0000644000004100000410000000211313576031220023641 0ustar www-datawww-data
<%%= simple_captcha_options[:image] %>
<%%= simple_captcha_options[:field] %>
<%%= simple_captcha_options[:label] %>
<%%= simple_captcha_options[:refresh_button] %>
simple_captcha2-0.5.0/lib/generators/simple_captcha_generator.rb0000644000004100000410000000150413576031220025067 0ustar www-datawww-datarequire 'rails/generators' class SimpleCaptchaGenerator < Rails::Generators::Base argument :template_format, :type => :string, :default => 'erb' include Rails::Generators::Migration def self.source_root @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates/')) end def self.next_migration_number(dirname) Time.now.strftime("%Y%m%d%H%M%S") end def create_partial template "partial.#{template_format}", File.join('app/views', 'simple_captcha', "_simple_captcha.#{template_format}") end def create_captcha_migration migration_template migration_file, File.join('db/migrate', "create_simple_captcha_data.rb") end private def migration_file return "migration_sequel.rb" if defined?(Sequel) Rails::VERSION::MAJOR > 4 ? "migration5.rb" : "migration.rb" end end simple_captcha2-0.5.0/lib/generators/USAGE0000644000004100000410000000045013576031220020306 0ustar www-datawww-dataSimpleCaptcha ============= # Generate migration and copy view partial rails generate simple_captcha [template_format] template_format Sets template format to be generated Available options: erb, haml Default: erb simple_captcha2-0.5.0/lib/simple_captcha/0000755000004100000410000000000013576031220020323 5ustar www-datawww-datasimple_captcha2-0.5.0/lib/simple_captcha/version.rb0000644000004100000410000000006413576031220022335 0ustar www-datawww-datamodule SimpleCaptcha VERSION = "0.5.0".freeze end simple_captcha2-0.5.0/lib/simple_captcha/image.rb0000644000004100000410000000573013576031220021737 0ustar www-datawww-datarequire 'tempfile' module SimpleCaptcha #:nodoc module ImageHelpers #:nodoc mattr_accessor :image_styles @@image_styles = { 'embosed_silver' => ['-fill darkblue', '-shade 20x60', '-background white'], 'simply_red' => ['-fill darkred', '-background white'], 'simply_green' => ['-fill darkgreen', '-background white'], 'simply_blue' => ['-fill darkblue', '-background white'], 'distorted_black' => ['-fill darkblue', '-edge 10', '-background white'], 'all_black' => ['-fill darkblue', '-edge 2', '-background white'], 'charcoal_grey' => ['-fill darkblue', '-charcoal 5', '-background white'], 'almost_invisible' => ['-fill red', '-solarize 50', '-background white'] } DISTORTIONS = ['low', 'medium', 'high'] IMPLODES = { 'none' => 0, 'low' => 0.1, 'medium' => 0.2, 'high' => 0.3 } DEFAULT_IMPLODE = 'medium' class << self def image_params(key = 'simply_blue') image_keys = @@image_styles.keys style = begin if key == 'random' image_keys[rand(image_keys.length)] else image_keys.include?(key) ? key : 'simply_blue' end end @@image_styles[style] end def distortion(key='low') key = key == 'random' ? DISTORTIONS[rand(DISTORTIONS.length)] : DISTORTIONS.include?(key) ? key : 'low' case key.to_s when 'low' then return [0 + rand(2), 80 + rand(20)] when 'medium' then return [2 + rand(2), 50 + rand(20)] when 'high' then return [4 + rand(2), 30 + rand(20)] end end def implode IMPLODES[SimpleCaptcha.implode] || IMPLODES[DEFAULT_IMPLODE] end end if RUBY_VERSION < '1.9' class Tempfile < ::Tempfile # Replaces Tempfile's +make_tmpname+ with one that honors file extensions. def make_tmpname(basename, n = 0) extension = File.extname(basename) sprintf("%s,%d,%d%s", File.basename(basename, extension), $$, n, extension) end end end private def generate_simple_captcha_image(simple_captcha_key) #:nodoc amplitude, frequency = ImageHelpers.distortion(SimpleCaptcha.distortion) text = Utils::simple_captcha_value(simple_captcha_key) params = ImageHelpers.image_params(SimpleCaptcha.image_style).dup params << "-size #{SimpleCaptcha.image_size}" params << "-wave #{amplitude}x#{frequency}" params << "-gravity Center" params << "-pointsize 22" params << "-implode #{ImageHelpers.implode}" unless SimpleCaptcha.font.empty? params << "-font #{SimpleCaptcha.font}" end params << "label:#{text}" if SimpleCaptcha.noise and SimpleCaptcha.noise > 0 params << "-evaluate Uniform-noise #{SimpleCaptcha.noise}" end params << "jpeg:-" SimpleCaptcha::Utils::run("convert", params.join(' ')) end end end simple_captcha2-0.5.0/lib/simple_captcha/model_helpers.rb0000644000004100000410000000456213576031220023501 0ustar www-datawww-datamodule SimpleCaptcha #:nodoc module ModelHelpers #:nodoc def self.included(base) base.extend(SingletonMethods) end # To implement model based simple captcha use this method in the model as... # # class User < ActiveRecord::Base # # apply_simple_captcha :message => "my customized message" # # end # # Customize the error message by using :message, the default message is "Captcha did not match". # As in the applications captcha is needed with a very few cases like signing up the new user, but # not every time you need to authenticate the captcha with @user.save. So as to maintain simplicity # here we have the explicit method to save the instace with captcha validation as... # # * to validate the instance # # @user.valid_with_captcha? # whene captcha validation is required. # # @user.valid? # when captcha validation is not required. # # * to save the instance # # @user.save_with_captcha # whene captcha validation is required. # # @user.save # when captcha validation is not required. module SingletonMethods def apply_simple_captcha(options = {}) options = { :add_to_base => false }.merge(options) class_attribute :simple_captcha_options self.simple_captcha_options = options unless self.is_a?(ClassMethods) include InstanceMethods extend ClassMethods attr_accessor :captcha, :captcha_key end end end module ClassMethods end module InstanceMethods def valid_with_captcha? [valid?, is_captcha_valid?].all? end def is_captcha_valid? return true if SimpleCaptcha.always_pass if captcha && captcha.upcase.delete(" ") == SimpleCaptcha::Utils::simple_captcha_value(captcha_key) SimpleCaptcha::Utils::simple_captcha_passed!(captcha_key) return true else message = simple_captcha_options[:message] || I18n.t(self.class.model_name.to_s.downcase, :scope => [:simple_captcha, :message], :default => :default) simple_captcha_options[:add_to_base] ? errors.add(:base, message) : errors.add(:captcha, message) return false end end def save_with_captcha valid_with_captcha? && save(:validate => false) end end end end simple_captcha2-0.5.0/lib/simple_captcha/simple_captcha_data_sequel.rb0000644000004100000410000000073413576031220026177 0ustar www-datawww-datamodule SimpleCaptcha class SimpleCaptchaData < Sequel::Model plugin :update_or_create plugin :timestamps, update_on_create: true class << self def get_data(key) find_or_new(key: key) end def remove_data(key) where(key: key).delete clear_old_data(1.hour.ago) end def clear_old_data(time = 1.hour.ago) return unless Time === time where {updated_at < time}.delete end end end end simple_captcha2-0.5.0/lib/simple_captcha/simple_captcha_data.rb0000644000004100000410000000200613576031220024613 0ustar www-datawww-datamodule SimpleCaptcha class SimpleCaptchaData < ::ActiveRecord::Base if ::ActiveRecord::VERSION::MAJOR >= 3 # Fixes deprecation warning in Rails 3.2: # DEPRECATION WARNING: Calling set_table_name is deprecated. Please use `self.table_name = 'the_name'` instead. self.table_name = "simple_captcha_data" else set_table_name "simple_captcha_data" end if ::ActiveRecord::VERSION::MAJOR == 3 and defined? attr_protected attr_protected end class << self def get_data(key) where(key: key).first_or_initialize end def remove_data(key) where(["#{connection.quote_column_name(:key)} = ?", key]).delete_all clear_old_data(1.hour.ago) end def clear_old_data(time = 1.hour.ago) return unless Time === time where(["#{connection.quote_column_name(:updated_at)} < ?", time]).delete_all rescue ActiveRecord::Deadlocked => err Rails.logger.error "#{err.class} #{err.message}" end end end end simple_captcha2-0.5.0/lib/simple_captcha/engine.rb0000644000004100000410000000114413576031220022115 0ustar www-datawww-data# encoding: utf-8 require 'rails' module SimpleCaptcha class Engine < ::Rails::Engine config.before_initialize do ActiveSupport.on_load :active_record do ActiveRecord::Base.send(:include, SimpleCaptcha::ModelHelpers) end end config.after_initialize do ActionView::Base.send(:include, SimpleCaptcha::ViewHelper) ActionView::Helpers::FormBuilder.send(:include, SimpleCaptcha::FormBuilder) if Object.const_defined?("Formtastic") require 'simple_captcha/formtastic' end end config.app_middleware.use SimpleCaptcha::Middleware end end simple_captcha2-0.5.0/lib/simple_captcha/form_builder.rb0000644000004100000410000000260213576031220023321 0ustar www-datawww-datamodule SimpleCaptcha module FormBuilder def self.included(base) base.send(:include, SimpleCaptcha::ViewHelper) base.send(:include, SimpleCaptcha::FormBuilder::ClassMethods) base.send(:include, ActionView::Helpers) if defined? Sprockets::Helpers base.send(:include, Sprockets::Helpers::RailsHelper) base.send(:include, Sprockets::Helpers::IsolatedHelper) end base.delegate :render, :session, :to => :template end module ClassMethods # Example: # <% form_for :post, :url => posts_path do |form| %> # ... # <%= form.simple_captcha :label => "Enter numbers.." %> # <% end %> # def simple_captcha(options = {}) options.update :object => @object_name show_simple_captcha(objectify_options(options)) end private def template @template end def simple_captcha_field(options={}) html = {:autocomplete => 'off', :autocorrect => 'off', :autocapitalize => 'off', :required => 'required', :value => ''} html.merge!(options[:input_html] || {}) html[:placeholder] = options[:placeholder] || I18n.t('simple_captcha.placeholder') text_field(:captcha, html) + hidden_field(:captcha_key, {:value => options[:field_value], :id => simple_captch_hidden_field_id(options)}) end end end end simple_captcha2-0.5.0/lib/simple_captcha/utils.rb0000644000004100000410000000175413576031220022017 0ustar www-datawww-datarequire 'digest/sha1' module SimpleCaptcha #:nodoc module Utils #:nodoc # Execute command with params and return output if exit status equal expected_outcodes def self.run(cmd, params = "", expected_outcodes = 0) command = %Q[#{cmd} #{params}].gsub(/\s+/, " ") command = "#{command} 2>&1" unless (image_magick_path = SimpleCaptcha.image_magick_path).blank? command = File.join(image_magick_path, command) end output = `#{command}` unless [expected_outcodes].flatten.include?($?.exitstatus) raise ::StandardError, "Error while running #{cmd}: #{output}" end output end def self.simple_captcha_value(key) #:nodoc SimpleCaptchaData.get_data(key).value rescue nil end def self.simple_captcha_passed!(key) #:nodoc SimpleCaptchaData.remove_data(key) end def self.generate_key(*args) args << (Time.now.to_f * 1_000_000_000).to_s Digest::SHA1.hexdigest(args.join) end end end simple_captcha2-0.5.0/lib/simple_captcha/simple_captcha_data_mongoid.rb0000644000004100000410000000106513576031220026333 0ustar www-datawww-datamodule SimpleCaptcha class SimpleCaptchaData include Mongoid::Document include Mongoid::Timestamps field :key, type: String field :value, type: String class << self def get_data(key) data = where(:key => key).first || new(:key => key) end def remove_data(key) where(:key => key).delete_all clear_old_data(1.hour.ago) end def clear_old_data(time = 1.hour.ago) return unless Time === time where(:updated_at.lte => time).delete_all end end end end simple_captcha2-0.5.0/lib/simple_captcha/view.rb0000644000004100000410000001322413576031220021624 0ustar www-datawww-datamodule SimpleCaptcha #:nodoc module ViewHelper #:nodoc # Simple Captcha is a very simplified captcha. # # It can be used as a *Model* or a *Controller* based Captcha depending on what options # we are passing to the method show_simple_captcha. # # *show_simple_captcha* method will return the image, the label and the text box. # This method should be called from the view within your form as... # # <%= show_simple_captcha %> # # The available options to pass to this method are # * label # * object # # Label: # # default label is "type the text from the image", it can be modified by passing :label as # # <%= show_simple_captcha(:label => "new captcha label") %>. # # *Object* # # This option is needed to create a model based captcha. # If this option is not provided, the captcha will be controller based and # should be checked in controller's action just by calling the method simple_captcha_valid? # # To make a model based captcha give this option as... # # <%= show_simple_captcha(:object => "user") %> # and also call the method apply_simple_captcha in the model # this will consider "user" as the object of the model class. # # *Examples* # * controller based # <%= show_simple_captcha(:label => "Human Authentication: type the text from image above") %> # * model based # <%= show_simple_captcha(:object => "person", :label => "Human Authentication: type the text from image above") %> # # Find more detailed examples with sample images here on my blog http://EXPRESSICA.com # # All Feedbacks/CommentS/Issues/Queries are welcome. def show_simple_captcha(options = {}) render :partial => SimpleCaptcha.partial_path, :locals => { :simple_captcha_options => simple_captcha_options(options) } end def simple_captcha_options(options = {}) key = simple_captcha_key(options[:object]) if options[:multiple] === false # It's not the first captcha, we only need to return the key options[:field_value] = key else # It's the first captcha in the page, we generate a new key options[:field_value] = set_simple_captcha_data(key, options) end { :image => simple_captcha_image(key, options), :label => I18n.t('simple_captcha.label'), :field => simple_captcha_field(options), :refresh_button => simple_captcha_refresh_button(options), }.merge(options) end private def simple_captcha_image(simple_captcha_key, options = {}) url = simple_captcha_image_url simple_captcha_key, options: options id = simple_captcha_image_id(options) tag('img', :src => url, :alt => 'captcha', :id => id) end def simple_captcha_image_url(simple_captcha_key, options = {}) defaults = {} defaults[:time] = options[:time] || Time.now.to_i query = defaults.to_query path = "/simple_captcha?code=#{simple_captcha_key}&#{query}" build_url(options, path) end def build_url(options, path) if defined?(request) && request "#{request.protocol}#{request.host_with_port}#{ENV['RAILS_RELATIVE_URL_ROOT']}#{path}" else "#{ENV['RAILS_RELATIVE_URL_ROOT']}#{path}" end end def simple_captcha_field(options={}) html = {:autocomplete => 'off', :autocorrect => 'off', :autocapitalize => 'off', :required => 'required'} html.merge!(options[:input_html] || {}) html[:placeholder] = options[:placeholder] || I18n.t('simple_captcha.placeholder') if options[:object] text_field(options[:object], :captcha, html.merge(:value => '')) + hidden_field(options[:object], :captcha_key, {:value => options[:field_value], :id => simple_captch_hidden_field_id(options)}) else text_field_tag(:captcha, nil, html) + hidden_field_tag(:captcha_key, options[:field_value], :id => simple_captch_hidden_field_id(options)) end end def simple_captcha_refresh_button(options={}) html = {remote: true} html.merge!(options[:refresh_button_html] || {}) text = options[:refresh_button_text] || I18n.t('simple_captcha.refresh_button_text', default: 'Refresh') url = build_url(options, "/simple_captcha?id=#{simple_captcha_image_id(options)}") link_to(text, url, html) end def simple_captcha_image_id(options={}) "simple_captcha-#{options[:field_value][0..10]}" end def simple_captch_hidden_field_id(image_id) image_id = simple_captcha_image_id(image_id) if image_id.is_a?(Hash) "simple-captcha-hidden-field-#{ image_id }" end def set_simple_captcha_data(key, options={}) code_type = options[:code_type] value = generate_simple_captcha_data(code_type) data = SimpleCaptcha::SimpleCaptchaData.get_data(key) data.value = value data.save key end def generate_simple_captcha_data(code) value = '' case code when 'numeric' then SimpleCaptcha.length.times{value << (48 + rand(10)).chr} else SimpleCaptcha.length.times{value << (65 + rand(26)).chr} end return value end def simple_captcha_key(key_name = nil, prequest = request) local_session = prequest.try(:session) || session if key_name.nil? local_session[:captcha] ||= SimpleCaptcha::Utils.generate_key(local_session[:id].to_s, 'captcha') else SimpleCaptcha::Utils.generate_key(local_session[:id].to_s, key_name) end end end end simple_captcha2-0.5.0/lib/simple_captcha/controller.rb0000644000004100000410000000220413576031220023031 0ustar www-datawww-datamodule SimpleCaptcha #:nodoc module ControllerHelpers #:nodoc # This method is to validate the simple captcha in controller. # It means when the captcha is controller based i.e. :object has not been passed to the method show_simple_captcha. # # *Example* # # If you want to save an object say @user only if the captcha is validated then do like this in action... # # if simple_captcha_valid? # @user.save # else # flash[:notice] = "captcha did not match" # redirect_to :action => "myaction" # end def simple_captcha_valid? return true if SimpleCaptcha.always_pass return @_simple_captcha_result unless !defined?(@_simple_captcha_result) || @_simple_captcha_result.nil? if params[:captcha] captcha_key = params[:captcha_key] || session[:captcha] data = SimpleCaptcha::Utils::simple_captcha_value(captcha_key) result = data == params[:captcha].delete(" ").upcase SimpleCaptcha::Utils::simple_captcha_passed!(captcha_key) if result @_simple_captcha_result = result result else false end end end end simple_captcha2-0.5.0/lib/simple_captcha/formtastic.rb0000644000004100000410000000057213576031220023027 0ustar www-datawww-dataif defined? Formtastic require 'formtastic/version' if Formtastic::VERSION < '2.2' raise 'Only Formtastic Version 2.2 or greater is supported by SimpleCaptcha' end class SimpleCaptchaInput include Formtastic::Inputs::Base def to_html options.update :object => sanitized_object_name builder.send(:show_simple_captcha, options) end end end simple_captcha2-0.5.0/lib/simple_captcha/middleware.rb0000644000004100000410000000766313576031220023001 0ustar www-datawww-data# 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 simple_captcha2-0.5.0/simple_captcha2.gemspec0000644000004100000410000000611213576031220021204 0ustar www-datawww-data######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: simple_captcha2 0.5.0 ruby lib Gem::Specification.new do |s| s.name = "simple_captcha2".freeze s.version = "0.5.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Pavlo Galeta".freeze, "Igor Galeta".freeze, "Stefan Wienert".freeze, "Konrad Mallok".freeze] s.date = "2019-12-05" s.description = "SimpleCaptcha is available to be used with Rails 3 + 4 or above and also it provides the backward compatibility with previous versions of Rails.".freeze s.email = "stwienert@gmail.com".freeze s.extra_rdoc_files = ["README.md".freeze] s.files = ["README.md".freeze, "Rakefile".freeze, "lib/generators/USAGE".freeze, "lib/generators/simple_captcha_generator.rb".freeze, "lib/generators/templates/migration.rb".freeze, "lib/generators/templates/migration5.rb".freeze, "lib/generators/templates/migration_sequel.rb".freeze, "lib/generators/templates/partial.erb".freeze, "lib/generators/templates/partial.haml".freeze, "lib/simple_captcha.rb".freeze, "lib/simple_captcha/controller.rb".freeze, "lib/simple_captcha/engine.rb".freeze, "lib/simple_captcha/form_builder.rb".freeze, "lib/simple_captcha/formtastic.rb".freeze, "lib/simple_captcha/image.rb".freeze, "lib/simple_captcha/middleware.rb".freeze, "lib/simple_captcha/model_helpers.rb".freeze, "lib/simple_captcha/simple_captcha_data.rb".freeze, "lib/simple_captcha/simple_captcha_data_mongoid.rb".freeze, "lib/simple_captcha/simple_captcha_data_sequel.rb".freeze, "lib/simple_captcha/utils.rb".freeze, "lib/simple_captcha/version.rb".freeze, "lib/simple_captcha/view.rb".freeze, "lib/simple_captcha2.rb".freeze] s.homepage = "http://github.com/pludoni/simple-captcha".freeze s.rubygems_version = "2.5.2.1".freeze s.summary = "SimpleCaptcha is the simplest and a robust captcha plugin.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_runtime_dependency(%q.freeze, [">= 4.1"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 4.1"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 4.1"]) s.add_dependency(%q.freeze, [">= 0"]) end end