Statistics
| Branch: | Tag: | Revision:

root / pithos-macos / HashMapHash.m @ 75cecfcc

History | View | Annotate | Download (5.9 kB)

1 f2f50f78 Miltiadis Vasilakis
//
2 f2f50f78 Miltiadis Vasilakis
//  HashMapHash.m
3 f2f50f78 Miltiadis Vasilakis
//  pithos-macos
4 f2f50f78 Miltiadis Vasilakis
//
5 f2f50f78 Miltiadis Vasilakis
// Copyright 2011 GRNET S.A. All rights reserved.
6 f2f50f78 Miltiadis Vasilakis
//
7 f2f50f78 Miltiadis Vasilakis
// Redistribution and use in source and binary forms, with or
8 f2f50f78 Miltiadis Vasilakis
// without modification, are permitted provided that the following
9 f2f50f78 Miltiadis Vasilakis
// conditions are met:
10 f2f50f78 Miltiadis Vasilakis
// 
11 f2f50f78 Miltiadis Vasilakis
//   1. Redistributions of source code must retain the above
12 f2f50f78 Miltiadis Vasilakis
//      copyright notice, this list of conditions and the following
13 f2f50f78 Miltiadis Vasilakis
//      disclaimer.
14 f2f50f78 Miltiadis Vasilakis
// 
15 f2f50f78 Miltiadis Vasilakis
//   2. Redistributions in binary form must reproduce the above
16 f2f50f78 Miltiadis Vasilakis
//      copyright notice, this list of conditions and the following
17 f2f50f78 Miltiadis Vasilakis
//      disclaimer in the documentation and/or other materials
18 f2f50f78 Miltiadis Vasilakis
//      provided with the distribution.
19 f2f50f78 Miltiadis Vasilakis
// 
20 f2f50f78 Miltiadis Vasilakis
// THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
21 f2f50f78 Miltiadis Vasilakis
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 f2f50f78 Miltiadis Vasilakis
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 f2f50f78 Miltiadis Vasilakis
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
24 f2f50f78 Miltiadis Vasilakis
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 f2f50f78 Miltiadis Vasilakis
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 f2f50f78 Miltiadis Vasilakis
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 f2f50f78 Miltiadis Vasilakis
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 f2f50f78 Miltiadis Vasilakis
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 f2f50f78 Miltiadis Vasilakis
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 f2f50f78 Miltiadis Vasilakis
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 f2f50f78 Miltiadis Vasilakis
// POSSIBILITY OF SUCH DAMAGE.
32 f2f50f78 Miltiadis Vasilakis
// 
33 f2f50f78 Miltiadis Vasilakis
// The views and conclusions contained in the software and
34 f2f50f78 Miltiadis Vasilakis
// documentation are those of the authors and should not be
35 f2f50f78 Miltiadis Vasilakis
// interpreted as representing official policies, either expressed
36 f2f50f78 Miltiadis Vasilakis
// or implied, of GRNET S.A.
37 f2f50f78 Miltiadis Vasilakis
38 f2f50f78 Miltiadis Vasilakis
#import "HashMapHash.h"
39 f2f50f78 Miltiadis Vasilakis
#import <CommonCrypto/CommonHMAC.h>
40 f2f50f78 Miltiadis Vasilakis
41 f2f50f78 Miltiadis Vasilakis
@implementation HashMapHash
42 f2f50f78 Miltiadis Vasilakis
43 f2f50f78 Miltiadis Vasilakis
+ (NSString *)calculateHashMapHash:(NSArray *)hashes {
44 f2f50f78 Miltiadis Vasilakis
    const char padding[] = {
45 f2f50f78 Miltiadis Vasilakis
        '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
46 f2f50f78 Miltiadis Vasilakis
        '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'};
47 f2f50f78 Miltiadis Vasilakis
    
48 f2f50f78 Miltiadis Vasilakis
    if ([hashes count] == 0)
49 f2f50f78 Miltiadis Vasilakis
        return [HashMapHash formatHash:[HashMapHash calculateHash:[NSData dataWithBytes:padding length:0]]];
50 f2f50f78 Miltiadis Vasilakis
    if ([hashes count] == 1)
51 1284948f Miltiadis Vasilakis
        return [HashMapHash formatHash:[hashes objectAtIndex:0]];
52 f2f50f78 Miltiadis Vasilakis
    
53 f2f50f78 Miltiadis Vasilakis
    int s = 2;
54 f2f50f78 Miltiadis Vasilakis
    while (s < [hashes count])
55 f2f50f78 Miltiadis Vasilakis
        s = s * 2;
56 f2f50f78 Miltiadis Vasilakis
    
57 f2f50f78 Miltiadis Vasilakis
    NSMutableArray *h = [NSMutableArray array];
58 f2f50f78 Miltiadis Vasilakis
    for (int i = 0; i < [hashes count]; i++)
59 1284948f Miltiadis Vasilakis
        [h addObject:[hashes objectAtIndex:i]];
60 f2f50f78 Miltiadis Vasilakis
    for (int i = 0; i < s - [hashes count]; i++)
61 1284948f Miltiadis Vasilakis
        [h addObject:[NSMutableData dataWithBytes:padding length:32]];
62 f2f50f78 Miltiadis Vasilakis
    
63 f2f50f78 Miltiadis Vasilakis
    while ([h count] > 1) {
64 f2f50f78 Miltiadis Vasilakis
        for (int i = 0; i < [h count]; i = i + 2) {
65 f2f50f78 Miltiadis Vasilakis
            NSMutableData *bytesData = [h objectAtIndex:i];
66 f2f50f78 Miltiadis Vasilakis
            [bytesData appendData:[h objectAtIndex:i + 1]];
67 f2f50f78 Miltiadis Vasilakis
            [h replaceObjectAtIndex:i withObject:[HashMapHash calculateHash:bytesData]];
68 f2f50f78 Miltiadis Vasilakis
        }
69 f2f50f78 Miltiadis Vasilakis
        
70 f2f50f78 Miltiadis Vasilakis
        NSMutableIndexSet *indicesToRemove = [NSMutableIndexSet indexSet];
71 1284948f Miltiadis Vasilakis
        for (int i = 0; i < [h count]; i = i + 2) 
72 f2f50f78 Miltiadis Vasilakis
            [indicesToRemove addIndex:i + 1]; 
73 1284948f Miltiadis Vasilakis
        
74 f2f50f78 Miltiadis Vasilakis
        [h removeObjectsAtIndexes:indicesToRemove];
75 f2f50f78 Miltiadis Vasilakis
    }
76 f2f50f78 Miltiadis Vasilakis
    return [HashMapHash formatHash:[h objectAtIndex:0]];
77 f2f50f78 Miltiadis Vasilakis
}
78 f2f50f78 Miltiadis Vasilakis
79 f2f50f78 Miltiadis Vasilakis
+ (NSData *)calculateHash:(NSData *)data {
80 f2f50f78 Miltiadis Vasilakis
    unsigned char hash[CC_SHA256_DIGEST_LENGTH];
81 f2f50f78 Miltiadis Vasilakis
    CC_SHA256([data bytes], (unsigned int)[data length], hash);
82 f2f50f78 Miltiadis Vasilakis
    return [NSMutableData dataWithBytes:hash length:CC_SHA256_DIGEST_LENGTH];
83 f2f50f78 Miltiadis Vasilakis
}
84 f2f50f78 Miltiadis Vasilakis
85 f2f50f78 Miltiadis Vasilakis
+ (NSString *)formatHash:(NSData *)data {
86 f2f50f78 Miltiadis Vasilakis
    NSString *hashString;
87 f2f50f78 Miltiadis Vasilakis
    hashString = [NSString stringWithFormat:@"%@", data];
88 f2f50f78 Miltiadis Vasilakis
    hashString = [hashString stringByReplacingOccurrencesOfString:@" " withString:@""];
89 f2f50f78 Miltiadis Vasilakis
    hashString = [hashString stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
90 f2f50f78 Miltiadis Vasilakis
    return hashString;
91 f2f50f78 Miltiadis Vasilakis
}
92 f2f50f78 Miltiadis Vasilakis
93 f2f50f78 Miltiadis Vasilakis
// XXX hardcoded hash algorithm for now
94 f2f50f78 Miltiadis Vasilakis
+ (NSArray *)calculateObjectHashMap:(NSString *)filePath withBlockHash:(NSString *)blockHash andBlockSize:(NSUInteger)blockSize {
95 f2f50f78 Miltiadis Vasilakis
    NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:filePath];
96 f2f50f78 Miltiadis Vasilakis
    if (fh == nil) {
97 f2f50f78 Miltiadis Vasilakis
        NSLog(@"failed to open file: %@", filePath);
98 f2f50f78 Miltiadis Vasilakis
        return nil;
99 f2f50f78 Miltiadis Vasilakis
    }
100 f2f50f78 Miltiadis Vasilakis
    
101 f2f50f78 Miltiadis Vasilakis
    NSFileManager *fm = [NSFileManager defaultManager];
102 f2f50f78 Miltiadis Vasilakis
    NSDictionary *attributes = [fm attributesOfItemAtPath:filePath error:nil];
103 f2f50f78 Miltiadis Vasilakis
    NSUInteger endOfFile = [attributes fileSize];
104 f2f50f78 Miltiadis Vasilakis
    
105 f2f50f78 Miltiadis Vasilakis
    NSUInteger fileOffset = 0;
106 f2f50f78 Miltiadis Vasilakis
    [fh seekToFileOffset:fileOffset];
107 f2f50f78 Miltiadis Vasilakis
    
108 f2f50f78 Miltiadis Vasilakis
    NSMutableArray *hashes = [[[NSMutableArray alloc] init] autorelease];
109 f2f50f78 Miltiadis Vasilakis
    
110 f2f50f78 Miltiadis Vasilakis
    while(fileOffset < endOfFile){
111 f2f50f78 Miltiadis Vasilakis
        NSData *data = [fh readDataOfLength:blockSize];
112 f2f50f78 Miltiadis Vasilakis
        
113 f2f50f78 Miltiadis Vasilakis
        // Strip trailing slashes.
114 f2f50f78 Miltiadis Vasilakis
        const char *bytes = [data bytes];
115 f2f50f78 Miltiadis Vasilakis
        NSInteger i;
116 f2f50f78 Miltiadis Vasilakis
        for (i = [data length] - 1; i >= 0; i--)
117 f2f50f78 Miltiadis Vasilakis
            if (bytes[i] != '\0')
118 f2f50f78 Miltiadis Vasilakis
                break;
119 572efb9e Miltiadis Vasilakis
        if (i != [data length] - 1) {
120 572efb9e Miltiadis Vasilakis
            if (i >= 0)
121 572efb9e Miltiadis Vasilakis
                data = [data subdataWithRange:NSMakeRange(0, i + 1)];
122 572efb9e Miltiadis Vasilakis
            else
123 572efb9e Miltiadis Vasilakis
                data = [NSData data];
124 572efb9e Miltiadis Vasilakis
        }
125 f2f50f78 Miltiadis Vasilakis
        
126 f2f50f78 Miltiadis Vasilakis
        unsigned char hash[CC_SHA256_DIGEST_LENGTH];
127 f2f50f78 Miltiadis Vasilakis
        
128 f2f50f78 Miltiadis Vasilakis
        if ( CC_SHA256([data bytes], (unsigned int)[data length], hash) ) {
129 1284948f Miltiadis Vasilakis
            NSData *sha256 = [NSMutableData dataWithBytes:hash length:CC_SHA256_DIGEST_LENGTH];
130 1284948f Miltiadis Vasilakis
            [hashes addObject:sha256];
131 f2f50f78 Miltiadis Vasilakis
        }
132 f2f50f78 Miltiadis Vasilakis
        
133 f2f50f78 Miltiadis Vasilakis
        fileOffset += blockSize;
134 f2f50f78 Miltiadis Vasilakis
        [fh seekToFileOffset:fileOffset];
135 f2f50f78 Miltiadis Vasilakis
    }
136 f2f50f78 Miltiadis Vasilakis
    
137 f2f50f78 Miltiadis Vasilakis
    [fh closeFile];
138 f2f50f78 Miltiadis Vasilakis
    
139 f2f50f78 Miltiadis Vasilakis
    NSArray *hashMap = [NSArray arrayWithArray:hashes];
140 f2f50f78 Miltiadis Vasilakis
    
141 f2f50f78 Miltiadis Vasilakis
    return hashMap;
142 f2f50f78 Miltiadis Vasilakis
}
143 f2f50f78 Miltiadis Vasilakis
144 1284948f Miltiadis Vasilakis
+ (NSArray *)objectHashMapStrings:(NSString *)filePath withBlockHash:(NSString *)blockHash andBlockSize:(NSUInteger)blockSize {
145 1284948f Miltiadis Vasilakis
    NSArray *hashHexes = [HashMapHash calculateObjectHashMap:filePath withBlockHash:blockHash andBlockSize:blockSize];
146 1284948f Miltiadis Vasilakis
    if (hashHexes == nil)
147 1284948f Miltiadis Vasilakis
        return nil;
148 1284948f Miltiadis Vasilakis
    
149 1284948f Miltiadis Vasilakis
    NSMutableArray *hashStrings = [[[NSMutableArray alloc] init] autorelease];
150 1284948f Miltiadis Vasilakis
    
151 1284948f Miltiadis Vasilakis
    for (NSData *hashHex in hashHexes) {
152 1284948f Miltiadis Vasilakis
        [hashStrings addObject:[HashMapHash formatHash:hashHex]];
153 1284948f Miltiadis Vasilakis
    }
154 1284948f Miltiadis Vasilakis
    
155 1284948f Miltiadis Vasilakis
    NSArray *hashMap = [NSArray arrayWithArray:hashStrings];
156 1284948f Miltiadis Vasilakis
    return hashMap;
157 1284948f Miltiadis Vasilakis
}
158 1284948f Miltiadis Vasilakis
159 f2f50f78 Miltiadis Vasilakis
@end