阿里sdk

This commit is contained in:
Robin
2026-02-20 17:56:24 +08:00
parent 39524692e5
commit f3af234308
524 changed files with 58345 additions and 0 deletions

View File

@@ -0,0 +1,471 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#import <UIKit/UIKit.h>
#import "HttpdnsUtil.h"
#import "HttpdnsLog_Internal.h"
#import "CommonCrypto/CommonCrypto.h"
#import "arpa/inet.h"
#import "HttpdnsPublicConstant.h"
#import "httpdnsReachability.h"
#import "HttpdnsInternalConstant.h"
#import "HttpdnsHostObject.h"
#import "HttpdnsService.h"
@implementation HttpdnsUtil
+ (BOOL)isIPv4Address:(NSString *)addr {
if (!addr) {
return NO;
}
struct in_addr dst;
return inet_pton(AF_INET, [addr UTF8String], &(dst.s_addr)) == 1;
}
+ (BOOL)isIPv6Address:(NSString *)addr {
if (!addr) {
return NO;
}
struct in6_addr dst6;
return inet_pton(AF_INET6, [addr UTF8String], &dst6) == 1;
}
+ (BOOL)isAnIP:(NSString *)candidate {
if ([self isIPv4Address:candidate]) {
return YES;
}
if ([self isIPv6Address:candidate]) {
return YES;
}
return NO;
}
+ (BOOL)isAHost:(NSString *)host {
static dispatch_once_t once_token;
static NSRegularExpression *hostExpression = nil;
dispatch_once(&once_token, ^{
hostExpression = [[NSRegularExpression alloc] initWithPattern:@"^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$" options:NSRegularExpressionCaseInsensitive error:nil];
});
if (!host.length) {
return NO;
}
NSTextCheckingResult *checkResult = [hostExpression firstMatchInString:host options:0 range:NSMakeRange(0, [host length])];
if (checkResult.range.length == [host length]) {
return YES;
} else {
return NO;
}
}
+ (void)warnMainThreadIfNecessary {
if ([NSThread isMainThread]) {
HttpdnsLogDebug("Warning: A long-running Paas operation is being executed on the main thread.");
}
}
+ (NSDictionary *)getValidDictionaryFromJson:(id)jsonValue {
NSDictionary *dictionaryValueFromJson = nil;
if ([jsonValue isKindOfClass:[NSDictionary class]]) {
if ([(NSDictionary *)jsonValue allKeys].count > 0) {
NSMutableDictionary *mutableDict = [NSMutableDictionary dictionaryWithDictionary:jsonValue];
@try {
[self removeNSNullValueFromDictionary:mutableDict];
} @catch (NSException *exception) {}
dictionaryValueFromJson = [jsonValue copy];
}
}
return dictionaryValueFromJson;
}
+ (void)removeNSNullValueFromArray:(NSMutableArray *)array {
NSMutableArray *objToRemove = nil;
NSMutableIndexSet *indexToReplace = [[NSMutableIndexSet alloc] init];
NSMutableArray *objForReplace = [[NSMutableArray alloc] init];
for (int i = 0; i < array.count; ++i) {
id value = [array objectAtIndex:i];
if ([value isKindOfClass:[NSNull class]]) {
if (!objToRemove) {
objToRemove = [[NSMutableArray alloc] init];
}
[objToRemove addObject:value];
} else if ([value isKindOfClass:[NSDictionary class]]) {
NSMutableDictionary *mutableDict = [NSMutableDictionary dictionaryWithDictionary:value];
[self removeNSNullValueFromDictionary:mutableDict];
[indexToReplace addIndex:i];
[objForReplace addObject:mutableDict];
} else if ([value isKindOfClass:[NSArray class]]) {
NSMutableArray *v = [value mutableCopy];
[self removeNSNullValueFromArray:v];
[indexToReplace addIndex:i];
[objForReplace addObject:v];
}
}
[array replaceObjectsAtIndexes:indexToReplace withObjects:objForReplace];
if (objToRemove) {
[array removeObjectsInArray:objToRemove];
}
}
+ (void)removeNSNullValueFromDictionary:(NSMutableDictionary *)dict {
for (id key in [dict allKeys]) {
id value = [dict objectForKey:key];
if ([value isKindOfClass:[NSNull class]]) {
[dict removeObjectForKey:key];
} else if ([value isKindOfClass:[NSDictionary class]]) {
NSMutableDictionary *mutableDict = [NSMutableDictionary dictionaryWithDictionary:value];
[self removeNSNullValueFromDictionary:mutableDict];
[dict setObject:mutableDict forKey:key];
} else if ([value isKindOfClass:[NSArray class]]) {
NSMutableArray *v = [value mutableCopy];
[self removeNSNullValueFromArray:v];
[dict setObject:v forKey:key];
}
}
}
+ (BOOL)isEmptyArray:(NSArray *)inputArr {
if (!inputArr) {
return YES;
}
return [inputArr count] == 0;
}
+ (BOOL)isNotEmptyArray:(NSArray *)inputArr {
return ![self isEmptyArray:inputArr];
}
+ (BOOL)isEmptyString:(NSString *)inputStr {
if (!inputStr) {
return YES;
}
return [inputStr length] == 0;
}
+ (BOOL)isNotEmptyString:(NSString *)inputStr {
return ![self isEmptyString:inputStr];
}
+ (BOOL)isValidJSON:(id)JSON {
BOOL isValid;
@try {
isValid = ([JSON isKindOfClass:[NSDictionary class]] || [JSON isKindOfClass:[NSArray class]]);
} @catch (NSException *ignore) {
}
return isValid;
}
+ (BOOL)isEmptyDictionary:(NSDictionary *)inputDict {
if (!inputDict) {
return YES;
}
return [inputDict count] == 0;
}
+ (BOOL)isNotEmptyDictionary:(NSDictionary *)inputDict {
return ![self isEmptyDictionary:inputDict];
}
+ (NSArray *)joinArrays:(NSArray *)array1 withArray:(NSArray *)array2 {
NSMutableArray *resultArray = [array1 mutableCopy];
[resultArray addObjectsFromArray:array2];
return [resultArray copy];
}
+ (id)convertJsonDataToObject:(NSData *)jsonData {
if (jsonData) {
NSError *error;
id jsonObj = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
if (!error) {
return jsonObj;
}
}
return nil;
}
+ (NSString *)getMD5StringFrom:(NSString *)originString {
const char * pointer = [originString UTF8String];
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
CC_MD5(pointer, (CC_LONG)strlen(pointer), md5Buffer);
NSMutableString *string = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[string appendFormat:@"%02x",md5Buffer[i]];
return [string copy];
}
+ (NSString *)URLEncodedString:(NSString *)str {
if (str) {
return [str stringByAddingPercentEncodingWithAllowedCharacters:
[NSCharacterSet characterSetWithCharactersInString:@"!*'();:@&=+$,/?%#[]\""].invertedSet];
}
return nil;
}
/**
sessionId
App
sessionId12base62
*/
+ (NSString *)generateSessionID {
static NSString *sessionId = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *alphabet = @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
NSUInteger length = alphabet.length;
if (![HttpdnsUtil isNotEmptyString:sessionId]) {
NSMutableString *mSessionId = [NSMutableString string];
for (int i = 0; i < 12; i++) {
[mSessionId appendFormat:@"%@", [alphabet substringWithRange:NSMakeRange(arc4random() % length, 1)]];
}
sessionId = [mSessionId copy];
}
});
return sessionId;
}
+ (NSString *)generateUserAgent {
UIDevice *device = [UIDevice currentDevice];
NSString *systemName = [device systemName];
NSString *systemVersion = [device systemVersion];
NSString *model = [device model];
NSString *userAgent = [NSString stringWithFormat:@"HttpdnsSDK/%@ (%@; iOS %@; %@)", HTTPDNS_IOS_SDK_VERSION, model, systemVersion, systemName];
return userAgent;
}
+ (NSData *)encryptDataAESCBC:(NSData *)plaintext
withKey:(NSData *)key
error:(NSError **)error {
//
if (plaintext == nil || [plaintext length] == 0 || key == nil || [key length] != kCCKeySizeAES128) {
if (error) {
*error = [NSError errorWithDomain:ALICLOUD_HTTPDNS_ERROR_DOMAIN
code:ALICLOUD_HTTPDNS_ENCRYPT_INVALID_PARAMS_ERROR_CODE
userInfo:@{NSLocalizedDescriptionKey: @"Invalid input parameters"}];
}
return nil;
}
// CBC128bit(16)IV
NSMutableData *iv = [NSMutableData dataWithLength:kCCBlockSizeAES128];
int result = SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, iv.mutableBytes);
if (result != 0) {
if (error) {
*error = [NSError errorWithDomain:ALICLOUD_HTTPDNS_ERROR_DOMAIN
code:ALICLOUD_HTTPDNS_ENCRYPT_RANDOM_IV_ERROR_CODE
userInfo:@{NSLocalizedDescriptionKey: @"Failed to generate random IV"}];
}
return nil;
}
// ()
size_t bufferSize = [plaintext length] + kCCBlockSizeAES128;
size_t encryptedSize = 0;
//
NSMutableData *cipherData = [NSMutableData dataWithLength:bufferSize];
//
// AESPKCS5PaddingPKCS7Padding
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES,
kCCOptionPKCS7Padding,
[key bytes],
[key length],
[iv bytes],
[plaintext bytes],
[plaintext length],
[cipherData mutableBytes],
[cipherData length],
&encryptedSize);
if (cryptStatus != kCCSuccess) {
if (error) {
*error = [NSError errorWithDomain:ALICLOUD_HTTPDNS_ERROR_DOMAIN
code:ALICLOUD_HTTPDNS_ENCRYPT_FAILED_ERROR_CODE
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Encryption failed with status: %d", cryptStatus]}];
}
return nil;
}
//
[cipherData setLength:encryptedSize];
// IV
NSMutableData *resultData = [NSMutableData dataWithData:iv];
[resultData appendData:cipherData];
return resultData;
}
+ (NSString *)hexStringFromData:(NSData *)data {
if (!data || data.length == 0) {
return nil;
}
NSMutableString *hexString = [NSMutableString stringWithCapacity:data.length * 2];
const unsigned char *bytes = data.bytes;
for (NSInteger i = 0; i < data.length; i++) {
[hexString appendFormat:@"%02x", bytes[i]];
}
return [hexString copy];
}
+ (NSData *)dataFromHexString:(NSString *)hexString {
if (!hexString || hexString.length == 0) {
return nil;
}
//
NSString *cleanedString = [hexString stringByReplacingOccurrencesOfString:@" " withString:@""];
//
if (cleanedString.length % 2 != 0) {
return nil;
}
NSMutableData *data = [NSMutableData dataWithCapacity:cleanedString.length / 2];
for (NSUInteger i = 0; i < cleanedString.length; i += 2) {
NSString *byteString = [cleanedString substringWithRange:NSMakeRange(i, 2)];
NSScanner *scanner = [NSScanner scannerWithString:byteString];
unsigned int byteValue;
if (![scanner scanHexInt:&byteValue]) {
return nil;
}
uint8_t byte = (uint8_t)byteValue;
[data appendBytes:&byte length:1];
}
return data;
}
+ (NSString *)hmacSha256:(NSString *)data key:(NSString *)key {
if (!data || !key) {
return nil;
}
// NSData
NSData *keyData = [self dataFromHexString:key];
if (!keyData) {
return nil;
}
//
NSData *dataToSign = [data dataUsingEncoding:NSUTF8StringEncoding];
// HMAC
uint8_t digestBytes[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, keyData.bytes, keyData.length, dataToSign.bytes, dataToSign.length, digestBytes);
//
NSData *hmacData = [NSData dataWithBytes:digestBytes length:CC_SHA256_DIGEST_LENGTH];
//
return [self hexStringFromData:hmacData];
}
+ (NSData *)decryptDataAESCBC:(NSData *)ciphertext
withKey:(NSData *)key
error:(NSError **)error {
//
if (ciphertext == nil || [ciphertext length] <= kCCBlockSizeAES128 || key == nil || [key length] != kCCKeySizeAES128) {
if (error) {
*error = [NSError errorWithDomain:ALICLOUD_HTTPDNS_ERROR_DOMAIN
code:ALICLOUD_HTTPDNS_ENCRYPT_INVALID_PARAMS_ERROR_CODE
userInfo:@{NSLocalizedDescriptionKey: @"Invalid input parameters for decryption"}];
}
return nil;
}
// IV16
NSData *iv = [ciphertext subdataWithRange:NSMakeRange(0, kCCBlockSizeAES128)];
NSData *actualCiphertext = [ciphertext subdataWithRange:NSMakeRange(kCCBlockSizeAES128, ciphertext.length - kCCBlockSizeAES128)];
//
size_t bufferSize = actualCiphertext.length + kCCBlockSizeAES128;
size_t decryptedSize = 0;
//
NSMutableData *decryptedData = [NSMutableData dataWithLength:bufferSize];
//
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmAES,
kCCOptionPKCS7Padding,
[key bytes],
[key length],
[iv bytes],
[actualCiphertext bytes],
[actualCiphertext length],
[decryptedData mutableBytes],
[decryptedData length],
&decryptedSize);
if (cryptStatus != kCCSuccess) {
if (error) {
*error = [NSError errorWithDomain:ALICLOUD_HTTPDNS_ERROR_DOMAIN
code:ALICLOUD_HTTPDNS_ENCRYPT_FAILED_ERROR_CODE
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Decryption failed with status: %d", cryptStatus]}];
}
return nil;
}
//
[decryptedData setLength:decryptedSize];
return decryptedData;
}
+ (void)processCustomTTL:(HttpdnsHostObject *)hostObject forHost:(NSString *)host {
[self processCustomTTL:hostObject forHost:host service:[HttpDnsService sharedInstance]];
}
+ (void)processCustomTTL:(HttpdnsHostObject *)hostObject forHost:(NSString *)host service:(HttpDnsService *)service {
if (!hostObject || !host) {
return;
}
HttpDnsService *dnsService = service ?: [HttpDnsService sharedInstance];
if (dnsService.ttlDelegate && [dnsService.ttlDelegate respondsToSelector:@selector(httpdnsHost:ipType:ttl:)]) {
if ([self isNotEmptyArray:[hostObject getV4Ips]]) {
int64_t customV4TTL = [dnsService.ttlDelegate httpdnsHost:host ipType:AlicloudHttpDNS_IPTypeV4 ttl:hostObject.v4ttl];
if (customV4TTL > 0) {
hostObject.v4ttl = customV4TTL;
}
}
if ([self isNotEmptyArray:[hostObject getV6Ips]]) {
int64_t customV6TTL = [dnsService.ttlDelegate httpdnsHost:host ipType:AlicloudHttpDNS_IPTypeV6 ttl:hostObject.v6ttl];
if (customV6TTL > 0) {
hostObject.v6ttl = customV6TTL;
}
}
}
}
@end