From 3939d1bb02186fd2e89fd5df80eaec64c9c4fbed Mon Sep 17 00:00:00 2001 From: Rina <550686383@qq.com> Date: Thu, 7 Dec 2017 16:49:42 +0800 Subject: [PATCH] Allow change chars length and disable strikethrough (#57) --- Gemfile.lock | 2 +- README.md | 10 ++-- ext/rucaptcha/rucaptcha.c | 44 +++++++++++----- lib/rucaptcha.rb | 8 ++- lib/rucaptcha/configuration.rb | 5 ++ lib/rucaptcha/errors/configuration.rb | 5 ++ lib/rucaptcha/version.rb | 2 +- spec/captcha_spec.rb | 75 ++++++++++++++++++++++++++- 8 files changed, 131 insertions(+), 20 deletions(-) create mode 100644 lib/rucaptcha/errors/configuration.rb diff --git a/Gemfile.lock b/Gemfile.lock index ea14711..3cfd9e2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - rucaptcha (2.1.3) + rucaptcha (2.1.4) railties (>= 3.2) GEM diff --git a/README.md b/README.md index feba9c9..5317ff5 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,6 @@ This is a Captcha gem for Rails Applications which generates captcha image by C - High performance. ## Usage - Put rucaptcha in your `Gemfile`: ``` @@ -42,6 +41,10 @@ RuCaptcha.configure do  # 默认:会从 Rails 配置的 cache_store 里面读取相同的配置信息,并尝试用可以运行的方式,用于存储验证码字符  # 但如果是 [:null_store, :memory_store, :file_store] 之类的,你可以通过下面的配置项单独给 RuCaptcha 配置 cache_store  self.cache_store = :mem_cache_store + # 验证码长度 length, 默认是 5, allows: [3,4,5,6,7] + # self.length = 5 + # 验证码横线 line, 默认显示横线, default: true, allows: [true, false], 设置为false时, 横线不是显示, 验证码识别度高. + # self.line = true end ``` @@ -53,7 +56,7 @@ RuCaptcha 没有使用 Rails Session 来存储验证码信息,因为 Rails 的 所以,我建议大家使用的时候,配置上 `cache_store` (详见 [Rails Guides 缓存配置部分](https://ruby-china.github.io/rails-guides/caching_with_rails.html#%E9%85%8D%E7%BD%AE)的文档)到一个 Memcached 或 Redis,这才是最佳实践。 -# +# (RuCaptha do not use Rails Session to store captcha information. As the default session is stored in Cookie in Rails, there's a [Replay attack](https://en.wikipedia.org/wiki/Replay_attack) bug which may causes capthcha being destroyed if we store captcha in Rails Session. So in my design I require RuCaptcha to configure a distributed backend storage scheme, such as Memcached, Redis or other cache_store schemes which support distribution. @@ -61,7 +64,8 @@ So in my design I require RuCaptcha to configure a distributed backend storage s Meanwhile, for the ease of use, RuCapthca would try to use `:file_store` by default and store the capthca in `tmp/cache/rucaptcha/session` directory (kindly note that it's not working if deploy on multiple machine). For recommendation, configure the `cache_store`(more details on [Rails Guides Configuration of Cache Stores](http://guides.rubyonrails.org/caching_with_rails.html#configuration)) to Memcached or Redis, that would be the best practice.) -# + +# Controller `app/controller/account_controller.rb` diff --git a/ext/rucaptcha/rucaptcha.c b/ext/rucaptcha/rucaptcha.c index a39fbad..a3367bc 100644 --- a/ext/rucaptcha/rucaptcha.c +++ b/ext/rucaptcha/rucaptcha.c @@ -1,6 +1,6 @@ // http://github.com/ITikhonov/captcha const int gifsize; -void captcha(unsigned char im[70*200], unsigned char l[6]); +void captcha(unsigned char im[70*200], unsigned char l[8], int length, int i_line); void makegif(unsigned char im[70*200], unsigned char gif[gifsize], int style); #include @@ -152,18 +152,37 @@ static void filter(unsigned char im[70*200]) { static const char *letters="abcdafahijklmnopqrstuvwxyz"; -void captcha(unsigned char im[70*200], unsigned char l[6]) { +void captcha(unsigned char im[70*200], unsigned char l[8], int length, int i_line) { unsigned char swr[200]; uint8_t s1,s2; int f=open("/dev/urandom",O_RDONLY); read(f,l,5); read(f,swr,200); read(f,dr,sizeof(dr)); read(f,&s1,1); read(f,&s2,1); close(f); + memset(im,0xff,200*70); s1=s1&0x7f; s2=s2&0x3f; - memset(im,0xff,200*70); s1=s1&0x7f; s2=s2&0x3f; l[0]%=25; l[1]%=25; l[2]%=25; l[3]%=25; l[4]%=25; l[5]=0; - int p=30; p=letter(l[0],p,im,swr,s1,s2); p=letter(l[1],p,im,swr,s1,s2); p=letter(l[2],p,im,swr,s1,s2); p=letter(l[3],p,im,swr,s1,s2); letter(l[4],p,im,swr,s1,s2); - line(im,swr,s1); dots(im); // blur(im); // filter(im); - l[0]=letters[l[0]]; l[1]=letters[l[1]]; l[2]=letters[l[2]]; l[3]=letters[l[3]]; l[4]=letters[l[4]]; + int x; + for(x=0;x