[Python-checkins] bpo-41142: Add support of non-ASCII paths for CAB files. (GH-21195)

Serhiy Storchaka webhook-mailer at python.org
Tue Jun 30 04:56:09 EDT 2020


https://github.com/python/cpython/commit/ba67d7386edf20bcc0f878a518de0894cb574e9f
commit: ba67d7386edf20bcc0f878a518de0894cb574e9f
branch: master
author: Serhiy Storchaka <storchaka at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-06-30T11:56:03+03:00
summary:

bpo-41142: Add support of non-ASCII paths for CAB files. (GH-21195)

* The path to the CAB file can be non-ASCII.
* Paths of added files can be non-ASCII.

files:
A Misc/NEWS.d/next/Windows/2020-06-28-12-40-41.bpo-41142.jpZzzh.rst
M Lib/test/test_msilib.py
M PC/_msi.c

diff --git a/Lib/test/test_msilib.py b/Lib/test/test_msilib.py
index 4a233c3784e51..743bea7c14d0e 100644
--- a/Lib/test/test_msilib.py
+++ b/Lib/test/test_msilib.py
@@ -112,6 +112,16 @@ def test_getproperty_uninitialized_var(self):
         with self.assertRaises(msilib.MSIError):
             si.GetProperty(-1)
 
+    def test_FCICreate(self):
+        filepath = TESTFN + '.txt'
+        cabpath = TESTFN + '.cab'
+        self.addCleanup(unlink, filepath)
+        with open(filepath, 'wb'):
+            pass
+        self.addCleanup(unlink, cabpath)
+        msilib.FCICreate(cabpath, [(filepath, 'test.txt')])
+        self.assertTrue(os.path.isfile(cabpath))
+
 
 class Test_make_id(unittest.TestCase):
     #http://msdn.microsoft.com/en-us/library/aa369212(v=vs.85).aspx
diff --git a/Misc/NEWS.d/next/Windows/2020-06-28-12-40-41.bpo-41142.jpZzzh.rst b/Misc/NEWS.d/next/Windows/2020-06-28-12-40-41.bpo-41142.jpZzzh.rst
new file mode 100644
index 0000000000000..91406da7a2544
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2020-06-28-12-40-41.bpo-41142.jpZzzh.rst
@@ -0,0 +1,2 @@
+:mod:`msilib` now supports creating CAB files with non-ASCII file path and
+adding files with non-ASCII file path to them.
diff --git a/PC/_msi.c b/PC/_msi.c
index 58c1cfd997bf8..60a0c3aebb1e7 100644
--- a/PC/_msi.c
+++ b/PC/_msi.c
@@ -41,21 +41,50 @@ uuidcreate(PyObject* obj, PyObject*args)
 
 }
 
+/* Helper for converting file names from UTF-8 to wchat_t*.  */
+static wchar_t *
+utf8_to_wchar(const char *s, int *err)
+{
+    PyObject *obj = PyUnicode_FromString(s);
+    if (obj == NULL) {
+        if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
+            *err = ENOMEM;
+        }
+        else {
+            *err = EINVAL;
+        }
+        PyErr_Clear();
+        return NULL;
+    }
+    wchar_t *ws = PyUnicode_AsWideCharString(obj, NULL);
+    if (ws == NULL) {
+        *err = ENOMEM;
+        PyErr_Clear();
+    }
+    Py_DECREF(obj);
+    return ws;
+}
+
 /* FCI callback functions */
 
 static FNFCIALLOC(cb_alloc)
 {
-    return malloc(cb);
+    return PyMem_RawMalloc(cb);
 }
 
 static FNFCIFREE(cb_free)
 {
-    free(memory);
+    PyMem_RawFree(memory);
 }
 
 static FNFCIOPEN(cb_open)
 {
-    int result = _open(pszFile, oflag | O_NOINHERIT, pmode);
+    wchar_t *ws = utf8_to_wchar(pszFile, err);
+    if (ws == NULL) {
+        return -1;
+    }
+    int result = _wopen(ws, oflag | O_NOINHERIT, pmode);
+    PyMem_Free(ws);
     if (result == -1)
         *err = errno;
     return result;
@@ -95,7 +124,12 @@ static FNFCISEEK(cb_seek)
 
 static FNFCIDELETE(cb_delete)
 {
-    int result = remove(pszFile);
+    wchar_t *ws = utf8_to_wchar(pszFile, err);
+    if (ws == NULL) {
+        return -1;
+    }
+    int result = _wremove(ws);
+    PyMem_Free(ws);
     if (result != 0)
         *err = errno;
     return result;
@@ -159,15 +193,22 @@ static FNFCIGETOPENINFO(cb_getopeninfo)
     FILETIME filetime;
     HANDLE handle;
 
+    wchar_t *ws = utf8_to_wchar(pszName, err);
+    if (ws == NULL) {
+        return -1;
+    }
+
     /* Need Win32 handle to get time stamps */
-    handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
+    handle = CreateFileW(ws, GENERIC_READ, FILE_SHARE_READ, NULL,
         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-    if (handle == INVALID_HANDLE_VALUE)
+    if (handle == INVALID_HANDLE_VALUE) {
+        PyMem_Free(ws);
         return -1;
+    }
 
-    if (GetFileInformationByHandle(handle, &bhfi) == FALSE)
-    {
+    if (GetFileInformationByHandle(handle, &bhfi) == FALSE) {
         CloseHandle(handle);
+        PyMem_Free(ws);
         return -1;
     }
 
@@ -179,7 +220,9 @@ static FNFCIGETOPENINFO(cb_getopeninfo)
 
     CloseHandle(handle);
 
-    return _open(pszName, _O_RDONLY | _O_BINARY | O_NOINHERIT);
+    int result = _wopen(ws, _O_RDONLY | _O_BINARY | O_NOINHERIT);
+    PyMem_Free(ws);
+    return result;
 }
 
 static PyObject* fcicreate(PyObject* obj, PyObject* args)
@@ -212,7 +255,7 @@ static PyObject* fcicreate(PyObject* obj, PyObject* args)
     ccab.setID = 0;
     ccab.szDisk[0] = '\0';
 
-    for (i = 0, p = cabname; *p; p = CharNext(p))
+    for (i = 0, p = cabname; *p; p++)
         if (*p == '\\' || *p == '/')
             i = p - cabname + 1;
 



More information about the Python-checkins mailing list