From 6f182d78507b25fbe6602d82ca92c92a0f2dd38b Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 25 Aug 2011 17:22:37 +0200 Subject: [PATCH] * No more code inside lib/__init__.py * Fixed a circular import raised only when using commands like 'manage.py syncdb' --- admin/lib.py | 19 ++ admin/models.py | 3 +- admin/permissions.py | 2 +- admin/templatetags/admin_extras.py | 3 +- admin/views.py | 7 +- auth/lib.py | 18 ++ extensions/amavis_quarantine/main.py | 3 +- extensions/amavis_quarantine/sql_listing.py | 3 +- .../templatetags/amextras.py | 2 +- extensions/amavis_quarantine/views.py | 5 +- extensions/postfix_autoreply/main.py | 3 +- ...002_auto__add_armessage__add_arhistoric.py | 2 +- extensions/postfix_autoreply/views.py | 3 +- extensions/sievefilters/main.py | 3 +- .../templatetags/sfilters_tags.py | 2 +- extensions/sievefilters/views.py | 6 +- extensions/stats/main.py | 3 +- extensions/stats/views.py | 2 +- extensions/webmail/lib.py | 4 +- extensions/webmail/main.py | 3 +- extensions/webmail/middleware.py | 2 +- extensions/webmail/templatetags/webextras.py | 3 +- extensions/webmail/views.py | 7 +- lib/__init__.py | 199 ------------------ lib/authbackends.py | 2 +- lib/dbutils.py | 20 ++ lib/email_listing.py | 3 +- lib/emailutils.py | 15 +- lib/models.py | 2 +- lib/parameters.py | 9 +- lib/sysutils.py | 23 ++ lib/templatetags/libextras.py | 2 +- lib/webutils.py | 114 ++++++++++ locale/de/LC_MESSAGES/django.po | 2 +- locale/de/LC_MESSAGES/djangojs.po | 2 +- tools/pfxadmin_migrate/migrate.py | 2 +- userprefs/forms.py | 2 +- userprefs/templatetags/uprefs_extras.py | 3 +- userprefs/views.py | 6 +- 39 files changed, 273 insertions(+), 241 deletions(-) create mode 100644 lib/dbutils.py create mode 100644 lib/sysutils.py create mode 100644 lib/webutils.py diff --git a/admin/lib.py b/admin/lib.py index 40b896dd2..d85a4f9cd 100644 --- a/admin/lib.py +++ b/admin/lib.py @@ -1,7 +1,26 @@ # coding: utf-8 from django.http import HttpResponse, HttpResponseRedirect from django.contrib.auth.models import User, Group +from django.utils.translation import ugettext as _ from models import * +from modoboa.lib.webutils import _render_error + +def is_not_localadmin(errortpl="error"): + def dec(f): + def wrapped_f(request, *args, **kwargs): + if request.user.id == 1: + return _render_error(request, errortpl, { + "error" : _("Invalid action, %(user)s is a local user" \ + % {"user" : request.user.username}) + }) + return f(request, *args, **kwargs) + + wrapped_f.__name__ = f.__name__ + wrapped_f.__dict__ = f.__dict__ + wrapped_f.__doc__ = f.__doc__ + wrapped_f.__module__ = f.__module__ + return wrapped_f + return dec def is_domain_admin(user): """Tell if a user is administrator for a domain of not diff --git a/admin/models.py b/admin/models.py index 36a8bf331..aed4cd235 100644 --- a/admin/models.py +++ b/admin/models.py @@ -5,8 +5,9 @@ from django.utils.translation import ugettext as _ from django.dispatch import receiver from django.conf import settings from modoboa.lib import parameters -from modoboa.lib import exec_cmd, exec_as_vuser, crypt_password +from modoboa.lib.sysutils import exec_cmd, exec_as_vuser from modoboa.lib.emailutils import split_mailbox +from modoboa.auth.lib import crypt_password import os import pwd diff --git a/admin/permissions.py b/admin/permissions.py index 60c38d821..01c4e2902 100644 --- a/admin/permissions.py +++ b/admin/permissions.py @@ -3,7 +3,7 @@ import datetime from django.utils.translation import ugettext as _ from django.contrib.auth.models import User, Group -from modoboa.lib import _render, getctx, _render_to_string +from modoboa.lib.webutils import _render, getctx, _render_to_string from forms import * class Permissions(object): diff --git a/admin/templatetags/admin_extras.py b/admin/templatetags/admin_extras.py index 3670d87ae..c2a39923a 100644 --- a/admin/templatetags/admin_extras.py +++ b/admin/templatetags/admin_extras.py @@ -3,7 +3,8 @@ from django.template.loader import render_to_string from django.utils.translation import ugettext as _ from django.core.urlresolvers import reverse from modoboa import admin -from modoboa.lib import events, static_url, render_actions +from modoboa.lib import events +from modoboa.lib.webutils import static_url, render_actions register = template.Library() diff --git a/admin/views.py b/admin/views.py index 206429dd8..b3647dfc1 100644 --- a/admin/views.py +++ b/admin/views.py @@ -17,9 +17,10 @@ from modoboa import admin, userprefs from models import * from admin.permissions import * from admin.tables import * -from modoboa.lib import crypt_password -from modoboa.lib import _render, ajax_response, ajax_simple_response, \ - getctx, events, parameters +from modoboa.lib import events, parameters +from modoboa.auth.lib import crypt_password +from modoboa.lib.webutils \ + import _render, ajax_response, ajax_simple_response, getctx from modoboa.lib.emailutils import split_mailbox from modoboa.lib.models import Parameter import copy diff --git a/auth/lib.py b/auth/lib.py index 97c340792..6a6d921ea 100644 --- a/auth/lib.py +++ b/auth/lib.py @@ -1,5 +1,7 @@ # coding: utf-8 +import crypt, hashlib +from random import Random from Crypto.Cipher import AES import base64 from modoboa.lib import parameters @@ -22,3 +24,19 @@ def decrypt(ciph): def get_password(request): return decrypt(request.session["password"]) +def _check_password(password, crypted): + scheme = parameters.get_admin("PASSWORD_SCHEME", app="admin") + if scheme == "crypt": + return crypt.crypt(password, crypted) == crypted + if scheme == "md5": + return hashlib.md5(password).hexdigest() == crypted + return password + +def crypt_password(password): + scheme = parameters.get_admin("PASSWORD_SCHEME", app="admin") + if scheme == "crypt": + salt = ''.join(Random().sample(string.letters + string.digits, 2)) + return crypt.crypt(password, salt) + if scheme == "md5": + return hashlib.md5(password).hexdigest() + return password diff --git a/extensions/amavis_quarantine/main.py b/extensions/amavis_quarantine/main.py index cf330f2a8..bfbc0d53a 100644 --- a/extensions/amavis_quarantine/main.py +++ b/extensions/amavis_quarantine/main.py @@ -5,7 +5,8 @@ from django.conf.urls.defaults import * from django.utils.translation import ugettext as _, ungettext from django.core.urlresolvers import reverse -from modoboa.lib import events, parameters, static_url +from modoboa.lib import events, parameters +from modoboa.lib.webutils import static_url def infos(): return { diff --git a/extensions/amavis_quarantine/sql_listing.py b/extensions/amavis_quarantine/sql_listing.py index 0f5572f1e..3a9cf9295 100644 --- a/extensions/amavis_quarantine/sql_listing.py +++ b/extensions/amavis_quarantine/sql_listing.py @@ -3,7 +3,8 @@ from datetime import datetime from django.utils.translation import ugettext as _ from django.db.models import Q -from modoboa.lib import tables, static_url +from modoboa.lib import tables +from modoboa.lib.webutils import static_url from modoboa.lib.email_listing import MBconnector, EmailListing from modoboa.lib.emailutils import * from modoboa.admin.lib import is_domain_admin diff --git a/extensions/amavis_quarantine/templatetags/amextras.py b/extensions/amavis_quarantine/templatetags/amextras.py index 56996dd76..6618d139e 100644 --- a/extensions/amavis_quarantine/templatetags/amextras.py +++ b/extensions/amavis_quarantine/templatetags/amextras.py @@ -3,7 +3,7 @@ from django.template.loader import render_to_string from django.utils.translation import ugettext as _ from django.core.urlresolvers import reverse from django.conf import settings -from modoboa.lib import static_url +from modoboa.lib.webutils import static_url from modoboa.extensions import amavis_quarantine from modoboa.admin.lib import is_domain_admin diff --git a/extensions/amavis_quarantine/views.py b/extensions/amavis_quarantine/views.py index b9630077b..2b3a73210 100644 --- a/extensions/amavis_quarantine/views.py +++ b/extensions/amavis_quarantine/views.py @@ -9,13 +9,14 @@ from django.core.urlresolvers import reverse from django.contrib.auth.decorators \ import login_required from django.db.models import Q -from modoboa.lib import parameters, _render, getctx, ajax_response +from modoboa.lib import parameters +from modoboa.lib.webutils import _render, getctx, ajax_response from modoboa.admin.models import Mailbox from lib import AMrelease from templatetags.amextras import * from modoboa.lib.email_listing import parse_search_parameters from sql_listing import * -from admin.lib import is_domain_admin +from modoboa.admin.lib import is_domain_admin def __get_current_url(request): if request.session.has_key("page"): diff --git a/extensions/postfix_autoreply/main.py b/extensions/postfix_autoreply/main.py index f4bd8ff89..ca4ba700d 100644 --- a/extensions/postfix_autoreply/main.py +++ b/extensions/postfix_autoreply/main.py @@ -10,7 +10,8 @@ functionality into Postfix. from django.conf.urls.defaults import include from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _ -from modoboa.lib import events, parameters, static_url +from modoboa.lib import events, parameters +from modoboa.lib.webutils import static_url from models import * def infos(): diff --git a/extensions/postfix_autoreply/migrations/0002_auto__add_armessage__add_arhistoric.py b/extensions/postfix_autoreply/migrations/0002_auto__add_armessage__add_arhistoric.py index 5a7fe478f..0f816e834 100644 --- a/extensions/postfix_autoreply/migrations/0002_auto__add_armessage__add_arhistoric.py +++ b/extensions/postfix_autoreply/migrations/0002_auto__add_armessage__add_arhistoric.py @@ -3,7 +3,7 @@ import datetime from south.db import db from south.v2 import SchemaMigration from django.db import models -from modoboa.lib import db_table_exists +from modoboa.lib.dbutils import db_table_exists class Migration(SchemaMigration): diff --git a/extensions/postfix_autoreply/views.py b/extensions/postfix_autoreply/views.py index 580076fc0..abd67f25f 100644 --- a/extensions/postfix_autoreply/views.py +++ b/extensions/postfix_autoreply/views.py @@ -7,7 +7,8 @@ from django.contrib.auth.decorators \ from django.contrib import messages from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _ -from modoboa.lib import _render, ajax_response, is_not_localadmin +from modoboa.lib.webutils import _render, ajax_response +from modoboa.admin.lib import is_not_localadmin from forms import * from models import * diff --git a/extensions/sievefilters/main.py b/extensions/sievefilters/main.py index d43c0e1a1..a753bcddf 100644 --- a/extensions/sievefilters/main.py +++ b/extensions/sievefilters/main.py @@ -2,7 +2,8 @@ from django.utils.translation import ugettext as _ from django.core.urlresolvers import reverse from django.conf.urls.defaults import include -from modoboa.lib import events, parameters, static_url +from modoboa.lib import events, parameters +from modoboa.lib.webutils import static_url from sievelib.managesieve import SUPPORTED_AUTH_MECHS def init(): diff --git a/extensions/sievefilters/templatetags/sfilters_tags.py b/extensions/sievefilters/templatetags/sfilters_tags.py index c924b346f..10e5ac0a9 100644 --- a/extensions/sievefilters/templatetags/sfilters_tags.py +++ b/extensions/sievefilters/templatetags/sfilters_tags.py @@ -3,7 +3,7 @@ from django.template.loader import render_to_string from django.utils.translation import ugettext as _ from django.core.urlresolvers import reverse from modoboa.extensions.sievefilters import views -from modoboa.lib import render_actions +from modoboa.lib.webutils import render_actions register = template.Library() diff --git a/extensions/sievefilters/views.py b/extensions/sievefilters/views.py index 51adf8b01..f39fd0f83 100644 --- a/extensions/sievefilters/views.py +++ b/extensions/sievefilters/views.py @@ -4,8 +4,10 @@ from django.http import HttpResponse from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ from django.core.urlresolvers import reverse -from modoboa.lib import _render, _render_to_string, _render_error, \ - ajax_response, ajax_simple_response, is_not_localadmin, parameters +from modoboa.lib import parameters +from modoboa.lib.webutils import _render, _render_to_string, _render_error, \ + ajax_response, ajax_simple_response +from modoboa.admin.lib import is_not_localadmin from modoboa.lib.connections import ConnectionError from modoboa.auth.lib import get_password from lib import * diff --git a/extensions/stats/main.py b/extensions/stats/main.py index 3372e4e42..1a11ffa3a 100644 --- a/extensions/stats/main.py +++ b/extensions/stats/main.py @@ -10,7 +10,8 @@ sent, received, bounced, rejected from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _ from django.conf.urls.defaults import * -from modoboa.lib import events, parameters, static_url +from modoboa.lib import events, parameters +from modoboa.lib.webutils import static_url def infos(): return { diff --git a/extensions/stats/views.py b/extensions/stats/views.py index ecb933ae5..0abe10575 100644 --- a/extensions/stats/views.py +++ b/extensions/stats/views.py @@ -4,7 +4,7 @@ from django.http import HttpResponse from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _ from django.utils import simplejson -from modoboa.lib import _render, _render_to_string, getctx +from modoboa.lib.webutils import _render, _render_to_string, getctx from modoboa.admin.views import good_domain from modoboa.admin.models import Domain, Mailbox from django.contrib.auth.decorators \ diff --git a/extensions/webmail/lib.py b/extensions/webmail/lib.py index 1e05fa761..f1c5c50b5 100644 --- a/extensions/webmail/lib.py +++ b/extensions/webmail/lib.py @@ -14,8 +14,8 @@ import email import lxml from django.utils.translation import ugettext as _ from django.conf import settings -from modoboa.lib import decode, u2u_decode, tables, \ - imap_utf7, static_url, parameters +from modoboa.lib import u2u_decode, tables, imap_utf7, parameters +from modoboa.lib.webutils import static_url from modoboa.lib.connections import ConnectionsManager from modoboa.lib.email_listing import MBconnector, EmailListing from modoboa.lib.emailutils import * diff --git a/extensions/webmail/main.py b/extensions/webmail/main.py index 88d6adf1c..77a86ec60 100644 --- a/extensions/webmail/main.py +++ b/extensions/webmail/main.py @@ -2,7 +2,8 @@ from django.utils.translation import ugettext as _ from django.core.urlresolvers import reverse from django.conf.urls.defaults import include -from modoboa.lib import events, parameters, static_url +from modoboa.lib import events, parameters +from modoboa.lib.webutils import static_url def init(): events.register("UserMenuDisplay", menu) diff --git a/extensions/webmail/middleware.py b/extensions/webmail/middleware.py index 2b3bd5089..528f65a99 100644 --- a/extensions/webmail/middleware.py +++ b/extensions/webmail/middleware.py @@ -1,6 +1,6 @@ # coding: utf-8 -from modoboa.lib import ajax_response +from modoboa.lib.webutils import ajax_response from modoboa.extensions.webmail.lib import WebmailError class WebmailErrorMiddleware(object): diff --git a/extensions/webmail/templatetags/webextras.py b/extensions/webmail/templatetags/webextras.py index 92feb0a69..7c8dd1fd4 100644 --- a/extensions/webmail/templatetags/webextras.py +++ b/extensions/webmail/templatetags/webextras.py @@ -5,7 +5,8 @@ from django.core.urlresolvers import reverse from django.conf import settings from modoboa.extensions import webmail from modoboa.extensions.webmail.lib import IMAPheader -from modoboa.lib import parameters, static_url +from modoboa.lib import parameters +from modoboa.lib.webutils import static_url register = template.Library() diff --git a/extensions/webmail/views.py b/extensions/webmail/views.py index edf8acb92..e916375a3 100644 --- a/extensions/webmail/views.py +++ b/extensions/webmail/views.py @@ -10,11 +10,12 @@ from django.core.urlresolvers import reverse from django.contrib.auth.decorators import login_required from django.contrib import messages from modoboa.admin.models import Mailbox -from modoboa.lib import parameters, _render, _render_error, \ - getctx, is_not_localadmin, _render_to_string, \ - ajax_response +from modoboa.lib import parameters +from modoboa.lib.webutils import _render, _render_error, \ + getctx, _render_to_string, ajax_response from modoboa.lib.emailutils import split_mailbox from modoboa.lib.email_listing import parse_search_parameters, Paginator +from modoboa.admin.lib import is_not_localadmin from modoboa.auth.lib import * from lib import * from forms import * diff --git a/lib/__init__.py b/lib/__init__.py index 27999c802..e69de29bb 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -1,199 +0,0 @@ -# -*- coding: utf-8 -*- -import os -import sys -import time -import hashlib, crypt, string -from random import Random -from django.http import HttpResponse -from django.conf import settings -from django import template -from django.shortcuts import render_to_response -from django.template.loader import render_to_string -from django.utils.translation import ugettext as _ -from django.utils import simplejson -from modoboa.lib import parameters - -def exec_cmd(cmd, **kwargs): - import subprocess - - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, **kwargs) - output = p.communicate()[0] - return p.returncode, output - -def _render(request, tpl, user_context): - """Custom rendering function - - Just a wrapper which automatically adds a RequestContext instance - (useful to use settings variables like MEDIA_URL inside templates) - """ - return render_to_response(tpl, user_context, - context_instance=template.RequestContext(request)) - -def _render_to_string(request, tpl, user_context): - """Custom rendering function - - Same as _render. - """ - return render_to_string(tpl, user_context, - context_instance=template.RequestContext(request)) - -def _render_error(request, errortpl="error", user_context={}): - return render_to_response("common/%s.html" % errortpl, user_context, - context_instance=template.RequestContext(request)) - -def render_actions(actions): - t = template.Template(""" -{% for a in actions %} - - - -{% endfor %} -""") - return t.render(template.Context({ - "actions" : actions - })) - -def exec_as_vuser(cmd): - code, output = exec_cmd("sudo -u %s %s" \ - % (parameters.get_admin("VIRTUAL_UID", app="admin"), cmd)) - if code: - exec_cmd("echo '%s' >> /tmp/vmail.log" % output) - return False - return True - -def _ctx_ok(url): - return {"status" : "ok", "url" : url} - -def _ctx_ko(tpl, ctx): - return {"status" : "ko", "content" : render_to_string(tpl, ctx)} - -def static_url(path): - """Returns the correct static url for a given file - - :param path: the targeted static media - """ - if path.startswith("/"): - path = path[1:] - return "%s%s" % (settings.MEDIA_URL, path) - -def getctx(status, level=1, callback=None, **kwargs): - if not callback: - callername = sys._getframe(level).f_code.co_name - else: - callername = callback - ctx = {"status" : status, "callback" : callername} - for kw, v in kwargs.iteritems(): - ctx[kw] = v - return ctx - -def ajax_response(request, status="ok", respmsg=None, - url="", ajaxnav=False, norefresh=False, - template=None, **kwargs): - """Ajax response shortcut - - Simple shortcut that sends an JSON response. If a template is - provided, a 'content' field will be added to the response, - containing the result of this template rendering. - - :param request: a request object - :param status: the response status ('ok' or 'ko) - :param nexturl: url to display after receiving this response - :param template: eventual template's path - :param kwargs: dict used for template rendering - """ - ctx = {} - for k, v in kwargs.iteritems(): - ctx[k] = v - if template is not None: - content = _render_to_string(request, template, ctx) - elif kwargs.has_key("content"): - content = kwargs["content"] - else: - content = "" - jsonctx = {"status" : status, "content" : content} - if respmsg is not None: - jsonctx["respmsg"] = respmsg - if ajaxnav: - jsonctx["ajaxnav"] = True - if url != "": - jsonctx["url"] = url - jsonctx["norefresh"] = norefresh - return HttpResponse(simplejson.dumps(jsonctx), mimetype="application/json") - -def ajax_simple_response(content): - """Simple AJAX response - - No extra formatting is done. The content is passed directly to simplejon. - - :param content: the response's content (list, dict, string) - """ - return HttpResponse(simplejson.dumps(content), mimetype="application/json") - -def decode(s, encodings=('utf8', 'latin1', 'windows-1252', 'ascii'), charset=None): - if charset is not None: - try: - return s.decode(charset, 'ignore') - except LookupError: - pass - - for encoding in encodings: - try: - return s.decode(encoding) - except UnicodeDecodeError: - pass - return s.decode('ascii', 'ignore') - -def is_not_localadmin(errortpl="error"): - def dec(f): - def wrapped_f(request, *args, **kwargs): - if request.user.id == 1: - return _render_error(request, errortpl, { - "error" : _("Invalid action, %(user)s is a local user" \ - % {"user" : request.user.username}) - }) - return f(request, *args, **kwargs) - - wrapped_f.__name__ = f.__name__ - wrapped_f.__dict__ = f.__dict__ - wrapped_f.__doc__ = f.__doc__ - wrapped_f.__module__ = f.__module__ - return wrapped_f - return dec - -def db_table_exists(table, cursor=None): - """Check if table exists - - Taken from here: - https://gist.github.com/527113/307c2dec09ceeb647b8fa1d6d49591f3352cb034 - - """ - try: - if not cursor: - from django.db import connection - cursor = connection.cursor() - if not cursor: - raise Exception - table_names = connection.introspection.get_table_list(cursor) - except: - raise Exception("unable to determine if the table '%s' exists" % table) - else: - return table in table_names - -def _check_password(password, crypted): - scheme = parameters.get_admin("PASSWORD_SCHEME", app="admin") - if scheme == "crypt": - return crypt.crypt(password, crypted) == crypted - if scheme == "md5": - return hashlib.md5(password).hexdigest() == crypted - return password - -def crypt_password(password): - scheme = parameters.get_admin("PASSWORD_SCHEME", app="admin") - if scheme == "crypt": - salt = ''.join(Random().sample(string.letters + string.digits, 2)) - return crypt.crypt(password, salt) - if scheme == "md5": - return hashlib.md5(password).hexdigest() - return password - diff --git a/lib/authbackends.py b/lib/authbackends.py index c2fafa886..d49235ccd 100644 --- a/lib/authbackends.py +++ b/lib/authbackends.py @@ -1,6 +1,6 @@ from django.contrib.auth.models import User from modoboa.admin.models import Mailbox -from modoboa.lib import _check_password +from modoboa.auth.lib import _check_password class SimpleBackend: diff --git a/lib/dbutils.py b/lib/dbutils.py new file mode 100644 index 000000000..738b9f6a6 --- /dev/null +++ b/lib/dbutils.py @@ -0,0 +1,20 @@ +# coding: utf-8 +from django.db import connection + +def db_table_exists(table, cursor=None): + """Check if table exists + + Taken from here: + https://gist.github.com/527113/307c2dec09ceeb647b8fa1d6d49591f3352cb034 + + """ + try: + if not cursor: + cursor = connection.cursor() + if not cursor: + raise Exception + table_names = connection.introspection.get_table_list(cursor) + except: + raise Exception("unable to determine if the table '%s' exists" % table) + else: + return table in table_names diff --git a/lib/email_listing.py b/lib/email_listing.py index 0bfbdab89..f85201f11 100644 --- a/lib/email_listing.py +++ b/lib/email_listing.py @@ -9,7 +9,8 @@ from django.conf import settings from django.template.loader import render_to_string from django.template import Template, Context from django.utils.translation import ugettext as _ -from modoboa.lib import _render, decode +from modoboa.lib.webutils import _render +from modoboa.lib.emailutils import decode attached_map = {} diff --git a/lib/emailutils.py b/lib/emailutils.py index ed7bfbfa0..2a6f0102d 100644 --- a/lib/emailutils.py +++ b/lib/emailutils.py @@ -7,7 +7,6 @@ import lxml from django.template import Template, Context from django.template.loader import render_to_string import u2u_decode -from modoboa.lib import decode class EmailAddress(object): def __init__(self, address): @@ -196,3 +195,17 @@ def split_mailbox(mailbox): domain = parts[-1] address = "@".join(parts[:-1]) return (address, domain) + +def decode(s, encodings=('utf8', 'latin1', 'windows-1252', 'ascii'), charset=None): + if charset is not None: + try: + return s.decode(charset, 'ignore') + except LookupError: + pass + + for encoding in encodings: + try: + return s.decode(encoding) + except UnicodeDecodeError: + pass + return s.decode('ascii', 'ignore') diff --git a/lib/models.py b/lib/models.py index 03098b980..9e58b5ace 100644 --- a/lib/models.py +++ b/lib/models.py @@ -6,6 +6,6 @@ class Parameter(models.Model): value = models.CharField(max_length=255) class UserParameter(models.Model): - user = models.ForeignKey(User) + user = models.ForeignKey("auth.User") name = models.CharField(max_length=255) value = models.CharField(max_length=255) diff --git a/lib/parameters.py b/lib/parameters.py index f6ba8c127..8134f6e85 100644 --- a/lib/parameters.py +++ b/lib/parameters.py @@ -3,7 +3,6 @@ import string import inspect import re -from modoboa.lib.models import * """ This interface provides a simple way to declare and store parameters @@ -76,6 +75,8 @@ def unregister_app(app): return True def save_admin(name, value, app=None): + from models import Parameter + if app is None: app = __guess_extension() __is_defined(app, 'A', name) @@ -91,6 +92,8 @@ def save_admin(name, value, app=None): return True def save_user(user, name, value, app=None): + from models import UserParameter + if app is None: app = __guess_extension() __is_defined(app, 'U', name) @@ -107,6 +110,8 @@ def save_user(user, name, value, app=None): return True def get_admin(name, app=None): + from models import Parameter + if app is None: app = __guess_extension() __is_defined(app, "A", name) @@ -117,6 +122,8 @@ def get_admin(name, app=None): return p.value.decode("string_escape") def get_user(user, name, app=None): + from models import UserParameter + if app is None: app = __guess_extension() __is_defined(app, "U", name) diff --git a/lib/sysutils.py b/lib/sysutils.py new file mode 100644 index 000000000..efa73c957 --- /dev/null +++ b/lib/sysutils.py @@ -0,0 +1,23 @@ +# coding: utf-8 + +""" +This module extra functions/shortcuts to communicate with the system +(executing commands, etc.) +""" + +from modoboa.lib import parameters + +def exec_cmd(cmd, **kwargs): + import subprocess + + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, **kwargs) + output = p.communicate()[0] + return p.returncode, output + +def exec_as_vuser(cmd): + code, output = exec_cmd("sudo -u %s %s" \ + % (parameters.get_admin("VIRTUAL_UID", app="admin"), cmd)) + if code: + exec_cmd("echo '%s' >> /tmp/vmail.log" % output) + return False + return True diff --git a/lib/templatetags/libextras.py b/lib/templatetags/libextras.py index 1fa90af2c..ed04ba605 100644 --- a/lib/templatetags/libextras.py +++ b/lib/templatetags/libextras.py @@ -3,7 +3,7 @@ import os from django.conf import settings from django import template from django.contrib import messages -from modoboa.lib import exec_cmd +from modoboa.lib.sysutils import exec_cmd register = template.Library() diff --git a/lib/webutils.py b/lib/webutils.py new file mode 100644 index 000000000..a05380bc1 --- /dev/null +++ b/lib/webutils.py @@ -0,0 +1,114 @@ +# coding: utf-8 + +""" +This module contains extra functions/shortcuts used to render HTML. +""" +import sys +from django.http import HttpResponse +from django.shortcuts import render_to_response +from django.template.loader import render_to_string +from django import template +from django.utils import simplejson +from django.conf import settings + +def _render(request, tpl, user_context): + """Custom rendering function + + Just a wrapper which automatically adds a RequestContext instance + (useful to use settings variables like MEDIA_URL inside templates) + """ + return render_to_response(tpl, user_context, + context_instance=template.RequestContext(request)) + +def _render_to_string(request, tpl, user_context): + """Custom rendering function + + Same as _render. + """ + return render_to_string(tpl, user_context, + context_instance=template.RequestContext(request)) + +def _render_error(request, errortpl="error", user_context={}): + return render_to_response("common/%s.html" % errortpl, user_context, + context_instance=template.RequestContext(request)) + +def render_actions(actions): + t = template.Template(""" +{% for a in actions %} + + + +{% endfor %} +""") + return t.render(template.Context({ + "actions" : actions + })) + +def _ctx_ok(url): + return {"status" : "ok", "url" : url} + +def _ctx_ko(tpl, ctx): + return {"status" : "ko", "content" : render_to_string(tpl, ctx)} + +def getctx(status, level=1, callback=None, **kwargs): + if not callback: + callername = sys._getframe(level).f_code.co_name + else: + callername = callback + ctx = {"status" : status, "callback" : callername} + for kw, v in kwargs.iteritems(): + ctx[kw] = v + return ctx + +def ajax_response(request, status="ok", respmsg=None, + url="", ajaxnav=False, norefresh=False, + template=None, **kwargs): + """Ajax response shortcut + + Simple shortcut that sends an JSON response. If a template is + provided, a 'content' field will be added to the response, + containing the result of this template rendering. + + :param request: a request object + :param status: the response status ('ok' or 'ko) + :param nexturl: url to display after receiving this response + :param template: eventual template's path + :param kwargs: dict used for template rendering + """ + ctx = {} + for k, v in kwargs.iteritems(): + ctx[k] = v + if template is not None: + content = _render_to_string(request, template, ctx) + elif kwargs.has_key("content"): + content = kwargs["content"] + else: + content = "" + jsonctx = {"status" : status, "content" : content} + if respmsg is not None: + jsonctx["respmsg"] = respmsg + if ajaxnav: + jsonctx["ajaxnav"] = True + if url != "": + jsonctx["url"] = url + jsonctx["norefresh"] = norefresh + return HttpResponse(simplejson.dumps(jsonctx), mimetype="application/json") + +def ajax_simple_response(content): + """Simple AJAX response + + No extra formatting is done. The content is passed directly to simplejon. + + :param content: the response's content (list, dict, string) + """ + return HttpResponse(simplejson.dumps(content), mimetype="application/json") + +def static_url(path): + """Returns the correct static url for a given file + + :param path: the targeted static media + """ + if path.startswith("/"): + path = path[1:] + return "%s%s" % (settings.MEDIA_URL, path) diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po index a42f01d4a..613995c20 100644 --- a/locale/de/LC_MESSAGES/django.po +++ b/locale/de/LC_MESSAGES/django.po @@ -5,7 +5,7 @@ # Patrick Ben Koetter , 2010-2011. msgid "" msgstr "" -"Project-Id-Version: Modoboa-0.8.5\n" +"Project-Id-Version: Modoboa-0.8.6\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2011-08-25 09:53+0200\n" "PO-Revision-Date: 2011-08-25 13:03+0100\n" diff --git a/locale/de/LC_MESSAGES/djangojs.po b/locale/de/LC_MESSAGES/djangojs.po index 3e2db2121..31201d7fb 100644 --- a/locale/de/LC_MESSAGES/djangojs.po +++ b/locale/de/LC_MESSAGES/djangojs.po @@ -5,7 +5,7 @@ # Patrick Ben Koetter , 2010-2011. msgid "" msgstr "" -"Project-Id-Version: Modoboa-0.8.5\n" +"Project-Id-Version: Modoboa-0.8.6\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2011-08-25 09:58+0200\n" "PO-Revision-Date: 2011-07-10 07:30+0000\n" diff --git a/tools/pfxadmin_migrate/migrate.py b/tools/pfxadmin_migrate/migrate.py index a5a1140ba..0bce33811 100755 --- a/tools/pfxadmin_migrate/migrate.py +++ b/tools/pfxadmin_migrate/migrate.py @@ -48,7 +48,7 @@ from django.db.models import Q from django.contrib.auth.models import Group import modoboa.admin.models as md_models import models as pf_models -from modoboa.lib import exec_cmd +from modoboa.lib.sysutils import exec_cmd from modoboa.lib.emailutils import split_mailbox def migrate_dates(oldobj): diff --git a/userprefs/forms.py b/userprefs/forms.py index 72c987f2d..ec6196d15 100644 --- a/userprefs/forms.py +++ b/userprefs/forms.py @@ -1,6 +1,6 @@ from django import forms from modoboa.admin.models import Domain, Mailbox -from modoboa.lib import _check_password +from modoboa.auth.lib import _check_password from django.contrib.auth.models import check_password from django.utils.translation import ugettext as _ from modoboa.lib.emailutils import split_mailbox diff --git a/userprefs/templatetags/uprefs_extras.py b/userprefs/templatetags/uprefs_extras.py index 9a844f754..3c34858a3 100644 --- a/userprefs/templatetags/uprefs_extras.py +++ b/userprefs/templatetags/uprefs_extras.py @@ -3,7 +3,8 @@ from django.template.loader import render_to_string from django.utils.translation import ugettext as _ from django.core.urlresolvers import reverse from modoboa import userprefs -from modoboa.lib import events, static_url +from modoboa.lib import events +from modoboa.lib.webutils import static_url from modoboa.admin.lib import is_domain_admin register = template.Library() diff --git a/userprefs/views.py b/userprefs/views.py index 26bb61c7b..cab96d0c5 100644 --- a/userprefs/views.py +++ b/userprefs/views.py @@ -4,12 +4,12 @@ from django.http import HttpResponseRedirect from django.contrib.auth.decorators \ import login_required, user_passes_test from django.utils.translation import ugettext as _ -from modoboa.lib import _render, ajax_response, parameters -from modoboa.lib import crypt_password +from modoboa.lib import parameters +from modoboa.lib.webutils import _render, ajax_response from forms import * from modoboa.admin.models import Mailbox, Alias from modoboa.admin.lib import is_domain_admin -from modoboa.auth.lib import encrypt +from modoboa.auth.lib import encrypt, crypt_password @login_required def index(request):