Ben Copsey

Change S3 API to take a real S3 key as a parameter when creating a request, rath…

…er than forcing the user to encode the key themselves or add a '/' on the front
My thanks to Tom Andersen for his report!
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 #import "ASIInputStream.h" 21 #import "ASIInputStream.h"
22 22
23 // Automatically set on build 23 // Automatically set on build
24 -NSString *ASIHTTPRequestVersion = @"v1.6-3 2010-03-11"; 24 +NSString *ASIHTTPRequestVersion = @"v1.6-4 2010-03-16";
25 25
26 NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain"; 26 NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain";
27 27
@@ -30,17 +30,17 @@ @@ -30,17 +30,17 @@
30 30
31 - (ASIS3Request *)GETRequest 31 - (ASIS3Request *)GETRequest
32 { 32 {
33 - return [ASIS3Request requestWithBucket:[self bucket] path:[NSString stringWithFormat:@"/%@",[self key]]]; 33 + return [ASIS3Request requestWithBucket:[self bucket] key:[self key]];
34 } 34 }
35 35
36 - (ASIS3Request *)PUTRequestWithFile:(NSString *)filePath 36 - (ASIS3Request *)PUTRequestWithFile:(NSString *)filePath
37 { 37 {
38 - return [ASIS3Request PUTRequestForFile:filePath withBucket:[self bucket] path:[NSString stringWithFormat:@"/%@",[self key]]]; 38 + return [ASIS3Request PUTRequestForFile:filePath withBucket:[self bucket] key:[self key]];
39 } 39 }
40 40
41 - (ASIS3Request *)DELETERequest 41 - (ASIS3Request *)DELETERequest
42 { 42 {
43 - ASIS3Request *request = [ASIS3Request requestWithBucket:[self bucket] path:[NSString stringWithFormat:@"/%@",[self key]]]; 43 + ASIS3Request *request = [ASIS3Request requestWithBucket:[self bucket] key:[self key]];
44 [request setRequestMethod:@"DELETE"]; 44 [request setRequestMethod:@"DELETE"];
45 return request; 45 return request;
46 } 46 }
@@ -132,7 +132,7 @@ static NSDateFormatter *dateFormatter = nil; @@ -132,7 +132,7 @@ static NSDateFormatter *dateFormatter = nil;
132 [newRequest setPrefix:[self prefix]]; 132 [newRequest setPrefix:[self prefix]];
133 [newRequest setMarker:[self marker]]; 133 [newRequest setMarker:[self marker]];
134 [newRequest setMaxResultCount:[self maxResultCount]]; 134 [newRequest setMaxResultCount:[self maxResultCount]];
135 - [newRequest setDelimiter:[self path]]; 135 + [newRequest setDelimiter:[self delimiter]];
136 return newRequest; 136 return newRequest;
137 } 137 }
138 138
@@ -37,8 +37,8 @@ typedef enum _ASIS3ErrorType { @@ -37,8 +37,8 @@ typedef enum _ASIS3ErrorType {
37 // Name of the bucket to talk to 37 // Name of the bucket to talk to
38 NSString *bucket; 38 NSString *bucket;
39 39
40 - // Path to the resource you want to access on S3. Leave empty for the bucket root 40 + // Key of the resource you want to access on S3. Leave empty for the bucket root
41 - NSString *path; 41 + NSString *key;
42 42
43 // The string that will be used in the HTTP date header. Generally you'll want to ignore this and let the class add the current date for you, but the accessor is used by the tests 43 // The string that will be used in the HTTP date header. Generally you'll want to ignore this and let the class add the current date for you, but the accessor is used by the tests
44 NSString *dateString; 44 NSString *dateString;
@@ -53,7 +53,7 @@ typedef enum _ASIS3ErrorType { @@ -53,7 +53,7 @@ typedef enum _ASIS3ErrorType {
53 53
54 // The bucket + path of the object to be copied (used with COPYRequestFromBucket:path:toBucket:path:) 54 // The bucket + path of the object to be copied (used with COPYRequestFromBucket:path:toBucket:path:)
55 NSString *sourceBucket; 55 NSString *sourceBucket;
56 - NSString *sourcePath; 56 + NSString *sourceKey;
57 57
58 // Internally used while parsing errors 58 // Internally used while parsing errors
59 NSString *currentErrorString; 59 NSString *currentErrorString;
@@ -63,28 +63,30 @@ typedef enum _ASIS3ErrorType { @@ -63,28 +63,30 @@ typedef enum _ASIS3ErrorType {
63 #pragma mark Constructors 63 #pragma mark Constructors
64 64
65 // Create a request, building an appropriate url 65 // Create a request, building an appropriate url
66 -+ (id)requestWithBucket:(NSString *)bucket path:(NSString *)path; 66 ++ (id)requestWithBucket:(NSString *)bucket key:(NSString *)key;
67 67
68 // Create a PUT request using the file at filePath as the body 68 // Create a PUT request using the file at filePath as the body
69 -+ (id)PUTRequestForFile:(NSString *)filePath withBucket:(NSString *)bucket path:(NSString *)path; 69 ++ (id)PUTRequestForFile:(NSString *)filePath withBucket:(NSString *)bucket key:(NSString *)key;
70 70
71 // Create a PUT request using the supplied NSData as the body (set the mime-type manually with setMimeType: if necessary) 71 // Create a PUT request using the supplied NSData as the body (set the mime-type manually with setMimeType: if necessary)
72 -+ (id)PUTRequestForData:(NSData *)data withBucket:(NSString *)bucket path:(NSString *)path; 72 ++ (id)PUTRequestForData:(NSData *)data withBucket:(NSString *)bucket key:(NSString *)key;
73 73
74 // Create a DELETE request for the object at path 74 // Create a DELETE request for the object at path
75 -+ (id)DELETERequestWithBucket:(NSString *)bucket path:(NSString *)path; 75 ++ (id)DELETERequestWithBucket:(NSString *)bucket key:(NSString *)key;
76 76
77 // Create a PUT request to copy an object from one location to another 77 // Create a PUT request to copy an object from one location to another
78 // Clang will complain because it thinks this method should return an object with +1 retain :( 78 // Clang will complain because it thinks this method should return an object with +1 retain :(
79 -+ (id)COPYRequestFromBucket:(NSString *)sourceBucket path:(NSString *)sourcePath toBucket:(NSString *)bucket path:(NSString *)path; 79 ++ (id)COPYRequestFromBucket:(NSString *)sourceBucket key:(NSString *)sourceKey toBucket:(NSString *)bucket key:(NSString *)key;
80 80
81 // Creates a HEAD request for the object at path 81 // Creates a HEAD request for the object at path
82 -+ (id)HEADRequestWithBucket:(NSString *)bucket path:(NSString *)path; 82 ++ (id)HEADRequestWithBucket:(NSString *)bucket key:(NSString *)key;
83 83
84 84
85 // Uses the supplied date to create a Date header string 85 // Uses the supplied date to create a Date header string
86 - (void)setDate:(NSDate *)date; 86 - (void)setDate:(NSDate *)date;
87 87
  88 ++ (NSString *)stringByURLEncodingForS3Path:(NSString *)key;
  89 +
88 #pragma mark Shared access keys 90 #pragma mark Shared access keys
89 91
90 // Get and set the global access key, this will be used for all requests the access key hasn't been set for 92 // Get and set the global access key, this will be used for all requests the access key hasn't been set for
@@ -95,12 +97,12 @@ typedef enum _ASIS3ErrorType { @@ -95,12 +97,12 @@ typedef enum _ASIS3ErrorType {
95 97
96 98
97 @property (retain) NSString *bucket; 99 @property (retain) NSString *bucket;
98 -@property (retain) NSString *path; 100 +@property (retain) NSString *key;
99 @property (retain) NSString *dateString; 101 @property (retain) NSString *dateString;
100 @property (retain) NSString *mimeType; 102 @property (retain) NSString *mimeType;
101 @property (retain) NSString *accessKey; 103 @property (retain) NSString *accessKey;
102 @property (retain) NSString *secretAccessKey; 104 @property (retain) NSString *secretAccessKey;
103 @property (retain) NSString *accessPolicy; 105 @property (retain) NSString *accessPolicy;
104 @property (retain) NSString *sourceBucket; 106 @property (retain) NSString *sourceBucket;
105 -@property (retain) NSString *sourcePath; 107 +@property (retain) NSString *sourceKey;
106 @end 108 @end
@@ -29,25 +29,38 @@ static NSString *sharedSecretAccessKey = nil; @@ -29,25 +29,38 @@ static NSString *sharedSecretAccessKey = nil;
29 29
30 #pragma mark Constructors 30 #pragma mark Constructors
31 31
32 -+ (id)requestWithBucket:(NSString *)bucket path:(NSString *)path 32 ++ (NSString *)stringByURLEncodingForS3Path:(NSString *)key
33 { 33 {
  34 + if (!key) {
  35 + return @"/";
  36 + }
  37 + NSString *path = [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)key, NULL, CFSTR(":?#[]@!$ &'()*+,;=\"<>%{}|\\^~`"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)) autorelease];
  38 + if (![[path substringWithRange:NSMakeRange(0, 1)] isEqualToString:@"/"]) {
  39 + path = [@"/" stringByAppendingString:path];
  40 + }
  41 + return path;
  42 +}
  43 +
  44 ++ (id)requestWithBucket:(NSString *)bucket key:(NSString *)key
  45 +{
  46 + NSString *path = [ASIS3Request stringByURLEncodingForS3Path:key];
34 ASIS3Request *request = [[[self alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@.s3.amazonaws.com%@",bucket,path]]] autorelease]; 47 ASIS3Request *request = [[[self alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@.s3.amazonaws.com%@",bucket,path]]] autorelease];
35 [request setBucket:bucket]; 48 [request setBucket:bucket];
36 - [request setPath:path]; 49 + [request setKey:key];
37 return request; 50 return request;
38 } 51 }
39 52
40 -+ (id)PUTRequestForData:(NSData *)data withBucket:(NSString *)bucket path:(NSString *)path 53 ++ (id)PUTRequestForData:(NSData *)data withBucket:(NSString *)bucket key:(NSString *)key
41 { 54 {
42 - ASIS3Request *request = [self requestWithBucket:bucket path:path]; 55 + ASIS3Request *request = [self requestWithBucket:bucket key:key];
43 [request appendPostData:data]; 56 [request appendPostData:data];
44 [request setRequestMethod:@"PUT"]; 57 [request setRequestMethod:@"PUT"];
45 return request; 58 return request;
46 } 59 }
47 60
48 -+ (id)PUTRequestForFile:(NSString *)filePath withBucket:(NSString *)bucket path:(NSString *)path 61 ++ (id)PUTRequestForFile:(NSString *)filePath withBucket:(NSString *)bucket key:(NSString *)key
49 { 62 {
50 - ASIS3Request *request = [self requestWithBucket:bucket path:path]; 63 + ASIS3Request *request = [self requestWithBucket:bucket key:key];
51 [request setPostBodyFilePath:filePath]; 64 [request setPostBodyFilePath:filePath];
52 [request setShouldStreamPostDataFromDisk:YES]; 65 [request setShouldStreamPostDataFromDisk:YES];
53 [request setRequestMethod:@"PUT"]; 66 [request setRequestMethod:@"PUT"];
@@ -55,25 +68,25 @@ static NSString *sharedSecretAccessKey = nil; @@ -55,25 +68,25 @@ static NSString *sharedSecretAccessKey = nil;
55 return request; 68 return request;
56 } 69 }
57 70
58 -+ (id)DELETERequestWithBucket:(NSString *)bucket path:(NSString *)path 71 ++ (id)DELETERequestWithBucket:(NSString *)bucket key:(NSString *)key
59 { 72 {
60 - ASIS3Request *request = [self requestWithBucket:bucket path:path]; 73 + ASIS3Request *request = [self requestWithBucket:bucket key:key];
61 [request setRequestMethod:@"DELETE"]; 74 [request setRequestMethod:@"DELETE"];
62 return request; 75 return request;
63 } 76 }
64 77
65 -+ (id)COPYRequestFromBucket:(NSString *)sourceBucket path:(NSString *)sourcePath toBucket:(NSString *)bucket path:(NSString *)path 78 ++ (id)COPYRequestFromBucket:(NSString *)sourceBucket key:(NSString *)sourceKey toBucket:(NSString *)bucket key:(NSString *)key
66 { 79 {
67 - ASIS3Request *request = [self requestWithBucket:bucket path:path]; 80 + ASIS3Request *request = [self requestWithBucket:bucket key:key];
68 [request setRequestMethod:@"PUT"]; 81 [request setRequestMethod:@"PUT"];
69 [request setSourceBucket:sourceBucket]; 82 [request setSourceBucket:sourceBucket];
70 - [request setSourcePath:sourcePath]; 83 + [request setSourceKey:sourceKey];
71 return request; 84 return request;
72 } 85 }
73 86
74 -+ (id)HEADRequestWithBucket:(NSString *)bucket path:(NSString *)path 87 ++ (id)HEADRequestWithBucket:(NSString *)bucket key:(NSString *)key
75 { 88 {
76 - ASIS3Request *request = [self requestWithBucket:bucket path:path]; 89 + ASIS3Request *request = [self requestWithBucket:bucket key:key];
77 [request setRequestMethod:@"HEAD"]; 90 [request setRequestMethod:@"HEAD"];
78 return request; 91 return request;
79 } 92 }
@@ -81,12 +94,12 @@ static NSString *sharedSecretAccessKey = nil; @@ -81,12 +94,12 @@ static NSString *sharedSecretAccessKey = nil;
81 - (void)dealloc 94 - (void)dealloc
82 { 95 {
83 [bucket release]; 96 [bucket release];
84 - [path release]; 97 + [key release];
85 [dateString release]; 98 [dateString release];
86 [mimeType release]; 99 [mimeType release];
87 [accessKey release]; 100 [accessKey release];
88 [secretAccessKey release]; 101 [secretAccessKey release];
89 - [sourcePath release]; 102 + [sourceKey release];
90 [sourceBucket release]; 103 [sourceBucket release];
91 [super dealloc]; 104 [super dealloc];
92 } 105 }
@@ -106,7 +119,7 @@ static NSString *sharedSecretAccessKey = nil; @@ -106,7 +119,7 @@ static NSString *sharedSecretAccessKey = nil;
106 ASIS3Request *headRequest = (ASIS3Request *)[super HEADRequest]; 119 ASIS3Request *headRequest = (ASIS3Request *)[super HEADRequest];
107 [headRequest setAccessKey:[self accessKey]]; 120 [headRequest setAccessKey:[self accessKey]];
108 [headRequest setSecretAccessKey:[self secretAccessKey]]; 121 [headRequest setSecretAccessKey:[self secretAccessKey]];
109 - [headRequest setPath:[self path]]; 122 + [headRequest setKey:[self key]];
110 [headRequest setBucket:[self bucket]]; 123 [headRequest setBucket:[self bucket]];
111 return headRequest; 124 return headRequest;
112 } 125 }
@@ -130,11 +143,7 @@ static NSString *sharedSecretAccessKey = nil; @@ -130,11 +143,7 @@ static NSString *sharedSecretAccessKey = nil;
130 [self addRequestHeader:@"Date" value:[self dateString]]; 143 [self addRequestHeader:@"Date" value:[self dateString]];
131 144
132 // Ensure our formatted string doesn't use '(null)' for the empty path 145 // Ensure our formatted string doesn't use '(null)' for the empty path
133 - if (![self path]) { 146 + NSString *canonicalizedResource = [NSString stringWithFormat:@"/%@%@",[self bucket],[ASIS3Request stringByURLEncodingForS3Path:[self key]]];
134 - [self setPath:@"/"];  
135 - }  
136 -  
137 - NSString *canonicalizedResource = [NSString stringWithFormat:@"/%@%@",[self bucket],[self path]];  
138 147
139 // Add a header for the access policy if one was set, otherwise we won't add one (and S3 will default to private) 148 // Add a header for the access policy if one was set, otherwise we won't add one (and S3 will default to private)
140 NSMutableDictionary *amzHeaders = [[[NSMutableDictionary alloc] init] autorelease]; 149 NSMutableDictionary *amzHeaders = [[[NSMutableDictionary alloc] init] autorelease];
@@ -142,18 +151,19 @@ static NSString *sharedSecretAccessKey = nil; @@ -142,18 +151,19 @@ static NSString *sharedSecretAccessKey = nil;
142 if ([self accessPolicy]) { 151 if ([self accessPolicy]) {
143 [amzHeaders setObject:[self accessPolicy] forKey:@"x-amz-acl"]; 152 [amzHeaders setObject:[self accessPolicy] forKey:@"x-amz-acl"];
144 } 153 }
145 - if ([self sourcePath]) { 154 + if ([self sourceKey]) {
146 - [amzHeaders setObject:[[self sourceBucket] stringByAppendingString:[self sourcePath]] forKey:@"x-amz-copy-source"]; 155 + NSString *path = [ASIS3Request stringByURLEncodingForS3Path:[self sourceKey]];
  156 + [amzHeaders setObject:[[self sourceBucket] stringByAppendingString:path] forKey:@"x-amz-copy-source"];
147 } 157 }
148 - for (NSString *key in [amzHeaders keyEnumerator]) { 158 + for (NSString *header in [amzHeaders keyEnumerator]) {
149 - canonicalizedAmzHeaders = [NSString stringWithFormat:@"%@%@:%@\n",canonicalizedAmzHeaders,[key lowercaseString],[amzHeaders objectForKey:key]]; 159 + canonicalizedAmzHeaders = [NSString stringWithFormat:@"%@%@:%@\n",canonicalizedAmzHeaders,[header lowercaseString],[amzHeaders objectForKey:header]];
150 [self addRequestHeader:key value:[amzHeaders objectForKey:key]]; 160 [self addRequestHeader:key value:[amzHeaders objectForKey:key]];
151 } 161 }
152 162
153 163
154 // Jump through hoops while eating hot food 164 // Jump through hoops while eating hot food
155 NSString *stringToSign; 165 NSString *stringToSign;
156 - if ([[self requestMethod] isEqualToString:@"PUT"] && ![self sourcePath]) { 166 + if ([[self requestMethod] isEqualToString:@"PUT"] && ![self sourceKey]) {
157 [self addRequestHeader:@"Content-Type" value:[self mimeType]]; 167 [self addRequestHeader:@"Content-Type" value:[self mimeType]];
158 stringToSign = [NSString stringWithFormat:@"PUT\n\n%@\n%@\n%@%@",[self mimeType],dateString,canonicalizedAmzHeaders,canonicalizedResource]; 168 stringToSign = [NSString stringWithFormat:@"PUT\n\n%@\n%@\n%@%@",[self mimeType],dateString,canonicalizedAmzHeaders,canonicalizedResource];
159 } else { 169 } else {
@@ -170,7 +180,7 @@ static NSString *sharedSecretAccessKey = nil; @@ -170,7 +180,7 @@ static NSString *sharedSecretAccessKey = nil;
170 - (void)requestFinished 180 - (void)requestFinished
171 { 181 {
172 // COPY requests return a 200 whether they succeed or fail, so we need to look at the XML to see if we were successful. 182 // COPY requests return a 200 whether they succeed or fail, so we need to look at the XML to see if we were successful.
173 - if ([self responseStatusCode] == 200 && [self sourcePath] && [self sourceBucket]) { 183 + if ([self responseStatusCode] == 200 && [self sourceKey] && [self sourceBucket]) {
174 [self parseError]; 184 [self parseError];
175 return; 185 return;
176 } 186 }
@@ -222,11 +232,11 @@ static NSString *sharedSecretAccessKey = nil; @@ -222,11 +232,11 @@ static NSString *sharedSecretAccessKey = nil;
222 [newRequest setAccessKey:[self accessKey]]; 232 [newRequest setAccessKey:[self accessKey]];
223 [newRequest setSecretAccessKey:[self secretAccessKey]]; 233 [newRequest setSecretAccessKey:[self secretAccessKey]];
224 [newRequest setBucket:[self bucket]]; 234 [newRequest setBucket:[self bucket]];
225 - [newRequest setPath:[self path]]; 235 + [newRequest setKey:[self key]];
226 [newRequest setMimeType:[self mimeType]]; 236 [newRequest setMimeType:[self mimeType]];
227 [newRequest setAccessPolicy:[self accessPolicy]]; 237 [newRequest setAccessPolicy:[self accessPolicy]];
228 [newRequest setSourceBucket:[self sourceBucket]]; 238 [newRequest setSourceBucket:[self sourceBucket]];
229 - [newRequest setSourcePath:[self sourcePath]]; 239 + [newRequest setSourceKey:[self sourceKey]];
230 return newRequest; 240 return newRequest;
231 } 241 }
232 242
@@ -277,7 +287,7 @@ static NSString *sharedSecretAccessKey = nil; @@ -277,7 +287,7 @@ static NSString *sharedSecretAccessKey = nil;
277 } 287 }
278 288
279 @synthesize bucket; 289 @synthesize bucket;
280 -@synthesize path; 290 +@synthesize key;
281 @synthesize dateString; 291 @synthesize dateString;
282 @synthesize mimeType; 292 @synthesize mimeType;
283 @synthesize accessKey; 293 @synthesize accessKey;
@@ -285,5 +295,5 @@ static NSString *sharedSecretAccessKey = nil; @@ -285,5 +295,5 @@ static NSString *sharedSecretAccessKey = nil;
285 @synthesize accessPolicy; 295 @synthesize accessPolicy;
286 @synthesize currentErrorString; 296 @synthesize currentErrorString;
287 @synthesize sourceBucket; 297 @synthesize sourceBucket;
288 -@synthesize sourcePath; 298 +@synthesize sourceKey;
289 @end 299 @end
@@ -43,9 +43,9 @@ static NSString *bucket = @""; @@ -43,9 +43,9 @@ static NSString *bucket = @"";
43 NSString *exampleBucket = @"johnsmith"; 43 NSString *exampleBucket = @"johnsmith";
44 44
45 // Test GET 45 // Test GET
46 - NSString *path = @"/photos/puppy.jpg"; 46 + NSString *key = @"photos/puppy.jpg";
47 NSString *dateString = @"Tue, 27 Mar 2007 19:36:42 +0000"; 47 NSString *dateString = @"Tue, 27 Mar 2007 19:36:42 +0000";
48 - ASIS3Request *request = [ASIS3Request requestWithBucket:exampleBucket path:path]; 48 + ASIS3Request *request = [ASIS3Request requestWithBucket:exampleBucket key:key];
49 [request setDateString:dateString]; 49 [request setDateString:dateString];
50 [request setSecretAccessKey:exampleSecretAccessKey]; 50 [request setSecretAccessKey:exampleSecretAccessKey];
51 [request setAccessKey:exampleAccessKey]; 51 [request setAccessKey:exampleAccessKey];
@@ -54,9 +54,9 @@ static NSString *bucket = @""; @@ -54,9 +54,9 @@ static NSString *bucket = @"";
54 GHAssertTrue(success,@"Failed to generate the correct authorisation header for a GET request"); 54 GHAssertTrue(success,@"Failed to generate the correct authorisation header for a GET request");
55 55
56 // Test PUT 56 // Test PUT
57 - path = @"/photos/puppy.jpg"; 57 + key = @"photos/puppy.jpg";
58 dateString = @"Tue, 27 Mar 2007 21:15:45 +0000"; 58 dateString = @"Tue, 27 Mar 2007 21:15:45 +0000";
59 - request = [ASIS3Request requestWithBucket:exampleBucket path:path]; 59 + request = [ASIS3Request requestWithBucket:exampleBucket key:key];
60 [request setRequestMethod:@"PUT"]; 60 [request setRequestMethod:@"PUT"];
61 [request setMimeType:@"image/jpeg"]; 61 [request setMimeType:@"image/jpeg"];
62 [request setDateString:dateString]; 62 [request setDateString:dateString];
@@ -80,9 +80,9 @@ static NSString *bucket = @""; @@ -80,9 +80,9 @@ static NSString *bucket = @"";
80 GHAssertTrue(success,@"Failed to generate the correct authorisation header for a list request"); 80 GHAssertTrue(success,@"Failed to generate the correct authorisation header for a list request");
81 81
82 // Test fetch ACL 82 // Test fetch ACL
83 - path = @"/?acl"; 83 + key = @"?acl";
84 dateString = @"Tue, 27 Mar 2007 19:44:46 +0000"; 84 dateString = @"Tue, 27 Mar 2007 19:44:46 +0000";
85 - request = [ASIS3Request requestWithBucket:exampleBucket path:path]; 85 + request = [ASIS3Request requestWithBucket:exampleBucket key:key];
86 [request setDateString:dateString]; 86 [request setDateString:dateString];
87 [request setSecretAccessKey:exampleSecretAccessKey]; 87 [request setSecretAccessKey:exampleSecretAccessKey];
88 [request setAccessKey:exampleAccessKey]; 88 [request setAccessKey:exampleAccessKey];
@@ -93,9 +93,9 @@ static NSString *bucket = @""; @@ -93,9 +93,9 @@ static NSString *bucket = @"";
93 // Test Unicode keys 93 // Test Unicode keys
94 // (I think Amazon's name for this example is misleading since this test actually only uses URL encoded strings) 94 // (I think Amazon's name for this example is misleading since this test actually only uses URL encoded strings)
95 exampleBucket = @"dictionary"; 95 exampleBucket = @"dictionary";
96 - path = @"/fran%C3%A7ais/pr%c3%a9f%c3%a8re"; 96 + key = @"fran%C3%A7ais/pr%c3%a9f%c3%a8re";
97 dateString = @"Wed, 28 Mar 2007 01:49:49 +0000"; 97 dateString = @"Wed, 28 Mar 2007 01:49:49 +0000";
98 - request = [ASIS3Request requestWithBucket:exampleBucket path:path]; 98 + request = [ASIS3Request requestWithBucket:exampleBucket key:key];
99 [request setDateString:dateString]; 99 [request setDateString:dateString];
100 [request setSecretAccessKey:exampleSecretAccessKey]; 100 [request setSecretAccessKey:exampleSecretAccessKey];
101 [request setAccessKey:exampleAccessKey]; 101 [request setAccessKey:exampleAccessKey];
@@ -112,9 +112,9 @@ static NSString *bucket = @""; @@ -112,9 +112,9 @@ static NSString *bucket = @"";
112 NSString *exampleSecretAccessKey = @"uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o"; 112 NSString *exampleSecretAccessKey = @"uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o";
113 NSString *exampleAccessKey = @"0PN5J17HBGZHT7JJ3X82"; 113 NSString *exampleAccessKey = @"0PN5J17HBGZHT7JJ3X82";
114 NSString *exampleBucket = @"johnsmith"; 114 NSString *exampleBucket = @"johnsmith";
115 - NSString *path = @"/photos/puppy.jpg"; 115 + NSString *key = @"photos/puppy.jpg";
116 NSString *dateString = @"Tue, 27 Mar 2007 19:36:42 +0000"; 116 NSString *dateString = @"Tue, 27 Mar 2007 19:36:42 +0000";
117 - ASIS3Request *request = [ASIS3Request requestWithBucket:exampleBucket path:path]; 117 + ASIS3Request *request = [ASIS3Request requestWithBucket:exampleBucket key:key];
118 [request setDateString:dateString]; 118 [request setDateString:dateString];
119 [request setSecretAccessKey:exampleSecretAccessKey]; 119 [request setSecretAccessKey:exampleSecretAccessKey];
120 [request setAccessKey:exampleAccessKey]; 120 [request setAccessKey:exampleAccessKey];
@@ -136,7 +136,7 @@ static NSString *bucket = @""; @@ -136,7 +136,7 @@ static NSString *bucket = @"";
136 BOOL success = (![secretAccessKey isEqualToString:@""] && ![accessKey isEqualToString:@""] && ![bucket isEqualToString:@""]); 136 BOOL success = (![secretAccessKey isEqualToString:@""] && ![accessKey isEqualToString:@""] && ![bucket isEqualToString:@""]);
137 GHAssertTrue(success,@"You need to supply your S3 access details to run the REST test (see the top of ASIS3RequestTests.m)"); 137 GHAssertTrue(success,@"You need to supply your S3 access details to run the REST test (see the top of ASIS3RequestTests.m)");
138 138
139 - NSString *path = @"/test"; 139 + NSString *key = @"test";
140 140
141 // Create the file 141 // Create the file
142 NSString *text = @"This is my content"; 142 NSString *text = @"This is my content";
@@ -144,7 +144,7 @@ static NSString *bucket = @""; @@ -144,7 +144,7 @@ static NSString *bucket = @"";
144 [[text dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:NO]; 144 [[text dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:NO];
145 145
146 // PUT the file 146 // PUT the file
147 - ASIS3Request *request = [ASIS3Request PUTRequestForFile:filePath withBucket:bucket path:path]; 147 + ASIS3Request *request = [ASIS3Request PUTRequestForFile:filePath withBucket:bucket key:key];
148 [request setSecretAccessKey:secretAccessKey]; 148 [request setSecretAccessKey:secretAccessKey];
149 [request setAccessKey:accessKey]; 149 [request setAccessKey:accessKey];
150 [request startSynchronous]; 150 [request startSynchronous];
@@ -152,7 +152,7 @@ static NSString *bucket = @""; @@ -152,7 +152,7 @@ static NSString *bucket = @"";
152 GHAssertTrue(success,@"Failed to PUT a file to S3"); 152 GHAssertTrue(success,@"Failed to PUT a file to S3");
153 153
154 // GET the file 154 // GET the file
155 - request = [ASIS3Request requestWithBucket:bucket path:path]; 155 + request = [ASIS3Request requestWithBucket:bucket key:key];
156 [request setSecretAccessKey:secretAccessKey]; 156 [request setSecretAccessKey:secretAccessKey];
157 [request setAccessKey:accessKey]; 157 [request setAccessKey:accessKey];
158 [request startSynchronous]; 158 [request startSynchronous];
@@ -160,14 +160,14 @@ static NSString *bucket = @""; @@ -160,14 +160,14 @@ static NSString *bucket = @"";
160 GHAssertTrue(success,@"Failed to GET the correct data from S3"); 160 GHAssertTrue(success,@"Failed to GET the correct data from S3");
161 161
162 // COPY the file 162 // COPY the file
163 - request = [ASIS3Request COPYRequestFromBucket:bucket path:path toBucket:bucket path:@"/test-copy"]; 163 + request = [ASIS3Request COPYRequestFromBucket:bucket key:key toBucket:bucket key:@"test-copy"];
164 [request setSecretAccessKey:secretAccessKey]; 164 [request setSecretAccessKey:secretAccessKey];
165 [request setAccessKey:accessKey]; 165 [request setAccessKey:accessKey];
166 [request startSynchronous]; 166 [request startSynchronous];
167 GHAssertNil([request error],@"Failed to COPY a file"); 167 GHAssertNil([request error],@"Failed to COPY a file");
168 168
169 // GET the copy 169 // GET the copy
170 - request = [ASIS3Request requestWithBucket:bucket path:@"/test-copy"]; 170 + request = [ASIS3Request requestWithBucket:bucket key:@"test-copy"];
171 [request setSecretAccessKey:secretAccessKey]; 171 [request setSecretAccessKey:secretAccessKey];
172 [request setAccessKey:accessKey]; 172 [request setAccessKey:accessKey];
173 [request startSynchronous]; 173 [request startSynchronous];
@@ -176,7 +176,7 @@ static NSString *bucket = @""; @@ -176,7 +176,7 @@ static NSString *bucket = @"";
176 176
177 177
178 // HEAD the copy 178 // HEAD the copy
179 - request = [ASIS3Request HEADRequestWithBucket:bucket path:@"/test-copy"]; 179 + request = [ASIS3Request HEADRequestWithBucket:bucket key:@"test-copy"];
180 [request setSecretAccessKey:secretAccessKey]; 180 [request setSecretAccessKey:secretAccessKey];
181 [request setAccessKey:accessKey]; 181 [request setAccessKey:accessKey];
182 [request startSynchronous]; 182 [request startSynchronous];
@@ -194,7 +194,7 @@ static NSString *bucket = @""; @@ -194,7 +194,7 @@ static NSString *bucket = @"";
194 GHAssertTrue(success,@"The file didn't show up in the list"); 194 GHAssertTrue(success,@"The file didn't show up in the list");
195 195
196 // DELETE the file 196 // DELETE the file
197 - request = [ASIS3Request requestWithBucket:bucket path:path]; 197 + request = [ASIS3Request requestWithBucket:bucket key:key];
198 [request setSecretAccessKey:secretAccessKey]; 198 [request setSecretAccessKey:secretAccessKey];
199 [request setRequestMethod:@"DELETE"]; 199 [request setRequestMethod:@"DELETE"];
200 [request setAccessKey:accessKey]; 200 [request setAccessKey:accessKey];
@@ -203,7 +203,7 @@ static NSString *bucket = @""; @@ -203,7 +203,7 @@ static NSString *bucket = @"";
203 GHAssertTrue(success,@"Failed to DELETE the file from S3"); 203 GHAssertTrue(success,@"Failed to DELETE the file from S3");
204 204
205 // (Also DELETE the copy we made) 205 // (Also DELETE the copy we made)
206 - request = [ASIS3Request requestWithBucket:bucket path:@"/test-copy"]; 206 + request = [ASIS3Request requestWithBucket:bucket key:@"test-copy"];
207 [request setSecretAccessKey:secretAccessKey]; 207 [request setSecretAccessKey:secretAccessKey];
208 [request setRequestMethod:@"DELETE"]; 208 [request setRequestMethod:@"DELETE"];
209 [request setAccessKey:accessKey]; 209 [request setAccessKey:accessKey];
@@ -212,7 +212,7 @@ static NSString *bucket = @""; @@ -212,7 +212,7 @@ static NSString *bucket = @"";
212 GHAssertTrue(success,@"Failed to DELETE the copy from S3"); 212 GHAssertTrue(success,@"Failed to DELETE the copy from S3");
213 213
214 // Attempt to COPY the file, even though it is no longer there 214 // Attempt to COPY the file, even though it is no longer there
215 - request = [ASIS3Request COPYRequestFromBucket:bucket path:path toBucket:bucket path:@"/test-copy"]; 215 + request = [ASIS3Request COPYRequestFromBucket:bucket key:key toBucket:bucket key:@"test-copy"];
216 [request setSecretAccessKey:secretAccessKey]; 216 [request setSecretAccessKey:secretAccessKey];
217 [request setAccessKey:accessKey]; 217 [request setAccessKey:accessKey];
218 [request startSynchronous]; 218 [request startSynchronous];
@@ -223,7 +223,7 @@ static NSString *bucket = @""; @@ -223,7 +223,7 @@ static NSString *bucket = @"";
223 223
224 // PUT some data 224 // PUT some data
225 NSData *data = [@"Hello" dataUsingEncoding:NSUTF8StringEncoding]; 225 NSData *data = [@"Hello" dataUsingEncoding:NSUTF8StringEncoding];
226 - request = [ASIS3Request PUTRequestForData:data withBucket:bucket path:path]; 226 + request = [ASIS3Request PUTRequestForData:data withBucket:bucket key:key];
227 [request setMimeType:@"text/plain"]; 227 [request setMimeType:@"text/plain"];
228 [request setSecretAccessKey:secretAccessKey]; 228 [request setSecretAccessKey:secretAccessKey];
229 [request setAccessKey:accessKey]; 229 [request setAccessKey:accessKey];
@@ -232,7 +232,7 @@ static NSString *bucket = @""; @@ -232,7 +232,7 @@ static NSString *bucket = @"";
232 GHAssertTrue(success,@"Failed to PUT data to S3"); 232 GHAssertTrue(success,@"Failed to PUT data to S3");
233 233
234 // GET the data to check it uploaded properly 234 // GET the data to check it uploaded properly
235 - request = [ASIS3Request requestWithBucket:bucket path:path]; 235 + request = [ASIS3Request requestWithBucket:bucket key:key];
236 [request setSecretAccessKey:secretAccessKey]; 236 [request setSecretAccessKey:secretAccessKey];
237 [request setAccessKey:accessKey]; 237 [request setAccessKey:accessKey];
238 [request startSynchronous]; 238 [request startSynchronous];
@@ -240,7 +240,7 @@ static NSString *bucket = @""; @@ -240,7 +240,7 @@ static NSString *bucket = @"";
240 GHAssertTrue(success,@"Failed to GET the correct data from S3"); 240 GHAssertTrue(success,@"Failed to GET the correct data from S3");
241 241
242 // clean up (Delete it) 242 // clean up (Delete it)
243 - request = [ASIS3Request requestWithBucket:bucket path:path]; 243 + request = [ASIS3Request requestWithBucket:bucket key:key];
244 [request setSecretAccessKey:secretAccessKey]; 244 [request setSecretAccessKey:secretAccessKey];
245 [request setRequestMethod:@"DELETE"]; 245 [request setRequestMethod:@"DELETE"];
246 [request setAccessKey:accessKey]; 246 [request setAccessKey:accessKey];
@@ -266,8 +266,8 @@ static NSString *bucket = @""; @@ -266,8 +266,8 @@ static NSString *bucket = @"";
266 NSString *filePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"testfile.txt"]; 266 NSString *filePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"testfile.txt"];
267 [[text dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:NO]; 267 [[text dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:NO];
268 268
269 - NSString *path = @"/gzipped-data"; 269 + NSString *key = @"gzipped-data";
270 - ASIS3Request *request = [ASIS3Request PUTRequestForFile:filePath withBucket:bucket path:path]; 270 + ASIS3Request *request = [ASIS3Request PUTRequestForFile:filePath withBucket:bucket key:key];
271 [request setSecretAccessKey:secretAccessKey]; 271 [request setSecretAccessKey:secretAccessKey];
272 [request setAccessKey:accessKey]; 272 [request setAccessKey:accessKey];
273 [request setShouldCompressRequestBody:YES]; 273 [request setShouldCompressRequestBody:YES];
@@ -277,7 +277,7 @@ static NSString *bucket = @""; @@ -277,7 +277,7 @@ static NSString *bucket = @"";
277 GHAssertTrue(success,@"Failed to PUT the gzipped file"); 277 GHAssertTrue(success,@"Failed to PUT the gzipped file");
278 278
279 // GET the file 279 // GET the file
280 - request = [ASIS3Request requestWithBucket:bucket path:path]; 280 + request = [ASIS3Request requestWithBucket:bucket key:key];
281 [request setSecretAccessKey:secretAccessKey]; 281 [request setSecretAccessKey:secretAccessKey];
282 [request setAccessKey:accessKey]; 282 [request setAccessKey:accessKey];
283 [request startSynchronous]; 283 [request startSynchronous];
@@ -308,8 +308,8 @@ static NSString *bucket = @""; @@ -308,8 +308,8 @@ static NSString *bucket = @"";
308 NSString *text = [NSString stringWithFormat:@"This is the content of file #%hi",i]; 308 NSString *text = [NSString stringWithFormat:@"This is the content of file #%hi",i];
309 NSString *filePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:[NSString stringWithFormat:@"%hi.txt",i]]; 309 NSString *filePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:[NSString stringWithFormat:@"%hi.txt",i]];
310 [[text dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:NO]; 310 [[text dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:NO];
311 - NSString *path = [NSString stringWithFormat:@"/test-file/%hi",i]; 311 + NSString *key = [NSString stringWithFormat:@"test-file/%hi",i];
312 - ASIS3Request *request = [ASIS3Request PUTRequestForFile:filePath withBucket:bucket path:path]; 312 + ASIS3Request *request = [ASIS3Request PUTRequestForFile:filePath withBucket:bucket key:key];
313 [request setSecretAccessKey:secretAccessKey]; 313 [request setSecretAccessKey:secretAccessKey];
314 [request setAccessKey:accessKey]; 314 [request setAccessKey:accessKey];
315 [request startSynchronous]; 315 [request startSynchronous];
@@ -425,23 +425,23 @@ static NSString *bucket = @""; @@ -425,23 +425,23 @@ static NSString *bucket = @"";
425 // Ensure class convenience constructors return an instance of our subclass 425 // Ensure class convenience constructors return an instance of our subclass
426 - (void)testSubclasses 426 - (void)testSubclasses
427 { 427 {
428 - ASIS3RequestSubclass *instance = [ASIS3RequestSubclass requestWithBucket:@"bucket" path:@"path"]; 428 + ASIS3RequestSubclass *instance = [ASIS3RequestSubclass requestWithBucket:@"bucket" key:@"key"];
429 BOOL success = [instance isKindOfClass:[ASIS3RequestSubclass class]]; 429 BOOL success = [instance isKindOfClass:[ASIS3RequestSubclass class]];
430 GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class"); 430 GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class");
431 431
432 - instance = [ASIS3RequestSubclass PUTRequestForFile:@"/file" withBucket:@"bucket" path:@"path"]; 432 + instance = [ASIS3RequestSubclass PUTRequestForFile:@"/file" withBucket:@"bucket" key:@"key"];
433 success = [instance isKindOfClass:[ASIS3RequestSubclass class]]; 433 success = [instance isKindOfClass:[ASIS3RequestSubclass class]];
434 GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class"); 434 GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class");
435 435
436 - instance = [ASIS3RequestSubclass DELETERequestWithBucket:@"bucket" path:@"path"]; 436 + instance = [ASIS3RequestSubclass DELETERequestWithBucket:@"bucket" key:@"key"];
437 success = [instance isKindOfClass:[ASIS3RequestSubclass class]]; 437 success = [instance isKindOfClass:[ASIS3RequestSubclass class]];
438 GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class"); 438 GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class");
439 439
440 - instance = [ASIS3RequestSubclass COPYRequestFromBucket:@"bucket" path:@"path" toBucket:@"bucket" path:@"path2"]; 440 + instance = [ASIS3RequestSubclass COPYRequestFromBucket:@"bucket" key:@"key" toBucket:@"bucket" key:@"key2"];
441 success = [instance isKindOfClass:[ASIS3RequestSubclass class]]; 441 success = [instance isKindOfClass:[ASIS3RequestSubclass class]];
442 GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class"); 442 GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class");
443 443
444 - instance = [ASIS3RequestSubclass HEADRequestWithBucket:@"bucket" path:@"path"]; 444 + instance = [ASIS3RequestSubclass HEADRequestWithBucket:@"bucket" key:@"key"];
445 success = [instance isKindOfClass:[ASIS3RequestSubclass class]]; 445 success = [instance isKindOfClass:[ASIS3RequestSubclass class]];
446 GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class"); 446 GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class");
447 447
@@ -480,8 +480,8 @@ static NSString *bucket = @""; @@ -480,8 +480,8 @@ static NSString *bucket = @"";
480 480
481 int i; 481 int i;
482 for (i=0; i<5; i++) { 482 for (i=0; i<5; i++) {
483 - NSString *path = [NSString stringWithFormat:@"/images/%hi.jpg",i+1]; 483 + NSString *key = [NSString stringWithFormat:@"images/%hi.jpg",i+1];
484 - ASIS3Request *s3Request = [ASIS3Request requestWithBucket:bucket path:path]; 484 + ASIS3Request *s3Request = [ASIS3Request requestWithBucket:bucket key:key];
485 [s3Request setSecretAccessKey:secretAccessKey]; 485 [s3Request setSecretAccessKey:secretAccessKey];
486 [s3Request setAccessKey:accessKey]; 486 [s3Request setAccessKey:accessKey];
487 NSString *downloadPath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:[NSString stringWithFormat:@"%hi.jpg",i+1]]; 487 NSString *downloadPath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:[NSString stringWithFormat:@"%hi.jpg",i+1]];
@@ -509,7 +509,7 @@ static NSString *bucket = @""; @@ -509,7 +509,7 @@ static NSString *bucket = @"";
509 { 509 {
510 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 510 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
511 511
512 - ASIS3Request *request = [ASIS3Request requestWithBucket:@"foo" path:@"eep"]; 512 + ASIS3Request *request = [ASIS3Request requestWithBucket:@"foo" key:@"eep"];
513 ASIS3Request *request2 = [request copy]; 513 ASIS3Request *request2 = [request copy];
514 GHAssertNotNil(request2,@"Failed to create a copy"); 514 GHAssertNotNil(request2,@"Failed to create a copy");
515 515