diff --git a/src/main/java/systems/crigges/jmpq3/JMpqEditor.java b/src/main/java/systems/crigges/jmpq3/JMpqEditor.java index 23f12c3..627720c 100644 --- a/src/main/java/systems/crigges/jmpq3/JMpqEditor.java +++ b/src/main/java/systems/crigges/jmpq3/JMpqEditor.java @@ -490,7 +490,7 @@ public void extractAllFiles(File dest) throws JMpqException { try { int i = 0; for (Block b : blocks) { - if ((b.getFlags() & MpqFile.ENCRYPTED) == MpqFile.ENCRYPTED) { + if (b.hasFlag(MpqFile.ENCRYPTED)) { continue; } ByteBuffer buf = ByteBuffer.allocate(b.getCompressedSize()).order(ByteOrder.LITTLE_ENDIAN); @@ -616,6 +616,45 @@ public MpqFile getMpqFile(String name) throws IOException { return new MpqFile(buffer, b, discBlockSize, name); } + + /** + * Gets the mpq file. + * + * @param block a block + * @return the mpq file + * + * @throws IOException Signals that an I/O exception has occurred. + */ + public MpqFile getMpqFileByBlock(BlockTable.Block block) throws IOException { + if (block.hasFlag(MpqFile.ENCRYPTED)){ + throw new IOException("cant access this block"); + } + ByteBuffer buffer = ByteBuffer.allocate(block.getCompressedSize()).order(ByteOrder.LITTLE_ENDIAN); + fc.position(headerOffset + block.getFilePos()); + readFully(buffer, fc); + buffer.rewind(); + + return new MpqFile(buffer, block, discBlockSize, ""); + } + + /** + * Gets the mpq files. + * + * @return the mpq files + * + * @throws IOException Signals that an I/O exception has occurred. + */ + public List getMpqFilesByBlockTable() throws IOException { + List mpqFiles = new ArrayList<>(); + ArrayList list = blockTable.getAllVaildBlocks(); + for (Block block : list){ + try{ + MpqFile mpqFile = getMpqFileByBlock(block); + mpqFiles.add(mpqFile); + } catch (IOException ignore){} + } + return mpqFiles; + } /** * Deletes the specified file out of the mpq once you rebuild the mpq. @@ -633,27 +672,56 @@ public void deleteFile(String name) { filenameToData.remove(name); } } - + /** * Inserts the specified byte array into the mpq once you close the editor. * - * @param name of the file inside the mpq - * @param input the input byte array - * @throws JMpqException if file is not found or access errors occur + * @param name of the file inside the mpq + * @param input the input byte array + * @param override is override file + * @throws NonWritableChannelException the non writable channel exception + * @throws IllegalArgumentException when the mpq has filename and not override */ - public void insertByteArray(String name, byte[] input) throws NonWritableChannelException, IllegalArgumentException { + public void insertByteArray(String name, byte[] input,boolean override) throws NonWritableChannelException, + IllegalArgumentException { if (!canWrite) { throw new NonWritableChannelException(); } - - if (listFile.containsFile(name)) { + + if ((!override) && listFile.containsFile(name)) { throw new IllegalArgumentException("Archive already contains file with name: " + name); } - + listFile.addFile(name); ByteBuffer data = ByteBuffer.wrap(input); filenameToData.put(name, data); } + + /** + * Inserts the specified byte array into the mpq once you close the editor. + * + * @param name of the file inside the mpq + * @param input the input byte array + * @throws NonWritableChannelException the non writable channel exception + * @throws IllegalArgumentException when the mpq has filename + */ + public void insertByteArray(String name, byte[] input) throws NonWritableChannelException, IllegalArgumentException { + insertByteArray(name,input,false); + } + + /** + * Inserts the specified file into the mpq once you close the editor. + * + * @param name of the file inside the mpq + * @param file the file + * @param backupFile if true the editors creates a copy of the file to add, so + * further changes won't affect the resulting mpq + * @throws IOException the io exception + * @throws IllegalArgumentException the illegal argument exception + */ + public void insertFile(String name, File file, boolean backupFile) throws IOException, IllegalArgumentException { + insertFile(name,file,backupFile,false); + } /** * Inserts the specified file into the mpq once you close the editor. @@ -662,33 +730,34 @@ public void insertByteArray(String name, byte[] input) throws NonWritableChannel * @param file the file * @param backupFile if true the editors creates a copy of the file to add, so * further changes won't affect the resulting mpq + * @param override is override file * @throws JMpqException if file is not found or access errors occur */ - public void insertFile(String name, File file, boolean backupFile) throws IOException, IllegalArgumentException { - if (!canWrite) { + public void insertFile(String name, File file, boolean backupFile, boolean override) throws IOException, + IllegalArgumentException{ + if (!canWrite){ throw new NonWritableChannelException(); } - + log.info("insert file: " + name); - - if (listFile.containsFile(name)) { + + if ((!override) && listFile.containsFile(name)){ throw new IllegalArgumentException("Archive already contains file with name: " + name); } - - - try { + + try{ listFile.addFile(name); - if (backupFile) { + if (backupFile){ File temp = File.createTempFile("jmpq", "backup", JMpqEditor.tempDir); temp.deleteOnExit(); Files.copy(file.toPath(), temp.toPath(), StandardCopyOption.REPLACE_EXISTING); ByteBuffer data = ByteBuffer.wrap(Files.readAllBytes(temp.toPath())); filenameToData.put(name, data); - } else { + } else{ ByteBuffer data = ByteBuffer.wrap(Files.readAllBytes(file.toPath())); filenameToData.put(name, data); } - } catch (IOException e) { + } catch (IOException e){ throw new JMpqException(e); } } @@ -962,13 +1031,22 @@ public boolean isCanWrite() { public void setKeepHeaderOffset(boolean keepHeaderOffset) { this.keepHeaderOffset = keepHeaderOffset; } - - /* + + + /** + * Get block table block table. + * + * @return the block table + */ + public BlockTable getBlockTable(){ + return blockTable; + } + + /** * (non-Javadoc) * * @see java.lang.Object#toString() */ - @Override public String toString() { return "JMpqEditor [headerSize=" + headerSize + ", archiveSize=" + archiveSize + ", formatVersion=" + formatVersion + ", discBlockSize=" + discBlockSize diff --git a/src/test/java/systems/crigges/jmpq3test/MpqTests.java b/src/test/java/systems/crigges/jmpq3test/MpqTests.java index a8dfcf2..8e88e3f 100644 --- a/src/test/java/systems/crigges/jmpq3test/MpqTests.java +++ b/src/test/java/systems/crigges/jmpq3test/MpqTests.java @@ -248,7 +248,8 @@ public void testDuplicatePaths() throws IOException { Assert.expectThrows(IllegalArgumentException.class, () -> { mpqEditor.insertByteArray("teST", "bytesasdadasdad".getBytes()); }); - + //test override + mpqEditor.insertByteArray("teST", "bytesasdadasdad".getBytes(),true); } } } @@ -329,6 +330,17 @@ private void insertAndDelete(File mpq, String filename) throws IOException { mpqEditor.deleteFile(filename); } + try (JMpqEditor mpqEditor = new JMpqEditor(mpq, MPQOpenOption.FORCE_V0)) { + if (!mpqEditor.isCanWrite()) { + return; + } + //test override + mpqEditor.insertFile(filename, getFile(filename), false,true); + mpqEditor.insertFile(filename, getFile(filename), false,true); + + mpqEditor.deleteFile(filename); + } + try (JMpqEditor mpqEditor = new JMpqEditor(mpq, MPQOpenOption.READ_ONLY, MPQOpenOption.FORCE_V0)) { Assert.assertFalse(mpqEditor.hasFile(filename)); } @@ -396,4 +408,27 @@ public void newBlocksizeBufferOverflow() throws IOException { mpqEditor.close(); } + + @Test() + public void testForGetMpqFileByBlock() throws IOException { + File[] mpqs = getMpqs(); + for (File mpq : mpqs) { + if (mpq.getName().equals("invalidHashSize.scx_copy")) { + continue; + } + try (JMpqEditor mpqEditor = new JMpqEditor(mpq, MPQOpenOption.FORCE_V0)) { + + Assert.assertTrue(mpqEditor.getMpqFilesByBlockTable().size()>0); + BlockTable blockTable = mpqEditor.getBlockTable(); + Assert.assertNotNull(blockTable); + for (BlockTable.Block block : blockTable.getAllVaildBlocks()) + { + if (block.hasFlag(MpqFile.ENCRYPTED)){ + continue; + } + Assert.assertNotNull(mpqEditor.getMpqFileByBlock(block)); + } + } + } + } }