├── .DS_Store ├── 1.mobileprovision ├── BS-软件配置1.png ├── BS-软件配置2.png ├── Bsphp ├── .DS_Store ├── AFNetworking │ ├── AFHTTPSessionManager.h │ ├── AFHTTPSessionManager.m │ ├── AFNetworkReachabilityManager.h │ ├── AFNetworkReachabilityManager.m │ ├── AFNetworking.h │ ├── AFSecurityPolicy.h │ ├── AFSecurityPolicy.m │ ├── AFURLRequestSerialization.h │ ├── AFURLRequestSerialization.m │ ├── AFURLResponseSerialization.h │ ├── AFURLResponseSerialization.m │ ├── AFURLSessionManager.h │ └── AFURLSessionManager.m ├── Config.m ├── MBProgressHUD │ ├── MBProgressHUD+NJ.h │ ├── MBProgressHUD+NJ.m │ ├── MBProgressHUD.h │ └── MBProgressHUD.m ├── WX_NongShiFu123.h ├── WX_NongShiFu123.mm └── bsphp │ ├── DES3Util.h │ ├── DES3Util.m │ ├── MF_Base64Additions.h │ ├── MF_Base64Additions.m │ ├── NSDictionary+StichingStringkeyValue.h │ ├── NSDictionary+StichingStringkeyValue.m │ ├── NSString+MD5.h │ ├── NSString+MD5.m │ ├── NSString+Tools.h │ ├── NSString+Tools.m │ ├── NSString+URLCode.h │ ├── NSString+URLCode.m │ ├── NetWorkingApiClient.h │ ├── NetWorkingApiClient.m │ ├── getKeychain.h │ └── getKeychain.m ├── Config.h ├── README.md ├── SCLAlertView ├── SCLAlertView.h ├── SCLAlertView.m ├── SCLAlertViewResponder.h ├── SCLAlertViewResponder.m ├── SCLAlertViewStyleKit.h ├── SCLAlertViewStyleKit.m ├── SCLButton.h ├── SCLButton.m ├── SCLMacros.h ├── SCLSwitchView.h ├── SCLSwitchView.m ├── SCLTextView.h ├── SCLTextView.m ├── SCLTimerDisplay.h ├── SCLTimerDisplay.m ├── UIImage+ImageEffects.h └── UIImage+ImageEffects.m ├── main.m ├── myipad.cn-Prefix.pch ├── myipad.cn.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings │ └── xcuserdata │ │ ├── apple.xcuserdatad │ │ └── WorkspaceSettings.xcsettings │ │ ├── guyongagng.xcuserdatad │ │ └── WorkspaceSettings.xcsettings │ │ ├── guyonggang.xcuserdatad │ │ └── IDEFindNavigatorScopes.plist │ │ ├── nongshifu.xcuserdatad │ │ └── WorkspaceSettings.xcsettings │ │ └── shisange.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── xcshareddata │ └── xcschemes │ │ └── myipad.cn.xcscheme └── xcuserdata │ ├── apple.xcuserdatad │ └── xcschemes │ │ └── xcschememanagement.plist │ ├── guyongagng.xcuserdatad │ └── xcschemes │ │ └── xcschememanagement.plist │ ├── guyonggang.xcuserdatad │ └── xcschemes │ │ └── xcschememanagement.plist │ ├── mac126.xcuserdatad │ └── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ ├── macgu.xcuserdatad │ └── xcschemes │ │ └── xcschememanagement.plist │ ├── macgyg.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ └── xcschememanagement.plist │ ├── nongshifu.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ └── xcschememanagement.plist │ ├── shisange.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ └── xcschememanagement.plist │ └── yi.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── udid.php ├── 参数填写说明.png ├── 购买-更新说明图.png └── 通用BSPHP对接OC源码.zip /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nongshifu/Bsphp-des3_vi-UDID/ed6a6bf9bbd675d1afec57dd8067af1c91a7c83b/.DS_Store -------------------------------------------------------------------------------- /1.mobileprovision: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nongshifu/Bsphp-des3_vi-UDID/ed6a6bf9bbd675d1afec57dd8067af1c91a7c83b/1.mobileprovision -------------------------------------------------------------------------------- /BS-软件配置1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nongshifu/Bsphp-des3_vi-UDID/ed6a6bf9bbd675d1afec57dd8067af1c91a7c83b/BS-软件配置1.png -------------------------------------------------------------------------------- /BS-软件配置2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nongshifu/Bsphp-des3_vi-UDID/ed6a6bf9bbd675d1afec57dd8067af1c91a7c83b/BS-软件配置2.png -------------------------------------------------------------------------------- /Bsphp/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nongshifu/Bsphp-des3_vi-UDID/ed6a6bf9bbd675d1afec57dd8067af1c91a7c83b/Bsphp/.DS_Store -------------------------------------------------------------------------------- /Bsphp/AFNetworking/AFHTTPSessionManager.m: -------------------------------------------------------------------------------- 1 | // AFHTTPSessionManager.m 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "AFHTTPSessionManager.h" 23 | 24 | #import "AFURLRequestSerialization.h" 25 | #import "AFURLResponseSerialization.h" 26 | 27 | #import 28 | #import 29 | #import 30 | 31 | #import 32 | #import 33 | #import 34 | #import 35 | #import 36 | 37 | #if TARGET_OS_IOS || TARGET_OS_TV 38 | #import 39 | #elif TARGET_OS_WATCH 40 | #import 41 | #endif 42 | 43 | @interface AFHTTPSessionManager () 44 | @property (readwrite, nonatomic, strong) NSURL *baseURL; 45 | @end 46 | 47 | @implementation AFHTTPSessionManager 48 | @dynamic responseSerializer; 49 | 50 | + (instancetype)__attribute__((optnone))manager { 51 | return [[[self class] alloc] initWithBaseURL:nil]; 52 | } 53 | 54 | - (instancetype)__attribute__((optnone))init { 55 | return [self initWithBaseURL:nil]; 56 | } 57 | 58 | - (instancetype)__attribute__((optnone))initWithBaseURL:(NSURL *)url { 59 | return [self initWithBaseURL:url sessionConfiguration:nil]; 60 | } 61 | 62 | - (instancetype)__attribute__((optnone))initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration { 63 | return [self initWithBaseURL:nil sessionConfiguration:configuration]; 64 | } 65 | 66 | - (instancetype)__attribute__((optnone))initWithBaseURL:(NSURL *)url 67 | sessionConfiguration:(NSURLSessionConfiguration *)configuration 68 | { 69 | self = [super initWithSessionConfiguration:configuration]; 70 | if (!self) { 71 | return nil; 72 | } 73 | 74 | // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected 75 | if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) { 76 | url = [url URLByAppendingPathComponent:@""]; 77 | } 78 | 79 | self.baseURL = url; 80 | 81 | self.requestSerializer = [AFHTTPRequestSerializer serializer]; 82 | self.responseSerializer = [AFJSONResponseSerializer serializer]; 83 | 84 | return self; 85 | } 86 | 87 | #pragma mark - 88 | 89 | - (void)__attribute__((optnone))setRequestSerializer:(AFHTTPRequestSerializer *)requestSerializer { 90 | NSParameterAssert(requestSerializer); 91 | 92 | _requestSerializer = requestSerializer; 93 | } 94 | 95 | - (void)__attribute__((optnone))setResponseSerializer:(AFHTTPResponseSerializer *)responseSerializer { 96 | NSParameterAssert(responseSerializer); 97 | 98 | [super setResponseSerializer:responseSerializer]; 99 | } 100 | 101 | @dynamic securityPolicy; 102 | 103 | - (void)__attribute__((optnone))setSecurityPolicy:(AFSecurityPolicy *)securityPolicy { 104 | if (securityPolicy.SSLPinningMode != AFSSLPinningModeNone && ![self.baseURL.scheme isEqualToString:@"https"]) { 105 | NSString *pinningMode = @"Unknown Pinning Mode"; 106 | switch (securityPolicy.SSLPinningMode) { 107 | case AFSSLPinningModeNone: pinningMode = @"AFSSLPinningModeNone"; break; 108 | case AFSSLPinningModeCertificate: pinningMode = @"AFSSLPinningModeCertificate"; break; 109 | case AFSSLPinningModePublicKey: pinningMode = @"AFSSLPinningModePublicKey"; break; 110 | } 111 | NSString *reason = [NSString stringWithFormat:@"A security policy configured with `%@` can only be applied on a manager with a secure base URL (i.e. https)", pinningMode]; 112 | @throw [NSException exceptionWithName:@"Invalid Security Policy" reason:reason userInfo:nil]; 113 | } 114 | 115 | [super setSecurityPolicy:securityPolicy]; 116 | } 117 | 118 | #pragma mark - 119 | 120 | - (NSURLSessionDataTask *)__attribute__((optnone))GET:(NSString *)URLString 121 | parameters:(id)parameters 122 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 123 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 124 | { 125 | 126 | return [self GET:URLString parameters:parameters progress:nil success:success failure:failure]; 127 | } 128 | 129 | - (NSURLSessionDataTask *)__attribute__((optnone))GET:(NSString *)URLString 130 | parameters:(id)parameters 131 | progress:(void (^)(NSProgress * _Nonnull))downloadProgress 132 | success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success 133 | failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure 134 | { 135 | 136 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET" 137 | URLString:URLString 138 | parameters:parameters 139 | uploadProgress:nil 140 | downloadProgress:downloadProgress 141 | success:success 142 | failure:failure]; 143 | 144 | [dataTask resume]; 145 | 146 | return dataTask; 147 | } 148 | 149 | - (NSURLSessionDataTask *)__attribute__((optnone))HEAD:(NSString *)URLString 150 | parameters:(id)parameters 151 | success:(void (^)(NSURLSessionDataTask *task))success 152 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 153 | { 154 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"HEAD" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:^(NSURLSessionDataTask *task, __unused id responseObject) { 155 | if (success) { 156 | success(task); 157 | } 158 | } failure:failure]; 159 | 160 | [dataTask resume]; 161 | 162 | return dataTask; 163 | } 164 | 165 | - (NSURLSessionDataTask *)__attribute__((optnone))POST:(NSString *)URLString 166 | parameters:(id)parameters 167 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 168 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 169 | { 170 | return [self POST:URLString parameters:parameters progress:nil success:success failure:failure]; 171 | } 172 | 173 | - (NSURLSessionDataTask *)__attribute__((optnone))POST:(NSString *)URLString 174 | parameters:(id)parameters 175 | progress:(void (^)(NSProgress * _Nonnull))uploadProgress 176 | success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success 177 | failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure 178 | { 179 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure]; 180 | 181 | [dataTask resume]; 182 | 183 | return dataTask; 184 | } 185 | 186 | - (NSURLSessionDataTask *)__attribute__((optnone))POST:(NSString *)URLString 187 | parameters:(nullable id)parameters 188 | constructingBodyWithBlock:(nullable void (^)(id _Nonnull))block 189 | success:(nullable void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success 190 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure 191 | { 192 | return [self POST:URLString parameters:parameters constructingBodyWithBlock:block progress:nil success:success failure:failure]; 193 | } 194 | 195 | - (NSURLSessionDataTask *)__attribute__((optnone))POST:(NSString *)URLString 196 | parameters:(id)parameters 197 | constructingBodyWithBlock:(void (^)(id formData))block 198 | progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress 199 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 200 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 201 | { 202 | NSError *serializationError = nil; 203 | NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError]; 204 | if (serializationError) { 205 | if (failure) { 206 | dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ 207 | failure(nil, serializationError); 208 | }); 209 | } 210 | 211 | return nil; 212 | } 213 | 214 | __block NSURLSessionDataTask *task = [self uploadTaskWithStreamedRequest:request progress:uploadProgress completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { 215 | if (error) { 216 | if (failure) { 217 | failure(task, error); 218 | } 219 | } else { 220 | if (success) { 221 | success(task, responseObject); 222 | } 223 | } 224 | }]; 225 | 226 | [task resume]; 227 | 228 | return task; 229 | } 230 | 231 | - (NSURLSessionDataTask *)__attribute__((optnone))PUT:(NSString *)URLString 232 | parameters:(id)parameters 233 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 234 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 235 | { 236 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PUT" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure]; 237 | 238 | [dataTask resume]; 239 | 240 | return dataTask; 241 | } 242 | 243 | - (NSURLSessionDataTask *)__attribute__((optnone))PATCH:(NSString *)URLString 244 | parameters:(id)parameters 245 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 246 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 247 | { 248 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PATCH" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure]; 249 | 250 | [dataTask resume]; 251 | 252 | return dataTask; 253 | } 254 | 255 | - (NSURLSessionDataTask *)__attribute__((optnone))DELETE:(NSString *)URLString 256 | parameters:(id)parameters 257 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 258 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 259 | { 260 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"DELETE" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure]; 261 | 262 | [dataTask resume]; 263 | 264 | return dataTask; 265 | } 266 | 267 | - (NSURLSessionDataTask *)__attribute__((optnone))dataTaskWithHTTPMethod:(NSString *)method 268 | URLString:(NSString *)URLString 269 | parameters:(id)parameters 270 | uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress 271 | downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress 272 | success:(void (^)(NSURLSessionDataTask *, id))success 273 | failure:(void (^)(NSURLSessionDataTask *, NSError *))failure 274 | { 275 | NSError *serializationError = nil; 276 | NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError]; 277 | if (serializationError) { 278 | if (failure) { 279 | dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ 280 | failure(nil, serializationError); 281 | }); 282 | } 283 | 284 | return nil; 285 | } 286 | 287 | __block NSURLSessionDataTask *dataTask = nil; 288 | dataTask = [self dataTaskWithRequest:request 289 | uploadProgress:uploadProgress 290 | downloadProgress:downloadProgress 291 | completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { 292 | if (error) { 293 | if (failure) { 294 | failure(dataTask, error); 295 | } 296 | } else { 297 | if (success) { 298 | success(dataTask, responseObject); 299 | } 300 | } 301 | }]; 302 | 303 | return dataTask; 304 | } 305 | 306 | #pragma mark - NSObject 307 | 308 | - (NSString *)__attribute__((optnone))description { 309 | return [NSString stringWithFormat:@"<%@: %p, baseURL: %@, session: %@, operationQueue: %@>", NSStringFromClass([self class]), self, [self.baseURL absoluteString], self.session, self.operationQueue]; 310 | } 311 | 312 | #pragma mark - NSSecureCoding 313 | 314 | + (BOOL)__attribute__((optnone))supportsSecureCoding { 315 | return YES; 316 | } 317 | 318 | - (instancetype)__attribute__((optnone))initWithCoder:(NSCoder *)decoder { 319 | NSURL *baseURL = [decoder decodeObjectOfClass:[NSURL class] forKey:NSStringFromSelector(@selector(baseURL))]; 320 | NSURLSessionConfiguration *configuration = [decoder decodeObjectOfClass:[NSURLSessionConfiguration class] forKey:@"sessionConfiguration"]; 321 | if (!configuration) { 322 | NSString *configurationIdentifier = [decoder decodeObjectOfClass:[NSString class] forKey:@"identifier"]; 323 | if (configurationIdentifier) { 324 | #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1100) 325 | configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:configurationIdentifier]; 326 | #else 327 | configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:configurationIdentifier]; 328 | #endif 329 | } 330 | } 331 | 332 | self = [self initWithBaseURL:baseURL sessionConfiguration:configuration]; 333 | if (!self) { 334 | return nil; 335 | } 336 | 337 | self.requestSerializer = [decoder decodeObjectOfClass:[AFHTTPRequestSerializer class] forKey:NSStringFromSelector(@selector(requestSerializer))]; 338 | self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))]; 339 | AFSecurityPolicy *decodedPolicy = [decoder decodeObjectOfClass:[AFSecurityPolicy class] forKey:NSStringFromSelector(@selector(securityPolicy))]; 340 | if (decodedPolicy) { 341 | self.securityPolicy = decodedPolicy; 342 | } 343 | 344 | return self; 345 | } 346 | 347 | - (void)__attribute__((optnone))encodeWithCoder:(NSCoder *)coder { 348 | [super encodeWithCoder:coder]; 349 | 350 | [coder encodeObject:self.baseURL forKey:NSStringFromSelector(@selector(baseURL))]; 351 | if ([self.session.configuration conformsToProtocol:@protocol(NSCoding)]) { 352 | [coder encodeObject:self.session.configuration forKey:@"sessionConfiguration"]; 353 | } else { 354 | [coder encodeObject:self.session.configuration.identifier forKey:@"identifier"]; 355 | } 356 | [coder encodeObject:self.requestSerializer forKey:NSStringFromSelector(@selector(requestSerializer))]; 357 | [coder encodeObject:self.responseSerializer forKey:NSStringFromSelector(@selector(responseSerializer))]; 358 | [coder encodeObject:self.securityPolicy forKey:NSStringFromSelector(@selector(securityPolicy))]; 359 | } 360 | 361 | #pragma mark - NSCopying 362 | 363 | - (instancetype)__attribute__((optnone))copyWithZone:(NSZone *)zone { 364 | AFHTTPSessionManager *HTTPClient = [[[self class] allocWithZone:zone] initWithBaseURL:self.baseURL sessionConfiguration:self.session.configuration]; 365 | 366 | HTTPClient.requestSerializer = [self.requestSerializer copyWithZone:zone]; 367 | HTTPClient.responseSerializer = [self.responseSerializer copyWithZone:zone]; 368 | HTTPClient.securityPolicy = [self.securityPolicy copyWithZone:zone]; 369 | return HTTPClient; 370 | } 371 | 372 | @end 373 | -------------------------------------------------------------------------------- /Bsphp/AFNetworking/AFNetworkReachabilityManager.h: -------------------------------------------------------------------------------- 1 | // AFNetworkReachabilityManager.h 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | 24 | #if !TARGET_OS_WATCH 25 | #import 26 | 27 | typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { 28 | AFNetworkReachabilityStatusUnknown = -1, 29 | AFNetworkReachabilityStatusNotReachable = 0, 30 | AFNetworkReachabilityStatusReachableViaWWAN = 1, 31 | AFNetworkReachabilityStatusReachableViaWiFi = 2, 32 | }; 33 | 34 | NS_ASSUME_NONNULL_BEGIN 35 | 36 | /** 37 | `AFNetworkReachabilityManager` monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces. 38 | 39 | Reachability can be used to determine background information about why a network operation failed, or to trigger a network operation retrying when a connection is established. It should not be used to prevent a user from initiating a network request, as it's possible that an initial request may be required to establish reachability. 40 | 41 | See Apple's Reachability Sample Code ( https://developer.apple.com/library/ios/samplecode/reachability/ ) 42 | 43 | @warning Instances of `AFNetworkReachabilityManager` must be started with `-startMonitoring` before reachability status can be determined. 44 | */ 45 | @interface AFNetworkReachabilityManager : NSObject 46 | 47 | /** 48 | The current network reachability status. 49 | */ 50 | @property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; 51 | 52 | /** 53 | Whether or not the network is currently reachable. 54 | */ 55 | @property (readonly, nonatomic, assign, getter = isReachable) BOOL reachable; 56 | 57 | /** 58 | Whether or not the network is currently reachable via WWAN. 59 | */ 60 | @property (readonly, nonatomic, assign, getter = isReachableViaWWAN) BOOL reachableViaWWAN; 61 | 62 | /** 63 | Whether or not the network is currently reachable via WiFi. 64 | */ 65 | @property (readonly, nonatomic, assign, getter = isReachableViaWiFi) BOOL reachableViaWiFi; 66 | 67 | ///--------------------- 68 | /// @name Initialization 69 | ///--------------------- 70 | 71 | /** 72 | Returns the shared network reachability manager. 73 | */ 74 | + (instancetype)__attribute__((optnone))sharedManager; 75 | 76 | /** 77 | Creates and returns a network reachability manager with the default socket address. 78 | 79 | @return An initialized network reachability manager, actively monitoring the default socket address. 80 | */ 81 | + (instancetype)__attribute__((optnone))manager; 82 | 83 | /** 84 | Creates and returns a network reachability manager for the specified domain. 85 | 86 | @param domain The domain used to evaluate network reachability. 87 | 88 | @return An initialized network reachability manager, actively monitoring the specified domain. 89 | */ 90 | + (instancetype)__attribute__((optnone))managerForDomain:(NSString *)domain; 91 | 92 | /** 93 | Creates and returns a network reachability manager for the socket address. 94 | 95 | @param address The socket address (`sockaddr_in6`) used to evaluate network reachability. 96 | 97 | @return An initialized network reachability manager, actively monitoring the specified socket address. 98 | */ 99 | + (instancetype)__attribute__((optnone))managerForAddress:(const void *)address; 100 | 101 | /** 102 | Initializes an instance of a network reachability manager from the specified reachability object. 103 | 104 | @param reachability The reachability object to monitor. 105 | 106 | @return An initialized network reachability manager, actively monitoring the specified reachability. 107 | */ 108 | - (instancetype)__attribute__((optnone))initWithReachability:(SCNetworkReachabilityRef)reachability NS_DESIGNATED_INITIALIZER; 109 | 110 | /** 111 | * Initializes an instance of a network reachability manager 112 | * 113 | * @return nil as this method is unavailable 114 | */ 115 | - (nullable instancetype)__attribute__((optnone))init NS_UNAVAILABLE; 116 | 117 | ///-------------------------------------------------- 118 | /// @name Starting & Stopping Reachability Monitoring 119 | ///-------------------------------------------------- 120 | 121 | /** 122 | Starts monitoring for changes in network reachability status. 123 | */ 124 | - (void)__attribute__((optnone))startMonitoring; 125 | 126 | /** 127 | Stops monitoring for changes in network reachability status. 128 | */ 129 | - (void)__attribute__((optnone))stopMonitoring; 130 | 131 | ///------------------------------------------------- 132 | /// @name Getting Localized Reachability Description 133 | ///------------------------------------------------- 134 | 135 | /** 136 | Returns a localized string representation of the current network reachability status. 137 | */ 138 | - (NSString *)__attribute__((optnone))localizedNetworkReachabilityStatusString; 139 | 140 | ///--------------------------------------------------- 141 | /// @name Setting Network Reachability Change Callback 142 | ///--------------------------------------------------- 143 | 144 | /** 145 | Sets a callback to be executed when the network availability of the `baseURL` host changes. 146 | 147 | @param block A block object to be executed when the network availability of the `baseURL` host changes.. This block has no return value and takes a single argument which represents the various reachability states from the device to the `baseURL`. 148 | */ 149 | - (void)__attribute__((optnone))setReachabilityStatusChangeBlock:(nullable void (^)(AFNetworkReachabilityStatus status))block; 150 | 151 | @end 152 | 153 | ///---------------- 154 | /// @name Constants 155 | ///---------------- 156 | 157 | /** 158 | ## Network Reachability 159 | 160 | The following constants are provided by `AFNetworkReachabilityManager` as possible network reachability statuses. 161 | 162 | enum { 163 | AFNetworkReachabilityStatusUnknown, 164 | AFNetworkReachabilityStatusNotReachable, 165 | AFNetworkReachabilityStatusReachableViaWWAN, 166 | AFNetworkReachabilityStatusReachableViaWiFi, 167 | } 168 | 169 | `AFNetworkReachabilityStatusUnknown` 170 | The `baseURL` host reachability is not known. 171 | 172 | `AFNetworkReachabilityStatusNotReachable` 173 | The `baseURL` host cannot be reached. 174 | 175 | `AFNetworkReachabilityStatusReachableViaWWAN` 176 | The `baseURL` host can be reached via a cellular connection, such as EDGE or GPRS. 177 | 178 | `AFNetworkReachabilityStatusReachableViaWiFi` 179 | The `baseURL` host can be reached via a Wi-Fi connection. 180 | 181 | ### Keys for Notification UserInfo Dictionary 182 | 183 | Strings that are used as keys in a `userInfo` dictionary in a network reachability status change notification. 184 | 185 | `AFNetworkingReachabilityNotificationStatusItem` 186 | A key in the userInfo dictionary in a `AFNetworkingReachabilityDidChangeNotification` notification. 187 | The corresponding value is an `NSNumber` object representing the `AFNetworkReachabilityStatus` value for the current reachability status. 188 | */ 189 | 190 | ///-------------------- 191 | /// @name Notifications 192 | ///-------------------- 193 | 194 | /** 195 | Posted when network reachability changes. 196 | This notification assigns no notification object. The `userInfo` dictionary contains an `NSNumber` object under the `AFNetworkingReachabilityNotificationStatusItem` key, representing the `AFNetworkReachabilityStatus` value for the current network reachability. 197 | 198 | @warning In order for network reachability to be monitored, include the `SystemConfiguration` framework in the active target's "Link Binary With Library" build phase, and add `#import ` to the header prefix of the project (`Prefix.pch`). 199 | */ 200 | FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityDidChangeNotification; 201 | FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityNotificationStatusItem; 202 | 203 | ///-------------------- 204 | /// @name Functions 205 | ///-------------------- 206 | 207 | /** 208 | Returns a localized string representation of an `AFNetworkReachabilityStatus` value. 209 | */ 210 | FOUNDATION_EXPORT NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status); 211 | 212 | NS_ASSUME_NONNULL_END 213 | #endif 214 | -------------------------------------------------------------------------------- /Bsphp/AFNetworking/AFNetworkReachabilityManager.m: -------------------------------------------------------------------------------- 1 | // AFNetworkReachabilityManager.m 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "AFNetworkReachabilityManager.h" 23 | #if !TARGET_OS_WATCH 24 | 25 | #import 26 | #import 27 | #import 28 | #import 29 | #import 30 | 31 | NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change"; 32 | NSString * const AFNetworkingReachabilityNotificationStatusItem = @"AFNetworkingReachabilityNotificationStatusItem"; 33 | 34 | typedef void (^AFNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus status); 35 | 36 | NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status)__attribute__((optnone)) { 37 | switch (status) { 38 | case AFNetworkReachabilityStatusNotReachable: 39 | return NSLocalizedStringFromTable(@"Not Reachable", @"AFNetworking", nil); 40 | case AFNetworkReachabilityStatusReachableViaWWAN: 41 | return NSLocalizedStringFromTable(@"Reachable via WWAN", @"AFNetworking", nil); 42 | case AFNetworkReachabilityStatusReachableViaWiFi: 43 | return NSLocalizedStringFromTable(@"Reachable via WiFi", @"AFNetworking", nil); 44 | case AFNetworkReachabilityStatusUnknown: 45 | default: 46 | return NSLocalizedStringFromTable(@"Unknown", @"AFNetworking", nil); 47 | } 48 | } 49 | 50 | static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetworkReachabilityFlags flags)__attribute__((optnone)) { 51 | BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0); 52 | BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0); 53 | BOOL canConnectionAutomatically = (((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || ((flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)); 54 | BOOL canConnectWithoutUserInteraction = (canConnectionAutomatically && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0); 55 | BOOL isNetworkReachable = (isReachable && (!needsConnection || canConnectWithoutUserInteraction)); 56 | 57 | AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown; 58 | if (isNetworkReachable == NO) { 59 | status = AFNetworkReachabilityStatusNotReachable; 60 | } 61 | #if TARGET_OS_IPHONE 62 | else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) { 63 | status = AFNetworkReachabilityStatusReachableViaWWAN; 64 | } 65 | #endif 66 | else { 67 | status = AFNetworkReachabilityStatusReachableViaWiFi; 68 | } 69 | 70 | return status; 71 | } 72 | 73 | /** 74 | * Queue a status change notification for the main thread. 75 | * 76 | * This is done to ensure that the notifications are received in the same order 77 | * as they are sent. If notifications are sent directly, it is possible that 78 | * a queued notification (for an earlier status condition) is processed after 79 | * the later update, resulting in the listener being left in the wrong state. 80 | */ 81 | static void AFPostReachabilityStatusChange(SCNetworkReachabilityFlags flags, AFNetworkReachabilityStatusBlock block)__attribute__((optnone)) { 82 | AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags); 83 | dispatch_async(dispatch_get_main_queue(), ^{ 84 | if (block) { 85 | block(status); 86 | } 87 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 88 | NSDictionary *userInfo = @{ AFNetworkingReachabilityNotificationStatusItem: @(status) }; 89 | [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:userInfo]; 90 | }); 91 | } 92 | 93 | static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info)__attribute__((optnone)) { 94 | AFPostReachabilityStatusChange(flags, (__bridge AFNetworkReachabilityStatusBlock)info); 95 | } 96 | 97 | 98 | static const void * AFNetworkReachabilityRetainCallback(const void *info) { 99 | return Block_copy(info); 100 | } 101 | 102 | static void AFNetworkReachabilityReleaseCallback(const void *info) { 103 | if (info) { 104 | Block_release(info); 105 | } 106 | } 107 | 108 | @interface AFNetworkReachabilityManager () 109 | @property (readonly, nonatomic, assign) SCNetworkReachabilityRef networkReachability; 110 | @property (readwrite, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; 111 | @property (readwrite, nonatomic, copy) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock; 112 | @end 113 | 114 | @implementation AFNetworkReachabilityManager 115 | 116 | + (instancetype)__attribute__((optnone))sharedManager { 117 | static AFNetworkReachabilityManager *_sharedManager = nil; 118 | static dispatch_once_t onceToken; 119 | dispatch_once(&onceToken, ^{ 120 | _sharedManager = [self manager]; 121 | }); 122 | 123 | return _sharedManager; 124 | } 125 | 126 | + (instancetype)__attribute__((optnone))managerForDomain:(NSString *)domain { 127 | SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]); 128 | 129 | AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; 130 | 131 | CFRelease(reachability); 132 | 133 | return manager; 134 | } 135 | 136 | + (instancetype)__attribute__((optnone))managerForAddress:(const void *)address { 137 | SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address); 138 | AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; 139 | 140 | CFRelease(reachability); 141 | 142 | return manager; 143 | } 144 | 145 | + (instancetype)__attribute__((optnone))manager 146 | { 147 | #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 90000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) 148 | struct sockaddr_in6 address; 149 | bzero(&address, sizeof(address)); 150 | address.sin6_len = sizeof(address); 151 | address.sin6_family = AF_INET6; 152 | #else 153 | struct sockaddr_in address; 154 | bzero(&address, sizeof(address)); 155 | address.sin_len = sizeof(address); 156 | address.sin_family = AF_INET; 157 | #endif 158 | return [self managerForAddress:&address]; 159 | } 160 | 161 | - (instancetype)__attribute__((optnone))initWithReachability:(SCNetworkReachabilityRef)reachability { 162 | self = [super init]; 163 | if (!self) { 164 | return nil; 165 | } 166 | 167 | _networkReachability = CFRetain(reachability); 168 | self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown; 169 | 170 | return self; 171 | } 172 | 173 | - (instancetype)__attribute__((optnone))init NS_UNAVAILABLE 174 | { 175 | return nil; 176 | } 177 | 178 | - (void)__attribute__((optnone))dealloc { 179 | [self stopMonitoring]; 180 | 181 | if (_networkReachability != NULL) { 182 | CFRelease(_networkReachability); 183 | } 184 | } 185 | 186 | #pragma mark - 187 | 188 | - (BOOL)__attribute__((optnone))isReachable { 189 | return [self isReachableViaWWAN] || [self isReachableViaWiFi]; 190 | } 191 | 192 | - (BOOL)__attribute__((optnone))isReachableViaWWAN { 193 | return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWWAN; 194 | } 195 | 196 | - (BOOL)__attribute__((optnone))isReachableViaWiFi { 197 | return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWiFi; 198 | } 199 | 200 | #pragma mark - 201 | 202 | - (void)__attribute__((optnone))startMonitoring { 203 | [self stopMonitoring]; 204 | 205 | if (!self.networkReachability) { 206 | return; 207 | } 208 | 209 | __weak __typeof(self)weakSelf = self; 210 | AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) { 211 | __strong __typeof(weakSelf)strongSelf = weakSelf; 212 | 213 | strongSelf.networkReachabilityStatus = status; 214 | if (strongSelf.networkReachabilityStatusBlock) { 215 | strongSelf.networkReachabilityStatusBlock(status); 216 | } 217 | 218 | }; 219 | 220 | SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL}; 221 | SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context); 222 | SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); 223 | 224 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{ 225 | SCNetworkReachabilityFlags flags; 226 | if (SCNetworkReachabilityGetFlags(self.networkReachability, &flags)) { 227 | AFPostReachabilityStatusChange(flags, callback); 228 | } 229 | }); 230 | } 231 | 232 | - (void)__attribute__((optnone))stopMonitoring { 233 | if (!self.networkReachability) { 234 | return; 235 | } 236 | 237 | SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); 238 | } 239 | 240 | #pragma mark - 241 | 242 | - (NSString *)__attribute__((optnone))localizedNetworkReachabilityStatusString { 243 | return AFStringFromNetworkReachabilityStatus(self.networkReachabilityStatus); 244 | } 245 | 246 | #pragma mark - 247 | 248 | - (void)__attribute__((optnone))setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block { 249 | self.networkReachabilityStatusBlock = block; 250 | } 251 | 252 | #pragma mark - NSKeyValueObserving 253 | 254 | + (NSSet *)__attribute__((optnone))keyPathsForValuesAffectingValueForKey:(NSString *)key { 255 | if ([key isEqualToString:@"reachable"] || [key isEqualToString:@"reachableViaWWAN"] || [key isEqualToString:@"reachableViaWiFi"]) { 256 | return [NSSet setWithObject:@"networkReachabilityStatus"]; 257 | } 258 | 259 | return [super keyPathsForValuesAffectingValueForKey:key]; 260 | } 261 | 262 | @end 263 | #endif 264 | -------------------------------------------------------------------------------- /Bsphp/AFNetworking/AFNetworking.h: -------------------------------------------------------------------------------- 1 | // AFNetworking.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com/) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | #import 26 | 27 | #ifndef _AFNETWORKING_ 28 | #define _AFNETWORKING_ 29 | 30 | #import "AFURLRequestSerialization.h" 31 | #import "AFURLResponseSerialization.h" 32 | #import "AFSecurityPolicy.h" 33 | 34 | #if !TARGET_OS_WATCH 35 | #import "AFNetworkReachabilityManager.h" 36 | #endif 37 | 38 | #import "AFURLSessionManager.h" 39 | #import "AFHTTPSessionManager.h" 40 | 41 | #endif /* _AFNETWORKING_ */ 42 | -------------------------------------------------------------------------------- /Bsphp/AFNetworking/AFSecurityPolicy.h: -------------------------------------------------------------------------------- 1 | // AFSecurityPolicy.h 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | #import 24 | 25 | typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { 26 | AFSSLPinningModeNone, 27 | AFSSLPinningModePublicKey, 28 | AFSSLPinningModeCertificate, 29 | }; 30 | 31 | /** 32 | `AFSecurityPolicy` evaluates server trust against pinned X.509 certificates and public keys over secure connections. 33 | 34 | Adding pinned SSL certificates to your app helps prevent man-in-the-middle attacks and other vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged to route all communication over an HTTPS connection with SSL pinning configured and enabled. 35 | */ 36 | 37 | NS_ASSUME_NONNULL_BEGIN 38 | 39 | @interface AFSecurityPolicy : NSObject 40 | 41 | /** 42 | The criteria by which server trust should be evaluated against the pinned SSL certificates. Defaults to `AFSSLPinningModeNone`. 43 | */ 44 | @property (readonly, nonatomic, assign) AFSSLPinningMode SSLPinningMode; 45 | 46 | /** 47 | The certificates used to evaluate server trust according to the SSL pinning mode. 48 | 49 | By default, this property is set to any (`.cer`) certificates included in the target compiling AFNetworking. Note that if you are using AFNetworking as embedded framework, no certificates will be pinned by default. Use `certificatesInBundle` to load certificates from your target, and then create a new policy by calling `policyWithPinningMode:withPinnedCertificates`. 50 | 51 | Note that if pinning is enabled, `evaluateServerTrust:forDomain:` will return true if any pinned certificate matches. 52 | */ 53 | @property (nonatomic, strong, nullable) NSSet *pinnedCertificates; 54 | 55 | /** 56 | Whether or not to trust servers with an invalid or expired SSL certificates. Defaults to `NO`. 57 | */ 58 | @property (nonatomic, assign) BOOL allowInvalidCertificates; 59 | 60 | /** 61 | Whether or not to validate the domain name in the certificate's CN field. Defaults to `YES`. 62 | */ 63 | @property (nonatomic, assign) BOOL validatesDomainName; 64 | 65 | ///----------------------------------------- 66 | /// @name Getting Certificates from the Bundle 67 | ///----------------------------------------- 68 | 69 | /** 70 | Returns any certificates included in the bundle. If you are using AFNetworking as an embedded framework, you must use this method to find the certificates you have included in your app bundle, and use them when creating your security policy by calling `policyWithPinningMode:withPinnedCertificates`. 71 | 72 | @return The certificates included in the given bundle. 73 | */ 74 | + (NSSet *)__attribute__((optnone))certificatesInBundle:(NSBundle *)bundle; 75 | 76 | ///----------------------------------------- 77 | /// @name Getting Specific Security Policies 78 | ///----------------------------------------- 79 | 80 | /** 81 | Returns the shared default security policy, which does not allow invalid certificates, validates domain name, and does not validate against pinned certificates or public keys. 82 | 83 | @return The default security policy. 84 | */ 85 | + (instancetype)__attribute__((optnone))defaultPolicy; 86 | 87 | ///--------------------- 88 | /// @name Initialization 89 | ///--------------------- 90 | 91 | /** 92 | Creates and returns a security policy with the specified pinning mode. 93 | 94 | @param pinningMode The SSL pinning mode. 95 | 96 | @return A new security policy. 97 | */ 98 | + (instancetype)__attribute__((optnone))policyWithPinningMode:(AFSSLPinningMode)pinningMode; 99 | 100 | /** 101 | Creates and returns a security policy with the specified pinning mode. 102 | 103 | @param pinningMode The SSL pinning mode. 104 | @param pinnedCertificates The certificates to pin against. 105 | 106 | @return A new security policy. 107 | */ 108 | + (instancetype)__attribute__((optnone))policyWithPinningMode:(AFSSLPinningMode)pinningMode withPinnedCertificates:(NSSet *)pinnedCertificates; 109 | 110 | ///------------------------------ 111 | /// @name Evaluating Server Trust 112 | ///------------------------------ 113 | 114 | /** 115 | Whether or not the specified server trust should be accepted, based on the security policy. 116 | 117 | This method should be used when responding to an authentication challenge from a server. 118 | 119 | @param serverTrust The X.509 certificate trust of the server. 120 | @param domain The domain of serverTrust. If `nil`, the domain will not be validated. 121 | 122 | @return Whether or not to trust the server. 123 | */ 124 | - (BOOL)__attribute__((optnone))evaluateServerTrust:(SecTrustRef)serverTrust 125 | forDomain:(nullable NSString *)domain; 126 | 127 | @end 128 | 129 | NS_ASSUME_NONNULL_END 130 | 131 | ///---------------- 132 | /// @name Constants 133 | ///---------------- 134 | 135 | /** 136 | ## SSL Pinning Modes 137 | 138 | The following constants are provided by `AFSSLPinningMode` as possible SSL pinning modes. 139 | 140 | enum { 141 | AFSSLPinningModeNone, 142 | AFSSLPinningModePublicKey, 143 | AFSSLPinningModeCertificate, 144 | } 145 | 146 | `AFSSLPinningModeNone` 147 | Do not used pinned certificates to validate servers. 148 | 149 | `AFSSLPinningModePublicKey` 150 | Validate host certificates against public keys of pinned certificates. 151 | 152 | `AFSSLPinningModeCertificate` 153 | Validate host certificates against pinned certificates. 154 | */ 155 | -------------------------------------------------------------------------------- /Bsphp/AFNetworking/AFSecurityPolicy.m: -------------------------------------------------------------------------------- 1 | // AFSecurityPolicy.m 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "AFSecurityPolicy.h" 23 | 24 | #import 25 | 26 | #if !TARGET_OS_IOS && !TARGET_OS_WATCH && !TARGET_OS_TV 27 | static NSData * AFSecKeyGetData(SecKeyRef key)__attribute__((optnone)) { 28 | CFDataRef data = NULL; 29 | 30 | __Require_noErr_Quiet(SecItemExport(key, kSecFormatUnknown, kSecItemPemArmour, NULL, &data), _out); 31 | 32 | return (__bridge_transfer NSData *)data; 33 | 34 | _out: 35 | if (data) { 36 | CFRelease(data); 37 | } 38 | 39 | return nil; 40 | } 41 | #endif 42 | 43 | static BOOL AFSecKeyIsEqualToKey(SecKeyRef key1, SecKeyRef key2)__attribute__((optnone)) { 44 | #if TARGET_OS_IOS || TARGET_OS_WATCH || TARGET_OS_TV 45 | return [(__bridge id)key1 isEqual:(__bridge id)key2]; 46 | #else 47 | return [AFSecKeyGetData(key1) isEqual:AFSecKeyGetData(key2)]; 48 | #endif 49 | } 50 | 51 | static id AFPublicKeyForCertificate(NSData *certificate) __attribute__((optnone)){ 52 | id allowedPublicKey = nil; 53 | SecCertificateRef allowedCertificate; 54 | SecPolicyRef policy = nil; 55 | SecTrustRef allowedTrust = nil; 56 | SecTrustResultType result; 57 | 58 | allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificate); 59 | __Require_Quiet(allowedCertificate != NULL, _out); 60 | 61 | policy = SecPolicyCreateBasicX509(); 62 | __Require_noErr_Quiet(SecTrustCreateWithCertificates(allowedCertificate, policy, &allowedTrust), _out); 63 | __Require_noErr_Quiet(SecTrustEvaluate(allowedTrust, &result), _out); 64 | 65 | allowedPublicKey = (__bridge_transfer id)SecTrustCopyPublicKey(allowedTrust); 66 | 67 | _out: 68 | if (allowedTrust) { 69 | CFRelease(allowedTrust); 70 | } 71 | 72 | if (policy) { 73 | CFRelease(policy); 74 | } 75 | 76 | if (allowedCertificate) { 77 | CFRelease(allowedCertificate); 78 | } 79 | 80 | return allowedPublicKey; 81 | } 82 | 83 | static BOOL AFServerTrustIsValid(SecTrustRef serverTrust) __attribute__((optnone)){ 84 | BOOL isValid = NO; 85 | SecTrustResultType result; 86 | __Require_noErr_Quiet(SecTrustEvaluate(serverTrust, &result), _out); 87 | 88 | isValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed); 89 | 90 | _out: 91 | return isValid; 92 | } 93 | 94 | static NSArray * AFCertificateTrustChainForServerTrust(SecTrustRef serverTrust)__attribute__((optnone)) { 95 | CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust); 96 | NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount]; 97 | 98 | for (CFIndex i = 0; i < certificateCount; i++) { 99 | SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i); 100 | [trustChain addObject:(__bridge_transfer NSData *)SecCertificateCopyData(certificate)]; 101 | } 102 | 103 | return [NSArray arrayWithArray:trustChain]; 104 | } 105 | 106 | static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust)__attribute__((optnone)) { 107 | SecPolicyRef policy = SecPolicyCreateBasicX509(); 108 | CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust); 109 | NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount]; 110 | for (CFIndex i = 0; i < certificateCount; i++) { 111 | SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i); 112 | 113 | SecCertificateRef someCertificates[] = {certificate}; 114 | CFArrayRef certificates = CFArrayCreate(NULL, (const void **)someCertificates, 1, NULL); 115 | 116 | SecTrustRef trust; 117 | __Require_noErr_Quiet(SecTrustCreateWithCertificates(certificates, policy, &trust), _out); 118 | 119 | SecTrustResultType result; 120 | __Require_noErr_Quiet(SecTrustEvaluate(trust, &result), _out); 121 | 122 | [trustChain addObject:(__bridge_transfer id)SecTrustCopyPublicKey(trust)]; 123 | 124 | _out: 125 | if (trust) { 126 | CFRelease(trust); 127 | } 128 | 129 | if (certificates) { 130 | CFRelease(certificates); 131 | } 132 | 133 | continue; 134 | } 135 | CFRelease(policy); 136 | 137 | return [NSArray arrayWithArray:trustChain]; 138 | } 139 | 140 | #pragma mark - 141 | 142 | @interface AFSecurityPolicy() 143 | @property (readwrite, nonatomic, assign) AFSSLPinningMode SSLPinningMode; 144 | @property (readwrite, nonatomic, strong) NSSet *pinnedPublicKeys; 145 | @end 146 | 147 | @implementation AFSecurityPolicy 148 | 149 | + (NSSet *)__attribute__((optnone))certificatesInBundle:(NSBundle *)bundle { 150 | NSArray *paths = [bundle pathsForResourcesOfType:@"cer" inDirectory:@"."]; 151 | 152 | NSMutableSet *certificates = [NSMutableSet setWithCapacity:[paths count]]; 153 | for (NSString *path in paths) { 154 | NSData *certificateData = [NSData dataWithContentsOfFile:path]; 155 | [certificates addObject:certificateData]; 156 | } 157 | 158 | return [NSSet setWithSet:certificates]; 159 | } 160 | 161 | + (NSSet *)__attribute__((optnone))defaultPinnedCertificates { 162 | static NSSet *_defaultPinnedCertificates = nil; 163 | static dispatch_once_t onceToken; 164 | dispatch_once(&onceToken, ^{ 165 | NSBundle *bundle = [NSBundle bundleForClass:[self class]]; 166 | _defaultPinnedCertificates = [self certificatesInBundle:bundle]; 167 | }); 168 | 169 | return _defaultPinnedCertificates; 170 | } 171 | 172 | + (instancetype)__attribute__((optnone))defaultPolicy { 173 | AFSecurityPolicy *securityPolicy = [[self alloc] init]; 174 | securityPolicy.SSLPinningMode = AFSSLPinningModeNone; 175 | 176 | return securityPolicy; 177 | } 178 | 179 | + (instancetype)__attribute__((optnone))policyWithPinningMode:(AFSSLPinningMode)pinningMode { 180 | return [self policyWithPinningMode:pinningMode withPinnedCertificates:[self defaultPinnedCertificates]]; 181 | } 182 | 183 | + (instancetype)__attribute__((optnone))policyWithPinningMode:(AFSSLPinningMode)pinningMode withPinnedCertificates:(NSSet *)pinnedCertificates { 184 | AFSecurityPolicy *securityPolicy = [[self alloc] init]; 185 | securityPolicy.SSLPinningMode = pinningMode; 186 | 187 | [securityPolicy setPinnedCertificates:pinnedCertificates]; 188 | 189 | return securityPolicy; 190 | } 191 | 192 | - (instancetype)__attribute__((optnone))init { 193 | self = [super init]; 194 | if (!self) { 195 | return nil; 196 | } 197 | 198 | self.validatesDomainName = YES; 199 | 200 | return self; 201 | } 202 | 203 | - (void)__attribute__((optnone))setPinnedCertificates:(NSSet *)pinnedCertificates { 204 | _pinnedCertificates = pinnedCertificates; 205 | 206 | if (self.pinnedCertificates) { 207 | NSMutableSet *mutablePinnedPublicKeys = [NSMutableSet setWithCapacity:[self.pinnedCertificates count]]; 208 | for (NSData *certificate in self.pinnedCertificates) { 209 | id publicKey = AFPublicKeyForCertificate(certificate); 210 | if (!publicKey) { 211 | continue; 212 | } 213 | [mutablePinnedPublicKeys addObject:publicKey]; 214 | } 215 | self.pinnedPublicKeys = [NSSet setWithSet:mutablePinnedPublicKeys]; 216 | } else { 217 | self.pinnedPublicKeys = nil; 218 | } 219 | } 220 | 221 | #pragma mark - 222 | 223 | - (BOOL)__attribute__((optnone))evaluateServerTrust:(SecTrustRef)serverTrust 224 | forDomain:(NSString *)domain 225 | { 226 | if (domain && self.allowInvalidCertificates && self.validatesDomainName && (self.SSLPinningMode == AFSSLPinningModeNone || [self.pinnedCertificates count] == 0)) { 227 | // https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html 228 | // According to the docs, you should only trust your provided certs for evaluation. 229 | // Pinned certificates are added to the trust. Without pinned certificates, 230 | // there is nothing to evaluate against. 231 | // 232 | // From Apple Docs: 233 | // "Do not implicitly trust self-signed certificates as anchors (kSecTrustOptionImplicitAnchors). 234 | // Instead, add your own (self-signed) CA certificate to the list of trusted anchors." 235 | NSLog(@"In order to validate a domain name for self signed certificates, you MUST use pinning."); 236 | return NO; 237 | } 238 | 239 | NSMutableArray *policies = [NSMutableArray array]; 240 | if (self.validatesDomainName) { 241 | [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)]; 242 | } else { 243 | [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()]; 244 | } 245 | 246 | SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies); 247 | 248 | if (self.SSLPinningMode == AFSSLPinningModeNone) { 249 | return self.allowInvalidCertificates || AFServerTrustIsValid(serverTrust); 250 | } else if (!AFServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) { 251 | return NO; 252 | } 253 | 254 | switch (self.SSLPinningMode) { 255 | case AFSSLPinningModeNone: 256 | default: 257 | return NO; 258 | case AFSSLPinningModeCertificate: { 259 | NSMutableArray *pinnedCertificates = [NSMutableArray array]; 260 | for (NSData *certificateData in self.pinnedCertificates) { 261 | [pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)]; 262 | } 263 | SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates); 264 | 265 | if (!AFServerTrustIsValid(serverTrust)) { 266 | return NO; 267 | } 268 | 269 | // obtain the chain after being validated, which *should* contain the pinned certificate in the last position (if it's the Root CA) 270 | NSArray *serverCertificates = AFCertificateTrustChainForServerTrust(serverTrust); 271 | 272 | for (NSData *trustChainCertificate in [serverCertificates reverseObjectEnumerator]) { 273 | if ([self.pinnedCertificates containsObject:trustChainCertificate]) { 274 | return YES; 275 | } 276 | } 277 | 278 | return NO; 279 | } 280 | case AFSSLPinningModePublicKey: { 281 | NSUInteger trustedPublicKeyCount = 0; 282 | NSArray *publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust); 283 | 284 | for (id trustChainPublicKey in publicKeys) { 285 | for (id pinnedPublicKey in self.pinnedPublicKeys) { 286 | if (AFSecKeyIsEqualToKey((__bridge SecKeyRef)trustChainPublicKey, (__bridge SecKeyRef)pinnedPublicKey)) { 287 | trustedPublicKeyCount += 1; 288 | } 289 | } 290 | } 291 | return trustedPublicKeyCount > 0; 292 | } 293 | } 294 | 295 | return NO; 296 | } 297 | 298 | #pragma mark - NSKeyValueObserving 299 | 300 | + (NSSet *)__attribute__((optnone))keyPathsForValuesAffectingPinnedPublicKeys { 301 | return [NSSet setWithObject:@"pinnedCertificates"]; 302 | } 303 | 304 | #pragma mark - NSSecureCoding 305 | 306 | + (BOOL)__attribute__((optnone))supportsSecureCoding { 307 | return YES; 308 | } 309 | 310 | - (instancetype)__attribute__((optnone))initWithCoder:(NSCoder *)decoder { 311 | 312 | self = [self init]; 313 | if (!self) { 314 | return nil; 315 | } 316 | 317 | self.SSLPinningMode = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(SSLPinningMode))] unsignedIntegerValue]; 318 | self.allowInvalidCertificates = [decoder decodeBoolForKey:NSStringFromSelector(@selector(allowInvalidCertificates))]; 319 | self.validatesDomainName = [decoder decodeBoolForKey:NSStringFromSelector(@selector(validatesDomainName))]; 320 | self.pinnedCertificates = [decoder decodeObjectOfClass:[NSArray class] forKey:NSStringFromSelector(@selector(pinnedCertificates))]; 321 | 322 | return self; 323 | } 324 | 325 | - (void)__attribute__((optnone))encodeWithCoder:(NSCoder *)coder { 326 | [coder encodeObject:[NSNumber numberWithUnsignedInteger:self.SSLPinningMode] forKey:NSStringFromSelector(@selector(SSLPinningMode))]; 327 | [coder encodeBool:self.allowInvalidCertificates forKey:NSStringFromSelector(@selector(allowInvalidCertificates))]; 328 | [coder encodeBool:self.validatesDomainName forKey:NSStringFromSelector(@selector(validatesDomainName))]; 329 | [coder encodeObject:self.pinnedCertificates forKey:NSStringFromSelector(@selector(pinnedCertificates))]; 330 | } 331 | 332 | #pragma mark - NSCopying 333 | 334 | - (instancetype)__attribute__((optnone))copyWithZone:(NSZone *)zone { 335 | AFSecurityPolicy *securityPolicy = [[[self class] allocWithZone:zone] init]; 336 | securityPolicy.SSLPinningMode = self.SSLPinningMode; 337 | securityPolicy.allowInvalidCertificates = self.allowInvalidCertificates; 338 | securityPolicy.validatesDomainName = self.validatesDomainName; 339 | securityPolicy.pinnedCertificates = [self.pinnedCertificates copyWithZone:zone]; 340 | 341 | return securityPolicy; 342 | } 343 | 344 | @end 345 | -------------------------------------------------------------------------------- /Bsphp/AFNetworking/AFURLResponseSerialization.h: -------------------------------------------------------------------------------- 1 | // AFURLResponseSerialization.h 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | #import 24 | 25 | NS_ASSUME_NONNULL_BEGIN 26 | 27 | /** 28 | The `AFURLResponseSerialization` protocol is adopted by an object that decodes data into a more useful object representation, according to details in the server response. Response serializers may additionally perform validation on the incoming response and data. 29 | 30 | For example, a JSON response serializer may check for an acceptable status code (`2XX` range) and content type (`application/json`), decoding a valid JSON response into an object. 31 | */ 32 | @protocol AFURLResponseSerialization 33 | 34 | /** 35 | The response object decoded from the data associated with a specified response. 36 | 37 | @param response The response to be processed. 38 | @param data The response data to be decoded. 39 | @param error The error that occurred while attempting to decode the response data. 40 | 41 | @return The object decoded from the specified response data. 42 | */ 43 | - (nullable id)__attribute__((optnone))responseObjectForResponse:(nullable NSURLResponse *)response 44 | data:(nullable NSData *)data 45 | error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW; 46 | 47 | @end 48 | 49 | #pragma mark - 50 | 51 | /** 52 | `AFHTTPResponseSerializer` conforms to the `AFURLRequestSerialization` & `AFURLResponseSerialization` protocols, offering a concrete base implementation of query string / URL form-encoded parameter serialization and default request headers, as well as response status code and content type validation. 53 | 54 | Any request or response serializer dealing with HTTP is encouraged to subclass `AFHTTPResponseSerializer` in order to ensure consistent default behavior. 55 | */ 56 | @interface AFHTTPResponseSerializer : NSObject 57 | 58 | - (instancetype)__attribute__((optnone))init; 59 | 60 | @property (nonatomic, assign) NSStringEncoding stringEncoding DEPRECATED_MSG_ATTRIBUTE("The string encoding is never used. AFHTTPResponseSerializer only validates status codes and content types but does not try to decode the received data in any way."); 61 | 62 | /** 63 | Creates and returns a serializer with default configuration. 64 | */ 65 | + (instancetype)__attribute__((optnone))serializer; 66 | 67 | ///----------------------------------------- 68 | /// @name Configuring Response Serialization 69 | ///----------------------------------------- 70 | 71 | /** 72 | The acceptable HTTP status codes for responses. When non-`nil`, responses with status codes not contained by the set will result in an error during validation. 73 | 74 | See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 75 | */ 76 | @property (nonatomic, copy, nullable) NSIndexSet *acceptableStatusCodes; 77 | 78 | /** 79 | The acceptable MIME types for responses. When non-`nil`, responses with a `Content-Type` with MIME types that do not intersect with the set will result in an error during validation. 80 | */ 81 | @property (nonatomic, copy, nullable) NSSet *acceptableContentTypes; 82 | 83 | /** 84 | Validates the specified response and data. 85 | 86 | In its base implementation, this method checks for an acceptable status code and content type. Subclasses may wish to add other domain-specific checks. 87 | 88 | @param response The response to be validated. 89 | @param data The data associated with the response. 90 | @param error The error that occurred while attempting to validate the response. 91 | 92 | @return `YES` if the response is valid, otherwise `NO`. 93 | */ 94 | - (BOOL)__attribute__((optnone))validateResponse:(nullable NSHTTPURLResponse *)response 95 | data:(nullable NSData *)data 96 | error:(NSError * _Nullable __autoreleasing *)error; 97 | 98 | @end 99 | 100 | #pragma mark - 101 | 102 | 103 | /** 104 | `AFJSONResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes JSON responses. 105 | 106 | By default, `AFJSONResponseSerializer` accepts the following MIME types, which includes the official standard, `application/json`, as well as other commonly-used types: 107 | 108 | - `application/json` 109 | - `text/json` 110 | - `text/javascript` 111 | */ 112 | @interface AFJSONResponseSerializer : AFHTTPResponseSerializer 113 | 114 | - (instancetype)__attribute__((optnone))init; 115 | 116 | /** 117 | Options for reading the response JSON data and creating the Foundation objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONReadingOptions". `0` by default. 118 | */ 119 | @property (nonatomic, assign) NSJSONReadingOptions readingOptions; 120 | 121 | /** 122 | Whether to remove keys with `NSNull` values from response JSON. Defaults to `NO`. 123 | */ 124 | @property (nonatomic, assign) BOOL removesKeysWithNullValues; 125 | 126 | /** 127 | Creates and returns a JSON serializer with specified reading and writing options. 128 | 129 | @param readingOptions The specified JSON reading options. 130 | */ 131 | + (instancetype)__attribute__((optnone))serializerWithReadingOptions:(NSJSONReadingOptions)readingOptions; 132 | 133 | @end 134 | 135 | #pragma mark - 136 | 137 | /** 138 | `AFXMLParserResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLParser` objects. 139 | 140 | By default, `AFXMLParserResponseSerializer` accepts the following MIME types, which includes the official standard, `application/xml`, as well as other commonly-used types: 141 | 142 | - `application/xml` 143 | - `text/xml` 144 | */ 145 | @interface AFXMLParserResponseSerializer : AFHTTPResponseSerializer 146 | 147 | @end 148 | 149 | #pragma mark - 150 | 151 | #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED 152 | 153 | /** 154 | `AFXMLDocumentResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLDocument` objects. 155 | 156 | By default, `AFXMLDocumentResponseSerializer` accepts the following MIME types, which includes the official standard, `application/xml`, as well as other commonly-used types: 157 | 158 | - `application/xml` 159 | - `text/xml` 160 | */ 161 | @interface AFXMLDocumentResponseSerializer : AFHTTPResponseSerializer 162 | 163 | - (instancetype)__attribute__((optnone))init; 164 | 165 | /** 166 | Input and output options specifically intended for `NSXMLDocument` objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONReadingOptions". `0` by default. 167 | */ 168 | @property (nonatomic, assign) NSUInteger options; 169 | 170 | /** 171 | Creates and returns an XML document serializer with the specified options. 172 | 173 | @param mask The XML document options. 174 | */ 175 | + (instancetype)__attribute__((optnone))serializerWithXMLDocumentOptions:(NSUInteger)mask; 176 | 177 | @end 178 | 179 | #endif 180 | 181 | #pragma mark - 182 | 183 | /** 184 | `AFPropertyListResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLDocument` objects. 185 | 186 | By default, `AFPropertyListResponseSerializer` accepts the following MIME types: 187 | 188 | - `application/x-plist` 189 | */ 190 | @interface AFPropertyListResponseSerializer : AFHTTPResponseSerializer 191 | 192 | - (instancetype)__attribute__((optnone))init; 193 | 194 | /** 195 | The property list format. Possible values are described in "NSPropertyListFormat". 196 | */ 197 | @property (nonatomic, assign) NSPropertyListFormat format; 198 | 199 | /** 200 | The property list reading options. Possible values are described in "NSPropertyListMutabilityOptions." 201 | */ 202 | @property (nonatomic, assign) NSPropertyListReadOptions readOptions; 203 | 204 | /** 205 | Creates and returns a property list serializer with a specified format, read options, and write options. 206 | 207 | @param format The property list format. 208 | @param readOptions The property list reading options. 209 | */ 210 | + (instancetype)__attribute__((optnone))serializerWithFormat:(NSPropertyListFormat)format 211 | readOptions:(NSPropertyListReadOptions)readOptions; 212 | 213 | @end 214 | 215 | #pragma mark - 216 | 217 | /** 218 | `AFImageResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes image responses. 219 | 220 | By default, `AFImageResponseSerializer` accepts the following MIME types, which correspond to the image formats supported by UIImage or NSImage: 221 | 222 | - `image/tiff` 223 | - `image/jpeg` 224 | - `image/gif` 225 | - `image/png` 226 | - `image/ico` 227 | - `image/x-icon` 228 | - `image/bmp` 229 | - `image/x-bmp` 230 | - `image/x-xbitmap` 231 | - `image/x-win-bitmap` 232 | */ 233 | @interface AFImageResponseSerializer : AFHTTPResponseSerializer 234 | 235 | #if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH 236 | /** 237 | The scale factor used when interpreting the image data to construct `responseImage`. Specifying a scale factor of 1.0 results in an image whose size matches the pixel-based dimensions of the image. Applying a different scale factor changes the size of the image as reported by the size property. This is set to the value of scale of the main screen by default, which automatically scales images for retina displays, for instance. 238 | */ 239 | @property (nonatomic, assign) CGFloat imageScale; 240 | 241 | /** 242 | Whether to automatically inflate response image data for compressed formats (such as PNG or JPEG). Enabling this can significantly improve drawing performance on iOS when used with `setCompletionBlockWithSuccess:failure:`, as it allows a bitmap representation to be constructed in the background rather than on the main thread. `YES` by default. 243 | */ 244 | @property (nonatomic, assign) BOOL automaticallyInflatesResponseImage; 245 | #endif 246 | 247 | @end 248 | 249 | #pragma mark - 250 | 251 | /** 252 | `AFCompoundSerializer` is a subclass of `AFHTTPResponseSerializer` that delegates the response serialization to the first `AFHTTPResponseSerializer` object that returns an object for `responseObjectForResponse:data:error:`, falling back on the default behavior of `AFHTTPResponseSerializer`. This is useful for supporting multiple potential types and structures of server responses with a single serializer. 253 | */ 254 | @interface AFCompoundResponseSerializer : AFHTTPResponseSerializer 255 | 256 | /** 257 | The component response serializers. 258 | */ 259 | @property (readonly, nonatomic, copy) NSArray > *responseSerializers; 260 | 261 | /** 262 | Creates and returns a compound serializer comprised of the specified response serializers. 263 | 264 | @warning Each response serializer specified must be a subclass of `AFHTTPResponseSerializer`, and response to `-validateResponse:data:error:`. 265 | */ 266 | + (instancetype)__attribute__((optnone))compoundSerializerWithResponseSerializers:(NSArray > *)responseSerializers; 267 | 268 | @end 269 | 270 | ///---------------- 271 | /// @name Constants 272 | ///---------------- 273 | 274 | /** 275 | ## Error Domains 276 | 277 | The following error domain is predefined. 278 | 279 | - `NSString * const AFURLResponseSerializationErrorDomain` 280 | 281 | ### Constants 282 | 283 | `AFURLResponseSerializationErrorDomain` 284 | AFURLResponseSerializer errors. Error codes for `AFURLResponseSerializationErrorDomain` correspond to codes in `NSURLErrorDomain`. 285 | */ 286 | FOUNDATION_EXPORT NSString * const AFURLResponseSerializationErrorDomain; 287 | 288 | /** 289 | ## User info dictionary keys 290 | 291 | These keys may exist in the user info dictionary, in addition to those defined for NSError. 292 | 293 | - `NSString * const AFNetworkingOperationFailingURLResponseErrorKey` 294 | - `NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey` 295 | 296 | ### Constants 297 | 298 | `AFNetworkingOperationFailingURLResponseErrorKey` 299 | The corresponding value is an `NSURLResponse` containing the response of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`. 300 | 301 | `AFNetworkingOperationFailingURLResponseDataErrorKey` 302 | The corresponding value is an `NSData` containing the original data of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`. 303 | */ 304 | FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseErrorKey; 305 | 306 | FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey; 307 | 308 | NS_ASSUME_NONNULL_END 309 | -------------------------------------------------------------------------------- /Bsphp/Config.m: -------------------------------------------------------------------------------- 1 | // BSPHPOC 2 | // BSPHP 魔改UDID 技术团队 十三哥工作室 3 | // 承接软件APP开发 UDID定制 验证加密二改 PHP JS HTML5开发 辅助开发 4 | // WX:NongShiFu123 QQ350722326 5 | // Created by MRW on 2022/11/14. 6 | // GitHub:http://github.com/nongshifu/ 7 | // 开源Q群: 398423911 8 | // Copyright © 2019年 xiaozhou. All rights reserved. 9 | // 10 | #import "NetWorkingApiClient.h" 11 | #import "Config.h" 12 | #import "DES3Util.h" 13 | #import "NSDictionary+StichingStringkeyValue.h" 14 | #import "NSString+MD5.h" 15 | #import "NSString+URLCode.h" 16 | 17 | #define ConfigLog(fmt, ...) \ 18 | if (Config_NSLog_ENABLED) { \ 19 | NSLog((@"ConfigLog: " fmt), ##__VA_ARGS__); \ 20 | } 21 | //是否打印 22 | #define Config_NSLog_ENABLED YES 23 | 24 | @implementation NetTool : NSObject 25 | + (NSURLSessionDataTask *)__attribute__((optnone))Post_AppendURL:(NSString *)appendURL 26 | parameters:(NSDictionary *)param 27 | success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure{ 28 | NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init]; 29 | [parameters setObject:@"ok" forKey:@"json"]; 30 | if (param != nil) { 31 | NSString *desString = [NSDictionary stitchingStringFromDictionary:param]; 32 | NSString *md5String = [BSPHP_PASSWORD md5:BSPHP_PASSWORD]; 33 | desString = [DES3Util encrypt:desString gkey:md5String]; 34 | 35 | 36 | NSString * sginstr = [BSPHP_INSGIN stringByReplacingOccurrencesOfString:@"[KEY]"withString:desString]; 37 | NSString * sginstrMD5 = [sginstr md5:sginstr]; 38 | ConfigLog(@"replaceStr=%@",sginstrMD5); 39 | parameters[@"sgin"] = sginstrMD5; 40 | desString = [desString URLEncodedString]; 41 | parameters[@"parameter"] = desString; 42 | } 43 | return [[NetWorkingApiClient sharedNetWorkingApiClient] POST:appendURL 44 | parameters:parameters 45 | progress:nil 46 | success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { 47 | 48 | NSString *str = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; 49 | NSString *md5String = [BSPHP_PASSWORD md5:BSPHP_PASSWORD]; 50 | str = [DES3Util decrypt:str gkey:md5String]; 51 | ConfigLog(@"请求网址 = %@",appendURL); 52 | ConfigLog(@"请求parameters = %@",parameters); 53 | ConfigLog(@"服务器返回数据 = %@",str); 54 | NSData * data = [str dataUsingEncoding:NSUTF8StringEncoding]; 55 | NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; 56 | if(dict){ 57 | ConfigLog(@"dict = %@",dict); 58 | } 59 | NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; 60 | 61 | NSString * insginString = [NSString stringWithFormat:@"%@%@%@%@%@", json[@"response"][@"data"], json[@"response"][@"date"],json[@"response"][@"unix"],json[@"response"][@"microtime"],json[@"response"][@"appsafecode"]]; 62 | 63 | insginString = [BSPHP_TOSGIN stringByReplacingOccurrencesOfString:@"[KEY]"withString:insginString]; 64 | //本地签名 65 | md5String = [insginString md5:insginString]; 66 | NSString * sginstrMD5 = json[@"response"][@"sgin"]; 67 | if([md5String isEqualToString:sginstrMD5]){ 68 | //success(data); 69 | ConfigLog(@"签名验证通过\n"); 70 | 71 | }else{ 72 | ConfigLog(@"签名验证未通过\n"); 73 | 74 | 75 | NSData *testData = [@"-1000" dataUsingEncoding: NSUTF8StringEncoding]; 76 | data = testData; 77 | } 78 | 79 | 80 | 81 | success(data); 82 | }failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { 83 | ConfigLog(@"%@",error); 84 | failure(error); 85 | }]; 86 | 87 | } 88 | 89 | 90 | 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /Bsphp/MBProgressHUD/MBProgressHUD+NJ.h: -------------------------------------------------------------------------------- 1 | // 2 | // MBProgressHUD+NJ.h 3 | // NJWisdomCard 4 | // 5 | // Created by apple on 15/8/25. 6 | // Copyright (c) 2015年 Weconex. All rights reserved. 7 | // 8 | 9 | #import "MBProgressHUD.h" 10 | 11 | @interface MBProgressHUD (NJ) 12 | + (MBProgressHUD *)showYuanBing:(NSString *)message jd:(float)jd; 13 | + (MBProgressHUD *)showJindutiao:(NSString *)message jd:(float)jd; 14 | + (void)showSuccess:(NSString *)success HideTime:(float)hideTime; 15 | + (void)showSuccess:(NSString *)success toView:(UIView *)view HideTime:(float)hideTime; 16 | 17 | + (void)showError:(NSString *)error HideTime:(float)hideTime; 18 | + (void)showError:(NSString *)error toView:(UIView *)view HideTime:(float)hideTime; 19 | 20 | 21 | + (MBProgressHUD *)showMessage:(NSString *)message toView:(UIView *)view; 22 | 23 | + (void)hideHUD; 24 | + (void)hideHUDForView:(UIView *)view; 25 | + (MBProgressHUD *)showText:(NSString *)message HideTime:(float)hideTime; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Bsphp/MBProgressHUD/MBProgressHUD+NJ.m: -------------------------------------------------------------------------------- 1 | // 2 | // MBProgressHUD+NJ.m 3 | // NJWisdomCard 4 | // 5 | // Created by apple on 15/8/25. 6 | // Copyright (c) 2015年 Weconex. All rights reserved. 7 | // 8 | 9 | #import "MBProgressHUD+NJ.h" 10 | #define successimg @"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAZ5JREFUeNrMljFLw0AUx9sMQkFo3Apd4lQQAnXPkEU/RxwzibND6TfQxeKU7u03cLDQD6CTY+rQXUuhQpfzH3kJ4XG53OW0+IffkMvl/XmXd++uLYRoaagDLogz0KXxDXgDT8RXbaTMUEEPPICdqNeO5vZUMVVmt2ArzLWlb7UNO2Am7DWjWErDI7AUv6clxSw8HPZLH0HQaqYpOCGmNBZQTGnRRBaZrIBbiuWy9xFf0mOwtjCM2K/hhmvyKJY0Bv2GS7koLWGua/bcJ48iw9Qiu5Bl54EPybw0z9AHpxaFsmBjI+BK5mYevmNRlZ9gzMZCECm+CTLDQUPDO/AuyU6lgVNqxCbKjO7ZWEQZqtR1aia8ElxjWtJcrkZ2P3LoiJHpBpwTVxrbwNPw22RlHFeUO++zkeE2kCnOPvArXnoS06FkLDHYs75q47+w/igjNDBLy61tIlnvIXiu+Scjg8qelFubqnknFdmZnC5F89YNkEhOg1WT08SkABIycg0LJflXV4w9uATzlr3mFGuvey892DXxTy/C7UNf9b8FGADvi3oYmveiPgAAAABJRU5ErkJggg==" 11 | #define errorimg @"iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAARVJREFUeNrEljsKg0AQhnWLgBDQ0hsIAY+Re2jpAaxyj7Sb3iOk9A4BGysvIIIpJ7MwCbJkH6Lu/vA12cl8iY/ZDQEgsEiEXIkLEtPnI/JCnsTb2EkINaTIHZnBnJlqU11PneyGTLA+E33XWhghDWxPQ720whPSwn5pqadSyGH/cJWwgONSyMIzMih+XUJww7/Q1Q3k+AlrRaPE4pJzqSZR9KqXwt5SKEv5n3WVsP8Kc9sbLkl1a6rkoqBa85QZMD3lFcPplhmmX4Fwi3nLqVaXjC0G8RapjUwkZoHjMNpiTHkgpWa9pBpTRiHsNsrWSDsvr4XzF9/LaHM+vJ1vT142YC9HDOeHKC/HxEMPwqHro/5HgAEA49JgVVm9Og0AAAAASUVORK5CYII=" 12 | @implementation MBProgressHUD (NJ) 13 | 14 | /** 15 | * 显示信息 16 | * 17 | * @param text 信息内容 18 | * @param icon 图标 19 | * @param view 显示的视图 20 | */ 21 | + (void)show:(NSString *)text icon:(NSString *)icon view:(UIView *)view HideTime:(float)hideTime 22 | { 23 | if (view == nil) view = [[UIApplication sharedApplication].windows lastObject]; 24 | // 快速显示一个提示信息 25 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES]; 26 | hud.detailsLabelText = text; 27 | // 设置图片 28 | static NSData *data; 29 | if ([icon containsString:@"success.png"]) { 30 | data = [[NSData alloc] initWithBase64EncodedString:successimg options:NSDataBase64DecodingIgnoreUnknownCharacters]; 31 | } 32 | if ([icon containsString:@"error"]) { 33 | data = [[NSData alloc] initWithBase64EncodedString:errorimg options:NSDataBase64DecodingIgnoreUnknownCharacters];; 34 | } 35 | 36 | UIImage *image = [UIImage imageWithData:data]; 37 | hud.customView = [[UIImageView alloc] initWithImage:image]; 38 | // 再设置模式 39 | hud.mode = MBProgressHUDModeCustomView; 40 | 41 | // 隐藏时候从父控件中移除 42 | hud.removeFromSuperViewOnHide = YES; 43 | 44 | if (hideTime==0) { 45 | // 1秒之后再消失 46 | [hud hide:YES afterDelay:9999]; 47 | }else{ 48 | [hud hide:YES afterDelay:hideTime]; 49 | } 50 | 51 | } 52 | 53 | /** 54 | * 显示成功信息 55 | * 56 | * @param success 信息内容 57 | */ 58 | + (void)showSuccess:(NSString *)success HideTime:(float)hideTime 59 | { 60 | [self showSuccess:success toView:nil HideTime:hideTime]; 61 | } 62 | 63 | /** 64 | * 显示成功信息 65 | * 66 | * @param success 信息内容 67 | * @param view 显示信息的视图 68 | */ 69 | + (void)showSuccess:(NSString *)success toView:(UIView *)view HideTime:(float)hideTime 70 | { 71 | [self show:success icon:@"success.png" view:view HideTime:hideTime]; 72 | } 73 | 74 | /** 75 | * 显示错误信息 76 | * 77 | */ 78 | + (void)showError:(NSString *)error HideTime:(float)hideTime 79 | { 80 | [self showError:error toView:nil HideTime:hideTime]; 81 | } 82 | 83 | /** 84 | * 显示错误信息 85 | * 86 | * @param error 错误信息内容 87 | * @param view 需要显示信息的视图 88 | */ 89 | + (void)showError:(NSString *)error toView:(UIView *)view HideTime:(float)hideTime{ 90 | [self show:error icon:@"error.png" view:view HideTime:hideTime]; 91 | } 92 | 93 | /** 94 | * 显示错误信息 95 | * 96 | * @param message 信息内容 97 | * 98 | * @return 直接返回一个MBProgressHUD,需要手动关闭 99 | */ 100 | + (MBProgressHUD *)showMessage:(NSString *)message HideTime:(float)hideTime 101 | { 102 | return [self showMessage:message toView:nil]; 103 | } 104 | 105 | /** 106 | * 显示一些信息 107 | * 108 | * @param message 信息内容 109 | * @param view 需要显示信息的视图 110 | * 111 | * @return 直接返回一个MBProgressHUD,需要手动关闭 112 | */ 113 | + (MBProgressHUD *)showMessage:(NSString *)message toView:(UIView *)view { 114 | if (view == nil) view = [[UIApplication sharedApplication].windows lastObject]; 115 | // 快速显示一个提示信息 116 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES]; 117 | hud.detailsLabelText = message; 118 | // 隐藏时候从父控件中移除 119 | hud.removeFromSuperViewOnHide = YES; 120 | // YES代表需要蒙版效果 121 | hud.dimBackground = YES; 122 | 123 | return hud; 124 | } 125 | /** 126 | * 显示普通信息 127 | * 128 | * @param message 信息内容 129 | * 130 | * @return 直接返回一个MBProgressHUD,需要手动关闭 131 | */ 132 | + (MBProgressHUD *)showText:(NSString *)message HideTime:(float)hideTime 133 | { 134 | return [self showText:message toView:nil HideTime:hideTime]; 135 | } 136 | 137 | /** 138 | * 显示一些信息 139 | * 140 | * @param message 信息内容 141 | * @param view 需要显示信息的视图 142 | * 143 | * @return 直接返回一个MBProgressHUD,需要手动关闭 144 | */ 145 | + (MBProgressHUD *)showText:(NSString *)message toView:(UIView *)view HideTime:(float)hideTime{ 146 | if (view == nil) view = [[UIApplication sharedApplication].windows lastObject]; 147 | // 快速显示一个提示信息 148 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES]; 149 | hud.detailsLabelText = message; 150 | hud.mode = MBProgressHUDModeText; 151 | // 隐藏时候从父控件中移除 152 | hud.removeFromSuperViewOnHide = YES; 153 | // YES代表需要蒙版效果 154 | hud.dimBackground = YES; 155 | if (hideTime==0) { 156 | // 1秒之后再消失 157 | [hud hide:YES afterDelay:9999]; 158 | }else{ 159 | [hud hide:YES afterDelay:hideTime]; 160 | } 161 | return hud; 162 | } 163 | /** 164 | * 显示下载圆饼 165 | * 166 | * @param message 信息内容 167 | * 168 | * @return 直接返回一个MBProgressHUD,需要手动关闭 169 | */ 170 | + (MBProgressHUD *)showYuanBing:(NSString *)message jd:(float)jd 171 | { 172 | return [self showYuanBing:message toView:nil jd:(float)jd]; 173 | } 174 | 175 | /** 176 | * 显示一些信息 177 | * 178 | * @param message 信息内容 179 | * @param view 需要显示信息的视图 180 | * 181 | * @return 直接返回一个MBProgressHUD,需要手动关闭 182 | */ 183 | + (MBProgressHUD *)showYuanBing:(NSString *)message toView:(UIView *)view jd:(float)jd{ 184 | 185 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:[UIApplication sharedApplication].keyWindow animated:YES]; 186 | hud.mode = MBProgressHUDModeDeterminateHorizontalBar; 187 | hud.detailsLabelText =message; 188 | hud.userInteractionEnabled = YES; 189 | hud.progress = jd; 190 | 191 | return hud; 192 | } 193 | /** 194 | * 显示下载进度条 195 | * 196 | * @param message 信息内容 197 | * 198 | * @return 直接返回一个MBProgressHUD,需要手动关闭 199 | */ 200 | + (MBProgressHUD *)showJindutiao:(NSString *)message jd:(float)jd 201 | { 202 | return [self showJindutiao:message toView:nil jd:(float)jd]; 203 | } 204 | 205 | /** 206 | * 显示一些信息 207 | * 208 | * @param message 信息内容 209 | * @param view 需要显示信息的视图 210 | * 211 | * @return 直接返回一个MBProgressHUD,需要手动关闭 212 | */ 213 | + (MBProgressHUD *)showJindutiao:(NSString *)message toView:(UIView *)view jd:(float)jd{ 214 | 215 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:[UIApplication sharedApplication].keyWindow animated:YES]; 216 | hud.mode = MBProgressHUDModeDeterminate; 217 | hud.detailsLabelText =message; 218 | hud.userInteractionEnabled = YES; 219 | hud.progress = jd; 220 | 221 | return hud; 222 | } 223 | 224 | /** 225 | * 手动关闭MBProgressHUD 226 | */ 227 | + (void)hideHUD 228 | { 229 | [self hideHUDForView:nil]; 230 | } 231 | 232 | /** 233 | * 手动关闭MBProgressHUD 234 | * 235 | * @param view 显示MBProgressHUD的视图 236 | */ 237 | + (void)hideHUDForView:(UIView *)view 238 | { 239 | if (view == nil) view = [[UIApplication sharedApplication].windows lastObject]; 240 | [self hideHUDForView:view animated:YES]; 241 | } 242 | 243 | @end 244 | -------------------------------------------------------------------------------- /Bsphp/WX_NongShiFu123.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // BSPHPOC 4 | // BSPHP 魔改UDID 技术团队 十三哥工作室 5 | // 承接软件APP开发 UDID定制 验证加密二改 PHP JS HTML5开发 辅助开发 6 | // WX:NongShiFu123 QQ350722326 7 | // Created by MRW on 2022/11/14. 8 | // GitHub:http://github.com/nongshifu/ 9 | // 开源Q群: 398423911 10 | // Copyright © 2019年 xiaozhou. All rights reserved. 11 | // 12 | #import 13 | #import 14 | 15 | extern NSString*软件版本号,*软件公告,*软件描述,*软件网页地址,*软件url地址,*逻辑A,*逻辑B,*解绑扣除时间,*试用模式; 16 | extern bool 验证状态,过直播开关; 17 | extern NSString*设备特征码; 18 | extern NSString*到期时间; 19 | extern NSString*软件信息; 20 | @interface WX_NongShiFu123 : UIAlertController 21 | - (void)BSPHP; 22 | @property (strong, nonatomic) NSMutableData *receivedData; 23 | @end 24 | 25 | -------------------------------------------------------------------------------- /Bsphp/bsphp/DES3Util.h: -------------------------------------------------------------------------------- 1 | // 2 | // DES3Util.h 3 | // BSPHPOC 4 | // BSPHP 魔改UDID 技术团队 十三哥工作室 5 | // 承接软件APP开发 UDID定制 验证加密二改 PHP JS HTML5开发 辅助开发 6 | // WX:NongShiFu123 QQ350722326 7 | // Created by MRW on 2022/11/14. 8 | // GitHub:http://github.com/nongshifu/ 9 | // 开源Q群: 398423911 10 | // Copyright © 2019年 xiaozhou. All rights reserved. 11 | // 12 | #import 13 | @interface DES3Util : NSObject { 14 | } 15 | // 加密方法 16 | + (NSString*)__attribute__((optnone))encrypt:(NSString*)plainText gkey:(NSString *)gkey; 17 | // 解密方法 18 | + (NSString*)__attribute__((optnone))decrypt:(NSString*)encryptText gkey:(NSString *)gkey; 19 | 20 | @end 21 | 22 | #import 23 | 24 | //@interface DES3Util : NSObject 25 | 26 | //@end 27 | -------------------------------------------------------------------------------- /Bsphp/bsphp/DES3Util.m: -------------------------------------------------------------------------------- 1 | // 2 | // DES3Util.m 3 | // BSPHPOC 4 | // BSPHP 魔改UDID 技术团队 十三哥工作室 5 | // 承接软件APP开发 UDID定制 验证加密二改 PHP JS HTML5开发 辅助开发 6 | // WX:NongShiFu123 QQ350722326 7 | // Created by MRW on 2022/11/14. 8 | // GitHub:http://github.com/nongshifu/ 9 | // 开源Q群: 398423911 10 | // Copyright © 2019年 xiaozhou. All rights reserved. 11 | // 12 | #import "Config.h" 13 | #import "DES3Util.h" 14 | #import 15 | #import "MF_Base64Additions.h" 16 | 17 | @implementation DES3Util 18 | 19 | // 加密方法 20 | + (NSString*)__attribute__((optnone))encrypt:(NSString*)plainText gkey:(NSString *)gkey { 21 | NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding]; 22 | size_t plainTextBufferSize = [data length]; 23 | const void *vplainText = (const void *)[data bytes]; 24 | 25 | CCCryptorStatus ccStatus; 26 | uint8_t *bufferPtr = NULL; 27 | size_t bufferPtrSize = 0; 28 | size_t movedBytes = 0; 29 | 30 | bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1); 31 | bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t)); 32 | memset((void *)bufferPtr, 0x0, bufferPtrSize); 33 | 34 | const void *vkey = (const void *) [gkey UTF8String]; 35 | const void *vinitVec = (const void *) [gIv UTF8String]; 36 | 37 | ccStatus = CCCrypt(kCCEncrypt, 38 | kCCAlgorithm3DES, 39 | kCCOptionPKCS7Padding, 40 | vkey, 41 | kCCKeySize3DES, 42 | vinitVec, 43 | vplainText, 44 | plainTextBufferSize, 45 | (void *)bufferPtr, 46 | bufferPtrSize, 47 | &movedBytes); 48 | 49 | NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes]; 50 | NSString *result = [myData base64String];//[GTMBase64 stringByEncodingData:myData]; 51 | return result; 52 | } 53 | 54 | // 解密方法 55 | + (NSString*)__attribute__((optnone))decrypt:(NSString*)encryptText gkey:(NSString *)gkey { 56 | //NSString *base64Str = [encryptText dataUsingEncoding:NSUTF8StringEncoding] 57 | NSData *encryptData = [NSData dataWithBase64String:encryptText];//[GTMBase64 decodeData:[encryptText dataUsingEncoding:NSUTF8StringEncoding]]; 58 | size_t plainTextBufferSize = [encryptData length]; 59 | const void *vplainText = [encryptData bytes]; 60 | 61 | CCCryptorStatus ccStatus; 62 | uint8_t *bufferPtr = NULL; 63 | size_t bufferPtrSize = 0; 64 | size_t movedBytes = 0; 65 | bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1); 66 | bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t)); 67 | memset((void *)bufferPtr, 0x0, bufferPtrSize); 68 | const void *vkey = (const void *) [gkey UTF8String]; 69 | const void *vinitVec = (const void *) [gIv UTF8String]; 70 | 71 | ccStatus = CCCrypt(kCCDecrypt, 72 | kCCAlgorithm3DES, 73 | kCCOptionPKCS7Padding, 74 | vkey, 75 | kCCKeySize3DES, 76 | vinitVec, 77 | vplainText, 78 | plainTextBufferSize, 79 | (void *)bufferPtr, 80 | bufferPtrSize, 81 | &movedBytes); 82 | 83 | NSString *result = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr 84 | length:(NSUInteger)movedBytes] encoding:NSUTF8StringEncoding]; 85 | return result; 86 | } 87 | 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /Bsphp/bsphp/MF_Base64Additions.h: -------------------------------------------------------------------------------- 1 | // 2 | // MF_Base64Additions.h 3 | // Base64 -- RFC 4648 compatible implementation 4 | // see http://www.ietf.org/rfc/rfc4648.txt for more details 5 | // 6 | // Designed to be compiled with Automatic Reference Counting 7 | // 8 | // Created by Dave Poirier on 2012-06-14. 9 | // Public Domain 10 | // Hosted at https://github.com/ekscrypto/Base64 11 | // 12 | 13 | #import 14 | 15 | @interface NSString (Base64Addition) 16 | +(NSString *)__attribute__((optnone))stringFromBase64String:(NSString *)base64String; 17 | +(NSString *)__attribute__((optnone))stringFromBase64UrlEncodedString:(NSString *)base64UrlEncodedString; 18 | -(NSString *)__attribute__((optnone))base64String; 19 | -(NSString *)__attribute__((optnone))base64UrlEncodedString; 20 | @end 21 | 22 | @interface NSData (Base64Addition) 23 | +(NSData *)__attribute__((optnone))dataWithBase64String:(NSString *)base64String; 24 | +(NSData *)__attribute__((optnone))dataWithBase64UrlEncodedString:(NSString *)base64UrlEncodedString; 25 | -(NSString *)__attribute__((optnone))base64String; 26 | -(NSString *)__attribute__((optnone))base64UrlEncodedString; 27 | @end 28 | 29 | @interface MF_Base64Codec : NSObject 30 | +(NSData *)__attribute__((optnone))dataFromBase64String:(NSString *)base64String; 31 | +(NSString *)__attribute__((optnone))base64StringFromData:(NSData *)data; 32 | +(NSString *)__attribute__((optnone))base64UrlEncodedStringFromBase64String:(NSString *)base64String; 33 | +(NSString *)__attribute__((optnone))base64StringFromBase64UrlEncodedString:(NSString *)base64UrlEncodedString; 34 | @end 35 | -------------------------------------------------------------------------------- /Bsphp/bsphp/MF_Base64Additions.m: -------------------------------------------------------------------------------- 1 | // 2 | // MF_Base64Additions.m 3 | // Base64 -- RFC 4648 compatible implementation 4 | // see http://www.ietf.org/rfc/rfc4648.txt for more details 5 | // 6 | // Designed to be compiled with Automatic Reference Counting 7 | // 8 | // Created by Dave Poirier on 2012-06-14. 9 | // Public Domain 10 | // Hosted at https://github.com/ekscrypto/Base64 11 | // 12 | 13 | #import "MF_Base64Additions.h" 14 | 15 | @implementation MF_Base64Codec 16 | //加编译器属性 17 | +(NSString *)__attribute__((optnone))base64StringFromBase64UrlEncodedString:(NSString *)base64UrlEncodedString 18 | { 19 | NSString *s = base64UrlEncodedString; 20 | s = [s stringByReplacingOccurrencesOfString:@"-" withString:@"+"]; 21 | s = [s stringByReplacingOccurrencesOfString:@"_" withString:@"/"]; 22 | switch (s.length % 4) { 23 | case 2: 24 | s = [s stringByAppendingString:@"=="]; 25 | break; 26 | case 3: 27 | s = [s stringByAppendingString:@"="]; 28 | break; 29 | default: 30 | break; 31 | } 32 | return s; 33 | } 34 | 35 | +(NSString *)__attribute__((optnone))base64UrlEncodedStringFromBase64String:(NSString *)base64String 36 | { 37 | NSString *s = base64String; 38 | s = [s stringByReplacingOccurrencesOfString:@"=" withString:@""]; 39 | s = [s stringByReplacingOccurrencesOfString:@"+" withString:@"-"]; 40 | s = [s stringByReplacingOccurrencesOfString:@"/" withString:@"_"]; 41 | return s; 42 | } 43 | 44 | +(NSData *)__attribute__((optnone))dataFromBase64String:(NSString *)encoding 45 | { 46 | NSData *data = nil; 47 | unsigned char *decodedBytes = NULL; 48 | @try { 49 | #define __ 255 50 | static char decodingTable[256] = { 51 | __,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0x00 - 0x0F 52 | __,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0x10 - 0x1F 53 | __,__,__,__, __,__,__,__, __,__,__,62, __,__,__,63, // 0x20 - 0x2F 54 | 52,53,54,55, 56,57,58,59, 60,61,__,__, __, 0,__,__, // 0x30 - 0x3F 55 | __, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, // 0x40 - 0x4F 56 | 15,16,17,18, 19,20,21,22, 23,24,25,__, __,__,__,__, // 0x50 - 0x5F 57 | __,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, // 0x60 - 0x6F 58 | 41,42,43,44, 45,46,47,48, 49,50,51,__, __,__,__,__, // 0x70 - 0x7F 59 | __,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0x80 - 0x8F 60 | __,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0x90 - 0x9F 61 | __,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0xA0 - 0xAF 62 | __,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0xB0 - 0xBF 63 | __,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0xC0 - 0xCF 64 | __,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0xD0 - 0xDF 65 | __,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0xE0 - 0xEF 66 | __,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0xF0 - 0xFF 67 | }; 68 | encoding = [encoding stringByReplacingOccurrencesOfString:@"=" withString:@""]; 69 | NSData *encodedData = [encoding dataUsingEncoding:NSASCIIStringEncoding]; 70 | unsigned char *encodedBytes = (unsigned char *)[encodedData bytes]; 71 | 72 | NSUInteger encodedLength = [encodedData length]; 73 | if( encodedLength >= (NSUIntegerMax - 3) ) return nil; // NSUInteger overflow check 74 | NSUInteger encodedBlocks = (encodedLength+3) >> 2; 75 | NSUInteger expectedDataLength = encodedBlocks * 3; 76 | 77 | unsigned char decodingBlock[4]; 78 | 79 | decodedBytes = malloc(expectedDataLength); 80 | if( decodedBytes != NULL ) { 81 | 82 | NSUInteger i = 0; 83 | NSUInteger j = 0; 84 | NSUInteger k = 0; 85 | unsigned char c; 86 | while( i < encodedLength ) { 87 | c = decodingTable[encodedBytes[i]]; 88 | i++; 89 | if( c != __ ) { 90 | decodingBlock[j] = c; 91 | j++; 92 | if( j == 4 ) { 93 | decodedBytes[k] = (decodingBlock[0] << 2) | (decodingBlock[1] >> 4); 94 | decodedBytes[k+1] = (decodingBlock[1] << 4) | (decodingBlock[2] >> 2); 95 | decodedBytes[k+2] = (decodingBlock[2] << 6) | (decodingBlock[3]); 96 | j = 0; 97 | k += 3; 98 | } 99 | } 100 | } 101 | 102 | // Process left over bytes, if any 103 | if( j == 3 ) { 104 | decodedBytes[k] = (decodingBlock[0] << 2) | (decodingBlock[1] >> 4); 105 | decodedBytes[k+1] = (decodingBlock[1] << 4) | (decodingBlock[2] >> 2); 106 | k += 2; 107 | } else if( j == 2 ) { 108 | decodedBytes[k] = (decodingBlock[0] << 2) | (decodingBlock[1] >> 4); 109 | k += 1; 110 | } 111 | data = [[NSData alloc] initWithBytes:decodedBytes length:k]; 112 | } 113 | } 114 | @catch (NSException *exception) { 115 | data = nil; 116 | NSLog(@"WARNING: error occured while decoding base 32 string: %@", exception); 117 | } 118 | @finally { 119 | if( decodedBytes != NULL ) { 120 | free( decodedBytes ); 121 | } 122 | } 123 | return data; 124 | } 125 | +(NSString *)__attribute__((optnone))base64StringFromData:(NSData *)data 126 | { 127 | NSString *encoding = nil; 128 | unsigned char *encodingBytes = NULL; 129 | @try { 130 | static char encodingTable[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 131 | static NSUInteger paddingTable[] = {0,2,1}; 132 | // Table 1: The Base 64 Alphabet 133 | // 134 | // Value Encoding Value Encoding Value Encoding Value Encoding 135 | // 0 A 17 R 34 i 51 z 136 | // 1 B 18 S 35 j 52 0 137 | // 2 C 19 T 36 k 53 1 138 | // 3 D 20 U 37 l 54 2 139 | // 4 E 21 V 38 m 55 3 140 | // 5 F 22 W 39 n 56 4 141 | // 6 G 23 X 40 o 57 5 142 | // 7 H 24 Y 41 p 58 6 143 | // 8 I 25 Z 42 q 59 7 144 | // 9 J 26 a 43 r 60 8 145 | // 10 K 27 b 44 s 61 9 146 | // 11 L 28 c 45 t 62 + 147 | // 12 M 29 d 46 u 63 / 148 | // 13 N 30 e 47 v 149 | // 14 O 31 f 48 w (pad) = 150 | // 15 P 32 g 49 x 151 | // 16 Q 33 h 50 y 152 | 153 | NSUInteger dataLength = [data length]; 154 | NSUInteger encodedBlocks = dataLength / 3; 155 | if( (encodedBlocks + 1) >= (NSUIntegerMax / 4) ) return nil; // NSUInteger overflow check 156 | NSUInteger padding = paddingTable[dataLength % 3]; 157 | if( padding > 0 ) encodedBlocks++; 158 | NSUInteger encodedLength = encodedBlocks * 4; 159 | 160 | encodingBytes = malloc(encodedLength); 161 | if( encodingBytes != NULL ) { 162 | NSUInteger rawBytesToProcess = dataLength; 163 | NSUInteger rawBaseIndex = 0; 164 | NSUInteger encodingBaseIndex = 0; 165 | unsigned char *rawBytes = (unsigned char *)[data bytes]; 166 | unsigned char rawByte1, rawByte2, rawByte3; 167 | while( rawBytesToProcess >= 3 ) { 168 | rawByte1 = rawBytes[rawBaseIndex]; 169 | rawByte2 = rawBytes[rawBaseIndex+1]; 170 | rawByte3 = rawBytes[rawBaseIndex+2]; 171 | encodingBytes[encodingBaseIndex] = encodingTable[((rawByte1 >> 2) & 0x3F)]; 172 | encodingBytes[encodingBaseIndex+1] = encodingTable[((rawByte1 << 4) & 0x30) | ((rawByte2 >> 4) & 0x0F) ]; 173 | encodingBytes[encodingBaseIndex+2] = encodingTable[((rawByte2 << 2) & 0x3C) | ((rawByte3 >> 6) & 0x03) ]; 174 | encodingBytes[encodingBaseIndex+3] = encodingTable[(rawByte3 & 0x3F)]; 175 | 176 | rawBaseIndex += 3; 177 | encodingBaseIndex += 4; 178 | rawBytesToProcess -= 3; 179 | } 180 | rawByte2 = 0; 181 | switch (dataLength-rawBaseIndex) { 182 | case 2: 183 | rawByte2 = rawBytes[rawBaseIndex+1]; 184 | case 1: 185 | rawByte1 = rawBytes[rawBaseIndex]; 186 | encodingBytes[encodingBaseIndex] = encodingTable[((rawByte1 >> 2) & 0x3F)]; 187 | encodingBytes[encodingBaseIndex+1] = encodingTable[((rawByte1 << 4) & 0x30) | ((rawByte2 >> 4) & 0x0F) ]; 188 | encodingBytes[encodingBaseIndex+2] = encodingTable[((rawByte2 << 2) & 0x3C) ]; 189 | // we can skip rawByte3 since we have a partial block it would always be 0 190 | break; 191 | } 192 | // compute location from where to begin inserting padding, it may overwrite some bytes from the partial block encoding 193 | // if their value was 0 (cases 1-2). 194 | encodingBaseIndex = encodedLength - padding; 195 | while( padding-- > 0 ) { 196 | encodingBytes[encodingBaseIndex++] = '='; 197 | } 198 | encoding = [[NSString alloc] initWithBytes:encodingBytes length:encodedLength encoding:NSASCIIStringEncoding]; 199 | } 200 | } 201 | @catch (NSException *exception) { 202 | encoding = nil; 203 | NSLog(@"WARNING: error occured while tring to encode base 32 data: %@", exception); 204 | } 205 | @finally { 206 | if( encodingBytes != NULL ) { 207 | free( encodingBytes ); 208 | } 209 | } 210 | return encoding; 211 | } 212 | @end 213 | 214 | @implementation NSString (Base64Addition) 215 | -(NSString *)__attribute__((optnone))base64String 216 | { 217 | NSData *utf8encoding = [self dataUsingEncoding:NSUTF8StringEncoding]; 218 | return [MF_Base64Codec base64StringFromData:utf8encoding]; 219 | } 220 | -(NSString *)__attribute__((optnone))base64UrlEncodedString 221 | { 222 | return [MF_Base64Codec base64UrlEncodedStringFromBase64String:[self base64String]]; 223 | } 224 | +(NSString *)__attribute__((optnone))stringFromBase64String:(NSString *)base64String 225 | { 226 | NSData *utf8encoding = [MF_Base64Codec dataFromBase64String:base64String]; 227 | return [[NSString alloc] initWithData:utf8encoding encoding:NSUTF8StringEncoding]; 228 | } 229 | +(NSString *)__attribute__((optnone))stringFromBase64UrlEncodedString:(NSString *)base64UrlEncodedString 230 | { 231 | return [self stringFromBase64String:[MF_Base64Codec base64StringFromBase64UrlEncodedString:base64UrlEncodedString]]; 232 | } 233 | @end 234 | 235 | @implementation NSData (Base64Addition) 236 | +(NSData *)__attribute__((optnone))dataWithBase64String:(NSString *)base64String 237 | { 238 | return [MF_Base64Codec dataFromBase64String:base64String]; 239 | } 240 | +(NSData *)__attribute__((optnone))dataWithBase64UrlEncodedString:(NSString *)base64UrlEncodedString 241 | { 242 | return [self dataWithBase64String:[MF_Base64Codec base64StringFromBase64UrlEncodedString:base64UrlEncodedString]]; 243 | } 244 | -(NSString *)__attribute__((optnone))base64String 245 | { 246 | return [MF_Base64Codec base64StringFromData:self]; 247 | } 248 | -(NSString *)__attribute__((optnone))base64UrlEncodedString 249 | { 250 | return [MF_Base64Codec base64UrlEncodedStringFromBase64String:[self base64String]]; 251 | } 252 | @end 253 | -------------------------------------------------------------------------------- /Bsphp/bsphp/NSDictionary+StichingStringkeyValue.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+StichingStringkeyValue.h 3 | // BSPHPOC 4 | // 5 | // Created by MRW on 2016/12/28. 6 | // Copyright © 2016年 xiaozhou. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSDictionary (StichingStringkeyValue) 12 | + (NSString *)__attribute__((optnone))stitchingStringFromDictionary:(NSDictionary *)dictionary; 13 | @end 14 | -------------------------------------------------------------------------------- /Bsphp/bsphp/NSDictionary+StichingStringkeyValue.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+StichingStringkeyValue.m 3 | // BSPHPOC 4 | // 5 | // Created by MRW on 2016/12/28. 6 | // Copyright © 2016年 xiaozhou. All rights reserved. 7 | // 8 | 9 | #import "NSDictionary+StichingStringkeyValue.h" 10 | 11 | @implementation NSDictionary (StichingStringkeyValue) 12 | /** 13 | 将字典拼接成URL形式并以字符串返回 14 | 15 | @param dictionary 参数字典 16 | @return 字符串形式返回 17 | */ 18 | + (NSString *)__attribute__((optnone))stitchingStringFromDictionary:(NSDictionary *)dictionary{ 19 | NSMutableString *str = [[NSMutableString alloc]initWithCapacity:10]; 20 | bool first = YES; 21 | for (NSString *key in dictionary) 22 | { 23 | if (first) 24 | { 25 | [str appendString:[NSString stringWithFormat:@"%@=%@",key,[dictionary objectForKey:key]]]; 26 | first = !first; 27 | }else 28 | { 29 | 30 | [str appendString:[NSString stringWithFormat:@"&%@=%@",key,[dictionary objectForKey:key]]]; 31 | } 32 | } 33 | return str; 34 | } 35 | @end 36 | -------------------------------------------------------------------------------- /Bsphp/bsphp/NSString+MD5.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+MD5.h 3 | // 4 | // Created by Keith Smiley on 3/25/13. 5 | // Copyright (c) 2013 Keith Smiley. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | 11 | #ifdef NS_ASSUME_NONNULL_BEGIN 12 | NS_ASSUME_NONNULL_BEGIN 13 | #endif 14 | 15 | @interface NSString (MD5) 16 | 17 | - (NSString *)__attribute__((optnone))MD5Digest; 18 | - (NSString *)__attribute__((optnone))stringByReversed; 19 | 20 | @end 21 | 22 | #ifdef NS_ASSUME_NONNULL_END 23 | NS_ASSUME_NONNULL_END 24 | #endif 25 | -------------------------------------------------------------------------------- /Bsphp/bsphp/NSString+MD5.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+MD5.m 3 | // 4 | // Created by Keith Smiley on 3/25/13. 5 | // Copyright (c) 2013 Keith Smiley. All rights reserved. 6 | // 7 | 8 | #import 9 | #import "NSString+MD5.h" 10 | 11 | @implementation NSString (MD5) 12 | 13 | - (NSString *)__attribute__((optnone))MD5Digest 14 | { 15 | const char* input = [self UTF8String]; 16 | unsigned char result[CC_MD5_DIGEST_LENGTH]; 17 | CC_MD5(input, (CC_LONG)strlen(input), result); 18 | 19 | NSMutableString *digest = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2]; 20 | for (NSInteger i = 0; i < CC_MD5_DIGEST_LENGTH; i++) { 21 | [digest appendFormat:@"%02X", result[i]]; 22 | } 23 | 24 | return digest; 25 | } 26 | 27 | - (NSString *)__attribute__((optnone))stringByReversed 28 | { 29 | NSMutableString *s = [NSMutableString string]; 30 | for (NSUInteger i=self.length; i>0; i--) { 31 | [s appendString:[self substringWithRange:NSMakeRange(i-1, 1)]]; 32 | } 33 | return s; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Bsphp/bsphp/NSString+Tools.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Tools.h 3 | // XFSettings 4 | // 5 | // Created by apple on 14-8-21. 6 | // Copyright (c) 2014年 itcast. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | @interface NSString (Tools) 14 | 15 | /** 16 | * 获取单行文本的size 17 | * 18 | * @param fontSize fontSize 19 | * 20 | * @return textSize 21 | */ 22 | - (CGSize)__attribute__((optnone))sizeOfFontSize:(CGFloat)fontSize; 23 | /** 24 | * 获得多行文本的size 25 | * 26 | * @param fontSize fontSize 27 | * @param maxWidth maxWidth 28 | * 29 | * @return textSize 30 | */ 31 | - (CGSize)__attribute__((optnone))sizeOfFontSize:(CGFloat)fontSize maxWidth:(CGFloat)maxWidth; 32 | /** 33 | * 返回文件或目录的大小byte单位 34 | * 35 | * @return fileSize 如果路径不存在返回0 36 | */ 37 | - (NSInteger)__attribute__((optnone))fileSize; 38 | 39 | + (CGSize)__attribute__((optnone))sizeWithString:(NSString*)str andFont:(UIFont*)font andMaxSize:(CGSize)size; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Bsphp/bsphp/NSString+Tools.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Tools.m 3 | // XFSettings 4 | // 5 | // Created by apple on 14-8-21. 6 | // Copyright (c) 2014年 itcast. All rights reserved. 7 | // 8 | 9 | #import "NSString+Tools.h" 10 | 11 | @implementation NSString (Tools) 12 | 13 | //用对象的方法计算文本的大小 14 | - (CGSize)__attribute__((optnone))sizeWithFont:(UIFont*)font andMaxSize:(CGSize)size { 15 | //特殊的格式要求都写在属性字典中 16 | NSDictionary*attrs =@{NSFontAttributeName: font}; 17 | //返回一个矩形,大小等于文本绘制完占据的宽和高。 18 | return [self boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size; 19 | } 20 | 21 | + (CGSize)__attribute__((optnone))sizeWithString:(NSString*)str andFont:(UIFont*)font andMaxSize:(CGSize)size{ 22 | NSDictionary*attrs =@{NSFontAttributeName: font}; 23 | return [str boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size; 24 | } 25 | 26 | 27 | - (CGSize)__attribute__((optnone))sizeOfFontSize:(CGFloat)fontSize 28 | { 29 | return [self sizeOfFontSize:fontSize maxWidth:MAXFLOAT]; 30 | } 31 | - (CGSize)__attribute__((optnone))sizeOfFontSize:(CGFloat)fontSize maxWidth:(CGFloat)maxWidth 32 | { 33 | 34 | return [self boundingRectWithSize:CGSizeMake(maxWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{ 35 | NSFontAttributeName : [UIFont systemFontOfSize:fontSize] 36 | } context:nil].size; 37 | 38 | } 39 | 40 | 41 | - (NSInteger)__attribute__((optnone))fileSize 42 | { 43 | NSFileManager *mgr = [NSFileManager defaultManager]; 44 | // 判断是否为文件 45 | BOOL dir = NO; 46 | BOOL exists = [mgr fileExistsAtPath:self isDirectory:&dir]; 47 | // 文件\文件夹不存在 48 | if (exists == NO) return 0; 49 | 50 | if (dir) { // self是一个文件夹 51 | // 这个方法只会遍历直接内容(一级深度内容) 52 | // [mgr contentsOfDirectoryAtPath:self error:nil]; 53 | // 遍历caches里面的所有内容 --- 直接和间接内容 54 | NSArray *subpaths = [mgr subpathsAtPath:self]; 55 | NSInteger totalByteSize = 0; 56 | for (NSString *subpath in subpaths) { 57 | // 获得全路径 58 | NSString *fullSubpath = [self stringByAppendingPathComponent:subpath]; 59 | // 判断是否为文件 60 | BOOL dir = NO; 61 | [mgr fileExistsAtPath:fullSubpath isDirectory:&dir]; 62 | if (dir == NO) { // 文件 63 | totalByteSize += [[mgr attributesOfItemAtPath:fullSubpath error:nil][NSFileSize] integerValue]; 64 | } 65 | } 66 | return totalByteSize; 67 | } else { // self是一个文件 68 | return [[mgr attributesOfItemAtPath:self error:nil][NSFileSize] integerValue]; 69 | } 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /Bsphp/bsphp/NSString+URLCode.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+URLCode.h 3 | // LOL 4 | // 5 | // Created by 刘清 on 16/3/10. 6 | // Copyright (c) 2016年 LQ. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (URLCode) 12 | //编码 string code -> url code 13 | - (NSString *)__attribute__((optnone))URLEncodedString; 14 | //解码 url code -> string code 15 | - (NSString *)__attribute__((optnone))URLDecodedString; 16 | 17 | /** 18 | md5加密 19 | 20 | @param input 输入要加密的 21 | @return 输出加密后 22 | */ 23 | - (NSString *)__attribute__((optnone)) md5:(NSString *) input; 24 | @end 25 | -------------------------------------------------------------------------------- /Bsphp/bsphp/NSString+URLCode.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+URLCode.m 3 | // LOL 4 | // 5 | // Created by 刘清 on 16/3/10. 6 | // Copyright (c) 2016年 LQ. All rights reserved. 7 | // 8 | 9 | #import "NSString+URLCode.h" 10 | #import 11 | @implementation NSString (URLCode) 12 | 13 | - (NSString *)__attribute__((optnone))URLEncodedString 14 | { 15 | /* 16 | CFURLCreateStringByAddingPercentEscapes函数是Core Foundation框架提供的C函数,可以把内容转换成URL【资源定位符】编码, 17 | 18 | */ 19 | 20 | // NSString *result = ( NSString *) 21 | // CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, 22 | // (CFStringRef)self, 23 | // NULL,//指定了将本身为非法的URL字符不进行编码的字符集合 24 | // CFSTR("!*();+$,%#[] "),//将本身为合法的URL字符需要进行编码的字符集合 25 | // kCFStringEncodingUTF8)); 26 | NSCharacterSet *allowedCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@"!*();+$,%#[] "]; 27 | NSString *result = [self stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; 28 | return result; 29 | } 30 | 31 | - (NSString*) __attribute__((optnone))URLDecodedString 32 | { 33 | // CFURLCreateStringByReplacingPercentEscapesUsingEncoding与CFURLCreateStringByAddingPercentEscapes相反,是进行URL解码 34 | // Foundation框架 35 | // NSString*ss; 36 | // [ss stringByReplacingPercentEscapesUsingEncoding:(NSStringEncoding)] 37 | 38 | // CoreFoundation框架 39 | // CFURLCreateStringByReplacingPercentEscapesUsingEncoding 40 | 41 | // NSString *result = ( NSString *) 42 | // CFBridgingRelease(CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, 43 | // (CFStringRef)self, 44 | // CFSTR(""),//指定不进行解码的字符集 45 | // kCFStringEncodingUTF8)); 46 | NSString *result = [self stringByRemovingPercentEncoding]; 47 | return result; 48 | } 49 | //md5 50 | - (NSString *)__attribute__((optnone)) md5:(NSString *) input { 51 | const char *cStr = [input UTF8String]; 52 | unsigned char digest[CC_MD5_DIGEST_LENGTH]; 53 | CC_MD5( cStr, (CC_LONG)strlen(cStr), digest ); // This is the md5 call 54 | 55 | NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2]; 56 | 57 | for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) 58 | [output appendFormat:@"%02x", digest[i]]; 59 | 60 | return output; 61 | } 62 | @end 63 | -------------------------------------------------------------------------------- /Bsphp/bsphp/NetWorkingApiClient.h: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // NetWorkingApiClient.h 4 | // BSPHPOC 5 | // 6 | // Created by MRW on 2016/12/14. 7 | // Copyright © 2016年 xiaozhou. All rights reserved. 8 | // 9 | 10 | #import "AFNetworking.h" 11 | 12 | @interface NetWorkingApiClient : AFHTTPSessionManager 13 | + (NetWorkingApiClient *)sharedNetWorkingApiClient; 14 | @end 15 | -------------------------------------------------------------------------------- /Bsphp/bsphp/NetWorkingApiClient.m: -------------------------------------------------------------------------------- 1 | // 2 | // NetWorkingApiClient.m 3 | // BSPHPOC 4 | // 5 | // Created by MRW on 2016/12/14. 6 | // Copyright © 2016年 xiaozhou. All rights reserved. 7 | // 8 | 9 | #import "NetWorkingApiClient.h" 10 | static NetWorkingApiClient *netWorkingClient = nil; 11 | @implementation NetWorkingApiClient 12 | + (NetWorkingApiClient *)__attribute__((optnone))sharedNetWorkingApiClient{ 13 | static dispatch_once_t onceToken; 14 | dispatch_once(&onceToken, ^{ 15 | netWorkingClient = [[NetWorkingApiClient alloc] initWithBaseURL:[NSURL URLWithString:@""]]; 16 | netWorkingClient.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone]; 17 | //设置返回原生状态数据:返回NSData类型 18 | netWorkingClient.responseSerializer = [AFHTTPResponseSerializer serializer]; 19 | //返回的数据是解析完的json数据 20 | //netWorkingClient.responseSerializer = [AFJSONResponseSerializer serializer]; 21 | //返回的数据是解析完的XML数据 22 | //netWorkingClient.responseSerializer = [AFXMLParserResponseSerializer serializer]; 23 | 24 | }); 25 | return netWorkingClient; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Bsphp/bsphp/getKeychain.h: -------------------------------------------------------------------------------- 1 | // 2 | // GIKeychain.h 3 | // BSPHPOC 4 | // BSPHP 魔改UDID 技术团队 十三哥工作室 5 | // 承接软件APP开发 UDID定制 验证加密二改 PHP JS HTML5开发 辅助开发 6 | // WX:NongShiFu123 QQ350722326 7 | // Created by MRW on 2022/11/14. 8 | // GitHub:http://github.com/nongshifu/ 9 | // 开源Q群: 398423911 10 | // Copyright © 2019年 xiaozhou. All rights reserved. 11 | // 12 | 13 | #import 14 | 15 | #define accessGroupItem @"XXXXX.GrassInfoAppFamily" 16 | 17 | @interface getKeychain : NSObject 18 | 19 | + (id)getKeychainDataForKey:(NSString *)key; 20 | + (void)addKeychainData:(id)data forKey:(NSString *)key; 21 | + (void)removeKeychainDataForKey:(NSString *)key; 22 | + (void)addShareKeyChainData:(id)data forKey:(NSString *)key; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Bsphp/bsphp/getKeychain.m: -------------------------------------------------------------------------------- 1 | // 2 | // GIKeychain.m 3 | // BSPHPOC 4 | // BSPHP 魔改UDID 技术团队 十三哥工作室 5 | // 承接软件APP开发 UDID定制 验证加密二改 PHP JS HTML5开发 辅助开发 6 | // WX:NongShiFu123 QQ350722326 7 | // Created by MRW on 2022/11/14. 8 | // GitHub:http://github.com/nongshifu/ 9 | // 开源Q群: 398423911 10 | // Copyright © 2019年 xiaozhou. All rights reserved. 11 | // 12 | 13 | #import "getKeychain.h" 14 | 15 | @implementation getKeychain 16 | 17 | //创建一个基本的查询字典 18 | + (NSMutableDictionary *)getKeychainQuery:(NSString *)service { 19 | return [NSMutableDictionary dictionaryWithObjectsAndKeys: 20 | (__bridge id)kSecClassGenericPassword,(__bridge id)kSecClass, 21 | service, (__bridge id)kSecAttrService, 22 | service, (__bridge id)kSecAttrAccount, 23 | (__bridge id)kSecAttrAccessibleAfterFirstUnlock,(__bridge id)kSecAttrAccessible, 24 | nil]; 25 | } 26 | 27 | + (id)getKeychainDataForKey:(NSString *)key{ 28 | id ret = nil; 29 | NSMutableDictionary *keychainQuery = [self getKeychainQuery:key]; 30 | //Configure the search setting 31 | //Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue 32 | [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData]; 33 | [keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; 34 | CFDataRef keyData = NULL; 35 | if (SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) { 36 | @try { 37 | NSError *error = nil; 38 | ret = [NSKeyedUnarchiver unarchivedObjectOfClass:[getKeychain class] fromData:(__bridge NSData *)keyData error:&error]; 39 | 40 | } @catch (NSException *e) { 41 | NSLog(@"Unarchive of %@ failed: %@",key,e); 42 | } @finally { 43 | } 44 | } 45 | if (keyData) 46 | CFRelease(keyData); 47 | return ret; 48 | } 49 | 50 | + (void)addKeychainData:(id)data forKey:(NSString *)key{ 51 | //Get search dictionary 52 | NSMutableDictionary *keychainQuery = [self getKeychainQuery:key]; 53 | //Delete old item before add new item 54 | SecItemDelete((__bridge CFDictionaryRef)keychainQuery); 55 | //Add new object to search dictionary(Attention:the data format) 56 | NSError*error; 57 | [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data requiringSecureCoding:YES error:&error] forKey:(__bridge id)kSecValueData]; 58 | //Add item to keychain with the search dictionary 59 | SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL); 60 | } 61 | 62 | +(void)addShareKeyChainData:(id)data forKey:(NSString *)key{ 63 | //获取搜索词典 64 | NSMutableDictionary *keychainQuery = [self getKeychainQuery:key]; 65 | [keychainQuery setObject:accessGroupItem forKey:(id)kSecAttrAccessGroup]; 66 | //在添加新项目之前删除旧项目 67 | SecItemDelete((__bridge CFDictionaryRef)keychainQuery); 68 | NSError*error; 69 | [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data requiringSecureCoding:YES error:&error] forKey:(__bridge id)kSecValueData]; 70 | //使用搜索词典将项目添加到钥匙串 71 | SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL); 72 | 73 | } 74 | 75 | + (void)removeKeychainDataForKey:(NSString *)key{ 76 | NSMutableDictionary *keychainQuery = [self getKeychainQuery:key]; 77 | SecItemDelete((__bridge CFDictionaryRef)keychainQuery); 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /Config.h: -------------------------------------------------------------------------------- 1 | // BSPHPOC 2 | // BSPHP 魔改UDID 技术团队 十三哥工作室 3 | // 承接软件APP开发 UDID定制 验证加密二改 PHP JS HTML5开发 辅助开发 4 | // WX:NongShiFu123 QQ350722326 5 | // Created by MRW on 2022/11/14. 6 | // GitHub:http://github.com/nongshifu/ 7 | // 开源Q群: 398423911 8 | // Copyright © 2019年 xiaozhou. All rights reserved. 9 | // 10 | #import 11 | 12 | #import 13 | 14 | //服务器地址 15 | #define BSPHP_HOST @"http://39.100.249.84/AppEn.php?appid=22334459&m=6178973ec8133d21a0156c650cb114a5" 16 | //通信认证Key 17 | #define BSPHP_MUTUALKEY @"eeed1eb17dd960153b23ddeaad5c768d" 18 | //接收Sgin验证 注意必须填写 并且有[KEY] 19 | #define BSPHP_INSGIN @"[KEY]HDJFHDJQHDY" 20 | //输出Sgin验证 注意必须填写 并且有[KEY] 21 | #define BSPHP_TOSGIN @"[KEY]HDJFHDJQHDY" 22 | //数据加密密码 23 | #define BSPHP_PASSWORD @"3XIytAFfgR2qt5ne36" 24 | 25 | //版本 和软件配置版本号一致 发布新版的时候 修改软件配置的版本号并且在URL那填写下载地址即可 客户端会弹出更新 确定会跳转浏览器下载 26 | #define JN_VERSION @"v1.0" 27 | 28 | //加密秘钥 这个在服务器文件后台 网站目录/include/applibapi/encryption下的bsphp_3des_vi.php 里面保持一致 搜索bsphp666就有3处地方都改掉 和这里源码一致 BS安装默认为bsphp666 29 | //**注意 仅限8位数 30 | #define gIv @"bsphp666" 31 | 32 | //定期验证 单位为秒 可以设置10分钟 几分钟看个人需求 用于动态检测版本更新 公告更新 检测是否到期 检测是否冻结 时间太短 用户多会增加服务器压力 33 | #define BS_DSQ 600 34 | 35 | //如果使用udid获取描述文件 需要udid.php上传到域名指定目录 36 | #define UDID_HOST @"https://udid.zzmy001.com/udid/" 37 | 38 | //启动APP后多少秒开始验证 单位秒 ** 因为很多游戏有启动画面 启动动画 会刷新UI 刷掉弹窗 相当于没了验证 比如光遇 王者荣耀 等 要等启动动画结束才弹窗 自己测试时间 39 | #define BS延迟启动时间 0 40 | 41 | 42 | 43 | #define MyLog(fmt, ...) \ 44 | if (MY_NSLog_ENABLED) { \ 45 | NSLog((@"MyLog: " fmt), ##__VA_ARGS__); \ 46 | } 47 | //是否打印 48 | #define MY_NSLog_ENABLED YES 49 | 50 | /*以下参数 填写在BSPHP后台对应的软件设置-软件描述处 每个功能一个换行 切记 参数为BOOL 值 YES 或NO 大写 顺序不能错源码写死了 复制粘贴即可 具体看 参数填写说明 图 51 | 到期时间弹窗:YES 52 | 验证udid还是idfv:YES 53 | 验证版本更新:YES 54 | 过直播:NO 55 | 系统弹窗/SCL弹窗:NO 56 | 是否每次弹公告:YES 57 | 试用模式:YES 58 | 支持解绑:YES 59 | 60 | 61 | */ 62 | 63 | /*BS参数说明-详情可以看图片 说明.png 64 | 到期时间弹窗:YES 65 | 解释=设置YES每次启动都提示到期时间,设置NO 仅首次激活有提示 到期会有提示 正常使用期间不会提示 66 | 67 | 验证udid还是idfv:YES 68 | 解释=设置YES获取描述文件获取UDID ,NO 获取IDFV无需描述文件,IDFV弊端同设备不同app获取机器码码不同,刷机 升级 还原 会变,想同设备多个app通用卡密的建议UDID 69 | 70 | 验证版本更新:YES 71 | 解释=设YES验证BS软件配置里面的版本号和上面JN_VERSION处是否一致 不一致就弹出URL 去浏览器下载同时app闪退 强制更新 弹出的URL更新地址在软件配置-URL地址 处 ,设置NO不验证 72 | 73 | 过直播:YES 74 | 解释=设置YES 弹窗就可以过直播 版本弹窗 时间到期弹窗 公告弹窗等 都能过录屏和截图 直播 ***果直播仅限SCL弹窗 系统弹窗不支持果直播 既(系统弹窗/SCL弹窗:NO)才支持 75 | 76 | 系统弹窗/SCL弹窗:YES 77 | 解释=YES使用系统弹窗(不支持过截屏直播不隐藏) ,NO 使用SCL 弹窗支持果直播 防止录屏 78 | 79 | 是否每次弹公告:YES 80 | 解释=YES 每次启动app 都会弹窗公告 NO 不弹公告 除非 公告发生在线更新变化 如BS后台修改功能 客户端那边会在线提示公告变化 定时检测提示的时间由BS_DSQ 控制 81 | 82 | 83 | 试用模式:YES 84 | 解释=如开启 试用模式开启 新设备无需卡密直接试用 赠送时间在BS 软件配置-首次使用送 85 | 86 | 支持解绑:YES 87 | 解释=如开启 新设备会检测机器码和首次激活绑定机器码判断 不一致就弹出解绑 扣除时间设置 在BS-软件配置-解绑定扣 88 | ** 注意 如果开启 那么 软件-限开控制-多开机器量 将失效 等同关闭。 账号多开设功能不影响 89 | 90 | 更新日志====== 91 | 2023.03.21 增加了拉黑功能 删除shiyong.php 试用功能集合到udid.php 并且自动识别目录 udid.php可上传任意目录 92 | ******注意 黑名单功能 需要BS后台-软件列表-用户分组-新建一个黑名单分组 93 | ***拉黑用户说明:复制卡密-或者机器码 BS后台-软件列表-用户-搜索卡密/机器码-编辑 分组移动到黑名单分组 **并且填写一个备注 比如:你已经被拉黑-别玩了,用户那边提示你备注的信息 94 | *** 特别注意 备注 必须有一个 中文的"黑"字 用来判断是否是黑名单 正常用户备注 请勿出现关键字"黑" 否则被拉黑 并且用户那边提示你备注的信息 95 | 96 | 2023.03.17 更新支持解绑 97 | 2023.03.15 试用功能集合至软件描述处 优化跨进程注入桌面安全模式问题 arm64e 98 | 2023.03.11 添加了试用功能 如开启 BOOL 试用模式:YES 并且shiyong.php上传至服务器站点目录下 可以是二级目录 具体打开shiyong.php看注释说明, 99 | 试用开启 新设备获取机器码查询服务器记录 没就按BS软件配置-基础设置-首次使用送 处 赠送时间 卡密随机生成 100 | ******注意 试用功能按机器码查询的 建议只在UDID模式下 试用 IDFA IDFV模式下刷机 升级 多开APP会变串码 存在变相无限试用风险 101 | 102 | 2023.03.09 全面弃用IDFA 支持多开控制 设备数量控制 在BS后台-软件配置-账号多开设 和 多开机器量设置 具体看使用说明的注意事项 103 | 104 | 2023.03.05 优化公告弹窗逻辑 增加了购买卡密识别 BS后台-软件网页地址处 留空则不会提示购买按钮 105 | 2023.03.02 吧卡密和UDID钥匙串储存 从新安装app或者多开直接读取无需重复输入卡密 106 | 2023.02.28 合并了两种UI弹窗 BS-软件描述-系统弹窗/SCL弹窗 处 YES=系统UI NO SCL弹窗 107 | 2023.02.25 优化了UDID获取页面逻辑 签名直接保存SSL证书key为key.key PEM证书储存为pem.pem 放在udid.php同级目录即可 108 | 109 | 110 | 使用说明=============== 111 | 1.将udid.php上传至服务器站点二级目录下 如站点 143.542.5.76 根目录的UDID目录下 112 | 2.修改以上 #define UDID_HOST 处为第一步骤的 站点ip或者域名+目录 如上步骤则 http://143.542.5.76/UDID/ 注意二级目录大小写 113 | 3.编辑udid.php 里面的 $签名 处 和 $域名 处 即可 $域名 和上步骤一致 $签名=1表示 描述文件签名 2不签名 签名需要 到站点对应的php软件-设置-禁用函数-删除 shell_exec()函数 114 | 4.将1.mobileprovision 上传至udid.php同级目录 1.mobileprovision必须是未掉签的企业证书描述文件 可以随便找个没掉签的企业证书描述文件 115 | 个人证书的不行 如果掉签的 下载描述文件后就不能跳转自动iOS设置 需要手动打开 iOS设置 116 | 117 | **多开设置**注意 账号多开数量为全部设备在线APP总和 118 | 举例 情况1 :多开机器量设置为2 账号多开设2 那么同一个卡密在设备A登录 然后在设备B登录 也可以使用 但是1个设备只能1个App AB任意设备打开第三个 第一个App就退出 总之两个设备打开的APP不超过2 119 | 120 | 举例 情况2:多开机器量设置为2 账号多开设1 那么同一个卡密在设备A登录 然后在设备B登录 也可以使用 但是设备A会被迫下线 反之如果重启设备A 则B又被破下线 虽然多开机器设置为2 但是多开总量为1 121 | 举例 模式3:多开机器量设置为1或者-1(即关闭)默认只能1台设备 多开设置为5 那么设备A 上同一个卡密 最多可以激活码5个App 启动第六个激活 那么第一个被迫退出 , 换另一个设备B 同一个卡密登录 A设备所有APP退出 122 | 123 | *** 推荐 大多情况下 验证系统目的是为了绑定设备 因此多开机器量设置为-1 关闭 然后软件 设置-是否绑定模式:验证绑定特征 这样防止卡密倒卖 在A设备激活绑定后 无法在设备B激活 124 | *** 因为如果 设置-是否绑定模式:免验证绑定特征 那么即使多开设为1 多开设备也为1 但是可以错开时间使用 比如早上小学生A在A设备玩 下午B小学生在B设备玩 因为错开 不会被迫下线 125 | */ 126 | 127 | 128 | @interface NetTool : NSObject 129 | 130 | /** 131 | * AFN异步发送post请求,返回原生数据 132 | * 133 | * @param appendURL 追加URL 134 | * @param param 参数字典 135 | * @param success 成功Block 136 | * @param failure 失败Block 137 | * 138 | * @return NSURLSessionDataTask任务类型 139 | */ 140 | + (NSURLSessionDataTask *)__attribute__((optnone))Post_AppendURL:(NSString *)appendURL parameters:(NSDictionary *)param success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure; 141 | @end 142 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 功能介绍-参数说明 2 | ### 远程功能都在BS后台-软件配置-软件描述设置 3 | ### 支持远程开启关闭 到期时间弹窗 4 | 1.到期时间弹窗:YES 每次启动App都弹到期时间 5 | 2.到期时间弹窗:NO 仅首次激活/到期/冻结/更新 才弹到期时间 6 | ### 心跳定时验证 - 防止天卡不关app一直玩 7 | 1. 逻辑B 的真假作为心跳验证的开关,逻辑B的内容为纯数字 单位秒 作为心跳定时验证时间 -注意 这个时间务必 比软件设置-掀开设置-里面的心跳时间少 最好一半 8 | 2. 因为验证的时候生成唯一串码 这个串码会在 软件设置-掀开设置-里面的心跳时间 之后清除 app那边就被迫下线 因此心跳时间要少于软件后台心跳时间 重新验证会延迟时间 9 | 1.到期时间弹窗:YES 每次启动App都弹到期时间 10 | ### 支持IDFV UDID 两种模式绑定机器码 11 | 1. 验证udid还是idfv:YES YES为UDID 获取描述文件 更新/刷机/还原 机器码不变 12 | 2. 验证udid还是idfv:NO NO为idfv 更新/刷机/还原 机器码会变 不同app读取也不同 13 | ### 验证版本更新:YES 14 | 1. 验证版本更新:YES YES为验证发布版本的Config.h 里版本号和软件设置-版本号是否一致 15 | 2. 验证版本更新:NO NO不验证 16 | ### 是否免费模式:NO/YES 字面意思 YES的话就单纯弹个公告 免费用 17 | 1. 后台可以远程修改为NO 客户离线周期到或者心跳时间到会读取远程配置重新为需要卡密 18 | ### 是否强制版本更新:NO/YES 强制的话 软件设置-版本号 修改后 客户端会强制更新才能用 19 | ### 支持SCL弹窗过直播过录屏截图 20 | 过直播:YES YES/NO 开启防录屏截图直播 仅支持SCL弹窗 iOS弹窗不支持 21 | ### 支持远程开启关闭试用功能 -新用户自动注册生成卡密 22 | 试用模式:YES YES/NO开启关闭试用功能 如开启 新用户获取机器码后查询数据库是否存在机器码最为依据 不存在就自动生成卡密 赠送时间=BS后台-软件配置-首次使用送 单位秒 23 | ### 支持远程SCL弹窗和IOS弹窗 24 | 系统弹窗/SCL弹窗:YES YES为iOS系统默认弹窗 NO 为SCL弹窗https://github.com/nongshifu/SCLAlertView-develop 25 | ### 支持远程更新公告 26 | BS后台-修改公告-客户端会在心跳时间到就弹窗新公告- 心跳时间-Config.h #define BS_DSQ 处 27 | ### 支持远程版本管理 28 | 验证版本更新:YES 当BS后台软件配置-版本-修改版本号 客户端会弹出更新 并且跳转URL 如果无需跳转 bs-软件配置-URL地址: 留空 29 | ### 支持远程发卡网弹窗 30 | BS后台-软件配置-软件网页地址: 处 客户打开APP 在输入激活码界面会有购买按钮 跳转此处链接 如果不需要跳转 请留空 不显示购买按钮 31 | ### 支持远程锁定黑名单 32 | BS后台-软件配置-用户分组 新建一个 黑名单分组 ,拉黑操作 BS后台-软件列表-用户 搜索对方卡密/机器码 编辑 移动到黑名单分组 33 | 注意: 拉进黑名单分组 并未生效 必须同时在备注 那给客户留言 并且留言内容只是有个关键字"黑" 作为拉黑依据 比如:您已被拉黑 34 | ### 支持远程修改同卡密在线数量 35 | BS后台-软件配置-限开控制-账号多开设: 注意这个为所有设备的总和 假如一个卡密 两个设备 每个设备2个app 那么在线数量写4 比如写3 只能两个设备里面三个app同时在线 36 | ### 支持远程修改卡密多开机器量 37 | BS后台-软件配置-多开机器量: 机器码作为区分依据 比如设置1 设备A 激活了卡密 设备B也激活这个卡密 A上所有APP 将被迫下线不管同时在线写多少 只区分机器码 38 | ### 支持远程心态检测 被迫下线功能 39 | 源码Config.h 的#define BS_DSQ 处 单位秒 既每个用户多少秒查询一次 冻结/到期/在线/多开/被迫下线/公告/版本更新等 用户多会增加服务器压力 量力而行 如10分钟检测一次 40 | ### 支持用户自主解绑-扣除时间远程控制 41 | 支持解绑:YES YES/NO 开启和关闭 比如卡密abc 绑定了A设备 想换B设备 在B设备登录 会提示解绑按钮 扣除时间设置在 BS设置-软件配置-解绑定扣: 处 单位秒 42 | ### 支持离线验证 服务器被打 无法访问 也能本地验证 43 | 1. 逻辑A 的真假 为本地离线验证开关 逻辑A的内容为存数字 作为离线验证周期 单位是 6 比如60 就是60秒内重新打开不走网络验证 减少服务器压力 或者被打的时候能走本地验证 44 | ### 一个php文件 搞定UDID 试用 黑名单 解绑 45 | udid.php 上传至BS站点目录下 可以是二级目录 修改里面的$签名=1 $数据库表前缀="bsphp_" 46 | 1.$签名 =2不签名,=1签名 如设置1,描述文件进行签名 需要一个SSL证书 放在udid.php同级目录,证书key保存为key.key 证书公匙保存为pem.pem,并且修改php设置 47 | 如需签名宝塔为例-打开宝塔-软件商店-已安装 找到BS站点对应的php 设置-禁用函数 找到 shell_exec() 删除 48 | 49 | ### 完美兼容BSPHP最新版 开发定制联系:十三哥 WX:shisange2026 QQ:350722326 50 | 51 | # 使用教程 52 | ### 1.将以下配置写到BS-软件描述 53 | 54 | 到期时间弹窗:YES 55 | 验证udid还是idfa:YES 56 | 验证版本更新:YES 57 | SCL弹窗过直播:NO 58 | 系统UI弹窗/SCL弹窗:NO 59 | 公告弹窗:YES 60 | 试用模式:NO 61 | 支持解绑:YES 62 | 黑名单检测:YES 63 | 是否免费模式:NO 64 | 是否强制版本更新:NO 65 | 66 | ### 只能改大写的YES/NO 也不要多换行 源码写死了关键字和顺序 YES/NO 说明看上面 67 | ![详细说明2](https://github.com/user-attachments/assets/65ad1a6d-fb7c-4767-8053-c7039124bcdc) 68 | 69 | ![详细参数说明](https://github.com/user-attachments/assets/33c9e316-1247-4dbf-bdeb-2b912f318f60) 70 | ### 2.这里的接收和输出Sgin 必须大小的[KEY] 开头 不能留空 源码写死 71 | image 72 | 73 | ### 3.这里必须按这个配置 74 | image 75 | 76 | ### 4.udid.php 上传至BS站点目录下-可以是二级目录 并且修改php里面$签名=1或者2 和$数据库表前缀 77 | #### 签名=1 代表面描述文件签名,2不签名 如需签名 需要配置SSL证书 78 | image 79 | 80 | #### 将任意未到期的网站SSL证书 秘钥key保存到文本重命名为key.key 公匙pem保存文本重命名pem.pem 81 | image 82 | 83 | #### 将key.key pem.pem 放到udid.php同级目录 如果是二级目录 记得给777权限 84 | 重要 如果需要描述文件签名- BS站点对应的 PHP 禁用函数 删除shell_exec() 85 | image 86 | 87 | ### 5.BS输出输入加密秘钥修改 88 | 源码里面Config.h里#define gIv 处 bs新安装默认是bsphp666 **注意 仅限8位数 89 | image 90 | 91 | 建议修改掉 在BS 站点目录/include/applibapi/encryption/ 下的bsphp_3des_vi.php 里 92 | image 93 | 94 | 有3处 改成一样的 并且填写到Config.h 的#define gIv 处 建议修改 否则用bsphp666即可解析验证内容 等同于明文 95 | Ctrl+F 搜索bsphp666 即可3处都改成一样的 96 | image 97 | 98 | 99 | ### 6. OK 生效就是在Config.h 傻瓜式搬运BS配置了 100 | 101 | 102 | # 更新日志 103 | ##### 2025.02.14 重构验证逻辑 增加离线本地验证 104 | ##### 2023.03.21 删除shiyong.php 增加了拉黑功能,试用,解绑,功能集合到udid.php 并且自动识别目录 udid.php可上传任意目录 105 | 优化了UDID逻辑 并且获取后自动删除udid缓存 106 | ***注意*** 黑名单功能 需要BS后台-软件列表-用户分组-新建一个黑名单分组 107 | ***拉黑用户说明:复制卡密-或者机器码 BS后台-软件列表-用户-搜索卡密/机器码-编辑 分组移动到黑名单分组 **并且填写一个备注 比如:你已经被拉黑-别玩了,用户那边提示你备注的信息 108 | *** 特别注意 备注 必须有一个 中文的"黑"字 用来判断是否是黑名单 正常用户备注 请勿出现关键字"黑" 否则被拉黑 并且用户那边提示你备注的信息 109 | 110 | ##### 2023.03.15 试用功能集合至软件描述处 优化跨进程注入桌面安全模式问题 arm64e
111 | ##### 2023.03.11 添加了试用功能 如开启 BOOL 试用模式:YES 并且shiyong.php上传至服务器站点目录下 可以是二级目录 具体打开shiyong.php看注释说明,
112 | 试用开启 新设备获取机器码查询服务器记录 没就按BS软件配置-基础设置-首次使用送 处 赠送时间 卡密随机生成
113 | ***注意*** 试用功能按机器码查询的 建议只在UDID模式下 试用 IDFA IDFV模式下刷机 升级 多开APP会变串码 存在变相无限试用风险
114 | 115 | ##### 2023.03.09 全面弃用IDFA 支持多开控制 设备数量控制 在BS后台-软件配置-账号多开设 和 多开机器量设置 具体看使用说明的注意事项
116 | 117 | ##### 2023.03.05 优化公告弹窗逻辑 增加了购买卡密识别 BS后台-软件网页地址处 留空则不会提示购买按钮
118 | ##### 2023.03.02 吧卡密和UDID钥匙串储存 从新安装app或者多开直接读取无需重复输入卡密
119 | ##### 2023.02.28 合并了两种UI弹窗 BS-软件描述-系统弹窗/SCL弹窗 处 YES=系统UI NO SCL弹窗
120 | ##### 2023.02.25 优化了UDID获取页面逻辑 签名直接保存SSL证书key为key.key PEM证书储存为pem.pem 放在udid.php同级目录即可
121 | 122 | # 居于Bsphp官方源码 增加了UDID验证绑定 123 | -------------------------------------------------------------------------------- /SCLAlertView/SCLAlertViewResponder.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCLAlertViewResponder.h 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/26/14. 6 | // Copyright (c) 2014-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #if defined(__has_feature) && __has_feature(modules) 10 | @import Foundation; 11 | #else 12 | #import 13 | #endif 14 | #import "SCLAlertView.h" 15 | 16 | @interface SCLAlertViewResponder : NSObject 17 | 18 | /** TODO 19 | * 20 | * TODO 21 | */ 22 | - (instancetype)init:(SCLAlertView *)alertview; 23 | 24 | /** TODO 25 | * 26 | * TODO 27 | */ 28 | - (void)close; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /SCLAlertView/SCLAlertViewResponder.m: -------------------------------------------------------------------------------- 1 | // 2 | // SCLAlertViewResponder.m 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/26/14. 6 | // Copyright (c) 2014-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #import "SCLAlertViewResponder.h" 10 | 11 | @interface SCLAlertViewResponder () 12 | 13 | @property SCLAlertView *alertview; 14 | 15 | @end 16 | 17 | @implementation SCLAlertViewResponder 18 | 19 | // 20 | //// Allow alerts to be closed/renamed in a chainable manner 21 | //// Example: SCLAlertView().showSuccess(self, title: "Test", subTitle: "Value").close() 22 | 23 | // Initialisation and Title/Subtitle/Close functions 24 | - (instancetype)init:(SCLAlertView *)alertview 25 | { 26 | self.alertview = alertview; 27 | return self; 28 | } 29 | 30 | - (void)setTitletitle:(NSString *)title 31 | { 32 | self.alertview.labelTitle.text = title; 33 | } 34 | 35 | - (void)setSubTitle:(NSString *)subTitle 36 | { 37 | self.alertview.viewText.text = subTitle; 38 | } 39 | 40 | - (void)close 41 | { 42 | [self.alertview hideView]; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /SCLAlertView/SCLAlertViewStyleKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCLAlertViewStyleKit.h 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/26/14. 6 | // Copyright (c) 2014-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #if defined(__has_feature) && __has_feature(modules) 10 | @import Foundation; 11 | @import UIKit; 12 | #else 13 | #import 14 | #import 15 | #endif 16 | #import "SCLButton.h" 17 | 18 | @interface SCLAlertViewStyleKit : NSObject 19 | 20 | // Images 21 | /** TODO 22 | * 23 | * TODO 24 | */ 25 | + (UIImage *)imageOfCheckmark; 26 | 27 | /** TODO 28 | * 29 | * TODO 30 | */ 31 | + (UIImage *)imageOfCross; 32 | 33 | /** TODO 34 | * 35 | * TODO 36 | */ 37 | + (UIImage *)imageOfNotice; 38 | 39 | /** TODO 40 | * 41 | * TODO 42 | */ 43 | + (UIImage *)imageOfWarning; 44 | 45 | /** TODO 46 | * 47 | * TODO 48 | */ 49 | + (UIImage *)imageOfInfo; 50 | 51 | /** TODO 52 | * 53 | * TODO 54 | */ 55 | + (UIImage *)imageOfEdit; 56 | 57 | /** TODO 58 | * 59 | * TODO 60 | */ 61 | + (UIImage *)imageOfQuestion; 62 | 63 | /** TODO 64 | * 65 | * TODO 66 | */ 67 | + (void)drawCheckmark; 68 | 69 | /** TODO 70 | * 71 | * TODO 72 | */ 73 | + (void)drawCross; 74 | 75 | /** TODO 76 | * 77 | * TODO 78 | */ 79 | + (void)drawNotice; 80 | 81 | /** TODO 82 | * 83 | * TODO 84 | */ 85 | + (void)drawWarning; 86 | 87 | /** TODO 88 | * 89 | * TODO 90 | */ 91 | + (void)drawInfo; 92 | 93 | /** TODO 94 | * 95 | * TODO 96 | */ 97 | + (void)drawEdit; 98 | 99 | /** TODO 100 | * 101 | * TODO 102 | */ 103 | + (void)drawQuestion; 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /SCLAlertView/SCLButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCLButton.h 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/26/14. 6 | // Copyright (c) 2014-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #if defined(__has_feature) && __has_feature(modules) 10 | @import UIKit; 11 | #else 12 | #import 13 | #endif 14 | 15 | @class SCLTimerDisplay; 16 | 17 | @interface SCLButton : UIButton 18 | 19 | typedef void (^SCLActionBlock)(void); 20 | typedef BOOL (^SCLValidationBlock)(void); 21 | typedef NSDictionary* (^CompleteButtonFormatBlock)(void); 22 | typedef NSDictionary* (^ButtonFormatBlock)(void); 23 | 24 | // Action Types 25 | typedef NS_ENUM(NSInteger, SCLActionType) 26 | { 27 | SCLNone, 28 | SCLSelector, 29 | SCLBlock 30 | }; 31 | 32 | /** Set button action type. 33 | * 34 | * Holds the button action type. 35 | */ 36 | @property SCLActionType actionType; 37 | 38 | /** Set action button block. 39 | * 40 | * TODO 41 | */ 42 | @property (copy, nonatomic) SCLActionBlock actionBlock; 43 | 44 | /** Set Validation button block. 45 | * 46 | * Set one kind of validation and keeps the alert visible until the validation is successful 47 | */ 48 | @property (copy, nonatomic) SCLValidationBlock validationBlock; 49 | 50 | /** Set Complete button format block. 51 | * 52 | * Holds the complete button format block. 53 | * Support keys : backgroundColor, borderWidth, borderColor, textColor 54 | */ 55 | @property (copy, nonatomic) CompleteButtonFormatBlock completeButtonFormatBlock; 56 | 57 | /** Set button format block. 58 | * 59 | * Holds the button format block. 60 | * Support keys : backgroundColor, borderWidth, borderColor, textColor 61 | */ 62 | @property (copy, nonatomic) ButtonFormatBlock buttonFormatBlock; 63 | 64 | /** Set SCLButton color. 65 | * 66 | * Set SCLButton color. 67 | */ 68 | @property (strong, nonatomic) UIColor *defaultBackgroundColor UI_APPEARANCE_SELECTOR; 69 | 70 | /** Set Target object. 71 | * 72 | * Target is an object that holds the information necessary to send a message to another object when an event occurs. 73 | */ 74 | @property id target; 75 | 76 | /** Set selector id. 77 | * 78 | * A selector is the name used to select a method to execute for an object, 79 | * or the unique identifier that replaces the name when the source code is compiled. 80 | */ 81 | @property SEL selector; 82 | 83 | /** Parse button configuration 84 | * 85 | * Parse ButtonFormatBlock and CompleteButtonFormatBlock setting custom configuration. 86 | * Set keys : backgroundColor, borderWidth, borderColor, textColor 87 | */ 88 | - (void)parseConfig:(NSDictionary *)buttonConfig; 89 | 90 | /** Set button timer. 91 | * 92 | * Holds the button timer, if present. 93 | */ 94 | @property (strong, nonatomic) SCLTimerDisplay *timer; 95 | 96 | /** Init method 97 | * 98 | */ 99 | - (instancetype)initWithWindowWidth:(CGFloat)windowWidth; 100 | 101 | /** Adjust width of the button according to the width of the alert and 102 | * the number of buttons. Only used when buttons are horizontally aligned. 103 | * 104 | * @param windowWidth The width of the alert. 105 | * @param numberOfButtons The number of buttons in the alert. 106 | */ 107 | - (void)adjustWidthWithWindowWidth:(CGFloat)windowWidth numberOfButtons:(NSUInteger)numberOfButtons; 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /SCLAlertView/SCLButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // SCLButton.m 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/26/14. 6 | // Copyright (c) 2014-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #import "SCLButton.h" 10 | #import "SCLTimerDisplay.h" 11 | 12 | #define MARGIN_BUTTON 12.0f 13 | #define DEFAULT_WINDOW_WIDTH 240 14 | #define MIN_HEIGHT 35.0f 15 | 16 | @implementation SCLButton 17 | 18 | - (instancetype)init 19 | { 20 | self = [super init]; 21 | if (self) 22 | { 23 | [self setupWithWindowWidth:DEFAULT_WINDOW_WIDTH]; 24 | } 25 | return self; 26 | } 27 | 28 | - (instancetype)initWithWindowWidth:(CGFloat)windowWidth 29 | { 30 | self = [super init]; 31 | if (self) 32 | { 33 | [self setupWithWindowWidth:windowWidth]; 34 | } 35 | return self; 36 | } 37 | 38 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 39 | { 40 | self = [super initWithCoder:aDecoder]; 41 | if(self) 42 | { 43 | [self setupWithWindowWidth:DEFAULT_WINDOW_WIDTH]; 44 | } 45 | return self; 46 | } 47 | 48 | - (instancetype)initWithFrame:(CGRect)frame 49 | { 50 | self = [super initWithFrame:frame]; 51 | if (self) 52 | { 53 | [self setupWithWindowWidth:DEFAULT_WINDOW_WIDTH]; 54 | } 55 | return self; 56 | } 57 | 58 | - (void)setupWithWindowWidth:(CGFloat)windowWidth 59 | { 60 | self.frame = CGRectMake(0.0f, 0.0f, windowWidth - (MARGIN_BUTTON * 2), MIN_HEIGHT); 61 | self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; 62 | self.titleLabel.textAlignment = NSTextAlignmentCenter; 63 | self.layer.cornerRadius = 3.0f; 64 | } 65 | 66 | - (void)adjustWidthWithWindowWidth:(CGFloat)windowWidth numberOfButtons:(NSUInteger)numberOfButtons 67 | { 68 | CGFloat allButtonsWidth = windowWidth - (MARGIN_BUTTON * 2); 69 | CGFloat buttonWidth = (allButtonsWidth - ((numberOfButtons - 1) * 10)) / numberOfButtons; 70 | 71 | self.frame = CGRectMake(0.0f, 0.0f, buttonWidth, MIN_HEIGHT); 72 | } 73 | 74 | - (void)setTitle:(NSString *)title forState:(UIControlState)state 75 | { 76 | [super setTitle:title forState:state]; 77 | self.titleLabel.numberOfLines = 0; 78 | 79 | // Update title frame. 80 | [self.titleLabel sizeToFit]; 81 | 82 | // Update button frame 83 | [self layoutIfNeeded]; 84 | 85 | // Get height needed to display title label completely 86 | CGFloat buttonHeight = MAX(self.titleLabel.frame.size.height, MIN_HEIGHT); 87 | 88 | // Update button frame 89 | self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, buttonHeight); 90 | } 91 | 92 | - (void)setHighlighted:(BOOL)highlighted 93 | { 94 | self.backgroundColor = (highlighted) ? [self darkerColorForColor:_defaultBackgroundColor] : _defaultBackgroundColor; 95 | [super setHighlighted:highlighted]; 96 | } 97 | 98 | - (void)setDefaultBackgroundColor:(UIColor *)defaultBackgroundColor 99 | { 100 | self.backgroundColor = _defaultBackgroundColor = defaultBackgroundColor; 101 | } 102 | 103 | - (void)setTimer:(SCLTimerDisplay *)timer 104 | { 105 | _timer = timer; 106 | [self addSubview:timer]; 107 | [timer updateFrame:self.frame.size]; 108 | timer.color = self.titleLabel.textColor; 109 | } 110 | 111 | #pragma mark - Button Apperance 112 | 113 | - (void)parseConfig:(NSDictionary *)buttonConfig 114 | { 115 | if (buttonConfig[@"backgroundColor"]) 116 | { 117 | self.defaultBackgroundColor = buttonConfig[@"backgroundColor"]; 118 | } 119 | if (buttonConfig[@"textColor"]) 120 | { 121 | [self setTitleColor:buttonConfig[@"textColor"] forState:UIControlStateNormal]; 122 | } 123 | if (buttonConfig[@"cornerRadius"]) 124 | { 125 | self.layer.cornerRadius = [buttonConfig[@"cornerRadius"] floatValue]; 126 | } 127 | if ((buttonConfig[@"borderColor"]) && (buttonConfig[@"borderWidth"])) 128 | { 129 | self.layer.borderColor = ((UIColor*)buttonConfig[@"borderColor"]).CGColor; 130 | self.layer.borderWidth = [buttonConfig[@"borderWidth"] floatValue]; 131 | } 132 | else if (buttonConfig[@"borderWidth"]) 133 | { 134 | self.layer.borderWidth = [buttonConfig[@"borderWidth"] floatValue]; 135 | } 136 | 137 | // Add Button custom font with buttonConfig parameters 138 | if (buttonConfig[@"font"]) { 139 | self.titleLabel.font = buttonConfig[@"font"]; 140 | } 141 | } 142 | 143 | #pragma mark - Helpers 144 | 145 | - (UIColor *)darkerColorForColor:(UIColor *)color 146 | { 147 | CGFloat r, g, b, a; 148 | if ([color getRed:&r green:&g blue:&b alpha:&a]) 149 | return [UIColor colorWithRed:MAX(r - 0.2f, 0.0f) 150 | green:MAX(g - 0.2f, 0.0f) 151 | blue:MAX(b - 0.2f, 0.0f) 152 | alpha:a]; 153 | return nil; 154 | } 155 | 156 | - (UIColor *)lighterColorForColor:(UIColor *)color 157 | { 158 | CGFloat r, g, b, a; 159 | if ([color getRed:&r green:&g blue:&b alpha:&a]) 160 | return [UIColor colorWithRed:MIN(r + 0.2f, 1.0f) 161 | green:MIN(g + 0.2f, 1.0f) 162 | blue:MIN(b + 0.2f, 1.0f) 163 | alpha:a]; 164 | return nil; 165 | } 166 | 167 | @end 168 | -------------------------------------------------------------------------------- /SCLAlertView/SCLMacros.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCLMacros.h 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 10/03/15. 6 | // Copyright (c) 2015-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #ifndef SCL_MACROS_H 10 | #define SCL_MACROS_H 11 | 12 | #define UIColorFromHEX(rgbValue) [UIColor \ 13 | colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \ 14 | green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \ 15 | blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0] 16 | 17 | #define DEGREES_TO_RADIANS(degrees) ((M_PI * degrees)/ 180) 18 | #define TIMER_STEP .01 19 | #define START_DEGREE_OFFSET -90 20 | 21 | #define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame) 22 | #define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending) 23 | #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) 24 | #define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) 25 | #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending) 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /SCLAlertView/SCLSwitchView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCLSwitchView.h 3 | // SCLAlertView 4 | // 5 | // Created by André Felipe Santos on 27/01/16. 6 | // Copyright (c) 2016-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #if defined(__has_feature) && __has_feature(modules) 10 | @import UIKit; 11 | #else 12 | #import 13 | #endif 14 | 15 | @interface SCLSwitchView : UIView 16 | 17 | @property (strong, nonatomic) UIColor *tintColor UI_APPEARANCE_SELECTOR; 18 | @property (strong, nonatomic) UIColor *labelColor UI_APPEARANCE_SELECTOR; 19 | @property (strong, nonatomic) UIFont *labelFont UI_APPEARANCE_SELECTOR; 20 | @property (strong, nonatomic) NSString *labelText UI_APPEARANCE_SELECTOR; 21 | @property (nonatomic, getter=isSelected) BOOL selected; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /SCLAlertView/SCLSwitchView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SCLSwitchView.m 3 | // SCLAlertView 4 | // 5 | // Created by André Felipe Santos on 27/01/16. 6 | // Copyright (c) 2016-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #import "SCLSwitchView.h" 10 | #import "SCLMacros.h" 11 | 12 | @interface SCLSwitchView () 13 | 14 | @property (strong, nonatomic) UISwitch *switchKnob; 15 | @property (strong, nonatomic) UILabel *switchLabel; 16 | 17 | @end 18 | 19 | #pragma mark 20 | 21 | @implementation SCLSwitchView 22 | 23 | #pragma mark - Constructors 24 | 25 | - (instancetype)init 26 | { 27 | self = [super init]; 28 | if (self) 29 | { 30 | [self setup]; 31 | } 32 | return self; 33 | } 34 | 35 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 36 | { 37 | self = [super initWithCoder:aDecoder]; 38 | if(self) 39 | { 40 | [self setup]; 41 | } 42 | return self; 43 | } 44 | 45 | - (instancetype)initWithFrame:(CGRect)frame 46 | { 47 | self = [super initWithFrame:frame]; 48 | if (self) 49 | { 50 | [self setup]; 51 | } 52 | return self; 53 | } 54 | 55 | #pragma mark - Initialization 56 | 57 | - (void)setup 58 | { 59 | // Add switch knob 60 | self.switchKnob = [[UISwitch alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, 0.f)]; 61 | [self addSubview:self.switchKnob]; 62 | 63 | // Add switch label 64 | CGFloat x, width, height; 65 | x = self.switchKnob.frame.size.width + 8.0f; 66 | width = self.frame.size.width - self.switchKnob.frame.size.width - 8.0f; 67 | height = self.switchKnob.frame.size.height; 68 | 69 | self.switchLabel = [[UILabel alloc] initWithFrame:CGRectMake(x, 0.0f, width-15, height)]; 70 | 71 | NSString *switchFontFamily = @"HelveticaNeue-Bold"; 72 | CGFloat switchFontSize = 15.0f; 73 | 74 | self.switchLabel.numberOfLines = 5; 75 | self.switchLabel.textAlignment = NSTextAlignmentRight; 76 | self.switchLabel.lineBreakMode = NSLineBreakByTruncatingTail; 77 | self.switchLabel.adjustsFontSizeToFitWidth = YES; 78 | self.switchLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; 79 | self.switchLabel.minimumScaleFactor = 0.5f; 80 | self.switchLabel.font = [UIFont fontWithName:switchFontFamily size:switchFontSize]; 81 | self.switchLabel.textColor = UIColorFromHEX(0x4D4D4D); 82 | 83 | [self addSubview:self.switchLabel]; 84 | } 85 | 86 | #pragma mark - Getters 87 | 88 | - (UIColor *)tintColor 89 | { 90 | return self.switchKnob.tintColor; 91 | } 92 | 93 | - (UIColor *)labelColor 94 | { 95 | return self.switchLabel.textColor; 96 | } 97 | 98 | - (UIFont *)labelFont 99 | { 100 | return self.switchLabel.font; 101 | } 102 | 103 | - (NSString *)labelText 104 | { 105 | return self.switchLabel.text; 106 | } 107 | 108 | - (BOOL)isSelected 109 | { 110 | return self.switchKnob.isOn; 111 | } 112 | 113 | #pragma mark - Setters 114 | 115 | - (void)setTintColor:(UIColor *)tintColor 116 | { 117 | self.switchKnob.onTintColor = tintColor; 118 | } 119 | 120 | - (void)setLabelColor:(UIColor *)labelColor 121 | { 122 | self.switchLabel.textColor = labelColor; 123 | } 124 | 125 | - (void)setLabelFont:(UIFont *)labelFont 126 | { 127 | self.switchLabel.font = labelFont; 128 | } 129 | 130 | - (void)setLabelText:(NSString *)labelText 131 | { 132 | self.switchLabel.text = labelText; 133 | } 134 | 135 | - (void)setSelected:(BOOL)selected 136 | { 137 | self.switchKnob.on = selected; 138 | } 139 | 140 | @end 141 | -------------------------------------------------------------------------------- /SCLAlertView/SCLTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCLTextView.h 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/18/15. 6 | // Copyright (c) 2015-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #if defined(__has_feature) && __has_feature(modules) 10 | @import UIKit; 11 | #else 12 | #import 13 | #endif 14 | 15 | @interface SCLTextView : UITextField 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /SCLAlertView/SCLTextView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SCLTextView.m 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/18/15. 6 | // Copyright (c) 2015-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #import "SCLTextView.h" 10 | 11 | #define MIN_HEIGHT 30.0f 12 | 13 | @implementation SCLTextView 14 | 15 | - (instancetype)init 16 | { 17 | self = [super init]; 18 | if (self) 19 | { 20 | [self setup]; 21 | } 22 | return self; 23 | } 24 | 25 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 26 | { 27 | self = [super initWithCoder:aDecoder]; 28 | if(self) 29 | { 30 | [self setup]; 31 | } 32 | return self; 33 | } 34 | 35 | - (instancetype)initWithFrame:(CGRect)frame 36 | { 37 | self = [super initWithFrame:frame]; 38 | if (self) 39 | { 40 | [self setup]; 41 | } 42 | return self; 43 | } 44 | 45 | - (void)setup 46 | { 47 | self.frame = CGRectMake(0.0f, 0.0f, 0.0f, MIN_HEIGHT); 48 | self.returnKeyType = UIReturnKeyDone; 49 | self.borderStyle = UITextBorderStyleRoundedRect; 50 | self.autocapitalizationType = UITextAutocapitalizationTypeSentences; 51 | self.clearButtonMode = UITextFieldViewModeWhileEditing; 52 | self.layer.masksToBounds = YES; 53 | self.layer.borderWidth = 1.0f; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /SCLAlertView/SCLTimerDisplay.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCLTimerDisplay.h 3 | // SCLAlertView 4 | // 5 | // Created by Taylor Ryan on 8/18/15. 6 | // Copyright (c) 2015-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | // Taken from https://stackoverflow.com/questions/11783439/uibutton-with-timer 9 | 10 | #if defined(__has_feature) && __has_feature(modules) 11 | @import UIKit; 12 | #else 13 | #import 14 | #endif 15 | #import "SCLButton.h" 16 | 17 | @interface SCLTimerDisplay : UIView { 18 | CGFloat currentAngle; 19 | CGFloat currentTime; 20 | CGFloat timerLimit; 21 | CGFloat radius; 22 | CGFloat lineWidth; 23 | NSTimer *timer; 24 | SCLActionBlock completedBlock; 25 | } 26 | 27 | @property CGFloat currentAngle; 28 | @property NSInteger buttonIndex; 29 | @property (strong, nonatomic) UIColor *color; 30 | @property (assign, nonatomic) BOOL reverse; 31 | 32 | - (instancetype)initWithOrigin:(CGPoint)origin radius:(CGFloat)r; 33 | - (instancetype)initWithOrigin:(CGPoint)origin radius:(CGFloat)r lineWidth:(CGFloat)width; 34 | - (void)updateFrame:(CGSize)size; 35 | - (void)cancelTimer; 36 | - (void)stopTimer; 37 | - (void)startTimerWithTimeLimit:(int)tl completed:(SCLActionBlock)completed; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /SCLAlertView/SCLTimerDisplay.m: -------------------------------------------------------------------------------- 1 | // 2 | // SCLTimerDisplay.m 3 | // SCLAlertView 4 | // 5 | // Created by Taylor Ryan on 8/18/15. 6 | // Copyright (c) 2015-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #import "SCLTimerDisplay.h" 10 | #import "SCLMacros.h" 11 | 12 | @interface SCLTimerDisplay () 13 | 14 | @property (strong, nonatomic) UILabel *countLabel; 15 | 16 | @end 17 | 18 | @implementation SCLTimerDisplay 19 | 20 | @synthesize currentAngle; 21 | 22 | - (instancetype)initWithFrame:(CGRect)frame 23 | { 24 | self = [super initWithFrame:frame]; 25 | if (self) 26 | { 27 | self.backgroundColor = [UIColor clearColor]; 28 | currentAngle = 0.0f; 29 | } 30 | return self; 31 | } 32 | 33 | - (instancetype)initWithOrigin:(CGPoint)origin radius:(CGFloat)r 34 | { 35 | return [self initWithOrigin:(CGPoint)origin radius:r lineWidth:5.0f]; 36 | } 37 | 38 | - (instancetype)initWithOrigin:(CGPoint)origin radius:(CGFloat)r lineWidth:(CGFloat)width 39 | { 40 | self = [super initWithFrame:CGRectMake(origin.x, origin.y, r*2, r*2)]; 41 | if (self) { 42 | self.backgroundColor = [UIColor clearColor]; 43 | currentAngle = START_DEGREE_OFFSET; 44 | radius = r-(width/2); 45 | lineWidth = width; 46 | self.color = [UIColor whiteColor]; 47 | self.userInteractionEnabled = NO; 48 | 49 | // Add count label 50 | _countLabel = [[UILabel alloc] init]; 51 | _countLabel.textColor = [UIColor whiteColor]; 52 | _countLabel.backgroundColor = [UIColor clearColor]; 53 | _countLabel.font = [UIFont fontWithName: @"HelveticaNeue-Bold" size:12.0f]; 54 | _countLabel.textAlignment = NSTextAlignmentCenter; 55 | _countLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; 56 | [self addSubview:_countLabel]; 57 | } 58 | return self; 59 | } 60 | 61 | - (void)updateFrame:(CGSize)size 62 | { 63 | CGFloat r = radius+(lineWidth/2); 64 | 65 | CGFloat originX = size.width - (2*r) - 5; 66 | CGFloat originY = (size.height - (2*r))/2; 67 | 68 | self.frame = CGRectMake(originX, originY, r*2, r*2); 69 | self.countLabel.frame = CGRectMake(0, 0, r*2, r*2); 70 | } 71 | 72 | - (void)drawRect:(CGRect)rect 73 | { 74 | UIBezierPath* aPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(radius+(lineWidth/2), radius+(lineWidth/2)) 75 | radius:radius 76 | startAngle:DEGREES_TO_RADIANS(START_DEGREE_OFFSET) 77 | endAngle:DEGREES_TO_RADIANS(currentAngle) 78 | clockwise:YES]; 79 | [self.color setStroke]; 80 | aPath.lineWidth = lineWidth; 81 | [aPath stroke]; 82 | 83 | _countLabel.text = [NSString stringWithFormat:@"%d", (int)currentTime]; 84 | } 85 | 86 | - (void)startTimerWithTimeLimit:(int)tl completed:(SCLActionBlock)completed 87 | { 88 | if (_reverse) 89 | { 90 | currentTime = tl; 91 | } 92 | timerLimit = tl; 93 | timer = [NSTimer scheduledTimerWithTimeInterval:TIMER_STEP target:self selector:@selector(updateTimerButton:) userInfo:nil repeats:YES]; 94 | completedBlock = completed; 95 | _countLabel.textColor = _color; 96 | } 97 | 98 | - (void)cancelTimer 99 | { 100 | [timer invalidate]; 101 | } 102 | 103 | - (void)stopTimer 104 | { 105 | [timer invalidate]; 106 | if (completedBlock != nil) { 107 | completedBlock(); 108 | } 109 | } 110 | 111 | - (void)updateTimerButton:(NSTimer *)timer 112 | { 113 | if (_reverse) 114 | { 115 | currentTime -= TIMER_STEP; 116 | currentAngle = (currentTime/timerLimit) * 360 + START_DEGREE_OFFSET; 117 | 118 | if(currentTime <= 0) { 119 | [self stopTimer]; 120 | } 121 | } 122 | else { 123 | currentTime += TIMER_STEP; 124 | currentAngle = (currentTime/timerLimit) * 360 + START_DEGREE_OFFSET; 125 | 126 | if(currentAngle >= (360 + START_DEGREE_OFFSET)) { 127 | [self stopTimer]; 128 | } 129 | } 130 | [self setNeedsDisplay]; 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /SCLAlertView/UIImage+ImageEffects.h: -------------------------------------------------------------------------------- 1 | /* 2 | File: UIImage+ImageEffects.h 3 | Abstract: This is a category of UIImage that adds methods to apply blur and tint effects to an image. This is the code you’ll want to look out to find out how to use vImage to efficiently calculate a blur. 4 | Version: 1.0 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2013 Apple Inc. All Rights Reserved. 45 | 46 | 47 | Copyright © 2013 Apple Inc. All rights reserved. 48 | WWDC 2013 License 49 | 50 | NOTE: This Apple Software was supplied by Apple as part of a WWDC 2013 51 | Session. Please refer to the applicable WWDC 2013 Session for further 52 | information. 53 | 54 | IMPORTANT: This Apple software is supplied to you by Apple Inc. 55 | ("Apple") in consideration of your agreement to the following terms, and 56 | your use, installation, modification or redistribution of this Apple 57 | software constitutes acceptance of these terms. If you do not agree with 58 | these terms, please do not use, install, modify or redistribute this 59 | Apple software. 60 | 61 | In consideration of your agreement to abide by the following terms, and 62 | subject to these terms, Apple grants you a non-exclusive license, under 63 | Apple's copyrights in this original Apple software (the "Apple 64 | Software"), to use, reproduce, modify and redistribute the Apple 65 | Software, with or without modifications, in source and/or binary forms; 66 | provided that if you redistribute the Apple Software in its entirety and 67 | without modifications, you must retain this notice and the following 68 | text and disclaimers in all such redistributions of the Apple Software. 69 | Neither the name, trademarks, service marks or logos of Apple Inc. may 70 | be used to endorse or promote products derived from the Apple Software 71 | without specific prior written permission from Apple. Except as 72 | expressly stated in this notice, no other rights or licenses, express or 73 | implied, are granted by Apple herein, including but not limited to any 74 | patent rights that may be infringed by your derivative works or by other 75 | works in which the Apple Software may be incorporated. 76 | 77 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES 78 | NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 79 | IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR 80 | A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 81 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 82 | 83 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 84 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 85 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 86 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 87 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 88 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 89 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 90 | POSSIBILITY OF SUCH DAMAGE. 91 | 92 | EA1002 93 | 5/3/2013 94 | */ 95 | 96 | #if defined(__has_feature) && __has_feature(modules) 97 | @import UIKit; 98 | #else 99 | #import 100 | #endif 101 | 102 | @interface UIImage (ImageEffects) 103 | 104 | - (UIImage *)applyLightEffect; 105 | - (UIImage *)applyExtraLightEffect; 106 | - (UIImage *)applyDarkEffect; 107 | - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor; 108 | 109 | - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage; 110 | 111 | + (UIImage *)imageWithColor:(UIColor *)color; 112 | + (UIImage *)convertViewToImage; 113 | + (UIImage *)convertViewToImage:(UIView *)view; 114 | 115 | @end 116 | -------------------------------------------------------------------------------- /SCLAlertView/UIImage+ImageEffects.m: -------------------------------------------------------------------------------- 1 | /* 2 | File: UIImage+ImageEffects.m 3 | Abstract: This is a category of UIImage that adds methods to apply blur and tint effects to an image. This is the code you’ll want to look out to find out how to use vImage to efficiently calculate a blur. 4 | Version: 1.0 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2013 Apple Inc. All Rights Reserved. 45 | 46 | 47 | Copyright © 2013 Apple Inc. All rights reserved. 48 | WWDC 2013 License 49 | 50 | NOTE: This Apple Software was supplied by Apple as part of a WWDC 2013 51 | Session. Please refer to the applicable WWDC 2013 Session for further 52 | information. 53 | 54 | IMPORTANT: This Apple software is supplied to you by Apple Inc. 55 | ("Apple") in consideration of your agreement to the following terms, and 56 | your use, installation, modification or redistribution of this Apple 57 | software constitutes acceptance of these terms. If you do not agree with 58 | these terms, please do not use, install, modify or redistribute this 59 | Apple software. 60 | 61 | In consideration of your agreement to abide by the following terms, and 62 | subject to these terms, Apple grants you a non-exclusive license, under 63 | Apple's copyrights in this original Apple software (the "Apple 64 | Software"), to use, reproduce, modify and redistribute the Apple 65 | Software, with or without modifications, in source and/or binary forms; 66 | provided that if you redistribute the Apple Software in its entirety and 67 | without modifications, you must retain this notice and the following 68 | text and disclaimers in all such redistributions of the Apple Software. 69 | Neither the name, trademarks, service marks or logos of Apple Inc. may 70 | be used to endorse or promote products derived from the Apple Software 71 | without specific prior written permission from Apple. Except as 72 | expressly stated in this notice, no other rights or licenses, express or 73 | implied, are granted by Apple herein, including but not limited to any 74 | patent rights that may be infringed by your derivative works or by other 75 | works in which the Apple Software may be incorporated. 76 | 77 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES 78 | NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 79 | IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR 80 | A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 81 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 82 | 83 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 84 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 85 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 86 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 87 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 88 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 89 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 90 | POSSIBILITY OF SUCH DAMAGE. 91 | 92 | EA1002 93 | 5/3/2013 94 | */ 95 | 96 | #import "UIImage+ImageEffects.h" 97 | #import "SCLMacros.h" 98 | 99 | #if defined(__has_feature) && __has_feature(modules) 100 | @import Accelerate; 101 | #else 102 | #import 103 | #endif 104 | #import 105 | 106 | 107 | @implementation UIImage (ImageEffects) 108 | 109 | 110 | - (UIImage *)applyLightEffect 111 | { 112 | UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3]; 113 | return [self applyBlurWithRadius:30 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil]; 114 | } 115 | 116 | 117 | - (UIImage *)applyExtraLightEffect 118 | { 119 | UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82]; 120 | return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil]; 121 | } 122 | 123 | 124 | - (UIImage *)applyDarkEffect 125 | { 126 | UIColor *tintColor = [UIColor colorWithWhite:0.11 alpha:0.73]; 127 | return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil]; 128 | } 129 | 130 | 131 | - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor 132 | { 133 | const CGFloat EffectColorAlpha = 0.6; 134 | UIColor *effectColor = tintColor; 135 | NSUInteger componentCount = CGColorGetNumberOfComponents(tintColor.CGColor); 136 | if (componentCount == 2) { 137 | CGFloat b; 138 | if ([tintColor getWhite:&b alpha:NULL]) { 139 | effectColor = [UIColor colorWithWhite:b alpha:EffectColorAlpha]; 140 | } 141 | } 142 | else { 143 | CGFloat r, g, b; 144 | if ([tintColor getRed:&r green:&g blue:&b alpha:NULL]) { 145 | effectColor = [UIColor colorWithRed:r green:g blue:b alpha:EffectColorAlpha]; 146 | } 147 | } 148 | return [self applyBlurWithRadius:10 tintColor:effectColor saturationDeltaFactor:-1.0 maskImage:nil]; 149 | } 150 | 151 | 152 | - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage 153 | { 154 | // Check pre-conditions. 155 | if (self.size.width < 1 || self.size.height < 1) { 156 | NSLog (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self); 157 | return nil; 158 | } 159 | if (!self.CGImage) { 160 | NSLog (@"*** error: image must be backed by a CGImage: %@", self); 161 | return nil; 162 | } 163 | if (maskImage && !maskImage.CGImage) { 164 | NSLog (@"*** error: maskImage must be backed by a CGImage: %@", maskImage); 165 | return nil; 166 | } 167 | 168 | CGRect imageRect = { CGPointZero, self.size }; 169 | UIImage *effectImage = self; 170 | 171 | BOOL hasBlur = blurRadius > __FLT_EPSILON__; 172 | BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__; 173 | if (hasBlur || hasSaturationChange) { 174 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]); 175 | CGContextRef effectInContext = UIGraphicsGetCurrentContext(); 176 | CGContextScaleCTM(effectInContext, 1.0, -1.0); 177 | CGContextTranslateCTM(effectInContext, 0, -self.size.height); 178 | CGContextDrawImage(effectInContext, imageRect, self.CGImage); 179 | 180 | vImage_Buffer effectInBuffer; 181 | effectInBuffer.data = CGBitmapContextGetData(effectInContext); 182 | effectInBuffer.width = CGBitmapContextGetWidth(effectInContext); 183 | effectInBuffer.height = CGBitmapContextGetHeight(effectInContext); 184 | effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext); 185 | 186 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]); 187 | CGContextRef effectOutContext = UIGraphicsGetCurrentContext(); 188 | vImage_Buffer effectOutBuffer; 189 | effectOutBuffer.data = CGBitmapContextGetData(effectOutContext); 190 | effectOutBuffer.width = CGBitmapContextGetWidth(effectOutContext); 191 | effectOutBuffer.height = CGBitmapContextGetHeight(effectOutContext); 192 | effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext); 193 | 194 | if (hasBlur) { 195 | // A description of how to compute the box kernel width from the Gaussian 196 | // radius (aka standard deviation) appears in the SVG spec: 197 | // http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement 198 | // 199 | // For larger values of 's' (s >= 2.0), an approximation can be used: Three 200 | // successive box-blurs build a piece-wise quadratic convolution kernel, which 201 | // approximates the Gaussian kernel to within roughly 3%. 202 | // 203 | // let d = floor(s * 3*sqrt(2*pi)/4 + 0.5) 204 | // 205 | // ... if d is odd, use three box-blurs of size 'd', centered on the output pixel. 206 | // 207 | CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale]; 208 | uint32_t radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5); 209 | if (radius % 2 != 1) { 210 | radius += 1; // force radius to be odd so that the three box-blur methodology works. 211 | } 212 | vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend); 213 | vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend); 214 | vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend); 215 | } 216 | BOOL effectImageBuffersAreSwapped = NO; 217 | if (hasSaturationChange) { 218 | CGFloat s = saturationDeltaFactor; 219 | CGFloat floatingPointSaturationMatrix[] = { 220 | 0.0722 + 0.9278 * s, 0.0722 - 0.0722 * s, 0.0722 - 0.0722 * s, 0, 221 | 0.7152 - 0.7152 * s, 0.7152 + 0.2848 * s, 0.7152 - 0.7152 * s, 0, 222 | 0.2126 - 0.2126 * s, 0.2126 - 0.2126 * s, 0.2126 + 0.7873 * s, 0, 223 | 0, 0, 0, 1, 224 | }; 225 | const int32_t divisor = 256; 226 | NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]); 227 | int16_t saturationMatrix[matrixSize]; 228 | for (NSUInteger i = 0; i < matrixSize; ++i) { 229 | saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor); 230 | } 231 | if (hasBlur) { 232 | vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags); 233 | effectImageBuffersAreSwapped = YES; 234 | } 235 | else { 236 | vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags); 237 | } 238 | } 239 | if (!effectImageBuffersAreSwapped) 240 | effectImage = UIGraphicsGetImageFromCurrentImageContext(); 241 | UIGraphicsEndImageContext(); 242 | 243 | if (effectImageBuffersAreSwapped) 244 | effectImage = UIGraphicsGetImageFromCurrentImageContext(); 245 | UIGraphicsEndImageContext(); 246 | } 247 | 248 | // Set up output context. 249 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]); 250 | CGContextRef outputContext = UIGraphicsGetCurrentContext(); 251 | CGContextScaleCTM(outputContext, 1.0, -1.0); 252 | CGContextTranslateCTM(outputContext, 0, -self.size.height); 253 | 254 | // Draw base image. 255 | CGContextDrawImage(outputContext, imageRect, self.CGImage); 256 | 257 | // Draw effect image. 258 | if (hasBlur) { 259 | CGContextSaveGState(outputContext); 260 | if (maskImage) { 261 | CGContextClipToMask(outputContext, imageRect, maskImage.CGImage); 262 | } 263 | CGContextDrawImage(outputContext, imageRect, effectImage.CGImage); 264 | CGContextRestoreGState(outputContext); 265 | } 266 | 267 | // Add in color tint. 268 | if (tintColor) { 269 | CGContextSaveGState(outputContext); 270 | CGContextSetFillColorWithColor(outputContext, tintColor.CGColor); 271 | CGContextFillRect(outputContext, imageRect); 272 | CGContextRestoreGState(outputContext); 273 | } 274 | 275 | // Output image is ready. 276 | UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext(); 277 | UIGraphicsEndImageContext(); 278 | 279 | return outputImage; 280 | } 281 | 282 | + (UIImage *)imageWithColor:(UIColor *)color 283 | { 284 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); 285 | UIGraphicsBeginImageContext(rect.size); 286 | CGContextRef context = UIGraphicsGetCurrentContext(); 287 | 288 | CGContextSetFillColorWithColor(context, [color CGColor]); 289 | CGContextFillRect(context, rect); 290 | 291 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 292 | UIGraphicsEndImageContext(); 293 | 294 | return image; 295 | } 296 | 297 | + (UIImage *)convertViewToImage 298 | { 299 | UIWindow *keyWindow = [[UIApplication sharedApplication]keyWindow]; 300 | CGRect rect = [keyWindow bounds]; 301 | UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0.0f); 302 | CGContextRef context = UIGraphicsGetCurrentContext(); 303 | [keyWindow.layer renderInContext:context]; 304 | UIImage *capturedScreen = UIGraphicsGetImageFromCurrentImageContext(); 305 | UIGraphicsEndImageContext(); 306 | 307 | return capturedScreen; 308 | } 309 | 310 | + (UIImage *)convertViewToImage:(UIView *)view 311 | { 312 | CGFloat scale = [UIScreen mainScreen].scale; 313 | UIImage *capturedScreen; 314 | 315 | //Optimized/fast method for rendering a UIView as image on iOS 7 and later versions. 316 | UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, scale); 317 | [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO]; 318 | capturedScreen = UIGraphicsGetImageFromCurrentImageContext(); 319 | UIGraphicsEndImageContext(); 320 | 321 | return capturedScreen; 322 | } 323 | 324 | @end 325 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | // BSPHPOC 2 | // BSPHP 魔改UDID 技术团队 十三哥工作室 3 | // 承接软件APP开发 UDID定制 验证加密二改 PHP JS HTML5开发 辅助开发 4 | // WX:NongShiFu123 QQ350722326 5 | // Created by MRW on 2022/11/14. 6 | // GitHub:http://github.com/nongshifu/ 7 | // 开源Q群: 398423911 8 | // Copyright © 2019年 xiaozhou. All rights reserved. 9 | //com.rileytestut.Delta.Beta 10 | #import "WX_NongShiFu123.h" 11 | #import "getKeychain.h" 12 | @implementation NSObject (mian) 13 | +(void)load 14 | { 15 | //测试的时候 可以取消注释 启动一次便可清除 16 | // [getKeychain removeKeychainDataForKey:@"DZUDID"];//清除UDID 17 | // [getKeychain removeKeychainDataForKey:@"SJUSERID"];//清除用户ID 18 | // [getKeychain removeKeychainDataForKey:@"ShiSanGeDZKM"];//清除卡密 19 | // [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"公告"];//清除公告 20 | // [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"到期时间"];//清除到期时间 21 | 22 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 23 | [[WX_NongShiFu123 alloc] BSPHP]; 24 | }); 25 | } 26 | @end 27 | -------------------------------------------------------------------------------- /myipad.cn-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'HackMenu' target in the 'HackMenu' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | 8 | 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/project.xcworkspace/xcuserdata/apple.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | EnabledFullIndexStoreVisibility 12 | 13 | IssueFilterStyle 14 | ShowActiveSchemeOnly 15 | LiveSourceIssuesEnabled 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/project.xcworkspace/xcuserdata/guyongagng.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | EnabledFullIndexStoreVisibility 12 | 13 | IssueFilterStyle 14 | ShowActiveSchemeOnly 15 | LiveSourceIssuesEnabled 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/project.xcworkspace/xcuserdata/guyonggang.xcuserdatad/IDEFindNavigatorScopes.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/project.xcworkspace/xcuserdata/nongshifu.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | IssueFilterStyle 12 | ShowActiveSchemeOnly 13 | LiveSourceIssuesEnabled 14 | 15 | ShowSharedSchemesAutomaticallyEnabled 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/project.xcworkspace/xcuserdata/shisange.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nongshifu/Bsphp-des3_vi-UDID/ed6a6bf9bbd675d1afec57dd8067af1c91a7c83b/myipad.cn.xcodeproj/project.xcworkspace/xcuserdata/shisange.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/xcshareddata/xcschemes/myipad.cn.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 57 | 58 | 59 | 60 | 62 | 63 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | JnDlg.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | PUBGMOBILENewiOSGodsComJailed.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/xcuserdata/guyongagng.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PUBGMOBILENewiOSGodsComJailed.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/xcuserdata/guyonggang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PUBGMOBILENewiOSGodsComJailed.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/xcuserdata/mac126.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/xcuserdata/macgu.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DLGMemor.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 194F3B38218327B10070F5BC 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/xcuserdata/macgyg.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/xcuserdata/macgyg.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DLGMemor.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | JnDlg.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/xcuserdata/nongshifu.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/xcuserdata/nongshifu.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Hack.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | HackMenu.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | PUBGMOBILENewiOSGodsComJailed.xcscheme 18 | 19 | orderHint 20 | 0 21 | 22 | PUBGMOBILENewiOSGodsComJailed.xcscheme_^#shared#^_ 23 | 24 | orderHint 25 | 0 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/xcuserdata/shisange.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/xcuserdata/shisange.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | myipad.cn.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 194F3B38218327B10070F5BC 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /myipad.cn.xcodeproj/xcuserdata/yi.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | HackMenu.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /udid.php: -------------------------------------------------------------------------------- 1 | 36 | 37 | 38 | 39 | "; 46 | $arr = explode("udid.php", $url); 47 | $域名=$arr[0]; 48 | // echo "域名是:" . $域名. "
"; 49 | $数据库表前缀="bsphp_"; 50 | $doc_root = $_SERVER['DOCUMENT_ROOT']; 51 | // echo "当前站点目录是:" . $doc_root. "
"; 52 | //自动加载数据库 53 | include("$doc_root/Plug/Plug.php"); 54 | 55 | //获取URL参数 56 | $id = isset($_GET['id']) ? trim($_GET['id']) : ''; 57 | $rm = isset($_GET['rm']) ? trim($_GET['rm']) : ''; 58 | $openurl = isset($_GET['openurl']) ? trim($_GET['openurl']) : ''; 59 | $daihao = isset($_GET['daihao']) ? trim($_GET['daihao']) : ''; 60 | $code = isset($_GET['code']) ? trim($_GET['code']) : ''; 61 | //判断是查询黑名单功能 62 | if(strlen($code)>5){ 63 | //获取udid=$code 64 | $sql="SELECT * FROM `".$数据库表前缀."pattern_login` WHERE `L_key_info` LIKE '$code' AND `L_class` != 0 AND `L_beizhu` LIKE '%黑%'"; 65 | $info = plug_query_array($sql); 66 | if($info){ 67 | if (strpos($info['L_beizhu'], '黑') !== false) { 68 | // echo "字符串包含 '黑' 黑名单用户"; 69 | $code="黑名单用户".$info['L_beizhu']."联系管理员解除"; 70 | 71 | } 72 | } 73 | 74 | 75 | } 76 | // 获取描述文件POST 参数 77 | $data = file_get_contents('php://input'); 78 | $plistBegin = ''; 79 | $plistEnd = ''; 80 | $pos1 = strpos($data, $plistBegin); 81 | $pos2 = strpos($data, $plistEnd); 82 | $data2 = substr ($data,$pos1,$pos2-$pos1); 83 | //解析出UDID 84 | $UDID = str_replace("", "", $data2); 85 | 86 | //删除缓存- 87 | if (strlen($rm) > 0 && strlen($rm) <= 50) { 88 | $dir = '.'; 89 | $keyword = '/^' . preg_quote($rm, '/') . '$/'; 90 | $count = 0; 91 | 92 | foreach (glob($dir . '/*.*') as $file) { 93 | 94 | if (is_file($file) && (strpos($file, $rm) !== false)) { 95 | // echo $file."
"; 96 | 97 | if (unlink($file)) { 98 | // echo "File {$file} deleted successfully\n"; 99 | $count++; 100 | } else { 101 | // echo "Failed to delete file {$file}\n"; 102 | } 103 | } 104 | } 105 | 106 | if ($count > 0) { 107 | // echo "{$count} file(s) deleted successfully."; 108 | } else { 109 | // echo "No file deleted."; 110 | } 111 | } else { 112 | // echo "Invalid parameter."; 113 | } 114 | 115 | //储存OPENURL 既跳转app的链接 和软件代号 到 用户id.txt 116 | if(strlen($openurl)>5){ 117 | $fp = fopen($id.'.txt', 'w'); 118 | fwrite($fp, $openurl."|".$daihao); 119 | fclose($fp); 120 | } 121 | // UDID不为空证明获取到 跳转APP打开等后续操作 122 | if(strlen($UDID)>10){ 123 | //接收描述文件POST过来的数据 124 | $res = file_get_contents("./".$id.'.txt');//读取txt 125 | $keywords_array = explode("|", $res);//拆分openurl 和 软件代号 126 | $openurl=$keywords_array[0]; 127 | $daihao=$keywords_array[1]; 128 | $备注=""; 129 | //查询是否在黑名单 130 | $sql="SELECT * FROM `".$数据库表前缀."pattern_login` WHERE `L_key_info` LIKE '$UDID' AND `L_class` != 0 AND `L_beizhu` LIKE '%黑%'"; 131 | $info = plug_query_array($sql); 132 | if($info){ 133 | //读取备注 134 | $备注=$info['L_beizhu']; 135 | }else{ 136 | //没有备注 137 | $备注=""; 138 | } 139 | //判断备注内容 包含关键字:黑 就是拉黑用户 140 | if (strpos($备注, '黑') !== false) { 141 | // echo "字符串包含 '黑' 黑名单用户"; 142 | $write=$UDID."|老用户|黑名单用户|".$备注; 143 | 144 | } else { 145 | // echo "字符串不包含 '黑' 正常用户"; 146 | //查询是否存在记录 存在就老用户 不存在 新用户 147 | $sql = "SELECT L_key_info FROM bsphp_pattern_login WHERE L_key_info = '$UDID' AND `L_daihao`='$daihao'"; 148 | $info = plug_query_array($sql); 149 | if($info){ 150 | //有记录 151 | $write=$UDID."|老用户|正常用户|".$备注; 152 | 153 | }else{ 154 | //有记录 155 | $write=$UDID."|新用户|正常用户|".$备注; 156 | 157 | } 158 | 159 | } 160 | 161 | // 储存udid 162 | $fp = fopen("./udid".$id.'.txt', 'w'); 163 | fwrite($fp, $write); 164 | fclose($fp); 165 | 166 | //判断是否为空 没有openurl 则是跳转会浏览器 提示用户自行打开APP 167 | if (strpos($res, 'null') !== false) { 168 | $url="Location: ".$域名."udid.php?id=null"; 169 | header('HTTP/1.1 301 Moved Permanently'); 170 | header($url); 171 | } else { 172 | $url="Location: ".$openurl."://"; 173 | header('HTTP/1.1 301 Moved Permanently'); 174 | header($url); 175 | } 176 | 177 | 178 | }else{ 179 | // UDID为空 创建描述文件 并提示下载描述文件 180 | 181 | $str=" 182 | PayloadContent 183 | 184 | URL 185 | ".$域名."udid.php?id=".$id." 186 | 187 | DeviceAttributes 188 | 189 | UDID 190 | 191 | 192 | 193 | 194 | PayloadVersion 195 | 1 196 | 197 | PayloadUUID 198 | c156f23f8-fc342-7545-8fc5-3256761d82933 199 | 200 | PayloadIdentifier 201 | 获取UDID 202 | 203 | PayloadType 204 | Profile Service 205 | "; 206 | // 储存描述文件 207 | $fp = fopen("./".$id.'.mobileconfig', 'w'); 208 | fwrite($fp, $str); 209 | fclose($fp); 210 | if($签名==1){ 211 | 212 | if(!is_file('b.crt')){ 213 | // echo "不存在 就读取证书PEM 拆分储存
"; 214 | if(!is_file('pem.pem')){ 215 | // echo "证书文件不存在 不签名
"; 216 | $mobileconfig="./".$id.'.mobileconfig'; 217 | }else{ 218 | // echo "证书文件存在 读取进行拆分储存
"; 219 | $res = file_get_contents('pem.pem'); 220 | //替换 221 | $search = "/-----END CERTIFICATE-----/"; 222 | $replace = "-----END CERTIFICATE--------"; 223 | $result = preg_replace($search, $replace, $res, 1); 224 | 225 | //拆分证书文件 226 | $penarr=explode("-----END CERTIFICATE--------",$result); 227 | //储存前段部分为a.crt 228 | $fp = fopen("a.crt", 'w'); 229 | $acrt=$penarr[0]."-----END CERTIFICATE-----"; 230 | 231 | fwrite($fp, $acrt); 232 | fclose($fp); 233 | //储存后段部分为b.crt 234 | $carb=$penarr[1]; 235 | $fp = fopen("b.crt", 'w'); 236 | 237 | fwrite($fp,$carb ); 238 | fclose($fp); 239 | } 240 | if (strpos($res, 'null') !== false) { 241 | $url="Location: ".$域名."udid.php?id=null"; 242 | header('HTTP/1.1 301 Moved Permanently'); 243 | header($url); 244 | 245 | } 246 | } 247 | 248 | //描述文件签名 key为网站证书key a.crt 为证书上部分 b.crt为证书下半部分 249 | $miss2=shell_exec("openssl smime -sign -in ".$id.".mobileconfig -out 2".$id.".mobileconfig -signer a.crt -inkey key.key -certfile b.crt -outform der -nodetach"); 250 | 251 | $mobileconfig="./2".$id.'.mobileconfig'; 252 | }else{ 253 | $mobileconfig="./".$id.'.mobileconfig'; 254 | } 255 | } 256 | 257 | //判断企业描述文件是否存在 1.mobileprovision 存在就提示跳转iOS设置 没有就不提示 258 | if(!is_file('1.mobileprovision')){ 259 | // 文件不存 260 | $跳转=""; 261 | }else{ 262 | //文件存在 263 | $跳转="./1.mobileprovision"; 264 | } 265 | 266 | ?> 267 | 268 | 269 | 270 | 271 | 272 | IOS安全防护 273 | 274 | 275 | 276 |
277 |
278 | 279 |
280 | 281 |
282 |

UDID获取

283 |

如果安装失败请重新打开游戏
UDID仅作为授权码绑定标识符作用
请按照步骤安装

284 |

285 |
286 | 287 |
288 |

289 | 290 | 291 |

292 | 293 |
294 |
295 |

承接iOS软件开发 验证对接 Php Html Js开发

296 |
297 | 298 |
299 | 306 |
307 |
308 | 309 | 320 | 338 | 339 | 340 | -------------------------------------------------------------------------------- /参数填写说明.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nongshifu/Bsphp-des3_vi-UDID/ed6a6bf9bbd675d1afec57dd8067af1c91a7c83b/参数填写说明.png -------------------------------------------------------------------------------- /购买-更新说明图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nongshifu/Bsphp-des3_vi-UDID/ed6a6bf9bbd675d1afec57dd8067af1c91a7c83b/购买-更新说明图.png -------------------------------------------------------------------------------- /通用BSPHP对接OC源码.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nongshifu/Bsphp-des3_vi-UDID/ed6a6bf9bbd675d1afec57dd8067af1c91a7c83b/通用BSPHP对接OC源码.zip --------------------------------------------------------------------------------