using System;
using System.IO;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Date;
namespace Org.BouncyCastle.Bcpg.OpenPgp
{
/// Class for producing literal data packets.
public class PgpLiteralDataGenerator
: IStreamGenerator
{
public const char Binary = PgpLiteralData.Binary;
public const char Text = PgpLiteralData.Text;
public const char Utf8 = PgpLiteralData.Utf8;
/// The special name indicating a "for your eyes only" packet.
public const string Console = PgpLiteralData.Console;
private BcpgOutputStream pkOut;
private bool oldFormat;
public PgpLiteralDataGenerator()
{
}
///
/// Generates literal data objects in the old format.
/// This is important if you need compatibility with PGP 2.6.x.
///
/// If true, uses old format.
public PgpLiteralDataGenerator(
bool oldFormat)
{
this.oldFormat = oldFormat;
}
private void WriteHeader(
BcpgOutputStream outStr,
char format,
byte[] encName,
long modificationTime)
{
outStr.Write(
(byte) format,
(byte) encName.Length);
outStr.Write(encName);
long modDate = modificationTime / 1000L;
outStr.Write(
(byte)(modDate >> 24),
(byte)(modDate >> 16),
(byte)(modDate >> 8),
(byte)modDate);
}
///
///
/// Open a literal data packet, returning a stream to store the data inside the packet.
///
///
/// The stream created can be closed off by either calling Close()
/// on the stream or Close() on the generator. Closing the returned
/// stream does not close off the Stream parameter outStr.
///
///
/// The stream we want the packet in.
/// The format we are using.
/// The name of the 'file'.
/// The length of the data we will write.
/// The time of last modification we want stored.
public Stream Open(
Stream outStr,
char format,
string name,
long length,
DateTime modificationTime)
{
if (pkOut != null)
throw new InvalidOperationException("generator already in open state");
if (outStr == null)
throw new ArgumentNullException("outStr");
// Do this first, since it might throw an exception
long unixMs = DateTimeUtilities.DateTimeToUnixMs(modificationTime);
byte[] encName = Strings.ToUtf8ByteArray(name);
pkOut = new BcpgOutputStream(outStr, PacketTag.LiteralData,
length + 2 + encName.Length + 4, oldFormat);
WriteHeader(pkOut, format, encName, unixMs);
return new WrappedGeneratorStream(this, pkOut);
}
///
///
/// Open a literal data packet, returning a stream to store the data inside the packet,
/// as an indefinite length stream. The stream is written out as a series of partial
/// packets with a chunk size determined by the size of the passed in buffer.
///
///
/// The stream created can be closed off by either calling Close()
/// on the stream or Close() on the generator. Closing the returned
/// stream does not close off the Stream parameter outStr.
///
///
/// Note: if the buffer is not a power of 2 in length only the largest power of 2
/// bytes worth of the buffer will be used.
///
/// The stream we want the packet in.
/// The format we are using.
/// The name of the 'file'.
/// The time of last modification we want stored.
/// The buffer to use for collecting data to put into chunks.
public Stream Open(
Stream outStr,
char format,
string name,
DateTime modificationTime,
byte[] buffer)
{
if (pkOut != null)
throw new InvalidOperationException("generator already in open state");
if (outStr == null)
throw new ArgumentNullException("outStr");
// Do this first, since it might throw an exception
long unixMs = DateTimeUtilities.DateTimeToUnixMs(modificationTime);
byte[] encName = Strings.ToUtf8ByteArray(name);
pkOut = new BcpgOutputStream(outStr, PacketTag.LiteralData, buffer);
WriteHeader(pkOut, format, encName, unixMs);
return new WrappedGeneratorStream(this, pkOut);
}
///
///
/// Open a literal data packet for the passed in FileInfo object, returning
/// an output stream for saving the file contents.
///
///
/// The stream created can be closed off by either calling Close()
/// on the stream or Close() on the generator. Closing the returned
/// stream does not close off the Stream parameter outStr.
///
///
/// The stream we want the packet in.
/// The format we are using.
/// The FileInfo object containg the packet details.
public Stream Open(
Stream outStr,
char format,
FileInfo file)
{
return Open(outStr, format, file.Name, file.Length, file.LastWriteTime);
}
[Obsolete("Dispose any opened Stream directly")]
public void Close()
{
if (pkOut != null)
{
pkOut.Finish();
pkOut.Flush();
pkOut = null;
}
}
}
}