public static Map<String, ZipEntry> getZipEntries(String zipFile) throws PatchCreationException { Map<String, ZipEntry> result = new HashMap<String, ZipEntry>(); ZipFile zF = null; try { zF = new ZipFile(zipFile); for (Enumeration<? extends ZipEntry> zEntries = zF.entries(); zEntries.hasMoreElements(); ) { ZipEntry entry = (ZipEntry) zEntries.nextElement(); if (!entry.isDirectory()) if ((entry.getCrc() == -1L) || (entry.getCrc() == 0L)) { Log.info("warning: " + entry.getName() + " has wrong CRC or is a directory, ignoring"); } else { result.put(entry.getName(), entry); } } } catch (Exception e) { throw new PatchCreationException("Problem getting zip entries", e); } finally { try { if (zF != null) zF.close(); } catch (Exception e) { } } return result; }
/** * This method calculates the differences between the files inside a Jar file and generates an * output file. The output only contains the files that have difference in their CRC. * * @param olderVersionJar - file to be compared to. * @param newerVersionJar - source file of the comparisson. * @param outputDestination - path to the file that will contain the differences in those Jars. * @throws ZipException - if a ZIP error has occurred * @throws IOException - if an I/O error has occurred * @return true if the output file was generated AND has at least one entry inside it, false * otherwise. */ private static boolean calculate( File olderVersionJar, File newerVersionJar, String outputDestination) throws ZipException, IOException { ZipFile oldZip = new ZipFile(olderVersionJar); ZipFile newZip = new ZipFile(newerVersionJar); Enumeration oldEntries = oldZip.entries(); Enumeration newEntries = newZip.entries(); HashMap<String, Long> map = new HashMap<String, Long>(); while (newEntries.hasMoreElements()) { ZipEntry entry = (ZipEntry) newEntries.nextElement(); map.put(entry.getName(), entry.getCrc()); } while (oldEntries.hasMoreElements()) { ZipEntry entry = (ZipEntry) oldEntries.nextElement(); Long l = map.get(entry.getName()); if (l != null && l.longValue() == entry.getCrc()) { map.remove(entry.getName()); } } if (!map.isEmpty()) { ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outputDestination)); Set<Entry<String, Long>> set = map.entrySet(); Iterator<Entry<String, Long>> it = set.iterator(); while (it.hasNext()) { Entry<String, Long> entry = it.next(); ZipEntry zipEntry = newZip.getEntry(entry.getKey()); InputStream is = newZip.getInputStream(zipEntry); zos.putNextEntry(zipEntry); copyInputStream(is, zos); zos.closeEntry(); is.close(); } zos.flush(); zos.close(); } oldZip.close(); newZip.close(); if (map.isEmpty()) { return false; } else { return true; } }
/** * Reads a block of bytes from the current zip entry. * * @return the number of bytes read (may be smaller, even before EOF), or -1 on EOF. * @exception IOException if a i/o error occured. * @exception ZipException if the deflated stream is corrupted. */ public int read(byte[] b, int off, int len) throws IOException { if (len == 0) return 0; if (crc == null) throw new IOException("Stream closed."); if (entry == null) return -1; boolean finished = false; switch (method) { case ZipOutputStream.DEFLATED: len = super.read(b, off, len); if (len < 0) { if (!inf.finished()) throw new ZipException("Inflater not finished!?"); avail = inf.getRemaining(); if ((flags & 8) != 0) readDataDescr(); if (inf.getTotalIn() != csize || inf.getTotalOut() != size) throw new ZipException( "size mismatch: " + csize + ";" + size + " <-> " + inf.getTotalIn() + ";" + inf.getTotalOut()); inf.reset(); finished = true; } break; case ZipOutputStream.STORED: if (len > csize && csize >= 0) len = csize; len = readBuf(b, off, len); if (len > 0) { csize -= len; size -= len; } if (csize == 0) finished = true; else if (len < 0) throw new ZipException("EOF in stored block"); break; } if (len > 0) crc.update(b, off, len); if (finished) { if ((crc.getValue() & 0xffffffffL) != entry.getCrc()) throw new ZipException("CRC mismatch"); crc.reset(); entry = null; entryAtEOF = true; } return len; }
private int extractZip(String zip_path) { ZipInputStream zip = null; try { zip = new ZipInputStream(new BufferedInputStream(new FileInputStream(zip_path))); } catch (java.io.FileNotFoundException e) { sendMessage(-2, 0, "Failed to read from zip file: " + e.toString()); return -1; } ; int num_file = 0; while (true) { num_file++; ZipEntry entry = null; try { entry = zip.getNextEntry(); } catch (java.io.IOException e) { sendMessage(-2, 0, "Failed to get entry from zip file: " + e.toString()); return -1; } if (entry == null) break; String path = extract_dir + "/" + entry.getName(); if (entry.isDirectory()) { try { (new File(path)).mkdirs(); } catch (SecurityException e) { sendMessage(-2, 0, "Failed to create directory: " + e.toString()); return -1; } continue; } try { (new File(path.substring(0, path.lastIndexOf("/")))).mkdirs(); } catch (SecurityException e) { sendMessage(-2, 0, "Failed to create directory: " + e.toString()); return -1; } ; if (extractZipEntry(path, zip, (int) entry.getSize(), "Extracting archives: " + num_file) != 0) return -1; try { CheckedInputStream check = new CheckedInputStream(new FileInputStream(path), new CRC32()); while (check.read(buf) > 0) {} ; check.close(); if (check.getChecksum().getValue() != entry.getCrc()) { File ff = new File(path); ff.delete(); throw new Exception(); } } catch (Exception e) { sendMessage(-2, 0, "CRC check failed"); return -1; } } return 0; }
public long getSlowChecksum() { return entry.getCrc(); }
public boolean DownloadDataFile(final String DataDownloadUrl, final String DownloadFlagFileName) { String[] downloadUrls = DataDownloadUrl.split("[|]"); if (downloadUrls.length < 2) return false; Resources res = Parent.getResources(); String path = getOutFilePath(DownloadFlagFileName); InputStream checkFile = null; try { checkFile = new FileInputStream(path); } catch (FileNotFoundException e) { } catch (SecurityException e) { } ; if (checkFile != null) { try { byte b[] = new byte[Globals.DataDownloadUrl.getBytes("UTF-8").length + 1]; int readed = checkFile.read(b); String compare = new String(b, 0, readed, "UTF-8"); boolean matched = false; // System.out.println("Read URL: '" + compare + "'"); for (int i = 1; i < downloadUrls.length; i++) { // System.out.println("Comparing: '" + downloadUrls[i] + "'"); if (compare.compareTo(downloadUrls[i]) == 0) matched = true; } // System.out.println("Matched: " + String.valueOf(matched)); if (!matched) throw new IOException(); Status.setText(res.getString(R.string.download_unneeded)); return true; } catch (IOException e) { } ; } checkFile = null; // Create output directory (not necessary for phone storage) // System.out.println("Downloading data to: '" + outFilesDir + "'"); try { (new File(outFilesDir)).mkdirs(); OutputStream out = new FileOutputStream(getOutFilePath(".nomedia")); out.flush(); out.close(); } catch (SecurityException e) { } catch (FileNotFoundException e) { } catch (IOException e) { } ; HttpResponse response = null; HttpGet request; long totalLen = 0; CountingInputStream stream; byte[] buf = new byte[16384]; boolean DoNotUnzip = false; boolean FileInAssets = false; String url = ""; int downloadUrlIndex = 1; while (downloadUrlIndex < downloadUrls.length) { System.out.println("Processing download " + downloadUrls[downloadUrlIndex]); url = new String(downloadUrls[downloadUrlIndex]); DoNotUnzip = false; if (url.indexOf(":") == 0) { url = url.substring(url.indexOf(":", 1) + 1); DoNotUnzip = true; } Status.setText(res.getString(R.string.connecting_to, url)); if (url.indexOf("http://") == -1 && url.indexOf("https://") == -1) // File inside assets { System.out.println("Fetching file from assets: " + url); FileInAssets = true; break; } else { System.out.println("Connecting to: " + url); request = new HttpGet(url); request.addHeader("Accept", "*/*"); try { DefaultHttpClient client = HttpWithDisabledSslCertCheck(); client.getParams().setBooleanParameter("http.protocol.handle-redirects", true); response = client.execute(request); } catch (IOException e) { System.out.println("Failed to connect to " + url); downloadUrlIndex++; } ; if (response != null) { if (response.getStatusLine().getStatusCode() != 200) { response = null; System.out.println("Failed to connect to " + url); downloadUrlIndex++; } else break; } } } if (FileInAssets) { System.out.println("Unpacking from assets: '" + url + "'"); try { // System.out.println("Unpacking from assets: '" + url + "' 1"); stream = new CountingInputStream(Parent.getAssets().open(url), 8192); // System.out.println("Unpacking from assets: '" + url + "' 2"); while (stream.skip(65536) > 0) {} ; // System.out.println("Unpacking from assets: '" + url + "' 3"); totalLen = stream.getBytesRead(); // System.out.println("Unpacking from assets: '" + url + "' 4 totalLen = " + // String.valueOf(totalLen)); stream.close(); // System.out.println("Unpacking from assets: '" + url + "' 5"); stream = new CountingInputStream(Parent.getAssets().open(url), 8192); // System.out.println("Unpacking from assets: '" + url + "' 6"); } catch (IOException e) { System.out.println("Unpacking from assets '" + url + "' - error: " + e.toString()); Status.setText(res.getString(R.string.error_dl_from, url)); return false; } } else { if (response == null) { // System.out.println("Error connecting to " + url); Status.setText(res.getString(R.string.failed_connecting_to, url)); return false; } Status.setText(res.getString(R.string.dl_from, url)); totalLen = response.getEntity().getContentLength(); try { stream = new CountingInputStream(response.getEntity().getContent(), 8192); } catch (java.io.IOException e) { Status.setText(res.getString(R.string.error_dl_from, url)); return false; } } if (DoNotUnzip) { path = getOutFilePath( downloadUrls[downloadUrlIndex].substring( 1, downloadUrls[downloadUrlIndex].indexOf(":", 1))); // System.out.println("Saving file '" + path + "'"); OutputStream out = null; try { try { (new File(path.substring(0, path.lastIndexOf("/")))).mkdirs(); } catch (SecurityException e) { } ; out = new FileOutputStream(path); } catch (FileNotFoundException e) { System.out.println( "Saving file '" + path + "' - error creating output file: " + e.toString()); } catch (SecurityException e) { System.out.println( "Saving file '" + path + "' - error creating output file: " + e.toString()); } ; if (out == null) { Status.setText(res.getString(R.string.error_write, path)); System.out.println("Saving file '" + path + "' - error creating output file"); return false; } try { int len = stream.read(buf); while (len >= 0) { if (len > 0) out.write(buf, 0, len); len = stream.read(buf); float percent = 0.0f; if (totalLen > 0) percent = stream.getBytesRead() * 100.0f / totalLen; Status.setText(res.getString(R.string.dl_progress, percent, path)); } out.flush(); out.close(); out = null; } catch (java.io.IOException e) { Status.setText(res.getString(R.string.error_write, path)); System.out.println("Saving file '" + path + "' - error writing: " + e.toString()); return false; } // System.out.println("Saving file '" + path + "' done"); } else { // System.out.println("Reading from zip file aa'" + url + "'"); ZipInputStream zip = new ZipInputStream(stream); while (true) { ZipEntry entry = null; try { entry = zip.getNextEntry(); if (entry != null) System.out.println( "Reading from zip file '" + url + "' entry '" + entry.getName() + "'"); } catch (java.io.IOException e) { Status.setText(res.getString(R.string.error_dl_from, url)); System.out.println("Error reading from zip file '" + url + "': " + e.toString()); return false; } if (entry == null) { System.out.println("Reading from zip file '" + url + "' finished"); break; } if (entry.isDirectory()) { System.out.println("Creating dir '" + getOutFilePath(entry.getName()) + "'"); try { (new File(getOutFilePath(entry.getName()))).mkdirs(); } catch (SecurityException e) { } ; continue; } OutputStream out = null; path = getOutFilePath(entry.getName()); // System.out.println("Saving file a '" + path + "'"); try { (new File(path.substring(0, path.lastIndexOf("/")))).mkdirs(); } catch (SecurityException e) { } ; try { CheckedInputStream check = new CheckedInputStream(new FileInputStream(path), new CRC32()); while (check.read(buf, 0, buf.length) > 0) {} ; check.close(); if (check.getChecksum().getValue() != entry.getCrc()) { File ff = new File(path); ff.delete(); throw new Exception(); } // System.out.println("File '" + path + "' exists and passed CRC check - not // overwriting it"); continue; } catch (Exception e) { } try { out = new FileOutputStream(path); } catch (FileNotFoundException e) { System.out.println("Saving file '" + path + "' - cannot create file: " + e.toString()); } catch (SecurityException e) { System.out.println("Saving file '" + path + "' - cannot create file: " + e.toString()); } ; if (out == null) { Status.setText(res.getString(R.string.error_write, path)); System.out.println("Saving file '" + path + "' - cannot create file"); return false; } float percent = 0.0f; if (totalLen > 0) percent = stream.getBytesRead() * 100.0f / totalLen; Status.setText(res.getString(R.string.dl_progress, percent, path)); try { int len = zip.read(buf); while (len >= 0) { if (len > 0) out.write(buf, 0, len); len = zip.read(buf); percent = 0.0f; if (totalLen > 0) percent = stream.getBytesRead() * 100.0f / totalLen; Status.setText(res.getString(R.string.dl_progress, percent, path)); } out.flush(); out.close(); out = null; } catch (java.io.IOException e) { Status.setText(res.getString(R.string.error_write, path)); System.out.println( "Saving file '" + path + "' - error writing or downloading: " + e.toString()); return false; } try { CheckedInputStream check = new CheckedInputStream(new FileInputStream(path), new CRC32()); while (check.read(buf, 0, buf.length) > 0) {} ; check.close(); if (check.getChecksum().getValue() != entry.getCrc()) { File ff = new File(path); ff.delete(); throw new Exception(); } } catch (Exception e) { Status.setText(res.getString(R.string.error_write, path)); System.out.println("Saving file '" + path + "' - CRC check failed"); return false; } System.out.println("Saving file '" + path + "' done"); } } ; OutputStream out = null; path = getOutFilePath(DownloadFlagFileName); try { out = new FileOutputStream(path); out.write(downloadUrls[downloadUrlIndex].getBytes("UTF-8")); out.flush(); out.close(); } catch (FileNotFoundException e) { } catch (SecurityException e) { } catch (java.io.IOException e) { Status.setText(res.getString(R.string.error_write, path)); return false; } ; Status.setText(res.getString(R.string.dl_finished)); try { stream.close(); } catch (java.io.IOException e) { } ; return true; };
private boolean InstallGame(File romZipFile) { NodeList gameList = docGameXML.getElementsByTagName("game"); Element elmIterGame = null; Element elmRomFile, elmFileset; Map<Long, Long> colZipEntries = new HashMap<Long, Long>(15); Map<Object, Object> FilesetEntries = new HashMap<Object, Object>(15); Enumeration<? extends ZipEntry> eze; ZipFile zfGame = null; ZipEntry ze; NodeList filesetList, romList; Element elmROM; File romFile, gamePath; String sROMFileName; long lROMFileSize, lROMCRC; InputStream in = null; FileOutputStream fout = null; boolean bFound = false, bSuccess = true; boolean bFileFound; bReinstalledGame = false; try { zfGame = new ZipFile(romZipFile); /* if ((zfGame.size() > 40) || (zfGame.size() <= 0)) { JOptionPane.showMessageDialog(parentFrame, "The game (" + romZipFile.getName() + ") file is invalid. A game zip file can contain at most 40 " + "rom files.", "Invalid Game File", JOptionPane.WARNING_MESSAGE); return false; // finally block is guaranteedly executed even if we do return. } */ eze = zfGame.entries(); while (eze.hasMoreElements()) { ze = eze.nextElement(); if (!ze.isDirectory()) { if (!ze.getName().contains("/")) { lROMFileSize = ze.getSize(); lROMCRC = ze.getCrc(); if (lROMFileSize == -1) { JOptionPane.showMessageDialog( parentFrame, "The game (" + romZipFile.getName() + ") file is invalid.", "Invalid Game File", JOptionPane.WARNING_MESSAGE); return false; // finally block is guaranteedly executed even if we do return. } else if (lROMCRC == -1) { JOptionPane.showMessageDialog( parentFrame, "(" + romZipFile.getName() + ") contains invalid files (no CRC)", "Invalid Game File", JOptionPane.WARNING_MESSAGE); return false; // finally block is guaranteedly executed even if we do return. } colZipEntries.put(Long.valueOf(lROMCRC), Long.valueOf(lROMFileSize)); } } } // return false; for (int gameIndex = 0; gameIndex < gameList.getLength(); gameIndex++) { elmIterGame = (Element) gameList.item(gameIndex); filesetList = elmIterGame.getElementsByTagName("fileset"); // TODO: Make a map of matching file names, if any mismatch occurs // reset this map and start over FilesetEntries.clear(); for (int filesetIndex = 0; filesetIndex < filesetList.getLength(); filesetIndex++) { elmFileset = (Element) filesetList.item(filesetIndex); romList = elmFileset.getElementsByTagName("rom"); for (int romIndex = 0; romIndex < romList.getLength(); romIndex++) { // TODO: Check if each file in the roms list has a match in the zip file elmRomFile = (Element) romList.item(romIndex); eze = zfGame.entries(); bFileFound = false; while (eze.hasMoreElements()) { // according to rom tag order ze = eze.nextElement(); if (!ze.isDirectory()) { // Check if this file matches the current rom file // on size and CRC if (Long.valueOf(elmRomFile.getAttribute("crc").toString(), 16).longValue() == ze.getCrc()) { FilesetEntries.put(elmRomFile, ze); bFileFound = true; break; } } } if (!bFileFound) break; } // TODO: Check if all files match, if yes create the folder if // does not exist and extract the files according to // the map to the game folder by corresponding names if (FilesetEntries.size() == romList.getLength()) { byte[] buf = new byte[1024]; // Found a complete match of all files in the fileset gamePath = new File(romsFolder, elmIterGame.getAttribute("id")); gamePath.mkdir(); // Extract all the files in the zip file to the game folder for (Entry<Object, Object> entry : FilesetEntries.entrySet()) { // Extract the file ze = zfGame.getEntry(entry.getValue().toString()); elmRomFile = (Element) entry.getKey(); File newFile = new File(gamePath, elmRomFile.getAttribute("file")); InputStream fin = zfGame.getInputStream(ze); int n; fout = new FileOutputStream(newFile); while ((n = fin.read(buf, 0, 1024)) > -1) fout.write(buf, 0, n); fout.close(); } // TODO: Check if all appropriate number of files are present // in the game folder, if yes add this to the installed games list installedGameName = elmIterGame.getAttribute("name"); installedGameId = elmIterGame.getAttribute("id"); if (gamePath.listFiles().length != romList.getLength()) { bSuccess = false; if (elmFileset.getAttribute("primary").equalsIgnoreCase("true")) { // If no, and current fileset is primary, issue a message saying // more files are needed JOptionPane.showMessageDialog( this, "Not all files required by " + installedGameName + " were installed. Please install rest of the files to play " + installedGameName, "Game Installation Unsuccessful", JOptionPane.WARNING_MESSAGE); } else { // else if current fileset is not primary // issue a message saying parent game files required JOptionPane.showMessageDialog( this, "Not all files required by " + installedGameName + " were installed. Please install rest of the files to play " + installedGameName, "Game Installation Unsuccessful", JOptionPane.WARNING_MESSAGE); } } else { // Game is successfully installed bSuccess = true; installedGameIndex = gameIndex + 1; // Taking into account "Top Filler" } bFound = true; break; } if (bFound) break; } if (bFound) break; } } catch (ZipException zex) { /* ------------------------------------------------------------------------------------ * ZipException is a subclass of IOException that indicates the data in the zip file * doesn't fit the zip format. In this case, the zip exception's message will contain * more details, like "invalid END header signature" or "cannot have more than one drive." * While these may be useful to a zip expert, in general they indicate that the file is * corrupted, and there's not much that can be done about it. * ------------------------------------------------------------------------------------ */ System.err.println("InstallGame()\t" + zex.getMessage()); bSuccess = false; JOptionPane.showMessageDialog( this, "The game zip file (" + romZipFile.getName() + ")" + ", you are attempting to install, is corrupt. The game cannot be installed.", "Corrupt Zip File", JOptionPane.ERROR_MESSAGE); } catch (IOException e) { System.err.println("InstallGame()\t" + e.getMessage()); bSuccess = false; } finally { if (in != null) { try { in.close(); } catch (IOException ioex) { System.err.println(ioex.getMessage()); } } if (fout != null) { try { fout.close(); } catch (IOException ioex) { System.err.println(ioex.getMessage()); } } if (zfGame != null) { try { zfGame.close(); } catch (IOException ioex) { System.err.println(ioex.getMessage()); } } } if (!bFound) { JOptionPane.showMessageDialog( this, "The game (" + romZipFile.getName() + ") you are " + "trying to install does not match any known game " + "names.\nThis game cannot be installed.", "Invalid Game File", JOptionPane.ERROR_MESSAGE); return false; } /* else if (gamePath.isDirectory()) { bReinstalledGame = true; if (JOptionPane.showConfirmDialog(this, "The game " + installedGameId + " is already installed.\n" + "Do you want to reinstall " + installedGameId + "?", "Game Already Installed", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.NO_OPTION) return false; } */ if (bSuccess) { installedGameName = elmIterGame.getAttribute("name"); JOptionPane.showMessageDialog( this, installedGameName + " has been " + "successfully installed.\nYou can now load and play " + installedGameName + ".", "Game Installation Successful", JOptionPane.INFORMATION_MESSAGE); return true; } else return false; }
/** Updates an existing jar file. */ boolean update(InputStream in, OutputStream out, InputStream newManifest, JarIndex jarIndex) throws IOException { ZipInputStream zis = new ZipInputStream(in); ZipOutputStream zos = new JarOutputStream(out); ZipEntry e = null; boolean foundManifest = false; boolean updateOk = true; if (jarIndex != null) { addIndex(jarIndex, zos); } // put the old entries first, replace if necessary while ((e = zis.getNextEntry()) != null) { String name = e.getName(); boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME); if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME)) || (Mflag && isManifestEntry)) { continue; } else if (isManifestEntry && ((newManifest != null) || (ename != null) || (pname != null))) { foundManifest = true; if (newManifest != null) { // Don't read from the newManifest InputStream, as we // might need it below, and we can't re-read the same data // twice. FileInputStream fis = new FileInputStream(mname); boolean ambiguous = isAmbiguousMainClass(new Manifest(fis)); fis.close(); if (ambiguous) { return false; } } // Update the manifest. Manifest old = new Manifest(zis); if (newManifest != null) { old.read(newManifest); } if (!updateManifest(old, zos)) { return false; } } else { if (!entryMap.containsKey(name)) { // copy the old stuff // do our own compression ZipEntry e2 = new ZipEntry(name); e2.setMethod(e.getMethod()); e2.setTime(e.getTime()); e2.setComment(e.getComment()); e2.setExtra(e.getExtra()); if (e.getMethod() == ZipEntry.STORED) { e2.setSize(e.getSize()); e2.setCrc(e.getCrc()); } zos.putNextEntry(e2); copy(zis, zos); } else { // replace with the new files File f = entryMap.get(name); addFile(zos, f); entryMap.remove(name); entries.remove(f); } } } // add the remaining new files for (File f : entries) { addFile(zos, f); } if (!foundManifest) { if (newManifest != null) { Manifest m = new Manifest(newManifest); updateOk = !isAmbiguousMainClass(m); if (updateOk) { if (!updateManifest(m, zos)) { updateOk = false; } } } else if (ename != null || pname != null) { if (!updateManifest(new Manifest(), zos)) { updateOk = false; } } } zis.close(); zos.close(); return updateOk; }