Thread: [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 |