tools v2.2
This commit is contained in:
27
ePub_Fixer/lib/scrolltextwidget.py
Normal file
27
ePub_Fixer/lib/scrolltextwidget.py
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
|
||||
|
||||
import Tkinter
|
||||
import Tkconstants
|
||||
|
||||
# basic scrolled text widget
|
||||
class ScrolledText(Tkinter.Text):
|
||||
def __init__(self, master=None, **kw):
|
||||
self.frame = Tkinter.Frame(master)
|
||||
self.vbar = Tkinter.Scrollbar(self.frame)
|
||||
self.vbar.pack(side=Tkconstants.RIGHT, fill=Tkconstants.Y)
|
||||
kw.update({'yscrollcommand': self.vbar.set})
|
||||
Tkinter.Text.__init__(self, self.frame, **kw)
|
||||
self.pack(side=Tkconstants.LEFT, fill=Tkconstants.BOTH, expand=True)
|
||||
self.vbar['command'] = self.yview
|
||||
# Copy geometry methods of self.frame without overriding Text
|
||||
# methods = hack!
|
||||
text_meths = vars(Tkinter.Text).keys()
|
||||
methods = vars(Tkinter.Pack).keys() + vars(Tkinter.Grid).keys() + vars(Tkinter.Place).keys()
|
||||
methods = set(methods).difference(text_meths)
|
||||
for m in methods:
|
||||
if m[0] != '_' and m != 'config' and m != 'configure':
|
||||
setattr(self, m, getattr(self.frame, m))
|
||||
|
||||
def __str__(self):
|
||||
return str(self.frame)
|
||||
149
ePub_Fixer/lib/subasyncio.py
Normal file
149
ePub_Fixer/lib/subasyncio.py
Normal file
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
|
||||
|
||||
import os, sys
|
||||
import signal
|
||||
import threading
|
||||
import subprocess
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
|
||||
# **heavily** chopped up and modfied version of asyncproc.py
|
||||
# to make it actually work on Windows as well as Mac/Linux
|
||||
# For the original see:
|
||||
# "http://www.lysator.liu.se/~bellman/download/"
|
||||
# author is "Thomas Bellman <bellman@lysator.liu.se>"
|
||||
# available under GPL version 3 or Later
|
||||
|
||||
# create an asynchronous subprocess whose output can be collected in
|
||||
# a non-blocking manner
|
||||
|
||||
# What a mess! Have to use threads just to get non-blocking io
|
||||
# in a cross-platform manner
|
||||
|
||||
# luckily all thread use is hidden within this class
|
||||
|
||||
class Process(object):
|
||||
def __init__(self, *params, **kwparams):
|
||||
if len(params) <= 3:
|
||||
kwparams.setdefault('stdin', subprocess.PIPE)
|
||||
if len(params) <= 4:
|
||||
kwparams.setdefault('stdout', subprocess.PIPE)
|
||||
if len(params) <= 5:
|
||||
kwparams.setdefault('stderr', subprocess.PIPE)
|
||||
self.__pending_input = []
|
||||
self.__collected_outdata = []
|
||||
self.__collected_errdata = []
|
||||
self.__exitstatus = None
|
||||
self.__lock = threading.Lock()
|
||||
self.__inputsem = threading.Semaphore(0)
|
||||
self.__quit = False
|
||||
|
||||
self.__process = subprocess.Popen(*params, **kwparams)
|
||||
|
||||
if self.__process.stdin:
|
||||
self.__stdin_thread = threading.Thread(
|
||||
name="stdin-thread",
|
||||
target=self.__feeder, args=(self.__pending_input,
|
||||
self.__process.stdin))
|
||||
self.__stdin_thread.setDaemon(True)
|
||||
self.__stdin_thread.start()
|
||||
|
||||
if self.__process.stdout:
|
||||
self.__stdout_thread = threading.Thread(
|
||||
name="stdout-thread",
|
||||
target=self.__reader, args=(self.__collected_outdata,
|
||||
self.__process.stdout))
|
||||
self.__stdout_thread.setDaemon(True)
|
||||
self.__stdout_thread.start()
|
||||
|
||||
if self.__process.stderr:
|
||||
self.__stderr_thread = threading.Thread(
|
||||
name="stderr-thread",
|
||||
target=self.__reader, args=(self.__collected_errdata,
|
||||
self.__process.stderr))
|
||||
self.__stderr_thread.setDaemon(True)
|
||||
self.__stderr_thread.start()
|
||||
|
||||
def pid(self):
|
||||
return self.__process.pid
|
||||
|
||||
def kill(self, signal):
|
||||
self.__process.send_signal(signal)
|
||||
|
||||
# check on subprocess (pass in 'nowait') to act like poll
|
||||
def wait(self, flag):
|
||||
if flag.lower() == 'nowait':
|
||||
rc = self.__process.poll()
|
||||
else:
|
||||
rc = self.__process.wait()
|
||||
if rc != None:
|
||||
if self.__process.stdin:
|
||||
self.closeinput()
|
||||
if self.__process.stdout:
|
||||
self.__stdout_thread.join()
|
||||
if self.__process.stderr:
|
||||
self.__stderr_thread.join()
|
||||
return self.__process.returncode
|
||||
|
||||
def terminate(self):
|
||||
if self.__process.stdin:
|
||||
self.closeinput()
|
||||
self.__process.terminate()
|
||||
|
||||
# thread gets data from subprocess stdout
|
||||
def __reader(self, collector, source):
|
||||
while True:
|
||||
data = os.read(source.fileno(), 65536)
|
||||
self.__lock.acquire()
|
||||
collector.append(data)
|
||||
self.__lock.release()
|
||||
if data == "":
|
||||
source.close()
|
||||
break
|
||||
return
|
||||
|
||||
# thread feeds data to subprocess stdin
|
||||
def __feeder(self, pending, drain):
|
||||
while True:
|
||||
self.__inputsem.acquire()
|
||||
self.__lock.acquire()
|
||||
if not pending and self.__quit:
|
||||
drain.close()
|
||||
self.__lock.release()
|
||||
break
|
||||
data = pending.pop(0)
|
||||
self.__lock.release()
|
||||
drain.write(data)
|
||||
|
||||
# non-blocking read of data from subprocess stdout
|
||||
def read(self):
|
||||
self.__lock.acquire()
|
||||
outdata = "".join(self.__collected_outdata)
|
||||
del self.__collected_outdata[:]
|
||||
self.__lock.release()
|
||||
return outdata
|
||||
|
||||
# non-blocking read of data from subprocess stderr
|
||||
def readerr(self):
|
||||
self.__lock.acquire()
|
||||
errdata = "".join(self.__collected_errdata)
|
||||
del self.__collected_errdata[:]
|
||||
self.__lock.release()
|
||||
return errdata
|
||||
|
||||
# non-blocking write to stdin of subprocess
|
||||
def write(self, data):
|
||||
if self.__process.stdin is None:
|
||||
raise ValueError("Writing to process with stdin not a pipe")
|
||||
self.__lock.acquire()
|
||||
self.__pending_input.append(data)
|
||||
self.__inputsem.release()
|
||||
self.__lock.release()
|
||||
|
||||
# close stdinput of subprocess
|
||||
def closeinput(self):
|
||||
self.__lock.acquire()
|
||||
self.__quit = True
|
||||
self.__inputsem.release()
|
||||
self.__lock.release()
|
||||
|
||||
136
ePub_Fixer/lib/zipfix.py
Normal file
136
ePub_Fixer/lib/zipfix.py
Normal file
@@ -0,0 +1,136 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import zlib
|
||||
import zipfile
|
||||
import os
|
||||
import os.path
|
||||
import getopt
|
||||
from struct import unpack
|
||||
|
||||
|
||||
_FILENAME_LEN_OFFSET = 26
|
||||
_EXTRA_LEN_OFFSET = 28
|
||||
_FILENAME_OFFSET = 30
|
||||
_MAX_SIZE = 64 * 1024
|
||||
|
||||
class fixZip:
|
||||
def __init__(self, zinput, zoutput):
|
||||
self.inzip = zipfile.ZipFile(zinput,'r')
|
||||
self.outzip = zipfile.ZipFile(zoutput,'w')
|
||||
# open the input zip for reading only as a raw file
|
||||
self.bzf = file(zinput,'rb')
|
||||
|
||||
def getlocalname(self, zi):
|
||||
local_header_offset = zi.header_offset
|
||||
self.bzf.seek(local_header_offset + _FILENAME_LEN_OFFSET)
|
||||
leninfo = self.bzf.read(2)
|
||||
local_name_length, = unpack('<H', leninfo)
|
||||
self.bzf.seek(local_header_offset + _FILENAME_OFFSET)
|
||||
local_name = self.bzf.read(local_name_length)
|
||||
return local_name
|
||||
|
||||
def uncompress(self, cmpdata):
|
||||
dc = zlib.decompressobj(-15)
|
||||
data = ''
|
||||
while len(cmpdata) > 0:
|
||||
if len(cmpdata) > _MAX_SIZE :
|
||||
newdata = cmpdata[0:_MAX_SIZE]
|
||||
cmpdata = cmpdata[_MAX_SIZE:]
|
||||
else:
|
||||
newdata = cmpdata
|
||||
cmpdata = ''
|
||||
newdata = dc.decompress(newdata)
|
||||
unprocessed = dc.unconsumed_tail
|
||||
if len(unprocessed) == 0:
|
||||
newdata += dc.flush()
|
||||
data += newdata
|
||||
cmpdata += unprocessed
|
||||
unprocessed = ''
|
||||
return data
|
||||
|
||||
def getfiledata(self, zi):
|
||||
# get file name length and exta data length to find start of file data
|
||||
local_header_offset = zi.header_offset
|
||||
|
||||
self.bzf.seek(local_header_offset + _FILENAME_LEN_OFFSET)
|
||||
leninfo = self.bzf.read(2)
|
||||
local_name_length, = unpack('<H', leninfo)
|
||||
|
||||
self.bzf.seek(local_header_offset + _EXTRA_LEN_OFFSET)
|
||||
exinfo = self.bzf.read(2)
|
||||
extra_field_length, = unpack('<H', exinfo)
|
||||
|
||||
self.bzf.seek(local_header_offset + _FILENAME_OFFSET + local_name_length + extra_field_length)
|
||||
data = None
|
||||
|
||||
# if not compressed we are good to go
|
||||
if zi.compress_type == zipfile.ZIP_STORED:
|
||||
data = self.bzf.read(zi.file_size)
|
||||
|
||||
# if compressed we must decompress it using zlib
|
||||
if zi.compress_type == zipfile.ZIP_DEFLATED:
|
||||
cmpdata = self.bzf.read(zi.compress_size)
|
||||
data = self.uncompress(cmpdata)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
|
||||
def fix(self):
|
||||
# get the zipinfo for each member of the input archive
|
||||
# and copy member over to output archive
|
||||
# if problems exist with local vs central filename, fix them
|
||||
|
||||
for i, zinfo in enumerate(self.inzip.infolist()):
|
||||
data = None
|
||||
nzinfo = zinfo
|
||||
|
||||
try:
|
||||
data = self.inzip.read(zinfo)
|
||||
except zipfile.BadZipfile or zipfile.error:
|
||||
local_name = self.getlocalname(zinfo)
|
||||
data = self.getfiledata(zinfo)
|
||||
nzinfo.filename = local_name
|
||||
|
||||
nzinfo.date_time = zinfo.date_time
|
||||
nzinfo.compress_type = zinfo.compress_type
|
||||
nzinfo.flag_bits = 0
|
||||
nzinfo.internal_attr = 0
|
||||
self.outzip.writestr(nzinfo,data)
|
||||
|
||||
self.bzf.close()
|
||||
self.inzip.close()
|
||||
self.outzip.close()
|
||||
|
||||
|
||||
def usage():
|
||||
print """usage: zipfix.py inputzip outputzip
|
||||
inputzip is the source zipfile to fix
|
||||
outputzip is the fixed zip archive
|
||||
"""
|
||||
|
||||
|
||||
def main(argv=sys.argv):
|
||||
if len(argv)!=3:
|
||||
usage()
|
||||
return 1
|
||||
infile = None
|
||||
outfile = None
|
||||
infile = argv[1]
|
||||
outfile = argv[2]
|
||||
if not os.path.exists(infile):
|
||||
print "Error: Input Zip File does not exist"
|
||||
return 1
|
||||
try:
|
||||
fr = fixZip(infile, outfile)
|
||||
fr.fix()
|
||||
return 0
|
||||
except Exception, e:
|
||||
print "Error Occurred ", e
|
||||
return 2
|
||||
|
||||
if __name__ == '__main__' :
|
||||
sys.exit(main())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user