mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-18 05:51:26 +02:00
This commit adds the following features: * Folder creation, * Folder modification, * Folder removal. There are still issues with subfolders but they should not be too complicated to fix. I've also done some javascript refactoring.
191 lines
6.0 KiB
Python
191 lines
6.0 KiB
Python
# -*- 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.template import RequestContext
|
|
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=RequestContext(request))
|
|
|
|
def _render_to_string(request, tpl, user_context):
|
|
"""Custom rendering function
|
|
|
|
Same a mrender_render.
|
|
"""
|
|
return render_to_string(tpl, user_context,
|
|
context_instance=RequestContext(request))
|
|
|
|
def _render_error(request, errortpl="error", user_context={}):
|
|
return render_to_response("common/%s.html" % errortpl, user_context,
|
|
context_instance=RequestContext(request))
|
|
|
|
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", url="", ajaxnav=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)
|
|
else:
|
|
content = ""
|
|
jsonctx = {"status" : status, "content" : content}
|
|
if ajaxnav:
|
|
jsonctx["ajaxnav"] = True
|
|
else:
|
|
jsonctx["url"] = url
|
|
return HttpResponse(simplejson.dumps(jsonctx), 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
|
|
|
|
class Singleton(type):
|
|
def __init__(cls, name, bases, dict):
|
|
super(Singleton, cls).__init__(name, bases, dict)
|
|
cls.instance = None
|
|
|
|
def __call__(cls, *args, **kwargs):
|
|
if cls.instance is None:
|
|
cls.instance = super(Singleton, cls).__call__(*args, **kwargs)
|
|
return cls.instance
|
|
|
|
|
|
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
|
|
|
|
def split_mailbox(mailbox):
|
|
parts = mailbox.split('@')
|
|
if len(parts) == 2:
|
|
address = parts[0]
|
|
domain = parts[1]
|
|
else:
|
|
domain = parts[-1]
|
|
address = "@".join(parts[:-1])
|
|
return (address, domain)
|