Skip to content

Commit c32c124

Browse files
author
DevelopLab
committed
1. Replace locked file method
2. Add an unlocked file function
1 parent bc4142d commit c32c124

File tree

13 files changed

+201
-44
lines changed

13 files changed

+201
-44
lines changed

AdvancedHelper/AdvancedHelper

212 KB
Binary file not shown.

AdvancedHelper/Makefile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
TARGET := iphone:clang:latest:7.0
2+
3+
include $(THEOS)/makefiles/common.mk
4+
5+
TOOL_NAME = AdvancedHelper
6+
7+
AdvancedHelper_FILES = main.m
8+
AdvancedHelper_CFLAGS = -fobjc-arc
9+
AdvancedHelper_CODESIGN_FLAGS = -Sentitlements.plist
10+
AdvancedHelper_INSTALL_PATH = /usr/local/bin
11+
12+
include $(THEOS_MAKE_PATH)/tool.mk
13+
14+
after-stage::
15+
@echo "Copying file to parent directory..."
16+
cp $(THEOS_STAGING_DIR)/usr/local/bin/$(TOOL_NAME) ../$(TOOL_NAME)/
17+
@echo "Copy completed."

AdvancedHelper/entitlements.plist

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
2+
<plist version="1.0">
3+
<dict>
4+
<key>platform-application</key>
5+
<true/>
6+
<key>com.apple.private.security.container-required</key>
7+
<false/>
8+
</dict>
9+
</plist>

AdvancedHelper/main.m

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <stdio.h>
2+
#include <unistd.h>
3+
#include <sys/stat.h>
4+
#include <sys/mount.h>
5+
@import Foundation;
6+
7+
int main(int argc, char *argv[], char *envp[]) {
8+
@autoreleasepool {
9+
if (argc < 2) {
10+
NSLog(@"Usage: %s <lock|unlock>", argv[0]);
11+
return 1; // 参数不足,返回错误
12+
}
13+
14+
NSString *action = [NSString stringWithUTF8String:argv[1]];
15+
NSString *filePath = @"/var/preferences/com.apple.networkd.plist";
16+
const char *cFilePath = [filePath UTF8String];
17+
18+
// 判断是锁定还是解锁
19+
if ([action isEqualToString:@"lock"]) {
20+
if (chflags(cFilePath, UF_IMMUTABLE) != 0) {
21+
perror("Error setting immutable flag");
22+
return 2; // 锁定失败
23+
}
24+
NSLog(@"Successfully locked file: %@", filePath);
25+
} else if ([action isEqualToString:@"unlock"]) {
26+
if (chflags(cFilePath, 0) != 0) {
27+
perror("Error removing immutable flag");
28+
return 3; // 解锁失败
29+
}
30+
NSLog(@"Successfully unlocked file: %@", filePath);
31+
} else {
32+
NSLog(@"Invalid action. Use 'lock' or 'unlock'.");
33+
return 4; // 非法参数
34+
}
35+
36+
return 0; // 成功
37+
}
38+
}

EnableQUIC.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@
147147
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
148148
CLANG_ENABLE_MODULES = YES;
149149
CODE_SIGN_STYLE = Automatic;
150-
CURRENT_PROJECT_VERSION = 4;
150+
CURRENT_PROJECT_VERSION = 5;
151151
DEVELOPMENT_TEAM = X2WABLB38D;
152152
GENERATE_INFOPLIST_FILE = YES;
153153
HEADER_SEARCH_PATHS = "";
@@ -163,7 +163,7 @@
163163
"$(inherited)",
164164
"@executable_path/Frameworks",
165165
);
166-
MARKETING_VERSION = 1.2.1;
166+
MARKETING_VERSION = 1.2.2;
167167
PRODUCT_BUNDLE_IDENTIFIER = com.developlab.EnableQUIC;
168168
PRODUCT_NAME = "$(TARGET_NAME)";
169169
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@@ -185,7 +185,7 @@
185185
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
186186
CLANG_ENABLE_MODULES = YES;
187187
CODE_SIGN_STYLE = Automatic;
188-
CURRENT_PROJECT_VERSION = 4;
188+
CURRENT_PROJECT_VERSION = 5;
189189
DEVELOPMENT_TEAM = X2WABLB38D;
190190
GENERATE_INFOPLIST_FILE = YES;
191191
HEADER_SEARCH_PATHS = "";
@@ -201,7 +201,7 @@
201201
"$(inherited)",
202202
"@executable_path/Frameworks",
203203
);
204-
MARKETING_VERSION = 1.2.1;
204+
MARKETING_VERSION = 1.2.2;
205205
PRODUCT_BUNDLE_IDENTIFIER = com.developlab.EnableQUIC;
206206
PRODUCT_NAME = "$(TARGET_NAME)";
207207
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";

EnableQUIC/DeviceController.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
group:(NSString *)group;
1111

1212
- (BOOL)moveFileFromPath:(NSString *)fromPath toPath:(NSString *)toPath;
13+
- (BOOL)setFileLock:(BOOL)lock;
1314

1415
@end
1516

EnableQUIC/DeviceController.m

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,27 @@ - (BOOL)moveFileFromPath:(NSString *)fromPath toPath:(NSString *)toPath {
8181
}
8282
}
8383

84+
- (BOOL)setFileLock:(BOOL)lock {
85+
NSString *path = [[NSBundle mainBundle] pathForResource:@"AdvancedHelper" ofType:@""];
86+
if (!path) {
87+
NSLog(@"RootHelper not found");
88+
return NO;
89+
}
90+
91+
NSArray *args = lock ? @[@"lock"] : @[@"unlock"];
92+
NSString *stdOut = nil;
93+
NSString *stdErr = nil;
94+
int result = spawnRoot(path, args, &stdOut, &stdErr);
95+
96+
if (result == 0) {
97+
NSLog(@"File %@ successfully", lock ? @"locked" : @"unlocked");
98+
return YES;
99+
} else {
100+
NSLog(@"Error %@ file: %@", lock ? @"locking" : @"unlocking", stdErr);
101+
return NO;
102+
}
103+
}
104+
84105
- (BOOL) RebootDevice
85106
{
86107
NSString *path = [[NSBundle mainBundle] pathForResource:@"RebootRootHelper" ofType:@""];

EnableQUIC/FileUtils.swift

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,24 @@ class FileUtils {
8888
return editQUICProfile(statusItems: statusItems, defaultConfigItems: nil)
8989
}
9090

91-
static func setLockProfileAttributes() -> Bool {
91+
static func setLockProfileAttributes(lock: Bool) -> Bool {
9292
let deviceController = DeviceController()
93-
return deviceController.setFileAttributes("/var/preferences/com.apple.networkd.plist", permissions: 0o444, owner: "root", group: "wheel")
93+
return deviceController.setFileLock(lock)
94+
// return deviceController.setFileAttributes("/var/preferences/com.apple.networkd.plist", permissions: 0o444, owner: "root", group: "wheel")
95+
}
96+
97+
/// 获取文件是否被锁定
98+
static func isFileLocked() -> Bool {
99+
var fileStat = stat()
100+
101+
// 调用 stat() 获取文件信息
102+
if stat("/var/preferences/com.apple.networkd.plist", &fileStat) == 0 {
103+
// 判断文件是否具有 UF_IMMUTABLE (uchg) 标志
104+
return (fileStat.st_flags & UInt32(UF_IMMUTABLE)) != 0
105+
} else {
106+
print("Failed to get file attributes")
107+
return false
108+
}
94109
}
95110

96111
private static func editQUICProfile(statusItems: [(String, Bool)], defaultConfigItems: [(String, Bool)]? = nil) -> Bool {

EnableQUIC/MainViewController.swift

Lines changed: 77 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import AudioToolbox
33

44
class MainViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
55

6-
let versionCode = "1.2.1"
6+
let versionCode = "1.2.2"
77

88
var tableView = UITableView()
99

@@ -16,7 +16,7 @@ class MainViewController: UIViewController, UITableViewDelegate, UITableViewData
1616
var sections = [
1717
[],
1818
[NSLocalizedString("CFBundleDisplayName", comment: ""), NSLocalizedString("Restore_Default_Settings_text", comment: ""), NSLocalizedString("Reload_QUIC_Config_text", comment: "")],
19-
[NSLocalizedString("Version_text", comment: ""), "GitHub", NSLocalizedString("How_It_Works_text", comment: ""), NSLocalizedString("Introduction_QUIC_text", comment: ""), NSLocalizedString("Reference_text", comment: ""), NSLocalizedString("ThanksForXiaoboVlog", comment: "")]
19+
[NSLocalizedString("Version_text", comment: ""), "GitHub", NSLocalizedString("How_It_Works_text", comment: ""), NSLocalizedString("Introduction_QUIC_text", comment: ""), NSLocalizedString("Reference_text", comment: ""), NSLocalizedString("ThanksForXiaoboVlog", comment: ""), NSLocalizedString("Reference_text", comment: "")]
2020
]
2121

2222
var statusItems: [(String, Bool)] = []
@@ -107,7 +107,7 @@ class MainViewController: UIViewController, UITableViewDelegate, UITableViewData
107107
if section == 0 {
108108
return statusItems.count
109109
} else if section == 3 {
110-
return statusItems.count + 3
110+
return statusItems.count + 4
111111
} else {
112112
return sections[section].count
113113
}
@@ -199,6 +199,10 @@ class MainViewController: UIViewController, UITableViewDelegate, UITableViewData
199199
cell.textLabel?.textAlignment = .center
200200
cell.textLabel?.textColor = .systemRed
201201
} else if indexPath.row == (statusItems.count + 2) {
202+
cell.textLabel?.text = NSLocalizedString("Unlock_Permissions_text", comment: "")
203+
cell.textLabel?.textAlignment = .center
204+
cell.textLabel?.textColor = .systemOrange
205+
} else if indexPath.row == (statusItems.count + 3) {
202206
cell.textLabel?.text = NSLocalizedString("Hide_Advanced_Settings_text", comment: "")
203207
cell.textLabel?.textAlignment = .center
204208
cell.textLabel?.textColor = .systemBlue
@@ -226,6 +230,11 @@ class MainViewController: UIViewController, UITableViewDelegate, UITableViewData
226230
// 添加确定按钮
227231
let confirmButton = UIAlertAction(title: NSLocalizedString("Confirm_text", comment: ""), style: .default // 按钮样式
228232
) { _ in
233+
234+
if FileUtils.isFileLocked() { // 检查文件是否被锁定了
235+
self.showAlertDialog(messags: NSLocalizedString("File_Locked_message", comment: ""), showRespringButton: false)
236+
return
237+
}
229238
// 按钮回调处理
230239
if FileUtils.enableQUIC(statusItems: self.statusItems) {
231240
self.showAlertDialog(messags: String.localizedStringWithFormat(NSLocalizedString("Enable_QUIC_Successful_text", comment: ""), FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.path.appending("/backups/") ?? NSLocalizedString("Unknown_text", comment: "")), showRespringButton: true)
@@ -255,6 +264,10 @@ class MainViewController: UIViewController, UITableViewDelegate, UITableViewData
255264
// 添加确定按钮
256265
let confirmButton = UIAlertAction(title: NSLocalizedString("Confirm_text", comment: ""), style: .default // 按钮样式
257266
) { _ in
267+
if FileUtils.isFileLocked() { // 检查文件是否被锁定了
268+
self.showAlertDialog(messags: NSLocalizedString("File_Locked_message", comment: ""), showRespringButton: false)
269+
return
270+
}
258271
// 按钮回调处理
259272
if FileUtils.setDefaultQUICConfig(statusItems: self.statusItems) {
260273
// 刷新数据和列表
@@ -307,9 +320,14 @@ class MainViewController: UIViewController, UITableViewDelegate, UITableViewData
307320
if let url = URL(string: "https://github.com/xiaobovlog") {
308321
UIApplication.shared.open(url, options: [:], completionHandler: nil)
309322
}
323+
} else if indexPath.row == 6 {
324+
if let url = URL(string: "https://www.douyin.com/video/7339933821128822051") {
325+
UIApplication.shared.open(url, options: [:], completionHandler: nil)
326+
}
310327
}
311328
}
312329
if indexPath.section == 3 { // 高级设置
330+
tableView.deselectRow(at: indexPath, animated: true)
313331
if indexPath.row == (statusItems.count) {
314332
let alert = UIAlertController(
315333
title: NSLocalizedString("Alert_text", comment: ""), // 设置标题
@@ -320,6 +338,10 @@ class MainViewController: UIViewController, UITableViewDelegate, UITableViewData
320338
// 添加确定按钮
321339
let confirmButton = UIAlertAction(title: NSLocalizedString("Confirm_text", comment: ""), style: .default // 按钮样式
322340
) { _ in
341+
if FileUtils.isFileLocked() { // 检查文件是否被锁定了
342+
self.showAlertDialog(messags: NSLocalizedString("File_Locked_message", comment: ""), showRespringButton: false)
343+
return
344+
}
323345
// 按钮回调处理
324346
if FileUtils.customerQUICProfile(statusItems: self.statusItems) {
325347
// 刷新数据和列表
@@ -338,36 +360,11 @@ class MainViewController: UIViewController, UITableViewDelegate, UITableViewData
338360
DispatchQueue.main.async {
339361
self.present(alert, animated: true)
340362
}
341-
} else if indexPath.row == (statusItems.count + 1) {
342-
// 锁定文件权限
343-
let alert = UIAlertController(
344-
title: NSLocalizedString("Alert_text", comment: ""), // 设置标题
345-
message: NSLocalizedString("Lock_QUIC_Config_message", comment: ""), // 设置文本提示
346-
preferredStyle: .alert // 弹窗样式
347-
)
348-
349-
// 添加确定按钮
350-
let confirmButton = UIAlertAction(title: NSLocalizedString("Confirm_text", comment: ""), style: .default // 按钮样式
351-
) { _ in
352-
// 按钮回调处理
353-
if FileUtils.setLockProfileAttributes() {
354-
// 刷新数据和列表
355-
self.loadConfigData()
356-
tableView.reloadData()
357-
358-
self.showAlertDialog(messags: NSLocalizedString("Lock_QUIC_Config_Successful_text", comment: ""), showRespringButton: true)
359-
} else {
360-
self.showAlertDialog(messags: NSLocalizedString("Lock_QUIC_Config_Failed_text", comment: ""), showRespringButton: false)
361-
}
362-
}
363-
alert.addAction(confirmButton)
364-
// 添加取消按钮
365-
alert.addAction(UIAlertAction(title: NSLocalizedString("Cancel_text", comment: ""), style: .cancel))
366-
// 显示弹窗
367-
DispatchQueue.main.async {
368-
self.present(alert, animated: true)
369-
}
370-
} else if indexPath.row == (statusItems.count + 2) {
363+
} else if indexPath.row == (statusItems.count + 1) { // 锁定文件权限
364+
changeFileLockStatus(lock: true)
365+
} else if indexPath.row == (statusItems.count + 2) { // 解锁文件权限
366+
changeFileLockStatus(lock: false)
367+
} else if indexPath.row == (statusItems.count + 3) {
371368
// 隐藏高级设置
372369
showAdvancedItems = false
373370
clickIconImageTimes = 0
@@ -437,6 +434,53 @@ class MainViewController: UIViewController, UITableViewDelegate, UITableViewData
437434
}
438435
}
439436

437+
/// 锁定/解锁配置文件
438+
private func changeFileLockStatus(lock: Bool) {
439+
440+
var message = NSLocalizedString("Lock_QUIC_Config_message", comment: "")
441+
if !lock {
442+
message = NSLocalizedString("Unlock_QUIC_Config_message", comment: "")
443+
}
444+
445+
// 锁定/解锁文件权限
446+
let alert = UIAlertController(
447+
title: NSLocalizedString("Alert_text", comment: ""), // 设置标题
448+
message: message, // 设置文本提示
449+
preferredStyle: .alert // 弹窗样式
450+
)
451+
452+
// 添加确定按钮
453+
let confirmButton = UIAlertAction(title: NSLocalizedString("Confirm_text", comment: ""), style: .default // 按钮样式
454+
) { _ in
455+
// 按钮回调处理
456+
if FileUtils.setLockProfileAttributes(lock: lock) {
457+
// 刷新数据和列表
458+
self.loadConfigData()
459+
self.tableView.reloadData()
460+
461+
if lock {
462+
self.showAlertDialog(messags: NSLocalizedString("Lock_QUIC_Config_Successful_text", comment: ""), showRespringButton: false)
463+
} else {
464+
self.showAlertDialog(messags: NSLocalizedString("Unlock_QUIC_Config_Successful_text", comment: ""), showRespringButton: false)
465+
}
466+
467+
} else {
468+
if lock {
469+
self.showAlertDialog(messags: NSLocalizedString("Lock_QUIC_Config_Failed_text", comment: ""), showRespringButton: false)
470+
} else {
471+
self.showAlertDialog(messags: NSLocalizedString("Unlock_QUIC_Config_Failed_text", comment: ""), showRespringButton: false)
472+
}
473+
}
474+
}
475+
alert.addAction(confirmButton)
476+
// 添加取消按钮
477+
alert.addAction(UIAlertAction(title: NSLocalizedString("Cancel_text", comment: ""), style: .cancel))
478+
// 显示弹窗
479+
DispatchQueue.main.async {
480+
self.present(alert, animated: true)
481+
}
482+
}
483+
440484
func showAlertDialog(messags: String, showRespringButton: Bool) {
441485
let alert = UIAlertController(
442486
title: NSLocalizedString("Alert_text", comment: ""),

EnableQUIC/en.lproj/Localizable.strings

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"Reference_text" = "Reference(Chinese)";
1111
"Save_text" = "Save";
1212
"Lock_Permissions_text" = "Lock File Permissions";
13+
"Unlock_Permissions_text" = "Unlock File Permissions";
1314
"Hide_Advanced_Settings_text" = "Hide Advanced Settings";
1415
"Alert_text" = "Alert";
1516
"Need_Install_With_TrollStore_text" = "Root permission required. Please install using TrollStore. Alternatively, your developer certificate must have the 'com.apple.private.security.no-sandbox' entitlement.\n(This is almost impossible, so stop asking why certificate-signed installation is not supported.)";
@@ -24,10 +25,14 @@
2425
"Save_Config_Failed_text" = "Failed to save settings";
2526
"Respiring_text" = "Respring";
2627
"Enable_QUIC_message" = "Do you want to enable QUIC?\nThe effects and potential side effects cannot be guaranteed.";
28+
"File_Locked_message" = "The file is locked, please unlock the file write permission in advanced settings first.";
2729
"Restore_QUIC_message" = "Do you want to restore the system's default QUIC settings?";
28-
"Lock_QUIC_Config_message" = "Do you want to lock the configuration file's write permissions?\n(Untested. Proceed with caution!)";
30+
"Lock_QUIC_Config_message" = "Do you want to lock the configuration file's write permissions?\n(Untested. Proceed with caution! Please unlock file permissions before uninstalling the app if it is locked.)";
31+
"Unlock_QUIC_Config_message" = "Do you want to unlock the configuration file's write permissions?";
2932
"Lock_QUIC_Config_Successful_text" = "File permissions locked successfully";
33+
"Unlock_QUIC_Config_Successful_text" = "File permissions unlocked successfully";
3034
"Lock_QUIC_Config_Failed_text" = "Failed to lock file permissions";
35+
"Unlock_QUIC_Config_Failed_text" = "Failed to unlock file permissions";
3136
"How_It_Works_text" = "How It Works";
3237
"Works_Principle_text" = "Based on the content from 'https://www.feng.com/post/13873305'(Chinese), this app modifies the parameters in '/var/preferences/com.apple.networkd.plist'.\nHowever, I cannot guarantee the effectiveness or lack of side effects after enabling QUIC. You are advised to understand how it works yourself. We are not responsible for any impact on your device.";
3338
"Not_Supported_text" = "Oops, the configuration file was not retrieved. Your system might not support QUIC, so we cannot proceed.";

0 commit comments

Comments
 (0)