[csmaild-cvs] csmaild/src/Imap/Commands ImapCommand.cs,1.4,1.5
Brought to you by:
tamc
|
From: <ta...@us...> - 2003-07-26 01:44:10
|
Update of /cvsroot/csmaild/csmaild/src/Imap/Commands
In directory sc8-pr-cvs1:/tmp/cvs-serv906/src/Imap/Commands
Modified Files:
ImapCommand.cs
Log Message:
UIDs, UIDVALIDITYs, and literal sizes can all be uint.MaxValue big
Finished up parenthesized list parser, it should work for all commands that need it except SEARCH for now
Quite a bit of fixing yet to do to handle buffer overruns and large transmissions, but for small things (can fit into memory), we should be alright for now
Index: ImapCommand.cs
===================================================================
RCS file: /cvsroot/csmaild/csmaild/src/Imap/Commands/ImapCommand.cs,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** ImapCommand.cs 25 Jul 2003 18:46:40 -0000 1.4
--- ImapCommand.cs 25 Jul 2003 23:35:24 -0000 1.5
***************
*** 124,127 ****
--- 124,129 ----
ListString = 13, // quoted(1) + literal(4) + listchars(8)
SequenceSet = 16,
+ ParenthesizedList = 32,
+ ParenthesizedListAtom = 34, // paren(32) + atom(2)
}
***************
*** 161,164 ****
--- 163,174 ----
ParseArgumentHandler(false, string.Empty);
}
+ else if(((mArgumentTypes[mCurrentArgument] & ArgumentType.ParenthesizedList) == ArgumentType.ParenthesizedList) && mUnparsedArguments[mUnparsedArgumentIdx] == '(') // paren list
+ {
+ ParenthesizedList list;
+ if(ParseParenthesizedList(out list))
+ ParseArgumentHandler(true, list);
+ else
+ ParseArgumentHandler(false, string.Empty);
+ }
else if(((mArgumentTypes[mCurrentArgument] & ArgumentType.ListChars) == ArgumentType.ListChars))
{
***************
*** 192,201 ****
++mUnparsedArgumentIdx; // move past '{'
! int literalSize;
// read digit-nz
if(CommandPart.DigitNz.IndexOf(mUnparsedArguments[mUnparsedArgumentIdx]) != -1)
{
! literalSize = int.Parse(mUnparsedArguments[mUnparsedArgumentIdx] + string.Empty);
// read the rest of the digits
--- 202,211 ----
++mUnparsedArgumentIdx; // move past '{'
! uint literalSize;
// read digit-nz
if(CommandPart.DigitNz.IndexOf(mUnparsedArguments[mUnparsedArgumentIdx]) != -1)
{
! literalSize = uint.Parse(mUnparsedArguments[mUnparsedArgumentIdx] + string.Empty);
// read the rest of the digits
***************
*** 209,212 ****
--- 219,225 ----
else
{
+ // TODO: need to chunk the blocks somehow, as creating a uint.MaxVal buffer throws some pretty errors
+ // probably should also allow the command to specify how big is too big (for example, somebody typing
+ // in a 20 thousand character username probably is trying to break stuff
mConnection.SendContinueMessage("Ready");
mConnection.Connection.ReadBlock(new byte[literalSize], 0, literalSize, new ReceivedBlockDelegate(ReceivedLiteralString));
***************
*** 216,221 ****
else if(CommandPart.Digit.IndexOf(mUnparsedArguments[mUnparsedArgumentIdx]) != -1)
{
literalSize *= 10;
! literalSize += int.Parse(mUnparsedArguments[mUnparsedArgumentIdx] + string.Empty);
}
else // not a valid digit
--- 229,238 ----
else if(CommandPart.Digit.IndexOf(mUnparsedArguments[mUnparsedArgumentIdx]) != -1)
{
+ // TODO: this will overflow the size , so we'll need to check for that
+ // we can set a compilation option that will throw exceptions on overflow,
+ // but I would imagine that this would make things very inefficient
+ // it won't error as is, just roll around
literalSize *= 10;
! literalSize += uint.Parse(mUnparsedArguments[mUnparsedArgumentIdx] + string.Empty);
}
else // not a valid digit
***************
*** 349,354 ****
bool isGood = false; // will determine whether we've read a valid quoted string
sequenceSet = new SequenceSet(); // will store the sequenceSet string as we "read" it
! int startNumber = 0;
! int sequenceNumber = 0;
for(; mUnparsedArgumentIdx < mUnparsedArguments.Length; ++mUnparsedArgumentIdx)
--- 366,371 ----
bool isGood = false; // will determine whether we've read a valid quoted string
sequenceSet = new SequenceSet(); // will store the sequenceSet string as we "read" it
! uint startNumber = 0;
! uint sequenceNumber = 0;
for(; mUnparsedArgumentIdx < mUnparsedArguments.Length; ++mUnparsedArgumentIdx)
***************
*** 360,364 ****
else
{
! sequenceNumber = int.Parse(mUnparsedArguments[mUnparsedArgumentIdx] + string.Empty);
isGood = true;
}
--- 377,381 ----
else
{
! sequenceNumber = uint.Parse(mUnparsedArguments[mUnparsedArgumentIdx] + string.Empty);
isGood = true;
}
***************
*** 385,388 ****
--- 402,411 ----
sequenceNumber = 0;
}
+ else if(mUnparsedArguments[mUnparsedArgumentIdx] == '*') // largest possible message
+ {
+ if(sequenceNumber != 0) // * can't be part of a number
+ return false;
+ sequenceNumber = int.MaxValue;
+ }
else if(mUnparsedArguments[mUnparsedArgumentIdx] == ' ') // a space, done with the argument
break;
***************
*** 394,398 ****
{
sequenceNumber *= 10;
! sequenceNumber += int.Parse(mUnparsedArguments[mUnparsedArgumentIdx] + string.Empty);
}
}
--- 417,421 ----
{
sequenceNumber *= 10;
! sequenceNumber += uint.Parse(mUnparsedArguments[mUnparsedArgumentIdx] + string.Empty);
}
}
***************
*** 411,425 ****
}
protected class SequenceSet
{
public class SequenceRange
{
! private int mLow;
! private int mHigh;
private SequenceRange mPrevious;
private SequenceRange mNext;
! public int Low
{
get
--- 434,449 ----
}
+ #region SequenceSet
protected class SequenceSet
{
public class SequenceRange
{
! private uint mLow;
! private uint mHigh;
private SequenceRange mPrevious;
private SequenceRange mNext;
! public uint Low
{
get
***************
*** 445,449 ****
}
! public int High
{
get
--- 469,473 ----
}
! public uint High
{
get
***************
*** 469,473 ****
}
! public SequenceRange(int low, int high)
{
mLow = low;
--- 493,497 ----
}
! public SequenceRange(uint low, uint high)
{
mLow = low;
***************
*** 477,481 ****
}
! public SequenceRange AddRange(int low, int high)
{
if(low <= mHigh + 1 && high >= mLow - 1) // they can combine with us
--- 501,505 ----
}
! public SequenceRange AddRange(uint low, uint high)
{
if(low <= mHigh + 1 && high >= mLow - 1) // they can combine with us
***************
*** 520,532 ****
private SequenceRange mRootNode;
! public void AddRange(int num)
{
AddRange(num, num);
}
! public void AddRange(int start, int end)
{
! int low = Math.Min(start, end);
! int high = Math.Max(start, end);
if(mRootNode == null)
--- 544,556 ----
private SequenceRange mRootNode;
! public void AddRange(uint num)
{
AddRange(num, num);
}
! public void AddRange(uint start, uint end)
{
! uint low = Math.Min(start, end);
! uint high = Math.Max(start, end);
if(mRootNode == null)
***************
*** 536,607 ****
}
- // private void AddHelper(int lowVal, int highVal)
- // {
- // for(int idx = 0; idx < mStartRange.Count; ++idx)
- // {
- // if(lowVal == (int)mStartRange[idx]) // we start on the same value, wee!
- // {
- // if(highVal > (int)mEndRange[idx]) // we end higher, change some stuff
- // AddHelperHelper(idx, highVal);
- // break;
- // }
- // else if(lowVal > (int)mStartRange[idx]) // we start higher then this guy starts
- // {
- // if(lowVal <= (int)mEndRange[idx]+1) // we start lower or on this guys end+1
- // {
- // if(highVal > (int)mEndRange[idx]) // we end higher, change some stuff
- // AddHelperHelper(idx, highVal);
- // break;
- // }
- // else if(idx == mStartRange.Count-1) // start higher then end and at the end of ranges, just add
- // {
- // mStartRange.Insert(idx+1, lowVal);
- // mEndRange.Insert(idx+1, highVal);
- // }
- // }
- // else // we start lower then this guy starts
- // {
- // if(highVal > (int)mStartRange[idx]) // we end higher or on this guys start+1
- // {
- // // need to adjust start
- // mStartRange[idx] = lowVal;
- //
- // if(highVal > (int)mEndRange[idx]) // we end higher then this guy ends
- // AddHelperHelper(idx, highVal);
- // break;
- // }
- // continue;
- // }
- // }
- // }
- //
- // private void AddHelperHelper(int idx, int highVal)
- // {
- // // firstly, adjust the end
- // mEndRange[idx] = Math.Max(highVal, (int)mEndRange[idx]);
- //
- // ++idx;
- //
- // // while we haven't exhausted the array and we can combine sequences
- // while(idx < mStartRange.Count && highVal > (int)mStartRange[idx])
- // {
- // // this range can consume the entire next range
- // if(highVal >= (int)mEndRange[idx])
- // {
- // mStartRange.RemoveAt(idx);
- // mEndRange.RemoveAt(idx);
- // continue; // still need to see how much more we can eat
- // }
- // else // we need to combine the ranges
- // {
- // // make previous range all inclusive
- // mEndRange[idx-1] = mEndRange[idx];
- // mStartRange.RemoveAt(idx);
- // mEndRange.RemoveAt(idx);
- // break; // done
- // }
- // }
- // }
-
public override string ToString()
{
--- 560,563 ----
***************
*** 609,612 ****
--- 565,695 ----
}
}
+ #endregion
+
+ #endregion
+
+ #region Parenthesized list string
+ /// <summary>
+ /// Default implementation does not handle anything but atoms as elements
+ /// Which means as of IMAP4rev1 it should handle all input except for the SEARCH command
+ /// </summary>
+ protected virtual bool ParseParenthesizedList(out ParenthesizedList list)
+ {
+ bool isGood = false; // will determine whether we've read a valid parenthesized list
+ string dataItem = string.Empty; // stores the data item as we're reading it
+ list = new ParenthesizedList();
+
+ for(++mUnparsedArgumentIdx; mUnparsedArgumentIdx < mUnparsedArguments.Length; ++mUnparsedArgumentIdx)
+ {
+ if(mUnparsedArguments[mUnparsedArgumentIdx] == ')')
+ {
+ isGood = true;
+ if(dataItem != string.Empty)
+ list.AddItem(dataItem);
+ break;
+ }
+ else if(mUnparsedArguments[mUnparsedArgumentIdx] == '(')
+ {
+ ParenthesizedList nestedList;
+ if(ParseParenthesizedList(out nestedList))
+ list.AddItem(list);
+ else
+ return false;
+ }
+ else if(mUnparsedArguments[mUnparsedArgumentIdx] == ' ')
+ {
+ if(dataItem != string.Empty)
+ {
+ list.AddItem(dataItem);
+ dataItem = string.Empty;
+ }
+ else // getting a space after an empty item is not permitted
+ return false;
+ }
+ else
+ {
+ if(CommandPart.AtomChar.IndexOf(mUnparsedArguments[mUnparsedArgumentIdx]) == -1)
+ return false;
+ else
+ dataItem += mUnparsedArguments[mUnparsedArgumentIdx];
+ }
+ }
+
+ ++mUnparsedArgumentIdx;
+ return isGood;
+ }
+
+ #region ParenthesizedList
+ protected class ParenthesizedList
+ {
+ #region ParenthesizedListItem
+ public class ParenthesizedListItem
+ {
+ private object mDataItem;
+ private ParenthesizedList mNestedList;
+
+ public object DataItem
+ {
+ get
+ {
+ return mDataItem;
+ }
+ }
+
+ public ParenthesizedList NestedList
+ {
+ get
+ {
+ return mNestedList;
+ }
+ }
+
+ public ParenthesizedListItem(object data)
+ {
+ if(data is ParenthesizedList)
+ {
+ mDataItem = null;
+ mNestedList = data as ParenthesizedList;
+ }
+ else
+ {
+ mDataItem = data;
+ mNestedList = null;
+ }
+ }
+
+ public override string ToString()
+ {
+ if(mDataItem == null)
+ return mNestedList.ToString();
+ else
+ return mDataItem.ToString();
+ }
+
+ }
+ #endregion
+
+ private ArrayList mItems;
+
+ public ParenthesizedList()
+ {
+ mItems = new ArrayList();
+ }
+
+ public void AddItem(object data)
+ {
+ mItems.Add(new ParenthesizedListItem(data));
+ }
+
+ public override string ToString()
+ {
+ string rv = "(";
+ for(int idx = 0; idx < mItems.Count; ++idx)
+ rv += mItems[idx].ToString() + (idx != mItems.Count-1 ? " " : string.Empty);
+ return rv + ")";
+ }
+ }
+ #endregion
+
#endregion
|