@@ -581,6 +581,15 @@ + (void) readFile:(NSString *)path
581
581
582
582
# pragma mark - hash
583
583
584
+ typedef enum {
585
+ HashAlgorithmMD5,
586
+ HashAlgorithmSHA1,
587
+ HashAlgorithmSHA224,
588
+ HashAlgorithmSHA256,
589
+ HashAlgorithmSHA384,
590
+ HashAlgorithmSHA512,
591
+ } HashAlgorithm;
592
+
584
593
+ (void ) hash : (NSString *)path
585
594
algorithm : (NSString *)algorithm
586
595
resolver : (RCTPromiseResolveBlock)resolve
@@ -611,7 +620,11 @@ + (void) hash:(NSString *)path
611
620
return ;
612
621
}
613
622
614
- NSData *content = [[NSFileManager defaultManager ] contentsAtPath: path];
623
+ NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath: path];
624
+ if (fileHandle == nil ) {
625
+ reject (@" EUNKNOWN" , [NSString stringWithFormat: @" Error opening '%@ ' for reading" , path], error);
626
+ return ;
627
+ }
615
628
616
629
NSArray *keys = [NSArray arrayWithObjects: @" md5" , @" sha1" , @" sha224" , @" sha256" , @" sha384" , @" sha512" , nil ];
617
630
@@ -634,23 +647,97 @@ + (void) hash:(NSString *)path
634
647
635
648
unsigned char buffer[digestLength];
636
649
650
+ const NSUInteger chunkSize = 1024 * 1024 ; // 1 Megabyte
651
+ NSData *dataChunk;
652
+
653
+ CC_MD5_CTX md5Context;
654
+ CC_SHA1_CTX sha1Context;
655
+ CC_SHA256_CTX sha256Context;
656
+ CC_SHA512_CTX sha512Context;
657
+ HashAlgorithm hashAlgorithm;
658
+
637
659
if ([algorithm isEqualToString: @" md5" ]) {
638
- CC_MD5 (content.bytes , (CC_LONG)content.length , buffer);
660
+ CC_MD5_Init (&md5Context);
661
+ hashAlgorithm = HashAlgorithmMD5;
639
662
} else if ([algorithm isEqualToString: @" sha1" ]) {
640
- CC_SHA1 (content.bytes , (CC_LONG)content.length , buffer);
663
+ CC_SHA1_Init (&sha1Context);
664
+ hashAlgorithm = HashAlgorithmSHA1;
641
665
} else if ([algorithm isEqualToString: @" sha224" ]) {
642
- CC_SHA224 (content.bytes , (CC_LONG)content.length , buffer);
666
+ CC_SHA224_Init (&sha256Context);
667
+ hashAlgorithm = HashAlgorithmSHA224;
643
668
} else if ([algorithm isEqualToString: @" sha256" ]) {
644
- CC_SHA256 (content.bytes , (CC_LONG)content.length , buffer);
669
+ CC_SHA256_Init (&sha256Context);
670
+ hashAlgorithm = HashAlgorithmSHA256;
645
671
} else if ([algorithm isEqualToString: @" sha384" ]) {
646
- CC_SHA384 (content.bytes , (CC_LONG)content.length , buffer);
672
+ CC_SHA384_Init (&sha512Context);
673
+ hashAlgorithm = HashAlgorithmSHA384;
647
674
} else if ([algorithm isEqualToString: @" sha512" ]) {
648
- CC_SHA512 (content.bytes , (CC_LONG)content.length , buffer);
675
+ CC_SHA512_Init (&sha512Context);
676
+ hashAlgorithm = HashAlgorithmSHA512;
649
677
} else {
650
678
reject (@" EINVAL" , [NSString stringWithFormat: @" Invalid algorithm '%@ ', must be one of md5, sha1, sha224, sha256, sha384, sha512" , algorithm], nil );
651
679
return ;
652
680
}
653
681
682
+ while (true ) {
683
+ @autoreleasepool {
684
+ dataChunk = [fileHandle readDataUpToLength: chunkSize error: &error];
685
+
686
+ if (error) {
687
+ return reject (@" EREAD" , [NSString stringWithFormat: @" Error reading file '%@ '" , path], error);
688
+ break ;
689
+ }
690
+
691
+ if (dataChunk == nil || dataChunk.length == 0 ) {
692
+ break ;
693
+ }
694
+
695
+ switch (hashAlgorithm) {
696
+ case HashAlgorithmMD5:
697
+ CC_MD5_Update (&md5Context, [dataChunk bytes ], CC_LONG ([dataChunk length ]));
698
+ break ;
699
+ case HashAlgorithmSHA1:
700
+ CC_SHA1_Update (&sha1Context, [dataChunk bytes ], CC_LONG ([dataChunk length ]));
701
+ break ;
702
+ case HashAlgorithmSHA224:
703
+ CC_SHA224_Update (&sha256Context, [dataChunk bytes ], CC_LONG ([dataChunk length ]));
704
+ break ;
705
+ case HashAlgorithmSHA256:
706
+ CC_SHA256_Update (&sha256Context, [dataChunk bytes ], CC_LONG ([dataChunk length ]));
707
+ break ;
708
+ case HashAlgorithmSHA384:
709
+ CC_SHA384_Update (&sha512Context, [dataChunk bytes ], CC_LONG ([dataChunk length ]));
710
+ break ;
711
+ case HashAlgorithmSHA512:
712
+ CC_SHA512_Update (&sha512Context, [dataChunk bytes ], CC_LONG ([dataChunk length ]));
713
+ break ;
714
+ }
715
+
716
+ dataChunk = nil ;
717
+ }
718
+ }
719
+
720
+ switch (hashAlgorithm) {
721
+ case HashAlgorithmMD5:
722
+ CC_MD5_Final (buffer, &md5Context);
723
+ break ;
724
+ case HashAlgorithmSHA1:
725
+ CC_SHA1_Final (buffer, &sha1Context);
726
+ break ;
727
+ case HashAlgorithmSHA224:
728
+ CC_SHA224_Final (buffer, &sha256Context);
729
+ break ;
730
+ case HashAlgorithmSHA256:
731
+ CC_SHA256_Final (buffer, &sha256Context);
732
+ break ;
733
+ case HashAlgorithmSHA384:
734
+ CC_SHA384_Final (buffer, &sha512Context);
735
+ break ;
736
+ case HashAlgorithmSHA512:
737
+ CC_SHA512_Final (buffer, &sha512Context);
738
+ break ;
739
+ }
740
+
654
741
NSMutableString *output = [NSMutableString stringWithCapacity: digestLength * 2 ];
655
742
for (int i = 0 ; i < digestLength; i++)
656
743
[output appendFormat: @" %02x " ,buffer[i]];
0 commit comments