diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cacc671 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +DerivedData/FTPKit/Build +DerivedData +FTPKit.xcodeproj/project.xcworkspace/xcuserdata +FTPKit.xcodeproj/xcuserdata/ssb.xcuserdatad diff --git a/FTPKit Tests/FTPKit Tests-Info.plist b/FTPKit Tests/FTPKit Tests-Info.plist index 53c8404..169b6f7 100644 --- a/FTPKit Tests/FTPKit Tests-Info.plist +++ b/FTPKit Tests/FTPKit Tests-Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.upstart-illustration-llc.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType diff --git a/FTPKit.xcodeproj/project.pbxproj b/FTPKit.xcodeproj/project.pbxproj index a6ddf87..22f5c89 100644 --- a/FTPKit.xcodeproj/project.pbxproj +++ b/FTPKit.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 072A829B18CC2450001E640B /* NSError+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 072A829818CC2450001E640B /* NSError+Additions.m */; }; - 072A829C18CC2450001E640B /* NSString+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 072A829A18CC2450001E640B /* NSString+Additions.m */; }; 074A7B5218CAC98F00A03068 /* libFTPKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F27BA1CE1802FE7E00584A9E /* libFTPKit.a */; }; 076BD40018CD18CC00517DEE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F27BA1D11802FE7E00584A9E /* Foundation.framework */; }; 076BD40518CD198D00517DEE /* FTPCredentials.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = F27BA2051802FF1800584A9E /* FTPCredentials.h */; }; @@ -22,6 +21,38 @@ 07F23C4D18CA4C43002BDF93 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 07F23C4C18CA4C43002BDF93 /* UIKit.framework */; }; 07F23C5318CA4C43002BDF93 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 07F23C5118CA4C43002BDF93 /* InfoPlist.strings */; }; 07F23C5518CA4C43002BDF93 /* FTPKit_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 07F23C5418CA4C43002BDF93 /* FTPKit_Tests.m */; }; + 54DBC7C11FD949AC004BA12D /* FTPKitMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 54DBC7BF1FD949AC004BA12D /* FTPKitMac.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54DBC7DE1FD94B44004BA12D /* FTPKit.h in Headers */ = {isa = PBXBuildFile; fileRef = F27BA1D61802FE7E00584A9E /* FTPKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54DBC7DF1FD94B44004BA12D /* FTPClient.h in Headers */ = {isa = PBXBuildFile; fileRef = F27BA1F71802FF1800584A9E /* FTPClient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54DBC7E01FD94B44004BA12D /* FTPCredentials.h in Headers */ = {isa = PBXBuildFile; fileRef = F27BA2051802FF1800584A9E /* FTPCredentials.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54DBC7E11FD94B44004BA12D /* FTPHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = F27BA1FB1802FF1800584A9E /* FTPHandle.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54DBC7E21FD94CA5004BA12D /* FTPClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F27BA1F81802FF1800584A9E /* FTPClient.m */; }; + 54DBC7E31FD94CA8004BA12D /* FTPCredentials.m in Sources */ = {isa = PBXBuildFile; fileRef = F27BA2061802FF1800584A9E /* FTPCredentials.m */; }; + 54DBC7E41FD94CAC004BA12D /* FTPHandle.m in Sources */ = {isa = PBXBuildFile; fileRef = F27BA1FC1802FF1800584A9E /* FTPHandle.m */; }; + 54DBC7E51FD94CB4004BA12D /* NSError+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 072A829818CC2450001E640B /* NSError+Additions.m */; }; + 54DBC7E71FD94CBE004BA12D /* ftplib.c in Sources */ = {isa = PBXBuildFile; fileRef = 076BD46118CFB76E00517DEE /* ftplib.c */; }; + 54DBC8281FD977AD004BA12D /* TVFTPKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 54DBC8261FD977AD004BA12D /* TVFTPKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54DBC82C1FD977BD004BA12D /* FTPClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F27BA1F81802FF1800584A9E /* FTPClient.m */; }; + 54DBC82D1FD977BD004BA12D /* FTPCredentials.m in Sources */ = {isa = PBXBuildFile; fileRef = F27BA2061802FF1800584A9E /* FTPCredentials.m */; }; + 54DBC82E1FD977BD004BA12D /* FTPHandle.m in Sources */ = {isa = PBXBuildFile; fileRef = F27BA1FC1802FF1800584A9E /* FTPHandle.m */; }; + 54DBC82F1FD977CC004BA12D /* NSError+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 072A829818CC2450001E640B /* NSError+Additions.m */; }; + 54DBC8311FD977CC004BA12D /* ftplib.c in Sources */ = {isa = PBXBuildFile; fileRef = 076BD46118CFB76E00517DEE /* ftplib.c */; }; + 54DBC8321FD9798D004BA12D /* FTPKit.h in Headers */ = {isa = PBXBuildFile; fileRef = F27BA1D61802FE7E00584A9E /* FTPKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54DBC8331FD9798D004BA12D /* FTPClient.h in Headers */ = {isa = PBXBuildFile; fileRef = F27BA1F71802FF1800584A9E /* FTPClient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54DBC8341FD9798D004BA12D /* FTPCredentials.h in Headers */ = {isa = PBXBuildFile; fileRef = F27BA2051802FF1800584A9E /* FTPCredentials.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54DBC8351FD9798D004BA12D /* FTPHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = F27BA1FB1802FF1800584A9E /* FTPHandle.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54F7CC791FF6FC7200185880 /* MobileFTPKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 54F7CC771FF6FC7200185880 /* MobileFTPKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54F7CC7D1FF6FCC700185880 /* ftplib.c in Sources */ = {isa = PBXBuildFile; fileRef = 076BD46118CFB76E00517DEE /* ftplib.c */; }; + 54F7CC7E1FF6FCD200185880 /* NSError+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 072A829818CC2450001E640B /* NSError+Additions.m */; }; + 54F7CC7F1FF6FCE100185880 /* FTPClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F27BA1F81802FF1800584A9E /* FTPClient.m */; }; + 54F7CC801FF6FCE100185880 /* FTPCredentials.m in Sources */ = {isa = PBXBuildFile; fileRef = F27BA2061802FF1800584A9E /* FTPCredentials.m */; }; + 54F7CC811FF6FCE100185880 /* FTPHandle.m in Sources */ = {isa = PBXBuildFile; fileRef = F27BA1FC1802FF1800584A9E /* FTPHandle.m */; }; + 54F7CC821FF6FCF900185880 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F27BA1D11802FE7E00584A9E /* Foundation.framework */; }; + 54F7CC831FF6FD2300185880 /* FTPKit.h in Headers */ = {isa = PBXBuildFile; fileRef = F27BA1D61802FE7E00584A9E /* FTPKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54F7CC841FF6FD2700185880 /* FTPClient.h in Headers */ = {isa = PBXBuildFile; fileRef = F27BA1F71802FF1800584A9E /* FTPClient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54F7CC851FF6FD2B00185880 /* FTPCredentials.h in Headers */ = {isa = PBXBuildFile; fileRef = F27BA2051802FF1800584A9E /* FTPCredentials.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54F7CC861FF6FD2F00185880 /* FTPHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = F27BA1FB1802FF1800584A9E /* FTPHandle.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54F7CC871FF6FD3800185880 /* ftplib.h in Headers */ = {isa = PBXBuildFile; fileRef = 076BD46218CFB76E00517DEE /* ftplib.h */; settings = {ATTRIBUTES = (Public, ); }; }; F27BA20B1802FF1800584A9E /* FTPClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F27BA1F81802FF1800584A9E /* FTPClient.m */; }; F27BA20D1802FF1800584A9E /* FTPHandle.m in Sources */ = {isa = PBXBuildFile; fileRef = F27BA1FC1802FF1800584A9E /* FTPHandle.m */; }; F27BA2121802FF1800584A9E /* FTPCredentials.m in Sources */ = {isa = PBXBuildFile; fileRef = F27BA2061802FF1800584A9E /* FTPCredentials.m */; }; @@ -69,6 +100,15 @@ 07F23C5218CA4C43002BDF93 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 07F23C5418CA4C43002BDF93 /* FTPKit_Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FTPKit_Tests.m; sourceTree = ""; }; 07F23C5618CA4C43002BDF93 /* FTPKit Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FTPKit Tests-Prefix.pch"; sourceTree = ""; }; + 54DBC7BD1FD949AC004BA12D /* FTPKitMac.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FTPKitMac.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 54DBC7BF1FD949AC004BA12D /* FTPKitMac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FTPKitMac.h; sourceTree = ""; }; + 54DBC7C01FD949AC004BA12D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 54DBC8241FD977AD004BA12D /* TVFTPKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TVFTPKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 54DBC8261FD977AD004BA12D /* TVFTPKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TVFTPKit.h; sourceTree = ""; }; + 54DBC8271FD977AD004BA12D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 54F7CC751FF6FC7200185880 /* MobileFTPKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MobileFTPKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 54F7CC771FF6FC7200185880 /* MobileFTPKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MobileFTPKit.h; sourceTree = ""; }; + 54F7CC781FF6FC7200185880 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; F27BA1CE1802FE7E00584A9E /* libFTPKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFTPKit.a; sourceTree = BUILT_PRODUCTS_DIR; }; F27BA1D11802FE7E00584A9E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; F27BA1D51802FE7E00584A9E /* FTPKit-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FTPKit-Prefix.pch"; sourceTree = ""; }; @@ -93,6 +133,28 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 54DBC7B91FD949AC004BA12D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 54DBC8201FD977AD004BA12D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 54F7CC711FF6FC7200185880 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 54F7CC821FF6FCF900185880 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; F27BA1CB1802FE7E00584A9E /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -159,11 +221,41 @@ name = "Supporting Files"; sourceTree = ""; }; + 54DBC7BE1FD949AC004BA12D /* FTPKitMac */ = { + isa = PBXGroup; + children = ( + 54DBC7BF1FD949AC004BA12D /* FTPKitMac.h */, + 54DBC7C01FD949AC004BA12D /* Info.plist */, + ); + path = FTPKitMac; + sourceTree = ""; + }; + 54DBC8251FD977AD004BA12D /* TVFTPKit */ = { + isa = PBXGroup; + children = ( + 54DBC8261FD977AD004BA12D /* TVFTPKit.h */, + 54DBC8271FD977AD004BA12D /* Info.plist */, + ); + path = TVFTPKit; + sourceTree = ""; + }; + 54F7CC761FF6FC7200185880 /* MobileFTPKit */ = { + isa = PBXGroup; + children = ( + 54F7CC771FF6FC7200185880 /* MobileFTPKit.h */, + 54F7CC781FF6FC7200185880 /* Info.plist */, + ); + path = MobileFTPKit; + sourceTree = ""; + }; F27BA1C51802FE7E00584A9E = { isa = PBXGroup; children = ( F27BA1D31802FE7E00584A9E /* FTPKit */, 07F23C4E18CA4C43002BDF93 /* FTPKit Tests */, + 54DBC7BE1FD949AC004BA12D /* FTPKitMac */, + 54DBC8251FD977AD004BA12D /* TVFTPKit */, + 54F7CC761FF6FC7200185880 /* MobileFTPKit */, F27BA1D01802FE7E00584A9E /* Frameworks */, F27BA1CF1802FE7E00584A9E /* Products */, ); @@ -174,6 +266,9 @@ children = ( F27BA1CE1802FE7E00584A9E /* libFTPKit.a */, 07F23C4818CA4C43002BDF93 /* FTPKit Tests.xctest */, + 54DBC7BD1FD949AC004BA12D /* FTPKitMac.framework */, + 54DBC8241FD977AD004BA12D /* TVFTPKit.framework */, + 54F7CC751FF6FC7200185880 /* MobileFTPKit.framework */, ); name = Products; sourceTree = ""; @@ -216,6 +311,46 @@ }; /* End PBXGroup section */ +/* Begin PBXHeadersBuildPhase section */ + 54DBC7BA1FD949AC004BA12D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 54DBC7DE1FD94B44004BA12D /* FTPKit.h in Headers */, + 54DBC7DF1FD94B44004BA12D /* FTPClient.h in Headers */, + 54DBC7E01FD94B44004BA12D /* FTPCredentials.h in Headers */, + 54DBC7C11FD949AC004BA12D /* FTPKitMac.h in Headers */, + 54DBC7E11FD94B44004BA12D /* FTPHandle.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 54DBC8211FD977AD004BA12D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 54DBC8281FD977AD004BA12D /* TVFTPKit.h in Headers */, + 54DBC8321FD9798D004BA12D /* FTPKit.h in Headers */, + 54DBC8331FD9798D004BA12D /* FTPClient.h in Headers */, + 54DBC8341FD9798D004BA12D /* FTPCredentials.h in Headers */, + 54DBC8351FD9798D004BA12D /* FTPHandle.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 54F7CC721FF6FC7200185880 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 54F7CC791FF6FC7200185880 /* MobileFTPKit.h in Headers */, + 54F7CC831FF6FD2300185880 /* FTPKit.h in Headers */, + 54F7CC841FF6FD2700185880 /* FTPClient.h in Headers */, + 54F7CC851FF6FD2B00185880 /* FTPCredentials.h in Headers */, + 54F7CC861FF6FD2F00185880 /* FTPHandle.h in Headers */, + 54F7CC871FF6FD3800185880 /* ftplib.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + /* Begin PBXNativeTarget section */ 07F23C4718CA4C43002BDF93 /* FTPKit Tests */ = { isa = PBXNativeTarget; @@ -235,6 +370,60 @@ productReference = 07F23C4818CA4C43002BDF93 /* FTPKit Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + 54DBC7BC1FD949AC004BA12D /* FTPKitMac */ = { + isa = PBXNativeTarget; + buildConfigurationList = 54DBC7C41FD949AC004BA12D /* Build configuration list for PBXNativeTarget "FTPKitMac" */; + buildPhases = ( + 54DBC7B81FD949AC004BA12D /* Sources */, + 54DBC7B91FD949AC004BA12D /* Frameworks */, + 54DBC7BA1FD949AC004BA12D /* Headers */, + 54DBC7BB1FD949AC004BA12D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = FTPKitMac; + productName = FTPKitMac; + productReference = 54DBC7BD1FD949AC004BA12D /* FTPKitMac.framework */; + productType = "com.apple.product-type.framework"; + }; + 54DBC8231FD977AD004BA12D /* TVFTPKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = 54DBC82B1FD977AD004BA12D /* Build configuration list for PBXNativeTarget "TVFTPKit" */; + buildPhases = ( + 54DBC81F1FD977AD004BA12D /* Sources */, + 54DBC8201FD977AD004BA12D /* Frameworks */, + 54DBC8211FD977AD004BA12D /* Headers */, + 54DBC8221FD977AD004BA12D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = TVFTPKit; + productName = TVFTPKit; + productReference = 54DBC8241FD977AD004BA12D /* TVFTPKit.framework */; + productType = "com.apple.product-type.framework"; + }; + 54F7CC741FF6FC7200185880 /* MobileFTPKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = 54F7CC7C1FF6FC7200185880 /* Build configuration list for PBXNativeTarget "MobileFTPKit" */; + buildPhases = ( + 54F7CC701FF6FC7200185880 /* Sources */, + 54F7CC711FF6FC7200185880 /* Frameworks */, + 54F7CC721FF6FC7200185880 /* Headers */, + 54F7CC731FF6FC7200185880 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MobileFTPKit; + productName = MobileFTPKit; + productReference = 54F7CC751FF6FC7200185880 /* MobileFTPKit.framework */; + productType = "com.apple.product-type.framework"; + }; F27BA1CD1802FE7E00584A9E /* FTPKit */ = { isa = PBXNativeTarget; buildConfigurationList = F27BA1F11802FE7E00584A9E /* Build configuration list for PBXNativeTarget "FTPKit" */; @@ -258,12 +447,26 @@ F27BA1C61802FE7E00584A9E /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0510; + LastUpgradeCheck = 0940; ORGANIZATIONNAME = "Upstart Illustration LLC"; TargetAttributes = { 07F23C4718CA4C43002BDF93 = { TestTargetID = F27BA1CD1802FE7E00584A9E; }; + 54DBC7BC1FD949AC004BA12D = { + CreatedOnToolsVersion = 9.2; + DevelopmentTeam = B75KV4ZCCF; + ProvisioningStyle = Automatic; + }; + 54DBC8231FD977AD004BA12D = { + CreatedOnToolsVersion = 9.2; + DevelopmentTeam = CL94MF5PCP; + ProvisioningStyle = Automatic; + }; + 54F7CC741FF6FC7200185880 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Automatic; + }; }; }; buildConfigurationList = F27BA1C91802FE7E00584A9E /* Build configuration list for PBXProject "FTPKit" */; @@ -280,6 +483,9 @@ targets = ( F27BA1CD1802FE7E00584A9E /* FTPKit */, 07F23C4718CA4C43002BDF93 /* FTPKit Tests */, + 54DBC7BC1FD949AC004BA12D /* FTPKitMac */, + 54DBC8231FD977AD004BA12D /* TVFTPKit */, + 54F7CC741FF6FC7200185880 /* MobileFTPKit */, ); }; /* End PBXProject section */ @@ -293,6 +499,27 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 54DBC7BB1FD949AC004BA12D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 54DBC8221FD977AD004BA12D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 54F7CC731FF6FC7200185880 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -304,6 +531,42 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 54DBC7B81FD949AC004BA12D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 54DBC7E71FD94CBE004BA12D /* ftplib.c in Sources */, + 54DBC7E21FD94CA5004BA12D /* FTPClient.m in Sources */, + 54DBC7E41FD94CAC004BA12D /* FTPHandle.m in Sources */, + 54DBC7E31FD94CA8004BA12D /* FTPCredentials.m in Sources */, + 54DBC7E51FD94CB4004BA12D /* NSError+Additions.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 54DBC81F1FD977AD004BA12D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 54DBC8311FD977CC004BA12D /* ftplib.c in Sources */, + 54DBC82C1FD977BD004BA12D /* FTPClient.m in Sources */, + 54DBC82E1FD977BD004BA12D /* FTPHandle.m in Sources */, + 54DBC82D1FD977BD004BA12D /* FTPCredentials.m in Sources */, + 54DBC82F1FD977CC004BA12D /* NSError+Additions.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 54F7CC701FF6FC7200185880 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 54F7CC7D1FF6FCC700185880 /* ftplib.c in Sources */, + 54F7CC7F1FF6FCE100185880 /* FTPClient.m in Sources */, + 54F7CC7E1FF6FCD200185880 /* NSError+Additions.m in Sources */, + 54F7CC801FF6FCE100185880 /* FTPCredentials.m in Sources */, + 54F7CC811FF6FCE100185880 /* FTPHandle.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; F27BA1CA1802FE7E00584A9E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -312,7 +575,6 @@ F27BA2121802FF1800584A9E /* FTPCredentials.m in Sources */, F27BA20D1802FF1800584A9E /* FTPHandle.m in Sources */, F27BA20B1802FF1800584A9E /* FTPClient.m in Sources */, - 072A829C18CC2450001E640B /* NSString+Additions.m in Sources */, 072A829B18CC2450001E640B /* NSError+Additions.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -355,6 +617,7 @@ "$(inherited)", ); INFOPLIST_FILE = "FTPKit Tests/FTPKit Tests-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.upstart-illustration-llc.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = xctest; }; @@ -372,11 +635,262 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "FTPKit Tests/FTPKit Tests-Prefix.pch"; INFOPLIST_FILE = "FTPKit Tests/FTPKit Tests-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.upstart-illustration-llc.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = xctest; }; name = Release; }; + 54DBC7C21FD949AC004BA12D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = B75KV4ZCCF; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + FRAMEWORK_VERSION = A; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREFIX_HEADER = "FTPKit/FTPKit-Prefix.pch"; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = FTPKitMac/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "de.schmidt-bilkenroth.FTPKitMac"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 54DBC7C31FD949AC004BA12D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = B75KV4ZCCF; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FRAMEWORK_VERSION = A; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREFIX_HEADER = "FTPKit/FTPKit-Prefix.pch"; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = FTPKitMac/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "de.schmidt-bilkenroth.FTPKitMac"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 54DBC8291FD977AD004BA12D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = CL94MF5PCP; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_BITCODE = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_PREFIX_HEADER = "FTPKit/FTPKit-Prefix.pch"; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = TVFTPKit/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "de.schmidt-bilkenroth.TVFTPKit"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 54DBC82A1FD977AD004BA12D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = CL94MF5PCP; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_BITCODE = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_PREFIX_HEADER = "FTPKit/FTPKit-Prefix.pch"; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = TVFTPKit/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "de.schmidt-bilkenroth.TVFTPKit"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 54F7CC7A1FF6FC7200185880 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_PREFIX_HEADER = "FTPKit/FTPKit-Prefix.pch"; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = MobileFTPKit/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "de.schmidt-bilkenroth.MobileFTPKit"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 54F7CC7B1FF6FC7200185880 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_PREFIX_HEADER = "FTPKit/FTPKit-Prefix.pch"; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = MobileFTPKit/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "de.schmidt-bilkenroth.MobileFTPKit"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; F27BA1EF1802FE7E00584A9E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -385,17 +899,31 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = NO; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -408,7 +936,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( "-ObjC", @@ -426,24 +954,37 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = NO; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; OTHER_LDFLAGS = ( "-ObjC", "-all_load", @@ -468,7 +1009,7 @@ LIBRARY_SEARCH_PATHS = "$(inherited)"; LINK_WITH_STANDARD_LIBRARIES = YES; MACH_O_TYPE = staticlib; - ONLY_ACTIVE_ARCH = YES; + ONLY_ACTIVE_ARCH = NO; OTHER_LDFLAGS = "-ObjC"; PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include; PRODUCT_NAME = FTPKit; @@ -477,6 +1018,7 @@ SKIP_INSTALL = YES; STRIP_STYLE = debugging; TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = "arm64 armv7 armv7s"; WRAPPER_EXTENSION = ""; }; name = Debug; @@ -506,6 +1048,7 @@ SKIP_INSTALL = YES; STRIP_STYLE = debugging; TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = "arm64 armv7 armv7s"; WRAPPER_EXTENSION = ""; }; name = Release; @@ -522,6 +1065,33 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 54DBC7C41FD949AC004BA12D /* Build configuration list for PBXNativeTarget "FTPKitMac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 54DBC7C21FD949AC004BA12D /* Debug */, + 54DBC7C31FD949AC004BA12D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 54DBC82B1FD977AD004BA12D /* Build configuration list for PBXNativeTarget "TVFTPKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 54DBC8291FD977AD004BA12D /* Debug */, + 54DBC82A1FD977AD004BA12D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 54F7CC7C1FF6FC7200185880 /* Build configuration list for PBXNativeTarget "MobileFTPKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 54F7CC7A1FF6FC7200185880 /* Debug */, + 54F7CC7B1FF6FC7200185880 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; F27BA1C91802FE7E00584A9E /* Build configuration list for PBXProject "FTPKit" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/FTPKit/Categories/NSError+Additions.m b/FTPKit/Categories/NSError+Additions.m index 27166f2..622bf8e 100644 --- a/FTPKit/Categories/NSError+Additions.m +++ b/FTPKit/Categories/NSError+Additions.m @@ -7,127 +7,135 @@ @implementation NSError (NSError_FTPKitAdditions) + (NSString *)FTPKitErrorMessageFromCode:(int)errorCode { - // http://en.wikipedia.org/wiki/List_of_FTP_server_return_codes - NSString *message = NSLocalizedString(@"Undefined error has occurred.", @""); - switch (errorCode) { - case 331: - message = NSLocalizedString(@"User name okay, need password.", @""); - break; - case 332: - message = NSLocalizedString(@"Need account for login.", @""); - break; - case 350: - message = NSLocalizedString(@"Requested file action pending further information.", @""); - break; - case 421: - message = NSLocalizedString(@"Service not available, closing control connection.", @""); - break; - case 425: - message = NSLocalizedString(@"Can't open data connection.", @""); - break; - case 426: - message = NSLocalizedString(@"Connection closed, transfer aborted.", @""); - break; - case 430: - message = NSLocalizedString(@"Invalid username or password.", @""); - break; - case 450: - message = NSLocalizedString(@"Requested file action not taken. File unavailable (e.g., file busy).", @""); - break; - case 451: - message = NSLocalizedString(@"Requested action aborted, local error in processing.", @""); - break; - case 452: - message = NSLocalizedString(@"Requested action not taken. Insufficient storage space in system.", @""); - break; - case 500: - message = NSLocalizedString(@"Syntax error, command unrecognized. This may include errors such as command line too long.", @""); - break; - case 501: - message = NSLocalizedString(@"Syntax error in parameters or arguments.", @""); - break; - case 502: - message = NSLocalizedString(@"Command not implemented.", @""); - break; - case 503: - message = NSLocalizedString(@"Bad sequence of commands.", @""); - break; - case 504: - message = NSLocalizedString(@"Command not implemented for that parameter.", @""); - break; - case 530: - message = NSLocalizedString(@"User not logged in.", @""); - break; - case 532: - message = NSLocalizedString(@"Need account for storing files.", @""); - break; - case 550: - message = NSLocalizedString(@"Requested action not taken. File unavailable (e.g., file not found, no access).", @""); - break; - case 551: - message = NSLocalizedString(@"Requested action aborted. Page type unknown.", @""); - break; - case 552: - message = NSLocalizedString(@"Requested file action aborted, storage allocation exceeded.", @""); - break; - case 553: - message = NSLocalizedString(@"Requested action not taken. File name not allowed.", @""); - break; - case 600: - message = NSLocalizedString(@"Replies regarding confidentiality and integrity.", @""); - break; - case 631: - message = NSLocalizedString(@"Integrity protected reply.", @""); - break; - case 632: - message = NSLocalizedString(@"Confidentiality and integrity protected reply.", @""); - break; - case 633: - message = NSLocalizedString(@"Confidentiality protected reply.", @""); - break; - // 1000 Series Common Winsock Error Codes - case 10054: - message = NSLocalizedString(@"Connection reset by peer. The connection was forcibly closed by the remote host.", @""); - break; - case 10060: - message = NSLocalizedString(@"Cannot connect to remote server.", @""); - break; - case 10061: - message = NSLocalizedString(@"Cannot connect to remote server. The connection is actively refused by the server.", @""); - break; - case 10066: - message = NSLocalizedString(@"Directory not empty.", @""); - break; - case 10068: - message = NSLocalizedString(@"Too many users, server is full.", @""); - break; - default: - break; - } - return message; + // http://en.wikipedia.org/wiki/List_of_FTP_server_return_codes + NSString *message = NSLocalizedString(@"Undefined error has occurred.", @""); + switch (errorCode) { + case 331: + message = NSLocalizedString(@"User name okay, need password.", @""); + break; + case 332: + message = NSLocalizedString(@"Need account for login.", @""); + break; + case 350: + message = NSLocalizedString(@"Requested file action pending further information.", @""); + break; + case 421: + message = NSLocalizedString(@"Service not available, closing control connection.", @""); + break; + case 425: + message = NSLocalizedString(@"Can't open data connection.", @""); + break; + case 426: + message = NSLocalizedString(@"Connection closed, transfer aborted.", @""); + break; + case 430: + message = NSLocalizedString(@"Invalid username or password.", @""); + break; + case 450: + message = NSLocalizedString(@"Requested file action not taken. File unavailable (e.g., file busy).", @""); + break; + case 451: + message = NSLocalizedString(@"Requested action aborted, local error in processing.", @""); + break; + case 452: + message = NSLocalizedString(@"Requested action not taken. Insufficient storage space in system.", @""); + break; + case 500: + message = NSLocalizedString(@"Syntax error, command unrecognized. This may include errors such as command line too long.", @""); + break; + case 501: + message = NSLocalizedString(@"Syntax error in parameters or arguments.", @""); + break; + case 502: + message = NSLocalizedString(@"Command not implemented.", @""); + break; + case 503: + message = NSLocalizedString(@"Bad sequence of commands.", @""); + break; + case 504: + message = NSLocalizedString(@"Command not implemented for that parameter.", @""); + break; + case 530: + message = NSLocalizedString(@"User not logged in.", @""); + break; + case 532: + message = NSLocalizedString(@"Need account for storing files.", @""); + break; + case 550: + message = NSLocalizedString(@"Requested action not taken. File unavailable (e.g., file not found, no access).", @""); + break; + case 551: + message = NSLocalizedString(@"Requested action aborted. Page type unknown.", @""); + break; + case 552: + message = NSLocalizedString(@"Requested file action aborted, storage allocation exceeded.", @""); + break; + case 553: + message = NSLocalizedString(@"Requested action not taken. File name not allowed.", @""); + break; + case 600: + message = NSLocalizedString(@"Replies regarding confidentiality and integrity.", @""); + break; + case 631: + message = NSLocalizedString(@"Integrity protected reply.", @""); + break; + case 632: + message = NSLocalizedString(@"Confidentiality and integrity protected reply.", @""); + break; + case 633: + message = NSLocalizedString(@"Confidentiality protected reply.", @""); + break; + // 1000 Series Common Winsock Error Codes + case 10054: + message = NSLocalizedString(@"Connection reset by peer. The connection was forcibly closed by the remote host.", @""); + break; + case 10060: + message = NSLocalizedString(@"Cannot connect to remote server.", @""); + break; + case 10061: + message = NSLocalizedString(@"Cannot connect to remote server. The connection is actively refused by the server.", @""); + break; + case 10066: + message = NSLocalizedString(@"Directory not empty.", @""); + break; + case 10068: + message = NSLocalizedString(@"Too many users, server is full.", @""); + break; + default: + break; + } + return message; } + (NSError *)FTPKitErrorWithCode:(int)errorCode { - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSError FTPKitErrorMessageFromCode:errorCode] - forKey:NSLocalizedDescriptionKey]; - return [[NSError alloc] initWithDomain:FTPErrorDomain code:errorCode userInfo:userInfo]; + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSError FTPKitErrorMessageFromCode:errorCode] + forKey:NSLocalizedDescriptionKey]; + return [[NSError alloc] initWithDomain:FTPErrorDomain code:errorCode userInfo:userInfo]; } + + (NSError *)FTPKitErrorWithResponse:(NSString *)response { - // Extract the code and message from the reponse message. - // Ex: '500 Server error' - NSMutableArray *components = [[response componentsSeparatedByString:@" "] mutableCopy]; - NSInteger code = 500; - if ([components[0] isIntegerValue]) { - code = [components[0] integerValue]; - [components removeObjectAtIndex:0]; - } - NSString *message = [components componentsJoinedByString:@" "]; - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:message - forKey:NSLocalizedDescriptionKey]; - return [[NSError alloc] initWithDomain:FTPErrorDomain code:code userInfo:userInfo]; + // Extract the code and message from the reponse message. + // Ex: '500 Server error' + NSMutableArray *components = [[response componentsSeparatedByString:@" "] mutableCopy]; + NSInteger code = 500; + BOOL isIntegerValue = NO; + + NSScanner *scanner = [NSScanner scannerWithString:components[0]]; + if ([scanner scanInteger:NULL]) { + isIntegerValue = [scanner isAtEnd]; + } + + if ( isIntegerValue) { + code = [components[0] integerValue]; + [components removeObjectAtIndex:0]; + } + NSString *message = [components componentsJoinedByString:@" "]; + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:message + forKey:NSLocalizedDescriptionKey]; + return [[NSError alloc] initWithDomain:FTPErrorDomain code:code userInfo:userInfo]; } @end diff --git a/FTPKit/Categories/NSString+Additions.h b/FTPKit/Categories/NSString+Additions.h index 9d32243..3509ea0 100644 --- a/FTPKit/Categories/NSString+Additions.h +++ b/FTPKit/Categories/NSString+Additions.h @@ -20,6 +20,6 @@ - (NSString *)FTPKitURLEncodedString; - (NSString *)FTPKitURLDecodedString; -- (BOOL)isIntegerValue; +//- (BOOL)isIntegerValue; -@end \ No newline at end of file +@end diff --git a/FTPKit/Categories/NSString+Additions.m b/FTPKit/Categories/NSString+Additions.m index f30ed61..9d4e955 100644 --- a/FTPKit/Categories/NSString+Additions.m +++ b/FTPKit/Categories/NSString+Additions.m @@ -4,13 +4,15 @@ @implementation NSString (NSString_FTPKitAdditions) + (NSString *)FTPKitURLEncodeString:(NSString *)unescaped { - NSString *result = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(NULL, (__bridge CFStringRef)unescaped, NULL, CFSTR("!*'();:@&=+$,?%#[]\" ") /* Removed '/' */, kCFStringEncodingUTF8); +// NSString *result = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(NULL, (__bridge CFStringRef)unescaped, NULL, CFSTR("!*'();:@&=+$,?%#[]\" ") /* Removed '/' */, kCFStringEncodingUTF8); + NSString *result = [unescaped stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]; return result; } + (NSString *)FTPKitURLDecodeString:(NSString *)string { - NSString *result = (__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (__bridge CFStringRef)string, CFSTR(""), kCFStringEncodingUTF8); +// NSString *result = (__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (__bridge CFStringRef)string, CFSTR(""), kCFStringEncodingUTF8); + NSString *result = [string stringByRemovingPercentEncoding]; return result; } diff --git a/FTPKit/FTPClient.h b/FTPKit/FTPClient.h index a99779a..9fafcf7 100644 --- a/FTPKit/FTPClient.h +++ b/FTPKit/FTPClient.h @@ -33,7 +33,7 @@ /** Factory method to create FTPClient instance. - @param FTPLocation The location's credentials + @param credentials The location's credentials @return FTPClient */ + (instancetype)clientWithCredentials:(FTPCredentials *)credentials; @@ -52,7 +52,7 @@ /** Create an instance of FTPClient. - @param FTPLocation The location's credentials + @param credentials The location's credentials @return FTPClient */ - (instancetype)initWithCredentials:(FTPCredentials *)credentials; @@ -81,7 +81,7 @@ List directory contents at path. @param path Path to remote directory to list. - @param showHiddenItems Show hidden items in directory. + @param showHiddenFiles Show hidden items in directory. @return List of contents as FTPHandle objects. */ - (NSArray *)listContentsAtPath:(NSString *)path showHiddenFiles:(BOOL)showHiddenFiles; @@ -92,7 +92,7 @@ This adds the ability to perform the operation asynchronously. @param path Path to remote directory to list. - @param showHiddenItems Show hidden items in directory. + @param showHiddenFiles Show hidden items in directory. @param success Method called when process succeeds. Provides list of contents as FTPHandle objects. @param failure Method called when process fails. @@ -105,7 +105,7 @@ List directory contents at handle's location. @param handle Remote directory handle to list. - @param showHiddenItems Show hidden items in directory. + @param showHiddenFiles Show hidden items in directory. @return List of contents as FTPHandle objects. */ - (NSArray *)listContentsAtHandle:(FTPHandle *)handle showHiddenFiles:(BOOL)showHiddenFiles; @@ -115,7 +115,7 @@ This adds the ability to perform the operation asynchronously. - @param showHiddenItems Show hidden items in directory. + @param showHiddenFiles Show hidden items in directory. @param success Method called when process succeeds. Provides list of contents as FTPHandle objects. @param failure Method called when process fails. @@ -127,7 +127,7 @@ /** Download remote file path to local path. - @param fileName Full path of remote file to download. + @param remotePath Full path of remote file to download. @param localPath Local path to download file to. @param progress Calls after data has been received to remote server. Return NO to cancel the operation. @@ -141,7 +141,7 @@ This adds the ability to perform the operation asynchronously. - @param fileName Full path of remote file to download. + @param remotePath Full path of remote file to download. @param localPath Local path to download file to. @param progress Calls after data has been received to remote server. Return NO to cancel the operation. @@ -186,7 +186,7 @@ Upload file to specific directory on remote server. @param localPath Path of local file to upload. - @param toPath Remote path where file will be uploaded to. + @param remotePath Remote path where file will be uploaded to. @param progress Calls after data has been sent to remote server. Return NO to cancel the operation. @return YES on success. NO on failure. @@ -200,7 +200,7 @@ This adds the ability to perform the operation asynchronously. @param localPath Path of local file to upload. - @param toPath Remote path where file will be uploaded to. + @param remotePath Remote path where file will be uploaded to. @param progress Calls after data has been sent to remote server. Return NO to cancel the operation. @param success Method called when process succeeds. @@ -233,8 +233,7 @@ /** Create remote directory within the handle's location. - @param directoryName Name of directory to create on remote server. - @param remotePath Path to remote directory where file should be created. + @param handle Path to remote directory where file should be created. @return YES on success. NO on failure. */ - (BOOL)createDirectoryAtHandle:(FTPHandle *)handle; @@ -244,8 +243,7 @@ This adds the ability to perform the operation asynchronously. - @param directoryName Name of directory to create on remote server. - @param remotePath Path to remote directory where file should be created. + @param handle Path to remote directory where file should be created. @param success Method called when process succeeds. @param failure Method called when process fails. */ @@ -290,7 +288,6 @@ @param remotePath The path to the remote resource to delete. @param success Method called when process succeeds. @param failure Method called when process fails. - @return FTPRequest The request instance. */ - (void)deleteFileAtPath:(NSString *)remotePath success:(void (^)(void))success @@ -312,7 +309,6 @@ @param handle The remote handle to delete. @param success Method called when process succeeds. @param failure Method called when process fails. - @return FTPRequest The request instance. */ - (void)deleteHandle:(FTPHandle *)handle success:(void (^)(void))success @@ -484,4 +480,4 @@ */ - (NSString *)printWorkingDirectory; -@end \ No newline at end of file +@end diff --git a/FTPKit/FTPClient.m b/FTPKit/FTPClient.m index ea0eb21..b361954 100644 --- a/FTPKit/FTPClient.m +++ b/FTPKit/FTPClient.m @@ -24,7 +24,7 @@ - (netbuf *)connect; Send arbitrary command to the FTP server. @param command Command to send to the FTP server. - @param netbuf Connection to FTP server. + @param conn Connection to FTP server. @return BOOL YES on success. NO otherwise. */ - (BOOL)sendCommand:(NSString *)command conn:(netbuf *)conn; @@ -80,651 +80,653 @@ @implementation FTPClient + (instancetype)clientWithCredentials:(FTPCredentials *)credentials { - return [[self alloc] initWithCredentials:credentials]; + return [[self alloc] initWithCredentials:credentials]; } + (instancetype)clientWithHost:(NSString *)host port:(int)port username:(NSString *)username password:(NSString *)password { - return [[self alloc] initWithHost:host port:port username:username password:password]; + return [[self alloc] initWithHost:host port:port username:username password:password]; } - (instancetype)initWithCredentials:(FTPCredentials *)aLocation { - self = [super init]; - if (self) { - self.credentials = aLocation; - self.queue = dispatch_queue_create("com.upstart-illustration-llc.FTPKitQueue", DISPATCH_QUEUE_SERIAL); - } - return self; + self = [super init]; + if (self) { + self.credentials = aLocation; + self.queue = dispatch_queue_create("com.upstart-illustration-llc.FTPKitQueue", DISPATCH_QUEUE_SERIAL); + } + return self; } - (instancetype)initWithHost:(NSString *)host port:(int)port username:(NSString *)username password:(NSString *)password { - FTPCredentials *creds = [FTPCredentials credentialsWithHost:host port:port username:username password:password]; - return [self initWithCredentials:creds]; + FTPCredentials *creds = [FTPCredentials credentialsWithHost:host port:port username:username password:password]; + return [self initWithCredentials:creds]; } - (NSString *)urlEncode:(NSString *)path { - return [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + return [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; } - (long long int)fileSizeAtPath:(NSString *)path { - netbuf *conn = [self connect]; - if (conn == NULL) - return -1; - const char *cPath = [[self urlEncode:path] cStringUsingEncoding:NSUTF8StringEncoding]; - unsigned int bytes; - int stat = FtpSize(cPath, &bytes, FTPLIB_BINARY, conn); - FtpQuit(conn); - if (stat == 0) { - FKLogError(@"File most likely does not exist %@", path); - return -1; - } - FKLogDebug(@"%@ bytes %d", path, bytes); - return (long long int)bytes; + netbuf *conn = [self connect]; + if (conn == NULL) + return -1; + const char *cPath = [[self urlEncode:path] cStringUsingEncoding:NSUTF8StringEncoding]; + unsigned int bytes; + int stat = FtpSize(cPath, &bytes, FTPLIB_BINARY, conn); + FtpQuit(conn); + if (stat == 0) { + FKLogError(@"File most likely does not exist %@", path); + return -1; + } + FKLogDebug(@"%@ bytes %d", path, bytes); + return (long long int)bytes; } - (NSArray *)listContentsAtPath:(NSString *)path showHiddenFiles:(BOOL)showHiddenFiles { - FTPHandle *hdl = [FTPHandle handleAtPath:path type:FTPHandleTypeDirectory]; - return [self listContentsAtHandle:hdl showHiddenFiles:showHiddenFiles]; + FTPHandle *hdl = [FTPHandle handleAtPath:path type:FTPHandleTypeDirectory]; + return [self listContentsAtHandle:hdl showHiddenFiles:showHiddenFiles]; } - (void)listContentsAtPath:(NSString *)path showHiddenFiles:(BOOL)showHiddenFiles success:(void (^)(NSArray *))success failure:(void (^)(NSError *))failure { - FTPHandle *hdl = [FTPHandle handleAtPath:path type:FTPHandleTypeDirectory]; - [self listContentsAtHandle:hdl showHiddenFiles:showHiddenFiles success:success failure:failure]; + FTPHandle *hdl = [FTPHandle handleAtPath:path type:FTPHandleTypeDirectory]; + [self listContentsAtHandle:hdl showHiddenFiles:showHiddenFiles success:success failure:failure]; } - (NSArray *)listContentsAtHandle:(FTPHandle *)handle showHiddenFiles:(BOOL)showHiddenFiles { - netbuf *conn = [self connect]; - if (conn == NULL) - return nil; - const char *path = [[self urlEncode:handle.path] cStringUsingEncoding:NSUTF8StringEncoding]; - NSString *tmpPath = [self temporaryUrl]; - const char *output = [tmpPath cStringUsingEncoding:NSUTF8StringEncoding]; - int stat = FtpDir(output, path, conn); - NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; - FtpQuit(conn); - if (stat == 0) { - self.lastError = [NSError FTPKitErrorWithResponse:response]; - return nil; - } - NSError *error = nil; - NSData *data = [NSData dataWithContentsOfFile:tmpPath options:NSDataReadingUncached error:&error]; - if (error) { - FKLogError(@"Error: %@", error.localizedDescription); - self.lastError = error; - return nil; - } - /** - Please note: If there are no contents in the folder OR if the folder does - not exist data.bytes _will_ be 0. Therefore, you can not use this method to - determine if a directory exists! - */ - [[NSFileManager defaultManager] removeItemAtPath:tmpPath error:&error]; - // Log the error, but do not fail. - if (error) { - FKLogError(@"Failed to remove tmp file. Error: %@", error.localizedDescription); - } - NSArray *files = [self parseListData:data handle:handle showHiddentFiles:showHiddenFiles]; - return files; // If files == nil, method will set the lastError. + netbuf *conn = [self connect]; + if (conn == NULL) + return nil; + const char *path = [[self urlEncode:handle.path] cStringUsingEncoding:NSUTF8StringEncoding]; + NSString *tmpPath = [self temporaryUrl]; + const char *output = [tmpPath cStringUsingEncoding:NSUTF8StringEncoding]; + int stat = FtpDir(output, path, conn); + NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; + FtpQuit(conn); + if (stat == 0) { + self.lastError = [NSError FTPKitErrorWithResponse:response]; + return nil; + } + NSError *error = nil; + NSData *data = [NSData dataWithContentsOfFile:tmpPath options:NSDataReadingUncached error:&error]; + if (error) { + FKLogError(@"Error: %@", error.localizedDescription); + self.lastError = error; + return nil; + } + /** + Please note: If there are no contents in the folder OR if the folder does + not exist data.bytes _will_ be 0. Therefore, you can not use this method to + determine if a directory exists! + */ + [[NSFileManager defaultManager] removeItemAtPath:tmpPath error:&error]; + // Log the error, but do not fail. + if (error) { + FKLogError(@"Failed to remove tmp file. Error: %@", error.localizedDescription); + } + NSArray *files = [self parseListData:data handle:handle showHiddentFiles:showHiddenFiles]; + return files; // If files == nil, method will set the lastError. } - (void)listContentsAtHandle:(FTPHandle *)handle showHiddenFiles:(BOOL)showHiddenFiles success:(void (^)(NSArray *))success failure:(void (^)(NSError *))failure { - dispatch_async(_queue, ^{ - NSArray *contents = [self listContentsAtHandle:handle showHiddenFiles:showHiddenFiles]; - if (contents && success) { - dispatch_async(dispatch_get_main_queue(), ^{ - success(contents); - }); - } else if (! contents && failure) { - [self returnFailure:failure]; - } - }); + dispatch_async(_queue, ^{ + NSArray *contents = [self listContentsAtHandle:handle showHiddenFiles:showHiddenFiles]; + if (contents && success) { + dispatch_async(dispatch_get_main_queue(), ^{ + success(contents); + }); + } else if (! contents && failure) { + [self returnFailure:failure]; + } + }); } - (BOOL)downloadFile:(NSString *)remotePath to:(NSString *)localPath progress:(BOOL (^)(NSUInteger, NSUInteger))progress { - return [self downloadHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeFile] to:localPath progress:progress]; + return [self downloadHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeFile] to:localPath progress:progress]; } - (void)downloadFile:(NSString *)remotePath to:(NSString *)localPath progress:(BOOL (^)(NSUInteger, NSUInteger))progress success:(void (^)(void))success failure:(void (^)(NSError *))failure { - [self downloadHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeFile] to:localPath progress:progress success:success failure:failure]; + [self downloadHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeFile] to:localPath progress:progress success:success failure:failure]; } - (BOOL)downloadHandle:(FTPHandle *)handle to:(NSString *)localPath progress:(BOOL (^)(NSUInteger, NSUInteger))progress { - netbuf *conn = [self connect]; - if (conn == NULL) - return NO; - const char *output = [localPath cStringUsingEncoding:NSUTF8StringEncoding]; - const char *path = [[self urlEncode:handle.path] cStringUsingEncoding:NSUTF8StringEncoding]; - // @todo Send w/ appropriate mode. FTPLIB_ASCII | FTPLIB_BINARY - int stat = FtpGet(output, path, FTPLIB_BINARY, conn); - NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; - // @todo Use 'progress' block. - FtpQuit(conn); - if (stat == 0) { - self.lastError = [NSError FTPKitErrorWithResponse:response]; - return NO; - } - return YES; + netbuf *conn = [self connect]; + if (conn == NULL) + return NO; + const char *output = [localPath cStringUsingEncoding:NSUTF8StringEncoding]; + const char *path = [[self urlEncode:handle.path] cStringUsingEncoding:NSUTF8StringEncoding]; + // @todo Send w/ appropriate mode. FTPLIB_ASCII | FTPLIB_BINARY + int stat = FtpGet(output, path, FTPLIB_BINARY, conn); + NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; + // @todo Use 'progress' block. + FtpQuit(conn); + if (stat == 0) { + self.lastError = [NSError FTPKitErrorWithResponse:response]; + return NO; + } + return YES; } - (void)downloadHandle:(FTPHandle *)handle to:(NSString *)localPath progress:(BOOL (^)(NSUInteger, NSUInteger))progress success:(void (^)(void))success failure:(void (^)(NSError *))failure { - dispatch_async(_queue, ^{ - BOOL ret = [self downloadHandle:handle to:localPath progress:progress]; - if (ret && success) { - dispatch_async(dispatch_get_main_queue(), ^{ - success(); - }); - } else if (! ret && failure) { - [self returnFailure:failure]; - } - }); + dispatch_async(_queue, ^{ + BOOL ret = [self downloadHandle:handle to:localPath progress:progress]; + if (ret && success) { + dispatch_async(dispatch_get_main_queue(), ^{ + success(); + }); + } else if (! ret && failure) { + [self returnFailure:failure]; + } + }); } - (BOOL)uploadFile:(NSString *)localPath to:(NSString *)remotePath progress:(BOOL (^)(NSUInteger, NSUInteger))progress { - netbuf *conn = [self connect]; - if (conn == NULL) - return NO; - const char *input = [localPath cStringUsingEncoding:NSUTF8StringEncoding]; - const char *path = [remotePath cStringUsingEncoding:NSUTF8StringEncoding]; - // @todo Send w/ appropriate mode. FTPLIB_ASCII | FTPLIB_BINARY - int stat = FtpPut(input, path, FTPLIB_BINARY, conn); - // @todo Use 'progress' block. - NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; - FtpQuit(conn); - if (stat == 0) { - // Invalid path, wrong permissions, etc. Make sure that permissions are - // set corectly on the path AND the path of the initialPath is correct. - self.lastError = [NSError FTPKitErrorWithResponse:response]; - return NO; - } - return YES; + netbuf *conn = [self connect]; + if (conn == NULL) + return NO; + const char *input = [localPath cStringUsingEncoding:NSUTF8StringEncoding]; + const char *path = [remotePath cStringUsingEncoding:NSUTF8StringEncoding]; + // @todo Send w/ appropriate mode. FTPLIB_ASCII | FTPLIB_BINARY + int stat = FtpPut(input, path, FTPLIB_BINARY, conn); + // @todo Use 'progress' block. + NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; + FtpQuit(conn); + if (stat == 0) { + // Invalid path, wrong permissions, etc. Make sure that permissions are + // set corectly on the path AND the path of the initialPath is correct. + self.lastError = [NSError FTPKitErrorWithResponse:response]; + return NO; + } + return YES; } - (void)uploadFile:(NSString *)localPath to:(NSString *)remotePath progress:(BOOL (^)(NSUInteger, NSUInteger))progress success:(void (^)(void))success failure:(void (^)(NSError *))failure { - dispatch_async(_queue, ^{ - BOOL ret = [self uploadFile:localPath to:remotePath progress:progress]; - if (ret && success) { - dispatch_async(dispatch_get_main_queue(), ^{ - success(); - }); - } else if (! ret && failure) { - [self returnFailure:failure]; - } - }); + dispatch_async(_queue, ^{ + BOOL ret = [self uploadFile:localPath to:remotePath progress:progress]; + if (ret && success) { + dispatch_async(dispatch_get_main_queue(), ^{ + success(); + }); + } else if (! ret && failure) { + [self returnFailure:failure]; + } + }); } - (BOOL)createDirectoryAtPath:(NSString *)remotePath { - return [self createDirectoryAtHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeDirectory]]; + return [self createDirectoryAtHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeDirectory]]; } - (void)createDirectoryAtPath:(NSString *)remotePath success:(void (^)(void))success failure:(void (^)(NSError *))failure { - [self createDirectoryAtHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeDirectory] success:success failure:failure]; + [self createDirectoryAtHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeDirectory] success:success failure:failure]; } - (BOOL)createDirectoryAtHandle:(FTPHandle *)handle { - netbuf *conn = [self connect]; - if (conn == NULL) - return NO; - const char *path = [handle.path cStringUsingEncoding:NSUTF8StringEncoding]; - int stat = FtpMkdir(path, conn); - NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; - FtpQuit(conn); - if (stat == 0) { - self.lastError = [NSError FTPKitErrorWithResponse:response]; - return NO; - } - return YES; + netbuf *conn = [self connect]; + if (conn == NULL) + return NO; + const char *path = [handle.path cStringUsingEncoding:NSUTF8StringEncoding]; + int stat = FtpMkdir(path, conn); + NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; + FtpQuit(conn); + if (stat == 0) { + self.lastError = [NSError FTPKitErrorWithResponse:response]; + return NO; + } + return YES; } - (void)createDirectoryAtHandle:(FTPHandle *)handle success:(void (^)(void))success failure:(void (^)(NSError *))failure { - dispatch_async(_queue, ^{ - BOOL ret = [self createDirectoryAtHandle:handle]; - if (ret && success) { - dispatch_async(dispatch_get_main_queue(), ^{ - success(); - }); - } else if (! ret && failure) { - [self returnFailure:failure]; - } - }); + dispatch_async(_queue, ^{ + BOOL ret = [self createDirectoryAtHandle:handle]; + if (ret && success) { + dispatch_async(dispatch_get_main_queue(), ^{ + success(); + }); + } else if (! ret && failure) { + [self returnFailure:failure]; + } + }); } - (BOOL)deleteDirectoryAtPath:(NSString *)remotePath { - return [self deleteHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeDirectory]]; + return [self deleteHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeDirectory]]; } - (void)deleteDirectoryAtPath:(NSString *)remotePath success:(void (^)(void))success failure:(void (^)(NSError *))failure { - [self deleteHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeDirectory] success:success failure:failure]; + [self deleteHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeDirectory] success:success failure:failure]; } - (BOOL)deleteFileAtPath:(NSString *)remotePath { - return [self deleteHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeFile]]; + return [self deleteHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeFile]]; } - (void)deleteFileAtPath:(NSString *)remotePath success:(void (^)(void))success failure:(void (^)(NSError *))failure { - [self deleteHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeFile] success:success failure:failure]; + [self deleteHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeFile] success:success failure:failure]; } - (BOOL)deleteHandle:(FTPHandle *)handle { - netbuf *conn = [self connect]; - if (conn == NULL) - return NO; - const char *path = [[self urlEncode:handle.path] cStringUsingEncoding:NSUTF8StringEncoding]; - int stat = 0; - if (handle.type == FTPHandleTypeDirectory) - stat = FtpRmdir(path, conn); - else - stat = FtpDelete(path, conn); - NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; - FtpQuit(conn); - if (stat == 0) { - self.lastError = [NSError FTPKitErrorWithResponse:response]; - return NO; - } - return YES; + netbuf *conn = [self connect]; + if (conn == NULL) + return NO; + const char *path = [[self urlEncode:handle.path] cStringUsingEncoding:NSUTF8StringEncoding]; + int stat = 0; + if (handle.type == FTPHandleTypeDirectory) + stat = FtpRmdir(path, conn); + else + stat = FtpDelete(path, conn); + NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; + FtpQuit(conn); + if (stat == 0) { + self.lastError = [NSError FTPKitErrorWithResponse:response]; + return NO; + } + return YES; } - (void)deleteHandle:(FTPHandle *)handle success:(void (^)(void))success failure:(void (^)(NSError *))failure { - dispatch_async(_queue, ^{ - BOOL ret = [self deleteHandle:handle]; - if (ret && success) { - dispatch_async(dispatch_get_main_queue(), ^{ - success(); - }); - } else if (! ret && failure) { - [self returnFailure:failure]; - } - }); + dispatch_async(_queue, ^{ + BOOL ret = [self deleteHandle:handle]; + if (ret && success) { + dispatch_async(dispatch_get_main_queue(), ^{ + success(); + }); + } else if (! ret && failure) { + [self returnFailure:failure]; + } + }); } - (BOOL)chmodPath:(NSString *)remotePath toMode:(int)mode { - return [self chmodHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeUnknown] toMode:mode]; + return [self chmodHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeUnknown] toMode:mode]; } - (void)chmodPath:(NSString *)remotePath toMode:(int)mode success:(void (^)(void))success failure:(void (^)(NSError *))failure { - [self chmodHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeUnknown] toMode:mode success:success failure:failure]; + [self chmodHandle:[FTPHandle handleAtPath:remotePath type:FTPHandleTypeUnknown] toMode:mode success:success failure:failure]; } - (BOOL)chmodHandle:(FTPHandle *)handle toMode:(int)mode { - if (mode < 0 || mode > 777) { - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedString(@"File mode value must be between 0 and 0777.", @"") - forKey:NSLocalizedDescriptionKey]; - self.lastError = [[NSError alloc] initWithDomain:FTPErrorDomain code:0 userInfo:userInfo]; - return NO; - } - NSString *command = [NSString stringWithFormat:@"SITE CHMOD %i %@", mode, [self urlEncode:handle.path]]; - netbuf *conn = [self connect]; - if (conn == NULL) - return NO; - BOOL success = [self sendCommand:command conn:conn]; - NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; - FtpQuit(conn); - if (! success) { - self.lastError = [NSError FTPKitErrorWithResponse:response]; - return NO; - } - return YES; + if (mode < 0 || mode > 777) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedString(@"File mode value must be between 0 and 0777.", @"") + forKey:NSLocalizedDescriptionKey]; + self.lastError = [[NSError alloc] initWithDomain:FTPErrorDomain code:0 userInfo:userInfo]; + return NO; + } + NSString *command = [NSString stringWithFormat:@"SITE CHMOD %i %@", mode, [self urlEncode:handle.path]]; + netbuf *conn = [self connect]; + if (conn == NULL) + return NO; + BOOL success = [self sendCommand:command conn:conn]; + NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; + FtpQuit(conn); + if (! success) { + self.lastError = [NSError FTPKitErrorWithResponse:response]; + return NO; + } + return YES; } - (void)chmodHandle:(FTPHandle *)handle toMode:(int)mode success:(void (^)(void))success failure:(void (^)(NSError *))failure { - dispatch_async(_queue, ^{ - BOOL ret = [self chmodHandle:handle toMode:mode]; - if (ret && success) { - dispatch_async(dispatch_get_main_queue(), ^{ - success(); - }); - } else if (! ret && failure) { - [self returnFailure:failure]; - } - }); + dispatch_async(_queue, ^{ + BOOL ret = [self chmodHandle:handle toMode:mode]; + if (ret && success) { + dispatch_async(dispatch_get_main_queue(), ^{ + success(); + }); + } else if (! ret && failure) { + [self returnFailure:failure]; + } + }); } - (BOOL)renamePath:(NSString *)sourcePath to:(NSString *)destPath { - netbuf *conn = [self connect]; - if (conn == NULL) - return NO; - const char *src = [[self urlEncode:sourcePath] cStringUsingEncoding:NSUTF8StringEncoding]; - // @note The destination path does not need to be URL encoded. In fact, if - // it is, the filename will include the percent escaping! - const char *dst = [destPath cStringUsingEncoding:NSUTF8StringEncoding]; - int stat = FtpRename(src, dst, conn); - NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; - FtpQuit(conn); - if (stat == 0) { - self.lastError = [NSError FTPKitErrorWithResponse:response]; - return NO; - } - return YES; + netbuf *conn = [self connect]; + if (conn == NULL) + return NO; + const char *src = [[self urlEncode:sourcePath] cStringUsingEncoding:NSUTF8StringEncoding]; + // @note The destination path does not need to be URL encoded. In fact, if + // it is, the filename will include the percent escaping! + const char *dst = [destPath cStringUsingEncoding:NSUTF8StringEncoding]; + int stat = FtpRename(src, dst, conn); + NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; + FtpQuit(conn); + if (stat == 0) { + self.lastError = [NSError FTPKitErrorWithResponse:response]; + return NO; + } + return YES; } - (void)renamePath:(NSString *)sourcePath to:(NSString *)destPath success:(void (^)(void))success failure:(void (^)(NSError *))failure { - dispatch_async(_queue, ^{ - BOOL ret = [self renamePath:sourcePath to:destPath]; - if (ret && success) { - dispatch_async(dispatch_get_main_queue(), ^{ - success(); - }); - } else if (! ret && failure) { - [self returnFailure:failure]; - } - }); + dispatch_async(_queue, ^{ + BOOL ret = [self renamePath:sourcePath to:destPath]; + if (ret && success) { + dispatch_async(dispatch_get_main_queue(), ^{ + success(); + }); + } else if (! ret && failure) { + [self returnFailure:failure]; + } + }); } - (BOOL)copyPath:(NSString *)sourcePath to:(NSString *)destPath { - NSString *tmpPath = [self temporaryUrl]; - BOOL success = [self downloadFile:sourcePath to:tmpPath progress:NULL]; - if (! success) - return NO; - success = [self uploadFile:tmpPath to:destPath progress:NULL]; - // Remove file. - NSError *error; - [[NSFileManager defaultManager] removeItemAtPath:tmpPath error:&error]; - // Log the error, but do not fail. - if (error) { - FKLogError(@"Failed to remove tmp file. Error: %@", error.localizedDescription); - } - if (! success) - return NO; - return YES; + NSString *tmpPath = [self temporaryUrl]; + BOOL success = [self downloadFile:sourcePath to:tmpPath progress:NULL]; + if (! success) + return NO; + success = [self uploadFile:tmpPath to:destPath progress:NULL]; + // Remove file. + NSError *error; + [[NSFileManager defaultManager] removeItemAtPath:tmpPath error:&error]; + // Log the error, but do not fail. + if (error) { + FKLogError(@"Failed to remove tmp file. Error: %@", error.localizedDescription); + } + if (! success) + return NO; + return YES; } - (void)copyPath:(NSString *)sourcePath to:(NSString *)destPath success:(void (^)(void))success failure:(void (^)(NSError *))failure { - dispatch_async(_queue, ^{ - BOOL ret = [self copyPath:sourcePath to:destPath]; - if (ret && success) { - dispatch_async(dispatch_get_main_queue(), ^{ - success(); - }); - } else if (! ret && failure) { - [self returnFailure:failure]; - } - }); + dispatch_async(_queue, ^{ + BOOL ret = [self copyPath:sourcePath to:destPath]; + if (ret && success) { + dispatch_async(dispatch_get_main_queue(), ^{ + success(); + }); + } else if (! ret && failure) { + [self returnFailure:failure]; + } + }); } /** Private Methods */ - (netbuf *)connect { - self.lastError = nil; - const char *host = [_credentials.host cStringUsingEncoding:NSUTF8StringEncoding]; - const char *user = [_credentials.username cStringUsingEncoding:NSUTF8StringEncoding]; - const char *pass = [_credentials.password cStringUsingEncoding:NSUTF8StringEncoding]; - netbuf *conn; - int stat = FtpConnect(host, &conn); - if (stat == 0) { - // @fixme We don't get the exact error code from the lib. Use a generic - // connection error. - self.lastError = [NSError FTPKitErrorWithCode:10060]; - return NULL; - } - stat = FtpLogin(user, pass, conn); - if (stat == 0) { - NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; - self.lastError = [NSError FTPKitErrorWithResponse:response]; - FtpQuit(conn); - return NULL; - } - return conn; + self.lastError = nil; + const char *host = [_credentials.host cStringUsingEncoding:NSUTF8StringEncoding]; + const char *user = _credentials.username != nil ? [_credentials.username cStringUsingEncoding:NSUTF8StringEncoding] : NULL; + const char *pass = _credentials.password != nil ? [_credentials.password cStringUsingEncoding:NSUTF8StringEncoding] : NULL; + netbuf *conn; + int stat = FtpConnect(host, &conn); + if (stat == 0) { + // @fixme We don't get the exact error code from the lib. Use a generic + // connection error. + self.lastError = [NSError FTPKitErrorWithCode:10060]; + return NULL; + } + if ( user != NULL && pass != NULL ) { + stat = FtpLogin(user, pass, conn); + if (stat == 0) { + NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; + self.lastError = [NSError FTPKitErrorWithResponse:response]; + FtpQuit(conn); + return NULL; + } + } + return conn; } - (BOOL)sendCommand:(NSString *)command conn:(netbuf *)conn { - const char *cmd = [command cStringUsingEncoding:NSUTF8StringEncoding]; - if (!FtpSendCmd(cmd, '2', conn)) { - NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; - self.lastError = [NSError FTPKitErrorWithResponse:response]; - return NO; - } - return YES; + const char *cmd = [command cStringUsingEncoding:NSUTF8StringEncoding]; + if (!FtpSendCmd(cmd, '2', conn)) { + NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; + self.lastError = [NSError FTPKitErrorWithResponse:response]; + return NO; + } + return YES; } - (void)failedWithMessage:(NSString *)message { - self.lastError = [NSError errorWithDomain:FTPErrorDomain - code:502 - userInfo:[NSDictionary dictionaryWithObject:message forKey:NSLocalizedDescriptionKey]]; + self.lastError = [NSError errorWithDomain:FTPErrorDomain + code:502 + userInfo:[NSDictionary dictionaryWithObject:message forKey:NSLocalizedDescriptionKey]]; } - (NSString *)temporaryUrl { - // Do not use NSURL. It will not allow you to read the file contents. - NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"FTPKit.list"]; - //FKLogDebug(@"path: %@", path); - return path; + // Do not use NSURL. It will not allow you to read the file contents. + NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"FTPKit.list"]; + //FKLogDebug(@"path: %@", path); + return path; } - (NSDictionary *)entryByReencodingNameInEntry:(NSDictionary *)entry encoding:(NSStringEncoding)newEncoding { - // Convert to the preferred encoding. By default CF encodes the string - // as MacRoman. - NSString *newName = nil; - NSString *name = [entry objectForKey:(id)kCFFTPResourceName]; - if (name != nil) { - NSData *data = [name dataUsingEncoding:NSMacOSRomanStringEncoding]; - if (data != nil) { - newName = [[NSString alloc] initWithData:data encoding:newEncoding]; - } - } - - // If the above failed, just return the entry unmodified. If it succeeded, - // make a copy of the entry and replace the name with the new name that we - // calculated. - NSDictionary *result = nil; - if (! newName) { - result = (NSDictionary *)entry; - } else { - NSMutableDictionary *newEntry = [NSMutableDictionary dictionaryWithDictionary:entry]; - [newEntry setObject:newName forKey:(id)kCFFTPResourceName]; - result = newEntry; - } - return result; + // Convert to the preferred encoding. By default CF encodes the string + // as MacRoman. + NSString *newName = nil; + NSString *name = [entry objectForKey:(id)kCFFTPResourceName]; + if (name != nil) { + NSData *data = [name dataUsingEncoding:NSMacOSRomanStringEncoding]; + if (data != nil) { + newName = [[NSString alloc] initWithData:data encoding:newEncoding]; + } + } + + // If the above failed, just return the entry unmodified. If it succeeded, + // make a copy of the entry and replace the name with the new name that we + // calculated. + NSDictionary *result = nil; + if (! newName) { + result = (NSDictionary *)entry; + } else { + NSMutableDictionary *newEntry = [NSMutableDictionary dictionaryWithDictionary:entry]; + [newEntry setObject:newName forKey:(id)kCFFTPResourceName]; + result = newEntry; + } + return result; } - (NSArray *)parseListData:(NSData *)data handle:(FTPHandle *)handle showHiddentFiles:(BOOL)showHiddenFiles { - NSMutableArray *files = [NSMutableArray array]; - NSUInteger offset = 0; - do { - CFDictionaryRef thisEntry = NULL; - CFIndex bytes = CFFTPCreateParsedResourceListing(NULL, &((const uint8_t *) data.bytes)[offset], data.length - offset, &thisEntry); - if (bytes > 0) { - if (thisEntry != NULL) { - NSDictionary *entry = [self entryByReencodingNameInEntry:(__bridge NSDictionary *)thisEntry encoding:NSUTF8StringEncoding]; - FTPHandle *ftpHandle = [FTPHandle handleAtPath:handle.path attributes:entry]; - if (! [ftpHandle.name hasPrefix:@"."] || showHiddenFiles) { - [files addObject:ftpHandle]; - } + NSMutableArray *files = [NSMutableArray array]; + NSUInteger offset = 0; + do { + CFDictionaryRef thisEntry = NULL; + CFIndex bytes = CFFTPCreateParsedResourceListing(NULL, &((const uint8_t *) data.bytes)[offset], data.length - offset, &thisEntry); + if (bytes > 0) { + if (thisEntry != NULL) { + NSDictionary *entry = [self entryByReencodingNameInEntry:(__bridge NSDictionary *)thisEntry encoding:NSUTF8StringEncoding]; + FTPHandle *ftpHandle = [FTPHandle handleAtPath:handle.path attributes:entry]; + if (! [ftpHandle.name hasPrefix:@"."] || showHiddenFiles) { + [files addObject:ftpHandle]; } - offset += bytes; - } - - if (thisEntry != NULL) { - CFRelease(thisEntry); - } - - if (bytes == 0) { - break; - } else if (bytes < 0) { - [self failedWithMessage:NSLocalizedString(@"Failed to parse directory listing", @"")]; - return nil; - } - } while (YES); - - if (offset != data.length) { - FKLogWarn(@"Some bytes not read!"); - } - - return files; + } + offset += bytes; + } + + if (thisEntry != NULL) { + CFRelease(thisEntry); + } + + if (bytes == 0) { + break; + } else if (bytes < 0) { + [self failedWithMessage:NSLocalizedString(@"Failed to parse directory listing", @"")]; + return nil; + } + } while (YES); + + if (offset != data.length) { + FKLogWarn(@"Some bytes not read!"); + } + + return files; } - (NSDate *)lastModifiedAtPath:(NSString *)remotePath { - netbuf *conn = [self connect]; - if (conn == NULL) - return nil; - const char *cPath = [[self urlEncode:remotePath] cStringUsingEncoding:NSUTF8StringEncoding]; - char dt[kFTPKitRequestBufferSize]; - // This is returning FALSE when attempting to create a new folder that exists... why? - // MDTM does not work with folders. It is meant to be used only for types - // of files that can be downloaded using the RETR command. - int stat = FtpModDate(cPath, dt, kFTPKitRequestBufferSize, conn); - NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; - FtpQuit(conn); - if (stat == 0) { - self.lastError = [NSError FTPKitErrorWithResponse:response]; - return nil; - } - NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; - // FTP spec: YYYYMMDDhhmmss - // @note dt always contains a trailing newline char. - formatter.dateFormat = @"yyyyMMddHHmmss\n"; - NSString *dateString = [NSString stringWithCString:dt encoding:NSUTF8StringEncoding]; - NSDate *date = [formatter dateFromString:dateString]; - return date; + netbuf *conn = [self connect]; + if (conn == NULL) + return nil; + const char *cPath = [[self urlEncode:remotePath] cStringUsingEncoding:NSUTF8StringEncoding]; + char dt[kFTPKitRequestBufferSize]; + // This is returning FALSE when attempting to create a new folder that exists... why? + // MDTM does not work with folders. It is meant to be used only for types + // of files that can be downloaded using the RETR command. + int stat = FtpModDate(cPath, dt, kFTPKitRequestBufferSize, conn); + NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; + FtpQuit(conn); + if (stat == 0) { + self.lastError = [NSError FTPKitErrorWithResponse:response]; + return nil; + } + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + // FTP spec: YYYYMMDDhhmmss + // @note dt always contains a trailing newline char. + formatter.dateFormat = @"yyyyMMddHHmmss\n"; + NSString *dateString = [NSString stringWithCString:dt encoding:NSUTF8StringEncoding]; + NSDate *date = [formatter dateFromString:dateString]; + return date; } - (void)lastModifiedAtPath:(NSString *)remotePath success:(void (^)(NSDate *))success failure:(void (^)(NSError *))failure { - dispatch_async(_queue, ^{ - NSDate *date = [self lastModifiedAtPath:remotePath]; - if (! _lastError && success) { - dispatch_async(dispatch_get_main_queue(), ^{ - success(date); - }); - } else if (_lastError && failure) { - [self returnFailure:failure]; - } - }); + dispatch_async(_queue, ^{ + NSDate *date = [self lastModifiedAtPath:remotePath]; + if (! self->_lastError && success) { + dispatch_async(dispatch_get_main_queue(), ^{ + success(date); + }); + } else if (self->_lastError && failure) { + [self returnFailure:failure]; + } + }); } - (BOOL)directoryExistsAtPath:(NSString *)remotePath { - /** - Test the directory by changing to the directory. If the process succeeds - then the directory exists. - - The process is to get the current working directory and change _back_ to - the previous current working directory. There is a possibility that the - second changeDirectoryToPath: may fail! This is really the price we pay - for this command as there is no other accurate way to determine this. - - Using listContentsAtPath:showHiddenFiles: will fail as it will return empty - contents even if the directory doesn't exist! So long as the command - _succeeds_ it will return an empty list. - + /** + Test the directory by changing to the directory. If the process succeeds + then the directory exists. + + The process is to get the current working directory and change _back_ to + the previous current working directory. There is a possibility that the + second changeDirectoryToPath: may fail! This is really the price we pay + for this command as there is no other accurate way to determine this. + + Using listContentsAtPath:showHiddenFiles: will fail as it will return empty + contents even if the directory doesn't exist! So long as the command + _succeeds_ it will return an empty list. + // Get the current working directory. We will change back to this directory // if necessary. NSString *cwd = [self printWorkingDirectory]; // No need to continue. We already know the path exists by the fact that we // are currently _in_ the directory. if ([cwd isEqualToString:remotePath]) - return YES; + return YES; // Test directory by changing to it. BOOL success = [self changeDirectoryToPath:remotePath]; // Attempt to change back to the previous directory. if (success) - [self changeDirectoryToPath:cwd]; + [self changeDirectoryToPath:cwd]; return success; - */ - - /** - Currently the lib creates a new connection for every command issued. - Therefore, it is unnecessary to change back to the original cwd. - */ - netbuf *conn = [self connect]; - if (conn == NULL) - return NO; - const char *cPath = [remotePath cStringUsingEncoding:NSUTF8StringEncoding]; - int stat = FtpChdir(cPath, conn); - FtpQuit(conn); - if (stat == 0) - return NO; - return YES; + */ + + /** + Currently the lib creates a new connection for every command issued. + Therefore, it is unnecessary to change back to the original cwd. + */ + netbuf *conn = [self connect]; + if (conn == NULL) + return NO; + const char *cPath = [remotePath cStringUsingEncoding:NSUTF8StringEncoding]; + int stat = FtpChdir(cPath, conn); + FtpQuit(conn); + if (stat == 0) + return NO; + return YES; } - (void)directoryExistsAtPath:(NSString *)remotePath success:(void (^)(BOOL))success failure:(void (^)(NSError *))failure { - dispatch_async(_queue, ^{ - BOOL exists = [self directoryExistsAtPath:remotePath]; - if (! _lastError && success) { - dispatch_async(dispatch_get_main_queue(), ^{ - success(exists); - }); - } else if (_lastError && failure) { - [self returnFailure:failure]; - } - }); + dispatch_async(_queue, ^{ + BOOL exists = [self directoryExistsAtPath:remotePath]; + if (! self->_lastError && success) { + dispatch_async(dispatch_get_main_queue(), ^{ + success(exists); + }); + } else if (self->_lastError && failure) { + [self returnFailure:failure]; + } + }); } - (BOOL)changeDirectoryToPath:(NSString *)remotePath { - netbuf *conn = [self connect]; - if (conn == NULL) - return NO; - const char *cPath = [remotePath cStringUsingEncoding:NSUTF8StringEncoding]; - int stat = FtpChdir(cPath, conn); - NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; - FtpQuit(conn); - if (stat == 0) { - self.lastError = [NSError FTPKitErrorWithResponse:response]; - return NO; - } - return YES; + netbuf *conn = [self connect]; + if (conn == NULL) + return NO; + const char *cPath = [remotePath cStringUsingEncoding:NSUTF8StringEncoding]; + int stat = FtpChdir(cPath, conn); + NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; + FtpQuit(conn); + if (stat == 0) { + self.lastError = [NSError FTPKitErrorWithResponse:response]; + return NO; + } + return YES; } - (NSString *)printWorkingDirectory { - netbuf *conn = [self connect]; - if (conn == NULL) - return nil; - char cPath[kFTPKitTempBufferSize]; - int stat = FtpPwd(cPath, kFTPKitTempBufferSize, conn); - NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; - FtpQuit(conn); - if (stat == 0) { - self.lastError = [NSError FTPKitErrorWithResponse:response]; - return nil; - } - return [NSString stringWithCString:cPath encoding:NSUTF8StringEncoding]; + netbuf *conn = [self connect]; + if (conn == NULL) + return nil; + char cPath[kFTPKitTempBufferSize]; + int stat = FtpPwd(cPath, kFTPKitTempBufferSize, conn); + NSString *response = [NSString stringWithCString:FtpLastResponse(conn) encoding:NSUTF8StringEncoding]; + FtpQuit(conn); + if (stat == 0) { + self.lastError = [NSError FTPKitErrorWithResponse:response]; + return nil; + } + return [NSString stringWithCString:cPath encoding:NSUTF8StringEncoding]; } - (void)returnFailure:(void (^)(NSError *))failure { - NSError *error = [_lastError copy]; - dispatch_async(dispatch_get_main_queue(), ^{ - failure(error); - }); + NSError *error = [_lastError copy]; + dispatch_async(dispatch_get_main_queue(), ^{ + failure(error); + }); } @end diff --git a/FTPKit/FTPCredentials.m b/FTPKit/FTPCredentials.m index 78c79f7..0aa398e 100644 --- a/FTPKit/FTPCredentials.m +++ b/FTPKit/FTPCredentials.m @@ -1,5 +1,5 @@ #import "FTPCredentials.h" -#import "NSString+Additions.h" +//#import "NSString+Additions.h" @interface FTPCredentials() @property (nonatomic, strong) NSString *host; @@ -12,29 +12,30 @@ @implementation FTPCredentials + (instancetype)credentialsWithHost:(NSString *)aHost port:(int)aPort username:(NSString *)aUsername password:(NSString *)aPassword { - return [[self alloc] initWithHost:aHost port:aPort username:aUsername password:aPassword]; + return [[self alloc] initWithHost:aHost port:aPort username:aUsername password:aPassword]; } - (id)initWithHost:(NSString *)aHost port:(int)aPort username:(NSString *)aUsername password:(NSString *)aPassword { - self = [super init]; - if (self) { - self.host = aHost; - self.port = aPort < 1 ? 21 : aPort; - self.username = aUsername; - self.password = aPassword; - } - return self; + self = [super init]; + if (self) { + self.host = aHost; + self.port = aPort < 1 ? 21 : aPort; + self.username = aUsername; + self.password = aPassword; + } + return self; } - (NSURL *)urlForPath:(NSString *)path { - // @todo encode username and password? - NSString *scheme = [NSString stringWithFormat:@"ftp://%@:%@@%@:%d", _username, _password, _host, _port]; - NSString *decoded = [path FTPKitURLDecodedString]; - NSString *encoded = [decoded isEqualToString:path] ? [path FTPKitURLEncodedString] : path; - NSURL *url = [NSURL URLWithString:[scheme stringByAppendingString:encoded]]; - return url; + // @todo encode username and password? + NSString *scheme = [NSString stringWithFormat:@"ftp://%@:%@@%@:%d", _username, _password, _host, _port]; + NSString *decoded = [path stringByRemovingPercentEncoding]; +// NSString *decoded = [path FTPKitURLDecodedString]; + if ( [decoded isEqualToString:path] ) + return [NSURL URLWithString:[scheme stringByAppendingString:[path stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]]]; + return [NSURL URLWithString:[scheme stringByAppendingString:path]]; } @end diff --git a/FTPKit/FTPHandle.h b/FTPKit/FTPHandle.h index 09a022c..957c138 100644 --- a/FTPKit/FTPHandle.h +++ b/FTPKit/FTPHandle.h @@ -59,7 +59,6 @@ typedef enum { /** If mode set, returns string representation of file permissions. - @param localPath Local path to handle @return string representation of permissions. */ - (NSString *)permissions; diff --git a/FTPKit/FTPKit.h b/FTPKit/FTPKit.h index 27a97ce..71c6951 100644 --- a/FTPKit/FTPKit.h +++ b/FTPKit/FTPKit.h @@ -1,4 +1,5 @@ #import "FTPCredentials.h" #import "FTPHandle.h" -#import "FTPClient.h" \ No newline at end of file +#import "FTPClient.h" +#import "ftplib.h" diff --git a/FTPKitMac/FTPKitMac.h b/FTPKitMac/FTPKitMac.h new file mode 100644 index 0000000..19a0c64 --- /dev/null +++ b/FTPKitMac/FTPKitMac.h @@ -0,0 +1,19 @@ +// +// FTPKitMac.h +// FTPKitMac +// +// Created by ssb on 07.12.17. +// Copyright © 2017 Upstart Illustration LLC. All rights reserved. +// + +#import + +//! Project version number for FTPKitMac. +FOUNDATION_EXPORT double FTPKitMacVersionNumber; + +//! Project version string for FTPKitMac. +FOUNDATION_EXPORT const unsigned char FTPKitMacVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + +#import "FTPKit.h" diff --git a/FTPKitMac/Info.plist b/FTPKitMac/Info.plist new file mode 100644 index 0000000..884c04b --- /dev/null +++ b/FTPKitMac/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2017 Upstart Illustration LLC. All rights reserved. + NSPrincipalClass + + + diff --git a/Libraries/include/ftplib/src/ftplib.c b/Libraries/include/ftplib/src/ftplib.c index de617c1..32f11bc 100644 --- a/Libraries/include/ftplib/src/ftplib.c +++ b/Libraries/include/ftplib/src/ftplib.c @@ -100,7 +100,7 @@ struct NetBuf { static char *version = "ftplib Release 4.0 07-Jun-2013, copyright 1996-2003, 2013 Thomas Pfau"; -GLOBALDEF int ftplib_debug = 3; +/*GLOBALDEF*/ int ftplib_debug = 3; #if defined(NEED_STRDUP) /* @@ -371,9 +371,9 @@ static int socket_wait(netbuf *ctl) * * return -1 on error or bytecount */ -static int readline(char *buf, int max, netbuf *ctl) +static long readline(char *buf, int max, netbuf *ctl) { - int x, retval = 0; + long x, retval = 0; char *end, *bp=buf; int eof = 0; @@ -448,7 +448,7 @@ static int readline(char *buf, int max, netbuf *ctl) * * return -1 on error or bytecount */ -static int writeline(const char *buf, int len, netbuf *nData) +static long writeline(const char *buf, long len, netbuf *nData) { int x, nb=0, w; const char *ubp = buf; @@ -844,7 +844,7 @@ GLOBALDEF int FtpLogin(const char *user, const char *pass, netbuf *nControl) { char tempbuf[64]; - if (((strlen(user) + 7) > sizeof(tempbuf)) || + if (((strlen(user) + 7) > sizeof(tempbuf)) || ((strlen(pass) + 7) > sizeof(tempbuf))) return 0; sprintf(tempbuf,"USER %s",user); @@ -1161,9 +1161,9 @@ GLOBALDEF int FtpAccess(const char *path, int typ, int mode, netbuf *nControl, /* * FtpRead - read from a data connection */ -GLOBALDEF int FtpRead(void *buf, int max, netbuf *nData) +GLOBALDEF long FtpRead(void *buf, int max, netbuf *nData) { - int i; + long i; if (nData->dir != FTPLIB_READ) return 0; if (nData->buf) @@ -1194,9 +1194,9 @@ GLOBALDEF int FtpRead(void *buf, int max, netbuf *nData) /* * FtpWrite - write to a data connection */ -GLOBALDEF int FtpWrite(const void *buf, int len, netbuf *nData) +GLOBALDEF long FtpWrite(const void *buf, long len, netbuf *nData) { - int i; + long i; if (nData->dir != FTPLIB_WRITE) return 0; if (nData->buf) @@ -1397,7 +1397,7 @@ GLOBALDEF int FtpPwd(char *path, int max, netbuf *nControl) static int FtpXfer(const char *localfile, const char *path, netbuf *nControl, int typ, int mode) { - int l,c; + long l,c; char *dbuf; FILE *local = NULL; netbuf *nData; @@ -1440,7 +1440,7 @@ static int FtpXfer(const char *localfile, const char *path, { if ((c = FtpWrite(dbuf, l, nData)) < l) { - printf("short write: passed %d, wrote %d\n", l, c); + printf("short write: passed %ld, wrote %ld\n", l, c); rv = 0; break; } diff --git a/Libraries/include/ftplib/src/ftplib.h b/Libraries/include/ftplib/src/ftplib.h index 7f9616a..a2625d7 100644 --- a/Libraries/include/ftplib/src/ftplib.h +++ b/Libraries/include/ftplib/src/ftplib.h @@ -87,8 +87,8 @@ GLOBALREF int FtpSetCallback(const FtpCallbackOptions *opt, netbuf *nControl); GLOBALREF int FtpClearCallback(netbuf *nControl); GLOBALREF int FtpLogin(const char *user, const char *pass, netbuf *nControl); GLOBALREF int FtpAccess(const char *path, int typ, int mode, netbuf *nControl, netbuf **nData); -GLOBALREF int FtpRead(void *buf, int max, netbuf *nData); -GLOBALREF int FtpWrite(const void *buf, int len, netbuf *nData); +GLOBALREF long FtpRead(void *buf, int max, netbuf *nData); +GLOBALREF long FtpWrite(const void *buf, long len, netbuf *nData); GLOBALREF int FtpClose(netbuf *nData); GLOBALREF int FtpSite(const char *cmd, netbuf *nControl); GLOBALREF int FtpSysType(char *buf, int max, netbuf *nControl); diff --git a/MobileFTPKit/Info.plist b/MobileFTPKit/Info.plist new file mode 100644 index 0000000..1007fd9 --- /dev/null +++ b/MobileFTPKit/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/MobileFTPKit/MobileFTPKit.h b/MobileFTPKit/MobileFTPKit.h new file mode 100644 index 0000000..ba84477 --- /dev/null +++ b/MobileFTPKit/MobileFTPKit.h @@ -0,0 +1,19 @@ +// +// MobileFTPKit.h +// MobileFTPKit +// +// Created by ssb on 29.12.17. +// Copyright © 2017 Upstart Illustration LLC. All rights reserved. +// + +#import + +//! Project version number for MobileFTPKit. +FOUNDATION_EXPORT double MobileFTPKitVersionNumber; + +//! Project version string for MobileFTPKit. +FOUNDATION_EXPORT const unsigned char MobileFTPKitVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + +#import "FTPKit.h" diff --git a/TVFTPKit/Info.plist b/TVFTPKit/Info.plist new file mode 100644 index 0000000..1007fd9 --- /dev/null +++ b/TVFTPKit/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/TVFTPKit/TVFTPKit.h b/TVFTPKit/TVFTPKit.h new file mode 100644 index 0000000..42098bd --- /dev/null +++ b/TVFTPKit/TVFTPKit.h @@ -0,0 +1,19 @@ +// +// TVFTPKit.h +// TVFTPKit +// +// Created by ssb on 07.12.17. +// Copyright © 2017 Upstart Illustration LLC. All rights reserved. +// + +#import + +//! Project version number for TVFTPKit. +FOUNDATION_EXPORT double TVFTPKitVersionNumber; + +//! Project version string for TVFTPKit. +FOUNDATION_EXPORT const unsigned char TVFTPKitVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + +#import "FTPKit.h"