mirror of
https://github.com/marcus-alicia/iRedAdmin-Pro-SQL.git
synced 2026-05-26 07:08:10 +00:00
Update to 5.4
This commit is contained in:
@@ -1,3 +1,14 @@
|
||||
# 5.4
|
||||
* RESTful API:
|
||||
+ `GET /api/users/<domain>`: Export used quota info.
|
||||
|
||||
* Fixed issues:
|
||||
- [API] Disabling domain causes losing inbound BCC email address.
|
||||
- Can not save few per-admin privileges.
|
||||
- Not respect server wide min/max password lengths while adding new user.
|
||||
- tools/cleanup_amavisd_db.py: Can not clean up old SQL records if
|
||||
column "quar_type" value is null.
|
||||
|
||||
# 5.3
|
||||
+ Ship Python module web.py (github.com/webpy/webpy, public domain).
|
||||
* RESTful API:
|
||||
|
||||
16
EULA
Normal file
16
EULA
Normal file
@@ -0,0 +1,16 @@
|
||||
* What's included within iRedAdmin-Pro license
|
||||
|
||||
- Free upgrade with valid license.
|
||||
|
||||
* Restrictions
|
||||
|
||||
- One license per server. Customer must purchase license for each server.
|
||||
|
||||
- Customer has to renew the license of iRedAdmin-Pro to continue using
|
||||
iRedAdmin-Pro before license expired.
|
||||
|
||||
- After license expired, customer has to purchase a new license to continue
|
||||
using iRedAdmin-Pro.
|
||||
|
||||
- NOT allowed to redistribute and/or resell original iRedAdmin-Pro source
|
||||
code and the copy you modified based on iRedAdmin-Pro.
|
||||
0
controllers/sql/urls.py
Normal file → Executable file
0
controllers/sql/urls.py
Normal file → Executable file
Binary file not shown.
@@ -9,11 +9,11 @@ msgstr ""
|
||||
"Last-Translator: Shafeek SUMSER <shafeeks@gmail.com>\n"
|
||||
"Language: fr_FR\n"
|
||||
"Language-Team: fr_FR <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.3.4\n"
|
||||
"Generated-By: Babel 2.11.0\n"
|
||||
|
||||
#, python-format
|
||||
msgid "%d admin(s) found."
|
||||
@@ -118,7 +118,7 @@ msgid "Account is disabled."
|
||||
msgstr "Compte désactivé."
|
||||
|
||||
msgid "Account is domain admin"
|
||||
msgstr "Compte désactivé."
|
||||
msgstr "Compte administrateur du domaine."
|
||||
|
||||
msgid "Account is global admin"
|
||||
msgstr "Le compte est un administrateur global."
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
__author__ = "Zhang Huangbin"
|
||||
__author_mail__ = "zhb@iredmail.org"
|
||||
__version_ldap__ = "5.4"
|
||||
__version_sql__ = "5.3"
|
||||
__version_ldap__ = "5.5"
|
||||
__version_sql__ = "5.4"
|
||||
__url_license_terms__ = "http://www.iredmail.org/pricing.html#EULA"
|
||||
|
||||
@@ -7,30 +7,36 @@ from libs import iredutils
|
||||
# - Amavisd-new-2.6.x: [ A-Z, a-z, 0-9, +, - ]
|
||||
MAIL_ID_CHARACTERS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-_'
|
||||
|
||||
WBLIST_FORM_INPUT_NAMES = {'wl_sender': 'whitelistSender',
|
||||
'bl_sender': 'blacklistSender',
|
||||
'wl_rcpt': 'whitelistRecipient',
|
||||
'bl_rcpt': 'blacklistRecipient'}
|
||||
WBLIST_FORM_INPUT_NAMES = {
|
||||
'wl_sender': 'whitelistSender',
|
||||
'bl_sender': 'blacklistSender',
|
||||
'wl_rcpt': 'whitelistRecipient',
|
||||
'bl_rcpt': 'blacklistRecipient',
|
||||
}
|
||||
|
||||
# Available quarantined types in iRedAdmin web interface, and the short code
|
||||
# in `amavisd.msgs` sql table.
|
||||
QUARANTINE_TYPES = {'spam': 'S',
|
||||
'virus': 'V',
|
||||
'banned': 'B',
|
||||
'clean': 'C',
|
||||
'badheader': 'H',
|
||||
'badmime': 'M'}
|
||||
QUARANTINE_TYPES = {
|
||||
'spam': 'S',
|
||||
'virus': 'V',
|
||||
'banned': 'B',
|
||||
'clean': 'C',
|
||||
'badheader': 'H',
|
||||
'badmime': 'M',
|
||||
}
|
||||
|
||||
# Value of `msgs.content` and comment.
|
||||
CONTENT_TYPES = {'B': 'Banned',
|
||||
'C': 'Clean',
|
||||
'H': 'Bad header',
|
||||
'M': 'Bad mime',
|
||||
'O': 'Oversized',
|
||||
'S': 'Spam',
|
||||
'T': 'MTA error',
|
||||
'V': 'Virus',
|
||||
'U': 'Unchecked'}
|
||||
CONTENT_TYPES = {
|
||||
'B': 'Banned',
|
||||
'C': 'Clean',
|
||||
'H': 'Bad header',
|
||||
'M': 'Bad mime',
|
||||
'O': 'Oversized',
|
||||
'S': 'Spam',
|
||||
'T': 'MTA error',
|
||||
'V': 'Virus',
|
||||
'U': 'Unchecked',
|
||||
}
|
||||
|
||||
|
||||
def get_wblist_from_form(form, form_input_name):
|
||||
|
||||
@@ -98,7 +98,7 @@ def get_quarantined_mails(page=1,
|
||||
elif account_type == 'user':
|
||||
if session.get('is_normal_admin'):
|
||||
# Make sure account is under managed domains
|
||||
if not account.split('@', 1)[-1] in all_domains:
|
||||
if account.split('@', 1)[-1] not in all_domains:
|
||||
# PERMISSION_DENIED
|
||||
return True, (0, {})
|
||||
elif session.get('account_is_mail_user'):
|
||||
|
||||
@@ -371,7 +371,7 @@ def get_account_status(form,
|
||||
to_integer=False):
|
||||
status = get_single_value(form, input_name=input_name, to_string=True)
|
||||
|
||||
if not (status in ['active', 'disabled']):
|
||||
if status not in ['active', 'disabled']:
|
||||
status = default_value
|
||||
|
||||
# SQL backends store the account status as `active=[1|0]`
|
||||
|
||||
@@ -31,7 +31,7 @@ def delete_throttle_setting(account, inout_type):
|
||||
if not iredutils.is_valid_amavisd_address(account):
|
||||
return False, 'INVALID_ACCOUNT'
|
||||
|
||||
if not (inout_type in ['inbound', 'outbound']):
|
||||
if inout_type not in ['inbound', 'outbound']:
|
||||
return False, 'INVALID_INOUT_TYPE'
|
||||
|
||||
if account and inout_type:
|
||||
|
||||
0
libs/iredbase.py
Normal file → Executable file
0
libs/iredbase.py
Normal file → Executable file
@@ -677,7 +677,7 @@ def generate_random_strings(length=10) -> str:
|
||||
"23456789"
|
||||
|
||||
s = ""
|
||||
for x in range(length):
|
||||
for _ in range(length):
|
||||
s += random.choice(chars)
|
||||
|
||||
return s
|
||||
|
||||
0
libs/l10n.py
Normal file → Executable file
0
libs/l10n.py
Normal file → Executable file
@@ -52,7 +52,11 @@ def list_logs(event='all', domain='all', admin='all', cur_page=1):
|
||||
listed_only=True,
|
||||
conn=None)
|
||||
if qr[0]:
|
||||
sql_vars["managed_domains"] = qr[1]
|
||||
managed_domains = qr[1]
|
||||
if not managed_domains:
|
||||
return 0, []
|
||||
|
||||
sql_vars["managed_domains"] = managed_domains
|
||||
sql_wheres += ["domain IN $managed_domains"]
|
||||
else:
|
||||
return qr
|
||||
|
||||
@@ -1129,7 +1129,7 @@ def update(conn, mail, profile_type, form):
|
||||
# If marked as normal domain admin, allow to create new domains
|
||||
#
|
||||
if 'allowed_to_create_domain' in form:
|
||||
_new_settings = {'create_new_domains': 'yes'}
|
||||
_new_settings['create_new_domains'] = 'yes'
|
||||
|
||||
for i in ['create_max_domains',
|
||||
'create_max_quota',
|
||||
@@ -2257,14 +2257,17 @@ def get_basic_user_profiles(domain,
|
||||
|
||||
for row in rows:
|
||||
email = row.username
|
||||
used_bytes = 0
|
||||
used_messages = 0
|
||||
_bytes = 0
|
||||
_messages = 0
|
||||
|
||||
if email in used_quota_info:
|
||||
used_bytes = used_quota_info[email]["bytes"]
|
||||
used_messages = used_quota_info[email]["messages"]
|
||||
_bytes = used_quota_info[email]["bytes"]
|
||||
_messages = used_quota_info[email]["messages"]
|
||||
|
||||
row["used_quota"] = {"bytes": used_bytes, "messages": used_messages}
|
||||
row["used_quota"] = {
|
||||
"bytes": _bytes,
|
||||
"messages": _messages,
|
||||
}
|
||||
|
||||
return True, rows
|
||||
except Exception as e:
|
||||
|
||||
@@ -264,7 +264,7 @@ def search(search_string,
|
||||
|
||||
# Add new, remove duplicate records.
|
||||
for i in _records:
|
||||
if not (i in result['user']):
|
||||
if i not in result['user']:
|
||||
result['user'] += [i]
|
||||
|
||||
if qr_user_forwarding:
|
||||
@@ -272,7 +272,7 @@ def search(search_string,
|
||||
|
||||
# Add new, remove duplicate records.
|
||||
for i in _records:
|
||||
if not (i in result['user']):
|
||||
if i not in result['user']:
|
||||
result['user'] += [i]
|
||||
|
||||
# Get email addresses of returned user accounts
|
||||
|
||||
0
rc_scripts/iredadmin.debian
Normal file → Executable file
0
rc_scripts/iredadmin.debian
Normal file → Executable file
0
rc_scripts/iredadmin.freebsd
Normal file → Executable file
0
rc_scripts/iredadmin.freebsd
Normal file → Executable file
0
rc_scripts/iredadmin.openbsd
Normal file → Executable file
0
rc_scripts/iredadmin.openbsd
Normal file → Executable file
0
rc_scripts/iredadmin.rhel
Normal file → Executable file
0
rc_scripts/iredadmin.rhel
Normal file → Executable file
@@ -1,3 +1,5 @@
|
||||
* Please read file 'EULA' for End User License Agreement.
|
||||
|
||||
* If you already have iRedAdmin open source edition or old iRedAdmin-Pro
|
||||
release installed, please follow below tutorial to upgrade it to the latest
|
||||
iRedAdmin-Pro, it's the easiest way with minimal steps:
|
||||
|
||||
8
static/.htaccess
Executable file
8
static/.htaccess
Executable file
@@ -0,0 +1,8 @@
|
||||
<IfModule mod_expires.c>
|
||||
ExpiresActive On
|
||||
ExpiresByType application/x-javascript "access plus 1 month"
|
||||
ExpiresByType text/css "access plus 1 month"
|
||||
ExpiresByType image/png "access plus 1 month"
|
||||
ExpiresByType image/gif "access plus 1 month"
|
||||
ExpiresByType image/jpg "access plus 1 month"
|
||||
</IfModule>
|
||||
0
static/default/css/spectre-icons.min.css
vendored
Normal file → Executable file
0
static/default/css/spectre-icons.min.css
vendored
Normal file → Executable file
0
static/default/css/spectre.min.css
vendored
Normal file → Executable file
0
static/default/css/spectre.min.css
vendored
Normal file → Executable file
5
static/js/jquery-1.12.4.min.js
vendored
5
static/js/jquery-1.12.4.min.js
vendored
File diff suppressed because one or more lines are too long
2
static/js/jquery-3.6.4.min.js
vendored
Normal file
2
static/js/jquery-3.6.4.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
static/js/jquery.fancybox.js
vendored
2
static/js/jquery.fancybox.js
vendored
File diff suppressed because one or more lines are too long
0
static/js/jquery.quickfilter.js
Normal file → Executable file
0
static/js/jquery.quickfilter.js
Normal file → Executable file
0
static/js/stupidtable.min.js
vendored
Normal file → Executable file
0
static/js/stupidtable.min.js
vendored
Normal file → Executable file
@@ -5,7 +5,6 @@
|
||||
{% set token = token |e %}
|
||||
{% endif %}
|
||||
|
||||
<!--suppress ALL -->
|
||||
<input type="hidden" name="csrf_token" value="{{ token }}"/>
|
||||
{%- endmacro %}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
{# ------------ Load JS files ------------- #}
|
||||
{% macro load_jquery() -%}
|
||||
<script type="text/javascript" src="{{ctx.homepath}}/static/js/jquery-1.12.4.min.js"></script>
|
||||
<script type="text/javascript" src="{{ctx.homepath}}/static/js/jquery-3.6.4.min.js"></script>
|
||||
<script type="text/javascript" src="{{ctx.homepath}}/static/js/jquery.tooltip.js"></script>
|
||||
<script type="text/javascript" src="{{ctx.homepath}}/static/js/jquery.idtabs.js"></script>
|
||||
<script type="text/javascript" src="{{ctx.homepath}}/static/js/jquery.fancybox.js"></script>
|
||||
|
||||
@@ -330,36 +330,39 @@
|
||||
{% endif %}
|
||||
|
||||
{# profile_type: throttling #}
|
||||
{% if session.get('is_global_admin') or 'throttle' not in disabled_domain_profiles %}
|
||||
|
||||
{% if (session.get('is_global_admin') or 'throttle' not in disabled_domain_profiles) and session.get('iredapd_enabled') %}
|
||||
<div id="profile_throttle">
|
||||
<form name="throttle" method="post" action="{{ctx.homepath}}/profile/domain/throttle/{{cur_domain}}">
|
||||
<form name="throttle"
|
||||
method="post"
|
||||
action="{{ctx.homepath}}/profile/domain/throttle/{{cur_domain}}"
|
||||
>
|
||||
{{ input_csrf_token() }}
|
||||
|
||||
{% if session.get('iredapd_enabled') %}
|
||||
{# Throttling with iRedAPD #}
|
||||
<div class="columns clear">
|
||||
{{ input_csrf_token() }}
|
||||
{% if session.get('iredapd_enabled') %}
|
||||
{# Throttling with iRedAPD #}
|
||||
<div class="columns clear">
|
||||
{{ input_csrf_token() }}
|
||||
|
||||
{{ display_throttle_setting(account='@' + cur_domain,
|
||||
setting=outbound_throttle_setting,
|
||||
inout_type='outbound') }}
|
||||
{{ display_throttle_setting(account='@' + cur_domain,
|
||||
setting=inbound_throttle_setting,
|
||||
inout_type='inbound',
|
||||
with_left_border=true) }}
|
||||
{{ display_throttle_setting(account='@' + cur_domain,
|
||||
setting=outbound_throttle_setting,
|
||||
inout_type='outbound') }}
|
||||
|
||||
<div class="col1-3 lastcol">
|
||||
<div class="mark_blue bt-space10">
|
||||
<ul class="standard clean-padding bt-space10">
|
||||
<li class="bt-space5">{{ _('This throttle setting will be applied to all individual accounts under domain %s.') |format(cur_domain) }}</li>
|
||||
<li class="bt-space5">{{ _('You can set per-user throttling in account profile page.') }}</li>
|
||||
<li class="bt-space5">{{ _('Per-user throttle setting has higher priority.') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>{#-- .col1-3 --#}
|
||||
</div>{# .columns #}
|
||||
{% endif %}
|
||||
{{ display_throttle_setting(account='@' + cur_domain,
|
||||
setting=inbound_throttle_setting,
|
||||
inout_type='inbound',
|
||||
with_left_border=true) }}
|
||||
|
||||
<div class="col1-3 lastcol">
|
||||
<div class="mark_blue bt-space10">
|
||||
<ul class="standard clean-padding bt-space10">
|
||||
<li class="bt-space5">{{ _('This throttle setting will be applied to all individual accounts under domain %s.') |format(cur_domain) }}</li>
|
||||
<li class="bt-space5">{{ _('You can set per-user throttling in account profile page.') }}</li>
|
||||
<li class="bt-space5">{{ _('Per-user throttle setting has higher priority.') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>{#-- .col1-3 --#}
|
||||
</div>{# .columns #}
|
||||
{% endif %}
|
||||
|
||||
{{ input_submit() }}
|
||||
</form>
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import web
|
||||
|
||||
os.environ['LC_ALL'] = 'C'
|
||||
|
||||
rootdir = os.path.abspath(os.path.dirname(__file__)) + '/../'
|
||||
sys.path.insert(0, rootdir)
|
||||
|
||||
import web
|
||||
import settings
|
||||
from libs import iredutils
|
||||
from tools import ira_tool_lib
|
||||
|
||||
@@ -27,13 +27,13 @@
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import web
|
||||
|
||||
os.environ['LC_ALL'] = 'C'
|
||||
|
||||
rootdir = os.path.abspath(os.path.dirname(__file__)) + '/../'
|
||||
sys.path.insert(0, rootdir)
|
||||
|
||||
import web
|
||||
import settings
|
||||
from tools.ira_tool_lib import debug, logger, sql_dbn, get_db_conn, sql_count_id
|
||||
|
||||
|
||||
@@ -40,13 +40,13 @@ import time
|
||||
import logging
|
||||
import shutil
|
||||
import pwd
|
||||
import web
|
||||
|
||||
os.environ['LC_ALL'] = 'C'
|
||||
|
||||
rootdir = os.path.abspath(os.path.dirname(__file__)) + '/../'
|
||||
sys.path.insert(0, rootdir)
|
||||
|
||||
import web
|
||||
from libs import iredutils
|
||||
from tools import ira_tool_lib
|
||||
import settings
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import web
|
||||
|
||||
os.environ['LC_ALL'] = 'C'
|
||||
|
||||
rootdir = os.path.abspath(os.path.dirname(__file__)) + '/../'
|
||||
sys.path.insert(0, rootdir)
|
||||
|
||||
import web
|
||||
from tools import ira_tool_lib
|
||||
|
||||
web.config.debug = ira_tool_lib.debug
|
||||
|
||||
@@ -26,9 +26,6 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import web
|
||||
|
||||
web.config.debug = False
|
||||
|
||||
# Directory used to store disclaimer files.
|
||||
# Default directory is /etc/postfix/disclaimer/.
|
||||
@@ -43,11 +40,14 @@ os.environ['LC_ALL'] = 'C'
|
||||
rootdir = os.path.abspath(os.path.dirname(__file__)) + '/../'
|
||||
sys.path.insert(0, rootdir)
|
||||
|
||||
import web
|
||||
import settings
|
||||
from libs import iredutils
|
||||
from tools import ira_tool_lib
|
||||
logger = ira_tool_lib.logger
|
||||
|
||||
web.config.debug = False
|
||||
|
||||
if settings.backend == 'ldap':
|
||||
import ldap
|
||||
elif settings.backend == 'mysql':
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import web
|
||||
|
||||
output_dir = sys.argv[1]
|
||||
if not os.path.isdir(output_dir):
|
||||
@@ -20,6 +19,7 @@ os.environ['LC_ALL'] = 'C'
|
||||
rootdir = os.path.abspath(os.path.dirname(__file__)) + '/../'
|
||||
sys.path.insert(0, rootdir)
|
||||
|
||||
import web
|
||||
from tools.ira_tool_lib import debug, get_db_conn
|
||||
|
||||
web.config.debug = debug
|
||||
|
||||
@@ -14,13 +14,13 @@ Usage:
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import web
|
||||
|
||||
os.environ['LC_ALL'] = 'C'
|
||||
|
||||
rootdir = os.path.abspath(os.path.dirname(__file__)) + '/../'
|
||||
sys.path.insert(0, rootdir)
|
||||
|
||||
import web
|
||||
import settings
|
||||
from tools import ira_tool_lib
|
||||
from libs.iredutils import epoch_seconds_to_gmt
|
||||
|
||||
@@ -5,21 +5,21 @@
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
import web
|
||||
|
||||
debug = False
|
||||
|
||||
# Set True to print SQL queries.
|
||||
web.config.debug = debug
|
||||
|
||||
os.environ['LC_ALL'] = 'C'
|
||||
|
||||
rootdir = os.path.abspath(os.path.dirname(__file__)) + '/../'
|
||||
sys.path.insert(0, rootdir)
|
||||
|
||||
import web
|
||||
import settings
|
||||
from libs import iredutils
|
||||
|
||||
# Set True to print SQL queries.
|
||||
web.config.debug = debug
|
||||
|
||||
backend = settings.backend
|
||||
if backend in ['ldap', 'mysql']:
|
||||
sql_dbn = 'mysql'
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import web
|
||||
|
||||
os.environ['LC_ALL'] = 'C'
|
||||
|
||||
rootdir = os.path.abspath(os.path.dirname(__file__)) + '/../'
|
||||
sys.path.insert(0, rootdir)
|
||||
|
||||
import web
|
||||
import settings
|
||||
from libs.iredutils import is_valid_amavisd_address
|
||||
from libs.amavisd import wblist
|
||||
|
||||
@@ -93,7 +93,6 @@ import time
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.header import Header
|
||||
import web
|
||||
|
||||
os.environ['LC_ALL'] = 'C'
|
||||
|
||||
@@ -103,6 +102,7 @@ sys.path.insert(0, rootdir)
|
||||
|
||||
now = int(time.time())
|
||||
|
||||
import web
|
||||
import settings
|
||||
from libs import iredutils
|
||||
from libs.ireddate import utc_to_timezone
|
||||
|
||||
@@ -15,13 +15,13 @@ def usage():
|
||||
|
||||
import os
|
||||
import sys
|
||||
import web
|
||||
|
||||
os.environ['LC_ALL'] = 'C'
|
||||
|
||||
rootdir = os.path.abspath(os.path.dirname(__file__)) + '/../'
|
||||
sys.path.insert(0, rootdir)
|
||||
|
||||
import web
|
||||
import settings
|
||||
from tools.ira_tool_lib import debug, get_db_conn
|
||||
from libs.iredutils import is_email
|
||||
|
||||
@@ -14,13 +14,13 @@ def usage():
|
||||
|
||||
import os
|
||||
import sys
|
||||
import web
|
||||
|
||||
os.environ['LC_ALL'] = 'C'
|
||||
|
||||
rootdir = os.path.abspath(os.path.dirname(__file__)) + '/../'
|
||||
sys.path.insert(0, rootdir)
|
||||
|
||||
import web
|
||||
import settings
|
||||
from tools.ira_tool_lib import debug, get_db_conn
|
||||
from libs.iredutils import is_email
|
||||
|
||||
@@ -32,13 +32,13 @@ def usage():
|
||||
|
||||
import os
|
||||
import sys
|
||||
import web
|
||||
|
||||
os.environ['LC_ALL'] = 'C'
|
||||
|
||||
rootdir = os.path.abspath(os.path.dirname(__file__)) + '/../'
|
||||
sys.path.insert(0, rootdir)
|
||||
|
||||
import web
|
||||
import settings
|
||||
from tools.ira_tool_lib import debug, logger, get_db_conn
|
||||
from libs.iredutils import is_email
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import web
|
||||
|
||||
|
||||
def usage():
|
||||
@@ -33,6 +32,7 @@ os.environ['LC_ALL'] = 'C'
|
||||
rootdir = os.path.abspath(os.path.dirname(__file__)) + '/../'
|
||||
sys.path.insert(0, rootdir)
|
||||
|
||||
import web
|
||||
import settings
|
||||
from tools.ira_tool_lib import debug, logger, get_db_conn
|
||||
from libs.iredutils import is_email
|
||||
|
||||
0
web/utils.py
Normal file → Executable file
0
web/utils.py
Normal file → Executable file
Reference in New Issue
Block a user