mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-03 09:45:10 +08:00
* Builds on work started by @OpenFibers. * Should eliminate all cache warnings. * Added FileMD5Hash library for efficiently computing MD5 for files * Extended RKParams to return composite MD5 for all attachments * Implemented MD5 method on each RKParamsAttachment instance * Updated RKRequest to utilize new MD5 sums and enabled cache keys for RKParams
121 lines
3.7 KiB
C
121 lines
3.7 KiB
C
/*
|
|
* FileMD5Hash.c
|
|
* FileMD5Hash
|
|
*
|
|
* Copyright © 2010 Joel Lopes Da Silva. All rights reserved.
|
|
*
|
|
* Licensed 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.
|
|
*
|
|
*/
|
|
|
|
//---------------------------------------------------------
|
|
// Includes
|
|
//---------------------------------------------------------
|
|
|
|
// Header file
|
|
#include "FileMD5Hash.h"
|
|
|
|
// Standard library
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
|
|
// Core Foundation
|
|
#include <CoreFoundation/CoreFoundation.h>
|
|
|
|
// Cryptography
|
|
#include <CommonCrypto/CommonDigest.h>
|
|
|
|
|
|
//---------------------------------------------------------
|
|
// Function definition
|
|
//---------------------------------------------------------
|
|
|
|
CFStringRef FileMD5HashCreateWithPath(CFStringRef filePath,
|
|
size_t chunkSizeForReadingData) {
|
|
|
|
// Declare needed variables
|
|
CFStringRef result = NULL;
|
|
CFReadStreamRef readStream = NULL;
|
|
|
|
// Get the file URL
|
|
CFURLRef fileURL =
|
|
CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
|
|
(CFStringRef)filePath,
|
|
kCFURLPOSIXPathStyle,
|
|
(Boolean)false);
|
|
if (!fileURL) goto done;
|
|
|
|
// Create and open the read stream
|
|
readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault,
|
|
(CFURLRef)fileURL);
|
|
if (!readStream) goto done;
|
|
bool didSucceed = (bool)CFReadStreamOpen(readStream);
|
|
if (!didSucceed) goto done;
|
|
|
|
// Initialize the hash object
|
|
CC_MD5_CTX hashObject;
|
|
CC_MD5_Init(&hashObject);
|
|
|
|
// Make sure chunkSizeForReadingData is valid
|
|
if (!chunkSizeForReadingData) {
|
|
chunkSizeForReadingData = FileHashDefaultChunkSizeForReadingData;
|
|
}
|
|
|
|
// Feed the data to the hash object
|
|
bool hasMoreData = true;
|
|
while (hasMoreData) {
|
|
uint8_t buffer[chunkSizeForReadingData];
|
|
CFIndex readBytesCount = CFReadStreamRead(readStream,
|
|
(UInt8 *)buffer,
|
|
(CFIndex)sizeof(buffer));
|
|
if (readBytesCount == -1) break;
|
|
if (readBytesCount == 0) {
|
|
hasMoreData = false;
|
|
continue;
|
|
}
|
|
CC_MD5_Update(&hashObject,
|
|
(const void *)buffer,
|
|
(CC_LONG)readBytesCount);
|
|
}
|
|
|
|
// Check if the read operation succeeded
|
|
didSucceed = !hasMoreData;
|
|
|
|
// Compute the hash digest
|
|
unsigned char digest[CC_MD5_DIGEST_LENGTH];
|
|
CC_MD5_Final(digest, &hashObject);
|
|
|
|
// Abort if the read operation failed
|
|
if (!didSucceed) goto done;
|
|
|
|
// Compute the string result
|
|
char hash[2 * sizeof(digest) + 1];
|
|
for (size_t i = 0; i < sizeof(digest); ++i) {
|
|
snprintf(hash + (2 * i), 3, "%02x", (int)(digest[i]));
|
|
}
|
|
result = CFStringCreateWithCString(kCFAllocatorDefault,
|
|
(const char *)hash,
|
|
kCFStringEncodingUTF8);
|
|
|
|
done:
|
|
|
|
if (readStream) {
|
|
CFReadStreamClose(readStream);
|
|
CFRelease(readStream);
|
|
}
|
|
if (fileURL) {
|
|
CFRelease(fileURL);
|
|
}
|
|
return result;
|
|
}
|