1
2 package es.caib.signatura.impl;
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.UnsupportedEncodingException;
6
7
8
9
10
11
12
13
14 public class SMIMEPkcs7InputStream extends InputStream {
15
16 private static final int CHUNK_SIZE = 48;
17
18
19
20
21 private int status;
22 static private final int STATUS_IDLE = 0;
23 static private final int STATUS_HEADER = 1;
24 static private final int STATUS_BODY = 2;
25 static private final int STATUS_END = 3;
26
27 int bufferOffset;
28 byte buffer [];
29
30 byte signatureData [];
31 int signatureDataOffset ;
32
33
34
35
36
37 public SMIMEPkcs7InputStream(byte[] pkcs7) {
38 status = STATUS_IDLE;
39 bufferOffset = 0;
40 buffer = null;
41 signatureData = pkcs7;
42 signatureDataOffset = 0;
43
44 }
45
46
47
48
49
50
51 public synchronized void close ()
52 throws IOException {
53 status = STATUS_END;
54 }
55
56
57
58
59 public synchronized int read ()
60 throws IOException {
61 do {
62 if ( buffer != null && bufferOffset < buffer.length)
63 {
64 byte b = buffer [ bufferOffset ++ ];
65 return b;
66 } else if (status == STATUS_END) {
67 return -1;
68 } else {
69 fetchData();
70 }
71
72 } while (true);
73 }
74
75
76
77
78 public synchronized int read (byte[] targetBuffer, int offset, int length)
79 throws IOException {
80 do {
81 if ( buffer != null && bufferOffset < buffer.length)
82 {
83 int actualLength = buffer.length - bufferOffset;
84 if ( actualLength > length)
85 actualLength = length;
86 System.arraycopy(buffer, bufferOffset, targetBuffer, offset, actualLength);
87 bufferOffset = bufferOffset + actualLength;
88 return actualLength;
89 } else if (status == STATUS_END) {
90 return -1;
91 } else {
92 fetchData();
93 }
94
95 } while (true);
96 }
97
98
99
100
101 public synchronized int available()
102 throws IOException {
103 do {
104 if ( buffer != null && bufferOffset < buffer.length)
105 {
106 return buffer.length - bufferOffset;
107 } else if (status == STATUS_END) {
108 return -1;
109 } else {
110 fetchData ();
111 }
112 } while (true);
113 }
114
115 private void fetchData() throws IOException {
116 switch (status)
117 {
118 case STATUS_IDLE:
119 buffer = fetchIdle ();
120 break;
121 case STATUS_HEADER:
122 buffer = fetchHeader ();
123 break;
124 case STATUS_BODY:
125 buffer = fetchSignatureBody ();
126 break;
127 default:
128 buffer = null;
129 break;
130 }
131 bufferOffset = 0;
132 }
133
134 private byte [] fetchSignatureBody() {
135 int len = signatureData.length - signatureDataOffset;
136 if ( len <= 0)
137 {
138 status = STATUS_END;
139 return null;
140 }
141 else if ( len > CHUNK_SIZE )
142 {
143 len = CHUNK_SIZE;
144 }
145
146 byte result []= Base64.toBase64(signatureData, signatureDataOffset, len);
147 signatureDataOffset = signatureDataOffset + len;
148 return result;
149 }
150
151
152 private byte [] fetchHeader() {
153 try {
154 status = STATUS_BODY;
155 return ("Content-Type: application/pkcs7-mime; smime-type=signed-data; name=smime.p7m;\r\n"+
156 "Content-Transfer-Encoding: base64\r\n"+
157 "Content-Disposition: attachment; filename=\"smime.p7m\"\r\n"+
158 "Content-Description: S/MIME Cryptographic Signature\r\n"+
159 "\r\n").getBytes("ISO-8859-1");
160 } catch (UnsupportedEncodingException e) {
161 throw new RuntimeException (e);
162 }
163 }
164
165
166 private byte [] fetchIdle() {
167 status = STATUS_HEADER;
168 return null;
169 }
170
171
172
173
174
175
176
177
178 public synchronized long skip(long n) throws IOException {
179 for (long i = 0; i < n; i++)
180 if (this.read() < 0) return i;
181 return n;
182 }
183
184
185
186
187 public void mark(int readlimit) {}
188
189
190
191
192 public void reset() throws IOException {
193 throw new IOException("Base64InputStream does not support mark/reset");
194 }
195
196
197
198
199 public boolean markSupported() { return false; }
200
201
202
203
204
205 }