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