Bug 390721 - When parsing headers to cancel an article, also use folded lines.

Tag #1273
This commit is contained in:
Matt A. Tobin 2019-11-10 23:01:33 -05:00 • committed by Roy Tam
commit 70d9e97b14
2 changed files with 53 additions and 79 deletions

View file

@ -274,11 +274,6 @@ nsNNTPProtocol::nsNNTPProtocol(nsINntpIncomingServer *aServer, nsIURI *aURL,
m_responseText = nullptr; m_responseText = nullptr;
m_dataBuf = nullptr; m_dataBuf = nullptr;
m_cancelFromHdr = nullptr;
m_cancelNewsgroups = nullptr;
m_cancelDistribution = nullptr;
m_cancelID = nullptr;
m_key = nsMsgKey_None; m_key = nsMsgKey_None;
mBytesReceived = 0; mBytesReceived = 0;
@ -315,10 +310,6 @@ void nsNNTPProtocol::Cleanup() //free char* member variables
{ {
PR_FREEIF(m_responseText); PR_FREEIF(m_responseText);
PR_FREEIF(m_dataBuf); PR_FREEIF(m_dataBuf);
PR_FREEIF(m_cancelFromHdr);
PR_FREEIF(m_cancelNewsgroups);
PR_FREEIF(m_cancelDistribution);
PR_FREEIF(m_cancelID);
} }
NS_IMETHODIMP nsNNTPProtocol::Initialize(nsIURI *aURL, nsIMsgWindow *aMsgWindow) NS_IMETHODIMP nsNNTPProtocol::Initialize(nsIURI *aURL, nsIMsgWindow *aMsgWindow)
@ -469,10 +460,10 @@ NS_IMETHODIMP nsNNTPProtocol::Initialize(nsIURI *aURL, nsIMsgWindow *aMsgWindow)
m_articleNumber = 0; m_articleNumber = 0;
m_originalContentLength = 0; m_originalContentLength = 0;
m_cancelID = nullptr; m_cancelID.Truncate();
m_cancelFromHdr = nullptr; m_cancelFromHdr.Truncate();
m_cancelNewsgroups = nullptr; m_cancelNewsgroups.Truncate();
m_cancelDistribution = nullptr; m_cancelDistribution.Truncate();
return NS_OK; return NS_OK;
} }
@ -2225,7 +2216,30 @@ nsresult nsNNTPProtocol::ReadArticle(nsIInputStream * inputStream, uint32_t leng
void nsNNTPProtocol::ParseHeaderForCancel(char *buf) void nsNNTPProtocol::ParseHeaderForCancel(char *buf)
{ {
static int lastHeader = 0;
nsAutoCString header(buf); nsAutoCString header(buf);
if (header.First() == ' ' || header.First() == '\t') {
header.StripWhitespace();
// Add folded line to header if needed.
switch (lastHeader) {
case 1:
m_cancelFromHdr += header;
break;
case 2:
m_cancelID += header;
break;
case 3:
m_cancelNewsgroups += header;
break;
case 4:
m_cancelDistribution += header;
break;
}
// Other folded lines are of no interest.
return;
}
lastHeader = 0;
int32_t colon = header.FindChar(':'); int32_t colon = header.FindChar(':');
if (!colon) if (!colon)
return; return;
@ -2236,26 +2250,26 @@ void nsNNTPProtocol::ParseHeaderForCancel(char *buf)
switch (header.First()) { switch (header.First()) {
case 'F': case 'f': case 'F': case 'f':
if (header.Find("From", CaseInsensitiveCompare) == 0) { if (header.Find("From", CaseInsensitiveCompare) == 0) {
PR_FREEIF(m_cancelFromHdr); m_cancelFromHdr = value;
m_cancelFromHdr = ToNewCString(value); lastHeader = 1;
} }
break; break;
case 'M': case 'm': case 'M': case 'm':
if (header.Find("Message-ID", CaseInsensitiveCompare) == 0) { if (header.Find("Message-ID", CaseInsensitiveCompare) == 0) {
PR_FREEIF(m_cancelID); m_cancelID = value;
m_cancelID = ToNewCString(value); lastHeader = 2;
} }
break; break;
case 'N': case 'n': case 'N': case 'n':
if (header.Find("Newsgroups", CaseInsensitiveCompare) == 0) { if (header.Find("Newsgroups", CaseInsensitiveCompare) == 0) {
PR_FREEIF(m_cancelNewsgroups); m_cancelNewsgroups = value;
m_cancelNewsgroups = ToNewCString(value); lastHeader = 3;
} }
break; break;
case 'D': case 'd': case 'D': case 'd':
if (header.Find("Distributions", CaseInsensitiveCompare) == 0) { if (header.Find("Distributions", CaseInsensitiveCompare) == 0) {
PR_FREEIF(m_cancelDistribution); m_cancelDistribution = value;
m_cancelDistribution = ToNewCString(value); lastHeader = 4;
} }
break; break;
} }
@ -3499,16 +3513,9 @@ nsresult nsNNTPProtocol::DoCancel()
int32_t status = 0; int32_t status = 0;
bool failure = false; bool failure = false;
nsresult rv = NS_OK; nsresult rv = NS_OK;
char *id = nullptr;
char *subject = nullptr;
char *newsgroups = nullptr;
char *distribution = nullptr;
char *body = nullptr;
bool requireConfirmationForCancel = true; bool requireConfirmationForCancel = true;
bool showAlertAfterCancel = true; bool showAlertAfterCancel = true;
int L;
/* #### Should we do a more real check than this? If the POST command /* #### Should we do a more real check than this? If the POST command
didn't respond with "MK_NNTP_RESPONSE_POST_SEND_NOW Ok", then it's not ready for us to throw a didn't respond with "MK_NNTP_RESPONSE_POST_SEND_NOW Ok", then it's not ready for us to throw a
message at it... But the normal posting code doesn't do this check. message at it... But the normal posting code doesn't do this check.
@ -3516,13 +3523,6 @@ nsresult nsNNTPProtocol::DoCancel()
*/ */
NS_ASSERTION (m_responseCode == MK_NNTP_RESPONSE_POST_SEND_NOW, "code != POST_SEND_NOW"); NS_ASSERTION (m_responseCode == MK_NNTP_RESPONSE_POST_SEND_NOW, "code != POST_SEND_NOW");
// These shouldn't be set yet, since the headers haven't been "flushed"
// "Distribution: " doesn't appear to be required, so
// don't assert on m_cancelDistribution
NS_ASSERTION (m_cancelID &&
m_cancelFromHdr &&
m_cancelNewsgroups, "null ptr");
nsCOMPtr<nsIStringBundleService> bundleService = nsCOMPtr<nsIStringBundleService> bundleService =
mozilla::services::GetStringBundleService(); mozilla::services::GetStringBundleService();
NS_ENSURE_TRUE(bundleService, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(bundleService, NS_ERROR_OUT_OF_MEMORY);
@ -3538,9 +3538,9 @@ nsresult nsNNTPProtocol::DoCancel()
NS_ENSURE_SUCCESS(rv,rv); NS_ENSURE_SUCCESS(rv,rv);
NS_ConvertUTF16toUTF8 appName(brandFullName); NS_ConvertUTF16toUTF8 appName(brandFullName);
newsgroups = m_cancelNewsgroups; nsCString newsgroups(m_cancelNewsgroups);
distribution = m_cancelDistribution; nsCString distribution (m_cancelDistribution);
id = m_cancelID; nsCString id (m_cancelID);
nsCString oldFrom(m_cancelFromHdr); nsCString oldFrom(m_cancelFromHdr);
nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv); nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
@ -3554,18 +3554,13 @@ nsresult nsNNTPProtocol::DoCancel()
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
NS_ASSERTION (id && newsgroups, "null ptr"); if (id.IsEmpty() || newsgroups.IsEmpty())
if (!id || !newsgroups) return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
m_cancelNewsgroups = nullptr; m_cancelNewsgroups.Truncate();
m_cancelDistribution = nullptr; m_cancelDistribution.Truncate();
m_cancelFromHdr = nullptr; m_cancelFromHdr.Truncate();
m_cancelID = nullptr; m_cancelID.Truncate();
L = PL_strlen (id);
subject = (char *) PR_Malloc (L + 20);
body = (char *) PR_Malloc (PL_strlen (appName.get()) + 100);
nsString alertText; nsString alertText;
nsString confirmText; nsString confirmText;
@ -3653,29 +3648,15 @@ nsresult nsNNTPProtocol::DoCancel()
goto FAIL; goto FAIL;
} }
if (!subject || !body)
{
status = MK_OUT_OF_MEMORY;
failure = true;
goto FAIL;
}
PL_strcpy (subject, "cancel ");
PL_strcat (subject, id);
otherHeaders.AppendLiteral("Control: cancel "); otherHeaders.AppendLiteral("Control: cancel ");
otherHeaders += id; otherHeaders += id;
otherHeaders.AppendLiteral(CRLF); otherHeaders.AppendLiteral(CRLF);
if (distribution) { if (!distribution.IsEmpty()) {
otherHeaders.AppendLiteral("Distribution: "); otherHeaders.AppendLiteral("Distribution: ");
otherHeaders += distribution; otherHeaders += distribution;
otherHeaders.AppendLiteral(CRLF); otherHeaders.AppendLiteral(CRLF);
} }
PL_strcpy (body, "This message was cancelled from within ");
PL_strcat (body, appName.get());
PL_strcat (body, "." CRLF);
m_cancelStatus = 0; m_cancelStatus = 0;
{ {
@ -3684,14 +3665,14 @@ nsresult nsNNTPProtocol::DoCancel()
char *data; char *data;
data = PR_smprintf("From: %s" CRLF data = PR_smprintf("From: %s" CRLF
"Newsgroups: %s" CRLF "Newsgroups: %s" CRLF
"Subject: %s" CRLF "Subject: cancel %s" CRLF
"References: %s" CRLF "References: %s" CRLF
"%s" /* otherHeaders, already with CRLF */ "%s" /* otherHeaders, already with CRLF */
CRLF /* body separator */ CRLF /* body separator */
"%s" /* body, already with CRLF */ "This message was cancelled from within %s." CRLF /* body */
"." CRLF, /* trailing message terminator "." */ "." CRLF, /* trailing message terminator "." */
from.get(), newsgroups, subject, id, from.get(), newsgroups.get(), id.get(), id.get(),
otherHeaders.get(), body); otherHeaders.get(), appName.get());
rv = SendData(data); rv = SendData(data);
PR_Free (data); PR_Free (data);
@ -3730,12 +3711,6 @@ FAIL:
rv = ( failure ) ? m_newsFolder->CancelFailed() rv = ( failure ) ? m_newsFolder->CancelFailed()
: m_newsFolder->CancelComplete(); : m_newsFolder->CancelComplete();
PR_Free (id);
PR_Free (subject);
PR_Free (newsgroups);
PR_Free (distribution);
PR_Free (body);
return rv; return rv;
} }

View file

@ -231,11 +231,10 @@ private:
// Cancelation specific state. In particular, the headers that should be // Cancelation specific state. In particular, the headers that should be
// used for the cancelation message. // used for the cancelation message.
// mscott: we can probably replace this stuff with nsString nsCString m_cancelFromHdr;
char *m_cancelFromHdr; nsCString m_cancelNewsgroups;
char *m_cancelNewsgroups; nsCString m_cancelDistribution;
char *m_cancelDistribution; nsCString m_cancelID;
char *m_cancelID;
int32_t m_cancelStatus; int32_t m_cancelStatus;
// variable for ReadNewsList // variable for ReadNewsList