diff --git a/.github/workflows/swiftlint.yml b/.github/workflows/swiftlint.yml index 526a758..b5e22bf 100644 --- a/.github/workflows/swiftlint.yml +++ b/.github/workflows/swiftlint.yml @@ -1,10 +1,8 @@ name: SwiftLint on: - push: - branches: [ '**' ] - pull_request_target: - branches: [ '**' ] + pull_request: + types: [opened, synchronize, reopened] workflow_dispatch: jobs: diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 3faf441..8a21704 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -1,10 +1,8 @@ name: Unit Tests on: - push: - branches: [ '**' ] - pull_request_target: - branches: [ '**' ] + pull_request: + types: [opened, synchronize, reopened] workflow_dispatch: jobs: diff --git a/Sources/NostrSDK/EventSerializer.swift b/Sources/NostrSDK/EventSerializer.swift index 0917ddb..d275d5b 100644 --- a/Sources/NostrSDK/EventSerializer.swift +++ b/Sources/NostrSDK/EventSerializer.swift @@ -31,14 +31,14 @@ public enum EventSerializer { let tagsString: String if let tagsData = try? encoder.encode(tags) { - tagsString = String(decoding: tagsData, as: UTF8.self) + tagsString = String(data: tagsData, encoding: .utf8) ?? "[]" } else { tagsString = "[]" } let contentString: String if let contentData = try? encoder.encode(content) { - contentString = String(decoding: contentData, as: UTF8.self) + contentString = String(data: contentData, encoding: .utf8) ?? "\"\"" } else { contentString = "\"\"" } diff --git a/Sources/NostrSDK/Events/BookmarksListEvent.swift b/Sources/NostrSDK/Events/BookmarksListEvent.swift index d5ae1d9..64e968a 100644 --- a/Sources/NostrSDK/Events/BookmarksListEvent.swift +++ b/Sources/NostrSDK/Events/BookmarksListEvent.swift @@ -149,8 +149,8 @@ public extension EventCreating { var encryptedContent: String? if !privateTags.isEmpty { let rawPrivateTags = privateTags.map { $0.raw } - if let unencryptedData = try? JSONSerialization.data(withJSONObject: rawPrivateTags) { - let unencryptedContent = String(decoding: unencryptedData, as: UTF8.self) + if let unencryptedData = try? JSONSerialization.data(withJSONObject: rawPrivateTags), + let unencryptedContent = String(data: unencryptedData, encoding: .utf8) { encryptedContent = try legacyEncrypt(content: unencryptedContent, privateKey: keypair.privateKey, publicKey: keypair.publicKey) diff --git a/Sources/NostrSDK/Events/GenericRepostEvent.swift b/Sources/NostrSDK/Events/GenericRepostEvent.swift index b2f2ac5..858598b 100644 --- a/Sources/NostrSDK/Events/GenericRepostEvent.swift +++ b/Sources/NostrSDK/Events/GenericRepostEvent.swift @@ -80,7 +80,9 @@ public extension EventCreating { /// See [NIP-18](https://github.com/nostr-protocol/nips/blob/master/18.md#reposts). func repost(event: NostrEvent, signedBy keypair: Keypair) throws -> GenericRepostEvent { let jsonData = try JSONEncoder().encode(event) - let stringifiedJSON = String(decoding: jsonData, as: UTF8.self) + guard let stringifiedJSON = String(data: jsonData, encoding: .utf8) else { + throw EventCreatingError.invalidInput + } var tags: [Tag] = [ .event(event.id), .pubkey(event.pubkey) diff --git a/Sources/NostrSDK/Events/GiftWrap/GiftWrapEvent.swift b/Sources/NostrSDK/Events/GiftWrap/GiftWrapEvent.swift index c11729c..c05b75f 100644 --- a/Sources/NostrSDK/Events/GiftWrap/GiftWrapEvent.swift +++ b/Sources/NostrSDK/Events/GiftWrap/GiftWrapEvent.swift @@ -119,7 +119,9 @@ public extension EventCreating { signedBy keypair: Keypair ) throws -> GiftWrapEvent { let jsonData = try JSONEncoder().encode(seal) - let stringifiedJSON = String(decoding: jsonData, as: UTF8.self) + guard let stringifiedJSON = String(data: jsonData, encoding: .utf8) else { + throw GiftWrapError.utf8EncodingFailed + } guard let randomKeypair = Keypair() else { throw GiftWrapError.keypairGenerationFailed diff --git a/Sources/NostrSDK/Events/GiftWrap/SealEvent.swift b/Sources/NostrSDK/Events/GiftWrap/SealEvent.swift index 3b1ebba..44cea59 100644 --- a/Sources/NostrSDK/Events/GiftWrap/SealEvent.swift +++ b/Sources/NostrSDK/Events/GiftWrap/SealEvent.swift @@ -96,7 +96,10 @@ public extension EventCreating { } let jsonData = try JSONEncoder().encode(rumor) - let stringifiedJSON = String(decoding: jsonData, as: UTF8.self) + guard let stringifiedJSON = String(data: jsonData, encoding: .utf8) else { + throw SealEventError.utf8EncodingFailed + } + let encryptedRumor = try encrypt(plaintext: stringifiedJSON, privateKeyA: keypair.privateKey, publicKeyB: recipient) return try SealEvent(content: encryptedRumor, createdAt: createdAt, signedBy: keypair) } diff --git a/Sources/NostrSDK/Events/MetadataEvent.swift b/Sources/NostrSDK/Events/MetadataEvent.swift index c5f2e85..c57fab2 100644 --- a/Sources/NostrSDK/Events/MetadataEvent.swift +++ b/Sources/NostrSDK/Events/MetadataEvent.swift @@ -184,7 +184,10 @@ public extension MetadataEvent { allUserMetadataAsData = try JSONSerialization.data(withJSONObject: userMetadataAsDictionary, options: .sortedKeys) } - let allUserMetadataAsString = String(decoding: allUserMetadataAsData, as: UTF8.self) + guard let allUserMetadataAsString = String(data: allUserMetadataAsData, encoding: .utf8) else { + throw EventCreatingError.invalidInput + } + content(allUserMetadataAsString) return self diff --git a/Sources/NostrSDK/Events/MuteListEvent.swift b/Sources/NostrSDK/Events/MuteListEvent.swift index d70f37b..1637509 100644 --- a/Sources/NostrSDK/Events/MuteListEvent.swift +++ b/Sources/NostrSDK/Events/MuteListEvent.swift @@ -108,8 +108,8 @@ public extension EventCreating { var encryptedContent: String? if !privateTags.isEmpty { let rawPrivateTags = privateTags.map { $0.raw } - if let unencryptedData = try? JSONSerialization.data(withJSONObject: rawPrivateTags) { - let unencryptedContent = String(decoding: unencryptedData, as: UTF8.self) + if let unencryptedData = try? JSONSerialization.data(withJSONObject: rawPrivateTags), + let unencryptedContent = String(data: unencryptedData, encoding: .utf8) { encryptedContent = try legacyEncrypt(content: unencryptedContent, privateKey: keypair.privateKey, publicKey: keypair.publicKey) diff --git a/Sources/NostrSDK/LegacyDirectMessageEncrypting.swift b/Sources/NostrSDK/LegacyDirectMessageEncrypting.swift index e11feb9..8288197 100644 --- a/Sources/NostrSDK/LegacyDirectMessageEncrypting.swift +++ b/Sources/NostrSDK/LegacyDirectMessageEncrypting.swift @@ -77,11 +77,12 @@ public extension LegacyDirectMessageEncrypting { let ivContentTrimmed = ivContent.dropFirst(3) guard let ivContentData = Data(base64Encoded: String(ivContentTrimmed)), - let decryptedContentData = AESDecrypt(data: encryptedContentData.bytes, iv: ivContentData.bytes, sharedSecret: sharedSecret) else { + let decryptedContentData = AESDecrypt(data: encryptedContentData.bytes, iv: ivContentData.bytes, sharedSecret: sharedSecret), + let decodedContent = String(data: decryptedContentData, encoding: .utf8) else { throw LegacyDirectMessageEncryptingError.decryptionError } - return String(decoding: decryptedContentData, as: UTF8.self) + return decodedContent } private func getSharedSecret(privateKey: PrivateKey, recipient pubkey: PublicKey) throws -> [UInt8] { diff --git a/Sources/NostrSDK/NIP44v2Encrypting.swift b/Sources/NostrSDK/NIP44v2Encrypting.swift index bacbbac..fea1a2a 100644 --- a/Sources/NostrSDK/NIP44v2Encrypting.swift +++ b/Sources/NostrSDK/NIP44v2Encrypting.swift @@ -149,12 +149,12 @@ extension NIP44v2Encrypting { guard unpaddedLength > 0, unpadded.count == unpaddedLength, - padded.count == 2 + paddedLength - else { + padded.count == 2 + paddedLength, + let result = String(data: Data(unpadded), encoding: .utf8) else { throw NIP44v2EncryptingError.paddingInvalid } - return String(decoding: Data(unpadded), as: UTF8.self) + return result } func decodePayload(_ payload: String) throws -> DecodedPayload { diff --git a/Sources/NostrSDK/RelayRequest.swift b/Sources/NostrSDK/RelayRequest.swift index a9e9961..5626170 100644 --- a/Sources/NostrSDK/RelayRequest.swift +++ b/Sources/NostrSDK/RelayRequest.swift @@ -29,9 +29,10 @@ enum RelayRequest { payload = [AnyEncodable("COUNT"), AnyEncodable(subscriptionId), AnyEncodable(filter)] } - guard let data = try? JSONEncoder().encode(payload) else { + guard let data = try? JSONEncoder().encode(payload), + let decoded = String(data: data, encoding: .utf8) else { return nil } - return String(decoding: data, as: UTF8.self).trimmingCharacters(in: .whitespacesAndNewlines) + return decoded.trimmingCharacters(in: .whitespacesAndNewlines) } } diff --git a/Sources/NostrSDK/WebSocket.swift b/Sources/NostrSDK/WebSocket.swift index 91ddf1c..bbd1bfb 100644 --- a/Sources/NostrSDK/WebSocket.swift +++ b/Sources/NostrSDK/WebSocket.swift @@ -80,7 +80,7 @@ final class WebSocket: NSObject, URLSessionWebSocketDelegate { let reasonString: String? if let reason { - reasonString = String(decoding: reason, as: UTF8.self) + reasonString = String(data: reason, encoding: .utf8) } else { reasonString = nil } diff --git a/Tests/NostrSDKTests/FilterTests.swift b/Tests/NostrSDKTests/FilterTests.swift index 951db47..558211e 100644 --- a/Tests/NostrSDKTests/FilterTests.swift +++ b/Tests/NostrSDKTests/FilterTests.swift @@ -19,7 +19,7 @@ final class FilterTests: XCTestCase, FixtureLoading, JSONTesting { let encoder = JSONEncoder() let result = try encoder.encode(filter) - let resultString = String(decoding: result, as: UTF8.self) + let resultString = try XCTUnwrap(String(data: result, encoding: .utf8)) XCTAssertTrue(areEquivalentJSONObjectStrings(expected, resultString)) } @@ -39,7 +39,7 @@ final class FilterTests: XCTestCase, FixtureLoading, JSONTesting { let encoder = JSONEncoder() let result = try encoder.encode(filter) - let resultString = String(decoding: result, as: UTF8.self) + let resultString = try XCTUnwrap(String(data: result, encoding: .utf8)) XCTAssertTrue(areEquivalentJSONObjectStrings(expected, resultString)) } diff --git a/Tests/NostrSDKTests/FixtureLoading.swift b/Tests/NostrSDKTests/FixtureLoading.swift index 8e9837b..4d4a76e 100644 --- a/Tests/NostrSDKTests/FixtureLoading.swift +++ b/Tests/NostrSDKTests/FixtureLoading.swift @@ -27,7 +27,11 @@ extension FixtureLoading { func loadFixtureString(_ filename: String) throws -> String? { let data = try loadFixtureData(filename) - let originalString = String(decoding: data, as: UTF8.self) + + guard let originalString = String(data: data, encoding: .utf8) else { + throw FixtureLoadingError.decodingError + } + let trimmedString = originalString.filter { !"\n\t\r".contains($0) } return trimmedString }