33// copy, modify, and distribute this software in source code or binary form for use
44// in connection with the web services and APIs provided by Rover.
55//
6- // This copyright notice shall be included in all copies or substantial portions of
6+ // This copyright notice shall be included in all copies or substantial portions of
77// the software.
88//
99// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1313// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1414// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1515
16- import os. log
17- import UIKit
1816import RoverFoundation
17+ import UIKit
18+ import os. log
1919
2020class ContextManager {
2121 let persistedPushToken = PersistedValue < Context . PushToken > ( storageKey: " io.rover.RoverData.pushToken " )
@@ -24,7 +24,7 @@ class ContextManager {
2424 let persistedAppLastSeenTimestamp = PersistedValue < Date > ( storageKey: " io.rover.RoverData.appLastSeenTimestamp " )
2525 let reachability = Reachability ( hostname: " google.com " ) !
2626 let privacyService : PrivacyService
27-
27+
2828 init ( privacyService: PrivacyService ) {
2929 self . privacyService = privacyService
3030 }
@@ -44,11 +44,11 @@ extension ContextManager: LocaleContextProvider {
4444 var localeLanguage : String ? {
4545 return Locale . current. languageCode
4646 }
47-
47+
4848 var localeRegion : String ? {
4949 return Locale . current. regionCode
5050 }
51-
51+
5252 var localeScript : String ? {
5353 return Locale . current. scriptCode
5454 }
@@ -68,14 +68,12 @@ extension ContextManager: ReachabilityContextProvider {
6868 var isCellularEnabled : Bool {
6969 return self . reachability. isReachableViaWWAN
7070 }
71-
71+
7272 var isWifiEnabled : Bool {
7373 return self . reachability. isReachableViaWiFi
7474 }
7575}
7676
77-
78-
7977// MARK: StaticContextProvider
8078
8179extension ContextManager : StaticContextProvider {
@@ -88,78 +86,83 @@ extension ContextManager: StaticContextProvider {
8886 }
8987 }
9088 }
91-
89+
9290 var appBuild : String {
9391 return Bundle . main. infoDictionary![ " CFBundleVersion " ] as! String
9492 }
95-
93+
9694 var appIdentifier : String {
9795 return Bundle . main. bundleIdentifier!
9896 }
99-
97+
10098 var appVersion : String {
10199 return Bundle . main. infoDictionary![ " CFBundleShortVersionString " ] as! String
102100 }
103-
101+
104102 var buildEnvironment : Context . BuildEnvironment {
105103 #if targetEnvironment(simulator)
106- return . development
107- #else
108- guard let path = Bundle . main. path ( forResource: " embedded " , ofType: " mobileprovision " ) else {
109- os_log ( " Provisioning profile not found " , log: . context, type: . error)
110- return . production
111- }
112-
113- guard let embeddedProfile = try ? String ( contentsOfFile: path, encoding: String . Encoding. ascii) else {
114- os_log ( " Failed to read provisioning profile at path: %@ " , log: . context, type: . error, path)
115- return . production
116- }
117-
118- let scanner = Scanner ( string: embeddedProfile)
119-
120-
121-
122- guard scanner. scanUpToString ( " <?xml version= \" 1.0 \" encoding= \" UTF-8 \" ?> " ) != nil ,
123- let string = scanner. scanUpToString ( " </plist> " ) else {
124- os_log ( " Unrecognized provisioning profile structure " , log: . context, type: . error)
125- return . production
126- }
127-
128- guard let data = string. appending ( " </plist> " ) . data ( using: String . Encoding. utf8) else {
129- os_log ( " Failed to decode provisioning profile " , log: . context, type: . error)
130- return . production
131- }
132-
133- guard let plist = ( try ? PropertyListSerialization . propertyList ( from: data, options: [ ] , format: nil ) ) as? [ String : Any ] else {
134- os_log ( " Failed to serialize provisioning profile " , log: . context, type: . error)
135- return . production
136- }
137-
138- guard let entitlements = plist [ " Entitlements " ] as? [ String : Any ] , let apsEnvironment = entitlements [ " aps-environment " ] as? String else {
139- os_log ( " No entry for \" aps-environment \" found in Entitlements – defaulting to production " , log: . context, type: . info)
140- return . production
141- }
142-
143- switch apsEnvironment {
144- case " production " :
145- return . production
146- case " development " :
147104 return . development
148- default :
149- os_log ( " Unrecognized value for aps-environment: %@ " , log: . context, type: . error, apsEnvironment)
150- return . production
151- }
105+ #else
106+ guard let path = Bundle . main. path ( forResource: " embedded " , ofType: " mobileprovision " ) else {
107+ os_log ( " Provisioning profile not found " , log: . context, type: . error)
108+ return . production
109+ }
110+
111+ guard let profileData = try ? Data ( contentsOf: URL ( fileURLWithPath: path) ) else {
112+ os_log ( " Failed to read provisioning profile at path: %@ " , log: . context, type: . error, path)
113+ return . production
114+ }
115+
116+ // Extract the plist by finding byte ranges in the original data
117+ let startMarker = Data ( " <?xml version= \" 1.0 \" encoding= \" UTF-8 \" ?> " . utf8)
118+ let endMarker = Data ( " </plist> " . utf8)
119+
120+ guard let startRange = profileData. range ( of: startMarker) ,
121+ let endRange = profileData. range ( of: endMarker, in: startRange. upperBound..< profileData. endIndex)
122+ else {
123+ os_log ( " Unrecognized provisioning profile structure " , log: . context, type: . error)
124+ return . production
125+ }
126+
127+ let data = profileData. subdata ( in: startRange. lowerBound..< endRange. upperBound)
128+
129+ guard
130+ let plist = ( try ? PropertyListSerialization . propertyList ( from: data, options: [ ] , format: nil ) )
131+ as? [ String : Any ]
132+ else {
133+ os_log ( " Failed to serialize provisioning profile " , log: . context, type: . error)
134+ return . production
135+ }
136+
137+ guard let entitlements = plist [ " Entitlements " ] as? [ String : Any ] ,
138+ let apsEnvironment = entitlements [ " aps-environment " ] as? String
139+ else {
140+ os_log (
141+ " No entry for \" aps-environment \" found in Entitlements – defaulting to production " , log: . context,
142+ type: . info)
143+ return . production
144+ }
145+
146+ switch apsEnvironment {
147+ case " production " :
148+ return . production
149+ case " development " :
150+ return . development
151+ default :
152+ os_log ( " Unrecognized value for aps-environment: %@ " , log: . context, type: . error, apsEnvironment)
153+ return . production
154+ }
152155 #endif
153156 }
154-
157+
155158 var deviceIdentifier : String ? {
156159 return UIDevice . current. identifierForVendor? . uuidString
157160 }
158-
161+
159162 var deviceManufacturer : String {
160163 return " Apple "
161164 }
162-
165+
163166 var deviceModel : String {
164167 var systemInfo = utsname ( )
165168 uname ( & systemInfo)
@@ -169,37 +172,37 @@ extension ContextManager: StaticContextProvider {
169172 String ( cString: UnsafePointer < CChar > ( $0) )
170173 }
171174 }
172-
175+
173176 let modelName = String ( modelCode)
174-
177+
175178 guard let deviceModel = DeviceModel ( modelName: modelName) else {
176179 os_log ( " Unknown model name: %@ " , log: . context, type: . error, modelName)
177180 return modelName
178181 }
179-
182+
180183 return deviceModel. description
181184 }
182-
185+
183186 var deviceName : String {
184187 return self . persistedDeviceName. value ?? UIDevice . current. name
185188 }
186-
189+
187190 var operatingSystemName : String {
188191 return UIDevice . current. systemName
189192 }
190-
193+
191194 var operatingSystemVersion : String {
192195 return UIDevice . current. systemVersion
193196 }
194-
197+
195198 var screenHeight : Double {
196199 return UIScreen . main. bounds. height
197200 }
198-
201+
199202 var screenWidth : Double {
200203 return UIScreen . main. bounds. width
201204 }
202-
205+
203206 var sdkVersion : String {
204207 return Meta . SDKVersion
205208 }
@@ -240,16 +243,14 @@ extension ContextManager: UserInfoManager {
240243 block ( & userInfo)
241244 self . persistedUserInfo. value = userInfo
242245 }
243-
246+
244247 func clearUserInfo( ) {
245248 self . persistedUserInfo. value = nil
246249 }
247-
250+
248251 var currentUserInfo : [ String : Any ] {
249- get {
250- let attributes : Attributes = self . persistedUserInfo. value ?? Attributes ( )
251- return attributes. flatRawValue ( )
252- }
252+ let attributes : Attributes = self . persistedUserInfo. value ?? Attributes ( )
253+ return attributes. flatRawValue ( )
253254 }
254255}
255256
0 commit comments