Fix for bug 100591. We need to replace illegal characters in file name before trying to use it during a file save. R=cavin, law, SR=alecf, mscott

This commit is contained in:
ducarroz%netscape.com 2002-02-12 03:57:39 +00:00
Родитель 073e999f03
Коммит 3ae0f8b9c3
5 изменённых файлов: 121 добавлений и 60 удалений

Просмотреть файл

@ -202,6 +202,42 @@ ConvertBufToPlainText(nsString &aConBuf)
return rv;
}
nsresult ConvertAndSanitizeFileName(const char * displayName, PRUnichar ** unicodeResult, char ** result)
{
char * unescapedName = PL_strdup(displayName);
if (!unescapedName)
return NS_ERROR_OUT_OF_MEMORY;
/* we need to convert the UTF-8 fileName to platform specific character set.
The display name is in UTF-8 because it has been escaped from JS
*/
nsUnescape(unescapedName);
nsAutoString ucs2Str = NS_ConvertUTF8toUCS2(unescapedName);
PR_FREEIF(unescapedName);
#if defined(XP_MAC)
/* We need to truncate the name to 31 characters, this even on MacOS X until the file API
correctly support long file name. Using a nsILocalFIle will do the trick...
*/
nsresult rv;
nsCOMPtr<nsILocalFile> aLocalFile(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
if (NS_SUCCEEDED(aLocalFile->SetUnicodeLeafName(ucs2Str.get())))
aLocalFile->GetUnicodeLeafName(getter_Copies(ucs2Str));
#endif
// replace platform specific path separator and illegale characters to avoid any confusion
ucs2Str.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '-');
nsresult rv = NS_OK;
if (result)
rv = ConvertFromUnicode(nsMsgI18NFileSystemCharset(), ucs2Str, result);
if (unicodeResult)
*unicodeResult = ToNewUnicode(ucs2Str);
return rv;
}
// ***************************************************
// jefft - this is a rather obscured class serves for Save Message As File,
// Save Message As Template, and Save Attachment to a file
@ -677,11 +713,18 @@ NS_IMETHODIMP
nsMessenger::SaveAttachment(const char * contentType, const char * url,
const char * displayName, const char * messageUri)
{
NS_ENSURE_ARG_POINTER(url);
#ifdef DEBUG_MESSENGER
printf("nsMessenger::SaveAttachment(%s)\n",url);
#endif
nsresult rv = NS_ERROR_OUT_OF_MEMORY;
char *unescapedUrl = nsnull;
nsCOMPtr<nsIFilePicker> filePicker =
do_CreateInstance("@mozilla.org/filepicker;1", &rv);
char * unescapedDisplayName = nsnull;
NS_ENSURE_SUCCESS(rv, rv);
PRInt16 dialogResult;
nsCOMPtr<nsILocalFile> localFile;
nsCOMPtr <nsILocalFile> lastSaveDir;
@ -689,38 +732,15 @@ nsMessenger::SaveAttachment(const char * contentType, const char * url,
nsXPIDLCString filePath;
nsXPIDLString defaultDisplayString;
if (NS_FAILED(rv)) goto done;
if (!url) goto done;
#ifdef DEBUG_MESSENGER
printf("nsMessenger::SaveAttachment(%s)\n",url);
#endif
unescapedUrl = PL_strdup(url);
if (!unescapedUrl) goto done;
if (!unescapedUrl)
return NS_ERROR_OUT_OF_MEMORY;
nsUnescape(unescapedUrl);
unescapedDisplayName = nsCRT::strdup(displayName);
if (!unescapedDisplayName) goto done;
nsUnescape(unescapedDisplayName);
/* we need to convert the UTF-8 fileName to platform specific character set.
The display name is in UTF-8 because it has been escaped from JS
*/
defaultDisplayString.Assign(NS_ConvertUTF8toUCS2(unescapedDisplayName));
nsCRT::free(unescapedDisplayName);
#if defined (XP_MAC)
{
/* We need to truncate the name to 31 characters, this even on MacOS X until the file API
correctly support long file name. Using a nsILocalFIle will do the trick...
*/
nsCOMPtr<nsILocalFile> aLocalFile(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
if (NS_SUCCEEDED(aLocalFile->SetUnicodeLeafName(defaultDisplayString.get())))
aLocalFile->GetUnicodeLeafName(getter_Copies(defaultDisplayString));
}
#endif
rv = ConvertAndSanitizeFileName(displayName, getter_Copies(defaultDisplayString), nsnull);
if (NS_FAILED(rv)) goto done;
filePicker->Init(
nsnull,
GetString(NS_LITERAL_STRING("Save Attachment").get()),
@ -736,24 +756,26 @@ nsMessenger::SaveAttachment(const char * contentType, const char * url,
filePicker->Show(&dialogResult);
if (dialogResult == nsIFilePicker::returnCancel)
goto done;
{
rv = NS_OK;
goto done;
}
rv = filePicker->GetFile(getter_AddRefs(localFile));
if (NS_FAILED(rv)) goto done;
rv = SetLastSaveDirectory(localFile);
if (NS_FAILED(rv))
goto done;
(void)SetLastSaveDirectory(localFile);
rv = localFile->GetPath(getter_Copies(filePath));
fileSpec = do_CreateInstance("@mozilla.org/filespec;1", &rv);
if (NS_FAILED(rv)) goto done;
fileSpec->SetNativePath(filePath);
rv = SaveAttachment(fileSpec, unescapedUrl, messageUri, contentType, nsnull);
done:
PR_FREEIF(unescapedUrl);
return rv;
PR_FREEIF(unescapedUrl);
return rv;
}
@ -771,7 +793,7 @@ nsMessenger::SaveAllAttachments(PRUint32 count,
nsCOMPtr<nsILocalFile> lastSaveDir;
nsCOMPtr<nsIFileSpec> fileSpec;
nsXPIDLCString dirName;
char *unescapedUrl = nsnull, *unescapedName = nsnull, *tempCStr = nsnull;
char *unescapedUrl = nsnull, *unescapedName = nsnull;
nsSaveAllAttachmentsState *saveState = nsnull;
PRInt16 dialogResult;
@ -813,13 +835,11 @@ nsMessenger::SaveAllAttachments(PRUint32 count,
nsFileSpec aFileSpec((const char *) dirName);
unescapedUrl = PL_strdup(urlArray[0]);
nsUnescape(unescapedUrl);
unescapedName = PL_strdup(displayNameArray[0]);
nsUnescape(unescapedName);
rv = ConvertFromUnicode(nsMsgI18NFileSystemCharset(), NS_ConvertUTF8toUCS2(unescapedName),
&tempCStr);
if (NS_FAILED(rv)) goto done;
PR_FREEIF(unescapedName);
unescapedName = tempCStr;
rv = ConvertAndSanitizeFileName(displayNameArray[0], nsnull, &unescapedName);
if (NS_FAILED(rv))
goto done;
aFileSpec += unescapedName;
rv = PromptIfFileExists(aFileSpec);
if (NS_FAILED(rv)) return rv;
@ -1756,8 +1776,7 @@ nsSaveMsgListener::OnStopRequest(nsIRequest* request, nsISupports* aSupport,
if (m_saveAllAttachmentsState->m_curIndex <
m_saveAllAttachmentsState->m_count)
{
char * unescapedUrl = nsnull, * unescapedName = nsnull,
* tempCStr = nsnull;
char * unescapedUrl = nsnull, * unescapedName = nsnull;
nsSaveAllAttachmentsState *state = m_saveAllAttachmentsState;
PRUint32 i = state->m_curIndex;
nsCOMPtr<nsIFileSpec> fileSpec;
@ -1767,13 +1786,11 @@ nsSaveMsgListener::OnStopRequest(nsIRequest* request, nsISupports* aSupport,
if (NS_FAILED(rv)) goto done;
unescapedUrl = PL_strdup(state->m_urlArray[i]);
nsUnescape(unescapedUrl);
unescapedName = PL_strdup(state->m_displayNameArray[i]);
nsUnescape(unescapedName);
rv = ConvertFromUnicode(nsMsgI18NFileSystemCharset(), NS_ConvertUTF8toUCS2(unescapedName),
&tempCStr);
if (NS_FAILED(rv)) goto done;
PR_FREEIF(unescapedName);
unescapedName = tempCStr;
rv = ConvertAndSanitizeFileName(state->m_displayNameArray[i], nsnull, &unescapedName);
if (NS_FAILED(rv))
goto done;
aFileSpec += unescapedName;
rv = m_messenger->PromptIfFileExists(aFileSpec);
if (NS_FAILED(rv)) goto done;

Просмотреть файл

@ -231,20 +231,17 @@ static PRUint32 StringHash(const char *ubuf)
nsresult NS_MsgHashIfNecessary(nsCAutoString &name)
{
#if defined(XP_MAC)
nsCAutoString illegalChars(":");
const PRUint32 MAX_LEN = 25;
#elif defined(XP_UNIX) || defined(XP_BEOS)
nsCAutoString illegalChars; // is this correct for BEOS?
const PRUint32 MAX_LEN = 55;
#elif defined(XP_WIN32)
nsCAutoString illegalChars("\"/\\[]:;=,|?<>*$");
const PRUint32 MAX_LEN = 55;
#elif defined(XP_OS2)
nsCAutoString illegalChars("\"/\\[]:;=,|?<>*$");
const PRUint32 MAX_LEN = 55;
#else
#error need_to_define_your_max_filename_length
#error need_to_define_your_max_filename_length
#endif
nsCAutoString illegalChars(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS);
nsCAutoString str(name);
// Given a filename, make it safe for filesystem

Просмотреть файл

@ -836,6 +836,9 @@ void nsExternalAppHandler::ExtractSuggestedFileNameFromChannel(nsIChannel* aChan
// ONLY if we got here, will we remember the suggested file name...
// The filename must be ASCII, see RFC 2183, section 2.3
CopyASCIItoUCS2(Substring(start, iter), mSuggestedFileName);
// replace platform specific path separator and illegal characters to avoid any confusion
mSuggestedFileName.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '-');
}
}
} // if we found a file name in the header disposition field
@ -940,6 +943,9 @@ nsresult nsExternalAppHandler::SetUpTempFile(nsIChannel * aChannel)
NS_UnescapeURL(leafName);
mSuggestedFileName = NS_ConvertUTF8toUCS2(leafName);
nsMemory::Free(leafName);
// replace platform specific path separator and illegal characters to avoid any confusion
mSuggestedFileName.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '-');
}
}

Просмотреть файл

@ -202,9 +202,9 @@ NS_IMETHODIMP nsFilePicker::Show(PRInt16 *retval)
result = ::GetSaveFileName(&ofn);
if (!result) {
// Error, find out what kind.
DWORD error = ::GetLastError();
if (error == ERROR_INVALID_PARAMETER) {
// Parameter error; probably the default file name is too long.
if (::GetLastError() == ERROR_INVALID_PARAMETER ||
::CommDlgExtendedError() == FNERR_INVALIDFILENAME) {
// probably the default file name is too long or contains illegal characters!
// Try again, without a starting file name.
ofn.lpstrFile[0] = 0;
result = ::GetSaveFileName(&ofn);
@ -322,6 +322,32 @@ NS_IMETHODIMP nsFilePicker::GetFileURL(nsIFileURL **aFileURL)
NS_IMETHODIMP nsFilePicker::SetDefaultString(const PRUnichar *aString)
{
mDefault = aString;
//First, make sure the file name is not too long!
PRInt32 nameLength;
PRInt32 nameIndex = mDefault.RFind("\\");
if (nameIndex == kNotFound)
nameIndex = 0;
else
nameIndex ++;
nameLength = mDefault.Length() - nameIndex;
if (nameLength > _MAX_FNAME) {
PRInt32 extIndex = mDefault.RFind(".");
if (extIndex == kNotFound)
extIndex = mDefault.Length();
//Let's try to shave the needed characters from the name part
PRInt32 charsToRemove = nameLength - _MAX_FNAME;
if (extIndex - nameIndex >= charsToRemove) {
mDefault.Cut(extIndex - charsToRemove, charsToRemove);
}
}
//Then, we need to replace illegal characters.
//At this stage, we cannot replace the backslash as the string might represent a file path.
mDefault.ReplaceChar(FILE_ILLEGAL_CHARACTERS, '-');
return NS_OK;
}

Просмотреть файл

@ -267,4 +267,19 @@ public:
#define LFSTR "\012"
#define CRLF "\015\012" /* A CR LF equivalent string */
#if defined(XP_MAC)
#define FILE_PATH_SEPARATOR ":"
#define FILE_ILLEGAL_CHARACTERS ""
#elif defined(XP_WIN) || defined(XP_OS2)
#define FILE_PATH_SEPARATOR "\\"
#define FILE_ILLEGAL_CHARACTERS "/:*?\"<>|"
#elif (defined(XP_UNIX) || defined(XP_BEOS)
#define FILE_PATH_SEPARATOR "/"
#define FILE_ILLEGAL_CHARACTERS ""
#elif
#error need_to_define_your_file_path_separator_and_illegal_characters
#endif
#endif /* nsCRT_h___ */