8000 bpo-41142: Add support of non-ASCII paths for CAB files. (GH-21195) · python/cpython@ba67d73 · GitHub
[go: up one dir, main page]

Skip to content

Commit ba67d73

Browse files
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.
1 parent 694d31e commit ba67d73

File tree

3 files changed

+65
-10
lines changed

3 files changed

+65
-10
lines changed

Lib/test/test_msilib.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,16 @@ def test_getproperty_uninitialized_var(self):
112112
with self.assertRaises(msilib.MSIError):
113113
si.GetProperty(-1)
114114

115+
def test_FCICreate(self):
116+
filepath = TESTFN + '.txt'
117+
cabpath = TESTFN + '.cab'
118+
self.addCleanup(unlink, filepath)
119+
with open(filepath, 'wb'):
120+
pass
121+
self.addCleanup(unlink, cabpath)
122+
msilib.FCICreate(cabpath, [(filepath, 'test.txt')])
123+
self.assertTrue(os.path.isfile(cabpath))
124+
115125

116126
class Test_make_id(unittest.TestCase):
117127
#http://msdn.microsoft.com/en-us/library/aa369212(v=vs.85).aspx
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:mod:`msilib` now supports creating CAB files with non-ASCII file path and
2+
adding files with non-ASCII file path to them.

PC/_msi.c

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,50 @@ uuidcreate(PyObject* obj, PyObject*args)
4141

4242
}
4343

44+
/* Helper for converting file names from UTF-8 to wchat_t*. */
45+
static wchar_t *
46+
utf8_to_wchar(const char *s, int *err)
47+
{
48+
PyObject *obj = PyUnicode_FromString(s);
49+
if (obj == NULL) {
50+
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
51+
*err = ENOMEM;
52+
}
53+
else {
54+
*err = EINVAL;
55+
}
56+
PyErr_Clear();
57+
return NULL;
58+
}
59+
wchar_t *ws = PyUnicode_AsWideCharString(obj, NULL);
60+
if (ws == NULL) {
61+
*err = ENOMEM;
62+
PyErr_Clear();
63+
}
64+
Py_DECREF(obj);
65+
return ws;
66+
}
67+
4468
/* FCI callback functions */
4569

4670
static FNFCIALLOC(cb_alloc)
4771
{
48-
return malloc(cb);
72+
return PyMem_RawMalloc(cb);
4973
}
5074

5175
static FNFCIFREE(cb_free)
5276
{
53-
free(memory);
77+
PyMem_RawFree(memory);
5478
}
5579

5680
static FNFCIOPEN(cb_open)
5781
{
58-
int result = _open(pszFile, oflag | O_NOINHERIT, pmode);
82+
wchar_t *ws = utf8_to_wchar(pszFile, err);
83+
if (ws == NULL) {
84+
return -1;
85+
}
86+
int result = _wopen(ws, oflag | O_NOINHERIT, pmode);
87+
PyMem_Free(ws);
5988
if (result == -1)
6089
*err = errno;
6190
return result;
@@ -95,7 +124,12 @@ static FNFCISEEK(cb_seek)
95124

96125
static FNFCIDELETE(cb_delete)
97126
{
98-
int result = remove(pszFile);
127+
wchar_t *ws = utf8_to_wchar(pszFile, err);
128+
if (ws == NULL) {
129+
return -1;
130+
}
131+
int result = _wremove(ws);
132+
PyMem_Free(ws);
99133
if (result != 0)
100134
*err = errno;
101135
return result;
@@ -159,15 +193,22 @@ static FNFCIGETOPENINFO(cb_getopeninfo)
159193
FILETIME filetime;
160194
HANDLE handle;
161195

196+
wchar_t *ws = utf8_to_wchar(pszName, err);
197+
if (ws == NULL) {
198+
return -1;
199+
}
200+
162201
/* Need Win32 handle to get time stamps */
57AE
163-
handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
202+
handle = CreateFileW(ws, GENERIC_READ, FILE_SHARE_READ, NULL,
164203
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
165-
if (handle == INVALID_HANDLE_VALUE)
204+
if (handle == INVALID_HANDLE_VALUE) {
205+
PyMem_Free(ws);
166206
return -1;
207+
}
167208

168-
if (GetFileInformationByHandle(handle, &bhfi) == FALSE)
169-
{
209+
if (GetFileInformationByHandle(handle, &bhfi) == FALSE) {
170210
CloseHandle(handle);
211+
PyMem_Free(ws);
171212
return -1;
172213
}
173214

@@ -179,7 +220,9 @@ static FNFCIGETOPENINFO(cb_getopeninfo)
179220

180221
CloseHandle(handle);
181222

182-
return _open(pszName, _O_RDONLY | _O_BINARY | O_NOINHERIT);
223+
int result = _wopen(ws, _O_RDONLY | _O_BINARY | O_NOINHERIT);
224+
PyMem_Free(ws);
225+
return result;
183226
}
184227

185228
static PyObject* fcicreate(PyObject* obj, PyObject* args)
@@ -212,7 +255,7 @@ static PyObject* fcicreate(PyObject* obj, PyObject* args)
212255
ccab.setID = 0;
213256
ccab.szDisk[0] = '\0';
214257

215-
for (i = 0, p = cabname; *p; p = CharNext(p))
258+
for (i = 0, p = cabname; *p; p++)
216259
if (*p == '\\' || *p == '/')
217260
i = p - cabname + 1;
218261

0 commit comments

Comments
 (0)
0