QT: Escape slash / in saving location on a mac - macos

I have HTML input I am supposed to extract 2 Strings of, build a document title string of type <string 1> / <string 2, create a PDF from the source on the users mac desktop and name it as described.
I do know that a slash in a document name is not such a brilliant idea but this is what I am asked to do.
Problem is: the forward slash is interpreted as a folder on the mac and not as part of the documents name which means QPainter fails to print to PDF because it interpretes string1 / being a folder that doesn't exist.
BTW when omitting the / my code is working fine.
How am I supposed to escape the /?
Here's the string building logic:
QString docTitle;
docTitle.append(string1);
docTitle.append(" / ");
docTitle.append(string2);

On OS X, the name of a file at the level of the APIs is different from the display name that is shown to the user in the Finder, open and save panels, etc.
At the level of the APIs, file names simply can't contain slashes. They are reserved for separating names within a path. There's no form of escaping or quoting to allow it.
However, you can create a file whose name will be displayed with a slash in the UI.
Basically, the slash (/) and colon (:) characters swap roles. The display names of files can't include a colon, because it's reserved. (This is a holdover of the old HFS file system used in Classic Mac OS.) So, one aspect of the conversion from names-in-the-APIs to display names is to convert from colons to slashes. Thus, if you want a file whose display name has a slash, you actually use a colon.
A file whose name as per the APIs is "Important legal document 06:13:2015.pdf" will be displayed in the UI as "Important legal document 06/13/2015.pdf". Likewise, if a user names a file in a save dialog or in the Finder as "Important legal document 06/13/2015.pdf", it will end up with a name which, when observed via the APIs, will be "Important legal document 06:13:2015.pdf".

Related

SHParseDisplayName fails with ERROR_FILE_NOT_FOUND when passed existing directory whose name ends with a space character

I'm developing a file manager application, and noticed that some functions don't work with an existing folder that ends with a space symbol. E. g. "E:\1 \". This isn't specific to this particular folder, but indeed to any one with a space as the last character of the folder's name. For such folders, SHParseDisplayName returns ERROR_FILE_NOT_FOUND.
I'm calling SHParseDisplayName like so from C++:
ITEMIDLIST* idPtr = nullptr;
const auto result = SHParseDisplayName(L"E:\\1 \\", nullptr, &idPtr, 0, nullptr);
The documentation doesn't specify any edge cases, nor any ways in which the input path should be pre-processed. Regardless, I tried decorating it with quotes:
SHParseDisplayName(L"\"E:\\1 \\\"", nullptr, &idPtr, 0, nullptr);
And supplying a UNC path:
SHParseDisplayName(L"\\\\?\\E:\\1 \\", nullptr, &idPtr, 0, nullptr);
Both of which results in E_INVALIDARG.
Of note: SHParseDisplayName does work properly for items nested inside such a folder, e. g. L"E:\\1 \\some_internal_folder\\", just not the folder whose name ends with a space itself.
Is there any workaround? Windows Explorer seems to work just fine with such folders (as one would expect).
Also, SHParseDisplayName isn't the only Windows API function that fails for such folders. Another example of the same behavior is ILCreateFromPathW.
File and Folder names that begin or end with the ASCII Space (0x20)
will be saved without these characters. File and Folder names that end
with the ASCII Period (0x2E) character will also be saved without this
character. All other trailing or leading whitespace characters are
retained.
The Win32 API (CreateFile, FindFirstFile, etc.) uses a direct method
to enumerate the files and folders on a local or remote file system.
All files and folders are discoverable regardless of the inclusion or
location of whitespace characters.
Refer to "Support for Whitespace characters in File and Folder names"
And blog "MS-DOS also allowed spaces in file names, although vanishingly few programs knew how to access them.
So for existing files/folders with space at the end of names, either use Win32 API (CreateFile, FindFirstFile, etc.) or replace them with a new name without trailing or leading whitespace characters.

Certain characters make moveItemAtURL:toURL:error: crash. how do I avoid them?

First, I'm using Swift. Second this line works fine in my code:
let didIt = fileManager.moveItemAtURL(originalFilePath, toURL: newFilePath, error: nil)
...as long as there are no special characters in the newFilePath. if the newFilePath has a dollar sign or an ampersand ($, & ) in it, the line fails. My issue is that the newFilePath comes from a text field in a window where the user can type any old thing. How do I escape special characters, or encode them so they will pass the test and be included in the new filename?
thanks in advance for any pointers.
My issue is that the newFilePath comes from a text field in a window where the user can type any old thing.
Right there is your problem. Why are you not using an NSSavePanel for letting the user select a name under which to save a file?
If you insist on taking input from a text field, the docs for -URLByAppendingPathComponent: specifically say that the path component string should be "in its original form (not URL encoded)" (emphasis mine).
How did you originally create newFilePath, before appending the path component? For example, you should have used one of the methods with "[fF]ileURL" in the name.

Does the "SubstituteName" string in the PathBuffer of a REPARSE_DATA_BUFFER structure always start with the prefix "\??\", and if so, why?

I am trying to use Windows API functions compatible with Windows XP and up to find the target of a junction or symbolic link. I am using CreateFile to get a handle to the reparse point, then DeviceIoControl with the FSCTL_GET_REPARSE_POINT flag to read the reparse data into a REPARSE_DATA_BUFFER. Then, I use the offsets and lengths in the buffer to extract the SubstituteName and PrintName strings.
In Windows 8, extracting the PrintName works perfectly, giving me a normal path (ie c:\filename.ext), but in XP the PrintName section of the REPARSE_DATA_BUFFER seems to always have a length of 0, leaving me with an empty string.
Using the SubsituteName seems to work in both, but I always end up with a prefix of \??\ on the beginning of the file path (ie \??\c:\filename.ext). (as a side note, fsutil reparsepoint query shows the \??\ prefix as well).
I've read through much of the documentation on MSDN, but I can't find any explanation of this prefix. If the prefix is guaranteed to begin every SubstituteName, then I can just exclude the first four characters when I copy the file path from the buffer, but I'm not sure that this is the case. I would love to know if the "\??\" prefix appears in the SubstituteName for all Microsoft reparse points and why.
The Windows kernel has a "DOS Devices namespace" \DosDevices\ which is basically where anything you can open with CreateFile resides. (QueryDosDevice is a function which gives you all the members of that namespace.)
Because it's such a commonly used path, \??\ also redirects to that namespace. So, to the kernel, the path C:\Windows is invalid -- it should really be written as something like \??\C:\Windows. That's where this notation comes from.
The \??\ prefix means the path is not parsed. It is not guaranteed on every name, so you will have to look for the prefix on a per-name basis and skip it if present.
Update: I could not find any definitive documentation explaining exactly that \??\ actually represents, but here are some links that mention the \??\ prefix in action:
http://www.flexhex.com/docs/articles/hard-links.phtml
Note that szTarget string must contain the path prefixed with the "non-parsed" prefix "\??\", and terminated with the backslash character, for example "\??\C:\Some Dir\".
http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/908b3927-1ee9-4e03-9922-b4fd49fc51a6
http://mjunction.googlecode.com/svn-history/r5/trunk/MJunction/MJunction/JunctionPoint.cs
This prefix indicates to NTFS that the path is to be treated as a non-interpreted path in the virtual file system.
Private Const NonInterpretedPathPrefix As String = "\??\"

Wrong encoding of "file name from a file handle"

I have used this code in msdn (Obtaining a file name from a file handle) to obtain the file name of a file handle that i got from findfirstchangenotification.
But now the problem is that the encoding of the resulting string is somehow wrong. I just see one character instead of all characters (usually a question mark).
So my code calls GetMappedFileName, and gets question marks.
if (GetMappedFileName (GetCurrentProcess(),
pMem,
pszFilename,
MAX_PATH))
Why?
You are calling the 'A' form of GetMappedFileName, which can only deliver characters in your current ACP. Your filename has characters not in the current ACP, so they get turned to question marks.
If the file name includes Unicode characters that have no representation in your current ACP, you will get question marks. You should call the 'W' form of the API to get the Unicode form of the file name, and then decide what you want to do with it.

How to get a file in Windows with a colon in the filename?

I am getting errors from customers who are uploading files with a colon in the file name, i.e. C:/uploads/test : doc.html
I assume that some Unix or Linux system is generating the file but I'm not sure how the users are saving them with the invalid filename. I have coded a piece that should rename the document on upload. My problem is that I can't test it because I can't get a file on Windows that has a colon in the filename.
I found a very similar character to a colon, "꞉" it is a unicode character called a Modifier Letter Colon. This has no space like the fullwidth colon and is pretty much exactly the same as a regular colon but the symbol works. You can either copy and paste it from above or you can use the code point, U+A789
A colon is an invalid character for a Windows file name. You won't be able to allow ':' in the file name, but you can work around it.
You can either do what it sounds like you have already done; create a script that replaces these invalid characters with valid ones on the UNIX side. Or, you can take care of this on the Windows server with File Name Character Translation: http://support.microsoft.com/kb/289627
Other replacements I've found for reserved characters are
” ‹ › ⁎ ∕ ⑊ \︖ ꞉ ⏐
For example in python you could do:
fixed_name = orig_name.replace('\\\\','⑊')
forbidden_characters = '"*/:<>?\|'
unicode_characters = '”⁎∕꞉‹›︖\⏐'
for a, b in zip(forbidden_characters, unicode_characters):
fixed_name = fixed_name.replace(a, b)
It's probable from the filename you provided that the character you have in your filenames is not a literal colon :, which is a reserved character in Windows filenames, but a fullwidth colon : Instead. It's a Unicode character that looks very much like a colon, visually surrounded by spaces that you can't remove. You can handle it the very same way as any Unicode chacter, the code point is U+FF1A.
You can use the CJK(Chinese/Japan/Korean) one
":"
which is pretty generic.
Currently, you would use WSL, url for instructions: https://learn.microsoft.com/en-us/windows/wsl/install-win10.
You could then create a colon in your Linux Distro.
HOW TO NAME A FILE OR FOLDER USING A SYMBOL THAT LOOKS LIKE A COLON
In the example below, the font size is 12, with the exception of the symbol, which is set to Subscript, Bold and a font size of 16. The character code for the colon-like symbol is 02F8.
The reason for the Subscript setting is to position the symbol lower relative to its vertical position. The bold and larger font settings are applied so that the symbol is more discernible on the page, and have no affect when used in a file or folder name.
Example: (C˸) Symbol – Subscript, Calibri, Bold and font size of 16.
*Using Windows 7, and Word 2007

Resources