Include PySFX
parent
202cc6bcd0
commit
dc6f1536a3
@ -0,0 +1,48 @@
|
||||
import base64, sys, math
|
||||
|
||||
class Base64Reader(object):
|
||||
def __init__(self, source):
|
||||
self.source = source
|
||||
self.buff = ""
|
||||
self.done = False
|
||||
|
||||
def read(self, size = -1):
|
||||
if size < 0:
|
||||
return base64.b64encode(self.source.read())
|
||||
else:
|
||||
if self.done == False:
|
||||
if len(self.buff) < size:
|
||||
actual_size = int(math.ceil(size / 3) * 3)
|
||||
data = self.source.read(actual_size)
|
||||
|
||||
if data == "":
|
||||
self.done = True
|
||||
return self.buff
|
||||
|
||||
# TODO: Investigate whether the possibility exists that we get the wrong amount
|
||||
# of bytes from the source read.
|
||||
self.buff += base64.b64encode(data)
|
||||
|
||||
if len(self.buff) > size:
|
||||
returndata = self.buff[:size]
|
||||
self.buff = self.buff[size:]
|
||||
else:
|
||||
returndata = self.buff
|
||||
self.buff = ""
|
||||
|
||||
return returndata
|
||||
else:
|
||||
returndata = self.buff[:size]
|
||||
self.buff = self.buff[size:]
|
||||
return returndata
|
||||
else:
|
||||
return ""
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
def write(self, data):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
self.source.close()
|
@ -0,0 +1,47 @@
|
||||
import zlib, sys
|
||||
|
||||
class GzipReader(object):
|
||||
source = None
|
||||
cobj = None
|
||||
done = False
|
||||
buff = ""
|
||||
|
||||
def __init__(self, source):
|
||||
self.source = source
|
||||
self.cobj = zlib.compressobj()
|
||||
|
||||
def read(self, size = -1):
|
||||
if self.done == False:
|
||||
if size < 0:
|
||||
data = self.source.read()
|
||||
return self.cobj.compress(data) + self.cobj.flush(zlib.Z_FINISH)
|
||||
else:
|
||||
# Keep reading and compressing until we have something to return.
|
||||
while len(self.buff) < size:
|
||||
data = self.source.read(size)
|
||||
|
||||
if data == "":
|
||||
# Process the last data left in the compressor buffer.
|
||||
self.buff += self.cobj.flush(zlib.Z_FINISH)
|
||||
|
||||
# Mark as done to prevent calling flush(zlib.Z_FINISH) twice.
|
||||
self.done = True
|
||||
|
||||
return self.buff
|
||||
|
||||
self.buff += self.cobj.compress(data)
|
||||
|
||||
returndata = self.buff[:size]
|
||||
self.buff = self.buff[size:]
|
||||
return returndata
|
||||
else:
|
||||
return ""
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
def write(self, data):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
self.source.close()
|
@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import zlib, base64, sys, argparse, os
|
||||
from gzipreader import GzipReader
|
||||
from b64reader import Base64Reader
|
||||
|
||||
parser = argparse.ArgumentParser(description="Creates an SFX from a specified archive or file.")
|
||||
parser.add_argument("-a", help="Treat the input file as a tar.gz archive that needs to be extracted upon running the SFX.", action="store_true", dest="is_archive")
|
||||
parser.add_argument("-s", help="Define a command to be run after extraction of the SFX. %%NAME will be replaced with the path of the extracted file or folder. "
|
||||
"For archives, the working directory is set to the extraction directory.", action="store", dest="command")
|
||||
parser.add_argument("input_file", metavar="INPUTFILE", type=str, nargs=1, help="The file to read from. Use a dash (-) to read from STDIN instead.")
|
||||
parser.add_argument("output_file", metavar="OUTPUTFILE", type=str, nargs=1, help="The file to write to. Use a dash (-) to write to STDOUT instead.")
|
||||
options = vars(parser.parse_args())
|
||||
|
||||
if options['input_file'][0] == "-":
|
||||
infile = sys.stdin
|
||||
extension = "dat"
|
||||
else:
|
||||
infile = open(options['input_file'][0], "rb")
|
||||
extension = os.path.splitext(options['input_file'][0])
|
||||
|
||||
if options['output_file'][0] == "-":
|
||||
outfile = sys.stdout
|
||||
else:
|
||||
outfile = open(options['output_file'][0], "wb")
|
||||
|
||||
if options['is_archive'] == True:
|
||||
is_archive = "True"
|
||||
extension = "tar.gz"
|
||||
else:
|
||||
is_archive = "False"
|
||||
|
||||
if options['command']:
|
||||
run_after_extract = "True"
|
||||
command = options['command']
|
||||
else:
|
||||
run_after_extract = "False"
|
||||
command = ""
|
||||
|
||||
template = open("%s/unpack.template" % os.path.dirname(__file__), "r")
|
||||
|
||||
variables = {
|
||||
"run_after_extract": run_after_extract,
|
||||
"targz": is_archive,
|
||||
"extension": extension,
|
||||
"command": command
|
||||
}
|
||||
|
||||
for curline in template:
|
||||
if curline.startswith('"""EOFDATA'):
|
||||
# Found the EOF data marker, insert packed data before
|
||||
# moving on with the next line.
|
||||
outfile.write(curline)
|
||||
|
||||
data = b""
|
||||
reader = Base64Reader(GzipReader(infile))
|
||||
chunk_size = 128
|
||||
|
||||
while True:
|
||||
chunk = reader.read(chunk_size)
|
||||
|
||||
if chunk == "":
|
||||
break
|
||||
|
||||
outfile.write(chunk + "\n")
|
||||
else:
|
||||
if "{%" in curline:
|
||||
for variable_key, variable_value in variables.iteritems():
|
||||
curline = curline.replace("{%%%s}" % variable_key, variable_value)
|
||||
|
||||
outfile.write(curline)
|
||||
|
||||
outfile.close()
|
@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import zlib, base64, sys, os, random, shlex, subprocess
|
||||
|
||||
run_after_extract = {%run_after_extract}
|
||||
targz = {%targz}
|
||||
extension = "{%extension}"
|
||||
command = "{%command}"
|
||||
|
||||
try:
|
||||
if sys.argv[1] != "-q":
|
||||
quiet = True
|
||||
else:
|
||||
quiet = False
|
||||
except IndexError:
|
||||
quiet = False
|
||||
|
||||
if quiet == False:
|
||||
sys.stdout.write("PySFX 1.0 by Sven Slootweg http://cryto.net/pysfx\n")
|
||||
sys.stdout.write("PySFX may be reused, modified, and redistributed freely without restriction under the WTFPL.\n\n")
|
||||
|
||||
identifier = "pysfx-%s" % "".join(["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[random.randint(0, 61)] for i in xrange(0, 16)])
|
||||
directory_destination = "/var/tmp/%s" % identifier
|
||||
file_destination = "/var/tmp/%s.%s" % (identifier, extension)
|
||||
|
||||
if targz == True:
|
||||
name = "/var/tmp/%s"
|
||||
else:
|
||||
name = "/var/tmp/%s.%s" % (identifier, extension)
|
||||
|
||||
reader = open(__file__, "rb")
|
||||
reading_data = False
|
||||
|
||||
writer = open(file_destination, "wb")
|
||||
|
||||
dobj = zlib.decompressobj()
|
||||
|
||||
total_bytes = 0
|
||||
original_bytes = 0
|
||||
|
||||
for line in reader:
|
||||
if line.startswith('"""'):
|
||||
reading_data = False
|
||||
|
||||
if reading_data == True:
|
||||
data = dobj.decompress(base64.b64decode(line.rstrip("\r\n")))
|
||||
writer.write(data)
|
||||
total_bytes += (len(line) - 1)
|
||||
original_bytes += len(data)
|
||||
|
||||
if line.startswith('"""EOFDATA'):
|
||||
reading_data = True
|
||||
|
||||
writer.write(dobj.flush())
|
||||
writer.close()
|
||||
|
||||
reader.close()
|
||||
|
||||
if quiet == False:
|
||||
sys.stdout.write("Processed %d bytes, of which %d bytes were written to %s.\n" % (total_bytes, original_bytes, file_destination))
|
||||
|
||||
if targz == True:
|
||||
stfu = open(os.devnull, 'w')
|
||||
|
||||
if quiet == False:
|
||||
sys.stdout.write("Unpacking archive...\n")
|
||||
|
||||
os.makedirs(directory_destination)
|
||||
|
||||
result = subprocess.call(["tar", "-xzf", file_destination, "-C", directory_destination], stdout=stfu, stderr=stfu)
|
||||
|
||||
if result != 0:
|
||||
sys.stderr.write("Extraction of inner archive failed. The file may be corrupted.\n")
|
||||
exit(1)
|
||||
|
||||
if run_after_extract == True:
|
||||
tokens = shlex.split(command)
|
||||
result = subprocess.call(tokens, cwd=directory_destination)
|
||||
|
||||
if result != 0:
|
||||
sys.stderr.write("Autorun command failed. The file may be corrupted.\n")
|
||||
exit(1)
|
||||
|
||||
"""EOFDATA
|
||||
"""
|
Loading…
Reference in New Issue