├── examples ├── demo │ ├── __init__.py │ ├── templates │ │ ├── django_form.html │ │ ├── library_form.html │ │ ├── custom_form.html │ │ ├── base.html │ │ └── form.html │ ├── models.py │ ├── tests.py │ ├── urls.py │ ├── forms.py │ └── views.py ├── website │ ├── __init__.py │ ├── urls.py │ ├── wsgi.py │ └── settings.py ├── requirements.txt └── manage.py ├── nocaptcha ├── client │ ├── __init__.py │ └── captcha.py └── __init__.py ├── setup.cfg ├── PKG-INFO ├── .gitignore ├── setup.py └── ez_setup.py /examples/demo/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/website/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nocaptcha/client/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==1.6.2 -------------------------------------------------------------------------------- /examples/demo/templates/django_form.html: -------------------------------------------------------------------------------- 1 | {% extends "form.html" %} -------------------------------------------------------------------------------- /nocaptcha/__init__.py: -------------------------------------------------------------------------------- 1 | __import__('pkg_resources').declare_namespace(__name__) 2 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [egg_info] 2 | tag_build = 3 | tag_date = 0 4 | tag_svn_revision = 0 5 | 6 | -------------------------------------------------------------------------------- /examples/demo/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /examples/demo/templates/library_form.html: -------------------------------------------------------------------------------- 1 | {% extends "form.html" %} 2 | 3 | 4 | {% block head %} 5 | {{ display_captcha|safe }} 6 | {{ block.super }} 7 | {% endblock %} -------------------------------------------------------------------------------- /examples/demo/templates/custom_form.html: -------------------------------------------------------------------------------- 1 | {% extends "form.html" %} 2 | 3 | 4 | {% block head %} 5 | 6 | {{ block.super }} 7 | {% endblock %} -------------------------------------------------------------------------------- /examples/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "website.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /examples/demo/tests.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file demonstrates writing tests using the unittest module. These will pass 3 | when you run "manage.py test". 4 | 5 | Replace this with more appropriate tests for your application. 6 | """ 7 | 8 | from django.test import TestCase 9 | 10 | 11 | class SimpleTest(TestCase): 12 | def test_basic_addition(self): 13 | """ 14 | Tests that 1 + 1 always equals 2. 15 | """ 16 | self.assertEqual(1 + 1, 2) 17 | -------------------------------------------------------------------------------- /examples/demo/urls.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | from django.conf.urls import patterns, url 3 | 4 | from views import IndexView 5 | from views import CustomProductionView, LibraryProductionView 6 | from views import CustomDevView, LibraryDevView 7 | 8 | 9 | urlpatterns = patterns('', 10 | url(r'^$', IndexView.as_view(), name='index'), 11 | url(r'^cp/$', CustomProductionView.as_view(), name='cp'), 12 | url(r'^cd/$', CustomDevView.as_view(), name='cd'), 13 | url(r'^lp/$', LibraryProductionView.as_view(), name='lp'), 14 | url(r'^ld/$', LibraryDevView.as_view(), name='ld'), 15 | 16 | ) 17 | -------------------------------------------------------------------------------- /examples/website/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, include, url 2 | 3 | # Uncomment the next two lines to enable the admin: 4 | # from django.contrib import admin 5 | # admin.autodiscover() 6 | 7 | urlpatterns = patterns('', 8 | # Examples: 9 | url(r'^', include('demo.urls', 'demo')), 10 | # url(r'^djcaptcha/', include('djcaptcha.foo.urls')), 11 | 12 | # Uncomment the admin/doc line below to enable admin documentation: 13 | # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), 14 | 15 | # Uncomment the next line to enable the admin: 16 | # url(r'^admin/', include(admin.site.urls)), 17 | ) 18 | -------------------------------------------------------------------------------- /PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 1.0 2 | Name: nocaptcha-client 3 | Version: 1.0.0 4 | Summary: A plugin for nocaptcha.mail.ru 5 | Home-page: http://nocaptcha.mail.ru 6 | Author: Sergey Trofimov 7 | Author-email: s.trofimov@corp.mail.ru 8 | License: MIT/X11 9 | Description: Provides a captcha for Python using the nocaptcha.mail.ru service. Does not require 10 | any imaging libraries because the nocaptcha is served directly from mail.ru. 11 | 12 | It is licensed under an MIT/X11 license. 13 | 14 | Platform: UNKNOWN 15 | Classifier: Topic :: Security 16 | Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries 17 | Classifier: Development Status :: 4 - Beta 18 | Classifier: Environment :: Web Environment 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | 6 | # Distribution / packaging 7 | env/ 8 | bin/ 9 | build/ 10 | develop-eggs/ 11 | dist/ 12 | eggs/ 13 | lib/ 14 | lib64/ 15 | parts/ 16 | sdist/ 17 | var/ 18 | *.egg-info/ 19 | .installed.cfg 20 | *.egg 21 | .coverage 22 | tests/htmlcov 23 | 24 | # Installer logs 25 | pip-log.txt 26 | pip-delete-this-directory.txt 27 | 28 | # Translations 29 | *.mo 30 | 31 | # Related to Desktops and OS 32 | .DS_Store 33 | .AppleDouble 34 | .LSOverride 35 | ._* 36 | .~ 37 | .bak 38 | *.swp 39 | *.swo 40 | *.swn 41 | 42 | # VCS and DVCS 43 | .svn 44 | 45 | # Common IDE's 46 | .idea 47 | .project 48 | .pydevproject 49 | .ropeproject 50 | 51 | # Sphinx documentation 52 | docs/_build/ 53 | 54 | # Virtualenv 55 | .env/ -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | try: 2 | from setuptools import setup, find_packages 3 | except ImportError: 4 | from ez_setup import use_setuptools 5 | use_setuptools() 6 | from setuptools import setup, find_packages 7 | 8 | setup( 9 | name='nocaptcha-client', 10 | version='1.0.0', 11 | url="http://nocaptcha.mail.ru", 12 | author="Sergey Trofimov", 13 | author_email="s.trofimov@corp.mail.ru", 14 | description="A client library for nocaptcha.mail.ru", 15 | long_description="""\ 16 | Provides a captcha for Python using the nocaptcha.mail.ru service. Does not require 17 | any imaging libraries because the nocaptcha is served directly from mail.ru. 18 | 19 | It is licensed under an MIT/X11 license. 20 | """, 21 | license="MIT/X11", 22 | classifiers=[ 23 | "Topic :: Security", 24 | "Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries", 25 | "Development Status :: 4 - Beta", 26 | "Environment :: Web Environment", 27 | ], 28 | packages=find_packages(), 29 | namespace_packages=['nocaptcha'], 30 | zip_safe=False, 31 | ) 32 | -------------------------------------------------------------------------------- /examples/demo/forms.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | from django import forms 3 | from django.conf import settings 4 | 5 | from nocaptcha.client import captcha 6 | 7 | 8 | class BaseForm(forms.Form): 9 | name = forms.CharField(label=u'Имя') 10 | email = forms.EmailField(label=u'Электронная почта') 11 | 12 | # def __init__(self, *args, **kwargs): 13 | # self.private_key = kwargs.get('private_key') 14 | # super(BaseForm, self).__init__(*args, **kwargs) 15 | 16 | def clean(self): 17 | try: 18 | captcha.check_captcha( 19 | self.private_key, 20 | self.data.get('captcha_id'), 21 | self.data.get('captcha_value'), 22 | self.is_dev, 23 | ) 24 | except captcha.CaptchaError as e: 25 | raise forms.ValidationError(e) 26 | 27 | return super(BaseForm, self).clean() 28 | 29 | 30 | class DevForm(BaseForm): 31 | private_key = settings.DEV_PRIVATE_KEY 32 | is_dev = True 33 | 34 | 35 | class ProductionForm(BaseForm): 36 | private_key = settings.PRODUCTION_PRIVATE_KEY 37 | is_dev = False -------------------------------------------------------------------------------- /examples/demo/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {% block head %} 10 | {% endblock %} 11 | 12 | 13 | {% block body %} 14 | 15 | {% if messages %} 16 | {% for x in messages %} 17 | {% if forloop.first %}

Сообщения

{% endif %} 20 | {% endfor %} 21 | {% endif %} 22 | 23 | {% if request.path != "/" %} 24 | <<< Назад 25 | {% endif %} 26 | 27 |

{% block heading %}ДЕМО{% endblock %}

28 | {% block content %} 29 | 35 | {% endblock %} 36 | 37 | {% endblock %} 38 | 39 | -------------------------------------------------------------------------------- /examples/website/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for djcaptcha project. 3 | 4 | This module contains the WSGI application used by Django's development server 5 | and any production WSGI deployments. It should expose a module-level variable 6 | named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover 7 | this application via the ``WSGI_APPLICATION`` setting. 8 | 9 | Usually you will have the standard Django WSGI application here, but it also 10 | might make sense to replace the whole Django WSGI application with a custom one 11 | that later delegates to the Django one. For example, you could introduce WSGI 12 | middleware here, or combine a Django application with an application of another 13 | framework. 14 | 15 | """ 16 | import os 17 | 18 | # We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks 19 | # if running multiple sites in the same mod_wsgi process. To fix this, use 20 | # mod_wsgi daemon mode with each site in its own daemon process, or use 21 | # os.environ["DJANGO_SETTINGS_MODULE"] = "djcaptcha.settings" 22 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djcaptcha.settings") 23 | 24 | # This application object is used by any WSGI server configured to use this 25 | # file. This includes Django's development server, if the WSGI_APPLICATION 26 | # setting points here. 27 | from django.core.wsgi import get_wsgi_application 28 | application = get_wsgi_application() 29 | 30 | # Apply WSGI middleware here. 31 | # from helloworld.wsgi import HelloWorldApplication 32 | # application = HelloWorldApplication(application) 33 | -------------------------------------------------------------------------------- /examples/demo/templates/form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block head %} 4 | {% if is_dev %} 5 | 10 | {% else %} 11 | 16 | {% endif %} 17 | 18 | 30 | {% endblock %} 31 | 32 | {% block heading %} 33 | {{ heading }} 34 | {% endblock %} 35 | 36 | 37 | {% block content %} 38 |

Сервер: {{ server_url }}

39 |

Публичный ключ: {{ public_key }}

40 |

Приватный ключ: {{ private_key }}

41 |

Клиентский скрипт: false

42 |

Событие nocaptcha: -

43 | {% if is_dev %} 44 |

45 | Войти/выйти 46 |

47 | {% endif %} 48 | 49 | {% block form %} 50 |
51 |
52 | Форма 53 | {{ form.media }} 54 | {% csrf_token %} 55 | {{ form.as_p }} 56 |
57 | 58 |
59 |
60 | {% endblock %} 61 | 62 | {% endblock %} -------------------------------------------------------------------------------- /nocaptcha/client/captcha.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import json 3 | import urllib 4 | import logging 5 | 6 | 7 | API_SERVER = 'https://api-nocaptcha.mail.ru' 8 | 9 | 10 | class CaptchaError(Exception): 11 | pass 12 | 13 | 14 | def check_captcha(private_key, captcha_id, captcha_value, **kwargs): 15 | """ 16 | Returns True if captcha is valid 17 | Or raise CaptchaError exception with description 18 | """ 19 | result, error = None, None 20 | params = urllib.urlencode({ 21 | 'private_key': private_key, 22 | 'captcha_id': captcha_id, 23 | 'captcha_value': isinstance(captcha_value, unicode) and captcha_value.encode('utf-8') or captcha_value, 24 | }) 25 | 26 | try: 27 | url = '{api_server}/check?{params}'.format( 28 | api_server=kwargs.get('api_server', API_SERVER), 29 | params=params 30 | ) 31 | logging.debug(url) 32 | 33 | result = urllib.urlopen(url) 34 | result = result.read() 35 | logging.debug(result) 36 | 37 | result = json.loads(result) 38 | 39 | if result['status'] != 'ok': 40 | error = result.get('desc', 'Bad response') 41 | elif not result['is_correct']: 42 | error = 'Bad captcha' 43 | except IOError: 44 | error = 'Server unavailable' 45 | except ValueError: 46 | error = 'Bad response' 47 | 48 | if error: 49 | raise CaptchaError(error) 50 | 51 | return True 52 | 53 | 54 | def source_captcha(public_key, **kwargs): 55 | """ 56 | Return url of source script to display captcha 57 | public_key - The public api key 58 | """ 59 | return '{api_server}/captcha?public_key={public_key}'.format( 60 | api_server=kwargs.get('api_server', API_SERVER), 61 | public_key=public_key, 62 | ) 63 | 64 | 65 | def display_captcha(public_key, **kwargs): 66 | """ 67 | Return HTML code to display captcha 68 | public_key - The public api key 69 | """ 70 | 71 | return ''.format( 72 | url=source_captcha(public_key, **kwargs), 73 | ) 74 | -------------------------------------------------------------------------------- /examples/demo/views.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | from django.contrib import messages 3 | from django.http import HttpResponseRedirect 4 | from django.views.generic import FormView, TemplateView 5 | from django.conf import settings 6 | 7 | from nocaptcha.client import captcha 8 | from forms import DevForm, ProductionForm 9 | 10 | 11 | class IndexView(TemplateView): 12 | template_name = 'base.html' 13 | 14 | 15 | class CaptchaView(FormView): 16 | template_name = 'form.html' 17 | 18 | # def get_context_data(self, **kwargs): 19 | # return { 20 | # 21 | # } 22 | 23 | def form_invalid(self, form): 24 | messages.error(self.request, u'Форма заполнена неправильно, ниже будут пояснения') 25 | return super(CaptchaView, self).form_invalid(form) 26 | 27 | def form_valid(self, form): 28 | messages.info(self.request, u'С капчей всё ок и тут мы отсылаем сообщение для пользователя «{name}» с почтой «{email}»'.format( 29 | **form.cleaned_data 30 | )) 31 | 32 | return HttpResponseRedirect('/') 33 | 34 | 35 | class CustomProductionView(CaptchaView): 36 | template_name = 'custom_form.html' 37 | form_class = ProductionForm 38 | 39 | def get_context_data(self, **kwargs): 40 | kwargs['heading'] = u'Без библиотеки через боевой сервер' 41 | kwargs['public_key'] = settings.PRODUCTION_PUBLIC_KEY 42 | kwargs['private_key'] = settings.PRODUCTION_PRIVATE_KEY 43 | kwargs['server_url'] = settings.PRODUCTION_SERVER 44 | print settings.TEMPLATE_DEBUG 45 | return kwargs 46 | 47 | 48 | class CustomDevView(CaptchaView): 49 | template_name = 'custom_form.html' 50 | form_class = DevForm 51 | 52 | def get_context_data(self, **kwargs): 53 | kwargs['is_dev'] = True 54 | kwargs['heading'] = u'Без библиотеки через девелоперский сервер' 55 | kwargs['public_key'] = settings.DEV_PUBLIC_KEY 56 | kwargs['private_key'] = settings.DEV_PRIVATE_KEY 57 | kwargs['server_url'] = settings.DEV_SERVER 58 | return kwargs 59 | 60 | 61 | class LibraryProductionView(CaptchaView): 62 | template_name = 'library_form.html' 63 | form_class = ProductionForm 64 | 65 | def get_context_data(self, **kwargs): 66 | kwargs['heading'] = u'С библиотекой через боевой сервер' 67 | kwargs['public_key'] = settings.PRODUCTION_PUBLIC_KEY 68 | kwargs['private_key'] = settings.PRODUCTION_PRIVATE_KEY 69 | kwargs['server_url'] = settings.PRODUCTION_SERVER 70 | kwargs['display_captcha'] = captcha.display_captcha(settings.PRODUCTION_PUBLIC_KEY) 71 | return kwargs 72 | 73 | 74 | class LibraryDevView(CaptchaView): 75 | template_name = 'library_form.html' 76 | form_class = DevForm 77 | 78 | def get_context_data(self, **kwargs): 79 | kwargs['is_dev'] = True 80 | kwargs['heading'] = u'С библиотекой через девелоперский сервер' 81 | kwargs['public_key'] = settings.DEV_PUBLIC_KEY 82 | kwargs['private_key'] = settings.DEV_PRIVATE_KEY 83 | kwargs['server_url'] = settings.DEV_SERVER 84 | kwargs['display_captcha'] = captcha.display_captcha(settings.DEV_PUBLIC_KEY, api_server=settings.DEV_SERVER) 85 | return kwargs 86 | 87 | 88 | class DjangoProductionView(CaptchaView): 89 | template_name = 'django_form.html' 90 | form_class = ProductionForm 91 | 92 | def get_context_data(self, **kwargs): 93 | kwargs['heading'] = u'С библиотекой через боевой сервер' 94 | kwargs['public_key'] = settings.PRODUCTION_PUBLIC_KEY 95 | kwargs['private_key'] = settings.PRODUCTION_PRIVATE_KEY 96 | kwargs['server_url'] = settings.PRODUCTION_SERVER 97 | kwargs['display_captcha'] = captcha.display_captcha(settings.PRODUCTION_PUBLIC_KEY) 98 | return kwargs 99 | 100 | 101 | class DjangoDevView(CaptchaView): 102 | template_name = 'django_form.html' 103 | form_class = DevForm 104 | 105 | def get_context_data(self, **kwargs): 106 | kwargs['is_dev'] = True 107 | kwargs['heading'] = u'С библиотекой через девелоперский сервер' 108 | kwargs['public_key'] = settings.DEV_PUBLIC_KEY 109 | kwargs['private_key'] = settings.DEV_PRIVATE_KEY 110 | kwargs['server_url'] = settings.DEV_SERVER 111 | kwargs['display_captcha'] = captcha.display_captcha(settings.DEV_PUBLIC_KEY, is_dev=True) 112 | return kwargs 113 | -------------------------------------------------------------------------------- /examples/website/settings.py: -------------------------------------------------------------------------------- 1 | import django.conf.global_settings as DEFAULT_SETTINGS 2 | 3 | 4 | DEBUG = True 5 | TEMPLATE_DEBUG = DEBUG 6 | 7 | ADMINS = ( 8 | # ('Your Name', 'your_email@example.com'), 9 | ) 10 | 11 | MANAGERS = ADMINS 12 | 13 | DATABASES = { 14 | 'default': { 15 | 'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. 16 | 'NAME': '', # Or path to database file if using sqlite3. 17 | # The following settings are not used with sqlite3: 18 | 'USER': '', 19 | 'PASSWORD': '', 20 | 'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP. 21 | 'PORT': '', # Set to empty string for default. 22 | } 23 | } 24 | # Hosts/domain names that are valid for this site; required if DEBUG is False 25 | # See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts 26 | ALLOWED_HOSTS = [] 27 | 28 | # Local time zone for this installation. Choices can be found here: 29 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 30 | # although not all choices may be available on all operating systems. 31 | # In a Windows environment this must be set to your system time zone. 32 | TIME_ZONE = 'America/Chicago' 33 | 34 | # Language code for this installation. All choices can be found here: 35 | # http://www.i18nguy.com/unicode/language-identifiers.html 36 | LANGUAGE_CODE = 'ru-ru' 37 | 38 | SITE_ID = 1 39 | 40 | # If you set this to False, Django will make some optimizations so as not 41 | # to load the internationalization machinery. 42 | USE_I18N = True 43 | 44 | # If you set this to False, Django will not format dates, numbers and 45 | # calendars according to the current locale. 46 | USE_L10N = True 47 | 48 | # If you set this to False, Django will not use timezone-aware datetimes. 49 | USE_TZ = True 50 | 51 | # Absolute filesystem path to the directory that will hold user-uploaded files. 52 | # Example: "/var/www/example.com/media/" 53 | MEDIA_ROOT = '../media/' 54 | 55 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a 56 | # trailing slash. 57 | # Examples: "http://example.com/media/", "http://media.example.com/" 58 | MEDIA_URL = '/media/' 59 | 60 | # Absolute path to the directory static files should be collected to. 61 | # Don't put anything in this directory yourself; store your static files 62 | # in apps' "static/" subdirectories and in STATICFILES_DIRS. 63 | # Example: "/var/www/example.com/static/" 64 | STATIC_ROOT = '../static/' 65 | 66 | # URL prefix for static files. 67 | # Example: "http://example.com/static/", "http://static.example.com/" 68 | STATIC_URL = '/static/' 69 | 70 | # Additional locations of static files 71 | STATICFILES_DIRS = ( 72 | # Put strings here, like "/home/html/static" or "C:/www/django/static". 73 | # Always use forward slashes, even on Windows. 74 | # Don't forget to use absolute paths, not relative paths. 75 | ) 76 | 77 | # List of finder classes that know how to find static files in 78 | # various locations. 79 | STATICFILES_FINDERS = ( 80 | 'django.contrib.staticfiles.finders.FileSystemFinder', 81 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 82 | # 'django.contrib.staticfiles.finders.DefaultStorageFinder', 83 | ) 84 | 85 | # Make this unique, and don't share it with anybody. 86 | SECRET_KEY = 'gvw%afph-s8(o)_ynxaal6n1)c-u+yofrjc24p)fb(p*fw32i2' 87 | 88 | # List of callables that know how to import templates from various sources. 89 | TEMPLATE_LOADERS = ( 90 | 'django.template.loaders.filesystem.Loader', 91 | 'django.template.loaders.app_directories.Loader', 92 | # 'django.template.loaders.eggs.Loader', 93 | ) 94 | 95 | MIDDLEWARE_CLASSES = ( 96 | 'django.middleware.common.CommonMiddleware', 97 | 'django.contrib.sessions.middleware.SessionMiddleware', 98 | 'django.middleware.csrf.CsrfViewMiddleware', 99 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 100 | 'django.contrib.messages.middleware.MessageMiddleware', 101 | # Uncomment the next line for simple clickjacking protection: 102 | # 'django.middleware.clickjacking.XFrameOptionsMiddleware', 103 | ) 104 | 105 | TEMPLATE_CONTEXT_PROCESSORS = DEFAULT_SETTINGS.TEMPLATE_CONTEXT_PROCESSORS + ( 106 | 'django.core.context_processors.request', 107 | ) 108 | 109 | ROOT_URLCONF = 'website.urls' 110 | 111 | # Python dotted path to the WSGI application used by Django's runserver. 112 | WSGI_APPLICATION = 'website.wsgi.application' 113 | 114 | TEMPLATE_DIRS = ( 115 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". 116 | # Always use forward slashes, even on Windows. 117 | # Don't forget to use absolute paths, not relative paths. 118 | ) 119 | 120 | INSTALLED_APPS = ( 121 | 'django.contrib.auth', 122 | 'django.contrib.contenttypes', 123 | 'django.contrib.sessions', 124 | 'django.contrib.sites', 125 | 'django.contrib.messages', 126 | 'django.contrib.staticfiles', 127 | # Uncomment the next line to enable the admin: 128 | # 'django.contrib.admin', 129 | # Uncomment the next line to enable admin documentation: 130 | # 'django.contrib.admindocs', 131 | 132 | 'demo', 133 | ) 134 | 135 | SESSION_SERIALIZER = 'django.contrib.sessions.serializers.JSONSerializer' 136 | 137 | # A sample logging configuration. The only tangible logging 138 | # performed by this configuration is to send an email to 139 | # the site admins on every HTTP 500 error when DEBUG=False. 140 | # See http://docs.djangoproject.com/en/dev/topics/logging for 141 | # more details on how to customize your logging configuration. 142 | LOGGING = { 143 | 'version': 1, 144 | 'disable_existing_loggers': False, 145 | 'filters': { 146 | 'require_debug_false': { 147 | '()': 'django.utils.log.RequireDebugFalse' 148 | } 149 | }, 150 | 'handlers': { 151 | 'mail_admins': { 152 | 'level': 'ERROR', 153 | 'filters': ['require_debug_false'], 154 | 'class': 'django.utils.log.AdminEmailHandler' 155 | } 156 | }, 157 | 'loggers': { 158 | 'django.request': { 159 | 'handlers': ['mail_admins'], 160 | 'level': 'ERROR', 161 | 'propagate': True, 162 | }, 163 | } 164 | } 165 | 166 | 167 | ### NOCAPTCHA ### 168 | PRODUCTION_SERVER = 'https://api-nocaptcha.mail.ru' 169 | DEV_SERVER = 'https://mp.dev.mail.ru' 170 | 171 | # localsite.loc 172 | DEV_PUBLIC_KEY = '03da35d17f5c84229be219c5a2f89488' 173 | DEV_PRIVATE_KEY = '0bbd376c828f245b4a8ae88f5929ffb5' 174 | 175 | PRODUCTION_PUBLIC_KEY = '8dd9f759e0bf146a9a13206df6feadfe' 176 | PRODUCTION_PRIVATE_KEY = 'dca7c260125df4b6ab29b25811cb32bc' 177 | ### NOCAPTCHA ### -------------------------------------------------------------------------------- /ez_setup.py: -------------------------------------------------------------------------------- 1 | #!python 2 | """Bootstrap setuptools installation 3 | 4 | If you want to use setuptools in your package's setup.py, just include this 5 | file in the same directory with it, and add this to the top of your setup.py:: 6 | 7 | from ez_setup import use_setuptools 8 | use_setuptools() 9 | 10 | If you want to require a specific version of setuptools, set a download 11 | mirror, or use an alternate download directory, you can do so by supplying 12 | the appropriate options to ``use_setuptools()``. 13 | 14 | This file can also be run as a script to install or upgrade setuptools. 15 | """ 16 | import sys 17 | DEFAULT_VERSION = "0.6c11" 18 | DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3] 19 | 20 | md5_data = { 21 | 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca', 22 | 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb', 23 | 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b', 24 | 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a', 25 | 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618', 26 | 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac', 27 | 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5', 28 | 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', 29 | 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', 30 | 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', 31 | 'setuptools-0.6c10-py2.3.egg': 'ce1e2ab5d3a0256456d9fc13800a7090', 32 | 'setuptools-0.6c10-py2.4.egg': '57d6d9d6e9b80772c59a53a8433a5dd4', 33 | 'setuptools-0.6c10-py2.5.egg': 'de46ac8b1c97c895572e5e8596aeb8c7', 34 | 'setuptools-0.6c10-py2.6.egg': '58ea40aef06da02ce641495523a0b7f5', 35 | 'setuptools-0.6c11-py2.3.egg': '2baeac6e13d414a9d28e7ba5b5a596de', 36 | 'setuptools-0.6c11-py2.4.egg': 'bd639f9b0eac4c42497034dec2ec0c2b', 37 | 'setuptools-0.6c11-py2.5.egg': '64c94f3bf7a72a13ec83e0b24f2749b2', 38 | 'setuptools-0.6c11-py2.6.egg': 'bfa92100bd772d5a213eedd356d64086', 39 | 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', 40 | 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', 41 | 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', 42 | 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e', 43 | 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e', 44 | 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f', 45 | 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2', 46 | 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc', 47 | 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167', 48 | 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64', 49 | 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d', 50 | 'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20', 51 | 'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab', 52 | 'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53', 53 | 'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2', 54 | 'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e', 55 | 'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372', 56 | 'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902', 57 | 'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de', 58 | 'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b', 59 | 'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03', 60 | 'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a', 61 | 'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6', 62 | 'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a', 63 | } 64 | 65 | import sys, os 66 | try: from hashlib import md5 67 | except ImportError: from md5 import md5 68 | 69 | def _validate_md5(egg_name, data): 70 | if egg_name in md5_data: 71 | digest = md5(data).hexdigest() 72 | if digest != md5_data[egg_name]: 73 | print >>sys.stderr, ( 74 | "md5 validation of %s failed! (Possible download problem?)" 75 | % egg_name 76 | ) 77 | sys.exit(2) 78 | return data 79 | 80 | def use_setuptools( 81 | version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, 82 | download_delay=15 83 | ): 84 | """Automatically find/download setuptools and make it available on sys.path 85 | 86 | `version` should be a valid setuptools version number that is available 87 | as an egg for download under the `download_base` URL (which should end with 88 | a '/'). `to_dir` is the directory where setuptools will be downloaded, if 89 | it is not already available. If `download_delay` is specified, it should 90 | be the number of seconds that will be paused before initiating a download, 91 | should one be required. If an older version of setuptools is installed, 92 | this routine will print a message to ``sys.stderr`` and raise SystemExit in 93 | an attempt to abort the calling script. 94 | """ 95 | was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules 96 | def do_download(): 97 | egg = download_setuptools(version, download_base, to_dir, download_delay) 98 | sys.path.insert(0, egg) 99 | import setuptools; setuptools.bootstrap_install_from = egg 100 | try: 101 | import pkg_resources 102 | except ImportError: 103 | return do_download() 104 | try: 105 | pkg_resources.require("setuptools>="+version); return 106 | except pkg_resources.VersionConflict, e: 107 | if was_imported: 108 | print >>sys.stderr, ( 109 | "The required version of setuptools (>=%s) is not available, and\n" 110 | "can't be installed while this script is running. Please install\n" 111 | " a more recent version first, using 'easy_install -U setuptools'." 112 | "\n\n(Currently using %r)" 113 | ) % (version, e.args[0]) 114 | sys.exit(2) 115 | else: 116 | del pkg_resources, sys.modules['pkg_resources'] # reload ok 117 | return do_download() 118 | except pkg_resources.DistributionNotFound: 119 | return do_download() 120 | 121 | def download_setuptools( 122 | version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, 123 | delay = 15 124 | ): 125 | """Download setuptools from a specified location and return its filename 126 | 127 | `version` should be a valid setuptools version number that is available 128 | as an egg for download under the `download_base` URL (which should end 129 | with a '/'). `to_dir` is the directory where the egg will be downloaded. 130 | `delay` is the number of seconds to pause before an actual download attempt. 131 | """ 132 | import urllib2, shutil 133 | egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) 134 | url = download_base + egg_name 135 | saveto = os.path.join(to_dir, egg_name) 136 | src = dst = None 137 | if not os.path.exists(saveto): # Avoid repeated downloads 138 | try: 139 | from distutils import log 140 | if delay: 141 | log.warn(""" 142 | --------------------------------------------------------------------------- 143 | This script requires setuptools version %s to run (even to display 144 | help). I will attempt to download it for you (from 145 | %s), but 146 | you may need to enable firewall access for this script first. 147 | I will start the download in %d seconds. 148 | 149 | (Note: if this machine does not have network access, please obtain the file 150 | 151 | %s 152 | 153 | and place it in this directory before rerunning this script.) 154 | ---------------------------------------------------------------------------""", 155 | version, download_base, delay, url 156 | ); from time import sleep; sleep(delay) 157 | log.warn("Downloading %s", url) 158 | src = urllib2.urlopen(url) 159 | # Read/write all in one block, so we don't create a corrupt file 160 | # if the download is interrupted. 161 | data = _validate_md5(egg_name, src.read()) 162 | dst = open(saveto,"wb"); dst.write(data) 163 | finally: 164 | if src: src.close() 165 | if dst: dst.close() 166 | return os.path.realpath(saveto) 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | def main(argv, version=DEFAULT_VERSION): 204 | """Install or upgrade setuptools and EasyInstall""" 205 | try: 206 | import setuptools 207 | except ImportError: 208 | egg = None 209 | try: 210 | egg = download_setuptools(version, delay=0) 211 | sys.path.insert(0,egg) 212 | from setuptools.command.easy_install import main 213 | return main(list(argv)+[egg]) # we're done here 214 | finally: 215 | if egg and os.path.exists(egg): 216 | os.unlink(egg) 217 | else: 218 | if setuptools.__version__ == '0.0.1': 219 | print >>sys.stderr, ( 220 | "You have an obsolete version of setuptools installed. Please\n" 221 | "remove it from your system entirely before rerunning this script." 222 | ) 223 | sys.exit(2) 224 | 225 | req = "setuptools>="+version 226 | import pkg_resources 227 | try: 228 | pkg_resources.require(req) 229 | except pkg_resources.VersionConflict: 230 | try: 231 | from setuptools.command.easy_install import main 232 | except ImportError: 233 | from easy_install import main 234 | main(list(argv)+[download_setuptools(delay=0)]) 235 | sys.exit(0) # try to force an exit 236 | else: 237 | if argv: 238 | from setuptools.command.easy_install import main 239 | main(argv) 240 | else: 241 | print "Setuptools version",version,"or greater has been installed." 242 | print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' 243 | 244 | def update_md5(filenames): 245 | """Update our built-in md5 registry""" 246 | 247 | import re 248 | 249 | for name in filenames: 250 | base = os.path.basename(name) 251 | f = open(name,'rb') 252 | md5_data[base] = md5(f.read()).hexdigest() 253 | f.close() 254 | 255 | data = [" %r: %r,\n" % it for it in md5_data.items()] 256 | data.sort() 257 | repl = "".join(data) 258 | 259 | import inspect 260 | srcfile = inspect.getsourcefile(sys.modules[__name__]) 261 | f = open(srcfile, 'rb'); src = f.read(); f.close() 262 | 263 | match = re.search("\nmd5_data = {\n([^}]+)}", src) 264 | if not match: 265 | print >>sys.stderr, "Internal error!" 266 | sys.exit(2) 267 | 268 | src = src[:match.start(1)] + repl + src[match.end(1):] 269 | f = open(srcfile,'w') 270 | f.write(src) 271 | f.close() 272 | 273 | 274 | if __name__=='__main__': 275 | if len(sys.argv)>2 and sys.argv[1]=='--md5update': 276 | update_md5(sys.argv[2:]) 277 | else: 278 | main(sys.argv[1:]) 279 | 280 | 281 | 282 | 283 | 284 | 285 | --------------------------------------------------------------------------------