Composer Publishing fixes: Add support to not upload images (b=134001,r=akkana, sr=kin), Don't save site data if not successfully published (b=132604, r=akkana, sr=kin), improve error handling (b=126258, r=andreww, sr=dveditz), Make 'CheckAndSaveDocument' do publishing for remote url (b=126450, r=brade, sr=kin), Save command should publish if remote file (b=132634, r=brade,sr=kin), Fix FTP publishing (b=133823, r=brade, sr=kin) all are: a=asa, adt1.0.0+

This commit is contained in:
cmanske%netscape.com 2002-04-04 15:14:32 +00:00
Родитель a7a0d0cd80
Коммит d84a792769
5 изменённых файлов: 561 добавлений и 265 удалений

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

@ -354,7 +354,10 @@ var nsSaveCommand =
var docUrl = GetDocumentUrl();
var scheme = GetScheme(docUrl);
if (scheme && scheme != "file")
{
goDoCommand("cmd_publish");
return true;
}
FinishHTMLSource();
result = SaveDocument(IsUrlAboutBlank(docUrl), false, editorShell.contentsMIMEType);
@ -445,10 +448,17 @@ var nsPublishCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return window.editorShell && window.editorShell.documentEditable
&& (window.editorShell.documentModified ||
IsUrlAboutBlank(GetDocumentUrl()) ||
window.gHTMLSourceChanged);
if (window.editorShell && window.editorShell.documentEditable)
{
// Always allow publishing when editing a local document,
// otherwise the document modified state would prevent that
// when you first open any local file.
var docUrl = GetDocumentUrl();
return window.editorShell.documentModified || window.gHTMLSourceChanged
|| IsUrlAboutBlank(docUrl) || GetScheme(docUrl) == "file";
}
return false;
},
doCommand: function(aCommand)
@ -472,9 +482,9 @@ var nsPublishCommand =
// Try to get publish data from the document url
publishData = CreatePublishDataFromUrl(docUrl);
// If none, use default publishing site
if (!publishData)
publishData = GetPublishDataFromSiteName(GetDefaultPublishSiteName(), filename);
// If none, use default publishing site? Need a pref for this
//if (!publishData)
// publishData = GetPublishDataFromSiteName(GetDefaultPublishSiteName(), filename);
}
if (showPublishDialog || !publishData)
@ -561,12 +571,13 @@ function GetSuggestedFileName(aDocumentURLString, aMIMEType, aHTMLDoc)
{
var docURI = null;
try {
docURI = Components.classes["@mozilla.org/network/standard-url;1"].createInstance(Components.interfaces.nsIURI);
docURI.spec = aDocumentURLString;
var docURL = docURI.QueryInterface(Components.interfaces.nsIURL);
var ioService = GetIOService();
docURI = ioService.newURI(aDocumentURLString, window.editorShell.GetDocumentCharacterSet(), null);
docURI = docURI.QueryInterface(Components.interfaces.nsIURL);
// grab the file name
var url = docURL.fileBaseName;
var url = docURI.fileBaseName;
if (url)
return url+extension;
} catch(e) {}
@ -585,8 +596,7 @@ function GetSuggestedFileName(aDocumentURLString, aMIMEType, aHTMLDoc)
}
// if we still don't have a file name, let's just go with "untitled"
// shouldn't this come out of a string bundle? I'm shocked localizers haven't complained!
return "untitled" + extension;
return GetString("untitled") + extension;
}
// returns file picker result
@ -631,8 +641,7 @@ function PromptForSaveLocation(aDoSaveAsText, aEditorType, aMIMEType, ahtmlDocum
var isLocalFile = true;
try {
var docURI = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIURI);
docURI.spec = aDocumentURLString;
var docURI = ioService.newURI(aDocumentURLString, window.editorShell.GetDocumentCharacterSet(), null);
isLocalFile = docURI.schemeIs("file");
}
catch (e) {}
@ -789,6 +798,7 @@ function GetOutputFlags(aMimeType, aWrapColumn)
}
// returns number of column where to wrap
const nsIPlaintextEditor = Components.interfaces.nsIPlaintextEditor;
function GetWrapColumn()
{
var wrapCol = 72;
@ -812,9 +822,9 @@ function GetPromptService()
return promptService;
}
const gShowDebugOutputStateChange = false;
const gShowDebugOutputStateChange = true;
const gShowDebugOutputProgress = false;
const gShowDebugOutputStatusChange = false;
const gShowDebugOutputStatusChange = true;
const gShowDebugOutputLocationChange = false;
const gShowDebugOutputSecurityChange = false;
@ -852,6 +862,8 @@ var gEditorOutputProgressListener =
dump(" STATE_IS_NETWORK ");
dump("\n * requestSpec="+requestSpec+", pubSpec="+pubSpec+", aStatus="+aStatus+"\n");
DumpDebugStatus(aStatus);
}
// Detect start of file upload of any file:
@ -870,61 +882,85 @@ var gEditorOutputProgressListener =
}
}
// Detect end of file upload of HTML file:
// Detect end of file upload of any file:
if ((aStateFlags & nsIWebProgressListener.STATE_STOP) && requestSpec)
{
// Show final status in progress dialog when we receive the STOP
// notification for the destination file
if (gProgressDialog)
// New: Stop at the first bad aStatus, rather than waiting for STATE_IS_NETWORK message
try {
// check http channel for response: 200 range is ok; other ranges are not
var httpChannel = aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
var httpResponse = httpChannel.responseStatus;
if (httpResponse < 200 || httpResponse >= 300)
aStatus = httpResponse; // not a real error but enough to pass check below
} catch(e) {}
// Notify progress dialog when we receive the STOP
// notification for a file if there was an error
// or for a successful finish only if
// destination url is contains the publishing location
if (gProgressDialog &&
(aStatus != 0
|| requestSpec && requestSpec.indexOf(gPublishData.publishUrl) == 0))
{
try {
gProgressDialog.SetProgressFinished(GetFilename(requestSpec), aStatus);
} catch(e) {
dump(" Exception error calling SetProgressFinished\n");
}
} catch(e) {}
}
if (aStatus)
{
// Cancel the publish
gPersistObj.cancelSave();
//XXX TODO: we should provide more meaningful errors (if possible)
var failedStr = GetString("PublishFailed");
// XXX We don't have error codes in IDL !!!
// Give better error messages for cases we know about:
if (aStatus == 2152398868) // Bad directory
{
var requestFilename = requestSpec ? GetFilename(requestSpec) : "";
var dir = (gPublishData.filename == requestFilename) ?
gPublishData.docDir : gPublishData.otherDir;
failedStr = GetString("PublishDirFailed").replace(/%dir%/, gPublishData.docDir);
if (gProgressDialog)
gProgressDialog.SetStatusMessage(failedStr);
// Remove directory from saved prefs
RemovePublishSubdirectoryFromPrefs(gPublishData, dir);
}
// Do not do any commands after failure
gCommandAfterPublishing = null;
// Show error in progress dialog and let user close it
if (gProgressDialog)
{
try {
// Tell dialog final status value so it can show appropriate message
gProgressDialog.SetProgressFinished(null, aStatus);
} catch (e) {
dump(" **** EXCEPTION ERROR CALLING ProgressDialog.SetProgressFinished\n");
AlertWithTitle(GetString("Publish"), failedStr);
}
}
else
{
// In case we ever get final alert with no dialog
AlertWithTitle(GetString("Publish"), failedStr);
// Final cleanup
FinishPublishing();
}
return; // we don't want to change location or reset mod count, etc.
}
if ((aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK))
{
// FINISHED ALL PUBLISHING
try {
// check http channel for response: 200 range is ok; other ranges are not
var httpChannel = aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
var httpResponse = httpChannel.responseStatus;
if (httpResponse < 200 || httpResponse >= 300)
aStatus = httpResponse; // not a real error but enough to pass check below
} catch(e) {}
if (aStatus)
{
// Cancel the publish
gPersistObj.cancelSave();
//XXX TODO: we should provide more meaningful errors (if possible)
var failedStr = GetString("PublishFailed");
// Show error in progress dialog and let user close it
if (gProgressDialog)
{
try {
// Tell dialog final status value so it can show appropriate message
gProgressDialog.SetProgressFinished(null, aStatus);
} catch (e) {
dump(" **** EXCEPTION ERROR CALLING ProgressDialog.SetProgressFinished\n");
AlertWithTitle(GetString("Publish"), failedStr);
}
}
else
{
// In case we ever get final alert with no dialog
AlertWithTitle(GetString("Publish"), failedStr);
// Final cleanup
FinishPublishing();
}
return; // we don't want to change location or reset mod count, etc.
}
// All files are finished uploading
// Publishing succeeded...
try {
// Get the new docUrl from the "browse location" in case "publish location" was FTP
var urlstring = GetDocUrlFromPublishData(gPublishData);
@ -937,18 +973,26 @@ var gEditorOutputProgressListener =
// Set UI based on whether we're editing a remote or local url
SetSaveAndPublishUI(urlstring);
// Save publishData to prefs
if (publishData.savePublishData)
SavePublishDataToPrefs(publishData);
else
SavePassword();
} catch (e) {}
// Ask progress dialog to close,
// "false" = don't force it if user checked checkbox to keep it open
// Save publishData to prefs
if (gPublishData)
{
if (gPublishData.savePublishData)
{
// We published successfully, so we can safely
// save docDir and otherDir to prefs
gPublishData.saveDirs = true;
SavePublishDataToPrefs(gPublishData);
}
else
SavePassword(gPublishData);
}
// Ask progress dialog to close, but it may not
// if user checked checkbox to keep it open
if (gProgressDialog)
gProgressDialog.CloseDialog(false);
gProgressDialog.RequestCloseDialog();
else
FinishPublishing();
}
@ -977,9 +1021,6 @@ var gEditorOutputProgressListener =
else if(gPersistObj.currentState == gPersistObj.PERSIST_STATE_FINISHED)
{
dump(" PERSISTER HAS FINISHED SAVING DATA\n\n\n");
// Allow editing again
// XXXX WE REALLY SHOULDN'T DO THIS!!!
// SetDocumentEditable(true);
}
}
}
@ -1005,37 +1046,8 @@ var gEditorOutputProgressListener =
dump("***** request: " + channel.URI.spec + "\n");
}
catch (e) { dump(" couldn't get request\n"); }
if (aStatus == 2152398852)
dump("***** status is UNKNOWN_TYPE\n");
else if (aStatus == 2152398853)
dump("***** status is DESTINATION_NOT_DIR\n");
else if (aStatus == 2152398854)
dump("***** status is TARGET_DOES_NOT_EXIST\n");
else if (aStatus == 2152398856)
dump("***** status is ALREADY_EXISTS\n");
else if (aStatus == 2152398858)
dump("***** status is DISK_FULL\n");
else if (aStatus == 2152398860)
dump("***** status is NOT_DIRECTORY\n");
else if (aStatus == 2152398861)
dump("***** status is IS_DIRECTORY\n");
else if (aStatus == 2152398862)
dump("***** status is IS_LOCKED\n");
else if (aStatus == 2152398863)
dump("***** status is TOO_BIG\n");
else if (aStatus == 2152398865)
dump("***** status is NAME_TOO_LONG\n");
else if (aStatus == 2152398866)
dump("***** status is NOT_FOUND\n");
else if (aStatus == 2152398867)
dump("***** status is READ_ONLY\n");
else if (aStatus == 2152398868)
dump("***** status is DIR_NOT_EMPTY\n");
else if (aStatus == 2152398869)
dump("***** status is ACCESS_DENIED\n");
else
dump("***** status is " + aStatus + "\n");
DumpDebugStatus(aStatus);
if (gPersistObj)
{
@ -1074,23 +1086,9 @@ var gEditorOutputProgressListener =
// nsIPrompt
alert : function(dlgTitle, text)
{
// If Progress dialog is up, put message in there instead of Alert
if (gProgressDialog)
{
try {
gProgressDialog.SetStatusMessage(failedStr);
} catch (e) {
dump(" nsIPrompt::Alert EXCEPTION ERROR CALLING ProgressDialog.SetStatusMessage\n");
AlertWithTitle(dlgTitle, text);
}
}
else
{
AlertWithTitle(dlgTitle, text);
CancelPublishing();
}
AlertWithTitle(dlgTitle, text, gProgressDialog ? gProgressDialog : window);
},
alertCheck : function(dialogTitle, text, checkBoxLabel, checkValue)
alertCheck : function(dialogTitle, text, checkBoxLabel, checkObj)
{
AlertWithTitle(dialogTitle, text);
},
@ -1098,14 +1096,14 @@ var gEditorOutputProgressListener =
{
return ConfirmWithTitle(dlgTitle, text, null, null);
},
confirmCheck : function(dlgTitle, text, checkBoxLabel, checkValue)
confirmCheck : function(dlgTitle, text, checkBoxLabel, checkObj)
{
var promptServ = GetPromptService();
if (!promptServ)
return;
promptServ.confirmEx(window, dlgTitle, text, nsIPromptService.STD_OK_CANCEL_BUTTONS,
"", "", "", checkBoxLabel, checkValue, outButtonPressed);
"", "", "", checkBoxLabel, checkObj, outButtonPressed);
},
confirmEx : function(dlgTitle, text, btnFlags, btn0Title, btn1Title, btn2Title, checkBoxLabel, checkVal, outBtnPressed)
{
@ -1117,34 +1115,47 @@ var gEditorOutputProgressListener =
btn0Title, btn1Title, btn2Title,
checkBoxLabel, checkVal, outBtnPressed);
},
prompt : function(dlgTitle, text, inoutText, checkBoxLabel, checkValue)
prompt : function(dlgTitle, text, inoutText, checkBoxLabel, checkObj)
{
var promptServ = GetPromptService();
if (!promptServ)
return false;
return promptServ.prompt(window, dlgTitle, text, inoutText, checkBoxLabel, checkValue);
return promptServ.prompt(window, dlgTitle, text, inoutText, checkBoxLabel, checkObj);
},
promptPassword : function(dlgTitle, text, password, checkBoxLabel, checkValue)
promptPassword : function(dlgTitle, text, pwObj, checkBoxLabel, savePWObj)
{
var promptServ = GetPromptService();
if (!promptServ)
return false;
return false;
var ret = false;
try {
// Note difference with nsIAuthPrompt::promptPassword, which has
// just "in" savePassword param, while nsIPrompt is "inout"
// Initialize with user's previous preference for this site
if (gPublishData)
savePWObj.value = gPublishData.savePassword;
ret = promptServ.promptPassword(gProgressDialog ? gProgressDialog : window,
dlgTitle, text, pwObj, checkBoxLabel, savePWObj);
if (!ret)
setTimeout(CancelPublishing,0);
if (ret && gPublishData)
UpdateUsernamePasswordFromPrompt(gPublishData, gPublishData.username, pwObj.value, savePWObj.value);
} catch(e) {}
var ret = promptServ.promptPassword(window, dlgTitle, text, password, checkBoxLabel, checkValue);
if (!ret)
setTimeout("CancelPublishing()",0);
return ret;
},
promptUsernameAndPassword : function(dlgTitle, text, login, pw, checkBoxLabel, checkValue)
promptUsernameAndPassword : function(dlgTitle, text, userObj, pwObj, checkBoxLabel, savePWObj)
{
var promptServ = GetPromptService();
if (!promptServ)
return false;
var ret = promptServ.promptUsernameAndPassword(window, dlgTitle, text, login, pw, checkBoxLabel, checkValue);
var ret = PromptUsernameAndPassword(dlgTitle, text, savePWObj, userObj, pwObj);
if (!ret)
setTimeout("CancelPublishing()",0);
setTimeout(CancelPublishing,0);
return ret;
},
select : function(dlgTitle, text, count, selectList, outSelection)
@ -1163,11 +1174,11 @@ var gEditorOutputProgressListener =
if (!promptServ)
return false;
var saveCheck = {value:savePW};
var savePWObj = {value:savePW};
var ret = promptServ.prompt(gProgressDialog ? gProgressDialog : window,
dlgTitle, text, defaultText, pwrealm, saveCheck);
dlgTitle, text, defaultText, pwrealm, savePWObj);
if (!ret)
setTimeout("CancelPublishing()",0);
setTimeout(CancelPublishing,0);
return ret;
},
@ -1175,7 +1186,7 @@ var gEditorOutputProgressListener =
{
var ret = PromptUsernameAndPassword(dlgTitle, text, savePW, userObj, pwObj);
if (!ret)
setTimeout("CancelPublishing()",0);
setTimeout(CancelPublishing,0);
return ret;
},
@ -1187,16 +1198,23 @@ var gEditorOutputProgressListener =
if (!promptServ)
return false;
var saveCheck = {value:savePW};
// Note difference with nsIPrompt::promptPassword, which has
// "inout" savePassword param, while nsIAuthPrompt is just "in"
// Also nsIAuth doesn't supply "checkBoxLabel"
// Initialize with user's previous preference for this site
var savePWObj = {value:savePW};
// Initialize with user's previous preference for this site
if (gPublishData)
saveCheck.value = gPublishData.savePassword;
savePWObj.value = gPublishData.savePassword;
ret = promptServ.promptPassword(gProgressDialog ? gProgressDialog : window,
dlgTitle, text, pwObj, GetString("SavePassword"), saveCheck);
dlgTitle, text, pwObj, GetString("SavePassword"), savePWObj);
if (!ret)
setTimeout(CancelPublishing,0);
if (ret && gPublishData)
UpdateUsernamePasswordFromPrompt(gPublishData, gPublishData.username, pwObj.value, saveCheck.value);
UpdateUsernamePasswordFromPrompt(gPublishData, gPublishData.username, pwObj.value, savePWObj.value);
} catch(e) {}
return ret;
@ -1216,29 +1234,63 @@ function PromptUsernameAndPassword(dlgTitle, text, savePW, userObj, pwObj)
if (!promptServ)
return false;
var saveCheck = {value:savePW};
var savePWObj = {value:savePW};
// Initialize with user's previous preference for this site
if (gPublishData)
{
// HTTP put uses this dialog if either username or password is bad,
// so prefill username input field with the previous value for modification
saveCheck.value = gPublishData.savePassword;
savePWObj.value = gPublishData.savePassword;
if (!userObj.value)
userObj.value = gPublishData.username;
}
ret = promptServ.promptUsernameAndPassword(gProgressDialog ? gProgressDialog : window,
dlgTitle, text, userObj, pwObj,
GetString("SavePassword"), saveCheck);
GetString("SavePassword"), savePWObj);
if (ret && gPublishData)
UpdateUsernamePasswordFromPrompt(gPublishData, userObj.value, pwObj.value, saveCheck.value);
UpdateUsernamePasswordFromPrompt(gPublishData, userObj.value, pwObj.value, savePWObj.value);
} catch (e) {}
return ret;
}
function DumpDebugStatus(aStatus)
{
if (aStatus == 2152398852)
dump("***** status is UNKNOWN_TYPE\n");
else if (aStatus == 2152398853)
dump("***** status is DESTINATION_NOT_DIR\n");
else if (aStatus == 2152398854)
dump("***** status is TARGET_DOES_NOT_EXIST\n");
else if (aStatus == 2152398856)
dump("***** status is ALREADY_EXISTS\n");
else if (aStatus == 2152398858)
dump("***** status is DISK_FULL\n");
else if (aStatus == 2152398860)
dump("***** status is NOT_DIRECTORY\n");
else if (aStatus == 2152398861)
dump("***** status is IS_DIRECTORY\n");
else if (aStatus == 2152398862)
dump("***** status is IS_LOCKED\n");
else if (aStatus == 2152398863)
dump("***** status is TOO_BIG\n");
else if (aStatus == 2152398865)
dump("***** status is NAME_TOO_LONG\n");
else if (aStatus == 2152398866)
dump("***** status is NOT_FOUND\n");
else if (aStatus == 2152398867)
dump("***** status is READ_ONLY\n");
else if (aStatus == 2152398868)
dump("***** status is DIR_NOT_EMPTY\n");
else if (aStatus == 2152398869)
dump("***** status is ACCESS_DENIED\n");
else
dump("***** status is " + aStatus + "\n");
}
// Update any data that the user supplied in a prompt dialog
function UpdateUsernamePasswordFromPrompt(publishData, username, password, savePassword)
{
@ -1424,9 +1476,11 @@ function SaveDocument(aSaveAs, aSaveCopy, aMimeType)
return success;
}
//------------------------------- Publishing
var gPublishData;
var gProgressDialog;
var gCommandAfterPublishing = null;
function Publish(publishData)
{
@ -1442,21 +1496,25 @@ function Publish(publishData)
if (!gPublishData.docURI)
return false;
gPublishData.otherFilesURI = CreateURIFromPublishData(publishData, false);
if (gPublishData.publishOtherFiles)
gPublishData.otherFilesURI = CreateURIFromPublishData(publishData, false);
else
gPublishData.otherFilesURI = null;
if (gShowDebugOutputStateChange)
{
dump("\n *** publishData: PublishUrl="+publishData.publishUrl+", BrowseUrl="+publishData.browseUrl+
", Username="+publishData.username+", Dir="+publishData.docDir+
", Filename="+publishData.filename+"\n");
dump(" * gPublishData.docURI.spec="+gPublishData.docURI.spec+"\n");
// dump(" * gPublishData.docURI.spec w/o pass="+StripPassword(gPublishData.docURI.spec)+", PublishOtherFiles="+gPublishData.publishOtherFiles+"\n");
dump(" * gPublishData.docURI.spec w/o pass="+gPublishData.docURI.spec+", PublishOtherFiles="+gPublishData.publishOtherFiles+"\n");
}
// XXX Missing username or password will make FTP fail
// and it won't call us for prompt dialog (bug 132320),
// so we should do the prompt before trying to publish
if (GetScheme(publishData.publishUrl) == "ftp" &&
(!publishData.username || !publishData.password))
// XXX Missing username will make FTP fail
// and it won't call us for prompt dialog (bug 132320)
// (It does prompt if just password is missing)
// So we should do the prompt ourselves before trying to publish
if (GetScheme(publishData.publishUrl) == "ftp" && !publishData.username)
{
var message = GetString("PromptFTPUsernamePassword").replace(/%host%/, GetHost(publishData.publishUrl));
var savePWobj = {value:publishData.savePassword};
@ -1469,8 +1527,11 @@ function Publish(publishData)
gPublishData.docURI.username = publishData.username;
gPublishData.docURI.password = publishData.password;
gPublishData.otherFilesURI.username = publishData.username;
gPublishData.otherFilesURI.password = publishData.password;
if (gPublishData.otherFilesURI)
{
gPublishData.otherFilesURI.username = publishData.username;
gPublishData.otherFilesURI.password = publishData.password;
}
}
try {
@ -1481,7 +1542,7 @@ function Publish(publishData)
// Start progress monitoring
gProgressDialog =
window.openDialog("chrome://editor/content/EditorPublishProgress.xul", "_blank",
"chrome,dependent", gPublishData, gPersistObj);
"chrome,dependent,titlebar", gPublishData, gPersistObj);
} catch (e) {}
@ -1506,12 +1567,14 @@ function CancelPublishing()
gPersistObj.cancelSave(); // Cancel all networking transactions
} catch (e) {}
// If canceling publishing do not do any commands after this
gCommandAfterPublishing = null;
if (gProgressDialog)
{
// Close Progress dialog
// "true" will force close,
// (this will call FinishPublishing())
gProgressDialog.CloseDialog(true);
gProgressDialog.CloseDialog();
}
else
FinishPublishing();
@ -1522,7 +1585,14 @@ function FinishPublishing()
SetDocumentEditable(true);
gProgressDialog = null;
gPublishData = null;
window._content.focus();
if (gCommandAfterPublishing)
{
// Be sure to null out the global now incase of trouble when executing command
var command = gCommandAfterPublishing;
gCommandAfterPublishing = null;
goDoCommand(command);
}
}
// Create a nsIURI object filled in with all required publishing info
@ -1533,18 +1603,14 @@ function CreateURIFromPublishData(publishData, doDocUri)
var URI;
try {
URI = Components.classes["@mozilla.org/network/standard-url;1"].createInstance(Components.interfaces.nsIURI);
if (!URI)
return null;
var spec = publishData.publishUrl;
if (doDocUri)
spec += FormatDirForPublishing(publishData.docDir) + publishData.filename;
else
spec += FormatDirForPublishing(publishData.otherDir);
URI.spec = spec;
var ioService = GetIOService();
URI = ioService.newURI(spec, window.editorShell.GetDocumentCharacterSet(), null);
if (publishData.username)
URI.username = publishData.username;
@ -1566,20 +1632,25 @@ function GetDocUrlFromPublishData(publishData)
var url;
var docScheme = GetScheme(GetDocumentUrl());
if (docScheme == "ftp" || !publishData.browseUrl)
// Always use the "HTTP" address if available
// XXX Should we do some more validation here for bad urls???
// Let's at least check for a scheme!
if (!GetScheme(publishData.browseUrl))
url = publishData.publishUrl;
else
url = publishData.browseUrl;
url += FormatDirForPublishing(publishData.docDir) + publishData.filename;
if (GetScheme(url) == "ftp")
url = InsertUsernameIntoUrl(url, publishData.username);
return url;
}
// Depending on editing local vs. remote files:
// 1. Switch the "Save" and "Publish" buttons on toolbars,
// 2. Hide "Save" menuitem if editing remote
// 3. Shift accel+S keybinding to Save or Publish commands
// * Switch the "Save" and "Publish" buttons on toolbars,
// * Shift accel+S keybinding to Save or Publish commands
// Note: A new, unsaved file is treated as a local file
// (XXX Have a pref to treat as remote for user's who mostly edit remote?)
function SetSaveAndPublishUI(urlstring)
@ -1616,8 +1687,9 @@ function SetSaveAndPublishUI(urlstring)
SetElementHidden(publishButton, false);
}
SetElementHidden(menuItem1, true);
SetElementHidden(menuItem2, false);
// Use this to hide "Save" menuitem if editing remote, Hide "Publish" if editing local
// SetElementHidden(menuItem1, true);
// SetElementHidden(menuItem2, false);
var key = document.getElementById("savekb");
if (key && command)
@ -1628,6 +1700,9 @@ function SetSaveAndPublishUI(urlstring)
menuItem1.removeAttribute("key");
menuItem2.setAttribute("key","savekb");
}
// Be sure enabled state of toolbar button is correct
goUpdateCommand(command);
}
function SetDocumentEditable(isDocEditable)
@ -1639,11 +1714,11 @@ function SetDocumentEditable(isDocEditable)
window.editorShell.editor.flags = isDocEditable ?
flags &= ~nsIPlaintextEditor.eEditorReadonlyMask :
flags | nsIPlaintextEditor.eEditorReadonlyMask;
// update all commands
window.updateCommands("create");
} catch(e) {}
// update all commands
window._content.focus();
window.updateCommands("create");
}
}
@ -1731,7 +1806,7 @@ function CloseWindow()
{
// Check to make sure document is saved. "true" means allow "Don't Save" button,
// so user can choose to close without saving
if (CheckAndSaveDocument(GetString("BeforeClosing"), true))
if (CheckAndSaveDocument("cmd_close", true))
{
if (window.InsertCharWindow)
SwitchInsertCharToAnotherEditorOrClose();
@ -1773,7 +1848,7 @@ var nsPreviewCommand =
{
// Don't continue if user canceled during prompt for saving
// DocumentHasBeenSaved will test if we have a URL and suppress "Don't Save" button if not
if (!CheckAndSaveDocument(GetString("BeforePreview"), DocumentHasBeenSaved()))
if (!CheckAndSaveDocument("cmd_preview", DocumentHasBeenSaved()))
return;
// Check if we saved again just in case?
@ -1807,7 +1882,7 @@ var nsPreviewCommand =
// Be sure browser contains real source content, not cached
// setTimeout is needed because the "browser" created by openDialog
// needs time to finish else BrowserReloadSkipCache doesn't exist
setTimeout( function(browser) { browser.BrowserReloadSkipCache(); }, 0, browser );
setTimeout( function(browser) { browser.BrowserReloadSkipCache(); }, 10, browser );
browser.focus();
}
} catch (ex) {}
@ -1828,7 +1903,7 @@ var nsSendPageCommand =
{
// Don't continue if user canceled during prompt for saving
// DocumentHasBeenSaved will test if we have a URL and suppress "Don't Save" button if not
if (!CheckAndSaveDocument(GetString("SendPageReason"), DocumentHasBeenSaved()))
if (!CheckAndSaveDocument("cmd_editSendPage", DocumentHasBeenSaved()))
return;
// Check if we saved again just in case?
@ -1920,7 +1995,7 @@ var nsFindCommand =
{
try {
window.openDialog("chrome://editor/content/EdReplace.xul", "_blank",
"chrome,dependent", "");
"chrome,dependent,titlebar", "");
}
catch(ex) {
dump("*** Exception: couldn't open Replace Dialog\n");
@ -2008,8 +2083,7 @@ var nsValidateCommand =
// then just validate the current url.
if (editorShell.documentModified || gHTMLSourceChanged)
{
if (!CheckAndSaveDocument(GetString("BeforeValidate"),
false))
if (!CheckAndSaveDocument("cmd_validate", false))
return;
// Check if we saved again just in case?

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

@ -441,11 +441,13 @@ function DocumentHasBeenSaved()
return true;
}
function CheckAndSaveDocument(reasonToSave, allowDontSave)
function CheckAndSaveDocument(command, allowDontSave)
{
// if we don't have an editorShell or an editorDocument, bail
if (!window.editorShell && !window.editorShell.editorDocument)
return true;
try {
// if we don't have an editorShell or an editorDocument, bail
if (!window.editorShell && !window.editorShell.editorDocument)
return true;
} catch (e) { return true; }
var document = editorShell.editorDocument;
if (!editorShell.documentModified && !gHTMLSourceChanged)
@ -455,11 +457,33 @@ function CheckAndSaveDocument(reasonToSave, allowDontSave)
// and therefore need to be visible (to prevent user confusion)
window.focus();
var scheme = GetScheme(GetDocumentUrl());
var doPublish = (scheme && scheme != "file");
var strID;
switch (command)
{
case "cmd_close":
strID = "BeforeClosing";
break;
case "cmd_preview":
strID = "BeforePreview";
break;
case "cmd_editSendPage":
strID = "SendPageReason";
break;
case "cmd_validate":
strID = "BeforeValidate";
break;
}
var reasonToSave = strID ? GetString(strID) : "";
var title = window.editorShell.editorDocument.title;
if (!title)
title = GetString("untitled");
var dialogTitle = GetString("SaveDocument");
var dialogTitle = GetString(doPublish ? "PublishPage" : "SaveDocument");
var dialogMsg = GetString("SaveFilePrompt");
dialogMsg = (dialogMsg.replace(/%title%/,title)).replace(/%reason%/,reasonToSave);
@ -467,16 +491,29 @@ function CheckAndSaveDocument(reasonToSave, allowDontSave)
promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
var result = {value:0};
var promptFlags =
(promptService.BUTTON_TITLE_SAVE * promptService.BUTTON_POS_0) +
(promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1) +
(allowDontSave
? (promptService.BUTTON_TITLE_DONT_SAVE * promptService.BUTTON_POS_2)
: 0);
promptService.confirmEx(
window, dialogTitle, dialogMsg, promptFlags,
null, null, null, null, {value:0}, result
);
var promptFlags = promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1;
var button1Title = null;
var button3Title = null;
if (doPublish)
{
promptFlags += promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0;
button1Title = GetString("Publish");
button3Title = GetString("DontPublish");
}
else
{
promptFlags += promptService.BUTTON_TITLE_SAVE * promptService.BUTTON_POS_0;
}
// If allowing "Don't..." button, add that
if (allowDontSave)
promptFlags += doPublish ?
(promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_2)
: (promptService.BUTTON_TITLE_DONT_SAVE * promptService.BUTTON_POS_2);
promptService.confirmEx(window, dialogTitle, dialogMsg, promptFlags,
button1Title, null, button3Title, null, {value:0}, result);
if (result.value == 0)
{
@ -484,6 +521,17 @@ function CheckAndSaveDocument(reasonToSave, allowDontSave)
if (gHTMLSourceChanged)
FinishHTMLSource();
if (doPublish)
{
// We save the command the user wanted to do in a global
// and return as if user canceled because publishing is asynchronous
// This command will be fired when publishing finishes
gCommandAfterPublishing = command;
goDoCommand("cmd_publish");
return false;
}
// Save to local disk
var success = SaveDocument(false, false, editorShell.contentsMIMEType);
return success;
}
@ -520,7 +568,7 @@ function EditorCanClose()
// Returns FALSE only if user cancels save action
// "true" means allow "Don't Save" button
var canClose = CheckAndSaveDocument(GetString("BeforeClosing"), true);
var canClose = CheckAndSaveDocument("cmd_close", true);
// This is our only hook into closing via the "X" in the caption
// or "Quit" (or other paths?)
@ -1583,7 +1631,7 @@ function BuildRecentMenu(savePrefs)
// Current page is the "0" item in the list we save in prefs,
// but we don't include it in the menu.
var curTitle = window.editorShell.editorDocument.title;
var curUrl = GetDocumentUrl();
var curUrl = StripPassword(GetDocumentUrl());
var historyCount = 10;
try { historyCount = gPrefs.getIntPref("editor.history.url_maximum"); } catch(e) {}
var titleArray = new Array(historyCount);
@ -1607,13 +1655,17 @@ function BuildRecentMenu(savePrefs)
// Continue if URL pref is missing because
// a URL not found during loading may have been removed
if (!url)
// Also skip "data:" URL
if (!url || GetScheme(url) == "data")
continue;
var scheme = GetScheme(url);
// Skip over current and "data:" URL
if (url != curUrl && scheme && scheme != "data")
// Never show password in menu!
url = StripPassword(url);
// Skip over current URL
if (url != curUrl)
{
// Build the menu
AppendRecentMenuitem(popup, title, url, menuIndex);
menuIndex++;
@ -1690,6 +1742,14 @@ function AppendRecentMenuitem(menupopup, title, url, menuIndex)
}
}
function EditorInitFileMenu()
{
// Disable "Save" menuitem when editing remote url. User should use "Save As"
var scheme = GetScheme(GetDocumentUrl());
if (scheme && scheme != "file")
SetElementEnabledById("saveMenuitem", false);
}
function EditorInitFormatMenu()
{
try {

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

@ -290,7 +290,7 @@
so we use our own id, label, and accesskey but connect to the same global key and broadcaster node
-->
<menu id="fileMenu" label="&fileMenu.label;" accesskey="&filemenu.accesskey;">
<menupopup id="menu_FilePopup">
<menupopup id="menu_FilePopup" onpopupshowing="EditorInitFileMenu();">
<menu id="menu_New">
<menupopup id="menu_NewPopup">
<!-- From globalOverlay.xul -->

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

@ -48,8 +48,11 @@ const gMac = "Mac";
/************* Message dialogs ***************/
function AlertWithTitle(title, message)
function AlertWithTitle(title, message, parentWindow)
{
if (!parentWindow)
parentWindow = window;
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
@ -59,7 +62,7 @@ function AlertWithTitle(title, message)
title = GetString("Alert");
// "window" is the calling dialog window
promptService.alert(window, title, message);
promptService.alert(parentWindow, title, message);
}
}

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

@ -157,7 +157,9 @@ function CreatePublishDataFromUrl(docUrl)
browseUrl : pubUrl,
docDir : "",
otherDir : "",
publishOtherFiles : true,
dirList : [""],
saveDirs : false,
notInSiteData : true
}
@ -183,22 +185,11 @@ function GetPublishDataFromSiteName(siteName, docUrlOrFilename)
if (siteNameList[i] == siteName)
{
var publishData = GetPublishData_internal(publishBranch, siteName);
var filename = docUrlOrFilename;
var scheme = GetScheme(docUrlOrFilename);
if (scheme)
{
// Separate into the base url and filename
var lastSlash = docUrlOrFilename.lastIndexOf("\/");
var url = docUrlOrFilename.slice(0, lastSlash);
filename = docUrlOrFilename.slice(lastSlash+1);
if (GetScheme(docUrlOrFilename))
FillInMatchingPublishData(publishData, docUrlOrFilename);
else
publishData.filename = docUrlOrFilename;
// Get length of the publish url that matches this docUrl
var len = GetMatchingPublishUrlLength(publishData, url);
if (len)
// The remainder is a subdirectory within the site
publishData.docDir = FormatDirForPublishing(url.slice(len));
}
publishData.filename = filename;
return publishData;
}
}
@ -233,8 +224,10 @@ function GetPublishData_internal(publishBranch, siteName)
return null;
var savePassword = false;
var publishOtherFiles = true;
try {
savePassword = publishBranch.getBoolPref(prefPrefix+"save_password");
publishOtherFiles = publishBranch.getBoolPref(prefPrefix+"publish_other_files");
} catch (e) {}
var publishData = {
@ -245,11 +238,27 @@ function GetPublishData_internal(publishBranch, siteName)
publishUrl : publishUrl,
browseUrl : GetPublishStringPref(publishBranch, prefPrefix+"browse_url"),
docDir : FormatDirForPublishing(GetPublishStringPref(publishBranch, prefPrefix+"doc_dir")),
otherDir : FormatDirForPublishing(GetPublishStringPref(publishBranch, prefPrefix+"other_dir"))
otherDir : FormatDirForPublishing(GetPublishStringPref(publishBranch, prefPrefix+"other_dir")),
publishOtherFiles : publishOtherFiles,
saveDirs : false
}
// Get password from PasswordManager
publishData.password = GetSavedPassword(publishData);
// If password was found, user must have checked "Save password"
// checkbox in prompt outside of publishing, so override the pref we stored
if (publishData.password)
{
if (!savePassword)
{
try {
publishPrefsBranch.setBoolPref(prefPrefix+"save_password", true);
} catch (e) {}
}
publishData.savePassword = true;
}
// Build history list of directories
// Always supply the root dir
publishData.dirList = [""];
@ -352,14 +361,22 @@ function SavePublishDataToPrefs(publishData)
{
var siteName = GetPublishStringPref(publishBranch, "site_name."+i);
if (siteName == publishData.siteName)
{
// Delete prefs for an existing site
try {
publishBranch.deleteBranch("site_data." + siteName + ".");
} catch (e) {}
break;
}
}
var ret = SavePublishData_Internal(publishBranch, publishData, i);
if (ret)
{
SavePrefFile();
// Clear signal to save these data
if (publishData.notInSiteData)
if ("notInSiteData" in publishData && publishData.notInSiteData)
publishData.notInSiteData = false;
}
return ret;
@ -376,23 +393,38 @@ function SavePublishData_Internal(publishPrefsBranch, publishData, siteIndex)
FixupUsernamePasswordInPublishData(publishData);
var prefPrefix = "site_data." + publishData.siteName + "."
SetPublishStringPref(publishPrefsBranch, prefPrefix+"url", publishData.publishUrl);
SetPublishStringPref(publishPrefsBranch, prefPrefix+"browse_url", publishData.browseUrl);
SetPublishStringPref(publishPrefsBranch, prefPrefix+"username", publishData.username);
try {
publishPrefsBranch.setBoolPref(prefPrefix+"save_password", publishData.savePassword);
publishPrefsBranch.setBoolPref(prefPrefix+"publish_other_files", publishData.publishOtherFiles);
} catch (e) {}
// Save password using PasswordManager
// (If publishData.savePassword = false, this clears existing password)
SavePassword(publishData);
SetPublishStringPref(publishPrefsBranch, prefPrefix+"doc_dir", publishData.docDir);
if (publishData.otherDir)
SetPublishStringPref(publishPrefsBranch, prefPrefix+"other_dir", publishData.otherDir);
SetPublishStringPref(publishPrefsBranch, prefPrefix+"doc_dir",
FormatDirForPublishing(publishData.docDir));
// Save array of directories in each site
if (publishData.publishOtherFiles && publishData.otherDir)
SetPublishStringPref(publishPrefsBranch, prefPrefix+"other_dir",
FormatDirForPublishing(publishData.otherDir));
if ("saveDirs" in publishData && publishData.saveDirs)
{
if (publishData.docDir)
AppendNewDirToList(publishData, publishData.docDir);
if (publishData.publishOtherFiles && publishData.otherDir
&& publishData.otherDir != publishData.docDir)
AppendNewDirToList(publishData, publishData.otherDir);
}
// Save array of subdirectories with site
if (publishData.dirList.length)
{
publishData.dirList.sort();
@ -409,6 +441,89 @@ function SavePublishData_Internal(publishPrefsBranch, publishData, siteIndex)
}
}
}
return true;
}
function AppendNewDirToList(publishData, newDir)
{
newDir = FormatDirForPublishing(newDir);
if (!publishData || !newDir)
return;
if (!publishData.dirList)
{
publishData.dirList = [newDir];
return;
}
// Check if already in the list
for (var i = 0; i < publishData.dirList.length; i++)
{
// Don't add if already in the list
if (newDir == publishData.dirList[i])
return;
}
// Add to end of list
publishData.dirList[publishData.dirList.length] = newDir;
}
function RemovePublishSubdirectoryFromPrefs(publishData, removeDir)
{
removeDir = FormatDirForPublishing(removeDir);
if (!publishData || !publishData.siteName || !removeDir)
return false;
var publishBranch = GetPublishPrefsBranch();
if (!publishBranch)
return false;
var prefPrefix = "site_data." + publishData.siteName + ".";
// Remove dir from the default dir prefs
if (publishData.docDir == removeDir)
{
publishData.docDir = "";
SetPublishStringPref(publishBranch, prefPrefix+"doc_dir", "");
}
if (publishData.otherDir == removeDir)
{
publishData.otherDir = "";
SetPublishStringPref(publishBranch, prefPrefix+"other_dir", "");
}
prefPrefix += "dir.";
// Delete entire subdir list
try {
publishBranch.deleteBranch(prefPrefix);
} catch (e) {}
// Rebuild prefs, skipping over site to remove
if (publishData.dirList.length)
{
var dirIndex = 0;
var docDirInList = false;
var otherDirInList = false;
for (var i = 0; i < publishData.dirList.length; i++)
{
var dir = publishData.dirList[i];
if (dir == removeDir)
{
// Remove item from the dirList array
publishData.dirList.splice(i, 1);
--i;
}
else if (dir && dir != "/") // skip empty or root dir
{
// Save to prefs
SetPublishStringPref(publishBranch, prefPrefix + dirIndex, dir);
dirIndex++;
}
}
}
SavePrefFile();
return true;
}
@ -533,55 +648,74 @@ function FindSiteIndexAndDocDir(publishSiteData, docUrl, dirObj)
if (!publishSiteData || !docUrl || GetScheme(docUrl) == "file")
return -1;
// Remove filename from docUrl
// (Check for terminal "/" so docUrl param can be a directory path)
if (docUrl.charAt(docUrl.length-1) != "/")
{
var lastSlash = docUrl.lastIndexOf("/");
docUrl = docUrl.slice(0, lastSlash+1);
}
var siteIndex = -1;
var siteUrlLen = 0;
var urlLen = docUrl.length;
for (var i = 0; i < publishSiteData.length; i++)
{
// Site publish or browse url needs to be contained in document URL,
// but that may also have a directory after the site base URL
// So we must examine all records to find the site URL that best
// matches the document URL (XXX is this right?)
var len = GetMatchingPublishUrlLength(publishSiteData[i], docUrl);
// matches the document URL: the longest-matching substring (XXX is this right?)
var lenObj = {value:0};
var tempData = publishSiteData[i];
// Check if this site matches docUrl (returns length of match if found)
var len = FillInMatchingPublishData(tempData, docUrl);
if (len > siteUrlLen)
{
siteIndex = i;
siteUrlLen = len;
if (dirObj)
dirObj.value = tempData.docDir;
// Continue to find the site with longest-matching publishUrl
}
}
// Get directory name from the end of url
if (dirObj && siteIndex >= 0 && urlLen > siteUrlLen)
dirObj.value = FormatDirForPublishing(docUrl.slice(siteUrlLen));
return siteIndex;
}
// Look for a matching publish url within the document url
// (We need to look at both "publishUrl" and "browseUrl" in case we are editing
// an http: document but using ftp: to publish.)
// Return the length of that matching portion
// Used to find the optimum publishing site within all site data
// and to extract remaining directory from the end of a document url
function GetMatchingPublishUrlLength(publishData, docUrl)
// If match is found:
// Fill in the filename and subirectory based on the docUrl and
// return the length of the docUrl with username+password stripped out
function FillInMatchingPublishData(publishData, docUrl)
{
if (publishData && docUrl)
if (!publishData || !docUrl)
return 0;
// Separate docUrl into the base url and filename
var lastSlash = docUrl.lastIndexOf("\/");
var baseUrl = docUrl.slice(0, lastSlash+1);
var filename = docUrl.slice(lastSlash+1);
// Strip username+password from docUrl because these
// are stored separately in publishData, never embedded in the publishUrl
// If both docUrl and publishData contain usernames,
// we must match that as well as the url
var username = {value:""};
baseUrl = StripUsernamePassword(baseUrl, username);
username = username.value;
var matchedLength = 0;
var pubUrlFound = baseUrl.indexOf(publishData.publishUrl) == 0;
var browseUrlFound = baseUrl.indexOf(publishData.browseUrl) == 0;
if ((pubUrlFound || browseUrlFound)
&& (!username || !publishData.username || username == publishData.username))
{
var pubUrlFound = docUrl.indexOf(publishData.publishUrl) == 0;
var browseUrlFound = docUrl.indexOf(publishData.browseUrl) == 0;
if (pubUrlFound || browseUrlFound)
return pubUrlFound ? publishData.publishUrl.length : publishData.browseUrl.length;
// We found a match
matchedLength = pubUrlFound ? publishData.publishUrl.length
: publishData.browseUrl.length;
publishData.filename = filename;
// Subdirectory within the site is whats left in baseUrl after the matched portion
publishData.docDir = FormatDirForPublishing(baseUrl.slice(matchedLength));
}
return 0;
return matchedLength;
}
// Prefs that don't exist will through an exception,
@ -707,7 +841,7 @@ function GetPasswordManagerInternal()
function GetSavedPassword(publishData)
{
if (!publishData || !publishData.savePassword)
if (!publishData)
return "";
var passwordManagerInternal = GetPasswordManagerInternal();
if (!passwordManagerInternal)
@ -716,12 +850,13 @@ function GetSavedPassword(publishData)
var host = {value:""};
var user = {value:""};
var password = {value:""};
var url = GetUrlForPasswordManager(publishData);
try {
passwordManagerInternal.findPasswordEntry
(publishData.publishUrl, publishData.username, "", host, user, password);
(url, publishData.username, "", host, user, password);
return password.value;
} catch (e) {
}
} catch (e) {}
return "";
}
@ -734,20 +869,44 @@ function SavePassword(publishData)
var passwordManager = GetPasswordManager();
if (passwordManager)
{
var url = GetUrlForPasswordManager(publishData);
// Remove existing entry
// (Note: there is no method to update a password for an existing entry)
try {
passwordManager.removeUser(publishData.publishUrl, publishData.username);
passwordManager.removeUser(url, publishData.username);
} catch (e) {}
// If SavePassword is true, add new password
if (publishData.savePassword)
{
try {
passwordManager.addUser(publishData.publishUrl, publishData.username, publishData.password);
passwordManager.addUser(url, publishData.username, publishData.password);
} catch (e) {}
}
return true;
}
return false;
}
function GetUrlForPasswordManager(publishData)
{
if (!publishData || !publishData.publishUrl)
return false;
var url;
// For FTP, we must embed the username into the url for a site address
// XXX Maybe we should we do this for HTTP as well???
if (publishData.username && GetScheme(publishData.publishUrl) == "ftp")
url = InsertUsernameIntoUrl(publishData.publishUrl, publishData.username);
else
url = publishData.publishUrl;
// Strip off terminal "/"
var len = url.length;
if (len && url.charAt(len-1) == "\/")
url = url.slice(0, len-1);
return url;
}