Index: src/XMPPConnection.h ================================================================== --- src/XMPPConnection.h +++ src/XMPPConnection.h @@ -37,10 +37,11 @@ #define XMPP_NS_ROSTER @"jabber:iq:roster" #define XMPP_NS_SASL @"urn:ietf:params:xml:ns:xmpp-sasl" #define XMPP_NS_STARTTLS @"urn:ietf:params:xml:ns:xmpp-tls" #define XMPP_NS_STANZAS @"urn:ietf:params:xml:ns:xmpp-stanzas" #define XMPP_NS_SESSION @"urn:ietf:params:xml:ns:xmpp-session" +#define XMPP_NS_XMPP_STREAM @"urn:ietf:params:xml:ns:xmpp-streams" #define XMPP_NS_STREAM @"http://etherx.jabber.org/streams" @protocol XMPPConnectionDelegate #ifndef XMPP_CONNECTION_M Index: src/XMPPConnection.m ================================================================== --- src/XMPPConnection.m +++ src/XMPPConnection.m @@ -283,10 +283,23 @@ [parser setDelegate: elementBuilder]; [pool release]; } + +- (void)parser: (OFXMLParser*)p + didEndElement: (OFString*)name + withPrefix: (OFString*)prefix + namespace: (OFString*)ns + attributes: (OFArray*)attrs +{ + if (![name isEqual: @"stream"] || ![prefix isEqual: @"stream"] || + ![ns isEqual: XMPP_NS_STREAM]) { + of_log(@"Did not get expected stream end!"); + assert(0); + } +} - (void)elementBuilder: (OFXMLElementBuilder*)b didBuildElement: (OFXMLElement*)elem { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; @@ -348,10 +361,105 @@ { if ([[elem name] isEqual: @"features"]) { [self XMPP_handleFeatures: elem]; return; } + + if ([[elem name] isEqual: @"error"]) { + OFString *condition, *reason; + [parser setDelegate: self]; + [sock writeString: @""]; + [sock close]; + + if ([elem elementForName: @"bad-format" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"bad-format"; + else if ([elem elementForName: @"bad-namespace-prefix" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"bad-namespace-prefix"; + else if ([elem elementForName: @"conflict" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"conflict"; + else if ([elem elementForName: @"connection-timeout" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"connection-timeout"; + else if ([elem elementForName: @"host-gone" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"host-gone"; + else if ([elem elementForName: @"host-unknown" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"host-unknown"; + else if ([elem elementForName: @"improper-addressing" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"improper-addressing"; + else if ([elem elementForName: @"internal-server-error" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"internal-server-error"; + else if ([elem elementForName: @"invalid-from" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"invalid-from"; + else if ([elem elementForName: @"invalid-namespace" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"invalid-namespace"; + else if ([elem elementForName: @"invalid-xml" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"invalid-xml"; + else if ([elem elementForName: @"not-authorized" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"not-authorized"; + else if ([elem elementForName: @"not-well-formed" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"not-well-formed"; + else if ([elem elementForName: @"policy-violation" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"policy-violation"; + else if ([elem elementForName: @"remote-connection-failed" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"remote-connection-failed"; + else if ([elem elementForName: @"reset" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"reset"; + else if ([elem elementForName: @"resource-constraint" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"resource-constraint"; + else if ([elem elementForName: @"restricted-xml" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"restricted-xml"; + else if ([elem elementForName: @"see-other-host" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"see-other-host"; + else if ([elem elementForName: @"system-shutdown" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"system-shutdown"; + else if ([elem elementForName: @"undefined-condition" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"undefined-condition"; + else if ([elem elementForName: @"unsupported-encoding" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"unsupported-encoding"; + else if ([elem elementForName: @"unsupported-feature" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"unsupported-feature"; + else if ([elem elementForName: @"unsupported-stanza-type" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"unsupported-stanza-type"; + else if ([elem elementForName: @"unsupported-version" + namespace: XMPP_NS_XMPP_STREAM]) + condition = @"unsupported-version"; + else + condition = @"undefined"; + + reason = [[elem elementForName: @"text" + namespace: XMPP_NS_XMPP_STREAM] + stringValue]; + + @throw [XMPPStreamErrorException newWithClass: isa + connection: self + condition: condition + reason: reason]; + return; + } assert(0); } - (void)XMPP_handleTLS: (OFXMLElement*)elem Index: src/XMPPExceptions.h ================================================================== --- src/XMPPExceptions.h +++ src/XMPPExceptions.h @@ -38,10 +38,33 @@ connection: (XMPPConnection*)conn; - initWithClass: (Class)class_ connection: (XMPPConnection*)conn; - (XMPPConnection*)connection; @end + +@interface XMPPStreamErrorException: XMPPException +{ + OFString *condition; + OFString *reason; +} + +#ifdef OF_HAVE_PROPERTIES +@property (readonly, nonatomic) OFString *condition; +@property (readonly, nonatomic) OFString *reason; +#endif + ++ newWithClass: (Class)class_ + connection: (XMPPConnection*)conn + condition: (OFString*)condition_ + reason: (OFString*)reason_; +- initWithClass: (Class)class_ + connection: (XMPPConnection*)conn + condition: (OFString*)condition_ + reason: (OFString*)reason_; +- (OFString*)condition; +- (OFString*)reason; +@end @interface XMPPStringPrepFailedException: XMPPException { OFString *profile; OFString *string; Index: src/XMPPExceptions.m ================================================================== --- src/XMPPExceptions.m +++ src/XMPPExceptions.m @@ -74,10 +74,80 @@ - (XMPPConnection*)connection { return connection; } @end + +@implementation XMPPStreamErrorException ++ newWithClass: (Class)class_ + connection: (XMPPConnection*)conn + condition: (OFString*)condition_ + reason: (OFString*)reason_; +{ + return [[self alloc] initWithClass: class_ + connection: conn + condition: condition_ + reason: reason_]; +} + +- initWithClass: (Class)class_ + connection: (XMPPConnection*)conn +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException newWithClass: c + selector: _cmd]; +} + +- initWithClass: (Class)class_ + connection: (XMPPConnection*)conn + condition: (OFString*)condition_ + reason: (OFString*)reason_ +{ + self = [super initWithClass: class_ + connection: conn]; + + @try { + condition = [condition_ copy]; + reason = [reason_ copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [condition release]; + [reason release]; + + [super dealloc]; +} + +- (OFString*)description +{ + if (description != nil) + return description; + + description = [[OFString alloc] initWithFormat: + @"Got stream error: %@. Reason: %@!", condition, reason]; + + return description; +} + +- (OFString*)condition +{ + return condition; +} + +- (OFString*)reason +{ + return reason; +} +@end @implementation XMPPStringPrepFailedException + newWithClass: (Class)class_ connection: (XMPPConnection*)conn profile: (OFString*)profile