diff --git a/src/XMPPConnection.h b/src/XMPPConnection.h index 3d8d738..e56d91c 100644 --- a/src/XMPPConnection.h +++ b/src/XMPPConnection.h @@ -1,8 +1,7 @@ #import -#import "XMPPJID.h" - @class XMPPConnection; +@class XMPPJID; @class XMPPIQ; @class XMPPMessage; @class XMPPPresence; @@ -18,47 +17,26 @@ @end /** - * \brief A class that abstracts a connection to an XMPP service + * \brief A class which abstracts a connection to an XMPP service. */ @interface XMPPConnection: OFObject { OFTCPSocket *sock; OFXMLParser *parser; OFXMLElementBuilder *elementBuilder; - - /** - * The username to connect with - */ + /// The username to connect with OFString *username; - - /** - * The password to connect with - */ + /// The password to connect with OFString *password; - - /** - * The server to connect to - */ + /// The server to connect to OFString *server; - - /** - * The resource to connect with - */ + /// The resource to connect with OFString *resource; - - /** - * The JID bound to this connection (this is determined by the server) - */ + /// The JID bound to this connection (this is determined by the server) XMPPJID *JID; - - /** - * The port to connect to - */ + /// The port to connect to short port; - - /** - * Whether to use TLS - */ + /// Whether to use TLS BOOL useTLS; id delegate; OFMutableArray *mechanisms; @@ -68,23 +46,23 @@ @property (copy) OFString *password; @property (copy) OFString *server; @property (copy) OFString *resource; -@property (readonly) XMPPJID *JID; +@property (copy, readonly) XMPPJID *JID; @property (assign) short port; @property (assign) BOOL useTLS; @property (retain) id delegate; /** - * Connects to the XMPP service + * Connects to the XMPP service. */ - (void)connect; /** - * Starts a loop handling incomming data + * Starts a loop handling incomming data. */ - (void)handleConnection; /** - * Sends a OFXMLElement (usually a XMPPStanza) + * Sends an OFXMLElement, usually an XMPPStanza. * * \param elem The element to send */ diff --git a/src/XMPPConnection.m b/src/XMPPConnection.m index e5126a8..d55f3ff 100644 --- a/src/XMPPConnection.m +++ b/src/XMPPConnection.m @@ -4,6 +4,7 @@ #import "XMPPConnection.h" #import "XMPPStanza.h" +#import "XMPPJID.h" #import "XMPPIQ.h" #define NS_BIND @"urn:ietf:params:xml:ns:xmpp-bind" @@ -55,8 +56,8 @@ char *node; Stringprep_rc rc; - if ((rc = stringprep_profile([username_ cString], &node, "SASLprep", 0)) - != STRINGPREP_OK) { + if ((rc = stringprep_profile([username_ cString], &node, + "SASLprep", 0)) != STRINGPREP_OK) { of_log(@"SASLprep failed: %s", stringprep_strerror(rc)); assert(0); } @@ -76,8 +77,8 @@ char *res; Stringprep_rc rc; - if ((rc = stringprep_profile([resource_ cString], &res, "Resourceprep", 0)) - != STRINGPREP_OK) { + if ((rc = stringprep_profile([resource_ cString], &res, + "Resourceprep", 0)) != STRINGPREP_OK) { of_log(@"Resourceprep failed: %s", stringprep_strerror(rc)); assert(0); } @@ -97,8 +98,8 @@ char *srv; Stringprep_rc rc; - if ((rc = stringprep_profile([server_ cString], &srv, "Nameprep", 0)) - != STRINGPREP_OK) { + if ((rc = stringprep_profile([server_ cString], &srv, + "Nameprep", 0)) != STRINGPREP_OK) { of_log(@"Nameprep failed: %s", stringprep_strerror(rc)); assert(0); } @@ -118,8 +119,8 @@ char *pass; Stringprep_rc rc; - if ((rc = stringprep_profile([password_ cString], &pass, "SASLprep", 0)) - != STRINGPREP_OK) { + if ((rc = stringprep_profile([password_ cString], &pass, + "SASLprep", 0)) != STRINGPREP_OK) { of_log(@"SASLprep failed: %s", stringprep_strerror(rc)); assert(0); } @@ -145,7 +146,8 @@ { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - [sock connectToHost: server onPort: port]; + [sock connectToHost: server + onPort: port]; [self _startStream]; [pool release]; @@ -181,13 +183,18 @@ attributes: (OFArray*)attrs { if (![name isEqual: @"stream"] || ![prefix isEqual: @"stream"] || - ![ns isEqual: NS_STREAM]) + ![ns isEqual: NS_STREAM]) { of_log(@"Did not get expected stream start!"); + assert(0); + } - for (OFXMLAttribute *attr in attrs) + for (OFXMLAttribute *attr in attrs) { if ([attr.name isEqual: @"from"] && - ![attr.stringValue isEqual: server]) + ![attr.stringValue isEqual: server]) { of_log(@"Got invalid from in stream start!"); + assert(0); + } + } parser.delegate = elementBuilder; } @@ -244,11 +251,12 @@ - (void)_handleResourceBind: (XMPPIQ*)iq { OFXMLElement *bindElem = iq.children.firstObject; + if ([bindElem.name isEqual: @"bind"] && [bindElem.namespace isEqual: NS_BIND]) { OFXMLElement *jidElem = bindElem.children.firstObject; JID = [[XMPPJID alloc] initWithString: - [jidElem.children.firstObject stringValue]]; + [jidElem.children.firstObject stringValue]]; of_log(@"Bound to JID: %@", [JID fullJID]); } } @@ -302,9 +310,10 @@ if ([elem.name isEqual: @"iq"] && [elem.namespace isEqual: NS_CLIENT]) { XMPPIQ *iq = [XMPPIQ stanzaWithElement: elem]; - if ([iq.ID isEqual: @"bind0"] && [iq.type isEqual: @"result"]) { + + // FIXME: More checking! + if ([iq.ID isEqual: @"bind0"] && [iq.type isEqual: @"result"]) [self _handleResourceBind: iq]; - } } } diff --git a/src/XMPPIQ.h b/src/XMPPIQ.h index 9e61ab3..7dd6eca 100644 --- a/src/XMPPIQ.h +++ b/src/XMPPIQ.h @@ -1,11 +1,11 @@ #import "XMPPStanza.h" /** - * \brief A class describing a IQ stanza + * \brief A class describing an IQ stanza. */ @interface XMPPIQ: XMPPStanza /** - * Creates a new XMPPIQ with a certain type and id + * Creates a new XMPPIQ with the specified type and id. * * \param type The value for the stanza's type attribute * \param ID The value for the stanza's id attribute @@ -15,7 +15,7 @@ ID: (OFString*)ID; /** - * Initializes an already allocated XMPPIQ with a certain type and id + * Initializes an already allocated XMPPIQ with the specified type and id * * \param type The value for the stanza's type attribute * \param ID The value for the stanza's id attribute diff --git a/src/XMPPIQ.m b/src/XMPPIQ.m index 483c751..4f067bd 100644 --- a/src/XMPPIQ.m +++ b/src/XMPPIQ.m @@ -11,14 +11,14 @@ - initWithType: (OFString*)type_ ID: (OFString*)ID_ { - if (!([type_ isEqual: @"get"] || - [type_ isEqual: @"set"] || - [type_ isEqual: @"result"] || - [type_ isEqual: @"error"])) + if (![type_ isEqual: @"get"] && + ![type_ isEqual: @"set"] && + ![type_ isEqual: @"result"] && + ![type_ isEqual: @"error"]) of_log(@"Invalid IQ type!"); return [super initWithName: @"iq" - type: type_ - ID: ID_]; + type: type_ + ID: ID_]; } @end diff --git a/src/XMPPJID.h b/src/XMPPJID.h index fe2ce41..fb1d7b7 100644 --- a/src/XMPPJID.h +++ b/src/XMPPJID.h @@ -1,23 +1,15 @@ #import /** - * \brief A class for easy handling of JIDs + * \brief A class for easy handling of JIDs. */ @interface XMPPJID: OFObject { - /** - * The JID's localpart - */ + /// The JID's localpart OFString *node; - - /** - * The JID's domainpart - */ + /// The JID's domainpart OFString *domain; - - /** - * The JID's resourcepart - */ + /// The JID's resourcepart OFString *resource; } @@ -26,14 +18,14 @@ @property (copy) OFString *resource; /** - * Creates a new XMPPJID + * Creates a new autoreleased XMPPJID. * * \return A new autoreleased XMPPJID */ + JID; /** - * Creates a new XMPPJID from a OFString + * Creates a new autoreleased XMPPJID from a string. * * \param str The string to parse into a JID object * \return A new autoreleased XMPPJID @@ -41,7 +33,7 @@ + JIDWithString: (OFString*)str; /** - * Initializes an already allocated XMPPJID using a OFString + * Initializes an already allocated XMPPJID with a string. * * \param str The string to parse into a JID object * \return A initialized XMPPJID @@ -49,12 +41,12 @@ - initWithString: (OFString*)str; /** - * \return A OFString containing the bare JID + * \return An OFString containing the bare JID */ - (OFString*)bareJID; /** - * \return A OFString containing the full JID + * \return An OFString containing the full JID */ - (OFString*)fullJID; @end diff --git a/src/XMPPJID.m b/src/XMPPJID.m index 3ab9e83..df23d6f 100644 --- a/src/XMPPJID.m +++ b/src/XMPPJID.m @@ -1,5 +1,7 @@ #include + #include + #import "XMPPJID.h" @implementation XMPPJID @@ -25,14 +27,14 @@ nodesep = [str indexOfFirstOccurrenceOfString: @"@"]; resourcesep = [str indexOfFirstOccurrenceOfString: @"/"]; - if (nodesep == -1) - [self setNode: @""]; + if (nodesep == SIZE_MAX) + [self setNode: nil]; else [self setNode: [str substringFromIndex: 0 toIndex: nodesep]]; - if (resourcesep == -1) { - [self setResource: @""]; + if (resourcesep == SIZE_MAX) { + [self setResource: nil]; resourcesep = [str length]; } else [self setResource: [str substringFromIndex: resourcesep + 1 @@ -48,10 +50,16 @@ { OFString *old = node; char *nodepart; - Stringprep_rc rc; - if ((rc = stringprep_profile([node_ cString], &nodepart, "Nodeprep", 0)) - != STRINGPREP_OK) { + + if (node_ == nil) { + [old release]; + node = nil; + return; + } + + if ((rc = stringprep_profile([node_ cString], &nodepart, + "Nodeprep", 0)) != STRINGPREP_OK) { of_log(@"Nodeprep failed: %s", stringprep_strerror(rc)); assert(0); } @@ -69,10 +77,10 @@ { OFString *old = domain; char *srv; - Stringprep_rc rc; - if ((rc = stringprep_profile([domain_ cString], &srv, "Nameprep", 0)) - != STRINGPREP_OK) { + + if ((rc = stringprep_profile([domain_ cString], &srv, + "Nameprep", 0)) != STRINGPREP_OK) { of_log(@"Nameprep failed: %s", stringprep_strerror(rc)); assert(0); } @@ -90,10 +98,16 @@ { OFString *old = resource; char *res; - Stringprep_rc rc; + + if (resource_ == nil) { + [old release]; + resource = nil; + return; + } + if ((rc = stringprep_profile([resource_ cString], &res, - "Resourceprep", 0)) != STRINGPREP_OK) { + "Resourceprep", 0)) != STRINGPREP_OK) { of_log(@"Resourceprep failed: %s", stringprep_strerror(rc)); assert(0); } @@ -109,7 +123,7 @@ - (OFString*)bareJID { - if ([node length]) + if (node != nil) return [OFString stringWithFormat: @"%@@%@", node, domain]; else return [OFString stringWithFormat: @"%@", domain]; @@ -117,7 +131,7 @@ - (OFString*)fullJID { - if ([node length]) + if (node != nil) return [OFString stringWithFormat: @"%@@%@/%@", node, domain, resource]; else diff --git a/src/XMPPMessage.h b/src/XMPPMessage.h index c1dd208..0737a0c 100644 --- a/src/XMPPMessage.h +++ b/src/XMPPMessage.h @@ -1,21 +1,18 @@ #import "XMPPStanza.h" /** - * \brief A class describing a message stanza + * \brief A class describing a message stanza. */ @interface XMPPMessage: XMPPStanza -{ -} - /** - * Creates a new XMPPMessage + * Creates a new autoreleased XMPPMessage. * * \return A new autoreleased XMPPMessage */ + message; /** - * Creates a new XMPPMessage with a certain id + * Creates a new autoreleased XMPPMessage with the specified id. * * \param ID The value for the stanza's id attribute * \return A new autoreleased XMPPMessage @@ -23,7 +20,7 @@ + messageWithID: (OFString*)ID; /** - * Creates a new XMPPMessage with a certain type + * Creates a new autoreleased XMPPMessage with the specified type. * * \param type The value for the stanza's type attribute * \return A new autoreleased XMPPMessage @@ -31,7 +28,7 @@ + messageWithType: (OFString*)type; /** - * Creates a new XMPPMessage with a certain type and id + * Creates a new autoreleased XMPPMessage with the specified type and id. * * \param type The value for the stanza's type attribute * \param ID The value for the stanza's id attribute @@ -41,14 +38,14 @@ ID: (OFString*)ID; /** - * Initializes an already allocated XMPPMessage + * Initializes an already allocated XMPPMessage. * * \return A initialized XMPPMessage */ - init; /** - * Initializes an already allocated XMPPMessage with a certain id + * Initializes an already allocated XMPPMessage with the specified id. * * \param ID The value for the stanza's id attribute * \return A initialized XMPPMessage @@ -56,7 +53,7 @@ - initWithID: (OFString*)ID; /** - * Initializes an already allocated XMPPMessage with a certain type + * Initializes an already allocated XMPPMessage with the specified type. * * \param type The value for the stanza's type attribute * \return A initialized XMPPMessage @@ -64,7 +61,7 @@ - initWithType: (OFString*)type; /** - * Initializes an already allocated XMPPMessage with a certain type and id + * Initializes an already allocated XMPPMessage with the specified type and id. * * \param type The value for the stanza's type attribute * \param ID The value for the stanza's id attribute diff --git a/src/XMPPPresence.h b/src/XMPPPresence.h index a918645..458b911 100644 --- a/src/XMPPPresence.h +++ b/src/XMPPPresence.h @@ -1,21 +1,18 @@ #import "XMPPStanza.h" /** - * \brief A class describing a presence stanza + * \brief A class describing a presence stanza. */ @interface XMPPPresence: XMPPStanza -{ -} - /** - * Creates a new XMPPPresence + * Creates a new autoreleased XMPPPresence. * * \return A new autoreleased XMPPPresence */ + presence; /** - * Creates a new XMPPPresence with a certain id + * Creates a new autoreleased XMPPPresence with the specified id. * * \param ID The value for the stanza's id attribute * \return A new autoreleased XMPPPresence @@ -23,7 +20,7 @@ + presenceWithID: (OFString*)ID; /** - * Creates a new XMPPPresence with a certain type + * Creates a new autoreleased XMPPPresence with the specified type. * * \param type The value for the stanza's type attribute * \return A new autoreleased XMPPPresence @@ -31,7 +28,7 @@ + presenceWithType: (OFString*)type; /** - * Creates a new XMPPPresence with a certain type and id + * Creates a new autoreleased XMPPPresence with the specified type and id. * * \param type The value for the stanza's type attribute * \param ID The value for the stanza's id attribute @@ -41,14 +38,14 @@ ID: (OFString*)ID; /** - * Initializes an already allocated XMPPPresence + * Initializes an already allocated XMPPPresence. * * \return A initialized XMPPPresence */ - init; /** - * Initializes an already allocated XMPPPresence with a certain id + * Initializes an already allocated XMPPPresence with the specified id. * * \param ID The value for the stanza's id attribute * \return A initialized XMPPPresence @@ -56,7 +53,7 @@ - initWithID: (OFString*)ID; /** - * Initializes an already allocated XMPPPresence with a certain type + * Initializes an already allocated XMPPPresence with the specified type. * * \param type The value for the stanza's type attribute * \return A initialized XMPPPresence @@ -64,7 +61,7 @@ - initWithType: (OFString*)type; /** - * Initializes an already allocated XMPPPresence with a certain type and id + * Initializes an already allocated XMPPPresence with the specified type and id. * * \param type The value for the stanza's type attribute * \param ID The value for the stanza's id attribute @@ -74,21 +71,21 @@ ID: (OFString*)ID; /** - * Adds a show element to the presence stanza + * Adds a show element to the presence stanza. * * \param show The text content of the show element */ - (void)addShow: (OFString*)show; /** - * Adds a status element to the presence stanza + * Adds a status element to the presence stanza. * * \param status The text content of the status element */ - (void)addStatus: (OFString*)status; /** - * Adds a priority element to the presence stanza + * Adds a priority element to the presence stanza. * * \param priority The text content of the priority element */ diff --git a/src/XMPPStanza.h b/src/XMPPStanza.h index 176fd21..ac681e4 100644 --- a/src/XMPPStanza.h +++ b/src/XMPPStanza.h @@ -1,28 +1,17 @@ #import /** - * \brief A class describing a XMPP Stanza + * \brief A class describing an XMPP Stanza. */ @interface XMPPStanza: OFXMLElement { - /** - * The value of the stanza's from attribute - */ + /// The value of the stanza's from attribute OFString *from; - - /** - * The value of the stanza's to attribute - */ + /// The value of the stanza's to attribute OFString *to; - - /** - * The value of the stanza's type attribute - */ + /// The value of the stanza's type attribute OFString *type; - - /** - * The value of the stanza's id attribute - */ + /// The value of the stanza's id attribute OFString *ID; } @@ -32,7 +21,7 @@ @property (copy) OFString *ID; /** - * Creates a new XMPPStanza with a certain name + * Creates a new autoreleased XMPPStanza with the specified name. * * \param name The stanza's name (one of iq, message or presence) * \return A new autoreleased XMPPStanza @@ -40,7 +29,7 @@ + stanzaWithName: (OFString*)name; /** - * Creates a new XMPPStanza with a certain name and type + * Creates a new autoreleased XMPPStanza with the specified name and type. * * \param name The stanza's name (one of iq, message or presence) * \param type The value for the stanza's type attribute @@ -50,7 +39,7 @@ type: (OFString*)type; /** - * Creates a new XMPPStanza with a certain name and id + * Creates a new autoreleased XMPPStanza with the specified name and id. * * \param name The stanza's name (one of iq, message or presence) * \param ID The value for the stanza's id attribute @@ -60,7 +49,7 @@ ID: (OFString*)ID; /** - * Creates a new XMPPStanza with a certain name, type and id + * Creates a new autoreleased XMPPStanza with the specified name, type and id. * * \param name The stanza's name (one of iq, message or presence) * \param type The value for the stanza's type attribute @@ -72,7 +61,7 @@ ID: (OFString*)ID; /** - * Creates a new XMPPStanza from a OFXMLElement + * Creates a new autoreleased XMPPStanza from an OFXMLElement. * * \param elem The element to base the XMPPStanza on * \return A new autoreleased XMPPStanza @@ -80,7 +69,7 @@ + stanzaWithElement: (OFXMLElement*)elem; /** - * Initializes an already allocated XMPPStanza with a certain name + * Initializes an already allocated XMPPStanza with the specified name. * * \param name The stanza's name (one of iq, message or presence) * \return A initialized XMPPStanza @@ -88,27 +77,28 @@ - initWithName: (OFString*)name; /** - * Initializes an already allocated XMPPStanza with a certain name and type + * Initializes an already allocated XMPPStanza with the specified name and type. * * \param name The stanza's name (one of iq, message or presence) * \param type The value for the stanza's type attribute * \return A initialized XMPPStanza */ - initWithName: (OFString*)name - type: (OFString*)type; + type: (OFString*)type; /** - * Initializes an already allocated XMPPStanza with a certain name and id + * Initializes an already allocated XMPPStanza with the specified name and id. * * \param name The stanza's name (one of iq, message or presence) * \param ID The value for the stanza's id attribute * \return A initialized XMPPStanza */ - initWithName: (OFString*)name - ID: (OFString*)ID; + ID: (OFString*)ID; /** - * Initializes an already allocated XMPPStanza with a certain name, type and id + * Initializes an already allocated XMPPStanza with the specified name, type + * and id. * * \param name The stanza's name (one of iq, message or presence) * \param type The value for the stanza's type attribute @@ -116,8 +106,8 @@ * \return A initialized XMPPStanza */ - initWithName: (OFString*)name - type: (OFString*)type - ID: (OFString*)ID; + type: (OFString*)type + ID: (OFString*)ID; /** * Initializes an already allocated XMPPStanza based on a OFXMLElement diff --git a/src/XMPPStanza.m b/src/XMPPStanza.m index 8f8437a..c95134e 100644 --- a/src/XMPPStanza.m +++ b/src/XMPPStanza.m @@ -65,17 +65,26 @@ type: (OFString*)type_ ID: (OFString*)ID_ { - if (!([name_ isEqual: @"iq"] || - [name_ isEqual: @"message"] || - [name_ isEqual: @"presence"])) + if (![name_ isEqual: @"iq"] && + ![name_ isEqual: @"message"] && + ![name_ isEqual: @"presence"]) of_log(@"Invalid stanza name!"); self = [super initWithName: name_]; - [self setDefaultNamespace: @"jabber:client"]; - if (type_) - [self setType: type_]; - if (ID_) - [self setID: ID_]; + + @try { + [self setDefaultNamespace: @"jabber:client"]; + + if (type_) + [self setType: type_]; + + if (ID_) + [self setID: ID_]; + } @catch (id e) { + [self release]; + @throw e; + } + return self; } @@ -84,26 +93,28 @@ self = [super initWithName: elem.name namespace: elem.namespace]; - OFXMLAttribute *attr; + @try { + OFXMLAttribute *attr; + OFXMLElement *el; - for (attr in elem.attributes) { - if ([attr.name isEqual: @"from"]) { - [self setFrom: [attr stringValue]]; - } else if ([attr.name isEqual: @"to"]) { - [self setTo: [attr stringValue]]; - } else if ([attr.name isEqual: @"type"]) { - [self setType: [attr stringValue]]; - } else if ([attr.name isEqual: @"id"]) { - [self setID: [attr stringValue]]; - } else { - [self addAttribute: attr]; + for (attr in elem.attributes) { + if ([attr.name isEqual: @"from"]) + [self setFrom: [attr stringValue]]; + else if ([attr.name isEqual: @"to"]) + [self setTo: [attr stringValue]]; + else if ([attr.name isEqual: @"type"]) + [self setType: [attr stringValue]]; + else if ([attr.name isEqual: @"id"]) + [self setID: [attr stringValue]]; + else + [self addAttribute: attr]; } - } - OFXMLElement *el; - - for (el in elem.children) { - [self addChild: el]; + for (el in elem.children) + [self addChild: el]; + } @catch (id e) { + [self release]; + @throw e; } return self; @@ -124,7 +135,10 @@ OFString* old = from; from = [from_ copy]; [old release]; - [self addAttributeWithName: @"from" stringValue: from_]; + + /* FIXME: Remove old attribute! */ + [self addAttributeWithName: @"from" + stringValue: from_]; } - (void)setTo: (OFString*)to_ @@ -132,7 +146,10 @@ OFString* old = to; to = [to_ copy]; [old release]; - [self addAttributeWithName: @"to" stringValue: to]; + + /* FIXME: Remove old attribute! */ + [self addAttributeWithName: @"to" + stringValue: to]; } - (void)setType: (OFString*)type_ @@ -140,7 +157,10 @@ OFString* old = type; type = [type_ copy]; [old release]; - [self addAttributeWithName: @"type" stringValue: type]; + + /* FIXME: Remove old attribute! */ + [self addAttributeWithName: @"type" + stringValue: type]; } - (void)setID: (OFString*)ID_ @@ -148,6 +168,8 @@ OFString* old = ID; ID = [ID_ copy]; [old release]; + + /* FIXME: Remove old attribute! */ [self addAttributeWithName: @"id" stringValue: ID]; } diff --git a/tests/test.m b/tests/test.m index 87dbdc7..44b314a 100644 --- a/tests/test.m +++ b/tests/test.m @@ -4,6 +4,9 @@ #import "XMPPConnection.h" #import "XMPPStanza.h" +#import "XMPPIQ.h" +#import "XMPPMessage.h" +#import "XMPPPresence.h" @interface AppDelegate: OFObject { @@ -25,25 +28,25 @@ OF_APPLICATION_DELEGATE(AppDelegate) pres.to = @"alice@example.com"; pres.from = @"bob@example.org"; assert([[pres stringValue] isEqual: @"chat" - @"Bored20" - @""]); + @"from='bob@example.org'>chat" + @"Bored20" + @""]); XMPPMessage *msg = [XMPPMessage messageWithType: @"chat"]; [msg addBody: @"Hello everyone"]; msg.to = @"jdev@conference.jabber.org"; msg.from = @"alice@example.com"; assert([[msg stringValue] isEqual: @"Hello everyone" - @""]); + @"to='jdev@conference.jabber.org' " + @"from='alice@example.com'>Hello everyone" + @""]); XMPPIQ *iq = [XMPPIQ IQWithType: @"set" ID: @"128"]; iq.to = @"juliet@capulet.lit"; iq.from = @"romeo@montague.lit"; assert([[iq stringValue] isEqual: @""]); + @"to='juliet@capulet.lit' " + @"from='romeo@montague.lit'/>"]); OFXMLElement *elem = [OFXMLElement elementWithName: @"iq"]; [elem addAttributeWithName: @"from" stringValue: @"bob@localhost"]; @@ -53,8 +56,8 @@ OF_APPLICATION_DELEGATE(AppDelegate) XMPPStanza *stanza = [XMPPStanza stanzaWithElement: elem]; assert([[elem stringValue] isEqual: [stanza stringValue]]); assert(([[OFString stringWithFormat: @"%@, %@, %@, %@", stanza.from, - stanza.to, stanza.type, stanza.ID] - isEqual: @"bob@localhost, alice@localhost, get, 42"])); + stanza.to, stanza.type, stanza.ID] + isEqual: @"bob@localhost, alice@localhost, get, 42"])); conn = [[XMPPConnection alloc] init];