add support for envelope command 23181 and other bug fixes 27145 31913 r=mscott

git-svn-id: svn://10.0.0.236/trunk@63454 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
bienvenu%netscape.com
2000-03-20 01:29:13 +00:00
parent 71879c4632
commit 119f0123c6
7 changed files with 321 additions and 72 deletions

View File

@@ -156,18 +156,6 @@ void nsIMAPGenericParser::SetSyntaxError(PRBool error)
{
NS_ASSERTION(PR_FALSE, "syntax error in generic parser");
fSyntaxErrorLine = PL_strdup(fCurrentLine);
if (!fSyntaxErrorLine)
{
HandleMemoryFailure();
// PR_LOG(IMAP, out, ("PARSER: Internal Syntax Error: <no line>"));
}
else
{
// if (!nsCRT::strcmp(fSyntaxErrorLine, CRLF))
// PR_LOG(IMAP, out, ("PARSER: Internal Syntax Error: <CRLF>"));
// else
// PR_LOG(IMAP, out, ("PARSER: Internal Syntax Error: %s", fSyntaxErrorLine));
}
}
else
fSyntaxErrorLine = NULL;
@@ -381,8 +369,10 @@ char *nsIMAPGenericParser::CreateAtom()
// Regardless of type, call GetNextToken() to get the token after it.
char *nsIMAPGenericParser::CreateNilString()
{
if (!PL_strcasecmp(fNextToken, "NIL"))
if (!PL_strncasecmp(fNextToken, "NIL", 3))
{
if (nsCRT::strlen(fNextToken) != 3)
fNextToken += 3;
//fNextToken = GetNextToken();
return NULL;
}
@@ -473,14 +463,17 @@ char *nsIMAPGenericParser::CreateQuoted(PRBool /*skipToEnd*/)
// the quoted string was fully contained within fNextToken,
// and there is text after the quote in fNextToken that we
// still need
int charDiff = PL_strlen(fNextToken) - charIndex - 1;
fCurrentTokenPlaceHolder -= charDiff;
if (!nsCRT::strcmp(fCurrentTokenPlaceHolder, CRLF))
fAtEndOfLine = PR_TRUE;
// int charDiff = PL_strlen(fNextToken) - charIndex - 1;
// fCurrentTokenPlaceHolder -= charDiff;
// if (!nsCRT::strcmp(fCurrentTokenPlaceHolder, CRLF))
// fAtEndOfLine = PR_TRUE;
AdvanceTokenizerStartingPoint ((fNextToken - fLineOfTokens) + nsCRT::strlen(returnString) + 2);
if (!nsCRT::strcmp(fLineOfTokens, CRLF))
fAtEndOfLine = TRUE;
}
else
{
fCurrentTokenPlaceHolder += tokenIndex + charIndex + 2 - PL_strlen(fNextToken);
fCurrentTokenPlaceHolder += tokenIndex + charIndex + 1 - PL_strlen(fNextToken);
if (!*fCurrentTokenPlaceHolder)
*fCurrentTokenPlaceHolder = ' '; // put the token delimiter back
/* if (!nsCRT::strcmp(fNextToken, CRLF))
@@ -488,6 +481,8 @@ char *nsIMAPGenericParser::CreateQuoted(PRBool /*skipToEnd*/)
*/
}
}
else
NS_ASSERTION(PR_FALSE, "didn't find close quote");
return PL_strdup(returnString.GetBuffer());
}

View File

@@ -93,11 +93,11 @@ protected:
PRBool fAtEndOfLine;
PRBool fTokenizerAdvanced;
private:
char *fSyntaxErrorLine;
PRBool fDisconnected;
PRBool fSyntaxError;
private:
PRBool fDisconnected;
};

View File

@@ -221,7 +221,7 @@ nsShouldIgnoreFile(nsString& name)
return PR_TRUE;
}
NS_IMETHODIMP nsImapMailFolder::AddSubfolder(nsAutoString *name,
NS_IMETHODIMP nsImapMailFolder::AddSubfolderWithPath(nsAutoString *name, nsIFileSpec *dbPath,
nsIMsgFolder **child)
{
if(!child)
@@ -252,6 +252,7 @@ NS_IMETHODIMP nsImapMailFolder::AddSubfolder(nsAutoString *name,
if (NS_FAILED(rv))
return rv;
folder->SetPath(dbPath);
nsCOMPtr<nsIMsgImapMailFolder> imapFolder = do_QueryInterface(folder);
folder->GetFlags((PRUint32 *)&flags);
@@ -311,7 +312,6 @@ nsresult nsImapMailFolder::CreateSubFolders(nsFileSpec &path)
for (nsDirectoryIterator dir(path, PR_FALSE); dir.Exists(); dir++)
{
nsFileSpec currentFolderPath = (nsFileSpec&)dir;
folderName = currentFolderPath.GetLeafName();
currentFolderNameStr = folderName;
if (nsShouldIgnoreFile(currentFolderNameStr))
@@ -320,7 +320,7 @@ nsresult nsImapMailFolder::CreateSubFolders(nsFileSpec &path)
continue;
}
// OK, here we need to get the online name from the folder cache if we can.
// OK, here we need to get the online name from the folder cache if we can.
// If we can, use that to create the sub-folder
nsCOMPtr <nsIMsgFolderCacheElement> cacheElement;
@@ -328,7 +328,6 @@ nsresult nsImapMailFolder::CreateSubFolders(nsFileSpec &path)
nsCOMPtr <nsIFileSpec> dbFile;
NS_NewFileSpecWithSpec(currentFolderPath, getter_AddRefs(dbFile));
// don't strip off the .msf in currentFolderPath.
currentFolderPath.SetLeafName(currentFolderNameStr);
rv = NS_NewFileSpecWithSpec(currentFolderPath, getter_AddRefs(curFolder));
@@ -366,9 +365,19 @@ nsresult nsImapMailFolder::CreateSubFolders(nsFileSpec &path)
utf7LeafName.Cut(0, leafPos + 1);
}
}
}
// make the imap folder remember the file spec it was created with.
nsCAutoString leafName (currentFolderDBNameStr);
nsCOMPtr <nsIFileSpec> msfFileSpec;
rv = NS_NewFileSpecWithSpec(currentFolderPath, getter_AddRefs(msfFileSpec));
if (NS_SUCCEEDED(rv) && msfFileSpec)
{
// leaf name is the db name w/o .msf (nsShouldIgnoreFile strips it off)
// so this trims the .msf off the file spec.
msfFileSpec->SetLeafName(leafName);
}
// use the utf7 name as the uri for the folder.
AddSubfolder(&utf7LeafName, getter_AddRefs(child));
AddSubfolderWithPath(&utf7LeafName, msfFileSpec, getter_AddRefs(child));
if (child)
{
// use the unicode name as the "pretty" name. Set it so it won't be
@@ -376,17 +385,6 @@ nsresult nsImapMailFolder::CreateSubFolders(nsFileSpec &path)
if (currentFolderNameStr.Length() > 0)
child->SetName(currentFolderNameStr.GetUnicode());
// make the imap folder remember the file spec it was created with.
nsCAutoString leafName (currentFolderDBNameStr);
nsCOMPtr <nsIFileSpec> msfFileSpec;
rv = NS_NewFileSpecWithSpec(currentFolderPath, getter_AddRefs(msfFileSpec));
if (NS_SUCCEEDED(rv) && msfFileSpec)
{
// leaf name is the db name w/o .msf (nsShouldIgnoreFile strips it off)
// so this trims the .msf off the file spec.
msfFileSpec->SetLeafName(leafName);
child->SetPath(msfFileSpec);
}
}
PL_strfree(folderName);
}
@@ -650,9 +648,9 @@ NS_IMETHODIMP nsImapMailFolder::CreateClientSubfolderInfo(const char *folderName
}
//Now let's create the actual new folder
rv = AddSubfolder(&folderNameStr, getter_AddRefs(child));
if (NS_SUCCEEDED(rv) && child)
child->SetPath(dbFileSpec);
rv = AddSubfolderWithPath(&folderNameStr, dbFileSpec, getter_AddRefs(child));
// if (NS_SUCCEEDED(rv) && child)
// child->SetPath(dbFileSpec);
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(child);
if (imapFolder)
@@ -1382,6 +1380,24 @@ NS_IMETHODIMP nsImapMailFolder::DeleteMessages(nsISupportsArray *messages,
if (NS_FAILED(rv)) return rv;
rv = GetFlag(MSG_FOLDER_FLAG_TRASH, &isTrashFolder);
nsCOMPtr<nsIMsgFolder> rootFolder;
nsCOMPtr<nsIMsgFolder> trashFolder;
if (!isTrashFolder)
{
rv = GetRootFolder(getter_AddRefs(rootFolder));
if (NS_SUCCEEDED(rv) && rootFolder)
{
PRUint32 numFolders = 0;
rv = rootFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_TRASH,
1, &numFolders,
getter_AddRefs(trashFolder));
// if we can't find the trash, we'll just have to do an imap delete and pretend this is the trash
if (NS_FAILED(rv) || !trashFolder)
isTrashFolder = PR_TRUE;
}
}
if (NS_SUCCEEDED(rv) && isTrashFolder)
{
rv = StoreImapFlags(kImapMsgDeletedFlag, PR_TRUE, srcKeyArray);
@@ -1390,7 +1406,7 @@ NS_IMETHODIMP nsImapMailFolder::DeleteMessages(nsISupportsArray *messages,
if (mDatabase)
{
mDatabase->DeleteMessages(&srcKeyArray,NULL);
if(!isMove)
// if(!isMove)
{
NotifyDeleteOrMoveMessagesCompleted(this);
}
@@ -1410,28 +1426,17 @@ NS_IMETHODIMP nsImapMailFolder::DeleteMessages(nsISupportsArray *messages,
if (txnMgr) SetTransactionManager(txnMgr);
}
nsCOMPtr<nsIMsgFolder> rootFolder;
rv = GetRootFolder(getter_AddRefs(rootFolder));
if (NS_SUCCEEDED(rv) && rootFolder)
{
nsCOMPtr<nsIMsgFolder> trashFolder;
PRUint32 numFolders = 0;
rv = rootFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_TRASH,
1, &numFolders,
getter_AddRefs(trashFolder));
if(trashFolder)
{
nsCOMPtr<nsIMsgFolder> srcFolder;
nsCOMPtr<nsISupports>srcSupport;
PRUint32 count = 0;
rv = messages->Count(&count);
if(NS_SUCCEEDED(rv) && trashFolder)
{
nsCOMPtr<nsIMsgFolder> srcFolder;
nsCOMPtr<nsISupports>srcSupport;
PRUint32 count = 0;
rv = messages->Count(&count);
rv = QueryInterface(NS_GET_IID(nsIMsgFolder),
getter_AddRefs(srcFolder));
rv = QueryInterface(NS_GET_IID(nsIMsgFolder),
getter_AddRefs(srcFolder));
rv = trashFolder->CopyMessages(srcFolder, messages, PR_TRUE, msgWindow, nsnull);
}
}
}
}
return rv;
}
@@ -1852,7 +1857,13 @@ NS_IMETHODIMP nsImapMailFolder::NormalEndHeaderParseStream(nsIImapProtocol*
nsresult rv = NS_OK;
if (m_msgParser)
{
nsMailboxParseState parseState;
m_msgParser->GetState(&parseState);
if (parseState == nsIMsgParseMailMsgState::ParseHeadersState)
m_msgParser->ParseAFolderLine(CRLF, 2);
m_msgParser->GetNewMsgHdr(getter_AddRefs(newMsgHdr));
}
if (NS_SUCCEEDED(rv) && newMsgHdr)
{
char *headers;
@@ -2444,7 +2455,6 @@ void nsImapMailFolder::FindKeysToDelete(const nsMsgKeyArray &existingKeys, nsMsg
void nsImapMailFolder::FindKeysToAdd(const nsMsgKeyArray &existingKeys, nsMsgKeyArray &keysToFetch, nsIImapFlagAndUidState *flagState)
{
PRBool showDeletedMessages = ShowDeletedMessages();
int dbIndex=0; // current index into existingKeys
PRInt32 existTotal, numberOfKnownKeys;
PRInt32 messageIndex;

View File

@@ -118,7 +118,7 @@ public:
NS_IMETHOD UpdateFolder(nsIMsgWindow *aWindow);
NS_IMETHOD CreateSubfolder(const PRUnichar *folderName);
NS_IMETHOD AddSubfolder(nsAutoString *name, nsIMsgFolder **child);
NS_IMETHOD AddSubfolderWithPath(nsAutoString *name, nsIFileSpec *dbPath, nsIMsgFolder **child);
NS_IMETHOD Compact();
NS_IMETHOD EmptyTrash(nsIMsgWindow *msgWindow);

View File

@@ -87,8 +87,8 @@ static NS_DEFINE_IID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
#define OUTPUT_BUFFER_SIZE (4096*2) // mscott - i should be able to remove this if I can use nsMsgLineBuffer???
#define IMAP_DB_HEADERS "From To Cc Subject Date Priority X-Priority Message-ID References Newsgroups"
//#define IMAP_DB_HEADERS "From To Cc Subject Date Priority X-Priority Message-ID References Newsgroups"
#define IMAP_DB_HEADERS "Priority X-Priority References Newsgroups"
static const PRInt32 kImapSleepTime = 1000000;
static PRInt32 gPromoteNoopToCheckCount = 0;
@@ -2423,6 +2423,7 @@ nsImapProtocol::FetchMessage(const char * messageIds,
if (GetServerStateParser().ServerHasIMAP4Rev1Capability())
{
PRUint32 server_capabilityFlags = GetServerStateParser().GetCapabilityFlag();
PRBool aolImapServer = ((server_capabilityFlags & kAOLImapCapability) != 0);
PRBool useArbitraryHeaders = GetShouldDownloadArbitraryHeaders(); // checks filter headers, etc.
if (/***** Fix me *** gOptimizedHeaders && */// preference -- able to turn it off
useArbitraryHeaders) // if it's ok -- no filters on any header, etc.
@@ -2436,16 +2437,19 @@ nsImapProtocol::FetchMessage(const char * messageIds,
}
else
{
headersToDL = PR_smprintf("%s",IMAP_DB_HEADERS);
if (aolImapServer)
headersToDL = nsCRT::strdup(" XAOL-ENVELOPE INTERNALDATE)");
else
headersToDL = PR_smprintf("%s",IMAP_DB_HEADERS);
}
if (headersToDL)
{
char *what = PR_smprintf(" BODY.PEEK[HEADER.FIELDS (%s)])", headersToDL);
char *what = (!aolImapServer) ? PR_smprintf(" ENVELOPE BODY.PEEK[HEADER.FIELDS (%s)])", headersToDL) : nsCRT::strdup(headersToDL);
if (what)
{
commandString.Append(" %s (UID ");
if (server_capabilityFlags & kAOLImapCapability)
commandString.Append("XAOL.SIZE");
if (aolImapServer)
commandString.Append(" XAOL.SIZE") ;
else
commandString.Append("RFC822.SIZE");
commandString.Append(" FLAGS");
@@ -3349,7 +3353,6 @@ PRBool nsImapProtocol::GetShowAttachmentsInline()
PL_strchr(messageIdString,':') != nsnull);
}
PRUint32 nsImapProtocol::CountMessagesInIdString(const char *idString)
{
PRUint32 numberOfMessages = 0;

View File

@@ -956,6 +956,7 @@ void nsImapServerResponseParser::numeric_mailbox_data()
void nsImapServerResponseParser::msg_fetch()
{
nsresult res;
PRBool bNeedEndMessageDownload = PR_FALSE;
// we have not seen a uid response or flags for this fetch, yet
fCurrentResponseUID = 0;
@@ -1022,6 +1023,7 @@ void nsImapServerResponseParser::msg_fetch()
// all of this message's headers
fNextToken = GetNextToken();
fDownloadingHeaders = PR_TRUE;
bNeedEndMessageDownload = PR_FALSE;
if (ContinueParse())
msg_fetch_headers(nsnull);
}
@@ -1033,6 +1035,7 @@ void nsImapServerResponseParser::msg_fetch()
fNextToken = GetNextToken();
if (ContinueParse())
{
bNeedEndMessageDownload = PR_FALSE;
fNextToken = GetNextToken();
if (ContinueParse())
msg_fetch_headers(nsnull);
@@ -1160,9 +1163,19 @@ void nsImapServerResponseParser::msg_fetch()
mime_data();
}
else if (!PL_strcasecmp(fNextToken, "ENVELOPE"))
skip_to_CRLF(); // I never ask for this
{
fDownloadingHeaders = PR_TRUE;
bNeedEndMessageDownload = PR_TRUE;
envelope_data();
}
else if (!PL_strcasecmp(fNextToken, "INTERNALDATE"))
skip_to_CRLF(); // I will need to implement this
internal_date();
else if (!PL_strcasecmp(fNextToken, "XAOL-ENVELOPE"))
{
xaolenvelope_data();
fDownloadingHeaders = PR_TRUE;
bNeedEndMessageDownload = PR_TRUE;
}
else
SetSyntaxError(PR_TRUE);
@@ -1177,9 +1190,209 @@ void nsImapServerResponseParser::msg_fetch()
fNextToken = GetNextToken(); // eat the ')' ending token
// should be at end of line
if (bNeedEndMessageDownload)
{
if (ContinueParse())
{
nsresult rv;
rv = fServerConnection.BeginMessageDownLoad(fSizeOfMostRecentMessage,
MESSAGE_RFC822);
if (NS_FAILED(rv))
{
skip_to_CRLF();
fServerConnection.PseudoInterrupt(PR_TRUE);
fServerConnection.AbortMessageDownLoad();
return;
}
// complete the message download
fServerConnection.NormalMessageEndDownload();
}
else
fServerConnection.AbortMessageDownLoad();
}
}
}
typedef enum _envelopeItemType
{
envelopeString,
envelopeAddress
} envelopeItemType;
typedef struct
{
const char *name;
envelopeItemType type;
} envelopeItem;
static envelopeItem EnvelopeTable[] =
{
{"Date", envelopeString},
{"Subject", envelopeString},
{"From", envelopeAddress},
{"Sender", envelopeAddress},
{"Reply-to", envelopeAddress},
{"To", envelopeAddress},
{"Cc", envelopeAddress},
{"Bcc", envelopeAddress},
{"In-reply-to", envelopeString},
{"Message-id", envelopeString}
};
void nsImapServerResponseParser::envelope_data()
{
//date, subject, from, sender,
// reply-to, to, cc, bcc, in-reply-to, and message-id.
// The date, subject, in-reply-to, and message-id
//fields are strings. The from, sender, reply-to,
//to, cc, and bcc fields are addresses
fNextToken = GetNextToken();
fNextToken++; // eat '('
for (int tableIndex = 0; tableIndex < (int)(sizeof(EnvelopeTable) / sizeof(EnvelopeTable[0])); tableIndex++)
{
PRBool headerNonNil = PR_TRUE;
if (ContinueParse() && (*fNextToken != ')'))
{
nsCAutoString headerLine(EnvelopeTable[tableIndex].name);
headerLine += ": ";
if (EnvelopeTable[tableIndex].type == envelopeString)
{
char *strValue = CreateNilString();
if (strValue)
{
nsSubsumeCStr str(strValue, PR_TRUE);
headerLine += str;
}
else
headerNonNil = PR_FALSE;
}
else
{
nsCAutoString address;
parse_address(address);
headerLine += address;
if (address.Length() == 0)
headerNonNil = PR_FALSE;
}
if (headerNonNil)
fServerConnection.HandleMessageDownLoadLine(headerLine.GetBuffer(), PR_FALSE);
}
else
break;
fNextToken = GetNextToken();
}
fNextToken = GetNextToken();
}
void nsImapServerResponseParser::xaolenvelope_data()
{
// eat the opening '('
fNextToken++;
if (ContinueParse() && (*fNextToken != ')'))
{
fNextToken = GetNextToken();
fNextToken++; // eat '('
nsSubsumeCStr subject(CreateNilString(), PR_TRUE);
nsCAutoString subjectLine("Subject: ");
subjectLine += subject;
fServerConnection.HandleMessageDownLoadLine(subjectLine.GetBuffer(), PR_FALSE);
fNextToken++; // eat the next '('
if (ContinueParse())
{
fNextToken = GetNextToken();
if (ContinueParse())
{
nsCAutoString fromLine("From: ");
parse_address(fromLine);
fServerConnection.HandleMessageDownLoadLine(fromLine.GetBuffer(), PR_FALSE);
if (ContinueParse())
fNextToken = GetNextToken(); // skip attachment size
if (ContinueParse())
fNextToken = GetNextToken(); // skip image size
if (ContinueParse())
fNextToken = GetNextToken(); // skip )
}
}
}
}
void nsImapServerResponseParser::parse_address(nsCAutoString &addressLine)
{
if (!nsCRT::strcmp(fNextToken, "NIL"))
return;
PRBool firstAddress = PR_TRUE;
// should really look at chars here
NS_ASSERTION(*fNextToken == '(', "address should start with '('");
fNextToken++; // eat the next '('
while (ContinueParse() && *fNextToken == '(')
{
NS_ASSERTION(*fNextToken == '(', "address should start with '('");
fNextToken++; // eat the next '('
if (!firstAddress)
{
addressLine += ", ";
firstAddress = PR_FALSE;
}
char *personalName = CreateNilString();
fNextToken = GetNextToken();
char *atDomainList = CreateNilString();
if (ContinueParse())
{
fNextToken = GetNextToken();
char *mailboxName = CreateNilString();
if (ContinueParse())
{
fNextToken = GetNextToken();
char *hostName = CreateNilString();
// our tokenizer doesn't handle "NIL)" quite like we
// expect, so we need to check specially for this.
if (hostName || *fNextToken != ')')
fNextToken = GetNextToken(); // skip hostName
addressLine += mailboxName;
if (hostName)
{
addressLine += '@';
addressLine += hostName;
}
if (personalName)
{
addressLine += " (";
addressLine += personalName;
addressLine += ')';
}
}
}
if (*fNextToken == ')')
fNextToken++;
}
if (*fNextToken == ')')
fNextToken++;
// fNextToken = GetNextToken(); // skip "))"
}
void nsImapServerResponseParser::internal_date()
{
fNextToken = GetNextToken();
if (ContinueParse())
{
nsCAutoString dateLine("Date: ");
char *strValue = CreateNilString();
if (strValue)
{
dateLine += strValue;
nsCRT::free(strValue);
}
fServerConnection.HandleMessageDownLoadLine(dateLine.GetBuffer(), PR_FALSE);
}
// advance the parser.
fNextToken = GetNextToken();
}
void nsImapServerResponseParser::flags()
{
imapMessageFlagsType messageFlags = kNoImapMsgFlag;
@@ -2374,3 +2587,24 @@ nsImapServerResponseParser::ClearCopyResponseUID()
fCopyResponseKeyArray.RemoveAll();
}
void nsImapServerResponseParser::SetSyntaxError(PRBool error)
{
nsIMAPGenericParser::SetSyntaxError(error);
if (error)
{
if (!fSyntaxErrorLine)
{
HandleMemoryFailure();
fServerConnection.Log("PARSER", ("Internal Syntax Error: <no line>"), nsnull);
}
else
{
if (!nsCRT::strcmp(fSyntaxErrorLine, CRLF))
fServerConnection.Log("PARSER", "Internal Syntax Error: <CRLF>", nsnull);
else
fServerConnection.Log("PARSER", "Internal Syntax Error: %s", fSyntaxErrorLine);
}
}
}

View File

@@ -138,6 +138,11 @@ public:
protected:
virtual void flags();
virtual void envelope_data();
virtual void xaolenvelope_data();
virtual void parse_address(nsCAutoString &addressLine);
virtual void internal_date();
virtual void response_data();
virtual void resp_text();
virtual void resp_cond_state();
@@ -179,6 +184,8 @@ protected:
// from the open socket.
virtual PRBool GetNextLineForParser(char **nextLine);
virtual void end_of_line();
// overriden to do logging
virtual void SetSyntaxError(PRBool error);
private:
PRBool fProcessingTaggedResponse;