fix 2920 support for deleting and detaching attachments, sr=mscott

This commit is contained in:
bienvenu%nventure.com 2005-03-02 15:25:16 +00:00
Родитель b7a4cee1fd
Коммит eb0d7b1270
10 изменённых файлов: 286 добавлений и 63 удалений

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

@ -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