From 1a824b3ed577ad99a3c4b6671e3e871079633d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8D=E3=82=83=E3=82=8C=E3=81=84?= Date: Wed, 16 Aug 2017 03:10:31 +0000 Subject: =?UTF-8?q?Fix=20for=20Windows=20=E2=80=93=20replace=20backslashes?= =?UTF-8?q?=20with=20forward=20slashes=20before=20saving=20as=20entry?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- repack.py | 257 +++++++++++++++++++++++++++++++------------------------------- 1 file changed, 129 insertions(+), 128 deletions(-) diff --git a/repack.py b/repack.py index c566a59..2b37bba 100644 --- a/repack.py +++ b/repack.py @@ -1,128 +1,129 @@ -#!/usr/bin/env python3 - -import argparse -import io -import pathlib -import re -import zlib - -# The MIT License (MIT) -# Copyright (c) 2016 kyarei -# -# Permission is hereby granted, free of charge, to any person obtaining a copy of -# this software and associated documentation files (the "Software"), to deal in -# the Software without restriction, including without limitation the rights to -# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -# of the Software, and to permit persons to whom the Software is furnished to do -# so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -# Usage: python3 repack.py - -# Parse the arguments - -parser = argparse.ArgumentParser(description='Repack Wizard101 WAD files.') -parser.add_argument('sourcePath', type=str, - help='the root directory of the files to be archived') -parser.add_argument('archivePath', type=str, - help='the path of the archive file to be made') -parser.add_argument('blacklist', type=str, nargs='?', default='', - help='a file containing patterns to avoid compressing') -parser.add_argument('--verbose', '-v', type=bool, - help='if enabled, use diagnostics') - -args = parser.parse_args() - -# Get all files in the directory specified - -root = pathlib.Path(args.sourcePath) -files = root.glob("**/*"); -blacklist = set() -if args.blacklist != '': - blacklistPatterns = re.split('\s', open(args.blacklist).read(-1)) - for p in blacklistPatterns: - if p != '': - blacklist.update(set(root.glob(p))) -entries = [] -offset = 14 # Precalculate offset of data section in loop below - -# Make entries of all files - -for f in files: - if f.is_file(): - with f.open(mode="rb") as h: - contents = h.read(-1) - isCompressed = not f in blacklist - zSize = 0xFFFFFFFF - uSize = len(contents) - if isCompressed: - compressedContents = zlib.compress(contents) - zSize = len(compressedContents) - isCompressed = zSize < uSize - name = str(f.relative_to(root)) - crc = zlib.crc32(contents) - entry = { - "contents": compressedContents if isCompressed else contents, - "uSize": uSize, - "zSize": zSize, - "name": name, - "isCompressed": isCompressed, - "crc": crc - } - entries.append(entry) - offset += 22 + len(name) - if args.verbose: - print("> File %s acknowledged" % name) - -if args.verbose: - print("%d files acknowledged" % len(entries)) - -# Open the output file - -out = open(args.archivePath, "wb"); - -def writeByte(stream, val): - stream.write(bytes([val])) -def writeInt(stream, val): - stream.write(val.to_bytes(4, byteorder="little")) - -if args.verbose: - print("Opened output file; writing data...") - -# Write magic string -out.write(b"KIWAD") -# Write version -writeInt(out, 2) -# Write number of files -writeInt(out, len(entries)) -# Write dummy byte -writeByte(out, 1) -# Write file ENTRIES -for e in entries: - netSize = e["zSize"] if e["isCompressed"] else e["uSize"] - writeInt(out, offset) # Offset - writeInt(out, e["uSize"]) - writeInt(out, e["zSize"]) - writeByte(out, e["isCompressed"]) - writeInt(out, e["crc"]) - writeInt(out, len(e["name"].encode()) + 1) # includes terminating null - out.write(e["name"].encode()) - writeByte(out, 0) - offset += netSize - if args.verbose: - print("> Wrote ENTRY for %s" % e["name"]) -# Write file DATA -for e in entries: - out.write(e["contents"]) - if args.verbose: - print("> Wrote DATA for %s" % e["name"]) +#!/usr/bin/env python3 + +import argparse +import io +import pathlib +import re +import zlib + +# The MIT License (MIT) +# Copyright (c) 2016 kyarei +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is furnished to do +# so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Usage: python3 repack.py + +# Parse the arguments + +parser = argparse.ArgumentParser(description='Repack Wizard101 WAD files.') +parser.add_argument('sourcePath', type=str, + help='the root directory of the files to be archived') +parser.add_argument('archivePath', type=str, + help='the path of the archive file to be made') +parser.add_argument('blacklist', type=str, nargs='?', default='', + help='a file containing patterns to avoid compressing') +parser.add_argument('--verbose', '-v', type=bool, + help='if enabled, use diagnostics') + +args = parser.parse_args() + +# Get all files in the directory specified + +root = pathlib.Path(args.sourcePath) +files = root.glob("**/*"); +blacklist = set() +if args.blacklist != '': + blacklistPatterns = re.split('\s', open(args.blacklist).read(-1)) + for p in blacklistPatterns: + if p != '': + blacklist.update(set(root.glob(p))) +entries = [] +offset = 14 # Precalculate offset of data section in loop below + +# Make entries of all files + +for f in files: + if f.is_file(): + with f.open(mode="rb") as h: + contents = h.read(-1) + isCompressed = not f in blacklist + zSize = 0xFFFFFFFF + uSize = len(contents) + if isCompressed: + compressedContents = zlib.compress(contents) + zSize = len(compressedContents) + isCompressed = zSize < uSize + name = str(f.relative_to(root)) + name = name.replace("\\", "/") + crc = zlib.crc32(contents) + entry = { + "contents": compressedContents if isCompressed else contents, + "uSize": uSize, + "zSize": zSize, + "name": name, + "isCompressed": isCompressed, + "crc": crc + } + entries.append(entry) + offset += 22 + len(name) + if args.verbose: + print("> File %s acknowledged" % name) + +if args.verbose: + print("%d files acknowledged" % len(entries)) + +# Open the output file + +out = open(args.archivePath, "wb"); + +def writeByte(stream, val): + stream.write(bytes([val])) +def writeInt(stream, val): + stream.write(val.to_bytes(4, byteorder="little")) + +if args.verbose: + print("Opened output file; writing data...") + +# Write magic string +out.write(b"KIWAD") +# Write version +writeInt(out, 2) +# Write number of files +writeInt(out, len(entries)) +# Write dummy byte +writeByte(out, 1) +# Write file ENTRIES +for e in entries: + netSize = e["zSize"] if e["isCompressed"] else e["uSize"] + writeInt(out, offset) # Offset + writeInt(out, e["uSize"]) + writeInt(out, e["zSize"]) + writeByte(out, e["isCompressed"]) + writeInt(out, e["crc"]) + writeInt(out, len(e["name"].encode()) + 1) # includes terminating null + out.write(e["name"].encode()) + writeByte(out, 0) + offset += netSize + if args.verbose: + print("> Wrote ENTRY for %s" % e["name"]) +# Write file DATA +for e in entries: + out.write(e["contents"]) + if args.verbose: + print("> Wrote DATA for %s" % e["name"]) -- cgit v1.2.3