1590 lines
44 KiB
C++
1590 lines
44 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
#include "nsMsgCompose.h"
|
|
#include "nsMsgCompPrefs.h"
|
|
#include "nsIScriptGlobalObject.h"
|
|
#include "nsIDOMNode.h"
|
|
#include "nsIDOMNodeList.h"
|
|
#include "nsIDOMHTMLInputElement.h"
|
|
#include "nsIDOMDocument.h"
|
|
#include "nsMsgI18N.h"
|
|
#include "nsMsgSend.h"
|
|
#include "nsIMessenger.h" //temporary!
|
|
#include "nsIMessage.h" //temporary!
|
|
#include "nsMsgQuote.h"
|
|
#include "nsIPref.h"
|
|
#include "nsIEditor.h" // for output flags
|
|
#include "nsXPIDLString.h"
|
|
#include "nsIParser.h"
|
|
#include "nsParserCIID.h"
|
|
#include "nsHTMLToTXTSinkStream.h"
|
|
#include "CNavDTD.h"
|
|
#include "nsMsgCompUtils.h"
|
|
#include "nsMsgComposeStringBundle.h"
|
|
|
|
// XXX temporary so we can use the current identity hack -alecf
|
|
#include "nsIMsgMailSession.h"
|
|
#include "nsMsgBaseCID.h"
|
|
static NS_DEFINE_CID(kMsgMailSessionCID, NS_MSGMAILSESSION_CID);
|
|
|
|
#if defined(XP_UNIX) || defined(XP_BEOS)
|
|
#define TEMP_PATH_DIR "/tmp/"
|
|
#elif defined(XP_PC)
|
|
#define TEMP_PATH_DIR "c:\\temp\\"
|
|
#elif defined(XP_MAC)
|
|
#define TEMP_PATH_DIR ""
|
|
#else
|
|
#error TEMP_PATH_DIR_NOT_DEFINED
|
|
#endif
|
|
|
|
#define TEMP_MESSAGE_IN "tempMessage.eml"
|
|
#define TEMP_MESSAGE_OUT "tempMessage.html"
|
|
#define TEMP_MESSAGE_OUT_TEXT "tempMessage.txt"
|
|
|
|
// Defines....
|
|
static NS_DEFINE_CID(kMsgQuoteCID, NS_MSGQUOTE_CID);
|
|
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
|
|
|
|
// RICHIE
|
|
// This is a temp hack and will go away soon!
|
|
//
|
|
PRBool
|
|
nsMsgCompose::UsingOldQuotingHack(const char *compString)
|
|
{
|
|
nsresult rv;
|
|
|
|
NS_WITH_SERVICE(nsIPref, prefs, kPrefCID, &rv);
|
|
if (NS_SUCCEEDED(rv) && prefs)
|
|
rv = prefs->GetBoolPref("mail.old_quoting", &mUseOldQuotingHack);
|
|
|
|
if (compString)
|
|
{
|
|
if (PL_strncasecmp(compString, "mailbox_message:", 16) != 0)
|
|
{
|
|
mUseOldQuotingHack = PR_TRUE;
|
|
}
|
|
}
|
|
|
|
return mUseOldQuotingHack;
|
|
}
|
|
|
|
nsMsgCompose::nsMsgCompose()
|
|
{
|
|
mTempComposeFileSpec = nsnull;
|
|
mQuotingToFollow = PR_FALSE;
|
|
mSigFileSpec = nsnull;
|
|
mUseOldQuotingHack = PR_FALSE; // RICHIE - hack for old quoting
|
|
mWhatHolder = 1; // RICHIE - hack for old quoting
|
|
mQuoteURI = "";
|
|
mDocumentListener = nsnull;
|
|
mMsgSend = nsnull;
|
|
m_sendListener = nsnull;
|
|
m_window = nsnull;
|
|
m_webShell = nsnull;
|
|
m_webShellWin = nsnull;
|
|
m_editor = nsnull;
|
|
mQuoteStreamListener=nsnull;
|
|
m_compFields = new nsMsgCompFields;
|
|
NS_IF_ADDREF(m_compFields);
|
|
|
|
// Get the default charset from pref, use this as a mail charset.
|
|
char * default_mail_charset = nsMsgI18NGetDefaultMailCharset();
|
|
if (default_mail_charset)
|
|
{
|
|
m_compFields->SetCharacterSet(default_mail_charset);
|
|
PR_Free(default_mail_charset);
|
|
}
|
|
|
|
m_composeHTML = PR_FALSE;
|
|
// temporary - m_composeHTML from the "current" identity
|
|
// eventually we should know this when we open the compose window
|
|
// -alecf
|
|
nsresult rv;
|
|
NS_WITH_SERVICE(nsIMsgMailSession, mailSession, kMsgMailSessionCID, &rv);
|
|
if (NS_FAILED(rv)) return;
|
|
|
|
nsCOMPtr<nsIMsgIdentity> identity;
|
|
rv = mailSession->GetCurrentIdentity(getter_AddRefs(identity));
|
|
if (NS_FAILED(rv)) return;
|
|
|
|
rv = identity->GetComposeHtml(&m_composeHTML);
|
|
|
|
NS_INIT_REFCNT();
|
|
}
|
|
|
|
|
|
nsMsgCompose::~nsMsgCompose()
|
|
{
|
|
if (m_editor)
|
|
m_editor->UnregisterDocumentStateListener(mDocumentListener);
|
|
NS_IF_RELEASE(mDocumentListener);
|
|
NS_IF_RELEASE(m_sendListener);
|
|
NS_IF_RELEASE(m_compFields);
|
|
NS_IF_RELEASE(mQuoteStreamListener);
|
|
}
|
|
|
|
|
|
/* the following macro actually implement addref, release and query interface for our component. */
|
|
NS_IMPL_ISUPPORTS(nsMsgCompose, nsCOMTypeInfo<nsMsgCompose>::GetIID());
|
|
|
|
|
|
nsresult
|
|
nsMsgCompose::SetQuotingToFollow(PRBool aVal)
|
|
{
|
|
mQuotingToFollow = aVal;
|
|
return NS_OK;
|
|
}
|
|
|
|
PRBool
|
|
nsMsgCompose::QuotingToFollow(void)
|
|
{
|
|
return mQuotingToFollow;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgCompose::LoadAsQuote(nsString aTextToLoad)
|
|
{
|
|
// Now Load the body...
|
|
if (m_editor)
|
|
{
|
|
if (aTextToLoad.Length())
|
|
{
|
|
m_editor->InsertAsQuotation(aTextToLoad.GetUnicode());
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsMsgCompose::Initialize(nsIDOMWindow *aWindow, const PRUnichar *originalMsgURI,
|
|
MSG_ComposeType type, MSG_ComposeFormat format, nsIMsgCompFields *compFields, nsISupports *object)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if (aWindow)
|
|
{
|
|
m_window = aWindow;
|
|
nsCOMPtr<nsIScriptGlobalObject> globalObj(do_QueryInterface(aWindow));
|
|
if (!globalObj)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIWebShell> webShell;
|
|
globalObj->GetWebShell(getter_AddRefs(webShell));
|
|
if (!webShell)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
m_webShell = webShell;
|
|
|
|
nsCOMPtr<nsIWebShellContainer> webShellContainer;
|
|
m_webShell->GetContainer(*getter_AddRefs(webShellContainer));
|
|
if (!webShellContainer)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
nsCOMPtr<nsIWebShellWindow> webShellWin = do_QueryInterface(webShellContainer, &rv);
|
|
m_webShellWin = webShellWin;
|
|
}
|
|
|
|
switch (format)
|
|
{
|
|
case MSGCOMP_FORMAT_HTML : m_composeHTML = PR_TRUE; break;
|
|
case MSGCOMP_FORMAT_PlainText : m_composeHTML = PR_FALSE; break;
|
|
default : /* m_composeHTML initialized in ctor */ break;
|
|
|
|
}
|
|
|
|
CreateMessage(originalMsgURI, type, format, compFields, object); //object is temporary
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult nsMsgCompose::LoadFields()
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
// Not sure if this call is really necessary anymore...
|
|
return rv;
|
|
}
|
|
|
|
nsresult nsMsgCompose::SetDocumentCharset(const PRUnichar *charset)
|
|
{
|
|
// Set charset, this will be used for the MIME charset labeling.
|
|
m_compFields->SetCharacterSet(nsAutoCString(charset));
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsMsgCompose::_SendMsg(MSG_DeliverMode deliverMode,
|
|
nsIMsgIdentity *identity,
|
|
const PRUnichar *callback)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if (m_compFields && identity)
|
|
{
|
|
// Pref values are supposed to be stored as UTF-8, so no conversion
|
|
nsXPIDLCString email;
|
|
nsXPIDLCString replyTo;
|
|
nsXPIDLCString organization;
|
|
|
|
identity->GetEmail(getter_Copies(email));
|
|
identity->GetReplyTo(getter_Copies(replyTo));
|
|
identity->GetOrganization(getter_Copies(organization));
|
|
|
|
m_compFields->SetFrom(NS_CONST_CAST(char*, (const char *)email));
|
|
//Set the reply-to only if the user have not specified one in the message
|
|
const char * reply = m_compFields->GetReplyTo();
|
|
if (reply == nsnull || *reply == 0)
|
|
m_compFields->SetReplyTo(NS_CONST_CAST(char*, (const char *)replyTo));
|
|
m_compFields->SetOrganization(NS_CONST_CAST(char*, (const char *)organization));
|
|
|
|
#if defined(DEBUG_ducarroz) || defined(DEBUG_seth_)
|
|
printf("----------------------------\n");
|
|
printf("-- Sending Mail Message --\n");
|
|
printf("----------------------------\n");
|
|
printf("from: %s\n", m_compFields->GetFrom());
|
|
printf("To: %s Cc: %s Bcc: %s\n", m_compFields->GetTo(), m_compFields->GetCc(), m_compFields->GetBcc());
|
|
printf("Newsgroups: %s\n", m_compFields->GetNewsgroups());
|
|
printf("Subject: %s \nMsg: %s\n", m_compFields->GetSubject(), m_compFields->GetBody());
|
|
printf("Attachments: %s\n",m_compFields->GetAttachments());
|
|
printf("----------------------------\n");
|
|
#endif //DEBUG
|
|
|
|
nsIMsgSend *tMsgComp = new nsMsgComposeAndSend();
|
|
if (!tMsgComp)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
mMsgSend = do_QueryInterface( tMsgComp );
|
|
if (mMsgSend)
|
|
{
|
|
const char *bodyString = m_compFields->GetBody();
|
|
PRInt32 bodyLength = PL_strlen(bodyString);
|
|
|
|
|
|
// Create the listener for the send operation...
|
|
m_sendListener = new nsMsgComposeSendListener();
|
|
if (!m_sendListener)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
NS_ADDREF(m_sendListener);
|
|
// set this object for use on completion...
|
|
m_sendListener->SetComposeObj(this);
|
|
m_sendListener->SetDeliverMode(deliverMode);
|
|
nsIMsgSendListener **tArray = m_sendListener->CreateListenerArray();
|
|
if (!tArray)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Error creating listener array.\n");
|
|
#endif
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// If we are composing HTML, then this should be sent as
|
|
// multipart/related which means we pass the editor into the
|
|
// backend...if not, just pass nsnull
|
|
//
|
|
nsIEditorShell *tEditor = nsnull;
|
|
|
|
if (m_composeHTML)
|
|
{
|
|
tEditor = m_editor;
|
|
}
|
|
else
|
|
tEditor = nsnull;
|
|
|
|
rv = mMsgSend->CreateAndSendMessage(
|
|
tEditor,
|
|
identity,
|
|
m_compFields,
|
|
PR_FALSE, // PRBool digest_p,
|
|
PR_FALSE, // PRBool dont_deliver_p,
|
|
(nsMsgDeliverMode)deliverMode, // nsMsgDeliverMode mode,
|
|
nsnull, // nsIMessage *msgToReplace,
|
|
m_composeHTML?TEXT_HTML:TEXT_PLAIN, // const char *attachment1_type,
|
|
bodyString, // const char *attachment1_body,
|
|
bodyLength, // PRUint32 attachment1_body_length,
|
|
nsnull, // const struct nsMsgAttachmentData *attachments,
|
|
nsnull, // const struct nsMsgAttachedFile *preloaded_attachments,
|
|
nsnull, // nsMsgSendPart *relatedPart,
|
|
tArray); // listener array
|
|
|
|
delete tArray;
|
|
}
|
|
else
|
|
rv = NS_ERROR_FAILURE;
|
|
}
|
|
else
|
|
rv = NS_ERROR_NOT_INITIALIZED;
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
/*TODO, don't close the window but just hide it, we will close it later when we receive a call back from the BE
|
|
if (nsnull != mScriptContext) {
|
|
const char* url = "";
|
|
PRBool isUndefined = PR_FALSE;
|
|
nsString rVal;
|
|
|
|
mScriptContext->EvaluateString(mScript, url, 0, rVal, &isUndefined);
|
|
CloseWindow();
|
|
}
|
|
else // If we don't have a JS callback, then close the window by default!
|
|
*/
|
|
// rhp:
|
|
// We shouldn't close the window if we are just saving a draft or a template
|
|
// so do this check
|
|
if ( (deliverMode != nsMsgSaveAsDraft) && (deliverMode != nsMsgSaveAsTemplate) )
|
|
ShowWindow(PR_FALSE);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult nsMsgCompose::SendMsg(MSG_DeliverMode deliverMode,
|
|
nsIMsgIdentity *identity,
|
|
const PRUnichar *callback)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if (m_editor && m_compFields)
|
|
{
|
|
nsAutoString msgBody;
|
|
PRUnichar *bodyText = NULL;
|
|
nsString format;
|
|
PRUint32 flags = 0;
|
|
if (m_composeHTML)
|
|
format = "text/html";
|
|
else
|
|
{
|
|
flags = nsIEditor::EditorOutputFormatted;
|
|
format = "text/plain";
|
|
}
|
|
m_editor->GetContentsAs(format.GetUnicode(), flags, &bodyText);
|
|
|
|
msgBody = bodyText;
|
|
delete [] bodyText;
|
|
|
|
// Convert body to mail charset not to utf-8 (because we don't manipulate body text)
|
|
char *outCString;
|
|
nsString aCharset = m_compFields->GetCharacterSet();
|
|
if (NS_SUCCEEDED(ConvertFromUnicode(aCharset, msgBody, &outCString)))
|
|
{
|
|
m_compFields->SetBody(outCString);
|
|
PR_Free(outCString);
|
|
}
|
|
else
|
|
m_compFields->SetBody(nsAutoCString(msgBody));
|
|
}
|
|
|
|
rv = _SendMsg(deliverMode, identity, callback);
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
nsresult
|
|
nsMsgCompose::SendMsgEx(MSG_DeliverMode deliverMode,
|
|
nsIMsgIdentity *identity,
|
|
const PRUnichar *addrTo, const PRUnichar *addrCc,
|
|
const PRUnichar *addrBcc, const PRUnichar *newsgroup,
|
|
const PRUnichar *subject, const PRUnichar *body,
|
|
const PRUnichar *callback)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if (m_compFields && identity)
|
|
{
|
|
nsString aString;
|
|
nsString aCharset(msgCompHeaderInternalCharset());
|
|
char *outCString;
|
|
|
|
// Convert fields to UTF-8
|
|
if (NS_SUCCEEDED(ConvertFromUnicode(aCharset, addrTo, &outCString)))
|
|
{
|
|
m_compFields->SetTo(outCString);
|
|
PR_Free(outCString);
|
|
}
|
|
else
|
|
m_compFields->SetTo(nsAutoCString(addrTo));
|
|
|
|
if (NS_SUCCEEDED(ConvertFromUnicode(aCharset, addrCc, &outCString)))
|
|
{
|
|
m_compFields->SetCc(outCString);
|
|
PR_Free(outCString);
|
|
}
|
|
else
|
|
m_compFields->SetCc(nsAutoCString(addrCc));
|
|
|
|
if (NS_SUCCEEDED(ConvertFromUnicode(aCharset, addrBcc, &outCString)))
|
|
{
|
|
m_compFields->SetBcc(outCString);
|
|
PR_Free(outCString);
|
|
}
|
|
else
|
|
m_compFields->SetBcc(nsAutoCString(addrBcc));
|
|
|
|
if (NS_SUCCEEDED(ConvertFromUnicode(aCharset, newsgroup, &outCString)))
|
|
{
|
|
m_compFields->SetNewsgroups(outCString);
|
|
PR_Free(outCString);
|
|
}
|
|
else
|
|
m_compFields->SetNewsgroups(nsAutoCString(newsgroup));
|
|
|
|
if (NS_SUCCEEDED(ConvertFromUnicode(aCharset, subject, &outCString)))
|
|
{
|
|
m_compFields->SetSubject(outCString);
|
|
PR_Free(outCString);
|
|
}
|
|
else
|
|
m_compFields->SetSubject(nsAutoCString(subject));
|
|
|
|
// Convert body to mail charset not to utf-8 (because we don't manipulate body text)
|
|
aCharset.SetString(m_compFields->GetCharacterSet());
|
|
if (NS_SUCCEEDED(ConvertFromUnicode(aCharset, body, &outCString)))
|
|
{
|
|
m_compFields->SetBody(outCString);
|
|
PR_Free(outCString);
|
|
}
|
|
else
|
|
m_compFields->SetBody(nsAutoCString(body));
|
|
|
|
rv = _SendMsg(deliverMode, identity, callback);
|
|
}
|
|
else
|
|
rv = NS_ERROR_NOT_INITIALIZED;
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult nsMsgCompose::CloseWindow()
|
|
{
|
|
if (m_webShellWin)
|
|
{
|
|
m_editor = nsnull; /* m_editor will be destroyed during the Close Window. Set it to null to */
|
|
/* be sure we wont use it anymore. */
|
|
m_webShellWin->Close();
|
|
m_webShellWin = nsnull;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsMsgCompose::ShowWindow(PRBool show)
|
|
{
|
|
if (m_webShellWin)
|
|
{
|
|
m_webShellWin->Show(show);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsMsgCompose::GetEditor(nsIEditorShell * *aEditor)
|
|
{
|
|
*aEditor = m_editor;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsMsgCompose::SetEditor(nsIEditorShell * aEditor)
|
|
{
|
|
// First, store the editor shell.
|
|
m_editor = aEditor;
|
|
|
|
//
|
|
// Now this routine will create a listener for state changes
|
|
// in the editor and set us as the compose object of interest.
|
|
//
|
|
mDocumentListener = new nsMsgDocumentStateListener();
|
|
if (!mDocumentListener)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
mDocumentListener->SetComposeObj(this);
|
|
NS_ADDREF(mDocumentListener);
|
|
|
|
// Make sure we setup to listen for editor state changes...
|
|
m_editor->RegisterDocumentStateListener(mDocumentListener);
|
|
|
|
//
|
|
// Have to check to see if there is a body stored in the
|
|
// comp fields...
|
|
//
|
|
PRBool bodyInCompFields = PR_FALSE;
|
|
if (m_compFields)
|
|
{
|
|
PRUnichar *bod;
|
|
|
|
m_compFields->GetBody(&bod);
|
|
if ((bod) && (*bod))
|
|
bodyInCompFields = PR_TRUE;
|
|
}
|
|
|
|
// Now, do the appropriate startup operation...signature only
|
|
// or quoted message and signature...
|
|
if ( QuotingToFollow() )
|
|
return BuildQuotedMessageAndSignature();
|
|
else if (bodyInCompFields)
|
|
return BuildBodyMessage();
|
|
else
|
|
return ProcessSignature(nsnull);
|
|
}
|
|
|
|
nsresult nsMsgCompose::GetDomWindow(nsIDOMWindow * *aDomWindow)
|
|
{
|
|
*aDomWindow = m_window;
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
nsresult nsMsgCompose::GetCompFields(nsIMsgCompFields * *aCompFields)
|
|
{
|
|
*aCompFields = (nsIMsgCompFields*)m_compFields;
|
|
NS_IF_ADDREF(*aCompFields);
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
nsresult nsMsgCompose::GetComposeHTML(PRBool *aComposeHTML)
|
|
{
|
|
*aComposeHTML = m_composeHTML;
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
nsresult nsMsgCompose::GetWrapLength(PRInt32 *aWrapLength)
|
|
{
|
|
nsMsgCompPrefs prefs;
|
|
|
|
*aWrapLength = prefs.GetWrapColumn();
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsMsgCompose::CreateMessage(const PRUnichar * originalMsgURI, MSG_ComposeType type, MSG_ComposeFormat format,
|
|
nsIMsgCompFields * compFields, nsISupports * object)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if (compFields)
|
|
{
|
|
if (m_compFields)
|
|
m_compFields->Copy(compFields);
|
|
return rv;
|
|
}
|
|
|
|
/* At this point, we have a list of URI of original message to reply to or forward but as the BE isn't ready yet,
|
|
we still need to use the old patch... gather the information from the object and the temp file use to display the selected message*/
|
|
if (object)
|
|
{
|
|
nsCOMPtr<nsIMessage> message;
|
|
rv = object->QueryInterface(nsIMessage::GetIID(), getter_AddRefs(message));
|
|
if ((NS_SUCCEEDED(rv)) && message)
|
|
{
|
|
nsString aString = "";
|
|
nsString bString = "";
|
|
nsString aCharset = "";
|
|
nsString decodedString;
|
|
nsString encodedCharset; // we don't use this
|
|
char *aCString;
|
|
|
|
message->GetCharSet(&aCharset);
|
|
message->GetSubject(&aString);
|
|
switch (type)
|
|
{
|
|
default: break;
|
|
case MSGCOMP_TYPE_Reply :
|
|
case MSGCOMP_TYPE_ReplyAll:
|
|
{
|
|
mQuotingToFollow = PR_TRUE;
|
|
// get an original charset, used for a label, UTF-8 is used for the internal processing
|
|
if (!aCharset.Equals(""))
|
|
m_compFields->SetCharacterSet(nsAutoCString(aCharset));
|
|
|
|
bString += "Re: ";
|
|
bString += aString;
|
|
if (NS_SUCCEEDED(rv = nsMsgI18NDecodeMimePartIIStr(bString, encodedCharset, decodedString)))
|
|
m_compFields->SetSubject(decodedString.GetUnicode());
|
|
else
|
|
m_compFields->SetSubject(bString.GetUnicode());
|
|
|
|
message->GetAuthor(&aString);
|
|
m_compFields->SetTo(nsAutoCString(aString));
|
|
if (NS_SUCCEEDED(rv = nsMsgI18NDecodeMimePartIIStr(aString, encodedCharset, decodedString)))
|
|
if (NS_SUCCEEDED(rv = ConvertFromUnicode(msgCompHeaderInternalCharset(), decodedString, &aCString)))
|
|
{
|
|
m_compFields->SetTo(aCString);
|
|
PR_Free(aCString);
|
|
}
|
|
|
|
if (type == MSGCOMP_TYPE_ReplyAll)
|
|
{
|
|
nsString cString, dString;
|
|
message->GetRecipients(&cString);
|
|
CleanUpRecipients(cString);
|
|
message->GetCCList(&dString);
|
|
CleanUpRecipients(dString);
|
|
if (cString.Length() > 0 && dString.Length() > 0)
|
|
cString = cString + ", ";
|
|
cString = cString + dString;
|
|
m_compFields->SetCc(nsAutoCString(cString));
|
|
if (NS_SUCCEEDED(rv = nsMsgI18NDecodeMimePartIIStr(cString, encodedCharset, decodedString)))
|
|
if (NS_SUCCEEDED(rv = ConvertFromUnicode(msgCompHeaderInternalCharset(), decodedString, &aCString)))
|
|
{
|
|
m_compFields->SetCc(aCString);
|
|
PR_Free(aCString);
|
|
}
|
|
}
|
|
|
|
// Setup quoting callbacks for later...
|
|
mWhatHolder = 1;
|
|
mQuoteURI = originalMsgURI;
|
|
|
|
break;
|
|
}
|
|
case MSGCOMP_TYPE_ForwardAsAttachment:
|
|
case MSGCOMP_TYPE_ForwardInline:
|
|
{
|
|
mQuotingToFollow = PR_TRUE;
|
|
|
|
if (!aCharset.Equals(""))
|
|
m_compFields->SetCharacterSet(nsAutoCString(aCharset));
|
|
|
|
bString += "[Fwd: ";
|
|
bString += aString;
|
|
bString += "]";
|
|
|
|
if (NS_SUCCEEDED(rv = nsMsgI18NDecodeMimePartIIStr(bString, encodedCharset, decodedString)))
|
|
m_compFields->SetSubject(decodedString.GetUnicode());
|
|
else
|
|
m_compFields->SetSubject(bString.GetUnicode());
|
|
|
|
// Setup quoting callbacks for later...
|
|
mQuoteURI = originalMsgURI;
|
|
if (type == MSGCOMP_TYPE_ForwardAsAttachment)
|
|
{
|
|
mWhatHolder = 0;
|
|
}
|
|
else
|
|
{
|
|
mWhatHolder = 2;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// THIS IS THE CLASS THAT IS THE STREAM CONSUMER OF THE HTML OUPUT
|
|
// FROM LIBMIME. THIS IS FOR QUOTING
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
QuotingOutputStreamListener::~QuotingOutputStreamListener()
|
|
{
|
|
if (mComposeObj)
|
|
NS_RELEASE(mComposeObj);
|
|
}
|
|
|
|
QuotingOutputStreamListener::QuotingOutputStreamListener(void)
|
|
{
|
|
mComposeObj = nsnull;
|
|
mMsgBody = "<br><BLOCKQUOTE TYPE=CITE><html><br>--- Original Message ---<br><br>";
|
|
mMsgBody = "";
|
|
NS_INIT_REFCNT();
|
|
}
|
|
|
|
static nsresult
|
|
ConvertBufToPlainText(nsString &aConBuf, const char *charSet)
|
|
{
|
|
nsresult rv;
|
|
nsString convertedText;
|
|
nsIParser *parser;
|
|
|
|
static NS_DEFINE_IID(kCParserIID, NS_IPARSER_IID);
|
|
static NS_DEFINE_IID(kCParserCID, NS_PARSER_IID);
|
|
|
|
rv = nsComponentManager::CreateInstance(kCParserCID, nsnull,
|
|
kCParserIID, (void **)&parser);
|
|
if (NS_SUCCEEDED(rv) && parser)
|
|
{
|
|
nsHTMLToTXTSinkStream *sink = nsnull;
|
|
|
|
rv = NS_New_HTMLToTXT_SinkStream((nsIHTMLContentSink **)&sink, &convertedText, PR_TRUE);
|
|
if (sink && NS_SUCCEEDED(rv))
|
|
{
|
|
sink->DoFragment(PR_TRUE);
|
|
parser->SetContentSink(sink);
|
|
|
|
// Set the charset...
|
|
//
|
|
if (charSet)
|
|
{
|
|
nsAutoString cSet(charSet);
|
|
parser->SetDocumentCharset(cSet, kCharsetFromMetaTag);
|
|
}
|
|
|
|
nsIDTD* dtd = nsnull;
|
|
rv = NS_NewNavHTMLDTD(&dtd);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
parser->RegisterDTD(dtd);
|
|
rv = parser->Parse(aConBuf, 0, "text/html", PR_FALSE, PR_TRUE);
|
|
}
|
|
NS_IF_RELEASE(dtd);
|
|
NS_IF_RELEASE(sink);
|
|
}
|
|
|
|
NS_RELEASE(parser);
|
|
//
|
|
// Now assign the results if we worked!
|
|
//
|
|
if (NS_SUCCEEDED(rv))
|
|
aConBuf = convertedText;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
QuotingOutputStreamListener::ConvertToPlainText()
|
|
{
|
|
return ConvertBufToPlainText(mMsgBody, "UTF-8");
|
|
}
|
|
|
|
NS_IMETHODIMP QuotingOutputStreamListener::OnStartRequest(nsIChannel * /* aChannel */, nsISupports * /* ctxt */)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP QuotingOutputStreamListener::OnStopRequest(nsIChannel * /* aChannel */, nsISupports * /* ctxt */, nsresult status, const PRUnichar * /* errorMsg */)
|
|
{
|
|
if (mComposeObj)
|
|
{
|
|
mMsgBody += "</html></BLOCKQUOTE>";
|
|
|
|
// Now we have an HTML representation of the quoted message.
|
|
// If we are in plain text mode, we need to convert this to plain
|
|
// text before we try to insert it into the editor. If we don't, we
|
|
// just get lots of HTML text in the message...not good.
|
|
//
|
|
PRBool composeHTML = PR_TRUE;
|
|
mComposeObj->GetComposeHTML(&composeHTML);
|
|
if (!composeHTML)
|
|
ConvertToPlainText();
|
|
|
|
|
|
//
|
|
// Ok, now we have finished quoting so we should load this into the editor
|
|
// window.
|
|
//
|
|
|
|
PRBool compHTML = PR_FALSE;
|
|
mComposeObj->GetComposeHTML(&compHTML);
|
|
mComposeObj->mTempComposeFileSpec = nsMsgCreateTempFileSpec(compHTML ? "nscomp.html" : "nscomp.txt");
|
|
if (!mComposeObj->mTempComposeFileSpec)
|
|
return NS_MSG_ERROR_WRITING_FILE;
|
|
|
|
nsOutputFileStream tempFile(*(mComposeObj->mTempComposeFileSpec));
|
|
if (!tempFile.is_open())
|
|
return NS_MSG_ERROR_WRITING_FILE;
|
|
tempFile.write(nsAutoCString(mMsgBody), mMsgBody.Length());
|
|
mComposeObj->ProcessSignature(&tempFile);
|
|
tempFile.close();
|
|
|
|
// Now load the URL...
|
|
nsString urlStr = mComposeObj->mTempComposeFileSpec->GetNativePathCString();
|
|
nsIEditorShell *editor;
|
|
|
|
mComposeObj->GetEditor(&editor);
|
|
if (editor)
|
|
editor->LoadUrl(urlStr.GetUnicode());
|
|
else
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP QuotingOutputStreamListener::OnDataAvailable(nsIChannel * /* aChannel */,
|
|
nsISupports *ctxt, nsIInputStream *inStr,
|
|
PRUint32 sourceOffset, PRUint32 count)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
if (!inStr)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
char *newBuf = (char *)PR_Malloc(count + 1);
|
|
if (!newBuf)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
PRUint32 numWritten = 0;
|
|
rv = inStr->Read(newBuf, count, &numWritten);
|
|
newBuf[count] = '\0';
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
mMsgBody += newBuf;
|
|
}
|
|
|
|
PR_FREEIF(newBuf);
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
QuotingOutputStreamListener::SetComposeObj(nsMsgCompose *obj)
|
|
{
|
|
mComposeObj = obj;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS(QuotingOutputStreamListener, nsCOMTypeInfo<nsIStreamListener>::GetIID());
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// END OF QUOTING LISTENER
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
nsresult
|
|
nsMsgCompose::QuoteOriginalMessage(const PRUnichar *originalMsgURI, PRInt32 what) // New template
|
|
{
|
|
nsresult rv;
|
|
|
|
mQuotingToFollow = PR_FALSE;
|
|
|
|
nsString tmpURI(originalMsgURI);
|
|
char *compString = tmpURI.ToNewCString();
|
|
|
|
// RICHIE - this will get removed when we
|
|
UsingOldQuotingHack(compString);
|
|
PR_FREEIF(compString);
|
|
|
|
if (mUseOldQuotingHack)
|
|
{
|
|
printf("nsMsgCompose: using old quoting function!");
|
|
HackToGetBody(what);
|
|
return NS_OK;
|
|
}
|
|
|
|
// Create a mime parser (nsIStreamConverter)!
|
|
rv = nsComponentManager::CreateInstance(kMsgQuoteCID,
|
|
NULL, nsCOMTypeInfo<nsIMsgQuote>::GetIID(),
|
|
(void **) getter_AddRefs(mQuote));
|
|
if (NS_FAILED(rv) || !mQuote)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// Create the consumer output stream.. this will receive all the HTML from libmime
|
|
mQuoteStreamListener = new QuotingOutputStreamListener();
|
|
|
|
if (!mQuoteStreamListener)
|
|
{
|
|
printf("Failed to create mQuoteStreamListener\n");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
NS_ADDREF(mQuoteStreamListener);
|
|
|
|
NS_ADDREF(this);
|
|
mQuoteStreamListener->SetComposeObj(this);
|
|
|
|
return mQuote->QuoteMessage(originalMsgURI, mQuoteStreamListener);
|
|
}
|
|
|
|
void nsMsgCompose::HackToGetBody(PRInt32 what)
|
|
{
|
|
char *buffer = (char *) PR_CALLOC(16384);
|
|
if (buffer)
|
|
{
|
|
nsString fileName(TEMP_PATH_DIR);
|
|
fileName += TEMP_MESSAGE_IN;
|
|
|
|
nsFileSpec fileSpec(fileName);
|
|
nsInputFileStream fileStream(fileSpec);
|
|
|
|
nsString msgBody = (what == 2 && !m_composeHTML) ? "--------Original Message--------\r\n" : "";
|
|
|
|
// skip RFC822 header
|
|
while (!fileStream.eof() && !fileStream.failed() &&
|
|
fileStream.is_open())
|
|
{
|
|
fileStream.readline(buffer, 1024);
|
|
if (*buffer == 0)
|
|
break;
|
|
}
|
|
// copy message body
|
|
while (!fileStream.eof() && !fileStream.failed() &&
|
|
fileStream.is_open())
|
|
{
|
|
fileStream.readline(buffer, 1024);
|
|
if (what == 1 && ! m_composeHTML)
|
|
msgBody += "> ";
|
|
msgBody += buffer;
|
|
msgBody += MSG_LINEBREAK;
|
|
}
|
|
|
|
if (m_composeHTML)
|
|
{
|
|
nsString lowerMsgBody (msgBody);
|
|
lowerMsgBody.ToLowerCase();
|
|
|
|
PRInt32 startBodyOffset;
|
|
PRInt32 endBodyOffset = -1;
|
|
PRInt32 offset;
|
|
startBodyOffset = lowerMsgBody.Find("<html>");
|
|
if (startBodyOffset != -1) //it's an HTML body
|
|
{
|
|
//Does it have a <body> tag?
|
|
offset = lowerMsgBody.Find("<body");
|
|
if (offset != -1)
|
|
{
|
|
offset = lowerMsgBody.FindChar('>', PR_FALSE,offset);
|
|
if (offset != -1)
|
|
{
|
|
startBodyOffset = offset + 1;
|
|
endBodyOffset = lowerMsgBody.RFind("</body>");
|
|
}
|
|
}
|
|
if (endBodyOffset == -1)
|
|
endBodyOffset = lowerMsgBody.RFind("</html>");
|
|
}
|
|
|
|
if (startBodyOffset == -1)
|
|
startBodyOffset = 0;
|
|
if (endBodyOffset == -1)
|
|
endBodyOffset = lowerMsgBody.Length();
|
|
|
|
msgBody.Insert(MSG_LINEBREAK, endBodyOffset);
|
|
if (startBodyOffset == 0)
|
|
{
|
|
msgBody.Insert("</html>", endBodyOffset);
|
|
msgBody.Insert(MSG_LINEBREAK, endBodyOffset);
|
|
}
|
|
msgBody.Insert("</blockquote>", endBodyOffset);
|
|
msgBody.Insert(MSG_LINEBREAK, endBodyOffset);
|
|
|
|
msgBody.Insert(MSG_LINEBREAK, startBodyOffset);
|
|
msgBody.Insert("<blockquote TYPE=CITE>", startBodyOffset);
|
|
msgBody.Insert(MSG_LINEBREAK, startBodyOffset);
|
|
if (startBodyOffset == 0)
|
|
{
|
|
msgBody.Insert("<html>", startBodyOffset);
|
|
msgBody.Insert(MSG_LINEBREAK, startBodyOffset);
|
|
msgBody.Insert("<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">", startBodyOffset);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//ducarroz: today, we are not converting HTML to plain text if needed!
|
|
}
|
|
|
|
// m_compFields->SetBody(msgBody.ToNewCString());
|
|
// SetBody() strdup()'s cmsgBody.
|
|
m_compFields->SetBody(nsAutoCString(msgBody));
|
|
PR_Free(buffer);
|
|
|
|
ProcessSignature(nsnull);
|
|
}
|
|
}
|
|
|
|
//CleanUpRecipient will remove un-necesary "<>" when a recipient as an address without name
|
|
void nsMsgCompose::CleanUpRecipients(nsString& recipients)
|
|
{
|
|
// TODO...
|
|
PRInt16 i;
|
|
PRBool startANewRecipient = PR_TRUE;
|
|
PRBool removeBracket = PR_FALSE;
|
|
nsAutoString newRecipient;
|
|
PRUnichar aChar;
|
|
|
|
for (i = 0; i < recipients.Length(); i ++)
|
|
{
|
|
aChar = recipients[i];
|
|
switch (aChar)
|
|
{
|
|
case '<' :
|
|
if (startANewRecipient)
|
|
removeBracket = PR_TRUE;
|
|
else
|
|
newRecipient += aChar;
|
|
startANewRecipient = PR_FALSE;
|
|
break;
|
|
|
|
case '>' :
|
|
if (removeBracket)
|
|
removeBracket = PR_FALSE;
|
|
else
|
|
newRecipient += aChar;
|
|
break;
|
|
|
|
case ' ' :
|
|
newRecipient += aChar;
|
|
break;
|
|
|
|
case ',' :
|
|
newRecipient += aChar;
|
|
startANewRecipient = PR_TRUE;
|
|
removeBracket = PR_FALSE;
|
|
break;
|
|
|
|
default :
|
|
newRecipient += aChar;
|
|
startANewRecipient = PR_FALSE;
|
|
break;
|
|
}
|
|
}
|
|
recipients = newRecipient;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// This is the listener class for both the send operation and the copy operation.
|
|
// We have to create this class to listen for message send completion and deal with
|
|
// failures in both send and copy operations
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
NS_IMPL_ADDREF(nsMsgComposeSendListener)
|
|
NS_IMPL_RELEASE(nsMsgComposeSendListener)
|
|
|
|
nsIMsgSendListener ** nsMsgComposeSendListener::CreateListenerArray()
|
|
{
|
|
nsIMsgSendListener **tArray = (nsIMsgSendListener **)PR_Malloc(sizeof(nsIMsgSendListener *) * 2);
|
|
if (!tArray)
|
|
return nsnull;
|
|
nsCRT::memset(tArray, 0, sizeof(nsIMsgSendListener *) * 2);
|
|
tArray[0] = this;
|
|
return tArray;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgComposeSendListener::QueryInterface(const nsIID &aIID, void** aInstancePtr)
|
|
{
|
|
if (NULL == aInstancePtr)
|
|
return NS_ERROR_NULL_POINTER;
|
|
*aInstancePtr = NULL;
|
|
|
|
if (aIID.Equals(nsCOMTypeInfo<nsIMsgSendListener>::GetIID()))
|
|
{
|
|
*aInstancePtr = (nsIMsgSendListener *) this;
|
|
NS_ADDREF_THIS();
|
|
return NS_OK;
|
|
}
|
|
if (aIID.Equals(nsCOMTypeInfo<nsIMsgCopyServiceListener>::GetIID()))
|
|
{
|
|
*aInstancePtr = (nsIMsgCopyServiceListener *) this;
|
|
NS_ADDREF_THIS();
|
|
return NS_OK;
|
|
}
|
|
|
|
return NS_NOINTERFACE;
|
|
}
|
|
|
|
nsMsgComposeSendListener::nsMsgComposeSendListener(void)
|
|
{
|
|
mComposeObj = nsnull;
|
|
mDeliverMode = 0;
|
|
|
|
NS_INIT_REFCNT();
|
|
}
|
|
|
|
nsMsgComposeSendListener::~nsMsgComposeSendListener(void)
|
|
{
|
|
}
|
|
|
|
nsresult nsMsgComposeSendListener::SetComposeObj(nsMsgCompose *obj)
|
|
{
|
|
mComposeObj = obj;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsMsgComposeSendListener::SetDeliverMode(MSG_DeliverMode deliverMode)
|
|
{
|
|
mDeliverMode = deliverMode;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgComposeSendListener::OnStartSending(const char *aMsgID, PRUint32 aMsgSize)
|
|
{
|
|
#ifdef NS_DEBUG
|
|
printf("nsMsgComposeSendListener::OnStartSending()\n");
|
|
#endif
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgComposeSendListener::OnProgress(const char *aMsgID, PRUint32 aProgress, PRUint32 aProgressMax)
|
|
{
|
|
#ifdef NS_DEBUG
|
|
printf("nsMsgComposeSendListener::OnProgress()\n");
|
|
#endif
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgComposeSendListener::OnStatus(const char *aMsgID, const PRUnichar *aMsg)
|
|
{
|
|
#ifdef NS_DEBUG
|
|
printf("nsMsgComposeSendListener::OnStatus()\n");
|
|
#endif
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsMsgComposeSendListener::OnStopSending(const char *aMsgID, nsresult aStatus, const PRUnichar *aMsg,
|
|
nsIFileSpec *returnFileSpec)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if (mComposeObj)
|
|
{
|
|
if (NS_SUCCEEDED(aStatus))
|
|
{
|
|
#ifdef NS_DEBUG
|
|
printf("nsMsgComposeSendListener: Success on the message send operation!\n");
|
|
#endif
|
|
nsIMsgCompFields *compFields = nsnull;
|
|
mComposeObj->GetCompFields(&compFields); //GetCompFields will addref, you need to release when your are done with it
|
|
|
|
// Close the window ONLY if we are not going to do a save operation
|
|
PRUnichar *fieldsFCC = nsnull;
|
|
if (NS_SUCCEEDED(compFields->GetFcc(&fieldsFCC)))
|
|
{
|
|
nsString2 compString("nocopy://");
|
|
if (fieldsFCC && *fieldsFCC)
|
|
{
|
|
if (compString == fieldsFCC)
|
|
mComposeObj->CloseWindow();
|
|
}
|
|
}
|
|
else
|
|
mComposeObj->CloseWindow(); // if we fail on the simple GetFcc call, close the window to be safe and avoid
|
|
// windows hanging around to prevent the app from exiting.
|
|
|
|
NS_IF_RELEASE(compFields);
|
|
}
|
|
else
|
|
{
|
|
#ifdef NS_DEBUG
|
|
printf("nsMsgComposeSendListener: the message send operation failed!\n");
|
|
#endif
|
|
mComposeObj->ShowWindow(PR_TRUE);
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgComposeSendListener::OnStartCopy()
|
|
{
|
|
#ifdef NS_DEBUG
|
|
printf("nsMsgComposeSendListener::OnStartCopy()\n");
|
|
#endif
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgComposeSendListener::OnProgress(PRUint32 aProgress, PRUint32 aProgressMax)
|
|
{
|
|
#ifdef NS_DEBUG
|
|
printf("nsMsgComposeSendListener::OnProgress() - COPY\n");
|
|
#endif
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgComposeSendListener::OnStopCopy(nsresult aStatus)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if (mComposeObj)
|
|
{
|
|
// Ok, if we are here, we are done with the send/copy operation so
|
|
// we have to do something with the window....SHOW if failed, Close
|
|
// if succeeded
|
|
if (NS_SUCCEEDED(aStatus))
|
|
{
|
|
#ifdef NS_DEBUG
|
|
printf("nsMsgComposeSendListener: Success on the message copy operation!\n");
|
|
#endif
|
|
// We should only close the window if we are done. Things like templates
|
|
// and drafts aren't done so their windows should stay open
|
|
if ( (mDeliverMode != nsMsgSaveAsDraft) && (mDeliverMode != nsMsgSaveAsTemplate) )
|
|
mComposeObj->CloseWindow();
|
|
}
|
|
else
|
|
{
|
|
#ifdef NS_DEBUG
|
|
printf("nsMsgComposeSendListener: the message copy operation failed!\n");
|
|
#endif
|
|
mComposeObj->ShowWindow(PR_TRUE);
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgComposeSendListener::SetMessageKey(PRUint32 aMessageKey)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgComposeSendListener::GetMessageId(nsString2* aMessageId)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// This is a class that will allow us to listen to state changes in the Ender
|
|
// compose window. This is important since we must wait until we are told Ender
|
|
// is ready before we do various quoting operations
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NS_IMPL_ISUPPORTS(nsMsgDocumentStateListener, nsCOMTypeInfo<nsIDocumentStateListener>::GetIID());
|
|
|
|
nsMsgDocumentStateListener::nsMsgDocumentStateListener(void)
|
|
{
|
|
NS_INIT_REFCNT();
|
|
mComposeObj = nsnull;
|
|
}
|
|
|
|
nsMsgDocumentStateListener::~nsMsgDocumentStateListener(void)
|
|
{
|
|
}
|
|
|
|
void
|
|
nsMsgDocumentStateListener::SetComposeObj(nsMsgCompose *obj)
|
|
{
|
|
mComposeObj = obj;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgDocumentStateListener::NotifyDocumentCreated(void)
|
|
{
|
|
// Ok, now the document has been loaded, so we are ready to let
|
|
// the user run hog wild with editing...but first, lets cleanup
|
|
// any temp files
|
|
//
|
|
if (mComposeObj->mSigFileSpec)
|
|
{
|
|
mComposeObj->mSigFileSpec->Delete(PR_FALSE);
|
|
delete mComposeObj->mSigFileSpec;
|
|
mComposeObj->mSigFileSpec = nsnull;
|
|
}
|
|
|
|
if (mComposeObj->mTempComposeFileSpec)
|
|
{
|
|
mComposeObj->mTempComposeFileSpec->Delete(PR_FALSE);
|
|
delete mComposeObj->mTempComposeFileSpec;
|
|
mComposeObj->mTempComposeFileSpec = nsnull;
|
|
}
|
|
|
|
// RICHIE - hack! This is only if we are using the old
|
|
// quoting hack
|
|
if (mComposeObj->mUseOldQuotingHack)
|
|
{
|
|
PRUnichar *bod;
|
|
|
|
nsIMsgCompFields *compFields;
|
|
mComposeObj->GetCompFields(&compFields);
|
|
compFields->GetBody(&bod);
|
|
mComposeObj->LoadAsQuote(nsString(bod));
|
|
PR_FREEIF(bod);
|
|
}
|
|
// RICHIE - hack! This is only if we are using the old
|
|
// quoting hack
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgDocumentStateListener::NotifyDocumentWillBeDestroyed(void)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgDocumentStateListener::NotifyDocumentStateChanged(PRBool nowDirty)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgCompose::ConvertHTMLToText(char *aSigFile, nsString &aSigData)
|
|
{
|
|
nsresult rv;
|
|
nsString origBuf;
|
|
|
|
rv = LoadDataFromFile(aSigFile, origBuf);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
ConvertBufToPlainText(origBuf, nsnull);
|
|
aSigData = origBuf;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgCompose::ConvertTextToHTML(char *aSigFile, nsString &aSigData)
|
|
{
|
|
nsresult rv;
|
|
nsString origBuf;
|
|
|
|
rv = LoadDataFromFile(aSigFile, origBuf);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
aSigData = "<pre>";
|
|
aSigData.Append(origBuf);
|
|
aSigData.Append("</pre>");
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgCompose::LoadDataFromFile(char *sigFilePath, nsString &sigData)
|
|
{
|
|
nsFileSpec fSpec(sigFilePath);
|
|
PRInt32 readSize;
|
|
char *readBuf;
|
|
|
|
nsInputFileStream tempFile(fSpec);
|
|
if (!tempFile.is_open())
|
|
return NS_MSG_ERROR_WRITING_FILE;
|
|
|
|
readSize = fSpec.GetFileSize();
|
|
readBuf = (char *)PR_Malloc(readSize + 1);
|
|
if (!readBuf)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
nsCRT::memset(readBuf, 0, readSize + 1);
|
|
|
|
tempFile.read(readBuf, readSize);
|
|
tempFile.close();
|
|
|
|
sigData = readBuf;
|
|
PR_FREEIF(readBuf);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgCompose::BuildQuotedMessageAndSignature(void)
|
|
{
|
|
//
|
|
// This should never happen...if it does, just bail out...
|
|
//
|
|
if (!m_editor)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// We will fire off the quote operation and wait for it to
|
|
// finish before we actually do anything with Ender...
|
|
return QuoteOriginalMessage(mQuoteURI.GetUnicode(), mWhatHolder);
|
|
}
|
|
|
|
//
|
|
// This will process the signature file for the user. If aAppendFile
|
|
// is passed in, then this will be treated as an operation following
|
|
// a quoting operation and the specified signature will be appended
|
|
// to the file passed in. If this argument is null, then this is a clean
|
|
// compose window and we should just create whatever we need to create
|
|
// as a temp file and do a LoadURL operation.
|
|
//
|
|
nsresult
|
|
nsMsgCompose::ProcessSignature(nsOutputFileStream *aAppendFileStream)
|
|
{
|
|
nsresult rv;
|
|
|
|
//
|
|
// This should never happen...if it does, just bail out...
|
|
//
|
|
if (!m_editor)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// Now, we can get sort of fancy. This is the time we need to check
|
|
// for all sorts of user defined stuff, like signatures and editor
|
|
// types and the like!
|
|
//
|
|
// user_pref("mail.signature_file", "y:\\sig.html");
|
|
// user_pref("mail.use_signature_file", true);
|
|
//
|
|
// Note: We will have intelligent signature behavior in that we
|
|
// look at the signature file first...if the extension is .htm or
|
|
// .html, we assume its HTML, otherwise, we assume it is plain text
|
|
//
|
|
nsString urlStr;
|
|
char *sigFilePath = nsnull;
|
|
PRBool useSigFile = PR_FALSE;
|
|
PRBool htmlSig = PR_FALSE;
|
|
nsString sigData = "";
|
|
|
|
NS_WITH_SERVICE(nsIPref, prefs, kPrefCID, &rv);
|
|
if (NS_SUCCEEDED(rv) && prefs)
|
|
{
|
|
rv = prefs->GetBoolPref("mail.use_signature_file", &useSigFile);
|
|
if (NS_SUCCEEDED(rv) && useSigFile)
|
|
{
|
|
rv = prefs->CopyCharPref("mail.signature_file", &sigFilePath);
|
|
}
|
|
}
|
|
|
|
// Setup the urlStr to load to be the signature if the user wants it
|
|
// that way...
|
|
//
|
|
if ((useSigFile) && (sigFilePath))
|
|
{
|
|
nsFileSpec testSpec(sigFilePath);
|
|
|
|
if (!testSpec.Exists())
|
|
{
|
|
PR_FREEIF(sigFilePath);
|
|
sigFilePath = nsnull;
|
|
if (m_composeHTML)
|
|
urlStr = "chrome://messengercompose/content/defaultHtmlBody.html";
|
|
else
|
|
urlStr = "chrome://messengercompose/content/defaultTextBody.txt";
|
|
}
|
|
else
|
|
{
|
|
// Once we get here, we need to figure out if we have the correct file
|
|
// type for the editor.
|
|
//
|
|
char *fileExt = nsMsgGetExtensionFromFileURL(nsString(sigFilePath));
|
|
|
|
if ( (fileExt) && (*fileExt) )
|
|
{
|
|
htmlSig = ( (!PL_strcasecmp(fileExt, "HTM")) || (!PL_strcasecmp(fileExt, "HTML")) );
|
|
PR_FREEIF(fileExt);
|
|
}
|
|
|
|
// is this a text sig with an HTML editor?
|
|
if ( (m_composeHTML) && (!htmlSig) )
|
|
ConvertTextToHTML(sigFilePath, sigData);
|
|
// is this a HTML sig with a text window?
|
|
else if ( (!m_composeHTML) && (htmlSig) )
|
|
ConvertHTMLToText(sigFilePath, sigData);
|
|
else // We have a match...
|
|
{
|
|
if (!aAppendFileStream) // Just load this URL
|
|
urlStr = nsMsgPlatformFileToURL(sigFilePath);
|
|
else
|
|
LoadDataFromFile(sigFilePath, sigData); // Get the data!
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_composeHTML)
|
|
urlStr = "chrome://messengercompose/content/defaultHtmlBody.html";
|
|
else
|
|
urlStr = "chrome://messengercompose/content/defaultTextBody.txt";
|
|
}
|
|
|
|
PR_FREEIF(sigFilePath);
|
|
|
|
// This is the "load signature alone" operation!
|
|
char *htmlBreak = "<BR>";
|
|
char *dashes = "--";
|
|
if (!aAppendFileStream)
|
|
{
|
|
if ( (sigData == "") && (urlStr != "") ) // just load URL
|
|
{
|
|
m_editor->LoadUrl(urlStr.GetUnicode());
|
|
}
|
|
else // Have to write data to a temp file then load the URL...
|
|
{
|
|
mSigFileSpec = nsMsgCreateTempFileSpec(m_composeHTML ? "sig.html" : "sig.txt");
|
|
if (!mSigFileSpec)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsOutputFileStream tempFile(*mSigFileSpec);
|
|
if (!tempFile.is_open())
|
|
return NS_MSG_ERROR_WRITING_FILE;
|
|
|
|
if (m_composeHTML)
|
|
tempFile.write(htmlBreak, PL_strlen(htmlBreak));
|
|
else
|
|
{
|
|
tempFile.write(MSG_LINEBREAK, MSG_LINEBREAK_LEN);
|
|
tempFile.write(dashes, PL_strlen(dashes));
|
|
}
|
|
if (m_composeHTML)
|
|
tempFile.write(htmlBreak, PL_strlen(htmlBreak));
|
|
else
|
|
tempFile.write(MSG_LINEBREAK, MSG_LINEBREAK_LEN);
|
|
|
|
tempFile.write(nsAutoCString(sigData), sigData.Length());
|
|
tempFile.close();
|
|
urlStr = mSigFileSpec->GetNativePathCString();
|
|
m_editor->LoadUrl(urlStr.GetUnicode());
|
|
}
|
|
}
|
|
else // This is where we are appending to the current file...
|
|
{
|
|
if (sigData != "")
|
|
{
|
|
if (!aAppendFileStream->is_open())
|
|
return NS_MSG_ERROR_WRITING_FILE;
|
|
|
|
if (m_composeHTML)
|
|
aAppendFileStream->write(htmlBreak, PL_strlen(htmlBreak));
|
|
else
|
|
aAppendFileStream->write(MSG_LINEBREAK, MSG_LINEBREAK_LEN);
|
|
|
|
aAppendFileStream->write(dashes, PL_strlen(dashes));
|
|
if (m_composeHTML)
|
|
aAppendFileStream->write(htmlBreak, PL_strlen(htmlBreak));
|
|
else
|
|
aAppendFileStream->write(MSG_LINEBREAK, MSG_LINEBREAK_LEN);
|
|
|
|
aAppendFileStream->write(nsAutoCString(sigData), sigData.Length());
|
|
}
|
|
// else // We are punting on putting a default signature on a quoted message!
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgCompose::BuildBodyMessage()
|
|
{
|
|
PRUnichar *bod;
|
|
|
|
//
|
|
// This should never happen...if it does, just bail out...
|
|
//
|
|
if (!m_editor)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// Since we have a body in the comp fields, we need to create a
|
|
// body of this old body...
|
|
//
|
|
mTempComposeFileSpec = nsMsgCreateTempFileSpec(m_composeHTML ? "nscomp.html" : "nscomp.txt");
|
|
if (!mTempComposeFileSpec)
|
|
return NS_MSG_ERROR_WRITING_FILE;
|
|
|
|
nsOutputFileStream tempFile(*(mTempComposeFileSpec));
|
|
if (!tempFile.is_open())
|
|
return NS_MSG_ERROR_WRITING_FILE;
|
|
|
|
m_compFields->GetBody(&bod);
|
|
|
|
nsString tempBody(bod);
|
|
tempFile.write(nsAutoCString(tempBody), tempBody.Length());
|
|
tempFile.close();
|
|
|
|
//
|
|
// Now load the URL...
|
|
//
|
|
nsString urlStr = nsMsgPlatformFileToURL(mTempComposeFileSpec->GetNativePathCString());
|
|
m_editor->LoadUrl(urlStr.GetUnicode());
|
|
return NS_OK;
|
|
}
|