Initial commit

master
Sven Slootweg 11 years ago
commit 726e9a98b4

1
.gitignore vendored

@ -0,0 +1 @@
*.pyc

@ -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()

73
pysfx

@ -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…
Cancel
Save