Index: src/XMPPConnection.h ================================================================== --- src/XMPPConnection.h +++ src/XMPPConnection.h @@ -65,11 +65,11 @@ #endif { OFTCPSocket *sock; OFXMLParser *parser, *oldParser; OFXMLElementBuilder *elementBuilder, *oldElementBuilder; - OFString *username, *password, *server, *resource; + OFString *username, *password, *server, *domain, *resource; XMPPJID *JID; uint16_t port; id delegate; XMPPAuthenticator *authModule; BOOL needsSession; @@ -77,11 +77,11 @@ OFString *bindID, *sessionID; XMPPRoster *roster; } #ifdef OF_HAVE_PROPERTIES -@property (copy) OFString *username, *password, *server, *resource; +@property (copy) OFString *username, *password, *server, *domain, *resource; @property (copy, readonly) XMPPJID *JID; @property (assign) uint16_t port; @property (retain) id delegate; @property (readonly, retain) XMPPRoster *roster; @property (readonly, retain, getter=socket) OFTCPSocket *sock; @@ -137,10 +137,12 @@ - (OFString*)username; - (void)setPassword: (OFString*)password; - (OFString*)password; - (void)setServer: (OFString*)server; - (OFString*)server; +- (void)setDomain: (OFString*)domain; +- (OFString*)domain; - (void)setResource: (OFString*)resource; - (OFString*)resource; - (XMPPJID*)JID; - (void)setPort: (uint16_t)port; - (uint16_t)port; Index: src/XMPPConnection.m ================================================================== --- src/XMPPConnection.m +++ src/XMPPConnection.m @@ -75,10 +75,11 @@ [parser release]; [elementBuilder release]; [username release]; [password release]; [server release]; + [domain release]; [resource release]; [JID release]; [delegate release]; [authModule release]; [bindID release]; @@ -168,10 +169,37 @@ - (OFString*)server { return [[server copy] autorelease]; } + +- (void)setDomain: (OFString*)domain_ +{ + OFString *old = domain; + char *srv; + Stringprep_rc rc; + + if ((rc = stringprep_profile([domain_ cString], &srv, + "Nameprep", 0)) != STRINGPREP_OK) + @throw [XMPPStringPrepFailedException newWithClass: isa + connection: self + profile: @"Nameprep" + string: domain_]; + + @try { + domain = [[OFString alloc] initWithCString: srv]; + } @finally { + free(srv); + } + + [old release]; +} + +- (OFString*)domain +{ + return [[domain copy] autorelease]; +} - (void)setPassword: (OFString*)password_ { OFString *old = password; char *pass; @@ -199,29 +227,61 @@ } - (void)connect { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - XMPPSRVLookup *SRVLookup = [XMPPSRVLookup lookupWithDomain: server]; - OFEnumerator *enumerator = [SRVLookup objectEnumerator]; - XMPPSRVEntry *candidate; - - while ((candidate = [enumerator nextObject]) != nil) { - @try { - [sock connectToHost: [candidate target] - onPort: [candidate port]]; - break; - } @catch (OFAddressTranslationFailedException *e) { - [e release]; - } @catch (OFConnectionFailedException *e) { - [e release]; - } - } - - if (!candidate) + XMPPSRVEntry *candidate = nil; + XMPPSRVLookup *SRVLookup; + OFEnumerator *enumerator; + OFString *domainToASCII; + char *cDomainToASCII; + Idna_rc rc; + + if (server) [sock connectToHost: server onPort: port]; + else { + if ((rc = idna_to_ascii_8z([domain cString], &cDomainToASCII, + IDNA_USE_STD3_ASCII_RULES)) != IDNA_SUCCESS) + @throw [XMPPIDNATranslationFailedException + newWithClass: isa + connection: self + operation: @"ToASCII" + string: domain]; + + @try { + domainToASCII = [OFString + stringWithCString: cDomainToASCII]; + } @finally { + free(cDomainToASCII); + } + + @try { + SRVLookup = [XMPPSRVLookup + lookupWithDomain: domainToASCII]; + enumerator = [SRVLookup objectEnumerator]; + + while ((candidate = [enumerator nextObject]) != nil) { + @try { + [sock connectToHost: [candidate target] + onPort: [candidate port]]; + break; + } @catch (OFAddressTranslationFailedException + *e) { + [e release]; + } @catch (OFConnectionFailedException *e) { + [e release]; + } + } + } @catch (OFAddressTranslationFailedException *e) { + [e release]; + } + + if (!candidate) + [sock connectToHost: domainToASCII + onPort: port]; + } [self XMPP_startStream]; [pool release]; } @@ -292,11 +352,11 @@ } enumerator = [attributes objectEnumerator]; while ((attribute = [enumerator nextObject]) != nil) { if ([[attribute name] isEqual: @"from"] && - ![[attribute stringValue] isEqual: server]) { + ![[attribute stringValue] isEqual: domain]) { of_log(@"Got invalid from in stream start!"); assert(0); } } @@ -367,11 +427,11 @@ [sock writeFormat: @"\n" @"", server]; + @"version='1.0'>", domain]; } - (void)XMPP_handleStanza: (OFXMLElement*)element { if ([[element name] isEqual: @"iq"]) { Index: tests/test.m ================================================================== --- tests/test.m +++ tests/test.m @@ -95,11 +95,11 @@ if ([arguments count] != 3) { of_log(@"Invalid count of command line arguments!"); [OFApplication terminateWithStatus: 1]; } - [conn setServer: [arguments objectAtIndex: 0]]; + [conn setDomain: [arguments objectAtIndex: 0]]; [conn setUsername: [arguments objectAtIndex: 1]]; [conn setPassword: [arguments objectAtIndex: 2]]; [conn setResource: @"ObjXMPP"]; @try {