зеркало из https://github.com/mozilla/pjs.git
fix 2920 support for deleting and detaching attachments, sr=mscott
This commit is contained in:
Родитель
b7a4cee1fd
Коммит
eb0d7b1270
|
@ -1074,6 +1074,10 @@ function dofunc(aFunctionName, aFunctionArg)
|
|||
openAttachment(aFunctionArg);
|
||||
else if (aFunctionName == "printAttachment")
|
||||
printAttachment(aFunctionArg);
|
||||
else if (aFunctionName == "deleteAttachment")
|
||||
detachAttachment(aFunctionArg, false);
|
||||
else if (aFunctionName == "detachAttachment")
|
||||
detachAttachment(aFunctionArg, true);
|
||||
}
|
||||
|
||||
function saveAttachment(aAttachment)
|
||||
|
@ -1102,6 +1106,14 @@ function printAttachment(aAttachment)
|
|||
*/
|
||||
}
|
||||
|
||||
function detachAttachment(aAttachment, aSaveFirst)
|
||||
{
|
||||
messenger.detachAttachment(aAttachment.contentType,
|
||||
aAttachment.url,
|
||||
encodeURIComponent(aAttachment.displayName),
|
||||
aAttachment.messageUri, aSaveFirst);
|
||||
}
|
||||
|
||||
function onShowAttachmentContextMenu()
|
||||
{
|
||||
// if no attachments are selected, disable the Open and Save...
|
||||
|
@ -1133,7 +1145,7 @@ function attachmentListClick(event)
|
|||
var target = event.target;
|
||||
if (target.localName == "descriptionitem")
|
||||
{
|
||||
dofunc("openAttachment", target.attachment);
|
||||
dofunc("openAttachment", target.attachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1222,7 +1234,10 @@ function setApplicationIconForAttachment(attachment, listitem, largeView)
|
|||
{
|
||||
var iconSize = largeView ? kLargeIcon : kSmallIcon;
|
||||
// generate a moz-icon url for the attachment so we'll show a nice icon next to it.
|
||||
listitem.setAttribute('image', "moz-icon:" + "//" + attachment.displayName + "?size=" + iconSize + "&contentType=" + attachment.contentType);
|
||||
if ( attachment.contentType == 'text/x-moz-deleted' )
|
||||
listitem.setAttribute('image', 'chrome://messenger/skin/icons/message-mail-attach-del.gif');
|
||||
else
|
||||
listitem.setAttribute('image', "moz-icon:" + "//" + attachment.displayName + "?size=" + iconSize + "&contentType=" + attachment.contentType);
|
||||
}
|
||||
|
||||
// Public method called to generate a tooltip over an attachment
|
||||
|
@ -1313,6 +1328,14 @@ function addAttachmentToPopup(popup, attachment, attachmentIndex)
|
|||
gOpenLabel = gMessengerBundle.getString("openLabel");
|
||||
if (!gOpenLabelAccesskey)
|
||||
gOpenLabelAccesskey = gMessengerBundle.getString("openLabelAccesskey");
|
||||
if (!gDetachLabel)
|
||||
gDetachLabel = gMessengerBundle.getString("detachLabel");
|
||||
if (!gDetachLabelAccesskey)
|
||||
gDetachLabelAccesskey = gMessengerBundle.getString("detachLabelAccesskey");
|
||||
if (!gDeleteLabel)
|
||||
gDeleteLabel = gMessengerBundle.getString("deleteLabel");
|
||||
if (!gDeleteLabelAccesskey)
|
||||
gDeleteLabelAccesskey = gMessengerBundle.getString("deleteLabelAccesskey");
|
||||
|
||||
menuitementry.setAttribute('label', gOpenLabel);
|
||||
menuitementry.setAttribute('accesskey', gOpenLabelAccesskey);
|
||||
|
@ -1326,12 +1349,32 @@ function addAttachmentToPopup(popup, attachment, attachmentIndex)
|
|||
menuitementry.setAttribute('oncommand', 'saveAttachment(this.attachment)');
|
||||
menuitementry.setAttribute('label', gSaveLabel);
|
||||
menuitementry.setAttribute('accesskey', gSaveLabelAccesskey);
|
||||
if (attachment.contentType == 'text/x-moz-deleted')
|
||||
menuitementry.setAttribute('disabled', true);
|
||||
menuitementry = openpopup.appendChild(menuitementry);
|
||||
|
||||
menuitementry = document.createElement('menuitem');
|
||||
menuitementry.attachment = attachment;
|
||||
menuitementry.setAttribute('oncommand', 'this.attachment.detachAttachment()');
|
||||
menuitementry.setAttribute('label', gDetachLabel);
|
||||
menuitementry.setAttribute('accesskey', gDetachLabelAccesskey);
|
||||
if (attachment.contentType == 'text/x-moz-deleted')
|
||||
menuitementry.setAttribute('disabled', true);
|
||||
menuitementry = openpopup.appendChild(menuitementry);
|
||||
|
||||
menuitementry = document.createElement('menuitem');
|
||||
menuitementry.attachment = attachment;
|
||||
menuitementry.setAttribute('oncommand', 'this.attachment.deleteAttachment()');
|
||||
menuitementry.setAttribute('label', gDeleteLabel);
|
||||
menuitementry.setAttribute('accesskey', gDeleteLabelAccesskey);
|
||||
if (attachment.contentType == 'text/x-moz-deleted')
|
||||
menuitementry.setAttribute('disabled', true);
|
||||
menuitementry = openpopup.appendChild(menuitementry);
|
||||
} // if we created a menu item for this attachment...
|
||||
} // if we have a popup
|
||||
}
|
||||
|
||||
function SaveAllAttachments()
|
||||
function HandleAllAttachments(action)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -1342,24 +1385,43 @@ function SaveAllAttachments()
|
|||
var attachmentMessageUriArray = new Array();
|
||||
|
||||
// populate these arrays..
|
||||
var actionIndex = 0;
|
||||
for (index in currentAttachments)
|
||||
{
|
||||
// exclude all attachments already deleted
|
||||
var attachment = currentAttachments[index];
|
||||
attachmentContentTypeArray[index] = attachment.contentType;
|
||||
attachmentUrlArray[index] = attachment.url;
|
||||
attachmentDisplayNameArray[index] = encodeURIComponent(attachment.displayName);
|
||||
attachmentMessageUriArray[index] = attachment.uri;
|
||||
if ( attachment.contentType != 'text/x-moz-deleted' )
|
||||
{
|
||||
attachmentContentTypeArray[actionIndex] = attachment.contentType;
|
||||
attachmentUrlArray[actionIndex] = attachment.url;
|
||||
attachmentDisplayNameArray[actionIndex] = encodeURI(attachment.displayName);
|
||||
attachmentMessageUriArray[actionIndex] = attachment.uri;
|
||||
++actionIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// okay the list has been built...now call our save all attachments code...
|
||||
messenger.saveAllAttachments(attachmentContentTypeArray.length,
|
||||
attachmentContentTypeArray, attachmentUrlArray,
|
||||
attachmentDisplayNameArray, attachmentMessageUriArray);
|
||||
}
|
||||
catch (ex)
|
||||
{
|
||||
dump ("** failed to save all attachments **\n");
|
||||
}
|
||||
// okay the list has been built... now call our action code...
|
||||
if ( action == 'save' )
|
||||
messenger.saveAllAttachments(attachmentContentTypeArray.length,
|
||||
attachmentContentTypeArray, attachmentUrlArray,
|
||||
attachmentDisplayNameArray, attachmentMessageUriArray);
|
||||
else if ( action == 'detach' )
|
||||
messenger.detachAllAttachments(attachmentContentTypeArray.length,
|
||||
attachmentContentTypeArray, attachmentUrlArray,
|
||||
attachmentDisplayNameArray, attachmentMessageUriArray,
|
||||
true); // save
|
||||
else if ( action == 'delete' )
|
||||
messenger.detachAllAttachments(attachmentContentTypeArray.length,
|
||||
attachmentContentTypeArray, attachmentUrlArray,
|
||||
attachmentDisplayNameArray, attachmentMessageUriArray,
|
||||
false); // don't save
|
||||
else
|
||||
dump ("** unknown HandleAllAttachments action: " + action + "**\n");
|
||||
}
|
||||
catch (ex)
|
||||
{
|
||||
dump ("** failed to handle all attachments **\n");
|
||||
}
|
||||
}
|
||||
|
||||
function ClearAttachmentList()
|
||||
|
|
|
@ -62,12 +62,28 @@
|
|||
<menuitem id="context-saveAttachment" label="&saveAsAttachmentCmd.label;" accesskey="&saveAsAttachmentCmd.accesskey;"
|
||||
oncommand="handleAttachmentSelection('saveAttachment');"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="context-saveAllAttachments" oncommand="SaveAllAttachments();" label="&saveAllAttachmentsCmd.label;" accesskey="&saveAllAttachmentsCmd.accesskey;"/>
|
||||
<menuitem id="context-detachAttachment" label="&detachAttachmentCmd.label;"
|
||||
oncommand="handleAttachmentSelection('detachAttachment');"/>
|
||||
<menuitem id="context-deleteAttachment" label="&deleteAttachmentCmd.label;"
|
||||
oncommand="handleAttachmentSelection('deleteAttachment');"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="context-saveAllAttachments" oncommand="HandleAllAttachments('save');"
|
||||
label="&saveAllAttachmentsCmd.label;" accesskey="&saveAllAttachmentsCmd.accesskey;"/>
|
||||
<menuitem id="context-detachAllAttachments" oncommand="HandleAllAttachments('detach');"
|
||||
label="&detachAllAttachmentsCmd.label;"/>
|
||||
<menuitem id="context-deleteAllAttachments" oncommand="HandleAllAttachments('delete');"
|
||||
label="&deleteAllAttachmentsCmd.label;"/>
|
||||
</popup>
|
||||
|
||||
<popup id="attachmentMenuList">
|
||||
<menuseparator/>
|
||||
<menuitem label="&saveAllAttachmentsCmd.label;" accesskey="&saveAllAttachmentsCmd.accesskey;" oncommand="SaveAllAttachments();"/>
|
||||
<menuitem id="file-saveAllAttachments" label="&saveAllAttachmentsCmd.label;"
|
||||
accesskey="&saveAllAttachmentsCmd.accesskey;" oncommand="HandleAllAttachments('save');"/>
|
||||
<menuitem id="file-detachAllAttachments" label="&detachAllAttachmentsCmd.label;"
|
||||
accesskey="&detachAllAttachmentsCmd.accesskey;" oncommand="HandleAllAttachments('detach');" />
|
||||
<menuitem id="file-deleteAllAttachments" label="&deleteAllAttachmentsCmd.label;"
|
||||
accesskey="&deleteAllAttachmentsCmd.accesskey;" oncommand="HandleAllAttachments('delete');" />
|
||||
</popup>
|
||||
|
||||
<popup id="copyUrlPopup" popupanchor="bottomleft">
|
||||
|
@ -171,7 +187,8 @@
|
|||
<!-- the message pane consists of 3 'boxes'. Box #3 is the attachment box which can be toggled into a slim or an expanded view -->
|
||||
<hbox id="attachmentView" class="headerContainer" collapsed="true">
|
||||
<label id="attachmentLabel" class="subjectvalue" value="&attachmentsTree.label;"/>
|
||||
<description flex="1" id="attachmentList" selectable="true" seltype="multiple" onclick="attachmentListClick(event);" ondraggesture="nsDragAndDrop.startDrag(event,attachmentAreaDNDObserver);" ondragover="nsDragAndDrop.dragOver(event, attachmentAreaDNDObserver);" context="attachmentListContext">
|
||||
<description flex="1" id="attachmentList" selectable="true" seltype="multiple"
|
||||
onclick="attachmentListClick(event);" ondraggesture="nsDragAndDrop.startDrag(event,attachmentAreaDNDObserver);" ondragover="nsDragAndDrop.dragOver(event, attachmentAreaDNDObserver);" context="attachmentListContext">
|
||||
</description>
|
||||
</hbox>
|
||||
|
||||
|
|
|
@ -280,6 +280,15 @@ openLabel=Open
|
|||
openLabelAccesskey=O
|
||||
saveLabel=Save As...
|
||||
saveLabelAccesskey=A
|
||||
detachLabel=Detach...
|
||||
detachLabelAccesskey=D
|
||||
deleteLabel=Delete
|
||||
deleteLabelAccesskey=E
|
||||
deleteAttachments=The following attachments will be permanently deleted from this message:\n%S\nThis action cannot be undone. Do you wish to continue?
|
||||
detachAttachments=The following attachments have been successfully saved and will now be permanently deleted from this message:\n%S\nThis action cannot be undone. Do you wish to continue?
|
||||
deleteAttachmentFailure=Failed to delete the selected attachments.
|
||||
# LOCALIZATION NOTES(attachmentDeletePrefix): Do not translate until foreign language attachment names are fixed
|
||||
attachmentDeletePrefix=Deleted: %S
|
||||
|
||||
# This is the format for prepending accesskeys to the
|
||||
# each of the attachments in the file|attachments menu:
|
||||
|
|
|
@ -61,8 +61,14 @@
|
|||
<!ENTITY saveAsAttachmentCmd.accesskey "A">
|
||||
<!ENTITY printAttachmentCmd.label ".Print">
|
||||
<!ENTITY printAttachmentCmd.accesskey "P">
|
||||
<!ENTITY detachAttachmentCmd.label "Detach ...">
|
||||
<!ENTITY deleteAttachmentCmd.label "Delete">
|
||||
<!ENTITY saveAllAttachmentsCmd.label "Save All...">
|
||||
<!ENTITY saveAllAttachmentsCmd.accesskey "S">
|
||||
<!ENTITY detachAllAttachmentsCmd.label "Detach All...">
|
||||
<!ENTITY detachAllAttachmentsCmd.accesskey "D">
|
||||
<!ENTITY deleteAllAttachmentsCmd.label "Delete All...">
|
||||
<!ENTITY deleteAllAttachmentsCmd.accesskey "E">
|
||||
|
||||
<!ENTITY copyLinkCmd.label "Copy Link Location">
|
||||
<!ENTITY copyLinkCmd.accesskey "C">
|
||||
|
|
|
@ -303,7 +303,8 @@ public:
|
|||
const char **urlArray,
|
||||
const char **displayNameArray,
|
||||
const char **messageUriArray,
|
||||
const char *directoryName);
|
||||
const char *directoryName,
|
||||
PRBool detachingAttachments);
|
||||
virtual ~nsSaveAllAttachmentsState();
|
||||
|
||||
PRUint32 m_count;
|
||||
|
@ -313,6 +314,8 @@ public:
|
|||
char** m_urlArray;
|
||||
char** m_displayNameArray;
|
||||
char** m_messageUriArray;
|
||||
PRBool m_detachingAttachments;
|
||||
nsCStringArray m_savedFiles; // if detaching first, remember where we saved to.
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -655,14 +658,33 @@ nsMessenger::SaveAttachment(nsIFileSpec * fileSpec,
|
|||
// whacky ref counting here...what's the deal? when does saveListener get released? it's not clear.
|
||||
nsSaveMsgListener *saveListener = new nsSaveMsgListener(fileSpec, this);
|
||||
if (!saveListener)
|
||||
{
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_ADDREF(saveListener);
|
||||
|
||||
saveListener->m_contentType = contentType;
|
||||
if (saveState)
|
||||
saveListener->m_saveAllAttachmentsState = saveState;
|
||||
{
|
||||
saveListener->m_saveAllAttachmentsState = saveState;
|
||||
if (saveState->m_detachingAttachments)
|
||||
{
|
||||
|
||||
nsFileSpec realSpec;
|
||||
fileSpec->GetFileSpec(&realSpec);
|
||||
|
||||
// Create nsILocalFile from a nsFileSpec.
|
||||
nsCOMPtr<nsILocalFile> outputFile;
|
||||
nsresult rv = NS_FileSpecToIFile(&realSpec, getter_AddRefs(outputFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> outputURI;
|
||||
rv = NS_NewFileURI(getter_AddRefs(outputURI), outputFile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCAutoString fileUriSpec;
|
||||
outputURI->GetSpec(fileUriSpec);
|
||||
saveState->m_savedFiles.AppendCString(fileUriSpec);
|
||||
}
|
||||
}
|
||||
|
||||
urlString = url;
|
||||
urlString.ReplaceSubstring("/;section", "?section");
|
||||
|
@ -717,7 +739,7 @@ nsMessenger::SaveAttachment(nsIFileSpec * fileSpec,
|
|||
NS_IF_RELEASE(saveListener);
|
||||
Alert("saveAttachmentFailed");
|
||||
}
|
||||
return rv;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -834,6 +856,17 @@ nsMessenger::SaveAllAttachments(PRUint32 count,
|
|||
const char **urlArray,
|
||||
const char **displayNameArray,
|
||||
const char **messageUriArray)
|
||||
{
|
||||
return SaveAllAttachments(count, contentTypeArray, urlArray, displayNameArray, messageUriArray, PR_FALSE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMessenger::SaveAllAttachments(PRUint32 count,
|
||||
const char **contentTypeArray,
|
||||
const char **urlArray,
|
||||
const char **displayNameArray,
|
||||
const char **messageUriArray,
|
||||
PRBool detaching)
|
||||
{
|
||||
nsresult rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
nsCOMPtr<nsIFilePicker> filePicker =
|
||||
|
@ -877,7 +910,7 @@ nsMessenger::SaveAllAttachments(PRUint32 count,
|
|||
urlArray,
|
||||
displayNameArray,
|
||||
messageUriArray,
|
||||
(const char*) dirName);
|
||||
(const char*) dirName, detaching);
|
||||
{
|
||||
nsFileSpec aFileSpec((const char *) dirName);
|
||||
|
||||
|
@ -888,7 +921,8 @@ nsMessenger::SaveAllAttachments(PRUint32 count,
|
|||
|
||||
aFileSpec += unescapedName.get();
|
||||
rv = PromptIfFileExists(aFileSpec);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
fileSpec->SetFromFileSpec(aFileSpec);
|
||||
rv = SaveAttachment(fileSpec, urlArray[0], messageUriArray[0],
|
||||
contentTypeArray[0], (void *)saveState);
|
||||
|
@ -1738,9 +1772,7 @@ done:
|
|||
realSpec.Delete(PR_FALSE);
|
||||
}
|
||||
if (m_messenger)
|
||||
{
|
||||
m_messenger->Alert("saveMessageFailed");
|
||||
}
|
||||
}
|
||||
if (killSelf)
|
||||
Release(); // no more work needs to be done; kill ourself
|
||||
|
@ -1973,8 +2005,20 @@ nsSaveMsgListener::OnStopRequest(nsIRequest* request, nsISupports* aSupport,
|
|||
}
|
||||
else
|
||||
{
|
||||
delete m_saveAllAttachmentsState;
|
||||
m_saveAllAttachmentsState = nsnull;
|
||||
// check if we're saving attachments prior to detaching them.
|
||||
if (m_saveAllAttachmentsState->m_detachingAttachments)
|
||||
{
|
||||
nsSaveAllAttachmentsState *state = m_saveAllAttachmentsState;
|
||||
m_messenger->DetachAttachments(state->m_count,
|
||||
(const char **) state->m_contentTypeArray,
|
||||
(const char **) state->m_urlArray,
|
||||
(const char **) state->m_displayNameArray,
|
||||
(const char **) state->m_messageUriArray,
|
||||
&state->m_savedFiles);
|
||||
}
|
||||
|
||||
delete m_saveAllAttachmentsState;
|
||||
m_saveAllAttachmentsState = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2087,7 +2131,8 @@ nsSaveAllAttachmentsState::nsSaveAllAttachmentsState(PRUint32 count,
|
|||
const char **urlArray,
|
||||
const char **nameArray,
|
||||
const char **uriArray,
|
||||
const char *dirName)
|
||||
const char *dirName,
|
||||
PRBool detachingAttachments)
|
||||
{
|
||||
PRUint32 i;
|
||||
NS_ASSERTION(count && urlArray && nameArray && uriArray && dirName,
|
||||
|
@ -2107,6 +2152,7 @@ nsSaveAllAttachmentsState::nsSaveAllAttachmentsState(PRUint32 count,
|
|||
m_messageUriArray[i] = nsCRT::strdup(uriArray[i]);
|
||||
}
|
||||
m_directoryName = nsCRT::strdup(dirName);
|
||||
m_detachingAttachments = detachingAttachments;
|
||||
}
|
||||
|
||||
nsSaveAllAttachmentsState::~nsSaveAllAttachmentsState()
|
||||
|
@ -2442,6 +2488,8 @@ public:
|
|||
|
||||
// temp
|
||||
PRBool mWrittenExtra;
|
||||
PRBool mDetaching;
|
||||
nsCStringArray mDetachedFileUris;
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -2639,12 +2687,12 @@ nsDelAttachListener::~nsDelAttachListener()
|
|||
|
||||
nsresult
|
||||
nsDelAttachListener::StartProcessing(nsMessenger * aMessenger, nsIMsgWindow * aMsgWindow,
|
||||
nsAttachmentState * aAttach, PRBool aSaveFirst)
|
||||
nsAttachmentState * aAttach, PRBool detaching)
|
||||
{
|
||||
aMessenger->QueryInterface(NS_GET_IID(nsIMessenger), getter_AddRefs(mMessenger));
|
||||
mMsgWindow = aMsgWindow;
|
||||
mAttach = aAttach;
|
||||
mSaveFirst = aSaveFirst;
|
||||
mDetaching = detaching;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
|
@ -2694,15 +2742,24 @@ nsDelAttachListener::StartProcessing(nsMessenger * aMessenger, nsIMsgWindow * aM
|
|||
const char * partId;
|
||||
const char * nextField;
|
||||
nsCAutoString sHeader("attach&del=");
|
||||
nsCAutoString detachToHeader("&detachTo=");
|
||||
for (PRUint32 u = 0; u < mAttach->mCount; ++u)
|
||||
{
|
||||
if (u > 0)
|
||||
{
|
||||
sHeader.Append(",");
|
||||
if (detaching)
|
||||
detachToHeader.Append(",");
|
||||
}
|
||||
partId = GetAttachmentPartId(mAttach->mAttachmentArray[u].mUrl);
|
||||
nextField = PL_strchr(partId, '&');
|
||||
sHeader.Append(partId, nextField ? nextField - partId : -1);
|
||||
if (detaching)
|
||||
detachToHeader.Append(mDetachedFileUris.CStringAt(u)->get());
|
||||
}
|
||||
|
||||
if (detaching)
|
||||
sHeader.Append(detachToHeader);
|
||||
// stream this message to our listener converting it via the attachment mime
|
||||
// converter. The listener will just write the converted message straight to disk.
|
||||
nsCOMPtr<nsISupports> listenerSupports;
|
||||
|
@ -2753,8 +2810,25 @@ nsMessenger::DetachAllAttachments(PRUint32 aCount,
|
|||
NS_ENSURE_ARG_POINTER(aDisplayNameArray);
|
||||
NS_ENSURE_ARG_POINTER(aMessageUriArray);
|
||||
|
||||
if (aSaveFirst)
|
||||
return SaveAllAttachments(aCount, aContentTypeArray, aUrlArray, aDisplayNameArray, aMessageUriArray, PR_TRUE);
|
||||
else
|
||||
return DetachAttachments(aCount, aContentTypeArray, aUrlArray, aDisplayNameArray, aMessageUriArray, nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMessenger::DetachAttachments(PRUint32 aCount,
|
||||
const char ** aContentTypeArray,
|
||||
const char ** aUrlArray,
|
||||
const char ** aDisplayNameArray,
|
||||
const char ** aMessageUriArray,
|
||||
nsCStringArray *saveFileUris)
|
||||
{
|
||||
if (NS_FAILED(PromptIfDeleteAttachments(saveFileUris != nsnull, aCount, aDisplayNameArray)))
|
||||
return NS_OK;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
||||
// ensure that our arguments are valid
|
||||
// char * partId;
|
||||
for (PRUint32 u = 0; u < aCount; ++u)
|
||||
|
@ -2800,20 +2874,20 @@ nsMessenger::DetachAllAttachments(PRUint32 aCount,
|
|||
|
||||
// get the listener for running the url
|
||||
nsDelAttachListener * listener = new nsDelAttachListener;
|
||||
if (!listener) return NS_ERROR_OUT_OF_MEMORY;
|
||||
if (!listener)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
nsCOMPtr<nsISupports> listenerSupports; // auto-delete of the listener with error
|
||||
listener->QueryInterface(NS_GET_IID(nsISupports), getter_AddRefs(listenerSupports));
|
||||
|
||||
if (saveFileUris)
|
||||
listener->mDetachedFileUris = *saveFileUris;
|
||||
// create the attachments for use by the listener
|
||||
nsAttachmentState * attach = new nsAttachmentState;
|
||||
if (!attach) return NS_ERROR_OUT_OF_MEMORY;
|
||||
if (!attach)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
rv = attach->Init(aCount, aContentTypeArray, aUrlArray, aDisplayNameArray, aMessageUriArray);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
delete attach;
|
||||
return rv;
|
||||
}
|
||||
rv = attach->PrepareForAttachmentDelete();
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = attach->PrepareForAttachmentDelete();
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
delete attach;
|
||||
|
@ -2822,7 +2896,7 @@ nsMessenger::DetachAllAttachments(PRUint32 aCount,
|
|||
|
||||
// initialize our listener with the attachments and details. The listener takes ownership
|
||||
// of 'attach' immediately irrespective of the return value (error or not).
|
||||
return listener->StartProcessing(this, mMsgWindow, attach, aSaveFirst);
|
||||
return listener->StartProcessing(this, mMsgWindow, attach, saveFileUris != nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -66,6 +66,18 @@ public:
|
|||
const char* messageUri, const char* contentType,
|
||||
void *closure);
|
||||
nsresult PromptIfFileExists(nsFileSpec &fileSpec);
|
||||
nsresult DetachAttachments(PRUint32 aCount,
|
||||
const char ** aContentTypeArray,
|
||||
const char ** aUrlArray,
|
||||
const char ** aDisplayNameArray,
|
||||
const char ** aMessageUriArray,
|
||||
nsCStringArray *saveFileUris);
|
||||
nsresult SaveAllAttachments(PRUint32 count,
|
||||
const char **contentTypeArray,
|
||||
const char **urlArray,
|
||||
const char **displayNameArray,
|
||||
const char **messageUriArray,
|
||||
PRBool detaching);
|
||||
|
||||
protected:
|
||||
nsresult DoDelete(nsIRDFCompositeDataSource* db, nsISupportsArray *srcArray,
|
||||
|
|
|
@ -1791,6 +1791,7 @@ nsMsgLocalMailFolder::CopyMessages(nsIMsgFolder* srcFolder, nsISupportsArray*
|
|||
return rv;
|
||||
}
|
||||
// for srcFolder that are on different server than the dstFolder.
|
||||
// "this" is the parent of the new dest folder.
|
||||
nsresult
|
||||
nsMsgLocalMailFolder::CopyFolderAcrossServer(nsIMsgFolder* srcFolder, nsIMsgWindow *msgWindow,
|
||||
nsIMsgCopyServiceListener *listener )
|
||||
|
|
|
@ -421,7 +421,9 @@ public:
|
|||
dexlateion did in fact occur.
|
||||
*/
|
||||
nsCStringArray partsToStrip; /* if we're stripping parts, what parts to strip */
|
||||
nsCStringArray detachToFiles; /* if we're detaching parts, where each part was detached to */
|
||||
PRBool strippingPart;
|
||||
nsCString detachedFilePath; /* if we've detached this part, filepath of detached part */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -203,12 +203,15 @@ MimeMultipart_parse_line (char *line, PRInt32 length, MimeObject *obj)
|
|||
newPart.Append('.');
|
||||
newPart.AppendInt(container->nchildren + 1);
|
||||
obj->options->state->strippingPart = PR_FALSE;
|
||||
// obj->options->state->detachedFilePath.Truncate(0);
|
||||
// check if this is a sub-part of a part we're stripping.
|
||||
for (PRInt32 partIndex = 0; partIndex < obj->options->state->partsToStrip.Count(); partIndex++)
|
||||
{
|
||||
if (newPart.Find(*obj->options->state->partsToStrip.CStringAt(partIndex)) == 0)
|
||||
{
|
||||
obj->options->state->strippingPart = PR_TRUE;
|
||||
if (partIndex < obj->options->state->detachToFiles.Count())
|
||||
obj->options->state->detachedFilePath = *obj->options->state->detachToFiles.CStringAt(partIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -245,17 +248,45 @@ MimeMultipart_parse_line (char *line, PRInt32 length, MimeObject *obj)
|
|||
{
|
||||
if (obj->options->state->strippingPart)
|
||||
{
|
||||
nsCAutoString header("Content-Type: text/x-moz-deleted; name=\"Deleted: ");
|
||||
PRBool detachingPart = obj->options->state->detachedFilePath.Length() > 0;
|
||||
|
||||
nsCAutoString fileName;
|
||||
fileName.Adopt(MimeHeaders_get_name(mult->hdrs, obj->options));
|
||||
header.Append(fileName);
|
||||
status = MimeWriteAString(obj, header);
|
||||
if (status < 0)
|
||||
return status;
|
||||
status = MimeWriteAString(obj, NS_LITERAL_CSTRING("\""MSG_LINEBREAK"Content-Transfer-Encoding: 8bit"MSG_LINEBREAK));
|
||||
MimeWriteAString(obj, NS_LITERAL_CSTRING("Content-Disposition: inline; filename=\"Deleted:"));
|
||||
MimeWriteAString(obj, fileName);
|
||||
MimeWriteAString(obj, NS_LITERAL_CSTRING("\""MSG_LINEBREAK"X-Mozilla-Altered: AttachmentDeleted; date=\""));
|
||||
if (detachingPart)
|
||||
{
|
||||
char *contentType = MimeHeaders_get(mult->hdrs, "Content-Type", PR_FALSE, PR_FALSE);
|
||||
MimeWriteAString(obj, NS_LITERAL_CSTRING("Content-Type: "));
|
||||
MimeWriteAString(obj, nsDependentCString(contentType));
|
||||
PR_Free(contentType);
|
||||
char *contentEncoding = MimeHeaders_get(mult->hdrs, "Content-Transfer-Encoding", PR_FALSE, PR_FALSE);
|
||||
if (contentEncoding)
|
||||
{
|
||||
MimeWriteAString(obj, NS_LITERAL_CSTRING(MSG_LINEBREAK));
|
||||
MimeWriteAString(obj, NS_LITERAL_CSTRING("Content-Transfer-Encoding: "));
|
||||
MimeWriteAString(obj, nsDependentCString(contentEncoding));
|
||||
PR_Free(contentEncoding);
|
||||
}
|
||||
MimeWriteAString(obj, NS_LITERAL_CSTRING(MSG_LINEBREAK));
|
||||
MimeWriteAString(obj, NS_LITERAL_CSTRING("Content-Disposition: attachment; filename=\""));
|
||||
MimeWriteAString(obj, fileName);
|
||||
MimeWriteAString(obj, NS_LITERAL_CSTRING("\""MSG_LINEBREAK));
|
||||
MimeWriteAString(obj, NS_LITERAL_CSTRING("X-Mozilla-External-Attachment-URL: "));
|
||||
MimeWriteAString(obj, obj->options->state->detachedFilePath);
|
||||
MimeWriteAString(obj, NS_LITERAL_CSTRING(MSG_LINEBREAK));
|
||||
MimeWriteAString(obj, NS_LITERAL_CSTRING("X-Mozilla-Altered: AttachmentDetached; date=\""));
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCAutoString header("Content-Type: text/x-moz-deleted; name=\"Deleted: ");
|
||||
header.Append(fileName);
|
||||
status = MimeWriteAString(obj, header);
|
||||
if (status < 0)
|
||||
return status;
|
||||
status = MimeWriteAString(obj, NS_LITERAL_CSTRING("\""MSG_LINEBREAK"Content-Transfer-Encoding: 8bit"MSG_LINEBREAK));
|
||||
MimeWriteAString(obj, NS_LITERAL_CSTRING("Content-Disposition: inline; filename=\"Deleted:"));
|
||||
MimeWriteAString(obj, fileName);
|
||||
MimeWriteAString(obj, NS_LITERAL_CSTRING("\""MSG_LINEBREAK"X-Mozilla-Altered: AttachmentDeleted; date=\""));
|
||||
}
|
||||
nsCString result;
|
||||
char timeBuffer[128];
|
||||
PRExplodedTime now;
|
||||
|
|
|
@ -195,20 +195,29 @@ MimeObject_parse_begin (MimeObject *obj)
|
|||
/* If we haven't set up the state object yet, then this should be
|
||||
the outermost object... */
|
||||
if (obj->options && !obj->options->state)
|
||||
{
|
||||
NS_ASSERTION(!obj->headers, "headers should be null"); /* should be the outermost object. */
|
||||
{
|
||||
NS_ASSERTION(!obj->headers, "headers should be null"); /* should be the outermost object. */
|
||||
|
||||
obj->options->state = new MimeParseStateObject;
|
||||
if (!obj->options->state) return MIME_OUT_OF_MEMORY;
|
||||
obj->options->state->root = obj;
|
||||
obj->options->state->separator_suppressed_p = PR_TRUE; /* no first sep */
|
||||
const char *delParts = PL_strcasestr(obj->options->url, "&del=");
|
||||
if (delParts)
|
||||
{
|
||||
delParts += 5; // advance past "&del="
|
||||
obj->options->state->partsToStrip.ParseString(delParts, ",");
|
||||
}
|
||||
}
|
||||
obj->options->state = new MimeParseStateObject;
|
||||
if (!obj->options->state) return MIME_OUT_OF_MEMORY;
|
||||
obj->options->state->root = obj;
|
||||
obj->options->state->separator_suppressed_p = PR_TRUE; /* no first sep */
|
||||
const char *delParts = PL_strcasestr(obj->options->url, "&del=");
|
||||
const char *detachLocations = PL_strcasestr(obj->options->url, "&detachTo=");
|
||||
if (delParts)
|
||||
{
|
||||
const char *delEnd = PL_strcasestr(delParts + 1, "&");
|
||||
if (!delEnd)
|
||||
delEnd = delParts + strlen(delParts) - 1;
|
||||
nsCAutoString partsToDel(Substring(delParts + 5, delEnd));
|
||||
obj->options->state->partsToStrip.ParseString(partsToDel.get(), ",");
|
||||
}
|
||||
if (detachLocations)
|
||||
{
|
||||
detachLocations += 10; // advance past "&detachTo="
|
||||
obj->options->state->detachToFiles.ParseString(detachLocations, ",");
|
||||
}
|
||||
}
|
||||
|
||||
/* Decide whether this object should be output or not... */
|
||||
if (!obj->options || !obj->options->output_fn
|
||||
|
|
Загрузка…
Ссылка в новой задаче