├── DEVELOPERS.md
├── README.md
├── ispdb
├── TODO
├── __init__.py
├── apache
│ ├── __init__.py
│ ├── ispdb.wsgi
│ ├── production.py
│ ├── staging.py
│ ├── trunk.py
│ └── wsgi.conf
├── audit.py
├── config
│ ├── __init__.py
│ ├── admin.py
│ ├── configChecks.py
│ ├── forms.py
│ ├── models.py
│ ├── serializers.py
│ ├── static
│ │ ├── css
│ │ │ ├── base.css
│ │ │ ├── comments.css
│ │ │ ├── details.css
│ │ │ ├── enter_config.css
│ │ │ ├── ispdb.css
│ │ │ └── show_issue.css
│ │ ├── img
│ │ │ ├── ajax-loading.gif
│ │ │ ├── error-icon.png
│ │ │ ├── nav-bg-grabber.gif
│ │ │ ├── nav-bg-reverse.gif
│ │ │ ├── nav-bg.gif
│ │ │ ├── sign_in_blue.png
│ │ │ ├── thunderbird.png
│ │ │ └── warning-icon.png
│ │ └── js
│ │ │ ├── jquery-1.7.2.min.js
│ │ │ └── jquery.validate.min.js
│ ├── templatetags
│ │ ├── __init__.py
│ │ └── custom_filters.py
│ └── views.py
├── convert.py
├── fixtures
│ ├── domain_testdata.json
│ ├── issue_testdata.json
│ ├── login_testdata.json
│ ├── sanity.json
│ └── xml_testdata.json
├── middleware
│ ├── __init__.py
│ └── x_ssl.py
├── settings.py
├── templates
│ ├── 404.html
│ ├── 500.html
│ └── config
│ │ ├── base.html
│ │ ├── details.html
│ │ ├── enter_config.html
│ │ ├── export.xml
│ │ ├── intro.html
│ │ ├── list.html
│ │ ├── login.html
│ │ ├── queue.html
│ │ ├── show_issue.html
│ │ └── urls
│ │ ├── desc_form.html
│ │ ├── desc_list.html
│ │ ├── desc_template_form.html
│ │ ├── url_form.html
│ │ ├── url_list.html
│ │ └── url_template_form.html
├── tests
│ ├── __init__.py
│ ├── common.py
│ ├── relaxng_schema.1.1.xml
│ ├── relaxng_schema.xml
│ ├── test_add.py
│ ├── test_approve.py
│ ├── test_cache.py
│ ├── test_delete.py
│ ├── test_edit.py
│ ├── test_issue.py
│ ├── test_sanity.py
│ ├── test_view.py
│ └── test_xml.py
└── urls.py
├── manage.py
├── requirements.txt
└── tools
├── MozAutoConfig.pm
├── convert.py
├── etld.py
└── quickparse.py
/DEVELOPERS.md:
--------------------------------------------------------------------------------
1 | # ISPDB
2 |
3 | ISPDB is a Django front-end to figure out workflow of ISP database info for the
4 | Thunderbird autoconfig database.
5 |
6 | This file contains useful informations to help developers.
7 |
8 | ## Documentation
9 |
10 | ### Models
11 |
12 | ISPDB has the following models: Domain, DomainRequest, Config, Issue, DocURL,
13 | DocURLDesc, EnableURL, EnableURLInst.
14 |
15 | Both Domain and DomainRequest represent a mail domain. The difference is that
16 | DomainRequest is not approved yet. It means that users can vote on it and their
17 | name attribute is not unique (we can have more than one DomainRequest with the
18 | same name). A Config holds the domain configuration. It can be related to more
19 | than one domain. It has zero or more documentation pages (DocURL) and zero or
20 | more enable pages (EnableURL). A DocURL has one or more descriptions
21 | (DocURLDesc) and a EnableURL has one or more instructions (EnableURLInst).
22 | Because those 4 classes are very similar, we have created common model and form
23 | classes.
24 |
25 | The Issue model represents a reported issue. It is related to the configuration
26 | and optionally to an user suggested configuration.
27 |
28 | ### Forms
29 |
30 | The complexity of the forms is in the form's classes. For example, ConfigForm
31 | class has domain_formset, docurl_formset and enableurl_formset attributes. So we
32 | can do things like the save_all method which save all of the forms (Domain,
33 | Config, DocURL, EnableURL), simplifying the views.
34 |
35 | Also there are two nested forms (for DocURL and EnableURL models). So each
36 | DocURLForm has a DocURLDesc formset and each EnableURLForm has a EnableURLInst
37 | formset.
38 |
39 | It is possible to add new forms dynamically in all of the formsets. There are
40 | two form classes to help with this task: DynamicModelForm and
41 | DynamicBaseModelFormSet. Basically they add a DELETE hidden boolean field and a
42 | overriden empty_form attribute (see below).
43 |
44 | #### Dynamic Forms
45 |
46 | enter_config.html template has hidden textarea elements which contains empty
47 | forms. These empty forms have on their attributes JQuery Validation tags, in our
48 | case "{1}-{0}" string, which are replaced with a form prefix and a index.
49 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This repository is no longer active, current ISPDB is available at: https://github.com/thundernest/autoconfig
2 |
3 | experimental django front-end to figure out workflow of ISP database info
4 | for the Thunderbird autoconfig database
5 |
6 | ## Dependencies
7 |
8 | You can install all of the dependencies with:
9 |
10 | pip install -r requirements.txt
11 |
12 | Note: You may have to do an "easy_install pip" first. See requirements.txt for details on what we depend on.
13 |
14 | ## Getting Started
15 | 1. python ../manage.py syncdb
16 | 2. convert existing XML data to the DB:
17 |
18 | have http://svn.mozilla.org/mozillamessaging.com/sites/autoconfig.mozillamessaging.com/trunk checked out at ../autoconfig_data
19 |
20 | if autoconfig_data is somewhere else, you can set the env't var AUTOCONFIG_DATA to point to it
21 |
22 | echo 'import ispdb.convert;ispdb.convert.main()' | python manage.py shell
23 |
24 | 3. python manage.py runserver
25 | 4. then hit http://localhost:8000
26 |
--------------------------------------------------------------------------------
/ispdb/TODO:
--------------------------------------------------------------------------------
1 | Work:
2 |
3 | P1
4 | * new config entry
5 | * validation: domain already in the DB? config wrong?
6 | * correct models (e.g. authentication types, etc.)
7 | * language list for popup
8 | * remove buttons for +1 and -1
9 | * command line script to export XML files w/ some sane convention
10 | * in review process, allow choice when marking invalid
11 | - "not available from our domain"
12 | - "incorrect data"
13 | - "other"
14 | (in addition to textfield)
15 |
16 | P2
17 | * allow reviewer-only comments: not visible to non reviewers
18 | * review process: have backend script to do telnet/ssh call to the ports,
19 | detect IMAP settinsgs, etc.
20 | * annotate results of backend script to the configuration
21 | * think about how to indicate when a record is out of date, the new record is in the db, but the old one is still being published (link to actual http:// data)
22 | * settings page language detection?
23 | * allow addition of domains to existing configurations
24 |
25 | Quality:
26 | * test convert -> export compare w/ original data
27 | * test suite
28 |
29 | Prettier:vi
30 | * CSS: make comment form prettier
31 | * django/ajax: fix comment submission (ajax baby!)
32 |
--------------------------------------------------------------------------------
/ispdb/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla/ispdb/3b87b2c797d0d56cdf5343cca831af721360ca53/ispdb/__init__.py
--------------------------------------------------------------------------------
/ispdb/apache/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla/ispdb/3b87b2c797d0d56cdf5343cca831af721360ca53/ispdb/apache/__init__.py
--------------------------------------------------------------------------------
/ispdb/apache/ispdb.wsgi:
--------------------------------------------------------------------------------
1 | import os, sys
2 |
3 | #Calculate the path based on the location of the WSGI script.
4 | apache_configuration= os.path.dirname(__file__)
5 | project = os.path.dirname(apache_configuration)
6 | workspace = os.path.dirname(project)
7 | sys.path.append(workspace)
8 |
9 | print >> sys.stderr, "Path is %s" % sys.path
10 |
11 | #Add the path to 3rd party django application and to django itself.
12 | #sys.path.append('C:\\yml\\_myScript_\\dj_things\\web_development\\svn_views\\django_src\\trunk')
13 | #sys.path.append('C:\\yml\\_myScript_\\dj_things\\web_development\\svn_views\\django-registration')
14 |
15 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ispdb.apache.production")
16 |
17 | # This application object is used by any WSGI server configured to use this
18 | # file. This includes Django's development server, if the WSGI_APPLICATION
19 | # setting points here.
20 | from django.core.wsgi import get_wsgi_application
21 | application = get_wsgi_application()
22 |
--------------------------------------------------------------------------------
/ispdb/apache/production.py:
--------------------------------------------------------------------------------
1 | # Django settings for ispdb project.
2 |
3 | #Calculate the path based on the location of the WSGI script.
4 | import os
5 | apache_configuration = os.path.dirname(__file__)
6 | project = os.path.dirname(apache_configuration)
7 | workspace = os.path.dirname(project)
8 |
9 | DEBUG = False
10 | TEMPLATE_DEBUG = DEBUG
11 |
12 | ADMINS = (
13 | # ('Your Name', 'your_email@domain.com'),
14 | )
15 |
16 | MANAGERS = ADMINS
17 |
18 | DATABASES = {
19 | 'default': {
20 | 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
21 | 'NAME': 'production_ispdb', # Or path to database file if using sqlite3.
22 | 'USER': 'prod_ispdb', # Not used with sqlite3.
23 | 'PASSWORD': '', # Not used with sqlite3.
24 | 'HOST': 'db-write', # Set to empty string for localhost. Not used with sqlite3.
25 | 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
26 | 'PORT': '', # Set to empty string for default. Not used with sqlite3.
27 | }
28 | }
29 |
30 | # Local time zone for this installation. Choices can be found here:
31 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
32 | # although not all choices may be available on all operating systems.
33 | # If running in a Windows environment this must be set to the same as your
34 | # system time zone.
35 | TIME_ZONE = 'America/Chicago'
36 |
37 | # Language code for this installation. All choices can be found here:
38 | # http://www.i18nguy.com/unicode/language-identifiers.html
39 | LANGUAGE_CODE = 'en-us'
40 |
41 | SITE_ID = 1
42 |
43 | # If you set this to False, Django will make some optimizations so as not
44 | # to load the internationalization machinery.
45 | USE_I18N = False
46 |
47 | # If you set this to False, Django will not format dates, numbers and
48 | # calendars according to the current locale
49 | USE_L10N = True
50 |
51 | # If you set this to False, Django will not use timezone-aware datetimes.
52 | USE_TZ = True
53 |
54 | # Absolute filesystem path to the directory that will hold user-uploaded files.
55 | # Example: "/home/media/media.lawrence.com/media/"
56 | MEDIA_ROOT = '/var/www/ispdb/ispdb/media/'
57 |
58 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a
59 | # trailing slash.
60 | # Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
61 | MEDIA_URL = '/media/'
62 |
63 | # Absolute path to the directory static files should be collected to.
64 | # Don't put anything in this directory yourself; store your static files
65 | # in apps' "static/" subdirectories and in STATICFILES_DIRS.
66 | # Example: "/home/media/media.lawrence.com/static/"
67 | STATIC_ROOT = '/var/www/ispdb/ispdb/static/'
68 |
69 | # URL prefix for static files.
70 | # Example: "http://media.lawrence.com/static/"
71 | STATIC_URL = '/static/'
72 |
73 | # Additional locations of static files
74 | STATICFILES_DIRS = (
75 | # Put strings here, like "/home/html/static" or "C:/www/django/static".
76 | # Always use forward slashes, even on Windows.
77 | # Don't forget to use absolute paths, not relative paths.
78 | )
79 |
80 | # List of finder classes that know how to find static files in
81 | # various locations.
82 | STATICFILES_FINDERS = (
83 | 'django.contrib.staticfiles.finders.FileSystemFinder',
84 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
85 | # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
86 | )
87 |
88 | # Make this unique, and don't share it with anybody.
89 | SECRET_KEY = '02$7gj$t@dtd7um)d#3zlfg7ommedl#*ekt@@*ysy_fns(lp9+'
90 |
91 | # List of callables that know how to import templates from various sources.
92 | TEMPLATE_LOADERS = (
93 | 'django.template.loaders.filesystem.Loader',
94 | 'django.template.loaders.app_directories.Loader',
95 | )
96 |
97 | MIDDLEWARE_CLASSES = (
98 | 'django.middleware.common.CommonMiddleware',
99 | 'django.contrib.sessions.middleware.SessionMiddleware',
100 | 'django.middleware.csrf.CsrfViewMiddleware',
101 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
102 | 'django.contrib.messages.middleware.MessageMiddleware',
103 | # Uncomment the next line for simple clickjacking protection:
104 | # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
105 | # 'ispdb.middleware.x_ssl',
106 | )
107 |
108 | ROOT_URLCONF = 'ispdb.urls'
109 |
110 | TEMPLATE_DIRS = (
111 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
112 | # Always use forward slashes, even on Windows.
113 | # Don't forget to use absolute paths, not relative paths.
114 | "%s/templates" % project,
115 | )
116 |
117 | INSTALLED_APPS = (
118 | 'django.contrib.auth',
119 | 'django.contrib.contenttypes',
120 | 'django.contrib.sessions',
121 | 'django.contrib.sites',
122 | 'django.contrib.admin',
123 | 'django.contrib.comments',
124 | 'django.contrib.staticfiles',
125 | 'django_openid_auth',
126 | 'ispdb.config'
127 | )
128 |
129 | AUTHENTICATION_BACKENDS = (
130 | 'django_openid_auth.auth.OpenIDBackend',
131 | 'django.contrib.auth.backends.ModelBackend',
132 | )
133 |
134 | OPENID_CREATE_USERS = True
135 |
136 | OPENID_UPDATE_DETAILS_FROM_SREG = True
137 |
138 | LOGIN_URL = '/openid/login'
139 | LOGIN_REDIRECT_URL = '/'
140 | DOCS_ROOT="/Users/davida/src/django/docs/"
141 |
142 | ROOT = '/'
143 |
--------------------------------------------------------------------------------
/ispdb/apache/staging.py:
--------------------------------------------------------------------------------
1 | # Django settings for ispdb project.
2 |
3 | #Calculate the path based on the location of the WSGI script.
4 | import os
5 | apache_configuration = os.path.dirname(__file__)
6 | project = os.path.dirname(apache_configuration)
7 | workspace = os.path.dirname(project)
8 |
9 | DEBUG = True
10 | TEMPLATE_DEBUG = DEBUG
11 |
12 | ADMINS = (
13 | # ('Your Name', 'your_email@domain.com'),
14 | )
15 |
16 | MANAGERS = ADMINS
17 |
18 | DATABASE_ENGINE = 'mysql' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
19 | #DATABASE_NAME = "%s/ispdb.sqlite" % project
20 | DATABASE_NAME = 'stage_ispdb'
21 | DATABASE_USER = 'ispdb_user' # Not used with sqlite3.
22 | DATABASE_PASSWORD = '' # Not used with sqlite3.
23 | DATABASE_HOST = 'db-write' # Set to empty string for localhost. Not used with sqlite3.
24 | DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
25 |
26 | # Local time zone for this installation. Choices can be found here:
27 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
28 | # although not all choices may be available on all operating systems.
29 | # If running in a Windows environment this must be set to the same as your
30 | # system time zone.
31 | TIME_ZONE = 'America/Chicago'
32 |
33 | # Language code for this installation. All choices can be found here:
34 | # http://www.i18nguy.com/unicode/language-identifiers.html
35 | LANGUAGE_CODE = 'en-us'
36 |
37 | SITE_ID = 1
38 |
39 | # If you set this to False, Django will make some optimizations so as not
40 | # to load the internationalization machinery.
41 | USE_I18N = True
42 |
43 | # Absolute path to the directory that holds media.
44 | # Example: "/home/media/media.lawrence.com/"
45 | MEDIA_ROOT = '/var/www/ispdb/media'
46 |
47 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a
48 | # trailing slash if there is a path component (optional in other cases).
49 | # Examples: "http://media.lawrence.com", "http://example.com/media/"
50 | MEDIA_URL = '/media/'
51 |
52 | # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
53 | # trailing slash.
54 | # Examples: "http://foo.com/media/", "/media/".
55 | ADMIN_MEDIA_PREFIX = '/admin_media/'
56 |
57 | # Make this unique, and don't share it with anybody.
58 | SECRET_KEY = '02$7gj$t@dtd7um)d#3zlfg7ommedl#*ekt@@*ysy_fns(lp9+'
59 |
60 | # List of callables that know how to import templates from various sources.
61 | TEMPLATE_LOADERS = (
62 | 'django.template.loaders.filesystem.load_template_source',
63 | 'django.template.loaders.app_directories.load_template_source',
64 | # 'django.template.loaders.eggs.load_template_source',
65 | )
66 |
67 | MIDDLEWARE_CLASSES = (
68 | 'django.middleware.common.CommonMiddleware',
69 | 'django.contrib.sessions.middleware.SessionMiddleware',
70 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
71 | # 'ispdb.middleware.x_ssl',
72 | )
73 |
74 | ROOT_URLCONF = 'ispdb.urls'
75 |
76 | TEMPLATE_DIRS = (
77 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
78 | # Always use forward slashes, even on Windows.
79 | # Don't forget to use absolute paths, not relative paths.
80 | "%s/templates" % project,
81 | )
82 |
83 | INSTALLED_APPS = (
84 | 'django.contrib.auth',
85 | 'django.contrib.contenttypes',
86 | 'django.contrib.sessions',
87 | 'django.contrib.sites',
88 | 'django.contrib.admin',
89 | 'django.contrib.comments',
90 | 'django_openid_auth',
91 | 'ispdb.config'
92 | )
93 |
94 | AUTHENTICATION_BACKENDS = (
95 | 'django_openid_auth.auth.OpenIDBackend',
96 | 'django.contrib.auth.backends.ModelBackend',
97 | )
98 |
99 | OPENID_CREATE_USERS = True
100 |
101 | OPENID_UPDATE_DETAILS_FROM_SREG = True
102 |
103 | LOGIN_URL = '/openid/login'
104 | LOGIN_REDIRECT_URL = '/'
105 | DOCS_ROOT="/Users/davida/src/django/docs/"
106 | LOCAL_DEVELOPMENT = True
107 | USE_I18N = False
108 |
109 | ROOT = '/'
110 |
--------------------------------------------------------------------------------
/ispdb/apache/trunk.py:
--------------------------------------------------------------------------------
1 | # Django settings for ispdb project.
2 |
3 | #Calculate the path based on the location of the WSGI script.
4 | import os
5 | apache_configuration = os.path.dirname(__file__)
6 | project = os.path.dirname(apache_configuration)
7 | workspace = os.path.dirname(project)
8 |
9 | DEBUG = True
10 | TEMPLATE_DEBUG = DEBUG
11 |
12 | ADMINS = (
13 | # ('Your Name', 'your_email@domain.com'),
14 | )
15 |
16 | MANAGERS = ADMINS
17 |
18 | DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
19 | #DATABASE_NAME = "%s/ispdb.sqlite" % project
20 | DATABASE_NAME = '/var/ispdb/trunk/ispdb.sqlite'
21 | DATABASE_USER = '' # Not used with sqlite3.
22 | DATABASE_PASSWORD = '' # Not used with sqlite3.
23 | DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
24 | DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
25 |
26 | # Local time zone for this installation. Choices can be found here:
27 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
28 | # although not all choices may be available on all operating systems.
29 | # If running in a Windows environment this must be set to the same as your
30 | # system time zone.
31 | TIME_ZONE = 'America/Chicago'
32 |
33 | # Language code for this installation. All choices can be found here:
34 | # http://www.i18nguy.com/unicode/language-identifiers.html
35 | LANGUAGE_CODE = 'en-us'
36 |
37 | SITE_ID = 1
38 |
39 | # If you set this to False, Django will make some optimizations so as not
40 | # to load the internationalization machinery.
41 | USE_I18N = True
42 |
43 | # Absolute path to the directory that holds media.
44 | # Example: "/home/media/media.lawrence.com/"
45 | MEDIA_ROOT = '/var/www/ispdb/media'
46 |
47 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a
48 | # trailing slash if there is a path component (optional in other cases).
49 | # Examples: "http://media.lawrence.com", "http://example.com/media/"
50 | MEDIA_URL = '/media/'
51 |
52 | # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
53 | # trailing slash.
54 | # Examples: "http://foo.com/media/", "/media/".
55 | ADMIN_MEDIA_PREFIX = '/admin_media/'
56 |
57 | # Make this unique, and don't share it with anybody.
58 | SECRET_KEY = '02$7gj$t@dtd7um)d#3zlfg7ommedl#*ekt@@*ysy_fns(lp9+'
59 |
60 | # List of callables that know how to import templates from various sources.
61 | TEMPLATE_LOADERS = (
62 | 'django.template.loaders.filesystem.load_template_source',
63 | 'django.template.loaders.app_directories.load_template_source',
64 | # 'django.template.loaders.eggs.load_template_source',
65 | )
66 |
67 | MIDDLEWARE_CLASSES = (
68 | 'django.middleware.common.CommonMiddleware',
69 | 'django.contrib.sessions.middleware.SessionMiddleware',
70 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
71 | # 'ispdb.middleware.x_ssl',
72 | )
73 |
74 | ROOT_URLCONF = 'ispdb.urls'
75 |
76 | TEMPLATE_DIRS = (
77 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
78 | # Always use forward slashes, even on Windows.
79 | # Don't forget to use absolute paths, not relative paths.
80 | "%s/templates" % project,
81 | )
82 |
83 | INSTALLED_APPS = (
84 | 'django.contrib.auth',
85 | 'django.contrib.contenttypes',
86 | 'django.contrib.sessions',
87 | 'django.contrib.sites',
88 | 'django.contrib.admin',
89 | 'django.contrib.comments',
90 | 'django_openid_auth',
91 | 'ispdb.config'
92 | )
93 |
94 | AUTHENTICATION_BACKENDS = (
95 | 'django_openid_auth.auth.OpenIDBackend',
96 | 'django.contrib.auth.backends.ModelBackend',
97 | )
98 |
99 | OPENID_CREATE_USERS = True
100 |
101 | OPENID_UPDATE_DETAILS_FROM_SREG = True
102 |
103 | LOGIN_URL = '/openid/login'
104 | LOGIN_REDIRECT_URL = '/'
105 | DOCS_ROOT="/Users/davida/src/django/docs/"
106 | LOCAL_DEVELOPMENT = True
107 | USE_I18N = False
108 |
109 | ROOT = '/'
110 |
--------------------------------------------------------------------------------
/ispdb/apache/wsgi.conf:
--------------------------------------------------------------------------------
1 | Alias /media/ "/var/www/ispdb/media/"
2 | Alias /static/ "/var/www/ispdb/static/"
3 | The requested URL {{ request.path|escape }} was not found on this
9 | server. I'm sorry, that page is currently unavailable due to a server
9 | misconfiguration. The server administrator has been notified, and we apologise for any
12 | inconvenience. {{ error|linebreaks }} This configuration is APPROVED. Is there a reason it shouldn't be?
127 | This configuration has been determined INVALID. We've looked at the
128 | data, and either it's not correct, or it can't be verified from outside
129 | the ISP's firewall, or the ISP has asked not to publish it.
130 | Is there a reason it shouldn't be? This configuration has been DELETED. Can you confirm that this is a good configuration according to our policies? This configuration is PENDING REVIEW. Our team of crack volunteers will review
193 | it, and assuming the data checks out, we'll publish it.
'.join(str(c) for c in obj.domains.all())
33 | else:
34 | return '
'.join(str(c) for c in obj.domainrequests.all())
35 | list_domains.allow_tags = True
36 |
37 | admin.site.register(Config, ConfigAdmin)
38 |
--------------------------------------------------------------------------------
/ispdb/config/models.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from django.conf import settings
4 | from django.contrib.auth.models import User
5 | from django.db import models
6 |
7 | import ispdb.audit as audit
8 |
9 |
10 | class Domain(models.Model):
11 | name = models.CharField(max_length=100, unique=True,
12 | verbose_name="Email domain",
13 | help_text="(e.g. \"gmail.com\")")
14 | config = models.ForeignKey('Config', related_name="domains",
15 | blank=True) # blank is for requests and rejects
16 |
17 | @staticmethod
18 | def create_from_domainrequest(domainrequest):
19 | """create domain from domainrequest
20 | """
21 | d = Domain()
22 | d.name = domainrequest.name
23 | d.config = domainrequest.config
24 | return d
25 |
26 | def __str__(self):
27 | return str(self.name)
28 |
29 | def __unicode__(self):
30 | return self.name
31 |
32 |
33 | class DomainRequest(models.Model):
34 | name = models.CharField(max_length=100, verbose_name="Email domain",
35 | help_text="(e.g. \"gmail.com\")")
36 | config = models.ForeignKey('Config', related_name="domainrequests",
37 | blank=True, null=True)
38 | votes = models.IntegerField(default=1)
39 |
40 | def __str__(self):
41 | return str(self.name)
42 |
43 | def __unicode__(self):
44 | return self.name
45 |
46 |
47 | class Config(models.Model):
48 | """
49 | A Config object contains all of the metadata about a configuration.
50 | It is 1-many mapped to Domain objects which apply to it.
51 |
52 | """
53 |
54 | class Meta:
55 | permissions = (
56 | ('can_approve', 'Can approve configurations'),
57 | )
58 |
59 | def __str__(self):
60 | "for use in the admin UI"
61 | return str(self.display_name)
62 |
63 | def __unicode__(self):
64 | return self.display_name
65 |
66 | owner = models.ForeignKey(User, unique=False, blank=True, null=True,
67 | on_delete=models.SET_NULL)
68 | last_update_datetime = models.DateTimeField(auto_now=True)
69 | created_datetime = models.DateTimeField(auto_now_add=True)
70 | deleted_datetime = models.DateTimeField(null=True, blank=True)
71 | CONFIG_CHOICES = [
72 | ("requested", "requested"),
73 | ("suggested", "suggested"),
74 | ("approved", "approved"),
75 | ("invalid", "invalid"),
76 | ("deleted", "deleted"),
77 | ]
78 | status = models.CharField(max_length=20, choices=CONFIG_CHOICES)
79 | last_status = models.CharField(max_length=20, choices=CONFIG_CHOICES,
80 | blank=True)
81 | email_provider_id = models.CharField(max_length=50, blank=True)
82 | display_name = models.CharField(
83 | max_length=100,
84 | verbose_name="The name of this ISP",
85 | help_text="e.g. \"Google's Gmail Service\"")
86 | display_short_name = models.CharField(
87 | max_length=100,
88 | verbose_name="A short version of the ISP name",
89 | help_text="e.g. \"Gmail\"")
90 | INCOMING_TYPE_CHOICES = (
91 | ('imap', 'IMAP'),
92 | ('pop3', 'POP'),
93 | )
94 | incoming_type = models.CharField(max_length=100,
95 | choices=INCOMING_TYPE_CHOICES)
96 | incoming_hostname = models.CharField(max_length=100)
97 | incoming_port = models.PositiveIntegerField()
98 | INCOMING_SOCKET_TYPE_CHOICES = (
99 | ("plain", "No encryption"),
100 | ("SSL", "SSL/TLS"),
101 | ("STARTTLS", "STARTTLS"),
102 | )
103 | incoming_socket_type = models.CharField(
104 | max_length=8,
105 | choices=INCOMING_SOCKET_TYPE_CHOICES)
106 | incoming_username_form = models.CharField(max_length=100,
107 | verbose_name="Username formula")
108 | INCOMING_AUTHENTICATION_CHOICES = (
109 | ("password-cleartext", "Unencrypted Password"),
110 | ("password-encrypted", "Encrypted Password"),
111 | ("NTLM", "NTLM"),
112 | ("GSSAPI", "GSSAPI"),
113 | )
114 | incoming_authentication = models.CharField(
115 | max_length=20,
116 | choices=INCOMING_AUTHENTICATION_CHOICES,
117 | default="password-encrypted",
118 | help_text="""Unencrypted Password: Send password
119 | unencrypted in the clear. Dangerous, if SSL isn't used
120 | either. PLAIN or LOGIN etc…
121 |
122 | Encrypted Password: Hashed password.
123 | Offers minimal protection for passwords. CRAM-MD5 or
124 | DIGEST-MD5. Not NTLM.
"""
125 | )
126 | outgoing_hostname = models.CharField(max_length=100)
127 | outgoing_port = models.PositiveIntegerField()
128 | OUTGOING_SOCKET_TYPE_CHOICES = (
129 | ("plain", "No encryption"),
130 | ("SSL", "SSL/TLS"),
131 | ("STARTTLS", "STARTTLS"),
132 | )
133 | outgoing_socket_type = models.CharField(
134 | max_length=8,
135 | choices=OUTGOING_SOCKET_TYPE_CHOICES)
136 | outgoing_username_form = models.CharField(max_length=100,
137 | verbose_name="Username formula")
138 | OUTGOING_AUTHENTICATION_CHOICES = (
139 | ("password-cleartext", "Unencrypted Password"),
140 | ("password-encrypted", "Encrypted Password"),
141 | ("none", "Client IP address"),
142 | ("smtp-after-pop", "SMTP-after-POP"),
143 | ("NTLM", "NTLM"),
144 | ("GSSAPI", "GSSAPI"),
145 | )
146 | outgoing_authentication = models.CharField(
147 | max_length=20,
148 | choices=OUTGOING_AUTHENTICATION_CHOICES,
149 | default="password-encrypted",
150 | help_text="""Unencrypted Password: Send password
151 | unencrypted in the clear. Dangerous, if SSL isn't used
152 | either. PLAIN or LOGIN etc…
153 |
154 | Encrypted Password: Hashed password.
155 | Offers minimal protection for passwords. CRAM-MD5 or
156 | DIGEST-MD5. Not NTLM.
"""
157 | )
158 | outgoing_add_this_server = models.BooleanField(
159 | verbose_name="Add this server to list???")
160 | outgoing_use_global_preferred_server = models.BooleanField(
161 | verbose_name="Use global server instead")
162 |
163 | locked = models.BooleanField()
164 |
165 | history = audit.AuditTrail()
166 |
167 |
168 | class Issue(models.Model):
169 | title = models.CharField(max_length=50)
170 | description = models.TextField(max_length=3000)
171 | created_datetime = models.DateTimeField(auto_now_add=True)
172 | config = models.ForeignKey(Config, related_name="reported_issues")
173 | updated_config = models.ForeignKey(Config, null=True, related_name="issue")
174 | owner = models.ForeignKey(User, unique=False, blank=True, null=True,
175 | on_delete=models.SET_NULL)
176 | STATUS_CHOICES = [
177 | ("open", "open"),
178 | ("closed", "closed"),
179 | ]
180 | status = models.CharField(max_length=20, choices=STATUS_CHOICES,
181 | default="open")
182 |
183 |
184 | class CommonConfigURL(models.Model):
185 | url = models.URLField(
186 | verbose_name="URL of the page")
187 | config = models.ForeignKey(Config, related_name="%(class)s_set")
188 |
189 | class Meta:
190 | abstract = True
191 |
192 | def __str__(self):
193 | return str(self.url)
194 |
195 | def __unicode__(self):
196 | return self.url
197 |
198 |
199 | class CommonURLDesc(models.Model):
200 | description = models.TextField(
201 | max_length=100,
202 | verbose_name="Description")
203 | language = models.CharField(
204 | max_length=10,
205 | verbose_name="Language",
206 | choices=settings.LANGUAGES)
207 |
208 | class Meta:
209 | abstract = True
210 |
211 | def __str__(self):
212 | return str(self.description)
213 |
214 | def __unicode__(self):
215 | return self.description
216 |
217 |
218 | class DocURL(CommonConfigURL):
219 | pass
220 | DocURL._meta.get_field('url').verbose_name = ("URL of the page describing "
221 | "these settings")
222 |
223 |
224 | class DocURLDesc(CommonURLDesc):
225 | docurl = models.ForeignKey(DocURL, related_name="descriptions")
226 | DocURLDesc._meta.get_field('description').verbose_name = ('Description of the '
227 | 'settings page')
228 |
229 |
230 | class EnableURL(CommonConfigURL):
231 | pass
232 | EnableURL._meta.get_field('url').verbose_name = ("URL of the page with enable "
233 | "instructions")
234 |
235 |
236 | class EnableURLInst(CommonURLDesc):
237 | enableurl = models.ForeignKey(EnableURL, related_name="instructions")
238 | EnableURLInst._meta.get_field('description').verbose_name = ('Instruction')
239 |
--------------------------------------------------------------------------------
/ispdb/config/serializers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import lxml.etree as ET
4 | from StringIO import StringIO
5 |
6 | from ispdb.config.models import Domain, DomainRequest
7 |
8 | # The serializers in reverse order, newest at the top.
9 |
10 |
11 | def xmlOneDotOne(data):
12 | """
13 | Return the configuration using the XML document that Thunderbird is
14 | expecting.
15 | """
16 | desiredOutput = {
17 | "display_name": "displayName",
18 | "display_short_name": "displayShortName",
19 | "incoming_hostname": "hostname",
20 | "incoming_port": "port",
21 | "incoming_socket_type": "socketType",
22 | "incoming_username_form": "username",
23 | "incoming_authentication": "authentication",
24 | "outgoing_hostname": "hostname",
25 | "outgoing_port": "port",
26 | "outgoing_socket_type": "socketType",
27 | "outgoing_username_form": "username",
28 | "outgoing_authentication": "authentication",
29 | }
30 | incoming = None
31 | outgoing = None
32 | config = ET.Element("clientConfig")
33 | config.attrib["version"] = "1.1"
34 | emailProvider = ET.SubElement(config, "emailProvider")
35 | qs = Domain.objects.filter(config=data) or (
36 | DomainRequest.objects.filter(config=data))
37 | for domain in qs:
38 | if not data.email_provider_id:
39 | data.email_provider_id = domain.name
40 | ET.SubElement(emailProvider, "domain").text = domain.name
41 | emailProvider.attrib["id"] = data.email_provider_id
42 | for field in data._meta.fields:
43 | if field.name not in desiredOutput:
44 | continue
45 | if field.name.startswith("incoming"):
46 | if incoming is None:
47 | incoming = ET.SubElement(emailProvider, "incomingServer")
48 | incoming.attrib["type"] = data.incoming_type
49 | name = field.name
50 | currParent = incoming
51 | elif field.name.startswith("outgoing"):
52 | if outgoing is None:
53 | outgoing = ET.SubElement(emailProvider, "outgoingServer")
54 | outgoing.attrib["type"] = "smtp"
55 | name = field.name
56 | currParent = outgoing
57 | else:
58 | name = field.name
59 | currParent = emailProvider
60 | if (name == "incoming_username_form") and (
61 | data.incoming_username_form == ""):
62 | data.incoming_username_form = data.outgoing_username_form
63 | name = desiredOutput[name]
64 | e = ET.SubElement(currParent, name)
65 | text = getattr(data, field.name)
66 |
67 | if type(text) is bool:
68 | # Force boolean values to use lowercase.
69 | text = unicode(text).lower()
70 | else:
71 | # Force other values to be converted into unicode strings.
72 | text = unicode(text)
73 | e.text = text
74 | # EnableURL
75 | for enableurl in data.enableurl_set.all():
76 | enable = ET.SubElement(emailProvider, "enable")
77 | enable.attrib["visiturl"] = enableurl.url
78 | for inst in enableurl.instructions.all():
79 | d = ET.SubElement(enable, "instruction")
80 | d.attrib["lang"] = inst.language
81 | d.text = unicode(inst.description)
82 | # DocURL
83 | for docurl in data.docurl_set.all():
84 | doc = ET.SubElement(emailProvider, "documentation")
85 | doc.attrib["url"] = docurl.url
86 | for desc in docurl.descriptions.all():
87 | d = ET.SubElement(doc, "descr")
88 | d.attrib["lang"] = desc.language
89 | d.text = unicode(desc.description)
90 |
91 | retval = StringIO("w")
92 | xml = ET.ElementTree(config)
93 | xml.write(retval, encoding="UTF-8", xml_declaration=True)
94 | return retval.getvalue()
95 |
96 |
97 | def xmlOneDotZero(data):
98 | """
99 | Return the configuration using the XML document that Thunderbird is
100 | expecting.
101 | """
102 | desiredOutput = {
103 | "display_name": "displayName",
104 | "display_short_name": "displayShortName",
105 | "incoming_hostname": "hostname",
106 | "incoming_port": "port",
107 | "incoming_socket_type": "socketType",
108 | "incoming_username_form": "username",
109 | "incoming_authentication": "authentication",
110 | "outgoing_hostname": "hostname",
111 | "outgoing_port": "port",
112 | "outgoing_socket_type": "socketType",
113 | "outgoing_username_form": "username",
114 | "outgoing_authentication": "authentication",
115 | "outgoing_add_this_server": "addThisServer",
116 | "outgoing_use_global_preferred_server": "useGlobalPreferredServer",
117 | }
118 | authentication_values = {
119 | "password-cleartext": "plain",
120 | "password-encrypted": "secure",
121 | "client-ip-address": "none",
122 | "smtp-after-pop": "none",
123 | }
124 | incoming = None
125 | outgoing = None
126 | config = ET.Element("clientConfig")
127 | config.attrib["version"] = "1.0"
128 | emailProvider = ET.SubElement(config, "emailProvider")
129 | for domain in Domain.objects.filter(config=data):
130 | ET.SubElement(emailProvider, "domain").text = domain.name
131 | if not data.email_provider_id:
132 | data.email_provider_id = domain.name
133 | emailProvider.attrib["id"] = data.email_provider_id
134 | for field in data._meta.fields:
135 | if field.name not in desiredOutput:
136 | continue
137 | if field.name.startswith("incoming"):
138 | if incoming is None:
139 | incoming = ET.SubElement(emailProvider, "incomingServer")
140 | incoming.attrib["type"] = data.incoming_type
141 | name = field.name
142 | currParent = incoming
143 | elif field.name.startswith("outgoing"):
144 | if outgoing is None:
145 | outgoing = ET.SubElement(emailProvider, "outgoingServer")
146 | outgoing.attrib["type"] = "smtp"
147 | name = field.name
148 | currParent = outgoing
149 | else:
150 | name = field.name
151 | currParent = emailProvider
152 | if (name == "incoming_username_form") and (
153 | data.incoming_username_form == ""):
154 | data.incoming_username_form = data.outgoing_username_form
155 | name = desiredOutput[name]
156 | e = ET.SubElement(currParent, name)
157 | text = getattr(data, field.name)
158 |
159 | if type(text) is bool:
160 | # Force boolean values to use lowercase.
161 | text = unicode(text).lower()
162 | else:
163 | # Force other values to be converted into unicode strings.
164 | text = unicode(text)
165 |
166 | # Fix up the data to make it 1.0 compliant.
167 | if name == "authentication":
168 | text = authentication_values.get(text, text)
169 |
170 | e.text = text
171 |
172 | retval = StringIO("w")
173 | xml = ET.ElementTree(config)
174 | xml.write(retval, encoding="UTF-8", xml_declaration=True)
175 | return retval.getvalue()
176 |
177 | # This is the data format version, not the application version.
178 | # It only needs to change when the data format needs to change in a way
179 | # that breaks old clients, which are hopefully exceptional cases.
180 | # In other words, this does *not* change with every TB major release.
181 | _serializers = {
182 | "1.0": xmlOneDotZero,
183 | "1.1": xmlOneDotOne,
184 | }
185 |
186 |
187 | def get(version):
188 | # If there is no version requested, return the most recent version.
189 | if version is None:
190 | return xmlOneDotZero
191 | return _serializers.get(version, None)
192 |
--------------------------------------------------------------------------------
/ispdb/config/static/css/base.css:
--------------------------------------------------------------------------------
1 | body { margin:0; padding:0; font-size:12px; font-family:"Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif; color:#333; background:#fff; }
2 |
3 | /* LINKS */
4 | a:link, a:visited { color: #5b80b2; text-decoration:none; }
5 | a:hover { color: #036; }
6 | a img { border:none; }
7 | a.section:link, a.section:visited { color: white; text-decoration:none; }
8 |
9 | /* GLOBAL DEFAULTS */
10 | p, ol, ul, dl { margin:.2em 0 .8em 0; }
11 | p { padding:0; line-height:140%; }
12 |
13 | h1,h2,h3,h4,h5 { font-weight:bold; }
14 | h1 { font-size:18px; color:#666; padding:0 6px 0 0; margin:0 0 .2em 0; }
15 | h2 { font-size:16px; margin:1em 0 .5em 0; }
16 | h2.subhead { font-weight:normal;margin-top:0; }
17 | h3 { font-size:14px; margin:.8em 0 .3em 0; color:#666; font-weight:bold; }
18 | h4 { font-size:12px; margin:1em 0 .8em 0; padding-bottom:3px; }
19 | h5 { font-size:10px; margin:1.5em 0 .5em 0; color:#666; text-transform:uppercase; letter-spacing:1px; }
20 |
21 | ul li { list-style-type:square; padding:1px 0; }
22 | ul.plainlist { margin-left:0 !important; }
23 | ul.plainlist li { list-style-type:none; }
24 | li ul { margin-bottom:0; }
25 | li, dt, dd { font-size:11px; line-height:14px; }
26 | dt { font-weight:bold; margin-top:4px; }
27 | dd { margin-left:0; }
28 |
29 | form { margin:0; padding:0; }
30 | fieldset { margin:0; padding:0; }
31 |
32 | blockquote { font-size:11px; color:#777; margin-left:2px; padding-left:10px; border-left:5px solid #ddd; }
33 | code, pre { font-family:"Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace; background:inherit; color:#666; font-size:11px; }
34 | pre.literal-block { margin:10px; background:#eee; padding:6px 8px; }
35 | code strong { color:#930; }
36 | hr { clear:both; color:#eee; background-color:#eee; height:1px; border:none; margin:0; padding:0; font-size:1px; line-height:1px; }
37 |
38 | /* TEXT STYLES & MODIFIERS */
39 | .small { font-size:11px; }
40 | .tiny { font-size:10px; }
41 | p.tiny { margin-top:-2px; }
42 | .mini { font-size:9px; }
43 | p.mini { margin-top:-3px; }
44 | .help, p.help { font-size:10px !important; color:#999; }
45 | p img, h1 img, h2 img, h3 img, h4 img, td img { vertical-align:middle; }
46 | .quiet, a.quiet:link, a.quiet:visited { color:#999 !important;font-weight:normal !important; }
47 | .quiet strong { font-weight:bold !important; }
48 | .float-right { float:right; }
49 | .float-left { float:left; }
50 | .clear { clear:both; }
51 | .align-left { text-align:left; }
52 | .align-right { text-align:right; }
53 | .example { margin:10px 0; padding:5px 10px; background:#efefef; }
54 | .nowrap { white-space:nowrap; }
55 |
56 | /* TABLES */
57 | table { border-collapse:collapse; border-color:#ccc; }
58 | td, th { font-size:11px; line-height:13px; border-bottom:1px solid #eee; vertical-align:top; padding:5px; font-family:"Lucida Grande", Verdana, Arial, sans-serif; }
59 | th { text-align:left; font-size:12px; font-weight:bold; }
60 | thead th,
61 | tfoot td { color:#666; padding:2px 5px; font-size:11px; background:#e1e1e1 url(../img/nav-bg.gif) top left repeat-x; border-left:1px solid #ddd; border-bottom:1px solid #ddd; }
62 | tfoot td { border-bottom:none; border-top:1px solid #ddd; }
63 | thead th:first-child,
64 | tfoot td:first-child { border-left:none !important; }
65 | thead th.optional { font-weight:normal !important; }
66 | fieldset table { border-right:1px solid #eee; }
67 | tr.row-label td { font-size:9px; padding-top:2px; padding-bottom:0; border-bottom:none; color:#666; margin-top:-1px; }
68 | tr.alt { background:#f6f6f6; }
69 | .row1 { background:#EDF3FE; }
70 | .row2 { background:white; }
71 |
72 | /* FORM DEFAULTS */
73 | input, textarea, select { margin:2px 0; padding:2px 3px; vertical-align:middle; font-family:"Lucida Grande", Verdana, Arial, sans-serif; font-weight:normal; font-size:11px; }
74 | textarea { vertical-align:top !important; }
75 | input[type=text], input[type=password], textarea, select, .vTextField { border:1px solid #ccc; }
76 |
77 | /* FORM BUTTONS */
78 | .button, input[type=submit], input[type=button], .submit-row input { background:white url(../img/nav-bg.gif) bottom repeat-x; padding:3px; color:black; border:1px solid #bbb; border-color:#ddd #aaa #aaa #ddd; }
79 | .button:active, input[type=submit]:active, input[type=button]:active { background-image:url(../img/nav-bg-reverse.gif); background-position:top; }
80 | .button.default, input[type=submit].default, .submit-row input.default { border:2px solid #5b80b2; background:#7CA0C7 url(../img/default-bg.gif) bottom repeat-x; font-weight:bold; color:white; float:right; }
81 | .button.default:active, input[type=submit].default:active { background-image:url(../img/default-bg-reverse.gif); background-position:top; }
82 |
83 | /* MODULES */
84 | .module { border:1px solid #ccc; margin-bottom:5px; background:white; }
85 | .module p, .module ul, .module h3, .module h4, .module dl, .module pre { padding-left:10px; padding-right:10px; }
86 | .module blockquote { margin-left:12px; }
87 | .module ul, .module ol { margin-left:1.5em; }
88 | .module h3 { margin-top:.6em; }
89 | .module h2, .module caption, .inline-group h2 { margin:0; padding:2px 5px 3px 5px; font-size:11px; text-align:left; font-weight:bold; background:#7CA0C7 url(../img/default-bg.gif) top left repeat-x; color:white; }
90 | .module table { border-collapse: collapse; }
91 |
92 | /* MESSAGES & ERRORS */
93 | ul.messagelist { padding:0 0 5px 0; margin:0; }
94 | ul.messagelist li { font-size:12px; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border-bottom:1px solid #ddd; color:#666; background:#ffc url(../img/icon_success.gif) 5px .3em no-repeat; }
95 | .errornote { font-size:12px !important; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border:1px solid red; color:red;background:#ffc url(../img/icon_error.gif) 5px .3em no-repeat; }
96 | ul.errorlist { margin:0 !important; padding:0 !important; }
97 | .errorlist li { font-size:12px !important; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border:1px solid red; color:white; background:red url(../img/icon_alert.gif) 5px .3em no-repeat; }
98 | td ul.errorlist { margin:0 !important; padding:0 !important; }
99 | td ul.errorlist li { margin:0 !important; }
100 | .errors { background:#ffc; }
101 | .errors input, .errors select { border:1px solid red; }
102 | div.system-message { background: #ffc; margin: 10px; padding: 6px 8px; font-size: .8em; }
103 | div.system-message p.system-message-title { padding:4px 5px 4px 25px; margin:0; color:red; background:#ffc url(../img/icon_error.gif) 5px .3em no-repeat; }
104 | .description { font-size:12px; padding:5px 0 0 12px; }
105 | #warning {
106 | display: block; margin: 20px auto 0px; width: 700px; background-color: #FFFFCC; color: red; border: medium thin black; padding-left:12px;
107 | }
108 | #warning a {color: DarkRed !important; text-decoration: underline !important}
109 |
110 |
111 | /* PAGE STRUCTURE */
112 | #container { position:relative; width:100%; padding:0; }
113 | #content { margin:10px 15px; }
114 | #header { width:100%; }
115 | #content-main { float:left; width:100%; }
116 | #content-related { float:right; width:18em; position:relative; margin-right:-19em; }
117 | #footer { clear:both; padding:10px; }
118 |
119 | /* COLUMN TYPES */
120 | .colMS { margin-right:20em !important; }
121 | .colSM { margin-left:20em !important; }
122 | .colSM #content-related { float:left; margin-right:0; margin-left:-19em; }
123 | .colSM #content-main { float:right; }
124 | .popup .colM { width:95%; }
125 | .subcol { float:left; width:46%; margin-right:15px; }
126 | .dashboard #content { width:500px; }
127 |
128 | /* HEADER */
129 | #header { background:#394345; color:orange; overflow:hidden; }
130 | #header a:link, #header a:visited { color:white; }
131 | #header a:hover { text-decoration:underline; }
132 | #branding h1 {
133 | padding:0 10px;
134 | font-size:18px;
135 | margin:8px 0;
136 | font-weight:normal;
137 | color:white;
138 | }
139 | #branding h2 { padding:0 10px; font-size:14px; margin:-8px 0 8px 0; font-weight:normal; color:#ffc; }
140 | #user-tools { position:absolute; top:0; right:0; padding:1.2em 10px; font-size:11px; text-align:right; }
141 |
142 | #branding h1 {
143 | padding-top: 20px;
144 | }
145 |
146 | #branding {
147 | background: transparent url(../img/thunderbird.png) 0 0 no-repeat;
148 | margin-right: 200px;
149 | padding-left: 64px;
150 | min-height: 64px;
151 | }
152 |
153 |
154 | /* SIDEBAR */
155 | #content-related h3 { font-size:12px; color:#666; margin-bottom:3px; }
156 | #content-related h4 { font-size:11px; }
157 | #content-related .module h2 { background:#eee url(../img/nav-bg.gif) bottom left repeat-x; color:#666; }
158 |
159 | div.breadcrumbs {
160 | background: white url(../img/nav-bg-reverse.gif) 0 -10px repeat-x;
161 | padding: 2px 8px 3px 8px;
162 | font-size: 11px;
163 | color: #999;
164 | border-top: 1px solid white;
165 | border-bottom: 1px solid #ccc;
166 | text-align: left;
167 | }
168 |
169 | /* useful for which don't have hrefs */
170 | a.link { color: #5b80b2; text-decoration:none; }
171 | a.link:hover {
172 | color: #036;
173 | cursor: pointer;
174 | }
175 |
176 |
177 |
--------------------------------------------------------------------------------
/ispdb/config/static/css/comments.css:
--------------------------------------------------------------------------------
1 | .comment {
2 | width: 50%;
3 | overflow: auto;
4 | word-wrap: break-word;
5 | padding-top: 10px;
6 | }
7 |
8 | .comment_author {
9 | font-weight: bold;
10 | border: 0px;
11 | font-size: 12px;
12 | }
13 |
14 | .comment_date {
15 | border: 0px;
16 | font-size: 11px;
17 | }
18 |
19 | .comment_body {
20 | padding-top: 10px;
21 | padding-left: 5px;
22 | padding-right: 5px;
23 | }
24 |
25 | .comment_list {
26 | padding-top: 2px;
27 | padding-bottom: 10px;
28 | padding-left:10px;
29 | }
30 |
31 | #showcomments {
32 | padding-top: 2px;
33 | }
34 |
35 | #add_a_comment {
36 | padding-top: 10px;
37 | padding-bottom: 10px;
38 | }
39 |
40 | .remove_comment {
41 | font-size: 10px;
42 | }
43 |
--------------------------------------------------------------------------------
/ispdb/config/static/css/details.css:
--------------------------------------------------------------------------------
1 | #server_data {
2 | }
3 |
4 | #incoming_data {
5 | display: inline;
6 | }
7 |
8 | #outgoing_data {
9 | float: right;
10 | }
11 |
12 | #other_data {
13 | }
14 |
15 | #domains {
16 | padding: 1em;
17 | }
18 |
19 | .domain {
20 | -moz-border-radius: 3px;
21 | border: 1px solid grey;
22 | background: #FFEFAF;
23 | padding: 1ex;
24 | margin-right: 0.2ex;
25 | margin-bottom: 1ex;
26 | display: inline-block;
27 | }
28 |
29 | .configstatus {
30 | padding: 1.5em;
31 | margin: 1.5em;
32 | }
33 |
34 | .approved {
35 | border: 1px solid green;
36 | }
37 |
38 | .invalid {
39 | border: 1px solid red;
40 | }
41 |
42 | .deleted {
43 | border: 1px solid black;
44 | }
45 |
46 | .requested {
47 | border: 1px solid orange;
48 | }
49 |
50 | .float {
51 | float: left;
52 | clear: none;
53 | margin-right: 4px;
54 | }
55 |
56 | .errornote {
57 | margin-top: 10px;
58 | }
59 |
60 | #commenttext_div {
61 | padding: 8px;
62 | }
63 |
64 | #commenttext {
65 | font-size: 12px;
66 | }
67 |
68 | #sanity_checks{
69 | margin-top: 15px;
70 | }
71 |
72 | .error {
73 | background:url(../img/error-icon.png);
74 | background-size:15px 15px;
75 | background-repeat: no-repeat;
76 | padding: 0px 0 3px 23px;
77 | font-size: 13px;
78 | line-height: 20px;
79 | }
80 |
81 | .warning {
82 | background:url(../img/warning-icon.png);
83 | background-size:15px 15px;
84 | background-repeat: no-repeat;
85 | padding: 2px 0 3px 23px;
86 | font-size: 13px;
87 | line-height: 20px;
88 | }
89 |
90 | #sanity_results {
91 | margin-top: 10px;
92 | }
93 |
94 | .tab_desc {
95 | margin-left: 10px;
96 | }
97 |
--------------------------------------------------------------------------------
/ispdb/config/static/css/enter_config.css:
--------------------------------------------------------------------------------
1 | #domain_list {
2 | position: relative;
3 | max-width: 50em;
4 | }
5 |
6 | #domain_list table {
7 | max-width: 40em;
8 | }
9 | input[readonly=readonly] {
10 | color: grey;
11 | background-color:#F0F0F0;
12 | }
13 |
14 | #id_title {
15 | width: 30%;
16 | padding: 5px 5px;
17 | font-size: 14px;
18 | }
19 |
20 | #id_description {
21 | width: 30%;
22 | padding: 5px 5px;
23 | font-size: 14px;
24 | }
25 |
26 | #div_report_link {
27 | padding: 10px;
28 | }
29 |
30 | table.tab_descs td, table.tab_descs th,
31 | table.tab_insts td, table.tab_insts th,
32 | td.noborder, th.noborder {
33 | border-bottom: 0px;
34 | }
35 |
--------------------------------------------------------------------------------
/ispdb/config/static/css/ispdb.css:
--------------------------------------------------------------------------------
1 | .hidden {
2 | display: none;
3 | }
4 |
5 |
--------------------------------------------------------------------------------
/ispdb/config/static/css/show_issue.css:
--------------------------------------------------------------------------------
1 | .box {
2 | border: 1px solid #CACACA;
3 | border-radius: 10px;
4 | width: 70%;
5 | overflow: auto;
6 | word-wrap: break-word;
7 | }
8 |
9 | #author {
10 | color: #666;
11 | font-style: italic;
12 | padding: 0 10px;
13 | }
14 |
15 | #title {
16 | margin: -10px 0 0;
17 | padding: 0 10px;
18 | }
19 |
20 | #status {
21 | background-color: rgb(245, 245, 245);
22 | border-top: 1px solid #CACACA;
23 | border-bottom: 1px solid #CACACA;
24 | border-radius: 2px;
25 | padding: 5px 10px 0px 10px;
26 | color: #444;
27 | font-size: 11.5px;
28 | }
29 |
30 | #description {
31 | padding: 10px 40px 0 40px;
32 | }
33 |
34 | #buttons {
35 | padding: 5px 10px;
36 | border-top: 1px solid #CACACA;
37 | border-top:1px solid #eee;
38 | border-left:1px solid #eee;
39 | }
40 |
41 | #domains {
42 | line-height: 20px;
43 | padding: 0px 20px;
44 | }
45 |
46 | .domain_removed {
47 | text-decoration: line-through;
48 | }
49 |
50 | .domain_added {
51 | font-weight: bold;
52 | }
53 |
54 | #config {
55 | padding: 0 10px;
56 | }
57 |
58 | .config_changed {
59 | font-weight: bold;
60 | }
61 |
62 | #edit {
63 | float: right;
64 | }
65 |
66 | .tab_desc {
67 | margin-left: 10px;
68 | }
69 |
--------------------------------------------------------------------------------
/ispdb/config/static/img/ajax-loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla/ispdb/3b87b2c797d0d56cdf5343cca831af721360ca53/ispdb/config/static/img/ajax-loading.gif
--------------------------------------------------------------------------------
/ispdb/config/static/img/error-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla/ispdb/3b87b2c797d0d56cdf5343cca831af721360ca53/ispdb/config/static/img/error-icon.png
--------------------------------------------------------------------------------
/ispdb/config/static/img/nav-bg-grabber.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla/ispdb/3b87b2c797d0d56cdf5343cca831af721360ca53/ispdb/config/static/img/nav-bg-grabber.gif
--------------------------------------------------------------------------------
/ispdb/config/static/img/nav-bg-reverse.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla/ispdb/3b87b2c797d0d56cdf5343cca831af721360ca53/ispdb/config/static/img/nav-bg-reverse.gif
--------------------------------------------------------------------------------
/ispdb/config/static/img/nav-bg.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla/ispdb/3b87b2c797d0d56cdf5343cca831af721360ca53/ispdb/config/static/img/nav-bg.gif
--------------------------------------------------------------------------------
/ispdb/config/static/img/sign_in_blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla/ispdb/3b87b2c797d0d56cdf5343cca831af721360ca53/ispdb/config/static/img/sign_in_blue.png
--------------------------------------------------------------------------------
/ispdb/config/static/img/thunderbird.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla/ispdb/3b87b2c797d0d56cdf5343cca831af721360ca53/ispdb/config/static/img/thunderbird.png
--------------------------------------------------------------------------------
/ispdb/config/static/img/warning-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla/ispdb/3b87b2c797d0d56cdf5343cca831af721360ca53/ispdb/config/static/img/warning-icon.png
--------------------------------------------------------------------------------
/ispdb/config/templatetags/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla/ispdb/3b87b2c797d0d56cdf5343cca831af721360ca53/ispdb/config/templatetags/__init__.py
--------------------------------------------------------------------------------
/ispdb/config/templatetags/custom_filters.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from django import template
4 | from django.utils import timezone
5 |
6 | register = template.Library()
7 |
8 |
9 | @register.filter
10 | def data_verbose(boundField, attr_name="value"):
11 | """
12 | Returns field's data or its verbose version
13 | for a field with choices defined.
14 |
15 | Usage::
16 |
17 | {% load data_verbose %}
18 | {{form.some_field|data_verbose}}
19 | """
20 | data = boundField[attr_name]
21 | field = boundField
22 | rv = data
23 | if 'choices' in field and dict(field['choices']).get(data, ''):
24 | rv = dict(field["choices"]).get(data, "")
25 | return rv
26 |
27 |
28 | @register.filter
29 | def data_verbose_field(boundField, attr_name="value"):
30 | """
31 | Returns field's data or its verbose version
32 | for a field with choices defined.
33 |
34 | Usage::
35 |
36 | {{form.some_field|data_verbose_field}}
37 | """
38 | data = boundField.value()
39 | field = boundField.field
40 | return hasattr(field, 'choices') and dict(field.choices).get(data, '') or \
41 | data
42 |
43 |
44 | @register.filter
45 | def is_undo_available(self):
46 | delta = timezone.now() - self.deleted_datetime
47 | if delta.days > 0:
48 | return False
49 | return True
50 |
--------------------------------------------------------------------------------
/ispdb/convert.py:
--------------------------------------------------------------------------------
1 | import lxml.etree as ET
2 | import os
3 |
4 | from ispdb.config.models import Config, Domain
5 |
6 |
7 | def get_username(element):
8 | rv = element.find('username')
9 | if rv is None:
10 | rv = element.find('usernameForm')
11 | if rv is None:
12 | rv = ""
13 | else:
14 | rv = rv.text
15 | return rv
16 |
17 |
18 | def get_authentication(element):
19 | rv = element.find('authentication').text
20 | if (rv == "plain"):
21 | rv = "password-cleartext"
22 | elif (rv == "secure"):
23 | rv = "password-encrypted"
24 | return rv
25 |
26 |
27 | def main():
28 | datadir = os.environ.get("AUTOCONFIG_DATA", "../autoconfig_data")
29 | for fname in os.listdir(datadir):
30 | fullpath = os.path.join(datadir, fname)
31 | if fname.startswith('.') or os.path.isdir(fullpath) or (fname ==
32 | "README"):
33 | continue
34 | print "PROCESSING", fname
35 | et = ET.parse(fullpath)
36 | root = et.getroot()
37 | #print root
38 | incoming = root.find('.//incomingServer')
39 | outgoing = root.find('.//outgoingServer')
40 | id = root.find(".//emailProvider").attrib['id']
41 | # if we have one for this id, skip it
42 | if Config.objects.filter(email_provider_id=id):
43 | continue
44 |
45 | # Handle the older forms of XML.
46 | incoming_username_form = get_username(incoming)
47 | outgoing_username_form = get_username(outgoing)
48 | incoming_authentication = get_authentication(incoming)
49 | outgoing_authentication = get_authentication(outgoing)
50 |
51 | if not incoming_authentication:
52 | continue
53 |
54 | try:
55 | addThisServer = outgoing.find('addThisServer').text == "true"
56 | except:
57 | addThisServer = False
58 |
59 | try:
60 | useGlobalPreferredServer = \
61 | outgoing.find('useGlobalPreferredServer').text == "true"
62 | except:
63 | useGlobalPreferredServer = False
64 |
65 | c = Config(id=None,
66 | email_provider_id=id,
67 | display_name=root.find('.//displayName').text,
68 | display_short_name=root.find('.//displayShortName').text,
69 | incoming_type=incoming.attrib['type'],
70 | incoming_hostname=incoming.find('hostname').text,
71 | incoming_port=int(incoming.find('port').text),
72 | incoming_socket_type=incoming.find('socketType').text,
73 | incoming_authentication=incoming_authentication,
74 | incoming_username_form=incoming_username_form,
75 | outgoing_hostname=outgoing.find('hostname').text,
76 | outgoing_port=int(outgoing.find('port').text),
77 | outgoing_socket_type=outgoing.find('socketType').text,
78 | outgoing_username_form=outgoing_username_form,
79 | outgoing_authentication=outgoing_authentication,
80 | outgoing_add_this_server=addThisServer,
81 | outgoing_use_global_preferred_server=(
82 | useGlobalPreferredServer),
83 | status='approved',
84 | )
85 | domains = root.findall('.//domain')
86 | c.save()
87 | ds = [Domain(id=None, name=d.text, config=c) for d in domains]
88 | for d in ds:
89 | d.save()
90 |
91 |
92 | if __name__ == "__main__":
93 | main()
94 |
--------------------------------------------------------------------------------
/ispdb/fixtures/domain_testdata.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "pk": 1,
4 | "model": "config.domain",
5 | "fields": {
6 | "config": 2,
7 | "name": "validdomain.com"
8 | }
9 | },
10 | {
11 | "pk": 2,
12 | "model": "config.domain",
13 | "fields": {
14 | "config": 4,
15 | "name": "invaliddomain.com"
16 | }
17 | },
18 | {
19 | "pk": 1,
20 | "model": "config.domainrequest",
21 | "fields": {
22 | "votes": 1,
23 | "config": 1,
24 | "name": "domainrequest.com"
25 | }
26 | },
27 | {
28 | "pk": 2,
29 | "model": "config.domainrequest",
30 | "fields": {
31 | "votes": 1,
32 | "config": 3,
33 | "name": "invaliddomainrequest.com"
34 | }
35 | },
36 | {
37 | "pk": 1,
38 | "model": "config.config",
39 | "fields": {
40 | "outgoing_username_form": "test",
41 | "incoming_socket_type": "plain",
42 | "outgoing_port": 465,
43 | "incoming_authentication": "password-encrypted",
44 | "email_provider_id": "",
45 | "owner": 1,
46 | "display_name": "Domain Request",
47 | "outgoing_add_this_server": false,
48 | "outgoing_socket_type": "SSL",
49 | "created_datetime": "2012-05-31T21:06:47.613Z",
50 | "outgoing_authentication": "password-encrypted",
51 | "incoming_hostname": "test.com",
52 | "status": "requested",
53 | "display_short_name": "Domain Request",
54 | "outgoing_use_global_preferred_server": false,
55 | "incoming_port": 143,
56 | "last_update_datetime": "2012-05-31T21:06:47.613Z",
57 | "incoming_username_form": "",
58 | "outgoing_hostname": "test.com",
59 | "incoming_type": "imap",
60 | "deleted_datetime": null,
61 | "last_status": "",
62 | "locked": "False"
63 | }
64 | },
65 | {
66 | "pk": 2,
67 | "model": "config.config",
68 | "fields": {
69 | "outgoing_username_form": "Valid Domain",
70 | "incoming_socket_type": "plain",
71 | "outgoing_port": 587,
72 | "incoming_authentication": "password-encrypted",
73 | "email_provider_id": "",
74 | "owner": 1,
75 | "display_name": "Valid Domain",
76 | "outgoing_add_this_server": false,
77 | "outgoing_socket_type": "plain",
78 | "created_datetime": "2012-05-31T21:07:24.426Z",
79 | "outgoing_authentication": "password-encrypted",
80 | "incoming_hostname": "Valid Domain",
81 | "status": "approved",
82 | "display_short_name": "Valid Domain",
83 | "outgoing_use_global_preferred_server": false,
84 | "incoming_port": 143,
85 | "last_update_datetime": "2012-05-31T21:07:27.421Z",
86 | "incoming_username_form": "",
87 | "outgoing_hostname": "Valid Domain",
88 | "incoming_type": "imap",
89 | "deleted_datetime": null,
90 | "last_status": "",
91 | "locked": "False"
92 | }
93 | },
94 | {
95 | "pk": 3,
96 | "model": "config.config",
97 | "fields": {
98 | "outgoing_username_form": "test",
99 | "incoming_socket_type": "plain",
100 | "outgoing_port": 587,
101 | "incoming_authentication": "password-encrypted",
102 | "email_provider_id": "",
103 | "owner": 1,
104 | "display_name": "Invalid Domain",
105 | "outgoing_add_this_server": false,
106 | "outgoing_socket_type": "plain",
107 | "created_datetime": "2012-05-31T21:08:09.314Z",
108 | "outgoing_authentication": "password-encrypted",
109 | "incoming_hostname": "Invalid Domain",
110 | "status": "invalid",
111 | "display_short_name": "Invalid Domain",
112 | "outgoing_use_global_preferred_server": false,
113 | "incoming_port": 143,
114 | "last_update_datetime": "2012-05-31T21:08:11.305Z",
115 | "incoming_username_form": "",
116 | "outgoing_hostname": "test.com",
117 | "incoming_type": "imap",
118 | "last_status": "",
119 | "deleted_datetime": null,
120 | "locked": "False"
121 | }
122 | },
123 | {
124 | "pk": 4,
125 | "model": "config.config",
126 | "fields": {
127 | "outgoing_username_form": "test",
128 | "incoming_socket_type": "plain",
129 | "outgoing_port": 587,
130 | "incoming_authentication": "password-encrypted",
131 | "email_provider_id": "",
132 | "owner": 1,
133 | "display_name": "Invalid Domain",
134 | "outgoing_add_this_server": false,
135 | "outgoing_socket_type": "plain",
136 | "created_datetime": "2012-05-31T21:08:09.314Z",
137 | "outgoing_authentication": "password-encrypted",
138 | "incoming_hostname": "Invalid Domain",
139 | "status": "invalid",
140 | "display_short_name": "Invalid Domain",
141 | "outgoing_use_global_preferred_server": false,
142 | "incoming_port": 143,
143 | "last_update_datetime": "2012-05-31T21:08:11.305Z",
144 | "incoming_username_form": "",
145 | "outgoing_hostname": "test.com",
146 | "incoming_type": "imap",
147 | "last_status": "",
148 | "deleted_datetime": null,
149 | "locked": "False"
150 | }
151 | },
152 | {
153 | "pk": 1,
154 | "model": "config.docurl",
155 | "fields": {
156 | "url": "http://test.com/",
157 | "config": 2
158 | }
159 | },
160 | {
161 | "pk": 1,
162 | "model": "config.docurldesc",
163 | "fields": {
164 | "docurl": 1,
165 | "description": "test",
166 | "language": "en"
167 | }
168 | }
169 | ]
170 |
--------------------------------------------------------------------------------
/ispdb/fixtures/issue_testdata.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "pk": 1,
4 | "model": "config.domain",
5 | "fields": {
6 | "config": 1,
7 | "name": "test.com"
8 | }
9 | },
10 | {
11 | "pk": 1,
12 | "model": "config.config",
13 | "fields": {
14 | "outgoing_username_form": "%EMAILLOCALPART%",
15 | "incoming_socket_type": "plain",
16 | "outgoing_port": 587,
17 | "incoming_authentication": "password-encrypted",
18 | "email_provider_id": "",
19 | "owner": 1,
20 | "display_name": "Test",
21 | "outgoing_add_this_server": false,
22 | "outgoing_socket_type": "plain",
23 | "created_datetime": "2012-05-31T21:06:47.613Z",
24 | "outgoing_authentication": "password-encrypted",
25 | "incoming_hostname": "test.com",
26 | "status": "approved",
27 | "display_short_name": "Domain Request",
28 | "outgoing_use_global_preferred_server": false,
29 | "incoming_port": 143,
30 | "last_update_datetime": "2012-05-31T21:06:47.613Z",
31 | "incoming_username_form": "%EMAILLOCALPART%",
32 | "outgoing_hostname": "test.com",
33 | "incoming_type": "imap",
34 | "deleted_datetime": null,
35 | "last_status": ""
36 | }
37 | },
38 | {
39 | "pk": 1,
40 | "model": "config.docurl",
41 | "fields": {
42 | "url": "http://test.com/",
43 | "config": 1
44 | }
45 | },
46 | {
47 | "pk": 1,
48 | "model": "config.docurldesc",
49 | "fields": {
50 | "docurl": 1,
51 | "description": "test",
52 | "language": "en"
53 | }
54 | },
55 | {
56 | "pk": 1,
57 | "model": "config.enableurl",
58 | "fields": {
59 | "url": "http://test.com/",
60 | "config": 1
61 | }
62 | },
63 | {
64 | "pk": 1,
65 | "model": "config.enableurlinst",
66 | "fields": {
67 | "enableurl": 1,
68 | "description": "test",
69 | "language": "en"
70 | }
71 | }
72 | ]
73 |
--------------------------------------------------------------------------------
/ispdb/fixtures/login_testdata.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "pk": 1,
4 | "model": "auth.user",
5 | "fields": {
6 | "username": "test",
7 | "first_name": "",
8 | "last_name": "",
9 | "is_active": true,
10 | "is_superuser": false,
11 | "is_staff": false,
12 | "last_login": "2012-05-21T14:24:50.063Z",
13 | "groups": [],
14 | "user_permissions": [],
15 | "password": "pbkdf2_sha256$10000$1xx5mUXNECJX$8nPvbdDdEsSFIinfnyQueJdMwzU74XaDYqSTHySdvcw=",
16 | "email": "test@test.com",
17 | "date_joined": "2012-05-21T14:24:50.063Z"
18 | }
19 | },
20 | {
21 | "pk": 2,
22 | "model": "auth.user",
23 | "fields": {
24 | "username": "test_admin",
25 | "first_name": "",
26 | "last_name": "",
27 | "is_active": true,
28 | "is_superuser": true,
29 | "is_staff": true,
30 | "last_login": "2012-05-21T14:24:50.063Z",
31 | "groups": [],
32 | "user_permissions": [],
33 | "password": "pbkdf2_sha256$10000$1xx5mUXNECJX$8nPvbdDdEsSFIinfnyQueJdMwzU74XaDYqSTHySdvcw=",
34 | "email": "testadmin@test.com",
35 | "date_joined": "2012-05-21T14:24:50.063Z"
36 | }
37 | },
38 | {
39 | "pk": 3,
40 | "model": "auth.user",
41 | "fields": {
42 | "username": "test2",
43 | "first_name": "",
44 | "last_name": "",
45 | "is_active": true,
46 | "is_superuser": false,
47 | "is_staff": false,
48 | "last_login": "2012-05-21T14:24:50.063Z",
49 | "groups": [],
50 | "user_permissions": [],
51 | "password": "pbkdf2_sha256$10000$1xx5mUXNECJX$8nPvbdDdEsSFIinfnyQueJdMwzU74XaDYqSTHySdvcw=",
52 | "email": "test2@test.com",
53 | "date_joined": "2012-05-21T14:24:50.063Z"
54 | }
55 | }
56 | ]
57 |
--------------------------------------------------------------------------------
/ispdb/fixtures/sanity.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "pk": 1,
4 | "model": "config.domain",
5 | "fields": {
6 | "config": 1,
7 | "name": "test.org"
8 | }
9 | },
10 | {
11 | "pk": 2,
12 | "model": "config.domain",
13 | "fields": {
14 | "config": 1,
15 | "name": "test.com"
16 | }
17 | },
18 | {
19 | "pk": 1,
20 | "model": "config.config",
21 | "fields": {
22 | "outgoing_username_form": "%EMAILLOCALPART%",
23 | "incoming_socket_type": "SSL",
24 | "outgoing_port": 465,
25 | "incoming_authentication": "password-cleartext",
26 | "email_provider_id": "",
27 | "owner": 2,
28 | "display_name": "Test",
29 | "outgoing_add_this_server": false,
30 | "outgoing_socket_type": "SSL",
31 | "created_datetime": "2012-05-31T21:06:47.613Z",
32 | "outgoing_authentication": "password-cleartext",
33 | "incoming_hostname": "mail.test.com",
34 | "status": "valid",
35 | "display_short_name": "Test",
36 | "outgoing_use_global_preferred_server": false,
37 | "incoming_port": 995,
38 | "last_update_datetime": "2012-05-31T21:06:47.613Z",
39 | "incoming_username_form": "%EMAILLOCALPART%",
40 | "outgoing_hostname": "mail.test.com",
41 | "incoming_type": "imap",
42 | "deleted_datetime": null,
43 | "last_status": ""
44 | }
45 | }
46 | ]
47 |
--------------------------------------------------------------------------------
/ispdb/fixtures/xml_testdata.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "pk":1,
4 | "model":"config.domain",
5 | "fields": {
6 | "config": 1,
7 | "name": "test.com"
8 | }
9 | },
10 | {
11 | "pk":2,
12 | "model":"config.domain",
13 | "fields": {
14 | "config": 2,
15 | "name": "test2.com"
16 | }
17 | },
18 | {
19 | "pk":1,
20 | "model":"config.config",
21 | "fields": {
22 | "outgoing_use_global_preferred_server":false,
23 | "incoming_socket_type":"SSL",
24 | "outgoing_port":25,
25 | "email_provider_id":"test.com",
26 | "incoming_authentication":"password-cleartext",
27 | "display_name":"NetZero Email",
28 | "outgoing_add_this_server":false,
29 | "outgoing_socket_type":"SSL",
30 | "created_datetime": "2012-05-31T21:08:09.314Z",
31 | "outgoing_authentication":"password-cleartext",
32 | "incoming_hostname":"hostname_in",
33 | "outgoing_username_form":"%EMAILLOCALPART%",
34 | "display_short_name":"netzero",
35 | "status":"approved",
36 | "incoming_port":143,
37 | "last_update_datetime": "2012-05-31T21:08:11.305Z",
38 | "incoming_username_form":"",
39 | "outgoing_hostname":"hostname_out",
40 | "incoming_type":"imap",
41 | "locked": "False"
42 | }
43 | },
44 | {
45 | "pk":2,
46 | "model":"config.config",
47 | "fields": {
48 | "outgoing_use_global_preferred_server":false,
49 | "incoming_socket_type":"SSL",
50 | "outgoing_port":25,
51 | "flagged_by_email":"",
52 | "flagged_as_incorrect":false,
53 | "email_provider_id":"test.com",
54 | "incoming_authentication":"password-cleartext",
55 | "display_name":"NetZero Email",
56 | "outgoing_add_this_server":false,
57 | "outgoing_socket_type":"SSL",
58 | "created_datetime": "2012-05-31T21:08:09.314Z",
59 | "outgoing_authentication":"password-cleartext",
60 | "incoming_hostname":"hostname_in",
61 | "outgoing_username_form":"%EMAILLOCALPART%",
62 | "display_short_name":"netzero",
63 | "status":"approved",
64 | "incoming_port":143,
65 | "last_update_datetime": "2012-04-30T21:08:11.305Z",
66 | "incoming_username_form":"",
67 | "outgoing_hostname":"hostname_out",
68 | "incoming_type":"imap",
69 | "locked": "False"
70 | }
71 | },
72 | {
73 | "pk": 1,
74 | "model": "config.docurl",
75 | "fields": {
76 | "url": "http://test.com/",
77 | "config": 1
78 | }
79 | },
80 | {
81 | "pk": 1,
82 | "model": "config.docurldesc",
83 | "fields": {
84 | "docurl": 1,
85 | "description": "test",
86 | "language": "en"
87 | }
88 | },
89 | {
90 | "pk": 2,
91 | "model": "config.docurl",
92 | "fields": {
93 | "url": "http://test.com/",
94 | "config": 1
95 | }
96 | },
97 | {
98 | "pk": 2,
99 | "model": "config.docurldesc",
100 | "fields": {
101 | "docurl": 2,
102 | "description": "test",
103 | "language": "en"
104 | }
105 | },
106 | {
107 | "pk": 3,
108 | "model": "config.docurldesc",
109 | "fields": {
110 | "docurl": 2,
111 | "description": "test2",
112 | "language": "fr"
113 | }
114 | },
115 | {
116 | "pk": 1,
117 | "model": "config.enableurl",
118 | "fields": {
119 | "url": "http://test.com/",
120 | "config": 1
121 | }
122 | },
123 | {
124 | "pk": 1,
125 | "model": "config.enableurlinst",
126 | "fields": {
127 | "enableurl": 1,
128 | "description": "test",
129 | "language": "en"
130 | }
131 | },
132 | {
133 | "pk": 2,
134 | "model": "config.enableurl",
135 | "fields": {
136 | "url": "http://test.com/",
137 | "config": 1
138 | }
139 | },
140 | {
141 | "pk": 2,
142 | "model": "config.enableurlinst",
143 | "fields": {
144 | "enableurl": 2,
145 | "description": "test",
146 | "language": "en"
147 | }
148 | },
149 | {
150 | "pk": 3,
151 | "model": "config.enableurlinst",
152 | "fields": {
153 | "enableurl": 2,
154 | "description": "test2",
155 | "language": "fr"
156 | }
157 | }
158 | ]
159 |
--------------------------------------------------------------------------------
/ispdb/middleware/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozilla/ispdb/3b87b2c797d0d56cdf5343cca831af721360ca53/ispdb/middleware/__init__.py
--------------------------------------------------------------------------------
/ispdb/middleware/x_ssl.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect, get_host
3 |
4 | SSL = 'SSL'
5 |
6 | def is_secure(request):
7 | if 'HTTP_X_SSL' in request.META:
8 | return request.META['HTTP_X_SSL'] == 'on'
9 | return False
10 |
11 | class x_ssl:
12 | def process_view(self, request, view_func, view_args, view_kwargs):
13 | if SSL in view_kwargs:
14 | secure = view_kwargs[SSL]
15 | del view_kwargs[SSL]
16 | else:
17 | secure = False
18 |
19 | if not secure == is_secure(request):
20 | return self._redirect(request, secure)
21 |
22 | def _redirect(self, request, secure):
23 | protocol = secure and "https" or "http"
24 | newurl = "%s://%s%s" % (protocol,get_host(request),request.get_full_path())
25 | if settings.DEBUG and request.method == 'POST':
26 | raise RuntimeError, \
27 | """Django can't perform a SSL redirect while maintaining POST data.
28 | Please structure your views so that redirects only occur during GETs."""
29 |
30 | #return HttpResponseRedirect(newurl)
31 | return HttpResponsePermanentRedirect(newurl) #I have not had time to test this, but it appears to work better.
32 |
33 |
--------------------------------------------------------------------------------
/ispdb/settings.py:
--------------------------------------------------------------------------------
1 | import os
2 | # Django settings for ispdb project.
3 |
4 | DEBUG = True
5 | TEMPLATE_DEBUG = DEBUG
6 |
7 | ISPDB_ROOT = os.path.dirname(os.path.abspath(__file__))
8 |
9 | ADMINS = (
10 | )
11 |
12 | MANAGERS = ADMINS
13 |
14 | DATABASES = {
15 | 'default': {
16 | 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
17 | 'NAME': os.path.join(ISPDB_ROOT,'ispdb.sqlite'), # Or path to database file if using sqlite3.
18 | 'USER': '', # Not used with sqlite3.
19 | 'PASSWORD': '', # Not used with sqlite3.
20 | 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
21 | 'PORT': '', # Set to empty string for default. Not used with sqlite3.
22 | }
23 | }
24 |
25 | #Test Runner
26 | TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
27 | NOSE_ARGS = ['--with-doctest', '--doctest-extension=.doctest']
28 |
29 | #Fixtures
30 | FIXTURE_DIRS = (
31 | #TODO: Clean this up after eric's patch for local settings
32 | os.path.join(ISPDB_ROOT,"fixtures/"),
33 | )
34 |
35 | # Local time zone for this installation. Choices can be found here:
36 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
37 | # although not all choices may be available on all operating systems.
38 | # If running in a Windows environment this must be set to the same as your
39 | # system time zone.
40 | TIME_ZONE = 'America/Chicago'
41 |
42 | # Language code for this installation. All choices can be found here:
43 | # http://www.i18nguy.com/unicode/language-identifiers.html
44 | LANGUAGE_CODE = 'en-us'
45 |
46 | SITE_ID = 1
47 |
48 | # If you set this to False, Django will make some optimizations so as not
49 | # to load the internationalization machinery.
50 | USE_I18N = False
51 |
52 | # If you set this to False, Django will not format dates, numbers and
53 | # calendars according to the current locale
54 | USE_L10N = True
55 |
56 | # If you set this to False, Django will not use timezone-aware datetimes.
57 | USE_TZ = True
58 |
59 | # Absolute filesystem path to the directory that will hold user-uploaded files.
60 | # Example: "/home/media/media.lawrence.com/media/"
61 | MEDIA_ROOT = ''
62 |
63 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a
64 | # trailing slash.
65 | # Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
66 | MEDIA_URL = ''
67 |
68 | # Absolute path to the directory static files should be collected to.
69 | # Don't put anything in this directory yourself; store your static files
70 | # in apps' "static/" subdirectories and in STATICFILES_DIRS.
71 | # Example: "/home/media/media.lawrence.com/static/"
72 | STATIC_ROOT = ''
73 |
74 | # URL prefix for static files.
75 | # Example: "http://media.lawrence.com/static/"
76 | STATIC_URL = '/static/'
77 |
78 | # Additional locations of static files
79 | STATICFILES_DIRS = (
80 | # Put strings here, like "/home/html/static" or "C:/www/django/static".
81 | # Always use forward slashes, even on Windows.
82 | # Don't forget to use absolute paths, not relative paths.
83 | )
84 |
85 | # List of finder classes that know how to find static files in
86 | # various locations.
87 | STATICFILES_FINDERS = (
88 | 'django.contrib.staticfiles.finders.FileSystemFinder',
89 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
90 | # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
91 | )
92 |
93 | # Make this unique, and don't share it with anybody.
94 | SECRET_KEY = '02$7gj$t@dtd7um)d#3zlfg7ommedl#*ekt@@*ysy_fns(lp9+'
95 |
96 | # List of callables that know how to import templates from various sources.
97 | TEMPLATE_LOADERS = (
98 | 'django.template.loaders.filesystem.Loader',
99 | 'django.template.loaders.app_directories.Loader',
100 | )
101 |
102 | MIDDLEWARE_CLASSES = (
103 | 'django.middleware.cache.UpdateCacheMiddleware',
104 | 'django.middleware.common.CommonMiddleware',
105 | 'django.contrib.sessions.middleware.SessionMiddleware',
106 | 'django.middleware.csrf.CsrfViewMiddleware',
107 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
108 | 'django.contrib.messages.middleware.MessageMiddleware',
109 | # Uncomment the next line for simple clickjacking protection:
110 | # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
111 | 'django.middleware.cache.FetchFromCacheMiddleware',
112 | )
113 |
114 | ROOT_URLCONF = 'ispdb.urls'
115 |
116 | TEMPLATE_DIRS = (
117 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
118 | # Always use forward slashes, even on Windows.
119 | # Don't forget to use absolute paths, not relative paths.
120 | os.path.join(ISPDB_ROOT, "templates/"),
121 | os.path.join(ISPDB_ROOT, "templates/config/"),
122 | )
123 |
124 |
125 | INSTALLED_APPS = (
126 | 'django.contrib.auth',
127 | 'django_browserid',
128 | 'django.contrib.contenttypes',
129 | 'django.contrib.sessions',
130 | 'django.contrib.sites',
131 | 'django.contrib.admin',
132 | 'django.contrib.comments',
133 | 'django.contrib.staticfiles',
134 | 'ispdb.config',
135 | 'django_nose',
136 | )
137 |
138 | AUTHENTICATION_BACKENDS = (
139 | 'django_browserid.auth.BrowserIDBackend',
140 | 'django.contrib.auth.backends.ModelBackend',
141 | )
142 |
143 | SITE_URL = 'http://localhost:8000'
144 | LOGIN_URL = '/login'
145 | LOGIN_REDIRECT_URL = '/'
146 | LOGIN_REDIRECT_URL_FAILURE = '/'
147 | BROWSERID_CREATE_USER = True
148 |
149 | TEMPLATE_CONTEXT_PROCESSORS = (
150 | "django.contrib.auth.context_processors.auth",
151 | "django.core.context_processors.debug",
152 | "django.core.context_processors.i18n",
153 | "django.core.context_processors.media",
154 | "django.core.context_processors.static",
155 | "django.core.context_processors.tz",
156 | "django.contrib.messages.context_processors.messages",
157 | "django.core.context_processors.request",
158 | "django_browserid.context_processors.browserid_form",
159 | )
160 |
161 | CACHES = {
162 | 'default': {
163 | 'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/ispdb/templates/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Not Found
7 |
8 | Internal Server Error
7 |
8 | {% block heading %}{% endblock %}
27 |
37 |
42 | {% endif %}
43 |
{{config.display_name}}
89 | {% ifnotequal config.display_name config.display_short_name %} ({{config.display_short_name}} for short) {% endifnotequal %}
90 |
91 |
146 |
147 |
189 |
190 |
Domains Served
208 |
222 |
251 |
223 |
250 |
224 |
235 | Incoming Server
226 |
227 | {% for field in incoming %}
228 |
233 |
229 |
231 | {% endfor %}
232 | {{ field.verbose_name|capfirst }}: {{field|data_verbose}}
230 |
236 |
237 |
249 | Outgoing Server
239 |
240 | {% for field in outgoing %}
241 |
247 |
242 |
245 | {% endfor %}
246 | {{ field.verbose_name|capfirst }}:
243 | {{field|data_verbose}}
244 | Documentation
256 | {% for form in docurls %}
257 | {% include "config/urls/url_list.html" %}
258 | {% for desc_form in form.desc_formset %}
259 | {% include "config/urls/desc_list.html" %}
260 | {% endfor %}
261 | {% endfor %}
262 | Enable Instructions
268 | {% for form in enableurls %}
269 | {% include "config/urls/url_list.html" %}
270 | {% for desc_form in form.inst_formset %}
271 | {% include "config/urls/desc_list.html" %}
272 | {% endfor %}
273 | {% endfor %}
274 | Other Fields
279 |
280 | {% for field in other_fields %}
281 |
286 |
282 |
284 | {% endfor %}
285 | {{ field.verbose_name|capfirst }}: {{field.value}}
283 |
See XML version (used by Thunderbird).
293 | 294 | {% if config.status == "approved" %} 295 |No reported issues.
303 | {% endfor %} 304 | 305 |If you know the data above is not accurate, do let us know: 308 | these parameters are out of date! 309 |
310 | {% endif %} 311 | 312 |This site lets you contribute data to Mozilla's database of 66 | ISP email configuration files. These files will be used by 67 | Thunderbird 3 to facilitate account configuration. 68 |
69 | 70 |You don't have permission to access this page. 27 | {% if not user.is_authenticated %} 28 | Log in.
29 | 30 | {% endif %} 31 | {% endblock %} 32 | -------------------------------------------------------------------------------- /ispdb/templates/config/queue.html: -------------------------------------------------------------------------------- 1 | {% extends "config/base.html" %} 2 | {% load url from future %} 3 | {% block scripts %} 4 | 5 | 6 | {% endblock %} 7 | 8 | 9 | {% block title %}ISP Configuration Review Queue{% endblock %} 10 | {% block heading %}Mozilla Messaging ISP Configuration Management: Review Queue{% endblock %} 11 | 12 | {% block bodystart %} 13 | 16 | {% endblock %} 17 | 18 | {% block content %} 19 |{{ error }}
This issue is {{ issue.status }}
{{ issue.description }}
{{ field.verbose_name|capfirst }}: | 89 |{{field|data_verbose:"new_value"}} | 91 | {% else %} 92 |{{ field.verbose_name|capfirst }}: | {{field|data_verbose}} | 93 | {% endif %} 94 |
{{ field.verbose_name|capfirst }}: | 106 |{{field|data_verbose:"new_value"}} | 108 | {% else %} 109 |{{ field.verbose_name|capfirst }}: | {{field|data_verbose}} | 110 | {% endif %} 111 |
{{ field.verbose_name|capfirst }}: | 123 |{{field|data_verbose:"new_value"}} | 125 | {% else %} 126 |{{ field.verbose_name|capfirst }}: | 127 |{{field|data_verbose}} | 128 | {% endif %} 129 |
{{ desc_form.description.label }}: | {{ desc_form.description.value }} | {{ desc_form.language|data_verbose_field }} | 5 |
{{ form.url.label}}: | {{ form.url.value}} | 4 |
340 |