From 5b16eaa1f0ca06febe4e62021818b66aa399a360 Mon Sep 17 00:00:00 2001 From: Jonathan Schleifer Date: Tue, 29 Mar 2011 03:46:20 +0200 Subject: [PATCH] Port to ObjC 1. --- ObjXMPP.xcodeproj/project.pbxproj | 4 - src/Makefile | 2 +- src/XMPPAuthenticator.h | 16 +- src/XMPPAuthenticator.m | 40 ++++- src/XMPPConnection.h | 44 +++++- src/XMPPConnection.m | 242 +++++++++++++++++++----------- src/XMPPExceptions.h | 14 ++ src/XMPPExceptions.m | 38 ++++- src/XMPPJID.h | 15 +- src/XMPPRoster.h | 1 + src/XMPPRoster.m | 27 ++-- src/XMPPRosterItem.h | 10 ++ src/XMPPRosterItem.m | 60 +++++++- src/XMPPRoster_private.h | 27 ---- src/XMPPSCRAMAuth.h | 7 + src/XMPPSCRAMAuth.m | 29 ++-- src/XMPPStanza.h | 19 ++- src/XMPPStanza.m | 30 ++-- tests/test.m | 47 +++--- 19 files changed, 468 insertions(+), 204 deletions(-) delete mode 100644 src/XMPPRoster_private.h diff --git a/ObjXMPP.xcodeproj/project.pbxproj b/ObjXMPP.xcodeproj/project.pbxproj index 20cc5bd..1357472 100644 --- a/ObjXMPP.xcodeproj/project.pbxproj +++ b/ObjXMPP.xcodeproj/project.pbxproj @@ -37,7 +37,6 @@ 4BD9BF5A134003F700DAB43A /* XMPPRosterItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BD9BF58134003F700DAB43A /* XMPPRosterItem.m */; }; 4BDEF8071340B240000156D1 /* XMPPRoster.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BDEF8051340B240000156D1 /* XMPPRoster.h */; }; 4BDEF8081340B240000156D1 /* XMPPRoster.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BDEF8061340B240000156D1 /* XMPPRoster.m */; }; - 4BF459B91340DE3600701BCC /* XMPPRoster_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF459B81340DE3600701BCC /* XMPPRoster_private.h */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -84,7 +83,6 @@ 4BD9BF58134003F700DAB43A /* XMPPRosterItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPRosterItem.m; path = src/XMPPRosterItem.m; sourceTree = SOURCE_ROOT; }; 4BDEF8051340B240000156D1 /* XMPPRoster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPRoster.h; path = src/XMPPRoster.h; sourceTree = SOURCE_ROOT; }; 4BDEF8061340B240000156D1 /* XMPPRoster.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPRoster.m; path = src/XMPPRoster.m; sourceTree = SOURCE_ROOT; }; - 4BF459B81340DE3600701BCC /* XMPPRoster_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPRoster_private.h; path = src/XMPPRoster_private.h; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -166,7 +164,6 @@ 4BC559E81337AC0900E345C7 /* XMPPPresence.h */, 4BC559E91337AC0900E345C7 /* XMPPPresence.m */, 4BDEF8051340B240000156D1 /* XMPPRoster.h */, - 4BF459B81340DE3600701BCC /* XMPPRoster_private.h */, 4BDEF8061340B240000156D1 /* XMPPRoster.m */, 4BD9BF57134003F700DAB43A /* XMPPRosterItem.h */, 4BD9BF58134003F700DAB43A /* XMPPRosterItem.m */, @@ -206,7 +203,6 @@ 4BC55A011337AC1800E345C7 /* XMPPStanza.h in Headers */, 4BD9BF59134003F700DAB43A /* XMPPRosterItem.h in Headers */, 4BDEF8071340B240000156D1 /* XMPPRoster.h in Headers */, - 4BF459B91340DE3600701BCC /* XMPPRoster_private.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/Makefile b/src/Makefile index 016f146..cca364a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,5 @@ all: - objfw-compile -Wall -g --lib 0.0 -o objxmpp *.m \ + objfw-compile -Wall -Werror -g --lib 0.0 -o objxmpp *.m \ `pkg-config --cflags --libs libidn` -lobjopenssl clean: diff --git a/src/XMPPAuthenticator.h b/src/XMPPAuthenticator.h index 4323838..ed84098 100644 --- a/src/XMPPAuthenticator.h +++ b/src/XMPPAuthenticator.h @@ -27,16 +27,19 @@ */ @interface XMPPAuthenticator: OFObject { - /// The authzid to get authorization for OFString *authzid; - /// The authcid to authenticate with OFString *authcid; - /// The password to authenticate with OFString *password; } + +#ifdef OF_HAVE_PROPERTIES +/// The authzid to get authorization for @property (copy) OFString *authzid; +/// The authcid to authenticate with @property (copy) OFString *authcid; +/// The password to authenticate with @property (copy) OFString *password; +#endif /** * Initializes an already allocated XMPPAuthenticator with an authcid @@ -79,4 +82,11 @@ * \param message The servers final message */ - (void)parseServerFinalMessage: (OFDataArray*)message; + +- (void)setAuthzid: (OFString*)authzid; +- (OFString*)authzid; +- (void)setAuthcid: (OFString*)authcid; +- (OFString*)authcid; +- (void)setPassword: (OFString*)password; +- (OFString*)password; @end diff --git a/src/XMPPAuthenticator.m b/src/XMPPAuthenticator.m index 1411aaa..bbbd359 100644 --- a/src/XMPPAuthenticator.m +++ b/src/XMPPAuthenticator.m @@ -23,10 +23,6 @@ #import "XMPPAuthenticator.h" @implementation XMPPAuthenticator -@synthesize authzid; -@synthesize authcid; -@synthesize password; - - initWithAuthcid: (OFString*)authcid_ password: (OFString*)password_ { @@ -57,6 +53,42 @@ [super dealloc]; } +- (void)setAuthzid: (OFString*)authzid_ +{ + OFString *old = authzid; + authzid = [authzid_ copy]; + [old release]; +} + +- (OFString*)authzid +{ + return [[authzid copy] autorelease]; +} + +- (void)setAuthcid: (OFString*)authcid_ +{ + OFString *old = authcid; + authcid = [authcid_ copy]; + [old release]; +} + +- (OFString*)authcid +{ + return [[authcid copy] autorelease]; +} + +- (void)setPassword: (OFString*)password_ +{ + OFString *old = password; + password = [password_ copy]; + [old release]; +} + +- (OFString*)password +{ + return [[password copy] autorelease]; +} + - (OFDataArray*)clientFirstMessage { @throw [OFNotImplementedException newWithClass: isa diff --git a/src/XMPPConnection.h b/src/XMPPConnection.h index ea80b4a..90c20fb 100644 --- a/src/XMPPConnection.h +++ b/src/XMPPConnection.h @@ -41,7 +41,12 @@ #define XMPP_NS_STREAM @"http://etherx.jabber.org/streams" @protocol XMPPConnectionDelegate +#ifndef XMPP_CONNECTION_M + +#endif +#ifdef OF_HAVE_OPTIONAL_PROTOCOLS @optional +#endif - (void)connectionWasAuthenticated: (XMPPConnection*)conn; - (void)connection: (XMPPConnection*)conn wasBoundToJID: (XMPPJID*)jid; @@ -58,8 +63,10 @@ /** * \brief A class which abstracts a connection to an XMPP service. */ -@interface XMPPConnection: OFObject +@interface XMPPConnection: OFObject +#ifdef OF_HAVE_OPTONAL_PROTOCOLS + +#endif { OFTCPSocket *sock; OFXMLParser *parser; @@ -75,11 +82,13 @@ XMPPRoster *roster; } +#ifdef OF_HAVE_PROPERTIES @property (copy) OFString *username, *password, *server, *resource; @property (copy, readonly) XMPPJID *JID; @property (assign) uint16_t port; @property (retain) id delegate; @property (readonly, retain) XMPPRoster *roster; +#endif /** * Connects to the XMPP service. @@ -109,4 +118,35 @@ * Requests the roster. */ - (void)requestRoster; + +- (void)setUsername: (OFString*)username; +- (OFString*)username; +- (void)setPassword: (OFString*)password; +- (OFString*)password; +- (void)setServer: (OFString*)server; +- (OFString*)server; +- (void)setResource: (OFString*)resource; +- (OFString*)resource; +- (XMPPJID*)JID; +- (void)setPort: (uint16_t)port; +- (uint16_t)port; +- (void)setDelegate: (id )delegate; +- (id )delegate; +- (XMPPRoster*)roster; + +- (void)XMPP_startStream; +- (void)XMPP_handleStanza: (OFXMLElement*)elem; +- (void)XMPP_sendAuth: (OFString*)name; +- (void)XMPP_handleIQ: (XMPPIQ*)iq; +- (void)XMPP_handleMessage: (XMPPMessage*)msg; +- (void)XMPP_handlePresence: (XMPPPresence*)pres; +- (void)XMPP_handleFeatures: (OFXMLElement*)elem; +- (void)XMPP_sendResourceBind; +- (void)XMPP_handleResourceBind: (XMPPIQ*)iq; +- (void)XMPP_sendSession; +- (void)XMPP_handleSession: (XMPPIQ*)iq; +- (void)XMPP_handleRoster: (XMPPIQ*)iq; +@end + +@interface OFObject (XMPPConnectionDelegate) @end diff --git a/src/XMPPConnection.m b/src/XMPPConnection.m index 1fa679c..37fe658 100644 --- a/src/XMPPConnection.m +++ b/src/XMPPConnection.m @@ -21,6 +21,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#define XMPP_CONNECTION_M + #include #include @@ -37,28 +39,10 @@ #import "XMPPMessage.h" #import "XMPPPresence.h" #import "XMPPRoster.h" -#import "XMPPRoster_private.h" #import "XMPPRosterItem.h" #import "XMPPExceptions.h" -@interface XMPPConnection () -- (void)XMPP_startStream; -- (void)XMPP_handleStanza: (OFXMLElement*)elem; -- (void)XMPP_sendAuth: (OFString*)name; -- (void)XMPP_handleIQ: (XMPPIQ*)iq; -- (void)XMPP_handleMessage: (XMPPMessage*)msg; -- (void)XMPP_handlePresence: (XMPPPresence*)pres; -- (void)XMPP_handleFeatures: (OFXMLElement*)elem; -- (void)XMPP_sendResourceBind; -- (void)XMPP_handleResourceBind: (XMPPIQ*)iq; -- (void)XMPP_sendSession; -- (void)XMPP_handleSession: (XMPPIQ*)iq; -- (void)XMPP_handleRoster: (XMPPIQ*)iq; -@end - @implementation XMPPConnection -@synthesize JID, port, delegate, roster; - - init { self = [super init]; @@ -70,8 +54,8 @@ port = 5222; - parser.delegate = self; - elementBuilder.delegate = self; + [parser setDelegate: self]; + [elementBuilder setDelegate: self]; roster = [[XMPPRoster alloc] initWithConnection: self]; } @catch (id e) { @@ -166,10 +150,10 @@ if ((rc = idna_to_ascii_8z([server_ cString], &srv, IDNA_USE_STD3_ASCII_RULES)) != IDNA_SUCCESS) @throw [XMPPIDNATranslationFailedException - newWithClass: isa - connection: self - operation: @"ToASCII" - string: server_]; + newWithClass: isa + connection: self + operation: @"ToASCII" + string: server_]; @try { server = [[OFString alloc] initWithCString: srv]; @@ -258,6 +242,8 @@ attributes: (OFArray*)attrs { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + OFEnumerator *enumerator; + OFXMLAttribute *attr; if (![name isEqual: @"stream"] || ![prefix isEqual: @"stream"] || ![ns isEqual: XMPP_NS_STREAM]) { @@ -265,15 +251,16 @@ assert(0); } - for (OFXMLAttribute *attr in attrs) { - if ([attr.name isEqual: @"from"] && - ![attr.stringValue isEqual: server]) { + enumerator = [attrs objectEnumerator]; + while ((attr = [enumerator nextObject]) != nil) { + if ([[attr name] isEqual: @"from"] && + ![[attr stringValue] isEqual: server]) { of_log(@"Got invalid from in stream start!"); assert(0); } } - parser.delegate = elementBuilder; + [parser setDelegate: elementBuilder]; [pool release]; } @@ -283,7 +270,7 @@ { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - elem.defaultNamespace = XMPP_NS_CLIENT; + [elem setDefaultNamespace: XMPP_NS_CLIENT]; [elem setPrefix: @"stream" forNamespace: XMPP_NS_STREAM]; @@ -305,19 +292,19 @@ - (void)XMPP_handleStanza: (OFXMLElement*)elem { - if ([elem.namespace isEqual: XMPP_NS_CLIENT]) { - if ([elem.name isEqual: @"iq"]) { + if ([[elem namespace] isEqual: XMPP_NS_CLIENT]) { + if ([[elem name] isEqual: @"iq"]) { [self XMPP_handleIQ: [XMPPIQ stanzaWithElement: elem]]; return; } - if ([elem.name isEqual: @"message"]) { + if ([[elem name] isEqual: @"message"]) { [self XMPP_handleMessage: [XMPPMessage stanzaWithElement: elem]]; return; } - if ([elem.name isEqual: @"presence"]) { + if ([[elem name] isEqual: @"presence"]) { [self XMPP_handlePresence: [XMPPPresence stanzaWithElement: elem]]; return; @@ -326,8 +313,8 @@ assert(0); } - if ([elem.namespace isEqual: XMPP_NS_STREAM]) { - if ([elem.name isEqual: @"features"]) { + if ([[elem namespace] isEqual: XMPP_NS_STREAM]) { + if ([[elem name] isEqual: @"features"]) { [self XMPP_handleFeatures: elem]; return; } @@ -335,30 +322,30 @@ assert(0); } - if ([elem.namespace isEqual: XMPP_NS_STARTTLS]) { - if ([elem.name isEqual: @"proceed"]) { + if ([[elem namespace] isEqual: XMPP_NS_STARTTLS]) { + if ([[elem name] isEqual: @"proceed"]) { /* FIXME: Catch errors here */ sock = [[SSLSocket alloc] initWithSocket: sock]; /* Stream restart */ - parser.delegate = self; + [parser setDelegate: self]; [self XMPP_startStream]; return; } - if ([elem.name isEqual: @"failure"]) + if ([[elem name] isEqual: @"failure"]) /* TODO: Find/create an exception to throw here */ @throw [OFException newWithClass: isa]; assert(0); } - if ([elem.namespace isEqual: XMPP_NS_SASL]) { - if ([elem.name isEqual: @"challenge"]) { + if ([[elem namespace] isEqual: XMPP_NS_SASL]) { + if ([[elem name] isEqual: @"challenge"]) { OFXMLElement *responseTag; OFDataArray *challenge = [OFDataArray dataArrayWithBase64EncodedString: - [elem.children.firstObject stringValue]]; + [[[elem children] firstObject] stringValue]]; OFDataArray *response = [authModule calculateResponseWithChallenge: challenge]; @@ -373,28 +360,28 @@ return; } - if ([elem.name isEqual: @"success"]) { + if ([[elem name] isEqual: @"success"]) { [authModule parseServerFinalMessage: [OFDataArray dataArrayWithBase64EncodedString: - [elem.children.firstObject stringValue]]]; + [[[elem children] firstObject] stringValue]]]; if ([delegate respondsToSelector: @selector(connectionWasAuthenticated:)]) [delegate connectionWasAuthenticated: self]; /* Stream restart */ - parser.delegate = self; + [parser setDelegate: self]; [self XMPP_startStream]; return; } - if ([elem.name isEqual: @"failure"]) { + if ([[elem name] isEqual: @"failure"]) { of_log(@"Auth failed!"); // FIXME: Do more parsing/handling @throw [XMPPAuthFailedException newWithClass: isa connection: self - reason: elem.stringValue]; + reason: [elem stringValue]]; } assert(0); @@ -407,17 +394,17 @@ { BOOL handled = NO; - if ([iq.ID isEqual: bindID]) { + if ([[iq ID] isEqual: bindID]) { [self XMPP_handleResourceBind: iq]; return; } - if ([iq.ID isEqual: sessionID]) { + if ([[iq ID] isEqual: sessionID]) { [self XMPP_handleSession: iq]; return; } - if ([iq.ID isEqual: rosterID]) { + if ([[iq ID] isEqual: rosterID]) { [self XMPP_handleRoster: iq]; return; } @@ -427,14 +414,13 @@ didReceiveIQ: iq]; if (!handled) { - XMPPJID *from = iq.from; - XMPPJID *to = iq.to; + XMPPJID *from = [iq from]; + XMPPJID *to = [iq to]; OFXMLElement *error; [iq setType: @"error"]; - - iq.to = from; - iq.from = to; + [iq setTo: from]; + [iq setFrom: to]; error = [OFXMLElement elementWithName: @"error"]; [error addAttributeWithName: @"type" @@ -467,13 +453,13 @@ - (void)XMPP_handleFeatures: (OFXMLElement*)elem { OFXMLElement *starttls = - [elem elementsForName: @"starttls" - namespace: XMPP_NS_STARTTLS].firstObject; - OFXMLElement *bind = [elem elementsForName: @"bind" - namespace: XMPP_NS_BIND].firstObject; + [[elem elementsForName: @"starttls" + namespace: XMPP_NS_STARTTLS] firstObject]; + OFXMLElement *bind = [[elem elementsForName: @"bind" + namespace: XMPP_NS_BIND] firstObject]; OFXMLElement *session = - [elem elementsForName: @"session" - namespace: XMPP_NS_SESSION].firstObject; + [[elem elementsForName: @"session" + namespace: XMPP_NS_SESSION] firstObject]; OFArray *mechs = [elem elementsForName: @"mechanisms" namespace: XMPP_NS_SASL]; OFMutableArray *mechanisms = [OFMutableArray array]; @@ -485,10 +471,14 @@ return; } - if (mechs.count > 0) { - for (OFXMLElement *mech in [mechs.firstObject children]) + if ([mechs count] > 0) { + OFEnumerator *enumerator; + OFXMLElement *mech; + + enumerator = [[[mechs firstObject] children] objectEnumerator]; + while ((mech = [enumerator nextObject]) != nil) [mechanisms addObject: - [mech.children.firstObject stringValue]]; + [[[mech children] firstObject] stringValue]]; if ([mechanisms containsObject: @"SCRAM-SHA-1"]) { authModule = [[XMPPSCRAMAuth alloc] @@ -561,18 +551,18 @@ OFXMLElement *bindElem; OFXMLElement *jidElem; - if (![iq.type isEqual: @"result"]) + if (![[iq type] isEqual: @"result"]) assert(0); - bindElem = iq.children.firstObject; + bindElem = [[iq children] firstObject]; - if (![bindElem.name isEqual: @"bind"] || - ![bindElem.namespace isEqual: XMPP_NS_BIND]) + if (![[bindElem name] isEqual: @"bind"] || + ![[bindElem namespace] isEqual: XMPP_NS_BIND]) assert(0); - jidElem = bindElem.children.firstObject; + jidElem = [[bindElem children] firstObject]; JID = [[XMPPJID alloc] initWithString: - [jidElem.children.firstObject stringValue]]; + [[[jidElem children] firstObject] stringValue]]; [bindID release]; bindID = nil; @@ -601,7 +591,7 @@ - (void)XMPP_handleSession: (XMPPIQ*)iq { - if (![iq.type isEqual: @"result"]) + if (![[iq type] isEqual: @"result"]) assert(0); if ([delegate respondsToSelector: @selector(connection:wasBoundToJID:)]) @@ -630,39 +620,46 @@ - (void)XMPP_handleRoster: (XMPPIQ*)iq { OFXMLElement *rosterElem; + OFEnumerator *enumerator; + OFXMLElement *elem; - if (![iq.type isEqual: @"result"]) + if (![[iq type] isEqual: @"result"]) assert(0); - rosterElem = iq.children.firstObject; + rosterElem = [[iq children] firstObject]; - if (![rosterElem.name isEqual: @"query"] || - ![rosterElem.namespace isEqual: XMPP_NS_ROSTER]) + if (![[rosterElem name] isEqual: @"query"] || + ![[rosterElem namespace] isEqual: XMPP_NS_ROSTER]) assert(0); - for (OFXMLElement *elem in rosterElem.children) { + enumerator = [[rosterElem children] objectEnumerator]; + while ((elem = [enumerator nextObject]) != nil) { XMPPRosterItem *rosterItem; OFMutableArray *groups = [OFMutableArray array]; + OFEnumerator *groupEnumerator; + OFXMLElement *groupElem; - if (![elem.name isEqual: @"item"] || - ![elem.ns isEqual: XMPP_NS_ROSTER]) + if (![[elem name] isEqual: @"item"] || + ![[elem namespace] isEqual: XMPP_NS_ROSTER]) continue; rosterItem = [XMPPRosterItem rosterItem]; - rosterItem.JID = [XMPPJID JIDWithString: - [elem attributeForName: @"jid"].stringValue]; - rosterItem.name = [elem attributeForName: @"name"].stringValue; - rosterItem.subscription = - [elem attributeForName: @"subscription"].stringValue; + [rosterItem setJID: [XMPPJID JIDWithString: + [[elem attributeForName: @"jid"] stringValue]]]; + [rosterItem setName: + [[elem attributeForName: @"name"] stringValue]]; + [rosterItem setSubscription: + [[elem attributeForName: @"subscription"] stringValue]]; - for (OFXMLElement *groupElem in - [elem elementsForName: @"group" - namespace: XMPP_NS_ROSTER]) + groupEnumerator = + [[elem elementsForName: @"group" + namespace: XMPP_NS_ROSTER] objectEnumerator]; + while ((groupElem = [groupEnumerator nextObject]) != nil) [groups addObject: - [groupElem.children.firstObject stringValue]]; + [[[groupElem children] firstObject] stringValue]]; - if (groups.count > 0) - rosterItem.groups = groups; + if ([groups count] > 0) + [rosterItem setGroups: groups]; [roster XMPP_addRosterItem: rosterItem]; } @@ -674,4 +671,71 @@ [rosterID release]; rosterID = nil; } + +- (XMPPJID*)JID +{ + return [[JID copy] autorelease]; +} + +- (void)setPort: (uint16_t)port_ +{ + port = port_; +} + +- (uint16_t)port +{ + return port; +} + +- (void)setDelegate: (id )delegate_ +{ + id old = delegate; + delegate = [(id)delegate_ retain]; + [old release]; +} + +- (id )delegate +{ + return [[delegate retain] autorelease]; +} + +- (XMPPRoster*)roster +{ + return [[roster retain] autorelease]; +} +@end + +@implementation OFObject (XMPPConnectionDelegate) +- (void)connectionWasAuthenticated: (XMPPConnection*)conn +{ +} + +- (void)connection: (XMPPConnection*)conn + wasBoundToJID: (XMPPJID*)jid +{ +} + +- (void)connectionDidReceiveRoster: (XMPPConnection*)conn +{ +} + +- (BOOL)connection: (XMPPConnection*)conn + didReceiveIQ: (XMPPIQ*)iq +{ + return NO; +} + +- (void)connection: (XMPPConnection*)conn + didReceivePresence: (XMPPPresence*)pres +{ +} + +- (void)connection: (XMPPConnection*)conn + didReceiveMessage: (XMPPMessage*)msg +{ +} + +- (void)connectionWasClosed: (XMPPConnection*)conn +{ +} @end diff --git a/src/XMPPExceptions.h b/src/XMPPExceptions.h index 9926229..892a978 100644 --- a/src/XMPPExceptions.h +++ b/src/XMPPExceptions.h @@ -30,12 +30,15 @@ XMPPConnection *connection; } +#ifdef OF_HAVE_PROPERTIES @property (readonly, nonatomic) XMPPConnection *connection; +#endif + newWithClass: (Class)class_ connection: (XMPPConnection*)conn; - initWithClass: (Class)class_ connection: (XMPPConnection*)conn; +- (XMPPConnection*)connection; @end @interface XMPPStringPrepFailedException: XMPPException @@ -44,7 +47,9 @@ OFString *string; } +#ifdef OF_HAVE_PROPERTIES @property (readonly, nonatomic) OFString *profile, *string; +#endif + newWithClass: (Class)class_ connection: (XMPPConnection*)conn @@ -54,6 +59,8 @@ connection: (XMPPConnection*)conn profile: (OFString*)profile string: (OFString*)string; +- (OFString*)profile; +- (OFString*)string; @end @interface XMPPIDNATranslationFailedException: XMPPException @@ -62,7 +69,9 @@ OFString *string; } +#ifdef OF_HAVE_PROPERTIES @property (readonly, nonatomic) OFString *operation, *string; +#endif + newWithClass: (Class)class_ connection: (XMPPConnection*)conn @@ -72,6 +81,8 @@ connection: (XMPPConnection*)conn operation: (OFString*)operation string: (OFString*)string; +- (OFString*)operation; +- (OFString*)string; @end @interface XMPPAuthFailedException: XMPPException @@ -79,7 +90,9 @@ OFString *reason; } +#ifdef OF_HAVE_PROPERTIES @property (readonly, nonatomic) OFString *reason; +#endif + newWithClass: (Class)class_ connection: (XMPPConnection*)conn @@ -87,4 +100,5 @@ - initWithClass: (Class)class_ connection: (XMPPConnection*)conn reason: (OFString*)reason_; +- (OFString*)reason; @end diff --git a/src/XMPPExceptions.m b/src/XMPPExceptions.m index 357f8db..616ce3f 100644 --- a/src/XMPPExceptions.m +++ b/src/XMPPExceptions.m @@ -23,8 +23,6 @@ #import "XMPPExceptions.h" @implementation XMPPException -@synthesize connection; - + newWithClass: (Class)class_ connection: (XMPPConnection*)conn { @@ -72,11 +70,14 @@ return description; } + +- (XMPPConnection*)connection +{ + return connection; +} @end @implementation XMPPStringPrepFailedException -@synthesize profile, string; - + newWithClass: (Class)class_ connection: (XMPPConnection*)conn profile: (OFString*)profile @@ -135,11 +136,19 @@ return description; } + +- (OFString*)profile +{ + return profile; +} + +- (OFString*)string +{ + return string; +} @end @implementation XMPPIDNATranslationFailedException -@synthesize operation, string; - + newWithClass: (Class)class_ connection: (XMPPConnection*)conn operation: (OFString*)operation @@ -197,11 +206,19 @@ return description; } + +- (OFString*)operation +{ + return operation; +} + +- (OFString*)string +{ + return string; +} @end @implementation XMPPAuthFailedException -@synthesize reason; - + newWithClass: (Class)class_ connection: (XMPPConnection*)conn reason: (OFString*)reason_; @@ -254,4 +271,9 @@ return description; } + +- (OFString*)reason +{ + return reason; +} @end diff --git a/src/XMPPJID.h b/src/XMPPJID.h index ccfdc1f..e4199c8 100644 --- a/src/XMPPJID.h +++ b/src/XMPPJID.h @@ -28,17 +28,19 @@ */ @interface XMPPJID: OFObject { - /// The JID's localpart OFString *node; - /// The JID's domainpart OFString *domain; - /// The JID's resourcepart OFString *resource; } +#ifdef OF_HAVE_PROPERTIES +/// The JID's localpart @property (copy) OFString *node; +/// The JID's domainpart @property (copy) OFString *domain; +/// The JID's resourcepart @property (copy) OFString *resource; +#endif /** * Creates a new autoreleased XMPPJID. @@ -72,4 +74,11 @@ * \return An OFString containing the full JID */ - (OFString*)fullJID; + +- (void)setNode: (OFString*)node; +- (OFString*)node; +- (void)setDomain: (OFString*)domain; +- (OFString*)domain; +- (void)setResource: (OFString*)resource; +- (OFString*)resource; @end diff --git a/src/XMPPRoster.h b/src/XMPPRoster.h index 0bfdd51..faa8632 100644 --- a/src/XMPPRoster.h +++ b/src/XMPPRoster.h @@ -32,6 +32,7 @@ } - initWithConnection: (XMPPConnection*)conn; +- (void)XMPP_addRosterItem: (XMPPRosterItem*)rosterItem; - (OFArray*)groups; - (OFArray*)rosterItemsInGroup: (OFString*)group; - (void)addRosterItem: (XMPPRosterItem*)rosterItem; diff --git a/src/XMPPRoster.m b/src/XMPPRoster.m index 282e4d8..57795bd 100644 --- a/src/XMPPRoster.m +++ b/src/XMPPRoster.m @@ -21,7 +21,6 @@ */ #import "XMPPRoster.h" -#import "XMPPRoster_private.h" #import "XMPPRosterItem.h" #import "XMPPConnection.h" #import "XMPPIQ.h" @@ -52,8 +51,12 @@ - (void)XMPP_addRosterItem: (XMPPRosterItem*)rosterItem { - if (rosterItem.groups.count > 0) { - for (OFString *group in rosterItem.groups) { + if ([[rosterItem groups] count] > 0) { + OFEnumerator *enumerator; + OFString *group; + + enumerator = [[rosterItem groups] objectEnumerator]; + while ((group = [enumerator nextObject]) != nil) { OFMutableArray *rosterGroup = [groups objectForKey: group]; @@ -81,8 +84,11 @@ - (OFArray*)groups { OFMutableArray *ret = [OFMutableArray array]; + OFEnumerator *enumerator; + OFString *group; - for (OFString *group in groups) + enumerator = [groups keyEnumerator]; + while ((group = [enumerator nextObject]) != nil) [ret addObject: group]; ret->isa = [OFArray class]; @@ -110,14 +116,17 @@ namespace: XMPP_NS_ROSTER]; OFXMLElement *item = [OFXMLElement elementWithName: @"item" namespace: XMPP_NS_ROSTER]; + OFEnumerator *enumerator; + OFString *group; [item addAttributeWithName: @"jid" - stringValue: rosterItem.JID.bareJID]; - if (rosterItem.name != nil) + stringValue: [[rosterItem JID] bareJID]]; + if ([rosterItem name] != nil) [item addAttributeWithName: @"name" - stringValue: rosterItem.name]; + stringValue: [rosterItem name]]; - for (OFString *group in rosterItem.groups) + enumerator = [[rosterItem groups] objectEnumerator]; + while ((group = [enumerator nextObject]) != nil) [item addChild: [OFXMLElement elementWithName: @"group" namespace: XMPP_NS_ROSTER stringValue: group]]; @@ -138,7 +147,7 @@ namespace: XMPP_NS_ROSTER]; [item addAttributeWithName: @"jid" - stringValue: rosterItem.JID.bareJID]; + stringValue: [[rosterItem JID] bareJID]]; [item addAttributeWithName: @"subscription" stringValue: @"remove"]; diff --git a/src/XMPPRosterItem.h b/src/XMPPRosterItem.h index ffc3e66..0fbf74d 100644 --- a/src/XMPPRosterItem.h +++ b/src/XMPPRosterItem.h @@ -32,10 +32,20 @@ OFArray *groups; } +#ifdef OF_HAVE_PROPERTIES @property (copy) XMPPJID *JID; @property (copy) OFString *name; @property (copy) OFString *subscription; @property (copy) OFArray *groups; +#endif + rosterItem; +- (void)setJID: (XMPPJID*)JID; +- (XMPPJID*)JID; +- (void)setName: (OFString*)name; +- (OFString*)name; +- (void)setSubscription: (OFString*)subscription; +- (OFString*)subscription; +- (void)setGroups: (OFArray*)groups; +- (OFArray*)groups; @end diff --git a/src/XMPPRosterItem.m b/src/XMPPRosterItem.m index 80ba6c1..6bfeffb 100644 --- a/src/XMPPRosterItem.m +++ b/src/XMPPRosterItem.m @@ -23,13 +23,21 @@ #import "XMPPRosterItem.h" @implementation XMPPRosterItem -@synthesize JID, name, subscription, groups; - + rosterItem { return [[[self alloc] init] autorelease]; } +- (void)dealloc +{ + [JID release]; + [name release]; + [subscription release]; + [groups release]; + + [super dealloc]; +} + - copy { XMPPRosterItem *new = [[XMPPRosterItem alloc] init]; @@ -53,4 +61,52 @@ @"subscription=%@, groups=%@>", JID, name, subscription, groups]; } + +- (void)setJID: (XMPPJID*)JID_ +{ + XMPPJID *old = JID; + JID = [JID_ copy]; + [old release]; +} + +- (XMPPJID*)JID +{ + return [[JID copy] autorelease]; +} + +- (void)setName: (OFString*)name_ +{ + OFString *old = name; + name = [name_ copy]; + [old release]; +} + +- (OFString*)name +{ + return [[name copy] autorelease]; +} + +- (void)setSubscription: (OFString*)subscription_ +{ + OFString *old = subscription; + subscription = [subscription_ copy]; + [old release]; +} + +- (OFString*)subscription +{ + return [[subscription copy] autorelease]; +} + +- (void)setGroups: (OFArray*)groups_ +{ + OFArray *old = groups; + groups = [groups_ copy]; + [old release]; +} + +- (OFArray*)groups +{ + return [[groups copy] autorelease]; +} @end diff --git a/src/XMPPRoster_private.h b/src/XMPPRoster_private.h deleted file mode 100644 index a962657..0000000 --- a/src/XMPPRoster_private.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2011, Jonathan Schleifer - * - * https://webkeks.org/hg/objxmpp/ - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#import "XMPPRoster.h" - -@interface XMPPRoster () -- (void)XMPP_addRosterItem: (XMPPRosterItem*)rosterItem; -@end diff --git a/src/XMPPSCRAMAuth.h b/src/XMPPSCRAMAuth.h index ea39099..7c58135 100644 --- a/src/XMPPSCRAMAuth.h +++ b/src/XMPPSCRAMAuth.h @@ -88,4 +88,11 @@ authcid: (OFString*)authcid password: (OFString*)password hash: (Class)hash; + +- (OFString*)XMPP_genNonce; +- (uint8_t*)XMPP_HMACWithKey: (OFDataArray*)key + data: (OFDataArray*)data; +- (OFDataArray*)XMPP_hiWithData: (OFDataArray *)str + salt: (OFDataArray *)salt_ + iterationCount: (intmax_t)i; @end diff --git a/src/XMPPSCRAMAuth.m b/src/XMPPSCRAMAuth.m index a29b95d..8462708 100644 --- a/src/XMPPSCRAMAuth.m +++ b/src/XMPPSCRAMAuth.m @@ -33,15 +33,6 @@ extern uint32_t arc4random_uniform(uint32_t); #endif -@interface XMPPSCRAMAuth () -- (OFString*)XMPP_genNonce; -- (uint8_t*)XMPP_HMACWithKey: (OFDataArray*)key - data: (OFDataArray*)data; -- (OFDataArray*)XMPP_hiWithData: (OFDataArray *)str - salt: (OFDataArray *)salt_ - iterationCount: (intmax_t)i; -@end - @implementation XMPPSCRAMAuth + SCRAMAuthWithAuthcid: (OFString*)authcid password: (OFString*)password @@ -172,6 +163,8 @@ extern uint32_t arc4random_uniform(uint32_t); OFDataArray *ret, *authMessage, *tmpArray, *salt, *saltedPassword; OFString *tmpString, *sNonce; OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + OFEnumerator *enumerator; + OFString *comp; enum { GOT_SNONCE, GOT_SALT, GOT_ITERCOUNT } got = 0; @@ -184,7 +177,9 @@ extern uint32_t arc4random_uniform(uint32_t); length: [challenge count] * [challenge itemSize]]; - for (OFString *comp in [chal componentsSeparatedByString: @","]) { + enumerator = + [[chal componentsSeparatedByString: @","] objectEnumerator]; + while ((comp = [enumerator nextObject]) != nil) { OFString *entry = [comp substringFromIndex: 2 toIndex: [comp length]]; @@ -373,14 +368,14 @@ extern uint32_t arc4random_uniform(uint32_t); uint8_t *kCArray, *kI = NULL, *kO = NULL; OFHash *hash; - if (key.itemSize * key.count > blockSize) { + if ([key itemSize] * [key count] > blockSize) { hash = [[[hashType alloc] init] autorelease]; [hash updateWithBuffer: [key cArray] - ofSize: key.itemSize * key.count]; + ofSize: [key itemSize] * [key count]]; [k addNItems: [hashType digestSize] fromCArray: [hash digest]]; } else - [k addNItems: key.itemSize * key.count + [k addNItems: [key itemSize] * [key count] fromCArray: [key cArray]]; @try { @@ -391,7 +386,7 @@ extern uint32_t arc4random_uniform(uint32_t); memset(kO, HMAC_OPAD, blockSize * sizeof(uint8_t)); kCArray = [k cArray]; - kSize = k.count; + kSize = [k count]; for (i = 0; i < kSize; i++) { kI[i] ^= kCArray[i]; kO[i] ^= kCArray[i]; @@ -400,12 +395,12 @@ extern uint32_t arc4random_uniform(uint32_t); k = [OFDataArray dataArrayWithItemSize: 1]; [k addNItems: blockSize fromCArray: kI]; - [k addNItems: data.itemSize * data.count + [k addNItems: [data itemSize] * [data count] fromCArray: [data cArray]]; hash = [[[hashType alloc] init] autorelease]; [hash updateWithBuffer: [k cArray] - ofSize: k.count]; + ofSize: [k count]]; k = [OFDataArray dataArrayWithItemSize: 1]; [k addNItems: blockSize fromCArray: kO]; @@ -418,7 +413,7 @@ extern uint32_t arc4random_uniform(uint32_t); hash = [[[hashType alloc] init] autorelease]; [hash updateWithBuffer: [k cArray] - ofSize: k.count]; + ofSize: [k count]]; [hash retain]; [pool release]; diff --git a/src/XMPPStanza.h b/src/XMPPStanza.h index a2ce9a2..b8949f9 100644 --- a/src/XMPPStanza.h +++ b/src/XMPPStanza.h @@ -30,20 +30,22 @@ */ @interface XMPPStanza: OFXMLElement { - /// The value of the stanza's from attribute XMPPJID *from; - /// The value of the stanza's to attribute XMPPJID *to; - /// The value of the stanza's type attribute OFString *type; - /// The value of the stanza's id attribute OFString *ID; } +#ifdef OF_HAVE_PROPERTIES +/// The value of the stanza's from attribute @property (copy) XMPPJID *from; +/// The value of the stanza's to attribute @property (copy) XMPPJID *to; +/// The value of the stanza's type attribute @property (copy) OFString *type; +/// The value of the stanza's id attribute @property (copy) OFString *ID; +#endif /** * Creates a new autoreleased XMPPStanza with the specified name. @@ -141,4 +143,13 @@ * \return A initialized XMPPStanza */ - initWithElement: (OFXMLElement*)elem; + +- (void)setFrom: (XMPPJID*)from; +- (XMPPJID*)from; +- (void)setTo: (XMPPJID*)to; +- (XMPPJID*)to; +- (void)setType: (OFString*)type; +- (OFString*)type; +- (void)setID: (OFString*)ID; +- (OFString*)ID; @end diff --git a/src/XMPPStanza.m b/src/XMPPStanza.m index 28fd6ee..09f4c44 100644 --- a/src/XMPPStanza.m +++ b/src/XMPPStanza.m @@ -95,10 +95,10 @@ [self setDefaultNamespace: @"jabber:client"]; - if (type_) + if (type_ != nil) [self setType: type_]; - if (ID_) + if (ID_ != nil) [self setID: ID_]; } @catch (id e) { [self release]; @@ -110,26 +110,32 @@ - initWithElement: (OFXMLElement*)elem { - self = [super initWithName: elem.name - namespace: elem.namespace]; + self = [super initWithName: [elem name] + namespace: [elem namespace]]; @try { - for (OFXMLAttribute *attr in elem.attributes) { - if ([attr.name isEqual: @"from"]) + OFEnumerator *enumerator; + OFXMLAttribute *attr; + OFXMLElement *el; + + enumerator = [[elem attributes] objectEnumerator]; + while ((attr = [enumerator nextObject]) != nil) { + if ([[attr name] isEqual: @"from"]) [self setFrom: [XMPPJID JIDWithString: [attr stringValue]]]; - else if ([attr.name isEqual: @"to"]) + else if ([[attr name] isEqual: @"to"]) [self setTo: [XMPPJID JIDWithString: [attr stringValue]]]; - else if ([attr.name isEqual: @"type"]) + else if ([[attr name] isEqual: @"type"]) [self setType: [attr stringValue]]; - else if ([attr.name isEqual: @"id"]) + else if ([[attr name] isEqual: @"id"]) [self setID: [attr stringValue]]; else [self addAttribute: attr]; } - for (OFXMLElement *el in elem.children) + enumerator = [[elem children] objectEnumerator]; + while ((el = [enumerator nextObject]) != nil) [self addChild: el]; } @catch (id e) { [self release]; @@ -159,7 +165,7 @@ if (from_ != nil) [self addAttributeWithName: @"from" - stringValue: from_.fullJID]; + stringValue: [from_ fullJID]]; } - (XMPPJID*)from @@ -177,7 +183,7 @@ if (to_ != nil) [self addAttributeWithName: @"to" - stringValue: to_.fullJID]; + stringValue: [to_ fullJID]]; } - (XMPPJID*)to diff --git a/tests/test.m b/tests/test.m index 18c12a5..fda13fd 100644 --- a/tests/test.m +++ b/tests/test.m @@ -33,7 +33,10 @@ #import "XMPPPresence.h" #import "XMPPRoster.h" -@interface AppDelegate: OFObject +@interface AppDelegate: OFObject +#ifdef OF_HAVE_OPTIONAL_PROTOCOLS + +#endif @end OF_APPLICATION_DELEGATE(AppDelegate) @@ -48,8 +51,8 @@ OF_APPLICATION_DELEGATE(AppDelegate) [pres addShow: @"chat"]; [pres addStatus: @"Bored"]; [pres addPriority: 20]; - pres.to = [XMPPJID JIDWithString: @"alice@example.com"]; - pres.from = [XMPPJID JIDWithString: @"bob@example.org"]; + [pres setTo: [XMPPJID JIDWithString: @"alice@example.com"]]; + [pres setFrom: [XMPPJID JIDWithString: @"bob@example.org"]]; assert([[pres stringValue] isEqual: @"chat" @"Bored20" @@ -57,35 +60,39 @@ OF_APPLICATION_DELEGATE(AppDelegate) XMPPMessage *msg = [XMPPMessage messageWithType: @"chat"]; [msg addBody: @"Hello everyone"]; - msg.to = [XMPPJID JIDWithString: @"jdev@conference.jabber.org"]; - msg.from = [XMPPJID JIDWithString: @"alice@example.com"]; + [msg setTo: [XMPPJID JIDWithString: @"jdev@conference.jabber.org"]]; + [msg setFrom: [XMPPJID JIDWithString: @"alice@example.com"]]; assert([[msg stringValue] isEqual: @"Hello everyone" @""]); XMPPIQ *iq = [XMPPIQ IQWithType: @"set" ID: @"128"]; - iq.to = [XMPPJID JIDWithString: @"juliet@capulet.lit"]; - iq.from = [XMPPJID JIDWithString: @"romeo@montague.lit"]; + [iq setTo: [XMPPJID JIDWithString: @"juliet@capulet.lit"]]; + [iq setFrom: [XMPPJID JIDWithString: @"romeo@montague.lit"]]; assert([[iq stringValue] isEqual: @""]); OFXMLElement *elem = [OFXMLElement elementWithName: @"iq"]; - [elem addAttributeWithName: @"from" stringValue: @"bob@localhost"]; - [elem addAttributeWithName: @"to" stringValue: @"alice@localhost"]; - [elem addAttributeWithName: @"type" stringValue: @"get"]; - [elem addAttributeWithName: @"id" stringValue: @"42"]; + [elem addAttributeWithName: @"from" + stringValue: @"bob@localhost"]; + [elem addAttributeWithName: @"to" + stringValue: @"alice@localhost"]; + [elem addAttributeWithName: @"type" + stringValue: @"get"]; + [elem addAttributeWithName: @"id" + stringValue: @"42"]; XMPPStanza *stanza = [XMPPStanza stanzaWithElement: elem]; assert([[elem stringValue] isEqual: [stanza stringValue]]); assert(([[OFString stringWithFormat: @"%@, %@, %@, %@", - stanza.from.fullJID, stanza.to.fullJID, stanza.type, stanza.ID] - isEqual: @"bob@localhost, alice@localhost, get, 42"])); + [[stanza from] fullJID], [[stanza to] fullJID], [stanza type], + [stanza ID]] isEqual: @"bob@localhost, alice@localhost, get, 42"])); conn = [[XMPPConnection alloc] init]; - conn.delegate = self; + [conn setDelegate: self]; - if (arguments.count != 3) { + if ([arguments count] != 3) { of_log(@"Invalid count of command line arguments!"); [OFApplication terminateWithStatus: 1]; } @@ -94,7 +101,6 @@ OF_APPLICATION_DELEGATE(AppDelegate) [conn setUsername: [arguments objectAtIndex: 1]]; [conn setPassword: [arguments objectAtIndex: 2]]; [conn setResource: @"ObjXMPP"]; - [conn setUseTLS: NO]; [conn connect]; @try { @@ -120,11 +126,14 @@ OF_APPLICATION_DELEGATE(AppDelegate) - (void)connectionDidReceiveRoster :(XMPPConnection*)conn { XMPPPresence *pres; + OFEnumerator *enumerator; + OFString *group; - of_log(@"Got roster! Groups: %@", conn.roster.groups); - for (OFString *group in conn.roster.groups) + of_log(@"Got roster! Groups: %@", [[conn roster] groups]); + enumerator = [[[conn roster] groups] objectEnumerator]; + while ((group = [enumerator nextObject]) != nil) of_log(@"Group %@: %@", group, - [conn.roster rosterItemsInGroup: group]); + [[conn roster] rosterItemsInGroup: group]); pres = [XMPPPresence presence]; [pres addPriority: 10];