Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Protected Member Functions | Protected Attributes | Private Types | Private Attributes
nsIMAPGenericParser Class Reference

#include <nsIMAPGenericParser.h>

Inheritance diagram for nsIMAPGenericParser:
Inheritance graph
[legend]

List of all members.

Public Member Functions

 nsIMAPGenericParser ()
virtual ~nsIMAPGenericParser ()
virtual PRBool LastCommandSuccessful ()
PRBool SyntaxError ()
PRBool ContinueParse ()
PRBool Connected ()
void SetConnected (PRBool error)

Protected Member Functions

virtual PRBool GetNextLineForParser (char **nextLine)=0
virtual void HandleMemoryFailure ()
void skip_to_CRLF ()
void skip_to_close_paren ()
char * CreateString ()
char * CreateAstring ()
char * CreateNilString ()
char * CreateLiteral ()
char * CreateAtom (PRBool isAstring=PR_FALSE)
char * CreateQuoted (PRBool skipToEnd=PR_TRUE)
char * CreateParenGroup ()
virtual void SetSyntaxError (PRBool error, const char *msg)
void AdvanceToNextToken ()
void AdvanceToNextLine ()
void AdvanceTokenizerStartingPoint (int32 bytesToAdvance)
void ResetLexAnalyzer ()

Protected Attributes

char * fNextToken
char * fCurrentLine
char * fLineOfTokens
char * fStartOfLineOfTokens
char * fCurrentTokenPlaceHolder
PRBool fAtEndOfLine

Private Types

enum  nsIMAPGenericParserState { stateOK = 0, stateSyntaxErrorFlag = 0x1, stateDisconnectedFlag = 0x2 }

Private Attributes

PRUint32 fParserState

Detailed Description

Definition at line 50 of file nsIMAPGenericParser.h.


Member Enumeration Documentation

Enumerator:
stateOK 
stateSyntaxErrorFlag 
stateDisconnectedFlag 

Definition at line 102 of file nsIMAPGenericParser.h.


Constructor & Destructor Documentation


Member Function Documentation

Definition at line 211 of file nsIMAPGenericParser.cpp.

{
  NS_PRECONDITION(bytesToAdvance>=0, "bytesToAdvance must not be negative");
  if (!fStartOfLineOfTokens)
  {
    AdvanceToNextToken();  // the tokenizer was not yet initialized, do it now
    if (!fStartOfLineOfTokens)
      return;
  }
    
  if(!fStartOfLineOfTokens)
      return;
  // The last call to AdvanceToNextToken() cleared the token separator to '\0'
  // iff |fCurrentTokenPlaceHolder|.  We must recover this token separator now.
  if (fCurrentTokenPlaceHolder)
  {
    int endTokenOffset = fCurrentTokenPlaceHolder - fStartOfLineOfTokens - 1;
    if (endTokenOffset >= 0)
      fStartOfLineOfTokens[endTokenOffset] = fCurrentLine[endTokenOffset];
  }

  NS_ASSERTION(bytesToAdvance + (fLineOfTokens-fStartOfLineOfTokens) <=
    (int32)strlen(fCurrentLine), "cannot advance beyond end of fLineOfTokens");
  fLineOfTokens += bytesToAdvance;
  fCurrentTokenPlaceHolder = fLineOfTokens;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 177 of file nsIMAPGenericParser.cpp.

{
  PR_FREEIF( fCurrentLine );
  PR_FREEIF( fStartOfLineOfTokens);
  
  PRBool ok = GetNextLineForParser(&fCurrentLine);
  if (!ok)
  {
    SetConnected(PR_FALSE);
    fStartOfLineOfTokens = nsnull;
    fLineOfTokens = nsnull;
    fCurrentTokenPlaceHolder = nsnull;
    fAtEndOfLine = PR_TRUE;
    fNextToken = CRLF;
  }
  else if (!fCurrentLine)
  {
    HandleMemoryFailure();
  }
  else
  {
     fNextToken = nsnull;
     // determine if there are any tokens (without calling AdvanceToNextToken);
     // otherwise we are already at end of line
     NS_ASSERTION(strlen(WHITESPACE) == 3, "assume 3 chars of whitespace");
     char *firstToken = fCurrentLine;
     while (*firstToken && (*firstToken == WHITESPACE[0] ||
            *firstToken == WHITESPACE[1] || *firstToken == WHITESPACE[2]))
       firstToken++;
     fAtEndOfLine = (*firstToken == '\0');
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 150 of file nsIMAPGenericParser.cpp.

Here is the call graph for this function:

Definition at line 62 of file nsIMAPGenericParser.h.

Here is the caller graph for this function:

Definition at line 61 of file nsIMAPGenericParser.h.

{ return fParserState == stateOK; }

Here is the caller graph for this function:

char * nsIMAPGenericParser::CreateAstring ( ) [protected]

Definition at line 242 of file nsIMAPGenericParser.cpp.

{
  if (*fNextToken == '{')
    return CreateLiteral();        // literal
  else if (*fNextToken == '"')
    return CreateQuoted();         // quoted
  else
    return CreateAtom(PR_TRUE); // atom
}

Here is the call graph for this function:

Here is the caller graph for this function:

char * nsIMAPGenericParser::CreateAtom ( PRBool  isAstring = PR_FALSE) [protected]

Definition at line 264 of file nsIMAPGenericParser.cpp.

{
  char *rv = PL_strdup(fNextToken);
  if (!rv)
  {
    HandleMemoryFailure();
    return nsnull;
  }
  // We wish to stop at the following characters (in decimal ascii)
  // 1-31 (CTL), 32 (SP), 34 '"', 37 '%', 40-42 "()*", 92 '\\', 123 '{'
  // also, ']' is only allowed in astrings
  char *last = rv;
  char c = *last;
  while ((c > 42 || c == 33 || c == 35 || c == 36 || c == 38 || c == 39)
         && c != '\\' && c != '{' && (isAstring || c != ']'))
     c = *++last;
  if (rv == last) {
     SetSyntaxError(PR_TRUE, "no atom characters found");
     PL_strfree(rv);
     return nsnull;
  }
  if (*last)
  {
    // not the whole token was consumed  
    *last = '\0';
    AdvanceTokenizerStartingPoint((fNextToken - fLineOfTokens) + (last-rv));
  }
  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char * nsIMAPGenericParser::CreateLiteral ( ) [protected]

Definition at line 416 of file nsIMAPGenericParser.cpp.

{
  int32 numberOfCharsInMessage = atoi(fNextToken + 1);
  int32 charsReadSoFar = 0, currentLineLength = 0;
  int32 bytesToCopy = 0;
  
  uint32 numBytes = numberOfCharsInMessage + 1;
  NS_ASSERTION(numBytes, "overflow!");
  if (!numBytes)
    return nsnull;
  
  char *returnString = (char *) PR_Malloc(numBytes);
    if (!returnString)
        return nsnull;
 
    *(returnString + numberOfCharsInMessage) = 0; // Null terminate it first
    
    PRBool terminatedLine = PR_FALSE;
        if (fCurrentTokenPlaceHolder &&
          *fCurrentTokenPlaceHolder == nsCRT::LF &&
          *(fCurrentTokenPlaceHolder+1))
        {
          // This is a static buffer, with a CRLF between the literal size ({91}) and
          // the string itself
          fCurrentTokenPlaceHolder++;
        }
        else
        {
          // We have to read the next line from AdvanceToNextLine().
          terminatedLine = PR_TRUE;
        }
    while (ContinueParse() && (charsReadSoFar < numberOfCharsInMessage))
    {
      if(terminatedLine)
        AdvanceToNextLine();

      if (ContinueParse())
      {
        currentLineLength = strlen(terminatedLine ? fCurrentLine : fCurrentTokenPlaceHolder);
        bytesToCopy = (currentLineLength > numberOfCharsInMessage - charsReadSoFar ?
          numberOfCharsInMessage - charsReadSoFar : currentLineLength);
        NS_ASSERTION (bytesToCopy, "0 length literal?");
        
        memcpy(returnString + charsReadSoFar, terminatedLine ? fCurrentLine : fCurrentTokenPlaceHolder, bytesToCopy); 
        charsReadSoFar += bytesToCopy;
      }
      if (charsReadSoFar < numberOfCharsInMessage) // read the next line
          terminatedLine = PR_TRUE;
    }
    
    if (ContinueParse())
    {
      if (bytesToCopy == 0)
      {
        // the loop above was never executed, we just move to the next line
        if (terminatedLine)
          AdvanceToNextLine();
      }
      else if (currentLineLength == bytesToCopy)
      {
          // We have consumed the entire line.
          // Consider the input  "A1 {4}\r\nL2\r\n A3\r\n" which is read
          // line-by-line.  Reading 3 Astrings, this should result in 
          // "A1", "L2\r\n", and "A3".  Note that this confuses the parser, 
          // since the second line is "L2\r\n" where the "\r\n" is part of the
          // literal.  Hence, the 'full' imap line was not read in yet after the
          // second line of input (which is where we are now).  We now read the
          // next line to ensure that the next call to AdvanceToNextToken()
          // would lead to fNextToken=="A3" in our example.
          // Note that setting fAtEndOfLine=PR_TRUE is wrong here, since the "\r\n"
          // were just some characters from the literal; fAtEndOfLine would
          // give a misleading result.
          AdvanceToNextLine();
      }
      else
      {
        // Move fCurrentTokenPlaceHolder
        if (terminatedLine)
          AdvanceTokenizerStartingPoint (bytesToCopy);
        else
          AdvanceTokenizerStartingPoint ( bytesToCopy + 
          strlen(fNextToken) + 
          2 /* CRLF */ +
          (fNextToken - fLineOfTokens)
          );
      }       
    }
  
  return returnString;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char * nsIMAPGenericParser::CreateNilString ( ) [protected]

Definition at line 299 of file nsIMAPGenericParser.cpp.

{
  if (!PL_strncasecmp(fNextToken, "NIL", 3))
  {
    if (strlen(fNextToken) != 3)
      fNextToken += 3;
    return NULL;
  }
  else
    return CreateString();
}

Here is the call graph for this function:

Here is the caller graph for this function:

char * nsIMAPGenericParser::CreateParenGroup ( ) [protected]

Definition at line 514 of file nsIMAPGenericParser.cpp.

{
#ifdef DEBUG_bienvenu
  NS_ASSERTION(fNextToken[0] == '(', "we don't have a paren group!");
#endif
  
  int numOpenParens = 1;
  
  // build up a buffer with the paren group.
  // start with an initial chunk, expand later if necessary
  nsCString buf;
  nsCString returnString;
  int bytesUsed = 0;
  
  // count the number of parens in the current token
  int count, tokenLen = strlen(fNextToken);
  for (count = 1; (count < tokenLen) && (numOpenParens > 0); count++)
  {
    if (fNextToken[count] == '(')
      numOpenParens++;
    else if (fNextToken[count] == ')')
      numOpenParens--;
  }
  
  if ((numOpenParens > 0) && ContinueParse())
  {
    // Copy that first token from before
    returnString =fNextToken;
    returnString.Append(" ");      // space that got stripped off the token
    
    PRBool extractReset = PR_TRUE;
    while (extractReset && ContinueParse())
    {
      extractReset = PR_FALSE;
      // Go through the current line and look for the last close paren.
      // We're not trying to parse it just yet, just separate it out.
      int len = strlen(fCurrentTokenPlaceHolder);
      for (count = 0; (count < len) && (numOpenParens > 0) && !extractReset; count++)
      {
        if (*fCurrentTokenPlaceHolder == '{')
        {
          AdvanceToNextToken();
          NS_ASSERTION(fNextToken, "out of memory?or invalid syntax");
          if (fNextToken)
          {
            tokenLen = strlen(fNextToken);
            if (fNextToken[tokenLen-1] == '}')
            {
              // ok, we're looking at a literal string here
              
              // first, flush buf
              if (bytesUsed > 0)
              {
                buf.Truncate(bytesUsed);
                returnString.Append(buf);
                buf.Truncate();
                bytesUsed = 0;
              }
              
              returnString.Append(fNextToken);   // append the {xx} to the buffer
              returnString.Append(CRLF);                // append a CRLF to the buffer
              char *lit = CreateLiteral();
              NS_ASSERTION(lit, "syntax error or out of memory");
              if (lit)
              {
                returnString.Append(lit);
                //fCurrentTokenPlaceHolder += nsCRT::strlen(lit);
                //AdvanceTokenizerStartingPoint(nsCRT::strlen(lit));
                //AdvanceToNextToken();
                extractReset = PR_TRUE;
                PR_Free(lit);
              }
            }
            else
            {
#ifdef DEBUG_bienvenu
              NS_ASSERTION(PR_FALSE, "syntax error creating paren group");   // maybe not an error, but definitely a rare condition
#endif
            }
          }
        }
        else if (*fCurrentTokenPlaceHolder == '"')
        {
          // We're looking at a quoted string here.
          // Ignore the characters within it.
          
          // first, flush buf
          if (bytesUsed > 0)
          {
            buf.Truncate(bytesUsed);
            returnString.Append(buf);
            buf.Truncate();
            bytesUsed = 0;
          }
          
          AdvanceToNextToken();
          NS_ASSERTION(fNextToken, "syntax error or out of memory creating paren group");
          if (fNextToken)
          {
            char *q = CreateQuoted();
            NS_ASSERTION(q, "syntax error or out of memory creating paren group");
            if (q)
            {
              returnString.Append("\"");
              returnString.Append(q);
              returnString.Append("\"");
              extractReset = PR_TRUE;
              PR_Free(q);
            }
          }
        }
        else if (*fCurrentTokenPlaceHolder == '(')
          numOpenParens++;
        else if (*fCurrentTokenPlaceHolder == ')')
          numOpenParens--;
        
        
        if (!extractReset)
        {
          // append this character to the buffer
          buf += *fCurrentTokenPlaceHolder;
          
          //.SetCharAt(*fCurrentTokenPlaceHolder, bytesUsed);
          bytesUsed++;
          fCurrentTokenPlaceHolder++;
        }
      }
    }
  }
  else if ((numOpenParens == 0) && ContinueParse())
  {
    // the whole paren group response was finished in a single token
    buf.Append(fNextToken);
  }
  
  
  if (numOpenParens != 0 || !ContinueParse())
  {
    SetSyntaxError(PR_TRUE, "closing ')' not found in paren group");
    returnString.SetLength(0);
  }
  else
  {
    // flush buf the final time
    if (bytesUsed > 0)
    {
      buf.Truncate(bytesUsed);
      returnString.Append(buf);
      buf.Truncate();
    }
    AdvanceToNextToken();
  }
  
  return ToNewCString(returnString);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char * nsIMAPGenericParser::CreateQuoted ( PRBool  skipToEnd = PR_TRUE) [protected]

Definition at line 343 of file nsIMAPGenericParser.cpp.

{
  char *currentChar = fCurrentLine + 
    (fNextToken - fStartOfLineOfTokens)
    + 1;      // one char past opening '"'
  
  int  charIndex = 0;
  int  escapeCharsCut = 0;
  PRBool closeQuoteFound = PR_FALSE;
  nsCString returnString(currentChar);
  
  while (returnString.CharAt(charIndex))
  {
    if (returnString.CharAt(charIndex) == '"')
    {
      // don't check to see if it was escaped, 
      // that was handled in the next clause
      closeQuoteFound = PR_TRUE;
      break;
    }
    else if (returnString.CharAt(charIndex) == '\\')
    {
      // eat the escape character
      returnString.Cut(charIndex, 1);
      // whatever the escaped character was, we want it
      charIndex++;
      
      // account for charIndex not reflecting the eat of the escape character
      escapeCharsCut++;
    }
    else
      charIndex++;
  }
  
  if (closeQuoteFound)
  {
    returnString.Truncate(charIndex);
    //if ((charIndex == 0) && skipToEnd)  // it's an empty string.  Why skip to end?
    // skip_to_CRLF();
    //else if (charIndex == strlen(fCurrentLine))       // should we have this?
    //AdvanceToNextLine();
    //else 
    if (charIndex < (int) (strlen(fNextToken) - 2))     // -2 because of the start and end quotes
    {
      // the quoted string was fully contained within fNextToken,
      // and there is text after the quote in fNextToken that we
      // still need
      //                    int charDiff = strlen(fNextToken) - charIndex - 1;
      //                    fCurrentTokenPlaceHolder -= charDiff;
      //                    if (!nsCRT::strcmp(fCurrentTokenPlaceHolder, CRLF))
      //                           fAtEndOfLine = PR_TRUE;
      AdvanceTokenizerStartingPoint ((fNextToken - fLineOfTokens) + returnString.Length() + escapeCharsCut + 2);
    }
    else
    {
      fCurrentTokenPlaceHolder += escapeCharsCut + charIndex + 1 - strlen(fNextToken);
      if (!*fCurrentTokenPlaceHolder)
        *fCurrentTokenPlaceHolder = ' ';  // put the token delimiter back
                                                /*      if (!nsCRT::strcmp(fNextToken, CRLF))
                                                fAtEndOfLine = PR_TRUE;
      */
    }
  }
  else
    SetSyntaxError(PR_TRUE, "no closing '\"' found in quoted");
  
  return ToNewCString(returnString);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char * nsIMAPGenericParser::CreateString ( ) [protected]

Definition at line 316 of file nsIMAPGenericParser.cpp.

{
  if (*fNextToken == '{')
  {
    char *rv = CreateLiteral();           // literal
    return (rv);
  }
  else if (*fNextToken == '"')
  {
    char *rv = CreateQuoted();            // quoted
    return (rv);
  }
  else
  {
    SetSyntaxError(PR_TRUE, "string does not start with '{' or '\"'");
    return NULL;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

virtual PRBool nsIMAPGenericParser::GetNextLineForParser ( char **  nextLine) [protected, pure virtual]

Implemented in nsImapServerResponseParser.

Here is the caller graph for this function:

Reimplemented in nsImapServerResponseParser.

Definition at line 67 of file nsIMAPGenericParser.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:

Reimplemented in nsImapServerResponseParser.

Definition at line 81 of file nsIMAPGenericParser.cpp.

{
  return fParserState == stateOK;
}

Definition at line 95 of file nsIMAPGenericParser.cpp.

Here is the caller graph for this function:

void nsIMAPGenericParser::SetSyntaxError ( PRBool  error,
const char *  msg 
) [protected, virtual]

Reimplemented in nsImapServerResponseParser.

Definition at line 86 of file nsIMAPGenericParser.cpp.

{
  if (error)
      fParserState |= stateSyntaxErrorFlag;
  else
      fParserState &= ~stateSyntaxErrorFlag;
  NS_ASSERTION(!error, "syntax error in generic parser");      
}

Here is the caller graph for this function:

Definition at line 115 of file nsIMAPGenericParser.cpp.

{
  int numberOfCloseParensNeeded = 1;
  while (ContinueParse())
  {
    // go through fNextToken, account for nested parens
    char *loc;
    for (loc = fNextToken; loc && *loc; loc++)
    {
      if (*loc == '(')
        numberOfCloseParensNeeded++;
      else if (*loc == ')')
      {
        numberOfCloseParensNeeded--;
        if (numberOfCloseParensNeeded == 0)
        {
          fNextToken = loc + 1;
          if (!fNextToken || !*fNextToken)
            AdvanceToNextToken();
          return;
        }
      }
      else if (*loc == '{' || *loc == '"') {
        // quoted or literal  
        fNextToken = loc;
        char *a = CreateString();
        PR_FREEIF(a);
        break; // move to next token
      }
    }
    if (ContinueParse())
      AdvanceToNextToken();
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 103 of file nsIMAPGenericParser.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 60 of file nsIMAPGenericParser.h.

{ return (fParserState & stateSyntaxErrorFlag) != 0; }

Member Data Documentation

Definition at line 99 of file nsIMAPGenericParser.h.

Definition at line 95 of file nsIMAPGenericParser.h.

Definition at line 98 of file nsIMAPGenericParser.h.

Definition at line 96 of file nsIMAPGenericParser.h.

Definition at line 94 of file nsIMAPGenericParser.h.

Definition at line 105 of file nsIMAPGenericParser.h.

Definition at line 97 of file nsIMAPGenericParser.h.


The documentation for this class was generated from the following files: