mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 22:25:30 +00:00
1a97e11ffd
The mailto library is the mail compose code ripped out of the old Messenger libmsg library, then cleaned up somewhat (it could still use more cleaning). This library should only be built ifdef MOZ_MAIL_COMPOSE.
383 lines
8.6 KiB
C++
383 lines
8.6 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#include "rosetta.h"
|
|
#include "msg.h"
|
|
#include "errcode.h"
|
|
|
|
#include "msgcflds.h"
|
|
#include "prefapi.h"
|
|
#include "ptrarray.h"
|
|
|
|
extern "C" {
|
|
extern int MK_OUT_OF_MEMORY;
|
|
}
|
|
|
|
MSG_CompositionFields::MSG_CompositionFields()
|
|
{
|
|
XP_Bool bReturnReceiptOn = FALSE;
|
|
|
|
PREF_GetBoolPref("mail.request.return_receipt_on", &bReturnReceiptOn);
|
|
PREF_GetIntPref("mail.request.return_receipt", &m_receiptType);
|
|
SetReturnReceipt (bReturnReceiptOn);
|
|
}
|
|
|
|
|
|
MSG_CompositionFields::MSG_CompositionFields(MSG_CompositionFields* c)
|
|
{
|
|
int i;
|
|
for (i=0 ; i<sizeof(m_headers) / sizeof(char*) ; i++) {
|
|
if (c->m_headers[i]) {
|
|
m_headers[i] = XP_STRDUP(c->m_headers[i]);
|
|
}
|
|
}
|
|
if (c->m_body) {
|
|
m_body = XP_STRDUP(c->m_body);
|
|
}
|
|
for (i=0 ; i<c->m_numforward ; i++) {
|
|
AddForwardURL(c->m_forwardurl[i]);
|
|
}
|
|
for (i=0; i<sizeof(m_boolHeaders)/sizeof(XP_Bool) ; i++) {
|
|
m_boolHeaders[i] = c->m_boolHeaders[i];
|
|
}
|
|
m_receiptType = c->m_receiptType;
|
|
}
|
|
|
|
|
|
|
|
MSG_CompositionFields::~MSG_CompositionFields()
|
|
{
|
|
int i;
|
|
for (i=0 ; i<sizeof(m_headers) / sizeof(char*) ; i++) {
|
|
FREEIF(m_headers[i]);
|
|
}
|
|
FREEIF(m_body);
|
|
for (i=0 ; i<m_numforward ; i++) {
|
|
delete [] m_forwardurl[i];
|
|
}
|
|
delete [] m_forwardurl;
|
|
}
|
|
|
|
|
|
int MSG_CompositionFields::SetNewsUrlHeader (const char *hostPort, XP_Bool xxx, const char *group)
|
|
{
|
|
// Here's where we allow URLs in the newsgroups: header
|
|
|
|
int status = -1;
|
|
if (hostPort && group) // must have a group
|
|
{
|
|
char *newsPostUrl = PR_smprintf ("%s://%s/", HG71654 "news", hostPort);
|
|
if (newsPostUrl)
|
|
{
|
|
SetHeader (MSG_NEWSPOSTURL_HEADER_MASK, newsPostUrl);
|
|
XP_FREE(newsPostUrl);
|
|
status = 0; // we succeeded, no need to keep looking at this header
|
|
}
|
|
else
|
|
status = MK_OUT_OF_MEMORY;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
int MSG_CompositionFields::ParseNewsgroupsForUrls (const char *value)
|
|
{
|
|
int status = 0;
|
|
|
|
#ifdef MOZ_MAIL_NEWS
|
|
// Here we pull apart the comma-separated header value and look for news
|
|
// URLs. We'll use the URL to set the newspost URL to determine the host
|
|
msg_StringArray values (TRUE /*owns memory for strings*/);
|
|
values.ImportTokenList (value);
|
|
for (int i = 0; i < values.GetSize(); i++)
|
|
{
|
|
const char *singleValue = values.GetAt(i);
|
|
if (NEWS_TYPE_URL == NET_URL_Type (singleValue))
|
|
{
|
|
char *hostPort, *group, *id, *data;
|
|
XP_Bool xxx;
|
|
if (0 == NET_parse_news_url (value, &hostPort, &xxx, &group, &id, &data))
|
|
{
|
|
status = SetNewsUrlHeader (hostPort, xxx, group);
|
|
if (status == 0)
|
|
{
|
|
values.RemoveAt(i); // Remove the URL spec for this group
|
|
values.Add (group); // Add in the plain old group name
|
|
}
|
|
FREEIF (hostPort);
|
|
FREEIF (group);
|
|
FREEIF (id);
|
|
FREEIF (data);
|
|
}
|
|
}
|
|
}
|
|
char *newValue = values.ExportTokenList ();
|
|
if (newValue)
|
|
{
|
|
status = SetHeader (MSG_NEWSGROUPS_HEADER_MASK, newValue);
|
|
XP_FREE(newValue);
|
|
}
|
|
#endif /* MOZ_MAIL_NEWS */
|
|
return status;
|
|
}
|
|
|
|
|
|
int
|
|
MSG_CompositionFields::SetHeader(MSG_HEADER_SET header, const char* value)
|
|
{
|
|
int status = 0;
|
|
|
|
// Since colon is not a legal character in a newsgroup name under son-of-1036
|
|
// we're assuming that such a header contains a URL, and we should parse it out
|
|
// to infer the news server.
|
|
if (value && MSG_NEWSGROUPS_HEADER_MASK == header && XP_STRCHR(value, ':'))
|
|
return ParseNewsgroupsForUrls (value);
|
|
|
|
int i = DecodeHeader(header);
|
|
if (i >= 0)
|
|
{
|
|
char* old = m_headers[i]; // Done with careful paranoia, in case the
|
|
// value given is the old value (or worse,
|
|
// a substring of the old value, as does
|
|
// happen here and there.)
|
|
if (value != old)
|
|
{
|
|
if (value)
|
|
{
|
|
m_headers[i] = XP_STRDUP(value);
|
|
if (!m_headers[i])
|
|
status = MK_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
m_headers[i] = NULL;
|
|
FREEIF(old);
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
extern "C"const char* MSG_GetCompFieldsHeader(MSG_CompositionFields *fields,
|
|
MSG_HEADER_SET header)
|
|
{
|
|
return fields->GetHeader(header);
|
|
}
|
|
|
|
const char*
|
|
MSG_CompositionFields::GetHeader(MSG_HEADER_SET header)
|
|
{
|
|
int i = DecodeHeader(header);
|
|
if (i >= 0) {
|
|
return m_headers[i] ? m_headers[i] : "";
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
int
|
|
MSG_CompositionFields::SetBoolHeader(MSG_BOOL_HEADER_SET header, XP_Bool bValue)
|
|
{
|
|
int status = 0;
|
|
XP_ASSERT ((int) header >= (int) MSG_RETURN_RECEIPT_BOOL_HEADER_MASK &&
|
|
(int) header < (int) MSG_LAST_BOOL_HEADER_MASK);
|
|
|
|
if ( (int) header < (int) MSG_RETURN_RECEIPT_BOOL_HEADER_MASK ||
|
|
(int) header >= (int) MSG_LAST_BOOL_HEADER_MASK )
|
|
return -1;
|
|
|
|
m_boolHeaders[header] = bValue;
|
|
return status;
|
|
}
|
|
|
|
|
|
XP_Bool
|
|
MSG_CompositionFields::GetBoolHeader(MSG_BOOL_HEADER_SET header)
|
|
{
|
|
XP_ASSERT ((int) header >= (int) MSG_RETURN_RECEIPT_BOOL_HEADER_MASK &&
|
|
(int) header < (int) MSG_LAST_BOOL_HEADER_MASK);
|
|
|
|
if ( (int) header < (int) MSG_RETURN_RECEIPT_BOOL_HEADER_MASK ||
|
|
(int) header >= (int) MSG_LAST_BOOL_HEADER_MASK )
|
|
return FALSE;
|
|
|
|
return m_boolHeaders[header];
|
|
}
|
|
|
|
|
|
int
|
|
MSG_CompositionFields::SetBody(const char* value)
|
|
{
|
|
FREEIF(m_body);
|
|
if (value) {
|
|
m_body = XP_STRDUP(value);
|
|
if (!m_body) return MK_OUT_OF_MEMORY;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
const char*
|
|
MSG_CompositionFields::GetBody()
|
|
{
|
|
return m_body ? m_body : "";
|
|
}
|
|
|
|
|
|
int
|
|
MSG_CompositionFields::AppendBody(const char* value)
|
|
{
|
|
if (!value || !*value) return 0;
|
|
if (!m_body) {
|
|
return SetBody(value);
|
|
} else {
|
|
char* tmp = (char*) XP_ALLOC(XP_STRLEN(m_body) + XP_STRLEN(value) + 1);
|
|
if (tmp) {
|
|
XP_STRCPY(tmp, m_body);
|
|
XP_STRCAT(tmp, value);
|
|
XP_FREE(m_body);
|
|
m_body = tmp;
|
|
} else {
|
|
return MK_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
MSG_CompositionFields::DecodeHeader(MSG_HEADER_SET header)
|
|
{
|
|
int result;
|
|
switch(header) {
|
|
case MSG_FROM_HEADER_MASK:
|
|
result = 0;
|
|
break;
|
|
case MSG_REPLY_TO_HEADER_MASK:
|
|
result = 1;
|
|
break;
|
|
case MSG_TO_HEADER_MASK:
|
|
result = 2;
|
|
break;
|
|
case MSG_CC_HEADER_MASK:
|
|
result = 3;
|
|
break;
|
|
case MSG_BCC_HEADER_MASK:
|
|
result = 4;
|
|
break;
|
|
case MSG_FCC_HEADER_MASK:
|
|
result = 5;
|
|
break;
|
|
case MSG_NEWSGROUPS_HEADER_MASK:
|
|
result = 6;
|
|
break;
|
|
case MSG_FOLLOWUP_TO_HEADER_MASK:
|
|
result = 7;
|
|
break;
|
|
case MSG_SUBJECT_HEADER_MASK:
|
|
result = 8;
|
|
break;
|
|
case MSG_ATTACHMENTS_HEADER_MASK:
|
|
result = 9;
|
|
break;
|
|
case MSG_ORGANIZATION_HEADER_MASK:
|
|
result = 10;
|
|
break;
|
|
case MSG_REFERENCES_HEADER_MASK:
|
|
result = 11;
|
|
break;
|
|
case MSG_OTHERRANDOMHEADERS_HEADER_MASK:
|
|
result = 12;
|
|
break;
|
|
case MSG_NEWSPOSTURL_HEADER_MASK:
|
|
result = 13;
|
|
break;
|
|
case MSG_PRIORITY_HEADER_MASK:
|
|
result = 14;
|
|
break;
|
|
case MSG_NEWS_FCC_HEADER_MASK:
|
|
result = 15;
|
|
break;
|
|
case MSG_MESSAGE_ENCODING_HEADER_MASK:
|
|
result = 16;
|
|
break;
|
|
case MSG_CHARACTER_SET_HEADER_MASK:
|
|
result = 17;
|
|
break;
|
|
case MSG_MESSAGE_ID_HEADER_MASK:
|
|
result = 18;
|
|
break;
|
|
case MSG_NEWS_BCC_HEADER_MASK:
|
|
result = 19;
|
|
break;
|
|
case MSG_HTML_PART_HEADER_MASK:
|
|
result = 20;
|
|
break;
|
|
case MSG_DEFAULTBODY_HEADER_MASK:
|
|
result = 21;
|
|
break;
|
|
case MSG_X_TEMPLATE_HEADER_MASK:
|
|
result = 22;
|
|
break;
|
|
default:
|
|
XP_ASSERT(0);
|
|
result = -1;
|
|
break;
|
|
}
|
|
XP_ASSERT(result < sizeof(m_headers) / sizeof(char*));
|
|
return result;
|
|
}
|
|
|
|
int
|
|
MSG_CompositionFields::AddForwardURL(const char* url)
|
|
{
|
|
XP_ASSERT(url && *url);
|
|
if (!url || !*url) return -1;
|
|
if (m_numforward >= m_maxforward) {
|
|
m_maxforward += 10;
|
|
char** tmp = new char* [m_maxforward];
|
|
if (!tmp) return MK_OUT_OF_MEMORY;
|
|
for (int32 i=0 ; i<m_numforward ; i++) {
|
|
tmp[i] = m_forwardurl[i];
|
|
}
|
|
delete [] m_forwardurl;
|
|
m_forwardurl = tmp;
|
|
}
|
|
m_forwardurl[m_numforward] = new char[XP_STRLEN(url) + 1];
|
|
if (!m_forwardurl[m_numforward]) return MK_OUT_OF_MEMORY;
|
|
XP_STRCPY(m_forwardurl[m_numforward], url);
|
|
m_numforward++;
|
|
return 0;
|
|
}
|
|
|
|
int32
|
|
MSG_CompositionFields::GetNumForwardURL()
|
|
{
|
|
return m_numforward;
|
|
}
|
|
|
|
const char*
|
|
MSG_CompositionFields::GetForwardURL(int32 which)
|
|
{
|
|
XP_ASSERT(which >= 0 && which < m_numforward);
|
|
if (which >= 0 && which < m_numforward) {
|
|
return m_forwardurl[which];
|
|
}
|
|
return NULL;
|
|
}
|