Skip to content

Instantly share code, notes, and snippets.

@asaf400
Created December 16, 2021 08:22
Show Gist options
  • Save asaf400/146887bf13aa36dafa57aee725e921d4 to your computer and use it in GitHub Desktop.
Save asaf400/146887bf13aa36dafa57aee725e921d4 to your computer and use it in GitHub Desktop.
import pathlib
import zipfile
from shutil import copyfile
java_classes = ['org/apache/log4j/net/JMSAppender.class']
# from six import string_types # would be better here,
# but I wanted something without external deps
try:
basestring
except NameError:
basestring = str
# Parts of this code use the 'ruamel.std.zipfile' package code, without pip dependency
# Author: Anthon van der Neut
# Package: ruamel.std.zipfile
# URL: https://sourceforge.net/u/anthon/profile/
class InMemoryZipFile(object):
# original idea from http://stackoverflow.com/a/19722365/1307905
def __init__(self, file_name=None, compression=None, debug=0):
if compression is None:
compression = zipfile.ZIP_DEFLATED
try:
from cStringIO import StringIO
except ImportError:
from io import BytesIO as StringIO
# Create the in-memory file-like object
if hasattr(file_name, '_from_parts'):
self._file_name = str(file_name)
else:
self._file_name = file_name
self.in_memory_data = StringIO()
# Create the in-memory zipfile
self.in_memory_zip = zipfile.ZipFile(
self.in_memory_data, "w", compression, False)
self.in_memory_zip.debug = debug
def append(self, filename_in_zip, file_contents):
'''Appends a file with name filename_in_zip and contents of
file_contents to the in-memory zip.'''
self.in_memory_zip.writestr(filename_in_zip, file_contents)
return self # so you can daisy-chain
def write_to_file(self, filename):
'''Writes the in-memory zip to a file.'''
# Mark the files as having been created on Windows so that
# Unix permissions are not inferred as 0000
for zfile in self.in_memory_zip.filelist:
zfile.create_system = 0
self.in_memory_zip.close()
with open(filename, 'wb') as f:
f.write(self.data)
@property
def data(self):
return self.in_memory_data.getvalue()
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
if self._file_name is None:
return
self.write_to_file(self._file_name)
def delete_from_zip_file(self, pattern=None, file_names=None):
"""
zip_file can be a string or a zipfile.ZipFile object, the latter will be closed
any name in file_names is deleted, all file_names provided have to be in the ZIP
archive or else an IOError is raised
"""
if pattern and isinstance(pattern, basestring):
import re
pattern = re.compile(pattern)
if file_names:
if not isinstance(file_names, list):
file_names = [str(file_names)]
else:
file_names = [str(f) for f in file_names]
else:
file_names = []
with zipfile.ZipFile(self._file_name) as zf:
for l in zf.infolist():
if l.filename in file_names:
file_names.remove(l.filename)
continue
if pattern and pattern.match(l.filename):
continue
self.append(l.filename, zf.read(l))
if file_names:
raise IOError('[Errno 2] No such file{}: {}'.format(
'' if len(file_names) == 1 else 's',
', '.join([repr(f) for f in file_names])))
def delete_from_zip_file(file_name, pattern=None, file_names=None,
compression=None):
with InMemoryZipFile(file_name, compression=compression) as imz:
imz.delete_from_zip_file(pattern, file_names)
filepath = pathlib.Path(sys.argsv[2])
print(filepath)
if not pathlib.Path("{}.bak".format(filepath)).exists():
print("Creating backup @ '{}.bak'".format(filepath))
copyfile(filepath, "{}.bak".format(filepath))
try:
print('Attempting to delete class {}'.format(java_classes[0]))
delete_from_zip_file(filepath, file_names=java_classes)
except OSError as e:
print("Failed to delete class:\n'{}' from jar file:\n'{}'\nProbably already removed previously".format(java_classes[0],filepath))
# Probably 'No such file' error.
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment