MIO-KITCHEN-SOURCE/tool.py

2969 lines
126 KiB
Python

#!/usr/bin/env python3
import mmap
import platform
import subprocess
from functools import wraps
if not platform.system() == 'Darwin':
try:
import load_window
except ModuleNotFoundError:
pass
import json
import os.path
import shlex
import sys
import time
import tkinter as tk
from configparser import ConfigParser
from webbrowser import open as openurl
import contextpatch
import extra
import utils
from extra import *
from utils import cz, jzxs, v_code, gettype, findfile, findfolder, sdat2img
if os.name == 'nt':
import windnd
from tkinter import filedialog
elif os.name == "posix":
import mkc_filedialog as filedialog
import zipfile
from io import BytesIO, StringIO
from platform import machine
from tkinter import *
from tkinter import ttk, messagebox
from shutil import rmtree, copy, move
import requests
import sv_ttk
from PIL import Image, ImageTk
import fspatch
import imgextractor
import lpunpack
import mkdtboimg
import ozipdecrypt
import payload_dumper
import splituapp
from timeit import default_timer as dti
import ofp_qc_decrypt
import ofp_mtk_decrypt
import editor
import yaml
import opscrypto
class load_car(object):
def __init__(self, *args):
pass
def run(self, ind: int = 0):
self.hide_gifl = False
if not self.hide_gifl:
win.gifl.pack(padx=10, pady=10)
self.frame = self.frames[ind]
ind += 1
if ind == len(self.frames):
ind = 0
win.gifl.configure(image=self.frame)
self.gifs = win.gifl.after(30, self.run, ind)
def endupdate(self):
win.gifl.after_cancel(self.gifs)
win.gifl.pack_forget()
self.hide_gifl = True
def init(self):
self.run()
self.endupdate()
def loadgif(self, gif):
self.frames = []
try:
while True:
self.frames.append(ImageTk.PhotoImage(gif.copy()))
gif.seek(len(self.frames))
except EOFError:
pass
def __call__(self, func):
@wraps(func)
def call_func(*args, **kwargs):
cz(self.run())
func(*args, **kwargs)
self.endupdate()
return call_func
cartoon = load_car()
class dev_null(object):
def __init__(self):
pass
def write(self, string):
pass
@staticmethod
def flush():
pass
def __exit__(self):
pass
def close(self):
pass
class Tool(Tk):
def __init__(self):
super().__init__()
self.title('MIO-KITCHEN')
if os.name != "posix":
self.iconphoto(True,
tk.PhotoImage(
file="".join([os.getcwd(), os.sep, "bin", os.sep, "images", os.sep, "icon.png"])))
sys.stdout = dev_null()
def gui(self):
if os.name == 'posix' and os.geteuid() != 0:
print(lang.warn13)
self.subwin2 = ttk.LabelFrame(self, text=lang.text9)
self.subwin3 = ttk.LabelFrame(self, text=lang.text10)
self.subwin3.pack(fill=BOTH, side=LEFT, expand=True, padx=5)
self.subwin2.pack(fill=BOTH, side=LEFT, expand=True, pady=5)
self.notepad = ttk.Notebook(self.subwin2)
self.tab = ttk.Frame(self.notepad)
self.tab2 = ttk.Frame(self.notepad)
self.tab3 = ttk.Frame(self.notepad)
self.tab4 = ttk.Frame(self.notepad)
self.tab5 = ttk.Frame(self.notepad)
self.tab6 = ttk.Frame(self.notepad)
self.tab7 = ttk.Frame(self.notepad)
self.notepad.add(self.tab, text=lang.text11)
self.notepad.add(self.tab2, text=lang.text12)
self.notepad.add(self.tab7, text=lang.text19)
self.notepad.add(self.tab3, text=lang.text13)
self.notepad.add(self.tab4, text=lang.text14)
self.notepad.add(self.tab5, text=lang.text15)
self.notepad.add(self.tab6, text=lang.text16)
self.scrollbar = ttk.Scrollbar(self.tab5, orient=tk.VERTICAL)
self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.canvas1 = Canvas(self.tab5, yscrollcommand=self.scrollbar.set)
self.canvas1.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
self.frame_bg = ttk.Frame(self.canvas1)
self.canvas1.create_window((0, 0), window=self.frame_bg, anchor='nw')
self.canvas1.config(highlightthickness=0)
self.tab4_n()
self.tab6_n()
self.setting_tab()
self.notepad.pack(fill=BOTH)
self.rzf = ttk.Frame(self.subwin3)
self.tsk = Label(self.subwin3, text="MIO-KITCHEN", font=('楷书', 15))
self.tsk.bind('<Button-1>')
self.tsk.pack(padx=10, pady=10, side='top')
tr = ttk.LabelFrame(self.subwin3, text=lang.text131)
Label(tr, text=lang.text132).pack(padx=10, pady=10, side='bottom')
tr.bind('<Button-1>', sdxz)
tr.pack(padx=5, pady=5, side='top', expand=True, fill=BOTH)
if os.name == 'nt':
windnd.hook_dropfiles(tr, func=dndfile)
self.show = Text(self.rzf)
self.show.pack(side=LEFT, fill=BOTH, expand=True)
ttk.Button(self.rzf, text=lang.text105, command=lambda: self.show.delete(1.0, END)).pack(side='bottom', padx=10,
pady=5,
expand=True)
ttk.Button(self.rzf, text=lang.text106, command=handle_log().putlog).pack(side='bottom', padx=10, pady=5,
expand=True)
self.rzf.pack(padx=5, pady=5, fill=BOTH, side='bottom')
# 项目列表的控件
sys.stdout = StdoutRedirector(self.show)
sys.stderr = StdoutRedirector(self.show)
zyf1 = ttk.LabelFrame(win.tab, text=lang.text9)
zyf1.pack(padx=10, pady=10)
ttk.Button(zyf1, text=lang.text16, command=lambda: self.notepad.select(win.tab6)).pack(side='left',
padx=10,
pady=10)
ttk.Button(zyf1, text=lang.text114, command=lambda: cz(download_file)).pack(side='left', padx=10, pady=10)
mpkman()
self.gifl = Label(self.rzf)
self.gifl.pack(padx=10, pady=10)
def upjdt(self):
self.frame_bg.update_idletasks()
self.canvas1.config(scrollregion=self.canvas1.bbox('all'))
self.scrollbar.config(command=self.canvas1.yview)
def getframe(self, title):
frame = ttk.LabelFrame(self.frame_bg, text=title)
frame.pack(padx=10, pady=10)
ttk.Button(frame, text=lang.text17, command=frame.destroy).pack(anchor="ne")
self.upjdt()
return frame
def tab4_n(self):
def open_github(o):
openurl("https://github.com/ColdWindScholar/MIO-KITCHEN-SOURCE")
Label(self.tab4, text="MIO-KITCHEN", font=('楷书', 30)).pack(padx=20, pady=10)
Label(self.tab4, text=lang.text111, font=('楷书', 15), fg='#00BFFF').pack(padx=10, pady=10)
ttk.Separator(self.tab4, orient=HORIZONTAL).pack(padx=100, fill=X)
Label(self.tab4,
text=lang.text128.format(settings.version, sys.version[:6], os.name, machine()),
font=('楷书', 11), fg='#00aaff').pack(padx=10, pady=10)
ttk.Separator(self.tab4, orient=HORIZONTAL).pack(padx=100, fill=X)
Label(self.tab4,
text=lang.text127,
font=('楷书', 12), fg='#ff8800').pack(padx=10, pady=10)
ttk.Separator(self.tab4, orient=HORIZONTAL).pack(padx=100, fill=X)
Label(self.tab4, text=lang.text110, font=('楷书', 10)).pack(padx=10, pady=10, side='bottom')
# ttk.Button(self.tab4, text="检查更新", command=lambda: cz(upgrade())).pack(padx=10, pady=10)
link = ttk.Label(self.tab4, text="Github: MIO-KITCHEN-SOURCE", cursor="hand2",
style="Link.TLabel")
link.bind("<Button-1>", open_github)
link.pack()
def tab6_n(self):
Label(self.tab6,
text=f"Wechat Pay/微信支付",
font=('楷书', 20), fg='#008000').pack(padx=10, pady=10)
self.photo = ImageTk.PhotoImage(Image.open('bin/images/wechat.gif'))
Label(self.tab6, image=self.photo).pack(padx=5, pady=5)
Label(self.tab6, text=lang.text109, font=('楷书', 12), fg='#00aafA').pack(padx=10, pady=10, side='bottom')
def setting_tab(self):
self.slocal = StringVar()
self.slocal.set(settings.path)
sf1 = ttk.Frame(self.tab3)
sf2 = ttk.Frame(self.tab3)
sf3 = ttk.Frame(self.tab3)
ttk.Label(sf1, text=lang.text124).pack(side='left', padx=10, pady=10)
self.LB2 = ttk.Combobox(sf1, textvariable=theme, state='readonly', values=["light", "dark"])
self.LB2.pack(padx=10, pady=10, side='left')
self.LB2.bind('<<ComboboxSelected>>', set_theme)
def startwjjj(ev):
if os.name == 'nt':
os.startfile(self.slocal.get())
ttk.Label(sf3, text=lang.text125).pack(side='left', padx=10, pady=10)
slo = ttk.Label(sf3, textvariable=self.slocal)
slo.bind('<Button-1>', startwjjj)
slo.pack(padx=10, pady=10, side='left')
ttk.Button(sf3, text=lang.text126, command=modpath).pack(side="left", padx=10, pady=10)
ttk.Label(sf2, text=lang.lang).pack(side='left', padx=10, pady=10)
LB3 = ttk.Combobox(sf2, state='readonly', textvariable=language,
value=[i.rsplit('.', 1)[0] for i in
os.listdir(elocal + os.sep + "bin" + os.sep + "languages")])
LB3.pack(padx=10, pady=10, side='left')
LB3.bind('<<ComboboxSelected>>', set_language)
sf1.pack(padx=10, pady=10, fill='both')
sf2.pack(padx=10, pady=10, fill='both')
sf3.pack(padx=10, pady=10, fill='both')
win = Tool()
start = dti()
setfile = ''.join([(elocal := utils.elocal), os.sep, "bin", os.sep, "setting.ini"])
modfile = ''.join([elocal, os.sep, "bin", os.sep, "module", os.sep, "module.json"])
dn = utils.dn = StringVar()
theme = StringVar()
language = StringVar()
class ModuleError(Exception):
pass
class lang:
pass
def load(name):
if not name and not os.path.exists(elocal + os.sep + f'bin/languages/English.json'):
error(1)
elif not os.path.exists(elocal + os.sep + f'bin/languages/{name}.json'):
with open("".join([elocal, os.sep, 'bin/languages/English.json']), 'r', encoding='utf-8') as f:
_lang = json.load(f)
else:
with open(f'{elocal}{os.sep}bin/languages/{name}.json', 'r', encoding='utf-8') as f:
_lang = json.load(f)
[setattr(lang, i, _lang[i]) for i in _lang]
def error(code, desc="未知错误"):
if not win:
er = Tk()
else:
er = win
er.protocol("WM_DELETE_WINDOW", sys.exit)
er.title("错误")
er.lift()
er.resizable(False, False)
jzxs(er)
Label(er, text="错误代码:%s" % code).pack(padx=10, pady=10)
te = Text(er)
te.pack(padx=10, pady=10)
te.insert('insert', desc)
ttk.Button(er, text="确定", command=lambda: sys.exit(1)).pack(padx=10, pady=10)
if not win:
er.wait_window()
else:
er.mainloop()
class welcome(object):
def __init__(self):
self.ck = Toplevel()
self.ck.title(lang.text135)
self.ck.resizable(False, False)
self.ck.protocol("WM_DELETE_WINDOW", self.clos)
self.frame = None
oobe = int(settings.oobe)
if oobe == "1":
self.main()
elif oobe == '2':
self.license()
elif oobe == '3':
self.private()
elif oobe == '4':
self.done()
else:
ttk.Label(self.ck, text=lang.text135, font=("宋体", 40)).pack(padx=10, pady=10, fill=BOTH, expand=True)
ttk.Separator(self.ck, orient=HORIZONTAL).pack(padx=10, pady=10, fill=X)
ttk.Label(self.ck, text=lang.text137, font=("宋体", 20)).pack(padx=10, pady=10, fill=BOTH, expand=True)
ttk.Button(self.ck, text=lang.text136, command=self.main).pack(fill=BOTH)
win.withdraw()
self.ck.wait_window()
win.deiconify()
def reframe(self):
if self.frame:
self.frame.destroy()
self.frame = ttk.Frame(self.ck)
self.frame.pack(expand=1, fill=BOTH)
def main(self):
settings.setf("oobe", "1")
for i in self.ck.winfo_children():
i.destroy()
self.reframe()
ttk.Label(self.frame, text=lang.text129, font=("宋体", 20)).pack(padx=10, pady=10, fill=BOTH, expand=True)
ttk.Separator(self.frame, orient=HORIZONTAL).pack(padx=10, pady=10, fill=X)
LB3_ = ttk.Combobox(self.frame, state='readonly', textvariable=language,
value=[i.rsplit('.', 1)[0] for i in
os.listdir(elocal + os.sep + "bin" + os.sep + "languages")])
LB3_.pack(padx=10, pady=10, side='top')
LB3_.bind('<<ComboboxSelected>>', set_language)
ttk.Button(self.frame, text=lang.text138, command=self.license).pack(fill=X, side='bottom')
def license(self):
settings.setf("oobe", "2")
lce = StringVar()
def loadlice(self):
te.delete(1.0, END)
with open(''.join([elocal, os.sep, "bin", os.sep, "licenses", os.sep, lce.get(), ".txt"]), 'r',
encoding='UTF-8') as f:
te.insert('insert', f.read())
self.reframe()
LB = ttk.Combobox(self.frame, state='readonly', textvariable=lce,
value=[i.rsplit('.')[0] for i in os.listdir(elocal + os.sep + "bin" + os.sep + "licenses")])
LB.bind('<<ComboboxSelected>>', loadlice)
LB.current(0)
ttk.Label(self.frame, text=lang.text139, font=("宋体", 25)).pack(side='top', padx=10, pady=10, fill=BOTH,
expand=True)
ttk.Separator(self.frame, orient=HORIZONTAL).pack(padx=10, pady=10, fill=X)
LB.pack(padx=10, pady=10, side='top', fill=X)
te = Text(self.frame)
te.pack(fill=BOTH, side='top')
loadlice(self)
ttk.Label(self.frame, text=lang.t1).pack()
ttk.Button(self.frame, text=lang.text138, command=self.private).pack(fill=BOTH, side='bottom')
def private(self):
settings.setf("oobe", "3")
self.reframe()
ttk.Label(self.frame, text=lang.t2, font=("宋体", 25)).pack(side='top', padx=10, pady=10, fill=BOTH,
expand=True)
ttk.Separator(self.frame, orient=HORIZONTAL).pack(padx=10, pady=10, fill=X)
with open(''.join([elocal, os.sep, "bin", os.sep, "licenses", os.sep, "private.txt"]), 'r',
encoding='UTF-8') as f:
(te := Text(self.frame)).insert('insert', f.read())
te.pack(fill=BOTH)
ttk.Label(self.frame, text=lang.t3).pack()
ttk.Button(self.frame, text=lang.text138, command=self.done).pack(fill=BOTH, side='bottom')
def done(self):
settings.setf("oobe", "4")
self.reframe()
ttk.Label(self.frame, text=lang.t4, font=("宋体", 25)).pack(side='top', padx=10, pady=10, fill=BOTH,
expand=True)
ttk.Separator(self.frame, orient=HORIZONTAL).pack(padx=10, pady=10, fill=X)
ttk.Label(self.frame, text=lang.t5, font=("宋体", 20)).pack(
side='top', fill=BOTH, padx=10, pady=10)
ttk.Button(self.ck, text=lang.text34, command=self.ck.destroy).pack(fill=BOTH, side='bottom')
def clos(self):
pass
def upgrade():
ck = Toplevel()
ck.title("检查更新")
data = requests.get(settings.update_url + "update.json").content.decode()
up = json.loads(data)
Label(ck, text="MIO-KITCHEN", font=('楷书', 30)).pack(padx=5, pady=5)
ttk.Separator(ck, orient=HORIZONTAL).pack(padx=30, fill=X)
if up['version'] != settings.version:
Label(ck, text="发现新版本:%s" % (up['version']), font=('楷书', 15), fg='green').pack(padx=5, pady=5)
lf = ttk.LabelFrame(ck, text="更新日志")
lf.pack(padx=10, pady=10)
text = Text(lf)
text.insert("insert", up['uplog'])
text.pack(fill=BOTH, padx=5, pady=5)
ttk.Button(ck, text="更新").pack(padx=5, pady=5, fill=X)
else:
Label(ck, text="已是最新版本:%s" % settings.version, font=('华文行楷', 15)).pack(padx=5, pady=5)
ttk.Button(ck, text="确定", command=ck.destroy).pack(padx=5, pady=5, fill=X, side=LEFT, expand=True)
ttk.Button(ck, text="刷新", command=ck.destroy).pack(padx=5, pady=5, fill=X, side=LEFT, expand=True)
class set_utils(object):
def __init__(self, set_ini):
self.path = None
self.barlevel = '0.9'
self.set_file = set_ini
self.config = ConfigParser()
if os.access(self.set_file, os.F_OK):
self.load()
else:
sv_ttk.set_theme("dark")
error(1, '缺失配置文件,请重新安装此软件')
def load(self):
self.config.read(self.set_file)
for i in self.config.items('setting'):
setattr(self, i[0], i[1])
if os.path.exists(self.path):
if not self.path:
self.path = os.getcwd()
else:
self.path = os.getcwd()
language.set(self.language)
load(language.get())
theme.set(self.theme)
sv_ttk.set_theme(self.theme)
win.attributes("-alpha", self.barlevel)
def setf(self, name, value):
self.config.read(setfile)
self.config.set("setting", "%s" % name, "%s" % value)
with open(self.set_file, 'w') as fil:
self.config.write(fil)
self.load()
settings = set_utils(setfile)
settings.load()
def messpop(message, color='orange') -> None:
win.tsk.config(text=message, bg=color)
def get_time() -> None:
win.tsk.config(text=time.strftime("%H:%M:%S"), bg=win.cget('bg'))
win.after(1000, get_time)
def re_folder(path) -> None:
if os.path.exists(path):
rmdir(path, 1)
os.mkdir(path)
else:
os.mkdir(path)
@cartoon
def un_dtbo(bn: str = 'dtbo') -> any:
if not (dtboimg := findfile(f"{bn}.img", work := rwork())):
print(lang.warn3.format(bn))
return False
re_folder(work + f"{bn}")
re_folder(work + f"{bn}" + os.sep + "dtbo")
re_folder(work + f"{bn}" + os.sep + "dts")
try:
mkdtboimg.dump_dtbo(dtboimg, work + f"{bn}" + os.sep + "dtbo" + os.sep + "dtbo")
except Exception as e:
print(lang.warn4.format(e))
return False
for dtbo in os.listdir(work + f"{bn}" + os.sep + "dtbo"):
if dtbo.startswith("dtbo."):
print(lang.text4.format(dtbo))
call(exe="dtc -@ -I dtb -O dts %s -o %s" % (work + f"{bn}" + os.sep + "dtbo" + os.sep + dtbo,
"".join([work, f"{bn}", os.sep, "dts", os.sep, "dts." +
os.path.basename(dtbo).rsplit('.', 1)[1]])), out=1)
print(lang.text5)
try:
os.remove(dtboimg)
except:
pass
rmdir(work + "dtbo" + os.sep + "dtbo", 1)
@cartoon
def padtbo() -> any:
work = rwork()
if not os.path.exists(work + "dtbo" + os.sep + "dts") or not os.path.exists(work + "dtbo"):
print(lang.warn5)
return False
re_folder(work + "dtbo" + os.sep + "dtbo")
for dts in os.listdir(work + "dtbo" + os.sep + "dts"):
if dts.startswith("dts."):
print(f"{lang.text6}:%s" % dts)
call(exe="dtc -@ -I dts -O dtb %s -o %s" % (work + "dtbo" + os.sep + "dts" + os.sep + dts,
work + "dtbo" + os.sep + "dtbo" + os.sep + "dtbo." +
os.path.basename(dts).rsplit('.', 1)[1]), out=1)
print(f"{lang.text7}:dtbo.img")
list_ = []
for f in os.listdir(work + "dtbo" + os.sep + "dtbo"):
if f.startswith("dtbo."):
list_.append(work + "dtbo" + os.sep + "dtbo" + os.sep + f)
list_ = sorted(list_, key=lambda x: int(x.rsplit('.')[1]))
mkdtboimg.create_dtbo(work + "dtbo.img", list_, 4096)
rmdir(work + "dtbo", 1)
print(lang.text8)
@cartoon
def logodump(bn: str = 'logo'):
if not (logo := findfile(f'{bn}.img', work := rwork())):
messpop(lang.warn3.format(bn))
return False
re_folder(work + f"{bn}")
utils.LOGODUMPER(logo, work + f"{bn}").unpack()
@cartoon
def logopack() -> int:
orlogo = findfile('logo.img', work := rwork())
logo = work + "logo-new.img"
if not os.path.exists(dir_ := work + "logo"):
print(lang.warn6)
return 1
if not os.path.exists(orlogo):
print(lang.warn6)
return 1
utils.LOGODUMPER(orlogo, logo, dir_).repack()
os.remove(orlogo)
os.rename(logo, orlogo)
rmdir(dir_, 1)
def subp(com: int = 1, title: str = lang.text18, master: any = None):
if com == 1:
subpage = Toplevel()
subpage.title(title)
jzxs(subpage)
return subpage
else:
master.destroy()
class Process(Toplevel):
def __init__(self, mps):
super().__init__()
self.prc = None
self.dir = os.path.join(elocal + os.sep + 'bin' + os.sep + 'temp', v_code(10))
self.project = os.path.join(self.dir, v_code())
self.mps = mps
self.in_process = False
self.error = 1
dn.set(os.path.basename(self.project))
self.gavs = {
'bin': self.dir,
'tool_bin': f'{elocal}{os.sep}bin{os.sep}{platform.system()}{os.sep}{platform.machine()}{os.sep}'.replace(
'\\', '/'),
'mkc_env': os.path.join(self.dir, v_code(10)),
'project': self.project.replace('\\', '/')
}
self.value = ['tool_bin', 'bin', 'mkc_env', 'project']
self.control = []
self.able = True
self.protocol("WM_DELETE_WINDOW", self.exit)
try:
win.withdraw()
finally:
pass
self.notice = Label(self, text='Preparing...', font=(None, 15))
self.notice.pack(padx=10, pady=10)
self.title("Preparing...")
self.start = ttk.Button(self, text='Preparing', state='disabled', command=lambda: cz(self.run))
self.start.pack(side=BOTTOM, padx=30, pady=30)
self.progbar = ttk.Progressbar(self, orient=HORIZONTAL, length=200, mode='indeterminate')
self.progbar.pack(side=TOP, fill=X)
self.prepare()
def prepare(self):
zipfile.ZipFile(self.mps).extractall(self.dir)
jzxs(self)
with open(self.dir + os.sep + "main.yml", 'r', encoding='utf-8') as yml:
self.prc = yaml.load(yml.read(), Loader=yaml.FullLoader)
self.title(self.prc['name'])
if "system" in self.prc['support']:
if sys.platform not in self.prc['support']['system']:
self.notice.configure(text="未满足系统要求", fg='red')
self.able = False
if "version" in self.prc['support']:
if settings.version not in self.prc['support']['version']:
self.notice.configure(text="未满足版本要求", fg='red')
self.able = False
self.start.configure(state='normal')
if not self.able:
self.start.configure(text="退出")
else:
self.controls()
self.notice.configure(text="准备就绪", fg='green')
self.start.configure(text="运行")
def controls(self):
for key in self.prc['inputs']:
con = self.prc['inputs'][key]
self.value.append(key)
if con["type"] == "radio":
radio_var_name = key
self.gavs[radio_var_name] = StringVar()
options = con['opins'].split()
if 'text' in con:
pft1 = ttk.LabelFrame(self, text=con['text'])
else:
pft1 = ttk.Frame(self)
self.control.append(pft1)
pft1.pack(padx=10, pady=10)
for option in options:
text, value = option.split('|')
self.gavs[radio_var_name].set(value)
ttk.Radiobutton(pft1, text=text, variable=self.gavs[radio_var_name],
value=value).pack(side=LEFT, padx=5, pady=5)
elif con["type"] in ['entry', 'Entry']:
input_frame = Frame(self)
input_frame.pack(padx=10, pady=10)
self.control.append(input_frame)
input_var_name = key
self.gavs[input_var_name] = StringVar()
if 'text' in con:
ttk.Label(input_frame, text=con['text']).pack(side=LEFT, padx=5, pady=5, fill=X)
ttk.Entry(input_frame, textvariable=self.gavs[input_var_name]).pack(side=LEFT, pady=5,
padx=5,
fill=X)
elif con['type'] == 'checkbutton':
b_var_name = key
self.gavs[b_var_name] = IntVar()
if 'text' not in con:
text = 'M.K.C'
else:
text = con['text']
self.control.append(cb := ttk.Checkbutton(self, text=text, variable=self.gavs[b_var_name], onvalue=1,
offvalue=0,
style="Switch.TCheckbutton"))
cb.pack(
padx=5, pady=5, fill=BOTH)
else:
print(lang.warn14.format(con['type']))
def run(self):
if not self.able:
self.exit()
return
for c in self.control:
c.destroy()
self.in_process = True
process = Text(self)
process.pack(fill=BOTH)
sys.stdout = StdoutRedirector(process)
sys.stderr = StdoutRedirector(process)
self.start.configure(text="正在运行", state='disabled')
with open(engine := self.dir + os.sep + v_code() + "_engine", 'w', encoding='utf-8') as en:
for u in self.value:
try:
var = self.gavs[u].get()
except:
var = self.gavs[u]
en.write(f"export {u}={var}\n")
en.write("source $1")
self.progbar.start()
for step in self.prc['steps']:
self.notice.configure(text=step['name'])
if 'run' in step:
with open(sh_tmp_file := self.dir + os.sep + v_code(), 'w', encoding='utf-8') as sh_tmp:
sh_tmp.writelines(step['run'])
if os.name == 'posix':
sh = "ash"
else:
sh = "bash"
self.error = call("busybox {} {} {}".format(sh, engine, sh_tmp_file))
elif "use" in step:
try:
self.use(step)
except Exception as e:
print(e)
self.error = 0
self.stop()
break
else:
print(f"Unsupported {step}")
self.progbar.stop()
self.able = False
self.in_process = False
self.start.configure(text="退出", state='normal')
def use(self, step):
def download(url):
start_time = time.time()
try:
response = requests.Session().head(url)
file_size = int(response.headers.get("Content-Length", 0))
response = requests.Session().get(url, stream=True, verify=False)
with open(self.dir + os.sep + os.path.basename(url), "wb") as f:
chunk_size = 2048576
bytes_downloaded = 0
for data in response.iter_content(chunk_size=chunk_size):
f.write(data)
bytes_downloaded += len(data)
elapsed = time.time() - start_time
speed = bytes_downloaded / (1024 * elapsed)
percentage = int(bytes_downloaded * 100 / file_size)
print(lang.text64.format(str(percentage), str(speed), str(bytes_downloaded), str(file_size)))
except:
self.error = 0
else:
self.error = 1
def unzip(file, folder):
print(f"Unzipping {file}...")
with zipfile.ZipFile(file) as zip_:
for file_ in zip_.namelist():
try:
file = str(file_).encode('cp437').decode('gbk')
except:
file = str(file_).encode('utf-8').decode('utf-8')
print(lang.text38.format(file_))
zip_.extract(file, folder)
def pack_super(type, dbfz, size, lb, sparse):
if type == 'A':
set_ = 1
elif type == 'VAB':
set_ = 2
elif type == 'AB':
set_ = 3
if sparse == "True":
sparse = True
else:
sparse = False
(supers := IntVar()).set(int(size))
(ssparse := IntVar()).set(int(sparse))
(supersz := IntVar()).set(int(set_))
(sdbfz := StringVar()).set(dbfz)
c = packsuper(sparse=ssparse, dbfz=sdbfz, size=supers, set_=supersz, lb=lb, return_cmd=1)
call(c)
actions = {
'download': lambda url: download(url['url']),
'unzip': lambda cmd: unzip(os.path.abspath(cmd['src']), os.path.abspath(cmd['dst'])),
'unpack': lambda cmd: print(cmd),
'pack': lambda cmd: print(cmd),
'pack_super': lambda cmd: pack_super(cmd['type'], cmd['cluster_name'], cmd['size'],
cmd['partition'].split(), cmd['sparse'])
}
actions[step['use']](step)
def stop(self):
self.in_process = False
self.able = False
self.progbar.stop()
self.notice.configure(text="错误!", fg='red')
self.start.configure(text="退出", state='normal')
def exit(self):
if self.in_process:
return
settings.load()
sys.stdout = StdoutRedirector(win.show)
sys.stderr = StdoutRedirector(win.show)
xmcd_.listdir()
rmdir(self.dir)
self.destroy()
win.deiconify()
class IconGrid(tk.Frame):
def __init__(self, master=None, **kwargs):
super().__init__(master, **kwargs)
self.master = master
self.icons = []
self.canvas = tk.Canvas(self)
self.scrollbar = ttk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
self.scrollable_frame = tk.Frame(self.canvas)
self.canvas.configure(yscrollcommand=self.scrollbar.set)
self.canvas.pack(side="left", fill="both")
self.scrollbar.pack(side="right", fill="y")
self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
self.scrollable_frame.bind("<Configure>", self.on_frame_configure)
# Bind mouse wheel event to scrollbar
self.master.bind_all("<MouseWheel>", self.on_mousewheel)
def add_icon(self, icon):
self.icons.append(icon)
row = (len(self.icons) - 1) // 4
col = (len(self.icons) - 1) % 4
icon.grid(row=row, column=col, padx=10, pady=10)
def clean(self):
for i in self.icons:
i.destroy()
def on_frame_configure(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def on_mousewheel(self, event):
self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
def mpkman() -> None:
chosed = tk.StringVar()
chosed.set('')
def impk():
installmpk(filedialog.askopenfilename(title=lang.text25, filetypes=((lang.text26, "*.mpk"),)))
list_pls()
class new_(Toplevel):
def __init__(self):
super().__init__()
jzxs(self)
self.title(lang.text115)
ttk.Label(self, text=lang.t19, font=(None, 25)).pack(fill=BOTH, expand=0, padx=10, pady=10)
ttk.Separator(self, orient=HORIZONTAL).pack(padx=10, pady=10, fill=X)
f1 = ttk.Frame(self)
ttk.Label(f1, text=lang.t20).pack(side=LEFT, padx=5, pady=5)
self.name = ttk.Entry(f1)
self.name.pack(padx=5, pady=5, side=LEFT)
f1.pack(padx=5, pady=5, fill=X)
f2 = ttk.Frame(self)
ttk.Label(f2, text=lang.t21).pack(side=LEFT, padx=5, pady=5)
self.aou = ttk.Entry(f2)
self.aou.pack(padx=5, pady=5, side=LEFT)
f2.pack(padx=5, pady=5, fill=X)
f3 = ttk.Frame(self)
ttk.Label(f3, text=lang.t22).pack(side=LEFT, padx=5, pady=5)
self.ver = ttk.Entry(f3)
self.ver.pack(padx=5, pady=5, side=LEFT)
f3.pack(padx=5, pady=5, fill=X)
f4 = ttk.Frame(self)
ttk.Label(f4, text=lang.t23).pack(side=LEFT, padx=5, pady=5)
self.dep = ttk.Entry(f4)
self.dep.pack(padx=5, pady=5, side=LEFT)
f4.pack(padx=5, pady=5, fill=X)
ttk.Label(self, text=lang.t24).pack(padx=5, pady=5, expand=1)
self.intro = Text(self)
self.intro.pack(fill=BOTH, padx=5, pady=5, expand=1)
ttk.Button(self, text=lang.text115, command=self.create).pack(fill=BOTH, side=BOTTOM)
def create(self):
data = {
"name": self.name.get(),
"author": self.aou.get(),
"version": self.ver.get(),
"identifier": (iden := v_code()),
"describe": self.intro.get(1.0, END),
"depend": self.dep.get()
}
self.destroy()
if not os.path.exists(moduledir + os.sep + iden):
os.makedirs(moduledir + os.sep + iden)
with open(moduledir + os.sep + iden + os.sep + "info.json", 'w+', encoding='utf-8', newline='\n') as js:
js.write(json.dumps(data))
list_pls()
editor_(iden)
def editor_(id_=None):
if not chosed.get():
messpop(lang.warn2)
return 1
if id_ is None:
id_ = globals()[chosed.get()]
path = "".join([moduledir, os.sep, id_, os.sep])
if not os.path.exists(path + "main.msh") and not os.path.exists(path + 'main.sh'):
if ask_win(lang.t18, 'SH', 'MSH') == 1:
s = "main.sh"
else:
s = "main.msh"
with open(path + s, 'w+', encoding='utf-8', newline='\n') as sh:
sh.write("echo MIO-KITCHEN")
editor.main(path + s)
else:
if os.path.exists(path + "main.msh"):
editor.main(path + "main.msh")
elif os.path.exists(path + 'main.sh'):
editor.main(path + 'main.sh')
class mpkrun:
def __init__(self, name):
self.name = name
def popup(self, event):
chosed.set(self.name)
rmenu2.post(event.x_root, event.y_root)
def run(self, event):
chosed.set(self.name)
run()
@cartoon
def export():
if not chosed.get():
messpop(lang.warn2)
return 1
with open("".join([moduledir, os.sep, (value := globals()[chosed.get()]), os.sep, "info.json"]),
'r',
encoding='UTF-8') as f:
data = json.load(f)
if "describe" in data:
des = data["describe"]
else:
des = ''
(info_ := ConfigParser())['module'] = {
'name': f'{data["name"]}',
'version': f'{data["version"]}',
'author': f'{data["author"]}',
'describe': f'{des}',
'resource': 'main.zip',
'identifier': f'{value}',
'depend': f'{data["depend"]}'
}
info_.write((buffer2 := StringIO()))
with zipfile.ZipFile((buffer := BytesIO()), 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as mpk:
os.chdir(moduledir + os.sep + value + os.sep)
for i in get_all_file_paths("."):
print(f"{lang.text1}:%s" % i.rsplit(".\\")[1])
try:
mpk.write(i)
except Exception as e:
print(lang.text2.format(i, e))
os.chdir(elocal)
with zipfile.ZipFile("".join([settings.path, os.sep, chosed.get(), ".mpk"]), 'w',
compression=zipfile.ZIP_DEFLATED, allowZip64=True) as mpk2:
mpk2.writestr('main.zip', buffer.getvalue())
mpk2.writestr('info', buffer2.getvalue())
if os.path.exists(settings.path + os.sep + chosed.get() + ".mpk"):
print(lang.t15 % (settings.path + os.sep + chosed.get() + ".mpk"))
else:
print(lang.t16 % (settings.path + os.sep + chosed.get() + ".mpk"))
def popup(event):
rmenu.post(event.x_root, event.y_root) # post在指定的位置显示弹出菜单
moduledir = "".join([elocal, os.sep, "bin", os.sep, "module"])
file = StringVar()
def list_pls():
try:
pls.clean()
for i in os.listdir(moduledir):
if os.path.isdir(moduledir + os.sep + i):
with open("".join([moduledir, os.sep, i, os.sep, "info.json"]), 'r', encoding='UTF-8') as f:
data = json.load(f)
icon = tk.Label(pls.scrollable_frame, text=data['name'], width=10, height=5, bg="#4682B4",
wraplength=70, justify='center')
icon.bind('<Double-Button-1>', mpkrun(data['name']).run)
icon.bind('<Button-3>', mpkrun(data['name']).popup)
pls.add_icon(icon)
globals()[data['name']] = data['identifier']
except:
return 1
class msh_parse(object):
envs = {'version': settings.version,
'tool_bin': f'{elocal}{os.sep}bin{os.sep}{platform.system()}{os.sep}{platform.machine()}{os.sep}'.replace(
'\\',
'/'),
'project': (settings.path + os.sep + dn.get()).replace('\\', '/'),
'moddir': moduledir.replace('\\', '/')}
def __init__(self, sh):
self.envs['bin'] = os.path.dirname(sh.replace('\\', '/'))
with open(sh, 'r+', encoding='utf-8', newline='\n') as shell:
for i in shell.readlines():
for key, value in self.envs.items():
i = i.replace('@{}@'.format(key), value).strip()
try:
if i[:1] != "#" and i not in ["", '\n']:
if i.split()[0] == "if":
self.sif(i.split()[1], i.split()[2], shlex.split(i)[3])
elif i.split()[0] == "for":
self.sfor(i.split()[1], shlex.split(i)[3], shlex.split(i)[4])
else:
getattr(self, i.split()[0])(i[i.index(" ") + 1:])
except AttributeError as e:
print("未知的参数或命令:%s\n错误:%s" % (i, str(e).replace("msh_parse", 'MSH解释器')))
except ModuleError as e:
print("异常:%s" % e)
return
except Exception as e:
print("运行错误:%s\n错误:%s" % (i, e))
except:
print("运行错误:%s" % i)
self.envs.clear()
def set(self, cmd):
try:
vn, va = cmd.split()
except Exception as e:
print("赋值异常:%s\n语句:%s" % (e, cmd))
return 1
self.envs[vn] = va
def run_ex(self, cmd):
try:
vn, va = shlex.split(cmd)
except Exception as e:
print("运行异常:%s\n语句:run_ma %s" % (e, cmd))
return 1
try:
getattr(extra, vn)(va.split())
except:
print("调用失败! %s " % va)
@staticmethod
def echo(cmd):
print(cmd)
@staticmethod
def gettype(file_):
gettype(file_)
def sfor(self, vn, vs, do):
if ',' in vs:
fgf = ','
else:
fgf = None
for v in vs.split(fgf):
getattr(self, (do_ := do.replace(f'@{vn}@', v)).split()[0])(do_[do_.index(' ') + 1:])
@staticmethod
def rmdir(path):
rmdir(path.strip(), up=1)
@staticmethod
def run(cmd):
call(exe=str(cmd), kz='N', shstate=True)
@staticmethod
def packsuper(cmd):
try:
sparse, dbfz, size, set_, lb = shlex.split(cmd)
except:
raise ModuleError("打包SUPER参数异常")
(supers := IntVar()).set(int(size))
(ssparse := IntVar()).set(int(sparse))
(supersz := IntVar()).set(int(set_))
(sdbfz := StringVar()).set(dbfz)
packsuper(sparse=ssparse, dbfz=sdbfz, size=supers, set_=supersz, lb=lb)
def sh(self, cmd):
with open(file_ := ("".join([elocal, os.sep, "bin", os.sep, "temp", os.sep])) + v_code(), "w",
encoding='UTF-8',
newline="\n") as f:
for i in self.envs:
f.write(f'export {i}={self.envs[i]}\n')
f.write("source $1")
if os.path.exists(file_):
if os.name == 'posix':
sh = "ash"
else:
sh = "bash"
call("busybox {} {} {}".format(sh, file_, cmd.replace('\\', '/')))
try:
os.remove(file_)
except:
pass
def msh(self, cmd):
try:
cmd_, argv = cmd.split()
except Exception:
raise ModuleError("MSH解释器: 不支持的命令 %s" % cmd)
if cmd_ == 'run':
if not os.path.exists(argv.replace("\\", '/')):
print("脚本不存在:%s" % argv)
return 1
else:
print("开始执行:%s" % os.path.basename(argv))
self.__init__(argv)
print("执行完成:%s" % os.path.basename(argv))
else:
print('-------\nMSH解释器\n-------\n用法:\nmsh run [script]')
@staticmethod
def exit(value):
raise ModuleError(value)
def sif(self, mode, var_, other):
modes = {
'exist': lambda var: os.path.exists(var),
'!exist': lambda var: not os.path.exists(var),
'equ': lambda var: var.split('--')[0] == var.split('--')[1],
'!equ': lambda var: var.split('--')[0] != var.split('--')[1],
'gettype': lambda var: gettype(var.split('--')[0]) == var.split('--')[1],
'!gettype': lambda var: gettype(var.split('--')[0]) != var.split('--')[1]
}
if modes[mode](var_):
getattr(self, other.split()[0])(other[other.index(' ') + 1:])
class parse(Toplevel):
gavs = {}
def __init__(self, jsons, msh=False):
super().__init__()
self.value = []
def callcmd(cmd):
if cmd.split()[0] == "msg":
messagebox.showinfo(cmd.split()[1], cmd.split()[2])
elif cmd.split()[0] == "start":
cz(call(cmd[cmd.index(' ') + 1:], 'N'))
elif cmd.split()[0] == "exec":
exec(cmd[cmd.index(' ') + 1:])
else:
print(lang.text27, cmd)
def generate_sh():
sh_content = ""
for va in self.value:
if gva := self.gavs[va].get():
if gva is str and os.path.isabs(gva) and os.name == 'nt':
if os.sep in gva:
gva = gva.replace(os.sep, '/')
sh_content += f"export {va}='{gva}'\n"
temp = elocal + os.sep + "bin" + os.sep + "temp" + os.sep
if not os.path.exists(temp):
re_folder(temp)
file.set(temp + v_code())
with open(file.get(), "w", encoding='UTF-8', newline="\n") as f:
f.write(sh_content)
f.write('export version={}\n'.format(settings.version))
f.write('export tool_bin={}\n'.format(
f'{elocal}{os.sep}bin{os.sep}{platform.system()}{os.sep}{platform.machine()}{os.sep}'.replace(
'\\', '/')))
f.write('export moddir={}\n'.format(moduledir.replace('\\', '/')))
f.write(
"export project={}\nsource $1".format((settings.path + os.sep + dn.get()).replace('\\', '/')))
self.destroy()
self.gavs.clear()
self.value.clear()
def generate_msh():
for va in self.value:
if gva := self.gavs[va].get():
if gva is str and os.path.isabs(gva) and os.name == 'nt':
if '\\' in gva:
msh_parse.envs[va] = gva.replace("\\", '/')
else:
msh_parse.envs[va] = gva
else:
msh_parse.envs[va] = gva
self.destroy()
self.gavs.clear()
self.value.clear()
with open(jsons, 'r', encoding='UTF-8') as f:
try:
data = json.load(f)
except Exception as e:
messpop(lang.text133 + str(e))
print(lang.text133 + str(e))
self.destroy()
self.title(data['main']['info']['title'])
# 设置窗口大小和位置
height = data['main']['info']['height']
width = data['main']['info']['weight']
if height != 'none' and width != 'none':
self.geometry(f"{width}x{height}")
resizable = data['main']['info']['resize']
try:
self.attributes('-topmost', 'true')
except:
pass
if resizable == '1':
self.resizable(True, True)
else:
self.resizable(False, False)
for group_name, group_data in data['main'].items():
if group_name != "info":
group_frame = ttk.LabelFrame(self, text=group_data['title'])
group_frame.pack(padx=10, pady=10)
for con in group_data['controls']:
if 'set' in con:
self.value.append(con['set'])
if con["type"] == "text":
text_label = ttk.Label(group_frame, text=con['text'],
font=(None, int(con['fontsize'])))
text_label.pack(side=con['side'], padx=5, pady=5)
elif con["type"] == "button":
button_command = con['command']
button = ttk.Button(group_frame, text=con['text'],
command=lambda: callcmd(button_command))
button.pack(side='left')
elif con["type"] == "filechose":
ft = ttk.Frame(group_frame)
ft.pack(fill=X)
file_var_name = con['set']
self.gavs[file_var_name] = StringVar()
file_label = ttk.Label(ft, text=con['text'])
file_label.pack(side='left', padx=10, pady=10)
file_entry = ttk.Entry(ft, textvariable=self.gavs[file_var_name])
file_entry.pack(side='left', padx=5, pady=5)
file_button = ttk.Button(ft, text=lang.text28,
command=lambda: self.gavs[file_var_name].set(
filedialog.askopenfilename()))
file_button.pack(side='left', padx=10, pady=10)
elif con["type"] == "radio":
radio_var_name = con['set']
self.gavs[radio_var_name] = StringVar()
options = con['opins'].split()
pft1 = ttk.Frame(group_frame)
pft1.pack(padx=10, pady=10)
for option in options:
text, value = option.split('|')
self.gavs[radio_var_name].set(value)
ttk.Radiobutton(pft1, text=text, variable=self.gavs[radio_var_name],
value=value).pack(side=con['side'])
elif con["type"] == 'input':
input_frame = Frame(group_frame)
input_frame.pack(fill=X)
input_var_name = con['set']
self.gavs[input_var_name] = StringVar()
if 'text' in con:
ttk.Label(input_frame, text=con['text']).pack(side=LEFT, padx=5, pady=5, fill=X)
ttk.Entry(input_frame, textvariable=self.gavs[input_var_name]).pack(side=LEFT, pady=5,
padx=5,
fill=X)
elif con['type'] == 'checkbutton':
b_var_name = con['set']
self.gavs[b_var_name] = IntVar()
if 'text' not in con:
text = 'M.K.C'
else:
text = con['text']
ttk.Checkbutton(group_frame, text=text, variable=self.gavs[b_var_name], onvalue=1,
offvalue=0,
style="Switch.TCheckbutton").pack(
padx=5, pady=5, fill=BOTH)
else:
print(lang.warn14.format(con['type']))
if msh:
ttk.Button(self, text=lang.ok, command=lambda: cz(generate_msh)).pack(fill=X, side='bottom')
else:
ttk.Button(self, text=lang.ok, command=lambda: cz(generate_sh)).pack(fill=X, side='bottom')
jzxs(self)
self.wait_window()
@cartoon
def run():
if not dn.get():
print(lang.warn1)
return
if chosed.get():
value = globals()[chosed.get()]
else:
value = ""
if value:
if os.path.exists(moduledir + os.sep + value + os.sep + "main.sh") or os.path.exists(
moduledir + os.sep + value + os.sep + "main.msh"):
if os.path.exists(moduledir + os.sep + value + os.sep + "main.json"):
parse(moduledir + os.sep + value + os.sep + "main.json",
(os.path.exists(moduledir + os.sep + value + os.sep + "main.msh")))
if os.path.exists(moduledir + os.sep + value + os.sep + "main.sh"):
if os.path.exists(file.get()):
if os.name == 'posix':
sh = "ash"
else:
sh = "bash"
call("busybox {} {} {}".format(sh, file.get(),
(moduledir + os.sep + value + os.sep + "main.sh").replace(
'\\',
'/')))
os.remove(file.get())
elif os.path.exists("".join([moduledir, os.sep, value, os.sep, "main.msh"])):
msh_parse("".join([moduledir, os.sep, value, os.sep, "main.msh"]))
else:
if os.path.exists("".join([moduledir, os.sep, value, os.sep, "main.sh"])):
if not os.path.exists(temp := "".join([elocal, os.sep, "bin", os.sep, "temp", os.sep])):
re_folder(temp)
if not file.get():
file.set(temp + os.sep + v_code())
with open(file.get(), "w", encoding='UTF-8', newline="\n") as f:
f.write('export tool_bin={}\n'.format(
f'{elocal}{os.sep}bin{os.sep}{platform.system()}{os.sep}{platform.machine()}{os.sep}'.replace(
'\\',
'/')))
f.write('export version={}\n'.format(settings.version))
f.write('export moddir={}\n'.format(moduledir.replace('\\', '/')))
f.write(
"export project={}\nsource $1".format(
(settings.path + os.sep + dn.get()).replace('\\', '/')))
if os.path.exists(file.get()):
if os.name == 'posix':
sh = "ash"
else:
sh = "bash"
call("busybox {} {} {}".format(sh, file.get(),
(
moduledir + os.sep + value + os.sep + "main.sh").replace(
'\\',
'/')))
os.remove(file.get())
elif os.path.exists(msh_tmp := moduledir + os.sep + value + os.sep + "main.msh"):
msh_parse(msh_tmp)
else:
if not os.path.exists(moduledir + os.sep + value):
messpop(lang.warn7.format(value))
list_pls()
win.tab7.lift()
else:
print(lang.warn8)
else:
print(lang.warn2)
class unmpk:
def __init__(self):
self.arr = []
self.arr2 = []
if chosed.get():
self.value = globals()[chosed.get()]
self.value2 = chosed.get()
self.lfdep()
self.ask()
else:
messpop(lang.warn2)
def ask(self):
self.ck = Toplevel()
try:
self.ck.attributes('-topmost', 'true')
except:
pass
self.ck.title(lang.t6)
jzxs(self.ck)
ttk.Label(self.ck, text=lang.t7 % self.value2, font=(None, 30)).pack(padx=10, pady=10, fill=BOTH,
expand=True)
if self.arr2:
ttk.Separator(self.ck, orient=HORIZONTAL).pack(padx=10, pady=10, fill=X)
ttk.Label(self.ck, text=lang.t8, font=(None, 15)).pack(padx=10, pady=10, fill=BOTH,
expand=True)
te = Listbox(self.ck, highlightthickness=0, activestyle='dotbox')
for i in self.arr2:
te.insert("end", i)
te.pack(fill=BOTH, padx=10, pady=10)
ttk.Button(self.ck, text=lang.ok, command=self.unloop).pack(fill=X, expand=True, side=LEFT, pady=10,
padx=10)
ttk.Button(self.ck, text=lang.cancel, command=self.ck.destroy).pack(fill=X, expand=True, side=LEFT,
pady=10,
padx=10)
def lfdep(self, name=None):
if not name:
name = self.value
for i in [i for i in os.listdir(moduledir) if os.path.isdir(moduledir + os.sep + i)]:
with open("".join([moduledir, os.sep, i, os.sep, "info.json"]), 'r', encoding='UTF-8') as f:
data = json.load(f)
for n in data['depend'].split():
if name == n:
self.arr.append(i)
self.arr2.append(data['name'])
self.lfdep(i)
break
self.arr = sorted(set(self.arr), key=self.arr.index)
self.arr2 = sorted(set(self.arr2), key=self.arr2.index)
def unloop(self):
self.ck.destroy()
for i in self.arr:
self.umpk(i)
self.umpk(self.value)
@staticmethod
def umpk(name=None) -> None:
if name:
print(lang.text29.format(name))
if os.path.exists(moduledir + os.sep + name):
try:
rmtree(moduledir + os.sep + name)
except PermissionError as e:
print(e)
if os.path.exists(moduledir + os.sep + name):
messpop(lang.warn9, 'red')
else:
print(lang.text30)
try:
list_pls()
except:
pass
else:
messpop(lang.warn2)
title = ttk.Label(win.tab7, text=lang.text19, font=("宋体", 20))
title.pack(padx=10, pady=10, fill=BOTH)
ttk.Separator(win.tab7, orient=HORIZONTAL).pack(padx=10, pady=10, fill=X)
Label(win.tab7, text=lang.text24).pack(padx=5, pady=5)
pls = IconGrid(win.tab7)
lf1 = Frame(win.tab7)
pls.pack(padx=5, pady=5, fill=BOTH, side=LEFT, expand=True)
pls.canvas.bind('<Button-3>', popup)
pls.bind('<Button-3>', popup)
rmenu = Menu(pls, tearoff=False, borderwidth=0)
rmenu.add_command(label=lang.text21, command=lambda: cz(impk))
rmenu.add_command(label=lang.text23, command=lambda: cz(list_pls))
rmenu.add_command(label=lang.text115, command=lambda: cz(new_))
rmenu2 = Menu(pls, tearoff=False, borderwidth=0)
rmenu2.add_command(label=lang.text20, command=lambda: cz(unmpk))
rmenu2.add_command(label=lang.text22, command=lambda: cz(run))
rmenu2.add_command(label=lang.t14, command=lambda: cz(export))
rmenu2.add_command(label=lang.t17, command=lambda: cz(editor_))
try:
list_pls()
except:
pass
lf1.pack(padx=10, pady=10)
class installmpk(Toplevel):
def __init__(self, mpk):
super().__init__()
self.mconf = ConfigParser()
if not mpk:
messpop(lang.warn2)
self.destroy()
return
self.title(lang.text31)
self.resizable(False, False)
with zipfile.ZipFile(mpk, 'r') as myfile:
with myfile.open('info') as info_file:
self.mconf.read_string(info_file.read().decode('utf-8'))
try:
with myfile.open('icon') as myfi:
try:
pyt = ImageTk.PhotoImage(Image.open(BytesIO(myfi.read())))
except Exception as e:
print(e)
pyt = ImageTk.PhotoImage(Image.open(elocal + os.sep + "images" + os.sep + "none"))
except:
pyt = ImageTk.PhotoImage(Image.open("".join([elocal, os.sep, "bin", os.sep, "images", os.sep, "none"])))
with myfile.open('%s' % (self.mconf.get('module', 'resource')), 'r') as inner_file:
self.inner_zipdata = inner_file.read()
self.inner_filenames = zipfile.ZipFile(BytesIO(self.inner_zipdata)).namelist()
Label(self, image=pyt).pack(padx=10, pady=10)
Label(self, text="%s" % (self.mconf.get('module', 'name')), font=('黑体', 14)).pack(padx=10, pady=10)
Label(self, text=lang.text32.format((self.mconf.get('module', 'version'))), font=('黑体', 12)).pack(padx=10,
pady=10)
Label(self, text=lang.text33.format((self.mconf.get('module', 'author'))), font=('黑体', 12)).pack(padx=10,
pady=10)
text = Text(self)
text.insert("insert", "%s" % (self.mconf.get('module', 'describe')))
text.pack(padx=10, pady=10)
self.prog = ttk.Progressbar(self, length=200, mode='determinate', orient=HORIZONTAL, maximum=100, value=0)
self.prog.pack()
self.state = Label(self, text=lang.text40, font=('黑体', 12))
self.state.pack(padx=10, pady=10)
self.installb = ttk.Button(self, text=lang.text41, command=lambda: cz(self.install))
self.installb.pack(padx=10, pady=10, expand=True, fill=X)
jzxs(self)
self.wait_window()
def install(self):
if self.installb.cget('text') == lang.text34:
self.destroy()
return True
self.installb.config(state=DISABLED)
try:
supports = self.mconf.get('module', 'supports').split()
except:
supports = [sys.platform]
if sys.platform not in supports:
self.state['text'] = lang.warn15.format(sys.platform)
return False
for dep in self.mconf.get('module', 'depend').split():
if not os.path.isdir("".join([elocal, os.sep, "bin", os.sep, "module", os.sep, dep])):
self.state['text'] = lang.text36 % (self.mconf.get('module', 'name'), dep, dep)
self.installb['text'] = lang.text37
self.installb.config(state='normal')
return False
if os.path.exists(
"".join([elocal, os.sep, "bin", os.sep, "module", os.sep, self.mconf.get('module', 'identifier')])
):
rmtree("".join([elocal, os.sep, "bin", os.sep, "module", os.sep, self.mconf.get('module', 'identifier')]))
fz = zipfile.ZipFile(BytesIO(self.inner_zipdata), 'r')
uncompress_size = sum((file.file_size for file in fz.infolist()))
extracted_size = 0
for file in self.inner_filenames:
try:
file = str(file).encode('cp437').decode('gbk')
except:
file = str(file).encode('utf-8').decode('utf-8')
info = fz.getinfo(file)
extracted_size += info.file_size
self.state['text'] = lang.text38.format(file)
fz.extract(file,
"".join(
[elocal, os.sep, "bin", os.sep, "module", os.sep, self.mconf.get('module', 'identifier')]))
self.prog['value'] = extracted_size * 100 / uncompress_size
try:
depends = self.mconf.get('module', 'depend')
except:
depends = ''
minfo = {"name": "%s" % (self.mconf.get('module', 'name')),
"author": "%s" % (self.mconf.get('module', 'author')),
"version": "%s" % (self.mconf.get('module', 'version')),
"identifier": "%s" % (self.mconf.get('module', 'identifier')),
"describe": "%s" % (self.mconf.get('module', 'describe')),
"depend": "%s" % depends}
with open("".join([elocal, os.sep, "bin", os.sep, "module", os.sep, self.mconf.get('module', 'identifier'),
os.sep, "info.json"]),
'w') as f:
json.dump(minfo, f, indent=2)
self.state['text'] = lang.text39
self.installb['text'] = lang.text34
self.installb.config(state='normal')
class packxx(object):
def __init__(self, list_):
if not list_:
return
self.dbfs = StringVar()
self.dbgs = StringVar()
self.edbgs = StringVar()
self.scale = IntVar()
self.scale_erofs = IntVar()
self.spatchvb = IntVar()
self.delywj = IntVar()
self.lg = list_
self.ck = subp(com=1, title=lang.text42)
lf1 = ttk.LabelFrame(self.ck, text=lang.text43)
lf1.pack(fill=BOTH, padx=5, pady=5)
lf2 = ttk.LabelFrame(self.ck, text=lang.text44)
lf2.pack(fill=BOTH, padx=5, pady=5)
lf3 = ttk.LabelFrame(self.ck, text=lang.text45)
lf3.pack(fill=BOTH, padx=5, pady=5)
lf4 = ttk.LabelFrame(self.ck, text=lang.text46)
lf4.pack(fill=BOTH, pady=5, padx=5)
(sf1 := Frame(lf3)).pack(fill=X, padx=5, pady=5, side=TOP)
self.scale.set(0)
Label(lf1, text=lang.text48).pack(side='left', padx=5, pady=5)
dbfss = ttk.Combobox(lf1, state="readonly", textvariable=self.dbfs)
dbfss.pack(side='left', padx=5, pady=5)
dbfss['value'] = ("make_ext4fs", "mke2fs+e2fsdroid")
Label(lf3, text=lang.text49).pack(side='left', padx=5, pady=5)
dbgss = ttk.Combobox(lf3, state="readonly", textvariable=self.dbgs, values=("raw", "sparse", "br", "dat"))
dbgss.pack(padx=5, pady=5, side='left')
Label(lf2, text=lang.text50).pack(side='left', padx=5, pady=5)
edbgss = ttk.Combobox(lf2, state="readonly", textvariable=self.edbgs)
edbgss.pack(side='left', padx=5, pady=5)
edbgss['value'] = ("lz4", "lz4hc", "lzma", "deflate")
# --
scales_erofs = ttk.Scale(lf2, from_=0, to=9, orient="horizontal", command=self.update_label_erofs,
variable=self.scale_erofs)
self.label_e = tk.Label(lf2, text=lang.t30.format(int(scales_erofs.get())))
self.label_e.pack(side='left', padx=5, pady=5)
scales_erofs.pack(fill="x", padx=5, pady=5)
# --
scales = ttk.Scale(sf1, from_=0, to=9, orient="horizontal", command=self.update_label, variable=self.scale)
self.label = tk.Label(sf1, text=lang.text47.format(int(scales.get())))
self.label.pack(side='left', padx=5, pady=5)
scales.pack(fill="x", padx=5, pady=5)
ttk.Checkbutton(lf3, text=lang.text52, variable=self.spatchvb, onvalue=1, offvalue=0,
style="Switch.TCheckbutton").pack(
padx=5, pady=5, fill=BOTH)
ttk.Checkbutton(lf3, text=lang.t11, variable=self.delywj, onvalue=1, offvalue=0,
style="Switch.TCheckbutton").pack(
padx=5, pady=5, fill=BOTH)
dbfss.current(0)
dbgss.current(0)
edbgss.current(0)
ttk.Button(self.ck, text=lang.pack, command=lambda: cz(self.start_)).pack(side='left', padx=2, pady=2,
fill=X,
expand=True)
ttk.Button(self.ck, text=lang.cancel, command=lambda: subp(com=0, master=self.ck)).pack(side='left', padx=2,
pady=2,
fill=X,
expand=True)
def update_label(self, value):
self.label.config(text=lang.text47.format(int(float(value))))
def update_label_erofs(self, value):
self.label_e.config(text=lang.t30.format(int(float(value))))
def start_(self):
lg = self.lg
subp(com=0, master=self.ck)
packrom(self.edbgs, self.dbgs, self.dbfs, self.scale, lg, self.spatchvb, self.delywj.get(),
int(self.scale_erofs.get()))
class dbkxyt:
def __init__(self):
if not dn.get():
messpop(lang.warn1)
return
if os.path.exists((dir_ := rwork()) + "firmware-update"):
os.rename(dir_ + "firmware-update", dir_ + "images")
if not os.path.exists(dir_ + "images"):
os.makedirs(dir_ + 'images')
if os.path.exists(dir_ + 'META-INF'):
rmdir(dir_ + 'META-INF')
zipfile.ZipFile(elocal + os.sep + "bin" + os.sep + "extra_flash.zip").extractall(dir_)
right_device = input_(lang.t26, 'olive')
with open(dir_ + "bin" + os.sep + "right_device", 'w', encoding='gbk') as rd:
rd.write(right_device + "\n")
with open(
dir_ + 'META-INF' + os.sep + "com" + os.sep + "google" + os.sep + "android" + os.sep + "update-binary",
'r+', encoding='utf-8', newline='\n') as script:
lines = script.readlines()
lines.insert(45, f'right_device="{right_device}"\n')
for t in os.listdir(dir_ + "images"):
if t.endswith('.img') and not os.path.isdir(dir_ + t):
print("Add Flash method {} to update-binary".format(t))
if os.path.getsize(os.path.join(dir_ + 'images', t)) > 209715200:
self.zstd_compress(os.path.join(dir_ + 'images', t))
lines.insert(70,
'package_extract_zstd "images/{}.zst" "/dev/block/by-name/{}"\n'.format(t, t[:-4]))
else:
lines.insert(70, 'package_extract_file "images/{}" "/dev/block/by-name/{}"\n'.format(t, t[:-4]))
for t in os.listdir(dir_):
if not t.startswith("preloader_") and not os.path.isdir(dir_ + t) and t.endswith('.img'):
print("Add Flash method {} to update-binary".format(t))
if os.path.getsize(dir_ + t) > 209715200:
self.zstd_compress(dir_ + t)
move(os.path.join(dir_, t + ".zst"), os.path.join(dir_ + "images", t + ".zst"))
lines.insert(70,
'package_extract_zstd "images/{}.zst" "/dev/block/by-name/{}"\n'.format(t, t[:-4]))
else:
lines.insert(70, 'package_extract_file "images/{}" "/dev/block/by-name/{}"\n'.format(t, t[:-4]))
move(os.path.join(dir_, t), os.path.join(dir_ + "images", t))
script.seek(0)
script.truncate()
script.writelines(lines)
def zstd_compress(self, path):
if os.path.exists(path):
if gettype(path) == "sparse":
print(f"[INFO] {os.path.basename(path)} is (sparse), converting to (raw)")
utils.simg2img(path)
try:
print(f"[Compress] {os.path.basename(path)}...")
call("zstd -5 --rm {} -o {}".format(path, path + ".zst"))
except Exception as e:
print(f"[Fail] Compress {os.path.basename(path)} Fail:{e}")
class packss:
def __init__(self):
supers = IntVar()
ssparse = IntVar()
supersz = IntVar()
sdbfz = StringVar()
scywj = IntVar()
(lf1 := ttk.LabelFrame((ck := subp(com=1, title=lang.text53)), text=lang.text54)).pack(fill=BOTH)
(lf2 := ttk.LabelFrame(ck, text=lang.settings)).pack(fill=BOTH)
(lf3 := ttk.LabelFrame(ck, text=lang.text55)).pack(fill=BOTH)
supersz.set(1)
# 自动设置
ttk.Radiobutton(lf1, text="A-only", variable=supersz, value=1).pack(side='left', padx=10, pady=10)
ttk.Radiobutton(lf1, text="Virtual-ab", variable=supersz, value=2).pack(side='left', padx=10, pady=10)
ttk.Radiobutton(lf1, text="A/B", variable=supersz, value=3).pack(side='left', padx=10, pady=10)
Label(lf2, text=lang.text56).pack(side='left', padx=10, pady=10)
(sdbfzs := ttk.Combobox(lf2, textvariable=sdbfz)).pack(side='left', padx=10, pady=10, fill='both')
sdbfzs['value'] = ("qti_dynamic_partitions", "main")
sdbfzs.current(0)
Label(lf2, text=lang.text57).pack(side='left', padx=10, pady=10)
supers.set(9126805504)
(ttk.Entry(lf2, textvariable=supers)).pack(side='left', padx=10, pady=10)
(tl := Listbox(lf3, selectmode=MULTIPLE, activestyle='dotbox')).config(highlightthickness=0)
work = rwork()
for file_name in os.listdir(work):
if file_name.endswith(".img"):
if gettype(work + file_name) in ["ext", "erofs"]:
tl.insert(END, file_name[:-4])
tl.pack(padx=10, pady=10, fill=BOTH)
ttk.Checkbutton(ck, text=lang.text58, variable=ssparse, onvalue=1, offvalue=0,
style="Switch.TCheckbutton").pack(
padx=10, pady=10, fill=BOTH)
t_Frame = Frame(ck)
ttk.Checkbutton(t_Frame, text=lang.t11, variable=scywj, onvalue=1, offvalue=0,
style="Switch.TCheckbutton").pack(side=LEFT,
padx=10, pady=10, fill=BOTH)
g_b = ttk.Button(t_Frame, text=lang.t27, command=lambda: cz(generate))
g_b.pack(side=LEFT, padx=10, pady=10, fill=BOTH)
t_Frame.pack(fill=X)
def read_list():
if os.path.exists(work + "dynamic_partitions_op_list"):
try:
data = utils.dynamic_list_reader(work + "dynamic_partitions_op_list")
except:
return
if len(data) > 1:
fir, sec = data
if fir[:-2] == sec[:-2]:
sdbfz.set(fir[:-2])
supersz.set(2)
supers.set(int(data[fir]['size']))
else:
dbfz, = data
sdbfz.set(dbfz)
supers.set(int(data[dbfz]['size']))
supersz.set(1)
def versize():
size = 0
for i in [tl.get(index) for index in tl.curselection()]:
size += os.path.getsize(work + i + ".img")
if size > supers.get() + 409600:
supers.set(size + 4096000)
return False
else:
return True
def generate():
g_b.config(text=lang.t28, state='disabled')
utils.generate_dynamic_list(dbfz=sdbfz.get(), size=supers.get(), set_=supersz.get(),
lb=[tl.get(index) for index in tl.curselection()], work=rwork())
g_b.config(text=lang.text34)
time.sleep(1)
g_b.config(text=lang.t27, state='normal')
def start_():
try:
supers.get()
except:
supers.set(0)
if not versize():
ask_win(lang.t10)
return False
lbs = [tl.get(index) for index in tl.curselection()]
sc = scywj.get()
subp(com=0, master=ck)
packsuper(sparse=ssparse, dbfz=sdbfz, size=supers, set_=supersz, lb=lbs, del_=sc)
ttk.Button(ck, text=lang.pack, command=lambda: cz(start_)).pack(side='left',
padx=5,
pady=5, fill=X, expand=True)
ttk.Button(ck, text=lang.cancel, command=lambda: subp(com=0, master=ck)).pack(side='left', padx=10, pady=10,
fill=X,
expand=True)
read_list()
@cartoon
def packsuper(sparse, dbfz, size, set_, lb, del_=0, return_cmd=0):
if not dn.get():
messpop(lang.warn1)
return False
work = rwork()
command = "lpmake --metadata-size 65536 -super-name super -metadata-slots "
if set_.get() == 1:
command += "2 -device super:%s --group %s:%s " % (size.get(), dbfz.get(), size.get())
for part in lb:
command += "--partition %s:readonly:%s:%s --image %s=%s.img " % (
part, os.path.getsize(work + part + ".img"), dbfz.get(), part, work + part)
else:
command += "3 -device super:%s --group %s_a:%s " % (size.get(), dbfz.get(), size.get())
for part in lb:
command += "--partition %s_a:readonly:%s:%s_a --image %s_a=%s.img " % (
part, os.path.getsize(work + part + ".img"), dbfz.get(), part, work + part)
command += "--group %s_b:%s " % (dbfz.get(), size.get())
for part in lb:
command += "--partition %s_b:readonly:0:%s_b " % (part, dbfz.get())
if set_.get() == 2:
command += "--virtual-ab "
if sparse.get() == 1:
command += "--sparse "
command += " --out %s" % (work + "super.img")
if return_cmd == 1:
return command
if call(command) == 0:
if os.access(work + "super.img", os.F_OK):
print(lang.text59 % (work + "super.img"))
if del_ == 1:
for img in lb:
if os.path.exists(work + img + ".img"):
try:
os.remove(work + img + ".img")
except Exception as e:
print(e)
else:
messpop(lang.warn10)
else:
messpop(lang.warn10)
class StdoutRedirector(object):
def __init__(self, text_widget):
self.text_space = text_widget
def write(self, string):
self.text_space.insert(END, string)
self.text_space.yview('end')
def flush(self):
pass
def close(self):
pass
def __exit__(self):
pass
def call(exe, kz='Y', out=0, shstate=False, sp=0):
if kz == "Y":
cmd = f'{elocal}{os.sep}bin{os.sep}{platform.system()}{os.sep}{platform.machine()}{os.sep}{exe}'
else:
cmd = exe
if os.name != 'posix':
conf = subprocess.CREATE_NO_WINDOW
else:
if sp == 0:
cmd = cmd.split()
conf = 0
try:
ret = subprocess.Popen(cmd, shell=shstate, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, creationflags=conf)
for i in iter(ret.stdout.readline, b""):
if out == 0:
print(i.decode("utf-8", "ignore").strip())
except subprocess.CalledProcessError as e:
for i in iter(e.stdout.readline, b""):
if out == 0:
print(e.decode("utf-8", "ignore").strip())
ret.wait()
return ret.returncode
def download_file():
var1 = IntVar()
down = win.getframe(lang.text61 + os.path.basename(url := input_(title=lang.text60)))
messpop(lang.text62, "green")
progressbar = tk.ttk.Progressbar(down, length=200, mode="determinate")
progressbar.pack(padx=10, pady=10)
var1.set(0)
ttk.Label(down, textvariable=(jd := StringVar())).pack(padx=10, pady=10)
c1 = ttk.Checkbutton(down, text=lang.text63, variable=var1, onvalue=1, offvalue=0)
c1.pack(padx=10, pady=10)
start_time = time.time()
try:
response = requests.Session().head(url)
file_size = int(response.headers.get("Content-Length", 0))
response = requests.Session().get(url, stream=True, verify=False)
with open(settings.path + os.sep + os.path.basename(url), "wb") as f:
chunk_size = 2048576
bytes_downloaded = 0
for data in response.iter_content(chunk_size=chunk_size):
f.write(data)
bytes_downloaded += len(data)
elapsed = time.time() - start_time
speed = bytes_downloaded / (1024 * elapsed)
percentage = int(bytes_downloaded * 100 / file_size)
progressbar["value"] = percentage
jd.set(lang.text64.format(str(percentage), str(speed), str(bytes_downloaded), str(file_size)))
progressbar.update()
print(lang.text65.format(os.path.basename(url), str(elapsed)))
down.destroy()
if var1.get() == 1:
unpackrom(settings.path + os.sep + os.path.basename(url))
os.remove(settings.path + os.sep + os.path.basename(url))
except Exception as e:
print(lang.text66, str(e))
try:
os.remove(os.path.basename(url))
except:
if os.access(os.path.basename(url), os.F_OK):
print(lang.text67 + os.path.basename(url))
else:
try:
down.destroy()
except Exception as e:
messpop("%s" % e)
messpop(lang.text68, "red")
@cartoon
def jboot(bn: str = 'boot'):
if not (boot := findfile(f"{bn}.img", (work := rwork()))):
print(lang.warn3.format(bn))
return
if not os.path.exists(boot):
messpop(lang.warn3.format(bn))
return
if os.path.exists(work + f"{bn}"):
if rmdir((work + f"{bn}")) != 0:
print(lang.text69)
return
re_folder(work + f"{bn}")
os.chdir(work + f"{bn}")
if call("magiskboot unpack -h %s" % boot) != 0:
print("Unpack %s Fail..." % boot)
os.chdir(elocal)
rmtree((work + f"{bn}"))
return
if os.access(work + f"{bn}" + os.sep + "ramdisk.cpio", os.F_OK):
comp = gettype(work + f"{bn}" + os.sep + "ramdisk.cpio")
print("Ramdisk is %s" % comp)
with open(work + f"{bn}" + os.sep + "comp", "w") as f:
f.write(comp)
if comp != "unknow":
os.rename(work + f"{bn}" + os.sep + "ramdisk.cpio",
work + f"{bn}" + os.sep + "ramdisk.cpio.comp")
if call("magiskboot decompress %s %s" % (
work + f"{bn}" + os.sep + "ramdisk.cpio.comp",
work + f"{bn}" + os.sep + "ramdisk.cpio")) != 0:
print("Decompress Ramdisk Fail...")
return
if not os.path.exists(work + f"{bn}" + os.sep + "ramdisk"):
os.mkdir(work + f"{bn}" + os.sep + "ramdisk")
os.chdir(work + f"{bn}" + os.sep)
print("Unpacking Ramdisk...")
call("cpio -d --no-absolute-filenames -F %s -i -D %s" % ("ramdisk.cpio", "ramdisk"))
os.chdir(elocal)
else:
print("Unpack Done!")
os.chdir(elocal)
@cartoon
def dboot(nm: str = 'boot'):
work = rwork()
flag = ''
boot = findfile(f"{nm}.img", work)
if not os.path.exists(work + f"{nm}"):
print(f"Cannot Find {nm}...")
return
if os.name != 'posix':
cpio = findfile("cpio.exe",
f'{elocal}{os.sep}bin{os.sep}{platform.system()}{os.sep}{platform.machine()}{os.sep}').replace(
'\\', "/")
else:
cpio = findfile("cpio", f'{elocal}{os.sep}bin{os.sep}{platform.system()}{os.sep}{platform.machine()}{os.sep}')
if os.path.isdir(work + f"{nm}" + os.sep + "ramdisk"):
os.chdir(work + f"{nm}" + os.sep + "ramdisk")
call(exe="busybox ash -c \"find . | %s -H newc -R 0:0 -o -F ../ramdisk-new.cpio\"" % cpio, sp=1, shstate=True)
os.chdir(work + f"{nm}" + os.sep)
with open(work + f"{nm}" + os.sep + "comp", "r", encoding='utf-8') as compf:
comp = compf.read()
print("Compressing:%s" % comp)
if comp != "unknow":
if call("magiskboot compress=%s ramdisk-new.cpio" % comp) != 0:
print("Pack Ramdisk Fail...")
os.remove("ramdisk-new.cpio")
return
else:
print("Pack Ramdisk Successful..")
try:
os.remove("ramdisk.cpio")
except:
pass
os.rename("ramdisk-new.cpio.%s" % comp.split('_')[0], "ramdisk.cpio")
else:
print("Pack Ramdisk Successful..")
os.remove("ramdisk.cpio")
os.rename("ramdisk-new.cpio", "ramdisk.cpio")
if comp == "cpio":
flag = "-n"
ramdisk = True
else:
ramdisk = False
if call("magiskboot repack %s %s" % (flag, boot)) != 0:
print("Pack boot Fail...")
return
else:
if ramdisk:
os.remove(work + f"{nm}.img")
os.rename(work + f"{nm}" + os.sep + "new-boot.img", work + f"{nm}.img")
os.chdir(elocal)
try:
rmdir((work + f"{nm}"), up=1)
except:
print(lang.warn11.format(nm))
print("Pack Successful...")
@cartoon
def packrom(edbgs, dbgs, dbfs, scale, parts, spatch, *others) -> any:
dely = others[0]
erofs_level = others[1]
if not dn.get():
messpop(lang.warn1)
return False
else:
if not os.path.exists(settings.path + os.sep + dn.get()):
messpop(lang.warn1, "red")
return False
if os.path.exists((work := rwork()) + "config" + os.sep + "parts_info"):
with open(work + "config" + os.sep + "parts_info", 'r+', encoding='utf-8') as fff:
parts_dict = json.loads(fff.read())
else:
parts_dict = {}
for i in parts:
dname = os.path.basename(i)
if dname not in parts_dict.keys():
parts_dict[dname] = 'unknow'
if spatch == 1:
for j in "vbmeta.img", "vbmeta_system.img", "vbmeta_vendor.img":
file = findfile(j, work)
if file:
if gettype(file) == 'vbmeta':
print(lang.text71 % file)
utils.vbpatch(file).disavb()
if os.access(work + "config" + os.sep + "%s_fs_config" % dname, os.F_OK):
if os.name == 'nt':
try:
if folder := findfolder(work, "com.google.android.apps.nbu."):
call("mv {} {}".format(folder, folder.replace("com.google.android.apps.nbu.",
"com.google.android.apps.nbu")))
rmdir(findfolder(work, "com.google.android.apps.nbu"))
except Exception as e:
print(e)
fspatch.main(work + dname, work + "config" + os.sep + dname + "_fs_config")
utils.qc(work + "config" + os.sep + dname + "_fs_config")
contextpatch.main(work + dname, work + "config" + os.sep + dname + "_file_contexts")
utils.qc(work + "config" + os.sep + dname + "_file_contexts")
if parts_dict[dname] == 'erofs':
mkerofs(dname, "%s" % (edbgs.get()), work, erofs_level)
if dely == 1:
rdi(work, dname)
print(lang.text3.format(dname))
if dbgs.get() in ["dat", "br", "sparse"]:
call('img2simg {}.img {}.simg'.format(work + dname, work + dname))
if os.path.exists(work + dname + ".simg"):
os.remove(work + dname + ".img")
os.rename(work + dname + ".simg", work + dname + ".img")
if dbgs.get() == 'dat':
datbr(work, dname, "dat")
elif dbgs.get() == 'br':
datbr(work, dname, scale.get())
else:
print(lang.text3.format(dname))
else:
if dbgs.get() in ["dat", "br", "sparse"]:
if dbfs.get() == "make_ext4fs":
make_ext4fs(dname, work, "-s")
else:
mke2fs(dname, work, "y")
if dely == 1:
rdi(work, dname)
if dbgs.get() == "dat":
datbr(work, dname, "dat")
elif dbgs.get() == "br":
datbr(work, dname, scale.get())
else:
print(lang.text3.format(dname))
else:
if dbfs.get() == "make_ext4fs":
make_ext4fs(dname, work, "")
else:
mke2fs(dname, work, "n")
if dely == 1:
rdi(work, dname)
elif parts_dict[i] in ['boot', 'vendor_boot']:
dboot(i)
elif parts_dict[i] == 'dtbo':
padtbo()
elif parts_dict[i] == 'logo':
logopack()
else:
print(f"Unsupport {i}:{parts_dict[i]}")
@cartoon
def rdi(work, dname) -> any:
if not os.listdir(work + "config"):
rmtree(work + "config")
return False
if os.access(work + dname + ".img", os.F_OK):
print(lang.text72 % dname)
try:
rmdir(work + dname, 1)
if os.access(work + "config" + os.sep + "%s_size.txt" % dname, os.F_OK):
os.remove(work + "config" + os.sep + "%s_size.txt" % dname)
os.remove(work + "config" + os.sep + "%s_file_contexts" % dname)
os.remove(work + "config" + os.sep + "%s_fs_config" % dname)
except Exception as e:
print(lang.text73 % (dname, e))
print(lang.text3.format(dname))
else:
messpop(lang.text75 % dname, "red")
def input_(title: str = lang.text76, text: str = "") -> str:
(inputvar := StringVar()).set(text)
input__ = Toplevel()
input__.geometry("300x180")
input__.resizable(False, False)
input__.title(title)
ttk.Entry(input__, textvariable=inputvar).pack(pady=5, padx=5, fill=BOTH)
ttk.Button(input__, text=lang.ok, command=input__.destroy).pack(padx=5, pady=5, fill=BOTH, side='bottom')
jzxs(input__)
input__.wait_window()
return inputvar.get()
def script2fs(path):
if os.path.exists(path + os.sep + "system" + os.sep + "app"):
if not os.path.exists(path + os.sep + "config"):
os.makedirs(path + os.sep + "config")
extra.script2fs_context(findfile("updater-script", path + os.sep + "META-INF"), path + os.sep + "config", path)
if os.path.exists(path + os.sep + "config" + os.sep + "parts_info"):
with open(path + os.sep + "config" + os.sep + "parts_info", 'r+', encoding='utf-8') as pf:
parts = json.loads(pf.read())
else:
parts = {}
for v in os.listdir(path):
if os.path.exists(path + os.sep + "config" + os.sep + v + "_fs_config"):
if v not in parts.keys():
parts[v] = 'ext'
with open(path + os.sep + "config" + os.sep + "parts_info", 'w+', encoding='utf-8') as pf:
json.dump(parts, pf, indent=4)
@cartoon
def unpackrom(ifile) -> None:
print(lang.text77 + (zip_src := ifile))
if (ftype := gettype(ifile)) == "ozip":
print(lang.text78 + ifile)
ozipdecrypt.main(ifile)
try:
os.remove(ifile)
except Exception as e:
messpop(lang.warn11.format(e))
zip_src = os.path.dirname(ifile) + os.sep + os.path.basename(ifile)[:-4] + "zip"
elif os.path.splitext(ifile)[1] == '.ofp':
if ask_win(lang.t12) == 1:
ofp_mtk_decrypt.main(ifile, settings.path + os.sep + os.path.splitext(os.path.basename(zip_src))[0])
else:
ofp_qc_decrypt.main(ifile, settings.path + os.sep + os.path.splitext(os.path.basename(zip_src))[0])
script2fs(settings.path + os.sep + os.path.splitext(os.path.basename(zip_src))[0])
try:
unpackg.refs()
except:
pass
return
elif os.path.splitext(ifile)[1] == '.ops':
args = {'decrypt': True,
"<filename>": ifile,
'outdir': os.path.join(settings.path, os.path.basename(ifile).split('.')[0])}
opscrypto.main(args)
try:
unpackg.refs()
except:
pass
return
if gettype(zip_src) == 'zip':
fz = zipfile.ZipFile(zip_src, 'r')
for fi in fz.namelist():
try:
file = fi.encode('cp437').decode('gbk')
except:
try:
file = fi.encode('cp437').decode('utf-8')
except:
pass
print(lang.text79 + file)
try:
fz.extract(file, settings.path + os.sep + os.path.splitext(os.path.basename(zip_src))[0])
except Exception as e:
print(lang.text80 % (file, e))
messpop(lang.warn4.format(file))
finally:
pass
print(lang.text81)
if os.path.exists("".join([settings.path, os.sep, os.path.splitext(os.path.basename(zip_src))[0]])):
xmcd_.listdir()
dn.set(os.path.splitext(os.path.basename(zip_src))[0])
else:
xmcd_.listdir()
script2fs(settings.path + os.sep + os.path.splitext(os.path.basename(zip_src))[0])
try:
unpackg.refs()
except:
pass
return
elif ftype != 'unknow':
if os.path.exists(settings.path + os.sep + os.path.splitext(os.path.basename(ifile))[0]):
folder = settings.path + os.sep + os.path.splitext(os.path.basename(ifile))[0] + v_code()
else:
folder = settings.path + os.sep + os.path.splitext(os.path.basename(ifile))[0]
try:
os.mkdir(folder)
except Exception as e:
messpop(e)
copy(ifile, folder)
xmcd_.listdir()
dn.set(os.path.basename(folder))
else:
print(lang.text82 % ftype)
try:
unpackg.refs()
except:
pass
def rwork() -> str:
return settings.path + os.sep + dn.get() + os.sep
@cartoon
def unpack(chose, form: any = None):
if not dn.get():
messpop(lang.warn1)
return False
else:
if not os.path.exists(settings.path + os.sep + dn.get()):
messpop(lang.warn1, "red")
return False
if os.path.exists((work := rwork()) + "config" + os.sep + "parts_info"):
with open(work + "config" + os.sep + "parts_info", 'r+', encoding='utf-8') as pf:
parts = json.loads(pf.read())
else:
parts = {}
for fd in [f for f in os.listdir(work) if re.search(r'\.new\.dat\.\d+', f)]:
with open(work + os.path.basename(fd).rsplit('.', 1)[0], 'ab') as ofd:
for fd1 in sorted(
[f for f in os.listdir(work) if f.startswith(os.path.basename(fd).rsplit('.', 1)[0] + ".")],
key=lambda x: int(x.rsplit('.')[3])):
print(lang.text83 % (fd1, os.path.basename(fd).rsplit('.', 1)[0]))
with open(work + fd1, 'rb') as nfd:
ofd.write(nfd.read())
os.remove(work + fd1)
if os.access(work + "UPDATE.APP", os.F_OK):
print(lang.text79 + "UPDATE.APP")
splituapp.extract(work + "UPDATE.APP", "")
if not chose:
return 1
if form == 'payload':
print(lang.text79 + "payload")
with open(work + "payload.bin", 'rb') as pay:
try:
mmap.mmap(pay.fileno(), 0, access=mmap.ACCESS_READ).close()
except ValueError as e:
print(e, "Use Old Method")
payload_dumper.ota_payload_dumper(pay, work, 'old', chose)
else:
payload_dumper.ota_payload_dumper(mmap.mmap(pay.fileno(), 0, access=mmap.ACCESS_READ), work, 'old',
chose)
if ask_win(lang.t9.format("payload.bin")) == 1:
try:
os.remove(work + "payload.bin")
except Exception as e:
print(lang.text72 + " payload.bin:%s" % e)
os.remove(work + "payload.bin")
return 1
for i in chose:
if os.access(work + i + ".new.dat.br", os.F_OK):
print(lang.text79 + i + ".new.dat.br")
call("brotli -dj " + work + i + ".new.dat.br")
if os.access(work + i + ".new.dat", os.F_OK):
print(lang.text79 + work + i + ".new.dat")
if os.path.getsize(work + i + ".new.dat") != 0:
transferpath = os.path.abspath(os.path.dirname(work)) + os.sep + i + ".transfer.list"
if os.access(transferpath, os.F_OK):
sdat2img(transferpath, work + i + ".new.dat", work + i + ".img")
if os.access(work + i + ".img", os.F_OK):
os.remove(work + i + ".new.dat")
os.remove(transferpath)
try:
os.remove(work + i + '.patch.dat')
except:
pass
else:
print("transferpath" + lang.text84)
if os.access(work + i + ".img", os.F_OK):
try:
parts.pop(i)
except KeyError:
pass
if gettype(work + i + ".img") != 'sparse':
parts[i] = gettype(work + i + ".img")
if gettype(work + i + ".img") == 'dtbo':
un_dtbo(i)
if gettype(work + i + ".img") in ['boot', 'vendor_boot']:
jboot(i)
if i == 'logo':
logodump(i)
if gettype(work + i + ".img") == 'vbmeta':
print(f"{lang.text85}AVB:{i}")
utils.vbpatch(work + i + ".img").disavb()
ftype = gettype(work + i + ".img")
if ftype == "sparse":
print(lang.text79 + i + ".img [%s]" % ftype)
try:
utils.simg2img(work + i + ".img")
except:
messpop(lang.warn11.format(i + ".img"))
if i not in parts.keys():
parts[i] = gettype(work + i + ".img")
if gettype(work + i + ".img") == 'super':
print(lang.text79 + i + ".img")
if gettype(work + i + ".img") == "sparse":
try:
utils.simg2img(work + i + ".img")
except:
messpop(lang.warn11.format(i))
lpunpack.unpack(work + i + ".img", work)
if os.access(work + "system_a.img", os.F_OK):
for wjm in os.listdir(work):
if wjm.endswith('_a.img'):
os.rename(work + wjm, work + wjm.replace('_a', ''))
if wjm.endswith('_b.img'):
if os.path.getsize(work + wjm) == 0:
os.remove(work + wjm)
else:
pass
if (ftype := gettype(work + i + ".img")) == "ext":
print(lang.text79 + i + ".img [%s]" % ftype)
try:
imgextractor.Extractor().main(work + i + ".img", work + i, work)
except Exception as e:
print(f"Unpack Fail..{e}")
continue
if os.path.exists(work + i):
try:
os.remove(work + i + ".img")
except Exception as e:
messpop(lang.warn11.format(i + ".img:" + e))
if ftype == "erofs":
print(lang.text79 + i + ".img [%s]" % ftype)
if call(exe="extract.erofs -i " + settings.path + os.sep + dn.get() + os.sep + i + ".img -o " + work + " -x",
out=1) != 0:
print(f'Unpack Fail...')
continue
if os.access(work + "config" + os.sep + i + "_fs_config", os.F_OK):
with open(work + "config" + os.sep + i + "_fs_config", 'a', encoding='utf-8',
newline='\n') as fs:
fs.write("/lost+found 0 0 0777\r\n")
if os.path.exists(work + i):
try:
os.remove(work + i + ".img")
except:
messpop(lang.warn11.format(i + ".img"))
if not os.path.exists(work + "config"):
os.makedirs(work + "config")
with open(work + "config" + os.sep + "parts_info", 'w+', encoding='utf-8', newline='\n') as ff:
ff.write(json.dumps(parts))
parts.clear()
print(lang.text8)
def ask_win(text='', ok=lang.ok, cancel=lang.cancel) -> int:
value = IntVar()
ask = Toplevel()
ask.resizable(False, False)
ttk.Label(ask, text=text, font=(None, 20)).pack()
ttk.Button(ask, text=ok, command=lambda: close_ask(1)).pack(side='left', padx=5, pady=5, fill=BOTH,
expand=True)
ttk.Button(ask, text=cancel, command=lambda: close_ask(0)).pack(side='left', padx=5, pady=5, fill=BOTH,
expand=True)
def close_ask(value_=1):
value.set(value_)
ask.destroy()
jzxs(ask)
ask.wait_window()
return value.get()
class dirsize(object):
# get-command
# 1 - retun True value of dir size
# 2 - return Rsize value of dir size
# 3 - return Rsize value of dir size and modify dynampic_partition_list
def __init__(self, dir: str, num: int = 1, get: int = 2, list_f: str = None):
self.rsize_v: int
self.num = num
self.get = get
self.list_f = list_f
self.dname = os.path.basename(dir)
self.size = 0
for root, dirs, files in os.walk(dir):
self.size += sum([os.path.getsize(os.path.join(root, name)) for name in files if
not os.path.islink(os.path.join(root, name))])
if self.get == 1:
self.rsize_v = self.size
elif self.get in [2, 3]:
self.rsize(self.size, self.num)
else:
self.rsize(self.size, self.num)
def rsize(self, size: int, num: int):
if size <= 2097152:
size_ = 2097152
bs = 1
else:
size_ = int(size + 10086)
if size_ > 2684354560:
bs = 1.0658
if size_ <= 2684354560:
bs = 1.0758
if size_ <= 1073741824:
bs = 1.0858
if size_ <= 536870912:
bs = 1.0958
if size_ <= 104857600:
bs = 1.1158
else:
bs = 1.1258
print(f"Multiple:{bs}")
if self.get == 3:
self.rsizelist(self.dname, int(size_ * bs), self.list_f)
self.rsize_v = int(size_ * bs / num)
@staticmethod
def rsizelist(dname, size, file):
if os.access(file, os.F_OK):
print(lang.text74 % (dname, size))
with open(file, 'r') as f:
content = f.read()
with open(file, 'w', encoding='utf-8', newline='\n') as ff:
content = re.sub("resize {} \\d+".format(dname),
"resize {} {}".format(dname, size), content)
content = re.sub("resize {}_a \\d+".format(dname),
"resize {}_a {}".format(dname, size), content)
content = re.sub("# Grow partition {} from 0 to \\d+".format(dname),
"# Grow partition {} from 0 to {}".format(dname, size),
content)
content = re.sub("# Grow partition {}_a from 0 to \\d+".format(dname),
"# Grow partition {}_a from 0 to {}".format(dname, size), content)
ff.write(content)
@cartoon
def datbr(work, name, brl: any):
print(lang.text86 % (name, name))
utils.img2sdat(work + name + ".img", work, 4, name)
if os.access(work + name + ".new.dat", os.F_OK):
try:
os.remove(work + name + ".img")
except Exception as e:
print(e)
os.remove(work + name + ".img")
if brl == "dat":
print(lang.text87 % name)
else:
print(lang.text88 % name)
call("brotli -q {} -j -w 24 {} -o {}".format(brl, work + name + ".new.dat", work + name + ".new.dat.br"))
if os.access(work + name + ".new.dat", os.F_OK):
try:
os.remove(work + name + ".new.dat")
except Exception as e:
print(e)
print(lang.text89 % name)
@cartoon
def mkerofs(name, format_, work, level):
print(lang.text90 % (name, format_ + f',{level}', "1.x"))
if format_ != 'lz4':
extra_ = f'{format_},{level}'
else:
extra_ = f'{format_}'
cmd = f"mkfs.erofs -z{extra_} -T {int(time.time())} --mount-point=/{name} --product-out={work} --fs-config-file={work}config{os.sep}{name}_fs_config --file-contexts={work}config{os.sep}{name}_file_contexts {work + name}.img {work + name + os.sep}"
call(cmd)
@cartoon
def make_ext4fs(name, work, sparse):
print(lang.text91 % name)
size = dirsize(work + name, 1, 3, work + "dynamic_partitions_op_list").rsize_v
call(
f"make_ext4fs -J -T {int(time.time())} {sparse} -S {work}config{os.sep}{name}_file_contexts -l {size} -C {work}config{os.sep}{name}_fs_config -L {name} -a {name} {work + name}.img {work + name}")
@cartoon
def mke2fs(name, work, sparse):
print(lang.text91 % name)
size = dirsize(work + name, 4096, 3, work + "dynamic_partitions_op_list").rsize_v
if call(
f"mke2fs -O ^has_journal -L {name} -I 256 -M /{name} -m 0 -t ext4 -b 4096 {work + name}_new.img {size}") != 0:
rmdir(f'{work + name}_new.img', 1)
print(lang.text75 % name)
return False
if call(
f"e2fsdroid -e -T {int(time.time())} -S {work}config{os.sep}{name}_file_contexts -C {work}config{os.sep}{name}_fs_config -a /{name} -f {work + name} {work + name}_new.img") != 0:
rmdir(f'{work + name}_new.img', 1)
print(lang.text75 % name)
return False
if sparse == "y":
call(f"img2simg {work + name}_new.img {work + name}.img")
try:
os.remove(work + name + "_new.img")
except:
pass
else:
if os.path.isfile(work + name + ".img"):
try:
os.remove(work + name + ".img")
except:
pass
os.rename(work + name + "_new.img", work + name + ".img")
class handle_log:
@staticmethod
def putlog():
with open(settings.path + os.sep + (
log := time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())) + v_code() + '.txt',
'w', encoding='utf-8', newline='\n') as f:
f.write(win.show.get(1.0, END))
win.show.delete(1.0, END)
print(lang.text95 + settings.path + os.sep + log + v_code() + ".txt")
def selectp(self):
print(lang.text96 + dn.get())
if ' ' in dn.get():
print(lang.t29 + dn.get())
@cartoon
def rmdir(path, up=0):
if not path:
messpop(lang.warn1)
else:
print(lang.text97 + f'{os.path.basename(path)}')
try:
try:
rmtree(f'{path}')
except:
call(f'busybox rm -rf {path}')
except:
print(lang.warn11.format(path))
if os.path.exists(path):
messpop(lang.warn11.format(path))
else:
print(lang.text98 + path)
def get_all_file_paths(directory) -> Ellipsis:
for root, directories, files in os.walk(directory):
for filename in files:
yield os.path.join(root, filename)
def set_theme(self):
print(lang.text100 + theme.get())
try:
settings.setf("theme", theme.get())
sv_ttk.set_theme(theme.get())
gif = Image.open("bin/images/loading_{}.gif".format(win.LB2.get()))
cartoon.loadgif(gif)
except Exception as e:
messpop(lang.text101 % (theme.get(), e))
def set_language(self):
print(lang.text129 + language.get())
try:
settings.setf("language", language.get())
load(language.get())
except Exception as e:
print(lang.t130, e)
class zip_file(object):
def __init__(self, file, dst_dir, path=None):
if not path:
path = settings.path + os.sep
os.chdir(dst_dir)
with zipfile.ZipFile(relpath := path + file, 'w', compression=zipfile.ZIP_DEFLATED,
allowZip64=True) as zip_:
# 遍历写入文件
for file in get_all_file_paths('.'):
print(f"{lang.text1}:%s" % file)
try:
zip_.write(file)
except Exception as e:
print(lang.text2.format(file, e))
if os.path.exists(relpath):
print(lang.text3.format(relpath))
os.chdir(elocal)
@cartoon
def packzip():
if not dn.get():
messpop(lang.warn1)
else:
print(lang.text91 % dn.get())
if ask_win(lang.t25) == 1:
dbkxyt()
zip_file(dn.get() + ".zip", settings.path + os.sep + dn.get())
def modpath():
if not (folder := filedialog.askdirectory()):
return False
settings.setf("path", folder)
win.slocal.set(folder)
settings.load()
def dndfile(files):
for fi in files:
try:
fi = fi.decode('gbk')
except:
fi = fi
if os.path.exists(fi):
if os.path.basename(fi).endswith(".mpk"):
installmpk(fi)
elif os.path.basename(fi).endswith(".mps"):
Process(fi)
else:
cz(unpackrom, fi)
else:
print(fi + lang.text84)
def sdxz(other):
dndfile([filedialog.askopenfilename()])
class xmcd(ttk.LabelFrame):
def __init__(self):
super().__init__(master=win.tab2, text=lang.text12)
self.pack(padx=5, pady=5)
def gui(self):
self.LB1 = ttk.Combobox(self, textvariable=dn, state='readonly')
self.LB1.pack(side="top", padx=10, pady=10, fill=X)
self.LB1.bind('<<ComboboxSelected>>', selectp)
ttk.Button(self, text=lang.text23, command=self.listdir).pack(side="left", padx=10, pady=10)
ttk.Button(self, text=lang.text115, command=self.newp).pack(side="left", padx=10, pady=10)
ttk.Button(self, text=lang.text116, command=lambda: cz(self.delwork)).pack(side="left", padx=10, pady=10)
ttk.Button(self, text=lang.text117, command=lambda: cz(self.cmm)).pack(side="left", padx=10, pady=10)
def listdir(self):
array = []
for f in os.listdir(settings.path + os.sep + "."):
if os.path.isdir(settings.path + os.sep + f) and f != 'bin' and not f.startswith('.'):
array.append(f)
if not array:
dn.set("")
self.LB1["value"] = array
self.LB1.current()
else:
self.LB1["value"] = array
self.LB1.current(0)
def cmm(self):
if not dn.get():
print(lang.warn1)
return
if os.path.exists(settings.path + os.sep + (inputvar := input_(lang.text102 + dn.get(), dn.get()))):
print(lang.text103)
return False
if inputvar != dn.get():
os.rename(settings.path + os.sep + dn.get(), settings.path + os.sep + inputvar)
self.listdir()
else:
print(lang.text104)
def delwork(self):
if not dn.get():
messpop(lang.warn1)
else:
rmdir(settings.path + os.sep + dn.get())
self.listdir()
def newp(self):
if not (inputvar := input_()):
messpop(lang.warn12)
else:
print(lang.text99 % inputvar)
os.mkdir(settings.path + os.sep + "%s" % inputvar)
self.listdir()
class frame3(ttk.LabelFrame):
def __init__(self):
super().__init__(master=win.tab2, text=lang.text112)
self.pack(padx=5, pady=5)
def gui(self):
ttk.Button(self, text=lang.text122, command=lambda: cz(packzip)).pack(side="left", padx=10, pady=10)
ttk.Button(self, text=lang.text123, command=lambda: cz(packss)).pack(side="left", padx=10, pady=10)
ttk.Button(self, text=lang.text19, command=lambda: win.notepad.select(win.tab7)).pack(side="left", padx=10,
pady=10)
ttk.Button(self, text=lang.t13, command=lambda: cz(format_conversion)).pack(side="left", padx=10, pady=10)
class unpack_gui(ttk.LabelFrame):
def __init__(self):
super().__init__(master=win.tab2, text=lang.text9)
def gui(self):
self.pack(padx=5, pady=5)
self.ch = IntVar()
self.ch.set(1)
self.fm = ttk.Combobox(self, state="readonly", values=('new.dat.br', "new.dat", 'img', 'payload'))
self.lsg = Listbox(self, activestyle='dotbox', selectmode=MULTIPLE, highlightthickness=0)
self.fm.current(0)
self.fm.bind("<<ComboboxSelected>>", self.refs)
self.lsg.pack(padx=5, pady=5, fill=X, side='top')
ttk.Separator(self, orient=HORIZONTAL).pack(padx=50, fill=X)
ff1 = ttk.Frame(self)
ttk.Radiobutton(ff1, text=lang.unpack, variable=self.ch,
value=1).pack(padx=5, pady=5, side='left')
ttk.Radiobutton(ff1, text=lang.pack, variable=self.ch,
value=0).pack(padx=5, pady=5, side='left')
ff1.pack(padx=5, pady=5, fill=X)
ttk.Separator(self, orient=HORIZONTAL).pack(padx=50, fill=X)
self.fm.pack(padx=5, pady=5, fill=Y, side='left')
ttk.Button(self, text=lang.run, command=lambda: cz(self.close_)).pack(padx=5, pady=5, side='left')
self.refs()
self.ch.trace("w", self.hd)
def hd(self, *args):
if self.ch.get() == 1:
self.fm.configure(state='readonly')
self.refs(None)
else:
self.fm.configure(state="disabled")
self.refs2()
def refs(self, N=None):
self.lsg.delete(0, END)
if not os.path.exists(work := rwork()):
messpop(lang.warn1)
return False
if not self.fm.get() in ['payload', 'super']:
for file_name in os.listdir(work):
if file_name.endswith(self.fm.get()):
self.lsg.insert(END, file_name.split("." + self.fm.get())[0])
else:
if self.fm.get() == 'payload':
if os.path.exists(work + "payload.bin"):
with open(work + "payload.bin", 'rb') as pay:
for i in payload_dumper.ota_payload_dumper(pay, work, 'old', '',
0):
self.lsg.insert(END, i.partition_name)
def rt_info(self):
if os.path.exists((work := rwork()) + "config" + os.sep + "parts_info"):
with open(work + "config" + os.sep + "parts_info", 'r+', encoding='utf-8') as fff:
return json.loads(fff.read())
else:
return {}
def refs2(self):
self.lsg.delete(0, END)
if not os.path.exists(work := rwork()):
messpop(lang.warn1)
return False
parts_dict = self.rt_info()
for folder in os.listdir(work):
if os.path.isdir(work + folder) and folder in parts_dict.keys():
self.lsg.insert(END, folder)
def close_(self):
lbs = [self.lsg.get(index) for index in self.lsg.curselection()]
self.hd()
if self.ch.get() == 1:
unpack(lbs, self.fm.get())
self.refs()
else:
packxx(lbs)
if int(settings.oobe) < 4:
welcome()
win.gui()
unpackg = unpack_gui()
xmcd_ = xmcd()
xmcd_.gui()
unpackg.gui()
frame3().gui()
xmcd_.listdir()
class format_conversion(Toplevel):
def __init__(self):
super().__init__()
self.resizable(False, False)
self.title(lang.t13)
self.f = Frame(self)
self.f.pack(pady=5, padx=5, fill=X)
self.h = ttk.Combobox(self.f, values=("raw", "sparse", 'dat', 'br'), state='readonly')
self.h.current(0)
self.h.bind("<<ComboboxSelected>>", self.relist)
self.h.pack(side='left', padx=5)
Label(self.f, text='>>>>>>').pack(side='left', padx=5)
self.f = ttk.Combobox(self.f, values=("raw", "sparse", 'dat', 'br'), state='readonly')
self.f.current(0)
self.f.pack(side='left', padx=5)
self.list_b = Listbox(self, highlightthickness=0, activestyle='dotbox', selectmode=MULTIPLE)
self.list_b.pack(padx=5, pady=5, fill=BOTH)
self.relist()
ttk.Button(self, text=lang.ok, command=lambda: cz(self.conversion)).pack(side=BOTTOM, fill=BOTH)
jzxs(self)
def relist(self, *other):
work = rwork()
self.list_b.delete(0, "end")
if self.h.get() == "br":
for i in self.refile(".new.dat.br"):
self.list_b.insert('end', i)
elif self.h.get() == 'dat':
for i in self.refile(".new.dat"):
self.list_b.insert('end', i)
elif self.h.get() == 'sparse':
for i in os.listdir(work):
if os.path.isfile(work + i) and gettype(work + i) == 'sparse':
self.list_b.insert('end', i)
elif self.h.get() == 'raw':
for i in os.listdir(work):
if os.path.isfile(work + i):
if gettype(work + i) in ['ext', 'erofs', 'super']:
self.list_b.insert('end', i)
@staticmethod
def refile(f):
for i in os.listdir(work := rwork()):
if i.endswith(f):
if os.path.isfile(work + i):
yield i
@cartoon
def conversion(self):
work = rwork()
fget = self.f.get()
hget = self.h.get()
selection = [self.list_b.get(index) for index in self.list_b.curselection()]
self.destroy()
if fget == hget:
pass
elif fget == 'sparse':
for i in selection:
print(f'[{hget}->{fget}]{i}')
dname = os.path.basename(i).split('.')[0]
if hget == 'br':
if os.access(work + i, os.F_OK):
print(lang.text79 + i)
call("brotli -dj " + work + i)
if hget == 'dat':
if os.access(work + i, os.F_OK):
print(lang.text79 + work + i)
if os.path.getsize(work + i) != 0:
transferpath = os.path.abspath(os.path.dirname(work)) + os.sep + dname + ".transfer.list"
if os.access(transferpath, os.F_OK):
sdat2img(transferpath, work + i, work + dname + ".img")
if os.access(work + dname + ".img", os.F_OK):
os.remove(work + i)
os.remove(transferpath)
try:
os.remove(work + dname + '.patch.dat')
except:
pass
else:
print("transferpath" + lang.text84)
if os.path.exists(work + dname + '.img'):
call('img2simg {} {}'.format(work + i, work + i + 's'))
if os.path.exists(work + i + 's'):
try:
os.remove(work + i)
os.rename(work + i + 's', work + i)
except Exception as e:
print(e)
elif fget == 'raw':
for i in selection:
print(f'[{hget}->{fget}]{i}')
dname = os.path.basename(i).split('.')[0]
if hget == 'br':
if os.access(work + i, os.F_OK):
print(lang.text79 + i)
call("brotli -dj " + work + i)
if hget in ['dat', 'br']:
if os.path.exists(work):
if hget == 'br':
i = i.replace('.br', '')
print(lang.text79 + work + i)
if os.path.getsize(work + i) != 0:
transferpath = os.path.abspath(os.path.dirname(work)) + os.sep + dname + ".transfer.list"
if os.access(transferpath, os.F_OK):
sdat2img(transferpath, work + i, work + dname + ".img")
if os.access(work + dname + ".img", os.F_OK):
try:
os.remove(work + i)
os.remove(transferpath)
os.remove(work + dname + '.patch.dat')
except:
pass
else:
print("transferpath" + lang.text84)
if hget == 'sparse':
utils.simg2img(work + i)
elif fget == 'dat':
for i in selection:
print(f'[{hget}->{fget}]{i}')
if hget == 'raw':
call('img2simg {} {}'.format(work + i, work + i + 's'))
if os.path.exists(work + i + 's'):
try:
os.remove(work + i)
os.rename(work + i + 's', work + i)
except Exception as e:
print(e)
if hget in ['raw', 'sparse']:
datbr(work, os.path.basename(i).split('.')[0], "dat")
if hget == 'br':
print(lang.text79 + i)
call("brotli -dj " + work + i)
elif fget == 'br':
for i in selection:
print(f'[{hget}->{fget}]{i}')
if hget == 'raw':
call('img2simg {} {}'.format(work + i, work + i + 's'))
if os.path.exists(work + i + 's'):
try:
os.remove(work + i)
os.rename(work + i + 's', work + i)
except Exception as e:
print(e)
if hget in ['raw', 'sparse']:
datbr(work, os.path.basename(i).split('.')[0], 0)
if hget == 'dat':
print(lang.text88 % os.path.basename(i).split('.')[0])
call("brotli -q {} -j -w 24 {} -o {}".format(0, work + i,
work + i + ".br"))
if os.access(work + i + '.br', os.F_OK):
try:
os.remove(work + i)
except Exception as e:
print(e)
print(lang.text8)
cartoon.loadgif(Image.open("bin/images/loading_%s.gif" % (win.LB2.get())))
cartoon.init()
print(lang.text108)
cz(get_time)
win.update()
jzxs(win)
print(lang.text134 % (dti() - start))
win.mainloop()