From 7b02207537d35bfa1714bf8beafc921f717d100a Mon Sep 17 00:00:00 2001
From: 单军华
Date: Wed, 11 Jul 2018 10:47:42 +0800
Subject: [PATCH] 首次上传

---
 screendisplay/Pods/ASIHTTPRequest/Classes/ASIDownloadCache.m |  514 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 514 insertions(+), 0 deletions(-)

diff --git a/screendisplay/Pods/ASIHTTPRequest/Classes/ASIDownloadCache.m b/screendisplay/Pods/ASIHTTPRequest/Classes/ASIDownloadCache.m
new file mode 100755
index 0000000..93da36f
--- /dev/null
+++ b/screendisplay/Pods/ASIHTTPRequest/Classes/ASIDownloadCache.m
@@ -0,0 +1,514 @@
+//
+//  ASIDownloadCache.m
+//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
+//
+//  Created by Ben Copsey on 01/05/2010.
+//  Copyright 2010 All-Seeing Interactive. All rights reserved.
+//
+
+#import "ASIDownloadCache.h"
+#import "ASIHTTPRequest.h"
+#import <CommonCrypto/CommonHMAC.h>
+
+static ASIDownloadCache *sharedCache = nil;
+
+static NSString *sessionCacheFolder = @"SessionStore";
+static NSString *permanentCacheFolder = @"PermanentStore";
+static NSArray *fileExtensionsToHandleAsHTML = nil;
+
+@interface ASIDownloadCache ()
++ (NSString *)keyForURL:(NSURL *)url;
+- (NSString *)pathToFile:(NSString *)file;
+@end
+
+@implementation ASIDownloadCache
+
++ (void)initialize
+{
+	if (self == [ASIDownloadCache class]) {
+		// Obviously this is not an exhaustive list, but hopefully these are the most commonly used and this will 'just work' for the widest range of people
+		// I imagine many web developers probably use url rewriting anyway
+		fileExtensionsToHandleAsHTML = [[NSArray alloc] initWithObjects:@"asp",@"aspx",@"jsp",@"php",@"rb",@"py",@"pl",@"cgi", nil];
+	}
+}
+
+- (id)init
+{
+	self = [super init];
+	[self setShouldRespectCacheControlHeaders:YES];
+	[self setDefaultCachePolicy:ASIUseDefaultCachePolicy];
+	[self setAccessLock:[[[NSRecursiveLock alloc] init] autorelease]];
+	return self;
+}
+
++ (id)sharedCache
+{
+	if (!sharedCache) {
+		@synchronized(self) {
+			if (!sharedCache) {
+				sharedCache = [[self alloc] init];
+				[sharedCache setStoragePath:[[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"ASIHTTPRequestCache"]];
+			}
+		}
+	}
+	return sharedCache;
+}
+
+- (void)dealloc
+{
+	[storagePath release];
+	[accessLock release];
+	[super dealloc];
+}
+
+- (NSString *)storagePath
+{
+	[[self accessLock] lock];
+	NSString *p = [[storagePath retain] autorelease];
+	[[self accessLock] unlock];
+	return p;
+}
+
+
+- (void)setStoragePath:(NSString *)path
+{
+	[[self accessLock] lock];
+	[self clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
+	[storagePath release];
+	storagePath = [path retain];
+
+	NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
+
+	BOOL isDirectory = NO;
+	NSArray *directories = [NSArray arrayWithObjects:path,[path stringByAppendingPathComponent:sessionCacheFolder],[path stringByAppendingPathComponent:permanentCacheFolder],nil];
+	for (NSString *directory in directories) {
+		BOOL exists = [fileManager fileExistsAtPath:directory isDirectory:&isDirectory];
+		if (exists && !isDirectory) {
+			[[self accessLock] unlock];
+			[NSException raise:@"FileExistsAtCachePath" format:@"Cannot create a directory for the cache at '%@', because a file already exists",directory];
+		} else if (!exists) {
+			[fileManager createDirectoryAtPath:directory withIntermediateDirectories:NO attributes:nil error:nil];
+			if (![fileManager fileExistsAtPath:directory]) {
+				[[self accessLock] unlock];
+				[NSException raise:@"FailedToCreateCacheDirectory" format:@"Failed to create a directory for the cache at '%@'",directory];
+			}
+		}
+	}
+	[self clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
+	[[self accessLock] unlock];
+}
+
+- (void)updateExpiryForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge
+{
+	NSString *headerPath = [self pathToStoreCachedResponseHeadersForRequest:request];
+	NSMutableDictionary *cachedHeaders = [NSMutableDictionary dictionaryWithContentsOfFile:headerPath];
+	if (!cachedHeaders) {
+		return;
+	}
+	NSDate *expires = [self expiryDateForRequest:request maxAge:maxAge];
+	if (!expires) {
+		return;
+	}
+	[cachedHeaders setObject:[NSNumber numberWithDouble:[expires timeIntervalSince1970]] forKey:@"X-ASIHTTPRequest-Expires"];
+	[cachedHeaders writeToFile:headerPath atomically:NO];
+}
+
+- (NSDate *)expiryDateForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge
+{
+  return [ASIHTTPRequest expiryDateForRequest:request maxAge:maxAge];
+}
+
+- (void)storeResponseForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge
+{
+	[[self accessLock] lock];
+
+	if ([request error] || ![request responseHeaders] || ([request cachePolicy] & ASIDoNotWriteToCacheCachePolicy)) {
+		[[self accessLock] unlock];
+		return;
+	}
+
+	// We only cache 200/OK or redirect reponses (redirect responses are cached so the cache works better with no internet connection)
+	int responseCode = [request responseStatusCode];
+	if (responseCode != 200 && responseCode != 301 && responseCode != 302 && responseCode != 303 && responseCode != 307) {
+		[[self accessLock] unlock];
+		return;
+	}
+
+	if ([self shouldRespectCacheControlHeaders] && ![[self class] serverAllowsResponseCachingForRequest:request]) {
+		[[self accessLock] unlock];
+		return;
+	}
+
+	NSString *headerPath = [self pathToStoreCachedResponseHeadersForRequest:request];
+	NSString *dataPath = [self pathToStoreCachedResponseDataForRequest:request];
+
+	NSMutableDictionary *responseHeaders = [NSMutableDictionary dictionaryWithDictionary:[request responseHeaders]];
+	if ([request isResponseCompressed]) {
+		[responseHeaders removeObjectForKey:@"Content-Encoding"];
+	}
+
+	// Create a special 'X-ASIHTTPRequest-Expires' header
+	// This is what we use for deciding if cached data is current, rather than parsing the expires / max-age headers individually each time
+	// We store this as a timestamp to make reading it easier as NSDateFormatter is quite expensive
+
+	NSDate *expires = [self expiryDateForRequest:request maxAge:maxAge];
+	if (expires) {
+		[responseHeaders setObject:[NSNumber numberWithDouble:[expires timeIntervalSince1970]] forKey:@"X-ASIHTTPRequest-Expires"];
+	}
+
+	// Store the response code in a custom header so we can reuse it later
+
+	// We'll change 304/Not Modified to 200/OK because this is likely to be us updating the cached headers with a conditional GET
+	int statusCode = [request responseStatusCode];
+	if (statusCode == 304) {
+		statusCode = 200;
+	}
+	[responseHeaders setObject:[NSNumber numberWithInt:statusCode] forKey:@"X-ASIHTTPRequest-Response-Status-Code"];
+
+	[responseHeaders writeToFile:headerPath atomically:NO];
+
+	if ([request responseData]) {
+		[[request responseData] writeToFile:dataPath atomically:NO];
+	} else if ([request downloadDestinationPath] && ![[request downloadDestinationPath] isEqualToString:dataPath]) {        
+		NSError *error = nil;
+        NSFileManager* manager = [[NSFileManager alloc] init];
+        if ([manager fileExistsAtPath:dataPath]) {
+            [manager removeItemAtPath:dataPath error:&error];
+        }
+        [manager copyItemAtPath:[request downloadDestinationPath] toPath:dataPath error:&error];
+        [manager release];
+	}
+	[[self accessLock] unlock];
+}
+
+- (NSDictionary *)cachedResponseHeadersForURL:(NSURL *)url
+{
+	NSString *path = [self pathToCachedResponseHeadersForURL:url];
+	if (path) {
+		return [NSDictionary dictionaryWithContentsOfFile:path];
+	}
+	return nil;
+}
+
+- (NSData *)cachedResponseDataForURL:(NSURL *)url
+{
+	NSString *path = [self pathToCachedResponseDataForURL:url];
+	if (path) {
+		return [NSData dataWithContentsOfFile:path];
+	}
+	return nil;
+}
+
+- (NSString *)pathToCachedResponseDataForURL:(NSURL *)url
+{
+	// Grab the file extension, if there is one. We do this so we can save the cached response with the same file extension - this is important if you want to display locally cached data in a web view 
+	NSString *extension = [[url path] pathExtension];
+
+	// If the url doesn't have an extension, we'll add one so a webview can read it when locally cached
+	// If the url has the extension of a common web scripting language, we'll change the extension on the cached path to html for the same reason
+	if (![extension length] || [[[self class] fileExtensionsToHandleAsHTML] containsObject:[extension lowercaseString]]) {
+		extension = @"html";
+	}
+	return [self pathToFile:[[[self class] keyForURL:url] stringByAppendingPathExtension:extension]];
+}
+
++ (NSArray *)fileExtensionsToHandleAsHTML
+{
+	return fileExtensionsToHandleAsHTML;
+}
+
+
+- (NSString *)pathToCachedResponseHeadersForURL:(NSURL *)url
+{
+	return [self pathToFile:[[[self class] keyForURL:url] stringByAppendingPathExtension:@"cachedheaders"]];
+}
+
+- (NSString *)pathToFile:(NSString *)file
+{
+	[[self accessLock] lock];
+	if (![self storagePath]) {
+		[[self accessLock] unlock];
+		return nil;
+	}
+
+	NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
+
+	// Look in the session store
+	NSString *dataPath = [[[self storagePath] stringByAppendingPathComponent:sessionCacheFolder] stringByAppendingPathComponent:file];
+	if ([fileManager fileExistsAtPath:dataPath]) {
+		[[self accessLock] unlock];
+		return dataPath;
+	}
+	// Look in the permanent store
+	dataPath = [[[self storagePath] stringByAppendingPathComponent:permanentCacheFolder] stringByAppendingPathComponent:file];
+	if ([fileManager fileExistsAtPath:dataPath]) {
+		[[self accessLock] unlock];
+		return dataPath;
+	}
+	[[self accessLock] unlock];
+	return nil;
+}
+
+
+- (NSString *)pathToStoreCachedResponseDataForRequest:(ASIHTTPRequest *)request
+{
+	[[self accessLock] lock];
+	if (![self storagePath]) {
+		[[self accessLock] unlock];
+		return nil;
+	}
+
+	NSString *path = [[self storagePath] stringByAppendingPathComponent:([request cacheStoragePolicy] == ASICacheForSessionDurationCacheStoragePolicy ? sessionCacheFolder : permanentCacheFolder)];
+
+	// Grab the file extension, if there is one. We do this so we can save the cached response with the same file extension - this is important if you want to display locally cached data in a web view 
+	NSString *extension = [[[request url] path] pathExtension];
+
+	// If the url doesn't have an extension, we'll add one so a webview can read it when locally cached
+	// If the url has the extension of a common web scripting language, we'll change the extension on the cached path to html for the same reason
+	if (![extension length] || [[[self class] fileExtensionsToHandleAsHTML] containsObject:[extension lowercaseString]]) {
+		extension = @"html";
+	}
+	path =  [path stringByAppendingPathComponent:[[[self class] keyForURL:[request url]] stringByAppendingPathExtension:extension]];
+	[[self accessLock] unlock];
+	return path;
+}
+
+- (NSString *)pathToStoreCachedResponseHeadersForRequest:(ASIHTTPRequest *)request
+{
+	[[self accessLock] lock];
+	if (![self storagePath]) {
+		[[self accessLock] unlock];
+		return nil;
+	}
+	NSString *path = [[self storagePath] stringByAppendingPathComponent:([request cacheStoragePolicy] == ASICacheForSessionDurationCacheStoragePolicy ? sessionCacheFolder : permanentCacheFolder)];
+	path =  [path stringByAppendingPathComponent:[[[self class] keyForURL:[request url]] stringByAppendingPathExtension:@"cachedheaders"]];
+	[[self accessLock] unlock];
+	return path;
+}
+
+- (void)removeCachedDataForURL:(NSURL *)url
+{
+	[[self accessLock] lock];
+	if (![self storagePath]) {
+		[[self accessLock] unlock];
+		return;
+	}
+	NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
+
+	NSString *path = [self pathToCachedResponseHeadersForURL:url];
+	if (path) {
+		[fileManager removeItemAtPath:path error:NULL];
+	}
+
+	path = [self pathToCachedResponseDataForURL:url];
+	if (path) {
+		[fileManager removeItemAtPath:path error:NULL];
+	}
+	[[self accessLock] unlock];
+}
+
+- (void)removeCachedDataForRequest:(ASIHTTPRequest *)request
+{
+	[self removeCachedDataForURL:[request url]];
+}
+
+- (BOOL)isCachedDataCurrentForRequest:(ASIHTTPRequest *)request
+{
+	[[self accessLock] lock];
+	if (![self storagePath]) {
+		[[self accessLock] unlock];
+		return NO;
+	}
+	NSDictionary *cachedHeaders = [self cachedResponseHeadersForURL:[request url]];
+	if (!cachedHeaders) {
+		[[self accessLock] unlock];
+		return NO;
+	}
+	NSString *dataPath = [self pathToCachedResponseDataForURL:[request url]];
+	if (!dataPath) {
+		[[self accessLock] unlock];
+		return NO;
+	}
+
+	// New content is not different
+	if ([request responseStatusCode] == 304) {
+		[[self accessLock] unlock];
+		return YES;
+	}
+
+	// If we already have response headers for this request, check to see if the new content is different
+	// We check [request complete] so that we don't end up comparing response headers from a redirection with these
+	if ([request responseHeaders] && [request complete]) {
+
+		// If the Etag or Last-Modified date are different from the one we have, we'll have to fetch this resource again
+		NSArray *headersToCompare = [NSArray arrayWithObjects:@"Etag",@"Last-Modified",nil];
+		for (NSString *header in headersToCompare) {
+			if (![[[request responseHeaders] objectForKey:header] isEqualToString:[cachedHeaders objectForKey:header]]) {
+				[[self accessLock] unlock];
+				return NO;
+			}
+		}
+	}
+
+	if ([self shouldRespectCacheControlHeaders]) {
+
+		// Look for X-ASIHTTPRequest-Expires header to see if the content is out of date
+		NSNumber *expires = [cachedHeaders objectForKey:@"X-ASIHTTPRequest-Expires"];
+		if (expires) {
+			if ([[NSDate dateWithTimeIntervalSince1970:[expires doubleValue]] timeIntervalSinceNow] >= 0) {
+				[[self accessLock] unlock];
+				return YES;
+			}
+		}
+
+		// No explicit expiration time sent by the server
+		[[self accessLock] unlock];
+		return NO;
+	}
+	
+
+	[[self accessLock] unlock];
+	return YES;
+}
+
+- (ASICachePolicy)defaultCachePolicy
+{
+	[[self accessLock] lock];
+	ASICachePolicy cp = defaultCachePolicy;
+	[[self accessLock] unlock];
+	return cp;
+}
+
+
+- (void)setDefaultCachePolicy:(ASICachePolicy)cachePolicy
+{
+	[[self accessLock] lock];
+	if (!cachePolicy) {
+		defaultCachePolicy = ASIAskServerIfModifiedWhenStaleCachePolicy;
+	}  else {
+		defaultCachePolicy = cachePolicy;	
+	}
+	[[self accessLock] unlock];
+}
+
+- (void)clearCachedResponsesForStoragePolicy:(ASICacheStoragePolicy)storagePolicy
+{
+	[[self accessLock] lock];
+	if (![self storagePath]) {
+		[[self accessLock] unlock];
+		return;
+	}
+	NSString *path = [[self storagePath] stringByAppendingPathComponent:(storagePolicy == ASICacheForSessionDurationCacheStoragePolicy ? sessionCacheFolder : permanentCacheFolder)];
+
+	NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
+
+	BOOL isDirectory = NO;
+	BOOL exists = [fileManager fileExistsAtPath:path isDirectory:&isDirectory];
+	if (!exists || !isDirectory) {
+		[[self accessLock] unlock];
+		return;
+	}
+	NSError *error = nil;
+	NSArray *cacheFiles = [fileManager contentsOfDirectoryAtPath:path error:&error];
+	if (error) {
+		[[self accessLock] unlock];
+		[NSException raise:@"FailedToTraverseCacheDirectory" format:@"Listing cache directory failed at path '%@'",path];	
+	}
+	for (NSString *file in cacheFiles) {
+		[fileManager removeItemAtPath:[path stringByAppendingPathComponent:file] error:&error];
+		if (error) {
+			[[self accessLock] unlock];
+			[NSException raise:@"FailedToRemoveCacheFile" format:@"Failed to remove cached data at path '%@'",path];
+		}
+	}
+	[[self accessLock] unlock];
+}
+
++ (BOOL)serverAllowsResponseCachingForRequest:(ASIHTTPRequest *)request
+{
+	NSString *cacheControl = [[[request responseHeaders] objectForKey:@"Cache-Control"] lowercaseString];
+	if (cacheControl) {
+		if ([cacheControl isEqualToString:@"no-cache"] || [cacheControl isEqualToString:@"no-store"]) {
+			return NO;
+		}
+	}
+	NSString *pragma = [[[request responseHeaders] objectForKey:@"Pragma"] lowercaseString];
+	if (pragma) {
+		if ([pragma isEqualToString:@"no-cache"]) {
+			return NO;
+		}
+	}
+	return YES;
+}
+
++ (NSString *)keyForURL:(NSURL *)url
+{
+	NSString *urlString = [url absoluteString];
+	if ([urlString length] == 0) {
+		return nil;
+	}
+
+	// Strip trailing slashes so http://allseeing-i.com/ASIHTTPRequest/ is cached the same as http://allseeing-i.com/ASIHTTPRequest
+	if ([[urlString substringFromIndex:[urlString length]-1] isEqualToString:@"/"]) {
+		urlString = [urlString substringToIndex:[urlString length]-1];
+	}
+
+	// Borrowed from: http://stackoverflow.com/questions/652300/using-md5-hash-on-a-string-in-cocoa
+	const char *cStr = [urlString UTF8String];
+	unsigned char result[16];
+	CC_MD5(cStr, (CC_LONG)strlen(cStr), result);
+	return [NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],result[8], result[9], result[10], result[11],result[12], result[13], result[14], result[15]]; 	
+}
+
+- (BOOL)canUseCachedDataForRequest:(ASIHTTPRequest *)request
+{
+	// Ensure the request is allowed to read from the cache
+	if ([request cachePolicy] & ASIDoNotReadFromCacheCachePolicy) {
+		return NO;
+
+	// If we don't want to load the request whatever happens, always pretend we have cached data even if we don't
+	} else if ([request cachePolicy] & ASIDontLoadCachePolicy) {
+		return YES;
+	}
+
+	NSDictionary *headers = [self cachedResponseHeadersForURL:[request url]];
+	if (!headers) {
+		return NO;
+	}
+	NSString *dataPath = [self pathToCachedResponseDataForURL:[request url]];
+	if (!dataPath) {
+		return NO;
+	}
+
+	// If we get here, we have cached data
+
+	// If we have cached data, we can use it
+	if ([request cachePolicy] & ASIOnlyLoadIfNotCachedCachePolicy) {
+		return YES;
+
+	// If we want to fallback to the cache after an error
+	} else if ([request complete] && [request cachePolicy] & ASIFallbackToCacheIfLoadFailsCachePolicy) {
+		return YES;
+
+	// If we have cached data that is current, we can use it
+	} else if ([request cachePolicy] & ASIAskServerIfModifiedWhenStaleCachePolicy) {
+		if ([self isCachedDataCurrentForRequest:request]) {
+			return YES;
+		}
+
+	// If we've got headers from a conditional GET and the cached data is still current, we can use it
+	} else if ([request cachePolicy] & ASIAskServerIfModifiedCachePolicy) {
+		if (![request responseHeaders]) {
+			return NO;
+		} else if ([self isCachedDataCurrentForRequest:request]) {
+			return YES;
+		}
+	}
+	return NO;
+}
+
+@synthesize storagePath;
+@synthesize defaultCachePolicy;
+@synthesize accessLock;
+@synthesize shouldRespectCacheControlHeaders;
+@end

--
Gitblit v1.8.0