//
// Simple Usenet
article decoders; includes classes to decode
// either yEnc
or UuEncoded binaries. In either case
you
// instantiate
the appropriate class passing it the stream
// you want
output written to, and then feed it the input lines
// via the
DecodeLine method.
//
// by Steve
Tibbett
//
using System;
using System.Collections;
using
System.Collections.Specialized;
using System.Diagnostics;
using System.Text;
using System.IO;
namespace NntpLib
{
public abstract
class ArticleDecoder
{
protected Stream
outStream = null;
public
ArticleDecoder(Stream OutputStream)
{
outStream = OutputStream;
}
public abstract bool
DecodeLine(string line);
}
public class
YencDecoder : ArticleDecoder
{
bool inBody = false;
bool inCode = false;
string beginLine;
public YencDecoder(Stream
OutputStream, string BeginLine) : base(OutputStream)
{
this.beginLine =
BeginLine;
}
/// <summary>
/// Returns true when we're done (we've found the
/// encoded block, and completed decoding it)
/// </summary>
public override bool
DecodeLine(string line)
{
if (!inBody)
{
if
(line.StartsWith("=ybegin "))
{
inBody = true;
return false;
};
}
if
(line.StartsWith("=yend "))
{
// Done
return true;
}
if (!inCode)
{
if
(line.StartsWith("=ypart "))
inCode = true;
return false;
};
if
(line.EndsWith("="))
{
Debugger.Break();
};
byte[] lineBytes =
Encoding.UTF8.GetBytes(line);
byte[] outBytes = new byte[lineBytes.Length];
int outByte = 0;
for (int i=0; i<lineBytes.Length; i++)
{
lineBytes[i] = (byte)((lineBytes[i]
+ 42) & 0xff);
char ch = (char)lineBytes[i];
if (ch ==
'=')
{
i++;
outBytes[outByte++] = (byte)((lineBytes[i]+64)&0xff);
} else
{
outBytes[outByte++] = lineBytes[i];
};
};
outStream.Write(outBytes, 0, outByte);
return false;
}
}
/// <summary>
///
Summary description for Article.
/// </summary>
public class
UuDecoder : ArticleDecoder
{
bool inBody = false;
bool inCode = false;
string beginLine;
public UuDecoder(Stream
OutputStream, string BeginLine) : base(OutputStream)
{
beginLine = BeginLine;
}
public static byte[]
uuDecode(string sBuffer)
{
// Create an output array
byte[] outBuffer = new byte[(sBuffer.Length-1)/4*3];
int outIdx = 0;
// Get the string as an
array of ASCII bytes
byte[] asciiBytes =
Encoding.ASCII.GetBytes(sBuffer);
for (int i=0; i<asciiBytes.Length; i++)
asciiBytes[i] = (byte)((asciiBytes[i]-0x20)
& 0x3f);
// Convert each block fo
4 input bytes into 3
// output bytes
for (int i = 1; i <= (asciiBytes.Length-1); i += 4)
{
outBuffer[outIdx++] = (byte)(asciiBytes[i] << 2 | asciiBytes[i+1]
>> 4);
outBuffer[outIdx++] = (byte)(asciiBytes[i+1] << 4 | asciiBytes[i+2]
>> 2);
outBuffer[outIdx++] = (byte)(asciiBytes[i+2] << 6 | asciiBytes[i+3]);
}
return outBuffer;
}
/// <summary>
/// Returns true when we're done (we've found the
/// encoded block, and completed decoding it)
/// </summary>
public override bool
DecodeLine(string line)
{
if (line.Length ==
0 && !inBody)
{
inBody = true;
return false;
};
if (inBody
&& line.StartsWith("begin"))
{
inCode = true;
return false;
};
if (inCode)
{
if
(line.Length < 5)
return true;
byte[] data =
uuDecode(line);
outStream.Write(data, 0, data.Length);
};
return false;
}
}
}