summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/local/src/nsParseMailbox.h
blob: 1e272cd8c048d6e8829f8ab98aea07717def933c (plain)
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
/* -*- 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 nsParseMailbox_H
#define nsParseMailbox_H

#include "mozilla/Attributes.h"
#include "nsIURI.h"
#include "nsIMsgParseMailMsgState.h"
#include "nsIStreamListener.h"
#include "nsMsgLineBuffer.h"
#include "nsIMsgDatabase.h"
#include "nsIMsgHdr.h"
#include "nsIMsgStatusFeedback.h"
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
#include "nsIDBChangeListener.h"
#include "nsIWeakReferenceUtils.h"
#include "nsIMsgWindow.h"
#include "nsImapMoveCoalescer.h"
#include "nsString.h"
#include "nsIMsgFilterList.h"
#include "nsIMsgFilter.h"
#include "nsIMsgFilterHitNotify.h"
#include "nsTArray.h"

class nsOutputFileStream;
class nsIMsgFolder;

/* Used for the various things that parse RFC822 headers...
 */
typedef struct message_header {
  const char* value; /* The contents of a header (after ": ") */
  int32_t length;    /* The length of the data (it is not NULL-terminated.) */
} message_header;

// This object maintains the parse state for a single mail message.
class nsParseMailMessageState : public nsIMsgParseMailMsgState,
                                public nsIDBChangeListener {
 public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSIMSGPARSEMAILMSGSTATE
  NS_DECL_NSIDBCHANGELISTENER

  nsParseMailMessageState();

  nsresult ParseFolderLine(const char* line, uint32_t lineLength);
  nsresult StartNewEnvelope(const char* line, uint32_t lineLength);
  nsresult ParseHeaders();
  nsresult FinalizeHeaders();
  nsresult ParseEnvelope(const char* line, uint32_t line_size);
  nsresult InternSubject(struct message_header* header);

  // Returns true if line looks like an mbox "From " line.
  static bool IsEnvelopeLine(const char* buf, int32_t buf_size);

  // Helpers for dealing with multi-value headers.
  struct message_header* GetNextHeaderInAggregate(
      nsTArray<struct message_header*>& list);
  void GetAggregateHeader(nsTArray<struct message_header*>& list,
                          struct message_header*);
  void ClearAggregateHeader(nsTArray<struct message_header*>& list);

  nsCOMPtr<nsIMsgDBHdr> m_newMsgHdr; /* current message header we're building */
  nsCOMPtr<nsIMsgDatabase> m_mailDB;
  nsCOMPtr<nsIMsgDatabase> m_backupMailDB;

  nsMailboxParseState m_state;
  int64_t m_position;
  // The start of the "From " line (the line before the start of the message).
  uint64_t m_envelope_pos;
  // The start of the message headers (immediately follows "From " line).
  uint64_t m_headerstartpos;
  nsMsgKey m_new_key;  // DB key for the new header.

  // The "From " line, if any.
  ::nsByteArray m_envelope;

  // These two point into the m_envelope buffer.
  struct message_header m_envelope_from;
  struct message_header m_envelope_date;

  // The raw header data.
  ::nsByteArray m_headers;

  // These all point into the m_headers buffer.
  struct message_header m_message_id;
  struct message_header m_references;
  struct message_header m_date;
  struct message_header m_delivery_date;
  struct message_header m_from;
  struct message_header m_sender;
  struct message_header m_newsgroups;
  struct message_header m_subject;
  struct message_header m_status;
  struct message_header m_mozstatus;
  struct message_header m_mozstatus2;
  struct message_header m_in_reply_to;
  struct message_header m_replyTo;
  struct message_header m_content_type;
  struct message_header m_bccList;

  // Support for having multiple To or Cc header lines in a message
  nsTArray<struct message_header*> m_toList;
  nsTArray<struct message_header*> m_ccList;

  struct message_header m_priority;
  struct message_header m_account_key;
  struct message_header m_keywords;

  // Mdn support
  struct message_header m_mdn_original_recipient;
  struct message_header m_return_path;
  struct message_header m_mdn_dnt; /* MDN Disposition-Notification-To: header */

  PRTime m_receivedTime;
  uint16_t m_body_lines;
  uint16_t m_lastLineBlank;

  // this enables extensions to add the values of particular headers to
  // the .msf file as properties of nsIMsgHdr. It is initialized from a
  // pref, mailnews.customDBHeaders
  nsTArray<nsCString> m_customDBHeaders;
  struct message_header* m_customDBHeaderValues;
  nsCString m_receivedValue;  // accumulated received header
 protected:
  virtual ~nsParseMailMessageState();
};

// This class is part of the mailbox parsing state machine
class nsMsgMailboxParser : public nsIStreamListener,
                           public nsParseMailMessageState,
                           public nsMsgLineBuffer {
 public:
  explicit nsMsgMailboxParser(nsIMsgFolder*);
  nsMsgMailboxParser();
  nsresult Init();

  NS_DECL_ISUPPORTS_INHERITED

  ////////////////////////////////////////////////////////////////////////////////////////
  // we support the nsIStreamListener interface
  ////////////////////////////////////////////////////////////////////////////////////////
  NS_DECL_NSIREQUESTOBSERVER
  NS_DECL_NSISTREAMLISTENER

  void SetDB(nsIMsgDatabase* mailDB) { m_mailDB = mailDB; }

  // message socket libnet callbacks, which come through folder pane
  nsresult ProcessMailboxInputStream(nsIInputStream* aIStream,
                                     uint32_t aLength);

  virtual void DoneParsingFolder(nsresult status);
  virtual void AbortNewHeader();

  // for nsMsgLineBuffer
  virtual nsresult HandleLine(const char* line, uint32_t line_length) override;

  void UpdateDBFolderInfo();
  void UpdateDBFolderInfo(nsIMsgDatabase* mailDB);
  void UpdateStatusText(const char* stringName);

  // Update the progress bar based on what we know.
  virtual void UpdateProgressPercent();
  virtual void OnNewMessage(nsIMsgWindow* msgWindow);

 protected:
  virtual ~nsMsgMailboxParser();
  nsCOMPtr<nsIMsgStatusFeedback> m_statusFeedback;

  virtual int32_t PublishMsgHeader(nsIMsgWindow* msgWindow);

  // data
  nsString m_folderName;
  nsCString m_inboxUri;
  ::nsByteArray m_inputStream;
  uint64_t m_graph_progress_total;
  uint64_t m_graph_progress_received;

 private:
  nsWeakPtr m_folder;
  void ReleaseFolderLock();
  nsresult AcquireFolderLock();
};

class nsParseNewMailState : public nsMsgMailboxParser,
                            public nsIMsgFilterHitNotify {
 public:
  nsParseNewMailState();
  NS_DECL_ISUPPORTS_INHERITED

  nsresult Init(nsIMsgFolder* rootFolder, nsIMsgFolder* downloadFolder,
                nsIMsgWindow* aMsgWindow, nsIMsgDBHdr* aHdr,
                nsIOutputStream* aOutputStream);

  virtual void DoneParsingFolder(nsresult status) override;

  void DisableFilters() { m_disableFilters = true; }

  NS_DECL_NSIMSGFILTERHITNOTIFY

  nsOutputFileStream* GetLogFile();
  virtual int32_t PublishMsgHeader(nsIMsgWindow* msgWindow) override;
  void GetMsgWindow(nsIMsgWindow** aMsgWindow);
  nsresult EndMsgDownload();

  nsresult AppendMsgFromStream(nsIInputStream* fileStream, nsIMsgDBHdr* aHdr,
                               nsIMsgFolder* destFolder);

  void ApplyFilters(bool* pMoved, nsIMsgWindow* msgWindow);
  nsresult ApplyForwardAndReplyFilter(nsIMsgWindow* msgWindow);
  virtual void OnNewMessage(nsIMsgWindow* msgWindow) override;

  // this keeps track of how many messages we downloaded that
  // aren't new - e.g., marked read, or moved to an other server.
  int32_t m_numNotNewMessages;

 protected:
  virtual ~nsParseNewMailState();
  virtual nsresult GetTrashFolder(nsIMsgFolder** pTrashFolder);
  virtual nsresult MoveIncorporatedMessage(nsIMsgDBHdr* mailHdr,
                                           nsIMsgDatabase* sourceDB,
                                           nsIMsgFolder* destIFolder,
                                           nsIMsgFilter* filter,
                                           nsIMsgWindow* msgWindow);
  virtual void MarkFilteredMessageRead(nsIMsgDBHdr* msgHdr);
  virtual void MarkFilteredMessageUnread(nsIMsgDBHdr* msgHdr);

  nsCOMPtr<nsIMsgFilterList> m_filterList;
  nsCOMPtr<nsIMsgFilterList> m_deferredToServerFilterList;
  nsCOMPtr<nsIMsgFolder> m_rootFolder;
  nsCOMPtr<nsIMsgWindow> m_msgWindow;
  nsCOMPtr<nsIMsgFolder> m_downloadFolder;
  nsCOMPtr<nsIOutputStream> m_outputStream;
  nsCOMArray<nsIMsgFolder> m_filterTargetFolders;

  RefPtr<nsImapMoveCoalescer> m_moveCoalescer;

  bool m_msgMovedByFilter;
  bool m_msgCopiedByFilter;
  bool m_disableFilters;

  // we have to apply the reply/forward filters in a second pass, after
  // msg quarantining and moving to other local folders, so we remember the
  // info we'll need to apply them with these vars.
  // these need to be arrays in case we have multiple reply/forward filters.
  nsTArray<nsCString> m_forwardTo;
  nsTArray<nsCString> m_replyTemplateUri;
  nsCOMPtr<nsIMsgDBHdr> m_msgToForwardOrReply;
  nsCOMPtr<nsIMsgFilter> m_filter;
  nsCOMPtr<nsIMsgRuleAction> m_ruleAction;
};

#endif