pax_global_header00006660000000000000000000000064140251322530014507gustar00rootroot0000000000000052 comment=b2c713c25b0f06625210b0455d30fd11e2dee1ae django-simple-captcha-0.5.14/000077500000000000000000000000001402513225300157305ustar00rootroot00000000000000django-simple-captcha-0.5.14/.gitignore000066400000000000000000000002301402513225300177130ustar00rootroot00000000000000dist *.pyc *.egg-info docs/_build/ .venv* testproject/django-simple-captcha.db testproject/.coverage testproject/coverage.xml testproject/htmlcov/ .tox django-simple-captcha-0.5.14/.pep8000066400000000000000000000000771402513225300166110ustar00rootroot00000000000000[flake8] ignore = E501, W503 exclude = migrations,.venv_*,docs django-simple-captcha-0.5.14/.travis.yml000066400000000000000000000021451402513225300200430ustar00rootroot00000000000000language: python services: memcached sudo: false matrix: include: - python: "3.6" env: TOX_ENV=py36-django22 dist: xenial - python: "3.7" env: TOX_ENV=py37-django30 dist: xenial - python: "3.7" env: TOX_ENV=py37-django31 dist: xenial - python: "3.7" env: TOX_ENV=py37-django32 dist: xenial - python: "3.6" env: TOX_ENV=py36-django22-jinja2 - python: "3.7" env: TOX_ENV=flake8 - python: "3.6" env: TOX_ENV=gettext # Adding jobs for ppc64le architecture - python: "3.6" arch: ppc64le env: TOX_ENV=py36-django22 dist: xenial - python: "3.7" arch: ppc64le env: TOX_ENV=py37-django30 dist: xenial - python: "3.7" arch: ppc64le env: TOX_ENV=py37-django31 dist: xenial - python: "3.6" arch: ppc64le env: TOX_ENV=py36-django22-jinja2 - python: "3.7" arch: ppc64le env: TOX_ENV=flake8 - python: "3.6" arch: ppc64le env: TOX_ENV=gettext install: - pip install tox before_install: - if [[ "${TRAVIS_CPU_ARCH}" == "ppc64le" ]]; then sudo apt-get install gettext; fi script: - tox -e $TOX_ENV django-simple-captcha-0.5.14/CHANGES000066400000000000000000000210611402513225300167230ustar00rootroot00000000000000Version History =============== Version 0.5.14 -------------- * Generate deterministic CAPTCHA images for each Captcha instance (#194, thanks @mjnaderi) * New setting CAPTCHA_2X_IMAGE to disable the double resolution image option (#195, thanks @mjnaderi) * Test against Django 3.2a Version 0.5.13 -------------- * Fix DeprecationWarnings on Django 3 related to unicode (#173, thanks @jannh) * Applied black to the codebase and ignored W503 * tox: remove superfluous basepython statement (#172, thanks @devkral) * i18n: add Persian (fa) language translation files (#190, thanks @mavenium) * Test Django 2.2, 3.0 and 3.1 on Python 3.6, 3.7 and 3.8 (#171, thanks @devkral) * Fix deprecation warnings on Django 3.1 (#186, thanks @ jannh and @TheBuky) * Travis fixes and test on ppc64le arch (#192 and #191, thanks @kishorkunal-raj) Version 0.5.12 -------------- * Doc: Update url include line for Django (#164, thanks @jpic) * Doc: Fixed a typo (#162, thanks @RubenGarcia) * Initial fixes and test against Django 3.0 (#166, #165. Thanks @devkral) * Don't open dictionnary file in binary mode (#167, thanks @grasshoppermouse) Version 0.5.11 -------------- * Fix: CAPTCHA_TEST_MODE was broken. (#163, thanks @ohlr for reporting) Version 0.5.10 -------------- * Test against Django 2.2a1 * Docs: Grammar correction (#160, thanks @DanAtShenTech) * Fix: Add '+' to text replacement for audio support (#157, thanks @geirkairam) * I18N: Added Swedish translation (#155, thanks @stefannorman) * Docs: Provide an example of custom field template (#158, thanks @TheBuky) Version 0.5.9 ------------- * Add missing Jinja2 templates in the pypi packages. Version 0.5.8 ------------- * Add support for Jinja2 templates (Issue #145, PR #146, thanks @ziima) * Cleanup, drop dependency on South (#141, #142 thanks @ziima) Version 0.5.7 ------------- * Use templates for rendering of widgets (Issue #128, #134, PR #133, #139, thanks @ziima) * Always defined audio context variable (PR #132, thanks @ziima) * Test against Django 2.1a * Updated AJAX update docs (PR #140, thanks @CNmanyue) * Fixed a typo in a variable name (PR #130, thanks @galeo) Version 0.5.6 ------------- * Updated render method to adapt for Django 2.1 (PR #120, thanks @skozan) * Improved compatibility with Django 2.0, tests against Django 2.0a1 (PR #121, thanks @Kondou-ger) * Dropped support for PIL (use Pillow instead) * Updated documentation (Fixes #122, thanks @claudep) * Test against Django 2.0b1 * Return a Ranged Response when returning WAV audio to support Safari (Fixes #123, thanks @po5i) * Optionally inject brown noise into the generated WAV audio file, to avoid rainbow-table attacks (Fixes #124, thanks @appleorange1) * Test against Django 2.0 Version 0.5.5 ------------- * I messed the 0.5.4 release, re-releasing as 0.5.5 Version 0.5.4 ------------- * Removed a couple gremlins (PR #113, thanks @Pawamoy) * Added autocapitalize="off", autocorrect="off" and spellcheck="false" to the genreated field (PR #116, thanks @rdonnelly) * Test against Django 1.11 * Drop support of Django 1.7 ("it'll probably still work") Version 0.5.3 ------------- * Ability to pass a per-field challenge generator function (Fixes #109) * Added a feature to get captchas from a data pool of pre-created captchas (PR #110, thanks @skozan) * Cleanup to remove old code handling timezones for no longer supported Django versions * Fix for "Size must be a tuple" issue with Pillow 3.4.0 (Fixes #111) Version 0.5.2 ------------- * Use any mutliplication uperator instead of "*". (Fixes #77 via PR #104, thanks @honsdomi and @isergey) * Test against Django 1.10 Version 0.5.1 ------------- * Fine tuning MANIFEST.in * Prevent testproject from installing into site-packages Version 0.5.0 ------------- * Adds missing includes in MANIFEST.in Version 0.4.7 ------------- * Supported Django versions are now 1.7, 1.8 and 1.9 * Trying to fix the TravisCI build errors * Use Django templates to render the individual fields, as well as the assembled Captcha Field (Issue #31) Version 0.4.6 ------------- * Fixes an UnicodeDecodeError which was apparently only triggered during testing on TravisCI (I hope) * Support for Django 2.0 urlpatterns syntax (PR #82, Thanks @R3v1L) * settings.CAPTCHA_FONT_PATH may be a list, in which case a font is picked randomly (Issue #51 fixed in PR #88, Thanks @inflrscns) Version 0.4.5 ------------- * Test with tox * Test against Django 1.8 final * Added ability to force a fixed image size (PR #76, Thanks @superqwer) Version 0.4.4 ------------- * Added id_prefix argument (fixes issue #37) Version 0.4.3 ------------- * Add null noise helper (Thanks @xrmx) * Test against Django 1.7b4 * Added Spanish translations (Thanks @dragosdobrota) * Massive cleanup (pep8, translations) * Support for transparent background color. (Thanks @curaloucura) * Support both Django 1.7 migrations and South migrations. Please note, you *must* add the following to your settings, if you are using South migrations and Django 1.6 or lower. * Make sure autocomplete="off" is only applied to the text input, not the hidden input (Issue #68, thanks @narrowfail) * Fixed some grammar in the documentation. (Thanks @rikrian) * Return an HTTP 410 GONE error code for expired captcha images, to avoid crawlers from trying to reindex them (PR #70, thanks @joshuajonah) * Fixed title markup in documentation (#74, thanks @pavlov99) * Test against Django 1.7.1 Version 0.4.2 ------------- * Added autocomplete="off" to the input (Issue #57, thanks @Vincent-Vega) * Fixed the format (msgfmt -c) of most PO and MO files distributed with the project * Added Bulgarian translations. (Thanks @vstoykov) * Added Japanese translations. (Thanks, Keisuke URAGO) * Added Ukrainian translations. (Thanks, @FuriousCoder) * Added support for Python 3.2. (Thanks, @amrhassan) Version 0.4.1 ------------- * Dropped support for Django 1.3 * Fixed support of newer versions of Pillow (2.1 and above. Pillow 2.2.2 is now required) Thanks @viaregio (Issue #50) Version 0.4.0 ------------- * Perfom some tests at package installation, to check whether PIL or Pillow are already installed. (Issue #46) * Added Slovak translations. (Thanks @ciklysta) Version 0.3.9 ------------- * Run most tests both with a regular Form and a ModelForm, to avoid regressions such as Issue #40 * Handle the special case where CaptchaFields are instantiated with required=False (Issue #42, thanks @DrMeers) * Fixed a misspelled setting, we now support both spellings, but the docs suggest the correct one (Issue #36, thanks @sayadn) * Added Django 1.6b to testrunner and adapted the test cases to support Django 1.6's new test discovery * Added German translations. (Thanks @digi604) * Frozen the version of Pillow to 2.0.0, as 2.1.0 seems to be truncating the output image -- Issue #44, Thanks @andruby * Added Polish translations. (Thanks @stilzdev) Version 0.3.8 ------------- * Fixed a critical bug (Issue #40) that would generate two captcha objects, and the test would always fail. Thanks @pengqi for the heads-up. Version 0.3.7 ------------- * Improved Django 1.5 and Django HEAD (1.6) compatibility (thanks @uruz) * Python3 compatibility (requires six and Pillow >= 2.0) * Added zh_CN localization (thanks @mingchen) * Make sure the generated challenge is a string type (the math challenge was probably broken -- Issue #33, thanks @YDS19872712) * Massive cleanup and refactoring (Issue #38, thanks @tepez) * Test refactoring to test a couple generators that weren't tested by default Version 0.3.6 ------------- * Django 1.5 compatibility (only affects tests) * Italian localization (thanks @arjunadeltoso) * Russian localization (thanks @mikek) * Fixed issue #17 - Append content-length to response (thanks @shchemelevev) * Merged PR #19 - AJAX refresh of captcha (thanks @artofhuman) * Merged PR #22 - Use op.popen instead of subprocess.call to generate the audio CAPTCHA (thanks @beda42) * Fixed issue #10 - uniformize spelling of "CAPTCHA" (thanks @mikek) * Fixed issue #12 - Raise error when try to initialize CaptchaTextInput alone and/or when try to initialize CaptchaField with widget keyword argument (thanks @vstoykov) * Merged PR #15 - Allow a 'test mode' where the string 'PASSED' always validates the CAPTCHA (thanks @beda42) * Dutch translation (thanks @leonderijke) * Turkish translation (thanks @gkmngrgn) Version 0.3.5 ------------- * Fixes issue #4: Fixes id_for_label malfunction with prefixed forms (thanks @lolek09) Version 0.3.4 ------------- * Fixes issue #3: regression on Django 1.4 when USE_TZ is False Version 0.3.3 ------------- * Django 1.4 Time zones compatibility * PEP 8 love Version 0.3.2 ------------- * Added a test project to run tests * Added South migrations django-simple-captcha-0.5.14/LICENSE000066400000000000000000000020501402513225300167320ustar00rootroot00000000000000Copyright (c) 2008 - 2014 Marco Bonetti Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. django-simple-captcha-0.5.14/MANIFEST.in000066400000000000000000000007461402513225300174750ustar00rootroot00000000000000include MANIFEST.in include LICENSE include README.rst include CHANGES include tox.ini include .pep8 recursive-include captcha/fonts * recursive-include captcha/locale * recursive-include captcha/templates * recursive-include captcha/jinja2 * recursive-include testproject * recursive-include docs * exclude testproject/django-simple-captcha.db prune .tox prune docs/_build prune htmlcov global-exclude *pyc global-exclude coverage.xml global-exclude .DS_Store global-exclude .coverage django-simple-captcha-0.5.14/README.rst000066400000000000000000000025061402513225300174220ustar00rootroot00000000000000********************* Django Simple Captcha ********************* .. image:: https://travis-ci.org/mbi/django-simple-captcha.png?branch=master :target: http://travis-ci.org/mbi/django-simple-captcha .. image:: https://img.shields.io/pypi/v/django-simple-captcha :target: https://pypi.org/project/django-simple-captcha/ .. image:: https://img.shields.io/pypi/l/django-simple-captcha :target: https://github.com/mbi/django-simple-captcha/blob/master/LICENSE Django Simple Captcha is an extremely simple, yet highly customizable Django application to add captcha images to any Django form. .. image:: http://django-simple-captcha.readthedocs.io/en/latest/_images/captcha3.png Features ++++++++ * Very simple to setup and deploy, yet very configurable * Can use custom challenges (e.g. random chars, simple math, dictionary word, ...) * Custom generators, noise and filter functions alter the look of the generated image * Supports text-to-speech audio output of the challenge text, for improved accessibility * Ajax refresh Requirements ++++++++++++ * Django 2.2+, Python3.6+ * A recent version of the Pillow compiled with FreeType support * Flite is required for text-to-speech (audio) output, but not mandatory Documentation +++++++++++++ Read the `documentation online `_. django-simple-captcha-0.5.14/captcha/000077500000000000000000000000001402513225300173335ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/__init__.py000066400000000000000000000002141402513225300214410ustar00rootroot00000000000000VERSION = (0, 5, 14) def get_version(): "Return the version as a human-format string." return ".".join([str(i) for i in VERSION]) django-simple-captcha-0.5.14/captcha/conf/000077500000000000000000000000001402513225300202605ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/conf/__init__.py000066400000000000000000000000001402513225300223570ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/conf/settings.py000066400000000000000000000074041402513225300224770ustar00rootroot00000000000000import os import warnings from django.conf import settings 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) CAPTCHA_LETTER_ROTATION = getattr(settings, "CAPTCHA_LETTER_ROTATION", (-35, 35)) CAPTCHA_BACKGROUND_COLOR = getattr(settings, "CAPTCHA_BACKGROUND_COLOR", "#ffffff") CAPTCHA_FOREGROUND_COLOR = getattr(settings, "CAPTCHA_FOREGROUND_COLOR", "#001100") CAPTCHA_CHALLENGE_FUNCT = getattr( settings, "CAPTCHA_CHALLENGE_FUNCT", "captcha.helpers.random_char_challenge" ) CAPTCHA_NOISE_FUNCTIONS = getattr( settings, "CAPTCHA_NOISE_FUNCTIONS", ("captcha.helpers.noise_arcs", "captcha.helpers.noise_dots"), ) CAPTCHA_FILTER_FUNCTIONS = getattr( settings, "CAPTCHA_FILTER_FUNCTIONS", ("captcha.helpers.post_smooth",) ) CAPTCHA_WORDS_DICTIONARY = getattr( settings, "CAPTCHA_WORDS_DICTIONARY", "/usr/share/dict/words" ) CAPTCHA_PUNCTUATION = getattr(settings, "CAPTCHA_PUNCTUATION", """_"',.;:-""") CAPTCHA_FLITE_PATH = getattr(settings, "CAPTCHA_FLITE_PATH", None) CAPTCHA_SOX_PATH = getattr(settings, "CAPTCHA_SOX_PATH", None) CAPTCHA_TIMEOUT = getattr(settings, "CAPTCHA_TIMEOUT", 5) # Minutes CAPTCHA_LENGTH = int(getattr(settings, "CAPTCHA_LENGTH", 4)) # Chars # CAPTCHA_IMAGE_BEFORE_FIELD = getattr(settings, 'CAPTCHA_IMAGE_BEFORE_FIELD', True) CAPTCHA_DICTIONARY_MIN_LENGTH = getattr(settings, "CAPTCHA_DICTIONARY_MIN_LENGTH", 0) CAPTCHA_DICTIONARY_MAX_LENGTH = getattr(settings, "CAPTCHA_DICTIONARY_MAX_LENGTH", 99) CAPTCHA_IMAGE_SIZE = getattr(settings, "CAPTCHA_IMAGE_SIZE", None) CAPTCHA_IMAGE_TEMPLATE = getattr( settings, "CAPTCHA_IMAGE_TEMPLATE", "captcha/image.html" ) CAPTCHA_HIDDEN_FIELD_TEMPLATE = getattr( settings, "CAPTCHA_HIDDEN_FIELD_TEMPLATE", "captcha/hidden_field.html" ) CAPTCHA_TEXT_FIELD_TEMPLATE = getattr( settings, "CAPTCHA_TEXT_FIELD_TEMPLATE", "captcha/text_field.html" ) if getattr(settings, "CAPTCHA_FIELD_TEMPLATE", None): msg = "CAPTCHA_FIELD_TEMPLATE setting is deprecated in favor of widget's template_name." warnings.warn(msg, DeprecationWarning) CAPTCHA_FIELD_TEMPLATE = getattr(settings, "CAPTCHA_FIELD_TEMPLATE", None) if getattr(settings, "CAPTCHA_OUTPUT_FORMAT", None): msg = "CAPTCHA_OUTPUT_FORMAT setting is deprecated in favor of widget's template_name." warnings.warn(msg, DeprecationWarning) CAPTCHA_OUTPUT_FORMAT = getattr(settings, "CAPTCHA_OUTPUT_FORMAT", None) CAPTCHA_MATH_CHALLENGE_OPERATOR = getattr( settings, "CAPTCHA_MATH_CHALLENGE_OPERATOR", "*" ) CAPTCHA_GET_FROM_POOL = getattr(settings, "CAPTCHA_GET_FROM_POOL", False) CAPTCHA_GET_FROM_POOL_TIMEOUT = getattr(settings, "CAPTCHA_GET_FROM_POOL_TIMEOUT", 5) CAPTCHA_TEST_MODE = getattr(settings, "CAPTCHA_TEST_MODE", False) CAPTCHA_2X_IMAGE = getattr(settings, "CAPTCHA_2X_IMAGE", True) # Failsafe if CAPTCHA_DICTIONARY_MIN_LENGTH > CAPTCHA_DICTIONARY_MAX_LENGTH: CAPTCHA_DICTIONARY_MIN_LENGTH, CAPTCHA_DICTIONARY_MAX_LENGTH = ( CAPTCHA_DICTIONARY_MAX_LENGTH, CAPTCHA_DICTIONARY_MIN_LENGTH, ) def _callable_from_string(string_or_callable): if callable(string_or_callable): return string_or_callable else: return getattr( __import__(".".join(string_or_callable.split(".")[:-1]), {}, {}, [""]), string_or_callable.split(".")[-1], ) def get_challenge(generator=None): return _callable_from_string(generator or CAPTCHA_CHALLENGE_FUNCT) def noise_functions(): if CAPTCHA_NOISE_FUNCTIONS: return map(_callable_from_string, CAPTCHA_NOISE_FUNCTIONS) return [] def filter_functions(): if CAPTCHA_FILTER_FUNCTIONS: return map(_callable_from_string, CAPTCHA_FILTER_FUNCTIONS) return [] django-simple-captcha-0.5.14/captcha/fields.py000066400000000000000000000226111402513225300211550ustar00rootroot00000000000000import warnings import django from django.core.exceptions import ImproperlyConfigured from django.forms import ValidationError from django.forms.fields import CharField, MultiValueField from django.forms.widgets import HiddenInput, MultiWidget, TextInput from django.template.loader import render_to_string from django.utils import timezone from django.utils.safestring import mark_safe from captcha.conf import settings from captcha.models import CaptchaStore from six import u if django.VERSION < (1, 10): # NOQA from django.core.urlresolvers import reverse, NoReverseMatch # NOQA else: # NOQA from django.urls import reverse, NoReverseMatch # NOQA from django.utils.translation import gettext_lazy class CaptchaAnswerInput(TextInput): """Text input for captcha answer.""" # Use *args and **kwargs because signature changed in Django 1.11 def build_attrs(self, *args, **kwargs): """Disable automatic corrections and completions.""" attrs = super(CaptchaAnswerInput, self).build_attrs(*args, **kwargs) attrs["autocapitalize"] = "off" attrs["autocomplete"] = "off" attrs["autocorrect"] = "off" attrs["spellcheck"] = "false" return attrs class BaseCaptchaTextInput(MultiWidget): """ Base class for Captcha widgets """ def __init__(self, attrs=None): widgets = (HiddenInput(attrs), CaptchaAnswerInput(attrs)) super(BaseCaptchaTextInput, self).__init__(widgets, attrs) def decompress(self, value): if value: return value.split(",") return [None, None] def fetch_captcha_store(self, name, value, attrs=None, generator=None): """ Fetches a new CaptchaStore This has to be called inside render """ try: reverse("captcha-image", args=("dummy",)) except NoReverseMatch: raise ImproperlyConfigured( "Make sure you've included captcha.urls as explained in the INSTALLATION section on http://readthedocs.org/docs/django-simple-captcha/en/latest/usage.html#installation" ) if settings.CAPTCHA_GET_FROM_POOL: key = CaptchaStore.pick() else: key = CaptchaStore.generate_key(generator) # these can be used by format_output and render self._value = [key, u("")] self._key = key self.id_ = self.build_attrs(attrs).get("id", None) def id_for_label(self, id_): if id_: return id_ + "_1" return id_ def image_url(self): return reverse("captcha-image", kwargs={"key": self._key}) def audio_url(self): return ( reverse("captcha-audio", kwargs={"key": self._key}) if settings.CAPTCHA_FLITE_PATH else None ) def refresh_url(self): return reverse("captcha-refresh") class CaptchaTextInput(BaseCaptchaTextInput): template_name = "captcha/widgets/captcha.html" def __init__( self, attrs=None, field_template=None, id_prefix=None, generator=None, output_format=None, ): self.id_prefix = id_prefix self.generator = generator if field_template is not None: msg = "CaptchaTextInput's field_template argument is deprecated in favor of widget's template_name." warnings.warn(msg, DeprecationWarning) self.field_template = field_template or settings.CAPTCHA_FIELD_TEMPLATE if output_format is not None: msg = "CaptchaTextInput's output_format argument is deprecated in favor of widget's template_name." warnings.warn(msg, DeprecationWarning) self.output_format = output_format or settings.CAPTCHA_OUTPUT_FORMAT # Fallback to custom rendering in Django < 1.11 if ( not hasattr(self, "_render") and self.field_template is None and self.output_format is None ): self.field_template = "captcha/field.html" if self.output_format: for key in ("image", "hidden_field", "text_field"): if "%%(%s)s" % key not in self.output_format: raise ImproperlyConfigured( "All of %s must be present in your CAPTCHA_OUTPUT_FORMAT setting. Could not find %s" % ( ", ".join( [ "%%(%s)s" % k for k in ("image", "hidden_field", "text_field") ] ), "%%(%s)s" % key, ) ) super(CaptchaTextInput, self).__init__(attrs) def build_attrs(self, *args, **kwargs): ret = super(CaptchaTextInput, self).build_attrs(*args, **kwargs) if self.id_prefix and "id" in ret: ret["id"] = "%s_%s" % (self.id_prefix, ret["id"]) return ret def id_for_label(self, id_): ret = super(CaptchaTextInput, self).id_for_label(id_) if self.id_prefix and "id" in ret: ret = "%s_%s" % (self.id_prefix, ret) return ret def get_context(self, name, value, attrs): """Add captcha specific variables to context.""" context = super(CaptchaTextInput, self).get_context(name, value, attrs) context["image"] = self.image_url() context["audio"] = self.audio_url() return context def format_output(self, rendered_widgets): # hidden_field, text_field = rendered_widgets if self.output_format: ret = self.output_format % { "image": self.image_and_audio, "hidden_field": self.hidden_field, "text_field": self.text_field, } return ret elif self.field_template: context = { "image": mark_safe(self.image_and_audio), "hidden_field": mark_safe(self.hidden_field), "text_field": mark_safe(self.text_field), } return render_to_string(self.field_template, context) def _direct_render(self, name, attrs): """Render the widget the old way - using field_template or output_format.""" context = { "image": self.image_url(), "name": name, "key": self._key, "id": u"%s_%s" % (self.id_prefix, attrs.get("id")) if self.id_prefix else attrs.get("id"), "audio": self.audio_url(), } self.image_and_audio = render_to_string(settings.CAPTCHA_IMAGE_TEMPLATE, context) self.hidden_field = render_to_string( settings.CAPTCHA_HIDDEN_FIELD_TEMPLATE, context ) self.text_field = render_to_string(settings.CAPTCHA_TEXT_FIELD_TEMPLATE, context) return self.format_output(None) def render(self, name, value, attrs=None, renderer=None): self.fetch_captcha_store(name, value, attrs, self.generator) if self.field_template or self.output_format: return self._direct_render(name, attrs) extra_kwargs = {} if django.VERSION >= (1, 11): # https://docs.djangoproject.com/en/1.11/ref/forms/widgets/#django.forms.Widget.render extra_kwargs["renderer"] = renderer return super(CaptchaTextInput, self).render( name, self._value, attrs=attrs, **extra_kwargs ) class CaptchaField(MultiValueField): def __init__(self, *args, **kwargs): fields = (CharField(show_hidden_initial=True), CharField()) if "error_messages" not in kwargs or "invalid" not in kwargs.get( "error_messages" ): if "error_messages" not in kwargs: kwargs["error_messages"] = {} kwargs["error_messages"].update({"invalid": gettext_lazy("Invalid CAPTCHA")}) kwargs["widget"] = kwargs.pop( "widget", CaptchaTextInput( output_format=kwargs.pop("output_format", None), id_prefix=kwargs.pop("id_prefix", None), generator=kwargs.pop("generator", None), ), ) super(CaptchaField, self).__init__(fields, *args, **kwargs) def compress(self, data_list): if data_list: return ",".join(data_list) return None def clean(self, value): super(CaptchaField, self).clean(value) response, value[1] = (value[1] or "").strip().lower(), "" if not settings.CAPTCHA_GET_FROM_POOL: CaptchaStore.remove_expired() if settings.CAPTCHA_TEST_MODE and response.lower() == "passed": # automatically pass the test try: # try to delete the captcha based on its hash CaptchaStore.objects.get(hashkey=value[0]).delete() except CaptchaStore.DoesNotExist: # ignore errors pass elif not self.required and not response: pass else: try: CaptchaStore.objects.get( response=response, hashkey=value[0], expiration__gt=timezone.now() ).delete() except CaptchaStore.DoesNotExist: raise ValidationError( getattr(self, "error_messages", {}).get( "invalid", gettext_lazy("Invalid CAPTCHA") ) ) return value django-simple-captcha-0.5.14/captcha/fonts/000077500000000000000000000000001402513225300204645ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/fonts/COPYRIGHT.TXT000066400000000000000000000135021402513225300224360ustar00rootroot00000000000000Bitstream Vera Fonts Copyright The fonts have a generous copyright, allowing derivative works (as long as "Bitstream" or "Vera" are not in the names), and full redistribution (so long as they are not *sold* by themselves). They can be be bundled, redistributed and sold with any software. The fonts are distributed under the following copyright: Copyright ========= Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org. Copyright FAQ ============= 1. I don't understand the resale restriction... What gives? Bitstream is giving away these fonts, but wishes to ensure its competitors can't just drop the fonts as is into a font sale system and sell them as is. It seems fair that if Bitstream can't make money from the Bitstream Vera fonts, their competitors should not be able to do so either. You can sell the fonts as part of any software package, however. 2. I want to package these fonts separately for distribution and sale as part of a larger software package or system. Can I do so? Yes. A RPM or Debian package is a "larger software package" to begin with, and you aren't selling them independently by themselves. See 1. above. 3. Are derivative works allowed? Yes! 4. Can I change or add to the font(s)? Yes, but you must change the name(s) of the font(s). 5. Under what terms are derivative works allowed? You must change the name(s) of the fonts. This is to ensure the quality of the fonts, both to protect Bitstream and Gnome. We want to ensure that if an application has opened a font specifically of these names, it gets what it expects (though of course, using fontconfig, substitutions could still could have occurred during font opening). You must include the Bitstream copyright. Additional copyrights can be added, as per copyright law. Happy Font Hacking! 6. If I have improvements for Bitstream Vera, is it possible they might get adopted in future versions? Yes. The contract between the Gnome Foundation and Bitstream has provisions for working with Bitstream to ensure quality additions to the Bitstream Vera font family. Please contact us if you have such additions. Note, that in general, we will want such additions for the entire family, not just a single font, and that you'll have to keep both Gnome and Jim Lyles, Vera's designer, happy! To make sense to add glyphs to the font, they must be stylistically in keeping with Vera's design. Vera cannot become a "ransom note" font. Jim Lyles will be providing a document describing the design elements used in Vera, as a guide and aid for people interested in contributing to Vera. 7. I want to sell a software package that uses these fonts: Can I do so? Sure. Bundle the fonts with your software and sell your software with the fonts. That is the intent of the copyright. 8. If applications have built the names "Bitstream Vera" into them, can I override this somehow to use fonts of my choosing? This depends on exact details of the software. Most open source systems and software (e.g., Gnome, KDE, etc.) are now converting to use fontconfig (see www.fontconfig.org) to handle font configuration, selection and substitution; it has provisions for overriding font names and subsituting alternatives. An example is provided by the supplied local.conf file, which chooses the family Bitstream Vera for "sans", "serif" and "monospace". Other software (e.g., the XFree86 core server) has other mechanisms for font substitution. django-simple-captcha-0.5.14/captcha/fonts/README.TXT000066400000000000000000000005001402513225300220150ustar00rootroot00000000000000Contained herin is the Bitstream Vera font family. The Copyright information is found in the COPYRIGHT.TXT file (along with being incoporated into the fonts themselves). The releases notes are found in the file "RELEASENOTES.TXT". We hope you enjoy Vera! Bitstream, Inc. The Gnome Project django-simple-captcha-0.5.14/captcha/fonts/Vera.ttf000066400000000000000000002006141402513225300221030ustar00rootroot00000000000000OS/2_cpVPCLTъ^6cmaplXcvt 9fpgm&`gaspH glyf tA&~hdmx4!Hhead݄T6hheaEoL$hmtx Ǝ0kernRՙ-loca=maxpG:, nameټȵpostZ/prep; h::_:: dM0l   p t  &   Y &  &   c . 5 `  s 0 & {Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved.Bitstream Vera SansBitstreamVeraSans-RomanRelease 1.10Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.http://www.bitstream.comCopyright (c) 2003 by Bitstream, Inc. All Rights Reserved.Bitstream Vera SansBitstreamVeraSans-RomanRelease 1.10Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.http://www.bitstream.com5fqu-J3T99NR7s`s3VV9s3D{o{RoHT3fs +b-{T#\q#H99`#fy```{w``b{{Rffw;{J/}oo5jo{-{T7fD)fs@%2%%A:B2SAS//2ݖ}ٻ֊A}G}G͖2ƅ%]%]@@%d%d%A2dA  d   A(]%]@%..%A  %d%@~}}~}}|d{T{%zyxw v utsrqponl!kjBjSih}gBfedcba:`^ ][ZYX YX WW2VUTUBTSSRQJQP ONMNMLKJKJIJI IH GFEDC-CBAK@?>=>=<=<; <@; :987876765 65 43 21 21 0/ 0 / .- .- ,2+*%+d*)*%)('%(A'%&% &% $#"!! d d BBBdB-B}d       -d@--d++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++, %Id@QX Y!-,%Id@QX Y!-,  P y PXY%%# P y PXY%-,KPX EDY!-,%E`D-,KSX%%EDY!!-,ED-ff@ /10!%!!fsr)5 @@ <2991/0K TX @ 878Y P ]%3#3#5qeM@1<20KTKT[X@878Y@0 @ P ` p ]#!#o$++`@1      91/<<<<<<<2220@   ]!! !3!!!!#!#!5!!5!T%Dh$ig8R>hggh`TifaabbNm!(/@U" '&( /)/))/B" ) *!#*- ) " & 0<<<1/299990KSX99Y"K TX0@00878YK TKT[KT[X000@878Y#.'5.546753.'>54&dijfod]SS\dtzq{---@A$*.U# jXV`OnZXhq) #'3@6$%&%&'$'B .$ &($4'!%   ! + 1 49912<0KSXY"K TK T[K T[KT[KT[K T[X4@44878Y"32654&'2#"&546"32654&%3#2#"&546WccWUccUVcbWWcd1Zܻۻa ۻۼ 0@      !         B  (('+'$ .  .'.'!!199999991/9990KSX99999999Y"2]@ " ) **&:4D ^YZ UZZY0g{ "-  ' (   2'') #**(/2; 49?2J LKFO2VZ Y UY\_2j i`2uy z 2229]]3267 >73#'#"5467.54632.#"[UԠ_I{;B h]hΆ02޸SUWDi;#QX?@Yr~YW׀c?}<$$/1oX3goB@ 10KTKT[X@878Y@ @P`p]#o+{ O@  29910KTX@878YKTX@878Y#&547{>;o @ <99103#654<:=JN@,       <2<2991<22990%#'%%73%g:r:g:PrPbybcy #@   <<1/<<0!!#!5!-Ө-Ӫ--@ 1073#ӤR@d10!!d1/073#B-@B/9910KSXY"3#m #@  10"32'2#"  P3343ssyzZ K@B  1/20KSXY"KTX  @878Y]7!5%3!!JeJsHHժJ@'B   91/20KSX9Y"KTKT[KT[X@878Y@2UVVzzvtvust]]%!!567>54&#"5>32Ls3aM_xzXE[w:mIwBC12\ps({@.    #)&  )99190KTKT[X)@))878Y@ daa d!]!"&'532654&+532654&#"5>32?^jTmǹSrsY %Đ%%12wps{$& Ѳ|d @   B    <291/<290KSXY"K TK T[X@878Y@* *HYiw+&+6NO O Vfuz ]] !33##!55^%3`du@#    190KTKT[X@878YKTX@878Y!!>32!"&'532654&#",X,$^hZkʭQTժ 10$& $X@$  "% " !%190@]]"32654&.#">32# !2 LL;kPL;y$&W]ybhc@B991/0KSXY"KTX@878Y@X9Hg]]!#!3V+ #/C@% '-'0 $*$ !0991990"32654&%&&54632#"$54632654&#"HŚV г "Əُattt$X@# %!"" %190@]]7532#"543 !"&2654&#"LK:lL>$& V\s[#@<21/073#3### %@  <2103#3#ӤR#٬@^M@*B$#29190KSXY" 5Ѧ`@ #<210!!!!^O@+B$#<9190KSXY"55//m$p@+$     &%99991/9990K TX%@%%878Yy z z ]%3##546?>54&#"5>32ſ8ZZ93lOa^gHZX/'eVY5^1YnFC98ŸLVV/5<4q L@2  L4307$7CM34( (+(I+*(I,=M<9912990K TK T[KT[KT[KT[XMMM@878Y@ NN/N?N]32654&#"#"&5463253>54&'&$#"3267#"$'&5476$32|{zy!orqp ˘s'6@   0210].# !267# !2'ffjzSb_^^_HHghG.@   2 99991/0`]3 !%! )5BhPa/w.,~ .@   21/0 ]!!!!!!9>ժF# )@ 21/0 ]!!!!#ZpPժH7s9@ 43 1990%!5!# !2&&# !26uu^opkSUmnHF_`%; ,@ 8  221/<20P ]3!3#!#"d+991/0KTX@878Y@ 0@P`]3#+f M@  9 991990KTX  @878Y@ 0 @ P ` ]3+53265M?nj @(B  291/<290KSXY"]@ ((764GFCUgvw    (+*66650 A@E@@@ b`hgwp  ,]q]q3! !#3wH1j%@ :1/0@ 0P]3!!_ժ @4  B    >  91/<290KSXY"p]@V   && & 45 i|{y   #,'( 4<VY ej vy ]]! !###-}-+3 y@B6 991/<2990KSXY" ]@068HGif FIWXeiy ]]!3!#j+s #@  310"32' ! ':xyLHH[[bb:@   ? 291/0@ ?_]32654&#%!2+#8/ϒs R@*  B     39991990KSX9Y""32#'# ! '? !#y;:xLHHab[T@5  B    ?  299991/<9990KSX9Y"@]@Bz%%%&'&&& 66FFhuuw]]#.+#! 32654&#A{>ٿJx~hb؍O'~@<    B %( "-"(9999190KSX99Y")])/)O)].#"!"&'532654&/.54$32Hs_wzj{r{i76vce+ٶ0/EF~n|-&J@@@1/20K TX@878Y@  @ p ]!!#!ժ+)K@   8A1299990KTX@878Y]332653! ˮ®u\*$h@'B91/290KSXY"P]@b*GGZ} *&&))% 833<<7HEEIIGYVfiizvvyyu)]]!3 3J+D {@I      B     91/<2290KSXY"]@  ($ >>4 0 LMB @ Yjkg ` {|      !   # $ %  <:5306 9 ? 0FFJ@E@BBB@@ D M @@XVY Pfgab```d d d wv{xwtyywpx   []]3 3 3# #D:9:9+=; ]@F      B    91/<290KSXY"K TK T[KT[X  @878Y@ '' 486 KX[fkww       &()&(' ) 54<;:;4 4 8 ? H O X _ eejjhiil l xyyx}  x   @]]3 3 # #su \Y+3{@(B@@ 91/290KSXY" ]@<5000F@@@QQQe &)78@ ghxp ]]3 3#f9\ @BB 991/0KSXY"K TK T[X @ 878Y@@ )&8HGH    / 59? GJO UYfio wx ]]!!!5!sP=g՚oXS@C210K TX@878YKTKT[X@878Y!#3!XB-@B/9910KSXY"#mo<@C<10KTKT[X@878Y!53#5oXޏ@ 91290##HHu-10!5f1@ D10K TKT[X@878Y #ofv{-{ %@'   #   E&22991/9990@n0000 0!0"?'@@@@ @!@"PPPP P!P"P'p' !"'''000 0!@@@ @!PPP P!``` `!ppp p! !]]"326=7#5#"&5463!54&#"5>32߬o?`TeZ3f{bsٴ)Lfa..'' 8@  G F221/0`]4&#"326>32#"&'#3姒:{{:/Rdaadq{?@  HE210@ ].#"3267#"!2NPƳPNM]-U5++++$$>:#qZ8@G E221/0`]3#5#"3232654&#":||ǧ^daDDaq{p@$   KE9190@)?p?????,// , ooooo ]q]!3267# 32.#" ͷjbck)^Z44*,8 Cė/p@     L<<991/22990K TX@878YKTX@878Y@P]#"!!##535463cM/ѹPhc/яNqVZ{ (J@#  &#' & G E)221/990`***]4&#"326!"&'5326=#"3253aQQR9||9=,*[cb::bcd4@  N  F21/<90`]#4&#"#3>32d||Bu\edy+@F<21/0@  @ P ` p ]3#3#`Vy D@   O  F<2991990@ @P`p]3+532653#F1iL`a( @)B F 291/<90KSXY" ]@_ ')+Vfgsw    ('(++@ h` ]q]33 ##%kǹi#y"F1/0@ @P`p]3#{"Z@&   PPF#291/<<<290@0$P$p$$$$$$$ ]>32#4&#"#4&#"#3>32)Erurw?yz|v\`gb|d{6@  N  F21/<90`]#4&#"#3>32d||Bu\`edqu{ J@  QE10@#?{{   {  {]"32654&'2#"s98V{>@ GF2210@ `]%#3>32#"&4&#"326s:{{8 daaqVZ{ >@   GE2210@ `]32654&#"#"3253#/s:||:/daDDadJ{0@    F21/90P].#"#3>32JI,:.˾`fco{'@<  S  SB %( R"E(9999190KSX99Y"']@m   . , , , ; ; ; ; $( ( *//*(() )!$'      '/)?)_))))))]]q.#"#"&'532654&/.54632NZb?ĥZlfae@f?((TT@I!*##55YQKP%$78@  F<<2991/<2990]!!;#"&5#53w{KsբN`>X`6@    NF21/290`]332653#5#"&||Cua{fc=`@'B91/290KSXY"K TX@878YKTKT[X@878Y@Hj{  &&)) 55::0FFIIFH@VVYYPffiigh`ut{{uz>]]3 3#=^^\`TV5` @IU U U U   B     91/<2290KSXY"K TKT[KT[KT[K T[X  @878YK TK T[KT[X @ 878Y@" 5 IIF @ [[U P nnf yy          %%#'!%""%' $ ! # 9669 0FHF@B@@@D D D @@VVVPQRRPS T U cdejejjjn a g ouuy}x}zzxy  { v } @/   y]]333# #V`jjj;y` Z@F      B   91/<290KSXY"K TKT[KT[KT[X  @878YKTX @ 878Y@   & =1 UWX f vzvt        )&% * :9746 9 0 IFE J @ YVYYWVYVV Y P o x  /]] # # 3 dkr))`HJq=V`@C        B     9129990KSX2Y"K TKT[X@878YKTX@878Y@     # 5 I O N Z Z j        '$$  )( % $ $ ' ** 755008 6 6 8 990A@@@@@@@@B E G II@TQQUPPVUVW W U U YYPffh ii`{xx   e]]+5326?3 3N|lLT3!;^^hzHTNlX` @B 2991/0KSXY"K TK T[X @ 878YKTX  @878Y@B&GI  + 690 @@E@@CWY_ ``f``b ]]!!!5!qjL}e`ۓ%$@4 %   !  % $  C %<<29999999199999990K TX%%%@878Y&]#"&=4&+5326=46;#"3>l==k>DV[noZVtsݓXX10#$@6%   #%#C %<2<9999999199999990K TX%@%%878YKTX%%%@878Y&]326=467.=4&+532;#"+FUZooZUF?l>>l?VWstݔ1#@  1990#"'&'&'&#"56632326ian ^Xbian ^V1OD;>MSOE<>LhN'$uhm !@T   !!  ! !!!B     !  VV!"2299999991/<9990KSXY" #]@  s P#f iu {yyv v!# ]]4&#"326!.54632#!#TY?@WX??Y!X=>sr?<҈_Z?YWA?XXN)sIsrFv)su''&-k'(u3^'1usN'2'u)N'8u{-f'DR{-f'DCR{-f'DR{-'DR{-7'DR{-'DRqu{'Fqf'Hqf'HCqf'Hq'Hof'f'C\f'F'd7'Qquf'Rsquf'RCsquf'Rsqu'Rsqu7'RsXf'X{Xf'XC{Xf'X{X'X{9; '@  YW Y <<1<203!!#!5!oo\]u=  @  Z[Z10"32654&'2#"&546PnnPPnoO@v+..ooPOmmOOp1.-rB#!Q@+     "  "<<<221<9990%&&'667#&73JDFHAMf fIX⸹)**'# 32!b`@!    <<1/2<2990K TX@878Y66].#"!!!!53#535632NL=ty-=))׏/я\= >@54&.#"#"&'532654/.5467.54632{?>?>S8alӃ\]>9̭IXW:fqր][;;ȦI.Z.L-[.K''PGZsweZ54m@''TLf{xf[1,pE3!   \ 104632#"&3~|}}||};9 %@]] 91290!###&&54$yfNݸ/@0-'!  **.  !' $'$-F099991/990@@'(     ! "&  : :!MM I!I"jj  ]]4632#"&'532654&/.5467.#"#:A9`@IPAtx;e\`Wqqs`/Q*%jd_[?T>7;[gp/8L`@6EBC?2H09JC 9 $HE301BKL?gwyVpMI`3D/IC@&=>:A$104G$ 7aD=0^* D^ J21/02#"$'&5476$"32676654&'&&&&#"3267#"&54632mmllmmmmllmm^^``^^⃄^]]^\^BB@zBCFInmmmmnnmmmmng^^^傁^^__^]⃅]^^! "'F >@!    b b cbc91<<2<<903#######5Jq7rqr/B^^sRf1@ D10K TKT[X@878Y3#fF)@dd1<20K TK T[X@878YK TK T[KT[KT[X@878YKTKT[X@878Y@````pppp]3#%3#^y'>@"     <291<2<<990!!!!!'7!5!7!}/H{};fըfӪH@9  B     <291/<0KSXY"]@gww  ]!!!!!!#!59=qժF՞f +@< +,  )&  *&& &,+,* # )#3,99999999199999990@*WZWU!je!{vu! FYVjddj(|svz( ]] 324&'.#"&5!27!"&''3>_'y=_''NOy;WfNPƀ[gX@CHp@CpDfbMKYg[KKX /@- !$'!!0 $*0999919990@     $$$   $$ $ ***///***55500055 5 :::???:::EEE@@@EE E JJJOOOJJJV !"&'()]]32654&#".#"326#"&54632>32#"&1TevYR1UfvYRF^_HDa^/XZie7XXjeߦ~᧯w .@     <2<21/<<0!!#!5!!!-Ө-}} T@.B $# <2291/90KSXY" 5!!@po V@/B$ # <<291/90KSXY"55!5AǪR@F  B     fe f e<2299991/2<2<290KSXY"K TX@878Y@(' ' ')((79  ]]!#!5!5'!5!3 3!!!c`Tþ{yT9{3{JD{3V` M@%  !   NF!2912<990"`""]3326533267#"&'#"&'#% )I#ER2bf*V H<9 NPOONNh-)b@'! '!* $$*9991990K TK T[KT[KT[KT[X*@**878Y>54&#"#"&54632#"&54324&#"32IH7$$0e՘ݢe WOmVPmmWKt,>bFأ[t}t{w; ]@    91990@0QVPZ spvupz  Z pp{ t  ]]!! !!5 7AJI3!wq@gg120!#!# }/#@1 " $ #" #h#$9999991/<229990K TX$$$@878Y@V             ##(]]#3267#"&5467!##"#>3!i/7.%7vy"Pµ)6< yJ\:1fd.xo@E}/%&@  & iji&1026732#"&'&&#"#"&546327j Pd@7*8  kOeD=!0 l9TA6?&#Hn!bSA8?Ss;)_@3(%%  * "(kl"k *22999199990!!#5#"&5463354&#"56632"32655P,]uu>DIE~bRhP{@p?Dq[[""CO@Mr`d.@  klk 9910!!2#"&546"32654&PXγгi~hi}|P{ݿܾsN@@"   mm  9991/<20%!5654#"!5!&5! Dz?1/aL"a*>w؍{o{3>@C'-%= 4%:.-*1 %?47&%7& =&-7"E?<9999912<<29990@0+0,0-0.0/00@+@,@-@.@/@0P+P,P-P.P/P0+0@@@@@@@@@??? ??0,0-0.0/@,@-@.@/P,P-P.P/ooo oo`,`-`.`/p,p-p.p/,-./]q].#">32!3267#"&'#"&5463!54&#"5>32"326=DJԄ ̷hddjMI؏`TeZ߬o0Z^Z55*,ywxx..''`f{bsٴ)H +@<+,&  )&  *&& &,+,* # #Q)E,22999999199999990@p(?-YVUV jf!{    { z{ {!"#$%{&%--&YVUZ(ifej(ztvz($$]] 32654&'.#".5327#"&'')gA\*g>}66]C_56`?`!*(Ou))Hn.Mw834OMx43N $@/  !# #%" " "!& %999919990KTKT[KT[X%%%@878Y@ ttttv]33267#"&546?>7>5#537ZZ:3mN`^gIYX0&DeWX5^1YnFC98ŸLVV/5<65 b@ <2991/0K TX @ 878YKTKT[KT[X  @878Y P ]#53#3+e^@ 10!#!^=} *@    91903##'%\sB}}`s-Pb;V#@@   B   !$  $912299990KSX29Y"K TX$$$@878Y.#"!!#"&'53267#5!>32&P,`r<::d/4a/am"?$Ɨ5dzɏ!!J;?@.9*-" *19" <-<<219999990#"'&'&'&#"56632326#"'&'&'&#"56632326ian ^Xbian ^Vgian ^Xbian ^VoNE;=LTNE;=KڲOE;=LSNE;=K`8@91/90@cmpxyvn]] !3!^DC?%# @I    B   o o n<2991<2990KSXY"55%-+#-+#RRH# @I  B   o op<<991<2990KSXY"5%5+-+-#^R^  ^R^   #@   1/<<220%3#%3#%3#hk'$uh^'$us^'2'us ;@   299991/220!!!!! !# !39OAg@AժF|pm|q{'3@1 . ("%4"1 K1 Q+E499912<2290@%?5_5p55555????? ooooo ]q].#"!3267#"&'#"32>32%"32654& H ̷jbdjQGьBN5Z44*,nmnm98olkp݇y/10!!yy/10!!ym '@   1<20#53#53ӤRӤR??m '@   1<203#%3#ӤRӤRլ@@@ 10#53ӤR?@ q103#ӤR՘?o )@ r <<103#3#!!oA#u"@91990  9%-=V'\^N'<su+@B10KSXY"3#-\^R#/@I -'! - -'!0 *$0* $ $(st*(s099999999919999999907'#"&''7&&5467'766324&#"326{r%$&(r;t=:x=q%%&&s7t@?s9q(&%%s>v:@t8s'%$|pprs#G@%Bon29190KSXY"5s-+#R#I@&Bop<9190KSXY"5+-#^R^  /J@(   L<2<2991/<22990K TX@878YKTX@878Y@0P]]#!##53546;#"3#JcM`/яNPhc/J@!    L<<991/<22990K TX@878YKTX@878Y@0P ]!#!"!!##53546JcM/ѹ{Phc/яN9;>@   Y W Y <<2<<2122220%!#!5!!5!3!!!oooo\\HF103#F@ 10%3#ӤR@m '@    1<20%3#%3#ӤRfӤR@@q L #'3?K@D$%&%&'$'B@ .(F4 :&$L%IC'1+C =  1 =I 7+ ! L9912<<2220KSXY"KTK T[K T[K T[K T[KT[XL@LL878Y"32654&'2#"&5462#"&546!3#"32654&2#"&546"32654&WddWUccUt%ZVcbWWcdWccWUccܻۻۻۼܻۻhm'$um'(uhk'$uN'(uk'(uk',/u`m',/uXN',/u;k',/usk'2'usm'2'usk'2'u)k'8u)m'8u)k'8uy` F1/0@ @P`p]3#`?f7@ u91290K TKT[X@878Y3#'#fJ7c@$   VwVv99991<<99990K TK T[X@878Y'.#"#>3232673#"&9! &$}f[&@%9! &$}f[&@Z7IR!7IRb+/10K TKT[X@878Y!!V)9H W@ VV1<0K TX@878YKTKT[KT[X@878Y332673#"&v aWV` v HKKJLDf,@ d10K TX@878Y3# _@ V xV10K TK T[X@878YK TK T[K T[X@878Y4&#"3267#"&54632X@AWWA@Xzssss?XW@AWX@sss#u@  ' 1/90!#"&'532654&'T76xv.W+"J/;<+->i0Y[ 0.W=fB@991<20K TKT[X@878Y3#3#߉fxLu @   '1/90!33267#"&546w-+76 >&Dzs5=X.. W]0i?f7@ u91<90K TKT[X@878Y373xu ?@   : y<<991/900P]3%!!'79Pw^Mo;jnH ^@  z z <<991/90KTX @ 878Y@ @ P ` sz p ]37#'7Ǹ}Lɸ{JZjXjm'6uof'V\m'=uXf']@ <210##    g@    2  y<291/220@(   ]]! )#53!!3 !iP`P5~.,qu('@^%{&%#${##{#({'(#&'('%$%(('"#" ! B('&%"! ## #)&' ! (%#" QE)999999919990KSXY"?*]@v%+("/#/$)%-&-'*(6%F%X X!` `!f"u u!u"%#%$&&&''(6$6%F$E%Z Z!b b!z{     {zzv v!x"**']].#"32654&#"5432''%'3%F2X)6 ~r4*!M!ü޼z&77kc\̑oabk'<su=Vf'\^ =@   ? 2291/0@ ?_]332+#32654&#'ђV>@ GF2210@ `]%#3>32#"&4&#"326s:{{8daa-10!!ת? @M    B   <291<290KSXY" '77w55v8vL57y5yy5 ,@   |]|| 12035733! c)t'+n^J@$}}B ~9190KSX2Y"!!56754&#"56632 "?XhU4zHM98rn81^BQ##{l0b(H@'    #)~&~ )999190#"&'532654&##532654&#"56632 \e9}F4wCmxolV^^ad_(fQI7Z`mR|yOFJLl?<:=svcE`''5 d?''5db''5 dsm'* uqVZH'JP', /uu'6ou{'Vs'k'&-uqf'Fs'm'&-uqf'Fq$J@$ "    GE%<<1/<20`&&&]!5!533##5#"3232654&#"F:||ǧN}}daDDad10!!dHF103#F1@: "+ /) 2+"!)#&  , & &*!/<29999999999122<20K TK T[K T[KT[KT[KT[X222@878Y@z  1Ti lnooooiko o!o"o#n$l%i'i-  !"#$%&'()*+,-2   USjg ]].#"!!!!3267#"#734&5465#7332[f A78 ʝf[Y`(77(6bbiZȻ{.# .{ZiHH"{/ #/{"G)@ dd1<20KTKT[X@878YKTK T[KT[X@878YKTKT[X@878YKTX@878Y@````pppp]3#%3#^ys@B10KSXY"K TX@878YKTX@878Y@ %%6FVjg //]]3#7Ju@!  VV 99991<2990K TX@878YKTX@878Y ]'.#"#4632326=3#"&9 $(}gV$=09" (}gT";9! 2-ev 3)dw @B10KSXY"K TX@878YKTX@878Y@*$$5CUU//]]#ę1w@ 91<90K TX@878YKTX@878YKTX@878Y@ //- ]3#'#Ӌ1@ 91290K TK T[K T[K T[X@878YKTX@878YKTX@878Y@ "  ]373Ӌ ? @   ] <291<290KTKT[KT[KT[K T[K T[X@878YKTKT[X@878Y@T /9IFYi       "5GK S[ e]] !33##5!55bf]my9 j@ VV120K TX@878YKTX@878YKTKT[X@878Y332673#"&v cSRav 6978w{zf103#  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~>: ~1BSax~ & 0 : !""""+"H"e%  0AR^x}  0 9 !""""+"H"`%^ChVjq_8 (Bbcdefghjikmlnoqprsutvwxzy{}|~f55q=3=dd?y}s)3s\\?uLsLsyD{={\{fqqq/q999qqJ+o#7=V;=3XyysLs{{{{{{fqqqqq9999qqqqq9\3 'sLfR#hd+/s`N{H?55=ZyyLss/q%%=V^33 / /9% qyy\\\\;LsLsLs9#LF+o{\3X3 q=55^5bb3sq\+osfqsfqqds 5?+   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~     sfthyphenperiodcenteredEuroc6459c6460c6461c6462c6463c6466c6467c6468c6469""""XO!nE~Le  R s  X : i  = z /Eu)pP@"m#{CwRw [ r !5!B!!!" ""#"0"="J"W"d"q"~"""""""""## ##'#4#A#N#[#h##$4$%3%S%&&'K''((X()_*%*\**+z+,D,,-P-..R./0A011!1P12H2z23F3p3p3}3334z44445595g55556[667C77888J999)969C9P9]9j9w99999999::{::;;^;;;<"<_<<<<<<=c>;>H>U>>>?a??@:@K@\@m@z@@@@@@@@A@AVAkBEBBC_CCDUDE*E?- x$%&')*K+-r./2934K57D9:;< =IQR&UYZ\bdg9xy&z&{&|&}&9 999 K$$$$$9$&$*$2$4$6$7a$8$9}$:$;$= settings.CAPTCHA_DICTIONARY_MIN_LENGTH and len(word) <= settings.CAPTCHA_DICTIONARY_MAX_LENGTH ): break return word.upper(), word.lower() def huge_words_and_punctuation_challenge(): "Yay, undocumneted. Mostly used to test Issue 39 - http://code.google.com/p/django-simple-captcha/issues/detail?id=39" fd = open(settings.CAPTCHA_WORDS_DICTIONARY, "rb") l = fd.readlines() fd.close() word = "" while True: word1 = random.choice(l).strip() word2 = random.choice(l).strip() punct = random.choice(settings.CAPTCHA_PUNCTUATION) word = "%s%s%s" % (word1, punct, word2) if ( len(word) >= settings.CAPTCHA_DICTIONARY_MIN_LENGTH and len(word) <= settings.CAPTCHA_DICTIONARY_MAX_LENGTH ): break return word.upper(), word.lower() def noise_arcs(draw, image): size = image.size draw.arc([-20, -20, size[0], 20], 0, 295, fill=settings.CAPTCHA_FOREGROUND_COLOR) draw.line( [-20, 20, size[0] + 20, size[1] - 20], fill=settings.CAPTCHA_FOREGROUND_COLOR ) draw.line([-20, 0, size[0] + 20, size[1]], fill=settings.CAPTCHA_FOREGROUND_COLOR) return draw def noise_dots(draw, image): size = image.size for p in range(int(size[0] * size[1] * 0.1)): draw.point( (random.randint(0, size[0]), random.randint(0, size[1])), fill=settings.CAPTCHA_FOREGROUND_COLOR, ) return draw def noise_null(draw, image): return draw def post_smooth(image): from PIL import ImageFilter return image.filter(ImageFilter.SMOOTH) def captcha_image_url(key): """Return url to image. Need for ajax refresh and, etc""" return reverse("captcha-image", args=[key]) def captcha_audio_url(key): """Return url to image. Need for ajax refresh and, etc""" return reverse("captcha-audio", args=[key]) django-simple-captcha-0.5.14/captcha/jinja2/000077500000000000000000000000001402513225300205105ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/jinja2/captcha/000077500000000000000000000000001402513225300221135ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/jinja2/captcha/widgets/000077500000000000000000000000001402513225300235615ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/jinja2/captcha/widgets/captcha.html000066400000000000000000000002721402513225300260530ustar00rootroot00000000000000{% if audio %}{% endif %}captcha{% if audio %}{% endif %} {% include "django/forms/widgets/multiwidget.html" %} django-simple-captcha-0.5.14/captcha/locale/000077500000000000000000000000001402513225300205725ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/bg/000077500000000000000000000000001402513225300211625ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/bg/LC_MESSAGES/000077500000000000000000000000001402513225300227475ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/bg/LC_MESSAGES/django.mo000066400000000000000000000012151402513225300245450ustar00rootroot00000000000000<\pq_0.-_Invalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha 0.4.1 Report-Msgid-Bugs-To: PO-Revision-Date: 2014-02-10 15:00+0200 Last-Translator: Venelin Stoykov Language-Team: bg Language: bg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1) Сгрешен текстЧуй текста като аудио файлТова поле е задължителноdjango-simple-captcha-0.5.14/captcha/locale/bg/LC_MESSAGES/django.po000066400000000000000000000020441402513225300245510ustar00rootroot00000000000000# 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 , 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 \n" "Language-Team: bg \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 "Това поле е задължително" django-simple-captcha-0.5.14/captcha/locale/cs/000077500000000000000000000000001402513225300211775ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/cs/LC_MESSAGES/000077500000000000000000000000001402513225300227645ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/cs/LC_MESSAGES/django.mo000066400000000000000000000011251402513225300245620ustar00rootroot00000000000000<\pqS#>Invalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: 0.3.5 Report-Msgid-Bugs-To: PO-Revision-Date: 2012-10-09 07:08+0200 Last-Translator: Beda Kosata Language-Team: Czech <> Language: cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2; Neplatná CAPTCHAPřehrát captchu jako audio souborToto pole je povinné.django-simple-captcha-0.5.14/captcha/locale/cs/LC_MESSAGES/django.po000066400000000000000000000016661402513225300245770ustar00rootroot00000000000000# Czech translation of django-simple-captcha. # Copyright (C) 2012 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Beda Kosata , 2012. # msgid "" msgstr "" "Project-Id-Version: 0.3.5\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-10-09 07:05+0200\n" "PO-Revision-Date: 2012-10-09 07:08+0200\n" "Last-Translator: Beda Kosata \n" "Language-Team: Czech <>\n" "Language: cs\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:50 msgid "Play CAPTCHA as audio file" msgstr "Přehrát captchu jako audio soubor" #: fields.py:67 fields.py:99 tests/__init__.py:62 msgid "Invalid CAPTCHA" msgstr "Neplatná CAPTCHA" #: tests/__init__.py:88 msgid "This field is required." msgstr "Toto pole je povinné." django-simple-captcha-0.5.14/captcha/locale/de/000077500000000000000000000000001402513225300211625ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/de/LC_MESSAGES/000077500000000000000000000000001402513225300227475ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/de/LC_MESSAGES/django.mo000066400000000000000000000011721402513225300245470ustar00rootroot00000000000000<\pqs(!<^Invalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha Report-Msgid-Bugs-To: PO-Revision-Date: 2013-07-16 12:10+0100 Last-Translator: Patrick Lauber Language-Team: DE Language: de MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); X-Generator: Poedit 1.5.7 Ungültiges CAPTCHACAPTCHA als Audiodatei abspielen.Dieses Feld wird benötigt.django-simple-captcha-0.5.14/captcha/locale/de/LC_MESSAGES/django.po000066400000000000000000000017521402513225300245560ustar00rootroot00000000000000# 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 , 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: 2013-07-16 12:10+0100\n" "Last-Translator: Patrick Lauber \n" "Language-Team: DE \n" "Language: de\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.5.7\n" #: fields.py:90 msgid "Play CAPTCHA as audio file" msgstr "CAPTCHA als Audiodatei abspielen." #: fields.py:105 fields.py:134 tests/tests.py:99 tests/tests.py:239 #: tests/tests.py:246 msgid "Invalid CAPTCHA" msgstr "Ungültiges CAPTCHA" #: tests/tests.py:125 msgid "This field is required." msgstr "Dieses Feld wird benötigt." django-simple-captcha-0.5.14/captcha/locale/en/000077500000000000000000000000001402513225300211745ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/en/LC_MESSAGES/000077500000000000000000000000001402513225300227615ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/en/LC_MESSAGES/django.po000066400000000000000000000016101402513225300245610ustar00rootroot00000000000000# django-simple-captcha French translation. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Patrick Samson , 2010. # msgid "" msgstr "" "Project-Id-Version: django-simple-captcha 0.2.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-07-25 11:44+0300\n" "PO-Revision-Date: 2010-09-16 12:16+0200\n" "Last-Translator: Marco Bonetti \n" "Language-Team: en \n" "Language: en\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:49 msgid "Play CAPTCHA as audio file" msgstr "Play CAPTCHA as audio file" #: fields.py:66 fields.py:89 tests/__init__.py:62 msgid "Invalid CAPTCHA" msgstr "" #: tests/__init__.py:88 msgid "This field is required." msgstr "" django-simple-captcha-0.5.14/captcha/locale/es/000077500000000000000000000000001402513225300212015ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/es/LC_MESSAGES/000077500000000000000000000000001402513225300227665ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/es/LC_MESSAGES/django.mo000066400000000000000000000011301402513225300245600ustar00rootroot00000000000000<\pqY!=Invalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha Report-Msgid-Bugs-To: PO-Revision-Date: 2014-05-20 21:22+0100 Last-Translator: https://github.com/dragosdobrota Language-Team: es Language: es MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); X-Generator: Poedit 1.6.5 CAPTCHA no válidoReproducir CAPTCHA de audioEste campo es obligatorio.django-simple-captcha-0.5.14/captcha/locale/es/LC_MESSAGES/django.po000066400000000000000000000017101402513225300245670ustar00rootroot00000000000000# 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 , 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." django-simple-captcha-0.5.14/captcha/locale/fa/000077500000000000000000000000001402513225300211605ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/fa/LC_MESSAGES/000077500000000000000000000000001402513225300227455ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/fa/LC_MESSAGES/django.mo000066400000000000000000000012601402513225300245430ustar00rootroot00000000000000<\pqn##CG$Invalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha 0.2.0 Report-Msgid-Bugs-To: PO-Revision-Date: 2020-10-04 19:08+0330 Last-Translator: Mehdi Namaki Language-Team: fa Language: fa MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=n>1; X-Generator: Poedit 2.3 کد امنیتی صحیح نیستپخش کد امنیتی به عنوان یک پرونده صوتیاین فیلد اجباری است.django-simple-captcha-0.5.14/captcha/locale/fa/LC_MESSAGES/django.po000066400000000000000000000020231402513225300245440ustar00rootroot00000000000000# django-simple-captcha French translation. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Patrick Samson , 2010. # msgid "" msgstr "" "Project-Id-Version: django-simple-captcha 0.2.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-07-25 11:44+0300\n" "PO-Revision-Date: 2020-10-04 19:08+0330\n" "Last-Translator: Mehdi Namaki \n" "Language-Team: fa \n" "Language: fa\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 2.3\n" #: fields.py:49 msgid "Play CAPTCHA as audio file" msgstr "پخش کد امنیتی به عنوان یک پرونده صوتی" #: fields.py:66 fields.py:89 tests/__init__.py:62 msgid "Invalid CAPTCHA" msgstr "کد امنیتی صحیح نیست" #: tests/__init__.py:88 msgid "This field is required." msgstr "این فیلد اجباری است." django-simple-captcha-0.5.14/captcha/locale/fr/000077500000000000000000000000001402513225300212015ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/fr/LC_MESSAGES/000077500000000000000000000000001402513225300227665ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/fr/LC_MESSAGES/django.mo000066400000000000000000000011221402513225300245610ustar00rootroot00000000000000<\pqX 8Invalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha 0.2.0 Report-Msgid-Bugs-To: PO-Revision-Date: 2010-09-16 12:16+0200 Last-Translator: Patrick Samson Language-Team: fr Language: fr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=n>1; CAPTCHA invalideÉcouter la version audioCe champ est obligatoire.django-simple-captcha-0.5.14/captcha/locale/fr/LC_MESSAGES/django.po000066400000000000000000000016611402513225300245740ustar00rootroot00000000000000# django-simple-captcha French translation. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Patrick Samson , 2010. # msgid "" msgstr "" "Project-Id-Version: django-simple-captcha 0.2.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-07-25 11:44+0300\n" "PO-Revision-Date: 2010-09-16 12:16+0200\n" "Last-Translator: Patrick Samson \n" "Language-Team: fr \n" "Language: fr\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:49 msgid "Play CAPTCHA as audio file" msgstr "Écouter la version audio" #: fields.py:66 fields.py:89 tests/__init__.py:62 msgid "Invalid CAPTCHA" msgstr "CAPTCHA invalide" #: tests/__init__.py:88 msgid "This field is required." msgstr "Ce champ est obligatoire." django-simple-captcha-0.5.14/captcha/locale/it/000077500000000000000000000000001402513225300212065ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/it/LC_MESSAGES/000077500000000000000000000000001402513225300227735ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/it/LC_MESSAGES/django.mo000066400000000000000000000011671402513225300245770ustar00rootroot00000000000000<\pqh;ZInvalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha 0.3.6 Report-Msgid-Bugs-To: PO-Revision-Date: 2012-11-14 02:53+0000 Last-Translator: Arjuna Del Toso MIME-Version: 1.0 Language-Team: Arjuna Del Toso Language: it Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=n>1; Parola di controllo sbagliataAscolta la parola di controlloQuesto campo è obbligatoriodjango-simple-captcha-0.5.14/captcha/locale/it/LC_MESSAGES/django.po000066400000000000000000000017421402513225300246010ustar00rootroot00000000000000# django-simple-captcha Italian translation. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Arjuna Del Toso , 2012 # msgid "" msgstr "" "Project-Id-Version: django-simple-captcha 0.3.6\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-11-14 02:53+0000\n" "PO-Revision-Date: 2012-11-14 02:53+0000\n" "Last-Translator: Arjuna Del Toso \n" "MIME-Version: 1.0\n" "Language-Team: Arjuna Del Toso \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" #: .\fields.py:56 msgid "Play CAPTCHA as audio file" msgstr "Ascolta la parola di controllo" #: .\fields.py:71 .\fields.py:96 .\tests\__init__.py:70 msgid "Invalid CAPTCHA" msgstr "Parola di controllo sbagliata" #: .\tests\__init__.py:97 msgid "This field is required." msgstr "Questo campo è obbligatorio" django-simple-captcha-0.5.14/captcha/locale/ja/000077500000000000000000000000001402513225300211645ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/ja/LC_MESSAGES/000077500000000000000000000000001402513225300227515ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/ja/LC_MESSAGES/django.mo000066400000000000000000000011741402513225300245530ustar00rootroot00000000000000<\pq\"+4`Invalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha Report-Msgid-Bugs-To: PO-Revision-Date: 2014-02-13 07:11+0900 Last-Translator: Keisuke URAGO Language-Team: Keisuke URAGO Language: ja MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; CAPTCHAの値が違っていますCAPTCHAをオーディオで読み上げるこの項目は必須ですdjango-simple-captcha-0.5.14/captcha/locale/ja/LC_MESSAGES/django.po000066400000000000000000000017571402513225300245650ustar00rootroot00000000000000# 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 , 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 \n" "Language-Team: Keisuke URAGO \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 "この項目は必須です" django-simple-captcha-0.5.14/captcha/locale/nl/000077500000000000000000000000001402513225300212035ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/nl/LC_MESSAGES/000077500000000000000000000000001402513225300227705ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/nl/LC_MESSAGES/django.mo000066400000000000000000000011661402513225300245730ustar00rootroot00000000000000<\pqb%!=_Invalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha 0.3.6 Report-Msgid-Bugs-To: PO-Revision-Date: 2013-02-15 13:26+0100 Last-Translator: Leon de Rijke MIME-Version: 1.0 Language-Team: Leon de Rijke Language: nl Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1) CAPTCHA ongeldig, probeer het opnieuwSpeel CAPTCHA als audiobestand afDit veld is verplicht.django-simple-captcha-0.5.14/captcha/locale/nl/LC_MESSAGES/django.po000066400000000000000000000020001402513225300245620ustar00rootroot00000000000000# django-simple-captcha Dutch translation. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Leon de Rijke , 2013. # 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: 2013-02-15 13:26+0100\n" "Last-Translator: Leon de Rijke \n" "MIME-Version: 1.0\n" "Language-Team: Leon de Rijke \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" #: fields.py:50 msgid "Play CAPTCHA as audio file" msgstr "Speel CAPTCHA als audiobestand af" #: fields.py:67 fields.py:94 tests/__init__.py:64 tests/__init__.py:186 #: tests/__init__.py:193 msgid "Invalid CAPTCHA" msgstr "CAPTCHA ongeldig, probeer het opnieuw" #: tests/__init__.py:90 msgid "This field is required." msgstr "Dit veld is verplicht." django-simple-captcha-0.5.14/captcha/locale/pl/000077500000000000000000000000001402513225300212055ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/pl/LC_MESSAGES/000077500000000000000000000000001402513225300227725ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/pl/LC_MESSAGES/django.mo000066400000000000000000000012501402513225300245670ustar00rootroot00000000000000<\pqL'iInvalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha 0.3.6 Report-Msgid-Bugs-To: PO-Revision-Date: 2013-08-18 18:52+0200 Last-Translator: Sławomir Zborowski Language-Team: Polisch Language: pl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2) Niepoprawnie wpisana CAPTCHAOdtwórz CAPTCHĘ jako plik dźwiękowyTo pole jest wymagane.django-simple-captcha-0.5.14/captcha/locale/pl/LC_MESSAGES/django.po000066400000000000000000000021231402513225300245720ustar00rootroot00000000000000# Polish translation for django-simple-captcha. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the django-simple-captcha package. # Sławomir Zborowski , 2013. # msgid "" msgstr "" "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 \n" "Language-Team: Polisch\n" "Language: pl\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%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2)\n" #: fields.py:90 msgid "Play CAPTCHA as audio file" msgstr "Odtwórz CAPTCHĘ jako plik dźwiękowy" #: fields.py:105 fields.py:134 tests/tests.py:99 tests/tests.py:239 #: tests/tests.py:246 msgid "Invalid CAPTCHA" msgstr "Niepoprawnie wpisana CAPTCHA" #: tests/tests.py:125 msgid "This field is required." msgstr "To pole jest wymagane." django-simple-captcha-0.5.14/captcha/locale/pt_BR/000077500000000000000000000000001402513225300216005ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/pt_BR/LC_MESSAGES/000077500000000000000000000000001402513225300233655ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/pt_BR/LC_MESSAGES/django.mo000066400000000000000000000011451402513225300251650ustar00rootroot00000000000000<\pqg/IInvalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha 0.3.7 Report-Msgid-Bugs-To: PO-Revision-Date: 2013-05-18 13:12-0300 Last-Translator: Alisson Patricio Language-Team: Alisson Patricio Language: pt_br MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n > 1); Resposta inválidaOuça o arquivo de áudioEste campo é obrigatório.django-simple-captcha-0.5.14/captcha/locale/pt_BR/LC_MESSAGES/django.po000066400000000000000000000020011402513225300251600ustar00rootroot00000000000000# django-simple-captcha Portuguese (Brazilian) translation. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Alisson Patricio , 2013. # msgid "" msgstr "" "Project-Id-Version: django-simple-captcha 0.3.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-05-18 10:58-0300\n" "PO-Revision-Date: 2013-05-18 13:12-0300\n" "Last-Translator: Alisson Patricio \n" "Language-Team: Alisson Patricio \n" "Language: pt_br\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:49 msgid "Play CAPTCHA as audio file" msgstr "Ouça o arquivo de áudio" #: fields.py:66 fields.py:93 tests/__init__.py:69 #: tests/__init__.py:198 tests/__init__.py:205 msgid "Invalid CAPTCHA" msgstr "Resposta inválida" #: tests/__init__.py:95 msgid "This field is required." msgstr "Este campo é obrigatório." django-simple-captcha-0.5.14/captcha/locale/ru/000077500000000000000000000000001402513225300212205ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/ru/LC_MESSAGES/000077500000000000000000000000001402513225300230055ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/ru/LC_MESSAGES/django.mo000066400000000000000000000013241402513225300246040ustar00rootroot00000000000000<\pqz/DKCInvalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha 0.3.7 Report-Msgid-Bugs-To: PO-Revision-Date: 2012-07-25 11:17+0300 Last-Translator: Language-Team: ru Language: ru MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) Неверный ответВоспроизвести CAPTCHA в виде аудио файлаЭто поле обязательно для заполнения.django-simple-captcha-0.5.14/captcha/locale/ru/LC_MESSAGES/django.po000066400000000000000000000020351402513225300246070ustar00rootroot00000000000000# 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 , YEAR. # msgid "" msgstr "" "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: 2012-07-25 11:17+0300\n" "Last-Translator: \n" "Language-Team: ru \n" "Language: ru\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:49 msgid "Play CAPTCHA as audio file" msgstr "Воспроизвести CAPTCHA в виде аудио файла" #: fields.py:66 fields.py:89 tests/__init__.py:62 msgid "Invalid CAPTCHA" msgstr "Неверный ответ" #: tests/__init__.py:88 msgid "This field is required." msgstr "Это поле обязательно для заполнения." django-simple-captcha-0.5.14/captcha/locale/sk/000077500000000000000000000000001402513225300212075ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/sk/LC_MESSAGES/000077500000000000000000000000001402513225300227745ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/sk/LC_MESSAGES/django.mo000066400000000000000000000011361402513225300245740ustar00rootroot00000000000000<\pq^!%GInvalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha 0.3.7 Report-Msgid-Bugs-To: PO-Revision-Date: 2013-10-15 17:16+0200 Last-Translator: Pavol Otto Language-Team: SK Language: sk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2; Neplatná CAPTCHAPrehrať captchu ako audio súborToto pole je povinné.django-simple-captcha-0.5.14/captcha/locale/sk/LC_MESSAGES/django.po000066400000000000000000000017421402513225300246020ustar00rootroot00000000000000# 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 , 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 \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é." django-simple-captcha-0.5.14/captcha/locale/sv/000077500000000000000000000000001402513225300212225ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/sv/LC_MESSAGES/000077500000000000000000000000001402513225300230075ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/sv/LC_MESSAGES/django.mo000066400000000000000000000011671402513225300246130ustar00rootroot00000000000000<\pqy.>XInvalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha 0.2.0 Report-Msgid-Bugs-To: PO-Revision-Date: 2018-12-03 06:41+0100 Language-Team: en MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); X-Generator: Poedit 2.2 Last-Translator: Stefan Norman Language: sv Ogiltig CAPTCHASpela CAPTCHA som ljudfilDetta fält är obligatoriskt.django-simple-captcha-0.5.14/captcha/locale/sv/LC_MESSAGES/django.po000066400000000000000000000017371402513225300246210ustar00rootroot00000000000000# django-simple-captcha Swedish translation. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Stefan Norman , 2018. # msgid "" msgstr "" "Project-Id-Version: django-simple-captcha 0.2.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-07-25 11:44+0300\n" "PO-Revision-Date: 2018-12-03 06:41+0100\n" "Language-Team: en \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 2.2\n" "Last-Translator: Stefan Norman \n" "Language: sv\n" #: fields.py:49 msgid "Play CAPTCHA as audio file" msgstr "Spela CAPTCHA som ljudfil" #: fields.py:66 fields.py:89 tests/__init__.py:62 msgid "Invalid CAPTCHA" msgstr "Ogiltig CAPTCHA" #: tests/__init__.py:88 msgid "This field is required." msgstr "Detta fält är obligatoriskt." django-simple-captcha-0.5.14/captcha/locale/tr/000077500000000000000000000000001402513225300212175ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/tr/LC_MESSAGES/000077500000000000000000000000001402513225300230045ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/tr/LC_MESSAGES/django.mo000066400000000000000000000011351402513225300246030ustar00rootroot00000000000000<\pqb (IInvalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha 0.3.6 Report-Msgid-Bugs-To: PO-Revision-Date: 2013-01-19 20:52+0200 Last-Translator: Gokmen Gorgen Language-Team: TR Gokmen Gorgen Language: tr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0 Geçersiz değerDeğeri ses dosyası olarak çalBu alan zorunludur.django-simple-captcha-0.5.14/captcha/locale/tr/LC_MESSAGES/django.po000066400000000000000000000017221402513225300246100ustar00rootroot00000000000000# 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 , YEAR. # msgid "" msgstr "" "Project-Id-Version: django-simple-captcha 0.3.6\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-01-19 16:33-0200\n" "PO-Revision-Date: 2013-01-19 20:52+0200\n" "Last-Translator: Gokmen Gorgen \n" "Language-Team: TR Gokmen Gorgen \n" "Language: tr\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:50 msgid "Play CAPTCHA as audio file" msgstr "Değeri ses dosyası olarak çal" #: fields.py:67 fields.py:94 tests/__init__.py:64 tests/__init__.py:186 #: tests/__init__.py:193 msgid "Invalid CAPTCHA" msgstr "Geçersiz değer" #: tests/__init__.py:90 msgid "This field is required." msgstr "Bu alan zorunludur." django-simple-captcha-0.5.14/captcha/locale/uk/000077500000000000000000000000001402513225300212115ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/uk/LC_MESSAGES/000077500000000000000000000000001402513225300227765ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/uk/LC_MESSAGES/django.mo000066400000000000000000000013131402513225300245730ustar00rootroot00000000000000<\pq*?6j)Invalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha 0.3.6 Report-Msgid-Bugs-To: PO-Revision-Date: 2014-02-21 22:05+0200 Last-Translator: @FuriousCoder Language-Team: uk @FuriousCoder Language: uk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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); Неправильна відповідь.Відтворити CAPTCHA як аудіо файл.Це поле є обов'язковим.django-simple-captcha-0.5.14/captcha/locale/uk/LC_MESSAGES/django.po000066400000000000000000000020721402513225300246010ustar00rootroot00000000000000# 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 , 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 "Це поле є обов'язковим." django-simple-captcha-0.5.14/captcha/locale/zh_CN/000077500000000000000000000000001402513225300215735ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/zh_CN/LC_MESSAGES/000077500000000000000000000000001402513225300233605ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/zh_CN/LC_MESSAGES/django.mo000066400000000000000000000011321402513225300251540ustar00rootroot00000000000000<\pqZ!AInvalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha 0.3.6 Report-Msgid-Bugs-To: PO-Revision-Date: 2013-03-01 05:04+0800 Last-Translator: Ming Chen Language-Team: zh_cn Ming Chen Language: zh_cn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0 认证码错误使用语音方式播放认证码这个字段是必须的django-simple-captcha-0.5.14/captcha/locale/zh_CN/LC_MESSAGES/django.po000066400000000000000000000017551402513225300251720ustar00rootroot00000000000000# django-simple-captcha Chinese Simplified translation. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Ming Chen , 2013. # 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: 2013-03-01 05:04+0800\n" "Last-Translator: Ming Chen \n" "Language-Team: zh_cn Ming Chen \n" "Language: zh_cn\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:49 msgid "Play CAPTCHA as audio file" msgstr "使用语音方式播放认证码" #: fields.py:66 fields.py:93 tests/__init__.py:69 tests/__init__.py:198 #: tests/__init__.py:205 msgid "Invalid CAPTCHA" msgstr "认证码错误" #: tests/__init__.py:95 msgid "This field is required." msgstr "这个字段是必须的" django-simple-captcha-0.5.14/captcha/locale/zh_Hans/000077500000000000000000000000001402513225300221645ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/zh_Hans/LC_MESSAGES/000077500000000000000000000000001402513225300237515ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/locale/zh_Hans/LC_MESSAGES/django.mo000066400000000000000000000011321402513225300255450ustar00rootroot00000000000000<\pqZ!AInvalid CAPTCHAPlay CAPTCHA as audio fileThis field is required.Project-Id-Version: django-simple-captcha 0.3.6 Report-Msgid-Bugs-To: PO-Revision-Date: 2013-03-01 05:04+0800 Last-Translator: Ming Chen Language-Team: zh_cn Ming Chen Language: zh_cn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0 认证码错误使用语音方式播放认证码这个字段是必须的django-simple-captcha-0.5.14/captcha/locale/zh_Hans/LC_MESSAGES/django.po000066400000000000000000000017551402513225300255630ustar00rootroot00000000000000# django-simple-captcha Chinese Simplified translation. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Ming Chen , 2013. # 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: 2013-03-01 05:04+0800\n" "Last-Translator: Ming Chen \n" "Language-Team: zh_cn Ming Chen \n" "Language: zh_cn\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:49 msgid "Play CAPTCHA as audio file" msgstr "使用语音方式播放认证码" #: fields.py:66 fields.py:93 tests/__init__.py:69 tests/__init__.py:198 #: tests/__init__.py:205 msgid "Invalid CAPTCHA" msgstr "认证码错误" #: tests/__init__.py:95 msgid "This field is required." msgstr "这个字段是必须的" django-simple-captcha-0.5.14/captcha/management/000077500000000000000000000000001402513225300214475ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/management/__init__.py000066400000000000000000000000001402513225300235460ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/management/commands/000077500000000000000000000000001402513225300232505ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/management/commands/__init__.py000066400000000000000000000000001402513225300253470ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/management/commands/captcha_clean.py000066400000000000000000000015631402513225300263740ustar00rootroot00000000000000from django.core.management.base import BaseCommand from django.utils import timezone import sys class Command(BaseCommand): help = "Clean up expired captcha hashkeys." def handle(self, **options): from captcha.models import CaptchaStore verbose = int(options.get("verbosity")) expired_keys = CaptchaStore.objects.filter( expiration__lte=timezone.now() ).count() if verbose >= 1: print("Currently %d expired hashkeys" % expired_keys) try: CaptchaStore.remove_expired() except: if verbose >= 1: print("Unable to delete expired hashkeys.") sys.exit(1) if verbose >= 1: if expired_keys > 0: print("%d expired hashkeys removed." % expired_keys) else: print("No keys to remove.") django-simple-captcha-0.5.14/captcha/management/commands/captcha_create_pool.py000066400000000000000000000021001402513225300275720ustar00rootroot00000000000000from django.core.management.base import BaseCommand from django.db import transaction from captcha.models import CaptchaStore class Command(BaseCommand): help = "Create a pool of random captchas." def add_arguments(self, parser): parser.add_argument( "--pool-size", type=int, default=1000, help="Number of new captchas to create, default=1000", ) parser.add_argument( "--cleanup-expired", action="store_true", default=True, help="Cleanup expired captchas after creating new ones", ) @transaction.atomic() def handle(self, **options): verbose = int(options.get("verbosity")) count = options.get("pool_size") CaptchaStore.create_pool(count) verbose and self.stdout.write("Created %d new captchas\n" % count) options.get("cleanup_expired") and CaptchaStore.remove_expired() options.get("cleanup_expired") and verbose and self.stdout.write( "Expired captchas cleaned up\n" ) django-simple-captcha-0.5.14/captcha/migrations/000077500000000000000000000000001402513225300215075ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/migrations/0001_initial.py000066400000000000000000000016251402513225300241560ustar00rootroot00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations class Migration(migrations.Migration): dependencies = [] 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,), ) ] django-simple-captcha-0.5.14/captcha/migrations/__init__.py000066400000000000000000000000001402513225300236060ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/models.py000066400000000000000000000056301402513225300211740ustar00rootroot00000000000000import datetime import hashlib import logging import random import time import django from django.db import models from django.utils import timezone from captcha.conf import settings as captcha_settings from six import python_2_unicode_compatible if django.VERSION >= (3, 0): from django.utils.encoding import smart_str as smart_text else: from django.utils.encoding import smart_text # Heavily based on session key generation in Django # Use the system (hardware-based) random number generator if it exists. if hasattr(random, "SystemRandom"): randrange = random.SystemRandom().randrange else: randrange = random.randrange MAX_RANDOM_KEY = 18446744073709551616 # 2 << 63 logger = logging.getLogger(__name__) @python_2_unicode_compatible class CaptchaStore(models.Model): challenge = models.CharField(blank=False, max_length=32) response = models.CharField(blank=False, max_length=32) hashkey = models.CharField(blank=False, max_length=40, unique=True) expiration = models.DateTimeField(blank=False) def save(self, *args, **kwargs): self.response = self.response.lower() if not self.expiration: self.expiration = timezone.now() + datetime.timedelta( minutes=int(captcha_settings.CAPTCHA_TIMEOUT) ) if not self.hashkey: key_ = ( smart_text(randrange(0, MAX_RANDOM_KEY)) + smart_text(time.time()) + smart_text(self.challenge, errors="ignore") + smart_text(self.response, errors="ignore") ).encode("utf8") self.hashkey = hashlib.sha1(key_).hexdigest() del key_ super(CaptchaStore, self).save(*args, **kwargs) def __str__(self): return self.challenge def remove_expired(cls): cls.objects.filter(expiration__lte=timezone.now()).delete() remove_expired = classmethod(remove_expired) @classmethod def generate_key(cls, generator=None): challenge, response = captcha_settings.get_challenge(generator)() store = cls.objects.create(challenge=challenge, response=response) return store.hashkey @classmethod def pick(cls): if not captcha_settings.CAPTCHA_GET_FROM_POOL: return cls.generate_key() def fallback(): logger.error("Couldn't get a captcha from pool, generating") return cls.generate_key() # Pick up a random item from pool minimum_expiration = timezone.now() + datetime.timedelta( minutes=int(captcha_settings.CAPTCHA_GET_FROM_POOL_TIMEOUT) ) store = ( cls.objects.filter(expiration__gt=minimum_expiration).order_by("?").first() ) return (store and store.hashkey) or fallback() @classmethod def create_pool(cls, count=1000): assert count > 0 while count > 0: cls.generate_key() count -= 1 django-simple-captcha-0.5.14/captcha/templates/000077500000000000000000000000001402513225300213315ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/templates/captcha/000077500000000000000000000000001402513225300227345ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/templates/captcha/field.html000066400000000000000000000000501402513225300247000ustar00rootroot00000000000000{{image}}{{hidden_field}}{{text_field}} django-simple-captcha-0.5.14/captcha/templates/captcha/hidden_field.html000066400000000000000000000001101402513225300262100ustar00rootroot00000000000000 django-simple-captcha-0.5.14/captcha/templates/captcha/image.html000066400000000000000000000003471402513225300247100ustar00rootroot00000000000000{% load i18n %} {% spaceless %} {% if audio %}{% endif %}captcha{% if audio %}{% endif %} {% endspaceless %}django-simple-captcha-0.5.14/captcha/templates/captcha/text_field.html000066400000000000000000000002031402513225300257440ustar00rootroot00000000000000 django-simple-captcha-0.5.14/captcha/templates/captcha/widgets/000077500000000000000000000000001402513225300244025ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/templates/captcha/widgets/captcha.html000066400000000000000000000004721402513225300266760ustar00rootroot00000000000000{% load i18n %} {% spaceless %} {% if audio %} {% endif %} captcha {% if audio %}{% endif %} {% endspaceless %} {% include "django/forms/widgets/multiwidget.html" %} django-simple-captcha-0.5.14/captcha/tests/000077500000000000000000000000001402513225300204755ustar00rootroot00000000000000django-simple-captcha-0.5.14/captcha/tests/__init__.py000066400000000000000000000000721402513225300226050ustar00rootroot00000000000000from .tests import CaptchaCase, trivial_challenge # NOQA django-simple-captcha-0.5.14/captcha/tests/tests.py000066400000000000000000000601261402513225300222160ustar00rootroot00000000000000# -*- coding: utf-8 -*- import datetime import json import os import re import unittest import warnings import django from django.core import management from django.core.exceptions import ImproperlyConfigured from django.test import TestCase, override_settings from django.utils import timezone import six from captcha.conf import settings from captcha.fields import CaptchaField, CaptchaTextInput from captcha.models import CaptchaStore from PIL import Image from six import text_type, u from testfixtures import LogCapture if django.VERSION < (1, 10): # NOQA from django.core.urlresolvers import reverse # NOQA else: # NOQA from django.urls import reverse # NOQA if django.VERSION >= (3, 0): from django.utils.translation import gettext_lazy as ugettext_lazy else: from django.utils.translation import ugettext_lazy try: from cStringIO import StringIO except ImportError: from io import BytesIO as StringIO @override_settings(ROOT_URLCONF="captcha.tests.urls") class CaptchaCase(TestCase): def setUp(self): self.stores = {} self.__current_settings_output_format = settings.CAPTCHA_OUTPUT_FORMAT self.__current_settings_dictionary = settings.CAPTCHA_WORDS_DICTIONARY self.__current_settings_punctuation = settings.CAPTCHA_PUNCTUATION tested_helpers = [ "captcha.helpers.math_challenge", "captcha.helpers.random_char_challenge", "captcha.helpers.unicode_challenge", ] if os.path.exists("/usr/share/dict/words"): settings.CAPTCHA_WORDS_DICTIONARY = "/usr/share/dict/words" settings.CAPTCHA_PUNCTUATION = ";-,." tested_helpers.append("captcha.helpers.word_challenge") tested_helpers.append("captcha.helpers.huge_words_and_punctuation_challenge") for helper in tested_helpers: challenge, response = settings._callable_from_string(helper)() ( self.stores[helper.rsplit(".", 1)[-1].replace("_challenge", "_store")], _, ) = CaptchaStore.objects.get_or_create(challenge=challenge, response=response) challenge, response = settings.get_challenge()() self.stores["default_store"], _ = CaptchaStore.objects.get_or_create( challenge=challenge, response=response ) self.default_store = self.stores["default_store"] def tearDown(self): settings.CAPTCHA_OUTPUT_FORMAT = self.__current_settings_output_format 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 return hash_, response def test_image(self): 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["content-type"], "image/png") def test_audio(self): if not settings.CAPTCHA_FLITE_PATH: return for key in ( self.stores.get("math_store").hashkey, self.stores.get("math_store").hashkey, self.default_store.hashkey, ): response = self.client.get(reverse("captcha-audio", kwargs=dict(key=key))) self.assertEqual(response.status_code, 200) self.assertTrue(response.ranged_file.size > 1024) self.assertTrue(response.has_header("content-type")) self.assertEqual(response["content-type"], "audio/wav") def test_form_submit(self): r = self.client.get(reverse("captcha-test")) self.assertEqual(r.status_code, 200) hash_, response = self.__extract_hash_and_response(r) r = self.client.post( reverse("captcha-test"), 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) r = self.client.post( reverse("captcha-test"), dict( captcha_0=hash_, captcha_1=response, subject="xxx", sender="asasd@asdasd.com", ), ) self.assertEqual(r.status_code, 200) self.assertFalse(str(r.content).find("Form validated") > 0) def test_modelform(self): r = self.client.get(reverse("captcha-test-model-form")) self.assertEqual(r.status_code, 200) hash_, response = self.__extract_hash_and_response(r) r = self.client.post( reverse("captcha-test-model-form"), 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) r = self.client.post( reverse("captcha-test-model-form"), dict( captcha_0=hash_, captcha_1=response, subject="xxx", sender="asasd@asdasd.com", ), ) self.assertEqual(r.status_code, 200) self.assertFalse(str(r.content).find("Form validated") > 0) def test_wrong_submit(self): for urlname in ("captcha-test", "captcha-test-model-form"): r = self.client.get(reverse(urlname)) self.assertEqual(r.status_code, 200) r = self.client.post( reverse(urlname), dict( captcha_0="abc", captcha_1="wrong response", subject="xxx", sender="asasd@asdasd.com", ), ) self.assertFormError(r, "form", "captcha", ugettext_lazy("Invalid CAPTCHA")) def test_deleted_expired(self): self.default_store.expiration = timezone.now() - datetime.timedelta(minutes=5) self.default_store.save() hash_ = self.default_store.hashkey r = self.client.post( reverse("captcha-test"), dict( captcha_0=hash_, captcha_1=self.default_store.response, subject="xxx", sender="asasd@asdasd.com", ), ) self.assertEqual(r.status_code, 200) self.assertFalse("Form validated" in str(r.content)) # expired -> deleted try: CaptchaStore.objects.get(hashkey=hash_) self.fail() except: pass def test_custom_error_message(self): r = self.client.get(reverse("captcha-test-custom-error-message")) self.assertEqual(r.status_code, 200) # Wrong answer r = self.client.post( reverse("captcha-test-custom-error-message"), dict(captcha_0="abc", captcha_1="wrong response"), ) self.assertFormError(r, "form", "captcha", "TEST CUSTOM ERROR MESSAGE") # empty answer r = self.client.post( reverse("captcha-test-custom-error-message"), dict(captcha_0="abc", captcha_1=""), ) self.assertFormError( r, "form", "captcha", ugettext_lazy("This field is required.") ) def test_repeated_challenge(self): CaptchaStore.objects.create(challenge="xxx", response="xxx") try: CaptchaStore.objects.create(challenge="xxx", response="xxx") except Exception: self.fail() def test_repeated_challenge_form_submit(self): __current_challange_function = settings.CAPTCHA_CHALLENGE_FUNCT for urlname in ("captcha-test", "captcha-test-model-form"): settings.CAPTCHA_CHALLENGE_FUNCT = "captcha.tests.trivial_challenge" r1 = self.client.get(reverse(urlname)) r2 = self.client.get(reverse(urlname)) self.assertEqual(r1.status_code, 200) self.assertEqual(r2.status_code, 200) if re.findall(r'value="([0-9a-f]+)"', str(r1.content)): hash_1 = re.findall(r'value="([0-9a-f]+)"', str(r1.content))[0] else: self.fail() if re.findall(r'value="([0-9a-f]+)"', str(r2.content)): hash_2 = re.findall(r'value="([0-9a-f]+)"', str(r2.content))[0] else: self.fail() try: store_1 = CaptchaStore.objects.get(hashkey=hash_1) store_2 = CaptchaStore.objects.get(hashkey=hash_2) except: self.fail() self.assertTrue(store_1.pk != store_2.pk) self.assertTrue(store_1.response == store_2.response) self.assertTrue(hash_1 != hash_2) r1 = self.client.post( reverse(urlname), dict( captcha_0=hash_1, captcha_1=store_1.response, subject="xxx", sender="asasd@asdasd.com", ), ) self.assertEqual(r1.status_code, 200) self.assertTrue(str(r1.content).find("Form validated") > 0) try: store_2 = CaptchaStore.objects.get(hashkey=hash_2) except: self.fail() r2 = self.client.post( reverse(urlname), dict( captcha_0=hash_2, captcha_1=store_2.response, subject="xxx", sender="asasd@asdasd.com", ), ) self.assertEqual(r2.status_code, 200) self.assertTrue(str(r2.content).find("Form validated") > 0) settings.CAPTCHA_CHALLENGE_FUNCT = __current_challange_function def test_output_format(self): for urlname in ("captcha-test", "captcha-test-model-form"): settings.CAPTCHA_OUTPUT_FORMAT = u( "%(image)s

Hello, captcha world

%(hidden_field)s%(text_field)s" ) r = self.client.get(reverse(urlname)) self.assertEqual(r.status_code, 200) self.assertTrue("

Hello, captcha world

" in str(r.content)) def test_invalid_output_format(self): for urlname in ("captcha-test", "captcha-test-model-form"): settings.CAPTCHA_OUTPUT_FORMAT = u("%(image)s") try: with warnings.catch_warnings(record=True) as w: self.client.get(reverse(urlname)) assert len(w) == 1 self.assertTrue("CAPTCHA_OUTPUT_FORMAT" in str(w[-1].message)) self.fail() except ImproperlyConfigured as e: self.assertTrue("CAPTCHA_OUTPUT_FORMAT" in str(e)) def test_per_form_format(self): 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 test_custom_generator(self): r = self.client.get(reverse("test_custom_generator")) hash_, response = self.__extract_hash_and_response(r) self.assertEqual(response, u"111111") def test_issue31_proper_abel(self): settings.CAPTCHA_OUTPUT_FORMAT = u("%(image)s %(hidden_field)s %(text_field)s") r = self.client.get(reverse("captcha-test")) self.assertTrue('