| Server IP : 85.214.239.14 / Your IP : 216.73.216.178 Web Server : Apache/2.4.65 (Debian) System : Linux h2886529.stratoserver.net 4.9.0 #1 SMP Mon Sep 30 15:36:27 MSK 2024 x86_64 User : www-data ( 33) PHP Version : 8.2.29 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /srv/modoboa/env/lib/python3.5/site-packages/modoboa_amavis/ |
Upload File : |
# -*- coding: utf-8 -*-
"""A collection of utility functions for working with the Amavis database."""
import chardet
from django.conf import settings
from django.db.models.expressions import Func
from django.utils import six
from django.utils.encoding import (
smart_bytes as django_smart_bytes, smart_str as django_smart_str,
smart_text as django_smart_text
)
"""
Byte fields for text data are EVIL.
MySQL uses `varbyte` fields which mysqlclient client maps to `str` (Py2) or
`bytes` (Py3), Djangos smart_* functions work as expected.
PostgreSQL uses `bytea` fields which psycopg2 maps to `memoryview`,
Djangos smart_* functions don't work as expected, you must call `tobytes()` on
the memoryview for them to work.
For convenience use smart_bytes and smart_text from this file in modoboa_amavis
to avoid any headaches.
"""
def smart_bytes(value, *args, **kwargs):
if isinstance(value, memoryview):
value = value.tobytes()
return django_smart_bytes(value, *args, **kwargs)
def smart_str(value, *args, **kwargs):
if isinstance(value, memoryview):
value = value.tobytes()
return django_smart_str(value, *args, **kwargs)
def smart_text(value, *args, **kwargs):
if isinstance(value, memoryview):
value = value.tobytes()
return django_smart_text(value, *args, **kwargs)
def fix_utf8_encoding(value):
"""Fix utf-8 strings that contain utf-8 escaped characters.
msgs.from_addr and msgs.subject potentialy contain badly escaped utf-8
characters, this utility function fixes that and should be used anytime
these fields are accesses.
Didn't even know the raw_unicode_escape encoding existed :)
https://docs.python.org/2/library/codecs.html?highlight=raw_unicode_escape#python-specific-encodings
https://docs.python.org/3/library/codecs.html?highlight=raw_unicode_escape#python-specific-encodings
"""
assert isinstance(value, six.text_type), \
("value should be of type %s" % six.text_type.__name__)
if len(value) == 0:
# short circuit for empty strings
return ""
bytes_value = value.encode("raw_unicode_escape")
try:
value = bytes_value.decode("utf-8")
except UnicodeDecodeError:
encoding = chardet.detect(bytes_value)
try:
value = bytes_value.decode(encoding["encoding"], "replace")
except (TypeError, UnicodeDecodeError):
# ??? use the original value, we've done our best to try and
# convert it to a clean utf-8 string.
pass
return value
class ConvertFrom(Func):
"""Convert a binary value to a string.
Calls the database specific function to convert a binary value to a string
using the encoding set in AMAVIS_DEFAULT_DATABASE_ENCODING.
"""
"""PostgreSQL implementation.
See https://www.postgresql.org/docs/9.3/static/functions-string.html#FUNCTIONS-STRING-OTHER""" # NOQA:E501
function = "convert_from"
arity = 1
template = "%(function)s(%(expressions)s, '{}')".format(
settings.AMAVIS_DEFAULT_DATABASE_ENCODING)
def as_mysql(self, compiler, connection):
"""MySQL implementation.
See https://dev.mysql.com/doc/refman/5.5/en/cast-functions.html#function_convert""" # NOQA:E501
return super().as_sql(
compiler, connection,
function="CONVERT",
template="%(function)s(%(expressions)s USING {})".format(
settings.AMAVIS_DEFAULT_DATABASE_ENCODING),
arity=1,
)
def as_sqlite(self, compiler, connection):
"""SQLite implementation.
SQLite has no equivilant function, just return the field."""
return super().as_sql(
compiler, connection,
template="%(expressions)s",
arity=1,
)