| /******************************************************************************* |
| * Copyright (c) 2007, 2009 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.p2.jarprocessor.unsigner; |
| import java.io.*; |
| import java.util.Enumeration; |
| import java.util.jar.JarFile; |
| import java.util.jar.Manifest; |
| import java.util.zip.*; |
| |
| /** |
| * This class removes the signature files from a jar and clean up the manifest. |
| */ |
| public class Unsigner { |
| private static final String META_INF = "META-INF"; //$NON-NLS-1$ |
| private static final String DSA_EXT = ".DSA"; //$NON-NLS-1$ |
| private static final String RSA_EXT = ".RSA"; //$NON-NLS-1$ |
| private static final String SF_EXT = ".SF"; //$NON-NLS-1$ |
| private static final String META_INF_PREFIX = META_INF + '/'; |
| |
| private String[] signers; |
| private File jarFile; |
| private boolean keepManifestContent = false; |
| |
| private boolean isSigned(File file) { |
| ZipFile jar = null; |
| try { |
| jar = new ZipFile(file); |
| |
| if (signers != null) { |
| for (int i = 0; i < signers.length; i++) { |
| if (jar.getEntry((META_INF_PREFIX + signers[i] + SF_EXT).toUpperCase()) != null) |
| return true; |
| } |
| } else { |
| Enumeration entries = jar.entries(); |
| while (entries.hasMoreElements()) { |
| ZipEntry entry = (ZipEntry) entries.nextElement(); |
| String entryName = entry.getName(); |
| if(entryName.endsWith(SF_EXT) && entryName.startsWith(META_INF)) |
| return true; |
| } |
| } |
| return false; |
| } catch (ZipException e) { |
| return false; |
| } catch (IOException e) { |
| return false; |
| } finally { |
| if (jar != null) |
| try { |
| jar.close(); |
| } catch (IOException e) { |
| //Ignore |
| } |
| } |
| } |
| |
| public void execute() { |
| processJar(jarFile); |
| } |
| |
| private void processJar(File inputFile) { |
| if (!isSigned(inputFile)) |
| return; |
| |
| try { |
| ZipInputStream input = new ZipInputStream(new BufferedInputStream(new FileInputStream(inputFile))); |
| File outputFile = File.createTempFile("removing.", ".signature", inputFile.getParentFile()); //$NON-NLS-1$ //$NON-NLS-2$ |
| ZipOutputStream output = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(outputFile))); |
| |
| ZipEntry inputZe = input.getNextEntry(); |
| byte[] b = new byte[8192]; |
| while (inputZe != null) { |
| byte remove = shouldRemove(inputZe); |
| if (remove == 2) { |
| inputZe = input.getNextEntry(); |
| continue; |
| } |
| |
| //copy the file or modify the manifest.mf |
| if (remove == 1) { |
| output.putNextEntry(new ZipEntry(inputZe.getName())); |
| Manifest m = new Manifest(); |
| m.read(input); |
| m.getEntries().clear(); //This is probably not subtle enough |
| m.write(output); |
| } else { |
| output.putNextEntry(inputZe); |
| while (input.available() != 0) { |
| int read = input.read(b); |
| if (read != -1) |
| output.write(b, 0, read); |
| } |
| } |
| output.closeEntry(); |
| input.closeEntry(); |
| |
| inputZe = input.getNextEntry(); |
| } |
| output.close(); |
| input.close(); |
| inputFile.delete(); |
| outputFile.renameTo(inputFile); |
| } catch (FileNotFoundException e) { |
| //this can't happen we have checked before |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| private byte shouldRemove(ZipEntry entry) { |
| String entryName = entry.getName(); |
| if(keepManifestContent == false && entryName.equalsIgnoreCase(JarFile.MANIFEST_NAME)) { |
| return 1; |
| } |
| if (signers != null) { |
| for (int i = 0; i < signers.length; i++) { |
| if (entryName.equalsIgnoreCase(META_INF_PREFIX + signers[i] + SF_EXT) || entryName.equalsIgnoreCase(META_INF_PREFIX + signers[i] + RSA_EXT) || entryName.equalsIgnoreCase(META_INF_PREFIX + signers[i] + DSA_EXT)) |
| return 2; |
| } |
| } else { |
| if (entryName.startsWith(META_INF) && (entryName.endsWith(SF_EXT) || entryName.endsWith(RSA_EXT) || entryName.endsWith(DSA_EXT))) |
| return 2; |
| } |
| return 0; |
| } |
| |
| public void setRemoveSigners(String[] fileName) { |
| signers = fileName; |
| } |
| |
| public void setJar(File file) { |
| jarFile = file; |
| } |
| |
| public void setKeepManifestEntries(boolean keep) { |
| keepManifestContent = keep; |
| } |
| } |