Backout out patch for bug 16913 due to regressions (see bug 424607 for details); a=blocking-3.0a1+

git-svn-id: svn://10.0.0.236/trunk@250968 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
dmose%mozilla.org
2008-04-30 01:35:22 +00:00
parent b7c0eaff3d
commit 8cf21c503c
9 changed files with 214 additions and 653 deletions

View File

@@ -52,9 +52,7 @@ enterPasswordTitle=News Server Password Required
okButtonText=Download
noNewMessages=There are no new messages on the server.
# The difference between these two is that the second one is shown when processing XHDR commands
downloadingHeaders=Downloading %S of %S headers
downloadingFilterHeaders=Getting filter headers: %S (%S/%S)
downloadingArticles=Downloading articles %S-%S
bytesReceived=Downloading newsgroups: %S received (%SKB read at %SKB/sec)
checkingForNewNews=Checking newsgroup %S of %S on %S for new messages

View File

@@ -1015,15 +1015,11 @@ NS_IMETHODIMP nsMsgSearchValidityManager::GetTable (int whichTable, nsIMsgSearch
case nsMsgSearchScope::news:
if (!m_newsTable)
rv = InitNewsTable();
if (m_newsTable)
rv = SetOtherHeadersInTable(m_newsTable, customHeaders.get());
*ppOutTable = m_newsTable;
break;
case nsMsgSearchScope::newsFilter:
if (!m_newsFilterTable)
rv = InitNewsFilterTable();
if (m_newsFilterTable)
rv = SetOtherHeadersInTable(m_newsFilterTable, customHeaders.get());
*ppOutTable = m_newsFilterTable;
break;
case nsMsgSearchScope::localNews:

View File

@@ -144,14 +144,8 @@ char *nsMsgSearchNews::EncodeTerm (nsIMsgSearchTerm *term)
attribEncoding = m_kNntpSubject;
break;
default:
nsCString header;
term->GetArbitraryHeader(header);
if (header.IsEmpty())
{
NS_ASSERTION(PR_FALSE,"malformed search"); // malformed search term?
return nsnull;
}
attribEncoding = header.get();
NS_ASSERTION(PR_FALSE,"malformed search"); // malformed search term?
return nsnull;
}
// Build a string to represent the string pattern
@@ -466,23 +460,6 @@ nsresult nsMsgSearchValidityManager::InitNewsTable()
m_newsTable->SetEnabled (nsMsgSearchAttrib::Subject, nsMsgSearchOp::BeginsWith, 1);
m_newsTable->SetAvailable (nsMsgSearchAttrib::Subject, nsMsgSearchOp::EndsWith, 1);
m_newsTable->SetEnabled (nsMsgSearchAttrib::Subject, nsMsgSearchOp::EndsWith, 1);
#if 0
// Size should be handled after the fact...
m_newsTable->SetAvailable (nsMsgSearchAttrib::Size, nsMsgSearchOp::IsGreaterThan, 1);
m_newsTable->SetEnabled (nsMsgSearchAttrib::Size, nsMsgSearchOp::IsGreaterThan, 1);
m_newsTable->SetAvailable (nsMsgSearchAttrib::Size, nsMsgSearchOp::IsLessThan, 1);
m_newsTable->SetEnabled (nsMsgSearchAttrib::Size, nsMsgSearchOp::IsLessThan, 1);
#endif
m_newsTable->SetAvailable (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::Contains, 1);
m_newsTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::Contains, 1);
m_newsTable->SetAvailable (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::Is, 1);
m_newsTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::Is, 1);
m_newsTable->SetAvailable (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::BeginsWith, 1);
m_newsTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::BeginsWith, 1);
m_newsTable->SetAvailable (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::EndsWith, 1);
m_newsTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::EndsWith, 1);
}
return rv;
@@ -534,20 +511,6 @@ nsresult nsMsgSearchValidityManager::InitNewsFilterTable()
m_newsFilterTable->SetEnabled (nsMsgSearchAttrib::Date, nsMsgSearchOp::Is, 1);
m_newsFilterTable->SetAvailable (nsMsgSearchAttrib::Date, nsMsgSearchOp::Isnt, 1);
m_newsFilterTable->SetEnabled (nsMsgSearchAttrib::Date, nsMsgSearchOp::Isnt, 1);
m_newsFilterTable->SetAvailable (nsMsgSearchAttrib::Size, nsMsgSearchOp::IsGreaterThan, 1);
m_newsFilterTable->SetEnabled (nsMsgSearchAttrib::Size, nsMsgSearchOp::IsGreaterThan, 1);
m_newsFilterTable->SetAvailable (nsMsgSearchAttrib::Size, nsMsgSearchOp::IsLessThan, 1);
m_newsFilterTable->SetEnabled (nsMsgSearchAttrib::Size, nsMsgSearchOp::IsLessThan, 1);
m_newsFilterTable->SetAvailable (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::Contains, 1);
m_newsFilterTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::Contains, 1);
m_newsFilterTable->SetAvailable (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::Is, 1);
m_newsFilterTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::Is, 1);
m_newsFilterTable->SetAvailable (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::BeginsWith, 1);
m_newsFilterTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::BeginsWith, 1);
m_newsFilterTable->SetAvailable (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::EndsWith, 1);
m_newsFilterTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::EndsWith, 1);
}
return rv;

View File

@@ -73,19 +73,11 @@ interface nsINNTPNewsgroupList : nsISupports {
/* the XOVER Sink should maintain the ListNewsGroupState */
void initXOVER(in long first_message, in long last_message);
void processXOVERLINE(in string line, out unsigned long status);
void processNonXOVER(in string line);
void resetXOVER();
void finishXOVERLINE(in long status, out long newstatus);
void clearXOVERState();
ACString initXHDR();
void processXHDRLine(in ACString line);
void initHEAD(in long message);
void processHEADLine(in ACString line);
// Calls the entire header process
void callFilters();
attribute boolean getOldMessages;
};

View File

@@ -127,35 +127,6 @@ nsNNTPNewsgroupList::Initialize(nsINntpUrl *runningURL, nsIMsgNewsFolder *newsFo
m_runningURL = runningURL;
m_knownArts.set = nsMsgKeySet::Create();
nsresult rv;
nsCOMPtr <nsIMsgFolder> folder = do_QueryInterface(m_newsFolder, &rv);
NS_ENSURE_SUCCESS(rv,rv);
rv = folder->GetFilterList(m_msgWindow, getter_AddRefs(m_filterList));
NS_ENSURE_SUCCESS(rv,rv);
nsCString ngHeaders;
m_filterList->GetArbitraryHeaders(ngHeaders);
m_filterHeaders.ParseString(ngHeaders.get(), " ");
nsCOMPtr<nsIMsgIncomingServer> server;
rv = folder->GetServer(getter_AddRefs(server));
NS_ENSURE_SUCCESS(rv,rv);
rv = server->GetFilterList(m_msgWindow, getter_AddRefs(m_serverFilterList));
NS_ENSURE_SUCCESS(rv,rv);
nsCAutoString servHeaders;
m_serverFilterList->GetArbitraryHeaders(servHeaders);
nsCStringArray servArray;
servArray.ParseString(servHeaders.get(), " ");
// servArray may have duplicates already in m_filterHeaders.
for (PRInt32 i = 0; i < servArray.Count(); i++)
{
if (m_filterHeaders.IndexOf(*(servArray[i])) == -1)
m_filterHeaders.AppendCString(*(servArray[i]));
}
return NS_OK;
}
@@ -180,8 +151,9 @@ nsNNTPNewsgroupList::CleanUp()
if (lastMissingCheck)
firstKnown = lastMissingCheck + 1;
}
PRBool done = firstKnown > lastKnown; // just in case...
PRBool foundMissingArticle = PR_FALSE;
while (firstKnown <= lastKnown)
while (!done)
{
PRInt32 firstUnreadStart, firstUnreadEnd;
m_set->FirstMissingRange(firstKnown, lastKnown, &firstUnreadStart, &firstUnreadEnd);
@@ -520,13 +492,12 @@ nsNNTPNewsgroupList::InitXOVER(PRInt32 first_msg, PRInt32 last_msg)
m_firstMsgNumber = first_msg;
m_lastMsgNumber = last_msg;
m_lastProcessedNumber = first_msg > 1 ? first_msg - 1 : 1;
m_currentXHDRIndex = -1;
return status;
}
// from RFC 822, don't translate
#define FROM_HEADER "From: "
#define SUBJECT_HEADER "Subject: "
#define SUBECT_HEADER "Subject: "
#define DATE_HEADER "Date: "
nsresult
@@ -641,7 +612,136 @@ nsNNTPNewsgroupList::ParseLine(char *line, PRUint32 * message_number)
GET_TOKEN (); /* xref */
return m_newsDB->AddNewHdrToDB(newMsgHdr, PR_TRUE);
// apply filters
// XXX TODO
// do spam classification for news
nsCOMPtr <nsIMsgFolder> folder = do_QueryInterface(m_newsFolder, &rv);
NS_ENSURE_SUCCESS(rv,rv);
if (!m_filterList)
{
rv = folder->GetFilterList(m_msgWindow, getter_AddRefs(m_filterList));
NS_ENSURE_SUCCESS(rv,rv);
}
if (!m_serverFilterList)
{
nsCOMPtr<nsIMsgIncomingServer> server;
rv = folder->GetServer(getter_AddRefs(server));
NS_ENSURE_SUCCESS(rv,rv);
rv = server->GetFilterList(m_msgWindow, getter_AddRefs(m_serverFilterList));
NS_ENSURE_SUCCESS(rv,rv);
}
// flag for kill
// if the action is Delete, and we get a hit (see ApplyFilterHit())
// we set this to PR_FALSE. if false, we won't add it to the db.
m_addHdrToDB = PR_TRUE;
PRUint32 filterCount = 0;
if (m_filterList) {
rv = m_filterList->GetFilterCount(&filterCount);
NS_ENSURE_SUCCESS(rv,rv);
}
PRUint32 serverFilterCount = 0;
if (m_serverFilterList) {
rv = m_serverFilterList->GetFilterCount(&serverFilterCount);
NS_ENSURE_SUCCESS(rv,rv);
}
// only do this if we have filters
if (filterCount || serverFilterCount)
{
// build up a "headers" for filter code
nsCString subject;
rv = newMsgHdr->GetSubject(getter_Copies(subject));
NS_ENSURE_SUCCESS(rv,rv);
PRUint32 headersSize = 0;
// +1 to separate headers with a null byte
if (authorStr)
headersSize += strlen(FROM_HEADER) + strlen(authorStr) + 1;
if (!(subject.IsEmpty()))
headersSize += strlen(SUBECT_HEADER) + subject.Length() + 1;
if (dateStr)
headersSize += strlen(DATE_HEADER) + strlen(dateStr) + 1;
if (headersSize) {
char *headers = (char *)PR_Malloc(headersSize);
char *headerPos = headers;
if (!headers)
return NS_ERROR_OUT_OF_MEMORY;
if (authorStr) {
PL_strcpy(headerPos, FROM_HEADER);
headerPos += strlen(FROM_HEADER);
PL_strcpy(headerPos, authorStr);
headerPos += strlen(authorStr);
*headerPos = '\0';
headerPos++;
}
if (!(subject.IsEmpty())) {
PL_strcpy(headerPos, SUBECT_HEADER);
headerPos += strlen(SUBECT_HEADER);
PL_strcpy(headerPos, subject.get());
headerPos += subject.Length();
*headerPos = '\0';
headerPos++;
}
if (dateStr) {
PL_strcpy(headerPos, DATE_HEADER);
headerPos += strlen(DATE_HEADER);
PL_strcpy(headerPos, dateStr);
headerPos += strlen(dateStr);
*headerPos = '\0';
headerPos++;
}
// on a filter hit (see ApplyFilterHit()), we'll be modifying the header
// so keep track of the header
m_newMsgHdr = newMsgHdr;
// the per-newsgroup filters should probably go first. It doesn't matter
// right now since nothing stops filter execution for newsgroups, but if something
// does, like adding a "stop execution" action, then users should be able to
// override the global filters in the per-newsgroup filters.
if (filterCount)
{
rv = m_filterList->ApplyFiltersToHdr(nsMsgFilterType::NewsRule, newMsgHdr, folder, m_newsDB,
headers, headersSize, this, m_msgWindow, nsnull);
}
if (serverFilterCount)
{
rv = m_serverFilterList->ApplyFiltersToHdr(nsMsgFilterType::NewsRule, newMsgHdr, folder, m_newsDB,
headers, headersSize, this, m_msgWindow, nsnull);
}
PR_Free ((void*) headers);
NS_ENSURE_SUCCESS(rv,rv);
}
}
// if we deleted it, don't add it
if (m_addHdrToDB) {
rv = m_newsDB->AddNewHdrToDB(newMsgHdr, PR_TRUE);
NS_ENSURE_SUCCESS(rv,rv);
}
return NS_OK;
}
NS_IMETHODIMP nsNNTPNewsgroupList::ApplyFilterHit(nsIMsgFilter *aFilter, nsIMsgWindow *aMsgWindow, PRBool *aApplyMore)
@@ -829,13 +929,48 @@ nsNNTPNewsgroupList::ProcessXOVERLINE(const char *line, PRUint32 *status)
PRInt32 numDownloaded = lastIndex;
PRInt32 totIndex = m_lastMsgNumber - m_firstMsgNumber + 1;
PRInt32 percent = (totIndex) ? (PRInt32)(100.0 * (double)numDownloaded / (double)totalToDownload) : 0;
PRTime elapsedTime;
LL_SUB(elapsedTime, PR_Now(), m_lastStatusUpdate);
if (LL_CMP(elapsedTime, >, MIN_STATUS_UPDATE_INTERVAL) ||
lastIndex == totIndex)
UpdateStatus(PR_FALSE, numDownloaded, totalToDownload);
{
nsAutoString numDownloadedStr;
numDownloadedStr.AppendInt(numDownloaded);
nsAutoString totalToDownloadStr;
totalToDownloadStr.AppendInt(totalToDownload);
nsString statusString;
nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIStringBundle> bundle;
rv = bundleService->CreateBundle(NEWS_MSGS_URL, getter_AddRefs(bundle));
NS_ENSURE_SUCCESS(rv, rv);
const PRUnichar *formatStrings[2] = { numDownloadedStr.get(), totalToDownloadStr.get() };
rv = bundle->FormatStringFromName(NS_LITERAL_STRING("downloadingHeaders").get(), formatStrings, 2, getter_Copies(statusString));
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG_NEWS
PRInt32 elapsed;
LL_L2I(elapsed, elapsedTime);
printf("usecs elapsed since last update: %d\n", elapsed);
#endif
SetProgressStatus(statusString.get());
m_lastStatusUpdate = PR_Now();
// only update the progress meter if it has changed
if (percent != m_lastPercent) {
SetProgressBarPercent(percent);
m_lastPercent = percent;
}
}
}
return NS_OK;
}
@@ -848,6 +983,22 @@ nsNNTPNewsgroupList::ResetXOVER()
return 0;
}
/* When we don't have XOVER, but use HEAD, this is called instead.
It reads lines until it has a whole header block, then parses the
headers; then takes selected headers and creates an XOVER line
from them. This is more for simplicity and code sharing than
anything else; it means we end up parsing some things twice.
But if we don't have XOVER, things are going to be so horribly
slow anyway that this just doesn't matter.
*/
nsresult
nsNNTPNewsgroupList::ProcessNonXOVER (const char * /*line*/)
{
// ### dmb write me
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
nsNNTPNewsgroupList::FinishXOVERLINE(int status, int *newstatus)
{
@@ -923,282 +1074,6 @@ nsNNTPNewsgroupList::ClearXOVERState()
return NS_OK;
}
NS_IMETHODIMP
nsNNTPNewsgroupList::InitXHDR(nsACString &header)
{
++m_currentXHDRIndex;
if (m_currentXHDRIndex >= m_filterHeaders.Count())
header.Truncate();
else
header.Assign(*m_filterHeaders[m_currentXHDRIndex]);
return NS_OK;
}
NS_IMETHODIMP
nsNNTPNewsgroupList::ProcessXHDRLine(const nsACString &line)
{
PRInt32 middle = line.FindChar(' ');
nsCString value, key = PromiseFlatCString(line);
if (middle == kNotFound)
return NS_OK;
value = Substring(line, middle+1);
key.Truncate((PRUint32)middle);
// According to RFC 2980, some will send (none) instead.
// So we don't treat this is an error.
if (key.CharAt(0) < '0' || key.CharAt(0) > '9')
return NS_OK;
PRInt32 code;
PRInt32 number = key.ToInteger(&code);
if (code != NS_OK)
return NS_ERROR_FAILURE;
// RFC 2980 specifies one or more spaces.
value.Trim(" ");
nsCOMPtr <nsIMsgDBHdr> header;
nsresult rv = m_newsDB->GetMsgHdrForKey(number, getter_AddRefs(header));
NS_ENSURE_SUCCESS(rv, rv);
rv = header->SetStringProperty(m_filterHeaders[m_currentXHDRIndex]->get(), value.get());
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 totalToDownload = m_lastMsgToDownload - m_firstMsgToDownload + 1;
PRInt32 numDownloaded = number - m_firstMsgNumber + 1;
PRTime elapsedTime;
LL_SUB(elapsedTime, PR_Now(), m_lastStatusUpdate);
if (elapsedTime > MIN_STATUS_UPDATE_INTERVAL)
UpdateStatus(PR_TRUE, numDownloaded, totalToDownload);
return rv;
}
NS_IMETHODIMP
nsNNTPNewsgroupList::InitHEAD(PRInt32 number)
{
nsresult rv;
if (m_newMsgHdr)
{
// Finish processing for this header
// If HEAD didn't properly return, then the header won't be set
if (m_addHdrToDB)
{
rv = m_newsDB->AddNewHdrToDB(m_newMsgHdr, PR_TRUE);
NS_ENSURE_SUCCESS(rv,rv);
}
PRInt32 totalToDownload = m_lastMsgToDownload - m_firstMsgToDownload + 1;
PRInt32 lastIndex = m_lastProcessedNumber - m_firstMsgNumber + 1;
PRInt32 numDownloaded = lastIndex;
PRInt32 totIndex = m_lastMsgNumber - m_firstMsgNumber + 1;
PRTime elapsedTime;
LL_SUB(elapsedTime, PR_Now(), m_lastStatusUpdate);
if (LL_CMP(elapsedTime, >, MIN_STATUS_UPDATE_INTERVAL) ||
lastIndex == totIndex)
UpdateStatus(PR_FALSE, numDownloaded, totalToDownload);
}
if (number >= 0)
{
rv = m_newsDB->CreateNewHdr(number, getter_AddRefs(m_newMsgHdr));
m_addHdrToDB = PR_FALSE;
m_lastProcessedNumber = number;
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
NS_IMETHODIMP
nsNNTPNewsgroupList::ProcessHEADLine(const nsACString &line)
{
PRInt32 colon = line.FindChar(':');
nsCString header = PromiseFlatCString(line), value;
if (colon != kNotFound)
{
value = Substring(line, colon+1);
header.Truncate((PRUint32)colon);
}
else if (line.CharAt(0) == ' ' || line.CharAt(0) == '\t') // We are continuing the header
{
m_thisLine += header; // Preserve whitespace (should we?)
return NS_OK;
}
else
return NS_OK; // We are malformed. Just ignore and hope for the best...
nsresult rv;
if (!m_lastHeader.IsEmpty())
{
rv = AddHeader(m_lastHeader.get(), m_thisLine.get());
NS_ENSURE_SUCCESS(rv,rv);
}
value.Trim(" ");
ToLowerCase(header, m_lastHeader);
m_thisLine.Assign(value);
return NS_OK;
}
nsresult
nsNNTPNewsgroupList::AddHeader(const char *header, const char *value)
{
nsresult rv = NS_OK;
// The From, Date, and Subject headers have special requirements.
if (PL_strcmp(header, "from") == 0)
rv = m_newMsgHdr->SetAuthor(value);
else if (PL_strcmp(header, "date") == 0)
{
PRTime date;
PRStatus status = PR_ParseTimeString (value, PR_FALSE, &date);
if (PR_SUCCESS == status)
rv = m_newMsgHdr->SetDate(date);
}
else if (PL_strcmp(header, "subject") == 0)
{
const char *subject = value;
PRUint32 subjectLen = strlen(value);
PRUint32 flags = 0;
// ### should call IsHeaderRead here...
/* strip "Re: " */
nsCString modifiedSubject;
if (NS_MsgStripRE(&subject, &subjectLen, getter_Copies(modifiedSubject)))
// this will make sure read flags agree with newsrc
(void) m_newMsgHdr->OrFlags(MSG_FLAG_HAS_RE, &flags);
if (! (flags & MSG_FLAG_READ))
rv = m_newMsgHdr->OrFlags(MSG_FLAG_NEW, &flags);
rv = m_newMsgHdr->SetSubject(modifiedSubject.IsEmpty() ? subject :
modifiedSubject.get());
}
else if (PL_strcmp(header, "message-id") == 0)
{
char * strippedId = PL_strdup(value);
char * freeable = strippedId;
if (strippedId[0] == '<')
strippedId++;
char * lastChar = strippedId + PL_strlen(strippedId) - 1;
if (*lastChar == '>')
*lastChar = '\0';
rv = m_newMsgHdr->SetMessageId(strippedId);
PL_strfree(freeable);
}
else if (PL_strcmp(header, "references") == 0)
rv = m_newMsgHdr->SetReferences(value);
else if (PL_strcmp(header, "bytes") == 0)
rv = m_newMsgHdr->SetMessageSize(atol(value));
else if (PL_strcmp(header, "lines") == 0)
rv = m_newMsgHdr->SetLineCount(atol(value));
else if (m_filterHeaders.IndexOf(nsDependentCString(header)) != -1)
rv = m_newMsgHdr->SetStringProperty(header, value);
return rv;
}
nsresult
nsNNTPNewsgroupList::CallFilters()
{
nsresult rv;
nsCString filterString;
nsCOMPtr <nsIMsgFolder> folder = do_QueryInterface(m_newsFolder, &rv);
NS_ENSURE_SUCCESS(rv,rv);
PRUint32 filterCount = 0;
if (m_filterList)
{
rv = m_filterList->GetFilterCount(&filterCount);
NS_ENSURE_SUCCESS(rv,rv);
}
PRUint32 serverFilterCount = 0;
if (m_serverFilterList)
{
rv = m_serverFilterList->GetFilterCount(&serverFilterCount);
NS_ENSURE_SUCCESS(rv,rv);
}
if (filterCount == 0 && serverFilterCount == 0)
return NS_OK;
PRUint32 count = 0;
PRUint32 *keys;
rv = m_newsDB->GetNewList(&count, &keys);
NS_ENSURE_SUCCESS(rv,rv);
for (PRUint32 i = 0; i<count; i++)
{
m_addHdrToDB = PR_TRUE;
rv = m_newsDB->GetMsgHdrForKey(*keys++, getter_AddRefs(m_newMsgHdr));
NS_ENSURE_SUCCESS(rv, rv);
// build up a "headers" for filter code
nsCString subject, author, date;
rv = m_newMsgHdr->GetSubject(getter_Copies(subject));
NS_ENSURE_SUCCESS(rv,rv);
rv = m_newMsgHdr->GetAuthor(getter_Copies(author));
NS_ENSURE_SUCCESS(rv,rv);
nsCString fullHeaders;
if (!(author.IsEmpty()))
{
fullHeaders.AppendLiteral(FROM_HEADER);
fullHeaders += author;
fullHeaders += '\0';
}
if (!(subject.IsEmpty()))
{
fullHeaders.AppendLiteral(SUBJECT_HEADER);
fullHeaders += subject;
fullHeaders += '\0';
}
for (PRInt32 header = 0; header < m_filterHeaders.Count(); header++)
{
char *retValue;
m_newMsgHdr->GetStringProperty(m_filterHeaders[header]->get(), &retValue);
if (*retValue)
{
fullHeaders += *(m_filterHeaders[header]);
fullHeaders.AppendLiteral(": ");
fullHeaders += nsCString(retValue);
fullHeaders += '\0';
}
}
// the per-newsgroup filters should probably go first. It doesn't matter
// right now since nothing stops filter execution for newsgroups, but if something
// does, like adding a "stop execution" action, then users should be able to
// override the global filters in the per-newsgroup filters.
if (filterCount)
{
rv = m_filterList->ApplyFiltersToHdr(nsMsgFilterType::NewsRule, m_newMsgHdr, folder, m_newsDB,
fullHeaders.get(), fullHeaders.Length(), this, m_msgWindow, nsnull);
}
if (serverFilterCount)
{
rv = m_serverFilterList->ApplyFiltersToHdr(nsMsgFilterType::NewsRule, m_newMsgHdr, folder, m_newsDB,
fullHeaders.get(), fullHeaders.Length(), this, m_msgWindow, nsnull);
}
NS_ENSURE_SUCCESS(rv,rv);
if (!m_addHdrToDB)
m_newsDB->DeleteHeader(m_newMsgHdr, nsnull, PR_FALSE, PR_FALSE);
}
return NS_OK;
}
void
nsNNTPNewsgroupList::SetProgressBarPercent(PRInt32 percent)
{
@@ -1233,59 +1108,6 @@ nsNNTPNewsgroupList::SetProgressStatus(const PRUnichar *message)
}
}
void
nsNNTPNewsgroupList::UpdateStatus(PRBool filtering, PRInt32 numDLed, PRInt32 totToDL)
{
double ratio = filtering ? (m_currentXHDRIndex+1.0)/(m_filterHeaders.Count()+1)
: 1.0/(m_filterHeaders.Count()+1);
PRInt32 percent = (PRInt32)(ratio * numDLed / totToDL);
nsAutoString numDownloadedStr;
numDownloadedStr.AppendInt(numDLed);
nsAutoString totalToDownloadStr;
totalToDownloadStr.AppendInt(totToDL);
nsresult rv;
nsString statusString;
nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
if (!NS_SUCCEEDED(rv))
return;
nsCOMPtr<nsIStringBundle> bundle;
rv = bundleService->CreateBundle(NEWS_MSGS_URL, getter_AddRefs(bundle));
if (!NS_SUCCEEDED(rv))
return;
if (filtering)
{
NS_ConvertUTF8toUTF16 header(*m_filterHeaders[m_currentXHDRIndex]);
const PRUnichar *formatStrings[3] = { header.get(),
numDownloadedStr.get(), totalToDownloadStr.get() };
rv = bundle->FormatStringFromName(NS_LITERAL_STRING("downloadingFilterHeaders").get(),
formatStrings, 3, getter_Copies(statusString));
}
else
{
const PRUnichar *formatStrings[2] = { numDownloadedStr.get(),
totalToDownloadStr.get() };
rv = bundle->FormatStringFromName(NS_LITERAL_STRING("downloadingHeaders").get(),
formatStrings, 2, getter_Copies(statusString));
}
if (!NS_SUCCEEDED(rv))
return;
SetProgressStatus(statusString.get());
m_lastStatusUpdate = PR_Now();
// only update the progress meter if it has changed
if (percent != m_lastPercent)
{
SetProgressBarPercent(percent);
m_lastPercent = percent;
}
}
NS_IMETHODIMP nsNNTPNewsgroupList::SetGetOldMessages(PRBool aGetOldMessages)
{
m_getOldMessages = aGetOldMessages;

View File

@@ -103,9 +103,6 @@ private:
void SetProgressBarPercent(PRInt32 percent);
void SetProgressStatus(const PRUnichar *message);
void UpdateStatus(PRBool filtering, PRInt32 numDled, PRInt32 totToDL);
nsresult AddHeader(const char * header, const char * value);
protected:
PRBool m_getOldMessages;
PRBool m_promptedAlready;
@@ -127,19 +124,12 @@ protected:
struct MSG_NewsKnown m_knownArts;
nsMsgKeySet *m_set;
nsCStringArray m_filterHeaders;
PRInt32 m_currentXHDRIndex;
nsCString m_lastHeader;
nsCString m_thisLine;
private:
nsCOMPtr <nsIMsgWindow> m_msgWindow;
nsCOMPtr <nsIMsgFilterList> m_filterList;
nsCOMPtr <nsIMsgFilterList> m_serverFilterList;
nsCOMPtr <nsIMsgDBHdr> m_newMsgHdr; /* current message header we're building */
PRBool m_addHdrToDB;
};
#endif /* nsNNTPNewsgroupListState_h___ */

View File

@@ -97,8 +97,6 @@
#include "nsIMsgNewsFolder.h"
#include "nsIDocShell.h"
#include "nsIMsgFilterList.h"
// for the memory cache...
#include "nsICacheEntryDescriptor.h"
#include "nsICacheSession.h"
@@ -204,9 +202,6 @@ const char *const stateLabels[] = {
"NNTP_XOVER_RESPONSE",
"NNTP_XOVER",
"NEWS_PROCESS_XOVER",
"NNTP_XHDR_SEND",
"NNTP_XHDR_RESPONSE",
"NNTP_XHDR",
"NNTP_READ_GROUP",
"NNTP_READ_GROUP_RESPONSE",
"NNTP_READ_GROUP_BODY",
@@ -3295,11 +3290,8 @@ void nsNNTPProtocol::HandleAuthenticationFailure()
}
}
///////////////////////////////////////////////////////////////////////////////
// XOVER, XHDR, and HEAD processing code
// Used for filters
// State machine explanation located in doxygen comments for nsNNTPProtocol
///////////////////////////////////////////////////////////////////////////////
/* start the xover command
*/
PRInt32 nsNNTPProtocol::BeginReadXover()
{
@@ -3383,7 +3375,8 @@ PRInt32 nsNNTPProtocol::FigureNextChunk()
rv = m_newsgroupList->GetRangeOfArtsToDownload(m_msgWindow,
m_firstPossibleArticle,
m_lastPossibleArticle,
m_numArticlesWanted - m_numArticlesLoaded,
m_numArticlesWanted -
m_numArticlesLoaded,
&(m_firstArticle),
&(m_lastArticle),
&status);
@@ -3504,7 +3497,7 @@ PRInt32 nsNNTPProtocol::ReadXover(nsIInputStream * inputStream, PRUint32 length)
if(line[0] == '.' && line[1] == '\0')
{
m_nextState = NNTP_XHDR_SEND;
m_nextState = NNTP_FIGURE_NEXT_CHUNK;
ClearFlag(NNTP_PAUSE_FOR_READ);
PR_Free(lineToFree);
return(0);
@@ -3526,7 +3519,7 @@ PRInt32 nsNNTPProtocol::ReadXover(nsIInputStream * inputStream, PRUint32 length)
m_numArticlesLoaded++;
PR_Free(lineToFree);
return NS_SUCCEEDED(rv) ? (PRInt32)status : -1; /* keep going if no error */
return NS_SUCCEEDED(rv) ? status : -1; /* keep going if no error */
}
/* Finished processing all the XOVER data.
@@ -3541,7 +3534,6 @@ PRInt32 nsNNTPProtocol::ProcessXover()
if (!m_newsgroupList) return -1;
PRInt32 status = 0;
m_newsgroupList->CallFilters();
rv = m_newsgroupList->FinishXOVERLINE(0,&status);
m_newsgroupList = nsnull;
if (NS_SUCCEEDED(rv) && status < 0) return status;
@@ -3551,113 +3543,17 @@ PRInt32 nsNNTPProtocol::ProcessXover()
return(MK_DATA_LOADED);
}
PRInt32 nsNNTPProtocol::XhdrSend()
{
nsCString header;
m_newsgroupList->InitXHDR(header);
if (header.IsEmpty())
{
m_nextState = NNTP_FIGURE_NEXT_CHUNK;
return 0;
}
char outputBuffer[OUTPUT_BUFFER_SIZE];
PRInt32 status = 0;
PR_snprintf(outputBuffer, OUTPUT_BUFFER_SIZE,
"XHDR %s %d-%d" CRLF,
header.get(), m_firstArticle, m_lastArticle);
NNTP_LOG_WRITE(outputBuffer);
m_nextState = NNTP_RESPONSE;
m_nextStateAfterResponse = NNTP_XHDR_RESPONSE;
SetFlag(NNTP_PAUSE_FOR_READ);
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(m_runningURL);
if (mailnewsurl)
status = SendData(mailnewsurl, outputBuffer);
return status;
}
PRInt32 nsNNTPProtocol::ReadXhdrResponse()
{
#ifdef TEST_NO_XOVER_SUPPORT
m_responseCode = MK_NNTP_RESPONSE_CHECK_ERROR; /* pretend XHDR generated an error */
#endif
if(m_responseCode != MK_NNTP_RESPONSE_XHDR_OK)
{
m_nextState = NNTP_READ_GROUP;
// The reasoning behind setting this flag and not an XHDR flag is that we
// are going to have to use HEAD instead. At that point, using XOVER as
// well is just wasting bandwidth.
SetFlag(NNTP_NO_XOVER_SUPPORT);
}
else
{
m_nextState = NNTP_XHDR;
}
return(0); /* continue */
}
PRInt32 nsNNTPProtocol::ReadXhdr(nsIInputStream * inputStream, PRUint32 length)
{
char *line, *lineToFree;
nsresult rv;
PRUint32 status = 1;
PRBool pauseForMoreData = PR_FALSE;
line = lineToFree = m_lineStreamBuffer->ReadNextLine(inputStream, status, pauseForMoreData);
if(pauseForMoreData)
{
SetFlag(NNTP_PAUSE_FOR_READ);
return 0;
}
if(!line)
return(status); /* no line yet or TCP error */
if(line[0] == '.' && line[1] == '\0')
{
m_nextState = NNTP_XHDR_SEND;
ClearFlag(NNTP_PAUSE_FOR_READ);
PR_Free(lineToFree);
return(0);
}
else if (line [0] == '.' && line [1] == '.')
/* The NNTP server quotes all lines beginning with "." by doubling it. */
line++;
if(status > 1)
{
mBytesReceived += status;
mBytesReceivedSinceLastStatusUpdate += status;
}
rv = m_newsgroupList->ProcessXHDRLine(nsCString(line));
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to process the XHDRLINE");
m_numArticlesLoaded++;
PR_Free(lineToFree);
return NS_SUCCEEDED(rv) ? (PRInt32)status : -1; /* keep going if no error */
}
PRInt32 nsNNTPProtocol::ReadNewsgroup()
{
if(m_articleNumber > m_lastArticle)
{ /* end of groups */
m_newsgroupList->InitHEAD(-1);
m_nextState = NNTP_FIGURE_NEXT_CHUNK;
ClearFlag(NNTP_PAUSE_FOR_READ);
return(0);
}
else
{
m_newsgroupList->InitHEAD(m_articleNumber);
char outputBuffer[OUTPUT_BUFFER_SIZE];
PR_snprintf(outputBuffer,
OUTPUT_BUFFER_SIZE,
@@ -3691,7 +3587,10 @@ PRInt32 nsNNTPProtocol::ReadNewsgroupResponse()
m_key = nsMsgKey_None;
return 0;
/* Give the message number to the header parser. */
rv = m_newsgroupList->ProcessNonXOVER(m_responseText);
/* convert nsresult->status */
return NS_FAILED(rv);
}
else
{
@@ -3730,16 +3629,14 @@ PRInt32 nsNNTPProtocol::ReadNewsgroupBody(nsIInputStream * inputStream, PRUint32
{
m_nextState = NNTP_READ_GROUP;
ClearFlag(NNTP_PAUSE_FOR_READ);
return 0;
}
else if (line [0] == '.' && line [1] == '.')
/* The NNTP server quotes all lines beginning with "." by doubling it. */
line++;
nsCString safe_line(line);
rv = m_newsgroupList->ProcessHEADLine(safe_line);
PR_Free(lineToFree);
rv = m_newsgroupList->ProcessNonXOVER(line);
/* convert nsresult->status */
PR_Free(lineToFree);
return NS_FAILED(rv);
}
@@ -5135,18 +5032,6 @@ nsresult nsNNTPProtocol::ProcessProtocolState(nsIURI * url, nsIInputStream * inp
status = ProcessXover();
break;
case NNTP_XHDR_SEND:
status = XhdrSend();
break;
case NNTP_XHDR_RESPONSE:
status = ReadXhdrResponse();
break;
case NNTP_XHDR:
status = ReadXhdr(inputStream, length);
break;
case NNTP_READ_GROUP:
status = ReadNewsgroup();
break;
@@ -5159,7 +5044,7 @@ nsresult nsNNTPProtocol::ProcessProtocolState(nsIURI * url, nsIInputStream * inp
break;
case NNTP_READ_GROUP_BODY:
status = ReadNewsgroupBody(inputStream, length);
status = ReadNewsgroupResponse();
break;
case NNTP_SEND_POST_DATA:

View File

@@ -118,9 +118,6 @@ NNTP_XOVER_SEND,
NNTP_XOVER_RESPONSE,
NNTP_XOVER,
NEWS_PROCESS_XOVER,
NNTP_XHDR_SEND,
NNTP_XHDR_RESPONSE,
NNTP_XHDR,
NNTP_READ_GROUP,
NNTP_READ_GROUP_RESPONSE,
NNTP_READ_GROUP_BODY,
@@ -273,6 +270,7 @@ private:
PRInt32 m_originalContentLength; /* the content length at the time of calling graph progress */
nsCOMPtr<nsIStringBundle> m_stringBundle;
nsCOMPtr<nsINntpIncomingServer> m_nntpServer;
@@ -350,6 +348,11 @@ private:
PRInt32 BeginNewsgroups();
PRInt32 ProcessNewsgroups(nsIInputStream * inputStream, PRUint32 length);
PRInt32 ReadNewsgroup();
PRInt32 ReadNewsgroupResponse();
PRInt32 ReadNewsgroupBody(nsIInputStream * inputStream, PRUint32 length);
// Protocol handlers used for posting data
PRInt32 PostData();
PRInt32 PostDataResponse();
@@ -360,105 +363,19 @@ private:
PRInt32 DisplayNewsRC();
PRInt32 DisplayNewsRCResponse();
/////////////////////////////////////////////////////////////////////////////
// XHDR, XOVER, HEAD filtering process handlers
// These are ordered by the rough order of usage
/////////////////////////////////////////////////////////////////////////////
/**
* The first step in the filtering process, the state NNTP_XOVER_BEGIN.
* This method sets up m_newsgroupList.
* Followed by: NNTP_FIGURE_NEXT_CHUNK
*/
// start off the xover command
PRInt32 BeginReadXover();
/**
* The loop control for filtering, the state NNTP_FIGURE_NEXT_CHUNK.
* This method contacts the newsgroupList to figure out which articles to
* download and then prepares it for XOVER support.
* Followed by: NEWS_PROCESS_XOVER if everything is finished
* NNTP_READ_GROUP if XOVER doesn't work
* NNTP_XOVER_SEND if XOVER does work
*/
PRInt32 FigureNextChunk();
// The XOVER process core
/**
* The state NNTP_XOVER_SEND, which actually sends the message.
* Followed by: NNTP_XOVER_RESPONSE
*/
PRInt32 XoverSend();
/**
* This state, NNTP_XOVER_RESPONSE, actually checks the XOVER capabiliity.
* Followed by: NNTP_XOVER if XOVER is supported
* NNTP_READ_GROUP if it isn't
*/
PRInt32 ReadXoverResponse();
/**
* This state, NNTP_XOVER, processes the results from the XOVER command.
* It asks nsNNTPNewsgroupList to process the line using ProcessXOVERLINE.
* Followed by: NNTP_XHDR_SEND
*/
// process the xover list as it comes from the server and load it into the sort list.
PRInt32 ReadXover(nsIInputStream * inputStream, PRUint32 length);
// See if the xover response is going to return us data. If the proper code isn't returned then
// assume xover isn't supported and use normal read_group.
PRInt32 ReadXoverResponse();
// The XHDR process core
/**
* This state, NNTP_XHDR_SEND, sends the XHDR command.
* The headers are all managed by nsNNTPNewsgroupList, and this picks them up
* one by one as they are needed.
* Followed by: NNTP_XHDR_RESPONSE if there is a header to be sent
* NNTP_FIGURE_NEXT_CHUNK if all headers have been sent
*/
PRInt32 XhdrSend();
/**
* This state, NNTP_XHDR_RESPONSE, evaluates the response.
* Note that if XHDR doesn't work properly, HEAD fallback is switched on and
* all subsequent chunks will NOT use XOVER.
* Followed by: NNTP_XHDR if XHDR works properly
* NNTP_READ_GROUP if it doesn't
*/
PRInt32 ReadXhdrResponse();
/**
* This state, NNTP_XHDR, processes each line of the XHDR response.
* It mostly passes everything off to nsNNTPNewsgroupList and only checks for
* the end of the response and various other preprocessing.
* Followed by: NNTP_XHDR_SEND
*/
PRInt32 ReadXhdr(nsIInputStream * inputStream, PRUint32 length);
// HEAD processing core
/**
* This state, NNTP_READ_GROUP, is the control for the HEAD processor.
* It sends the HEAD command and increments the article number until it is
* finished. WARNING: HEAD is REALLY SLOW.
* Followed by: NNTP_FIGURE_NEXT_CHUNK when it is finished
* NNTP_READ_GROUP_RESPONSE when it is not
*/
PRInt32 ReadNewsgroup();
/**
* This state, NNTP_READ_GROUP_RESPONSE, checks if the article exists.
* Because it is required by NNTP, if it doesn't work, the only problem would
* be that the article doesn't exist. Passes off article number data to
* nsNNTPNewsgroupList.
* Followed by: NNTP_READ_GROUP_BODY if the article exists
* NNTP_READ_GROUP if it doesn't.
*/
PRInt32 ReadNewsgroupResponse();
/**
* This state, NNTP_READ_GROUP_BODY, reads the body of the HEAD command.
* Once again, it passes information off to nsNNTPNewsgroupList.
* Followed by: NNTP_READ_GROUP
*/
PRInt32 ReadNewsgroupBody(nsIInputStream * inputStream, PRUint32 length);
/**
* This state, NNTP_PROCESS_XOVER, is the final step of the filter-processing
* code. Currently, all it does is cleans up the unread count and calls the
* filters, both via nsNNTPNewsgroupList.
* Followed by: NEWS_DONE
*/
PRInt32 XoverSend();
PRInt32 ProcessXover();
PRInt32 FigureNextChunk();
// Canceling
PRInt32 StartCancel();

View File

@@ -52,9 +52,7 @@ enterPasswordTitle=News Server Password Required
okButtonText=Download
noNewMessages=There are no new messages on the server.
# The difference between these two is that the second one is shown when processing XHDR commands
downloadingHeaders=Downloading %S of %S headers
downloadingFilterHeaders=Getting filter headers: %S (%S/%S)
downloadingArticles=Downloading articles %S-%S
bytesReceived=Downloading newsgroups: %S received (%SKB read at %SKB/sec)
checkingForNewNews=Checking newsgroup %S of %S on %S for new messages