Bugs item #3277647, was opened at 2011-04-06 09:47
Message generated for change (Comment added) made by series8217
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=551954&aid=3277647&group_id=78018
Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: None
Group: None
Status: Open
Resolution: None
Priority: 5
Private: No
Submitted By: Series8217 (series8217)
Assigned to: Nobody/Anonymous (nobody)
Summary: GetOpenFileNameW may return a C-style null-terminated string
Initial Comment:
*Environment*
Windows 7 Professional 64-bit (no service pack), Python 2.7.1, PyWin32 Build 216
Addtl Note: I posted this as a question on Stack Overflow here: http://stackoverflow.com/questions/5559810/how-do-i-handle-python-unicode-strings-with-null-bytes-the-right-way/5559907
One other user has noted that the problem does not occur for them on Windows 7 SP1 64-bit with the same PyWin32 build (216) and Python 2.6.5 64-bit.
*Problem Description*
I'm using the Win32 file chooser function GetOpenFileNameW from the PyWin32 package. According to the documentation, this function returns a tuple containing the full filename path as a Python unicode object.
When I open the dialog with an existing path and filename set, I get a strange return value.
For example I had the default set to: C:\\Users\\Guest\\MyFileIsReallyReallyReallyAwesome.asy
In the dialog I changed the name to MyFile.asy and clicked save.
The full path part of the return value was: u'C:\Users\Guest\MyFile.asy\x00wesome.asy'`
I expected it to be: u'C:\\Users\\Guest\\MyFile.asy'
It appears that GetOopenFileNameW is returning a recycled buffer (from the default file path it seems) without trimming off the terminating bytes. Needless to say, the rest of my code wasn't set up for handling a C-style null-terminated string.
*Demo Code*
The following code demonstrates null-terminated string in return value from GetSaveFileNameW.
Directions: In the dialog change the filename to 'MyFile.asy' then click Save. Observe what is printed to the console. The output I get is u'C:\\Users\\Guest\\MyFile.asy\x00wesome.asy'.
import win32gui, win32con
if __name__ == "__main__":
initial_dir = 'C:\\Users\\Guest'
initial_file = 'MyFileIsReallyReallyReallyAwesome.asy'
filter_string = 'All Files\0*.*\0'
(filename, customfilter, flags) = \
win32gui.GetSaveFileNameW(InitialDir=initial_dir,
Flags=win32con.OFN_EXPLORER, File=initial_file,
DefExt='txt', Title="Save As", Filter=filter_string,
FilterIndex=0)
print repr(filename)
Note: If you don't shorten the filename enough (for example, if you try MyFileIsReally.asy) the string will be complete without a null byte.
----------------------------------------------------------------------
>Comment By: Series8217 (series8217)
Date: 2011-04-09 20:03
Message:
Thanks for the comment, Roger.
Perhaps the documentation could be more clear about the return value. At
the moment it says: "If multiple files are selected, returned string will
be the directory followed by files names separated by nulls, otherwise it
will be the full path."
There is no indication that there should be nulls if only a single file is
selected. Besides, without passing the multiple selection flag, selecting
multiple files isn't allowed so I would just expect a single path.
Assuming multiple selections ARE enabled, is the last selection in the
list always going to be followed by a double null? If so, it would make
sense to cut off the return value at the double null. Then we can do
return_vallue.split('\x00') to get the list of selected file paths, and
single selections would work predictably as well.
----------------------------------------------------------------------
Comment By: Roger Upole (rupole)
Date: 2011-04-08 18:31
Message:
This is because this function can legimately return a string with embedded
nulls when multiple files are selected. The wrapper code could be smarter
about how the string is trimmed, though. Cutting it off at a double null
might be the way to go. However, if you're only allowing a single
selection, you can just split it on '\x00' and use the first piece.
----------------------------------------------------------------------
Comment By: Series8217 (series8217)
Date: 2011-04-06 13:07
Message:
I added the test script as an attachment because the formatting is messed
up in the original bug details.
----------------------------------------------------------------------
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=551954&aid=3277647&group_id=78018
|