1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
package org.spongycastle.openpgp;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import org.spongycastle.bcpg.BCPGOutputStream;
import org.spongycastle.bcpg.PacketTags;
import org.spongycastle.util.Strings;
/**
* Class for producing literal data packets.
*/
public class PGPLiteralDataGenerator implements StreamGenerator
{
public static final char BINARY = PGPLiteralData.BINARY;
public static final char TEXT = PGPLiteralData.TEXT;
public static final char UTF8 = PGPLiteralData.UTF8;
/**
* The special name indicating a "for your eyes only" packet.
*/
public static final String CONSOLE = PGPLiteralData.CONSOLE;
/**
* The special time for a modification time of "now" or
* the present time.
*/
public static final Date NOW = PGPLiteralData.NOW;
private BCPGOutputStream pkOut;
private boolean oldFormat = false;
public PGPLiteralDataGenerator()
{
}
/**
* Generates literal data objects in the old format, this is
* important if you need compatability with PGP 2.6.x.
*
* @param oldFormat
*/
public PGPLiteralDataGenerator(
boolean oldFormat)
{
this.oldFormat = oldFormat;
}
private void writeHeader(
OutputStream out,
char format,
byte[] encName,
long modificationTime)
throws IOException
{
out.write(format);
out.write((byte)encName.length);
for (int i = 0; i != encName.length; i++)
{
out.write(encName[i]);
}
long modDate = modificationTime / 1000;
out.write((byte)(modDate >> 24));
out.write((byte)(modDate >> 16));
out.write((byte)(modDate >> 8));
out.write((byte)(modDate));
}
/**
* Open a literal data packet, returning a stream to store the data inside
* the packet.
* <p>
* 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 OutputStream parameter out.
*
* @param out the stream we want the packet in
* @param format the format we are using
* @param name the name of the "file"
* @param length the length of the data we will write
* @param modificationTime the time of last modification we want stored.
*/
public OutputStream open(
OutputStream out,
char format,
String name,
long length,
Date modificationTime)
throws IOException
{
if (pkOut != null)
{
throw new IllegalStateException("generator already in open state");
}
byte[] encName = Strings.toUTF8ByteArray(name);
pkOut = new BCPGOutputStream(out, PacketTags.LITERAL_DATA, length + 2 + encName.length + 4, oldFormat);
writeHeader(pkOut, format, encName, modificationTime.getTime());
return new WrappedGeneratorStream(pkOut, this);
}
/**
* 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.
* <p>
* 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 OutputStream parameter out.
* <p>
* <b>Note</b>: 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.
*
* @param out the stream we want the packet in
* @param format the format we are using
* @param name the name of the "file"
* @param modificationTime the time of last modification we want stored.
* @param buffer the buffer to use for collecting data to put into chunks.
*/
public OutputStream open(
OutputStream out,
char format,
String name,
Date modificationTime,
byte[] buffer)
throws IOException
{
if (pkOut != null)
{
throw new IllegalStateException("generator already in open state");
}
pkOut = new BCPGOutputStream(out, PacketTags.LITERAL_DATA, buffer);
byte[] encName = Strings.toUTF8ByteArray(name);
writeHeader(pkOut, format, encName, modificationTime.getTime());
return new WrappedGeneratorStream(pkOut, this);
}
/**
* Close the literal data packet - this is equivalent to calling close on the stream
* returned by the open() method.
*
* @throws IOException
*/
public void close()
throws IOException
{
if (pkOut != null)
{
pkOut.finish();
pkOut.flush();
pkOut = null;
}
}
}
|