1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "msgCore.h"
7 
8 #include "nsIURI.h"
9 #include "nsNetCID.h"
10 #include "nsSmtpUrl.h"
11 #include "nsString.h"
12 #include "nsMsgUtils.h"
13 #include "nsIMimeConverter.h"
14 #include "nsMsgMimeCID.h"
15 #include "nsComponentManagerUtils.h"
16 #include "nsServiceManagerUtils.h"
17 #include "nsCRT.h"
18 #include "mozilla/Encoding.h"
19 
20 /////////////////////////////////////////////////////////////////////////////////////
21 // mailto url definition
22 /////////////////////////////////////////////////////////////////////////////////////
nsMailtoUrl()23 nsMailtoUrl::nsMailtoUrl() { mFormat = nsIMsgCompFormat::Default; }
24 
~nsMailtoUrl()25 nsMailtoUrl::~nsMailtoUrl() {}
26 
NS_IMPL_ISUPPORTS(nsMailtoUrl,nsIMailtoUrl,nsIURI)27 NS_IMPL_ISUPPORTS(nsMailtoUrl, nsIMailtoUrl, nsIURI)
28 
29 static void UnescapeAndConvert(nsIMimeConverter* mimeConverter,
30                                const nsACString& escaped, nsACString& out) {
31   NS_ASSERTION(mimeConverter, "Set mimeConverter before calling!");
32   // If the string is empty, do absolutely nothing.
33   if (escaped.IsEmpty()) return;
34 
35   MsgUnescapeString(escaped, 0, out);
36   nsAutoCString decodedString;
37   nsresult rv = mimeConverter->DecodeMimeHeaderToUTF8(out, "UTF_8", false, true,
38                                                       decodedString);
39   if (NS_SUCCEEDED(rv) && !decodedString.IsEmpty()) out = decodedString;
40 }
41 
ParseMailtoUrl(char * searchPart)42 nsresult nsMailtoUrl::ParseMailtoUrl(char* searchPart) {
43   char* rest = searchPart;
44   nsCString escapedInReplyToPart;
45   nsCString escapedToPart;
46   nsCString escapedCcPart;
47   nsCString escapedSubjectPart;
48   nsCString escapedNewsgroupPart;
49   nsCString escapedNewsHostPart;
50   nsCString escapedReferencePart;
51   nsCString escapedBodyPart;
52   nsCString escapedBccPart;
53   nsCString escapedFollowUpToPart;
54   nsCString escapedFromPart;
55   nsCString escapedHtmlPart;
56   nsCString escapedOrganizationPart;
57   nsCString escapedReplyToPart;
58   nsCString escapedPriorityPart;
59 
60   // okay, first, free up all of our old search part state.....
61   CleanupMailtoState();
62   // m_toPart has the escaped address from before the query string, copy it
63   // over so we can add on any additional to= addresses and unescape them all.
64   escapedToPart = m_toPart;
65 
66   if (rest && *rest == '?') {
67     /* start past the '?' */
68     rest++;
69   }
70 
71   if (rest) {
72     char* token = NS_strtok("&", &rest);
73     while (token && *token) {
74       char* value = 0;
75       char* eq = PL_strchr(token, '=');
76       if (eq) {
77         value = eq + 1;
78         *eq = 0;
79       }
80 
81       nsCString decodedName;
82       MsgUnescapeString(nsDependentCString(token), 0, decodedName);
83 
84       if (decodedName.IsEmpty()) break;
85 
86       switch (NS_ToUpper(decodedName.First())) {
87           /* DO NOT support attachment= in mailto urls. This poses a security
88              fire hole!!! case 'A': if (!PL_strcasecmp (token, "attachment"))
89                             m_attachmentPart = value;
90                             break;
91                        */
92         case 'B':
93           if (decodedName.LowerCaseEqualsLiteral("bcc")) {
94             if (!escapedBccPart.IsEmpty()) {
95               escapedBccPart += ", ";
96               escapedBccPart += value;
97             } else
98               escapedBccPart = value;
99           } else if (decodedName.LowerCaseEqualsLiteral("body")) {
100             if (!escapedBodyPart.IsEmpty()) {
101               escapedBodyPart += "\n";
102               escapedBodyPart += value;
103             } else
104               escapedBodyPart = value;
105           }
106           break;
107         case 'C':
108           if (decodedName.LowerCaseEqualsLiteral("cc")) {
109             if (!escapedCcPart.IsEmpty()) {
110               escapedCcPart += ", ";
111               escapedCcPart += value;
112             } else
113               escapedCcPart = value;
114           }
115           break;
116         case 'F':
117           if (decodedName.LowerCaseEqualsLiteral("followup-to"))
118             escapedFollowUpToPart = value;
119           else if (decodedName.LowerCaseEqualsLiteral("from"))
120             escapedFromPart = value;
121           break;
122         case 'H':
123           if (decodedName.LowerCaseEqualsLiteral("html-part") ||
124               decodedName.LowerCaseEqualsLiteral("html-body")) {
125             // escapedHtmlPart holds the body for both html-part and html-body.
126             escapedHtmlPart = value;
127             mFormat = nsIMsgCompFormat::HTML;
128           }
129           break;
130         case 'I':
131           if (decodedName.LowerCaseEqualsLiteral("in-reply-to"))
132             escapedInReplyToPart = value;
133           break;
134 
135         case 'N':
136           if (decodedName.LowerCaseEqualsLiteral("newsgroups"))
137             escapedNewsgroupPart = value;
138           else if (decodedName.LowerCaseEqualsLiteral("newshost"))
139             escapedNewsHostPart = value;
140           break;
141         case 'O':
142           if (decodedName.LowerCaseEqualsLiteral("organization"))
143             escapedOrganizationPart = value;
144           break;
145         case 'R':
146           if (decodedName.LowerCaseEqualsLiteral("references"))
147             escapedReferencePart = value;
148           else if (decodedName.LowerCaseEqualsLiteral("reply-to"))
149             escapedReplyToPart = value;
150           break;
151         case 'S':
152           if (decodedName.LowerCaseEqualsLiteral("subject"))
153             escapedSubjectPart = value;
154           break;
155         case 'P':
156           if (decodedName.LowerCaseEqualsLiteral("priority"))
157             escapedPriorityPart = PL_strdup(value);
158           break;
159         case 'T':
160           if (decodedName.LowerCaseEqualsLiteral("to")) {
161             if (!escapedToPart.IsEmpty()) {
162               escapedToPart += ", ";
163               escapedToPart += value;
164             } else
165               escapedToPart = value;
166           }
167           break;
168         default:
169           break;
170       }  // end of switch statement...
171 
172       if (eq) *eq = '='; /* put it back */
173       token = NS_strtok("&", &rest);
174     }  // while we still have part of the url to parse...
175   }    // if rest && *rest
176 
177   nsresult rv;
178   // Get a global converter
179   nsCOMPtr<nsIMimeConverter> mimeConverter =
180       do_GetService(NS_MIME_CONVERTER_CONTRACTID, &rv);
181   NS_ENSURE_SUCCESS(rv, rv);
182 
183   // Now unescape everything, and mime-decode the things that can be encoded.
184   UnescapeAndConvert(mimeConverter, escapedToPart, m_toPart);
185   UnescapeAndConvert(mimeConverter, escapedCcPart, m_ccPart);
186   UnescapeAndConvert(mimeConverter, escapedBccPart, m_bccPart);
187   UnescapeAndConvert(mimeConverter, escapedSubjectPart, m_subjectPart);
188   UnescapeAndConvert(mimeConverter, escapedNewsgroupPart, m_newsgroupPart);
189   UnescapeAndConvert(mimeConverter, escapedReferencePart, m_referencePart);
190   if (!escapedBodyPart.IsEmpty())
191     MsgUnescapeString(escapedBodyPart, 0, m_bodyPart);
192   if (!escapedHtmlPart.IsEmpty())
193     MsgUnescapeString(escapedHtmlPart, 0, m_htmlPart);
194   UnescapeAndConvert(mimeConverter, escapedNewsHostPart, m_newsHostPart);
195   UnescapeAndConvert(mimeConverter, escapedFollowUpToPart, m_followUpToPart);
196   UnescapeAndConvert(mimeConverter, escapedFromPart, m_fromPart);
197   UnescapeAndConvert(mimeConverter, escapedOrganizationPart,
198                      m_organizationPart);
199   UnescapeAndConvert(mimeConverter, escapedReplyToPart, m_replyToPart);
200   UnescapeAndConvert(mimeConverter, escapedPriorityPart, m_priorityPart);
201 
202   nsCString inReplyToPart;  // Not a member like the others...
203   UnescapeAndConvert(mimeConverter, escapedInReplyToPart, inReplyToPart);
204 
205   if (!inReplyToPart.IsEmpty()) {
206     // Ensure that References and In-Reply-To are consistent... The last
207     // reference will be used as In-Reply-To header.
208     if (m_referencePart.IsEmpty()) {
209       // If References is not set, set it to be the In-Reply-To.
210       m_referencePart = inReplyToPart;
211     } else {
212       // References is set. Add the In-Reply-To as last header unless it's
213       // set as last reference already.
214       int32_t lastRefStart = m_referencePart.RFindChar('<');
215       nsAutoCString lastReference;
216       if (lastRefStart != -1)
217         lastReference = StringTail(m_referencePart, lastRefStart);
218       else
219         lastReference = m_referencePart;
220 
221       if (lastReference != inReplyToPart) {
222         m_referencePart += " ";
223         m_referencePart += inReplyToPart;
224       }
225     }
226   }
227 
228   return NS_OK;
229 }
230 
SetSpecInternal(const nsACString & aSpec)231 nsresult nsMailtoUrl::SetSpecInternal(const nsACString& aSpec) {
232   nsresult rv = NS_MutateURI(NS_SIMPLEURIMUTATOR_CONTRACTID)
233                     .SetSpec(aSpec)
234                     .Finalize(m_baseURL);
235   NS_ENSURE_SUCCESS(rv, rv);
236   return ParseUrl();
237 }
238 
CleanupMailtoState()239 nsresult nsMailtoUrl::CleanupMailtoState() {
240   m_ccPart = "";
241   m_subjectPart = "";
242   m_newsgroupPart = "";
243   m_newsHostPart = "";
244   m_referencePart = "";
245   m_bodyPart = "";
246   m_bccPart = "";
247   m_followUpToPart = "";
248   m_fromPart = "";
249   m_htmlPart = "";
250   m_organizationPart = "";
251   m_replyToPart = "";
252   m_priorityPart = "";
253   return NS_OK;
254 }
255 
ParseUrl()256 nsresult nsMailtoUrl::ParseUrl() {
257   // we can get the path from the simple url.....
258   nsCString escapedPath;
259   m_baseURL->GetPathQueryRef(escapedPath);
260 
261   int32_t startOfSearchPart = escapedPath.FindChar('?');
262   if (startOfSearchPart >= 0) {
263     // now parse out the search field...
264     nsAutoCString searchPart(Substring(escapedPath, startOfSearchPart));
265 
266     if (!searchPart.IsEmpty()) {
267       // now we need to strip off the search part from the
268       // to part....
269       escapedPath.SetLength(startOfSearchPart);
270       MsgUnescapeString(escapedPath, 0, m_toPart);
271       ParseMailtoUrl(searchPart.BeginWriting());
272     }
273   } else if (!escapedPath.IsEmpty()) {
274     MsgUnescapeString(escapedPath, 0, m_toPart);
275   }
276 
277   return NS_OK;
278 }
279 
280 NS_IMETHODIMP
GetMessageContents(nsACString & aToPart,nsACString & aCcPart,nsACString & aBccPart,nsACString & aSubjectPart,nsACString & aBodyPart,nsACString & aHtmlPart,nsACString & aReferencePart,nsACString & aNewsgroupPart,MSG_ComposeFormat * aFormat)281 nsMailtoUrl::GetMessageContents(nsACString& aToPart, nsACString& aCcPart,
282                                 nsACString& aBccPart, nsACString& aSubjectPart,
283                                 nsACString& aBodyPart, nsACString& aHtmlPart,
284                                 nsACString& aReferencePart,
285                                 nsACString& aNewsgroupPart,
286                                 MSG_ComposeFormat* aFormat) {
287   NS_ENSURE_ARG_POINTER(aFormat);
288 
289   aToPart = m_toPart;
290   aCcPart = m_ccPart;
291   aBccPart = m_bccPart;
292   aSubjectPart = m_subjectPart;
293   aBodyPart = m_bodyPart;
294   aHtmlPart = m_htmlPart;
295   aReferencePart = m_referencePart;
296   aNewsgroupPart = m_newsgroupPart;
297   *aFormat = mFormat;
298   return NS_OK;
299 }
300 
301 NS_IMETHODIMP
GetFromPart(nsACString & aResult)302 nsMailtoUrl::GetFromPart(nsACString& aResult) {
303   aResult = m_fromPart;
304   return NS_OK;
305 }
306 
307 NS_IMETHODIMP
GetFollowUpToPart(nsACString & aResult)308 nsMailtoUrl::GetFollowUpToPart(nsACString& aResult) {
309   aResult = m_followUpToPart;
310   return NS_OK;
311 }
312 
313 NS_IMETHODIMP
GetOrganizationPart(nsACString & aResult)314 nsMailtoUrl::GetOrganizationPart(nsACString& aResult) {
315   aResult = m_organizationPart;
316   return NS_OK;
317 }
318 
319 NS_IMETHODIMP
GetReplyToPart(nsACString & aResult)320 nsMailtoUrl::GetReplyToPart(nsACString& aResult) {
321   aResult = m_replyToPart;
322   return NS_OK;
323 }
324 
325 NS_IMETHODIMP
GetPriorityPart(nsACString & aResult)326 nsMailtoUrl::GetPriorityPart(nsACString& aResult) {
327   aResult = m_priorityPart;
328   return NS_OK;
329 }
330 
331 NS_IMETHODIMP
GetNewsHostPart(nsACString & aResult)332 nsMailtoUrl::GetNewsHostPart(nsACString& aResult) {
333   aResult = m_newsHostPart;
334   return NS_OK;
335 }
336 
337 //////////////////////////////////////////////////////////////////////////////
338 // Begin nsIURI support
339 //////////////////////////////////////////////////////////////////////////////
340 
GetSpec(nsACString & aSpec)341 NS_IMETHODIMP nsMailtoUrl::GetSpec(nsACString& aSpec) {
342   return m_baseURL->GetSpec(aSpec);
343 }
344 
GetPrePath(nsACString & aPrePath)345 NS_IMETHODIMP nsMailtoUrl::GetPrePath(nsACString& aPrePath) {
346   return m_baseURL->GetPrePath(aPrePath);
347 }
348 
GetScheme(nsACString & aScheme)349 NS_IMETHODIMP nsMailtoUrl::GetScheme(nsACString& aScheme) {
350   return m_baseURL->GetScheme(aScheme);
351 }
352 
SetScheme(const nsACString & aScheme)353 nsresult nsMailtoUrl::SetScheme(const nsACString& aScheme) {
354   nsresult rv = NS_MutateURI(m_baseURL).SetScheme(aScheme).Finalize(m_baseURL);
355   NS_ENSURE_SUCCESS(rv, rv);
356   return ParseUrl();
357 }
358 
GetUserPass(nsACString & aUserPass)359 NS_IMETHODIMP nsMailtoUrl::GetUserPass(nsACString& aUserPass) {
360   return m_baseURL->GetUserPass(aUserPass);
361 }
362 
SetUserPass(const nsACString & aUserPass)363 nsresult nsMailtoUrl::SetUserPass(const nsACString& aUserPass) {
364   nsresult rv =
365       NS_MutateURI(m_baseURL).SetUserPass(aUserPass).Finalize(m_baseURL);
366   NS_ENSURE_SUCCESS(rv, rv);
367   return ParseUrl();
368 }
369 
GetUsername(nsACString & aUsername)370 NS_IMETHODIMP nsMailtoUrl::GetUsername(nsACString& aUsername) {
371   return m_baseURL->GetUsername(aUsername);
372 }
373 
SetUsername(const nsACString & aUsername)374 nsresult nsMailtoUrl::SetUsername(const nsACString& aUsername) {
375   nsresult rv =
376       NS_MutateURI(m_baseURL).SetUsername(aUsername).Finalize(m_baseURL);
377   NS_ENSURE_SUCCESS(rv, rv);
378   return ParseUrl();
379 }
380 
GetPassword(nsACString & aPassword)381 NS_IMETHODIMP nsMailtoUrl::GetPassword(nsACString& aPassword) {
382   return m_baseURL->GetPassword(aPassword);
383 }
384 
SetPassword(const nsACString & aPassword)385 nsresult nsMailtoUrl::SetPassword(const nsACString& aPassword) {
386   nsresult rv =
387       NS_MutateURI(m_baseURL).SetPassword(aPassword).Finalize(m_baseURL);
388   NS_ENSURE_SUCCESS(rv, rv);
389   return ParseUrl();
390 }
391 
GetHostPort(nsACString & aHostPort)392 NS_IMETHODIMP nsMailtoUrl::GetHostPort(nsACString& aHostPort) {
393   return m_baseURL->GetHost(aHostPort);
394 }
395 
SetHostPort(const nsACString & aHostPort)396 nsresult nsMailtoUrl::SetHostPort(const nsACString& aHostPort) {
397   nsresult rv =
398       NS_MutateURI(m_baseURL).SetHostPort(aHostPort).Finalize(m_baseURL);
399   NS_ENSURE_SUCCESS(rv, rv);
400   return ParseUrl();
401 }
402 
GetHost(nsACString & aHost)403 NS_IMETHODIMP nsMailtoUrl::GetHost(nsACString& aHost) {
404   return m_baseURL->GetHost(aHost);
405 }
406 
SetHost(const nsACString & aHost)407 nsresult nsMailtoUrl::SetHost(const nsACString& aHost) {
408   nsresult rv = NS_MutateURI(m_baseURL).SetHost(aHost).Finalize(m_baseURL);
409   NS_ENSURE_SUCCESS(rv, rv);
410   return ParseUrl();
411 }
412 
GetPort(int32_t * aPort)413 NS_IMETHODIMP nsMailtoUrl::GetPort(int32_t* aPort) {
414   return m_baseURL->GetPort(aPort);
415 }
416 
SetPort(int32_t aPort)417 nsresult nsMailtoUrl::SetPort(int32_t aPort) {
418   nsresult rv = NS_MutateURI(m_baseURL).SetPort(aPort).Finalize(m_baseURL);
419   NS_ENSURE_SUCCESS(rv, rv);
420   return ParseUrl();
421 }
422 
GetPathQueryRef(nsACString & aPath)423 NS_IMETHODIMP nsMailtoUrl::GetPathQueryRef(nsACString& aPath) {
424   return m_baseURL->GetPathQueryRef(aPath);
425 }
426 
SetPathQueryRef(const nsACString & aPath)427 nsresult nsMailtoUrl::SetPathQueryRef(const nsACString& aPath) {
428   nsresult rv =
429       NS_MutateURI(m_baseURL).SetPathQueryRef(aPath).Finalize(m_baseURL);
430   NS_ENSURE_SUCCESS(rv, rv);
431   return ParseUrl();
432 }
433 
GetAsciiHost(nsACString & aHostA)434 NS_IMETHODIMP nsMailtoUrl::GetAsciiHost(nsACString& aHostA) {
435   return m_baseURL->GetAsciiHost(aHostA);
436 }
437 
GetAsciiHostPort(nsACString & aHostPortA)438 NS_IMETHODIMP nsMailtoUrl::GetAsciiHostPort(nsACString& aHostPortA) {
439   return m_baseURL->GetAsciiHostPort(aHostPortA);
440 }
441 
GetAsciiSpec(nsACString & aSpecA)442 NS_IMETHODIMP nsMailtoUrl::GetAsciiSpec(nsACString& aSpecA) {
443   return m_baseURL->GetAsciiSpec(aSpecA);
444 }
445 
SchemeIs(const char * aScheme,bool * _retval)446 NS_IMETHODIMP nsMailtoUrl::SchemeIs(const char* aScheme, bool* _retval) {
447   return m_baseURL->SchemeIs(aScheme, _retval);
448 }
449 
Equals(nsIURI * other,bool * _retval)450 NS_IMETHODIMP nsMailtoUrl::Equals(nsIURI* other, bool* _retval) {
451   // The passed-in URI might be an nsMailtoUrl. Pass our inner URL to its
452   // Equals method. The other nsMailtoUrl will then pass its inner URL to
453   // to the Equals method of our inner URL. Other URIs will return false.
454   if (other) return other->Equals(m_baseURL, _retval);
455 
456   return m_baseURL->Equals(other, _retval);
457 }
458 
Clone(nsIURI ** _retval)459 nsresult nsMailtoUrl::Clone(nsIURI** _retval) {
460   NS_ENSURE_ARG_POINTER(_retval);
461 
462   RefPtr<nsMailtoUrl> clone = new nsMailtoUrl();
463 
464   NS_ENSURE_TRUE(clone, NS_ERROR_OUT_OF_MEMORY);
465 
466   nsresult rv = NS_MutateURI(m_baseURL).Finalize(clone->m_baseURL);
467   NS_ENSURE_SUCCESS(rv, rv);
468   clone->ParseUrl();
469   clone.forget(_retval);
470   return NS_OK;
471 }
472 
Resolve(const nsACString & relativePath,nsACString & result)473 NS_IMETHODIMP nsMailtoUrl::Resolve(const nsACString& relativePath,
474                                    nsACString& result) {
475   return m_baseURL->Resolve(relativePath, result);
476 }
477 
SetRef(const nsACString & aRef)478 nsresult nsMailtoUrl::SetRef(const nsACString& aRef) {
479   return NS_MutateURI(m_baseURL).SetRef(aRef).Finalize(m_baseURL);
480 }
481 
482 NS_IMETHODIMP
GetRef(nsACString & result)483 nsMailtoUrl::GetRef(nsACString& result) { return m_baseURL->GetRef(result); }
484 
EqualsExceptRef(nsIURI * other,bool * result)485 NS_IMETHODIMP nsMailtoUrl::EqualsExceptRef(nsIURI* other, bool* result) {
486   // The passed-in URI might be an nsMailtoUrl. Pass our inner URL to its
487   // Equals method. The other nsMailtoUrl will then pass its inner URL to
488   // to the Equals method of our inner URL. Other URIs will return false.
489   if (other) return other->EqualsExceptRef(m_baseURL, result);
490 
491   return m_baseURL->EqualsExceptRef(other, result);
492 }
493 
494 NS_IMETHODIMP
GetSpecIgnoringRef(nsACString & result)495 nsMailtoUrl::GetSpecIgnoringRef(nsACString& result) {
496   return m_baseURL->GetSpecIgnoringRef(result);
497 }
498 
499 NS_IMETHODIMP
GetDisplaySpec(nsACString & aUnicodeSpec)500 nsMailtoUrl::GetDisplaySpec(nsACString& aUnicodeSpec) {
501   return GetSpec(aUnicodeSpec);
502 }
503 
504 NS_IMETHODIMP
GetDisplayHostPort(nsACString & aUnicodeHostPort)505 nsMailtoUrl::GetDisplayHostPort(nsACString& aUnicodeHostPort) {
506   return GetHostPort(aUnicodeHostPort);
507 }
508 
509 NS_IMETHODIMP
GetDisplayHost(nsACString & aUnicodeHost)510 nsMailtoUrl::GetDisplayHost(nsACString& aUnicodeHost) {
511   return GetHost(aUnicodeHost);
512 }
513 
514 NS_IMETHODIMP
GetDisplayPrePath(nsACString & aPrePath)515 nsMailtoUrl::GetDisplayPrePath(nsACString& aPrePath) {
516   return GetPrePath(aPrePath);
517 }
518 
519 NS_IMETHODIMP
GetHasRef(bool * result)520 nsMailtoUrl::GetHasRef(bool* result) { return m_baseURL->GetHasRef(result); }
521 
522 NS_IMETHODIMP
GetFilePath(nsACString & aFilePath)523 nsMailtoUrl::GetFilePath(nsACString& aFilePath) {
524   return m_baseURL->GetFilePath(aFilePath);
525 }
526 
SetFilePath(const nsACString & aFilePath)527 nsresult nsMailtoUrl::SetFilePath(const nsACString& aFilePath) {
528   return NS_MutateURI(m_baseURL).SetFilePath(aFilePath).Finalize(m_baseURL);
529 }
530 
531 NS_IMETHODIMP
GetQuery(nsACString & aQuery)532 nsMailtoUrl::GetQuery(nsACString& aQuery) {
533   return m_baseURL->GetQuery(aQuery);
534 }
535 
SetQuery(const nsACString & aQuery)536 nsresult nsMailtoUrl::SetQuery(const nsACString& aQuery) {
537   return NS_MutateURI(m_baseURL).SetQuery(aQuery).Finalize(m_baseURL);
538 }
539 
SetQueryWithEncoding(const nsACString & aQuery,const mozilla::Encoding * aEncoding)540 nsresult nsMailtoUrl::SetQueryWithEncoding(const nsACString& aQuery,
541                                            const mozilla::Encoding* aEncoding) {
542   return NS_MutateURI(m_baseURL)
543       .SetQueryWithEncoding(aQuery, aEncoding)
544       .Finalize(m_baseURL);
545 }
546 
NS_IMETHODIMP_(void)547 NS_IMETHODIMP_(void)
548 nsMailtoUrl::Serialize(mozilla::ipc::URIParams& aParams) {
549   m_baseURL->Serialize(aParams);
550 }
551 
NS_IMPL_ISUPPORTS(nsMailtoUrl::Mutator,nsIURISetters,nsIURIMutator)552 NS_IMPL_ISUPPORTS(nsMailtoUrl::Mutator, nsIURISetters, nsIURIMutator)
553 
554 NS_IMETHODIMP
555 nsMailtoUrl::Mutate(nsIURIMutator** aMutator) {
556   RefPtr<nsMailtoUrl::Mutator> mutator = new nsMailtoUrl::Mutator();
557   nsresult rv = mutator->InitFromURI(this);
558   if (NS_FAILED(rv)) {
559     return rv;
560   }
561   mutator.forget(aMutator);
562   return NS_OK;
563 }
564 
565 /////////////////////////////////////////////////////////////////////////////////////
566 // smtp url definition
567 /////////////////////////////////////////////////////////////////////////////////////
568 
nsSmtpUrl()569 nsSmtpUrl::nsSmtpUrl() : nsMsgMailNewsUrl() {
570   // nsISmtpUrl specific state...
571 
572   m_isPostMessage = true;
573   m_requestDSN = false;
574   m_verifyLogon = false;
575 }
576 
~nsSmtpUrl()577 nsSmtpUrl::~nsSmtpUrl() {}
578 
NS_IMPL_ISUPPORTS_INHERITED(nsSmtpUrl,nsMsgMailNewsUrl,nsISmtpUrl)579 NS_IMPL_ISUPPORTS_INHERITED(nsSmtpUrl, nsMsgMailNewsUrl, nsISmtpUrl)
580 
581 ////////////////////////////////////////////////////////////////////////////////////
582 // Begin nsISmtpUrl specific support
583 
584 ////////////////////////////////////////////////////////////////////////////////////
585 
586 NS_IMETHODIMP
587 nsSmtpUrl::SetRecipients(const char* aRecipientsList) {
588   NS_ENSURE_ARG(aRecipientsList);
589   MsgUnescapeString(nsDependentCString(aRecipientsList), 0, m_toPart);
590   return NS_OK;
591 }
592 
593 NS_IMETHODIMP
GetRecipients(char ** aRecipientsList)594 nsSmtpUrl::GetRecipients(char** aRecipientsList) {
595   NS_ENSURE_ARG_POINTER(aRecipientsList);
596   if (aRecipientsList) *aRecipientsList = ToNewCString(m_toPart);
597   return NS_OK;
598 }
599 
600 NS_IMETHODIMP
SetSender(const char * aSender)601 nsSmtpUrl::SetSender(const char* aSender) {
602   NS_ENSURE_ARG(aSender);
603   MsgUnescapeString(nsDependentCString(aSender), 0, m_fromPart);
604   return NS_OK;
605 }
606 
607 NS_IMETHODIMP
GetSender(char ** aSender)608 nsSmtpUrl::GetSender(char** aSender) {
609   NS_ENSURE_ARG_POINTER(aSender);
610   if (aSender) *aSender = ToNewCString(m_fromPart);
611   return NS_OK;
612 }
613 
NS_IMPL_GETSET(nsSmtpUrl,PostMessage,bool,m_isPostMessage)614 NS_IMPL_GETSET(nsSmtpUrl, PostMessage, bool, m_isPostMessage)
615 
616 NS_IMPL_GETSET(nsSmtpUrl, VerifyLogon, bool, m_verifyLogon)
617 
618 // the message can be stored in a file....allow accessors for getting and
619 // setting the file name to post...
620 NS_IMETHODIMP nsSmtpUrl::SetPostMessageFile(nsIFile* aFile) {
621   NS_ENSURE_ARG_POINTER(aFile);
622   m_fileName = aFile;
623   return NS_OK;
624 }
625 
GetPostMessageFile(nsIFile ** aFile)626 NS_IMETHODIMP nsSmtpUrl::GetPostMessageFile(nsIFile** aFile) {
627   NS_ENSURE_ARG_POINTER(aFile);
628   if (m_fileName) {
629     // Clone the file so nsLocalFile stat caching doesn't make the caller get
630     // the wrong file size.
631     m_fileName->Clone(aFile);
632     return *aFile ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
633   }
634   return NS_ERROR_NULL_POINTER;
635 }
636 
NS_IMPL_GETSET(nsSmtpUrl,RequestDSN,bool,m_requestDSN)637 NS_IMPL_GETSET(nsSmtpUrl, RequestDSN, bool, m_requestDSN)
638 
639 NS_IMETHODIMP
640 nsSmtpUrl::SetDsnEnvid(const nsACString& aDsnEnvid) {
641   m_dsnEnvid = aDsnEnvid;
642   return NS_OK;
643 }
644 
645 NS_IMETHODIMP
GetDsnEnvid(nsACString & aDsnEnvid)646 nsSmtpUrl::GetDsnEnvid(nsACString& aDsnEnvid) {
647   aDsnEnvid = m_dsnEnvid;
648   return NS_OK;
649 }
650 
651 NS_IMETHODIMP
GetSenderIdentity(nsIMsgIdentity ** aSenderIdentity)652 nsSmtpUrl::GetSenderIdentity(nsIMsgIdentity** aSenderIdentity) {
653   NS_ENSURE_ARG_POINTER(aSenderIdentity);
654   NS_ADDREF(*aSenderIdentity = m_senderIdentity);
655   return NS_OK;
656 }
657 
658 NS_IMETHODIMP
SetSenderIdentity(nsIMsgIdentity * aSenderIdentity)659 nsSmtpUrl::SetSenderIdentity(nsIMsgIdentity* aSenderIdentity) {
660   NS_ENSURE_ARG_POINTER(aSenderIdentity);
661   m_senderIdentity = aSenderIdentity;
662   return NS_OK;
663 }
664 
665 NS_IMETHODIMP
SetPrompt(nsIPrompt * aNetPrompt)666 nsSmtpUrl::SetPrompt(nsIPrompt* aNetPrompt) {
667   NS_ENSURE_ARG_POINTER(aNetPrompt);
668   m_netPrompt = aNetPrompt;
669   return NS_OK;
670 }
671 
672 NS_IMETHODIMP
GetPrompt(nsIPrompt ** aNetPrompt)673 nsSmtpUrl::GetPrompt(nsIPrompt** aNetPrompt) {
674   NS_ENSURE_ARG_POINTER(aNetPrompt);
675   NS_ENSURE_TRUE(m_netPrompt, NS_ERROR_NULL_POINTER);
676   NS_ADDREF(*aNetPrompt = m_netPrompt);
677   return NS_OK;
678 }
679 
680 NS_IMETHODIMP
SetAuthPrompt(nsIAuthPrompt * aNetAuthPrompt)681 nsSmtpUrl::SetAuthPrompt(nsIAuthPrompt* aNetAuthPrompt) {
682   NS_ENSURE_ARG_POINTER(aNetAuthPrompt);
683   m_netAuthPrompt = aNetAuthPrompt;
684   return NS_OK;
685 }
686 
687 NS_IMETHODIMP
GetAuthPrompt(nsIAuthPrompt ** aNetAuthPrompt)688 nsSmtpUrl::GetAuthPrompt(nsIAuthPrompt** aNetAuthPrompt) {
689   NS_ENSURE_ARG_POINTER(aNetAuthPrompt);
690   NS_ENSURE_TRUE(m_netAuthPrompt, NS_ERROR_NULL_POINTER);
691   NS_ADDREF(*aNetAuthPrompt = m_netAuthPrompt);
692   return NS_OK;
693 }
694 
695 NS_IMETHODIMP
SetNotificationCallbacks(nsIInterfaceRequestor * aCallbacks)696 nsSmtpUrl::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks) {
697   NS_ENSURE_ARG_POINTER(aCallbacks);
698   m_callbacks = aCallbacks;
699   return NS_OK;
700 }
701 
702 NS_IMETHODIMP
GetNotificationCallbacks(nsIInterfaceRequestor ** aCallbacks)703 nsSmtpUrl::GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks) {
704   NS_ENSURE_ARG_POINTER(aCallbacks);
705   NS_ENSURE_TRUE(m_callbacks, NS_ERROR_NULL_POINTER);
706   NS_ADDREF(*aCallbacks = m_callbacks);
707   return NS_OK;
708 }
709 
710 NS_IMETHODIMP
SetSmtpServer(nsISmtpServer * aSmtpServer)711 nsSmtpUrl::SetSmtpServer(nsISmtpServer* aSmtpServer) {
712   NS_ENSURE_ARG_POINTER(aSmtpServer);
713   m_smtpServer = aSmtpServer;
714   return NS_OK;
715 }
716 
717 NS_IMETHODIMP
GetSmtpServer(nsISmtpServer ** aSmtpServer)718 nsSmtpUrl::GetSmtpServer(nsISmtpServer** aSmtpServer) {
719   NS_ENSURE_ARG_POINTER(aSmtpServer);
720   NS_ENSURE_TRUE(m_smtpServer, NS_ERROR_NULL_POINTER);
721   NS_ADDREF(*aSmtpServer = m_smtpServer);
722   return NS_OK;
723 }
724