// -----------------------------------------------------------------------
//
// Copyright (C) 2003-2006 Angel Marin
//
// This file is part of SharpMimeTools
//
// SharpMimeTools is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// SharpMimeTools is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with SharpMimeTools; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
// -----------------------------------------------------------------------
using System;
namespace anmar.SharpMimeTools
{
///
///
internal class SharpMimeMessageStream {
#if LOG
private static log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
#endif
protected System.IO.Stream stream;
private System.IO.StreamReader sr;
private System.Text.Encoding enc;
protected long initpos;
protected long finalpos;
private System.String _buf;
private long _buf_initpos;
private long _buf_finalpos;
public SharpMimeMessageStream ( System.IO.Stream stream ) {
this.stream = stream;
this.enc = anmar.SharpMimeTools.SharpMimeHeader.EncodingDefault;
sr = new System.IO.StreamReader ( this.stream, this.enc );
}
public SharpMimeMessageStream ( System.Byte[] buffer ) {
this.stream = new System.IO.MemoryStream(buffer);
this.enc = anmar.SharpMimeTools.SharpMimeHeader.EncodingDefault;
sr = new System.IO.StreamReader ( this.stream, this.enc );
}
public void Close(){
this.sr.Close();
}
public System.String ReadAll ( ) {
return this.ReadLines ( this.Position, this.stream.Length );
}
public System.String ReadAll ( long start ) {
return this.ReadLines ( start, this.stream.Length );
}
public System.String ReadLine ( ) {
System.String line = null;
if ( this._buf!=null ) {
line = this._buf;
this.initpos = this._buf_initpos;
this.finalpos = this._buf_finalpos;
this._buf = null;
} else {
System.Text.StringBuilder sb = new System.Text.StringBuilder(80);
int ending = 0;
this.initpos = this.Position;
for ( int current=sr.Read(); current!=-1; current=sr.Read() ) {
sb.Append((char)current);
if ( current=='\r' )
ending++;
else if ( current=='\n' ) {
ending++;
break;
}
}
// Line ending found
if ( ending>0 ) {
// Bytes read
this.finalpos+=this.enc.GetByteCount(sb.ToString());
// A single dot is treated as message end
if ( sb.Length==(1+ending) && sb[0]== '.' )
sb = null;
// Undo the double dots
else if ( sb.Length>(1+ending) && sb[0]=='.' && sb[1]=='.' )
sb.Remove(0, 1);
if ( sb!=null )
line = sb.ToString(0, sb.Length-ending);
} else {
// Not line ending found, so we are at the end of the stream
this.finalpos=this.stream.Length;
// though at the end of the stream there may be some content
if ( sb.Length>0 )
line = sb.ToString();
}
sb = null;
}
return line;
}
public System.String ReadLines ( long start, long end ) {
return this.ReadLinesSB ( start, end ).ToString();
}
public System.Text.StringBuilder ReadLinesSB ( long start, long end ) {
System.Text.StringBuilder lines = new System.Text.StringBuilder();
System.String line;
this.SeekPoint ( start );
do {
line = this.ReadLine();
if ( line!=null ) {
// TODO: try catch
if ( lines.Length>0 )
lines.Append ( ABNF.CRLF );
lines.Append ( line );
}
} while ( line!=null && this.Position!=-1 && this.Position0 ) {
System.Text.StringBuilder line = null;
System.String tmpline;
for ( ;; ) {
tmpline = this.ReadLine();
// RFC 2822 - 2.2.3 Long Header Fields
if ( tmpline!=null && tmpline.Length>0 && (tmpline[0] == ' ' || tmpline[0] == '\t') ) {
if ( line==null )
line = new System.Text.StringBuilder(first_line, 72);
line.Append(tmpline);
} else {
this.ReadLine_Undo(tmpline);
break;
}
}
this.initpos = initpos;
if ( this.finalpos!=this.initpos ) {
if ( line==null )
return first_line;
else
return line.ToString();
} else
return null;
}
return (this.finalpos!=this.initpos)?first_line:null;
}
public bool SeekLine ( long line ) {
long linenumber = 0;
this.SeekOrigin();
for ( ; linenumber<(line-1) && this.ReadLine()!=null; linenumber++ ){}
return (linenumber==(line-1))?true:false;
}
public void SeekOrigin () {
this.SeekPoint (0);
}
public void SeekPoint ( long point ) {
if ( this.sr.BaseStream.CanSeek && this.sr.BaseStream.Seek (point, System.IO.SeekOrigin.Begin) != point ) {
#if LOG
if ( log.IsErrorEnabled) log.Error ("Error while seeking");
#endif
throw new System.IO.IOException ();
} else {
this.sr.DiscardBufferedData();
this.finalpos = point;
}
this._buf = null;
}
public System.Text.Encoding Encoding {
set {
if ( value!=null && this.enc.CodePage!=value.CodePage ) {
this.enc = value;
this.SeekPoint (this.Position);
sr = new System.IO.StreamReader ( this.stream, this.enc );
}
}
}
public long Position {
get { return this.finalpos; }
}
public long Position_preRead {
get { return this.initpos; }
}
public System.IO.Stream Stream {
get { return this.stream; }
}
}
}