diff --git a/Extensions/XEP-0357/XMPPIQ+XEP_0357.h b/Extensions/XEP-0357/XMPPIQ+XEP_0357.h new file mode 100644 index 0000000000..f48f0fb791 --- /dev/null +++ b/Extensions/XEP-0357/XMPPIQ+XEP_0357.h @@ -0,0 +1,37 @@ +// +// NSXMLElement+NSXMLElement_XEP_0357.h +// +// Created by David Chiles on 2/9/16. +// +// + +#import "XMPPIQ.h" +@class XMPPJID; + +/** + XMPPIQ (XEP0357) is a class extension on XMPPIQ for creating the elements for XEP-0357 http://xmpp.org/extensions/xep-0357.html + */ +extern NSString * __nonnull const XMPPPushXMLNS; + +@interface XMPPIQ (XEP0357) + +/** + Creates an IQ stanza for enabling push notificiations. http://xmpp.org/extensions/xep-0357.html#enabling + + @param jid The jid of the XMPP Push Service + @param node Optional node of the XMPP Push Service + @param options Optional values to passed to your XMPP service (this is likely some sort of secret or token to validate this user/device with teh app server) + @return An IQ stanza + */ ++ (nonnull instancetype)enableNotificationsElementWithJID:(nonnull XMPPJID *)jid node:(nullable NSString *)node options:(nullable NSDictionary *)options; + +/** + Creates an IQ stanza for disable push notifications. http://xmpp.org/extensions/xep-0357.html#disabling + + @param jid the jid of the XMPP Push Service + @param node the node of the XMPP push Service + @return an IQ Stanza + */ ++ (nonnull instancetype)disableNotificationsElementWithJID:(nonnull XMPPJID *)jid node:(nullable NSString *)node; + +@end diff --git a/Extensions/XEP-0357/XMPPIQ+XEP_0357.m b/Extensions/XEP-0357/XMPPIQ+XEP_0357.m new file mode 100644 index 0000000000..ea26e52720 --- /dev/null +++ b/Extensions/XEP-0357/XMPPIQ+XEP_0357.m @@ -0,0 +1,54 @@ +// +// NSXMLElement+NSXMLElement_XEP_0357.m +// Pods +// +// Created by David Chiles on 2/9/16. +// +// + +#import "XMPPIQ+XEP_0357.h" +#import "XMPPJID.h" + +NSString *const XMPPPushXMLNS = @"urn:xmpp:push:0"; + +@implementation XMPPIQ (XEP0357) + ++ (instancetype)enableNotificationsElementWithJID:(XMPPJID *)jid node:(NSString *)node options:(nullable NSDictionary *)options +{ + NSXMLElement *enableElement = [self elementWithName:@"enable" xmlns:XMPPPushXMLNS]; + [enableElement addAttributeWithName:@"jid" stringValue:[jid full]]; + if ([node length]) { + [enableElement addAttributeWithName:@"node" stringValue:node]; + } + + if ([options count]) { + NSXMLElement *dataForm = [self elementWithName:@"x" xmlns:@"jabber:x:data"]; + NSXMLElement *formTypeField = [NSXMLElement elementWithName:@"field"]; + [formTypeField addAttributeWithName:@"var" stringValue:@"FORM_TYPE"]; + [formTypeField addChild:[NSXMLElement elementWithName:@"value" stringValue:@"http://jabber.org/protocol/pubsub#publish-options"]]; + [dataForm addChild:formTypeField]; + + [options enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) { + NSXMLElement *formField = [NSXMLElement elementWithName:@"field"]; + [formField addAttributeWithName:@"var" stringValue:key]; + [formField addChild:[NSXMLElement elementWithName:@"value" stringValue:obj]]; + [dataForm addChild:formField]; + }]; + [enableElement addChild:dataForm]; + } + + return [self iqWithType:@"set" child:enableElement]; + +} + ++ (instancetype)disableNotificationsElementWithJID:(XMPPJID *)jid node:(NSString *)node +{ + NSXMLElement *disableElement = [self elementWithName:@"disable" xmlns:XMPPPushXMLNS]; + [disableElement addAttributeWithName:@"jid" stringValue:[jid full]]; + if ([node length]) { + [disableElement addAttributeWithName:@"node" stringValue:node]; + } + return [self iqWithType:@"set" child:disableElement]; +} + +@end diff --git a/XMPPFramework.podspec b/XMPPFramework.podspec index 9ed639d047..4b19694ae8 100644 --- a/XMPPFramework.podspec +++ b/XMPPFramework.podspec @@ -323,6 +323,12 @@ s.subspec 'XEP-0352' do |ss| ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" end +s.subspec 'XEP-0357' do |ss| + ss.source_files = 'Extensions/XEP-0357/*.{h,m}' + ss.dependency 'XMPPFramework/Core' + ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + s.subspec 'All' do |ss| ss.dependency 'XMPPFramework/Core' ss.dependency 'XMPPFramework/BandwidthMonitor' @@ -367,6 +373,7 @@ s.subspec 'All' do |ss| ss.dependency 'XMPPFramework/XEP-0333' ss.dependency 'XMPPFramework/XEP-0335' ss.dependency 'XMPPFramework/XEP-0352' + ss.dependency 'XMPPFramework/XEP-0357' end end diff --git a/Xcode/Testing-pod/Podfile.lock b/Xcode/Testing-pod/Podfile.lock index 39d61aac2e..831db65294 100644 --- a/Xcode/Testing-pod/Podfile.lock +++ b/Xcode/Testing-pod/Podfile.lock @@ -1,10 +1,13 @@ PODS: - CocoaAsyncSocket (7.4.2) - - CocoaLumberjack (1.9.2): - - CocoaLumberjack/Extensions (= 1.9.2) - - CocoaLumberjack/Core (1.9.2) - - CocoaLumberjack/Extensions (1.9.2): + - CocoaLumberjack (2.2.0): + - CocoaLumberjack/Default (= 2.2.0) + - CocoaLumberjack/Extensions (= 2.2.0) + - CocoaLumberjack/Core (2.2.0) + - CocoaLumberjack/Default (2.2.0): - CocoaLumberjack/Core + - CocoaLumberjack/Extensions (2.2.0): + - CocoaLumberjack/Default - KissXML/Core (5.0.3) - KissXML/libxml_module (5.0.3): - KissXML/Core @@ -53,11 +56,12 @@ PODS: - XMPPFramework/XEP-0333 - XMPPFramework/XEP-0335 - XMPPFramework/XEP-0352 + - XMPPFramework/XEP-0357 - XMPPFramework/BandwidthMonitor (3.6.7): - XMPPFramework/Core - XMPPFramework/Core (3.6.7): - CocoaAsyncSocket (~> 7.4.1) - - CocoaLumberjack (~> 1.9) + - CocoaLumberjack (~> 2.0) - KissXML/libxml_module (~> 5.0.3) - XMPPFramework/CoreDataStorage (3.6.7): - XMPPFramework/Core @@ -150,6 +154,8 @@ PODS: - XMPPFramework/Core - XMPPFramework/XEP-0352 (3.6.7): - XMPPFramework/Core + - XMPPFramework/XEP-0357 (3.6.7): + - XMPPFramework/Core DEPENDENCIES: - XMPPFramework (from `../../`) @@ -160,8 +166,8 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: CocoaAsyncSocket: f5783bdedd232d91b89769bc4b5a1580aed518ad - CocoaLumberjack: 628fca2e88ef06f7cf6817309aa405f325d9a6fa + CocoaLumberjack: 17fe8581f84914d5d7e6360f7c70022b173c3ae0 KissXML: d19dd6dc65e0dc721ba92b3077b8ebdd240f1c1e - XMPPFramework: b8f741bfd26268113a3f6b39b5c9dbd93a68944a + XMPPFramework: 53da6a70a6aa55aaaa47009b2b11ef975e3a0556 COCOAPODS: 0.39.0 diff --git a/Xcode/Testing-pod/XMPPFrameworkTests.xcodeproj/project.pbxproj b/Xcode/Testing-pod/XMPPFrameworkTests.xcodeproj/project.pbxproj index 25fa2f8fb0..c27c889469 100644 --- a/Xcode/Testing-pod/XMPPFrameworkTests.xcodeproj/project.pbxproj +++ b/Xcode/Testing-pod/XMPPFrameworkTests.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 637AE2E91C6AC0D50051BF1F /* XMPPPushTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637AE2E81C6AC0D50051BF1F /* XMPPPushTests.swift */; }; 63F50D9E1C6020A100CA0201 /* CapabilitiesHashingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 63F50D9B1C6020A100CA0201 /* CapabilitiesHashingTest.m */; }; 63F50D9F1C6020A100CA0201 /* EncodeDecodeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 63F50D9C1C6020A100CA0201 /* EncodeDecodeTest.m */; }; 63F50DA01C6020A100CA0201 /* XMPPURITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63F50D9D1C6020A100CA0201 /* XMPPURITests.m */; }; @@ -15,6 +16,7 @@ /* Begin PBXFileReference section */ 16B6474F735EF4CB50F33A27 /* Pods-XMPPFrameworkTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XMPPFrameworkTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-XMPPFrameworkTests/Pods-XMPPFrameworkTests.debug.xcconfig"; sourceTree = ""; }; + 637AE2E81C6AC0D50051BF1F /* XMPPPushTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XMPPPushTests.swift; sourceTree = ""; }; 63F50D921C60208200CA0201 /* XMPPFrameworkTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XMPPFrameworkTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 63F50D971C60208200CA0201 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 63F50D9B1C6020A100CA0201 /* CapabilitiesHashingTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CapabilitiesHashingTest.m; sourceTree = ""; }; @@ -67,6 +69,7 @@ 63F50D9B1C6020A100CA0201 /* CapabilitiesHashingTest.m */, 63F50D9C1C6020A100CA0201 /* EncodeDecodeTest.m */, 63F50D9D1C6020A100CA0201 /* XMPPURITests.m */, + 637AE2E81C6AC0D50051BF1F /* XMPPPushTests.swift */, 63F50D971C60208200CA0201 /* Info.plist */, ); path = XMPPFrameworkTests; @@ -200,6 +203,7 @@ files = ( 63F50D9E1C6020A100CA0201 /* CapabilitiesHashingTest.m in Sources */, 63F50D9F1C6020A100CA0201 /* EncodeDecodeTest.m in Sources */, + 637AE2E91C6AC0D50051BF1F /* XMPPPushTests.swift in Sources */, 63F50DA01C6020A100CA0201 /* XMPPURITests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -252,6 +256,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.davidchiles.XMPPFrameworkTests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; diff --git a/Xcode/Testing-pod/XMPPFrameworkTests.xcodeproj/xcshareddata/xcschemes/XMPPFrameworkTests.xcscheme b/Xcode/Testing-pod/XMPPFrameworkTests.xcodeproj/xcshareddata/xcschemes/XMPPFrameworkTests.xcscheme index e456da720c..1e6fce5662 100644 --- a/Xcode/Testing-pod/XMPPFrameworkTests.xcodeproj/xcshareddata/xcschemes/XMPPFrameworkTests.xcscheme +++ b/Xcode/Testing-pod/XMPPFrameworkTests.xcodeproj/xcshareddata/xcschemes/XMPPFrameworkTests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Xcode/Testing-pod/XMPPFrameworkTests/XMPPPushTests.swift b/Xcode/Testing-pod/XMPPFrameworkTests/XMPPPushTests.swift new file mode 100644 index 0000000000..9d703a1511 --- /dev/null +++ b/Xcode/Testing-pod/XMPPFrameworkTests/XMPPPushTests.swift @@ -0,0 +1,72 @@ +// +// XMPPPushTests.swift +// XMPPFrameworkTests +// +// Created by David Chiles on 2/9/16. +// +// +import XMPPFramework + +import XCTest + +class XMPPPushTests: XCTestCase { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testEnableStanzaWithoutOptions() { + + let jid = XMPPJID.jidWithString("push-5.client.example") + let node = "yxs32uqsflafdk3iuqo" + let enableStanza = XMPPIQ.enableNotificationsElementWithJID(jid, node: node, options: nil) + XCTAssertNotNil(enableStanza,"No Stanza") + + /** + + + + */ + XCTAssertTrue(enableStanza.XMLString() == "","XML does not match \(enableStanza.XMLString())") + } + + func testEnableStanzaWithOptions() { + let jid = XMPPJID.jidWithString("push-5.client.example") + let node = "yxs32uqsflafdk3iuqo" + let options = ["secret":"eruio234vzxc2kla-91"] + let enableStanza = XMPPIQ.enableNotificationsElementWithJID(jid, node: node, options: options) + XCTAssertNotNil(enableStanza,"No Stanza") + + /** + + + + http://jabber.org/protocol/pubsub#publish-options + eruio234vzxc2kla-91 + + + + */ + XCTAssertTrue(enableStanza.XMLString() == "http://jabber.org/protocol/pubsub#publish-optionseruio234vzxc2kla-91","XML does not match \(enableStanza.XMLString())") + } + + func testDisableStanza() { + let jid = XMPPJID.jidWithString("push-5.client.example") + let node = "yxs32uqsflafdk3iuqo" + let disableStanza = XMPPIQ.disableNotificationsElementWithJID(jid, node: node) + XCTAssertNotNil(disableStanza) + print("\(disableStanza.XMLString())") + /** + + + + */ + XCTAssertTrue(disableStanza.XMLString() == "","XML does not match \(disableStanza.XMLString())") + } +}