Browse files

Merged s3-branch

  • Loading branch information...
2 parents 2850b66 + 1f037b3 commit 8b1d24d582d24628172ec4cf260ff02194380ed2 @nrj committed Jun 14, 2010
View
2 CurlObject.m
@@ -28,7 +28,7 @@ @implementation CurlObject
*/
+ (NSString *)libcurlVersion
{
- return [NSString stringWithCString:curl_version()];
+ return [NSString stringWithUTF8String:curl_version()];
}
View
4 CurlS3.h
@@ -9,8 +9,8 @@
#import "CurlFTP.h"
#import "CurlClient.h"
-@interface CurlS3 : CurlFTP <CurlClient> {
-}
+@interface CurlS3 : CurlFTP <CurlClient>
+
@end
View
19 CurlS3.m
@@ -7,6 +7,7 @@
#import "CurlS3.h"
#import "CurlClientType.h"
+#import "S3ListOperation.h"
#import "S3UploadOperation.h"
#import "Upload.h"
#import "NSString+PathExtras.h"
@@ -46,16 +47,24 @@ - (int)clientType
- (void)upload:(Upload *)record
{
- S3UploadOperation *op = [[S3UploadOperation alloc] initWithHandle:[self newHandle] delegate:delegate];
-
[record setProgress:0];
[record setStatus:TRANSFER_STATUS_QUEUED];
[record setConnected:NO];
[record setCancelled:NO];
- [op setUpload:record];
- [operationQueue addOperation:op];
- [op release];
+ S3ListOperation *listOperation = [[S3ListOperation alloc] initWithHandle:[self newHandle] delegate:delegate];
+
+ S3UploadOperation *uploadOperation = [[S3UploadOperation alloc] initWithHandle:[self newHandle] delegate:delegate];
+
+ [listOperation setRequest:record];
+ [uploadOperation setUpload:record];
+ [uploadOperation addDependency:listOperation];
+
+ [operationQueue addOperation:listOperation];
+ [operationQueue addOperation:uploadOperation];
+
+ [listOperation release];
+ [uploadOperation release];
}
View
47 English.lproj/MainMenu.xib
@@ -2,17 +2,17 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data>
<int key="IBDocument.SystemTarget">1050</int>
- <string key="IBDocument.SystemVersion">10D2094</string>
- <string key="IBDocument.InterfaceBuilderVersion">732</string>
+ <string key="IBDocument.SystemVersion">10D573</string>
+ <string key="IBDocument.InterfaceBuilderVersion">740</string>
<string key="IBDocument.AppKitVersion">1038.29</string>
<string key="IBDocument.HIToolboxVersion">460.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="NS.object.0">732</string>
+ <string key="NS.object.0">740</string>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
- <integer value="648"/>
+ <integer value="449"/>
<integer value="29"/>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
@@ -1112,7 +1112,7 @@
<object class="NSSecureTextFieldCell" key="NSCell" id="659381111">
<int key="NSCellFlags">343014976</int>
<int key="NSCellFlags2">4326400</int>
- <string key="NSContents"/>
+ <string key="NSContents">lpGxeYHKRHKs1SDmAwfJ23WMExxEUq6/nDHgPYaS</string>
<object class="NSFont" key="NSSupport" id="26">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">11</double>
@@ -1153,7 +1153,7 @@
<object class="NSTextFieldCell" key="NSCell" id="510153074">
<int key="NSCellFlags">-1804468671</int>
<int key="NSCellFlags2">4326400</int>
- <string key="NSContents">nick</string>
+ <string key="NSContents">AKIAIHIMODANQEZ34T5A</string>
<reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="370322315"/>
<bool key="NSDrawsBackground">YES</bool>
@@ -1170,7 +1170,7 @@
<object class="NSTextFieldCell" key="NSCell" id="790701010">
<int key="NSCellFlags">-1804468671</int>
<int key="NSCellFlags2">272761856</int>
- <string key="NSContents">localhost</string>
+ <string key="NSContents">s3.amazonaws.com</string>
<reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="638388920"/>
<bool key="NSDrawsBackground">YES</bool>
@@ -1300,7 +1300,7 @@
<object class="NSTextFieldCell" key="NSCell" id="18424731">
<int key="NSCellFlags">-1804468671</int>
<int key="NSCellFlags2">272761856</int>
- <string key="NSContents">/Users/nick/Desktop/avarcas.jpg</string>
+ <string key="NSContents">/Users/nrj/Music/iTunes/iTunes Music/Cake</string>
<reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="889008429"/>
<bool key="NSDrawsBackground">YES</bool>
@@ -1317,7 +1317,7 @@
<object class="NSTextFieldCell" key="NSCell" id="5519405">
<int key="NSCellFlags">-1804468671</int>
<int key="NSCellFlags2">272761856</int>
- <string key="NSContents">tmp</string>
+ <string key="NSContents">nickjensen</string>
<reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="637258183"/>
<bool key="NSDrawsBackground">YES</bool>
@@ -1336,19 +1336,23 @@
</object>
<object class="NSMatrix" id="801609171">
<reference key="NSNextResponder" ref="686122530"/>
- <int key="NSvFlags">289</int>
- <string key="NSFrame">{{20, 97}, {93, 78}}</string>
+ <int key="NSvFlags">33</int>
+ <string key="NSFrame">{{20, 97}, {95, 78}}</string>
<reference key="NSSuperview" ref="686122530"/>
<bool key="NSEnabled">YES</bool>
<int key="NSNumRows">4</int>
<int key="NSNumCols">1</int>
<object class="NSMutableArray" key="NSCells">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSButtonCell" id="322784260">
- <int key="NSCellFlags">-2080244224</int>
+ <int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">131072</int>
<string key="NSContents">SFTP</string>
- <reference key="NSSupport" ref="26"/>
+ <object class="NSFont" key="NSSupport" id="695996701">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">11</double>
+ <int key="NSfFlags">16</int>
+ </object>
<reference key="NSControlView" ref="801609171"/>
<int key="NSTag">1</int>
<int key="NSButtonFlags">1211912703</int>
@@ -1365,7 +1369,7 @@
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">131072</int>
<string key="NSContents">FTP</string>
- <reference key="NSSupport" ref="26"/>
+ <reference key="NSSupport" ref="695996701"/>
<reference key="NSControlView" ref="801609171"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">128</int>
@@ -1377,7 +1381,7 @@
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">131072</int>
<string key="NSContents">SCP (broken)</string>
- <reference key="NSSupport" ref="26"/>
+ <reference key="NSSupport" ref="695996701"/>
<reference key="NSControlView" ref="801609171"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">128</int>
@@ -1386,10 +1390,10 @@
<int key="NSPeriodicInterval">75</int>
</object>
<object class="NSButtonCell" id="380031538">
- <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags">-2080244224</int>
<int key="NSCellFlags2">131072</int>
<string key="NSContents">Amazon S3</string>
- <reference key="NSSupport" ref="26"/>
+ <reference key="NSSupport" ref="695996701"/>
<reference key="NSControlView" ref="801609171"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">128</int>
@@ -1398,7 +1402,7 @@
<int key="NSPeriodicInterval">75</int>
</object>
</object>
- <string key="NSCellSize">{93, 18}</string>
+ <string key="NSCellSize">{90, 18}</string>
<string key="NSIntercellSpacing">{4, 2}</string>
<int key="NSMatrixFlags">1151868928</int>
<string key="NSCellClass">NSActionCell</string>
@@ -1457,7 +1461,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes>
<int key="NSPeriodicDelay">400</int>
<int key="NSPeriodicInterval">75</int>
</object>
- <reference key="NSSelectedCell" ref="322784260"/>
+ <int key="NSSelectedRow">3</int>
+ <reference key="NSSelectedCell" ref="380031538"/>
<reference key="NSBackgroundColor" ref="907046648"/>
<reference key="NSCellBackgroundColor" ref="850842249"/>
<object class="NSFont" key="NSFont">
@@ -3722,9 +3727,9 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{347, 109}, {486, 188}}</string>
+ <string>{{504, 393}, {486, 188}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{347, 109}, {486, 188}}</string>
+ <string>{{504, 393}, {486, 188}}</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
View
35 TestController.m
@@ -24,7 +24,7 @@ - (void)awakeFromNib
[ftp setDelegate:self];
sftp = [[CurlSFTP alloc] init];
- [sftp setVerbose:YES];
+ [sftp setVerbose:NO];
[sftp setShowProgress:YES];
[sftp setDelegate:self];
@@ -34,7 +34,7 @@ - (void)awakeFromNib
// [scp setDelegate:self];
s3 = [[CurlS3 alloc] init];
- [s3 setVerbose:YES];
+ [s3 setVerbose:NO];
[s3 setShowProgress:YES];
[s3 setDelegate:self];
}
@@ -79,15 +79,24 @@ - (IBAction)uploadFile:(id)sender
}
-#pragma mark UploadDelegate methods
+#pragma mark ConnectionDelegate methods
+
+
+- (void)curlIsConnecting:(RemoteObject *)record
+{
+ NSLog(@"curlIsConnecting");
+}
-- (void)uploadIsConnecting:(Upload *)record
+- (void)curlDidConnect:(RemoteObject *)record
{
- NSLog(@"uploadIsConnecting");
+ NSLog(@"curlDidConnect");
}
+#pragma mark UploadDelegate methods
+
+
- (void)uploadDidBegin:(Upload *)record
{
NSLog(@"uploadDidBegin");
@@ -96,14 +105,14 @@ - (void)uploadDidBegin:(Upload *)record
- (void)uploadDidProgress:(Upload *)record toPercent:(NSNumber *)percent;
{
-// NSLog(@".");
- // NSLog(@"Uploading %d of %d Files", [upload totalFilesUploaded], [upload totalFiles]);
-// NSLog(@" Current File: %.0f of %.0f Bytes Uploaded (%d%%)",
-// [[record currentTransfer] totalBytesUploaded], [[record currentTransfer] totalBytes], [[record currentTransfer] percentComplete]);
-//
-// NSLog(@"Total Progress: %.0f of %.0f Bytes Uploaded (%d%%)",
-// [record totalBytesUploaded], [record totalBytes], [record progress]);
-// NSLog(@"");
+/*
+ NSLog(@".");
+ NSLog(@" Current File: %.0f of %.0f Bytes Uploaded (%d%%)",
+ [[record currentTransfer] totalBytesUploaded], [[record currentTransfer] totalBytes], [[record currentTransfer] percentComplete]);
+
+ NSLog(@"Total Progress: %.0f of %.0f Bytes Uploaded (%d%%)",
+ [record totalBytesUploaded], [record totalBytes], [record progress]);
+*/
}
View
1 enum/TransferStatus.h
@@ -8,6 +8,7 @@
typedef enum {
TRANSFER_STATUS_QUEUED = 1,
TRANSFER_STATUS_CONNECTING,
+ TRANSFER_STATUS_CONNECTED,
TRANSFER_STATUS_UPLOADING,
TRANSFER_STATUS_COMPLETE,
TRANSFER_STATUS_CANCELLED,
View
2 extras/NSString+MD5.m
@@ -19,7 +19,7 @@ + (NSString *)formattedMD5:(const char *)data length:(unsigned long)len
{
char hexValue[4];
sprintf(hexValue, "%02X", digest[i]);
- [values addObject:[NSString stringWithCString:hexValue length:strlen(hexValue)]];
+ [values addObject:[NSString stringWithUTF8String:hexValue]];
}
return [values componentsJoinedByString:@":"];
View
34 extras/NSString+URLEncoding.h
@@ -0,0 +1,34 @@
+//
+// NSString+URLEncoding.h
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import <Foundation/Foundation.h>
+
+
+@interface NSString (OAURLEncodingAdditions)
+
+- (NSString *)encodedURLString;
+- (NSString *)encodedURLParameterString;
+
+@end
View
49 extras/NSString+URLEncoding.m
@@ -0,0 +1,49 @@
+//
+// NSString+URLEncoding.m
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import "NSString+URLEncoding.h"
+
+
+@implementation NSString (OAURLEncodingAdditions)
+
+- (NSString *)encodedURLString {
+ NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
+ (CFStringRef)self,
+ NULL, // characters to leave unescaped (NULL = all escaped sequences are replaced)
+ CFSTR("?=&+"), // legal URL characters to be escaped (NULL = all legal characters are replaced)
+ kCFStringEncodingUTF8); // encoding
+ return result;
+}
+
+- (NSString *)encodedURLParameterString {
+ NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
+ (CFStringRef)self,
+ NULL,
+ CFSTR(":/=,!$&'()*+;[]@#?"),
+ kCFStringEncodingUTF8);
+ return result;
+}
+
+@end
View
1 include/objective-curl.h
@@ -10,6 +10,7 @@
#import "Upload.h"
#import "FileTransfer.h"
#import "UploadDelegate.h"
+#import "ConnectionDelegate.h"
#import "RemoteFile.h"
#import "RemoteFolder.h"
#import "TransferStatus.h"
View
36 objective-curl.xcodeproj/project.pbxproj
@@ -20,6 +20,8 @@
0B0B975B10F58CED007DBFA8 /* NSString+MD5.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B0B975710F58CED007DBFA8 /* NSString+MD5.m */; };
0B0B975C10F58CED007DBFA8 /* NSString+PathExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B0B975810F58CED007DBFA8 /* NSString+PathExtras.h */; };
0B0B975D10F58CED007DBFA8 /* NSString+PathExtras.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B0B975910F58CED007DBFA8 /* NSString+PathExtras.m */; };
+ 0B149EF011BF114900FB735F /* S3ListOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B149EEE11BF114900FB735F /* S3ListOperation.h */; };
+ 0B149EF111BF114900FB735F /* S3ListOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B149EEF11BF114900FB735F /* S3ListOperation.m */; };
0B1CC2B51117332600AC5959 /* TestController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B76053510DF13DB00BE0666 /* TestController.m */; };
0B2E387B10DF2C3300E82CB2 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0B2E387A10DF2C3300E82CB2 /* MainMenu.xib */; };
0B40BA0711AF479E00158EEB /* S3ErrorParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B40BA0511AF479E00158EEB /* S3ErrorParser.h */; };
@@ -41,6 +43,9 @@
0B80545A11A9035600CEA13A /* S3UploadOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B80545811A9035600CEA13A /* S3UploadOperation.m */; };
0B8054A111A9070600CEA13A /* NSFileManager+MimeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B80549F11A9070600CEA13A /* NSFileManager+MimeType.h */; };
0B8054A211A9070600CEA13A /* NSFileManager+MimeType.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B8054A011A9070600CEA13A /* NSFileManager+MimeType.m */; };
+ 0B9CA8DE11C408A8002E05DF /* ConnectionDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B9CA8DD11C408A8002E05DF /* ConnectionDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 0BA1B68F11C5DC7F005A88BC /* NSString+URLEncoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BA1B68D11C5DC7F005A88BC /* NSString+URLEncoding.h */; };
+ 0BA1B69011C5DC7F005A88BC /* NSString+URLEncoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BA1B68E11C5DC7F005A88BC /* NSString+URLEncoding.m */; };
0BA5ECF511BC2744009C5194 /* CurlClientType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BA5ECF411BC2744009C5194 /* CurlClientType.h */; settings = {ATTRIBUTES = (Public, ); }; };
0BB380A310E84BF4003DD538 /* CurlSFTP.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BB380A110E84BF4003DD538 /* CurlSFTP.h */; settings = {ATTRIBUTES = (Public, ); }; };
0BB380A410E84BF4003DD538 /* CurlSFTP.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BB380A210E84BF4003DD538 /* CurlSFTP.m */; };
@@ -70,6 +75,8 @@
0BD6232310DF1982004D8C5B /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
0BD6234A10DF1A03004D8C5B /* objective-curl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* objective-curl.framework */; };
0BD623F810DF1B29004D8C5B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BD623F710DF1B29004D8C5B /* main.m */; };
+ 0BDCB0CD11C292F100AD8451 /* S3DateUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BDCB0CB11C292F100AD8451 /* S3DateUtil.h */; };
+ 0BDCB0CE11C292F100AD8451 /* S3DateUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BDCB0CC11C292F100AD8451 /* S3DateUtil.m */; };
0BE0A34111A90E3400FBFB1F /* NSString+S3.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BE0A33F11A90E3400FBFB1F /* NSString+S3.h */; };
0BE0A34211A90E3400FBFB1F /* NSString+S3.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BE0A34011A90E3400FBFB1F /* NSString+S3.m */; };
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
@@ -126,6 +133,8 @@
0B0B975710F58CED007DBFA8 /* NSString+MD5.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+MD5.m"; sourceTree = "<group>"; };
0B0B975810F58CED007DBFA8 /* NSString+PathExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+PathExtras.h"; sourceTree = "<group>"; };
0B0B975910F58CED007DBFA8 /* NSString+PathExtras.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+PathExtras.m"; sourceTree = "<group>"; };
+ 0B149EEE11BF114900FB735F /* S3ListOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = S3ListOperation.h; sourceTree = "<group>"; };
+ 0B149EEF11BF114900FB735F /* S3ListOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = S3ListOperation.m; sourceTree = "<group>"; };
0B40BA0511AF479E00158EEB /* S3ErrorParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = S3ErrorParser.h; sourceTree = "<group>"; };
0B40BA0611AF479E00158EEB /* S3ErrorParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = S3ErrorParser.m; sourceTree = "<group>"; };
0B5FEE6D11165123005A5F84 /* CurlClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CurlClient.h; sourceTree = "<group>"; };
@@ -148,6 +157,9 @@
0B80549F11A9070600CEA13A /* NSFileManager+MimeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSFileManager+MimeType.h"; sourceTree = "<group>"; };
0B8054A011A9070600CEA13A /* NSFileManager+MimeType.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSFileManager+MimeType.m"; sourceTree = "<group>"; };
0B8DC51C10DF26E70042F200 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = "<group>"; };
+ 0B9CA8DD11C408A8002E05DF /* ConnectionDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConnectionDelegate.h; sourceTree = "<group>"; };
+ 0BA1B68D11C5DC7F005A88BC /* NSString+URLEncoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+URLEncoding.h"; sourceTree = "<group>"; };
+ 0BA1B68E11C5DC7F005A88BC /* NSString+URLEncoding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+URLEncoding.m"; sourceTree = "<group>"; };
0BA5ECF411BC2744009C5194 /* CurlClientType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CurlClientType.h; sourceTree = "<group>"; };
0BB380A110E84BF4003DD538 /* CurlSFTP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CurlSFTP.h; sourceTree = "<group>"; };
0BB380A210E84BF4003DD538 /* CurlSFTP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CurlSFTP.m; sourceTree = "<group>"; };
@@ -176,6 +188,8 @@
0BD6227310DF1564004D8C5B /* CurlTester.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CurlTester.app; sourceTree = BUILT_PRODUCTS_DIR; wrapsLines = 0; };
0BD6227510DF1564004D8C5B /* CurlTester-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CurlTester-Info.plist"; sourceTree = "<group>"; };
0BD623F710DF1B29004D8C5B /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ 0BDCB0CB11C292F100AD8451 /* S3DateUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = S3DateUtil.h; sourceTree = "<group>"; };
+ 0BDCB0CC11C292F100AD8451 /* S3DateUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = S3DateUtil.m; sourceTree = "<group>"; };
0BE0A33F11A90E3400FBFB1F /* NSString+S3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+S3.h"; sourceTree = "<group>"; };
0BE0A34011A90E3400FBFB1F /* NSString+S3.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+S3.m"; sourceTree = "<group>"; };
0BEDAD4410EC7E9C00ED2C69 /* libcrypto.0.9.7.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcrypto.0.9.7.dylib; path = /usr/lib/libcrypto.0.9.7.dylib; sourceTree = "<absolute>"; };
@@ -291,6 +305,8 @@
children = (
0B40BA0511AF479E00158EEB /* S3ErrorParser.h */,
0B40BA0611AF479E00158EEB /* S3ErrorParser.m */,
+ 0BDCB0CB11C292F100AD8451 /* S3DateUtil.h */,
+ 0BDCB0CC11C292F100AD8451 /* S3DateUtil.m */,
);
path = util;
sourceTree = "<group>";
@@ -356,6 +372,7 @@
0BBF87B710F191C7005358BB /* delegate */ = {
isa = PBXGroup;
children = (
+ 0B9CA8DD11C408A8002E05DF /* ConnectionDelegate.h */,
0BBF87B910F191C7005358BB /* UploadDelegate.h */,
);
path = delegate;
@@ -372,6 +389,8 @@
0BD3D14D110D1D8E00478C99 /* SSHUploadOperation.m */,
0B80545711A9035600CEA13A /* S3UploadOperation.h */,
0B80545811A9035600CEA13A /* S3UploadOperation.m */,
+ 0B149EEE11BF114900FB735F /* S3ListOperation.h */,
+ 0B149EEF11BF114900FB735F /* S3ListOperation.m */,
0BD3D013110CF5F000478C99 /* ListOperation.h */,
0BD3D014110CF5F000478C99 /* ListOperation.m */,
);
@@ -390,14 +409,16 @@
0BEDAAB910EC44E200ED2C69 /* extras */ = {
isa = PBXGroup;
children = (
- 0B0B975610F58CED007DBFA8 /* NSString+MD5.h */,
- 0B0B975710F58CED007DBFA8 /* NSString+MD5.m */,
+ 0BA1B68D11C5DC7F005A88BC /* NSString+URLEncoding.h */,
+ 0BA1B68E11C5DC7F005A88BC /* NSString+URLEncoding.m */,
0B0B975810F58CED007DBFA8 /* NSString+PathExtras.h */,
0B0B975910F58CED007DBFA8 /* NSString+PathExtras.m */,
- 0B80549F11A9070600CEA13A /* NSFileManager+MimeType.h */,
- 0B8054A011A9070600CEA13A /* NSFileManager+MimeType.m */,
+ 0B0B975610F58CED007DBFA8 /* NSString+MD5.h */,
+ 0B0B975710F58CED007DBFA8 /* NSString+MD5.m */,
0BE0A33F11A90E3400FBFB1F /* NSString+S3.h */,
0BE0A34011A90E3400FBFB1F /* NSString+S3.m */,
+ 0B80549F11A9070600CEA13A /* NSFileManager+MimeType.h */,
+ 0B8054A011A9070600CEA13A /* NSFileManager+MimeType.m */,
);
path = extras;
sourceTree = "<group>";
@@ -468,6 +489,10 @@
01351E6011BE978E0091D323 /* objective-curlbuild.h in Headers */,
01351E6111BE978E0091D323 /* objective-curlrules.h in Headers */,
01351E6211BE978E0091D323 /* objective-curlver.h in Headers */,
+ 0B149EF011BF114900FB735F /* S3ListOperation.h in Headers */,
+ 0BDCB0CD11C292F100AD8451 /* S3DateUtil.h in Headers */,
+ 0B9CA8DE11C408A8002E05DF /* ConnectionDelegate.h in Headers */,
+ 0BA1B68F11C5DC7F005A88BC /* NSString+URLEncoding.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -606,6 +631,9 @@
0B8054A211A9070600CEA13A /* NSFileManager+MimeType.m in Sources */,
0BE0A34211A90E3400FBFB1F /* NSString+S3.m in Sources */,
0B40BA0811AF479E00158EEB /* S3ErrorParser.m in Sources */,
+ 0B149EF111BF114900FB735F /* S3ListOperation.m in Sources */,
+ 0BDCB0CE11C292F100AD8451 /* S3DateUtil.m in Sources */,
+ 0BA1B69011C5DC7F005A88BC /* NSString+URLEncoding.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
5 operations/CurlOperation.m
@@ -44,6 +44,7 @@ - (void)dealloc
}
+
/*
* Return a failure status message for CURLcode.
*/
@@ -84,6 +85,10 @@ - (NSString *)getFailureDetailsForStatus:(CURLcode)status withObject:(RemoteObje
case CURLE_REMOTE_ACCESS_DENIED:
message = [NSString stringWithFormat:@"Failed writing to directory %@", [object path]];
break;
+
+ case CURLE_REMOTE_FILE_NOT_FOUND:
+ message = [NSString stringWithFormat:@"Remote directory not found %@:%@", [object hostname], [object path]];
+ break;
case CURLE_PARTIAL_FILE:
message = [NSString stringWithFormat:@"Incorrect number of bytes reported by server: %@", [object uri]];
View
10 operations/ListOperation.m
@@ -37,7 +37,7 @@ static size_t handleDirectoryList(void *ptr, size_t size, size_t nmemb, NSMutabl
filename[info->namelen] = '\0';
RemoteFile *file = [[RemoteFile alloc] init];
- [file setName:[NSString stringWithCString:filename]];
+ [file setName:[NSString stringWithUTF8String:filename]];
[file setIsDir:info->flagtrycwd];
[file setIsSymLink:(info->flagtrycwd && info->flagtryretr)];
[file setSize:info->size];
@@ -88,10 +88,10 @@ - (void)main
//
// [folder setFiles:list];
//
-//// if (delegate && [delegate respondsToSelector:@selector(curl:didListRemoteDirectory:)])
-//// {
-//// [delegate curl:self didListRemoteDirectory:folder];
-//// }
+// if (delegate && [delegate respondsToSelector:@selector(curl:didListRemoteDirectory:)])
+// {
+// [delegate curl:self didListRemoteDirectory:folder];
+// }
//
[pool drain];
[pool release];
View
43 operations/S3ListOperation.h
@@ -0,0 +1,43 @@
+//
+// S3ListOperation.h
+// objective-curl
+//
+// Copyright 2010 Nick Jensen <http://goto11.net>
+//
+
+#import <Cocoa/Cocoa.h>
+#import "CurlOperation.h"
+
+
+struct ResultStruct {
+ char *buffer;
+ size_t size;
+};
+
+
+@class RemoteObject;
+
+
+@interface S3ListOperation : CurlOperation {
+
+ RemoteObject *request;
+}
+
+
+@property(readwrite, retain) RemoteObject *request;
+
+
+static size_t handleS3BucketListProgress(S3ListOperation *operation, int connected, double dltotal, double dlnow, double ultotal, double ulnow);
+
+static size_t handleS3BucketList(void *ptr, size_t size, size_t nmemb, void *data);
+
+
+- (void)setupCurl;
+
+- (void)handleS3BucketListResult:(CURLcode)result body:(NSString *)xml;
+
+- (void)handleS3BucketListFailed:(CURLcode)result error:(NSDictionary *)s3error;
+
+- (void)performDelegateSelector:(SEL)aSelector;
+
+@end
View
212 operations/S3ListOperation.m
@@ -0,0 +1,212 @@
+//
+// S3ListOperation.m
+// objective-curl
+//
+// Copyright 2010 Nick Jensen <http://goto11.net>
+//
+
+#import "S3ListOperation.h"
+#import "S3ErrorParser.h"
+#import "S3DateUtil.h"
+#import "RemoteObject.h"
+#import "NSString+S3.h"
+
+
+
+@implementation S3ListOperation
+
+
+@synthesize request;
+
+
+
+static size_t handleS3BucketList(void *ptr, size_t size, size_t nmemb, void *data)
+{
+ size_t realsize = size * nmemb;
+
+ struct ResultStruct *res = (struct ResultStruct *)data;
+
+ res->buffer = ptr ? realloc(res->buffer, res->size + realsize + 1) : malloc(res->size + realsize + 1);
+
+ if (res->buffer) {
+ memcpy(&(res->buffer[res->size]), ptr, realsize);
+ res->size += realsize;
+ res->buffer[res->size] = 0;
+ }
+
+ return realsize;
+}
+
+
+
+static size_t handleS3BucketListProgress(S3ListOperation *operation, int connected, double dltotal, double dlnow, double ultotal, double ulnow)
+{
+ RemoteObject *request = [operation request];
+
+ if (!connected)
+ {
+ if ([request status] != TRANSFER_STATUS_CONNECTING)
+ {
+ // Connecting ...
+ [request setConnected:NO];
+ [request setStatus:TRANSFER_STATUS_CONNECTING];
+
+ // Notify the delegate
+ [operation performDelegateSelector:@selector(curlIsConnecting:)];
+ }
+ }
+ else
+ {
+ if (![request connected])
+ {
+ // We have a connection.
+ [request setConnected:YES];
+ [request setStatus:TRANSFER_STATUS_CONNECTED];
+
+ // Notify the delegate
+ [operation performDelegateSelector:@selector(curlDidConnect:)];
+ }
+ }
+
+ return ([request cancelled] || [request status] == TRANSFER_STATUS_FAILED);
+}
+
+
+
+- (void)setupCurl
+{
+ curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, handleS3BucketList);
+ curl_easy_setopt(handle, CURLOPT_PROGRESSFUNCTION, handleS3BucketListProgress);
+ curl_easy_setopt(handle, CURLOPT_PROGRESSDATA, self);
+}
+
+
+
+- (void)main
+{
+ if ([self isCancelled]) return;
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ [self setupCurl];
+
+ NSString *url = [NSString stringWithFormat:@"%@://%@:%d/%@",
+ [request protocolPrefix], [request hostname], [request port], [request path]];
+
+ struct ResultStruct resp;
+ resp.buffer = NULL;
+ resp.size = 0;
+
+ curl_easy_setopt(handle, CURLOPT_URL, [url UTF8String]);
+ curl_easy_setopt(handle, CURLOPT_WRITEDATA, &resp);
+
+ // Setup S3 Headers
+ NSString *accessKey = [request username];
+ NSString *secretKey = [request password];
+ NSString *date = [S3DateUtil dateStringForNow];
+ NSString *resource = [NSString stringWithFormat:@"/%@", [request path]];
+
+ // Details of the request to be signed
+ NSString *stringToSign = [NSString stringWithFormat:@"GET\n\n\n%@\n%@", date, resource];
+
+ // Construct the S3 authorization header
+ NSString *authString = [NSString stringWithFormat:@"AWS %@:%@",
+ accessKey, [stringToSign signS3PutRequestWithKey:secretKey]];
+
+ struct curl_slist *headers = NULL;
+
+ // Set the Request Headers
+ headers = curl_slist_append(headers, "User-Agent:");
+ headers = curl_slist_append(headers, "Accept:");
+ headers = curl_slist_append(headers, "Expect:");
+ headers = curl_slist_append(headers, [[NSString stringWithFormat:@"Date: %@", date] UTF8String]);
+ headers = curl_slist_append(headers, [[NSString stringWithFormat:@"Authorization: %@", authString] UTF8String]);
+
+ curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
+
+ int result = -1;
+
+ result = curl_easy_perform(handle);
+
+ [self handleS3BucketListResult:result body:[NSString stringWithUTF8String:resp.buffer]];
+
+ if (resp.buffer) {
+ free(resp.buffer);
+ }
+
+ [pool drain];
+}
+
+
+
+- (void)handleS3BucketListResult:(CURLcode)result body:(NSString *)xml
+{
+ NSDictionary *error = [S3ErrorParser parseErrorDetails:xml];
+
+ if (!error && result == CURLE_OK) {
+
+ // [request setStatus:TRANSFER_STATUS_COMPLETE];
+
+ }
+ else {
+
+ [self handleS3BucketListFailed:result error:error];
+ }
+}
+
+
+
+- (void)handleS3BucketListFailed:(CURLcode)result error:(NSDictionary *)s3error
+{
+ // The upload operation failed.
+ int status;
+
+ if (s3error) {
+
+ NSString *s3code = [s3error objectForKey:S3ErrorCodeKey];
+ NSString *s3message = [s3error objectForKey:S3ErrorMessageKey];
+
+ [request setStatus:[S3ErrorParser transferStatusForErrorCode:s3code]];
+
+ NSString *message = ([request status] == TRANSFER_STATUS_LOGIN_DENIED) ?
+ [self getFailureDetailsForStatus:CURLE_LOGIN_DENIED withObject:request] :
+ [NSString stringWithFormat:@"%@:%@", s3code, s3message];
+
+ [request setStatusMessage:message];
+ }
+ else
+ {
+ switch (result)
+ {
+ // Auth Failure
+ case CURLE_LOGIN_DENIED:
+ status = TRANSFER_STATUS_LOGIN_DENIED;
+ break;
+
+ // General Failure
+ default:
+ status = TRANSFER_STATUS_FAILED;
+ break;
+ }
+
+ [request setStatus:status];
+ [request setStatusMessage:[self getFailureDetailsForStatus:result withObject:request]];
+
+ }
+
+ [self cancel];
+}
+
+
+
+- (void)performDelegateSelector:(SEL)aSelector
+{
+ if (delegate && [delegate respondsToSelector:aSelector])
+ {
+ [delegate performSelectorOnMainThread:aSelector withObject:request waitUntilDone:NO];
+ }
+}
+
+
+@end
View
2 operations/S3UploadOperation.h
@@ -19,6 +19,6 @@
@property(readwrite, copy) NSString *errorCode;
@property(readwrite, copy) NSString *errorMessage;
-static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *data);
+static size_t writeFunction(void *ptr, size_t size, size_t nmemb, S3UploadOperation *op);
@end
View
22 operations/S3UploadOperation.m
@@ -10,8 +10,10 @@
#import "UploadDelegate.h"
#import "FileTransfer.h"
#import "S3ErrorParser.h"
+#import "S3DateUtil.h"
#import "NSString+S3.h"
#import "NSString+PathExtras.h"
+#import "NSString+URLEncoding.h"
#import "NSFileManager+MimeType.h"
#import "NSObject+Extensions.h"
@@ -24,14 +26,13 @@ @implementation S3UploadOperation
@synthesize errorMessage;
+
/*
* If we got a response body from PUT request then we handle it as an error and bail.
*/
-static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *data)
-{
- S3UploadOperation *op = (S3UploadOperation *)data;
-
- NSString *resp = [NSString stringWithCString:(char *)ptr];
+static size_t writeFunction(void *ptr, size_t size, size_t nmemb, S3UploadOperation *op)
+{
+ NSString *resp = [NSString stringWithUTF8String:(char *)ptr];
NSDictionary *err = [S3ErrorParser parseErrorDetails:resp];
@@ -58,17 +59,14 @@ - (void)setProtocolSpecificOptions
*
*/
- (void)setFileSpecificOptions:(FileTransfer *)file
-{
+{
// These act the same as username and password
NSString *accessKey = [upload username];
NSString *secretKey = [upload password];
- // Construct the date Amazon date format
- NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
- [dateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm:ss zzzz"];
- NSString *date = [dateFormatter stringFromDate:[NSDate date]];
+ NSString *date = [S3DateUtil dateStringForNow];
- NSString *resource = [NSString stringWithFormat:@"/%@", [[file remotePath] stringByRemovingTildePrefix]];
+ NSString *resource = [[NSString stringWithFormat:@"/%@", [[file remotePath] stringByRemovingTildePrefix]] encodedURLString];
// Get the content type of the file we're uploading
NSString *contentType = [NSFileManager mimeTypeForFileAtPath:[file localPath]];
@@ -140,7 +138,7 @@ - (NSString *)urlForTransfer:(FileTransfer *)file
NSString *path = [[NSString stringWithFormat:@"%@:%d", [upload hostname], [upload port]] stringByAppendingPathComponent:filePath];
- NSString *url = [NSString stringWithFormat:@"%@://%@", [upload protocolPrefix], path];
+ NSString *url = [NSString stringWithFormat:@"%@://%@", [upload protocolPrefix], [path encodedURLString]];
return url;
}
View
2 operations/SSHUploadOperation.m
@@ -75,8 +75,6 @@ - (void)setFileSpecificOptions:(FileTransfer *)file
{
const char *removeTempFile = [[NSString stringWithFormat:@"RM \"%@\"", [[file remotePath] stringByRemovingTildePrefix]] UTF8String];
- printf("\nQuote Command is %s\n", removeTempFile);
-
[file appendPostQuote:removeTempFile];
}
View
8 operations/UploadOperation.h
@@ -22,6 +22,10 @@
static int handleUploadProgress(UploadOperation *operation, int connected, double dltotal, double dlnow, double ultotal, double ulnow);
+-(BOOL)dependentOperationCancelled;
+
+- (void)calculateUploadProgress:(double)ulnow total:(double)ultotal;
+
- (void)setProtocolSpecificOptions;
- (void)setFileSpecificOptions:(FileTransfer *)file;
@@ -34,7 +38,9 @@ static int handleUploadProgress(UploadOperation *operation, int connected, doubl
- (void)handleUploadFailed:(CURLcode)result;
-- (void)performUploadDelegateSelector:(SEL)aSelector withArgument:(id)arg;
+- (void)notifyDelegateOfFailure;
+
+- (void)performDelegateSelector:(SEL)aSelector withArgument:(id)arg;
- (NSString *)credentials;
View
143 operations/UploadOperation.m
@@ -10,6 +10,7 @@
#import "FileTransfer.h"
#import "Upload.h"
#import "UploadDelegate.h"
+#import "ConnectionDelegate.h"
#import "TransferStatus.h"
#import "NSString+PathExtras.h"
@@ -25,6 +26,13 @@ @implementation UploadOperation
*/
- (void)main
{
+ if ([self isCancelled] || [self dependentOperationCancelled]) {
+
+ [self notifyDelegateOfFailure];
+
+ return;
+ }
+
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Set options for uploading
@@ -111,15 +119,34 @@ - (NSString *)urlForTransfer:(FileTransfer *)file
{
NSString *filePath = [[file remotePath] stringByAddingTildePrefix];
- NSString *path = [[NSString stringWithFormat:@"%@:%d", [upload hostname], [upload port]]
- stringByAppendingPathPreservingAbsolutePaths:filePath];
+ NSString *path = [[NSString stringWithFormat:@"%@:%d", [upload hostname], [upload port]]
+ stringByAppendingPathPreservingAbsolutePaths:filePath];
NSString *url = [NSString stringWithFormat:@"%@://%@", [upload protocolPrefix], path];
return url;
}
+
+
+-(BOOL)dependentOperationCancelled
+{
+ BOOL answer = NO;
+
+ for (int i = 0; i < [[self dependencies] count]; i++) {
+ NSOperation *dependency = [[self dependencies] objectAtIndex:i];
+
+ if ([dependency isCancelled]) {
+ answer = YES;
+ break;
+ }
+ }
+
+ return answer;
+}
+
+
- (void)setProtocolSpecificOptions
{
curl_easy_setopt(handle, CURLOPT_USERPWD, [[self credentials] UTF8String]);
@@ -140,27 +167,29 @@ - (void)setFileSpecificOptions:(FileTransfer *)file
}
+
/*
* Used to handle upload progress if the showProgress flag is set. Invoked by libcurl on progress updates to calculates the
* new upload progress and sets it on the upload.
*
* See http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTPROGRESSFUNCTION
*/
static int handleUploadProgress(UploadOperation *operation, int connected, double dltotal, double dlnow, double ultotal, double ulnow)
-{
+{
Upload *upload = [operation upload];
+ if ([upload connected] && !connected) return 0; // Reconnecting...
+
if (!connected)
- {
-
+ {
if ([upload status] != TRANSFER_STATUS_CONNECTING)
{
// Connecting ...
[upload setConnected:NO];
[upload setStatus:TRANSFER_STATUS_CONNECTING];
-
+
// Notify the delegate
- [operation performUploadDelegateSelector:@selector(uploadIsConnecting:) withArgument:nil];
+ [operation performDelegateSelector:@selector(curlIsConnecting:) withArgument:nil];
}
}
@@ -170,47 +199,66 @@ static int handleUploadProgress(UploadOperation *operation, int connected, doubl
{
// We have a connection.
[upload setConnected:YES];
- [upload setStatus:TRANSFER_STATUS_UPLOADING];
+ [upload setStatus:TRANSFER_STATUS_CONNECTED];
// Notify the delegate
- [operation performUploadDelegateSelector:@selector(uploadDidBegin:) withArgument:nil];
-
- // Start the BPS timer
- [operation startByteTimer];
+ [operation performDelegateSelector:@selector(curlDidConnect:) withArgument:nil];
}
- // Compute the current files bytes uploaded
- double currentBytesUploaded = [[upload currentTransfer] isEmptyDirectory] ? [[upload currentTransfer] totalBytes] : ulnow;
-
- // Compute the total bytes uploaded
- double totalBytesUploaded = [upload totalBytesUploaded] + (currentBytesUploaded - [[upload currentTransfer] totalBytesUploaded]);
-
- // Compute current files percentage complete
- double percentComplete = [[upload currentTransfer] isEmptyDirectory] ? 100 : (ulnow * 100 / ultotal);
-
- [[upload currentTransfer] setTotalBytesUploaded:currentBytesUploaded];
- [[upload currentTransfer] setPercentComplete:percentComplete];
-
- [upload setTotalBytesUploaded:totalBytesUploaded];
-
- // Compute the total percent complete of the entire transfer
- int progressNow = ([upload totalBytesUploaded] * 100 / [upload totalBytes]);
-
- if (progressNow >= [upload progress])
+ if ([upload connected] && [upload status] != TRANSFER_STATUS_UPLOADING && ulnow > 0)
{
- // Set the current progress
- [upload setProgress:progressNow];
-
+ [upload setStatus:TRANSFER_STATUS_UPLOADING];
+
// Notify the delegate
- [operation performUploadDelegateSelector:@selector(uploadDidProgress:toPercent:)
- withArgument:[NSNumber numberWithInt:progressNow]];
+ [operation performDelegateSelector:@selector(uploadDidBegin:) withArgument:nil];
+
+ // Start the BPS timer
+ [operation startByteTimer];
}
+
+ [operation calculateUploadProgress:ulnow total:ultotal];
}
return ([upload cancelled] || [upload status] == TRANSFER_STATUS_FAILED);
}
+
+
+- (void)calculateUploadProgress:(double)ulnow total:(double)ultotal
+{
+ // Compute the current files bytes uploaded
+ double currentBytesUploaded = [[upload currentTransfer] isEmptyDirectory] ? [[upload currentTransfer] totalBytes] : ulnow;
+
+ // Compute the total bytes uploaded
+ double totalBytesUploaded = [upload totalBytesUploaded] + (currentBytesUploaded - [[upload currentTransfer] totalBytesUploaded]);
+
+ // Compute current files percentage complete
+ double percentComplete = [[upload currentTransfer] isEmptyDirectory] ? 100 : (ulnow * 100 / ultotal);
+
+ [[upload currentTransfer] setTotalBytesUploaded:currentBytesUploaded];
+ [[upload currentTransfer] setPercentComplete:percentComplete];
+
+ [upload setTotalBytesUploaded:totalBytesUploaded];
+
+ // Compute the total percent complete of the entire transfer
+ int progressNow = ([upload totalBytesUploaded] * 100 / [upload totalBytes]);
+
+ if (progressNow >= [upload progress])
+ {
+ // Set the current progress
+ [upload setProgress:progressNow];
+
+ // Notify the delegate
+ [self performDelegateSelector:@selector(uploadDidProgress:toPercent:)
+ withArgument:[NSNumber numberWithInt:progressNow]];
+ }
+
+}
+
+
+
+
/*
* Called when the upload loop execution has finished. Updates the state of the upload and notifies delegates.
*
@@ -223,17 +271,17 @@ - (void)handleUploadResult:(CURLcode)result
[upload setStatus:TRANSFER_STATUS_COMPLETE];
// Notify Delegates
- [self performUploadDelegateSelector:@selector(uploadDidFinish:)
- withArgument:nil];
+ [self performDelegateSelector:@selector(uploadDidFinish:)
+ withArgument:nil];
}
else if ([upload cancelled])
{
// Cancelled!
[upload setStatus:TRANSFER_STATUS_CANCELLED];
// Notify Delegate
- [self performUploadDelegateSelector:@selector(uploadWasCancelled:)
- withArgument:nil];
+ [self performDelegateSelector:@selector(uploadWasCancelled:)
+ withArgument:nil];
}
else
{
@@ -266,16 +314,23 @@ - (void)handleUploadFailed:(CURLcode)result
}
[upload setStatus:status];
-
- NSString *message = [self getFailureDetailsForStatus:result withObject:upload];
+ [upload setStatusMessage:[self getFailureDetailsForStatus:result withObject:upload]];
+ [self notifyDelegateOfFailure];
+}
+
+
+
+- (void)notifyDelegateOfFailure
+{
if (delegate && [delegate respondsToSelector:@selector(uploadDidFail:message:)])
{
- [[delegate invokeOnMainThread] uploadDidFail:upload message:message];
- }
+ [[delegate invokeOnMainThread] uploadDidFail:upload message:[upload statusMessage]];
+ }
}
+
/*
* Takes in a list of files and directories to be uploaded, and returns an array of FileTransfers.
* Gets the job done, but the code is a mess and I'm pretty sure it's leaking.
@@ -395,7 +450,7 @@ - (NSArray *)enumerateFilesToUpload:(NSArray *)files prefix:(NSString *)prefix t
* Calls an UploadDelegate method on the main thread.
*
*/
-- (void)performUploadDelegateSelector:(SEL)aSelector withArgument:(id)arg
+- (void)performDelegateSelector:(SEL)aSelector withArgument:(id)arg
{
if (delegate && [delegate respondsToSelector:aSelector])
{
View
26 protocol/delegate/ConnectionDelegate.h
@@ -0,0 +1,26 @@
+//
+// ConnectionDelegate.h
+// objective-curl
+//
+// Copyright 2010 Nick Jensen <http://goto11.net>
+//
+
+
+@class RemoteObject;
+
+
+@protocol ConnectionDelegate
+
+/*
+ * Called when curl starts the connection process.
+ */
+- (void)curlIsConnecting:(RemoteObject *)record;
+
+
+/*
+ * Called when curl successfully connects.
+ */
+- (void)curlDidConnect:(RemoteObject *)record;
+
+
+@end
View
6 protocol/delegate/UploadDelegate.h
@@ -13,12 +13,6 @@
/*
- * Called when the upload starts the connection process.
- */
-- (void)uploadIsConnecting:(Upload *)record;
-
-
-/*
* Called when the upload has started.
*/
- (void)uploadDidBegin:(Upload *)record;
View
15 util/S3DateUtil.h
@@ -0,0 +1,15 @@
+//
+// S3DateUtil.h
+// objective-curl
+//
+// Copyright 2010 Nick Jensen <http://goto11.net>
+//
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface S3DateUtil : NSObject
+
++ (NSString *)dateStringForNow;
+
+@end
View
24 util/S3DateUtil.m
@@ -0,0 +1,24 @@
+//
+// S3DateUtil.m
+// objective-curl
+//
+// Copyright 2010 Nick Jensen <http://goto11.net>
+//
+
+#import "S3DateUtil.h"
+
+
+@implementation S3DateUtil
+
++ (NSString *)dateStringForNow
+{
+ // Construct a date string in the format that S3 expects
+
+ NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
+
+ [dateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm:ss zzzz"];
+
+ return [dateFormatter stringFromDate:[NSDate date]];
+}
+
+@end
View
16 util/S3ErrorParser.m
@@ -27,14 +27,17 @@ + (NSDictionary *)parseErrorDetails:(NSString *)resp
options:NSXMLDocumentTidyXML
error:&err];
-
-
if (!err) {
NSXMLNode *msgNode, *codeNode = nil;
- msgNode = [[xml nodesForXPath:@"./Error/Message" error:nil] objectAtIndex:0];
-
- codeNode = [[xml nodesForXPath:@"./Error/Code" error:nil] objectAtIndex:0];
+ if ([xml nodesForXPath:@"./Error/Code" error:&err] && !err) {
+ codeNode = [[xml nodesForXPath:@"./Error/Code" error:nil] objectAtIndex:0];
+ msgNode = [[xml nodesForXPath:@"./Error/Message" error:nil] objectAtIndex:0];
+ }
+ else
+ {
+ return nil;
+ }
s3ErrorCode = [codeNode stringValue];
s3ErrorMessage = [msgNode stringValue];
@@ -56,7 +59,8 @@ + (NSDictionary *)parseErrorDetails:(NSString *)resp
+ (int)transferStatusForErrorCode:(NSString *)code
{
if ([code isEqualToString:(NSString *)S3SignatureDoesNotMatch] ||
- [code isEqualToString:(NSString *)S3InvalidAccessKeyId]) {
+ [code isEqualToString:(NSString *)S3InvalidAccessKeyId] ||
+ [code isEqualToString:(NSString *)S3AccessDenied]) {
return TRANSFER_STATUS_LOGIN_DENIED;
}

0 comments on commit 8b1d24d

Please sign in to comment.