Checking in Boris Zbarsky's <bzbarsky@mit.edu> fix for bug 117269. Making mozilla not invent silly file extensions when saving files. r=law@netscape.com, rs=jaggernaut@netscape.com, jst@netscape.com

This commit is contained in:
jst%netscape.com 2002-02-20 07:50:52 +00:00
Родитель 5d4df6629c
Коммит 8fd2822bf1
16 изменённых файлов: 219 добавлений и 50 удалений

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

@ -126,6 +126,15 @@ nsHelperAppDialog.prototype = {
.getInterface( Components.interfaces.nsIDOMWindowInternal );
picker.init( parent, windowTitle, nsIFilePicker.modeSave );
picker.defaultString = aDefaultFile;
if (aSuggestedFileExtension) {
// aSuggestedFileExtension includes the period, so strip it
picker.defaultExtension = aSuggestedFileExtension.substring(1);
} else {
try {
picker.defaultExtension = this.mLauncher.MIMEInfo.primaryExtension;
} catch (ex) {
}
}
var wildCardExtension = "*";
if ( aSuggestedFileExtension ) {

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

@ -93,7 +93,7 @@ static PRBool PR_CALLBACK DeleteEntry(nsHashKey *aKey, void *aData, void* closur
static nsDefaultMimeTypeEntry defaultMimeEntries [] =
{
{ TEXT_PLAIN, "txt,text", "Text File", 'TEXT', 'ttxt' },
{ TEXT_HTML, "htm,html,shtml,ehtml", "HyperText Markup Language", 'TEXT', 'MOSS' },
{ TEXT_HTML, "html,htm,shtml,ehtml", "HyperText Markup Language", 'TEXT', 'MOSS' },
{ TEXT_RDF, "rdf", "Resource Description Framework", 'TEXT','ttxt' },
{ TEXT_XUL, "xul", "XML-Based User Interface Language", 'TEXT', 'ttxt' },
{ TEXT_XML, "xml,xsl,xbl", "Extensible Markup Language", 'TEXT', 'ttxt' },

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

@ -73,9 +73,20 @@ interface nsIFilePicker : nsISupports
void appendFilter(in wstring title,
in wstring filter);
/* what is this? */
/**
* The filename that should be suggested to the user as a default.
*
* @throws NS_ERROR_FAILURE on attempts to get
*/
attribute wstring defaultString;
/**
* The extension that should be associated with files of the type we
* want to work with. On some platforms, this extension will be
* automatically appended to filenames the user enters, if needed.
*/
attribute wstring defaultExtension;
/**
* The filter which is currently selected in the File Picker dialog
*

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

@ -257,6 +257,22 @@ NS_IMETHODIMP nsFilePicker::GetDefaultString(PRUnichar **aString)
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
//
// The default extension to use for files
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::GetDefaultExtension(PRUnichar **aExtension)
{
*aExtension = nsnull;
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const PRUnichar *aExtension)
{
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the display directory

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

@ -50,6 +50,8 @@ public:
// nsIFilePicker (less what's in nsBaseFilePicker)
NS_IMETHOD GetDefaultString(PRUnichar * *aDefaultString);
NS_IMETHOD SetDefaultString(const PRUnichar * aDefaultString);
NS_IMETHOD GetDefaultExtension(PRUnichar * *aDefaultExtension);
NS_IMETHOD SetDefaultExtension(const PRUnichar * aDefaultExtension);
NS_IMETHOD GetDisplayDirectory(nsILocalFile * *aDisplayDirectory);
NS_IMETHOD SetDisplayDirectory(nsILocalFile * aDisplayDirectory);
NS_IMETHOD GetFile(nsILocalFile * *aFile);

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

@ -699,6 +699,22 @@ NS_IMETHODIMP nsFilePicker::GetDefaultString(PRUnichar **aString)
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
//
// The default extension to use for files
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::GetDefaultExtension(PRUnichar **aExtension)
{
*aExtension = nsnull;
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const PRUnichar *aExtension)
{
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the display directory

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

@ -48,6 +48,8 @@ public:
// nsIFilePicker (less what's in nsBaseFilePicker)
NS_IMETHOD GetDefaultString(PRUnichar * *aDefaultString);
NS_IMETHOD SetDefaultString(const PRUnichar * aDefaultString);
NS_IMETHOD GetDefaultExtension(PRUnichar * *aDefaultExtension);
NS_IMETHOD SetDefaultExtension(const PRUnichar * aDefaultExtension);
NS_IMETHOD GetDisplayDirectory(nsILocalFile * *aDisplayDirectory);
NS_IMETHOD SetDisplayDirectory(nsILocalFile * aDisplayDirectory);
NS_IMETHOD GetFile(nsILocalFile * *aFile);

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

@ -932,6 +932,22 @@ NS_IMETHODIMP nsFilePicker::GetDefaultString(PRUnichar **aString)
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
//
// The default extension to use for files
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::GetDefaultExtension(PRUnichar **aExtension)
{
*aExtension = nsnull;
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const PRUnichar *aExtension)
{
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the display directory

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

@ -48,6 +48,8 @@ public:
// nsIFilePicker (less what's in nsBaseFilePicker)
NS_IMETHOD GetDefaultString(PRUnichar * *aDefaultString);
NS_IMETHOD SetDefaultString(const PRUnichar * aDefaultString);
NS_IMETHOD GetDefaultExtension(PRUnichar * *aDefaultExtension);
NS_IMETHOD SetDefaultExtension(const PRUnichar * aDefaultExtension);
NS_IMETHOD GetDisplayDirectory(nsILocalFile * *aDisplayDirectory);
NS_IMETHOD SetDisplayDirectory(nsILocalFile * aDisplayDirectory);
NS_IMETHOD GetFile(nsILocalFile * *aFile);

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

@ -325,6 +325,22 @@ NS_IMETHODIMP nsFilePicker::GetDefaultString(PRUnichar **aString)
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
//
// The default extension to use for files
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::GetDefaultExtension(PRUnichar **aExtension)
{
*aExtension = nsnull;
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const PRUnichar *aExtension)
{
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the display directory

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

@ -47,6 +47,8 @@ public:
// nsIFilePicker (less what's in nsBaseFilePicker)
NS_IMETHOD GetDefaultString(PRUnichar * *aDefaultString);
NS_IMETHOD SetDefaultString(const PRUnichar * aDefaultString);
NS_IMETHOD GetDefaultExtension(PRUnichar * *aDefaultExtension);
NS_IMETHOD SetDefaultExtension(const PRUnichar * aDefaultExtension);
NS_IMETHOD GetDisplayDirectory(nsILocalFile * *aDisplayDirectory);
NS_IMETHOD SetDisplayDirectory(nsILocalFile * aDisplayDirectory);
NS_IMETHOD GetFile(nsILocalFile * *aFile);

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

@ -44,6 +44,8 @@ NS_IMPL_ISUPPORTS1(nsFilePicker, nsIFilePicker)
char nsFilePicker::mLastUsedDirectory[MAX_PATH+1] = { 0 };
#define MAX_EXTENSION_LENGTH 10
//-------------------------------------------------------------------------
//
// nsFilePicker constructor
@ -147,6 +149,8 @@ NS_IMETHODIMP nsFilePicker::Show(PRInt16 *retval)
ofn.lStructSize = sizeof(ofn);
char extensionBuffer[MAX_EXTENSION_LENGTH+1] = "";
PRInt32 l = (mFilterList.Length()+2)*2;
char *filterBuffer = (char*) nsMemory::Alloc(l);
int len = WideCharToMultiByte(CP_ACP, 0,
@ -160,7 +164,7 @@ NS_IMETHODIMP nsFilePicker::Show(PRInt16 *retval)
if (initialDir && *initialDir) {
ofn.lpstrInitialDir = initialDir;
}
ofn.lpstrTitle = title;
ofn.lpstrFilter = filterBuffer;
ofn.nFilterIndex = mSelectedType;
@ -170,24 +174,38 @@ NS_IMETHODIMP nsFilePicker::Show(PRInt16 *retval)
ofn.Flags = OFN_NOCHANGEDIR | OFN_SHAREAWARE | OFN_LONGNAMES | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
// Get file extension from suggested filename
// to detect if we are saving an html file
//XXX: nsIFile SHOULD HAVE A GetExtension() METHOD!
PRInt32 extIndex = mDefault.RFind(".");
if ( extIndex >= 0) {
nsAutoString ext;
mDefault.Right(ext, mDefault.Length() - extIndex);
// Should we test for ".cgi", ".asp", ".jsp" and other
// "generated" html pages?
if (!mDefaultExtension.IsEmpty()) {
// Someone was cool and told us what to do
char *convertedExt = ConvertToFileSystemCharset(mDefaultExtension.get());
if (!convertedExt) {
mDefaultExtension.ToCString(extensionBuffer, MAX_EXTENSION_LENGTH);
}
else {
PL_strncpyz(extensionBuffer, convertedExt, MAX_EXTENSION_LENGTH+1);
nsMemory::Free( convertedExt );
}
ofn.lpstrDefExt = extensionBuffer;
}
else {
// Get file extension from suggested filename
// to detect if we are saving an html file
//XXX: nsIFile SHOULD HAVE A GetExtension() METHOD!
PRInt32 extIndex = mDefault.RFind(".");
if ( extIndex >= 0) {
nsAutoString ext;
mDefault.Right(ext, mDefault.Length() - extIndex);
// Should we test for ".cgi", ".asp", ".jsp" and other
// "generated" html pages?
if ( ext.EqualsIgnoreCase(".htm") ||
ext.EqualsIgnoreCase(".html") ||
ext.EqualsIgnoreCase(".shtml") ) {
// This is supposed to append ".htm" if user doesn't supply an extension
//XXX Actually, behavior is sort of weird:
// often appends ".html" even if you have an extension
// It obeys your extension if you put quotes around name
ofn.lpstrDefExt = htmExt;
if ( ext.EqualsIgnoreCase(".htm") ||
ext.EqualsIgnoreCase(".html") ||
ext.EqualsIgnoreCase(".shtml") ) {
// This is supposed to append ".htm" if user doesn't supply an extension
//XXX Actually, behavior is sort of weird:
// often appends ".html" even if you have an extension
// It obeys your extension if you put quotes around name
ofn.lpstrDefExt = htmExt;
}
}
}
@ -355,6 +373,25 @@ NS_IMETHODIMP nsFilePicker::GetDefaultString(PRUnichar **aString)
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
//
// The default extension to use for files
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::GetDefaultExtension(PRUnichar **aExtension)
{
*aExtension = ToNewUnicode(mDefaultExtension);
if (!*aExtension)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const PRUnichar *aExtension)
{
mDefaultExtension = aExtension;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the filter index

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

@ -47,6 +47,8 @@ public:
// nsIFilePicker (less what's in nsBaseFilePicker)
NS_IMETHOD GetDefaultString(PRUnichar * *aDefaultString);
NS_IMETHOD SetDefaultString(const PRUnichar * aDefaultString);
NS_IMETHOD GetDefaultExtension(PRUnichar * *aDefaultExtension);
NS_IMETHOD SetDefaultExtension(const PRUnichar * aDefaultExtension);
NS_IMETHOD GetDisplayDirectory(nsILocalFile * *aDisplayDirectory);
NS_IMETHOD SetDisplayDirectory(nsILocalFile * aDisplayDirectory);
NS_IMETHOD GetFilterIndex(PRInt32 *aFilterIndex);
@ -73,6 +75,7 @@ protected:
PRInt16 mMode;
nsCString mFile;
nsString mDefault;
nsString mDefaultExtension;
nsString mFilterList;
nsIUnicodeEncoder* mUnicodeEncoder;
nsIUnicodeDecoder* mUnicodeDecoder;

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

@ -232,7 +232,9 @@ function foundHeaderInfo(aSniffer, aData)
var defaultFileName = getDefaultFileName(aData.fileName,
aSniffer.suggestedFileName,
aSniffer.uri);
fp.defaultString = getNormalizedLeafName(defaultFileName, contentType);
var defaultExtension = getDefaultExtension(defaultFileName, aSniffer.uri, contentType);
fp.defaultExtension = defaultExtension;
fp.defaultString = getNormalizedLeafName(defaultFileName, defaultExtension);
if (fp.show() == Components.interfaces.nsIFilePicker.returnCancel || !fp.file)
return;
@ -243,7 +245,6 @@ function foundHeaderInfo(aSniffer, aData)
prefs.setComplexValue("dir", nsILocalFile, directory);
fp.file.leafName = validateFileName(fp.file.leafName);
fp.file.leafName = getNormalizedLeafName(fp.file.leafName, contentType);
// If we're saving a document, and are saving either in complete mode or
// as converted text, pass the document to the web browser persist component.
@ -510,36 +511,64 @@ function validateFileName(aFileName)
return aFileName.replace(re, "_");
}
function getNormalizedLeafName(aFile, aContentType)
function getNormalizedLeafName(aFile, aDefaultExtension)
{
// Fix up the file name we're saving to so that if the user enters
// no extension, an appropriate one is appended.
var leafName = aFile;
var mimeInfo = getMIMEInfoForType(aContentType);
if (mimeInfo) {
var extCount = { };
var extList = { };
mimeInfo.GetFileExtensions(extCount, extList);
const stdURLContractID = "@mozilla.org/network/standard-url;1";
const stdURLIID = Components.interfaces.nsIURI;
var uri = Components.classes[stdURLContractID].createInstance(stdURLIID);
var url = uri.QueryInterface(Components.interfaces.nsIURL);
url.filePath = aFile;
if (aContentType == "text/html") {
if ((url.fileExtension &&
url.fileExtension != "htm" && url.fileExtension != "html") ||
(!url.fileExtension))
return leafName + ".html";
}
if (!url.fileExtension)
return leafName + "." + extList.value[0];
if (!aDefaultExtension)
return aFile;
// Fix up the file name we're saving to to include the default extension
const stdURLContractID = "@mozilla.org/network/standard-url;1";
const stdURLIID = Components.interfaces.nsIURL;
var url = Components.classes[stdURLContractID].createInstance(stdURLIID);
url.filePath = aFile;
if (url.fileExtension != aDefaultExtension) {
return aFile + "." + aDefaultExtension;
}
return aFile;
}
function getDefaultExtension(aFilename, aURI, aContentType)
{
// This mirrors some code in nsExternalHelperAppService::DoContent
// Use the filename first and then the URI if that fails
var mimeInfo = getMIMEInfoForType(aContentType);
// First try the extension from the filename
const stdURLContractID = "@mozilla.org/network/standard-url;1";
const stdURLIID = Components.interfaces.nsIURL;
var url = Components.classes[stdURLContractID].createInstance(stdURLIID);
url.filePath = aFilename;
var ext = url.fileExtension;
if (ext && mimeInfo.ExtensionExists(ext)) {
return ext;
}
// Well, that failed. Now try the extension from the URI
var urlext;
try {
url = aURI.QueryInterface(Components.interfaces.nsIURL);
urlext = url.fileExtension;
} catch (e) {
}
if (urlext && mimeInfo.ExtensionExists(urlext)) {
return urlext;
}
else {
try {
return mimeInfo.primaryExtension;
}
catch (e) {
// Fall back on the extensions in the filename and URI for lack
// of anything better.
return ext || urlext;
}
}
return leafName;
}
function isDocumentType(aContentType)

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

@ -100,6 +100,10 @@ nsFilePicker.prototype = {
set defaultString(a) { this.mDefaultString = a; },
get defaultString() { return this.mDefaultString; },
/* attribute wstring defaultExtension */
set defaultExtension(ext) { },
get defaultExtension() { return ""; },
/* attribute long filterIndex; */
set filterIndex(a) { this.mFilterIndex = a; },
get filterIndex() { return this.mFilterIndex; },

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

@ -100,6 +100,10 @@ nsFilePicker.prototype = {
set defaultString(a) { this.mDefaultString = a; },
get defaultString() { return this.mDefaultString; },
/* attribute wstring defaultExtension */
set defaultExtension(ext) { },
get defaultExtension() { return ""; },
/* attribute long filterIndex; */
set filterIndex(a) { this.mFilterIndex = a; },
get filterIndex() { return this.mFilterIndex; },