mirror of
https://github.com/zhigang1992/react-native-code-push.git
synced 2026-06-16 19:51:57 +08:00
verify hash after download ios
This commit is contained in:
156
iOS/CodePushUtils.m
Normal file
156
iOS/CodePushUtils.m
Normal file
@@ -0,0 +1,156 @@
|
||||
#import "CodePush.h"
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
|
||||
@implementation CodePushUtils
|
||||
|
||||
+ (void)addContentsOfFolderToManifest:(NSString *)folderPath
|
||||
pathPrefix:(NSString *)pathPrefix
|
||||
manifest:(NSMutableArray *)manifest
|
||||
error:(NSError **)error
|
||||
{
|
||||
NSArray* folderFiles = [[NSFileManager defaultManager]
|
||||
contentsOfDirectoryAtPath:folderPath
|
||||
error:error];
|
||||
if (*error) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (NSString *fileName in folderFiles) {
|
||||
NSString *fullFilePath = [folderPath stringByAppendingPathComponent:fileName];
|
||||
NSString *relativePath = [pathPrefix stringByAppendingPathComponent:fileName];
|
||||
BOOL isDir = NO;
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:fullFilePath
|
||||
isDirectory:&isDir] && isDir) {
|
||||
[self addContentsOfFolderToManifest:fullFilePath
|
||||
pathPrefix:relativePath
|
||||
manifest:manifest
|
||||
error:error];
|
||||
if (*error) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
NSData *fileContents = [NSData dataWithContentsOfFile:fullFilePath];
|
||||
NSString *fileContentsHash = [self computeHash:fileContents];
|
||||
[manifest addObject:[[relativePath stringByAppendingString:@":"] stringByAppendingString:fileContentsHash]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSString *)computeHash:(NSData *)inputData
|
||||
{
|
||||
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
|
||||
CC_SHA256(inputData.bytes, inputData.length, digest);
|
||||
NSMutableString* inputHash = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
|
||||
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
|
||||
[inputHash appendFormat:@"%02x", digest[i]];
|
||||
}
|
||||
|
||||
return inputHash;
|
||||
}
|
||||
|
||||
+ (void)copyEntriesInFolder:(NSString *)sourceFolder
|
||||
destFolder:(NSString *)destFolder
|
||||
error:(NSError **)error
|
||||
{
|
||||
NSArray* files = [[NSFileManager defaultManager]
|
||||
contentsOfDirectoryAtPath:sourceFolder
|
||||
error:error];
|
||||
if (*error) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (NSString *fileName in files) {
|
||||
NSString * fullFilePath = [sourceFolder stringByAppendingPathComponent:fileName];
|
||||
BOOL isDir = NO;
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:fullFilePath
|
||||
isDirectory:&isDir] && isDir) {
|
||||
NSString *nestedDestFolder = [destFolder stringByAppendingPathComponent:fileName];
|
||||
[self copyEntriesInFolder:fullFilePath
|
||||
destFolder:nestedDestFolder
|
||||
error:error];
|
||||
} else {
|
||||
NSString *destFileName = [destFolder stringByAppendingPathComponent:fileName];
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:destFileName]) {
|
||||
[[NSFileManager defaultManager] removeItemAtPath:destFileName error:error];
|
||||
if (*error) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:destFolder]) {
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:destFolder
|
||||
withIntermediateDirectories:YES
|
||||
attributes:nil
|
||||
error:error];
|
||||
if (*error) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[[NSFileManager defaultManager] copyItemAtPath:fullFilePath toPath:destFileName error:error];
|
||||
if (*error) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSString *)findMainBundleInFolder:(NSString *)folderPath
|
||||
error:(NSError **)error
|
||||
{
|
||||
NSArray* folderFiles = [[NSFileManager defaultManager]
|
||||
contentsOfDirectoryAtPath:folderPath
|
||||
error:error];
|
||||
if (*error) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
for (NSString *fileName in folderFiles) {
|
||||
NSString *fullFilePath = [folderPath stringByAppendingPathComponent:fileName];
|
||||
BOOL isDir = NO;
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:fullFilePath
|
||||
isDirectory:&isDir] && isDir) {
|
||||
NSString *mainBundlePathInFolder = [self findMainBundleInFolder:fullFilePath error:error];
|
||||
if (*error) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (mainBundlePathInFolder) {
|
||||
return [fileName stringByAppendingPathComponent:mainBundlePathInFolder];
|
||||
}
|
||||
} else if ([[fileName pathExtension] isEqualToString:@"bundle"] ||
|
||||
[[fileName pathExtension] isEqualToString:@"jsbundle"] ||
|
||||
[[fileName pathExtension] isEqualToString:@"js"]) {
|
||||
return fileName;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (BOOL)verifyHashForZipUpdate:(NSString *)finalUpdateFolder
|
||||
expectedHash:(NSString *)expectedHash
|
||||
error:(NSError **)error
|
||||
{
|
||||
NSMutableArray *updateContentsManifest = [NSMutableArray array];
|
||||
[self addContentsOfFolderToManifest:finalUpdateFolder
|
||||
pathPrefix:@""
|
||||
manifest:updateContentsManifest
|
||||
error:error];
|
||||
if (*error) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSArray *sortedUpdateContentsManifest = [updateContentsManifest sortedArrayUsingSelector:@selector(compare:)];
|
||||
NSData *updateContentsManifestData = [NSJSONSerialization dataWithJSONObject:sortedUpdateContentsManifest
|
||||
options:kNilOptions
|
||||
error:error];
|
||||
NSString *updateContentsManifestString = [[NSString alloc] initWithData:updateContentsManifestData
|
||||
encoding:NSUTF8StringEncoding];
|
||||
// The JSON serialization turns path seperators into "\/", e.g. "CodePush\/assets\/image.png"
|
||||
updateContentsManifestString = [updateContentsManifestString stringByReplacingOccurrencesOfString:@"\\/"
|
||||
withString:@"/"];
|
||||
NSString *updateContentsManifestHash = [self computeHash:[NSData dataWithBytes:updateContentsManifestString.UTF8String length:updateContentsManifestString.length]];
|
||||
return [updateContentsManifestHash isEqualToString:expectedHash];
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user