fdsa
This commit is contained in:
parent
16dbe037b9
commit
9086425c1a
@ -2,7 +2,7 @@
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:HD wallpaper.xcodeproj">
|
||||
location = "group:/Users/aaa/Documents/IOS/BZ/723/HDwallpaper/TallPaper.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
|
||||
Binary file not shown.
@ -16,7 +16,7 @@
|
||||
@end
|
||||
|
||||
@implementation AWM_AllWallpaperViewController
|
||||
- (void)backItemEvent{
|
||||
- (void)backItemEventLove:(id)sender{
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[[AWM_WallPapaerADManager shareInstance] showIntersitialAD_Back:^(NSInteger actionType) {
|
||||
[weakSelf.navigationController popViewControllerAnimated:YES];
|
||||
@ -46,7 +46,7 @@
|
||||
NSString *backitem = KLS(@"back", @"A friendly greeting");
|
||||
UIButton *backItem = [[UIButton alloc] initWithFrame:CGRectMake(20-1,0-1,74-1,44-1)];
|
||||
[backItem setImage:[UIImage imageNamed:backitem] forState:UIControlStateNormal];
|
||||
[backItem addTarget:self action:@selector(backItemEvent) forControlEvents:UIControlEventTouchUpInside];
|
||||
[backItem addTarget:self action:@selector(backItemEventLove:) forControlEvents:UIControlEventTouchUpInside];
|
||||
self.backItem = backItem;
|
||||
|
||||
self.data = @[@[@"fj1",@"fj2",@"fj3",@"fj4",@"fj5",@"fj6",@"fj7",@"fj8",@"fj9",@"fj10"],@[@"mv1",@"mv2",@"mv3",@"mv4",@"mv5",@"mv6",@"mv7",@"mv8",@"mv9",@"mv10"],@[@"kt1",@"kt2",@"kt3",@"kt4",@"kt5",@"kt6",@"kt7",@"kt8",@"kt9"],@[@"rw1",@"rw2",@"rw3",@"rw4",@"rw5",@"rw6",@"rw7",@"rw8",@"rw9",@"rw10",@"rw11",@"rw12",@"rw13",@"rw14",@"rw15",@"rw16",@"rw17",@"rw18",@"rw19"]];
|
||||
@ -87,7 +87,7 @@
|
||||
[btn setImage:[UIImage imageNamed:self.data[indexPath.section][i]] forState:UIControlStateNormal];
|
||||
btn.layer.cornerRadius = 5;
|
||||
btn.layer.masksToBounds = YES;
|
||||
[btn addTarget:self action:@selector(headerEvent:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[btn addTarget:self action:@selector(headerEventLove:) forControlEvents:UIControlEventTouchUpInside];
|
||||
btn.tag = indexPath.section;
|
||||
[cell.contentView addSubview:btn];
|
||||
}
|
||||
@ -129,7 +129,7 @@
|
||||
wpdetail.data = self.data[indexPath.section];
|
||||
[self.navigationController pushViewController:wpdetail animated:YES];
|
||||
}
|
||||
- (void)headerEvent:(UIButton *)btn{
|
||||
- (void)headerEventLove:(UIButton *)btn{
|
||||
AWM_DetailViewController *wpdetail = [[AWM_DetailViewController alloc] init];
|
||||
wpdetail.data = self.data[btn.tag];
|
||||
[self.navigationController pushViewController:wpdetail animated:YES];
|
||||
|
||||
@ -16,14 +16,14 @@
|
||||
@end
|
||||
|
||||
@implementation AWM_DetailViewController
|
||||
- (void)backItemEvent{
|
||||
- (void)backItemEventLove:(id)sender{
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[[AWM_WallPapaerADManager shareInstance] showIntersitialAD_Back:^(NSInteger actionType) {
|
||||
[weakSelf.navigationController popViewControllerAnimated:YES];
|
||||
}];
|
||||
// [self.navigationController popViewControllerAnimated:YES];
|
||||
}
|
||||
- (void)saveItemEvent{
|
||||
- (void)saveItemEventLove:(id)sender{
|
||||
UIImageWriteToSavedPhotosAlbum([UIImage imageNamed:self.data[self.index]], self, @selector(imageSavedToPhotosAlbum:didFinishSavingWithError:contextInfo:), nil);
|
||||
AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate];
|
||||
[app.saveImages addObject:self.data[self.index]];
|
||||
@ -56,13 +56,13 @@
|
||||
NSString *backitem = KLS(@"back", @"A friendly greeting");
|
||||
UIButton *backItem = [[UIButton alloc] initWithFrame:CGRectMake(20-1,0-1,74-1,44-1)];
|
||||
[backItem setImage:[UIImage imageNamed:backitem] forState:UIControlStateNormal];
|
||||
[backItem addTarget:self action:@selector(backItemEvent) forControlEvents:UIControlEventTouchUpInside];
|
||||
[backItem addTarget:self action:@selector(backItemEventLove:) forControlEvents:UIControlEventTouchUpInside];
|
||||
self.backItem = backItem;
|
||||
|
||||
UIButton *navImage = [[UIButton alloc] initWithFrame:CGRectMake(WPScreen_w-100-1,2-1,74-1,40-1)];
|
||||
NSString *save = KLS(@"save", @"A friendly greeting");
|
||||
[navImage setImage:[UIImage imageNamed:save] forState:UIControlStateNormal];
|
||||
[navImage addTarget:self action:@selector(saveItemEvent) forControlEvents:UIControlEventTouchUpInside];
|
||||
[navImage addTarget:self action:@selector(saveItemEventLove:) forControlEvents:UIControlEventTouchUpInside];
|
||||
self.navImage = navImage;
|
||||
|
||||
|
||||
@ -86,17 +86,17 @@
|
||||
UIButton *shangItem = [[UIButton alloc] initWithFrame:CGRectMake((WPScreen_w-240)/3-1,WPScreen_h-170-1,120-1,50-1)];
|
||||
NSString *shang = KLS(@"shang", @"A friendly greeting");
|
||||
[shangItem setImage:[UIImage imageNamed:shang] forState:UIControlStateNormal];
|
||||
[shangItem addTarget:self action:@selector(shangItemEvent) forControlEvents:UIControlEventTouchUpInside];
|
||||
[shangItem addTarget:self action:@selector(shangItemEventLove:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self.view addSubview:shangItem];
|
||||
|
||||
UIButton *xiaItem = [[UIButton alloc] initWithFrame:CGRectMake((WPScreen_w-240)/3*2+120-1-1,WPScreen_h-170-1-1,120-1-1,50-1-1)];
|
||||
NSString *xia = KLS(@"xia", @"A friendly greeting");
|
||||
[xiaItem setImage:[UIImage imageNamed:xia] forState:UIControlStateNormal];
|
||||
[xiaItem addTarget:self action:@selector(xiaItemEvent) forControlEvents:UIControlEventTouchUpInside];
|
||||
[xiaItem addTarget:self action:@selector(xiaItemEventLove:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self.view addSubview:xiaItem];
|
||||
|
||||
}
|
||||
- (void)shangItemEvent{
|
||||
- (void)shangItemEventLove:(id)sender{
|
||||
if (self.index == 0) {
|
||||
UIAlertView *iconAl = [[UIAlertView alloc] initWithTitle:@"" message:@"It's already the first one" delegate:self cancelButtonTitle:nil otherButtonTitles:@"ok", nil];
|
||||
[iconAl show];
|
||||
@ -105,7 +105,7 @@
|
||||
self.index --;
|
||||
[self.wpscroll setContentOffset:CGPointMake(self.index*WPScreen_w, 0)];
|
||||
}
|
||||
- (void)xiaItemEvent{
|
||||
- (void)xiaItemEventLove:(id)sender{
|
||||
if (self.index == self.data.count-1) {
|
||||
UIAlertView *iconAl = [[UIAlertView alloc] initWithTitle:@"" message:@"It's the last one" delegate:self cancelButtonTitle:nil otherButtonTitles:@"ok", nil];
|
||||
[iconAl show];
|
||||
|
||||
@ -37,13 +37,13 @@
|
||||
// btn.layer.cornerRadius = 5;
|
||||
// btn.layer.masksToBounds = YES;
|
||||
btn.tag = i;
|
||||
[btn addTarget:self action:@selector(iconEvent:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[btn addTarget:self action:@selector(iconEventLove:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self.view addSubview:btn];
|
||||
}
|
||||
|
||||
UIButton *pracy_btn = [UIButton new];
|
||||
[self.view addSubview:pracy_btn];
|
||||
[pracy_btn addTarget:self action:@selector(showUserPravcy) forControlEvents:UIControlEventTouchUpInside];
|
||||
[pracy_btn addTarget:self action:@selector(showUserPravcyLove:) forControlEvents:UIControlEventTouchUpInside];
|
||||
NSString *privacy = KLS(@"privacy", @"A friendly greeting");
|
||||
[pracy_btn setTitle:privacy forState:UIControlStateNormal];
|
||||
[pracy_btn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
|
||||
@ -55,12 +55,12 @@
|
||||
}
|
||||
|
||||
//显示用户隐私
|
||||
- (void)showUserPravcy {
|
||||
- (void)showUserPravcyLove:(id)s {
|
||||
AWM_UserPravcyVC *vc = [AWM_UserPravcyVC new];
|
||||
[self.navigationController pushViewController:vc animated:YES];
|
||||
}
|
||||
|
||||
- (void)iconEvent:(UIButton *)icon{
|
||||
- (void)iconEventLove:(UIButton *)icon{
|
||||
if (icon.tag == 0) {
|
||||
AWM_wallpaperViewController *wpdetail = [[AWM_wallpaperViewController alloc] init];
|
||||
[self.navigationController pushViewController:wpdetail animated:YES];
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
UIButton *searchBtn = [[UIButton alloc] initWithFrame:CGRectMake((WPScreen_w-300)/2-1,100-1,300-1,96-1)];
|
||||
NSString *search = KLS(@"search", @"A friendly greeting");
|
||||
[searchBtn setBackgroundImage:[UIImage imageNamed:search] forState:UIControlStateNormal];
|
||||
[searchBtn addTarget:self action:@selector(searchEvent) forControlEvents:UIControlEventTouchUpInside];
|
||||
[searchBtn addTarget:self action:@selector(searchEventLove) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self.view addSubview:searchBtn];
|
||||
|
||||
self.table = [[UITableView alloc] initWithFrame:CGRectMake(0-1,220-1,WPScreen_w-1,WPScreen_h-220-1) style:UITableViewStyleGrouped];
|
||||
@ -47,7 +47,7 @@
|
||||
self.table.separatorColor = [UIColor clearColor];
|
||||
[self.view addSubview:self.table];
|
||||
}
|
||||
- (void)searchEvent{
|
||||
- (void)searchEventLove{
|
||||
AWM_SearchViewController *vc = [[AWM_SearchViewController alloc] init];
|
||||
[self.navigationController pushViewController:vc animated:YES];
|
||||
}
|
||||
@ -78,7 +78,7 @@
|
||||
[btn setImage:[UIImage imageNamed:self.data[indexPath.section][i]] forState:UIControlStateNormal];
|
||||
btn.layer.cornerRadius = 5;
|
||||
btn.layer.masksToBounds = YES;
|
||||
[btn addTarget:self action:@selector(headerEvent) forControlEvents:UIControlEventTouchUpInside];
|
||||
[btn addTarget:self action:@selector(headerEventLove:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[bgView addSubview:btn];
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@
|
||||
[bgView addSubview:more];
|
||||
return cell;
|
||||
}
|
||||
- (void)headerEvent{
|
||||
- (void)headerEventLove:(id)sender{
|
||||
AWM_AllWallpaperViewController *wpdetail = [[AWM_AllWallpaperViewController alloc] init];
|
||||
[self.navigationController pushViewController:wpdetail animated:YES];
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
UIButton *searchBtn = [[UIButton alloc] initWithFrame:CGRectMake((WPScreen_w-300)/2-1,100-1,300-1,96-1)];
|
||||
NSString *search = KLS(@"search", @"A friendly greeting");
|
||||
[searchBtn setBackgroundImage:[UIImage imageNamed:search] forState:UIControlStateNormal];
|
||||
[searchBtn addTarget:self action:@selector(searchEvent) forControlEvents:UIControlEventTouchUpInside];
|
||||
[searchBtn addTarget:self action:@selector(searchEventLove:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self.view addSubview:searchBtn];
|
||||
|
||||
self.table = [[UITableView alloc] initWithFrame:CGRectMake(0-1,220-1,WPScreen_w-1,WPScreen_h-220-1) style:UITableViewStyleGrouped];
|
||||
@ -46,7 +46,7 @@
|
||||
self.table.separatorColor = [UIColor clearColor];
|
||||
[self.view addSubview:self.table];
|
||||
}
|
||||
- (void)searchEvent{
|
||||
- (void)searchEventLove:(id)s{
|
||||
AWM_SearchViewController *vc = [[AWM_SearchViewController alloc] init];
|
||||
[self.navigationController pushViewController:vc animated:YES];
|
||||
}
|
||||
@ -64,7 +64,7 @@
|
||||
return 3*(10+space*1.5)+30;
|
||||
}
|
||||
}
|
||||
- (void)headerEvent{
|
||||
- (void)headerEvent:(id)s{
|
||||
AWM_AllWallpaperViewController *wpdetail = [[AWM_AllWallpaperViewController alloc] init];
|
||||
[self.navigationController pushViewController:wpdetail animated:YES];
|
||||
}
|
||||
@ -82,7 +82,7 @@
|
||||
header.userInteractionEnabled = YES;
|
||||
|
||||
UIButton *headerbtn = [[UIButton alloc] initWithFrame:header.bounds];
|
||||
[headerbtn addTarget:self action:@selector(headerEvent) forControlEvents:UIControlEventTouchUpInside];
|
||||
[headerbtn addTarget:self action:@selector(headerEvent:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[cell.contentView addSubview:header];
|
||||
}
|
||||
}else{
|
||||
@ -99,7 +99,7 @@
|
||||
[btn setImage:[UIImage imageNamed:self.data[indexPath.section][i]] forState:UIControlStateNormal];
|
||||
btn.layer.cornerRadius = 5;
|
||||
btn.layer.masksToBounds = YES;
|
||||
[btn addTarget:self action:@selector(headerEvent) forControlEvents:UIControlEventTouchUpInside];
|
||||
[btn addTarget:self action:@selector(headerEvent:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[bgView addSubview:btn];
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
@end
|
||||
|
||||
@implementation AWM_SearchViewController
|
||||
- (void)backItemEvent{
|
||||
- (void)backItemEventLove:(id)sender{
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[[AWM_WallPapaerADManager shareInstance] showIntersitialAD_Back:^(NSInteger actionType) {
|
||||
[weakSelf.navigationController popViewControllerAnimated:YES];
|
||||
@ -50,7 +50,7 @@
|
||||
NSString *greeting1 = KLS(@"back", @"A friendly greeting");
|
||||
UIButton *backItem = [[UIButton alloc] initWithFrame:CGRectMake(20-1,0-1,74-1,44-1)];
|
||||
[backItem setImage:[UIImage imageNamed:greeting1] forState:UIControlStateNormal];
|
||||
[backItem addTarget:self action:@selector(backItemEvent) forControlEvents:UIControlEventTouchUpInside];
|
||||
[backItem addTarget:self action:@selector(backItemEventLove:) forControlEvents:UIControlEventTouchUpInside];
|
||||
self.backItem = backItem;
|
||||
|
||||
UIImageView *navImage = [[UIImageView alloc] initWithFrame:CGRectMake(WPScreen_w-150-1,8-1,130-1,28-1)];
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
NSString *greeting = KLS(@"back", @"A friendly greeting");
|
||||
UIButton *backItem = [[UIButton alloc] initWithFrame:CGRectMake(20-1,0-1,74-1,44-1)];
|
||||
[backItem setImage:[UIImage imageNamed:greeting] forState:UIControlStateNormal];
|
||||
[backItem addTarget:self action:@selector(backItemEvent) forControlEvents:UIControlEventTouchUpInside];
|
||||
[backItem addTarget:self action:@selector(backItemEventLove:) forControlEvents:UIControlEventTouchUpInside];
|
||||
self.backItem = backItem;
|
||||
|
||||
// UILabel *titleLabel = [UILabel new];
|
||||
@ -60,7 +60,7 @@
|
||||
[webView loadRequest:request];
|
||||
}
|
||||
|
||||
- (void)backItemEvent{
|
||||
- (void)backItemEventLove:(id)sender{
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
NSString *addpic = KLS(@"addpic", @"A friendly greeting");
|
||||
UIButton *addImage = [[UIButton alloc] initWithFrame:CGRectMake((WPScreen_w-150)/2-1,650-1,150-1,75-1)];
|
||||
[addImage setImage:[UIImage imageNamed:addpic] forState:UIControlStateNormal];
|
||||
[addImage addTarget:self action:@selector(selectPhoto) forControlEvents:UIControlEventTouchUpInside];
|
||||
[addImage addTarget:self action:@selector(selectPhotoLove:) forControlEvents:UIControlEventTouchUpInside];
|
||||
// addImage.center = self.view.center;
|
||||
[self.view addSubview:addImage];
|
||||
self.addImage = addImage;
|
||||
@ -42,7 +42,7 @@
|
||||
self.showImage = showImage;
|
||||
|
||||
}
|
||||
- (void)selectPhoto{
|
||||
- (void)selectPhotoLove:(id)sender{
|
||||
if (self.isShow) {
|
||||
__weak typeof(self)weakSelf = self;
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
@end
|
||||
|
||||
@implementation AWM_wallpaperViewController
|
||||
- (void)backItemEvent{
|
||||
- (void)backItemEventLove:(id)sender{
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[[AWM_WallPapaerADManager shareInstance] showIntersitialAD_Back:^(NSInteger actionType) {
|
||||
[weakSelf.navigationController popViewControllerAnimated:YES];
|
||||
@ -59,7 +59,7 @@
|
||||
NSString *backitem = KLS(@"back", @"A friendly greeting");
|
||||
UIButton *backItem = [[UIButton alloc] initWithFrame:CGRectMake(20-1,0-1,74-1,44-1)];
|
||||
[backItem setImage:[UIImage imageNamed:backitem] forState:UIControlStateNormal];
|
||||
[backItem addTarget:self action:@selector(backItemEvent) forControlEvents:UIControlEventTouchUpInside];
|
||||
[backItem addTarget:self action:@selector(backItemEventLove:) forControlEvents:UIControlEventTouchUpInside];
|
||||
self.backItem = backItem;
|
||||
NSString *greeting3 = KLS(@"navmy", @"A friendly greeting");
|
||||
UIImageView *navImage = [[UIImageView alloc] initWithFrame:CGRectMake(WPScreen_w-150-1,8-1,130-1,28-1)];
|
||||
@ -94,7 +94,7 @@
|
||||
[btn setImage:[UIImage imageNamed:self.data[i]] forState:UIControlStateNormal];
|
||||
btn.layer.cornerRadius = 5;
|
||||
btn.layer.masksToBounds = YES;
|
||||
[btn addTarget:self action:@selector(headerEvent) forControlEvents:UIControlEventTouchUpInside];
|
||||
[btn addTarget:self action:@selector(headerEventLove:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[cell.contentView addSubview:btn];
|
||||
}
|
||||
return cell;
|
||||
@ -121,7 +121,7 @@
|
||||
wpdetail.data = self.data;
|
||||
[self.navigationController pushViewController:wpdetail animated:YES];
|
||||
}
|
||||
- (void)headerEvent{
|
||||
- (void)headerEventLove:(id)sender{
|
||||
AWM_DetailViewController *wpdetail = [[AWM_DetailViewController alloc] init];
|
||||
wpdetail.data = self.data;
|
||||
[self.navigationController pushViewController:wpdetail animated:YES];
|
||||
|
||||
3
HX/.idea/.gitignore
generated
vendored
Normal file
3
HX/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
9
HX/.idea/HX.iml
generated
Normal file
9
HX/.idea/HX.iml
generated
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
HX/.idea/misc.xml
generated
Normal file
6
HX/.idea/misc.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
HX/.idea/modules.xml
generated
Normal file
8
HX/.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/HX.iml" filepath="$PROJECT_DIR$/.idea/HX.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
HX/.idea/vcs.xml
generated
Normal file
6
HX/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
197
HX/AddClashCodeToFile.py
Normal file
197
HX/AddClashCodeToFile.py
Normal file
@ -0,0 +1,197 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
import os,sys
|
||||
import random
|
||||
import string
|
||||
import re
|
||||
import time
|
||||
import json
|
||||
import shutil
|
||||
import hashlib
|
||||
import time
|
||||
import argparse
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
script_path = os.path.split(os.path.realpath(sys.argv[0]))[0]
|
||||
|
||||
swiftFunPattern = "func.*?\\{"
|
||||
|
||||
#目前oc只向对象实例方法注入垃圾代码
|
||||
ocFunPattern = "-.*?\\{"
|
||||
|
||||
#需要忽略的文件,写入这里后,这些文件将不会被添加垃圾代码
|
||||
ignore_files = ["ZHAuthorSetVC.m", "DownloadManager.swift"]
|
||||
|
||||
#用于匹配 // 注释 的文本信息,在插入函数垃圾代码前,需要清除掉注释,避免在被注释的函数中添加垃圾代码而导致编译不过
|
||||
explanatoryPattern = "(^//.*)"
|
||||
|
||||
#判断是否应该被忽略插入垃圾代码
|
||||
def isNeedIgnore(fileName):
|
||||
global ignore_files
|
||||
for file in ignore_files:
|
||||
if fileName.find(file) != -1:
|
||||
return True
|
||||
return False
|
||||
|
||||
#单词列表,用以随机名称
|
||||
with open(os.path.join(script_path, "./word_list.json"), "r") as fileObj:
|
||||
word_name_list = json.load(fileObj)
|
||||
|
||||
# 随机获取一个字符
|
||||
def get_random_char():
|
||||
# 可以根据需要更改字符的范围
|
||||
ascii_uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz'
|
||||
digits = '0123456789'
|
||||
# 这里可以选择不同的字符集合进行随机选择
|
||||
char_sets = [ascii_uppercase, ascii_lowercase, digits]
|
||||
char_set = random.choice(char_sets)
|
||||
return random.choice(char_set)
|
||||
|
||||
#获取一个随机变量名称
|
||||
def getVeriableName():
|
||||
global word_name_list
|
||||
return random.choice(word_name_list) + "_" + get_random_char()
|
||||
|
||||
|
||||
#向OC文件的既有函数添加垃圾代码
|
||||
def addClashCode2OC(filePath):
|
||||
global ocFunPattern
|
||||
print("\n开始向:\n%s\n添加垃圾代码\n" %filePath)
|
||||
with open(filePath,"r",errors="ignore") as fileObj:
|
||||
fileContent_text = fileObj.read()
|
||||
fileObj.close()
|
||||
matches = re.finditer(ocFunPattern,fileContent_text)
|
||||
#倒序遍历匹配的结果
|
||||
for match in reversed(list(matches)):
|
||||
firstPart_text = fileContent_text[:match.end()]
|
||||
firstPart_text = firstPart_text +"\n" + " " + getOCFakeCode() + "\n"
|
||||
fileContent_text = firstPart_text + fileContent_text[match.end():]
|
||||
#print("match position:",match.end())
|
||||
with open(filePath,"w",errors="ignore") as fileObj:
|
||||
fileObj.write(fileContent_text)
|
||||
|
||||
|
||||
|
||||
#获取OC垃圾伪装代码
|
||||
def getOCFakeCode():
|
||||
random_number = random.randint(1, 2)
|
||||
if random_number == 1:
|
||||
return getOCFakeCode_1()
|
||||
else:
|
||||
return getOCFakeCode_2()
|
||||
|
||||
#oc代码格式1
|
||||
def getOCFakeCode_1():
|
||||
vn1 = getVeriableName()
|
||||
vn2 = getVeriableName()
|
||||
vn_key = getVeriableName()
|
||||
resultText = "\nNSDateFormatter *%s = [NSDateFormatter new];\n[%s setDateFormat:@\"yyyy-MM-dd HH:mm\"];\nNSString *%s = [%s stringFromDate:[NSDate date]];\n[[NSUserDefaults standardUserDefaults] setObject:%s forKey:@\"%s\"];\n" %(vn1,vn1,vn2,vn1,vn2,vn_key)
|
||||
return resultText
|
||||
|
||||
#oc代码格式2
|
||||
def getOCFakeCode_2():
|
||||
digits = '0123456789'
|
||||
value1 = random.choice(digits)
|
||||
|
||||
vn1 = getVeriableName()
|
||||
vn2 = getVeriableName()
|
||||
vn_key = getVeriableName()
|
||||
resultText = "\nNSInteger %s = %s;\nNSInteger %s = [[NSUserDefaults standardUserDefaults] integerForKey:@\"%s\"];\n%s *= %s;\n[[NSUserDefaults standardUserDefaults] setInteger:%s forKey:@\"%s\"];\n" %(vn1,value1,vn2,vn_key,vn2,vn1,vn2,vn_key)
|
||||
return resultText
|
||||
|
||||
|
||||
|
||||
#向Swift文件的既有函数添加垃圾代码
|
||||
def addClashCode2Swift(filePath):
|
||||
global swiftFunPattern
|
||||
print("\n开始向:\n%s\n添加垃圾代码\n" %filePath)
|
||||
with open(filePath,"r",errors="ignore") as fileObj:
|
||||
fileContent_text = fileObj.read()
|
||||
fileObj.close()
|
||||
matches = re.finditer(swiftFunPattern,fileContent_text)
|
||||
#倒序遍历匹配的结果
|
||||
for match in reversed(list(matches)):
|
||||
firstPart_text = fileContent_text[:match.end()]
|
||||
firstPart_text = firstPart_text +"\n" + " " + getSwiftFakeCode() + "\n"
|
||||
fileContent_text = firstPart_text + fileContent_text[match.end():]
|
||||
#print("match position:",match.end())
|
||||
with open(filePath,"w",errors="ignore") as fileObj:
|
||||
fileObj.write(fileContent_text)
|
||||
|
||||
#获取swift垃圾伪装代码
|
||||
def getSwiftFakeCode():
|
||||
random_number = random.randint(1, 2)
|
||||
if random_number == 1:
|
||||
return getSwiftFakeCode_1()
|
||||
else:
|
||||
return getSwiftFakeCode_2()
|
||||
|
||||
#swift代码格式1
|
||||
def getSwiftFakeCode_1():
|
||||
vn1 = getVeriableName()
|
||||
digits = '0123456789'
|
||||
value1 = random.choice(digits)
|
||||
|
||||
vn2 = getVeriableName()
|
||||
vn2_key = getVeriableName()
|
||||
|
||||
vn3 = getVeriableName()
|
||||
|
||||
resultText = "\nlet %s:Int = %s\nlet %s:Int = UserDefaults.standard.integer(forKey: \"%s\")\nvar %s = %s * %s\nUserDefaults.standard .setValue(%s, forKey: \"%s\")\n" %(vn1,value1,vn2,vn2_key,vn3,vn1,vn2,vn3,vn2_key)
|
||||
return resultText
|
||||
|
||||
#swift代码格式2
|
||||
def getSwiftFakeCode_2():
|
||||
vn1 = getVeriableName()
|
||||
vn2 = getVeriableName()
|
||||
vn_key = getVeriableName()
|
||||
resultText = "\nlet %s = DateFormatter() \n%s.dateStyle = .full\nlet %s = %s.string(from: NSDate.now)\nUserDefaults.standard .setValue(%s, forKey: \"%s\")\n" %(vn1,vn1,vn2,vn1,vn2,vn_key)
|
||||
return resultText
|
||||
|
||||
|
||||
#解析初始化参数
|
||||
def parase_args():
|
||||
global script_path
|
||||
parseParam = argparse.ArgumentParser(description='添加垃圾代码.\n')
|
||||
#存放代码的根路径,即需要 函数 被添加垃圾代码 的根路径,该程序将遍历这个目录下的所有文件(即包含子目录的子文件 执行垃圾代码添加)
|
||||
parseParam.add_argument('--code_dir', dest='code_dir', type=str, required=False, default=script_path, help='需要添加垃圾函数代码的根目录')
|
||||
print("paraseParam:",parseParam)
|
||||
return parseParam.parse_args()
|
||||
|
||||
#进行循环处理目录中的文件
|
||||
def cycleDealDir(need_dealDir):
|
||||
print("开始循环这个目录:",need_dealDir)
|
||||
if not os.path.exists(need_dealDir):
|
||||
print("当前目录不存在:",need_dealDir)
|
||||
#以walk的方式,本身就会遍历完毕当前目录下的所有文件
|
||||
for parent,folders,files in os.walk(need_dealDir):
|
||||
#print("遍历子文件...")
|
||||
for file in files:
|
||||
filePath = os.path.join(parent, file)
|
||||
file_extension = file.split(".")[-1]
|
||||
if file_extension == "swift" and not isNeedIgnore(file):
|
||||
addClashCode2Swift(filePath)
|
||||
elif file_extension == "m" and not isNeedIgnore(file):
|
||||
addClashCode2OC(filePath)
|
||||
else:
|
||||
print("其他类型的文件暂不处理:",file)
|
||||
|
||||
|
||||
def main():
|
||||
#解析参数
|
||||
parseParam = parase_args()
|
||||
|
||||
#获取只要添加垃圾代码的目标 文件夹
|
||||
cycleDealDir(parseParam.code_dir)
|
||||
|
||||
#遍历获取目标文件夹中的目标文件
|
||||
#过滤 需要忽略的目标文件
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
12604
HX/ClassName_list.json
Normal file
12604
HX/ClassName_list.json
Normal file
File diff suppressed because it is too large
Load Diff
118
HX/README.md
Normal file
118
HX/README.md
Normal file
@ -0,0 +1,118 @@
|
||||
# iosMixTools
|
||||
ios混淆脚本工具,主要用于游戏类。顺便安利一波: [IOS马甲包混淆](https://blog.csdn.net/lyzz0612/article/details/80390362)
|
||||
有任何问题和建议欢迎联系: email: lyzz0612@qq.com
|
||||
|
||||
## Updated
|
||||
这些工具用完目前还是2.1被拒, 4.3的可以尝试下;第三方加固工具试用版也被拒,目前在打算先用小游戏过审。
|
||||
|
||||
资源混淆感觉应该够了,但还是被4.3。这边用的游戏引擎代码基本没动,准备对它动刀了
|
||||
|
||||
* 定义宏加到代码不同地方,根据行号不同插入不同代码,可引入第三方库
|
||||
```
|
||||
#define MIX_FUNC_1 {SOME CODE}
|
||||
#define MIX_FUNC(__LINE__) MIX_FUNC_##__LINE__
|
||||
```
|
||||
|
||||
* 改写原有宏实现,如cocos引擎的CCASSERT,CCLOG
|
||||
* 替换字符串,改为解密加密字符串
|
||||
|
||||
### Updated 2019/01/17
|
||||
刚用小游戏提审过了,主要改地方是
|
||||
1. 没加垃圾资源,但是把所有资源打成加密zip包+xor加密,启动时再解压执行。这样苹果机审应该不可能扫出重复资源来
|
||||
2. 换iOS类名、函数名。原来只是加了垃圾函数,类名也只是加前缀,这次全换了完全不同的名字
|
||||
3. 换机器打包、提审。本来公司就几台打包机器,提了很多次估计被标记了,一提就封号……这次是自己的电脑打包和提审的
|
||||
4. 去掉热更联网检查,改为固定时间判断。原来是启动会检查更新,虽然提示是改成正在加载资源了,但有可能检测到网络数据了。这次直接固定提审1个月开放热更
|
||||
|
||||
### Updated
|
||||
发现新的混淆工具[https://github.com/zfjsyqk/ZFJObsLib](https://github.com/zfjsyqk/ZFJObsLib),看描述功能很齐全,待试用。
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 1. addNative.py 生成oc垃圾代码工具
|
||||
此脚本会扫描指定目录,给OC文件添加垃圾函数,同时创建垃圾文件到/trash目录。
|
||||
#### 参数说明
|
||||
|
||||
* ` --oc_folder OC_FOLDER` OC_FOLDER为OC代码所在目录
|
||||
* `--replace`替换OC_FOLDER下的原文件,同时原代码会备份到脚本目录下的backup_ios目录。不指定此项垃圾代码只会放到脚本目录下的target_ios/
|
||||
|
||||
addNative.py里还有一些配置可以看需求手动修改,如生成垃圾文件的数量,垃圾函数的数量,忽略文件列表等,具体请查看代码顶部相关注释
|
||||
|
||||
### 2. renameNative.py 修改类名前缀工具
|
||||
类名是引用可能较为复杂的东西,工具批量替换的限制要求会比较多。如果你的项目满足以下条件,那么这个工具会比较适合你:
|
||||
|
||||
* 大部分类名都带相同的前缀,也只准备替换前缀;
|
||||
* 大部分类都只在一个大文件夹下,它们之间相互引用,外部调用的情况较少并且你能很有把握的排除或手动替换它们;
|
||||
* 类名和文件名一致;
|
||||
|
||||
本工具的流程是扫描指定文件夹,找到名称(或者说类名,工具假设两者是一致的)以指定前缀开始的文件;修改替换文件名前缀;并再次遍历此文件夹所有文件,将文件内容中的所有该名称也替换掉;替换xx.xcodeproj/project.pbxproj下的路径,省去在Xcode中手动添加文件(因为文件名修改了,不替换的话Xcode上还保持原来的名称会提示找不到文件);同时为了防止文件夹名称跟文件名相同而导致替换project.pbxproj时将目录名也替换掉的情况,对文件夹名称也进行相同的流程。
|
||||
|
||||
#### 参数说明:
|
||||
|
||||
* `--add_prefix PREFIX` 添加类名前缀,有此项old_prefix和new_prefix将不起作用,此项请提前在renameNative.py文件中ignore_path_text添加不需要前缀的文件或路径
|
||||
* `--old_prefix OLD_PREFIX` 替换前的类名前缀
|
||||
* `--new_prefix NEW_PREFIX` 替换后的类名前缀
|
||||
* `--ios_path IOS_PATH` OC文件目录
|
||||
* `--proj_path PROJ_PATH ` xx.xcodeproj路径
|
||||
|
||||
运行示例:
|
||||
`python renameNative.py --add_prefix ANDROID --ios_path xx/xx/xx/ --proj_path xx/xx/xx.xcodeproj`
|
||||
`python renameNative.py --old_prefix ANDROID --new_prefix IOS --ios_path xx/xx/xx/ --proj_path xx/xx/xx.xcodeproj`
|
||||
|
||||
|
||||
### 3. autoBornCode.py 添加lua和png,修改资源文件MD5
|
||||
此脚本会扫描指定文件夹,在路径包含/res的目录创建png, 其他地方创建lua。根据目录下的文件和文件夹数随机添加文件和子文件夹,创建数量是根据目录下原有文件和文件夹的数量随机。然后会给大部分类型资源文件添加一些无效内容来改变其MD5。
|
||||
|
||||
#### 参数说明
|
||||
|
||||
* `--res RESOURCE_DIR` 资源目录
|
||||
* `--target TARGET_FOLDER` 可选参数,修改后的资源存放目录。不设置为脚本目录下的target_resource
|
||||
|
||||
在代码的最前面有个匹配规则, path_exclude表示必须是不包含该字符串的路径才能创建该类型文件,path_include表示必须是包含该字符串的路径才要创建该类型文件
|
||||
```
|
||||
match_rule = {
|
||||
".png": {
|
||||
"path_include": os.path.sep + "res",
|
||||
},
|
||||
".lua": {
|
||||
# "path_include": "src",
|
||||
"path_exclude": os.path.sep + "res",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
**TODO**音效文件修改MD5值
|
||||
|
||||
|
||||
### 4. iOS加固插件
|
||||
[五款iOS加固产品测试与点评](http://telecom.chinabyte.com/300/14570300.shtml)
|
||||
|
||||
[加固产品比较](https://www.codercto.com/a/28193.html)
|
||||
|
||||
1. Obfuscator-LLVM
|
||||
|
||||
[Obfuscator-LLVM在iOS中的实践](https://www.jianshu.com/p/a631b5584de6)
|
||||
[obfuscator-llvm Github Installation](https://github.com/obfuscator-llvm/obfuscator/wiki/Installation)
|
||||
配置了一下,编译了好长时间发现支持的clang版本只到4.0,很多issue都没人管了,而且不支持字符串混淆,优点是开源,有空可以自己折腾一下
|
||||
|
||||
2. 网易的试用需要审核
|
||||
|
||||
[网易易盾](http://dun.163.com/product/ios-reinforce)
|
||||
|
||||
3. 顶象的试用插件有大概半个月的期限,~~只支持30%的加固,不过对我们提审的来说应该够了~~ 经试验试用版提审会被2.3.1拒绝,提示用了代码混淆
|
||||
|
||||
[顶象](https://www.dingxiang-inc.com/business/ios)
|
||||
[顶象文档](https://cdn.dingxiang-inc.com/public-service/docs/compiler-ios/)
|
||||
|
||||
|
||||
4. 几维安全、360都是在线加固的
|
||||
|
||||
[几维安全静态库](https://www.kiwisec.com/product/app-encrypt.html)
|
||||
[加固保iOS](http://jiagu.360.cn/#/app/android)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
240
HX/addNativeCode.py
Normal file
240
HX/addNativeCode.py
Normal file
@ -0,0 +1,240 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
# 添加OC垃圾代码
|
||||
import os,sys
|
||||
import random
|
||||
import string
|
||||
import re
|
||||
#import md5
|
||||
import time
|
||||
import json
|
||||
import shutil
|
||||
import hashlib
|
||||
import time
|
||||
import argparse
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
#sys.setdefaultencoding("utf-8")
|
||||
|
||||
script_path = os.path.split(os.path.realpath(sys.argv[0]))[0]
|
||||
#垃圾代码临时存放目录
|
||||
target_ios_folder = os.path.join(script_path, "./target_ios")
|
||||
#备份目录
|
||||
backup_ios_folder = os.path.join(script_path, "./backup_ios")
|
||||
|
||||
#忽略文件列表,不给这些文件添加垃圾函数
|
||||
ignore_file_list = ["main.m", "GNative.mm", "MobClickCpp.mm"]
|
||||
#忽略文件夹列表,不处理这些文件夹下的文件
|
||||
ignore_folder_list = ["thirdparty","Support",".svn","paycenter","UMMobClick.framework","UMessage_Sdk_1.5.0a","TencentOpenApi_IOS_Bundle.bundle",
|
||||
"TencentOpenAPI.framework","Bugly.framework","AlipaySDK.framework","AlipaySDK.bundle"]
|
||||
|
||||
#创建函数数量范围
|
||||
create_func_min = 2
|
||||
create_func_max = 10
|
||||
|
||||
#创建垃圾文件数量范围
|
||||
create_file_min = 10
|
||||
create_file_max = 100
|
||||
|
||||
#oc代码目录
|
||||
ios_src_path = ""
|
||||
|
||||
#确保添加的函数不重名
|
||||
funcname_set = set()
|
||||
|
||||
#单词列表,用以随机名称
|
||||
with open(os.path.join(script_path, "./word_list.json"), "r") as fileObj:
|
||||
word_name_list = json.load(fileObj)
|
||||
|
||||
#获取一个随机名称
|
||||
def getOneName():
|
||||
global word_name_list
|
||||
return random.choice(word_name_list)
|
||||
|
||||
#oc代码头文件函数声明
|
||||
def getOCHeaderFuncText():
|
||||
funcName = getOneName()
|
||||
text = "\n- (void)%s" %(funcName)
|
||||
return text
|
||||
|
||||
#oc代码函数实现模板
|
||||
def getOCFuncText(header_text):
|
||||
arg1 = getOneName()
|
||||
arg2 = getOneName()
|
||||
text = [
|
||||
header_text + "\n",
|
||||
"{\n",
|
||||
"\tint %s = 2;\n" %(arg1),
|
||||
"\tint %s = 3;\n" %(arg2),
|
||||
"\t%s += %s ;\n" %(arg2,arg1),
|
||||
"\t[[NSUserDefaults standardUserDefaults] setObject:@(%s) forKey:@\"%s\"];\n" %(arg2,arg1),
|
||||
"\tNSLog(@\"%s\");\n" %(arg1),
|
||||
"}\n"
|
||||
]
|
||||
return "".join(text)
|
||||
|
||||
#oc代码以@end结尾,在其前面添加text
|
||||
def appendTextToOCFile(file_path, text):
|
||||
with open(file_path, "r") as fileObj:
|
||||
old_text = fileObj.read()
|
||||
fileObj.close()
|
||||
end_mark_index = old_text.rfind("@end")
|
||||
if end_mark_index == -1:
|
||||
print("\t非法的结尾格式: " + file_path)
|
||||
return
|
||||
new_text = old_text[:end_mark_index]
|
||||
new_text = new_text + text + "\n"
|
||||
new_text = new_text + old_text[end_mark_index:]
|
||||
|
||||
with open(file_path, "w") as fileObj:
|
||||
fileObj.write(new_text)
|
||||
|
||||
#处理单个OC文件,添加垃圾函数。确保其对应头文件存在于相同目录
|
||||
def dealWithOCFile(filename, file_path):
|
||||
global target_ios_folder,create_func_min,create_func_max,funcname_set
|
||||
funcname_set.clear()
|
||||
end_index = file_path.rfind(".")
|
||||
pre_name = file_path[:end_index]
|
||||
header_path = pre_name + ".h"
|
||||
if not os.path.exists(header_path):
|
||||
print ("\t相应头文件不存在:" + file_path)
|
||||
return
|
||||
|
||||
new_func_num = random.randint(create_func_min, create_func_max)
|
||||
print ("\t给%s添加%d个方法" %(filename, new_func_num))
|
||||
for i in range(new_func_num):
|
||||
header_text = getOCHeaderFuncText()
|
||||
# print "add %s to %s" %(header_text, header_path.replace(target_ios_folder, ""))
|
||||
appendTextToOCFile(header_path, header_text + ";\n")
|
||||
funcText = getOCFuncText(header_text)
|
||||
appendTextToOCFile(file_path, funcText)
|
||||
|
||||
#扫描parent_folder,添加垃圾函数,处理了忽略列表
|
||||
def addOCFunctions(parent_folder):
|
||||
global ignore_file_list
|
||||
for parent, folders, files in os.walk(parent_folder):
|
||||
need_ignore = None
|
||||
for ignore_folder in ignore_folder_list:
|
||||
if parent.find("/" + ignore_folder) != -1:
|
||||
need_ignore = ignore_folder
|
||||
break
|
||||
if need_ignore:
|
||||
print ("\t忽略文件夹" + ignore_folder)
|
||||
continue
|
||||
|
||||
for file in files:
|
||||
if file.endswith(".m") or file.endswith(".mm"):
|
||||
if file in ignore_file_list:
|
||||
continue
|
||||
dealWithOCFile(file, os.path.join(parent, file))
|
||||
|
||||
#新创建的垃圾文件header模板
|
||||
def getOCHeaderFileText(class_name):
|
||||
global funcname_set
|
||||
new_func_name = getOneName()
|
||||
while new_func_name in funcname_set:
|
||||
new_func_name = getOneName()
|
||||
funcname_set.add(new_func_name)
|
||||
|
||||
text = [
|
||||
"#import <Foundation/Foundation.h>\n\n",
|
||||
"@interface %s : NSObject {\n" %(class_name),
|
||||
"\tint %s;\n" %(new_func_name),
|
||||
"\tfloat %s;\n" %(getOneName()),
|
||||
"}\n\n@end"
|
||||
]
|
||||
return "".join(text)
|
||||
|
||||
#新创建的垃圾文件mm模板
|
||||
def getOCMMFileText(class_name):
|
||||
text = [
|
||||
'#import "%s.h"\n\n' %(class_name),
|
||||
"@implementation %s\n" %(class_name),
|
||||
"\n\n@end"
|
||||
]
|
||||
return "".join(text)
|
||||
|
||||
#添加垃圾文件到parent_folder/trash/
|
||||
def addOCFile(parent_folder):
|
||||
global create_file_min, create_file_max
|
||||
file_list = []
|
||||
target_folder = os.path.join(parent_folder, "trash")
|
||||
if os.path.exists(target_folder):
|
||||
shutil.rmtree(target_folder)
|
||||
os.mkdir(target_folder)
|
||||
file_num = random.randint(create_file_min, create_file_max)
|
||||
for i in range(file_num):
|
||||
file_name = getOneName()
|
||||
file_list.append("#import \"" + file_name + ".h\"")
|
||||
print ("\t创建OC文件 trash/" + file_name)
|
||||
header_text = getOCHeaderFileText(file_name)
|
||||
full_path = os.path.join(target_folder, file_name + ".h")
|
||||
with open(full_path, "w") as fileObj:
|
||||
fileObj.write(header_text)
|
||||
fileObj.close()
|
||||
|
||||
mm_text = getOCMMFileText(file_name)
|
||||
full_path = os.path.join(target_folder, file_name + ".mm")
|
||||
with open(full_path, "w") as fileObj:
|
||||
fileObj.write(mm_text)
|
||||
all_header_text = "\n".join(file_list)
|
||||
|
||||
with open(os.path.join(parent_folder, "Trash.h"), "w") as fileObj:
|
||||
fileObj.write(all_header_text)
|
||||
fileObj.close()
|
||||
|
||||
#解析参数
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description='oc垃圾代码生成工具.')
|
||||
parser.add_argument('--oc_folder', dest='oc_folder', type=str, required=True, help='OC代码所在目录')
|
||||
parser.add_argument('--replace', dest='replace_ios', required=False, help='直接替换oc源代码', action="store_true")
|
||||
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
def main():
|
||||
app_args = parse_args()
|
||||
global ios_src_path, backup_ios_folder, target_ios_folder
|
||||
ios_src_path = app_args.oc_folder
|
||||
if not os.path.exists(ios_src_path):
|
||||
print ("oc_folder path not exist.")
|
||||
exit(0)
|
||||
|
||||
print ("拷贝OC代码到target_ios")
|
||||
if os.path.exists(target_ios_folder):
|
||||
shutil.rmtree(target_ios_folder)
|
||||
shutil.copytree(ios_src_path, target_ios_folder)
|
||||
|
||||
print ("开始创建oc文件到trash目录")
|
||||
addOCFile(target_ios_folder)
|
||||
print ("\n开始添加oc方法")
|
||||
addOCFunctions(target_ios_folder)
|
||||
|
||||
if app_args.replace_ios:
|
||||
print ("\n用target_ios替换原目录")
|
||||
print ("\t备份OC代码到" + os.path.abspath(backup_ios_folder))
|
||||
if os.path.exists(backup_ios_folder):
|
||||
shutil.rmtree(backup_ios_folder)
|
||||
shutil.copytree(ios_src_path, backup_ios_folder)
|
||||
|
||||
print ("\t开始替换")
|
||||
trash_folder = os.path.join(ios_src_path, "trash")
|
||||
if os.path.exists(trash_folder):
|
||||
shutil.rmtree(trash_folder)
|
||||
os.mkdir(trash_folder)
|
||||
|
||||
for parent, folders, files in os.walk(target_ios_folder):
|
||||
for file in files:
|
||||
if file.endswith(".h") or file.endswith(".m") or file.endswith(".mm"):
|
||||
full_path = os.path.join(parent, file)
|
||||
target_path = full_path.replace(target_ios_folder, ios_src_path)
|
||||
shutil.copy(full_path, target_path)
|
||||
print ("替换成功\n需要在Xcode上重新添加trash文件下的oc文件")
|
||||
else:
|
||||
print ("垃圾代码生成完毕,垃圾代码目录:" + os.path.abspath(target_ios_folder))
|
||||
|
||||
print ("\nfinished")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
174
HX/autoBornCode.py
Normal file
174
HX/autoBornCode.py
Normal file
@ -0,0 +1,174 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
import os,sys
|
||||
import random
|
||||
import string
|
||||
import re
|
||||
import time
|
||||
import json
|
||||
import shutil
|
||||
import hashlib
|
||||
import time
|
||||
import argparse
|
||||
#该脚本目前只针对Assets.xcassets目录下的文件进行副本、添加;
|
||||
#即:在该脚本执行完毕之后,请将指定的--target 对应目录下的Assets.xcassets拷贝回工程项目替换原有的Assets.xcassets即可
|
||||
#该脚本会修改原来的png图片的sha值,以及随机添加一些无效的且无法预览fake图片
|
||||
script_path = os.path.split(os.path.realpath(sys.argv[0]))[0]
|
||||
|
||||
resource_path = ""
|
||||
target_path = os.path.join(script_path, "target_resource")
|
||||
|
||||
#匹配规则,路径包含path_include且不包含path_exclude的才会创建对应类型的文件 os.path.sep:代表路径分隔符,即 /
|
||||
match_rule = {
|
||||
".png": {
|
||||
# "path_include": os.path.sep + "res",
|
||||
},
|
||||
}
|
||||
#确保添加的函数不重名
|
||||
funcname_set = set()
|
||||
|
||||
#单词列表,用以随机名称
|
||||
with open(os.path.join(script_path, "./ClassName_list.json"), "r") as fileObj:
|
||||
word_name_list = json.load(fileObj)
|
||||
|
||||
#获取一个随机名称
|
||||
def getOneName():
|
||||
global word_name_list
|
||||
return random.choice(word_name_list)
|
||||
|
||||
|
||||
|
||||
#获取png内容
|
||||
def getPngText():
|
||||
hexbyte = "0000000049454e44ae426082"
|
||||
text = str(random.randint(1, 100)) * random.randint(1024, 10240)
|
||||
text = text + bytes.fromhex(hexbyte).hex()
|
||||
text = text.encode('utf-8')
|
||||
return text
|
||||
|
||||
#添加单个文件
|
||||
def addSingleFile(file_path):
|
||||
global target_path
|
||||
print ("add file " + file_path.replace(target_path, ""))
|
||||
_, file_type = os.path.splitext(file_path)
|
||||
if file_type == ".png":
|
||||
# print("发现png文件,准备在文件末尾追加hex文件操作...")
|
||||
with open(file_path, "wb") as fileObj:
|
||||
fileObj.write(getPngText())
|
||||
fileObj.close()
|
||||
|
||||
def addFileTo(parent_folder, level, min_file_num=0):
|
||||
global match_rule, target_path
|
||||
create_folder_list = []
|
||||
for parent, folders, files in os.walk(parent_folder):
|
||||
target_file_type = ""
|
||||
relative_path = parent.replace(target_path, "")
|
||||
print("relative_path:"+relative_path)
|
||||
for file_type, match_config in match_rule.items():
|
||||
# print("file_type:" + file_type)
|
||||
print("match_config:" + str(match_config))
|
||||
|
||||
if "path_exclude" in match_config and relative_path.find(match_config["path_exclude"]) != -1:
|
||||
continue
|
||||
if "path_include" not in match_config or relative_path.find(match_config["path_include"]) != -1:
|
||||
target_file_type = file_type
|
||||
# print("target_file_type:"+target_file_type)
|
||||
break
|
||||
if not target_file_type:
|
||||
print("不在执行后续的addSingleFile步骤")
|
||||
continue
|
||||
|
||||
# Create file count 创建 指定的最小文件数量 + 文件列表长度一半 到 文件列表长度 之间 的数量
|
||||
new_file_num = random.randint(len(files) // 2, len(files)) + min_file_num
|
||||
for i in range(new_file_num):
|
||||
#根据随机的文件名 + 文件后缀类型 拼接为要创建的文件路径
|
||||
file_path = os.path.join(parent, getOneName() + target_file_type)
|
||||
addSingleFile(file_path)
|
||||
print("已经执行addSingleFile步骤...")
|
||||
# Prevent creating too many levels 如果该目录下已经被自动创建目录,则不再继续自动创建
|
||||
if level > 2:
|
||||
continue
|
||||
|
||||
# Create folder count
|
||||
new_fold_num = random.randint(len(folders) // 2, len(folders))
|
||||
for i in range(new_fold_num):
|
||||
target_folder = os.path.join(parent, getOneName())
|
||||
# Defer folder creation to avoid interrupting os.walk
|
||||
create_folder_list.append(target_folder)
|
||||
|
||||
for folder_path in create_folder_list:
|
||||
try:
|
||||
print("create folder", folder_path.replace(target_path, ""))
|
||||
os.makedirs(folder_path, exist_ok=True) # Handle existing folders
|
||||
addFileTo(folder_path, level + 1, random.randint(2, 5))
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
#----------------------------------------ended add file----------------------
|
||||
def changeSingleFileMD5(file_path):
|
||||
pre_hash_valaue = calculate_sha256_hash(file_path)
|
||||
# print("pre_hash_value:\n" + pre_hash_valaue)
|
||||
_, file_type = os.path.splitext(file_path)
|
||||
with open(file_path, "ab") as fileObj:
|
||||
if file_type == ".png":
|
||||
text = "".join(random.sample(string.ascii_letters, 11))
|
||||
elif file_type == ".jpg":
|
||||
text = "".join(random.sample(string.ascii_letters, 20))
|
||||
else:
|
||||
text = " "*random.randint(1, 100)
|
||||
fileObj.write(text.encode('utf-8'))
|
||||
fileObj.close()
|
||||
after_hash_valaue = calculate_sha256_hash(file_path)
|
||||
# print("after_hash_valaue:\n" + after_hash_valaue)
|
||||
|
||||
#改变文件md5
|
||||
def changeFolderMD5(target_path):
|
||||
# type_filter = set([".png", ".jpg", ".json", ".plist", ".fnt"])
|
||||
#暂时不处理json、pilist文件
|
||||
type_filter = set([".png", ".jpg"])
|
||||
for parent, folders, files in os.walk(target_path):
|
||||
for file in files:
|
||||
full_path = os.path.join(parent, file)
|
||||
_, file_type = os.path.splitext(full_path)
|
||||
if file_type in type_filter:
|
||||
changeSingleFileMD5(full_path)
|
||||
|
||||
#返回文件的hash值
|
||||
def calculate_sha256_hash(file_path):
|
||||
with open(file_path, 'rb') as f:
|
||||
data = f.read()
|
||||
hasher = hashlib.sha256()
|
||||
hasher.update(data)
|
||||
return hasher.hexdigest()
|
||||
#----------------------------------------------------main------------------------------------------------
|
||||
|
||||
def parse_args():
|
||||
global res_path
|
||||
parser = argparse.ArgumentParser(description='资源变异工具')
|
||||
parser.add_argument('--res', dest='res_dir', type=str, required=True, help='资源目录')
|
||||
parser.add_argument('--target', dest='target_dir', type=str, required=False, default=target_path, help='资源导出目录')
|
||||
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
def main():
|
||||
global resource_path, target_path
|
||||
app_args = parse_args()
|
||||
resource_path = app_args.res_dir
|
||||
target_path = app_args.target_dir
|
||||
|
||||
if not os.path.exists(resource_path):
|
||||
print ("res path not exists: " + resource_path)
|
||||
exit(0)
|
||||
if target_path != resource_path:
|
||||
if os.path.exists(target_path):
|
||||
shutil.rmtree(target_path)
|
||||
shutil.copytree(resource_path, target_path)
|
||||
#执行png文件的添加、目录的创建
|
||||
addFileTo(target_path, 0)
|
||||
|
||||
print ("\n\nstart modify file md5")
|
||||
changeFolderMD5(target_path)
|
||||
print ("finish!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
301
HX/confuseAndBuild.sh
Normal file
301
HX/confuseAndBuild.sh
Normal file
@ -0,0 +1,301 @@
|
||||
#!/bin/bash
|
||||
|
||||
# confuseAndBuild.sh
|
||||
# ConfuseSwift
|
||||
#
|
||||
|
||||
# ⚠️声明
|
||||
# 1. 请将该脚本放在Xcode的Project工程的根目录。
|
||||
# 2. 当前版本未配置完整Xcode环境变量,仅支持混淆功能,不支持framework编译,若需编译请用Xcode运行该脚本。
|
||||
|
||||
# ⚠️教程
|
||||
# https://www.jianshu.com/p/be751f780d94
|
||||
# 直接在终端cd到confuseAndBuild.sh上一层目录,然后运行./confuseAndBuild.sh -c 即可
|
||||
|
||||
|
||||
if [ -z "$PROJECT_NAME" ]; then
|
||||
CONFUSE_DIR="."
|
||||
else
|
||||
CONFUSE_DIR="${SRCROOT}/${PROJECT_NAME}"
|
||||
fi
|
||||
|
||||
# ⚠️自己配置自己的前缀
|
||||
CONFUSE_PREFIX="hunxiao_"
|
||||
|
||||
BACKUP_FILE=".backup.log"
|
||||
SYMBOL_FILE=".symbol.log"
|
||||
CONFUSE_FILE=".confuse.log"
|
||||
CONFUSE_FLAG=".confuseFlag"
|
||||
|
||||
SOURCE_ARRAY=( "*.swift"
|
||||
"*.m"
|
||||
"*.h"
|
||||
"*.c"
|
||||
"*.cpp")
|
||||
BACKUP_EXTENSION=".bak"
|
||||
|
||||
|
||||
# 格式:echo -e "\033[背景色;前景色m 打印的字符串 \033[0m"
|
||||
# 颜色:重置=0,黑色=30,红色=31,绿色=32,黄色=33,蓝色=34,洋红=35,青色=36,白色=37。
|
||||
# 示例:echo -e “\033[30m 我是黑色字 \033[0m”
|
||||
# 参考:https://www.cnblogs.com/xiansong1005/p/7221316.html
|
||||
# https://www.cnblogs.com/lr-ting/archive/2013/02/28/2936792.html
|
||||
info() {
|
||||
local green="\033[1;32m"
|
||||
local normal="\033[0m"
|
||||
echo -e "[${green}info${normal}] $1"
|
||||
}
|
||||
|
||||
error() {
|
||||
local red="\033[1;31m"
|
||||
local normal="\033[0m"
|
||||
echo -e "[${red}error${normal}] $1"
|
||||
}
|
||||
|
||||
# 生成随机字符串 16字
|
||||
randomString() {
|
||||
random_string=$(openssl rand -base64 64 | tr -cd 'a-zA-Z' | head -c 8)
|
||||
prefixed_string="water_$random_string"
|
||||
echo "$prefixed_string"
|
||||
}
|
||||
|
||||
# 获取符号的随机字符串 $1是符号名
|
||||
randomStringWithSymbol() {
|
||||
grep -w $1 $SYMBOL_FILE -h | cut -d \ -f 2
|
||||
}
|
||||
|
||||
removeIfExist() {
|
||||
if [ -f $1 ]; then
|
||||
rm $1
|
||||
fi
|
||||
}
|
||||
|
||||
# 备份文件 $1:file full path
|
||||
backupFile() {
|
||||
file=$1
|
||||
# 在原文件名前加个.(点符合)用作备份名
|
||||
fileName=${file##*/}
|
||||
backupPath=${file/$fileName/.$fileName$BACKUP_EXTENSION}
|
||||
echo "backup $file to $backupPath"
|
||||
|
||||
if [ ! -f $backupPath ]; then
|
||||
cp $file $backupPath
|
||||
echo $backupPath >>$BACKUP_FILE
|
||||
fi
|
||||
}
|
||||
|
||||
# 方案1. 精确备份:用关键字遍历会修改到的source文件,再将其备份 -- 消耗性能
|
||||
# 方案2. 整体备份:备份所有source文件 -- 消耗存储空间
|
||||
# 根据需要,为简单起见,这里选用方案2
|
||||
backupAllSource() {
|
||||
info "backup all swift files"
|
||||
NAMES="-name \"${SOURCE_ARRAY[0]}\""
|
||||
i=1
|
||||
while [ $i -lt ${#SOURCE_ARRAY[@]} ]; do
|
||||
NAMES+=" -or -name \"${SOURCE_ARRAY[$i]}\""
|
||||
let i++
|
||||
done
|
||||
# echo $NAMES
|
||||
|
||||
removeIfExist $BACKUP_FILE
|
||||
touch $BACKUP_FILE
|
||||
|
||||
eval "find $CONFUSE_DIR $NAMES" | while read file; do
|
||||
backupFile $file
|
||||
done
|
||||
}
|
||||
|
||||
# 混淆工作, ⚠️该函数不会自动备份,要备份请调用safeConfuse函数
|
||||
confuseOnly() {
|
||||
info "confuse start..."
|
||||
|
||||
# 获取要混淆的函数名和变量名
|
||||
INCLUDES="--include=\"${SOURCE_ARRAY[0]}\""
|
||||
i=1
|
||||
while [ $i -lt ${#SOURCE_ARRAY[@]} ]; do
|
||||
INCLUDES+=" --include=\"${SOURCE_ARRAY[$i]}\""
|
||||
let i++
|
||||
done
|
||||
eval "grep $CONFUSE_PREFIX -r $CONFUSE_DIR $INCLUDES -n" >$CONFUSE_FILE
|
||||
|
||||
# cat $CONFUSE_FILE
|
||||
# 绑定随机字符串
|
||||
removeIfExist $SYMBOL_FILE
|
||||
touch $SYMBOL_FILE
|
||||
|
||||
cat $CONFUSE_FILE | egrep -w $CONFUSE_PREFIX"[0-9a-zA-Z_]*" -o | sort | uniq | while read line; do
|
||||
echo $line" `randomString`" >>$SYMBOL_FILE
|
||||
done
|
||||
|
||||
# cat $SYMBOL_FILE
|
||||
|
||||
# 读取备份文件记录
|
||||
# 在这里没使用遍历批量替换,怕文件太多的时候影响性能
|
||||
cat $CONFUSE_FILE | while read line; do
|
||||
# echo "> $line"
|
||||
# 截取行号
|
||||
lineNum=`echo $line | sed 's/.*:\([0-9]*\):.*/\1/g'`
|
||||
# 截取文件路径
|
||||
path=${line%%:*}
|
||||
|
||||
# 一行可能有多个要替换的子串,要循环遍历完
|
||||
# 这里之所以要用`sort -r`倒序是因为有个bug:如有字符串"jjyy abc hello abcde", 现在要替换"abc"为"123"(abcde保持不变),也就是传说中的‘全匹配替换’,
|
||||
# 但不知为何在macOS下单词边界表达式不起作用:\<abc\> 或者 \babc\b都不起作用,Linux下这个正则表达式是没问题的。
|
||||
# 倒序之后有长串优先替换长串,防止短串把长串部分替换掉。但依然存在bug:若是长串不需要替换,则短串替换是依然会将长串部分替换😂
|
||||
# 因此依然还需要寻找macOS下单词边界/全匹配 的正则表达式
|
||||
echo $line | egrep -w $CONFUSE_PREFIX"[0-9a-zA-Z_]*" -o | sort -r | while read -ra symbol; do
|
||||
# 根据名称获取绑定的随机字符串
|
||||
random=`randomStringWithSymbol $symbol`
|
||||
# echo "$path $lineNum $symbol $random"
|
||||
# 随机字符串替换
|
||||
# -i:表示直接在原文件替换,"":表示不要备份
|
||||
sed -i "" "${lineNum}s/$symbol/$random/g" $path
|
||||
|
||||
echo " $symbol => $random"
|
||||
done
|
||||
done
|
||||
|
||||
info "confuse done"
|
||||
}
|
||||
|
||||
# 编译工作,生成通用framework
|
||||
buildAll() {
|
||||
info "build start..."
|
||||
|
||||
if [ -z "$PROJECT_NAME" ]; then
|
||||
echo -e "\033[1;31mERROR:当前版本未配置完整Xcode环境变量,仅支持混淆功能,不支持framework编译,若需编译请用Xcode运行该脚本\033[0m"
|
||||
return
|
||||
fi
|
||||
|
||||
# 要build的target名
|
||||
TARGET_NAME=${PROJECT_NAME}
|
||||
UNIVERSAL_OUTPUT_DIR="${SRCROOT}/Framework/"
|
||||
|
||||
# 创建输出目录,并删除之前的framework文件
|
||||
mkdir -p "${UNIVERSAL_OUTPUT_DIR}"
|
||||
rm -rf "${UNIVERSAL_OUTPUT_DIR}/${TARGET_NAME}.framework"
|
||||
|
||||
#分别编译模拟器和真机的Framework
|
||||
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} ARCHS="armv7 armv7s arm64" -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
|
||||
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} ARCHS="i386 x86_64" -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
|
||||
|
||||
#拷贝framework到univer目录
|
||||
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${TARGET_NAME}.framework" "${UNIVERSAL_OUTPUT_DIR}"
|
||||
|
||||
# 合并swiftmodule到univer目录
|
||||
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule/" "${UNIVERSAL_OUTPUT_DIR}/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule"
|
||||
|
||||
#合并framework,输出最终的framework到build目录
|
||||
lipo -create -output "${UNIVERSAL_OUTPUT_DIR}/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${TARGET_NAME}.framework/${TARGET_NAME}"
|
||||
|
||||
#删除编译之后生成的无关的配置文件
|
||||
dir_path="${UNIVERSAL_OUTPUT_DIR}/${TARGET_NAME}.framework/"
|
||||
for file in ls $dir_path; do
|
||||
if [[ ${file} =~ ".xcconfig" ]]; then
|
||||
rm -f "${dir_path}/${file}"
|
||||
fi
|
||||
done
|
||||
|
||||
#判断build文件夹是否存在,存在则删除
|
||||
if [ -d "${SRCROOT}/build" ]; then
|
||||
rm -rf "${SRCROOT}/build"
|
||||
fi
|
||||
|
||||
#rm -rf "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator" "${BUILD_DIR}/${CONFIGURATION}-iphoneos"
|
||||
|
||||
#打开合并后的文件夹
|
||||
open "${UNIVERSAL_OUTPUT_DIR}"
|
||||
|
||||
info "build done"
|
||||
}
|
||||
|
||||
# 清理工作,去混淆
|
||||
unconfuse() {
|
||||
info "clean start..."
|
||||
if [ -f $CONFUSE_FLAG ]; then
|
||||
# 恢复混淆的函数名所在source文件的bak内容
|
||||
cat $BACKUP_FILE | while read backup; do
|
||||
backupName=${backup##*/}
|
||||
fileName=`echo $backupName | cut -d "." -f2,3`
|
||||
filePath=${backup/$backupName/$fileName}
|
||||
|
||||
echo "recover $backup to $filePath"
|
||||
|
||||
cp $backup $filePath
|
||||
rm $backup
|
||||
done
|
||||
# 删除修改记录
|
||||
removeIfExist $SYMBOL_FILE
|
||||
removeIfExist $CONFUSE_FILE
|
||||
removeIfExist $BACKUP_FILE
|
||||
removeIfExist $CONFUSE_FLAG
|
||||
else
|
||||
echo "Not confuse yet!"
|
||||
fi
|
||||
info "clean done"
|
||||
}
|
||||
|
||||
# 检查是否上次未完成
|
||||
precheck() {
|
||||
# 创建一个隐藏文件,仅标记混淆编译的状态
|
||||
# 由于编译过程有可能被中断,因此混淆后的代码可能未恢复,在开始备份前先做判断
|
||||
unconfuse
|
||||
touch $CONFUSE_FLAG
|
||||
}
|
||||
|
||||
# 去混淆->备份->混淆
|
||||
safeConfuse() {
|
||||
precheck
|
||||
backupAllSource
|
||||
confuseOnly
|
||||
}
|
||||
|
||||
# 去混淆->备份->混淆
|
||||
# 编译
|
||||
# 去混淆
|
||||
safeConfuseAndBuild() {
|
||||
info "preparing confuse and build..."
|
||||
|
||||
safeConfuse
|
||||
buildAll
|
||||
unconfuse
|
||||
|
||||
info "all done"
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo -e "\033[1;31musage: ./confuseAndBuild.sh [-u|c|b|a]"
|
||||
echo -e " -u"
|
||||
echo -e " unconfuse: 清理工作,去混淆"
|
||||
echo -e " -c"
|
||||
echo -e " safeConfuse: 去混淆->备份->混淆"
|
||||
echo -e " -b"
|
||||
echo -e " buildAll: 编译生成通用framework"
|
||||
echo -e " -a"
|
||||
echo -e " safeConfuseAndBuild: 去混淆->备份->混淆->编译->去混淆"
|
||||
echo -e "EXAMPLE:"
|
||||
echo -e " ./confuseAndBuild.sh -u\033[0m"
|
||||
}
|
||||
|
||||
main() {
|
||||
echo "参数个数:$# 参数值:$1"
|
||||
case $1 in
|
||||
"-u" )
|
||||
unconfuse
|
||||
;;
|
||||
"-c" )
|
||||
safeConfuse
|
||||
;;
|
||||
"-b" )
|
||||
buildAll
|
||||
;;
|
||||
"-a" )
|
||||
safeConfuseAndBuild
|
||||
;;
|
||||
* )
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main $@
|
||||
301
HX/confuseAndBuild.txt
Normal file
301
HX/confuseAndBuild.txt
Normal file
@ -0,0 +1,301 @@
|
||||
#!/bin/bash
|
||||
|
||||
# confuseAndBuild.sh
|
||||
# ConfuseSwift
|
||||
#
|
||||
|
||||
# ⚠️声明
|
||||
# 1. 请将该脚本放在Xcode的Project工程的根目录。
|
||||
# 2. 当前版本未配置完整Xcode环境变量,仅支持混淆功能,不支持framework编译,若需编译请用Xcode运行该脚本。
|
||||
|
||||
# ⚠️教程
|
||||
# https://www.jianshu.com/p/be751f780d94
|
||||
# 直接在终端cd到confuseAndBuild.sh上一层目录,然后运行./confuseAndBuild.sh -c 即可
|
||||
|
||||
|
||||
if [ -z "$PROJECT_NAME" ]; then
|
||||
CONFUSE_DIR="."
|
||||
else
|
||||
CONFUSE_DIR="${SRCROOT}/${PROJECT_NAME}"
|
||||
fi
|
||||
|
||||
# ⚠️自己配置自己的前缀
|
||||
CONFUSE_PREFIX="hunxiao_"
|
||||
|
||||
BACKUP_FILE=".backup.log"
|
||||
SYMBOL_FILE=".symbol.log"
|
||||
CONFUSE_FILE=".confuse.log"
|
||||
CONFUSE_FLAG=".confuseFlag"
|
||||
|
||||
SOURCE_ARRAY=( "*.swift"
|
||||
"*.m"
|
||||
"*.h"
|
||||
"*.c"
|
||||
"*.cpp")
|
||||
BACKUP_EXTENSION=".bak"
|
||||
|
||||
|
||||
# 格式:echo -e "\033[背景色;前景色m 打印的字符串 \033[0m"
|
||||
# 颜色:重置=0,黑色=30,红色=31,绿色=32,黄色=33,蓝色=34,洋红=35,青色=36,白色=37。
|
||||
# 示例:echo -e “\033[30m 我是黑色字 \033[0m”
|
||||
# 参考:https://www.cnblogs.com/xiansong1005/p/7221316.html
|
||||
# https://www.cnblogs.com/lr-ting/archive/2013/02/28/2936792.html
|
||||
info() {
|
||||
local green="\033[1;32m"
|
||||
local normal="\033[0m"
|
||||
echo -e "[${green}info${normal}] $1"
|
||||
}
|
||||
|
||||
error() {
|
||||
local red="\033[1;31m"
|
||||
local normal="\033[0m"
|
||||
echo -e "[${red}error${normal}] $1"
|
||||
}
|
||||
|
||||
# 生成随机字符串 16字
|
||||
randomString() {
|
||||
random_string=$(openssl rand -base64 64 | tr -cd 'a-zA-Z' | head -c 8)
|
||||
prefixed_string="water_$random_string"
|
||||
echo "$prefixed_string"
|
||||
}
|
||||
|
||||
# 获取符号的随机字符串 $1是符号名
|
||||
randomStringWithSymbol() {
|
||||
grep -w $1 $SYMBOL_FILE -h | cut -d \ -f 2
|
||||
}
|
||||
|
||||
removeIfExist() {
|
||||
if [ -f $1 ]; then
|
||||
rm $1
|
||||
fi
|
||||
}
|
||||
|
||||
# 备份文件 $1:file full path
|
||||
backupFile() {
|
||||
file=$1
|
||||
# 在原文件名前加个.(点符合)用作备份名
|
||||
fileName=${file##*/}
|
||||
backupPath=${file/$fileName/.$fileName$BACKUP_EXTENSION}
|
||||
echo "backup $file to $backupPath"
|
||||
|
||||
if [ ! -f $backupPath ]; then
|
||||
cp $file $backupPath
|
||||
echo $backupPath >>$BACKUP_FILE
|
||||
fi
|
||||
}
|
||||
|
||||
# 方案1. 精确备份:用关键字遍历会修改到的source文件,再将其备份 -- 消耗性能
|
||||
# 方案2. 整体备份:备份所有source文件 -- 消耗存储空间
|
||||
# 根据需要,为简单起见,这里选用方案2
|
||||
backupAllSource() {
|
||||
info "backup all swift files"
|
||||
NAMES="-name \"${SOURCE_ARRAY[0]}\""
|
||||
i=1
|
||||
while [ $i -lt ${#SOURCE_ARRAY[@]} ]; do
|
||||
NAMES+=" -or -name \"${SOURCE_ARRAY[$i]}\""
|
||||
let i++
|
||||
done
|
||||
# echo $NAMES
|
||||
|
||||
removeIfExist $BACKUP_FILE
|
||||
touch $BACKUP_FILE
|
||||
|
||||
eval "find $CONFUSE_DIR $NAMES" | while read file; do
|
||||
backupFile $file
|
||||
done
|
||||
}
|
||||
|
||||
# 混淆工作, ⚠️该函数不会自动备份,要备份请调用safeConfuse函数
|
||||
confuseOnly() {
|
||||
info "confuse start..."
|
||||
|
||||
# 获取要混淆的函数名和变量名
|
||||
INCLUDES="--include=\"${SOURCE_ARRAY[0]}\""
|
||||
i=1
|
||||
while [ $i -lt ${#SOURCE_ARRAY[@]} ]; do
|
||||
INCLUDES+=" --include=\"${SOURCE_ARRAY[$i]}\""
|
||||
let i++
|
||||
done
|
||||
eval "grep $CONFUSE_PREFIX -r $CONFUSE_DIR $INCLUDES -n" >$CONFUSE_FILE
|
||||
|
||||
# cat $CONFUSE_FILE
|
||||
# 绑定随机字符串
|
||||
removeIfExist $SYMBOL_FILE
|
||||
touch $SYMBOL_FILE
|
||||
|
||||
cat $CONFUSE_FILE | egrep -w $CONFUSE_PREFIX"[0-9a-zA-Z_]*" -o | sort | uniq | while read line; do
|
||||
echo $line" `randomString`" >>$SYMBOL_FILE
|
||||
done
|
||||
|
||||
# cat $SYMBOL_FILE
|
||||
|
||||
# 读取备份文件记录
|
||||
# 在这里没使用遍历批量替换,怕文件太多的时候影响性能
|
||||
cat $CONFUSE_FILE | while read line; do
|
||||
# echo "> $line"
|
||||
# 截取行号
|
||||
lineNum=`echo $line | sed 's/.*:\([0-9]*\):.*/\1/g'`
|
||||
# 截取文件路径
|
||||
path=${line%%:*}
|
||||
|
||||
# 一行可能有多个要替换的子串,要循环遍历完
|
||||
# 这里之所以要用`sort -r`倒序是因为有个bug:如有字符串"jjyy abc hello abcde", 现在要替换"abc"为"123"(abcde保持不变),也就是传说中的‘全匹配替换’,
|
||||
# 但不知为何在macOS下单词边界表达式不起作用:\<abc\> 或者 \babc\b都不起作用,Linux下这个正则表达式是没问题的。
|
||||
# 倒序之后有长串优先替换长串,防止短串把长串部分替换掉。但依然存在bug:若是长串不需要替换,则短串替换是依然会将长串部分替换😂
|
||||
# 因此依然还需要寻找macOS下单词边界/全匹配 的正则表达式
|
||||
echo $line | egrep -w $CONFUSE_PREFIX"[0-9a-zA-Z_]*" -o | sort -r | while read -ra symbol; do
|
||||
# 根据名称获取绑定的随机字符串
|
||||
random=`randomStringWithSymbol $symbol`
|
||||
# echo "$path $lineNum $symbol $random"
|
||||
# 随机字符串替换
|
||||
# -i:表示直接在原文件替换,"":表示不要备份
|
||||
sed -i "" "${lineNum}s/$symbol/$random/g" $path
|
||||
|
||||
echo " $symbol => $random"
|
||||
done
|
||||
done
|
||||
|
||||
info "confuse done"
|
||||
}
|
||||
|
||||
# 编译工作,生成通用framework
|
||||
buildAll() {
|
||||
info "build start..."
|
||||
|
||||
if [ -z "$PROJECT_NAME" ]; then
|
||||
echo -e "\033[1;31mERROR:当前版本未配置完整Xcode环境变量,仅支持混淆功能,不支持framework编译,若需编译请用Xcode运行该脚本\033[0m"
|
||||
return
|
||||
fi
|
||||
|
||||
# 要build的target名
|
||||
TARGET_NAME=${PROJECT_NAME}
|
||||
UNIVERSAL_OUTPUT_DIR="${SRCROOT}/Framework/"
|
||||
|
||||
# 创建输出目录,并删除之前的framework文件
|
||||
mkdir -p "${UNIVERSAL_OUTPUT_DIR}"
|
||||
rm -rf "${UNIVERSAL_OUTPUT_DIR}/${TARGET_NAME}.framework"
|
||||
|
||||
#分别编译模拟器和真机的Framework
|
||||
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} ARCHS="armv7 armv7s arm64" -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
|
||||
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} ARCHS="i386 x86_64" -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
|
||||
|
||||
#拷贝framework到univer目录
|
||||
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${TARGET_NAME}.framework" "${UNIVERSAL_OUTPUT_DIR}"
|
||||
|
||||
# 合并swiftmodule到univer目录
|
||||
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule/" "${UNIVERSAL_OUTPUT_DIR}/${TARGET_NAME}.framework/Modules/${TARGET_NAME}.swiftmodule"
|
||||
|
||||
#合并framework,输出最终的framework到build目录
|
||||
lipo -create -output "${UNIVERSAL_OUTPUT_DIR}/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${TARGET_NAME}.framework/${TARGET_NAME}"
|
||||
|
||||
#删除编译之后生成的无关的配置文件
|
||||
dir_path="${UNIVERSAL_OUTPUT_DIR}/${TARGET_NAME}.framework/"
|
||||
for file in ls $dir_path; do
|
||||
if [[ ${file} =~ ".xcconfig" ]]; then
|
||||
rm -f "${dir_path}/${file}"
|
||||
fi
|
||||
done
|
||||
|
||||
#判断build文件夹是否存在,存在则删除
|
||||
if [ -d "${SRCROOT}/build" ]; then
|
||||
rm -rf "${SRCROOT}/build"
|
||||
fi
|
||||
|
||||
#rm -rf "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator" "${BUILD_DIR}/${CONFIGURATION}-iphoneos"
|
||||
|
||||
#打开合并后的文件夹
|
||||
open "${UNIVERSAL_OUTPUT_DIR}"
|
||||
|
||||
info "build done"
|
||||
}
|
||||
|
||||
# 清理工作,去混淆
|
||||
unconfuse() {
|
||||
info "clean start..."
|
||||
if [ -f $CONFUSE_FLAG ]; then
|
||||
# 恢复混淆的函数名所在source文件的bak内容
|
||||
cat $BACKUP_FILE | while read backup; do
|
||||
backupName=${backup##*/}
|
||||
fileName=`echo $backupName | cut -d "." -f2,3`
|
||||
filePath=${backup/$backupName/$fileName}
|
||||
|
||||
echo "recover $backup to $filePath"
|
||||
|
||||
cp $backup $filePath
|
||||
rm $backup
|
||||
done
|
||||
# 删除修改记录
|
||||
removeIfExist $SYMBOL_FILE
|
||||
removeIfExist $CONFUSE_FILE
|
||||
removeIfExist $BACKUP_FILE
|
||||
removeIfExist $CONFUSE_FLAG
|
||||
else
|
||||
echo "Not confuse yet!"
|
||||
fi
|
||||
info "clean done"
|
||||
}
|
||||
|
||||
# 检查是否上次未完成
|
||||
precheck() {
|
||||
# 创建一个隐藏文件,仅标记混淆编译的状态
|
||||
# 由于编译过程有可能被中断,因此混淆后的代码可能未恢复,在开始备份前先做判断
|
||||
unconfuse
|
||||
touch $CONFUSE_FLAG
|
||||
}
|
||||
|
||||
# 去混淆->备份->混淆
|
||||
safeConfuse() {
|
||||
precheck
|
||||
backupAllSource
|
||||
confuseOnly
|
||||
}
|
||||
|
||||
# 去混淆->备份->混淆
|
||||
# 编译
|
||||
# 去混淆
|
||||
safeConfuseAndBuild() {
|
||||
info "preparing confuse and build..."
|
||||
|
||||
safeConfuse
|
||||
buildAll
|
||||
unconfuse
|
||||
|
||||
info "all done"
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo -e "\033[1;31musage: ./confuseAndBuild.sh [-u|c|b|a]"
|
||||
echo -e " -u"
|
||||
echo -e " unconfuse: 清理工作,去混淆"
|
||||
echo -e " -c"
|
||||
echo -e " safeConfuse: 去混淆->备份->混淆"
|
||||
echo -e " -b"
|
||||
echo -e " buildAll: 编译生成通用framework"
|
||||
echo -e " -a"
|
||||
echo -e " safeConfuseAndBuild: 去混淆->备份->混淆->编译->去混淆"
|
||||
echo -e "EXAMPLE:"
|
||||
echo -e " ./confuseAndBuild.sh -u\033[0m"
|
||||
}
|
||||
|
||||
main() {
|
||||
echo "参数个数:$# 参数值:$1"
|
||||
case $1 in
|
||||
"-u" )
|
||||
unconfuse
|
||||
;;
|
||||
"-c" )
|
||||
safeConfuse
|
||||
;;
|
||||
"-b" )
|
||||
buildAll
|
||||
;;
|
||||
"-a" )
|
||||
safeConfuseAndBuild
|
||||
;;
|
||||
* )
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main $@
|
||||
183
HX/renameNative.py
Normal file
183
HX/renameNative.py
Normal file
@ -0,0 +1,183 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
import os,sys
|
||||
import random
|
||||
import string
|
||||
import re
|
||||
#import md5
|
||||
import time
|
||||
import json
|
||||
import shutil
|
||||
import hashlib
|
||||
import time
|
||||
import argparse
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
script_path = os.path.split(os.path.realpath(sys.argv[0]))[0]
|
||||
add_prefix = ""
|
||||
old_prefix = "ZZH_"
|
||||
new_prefix = "BSHighCode"
|
||||
ios_src_path = ""
|
||||
project_file_path = ""
|
||||
|
||||
ignore_path_text = [".a", ".png", ".plist", ".storyboard", ".pch"]
|
||||
|
||||
#首字母大写
|
||||
def isNeedIgnore(file_path):
|
||||
global ignore_path_text
|
||||
for ignore_text in ignore_path_text:
|
||||
if file_path.find(ignore_text) != -1:
|
||||
return True
|
||||
return False
|
||||
|
||||
def replaceStringInFile(full_path, old_text, new_text):
|
||||
with open(full_path, "r",errors="ignore") as fileObj:
|
||||
all_text = fileObj.read()
|
||||
fileObj.close()
|
||||
|
||||
all_text = all_text.replace(old_text, new_text)
|
||||
with open(full_path, "w",errors="ignore") as fileObj:
|
||||
fileObj.write(all_text)
|
||||
fileObj.close()
|
||||
|
||||
def renameFileInXcodeProj(old_file_name, new_file_name):
|
||||
global project_file_path
|
||||
if os.path.exists(project_file_path):
|
||||
replaceStringInFile(project_file_path, old_file_name, new_file_name)
|
||||
|
||||
#替换文件中的文本内容:匹配到的文本被替换为指定的new_text
|
||||
def renameInAllFile(old_text, new_text):
|
||||
global ios_src_path
|
||||
for parent, folders, files in os.walk(ios_src_path):
|
||||
for file in files:
|
||||
full_path = os.path.join(parent, file)
|
||||
replaceStringInFile(full_path, old_text, new_text)
|
||||
|
||||
#开始重命名类名
|
||||
def dealWithIos(folder_path):
|
||||
print ("开始重命名类名")
|
||||
global old_prefix, new_prefix
|
||||
for parent, folders, files in os.walk(folder_path):
|
||||
#先处理每个文件的名字
|
||||
for file in files:
|
||||
print("\n the file:" + file + "\n")
|
||||
#得到该文件的路径
|
||||
old_full_path = os.path.join(parent, file)
|
||||
#如果该文件名称匹配为需要重命名的类名 名称,并且该文本不属于被忽略的文件,则需要执行重命名操作
|
||||
if file.startswith(old_prefix) and not isNeedIgnore(old_full_path):
|
||||
#将该文件名称中匹配上的文本部分替换为new_prefix,并得到新文件名 名称
|
||||
new_file_name = file.replace(old_prefix, new_prefix)
|
||||
print ("\t重命名文件: %s -> %s" %(file, new_file_name))
|
||||
#合成新文件名对应的文件路径
|
||||
new_full_path = os.path.join(parent, new_file_name)
|
||||
#将原来的文件改命为新的文件名称
|
||||
os.rename(old_full_path, new_full_path)
|
||||
#在项目工程中改名
|
||||
renameFileInXcodeProj(file, new_file_name)
|
||||
|
||||
#在可能引用的地方替换,获取不带文件名后缀的部分
|
||||
old_file_base_name = os.path.splitext(file)[0]
|
||||
print("\n the old_file_base_name:" + old_file_base_name + "\n")
|
||||
new_file_base_name = old_file_base_name.replace(old_prefix, new_prefix)
|
||||
#将ios_src_path 所指定的目录下的所有old_file_base_name文本(主要是指的类名) 替换为新的new_file_base_name文本 (类名)
|
||||
renameInAllFile(old_file_base_name, new_file_base_name)
|
||||
|
||||
for parent, folders, files in os.walk(folder_path):
|
||||
for folder in folders:
|
||||
old_full_path = os.path.join(parent, folder)
|
||||
#递归处理该目录下的内容
|
||||
# dealWithIos(old_full_path)
|
||||
if folder.startswith(old_prefix) and not isNeedIgnore(old_full_path):
|
||||
new_folder_name = folder.replace(old_prefix, new_prefix)
|
||||
print ("\t重命名文件夹: %s -> %s" %(folder, new_folder_name))
|
||||
new_full_path = os.path.join(parent, new_folder_name)
|
||||
os.rename(old_full_path, new_full_path)
|
||||
#在项目工程中改名
|
||||
renameFileInXcodeProj(folder, new_folder_name)
|
||||
print ("finish\n")
|
||||
|
||||
#开始添加前缀
|
||||
def addPreFix():
|
||||
print ("开始添加前缀")
|
||||
global add_prefix, ios_src_path
|
||||
for parent, folders, files in os.walk(ios_src_path):
|
||||
for file in files:
|
||||
old_full_path = os.path.join(parent, file)
|
||||
if not isNeedIgnore(old_full_path):
|
||||
new_file_name = add_prefix + file
|
||||
print ("\t重命名文件: %s -> %s" %(file, new_file_name))
|
||||
|
||||
new_full_path = os.path.join(parent, new_file_name)
|
||||
os.rename(old_full_path, new_full_path)
|
||||
#在项目工程中改名
|
||||
renameFileInXcodeProj(file, new_file_name)
|
||||
|
||||
#在可能引用的地方替换
|
||||
old_file_base_name = os.path.splitext(file)[0]
|
||||
new_file_base_name = os.path.splitext(new_file_name)[0]
|
||||
renameInAllFile(old_file_base_name, new_file_base_name)
|
||||
renameInAllFile(add_prefix+add_prefix, add_prefix)
|
||||
|
||||
for parent, folders, files in os.walk(ios_src_path):
|
||||
for folder in folders:
|
||||
old_full_path = os.path.join(parent, folder)
|
||||
if not isNeedIgnore(old_full_path):
|
||||
new_folder_name = add_prefix + folder
|
||||
print ("\t重命名文件夹: %s -> %s" %(folder, new_folder_name))
|
||||
new_full_path = os.path.join(parent, new_folder_name)
|
||||
os.rename(old_full_path, new_full_path)
|
||||
#在项目工程中改名
|
||||
renameFileInXcodeProj(folder, new_folder_name)
|
||||
print ("finish\n")
|
||||
|
||||
#给方法添加前缀
|
||||
#.....
|
||||
|
||||
|
||||
#修改指定前缀的方法名
|
||||
#....
|
||||
|
||||
#给每个方法的起始行处 添加垃圾代码
|
||||
#......
|
||||
|
||||
#----------------------------------------------------main------------------------------------------------
|
||||
def parse_args():
|
||||
global script_path, proj_ios_path
|
||||
parser = argparse.ArgumentParser(description='修改类名前缀工具.\n')
|
||||
parser.add_argument('--add_prefix', dest='add_prefix', type=str, required=False, default="", help='添加类名前缀')
|
||||
parser.add_argument('--old_prefix', dest='old_prefix', type=str, required=False, help='原类名前缀')
|
||||
parser.add_argument('--new_prefix', dest='new_prefix', type=str, required=False, help='替换后类名前缀')
|
||||
parser.add_argument('--ios_path', dest='ios_path', type=str, required=True, help='OC文件目录')
|
||||
parser.add_argument('--proj_path', dest='proj_path', type=str, required=False, default="", help='xx.xcodeproj路径')
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
def main():
|
||||
global old_prefix, new_prefix, ios_src_path, project_file_path, add_prefix
|
||||
app_args = parse_args()
|
||||
|
||||
add_prefix = app_args.add_prefix
|
||||
old_prefix = app_args.old_prefix
|
||||
new_prefix = app_args.new_prefix
|
||||
ios_src_path = app_args.ios_path
|
||||
project_file_path = os.path.join(app_args.proj_path, "project.pbxproj")
|
||||
if not os.path.exists(ios_src_path):
|
||||
print ("ios_path not exists: " + ios_src_path)
|
||||
exit(0)
|
||||
if not os.path.exists(project_file_path):
|
||||
print ("proj_path not exists: " + project_file_path)
|
||||
|
||||
print ("请提前备份文件夹或确认在版本管理软件中")
|
||||
input("回车继续执行")
|
||||
#给类名添加前缀:实际作用是,当以前编写的项目工程中的类名(类名必需和文件名字一致,因为是通过文件名称去依次修改文件名、类名的)没有添加一致的前缀
|
||||
if add_prefix and add_prefix != "":
|
||||
addPreFix()
|
||||
#添加完毕前缀后,就退出程序
|
||||
print("\n添加完毕前缀后,就退出程序\n")
|
||||
exit(0)
|
||||
dealWithIos(ios_src_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
12604
HX/word_list.json
Normal file
12604
HX/word_list.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -330,7 +330,7 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 057AF78B2BF1E86F00078C98 /* Build configuration list for PBXProject "HD wallpaper" */;
|
||||
buildConfigurationList = 057AF78B2BF1E86F00078C98 /* Build configuration list for PBXProject "TallPaper" */;
|
||||
compatibilityVersion = "Xcode 14.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
@ -652,7 +652,7 @@
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
057AF78B2BF1E86F00078C98 /* Build configuration list for PBXProject "HD wallpaper" */ = {
|
||||
057AF78B2BF1E86F00078C98 /* Build configuration list for PBXProject "TallPaper" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
057AF7A72BF1E87100078C98 /* Debug */,
|
||||
@ -18,7 +18,7 @@
|
||||
BlueprintIdentifier = "057AF78F2BF1E86F00078C98"
|
||||
BuildableName = "TallPaper.app"
|
||||
BlueprintName = "TallPaper"
|
||||
ReferencedContainer = "container:HD wallpaper.xcodeproj">
|
||||
ReferencedContainer = "container:TallPaper.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
@ -47,7 +47,7 @@
|
||||
BlueprintIdentifier = "057AF78F2BF1E86F00078C98"
|
||||
BuildableName = "TallPaper.app"
|
||||
BlueprintName = "TallPaper"
|
||||
ReferencedContainer = "container:HD wallpaper.xcodeproj">
|
||||
ReferencedContainer = "container:TallPaper.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
@ -64,7 +64,7 @@
|
||||
BlueprintIdentifier = "057AF78F2BF1E86F00078C98"
|
||||
BuildableName = "TallPaper.app"
|
||||
BlueprintName = "TallPaper"
|
||||
ReferencedContainer = "container:HD wallpaper.xcodeproj">
|
||||
ReferencedContainer = "container:TallPaper.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
Loading…
Reference in New Issue
Block a user