mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-20 15:27:32 +09:00
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
This commit is contained in:
parent
23e0d82436
commit
e400f4130a
1564 changed files with 510348 additions and 0 deletions
55
mailnews/compose/src/moz.build
Normal file
55
mailnews/compose/src/moz.build
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
EXPORTS += [
|
||||
'nsComposeStrings.h',
|
||||
'nsMsgAttachmentHandler.h',
|
||||
'nsMsgCompFields.h',
|
||||
'nsMsgCompose.h',
|
||||
'nsMsgSend.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'nsComposeStrings.cpp',
|
||||
'nsMsgAttachment.cpp',
|
||||
'nsMsgAttachmentHandler.cpp',
|
||||
'nsMsgCompFields.cpp',
|
||||
'nsMsgCompose.cpp',
|
||||
'nsMsgComposeContentHandler.cpp',
|
||||
'nsMsgComposeParams.cpp',
|
||||
'nsMsgComposeProgressParams.cpp',
|
||||
'nsMsgComposeService.cpp',
|
||||
'nsMsgCompUtils.cpp',
|
||||
'nsMsgCopy.cpp',
|
||||
'nsMsgPrompts.cpp',
|
||||
'nsMsgQuote.cpp',
|
||||
'nsMsgSend.cpp',
|
||||
'nsMsgSendLater.cpp',
|
||||
'nsMsgSendPart.cpp',
|
||||
'nsMsgSendReport.cpp',
|
||||
'nsSmtpProtocol.cpp',
|
||||
'nsSmtpServer.cpp',
|
||||
'nsSmtpService.cpp',
|
||||
'nsSmtpUrl.cpp',
|
||||
'nsURLFetcher.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
SOURCES += [
|
||||
'nsMsgAppleDoubleEncode.cpp',
|
||||
'nsMsgAppleEncode.cpp',
|
||||
]
|
||||
EXPORTS += [
|
||||
'nsMsgAppleCodes.h',
|
||||
'nsMsgAppleDouble.h',
|
||||
]
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'nsSMTPProtocolHandler.js',
|
||||
'nsSMTPProtocolHandler.manifest',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'mail'
|
||||
|
||||
116
mailnews/compose/src/nsComposeStrings.cpp
Normal file
116
mailnews/compose/src/nsComposeStrings.cpp
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/* 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/. */
|
||||
|
||||
#include "nsComposeStrings.h"
|
||||
|
||||
const char16_t* errorStringNameForErrorCode(nsresult aCode)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
// Temporary workaroung until bug 783526 is fixed.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wswitch"
|
||||
#endif
|
||||
switch(aCode)
|
||||
{
|
||||
case NS_MSG_UNABLE_TO_OPEN_FILE:
|
||||
return u"unableToOpenFile";
|
||||
case NS_MSG_UNABLE_TO_OPEN_TMP_FILE:
|
||||
return u"unableToOpenTmpFile";
|
||||
case NS_MSG_UNABLE_TO_SAVE_TEMPLATE:
|
||||
return u"unableToSaveTemplate";
|
||||
case NS_MSG_UNABLE_TO_SAVE_DRAFT:
|
||||
return u"unableToSaveDraft";
|
||||
case NS_MSG_COULDNT_OPEN_FCC_FOLDER:
|
||||
return u"couldntOpenFccFolder";
|
||||
case NS_MSG_NO_SENDER:
|
||||
return u"noSender";
|
||||
case NS_MSG_NO_RECIPIENTS:
|
||||
return u"noRecipients";
|
||||
case NS_MSG_ERROR_WRITING_FILE:
|
||||
return u"errorWritingFile";
|
||||
case NS_ERROR_SENDING_FROM_COMMAND:
|
||||
return u"errorSendingFromCommand";
|
||||
case NS_ERROR_SENDING_DATA_COMMAND:
|
||||
return u"errorSendingDataCommand";
|
||||
case NS_ERROR_SENDING_MESSAGE:
|
||||
return u"errorSendingMessage";
|
||||
case NS_ERROR_POST_FAILED:
|
||||
return u"postFailed";
|
||||
case NS_ERROR_QUEUED_DELIVERY_FAILED:
|
||||
return u"errorQueuedDeliveryFailed";
|
||||
case NS_ERROR_SEND_FAILED:
|
||||
return u"sendFailed";
|
||||
case NS_ERROR_SMTP_SERVER_ERROR:
|
||||
return u"smtpServerError";
|
||||
case NS_MSG_UNABLE_TO_SEND_LATER:
|
||||
return u"unableToSendLater";
|
||||
case NS_ERROR_COMMUNICATIONS_ERROR:
|
||||
return u"communicationsError";
|
||||
case NS_ERROR_BUT_DONT_SHOW_ALERT:
|
||||
return u"dontShowAlert";
|
||||
case NS_ERROR_TCP_READ_ERROR:
|
||||
return u"tcpReadError";
|
||||
case NS_ERROR_COULD_NOT_GET_USERS_MAIL_ADDRESS:
|
||||
return u"couldNotGetUsersMailAddress";
|
||||
case NS_ERROR_MIME_MPART_ATTACHMENT_ERROR:
|
||||
return u"mimeMpartAttachmentError";
|
||||
case NS_MSG_FAILED_COPY_OPERATION:
|
||||
return u"failedCopyOperation";
|
||||
case NS_ERROR_NNTP_NO_CROSS_POSTING:
|
||||
return u"nntpNoCrossPosting";
|
||||
case NS_MSG_CANCELLING:
|
||||
return u"msgCancelling";
|
||||
case NS_ERROR_SEND_FAILED_BUT_NNTP_OK:
|
||||
return u"sendFailedButNntpOk";
|
||||
case NS_MSG_ERROR_READING_FILE:
|
||||
return u"errorReadingFile";
|
||||
case NS_MSG_ERROR_ATTACHING_FILE:
|
||||
return u"errorAttachingFile";
|
||||
case NS_ERROR_SMTP_GREETING:
|
||||
return u"incorrectSmtpGreeting";
|
||||
case NS_ERROR_SENDING_RCPT_COMMAND:
|
||||
return u"errorSendingRcptCommand";
|
||||
case NS_ERROR_STARTTLS_FAILED_EHLO_STARTTLS:
|
||||
return u"startTlsFailed";
|
||||
case NS_ERROR_SMTP_PASSWORD_UNDEFINED:
|
||||
return u"smtpPasswordUndefined";
|
||||
case NS_ERROR_SMTP_TEMP_SIZE_EXCEEDED:
|
||||
return u"smtpTempSizeExceeded";
|
||||
case NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_1:
|
||||
return u"smtpPermSizeExceeded1";
|
||||
case NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_2:
|
||||
return u"smtpPermSizeExceeded2";
|
||||
case NS_ERROR_SMTP_SEND_FAILED_UNKNOWN_SERVER:
|
||||
return u"smtpSendFailedUnknownServer";
|
||||
case NS_ERROR_SMTP_SEND_FAILED_REFUSED:
|
||||
return u"smtpSendRequestRefused";
|
||||
case NS_ERROR_SMTP_SEND_FAILED_INTERRUPTED:
|
||||
return u"smtpSendInterrupted";
|
||||
case NS_ERROR_SMTP_SEND_FAILED_TIMEOUT:
|
||||
return u"smtpSendTimeout";
|
||||
case NS_ERROR_SMTP_SEND_FAILED_UNKNOWN_REASON:
|
||||
return u"smtpSendFailedUnknownReason";
|
||||
case NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL:
|
||||
return u"smtpHintAuthEncryptToPlainNoSsl";
|
||||
case NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL:
|
||||
return u"smtpHintAuthEncryptToPlainSsl";
|
||||
case NS_ERROR_SMTP_AUTH_CHANGE_PLAIN_TO_ENCRYPT:
|
||||
return u"smtpHintAuthPlainToEncrypt";
|
||||
case NS_ERROR_SMTP_AUTH_FAILURE:
|
||||
return u"smtpAuthFailure";
|
||||
case NS_ERROR_SMTP_AUTH_GSSAPI:
|
||||
return u"smtpAuthGssapi";
|
||||
case NS_ERROR_SMTP_AUTH_MECH_NOT_SUPPORTED:
|
||||
return u"smtpAuthMechNotSupported";
|
||||
case NS_ERROR_SMTP_AUTH_NOT_SUPPORTED:
|
||||
return u"smtpAuthenticationNotSupported";
|
||||
case NS_ERROR_ILLEGAL_LOCALPART:
|
||||
return u"illegalLocalPart";
|
||||
default:
|
||||
return u"sendFailed";
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
77
mailnews/compose/src/nsComposeStrings.h
Normal file
77
mailnews/compose/src/nsComposeStrings.h
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/* 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/. */
|
||||
|
||||
/**
|
||||
String Ids used by mailnews\compose
|
||||
To Do: Convert the callers to use names instead of ids and then make this file obsolete.
|
||||
*/
|
||||
|
||||
#ifndef _nsComposeStrings_H__
|
||||
#define _nsComposeStrings_H__
|
||||
|
||||
#include "msgCore.h"
|
||||
|
||||
#define NS_MSG_UNABLE_TO_OPEN_FILE NS_MSG_GENERATE_FAILURE(12500)
|
||||
#define NS_MSG_UNABLE_TO_OPEN_TMP_FILE NS_MSG_GENERATE_FAILURE(12501)
|
||||
#define NS_MSG_UNABLE_TO_SAVE_TEMPLATE NS_MSG_GENERATE_FAILURE(12502)
|
||||
#define NS_MSG_UNABLE_TO_SAVE_DRAFT NS_MSG_GENERATE_FAILURE(12503)
|
||||
#define NS_MSG_COULDNT_OPEN_FCC_FOLDER NS_MSG_GENERATE_FAILURE(12506)
|
||||
#define NS_MSG_NO_SENDER NS_MSG_GENERATE_FAILURE(12510)
|
||||
#define NS_MSG_NO_RECIPIENTS NS_MSG_GENERATE_FAILURE(12511)
|
||||
#define NS_MSG_ERROR_WRITING_FILE NS_MSG_GENERATE_FAILURE(12512)
|
||||
#define NS_ERROR_SENDING_FROM_COMMAND NS_MSG_GENERATE_FAILURE(12514)
|
||||
#define NS_ERROR_SENDING_DATA_COMMAND NS_MSG_GENERATE_FAILURE(12516)
|
||||
#define NS_ERROR_SENDING_MESSAGE NS_MSG_GENERATE_FAILURE(12517)
|
||||
#define NS_ERROR_POST_FAILED NS_MSG_GENERATE_FAILURE(12518)
|
||||
#define NS_ERROR_QUEUED_DELIVERY_FAILED NS_MSG_GENERATE_FAILURE(12519)
|
||||
#define NS_ERROR_SEND_FAILED NS_MSG_GENERATE_FAILURE(12520)
|
||||
#define NS_ERROR_SMTP_SERVER_ERROR NS_MSG_GENERATE_FAILURE(12524)
|
||||
#define NS_MSG_UNABLE_TO_SEND_LATER NS_MSG_GENERATE_FAILURE(12525)
|
||||
#define NS_ERROR_COMMUNICATIONS_ERROR NS_MSG_GENERATE_FAILURE(12526)
|
||||
#define NS_ERROR_BUT_DONT_SHOW_ALERT NS_MSG_GENERATE_FAILURE(12527)
|
||||
#define NS_ERROR_TCP_READ_ERROR NS_MSG_GENERATE_FAILURE(12528)
|
||||
#define NS_ERROR_COULD_NOT_GET_USERS_MAIL_ADDRESS NS_MSG_GENERATE_FAILURE(12529)
|
||||
#define NS_ERROR_MIME_MPART_ATTACHMENT_ERROR NS_MSG_GENERATE_FAILURE(12531)
|
||||
#define NS_MSG_FAILED_COPY_OPERATION NS_MSG_GENERATE_FAILURE(12532)
|
||||
|
||||
/* 12554 is taken by NS_ERROR_NNTP_NO_CROSS_POSTING. use 12555 as the next one */
|
||||
|
||||
#define NS_MSG_CANCELLING NS_MSG_GENERATE_SUCCESS(12555)
|
||||
|
||||
// For message sending report
|
||||
#define NS_ERROR_SEND_FAILED_BUT_NNTP_OK NS_MSG_GENERATE_FAILURE(12560)
|
||||
#define NS_MSG_ERROR_READING_FILE NS_MSG_GENERATE_FAILURE(12563)
|
||||
|
||||
#define NS_MSG_ERROR_ATTACHING_FILE NS_MSG_GENERATE_FAILURE(12570)
|
||||
|
||||
#define NS_ERROR_SMTP_GREETING NS_MSG_GENERATE_FAILURE(12572)
|
||||
|
||||
#define NS_ERROR_SENDING_RCPT_COMMAND NS_MSG_GENERATE_FAILURE(12575)
|
||||
|
||||
#define NS_ERROR_STARTTLS_FAILED_EHLO_STARTTLS NS_MSG_GENERATE_FAILURE(12582)
|
||||
|
||||
#define NS_ERROR_SMTP_PASSWORD_UNDEFINED NS_MSG_GENERATE_FAILURE(12584)
|
||||
#define NS_ERROR_SMTP_TEMP_SIZE_EXCEEDED NS_MSG_GENERATE_FAILURE(12586)
|
||||
#define NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_1 NS_MSG_GENERATE_FAILURE(12587)
|
||||
#define NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_2 NS_MSG_GENERATE_FAILURE(12588)
|
||||
|
||||
#define NS_ERROR_SMTP_SEND_FAILED_UNKNOWN_SERVER NS_MSG_GENERATE_FAILURE(12589)
|
||||
#define NS_ERROR_SMTP_SEND_FAILED_REFUSED NS_MSG_GENERATE_FAILURE(12590)
|
||||
#define NS_ERROR_SMTP_SEND_FAILED_INTERRUPTED NS_MSG_GENERATE_FAILURE(12591)
|
||||
#define NS_ERROR_SMTP_SEND_FAILED_TIMEOUT NS_MSG_GENERATE_FAILURE(12592)
|
||||
#define NS_ERROR_SMTP_SEND_FAILED_UNKNOWN_REASON NS_MSG_GENERATE_FAILURE(12593)
|
||||
|
||||
#define NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL NS_MSG_GENERATE_FAILURE(12594)
|
||||
#define NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL NS_MSG_GENERATE_FAILURE(12595)
|
||||
#define NS_ERROR_SMTP_AUTH_CHANGE_PLAIN_TO_ENCRYPT NS_MSG_GENERATE_FAILURE(12596)
|
||||
#define NS_ERROR_SMTP_AUTH_FAILURE NS_MSG_GENERATE_FAILURE(12597)
|
||||
#define NS_ERROR_SMTP_AUTH_GSSAPI NS_MSG_GENERATE_FAILURE(12598)
|
||||
#define NS_ERROR_SMTP_AUTH_MECH_NOT_SUPPORTED NS_MSG_GENERATE_FAILURE(12599)
|
||||
#define NS_ERROR_SMTP_AUTH_NOT_SUPPORTED NS_MSG_GENERATE_FAILURE(12600)
|
||||
|
||||
#define NS_ERROR_ILLEGAL_LOCALPART NS_MSG_GENERATE_FAILURE(12601)
|
||||
|
||||
const char16_t* errorStringNameForErrorCode(nsresult aCode);
|
||||
|
||||
#endif /* _nsComposeStrings_H__ */
|
||||
106
mailnews/compose/src/nsMsgAppleCodes.h
Normal file
106
mailnews/compose/src/nsMsgAppleCodes.h
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/* -*- Mode: C; tab-width: 4; 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/. */
|
||||
|
||||
/*
|
||||
** AD_Codes.h
|
||||
**
|
||||
** ---------------
|
||||
**
|
||||
** Head file for Apple Decode/Encode essential codes.
|
||||
**
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef ad_codes_h
|
||||
#define ad_codes_h
|
||||
|
||||
/*
|
||||
** applefile definitions used
|
||||
*/
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=mac68k
|
||||
#endif
|
||||
|
||||
#define APPLESINGLE_MAGIC 0x00051600L
|
||||
#define APPLEDOUBLE_MAGIC 0x00051607L
|
||||
#define VERSION 0x00020000
|
||||
|
||||
#define NUM_ENTRIES 6
|
||||
|
||||
#define ENT_DFORK 1L
|
||||
#define ENT_RFORK 2L
|
||||
#define ENT_NAME 3L
|
||||
#define ENT_COMMENT 4L
|
||||
#define ENT_DATES 8L
|
||||
#define ENT_FINFO 9L
|
||||
#define CONVERT_TIME 1265437696L
|
||||
|
||||
/*
|
||||
** data type used in the encoder/decoder.
|
||||
*/
|
||||
typedef struct ap_header
|
||||
{
|
||||
int32_t magic;
|
||||
int32_t version;
|
||||
char fill[16];
|
||||
int16_t entries;
|
||||
|
||||
} ap_header;
|
||||
|
||||
typedef struct ap_entry
|
||||
{
|
||||
int32_t id;
|
||||
int32_t offset;
|
||||
int32_t length;
|
||||
|
||||
} ap_entry;
|
||||
|
||||
typedef struct ap_dates
|
||||
{
|
||||
int32_t create, modify, backup, access;
|
||||
|
||||
} ap_dates;
|
||||
|
||||
typedef struct myFInfo /* the mac FInfo structure for the cross platform. */
|
||||
{
|
||||
int32_t fdType, fdCreator;
|
||||
int16_t fdFlags;
|
||||
int32_t fdLocation; /* it really should be a pointer, but just a place-holder */
|
||||
int16_t fdFldr;
|
||||
|
||||
} myFInfo;
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
/*
|
||||
** string utils.
|
||||
*/
|
||||
int write_stream(appledouble_encode_object *p_ap_encode_obj, const char *s,int len);
|
||||
|
||||
int fill_apple_mime_header(appledouble_encode_object *p_ap_encode_obj);
|
||||
int ap_encode_file_infor(appledouble_encode_object *p_ap_encode_obj);
|
||||
int ap_encode_header(appledouble_encode_object* p_ap_encode_obj, bool firstTime);
|
||||
int ap_encode_data( appledouble_encode_object* p_ap_encode_obj, bool firstTime);
|
||||
|
||||
/*
|
||||
** the prototypes for the ap_decoder.
|
||||
*/
|
||||
int fetch_a_line(appledouble_decode_object* p_ap_decode_obj, char *buff);
|
||||
int ParseFileHeader(appledouble_decode_object* p_ap_decode_obj);
|
||||
int ap_seek_part_start(appledouble_decode_object* p_ap_decode_obj);
|
||||
void parse_param(char *p, char **param, char**define, char **np);
|
||||
int ap_seek_to_boundary(appledouble_decode_object* p_ap_decode_obj, bool firstime);
|
||||
int ap_parse_header(appledouble_decode_object* p_ap_decode_obj,bool firstime);
|
||||
int ap_decode_file_infor(appledouble_decode_object* p_ap_decode_obj);
|
||||
int ap_decode_process_header(appledouble_decode_object* p_ap_decode_obj, bool firstime);
|
||||
int ap_decode_process_data( appledouble_decode_object* p_ap_decode_obj, bool firstime);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=reset
|
||||
#endif
|
||||
|
||||
#endif /* ad_codes_h */
|
||||
207
mailnews/compose/src/nsMsgAppleDouble.h
Normal file
207
mailnews/compose/src/nsMsgAppleDouble.h
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/* -*- Mode: C; tab-width: 4; 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/. */
|
||||
|
||||
/*
|
||||
* AppleDouble.h
|
||||
* -------------
|
||||
*
|
||||
* The header file for a stream based apple single/double encodor/decodor.
|
||||
*
|
||||
* 2aug95 mym
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef AppleDouble_h
|
||||
#define AppleDouble_h
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsComposeStrings.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
||||
#define NOERR 0
|
||||
#define errDone 1
|
||||
/* Done with current operation. */
|
||||
#define errEOB 2
|
||||
/* End of a buffer. */
|
||||
#define errEOP 3
|
||||
/* End of a Part. */
|
||||
|
||||
|
||||
#define errFileOpen NS_ERROR_GET_CODE(NS_MSG_UNABLE_TO_OPEN_TMP_FILE)
|
||||
#define errFileWrite -202 /*Error writing temporary file.*/
|
||||
#define errUsrCancel -2 /*MK_INTERRUPTED */
|
||||
#define errDecoding -1
|
||||
|
||||
/*
|
||||
** The envirment block data type.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
kInit,
|
||||
kDoingHeaderPortion,
|
||||
kDoneHeaderPortion,
|
||||
kDoingDataPortion,
|
||||
kDoneDataPortion
|
||||
};
|
||||
|
||||
typedef struct _appledouble_encode_object
|
||||
{
|
||||
char fname[256];
|
||||
FSIORefNum fileId; /* the id for the open file (data/resource fork) */
|
||||
|
||||
int state;
|
||||
int text_file_type; /* if the file has a text file type with it. */
|
||||
char *boundary; /* the boundary string. */
|
||||
|
||||
int status; /* the error code if anyerror happens. */
|
||||
char b_overflow[200];
|
||||
int s_overflow;
|
||||
|
||||
int state64; /* the left over state of base64 enocding */
|
||||
int ct; /* the character count of base64 encoding */
|
||||
int c1, c2; /* the left of the last base64 encoding */
|
||||
|
||||
char *outbuff; /* the outbuff by the caller. */
|
||||
int s_outbuff; /* the size of the buffer. */
|
||||
int pos_outbuff; /* the offset in the current buffer. */
|
||||
|
||||
} appledouble_encode_object;
|
||||
|
||||
/* The possible content transfer encodings */
|
||||
|
||||
enum
|
||||
{
|
||||
kEncodeNone,
|
||||
kEncodeQP,
|
||||
kEncodeBase64,
|
||||
kEncodeUU
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kGeneralMine,
|
||||
kAppleDouble,
|
||||
kAppleSingle
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kInline,
|
||||
kDontCare
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kHeaderPortion,
|
||||
kDataPortion
|
||||
};
|
||||
|
||||
/* the decode states. */
|
||||
enum
|
||||
{
|
||||
kBeginParseHeader = 3,
|
||||
kParsingHeader,
|
||||
kBeginSeekBoundary,
|
||||
kSeekingBoundary,
|
||||
kBeginHeaderPortion,
|
||||
kProcessingHeaderPortion,
|
||||
kBeginDataPortion,
|
||||
kProcessingDataPortion,
|
||||
kFinishing
|
||||
};
|
||||
|
||||
/* uuencode states */
|
||||
enum
|
||||
{
|
||||
kWaitingForBegin = (int) 0,
|
||||
kBegin,
|
||||
kMainBody,
|
||||
kEnd
|
||||
};
|
||||
|
||||
typedef struct _appledouble_decode_object
|
||||
{
|
||||
int is_binary;
|
||||
int is_apple_single; /* if the object encoded is in apple single */
|
||||
int write_as_binhex;
|
||||
|
||||
int messagetype;
|
||||
char* boundary0; /* the boundary for the enclosure. */
|
||||
int deposition; /* the deposition. */
|
||||
int encoding; /* the encoding method. */
|
||||
int which_part;
|
||||
|
||||
char fname[256];
|
||||
// nsIOFileStream *fileSpec; /* the stream for data fork work. */
|
||||
|
||||
int state;
|
||||
|
||||
int rksize; /* the resource fork size count. */
|
||||
int dksize; /* the data fork size count. */
|
||||
|
||||
int status; /* the error code if anyerror happens. */
|
||||
char b_leftover[256];
|
||||
int s_leftover;
|
||||
|
||||
int encode; /* the encode type of the message. */
|
||||
int state64; /* the left over state of base64 enocding */
|
||||
int left; /* the character count of base64 encoding */
|
||||
int c[4]; /* the left of the last base64 encoding */
|
||||
int uu_starts_line; /* is decoder at the start of a line? (uuencode) */
|
||||
int uu_state; /* state w/r/t the uuencode body */
|
||||
int uu_bytes_written; /* bytes written from the current tuple (uuencode) */
|
||||
int uu_line_bytes; /* encoded bytes remaining in the current line (uuencode) */
|
||||
|
||||
char *inbuff; /* the outbuff by the caller. */
|
||||
int s_inbuff; /* the size of the buffer. */
|
||||
int pos_inbuff; /* the offset in the current buffer. */
|
||||
|
||||
|
||||
nsCOMPtr <nsIFile> tmpFile; /* the temp file to hold the decode data fork */
|
||||
/* when doing the binhex exporting. */
|
||||
nsCOMPtr <nsIOutputStream> tmpFileStream; /* The output File Stream */
|
||||
int32_t data_size; /* the size of the data in the tmp file. */
|
||||
|
||||
} appledouble_decode_object;
|
||||
|
||||
|
||||
/*
|
||||
** The protypes.
|
||||
*/
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
int ap_encode_init(appledouble_encode_object *p_ap_encode_obj,
|
||||
const char* fname,
|
||||
char* separator);
|
||||
|
||||
int ap_encode_next(appledouble_encode_object* p_ap_encode_obj,
|
||||
char *to_buff,
|
||||
int32_t buff_size,
|
||||
int32_t* real_size);
|
||||
|
||||
int ap_encode_end(appledouble_encode_object* p_ap_encode_obj,
|
||||
bool is_aborting);
|
||||
|
||||
int ap_decode_init(appledouble_decode_object* p_ap_decode_obj,
|
||||
bool is_apple_single,
|
||||
bool write_as_bin_hex,
|
||||
void *closure);
|
||||
|
||||
int ap_decode_next(appledouble_decode_object* p_ap_decode_obj,
|
||||
char *in_buff,
|
||||
int32_t buff_size);
|
||||
|
||||
int ap_decode_end(appledouble_decode_object* p_ap_decode_obj,
|
||||
bool is_aborting);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif
|
||||
266
mailnews/compose/src/nsMsgAppleDoubleEncode.cpp
Normal file
266
mailnews/compose/src/nsMsgAppleDoubleEncode.cpp
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
/* -*- Mode: C++; tab-width: 4; 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/. */
|
||||
|
||||
/*
|
||||
*
|
||||
* apple-double.c
|
||||
* --------------
|
||||
*
|
||||
* The codes to do apple double encoding/decoding.
|
||||
*
|
||||
* 02aug95 mym created.
|
||||
*
|
||||
*/
|
||||
#include "nsID.h"
|
||||
#include "nscore.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsMsgAppleDouble.h"
|
||||
#include "nsMsgAppleCodes.h"
|
||||
#include "nsMsgCompUtils.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
#include "nsIMIMEService.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "prmem.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
|
||||
void
|
||||
MacGetFileType(nsIFile *fs,
|
||||
bool *useDefault,
|
||||
char **fileType,
|
||||
char **encoding)
|
||||
{
|
||||
if ((fs == NULL) || (fileType == NULL) || (encoding == NULL))
|
||||
return;
|
||||
|
||||
bool exists = false;
|
||||
fs->Exists(&exists);
|
||||
if (!exists)
|
||||
return;
|
||||
|
||||
*useDefault = TRUE;
|
||||
*fileType = NULL;
|
||||
*encoding = NULL;
|
||||
|
||||
nsCOMPtr<nsILocalFileMac> macFile = do_QueryInterface(fs);
|
||||
FSRef fsRef;
|
||||
FSCatalogInfo catalogInfo;
|
||||
OSErr err = errFileOpen;
|
||||
if (NS_SUCCEEDED(macFile->GetFSRef(&fsRef)))
|
||||
err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &catalogInfo, nullptr, nullptr, nullptr);
|
||||
|
||||
if ( (err != noErr) || (((FileInfo*)(&catalogInfo.finderInfo))->fileType == 'TEXT') )
|
||||
*fileType = strdup(APPLICATION_OCTET_STREAM);
|
||||
else
|
||||
{
|
||||
// At this point, we should call the mime service and
|
||||
// see what we can find out?
|
||||
nsresult rv;
|
||||
nsCOMPtr <nsIURI> tURI;
|
||||
if (NS_SUCCEEDED(NS_NewFileURI(getter_AddRefs(tURI), fs)) && tURI)
|
||||
{
|
||||
nsCOMPtr<nsIMIMEService> mimeFinder (do_GetService(NS_MIMESERVICE_CONTRACTID, &rv));
|
||||
if (NS_SUCCEEDED(rv) && mimeFinder)
|
||||
{
|
||||
nsAutoCString mimeType;
|
||||
rv = mimeFinder->GetTypeFromURI(tURI, mimeType);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
*fileType = ToNewCString(mimeType);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we hit here, return something...default to this...
|
||||
*fileType = strdup(APPLICATION_OCTET_STREAM);
|
||||
}
|
||||
}
|
||||
|
||||
//#pragma cplusplus reset
|
||||
|
||||
/*
|
||||
* ap_encode_init
|
||||
* --------------
|
||||
*
|
||||
* Setup the encode envirment
|
||||
*/
|
||||
|
||||
int ap_encode_init( appledouble_encode_object *p_ap_encode_obj,
|
||||
const char *fname,
|
||||
char *separator)
|
||||
{
|
||||
nsCOMPtr <nsIFile> myFile;
|
||||
NS_NewNativeLocalFile(nsDependentCString(fname), true, getter_AddRefs(myFile));
|
||||
bool exists;
|
||||
if (myFile && NS_SUCCEEDED(myFile->Exists(&exists)) && !exists)
|
||||
return -1;
|
||||
|
||||
nsCOMPtr<nsILocalFileMac> macFile = do_QueryInterface(myFile);
|
||||
nsAutoCString path;
|
||||
macFile->GetNativePath(path);
|
||||
|
||||
memset(p_ap_encode_obj, 0, sizeof(appledouble_encode_object));
|
||||
|
||||
/*
|
||||
** Fill out the source file inforamtion.
|
||||
*/
|
||||
memcpy(p_ap_encode_obj->fname, path.get(), path.Length());
|
||||
p_ap_encode_obj->fname[path.Length()] = '\0';
|
||||
|
||||
p_ap_encode_obj->boundary = strdup(separator);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
/*
|
||||
** ap_encode_next
|
||||
** --------------
|
||||
**
|
||||
** return :
|
||||
** noErr : everything is ok
|
||||
** errDone : when encoding is done.
|
||||
** errors : otherwise.
|
||||
*/
|
||||
int ap_encode_next(
|
||||
appledouble_encode_object* p_ap_encode_obj,
|
||||
char *to_buff,
|
||||
int32_t buff_size,
|
||||
int32_t* real_size)
|
||||
{
|
||||
int status;
|
||||
|
||||
/*
|
||||
** install the out buff now.
|
||||
*/
|
||||
p_ap_encode_obj->outbuff = to_buff;
|
||||
p_ap_encode_obj->s_outbuff = buff_size;
|
||||
p_ap_encode_obj->pos_outbuff = 0;
|
||||
|
||||
/*
|
||||
** first copy the outstandind data in the overflow buff to the out buffer.
|
||||
*/
|
||||
if (p_ap_encode_obj->s_overflow)
|
||||
{
|
||||
status = write_stream(p_ap_encode_obj,
|
||||
(const char*)(p_ap_encode_obj->b_overflow),
|
||||
p_ap_encode_obj->s_overflow);
|
||||
if (status != noErr)
|
||||
return status;
|
||||
|
||||
p_ap_encode_obj->s_overflow = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** go the next processing stage based on the current state.
|
||||
*/
|
||||
switch (p_ap_encode_obj->state)
|
||||
{
|
||||
case kInit:
|
||||
/*
|
||||
** We are in the starting position, fill out the header.
|
||||
*/
|
||||
status = fill_apple_mime_header(p_ap_encode_obj);
|
||||
if (status != noErr)
|
||||
break; /* some error happens */
|
||||
|
||||
p_ap_encode_obj->state = kDoingHeaderPortion;
|
||||
status = ap_encode_header(p_ap_encode_obj, true);
|
||||
/* it is the first time to calling */
|
||||
if (status == errDone)
|
||||
{
|
||||
p_ap_encode_obj->state = kDoneHeaderPortion;
|
||||
}
|
||||
else
|
||||
{
|
||||
break; /* we need more work on header portion. */
|
||||
}
|
||||
|
||||
/*
|
||||
** we are done with the header, so let's go to the data port.
|
||||
*/
|
||||
p_ap_encode_obj->state = kDoingDataPortion;
|
||||
status = ap_encode_data(p_ap_encode_obj, true);
|
||||
/* it is first time call do data portion */
|
||||
|
||||
if (status == errDone)
|
||||
{
|
||||
p_ap_encode_obj->state = kDoneDataPortion;
|
||||
status = noErr;
|
||||
}
|
||||
break;
|
||||
|
||||
case kDoingHeaderPortion:
|
||||
|
||||
status = ap_encode_header(p_ap_encode_obj, false);
|
||||
/* continue with the header portion. */
|
||||
if (status == errDone)
|
||||
{
|
||||
p_ap_encode_obj->state = kDoneHeaderPortion;
|
||||
}
|
||||
else
|
||||
{
|
||||
break; /* we need more work on header portion. */
|
||||
}
|
||||
|
||||
/*
|
||||
** start the data portion.
|
||||
*/
|
||||
p_ap_encode_obj->state = kDoingDataPortion;
|
||||
status = ap_encode_data(p_ap_encode_obj, true);
|
||||
/* it is the first time calling */
|
||||
if (status == errDone)
|
||||
{
|
||||
p_ap_encode_obj->state = kDoneDataPortion;
|
||||
status = noErr;
|
||||
}
|
||||
break;
|
||||
|
||||
case kDoingDataPortion:
|
||||
|
||||
status = ap_encode_data(p_ap_encode_obj, false);
|
||||
/* it is not the first time */
|
||||
|
||||
if (status == errDone)
|
||||
{
|
||||
p_ap_encode_obj->state = kDoneDataPortion;
|
||||
status = noErr;
|
||||
}
|
||||
break;
|
||||
|
||||
case kDoneDataPortion:
|
||||
status = errDone; /* we are really done. */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
*real_size = p_ap_encode_obj->pos_outbuff;
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
** ap_encode_end
|
||||
** -------------
|
||||
**
|
||||
** clear the apple encoding.
|
||||
*/
|
||||
|
||||
int ap_encode_end(
|
||||
appledouble_encode_object *p_ap_encode_obj,
|
||||
bool is_aborting)
|
||||
{
|
||||
/*
|
||||
** clear up the apple doubler.
|
||||
*/
|
||||
if (p_ap_encode_obj == NULL)
|
||||
return noErr;
|
||||
|
||||
if (p_ap_encode_obj->fileId) /* close the file if it is open. */
|
||||
::FSCloseFork(p_ap_encode_obj->fileId);
|
||||
|
||||
PR_FREEIF(p_ap_encode_obj->boundary); /* the boundary string. */
|
||||
|
||||
return noErr;
|
||||
}
|
||||
703
mailnews/compose/src/nsMsgAppleEncode.cpp
Normal file
703
mailnews/compose/src/nsMsgAppleEncode.cpp
Normal file
|
|
@ -0,0 +1,703 @@
|
|||
/* -*- Mode: C++; tab-width: 4; 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/. */
|
||||
|
||||
/*
|
||||
*
|
||||
* apple_double_encode.c
|
||||
* ---------------------
|
||||
*
|
||||
* The routines doing the Apple Double Encoding.
|
||||
*
|
||||
* 2aug95 mym Created.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "prprf.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsMsgAppleDouble.h"
|
||||
#include "nsMsgAppleCodes.h"
|
||||
#include "nsILocalFileMac.h"
|
||||
|
||||
/*
|
||||
** Local Functions prototypes.
|
||||
*/
|
||||
static int output64chunk( appledouble_encode_object* p_ap_encode_obj,
|
||||
int c1, int c2, int c3, int pads);
|
||||
|
||||
static int to64(appledouble_encode_object* p_ap_encode_obj,
|
||||
char *p,
|
||||
int in_size);
|
||||
|
||||
static int finish64(appledouble_encode_object* p_ap_encode_obj);
|
||||
|
||||
|
||||
#define BUFF_LEFT(p) ((p)->s_outbuff - (p)->pos_outbuff)
|
||||
|
||||
/*
|
||||
** write_stream.
|
||||
*/
|
||||
int write_stream(
|
||||
appledouble_encode_object *p_ap_encode_obj,
|
||||
const char *out_string,
|
||||
int len)
|
||||
{
|
||||
if (p_ap_encode_obj->pos_outbuff + len < p_ap_encode_obj->s_outbuff)
|
||||
{
|
||||
memcpy(p_ap_encode_obj->outbuff + p_ap_encode_obj->pos_outbuff,
|
||||
out_string,
|
||||
len);
|
||||
p_ap_encode_obj->pos_outbuff += len;
|
||||
return noErr;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
** If the buff doesn't have enough space, use the overflow buffer then.
|
||||
*/
|
||||
int s_len = p_ap_encode_obj->s_outbuff - p_ap_encode_obj->pos_outbuff;
|
||||
|
||||
memcpy(p_ap_encode_obj->outbuff + p_ap_encode_obj->pos_outbuff,
|
||||
out_string,
|
||||
s_len);
|
||||
memcpy(p_ap_encode_obj->b_overflow + p_ap_encode_obj->s_overflow,
|
||||
out_string + s_len,
|
||||
p_ap_encode_obj->s_overflow += (len - s_len));
|
||||
p_ap_encode_obj->pos_outbuff += s_len;
|
||||
return errEOB;
|
||||
}
|
||||
}
|
||||
|
||||
int fill_apple_mime_header(
|
||||
appledouble_encode_object *p_ap_encode_obj)
|
||||
{
|
||||
int status;
|
||||
|
||||
char tmpstr[266];
|
||||
|
||||
#if 0
|
||||
// strcpy(tmpstr, "Content-Type: multipart/mixed; boundary=\"-\"\n\n---\n");
|
||||
// status = write_stream(p_ap_encode_env,
|
||||
// tmpstr,
|
||||
// strlen(tmpstr));
|
||||
// if (status != noErr)
|
||||
// return status;
|
||||
|
||||
PR_snprintf(tmpstr, sizeof(tmpstr),
|
||||
"Content-Type: multipart/appledouble; boundary=\"=\"; name=\"");
|
||||
status = write_stream(p_ap_encode_obj, (const char*)tmpstr, strlen(tmpstr));
|
||||
if (status != noErr)
|
||||
return status;
|
||||
|
||||
status = write_stream(p_ap_encode_obj,
|
||||
p_ap_encode_obj->fname,
|
||||
strlen(p_ap_encode_obj->fname));
|
||||
if (status != noErr)
|
||||
return status;
|
||||
|
||||
PR_snprintf(tmpstr, sizeof(tmpstr),
|
||||
"\"\r\nContent-Disposition: inline; filename=\"%s\"\r\n\r\n\r\n--=\r\n",
|
||||
p_ap_encode_obj->fname);
|
||||
#endif /* 0 */
|
||||
PR_snprintf(tmpstr, sizeof(tmpstr), "--%s" CRLF, p_ap_encode_obj->boundary);
|
||||
status = write_stream(p_ap_encode_obj, (const char*)tmpstr, strlen(tmpstr));
|
||||
return status;
|
||||
}
|
||||
|
||||
int ap_encode_file_infor(
|
||||
appledouble_encode_object *p_ap_encode_obj)
|
||||
{
|
||||
ap_header head;
|
||||
ap_entry entries[NUM_ENTRIES];
|
||||
ap_dates dates;
|
||||
short i;
|
||||
long comlen;
|
||||
char comment[256];
|
||||
int status;
|
||||
|
||||
nsCOMPtr <nsIFile> resFile;
|
||||
NS_NewNativeLocalFile(nsDependentCString(p_ap_encode_obj->fname), true,
|
||||
getter_AddRefs(resFile));
|
||||
if (!resFile)
|
||||
return errFileOpen;
|
||||
|
||||
FSRef ref;
|
||||
nsCOMPtr <nsILocalFileMac> macFile = do_QueryInterface(resFile);
|
||||
if (NS_FAILED(macFile->GetFSRef(&ref)))
|
||||
return errFileOpen;
|
||||
|
||||
FSCatalogInfo catalogInfo;
|
||||
if (::FSGetCatalogInfo(&ref, kFSCatInfoFinderInfo, &catalogInfo, nullptr, nullptr, nullptr) != noErr)
|
||||
{
|
||||
return errFileOpen;
|
||||
}
|
||||
|
||||
/* get a file comment, if possible */
|
||||
#if 1
|
||||
// Carbon doesn't support GetWDInfo(). (Bug 555684)
|
||||
|
||||
// not sure why working directories are needed here...
|
||||
comlen = 0;
|
||||
#else
|
||||
long procID;
|
||||
procID = 0;
|
||||
GetWDInfo(p_ap_encode_obj->vRefNum, &fpb->ioVRefNum, &fpb->ioDirID, &procID);
|
||||
IOParam vinfo;
|
||||
memset((void *) &vinfo, '\0', sizeof (vinfo));
|
||||
GetVolParmsInfoBuffer vp;
|
||||
vinfo.ioCompletion = nil;
|
||||
vinfo.ioVRefNum = fpb->ioVRefNum;
|
||||
vinfo.ioBuffer = (Ptr) &vp;
|
||||
vinfo.ioReqCount = sizeof (vp);
|
||||
comlen = 0;
|
||||
if (PBHGetVolParmsSync((HParmBlkPtr) &vinfo) == noErr &&
|
||||
((vp.vMAttrib >> bHasDesktopMgr) & 1))
|
||||
{
|
||||
DTPBRec dtp;
|
||||
memset((void *) &dtp, '\0', sizeof (dtp));
|
||||
dtp.ioVRefNum = fpb->ioVRefNum;
|
||||
if (PBDTGetPath(&dtp) == noErr)
|
||||
{
|
||||
dtp.ioCompletion = nil;
|
||||
dtp.ioDTBuffer = (Ptr) comment;
|
||||
dtp.ioNamePtr = fpb->ioNamePtr;
|
||||
dtp.ioDirID = fpb->ioFlParID;
|
||||
if (PBDTGetCommentSync(&dtp) == noErr)
|
||||
comlen = dtp.ioDTActCount;
|
||||
}
|
||||
}
|
||||
#endif /* ! 1 */
|
||||
|
||||
/* write header */
|
||||
// head.magic = dfork ? APPLESINGLE_MAGIC : APPLEDOUBLE_MAGIC;
|
||||
head.magic = APPLEDOUBLE_MAGIC; /* always do apple double */
|
||||
head.version = VERSION;
|
||||
memset(head.fill, '\0', sizeof (head.fill));
|
||||
head.entries = NUM_ENTRIES - 1;
|
||||
status = to64(p_ap_encode_obj,
|
||||
(char *) &head,
|
||||
sizeof (head));
|
||||
if (status != noErr)
|
||||
return status;
|
||||
|
||||
/* write entry descriptors */
|
||||
nsAutoCString leafname;
|
||||
macFile->GetNativeLeafName(leafname);
|
||||
entries[0].offset = sizeof (head) + sizeof (ap_entry) * head.entries;
|
||||
entries[0].id = ENT_NAME;
|
||||
entries[0].length = leafname.Length();
|
||||
entries[1].id = ENT_FINFO;
|
||||
entries[1].length = sizeof (FInfo) + sizeof (FXInfo);
|
||||
entries[2].id = ENT_DATES;
|
||||
entries[2].length = sizeof (ap_dates);
|
||||
entries[3].id = ENT_COMMENT;
|
||||
entries[3].length = comlen;
|
||||
entries[4].id = ENT_RFORK;
|
||||
entries[4].length = catalogInfo.rsrcLogicalSize;
|
||||
entries[5].id = ENT_DFORK;
|
||||
entries[5].length = catalogInfo.dataLogicalSize;
|
||||
|
||||
/* correct the link in the entries. */
|
||||
for (i = 1; i < NUM_ENTRIES; ++i)
|
||||
{
|
||||
entries[i].offset = entries[i-1].offset + entries[i-1].length;
|
||||
}
|
||||
status = to64(p_ap_encode_obj,
|
||||
(char *) entries,
|
||||
sizeof (ap_entry) * head.entries);
|
||||
if (status != noErr)
|
||||
return status;
|
||||
|
||||
/* write name */
|
||||
status = to64(p_ap_encode_obj,
|
||||
(char *) leafname.get(),
|
||||
leafname.Length());
|
||||
if (status != noErr)
|
||||
return status;
|
||||
|
||||
/* write finder info */
|
||||
status = to64(p_ap_encode_obj,
|
||||
(char *) &catalogInfo.finderInfo,
|
||||
sizeof (FInfo));
|
||||
if (status != noErr)
|
||||
return status;
|
||||
|
||||
status = to64(p_ap_encode_obj,
|
||||
(char *) &catalogInfo.extFinderInfo,
|
||||
sizeof (FXInfo));
|
||||
if (status != noErr)
|
||||
return status;
|
||||
|
||||
/* write dates */
|
||||
dates.create = catalogInfo.createDate.lowSeconds + CONVERT_TIME;
|
||||
dates.modify = catalogInfo.contentModDate.lowSeconds + CONVERT_TIME;
|
||||
dates.backup = catalogInfo.backupDate.lowSeconds + CONVERT_TIME;
|
||||
dates.access = catalogInfo.accessDate.lowSeconds + CONVERT_TIME;
|
||||
status = to64(p_ap_encode_obj,
|
||||
(char *) &dates,
|
||||
sizeof (ap_dates));
|
||||
if (status != noErr)
|
||||
return status;
|
||||
|
||||
/* write comment */
|
||||
if (comlen)
|
||||
{
|
||||
status = to64(p_ap_encode_obj,
|
||||
comment,
|
||||
comlen * sizeof(char));
|
||||
}
|
||||
/*
|
||||
** Get some help information on deciding the file type.
|
||||
*/
|
||||
if (((FileInfo*)(&catalogInfo.finderInfo))->fileType == 'TEXT' ||
|
||||
((FileInfo*)(&catalogInfo.finderInfo))->fileType == 'text')
|
||||
{
|
||||
p_ap_encode_obj->text_file_type = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
/*
|
||||
** ap_encode_header
|
||||
**
|
||||
** encode the file header and the resource fork.
|
||||
**
|
||||
*/
|
||||
int ap_encode_header(
|
||||
appledouble_encode_object* p_ap_encode_obj,
|
||||
bool firstime)
|
||||
{
|
||||
char rd_buff[256];
|
||||
FSIORefNum fileId;
|
||||
OSErr retval = noErr;
|
||||
int status;
|
||||
ByteCount inCount;
|
||||
|
||||
if (firstime)
|
||||
{
|
||||
PL_strcpy(rd_buff,
|
||||
"Content-Type: application/applefile\r\nContent-Transfer-Encoding: base64\r\n\r\n");
|
||||
status = write_stream(p_ap_encode_obj, (const char*)rd_buff, strlen(rd_buff));
|
||||
if (status != noErr)
|
||||
return status;
|
||||
|
||||
status = ap_encode_file_infor(p_ap_encode_obj);
|
||||
if (status != noErr)
|
||||
return status;
|
||||
|
||||
/*
|
||||
** preparing to encode the resource fork.
|
||||
*/
|
||||
nsCOMPtr <nsIFile> myFile;
|
||||
NS_NewNativeLocalFile(nsDependentCString(p_ap_encode_obj->fname), true, getter_AddRefs(myFile));
|
||||
if (!myFile)
|
||||
return errFileOpen;
|
||||
|
||||
FSRef ref;
|
||||
nsCOMPtr <nsILocalFileMac> macFile = do_QueryInterface(myFile);
|
||||
if (NS_FAILED(macFile->GetFSRef(&ref)))
|
||||
return errFileOpen;
|
||||
|
||||
HFSUniStr255 forkName;
|
||||
::FSGetResourceForkName(&forkName);
|
||||
retval = ::FSOpenFork(&ref, forkName.length, forkName.unicode, fsRdPerm, &p_ap_encode_obj->fileId);
|
||||
if (retval != noErr)
|
||||
return retval;
|
||||
}
|
||||
|
||||
fileId = p_ap_encode_obj->fileId;
|
||||
while (retval == noErr)
|
||||
{
|
||||
if (BUFF_LEFT(p_ap_encode_obj) < 400)
|
||||
break;
|
||||
|
||||
inCount = 0;
|
||||
retval = ::FSReadFork(fileId, fsAtMark, 0, 256, rd_buff, &inCount);
|
||||
if (inCount)
|
||||
{
|
||||
status = to64(p_ap_encode_obj,
|
||||
rd_buff,
|
||||
inCount);
|
||||
if (status != noErr)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == eofErr)
|
||||
{
|
||||
::FSCloseFork(fileId);
|
||||
p_ap_encode_obj->fileId = 0;
|
||||
|
||||
status = finish64(p_ap_encode_obj);
|
||||
if (status != noErr)
|
||||
return status;
|
||||
|
||||
/*
|
||||
** write out the boundary
|
||||
*/
|
||||
PR_snprintf(rd_buff, sizeof(rd_buff),
|
||||
CRLF "--%s" CRLF,
|
||||
p_ap_encode_obj->boundary);
|
||||
|
||||
status = write_stream(p_ap_encode_obj, (const char*)rd_buff, strlen(rd_buff));
|
||||
if (status == noErr)
|
||||
status = errDone;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// This is unused for now and Clang complains about that is it is ifdefed out
|
||||
static void replace(char *p, int len, char frm, char to)
|
||||
{
|
||||
for (; len > 0; len--, p++)
|
||||
if (*p == frm) *p = to;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Description of the various file formats and their magic numbers */
|
||||
struct magic
|
||||
{
|
||||
const char *name; /* Name of the file format */
|
||||
const char *num; /* The magic number */
|
||||
int len; /* Length (0 means strlen(magicnum)) */
|
||||
};
|
||||
|
||||
/* The magic numbers of the file formats we know about */
|
||||
static struct magic magic[] =
|
||||
{
|
||||
{ "image/gif", "GIF", 0 },
|
||||
{ "image/jpeg", "\377\330\377", 0 },
|
||||
{ "video/mpeg", "\0\0\001\263", 4 },
|
||||
{ "application/postscript", "%!", 0 },
|
||||
};
|
||||
static int num_magic = MOZ_ARRAY_LENGTH(magic);
|
||||
|
||||
static const char *text_type = TEXT_PLAIN; /* the text file type. */
|
||||
static const char *default_type = APPLICATION_OCTET_STREAM;
|
||||
|
||||
|
||||
/*
|
||||
* Determins the format of the file "inputf". The name
|
||||
* of the file format (or NULL on error) is returned.
|
||||
*/
|
||||
static const char *magic_look(char *inbuff, int numread)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i=0; i<num_magic; i++)
|
||||
{
|
||||
if (magic[i].len == 0)
|
||||
magic[i].len = strlen(magic[i].num);
|
||||
}
|
||||
|
||||
for (i=0; i<num_magic; i++)
|
||||
{
|
||||
if (numread >= magic[i].len)
|
||||
{
|
||||
for (j=0; j<magic[i].len; j++)
|
||||
{
|
||||
if (inbuff[j] != magic[i].num[j]) break;
|
||||
}
|
||||
|
||||
if (j == magic[i].len)
|
||||
return magic[i].name;
|
||||
}
|
||||
}
|
||||
|
||||
return default_type;
|
||||
}
|
||||
/*
|
||||
** ap_encode_data
|
||||
**
|
||||
** ---------------
|
||||
**
|
||||
** encode on the data fork.
|
||||
**
|
||||
*/
|
||||
int ap_encode_data(
|
||||
appledouble_encode_object* p_ap_encode_obj,
|
||||
bool firstime)
|
||||
{
|
||||
char rd_buff[256];
|
||||
FSIORefNum fileId;
|
||||
OSErr retval = noErr;
|
||||
ByteCount in_count;
|
||||
int status;
|
||||
|
||||
if (firstime)
|
||||
{
|
||||
const char* magic_type;
|
||||
|
||||
/*
|
||||
** preparing to encode the data fork.
|
||||
*/
|
||||
nsCOMPtr <nsIFile> resFile;
|
||||
NS_NewNativeLocalFile(nsDependentCString(p_ap_encode_obj->fname), true,
|
||||
getter_AddRefs(resFile));
|
||||
if (!resFile)
|
||||
return errFileOpen;
|
||||
|
||||
FSRef ref;
|
||||
nsCOMPtr <nsILocalFileMac> macFile = do_QueryInterface(resFile);
|
||||
if (NS_FAILED(macFile->GetFSRef(&ref)))
|
||||
return errFileOpen;
|
||||
|
||||
HFSUniStr255 forkName;
|
||||
::FSGetDataForkName(&forkName);
|
||||
retval = ::FSOpenFork(&ref, forkName.length, forkName.unicode, fsRdPerm, &fileId);
|
||||
if (retval != noErr)
|
||||
return retval;
|
||||
|
||||
p_ap_encode_obj->fileId = fileId;
|
||||
|
||||
|
||||
if (!p_ap_encode_obj->text_file_type)
|
||||
{
|
||||
/*
|
||||
** do a smart check for the file type.
|
||||
*/
|
||||
in_count = 0;
|
||||
retval = ::FSReadFork(fileId, fsFromStart, 0, 256, rd_buff, &in_count);
|
||||
magic_type = magic_look(rd_buff, in_count);
|
||||
|
||||
/* don't forget to rewind the index to start point. */
|
||||
::FSSetForkPosition(fileId, fsFromStart, 0);
|
||||
/* and reset retVal just in case... */
|
||||
if (retval == eofErr)
|
||||
retval = noErr;
|
||||
}
|
||||
else
|
||||
{
|
||||
magic_type = text_type; /* we already know it is a text type. */
|
||||
}
|
||||
|
||||
/*
|
||||
** the data portion header information.
|
||||
*/
|
||||
nsAutoCString leafName;
|
||||
resFile->GetNativeLeafName(leafName);
|
||||
PR_snprintf(rd_buff, sizeof(rd_buff),
|
||||
"Content-Type: %s; name=\"%s\"" CRLF "Content-Transfer-Encoding: base64" CRLF "Content-Disposition: inline; filename=\"%s\"" CRLF CRLF,
|
||||
magic_type,
|
||||
leafName.get(),
|
||||
leafName.get());
|
||||
|
||||
status = write_stream(p_ap_encode_obj, (const char*)rd_buff, strlen(rd_buff));
|
||||
if (status != noErr)
|
||||
return status;
|
||||
}
|
||||
|
||||
while (retval == noErr)
|
||||
{
|
||||
if (BUFF_LEFT(p_ap_encode_obj) < 400)
|
||||
break;
|
||||
|
||||
in_count = 0;
|
||||
retval = ::FSReadFork(p_ap_encode_obj->fileId, fsAtMark, 0, 256, rd_buff, &in_count);
|
||||
if (in_count)
|
||||
{
|
||||
#if 0
|
||||
/* replace(rd_buff, in_count, '\r', '\n'); */
|
||||
#endif
|
||||
/* ** may be need to do character set conversion here for localization. ** */
|
||||
status = to64(p_ap_encode_obj,
|
||||
rd_buff,
|
||||
in_count);
|
||||
if (status != noErr)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == eofErr)
|
||||
{
|
||||
::FSCloseFork(p_ap_encode_obj->fileId);
|
||||
p_ap_encode_obj->fileId = 0;
|
||||
|
||||
status = finish64(p_ap_encode_obj);
|
||||
if (status != noErr)
|
||||
return status;
|
||||
|
||||
/* write out the boundary */
|
||||
|
||||
PR_snprintf(rd_buff, sizeof(rd_buff),
|
||||
CRLF "--%s--" CRLF CRLF,
|
||||
p_ap_encode_obj->boundary);
|
||||
|
||||
status = write_stream(p_ap_encode_obj, (const char*)rd_buff, strlen(rd_buff));
|
||||
|
||||
if (status == noErr)
|
||||
status = errDone;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static char basis_64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
/*
|
||||
** convert the stream in the inbuff to 64 format and put it in the out buff.
|
||||
** To make the life easier, the caller will responcable of the cheking of the outbuff's bundary.
|
||||
*/
|
||||
static int
|
||||
to64(appledouble_encode_object* p_ap_encode_obj,
|
||||
char *p,
|
||||
int in_size)
|
||||
{
|
||||
int status;
|
||||
int c1, c2, c3, ct;
|
||||
unsigned char *inbuff = (unsigned char*)p;
|
||||
|
||||
ct = p_ap_encode_obj->ct; /* the char count left last time. */
|
||||
|
||||
/*
|
||||
** resume the left state of the last conversion.
|
||||
*/
|
||||
switch (p_ap_encode_obj->state64)
|
||||
{
|
||||
case 0:
|
||||
p_ap_encode_obj->c1 = c1 = *inbuff ++;
|
||||
if (--in_size <= 0)
|
||||
{
|
||||
p_ap_encode_obj->state64 = 1;
|
||||
return noErr;
|
||||
}
|
||||
p_ap_encode_obj->c2 = c2 = *inbuff ++;
|
||||
if (--in_size <= 0)
|
||||
{
|
||||
p_ap_encode_obj->state64 = 2;
|
||||
return noErr;
|
||||
}
|
||||
c3 = *inbuff ++; --in_size;
|
||||
break;
|
||||
case 1:
|
||||
c1 = p_ap_encode_obj->c1;
|
||||
p_ap_encode_obj->c2 = c2 = *inbuff ++;
|
||||
if (--in_size <= 0)
|
||||
{
|
||||
p_ap_encode_obj->state64 = 2;
|
||||
return noErr;
|
||||
}
|
||||
c3 = *inbuff ++; --in_size;
|
||||
break;
|
||||
case 2:
|
||||
c1 = p_ap_encode_obj->c1;
|
||||
c2 = p_ap_encode_obj->c2;
|
||||
c3 = *inbuff ++; --in_size;
|
||||
break;
|
||||
}
|
||||
|
||||
while (in_size >= 0)
|
||||
{
|
||||
status = output64chunk(p_ap_encode_obj,
|
||||
c1,
|
||||
c2,
|
||||
c3,
|
||||
0);
|
||||
if (status != noErr)
|
||||
return status;
|
||||
|
||||
ct += 4;
|
||||
if (ct > 71)
|
||||
{
|
||||
status = write_stream(p_ap_encode_obj,
|
||||
CRLF,
|
||||
2);
|
||||
if (status != noErr)
|
||||
return status;
|
||||
|
||||
ct = 0;
|
||||
}
|
||||
|
||||
if (in_size <= 0)
|
||||
{
|
||||
p_ap_encode_obj->state64 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
c1 = (int)*inbuff++;
|
||||
if (--in_size <= 0)
|
||||
{
|
||||
p_ap_encode_obj->c1 = c1;
|
||||
p_ap_encode_obj->state64 = 1;
|
||||
break;
|
||||
}
|
||||
c2 = *inbuff++;
|
||||
if (--in_size <= 0)
|
||||
{
|
||||
p_ap_encode_obj->c1 = c1;
|
||||
p_ap_encode_obj->c2 = c2;
|
||||
p_ap_encode_obj->state64 = 2;
|
||||
break;
|
||||
}
|
||||
c3 = *inbuff++;
|
||||
in_size--;
|
||||
}
|
||||
p_ap_encode_obj->ct = ct;
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
** clear the left base64 encodes.
|
||||
*/
|
||||
static int
|
||||
finish64(appledouble_encode_object* p_ap_encode_obj)
|
||||
{
|
||||
int status;
|
||||
|
||||
switch (p_ap_encode_obj->state64)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
status = output64chunk(p_ap_encode_obj,
|
||||
p_ap_encode_obj->c1,
|
||||
0,
|
||||
0,
|
||||
2);
|
||||
break;
|
||||
case 2:
|
||||
status = output64chunk(p_ap_encode_obj,
|
||||
p_ap_encode_obj->c1,
|
||||
p_ap_encode_obj->c2,
|
||||
0,
|
||||
1);
|
||||
break;
|
||||
}
|
||||
status = write_stream(p_ap_encode_obj, CRLF, 2);
|
||||
p_ap_encode_obj->state64 = 0;
|
||||
p_ap_encode_obj->ct = 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
static int output64chunk(
|
||||
appledouble_encode_object* p_ap_encode_obj,
|
||||
int c1, int c2, int c3, int pads)
|
||||
{
|
||||
char tmpstr[32];
|
||||
char *p = tmpstr;
|
||||
|
||||
*p++ = basis_64[c1>>2];
|
||||
*p++ = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)];
|
||||
if (pads == 2)
|
||||
{
|
||||
*p++ = '=';
|
||||
*p++ = '=';
|
||||
}
|
||||
else if (pads)
|
||||
{
|
||||
*p++ = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
|
||||
*p++ = '=';
|
||||
}
|
||||
else
|
||||
{
|
||||
*p++ = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
|
||||
*p++ = basis_64[c3 & 0x3F];
|
||||
}
|
||||
return write_stream(p_ap_encode_obj, (const char*) tmpstr, p-tmpstr);
|
||||
}
|
||||
262
mailnews/compose/src/nsMsgAttachment.cpp
Normal file
262
mailnews/compose/src/nsMsgAttachment.cpp
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "nsMsgAttachment.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMsgAttachment, nsIMsgAttachment)
|
||||
|
||||
nsMsgAttachment::nsMsgAttachment()
|
||||
{
|
||||
mTemporary = false;
|
||||
mSendViaCloud = false;
|
||||
mSize = -1;
|
||||
}
|
||||
|
||||
nsMsgAttachment::~nsMsgAttachment()
|
||||
{
|
||||
if (mTemporary && !mSendViaCloud)
|
||||
(void)DeleteAttachment();
|
||||
}
|
||||
|
||||
/* attribute wstring name; */
|
||||
NS_IMETHODIMP nsMsgAttachment::GetName(nsAString & aName)
|
||||
{
|
||||
aName = mName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgAttachment::SetName(const nsAString & aName)
|
||||
{
|
||||
mName = aName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute string url; */
|
||||
NS_IMETHODIMP nsMsgAttachment::GetUrl(nsACString & aUrl)
|
||||
{
|
||||
aUrl = mUrl;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgAttachment::SetUrl(const nsACString & aUrl)
|
||||
{
|
||||
mUrl = aUrl;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute string urlCharset; */
|
||||
NS_IMETHODIMP nsMsgAttachment::GetUrlCharset(nsACString & aUrlCharset)
|
||||
{
|
||||
aUrlCharset = mUrlCharset;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgAttachment::SetUrlCharset(const nsACString & aUrlCharset)
|
||||
{
|
||||
mUrlCharset = aUrlCharset;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute boolean temporary; */
|
||||
NS_IMETHODIMP nsMsgAttachment::GetTemporary(bool *aTemporary)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aTemporary);
|
||||
|
||||
*aTemporary = mTemporary;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgAttachment::SetTemporary(bool aTemporary)
|
||||
{
|
||||
mTemporary = aTemporary;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgAttachment::GetSendViaCloud(bool *aSendViaCloud)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSendViaCloud);
|
||||
|
||||
*aSendViaCloud = mSendViaCloud;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgAttachment::SetSendViaCloud(bool aSendViaCloud)
|
||||
{
|
||||
mSendViaCloud = aSendViaCloud;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgAttachment::SetHtmlAnnotation(const nsAString &aAnnotation)
|
||||
{
|
||||
mHtmlAnnotation = aAnnotation;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgAttachment::GetHtmlAnnotation(nsAString &aAnnotation)
|
||||
{
|
||||
aAnnotation = mHtmlAnnotation;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgAttachment::SetCloudProviderKey(const nsACString &aCloudProviderKey)
|
||||
{
|
||||
mCloudProviderKey = aCloudProviderKey;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgAttachment::GetCloudProviderKey(nsACString &aCloudProviderKey)
|
||||
{
|
||||
aCloudProviderKey = mCloudProviderKey;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgAttachment::GetContentLocation(nsACString &aContentLocation)
|
||||
{
|
||||
aContentLocation = mContentLocation;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgAttachment::SetContentLocation(const nsACString &aContentLocation)
|
||||
{
|
||||
mContentLocation = aContentLocation;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgAttachment::GetContentType(char * *aContentType)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aContentType);
|
||||
|
||||
*aContentType = ToNewCString(mContentType);
|
||||
return (*aContentType ? NS_OK : NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgAttachment::SetContentType(const char * aContentType)
|
||||
{
|
||||
mContentType = aContentType;
|
||||
/* a full content type could also contains parameters but we need to
|
||||
keep only the content type alone. Therefore we need to cleanup it.
|
||||
*/
|
||||
int32_t offset = mContentType.FindChar(';');
|
||||
if (offset >= 0)
|
||||
mContentType.SetLength(offset);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgAttachment::GetContentTypeParam(char * *aContentTypeParam)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aContentTypeParam);
|
||||
|
||||
*aContentTypeParam = ToNewCString(mContentTypeParam);
|
||||
return (*aContentTypeParam ? NS_OK : NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgAttachment::SetContentTypeParam(const char * aContentTypeParam)
|
||||
{
|
||||
if (aContentTypeParam)
|
||||
while (*aContentTypeParam == ';' || *aContentTypeParam == ' ')
|
||||
aContentTypeParam ++;
|
||||
mContentTypeParam = aContentTypeParam;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute string charset; */
|
||||
NS_IMETHODIMP nsMsgAttachment::GetCharset(char * *aCharset)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCharset);
|
||||
|
||||
*aCharset = ToNewCString(mCharset);
|
||||
return (*aCharset ? NS_OK : NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
NS_IMETHODIMP nsMsgAttachment::SetCharset(const char * aCharset)
|
||||
{
|
||||
mCharset = aCharset;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute string macType; */
|
||||
NS_IMETHODIMP nsMsgAttachment::GetMacType(char * *aMacType)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aMacType);
|
||||
|
||||
*aMacType = ToNewCString(mMacType);
|
||||
return (*aMacType ? NS_OK : NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
NS_IMETHODIMP nsMsgAttachment::SetMacType(const char * aMacType)
|
||||
{
|
||||
mMacType = aMacType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute string macCreator; */
|
||||
NS_IMETHODIMP nsMsgAttachment::GetMacCreator(char * *aMacCreator)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aMacCreator);
|
||||
|
||||
*aMacCreator = ToNewCString(mMacCreator);
|
||||
return (*aMacCreator ? NS_OK : NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
NS_IMETHODIMP nsMsgAttachment::SetMacCreator(const char * aMacCreator)
|
||||
{
|
||||
mMacCreator = aMacCreator;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute int64_t size; */
|
||||
NS_IMETHODIMP nsMsgAttachment::GetSize(int64_t *aSize)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSize);
|
||||
|
||||
*aSize = mSize;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgAttachment::SetSize(int64_t aSize)
|
||||
{
|
||||
mSize = aSize;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* boolean equalsUrl (in nsIMsgAttachment attachment); */
|
||||
NS_IMETHODIMP nsMsgAttachment::EqualsUrl(nsIMsgAttachment *attachment, bool *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(attachment);
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
nsAutoCString url;
|
||||
attachment->GetUrl(url);
|
||||
|
||||
*_retval = mUrl.Equals(url);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsMsgAttachment::DeleteAttachment()
|
||||
{
|
||||
nsresult rv;
|
||||
bool isAFile = false;
|
||||
|
||||
nsCOMPtr<nsIFile> urlFile;
|
||||
rv = NS_GetFileFromURLSpec(mUrl, getter_AddRefs(urlFile));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't nsIFile from URL string");
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
bool bExists = false;
|
||||
rv = urlFile->Exists(&bExists);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Exists() call failed!");
|
||||
if (NS_SUCCEEDED(rv) && bExists)
|
||||
{
|
||||
rv = urlFile->IsFile(&isAFile);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "IsFile() call failed!");
|
||||
}
|
||||
}
|
||||
|
||||
// remove it if it's a valid file
|
||||
if (isAFile)
|
||||
rv = urlFile->Remove(false);
|
||||
|
||||
return rv;
|
||||
}
|
||||
41
mailnews/compose/src/nsMsgAttachment.h
Normal file
41
mailnews/compose/src/nsMsgAttachment.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* -*- 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 _nsMsgAttachment_H_
|
||||
#define _nsMsgAttachment_H_
|
||||
|
||||
#include "nsIMsgAttachment.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsMsgAttachment : public nsIMsgAttachment
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMSGATTACHMENT
|
||||
|
||||
nsMsgAttachment();
|
||||
|
||||
private:
|
||||
virtual ~nsMsgAttachment();
|
||||
nsresult DeleteAttachment();
|
||||
|
||||
nsString mName;
|
||||
nsCString mUrl;
|
||||
nsCString mUrlCharset;
|
||||
bool mTemporary;
|
||||
bool mSendViaCloud;
|
||||
nsCString mCloudProviderKey;
|
||||
nsCString mContentLocation;
|
||||
nsCString mContentType;
|
||||
nsCString mContentTypeParam;
|
||||
nsCString mCharset;
|
||||
nsCString mMacType;
|
||||
nsCString mMacCreator;
|
||||
nsString mHtmlAnnotation;
|
||||
int64_t mSize;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _nsMsgAttachment_H_ */
|
||||
1383
mailnews/compose/src/nsMsgAttachmentHandler.cpp
Normal file
1383
mailnews/compose/src/nsMsgAttachmentHandler.cpp
Normal file
File diff suppressed because it is too large
Load diff
194
mailnews/compose/src/nsMsgAttachmentHandler.h
Normal file
194
mailnews/compose/src/nsMsgAttachmentHandler.h
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
/* -*- 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 _nsMsgAttachmentHandler_H_
|
||||
#define _nsMsgAttachmentHandler_H_
|
||||
|
||||
#include "nsIURL.h"
|
||||
#include "nsMsgCompFields.h"
|
||||
#include "nsIMsgStatusFeedback.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIMsgSend.h"
|
||||
#include "nsIFileStreams.h"
|
||||
#include "nsIStreamConverter.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIMsgAttachmentHandler.h"
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
|
||||
#include "nsMsgAppleDouble.h"
|
||||
#include "nsILocalFileMac.h"
|
||||
|
||||
class AppleDoubleEncodeObject
|
||||
{
|
||||
public:
|
||||
appledouble_encode_object ap_encode_obj;
|
||||
char *buff; // the working buff
|
||||
int32_t s_buff; // the working buff size
|
||||
nsCOMPtr <nsIOutputStream> fileStream; // file to hold the encoding
|
||||
};
|
||||
|
||||
class nsILocalFileMac;
|
||||
class nsIZipWriter;
|
||||
|
||||
/* Simple utility class that will synchronously zip any file
|
||||
(or folder hierarchy) you give it. */
|
||||
class nsSimpleZipper
|
||||
{
|
||||
public:
|
||||
|
||||
// Synchronously zips the input file/folder and writes all
|
||||
// data to the output file.
|
||||
static nsresult Zip(nsIFile *aInputFile, nsIFile *aOutputFile);
|
||||
|
||||
private:
|
||||
|
||||
// Recursively adds the file or folder to aZipWriter.
|
||||
static nsresult AddToZip(nsIZipWriter *aZipWriter,
|
||||
nsIFile *aFile,
|
||||
const nsACString &aPath);
|
||||
};
|
||||
#endif // XP_MACOSX
|
||||
|
||||
namespace mozilla {
|
||||
namespace mailnews {
|
||||
class MimeEncoder;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// This is a class that deals with processing remote attachments. It implements
|
||||
// an nsIStreamListener interface to deal with incoming data
|
||||
//
|
||||
class nsMsgAttachmentHandler : public nsIMsgAttachmentHandler
|
||||
{
|
||||
|
||||
typedef mozilla::mailnews::MimeEncoder MimeEncoder;
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIMSGATTACHMENTHANDLER
|
||||
|
||||
nsMsgAttachmentHandler();
|
||||
public:
|
||||
nsresult SnarfAttachment(nsMsgCompFields *compFields);
|
||||
nsresult PickEncoding(const char *charset, nsIMsgSend* mime_delivery_state);
|
||||
nsresult PickCharset();
|
||||
void AnalyzeSnarfedFile (); // Analyze a previously-snarfed file.
|
||||
// (Currently only used for plaintext
|
||||
// converted from HTML.)
|
||||
nsresult Abort();
|
||||
nsresult UrlExit(nsresult status, const char16_t* aMsg);
|
||||
|
||||
// if there's an intermediate temp file left, takes care to remove it from disk.
|
||||
//
|
||||
// NOTE: this takes care of the mEncodedWorkingFile temp file, but not mTmpFile which seems
|
||||
// to be used by lots of other classes at the moment.
|
||||
void CleanupTempFile();
|
||||
|
||||
private:
|
||||
virtual ~nsMsgAttachmentHandler();
|
||||
|
||||
// use when a message (e.g. original message in a reply) is attached as a rfc822 attachment.
|
||||
nsresult SnarfMsgAttachment(nsMsgCompFields *compFields);
|
||||
bool UseUUEncode_p(void);
|
||||
void AnalyzeDataChunk (const char *chunk, int32_t chunkSize);
|
||||
nsresult LoadDataFromFile(nsIFile *file, nsString &sigData, bool charsetConversion); //A similar function already exist in nsMsgCompose!
|
||||
#ifdef XP_MACOSX
|
||||
nsresult ConvertToAppleEncoding(const nsCString &aFileSpecURI,
|
||||
const nsCString &aFilePath,
|
||||
nsILocalFileMac *aSourceFile);
|
||||
// zips this attachment and does the work to make this attachment handler handle it properly.
|
||||
nsresult ConvertToZipFile(nsILocalFileMac *aSourceFile);
|
||||
bool HasResourceFork(FSRef *fsRef);
|
||||
#endif
|
||||
|
||||
//
|
||||
public:
|
||||
nsCOMPtr<nsIURI> mURL;
|
||||
nsCOMPtr<nsIFile> mTmpFile; // The temp file to which we save it
|
||||
nsCOMPtr<nsIOutputStream> mOutFile;
|
||||
nsCOMPtr<nsIRequest> mRequest; // The live request used while fetching an attachment
|
||||
nsMsgCompFields *mCompFields; // Message composition fields for the sender
|
||||
bool m_bogus_attachment; // This is to catch problem children...
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// if we need to encode this file into for example an appledouble, or zip file,
|
||||
// this file is our working file. currently only needed on mac.
|
||||
nsCOMPtr<nsIFile> mEncodedWorkingFile;
|
||||
#endif
|
||||
|
||||
nsCString m_xMacType; // Mac file type
|
||||
nsCString m_xMacCreator; // Mac file creator
|
||||
|
||||
bool m_done;
|
||||
nsCString m_charset; // charset name
|
||||
nsCString m_contentId; // This is for mutipart/related Content-ID's
|
||||
nsCString m_type; // The real type, once we know it.
|
||||
nsCString m_typeParam; // Any addition parameters to add to the content-type (other than charset, macType and maccreator)
|
||||
nsCString m_overrideType; // The type we should assume it to be
|
||||
// or 0, if we should get it from the
|
||||
// server)
|
||||
nsCString m_overrideEncoding; // Goes along with override_type
|
||||
|
||||
nsCString m_desiredType; // The type it should be converted to.
|
||||
nsCString m_description; // For Content-Description header
|
||||
nsCString m_realName; // The name for the headers, if different
|
||||
// from the URL.
|
||||
nsCString m_encoding; // The encoding, once we've decided. */
|
||||
bool m_already_encoded_p; // If we attach a document that is already
|
||||
// encoded, we just pass it through.
|
||||
|
||||
bool m_decrypted_p; /* S/MIME -- when attaching a message that was
|
||||
encrypted, it's necessary to decrypt it first
|
||||
(since nobody but the original recipient can
|
||||
read it -- if you forward it to someone in the
|
||||
raw, it will be useless to them.) This flag
|
||||
indicates whether decryption occurred, so that
|
||||
libmsg can issue appropriate warnings about
|
||||
doing a cleartext forward of a message that was
|
||||
originally encrypted. */
|
||||
|
||||
bool mDeleteFile; // If this is true, Delete the file...its
|
||||
// NOT the original file!
|
||||
|
||||
bool mMHTMLPart; // This is true if its an MHTML part, otherwise, false
|
||||
bool mPartUserOmissionOverride; // This is true if the user send send the email without this part
|
||||
bool mMainBody; // True if this is a main body.
|
||||
// true if this should be sent as a link to a file.
|
||||
bool mSendViaCloud;
|
||||
nsString mHtmlAnnotation;
|
||||
nsCString mCloudProviderKey;
|
||||
nsCString mCloudUrl;
|
||||
int32_t mNodeIndex; //If this is an embedded image, this is the index of the
|
||||
// corresponding domNode in the editor's
|
||||
//GetEmbeddedObjects. Otherwise, it will be -1.
|
||||
//
|
||||
// Vars for analyzing file data...
|
||||
//
|
||||
uint32_t m_size; /* Some state used while filtering it */
|
||||
uint32_t m_unprintable_count;
|
||||
uint32_t m_highbit_count;
|
||||
uint32_t m_ctl_count;
|
||||
uint32_t m_null_count;
|
||||
uint8_t m_have_cr, m_have_lf, m_have_crlf;
|
||||
bool m_prev_char_was_cr;
|
||||
uint32_t m_current_column;
|
||||
uint32_t m_max_column;
|
||||
uint32_t m_lines;
|
||||
bool m_file_analyzed;
|
||||
|
||||
nsAutoPtr<MimeEncoder> m_encoder;
|
||||
nsCString m_uri; // original uri string
|
||||
|
||||
nsresult GetMimeDeliveryState(nsIMsgSend** _retval);
|
||||
nsresult SetMimeDeliveryState(nsIMsgSend* mime_delivery_state);
|
||||
private:
|
||||
nsCOMPtr<nsIMsgSend> m_mime_delivery_state;
|
||||
nsCOMPtr<nsIStreamConverter> m_mime_parser;
|
||||
nsCOMPtr<nsIChannel> m_converter_channel;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _nsMsgAttachmentHandler_H_ */
|
||||
693
mailnews/compose/src/nsMsgCompFields.cpp
Normal file
693
mailnews/compose/src/nsMsgCompFields.cpp
Normal file
|
|
@ -0,0 +1,693 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "nsMsgCompose.h"
|
||||
#include "nsMsgCompFields.h"
|
||||
#include "nsMsgI18N.h"
|
||||
#include "nsMsgCompUtils.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "prmem.h"
|
||||
#include "nsIFileChannel.h"
|
||||
#include "nsIMsgAttachment.h"
|
||||
#include "nsIMsgMdnGenerator.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsMsgMimeCID.h"
|
||||
#include "nsArrayEnumerator.h"
|
||||
#include "nsMemory.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/mailnews/MimeHeaderParser.h"
|
||||
|
||||
using namespace mozilla::mailnews;
|
||||
|
||||
struct HeaderInfo {
|
||||
/// Header name
|
||||
const char *mName;
|
||||
/// If true, nsMsgCompFields should reflect the raw header value instead of
|
||||
/// the unstructured header value.
|
||||
bool mStructured;
|
||||
};
|
||||
|
||||
// This is a mapping of the m_headers local set to the actual header name we
|
||||
// store on the structured header object.
|
||||
static HeaderInfo kHeaders[] = {
|
||||
{ "From", true },
|
||||
{ "Reply-To", true },
|
||||
{ "To", true },
|
||||
{ "Cc", true },
|
||||
{ "Bcc", true },
|
||||
{ nullptr, false }, // FCC
|
||||
{ nullptr, false }, // FCC2
|
||||
{ "Newsgroups", true },
|
||||
{ "Followup-To", true },
|
||||
{ "Subject", false },
|
||||
{ "Organization", false },
|
||||
{ "References", true },
|
||||
{ "X-Mozilla-News-Host", false },
|
||||
{ "X-Priority", false },
|
||||
{ nullptr, false }, // CHARACTER_SET
|
||||
{ "Message-Id", true },
|
||||
{ "X-Template", true },
|
||||
{ nullptr, false }, // DRAFT_ID
|
||||
{ "Content-Language", true },
|
||||
{ nullptr, false } // CREATOR IDENTITY KEY
|
||||
};
|
||||
|
||||
static_assert(MOZ_ARRAY_LENGTH(kHeaders) ==
|
||||
nsMsgCompFields::MSG_MAX_HEADERS,
|
||||
"These two arrays need to be kept in sync or bad things will happen!");
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMsgCompFields, nsIMsgCompFields, msgIStructuredHeaders,
|
||||
msgIWritableStructuredHeaders)
|
||||
|
||||
nsMsgCompFields::nsMsgCompFields()
|
||||
: mStructuredHeaders(do_CreateInstance(NS_ISTRUCTUREDHEADERS_CONTRACTID))
|
||||
{
|
||||
m_body.Truncate();
|
||||
|
||||
m_attachVCard = false;
|
||||
m_forcePlainText = false;
|
||||
m_useMultipartAlternative = false;
|
||||
m_returnReceipt = false;
|
||||
m_receiptHeaderType = nsIMsgMdnGenerator::eDntType;
|
||||
m_DSN = false;
|
||||
m_bodyIsAsciiOnly = false;
|
||||
m_forceMsgEncoding = false;
|
||||
m_needToCheckCharset = true;
|
||||
m_attachmentReminder = false;
|
||||
m_deliveryFormat = nsIMsgCompSendFormat::AskUser;
|
||||
|
||||
// Get the default charset from pref, use this as a mail charset.
|
||||
nsString charset;
|
||||
NS_GetLocalizedUnicharPreferenceWithDefault(nullptr, "mailnews.send_default_charset",
|
||||
NS_LITERAL_STRING("UTF-8"), charset);
|
||||
|
||||
LossyCopyUTF16toASCII(charset, m_DefaultCharacterSet); // Charsets better be ASCII
|
||||
SetCharacterSet(m_DefaultCharacterSet.get());
|
||||
}
|
||||
|
||||
nsMsgCompFields::~nsMsgCompFields()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult nsMsgCompFields::SetAsciiHeader(MsgHeaderID header, const char *value)
|
||||
{
|
||||
NS_ASSERTION(header >= 0 && header < MSG_MAX_HEADERS,
|
||||
"Invalid message header index!");
|
||||
|
||||
// If we are storing this on the structured header object, we need to set the
|
||||
// value on that object as well. Note that the value may be null, which we'll
|
||||
// take as an attempt to delete the header.
|
||||
const char *headerName = kHeaders[header].mName;
|
||||
if (headerName)
|
||||
{
|
||||
if (!value || !*value)
|
||||
return mStructuredHeaders->DeleteHeader(headerName);
|
||||
|
||||
return mStructuredHeaders->SetRawHeader(headerName,
|
||||
nsDependentCString(value), "UTF-8");
|
||||
}
|
||||
|
||||
// Not on the structurd header object, so save it locally.
|
||||
m_headers[header] = value;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const char* nsMsgCompFields::GetAsciiHeader(MsgHeaderID header)
|
||||
{
|
||||
NS_ASSERTION(header >= 0 && header < MSG_MAX_HEADERS,
|
||||
"Invalid message header index!");
|
||||
|
||||
const char *headerName = kHeaders[header].mName;
|
||||
if (headerName)
|
||||
{
|
||||
// We may be out of sync with the structured header object. Retrieve the
|
||||
// header value.
|
||||
if (kHeaders[header].mStructured)
|
||||
{
|
||||
mStructuredHeaders->GetRawHeader(headerName, m_headers[header]);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsString value;
|
||||
mStructuredHeaders->GetUnstructuredHeader(headerName, value);
|
||||
CopyUTF16toUTF8(value, m_headers[header]);
|
||||
}
|
||||
}
|
||||
|
||||
return m_headers[header].get();
|
||||
}
|
||||
|
||||
nsresult nsMsgCompFields::SetUnicodeHeader(MsgHeaderID header, const nsAString& value)
|
||||
{
|
||||
return SetAsciiHeader(header, NS_ConvertUTF16toUTF8(value).get());
|
||||
}
|
||||
|
||||
nsresult nsMsgCompFields::GetUnicodeHeader(MsgHeaderID header, nsAString& aResult)
|
||||
{
|
||||
CopyUTF8toUTF16(nsDependentCString(GetAsciiHeader(header)), aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetFrom(const nsAString &value)
|
||||
{
|
||||
return SetUnicodeHeader(MSG_FROM_HEADER_ID, value);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetFrom(nsAString &_retval)
|
||||
{
|
||||
return GetUnicodeHeader(MSG_FROM_HEADER_ID, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetReplyTo(const nsAString &value)
|
||||
{
|
||||
return SetUnicodeHeader(MSG_REPLY_TO_HEADER_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetReplyTo(nsAString &_retval)
|
||||
{
|
||||
return GetUnicodeHeader(MSG_REPLY_TO_HEADER_ID, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetTo(const nsAString &value)
|
||||
{
|
||||
return SetUnicodeHeader(MSG_TO_HEADER_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetTo(nsAString &_retval)
|
||||
{
|
||||
return GetUnicodeHeader(MSG_TO_HEADER_ID, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetCc(const nsAString &value)
|
||||
{
|
||||
return SetUnicodeHeader(MSG_CC_HEADER_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetCc(nsAString &_retval)
|
||||
{
|
||||
return GetUnicodeHeader(MSG_CC_HEADER_ID, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetBcc(const nsAString &value)
|
||||
{
|
||||
return SetUnicodeHeader(MSG_BCC_HEADER_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetBcc(nsAString &_retval)
|
||||
{
|
||||
return GetUnicodeHeader(MSG_BCC_HEADER_ID, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetFcc(const nsAString &value)
|
||||
{
|
||||
return SetUnicodeHeader(MSG_FCC_HEADER_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetFcc(nsAString &_retval)
|
||||
{
|
||||
return GetUnicodeHeader(MSG_FCC_HEADER_ID, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetFcc2(const nsAString &value)
|
||||
{
|
||||
return SetUnicodeHeader(MSG_FCC2_HEADER_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetFcc2(nsAString &_retval)
|
||||
{
|
||||
return GetUnicodeHeader(MSG_FCC2_HEADER_ID, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetNewsgroups(const nsAString &aValue)
|
||||
{
|
||||
return SetUnicodeHeader(MSG_NEWSGROUPS_HEADER_ID, aValue);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetNewsgroups(nsAString &aGroup)
|
||||
{
|
||||
return GetUnicodeHeader(MSG_NEWSGROUPS_HEADER_ID, aGroup);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetFollowupTo(const nsAString &aValue)
|
||||
{
|
||||
return SetUnicodeHeader(MSG_FOLLOWUP_TO_HEADER_ID, aValue);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetFollowupTo(nsAString &_retval)
|
||||
{
|
||||
return GetUnicodeHeader(MSG_FOLLOWUP_TO_HEADER_ID, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetHasRecipients(bool *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
*_retval = NS_SUCCEEDED(mime_sanity_check_fields_recipients(
|
||||
GetTo(), GetCc(), GetBcc(), GetNewsgroups()));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetCreatorIdentityKey(const char *value)
|
||||
{
|
||||
return SetAsciiHeader(MSG_CREATOR_IDENTITY_KEY_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetCreatorIdentityKey(char **_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
*_retval = strdup(GetAsciiHeader(MSG_CREATOR_IDENTITY_KEY_ID));
|
||||
return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetSubject(const nsAString &value)
|
||||
{
|
||||
return SetUnicodeHeader(MSG_SUBJECT_HEADER_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetSubject(nsAString &_retval)
|
||||
{
|
||||
return GetUnicodeHeader(MSG_SUBJECT_HEADER_ID, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetOrganization(const nsAString &value)
|
||||
{
|
||||
return SetUnicodeHeader(MSG_ORGANIZATION_HEADER_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetOrganization(nsAString &_retval)
|
||||
{
|
||||
return GetUnicodeHeader(MSG_ORGANIZATION_HEADER_ID, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetReferences(const char *value)
|
||||
{
|
||||
return SetAsciiHeader(MSG_REFERENCES_HEADER_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetReferences(char **_retval)
|
||||
{
|
||||
*_retval = strdup(GetAsciiHeader(MSG_REFERENCES_HEADER_ID));
|
||||
return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetNewspostUrl(const char *value)
|
||||
{
|
||||
return SetAsciiHeader(MSG_NEWSPOSTURL_HEADER_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetNewspostUrl(char **_retval)
|
||||
{
|
||||
*_retval = strdup(GetAsciiHeader(MSG_NEWSPOSTURL_HEADER_ID));
|
||||
return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetPriority(const char *value)
|
||||
{
|
||||
return SetAsciiHeader(MSG_PRIORITY_HEADER_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetPriority(char **_retval)
|
||||
{
|
||||
*_retval = strdup(GetAsciiHeader(MSG_PRIORITY_HEADER_ID));
|
||||
return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetCharacterSet(const char *value)
|
||||
{
|
||||
return SetAsciiHeader(MSG_CHARACTER_SET_HEADER_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetCharacterSet(char **_retval)
|
||||
{
|
||||
*_retval = strdup(GetAsciiHeader(MSG_CHARACTER_SET_HEADER_ID));
|
||||
return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetMessageId(const char *value)
|
||||
{
|
||||
return SetAsciiHeader(MSG_MESSAGE_ID_HEADER_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetMessageId(char **_retval)
|
||||
{
|
||||
*_retval = strdup(GetAsciiHeader(MSG_MESSAGE_ID_HEADER_ID));
|
||||
return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetTemplateName(const nsAString &value)
|
||||
{
|
||||
return SetUnicodeHeader(MSG_X_TEMPLATE_HEADER_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetTemplateName(nsAString &_retval)
|
||||
{
|
||||
return GetUnicodeHeader(MSG_X_TEMPLATE_HEADER_ID, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetDraftId(const char *value)
|
||||
{
|
||||
return SetAsciiHeader(MSG_DRAFT_ID_HEADER_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetDraftId(char **_retval)
|
||||
{
|
||||
*_retval = strdup(GetAsciiHeader(MSG_DRAFT_ID_HEADER_ID));
|
||||
return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetReturnReceipt(bool value)
|
||||
{
|
||||
m_returnReceipt = value;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetReturnReceipt(bool *_retval)
|
||||
{
|
||||
*_retval = m_returnReceipt;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetReceiptHeaderType(int32_t value)
|
||||
{
|
||||
m_receiptHeaderType = value;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetReceiptHeaderType(int32_t *_retval)
|
||||
{
|
||||
*_retval = m_receiptHeaderType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetDSN(bool value)
|
||||
{
|
||||
m_DSN = value;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetDSN(bool *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
*_retval = m_DSN;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetAttachVCard(bool value)
|
||||
{
|
||||
m_attachVCard = value;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetAttachVCard(bool *_retval)
|
||||
{
|
||||
*_retval = m_attachVCard;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetAttachmentReminder(bool *_retval)
|
||||
{
|
||||
*_retval = m_attachmentReminder;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetAttachmentReminder(bool value)
|
||||
{
|
||||
m_attachmentReminder = value;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetDeliveryFormat(int32_t value)
|
||||
{
|
||||
switch (value) {
|
||||
case nsIMsgCompSendFormat::AskUser:
|
||||
case nsIMsgCompSendFormat::PlainText:
|
||||
case nsIMsgCompSendFormat::HTML:
|
||||
case nsIMsgCompSendFormat::Both:
|
||||
m_deliveryFormat = value;
|
||||
break;
|
||||
default:
|
||||
m_deliveryFormat = nsIMsgCompSendFormat::AskUser;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetDeliveryFormat(int32_t *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
*_retval = m_deliveryFormat;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetContentLanguage(const char *value)
|
||||
{
|
||||
return SetAsciiHeader(MSG_CONTENT_LANGUAGE_ID, value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetContentLanguage(char **_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
*_retval = strdup(GetAsciiHeader(MSG_CONTENT_LANGUAGE_ID));
|
||||
return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetForcePlainText(bool value)
|
||||
{
|
||||
m_forcePlainText = value;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetForcePlainText(bool *_retval)
|
||||
{
|
||||
*_retval = m_forcePlainText;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetForceMsgEncoding(bool value)
|
||||
{
|
||||
m_forceMsgEncoding = value;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetForceMsgEncoding(bool *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
*_retval = m_forceMsgEncoding;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetUseMultipartAlternative(bool value)
|
||||
{
|
||||
m_useMultipartAlternative = value;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetUseMultipartAlternative(bool *_retval)
|
||||
{
|
||||
*_retval = m_useMultipartAlternative;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetBodyIsAsciiOnly(bool value)
|
||||
{
|
||||
m_bodyIsAsciiOnly = value;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetBodyIsAsciiOnly(bool *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
*_retval = m_bodyIsAsciiOnly;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetBody(const nsAString &value)
|
||||
{
|
||||
CopyUTF16toUTF8(value, m_body);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetBody(nsAString &_retval)
|
||||
{
|
||||
CopyUTF8toUTF16(m_body, _retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgCompFields::SetBody(const char *value)
|
||||
{
|
||||
if (value)
|
||||
m_body = value;
|
||||
else
|
||||
m_body.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const char* nsMsgCompFields::GetBody()
|
||||
{
|
||||
return m_body.get();
|
||||
}
|
||||
|
||||
/* readonly attribute nsISimpleEnumerator attachmentsArray; */
|
||||
NS_IMETHODIMP nsMsgCompFields::GetAttachments(nsISimpleEnumerator * *aAttachmentsEnum)
|
||||
{
|
||||
return aAttachmentsEnum ? NS_NewArrayEnumerator(aAttachmentsEnum, m_attachments) : NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
/* void addAttachment (in nsIMsgAttachment attachment); */
|
||||
NS_IMETHODIMP nsMsgCompFields::AddAttachment(nsIMsgAttachment *attachment)
|
||||
{
|
||||
int32_t attachmentCount = m_attachments.Count();
|
||||
|
||||
//Don't add twice the same attachment.
|
||||
nsCOMPtr<nsIMsgAttachment> element;
|
||||
bool sameUrl;
|
||||
for (int32_t i = 0; i < attachmentCount; i ++)
|
||||
{
|
||||
m_attachments[i]->EqualsUrl(attachment, &sameUrl);
|
||||
if (sameUrl)
|
||||
return NS_OK;
|
||||
}
|
||||
m_attachments.AppendObject(attachment);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void removeAttachment (in nsIMsgAttachment attachment); */
|
||||
NS_IMETHODIMP nsMsgCompFields::RemoveAttachment(nsIMsgAttachment *attachment)
|
||||
{
|
||||
int32_t attachmentCount = m_attachments.Count();
|
||||
|
||||
nsCOMPtr<nsIMsgAttachment> element;
|
||||
bool sameUrl;
|
||||
for (int32_t i = 0; i < attachmentCount; i ++)
|
||||
{
|
||||
m_attachments[i]->EqualsUrl(attachment, &sameUrl);
|
||||
if (sameUrl)
|
||||
{
|
||||
m_attachments.RemoveObjectAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void removeAttachments (); */
|
||||
NS_IMETHODIMP nsMsgCompFields::RemoveAttachments()
|
||||
{
|
||||
m_attachments.Clear();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// This method is called during the creation of a new window.
|
||||
NS_IMETHODIMP
|
||||
nsMsgCompFields::SplitRecipients(const nsAString &aRecipients,
|
||||
bool aEmailAddressOnly,
|
||||
uint32_t *aLength,
|
||||
char16_t*** aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLength);
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
*aLength = 0;
|
||||
*aResult = nullptr;
|
||||
|
||||
nsCOMArray<msgIAddressObject> header(EncodedHeader(NS_ConvertUTF16toUTF8(aRecipients)));
|
||||
nsTArray<nsString> results;
|
||||
if (aEmailAddressOnly)
|
||||
ExtractEmails(header, results);
|
||||
else
|
||||
ExtractDisplayAddresses(header, results);
|
||||
|
||||
uint32_t count = results.Length();
|
||||
char16_t **result = (char16_t **)NS_Alloc(sizeof(char16_t *) * count);
|
||||
for (uint32_t i = 0; i < count; ++i)
|
||||
result[i] = ToNewUnicode(results[i]);
|
||||
|
||||
*aResult = result;
|
||||
*aLength = count;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// This method is called during the sending of message from nsMsgCompose::CheckAndPopulateRecipients()
|
||||
nsresult nsMsgCompFields::SplitRecipientsEx(const nsAString &recipients,
|
||||
nsTArray<nsMsgRecipient> &aResult)
|
||||
{
|
||||
nsTArray<nsString> names, addresses;
|
||||
ExtractAllAddresses(EncodedHeader(NS_ConvertUTF16toUTF8(recipients)), names,
|
||||
addresses);
|
||||
|
||||
uint32_t numAddresses = names.Length();
|
||||
for (uint32_t i = 0; i < numAddresses; ++i)
|
||||
{
|
||||
nsMsgRecipient msgRecipient;
|
||||
msgRecipient.mEmail = addresses[i];
|
||||
msgRecipient.mName = names[i];
|
||||
aResult.AppendElement(msgRecipient);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::ConvertBodyToPlainText()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (!m_body.IsEmpty())
|
||||
{
|
||||
nsAutoString body;
|
||||
rv = GetBody(body);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
bool flowed, delsp, formatted, disallowBreaks;
|
||||
GetSerialiserFlags(GetCharacterSet(), &flowed, &delsp, &formatted, &disallowBreaks);
|
||||
rv = ConvertBufToPlainText(body, flowed, delsp, formatted, disallowBreaks);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = SetBody(body);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetSecurityInfo(nsISupports ** aSecurityInfo)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSecurityInfo);
|
||||
*aSecurityInfo = mSecureCompFields;
|
||||
NS_IF_ADDREF(*aSecurityInfo);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetSecurityInfo(nsISupports * aSecurityInfo)
|
||||
{
|
||||
mSecureCompFields = aSecurityInfo;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetDefaultCharacterSet(char * *aDefaultCharacterSet)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDefaultCharacterSet);
|
||||
*aDefaultCharacterSet = ToNewCString(m_DefaultCharacterSet);
|
||||
return *aDefaultCharacterSet ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::GetNeedToCheckCharset(bool *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
*_retval = m_needToCheckCharset;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgCompFields::SetNeedToCheckCharset(bool aCheck)
|
||||
{
|
||||
m_needToCheckCharset = aCheck;
|
||||
return NS_OK;
|
||||
}
|
||||
172
mailnews/compose/src/nsMsgCompFields.h
Normal file
172
mailnews/compose/src/nsMsgCompFields.h
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/* -*- 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 _MsgCompFields_H_
|
||||
#define _MsgCompFields_H_
|
||||
|
||||
#include "nsIMsgCompFields.h"
|
||||
#include "msgCore.h"
|
||||
#include "nsIAbCard.h"
|
||||
#include "nsIAbDirectory.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
struct nsMsgRecipient
|
||||
{
|
||||
nsString mName;
|
||||
nsString mEmail;
|
||||
nsCOMPtr<nsIAbCard> mCard;
|
||||
nsCOMPtr<nsIAbDirectory> mDirectory;
|
||||
};
|
||||
|
||||
/* Note that all the "Get" methods never return NULL (except in case of serious
|
||||
error, like an illegal parameter); rather, they return "" if things were set
|
||||
to NULL. This makes it real handy for the callers. */
|
||||
|
||||
class nsMsgCompFields : public nsIMsgCompFields {
|
||||
public:
|
||||
nsMsgCompFields();
|
||||
|
||||
/* this macro defines QueryInterface, AddRef and Release for this class */
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_FORWARD_MSGISTRUCTUREDHEADERS(mStructuredHeaders->)
|
||||
NS_FORWARD_MSGIWRITABLESTRUCTUREDHEADERS(mStructuredHeaders->)
|
||||
NS_DECL_NSIMSGCOMPFIELDS
|
||||
|
||||
// Allow the C++ utility methods for people who use a concrete class instead
|
||||
// of the interfaces.
|
||||
using msgIStructuredHeaders::GetAddressingHeader;
|
||||
using msgIWritableStructuredHeaders::SetAddressingHeader;
|
||||
|
||||
typedef enum MsgHeaderID
|
||||
{
|
||||
MSG_FROM_HEADER_ID = 0,
|
||||
MSG_REPLY_TO_HEADER_ID,
|
||||
MSG_TO_HEADER_ID,
|
||||
MSG_CC_HEADER_ID,
|
||||
MSG_BCC_HEADER_ID,
|
||||
MSG_FCC_HEADER_ID,
|
||||
MSG_FCC2_HEADER_ID,
|
||||
MSG_NEWSGROUPS_HEADER_ID,
|
||||
MSG_FOLLOWUP_TO_HEADER_ID,
|
||||
MSG_SUBJECT_HEADER_ID,
|
||||
MSG_ORGANIZATION_HEADER_ID,
|
||||
MSG_REFERENCES_HEADER_ID,
|
||||
MSG_NEWSPOSTURL_HEADER_ID,
|
||||
MSG_PRIORITY_HEADER_ID,
|
||||
MSG_CHARACTER_SET_HEADER_ID,
|
||||
MSG_MESSAGE_ID_HEADER_ID,
|
||||
MSG_X_TEMPLATE_HEADER_ID,
|
||||
MSG_DRAFT_ID_HEADER_ID,
|
||||
MSG_CONTENT_LANGUAGE_ID,
|
||||
MSG_CREATOR_IDENTITY_KEY_ID,
|
||||
|
||||
MSG_MAX_HEADERS //Must be the last one.
|
||||
} MsgHeaderID;
|
||||
|
||||
nsresult SetAsciiHeader(MsgHeaderID header, const char *value);
|
||||
const char* GetAsciiHeader(MsgHeaderID header); //just return the address of the internal header variable, don't dispose it
|
||||
|
||||
nsresult SetUnicodeHeader(MsgHeaderID header, const nsAString &value);
|
||||
nsresult GetUnicodeHeader(MsgHeaderID header, nsAString &_retval);
|
||||
|
||||
/* Convenience routines to get and set header's value...
|
||||
|
||||
IMPORTANT:
|
||||
all routines const char* GetXxx(void) will return a pointer to the header, please don't free it.
|
||||
*/
|
||||
|
||||
nsresult SetFrom(const char *value) {return SetAsciiHeader(MSG_FROM_HEADER_ID, value);}
|
||||
const char* GetFrom(void) {return GetAsciiHeader(MSG_FROM_HEADER_ID);}
|
||||
|
||||
nsresult SetReplyTo(const char *value) {return SetAsciiHeader(MSG_REPLY_TO_HEADER_ID, value);}
|
||||
const char* GetReplyTo() {return GetAsciiHeader(MSG_REPLY_TO_HEADER_ID);}
|
||||
|
||||
nsresult SetTo(const char *value) {return SetAsciiHeader(MSG_TO_HEADER_ID, value);}
|
||||
const char* GetTo() {return GetAsciiHeader(MSG_TO_HEADER_ID);}
|
||||
|
||||
nsresult SetCc(const char *value) {return SetAsciiHeader(MSG_CC_HEADER_ID, value);}
|
||||
const char* GetCc() {return GetAsciiHeader(MSG_CC_HEADER_ID);}
|
||||
|
||||
nsresult SetBcc(const char *value) {return SetAsciiHeader(MSG_BCC_HEADER_ID, value);}
|
||||
const char* GetBcc() {return GetAsciiHeader(MSG_BCC_HEADER_ID);}
|
||||
|
||||
nsresult SetFcc(const char *value) {return SetAsciiHeader(MSG_FCC_HEADER_ID, value);}
|
||||
const char* GetFcc() {return GetAsciiHeader(MSG_FCC_HEADER_ID);}
|
||||
|
||||
nsresult SetFcc2(const char *value) {return SetAsciiHeader(MSG_FCC2_HEADER_ID, value);}
|
||||
const char* GetFcc2() {return GetAsciiHeader(MSG_FCC2_HEADER_ID);}
|
||||
|
||||
nsresult SetNewsgroups(const char *aValue) {return SetAsciiHeader(MSG_NEWSGROUPS_HEADER_ID, aValue);}
|
||||
const char* GetNewsgroups() {return GetAsciiHeader(MSG_NEWSGROUPS_HEADER_ID);}
|
||||
|
||||
nsresult SetFollowupTo(const char *aValue) {return SetAsciiHeader(MSG_FOLLOWUP_TO_HEADER_ID, aValue);}
|
||||
const char* GetFollowupTo() {return GetAsciiHeader(MSG_FOLLOWUP_TO_HEADER_ID);}
|
||||
|
||||
nsresult SetSubject(const char *value) {return SetAsciiHeader(MSG_SUBJECT_HEADER_ID, value);}
|
||||
const char* GetSubject() {return GetAsciiHeader(MSG_SUBJECT_HEADER_ID);}
|
||||
|
||||
nsresult SetOrganization(const char *value) {return SetAsciiHeader(MSG_ORGANIZATION_HEADER_ID, value);}
|
||||
const char* GetOrganization() {return GetAsciiHeader(MSG_ORGANIZATION_HEADER_ID);}
|
||||
|
||||
const char* GetReferences() {return GetAsciiHeader(MSG_REFERENCES_HEADER_ID);}
|
||||
|
||||
const char* GetNewspostUrl() {return GetAsciiHeader(MSG_NEWSPOSTURL_HEADER_ID);}
|
||||
|
||||
const char* GetPriority() {return GetAsciiHeader(MSG_PRIORITY_HEADER_ID);}
|
||||
|
||||
const char* GetCharacterSet() {return GetAsciiHeader(MSG_CHARACTER_SET_HEADER_ID);}
|
||||
|
||||
const char* GetMessageId() {return GetAsciiHeader(MSG_MESSAGE_ID_HEADER_ID);}
|
||||
|
||||
nsresult SetTemplateName(const char *value) {return SetAsciiHeader(MSG_X_TEMPLATE_HEADER_ID, value);}
|
||||
const char* GetTemplateName() {return GetAsciiHeader(MSG_X_TEMPLATE_HEADER_ID);}
|
||||
|
||||
const char* GetDraftId() {return GetAsciiHeader(MSG_DRAFT_ID_HEADER_ID);}
|
||||
|
||||
const char* GetContentLanguage() {return GetAsciiHeader(MSG_CONTENT_LANGUAGE_ID);}
|
||||
|
||||
bool GetReturnReceipt() {return m_returnReceipt;}
|
||||
bool GetDSN() {return m_DSN;}
|
||||
bool GetAttachVCard() {return m_attachVCard;}
|
||||
bool GetAttachmentReminder() {return m_attachmentReminder;}
|
||||
int32_t GetDeliveryFormat() {return m_deliveryFormat;}
|
||||
bool GetForcePlainText() {return m_forcePlainText;}
|
||||
bool GetUseMultipartAlternative() {return m_useMultipartAlternative;}
|
||||
bool GetBodyIsAsciiOnly() {return m_bodyIsAsciiOnly;}
|
||||
bool GetForceMsgEncoding() {return m_forceMsgEncoding;}
|
||||
|
||||
nsresult SetBody(const char *value);
|
||||
const char* GetBody();
|
||||
|
||||
nsresult SplitRecipientsEx(const nsAString &recipients,
|
||||
nsTArray<nsMsgRecipient> &aResult);
|
||||
|
||||
protected:
|
||||
virtual ~nsMsgCompFields();
|
||||
nsCString m_headers[MSG_MAX_HEADERS];
|
||||
nsCString m_body;
|
||||
nsCOMArray<nsIMsgAttachment> m_attachments;
|
||||
bool m_attachVCard;
|
||||
bool m_attachmentReminder;
|
||||
int32_t m_deliveryFormat;
|
||||
bool m_forcePlainText;
|
||||
bool m_useMultipartAlternative;
|
||||
bool m_returnReceipt;
|
||||
bool m_DSN;
|
||||
bool m_bodyIsAsciiOnly;
|
||||
bool m_forceMsgEncoding;
|
||||
int32_t m_receiptHeaderType; /* receipt header type */
|
||||
nsCString m_DefaultCharacterSet;
|
||||
bool m_needToCheckCharset;
|
||||
|
||||
nsCOMPtr<nsISupports> mSecureCompFields;
|
||||
nsCOMPtr<msgIWritableStructuredHeaders> mStructuredHeaders;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _MsgCompFields_H_ */
|
||||
1803
mailnews/compose/src/nsMsgCompUtils.cpp
Normal file
1803
mailnews/compose/src/nsMsgCompUtils.cpp
Normal file
File diff suppressed because it is too large
Load diff
143
mailnews/compose/src/nsMsgCompUtils.h
Normal file
143
mailnews/compose/src/nsMsgCompUtils.h
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/* -*- 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 _nsMsgCompUtils_H_
|
||||
#define _nsMsgCompUtils_H_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsMsgSend.h"
|
||||
#include "nsMsgCompFields.h"
|
||||
#include "nsIMsgSend.h"
|
||||
#include "nsIMsgCompUtils.h"
|
||||
|
||||
class nsIPrompt;
|
||||
|
||||
#define ANY_SERVER "anyfolder://"
|
||||
|
||||
// these are msg hdr property names for storing the original
|
||||
// msg uri's and disposition(replied/forwarded) when queuing
|
||||
// messages to send later.
|
||||
#define ORIG_URI_PROPERTY "origURIs"
|
||||
#define QUEUED_DISPOSITION_PROPERTY "queuedDisposition"
|
||||
|
||||
class nsMsgCompUtils : public nsIMsgCompUtils
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMSGCOMPUTILS
|
||||
|
||||
nsMsgCompUtils();
|
||||
|
||||
private:
|
||||
virtual ~nsMsgCompUtils();
|
||||
};
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
//
|
||||
// Create a file spec or file name using the name passed
|
||||
// in as a template
|
||||
//
|
||||
nsresult nsMsgCreateTempFile(const char *tFileName, nsIFile **tFile);
|
||||
char *nsMsgCreateTempFileName(const char *tFileName);
|
||||
|
||||
|
||||
//
|
||||
// Various utilities for building parts of MIME encoded
|
||||
// messages during message composition
|
||||
//
|
||||
|
||||
nsresult mime_sanity_check_fields_recipients (
|
||||
const char *to,
|
||||
const char *cc,
|
||||
const char *bcc,
|
||||
const char *newsgroups);
|
||||
|
||||
nsresult mime_sanity_check_fields (
|
||||
const char *from,
|
||||
const char *reply_to,
|
||||
const char *to,
|
||||
const char *cc,
|
||||
const char *bcc,
|
||||
const char *fcc,
|
||||
const char *newsgroups,
|
||||
const char *followup_to,
|
||||
const char * /*subject*/,
|
||||
const char * /*references*/,
|
||||
const char * /*organization*/,
|
||||
const char * /*other_random_headers*/);
|
||||
|
||||
nsresult mime_generate_headers(nsIMsgCompFields *fields,
|
||||
nsMsgDeliverMode deliver_mode,
|
||||
msgIWritableStructuredHeaders *headers);
|
||||
|
||||
char *mime_make_separator(const char *prefix);
|
||||
char *mime_gen_content_id(uint32_t aPartNum, const char *aEmailAddress);
|
||||
|
||||
char *mime_generate_attachment_headers (
|
||||
const char *type,
|
||||
const char *type_param,
|
||||
const char *encoding,
|
||||
const char *description,
|
||||
const char *x_mac_type,
|
||||
const char *x_mac_creator,
|
||||
const char *real_name,
|
||||
const char *base_url,
|
||||
bool digest_p,
|
||||
nsMsgAttachmentHandler *ma,
|
||||
const char *attachmentCharset, // charset of the attachment (can be null)
|
||||
const char *bodyCharset, // charset of the main body
|
||||
bool bodyIsAsciiOnly,
|
||||
const char *content_id,
|
||||
bool aBodyDocument);
|
||||
|
||||
char *msg_generate_message_id (nsIMsgIdentity*);
|
||||
|
||||
bool mime_7bit_data_p (const char *string, uint32_t size);
|
||||
|
||||
char *mime_fix_header_1 (const char *string, bool addr_p, bool news_p);
|
||||
char *mime_fix_header (const char *string);
|
||||
char *mime_fix_addr_header (const char *string);
|
||||
char *mime_fix_news_header (const char *string);
|
||||
|
||||
bool mime_type_requires_b64_p (const char *type);
|
||||
bool mime_type_needs_charset (const char *type);
|
||||
|
||||
char *msg_make_filename_qtext(const char *srcText, bool stripCRLFs);
|
||||
|
||||
// Rip apart the URL and extract a reasonable value for the `real_name' slot.
|
||||
void msg_pick_real_name (nsMsgAttachmentHandler *attachment, const char16_t *proposedName, const char *charset);
|
||||
|
||||
//
|
||||
// Informational calls...
|
||||
//
|
||||
void nsMsgMIMESetConformToStandard (bool conform_p);
|
||||
bool nsMsgMIMEGetConformToStandard (void);
|
||||
|
||||
//
|
||||
// network service type calls...
|
||||
//
|
||||
nsresult nsMsgNewURL(nsIURI** aInstancePtrResult, const char * aSpec);
|
||||
bool nsMsgIsLocalFile(const char *url);
|
||||
char *nsMsgGetLocalFileFromURL(const char *url);
|
||||
|
||||
char *nsMsgParseURLHost(const char *url);
|
||||
|
||||
char *GenerateFileNameFromURI(nsIURI *aURL);
|
||||
|
||||
//
|
||||
// Folder calls...
|
||||
//
|
||||
void GetFolderURIFromUserPrefs(nsMsgDeliverMode aMode, nsIMsgIdentity *identity, nsCString& uri);
|
||||
|
||||
// Check if we should use format=flowed
|
||||
void GetSerialiserFlags(const char *charset, bool *flowed, bool *delsp, bool *formatted, bool *disallowBreaks);
|
||||
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
|
||||
#endif /* _nsMsgCompUtils_H_ */
|
||||
|
||||
6052
mailnews/compose/src/nsMsgCompose.cpp
Normal file
6052
mailnews/compose/src/nsMsgCompose.cpp
Normal file
File diff suppressed because it is too large
Load diff
246
mailnews/compose/src/nsMsgCompose.h
Normal file
246
mailnews/compose/src/nsMsgCompose.h
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
/* -*- 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 _nsMsgCompose_H_
|
||||
#define _nsMsgCompose_H_
|
||||
|
||||
#include "nsIMsgCompose.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsMsgCompFields.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIMsgQuote.h"
|
||||
#include "nsIMsgCopyServiceListener.h"
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsIAbDirectory.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsIMimeConverter.h"
|
||||
#include "nsIUnicodeDecoder.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "mozIDOMWindow.h"
|
||||
|
||||
// Forward declares
|
||||
class QuotingOutputStreamListener;
|
||||
class nsMsgComposeSendListener;
|
||||
class nsIEditorMailSupport;
|
||||
class nsIRDFService;
|
||||
class nsIArray;
|
||||
struct nsMsgMailList;
|
||||
|
||||
class nsMsgCompose : public nsIMsgCompose, public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
|
||||
nsMsgCompose();
|
||||
|
||||
/* this macro defines QueryInterface, AddRef and Release for this class */
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
/*** nsIMsgCompose pure virtual functions */
|
||||
NS_DECL_NSIMSGCOMPOSE
|
||||
|
||||
/* nsIMsgSendListener interface */
|
||||
NS_DECL_NSIMSGSENDLISTENER
|
||||
|
||||
protected:
|
||||
virtual ~nsMsgCompose();
|
||||
|
||||
// Deal with quoting issues...
|
||||
nsresult QuoteOriginalMessage(); // New template
|
||||
nsresult SetQuotingToFollow(bool aVal);
|
||||
nsresult ConvertHTMLToText(nsIFile *aSigFile, nsString &aSigData);
|
||||
nsresult ConvertTextToHTML(nsIFile *aSigFile, nsString &aSigData);
|
||||
bool IsEmbeddedObjectSafe(const char * originalScheme,
|
||||
const char * originalHost,
|
||||
const char * originalPath,
|
||||
nsIDOMNode * object);
|
||||
nsresult ResetUrisForEmbeddedObjects();
|
||||
nsresult TagEmbeddedObjects(nsIEditorMailSupport *aMailEditor);
|
||||
|
||||
nsCString mQuoteCharset;
|
||||
nsCString mOriginalMsgURI; // used so we can mark message disposition flags after we send the message
|
||||
|
||||
int32_t mWhatHolder;
|
||||
|
||||
nsresult LoadDataFromFile(nsIFile *file,
|
||||
nsString &sigData,
|
||||
bool aAllowUTF8 = true,
|
||||
bool aAllowUTF16 = true);
|
||||
|
||||
bool CheckIncludeSignaturePrefs(nsIMsgIdentity *identity);
|
||||
//m_folderName to store the value of the saved drafts folder.
|
||||
nsCString m_folderName;
|
||||
void InsertDivWrappedTextAtSelection(const nsAString &aText,
|
||||
const nsAString &classStr);
|
||||
|
||||
protected:
|
||||
nsresult CreateMessage(const char * originalMsgURI, MSG_ComposeType type, nsIMsgCompFields* compFields);
|
||||
void CleanUpRecipients(nsString& recipients);
|
||||
nsresult GetABDirAndMailLists(const nsACString& aDirUri,
|
||||
nsCOMArray<nsIAbDirectory>& aDirArray,
|
||||
nsTArray<nsMsgMailList>& aMailListArray);
|
||||
nsresult ResolveMailList(nsIAbDirectory* aMailList,
|
||||
nsCOMArray<nsIAbDirectory>& allDirectoriesArray,
|
||||
nsTArray<nsMsgMailList>& allMailListArray,
|
||||
nsTArray<nsMsgMailList>& mailListResolved,
|
||||
nsTArray<nsMsgRecipient>& aListMembers);
|
||||
nsresult TagConvertible(nsIDOMElement *node, int32_t *_retval);
|
||||
nsresult _NodeTreeConvertible(nsIDOMElement *node, int32_t *_retval);
|
||||
nsresult MoveToAboveQuote(void);
|
||||
nsresult MoveToBeginningOfDocument(void);
|
||||
nsresult MoveToEndOfDocument(void);
|
||||
nsresult ReplaceFileURLs(nsAutoString &sigData);
|
||||
nsresult DataURLForFileURL(const nsAString &aFileURL, nsAString &aDataURL);
|
||||
|
||||
// 3 = To, Cc, Bcc
|
||||
#define MAX_OF_RECIPIENT_ARRAY 3
|
||||
typedef nsTArray<nsMsgRecipient> RecipientsArray[MAX_OF_RECIPIENT_ARRAY];
|
||||
/**
|
||||
* This method parses the compose fields and associates email addresses with
|
||||
* the relevant cards from the address books.
|
||||
*/
|
||||
nsresult LookupAddressBook(RecipientsArray &recipientList);
|
||||
bool IsLastWindow();
|
||||
|
||||
// Helper function. Parameters are not checked.
|
||||
bool mConvertStructs; // for TagConvertible
|
||||
|
||||
nsCOMPtr<nsIEditor> m_editor;
|
||||
mozIDOMWindowProxy *m_window;
|
||||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
nsCOMPtr<nsIBaseWindow> m_baseWindow;
|
||||
nsMsgCompFields *m_compFields;
|
||||
nsCOMPtr<nsIMsgIdentity> m_identity;
|
||||
bool m_composeHTML;
|
||||
QuotingOutputStreamListener *mQuoteStreamListener;
|
||||
nsCOMPtr<nsIOutputStream> mBaseStream;
|
||||
|
||||
nsCOMPtr<nsIMsgSend> mMsgSend; // for composition back end
|
||||
nsCOMPtr<nsIMsgProgress> mProgress; // use by the back end to report progress to the front end
|
||||
|
||||
// Deal with quoting issues...
|
||||
nsString mCiteReference;
|
||||
nsCOMPtr<nsIMsgQuote> mQuote;
|
||||
bool mQuotingToFollow; // Quoting indicator
|
||||
MSG_ComposeType mType; // Message type
|
||||
bool mCharsetOverride;
|
||||
bool mAnswerDefaultCharset;
|
||||
bool mDeleteDraft;
|
||||
nsMsgDispositionState mDraftDisposition;
|
||||
nsCOMPtr <nsIMsgDBHdr> mOrigMsgHdr;
|
||||
|
||||
nsCString mSmtpPassword;
|
||||
nsCString mHtmlToQuote;
|
||||
|
||||
nsTObserverArray<nsCOMPtr<nsIMsgComposeStateListener> > mStateListeners;
|
||||
nsTObserverArray<nsCOMPtr<nsIMsgSendListener> > mExternalSendListeners;
|
||||
|
||||
bool mInsertingQuotedContent;
|
||||
MSG_DeliverMode mDeliverMode; // nsIMsgCompDeliverMode long.
|
||||
|
||||
friend class QuotingOutputStreamListener;
|
||||
friend class nsMsgComposeSendListener;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// THIS IS THE CLASS THAT IS THE STREAM Listener OF THE HTML OUPUT
|
||||
// FROM LIBMIME. THIS IS FOR QUOTING
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
class QuotingOutputStreamListener : public nsIMsgQuotingOutputStreamListener
|
||||
{
|
||||
public:
|
||||
QuotingOutputStreamListener(const char *originalMsgURI,
|
||||
nsIMsgDBHdr *origMsgHdr,
|
||||
bool quoteHeaders,
|
||||
bool headersOnly,
|
||||
nsIMsgIdentity *identity,
|
||||
nsIMsgQuote* msgQuote,
|
||||
bool charsetFixed,
|
||||
bool quoteOriginal,
|
||||
const nsACString& htmlToQuote);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIMSGQUOTINGOUTPUTSTREAMLISTENER
|
||||
|
||||
NS_IMETHOD SetComposeObj(nsIMsgCompose *obj);
|
||||
NS_IMETHOD ConvertToPlainText(bool formatflowed,
|
||||
bool delsp,
|
||||
bool formatted,
|
||||
bool disallowBreaks);
|
||||
NS_IMETHOD InsertToCompose(nsIEditor *aEditor, bool aHTMLEditor);
|
||||
NS_IMETHOD AppendToMsgBody(const nsCString &inStr);
|
||||
|
||||
private:
|
||||
virtual ~QuotingOutputStreamListener();
|
||||
nsWeakPtr mWeakComposeObj;
|
||||
nsString mMsgBody;
|
||||
nsString mCitePrefix;
|
||||
nsString mSignature;
|
||||
bool mQuoteHeaders;
|
||||
bool mHeadersOnly;
|
||||
bool mCharsetFixed;
|
||||
nsCOMPtr<nsIMsgQuote> mQuote;
|
||||
nsCOMPtr<nsIMimeHeaders> mHeaders;
|
||||
nsCOMPtr<nsIMsgIdentity> mIdentity;
|
||||
nsCOMPtr<nsIMsgDBHdr> mOrigMsgHdr;
|
||||
nsString mCiteReference;
|
||||
nsCOMPtr<nsIMimeConverter> mMimeConverter;
|
||||
nsCOMPtr<nsIUnicodeDecoder> mUnicodeDecoder;
|
||||
int32_t mUnicodeBufferCharacterLength;
|
||||
char16_t* mUnicodeConversionBuffer;
|
||||
bool mQuoteOriginal;
|
||||
nsCString mHtmlToQuote;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// This is the listener class for the send operation. We have to create this class
|
||||
// to listen for message send completion and eventually notify the caller
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
class nsMsgComposeSendListener : public nsIMsgComposeSendListener, public nsIMsgSendListener, public nsIMsgCopyServiceListener, public nsIWebProgressListener
|
||||
{
|
||||
public:
|
||||
nsMsgComposeSendListener(void);
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIMsgComposeSendListener interface
|
||||
NS_DECL_NSIMSGCOMPOSESENDLISTENER
|
||||
|
||||
// nsIMsgSendListener interface
|
||||
NS_DECL_NSIMSGSENDLISTENER
|
||||
|
||||
// nsIMsgCopyServiceListener interface
|
||||
NS_DECL_NSIMSGCOPYSERVICELISTENER
|
||||
|
||||
// nsIWebProgressListener interface
|
||||
NS_DECL_NSIWEBPROGRESSLISTENER
|
||||
|
||||
nsresult RemoveCurrentDraftMessage(nsIMsgCompose *compObj, bool calledByCopy);
|
||||
nsresult GetMsgFolder(nsIMsgCompose *compObj, nsIMsgFolder **msgFolder);
|
||||
|
||||
private:
|
||||
virtual ~nsMsgComposeSendListener();
|
||||
nsWeakPtr mWeakComposeObj;
|
||||
MSG_DeliverMode mDeliverMode;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* nsMsgMailList
|
||||
******************************************************************************/
|
||||
struct nsMsgMailList
|
||||
{
|
||||
explicit nsMsgMailList(nsIAbDirectory* directory);
|
||||
|
||||
nsString mName;
|
||||
nsString mDescription;
|
||||
nsCOMPtr<nsIAbDirectory> mDirectory;
|
||||
};
|
||||
|
||||
#endif /* _nsMsgCompose_H_ */
|
||||
125
mailnews/compose/src/nsMsgComposeContentHandler.cpp
Normal file
125
mailnews/compose/src/nsMsgComposeContentHandler.cpp
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "nsMsgComposeContentHandler.h"
|
||||
#include "nsMsgComposeService.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsMsgCompCID.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIURI.h"
|
||||
#include "plstr.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "mozIDOMWindow.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIMsgMailNewsUrl.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "nsIMsgIncomingServer.h"
|
||||
#include "nsIMsgAccountManager.h"
|
||||
|
||||
static NS_DEFINE_CID(kMsgComposeServiceCID, NS_MSGCOMPOSESERVICE_CID);
|
||||
|
||||
nsMsgComposeContentHandler::nsMsgComposeContentHandler()
|
||||
{
|
||||
}
|
||||
|
||||
// The following macro actually implement addref, release and query interface
|
||||
// for our component.
|
||||
NS_IMPL_ISUPPORTS(nsMsgComposeContentHandler, nsIContentHandler)
|
||||
|
||||
nsMsgComposeContentHandler::~nsMsgComposeContentHandler()
|
||||
{
|
||||
}
|
||||
|
||||
// Try to get an appropriate nsIMsgIdentity by going through the window, getting
|
||||
// the document's URI, then the corresponding nsIMsgDBHdr. Then find the server
|
||||
// associated with that header and get the first identity for it.
|
||||
nsresult nsMsgComposeContentHandler::GetBestIdentity(
|
||||
nsIInterfaceRequestor* aWindowContext, nsIMsgIdentity **aIdentity)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<mozIDOMWindowProxy> domWindow = do_GetInterface(aWindowContext);
|
||||
NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(domWindow);
|
||||
|
||||
nsAutoString documentURIString;
|
||||
rv = window->GetDoc()->GetDocumentURI(documentURIString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> documentURI;
|
||||
rv = NS_NewURI(getter_AddRefs(documentURI), documentURIString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIMsgMessageUrl> msgURI = do_QueryInterface(documentURI);
|
||||
if (!msgURI)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIMsgDBHdr> msgHdr;
|
||||
rv = msgURI->GetMessageHeader(getter_AddRefs(msgHdr));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIMsgFolder> folder;
|
||||
rv = msgHdr->GetFolder(getter_AddRefs(folder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// nsIMsgDBHdrs from .eml messages have a null folder, so bail out if that's
|
||||
// the case.
|
||||
if (!folder)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIMsgIncomingServer> server;
|
||||
rv = folder->GetServer(getter_AddRefs(server));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIMsgAccountManager> accountManager = do_GetService(
|
||||
NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = accountManager->GetFirstIdentityForServer(server, aIdentity);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgComposeContentHandler::HandleContent(const char * aContentType,
|
||||
nsIInterfaceRequestor* aWindowContext, nsIRequest *request)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (!request)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// First of all, get the content type and make sure it is a content type we
|
||||
// know how to handle!
|
||||
if (PL_strcasecmp(aContentType, "application/x-mailto") == 0) {
|
||||
nsCOMPtr<nsIMsgIdentity> identity;
|
||||
|
||||
if (aWindowContext)
|
||||
GetBestIdentity(aWindowContext, getter_AddRefs(identity));
|
||||
|
||||
nsCOMPtr<nsIURI> aUri;
|
||||
nsCOMPtr<nsIChannel> aChannel = do_QueryInterface(request);
|
||||
if(!aChannel) return NS_ERROR_FAILURE;
|
||||
|
||||
rv = aChannel->GetURI(getter_AddRefs(aUri));
|
||||
if (aUri)
|
||||
{
|
||||
nsCOMPtr<nsIMsgComposeService> composeService =
|
||||
do_GetService(kMsgComposeServiceCID, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = composeService->OpenComposeWindowWithURI(nullptr, aUri, identity);
|
||||
}
|
||||
} else {
|
||||
// The content-type was not application/x-mailto...
|
||||
return NS_ERROR_WONT_HANDLE_CONTENT;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
20
mailnews/compose/src/nsMsgComposeContentHandler.h
Normal file
20
mailnews/compose/src/nsMsgComposeContentHandler.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "nsIContentHandler.h"
|
||||
#include "nsIMsgIdentity.h"
|
||||
|
||||
class nsMsgComposeContentHandler : public nsIContentHandler
|
||||
{
|
||||
public:
|
||||
nsMsgComposeContentHandler();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONTENTHANDLER
|
||||
private:
|
||||
virtual ~nsMsgComposeContentHandler();
|
||||
nsresult GetBestIdentity(nsIInterfaceRequestor* aWindowContext,
|
||||
nsIMsgIdentity **identity);
|
||||
};
|
||||
170
mailnews/compose/src/nsMsgComposeParams.cpp
Normal file
170
mailnews/compose/src/nsMsgComposeParams.cpp
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "nsMsgComposeParams.h"
|
||||
|
||||
nsMsgComposeParams::nsMsgComposeParams() :
|
||||
mType(nsIMsgCompType::New),
|
||||
mFormat(nsIMsgCompFormat::Default),
|
||||
mBodyIsLink(false)
|
||||
{
|
||||
}
|
||||
|
||||
/* the following macro actually implement addref, release and query interface for our component. */
|
||||
NS_IMPL_ISUPPORTS(nsMsgComposeParams, nsIMsgComposeParams)
|
||||
|
||||
nsMsgComposeParams::~nsMsgComposeParams()
|
||||
{
|
||||
}
|
||||
|
||||
/* attribute MSG_ComposeType type; */
|
||||
NS_IMETHODIMP nsMsgComposeParams::GetType(MSG_ComposeType *aType)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aType);
|
||||
|
||||
*aType = mType;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgComposeParams::SetType(MSG_ComposeType aType)
|
||||
{
|
||||
mType = aType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute MSG_ComposeFormat format; */
|
||||
NS_IMETHODIMP nsMsgComposeParams::GetFormat(MSG_ComposeFormat *aFormat)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aFormat);
|
||||
|
||||
*aFormat = mFormat;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgComposeParams::SetFormat(MSG_ComposeFormat aFormat)
|
||||
{
|
||||
mFormat = aFormat;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute string originalMsgURI; */
|
||||
NS_IMETHODIMP nsMsgComposeParams::GetOriginalMsgURI(char * *aOriginalMsgURI)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOriginalMsgURI);
|
||||
|
||||
*aOriginalMsgURI = ToNewCString(mOriginalMsgUri);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgComposeParams::SetOriginalMsgURI(const char * aOriginalMsgURI)
|
||||
{
|
||||
mOriginalMsgUri = aOriginalMsgURI;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute nsIMsgIdentity identity; */
|
||||
NS_IMETHODIMP nsMsgComposeParams::GetIdentity(nsIMsgIdentity * *aIdentity)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIdentity);
|
||||
NS_IF_ADDREF(*aIdentity = mIdentity);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgComposeParams::SetIdentity(nsIMsgIdentity * aIdentity)
|
||||
{
|
||||
mIdentity = aIdentity;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgComposeParams::SetOrigMsgHdr(nsIMsgDBHdr *aMsgHdr)
|
||||
{
|
||||
mOrigMsgHdr = aMsgHdr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgComposeParams::GetOrigMsgHdr(nsIMsgDBHdr * *aMsgHdr)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aMsgHdr);
|
||||
NS_IF_ADDREF(*aMsgHdr = mOrigMsgHdr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute ACString htmlToQuote; */
|
||||
NS_IMETHODIMP nsMsgComposeParams::GetHtmlToQuote(nsACString& aHtmlToQuote)
|
||||
{
|
||||
aHtmlToQuote = mHtmlToQuote;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgComposeParams::SetHtmlToQuote(const nsACString& aHtmlToQuote)
|
||||
{
|
||||
mHtmlToQuote = aHtmlToQuote;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute nsIMsgCompFields composeFields; */
|
||||
NS_IMETHODIMP nsMsgComposeParams::GetComposeFields(nsIMsgCompFields * *aComposeFields)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aComposeFields);
|
||||
|
||||
if (mComposeFields)
|
||||
{
|
||||
*aComposeFields = mComposeFields;
|
||||
NS_ADDREF(*aComposeFields);
|
||||
}
|
||||
else
|
||||
*aComposeFields = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgComposeParams::SetComposeFields(nsIMsgCompFields * aComposeFields)
|
||||
{
|
||||
mComposeFields = aComposeFields;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute boolean bodyIsLink; */
|
||||
NS_IMETHODIMP nsMsgComposeParams::GetBodyIsLink(bool *aBodyIsLink)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aBodyIsLink);
|
||||
|
||||
*aBodyIsLink = mBodyIsLink;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgComposeParams::SetBodyIsLink(bool aBodyIsLink)
|
||||
{
|
||||
mBodyIsLink = aBodyIsLink;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute nsIMsgSendLisneter sendListener; */
|
||||
NS_IMETHODIMP nsMsgComposeParams::GetSendListener(nsIMsgSendListener * *aSendListener)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSendListener);
|
||||
|
||||
if (mSendListener)
|
||||
{
|
||||
*aSendListener = mSendListener;
|
||||
NS_ADDREF(*aSendListener);
|
||||
}
|
||||
else
|
||||
*aSendListener = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgComposeParams::SetSendListener(nsIMsgSendListener * aSendListener)
|
||||
{
|
||||
mSendListener = aSendListener;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute string smtpPassword; */
|
||||
NS_IMETHODIMP nsMsgComposeParams::GetSmtpPassword(char * *aSmtpPassword)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSmtpPassword);
|
||||
|
||||
*aSmtpPassword = ToNewCString(mSMTPPassword);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgComposeParams::SetSmtpPassword(const char * aSmtpPassword)
|
||||
{
|
||||
mSMTPPassword = aSmtpPassword;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
30
mailnews/compose/src/nsMsgComposeParams.h
Normal file
30
mailnews/compose/src/nsMsgComposeParams.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "nsIMsgComposeParams.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIMsgHdr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
class nsMsgComposeParams : public nsIMsgComposeParams
|
||||
{
|
||||
public:
|
||||
nsMsgComposeParams();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMSGCOMPOSEPARAMS
|
||||
|
||||
private:
|
||||
virtual ~nsMsgComposeParams();
|
||||
MSG_ComposeType mType;
|
||||
MSG_ComposeFormat mFormat;
|
||||
nsCString mOriginalMsgUri;
|
||||
nsCOMPtr<nsIMsgIdentity> mIdentity;
|
||||
nsCOMPtr<nsIMsgCompFields> mComposeFields;
|
||||
bool mBodyIsLink;
|
||||
nsCOMPtr<nsIMsgSendListener> mSendListener;
|
||||
nsCString mSMTPPassword;
|
||||
nsCOMPtr<nsIMsgDBHdr> mOrigMsgHdr;
|
||||
nsCString mHtmlToQuote;
|
||||
};
|
||||
46
mailnews/compose/src/nsMsgComposeProgressParams.cpp
Normal file
46
mailnews/compose/src/nsMsgComposeProgressParams.cpp
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "nsMsgComposeProgressParams.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMsgComposeProgressParams, nsIMsgComposeProgressParams)
|
||||
|
||||
nsMsgComposeProgressParams::nsMsgComposeProgressParams() :
|
||||
m_deliveryMode(nsIMsgCompDeliverMode::Now)
|
||||
{
|
||||
}
|
||||
|
||||
nsMsgComposeProgressParams::~nsMsgComposeProgressParams()
|
||||
{
|
||||
}
|
||||
|
||||
/* attribute wstring subject; */
|
||||
NS_IMETHODIMP nsMsgComposeProgressParams::GetSubject(char16_t * *aSubject)
|
||||
{
|
||||
NS_ENSURE_ARG(aSubject);
|
||||
|
||||
*aSubject = ToNewUnicode(m_subject);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgComposeProgressParams::SetSubject(const char16_t * aSubject)
|
||||
{
|
||||
m_subject = aSubject;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute MSG_DeliverMode deliveryMode; */
|
||||
NS_IMETHODIMP nsMsgComposeProgressParams::GetDeliveryMode(MSG_DeliverMode *aDeliveryMode)
|
||||
{
|
||||
NS_ENSURE_ARG(aDeliveryMode);
|
||||
|
||||
*aDeliveryMode = m_deliveryMode;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgComposeProgressParams::SetDeliveryMode(MSG_DeliverMode aDeliveryMode)
|
||||
{
|
||||
m_deliveryMode = aDeliveryMode;
|
||||
return NS_OK;
|
||||
}
|
||||
20
mailnews/compose/src/nsMsgComposeProgressParams.h
Normal file
20
mailnews/compose/src/nsMsgComposeProgressParams.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "nsIMsgComposeProgressParams.h"
|
||||
|
||||
class nsMsgComposeProgressParams : public nsIMsgComposeProgressParams
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMSGCOMPOSEPROGRESSPARAMS
|
||||
|
||||
nsMsgComposeProgressParams();
|
||||
|
||||
private:
|
||||
virtual ~nsMsgComposeProgressParams();
|
||||
nsString m_subject;
|
||||
MSG_DeliverMode m_deliveryMode;
|
||||
};
|
||||
1479
mailnews/compose/src/nsMsgComposeService.cpp
Normal file
1479
mailnews/compose/src/nsMsgComposeService.cpp
Normal file
File diff suppressed because it is too large
Load diff
68
mailnews/compose/src/nsMsgComposeService.h
Normal file
68
mailnews/compose/src/nsMsgComposeService.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#define MSGCOMP_TRACE_PERFORMANCE 1
|
||||
|
||||
#include "nsIMsgComposeService.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozIDOMWindow.h"
|
||||
#include "nsIXULWindow.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsIMimeStreamConverter.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
|
||||
#include "nsICommandLineHandler.h"
|
||||
#define ICOMMANDLINEHANDLER nsICommandLineHandler
|
||||
|
||||
class nsMsgComposeService :
|
||||
public nsIMsgComposeService,
|
||||
public ICOMMANDLINEHANDLER,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
nsMsgComposeService();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMSGCOMPOSESERVICE
|
||||
NS_DECL_NSICOMMANDLINEHANDLER
|
||||
|
||||
nsresult Init();
|
||||
void Reset();
|
||||
void DeleteCachedWindows();
|
||||
nsresult AddGlobalHtmlDomains();
|
||||
|
||||
private:
|
||||
virtual ~nsMsgComposeService();
|
||||
bool mLogComposePerformance;
|
||||
|
||||
nsresult LoadDraftOrTemplate(const nsACString& aMsgURI, nsMimeOutputType aOutType,
|
||||
nsIMsgIdentity * aIdentity, const char * aOriginalMsgURI,
|
||||
nsIMsgDBHdr * aOrigMsgHdr, bool aForwardInline,
|
||||
bool overrideComposeFormat,
|
||||
nsIMsgWindow *aMsgWindow);
|
||||
|
||||
nsresult RunMessageThroughMimeDraft(const nsACString& aMsgURI,
|
||||
nsMimeOutputType aOutType,
|
||||
nsIMsgIdentity * aIdentity,
|
||||
const char * aOriginalMsgURI,
|
||||
nsIMsgDBHdr * aOrigMsgHdr,
|
||||
bool aForwardInline,
|
||||
const nsAString &forwardTo,
|
||||
bool overrideComposeFormat,
|
||||
nsIMsgWindow *aMsgWindow);
|
||||
|
||||
// hash table mapping dom windows to nsIMsgCompose objects
|
||||
nsInterfaceHashtable<nsISupportsHashKey, nsIWeakReference> mOpenComposeWindows;
|
||||
|
||||
// When doing a reply and the settings are enabled, get the HTML of the selected text
|
||||
// in the original message window so that it can be quoted instead of the entire message.
|
||||
nsresult GetOrigWindowSelection(MSG_ComposeType type, nsIMsgWindow *aMsgWindow, nsACString& aSelHTML);
|
||||
|
||||
#ifdef MSGCOMP_TRACE_PERFORMANCE
|
||||
PRIntervalTime mStartTime;
|
||||
PRIntervalTime mPreviousTime;
|
||||
#endif
|
||||
};
|
||||
553
mailnews/compose/src/nsMsgCopy.cpp
Normal file
553
mailnews/compose/src/nsMsgCopy.cpp
Normal file
|
|
@ -0,0 +1,553 @@
|
|||
/* -*- 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/. */
|
||||
#include "nsMsgCopy.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsMsgFolderFlags.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "nsIMsgAccountManager.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "nsIMsgIncomingServer.h"
|
||||
#include "nsIMsgProtocolInfo.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIRDFResource.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsMsgCompUtils.h"
|
||||
#include "prcmon.h"
|
||||
#include "nsIMsgImapMailFolder.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIMsgWindow.h"
|
||||
#include "nsIMsgProgress.h"
|
||||
#include "nsComposeStrings.h"
|
||||
#include "prmem.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "nsArrayUtils.h"
|
||||
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// This is the listener class for the copy operation. We have to create this class
|
||||
// to listen for message copy completion and eventually notify the caller
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
NS_IMPL_ISUPPORTS(CopyListener, nsIMsgCopyServiceListener)
|
||||
|
||||
CopyListener::CopyListener(void)
|
||||
{
|
||||
mCopyInProgress = false;
|
||||
}
|
||||
|
||||
CopyListener::~CopyListener(void)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
CopyListener::OnStartCopy()
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
printf("CopyListener::OnStartCopy()\n");
|
||||
#endif
|
||||
|
||||
if (mComposeAndSend)
|
||||
mComposeAndSend->NotifyListenerOnStartCopy();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CopyListener::OnProgress(uint32_t aProgress, uint32_t aProgressMax)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
printf("CopyListener::OnProgress() %d of %d\n", aProgress, aProgressMax);
|
||||
#endif
|
||||
|
||||
if (mComposeAndSend)
|
||||
mComposeAndSend->NotifyListenerOnProgressCopy(aProgress, aProgressMax);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CopyListener::SetMessageKey(nsMsgKey aMessageKey)
|
||||
{
|
||||
if (mComposeAndSend)
|
||||
mComposeAndSend->SetMessageKey(aMessageKey);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CopyListener::GetMessageId(nsACString& aMessageId)
|
||||
{
|
||||
if (mComposeAndSend)
|
||||
mComposeAndSend->GetMessageId(aMessageId);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CopyListener::OnStopCopy(nsresult aStatus)
|
||||
{
|
||||
if (NS_SUCCEEDED(aStatus))
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
printf("CopyListener: SUCCESSFUL ON THE COPY OPERATION!\n");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
printf("CopyListener: COPY OPERATION FAILED!\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mCopyInProgress)
|
||||
{
|
||||
PR_CEnterMonitor(this);
|
||||
PR_CNotifyAll(this);
|
||||
mCopyInProgress = false;
|
||||
PR_CExitMonitor(this);
|
||||
}
|
||||
if (mComposeAndSend)
|
||||
mComposeAndSend->NotifyListenerOnStopCopy(aStatus);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CopyListener::SetMsgComposeAndSendObject(nsIMsgSend *obj)
|
||||
{
|
||||
if (obj)
|
||||
mComposeAndSend = obj;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// END END END END END END END END END END END END END END END
|
||||
// This is the listener class for the copy operation. We have to create this class
|
||||
// to listen for message copy completion and eventually notify the caller
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMsgCopy, nsIUrlListener)
|
||||
|
||||
nsMsgCopy::nsMsgCopy()
|
||||
{
|
||||
mFile = nullptr;
|
||||
mMode = nsIMsgSend::nsMsgDeliverNow;
|
||||
mSavePref = nullptr;
|
||||
}
|
||||
|
||||
nsMsgCopy::~nsMsgCopy()
|
||||
{
|
||||
PR_Free(mSavePref);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgCopy::StartCopyOperation(nsIMsgIdentity *aUserIdentity,
|
||||
nsIFile *aFile,
|
||||
nsMsgDeliverMode aMode,
|
||||
nsIMsgSend *aMsgSendObj,
|
||||
const char *aSavePref,
|
||||
nsIMsgDBHdr *aMsgToReplace)
|
||||
{
|
||||
nsCOMPtr<nsIMsgFolder> dstFolder;
|
||||
bool isDraft = false;
|
||||
bool waitForUrl = false;
|
||||
nsresult rv;
|
||||
|
||||
if (!aMsgSendObj)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
// Store away the server location...
|
||||
if (aSavePref)
|
||||
mSavePref = PL_strdup(aSavePref);
|
||||
|
||||
//
|
||||
// Vars for implementation...
|
||||
//
|
||||
|
||||
// QueueForLater (Outbox)
|
||||
if (aMode == nsIMsgSend::nsMsgQueueForLater ||
|
||||
aMode == nsIMsgSend::nsMsgDeliverBackground)
|
||||
{
|
||||
rv = GetUnsentMessagesFolder(aUserIdentity, getter_AddRefs(dstFolder), &waitForUrl);
|
||||
isDraft = false;
|
||||
if (!dstFolder || NS_FAILED(rv)) {
|
||||
return NS_MSG_UNABLE_TO_SEND_LATER;
|
||||
}
|
||||
}
|
||||
else if (aMode == nsIMsgSend::nsMsgSaveAsDraft) // SaveAsDraft (Drafts)
|
||||
{
|
||||
rv = GetDraftsFolder(aUserIdentity, getter_AddRefs(dstFolder), &waitForUrl);
|
||||
isDraft = true;
|
||||
if (!dstFolder || NS_FAILED(rv))
|
||||
return NS_MSG_UNABLE_TO_SAVE_DRAFT;
|
||||
}
|
||||
else if (aMode == nsIMsgSend::nsMsgSaveAsTemplate) // SaveAsTemplate (Templates)
|
||||
{
|
||||
rv = GetTemplatesFolder(aUserIdentity, getter_AddRefs(dstFolder), &waitForUrl);
|
||||
isDraft = false;
|
||||
if (!dstFolder || NS_FAILED(rv))
|
||||
return NS_MSG_UNABLE_TO_SAVE_TEMPLATE;
|
||||
}
|
||||
else // SaveInSentFolder (Sent) - nsMsgDeliverNow or nsMsgSendUnsent
|
||||
{
|
||||
rv = GetSentFolder(aUserIdentity, getter_AddRefs(dstFolder), &waitForUrl);
|
||||
isDraft = false;
|
||||
if (!dstFolder || NS_FAILED(rv))
|
||||
return NS_MSG_COULDNT_OPEN_FCC_FOLDER;
|
||||
}
|
||||
|
||||
nsCOMPtr <nsIMsgWindow> msgWindow;
|
||||
|
||||
if (aMsgSendObj)
|
||||
{
|
||||
nsCOMPtr <nsIMsgProgress> progress;
|
||||
aMsgSendObj->GetProgress(getter_AddRefs(progress));
|
||||
if (progress)
|
||||
progress->GetMsgWindow(getter_AddRefs(msgWindow));
|
||||
}
|
||||
|
||||
mMode = aMode;
|
||||
mFile = aFile;
|
||||
mDstFolder = dstFolder;
|
||||
mMsgToReplace = aMsgToReplace;
|
||||
mIsDraft = isDraft;
|
||||
mMsgSendObj = aMsgSendObj;
|
||||
if (!waitForUrl)
|
||||
{
|
||||
// cache info needed for DoCopy and call DoCopy when OnStopUrl is called.
|
||||
rv = DoCopy(aFile, dstFolder, aMsgToReplace, isDraft, msgWindow, aMsgSendObj);
|
||||
// N.B. "this" may be deleted when this call returns.
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgCopy::DoCopy(nsIFile *aDiskFile, nsIMsgFolder *dstFolder,
|
||||
nsIMsgDBHdr *aMsgToReplace, bool aIsDraft,
|
||||
nsIMsgWindow *msgWindow,
|
||||
nsIMsgSend *aMsgSendObj)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Check sanity
|
||||
if ((!aDiskFile) || (!dstFolder))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
//Call copyservice with dstFolder, disk file, and txnManager
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
RefPtr<CopyListener> copyListener = new CopyListener();
|
||||
if (!copyListener)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
copyListener->SetMsgComposeAndSendObject(aMsgSendObj);
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
|
||||
if (aIsDraft)
|
||||
{
|
||||
nsCOMPtr<nsIMsgImapMailFolder> imapFolder =
|
||||
do_QueryInterface(dstFolder);
|
||||
nsCOMPtr<nsIMsgAccountManager> accountManager =
|
||||
do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
bool shutdownInProgress = false;
|
||||
rv = accountManager->GetShutdownInProgress(&shutdownInProgress);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && shutdownInProgress && imapFolder)
|
||||
{
|
||||
// set the following only when we were in the middle of shutdown
|
||||
// process
|
||||
copyListener->mCopyInProgress = true;
|
||||
thread = do_GetCurrentThread();
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIMsgCopyService> copyService = do_GetService(NS_MSGCOPYSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = copyService->CopyFileMessage(aDiskFile, dstFolder, aMsgToReplace,
|
||||
aIsDraft,
|
||||
aIsDraft ? 0 : nsMsgMessageFlags::Read,
|
||||
EmptyCString(), copyListener, msgWindow);
|
||||
// copyListener->mCopyInProgress can only be set when we are in the
|
||||
// middle of the shutdown process
|
||||
while (copyListener->mCopyInProgress)
|
||||
{
|
||||
PR_CEnterMonitor(copyListener);
|
||||
PR_CWait(copyListener, PR_MicrosecondsToInterval(1000UL));
|
||||
PR_CExitMonitor(copyListener);
|
||||
if (thread)
|
||||
NS_ProcessPendingEvents(thread);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// nsIUrlListener methods
|
||||
NS_IMETHODIMP
|
||||
nsMsgCopy::OnStartRunningUrl(nsIURI * aUrl)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgCopy::OnStopRunningUrl(nsIURI * aUrl, nsresult aExitCode)
|
||||
{
|
||||
nsresult rv = aExitCode;
|
||||
if (NS_SUCCEEDED(aExitCode))
|
||||
{
|
||||
rv = DoCopy(mFile, mDstFolder, mMsgToReplace, mIsDraft, nullptr, mMsgSendObj);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgCopy::GetUnsentMessagesFolder(nsIMsgIdentity *userIdentity, nsIMsgFolder **folder, bool *waitForUrl)
|
||||
{
|
||||
nsresult ret = LocateMessageFolder(userIdentity, nsIMsgSend::nsMsgQueueForLater, mSavePref, folder);
|
||||
if (*folder)
|
||||
(*folder)->SetFlag(nsMsgFolderFlags::Queue);
|
||||
CreateIfMissing(folder, waitForUrl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgCopy::GetDraftsFolder(nsIMsgIdentity *userIdentity, nsIMsgFolder **folder, bool *waitForUrl)
|
||||
{
|
||||
nsresult ret = LocateMessageFolder(userIdentity, nsIMsgSend::nsMsgSaveAsDraft, mSavePref, folder);
|
||||
if (*folder)
|
||||
(*folder)->SetFlag(nsMsgFolderFlags::Drafts);
|
||||
CreateIfMissing(folder, waitForUrl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgCopy::GetTemplatesFolder(nsIMsgIdentity *userIdentity, nsIMsgFolder **folder, bool *waitForUrl)
|
||||
{
|
||||
nsresult ret = LocateMessageFolder(userIdentity, nsIMsgSend::nsMsgSaveAsTemplate, mSavePref, folder);
|
||||
if (*folder)
|
||||
(*folder)->SetFlag(nsMsgFolderFlags::Templates);
|
||||
CreateIfMissing(folder, waitForUrl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgCopy::GetSentFolder(nsIMsgIdentity *userIdentity, nsIMsgFolder **folder, bool *waitForUrl)
|
||||
{
|
||||
nsresult ret = LocateMessageFolder(userIdentity, nsIMsgSend::nsMsgDeliverNow, mSavePref, folder);
|
||||
if (*folder)
|
||||
{
|
||||
// If mSavePref is the same as the identity's fcc folder, set the sent flag.
|
||||
nsCString identityFccUri;
|
||||
userIdentity->GetFccFolder(identityFccUri);
|
||||
if (identityFccUri.Equals(mSavePref))
|
||||
(*folder)->SetFlag(nsMsgFolderFlags::SentMail);
|
||||
}
|
||||
CreateIfMissing(folder, waitForUrl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgCopy::CreateIfMissing(nsIMsgFolder **folder, bool *waitForUrl)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (folder && *folder)
|
||||
{
|
||||
nsCOMPtr<nsIMsgFolder> parent;
|
||||
(*folder)->GetParent(getter_AddRefs(parent));
|
||||
if (!parent)
|
||||
{
|
||||
nsCOMPtr<nsIFile> folderPath;
|
||||
// for local folders, path is to the berkeley mailbox.
|
||||
// for imap folders, path needs to have .msf appended to the name
|
||||
(*folder)->GetFilePath(getter_AddRefs(folderPath));
|
||||
|
||||
nsCOMPtr<nsIMsgIncomingServer> server;
|
||||
rv = (*folder)->GetServer(getter_AddRefs(server));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIMsgProtocolInfo> protocolInfo;
|
||||
rv = server->GetProtocolInfo(getter_AddRefs(protocolInfo));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool isAsyncFolder;
|
||||
rv = protocolInfo->GetFoldersCreatedAsync(&isAsyncFolder);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// if we can't get the path from the folder, then try to create the storage.
|
||||
// for imap, it doesn't matter if the .msf file exists - it still might not
|
||||
// exist on the server, so we should try to create it
|
||||
bool exists = false;
|
||||
if (!isAsyncFolder && folderPath)
|
||||
folderPath->Exists(&exists);
|
||||
if (!exists)
|
||||
{
|
||||
(*folder)->CreateStorageIfMissing(this);
|
||||
if (isAsyncFolder)
|
||||
*waitForUrl = true;
|
||||
|
||||
rv = NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Utility Functions for MsgFolders
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
nsresult
|
||||
LocateMessageFolder(nsIMsgIdentity *userIdentity,
|
||||
nsMsgDeliverMode aFolderType,
|
||||
const char *aFolderURI,
|
||||
nsIMsgFolder **msgFolder)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (!msgFolder) return NS_ERROR_NULL_POINTER;
|
||||
*msgFolder = nullptr;
|
||||
|
||||
if (!aFolderURI || !*aFolderURI)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
// as long as it doesn't start with anyfolder://
|
||||
if (PL_strncasecmp(ANY_SERVER, aFolderURI, strlen(aFolderURI)) != 0)
|
||||
{
|
||||
nsCOMPtr<nsIRDFService> rdf(do_GetService(kRDFServiceCID, &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// get the corresponding RDF resource
|
||||
// RDF will create the folder resource if it doesn't already exist
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
rv = rdf->GetResource(nsDependentCString(aFolderURI), getter_AddRefs(resource));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr <nsIMsgFolder> folderResource;
|
||||
folderResource = do_QueryInterface(resource, &rv);
|
||||
if (NS_SUCCEEDED(rv) && folderResource)
|
||||
{
|
||||
// don't check validity of folder - caller will handle creating it
|
||||
nsCOMPtr<nsIMsgIncomingServer> server;
|
||||
//make sure that folder hierarchy is built so that legitimate parent-child relationship is established
|
||||
rv = folderResource->GetServer(getter_AddRefs(server));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
return server->GetMsgFolderFromURI(folderResource, nsDependentCString(aFolderURI), msgFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t cnt = 0;
|
||||
uint32_t i;
|
||||
|
||||
if (!userIdentity)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
// get the account manager
|
||||
nsCOMPtr<nsIMsgAccountManager> accountManager =
|
||||
do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// If any folder will do, go look for one.
|
||||
nsCOMPtr<nsIArray> retval;
|
||||
accountManager->GetServersForIdentity(userIdentity, getter_AddRefs(retval));
|
||||
if (!retval) return NS_ERROR_FAILURE;
|
||||
|
||||
// Ok, we have to look through the servers and try to find the server that
|
||||
// has a valid folder of the type that interests us...
|
||||
rv = retval->GetLength(&cnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (i=0; i<cnt; i++) {
|
||||
// Now that we have the server...we need to get the named message folder
|
||||
nsCOMPtr<nsIMsgIncomingServer> inServer;
|
||||
|
||||
inServer = do_QueryElementAt(retval, i, &rv);
|
||||
if(NS_FAILED(rv) || (!inServer))
|
||||
continue;
|
||||
|
||||
//
|
||||
// If aFolderURI is passed in, then the user has chosen a specific
|
||||
// mail folder to save the message, but if it is null, just find the
|
||||
// first one and make that work. The folder is specified as a URI, like
|
||||
// the following:
|
||||
//
|
||||
// mailbox://nobody@Local Folders/Sent
|
||||
// imap://rhp@nsmail-2/Drafts
|
||||
// newsgroup://news.mozilla.org/netscape.test
|
||||
//
|
||||
nsCString serverURI;
|
||||
rv = inServer->GetServerURI(serverURI);
|
||||
if (NS_FAILED(rv) || serverURI.IsEmpty())
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsIMsgFolder> rootFolder;
|
||||
rv = inServer->GetRootFolder(getter_AddRefs(rootFolder));
|
||||
|
||||
if(NS_FAILED(rv) || (!rootFolder))
|
||||
continue;
|
||||
|
||||
// use the defaults by getting the folder by flags
|
||||
if (aFolderType == nsIMsgSend::nsMsgQueueForLater ||
|
||||
aFolderType == nsIMsgSend::nsMsgDeliverBackground)
|
||||
{
|
||||
// QueueForLater (Outbox)
|
||||
rootFolder->GetFolderWithFlags(nsMsgFolderFlags::Queue, msgFolder);
|
||||
}
|
||||
else if (aFolderType == nsIMsgSend::nsMsgSaveAsDraft) // SaveAsDraft (Drafts)
|
||||
{
|
||||
rootFolder->GetFolderWithFlags(nsMsgFolderFlags::Drafts, msgFolder);
|
||||
}
|
||||
else if (aFolderType == nsIMsgSend::nsMsgSaveAsTemplate) // SaveAsTemplate (Templates)
|
||||
{
|
||||
rootFolder->GetFolderWithFlags(nsMsgFolderFlags::Templates, msgFolder);
|
||||
}
|
||||
else // SaveInSentFolder (Sent) - nsMsgDeliverNow or nsMsgSendUnsent
|
||||
{
|
||||
rootFolder->GetFolderWithFlags(nsMsgFolderFlags::SentMail, msgFolder);
|
||||
}
|
||||
|
||||
if (*msgFolder)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//
|
||||
// Figure out if a folder is local or not and return a boolean to
|
||||
// say so.
|
||||
//
|
||||
nsresult
|
||||
MessageFolderIsLocal(nsIMsgIdentity *userIdentity,
|
||||
nsMsgDeliverMode aFolderType,
|
||||
const char *aFolderURI,
|
||||
bool *aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (!aFolderURI) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsCOMPtr <nsIURL> url = do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = url->SetSpec(nsDependentCString(aFolderURI));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
/* mailbox:/ means its local (on disk) */
|
||||
rv = url->SchemeIs("mailbox", aResult);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
120
mailnews/compose/src/nsMsgCopy.h
Normal file
120
mailnews/compose/src/nsMsgCopy.h
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/* -*- 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 _nsMsgCopy_H_
|
||||
#define _nsMsgCopy_H_
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nscore.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsMsgSend.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "nsITransactionManager.h"
|
||||
#include "nsIMsgCopyServiceListener.h"
|
||||
#include "nsIMsgCopyService.h"
|
||||
|
||||
// {0874C3B5-317D-11d3-8EFB-00A024A7D144}
|
||||
#define NS_IMSGCOPY_IID \
|
||||
{ 0x874c3b5, 0x317d, 0x11d3, \
|
||||
{ 0x8e, 0xfb, 0x0, 0xa0, 0x24, 0xa7, 0xd1, 0x44 } };
|
||||
|
||||
// Forward declarations...
|
||||
class nsMsgCopy;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// This is the listener class for the copy operation. We have to create this class
|
||||
// to listen for message copy completion and eventually notify the caller
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
class CopyListener : public nsIMsgCopyServiceListener
|
||||
{
|
||||
public:
|
||||
CopyListener(void);
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
NS_IMETHOD OnStartCopy() override;
|
||||
|
||||
NS_IMETHOD OnProgress(uint32_t aProgress, uint32_t aProgressMax) override;
|
||||
|
||||
NS_IMETHOD SetMessageKey(nsMsgKey aMessageKey) override;
|
||||
|
||||
NS_IMETHOD GetMessageId(nsACString& aMessageId) override;
|
||||
|
||||
NS_IMETHOD OnStopCopy(nsresult aStatus) override;
|
||||
|
||||
NS_IMETHOD SetMsgComposeAndSendObject(nsIMsgSend *obj);
|
||||
|
||||
bool mCopyInProgress;
|
||||
|
||||
private:
|
||||
virtual ~CopyListener();
|
||||
nsCOMPtr<nsIMsgSend> mComposeAndSend;
|
||||
};
|
||||
|
||||
//
|
||||
// This is a class that deals with processing remote attachments. It implements
|
||||
// an nsIStreamListener interface to deal with incoming data
|
||||
//
|
||||
class nsMsgCopy : public nsIUrlListener
|
||||
{
|
||||
public:
|
||||
nsMsgCopy();
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIURLLISTENER
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Object methods...
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
nsresult StartCopyOperation(nsIMsgIdentity *aUserIdentity,
|
||||
nsIFile *aFile,
|
||||
nsMsgDeliverMode aMode,
|
||||
nsIMsgSend *aMsgSendObj,
|
||||
const char *aSavePref,
|
||||
nsIMsgDBHdr *aMsgToReplace);
|
||||
|
||||
nsresult DoCopy(nsIFile *aDiskFile, nsIMsgFolder *dstFolder,
|
||||
nsIMsgDBHdr *aMsgToReplace, bool aIsDraft,
|
||||
nsIMsgWindow *msgWindow,
|
||||
nsIMsgSend *aMsgSendObj);
|
||||
|
||||
nsresult GetUnsentMessagesFolder(nsIMsgIdentity *userIdentity, nsIMsgFolder **msgFolder, bool *waitForUrl);
|
||||
nsresult GetDraftsFolder(nsIMsgIdentity *userIdentity, nsIMsgFolder **msgFolder, bool *waitForUrl);
|
||||
nsresult GetTemplatesFolder(nsIMsgIdentity *userIdentity, nsIMsgFolder **msgFolder, bool *waitForUrl);
|
||||
nsresult GetSentFolder(nsIMsgIdentity *userIdentity, nsIMsgFolder **msgFolder, bool *waitForUrl);
|
||||
nsresult CreateIfMissing(nsIMsgFolder **folder, bool *waitForUrl);
|
||||
|
||||
|
||||
//
|
||||
// Vars for implementation...
|
||||
//
|
||||
nsIFile *mFile; // the file we are sending...
|
||||
nsMsgDeliverMode mMode;
|
||||
nsCOMPtr<nsIMsgFolder> mDstFolder;
|
||||
nsCOMPtr<nsIMsgDBHdr> mMsgToReplace;
|
||||
bool mIsDraft;
|
||||
nsCOMPtr<nsIMsgSend> mMsgSendObj;
|
||||
char *mSavePref;
|
||||
|
||||
private:
|
||||
virtual ~nsMsgCopy();
|
||||
};
|
||||
|
||||
// Useful function for the back end...
|
||||
nsresult LocateMessageFolder(nsIMsgIdentity *userIdentity,
|
||||
nsMsgDeliverMode aFolderType,
|
||||
const char *aSaveURI,
|
||||
nsIMsgFolder **msgFolder);
|
||||
|
||||
nsresult MessageFolderIsLocal(nsIMsgIdentity *userIdentity,
|
||||
nsMsgDeliverMode aFolderType,
|
||||
const char *aSaveURI,
|
||||
bool *aResult);
|
||||
|
||||
#endif /* _nsMsgCopy_H_ */
|
||||
115
mailnews/compose/src/nsMsgPrompts.cpp
Normal file
115
mailnews/compose/src/nsMsgPrompts.cpp
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/* -*- 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/. */
|
||||
#include "nsMsgPrompts.h"
|
||||
|
||||
#include "nsMsgCopy.h"
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
#include "nsMsgCompCID.h"
|
||||
#include "nsComposeStrings.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
nsresult
|
||||
nsMsgGetMessageByName(const char16_t* aName, nsString& aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIStringBundleService> bundleService =
|
||||
mozilla::services::GetStringBundleService();
|
||||
NS_ENSURE_TRUE(bundleService, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
rv = bundleService->CreateBundle(
|
||||
"chrome://messenger/locale/messengercompose/composeMsgs.properties",
|
||||
getter_AddRefs(bundle));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return bundle->GetStringFromName(aName, getter_Copies(aResult));
|
||||
}
|
||||
|
||||
static nsresult
|
||||
nsMsgBuildMessageByName(const char16_t *aName, nsIFile *aFile, nsString& aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aFile);
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIStringBundleService> bundleService =
|
||||
mozilla::services::GetStringBundleService();
|
||||
NS_ENSURE_TRUE(bundleService, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
rv = bundleService->CreateBundle("chrome://messenger/locale/messengercompose/composeMsgs.properties", getter_AddRefs(bundle));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsString path;
|
||||
aFile->GetPath(path);
|
||||
|
||||
const char16_t *params[1] = {path.get()};
|
||||
return bundle->FormatStringFromName(aName, params, 1, getter_Copies(aResult));
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgBuildMessageWithFile(nsIFile *aFile, nsString& aResult)
|
||||
{
|
||||
return nsMsgBuildMessageByName(u"unableToOpenFile", aFile, aResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgBuildMessageWithTmpFile(nsIFile *aFile, nsString& aResult)
|
||||
{
|
||||
return nsMsgBuildMessageByName(u"unableToOpenTmpFile", aFile, aResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgDisplayMessageByName(nsIPrompt *aPrompt, const char16_t* aName, const char16_t *windowTitle)
|
||||
{
|
||||
nsString msg;
|
||||
nsMsgGetMessageByName(aName, msg);
|
||||
return nsMsgDisplayMessageByString(aPrompt, msg.get(), windowTitle);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgDisplayMessageByString(nsIPrompt * aPrompt, const char16_t * msg, const char16_t * windowTitle)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(msg);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIPrompt> prompt = aPrompt;
|
||||
|
||||
if (!prompt)
|
||||
{
|
||||
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
|
||||
if (wwatch)
|
||||
wwatch->GetNewPrompter(0, getter_AddRefs(prompt));
|
||||
}
|
||||
|
||||
if (prompt)
|
||||
rv = prompt->Alert(windowTitle, msg);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgAskBooleanQuestionByString(nsIPrompt * aPrompt, const char16_t * msg, bool *answer, const char16_t * windowTitle)
|
||||
{
|
||||
NS_ENSURE_TRUE(msg && *msg, NS_ERROR_INVALID_ARG);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIPrompt> dialog = aPrompt;
|
||||
|
||||
if (!dialog)
|
||||
{
|
||||
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
|
||||
if (wwatch)
|
||||
wwatch->GetNewPrompter(0, getter_AddRefs(dialog));
|
||||
}
|
||||
|
||||
if (dialog) {
|
||||
rv = dialog->Confirm(windowTitle, msg, answer);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
22
mailnews/compose/src/nsMsgPrompts.h
Normal file
22
mailnews/compose/src/nsMsgPrompts.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/* -*- 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 _nsMsgPrompts_H_
|
||||
#define _nsMsgPrompts_H_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsError.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsIPrompt;
|
||||
|
||||
nsresult nsMsgGetMessageByName(const char16_t* aName, nsString& aResult);
|
||||
nsresult nsMsgBuildMessageWithFile(nsIFile * aFile, nsString& aResult);
|
||||
nsresult nsMsgBuildMessageWithTmpFile(nsIFile * aFile, nsString& aResult);
|
||||
nsresult nsMsgDisplayMessageByName(nsIPrompt *aPrompt, const char16_t *aName, const char16_t *windowTitle = nullptr);
|
||||
nsresult nsMsgDisplayMessageByString(nsIPrompt * aPrompt, const char16_t * msg, const char16_t * windowTitle = nullptr);
|
||||
nsresult nsMsgAskBooleanQuestionByString(nsIPrompt * aPrompt, const char16_t * msg, bool *answer, const char16_t * windowTitle = nullptr);
|
||||
|
||||
#endif /* _nsMsgPrompts_H_ */
|
||||
233
mailnews/compose/src/nsMsgQuote.cpp
Normal file
233
mailnews/compose/src/nsMsgQuote.cpp
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#include "nsIURL.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIStreamConverter.h"
|
||||
#include "nsIStreamConverterService.h"
|
||||
#include "nsIMimeStreamConverter.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
#include "prprf.h"
|
||||
#include "nsMsgQuote.h"
|
||||
#include "nsMsgCompUtils.h"
|
||||
#include "nsIMsgMessageService.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsMsgMimeCID.h"
|
||||
#include "nsMsgCompCID.h"
|
||||
#include "nsMsgCompose.h"
|
||||
#include "nsMsgMailNewsUrl.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMsgQuoteListener, nsIMsgQuoteListener,
|
||||
nsIMimeStreamConverterListener)
|
||||
|
||||
nsMsgQuoteListener::nsMsgQuoteListener()
|
||||
{
|
||||
}
|
||||
|
||||
nsMsgQuoteListener::~nsMsgQuoteListener()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgQuoteListener::SetMsgQuote(nsIMsgQuote * msgQuote)
|
||||
{
|
||||
mMsgQuote = do_GetWeakReference(msgQuote);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgQuoteListener::GetMsgQuote(nsIMsgQuote ** aMsgQuote)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (aMsgQuote)
|
||||
{
|
||||
nsCOMPtr<nsIMsgQuote> msgQuote = do_QueryReferent(mMsgQuote);
|
||||
*aMsgQuote = msgQuote;
|
||||
NS_IF_ADDREF(*aMsgQuote);
|
||||
}
|
||||
else
|
||||
rv = NS_ERROR_NULL_POINTER;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgQuoteListener::OnHeadersReady(nsIMimeHeaders * headers)
|
||||
{
|
||||
nsCOMPtr<nsIMsgQuotingOutputStreamListener> quotingOutputStreamListener;
|
||||
nsCOMPtr<nsIMsgQuote> msgQuote = do_QueryReferent(mMsgQuote);
|
||||
|
||||
if (msgQuote)
|
||||
msgQuote->GetStreamListener(getter_AddRefs(quotingOutputStreamListener));
|
||||
|
||||
if (quotingOutputStreamListener)
|
||||
quotingOutputStreamListener->SetMimeHeaders(headers);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// Implementation...
|
||||
//
|
||||
nsMsgQuote::nsMsgQuote()
|
||||
{
|
||||
mQuoteHeaders = false;
|
||||
mQuoteListener = nullptr;
|
||||
}
|
||||
|
||||
nsMsgQuote::~nsMsgQuote()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMsgQuote, nsIMsgQuote, nsISupportsWeakReference)
|
||||
|
||||
NS_IMETHODIMP nsMsgQuote::GetStreamListener(nsIMsgQuotingOutputStreamListener ** aStreamListener)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (aStreamListener)
|
||||
{
|
||||
*aStreamListener = mStreamListener;
|
||||
NS_IF_ADDREF(*aStreamListener);
|
||||
}
|
||||
else
|
||||
rv = NS_ERROR_NULL_POINTER;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgQuote::QuoteMessage(const char *msgURI, bool quoteHeaders,
|
||||
nsIMsgQuotingOutputStreamListener * aQuoteMsgStreamListener,
|
||||
const char * aMsgCharSet, bool headersOnly,
|
||||
nsIMsgDBHdr *aMsgHdr)
|
||||
{
|
||||
nsresult rv;
|
||||
if (!msgURI)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
mQuoteHeaders = quoteHeaders;
|
||||
mStreamListener = aQuoteMsgStreamListener;
|
||||
|
||||
nsAutoCString msgUri(msgURI);
|
||||
bool fileUrl = !strncmp(msgURI, "file:", 5);
|
||||
bool forwardedMessage = PL_strstr(msgURI, "&realtype=message/rfc822") != nullptr;
|
||||
nsCOMPtr<nsIURI> aURL;
|
||||
if (fileUrl)
|
||||
{
|
||||
msgUri.Replace(0, 5, NS_LITERAL_CSTRING("mailbox:"));
|
||||
msgUri.AppendLiteral("?number=0");
|
||||
rv = NS_NewURI(getter_AddRefs(aURL), msgUri);
|
||||
nsCOMPtr<nsIMsgMessageUrl> mailUrl(do_QueryInterface(aURL));
|
||||
if (mailUrl)
|
||||
mailUrl->SetMessageHeader(aMsgHdr);
|
||||
}
|
||||
else if (forwardedMessage)
|
||||
rv = NS_NewURI(getter_AddRefs(aURL), msgURI);
|
||||
else
|
||||
{
|
||||
nsCOMPtr <nsIMsgMessageService> msgService;
|
||||
rv = GetMessageServiceFromURI(nsDependentCString(msgURI), getter_AddRefs(msgService));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = msgService->GetUrlForUri(msgURI, getter_AddRefs(aURL), nullptr);
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr <nsIURL> mailNewsUrl = do_QueryInterface(aURL, &rv);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsAutoCString queryPart;
|
||||
rv = mailNewsUrl->GetQuery(queryPart);
|
||||
if (!queryPart.IsEmpty())
|
||||
queryPart.Append('&');
|
||||
|
||||
if (headersOnly) /* We don't need to quote the message body but we still need to extract the headers */
|
||||
queryPart.Append("header=only");
|
||||
else if (quoteHeaders)
|
||||
queryPart.Append("header=quote");
|
||||
else
|
||||
queryPart.Append("header=quotebody");
|
||||
rv = mailNewsUrl->SetQuery(queryPart);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
// if we were given a non empty charset, then use it
|
||||
if (aMsgCharSet && *aMsgCharSet)
|
||||
{
|
||||
nsCOMPtr<nsIMsgI18NUrl> i18nUrl (do_QueryInterface(aURL));
|
||||
if (i18nUrl)
|
||||
i18nUrl->SetCharsetOverRide(aMsgCharSet);
|
||||
}
|
||||
|
||||
mQuoteListener = do_CreateInstance(NS_MSGQUOTELISTENER_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
mQuoteListener->SetMsgQuote(this);
|
||||
|
||||
// funky magic go get the isupports for this class which inherits from multiple interfaces.
|
||||
nsISupports * supports;
|
||||
QueryInterface(NS_GET_IID(nsISupports), (void **) &supports);
|
||||
nsCOMPtr<nsISupports> quoteSupport = supports;
|
||||
NS_IF_RELEASE(supports);
|
||||
|
||||
// now we want to create a necko channel for this url and we want to open it
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan(
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> systemPrincipal;
|
||||
rv = secMan->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
mQuoteChannel = nullptr;
|
||||
nsCOMPtr<nsIIOService> netService = mozilla::services::GetIOService();
|
||||
NS_ENSURE_TRUE(netService, NS_ERROR_UNEXPECTED);
|
||||
rv = netService->NewChannelFromURI2(aURL,
|
||||
nullptr,
|
||||
systemPrincipal,
|
||||
nullptr,
|
||||
nsILoadInfo::SEC_NORMAL,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
getter_AddRefs(mQuoteChannel));
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsCOMPtr<nsISupports> ctxt = do_QueryInterface(aURL);
|
||||
|
||||
nsCOMPtr<nsIStreamConverterService> streamConverterService =
|
||||
do_GetService("@mozilla.org/streamConverters;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsCOMPtr<nsIStreamListener> convertedListener;
|
||||
rv = streamConverterService->AsyncConvertData("message/rfc822",
|
||||
"application/vnd.mozilla.xul+xml",
|
||||
mStreamListener,
|
||||
quoteSupport,
|
||||
getter_AddRefs(convertedListener));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// now try to open the channel passing in our display consumer as the listener
|
||||
rv = mQuoteChannel->AsyncOpen(convertedListener, ctxt);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgQuote::GetQuoteListener(nsIMimeStreamConverterListener** aQuoteListener)
|
||||
{
|
||||
if (!aQuoteListener || !mQuoteListener)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*aQuoteListener = mQuoteListener;
|
||||
NS_ADDREF(*aQuoteListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgQuote::GetQuoteChannel(nsIChannel** aQuoteChannel)
|
||||
{
|
||||
if (!aQuoteChannel || !mQuoteChannel)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*aQuoteChannel = mQuoteChannel;
|
||||
NS_ADDREF(*aQuoteChannel);
|
||||
return NS_OK;
|
||||
}
|
||||
52
mailnews/compose/src/nsMsgQuote.h
Normal file
52
mailnews/compose/src/nsMsgQuote.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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 __nsMsgQuote_h__
|
||||
#define __nsMsgQuote_h__
|
||||
|
||||
#include "nsIMsgQuote.h"
|
||||
#include "nsIMsgMessageService.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIMimeStreamConverter.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
class nsMsgQuote;
|
||||
|
||||
class nsMsgQuoteListener: public nsIMsgQuoteListener
|
||||
{
|
||||
public:
|
||||
nsMsgQuoteListener();
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
// nsIMimeStreamConverterListener support
|
||||
NS_DECL_NSIMIMESTREAMCONVERTERLISTENER
|
||||
NS_DECL_NSIMSGQUOTELISTENER
|
||||
|
||||
private:
|
||||
virtual ~nsMsgQuoteListener();
|
||||
nsWeakPtr mMsgQuote;
|
||||
};
|
||||
|
||||
class nsMsgQuote: public nsIMsgQuote, public nsSupportsWeakReference {
|
||||
public:
|
||||
nsMsgQuote();
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIMSGQUOTE
|
||||
|
||||
private:
|
||||
virtual ~nsMsgQuote();
|
||||
//
|
||||
// Implementation data...
|
||||
//
|
||||
nsCOMPtr<nsIMsgQuotingOutputStreamListener> mStreamListener;
|
||||
bool mQuoteHeaders;
|
||||
nsCOMPtr<nsIMsgQuoteListener> mQuoteListener;
|
||||
nsCOMPtr<nsIChannel> mQuoteChannel;
|
||||
};
|
||||
|
||||
#endif /* __nsMsgQuote_h__ */
|
||||
5218
mailnews/compose/src/nsMsgSend.cpp
Normal file
5218
mailnews/compose/src/nsMsgSend.cpp
Normal file
File diff suppressed because it is too large
Load diff
405
mailnews/compose/src/nsMsgSend.h
Normal file
405
mailnews/compose/src/nsMsgSend.h
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
/* -*- 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
|
||||
retreive 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 "nsIDOMNode.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"
|
||||
|
||||
//
|
||||
// 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 char16_t* aMsgName, char16_t **aString);
|
||||
|
||||
nsresult DoFcc();
|
||||
nsresult StartMessageCopyOperation(nsIFile *aFileSpec,
|
||||
nsMsgDeliverMode mode,
|
||||
const nsCString& dest_uri);
|
||||
|
||||
|
||||
nsresult SendToMagicFolder(nsMsgDeliverMode flag);
|
||||
|
||||
// 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 char *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(nsIDOMNode *node, 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;
|
||||
nsCString 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__ */
|
||||
1552
mailnews/compose/src/nsMsgSendLater.cpp
Normal file
1552
mailnews/compose/src/nsMsgSendLater.cpp
Normal file
File diff suppressed because it is too large
Load diff
144
mailnews/compose/src/nsMsgSendLater.h
Normal file
144
mailnews/compose/src/nsMsgSendLater.h
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/* -*- 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 _nsMsgSendLater_H_
|
||||
#define _nsMsgSendLater_H_
|
||||
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "nsIMsgSendListener.h"
|
||||
#include "nsIMsgSendLaterListener.h"
|
||||
#include "nsIMsgSendLater.h"
|
||||
#include "nsIMsgStatusFeedback.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIMsgShutdown.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// This is the listener class for the send operation. We have to create this class
|
||||
// to listen for message send completion and eventually notify the caller
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
class nsMsgSendLater;
|
||||
|
||||
class SendOperationListener : public nsIMsgSendListener,
|
||||
public nsIMsgCopyServiceListener
|
||||
{
|
||||
public:
|
||||
SendOperationListener(nsMsgSendLater *aSendLater);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMSGSENDLISTENER
|
||||
NS_DECL_NSIMSGCOPYSERVICELISTENER
|
||||
|
||||
private:
|
||||
virtual ~SendOperationListener();
|
||||
nsMsgSendLater *mSendLater;
|
||||
};
|
||||
|
||||
class nsMsgSendLater: public nsIMsgSendLater,
|
||||
public nsIFolderListener,
|
||||
public nsIObserver,
|
||||
public nsIUrlListener,
|
||||
public nsIMsgShutdownTask
|
||||
|
||||
{
|
||||
public:
|
||||
nsMsgSendLater();
|
||||
nsresult Init();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMSGSENDLATER
|
||||
NS_DECL_NSIFOLDERLISTENER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSIURLLISTENER
|
||||
NS_DECL_NSIMSGSHUTDOWNTASK
|
||||
|
||||
// Methods needed for implementing interface...
|
||||
nsresult StartNextMailFileSend(nsresult prevStatus);
|
||||
nsresult CompleteMailFileSend();
|
||||
|
||||
nsresult DeleteCurrentMessage();
|
||||
nsresult SetOrigMsgDisposition();
|
||||
// Necessary for creating a valid list of recipients
|
||||
nsresult BuildHeaders();
|
||||
nsresult DeliverQueuedLine(char *line, int32_t length);
|
||||
nsresult RebufferLeftovers(char *startBuf, uint32_t aLen);
|
||||
nsresult BuildNewBuffer(const char* aBuf, uint32_t aCount, uint32_t *totalBufSize);
|
||||
|
||||
// methods for listener array processing...
|
||||
void NotifyListenersOnStartSending(uint32_t aTotalMessageCount);
|
||||
void NotifyListenersOnMessageStartSending(uint32_t aCurrentMessage,
|
||||
uint32_t aTotalMessage,
|
||||
nsIMsgIdentity *aIdentity);
|
||||
void NotifyListenersOnProgress(uint32_t aCurrentMessage,
|
||||
uint32_t aTotalMessage,
|
||||
uint32_t aSendPercent,
|
||||
uint32_t aCopyPercent);
|
||||
void NotifyListenersOnMessageSendError(uint32_t aCurrentMessage,
|
||||
nsresult aStatus,
|
||||
const char16_t *aMsg);
|
||||
void EndSendMessages(nsresult aStatus, const char16_t *aMsg,
|
||||
uint32_t aTotalTried, uint32_t aSuccessful);
|
||||
|
||||
bool OnSendStepFinished(nsresult aStatus);
|
||||
void OnCopyStepFinished(nsresult aStatus);
|
||||
|
||||
// counters and things for enumeration
|
||||
uint32_t mTotalSentSuccessfully;
|
||||
uint32_t mTotalSendCount;
|
||||
nsCOMArray<nsIMsgDBHdr> mMessagesToSend;
|
||||
nsCOMPtr<nsISimpleEnumerator> mEnumerator;
|
||||
nsCOMPtr<nsIMsgFolder> mMessageFolder;
|
||||
nsCOMPtr<nsIMsgStatusFeedback> mFeedback;
|
||||
|
||||
// Private Information
|
||||
private:
|
||||
virtual ~nsMsgSendLater();
|
||||
nsresult GetIdentityFromKey(const char *aKey, nsIMsgIdentity **aIdentity);
|
||||
nsresult ReparseDBIfNeeded(nsIUrlListener *aListener);
|
||||
nsresult InternalSendMessages(bool aUserInitiated,
|
||||
nsIMsgIdentity *aIdentity);
|
||||
|
||||
nsTObserverArray<nsCOMPtr<nsIMsgSendLaterListener> > mListenerArray;
|
||||
nsCOMPtr<nsIMsgDBHdr> mMessage;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
bool mTimerSet;
|
||||
nsCOMPtr<nsIUrlListener> mShutdownListener;
|
||||
|
||||
//
|
||||
// File output stuff...
|
||||
//
|
||||
nsCOMPtr<nsIFile> mTempFile;
|
||||
nsCOMPtr<nsIOutputStream> mOutFile;
|
||||
|
||||
// For building headers and stream parsing...
|
||||
char *m_to;
|
||||
char *m_bcc;
|
||||
char *m_fcc;
|
||||
char *m_newsgroups;
|
||||
char *m_newshost;
|
||||
char *m_headers;
|
||||
int32_t m_flags;
|
||||
int32_t m_headersFP;
|
||||
bool m_inhead;
|
||||
int32_t m_headersPosition;
|
||||
int32_t m_bytesRead;
|
||||
int32_t m_position;
|
||||
int32_t m_flagsPosition;
|
||||
int32_t m_headersSize;
|
||||
char *mLeftoverBuffer;
|
||||
char *mIdentityKey;
|
||||
char *mAccountKey;
|
||||
|
||||
bool mSendingMessages;
|
||||
bool mUserInitiated;
|
||||
nsCOMPtr<nsIMsgIdentity> mIdentity;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _nsMsgSendLater_H_ */
|
||||
779
mailnews/compose/src/nsMsgSendPart.cpp
Normal file
779
mailnews/compose/src/nsMsgSendPart.cpp
Normal file
|
|
@ -0,0 +1,779 @@
|
|||
/* -*- 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/. */
|
||||
#include "nsMsgLocalFolderHdrs.h"
|
||||
#include "nsMsgSend.h"
|
||||
#include "nsMsgSendPart.h"
|
||||
#include "nsIMimeConverter.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsMsgI18N.h"
|
||||
#include "nsMsgCompUtils.h"
|
||||
#include "nsMsgMimeCID.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "prmem.h"
|
||||
#include "nsMsgPrompts.h"
|
||||
#include "nsNativeCharsetUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsReadLine.h"
|
||||
#include "nsILineInputStream.h"
|
||||
#include "nsComposeStrings.h"
|
||||
#include "mozilla/mailnews/MimeEncoder.h"
|
||||
|
||||
static char *mime_mailto_stream_read_buffer = 0;
|
||||
|
||||
int32_t nsMsgSendPart::M_counter = 0;
|
||||
|
||||
nsMsgSendPart::nsMsgSendPart(nsIMsgSend* state, const char *part_charset)
|
||||
{
|
||||
PL_strncpy(m_charset_name, (part_charset ? part_charset : "UTF-8"), sizeof(m_charset_name)-1);
|
||||
m_charset_name[sizeof(m_charset_name)-1] = '\0';
|
||||
m_children = nullptr;
|
||||
m_numchildren = 0;
|
||||
// if we're not added as a child, the default part number will be "1".
|
||||
m_partNum = "1";
|
||||
SetMimeDeliveryState(state);
|
||||
|
||||
m_parent = nullptr;
|
||||
m_buffer = nullptr;
|
||||
m_type = nullptr;
|
||||
m_other = nullptr;
|
||||
m_strip_sensitive_headers = false;
|
||||
|
||||
m_firstBlock = false;
|
||||
m_needIntlConversion = false;
|
||||
|
||||
m_mainpart = false;
|
||||
m_just_hit_CR = false;
|
||||
}
|
||||
|
||||
|
||||
nsMsgSendPart::~nsMsgSendPart()
|
||||
{
|
||||
for (int i=0 ; i < m_numchildren; i++)
|
||||
delete m_children[i];
|
||||
|
||||
delete [] m_children;
|
||||
PR_FREEIF(m_buffer);
|
||||
PR_FREEIF(m_other);
|
||||
PR_FREEIF(m_type);
|
||||
}
|
||||
|
||||
nsresult nsMsgSendPart::CopyString(char** dest, const char* src)
|
||||
{
|
||||
NS_ASSERTION(src, "src null");
|
||||
|
||||
PR_FREEIF(*dest);
|
||||
if (!src)
|
||||
*dest = PL_strdup("");
|
||||
else
|
||||
*dest = PL_strdup(src);
|
||||
|
||||
return *dest? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsMsgSendPart::SetFile(nsIFile *file)
|
||||
{
|
||||
m_file = file;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsMsgSendPart::SetBuffer(const char* buffer)
|
||||
{
|
||||
PR_FREEIF(m_buffer);
|
||||
return CopyString(&m_buffer, buffer);
|
||||
}
|
||||
|
||||
|
||||
nsresult nsMsgSendPart::SetType(const char* type)
|
||||
{
|
||||
PR_FREEIF(m_type);
|
||||
m_type = PL_strdup(type);
|
||||
return m_type ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsMsgSendPart::SetOtherHeaders(const char* other)
|
||||
{
|
||||
return CopyString(&m_other, other);
|
||||
}
|
||||
|
||||
nsresult nsMsgSendPart::SetMimeDeliveryState(nsIMsgSend *state)
|
||||
{
|
||||
m_state = state;
|
||||
if (GetNumChildren() > 0)
|
||||
{
|
||||
for (int i = 0; i < GetNumChildren(); i++)
|
||||
{
|
||||
nsMsgSendPart *part = GetChild(i);
|
||||
if (part)
|
||||
part->SetMimeDeliveryState(state);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgSendPart::AppendOtherHeaders(const char* more)
|
||||
{
|
||||
if (!m_other)
|
||||
return SetOtherHeaders(more);
|
||||
|
||||
if (!more || !*more)
|
||||
return NS_OK;
|
||||
|
||||
char* tmp = (char *) PR_Malloc(sizeof(char) * (PL_strlen(m_other) + PL_strlen(more) + 2));
|
||||
if (!tmp)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
PL_strcpy(tmp, m_other);
|
||||
PL_strcat(tmp, more);
|
||||
PR_FREEIF(m_other);
|
||||
m_other = tmp;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsMsgSendPart::SetMainPart(bool value)
|
||||
{
|
||||
m_mainpart = value;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgSendPart::AddChild(nsMsgSendPart* child)
|
||||
{
|
||||
m_numchildren++;
|
||||
nsMsgSendPart** tmp = new nsMsgSendPart* [m_numchildren];
|
||||
if (tmp == nullptr) return NS_ERROR_OUT_OF_MEMORY;
|
||||
for (int i=0 ; i<m_numchildren-1 ; i++) {
|
||||
tmp[i] = m_children[i];
|
||||
}
|
||||
delete [] m_children;
|
||||
m_children = tmp;
|
||||
m_children[m_numchildren - 1] = child;
|
||||
child->m_parent = this;
|
||||
nsCString partNum(m_partNum);
|
||||
partNum.Append(".");
|
||||
partNum.AppendInt(m_numchildren);
|
||||
child->m_partNum = partNum;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsMsgSendPart * nsMsgSendPart::DetachChild(int32_t whichOne)
|
||||
{
|
||||
nsMsgSendPart *returnValue = nullptr;
|
||||
|
||||
NS_ASSERTION(whichOne >= 0 && whichOne < m_numchildren, "parameter out of range");
|
||||
if (whichOne >= 0 && whichOne < m_numchildren)
|
||||
{
|
||||
returnValue = m_children[whichOne];
|
||||
|
||||
if (m_numchildren > 1)
|
||||
{
|
||||
nsMsgSendPart** tmp = new nsMsgSendPart* [m_numchildren-1];
|
||||
if (tmp != nullptr)
|
||||
{
|
||||
// move all the other kids over
|
||||
for (int i=0 ; i<m_numchildren-1 ; i++)
|
||||
{
|
||||
if (i >= whichOne)
|
||||
tmp[i] = m_children[i+1];
|
||||
else
|
||||
tmp[i] = m_children[i];
|
||||
}
|
||||
delete [] m_children;
|
||||
m_children = tmp;
|
||||
m_numchildren--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete [] m_children;
|
||||
m_children = nullptr;
|
||||
m_numchildren = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (returnValue)
|
||||
returnValue->m_parent = nullptr;
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
nsMsgSendPart* nsMsgSendPart::GetChild(int32_t which)
|
||||
{
|
||||
NS_ASSERTION(which >= 0 && which < m_numchildren, "parameter out of range");
|
||||
if (which >= 0 && which < m_numchildren) {
|
||||
return m_children[which];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsresult nsMsgSendPart::PushBody(const char* buffer, int32_t length)
|
||||
{
|
||||
nsresult status = NS_OK;
|
||||
const char* encoded_data = buffer;
|
||||
|
||||
if (m_encoder)
|
||||
{
|
||||
status = m_encoder->Write(encoded_data, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Merely translate all linebreaks to CRLF.
|
||||
const char *in = encoded_data;
|
||||
const char *end = in + length;
|
||||
char *buffer, *out;
|
||||
|
||||
|
||||
buffer = mime_get_stream_write_buffer();
|
||||
// XXX -1 is not a valid nsresult
|
||||
NS_ENSURE_TRUE(buffer, static_cast<nsresult>(-1));
|
||||
|
||||
NS_ASSERTION(encoded_data != buffer, "encoded_data == buffer");
|
||||
out = buffer;
|
||||
|
||||
for (; in < end; in++) {
|
||||
if (m_just_hit_CR) {
|
||||
m_just_hit_CR = false;
|
||||
if (*in == '\n') {
|
||||
// The last thing we wrote was a CRLF from hitting a CR.
|
||||
// So, we don't want to do anything from a following LF;
|
||||
// we want to ignore it.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (*in == '\r' || *in == '\n') {
|
||||
/* Write out the newline. */
|
||||
*out++ = '\r';
|
||||
*out++ = '\n';
|
||||
|
||||
status = mime_write_message_body(m_state, buffer,
|
||||
out - buffer);
|
||||
if (NS_FAILED(status)) return status;
|
||||
out = buffer;
|
||||
|
||||
if (*in == '\r') {
|
||||
m_just_hit_CR = true;
|
||||
}
|
||||
|
||||
out = buffer;
|
||||
} else {
|
||||
|
||||
/* Fix for bug #95985. We can't assume that all lines are shorter
|
||||
than 4096 chars (MIME_BUFFER_SIZE), so we need to test
|
||||
for this here. sfraser.
|
||||
*/
|
||||
if (out - buffer >= MIME_BUFFER_SIZE)
|
||||
{
|
||||
status = mime_write_message_body(m_state, buffer, out - buffer);
|
||||
if (NS_FAILED(status)) return status;
|
||||
|
||||
out = buffer;
|
||||
}
|
||||
|
||||
*out++ = *in;
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush the last line. */
|
||||
if (out > buffer) {
|
||||
status = mime_write_message_body(m_state, buffer, out - buffer);
|
||||
if (NS_FAILED(status)) return status;
|
||||
out = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
if (encoded_data && encoded_data != buffer) {
|
||||
PR_Free((char *) encoded_data);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Partition the headers into those which apply to the message as a whole;
|
||||
those which apply to the message's contents; and the Content-Type header
|
||||
itself. (This relies on the fact that all body-related headers begin with
|
||||
"Content-".)
|
||||
|
||||
(How many header parsers are in this program now?)
|
||||
*/
|
||||
static nsresult
|
||||
divide_content_headers(const char *headers,
|
||||
char **message_headers,
|
||||
char **content_headers,
|
||||
char **content_type_header)
|
||||
{
|
||||
const char *tail;
|
||||
char *message_tail, *content_tail, *type_tail;
|
||||
int L = 0;
|
||||
if (headers)
|
||||
L = PL_strlen(headers);
|
||||
|
||||
if (L == 0)
|
||||
return NS_OK;
|
||||
|
||||
*message_headers = (char *)PR_Malloc(L+1);
|
||||
if (!*message_headers)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
*content_headers = (char *)PR_Malloc(L+1);
|
||||
if (!*content_headers) {
|
||||
PR_Free(*message_headers);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
*content_type_header = (char *)PR_Malloc(L+1);
|
||||
if (!*content_type_header) {
|
||||
PR_Free(*message_headers);
|
||||
PR_Free(*content_headers);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
message_tail = *message_headers;
|
||||
content_tail = *content_headers;
|
||||
type_tail = *content_type_header;
|
||||
tail = headers;
|
||||
|
||||
while (*tail)
|
||||
{
|
||||
const char *head = tail;
|
||||
char **out;
|
||||
while(true) {
|
||||
/* Loop until we reach a newline that is not followed by whitespace.
|
||||
*/
|
||||
if (tail[0] == 0 ||
|
||||
((tail[0] == '\r' || tail[0] == '\n') &&
|
||||
!(tail[1] == ' ' || tail[1] == '\t' || tail[1] == '\n')))
|
||||
{
|
||||
/* Swallow the whole newline. */
|
||||
if (tail[0] == '\r' && tail[1] == '\n')
|
||||
tail++;
|
||||
if (*tail)
|
||||
tail++;
|
||||
break;
|
||||
}
|
||||
tail++;
|
||||
}
|
||||
|
||||
/* Decide which block this header goes into.
|
||||
*/
|
||||
if (!PL_strncasecmp(head, "Content-Type:", 13))
|
||||
out = &type_tail;
|
||||
else
|
||||
if (!PL_strncasecmp(head, "Content-", 8))
|
||||
out = &content_tail;
|
||||
else
|
||||
out = &message_tail;
|
||||
|
||||
memcpy(*out, head, (tail-head));
|
||||
*out += (tail-head);
|
||||
}
|
||||
|
||||
*message_tail = 0;
|
||||
*content_tail = 0;
|
||||
*type_tail = 0;
|
||||
|
||||
if (!**message_headers) {
|
||||
PR_Free(*message_headers);
|
||||
*message_headers = 0;
|
||||
}
|
||||
|
||||
if (!**content_headers) {
|
||||
PR_Free(*content_headers);
|
||||
*content_headers = 0;
|
||||
}
|
||||
|
||||
if (!**content_type_header) {
|
||||
PR_Free(*content_type_header);
|
||||
*content_type_header = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// ### mwelch Because of the extreme difficulty we've had with
|
||||
// duplicate part headers, I'm going to put in an
|
||||
// ASSERT here which makes sure that no duplicate
|
||||
// Content-Type or Content-Transfer-Encoding headers
|
||||
// leave here undetected.
|
||||
const char* tmp;
|
||||
if (*content_type_header) {
|
||||
tmp = PL_strstr(*content_type_header, "Content-Type");
|
||||
if (tmp) {
|
||||
tmp++; // get past the first occurrence
|
||||
NS_ASSERTION(!PL_strstr(tmp, "Content-Type"), "Content-part already present");
|
||||
}
|
||||
}
|
||||
|
||||
if (*content_headers) {
|
||||
tmp = PL_strstr(*content_headers, "Content-Transfer-Encoding");
|
||||
if (tmp) {
|
||||
tmp++; // get past the first occurrence
|
||||
NS_ASSERTION(!PL_strstr(tmp, "Content-Transfer-Encoding"), "Content-Transfert already present");
|
||||
}
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#define SKIP_EMPTY_PART 1966
|
||||
|
||||
nsresult
|
||||
nsMsgSendPart::Write()
|
||||
{
|
||||
nsresult status = NS_OK;
|
||||
char *separator = nullptr;
|
||||
bool needToWriteCRLFAfterEncodedBody = false;
|
||||
|
||||
#define PUSHLEN(str, length) \
|
||||
do { \
|
||||
status = mime_write_message_body(m_state, str, length); \
|
||||
if (NS_FAILED(status)) goto FAIL; \
|
||||
} while (0) \
|
||||
|
||||
#define PUSH(str) PUSHLEN(str, PL_strlen(str))
|
||||
|
||||
// rhp: Suppress the output of parts that are empty!
|
||||
if ( (m_parent) &&
|
||||
(m_numchildren == 0) &&
|
||||
( (!m_buffer) || (!*m_buffer) ) &&
|
||||
(!m_file) &&
|
||||
(!m_mainpart) )
|
||||
// XXX SKIP_EMPTY_PART (= 1966) is not a valid nsresult
|
||||
return static_cast<nsresult>(SKIP_EMPTY_PART);
|
||||
|
||||
if (m_mainpart && m_type && PL_strcmp(m_type, TEXT_HTML) == 0)
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
// The "insert HTML links" code requires a memory buffer,
|
||||
// so read the file into memory.
|
||||
NS_ASSERTION(m_buffer == nullptr, "not-null buffer");
|
||||
int32_t length = 0;
|
||||
int64_t fileSize;
|
||||
if (NS_SUCCEEDED(m_file->GetFileSize(&fileSize)))
|
||||
length = fileSize;
|
||||
|
||||
m_buffer = (char *) PR_Malloc(sizeof(char) * (length + 1));
|
||||
if (m_buffer)
|
||||
{
|
||||
nsCOMPtr<nsIInputStream> inputFile;
|
||||
nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inputFile), m_file);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
uint32_t bytesRead;
|
||||
rv = inputFile->Read(m_buffer, length, &bytesRead);
|
||||
inputFile->Close();
|
||||
m_buffer[length] = '\0';
|
||||
}
|
||||
else
|
||||
PR_Free(m_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_parent && m_parent->m_type &&
|
||||
!PL_strcasecmp(m_parent->m_type, MULTIPART_DIGEST) &&
|
||||
m_type &&
|
||||
(!PL_strcasecmp(m_type, MESSAGE_RFC822) ||
|
||||
!PL_strcasecmp(m_type, MESSAGE_NEWS)))
|
||||
{
|
||||
// If we're in a multipart/digest, and this document is of type
|
||||
// message/rfc822, then it's appropriate to emit no headers.
|
||||
//
|
||||
}
|
||||
else
|
||||
{
|
||||
char *message_headers = 0;
|
||||
char *content_headers = 0;
|
||||
char *content_type_header = 0;
|
||||
status = divide_content_headers(m_other,
|
||||
&message_headers,
|
||||
&content_headers,
|
||||
&content_type_header);
|
||||
if (NS_FAILED(status))
|
||||
goto FAIL;
|
||||
|
||||
/* First, write out all of the headers that refer to the message
|
||||
itself (From, Subject, MIME-Version, etc.)
|
||||
*/
|
||||
if (message_headers)
|
||||
{
|
||||
PUSH(message_headers);
|
||||
PR_Free(message_headers);
|
||||
message_headers = 0;
|
||||
}
|
||||
|
||||
/* Now allow the crypto library to (potentially) insert some text
|
||||
(it may want to wrap the body in an envelope.) */
|
||||
if (!m_parent) {
|
||||
status = m_state->BeginCryptoEncapsulation();
|
||||
if (NS_FAILED(status)) goto FAIL;
|
||||
}
|
||||
|
||||
/* Now make sure there's a Content-Type header.
|
||||
*/
|
||||
if (!content_type_header)
|
||||
{
|
||||
NS_ASSERTION(m_type && *m_type, "null ptr");
|
||||
bool needsCharset = mime_type_needs_charset(m_type ? m_type : TEXT_PLAIN);
|
||||
if (needsCharset)
|
||||
{
|
||||
content_type_header = PR_smprintf("Content-Type: %s; charset=%s" CRLF,
|
||||
(m_type ? m_type : TEXT_PLAIN), m_charset_name);
|
||||
}
|
||||
else
|
||||
content_type_header = PR_smprintf("Content-Type: %s" CRLF,
|
||||
(m_type ? m_type : TEXT_PLAIN));
|
||||
if (!content_type_header)
|
||||
{
|
||||
if (content_headers)
|
||||
PR_Free(content_headers);
|
||||
status = NS_ERROR_OUT_OF_MEMORY;
|
||||
goto FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is a compound object, tack a boundary string onto the
|
||||
Content-Type header. this
|
||||
*/
|
||||
if (m_numchildren > 0)
|
||||
{
|
||||
int L;
|
||||
char *ct2;
|
||||
NS_ASSERTION(m_type, "null ptr");
|
||||
|
||||
if (!separator)
|
||||
{
|
||||
separator = mime_make_separator("");
|
||||
if (!separator)
|
||||
{
|
||||
status = NS_ERROR_OUT_OF_MEMORY;
|
||||
goto FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
L = PL_strlen(content_type_header);
|
||||
|
||||
if (content_type_header[L-1] == '\n')
|
||||
content_type_header[--L] = 0;
|
||||
if (content_type_header[L-1] == '\r')
|
||||
content_type_header[--L] = 0;
|
||||
|
||||
ct2 = PR_smprintf("%s;\r\n boundary=\"%s\"" CRLF, content_type_header, separator);
|
||||
PR_Free(content_type_header);
|
||||
if (!ct2)
|
||||
{
|
||||
if (content_headers)
|
||||
PR_Free(content_headers);
|
||||
status = NS_ERROR_OUT_OF_MEMORY;
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
content_type_header = ct2;
|
||||
}
|
||||
|
||||
// Now write out the Content-Type header...
|
||||
NS_ASSERTION(content_type_header && *content_type_header, "null ptr");
|
||||
PUSH(content_type_header);
|
||||
PR_Free(content_type_header);
|
||||
content_type_header = 0;
|
||||
|
||||
/* ...followed by all of the other headers that refer to the body of
|
||||
the message (Content-Transfer-Encoding, Content-Dispositon, etc.)
|
||||
*/
|
||||
if (content_headers)
|
||||
{
|
||||
PUSH(content_headers);
|
||||
PR_Free(content_headers);
|
||||
content_headers = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PUSH(CRLF); // A blank line, to mark the end of headers.
|
||||
|
||||
m_firstBlock = true;
|
||||
/* only convert if we need to tag charset */
|
||||
m_needIntlConversion = mime_type_needs_charset(m_type);
|
||||
|
||||
if (m_buffer)
|
||||
{
|
||||
status = PushBody(m_buffer, PL_strlen(m_buffer));
|
||||
if (NS_FAILED(status))
|
||||
goto FAIL;
|
||||
}
|
||||
else if (m_file)
|
||||
{
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), m_file);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
// mysteriously disappearing?
|
||||
nsCOMPtr<nsIMsgSendReport> sendReport;
|
||||
m_state->GetSendReport(getter_AddRefs(sendReport));
|
||||
if (sendReport)
|
||||
{
|
||||
nsAutoString error_msg;
|
||||
nsMsgBuildMessageWithTmpFile(m_file, error_msg);
|
||||
sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), false);
|
||||
}
|
||||
status = NS_MSG_UNABLE_TO_OPEN_TMP_FILE;
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
nsCString curLine;
|
||||
bool more = true;
|
||||
|
||||
/* Kludge to avoid having to allocate memory on the toy computers... */
|
||||
if (!mime_mailto_stream_read_buffer)
|
||||
{
|
||||
mime_mailto_stream_read_buffer = (char *) PR_Malloc(MIME_BUFFER_SIZE);
|
||||
if (!mime_mailto_stream_read_buffer)
|
||||
{
|
||||
status = NS_ERROR_OUT_OF_MEMORY;
|
||||
goto FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
char *buffer = mime_mailto_stream_read_buffer;
|
||||
if (m_strip_sensitive_headers)
|
||||
{
|
||||
// We are attaching a message, so we should be careful to
|
||||
// strip out certain sensitive internal header fields.
|
||||
bool skipping = false;
|
||||
nsAutoPtr<nsLineBuffer<char> > lineBuffer(new nsLineBuffer<char>);
|
||||
NS_ENSURE_TRUE(lineBuffer, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
while (more)
|
||||
{
|
||||
// NS_ReadLine doesn't return line termination chars.
|
||||
rv = NS_ReadLine(inputStream.get(), lineBuffer.get(), curLine, &more);
|
||||
|
||||
curLine.Append(CRLF);
|
||||
|
||||
char *line = (char *) curLine.get();
|
||||
if (skipping) {
|
||||
if (*line == ' ' || *line == '\t')
|
||||
continue;
|
||||
else
|
||||
skipping = false;
|
||||
}
|
||||
|
||||
if (!PL_strncasecmp(line, "From -", 6) ||
|
||||
!PL_strncasecmp(line, "BCC:", 4) ||
|
||||
!PL_strncasecmp(line, "FCC:", 4) ||
|
||||
!PL_strncasecmp(line, CONTENT_LENGTH ":", CONTENT_LENGTH_LEN+1) ||
|
||||
!PL_strncasecmp(line, "Lines:", 6) ||
|
||||
!PL_strncasecmp(line, "Status:", 7) ||
|
||||
!PL_strncasecmp(line, X_MOZILLA_STATUS ":", X_MOZILLA_STATUS_LEN+1) ||
|
||||
!PL_strncasecmp(line, X_MOZILLA_STATUS2 ":", X_MOZILLA_STATUS2_LEN+1) ||
|
||||
!PL_strncasecmp(line, X_MOZILLA_DRAFT_INFO ":", X_MOZILLA_DRAFT_INFO_LEN+1) ||
|
||||
!PL_strncasecmp(line, X_MOZILLA_NEWSHOST ":", X_MOZILLA_NEWSHOST_LEN+1) ||
|
||||
!PL_strncasecmp(line, X_UIDL ":", X_UIDL_LEN+1) ||
|
||||
!PL_strncasecmp(line, "X-VM-", 5)) /* hi Kyle */
|
||||
{
|
||||
skipping = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
PUSH(line);
|
||||
|
||||
if (curLine.Length() == 2) {
|
||||
nsCOMPtr <nsISeekableStream> seekableStream = do_QueryInterface(inputStream);
|
||||
// seek back the amount of data left in the line buffer...
|
||||
seekableStream->Seek(nsISeekableStream::NS_SEEK_CUR, lineBuffer->start - lineBuffer->end);
|
||||
break; // Now can do normal reads for the body.
|
||||
}
|
||||
}
|
||||
lineBuffer = nullptr;
|
||||
}
|
||||
|
||||
while (NS_SUCCEEDED(status))
|
||||
{
|
||||
uint32_t bytesRead;
|
||||
nsresult rv = inputStream->Read(buffer, MIME_BUFFER_SIZE, &bytesRead);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
nsCOMPtr<nsIMsgSendReport> sendReport;
|
||||
m_state->GetSendReport(getter_AddRefs(sendReport));
|
||||
if (sendReport)
|
||||
{
|
||||
nsAutoString error_msg;
|
||||
nsMsgBuildMessageWithFile(m_file, error_msg);
|
||||
sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), false);
|
||||
status = NS_MSG_UNABLE_TO_OPEN_FILE;
|
||||
goto FAIL;
|
||||
}
|
||||
}
|
||||
status = PushBody(buffer, bytesRead);
|
||||
if (NS_FAILED(status))
|
||||
goto FAIL;
|
||||
if (bytesRead < MIME_BUFFER_SIZE)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_encoder)
|
||||
{
|
||||
nsresult rv = m_encoder->Flush();
|
||||
m_encoder = nullptr;
|
||||
needToWriteCRLFAfterEncodedBody = !m_parent;
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
// XXX -1 is not a valid nsresult
|
||||
status = static_cast<nsresult>(-1);
|
||||
goto FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Ok, from here we loop and drive the the output of all children
|
||||
// for this message.
|
||||
//
|
||||
if (m_numchildren > 0)
|
||||
{
|
||||
bool writeSeparator = true;
|
||||
|
||||
for (int i = 0 ; i < m_numchildren ; i ++)
|
||||
{
|
||||
if (writeSeparator)
|
||||
{
|
||||
PUSH(CRLF);
|
||||
PUSH("--");
|
||||
|
||||
PUSH(separator);
|
||||
PUSH(CRLF);
|
||||
}
|
||||
|
||||
status = m_children[i]->Write();
|
||||
if (NS_FAILED(status))
|
||||
goto FAIL;
|
||||
|
||||
// XXX SKIP_EMPTY_PART (= 1966) is not a valid nsresult
|
||||
if (status == static_cast<nsresult>(SKIP_EMPTY_PART))
|
||||
writeSeparator = false;
|
||||
else
|
||||
writeSeparator = true;
|
||||
}
|
||||
|
||||
PUSH(CRLF);
|
||||
PUSH("--");
|
||||
PUSH(separator);
|
||||
PUSH("--");
|
||||
PUSH(CRLF);
|
||||
}
|
||||
else if (needToWriteCRLFAfterEncodedBody)
|
||||
PUSH(CRLF);
|
||||
|
||||
FAIL:
|
||||
PR_FREEIF(separator);
|
||||
return status;
|
||||
}
|
||||
|
||||
101
mailnews/compose/src/nsMsgSendPart.h
Normal file
101
mailnews/compose/src/nsMsgSendPart.h
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/* -*- 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 _MsgSendPart_H_
|
||||
#define _MsgSendPart_H_
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "prprf.h" /* should be defined into msgCore.h? */
|
||||
#include "nsMsgSend.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace mailnews {
|
||||
class MimeEncoder;
|
||||
}
|
||||
}
|
||||
|
||||
typedef int (*MSG_SendPartWriteFunc)(const char* line, int32_t size,
|
||||
bool isheader, void* closure);
|
||||
|
||||
class nsMsgSendPart {
|
||||
typedef mozilla::mailnews::MimeEncoder MimeEncoder;
|
||||
public:
|
||||
nsMsgSendPart(nsIMsgSend* state, const char *part_charset = NULL);
|
||||
virtual ~nsMsgSendPart(); // Note that the destructor also destroys
|
||||
// any children that were added.
|
||||
|
||||
virtual nsresult Write();
|
||||
|
||||
virtual nsresult SetFile(nsIFile *filename);
|
||||
const nsIFile *GetFile() {return m_file;}
|
||||
|
||||
virtual nsresult SetBuffer(const char* buffer);
|
||||
const char *GetBuffer() {return m_buffer;}
|
||||
|
||||
virtual nsresult SetType(const char* type);
|
||||
const char *GetType() {return m_type;}
|
||||
|
||||
const char *GetCharsetName() {return m_charset_name;}
|
||||
|
||||
virtual nsresult SetOtherHeaders(const char* other);
|
||||
const char *SetOtherHeaders() {return m_other;}
|
||||
virtual nsresult AppendOtherHeaders(const char* moreother);
|
||||
|
||||
virtual nsresult SetMimeDeliveryState(nsIMsgSend* state);
|
||||
|
||||
// Note that the nsMsgSendPart class will take over ownership of the
|
||||
// MimeEncoderData* object, deleting it when it chooses. (This is
|
||||
// necessary because deleting these objects is the only current way to
|
||||
// flush out the data in them.)
|
||||
void SetEncoder(MimeEncoder* encoder) {m_encoder = encoder;}
|
||||
MimeEncoder *GetEncoder() {return m_encoder;}
|
||||
|
||||
void SetStripSensitiveHeaders(bool value)
|
||||
{
|
||||
m_strip_sensitive_headers = value;
|
||||
}
|
||||
bool GetStripSensitiveHeaders() {return m_strip_sensitive_headers;}
|
||||
|
||||
virtual nsresult AddChild(nsMsgSendPart* child);
|
||||
|
||||
int32_t GetNumChildren() {return m_numchildren;}
|
||||
nsMsgSendPart *GetChild(int32_t which);
|
||||
nsMsgSendPart *DetachChild(int32_t which);
|
||||
|
||||
virtual nsresult SetMainPart(bool value);
|
||||
bool IsMainPart()
|
||||
{
|
||||
return m_mainpart;
|
||||
}
|
||||
nsCString m_partNum;
|
||||
protected:
|
||||
nsresult CopyString(char** dest, const char* src);
|
||||
nsresult PushBody(const char* buffer, int32_t length);
|
||||
|
||||
nsCOMPtr<nsIMsgSend> m_state;
|
||||
nsMsgSendPart *m_parent;
|
||||
nsCOMPtr <nsIFile> m_file;
|
||||
char *m_buffer;
|
||||
char *m_type;
|
||||
char *m_other;
|
||||
char m_charset_name[64+1]; // charset name associated with this part
|
||||
bool m_strip_sensitive_headers;
|
||||
nsAutoPtr<MimeEncoder> m_encoder;
|
||||
|
||||
nsMsgSendPart **m_children;
|
||||
int32_t m_numchildren;
|
||||
|
||||
// Data used while actually writing.
|
||||
bool m_firstBlock;
|
||||
bool m_needIntlConversion;
|
||||
|
||||
bool m_mainpart;
|
||||
|
||||
bool m_just_hit_CR;
|
||||
|
||||
static int32_t M_counter;
|
||||
};
|
||||
|
||||
#endif /* _MsgSendPart_H_ */
|
||||
437
mailnews/compose/src/nsMsgSendReport.cpp
Normal file
437
mailnews/compose/src/nsMsgSendReport.cpp
Normal file
|
|
@ -0,0 +1,437 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "nsMsgSendReport.h"
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsIMsgCompose.h"
|
||||
#include "nsMsgCompCID.h"
|
||||
#include "nsMsgPrompts.h"
|
||||
#include "nsError.h"
|
||||
#include "nsComposeStrings.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMsgProcessReport, nsIMsgProcessReport)
|
||||
|
||||
nsMsgProcessReport::nsMsgProcessReport()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
nsMsgProcessReport::~nsMsgProcessReport()
|
||||
{
|
||||
}
|
||||
|
||||
/* attribute boolean proceeded; */
|
||||
NS_IMETHODIMP nsMsgProcessReport::GetProceeded(bool *aProceeded)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aProceeded);
|
||||
*aProceeded = mProceeded;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgProcessReport::SetProceeded(bool aProceeded)
|
||||
{
|
||||
mProceeded = aProceeded;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute nsresult error; */
|
||||
NS_IMETHODIMP nsMsgProcessReport::GetError(nsresult *aError)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aError);
|
||||
*aError = mError;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgProcessReport::SetError(nsresult aError)
|
||||
{
|
||||
mError = aError;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute wstring message; */
|
||||
NS_IMETHODIMP nsMsgProcessReport::GetMessage(char16_t * *aMessage)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aMessage);
|
||||
*aMessage = ToNewUnicode(mMessage);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgProcessReport::SetMessage(const char16_t * aMessage)
|
||||
{
|
||||
mMessage = aMessage;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void Reset (); */
|
||||
NS_IMETHODIMP nsMsgProcessReport::Reset()
|
||||
{
|
||||
mProceeded = false;
|
||||
mError = NS_OK;
|
||||
mMessage.Truncate();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMsgSendReport, nsIMsgSendReport)
|
||||
|
||||
nsMsgSendReport::nsMsgSendReport()
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i <= SEND_LAST_PROCESS; i ++)
|
||||
mProcessReport[i] = new nsMsgProcessReport();
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
nsMsgSendReport::~nsMsgSendReport()
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i <= SEND_LAST_PROCESS; i ++)
|
||||
mProcessReport[i] = nullptr;
|
||||
}
|
||||
|
||||
/* attribute long currentProcess; */
|
||||
NS_IMETHODIMP nsMsgSendReport::GetCurrentProcess(int32_t *aCurrentProcess)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCurrentProcess);
|
||||
*aCurrentProcess = mCurrentProcess;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgSendReport::SetCurrentProcess(int32_t aCurrentProcess)
|
||||
{
|
||||
if (aCurrentProcess < 0 || aCurrentProcess > SEND_LAST_PROCESS)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
mCurrentProcess = aCurrentProcess;
|
||||
if (mProcessReport[mCurrentProcess])
|
||||
mProcessReport[mCurrentProcess]->SetProceeded(true);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute long deliveryMode; */
|
||||
NS_IMETHODIMP nsMsgSendReport::GetDeliveryMode(int32_t *aDeliveryMode)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDeliveryMode);
|
||||
*aDeliveryMode = mDeliveryMode;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgSendReport::SetDeliveryMode(int32_t aDeliveryMode)
|
||||
{
|
||||
mDeliveryMode = aDeliveryMode;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void Reset (); */
|
||||
NS_IMETHODIMP nsMsgSendReport::Reset()
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i <= SEND_LAST_PROCESS; i ++)
|
||||
if (mProcessReport[i])
|
||||
mProcessReport[i]->Reset();
|
||||
|
||||
mCurrentProcess = 0;
|
||||
mDeliveryMode = 0;
|
||||
mAlreadyDisplayReport = false;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void setProceeded (in long process, in boolean proceeded); */
|
||||
NS_IMETHODIMP nsMsgSendReport::SetProceeded(int32_t process, bool proceeded)
|
||||
{
|
||||
if (process < process_Current || process > SEND_LAST_PROCESS)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
if (process == process_Current)
|
||||
process = mCurrentProcess;
|
||||
|
||||
if (!mProcessReport[process])
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mProcessReport[process]->SetProceeded(proceeded);
|
||||
}
|
||||
|
||||
/* void setError (in long process, in nsresult error, in boolean overwriteError); */
|
||||
NS_IMETHODIMP nsMsgSendReport::SetError(int32_t process, nsresult newError, bool overwriteError)
|
||||
{
|
||||
if (process < process_Current || process > SEND_LAST_PROCESS)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
if (process == process_Current)
|
||||
{
|
||||
if (mCurrentProcess == process_Current)
|
||||
// We don't know what we're currently trying to do
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
process = mCurrentProcess;
|
||||
}
|
||||
|
||||
if (!mProcessReport[process])
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult currError = NS_OK;
|
||||
mProcessReport[process]->GetError(&currError);
|
||||
if (overwriteError || NS_SUCCEEDED(currError))
|
||||
return mProcessReport[process]->SetError(newError);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void setMessage (in long process, in wstring message, in boolean overwriteMessage); */
|
||||
NS_IMETHODIMP nsMsgSendReport::SetMessage(int32_t process, const char16_t *message, bool overwriteMessage)
|
||||
{
|
||||
if (process < process_Current || process > SEND_LAST_PROCESS)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
if (process == process_Current)
|
||||
{
|
||||
if (mCurrentProcess == process_Current)
|
||||
// We don't know what we're currently trying to do
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
process = mCurrentProcess;
|
||||
}
|
||||
|
||||
if (!mProcessReport[process])
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsString currMessage;
|
||||
mProcessReport[process]->GetMessage(getter_Copies(currMessage));
|
||||
if (overwriteMessage || currMessage.IsEmpty())
|
||||
return mProcessReport[process]->SetMessage(message);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* nsIMsgProcessReport getProcessReport (in long process); */
|
||||
NS_IMETHODIMP nsMsgSendReport::GetProcessReport(int32_t process, nsIMsgProcessReport **_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
if (process < process_Current || process > SEND_LAST_PROCESS)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
if (process == process_Current)
|
||||
{
|
||||
if (mCurrentProcess == process_Current)
|
||||
// We don't know what we're currently trying to do
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
process = mCurrentProcess;
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*_retval = mProcessReport[process]);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* nsresult displayReport (in nsIPrompt prompt, in boolean showErrorOnly, in boolean dontShowReportTwice); */
|
||||
NS_IMETHODIMP nsMsgSendReport::DisplayReport(nsIPrompt *prompt, bool showErrorOnly, bool dontShowReportTwice, nsresult *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
NS_ENSURE_TRUE(mCurrentProcess >= 0 && mCurrentProcess <= SEND_LAST_PROCESS,
|
||||
NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsresult currError = NS_OK;
|
||||
mProcessReport[mCurrentProcess]->GetError(&currError);
|
||||
*_retval = currError;
|
||||
|
||||
if (dontShowReportTwice && mAlreadyDisplayReport)
|
||||
return NS_OK;
|
||||
|
||||
if (showErrorOnly && NS_SUCCEEDED(currError))
|
||||
return NS_OK;
|
||||
|
||||
nsString currMessage;
|
||||
mProcessReport[mCurrentProcess]->GetMessage(getter_Copies(currMessage));
|
||||
|
||||
nsresult rv; // don't step on currError.
|
||||
nsCOMPtr<nsIStringBundleService> bundleService =
|
||||
mozilla::services::GetStringBundleService();
|
||||
NS_ENSURE_TRUE(bundleService, NS_ERROR_UNEXPECTED);
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
rv = bundleService->CreateBundle("chrome://messenger/locale/messengercompose/composeMsgs.properties", getter_AddRefs(bundle));
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
//TODO need to display a generic hardcoded message
|
||||
mAlreadyDisplayReport = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsString dialogTitle;
|
||||
nsString dialogMessage;
|
||||
|
||||
if (NS_SUCCEEDED(currError))
|
||||
{
|
||||
//TODO display a success error message
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//Do we have an explanation of the error? if no, try to build one...
|
||||
if (currMessage.IsEmpty())
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
// Temporary workaroung until bug 783526 is fixed.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wswitch"
|
||||
#endif
|
||||
switch (currError)
|
||||
{
|
||||
case NS_BINDING_ABORTED:
|
||||
case NS_ERROR_SEND_FAILED:
|
||||
case NS_ERROR_SEND_FAILED_BUT_NNTP_OK:
|
||||
case NS_MSG_FAILED_COPY_OPERATION:
|
||||
case NS_MSG_UNABLE_TO_SEND_LATER:
|
||||
case NS_MSG_UNABLE_TO_SAVE_DRAFT:
|
||||
case NS_MSG_UNABLE_TO_SAVE_TEMPLATE:
|
||||
//Ignore, don't need to repeat ourself.
|
||||
break;
|
||||
default:
|
||||
const char16_t* errorString = errorStringNameForErrorCode(currError);
|
||||
nsMsgGetMessageByName(errorString, currMessage);
|
||||
break;
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mDeliveryMode == nsIMsgCompDeliverMode::Now || mDeliveryMode == nsIMsgCompDeliverMode::SendUnsent)
|
||||
{
|
||||
// SMTP is taking care of it's own error message and will return NS_ERROR_BUT_DONT_SHOW_ALERT as error code.
|
||||
// In that case, we must not show an alert ourself.
|
||||
if (currError == NS_ERROR_BUT_DONT_SHOW_ALERT)
|
||||
{
|
||||
mAlreadyDisplayReport = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bundle->GetStringFromName(u"sendMessageErrorTitle",
|
||||
getter_Copies(dialogTitle));
|
||||
|
||||
const char16_t* preStrName = u"sendFailed";
|
||||
bool askToGoBackToCompose = false;
|
||||
switch (mCurrentProcess)
|
||||
{
|
||||
case process_BuildMessage :
|
||||
preStrName = u"sendFailed";
|
||||
askToGoBackToCompose = false;
|
||||
break;
|
||||
case process_NNTP :
|
||||
preStrName = u"sendFailed";
|
||||
askToGoBackToCompose = false;
|
||||
break;
|
||||
case process_SMTP :
|
||||
bool nntpProceeded;
|
||||
mProcessReport[process_NNTP]->GetProceeded(&nntpProceeded);
|
||||
if (nntpProceeded)
|
||||
preStrName = u"sendFailedButNntpOk";
|
||||
else
|
||||
preStrName = u"sendFailed";
|
||||
askToGoBackToCompose = false;
|
||||
break;
|
||||
case process_Copy:
|
||||
preStrName = u"failedCopyOperation";
|
||||
askToGoBackToCompose = (mDeliveryMode == nsIMsgCompDeliverMode::Now);
|
||||
break;
|
||||
case process_FCC:
|
||||
preStrName = u"failedCopyOperation";
|
||||
askToGoBackToCompose = (mDeliveryMode == nsIMsgCompDeliverMode::Now);
|
||||
break;
|
||||
}
|
||||
bundle->GetStringFromName(preStrName, getter_Copies(dialogMessage));
|
||||
|
||||
//Do we already have an error message?
|
||||
if (!askToGoBackToCompose && currMessage.IsEmpty())
|
||||
{
|
||||
//we don't have an error description but we can put a generic explanation
|
||||
bundle->GetStringFromName(u"genericFailureExplanation",
|
||||
getter_Copies(currMessage));
|
||||
}
|
||||
|
||||
if (!currMessage.IsEmpty())
|
||||
{
|
||||
//Don't need to repeat ourself!
|
||||
if (!currMessage.Equals(dialogMessage))
|
||||
{
|
||||
if (!dialogMessage.IsEmpty())
|
||||
dialogMessage.Append(char16_t('\n'));
|
||||
dialogMessage.Append(currMessage);
|
||||
}
|
||||
}
|
||||
|
||||
if (askToGoBackToCompose)
|
||||
{
|
||||
bool oopsGiveMeBackTheComposeWindow = true;
|
||||
nsString text1;
|
||||
bundle->GetStringFromName(u"returnToComposeWindowQuestion",
|
||||
getter_Copies(text1));
|
||||
if (!dialogMessage.IsEmpty())
|
||||
dialogMessage.AppendLiteral("\n");
|
||||
dialogMessage.Append(text1);
|
||||
nsMsgAskBooleanQuestionByString(prompt, dialogMessage.get(), &oopsGiveMeBackTheComposeWindow, dialogTitle.get());
|
||||
if (!oopsGiveMeBackTheComposeWindow)
|
||||
*_retval = NS_OK;
|
||||
}
|
||||
else
|
||||
nsMsgDisplayMessageByString(prompt, dialogMessage.get(), dialogTitle.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
const char16_t* title;
|
||||
const char16_t* messageName;
|
||||
|
||||
switch (mDeliveryMode)
|
||||
{
|
||||
case nsIMsgCompDeliverMode::Later:
|
||||
title = u"sendLaterErrorTitle";
|
||||
messageName = u"unableToSendLater";
|
||||
break;
|
||||
|
||||
case nsIMsgCompDeliverMode::AutoSaveAsDraft:
|
||||
case nsIMsgCompDeliverMode::SaveAsDraft:
|
||||
title = u"saveDraftErrorTitle";
|
||||
messageName = u"unableToSaveDraft";
|
||||
break;
|
||||
|
||||
case nsIMsgCompDeliverMode::SaveAsTemplate:
|
||||
title = u"saveTemplateErrorTitle";
|
||||
messageName = u"unableToSaveTemplate";
|
||||
break;
|
||||
|
||||
default:
|
||||
/* This should never happen! */
|
||||
title = u"sendMessageErrorTitle";
|
||||
messageName = u"sendFailed";
|
||||
break;
|
||||
}
|
||||
|
||||
bundle->GetStringFromName(title, getter_Copies(dialogTitle));
|
||||
bundle->GetStringFromName(messageName,
|
||||
getter_Copies(dialogMessage));
|
||||
|
||||
//Do we have an error message...
|
||||
if (currMessage.IsEmpty())
|
||||
{
|
||||
//we don't have an error description but we can put a generic explanation
|
||||
bundle->GetStringFromName(u"genericFailureExplanation",
|
||||
getter_Copies(currMessage));
|
||||
}
|
||||
|
||||
if (!currMessage.IsEmpty())
|
||||
{
|
||||
if (!dialogMessage.IsEmpty())
|
||||
dialogMessage.Append(char16_t('\n'));
|
||||
dialogMessage.Append(currMessage);
|
||||
}
|
||||
nsMsgDisplayMessageByString(prompt, dialogMessage.get(), dialogTitle.get());
|
||||
}
|
||||
|
||||
mAlreadyDisplayReport = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
46
mailnews/compose/src/nsMsgSendReport.h
Normal file
46
mailnews/compose/src/nsMsgSendReport.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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 __nsMsgSendReport_h__
|
||||
#define __nsMsgSendReport_h__
|
||||
|
||||
#include "nsIMsgSendReport.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsMsgProcessReport : public nsIMsgProcessReport
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMSGPROCESSREPORT
|
||||
|
||||
nsMsgProcessReport();
|
||||
|
||||
private:
|
||||
virtual ~nsMsgProcessReport();
|
||||
bool mProceeded;
|
||||
nsresult mError;
|
||||
nsString mMessage;
|
||||
};
|
||||
|
||||
|
||||
class nsMsgSendReport : public nsIMsgSendReport
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMSGSENDREPORT
|
||||
|
||||
nsMsgSendReport();
|
||||
|
||||
private:
|
||||
virtual ~nsMsgSendReport();
|
||||
#define SEND_LAST_PROCESS process_FCC
|
||||
nsCOMPtr<nsIMsgProcessReport> mProcessReport[SEND_LAST_PROCESS + 1];
|
||||
int32_t mDeliveryMode;
|
||||
int32_t mCurrentProcess;
|
||||
bool mAlreadyDisplayReport;
|
||||
};
|
||||
|
||||
#endif
|
||||
62
mailnews/compose/src/nsSMTPProtocolHandler.js
Normal file
62
mailnews/compose/src/nsSMTPProtocolHandler.js
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* 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/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
var kNetworkProtocolCIDPrefix = "@mozilla.org/network/protocol;1?name=";
|
||||
var nsIProtocolHandler = Components.interfaces.nsIProtocolHandler;
|
||||
|
||||
function makeProtocolHandler(aProtocol, aDefaultPort, aClassID) {
|
||||
return {
|
||||
classID: Components.ID(aClassID),
|
||||
QueryInterface: XPCOMUtils.generateQI([nsIProtocolHandler]),
|
||||
|
||||
scheme: aProtocol,
|
||||
defaultPort: aDefaultPort,
|
||||
protocolFlags: nsIProtocolHandler.URI_NORELATIVE |
|
||||
nsIProtocolHandler.URI_DANGEROUS_TO_LOAD |
|
||||
nsIProtocolHandler.URI_NON_PERSISTABLE |
|
||||
nsIProtocolHandler.ALLOWS_PROXY |
|
||||
nsIProtocolHandler.URI_FORBIDS_AUTOMATIC_DOCUMENT_REPLACEMENT,
|
||||
|
||||
newURI: function (aSpec, aOriginCharset, aBaseURI) {
|
||||
var url = Components.classes["@mozilla.org/messengercompose/smtpurl;1"]
|
||||
.createInstance(Components.interfaces.nsIURI);
|
||||
|
||||
url.spec = aSpec;
|
||||
|
||||
return url;
|
||||
},
|
||||
|
||||
newChannel: function (aURI) {
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
newChannel2: function(aURI, aLoadInfo)
|
||||
{
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
allowPort: function (port, scheme) {
|
||||
return port == aDefaultPort;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function nsSMTPProtocolHandler() {}
|
||||
|
||||
nsSMTPProtocolHandler.prototype =
|
||||
makeProtocolHandler("smtp",
|
||||
Components.interfaces.nsISmtpUrl.DEFAULT_SMTP_PORT,
|
||||
"b14c2b67-8680-4c11-8d63-9403c7d4f757");
|
||||
|
||||
function nsSMTPSProtocolHandler() {}
|
||||
|
||||
nsSMTPSProtocolHandler.prototype =
|
||||
makeProtocolHandler("smtps",
|
||||
Components.interfaces.nsISmtpUrl.DEFAULT_SMTPS_PORT,
|
||||
"057d0997-9e3a-411e-b4ee-2602f53fe05f");
|
||||
|
||||
var components = [nsSMTPProtocolHandler, nsSMTPSProtocolHandler];
|
||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
|
||||
4
mailnews/compose/src/nsSMTPProtocolHandler.manifest
Normal file
4
mailnews/compose/src/nsSMTPProtocolHandler.manifest
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
component {b14c2b67-8680-4c11-8d63-9403c7d4f757} nsSMTPProtocolHandler.js
|
||||
contract @mozilla.org/network/protocol;1?name=smtp {b14c2b67-8680-4c11-8d63-9403c7d4f757}
|
||||
component {057d0997-9e3a-411e-b4ee-2602f53fe05f} nsSMTPProtocolHandler.js
|
||||
contract @mozilla.org/network/protocol;1?name=smtps {057d0997-9e3a-411e-b4ee-2602f53fe05f}
|
||||
2249
mailnews/compose/src/nsSmtpProtocol.cpp
Normal file
2249
mailnews/compose/src/nsSmtpProtocol.cpp
Normal file
File diff suppressed because it is too large
Load diff
225
mailnews/compose/src/nsSmtpProtocol.h
Normal file
225
mailnews/compose/src/nsSmtpProtocol.h
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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 nsSmtpProtocol_h___
|
||||
#define nsSmtpProtocol_h___
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "msgIOAuth2Module.h"
|
||||
#include "nsMsgProtocol.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsISmtpUrl.h"
|
||||
#include "nsIMsgStatusFeedback.h"
|
||||
#include "nsMsgLineBuffer.h"
|
||||
#include "nsIAuthModule.h"
|
||||
#include "MailNewsTypes2.h" // for nsMsgSocketType
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIVariant;
|
||||
class nsIWritableVariant;
|
||||
|
||||
/* states of the machine
|
||||
*/
|
||||
typedef enum _SmtpState {
|
||||
SMTP_RESPONSE = 0, // 0
|
||||
SMTP_START_CONNECT, // 1
|
||||
SMTP_FINISH_CONNECT, // 2
|
||||
SMTP_SEND_HELO_RESPONSE, // 3
|
||||
SMTP_SEND_EHLO_RESPONSE, // 4
|
||||
SMTP_SEND_MAIL_RESPONSE, // 5
|
||||
SMTP_SEND_RCPT_RESPONSE, // 6
|
||||
SMTP_SEND_DATA_RESPONSE, // 7
|
||||
SMTP_SEND_POST_DATA, // 8
|
||||
SMTP_SEND_MESSAGE_RESPONSE, // 9
|
||||
SMTP_DONE, // 10
|
||||
SMTP_ERROR_DONE, // 11
|
||||
SMTP_FREE, // 12
|
||||
SMTP_AUTH_LOGIN_STEP0_RESPONSE, // 13
|
||||
SMTP_EXTN_LOGIN_RESPONSE, // 14
|
||||
SMTP_SEND_AUTH_LOGIN_STEP0, // 15
|
||||
SMTP_SEND_AUTH_LOGIN_STEP1, // 16
|
||||
SMTP_SEND_AUTH_LOGIN_STEP2, // 17
|
||||
SMTP_AUTH_LOGIN_RESPONSE, // 18
|
||||
SMTP_TLS_RESPONSE, // 19
|
||||
SMTP_AUTH_EXTERNAL_RESPONSE, // 20
|
||||
SMTP_AUTH_PROCESS_STATE, // 21
|
||||
SMTP_AUTH_CRAM_MD5_CHALLENGE_RESPONSE, // 22
|
||||
SMTP_SEND_AUTH_GSSAPI_FIRST, // 23
|
||||
SMTP_SEND_AUTH_GSSAPI_STEP, // 24
|
||||
SMTP_SUSPENDED, // 25
|
||||
SMTP_AUTH_OAUTH2_STEP, // 26
|
||||
SMTP_AUTH_OAUTH2_RESPONSE, // 27
|
||||
} SmtpState;
|
||||
|
||||
// State Flags (Note, I use the word state in terms of storing
|
||||
// state information about the connection (authentication, have we sent
|
||||
// commands, etc. I do not intend it to refer to protocol state)
|
||||
#define SMTP_PAUSE_FOR_READ 0x00000001 /* should we pause for the next read */
|
||||
#define SMTP_ESMTP_SERVER 0x00000002
|
||||
#define SMTP_EHLO_DSN_ENABLED 0x00000004
|
||||
#define SMTP_EHLO_STARTTLS_ENABLED 0x00000008
|
||||
#define SMTP_EHLO_SIZE_ENABLED 0x00000010
|
||||
#define SMTP_EHLO_8BIT_ENABLED 0x00000020
|
||||
|
||||
// insecure mechanisms follow
|
||||
#define SMTP_AUTH_LOGIN_ENABLED 0x00000100
|
||||
#define SMTP_AUTH_PLAIN_ENABLED 0x00000200
|
||||
#define SMTP_AUTH_EXTERNAL_ENABLED 0x00000400
|
||||
// secure mechanisms follow
|
||||
#define SMTP_AUTH_GSSAPI_ENABLED 0x00000800
|
||||
#define SMTP_AUTH_DIGEST_MD5_ENABLED 0x00001000
|
||||
#define SMTP_AUTH_CRAM_MD5_ENABLED 0x00002000
|
||||
#define SMTP_AUTH_NTLM_ENABLED 0x00004000
|
||||
#define SMTP_AUTH_MSN_ENABLED 0x00008000
|
||||
#define SMTP_AUTH_OAUTH2_ENABLED 0x00010000
|
||||
// sum of all above auth mechanisms
|
||||
#define SMTP_AUTH_ANY 0x0001FF00
|
||||
// indicates that AUTH has been advertised
|
||||
#define SMTP_AUTH 0x00020000
|
||||
// No login necessary (pref)
|
||||
#define SMTP_AUTH_NONE_ENABLED 0x00040000
|
||||
|
||||
class nsSmtpProtocol : public nsMsgAsyncWriteProtocol,
|
||||
public msgIOAuth2ModuleListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_MSGIOAUTH2MODULELISTENER
|
||||
|
||||
// Creating a protocol instance requires the URL which needs to be run.
|
||||
nsSmtpProtocol(nsIURI * aURL);
|
||||
|
||||
virtual nsresult LoadUrl(nsIURI * aURL, nsISupports * aConsumer = nullptr) override;
|
||||
virtual nsresult SendData(const char * dataBuffer, bool aSuppressLogging = false) override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// we suppport the nsIStreamListener interface
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// stop binding is a "notification" informing us that the stream associated with aURL is going away.
|
||||
NS_IMETHOD OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult status) override;
|
||||
|
||||
private:
|
||||
virtual ~nsSmtpProtocol();
|
||||
// if we are asked to load a url while we are blocked waiting for redirection information,
|
||||
// then we'll store the url consumer in mPendingConsumer until we can actually load
|
||||
// the url.
|
||||
nsCOMPtr<nsISupports> mPendingConsumer;
|
||||
|
||||
// the nsISmtpURL that is currently running
|
||||
nsCOMPtr<nsISmtpUrl> m_runningURL;
|
||||
|
||||
// the error state we want to set on the url
|
||||
nsresult m_urlErrorState;
|
||||
nsCOMPtr<nsIMsgStatusFeedback> m_statusFeedback;
|
||||
|
||||
// Generic state information -- What state are we in? What state do we want to go to
|
||||
// after the next response? What was the last response code? etc.
|
||||
SmtpState m_nextState;
|
||||
SmtpState m_nextStateAfterResponse;
|
||||
int32_t m_responseCode; /* code returned from Smtp server */
|
||||
int32_t m_previousResponseCode;
|
||||
int32_t m_continuationResponse;
|
||||
nsCString m_responseText; /* text returned from Smtp server */
|
||||
nsMsgLineStreamBuffer *m_lineStreamBuffer; // used to efficiently extract lines from the incoming data stream
|
||||
|
||||
nsTArray<nsCString> m_addresses;
|
||||
uint32_t m_addressesLeft;
|
||||
nsCString m_mailAddr;
|
||||
nsCString m_helloArgument;
|
||||
int32_t m_sizelimit;
|
||||
|
||||
// *** the following should move to the smtp server when we support
|
||||
// multiple smtp servers
|
||||
bool m_usernamePrompted;
|
||||
int32_t m_prefSocketType;
|
||||
bool m_tlsEnabled;
|
||||
|
||||
bool m_tlsInitiated;
|
||||
|
||||
bool m_sendDone;
|
||||
|
||||
int32_t m_totalAmountRead;
|
||||
int64_t m_totalMessageSize;
|
||||
|
||||
char *m_dataBuf;
|
||||
uint32_t m_dataBufSize;
|
||||
|
||||
int32_t m_originalContentLength; /* the content length at the time of calling graph progress */
|
||||
|
||||
// initialization function given a new url and transport layer
|
||||
void Initialize(nsIURI * aURL);
|
||||
virtual nsresult ProcessProtocolState(nsIURI * url, nsIInputStream * inputStream,
|
||||
uint64_t sourceOffset, uint32_t length) override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Communication methods --> Reading and writing protocol
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void UpdateStatus(const char16_t* aStatusName);
|
||||
void UpdateStatusWithString(const char16_t * aStatusString);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protocol Methods --> This protocol is state driven so each protocol method is
|
||||
// designed to re-act to the current "state". I've attempted to
|
||||
// group them together based on functionality.
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult SmtpResponse(nsIInputStream * inputStream, uint32_t length);
|
||||
nsresult ExtensionLoginResponse(nsIInputStream * inputStream, uint32_t length);
|
||||
nsresult SendHeloResponse(nsIInputStream * inputStream, uint32_t length);
|
||||
nsresult SendEhloResponse(nsIInputStream * inputStream, uint32_t length);
|
||||
nsresult SendQuit(SmtpState aNextStateAfterResponse = SMTP_DONE);
|
||||
|
||||
nsresult AuthGSSAPIFirst();
|
||||
nsresult AuthGSSAPIStep();
|
||||
nsresult AuthLoginStep0();
|
||||
void AuthLoginStep0Response();
|
||||
nsresult AuthLoginStep1();
|
||||
nsresult AuthLoginStep2();
|
||||
nsresult AuthLoginResponse(nsIInputStream * stream, uint32_t length);
|
||||
nsresult AuthOAuth2Step1();
|
||||
|
||||
nsresult SendTLSResponse();
|
||||
nsresult SendMailResponse();
|
||||
nsresult SendRecipientResponse();
|
||||
nsresult SendDataResponse();
|
||||
void SendPostData();
|
||||
nsresult SendMessageResponse();
|
||||
nsresult ProcessAuth();
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// End of Protocol Methods
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SendMessageInFile();
|
||||
|
||||
void AppendHelloArgument(nsACString& aResult);
|
||||
nsresult GetPassword(nsCString &aPassword);
|
||||
nsresult GetUsernamePassword(nsACString &aUsername, nsACString &aPassword);
|
||||
nsresult PromptForPassword(nsISmtpServer *aSmtpServer, nsISmtpUrl *aSmtpUrl,
|
||||
const char16_t **formatStrings,
|
||||
nsACString &aPassword);
|
||||
|
||||
void InitPrefAuthMethods(int32_t authMethodPrefValue);
|
||||
nsresult ChooseAuthMethod();
|
||||
void MarkAuthMethodAsFailed(int32_t failedAuthMethod);
|
||||
void ResetAuthMethods();
|
||||
|
||||
virtual const char* GetType() override {return "smtp";}
|
||||
|
||||
int32_t m_prefAuthMethods; // set of capability flags for auth methods
|
||||
int32_t m_failedAuthMethods; // ditto
|
||||
int32_t m_currentAuthMethod; // exactly one capability flag, or 0
|
||||
|
||||
// The support module for OAuth2 logon, only present if OAuth2 is enabled
|
||||
// and working.
|
||||
nsCOMPtr<msgIOAuth2Module> mOAuth2Support;
|
||||
};
|
||||
|
||||
#endif // nsSmtpProtocol_h___
|
||||
629
mailnews/compose/src/nsSmtpServer.cpp
Normal file
629
mailnews/compose/src/nsSmtpServer.cpp
Normal file
|
|
@ -0,0 +1,629 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsSmtpServer.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIAuthPrompt.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "nsIMsgAccountManager.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsISmtpService.h"
|
||||
#include "nsMsgCompCID.h"
|
||||
#include "nsILoginInfo.h"
|
||||
#include "nsILoginManager.h"
|
||||
#include "nsIArray.h"
|
||||
#include "nsArrayUtils.h"
|
||||
|
||||
NS_IMPL_ADDREF(nsSmtpServer)
|
||||
NS_IMPL_RELEASE(nsSmtpServer)
|
||||
NS_INTERFACE_MAP_BEGIN(nsSmtpServer)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISmtpServer)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISmtpServer)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
nsSmtpServer::nsSmtpServer():
|
||||
mKey("")
|
||||
{
|
||||
m_logonFailed = false;
|
||||
getPrefs();
|
||||
}
|
||||
|
||||
nsSmtpServer::~nsSmtpServer()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::GetKey(char * *aKey)
|
||||
{
|
||||
if (!aKey) return NS_ERROR_NULL_POINTER;
|
||||
if (mKey.IsEmpty())
|
||||
*aKey = nullptr;
|
||||
else
|
||||
*aKey = ToNewCString(mKey);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::SetKey(const char * aKey)
|
||||
{
|
||||
NS_ASSERTION(aKey, "Bad key pointer");
|
||||
mKey = aKey;
|
||||
return getPrefs();
|
||||
}
|
||||
|
||||
nsresult nsSmtpServer::getPrefs()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefService> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsAutoCString branchName;
|
||||
branchName.AssignLiteral("mail.smtpserver.");
|
||||
branchName += mKey;
|
||||
branchName.Append('.');
|
||||
rv = prefs->GetBranch(branchName.get(), getter_AddRefs(mPrefBranch));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if(!mDefPrefBranch) {
|
||||
branchName.AssignLiteral("mail.smtpserver.default.");
|
||||
rv = prefs->GetBranch(branchName.get(), getter_AddRefs(mDefPrefBranch));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::GetHostname(nsACString &aHostname)
|
||||
{
|
||||
nsCString result;
|
||||
nsresult rv = mPrefBranch->GetCharPref("hostname", getter_Copies(result));
|
||||
if (NS_FAILED(rv))
|
||||
aHostname.Truncate();
|
||||
else
|
||||
aHostname = result;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::SetHostname(const nsACString &aHostname)
|
||||
{
|
||||
if (!aHostname.IsEmpty())
|
||||
return mPrefBranch->SetCharPref("hostname", PromiseFlatCString(aHostname).get());
|
||||
|
||||
// If the pref value is already empty, ClearUserPref will return
|
||||
// NS_ERROR_UNEXPECTED, so don't check the rv here.
|
||||
mPrefBranch->ClearUserPref("hostname");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::GetDescription(nsACString &aDescription)
|
||||
{
|
||||
nsCString temp;
|
||||
mPrefBranch->GetCharPref("description", getter_Copies(temp));
|
||||
aDescription.Assign(temp);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::SetDescription(const nsACString &aDescription)
|
||||
{
|
||||
if (!aDescription.IsEmpty())
|
||||
return mPrefBranch->SetCharPref("description", PromiseFlatCString(aDescription).get());
|
||||
else
|
||||
mPrefBranch->ClearUserPref("description");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// if GetPort returns 0, it means default port
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::GetPort(int32_t *aPort)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPort);
|
||||
if (NS_FAILED(mPrefBranch->GetIntPref("port", aPort)))
|
||||
*aPort = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::SetPort(int32_t aPort)
|
||||
{
|
||||
if (aPort)
|
||||
return mPrefBranch->SetIntPref("port", aPort);
|
||||
|
||||
mPrefBranch->ClearUserPref("port");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::GetDisplayname(char * *aDisplayname)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_ENSURE_ARG_POINTER(aDisplayname);
|
||||
|
||||
nsCString hostname;
|
||||
rv = mPrefBranch->GetCharPref("hostname", getter_Copies(hostname));
|
||||
if (NS_FAILED(rv)) {
|
||||
*aDisplayname=nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
int32_t port;
|
||||
rv = mPrefBranch->GetIntPref("port", &port);
|
||||
if (NS_FAILED(rv))
|
||||
port = 0;
|
||||
|
||||
if (port) {
|
||||
hostname.Append(':');
|
||||
hostname.AppendInt(port);
|
||||
}
|
||||
|
||||
*aDisplayname = ToNewCString(hostname);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::GetSocketType(int32_t *socketType)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(socketType);
|
||||
getIntPrefWithDefault("try_ssl", socketType, 0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::SetSocketType(int32_t socketType)
|
||||
{
|
||||
return mPrefBranch->SetIntPref("try_ssl", socketType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::GetHelloArgument(char * *aHelloArgument)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_ENSURE_ARG_POINTER(aHelloArgument);
|
||||
rv = mPrefBranch->GetCharPref("hello_argument", aHelloArgument);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
rv = mDefPrefBranch->GetCharPref("hello_argument", aHelloArgument);
|
||||
if (NS_FAILED(rv))
|
||||
*aHelloArgument = nullptr;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::GetAuthMethod(int32_t *authMethod)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(authMethod);
|
||||
getIntPrefWithDefault("authMethod", authMethod, 3);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsSmtpServer::getIntPrefWithDefault(const char *prefName,
|
||||
int32_t *val,
|
||||
int32_t defVal)
|
||||
{
|
||||
nsresult rv = mPrefBranch->GetIntPref(prefName, val);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return;
|
||||
|
||||
rv = mDefPrefBranch->GetIntPref(prefName, val);
|
||||
if (NS_FAILED(rv))
|
||||
// last resort
|
||||
*val = defVal;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::SetAuthMethod(int32_t authMethod)
|
||||
{
|
||||
return mPrefBranch->SetIntPref("authMethod", authMethod);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::GetUsername(nsACString &aUsername)
|
||||
{
|
||||
nsCString result;
|
||||
nsresult rv = mPrefBranch->GetCharPref("username", getter_Copies(result));
|
||||
if (NS_FAILED(rv))
|
||||
aUsername.Truncate();
|
||||
else
|
||||
aUsername = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::SetUsername(const nsACString &aUsername)
|
||||
{
|
||||
if (!aUsername.IsEmpty())
|
||||
return mPrefBranch->SetCharPref("username", PromiseFlatCString(aUsername).get());
|
||||
|
||||
// If the pref value is already empty, ClearUserPref will return
|
||||
// NS_ERROR_UNEXPECTED, so don't check the rv here.
|
||||
mPrefBranch->ClearUserPref("username");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::GetPassword(nsACString& aPassword)
|
||||
{
|
||||
if (m_password.IsEmpty() && !m_logonFailed)
|
||||
{
|
||||
// try to avoid prompting the user for another password. If the user has set
|
||||
// the appropriate pref, we'll use the password from an incoming server, if
|
||||
// the user has already logged onto that server.
|
||||
|
||||
// if this is set, we'll only use this, and not the other prefs
|
||||
// user_pref("mail.smtpserver.smtp1.incomingAccount", "server1");
|
||||
|
||||
// if this is set, we'll accept an exact match of user name and server
|
||||
// user_pref("mail.smtp.useMatchingHostNameServer", true);
|
||||
|
||||
// if this is set, and we don't find an exact match of user and host name,
|
||||
// we'll accept a match of username and domain, where domain
|
||||
// is everything after the first '.'
|
||||
// user_pref("mail.smtp.useMatchingDomainServer", true);
|
||||
|
||||
nsCString accountKey;
|
||||
bool useMatchingHostNameServer = false;
|
||||
bool useMatchingDomainServer = false;
|
||||
mPrefBranch->GetCharPref("incomingAccount", getter_Copies(accountKey));
|
||||
|
||||
nsCOMPtr<nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID);
|
||||
nsCOMPtr<nsIMsgIncomingServer> incomingServerToUse;
|
||||
if (accountManager)
|
||||
{
|
||||
if (!accountKey.IsEmpty())
|
||||
accountManager->GetIncomingServer(accountKey, getter_AddRefs(incomingServerToUse));
|
||||
else
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
prefBranch->GetBoolPref("mail.smtp.useMatchingHostNameServer", &useMatchingHostNameServer);
|
||||
prefBranch->GetBoolPref("mail.smtp.useMatchingDomainServer", &useMatchingDomainServer);
|
||||
if (useMatchingHostNameServer || useMatchingDomainServer)
|
||||
{
|
||||
nsCString userName;
|
||||
nsCString hostName;
|
||||
GetHostname(hostName);
|
||||
GetUsername(userName);
|
||||
if (useMatchingHostNameServer)
|
||||
// pass in empty type and port=0, to match imap and pop3.
|
||||
accountManager->FindRealServer(userName, hostName, EmptyCString(), 0, getter_AddRefs(incomingServerToUse));
|
||||
int32_t dotPos = -1;
|
||||
if (!incomingServerToUse && useMatchingDomainServer
|
||||
&& (dotPos = hostName.FindChar('.')) != kNotFound)
|
||||
{
|
||||
hostName.Cut(0, dotPos);
|
||||
nsCOMPtr<nsIArray> allServers;
|
||||
accountManager->GetAllServers(getter_AddRefs(allServers));
|
||||
if (allServers)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
allServers->GetLength(&count);
|
||||
uint32_t i;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
nsCOMPtr<nsIMsgIncomingServer> server = do_QueryElementAt(allServers, i);
|
||||
if (server)
|
||||
{
|
||||
nsCString serverUserName;
|
||||
nsCString serverHostName;
|
||||
server->GetRealUsername(serverUserName);
|
||||
server->GetRealHostName(serverHostName);
|
||||
if (serverUserName.Equals(userName))
|
||||
{
|
||||
int32_t serverDotPos = serverHostName.FindChar('.');
|
||||
if (serverDotPos != kNotFound)
|
||||
{
|
||||
serverHostName.Cut(0, serverDotPos);
|
||||
if (serverHostName.Equals(hostName))
|
||||
{
|
||||
incomingServerToUse = server;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (incomingServerToUse)
|
||||
return incomingServerToUse->GetPassword(aPassword);
|
||||
}
|
||||
aPassword = m_password;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::VerifyLogon(nsIUrlListener *aUrlListener, nsIMsgWindow *aMsgWindow,
|
||||
nsIURI **aURL)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISmtpService> smtpService(do_GetService(NS_SMTPSERVICE_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return smtpService->VerifyLogon(this, aUrlListener, aMsgWindow, aURL);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::SetPassword(const nsACString& aPassword)
|
||||
{
|
||||
m_password = aPassword;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSmtpServer::GetPasswordWithoutUI()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsILoginManager> loginMgr(do_GetService(NS_LOGINMANAGER_CONTRACTID,
|
||||
&rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ConvertASCIItoUTF16 serverUri(GetServerURIInternal(false));
|
||||
|
||||
uint32_t numLogins = 0;
|
||||
nsILoginInfo** logins = nullptr;
|
||||
rv = loginMgr->FindLogins(&numLogins, serverUri, EmptyString(),
|
||||
serverUri, &logins);
|
||||
// Login manager can produce valid fails, e.g. NS_ERROR_ABORT when a user
|
||||
// cancels the master password dialog. Therefore handle that here, but don't
|
||||
// warn about it.
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Don't abort here, if we didn't find any or failed, then we'll just have
|
||||
// to prompt.
|
||||
if (numLogins > 0)
|
||||
{
|
||||
nsCString serverCUsername;
|
||||
rv = GetUsername(serverCUsername);
|
||||
NS_ConvertASCIItoUTF16 serverUsername(serverCUsername);
|
||||
|
||||
nsString username;
|
||||
for (uint32_t i = 0; i < numLogins; ++i)
|
||||
{
|
||||
rv = logins[i]->GetUsername(username);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (username.Equals(serverUsername))
|
||||
{
|
||||
nsString password;
|
||||
rv = logins[i]->GetPassword(password);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
LossyCopyUTF16toASCII(password, m_password);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(numLogins, logins);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::GetPasswordWithUI(const char16_t *aPromptMessage,
|
||||
const char16_t *aPromptTitle,
|
||||
nsIAuthPrompt* aDialog,
|
||||
nsACString &aPassword)
|
||||
{
|
||||
if (!m_password.IsEmpty())
|
||||
return GetPassword(aPassword);
|
||||
|
||||
// We need to get a password, but see if we can get it from the password
|
||||
// manager without requiring a prompt.
|
||||
nsresult rv = GetPasswordWithoutUI();
|
||||
if (rv == NS_ERROR_ABORT)
|
||||
return NS_MSG_PASSWORD_PROMPT_CANCELLED;
|
||||
|
||||
// Now re-check if we've got a password or not, if we have, then we
|
||||
// don't need to prompt the user.
|
||||
if (!m_password.IsEmpty())
|
||||
{
|
||||
aPassword = m_password;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aDialog);
|
||||
|
||||
// PromptPassword needs the username as well.
|
||||
nsCString serverUri(GetServerURIInternal(true));
|
||||
|
||||
bool okayValue = true;
|
||||
nsString uniPassword;
|
||||
|
||||
rv = aDialog->PromptPassword(aPromptTitle, aPromptMessage,
|
||||
NS_ConvertASCIItoUTF16(serverUri).get(),
|
||||
nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
|
||||
getter_Copies(uniPassword), &okayValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If the user pressed cancel, just return an empty string.
|
||||
if (!okayValue)
|
||||
{
|
||||
aPassword.Truncate();
|
||||
return NS_MSG_PASSWORD_PROMPT_CANCELLED;
|
||||
}
|
||||
|
||||
NS_LossyConvertUTF16toASCII password(uniPassword);
|
||||
|
||||
rv = SetPassword(password);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aPassword = password;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::GetUsernamePasswordWithUI(const char16_t * aPromptMessage, const
|
||||
char16_t *aPromptTitle,
|
||||
nsIAuthPrompt* aDialog,
|
||||
nsACString &aUsername,
|
||||
nsACString &aPassword)
|
||||
{
|
||||
nsresult rv;
|
||||
if (!m_password.IsEmpty())
|
||||
{
|
||||
rv = GetUsername(aUsername);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return GetPassword(aPassword);
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aDialog);
|
||||
|
||||
nsCString serverUri;
|
||||
rv = GetServerURI(serverUri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsString uniUsername;
|
||||
nsString uniPassword;
|
||||
bool okayValue = true;
|
||||
|
||||
rv = aDialog->PromptUsernameAndPassword(aPromptTitle, aPromptMessage,
|
||||
NS_ConvertASCIItoUTF16(serverUri).get(),
|
||||
nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
|
||||
getter_Copies(uniUsername),
|
||||
getter_Copies(uniPassword),
|
||||
&okayValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If the user pressed cancel, just return emtpy strings.
|
||||
if (!okayValue)
|
||||
{
|
||||
aUsername.Truncate();
|
||||
aPassword.Truncate();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// We got a username and password back...so remember them.
|
||||
NS_LossyConvertUTF16toASCII username(uniUsername);
|
||||
|
||||
rv = SetUsername(username);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_LossyConvertUTF16toASCII password(uniPassword);
|
||||
|
||||
rv = SetPassword(password);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aUsername = username;
|
||||
aPassword = password;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::ForgetPassword()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsILoginManager> loginMgr =
|
||||
do_GetService(NS_LOGINMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Get the current server URI without the username
|
||||
nsAutoCString serverUri(NS_LITERAL_CSTRING("smtp://"));
|
||||
|
||||
nsCString hostname;
|
||||
rv = GetHostname(hostname);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !hostname.IsEmpty()) {
|
||||
nsCString escapedHostname;
|
||||
MsgEscapeString(hostname, nsINetUtil::ESCAPE_URL_PATH, escapedHostname);
|
||||
// not all servers have a hostname
|
||||
serverUri.Append(escapedHostname);
|
||||
}
|
||||
|
||||
uint32_t count;
|
||||
nsILoginInfo** logins;
|
||||
|
||||
NS_ConvertUTF8toUTF16 currServer(serverUri);
|
||||
|
||||
nsCString serverCUsername;
|
||||
rv = GetUsername(serverCUsername);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ConvertUTF8toUTF16 serverUsername(serverCUsername);
|
||||
|
||||
rv = loginMgr->FindLogins(&count, currServer, EmptyString(),
|
||||
currServer, &logins);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// There should only be one-login stored for this url, however just in case
|
||||
// there isn't.
|
||||
nsString username;
|
||||
for (uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
if (NS_SUCCEEDED(logins[i]->GetUsername(username)) &&
|
||||
username.Equals(serverUsername))
|
||||
{
|
||||
// If this fails, just continue, we'll still want to remove the password
|
||||
// from our local cache.
|
||||
loginMgr->RemoveLogin(logins[i]);
|
||||
}
|
||||
}
|
||||
NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
|
||||
|
||||
rv = SetPassword(EmptyCString());
|
||||
m_logonFailed = true;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::GetServerURI(nsACString &aResult)
|
||||
{
|
||||
aResult = GetServerURIInternal(true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCString
|
||||
nsSmtpServer::GetServerURIInternal(const bool aIncludeUsername)
|
||||
{
|
||||
nsCString uri(NS_LITERAL_CSTRING("smtp://"));
|
||||
nsresult rv;
|
||||
|
||||
if (aIncludeUsername)
|
||||
{
|
||||
nsCString username;
|
||||
rv = GetUsername(username);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !username.IsEmpty()) {
|
||||
nsCString escapedUsername;
|
||||
MsgEscapeString(username, nsINetUtil::ESCAPE_XALPHAS, escapedUsername);
|
||||
// not all servers have a username
|
||||
uri.Append(escapedUsername);
|
||||
uri.AppendLiteral("@");
|
||||
}
|
||||
}
|
||||
|
||||
nsCString hostname;
|
||||
rv = GetHostname(hostname);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !hostname.IsEmpty()) {
|
||||
nsCString escapedHostname;
|
||||
MsgEscapeString(hostname, nsINetUtil::ESCAPE_URL_PATH, escapedHostname);
|
||||
// not all servers have a hostname
|
||||
uri.Append(escapedHostname);
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpServer::ClearAllValues()
|
||||
{
|
||||
return mPrefBranch->DeleteBranch("");
|
||||
}
|
||||
40
mailnews/compose/src/nsSmtpServer.h
Normal file
40
mailnews/compose/src/nsSmtpServer.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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 __nsSmtpServer_h_
|
||||
#define __nsSmtpServer_h_
|
||||
|
||||
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsISmtpServer.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
class nsSmtpServer : public nsISmtpServer,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
nsSmtpServer();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISMTPSERVER
|
||||
|
||||
private:
|
||||
virtual ~nsSmtpServer();
|
||||
nsCString mKey;
|
||||
nsCOMPtr<nsIPrefBranch> mPrefBranch;
|
||||
nsCOMPtr<nsIPrefBranch> mDefPrefBranch;
|
||||
|
||||
nsresult getPrefs();
|
||||
void getIntPrefWithDefault(const char *prefName, int32_t *val,
|
||||
int32_t defval);
|
||||
nsresult GetPasswordWithoutUI();
|
||||
nsCString GetServerURIInternal(const bool aIncludeUsername);
|
||||
|
||||
nsCString m_password;
|
||||
bool m_logonFailed;
|
||||
};
|
||||
|
||||
#endif
|
||||
772
mailnews/compose/src/nsSmtpService.cpp
Normal file
772
mailnews/compose/src/nsSmtpService.cpp
Normal file
|
|
@ -0,0 +1,772 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "msgCore.h" // precompiled header...
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIPipe.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsSmtpService.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsMsgCompCID.h"
|
||||
#include "nsArrayEnumerator.h"
|
||||
#include "nsSmtpUrl.h"
|
||||
#include "nsSmtpProtocol.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIMsgIdentity.h"
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
#include "nsIUTF8ConverterService.h"
|
||||
#include "nsUConvCID.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsComposeStrings.h"
|
||||
#include "nsIAsyncInputStream.h"
|
||||
#include "nsIPrincipal.h"
|
||||
|
||||
#define SERVER_DELIMITER ','
|
||||
#define APPEND_SERVERS_VERSION_PREF_NAME "append_preconfig_smtpservers.version"
|
||||
#define MAIL_ROOT_PREF "mail."
|
||||
#define PREF_MAIL_SMTPSERVERS "mail.smtpservers"
|
||||
#define PREF_MAIL_SMTPSERVERS_APPEND_SERVERS "mail.smtpservers.appendsmtpservers"
|
||||
#define PREF_MAIL_SMTP_DEFAULTSERVER "mail.smtp.defaultserver"
|
||||
|
||||
typedef struct _findServerByKeyEntry {
|
||||
const char *key;
|
||||
nsISmtpServer *server;
|
||||
} findServerByKeyEntry;
|
||||
|
||||
typedef struct _findServerByHostnameEntry {
|
||||
nsCString hostname;
|
||||
nsCString username;
|
||||
nsISmtpServer *server;
|
||||
} findServerByHostnameEntry;
|
||||
|
||||
static NS_DEFINE_CID(kCSmtpUrlCID, NS_SMTPURL_CID);
|
||||
static NS_DEFINE_CID(kCMailtoUrlCID, NS_MAILTOURL_CID);
|
||||
|
||||
// foward declarations...
|
||||
nsresult
|
||||
NS_MsgBuildSmtpUrl(nsIFile * aFilePath,
|
||||
nsISmtpServer *aServer,
|
||||
const char* aRecipients,
|
||||
nsIMsgIdentity * aSenderIdentity,
|
||||
nsIUrlListener * aUrlListener,
|
||||
nsIMsgStatusFeedback *aStatusFeedback,
|
||||
nsIInterfaceRequestor* aNotificationCallbacks,
|
||||
nsIURI ** aUrl,
|
||||
bool aRequestDSN);
|
||||
|
||||
nsresult NS_MsgLoadSmtpUrl(nsIURI * aUrl, nsISupports * aConsumer, nsIRequest ** aRequest);
|
||||
|
||||
nsSmtpService::nsSmtpService() :
|
||||
mSmtpServersLoaded(false)
|
||||
{
|
||||
}
|
||||
|
||||
nsSmtpService::~nsSmtpService()
|
||||
{
|
||||
// save the SMTP servers to disk
|
||||
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsSmtpService, nsISmtpService, nsIProtocolHandler)
|
||||
|
||||
|
||||
NS_IMETHODIMP nsSmtpService::SendMailMessage(nsIFile * aFilePath,
|
||||
const char * aRecipients,
|
||||
nsIMsgIdentity * aSenderIdentity,
|
||||
const char * aPassword,
|
||||
nsIUrlListener * aUrlListener,
|
||||
nsIMsgStatusFeedback *aStatusFeedback,
|
||||
nsIInterfaceRequestor* aNotificationCallbacks,
|
||||
bool aRequestDSN,
|
||||
nsIURI ** aURL,
|
||||
nsIRequest ** aRequest)
|
||||
{
|
||||
nsIURI * urlToRun = nullptr;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsCOMPtr<nsISmtpServer> smtpServer;
|
||||
rv = GetServerByIdentity(aSenderIdentity, getter_AddRefs(smtpServer));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && smtpServer)
|
||||
{
|
||||
if (aPassword && *aPassword)
|
||||
smtpServer->SetPassword(nsDependentCString(aPassword));
|
||||
|
||||
// this ref counts urlToRun
|
||||
rv = NS_MsgBuildSmtpUrl(aFilePath, smtpServer, aRecipients, aSenderIdentity,
|
||||
aUrlListener, aStatusFeedback,
|
||||
aNotificationCallbacks, &urlToRun, aRequestDSN);
|
||||
if (NS_SUCCEEDED(rv) && urlToRun)
|
||||
rv = NS_MsgLoadSmtpUrl(urlToRun, nullptr, aRequest);
|
||||
|
||||
if (aURL) // does the caller want a handle on the url?
|
||||
*aURL = urlToRun; // transfer our ref count to the caller....
|
||||
else
|
||||
NS_IF_RELEASE(urlToRun);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// The following are two convience functions I'm using to help expedite building and running a mail to url...
|
||||
|
||||
// short cut function for creating a mailto url...
|
||||
nsresult NS_MsgBuildSmtpUrl(nsIFile * aFilePath,
|
||||
nsISmtpServer *aSmtpServer,
|
||||
const char * aRecipients,
|
||||
nsIMsgIdentity * aSenderIdentity,
|
||||
nsIUrlListener * aUrlListener,
|
||||
nsIMsgStatusFeedback *aStatusFeedback,
|
||||
nsIInterfaceRequestor* aNotificationCallbacks,
|
||||
nsIURI ** aUrl,
|
||||
bool aRequestDSN)
|
||||
{
|
||||
// mscott: this function is a convience hack until netlib actually dispatches
|
||||
// smtp urls. in addition until we have a session to get a password, host and
|
||||
// other stuff from, we need to use default values....
|
||||
// ..for testing purposes....
|
||||
|
||||
nsCString smtpHostName;
|
||||
nsCString smtpUserName;
|
||||
int32_t smtpPort;
|
||||
int32_t socketType;
|
||||
|
||||
aSmtpServer->GetHostname(smtpHostName);
|
||||
aSmtpServer->GetUsername(smtpUserName);
|
||||
aSmtpServer->GetPort(&smtpPort);
|
||||
aSmtpServer->GetSocketType(&socketType);
|
||||
|
||||
if (!smtpPort)
|
||||
smtpPort = (socketType == nsMsgSocketType::SSL) ?
|
||||
nsISmtpUrl::DEFAULT_SMTPS_PORT : nsISmtpUrl::DEFAULT_SMTP_PORT;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISmtpUrl> smtpUrl(do_CreateInstance(kCSmtpUrlCID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString urlSpec("smtp://");
|
||||
|
||||
if (!smtpUserName.IsEmpty())
|
||||
{
|
||||
nsCString escapedUsername;
|
||||
MsgEscapeString(smtpUserName, nsINetUtil::ESCAPE_XALPHAS,
|
||||
escapedUsername);
|
||||
urlSpec.Append(escapedUsername);
|
||||
urlSpec.Append('@');
|
||||
}
|
||||
|
||||
urlSpec.Append(smtpHostName);
|
||||
if (smtpHostName.FindChar(':') == -1)
|
||||
{
|
||||
urlSpec.Append(':');
|
||||
urlSpec.AppendInt(smtpPort);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIMsgMailNewsUrl> url(do_QueryInterface(smtpUrl, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = url->SetSpec(urlSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
smtpUrl->SetRecipients(aRecipients);
|
||||
smtpUrl->SetRequestDSN(aRequestDSN);
|
||||
smtpUrl->SetPostMessageFile(aFilePath);
|
||||
smtpUrl->SetSenderIdentity(aSenderIdentity);
|
||||
if (aNotificationCallbacks)
|
||||
smtpUrl->SetNotificationCallbacks(aNotificationCallbacks);
|
||||
smtpUrl->SetSmtpServer(aSmtpServer);
|
||||
|
||||
nsCOMPtr<nsIPrompt> smtpPrompt(do_GetInterface(aNotificationCallbacks));
|
||||
nsCOMPtr<nsIAuthPrompt> smtpAuthPrompt(do_GetInterface(aNotificationCallbacks));
|
||||
if (!smtpPrompt || !smtpAuthPrompt)
|
||||
{
|
||||
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!smtpPrompt)
|
||||
wwatch->GetNewPrompter(0, getter_AddRefs(smtpPrompt));
|
||||
if (!smtpAuthPrompt)
|
||||
wwatch->GetNewAuthPrompter(0, getter_AddRefs(smtpAuthPrompt));
|
||||
}
|
||||
|
||||
smtpUrl->SetPrompt(smtpPrompt);
|
||||
smtpUrl->SetAuthPrompt(smtpAuthPrompt);
|
||||
|
||||
if (aUrlListener)
|
||||
url->RegisterListener(aUrlListener);
|
||||
if (aStatusFeedback)
|
||||
url->SetStatusFeedback(aStatusFeedback);
|
||||
|
||||
return CallQueryInterface(smtpUrl, aUrl);
|
||||
}
|
||||
|
||||
nsresult NS_MsgLoadSmtpUrl(nsIURI * aUrl, nsISupports * aConsumer, nsIRequest ** aRequest)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aUrl);
|
||||
|
||||
// For now, assume the url is an smtp url and load it.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISmtpUrl> smtpUrl(do_QueryInterface(aUrl, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Create a smtp protocol instance to run the url in.
|
||||
RefPtr<nsSmtpProtocol> smtpProtocol = new nsSmtpProtocol(aUrl);
|
||||
if (!smtpProtocol)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// Protocol will get destroyed when url is completed.
|
||||
rv = smtpProtocol->LoadUrl(aUrl, aConsumer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return CallQueryInterface(smtpProtocol.get(), aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSmtpService::VerifyLogon(nsISmtpServer *aServer,
|
||||
nsIUrlListener *aUrlListener,
|
||||
nsIMsgWindow *aMsgWindow,
|
||||
nsIURI **aURL)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aServer);
|
||||
nsCString popHost;
|
||||
nsCString popUser;
|
||||
nsCOMPtr <nsIURI> urlToRun;
|
||||
|
||||
nsresult rv = NS_MsgBuildSmtpUrl(nullptr, aServer,
|
||||
nullptr, nullptr, aUrlListener, nullptr,
|
||||
nullptr , getter_AddRefs(urlToRun), false);
|
||||
if (NS_SUCCEEDED(rv) && urlToRun)
|
||||
{
|
||||
nsCOMPtr<nsIMsgMailNewsUrl> url(do_QueryInterface(urlToRun, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
url->SetMsgWindow(aMsgWindow);
|
||||
rv = NS_MsgLoadSmtpUrl(urlToRun, nullptr, nullptr /* aRequest */);
|
||||
if (aURL)
|
||||
urlToRun.forget(aURL);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSmtpService::GetScheme(nsACString &aScheme)
|
||||
{
|
||||
aScheme = "mailto";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSmtpService::GetDefaultPort(int32_t *aDefaultPort)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (aDefaultPort)
|
||||
*aDefaultPort = nsISmtpUrl::DEFAULT_SMTP_PORT;
|
||||
else
|
||||
rv = NS_ERROR_NULL_POINTER;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpService::AllowPort(int32_t port, const char *scheme, bool *_retval)
|
||||
{
|
||||
// allow smtp to run on any port
|
||||
*_retval = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSmtpService::GetProtocolFlags(uint32_t *result)
|
||||
{
|
||||
*result = URI_NORELATIVE | ALLOWS_PROXY | URI_LOADABLE_BY_ANYONE |
|
||||
URI_NON_PERSISTABLE | URI_DOES_NOT_RETURN_DATA |
|
||||
URI_FORBIDS_COOKIE_ACCESS;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// the smtp service is also the protocol handler for mailto urls....
|
||||
|
||||
NS_IMETHODIMP nsSmtpService::NewURI(const nsACString &aSpec,
|
||||
const char *aOriginCharset,
|
||||
nsIURI *aBaseURI,
|
||||
nsIURI **_retval)
|
||||
{
|
||||
// get a new smtp url
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIURI> mailtoUrl = do_CreateInstance(kCMailtoUrlCID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString utf8Spec;
|
||||
if (aOriginCharset)
|
||||
{
|
||||
nsCOMPtr<nsIUTF8ConverterService>
|
||||
utf8Converter(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID, &rv));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = utf8Converter->ConvertURISpecToUTF8(aSpec, aOriginCharset, utf8Spec);
|
||||
}
|
||||
|
||||
// utf8Spec is filled up only when aOriginCharset is specified and
|
||||
// the conversion is successful. Otherwise, fall back to aSpec.
|
||||
if (aOriginCharset && NS_SUCCEEDED(rv))
|
||||
rv = mailtoUrl->SetSpec(utf8Spec);
|
||||
else
|
||||
rv = mailtoUrl->SetSpec(aSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mailtoUrl.forget(_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSmtpService::NewChannel(nsIURI *aURI, nsIChannel **_retval)
|
||||
{
|
||||
return NewChannel2(aURI, nullptr, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSmtpService::NewChannel2(nsIURI *aURI,
|
||||
nsILoadInfo* aLoadInfo,
|
||||
nsIChannel **_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
// create an empty pipe for use with the input stream channel.
|
||||
nsCOMPtr<nsIAsyncInputStream> pipeIn;
|
||||
nsCOMPtr<nsIAsyncOutputStream> pipeOut;
|
||||
nsCOMPtr<nsIPipe> pipe = do_CreateInstance("@mozilla.org/pipe;1");
|
||||
nsresult rv = pipe->Init(false, false, 0, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// These always succeed because the pipe is initialized above.
|
||||
MOZ_ALWAYS_SUCCEEDS(pipe->GetInputStream(getter_AddRefs(pipeIn)));
|
||||
MOZ_ALWAYS_SUCCEEDS(pipe->GetOutputStream(getter_AddRefs(pipeOut)));
|
||||
|
||||
pipeOut->Close();
|
||||
|
||||
if (aLoadInfo) {
|
||||
return NS_NewInputStreamChannelInternal(_retval,
|
||||
aURI,
|
||||
pipeIn,
|
||||
NS_LITERAL_CSTRING("application/x-mailto"),
|
||||
EmptyCString(),
|
||||
aLoadInfo);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> nullPrincipal =
|
||||
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "CreateInstance of nullprincipal failed.");
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
return NS_NewInputStreamChannel(_retval, aURI, pipeIn,
|
||||
nullPrincipal, nsILoadInfo::SEC_NORMAL,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
NS_LITERAL_CSTRING("application/x-mailto"));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpService::GetServers(nsISimpleEnumerator **aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
// now read in the servers from prefs if necessary
|
||||
uint32_t serverCount = mSmtpServers.Count();
|
||||
|
||||
if (serverCount <= 0)
|
||||
loadSmtpServers();
|
||||
|
||||
return NS_NewArrayEnumerator(aResult, mSmtpServers);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSmtpService::loadSmtpServers()
|
||||
{
|
||||
if (mSmtpServersLoaded)
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefService> prefService(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
nsCOMPtr<nsIPrefBranch> prefRootBranch;
|
||||
prefService->GetBranch(nullptr, getter_AddRefs(prefRootBranch));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCString serverList;
|
||||
rv = prefRootBranch->GetCharPref(PREF_MAIL_SMTPSERVERS, getter_Copies(serverList));
|
||||
serverList.StripWhitespace();
|
||||
|
||||
nsTArray<nsCString> servers;
|
||||
ParseString(serverList, SERVER_DELIMITER, servers);
|
||||
|
||||
/**
|
||||
* Check to see if we need to add pre-configured smtp servers.
|
||||
* Following prefs are important to note in understanding the procedure here.
|
||||
*
|
||||
* 1. pref("mailnews.append_preconfig_smtpservers.version", version number);
|
||||
* This pref registers the current version in the user prefs file. A default value
|
||||
* is stored in mailnews.js file. If a given vendor needs to add more preconfigured
|
||||
* smtp servers, the default version number can be increased. Comparing version
|
||||
* number from user's prefs file and the default one from mailnews.js, we
|
||||
* can add new smtp servers and any other version level changes that need to be done.
|
||||
*
|
||||
* 2. pref("mail.smtpservers.appendsmtpservers", <comma separated servers list>);
|
||||
* This pref contains the list of pre-configured smp servers that ISP/Vendor wants to
|
||||
* to add to the existing servers list.
|
||||
*/
|
||||
nsCOMPtr<nsIPrefBranch> defaultsPrefBranch;
|
||||
rv = prefService->GetDefaultBranch(MAIL_ROOT_PREF, getter_AddRefs(defaultsPrefBranch));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch;
|
||||
rv = prefService->GetBranch(MAIL_ROOT_PREF, getter_AddRefs(prefBranch));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
int32_t appendSmtpServersCurrentVersion = 0;
|
||||
int32_t appendSmtpServersDefaultVersion = 0;
|
||||
rv = prefBranch->GetIntPref(APPEND_SERVERS_VERSION_PREF_NAME, &appendSmtpServersCurrentVersion);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = defaultsPrefBranch->GetIntPref(APPEND_SERVERS_VERSION_PREF_NAME, &appendSmtpServersDefaultVersion);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
// Update the smtp server list if needed
|
||||
if (appendSmtpServersCurrentVersion <= appendSmtpServersDefaultVersion) {
|
||||
// If there are pre-configured servers, add them to the existing server list
|
||||
nsCString appendServerList;
|
||||
rv = prefRootBranch->GetCharPref(PREF_MAIL_SMTPSERVERS_APPEND_SERVERS, getter_Copies(appendServerList));
|
||||
appendServerList.StripWhitespace();
|
||||
ParseString(appendServerList, SERVER_DELIMITER, servers);
|
||||
|
||||
// Increase the version number so that updates will happen as and when needed
|
||||
prefBranch->SetIntPref(APPEND_SERVERS_VERSION_PREF_NAME, appendSmtpServersCurrentVersion + 1);
|
||||
}
|
||||
|
||||
// use GetServerByKey to check if the key (pref) is already in
|
||||
// in the list. If not it calls createKeyedServer directly.
|
||||
|
||||
for (uint32_t i = 0; i < servers.Length(); i++) {
|
||||
nsCOMPtr<nsISmtpServer> server;
|
||||
GetServerByKey(servers[i].get(), getter_AddRefs(server));
|
||||
}
|
||||
|
||||
saveKeyList();
|
||||
|
||||
mSmtpServersLoaded = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// save the list of keys
|
||||
nsresult
|
||||
nsSmtpService::saveKeyList()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return prefBranch->SetCharPref(PREF_MAIL_SMTPSERVERS, mServerKeyList.get());
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSmtpService::createKeyedServer(const char *key, nsISmtpServer** aResult)
|
||||
{
|
||||
if (!key) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISmtpServer> server = do_CreateInstance(NS_SMTPSERVER_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
server->SetKey(key);
|
||||
mSmtpServers.AppendObject(server);
|
||||
|
||||
if (mServerKeyList.IsEmpty())
|
||||
mServerKeyList = key;
|
||||
else {
|
||||
mServerKeyList.Append(',');
|
||||
mServerKeyList += key;
|
||||
}
|
||||
|
||||
if (aResult)
|
||||
server.swap(*aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpService::GetSessionDefaultServer(nsISmtpServer **aServer)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aServer);
|
||||
|
||||
if (!mSessionDefaultServer)
|
||||
return GetDefaultServer(aServer);
|
||||
|
||||
NS_ADDREF(*aServer = mSessionDefaultServer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpService::SetSessionDefaultServer(nsISmtpServer *aServer)
|
||||
{
|
||||
mSessionDefaultServer = aServer;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpService::GetDefaultServer(nsISmtpServer **aServer)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aServer);
|
||||
|
||||
loadSmtpServers();
|
||||
|
||||
*aServer = nullptr;
|
||||
// always returns NS_OK, just leaving *aServer at nullptr
|
||||
if (!mDefaultSmtpServer) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// try to get it from the prefs
|
||||
nsCString defaultServerKey;
|
||||
rv = prefBranch->GetCharPref(PREF_MAIL_SMTP_DEFAULTSERVER, getter_Copies(defaultServerKey));
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
!defaultServerKey.IsEmpty()) {
|
||||
|
||||
nsCOMPtr<nsISmtpServer> server;
|
||||
rv = GetServerByKey(defaultServerKey.get(),
|
||||
getter_AddRefs(mDefaultSmtpServer));
|
||||
} else {
|
||||
// no pref set, so just return the first one, and set the pref
|
||||
|
||||
// Ensure the list of servers is loaded
|
||||
loadSmtpServers();
|
||||
|
||||
// nothing in the array, we had better create a new server
|
||||
// (which will add it to the array & prefs anyway)
|
||||
if (mSmtpServers.Count() == 0)
|
||||
// if there are no smtp servers then don't create one for the default.
|
||||
return NS_OK;
|
||||
|
||||
mDefaultSmtpServer = mSmtpServers[0];
|
||||
NS_ENSURE_TRUE(mDefaultSmtpServer, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// now we have a default server, set the prefs correctly
|
||||
nsCString serverKey;
|
||||
mDefaultSmtpServer->GetKey(getter_Copies(serverKey));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
prefBranch->SetCharPref(PREF_MAIL_SMTP_DEFAULTSERVER, serverKey.get());
|
||||
}
|
||||
}
|
||||
|
||||
// at this point:
|
||||
// * mDefaultSmtpServer has a valid server
|
||||
// * the key has been set in the prefs
|
||||
|
||||
NS_IF_ADDREF(*aServer = mDefaultSmtpServer);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpService::SetDefaultServer(nsISmtpServer *aServer)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aServer);
|
||||
|
||||
mDefaultSmtpServer = aServer;
|
||||
|
||||
nsCString serverKey;
|
||||
nsresult rv = aServer->GetKey(getter_Copies(serverKey));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
prefBranch->SetCharPref(PREF_MAIL_SMTP_DEFAULTSERVER, serverKey.get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsSmtpService::findServerByKey(nsISmtpServer *aServer, void *aData)
|
||||
{
|
||||
findServerByKeyEntry *entry = (findServerByKeyEntry*) aData;
|
||||
|
||||
nsCString key;
|
||||
nsresult rv = aServer->GetKey(getter_Copies(key));
|
||||
if (NS_FAILED(rv))
|
||||
return true;
|
||||
|
||||
if (key.Equals(entry->key))
|
||||
{
|
||||
entry->server = aServer;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpService::CreateServer(nsISmtpServer **aResult)
|
||||
{
|
||||
if (!aResult) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
loadSmtpServers();
|
||||
nsresult rv;
|
||||
int32_t i = 0;
|
||||
bool unique = false;
|
||||
|
||||
findServerByKeyEntry entry;
|
||||
nsAutoCString key;
|
||||
|
||||
do {
|
||||
key = "smtp";
|
||||
key.AppendInt(++i);
|
||||
entry.key = key.get();
|
||||
entry.server = nullptr;
|
||||
|
||||
mSmtpServers.EnumerateForwards(findServerByKey, (void *)&entry);
|
||||
if (!entry.server) unique=true;
|
||||
|
||||
} while (!unique);
|
||||
|
||||
rv = createKeyedServer(key.get(), aResult);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return saveKeyList();
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsSmtpService::GetServerByKey(const char* aKey, nsISmtpServer **aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
if (!aKey || !*aKey)
|
||||
{
|
||||
NS_ASSERTION(false, "bad key");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
findServerByKeyEntry entry;
|
||||
entry.key = aKey;
|
||||
entry.server = nullptr;
|
||||
mSmtpServers.EnumerateForwards(findServerByKey, (void *)&entry);
|
||||
|
||||
if (entry.server) {
|
||||
NS_ADDREF(*aResult = entry.server);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// not found in array, I guess we load it
|
||||
return createKeyedServer(aKey, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpService::DeleteServer(nsISmtpServer *aServer)
|
||||
{
|
||||
if (!aServer) return NS_OK;
|
||||
|
||||
int32_t idx = mSmtpServers.IndexOf(aServer);
|
||||
if (idx == -1)
|
||||
return NS_OK;
|
||||
|
||||
nsCString serverKey;
|
||||
aServer->GetKey(getter_Copies(serverKey));
|
||||
|
||||
mSmtpServers.RemoveObjectAt(idx);
|
||||
|
||||
if (mDefaultSmtpServer.get() == aServer)
|
||||
mDefaultSmtpServer = nullptr;
|
||||
if (mSessionDefaultServer.get() == aServer)
|
||||
mSessionDefaultServer = nullptr;
|
||||
|
||||
nsAutoCString newServerList;
|
||||
nsCString tmpStr = mServerKeyList;
|
||||
char *newStr = tmpStr.BeginWriting();
|
||||
char *token = NS_strtok(",", &newStr);
|
||||
while (token) {
|
||||
// only re-add the string if it's not the key
|
||||
if (strcmp(token, serverKey.get()) != 0) {
|
||||
if (newServerList.IsEmpty())
|
||||
newServerList = token;
|
||||
else {
|
||||
newServerList += ',';
|
||||
newServerList += token;
|
||||
}
|
||||
}
|
||||
token = NS_strtok(",", &newStr);
|
||||
}
|
||||
|
||||
// make sure the server clears out it's values....
|
||||
aServer->ClearAllValues();
|
||||
|
||||
mServerKeyList = newServerList;
|
||||
saveKeyList();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsSmtpService::findServerByHostname(nsISmtpServer *aServer, void *aData)
|
||||
{
|
||||
findServerByHostnameEntry *entry = (findServerByHostnameEntry*)aData;
|
||||
|
||||
nsCString hostname;
|
||||
nsresult rv = aServer->GetHostname(hostname);
|
||||
if (NS_FAILED(rv))
|
||||
return true;
|
||||
|
||||
nsCString username;
|
||||
rv = aServer->GetUsername(username);
|
||||
if (NS_FAILED(rv))
|
||||
return true;
|
||||
|
||||
bool checkHostname = !entry->hostname.IsEmpty();
|
||||
bool checkUsername = !entry->username.IsEmpty();
|
||||
|
||||
if ((!checkHostname ||
|
||||
(entry->hostname.Equals(hostname, nsCaseInsensitiveCStringComparator()))) &&
|
||||
(!checkUsername ||
|
||||
entry->username.Equals(username, nsCaseInsensitiveCStringComparator())))
|
||||
{
|
||||
entry->server = aServer;
|
||||
return false; // stop when found
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpService::FindServer(const char *aUsername,
|
||||
const char *aHostname, nsISmtpServer ** aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
findServerByHostnameEntry entry;
|
||||
entry.server = nullptr;
|
||||
entry.hostname = aHostname;
|
||||
entry.username = aUsername;
|
||||
|
||||
mSmtpServers.EnumerateForwards(findServerByHostname, (void *)&entry);
|
||||
|
||||
// entry.server may be null, but that's ok.
|
||||
// just return null if no server is found
|
||||
NS_IF_ADDREF(*aResult = entry.server);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpService::GetServerByIdentity(nsIMsgIdentity *aSenderIdentity,
|
||||
nsISmtpServer **aSmtpServer)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSmtpServer);
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
// First try the identity's preferred server
|
||||
if (aSenderIdentity)
|
||||
{
|
||||
nsCString smtpServerKey;
|
||||
rv = aSenderIdentity->GetSmtpServerKey(smtpServerKey);
|
||||
if (NS_SUCCEEDED(rv) && !(smtpServerKey.IsEmpty()))
|
||||
rv = GetServerByKey(smtpServerKey.get(), aSmtpServer);
|
||||
}
|
||||
|
||||
// Fallback to the default
|
||||
if (NS_FAILED(rv) || !(*aSmtpServer))
|
||||
rv = GetDefaultServer(aSmtpServer);
|
||||
return rv;
|
||||
}
|
||||
63
mailnews/compose/src/nsSmtpService.h
Normal file
63
mailnews/compose/src/nsSmtpService.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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 nsSmtpService_h___
|
||||
#define nsSmtpService_h___
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsISmtpService.h"
|
||||
#include "nsISmtpServer.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// The Smtp Service is an interfaced designed to make building and running mail to urls
|
||||
// easier. I'm not sure if this service will go away when the new networking model comes
|
||||
// on line (as part of the N2 project). So I reserve the right to change my mind and take
|
||||
// this service away =).
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class nsSmtpService : public nsISmtpService, public nsIProtocolHandler
|
||||
{
|
||||
public:
|
||||
|
||||
nsSmtpService();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// we suppport the nsISmtpService interface
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
NS_DECL_NSISMTPSERVICE
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// we suppport the nsIProtocolHandler interface
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
NS_DECL_NSIPROTOCOLHANDLER
|
||||
|
||||
protected:
|
||||
nsresult loadSmtpServers();
|
||||
|
||||
|
||||
private:
|
||||
virtual ~nsSmtpService();
|
||||
static bool findServerByKey(nsISmtpServer *aServer, void *aData);
|
||||
static bool findServerByHostname(nsISmtpServer *aServer, void *aData);
|
||||
|
||||
nsresult createKeyedServer(const char* key,
|
||||
nsISmtpServer **aResult = nullptr);
|
||||
nsresult saveKeyList();
|
||||
|
||||
nsCOMArray<nsISmtpServer> mSmtpServers;
|
||||
nsCOMPtr<nsISmtpServer> mDefaultSmtpServer;
|
||||
nsCOMPtr<nsISmtpServer> mSessionDefaultServer;
|
||||
|
||||
nsCString mServerKeyList;
|
||||
|
||||
bool mSmtpServersLoaded;
|
||||
};
|
||||
|
||||
#endif /* nsSmtpService_h___ */
|
||||
778
mailnews/compose/src/nsSmtpUrl.cpp
Normal file
778
mailnews/compose/src/nsSmtpUrl.cpp
Normal file
|
|
@ -0,0 +1,778 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "msgCore.h"
|
||||
|
||||
#include "nsIURI.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsSmtpUrl.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "nsIMimeConverter.h"
|
||||
#include "nsMsgMimeCID.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// mailto url definition
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
nsMailtoUrl::nsMailtoUrl()
|
||||
{
|
||||
mFormat = nsIMsgCompFormat::Default;
|
||||
m_baseURL = do_CreateInstance(NS_SIMPLEURI_CONTRACTID);
|
||||
}
|
||||
|
||||
nsMailtoUrl::~nsMailtoUrl()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMailtoUrl, nsIMailtoUrl, nsIURI)
|
||||
|
||||
static void UnescapeAndConvert(nsIMimeConverter *mimeConverter,
|
||||
const nsACString &escaped, nsACString &out)
|
||||
{
|
||||
NS_ASSERTION(mimeConverter, "Set mimeConverter before calling!");
|
||||
// If the string is empty, do absolutely nothing.
|
||||
if (escaped.IsEmpty())
|
||||
return;
|
||||
|
||||
MsgUnescapeString(escaped, 0, out);
|
||||
nsAutoCString decodedString;
|
||||
nsresult rv = mimeConverter->DecodeMimeHeaderToUTF8(out, "UTF_8", false,
|
||||
true, decodedString);
|
||||
if (NS_SUCCEEDED(rv) && !decodedString.IsEmpty())
|
||||
out = decodedString;
|
||||
}
|
||||
|
||||
nsresult nsMailtoUrl::ParseMailtoUrl(char * searchPart)
|
||||
{
|
||||
char *rest = searchPart;
|
||||
nsCString escapedInReplyToPart;
|
||||
nsCString escapedToPart;
|
||||
nsCString escapedCcPart;
|
||||
nsCString escapedSubjectPart;
|
||||
nsCString escapedNewsgroupPart;
|
||||
nsCString escapedNewsHostPart;
|
||||
nsCString escapedReferencePart;
|
||||
nsCString escapedBodyPart;
|
||||
nsCString escapedBccPart;
|
||||
nsCString escapedFollowUpToPart;
|
||||
nsCString escapedFromPart;
|
||||
nsCString escapedHtmlPart;
|
||||
nsCString escapedOrganizationPart;
|
||||
nsCString escapedReplyToPart;
|
||||
nsCString escapedPriorityPart;
|
||||
|
||||
// okay, first, free up all of our old search part state.....
|
||||
CleanupMailtoState();
|
||||
// m_toPart has the escaped address from before the query string, copy it
|
||||
// over so we can add on any additional to= addresses and unescape them all.
|
||||
escapedToPart = m_toPart;
|
||||
|
||||
if (rest && *rest == '?')
|
||||
{
|
||||
/* start past the '?' */
|
||||
rest++;
|
||||
}
|
||||
|
||||
if (rest)
|
||||
{
|
||||
char *token = NS_strtok("&", &rest);
|
||||
while (token && *token)
|
||||
{
|
||||
char *value = 0;
|
||||
char *eq = PL_strchr(token, '=');
|
||||
if (eq)
|
||||
{
|
||||
value = eq+1;
|
||||
*eq = 0;
|
||||
}
|
||||
|
||||
nsCString decodedName;
|
||||
MsgUnescapeString(nsDependentCString(token), 0, decodedName);
|
||||
|
||||
if (decodedName.Length() == 0)
|
||||
break;
|
||||
|
||||
switch (NS_ToUpper(decodedName.First()))
|
||||
{
|
||||
/* DO NOT support attachment= in mailto urls. This poses a security fire hole!!!
|
||||
case 'A':
|
||||
if (!PL_strcasecmp (token, "attachment"))
|
||||
m_attachmentPart = value;
|
||||
break;
|
||||
*/
|
||||
case 'B':
|
||||
if (decodedName.LowerCaseEqualsLiteral("bcc"))
|
||||
{
|
||||
if (!escapedBccPart.IsEmpty())
|
||||
{
|
||||
escapedBccPart += ", ";
|
||||
escapedBccPart += value;
|
||||
}
|
||||
else
|
||||
escapedBccPart = value;
|
||||
}
|
||||
else if (decodedName.LowerCaseEqualsLiteral("body"))
|
||||
{
|
||||
if (!escapedBodyPart.IsEmpty())
|
||||
{
|
||||
escapedBodyPart +="\n";
|
||||
escapedBodyPart += value;
|
||||
}
|
||||
else
|
||||
escapedBodyPart = value;
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
if (decodedName.LowerCaseEqualsLiteral("cc"))
|
||||
{
|
||||
if (!escapedCcPart.IsEmpty())
|
||||
{
|
||||
escapedCcPart += ", ";
|
||||
escapedCcPart += value;
|
||||
}
|
||||
else
|
||||
escapedCcPart = value;
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
if (decodedName.LowerCaseEqualsLiteral("followup-to"))
|
||||
escapedFollowUpToPart = value;
|
||||
else if (decodedName.LowerCaseEqualsLiteral("from"))
|
||||
escapedFromPart = value;
|
||||
break;
|
||||
case 'H':
|
||||
if (decodedName.LowerCaseEqualsLiteral("html-part") ||
|
||||
decodedName.LowerCaseEqualsLiteral("html-body"))
|
||||
{
|
||||
// escapedHtmlPart holds the body for both html-part and html-body.
|
||||
escapedHtmlPart = value;
|
||||
mFormat = nsIMsgCompFormat::HTML;
|
||||
}
|
||||
break;
|
||||
case 'I':
|
||||
if (decodedName.LowerCaseEqualsLiteral("in-reply-to"))
|
||||
escapedInReplyToPart = value;
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
if (decodedName.LowerCaseEqualsLiteral("newsgroups"))
|
||||
escapedNewsgroupPart = value;
|
||||
else if (decodedName.LowerCaseEqualsLiteral("newshost"))
|
||||
escapedNewsHostPart = value;
|
||||
break;
|
||||
case 'O':
|
||||
if (decodedName.LowerCaseEqualsLiteral("organization"))
|
||||
escapedOrganizationPart = value;
|
||||
break;
|
||||
case 'R':
|
||||
if (decodedName.LowerCaseEqualsLiteral("references"))
|
||||
escapedReferencePart = value;
|
||||
else if (decodedName.LowerCaseEqualsLiteral("reply-to"))
|
||||
escapedReplyToPart = value;
|
||||
break;
|
||||
case 'S':
|
||||
if(decodedName.LowerCaseEqualsLiteral("subject"))
|
||||
escapedSubjectPart = value;
|
||||
break;
|
||||
case 'P':
|
||||
if (decodedName.LowerCaseEqualsLiteral("priority"))
|
||||
escapedPriorityPart = PL_strdup(value);
|
||||
break;
|
||||
case 'T':
|
||||
if (decodedName.LowerCaseEqualsLiteral("to"))
|
||||
{
|
||||
if (!escapedToPart.IsEmpty())
|
||||
{
|
||||
escapedToPart += ", ";
|
||||
escapedToPart += value;
|
||||
}
|
||||
else
|
||||
escapedToPart = value;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
} // end of switch statement...
|
||||
|
||||
if (eq)
|
||||
*eq = '='; /* put it back */
|
||||
token = NS_strtok("&", &rest);
|
||||
} // while we still have part of the url to parse...
|
||||
} // if rest && *rest
|
||||
|
||||
// Get a global converter
|
||||
nsCOMPtr<nsIMimeConverter> mimeConverter =
|
||||
do_GetService(NS_MIME_CONVERTER_CONTRACTID);
|
||||
|
||||
// Now unescape everything, and mime-decode the things that can be encoded.
|
||||
UnescapeAndConvert(mimeConverter, escapedToPart, m_toPart);
|
||||
UnescapeAndConvert(mimeConverter, escapedCcPart, m_ccPart);
|
||||
UnescapeAndConvert(mimeConverter, escapedBccPart, m_bccPart);
|
||||
UnescapeAndConvert(mimeConverter, escapedSubjectPart, m_subjectPart);
|
||||
UnescapeAndConvert(mimeConverter, escapedNewsgroupPart, m_newsgroupPart);
|
||||
UnescapeAndConvert(mimeConverter, escapedReferencePart, m_referencePart);
|
||||
if (!escapedBodyPart.IsEmpty())
|
||||
MsgUnescapeString(escapedBodyPart, 0, m_bodyPart);
|
||||
if (!escapedHtmlPart.IsEmpty())
|
||||
MsgUnescapeString(escapedHtmlPart, 0, m_htmlPart);
|
||||
UnescapeAndConvert(mimeConverter, escapedNewsHostPart, m_newsHostPart);
|
||||
UnescapeAndConvert(mimeConverter, escapedFollowUpToPart, m_followUpToPart);
|
||||
UnescapeAndConvert(mimeConverter, escapedFromPart, m_fromPart);
|
||||
UnescapeAndConvert(mimeConverter, escapedOrganizationPart, m_organizationPart);
|
||||
UnescapeAndConvert(mimeConverter, escapedReplyToPart, m_replyToPart);
|
||||
UnescapeAndConvert(mimeConverter, escapedPriorityPart, m_priorityPart);
|
||||
|
||||
nsCString inReplyToPart; // Not a member like the others...
|
||||
UnescapeAndConvert(mimeConverter, escapedInReplyToPart, inReplyToPart);
|
||||
|
||||
if (!inReplyToPart.IsEmpty())
|
||||
{
|
||||
// Ensure that References and In-Reply-To are consistent... The last
|
||||
// reference will be used as In-Reply-To header.
|
||||
if (m_referencePart.IsEmpty())
|
||||
{
|
||||
// If References is not set, set it to be the In-Reply-To.
|
||||
m_referencePart = inReplyToPart;
|
||||
}
|
||||
else
|
||||
{
|
||||
// References is set. Add the In-Reply-To as last header unless it's
|
||||
// set as last reference already.
|
||||
int32_t lastRefStart = m_referencePart.RFindChar('<');
|
||||
nsAutoCString lastReference;
|
||||
if (lastRefStart != -1)
|
||||
lastReference = StringTail(m_referencePart, lastRefStart);
|
||||
else
|
||||
lastReference = m_referencePart;
|
||||
|
||||
if (lastReference != inReplyToPart)
|
||||
{
|
||||
m_referencePart += " ";
|
||||
m_referencePart += inReplyToPart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::SetSpec(const nsACString &aSpec)
|
||||
{
|
||||
nsresult rv = m_baseURL->SetSpec(aSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return ParseUrl();
|
||||
}
|
||||
|
||||
nsresult nsMailtoUrl::CleanupMailtoState()
|
||||
{
|
||||
m_ccPart = "";
|
||||
m_subjectPart = "";
|
||||
m_newsgroupPart = "";
|
||||
m_newsHostPart = "";
|
||||
m_referencePart = "";
|
||||
m_bodyPart = "";
|
||||
m_bccPart = "";
|
||||
m_followUpToPart = "";
|
||||
m_fromPart = "";
|
||||
m_htmlPart = "";
|
||||
m_organizationPart = "";
|
||||
m_replyToPart = "";
|
||||
m_priorityPart = "";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMailtoUrl::ParseUrl()
|
||||
{
|
||||
// we can get the path from the simple url.....
|
||||
nsCString escapedPath;
|
||||
m_baseURL->GetPath(escapedPath);
|
||||
|
||||
int32_t startOfSearchPart = escapedPath.FindChar('?');
|
||||
if (startOfSearchPart >= 0)
|
||||
{
|
||||
// now parse out the search field...
|
||||
nsAutoCString searchPart(Substring(escapedPath, startOfSearchPart));
|
||||
|
||||
if (!searchPart.IsEmpty())
|
||||
{
|
||||
// now we need to strip off the search part from the
|
||||
// to part....
|
||||
escapedPath.SetLength(startOfSearchPart);
|
||||
MsgUnescapeString(escapedPath, 0, m_toPart);
|
||||
ParseMailtoUrl(searchPart.BeginWriting());
|
||||
}
|
||||
}
|
||||
else if (!escapedPath.IsEmpty())
|
||||
{
|
||||
MsgUnescapeString(escapedPath, 0, m_toPart);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMailtoUrl::GetMessageContents(nsACString &aToPart, nsACString &aCcPart,
|
||||
nsACString &aBccPart, nsACString &aSubjectPart,
|
||||
nsACString &aBodyPart, nsACString &aHtmlPart,
|
||||
nsACString &aReferencePart,
|
||||
nsACString &aNewsgroupPart,
|
||||
MSG_ComposeFormat *aFormat)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aFormat);
|
||||
|
||||
aToPart = m_toPart;
|
||||
aCcPart = m_ccPart;
|
||||
aBccPart = m_bccPart;
|
||||
aSubjectPart = m_subjectPart;
|
||||
aBodyPart = m_bodyPart;
|
||||
aHtmlPart = m_htmlPart;
|
||||
aReferencePart = m_referencePart;
|
||||
aNewsgroupPart = m_newsgroupPart;
|
||||
*aFormat = mFormat;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMailtoUrl::GetFromPart(nsACString &aResult)
|
||||
{
|
||||
aResult = m_fromPart;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMailtoUrl::GetFollowUpToPart(nsACString &aResult)
|
||||
{
|
||||
aResult = m_followUpToPart;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMailtoUrl::GetOrganizationPart(nsACString &aResult)
|
||||
{
|
||||
aResult = m_organizationPart;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMailtoUrl::GetReplyToPart(nsACString &aResult)
|
||||
{
|
||||
aResult = m_replyToPart;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMailtoUrl::GetPriorityPart(nsACString &aResult)
|
||||
{
|
||||
aResult = m_priorityPart;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMailtoUrl::GetNewsHostPart(nsACString &aResult)
|
||||
{
|
||||
aResult = m_newsHostPart;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Begin nsIURI support
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::GetSpec(nsACString &aSpec)
|
||||
{
|
||||
return m_baseURL->GetSpec(aSpec);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::GetPrePath(nsACString &aPrePath)
|
||||
{
|
||||
return m_baseURL->GetPrePath(aPrePath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::GetScheme(nsACString &aScheme)
|
||||
{
|
||||
return m_baseURL->GetScheme(aScheme);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::SetScheme(const nsACString &aScheme)
|
||||
{
|
||||
m_baseURL->SetScheme(aScheme);
|
||||
return ParseUrl();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::GetUserPass(nsACString &aUserPass)
|
||||
{
|
||||
return m_baseURL->GetUserPass(aUserPass);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::SetUserPass(const nsACString &aUserPass)
|
||||
{
|
||||
m_baseURL->SetUserPass(aUserPass);
|
||||
return ParseUrl();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::GetUsername(nsACString &aUsername)
|
||||
{
|
||||
return m_baseURL->GetUsername(aUsername);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::SetUsername(const nsACString &aUsername)
|
||||
{
|
||||
m_baseURL->SetUsername(aUsername);
|
||||
return ParseUrl();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::GetPassword(nsACString &aPassword)
|
||||
{
|
||||
return m_baseURL->GetPassword(aPassword);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::SetPassword(const nsACString &aPassword)
|
||||
{
|
||||
m_baseURL->SetPassword(aPassword);
|
||||
return ParseUrl();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::GetHostPort(nsACString &aHostPort)
|
||||
{
|
||||
return m_baseURL->GetHost(aHostPort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::SetHostPort(const nsACString &aHostPort)
|
||||
{
|
||||
m_baseURL->SetHost(aHostPort);
|
||||
return ParseUrl();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::SetHostAndPort(const nsACString &aHostPort)
|
||||
{
|
||||
m_baseURL->SetHostAndPort(aHostPort);
|
||||
return ParseUrl();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::GetHost(nsACString &aHost)
|
||||
{
|
||||
return m_baseURL->GetHost(aHost);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::SetHost(const nsACString &aHost)
|
||||
{
|
||||
m_baseURL->SetHost(aHost);
|
||||
return ParseUrl();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::GetPort(int32_t *aPort)
|
||||
{
|
||||
return m_baseURL->GetPort(aPort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::SetPort(int32_t aPort)
|
||||
{
|
||||
m_baseURL->SetPort(aPort);
|
||||
return ParseUrl();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::GetPath(nsACString &aPath)
|
||||
{
|
||||
return m_baseURL->GetPath(aPath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::SetPath(const nsACString &aPath)
|
||||
{
|
||||
m_baseURL->SetPath(aPath);
|
||||
return ParseUrl();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::GetAsciiHost(nsACString &aHostA)
|
||||
{
|
||||
return m_baseURL->GetAsciiHost(aHostA);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::GetAsciiHostPort(nsACString &aHostPortA)
|
||||
{
|
||||
return m_baseURL->GetAsciiHostPort(aHostPortA);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::GetAsciiSpec(nsACString &aSpecA)
|
||||
{
|
||||
return m_baseURL->GetAsciiSpec(aSpecA);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::GetOriginCharset(nsACString &aOriginCharset)
|
||||
{
|
||||
return m_baseURL->GetOriginCharset(aOriginCharset);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::SchemeIs(const char *aScheme, bool *_retval)
|
||||
{
|
||||
return m_baseURL->SchemeIs(aScheme, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::Equals(nsIURI *other, bool *_retval)
|
||||
{
|
||||
// The passed-in URI might be an nsMailtoUrl. Pass our inner URL to its
|
||||
// Equals method. The other nsMailtoUrl will then pass its inner URL to
|
||||
// to the Equals method of our inner URL. Other URIs will return false.
|
||||
if (other)
|
||||
return other->Equals(m_baseURL, _retval);
|
||||
|
||||
return m_baseURL->Equals(other, _retval);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMailtoUrl::CloneInternal(RefHandlingEnum aRefHandlingMode,
|
||||
const nsACString& newRef, nsIURI** _retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
RefPtr<nsMailtoUrl> clone = new nsMailtoUrl();
|
||||
|
||||
NS_ENSURE_TRUE(clone, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv;
|
||||
if (aRefHandlingMode == eHonorRef) {
|
||||
rv = m_baseURL->Clone(getter_AddRefs(clone->m_baseURL));
|
||||
} else if (aRefHandlingMode == eReplaceRef) {
|
||||
rv = m_baseURL->CloneWithNewRef(newRef, getter_AddRefs(clone->m_baseURL));
|
||||
} else {
|
||||
rv = m_baseURL->CloneIgnoringRef(getter_AddRefs(clone->m_baseURL));
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
clone->ParseUrl();
|
||||
clone.forget(_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMailtoUrl::Clone(nsIURI **_retval)
|
||||
{
|
||||
return CloneInternal(eHonorRef, EmptyCString(), _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMailtoUrl::CloneIgnoringRef(nsIURI** _retval)
|
||||
{
|
||||
return CloneInternal(eIgnoreRef, EmptyCString(), _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMailtoUrl::CloneWithNewRef(const nsACString& newRef, nsIURI** _retval)
|
||||
{
|
||||
return CloneInternal(eReplaceRef, newRef, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::Resolve(const nsACString &relativePath, nsACString &result)
|
||||
{
|
||||
return m_baseURL->Resolve(relativePath, result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::SetRef(const nsACString &aRef)
|
||||
{
|
||||
return m_baseURL->SetRef(aRef);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMailtoUrl::GetRef(nsACString &result)
|
||||
{
|
||||
return m_baseURL->GetRef(result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailtoUrl::EqualsExceptRef(nsIURI *other, bool *result)
|
||||
{
|
||||
// The passed-in URI might be an nsMailtoUrl. Pass our inner URL to its
|
||||
// Equals method. The other nsMailtoUrl will then pass its inner URL to
|
||||
// to the Equals method of our inner URL. Other URIs will return false.
|
||||
if (other)
|
||||
return other->EqualsExceptRef(m_baseURL, result);
|
||||
|
||||
return m_baseURL->EqualsExceptRef(other, result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMailtoUrl::GetSpecIgnoringRef(nsACString &result)
|
||||
{
|
||||
return m_baseURL->GetSpecIgnoringRef(result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMailtoUrl::GetHasRef(bool *result)
|
||||
{
|
||||
return m_baseURL->GetHasRef(result);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// smtp url definition
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsSmtpUrl::nsSmtpUrl() : nsMsgMailNewsUrl()
|
||||
{
|
||||
// nsISmtpUrl specific state...
|
||||
|
||||
m_isPostMessage = true;
|
||||
m_requestDSN = false;
|
||||
m_verifyLogon = false;
|
||||
}
|
||||
|
||||
nsSmtpUrl::~nsSmtpUrl()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(nsSmtpUrl, nsMsgMailNewsUrl, nsISmtpUrl)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Begin nsISmtpUrl specific support
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpUrl::SetRecipients(const char * aRecipientsList)
|
||||
{
|
||||
NS_ENSURE_ARG(aRecipientsList);
|
||||
MsgUnescapeString(nsDependentCString(aRecipientsList), 0, m_toPart);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpUrl::GetRecipients(char ** aRecipientsList)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRecipientsList);
|
||||
if (aRecipientsList)
|
||||
*aRecipientsList = ToNewCString(m_toPart);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_GETSET(nsSmtpUrl, PostMessage, bool, m_isPostMessage)
|
||||
|
||||
NS_IMPL_GETSET(nsSmtpUrl, VerifyLogon, bool, m_verifyLogon)
|
||||
|
||||
// the message can be stored in a file....allow accessors for getting and setting
|
||||
// the file name to post...
|
||||
NS_IMETHODIMP nsSmtpUrl::SetPostMessageFile(nsIFile * aFile)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aFile);
|
||||
m_fileName = aFile;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSmtpUrl::GetPostMessageFile(nsIFile ** aFile)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aFile);
|
||||
if (m_fileName)
|
||||
{
|
||||
// Clone the file so nsLocalFile stat caching doesn't make the caller get
|
||||
// the wrong file size.
|
||||
m_fileName->Clone(aFile);
|
||||
return *aFile ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
NS_IMPL_GETSET(nsSmtpUrl, RequestDSN, bool, m_requestDSN)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpUrl::SetDsnEnvid(const nsACString &aDsnEnvid)
|
||||
{
|
||||
m_dsnEnvid = aDsnEnvid;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpUrl::GetDsnEnvid(nsACString &aDsnEnvid)
|
||||
{
|
||||
aDsnEnvid = m_dsnEnvid;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpUrl::GetSenderIdentity(nsIMsgIdentity **aSenderIdentity)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSenderIdentity);
|
||||
*aSenderIdentity = m_senderIdentity;
|
||||
NS_ADDREF(*aSenderIdentity);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpUrl::SetSenderIdentity(nsIMsgIdentity *aSenderIdentity)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSenderIdentity);
|
||||
m_senderIdentity = aSenderIdentity;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpUrl::SetPrompt(nsIPrompt *aNetPrompt)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNetPrompt);
|
||||
m_netPrompt = aNetPrompt;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpUrl::GetPrompt(nsIPrompt **aNetPrompt)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNetPrompt);
|
||||
NS_ENSURE_TRUE(m_netPrompt, NS_ERROR_NULL_POINTER);
|
||||
*aNetPrompt = m_netPrompt;
|
||||
NS_ADDREF(*aNetPrompt);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpUrl::SetAuthPrompt(nsIAuthPrompt *aNetAuthPrompt)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNetAuthPrompt);
|
||||
m_netAuthPrompt = aNetAuthPrompt;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpUrl::GetAuthPrompt(nsIAuthPrompt **aNetAuthPrompt)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNetAuthPrompt);
|
||||
NS_ENSURE_TRUE(m_netAuthPrompt, NS_ERROR_NULL_POINTER);
|
||||
*aNetAuthPrompt = m_netAuthPrompt;
|
||||
NS_ADDREF(*aNetAuthPrompt);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpUrl::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCallbacks);
|
||||
m_callbacks = aCallbacks;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpUrl::GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCallbacks);
|
||||
NS_ENSURE_TRUE(m_callbacks, NS_ERROR_NULL_POINTER);
|
||||
*aCallbacks = m_callbacks;
|
||||
NS_ADDREF(*aCallbacks);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpUrl::SetSmtpServer(nsISmtpServer * aSmtpServer)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSmtpServer);
|
||||
m_smtpServer = aSmtpServer;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSmtpUrl::GetSmtpServer(nsISmtpServer ** aSmtpServer)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSmtpServer);
|
||||
NS_ENSURE_TRUE(m_smtpServer, NS_ERROR_NULL_POINTER);
|
||||
*aSmtpServer = m_smtpServer;
|
||||
NS_ADDREF(*aSmtpServer);
|
||||
return NS_OK;
|
||||
}
|
||||
100
mailnews/compose/src/nsSmtpUrl.h
Normal file
100
mailnews/compose/src/nsSmtpUrl.h
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/* -*- 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 nsSmtpUrl_h__
|
||||
#define nsSmtpUrl_h__
|
||||
|
||||
#include "nsISmtpUrl.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsMsgMailNewsUrl.h"
|
||||
#include "nsIMsgIdentity.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsIAuthPrompt.h"
|
||||
#include "nsISmtpServer.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
|
||||
class nsMailtoUrl : public nsIMailtoUrl, public nsIURI
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIURI
|
||||
NS_DECL_NSIMAILTOURL
|
||||
|
||||
nsMailtoUrl();
|
||||
|
||||
protected:
|
||||
enum RefHandlingEnum {
|
||||
eIgnoreRef,
|
||||
eHonorRef,
|
||||
eReplaceRef
|
||||
};
|
||||
virtual ~nsMailtoUrl();
|
||||
nsresult ParseUrl();
|
||||
nsresult CleanupMailtoState();
|
||||
nsresult ParseMailtoUrl(char * searchPart);
|
||||
nsresult CloneInternal(RefHandlingEnum aRefHandlingMode,
|
||||
const nsACString& newRef, nsIURI** _retval);
|
||||
|
||||
nsCOMPtr<nsIURI> m_baseURL;
|
||||
|
||||
// data retrieved from parsing the url: (Note the url could be a post from file or it could be in the url)
|
||||
nsCString m_toPart;
|
||||
nsCString m_ccPart;
|
||||
nsCString m_subjectPart;
|
||||
nsCString m_newsgroupPart;
|
||||
nsCString m_newsHostPart;
|
||||
nsCString m_referencePart;
|
||||
nsCString m_bodyPart;
|
||||
nsCString m_bccPart;
|
||||
nsCString m_followUpToPart;
|
||||
nsCString m_fromPart;
|
||||
nsCString m_htmlPart;
|
||||
nsCString m_organizationPart;
|
||||
nsCString m_replyToPart;
|
||||
nsCString m_priorityPart;
|
||||
|
||||
MSG_ComposeFormat mFormat;
|
||||
};
|
||||
|
||||
class nsSmtpUrl : public nsISmtpUrl, public nsMsgMailNewsUrl
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// From nsISmtpUrl
|
||||
NS_DECL_NSISMTPURL
|
||||
|
||||
// nsSmtpUrl
|
||||
nsSmtpUrl();
|
||||
|
||||
protected:
|
||||
virtual ~nsSmtpUrl();
|
||||
|
||||
// data retrieved from parsing the url: (Note the url could be a post from
|
||||
// file or it could be in the url)
|
||||
nsCString m_toPart;
|
||||
|
||||
bool m_isPostMessage;
|
||||
bool m_requestDSN;
|
||||
nsCString m_dsnEnvid;
|
||||
bool m_verifyLogon;
|
||||
|
||||
// Smtp specific event sinks
|
||||
nsCOMPtr<nsIFile> m_fileName;
|
||||
nsCOMPtr<nsIMsgIdentity> m_senderIdentity;
|
||||
nsCOMPtr<nsIPrompt> m_netPrompt;
|
||||
nsCOMPtr<nsIAuthPrompt> m_netAuthPrompt;
|
||||
nsCOMPtr<nsIInterfaceRequestor> m_callbacks;
|
||||
nsCOMPtr<nsISmtpServer> m_smtpServer;
|
||||
|
||||
// it is possible to encode the message to parse in the form of a url.
|
||||
// This function is used to decompose the search and path part into the bare
|
||||
// message components (to, fcc, bcc, etc.)
|
||||
nsresult ParseMessageToPost(char * searchPart);
|
||||
};
|
||||
|
||||
#endif // nsSmtpUrl_h__
|
||||
526
mailnews/compose/src/nsURLFetcher.cpp
Normal file
526
mailnews/compose/src/nsURLFetcher.cpp
Normal file
|
|
@ -0,0 +1,526 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "nsURLFetcher.h"
|
||||
|
||||
#include "msgCore.h" // for pre-compiled headers
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsNullPrincipal.h"
|
||||
#include <stdio.h>
|
||||
#include "nscore.h"
|
||||
#include "nsIFactory.h"
|
||||
#include "nsISupports.h"
|
||||
#include "prmem.h"
|
||||
#include "plstr.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIWebProgress.h"
|
||||
#include "nsMsgAttachmentHandler.h"
|
||||
#include "nsMsgSend.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsIStreamConverterService.h"
|
||||
#include "nsIMsgProgress.h"
|
||||
#include "nsMsgUtils.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsURLFetcher,
|
||||
nsIURLFetcher,
|
||||
nsIStreamListener,
|
||||
nsIRequestObserver,
|
||||
nsIURIContentListener,
|
||||
nsIInterfaceRequestor,
|
||||
nsIWebProgressListener,
|
||||
nsISupportsWeakReference)
|
||||
|
||||
|
||||
/*
|
||||
* Inherited methods for nsMimeConverter
|
||||
*/
|
||||
nsURLFetcher::nsURLFetcher()
|
||||
{
|
||||
// Init member variables...
|
||||
mTotalWritten = 0;
|
||||
mBuffer = nullptr;
|
||||
mBufferSize = 0;
|
||||
mStillRunning = true;
|
||||
mCallback = nullptr;
|
||||
mOnStopRequestProcessed = false;
|
||||
mIsFile=false;
|
||||
nsURLFetcherStreamConsumer *consumer = new nsURLFetcherStreamConsumer(this);
|
||||
mConverter = do_QueryInterface(consumer);
|
||||
}
|
||||
|
||||
nsURLFetcher::~nsURLFetcher()
|
||||
{
|
||||
mStillRunning = false;
|
||||
|
||||
PR_FREEIF(mBuffer);
|
||||
// Remove the DocShell as a listener of the old WebProgress...
|
||||
if (mLoadCookie)
|
||||
{
|
||||
nsCOMPtr<nsIWebProgress> webProgress(do_QueryInterface(mLoadCookie));
|
||||
|
||||
if (webProgress)
|
||||
webProgress->RemoveProgressListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsURLFetcher::GetInterface(const nsIID & aIID, void * *aInstancePtr)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aInstancePtr);
|
||||
return QueryInterface(aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
// nsIURIContentListener support
|
||||
NS_IMETHODIMP
|
||||
nsURLFetcher::OnStartURIOpen(nsIURI* aURI, bool* aAbortOpen)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsURLFetcher::IsPreferred(const char * aContentType,
|
||||
char ** aDesiredContentType,
|
||||
bool * aCanHandleContent)
|
||||
|
||||
{
|
||||
return CanHandleContent(aContentType, true, aDesiredContentType,
|
||||
aCanHandleContent);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsURLFetcher::CanHandleContent(const char * aContentType,
|
||||
bool aIsContentPreferred,
|
||||
char ** aDesiredContentType,
|
||||
bool * aCanHandleContent)
|
||||
|
||||
{
|
||||
if (!mIsFile && PL_strcasecmp(aContentType, MESSAGE_RFC822) == 0)
|
||||
*aDesiredContentType = strdup("text/html");
|
||||
|
||||
// since we explicilty loaded the url, we always want to handle it!
|
||||
*aCanHandleContent = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsURLFetcher::DoContent(const nsACString& aContentType,
|
||||
bool aIsContentPreferred,
|
||||
nsIRequest *request,
|
||||
nsIStreamListener ** aContentHandler,
|
||||
bool * aAbortProcess)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (aAbortProcess)
|
||||
*aAbortProcess = false;
|
||||
QueryInterface(NS_GET_IID(nsIStreamListener), (void **) aContentHandler);
|
||||
|
||||
/*
|
||||
Check the content-type to see if we need to insert a converter
|
||||
*/
|
||||
if (PL_strcasecmp(PromiseFlatCString(aContentType).get(), UNKNOWN_CONTENT_TYPE) == 0 ||
|
||||
PL_strcasecmp(PromiseFlatCString(aContentType).get(), MULTIPART_MIXED_REPLACE) == 0 ||
|
||||
PL_strcasecmp(PromiseFlatCString(aContentType).get(), MULTIPART_MIXED) == 0 ||
|
||||
PL_strcasecmp(PromiseFlatCString(aContentType).get(), MULTIPART_BYTERANGES) == 0)
|
||||
{
|
||||
rv = InsertConverter(PromiseFlatCString(aContentType).get());
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mConverterContentType = PromiseFlatCString(aContentType).get();
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsURLFetcher::GetParentContentListener(nsIURIContentListener** aParent)
|
||||
{
|
||||
*aParent = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsURLFetcher::SetParentContentListener(nsIURIContentListener* aParent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsURLFetcher::GetLoadCookie(nsISupports ** aLoadCookie)
|
||||
{
|
||||
*aLoadCookie = mLoadCookie;
|
||||
NS_IF_ADDREF(*aLoadCookie);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsURLFetcher::SetLoadCookie(nsISupports * aLoadCookie)
|
||||
{
|
||||
// Remove the DocShell as a listener of the old WebProgress...
|
||||
if (mLoadCookie)
|
||||
{
|
||||
nsCOMPtr<nsIWebProgress> webProgress(do_QueryInterface(mLoadCookie));
|
||||
|
||||
if (webProgress)
|
||||
webProgress->RemoveProgressListener(this);
|
||||
}
|
||||
|
||||
mLoadCookie = aLoadCookie;
|
||||
|
||||
// Add the DocShell as a listener to the new WebProgress...
|
||||
if (mLoadCookie)
|
||||
{
|
||||
nsCOMPtr<nsIWebProgress> webProgress(do_QueryInterface(mLoadCookie));
|
||||
|
||||
if (webProgress)
|
||||
webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_ALL);
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsURLFetcher::StillRunning(bool *running)
|
||||
{
|
||||
*running = mStillRunning;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// Methods for nsIStreamListener...
|
||||
nsresult
|
||||
nsURLFetcher::OnDataAvailable(nsIRequest *request, nsISupports * ctxt, nsIInputStream *aIStream,
|
||||
uint64_t sourceOffset, uint32_t aLength)
|
||||
{
|
||||
/* let our converter or consumer process the data */
|
||||
if (!mConverter)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return mConverter->OnDataAvailable(request, ctxt, aIStream, sourceOffset, aLength);
|
||||
}
|
||||
|
||||
|
||||
// Methods for nsIStreamObserver
|
||||
nsresult
|
||||
nsURLFetcher::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
|
||||
{
|
||||
/* check if the user has canceld the operation */
|
||||
if (mTagData)
|
||||
{
|
||||
nsCOMPtr<nsIMsgSend> sendPtr;
|
||||
mTagData->GetMimeDeliveryState(getter_AddRefs(sendPtr));
|
||||
if (sendPtr)
|
||||
{
|
||||
nsCOMPtr<nsIMsgProgress> progress;
|
||||
sendPtr->GetProgress(getter_AddRefs(progress));
|
||||
if (progress)
|
||||
{
|
||||
bool cancel = false;
|
||||
progress->GetProcessCanceledByUser(&cancel);
|
||||
if (cancel)
|
||||
return request->Cancel(NS_ERROR_ABORT);
|
||||
}
|
||||
}
|
||||
mTagData->mRequest = request;
|
||||
}
|
||||
|
||||
/* call our converter or consumer */
|
||||
if (mConverter)
|
||||
return mConverter->OnStartRequest(request, ctxt);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsURLFetcher::OnStopRequest(nsIRequest *request, nsISupports * ctxt, nsresult aStatus)
|
||||
{
|
||||
// it's possible we could get in here from the channel calling us with an OnStopRequest and from our
|
||||
// onStatusChange method (in the case of an error). So we should protect against this to make sure we
|
||||
// don't process the on stop request twice...
|
||||
|
||||
if (mOnStopRequestProcessed)
|
||||
return NS_OK;
|
||||
|
||||
mOnStopRequestProcessed = true;
|
||||
|
||||
/* first, call our converter or consumer */
|
||||
if (mConverter)
|
||||
(void) mConverter->OnStopRequest(request, ctxt, aStatus);
|
||||
|
||||
if (mTagData)
|
||||
mTagData->mRequest = nullptr;
|
||||
|
||||
//
|
||||
// Now complete the stream!
|
||||
//
|
||||
mStillRunning = false;
|
||||
|
||||
// time to close the output stream...
|
||||
if (mOutStream)
|
||||
{
|
||||
mOutStream->Close();
|
||||
mOutStream = nullptr;
|
||||
|
||||
/* In case of multipart/x-mixed-replace, we need to truncate the file to the current part size */
|
||||
if (MsgLowerCaseEqualsLiteral(mConverterContentType, MULTIPART_MIXED_REPLACE))
|
||||
{
|
||||
mLocalFile->SetFileSize(mTotalWritten);
|
||||
}
|
||||
}
|
||||
|
||||
// Now if there is a callback, we need to call it...
|
||||
if (mCallback)
|
||||
mCallback (aStatus, mContentType, mCharset, mTotalWritten, nullptr, mTagData);
|
||||
|
||||
// Time to return...
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsURLFetcher::Initialize(nsIFile *localFile,
|
||||
nsIOutputStream *outputStream,
|
||||
nsAttachSaveCompletionCallback cb,
|
||||
nsMsgAttachmentHandler *tagData)
|
||||
{
|
||||
if (!outputStream || !localFile)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
mOutStream = outputStream;
|
||||
mLocalFile = localFile;
|
||||
mCallback = cb; //JFD: Please, no more callback, use a listener...
|
||||
mTagData = tagData;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsURLFetcher::FireURLRequest(nsIURI *aURL, nsIFile *localFile, nsIOutputStream *outputStream,
|
||||
nsAttachSaveCompletionCallback cb, nsMsgAttachmentHandler *tagData)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = Initialize(localFile, outputStream, cb, tagData);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
//check to see if aURL is a local file or not
|
||||
aURL->SchemeIs("file", &mIsFile);
|
||||
|
||||
// we're about to fire a new url request so make sure the on stop request flag is cleared...
|
||||
mOnStopRequestProcessed = false;
|
||||
|
||||
// let's try uri dispatching...
|
||||
nsCOMPtr<nsIURILoader> pURILoader (do_GetService(NS_URI_LOADER_CONTRACTID));
|
||||
NS_ENSURE_TRUE(pURILoader, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> nullPrincipal =
|
||||
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
aURL,
|
||||
nullPrincipal,
|
||||
nsILoadInfo::SEC_NORMAL,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
nullptr, // aLoadGroup
|
||||
this); // aCallbacks
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return pURILoader->OpenURI(channel, false, this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsURLFetcher::InsertConverter(const char * aContentType)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIStreamConverterService> convServ(do_GetService("@mozilla.org/streamConverters;1", &rv));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsIStreamListener> toListener(mConverter);
|
||||
nsCOMPtr<nsIStreamListener> fromListener;
|
||||
|
||||
rv = convServ->AsyncConvertData(aContentType,
|
||||
"*/*",
|
||||
toListener,
|
||||
nullptr,
|
||||
getter_AddRefs(fromListener));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mConverter = fromListener;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// web progress listener implementation
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsURLFetcher::OnProgressChange(nsIWebProgress *aProgress, nsIRequest *aRequest,
|
||||
int32_t aCurSelfProgress, int32_t aMaxSelfProgress,
|
||||
int32_t aCurTotalProgress, int32_t aMaxTotalProgress)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsURLFetcher::OnStateChange(nsIWebProgress *aProgress, nsIRequest *aRequest,
|
||||
uint32_t aStateFlags, nsresult aStatus)
|
||||
{
|
||||
// all we care about is the case where an error occurred (as in we were unable to locate the
|
||||
// the url....
|
||||
|
||||
if (NS_FAILED(aStatus))
|
||||
OnStopRequest(aRequest, nullptr, aStatus);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsURLFetcher::OnLocationChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
nsIURI *aURI,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsURLFetcher::OnStatusChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
nsresult aStatus,
|
||||
const char16_t* aMessage)
|
||||
{
|
||||
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsURLFetcher::OnSecurityChange(nsIWebProgress *aWebProgress,
|
||||
nsIRequest *aRequest,
|
||||
uint32_t state)
|
||||
{
|
||||
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stream consumer used for handling special content type like multipart/x-mixed-replace
|
||||
*/
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsURLFetcherStreamConsumer, nsIStreamListener, nsIRequestObserver)
|
||||
|
||||
nsURLFetcherStreamConsumer::nsURLFetcherStreamConsumer(nsURLFetcher* urlFetcher) :
|
||||
mURLFetcher(urlFetcher)
|
||||
{
|
||||
}
|
||||
|
||||
nsURLFetcherStreamConsumer::~nsURLFetcherStreamConsumer()
|
||||
{
|
||||
}
|
||||
|
||||
/** nsIRequestObserver methods **/
|
||||
|
||||
/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */
|
||||
NS_IMETHODIMP nsURLFetcherStreamConsumer::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt)
|
||||
{
|
||||
if (!mURLFetcher || !mURLFetcher->mOutStream)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
/* In case of multipart/x-mixed-replace, we need to erase the output file content */
|
||||
if (MsgLowerCaseEqualsLiteral(mURLFetcher->mConverterContentType, MULTIPART_MIXED_REPLACE))
|
||||
{
|
||||
nsCOMPtr<nsISeekableStream> seekStream = do_QueryInterface(mURLFetcher->mOutStream);
|
||||
if (seekStream)
|
||||
seekStream->Seek(nsISeekableStream::NS_SEEK_SET, 0);
|
||||
mURLFetcher->mTotalWritten = 0;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status); */
|
||||
NS_IMETHODIMP nsURLFetcherStreamConsumer::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt, nsresult status)
|
||||
{
|
||||
if (!mURLFetcher)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Check the content type!
|
||||
nsAutoCString contentType;
|
||||
nsAutoCString charset;
|
||||
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
||||
if(!channel) return NS_ERROR_FAILURE;
|
||||
|
||||
if (NS_SUCCEEDED(channel->GetContentType(contentType)) &&
|
||||
!contentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE))
|
||||
{
|
||||
nsAutoCString uriSpec;
|
||||
nsCOMPtr <nsIURI> channelURI;
|
||||
channel->GetURI(getter_AddRefs(channelURI));
|
||||
nsresult rv = channelURI->GetSpec(uriSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (uriSpec.Find("&realtype=message/rfc822") >= 0)
|
||||
mURLFetcher->mContentType = MESSAGE_RFC822;
|
||||
else
|
||||
mURLFetcher->mContentType = contentType;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(channel->GetContentCharset(charset)) && !charset.IsEmpty())
|
||||
{
|
||||
mURLFetcher->mCharset = charset;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** nsIStreamListener methods **/
|
||||
|
||||
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long long sourceOffset, in unsigned long count); */
|
||||
NS_IMETHODIMP nsURLFetcherStreamConsumer::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt, nsIInputStream *inStr, uint64_t sourceOffset, uint32_t count)
|
||||
{
|
||||
uint32_t readLen = count;
|
||||
uint32_t wroteIt;
|
||||
|
||||
if (!mURLFetcher)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!mURLFetcher->mOutStream)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
if (mURLFetcher->mBufferSize < count)
|
||||
{
|
||||
PR_FREEIF(mURLFetcher->mBuffer);
|
||||
|
||||
if (count > 0x1000)
|
||||
mURLFetcher->mBufferSize = count;
|
||||
else
|
||||
mURLFetcher->mBufferSize = 0x1000;
|
||||
|
||||
mURLFetcher->mBuffer = (char *)PR_Malloc(mURLFetcher->mBufferSize);
|
||||
if (!mURLFetcher->mBuffer)
|
||||
return NS_ERROR_OUT_OF_MEMORY; /* we couldn't allocate the object */
|
||||
}
|
||||
|
||||
// read the data from the input stram...
|
||||
nsresult rv = inStr->Read(mURLFetcher->mBuffer, count, &readLen);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// write to the output file...
|
||||
mURLFetcher->mOutStream->Write(mURLFetcher->mBuffer, readLen, &wroteIt);
|
||||
|
||||
if (wroteIt != readLen)
|
||||
return NS_ERROR_FAILURE;
|
||||
else
|
||||
{
|
||||
mURLFetcher->mTotalWritten += wroteIt;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
101
mailnews/compose/src/nsURLFetcher.h
Normal file
101
mailnews/compose/src/nsURLFetcher.h
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/* -*- Mode: C++; tab-width: 4; 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 nsURLFetcher_h_
|
||||
#define nsURLFetcher_h_
|
||||
|
||||
#include "nsIURLFetcher.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIStreamListener.h"
|
||||
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsCURILoader.h"
|
||||
#include "nsIURIContentListener.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsMsgAttachmentHandler;
|
||||
|
||||
class nsURLFetcher : public nsIURLFetcher,
|
||||
public nsIStreamListener,
|
||||
public nsIURIContentListener,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIWebProgressListener,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
nsURLFetcher();
|
||||
|
||||
/* this macro defines QueryInterface, AddRef and Release for this class */
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// Methods for nsIURLFetcher
|
||||
NS_DECL_NSIURLFETCHER
|
||||
|
||||
// Methods for nsIStreamListener
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
||||
// Methods for nsIRequestObserver
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
|
||||
// Methods for nsIURICOntentListener
|
||||
NS_DECL_NSIURICONTENTLISTENER
|
||||
|
||||
// Methods for nsIInterfaceRequestor
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
|
||||
// Methods for nsIWebProgressListener
|
||||
NS_DECL_NSIWEBPROGRESSLISTENER
|
||||
|
||||
protected:
|
||||
nsresult InsertConverter(const char * aContentType);
|
||||
|
||||
private:
|
||||
virtual ~nsURLFetcher();
|
||||
nsCOMPtr<nsIOutputStream> mOutStream; // the output file stream
|
||||
nsCOMPtr<nsIFile> mLocalFile; // the output file itself
|
||||
nsCOMPtr<nsIStreamListener> mConverter; // the stream converter, if needed
|
||||
nsCString mConverterContentType; // The content type of the converter
|
||||
bool mStillRunning; // Are we still running?
|
||||
int32_t mTotalWritten; // Size counter variable
|
||||
char *mBuffer; // Buffer used for reading the data
|
||||
uint32_t mBufferSize; // Buffer size;
|
||||
nsCString mContentType; // The content type retrieved from the server
|
||||
nsCString mCharset; // The charset retrieved from the server
|
||||
RefPtr<nsMsgAttachmentHandler> mTagData; // Tag data for callback...
|
||||
nsAttachSaveCompletionCallback mCallback; // Callback to call once the file is saved...
|
||||
nsCOMPtr<nsISupports> mLoadCookie; // load cookie used by the uri loader when we fetch the url
|
||||
bool mOnStopRequestProcessed; // used to prevent calling OnStopRequest multiple times
|
||||
bool mIsFile; // This is used to check whether the URI is a local file.
|
||||
|
||||
friend class nsURLFetcherStreamConsumer;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Stream consumer used for handling special content type like multipart/x-mixed-replace
|
||||
*/
|
||||
|
||||
class nsURLFetcherStreamConsumer : public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
nsURLFetcherStreamConsumer(nsURLFetcher* urlFetcher);
|
||||
|
||||
/* additional members */
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
|
||||
private:
|
||||
virtual ~nsURLFetcherStreamConsumer();
|
||||
nsURLFetcher* mURLFetcher;
|
||||
};
|
||||
|
||||
|
||||
#endif /* nsURLFetcher_h_ */
|
||||
Loading…
Add table
Add a link
Reference in a new issue