Index: XMPPConnection.m ================================================================== --- XMPPConnection.m +++ XMPPConnection.m @@ -1,6 +1,7 @@ #import "XMPPConnection.h" +#import "XMPPStanza.h" #define NS_BIND @"urn:ietf:params:xml:ns:xmpp-bind" #define NS_CLIENT @"jabber:client" #define NS_SASL @"urn:ietf:params:xml:ns:xmpp-sasl" #define NS_STREAM @"http://etherx.jabber.org/streams" @@ -133,12 +134,11 @@ [sock writeString: [authTag stringValue]]; } - (void)_sendResourceBind { - OFXMLElement *iq = [OFXMLElement elementWithName: @"iq"]; - [iq addAttributeWithName: @"type" stringValue: @"set"]; + XMPPIQ *iq = [XMPPIQ IQWithType: @"set" ID: @"bind0"]; [iq addChild: [OFXMLElement elementWithName: @"bind" namespace: NS_BIND]]; [sock writeString: [iq stringValue]]; } ADDED XMPPStanza.h Index: XMPPStanza.h ================================================================== --- XMPPStanza.h +++ XMPPStanza.h @@ -0,0 +1,57 @@ +#import + +@interface XMPPStanza: OFXMLElement +{ + OFString *from; + OFString *to; + OFString *type; + OFString *ID; +} + +@property (copy) OFString *from; +@property (copy) OFString *to; +@property (copy) OFString *type; +@property (copy) OFString *ID; + ++ stanzaWithName: (OFString*)name; ++ stanzaWithElement: (OFXMLElement*)elem; + +- initWithName: (OFString*)name; +- initWithElement: (OFXMLElement*)elem; +@end + +@interface XMPPIQ: XMPPStanza +{ +} + ++ IQWithType: (OFString*)type_ + ID: (OFString*)ID_; +@end + +@interface XMPPMessage: XMPPStanza +{ +} + ++ message; ++ messageWithID: (OFString*)ID_; ++ messageWithType: (OFString*)type_; ++ messageWithType: (OFString*)type_ + ID: (OFString*)ID_; + +- (void)addBody: (OFString*)body; +@end + +@interface XMPPPresence: XMPPStanza +{ +} + ++ presence; ++ presenceWithID: (OFString*)ID_; ++ presenceWithType: (OFString*)type_; ++ presenceWithType: (OFString*)type_ + ID: (OFString*)ID_; + +- (void)addShow: (OFString*)show; +- (void)addStatus: (OFString*)status; +- (void)addPriority: (char)priority; +@end ADDED XMPPStanza.m Index: XMPPStanza.m ================================================================== --- XMPPStanza.m +++ XMPPStanza.m @@ -0,0 +1,213 @@ +#import "XMPPStanza.h" + +@implementation XMPPStanza +@synthesize from; +@synthesize to; +@synthesize type; +@synthesize ID; + ++ stanzaWithName: (OFString*)name +{ + return [[[self alloc] initWithName: name] autorelease]; +} + ++ stanzaWithElement: (OFXMLElement*)elem { + return [[[self alloc] initWithElement: elem] autorelease]; +} + +- initWithName: (OFString*)name_ +{ + if (!([name_ isEqual: @"iq"] || + [name_ isEqual: @"message"] || + [name_ isEqual: @"presence"])) + of_log(@"Invalid stanza name!"); + + self = [super initWithName: name_]; + [self setDefaultNamespace: @"jabber:client"]; + + from = [[OFString alloc] init]; + to = [[OFString alloc] init]; + type = [[OFString alloc] init]; + ID = [[OFString alloc] init]; + + return self; +} + +- initWithElement: (OFXMLElement*)elem +{ + self = [super initWithName: elem.name + namespace: elem.namespace]; + + from = [[OFString alloc] init]; + to = [[OFString alloc] init]; + type = [[OFString alloc] init]; + ID = [[OFString alloc] init]; + + OFXMLAttribute *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]; + } + + return self; +} + +- (void)dealloc +{ + [from release]; + [to release]; + [type release]; + [ID release]; + + [super dealloc]; +} + +- (void)setFrom: (OFString*)from_ +{ + OFString* old = from; + from = [from_ copy]; + [old release]; + [self addAttributeWithName: @"from" stringValue: from_]; +} + +- (void)setTo: (OFString*)to_ +{ + OFString* old = to; + to = [to_ copy]; + [old release]; + [self addAttributeWithName: @"to" stringValue: to]; +} + +- (void)setType: (OFString*)type_ +{ + OFString* old = type; + type = [type_ copy]; + [old release]; + [self addAttributeWithName: @"type" stringValue: type]; +} + +- (void)setID: (OFString*)ID_ +{ + OFString* old = ID; + ID = [ID_ copy]; + [old release]; + [self addAttributeWithName: @"id" stringValue: ID]; +} +@end + +@implementation XMPPIQ ++ IQWithType: (OFString*)type_ + ID: (OFString*)ID_ +{ + if (!([type_ isEqual: @"get"] || + [type_ isEqual: @"set"] || + [type_ isEqual: @"result"] || + [type_ isEqual: @"error"])) + of_log(@"Invalid IQ type!"); + + id ret; + ret = [[[self alloc] initWithName: @"iq"] autorelease]; + [ret setType: type_]; + [ret setID: ID_]; + return ret; +} +@end + +@implementation XMPPMessage ++ message +{ + return [self messageWithType: nil ID: nil]; +} + ++ messageWithID: (OFString*)ID_ +{ + return [self messageWithType: nil ID: ID_]; +} + ++ messageWithType: (OFString*)type_ +{ + return [self messageWithType: type_ ID: nil]; +} + ++ messageWithType: (OFString*)type_ + ID: (OFString*)ID_ +{ + id ret; + ret = [[[self alloc] initWithName: @"message"] autorelease]; + if (type_) + [ret setType: type_]; + if (ID_) + [ret setID: ID_]; + return ret; +} + +- (void)addBody: (OFString*)body +{ + [self addChild: [OFXMLElement elementWithName: @"body" + stringValue: body]]; +} +@end + +@implementation XMPPPresence ++ presence +{ + return [self presenceWithType: nil ID: nil]; +} + ++ presenceWithID: (OFString*)ID_ +{ + return [self presenceWithType: nil ID: ID_]; +} + ++ presenceWithType: (OFString*)type_ +{ + return [self presenceWithType: type_ ID: nil]; +} + ++ presenceWithType: (OFString*)type_ + ID: (OFString*)ID_ +{ + id ret; + ret = [[[self alloc] initWithName: @"presence"] autorelease]; + if (type_) + [ret setType: type_]; + if (ID_) + [ret setID: ID_]; + return ret; +} + +- (void)addShow: (OFString*)show +{ + [self addChild: [OFXMLElement elementWithName: @"show" + stringValue: show]]; +} + +- (void)addStatus: (OFString*)status +{ + [self addChild: [OFXMLElement elementWithName: @"status" + stringValue: status]]; +} + +- (void)addPriority: (char)priority +{ + OFString* prio = [OFString stringWithFormat: @"%d", priority]; + [self addChild: [OFXMLElement elementWithName: @"priority" + stringValue: prio]]; +} +@end ADDED XMPPStanza.o Index: XMPPStanza.o ================================================================== --- XMPPStanza.o +++ XMPPStanza.o cannot compute difference between binary files Index: test.m ================================================================== --- test.m +++ test.m @@ -1,7 +1,9 @@ -#include +#include +#import #import "XMPPConnection.h" +#import "XMPPStanza.h" @interface AppDelegate: OFObject { XMPPConnection *conn; } @@ -12,10 +14,48 @@ @implementation AppDelegate - (void)applicationDidFinishLaunching { OFArray *arguments = [OFApplication arguments]; + XMPPPresence *pres = [XMPPPresence presence]; + [pres addShow: @"chat"]; + [pres addStatus: @"Bored"]; + [pres addPriority: 20]; + pres.to = @"alice@example.com"; + pres.from = @"bob@example.org"; + assert([[pres stringValue] isEqual: @"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" + @""]); + + XMPPIQ *iq = [XMPPIQ IQWithType: @"set" ID: @"128"]; + iq.to = @"juliet@capulet.lit"; + iq.from = @"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"]; + 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"])); + conn = [[XMPPConnection alloc] init]; if (arguments.count != 3) { of_log(@"Invalid count of command line arguments!"); [OFApplication terminateWithStatus: 1];