DXR will be turned off on Tuesday, December 29th. It will redirect to Searchfox.
See the announcement on Discourse.

DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef __MSGSEND_H__
#define __MSGSEND_H__

/* Asynchronous mailing of messages with attached URLs.

   - If there are any attachments, start their URLs going, and write each
     of them to a temp file.

   - While writing to their files, examine the data going by and decide
     what kind of encoding, if any, they need.  Also remember their content
     types.

   - Once that URLs has been saved to a temp file (or, if there were no
     attachments) generate a final temp file, of the actual message:

   -  Generate a string of the headers.
   -  Open the final temp file.
   -  Write the headers.
     -  Examine the first part, and decide whether to encode it.
   -  Write the first part to the file, possibly encoded.
   -  Write the second and subsequent parts to the file, possibly encoded.
        (Open the first temp file and copy it to the final temp file, and so
         on, through an encoding filter.)

   - Delete the attachment temp file(s) as we finish with them.
   - Close the final temp file.
   - Open the news: url.
   - Send the final temp file to NNTP.
     If there's an error, run the callback with "failure" status.
   - If mail succeeded, open the mailto: url.
   - Send the final temp file to SMTP.
     If there's an error, run the callback with "failure" status.
   - Otherwise, run the callback with "success" status.
   - Free everything, delete the final temp file.

  The theory behind the encoding logic:
  =====================================

  If the document is of type text/html, and the user has asked to attach it
  as source or postscript, it will be run through the appropriate converter
  (which will result in a document of type text/plain.)

  An attachment will be encoded if:

   - it is of a non-text type (in which case we will use base64); or
   - The "use QP" option has been selected and high-bit characters exist; or
   - any NULLs exist in the document; or
   - any line is longer than 990 bytes (see LINELENGTH_ENCODING_THRESHOLD below)
     and it is not of type message/rfc822.

   - If we are encoding, and more than 10% of the document consists of
     non-ASCII characters, then we always use base64 instead of QP.

  We eschew quoted-printable in favor of base64 for documents which are likely
  to always be binary (images, sound) because, on the off chance that a GIF
  file (for example) might contain primarily bytes in the ASCII range, using
  the quoted-printable representation might cause corruption due to the
  translation of CR or LF to CRLF.  So, when we don't know that the document
  has "lines", we don't use quoted-printable.
 */

/* For maximal compatibility, it helps to emit both
      Content-Type: <type>; name="<original-file-name>"
   as well as
      Content-Disposition: inline; filename="<original-file-name>"

  The lossage here is, RFC1341 defined the "name" parameter to Content-Type,
  but then RFC1521 deprecated it in anticipation of RFC1806, which defines
  Content-Type and the "filename" parameter.  But, RFC1521 is "Standards Track"
  while RFC1806 is still "Experimental."  So, it's probably best to just
  implement both.
 */
#define EMIT_NAME_IN_CONTENT_TYPE

/* Whether the contents of the BCC header should be preserved in the FCC'ed
   copy of a message.  See comments below, in mime_do_fcc_1().
 */
#define SAVE_BCC_IN_FCC_FILE

/* When attaching an HTML document, one must indicate the original URL of
   that document, if the receiver is to have any chance of being able to
   retrieve and display the inline images, or to click on any links in the
   HTML.

   The way we have done this in the past is by inserting a <BASE> tag as the
   first line of all HTML documents we attach.  (This is kind of bad in that
   we're actually modifying the document, and it really isn't our place to
   do that.)

   The sanctioned *new* way of doing this is to insert a Content-Base header
   field on the attachment.  This is (will be) a part of the forthcoming MHTML
   spec.

   If GENERATE_CONTENT_BASE, we generate a Content-Base header.

   We used to have a MANGLE_HTML_ATTACHMENTS_WITH_BASE_TAG symbol that we
   defined, which added a BASE tag to the bodies.  We stopped doing this in
   4.0.  */
#define GENERATE_CONTENT_BASE


//
// Necessary includes
//
#include "nsCOMPtr.h"
#include "nsIMsgSend.h"
#include "nsIStringBundle.h"
#include "msgCore.h"
#include "prprf.h"
#include "nsIOutputStream.h"
#include "nsMsgMessageFlags.h"
#include "nsIURL.h"
#include "nsMsgAttachmentHandler.h"
#include "nsMsgCompFields.h"
#include "nsIMsgSendListener.h"
#include "nsIEditor.h"
#include "nsIUrlListener.h"
#include "nsIMsgStatusFeedback.h"
#include "nsIMsgIdentity.h"
#include "nsIMsgHdr.h"
#include "nsIMsgIdentity.h"
#include "nsWeakReference.h"
#include "nsPIDOMWindow.h"
#include "nsIDOMWindow.h"
#include "nsIMsgComposeSecure.h"
#include "nsAutoPtr.h"
#include "nsMsgAttachmentData.h"
#include "nsIMsgFilterService.h"
#include "nsIMsgOperationListener.h"
#include "nsMsgIncomingServer.h"
#include "mozilla/dom/Element.h"

//
// Some necessary defines...
//
#define MIME_BUFFER_SIZE      4096 // must be greater than 1000
                                   // SMTP (RFC821) limit
// Maximum number of bytes we allow in a line before we force
// encoding to base64 if not already QR-encoded or of type message/rfc822.
#define LINELENGTH_ENCODING_THRESHOLD 990

//
// Utilities for string handling
//
#define PUSH_STRING(S) \
 do { PL_strcpy (buffer_tail, S); buffer_tail += PL_strlen (S); } while(0)
#define PUSH_STRINGN(S,N) \
 do { memcpy(buffer_tail, (S), (N)); buffer_tail += (N); } while(0)
#define PUSH_NEWLINE() \
 do { *buffer_tail++ = '\r'; *buffer_tail++ = '\n'; *buffer_tail = '\0'; } while(0)

//
// Forward declarations...
//
class nsMsgSendPart;
class nsMsgCopy;
class nsIPrompt;
class nsIInterfaceRequestor;

namespace mozilla {
namespace mailnews {
class MimeEncoder;
}
}

class nsMsgComposeAndSend : public nsIMsgSend,
                            public nsIMsgOperationListener,
                            public nsSupportsWeakReference
{
  typedef mozilla::mailnews::MimeEncoder MimeEncoder;
public:
  //
  // Define QueryInterface, AddRef and Release for this class
  //
  NS_DECL_THREADSAFE_ISUPPORTS
  NS_DECL_NSIMSGSEND
  NS_DECL_NSIMSGOPERATIONLISTENER

  nsMsgComposeAndSend();


  // Delivery and completion callback routines...
  NS_IMETHOD  DeliverMessage();
  NS_IMETHOD  DeliverFileAsMail();
  NS_IMETHOD  DeliverFileAsNews();
  void        DoDeliveryExitProcessing(nsIURI * aUrl, nsresult aExitCode, bool aCheckForMail);
  nsresult    FormatStringWithSMTPHostNameByName(const char* aMsgName, nsAString& aString);

  nsresult    DoFcc();
  nsresult    StartMessageCopyOperation(nsIFile          *aFileSpec,
                                        nsMsgDeliverMode mode,
                                        const nsCString& dest_uri);


  nsresult SendToMagicFolder(nsMsgDeliverMode flag);

  // For the folderURL return the corresponding pointer to the incoming server.
  nsresult GetIncomingServer(const char *folderURL, nsIMsgIncomingServer **aServer);

  // Check to see if it's ok to save msgs to the configured folder.
  bool CanSaveMessagesToFolder(const char *folderURL);

  //
  // FCC operations...
  //
  nsresult    MimeDoFCC (nsIFile *input_file,
    nsMsgDeliverMode mode,
    const char *bcc_header,
    const char *fcc_header,
    const char *news_url);

  // Init() will allow for either message creation without delivery or full
  // message creation and send operations
  //
  nsresult    Init(
                   nsIMsgIdentity   *aUserIdentity,
                   const char       *aAccountKey,
                   nsMsgCompFields  *fields,
                   nsIFile          *sendFile,
                   bool             digest_p,
                   bool             dont_deliver_p,
                   nsMsgDeliverMode mode,
                   nsIMsgDBHdr      *msgToReplace,
                   const char       *attachment1_type,
                   const nsACString &attachment1_body,
                   nsIArray   *attachments,
                   nsIArray     *preloaded_attachments,
                   const nsAString &password,
                   const nsACString &aOriginalMsgURI,
                   MSG_ComposeType  aType);

  //
  // Setup the composition fields
  //
  nsresult    InitCompositionFields(nsMsgCompFields *fields,
                                    const nsACString &aOriginalMsgURI,
                                    MSG_ComposeType aType);

  NS_IMETHOD  GetBodyFromEditor();


  //
  // Attachment processing...
  //
  nsresult    HackAttachments(nsIArray *attachments,
                              nsIArray *preloaded_attachments);
  nsresult    CountCompFieldAttachments();
  nsresult    AddCompFieldLocalAttachments();
  nsresult    AddCompFieldRemoteAttachments(uint32_t  aStartLocation, int32_t *aMailboxCount, int32_t *aNewsCount);

  // Deal with multipart related data
  nsresult    ProcessMultipartRelated(int32_t *aMailboxCount, int32_t *aNewsCount);
  nsresult    GetEmbeddedObjectInfo(mozilla::dom::Element *domElement, nsMsgAttachmentData *attachment, bool *acceptObject);
  uint32_t    GetMultipartRelatedCount(bool forceToBeCalculated = false);
  nsCOMPtr<nsIArray> mEmbeddedObjectList; // it's initialized when calling GetMultipartRelatedCount

  // Body processing
  nsresult    SnarfAndCopyBody(const nsACString &attachment1_body,
                               const char  *attachment1_type);

  int32_t     PreProcessPart(nsMsgAttachmentHandler  *ma,
                             nsMsgSendPart           *toppart); // The very top most container of the message
                                                                // For part processing

  nsresult    SetStatusMessage(const nsString &aMsgString);     // Status message method

  //
  // All vars necessary for this implementation
  //
  nsMsgKey                  m_messageKey;        // jt -- Draft/Template support; newly created key
  nsCOMPtr<nsIMsgIdentity>  mUserIdentity;
  nsCString                 mAccountKey;
  RefPtr<nsMsgCompFields> mCompFields;         // All needed composition fields (header, etc...)
  nsCOMPtr<nsIFile>         mTempFile;           // our temporary file

  nsCOMPtr<nsIOutputStream> mOutputFile;         // the actual output file stream
  uint32_t                  mMessageWarningSize; // Warn if a message is over this size!

  bool                      m_dont_deliver_p;    // If set, we just return the nsIFile of the file
                                                 // created, instead of actually delivering message.
  nsMsgDeliverMode          m_deliver_mode;      // nsMsgDeliverNow, nsMsgQueueForLater, nsMsgSaveAsDraft,
                                                 // nsMsgSaveAsTemplate and nsMsgSendUnsent
  nsCOMPtr<nsIMsgDBHdr>     mMsgToReplace;       // If the mode is nsMsgSaveAsDraft, this is the message it will
                                                 // replace
  nsString mSavedToFolderName; // Name of folder we're saving to, used when
                               // displaying error on save.
  // These are needed for callbacks to the FE...
  nsCOMPtr<nsPIDOMWindowOuter>    mParentWindow;
  nsCOMPtr<nsIMsgProgress>        mSendProgress;
  nsCOMPtr<nsIMsgSendListener>    mListener;
  nsCOMPtr<nsIMsgStatusFeedback>  mStatusFeedback;
  nsCOMPtr<nsIRequest>      mRunningRequest;
  bool                      mSendMailAlso;
  nsCOMPtr<nsIFile>         mReturnFile;     // a holder for file spec's to be returned to caller

  // File where we stored our HTML so that we could make the plaintext form.
  nsCOMPtr<nsIFile>         mHTMLFile;

  // Variable for storing the draft name;
  nsCString                  m_folderName;

  // mapping between editor dom node indexes and saved mime part numbers.
  nsTArray<nsCString> m_partNumbers;
  //
  // These variables are needed for message Copy operations!
  //
  nsCOMPtr<nsIFile>         mCopyFile;
  nsCOMPtr<nsIFile>         mCopyFile2;
  RefPtr<nsMsgCopy>       mCopyObj;
  bool                      mNeedToPerformSecondFCC;
  bool                      mPerformingSecondFCC;

  // For MHTML message creation
  nsCOMPtr<nsIEditor>       mEditor;

  //
  // The first attachment, if any (typed in by the user.)
  //
  char                    *m_attachment1_type;
  char                    *m_attachment1_encoding;
  nsAutoPtr<MimeEncoder>  m_attachment1_encoder;
  char                    *m_attachment1_body;
  uint32_t                m_attachment1_body_length;
  char                    *mOriginalHTMLBody;

  // The plaintext form of the first attachment, if needed.
  RefPtr<nsMsgAttachmentHandler>  m_plaintext;

  // The multipart/related save object for HTML text.
  nsMsgSendPart           *m_related_part;
  nsMsgSendPart           *m_related_body_part;

  //
  // Subsequent attachments, if any.
  //
  uint32_t                m_attachment_count;
  uint32_t                m_attachment_pending_count;
  nsTArray< RefPtr<nsMsgAttachmentHandler> >  m_attachments;
  nsresult                m_status; // in case some attachments fail but not all

  uint32_t                mPreloadedAttachmentCount;
  uint32_t                mRemoteAttachmentCount;
  int32_t                 mMultipartRelatedAttachmentCount; // the number of mpart related attachments, -1 means it has not been yet initialized

  uint32_t                mCompFieldLocalAttachments;     // the number of file:// attachments in the comp fields
  uint32_t                mCompFieldRemoteAttachments;    // the number of remote attachments in the comp fields

  //
  // attachment states and other info...
  //
  bool                    m_pre_snarfed_attachments_p;  // If true, then the attachments were
                                                        // loaded by in the background and therefore
                                                        // we shouldn't delete the tmp files (but should
                                                        // leave that to the caller.)

  bool                    m_digest_p;                   // Whether to be multipart/digest instead of
                                                        // multipart/mixed.

  bool                    m_be_synchronous_p;            // If true, we will load one URL after another,
                                                        // rather than starting all URLs going at once
                                                        // and letting them load in parallel.  This is
                                                        // more efficient if (for example) all URLs are
                                                        // known to be coming from the same news server
                                                        // or mailbox: loading them in parallel would
                                                        // cause multiple connections to the news
                                                        // server to be opened, or would cause much seek()ing.

  bool                    mGUINotificationEnabled;      // Should we throw up the GUI alerts on errors?
  bool                    mAbortInProcess;              // Used by Abort to avoid reentrance.

  nsCOMPtr<nsIMsgComposeSecure> m_crypto_closure;

protected:
  nsCOMPtr<nsIStringBundle> mComposeBundle;
  nsresult GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks);

  virtual ~nsMsgComposeAndSend();
  nsresult FilterSentMessage();
  nsresult MaybePerformSecondFCC(nsresult aStatus);

  // generates a message id for our message, if necessary
  void GenerateMessageId( );

  // add default custom headers to the message
  nsresult AddDefaultCustomHeaders();

  // add Mail-Followup-To and Mail-Reply-To header
  nsresult AddMailFollowupToHeader();
  nsresult AddMailReplyToHeader();
  nsresult AddXForwardedMessageIdHeader();

  nsCOMPtr<nsIMsgSendReport>  mSendReport;
  nsString                    mSmtpPassword;            // store the smtp Password use during a send
};

//
// These C routines should only be used by the nsMsgSendPart class.
//
extern nsresult mime_write_message_body(nsIMsgSend *state, const char *buf, uint32_t size);
extern char   *mime_get_stream_write_buffer(void);
extern nsresult mime_encoder_output_fn (const char *buf, int32_t size, void *closure);
extern bool UseQuotedPrintable(void);

#endif /*  __MSGSEND_H__ */