Ben Copsey

Merge branch 'cloudfiles' into integration

Conflicts:
	Classes/ASIHTTPRequest.m
	iPhone.xcodeproj/project.pbxproj
	set_version_number.sh
  1 +//
  2 +// ASICloudFilesCDNRequest.h
  3 +//
  4 +// Created by Michael Mayo on 1/6/10.
  5 +//
  6 +
  7 +#import "ASICloudFilesRequest.h"
  8 +
  9 +@class ASICloudFilesContainerXMLParserDelegate;
  10 +
  11 +@interface ASICloudFilesCDNRequest : ASICloudFilesRequest {
  12 + NSString *accountName;
  13 + NSString *containerName;
  14 + ASICloudFilesContainerXMLParserDelegate *xmlParserDelegate;
  15 +
  16 +}
  17 +
  18 +@property (nonatomic, retain) NSString *accountName;
  19 +@property (nonatomic, retain) NSString *containerName;
  20 +@property (nonatomic, retain) ASICloudFilesContainerXMLParserDelegate *xmlParserDelegate;
  21 +
  22 +
  23 +// HEAD /<api version>/<account>/<container>
  24 +// Response:
  25 +// X-CDN-Enabled: True
  26 +// X-CDN-URI: http://cdn.cloudfiles.mosso.com/c1234
  27 +// X-CDN-TTL: 86400
  28 ++ (id)containerInfoRequest:(NSString *)containerName;
  29 +- (BOOL)cdnEnabled;
  30 +- (NSString *)cdnURI;
  31 +- (NSUInteger)cdnTTL;
  32 +
  33 +
  34 +// GET /<api version>/<account>
  35 +// limit, marker, format, enabled_only=true
  36 ++ (id)listRequest;
  37 ++ (id)listRequestWithLimit:(NSUInteger)limit marker:(NSString *)marker enabledOnly:(BOOL)enabledOnly;
  38 +- (NSArray *)containers;
  39 +
  40 +
  41 +// PUT /<api version>/<account>/<container>
  42 +// PUT operations against a Container are used to CDN-enable that Container.
  43 +// Include an HTTP header of X-TTL to specify a custom TTL.
  44 ++ (id)putRequestWithContainer:(NSString *)containerName;
  45 ++ (id)putRequestWithContainer:(NSString *)containerName ttl:(NSUInteger)ttl;
  46 +// returns: - (NSString *)cdnURI;
  47 +
  48 +// POST /<api version>/<account>/<container>
  49 +// POST operations against a CDN-enabled Container are used to adjust CDN attributes.
  50 +// The POST operation can be used to set a new TTL cache expiration or to enable/disable public sharing over the CDN.
  51 +// X-TTL: 86400
  52 +// X-CDN-Enabled: True
  53 ++ (id)postRequestWithContainer:(NSString *)containerName;
  54 ++ (id)postRequestWithContainer:(NSString *)containerName cdnEnabled:(BOOL)cdnEnabled ttl:(NSUInteger)ttl;
  55 +// returns: - (NSString *)cdnURI;
  56 +
  57 +
  58 +@end
  1 +//
  2 +// ASICloudFilesCDNRequest.m
  3 +//
  4 +// Created by Michael Mayo on 1/6/10.
  5 +//
  6 +
  7 +#import "ASICloudFilesCDNRequest.h"
  8 +#import "ASICloudFilesContainerXMLParserDelegate.h"
  9 +
  10 +
  11 +@implementation ASICloudFilesCDNRequest
  12 +
  13 +@synthesize accountName, containerName, xmlParserDelegate;
  14 +
  15 ++ (id)cdnRequestWithMethod:(NSString *)method query:(NSString *)query {
  16 + NSString *urlString = [NSString stringWithFormat:@"%@%@", [ASICloudFilesRequest cdnManagementURL], query];
  17 + ASICloudFilesCDNRequest *request = [[ASICloudFilesCDNRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
  18 + [request setRequestMethod:method];
  19 + [request addRequestHeader:@"X-Auth-Token" value:[ASICloudFilesRequest authToken]];
  20 + return request;
  21 +}
  22 +
  23 ++ (id)cdnRequestWithMethod:(NSString *)method containerName:(NSString *)containerName {
  24 + NSString *urlString = [NSString stringWithFormat:@"%@/%@", [ASICloudFilesRequest cdnManagementURL], containerName];
  25 + ASICloudFilesCDNRequest *request = [[ASICloudFilesCDNRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
  26 + [request setRequestMethod:method];
  27 + [request addRequestHeader:@"X-Auth-Token" value:[ASICloudFilesRequest authToken]];
  28 + request.containerName = containerName;
  29 + return request;
  30 +}
  31 +
  32 +#pragma mark -
  33 +#pragma mark HEAD - Container Info
  34 +
  35 ++ (id)containerInfoRequest:(NSString *)containerName {
  36 + ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest cdnRequestWithMethod:@"HEAD" containerName:containerName];
  37 + return request;
  38 +}
  39 +
  40 +- (BOOL)cdnEnabled {
  41 + return [[[self responseHeaders] objectForKey:@"X-Cdn-Enabled"] boolValue];
  42 +}
  43 +
  44 +- (NSString *)cdnURI {
  45 + return [[self responseHeaders] objectForKey:@"X-Cdn-Uri"];
  46 +}
  47 +
  48 +- (NSUInteger)cdnTTL {
  49 + return [[[self responseHeaders] objectForKey:@"X-Ttl"] intValue];
  50 +}
  51 +
  52 +#pragma mark -
  53 +#pragma mark GET - CDN Container Lists
  54 +
  55 ++ (id)listRequest {
  56 + ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest cdnRequestWithMethod:@"GET" query:@"?format=xml"];
  57 + return request;
  58 +}
  59 +
  60 ++ (id)listRequestWithLimit:(NSUInteger)limit marker:(NSString *)marker enabledOnly:(BOOL)enabledOnly {
  61 + NSString *query = @"?format=xml";
  62 +
  63 + if (limit > 0) {
  64 + query = [query stringByAppendingString:[NSString stringWithFormat:@"&limit=%i", limit]];
  65 + }
  66 +
  67 + if (marker) {
  68 + query = [query stringByAppendingString:[NSString stringWithFormat:@"&marker=%@", marker]];
  69 + }
  70 +
  71 + if (limit > 0) {
  72 + query = [query stringByAppendingString:[NSString stringWithFormat:@"&limit=%i", limit]];
  73 + }
  74 +
  75 + ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest cdnRequestWithMethod:@"GET" query:query];
  76 + return request;
  77 +}
  78 +
  79 +- (NSArray *)containers {
  80 + if (xmlParserDelegate.containerObjects) {
  81 + return xmlParserDelegate.containerObjects;
  82 + }
  83 +
  84 + NSXMLParser *parser = [[[NSXMLParser alloc] initWithData:[self responseData]] autorelease];
  85 + if (xmlParserDelegate == nil) {
  86 + xmlParserDelegate = [[ASICloudFilesContainerXMLParserDelegate alloc] init];
  87 + }
  88 +
  89 + [parser setDelegate:xmlParserDelegate];
  90 + [parser setShouldProcessNamespaces:NO];
  91 + [parser setShouldReportNamespacePrefixes:NO];
  92 + [parser setShouldResolveExternalEntities:NO];
  93 + [parser parse];
  94 +
  95 + return xmlParserDelegate.containerObjects;
  96 +}
  97 +
  98 +#pragma mark -
  99 +#pragma mark PUT - CDN Enable Container
  100 +
  101 +// PUT /<api version>/<account>/<container>
  102 +// PUT operations against a Container are used to CDN-enable that Container.
  103 +// Include an HTTP header of X-TTL to specify a custom TTL.
  104 ++ (id)putRequestWithContainer:(NSString *)containerName {
  105 + ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest cdnRequestWithMethod:@"PUT" containerName:containerName];
  106 + return request;
  107 +}
  108 +
  109 ++ (id)putRequestWithContainer:(NSString *)containerName ttl:(NSUInteger)ttl {
  110 + ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest cdnRequestWithMethod:@"PUT" containerName:containerName];
  111 + [request addRequestHeader:@"X-Ttl" value:[NSString stringWithFormat:@"%i", ttl]];
  112 + return request;
  113 +}
  114 +
  115 +#pragma mark -
  116 +#pragma mark POST - Adjust CDN Attributes
  117 +
  118 +// POST /<api version>/<account>/<container>
  119 +// POST operations against a CDN-enabled Container are used to adjust CDN attributes.
  120 +// The POST operation can be used to set a new TTL cache expiration or to enable/disable public sharing over the CDN.
  121 +// X-TTL: 86400
  122 +// X-CDN-Enabled: True
  123 ++ (id)postRequestWithContainer:(NSString *)containerName {
  124 + ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest cdnRequestWithMethod:@"POST" containerName:containerName];
  125 + return request;
  126 +}
  127 +
  128 ++ (id)postRequestWithContainer:(NSString *)containerName cdnEnabled:(BOOL)cdnEnabled ttl:(NSUInteger)ttl {
  129 + ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest cdnRequestWithMethod:@"POST" containerName:containerName];
  130 + if (ttl > 0) {
  131 + [request addRequestHeader:@"X-Ttl" value:[NSString stringWithFormat:@"%i", ttl]];
  132 + }
  133 + [request addRequestHeader:@"X-Cdn-Enabled" value:cdnEnabled ? @"True" : @"False"];
  134 + return request;
  135 +}
  136 +
  137 +#pragma mark -
  138 +#pragma mark Memory Management
  139 +
  140 +-(void)dealloc {
  141 + [accountName release];
  142 + [containerName release];
  143 + [xmlParserDelegate release];
  144 + [super dealloc];
  145 +}
  146 +
  147 +@end
  1 +//
  2 +// ASICloudFilesContainer.h
  3 +//
  4 +// Created by Michael Mayo on 1/7/10.
  5 +//
  6 +
  7 +#import <Foundation/Foundation.h>
  8 +
  9 +
  10 +@interface ASICloudFilesContainer : NSObject {
  11 +
  12 + // regular container attributes
  13 + NSString *name;
  14 + NSUInteger count;
  15 + NSUInteger bytes;
  16 +
  17 + // CDN container attributes
  18 + BOOL cdnEnabled;
  19 + NSUInteger ttl;
  20 + NSString *cdnURL;
  21 + BOOL logRetention;
  22 + NSString *referrerACL;
  23 + NSString *useragentACL;
  24 +}
  25 +
  26 ++ (id)container;
  27 +
  28 +// regular container attributes
  29 +@property (nonatomic, retain) NSString *name;
  30 +@property (nonatomic) NSUInteger count;
  31 +@property (nonatomic) NSUInteger bytes;
  32 +
  33 +// CDN container attributes
  34 +@property (nonatomic) BOOL cdnEnabled;
  35 +@property (nonatomic) NSUInteger ttl;
  36 +@property (nonatomic, retain) NSString *cdnURL;
  37 +@property (nonatomic) BOOL logRetention;
  38 +@property (nonatomic, retain) NSString *referrerACL;
  39 +@property (nonatomic, retain) NSString *useragentACL;
  40 +
  41 +@end
  1 +//
  2 +// ASICloudFilesContainer.m
  3 +//
  4 +// Created by Michael Mayo on 1/7/10.
  5 +//
  6 +
  7 +#import "ASICloudFilesContainer.h"
  8 +
  9 +
  10 +@implementation ASICloudFilesContainer
  11 +
  12 +// regular container attributes
  13 +@synthesize name, count, bytes;
  14 +
  15 +// CDN container attributes
  16 +@synthesize cdnEnabled, ttl, cdnURL, logRetention, referrerACL, useragentACL;
  17 +
  18 ++ (id)container {
  19 + ASICloudFilesContainer *container = [[[self alloc] init] autorelease];
  20 + return container;
  21 +}
  22 +
  23 +-(void) dealloc {
  24 + [name release];
  25 + [super dealloc];
  26 +}
  27 +
  28 +@end
  1 +//
  2 +// ASICloudFilesContainerRequest.h
  3 +//
  4 +// Created by Michael Mayo on 1/6/10.
  5 +//
  6 +
  7 +#import "ASICloudFilesRequest.h"
  8 +
  9 +@class ASICloudFilesContainer, ASICloudFilesContainerXMLParserDelegate;
  10 +
  11 +@interface ASICloudFilesContainerRequest : ASICloudFilesRequest {
  12 +
  13 + // Internally used while parsing the response
  14 + NSString *currentContent;
  15 + NSString *currentElement;
  16 + ASICloudFilesContainer *currentObject;
  17 + ASICloudFilesContainerXMLParserDelegate *xmlParserDelegate;
  18 +}
  19 +
  20 +@property (nonatomic, retain) NSString *currentElement;
  21 +@property (nonatomic, retain) NSString *currentContent;
  22 +@property (nonatomic, retain) ASICloudFilesContainer *currentObject;
  23 +@property (nonatomic, retain) ASICloudFilesContainerXMLParserDelegate *xmlParserDelegate;
  24 +
  25 +// HEAD /<api version>/<account>
  26 +// HEAD operations against an account are performed to retrieve the number of Containers and the total bytes stored in Cloud Files for the account. This information is returned in two custom headers, X-Account-Container-Count and X-Account-Bytes-Used.
  27 ++ (id)accountInfoRequest;
  28 +- (NSUInteger)containerCount;
  29 +- (NSUInteger)bytesUsed;
  30 +
  31 +// GET /<api version>/<account>/<container>
  32 +// Create a request to list all containers
  33 ++ (id)listRequest;
  34 ++ (id)listRequestWithLimit:(NSUInteger)limit marker:(NSString *)marker;
  35 +- (NSArray *)containers;
  36 +
  37 +// PUT /<api version>/<account>/<container>
  38 ++ (id)createContainerRequest:(NSString *)containerName;
  39 +
  40 +// DELETE /<api version>/<account>/<container>
  41 ++ (id)deleteContainerRequest:(NSString *)containerName;
  42 +
  43 +@end
  1 +//
  2 +// ASICloudFilesContainerRequest.m
  3 +//
  4 +// Created by Michael Mayo on 1/6/10.
  5 +//
  6 +
  7 +#import "ASICloudFilesContainerRequest.h"
  8 +#import "ASICloudFilesContainer.h"
  9 +#import "ASICloudFilesContainerXMLParserDelegate.h"
  10 +
  11 +
  12 +@implementation ASICloudFilesContainerRequest
  13 +
  14 +@synthesize currentElement, currentContent, currentObject;
  15 +@synthesize xmlParserDelegate;
  16 +
  17 +#pragma mark -
  18 +#pragma mark Constructors
  19 +
  20 ++ (id)storageRequestWithMethod:(NSString *)method containerName:(NSString *)containerName queryString:(NSString *)queryString {
  21 + NSString *urlString;
  22 + if (containerName == nil) {
  23 + urlString = [NSString stringWithFormat:@"%@%@", [ASICloudFilesRequest storageURL], queryString];
  24 + } else {
  25 + urlString = [NSString stringWithFormat:@"%@/%@%@", [ASICloudFilesRequest storageURL], containerName, queryString];
  26 + }
  27 +
  28 + ASICloudFilesContainerRequest *request = [[ASICloudFilesContainerRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
  29 + [request setRequestMethod:method];
  30 + [request addRequestHeader:@"X-Auth-Token" value:[ASICloudFilesRequest authToken]];
  31 + return request;
  32 +}
  33 +
  34 ++ (id)storageRequestWithMethod:(NSString *)method queryString:(NSString *)queryString {
  35 + return [ASICloudFilesContainerRequest storageRequestWithMethod:method containerName:nil queryString:queryString];
  36 +}
  37 +
  38 ++ (id)storageRequestWithMethod:(NSString *)method {
  39 + return [ASICloudFilesContainerRequest storageRequestWithMethod:method queryString:@""];
  40 +}
  41 +
  42 +#pragma mark -
  43 +#pragma mark HEAD - Retrieve Container Count and Total Bytes Used
  44 +
  45 +// HEAD /<api version>/<account>
  46 +// HEAD operations against an account are performed to retrieve the number of Containers and the total bytes stored in Cloud Files for the account. This information is returned in two custom headers, X-Account-Container-Count and X-Account-Bytes-Used.
  47 ++ (id)accountInfoRequest {
  48 + ASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest storageRequestWithMethod:@"HEAD"];
  49 + return request;
  50 +}
  51 +
  52 +- (NSUInteger)containerCount {
  53 + return [[[self responseHeaders] objectForKey:@"X-Account-Container-Count"] intValue];
  54 +}
  55 +
  56 +- (NSUInteger)bytesUsed {
  57 + return [[[self responseHeaders] objectForKey:@"X-Account-Bytes-Used"] intValue];
  58 +}
  59 +
  60 +#pragma mark -
  61 +#pragma mark GET - Retrieve Container List
  62 +
  63 ++ (id)listRequestWithLimit:(NSUInteger)limit marker:(NSString *)marker {
  64 + NSString *queryString = @"?format=xml";
  65 +
  66 + if (limit > 0) {
  67 + queryString = [queryString stringByAppendingString:[NSString stringWithFormat:@"&limit=%i", limit]];
  68 + }
  69 +
  70 + if (marker != nil) {
  71 + queryString = [queryString stringByAppendingString:[NSString stringWithFormat:@"&marker=%@", marker]];
  72 + }
  73 +
  74 + ASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest storageRequestWithMethod:@"GET" queryString:queryString];
  75 + return request;
  76 +}
  77 +
  78 +// GET /<api version>/<account>/<container>
  79 +// Create a request to list all containers
  80 ++ (id)listRequest {
  81 + ASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest storageRequestWithMethod:@"GET"
  82 + queryString:@"?format=xml"];
  83 + return request;
  84 +}
  85 +
  86 +- (NSArray *)containers {
  87 + if (xmlParserDelegate.containerObjects) {
  88 + return xmlParserDelegate.containerObjects;
  89 + }
  90 +
  91 + NSXMLParser *parser = [[[NSXMLParser alloc] initWithData:[self responseData]] autorelease];
  92 + if (xmlParserDelegate == nil) {
  93 + xmlParserDelegate = [[ASICloudFilesContainerXMLParserDelegate alloc] init];
  94 + }
  95 +
  96 + [parser setDelegate:xmlParserDelegate];
  97 + [parser setShouldProcessNamespaces:NO];
  98 + [parser setShouldReportNamespacePrefixes:NO];
  99 + [parser setShouldResolveExternalEntities:NO];
  100 + [parser parse];
  101 +
  102 + return xmlParserDelegate.containerObjects;
  103 +}
  104 +
  105 +#pragma mark -
  106 +#pragma mark PUT - Create Container
  107 +
  108 +// PUT /<api version>/<account>/<container>
  109 ++ (id)createContainerRequest:(NSString *)containerName {
  110 + ASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest storageRequestWithMethod:@"PUT" containerName:containerName queryString:@""];
  111 + return request;
  112 +}
  113 +
  114 +#pragma mark -
  115 +#pragma mark DELETE - Delete Container
  116 +
  117 +// DELETE /<api version>/<account>/<container>
  118 ++ (id)deleteContainerRequest:(NSString *)containerName {
  119 + ASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest storageRequestWithMethod:@"DELETE" containerName:containerName queryString:@""];
  120 + return request;
  121 +}
  122 +
  123 +#pragma mark -
  124 +#pragma mark Memory Management
  125 +
  126 +- (void)dealloc {
  127 + [currentElement release];
  128 + [currentContent release];
  129 + [currentObject release];
  130 + [xmlParserDelegate release];
  131 + [super dealloc];
  132 +}
  133 +
  134 +@end
  1 +//
  2 +// ASICloudFilesContainerXMLParserDelegate.h
  3 +//
  4 +// Created by Michael Mayo on 1/10/10.
  5 +//
  6 +
  7 +#import "ASICloudFilesRequest.h"
  8 +
  9 +@class ASICloudFilesContainer;
  10 +
  11 +@interface ASICloudFilesContainerXMLParserDelegate : NSObject {
  12 +
  13 + NSMutableArray *containerObjects;
  14 +
  15 + // Internally used while parsing the response
  16 + NSString *currentContent;
  17 + NSString *currentElement;
  18 + ASICloudFilesContainer *currentObject;
  19 +}
  20 +
  21 +@property (nonatomic, retain) NSMutableArray *containerObjects;
  22 +
  23 +@property (nonatomic, retain) NSString *currentElement;
  24 +@property (nonatomic, retain) NSString *currentContent;
  25 +@property (nonatomic, retain) ASICloudFilesContainer *currentObject;
  26 +
  27 +@end
  1 +//
  2 +// ASICloudFilesContainerXMLParserDelegate.m
  3 +//
  4 +// Created by Michael Mayo on 1/10/10.
  5 +//
  6 +
  7 +#import "ASICloudFilesContainerXMLParserDelegate.h"
  8 +#import "ASICloudFilesContainer.h"
  9 +
  10 +
  11 +@implementation ASICloudFilesContainerXMLParserDelegate
  12 +
  13 +@synthesize containerObjects, currentElement, currentContent, currentObject;
  14 +
  15 +#pragma mark -
  16 +#pragma mark XML Parser Delegate
  17 +
  18 +- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
  19 + [self setCurrentElement:elementName];
  20 +
  21 + if ([elementName isEqualToString:@"container"]) {
  22 + [self setCurrentObject:[ASICloudFilesContainer container]];
  23 + }
  24 + [self setCurrentContent:@""];
  25 +}
  26 +
  27 +- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
  28 +
  29 + if ([elementName isEqualToString:@"name"]) {
  30 + [self currentObject].name = [self currentContent];
  31 + } else if ([elementName isEqualToString:@"count"]) {
  32 + [self currentObject].count = [[self currentContent] intValue];
  33 + } else if ([elementName isEqualToString:@"bytes"]) {
  34 + [self currentObject].bytes = [[self currentContent] intValue];
  35 + } else if ([elementName isEqualToString:@"cdn_enabled"]) {
  36 + [self currentObject].cdnEnabled = [[self currentObject] isEqual:@"True"];
  37 + } else if ([elementName isEqualToString:@"ttl"]) {
  38 + [self currentObject].ttl = [[self currentContent] intValue];
  39 + } else if ([elementName isEqualToString:@"cdn_url"]) {
  40 + [self currentObject].cdnURL = [self currentContent];
  41 + } else if ([elementName isEqualToString:@"log_retention"]) {
  42 + [self currentObject].logRetention = [[self currentObject] isEqual:@"True"];
  43 + } else if ([elementName isEqualToString:@"referrer_acl"]) {
  44 + [self currentObject].referrerACL = [self currentContent];
  45 + } else if ([elementName isEqualToString:@"useragent_acl"]) {
  46 + [self currentObject].useragentACL = [self currentContent];
  47 + } else if ([elementName isEqualToString:@"container"]) {
  48 + // we're done with this container. time to move on to the next
  49 + if (containerObjects == nil) {
  50 + containerObjects = [[NSMutableArray alloc] init];
  51 + }
  52 + [containerObjects addObject:currentObject];
  53 + [self setCurrentObject:nil];
  54 + }
  55 +}
  56 +
  57 +- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
  58 + [self setCurrentContent:[[self currentContent] stringByAppendingString:string]];
  59 +}
  60 +
  61 +#pragma mark -
  62 +#pragma mark Memory Management
  63 +
  64 +- (void)dealloc {
  65 + [containerObjects release];
  66 + [currentElement release];
  67 + [currentContent release];
  68 + [currentObject release];
  69 + [super dealloc];
  70 +}
  71 +
  72 +@end
  1 +//
  2 +// ASICloudFilesObject.h
  3 +//
  4 +// Created by Michael Mayo on 1/7/10.
  5 +//
  6 +
  7 +#import <Foundation/Foundation.h>
  8 +
  9 +
  10 +@interface ASICloudFilesObject : NSObject {
  11 + NSString *name;
  12 + NSString *hash;
  13 + NSUInteger bytes;
  14 + NSString *contentType;
  15 + NSDate *lastModified;
  16 + NSData *data;
  17 + NSMutableDictionary *metadata;
  18 +}
  19 +
  20 +@property (nonatomic, retain) NSString *name;
  21 +@property (nonatomic, retain) NSString *hash;
  22 +@property (nonatomic) NSUInteger bytes;
  23 +@property (nonatomic, retain) NSString *contentType;
  24 +@property (nonatomic, retain) NSDate *lastModified;
  25 +@property (nonatomic, retain) NSData *data;
  26 +@property (nonatomic, retain) NSMutableDictionary *metadata;
  27 +
  28 ++ (id)object;
  29 +
  30 +@end
  1 +//
  2 +// ASICloudFilesObject.m
  3 +//
  4 +// Created by Michael Mayo on 1/7/10.
  5 +//
  6 +
  7 +#import "ASICloudFilesObject.h"
  8 +
  9 +
  10 +@implementation ASICloudFilesObject
  11 +
  12 +@synthesize name, hash, bytes, contentType, lastModified, data, metadata;
  13 +
  14 ++ (id)object {
  15 + ASICloudFilesObject *object = [[[self alloc] init] autorelease];
  16 + return object;
  17 +}
  18 +
  19 +-(void)dealloc {
  20 + [name release];
  21 + [hash release];
  22 + [contentType release];
  23 + [lastModified release];
  24 + [data release];
  25 + [metadata release];
  26 + [super dealloc];
  27 +}
  28 +
  29 +@end
  1 +//
  2 +// ASICloudFilesObjectRequest.h
  3 +//
  4 +// Created by Michael Mayo on 1/6/10.
  5 +//
  6 +
  7 +#import "ASICloudFilesRequest.h"
  8 +
  9 +@class ASICloudFilesObject;
  10 +
  11 +@interface ASICloudFilesObjectRequest : ASICloudFilesRequest {
  12 +
  13 + NSString *accountName;
  14 + NSString *containerName;
  15 +
  16 + // Internally used while parsing the response
  17 + NSString *currentContent;
  18 + NSString *currentElement;
  19 + ASICloudFilesObject *currentObject;
  20 + NSMutableArray *objects;
  21 +
  22 +}
  23 +
  24 +@property (nonatomic, retain) NSString *accountName;
  25 +@property (nonatomic, retain) NSString *containerName;
  26 +@property (nonatomic, retain) NSString *currentElement;
  27 +@property (nonatomic, retain) NSString *currentContent;
  28 +@property (nonatomic, retain) ASICloudFilesObject *currentObject;
  29 +
  30 +
  31 +// HEAD /<api version>/<account>/<container>
  32 +// HEAD operations against an account are performed to retrieve the number of Containers and the total bytes stored in Cloud Files for the account. This information is returned in two custom headers, X-Account-Container-Count and X-Account-Bytes-Used.
  33 ++ (id)containerInfoRequest:(NSString *)containerName;
  34 +- (NSUInteger)containerObjectCount;
  35 +- (NSUInteger)containerBytesUsed;
  36 +
  37 +// HEAD /<api version>/<account>/<container>/<object>
  38 +// to get metadata
  39 ++ (id)objectInfoRequest:(NSString *)containerName objectPath:(NSString *)objectPath;
  40 +- (NSArray *)objects;
  41 +
  42 ++ (id)listRequestWithContainer:(NSString *)containerName;
  43 ++ (id)listRequestWithContainer:(NSString *)containerName limit:(NSUInteger)limit marker:(NSString *)marker prefix:(NSString *)prefix path:(NSString *)path;
  44 +
  45 +// Conditional GET headers: If-Match • If-None-Match • If-Modified-Since • If-Unmodified-Since
  46 +// HTTP Range header: “Range: bytes=0-5” • “Range: bytes=-5” • “Range: bytes=32-“
  47 ++ (id)getObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath;
  48 +- (ASICloudFilesObject *)object;
  49 +
  50 +// PUT /<api version>/<account>/<container>/<object>
  51 +// PUT operations are used to write, or overwrite, an Object's metadata and content.
  52 +// The Object can be created with custom metadata via HTTP headers identified with the “X-Object-Meta-” prefix.
  53 ++ (id)putObjectRequestWithContainer:(NSString *)containerName object:(ASICloudFilesObject *)object;
  54 ++ (id)putObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath contentType:(NSString *)contentType objectData:(NSData *)objectData metadata:(NSDictionary *)metadata etag:(NSString *)etag;
  55 +
  56 +// POST /<api version>/<account>/<container>/<object>
  57 +// POST operations against an Object name are used to set and overwrite arbitrary key/value metadata. You cannot use the POST operation to change any of the Object's other headers such as Content-Type, ETag, etc. It is not used to upload storage Objects (see PUT).
  58 +// A POST request will delete all existing metadata added with a previous PUT/POST.
  59 ++ (id)postObjectRequestWithContainer:(NSString *)containerName object:(ASICloudFilesObject *)object;
  60 ++ (id)postObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath metadata:(NSDictionary *)metadata;
  61 +
  62 +// DELETE /<api version>/<account>/<container>/<object>
  63 ++ (id)deleteObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath;
  64 +
  65 +@end
  1 +//
  2 +// ASICloudFilesObjectRequest.m
  3 +//
  4 +// Created by Michael Mayo on 1/6/10.
  5 +//
  6 +
  7 +#import "ASICloudFilesObjectRequest.h"
  8 +#import "ASICloudFilesObject.h"
  9 +
  10 +
  11 +@implementation ASICloudFilesObjectRequest
  12 +
  13 +@synthesize currentElement, currentContent, currentObject;
  14 +@synthesize accountName, containerName;
  15 +
  16 +#pragma mark -
  17 +#pragma mark Constructors
  18 +
  19 ++ (id)storageRequestWithMethod:(NSString *)method containerName:(NSString *)containerName {
  20 + NSString *urlString = [NSString stringWithFormat:@"%@/%@", [ASICloudFilesRequest storageURL], containerName];
  21 + ASICloudFilesObjectRequest *request = [[ASICloudFilesObjectRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
  22 + [request setRequestMethod:method];
  23 + [request addRequestHeader:@"X-Auth-Token" value:[ASICloudFilesRequest authToken]];
  24 + request.containerName = containerName;
  25 + return request;
  26 +}
  27 +
  28 ++ (id)storageRequestWithMethod:(NSString *)method containerName:(NSString *)containerName queryString:(NSString *)queryString {
  29 + NSString *urlString = [NSString stringWithFormat:@"%@/%@%@", [ASICloudFilesRequest storageURL], containerName, queryString];
  30 + ASICloudFilesObjectRequest *request = [[ASICloudFilesObjectRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
  31 + [request setRequestMethod:method];
  32 + [request addRequestHeader:@"X-Auth-Token" value:[ASICloudFilesRequest authToken]];
  33 + request.containerName = containerName;
  34 + return request;
  35 +}
  36 +
  37 ++ (id)storageRequestWithMethod:(NSString *)method containerName:(NSString *)containerName objectPath:(NSString *)objectPath {
  38 + NSString *urlString = [NSString stringWithFormat:@"%@/%@/%@", [ASICloudFilesRequest storageURL], containerName, objectPath];
  39 + ASICloudFilesObjectRequest *request = [[ASICloudFilesObjectRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
  40 + [request setRequestMethod:method];
  41 + [request addRequestHeader:@"X-Auth-Token" value:[ASICloudFilesRequest authToken]];
  42 + request.containerName = containerName;
  43 + return request;
  44 +}
  45 +
  46 +#pragma mark -
  47 +#pragma mark HEAD - Container Info
  48 +
  49 ++ (id)containerInfoRequest:(NSString *)containerName {
  50 + ASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest storageRequestWithMethod:@"HEAD" containerName:containerName];
  51 + return request;
  52 +}
  53 +
  54 +- (NSUInteger)containerObjectCount {
  55 + return [[[self responseHeaders] objectForKey:@"X-Container-Object-Count"] intValue];
  56 +}
  57 +
  58 +- (NSUInteger)containerBytesUsed {
  59 + return [[[self responseHeaders] objectForKey:@"X-Container-Bytes-Used"] intValue];
  60 +}
  61 +
  62 +#pragma mark -
  63 +#pragma mark HEAD - Object Info
  64 +
  65 ++ (id)objectInfoRequest:(NSString *)containerName objectPath:(NSString *)objectPath {
  66 + ASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest storageRequestWithMethod:@"HEAD" containerName:containerName objectPath:objectPath];
  67 + return request;
  68 +}
  69 +
  70 +#pragma mark -
  71 +#pragma mark GET - List Objects
  72 +
  73 ++ (NSString *)queryStringWithContainer:(NSString *)container limit:(NSUInteger)limit marker:(NSString *)marker prefix:(NSString *)prefix path:(NSString *)path {
  74 + NSString *queryString = @"?format=xml";
  75 +
  76 + if (limit && limit > 0) {
  77 + queryString = [queryString stringByAppendingString:[NSString stringWithFormat:@"&limit=%i", limit]];
  78 + }
  79 + if (marker) {
  80 + queryString = [queryString stringByAppendingString:[NSString stringWithFormat:@"&marker=%@", [marker stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
  81 + }
  82 + if (path) {
  83 + queryString = [queryString stringByAppendingString:[NSString stringWithFormat:@"&path=%@", [path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
  84 + }
  85 +
  86 + return queryString;
  87 +}
  88 +
  89 ++ (id)listRequestWithContainer:(NSString *)containerName limit:(NSUInteger)limit marker:(NSString *)marker prefix:(NSString *)prefix path:(NSString *)path {
  90 + NSString *queryString = [ASICloudFilesObjectRequest queryStringWithContainer:containerName limit:limit marker:marker prefix:prefix path:path];
  91 + ASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest storageRequestWithMethod:@"GET" containerName:containerName queryString:queryString];
  92 + return request;
  93 +}
  94 +
  95 ++ (id)listRequestWithContainer:(NSString *)containerName {
  96 + return [ASICloudFilesObjectRequest listRequestWithContainer:containerName limit:0 marker:nil prefix:nil path:nil];
  97 +}
  98 +
  99 +- (NSArray *)objects {
  100 + if (objects) {
  101 + return objects;
  102 + }
  103 + objects = [[[NSMutableArray alloc] init] autorelease];
  104 +
  105 + NSXMLParser *parser = [[[NSXMLParser alloc] initWithData:[self responseData]] autorelease];
  106 + [parser setDelegate:self];
  107 + [parser setShouldProcessNamespaces:NO];
  108 + [parser setShouldReportNamespacePrefixes:NO];
  109 + [parser setShouldResolveExternalEntities:NO];
  110 + [parser parse];
  111 + return objects;
  112 +}
  113 +
  114 +#pragma mark -
  115 +#pragma mark GET - Retrieve Object
  116 +
  117 ++ (id)getObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath {
  118 + return [ASICloudFilesObjectRequest storageRequestWithMethod:@"GET" containerName:containerName objectPath:objectPath];
  119 +}
  120 +
  121 +- (ASICloudFilesObject *)object {
  122 + ASICloudFilesObject *object = [ASICloudFilesObject object];
  123 +
  124 + NSString *path = [self url].path;
  125 + NSRange range = [path rangeOfString:self.containerName];
  126 + path = [path substringFromIndex:range.location + range.length + 1];
  127 +
  128 + object.name = path;
  129 + object.hash = [[self responseHeaders] objectForKey:@"ETag"];
  130 + object.bytes = [[[self responseHeaders] objectForKey:@"Content-Length"] intValue];
  131 + object.contentType = [[self responseHeaders] objectForKey:@"Content-Type"];
  132 + object.lastModified = [[self responseHeaders] objectForKey:@"Last-Modified"];
  133 + object.metadata = [[NSMutableDictionary alloc] init];
  134 +
  135 + NSDictionary *headers = [self responseHeaders];
  136 + NSArray *keys = [headers allKeys];
  137 + for (int i = 0; i < [keys count]; i++) {
  138 + NSString *key = [keys objectAtIndex:i];
  139 + NSString *value = [headers objectForKey:key];
  140 + NSRange range = [key rangeOfString:@"X-Object-Meta-"];
  141 +
  142 + if (range.location == 0) {
  143 + [object.metadata setObject:value forKey:[key substringFromIndex:range.length]];
  144 + }
  145 + }
  146 +
  147 + object.data = [self responseData];
  148 +
  149 + return object;
  150 +}
  151 +
  152 +#pragma mark -
  153 +#pragma mark PUT - Upload Object
  154 +
  155 ++ (id)putObjectRequestWithContainer:(NSString *)containerName object:(ASICloudFilesObject *)object {
  156 + return [self putObjectRequestWithContainer:containerName objectPath:object.name contentType:object.contentType objectData:object.data metadata:object.metadata etag:nil];
  157 +}
  158 +
  159 ++ (id)putObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath contentType:(NSString *)contentType objectData:(NSData *)objectData metadata:(NSDictionary *)metadata etag:(NSString *)etag {
  160 +
  161 + ASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest storageRequestWithMethod:@"PUT" containerName:containerName objectPath:objectPath];
  162 + [request addRequestHeader:@"Content-Type" value:contentType];
  163 + [request addRequestHeader:@"Content-Length" value:[NSString stringWithFormat:@"%i", objectData.length]];
  164 +
  165 + // add metadata to headers
  166 + if (metadata) {
  167 + NSArray *keys = [metadata allKeys];
  168 + for (int i = 0; i < [keys count]; i++) {
  169 + NSString *key = [keys objectAtIndex:i];
  170 + NSString *value = [metadata objectForKey:key];
  171 + [request addRequestHeader:[NSString stringWithFormat:@"X-Object-Meta-%@", key] value:value];
  172 + }
  173 + }
  174 +
  175 + [request appendPostData:objectData];
  176 + return request;
  177 +}
  178 +
  179 +#pragma mark -
  180 +#pragma mark POST - Set Object Metadata
  181 +
  182 ++ (id)postObjectRequestWithContainer:(NSString *)containerName object:(ASICloudFilesObject *)object {
  183 + return [self postObjectRequestWithContainer:containerName objectPath:object.name metadata:object.metadata];
  184 +}
  185 +
  186 ++ (id)postObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath metadata:(NSDictionary *)metadata {
  187 + ASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest storageRequestWithMethod:@"POST" containerName:containerName objectPath:objectPath];
  188 +
  189 + // add metadata to headers
  190 + if (metadata) {
  191 + NSArray *keys = [metadata allKeys];
  192 + for (int i = 0; i < [keys count]; i++) {
  193 + NSString *key = [keys objectAtIndex:i];
  194 + NSString *value = [metadata objectForKey:key];
  195 + [request addRequestHeader:[NSString stringWithFormat:@"X-Object-Meta-%@", key] value:value];
  196 + }
  197 + }
  198 +
  199 + return request;
  200 +}
  201 +
  202 +#pragma mark -
  203 +#pragma mark DELETE - Delete Object
  204 +
  205 ++ (id)deleteObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath {
  206 + ASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest storageRequestWithMethod:@"DELETE" containerName:containerName objectPath:objectPath];
  207 + return request;
  208 +}
  209 +
  210 +#pragma mark -
  211 +#pragma mark XML Parser Delegate
  212 +
  213 +- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
  214 + [self setCurrentElement:elementName];
  215 +
  216 + if ([elementName isEqualToString:@"object"]) {
  217 + [self setCurrentObject:[ASICloudFilesObject object]];
  218 + }
  219 + [self setCurrentContent:@""];
  220 +}
  221 +
  222 +- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
  223 + if ([elementName isEqualToString:@"name"]) {
  224 + [self currentObject].name = [self currentContent];
  225 + } else if ([elementName isEqualToString:@"hash"]) {
  226 + [self currentObject].hash = [self currentContent];
  227 + } else if ([elementName isEqualToString:@"bytes"]) {
  228 + [self currentObject].bytes = [[self currentContent] intValue];
  229 + } else if ([elementName isEqualToString:@"content_type"]) {
  230 + [self currentObject].contentType = [self currentContent];
  231 + } else if ([elementName isEqualToString:@"last_modified"]) {
  232 + [self currentObject].lastModified = [self dateFromString:[self currentContent]];
  233 + } else if ([elementName isEqualToString:@"object"]) {
  234 + // we're done with this object. time to move on to the next
  235 + [objects addObject:currentObject];
  236 + [self setCurrentObject:nil];
  237 + }
  238 +}
  239 +
  240 +- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
  241 + [self setCurrentContent:[[self currentContent] stringByAppendingString:string]];
  242 +}
  243 +
  244 +#pragma mark -
  245 +#pragma mark Memory Management
  246 +
  247 +- (void)dealloc {
  248 + [currentElement release];
  249 + [currentContent release];
  250 + [currentObject release];
  251 + [accountName release];
  252 + [containerName release];
  253 + [super dealloc];
  254 +}
  255 +
  256 +@end
  1 +//
  2 +// ASICloudFilesRequest.h
  3 +// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
  4 +//
  5 +// Created by Michael Mayo on 22/12/09.
  6 +// mike.mayo@rackspace.com or mike@overhrd.com
  7 +// twitter.com/greenisus
  8 +// Copyright 2009 All-Seeing Interactive. All rights reserved.
  9 +//
  10 +// A class for accessing data stored on the Rackspace Cloud Files Service
  11 +// http://www.rackspacecloud.com/cloud_hosting_products/files
  12 +//
  13 +// Cloud Files Developer Guide:
  14 +// http://docs.rackspacecloud.com/servers/api/cs-devguide-latest.pdf
  15 +
  16 +#import <Foundation/Foundation.h>
  17 +#import "ASIHTTPRequest.h"
  18 +
  19 +
  20 +@interface ASICloudFilesRequest : ASIHTTPRequest {
  21 +}
  22 +
  23 ++ (NSString *)storageURL;
  24 ++ (NSString *)cdnManagementURL;
  25 ++ (NSString *)authToken;
  26 +
  27 +#pragma mark Rackspace Cloud Authentication
  28 +
  29 ++ (id)authenticationRequest;
  30 ++ (void)authenticate;
  31 ++ (NSString *)username;
  32 ++ (void)setUsername:(NSString *)username;
  33 ++ (NSString *)apiKey;
  34 ++ (void)setApiKey:(NSString *)apiKey;
  35 +
  36 +// helper to parse dates in the format returned by Cloud Files
  37 +-(NSDate *)dateFromString:(NSString *)dateString;
  38 +
  39 +
  40 +@end
  1 +//
  2 +// ASICloudFilesRequest.m
  3 +// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
  4 +//
  5 +// Created by Michael Mayo on 22/12/09.
  6 +// Copyright 2009 All-Seeing Interactive. All rights reserved.
  7 +//
  8 +// A class for accessing data stored on Rackspace's Cloud Files Service
  9 +// http://www.rackspacecloud.com/cloud_hosting_products/files
  10 +//
  11 +// Cloud Files Developer Guide:
  12 +// http://docs.rackspacecloud.com/servers/api/cs-devguide-latest.pdf
  13 +
  14 +#import "ASICloudFilesRequest.h"
  15 +
  16 +static NSString *username = nil;
  17 +static NSString *apiKey = nil;
  18 +static NSString *authToken = nil;
  19 +static NSString *storageURL = nil;
  20 +static NSString *cdnManagementURL = nil;
  21 +static NSString *rackspaceCloudAuthURL = @"https://auth.api.rackspacecloud.com/v1.0";
  22 +
  23 +@implementation ASICloudFilesRequest
  24 +
  25 +#pragma mark -
  26 +#pragma mark Attributes and Service URLs
  27 +
  28 ++ (NSString *)authToken {
  29 + return authToken;
  30 +}
  31 +
  32 ++ (NSString *)storageURL {
  33 + return storageURL;
  34 +}
  35 +
  36 ++ (NSString *)cdnManagementURL {
  37 + return cdnManagementURL;
  38 +}
  39 +
  40 +#pragma mark -
  41 +#pragma mark Authentication
  42 +
  43 ++ (id)authenticationRequest {
  44 + ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:rackspaceCloudAuthURL]];
  45 + [request addRequestHeader:@"X-Auth-User" value:username];
  46 + [request addRequestHeader:@"X-Auth-Key" value:apiKey];
  47 + return request;
  48 +}
  49 +
  50 ++ (void)authenticate {
  51 + ASIHTTPRequest *request = [ASICloudFilesRequest authenticationRequest];
  52 + [request start];
  53 +
  54 + if (![request error]) {
  55 + NSDictionary *responseHeaders = [request responseHeaders];
  56 + authToken = [responseHeaders objectForKey:@"X-Auth-Token"];
  57 + storageURL = [responseHeaders objectForKey:@"X-Storage-Url"];
  58 + cdnManagementURL = [responseHeaders objectForKey:@"X-Cdn-Management-Url"];
  59 + }
  60 +}
  61 +
  62 ++ (NSString *)username {
  63 + return username;
  64 +}
  65 +
  66 ++ (void)setUsername:(NSString *)newUsername {
  67 + [username release];
  68 + username = [newUsername retain];
  69 +}
  70 +
  71 ++ (NSString *)apiKey {
  72 + return apiKey;
  73 +}
  74 +
  75 ++ (void)setApiKey:(NSString *)newApiKey {
  76 + [apiKey release];
  77 + apiKey = [newApiKey retain];
  78 +}
  79 +
  80 +#pragma mark -
  81 +#pragma mark Date Parser
  82 +
  83 +-(NSDate *)dateFromString:(NSString *)dateString {
  84 + NSDateFormatter *format = [[NSDateFormatter alloc] init];
  85 + // example: 2009-11-04T19:46:20.192723
  86 + [format setDateFormat:@"yyyy-MM-dd'T'H:mm:ss"];
  87 + NSDate *date = [format dateFromString:dateString];
  88 + [format release];
  89 +
  90 + return date;
  91 +}
  92 +
  93 +@end
  1 +//
  2 +// ASICloudFilesRequestTests.h
  3 +//
  4 +// Created by Michael Mayo on 1/6/10.
  5 +//
  6 +
  7 +#import "ASITestCase.h"
  8 +
  9 +@class ASINetworkQueue;
  10 +
  11 +@interface ASICloudFilesRequestTests : ASITestCase {
  12 + ASINetworkQueue *networkQueue;
  13 + float progress;
  14 +}
  15 +
  16 +@property (retain,nonatomic) ASINetworkQueue *networkQueue;
  17 +
  18 +@end
  1 +//
  2 +// ASICloudFilesRequestTests.m
  3 +//
  4 +// Created by Michael Mayo on 1/6/10.
  5 +//
  6 +
  7 +#import "ASICloudFilesRequestTests.h"
  8 +
  9 +// models
  10 +#import "ASICloudFilesContainer.h"
  11 +#import "ASICloudFilesObject.h"
  12 +
  13 +// requests
  14 +#import "ASICloudFilesRequest.h"
  15 +#import "ASICloudFilesContainerRequest.h"
  16 +#import "ASICloudFilesObjectRequest.h"
  17 +#import "ASICloudFilesCDNRequest.h"
  18 +
  19 +// Fill in these to run the tests that actually connect and manipulate objects on Cloud Files
  20 +static NSString *username = @"";
  21 +static NSString *apiKey = @"";
  22 +
  23 +@implementation ASICloudFilesRequestTests
  24 +
  25 +@synthesize networkQueue;
  26 +
  27 +// Authenticate before any test if there's no auth token present
  28 +- (void)authenticate {
  29 + if (![ASICloudFilesRequest authToken]) {
  30 + [ASICloudFilesRequest setUsername:username];
  31 + [ASICloudFilesRequest setApiKey:apiKey];
  32 + [ASICloudFilesRequest authenticate];
  33 + }
  34 +}
  35 +
  36 +// ASICloudFilesRequest
  37 +- (void)testAuthentication {
  38 + [self authenticate];
  39 + GHAssertNotNil([ASICloudFilesRequest authToken], @"Failed to authenticate and obtain authentication token");
  40 + GHAssertNotNil([ASICloudFilesRequest storageURL], @"Failed to authenticate and obtain storage URL");
  41 + GHAssertNotNil([ASICloudFilesRequest cdnManagementURL], @"Failed to authenticate and obtain CDN URL");
  42 +}
  43 +
  44 +- (void)testDateParser {
  45 + ASICloudFilesRequest *request = [[ASICloudFilesRequest alloc] init];
  46 + NSDate *date = [request dateFromString:@"2009-11-04T19:46:20.192723"];
  47 + GHAssertNotNil(date, @"Failed to parse date string");
  48 + date = [request dateFromString:@"invalid date string"];
  49 + GHAssertNil(date, @"Failed to not parse with invalid date string");
  50 + [request release];
  51 +}
  52 +
  53 +// ASICloudFilesContainerRequest
  54 +- (void)testAccountInfo {
  55 + [self authenticate];
  56 +
  57 + ASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest accountInfoRequest];
  58 + [request start];
  59 +
  60 + GHAssertTrue([request containerCount] > 0, @"Failed to retrieve account info");
  61 + GHAssertTrue([request bytesUsed] > 0, @"Failed to retrieve account info");
  62 +}
  63 +
  64 +- (void)testContainerList {
  65 + [self authenticate];
  66 +
  67 + NSArray *containers = nil;
  68 +
  69 + ASICloudFilesContainerRequest *containerListRequest = [ASICloudFilesContainerRequest listRequest];
  70 + [containerListRequest start];
  71 +
  72 + containers = [containerListRequest containers];
  73 + GHAssertTrue([containers count] > 0, @"Failed to list containers");
  74 + for (int i = 0; i < [containers count]; i++) {
  75 + ASICloudFilesContainer *container = [containers objectAtIndex:i];
  76 + GHAssertNotNil(container.name, @"Failed to parse container");
  77 + }
  78 +
  79 + ASICloudFilesContainerRequest *limitContainerListRequest = [ASICloudFilesContainerRequest listRequestWithLimit:2 marker:nil];
  80 + [limitContainerListRequest start];
  81 + containers = [limitContainerListRequest containers];
  82 + GHAssertTrue([containers count] == 2, @"Failed to limit container list");
  83 +}
  84 +
  85 +- (void)testContainerCreate {
  86 + [self authenticate];
  87 +
  88 + ASICloudFilesContainerRequest *createContainerRequest = [ASICloudFilesContainerRequest createContainerRequest:@"ASICloudFilesContainerTest"];
  89 + [createContainerRequest start];
  90 + GHAssertTrue([createContainerRequest error] == nil, @"Failed to create container");
  91 +}
  92 +
  93 +- (void)testContainerDelete {
  94 + [self authenticate];
  95 +
  96 + ASICloudFilesContainerRequest *deleteContainerRequest = [ASICloudFilesContainerRequest deleteContainerRequest:@"ASICloudFilesContainerTest"];
  97 + [deleteContainerRequest start];
  98 + GHAssertTrue([deleteContainerRequest error] == nil, @"Failed to delete container");
  99 +}
  100 +
  101 +// ASICloudFilesObjectRequest
  102 +- (void)testContainerInfo {
  103 + [self authenticate];
  104 +
  105 + // create a file first
  106 + ASICloudFilesContainerRequest *createContainerRequest = [ASICloudFilesContainerRequest createContainerRequest:@"ASICloudFilesTest"];
  107 + [createContainerRequest start];
  108 + NSData *data = [@"this is a test" dataUsingEncoding:NSUTF8StringEncoding];
  109 + ASICloudFilesObjectRequest *putRequest
  110 + = [ASICloudFilesObjectRequest putObjectRequestWithContainer:@"ASICloudFilesTest"
  111 + objectPath:@"infotestfile.txt" contentType:@"text/plain"
  112 + objectData:data metadata:nil etag:nil];
  113 +
  114 + [putRequest start];
  115 +
  116 + ASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest containerInfoRequest:@"ASICloudFilesTest"];
  117 + [request start];
  118 + GHAssertTrue([request containerObjectCount] > 0, @"Failed to retrieve container info");
  119 + GHAssertTrue([request containerBytesUsed] > 0, @"Failed to retrieve container info");
  120 +}
  121 +
  122 +- (void)testObjectInfo {
  123 + [self authenticate];
  124 +
  125 + ASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest objectInfoRequest:@"ASICloudFilesTest" objectPath:@"infotestfile.txt"];
  126 + [request start];
  127 +
  128 + ASICloudFilesObject *object = [request object];
  129 + GHAssertNotNil(object, @"Failed to retrieve object");
  130 + GHAssertTrue([object.metadata count] > 0, @"Failed to parse metadata");
  131 +
  132 + GHAssertTrue([object.metadata objectForKey:@"Test"] != nil, @"Failed to parse metadata");
  133 +
  134 +}
  135 +
  136 +- (void)testObjectList {
  137 + [self authenticate];
  138 +
  139 + ASICloudFilesObjectRequest *objectListRequest = [ASICloudFilesObjectRequest listRequestWithContainer:@"ASICloudFilesTest"];
  140 + [objectListRequest start];
  141 +
  142 + NSArray *containers = [objectListRequest objects];
  143 + GHAssertTrue([containers count] > 0, @"Failed to list objects");
  144 + for (int i = 0; i < [containers count]; i++) {
  145 + ASICloudFilesObject *object = [containers objectAtIndex:i];
  146 + GHAssertNotNil(object.name, @"Failed to parse object");
  147 + }
  148 +
  149 +}
  150 +
  151 +- (void)testGetObject {
  152 + [self authenticate];
  153 +
  154 + ASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest getObjectRequestWithContainer:@"ASICloudFilesTest" objectPath:@"infotestfile.txt"];
  155 + [request start];
  156 +
  157 + ASICloudFilesObject *object = [request object];
  158 + GHAssertNotNil(object, @"Failed to retrieve object");
  159 +
  160 + GHAssertNotNil(object.name, @"Failed to parse object name");
  161 + GHAssertTrue(object.bytes > 0, @"Failed to parse object bytes");
  162 + GHAssertNotNil(object.contentType, @"Failed to parse object content type");
  163 + GHAssertNotNil(object.lastModified, @"Failed to parse object last modified");
  164 + GHAssertNotNil(object.data, @"Failed to parse object data");
  165 +}
  166 +
  167 +- (void)testPutObject {
  168 + [self authenticate];
  169 +
  170 + ASICloudFilesContainerRequest *createContainerRequest
  171 + = [ASICloudFilesContainerRequest createContainerRequest:@"ASICloudFilesTest"];
  172 + [createContainerRequest start];
  173 +
  174 + NSData *data = [@"this is a test" dataUsingEncoding:NSUTF8StringEncoding];
  175 +
  176 + ASICloudFilesObjectRequest *putRequest
  177 + = [ASICloudFilesObjectRequest putObjectRequestWithContainer:@"ASICloudFilesTest"
  178 + objectPath:@"puttestfile.txt" contentType:@"text/plain"
  179 + objectData:data metadata:nil etag:nil];
  180 +
  181 + [putRequest start];
  182 +
  183 + GHAssertNil([putRequest error], @"Failed to PUT object");
  184 +
  185 + ASICloudFilesObjectRequest *getRequest = [ASICloudFilesObjectRequest getObjectRequestWithContainer:@"ASICloudFilesTest" objectPath:@"puttestfile.txt"];
  186 + [getRequest start];
  187 +
  188 + ASICloudFilesObject *object = [getRequest object];
  189 + NSString *string = [[NSString alloc] initWithData:object.data encoding:NSASCIIStringEncoding];
  190 +
  191 + GHAssertNotNil(object, @"Failed to retrieve new object");
  192 + GHAssertNotNil(object.name, @"Failed to parse object name");
  193 + GHAssertEqualStrings(object.name, @"puttestfile.txt", @"Failed to parse object name", @"Failed to parse object name");
  194 + GHAssertNotNil(object.data, @"Failed to parse object data");
  195 + GHAssertEqualStrings(string, @"this is a test", @"Failed to parse object data", @"Failed to parse object data");
  196 +
  197 + [string release];
  198 +
  199 + ASICloudFilesContainerRequest *deleteContainerRequest = [ASICloudFilesContainerRequest deleteContainerRequest:@"ASICloudFilesTest"];
  200 + [deleteContainerRequest start];
  201 +
  202 +}
  203 +
  204 +- (void)testPostObject {
  205 + [self authenticate];
  206 +
  207 + NSMutableDictionary *metadata = [[NSMutableDictionary alloc] initWithCapacity:2];
  208 + [metadata setObject:@"test" forKey:@"Test"];
  209 + [metadata setObject:@"test" forKey:@"ASITest"];
  210 +
  211 + ASICloudFilesObject *object = [ASICloudFilesObject object];
  212 + object.name = @"infotestfile.txt";
  213 + object.metadata = metadata;
  214 +
  215 + ASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest postObjectRequestWithContainer:@"ASICloudFilesTest" object:object];
  216 + [request start];
  217 +
  218 + GHAssertTrue([request responseStatusCode] == 202, @"Failed to post object metadata");
  219 +
  220 + [metadata release];
  221 +
  222 +}
  223 +
  224 +- (void)testDeleteObject {
  225 + [self authenticate];
  226 +
  227 + ASICloudFilesObjectRequest *deleteRequest = [ASICloudFilesObjectRequest deleteObjectRequestWithContainer:@"ASICloudFilesTest" objectPath:@"puttestfile.txt"];
  228 + [deleteRequest start];
  229 + GHAssertTrue([deleteRequest responseStatusCode] == 204, @"Failed to delete object");
  230 +}
  231 +
  232 +#pragma mark -
  233 +#pragma mark CDN Tests
  234 +
  235 +- (void)testCDNContainerInfo {
  236 + [self authenticate];
  237 +
  238 + ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest containerInfoRequest:@"ASICloudFilesTest"];
  239 + [request start];
  240 +
  241 + GHAssertTrue([request responseStatusCode] == 204, @"Failed to retrieve CDN container info");
  242 + GHAssertTrue([request cdnEnabled], @"Failed to retrieve CDN container info");
  243 + GHAssertNotNil([request cdnURI], @"Failed to retrieve CDN container info");
  244 + GHAssertTrue([request cdnTTL] > 0, @"Failed to retrieve CDN container info");
  245 +}
  246 +
  247 +- (void)testCDNContainerList {
  248 + [self authenticate];
  249 +
  250 + ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest listRequest];
  251 + [request start];
  252 +
  253 + GHAssertNotNil([request containers], @"Failed to retrieve CDN container list");
  254 +}
  255 +
  256 +- (void)testCDNContainerListWithParams {
  257 + [self authenticate];
  258 +
  259 + ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest listRequestWithLimit:2 marker:nil enabledOnly:YES];
  260 + [request start];
  261 +
  262 + GHAssertNotNil([request containers], @"Failed to retrieve CDN container list");
  263 + GHAssertTrue([[request containers] count] == 2, @"Failed to retrieve limited CDN container list");
  264 +}
  265 +
  266 +- (void)testCDNPut {
  267 + [self authenticate];
  268 +
  269 + ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest putRequestWithContainer:@"ASICloudFilesTest"];
  270 + [request start];
  271 +
  272 + GHAssertNotNil([request cdnURI], @"Failed to PUT to CDN container");
  273 +}
  274 +
  275 +- (void)testCDNPost {
  276 + [self authenticate];
  277 +
  278 + ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest postRequestWithContainer:@"ASICloudFilesTest" cdnEnabled:YES ttl:86600];
  279 + [request start];
  280 +
  281 + GHAssertNotNil([request cdnURI], @"Failed to POST to CDN container");
  282 +}
  283 +
  284 +#pragma mark -
  285 +#pragma mark Memory Management
  286 +
  287 +-(void)dealloc {
  288 + [networkQueue release];
  289 + [super dealloc];
  290 +}
  291 +
  292 +@end
@@ -23,9 +23,7 @@ @@ -23,9 +23,7 @@
23 [super dealloc]; 23 [super dealloc];
24 } 24 }
25 25
26 -  
27 - (void)applicationDidFinishLaunching:(UIApplication *)application { 26 - (void)applicationDidFinishLaunching:(UIApplication *)application {
28 -  
29 // Add the tab bar controller's current view as a subview of the window 27 // Add the tab bar controller's current view as a subview of the window
30 [window addSubview:[tabBarController view]]; 28 [window addSubview:[tabBarController view]];
31 [[tabBarController view] setFrame:CGRectMake(0,47,320,433)]; 29 [[tabBarController view] setFrame:CGRectMake(0,47,320,433)];