/******************************************************************************* * Copyright (c) 2009 Zhao 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: * Zhao - initial API and implementation *******************************************************************************/ package org.eclipse.php.internal.core.phar; import java.io.*; import java.security.MessageDigest; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.php.internal.core.phar.digest.Digest; public class PharUtil { public static ByteArrayInputStream getStubInputStream(IStub stub) throws IOException, CoreException { ByteArrayOutputStream stubOutput = new ByteArrayOutputStream(); stub.write(stubOutput); ByteArrayInputStream fileInput = new ByteArrayInputStream(stubOutput.toByteArray()); return fileInput; } public static ByteArrayInputStream getInputStream(byte[] signature) throws IOException { ByteArrayInputStream fileInput = new ByteArrayInputStream(signature); return fileInput; } public static byte[] getStubVersionBytes(String version) { int versionNumberLength = 4; String[] s = version.split("\\."); //$NON-NLS-1$ List<Integer> versionNumbers = new ArrayList<Integer>(); for (int i = 0; i < s.length; i++) { versionNumbers.add(Integer.valueOf(s[i])); } for (int i = 0; i < versionNumberLength; i++) { versionNumbers.add(Integer.valueOf(0)); } versionNumbers = versionNumbers.subList(0, versionNumberLength); // int number = 0; // for (Iterator<Integer> iterator = versionNumbers.iterator(); iterator // .hasNext();) { // Integer versionNumber = iterator.next(); // number = number * 16 + versionNumber.intValue(); // } byte[] versionBytes = new byte[versionNumberLength / 2]; for (int i = 0; i < versionBytes.length; i++) { versionBytes[i] = (byte) (versionNumbers.get(i * 2).intValue() * 16 + versionNumbers.get(i * 2 + 1).intValue()); } return versionBytes; } public static int getPositive(byte b) { return (256 + b) % 256; } public static void throwPharException(String string) throws PharException { throw new PharException(string); } public static String getVersion(byte[] subBytes) { StringBuilder sb = new StringBuilder(); sb.append(subBytes[0] >> 4 & 0xf); sb.append(subBytes[0] & 15); sb.append(subBytes[1] >> 4 & 0xf); return sb.toString(); } public static void checkStubVilidaty(InputStream bis) throws IOException { boolean stubHasBeenFound = false; int n = -1; // this is record for whether read a byte from the stream or not int currentByte = -1; // if currentByte is equal to char '_',we will not read the next // byte while (!stubHasBeenFound && (currentByte == PharConstants.Underline || (n = bis.read()) != -1)) { if (n == PharConstants.Underline) { boolean match = false; int j = 1; for (; j < PharConstants.STUB_ENDS.length && n != -1; j++) { if ((n = bis.read()) == PharConstants.STUB_ENDS[j]) { if (j == PharConstants.STUB_ENDS.length - 1) { match = true; } } else { break; } } if (match) { if (bis.available() > 0) { j = 0; match = false; for (; j < PharConstants.STUB_TAIL.length && n != -1; j++) { n = bis.read(); if (n == PharConstants.STUB_TAIL[j]) { if (j == PharConstants.STUB_TAIL.length - 1) { match = true; } } else { break; } } if (bis.available() == 0) { stubHasBeenFound = match; } else if (isEndOfLine(bis)) { stubHasBeenFound = match; } } else { stubHasBeenFound = match; } } } } if (!stubHasBeenFound) { PharUtil.throwIOException(Messages.Stub_Invalid); } } private static boolean isEndOfLine(InputStream bis) throws IOException { final int available = bis.available(); if (available == 1) { final int first = bis.read(); return first == PharConstants.R || first == PharConstants.N; } if (available == 2) { final int first = bis.read(); final int second = bis.read(); return first == PharConstants.R && second == PharConstants.N || first == PharConstants.N && second == PharConstants.R; } return false; } private static void throwIOException(String string) throws IOException { throw new IOException(string); } public static byte[] getWholeSignature(byte[] signature, PharPackage pharPackage) { byte[] tmp = comcat(signature, Digest.DIGEST_MAP.get(pharPackage.getSignature()).getBitMap()); tmp = comcat(tmp, PharConstants.GBMB); return tmp; } public static byte[] comcat(byte[] bs, byte[] content) { byte[] tmp = new byte[bs.length + content.length]; System.arraycopy(bs, 0, tmp, 0, bs.length); System.arraycopy(content, 0, tmp, bs.length, content.length); // for (int k = 0; k < result.length; k++) { // result[k] = bytes[i + k]; // } return tmp; } public static boolean byteArrayEquals(byte[] b1, byte[] b2) { if (b1 != null && b2 != null && b1.length == b2.length) { for (int i = 0; i < b1.length; i++) { if (b1[i] != b2[i]) return false; } return true; } else { return false; } } public static boolean checkSignature(File file, Digest digest, int end) throws IOException { MessageDigest messageDigest = digest.getDigest(); messageDigest.reset(); int length = 0; InputStream contentStream = new BufferedInputStream(new FileInputStream(file)); try { int n; int size = 4096; byte[] readBuffer; if (end < size) { readBuffer = new byte[end]; } else { readBuffer = new byte[4096]; } while ((n = contentStream.read(readBuffer)) > 0) { length += n; // if (length > end) { // // n = n - (length - end); // messageDigest.update(readBuffer, 0, n - (length - end)); // contentStream.skip(-(length - end)); // break; // } else { messageDigest.update(readBuffer, 0, n); // } if (length == end) { break; } if (length + readBuffer.length > end) { readBuffer = new byte[end - length]; } } readBuffer = new byte[contentStream.available() - 8]; contentStream.read(readBuffer); if (PharUtil.byteArrayEquals(messageDigest.digest(), readBuffer)) { return true; } } finally { if (contentStream != null) { contentStream.close(); } } return false; } public static byte[] getCopy(byte[] bytes) { byte[] result = new byte[bytes.length]; for (int i = 0; i < bytes.length; i++) { result[i] = bytes[i]; } return result; } public static byte[] getGlobalBitmap(PharPackage pharPackage) { byte[] globalBitmap = PharUtil.getCopy(PharConstants.Default_Global_Bitmap); // if(pharData.) switch (pharPackage.getCompressType()) { case PharConstants.BZ2_COMPRESSED: globalBitmap[1] = 32; break; case PharConstants.GZ_COMPRESSED: globalBitmap[1] = 16; break; default: break; } if (pharPackage.isUseSignature()) { globalBitmap[2] = 1; } return globalBitmap; } public static byte[] getBitmapBytes(PharAchiveOutputEntry entry) { byte[] bitmap = PharUtil.getCopy(PharConstants.Default_Entry_Bitmap); switch (entry.getMethod()) { case PharConstants.BZ2_COMPRESSED: bitmap[1] = (byte) (bitmap[1] + 32); break; case PharConstants.GZ_COMPRESSED: bitmap[1] = (byte) (bitmap[1] + 16); break; default: break; } return bitmap; } // if the length is too length,it will not skip that long public static void skip(BufferedInputStream bis, long length) throws IOException { long n; while ((n = bis.skip(length)) != 0) { length = length - n; } } }