Statistics
| Branch: | Revision:

root / asi-http-request-with-pithos / Classes / Pithos / ASIPithosObjectRequest.m @ 2f816d2a

History | View | Annotate | Download (102 kB)

1
//  ASIPithosObjectRequest.m
2
//  Based on ASICloudFilesObjectRequest.m
3
//
4
// Copyright 2011-2012 GRNET S.A. All rights reserved.
5
//
6
// Redistribution and use in source and binary forms, with or
7
// without modification, are permitted provided that the following
8
// conditions are met:
9
// 
10
//   1. Redistributions of source code must retain the above
11
//      copyright notice, this list of conditions and the following
12
//      disclaimer.
13
// 
14
//   2. Redistributions in binary form must reproduce the above
15
//      copyright notice, this list of conditions and the following
16
//      disclaimer in the documentation and/or other materials
17
//      provided with the distribution.
18
// 
19
// THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
20
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
23
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
// POSSIBILITY OF SUCH DAMAGE.
31
// 
32
// The views and conclusions contained in the software and
33
// documentation are those of the authors and should not be
34
// interpreted as representing official policies, either expressed
35
// or implied, of GRNET S.A.
36

    
37
#import "ASIPithosObjectRequest.h"
38
#import "ASIPithos.h"
39
#import "ASIPithosObject.h"
40

    
41
@interface ASIPithosObjectRequest (Private)
42
- (void)parseXMLData;
43
- (void)prepareObjectRequestWithETag:(NSString *)eTag 
44
                         contentType:(NSString *)contentType 
45
                     contentEncoding:(NSString *)contentEncoding 
46
                  contentDisposition:(NSString *)contentDisposition 
47
                            manifest:(NSString *)manifest 
48
                             sharing:(NSString *)sharing 
49
                            isPublic:(NSUInteger)isPublic 
50
                            metadata:(NSDictionary *)newMetadata;
51
@end
52

    
53
@implementation ASIPithosObjectRequest
54
@synthesize objectRequestType;
55
@synthesize containerName, objectName;
56
@synthesize currentObject;
57

    
58
#pragma mark -
59
#pragma mark Constructors
60

    
61
+ (id)storageRequestWithMethod:(NSString *)method pithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
62
                   queryString:(NSString *)queryString {
63
    NSString *urlString = [NSString stringWithFormat:@"%@/%@/%@", 
64
                           pithos.storageURL, 
65
                           [self encodeToPercentEscape:containerName], 
66
                           [((NSString *)CFURLCreateStringByAddingPercentEscapes(NULL, 
67
                                                                                 (CFStringRef)objectName, 
68
                                                                                 NULL, 
69
                                                                                 (CFStringRef)@"!*'();:@&=+$,?%#[]", 
70
                                                                                 kCFStringEncodingUTF8)) autorelease]];
71
    if (queryString)
72
        urlString = [urlString stringByAppendingString:queryString];
73
    
74
	ASIPithosObjectRequest *request = [[[self alloc] initWithURL:[NSURL URLWithString:urlString]] autorelease];
75
	[request setRequestMethod:method];
76
	[request addRequestHeader:@"X-Auth-Token" value:pithos.authToken];
77
    request.containerName = containerName;
78
    request.objectName = objectName;
79
	return request;
80
}
81

    
82
+ (id)storageRequestWithMethod:(NSString *)method pithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName {
83
	return [self storageRequestWithMethod:method pithos:pithos containerName:containerName objectName:(NSString *)objectName queryString:nil];
84
}
85

    
86
#pragma mark -
87
#pragma mark Memory Management
88

    
89
- (void)dealloc {
90
    [currentObject release];
91
    [versions release];
92
    [hashes release];
93
    [blockHash release];
94
    [objectName release];
95
    [containerName release];
96
	[super dealloc];
97
}
98

    
99
#pragma mark -
100
#pragma mark Internal
101

    
102
- (void)parseXMLData {
103
    if ((objectRequestType == ASIPithosObjectRequestHashmap)|| (objectRequestType == ASIPithosObjectRequestHashmapWrite)) {
104
        hashes = [[NSMutableArray alloc] init];
105
    } else if (objectRequestType == ASIPithosObjectRequestVersions) {
106
        versions = [[NSMutableArray alloc] init];
107
    }
108
    
109
    NSXMLParser *parser = [[[NSXMLParser alloc] initWithData:[self responseData]] autorelease];
110
    [parser setDelegate:self];
111
    [parser setShouldProcessNamespaces:NO];
112
    [parser setShouldReportNamespacePrefixes:NO];
113
    [parser setShouldResolveExternalEntities:NO];
114
    [parser parse];
115
}
116

    
117
- (void)prepareObjectRequestWithETag:(NSString *)eTag 
118
                         contentType:(NSString *)contentType 
119
                     contentEncoding:(NSString *)contentEncoding 
120
                  contentDisposition:(NSString *)contentDisposition 
121
                            manifest:(NSString *)manifest 
122
                             sharing:(NSString *)sharing 
123
                            isPublic:(NSUInteger)isPublic 
124
                            metadata:(NSDictionary *)newMetadata {
125
    if (eTag)
126
        [self addRequestHeader:@"ETag" value:eTag];
127
    if (contentType)
128
        [self addRequestHeader:@"Content-Type" value:contentType];
129
    if (contentEncoding)
130
        [self addRequestHeader:@"Content-Encoding" value:[self encodeToPercentEscape:contentEncoding]];
131
    if (contentDisposition)
132
        [self addRequestHeader:@"Content-Disposition" value:[self encodeToPercentEscape:contentDisposition]];
133
    if (manifest)
134
        [self addRequestHeader:@"X-Object-Manifest" value:[self encodeToPercentEscape:manifest]];
135
    if (sharing)
136
        [self addRequestHeader:@"X-Object-Sharing" value:[self encodeToPercentEscape:sharing]];
137
    if (isPublic == ASIPithosObjectRequestPublicTrue) {
138
        [self addRequestHeader:@"X-Object-Public" value:@"true"];
139
    } else if (isPublic == ASIPithosObjectRequestPublicFalse) {
140
        [self addRequestHeader:@"X-Object-Public" value:@"false"];
141
    }
142
    
143
    if (newMetadata) {
144
        for (NSString *key in [newMetadata keyEnumerator]) {
145
            [self addRequestHeader:[self encodeToPercentEscape:[NSString stringWithFormat:@"X-Object-Meta-%@", key]] 
146
                             value:[self encodeToPercentEscape:[newMetadata objectForKey:key]]];
147
        }
148
    }
149
}
150

    
151
#pragma mark -
152
#pragma mark HEAD
153

    
154
// HEAD storageURL/container/object
155
+ (id)objectMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName {
156
    return [self storageRequestWithMethod:@"HEAD" pithos:pithos containerName:containerName objectName:objectName];
157
}
158

    
159
// HEAD storageURL/container/object?[version=version]
160
+ (id)objectMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
161
                              version:(NSString *)version {
162
    NSString *queryString = nil;
163
    if (version)
164
        queryString = [NSString stringWithFormat:@"?version=%@", version];
165
	return [self storageRequestWithMethod:@"HEAD" pithos:pithos containerName:containerName objectName:objectName queryString:queryString];
166
}
167

    
168
// HEAD storageURL/container/object?[version=version] [If-Match]
169
+ (id)objectMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
170
                              version:(NSString *)version 
171
                              ifMatch:(NSString *)matchETag {
172
    ASIPithosObjectRequest *request = [self objectMetadataRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
173
    [request addRequestIfMatchHeader:matchETag];
174
    return request;
175
}
176

    
177
// HEAD storageURL/container/object?[version=version] [If-None-Match]
178
+ (id)objectMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
179
                              version:(NSString *)version 
180
                          ifNoneMatch:(NSString *)matchETag {
181
    ASIPithosObjectRequest *request = [self objectMetadataRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
182
    [request addRequestIfNoneMatchHeader:matchETag];
183
    return request;
184
}
185

    
186
// HEAD storageURL/container/object?[version=version] [If-Modified-Since]
187
+ (id)objectMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
188
                              version:(NSString *)version 
189
                      ifModifiedSince:(NSDate *)sinceTimestamp {
190
    ASIPithosObjectRequest *request = [self objectMetadataRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
191
    [request addRequestIfModifiedSinceHeader:sinceTimestamp];
192
    return request;
193
}
194

    
195
// HEAD storageURL/container/object?[version=version] [If-Unmodified-Since]
196
+ (id)objectMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
197
                              version:(NSString *)version 
198
                    ifUnmodifiedSince:(NSDate *)sinceTimestamp {
199
    ASIPithosObjectRequest *request = [self objectMetadataRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
200
    [request addRequestIfUnmodifiedSinceHeader:sinceTimestamp];
201
    return request;
202
}
203

    
204
- (NSString *)eTag {
205
    // Etag, instead of ETag, because CFNetwork changes it
206
    // http://groups.google.com/group/asihttprequest/browse_thread/thread/7119f1a0ccf26fdf
207
	return [[self responseHeaders] objectForKey:@"Etag"];
208
}
209

    
210
- (NSString *)objectHash {
211
    return [[self responseHeaders] objectForKey:@"X-Object-Hash"];
212
}
213

    
214
- (NSString *)UUID {
215
    return [[self responseHeaders] objectForKey:@"X-Object-UUID"];
216
}
217

    
218
- (NSUInteger)objectContentLength {
219
    NSString *objectContentLengthString = [[self responseHeaders] objectForKey:@"Content-Length"];
220
    if (objectContentLengthString)
221
        return [objectContentLengthString intValue];
222
    return 0;
223
}
224

    
225
- (NSString *)contentType {
226
	return [[self responseHeaders] objectForKey:@"Content-Type"];
227
}
228

    
229
- (NSDate *)lastModified {
230
    NSString *lastModifiedString = [[self responseHeaders] objectForKey:@"Last-Modified"];
231
    if (lastModifiedString)
232
        return [[self dateFormatterWithFormatId:1] dateFromString:lastModifiedString];
233
    return nil;
234
}
235

    
236
- (NSString *)contentEncoding {
237
	return [self decodeFromPercentEscape:[[self responseHeaders] objectForKey:@"Content-Encoding"]];
238
}
239

    
240
- (NSString *)contentDisposition {
241
	return [self decodeFromPercentEscape:[[self responseHeaders] objectForKey:@"Content-Disposition"]];
242
}
243

    
244
- (NSString *)version {
245
	return [[self responseHeaders] objectForKey:@"X-Object-Version"];
246
}
247

    
248
- (NSDate *)versionTimestamp {
249
    NSString *versionTimestampString = [[self responseHeaders] objectForKey:@"X-Object-Version-Timestamp"];
250
    if (versionTimestampString)
251
        return [[self dateFormatterWithFormatId:1] dateFromString:versionTimestampString];
252
    return nil;
253
}
254

    
255
- (NSString *)modifiedBy {
256
	return [[self responseHeaders] objectForKey:@"X-Object-Modified-By"];
257
}
258

    
259
- (NSString *)manifest {
260
	return [self decodeFromPercentEscape:[[self responseHeaders] objectForKey:@"X-Object-Manifest"]];
261
}
262

    
263
- (NSString *)sharing {
264
	return [self decodeFromPercentEscape:[[self responseHeaders] objectForKey:@"X-Object-Sharing"]];
265
}
266

    
267
- (NSString *)sharedBy {
268
	return [self decodeFromPercentEscape:[[self responseHeaders] objectForKey:@"X-Object-Shared-By"]];
269
}
270

    
271
- (NSString *)publicURI {
272
	return [[self responseHeaders] objectForKey:@"X-Object-Public"];
273
}
274

    
275
- (NSDictionary *)metadata {
276
    if (metadata == nil) {
277
        metadata = [self getHeadersDictionaryForPrefix:@"X-Object-Meta-"];
278
        [metadata retain];
279
    }
280
    return metadata;
281
}
282

    
283
- (NSString *)allowedTo {
284
    return [[self responseHeaders] objectForKey:@"X-Object-Allowed-To"];
285
}
286

    
287
- (ASIPithosObject *)object {
288
    ASIPithosObject *object = [ASIPithosObject object];
289
    object.name = objectName;
290
    object.hash = [self eTag];
291
    object.objectHash = [self objectHash];
292
    object.UUID = [self UUID];
293
    object.contentType = [self contentType];
294
    object.contentEncoding = [self contentEncoding];
295
    object.contentDisposition = [self contentDisposition];
296
    object.lastModified = [self lastModified];
297
    object.version = [self version];
298
    object.versionTimestamp = [self versionTimestamp];
299
    object.modifiedBy = [self modifiedBy];
300
    object.manifest = [self manifest];
301
    object.sharing = [self sharing];
302
    object.sharedBy = [self sharedBy];
303
    object.publicURI = [self publicURI];
304
    object.metadata = (NSMutableDictionary *)[self metadata];
305
    object.allowedTo = [self allowedTo];
306
    
307
    if (objectRequestType == ASIPithosObjectRequestData) {
308
        object.bytes = [self objectContentLength];
309
        object.data = [self responseData];
310
    } else if (objectRequestType == ASIPithosObjectRequestHashmap) {
311
        object.bytes = [self bytes];
312
    }
313
    
314
    return object;
315
}
316

    
317
#pragma mark -
318
#pragma mark GET
319

    
320
// GET storageURL/container/object
321
+ (id)objectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName {
322
    return [self storageRequestWithMethod:@"GET" pithos:pithos containerName:containerName objectName:objectName];
323
}
324

    
325
// GET storageURL/container/object?[version=version]
326
+ (id)objectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
327
                          version:(NSString *)version {
328
    NSString *queryString = nil;
329
    if (version)
330
        queryString = [NSString stringWithFormat:@"?version=%@", version];
331
	return [self storageRequestWithMethod:@"GET" pithos:pithos containerName:containerName objectName:objectName queryString:queryString];
332
}
333

    
334
// GET storageURL/container/object?[version=version] [If-Match]
335
+ (id)objectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
336
                          version:(NSString *)version 
337
                          ifMatch:(NSString *)matchETag {
338
    ASIPithosObjectRequest *request = [self objectDataRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
339
    [request addRequestIfMatchHeader:matchETag];
340
    return request;
341
}
342

    
343
// GET storageURL/container/object?[version=version] [If-None-Match]
344
+ (id)objectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
345
                          version:(NSString *)version 
346
                      ifNoneMatch:(NSString *)matchETag {
347
    ASIPithosObjectRequest *request = [self objectDataRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
348
    [request addRequestIfNoneMatchHeader:matchETag];
349
    return request;
350
}
351

    
352
// GET storageURL/container/object?[version=version] [If-Modified-Since]
353
+ (id)objectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
354
                          version:(NSString *)version 
355
                  ifModifiedSince:(NSDate *)sinceTimestamp {
356
    ASIPithosObjectRequest *request = [self objectDataRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
357
    [request addRequestIfModifiedSinceHeader:sinceTimestamp];
358
    return request;
359
}
360

    
361
// GET storageURL/container/object?[version=version] [If-Unmodified-Since]
362
+ (id)objectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
363
                          version:(NSString *)version 
364
                ifUnmodifiedSince:(NSDate *)sinceTimestamp {
365
    ASIPithosObjectRequest *request = [self objectDataRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
366
    [request addRequestIfUnmodifiedSinceHeader:sinceTimestamp];
367
    return request;
368
}
369

    
370
// GET storageURL/container/object?[version=version] [Range [If-Range]]
371
+ (id)objectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
372
                          version:(NSString *)version 
373
                            range:(NSString *)rangeString {
374
    ASIPithosObjectRequest *request = [self objectDataRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
375
    [request addRequestRangeHeader:rangeString];
376
    return request;
377
}
378

    
379
// GET storageURL/container/object?[version=version] [Range [If-Range]]
380
+ (id)objectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
381
                          version:(NSString *)version 
382
                            range:(NSString *)rangeString 
383
                      ifRangeETag:(NSString *)rangeETag {
384
    ASIPithosObjectRequest *request = [self objectDataRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
385
    [request addRequestRangeHeader:rangeString ifRangeETag:rangeETag];
386
    return request;
387
}
388

    
389
+ (id)objectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
390
                          version:(NSString *)version 
391
                            range:(NSString *)rangeString 
392
                 ifRangeTimestamp:(NSDate *)rangeTimestamp {
393
    ASIPithosObjectRequest *request = [self objectDataRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
394
    [request addRequestRangeHeader:rangeString ifRangeTimestamp:rangeTimestamp];
395
    return request;
396
}
397

    
398
// GET storageURL/container/object?[version=version] [Range] [If-Match]
399
+ (id)objectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
400
                          version:(NSString *)version 
401
                            range:(NSString *)rangeString 
402
                          ifMatch:(NSString *)matchETag {
403
    ASIPithosObjectRequest *request = [self objectDataRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
404
    [request addRequestRangeHeader:rangeString];
405
    [request addRequestIfMatchHeader:matchETag];
406
    return request;    
407
}
408

    
409
// GET storageURL/container/object?[version=version] [Range] [If-None-Match]
410
+ (id)objectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
411
                          version:(NSString *)version 
412
                            range:(NSString *)rangeString 
413
                      ifNoneMatch:(NSString *)matchETag {
414
    ASIPithosObjectRequest *request = [self objectDataRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
415
    [request addRequestRangeHeader:rangeString];
416
    [request addRequestIfNoneMatchHeader:matchETag];
417
    return request;
418
}
419

    
420
- (NSData *)data {
421
    return [self responseData];
422
}
423

    
424
// GET storageURL/container/object?format=xml&hashmap=
425
+ (id)objectHashmapRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName {
426
    ASIPithosObjectRequest *request = [self storageRequestWithMethod:@"GET" pithos:pithos containerName:containerName objectName:objectName queryString:@"?format=xml&hashmap="];
427
    request.objectRequestType = ASIPithosObjectRequestHashmap;
428
    return request;
429
}
430

    
431
// GET storageURL/container/object?format=xml&hashmap=[&version=version]
432
+ (id)objectHashmapRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
433
                             version:(NSString *)version {
434
    NSString *queryString = @"?format=xml&hashmap=";
435
    if (version)
436
        queryString = [queryString stringByAppendingString:[NSString stringWithFormat:@"&version=%@", version]];
437
	ASIPithosObjectRequest *request = [self storageRequestWithMethod:@"GET" pithos:pithos containerName:containerName objectName:objectName queryString:queryString];
438
    request.objectRequestType = ASIPithosObjectRequestHashmap;
439
    return request;
440
}
441

    
442
// GET storageURL/container/object?format=xml&hashmap=[&version=version] [If-Match]
443
+ (id)objectHashmapRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
444
                             version:(NSString *)version 
445
                             ifMatch:(NSString *)matchETag {
446
    ASIPithosObjectRequest *request = [self objectHashmapRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
447
    [request addRequestIfMatchHeader:matchETag];
448
    return request;
449
}
450

    
451
// GET storageURL/container/object?format=xml&hashmap=[&version=version] [If-NoneMatch]
452
+ (id)objectHashmapRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
453
                             version:(NSString *)version 
454
                         ifNoneMatch:(NSString *)matchETag {
455
    ASIPithosObjectRequest *request = [self objectHashmapRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
456
    [request addRequestIfNoneMatchHeader:matchETag];
457
    return request;
458
}
459

    
460
// GET storageURL/container/object?format=xml&hashmap=[&version=version] [If-Modified-Since]
461
+ (id)objectHashmapRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
462
                             version:(NSString *)version 
463
                     ifModifiedSince:(NSDate *)sinceTimestamp {
464
    ASIPithosObjectRequest *request = [self objectHashmapRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
465
    [request addRequestIfModifiedSinceHeader:sinceTimestamp];
466
    return request;
467
}
468

    
469
// GET storageURL/container/object?format=xml&hashmap=[&version=version] [If-Unmodified-Since]
470
+ (id)objectHashmapRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
471
                             version:(NSString *)version 
472
                   ifUnmodifiedSince:(NSDate *)sinceTimestamp {
473
    ASIPithosObjectRequest *request = [self objectHashmapRequestWithPithos:pithos containerName:containerName objectName:objectName version:version];
474
    [request addRequestIfUnmodifiedSinceHeader:sinceTimestamp];
475
    return request;
476
}
477

    
478
- (NSUInteger)blockSize {
479
    if (hashes == nil)
480
        [self parseXMLData];
481
    return blockSize;
482
}
483

    
484
- (NSString *)blockHash {
485
    if (hashes == nil)
486
        [self parseXMLData];
487
    return blockHash;
488
}
489

    
490
- (NSArray *)hashes {
491
    if (hashes == nil)
492
        [self parseXMLData];
493
    return hashes;
494
}
495

    
496
- (NSUInteger)bytes {
497
    if (hashes == nil)
498
        [self parseXMLData];
499
    return bytes;
500
}
501

    
502
// GET storageURL/container/object?format=xml&version=list
503
+ (id)objectVersionsRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName {
504
    ASIPithosObjectRequest *request = [self storageRequestWithMethod:@"GET" pithos:pithos containerName:containerName objectName:objectName queryString:@"?format=xml&version=list"];
505
    request.objectRequestType = ASIPithosObjectRequestVersions;
506
    return request;
507
}
508

    
509
// GET storageURL/container/object?format=xml&version=list [If-Match]
510
+ (id)objectVersionsRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
511
                              ifMatch:(NSString *)matchETag {
512
    ASIPithosObjectRequest *request = [self objectVersionsRequestWithPithos:pithos containerName:containerName objectName:objectName];
513
    [request addRequestIfMatchHeader:matchETag];
514
    return request;
515
}
516

    
517
// GET storageURL/container/object?format=xml&version=list [If-None-Match]
518
+ (id)objectVersionsRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
519
                          ifNoneMatch:(NSString *)matchETag {
520
    ASIPithosObjectRequest *request = [self objectVersionsRequestWithPithos:pithos containerName:containerName objectName:objectName];
521
    [request addRequestIfNoneMatchHeader:matchETag];
522
    return request;
523
}
524

    
525
// GET storageURL/container/object?format=xml&version=list [If-Modified-Since]
526
+ (id)objectVersionsRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
527
                      ifModifiedSince:(NSDate *)sinceTimestamp {
528
    ASIPithosObjectRequest *request = [self objectVersionsRequestWithPithos:pithos containerName:containerName objectName:objectName];
529
    [request addRequestIfModifiedSinceHeader:sinceTimestamp];
530
    return request;
531
}
532

    
533
// GET storageURL/container/object?format=xml&version=list [If-Unmodified-Since]
534
+ (id)objectVersionsRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
535
                    ifUnmodifiedSince:(NSDate *)sinceTimestamp {
536
    ASIPithosObjectRequest *request = [self objectVersionsRequestWithPithos:pithos containerName:containerName objectName:objectName];
537
    [request addRequestIfUnmodifiedSinceHeader:sinceTimestamp];
538
    return request;
539
}
540

    
541
- (NSArray *)versions {
542
    if (versions == nil)
543
        [self parseXMLData];
544
    return versions;
545
}
546

    
547
#pragma mark -
548
#pragma mark PUT, COPY, MOVE
549

    
550
// PUT storageURL/container/object (from ASIPithosObject with data)
551
+ (id)writeObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName object:(ASIPithosObject *)object {
552
    NSUInteger isPublic = ASIPithosObjectRequestPublicIgnore;
553
    if (object.publicURI) {
554
        isPublic = ASIPithosObjectRequestPublicTrue;
555
        if ([object.publicURI isEqualToString:@""])
556
            isPublic = ASIPithosObjectRequestPublicFalse;
557
    }
558
    return [self writeObjectDataRequestWithPithos:pithos containerName:containerName 
559
                                              objectName:object.name 
560
                                                    eTag:object.hash 
561
                                             contentType:object.contentType 
562
                                         contentEncoding:object.contentEncoding 
563
                                      contentDisposition:object.contentDisposition 
564
                                                manifest:object.manifest 
565
                                                 sharing:object.sharing 
566
                                                isPublic:isPublic
567
                                                metadata:object.metadata 
568
                                                    data:object.data];
569
}
570

    
571
// PUT storageURL/container/object (from ASIPithosObject with data) [If-Match]
572
+ (id)writeObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName object:(ASIPithosObject *)object 
573
                               ifMatch:(NSString *)matchETag {
574
    ASIPithosObjectRequest *request = [self writeObjectDataRequestWithPithos:pithos containerName:containerName object:object];
575
    [request addRequestIfMatchHeader:matchETag];
576
    return request;
577
}
578

    
579
// PUT storageURL/container/object (from ASIPithosObject with data) [If-None-Match]
580
+ (id)writeObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName object:(ASIPithosObject *)object 
581
                           ifNoneMatch:(NSString *)matchETag  {
582
    ASIPithosObjectRequest *request = [self writeObjectDataRequestWithPithos:pithos containerName:containerName object:object];
583
    [request addRequestIfNoneMatchHeader:matchETag];
584
    return request;
585
}
586

    
587
// PUT storageURL/container/object (from NSData)
588
+ (id)writeObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
589
                                  eTag:(NSString *)eTag 
590
                           contentType:(NSString *)contentType 
591
                       contentEncoding:(NSString *)contentEncoding 
592
                    contentDisposition:(NSString *)contentDisposition 
593
                              manifest:(NSString *)manifest 
594
                               sharing:(NSString *)sharing 
595
                              isPublic:(NSUInteger)isPublic 
596
                              metadata:(NSDictionary *)metadata 
597
                                  data:(NSData *)data {
598
	ASIPithosObjectRequest *request = [self storageRequestWithMethod:@"PUT" pithos:pithos containerName:containerName objectName:objectName];
599
    [request prepareObjectRequestWithETag:eTag 
600
                              contentType:contentType 
601
                          contentEncoding:contentEncoding 
602
                       contentDisposition:contentDisposition 
603
                                 manifest:manifest 
604
                                  sharing:sharing 
605
                                 isPublic:isPublic 
606
                                 metadata:metadata];
607
	[request appendPostData:data];
608
    request.requestMethod = @"PUT";
609
	return request;
610
}
611

    
612
// PUT storageURL/container/object (from NSData) [If-Match]
613
+ (id)writeObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
614
                                  eTag:(NSString *)eTag 
615
                           contentType:(NSString *)contentType 
616
                       contentEncoding:(NSString *)contentEncoding 
617
                    contentDisposition:(NSString *)contentDisposition 
618
                              manifest:(NSString *)manifest 
619
                               sharing:(NSString *)sharing 
620
                              isPublic:(NSUInteger)isPublic 
621
                              metadata:(NSDictionary *)metadata 
622
                                  data:(NSData *)data 
623
                               ifMatch:(NSString *)matchETag {
624
    ASIPithosObjectRequest *request = [self writeObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
625
                                                                               eTag:eTag 
626
                                                                        contentType:contentType 
627
                                                                    contentEncoding:contentEncoding 
628
                                                                 contentDisposition:contentDisposition 
629
                                                                           manifest:manifest 
630
                                                                            sharing:sharing 
631
                                                                           isPublic:isPublic 
632
                                                                           metadata:metadata 
633
                                                                               data:data];
634
    [request addRequestIfMatchHeader:matchETag];
635
    return request;                                                                          
636
}
637

    
638
// PUT storageURL/container/object (from NSData) [If-None-Match]
639
+ (id)writeObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
640
                                  eTag:(NSString *)eTag 
641
                           contentType:(NSString *)contentType 
642
                       contentEncoding:(NSString *)contentEncoding 
643
                    contentDisposition:(NSString *)contentDisposition 
644
                              manifest:(NSString *)manifest 
645
                               sharing:(NSString *)sharing 
646
                              isPublic:(NSUInteger)isPublic 
647
                              metadata:(NSDictionary *)metadata 
648
                                  data:(NSData *)data 
649
                           ifNoneMatch:(NSString *)matchETag {
650
    ASIPithosObjectRequest *request = [self writeObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
651
                                                                               eTag:eTag 
652
                                                                        contentType:contentType 
653
                                                                    contentEncoding:contentEncoding 
654
                                                                 contentDisposition:contentDisposition 
655
                                                                           manifest:manifest 
656
                                                                            sharing:sharing 
657
                                                                           isPublic:isPublic 
658
                                                                           metadata:metadata 
659
                                                                               data:data];
660
    [request addRequestIfNoneMatchHeader:matchETag];
661
    return request;                                                                          
662
}
663

    
664
// PUT storageURL/container/object (from file)
665
+ (id)writeObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
666
                                  eTag:(NSString *)eTag 
667
                           contentType:(NSString *)contentType 
668
                       contentEncoding:(NSString *)contentEncoding 
669
                    contentDisposition:(NSString *)contentDisposition 
670
                              manifest:(NSString *)manifest 
671
                               sharing:(NSString *)sharing 
672
                              isPublic:(NSUInteger)isPublic 
673
                              metadata:(NSDictionary *)metadata 
674
                                  file:(NSString *)filePath {
675
	ASIPithosObjectRequest *request = [self storageRequestWithMethod:@"PUT" pithos:pithos containerName:containerName objectName:objectName];
676
    [request prepareObjectRequestWithETag:eTag 
677
                              contentType:contentType 
678
                          contentEncoding:contentEncoding 
679
                       contentDisposition:contentDisposition 
680
                                 manifest:manifest 
681
                                  sharing:sharing 
682
                                 isPublic:isPublic 
683
                                 metadata:metadata];
684
	request.shouldStreamPostDataFromDisk = YES;
685
    request.postBodyFilePath = filePath;
686
    request.requestMethod = @"PUT";
687
	return request;    
688
}
689

    
690
// PUT storageURL/container/object (from file) [If-Match]
691
+ (id)writeObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
692
                                  eTag:(NSString *)eTag 
693
                           contentType:(NSString *)contentType 
694
                       contentEncoding:(NSString *)contentEncoding 
695
                    contentDisposition:(NSString *)contentDisposition 
696
                              manifest:(NSString *)manifest 
697
                               sharing:(NSString *)sharing 
698
                              isPublic:(NSUInteger)isPublic 
699
                              metadata:(NSDictionary *)metadata 
700
                                  file:(NSString *)filePath 
701
                               ifMatch:(NSString *)matchETag {
702
    ASIPithosObjectRequest *request = [self writeObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
703
                                                                               eTag:eTag 
704
                                                                        contentType:contentType 
705
                                                                    contentEncoding:contentEncoding 
706
                                                                 contentDisposition:contentDisposition 
707
                                                                           manifest:manifest 
708
                                                                            sharing:sharing 
709
                                                                           isPublic:isPublic 
710
                                                                           metadata:metadata 
711
                                                                               file:filePath];
712
    [request addRequestIfMatchHeader:matchETag];
713
    return request;                                                                          
714
}
715

    
716
// PUT storageURL/container/object (from file) [If-None-Match]
717
+ (id)writeObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
718
                                  eTag:(NSString *)eTag 
719
                           contentType:(NSString *)contentType 
720
                       contentEncoding:(NSString *)contentEncoding 
721
                    contentDisposition:(NSString *)contentDisposition 
722
                              manifest:(NSString *)manifest 
723
                               sharing:(NSString *)sharing 
724
                              isPublic:(NSUInteger)isPublic 
725
                              metadata:(NSDictionary *)metadata 
726
                                  file:(NSString *)filePath 
727
                           ifNoneMatch:(NSString *)matchETag {
728
    ASIPithosObjectRequest *request = [self writeObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
729
                                                                               eTag:eTag 
730
                                                                        contentType:contentType 
731
                                                                    contentEncoding:contentEncoding 
732
                                                                 contentDisposition:contentDisposition 
733
                                                                           manifest:manifest 
734
                                                                            sharing:sharing 
735
                                                                           isPublic:isPublic 
736
                                                                           metadata:metadata 
737
                                                                               file:filePath];
738
    [request addRequestIfNoneMatchHeader:matchETag];
739
    return request;                                                                          
740
}
741

    
742
// PUT storageURL/container/object (from hashes)
743
+ (id)writeObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
744
                           contentType:(NSString *)contentType 
745
                       contentEncoding:(NSString *)contentEncoding 
746
                    contentDisposition:(NSString *)contentDisposition 
747
                              manifest:(NSString *)manifest 
748
                               sharing:(NSString *)sharing 
749
                              isPublic:(NSUInteger)isPublic 
750
                              metadata:(NSDictionary *)metadata 
751
                             blockSize:(NSUInteger)blockSize 
752
                             blockHash:(NSString *)blockHash 
753
                                hashes:(NSArray *)hashes 
754
                                 bytes:(NSUInteger)bytes {
755
	ASIPithosObjectRequest *request = [self storageRequestWithMethod:@"PUT" pithos:pithos containerName:containerName objectName:objectName queryString:@"?format=xml&hashmap="];
756
    [request prepareObjectRequestWithETag:nil 
757
                              contentType:contentType 
758
                          contentEncoding:contentEncoding 
759
                       contentDisposition:contentDisposition 
760
                                 manifest:manifest 
761
                                  sharing:sharing 
762
                                 isPublic:isPublic 
763
                                 metadata:metadata];
764
    NSString *dataString = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?><object name=\"%@\" bytes=\"%lu\" block_size=\"%lu\" block_hash=\"%@\">", 
765
                            [(NSString *)CFXMLCreateStringByEscapingEntities(NULL, (CFStringRef)objectName , NULL) autorelease], 
766
                            bytes, blockSize, blockHash];
767
    for (NSString *hash in hashes) {
768
        dataString = [dataString stringByAppendingFormat:@"<hash>%@</hash>", hash];
769
    }
770
    dataString = [dataString stringByAppendingString:@"</object>"];
771
	[request appendPostData:[dataString dataUsingEncoding:NSUTF8StringEncoding]];
772
    request.requestMethod = @"PUT";
773
    request.objectRequestType = ASIPithosObjectRequestHashmapWrite;
774
	return request;
775
}
776

    
777
// PUT storageURL/container/object (from hashes) [If-Match]
778
+ (id)writeObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
779
                           contentType:(NSString *)contentType 
780
                       contentEncoding:(NSString *)contentEncoding 
781
                    contentDisposition:(NSString *)contentDisposition 
782
                              manifest:(NSString *)manifest 
783
                               sharing:(NSString *)sharing 
784
                              isPublic:(NSUInteger)isPublic 
785
                              metadata:(NSDictionary *)metadata 
786
                             blockSize:(NSUInteger)blockSize 
787
                             blockHash:(NSString *)blockHash 
788
                                hashes:(NSArray *)hashes 
789
                                 bytes:(NSUInteger)bytes 
790
                               ifMatch:(NSString *)matchETag {
791
    ASIPithosObjectRequest *request = [self writeObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
792
                                                                        contentType:contentType 
793
                                                                    contentEncoding:contentEncoding 
794
                                                                 contentDisposition:contentDisposition 
795
                                                                           manifest:manifest 
796
                                                                            sharing:sharing 
797
                                                                           isPublic:isPublic 
798
                                                                           metadata:metadata 
799
                                                                          blockSize:blockSize 
800
                                                                          blockHash:blockHash 
801
                                                                             hashes:hashes 
802
                                                                              bytes:bytes];
803
    [request addRequestIfMatchHeader:matchETag];
804
    return request;                                                                          
805
}
806

    
807
// PUT storageURL/container/object (from hashes) [If-None-Match]
808
+ (id)writeObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
809
                           contentType:(NSString *)contentType 
810
                       contentEncoding:(NSString *)contentEncoding 
811
                    contentDisposition:(NSString *)contentDisposition 
812
                              manifest:(NSString *)manifest 
813
                               sharing:(NSString *)sharing 
814
                              isPublic:(NSUInteger)isPublic 
815
                              metadata:(NSDictionary *)metadata 
816
                             blockSize:(NSUInteger)blockSize 
817
                             blockHash:(NSString *)blockHash 
818
                                hashes:(NSArray *)hashes 
819
                                 bytes:(NSUInteger)bytes 
820
                           ifNoneMatch:(NSString *)matchETag {
821
    ASIPithosObjectRequest *request = [self writeObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
822
                                                                        contentType:contentType 
823
                                                                    contentEncoding:contentEncoding 
824
                                                                 contentDisposition:contentDisposition 
825
                                                                           manifest:manifest 
826
                                                                            sharing:sharing 
827
                                                                           isPublic:isPublic 
828
                                                                           metadata:metadata 
829
                                                                          blockSize:blockSize 
830
                                                                          blockHash:blockHash 
831
                                                                             hashes:hashes 
832
                                                                              bytes:bytes];
833
    [request addRequestIfNoneMatchHeader:matchETag];
834
    return request;                                                                          
835
}
836

    
837
// PUT storageURL/container/object (copy from source)
838
+ (id)copyObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
839
                          contentType:(NSString *)contentType 
840
                      contentEncoding:(NSString *)contentEncoding 
841
                   contentDisposition:(NSString *)contentDisposition 
842
                             manifest:(NSString *)manifest 
843
                              sharing:(NSString *)sharing 
844
                             isPublic:(NSUInteger)isPublic 
845
                             metadata:(NSDictionary *)metadata 
846
                  sourceContainerName:(NSString *)sourceContainerName 
847
                     sourceObjectName:(NSString *)sourceObjectName
848
                        sourceAccount:(NSString *)sourceAccount
849
                        sourceVersion:(NSString *)sourceVersion {
850
	ASIPithosObjectRequest *request = [self storageRequestWithMethod:@"PUT" pithos:pithos containerName:containerName objectName:objectName];
851
    [request prepareObjectRequestWithETag:nil 
852
                              contentType:contentType 
853
                          contentEncoding:contentEncoding 
854
                       contentDisposition:contentDisposition 
855
                                 manifest:manifest 
856
                                  sharing:sharing 
857
                                 isPublic:isPublic 
858
                                 metadata:metadata];
859
    [request addRequestHeader:@"Content-Length" value:@"0"];
860
    [request addRequestHeader:@"X-Copy-From" 
861
                        value:[self encodeToPercentEscape:[NSString stringWithFormat:@"/%@/%@", sourceContainerName, sourceObjectName]]];
862
    if (sourceAccount)
863
        [request addRequestHeader:@"X-Source-Account" 
864
                            value:[self encodeToPercentEscape:sourceAccount]];
865
    if (sourceVersion)
866
        [request addRequestHeader:@"X-Source-Version" value:sourceVersion];
867
    return request;
868
}
869

    
870
// PUT storageURL/container/object (copy from source) [If-Match]
871
+ (id)copyObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
872
                          contentType:(NSString *)contentType 
873
                      contentEncoding:(NSString *)contentEncoding 
874
                   contentDisposition:(NSString *)contentDisposition 
875
                             manifest:(NSString *)manifest 
876
                              sharing:(NSString *)sharing 
877
                             isPublic:(NSUInteger)isPublic 
878
                             metadata:(NSDictionary *)metadata 
879
                  sourceContainerName:(NSString *)sourceContainerName 
880
                     sourceObjectName:(NSString *)sourceObjectName
881
                        sourceAccount:(NSString *)sourceAccount
882
                        sourceVersion:(NSString *)sourceVersion 
883
                              ifMatch:(NSString *)matchETag {
884
    ASIPithosObjectRequest *request = [self copyObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
885
                                                                       contentType:contentType 
886
                                                                   contentEncoding:contentEncoding 
887
                                                                contentDisposition:contentDisposition 
888
                                                                          manifest:manifest 
889
                                                                           sharing:sharing 
890
                                                                          isPublic:isPublic 
891
                                                                          metadata:metadata 
892
                                                               sourceContainerName:sourceContainerName 
893
                                                                  sourceObjectName:sourceObjectName 
894
                                                                     sourceAccount:sourceAccount
895
                                                                     sourceVersion:sourceVersion];
896
    [request addRequestIfMatchHeader:matchETag];
897
    return request;                                                                          
898
}
899

    
900
// PUT storageURL/container/object (copy from source) [If-None-Match]
901
+ (id)copyObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
902
                          contentType:(NSString *)contentType 
903
                      contentEncoding:(NSString *)contentEncoding 
904
                   contentDisposition:(NSString *)contentDisposition 
905
                             manifest:(NSString *)manifest 
906
                              sharing:(NSString *)sharing 
907
                             isPublic:(NSUInteger)isPublic 
908
                             metadata:(NSDictionary *)metadata 
909
                  sourceContainerName:(NSString *)sourceContainerName 
910
                     sourceObjectName:(NSString *)sourceObjectName
911
                        sourceAccount:(NSString *)sourceAccount
912
                        sourceVersion:(NSString *)sourceVersion 
913
                          ifNoneMatch:(NSString *)matchETag {
914
    ASIPithosObjectRequest *request = [self copyObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
915
                                                                       contentType:contentType 
916
                                                                   contentEncoding:contentEncoding 
917
                                                                contentDisposition:contentDisposition 
918
                                                                          manifest:manifest 
919
                                                                           sharing:sharing 
920
                                                                          isPublic:isPublic 
921
                                                                          metadata:metadata 
922
                                                               sourceContainerName:sourceContainerName 
923
                                                                  sourceObjectName:sourceObjectName 
924
                                                                     sourceAccount:sourceAccount
925
                                                                     sourceVersion:sourceVersion];
926
    [request addRequestIfNoneMatchHeader:matchETag];
927
    return request;                                                                          
928
}
929

    
930
// COPY storageURL/container/object (copy to destination)
931
+ (id)copyObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
932
                          contentType:(NSString *)contentType 
933
                      contentEncoding:(NSString *)contentEncoding 
934
                   contentDisposition:(NSString *)contentDisposition 
935
                             manifest:(NSString *)manifest 
936
                              sharing:(NSString *)sharing 
937
                             isPublic:(NSUInteger)isPublic 
938
                             metadata:(NSDictionary *)metadata 
939
             destinationContainerName:(NSString *)destinationContainerName 
940
                destinationObjectName:(NSString *)destinationObjectName
941
                   destinationAccount:(NSString *)destinationAccount
942
                        sourceVersion:(NSString *)sourceVersion {
943
    NSString *queryString = nil;
944
    if (!contentType)
945
        queryString = @"?ignore_content_type=";
946
	ASIPithosObjectRequest *request = [self storageRequestWithMethod:@"COPY" pithos:pithos containerName:containerName objectName:objectName queryString:queryString];
947
    [request prepareObjectRequestWithETag:nil 
948
                              contentType:contentType 
949
                          contentEncoding:contentEncoding 
950
                       contentDisposition:contentDisposition 
951
                                 manifest:manifest 
952
                                  sharing:sharing 
953
                                 isPublic:isPublic 
954
                                 metadata:metadata];
955
    [request addRequestHeader:@"Destination" 
956
                        value:[self encodeToPercentEscape:[NSString stringWithFormat:@"/%@/%@", destinationContainerName, destinationObjectName]]];
957
    if (destinationAccount)
958
        [request addRequestHeader:@"Destination-Account" 
959
                            value:[self encodeToPercentEscape:destinationAccount]];
960
    if (sourceVersion)
961
        [request addRequestHeader:@"X-Source-Version" value:sourceVersion];
962
    return request;
963
}
964

    
965
// COPY storageURL/container/object (copy to destination) [If-Match]
966
+ (id)copyObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
967
                          contentType:(NSString *)contentType 
968
                      contentEncoding:(NSString *)contentEncoding 
969
                   contentDisposition:(NSString *)contentDisposition 
970
                             manifest:(NSString *)manifest 
971
                              sharing:(NSString *)sharing 
972
                             isPublic:(NSUInteger)isPublic 
973
                             metadata:(NSDictionary *)metadata 
974
             destinationContainerName:(NSString *)destinationContainerName 
975
                destinationObjectName:(NSString *)destinationObjectName
976
                   destinationAccount:(NSString *)destinationAccount
977
                        sourceVersion:(NSString *)sourceVersion 
978
                              ifMatch:(NSString *)matchETag {
979
    ASIPithosObjectRequest *request = [self copyObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
980
                                                                       contentType:contentType 
981
                                                                   contentEncoding:contentEncoding 
982
                                                                contentDisposition:contentDisposition 
983
                                                                          manifest:manifest 
984
                                                                           sharing:sharing 
985
                                                                          isPublic:isPublic 
986
                                                                          metadata:metadata 
987
                                                          destinationContainerName:destinationContainerName 
988
                                                             destinationObjectName:destinationObjectName 
989
                                                                destinationAccount:destinationAccount
990
                                                                     sourceVersion:sourceVersion];
991
    [request addRequestIfMatchHeader:matchETag];
992
    return request;                                                                          
993
}
994

    
995
// COPY storageURL/container/object (copy to destination) [If-None-Match]
996
+ (id)copyObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
997
                          contentType:(NSString *)contentType 
998
                      contentEncoding:(NSString *)contentEncoding 
999
                   contentDisposition:(NSString *)contentDisposition 
1000
                             manifest:(NSString *)manifest 
1001
                              sharing:(NSString *)sharing 
1002
                             isPublic:(NSUInteger)isPublic 
1003
                             metadata:(NSDictionary *)metadata 
1004
             destinationContainerName:(NSString *)destinationContainerName 
1005
                destinationObjectName:(NSString *)destinationObjectName
1006
                   destinationAccount:(NSString *)destinationAccount
1007
                        sourceVersion:(NSString *)sourceVersion 
1008
                          ifNoneMatch:(NSString *)matchETag {
1009
    ASIPithosObjectRequest *request = [self copyObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
1010
                                                                       contentType:contentType 
1011
                                                                   contentEncoding:contentEncoding 
1012
                                                                contentDisposition:contentDisposition 
1013
                                                                          manifest:manifest 
1014
                                                                           sharing:sharing 
1015
                                                                          isPublic:isPublic 
1016
                                                                          metadata:metadata 
1017
                                                          destinationContainerName:destinationContainerName 
1018
                                                             destinationObjectName:destinationObjectName 
1019
                                                                destinationAccount:destinationAccount
1020
                                                                     sourceVersion:sourceVersion];
1021
    [request addRequestIfNoneMatchHeader:matchETag];
1022
    return request;                                                                          
1023
}
1024

    
1025
// PUT storageURL/container/object (move from source)
1026
+ (id)moveObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1027
                          contentType:(NSString *)contentType 
1028
                      contentEncoding:(NSString *)contentEncoding 
1029
                   contentDisposition:(NSString *)contentDisposition 
1030
                             manifest:(NSString *)manifest 
1031
                              sharing:(NSString *)sharing 
1032
                             isPublic:(NSUInteger)isPublic 
1033
                             metadata:(NSDictionary *)metadata 
1034
                  sourceContainerName:(NSString *)sourceContainerName 
1035
                     sourceObjectName:(NSString *)sourceObjectName 
1036
                        sourceAccount:(NSString *)sourceAccount { 
1037
	ASIPithosObjectRequest *request = [self storageRequestWithMethod:@"PUT" pithos:pithos containerName:containerName objectName:objectName];
1038
    [request prepareObjectRequestWithETag:nil 
1039
                              contentType:contentType 
1040
                          contentEncoding:contentEncoding 
1041
                       contentDisposition:contentDisposition 
1042
                                 manifest:manifest 
1043
                                  sharing:sharing 
1044
                                 isPublic:isPublic 
1045
                                 metadata:metadata];
1046
    [request addRequestHeader:@"Content-Length" value:@"0"];
1047
    [request addRequestHeader:@"X-Move-From" 
1048
                        value:[self encodeToPercentEscape:[NSString stringWithFormat:@"/%@/%@", sourceContainerName, sourceObjectName]]];
1049
    if (sourceAccount)
1050
        [request addRequestHeader:@"X-Source-Account" 
1051
                            value:[self encodeToPercentEscape:sourceAccount]];
1052
    return request;
1053
}
1054

    
1055
// PUT storageURL/container/object (move from source) [If-Match]
1056
+ (id)moveObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1057
                          contentType:(NSString *)contentType 
1058
                      contentEncoding:(NSString *)contentEncoding 
1059
                   contentDisposition:(NSString *)contentDisposition 
1060
                             manifest:(NSString *)manifest 
1061
                              sharing:(NSString *)sharing 
1062
                             isPublic:(NSUInteger)isPublic 
1063
                             metadata:(NSDictionary *)metadata 
1064
                  sourceContainerName:(NSString *)sourceContainerName 
1065
                     sourceObjectName:(NSString *)sourceObjectName
1066
                        sourceAccount:(NSString *)sourceAccount
1067
                              ifMatch:(NSString *)matchETag {
1068
    ASIPithosObjectRequest *request = [self moveObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
1069
                                                                       contentType:contentType 
1070
                                                                   contentEncoding:contentEncoding 
1071
                                                                contentDisposition:contentDisposition 
1072
                                                                          manifest:manifest 
1073
                                                                           sharing:sharing 
1074
                                                                          isPublic:isPublic 
1075
                                                                          metadata:metadata 
1076
                                                               sourceContainerName:sourceContainerName 
1077
                                                                  sourceObjectName:sourceObjectName 
1078
                                                                     sourceAccount:sourceAccount];
1079
    [request addRequestIfMatchHeader:matchETag];
1080
    return request;                                               
1081
}
1082

    
1083
// PUT storageURL/container/object (move from source) [If-None-Match]
1084
+ (id)moveObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1085
                          contentType:(NSString *)contentType 
1086
                      contentEncoding:(NSString *)contentEncoding 
1087
                   contentDisposition:(NSString *)contentDisposition 
1088
                             manifest:(NSString *)manifest 
1089
                              sharing:(NSString *)sharing 
1090
                             isPublic:(NSUInteger)isPublic 
1091
                             metadata:(NSDictionary *)metadata 
1092
                  sourceContainerName:(NSString *)sourceContainerName 
1093
                     sourceObjectName:(NSString *)sourceObjectName
1094
                        sourceAccount:(NSString *)sourceAccount
1095
                          ifNoneMatch:(NSString *)matchETag {
1096
    ASIPithosObjectRequest *request = [self moveObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
1097
                                                                       contentType:contentType 
1098
                                                                   contentEncoding:contentEncoding 
1099
                                                                contentDisposition:contentDisposition 
1100
                                                                          manifest:manifest 
1101
                                                                           sharing:sharing 
1102
                                                                          isPublic:isPublic 
1103
                                                                          metadata:metadata 
1104
                                                               sourceContainerName:sourceContainerName 
1105
                                                                  sourceObjectName:sourceObjectName 
1106
                                                                     sourceAccount:sourceAccount];
1107
    [request addRequestIfNoneMatchHeader:matchETag];
1108
    return request;                                               
1109
}
1110

    
1111
// MOVE storageURL/container/object (move to destination)
1112
+ (id)moveObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1113
                          contentType:(NSString *)contentType 
1114
                      contentEncoding:(NSString *)contentEncoding 
1115
                   contentDisposition:(NSString *)contentDisposition 
1116
                             manifest:(NSString *)manifest 
1117
                              sharing:(NSString *)sharing 
1118
                             isPublic:(NSUInteger)isPublic 
1119
                             metadata:(NSDictionary *)metadata 
1120
             destinationContainerName:(NSString *)destinationContainerName 
1121
                destinationObjectName:(NSString *)destinationObjectName 
1122
                   destinationAccount:(NSString *)destinationAccount {
1123
    NSString *queryString = nil;
1124
    if (!contentType)
1125
        queryString = @"?ignore_content_type=";
1126
	ASIPithosObjectRequest *request = [self storageRequestWithMethod:@"MOVE" pithos:pithos containerName:containerName objectName:objectName queryString:queryString];
1127
    [request prepareObjectRequestWithETag:nil 
1128
                              contentType:contentType 
1129
                          contentEncoding:contentEncoding 
1130
                       contentDisposition:contentDisposition 
1131
                                 manifest:manifest 
1132
                                  sharing:sharing 
1133
                                 isPublic:isPublic 
1134
                                 metadata:metadata];
1135
    [request addRequestHeader:@"Destination" 
1136
                        value:[self encodeToPercentEscape:[NSString stringWithFormat:@"/%@/%@", destinationContainerName, destinationObjectName]]];
1137
    if (destinationAccount)
1138
        [request addRequestHeader:@"Destination-Account" 
1139
                            value:[self encodeToPercentEscape:destinationAccount]];
1140
    return request;
1141
}
1142

    
1143
// MOVE storageURL/container/object (move to destination) [If-Match]
1144
+ (id)moveObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1145
                          contentType:(NSString *)contentType 
1146
                      contentEncoding:(NSString *)contentEncoding 
1147
                   contentDisposition:(NSString *)contentDisposition 
1148
                             manifest:(NSString *)manifest 
1149
                              sharing:(NSString *)sharing 
1150
                             isPublic:(NSUInteger)isPublic 
1151
                             metadata:(NSDictionary *)metadata 
1152
             destinationContainerName:(NSString *)destinationContainerName 
1153
                destinationObjectName:(NSString *)destinationObjectName
1154
                   destinationAccount:(NSString *)destinationAccount
1155
                              ifMatch:(NSString *)matchETag {
1156
    ASIPithosObjectRequest *request = [self moveObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
1157
                                                                       contentType:contentType 
1158
                                                                   contentEncoding:contentEncoding 
1159
                                                                contentDisposition:contentDisposition 
1160
                                                                          manifest:manifest 
1161
                                                                           sharing:sharing 
1162
                                                                          isPublic:isPublic 
1163
                                                                          metadata:metadata 
1164
                                                          destinationContainerName:destinationContainerName 
1165
                                                             destinationObjectName:destinationObjectName 
1166
                                                                destinationAccount:destinationAccount];
1167
    [request addRequestIfMatchHeader:matchETag];
1168
    return request;                                                                          
1169
}
1170

    
1171
// MOVE storageURL/container/object (move to destination) [If-None-Match]
1172
+ (id)moveObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1173
                          contentType:(NSString *)contentType 
1174
                      contentEncoding:(NSString *)contentEncoding 
1175
                   contentDisposition:(NSString *)contentDisposition 
1176
                             manifest:(NSString *)manifest 
1177
                              sharing:(NSString *)sharing 
1178
                             isPublic:(NSUInteger)isPublic 
1179
                             metadata:(NSDictionary *)metadata 
1180
             destinationContainerName:(NSString *)destinationContainerName 
1181
                destinationObjectName:(NSString *)destinationObjectName
1182
                   destinationAccount:(NSString *)destinationAccount
1183
                          ifNoneMatch:(NSString *)matchETag {
1184
    ASIPithosObjectRequest *request = [self moveObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
1185
                                                                       contentType:contentType 
1186
                                                                   contentEncoding:contentEncoding 
1187
                                                                contentDisposition:contentDisposition 
1188
                                                                          manifest:manifest 
1189
                                                                           sharing:sharing 
1190
                                                                          isPublic:isPublic 
1191
                                                                          metadata:metadata 
1192
                                                          destinationContainerName:destinationContainerName 
1193
                                                             destinationObjectName:destinationObjectName 
1194
                                                                destinationAccount:destinationAccount];
1195
    [request addRequestIfNoneMatchHeader:matchETag];
1196
    return request;                                                                          
1197
}
1198

    
1199
#pragma mark -
1200
#pragma mark POST
1201

    
1202
// POST storageURL/container/object?[update=] (update metadata)
1203
+ (id)updateObjectMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1204
                                     update:(BOOL)update {
1205
    NSString *queryString = nil;
1206
    if (update)
1207
        queryString = @"?update=";
1208
	return [self storageRequestWithMethod:@"POST" pithos:pithos containerName:containerName objectName:objectName queryString:queryString];
1209
}
1210

    
1211
// POST storageURL/container/object?[update=] (update metadata) [If-Match]
1212
+ (id)updateObjectMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1213
                                     update:(BOOL)update 
1214
                                    ifMatch:(NSString *)matchETag {
1215
    ASIPithosObjectRequest *request = [self updateObjectMetadataRequestWithPithos:pithos containerName:containerName objectName:objectName update:update];
1216
    [request addRequestIfMatchHeader:matchETag];
1217
    return request;                                                                          
1218
}
1219

    
1220
// POST storageURL/container/object?[update=] (update metadata) [If-None-Match]
1221
+ (id)updateObjectMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1222
                                     update:(BOOL)update 
1223
                                ifNoneMatch:(NSString *)matchETag {
1224
    ASIPithosObjectRequest *request = [self updateObjectMetadataRequestWithPithos:pithos containerName:containerName objectName:objectName update:update];
1225
    [request addRequestIfNoneMatchHeader:matchETag];
1226
    return request;                                                                          
1227
}
1228

    
1229
// POST storageURL/container/object?[update=] (update metadata)
1230
+ (id)updateObjectMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1231
                            contentEncoding:(NSString *)contentEncoding 
1232
                         contentDisposition:(NSString *)contentDisposition 
1233
                                   manifest:(NSString *)manifest 
1234
                                    sharing:(NSString *)sharing 
1235
                                   isPublic:(NSUInteger)isPublic 
1236
                                   metadata:(NSDictionary *)metadata 
1237
                                     update:(BOOL)update {
1238
    NSString *queryString = nil;
1239
    if (update)
1240
        queryString = @"?update=";
1241
	ASIPithosObjectRequest *request = [self storageRequestWithMethod:@"POST" pithos:pithos containerName:containerName objectName:objectName queryString:queryString];
1242
    [request prepareObjectRequestWithETag:nil 
1243
                              contentType:nil 
1244
                          contentEncoding:contentEncoding 
1245
                       contentDisposition:contentDisposition 
1246
                                 manifest:manifest 
1247
                                  sharing:sharing 
1248
                                 isPublic:isPublic 
1249
                                 metadata:metadata];
1250
    return request;
1251
}
1252

    
1253
// POST storageURL/container/object?[update=] (update metadata) [If-Match]
1254
+ (id)updateObjectMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1255
                            contentEncoding:(NSString *)contentEncoding 
1256
                         contentDisposition:(NSString *)contentDisposition 
1257
                                   manifest:(NSString *)manifest 
1258
                                    sharing:(NSString *)sharing 
1259
                                   isPublic:(NSUInteger)isPublic 
1260
                                   metadata:(NSDictionary *)metadata 
1261
                                     update:(BOOL)update 
1262
                                    ifMatch:(NSString *)matchETag {
1263
    ASIPithosObjectRequest *request = [self updateObjectMetadataRequestWithPithos:pithos containerName:containerName objectName:objectName 
1264
                                                                         contentEncoding:contentEncoding 
1265
                                                                      contentDisposition:contentDisposition 
1266
                                                                                manifest:manifest 
1267
                                                                                 sharing:sharing 
1268
                                                                                isPublic:isPublic 
1269
                                                                                metadata:metadata 
1270
                                                                                  update:update];
1271
    [request addRequestIfMatchHeader:matchETag];
1272
    return request;                                                                          
1273
}
1274

    
1275
// POST storageURL/container/object?[update=] (update metadata) [If-None-Match]
1276
+ (id)updateObjectMetadataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1277
                            contentEncoding:(NSString *)contentEncoding 
1278
                         contentDisposition:(NSString *)contentDisposition 
1279
                                   manifest:(NSString *)manifest 
1280
                                    sharing:(NSString *)sharing 
1281
                                   isPublic:(NSUInteger)isPublic 
1282
                                   metadata:(NSDictionary *)metadata 
1283
                                     update:(BOOL)update 
1284
                                ifNoneMatch:(NSString *)matchETag {
1285
    ASIPithosObjectRequest *request = [self updateObjectMetadataRequestWithPithos:pithos containerName:containerName objectName:objectName 
1286
                                                                         contentEncoding:contentEncoding 
1287
                                                                      contentDisposition:contentDisposition 
1288
                                                                                manifest:manifest 
1289
                                                                                 sharing:sharing 
1290
                                                                                isPublic:isPublic 
1291
                                                                                metadata:metadata 
1292
                                                                                  update:update];
1293
    [request addRequestIfNoneMatchHeader:matchETag];
1294
    return request;                                                                          
1295
}
1296

    
1297
// POST storageURL/container/object?[update=] (update data from ASIPithosObject with data)
1298
+ (id)updateObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName object:(ASIPithosObject *)object 
1299
                                 update:(BOOL)update 
1300
                           contentRange:(NSString *)contentRange {
1301
    NSUInteger isPublic = ASIPithosObjectRequestPublicIgnore;
1302
    if (object.publicURI) {
1303
        isPublic = ASIPithosObjectRequestPublicTrue;
1304
        if ([object.publicURI isEqualToString:@""])
1305
            isPublic = ASIPithosObjectRequestPublicFalse;
1306
    }
1307
    return [self updateObjectDataRequestWithPithos:pithos containerName:containerName objectName:object.name 
1308
                                          contentEncoding:object.contentEncoding 
1309
                                       contentDisposition:object.contentDisposition 
1310
                                                 manifest:object.manifest 
1311
                                                  sharing:object.sharing 
1312
                                                 isPublic:isPublic
1313
                                                 metadata:object.metadata 
1314
                                                   update:update 
1315
                                             contentRange:contentRange 
1316
                                                    bytes:[NSNumber numberWithUnsignedLong:object.bytes]
1317
                                                    data:object.data];
1318
}
1319

    
1320
// POST storageURL/container/object?[update=] (update data from ASIPithosObject with data) [If-Match]
1321
+ (id)updateObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName object:(ASIPithosObject *)object 
1322
                                 update:(BOOL)update 
1323
                           contentRange:(NSString *)contentRange 
1324
                                ifMatch:(NSString *)matchETag {
1325
    ASIPithosObjectRequest *request = [self updateObjectDataRequestWithPithos:pithos containerName:containerName object:object 
1326
                                                                              update:update 
1327
                                                                        contentRange:contentRange];
1328
    [request addRequestIfMatchHeader:matchETag];
1329
    return request;                                                                          
1330
}
1331

    
1332
// POST storageURL/container/object?[update=] (update data from ASIPithosObject with data) [If-None-Match]
1333
+ (id)updateObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName object:(ASIPithosObject *)object 
1334
                                 update:(BOOL)update 
1335
                           contentRange:(NSString *)contentRange 
1336
                            ifNoneMatch:(NSString *)matchETag {
1337
    ASIPithosObjectRequest *request = [self updateObjectDataRequestWithPithos:pithos containerName:containerName object:object 
1338
                                                                              update:update 
1339
                                                                        contentRange:contentRange];
1340
    [request addRequestIfNoneMatchHeader:matchETag];
1341
    return request;                                                                          
1342
}
1343

    
1344
// POST storageURL/container/object?[update=] (update data from NSData)
1345
+ (id)updateObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1346
                        contentEncoding:(NSString *)contentEncoding 
1347
                     contentDisposition:(NSString *)contentDisposition 
1348
                               manifest:(NSString *)manifest 
1349
                                sharing:(NSString *)sharing 
1350
                               isPublic:(NSUInteger)isPublic 
1351
                               metadata:(NSDictionary *)metadata 
1352
                                 update:(BOOL)update 
1353
                           contentRange:(NSString *)contentRange 
1354
                                  bytes:(NSNumber *)bytes 
1355
                                   data:(NSData *)data {
1356
    NSString *queryString = nil;
1357
    if (update)
1358
        queryString = @"?update=";
1359
	ASIPithosObjectRequest *request = [self storageRequestWithMethod:@"POST" pithos:pithos containerName:containerName objectName:objectName queryString:queryString];
1360
    [request prepareObjectRequestWithETag:nil
1361
                              contentType:@"application/octet-stream"
1362
                          contentEncoding:contentEncoding 
1363
                       contentDisposition:contentDisposition 
1364
                                 manifest:manifest 
1365
                                  sharing:sharing 
1366
                                 isPublic:isPublic 
1367
                                 metadata:metadata];
1368
    if (contentRange)
1369
        [request addRequestHeader:@"Content-Range" value:contentRange];
1370
    if (bytes)
1371
        [request addRequestHeader:@"X-Object-Bytes" value:[NSString stringWithFormat:@"%lu", [bytes unsignedLongValue]]];
1372
	[request appendPostData:data];
1373
	return request;
1374
}
1375

    
1376
// POST storageURL/container/object?[update=] (update data from NSData) [If-Match]
1377
+ (id)updateObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1378
                        contentEncoding:(NSString *)contentEncoding 
1379
                     contentDisposition:(NSString *)contentDisposition 
1380
                               manifest:(NSString *)manifest 
1381
                                sharing:(NSString *)sharing 
1382
                               isPublic:(NSUInteger)isPublic 
1383
                               metadata:(NSDictionary *)metadata 
1384
                                 update:(BOOL)update 
1385
                           contentRange:(NSString *)contentRange 
1386
                                  bytes:(NSNumber *)bytes 
1387
                                   data:(NSData *)data 
1388
                                ifMatch:(NSString *)matchETag {
1389
    ASIPithosObjectRequest *request = [self updateObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
1390
                                                                     contentEncoding:contentEncoding 
1391
                                                                  contentDisposition:contentDisposition 
1392
                                                                            manifest:manifest 
1393
                                                                             sharing:sharing 
1394
                                                                            isPublic:isPublic 
1395
                                                                            metadata:metadata 
1396
                                                                              update:update 
1397
                                                                        contentRange:contentRange 
1398
                                                                               bytes:bytes 
1399
                                                                                data:data];
1400
    [request addRequestIfMatchHeader:matchETag];
1401
    return request;                                                                          
1402
}
1403

    
1404
// POST storageURL/container/object?[update=] (update data from NSData) [If-None-Match]
1405
+ (id)updateObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1406
                        contentEncoding:(NSString *)contentEncoding 
1407
                     contentDisposition:(NSString *)contentDisposition 
1408
                               manifest:(NSString *)manifest 
1409
                                sharing:(NSString *)sharing 
1410
                               isPublic:(NSUInteger)isPublic 
1411
                               metadata:(NSDictionary *)metadata 
1412
                                 update:(BOOL)update 
1413
                           contentRange:(NSString *)contentRange 
1414
                                  bytes:(NSNumber *)bytes 
1415
                                   data:(NSData *)data 
1416
                            ifNoneMatch:(NSString *)matchETag {
1417
    ASIPithosObjectRequest *request = [self updateObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
1418
                                                                     contentEncoding:contentEncoding 
1419
                                                                  contentDisposition:contentDisposition 
1420
                                                                            manifest:manifest 
1421
                                                                             sharing:sharing 
1422
                                                                            isPublic:isPublic 
1423
                                                                            metadata:metadata 
1424
                                                                              update:update 
1425
                                                                        contentRange:contentRange 
1426
                                                                               bytes:bytes 
1427
                                                                                data:data];
1428
    [request addRequestIfNoneMatchHeader:matchETag];
1429
    return request;                                                                          
1430
}
1431

    
1432
// POST storageURL/container/object?[update=] (update data from file)
1433
+ (id)updateObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1434
                        contentEncoding:(NSString *)contentEncoding 
1435
                     contentDisposition:(NSString *)contentDisposition 
1436
                               manifest:(NSString *)manifest 
1437
                                sharing:(NSString *)sharing 
1438
                               isPublic:(NSUInteger)isPublic 
1439
                               metadata:(NSDictionary *)metadata 
1440
                                 update:(BOOL)update 
1441
                           contentRange:(NSString *)contentRange 
1442
                                  bytes:(NSNumber *)bytes 
1443
                                   file:(NSString *)filePath {
1444
    NSString *queryString = nil;
1445
    if (update)
1446
        queryString = @"?update=";
1447
	ASIPithosObjectRequest *request = [self storageRequestWithMethod:@"POST" pithos:pithos containerName:containerName objectName:objectName queryString:queryString];
1448
    [request prepareObjectRequestWithETag:nil
1449
                              contentType:@"application/octet-stream"
1450
                          contentEncoding:contentEncoding 
1451
                       contentDisposition:contentDisposition 
1452
                                 manifest:manifest 
1453
                                  sharing:sharing 
1454
                                 isPublic:isPublic 
1455
                                 metadata:metadata];
1456
    if (contentRange)
1457
        [request addRequestHeader:@"Content-Range" value:contentRange];
1458
    if (bytes)
1459
        [request addRequestHeader:@"X-Object-Bytes" value:[NSString stringWithFormat:@"%lu", [bytes unsignedLongValue]]];
1460
	request.shouldStreamPostDataFromDisk = YES;
1461
    request.postBodyFilePath = filePath;
1462
	return request;
1463
}
1464

    
1465
// POST storageURL/container/object?[update=] (update data from file) [If-Match]
1466
+ (id)updateObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1467
                        contentEncoding:(NSString *)contentEncoding 
1468
                     contentDisposition:(NSString *)contentDisposition 
1469
                               manifest:(NSString *)manifest 
1470
                                sharing:(NSString *)sharing 
1471
                               isPublic:(NSUInteger)isPublic 
1472
                               metadata:(NSDictionary *)metadata 
1473
                                 update:(BOOL)update 
1474
                           contentRange:(NSString *)contentRange 
1475
                                  bytes:(NSNumber *)bytes 
1476
                                   file:(NSString *)filePath 
1477
                                ifMatch:(NSString *)matchETag {
1478
    ASIPithosObjectRequest *request = [self updateObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
1479
                                                                     contentEncoding:contentEncoding 
1480
                                                                  contentDisposition:contentDisposition 
1481
                                                                            manifest:manifest 
1482
                                                                             sharing:sharing 
1483
                                                                            isPublic:isPublic 
1484
                                                                            metadata:metadata 
1485
                                                                              update:update 
1486
                                                                        contentRange:contentRange 
1487
                                                                               bytes:bytes 
1488
                                                                                file:filePath];
1489
    [request addRequestIfMatchHeader:matchETag];
1490
    return request;                                                                          
1491
}
1492

    
1493
// POST storageURL/container/object?[update=] (update data from file) [If-None-Match]
1494
+ (id)updateObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1495
                        contentEncoding:(NSString *)contentEncoding 
1496
                     contentDisposition:(NSString *)contentDisposition 
1497
                               manifest:(NSString *)manifest 
1498
                                sharing:(NSString *)sharing 
1499
                               isPublic:(NSUInteger)isPublic 
1500
                               metadata:(NSDictionary *)metadata 
1501
                                 update:(BOOL)update 
1502
                           contentRange:(NSString *)contentRange 
1503
                                  bytes:(NSNumber *)bytes 
1504
                                   file:(NSString *)filePath 
1505
                            ifNoneMatch:(NSString *)matchETag {
1506
    ASIPithosObjectRequest *request = [self updateObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
1507
                                                                     contentEncoding:contentEncoding 
1508
                                                                  contentDisposition:contentDisposition 
1509
                                                                            manifest:manifest 
1510
                                                                             sharing:sharing 
1511
                                                                            isPublic:isPublic 
1512
                                                                            metadata:metadata 
1513
                                                                              update:update 
1514
                                                                        contentRange:contentRange 
1515
                                                                               bytes:bytes 
1516
                                                                                file:filePath];
1517
    [request addRequestIfNoneMatchHeader:matchETag];
1518
    return request;                                                                          
1519
}
1520

    
1521
// POST storageURL/container/object?[update=] (update data from source)
1522
+ (id)updateObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1523
                        contentEncoding:(NSString *)contentEncoding 
1524
                     contentDisposition:(NSString *)contentDisposition 
1525
                               manifest:(NSString *)manifest 
1526
                                sharing:(NSString *)sharing 
1527
                               isPublic:(NSUInteger)isPublic 
1528
                               metadata:(NSDictionary *)metadata 
1529
                                 update:(BOOL)update 
1530
                           contentRange:(NSString *)contentRange 
1531
                                  bytes:(NSNumber *)bytes 
1532
                    sourceContainerName:(NSString *)sourceContainerName 
1533
                       sourceObjectName:(NSString *)sourceObjectName 
1534
                          sourceAccount:(NSString *)sourceAccount
1535
                          sourceVersion:(NSString *)sourceVersion {
1536
    NSString *queryString = nil;
1537
    if (update)
1538
        queryString = @"?update=";
1539
	ASIPithosObjectRequest *request = [self storageRequestWithMethod:@"POST" pithos:pithos containerName:containerName objectName:objectName queryString:queryString];
1540
    [request prepareObjectRequestWithETag:nil
1541
                              contentType:nil
1542
                          contentEncoding:contentEncoding 
1543
                       contentDisposition:contentDisposition 
1544
                                 manifest:manifest 
1545
                                  sharing:sharing 
1546
                                 isPublic:isPublic 
1547
                                 metadata:metadata];
1548
    if (contentRange)
1549
        [request addRequestHeader:@"Content-Range" value:contentRange];
1550
    if (bytes)
1551
        [request addRequestHeader:@"X-Object-Bytes" value:[NSString stringWithFormat:@"%lu", [bytes unsignedLongValue]]];
1552
    [request addRequestHeader:@"X-Source-Object" 
1553
                        value:[self encodeToPercentEscape:[NSString stringWithFormat:@"/%@/%@", sourceContainerName, sourceObjectName]]];
1554
    if (sourceAccount)
1555
        [request addRequestHeader:@"X-Source-Account" 
1556
                            value:[self encodeToPercentEscape:sourceAccount]];
1557
    if (sourceVersion)
1558
        [request addRequestHeader:@"X-Source-Version" value:sourceVersion];
1559
	return request;
1560

    
1561
}
1562

    
1563
// POST storageURL/container/object?[update=] (update data from source) [If-Match]
1564
+ (id)updateObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1565
                        contentEncoding:(NSString *)contentEncoding 
1566
                     contentDisposition:(NSString *)contentDisposition 
1567
                               manifest:(NSString *)manifest 
1568
                                sharing:(NSString *)sharing 
1569
                               isPublic:(NSUInteger)isPublic 
1570
                               metadata:(NSDictionary *)metadata 
1571
                                 update:(BOOL)update 
1572
                           contentRange:(NSString *)contentRange 
1573
                                  bytes:(NSNumber *)bytes 
1574
                    sourceContainerName:(NSString *)sourceContainerName 
1575
                       sourceObjectName:(NSString *)sourceObjectName 
1576
                          sourceAccount:(NSString *)sourceAccount
1577
                          sourceVersion:(NSString *)sourceVersion 
1578
                                ifMatch:(NSString *)matchETag {
1579
    ASIPithosObjectRequest *request = [self updateObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
1580
                                                                     contentEncoding:contentEncoding 
1581
                                                                  contentDisposition:contentDisposition 
1582
                                                                            manifest:manifest 
1583
                                                                             sharing:sharing 
1584
                                                                            isPublic:isPublic 
1585
                                                                            metadata:metadata 
1586
                                                                              update:update 
1587
                                                                        contentRange:contentRange 
1588
                                                                               bytes:bytes 
1589
                                                                 sourceContainerName:sourceContainerName 
1590
                                                                    sourceObjectName:sourceObjectName 
1591
                                                                       sourceAccount:sourceAccount 
1592
                                                                       sourceVersion:sourceVersion];
1593
    [request addRequestIfMatchHeader:matchETag];
1594
    return request;                                                                          
1595
}
1596

    
1597
// POST storageURL/container/object?[update=] (update data from source) [If-None-Match]
1598
+ (id)updateObjectDataRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1599
                        contentEncoding:(NSString *)contentEncoding 
1600
                     contentDisposition:(NSString *)contentDisposition 
1601
                               manifest:(NSString *)manifest 
1602
                                sharing:(NSString *)sharing 
1603
                               isPublic:(NSUInteger)isPublic 
1604
                               metadata:(NSDictionary *)metadata 
1605
                                 update:(BOOL)update 
1606
                           contentRange:(NSString *)contentRange 
1607
                                  bytes:(NSNumber *)bytes 
1608
                    sourceContainerName:(NSString *)sourceContainerName 
1609
                       sourceObjectName:(NSString *)sourceObjectName 
1610
                          sourceAccount:(NSString *)sourceAccount
1611
                          sourceVersion:(NSString *)sourceVersion 
1612
                            ifNoneMatch:(NSString *)matchETag {
1613
    ASIPithosObjectRequest *request = [self updateObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName 
1614
                                                                     contentEncoding:contentEncoding 
1615
                                                                  contentDisposition:contentDisposition 
1616
                                                                            manifest:manifest 
1617
                                                                             sharing:sharing 
1618
                                                                            isPublic:isPublic 
1619
                                                                            metadata:metadata 
1620
                                                                              update:update 
1621
                                                                        contentRange:contentRange 
1622
                                                                               bytes:bytes 
1623
                                                                 sourceContainerName:sourceContainerName 
1624
                                                                    sourceObjectName:sourceObjectName 
1625
                                                                       sourceAccount:sourceAccount 
1626
                                                                       sourceVersion:sourceVersion];
1627
    [request addRequestIfNoneMatchHeader:matchETag];
1628
    return request;                                                                          
1629
}
1630

    
1631
#pragma mark -
1632
#pragma mark DELETE
1633

    
1634
// DELETE storageURL/container/object
1635
+ (id)deleteObjectRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName {
1636
    return [self storageRequestWithMethod:@"DELETE" pithos:pithos containerName:containerName objectName:objectName];
1637
}
1638

    
1639
// DELETE storageURL/container/object?[until=untilTimestamp]
1640
+ (id)deleteObjectRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName 
1641
                              until:(NSDate *)untilTimestamp {
1642
    NSString *queryString = nil;
1643
    if (untilTimestamp)
1644
        queryString = [NSString stringWithFormat:@"?until=%d", (int)[untilTimestamp timeIntervalSince1970]];
1645
	return [self storageRequestWithMethod:@"DELETE" pithos:pithos containerName:containerName objectName:objectName queryString:queryString];
1646
}
1647

    
1648
#pragma mark -
1649
#pragma mark NSXMLParserDelegate
1650

    
1651
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
1652
	self.currentElement = elementName;
1653
    if ((objectRequestType == ASIPithosObjectRequestHashmap) && [elementName isEqualToString:@"object"]) {
1654
        blockSize = [[attributeDict valueForKey:@"block_size"] intValue];
1655
        blockHash = [[NSString alloc] initWithString:[attributeDict valueForKey:@"block_hash"]];
1656
        bytes = [[attributeDict valueForKey:@"bytes"] intValue];
1657
    } else if ((objectRequestType == ASIPithosObjectRequestVersions) && [elementName isEqualToString:@"version"]) {
1658
        self.currentObject = [ASIPithosObject object];
1659
        currentObject.versionTimestamp = [NSDate dateWithTimeIntervalSince1970:[[attributeDict valueForKey:@"timestamp"] doubleValue]];
1660
	}
1661
	self.currentContent = @"";
1662
}
1663

    
1664
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
1665
	if (((objectRequestType == ASIPithosObjectRequestHashmap) && [elementName isEqualToString:@"hash"]) ||
1666
        ((objectRequestType == ASIPithosObjectRequestHashmapWrite) && [elementName isEqualToString:@"item"])) {
1667
        [hashes addObject:currentContent];
1668
    } else if (objectRequestType == ASIPithosObjectRequestVersions) {
1669
        if ([elementName isEqualToString:@"version"]) {
1670
            currentObject.version = currentContent;
1671
        } else if ([elementName isEqualToString:@"object"]) {
1672
            [versions addObject:currentObject];
1673
            self.currentObject = nil;
1674
        }
1675
	}
1676
}
1677

    
1678
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
1679
    self.currentContent = [currentContent stringByAppendingString:string];
1680
}
1681

    
1682
@end