Created
February 10, 2014 04:20
-
-
Save RecursiveG/8910316 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
from gi.repository import Gtk | |
import os | |
import zipfile | |
GLADE_STRING='''<?xml version="1.0" encoding="UTF-8"?> | |
<!-- Generated with glade 3.16.1 --> | |
<interface> | |
<requires lib="gtk+" version="3.10"/> | |
<object class="GtkListStore" id="ZipContentList"> | |
<columns> | |
<!-- column-name FileName --> | |
<column type="gchararray"/> | |
<!-- column-name FileSize --> | |
<column type="gchararray"/> | |
</columns> | |
</object> | |
<object class="GtkWindow" id="MainWindow"> | |
<property name="can_focus">False</property> | |
<property name="title" translatable="yes">Nonstandard Encoded ZIP File Unpacker</property> | |
<signal name="delete-event" handler="onCloseWindow" swapped="no"/> | |
<child> | |
<object class="GtkBox" id="_box1"> | |
<property name="visible">True</property> | |
<property name="can_focus">False</property> | |
<property name="halign">center</property> | |
<property name="valign">center</property> | |
<property name="margin_left">5</property> | |
<property name="margin_right">5</property> | |
<property name="margin_top">1</property> | |
<property name="margin_bottom">5</property> | |
<property name="orientation">vertical</property> | |
<property name="spacing">5</property> | |
<child> | |
<object class="GtkBox" id="_box2"> | |
<property name="visible">True</property> | |
<property name="can_focus">False</property> | |
<property name="spacing">5</property> | |
<child> | |
<object class="GtkEntry" id="FilePathEntry"> | |
<property name="visible">True</property> | |
<property name="can_focus">True</property> | |
</object> | |
<packing> | |
<property name="expand">True</property> | |
<property name="fill">True</property> | |
<property name="position">0</property> | |
</packing> | |
</child> | |
<child> | |
<object class="GtkButton" id="ChooseFileBtn"> | |
<property name="label" translatable="yes">Choose File</property> | |
<property name="visible">True</property> | |
<property name="can_focus">True</property> | |
<property name="receives_default">True</property> | |
<signal name="clicked" handler="on_ChooseFileBtn_clicked" swapped="no"/> | |
</object> | |
<packing> | |
<property name="expand">False</property> | |
<property name="fill">True</property> | |
<property name="position">1</property> | |
</packing> | |
</child> | |
</object> | |
<packing> | |
<property name="expand">False</property> | |
<property name="fill">True</property> | |
<property name="position">0</property> | |
</packing> | |
</child> | |
<child> | |
<object class="GtkScrolledWindow" id="_scrolledwindow1"> | |
<property name="visible">True</property> | |
<property name="can_focus">True</property> | |
<property name="shadow_type">in</property> | |
<property name="min_content_width">500</property> | |
<property name="min_content_height">300</property> | |
<child> | |
<object class="GtkTreeView" id="_MainFileList"> | |
<property name="visible">True</property> | |
<property name="can_focus">True</property> | |
<property name="model">ZipContentList</property> | |
<property name="headers_clickable">False</property> | |
<property name="enable_grid_lines">both</property> | |
<child internal-child="selection"> | |
<object class="GtkTreeSelection" id="FileSelection"> | |
<property name="mode">browse</property> | |
</object> | |
</child> | |
<child> | |
<object class="GtkTreeViewColumn" id="_columnname"> | |
<property name="min_width">400</property> | |
<property name="title" translatable="yes">File Name</property> | |
<child> | |
<object class="GtkCellRendererText" id="_cellrenderertext1"/> | |
<attributes> | |
<attribute name="text">0</attribute> | |
</attributes> | |
</child> | |
</object> | |
</child> | |
<child> | |
<object class="GtkTreeViewColumn" id="_columnsize"> | |
<property name="title" translatable="yes">File Size</property> | |
<property name="expand">True</property> | |
<child> | |
<object class="GtkCellRendererText" id="_cellrenderertext2"/> | |
<attributes> | |
<attribute name="size">1</attribute> | |
<attribute name="text">1</attribute> | |
</attributes> | |
</child> | |
</object> | |
</child> | |
</object> | |
</child> | |
</object> | |
<packing> | |
<property name="expand">False</property> | |
<property name="fill">True</property> | |
<property name="position">1</property> | |
</packing> | |
</child> | |
<child> | |
<object class="GtkBox" id="_box3"> | |
<property name="visible">True</property> | |
<property name="can_focus">False</property> | |
<property name="spacing">5</property> | |
<child> | |
<object class="GtkComboBoxText" id="_comboboxtext1"> | |
<property name="visible">True</property> | |
<property name="can_focus">False</property> | |
<property name="has_entry">True</property> | |
<items> | |
<item translatable="yes">ASCII</item> | |
<item translatable="yes">GBK</item> | |
<item translatable="yes">SHIFT-JIS</item> | |
<item translatable="yes">BIG5</item> | |
<item translatable="yes">UTF-8</item> | |
</items> | |
<signal name="changed" handler="on_comboboxtext1_changed" swapped="no"/> | |
<child internal-child="entry"> | |
<object class="GtkEntry" id="EncodeSelectEntry"> | |
<property name="can_focus">False</property> | |
<property name="text" translatable="yes">ASCII</property> | |
</object> | |
</child> | |
</object> | |
<packing> | |
<property name="expand">False</property> | |
<property name="fill">True</property> | |
<property name="position">0</property> | |
</packing> | |
</child> | |
<child> | |
<object class="GtkButton" id="ExtractAllBtn"> | |
<property name="label" translatable="yes">Extract All</property> | |
<property name="visible">True</property> | |
<property name="can_focus">True</property> | |
<property name="receives_default">True</property> | |
<signal name="clicked" handler="on_ExtractAllBtn_clicked" swapped="no"/> | |
</object> | |
<packing> | |
<property name="expand">False</property> | |
<property name="fill">True</property> | |
<property name="position">1</property> | |
</packing> | |
</child> | |
<child> | |
<object class="GtkButton" id="ExtractOneBtn"> | |
<property name="label" translatable="yes">Extract Selected File</property> | |
<property name="visible">True</property> | |
<property name="can_focus">True</property> | |
<property name="receives_default">True</property> | |
<signal name="clicked" handler="on_ExtractOneBtn_clicked" swapped="no"/> | |
</object> | |
<packing> | |
<property name="expand">False</property> | |
<property name="fill">True</property> | |
<property name="position">2</property> | |
</packing> | |
</child> | |
</object> | |
<packing> | |
<property name="expand">False</property> | |
<property name="fill">True</property> | |
<property name="position">2</property> | |
</packing> | |
</child> | |
</object> | |
</child> | |
</object> | |
</interface>''' | |
class MyApplication(): | |
def MessageBox(self,message): | |
dia=Gtk.Dialog("MessageBox",self.MainWindow,0, | |
(Gtk.STOCK_OK, Gtk.ResponseType.OK,)) | |
dia.get_content_area().add(Gtk.Label(message)) | |
dia.show_all() | |
res=dia.run() | |
dia.destroy() | |
def try_decode(self): | |
self.ZipContentList.clear() | |
try: | |
enc=self.EncodeSelectEntry.get_text() | |
for x in self.zf: | |
self.ZipContentList.append([x.decode(enc),str(self.zf[x])]) | |
except UnicodeDecodeError: | |
self.MessageBox("Error when decoding. Try with another Encoding.") | |
def do_extract_file(self,pth,fname): | |
if (fname[-1]=="/") or (fname[-1]=="\\"): | |
return | |
folders=fname.split(os.path.sep) | |
folderpth=os.path.join(pth,os.path.sep.join(folders[:-1])) | |
if not os.path.isdir(folderpth): | |
os.makedirs(folderpth,0o755,exist_ok=True) | |
fullpth=os.path.join(pth,fname) | |
innerpth=fname.encode(self.EncodeSelectEntry.get_text()).decode('CP437') | |
f1=open(fullpth,"wb") | |
f1.write(self.z.read(innerpth)) | |
f1.close() | |
def onCloseWindow(self,*args): | |
Gtk.main_quit() | |
def on_ChooseFileBtn_clicked(self,*args): | |
dialog=Gtk.FileChooserDialog("Select A ZIP file",self.MainWindow, | |
Gtk.FileChooserAction.OPEN, | |
(Gtk.STOCK_CANCEL,Gtk.ResponseType.CANCEL, | |
Gtk.STOCK_OPEN,Gtk.ResponseType.OK)) | |
fi=Gtk.FileFilter() | |
fi.set_name("ZIP File") | |
fi.add_mime_type("application/zip") | |
dialog.add_filter(fi) | |
rsp=dialog.run() | |
if rsp!=Gtk.ResponseType.OK: | |
dialog.destroy() | |
return | |
pth=dialog.get_filename() | |
dialog.destroy() | |
self.FilePathEntry.set_text(pth) | |
self.z=zipfile.ZipFile(pth) | |
for i in self.z.infolist(): | |
self.zf[i.filename.encode('CP437')]=i.file_size | |
self.try_decode() | |
def on_comboboxtext1_changed(self,*args): | |
self.try_decode() | |
def on_ExtractAllBtn_clicked(self,*args): | |
dialog=Gtk.FileChooserDialog("Select A Folder",self.MainWindow, | |
Gtk.FileChooserAction.SELECT_FOLDER, | |
(Gtk.STOCK_CANCEL,Gtk.ResponseType.CANCEL, | |
"Select",Gtk.ResponseType.OK)) | |
rsp=dialog.run() | |
if rsp!=Gtk.ResponseType.OK: | |
dialog.destroy() | |
return | |
pth=dialog.get_filename()+"/" | |
dialog.destroy() | |
self.FilePathEntry.set_text("Extracting...") | |
for x in self.ZipContentList: | |
self.do_extract_file(pth,x[0]) | |
self.FilePathEntry.set_text("Extract Finished.") | |
def on_ExtractOneBtn_clicked(self,*args): | |
model,treeiter=self.FileSelection.get_selected() | |
if treeiter==None: | |
self.MessageBox("Choose a file first") | |
return | |
fname=model[treeiter][0] | |
if fname[-1]=="/": | |
self.MessageBox("This is a Folder, not a File") | |
dialog=Gtk.FileChooserDialog("Select A Folder",self.MainWindow, | |
Gtk.FileChooserAction.SELECT_FOLDER, | |
(Gtk.STOCK_CANCEL,Gtk.ResponseType.CANCEL, | |
"Select",Gtk.ResponseType.OK)) | |
rsp=dialog.run() | |
if rsp!=Gtk.ResponseType.OK: | |
dialog.destroy() | |
return | |
pth=dialog.get_filename()+"/" | |
dialog.destroy() | |
self.FilePathEntry.set_text("Extracting...") | |
self.do_extract_file(pth,fname) | |
self.FilePathEntry.set_text("Extract Finished.") | |
def _load(self): | |
handlers={ | |
"onCloseWindow":self.onCloseWindow, | |
"on_ChooseFileBtn_clicked":self.on_ChooseFileBtn_clicked, | |
"on_comboboxtext1_changed":self.on_comboboxtext1_changed, | |
"on_ExtractAllBtn_clicked":self.on_ExtractAllBtn_clicked, | |
"on_ExtractOneBtn_clicked":self.on_ExtractOneBtn_clicked, | |
} | |
self.builder.connect_signals(handlers) | |
go=self.builder.get_object | |
self.ZipContentList=go("ZipContentList") | |
self.MainWindow=go("MainWindow") | |
self.FilePathEntry=go("FilePathEntry") | |
self.ChooseFileBtn=go("ChooseFileBtn") | |
self.FileSelection=go("FileSelection") | |
self.EncodeSelectEntry=go("EncodeSelectEntry") | |
self.ExtractAllBtn=go("ExtractAllBtn") | |
self.ExtractOneBtn=go("ExtractOneBtn") | |
def __init__(self): | |
self.builder=Gtk.Builder(); | |
self.builder.add_from_string(GLADE_STRING) | |
self._load() | |
self.zf=dict() | |
def Start(self): | |
self.MainWindow.show_all() | |
Gtk.main() | |
if __name__=="__main__": | |
Application=MyApplication() | |
Application.Start() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment