Explorar o código

Fixed compilation error happening on "ipad ios 9.2 - https://github.com/glock45/swifter/issues/101".
Current tests moved to "SwifterTestsCommon" directory. Added test target for iOS.

Damian Kołakowski %!s(int64=10) %!d(string=hai) anos
pai
achega
b070d440ad

+ 5 - 5
Sources/String+SHA1.swift

@@ -24,11 +24,11 @@ extension String {
         
         var message = [UInt8](self.utf8)
         
-        var h0 = UInt32(0x67452301)
-        var h1 = UInt32(0xEFCDAB89)
-        var h2 = UInt32(0x98BADCFE)
-        var h3 = UInt32(0x10325476)
-        var h4 = UInt32(0xC3D2E1F0)
+        var h0 = UInt32(littleEndian: 0x67452301)
+        var h1 = UInt32(littleEndian: 0xEFCDAB89)
+        var h2 = UInt32(littleEndian: 0x98BADCFE)
+        var h3 = UInt32(littleEndian: 0x10325476)
+        var h4 = UInt32(littleEndian: 0xC3D2E1F0)
         
         // ml = message length in bits (always a multiple of the number of bits in a character).
         

+ 0 - 0
SwifterTests/SwifterTestsHttpParser.swift → Sources/SwifterTestsCommon/SwifterTestsHttpParser.swift


+ 0 - 0
SwifterTests/SwifterTestsStringExtensions.swift → Sources/SwifterTestsCommon/SwifterTestsStringExtensions.swift


+ 235 - 116
Swifter.xcodeproj/project.pbxproj

@@ -15,8 +15,6 @@
 		7C2BEC781C518B7C00B8EE90 /* String+SHA1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C2BEC771C518B7C00B8EE90 /* String+SHA1.swift */; };
 		7C2BEC791C5195EE00B8EE90 /* String+SHA1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C2BEC771C518B7C00B8EE90 /* String+SHA1.swift */; };
 		7C2BEC7A1C5195F200B8EE90 /* String+SHA1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C2BEC771C518B7C00B8EE90 /* String+SHA1.swift */; };
-		7C6EC0831C614051005A49B3 /* SwifterTestsStringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C6EC0821C614051005A49B3 /* SwifterTestsStringExtensions.swift */; };
-		7C6EC0851C614051005A49B3 /* Swifter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AE893FB1C0512C400A29F63 /* Swifter.framework */; };
 		7C71C5B01A1D52F800682BF0 /* login.html in CopyFiles */ = {isa = PBXBuildFile; fileRef = 98630C061A1C9A9D00478D08 /* login.html */; };
 		7C71C5B11A1EC49B00682BF0 /* logo.png in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7CB102DF1A17381D00CBA3B4 /* logo.png */; };
 		7C73C6911C2615FE00AEF6CA /* SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18E610A51BD6397D00B7D17A /* SwiftyJSON.swift */; };
@@ -47,11 +45,16 @@
 		7CA4815819A2EF2B0030B30D /* test.json in Resources */ = {isa = PBXBuildFile; fileRef = 7CA4815719A2EF2B0030B30D /* test.json */; };
 		7CA4815919A2EF560030B30D /* test.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7CA4815719A2EF2B0030B30D /* test.json */; };
 		7CB102E01A17381D00CBA3B4 /* logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 7CB102DF1A17381D00CBA3B4 /* logo.png */; };
-		7CB15EC71C6144BA004E0FF3 /* SwifterTestsHttpParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CB15EC61C6144BA004E0FF3 /* SwifterTestsHttpParser.swift */; };
 		7CC0F8C91C50136B00B65A94 /* HttpHandlers+Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC0F8C81C50136B00B65A94 /* HttpHandlers+Files.swift */; };
 		7CC0F8CA1C50136B00B65A94 /* HttpHandlers+Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC0F8C81C50136B00B65A94 /* HttpHandlers+Files.swift */; };
 		7CC0F8CC1C5014A200B65A94 /* HttpHandlers+WebSockets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC0F8CB1C5014A200B65A94 /* HttpHandlers+WebSockets.swift */; };
 		7CC0F8CD1C5014A200B65A94 /* HttpHandlers+WebSockets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC0F8CB1C5014A200B65A94 /* HttpHandlers+WebSockets.swift */; };
+		7CCD87611C66099B0068099B /* Swifter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AE893E71C05127900A29F63 /* Swifter.framework */; };
+		7CCD87701C660B250068099B /* SwifterTestsHttpParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CCD876D1C660B250068099B /* SwifterTestsHttpParser.swift */; };
+		7CCD87721C660B250068099B /* SwifterTestsStringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CCD876E1C660B250068099B /* SwifterTestsStringExtensions.swift */; };
+		7CCD877E1C660EA30068099B /* Swifter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AE893FB1C0512C400A29F63 /* Swifter.framework */; };
+		7CCD87841C660ED60068099B /* SwifterTestsHttpParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CCD876D1C660B250068099B /* SwifterTestsHttpParser.swift */; };
+		7CCD87851C660ED60068099B /* SwifterTestsStringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CCD876E1C660B250068099B /* SwifterTestsStringExtensions.swift */; };
 		7CDAB8131BE2A1D400C8A977 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7CDAB80D1BE2A1D400C8A977 /* Main.storyboard */; };
 		7CDAB8141BE2A1D400C8A977 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7CDAB80F1BE2A1D400C8A977 /* Images.xcassets */; };
 		7CDAB8161BE2A1D400C8A977 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CDAB8111BE2A1D400C8A977 /* ViewController.swift */; };
@@ -66,20 +69,27 @@
 			remoteGlobalIDString = 7AE893FA1C0512C400A29F63;
 			remoteInfo = SwifterMac;
 		};
-		7C6EC0861C614051005A49B3 /* PBXContainerItemProxy */ = {
+		7C73C6BF1C261AA700AEF6CA /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 7C839B6619422CFF003A6950 /* Project object */;
 			proxyType = 1;
-			remoteGlobalIDString = 7AE893FA1C0512C400A29F63;
-			remoteInfo = SwifterMac;
+			remoteGlobalIDString = 7AE893E61C05127900A29F63;
+			remoteInfo = SwifteriOS;
 		};
-		7C73C6BF1C261AA700AEF6CA /* PBXContainerItemProxy */ = {
+		7CCD87621C66099B0068099B /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 7C839B6619422CFF003A6950 /* Project object */;
 			proxyType = 1;
 			remoteGlobalIDString = 7AE893E61C05127900A29F63;
 			remoteInfo = SwifteriOS;
 		};
+		7CCD877F1C660EA30068099B /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 7C839B6619422CFF003A6950 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 7AE893FA1C0512C400A29F63;
+			remoteInfo = SwifterMac;
+		};
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXCopyFilesBuildPhase section */
@@ -109,9 +119,6 @@
 		7AE8940C1C05151100A29F63 /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
 		7C1A2BFA1C5605F50026D3BF /* String+BASE64.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+BASE64.swift"; sourceTree = "<group>"; };
 		7C2BEC771C518B7C00B8EE90 /* String+SHA1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+SHA1.swift"; sourceTree = "<group>"; };
-		7C6EC0801C614051005A49B3 /* SwifterTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwifterTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
-		7C6EC0821C614051005A49B3 /* SwifterTestsStringExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwifterTestsStringExtensions.swift; sourceTree = "<group>"; };
-		7C6EC0841C614051005A49B3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		7C73C6941C2619E100AEF6CA /* DemoServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DemoServer.swift; sourceTree = "<group>"; };
 		7C73C6951C2619E100AEF6CA /* HttpHandlers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HttpHandlers.swift; sourceTree = "<group>"; };
 		7C73C6961C2619E100AEF6CA /* HttpParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HttpParser.swift; sourceTree = "<group>"; };
@@ -128,9 +135,14 @@
 		7CA4813D19A2EA8D0030B30D /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
 		7CA4815719A2EF2B0030B30D /* test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = test.json; sourceTree = "<group>"; };
 		7CB102DF1A17381D00CBA3B4 /* logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logo.png; sourceTree = "<group>"; };
-		7CB15EC61C6144BA004E0FF3 /* SwifterTestsHttpParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsHttpParser.swift; sourceTree = "<group>"; };
 		7CC0F8C81C50136B00B65A94 /* HttpHandlers+Files.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "HttpHandlers+Files.swift"; sourceTree = "<group>"; };
 		7CC0F8CB1C5014A200B65A94 /* HttpHandlers+WebSockets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "HttpHandlers+WebSockets.swift"; sourceTree = "<group>"; };
+		7CCD875C1C66099B0068099B /* SwifteriOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwifteriOSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		7CCD87601C66099B0068099B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		7CCD876D1C660B250068099B /* SwifterTestsHttpParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsHttpParser.swift; sourceTree = "<group>"; };
+		7CCD876E1C660B250068099B /* SwifterTestsStringExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsStringExtensions.swift; sourceTree = "<group>"; };
+		7CCD87791C660EA30068099B /* SwifterOSXTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwifterOSXTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		7CCD877D1C660EA30068099B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		7CDAB80C1BE2A1D400C8A977 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		7CDAB80E1BE2A1D400C8A977 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
 		7CDAB80F1BE2A1D400C8A977 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
@@ -155,25 +167,33 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		7C6EC07D1C614051005A49B3 /* Frameworks */ = {
+		7C839B6B19422CFF003A6950 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				7C6EC0851C614051005A49B3 /* Swifter.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		7C839B6B19422CFF003A6950 /* Frameworks */ = {
+		7CA4813819A2EA8D0030B30D /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		7CA4813819A2EA8D0030B30D /* Frameworks */ = {
+		7CCD87591C66099B0068099B /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				7CCD87611C66099B0068099B /* Swifter.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7CCD87761C660EA30068099B /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				7CCD877E1C660EA30068099B /* Swifter.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -198,28 +218,20 @@
 			path = SwifterMac;
 			sourceTree = "<group>";
 		};
-		7C6EC0811C614051005A49B3 /* SwifterTests */ = {
-			isa = PBXGroup;
-			children = (
-				7CB15EC61C6144BA004E0FF3 /* SwifterTestsHttpParser.swift */,
-				7C6EC0821C614051005A49B3 /* SwifterTestsStringExtensions.swift */,
-				7C6EC0841C614051005A49B3 /* Info.plist */,
-			);
-			path = SwifterTests;
-			sourceTree = "<group>";
-		};
 		7C839B6519422CFF003A6950 = {
 			isa = PBXGroup;
 			children = (
 				7CEAF86F1C14B2B5003252DE /* Package.swift */,
+				7CA4815619A2EF2B0030B30D /* Resources */,
 				7CEAF84A1C14B29B003252DE /* Sources */,
-				7C6EC0811C614051005A49B3 /* SwifterTests */,
+				7CCD876C1C660B250068099B /* SwifterTestsCommon */,
+				7CCD875D1C66099B0068099B /* SwifteriOSTests */,
+				7CCD877A1C660EA30068099B /* SwifterOSXTests */,
 				7C839B6F19422CFF003A6950 /* Products */,
-				7CA4815619A2EF2B0030B30D /* Resources */,
 				7AE893FC1C0512C400A29F63 /* SwifterMac */,
+				7AE893E81C05127900A29F63 /* SwifteriOS */,
 				7CA4813C19A2EA8D0030B30D /* SwifterSampleOSX */,
 				7CDAB80B1BE2A1D400C8A977 /* SwifterSampleiOS */,
-				7AE893E81C05127900A29F63 /* SwifteriOS */,
 			);
 			sourceTree = "<group>";
 		};
@@ -230,7 +242,8 @@
 				7CA4813B19A2EA8D0030B30D /* SwifterSampleOSX */,
 				7AE893E71C05127900A29F63 /* Swifter.framework */,
 				7AE893FB1C0512C400A29F63 /* Swifter.framework */,
-				7C6EC0801C614051005A49B3 /* SwifterTests.xctest */,
+				7CCD875C1C66099B0068099B /* SwifteriOSTests.xctest */,
+				7CCD87791C660EA30068099B /* SwifterOSXTests.xctest */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -255,6 +268,31 @@
 			path = Resources;
 			sourceTree = "<group>";
 		};
+		7CCD875D1C66099B0068099B /* SwifteriOSTests */ = {
+			isa = PBXGroup;
+			children = (
+				7CCD87601C66099B0068099B /* Info.plist */,
+			);
+			path = SwifteriOSTests;
+			sourceTree = "<group>";
+		};
+		7CCD876C1C660B250068099B /* SwifterTestsCommon */ = {
+			isa = PBXGroup;
+			children = (
+				7CCD876D1C660B250068099B /* SwifterTestsHttpParser.swift */,
+				7CCD876E1C660B250068099B /* SwifterTestsStringExtensions.swift */,
+			);
+			path = SwifterTestsCommon;
+			sourceTree = "<group>";
+		};
+		7CCD877A1C660EA30068099B /* SwifterOSXTests */ = {
+			isa = PBXGroup;
+			children = (
+				7CCD877D1C660EA30068099B /* Info.plist */,
+			);
+			path = SwifterOSXTests;
+			sourceTree = "<group>";
+		};
 		7CDAB80B1BE2A1D400C8A977 /* SwifterSampleiOS */ = {
 			isa = PBXGroup;
 			children = (
@@ -347,24 +385,6 @@
 			productReference = 7AE893FB1C0512C400A29F63 /* Swifter.framework */;
 			productType = "com.apple.product-type.framework";
 		};
-		7C6EC07F1C614051005A49B3 /* SwifterTests */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 7C6EC0881C614051005A49B3 /* Build configuration list for PBXNativeTarget "SwifterTests" */;
-			buildPhases = (
-				7C6EC07C1C614051005A49B3 /* Sources */,
-				7C6EC07D1C614051005A49B3 /* Frameworks */,
-				7C6EC07E1C614051005A49B3 /* Resources */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-				7C6EC0871C614051005A49B3 /* PBXTargetDependency */,
-			);
-			name = SwifterTests;
-			productName = SwifterTests;
-			productReference = 7C6EC0801C614051005A49B3 /* SwifterTests.xctest */;
-			productType = "com.apple.product-type.bundle.unit-test";
-		};
 		7C839B6D19422CFF003A6950 /* SwifterSampleiOS */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = 7C839B8A19422D00003A6950 /* Build configuration list for PBXNativeTarget "SwifterSampleiOS" */;
@@ -401,6 +421,42 @@
 			productReference = 7CA4813B19A2EA8D0030B30D /* SwifterSampleOSX */;
 			productType = "com.apple.product-type.tool";
 		};
+		7CCD875B1C66099B0068099B /* SwifteriOSTests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 7CCD87641C66099B0068099B /* Build configuration list for PBXNativeTarget "SwifteriOSTests" */;
+			buildPhases = (
+				7CCD87581C66099B0068099B /* Sources */,
+				7CCD87591C66099B0068099B /* Frameworks */,
+				7CCD875A1C66099B0068099B /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				7CCD87631C66099B0068099B /* PBXTargetDependency */,
+			);
+			name = SwifteriOSTests;
+			productName = SwifteriOSTests;
+			productReference = 7CCD875C1C66099B0068099B /* SwifteriOSTests.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
+		7CCD87781C660EA30068099B /* SwifterOSXTests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 7CCD87811C660EA30068099B /* Build configuration list for PBXNativeTarget "SwifterOSXTests" */;
+			buildPhases = (
+				7CCD87751C660EA30068099B /* Sources */,
+				7CCD87761C660EA30068099B /* Frameworks */,
+				7CCD87771C660EA30068099B /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				7CCD87801C660EA30068099B /* PBXTargetDependency */,
+			);
+			name = SwifterOSXTests;
+			productName = SwifterOSXTests;
+			productReference = 7CCD87791C660EA30068099B /* SwifterOSXTests.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
 /* End PBXNativeTarget section */
 
 /* Begin PBXProject section */
@@ -417,15 +473,18 @@
 					7AE893FA1C0512C400A29F63 = {
 						CreatedOnToolsVersion = 7.1;
 					};
-					7C6EC07F1C614051005A49B3 = {
-						CreatedOnToolsVersion = 7.2;
-					};
 					7C839B6D19422CFF003A6950 = {
 						CreatedOnToolsVersion = 6.0;
 					};
 					7CA4813A19A2EA8D0030B30D = {
 						CreatedOnToolsVersion = 6.0;
 					};
+					7CCD875B1C66099B0068099B = {
+						CreatedOnToolsVersion = 7.2;
+					};
+					7CCD87781C660EA30068099B = {
+						CreatedOnToolsVersion = 7.2;
+					};
 				};
 			};
 			buildConfigurationList = 7C839B6919422CFF003A6950 /* Build configuration list for PBXProject "Swifter" */;
@@ -445,7 +504,8 @@
 				7CA4813A19A2EA8D0030B30D /* SwifterSampleOSX */,
 				7AE893E61C05127900A29F63 /* SwifteriOS */,
 				7AE893FA1C0512C400A29F63 /* SwifterMac */,
-				7C6EC07F1C614051005A49B3 /* SwifterTests */,
+				7CCD875B1C66099B0068099B /* SwifteriOSTests */,
+				7CCD87781C660EA30068099B /* SwifterOSXTests */,
 			);
 		};
 /* End PBXProject section */
@@ -465,13 +525,6 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		7C6EC07E1C614051005A49B3 /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 		7C839B6C19422CFF003A6950 /* Resources */ = {
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -486,6 +539,20 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		7CCD875A1C66099B0068099B /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7CCD87771C660EA30068099B /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
@@ -531,15 +598,6 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		7C6EC07C1C614051005A49B3 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				7C6EC0831C614051005A49B3 /* SwifterTestsStringExtensions.swift in Sources */,
-				7CB15EC71C6144BA004E0FF3 /* SwifterTestsHttpParser.swift in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 		7C839B6A19422CFF003A6950 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -559,6 +617,24 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		7CCD87581C66099B0068099B /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				7CCD87701C660B250068099B /* SwifterTestsHttpParser.swift in Sources */,
+				7CCD87721C660B250068099B /* SwifterTestsStringExtensions.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7CCD87751C660EA30068099B /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				7CCD87841C660ED60068099B /* SwifterTestsHttpParser.swift in Sources */,
+				7CCD87851C660ED60068099B /* SwifterTestsStringExtensions.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXSourcesBuildPhase section */
 
 /* Begin PBXTargetDependency section */
@@ -567,16 +643,21 @@
 			target = 7AE893FA1C0512C400A29F63 /* SwifterMac */;
 			targetProxy = 7AE8940E1C0515A200A29F63 /* PBXContainerItemProxy */;
 		};
-		7C6EC0871C614051005A49B3 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 7AE893FA1C0512C400A29F63 /* SwifterMac */;
-			targetProxy = 7C6EC0861C614051005A49B3 /* PBXContainerItemProxy */;
-		};
 		7C73C6C01C261AA700AEF6CA /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
 			target = 7AE893E61C05127900A29F63 /* SwifteriOS */;
 			targetProxy = 7C73C6BF1C261AA700AEF6CA /* PBXContainerItemProxy */;
 		};
+		7CCD87631C66099B0068099B /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 7AE893E61C05127900A29F63 /* SwifteriOS */;
+			targetProxy = 7CCD87621C66099B0068099B /* PBXContainerItemProxy */;
+		};
+		7CCD87801C660EA30068099B /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 7AE893FA1C0512C400A29F63 /* SwifterMac */;
+			targetProxy = 7CCD877F1C660EA30068099B /* PBXContainerItemProxy */;
+		};
 /* End PBXTargetDependency section */
 
 /* Begin PBXVariantGroup section */
@@ -694,41 +775,6 @@
 			};
 			name = Release;
 		};
-		7C6EC0891C614051005A49B3 /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
-				COMBINE_HIDPI_IMAGES = YES;
-				DEBUG_INFORMATION_FORMAT = dwarf;
-				GCC_NO_COMMON_BLOCKS = YES;
-				INFOPLIST_FILE = SwifterTests/Info.plist;
-				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
-				MACOSX_DEPLOYMENT_TARGET = 10.11;
-				MTL_ENABLE_DEBUG_INFO = YES;
-				PRODUCT_BUNDLE_IDENTIFIER = pl.kolakowski.SwifterTests;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SDKROOT = macosx;
-			};
-			name = Debug;
-		};
-		7C6EC08A1C614051005A49B3 /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CODE_SIGN_IDENTITY = "-";
-				COMBINE_HIDPI_IMAGES = YES;
-				COPY_PHASE_STRIP = NO;
-				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
-				GCC_NO_COMMON_BLOCKS = YES;
-				INFOPLIST_FILE = SwifterTests/Info.plist;
-				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
-				MACOSX_DEPLOYMENT_TARGET = 10.11;
-				MTL_ENABLE_DEBUG_INFO = NO;
-				PRODUCT_BUNDLE_IDENTIFIER = pl.kolakowski.SwifterTests;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SDKROOT = macosx;
-			};
-			name = Release;
-		};
 		7C839B8819422D00003A6950 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -878,6 +924,70 @@
 			};
 			name = Release;
 		};
+		7CCD87651C66099B0068099B /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = SwifteriOSTests/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.2;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MTL_ENABLE_DEBUG_INFO = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = pl.kolakowski.SwifteriOSTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		7CCD87661C66099B0068099B /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = SwifteriOSTests/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.2;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MTL_ENABLE_DEBUG_INFO = NO;
+				PRODUCT_BUNDLE_IDENTIFIER = pl.kolakowski.SwifteriOSTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+		7CCD87821C660EA30068099B /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CODE_SIGN_IDENTITY = "-";
+				COMBINE_HIDPI_IMAGES = YES;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = SwifterOSXTests/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+				MACOSX_DEPLOYMENT_TARGET = 10.11;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = pl.kolakowski.SwifterOSXTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		7CCD87831C660EA30068099B /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CODE_SIGN_IDENTITY = "-";
+				COMBINE_HIDPI_IMAGES = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = SwifterOSXTests/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+				MACOSX_DEPLOYMENT_TARGET = 10.11;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				PRODUCT_BUNDLE_IDENTIFIER = pl.kolakowski.SwifterOSXTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
@@ -899,15 +1009,6 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
-		7C6EC0881C614051005A49B3 /* Build configuration list for PBXNativeTarget "SwifterTests" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				7C6EC0891C614051005A49B3 /* Debug */,
-				7C6EC08A1C614051005A49B3 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
 		7C839B6919422CFF003A6950 /* Build configuration list for PBXProject "Swifter" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
@@ -935,6 +1036,24 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		7CCD87641C66099B0068099B /* Build configuration list for PBXNativeTarget "SwifteriOSTests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				7CCD87651C66099B0068099B /* Debug */,
+				7CCD87661C66099B0068099B /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		7CCD87811C660EA30068099B /* Build configuration list for PBXNativeTarget "SwifterOSXTests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				7CCD87821C660EA30068099B /* Debug */,
+				7CCD87831C660EA30068099B /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 /* End XCConfigurationList section */
 	};
 	rootObject = 7C839B6619422CFF003A6950 /* Project object */;

+ 19 - 4
Swifter.xcodeproj/xcuserdata/damiankolakowski.xcuserdatad/xcschemes/xcschememanagement.plist

@@ -9,6 +9,11 @@
 			<key>orderHint</key>
 			<integer>1</integer>
 		</dict>
+		<key>SwifterOSXTests.xcscheme</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>4</integer>
+		</dict>
 		<key>SwifterSampleOSX.xcscheme</key>
 		<dict>
 			<key>orderHint</key>
@@ -19,15 +24,15 @@
 			<key>orderHint</key>
 			<integer>2</integer>
 		</dict>
-		<key>SwifterTests.xcscheme</key>
+		<key>SwifteriOS.xcscheme_^#shared#^_</key>
 		<dict>
 			<key>orderHint</key>
-			<integer>4</integer>
+			<integer>0</integer>
 		</dict>
-		<key>SwifteriOS.xcscheme_^#shared#^_</key>
+		<key>SwifteriOSTests.xcscheme</key>
 		<dict>
 			<key>orderHint</key>
-			<integer>0</integer>
+			<integer>5</integer>
 		</dict>
 	</dict>
 	<key>SuppressBuildableAutocreation</key>
@@ -62,6 +67,16 @@
 			<key>primary</key>
 			<true/>
 		</dict>
+		<key>7CCD875B1C66099B0068099B</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>7CCD87781C660EA30068099B</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
 		<key>7CE581B41A36D9E300FB840F</key>
 		<dict>
 			<key>primary</key>

+ 0 - 0
SwifterTests/Info.plist → SwifterOSXTests/Info.plist


+ 106 - 0
SwifterTestsCommon/SwifterTestsHttpParser.swift

@@ -0,0 +1,106 @@
+//
+//  SwifterTests.swift
+//  SwifterTests
+//
+//  Copyright © 2016 Damian Kołakowski. All rights reserved.
+//
+
+import XCTest
+
+import Swifter
+
+class SwifterTestsHttpParser: XCTestCase {
+    
+    class TestSocket: Socket {
+        var content = [UInt8]()
+        var offset = 0
+        
+        init(_ content: String) {
+            super.init(socketFileDescriptor: -1)
+            self.content.appendContentsOf([UInt8](content.utf8))
+        }
+
+        override func read() throws -> UInt8 {
+            if offset < content.count {
+                let value = self.content[offset]
+                offset = offset + 1
+                return value
+            }
+            throw SocketError.RecvFailed("")
+        }
+    }
+    
+    func testParser() {
+        let parser = HttpParser()
+        
+        do {
+            try parser.readHttpRequest(TestSocket(""))
+            XCTAssertTrue(false, "Parser should throw an error if socket is empty.")
+        } catch { }
+
+        do {
+            try parser.readHttpRequest(TestSocket("12345678"))
+            XCTAssertTrue(false, "Parser should throw an error if status line has single token.")
+        } catch { }
+
+        do {
+            try parser.readHttpRequest(TestSocket("GET HTTP/1.0"))
+            XCTAssertTrue(false, "Parser should throw an error if status line has not enough tokens.")
+        } catch { }
+
+        do {
+            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0"))
+            XCTAssertTrue(false, "Parser should throw an error if there is no next line symbol.")
+        } catch { }
+            
+        do {
+            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0"))
+            XCTAssertTrue(false, "Parser should throw an error if there is no next line symbol.")
+        } catch { }
+        
+        do {
+            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\r"))
+            XCTAssertTrue(false, "Parser should throw an error if there is no next line symbol.")
+        } catch { }
+        
+        do {
+            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\n"))
+            XCTAssertTrue(false, "Parser should throw an error if there is no 'Content-Length' header.")
+        } catch { }
+        
+        do {
+            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\r\nContent-Length: 0\r\n\r\n"))
+        } catch {
+            XCTAssertTrue(false, "Parser should not throw any errors if there is a valid 'Content-Length' header.")
+        }
+        
+        do {
+            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\nContent-Length: 0\r\n\n"))
+        } catch {
+            XCTAssertTrue(false, "Parser should not throw any errors if there is a valid 'Content-Length' header.")
+        }
+        
+        do {
+            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\nContent-Length: 5\n\n12345"))
+        } catch {
+            XCTAssertTrue(false, "Parser should not throw any errors if there is a valid 'Content-Length' header.")
+        }
+        
+        do {
+            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\nContent-Length: 10\r\n\n"))
+            XCTAssertTrue(false, "Parser should throw an error if request' body is too short.")
+        } catch { }
+        
+        var r = try? parser.readHttpRequest(TestSocket("GET / HTTP/1.0\nContent-Length: 10\n\n1234567890"))
+        XCTAssertTrue(r?.method == "GET", "Parser should extract HTTP method name from the status line.")
+        XCTAssertTrue(r?.path == "/", "Parser should extract HTTP path value from the status line.")
+        XCTAssertTrue(r?.headers["content-length"] == "10", "Parser should extract Content-Length header value.")
+        
+        r = try? parser.readHttpRequest(TestSocket("POST / HTTP/1.0\nContent-Length: 10\n\n1234567890"))
+        XCTAssertTrue(r?.method == "POST", "Parser should extract HTTP method name from the status line.")
+        
+        r = try? parser.readHttpRequest(TestSocket("GET / HTTP/1.0\nHeader1: 1\nHeader2: 2\nContent-Length: 0\n\n"))
+        XCTAssertTrue(r?.headers["header1"] == "1", "Parser should extract multiple headers from the request.")
+        XCTAssertTrue(r?.headers["header2"] == "2", "Parser should extract multiple headers from the request.")
+    }
+}

+ 92 - 0
SwifterTestsCommon/SwifterTestsStringExtensions.swift

@@ -0,0 +1,92 @@
+//
+//  SwifterTests.swift
+//  SwifterTests
+//
+//  Copyright © 2016 Damian Kołakowski. All rights reserved.
+//
+
+import XCTest
+
+import Swifter
+
+class SwifterTestsStringExtensions: XCTestCase {
+    
+    func testSHA1() {
+        XCTAssertEqual("".SHA1(), "da39a3ee5e6b4b0d3255bfef95601890afd80709")
+        XCTAssertEqual("test".SHA1(), "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3")
+        
+        // Values copied from OpenSSL:
+        // https://github.com/openssl/openssl/blob/master/test/sha1test.c
+        
+        XCTAssertEqual("abc".SHA1(), "a9993e364706816aba3e25717850c26c9cd0d89d")
+        XCTAssertEqual("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".SHA1(),
+            "84983e441c3bd26ebaae4aa1f95129e5e54670f1")
+        
+        XCTAssertEqual(
+            ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +
+             "a9993e364706816aba3e25717850c26c9cd0d89d" +
+             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +
+             "a9993e364706816aba3e25717850c26c9cd0d89d" +
+             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +
+             "a9993e364706816aba3e25717850c26c9cd0d89d" +
+             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +
+             "a9993e364706816aba3e25717850c26c9cd0d89d" +
+             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +
+             "a9993e364706816aba3e25717850c26c9cd0d89d" +
+             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +
+             "a9993e364706816aba3e25717850c26c9cd0d89d" +
+             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq").SHA1(),
+            "a377b0c42d685fdc396e29a9eda7101d900947ca")
+    }
+    
+    func testBASE64() {
+        XCTAssertEqual(String.toBase64([UInt8]("".utf8)), "")
+        
+        // Values copied from OpenSSL:
+        // https://github.com/openssl/openssl/blob/995197ab84901df1cdf83509c4ce3511ea7f5ec0/test/evptests.txt
+        
+        XCTAssertEqual(String.toBase64([UInt8]("h".utf8)), "aA==")
+        XCTAssertEqual(String.toBase64([UInt8]("hello".utf8)), "aGVsbG8=")
+        XCTAssertEqual(String.toBase64([UInt8]("hello world!".utf8)), "aGVsbG8gd29ybGQh")
+        XCTAssertEqual(String.toBase64([UInt8]("OpenSSLOpenSSL\n".utf8)), "T3BlblNTTE9wZW5TU0wK")
+        XCTAssertEqual(String.toBase64([UInt8]("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".utf8)),
+            "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA==")
+        XCTAssertEqual(String.toBase64([UInt8]("h".utf8)), "aA==")
+    }
+    
+    func testMiscUnquote() {
+        XCTAssertEqual("".unquote(), "")
+        XCTAssertEqual("\"".unquote(), "\"")
+        XCTAssertEqual("\"\"".unquote(), "")
+        
+        XCTAssertEqual("1234".unquote(), "1234")
+        XCTAssertEqual("1234\"".unquote(), "1234\"")
+        XCTAssertEqual("\"1234".unquote(), "\"1234")
+        XCTAssertEqual("\"1234\"".unquote(), "1234")
+        XCTAssertEqual("\"1234\"".unquote(), "1234")
+        
+        XCTAssertEqual("\"\"\"".unquote(), "\"")
+        XCTAssertEqual("\"\" \"\"".unquote(), "\" \"")
+    }
+    
+    func testMiscTrim() {
+        XCTAssertEqual("".trim(), "")
+        XCTAssertEqual("\n".trim(), "")
+        XCTAssertEqual("\t".trim(), "")
+        XCTAssertEqual("\r".trim(), "")
+        XCTAssertEqual(" ".trim(), "")
+        XCTAssertEqual("      ".trim(), "")
+        XCTAssertEqual("1 test     ".trim(), "1 test")
+        XCTAssertEqual("      test          ".trim(), "test")
+        XCTAssertEqual("   \t\n\rtest          ".trim(), "test")
+        XCTAssertEqual("   \t\n\rtest  n   \n\t asd    ".trim(), "test  n   \n\t asd")
+    }
+
+    func testMiscReplace() {
+        XCTAssertEqual("".replace("+", "-"), "")
+        XCTAssertEqual("test".replace("+", "-"), "test")
+        XCTAssertEqual("+++".replace("+", "-"), "---")
+        XCTAssertEqual("t&e&s&t12%3%".replace("&", "+").replace("%", "+"), "t+e+s+t12+3+")
+        XCTAssertEqual("test 1234 #$%^&*( test   ".replace(" ", "_"), "test_1234_#$%^&*(_test___")
+    }
+}

+ 24 - 0
SwifteriOSTests/Info.plist

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>