@@ -35,21 +35,53 @@ public struct PassBuilder: Sendable {
3535 self . openSSLURL = URL ( fileURLWithPath: openSSLPath)
3636 }
3737
38- private func manifest ( for directory: URL ) throws -> Data {
39- var manifest : [ String : String ] = [ : ]
38+ private static func sourceFiles ( in directory: URL , isPersonalized : Bool = false ) throws -> [ String : Data ] {
39+ var files : [ String : Data ] = [ : ]
4040
4141 let paths = try FileManager . default. subpathsOfDirectory ( atPath: directory. path)
42+
43+ if isPersonalized {
44+ guard
45+ paths. contains ( " personalizationLogo.png " )
46+ || paths. contains ( " personalizationLogo@1x.png " )
47+ || paths. contains ( " personalizationLogo@2x.png " )
48+ || paths. contains ( " personalizationLogo@3x.png " )
49+ else {
50+ throw WalletPassesError . noPersonalizationLogo
51+ }
52+ }
53+
54+ guard
55+ paths. contains ( " icon.png " )
56+ || paths. contains ( " icon@1x.png " )
57+ || paths. contains ( " icon@2x.png " )
58+ || paths. contains ( " icon@3x.png " )
59+ else {
60+ throw WalletPassesError . noIcon
61+ }
62+
4263 for relativePath in paths {
4364 let file = URL ( fileURLWithPath: relativePath, relativeTo: directory)
4465 guard !file. hasDirectoryPath else {
4566 continue
4667 }
4768
48- let hash = try Insecure . SHA1. hash ( data: Data ( contentsOf: file) )
49- manifest [ relativePath] = hash. map { " 0 \( String ( $0, radix: 16 ) ) " . suffix ( 2 ) } . joined ( )
69+ guard !( file. lastPathComponent == " .gitkeep " || file. lastPathComponent == " .DS_Store " ) else {
70+ continue
71+ }
72+
73+ files [ relativePath] = try Data ( contentsOf: file)
74+ }
75+
76+ return files
77+ }
78+
79+ private func manifest( for sourceFiles: [ String : Data ] ) throws -> Data {
80+ let manifest = sourceFiles. mapValues { data in
81+ Insecure . SHA1. hash ( data: data) . map { " 0 \( String ( $0, radix: 16 ) ) " . suffix ( 2 ) } . joined ( )
5082 }
5183
52- return try encoder. encode ( manifest)
84+ return try self . encoder. encode ( manifest)
5385 }
5486
5587 /// Generates a signature for a given manifest or personalization token.
@@ -99,7 +131,7 @@ public struct PassBuilder: Sendable {
99131 ] ,
100132 certificate: Certificate ( pemEncoded: self . pemCertificate) ,
101133 privateKey: . init( pemEncoded: self . pemPrivateKey) ,
102- signingTime: Date ( )
134+ signingTime: Date . now
103135 )
104136 return Data ( signature)
105137 }
@@ -129,35 +161,31 @@ public struct PassBuilder: Sendable {
129161 try FileManager . default. copyItem ( at: filesDirectory, to: tempDir)
130162 defer { try ? FileManager . default. removeItem ( at: tempDir) }
131163
132- var files : [ ArchiveFile ] = [ ]
164+ var archiveFiles : [ ArchiveFile ] = [ ]
133165
134166 let passJSON = try self . encoder. encode ( pass)
135167 try passJSON. write ( to: tempDir. appendingPathComponent ( " pass.json " ) )
136- files . append ( ArchiveFile ( filename: " pass.json " , data: passJSON) )
168+ archiveFiles . append ( ArchiveFile ( filename: " pass.json " , data: passJSON) )
137169
138170 // Pass Personalization
139171 if let personalization {
140172 let personalizationJSONData = try self . encoder. encode ( personalization)
141173 try personalizationJSONData. write ( to: tempDir. appendingPathComponent ( " personalization.json " ) )
142- files . append ( ArchiveFile ( filename: " personalization.json " , data: personalizationJSONData) )
174+ archiveFiles . append ( ArchiveFile ( filename: " personalization.json " , data: personalizationJSONData) )
143175 }
144176
145- let manifest = try self . manifest ( for: tempDir)
146- files. append ( ArchiveFile ( filename: " manifest.json " , data: manifest) )
147- try files. append ( ArchiveFile ( filename: " signature " , data: self . signature ( for: manifest) ) )
177+ let sourceFiles = try Self . sourceFiles ( in: tempDir, isPersonalized: personalization != nil )
148178
149- let paths = try FileManager . default. subpathsOfDirectory ( atPath: filesDirectory. path)
150- for relativePath in paths {
151- let file = URL ( fileURLWithPath: relativePath, relativeTo: tempDir)
152- guard !file. hasDirectoryPath else {
153- continue
154- }
179+ let manifest = try self . manifest ( for: sourceFiles)
180+ archiveFiles. append ( ArchiveFile ( filename: " manifest.json " , data: manifest) )
181+ try archiveFiles. append ( ArchiveFile ( filename: " signature " , data: self . signature ( for: manifest) ) )
155182
156- try files. append ( ArchiveFile ( filename: relativePath, data: Data ( contentsOf: file) ) )
183+ for file in sourceFiles {
184+ archiveFiles. append ( ArchiveFile ( filename: file. key, data: file. value) )
157185 }
158186
159187 let zipFile = tempDir. appendingPathComponent ( " \( UUID ( ) . uuidString) .pkpass " )
160- try Zip . zipData ( archiveFiles: files , zipFilePath: zipFile)
188+ try Zip . zipData ( archiveFiles: archiveFiles , zipFilePath: zipFile)
161189 return try Data ( contentsOf: zipFile)
162190 }
163191}
0 commit comments