public bool TryAdd(byte pByte, out string rError) { mInputBytes[mInputByteCount++] = pByte; if (mInputByteCount == 4) { if (!ZTryDecodeBase64Byte(mInputBytes[0], out int l61) || !ZTryDecodeBase64Byte(mInputBytes[1], out int l62) || !ZTryDecodeBase64Byte(mInputBytes[2], out int l63) || !ZTryDecodeBase64Byte(mInputBytes[3], out int l64) ) { rError = "invalid base64 byte"; return(false); } mBytes.Add((byte)((l61 << 2) | (l62 >> 4))); mBytes.Add((byte)(((l62 & 15) << 4) | (l63 >> 2))); mBytes.Add((byte)(((l63 & 3) << 6) | l64)); mInputByteCount = 0; } rError = null; return(true); }
private static bool ZTryAsQuotedASCII(IList <byte> pBytes, bool pSecret, bool pEncoded, out cTextCommandPart rResult) { if (pBytes == null) { rResult = null; return(false); } var lBytes = new cByteList(pBytes.Count + 2); lBytes.Add(cASCII.DQUOTE); foreach (byte lByte in pBytes) { if (lByte == cASCII.NUL || lByte == cASCII.CR || lByte == cASCII.LF || lByte > cASCII.DEL) { rResult = null; return(false); } if (lByte == cASCII.DQUOTE || lByte == cASCII.BACKSL) { lBytes.Add(cASCII.BACKSL); } lBytes.Add(lByte); } lBytes.Add(cASCII.DQUOTE); rResult = new cTextCommandPart(lBytes, pSecret, pEncoded); return(true); }
private static bool ZTryAsQuotedASCII(string pString, bool pSecret, out cTextCommandPart rResult) { if (pString == null) { rResult = null; return(false); } var lBytes = new cByteList(pString.Length + 2); lBytes.Add(cASCII.DQUOTE); foreach (char lChar in pString) { if (lChar == cChar.NUL || lChar == cChar.CR || lChar == cChar.LF || lChar > cChar.DEL) { rResult = null; return(false); } if (lChar == '"' || lChar == '\\') { lBytes.Add(cASCII.BACKSL); } lBytes.Add((byte)lChar); } lBytes.Add(cASCII.DQUOTE); rResult = new cTextCommandPart(lBytes, pSecret); return(true); }
public bool GetRFC822FieldValue(out cByteList rFieldValue) { var lBookmark = Position; var lByteList = new cByteList(); while (true) { if (Position.AtEnd || Position.BytesLine.Literal) { Position = lBookmark; rFieldValue = null; return(false); } if (SkipBytes(kCRLFTAB)) { lByteList.Add(cASCII.TAB); } else if (SkipBytes(kCRLFSPACE)) { lByteList.Add(cASCII.SPACE); } else if (SkipBytes(CRLF)) { rFieldValue = lByteList; return(true); } else { lByteList.Add(Position.BytesLine[Position.Byte]); ZAdvance(ref Position); } } }
private static bool ZTryAsQuotedUTF8(string pString, bool pSecret, out cTextCommandPart rResult) { if (pString == null) { rResult = null; return(false); } var lEncBytes = Encoding.UTF8.GetBytes(pString); var lBytes = new cByteList(lEncBytes.Length + 2); lBytes.Add(cASCII.DQUOTE); foreach (byte lByte in lEncBytes) { if (lByte == cASCII.NUL || lByte == cASCII.CR || lByte == cASCII.LF) { rResult = null; return(false); } if (lByte == cASCII.DQUOTE || lByte == cASCII.BACKSL) { lBytes.Add(cASCII.BACKSL); } lBytes.Add(lByte); } lBytes.Add(cASCII.DQUOTE); rResult = new cTextCommandPart(lBytes, pSecret); return(true); }
}); // the byte 0-255 to be decoded is the index and the value at that position in the array is the byte that is encoded or -1 if this byte encodes nothing public static cByteList Encode(string pString) { if (pString.Length == 0) { return(new cByteList()); } var lBytes = new cByteList(); var lBuffer = new cToBase64Buffer(lBytes); bool lInBase64 = false; foreach (char lChar in pString) { if (lChar < ' ' || lChar > '~') { if (!lInBase64) { lBytes.Add(cASCII.AMPERSAND); lInBase64 = true; } byte[] lCharBytes = BitConverter.GetBytes(lChar); if (BitConverter.IsLittleEndian) { lBuffer.Add(lCharBytes[1]); lBuffer.Add(lCharBytes[0]); } else { lBuffer.Add(lCharBytes[0]); lBuffer.Add(lCharBytes[1]); } } else { if (lInBase64) { lBuffer.Flush(); lBytes.Add(cASCII.HYPEN); lInBase64 = false; } lBytes.Add((byte)lChar); if (lChar == '&') { lBytes.Add(cASCII.HYPEN); } } } if (lInBase64) { lBuffer.Flush(); lBytes.Add(cASCII.HYPEN); lInBase64 = false; } return(lBytes); }
public static cTextCommandPart AsDate(DateTime pDate) { var lBytes = new cByteList(11); lBytes.AddRange(ZIntToBytes(pDate.Day, 0)); lBytes.Add(cASCII.HYPEN); lBytes.AddRange(cASCIIMonth.Name[pDate.Month - 1]); lBytes.Add(cASCII.HYPEN); lBytes.AddRange(ZIntToBytes(pDate.Year, 4)); return(new cTextCommandPart(lBytes)); }
public void Add(byte pByte) { mInputBytes[mInputByteCount++] = pByte; if (mInputByteCount == 3) { mBytes.Add(kEncode[mInputBytes[0] >> 2]); mBytes.Add(kEncode[((mInputBytes[0] & 3) << 4) | (mInputBytes[1] >> 4)]); mBytes.Add(kEncode[((mInputBytes[1] & 15) << 2) | (mInputBytes[2] >> 6)]); mBytes.Add(kEncode[mInputBytes[2] & 63]); mInputByteCount = 0; } }
public cResponse BuildFromBuffer(byte[] pBuffer, ref int pBufferPosition, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cResponseBuilder), nameof(BuildFromBuffer)); while (pBufferPosition < pBuffer.Length) { byte lByte = pBuffer[pBufferPosition++]; if (mBytesToGo == 0) { if (mBufferedCR) { mBufferedCR = false; if (lByte == cASCII.LF) { if (ZBuildLineFromBytes(lContext)) { cResponse lResponse = new cResponse(mLines); mLines = new List <cResponseLine>(); return(lResponse); } continue; } mBytes.Add(cASCII.CR); } if (lByte == cASCII.CR) { mBufferedCR = true; } else { mBytes.Add(lByte); } } else { mBytes.Add(lByte); if (--mBytesToGo == 0) { ZAddWholeLine(true, lContext); } } } return(null); }
public static cTextCommandPart AsDateTime(DateTime pDate) { var lBytes = new cByteList(26); lBytes.Add(cASCII.DQUOTE); lBytes.AddRange(ZIntToBytes(pDate.Day, 2)); lBytes.Add(cASCII.HYPEN); lBytes.AddRange(cASCIIMonth.Name[pDate.Month - 1]); lBytes.Add(cASCII.HYPEN); lBytes.AddRange(ZIntToBytes(pDate.Year, 4)); lBytes.Add(cASCII.SPACE); lBytes.AddRange(ZIntToBytes(pDate.Hour, 2)); lBytes.Add(cASCII.COLON); lBytes.AddRange(ZIntToBytes(pDate.Minute, 2)); lBytes.Add(cASCII.COLON); lBytes.AddRange(ZIntToBytes(pDate.Second, 2)); lBytes.Add(cASCII.SPACE); if (pDate.Kind == DateTimeKind.Utc) { lBytes.AddRange(UTC); } else { var lOffset = TimeZoneInfo.Local.GetUtcOffset(pDate); if (lOffset < TimeSpan.Zero) { lBytes.Add(cASCII.HYPEN); lOffset = -lOffset; } else { lBytes.Add(cASCII.PLUS); } var lOffsetChars = lOffset.ToString("hhmm"); foreach (var lChar in lOffsetChars) { lBytes.Add((byte)lChar); } } return(new cTextCommandPart(lBytes)); }
public bool GetLanguageTag(out string rLanguageTag) { // rfc 5646, 4646, 3066, 1766 // this is a crude implementation ignoring the finer details cByteList lResult = new cByteList(); cByteList lPart; if (!GetToken(cCharset.Alpha, null, null, out lPart, 1, 8)) { rLanguageTag = null; return(false); } lResult.AddRange(lPart); while (true) { var lBookmark = Position; if (!SkipByte(cASCII.HYPEN)) { break; } if (!GetToken(cCharset.AlphaNumeric, null, null, out lPart, 1, 8)) { Position = lBookmark; break; } lResult.Add(cASCII.HYPEN); lResult.AddRange(lPart); } rLanguageTag = cTools.ASCIIBytesToString(lResult); return(true); }
public bool GetQuoted(out cByteList rBytes) { var lBookmark = Position; if (!SkipByte(cASCII.DQUOTE)) { rBytes = null; return(false); } rBytes = new cByteList(); bool lInQuote = false; while (true) { byte lByte = Position.BytesLine[Position.Byte]; ZAdvance(ref Position); if (lInQuote) { rBytes.Add(lByte); lInQuote = false; } else { if (lByte == cASCII.DQUOTE) { return(true); } if (lByte == cASCII.BACKSL) { lInQuote = true; } else { rBytes.Add(lByte); } } if (Position.AtEnd || Position.BytesLine.Literal) { Position = lBookmark; rBytes = null; return(false); } } }
public bool GetRFC822QuotedString(out string rString) { var lBookmark = Position; // optional leading spaces SkipRFC822CFWS(); // open quote if (!SkipByte(cASCII.DQUOTE)) { Position = lBookmark; rString = null; return(false); } cByteList lResult = new cByteList(); while (true) { ZGetRFC822FWS(lResult); if (Position.AtEnd || Position.BytesLine.Literal) { Position = lBookmark; rString = null; return(false); } byte lByte = Position.BytesLine[Position.Byte]; if (lByte == cASCII.BACKSL) { ZAdvance(ref Position); if (Position.AtEnd || Position.BytesLine.Literal) { Position = lBookmark; rString = null; return(false); } lByte = Position.BytesLine[Position.Byte]; } else if (!cCharset.QText.Contains(lByte)) { break; } lResult.Add(lByte); ZAdvance(ref Position); } // close quote if (!SkipByte(cASCII.DQUOTE)) { Position = lBookmark; rString = null; return(false); } // optional trailing spaces SkipRFC822CFWS(); // done rString = cTools.UTF8BytesToString(lResult); return(true); }
private async Task ZIdleIdleAsync(int pIdleRestartInterval, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cCommandPipeline), nameof(ZIdleIdleAsync), pIdleRestartInterval); using (cCountdownTimer lCountdownTimer = new cCountdownTimer(pIdleRestartInterval, lContext)) { while (true) { cCommandTag lTag = new cCommandTag(); mIdleBuffer.Clear(); mIdleBuffer.AddRange(lTag); mIdleBuffer.Add(cASCII.SPACE); mIdleBuffer.AddRange(kIdleIdle); mIdleBuffer.Add(cASCII.CR); mIdleBuffer.Add(cASCII.LF); lContext.TraceVerbose("sending {0}", mIdleBuffer); mSynchroniser.InvokeNetworkSend(mIdleBuffer, lContext); await mConnection.WriteAsync(mIdleBuffer.ToArray(), mBackgroundCancellationTokenSource.Token, lContext).ConfigureAwait(false); if (await ZIdleProcessResponsesAsync(false, null, lTag, true, lContext).ConfigureAwait(false) != eIdleProcessResponsesTerminatedBy.continuerequest) { throw new cUnexpectedServerActionException(fCapabilities.idle, "idle completed before done sent", lContext); } var lProcessResponsesTerminatedBy = await ZIdleProcessResponsesAsync(true, lCountdownTimer.GetAwaitCountdownTask(), lTag, false, lContext).ConfigureAwait(false); if (lProcessResponsesTerminatedBy == eIdleProcessResponsesTerminatedBy.commandcompletion) { throw new cUnexpectedServerActionException(fCapabilities.idle, "idle completed before done sent", lContext); } mIdleBuffer.Clear(); mIdleBuffer.AddRange(kIdleDone); mIdleBuffer.Add(cASCII.CR); mIdleBuffer.Add(cASCII.LF); lContext.TraceVerbose("sending {0}", mIdleBuffer); mSynchroniser.InvokeNetworkSend(mIdleBuffer, lContext); await mConnection.WriteAsync(mIdleBuffer.ToArray(), mBackgroundCancellationTokenSource.Token, lContext).ConfigureAwait(false); await ZIdleProcessResponsesAsync(false, null, lTag, false, lContext).ConfigureAwait(false); if (lProcessResponsesTerminatedBy == eIdleProcessResponsesTerminatedBy.backgroundreleaser) { return; } lCountdownTimer.Restart(lContext); } } }
private void ZLogResponse(cResponse pResponse, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cConnection), nameof(ZLogResponse)); cByteList lLogBytes = new cByteList(); foreach (var lLine in pResponse) { if (lLine.Literal) { lLogBytes.Add(cASCII.LBRACE); } else { lLogBytes.Add(cASCII.LBRACKET); } foreach (var lByte in lLine) { if (lLogBytes.Count == 60) { lContext.TraceVerbose($"received: {cTools.BytesToLoggableString(lLogBytes)}..."); return; } lLogBytes.Add(lByte); } if (lLine.Literal) { lLogBytes.Add(cASCII.RBRACE); } else { lLogBytes.Add(cASCII.RBRACKET); } } lContext.TraceVerbose($"received: {cTools.BytesToLoggableString(lLogBytes)}"); }
public override IList <byte> GetResponse(IList <byte> pChallenge) { if (mDone) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.AlreadyChallenged); } mDone = true; if (pChallenge != null && pChallenge.Count != 0) { throw new ArgumentOutOfRangeException("non zero length challenge"); } var lBytes = new cByteList(); lBytes.Add(0); lBytes.AddRange(Encoding.UTF8.GetBytes(mAuthenticationId)); lBytes.Add(0); lBytes.AddRange(Encoding.UTF8.GetBytes(mPassword)); return(lBytes); }
public void Flush() { if (mInputByteCount < 3) { mInputBytes[mInputByteCount] = 0; } mBytes.Add(kEncode[mInputBytes[0] >> 2]); mBytes.Add(kEncode[((mInputBytes[0] & 3) << 4) | (mInputBytes[1] >> 4)]); if (mInputByteCount != 1) { mBytes.Add(kEncode[((mInputBytes[1] & 15) << 2) | (mInputBytes[2] >> 6)]); if (mInputByteCount == 3) { mBytes.Add(kEncode[mInputBytes[2] & 63]); } } mInputByteCount = 0; return; }
private cByteList ZGetFromAsBytes(sPosition pFrom) { cByteList lBytes = new cByteList(); while (pFrom.LineNumber < Position.LineNumber) { for (int i = pFrom.Byte; i < pFrom.BytesLine.Count; i++) { lBytes.Add(pFrom.BytesLine[i]); } pFrom.Byte = 0; ZAdvancePart(ref pFrom); } if (pFrom.LineNumber == Position.LineNumber) { for (int i = pFrom.Byte; i < Position.Byte; i++) { lBytes.Add(pFrom.BytesLine[i]); } } return(lBytes); }
private static cByteList ZIntToBytes(int pNumber, int pMinLength) { if (pNumber < 0) { throw new ArgumentOutOfRangeException(nameof(pNumber)); } cByteList lBytes = cTools.IntToBytesReverse(pNumber); for (int i = lBytes.Count; i < pMinLength; i++) { lBytes.Add(cASCII.ZERO); } lBytes.Reverse(); return(lBytes); }
public static cByteList ULongToBytesReverse(ulong pNumber) { cByteList lBytes = new cByteList(20); ulong lNumber = pNumber; do { int lDigit = (int)(lNumber % 10); lBytes.Add((byte)(cASCII.ZERO + lDigit)); lNumber = lNumber / 10; } while (lNumber > 0); return(lBytes); }
private cByteList ZGetRestAsBytes() { cByteList lBytes = new cByteList(); while (!Position.AtEnd) { for (int i = Position.Byte; i < Position.BytesLine.Count; i++) { lBytes.Add(Position.BytesLine[i]); } Position.Byte = 0; ZAdvancePart(ref Position); } return(lBytes); }
private bool ZGetRFC822WSP(cByteList pBytes) { bool lResult = false; while (true) { if (Position.AtEnd || Position.BytesLine.Literal) { return(lResult); } byte lByte = Position.BytesLine[Position.Byte]; if (lByte != cASCII.SPACE && lByte != cASCII.TAB) { return(lResult); } lResult = true; pBytes.Add(lByte); ZAdvance(ref Position); } }
public cTextCommandPart(string pString, bool pSecret = false) : base(pSecret, false) { if (string.IsNullOrEmpty(pString)) { throw new ArgumentOutOfRangeException(nameof(pString)); } var lBytes = new cByteList(pString.Length); foreach (char lChar in pString) { if (lChar < ' ' || lChar > '~') { throw new ArgumentOutOfRangeException(nameof(pString)); } lBytes.Add((byte)lChar); } Bytes = new cBytes(lBytes); }
public static cByteList IntToBytesReverse(int pNumber) { if (pNumber < 0) { throw new ArgumentOutOfRangeException(nameof(pNumber)); } cByteList lBytes = new cByteList(10); int lNumber = pNumber; do { int lDigit = lNumber % 10; lBytes.Add((byte)(cASCII.ZERO + lDigit)); lNumber = lNumber / 10; } while (lNumber > 0); return(lBytes); }
private static bool ZTryAsBytesInCharset(string pString, cCharset pCharset, bool pSecret, out cTextCommandPart rResult) { if (string.IsNullOrEmpty(pString)) { rResult = null; return(false); } var lBytes = new cByteList(pString.Length); foreach (char lChar in pString) { if (!pCharset.Contains(lChar)) { rResult = null; return(false); } lBytes.Add((byte)lChar); } rResult = new cTextCommandPart(lBytes, pSecret); return(true); }
public static bool TryAsASCIILiteral(string pString, bool pSecret, out cLiteralCommandPart rResult) { if (pString == null) { rResult = null; return(false); } var lBytes = new cByteList(pString.Length); foreach (char lChar in pString) { if (lChar == cChar.NUL || lChar > cChar.DEL) { rResult = null; return(false); } lBytes.Add((byte)lChar); } rResult = new cLiteralCommandPart(lBytes, false, pSecret); return(true); }
private bool ZTryAsMailbox(string pString, char?pDelimiter, cCharset pCharset, out cCommandPart rCommandPart, out string rEncodedMailboxPath) { if (pString.Equals(cMailboxName.InboxString, StringComparison.InvariantCultureIgnoreCase)) { rCommandPart = cCommandPart.Inbox; rEncodedMailboxPath = cMailboxName.InboxString; } cTextCommandPart lText; cLiteralCommandPart lLiteral; if (ZTryAsBytesInCharset(pString, pCharset, false, out lText)) { rCommandPart = lText; rEncodedMailboxPath = pString; return(true); } if (UTF8Enabled) { if (ZTryAsQuotedUTF8(pString, false, out lText)) { rCommandPart = lText; rEncodedMailboxPath = pString; return(true); } rCommandPart = null; rEncodedMailboxPath = null; return(false); } cByteList lBytes; if (pDelimiter == null) { lBytes = cModifiedUTF7.Encode(pString); } else { char lDelimiterChar = pDelimiter.Value; byte lDelimiterByte = (byte)lDelimiterChar; string[] lSegments = pString.Split(lDelimiterChar); lBytes = new cByteList(); bool lFirst = true; foreach (string lSegment in lSegments) { if (lFirst) { lFirst = false; } else { lBytes.Add(lDelimiterByte); } lBytes.AddRange(cModifiedUTF7.Encode(lSegment)); } } if (ZTryAsBytesInCharset(lBytes, pCharset, false, false, out lText) || ZTryAsQuotedASCII(lBytes, false, false, out lText)) { rCommandPart = lText; rEncodedMailboxPath = cTools.ASCIIBytesToString(lBytes); return(true); } if (ZTryAsASCIILiteral(lBytes, false, out lLiteral)) { rCommandPart = lLiteral; rEncodedMailboxPath = cTools.ASCIIBytesToString(lBytes); return(true); } rCommandPart = null; rEncodedMailboxPath = null; return(false); }
public bool GetDomainLiteral(out string rDomainLiteral) { var lBookmark = Position; // optional leading spaces SkipRFC822CFWS(); // open bracket if (!SkipByte(cASCII.LBRACKET)) { Position = lBookmark; rDomainLiteral = null; return(false); } // the brackets are part of the result cByteList lResult = new cByteList(); lResult.Add(cASCII.LBRACKET); // optional leading FWS SkipRFC822FWS(); bool lSpace = false; while (true) { if (Position.AtEnd || Position.BytesLine.Literal) { Position = lBookmark; rDomainLiteral = null; return(false); } byte lByte = Position.BytesLine[Position.Byte]; if (lByte == cASCII.BACKSL) { ZAdvance(ref Position); if (Position.AtEnd || Position.BytesLine.Literal) { Position = lBookmark; rDomainLiteral = null; return(false); } lByte = Position.BytesLine[Position.Byte]; } else if (!cCharset.DText.Contains(lByte)) { break; } if (lSpace) { lResult.Add(cASCII.SPACE); } lResult.Add(lByte); ZAdvance(ref Position); lSpace = SkipRFC822FWS(); } // close bracket if (!SkipByte(cASCII.RBRACKET)) { Position = lBookmark; rDomainLiteral = null; return(false); } lResult.Add(cASCII.RBRACKET); // optional trailing spaces SkipRFC822CFWS(); // done rDomainLiteral = cTools.UTF8BytesToString(lResult); return(true); }
public cTextCommandPart(cSequenceSet pSequenceSet) : base(false, false) { cByteList lBytes = new cByteList(); cByteList lTemp = new cByteList(); bool lFirst = true; foreach (var lItem in pSequenceSet) { if (lFirst) { lFirst = false; } else { lBytes.Add(cASCII.COMMA); } if (lItem == cSequenceSetItem.Asterisk) { lBytes.Add(cASCII.ASTERISK); continue; } if (lItem is cSequenceSetNumber lNumber) { lTemp = cTools.UIntToBytesReverse(lNumber.Number); lTemp.Reverse(); lBytes.AddRange(lTemp); continue; } if (!(lItem is cSequenceSetRange lRange)) { throw new ArgumentException("invalid form 1", nameof(pSequenceSet)); } if (lRange.From == cSequenceSetItem.Asterisk) { lBytes.Add(cASCII.ASTERISK); continue; } if (!(lRange.From is cSequenceSetNumber lFrom)) { throw new ArgumentException("invalid form 2", nameof(pSequenceSet)); } lTemp = cTools.UIntToBytesReverse(lFrom.Number); lTemp.Reverse(); lBytes.AddRange(lTemp); lBytes.Add(cASCII.COLON); if (lRange.To == cSequenceSetItem.Asterisk) { lBytes.Add(cASCII.ASTERISK); continue; } if (!(lRange.To is cSequenceSetNumber lTo)) { throw new ArgumentException("invalid form 3", nameof(pSequenceSet)); } lTemp = cTools.UIntToBytesReverse(lTo.Number); lTemp.Reverse(); lBytes.AddRange(lTemp); } Bytes = new cBytes(lBytes); }
public bool GetToken(cCharset pCharset, byte?pEncodedIntro, byte?pRepresentsSpace, out cByteList rBytes, int pMinLength = 1, int pMaxLength = int.MaxValue) { if (Position.AtEnd) { rBytes = null; return(false); } if (Position.BytesLine.Literal) { rBytes = null; return(false); } var lBookmark1 = Position; rBytes = new cByteList(); while (true) { byte lByte = Position.BytesLine[Position.Byte]; if (lByte == pEncodedIntro) { var lBookmark2 = Position; ZAdvance(ref Position); if (ZGetHexEncodedByte(out var lByteFromHex)) { rBytes.Add(lByteFromHex); if (Position.AtEnd || Position.BytesLine.Literal || rBytes.Count == pMaxLength) { break; } continue; } Position = lBookmark2; } if (lByte == pRepresentsSpace) { rBytes.Add(cASCII.SPACE); } else { if (!pCharset.Contains(lByte)) { break; } rBytes.Add(lByte); } ZAdvance(ref Position); if (Position.AtEnd || Position.BytesLine.Literal || rBytes.Count == pMaxLength) { break; } } if (rBytes.Count < pMinLength) { Position = lBookmark1; rBytes = null; return(false); } return(true); }