1 package org.apache.maven.shared.jarsigner;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.shared.utils.io.FileUtils;
23 import org.apache.maven.shared.utils.io.IOUtil;
24
25 import java.io.BufferedInputStream;
26 import java.io.BufferedOutputStream;
27 import java.io.File;
28 import java.io.FileInputStream;
29 import java.io.FileOutputStream;
30 import java.io.IOException;
31 import java.util.Map;
32 import java.util.jar.Attributes;
33 import java.util.jar.Manifest;
34 import java.util.zip.ZipEntry;
35 import java.util.zip.ZipInputStream;
36 import java.util.zip.ZipOutputStream;
37
38
39
40
41
42
43
44
45 public class JarSignerUtil
46 {
47
48 private JarSignerUtil()
49 {
50
51 }
52
53
54
55
56
57
58
59
60 public static boolean isZipFile( final File file )
61 {
62 boolean result = false;
63 try
64 {
65 ZipInputStream zis = new ZipInputStream( new FileInputStream( file ) );
66 try
67 {
68 result = zis.getNextEntry() != null;
69 }
70 finally
71 {
72 zis.close();
73 }
74 }
75 catch ( Exception e )
76 {
77
78 }
79
80 return result;
81 }
82
83
84
85
86
87
88
89
90 public static void unsignArchive( File jarFile )
91 throws IOException
92 {
93
94 File unsignedFile = new File( jarFile.getAbsolutePath() + ".unsigned" );
95
96 ZipInputStream zis = null;
97 ZipOutputStream zos = null;
98 try
99 {
100 zis = new ZipInputStream( new BufferedInputStream( new FileInputStream( jarFile ) ) );
101 zos = new ZipOutputStream( new BufferedOutputStream( new FileOutputStream( unsignedFile ) ) );
102
103 for ( ZipEntry ze = zis.getNextEntry(); ze != null; ze = zis.getNextEntry() )
104 {
105 if ( isSignatureFile( ze.getName() ) )
106 {
107 continue;
108 }
109
110 zos.putNextEntry( new ZipEntry( ze.getName() ) );
111
112 if ( isManifestFile( ze.getName() ) )
113 {
114
115
116
117 Manifest oldManifest = new Manifest( zis );
118 Manifest newManifest = buildUnsignedManifest( oldManifest );
119 newManifest.write( zos );
120
121 continue;
122 }
123
124 IOUtil.copy( zis, zos );
125 }
126
127 }
128 finally
129 {
130 IOUtil.close( zis );
131 IOUtil.close( zos );
132 }
133
134 FileUtils.rename( unsignedFile, jarFile );
135
136 }
137
138
139
140
141
142
143
144
145
146
147
148 protected static Manifest buildUnsignedManifest( Manifest manifest )
149 {
150 Manifest result = new Manifest( manifest );
151 result.getEntries().clear();
152
153 for ( Map.Entry<String, Attributes> manifestEntry : manifest.getEntries().entrySet() )
154 {
155 Attributes oldAttributes = manifestEntry.getValue();
156 Attributes newAttributes = new Attributes();
157
158 for ( Map.Entry<Object, Object> attributesEntry : oldAttributes.entrySet() )
159 {
160 String attributeKey = String.valueOf( attributesEntry.getKey() );
161 if ( !attributeKey.endsWith( "-Digest" ) )
162 {
163
164 newAttributes.put( attributesEntry.getKey(), attributesEntry.getValue() );
165 }
166 }
167
168 if ( !newAttributes.isEmpty() )
169 {
170
171 result.getEntries().put( manifestEntry.getKey(), newAttributes );
172 }
173 }
174
175 return result;
176 }
177
178
179
180
181
182
183
184
185
186 public static boolean isArchiveSigned( final File jarFile )
187 throws IOException
188 {
189 if ( jarFile == null )
190 {
191 throw new NullPointerException( "jarFile" );
192 }
193
194 ZipInputStream in = null;
195 boolean suppressExceptionOnClose = true;
196
197 try
198 {
199 boolean signed = false;
200 in = new ZipInputStream( new BufferedInputStream( new FileInputStream( jarFile ) ) );
201
202 for ( ZipEntry ze = in.getNextEntry(); ze != null; ze = in.getNextEntry() )
203 {
204 if ( isSignatureFile( ze.getName() ) )
205 {
206 signed = true;
207 break;
208 }
209 }
210
211 suppressExceptionOnClose = false;
212 return signed;
213 }
214 finally
215 {
216 try
217 {
218 if ( in != null )
219 {
220 in.close();
221 }
222 }
223 catch ( IOException e )
224 {
225 if ( !suppressExceptionOnClose )
226 {
227 throw e;
228 }
229 }
230 }
231 }
232
233
234
235
236
237
238
239
240
241 protected static boolean isSignatureFile( String entryName )
242 {
243 if ( entryName.regionMatches( true, 0, "META-INF", 0, 8 ) )
244 {
245 entryName = entryName.replace( '\\', '/' );
246
247 if ( entryName.indexOf( '/' ) == 8 && entryName.lastIndexOf( '/' ) == 8 )
248 {
249 return endsWithIgnoreCase( entryName, ".SF" ) || endsWithIgnoreCase( entryName, ".DSA" )
250 || endsWithIgnoreCase( entryName, ".RSA" ) || endsWithIgnoreCase( entryName, ".EC" );
251 }
252 }
253 return false;
254 }
255
256 protected static boolean isManifestFile( String entryName )
257 {
258 if ( entryName.regionMatches( true, 0, "META-INF", 0, 8 ) )
259 {
260 entryName = entryName.replace( '\\', '/' );
261
262 if ( entryName.indexOf( '/' ) == 8 && entryName.lastIndexOf( '/' ) == 8 )
263 {
264 return endsWithIgnoreCase( entryName, "/MANIFEST.MF" );
265 }
266 }
267 return false;
268 }
269
270 private static boolean endsWithIgnoreCase( String str, String searchStr )
271 {
272 return str.regionMatches( true, str.length() - searchStr.length(), searchStr, 0, searchStr.length() );
273 }
274 }