def __init__(self, main, channels, default_channel=None): super(ChannelAddWidget, self).__init__() self.setObjectName("ChannelAddWidget") self.main_win = main self.channels = channels self.default_channel = default_channel self.channel = {} self.linedit_list = [] self.game = self.main_win.games[self.main_win.game_index] combox_items = os.listdir(Utils.get_full_path('channelsdk')) v_layout = QVBoxLayout() v_layout.addSpacing(30) select_channel_combox = QComboBox() select_channel_combox.addItems(combox_items) select_channel_combox.activated[str].connect(self.select_channel) v_layout.addWidget(select_channel_combox, alignment=Qt.AlignHCenter) v_layout.addSpacing(30) h_layout1 = QHBoxLayout() form_layout1 = QFormLayout() form_layout1.setContentsMargins(10, 10, 10, 0) game_appid_value = QLabel(self.game['id']) form_layout1.addRow("游戏ID:", game_appid_value) game_appid_value.setTextInteractionFlags(Qt.TextSelectableByMouse) self.channel_id_value = QLineEdit() self.channel_id_value.setPlaceholderText("必填参数") form_layout1.addRow("渠道ID:", self.channel_id_value) self.game_name_value = QLineEdit() self.game_name_value.setText(self.game['name']) form_layout1.addRow("游戏名称:", self.game_name_value) self.game_package_value = QLineEdit() form_layout1.addRow("游戏包名:", self.game_package_value) self.game_vcode_value = QLineEdit() form_layout1.addRow("游戏版本号:", self.game_vcode_value) self.game_vname_value = QLineEdit() form_layout1.addRow("游戏版本名:", self.game_vname_value) self.debug_value = QLineEdit("false") form_layout1.addRow("打印日志:", self.debug_value) h_layout1.addLayout(form_layout1) self.form_layout2 = QFormLayout() self.form_layout2.setContentsMargins(10, 10, 10, 0) h_layout1.addLayout(self.form_layout2) v_layout.addLayout(h_layout1) h_layout2 = QHBoxLayout() back_btn = QPushButton("返 回") back_btn.setFixedWidth(100) back_btn.clicked.connect(self.back) h_layout2.addWidget(back_btn, alignment=Qt.AlignLeft) add_btn = QPushButton("添 加") add_btn.setFixedWidth(100) add_btn.clicked.connect(self.add) h_layout2.addWidget(add_btn, alignment=Qt.AlignRight) v_layout.addSpacing(50) v_layout.addLayout(h_layout2) self.setLayout(v_layout) # 默认松鼠SDK select_channel_combox.setCurrentText("songshu") self.select_channel("songshu")
def add(self): if self.channel_id_value.text().strip() == "": QMessageBox.warning(self, "警告", "渠道ID不能为空!") return self.channel['channelId'] = self.channel_id_value.text().strip() for channel in self.channels: if self.channel['channelId'] == channel['channelId']: QMessageBox.warning(self, "警告", "渠道已存在!") return self.channel['gameName'] = self.game_name_value.text().strip() self.channel['package'] = self.game_package_value.text().strip() self.channel['gameVersionCode'] = self.game_vcode_value.text().strip() self.channel['gameVersionName'] = self.game_vname_value.text().strip() self.channel['debug'] = self.debug_value.text().strip() for i in range(len(self.linedit_list)): if self.linedit_list[i].text().strip() == "": QMessageBox.warning(self, "警告", "渠道参数不能为空!") return self.channel['sdkParams'][i]['value'] = self.linedit_list[i].text( ).strip() self.channels.append(self.channel) Utils.add_channel( Utils.get_full_path('games/' + self.game['id'] + '/config.xml'), self.channel) self.main_win.set_channel_list_widget(self.channels)
def save_data(self): if self.game_name_value.text().strip() == "": QMessageBox.warning(self, "警告", "游戏名称不能为空!") return False if self.keystore_path.text().strip() == "": QMessageBox.warning(self, "警告", "必须上传keystore签名文件!") return False if self.keystore_pwd_value.text().strip() == "": QMessageBox.warning(self, "警告", "keystore密码不能为空!") return False if self.keystore_alias_value.text().strip() == "": QMessageBox.warning(self, "警告", "alias不能为空!") return False if self.keystore_aliaspwd_value.text().strip() == "": QMessageBox.warning(self, "警告", "alias密码不能为空!") return False self.game['name'] = self.game_name_value.text().strip() self.game['desc'] = self.game_desc_value.toPlainText().strip() if self.keystore_exchanged: keystore = os.path.basename(self.keystore_path.text().strip()) self.game['keystore'] = keystore self.game['keypwd'] = self.keystore_pwd_value.text().strip() self.game['alias'] = self.keystore_alias_value.text().strip() self.game['aliaspwd'] = self.keystore_aliaspwd_value.text().strip() keystore_path = Utils.get_full_path('games/' + self.game['id'] + '/keystore/' + keystore) if not os.path.exists(keystore_path): Utils.copy_file(self.keystore_path.text().strip(), keystore_path) self.main_win.games[self.main_win.game_index] = self.game self.game_list_model.update_item(self.main_win.game_index, self.game) return Utils.update_games(Utils.get_full_path('games/games.xml'), self.game, self.main_win.game_index)
def copy_root_ext_files(apk_file, decompile_dir): aapt = Utils.get_full_path('tools/aapt2.exe') ignore_files = [ 'AndroidManifest.xml', 'apktool.yml', 'smali', 'res', 'original', 'lib', 'libs', 'build', 'assets', 'unknown', 'kotlin', 'smali_classes2', 'smali_classes3', 'smali_classes4', 'smali_classes5' ] ignore_file_paths = [] for file in ignore_files: path = os.path.join(decompile_dir, file) ignore_file_paths.append(path) add_files = [] add_files = Utils.list_files(decompile_dir, add_files, ignore_file_paths) if len(add_files) <= 0: return 0 cmd = '%s add %s' for f in add_files: name = f[len(decompile_dir) + 1:] cmd = cmd + ' ' + name cmd = cmd % (aapt, apk_file) curr_path = os.getcwd() os.chdir(decompile_dir) ret = Utils.exec_cmd(cmd) os.chdir(curr_path) return ret
def copy_libs(decompile_dir, sdk_dir): cpus = [ 'arm64-v8a', 'armeabi', 'armeabi-v7a', 'mips', 'mips64', 'x86', 'x86_64' ] dest_dir = os.path.join(decompile_dir, 'lib') src_dir = os.path.join(sdk_dir, 'libs') if not os.path.exists(src_dir): return if os.path.exists(dest_dir): for f in os.listdir(dest_dir): if f.endswith('.jar'): continue source_file = os.path.join(src_dir, f) target_file = os.path.join(dest_dir, f) if os.path.exists(source_file): Utils.copy_file(source_file, target_file) else: os.mkdir(dest_dir) for fi in os.listdir(src_dir): if fi.endswith('.jar'): continue source_file = os.path.join(src_dir, fi) target_file = os.path.join(dest_dir, fi) Utils.copy_file(source_file, target_file)
def decompile_apk(apk_file, target_dir, frame_work_dir): java = Utils.get_full_path('tools/jdk/bin/java') apk_tool = Utils.get_full_path('tools/apktool.jar') os.makedirs(target_dir) os.makedirs(frame_work_dir) cmd = "%s -jar %s d %s -o %s -p %s -f" % (java, apk_tool, apk_file, target_dir, frame_work_dir) return Utils.exec_cmd(cmd)
def signUp(): if fl.request.method == 'POST': status = signUpUser(fl.request.form) if status: return fl.redirect(fl.url_for('renderLogin', err = status)) else: ut.sendEmailConfirmation(fl.request.form['email'], fl.session['usrName'], host_url) return fl.render_template('signUpConfirmationPage.html') else: return fl.render_template('loginPage.html', parent = fl.url_for('signUp'))
def write_develop_info(game, channel, decompile_dir): assets_path = os.path.join(decompile_dir, 'assets') if not os.path.exists(assets_path): os.makedirs(assets_path) develop_config_file = os.path.join(assets_path, 'developer_configs_ss.properties') ret = Utils.write_developer_properties(game, channel, develop_config_file) if ret: return ret plugin_file = os.path.join(assets_path, 'plugin_configs_ss.xml') return Utils.write_plugin_config(channel, plugin_file)
def dex2smali(dex_file, target_dir, path): """ Transfer the dex to smali. """ if not os.path.exists(dex_file): LogUtils.error('the dexfile is not exists. path:%s', dex_file) return 1 if not os.path.exists(target_dir): os.makedirs(target_dir) smali_tool = Utils.get_full_path('tools/baksmali.jar') java = Utils.get_full_path('tools/jdk/bin/java') cmd = '%s -jar %s -o %s %s' % (java, smali_tool, target_dir, dex_file) return Utils.exec_cmd(cmd)
def exchange_icon(self): fname = QFileDialog.getOpenFileName( self, '选择icon', Utils.get_full_path('games/' + self.game['id'] + '/icon/'), ("Images (*.png)")) if fname[0]: pix = QPixmap(fname[0]) if pix.width() != 512 or pix.height() != 512: QMessageBox.warning(self, "警告", "必须上传512*512.png图片") return self.icon_img.setPixmap(pix) current_icon = Utils.get_full_path('games/' + self.game['id'] + '/icon/icon.png') if os.path.exists(current_icon): if os.path.samefile(os.path.dirname(fname[0]), os.path.dirname(current_icon)): if not os.path.samefile( fname[0], current_icon ): # 如果选中的,在game的icon目录下,但不是当前icon,则进行重命名 count = 0 temp = 'icon0.png' while os.path.exists( Utils.get_full_path('games/' + self.game['id'] + '/icon/' + temp)): count += 1 temp = 'icon' + str(count) + '.png' os.renames( current_icon, Utils.get_full_path('games/' + self.game['id'] + '/icon/' + temp)) os.renames(fname[0], current_icon) else: # 如果所选的是当前icon,不做处理 return else: # 如果选中的不在game的icon目录下,则重命名当前icon,并将选中的icon复制到目录下作为当前icon count = 0 temp = 'icon0.png' while os.path.exists( Utils.get_full_path('games/' + self.game['id'] + '/icon/' + temp)): count += 1 temp = 'icon' + str(count) + '.png' os.renames( current_icon, Utils.get_full_path('games/' + self.game['id'] + '/icon/' + temp)) Utils.copy_file(fname[0], current_icon) else: Utils.copy_file(fname[0], current_icon)
def __init__(self): super(MainWindow, self).__init__() LogUtils.add_logger() self.games = Utils.get_games(Utils.get_full_path('games/games.xml')) self.game_index = 0 self.setObjectName("MainWindow") self.resize(960, 540) size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(0) size_policy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(size_policy) self.setWindowIcon(QIcon('pack.ico')) self.set_main_widget()
def jar2dex(src_dir, dex_path): """ compile jar files to dex. """ dex_tool_path = Utils.get_full_path('tools/dx.jar') java = Utils.get_full_path('tools/jdk/bin/java') cmd = '%s -jar %s --dex --output %s' % (java, dex_tool_path, dex_path) for f in os.listdir(src_dir): if f.endswith('.jar'): cmd = cmd + ' ' + os.path.join(src_dir, f) for f in os.listdir(os.path.join(src_dir, 'libs')): if f.endswith('.jar'): cmd = cmd + ' ' + os.path.join(src_dir, 'libs', f) return Utils.exec_cmd(cmd)
def edit_yml(channel, decompile_dir): LogUtils.info('-----> EditYML <------') path = decompile_dir + '/apktool.yml' yml_file = open(path, encoding='utf-8') content = '' while True: line = yml_file.readline() if line.find('- assets/') == 0: yml_file.tell() elif line.find('targetSdkVersion') != -1: config = Utils.get_local_config() if config is not None and config['TARGET_SDK_VERSION'] != '0': content += ' targetSdkVersion: \'' + config[ 'TARGET_SDK_VERSION'] + '\'\n' else: content += line elif line.find('versionCode') != -1 and len( channel['gameVersionCode']) > 0: content += ' versionCode: \'' + channel['gameVersionCode'] + '\'\n' elif line.find('versionName') != -1 and len( channel['gameVersionName']) > 0: content += ' versionName: ' + channel['gameVersionName'] + '\n' else: if not line: break line.replace('\r', '') if line.strip() != '': if line.find('doNotCompress:') == 0: yml_file.tell() content += 'doNotCompress:\n- assets/*\n' else: content += line LogUtils.info("apktool.yml:\n%s", content) with open(path, 'w', encoding='utf-8') as f: f.write(content)
def select_list(self): index = self.qpb_list_widget.currentIndex().row() channel_id = self.channels[self.indexs[index]]['channelId'] success = self.lbps[channel_id]['success'] dest_apk_dir = Utils.get_full_path('output/' + self.game['id'] + '/' + channel_id) if success: os.startfile(dest_apk_dir) else: QMessageBox.warning(self, "警告", "打包成功了吗?")
def save_data(self): self.channel['gameName'] = self.game_name_value.text().strip() self.channel['package'] = self.game_package_value.text().strip() self.channel['gameVersionCode'] = self.game_vcode_value.text().strip() self.channel['gameVersionName'] = self.game_vname_value.text().strip() self.channel['debug'] = self.debug_value.text().strip() i = 0 while i < len(self.linedit_list): if self.linedit_list[i].text().strip() == "": QMessageBox.warning(self, "警告", "渠道参数不能为空!") return False self.channel['sdkParams'][i]['value'] = self.linedit_list[i].text( ).strip() i += 1 self.channels[self.channel_index] = self.channel game_id = self.main_win.games[self.main_win.game_index]['id'] return Utils.update_channels( Utils.get_full_path('games/' + game_id + '/config.xml'), self.channel, self.channel_index)
def next(self): if not self.save_data(): return channels = Utils.get_channels( Utils.get_full_path('games/' + self.game['id'] + '/config.xml')) if channels is None: if not os.path.exists(Utils.get_full_path('channelsdk')): QMessageBox.warning( self, "警告", os.path.dirname(os.getcwd()) + " 没有channelsdk文件夹") return elif len(os.listdir(Utils.get_full_path('channelsdk'))) <= 0: QMessageBox.warning( self, "警告", "本地没有渠道sdk,请手动添加sdk文件夹到" + Utils.get_full_path('channelsdk')) return channels = [] self.main_win.set_add_channel_widget(channels) else: self.main_win.set_channel_list_widget(channels)
def select_game(self, p_int): self.game_index = p_int if 'apk' in self.main_win.games[self.game_index]: self.apk_path.setText(self.main_win.games[self.game_index]['apk']) else: self.apk_path.setText("<h3><font color=%s>%s</font></h3>" % ('red', "请浏览选择本地母包路径")) # self.apk_path.setText("请浏览选择本地母包路径") # 当前选中的game,其下的所有渠道列表 self.channels = Utils.get_channels( Utils.get_full_path('games/' + self.main_win.games[p_int]['id'] + '/config.xml')) channel_ids = [] for channel in self.channels: channel_ids.append(channel['channelId']) list_model = QStringListModel() list_model.setStringList(channel_ids) self.clv = self.tool_box.currentWidget() self.clv.doubleClicked.connect(self.select_channel) self.clv.setModel(list_model)
def select_ketstore(self): fname = QFileDialog.getOpenFileName( self, '选择签名文件', Utils.get_full_path('games/' + self.game['id'] + '/keystore/')) if fname[0]: if os.path.samefile( fname[0], Utils.get_full_path('games/' + self.game['id'] + '/keystore/' + self.game['keystore'])): self.keystore_path.setText(self.game['keystore']) self.keystore_pwd_value.setText(self.game['keypwd']) self.keystore_alias_value.setText(self.game['alias']) self.keystore_aliaspwd_value.setText(self.game['aliaspwd']) self.keystore_exchanged = False else: self.keystore_path.setText(fname[0]) self.keystore_pwd_value.clear() self.keystore_alias_value.clear() self.keystore_aliaspwd_value.clear() self.keystore_exchanged = True
def del_channel(self): reply = QMessageBox.warning(self, "警告", "确定删除当前渠道?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: # 更新listview self.channel_ids.pop(self.channel_index) self.list_model.setStringList(self.channel_ids) # 更新表单view(index前移一位) self.channel = self.channels[self.channel_index - 1] self.set_info() # 更新本地数据 self.channels.pop(self.channel_index) game_id = self.main_win.games[self.main_win.game_index]['id'] Utils.del_channel( Utils.get_full_path('games/' + game_id + '/config.xml'), self.channel_index) # 重置index,防止 index out of range self.channel_index = self.channel_index - 1 if self.channel_index < 0: reply = QMessageBox.warning(self, "警告", "当前游戏未添加渠道,将返回游戏列表界面!", QMessageBox.Yes) if reply == QMessageBox.Yes: self.back()
def set_game_info(self): self.game_name_value.setText(self.game['name']) self.game_desc_value.setText(self.game['desc']) self.game_appid_value.setText(self.game['id']) self.game_appkey_value.setText(self.game['key']) self.keystore_path.setText(self.game['keystore']) self.keystore_pwd_value.setText(self.game['keypwd']) self.keystore_alias_value.setText(self.game['alias']) self.keystore_aliaspwd_value.setText(self.game['aliaspwd']) icon = Utils.get_full_path('games/' + self.game['id'] + '/icon/icon.png') if not os.path.exists(icon): icon = 'icon.png' self.icon_img.setPixmap(QPixmap(icon))
def select_channel(self, text): # 先初始化数据 self.linedit_list.clear() self.channel.clear() # 排序包体参数,防止参数写入乱排序 self.channel['name'] = '' self.channel['sdk'] = text self.channel['channelId'] = '' self.channel['gameName'] = '' self.channel['package'] = '' self.channel['gameVersionCode'] = '' self.channel['gameVersionName'] = '' self.channel['debug'] = "false" # 获取渠道参数定义 if not Utils.get_channel_config(self.channel): return # 再添加当前选择的渠道参数模板,刷新界面(先清空之前渠道参数表单,再添加) for i in range(self.form_layout2.rowCount()): # 因为formlayout清除一行,会自动上移,所以只需remove第一行 self.form_layout2.removeRow(0) channel_name = QLabel(self.channel['name'] + '\t\t\tVersion:' + self.channel['sdkVersionName'] + '\t\tUpdate:' + self.channel['sdkUpdateTime']) channel_name.setAlignment(Qt.AlignRight) self.form_layout2.addRow(channel_name) if self.default_channel is not None and text == self.default_channel[ 'sdk']: self.channel_id_value.setText(self.default_channel['channelId']) self.game_name_value.setText(self.default_channel['gameName']) self.game_package_value.setText(self.default_channel['package']) self.game_vcode_value.setText( self.default_channel['gameVersionCode']) self.game_vname_value.setText( self.default_channel['gameVersionName']) for param in self.default_channel['sdkParams']: line_edit = QLineEdit() line_edit.setText(param['value']) self.form_layout2.addRow(param['showName'] + ':', line_edit) self.linedit_list.append(line_edit) else: for param in self.channel['sdkParams']: line_edit = QLineEdit() line_edit.setPlaceholderText("渠道参数必填") self.form_layout2.addRow(param['showName'] + ':', line_edit) self.linedit_list.append(line_edit)
def data(self, index, role): if index.isValid() or (0 <= index.row() < len(self.ListItemData)): if role == Qt.DisplayRole: return QVariant(self.games[index.row()]['id']) elif role == Qt.DecorationRole: icon = self.games[index.row()]['id'] icon = Utils.get_full_path('games/' + icon + '/icon/icon.png') if not os.path.exists(icon): icon = 'icon.png' return QVariant(QIcon(icon)) elif role == Qt.SizeHintRole: return QVariant(QSize(80, 80)) elif role == Qt.TextAlignmentRole: return QVariant(int(Qt.AlignHCenter | Qt.AlignVCenter)) elif role == Qt.FontRole: font = QFont() font.setPixelSize(16) font.setFamily("Microsoft YaHei") return QVariant(font) else: return QVariant()
def validLogin(postForm): ''' Given email and password, authorize user to access Virtual Admin Dashboard ''' usr_name = postForm['email'].split('@')[0] psswrd = ut.hashPassword(postForm['password']) try: chapter = c_chapters.find({ 'email':postForm['email'], 'password':psswrd })[0] except IndexError: chapter = None if chapter: #If entry found do... if chapter['email_confirmed'] == True: fl.session['usrName'] = usr_name fl.session['password'] = psswrd return True else: return False else: return False
def sign_apk(game, apk_file): key_path = Utils.get_full_path('games/' + game['id'] + '/keystore/' + game['keystore']) if not os.path.exists(key_path): LogUtils.info('the keystore file not exists: %s', key_path) return 1 LogUtils.info('the keystore file is %s', key_path) aapt = Utils.get_full_path('tools/aapt.exe') lcmd = "%s list %s" % (aapt, apk_file) out = Utils.exec_cmd2(lcmd) if out is not None and len(out) > 0: for filename in out.split('\n'): if filename.find('META-INF') == 0: rmcmd = "%s remove %s %s" % (aapt, apk_file, filename) Utils.exec_cmd(rmcmd) jar_signer = Utils.get_full_path('tools/jdk/bin/jarsigner') sign_cmd = "%s -keystore %s -storepass %s -keypass %s %s %s -sigalg SHA1withRSA -digestalg SHA1" % ( jar_signer, key_path, game['keypwd'], game['aliaspwd'], apk_file, game['alias']) return Utils.exec_cmd(sign_cmd)
def align_apk(apk_file, target_file): align = Utils.get_full_path('tools/zipalign.exe') cmd = '%s -f 4 %s %s' % (align, apk_file, target_file) return Utils.exec_cmd(cmd)
def copy_ext_res(game, decompile_dir): ext_res_path = 'games/' + game['id'] + '/ext' ext_res_path = Utils.get_full_path(ext_res_path) if os.path.exists(ext_res_path): LogUtils.warning('the game ext res path: %s', ext_res_path) Utils.copy_file(ext_res_path, decompile_dir)
def modify_manifest(channel, decompile_dir, package_name): manifest_file = decompile_dir + '/AndroidManifest.xml' ET.register_namespace('android', androidNS) tree = ET.parse(manifest_file) root = tree.getroot() app_node = root.find('application') # 修改游戏名称 if len(channel['gameName']) > 0: label = app_node.get('{' + androidNS + '}label') if label.find('@string/') == 0: app_name = label[8:len(label)] else: app_name = 'app_name' app_node.set('{' + androidNS + '}label', '@string/' + app_name) activity_node_lst = app_node.findall('activity') for activity_node in activity_node_lst: if activity_node.get('{' + androidNS + '}label') is not None: activity_node.set('{' + androidNS + '}label', '@string/' + app_name) string_file = decompile_dir + '/res/values/strings.xml' string_tree = ET.parse(string_file) strings = string_tree.getroot().findall('string') for string in strings: if string.get('name') == app_name: string_tree.getroot().remove(string) break string_node = SubElement(string_tree.getroot(), 'string', {'name': app_name}) string_node.text = channel['gameName'] string_tree.write(string_file, xml_declaration=True, encoding='utf-8', method='xml') LogUtils.info('modify game name: %s', channel['gameName']) # 写入meta-data key = '{' + androidNS + '}name' val = '{' + androidNS + '}value' meta_data_list = app_node.findall('meta-data') if meta_data_list is not None: for metaDataNode in meta_data_list: key_name = metaDataNode.attrib[key] for child in channel['sdkParams']: if key_name == child['name'] and child['writeIn'] == '1': LogUtils.warning( 'the meta-data node %s repeated. remove it .', key_name) app_node.remove(metaDataNode) for child in channel['sdkParams']: if child['writeIn'] is not None and child['writeIn'] == '1': meta_node = SubElement(app_node, 'meta-data') meta_node.set(key, child['name']) meta_node.set(val, child['value']) LogUtils.info('writeIn meta-data: %s=%s', child['name'], child['value']) # 修改替换包名占位符 xml_str = ET.tostring(root, 'utf-8').decode('utf-8') if xml_str.find('NEW_PACKAGE_NAME') != -1: LogUtils.info('modify package name: %s', package_name) xml_str = xml_str.replace('NEW_PACKAGE_NAME', package_name) root = ET.fromstring(xml_str) Utils.indent(root) tree = ET.ElementTree(root) tree.write(manifest_file, xml_declaration=True, encoding='utf-8', method='xml') LogUtils.info('The manifestFile modify successfully')
def signUpUser(postForm): newUser = True fl.session['usrName'] = postForm['email'].split('@')[0] fl.session['password'] = ut.hashPassword(postForm['password']) post = { 'email': postForm['email'], 'name': fl.session['usrName'], 'password': fl.session['password'], 'joined_on': ut.dateNow(), 'email_confirmed': False, 'gfolder_link':None, 'w_agenda_date':None, 'integrations': { 'asana': { 'auth_token':None }, 'gdrive': { 'client_id':None, 'client_secret':None, 'scope':None, 'redirect_uri':None }, 'slack':{ 'auth_token':None, 'webhook_url':None }, 'twilio':{ 'accnt_sid':None, 'auth_token':None, 'twilio_num':None, } }, 'members': { 'Add-member': { 'email': None, 'phone_num': None, 'reminder_pref': None } }, 'organization': None } try: chapter = c_chapters.find({ 'email':postForm['email'] })[0] except IndexError: chapter = None if chapter: newUser = False if newUser: c_chapters.insert_one(post) status = None elif newUser and postForm['password'] == None: status = 'Password is a required field!' elif not newUser and postForm['password'] == None: status = 'Password is a required field!' else: status = 'There already exists an account with the email {0}. Please Log in here: {1}/login'.format(usr_email, host_url) return status
def generate_r_file(package_name, decompile_dir): # check_value_resources(decompile_dir) temp_path = os.path.dirname(decompile_dir) + '/temp' LogUtils.debug('generate R:the temp path is %s', temp_path) if os.path.exists(temp_path): Utils.del_file(temp_path) os.makedirs(temp_path) res_path = decompile_dir + '/res' temp_res_path = temp_path + '/res' Utils.copy_file(res_path, temp_res_path) gen_path = temp_path + '/gen' os.makedirs(gen_path) aapt_path = Utils.get_full_path('tools/aapt2.exe') android_path = Utils.get_full_path('tools/android.jar') java = Utils.get_full_path('tools/jdk/bin/java') javac = Utils.get_full_path('tools/jdk/bin/javac') manifest_path = decompile_dir + '/AndroidManifest.xml' res_flat_path = temp_path + "/res_flat.zip" cmd = '%s compile -o %s --dir %s' % (aapt_path, res_flat_path, temp_res_path) ret = Utils.exec_cmd(cmd) if ret: return 1 cmd = '%s link -o %s --manifest %s -I %s --java %s %s' % ( aapt_path, temp_path + '/res.apk', manifest_path, android_path, gen_path, res_flat_path) ret = Utils.exec_cmd(cmd) if ret: return 1 LogUtils.info('package_name:%s', package_name) r_path = package_name.replace('.', '/') r_path = gen_path + '/' + r_path + '/R.java' cmd = '%s -source 1.8 -target 1.8 -encoding UTF-8 %s' % (javac, r_path) ret = Utils.exec_cmd(cmd) if ret: return 1 dex_path = temp_path + '/classes.dex' dex_tool_path = Utils.get_full_path('tools/dx.jar') cmd = '%s -jar %s --dex --output %s %s' % (java, dex_tool_path, dex_path, gen_path) ret = Utils.exec_cmd(cmd) if ret: return 1 smali_path = decompile_dir + '/smali' ret = dex2smali(dex_path, smali_path, '') if ret: return 1 return 0
from multiprocessing import Process '''Web Imports''' import flask as fl from pymongo import MongoClient import oauth2client.client as client '''App Imports''' import scripts.Utils as ut import scripts.ApiUtils as au '''Web & Worker Clients''' host_url = 'http://127.0.0.1:5000' # host_url = 'http://virtualadmin.herokuapp.com' app = fl.Flask(__name__) app.secret_key = ut.generateAppKey() app.logger.addHandler(logging.StreamHandler(sys.stdout)) app.logger.setLevel(logging.ERROR) '''MongoDB Client & Collections''' #For Localhost use only mongo_client = MongoClient() va_db = mongo_client['virtual-admin-db'] c_chapters = va_db['chapters'] def signUpUser(postForm): newUser = True fl.session['usrName'] = postForm['email'].split('@')[0] fl.session['password'] = ut.hashPassword(postForm['password']) post = { 'email': postForm['email'],
def recompile_apk(source_folder, apk_file, frame_work_dir): java = Utils.get_full_path('tools/jdk/bin/java') apk_tool = Utils.get_full_path('tools/apktool.jar') cmd = "%s -jar %s b %s -o %s -p %s" % (java, apk_tool, source_folder, apk_file, frame_work_dir) return Utils.exec_cmd(cmd)
def run(self): # 开启任务,发送打包信号 self.signal.signal.emit(self.channel['channelId'], 0, "正在打包......", 0) # 清空已有的workspace work_dir = Utils.get_full_path('workspace/' + self.game['id'] + '/' + self.channel['channelId']) Utils.del_file(work_dir) os.makedirs(work_dir) # 生成当前打包任务的logger,添加到字典 LogUtils.add_logger(work_dir) LogUtils.info('Current Selected Game ID is : %s, with SDK is : %s', self.game['id'], self.channel['sdk']) LogUtils.info('game:\n%s', self.game) LogUtils.info('channel:\n%s', self.channel) src_apk_path = work_dir + '/songshu.apk' # 复制上传母包到workspace result = Utils.copy_file(self.apk, src_apk_path) if self.flag(result, "打包失败:复制母包文件失败,详情查看log.log", 5): return # 反编译母包 decompile_dir = work_dir + '/decompile' frame_work_dir = work_dir + '/framework' result = ApkUtils.decompile_apk(src_apk_path, decompile_dir, frame_work_dir) if self.flag(result, "打包失败:反编译母包异常,详情查看log.log", 15): return # 复制sdk资源到工作目录 sdk_source_dir = Utils.get_full_path('channelsdk/' + self.channel['sdk']) sdk_dest_dir = work_dir + '/sdk' result = Utils.copy_file(sdk_source_dir, sdk_dest_dir) if self.flag(result, "打包失败:复制SDK文件夹失败,详情查看log.log", 18): return # 将插件里的jar资源转dex result = ApkUtils.jar2dex(sdk_source_dir, sdk_dest_dir + '/classes.dex') if self.flag(result, "打包失败:渠道jar转dex异常,详情查看log.log", 25): return # 将插件里的dex资源转smali,合并到母包反编译目录中 result = ApkUtils.dex2smali(sdk_dest_dir + '/classes.dex', decompile_dir + '/smali', '') if self.flag(result, "打包失败:渠道dex转smali异常,详情查看log.log", 28): return # 合并manifest文件 result = ApkUtils.merge_manifest(decompile_dir, sdk_dest_dir) if self.flag(result, "打包失败:合并manifest文件失败,详情查看log.log", 30): return # 复制插件libs里的so库 ApkUtils.copy_libs(decompile_dir, sdk_dest_dir) if self.flag(0, "", 33): return # 复制插件assets文件夹 result = Utils.copy_file(sdk_dest_dir + '/assets', decompile_dir + '/assets') if self.flag(result, "打包失败:复制assets文件夹失败,详情查看log.log", 35): return # 复制插件res文件夹 result = Utils.copy_file(sdk_dest_dir + '/res', decompile_dir + '/res') if self.flag(result, "打包失败:复制res文件夹失败,详情查看log.log", 38): return # 复制渠道特殊配置资源,比如,针对个别渠道设置的loading页或logo ApkUtils.copy_ext_res(self.game, decompile_dir) if self.flag(0, "", 40): return # 将游戏原来的包名替换成渠道里面的包名,四大组件也会按照相关规则替换包名 package_name = ApkUtils.rename_package_name(decompile_dir, self.channel['package']) if self.flag(0, "", 45): return # 给对应的icon添加角标 ApkUtils.append_channel_mark(self.game, sdk_dest_dir, decompile_dir) if self.flag(0, "", 50): return # 配置参数写入 result = ApkUtils.write_develop_info(self.game, self.channel, decompile_dir) if self.flag(result, "打包失败:写入配置参数失败,详情查看log.log", 52): return # 如果主sdk有特殊的逻辑。执行特殊的逻辑脚本。 result = ApkUtils.do_sdk_script(self.channel, decompile_dir, package_name, sdk_dest_dir) if self.flag(result, "打包失败:执行渠道脚本异常,详情查看log.log", 55): return # 修改游戏名称,并将meta-data写入manifest文件 ApkUtils.modify_manifest(self.channel, decompile_dir, package_name) if self.flag(0, "", 60): return # 重新生成R文件,并导入到包名下 result = ApkUtils.generate_r_file(package_name, decompile_dir) if self.flag(result, "打包失败:重新生成R文件异常,详情查看log.log", 75): return # 防止方法数超65535,判断是否分dex result = ApkUtils.classes_split(decompile_dir, sdk_dest_dir) if self.flag(result, "打包失败:分dex出现异常,详情查看log.log", 78): return # 修改apktool.yml里的压缩配置,防止包体变大 ApkUtils.edit_yml(self.channel, decompile_dir) if self.flag(0, "", 80): return # 回编译生成apk target_apk = work_dir + '/output.apk' result = ApkUtils.recompile_apk(decompile_dir, target_apk, frame_work_dir) if self.flag(result, "打包失败:回编译APK异常,详情查看log.log", 90): return # 复制添加资源到apk result = ApkUtils.copy_root_ext_files(target_apk, decompile_dir) if self.flag(result, "打包失败:母包其余资源导入异常,详情查看log.log", 92): return # apk签名(v1签名) result = ApkUtils.sign_apk(self.game, target_apk) if self.flag(result, "打包失败:渠道包签名异常,详情查看log.log", 98): return # apk对齐 time_str = QDateTime.currentDateTime().toString("yyyyMMddhhmm") dest_apk_name = self.game['name'] + '-' + self.channel[ 'name'] + '-' + time_str + '.apk' dest_apk_dir = Utils.get_full_path('output/' + self.game['id'] + '/' + self.channel['channelId']) if not os.path.exists(dest_apk_dir): os.makedirs(dest_apk_dir) dest_apk = dest_apk_dir + '/' + dest_apk_name result = ApkUtils.align_apk(target_apk, dest_apk) if self.is_close: pass else: if result == 0: self.signal.signal.emit(self.channel['channelId'], 1, "打包成功:双击打开出包目录", 100) else: self.signal.signal.emit(self.channel['channelId'], result, "打包失败:apk包体4k对齐异常,详情查看log.log", 100) LogUtils.close()
def append_channel_mark(game, sdk_dest_dir, decompile_dir): game_icon_path = 'games/' + game['id'] + '/icon/icon.png' game_icon_path = Utils.get_full_path(game_icon_path) if not os.path.exists(game_icon_path): LogUtils.info('The game %s icon is not exists : %s', game['id'], game_icon_path) return LogUtils.info('The game %s icon path : %s', game['id'], game_icon_path) game_icon_name = get_app_icon_name(decompile_dir) if game_icon_name is None: return game_icon_name = game_icon_name + '.png' LogUtils.info('The game icon name: %s', game_icon_name) icon_img = Image.open(game_icon_path) mark_path = sdk_dest_dir + '/mark.png' if not os.path.exists(mark_path): LogUtils.info('The mark path is not exists : %s', mark_path) else: LogUtils.info('The mark path : %s', mark_path) mark_img = Image.open(mark_path) icon_img = merge_icon_mark(icon_img, mark_img, (0, 0)) ldpi_icon = icon_img.resize((36, 36), Image.ANTIALIAS) mdpi_icon = icon_img.resize((48, 48), Image.ANTIALIAS) hdpi_icon = icon_img.resize((72, 72), Image.ANTIALIAS) xhdpi_icon = icon_img.resize((96, 96), Image.ANTIALIAS) xxhdpi_icon = icon_img.resize((144, 144), Image.ANTIALIAS) xxxhdpi_icon = icon_img.resize((192, 192), Image.ANTIALIAS) icons = (ldpi_icon, mdpi_icon, hdpi_icon, xhdpi_icon, xxhdpi_icon, xxxhdpi_icon) drawables = ('drawable-ldpi', 'drawable-mdpi', 'drawable-hdpi', 'drawable-xhdpi', 'drawable-xxhdpi', 'drawable-xxxhdpi') mipmaps = ('mipmap-ldpi', 'mipmap-mdpi', 'mipmap-hdpi', 'mipmap-xhdpi', 'mipmap-xxhdpi', 'mipmap-xxxhdpi') for drawable in drawables: icon_dir = decompile_dir + '/res/' + drawable Utils.del_file(icon_dir + '/' + game_icon_name) if os.path.exists(icon_dir) and len(os.listdir(icon_dir)) <= 0: os.rmdir(icon_dir) icon_dir = decompile_dir + '/res/' + drawable + '-v4' Utils.del_file(icon_dir + '/' + game_icon_name) if os.path.exists(icon_dir) and len(os.listdir(icon_dir)) <= 0: os.rmdir(icon_dir) if not os.path.exists(decompile_dir + '/res/drawable'): os.mkdir(decompile_dir + '/res/drawable') xxhdpi_icon.save(decompile_dir + '/res/drawable/' + game_icon_name, 'PNG') for i in range(len(mipmaps)): icon_dir = decompile_dir + '/res/' + mipmaps[i] + '-v4' Utils.del_file(icon_dir + '/' + game_icon_name) if os.path.exists(icon_dir) and len(os.listdir(icon_dir)) <= 0: os.rmdir(icon_dir) icon_dir = decompile_dir + '/res/' + mipmaps[i] if not os.path.exists(icon_dir): os.makedirs(icon_dir) icons[i].save(os.path.join(icon_dir, game_icon_name), 'PNG')
# -*- coding: utf-8 -*- import sys, os if hasattr(sys, 'frozen'): os.environ['PATH'] = sys._MEIPASS + ";" + os.environ['PATH'] from PyQt5.Qt import QApplication, QFile, QTextStream from scripts.MainWindow import MainWindow from scripts import Utils if __name__ == '__main__': app = QApplication(sys.argv) mainWin = MainWindow() theme = Utils.get_local_config()['THEME'] file = QFile(theme + '.qss') file.open(QFile.ReadOnly | QFile.Text) stream = QTextStream(file) mainWin.setStyleSheet(stream.readAll()) mainWin.show() sys.exit(app.exec_())