diff --git a/Socket.IO-Client-Swift.xcodeproj/project.pbxproj b/Socket.IO-Client-Swift.xcodeproj/project.pbxproj index 7d543f1..fd05fde 100644 --- a/Socket.IO-Client-Swift.xcodeproj/project.pbxproj +++ b/Socket.IO-Client-Swift.xcodeproj/project.pbxproj @@ -127,12 +127,9 @@ 74BC45AD1D0C6675008CC431 /* SocketClientManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74BC45AA1D0C6675008CC431 /* SocketClientManager.swift */; }; 74F124F01BC574CF002966F4 /* SocketBasicPacketTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74F124EF1BC574CF002966F4 /* SocketBasicPacketTest.swift */; }; 74F124F11BC574CF002966F4 /* SocketBasicPacketTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74F124EF1BC574CF002966F4 /* SocketBasicPacketTest.swift */; }; - CEBA56961CDA0B7700BA0389 /* NSCharacterSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBA56951CDA0B7700BA0389 /* NSCharacterSet.swift */; }; - CEBA56971CDA0B7700BA0389 /* NSCharacterSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBA56951CDA0B7700BA0389 /* NSCharacterSet.swift */; }; - CEBA56981CDA0B7700BA0389 /* NSCharacterSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBA56951CDA0B7700BA0389 /* NSCharacterSet.swift */; }; - CEBA569A1CDA0B8200BA0389 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBA56991CDA0B8200BA0389 /* String.swift */; }; - CEBA569B1CDA0B8200BA0389 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBA56991CDA0B8200BA0389 /* String.swift */; }; - CEBA569C1CDA0B8200BA0389 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBA56991CDA0B8200BA0389 /* String.swift */; }; + CEBA569A1CDA0B8200BA0389 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBA56991CDA0B8200BA0389 /* Extensions.swift */; }; + CEBA569B1CDA0B8200BA0389 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBA56991CDA0B8200BA0389 /* Extensions.swift */; }; + CEBA569C1CDA0B8200BA0389 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBA56991CDA0B8200BA0389 /* Extensions.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -200,8 +197,7 @@ 74B4AD201D09A6190062A523 /* SSLSecurity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SSLSecurity.swift; path = Source/WebSocket/SSLSecurity.swift; sourceTree = ""; }; 74BC45AA1D0C6675008CC431 /* SocketClientManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketClientManager.swift; path = Source/SocketClientManager.swift; sourceTree = ""; }; 74F124EF1BC574CF002966F4 /* SocketBasicPacketTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketBasicPacketTest.swift; sourceTree = ""; }; - CEBA56951CDA0B7700BA0389 /* NSCharacterSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NSCharacterSet.swift; path = Source/NSCharacterSet.swift; sourceTree = ""; }; - CEBA56991CDA0B8200BA0389 /* String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = String.swift; path = Source/String.swift; sourceTree = ""; }; + CEBA56991CDA0B8200BA0389 /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Extensions.swift; path = Source/Extensions.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -375,8 +371,7 @@ CEBA569E1CDA0C0C00BA0389 /* utils */ = { isa = PBXGroup; children = ( - CEBA56951CDA0B7700BA0389 /* NSCharacterSet.swift */, - CEBA56991CDA0B8200BA0389 /* String.swift */, + CEBA56991CDA0B8200BA0389 /* Extensions.swift */, ); name = utils; sourceTree = ""; @@ -616,12 +611,11 @@ files = ( 740CA1221C496EF700CB98F4 /* SocketEngineWebsocket.swift in Sources */, 74171EA51C10CD240062D398 /* SocketIOClientStatus.swift in Sources */, - CEBA569A1CDA0B8200BA0389 /* String.swift in Sources */, + CEBA569A1CDA0B8200BA0389 /* Extensions.swift in Sources */, 74B4AD1D1D09A5D80062A523 /* WebSocket.swift in Sources */, 74171E751C10CD240062D398 /* SocketEngine.swift in Sources */, 74171E691C10CD240062D398 /* SocketAckManager.swift in Sources */, 7420CB791C49629E00956AA4 /* SocketEnginePollable.swift in Sources */, - CEBA56961CDA0B7700BA0389 /* NSCharacterSet.swift in Sources */, 74ABF7771C3991C10078C657 /* SocketIOClientSpec.swift in Sources */, 74171E871C10CD240062D398 /* SocketEngineSpec.swift in Sources */, 74171E631C10CD240062D398 /* SocketAckEmitter.swift in Sources */, @@ -675,11 +669,10 @@ 74B4AD241D09A6450062A523 /* WebSocket.swift in Sources */, 740CA1211C496EF200CB98F4 /* SocketEngineWebsocket.swift in Sources */, 7471CCEA1C39926300364B59 /* SocketIOClientSpec.swift in Sources */, - CEBA569B1CDA0B8200BA0389 /* String.swift in Sources */, + CEBA569B1CDA0B8200BA0389 /* Extensions.swift in Sources */, 74171EA71C10CD240062D398 /* SocketIOClientStatus.swift in Sources */, 74171E771C10CD240062D398 /* SocketEngine.swift in Sources */, 7420CB7A1C49629E00956AA4 /* SocketEnginePollable.swift in Sources */, - CEBA56971CDA0B7700BA0389 /* NSCharacterSet.swift in Sources */, 74171E6B1C10CD240062D398 /* SocketAckManager.swift in Sources */, 74171E891C10CD240062D398 /* SocketEngineSpec.swift in Sources */, 74171E651C10CD240062D398 /* SocketAckEmitter.swift in Sources */, @@ -721,11 +714,10 @@ 74B4AD251D09A6490062A523 /* WebSocket.swift in Sources */, 740CA1201C496EEB00CB98F4 /* SocketEngineWebsocket.swift in Sources */, 7471CCEB1C39926C00364B59 /* SocketIOClientSpec.swift in Sources */, - CEBA569C1CDA0B8200BA0389 /* String.swift in Sources */, + CEBA569C1CDA0B8200BA0389 /* Extensions.swift in Sources */, 74171EA91C10CD240062D398 /* SocketIOClientStatus.swift in Sources */, 74171E791C10CD240062D398 /* SocketEngine.swift in Sources */, 7420CB7B1C49629E00956AA4 /* SocketEnginePollable.swift in Sources */, - CEBA56981CDA0B7700BA0389 /* NSCharacterSet.swift in Sources */, 74171E6D1C10CD240062D398 /* SocketAckManager.swift in Sources */, 74171E8B1C10CD240062D398 /* SocketEngineSpec.swift in Sources */, 74171E671C10CD240062D398 /* SocketAckEmitter.swift in Sources */, diff --git a/Source/Extensions.swift b/Source/Extensions.swift new file mode 100644 index 0000000..6da96fd --- /dev/null +++ b/Source/Extensions.swift @@ -0,0 +1,68 @@ +// +// Extensions.swift +// Socket.IO-Client-Swift +// +// Created by Erik Little on 7/1/2016. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +enum JSONError : ErrorType { + case notArray + case notNSDictionary +} + +extension Array where Element: AnyObject { + func toJSON() throws -> NSData { + return try NSJSONSerialization.dataWithJSONObject(self as NSArray, options: NSJSONWritingOptions(rawValue: 0)) + } +} + +extension NSCharacterSet { + class var allowedURLCharacterSet: NSCharacterSet { + return NSCharacterSet(charactersInString: "!*'();:@&=+$,/?%#[]\" {}").invertedSet + } +} + +extension String { + func toArray() throws -> [AnyObject] { + guard let stringData = dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) else { return [] } + + guard let array = try NSJSONSerialization.JSONObjectWithData(stringData, options: .MutableContainers) as? [AnyObject] else { + throw JSONError.notArray + } + + return array + } + + func toNSDictionary() throws -> NSDictionary { + let binData = dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)! + + guard let json = try NSJSONSerialization.JSONObjectWithData(binData, options: .AllowFragments) as? NSDictionary else { + throw JSONError.notNSDictionary + } + + return json + } + + func urlEncode() -> String? { + return stringByAddingPercentEncodingWithAllowedCharacters(.allowedURLCharacterSet) + } +} diff --git a/Source/NSCharacterSet.swift b/Source/NSCharacterSet.swift deleted file mode 100644 index 3ccde2c..0000000 --- a/Source/NSCharacterSet.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// NSCharacterSet.swift -// Socket.IO-Client-Swift -// -// Created by Yannick Loriot on 5/4/16. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import Foundation - -extension NSCharacterSet { - class var allowedURLCharacterSet: NSCharacterSet { - return NSCharacterSet(charactersInString: "!*'();:@&=+$,/?%#[]\" {}").invertedSet - } -} diff --git a/Source/SocketEngine.swift b/Source/SocketEngine.swift index c6244e0..8630529 100644 --- a/Source/SocketEngine.swift +++ b/Source/SocketEngine.swift @@ -131,21 +131,17 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe } private func checkAndHandleEngineError(msg: String) { - guard let stringData = msg.dataUsingEncoding(NSUTF8StringEncoding, - allowLossyConversion: false) else { return } - do { - if let dict = try NSJSONSerialization.JSONObjectWithData(stringData, options: .MutableContainers) as? NSDictionary { - guard let error = dict["message"] as? String else { return } - - /* - 0: Unknown transport - 1: Unknown sid - 2: Bad handshake request - 3: Bad request - */ - didError(error) - } + let dict = try msg.toNSDictionary() + guard let error = dict["message"] as? String else { return } + + /* + 0: Unknown transport + 1: Unknown sid + 2: Bad handshake request + 3: Bad request + */ + didError(error) } catch { client?.engineDidError("Got unknown error from server \(msg)") } @@ -363,23 +359,22 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe } private func handleOpen(openData: String) { - let mesData = openData.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)! do { - let json = try NSJSONSerialization.JSONObjectWithData(mesData, - options: NSJSONReadingOptions.AllowFragments) as? NSDictionary - if let sid = json?["sid"] as? String { + let json = try openData.toNSDictionary() + + if let sid = json["sid"] as? String { let upgradeWs: Bool self.sid = sid connected = true - if let upgrades = json?["upgrades"] as? [String] { + if let upgrades = json["upgrades"] as? [String] { upgradeWs = upgrades.contains("websocket") } else { upgradeWs = false } - if let pingInterval = json?["pingInterval"] as? Double, pingTimeout = json?["pingTimeout"] as? Double { + if let pingInterval = json["pingInterval"] as? Double, pingTimeout = json["pingTimeout"] as? Double { self.pingInterval = pingInterval / 1000.0 self.pingTimeout = pingTimeout / 1000.0 } diff --git a/Source/SocketPacket.swift b/Source/SocketPacket.swift index 47bebed..5105333 100644 --- a/Source/SocketPacket.swift +++ b/Source/SocketPacket.swift @@ -94,11 +94,9 @@ struct SocketPacket { } do { - let jsonSend = try NSJSONSerialization.dataWithJSONObject(data, - options: NSJSONWritingOptions(rawValue: 0)) - guard let jsonString = String(data: jsonSend, encoding: NSUTF8StringEncoding) else { - return message + "[]" - } + let jsonSend = try data.toJSON() + + guard let jsonString = String(data: jsonSend, encoding: NSUTF8StringEncoding) else { return message + "[]" } restOfMessage = jsonString } catch { diff --git a/Source/SocketParsable.swift b/Source/SocketParsable.swift index 577722a..47ff845 100644 --- a/Source/SocketParsable.swift +++ b/Source/SocketParsable.swift @@ -126,15 +126,8 @@ extension SocketParsable { // Parses data for events private func parseData(data: String) -> Either { - let stringData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) - do { - if let arr = try NSJSONSerialization.JSONObjectWithData(stringData!, - options: NSJSONReadingOptions.MutableContainers) as? [AnyObject] { - return .Right(arr) - } else { - return .Left("Expected data array") - } + return .Right(try data.toArray()) } catch { return .Left("Error parsing data for packet") } diff --git a/Source/String.swift b/Source/String.swift deleted file mode 100644 index 0e30e8c..0000000 --- a/Source/String.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// String.swift -// Socket.IO-Client-Swift -// -// Created by Yannick Loriot on 5/4/16. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import Foundation - -extension String { - func urlEncode() -> String? { - return stringByAddingPercentEncodingWithAllowedCharacters(.allowedURLCharacterSet) - } -}