mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 23:48:47 +00:00
Update captcha
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import re
|
||||
|
||||
VERSION = (0, 4, 0)
|
||||
VERSION = (0, 4, 3)
|
||||
|
||||
|
||||
def get_version(svn=False):
|
||||
@@ -20,8 +20,8 @@ def pillow_required():
|
||||
except ImportError:
|
||||
try:
|
||||
import Image
|
||||
import ImageDraw
|
||||
import ImageFont
|
||||
import ImageDraw # NOQA
|
||||
import ImageFont # NOQA
|
||||
except ImportError:
|
||||
return True
|
||||
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import os
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
||||
CAPTCHA_FONT_PATH = getattr(settings, 'CAPTCHA_FONT_PATH', os.path.normpath(os.path.join(os.path.dirname(__file__), '..', 'fonts/Vera.ttf')))
|
||||
CAPTCHA_FONT_SIZE = getattr(settings, 'CAPTCHA_FONT_SIZE', 22)
|
||||
@@ -19,9 +18,9 @@ CAPTCHA_IMAGE_BEFORE_FIELD = getattr(settings, 'CAPTCHA_IMAGE_BEFORE_FIELD', Tru
|
||||
CAPTCHA_DICTIONARY_MIN_LENGTH = getattr(settings, 'CAPTCHA_DICTIONARY_MIN_LENGTH', 0)
|
||||
CAPTCHA_DICTIONARY_MAX_LENGTH = getattr(settings, 'CAPTCHA_DICTIONARY_MAX_LENGTH', 99)
|
||||
if CAPTCHA_IMAGE_BEFORE_FIELD:
|
||||
CAPTCHA_OUTPUT_FORMAT = getattr(settings, 'CAPTCHA_OUTPUT_FORMAT', u'%(image)s %(hidden_field)s %(text_field)s')
|
||||
CAPTCHA_OUTPUT_FORMAT = getattr(settings, 'CAPTCHA_OUTPUT_FORMAT', '%(image)s %(hidden_field)s %(text_field)s')
|
||||
else:
|
||||
CAPTCHA_OUTPUT_FORMAT = getattr(settings, 'CAPTCHA_OUTPUT_FORMAT', u'%(hidden_field)s %(text_field)s %(image)s')
|
||||
CAPTCHA_OUTPUT_FORMAT = getattr(settings, 'CAPTCHA_OUTPUT_FORMAT', '%(hidden_field)s %(text_field)s %(image)s')
|
||||
|
||||
CAPTCHA_TEST_MODE = getattr(settings, 'CAPTCHA_TEST_MODE', getattr(settings, 'CATPCHA_TEST_MODE', False))
|
||||
|
||||
|
@@ -1,12 +1,12 @@
|
||||
from captcha.conf import settings
|
||||
from django.conf import settings as django_settings
|
||||
from captcha.models import CaptchaStore, get_safe_now
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.core.urlresolvers import reverse, NoReverseMatch
|
||||
from django.core.urlresolvers import reverse, NoReverseMatch
|
||||
from django.forms import ValidationError
|
||||
from django.forms.fields import CharField, MultiValueField
|
||||
from django.forms.widgets import TextInput, MultiWidget, HiddenInput
|
||||
from django.utils.translation import ugettext, ugettext_lazy
|
||||
from six import u
|
||||
|
||||
|
||||
class BaseCaptchaTextInput(MultiWidget):
|
||||
@@ -38,14 +38,10 @@ class BaseCaptchaTextInput(MultiWidget):
|
||||
key = CaptchaStore.generate_key()
|
||||
|
||||
# these can be used by format_output and render
|
||||
self._value = [key, u'']
|
||||
self._value = [key, u('')]
|
||||
self._key = key
|
||||
self.id_ = self.build_attrs(attrs).get('id', None)
|
||||
|
||||
def render(self, name, value, attrs=None):
|
||||
#self.fetch_captcha_store(name, value, attrs)
|
||||
return super(BaseCaptchaTextInput, self).render(name, self._value, attrs=attrs)
|
||||
|
||||
def id_for_label(self, id_):
|
||||
if id_:
|
||||
return id_ + '_1'
|
||||
@@ -76,6 +72,7 @@ class CaptchaTextInput(BaseCaptchaTextInput):
|
||||
|
||||
def format_output(self, rendered_widgets):
|
||||
hidden_field, text_field = rendered_widgets
|
||||
text_field = text_field.replace('<input', '<input autocomplete="off"')
|
||||
return self._args['output_format'] % {
|
||||
'image': self.image_and_audio,
|
||||
'hidden_field': hidden_field,
|
||||
@@ -88,8 +85,6 @@ class CaptchaTextInput(BaseCaptchaTextInput):
|
||||
self.image_and_audio = '<img src="%s" alt="captcha" class="captcha" />' % self.image_url()
|
||||
if settings.CAPTCHA_FLITE_PATH:
|
||||
self.image_and_audio = '<a href="%s" title="%s">%s</a>' % (self.audio_url(), ugettext('Play CAPTCHA as audio file'), self.image_and_audio)
|
||||
|
||||
|
||||
return super(CaptchaTextInput, self).render(name, self._value, attrs=attrs)
|
||||
|
||||
|
||||
|
@@ -2,6 +2,7 @@
|
||||
import random
|
||||
from captcha.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from six import u
|
||||
|
||||
|
||||
def math_challenge():
|
||||
@@ -15,14 +16,14 @@ def math_challenge():
|
||||
|
||||
|
||||
def random_char_challenge():
|
||||
chars, ret = u'abcdefghijklmnopqrstuvwxyz', u''
|
||||
chars, ret = u('abcdefghijklmnopqrstuvwxyz'), u('')
|
||||
for i in range(settings.CAPTCHA_LENGTH):
|
||||
ret += random.choice(chars)
|
||||
return ret.upper(), ret
|
||||
|
||||
|
||||
def unicode_challenge():
|
||||
chars, ret = u'äàáëéèïíîöóòüúù', u''
|
||||
chars, ret = u('äàáëéèïíîöóòüúù'), u('')
|
||||
for i in range(settings.CAPTCHA_LENGTH):
|
||||
ret += random.choice(chars)
|
||||
return ret.upper(), ret
|
||||
@@ -70,6 +71,10 @@ def noise_dots(draw, image):
|
||||
return draw
|
||||
|
||||
|
||||
def noise_null(draw, image):
|
||||
return draw
|
||||
|
||||
|
||||
def post_smooth(image):
|
||||
try:
|
||||
import ImageFilter
|
||||
|
31
thirdpart/captcha/locale/bg/LC_MESSAGES/django.po
Normal file
31
thirdpart/captcha/locale/bg/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,31 @@
|
||||
# django-simple-captcha Bulgarian translation
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the django-simple-captcha package.
|
||||
# Venelin Stoykov <vkstoykov@gmail.com>, 2014.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-simple-captcha 0.4.1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-02-10 14:43+0200\n"
|
||||
"PO-Revision-Date: 2014-02-10 15:00+0200\n"
|
||||
"Last-Translator: Venelin Stoykov <vkstoykov@gmail.com>\n"
|
||||
"Language-Team: bg <vkstoykov@gmail.com>\n"
|
||||
"Language: bg\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
|
||||
#: fields.py:91
|
||||
msgid "Play CAPTCHA as audio file"
|
||||
msgstr "Чуй текста като аудио файл"
|
||||
|
||||
#: fields.py:106 fields.py:135 tests/tests.py:99 tests/tests.py:239
|
||||
#: tests/tests.py:246
|
||||
msgid "Invalid CAPTCHA"
|
||||
msgstr "Сгрешен текст"
|
||||
|
||||
#: tests/tests.py:125
|
||||
msgid "This field is required."
|
||||
msgstr "Това поле е задължително"
|
@@ -11,7 +11,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2012-10-09 07:08+0200\n"
|
||||
"Last-Translator: Beda Kosata <bedrich.kosata@nic.cz>\n"
|
||||
"Language-Team: Czech <>\n"
|
||||
"Language: \n"
|
||||
"Language: cs\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@@ -11,6 +11,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2013-07-16 12:10+0100\n"
|
||||
"Last-Translator: Patrick Lauber <patrick.lauber@divio.ch>\n"
|
||||
"Language-Team: DE <digi@treepy.com>\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
32
thirdpart/captcha/locale/es/LC_MESSAGES/django.po
Normal file
32
thirdpart/captcha/locale/es/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,32 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-simple-captcha\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-07-16 12:06+0200\n"
|
||||
"PO-Revision-Date: 2014-05-20 21:22+0100\n"
|
||||
"Last-Translator: https://github.com/dragosdobrota\n"
|
||||
"Language-Team: es\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 1.6.5\n"
|
||||
|
||||
#: fields.py:90
|
||||
msgid "Play CAPTCHA as audio file"
|
||||
msgstr "Reproducir CAPTCHA de audio"
|
||||
|
||||
#: fields.py:105 fields.py:134 tests/tests.py:99 tests/tests.py:239
|
||||
#: tests/tests.py:246
|
||||
msgid "Invalid CAPTCHA"
|
||||
msgstr "CAPTCHA no válido"
|
||||
|
||||
#: tests/tests.py:125
|
||||
msgid "This field is required."
|
||||
msgstr "Este campo es obligatorio."
|
@@ -3,7 +3,6 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Patrick Samson <maxcom@laposte.net>, 2010.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-simple-captcha 0.2.0\n"
|
||||
@@ -11,8 +10,8 @@ msgstr ""
|
||||
"POT-Creation-Date: 2012-07-25 11:44+0300\n"
|
||||
"PO-Revision-Date: 2010-09-16 12:16+0200\n"
|
||||
"Last-Translator: Patrick Samson <maxcom@laposte.net>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"Language-Team: fr <maxcom@laposte.net>\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@@ -3,7 +3,6 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Arjuna Del Toso <stupidate@gmail.net>, 2012
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-simple-captcha 0.3.6\n"
|
||||
@@ -12,6 +11,8 @@ msgstr ""
|
||||
"PO-Revision-Date: 2012-11-14 02:53+0000\n"
|
||||
"Last-Translator: Arjuna Del Toso <stupidate@gmail.com>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Language-Team: Arjuna Del Toso <stupidate@gmail.com>\n"
|
||||
"Language: it\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n>1;\n"
|
||||
|
31
thirdpart/captcha/locale/ja/LC_MESSAGES/django.po
Normal file
31
thirdpart/captcha/locale/ja/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,31 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Keisuke URAGO <bravo@resourcez.org>, 2014.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-simple-captcha\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-02-13 07:11+0900\n"
|
||||
"PO-Revision-Date: 2014-02-13 07:11+0900\n"
|
||||
"Last-Translator: Keisuke URAGO <bravo@resourcez.org>\n"
|
||||
"Language-Team: Keisuke URAGO <bravo@resourcez.org>\n"
|
||||
"Language: ja\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: fields.py:90
|
||||
msgid "Play CAPTCHA as audio file"
|
||||
msgstr "CAPTCHAをオーディオで読み上げる"
|
||||
|
||||
#: fields.py:105 fields.py:134 tests/tests.py:99 tests/tests.py:239
|
||||
#: tests/tests.py:246
|
||||
msgid "Invalid CAPTCHA"
|
||||
msgstr "CAPTCHAの値が違っています"
|
||||
|
||||
#: tests/tests.py:125
|
||||
msgid "This field is required."
|
||||
msgstr "この項目は必須です"
|
@@ -3,15 +3,16 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Leon de Rijke <leon@cmsworks.nl>, 2013.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-simple-captcha 0.3.6\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-02-15 13:26+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"PO-Revision-Date: 2013-02-15 13:26+0100\n"
|
||||
"Last-Translator: Leon de Rijke <leon@cmsworks.nl>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Language-Team: Leon de Rijke <leon@cmsworks.nl>\n"
|
||||
"Language: nl\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
|
@@ -3,16 +3,15 @@
|
||||
# This file is distributed under the same license as the django-simple-captcha package.
|
||||
# Sławomir Zborowski <slawomir.zborowski@hotmail.com>, 2013.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Project-Id-Version: django-simple-captcha 0.3.6\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-08-18 18:49+0200\n"
|
||||
"PO-Revision-Date: 2013-08-18 18:52+0200\n"
|
||||
"Last-Translator: Sławomir Zborowski <slawomir.zborowski@hotmail.com>\n"
|
||||
"Language-Team: Polisch\n"
|
||||
"Language: \n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@@ -3,7 +3,6 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Alisson Patricio <eu@alisson.net>, 2013.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-simple-captcha 0.3.7\n"
|
||||
@@ -11,7 +10,8 @@ msgstr ""
|
||||
"POT-Creation-Date: 2013-05-18 10:58-0300\n"
|
||||
"PO-Revision-Date: 2013-05-18 13:12-0300\n"
|
||||
"Last-Translator: Alisson Patricio <eu@alisson.net>\n"
|
||||
"Language: Portuguese (Brazilian)\n"
|
||||
"Language-Team: Alisson Patricio <eu@alisson.net>\n"
|
||||
"Language: pt_br\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@@ -3,16 +3,15 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Project-Id-Version: django-simple-captcha 0.3.7\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-07-25 11:17+0300\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"PO-Revision-Date: 2012-07-25 11:17+0300\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: ru <LL@li.org>\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
32
thirdpart/captcha/locale/sk/LC_MESSAGES/django.po
Normal file
32
thirdpart/captcha/locale/sk/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,32 @@
|
||||
# Slovak translation of django-simple-captcha.
|
||||
# Copyright (C) 2013 THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Pavol Otto <pavol.otto@nic.cz>, 2013.
|
||||
#
|
||||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-simple-captcha 0.3.7\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-10-15 17:16+0200\n"
|
||||
"PO-Revision-Date: 2013-10-15 17:16+0200\n"
|
||||
"Last-Translator: Pavol Otto <pavol.otto@nic.cz>\n"
|
||||
"Language-Team: SK\n"
|
||||
"Language: sk\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
|
||||
#: fields.py:90
|
||||
msgid "Play CAPTCHA as audio file"
|
||||
msgstr "Prehrať captchu ako audio súbor"
|
||||
|
||||
#: fields.py:105 fields.py:134 tests/tests.py:99 tests/tests.py:239
|
||||
#: tests/tests.py:246
|
||||
msgid "Invalid CAPTCHA"
|
||||
msgstr "Neplatná CAPTCHA"
|
||||
|
||||
#: tests/tests.py:125
|
||||
msgid "This field is required."
|
||||
msgstr "Toto pole je povinné."
|
@@ -3,7 +3,6 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-simple-captcha 0.3.6\n"
|
||||
@@ -11,7 +10,8 @@ msgstr ""
|
||||
"POT-Creation-Date: 2013-01-19 16:33-0200\n"
|
||||
"PO-Revision-Date: 2013-01-19 20:52+0200\n"
|
||||
"Last-Translator: Gokmen Gorgen <gokmen@alageek.com>\n"
|
||||
"Language: \n"
|
||||
"Language-Team: TR Gokmen Gorgen <gokmen@alageek.com>\n"
|
||||
"Language: tr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
32
thirdpart/captcha/locale/uk/LC_MESSAGES/django.po
Normal file
32
thirdpart/captcha/locale/uk/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,32 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-simple-captcha 0.3.6\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-02-21 22:05+0200\n"
|
||||
"PO-Revision-Date: 2014-02-21 22:05+0200\n"
|
||||
"Last-Translator: @FuriousCoder\n"
|
||||
"Language-Team: uk @FuriousCoder\n"
|
||||
"Language: uk\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: fields.py:91
|
||||
msgid "Play CAPTCHA as audio file"
|
||||
msgstr "Відтворити CAPTCHA як аудіо файл."
|
||||
|
||||
#: fields.py:106 fields.py:135 tests/tests.py:99 tests/tests.py:239
|
||||
#: tests/tests.py:246
|
||||
msgid "Invalid CAPTCHA"
|
||||
msgstr "Неправильна відповідь."
|
||||
|
||||
#: tests/tests.py:125
|
||||
msgid "This field is required."
|
||||
msgstr "Це поле є обов'язковим."
|
@@ -3,15 +3,15 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Ming Chen <c.ming@live.com>, 2013.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-simple-captcha 0.3.6\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-03-01 05:04+0800\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"PO-Revision-Date: 2013-03-01 05:04+0800\n"
|
||||
"Last-Translator: Ming Chen <c.ming@live.com>\n"
|
||||
"Language: \n"
|
||||
"Language-Team: zh_cn Ming Chen <c.ming@live.com>\n"
|
||||
"Language: zh_cn\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@@ -11,15 +11,15 @@ class Command(BaseCommand):
|
||||
verbose = int(options.get('verbosity'))
|
||||
expired_keys = CaptchaStore.objects.filter(expiration__lte=get_safe_now()).count()
|
||||
if verbose >= 1:
|
||||
print "Currently %d expired hashkeys" % expired_keys
|
||||
print("Currently %d expired hashkeys" % expired_keys)
|
||||
try:
|
||||
CaptchaStore.remove_expired()
|
||||
except:
|
||||
if verbose >= 1:
|
||||
print "Unable to delete expired hashkeys."
|
||||
print("Unable to delete expired hashkeys.")
|
||||
sys.exit(1)
|
||||
if verbose >= 1:
|
||||
if expired_keys > 0:
|
||||
print "%d expired hashkeys removed." % expired_keys
|
||||
print("%d expired hashkeys removed." % expired_keys)
|
||||
else:
|
||||
print "No keys to remove."
|
||||
print("No keys to remove.")
|
||||
|
@@ -1,39 +1,26 @@
|
||||
# encoding: utf-8
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Adding model 'CaptchaStore'
|
||||
db.create_table('captcha_captchastore', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('challenge', self.gf('django.db.models.fields.CharField')(max_length=32)),
|
||||
('response', self.gf('django.db.models.fields.CharField')(max_length=32)),
|
||||
('hashkey', self.gf('django.db.models.fields.CharField')(unique=True, max_length=40)),
|
||||
('expiration', self.gf('django.db.models.fields.DateTimeField')()),
|
||||
))
|
||||
db.send_create_signal('captcha', ['CaptchaStore'])
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting model 'CaptchaStore'
|
||||
db.delete_table('captcha_captchastore')
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
models = {
|
||||
'captcha.captchastore': {
|
||||
'Meta': {'object_name': 'CaptchaStore'},
|
||||
'challenge': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
|
||||
'expiration': ('django.db.models.fields.DateTimeField', [], {}),
|
||||
'hashkey': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'response': ('django.db.models.fields.CharField', [], {'max_length': '32'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['captcha']
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CaptchaStore',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('challenge', models.CharField(max_length=32)),
|
||||
('response', models.CharField(max_length=32)),
|
||||
('hashkey', models.CharField(unique=True, max_length=40)),
|
||||
('expiration', models.DateTimeField()),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
]
|
||||
|
@@ -0,0 +1,21 @@
|
||||
"""
|
||||
Django migrations for django-simple-captcha app
|
||||
|
||||
This package does not contain South migrations. South migrations can be found
|
||||
in the ``south_migrations`` package.
|
||||
"""
|
||||
|
||||
SOUTH_ERROR_MESSAGE = """\n
|
||||
For South support, customize the SOUTH_MIGRATION_MODULES setting like so:
|
||||
|
||||
SOUTH_MIGRATION_MODULES = {
|
||||
'captcha': 'captcha.south_migrations',
|
||||
}
|
||||
"""
|
||||
|
||||
# Ensure the user is not using Django 1.6 or below with South
|
||||
try:
|
||||
from django.db import migrations # noqa
|
||||
except ImportError:
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
raise ImproperlyConfigured(SOUTH_ERROR_MESSAGE)
|
@@ -40,10 +40,9 @@ class CaptchaStore(models.Model):
|
||||
expiration = models.DateTimeField(blank=False)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
#import ipdb; ipdb.set_trace()
|
||||
|
||||
self.response = six.text_type(self.response).lower()
|
||||
if not self.expiration:
|
||||
#self.expiration = datetime.datetime.now() + datetime.timedelta(minutes=int(captcha_settings.CAPTCHA_TIMEOUT))
|
||||
self.expiration = get_safe_now() + datetime.timedelta(minutes=int(captcha_settings.CAPTCHA_TIMEOUT))
|
||||
if not self.hashkey:
|
||||
key_ = unicodedata.normalize('NFKD', str(randrange(0, MAX_RANDOM_KEY)) + str(time.time()) + six.text_type(self.challenge)).encode('ascii', 'ignore') + unicodedata.normalize('NFKD', six.text_type(self.response)).encode('ascii', 'ignore')
|
||||
|
39
thirdpart/captcha/south_migrations/0001_initial.py
Normal file
39
thirdpart/captcha/south_migrations/0001_initial.py
Normal file
@@ -0,0 +1,39 @@
|
||||
# encoding: utf-8
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Adding model 'CaptchaStore'
|
||||
db.create_table('captcha_captchastore', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('challenge', self.gf('django.db.models.fields.CharField')(max_length=32)),
|
||||
('response', self.gf('django.db.models.fields.CharField')(max_length=32)),
|
||||
('hashkey', self.gf('django.db.models.fields.CharField')(unique=True, max_length=40)),
|
||||
('expiration', self.gf('django.db.models.fields.DateTimeField')()),
|
||||
))
|
||||
db.send_create_signal('captcha', ['CaptchaStore'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting model 'CaptchaStore'
|
||||
db.delete_table('captcha_captchastore')
|
||||
|
||||
|
||||
models = {
|
||||
'captcha.captchastore': {
|
||||
'Meta': {'object_name': 'CaptchaStore'},
|
||||
'challenge': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
|
||||
'expiration': ('django.db.models.fields.DateTimeField', [], {}),
|
||||
'hashkey': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'response': ('django.db.models.fields.CharField', [], {'max_length': '32'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['captcha']
|
0
thirdpart/captcha/south_migrations/__init__.py
Normal file
0
thirdpart/captcha/south_migrations/__init__.py
Normal file
@@ -1 +1 @@
|
||||
from .tests import CaptchaCase, trivial_challenge
|
||||
from .tests import CaptchaCase, trivial_challenge # NOQA
|
||||
|
@@ -12,6 +12,7 @@ import json
|
||||
import re
|
||||
import six
|
||||
import os
|
||||
from six import u
|
||||
|
||||
|
||||
class CaptchaCase(TestCase):
|
||||
@@ -42,7 +43,6 @@ class CaptchaCase(TestCase):
|
||||
settings.CAPTCHA_WORDS_DICTIONARY = self.__current_settings_dictionary
|
||||
settings.CAPTCHA_PUNCTUATION = self.__current_settings_punctuation
|
||||
|
||||
|
||||
def __extract_hash_and_response(self, r):
|
||||
hash_ = re.findall(r'value="([0-9a-f]+)"', str(r.content))[0]
|
||||
response = CaptchaStore.objects.get(hashkey=hash_).response
|
||||
@@ -175,7 +175,7 @@ class CaptchaCase(TestCase):
|
||||
|
||||
def testOutputFormat(self):
|
||||
for urlname in ('captcha-test', 'captcha-test-model-form'):
|
||||
settings.CAPTCHA_OUTPUT_FORMAT = u'%(image)s<p>Hello, captcha world</p>%(hidden_field)s%(text_field)s'
|
||||
settings.CAPTCHA_OUTPUT_FORMAT = u('%(image)s<p>Hello, captcha world</p>%(hidden_field)s%(text_field)s')
|
||||
r = self.client.get(reverse(urlname))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertTrue('<p>Hello, captcha world</p>' in str(r.content))
|
||||
@@ -186,7 +186,7 @@ class CaptchaCase(TestCase):
|
||||
# we turn on DEBUG because CAPTCHA_OUTPUT_FORMAT is only checked debug
|
||||
|
||||
django_settings.DEBUG = True
|
||||
settings.CAPTCHA_OUTPUT_FORMAT = u'%(image)s'
|
||||
settings.CAPTCHA_OUTPUT_FORMAT = u('%(image)s')
|
||||
try:
|
||||
self.client.get(reverse(urlname))
|
||||
self.fail()
|
||||
@@ -195,14 +195,14 @@ class CaptchaCase(TestCase):
|
||||
django_settings.DEBUG = __current_settings_debug
|
||||
|
||||
def testPerFormFormat(self):
|
||||
settings.CAPTCHA_OUTPUT_FORMAT = u'%(image)s testCustomFormatString %(hidden_field)s %(text_field)s'
|
||||
settings.CAPTCHA_OUTPUT_FORMAT = u('%(image)s testCustomFormatString %(hidden_field)s %(text_field)s')
|
||||
r = self.client.get(reverse('captcha-test'))
|
||||
self.assertTrue('testCustomFormatString' in str(r.content))
|
||||
r = self.client.get(reverse('test_per_form_format'))
|
||||
self.assertTrue('testPerFieldCustomFormatString' in str(r.content))
|
||||
|
||||
def testIssue31ProperLabel(self):
|
||||
settings.CAPTCHA_OUTPUT_FORMAT = u'%(image)s %(hidden_field)s %(text_field)s'
|
||||
settings.CAPTCHA_OUTPUT_FORMAT = u('%(image)s %(hidden_field)s %(text_field)s')
|
||||
r = self.client.get(reverse('captcha-test'))
|
||||
self.assertTrue('<label for="id_captcha_1"' in str(r.content))
|
||||
|
||||
@@ -226,12 +226,12 @@ class CaptchaCase(TestCase):
|
||||
This test covers a default django field and widget behavior
|
||||
It not assert anything. If something is wrong it will raise a error!
|
||||
"""
|
||||
settings.CAPTCHA_OUTPUT_FORMAT = u'%(image)s %(hidden_field)s %(text_field)s'
|
||||
settings.CAPTCHA_OUTPUT_FORMAT = u('%(image)s %(hidden_field)s %(text_field)s')
|
||||
widget = CaptchaTextInput(attrs={'class': 'required'})
|
||||
CaptchaField(widget=widget)
|
||||
|
||||
def testTestMode_Issue15(self):
|
||||
__current_test_mode_setting = settings.CAPTCHA_TEST_MODE
|
||||
__current_test_mode_setting = settings.CAPTCHA_TEST_MODE
|
||||
settings.CAPTCHA_TEST_MODE = False
|
||||
r = self.client.get(reverse('captcha-test'))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
@@ -270,11 +270,30 @@ class CaptchaCase(TestCase):
|
||||
self.assertEqual(r.status_code, 200)
|
||||
hash_, response = self.__extract_hash_and_response(r)
|
||||
|
||||
|
||||
r = self.client.post(reverse('captcha-test-non-required'), dict(captcha_0=hash_, captcha_1=response, subject='xxx', sender='asasd@asdasd.com'))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertTrue(str(r.content).find('Form validated') > 0)
|
||||
|
||||
def test_autocomplete_off(self):
|
||||
r = self.client.get(reverse('captcha-test'))
|
||||
self.assertTrue('<input autocomplete="off" ' in six.text_type(r.content))
|
||||
|
||||
def test_autocomplete_not_on_hidden_input(self):
|
||||
r = self.client.get(reverse('captcha-test'))
|
||||
self.assertFalse('autocomplete="off" type="hidden" name="captcha_0"' in six.text_type(r.content))
|
||||
self.assertFalse('autocomplete="off" id="id_captcha_0" name="captcha_0" type="hidden"' in six.text_type(r.content))
|
||||
|
||||
def test_transparent_background(self):
|
||||
__current_test_mode_setting = settings.CAPTCHA_BACKGROUND_COLOR
|
||||
settings.CAPTCHA_BACKGROUND_COLOR = "transparent"
|
||||
for key in [store.hashkey for store in six.itervalues(self.stores)]:
|
||||
response = self.client.get(reverse('captcha-image', kwargs=dict(key=key)))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTrue(response.has_header('content-type'))
|
||||
self.assertEqual(response._headers.get('content-type'), ('Content-Type', 'image/png'))
|
||||
|
||||
settings.CAPTCHA_BACKGROUND_COLOR = __current_test_mode_setting
|
||||
|
||||
|
||||
def trivial_challenge():
|
||||
return 'trivial', 'trivial'
|
||||
|
@@ -3,7 +3,8 @@ try:
|
||||
except ImportError:
|
||||
from django.conf.urls.defaults import url, patterns, include
|
||||
|
||||
urlpatterns = patterns('',
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
url(r'test/$', 'captcha.tests.views.test', name='captcha-test'),
|
||||
url(r'test-modelform/$', 'captcha.tests.views.test_model_form', name='captcha-test-model-form'),
|
||||
url(r'test2/$', 'captcha.tests.views.test_custom_error_message', name='captcha-test-custom-error-message'),
|
||||
|
@@ -3,7 +3,7 @@ from captcha.fields import CaptchaField
|
||||
from django.template import RequestContext, loader
|
||||
from django.http import HttpResponse
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
from six import u
|
||||
|
||||
TEST_TEMPLATE = r'''
|
||||
{% load url from future %}
|
||||
@@ -30,6 +30,7 @@ TEST_TEMPLATE = r'''
|
||||
</html>
|
||||
'''
|
||||
|
||||
|
||||
def _test(request, form_class):
|
||||
passed = False
|
||||
if request.POST:
|
||||
@@ -80,8 +81,10 @@ def test_per_form_format(request):
|
||||
help_text='asdasd',
|
||||
error_messages=dict(invalid='TEST CUSTOM ERROR MESSAGE'),
|
||||
output_format=(
|
||||
u'%(image)s testPerFieldCustomFormatString '
|
||||
u'%(hidden_field)s %(text_field)s'
|
||||
u(
|
||||
'%(image)s testPerFieldCustomFormatString '
|
||||
'%(hidden_field)s %(text_field)s'
|
||||
)
|
||||
)
|
||||
)
|
||||
return _test(request, CaptchaTestFormatForm)
|
||||
|
@@ -3,7 +3,8 @@ try:
|
||||
except ImportError:
|
||||
from django.conf.urls.defaults import patterns, url
|
||||
|
||||
urlpatterns = patterns('captcha.views',
|
||||
urlpatterns = patterns(
|
||||
'captcha.views',
|
||||
url(r'image/(?P<key>\w+)/$', 'captcha_image', name='captcha-image', kwargs={'scale': 1}),
|
||||
url(r'image/(?P<key>\w+)@2/$', 'captcha_image', name='captcha-image-2x', kwargs={'scale': 2}),
|
||||
url(r'audio/(?P<key>\w+)/$', 'captcha_audio', name='captcha-audio'),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
from captcha.conf import settings
|
||||
from captcha.conf import settings
|
||||
from captcha.helpers import captcha_image_url
|
||||
from captcha.models import CaptchaStore
|
||||
from django.http import HttpResponse, Http404
|
||||
@@ -27,6 +27,15 @@ except ImportError:
|
||||
from django.utils import simplejson as json
|
||||
|
||||
NON_DIGITS_RX = re.compile('[^\d]')
|
||||
# Distance of the drawn text from the top of the captcha image
|
||||
from_top = 4
|
||||
|
||||
|
||||
def getsize(font, text):
|
||||
if hasattr(font, 'getoffset'):
|
||||
return [x + y for x, y in zip(font.getsize(text), font.getoffset(text))]
|
||||
else:
|
||||
return font.getsize(text)
|
||||
|
||||
|
||||
def captcha_image(request, key, scale=1):
|
||||
@@ -38,9 +47,12 @@ def captcha_image(request, key, scale=1):
|
||||
else:
|
||||
font = ImageFont.load(settings.CAPTCHA_FONT_PATH)
|
||||
|
||||
size = font.getsize(text)
|
||||
size = (size[0] * 2, int(size[1] * 1.2))
|
||||
image = Image.new('RGB', size, settings.CAPTCHA_BACKGROUND_COLOR)
|
||||
size = getsize(font, text)
|
||||
size = (size[0] * 2, int(size[1] * 1.4))
|
||||
if settings.CAPTCHA_BACKGROUND_COLOR == "transparent":
|
||||
image = Image.new('RGBA', size)
|
||||
else:
|
||||
image = Image.new('RGB', size, settings.CAPTCHA_BACKGROUND_COLOR)
|
||||
|
||||
try:
|
||||
PIL_VERSION = int(NON_DIGITS_RX.sub('', Image.VERSION))
|
||||
@@ -56,7 +68,7 @@ def captcha_image(request, key, scale=1):
|
||||
charlist.append(char)
|
||||
for char in charlist:
|
||||
fgimage = Image.new('RGB', size, settings.CAPTCHA_FOREGROUND_COLOR)
|
||||
charimage = Image.new('L', font.getsize(' %s ' % char), '#000000')
|
||||
charimage = Image.new('L', getsize(font, ' %s ' % char), '#000000')
|
||||
chardraw = ImageDraw.Draw(charimage)
|
||||
chardraw.text((0, 0), ' %s ' % char, font=font, fill='#ffffff')
|
||||
if settings.CAPTCHA_LETTER_ROTATION:
|
||||
@@ -67,7 +79,7 @@ def captcha_image(request, key, scale=1):
|
||||
charimage = charimage.crop(charimage.getbbox())
|
||||
maskimage = Image.new('L', size)
|
||||
|
||||
maskimage.paste(charimage, (xpos, 4, xpos + charimage.size[0], 4 + charimage.size[1]))
|
||||
maskimage.paste(charimage, (xpos, from_top, xpos + charimage.size[0], from_top + charimage.size[1]))
|
||||
size = maskimage.size
|
||||
image = Image.composite(fgimage, image, maskimage)
|
||||
xpos = xpos + 2 + charimage.size[0]
|
||||
|
Reference in New Issue
Block a user