11import Foundation
22import os
3- import Zip
43import cdaswift
54import opainject
5+ import ZIPFoundation
66
77let MACH_PORT_NULL : mach_port_name_t = 0
88let MACH_PORT_DEAD : mach_port_name_t = ~ mach_port_name_t( 0 )
99
10+ let documentsPath : String = " /var/mobile/Documents/ "
11+
1012// Check if it's arm64e device
1113func isArm64eDevice( ) -> Bool {
1214 var systemInfo = utsname ( )
@@ -76,7 +78,7 @@ func createIpa(bundleId: String) -> Int {
7678 // Replace a original binary file with a dumped one
7779 let appResourceDir = ( AppUtils . sharedInstance ( ) . searchAppResourceDir ( bundleId) ! as NSString ) . lastPathComponent
7880 let fileToReplace = workPath. appendingPathComponent ( " Payload " ) . path + " / \( appResourceDir) / \( bundleExecutable) "
79- let replacementFile = " /var/mobile/Documents/ \( bundleExecutable) .decrypted "
81+ let replacementFile = " \( documentsPath ) \( bundleExecutable) .decrypted "
8082 try fileMgr. removeItem ( atPath: fileToReplace)
8183 try fileMgr. copyItem ( atPath: replacementFile, toPath: fileToReplace)
8284
@@ -102,19 +104,31 @@ func createIpa(bundleId: String) -> Int {
102104
103105 // Zip
104106 do {
107+ // Clean ipa first if it's already there
108+ if let filesInDocumentsDir = try ? fileMgr. contentsOfDirectory ( atPath: " \( documentsPath) " ) {
109+ for file in filesInDocumentsDir {
110+ let filefullpath = " \( documentsPath) " . appending ( ( file as NSString ) . lastPathComponent)
111+ if file == " \( bundleExecutable) .ipa " {
112+ try ? fileMgr. removeItem ( atPath: filefullpath)
113+ }
114+ }
115+ }
116+
105117 let buffer : StringBuffer = StringBuffer ( )
106118 var progressBar : ProgressBar = ProgressBar ( output: buffer)
107119
108120 let filePath = URL ( fileURLWithPath: workPath. appendingPathComponent ( " Payload " ) . path, isDirectory: true )
109- let zipFilePath = URL ( fileURLWithPath: " /var/mobile/Documents/ \( bundleExecutable) .ipa " , isDirectory: false )
110- try Zip . zipFiles ( paths: [ filePath] , zipFilePath: zipFilePath, password: nil , progress: { ( progress) in
111- progressBar. render ( count: Int ( progress * 100 ) , total: 100 )
112- progress == 1 ?
121+ let zipFilePath = URL ( fileURLWithPath: " \( documentsPath) \( bundleExecutable) .ipa " , isDirectory: false )
122+
123+ let zipProgress = Progress ( )
124+ let observation = zipProgress. observe ( \. fractionCompleted) { progress, _ in
125+ progressBar. render ( count: Int ( progress. fractionCompleted * 100 ) , total: 100 )
126+ progress. fractionCompleted == 1 ?
113127 { print ( " Zipping... \( buffer. string) " ) ; fflush ( stdout) } ( ) :
114128 { print ( " Zipping... \( buffer. string) " , terminator: " \r " ) ; fflush ( stdout) } ( )
115- } )
116- // Remove the real work path
117- try fileMgr . removeItem ( atPath : workPath . path )
129+ }
130+ try fileMgr . zipItem ( at : filePath , to : zipFilePath , progress : zipProgress )
131+ observation . invalidate ( )
118132 return 0
119133 }
120134 catch {
@@ -156,7 +170,7 @@ func setDecryptTarget(set: Bool, bundleId: String) -> Void {
156170}
157171
158172func backup( arguments: [ String ] , bundleId: String ) -> Void {
159- let documentsURL = URL ( string: " /var/mobile/Documents " ) !
173+ let documentsURL = URL ( string: documentsPath ) !
160174 let filelist = try ! FileManager . default. contentsOfDirectory ( atPath: documentsURL. path)
161175 let bundleExecutable = AppUtils . sharedInstance ( ) . searchAppExecutable ( bundleId) !
162176 for file in filelist {
0 commit comments