Kaydet (Commit) 2a2becc1 authored tarafından Steve Dower's avatar Steve Dower

Merge with 3.5

...@@ -126,12 +126,13 @@ def _finalize_set(msg, disposition, filename, cid, params): ...@@ -126,12 +126,13 @@ def _finalize_set(msg, disposition, filename, cid, params):
msg.set_param(key, value) msg.set_param(key, value)
# XXX: This is a cleaned-up version of base64mime.body_encode. It would # XXX: This is a cleaned-up version of base64mime.body_encode (including a bug
# be nice to drop both this and quoprimime.body_encode in favor of # fix in the calculation of unencoded_bytes_per_line). It would be nice to
# enhanced binascii routines that accepted a max_line_length parameter. # drop both this and quoprimime.body_encode in favor of enhanced binascii
# routines that accepted a max_line_length parameter.
def _encode_base64(data, max_line_length): def _encode_base64(data, max_line_length):
encoded_lines = [] encoded_lines = []
unencoded_bytes_per_line = max_line_length * 3 // 4 unencoded_bytes_per_line = max_line_length // 4 * 3
for i in range(0, len(data), unencoded_bytes_per_line): for i in range(0, len(data), unencoded_bytes_per_line):
thisline = data[i:i+unencoded_bytes_per_line] thisline = data[i:i+unencoded_bytes_per_line]
encoded_lines.append(binascii.b2a_base64(thisline).decode('ascii')) encoded_lines.append(binascii.b2a_base64(thisline).decode('ascii'))
......
...@@ -120,6 +120,10 @@ def parameterize(cls): ...@@ -120,6 +120,10 @@ def parameterize(cls):
Note: if and only if the generated test name is a valid identifier can it Note: if and only if the generated test name is a valid identifier can it
be used to select the test individually from the unittest command line. be used to select the test individually from the unittest command line.
The values in the params dict can be a single value, a tuple, or a
dict. If a single value of a tuple, it is passed to the test function
as positional arguments. If a dict, it is a passed via **kw.
""" """
paramdicts = {} paramdicts = {}
testers = collections.defaultdict(list) testers = collections.defaultdict(list)
...@@ -148,8 +152,12 @@ def parameterize(cls): ...@@ -148,8 +152,12 @@ def parameterize(cls):
if name.startswith(paramsname): if name.startswith(paramsname):
testnameroot = 'test_' + name[len(paramsname):] testnameroot = 'test_' + name[len(paramsname):]
for paramname, params in paramsdict.items(): for paramname, params in paramsdict.items():
test = (lambda self, name=name, params=params: if hasattr(params, 'keys'):
getattr(self, name)(*params)) test = (lambda self, name=name, params=params:
getattr(self, name)(**params))
else:
test = (lambda self, name=name, params=params:
getattr(self, name)(*params))
testname = testnameroot + '_' + paramname testname = testnameroot + '_' + paramname
test.__name__ = testname test.__name__ = testname
testfuncs[testname] = test testfuncs[testname] = test
......
...@@ -7,6 +7,7 @@ producing RFC valid messages. ...@@ -7,6 +7,7 @@ producing RFC valid messages.
import io import io
import unittest import unittest
from email import policy, message_from_bytes from email import policy, message_from_bytes
from email.message import EmailMessage
from email.generator import BytesGenerator from email.generator import BytesGenerator
from test.test_email import TestEmailBase, parameterize from test.test_email import TestEmailBase, parameterize
...@@ -23,7 +24,10 @@ def dedent(bstr): ...@@ -23,7 +24,10 @@ def dedent(bstr):
@parameterize @parameterize
class TestInversion(TestEmailBase, unittest.TestCase): class TestInversion(TestEmailBase):
policy = policy.default
message = EmailMessage
def msg_as_input(self, msg): def msg_as_input(self, msg):
m = message_from_bytes(msg, policy=policy.SMTP) m = message_from_bytes(msg, policy=policy.SMTP)
...@@ -44,6 +48,23 @@ class TestInversion(TestEmailBase, unittest.TestCase): ...@@ -44,6 +48,23 @@ class TestInversion(TestEmailBase, unittest.TestCase):
} }
payload_params = {
'plain_text': dict(payload='This is a test\n'*20),
'base64_text': dict(payload=(('xy a'*40+'\n')*5), cte='base64'),
'qp_text': dict(payload=(('xy a'*40+'\n')*5), cte='quoted-printable'),
}
def payload_as_body(self, payload, **kw):
msg = self._make_message()
msg['From'] = 'foo'
msg['To'] = 'bar'
msg['Subject'] = 'payload round trip test'
msg.set_content(payload, **kw)
b = bytes(msg)
msg2 = message_from_bytes(b, policy=self.policy)
self.assertEqual(bytes(msg2), b)
self.assertEqual(msg2.get_content(), payload)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -113,6 +113,11 @@ Core and Builtins ...@@ -113,6 +113,11 @@ Core and Builtins
Library Library
------- -------
- Issue #24594: Validates persist parameter when opening MSI database
- Issue #28047: Fixed calculation of line length used for the base64 CTE
in the new email policies.
- Issue #27576: Fix call order in OrderedDict.__init__(). - Issue #27576: Fix call order in OrderedDict.__init__().
- email.generator.DecodedGenerator now supports the policy keyword. - email.generator.DecodedGenerator now supports the policy keyword.
......
...@@ -955,6 +955,17 @@ static PyTypeObject msidb_Type = { ...@@ -955,6 +955,17 @@ static PyTypeObject msidb_Type = {
0, /*tp_is_gc*/ 0, /*tp_is_gc*/
}; };
#define Py_NOT_PERSIST(x, flag) \
(x != (int)(flag) && \
x != ((int)(flag) | MSIDBOPEN_PATCHFILE))
#define Py_INVALID_PERSIST(x) \
(Py_NOT_PERSIST(x, MSIDBOPEN_READONLY) && \
Py_NOT_PERSIST(x, MSIDBOPEN_TRANSACT) && \
Py_NOT_PERSIST(x, MSIDBOPEN_DIRECT) && \
Py_NOT_PERSIST(x, MSIDBOPEN_CREATE) && \
Py_NOT_PERSIST(x, MSIDBOPEN_CREATEDIRECT))
static PyObject* msiopendb(PyObject *obj, PyObject *args) static PyObject* msiopendb(PyObject *obj, PyObject *args)
{ {
int status; int status;
...@@ -962,11 +973,14 @@ static PyObject* msiopendb(PyObject *obj, PyObject *args) ...@@ -962,11 +973,14 @@ static PyObject* msiopendb(PyObject *obj, PyObject *args)
int persist; int persist;
MSIHANDLE h; MSIHANDLE h;
msiobj *result; msiobj *result;
if (!PyArg_ParseTuple(args, "si:MSIOpenDatabase", &path, &persist)) if (!PyArg_ParseTuple(args, "si:MSIOpenDatabase", &path, &persist))
return NULL; return NULL;
/* We need to validate that persist is a valid MSIDBOPEN_* value. Otherwise,
status = MsiOpenDatabase(path, (LPCSTR)persist, &h); MsiOpenDatabase may treat the value as a pointer, leading to unexpected
behavior. */
if (Py_INVALID_PERSIST(persist))
return msierror(ERROR_INVALID_PARAMETER);
status = MsiOpenDatabase(path, (LPCSTR)persist, &h);
if (status != ERROR_SUCCESS) if (status != ERROR_SUCCESS)
return msierror(status); return msierror(status);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment