ObjXMPP  Check-in [e00e687561]

Overview
Comment:Clean up the code.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: e00e687561853a90b80b3537bccda3235969d257012c8ad2938dc6eb30b7c343
User & Date: js on 2011-02-16 20:05:14
Other Links: manifest | tags
Context
2011-02-16
20:05
The full JID is the bare JID in case there's no resource. check-in: 219b0d5494 user: js tags: trunk
20:05
Clean up the code. check-in: e00e687561 user: js tags: trunk
19:32
Use one file per class. check-in: 28c341cb47 user: js tags: trunk
Changes

Modified src/XMPPConnection.h from [3f7778add9] to [9643929b2e].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#import <ObjFW/ObjFW.h>

#import "XMPPJID.h"

@class XMPPConnection;
@class XMPPIQ;
@class XMPPMessage;
@class XMPPPresence;

@protocol XMPPConnectionDelegate
- (void)connectionWasClosed: (XMPPConnection*)conn;
- (void)connection: (XMPPConnection*)conn
      didReceiveIQ: (XMPPIQ*)iq;
-   (void)connection: (XMPPConnection*)conn
  didReceivePresence: (XMPPPresence*)pres;
-  (void)connection: (XMPPConnection*)conn
  didReceiveMessage: (XMPPMessage*)msg;
@end

/**
 * \brief A class that abstracts a connection to an XMPP service
 */
@interface XMPPConnection: OFObject <OFXMLElementBuilderDelegate>
{
	OFTCPSocket *sock;
	OFXMLParser *parser;
	OFXMLElementBuilder *elementBuilder;

	/**
	 * The username to connect with
	 */
	OFString *username;

	/**
	 * The password to connect with
	 */
	OFString *password;

	/**
	 * The server to connect to
	 */
	OFString *server;

	/**
	 * The resource to connect with
	 */
	OFString *resource;

	/**
	 * The JID bound to this connection (this is determined by the server)
	 */
	XMPPJID *JID;

	/**
	 * The port to connect to
	 */
	short port;

	/**
	 * Whether to use TLS
	 */
	BOOL useTLS;
	id <XMPPConnectionDelegate> delegate;
	OFMutableArray *mechanisms;
}

@property (copy) OFString *username;
@property (copy) OFString *password;
@property (copy) OFString *server;
@property (copy) OFString *resource;
@property (readonly) XMPPJID *JID;
@property (assign) short port;
@property (assign) BOOL useTLS;
@property (retain) id <XMPPConnectionDelegate> delegate;

/**
 * Connects to the XMPP service
 */
- (void)connect;

/**
 * Starts a loop handling incomming data
 */
- (void)handleConnection;

/**
 * Sends a OFXMLElement (usually a XMPPStanza)
 *
 * \param elem The element to send
 */
- (void)sendStanza: (OFXMLElement*)elem;
@end


<
|
|















|






<
<
|
<

<
<
|
<

<
<
|
<

<
<
|
<

<
<
|
<

<
<
|
<

<
<
|
<









|





|




|




|





1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26


27

28


29

30


31

32


33

34


35

36


37

38


39

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#import <ObjFW/ObjFW.h>


@class XMPPConnection;
@class XMPPJID;
@class XMPPIQ;
@class XMPPMessage;
@class XMPPPresence;

@protocol XMPPConnectionDelegate
- (void)connectionWasClosed: (XMPPConnection*)conn;
- (void)connection: (XMPPConnection*)conn
      didReceiveIQ: (XMPPIQ*)iq;
-   (void)connection: (XMPPConnection*)conn
  didReceivePresence: (XMPPPresence*)pres;
-  (void)connection: (XMPPConnection*)conn
  didReceiveMessage: (XMPPMessage*)msg;
@end

/**
 * \brief A class which abstracts a connection to an XMPP service.
 */
@interface XMPPConnection: OFObject <OFXMLElementBuilderDelegate>
{
	OFTCPSocket *sock;
	OFXMLParser *parser;
	OFXMLElementBuilder *elementBuilder;


	/// The username to connect with

	OFString *username;


	/// The password to connect with

	OFString *password;


	/// The server to connect to

	OFString *server;


	/// The resource to connect with

	OFString *resource;


	/// The JID bound to this connection (this is determined by the server)

	XMPPJID *JID;


	/// The port to connect to

	short port;


	/// Whether to use TLS

	BOOL useTLS;
	id <XMPPConnectionDelegate> delegate;
	OFMutableArray *mechanisms;
}

@property (copy) OFString *username;
@property (copy) OFString *password;
@property (copy) OFString *server;
@property (copy) OFString *resource;
@property (copy, readonly) XMPPJID *JID;
@property (assign) short port;
@property (assign) BOOL useTLS;
@property (retain) id <XMPPConnectionDelegate> delegate;

/**
 * Connects to the XMPP service.
 */
- (void)connect;

/**
 * Starts a loop handling incomming data.
 */
- (void)handleConnection;

/**
 * Sends an OFXMLElement, usually an XMPPStanza.
 *
 * \param elem The element to send
 */
- (void)sendStanza: (OFXMLElement*)elem;
@end

Modified src/XMPPConnection.m from [4861f51dfb] to [ea49ed2a93].

1
2
3
4
5
6

7
8
9
10
11
12
13
#include <assert.h>

#include <stringprep.h>

#import "XMPPConnection.h"
#import "XMPPStanza.h"

#import "XMPPIQ.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"







>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <assert.h>

#include <stringprep.h>

#import "XMPPConnection.h"
#import "XMPPStanza.h"
#import "XMPPJID.h"
#import "XMPPIQ.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"

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

- (void)setUsername: (OFString*)username_
{
	OFString *old = username;
	char *node;

	Stringprep_rc rc;
	if ((rc = stringprep_profile([username_ cString], &node, "SASLprep", 0))
			!= STRINGPREP_OK) {
		of_log(@"SASLprep failed: %s", stringprep_strerror(rc));
		assert(0);
	}

	@try {
		username = [[OFString alloc] initWithCString: node];
	} @finally {
		free(node);
	}

	[old release];
}

- (void)setResource: (OFString*)resource_
{
	OFString *old = resource;
	char *res;

	Stringprep_rc rc;
	if ((rc = stringprep_profile([resource_ cString], &res, "Resourceprep", 0))
			!= STRINGPREP_OK) {
		of_log(@"Resourceprep failed: %s", stringprep_strerror(rc));
		assert(0);
	}

	@try {
		resource = [[OFString alloc] initWithCString: res];
	} @finally {
		free(res);
	}

	[old release];
}

- (void)setServer: (OFString*)server_
{
	OFString *old = server;
	char *srv;

	Stringprep_rc rc;
	if ((rc = stringprep_profile([server_ cString], &srv, "Nameprep", 0))
			!= STRINGPREP_OK) {
		of_log(@"Nameprep failed: %s", stringprep_strerror(rc));
		assert(0);
	}

	@try {
		server = [[OFString alloc] initWithCString: srv];
	} @finally {
		free(srv);
	}

	[old release];
}

- (void)setPassword: (OFString*)password_
{
	OFString *old = password;
	char *pass;

	Stringprep_rc rc;
	if ((rc = stringprep_profile([password_ cString], &pass, "SASLprep", 0))
			!= STRINGPREP_OK) {
		of_log(@"SASLprep failed: %s", stringprep_strerror(rc));
		assert(0);
	}

	@try {
		password = [[OFString alloc] initWithCString: pass];
	} @finally {







|
|



















|
|



















|
|



















|
|







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

- (void)setUsername: (OFString*)username_
{
	OFString *old = username;
	char *node;

	Stringprep_rc rc;
	if ((rc = stringprep_profile([username_ cString], &node,
	    "SASLprep", 0)) != STRINGPREP_OK) {
		of_log(@"SASLprep failed: %s", stringprep_strerror(rc));
		assert(0);
	}

	@try {
		username = [[OFString alloc] initWithCString: node];
	} @finally {
		free(node);
	}

	[old release];
}

- (void)setResource: (OFString*)resource_
{
	OFString *old = resource;
	char *res;

	Stringprep_rc rc;
	if ((rc = stringprep_profile([resource_ cString], &res,
	    "Resourceprep", 0)) != STRINGPREP_OK) {
		of_log(@"Resourceprep failed: %s", stringprep_strerror(rc));
		assert(0);
	}

	@try {
		resource = [[OFString alloc] initWithCString: res];
	} @finally {
		free(res);
	}

	[old release];
}

- (void)setServer: (OFString*)server_
{
	OFString *old = server;
	char *srv;

	Stringprep_rc rc;
	if ((rc = stringprep_profile([server_ cString], &srv,
	    "Nameprep", 0)) != STRINGPREP_OK) {
		of_log(@"Nameprep failed: %s", stringprep_strerror(rc));
		assert(0);
	}

	@try {
		server = [[OFString alloc] initWithCString: srv];
	} @finally {
		free(srv);
	}

	[old release];
}

- (void)setPassword: (OFString*)password_
{
	OFString *old = password;
	char *pass;

	Stringprep_rc rc;
	if ((rc = stringprep_profile([password_ cString], &pass,
	    "SASLprep", 0)) != STRINGPREP_OK) {
		of_log(@"SASLprep failed: %s", stringprep_strerror(rc));
		assert(0);
	}

	@try {
		password = [[OFString alloc] initWithCString: pass];
	} @finally {
141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
			   @"version='1.0'>", server];
}

- (void)connect
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];

	[sock connectToHost: server onPort: port];

	[self _startStream];

	[pool release];
}

- (void)handleConnection
{







|
>







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
			   @"version='1.0'>", server];
}

- (void)connect
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];

	[sock connectToHost: server
		     onPort: port];
	[self _startStream];

	[pool release];
}

- (void)handleConnection
{
177
178
179
180
181
182
183
184
185

186

187
188
189
190



191
192
193
194
195
196
197
-    (void)parser: (OFXMLParser*)p
  didStartElement: (OFString*)name
       withPrefix: (OFString*)prefix
	namespace: (OFString*)ns
       attributes: (OFArray*)attrs
{
	if (![name isEqual: @"stream"] || ![prefix isEqual: @"stream"] ||
	    ![ns isEqual: NS_STREAM])
		of_log(@"Did not get expected stream start!");



	for (OFXMLAttribute *attr in attrs)
		if ([attr.name isEqual: @"from"] &&
		    ![attr.stringValue isEqual: server])
			of_log(@"Got invalid from in stream start!");




	parser.delegate = elementBuilder;
}

- (void)_addAuthMechanisms: (OFXMLElement*)mechanisms_
{
	for (OFXMLElement *mechanism in mechanisms_.children)







|

>
|
>
|

|

>
>
>







179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
-    (void)parser: (OFXMLParser*)p
  didStartElement: (OFString*)name
       withPrefix: (OFString*)prefix
	namespace: (OFString*)ns
       attributes: (OFArray*)attrs
{
	if (![name isEqual: @"stream"] || ![prefix isEqual: @"stream"] ||
	    ![ns isEqual: NS_STREAM]) {
		of_log(@"Did not get expected stream start!");
		assert(0);
	}

	for (OFXMLAttribute *attr in attrs) {
		if ([attr.name isEqual: @"from"] &&
		    ![attr.stringValue isEqual: server]) {
			of_log(@"Got invalid from in stream start!");
			assert(0);
		}
	}

	parser.delegate = elementBuilder;
}

- (void)_addAuthMechanisms: (OFXMLElement*)mechanisms_
{
	for (OFXMLElement *mechanism in mechanisms_.children)
240
241
242
243
244
245
246

247
248
249
250
251
252
253
254
255
256
257
258

	[self sendStanza: iq];
}

- (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]];
		of_log(@"Bound to JID: %@", [JID fullJID]);
	}
}

- (void)_handleFeatures: (OFXMLElement*)elem
{
	for (OFXMLElement *child in elem.children) {







>




|







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266

	[self sendStanza: iq];
}

- (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]];
		of_log(@"Bound to JID: %@", [JID fullJID]);
	}
}

- (void)_handleFeatures: (OFXMLElement*)elem
{
	for (OFXMLElement *child in elem.children) {
298
299
300
301
302
303
304


305
306
307
308
309
310
311
312
313
314
315
316
317
318
			of_log(@"Auth failed!");
			// FIXME: Handle!
	}

	if ([elem.name isEqual: @"iq"] &&
	    [elem.namespace isEqual: NS_CLIENT]) {
		XMPPIQ *iq = [XMPPIQ stanzaWithElement: elem];


		if ([iq.ID isEqual: @"bind0"] && [iq.type isEqual: @"result"]) {
			[self _handleResourceBind: iq];
		}
	}
}

- (void)elementBuilder: (OFXMLElementBuilder*)b
  didNotExpectCloseTag: (OFString*)name
	    withPrefix: (OFString*)prefix
	     namespace: (OFString*)ns
{
	// TODO
}
@end







>
>
|

<











306
307
308
309
310
311
312
313
314
315
316

317
318
319
320
321
322
323
324
325
326
327
			of_log(@"Auth failed!");
			// FIXME: Handle!
	}

	if ([elem.name isEqual: @"iq"] &&
	    [elem.namespace isEqual: NS_CLIENT]) {
		XMPPIQ *iq = [XMPPIQ stanzaWithElement: elem];

		// FIXME: More checking!
		if ([iq.ID isEqual: @"bind0"] && [iq.type isEqual: @"result"])
			[self _handleResourceBind: iq];

	}
}

- (void)elementBuilder: (OFXMLElementBuilder*)b
  didNotExpectCloseTag: (OFString*)name
	    withPrefix: (OFString*)prefix
	     namespace: (OFString*)ns
{
	// TODO
}
@end

Modified src/XMPPIQ.h from [c57efbd317] to [897d4b81a3].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#import "XMPPStanza.h"

/**
 * \brief A class describing a IQ stanza
 */
@interface XMPPIQ: XMPPStanza
/**
 * Creates a new XMPPIQ with a certain type and id
 *
 * \param type The value for the stanza's type attribute
 * \param ID The value for the stanza's id attribute
 * \return A new autoreleased XMPPIQ
 */
+ IQWithType: (OFString*)type
	  ID: (OFString*)ID;

/**
 * Initializes an already allocated XMPPIQ with a certain type and id
 *
 * \param type The value for the stanza's type attribute
 * \param ID The value for the stanza's id attribute
 * \return A initialized XMPPIQ
 */
- initWithType: (OFString*)type
	    ID: (OFString*)ID;



|



|









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#import "XMPPStanza.h"

/**
 * \brief A class describing an IQ stanza.
 */
@interface XMPPIQ: XMPPStanza
/**
 * 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
 * \return A new autoreleased XMPPIQ
 */
+ IQWithType: (OFString*)type
	  ID: (OFString*)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
 * \return A initialized XMPPIQ
 */
- initWithType: (OFString*)type
	    ID: (OFString*)ID;

Modified src/XMPPIQ.m from [a069c37422] to [5cc3a4abb8].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#import "XMPPIQ.h"

@implementation XMPPIQ
+ IQWithType: (OFString*)type_
	  ID: (OFString*)ID_
{
	return [[[self alloc] initWithType: type_
					ID: ID_] autorelease];
}

- initWithType: (OFString*)type_
	    ID: (OFString*)ID_
{
	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_];
}
@end













|
|
|
|



|
|


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#import "XMPPIQ.h"

@implementation XMPPIQ
+ IQWithType: (OFString*)type_
	  ID: (OFString*)ID_
{
	return [[[self alloc] initWithType: type_
					ID: ID_] autorelease];
}

- initWithType: (OFString*)type_
	    ID: (OFString*)ID_
{
	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_];
}
@end

Modified src/XMPPJID.h from [ba250a7ca4] to [ac77d953dc].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#import <ObjFW/ObjFW.h>

/**
 * \brief A class for easy handling of JIDs
 */
@interface XMPPJID: OFObject
{
	/**
	 * The JID's localpart
	 */
	OFString *node;

	/**
	 * The JID's domainpart
	 */
	OFString *domain;

	/**
	 * The JID's resourcepart
	 */
	OFString *resource;
}

@property (copy) OFString *node;
@property (copy) OFString *domain;
@property (copy) OFString *resource;

/**
 * Creates a new XMPPJID
 *
 * \return A new autoreleased XMPPJID
 */
+ JID;

/**
 * Creates a new XMPPJID from a OFString
 *
 * \param str The string to parse into a JID object
 * \return A new autoreleased XMPPJID
 */
+ JIDWithString: (OFString*)str;

/**
 * Initializes an already allocated XMPPJID using a OFString
 *
 * \param str The string to parse into a JID object
 * \return A initialized XMPPJID
 */
- initWithString: (OFString*)str;

/**
 * \return A OFString containing the bare JID
 */
- (OFString*)bareJID;

/**
 * \return A OFString containing the full JID
 */
- (OFString*)fullJID;
@end



|



<
|
<

<
<
|
<

<
<
|
<








|






|







|







|




|



1
2
3
4
5
6
7

8

9


10

11


12

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#import <ObjFW/ObjFW.h>

/**
 * \brief A class for easy handling of JIDs.
 */
@interface XMPPJID: OFObject
{

	/// The JID's localpart

	OFString *node;


	/// The JID's domainpart

	OFString *domain;


	/// The JID's resourcepart

	OFString *resource;
}

@property (copy) OFString *node;
@property (copy) OFString *domain;
@property (copy) OFString *resource;

/**
 * Creates a new autoreleased XMPPJID.
 *
 * \return A new autoreleased XMPPJID
 */
+ JID;

/**
 * Creates a new autoreleased XMPPJID from a string.
 *
 * \param str The string to parse into a JID object
 * \return A new autoreleased XMPPJID
 */
+ JIDWithString: (OFString*)str;

/**
 * Initializes an already allocated XMPPJID with a string.
 *
 * \param str The string to parse into a JID object
 * \return A initialized XMPPJID
 */
- initWithString: (OFString*)str;

/**
 * \return An OFString containing the bare JID
 */
- (OFString*)bareJID;

/**
 * \return An OFString containing the full JID
 */
- (OFString*)fullJID;
@end

Modified src/XMPPJID.m from [2fdab65477] to [31bd443101].

1

2

3
4
5
6
7
8
9
#include <assert.h>

#include <stringprep.h>

#import "XMPPJID.h"

@implementation XMPPJID
@synthesize node;
@synthesize domain;
@synthesize resource;


>

>







1
2
3
4
5
6
7
8
9
10
11
#include <assert.h>

#include <stringprep.h>

#import "XMPPJID.h"

@implementation XMPPJID
@synthesize node;
@synthesize domain;
@synthesize resource;

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

51





52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

93





94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
{
	self = [super init];

	size_t nodesep, resourcesep;
	nodesep = [str indexOfFirstOccurrenceOfString: @"@"];
	resourcesep = [str indexOfFirstOccurrenceOfString: @"/"];

	if (nodesep == -1)
		[self setNode: @""];
	else
		[self setNode: [str substringFromIndex: 0
					       toIndex: nodesep]];

	if (resourcesep == -1) {
		[self setResource: @""];
		resourcesep = [str length];
	} else
		[self setResource: [str substringFromIndex: resourcesep + 1
						 toIndex: [str length]]];

	[self setDomain: [str substringFromIndex: nodesep + 1
					 toIndex: resourcesep]];

	return self;
}

- (void)setNode: (OFString*)node_
{
	OFString *old = node;
	char *nodepart;







	Stringprep_rc rc;
	if ((rc = stringprep_profile([node_ cString], &nodepart, "Nodeprep", 0))
			!= STRINGPREP_OK) {
		of_log(@"Nodeprep failed: %s", stringprep_strerror(rc));
		assert(0);
	}

	@try {
		node = [[OFString alloc] initWithCString: nodepart];
	} @finally {
		free(nodepart);
	}

	[old release];
}

- (void)setDomain: (OFString*)domain_
{
	OFString *old = domain;
	char *srv;

	Stringprep_rc rc;

	if ((rc = stringprep_profile([domain_ cString], &srv, "Nameprep", 0))
			!= STRINGPREP_OK) {
		of_log(@"Nameprep failed: %s", stringprep_strerror(rc));
		assert(0);
	}

	@try {
		domain = [[OFString alloc] initWithCString: srv];
	} @finally {
		free(srv);
	}

	[old release];
}

- (void)setResource: (OFString*)resource_
{
	OFString *old = resource;
	char *res;







	Stringprep_rc rc;
	if ((rc = stringprep_profile([resource_ cString], &res,
				"Resourceprep", 0)) != STRINGPREP_OK) {
		of_log(@"Resourceprep failed: %s", stringprep_strerror(rc));
		assert(0);
	}

	@try {
		resource = [[OFString alloc] initWithCString: res];
	} @finally {
		free(res);
	}

	[old release];
}

- (OFString*)bareJID
{
	if ([node length])
		return [OFString stringWithFormat: @"%@@%@", node, domain];
	else
		return [OFString stringWithFormat: @"%@", domain];
}

- (OFString*)fullJID
{
	if ([node length])
		return [OFString stringWithFormat: @"%@@%@/%@",
		       node, domain, resource];
	else
		return [OFString stringWithFormat: @"%@/%@",
		       domain, resource];
}
@end







|
|




|
|















>

>
>
>
>
>
|
|
|

















<

>
|
|

















>

>
>
>
>
>
|

|















|







|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
{
	self = [super init];

	size_t nodesep, resourcesep;
	nodesep = [str indexOfFirstOccurrenceOfString: @"@"];
	resourcesep = [str indexOfFirstOccurrenceOfString: @"/"];

	if (nodesep == SIZE_MAX)
		[self setNode: nil];
	else
		[self setNode: [str substringFromIndex: 0
					       toIndex: nodesep]];

	if (resourcesep == SIZE_MAX) {
		[self setResource: nil];
		resourcesep = [str length];
	} else
		[self setResource: [str substringFromIndex: resourcesep + 1
						 toIndex: [str length]]];

	[self setDomain: [str substringFromIndex: nodesep + 1
					 toIndex: resourcesep]];

	return self;
}

- (void)setNode: (OFString*)node_
{
	OFString *old = node;
	char *nodepart;
	Stringprep_rc rc;

	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);
	}

	@try {
		node = [[OFString alloc] initWithCString: nodepart];
	} @finally {
		free(nodepart);
	}

	[old release];
}

- (void)setDomain: (OFString*)domain_
{
	OFString *old = domain;
	char *srv;

	Stringprep_rc rc;

	if ((rc = stringprep_profile([domain_ cString], &srv,
	    "Nameprep", 0)) != STRINGPREP_OK) {
		of_log(@"Nameprep failed: %s", stringprep_strerror(rc));
		assert(0);
	}

	@try {
		domain = [[OFString alloc] initWithCString: srv];
	} @finally {
		free(srv);
	}

	[old release];
}

- (void)setResource: (OFString*)resource_
{
	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) {
		of_log(@"Resourceprep failed: %s", stringprep_strerror(rc));
		assert(0);
	}

	@try {
		resource = [[OFString alloc] initWithCString: res];
	} @finally {
		free(res);
	}

	[old release];
}

- (OFString*)bareJID
{
	if (node != nil)
		return [OFString stringWithFormat: @"%@@%@", node, domain];
	else
		return [OFString stringWithFormat: @"%@", domain];
}

- (OFString*)fullJID
{
	if (node != nil)
		return [OFString stringWithFormat: @"%@@%@/%@",
		       node, domain, resource];
	else
		return [OFString stringWithFormat: @"%@/%@",
		       domain, resource];
}
@end

Modified src/XMPPMessage.h from [2b9ab347bf] to [3564ea1dbd].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#import "XMPPStanza.h"

/**
 * \brief A class describing a message stanza
 */
@interface XMPPMessage: XMPPStanza
{
}

/**
 * Creates a new XMPPMessage
 *
 * \return A new autoreleased XMPPMessage
 */
+ message;

/**
 * Creates a new XMPPMessage with a certain id
 *
 * \param ID The value for the stanza's id attribute
 * \return A new autoreleased XMPPMessage
 */
+ messageWithID: (OFString*)ID;

/**
 * Creates a new XMPPMessage with a certain type
 *
 * \param type The value for the stanza's type attribute
 * \return A new autoreleased XMPPMessage
 */
+ messageWithType: (OFString*)type;

/**
 * Creates a new XMPPMessage with a certain type and id
 *
 * \param type The value for the stanza's type attribute
 * \param ID The value for the stanza's id attribute
 * \return A new autoreleased XMPPMessage
 */
+ messageWithType: (OFString*)type
	       ID: (OFString*)ID;

/**
 * Initializes an already allocated XMPPMessage
 *
 * \return A initialized XMPPMessage
 */
- init;

/**
 * Initializes an already allocated XMPPMessage with a certain id
 *
 * \param ID The value for the stanza's id attribute
 * \return A initialized XMPPMessage
 */
- initWithID: (OFString*)ID;

/**
 * Initializes an already allocated XMPPMessage with a certain type
 *
 * \param type The value for the stanza's type attribute
 * \return A initialized XMPPMessage
 */
- initWithType: (OFString*)type;

/**
 * Initializes an already allocated XMPPMessage with a certain type and id
 *
 * \param type The value for the stanza's type attribute
 * \param ID The value for the stanza's id attribute
 * \return A initialized XMPPMessage
 */
- initWithType: (OFString*)type
	    ID: (OFString*)ID;



|


<
<
<

|






|







|







|









|






|







|







|







1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#import "XMPPStanza.h"

/**
 * \brief A class describing a message stanza.
 */
@interface XMPPMessage: XMPPStanza



/**
 * Creates a new autoreleased XMPPMessage.
 *
 * \return A new autoreleased XMPPMessage
 */
+ message;

/**
 * Creates a new autoreleased XMPPMessage with the specified id.
 *
 * \param ID The value for the stanza's id attribute
 * \return A new autoreleased XMPPMessage
 */
+ messageWithID: (OFString*)ID;

/**
 * Creates a new autoreleased XMPPMessage with the specified type.
 *
 * \param type The value for the stanza's type attribute
 * \return A new autoreleased XMPPMessage
 */
+ messageWithType: (OFString*)type;

/**
 * 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
 * \return A new autoreleased XMPPMessage
 */
+ messageWithType: (OFString*)type
	       ID: (OFString*)ID;

/**
 * Initializes an already allocated XMPPMessage.
 *
 * \return A initialized XMPPMessage
 */
- init;

/**
 * Initializes an already allocated XMPPMessage with the specified id.
 *
 * \param ID The value for the stanza's id attribute
 * \return A initialized XMPPMessage
 */
- initWithID: (OFString*)ID;

/**
 * Initializes an already allocated XMPPMessage with the specified type.
 *
 * \param type The value for the stanza's type attribute
 * \return A initialized XMPPMessage
 */
- initWithType: (OFString*)type;

/**
 * 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
 * \return A initialized XMPPMessage
 */
- initWithType: (OFString*)type
	    ID: (OFString*)ID;

Modified src/XMPPPresence.h from [9d51b71144] to [7a021bddee].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#import "XMPPStanza.h"

/**
 * \brief A class describing a presence stanza
 */
@interface XMPPPresence: XMPPStanza
{
}

/**
 * Creates a new XMPPPresence
 *
 * \return A new autoreleased XMPPPresence
 */
+ presence;

/**
 * Creates a new XMPPPresence with a certain id
 *
 * \param ID The value for the stanza's id attribute
 * \return A new autoreleased XMPPPresence
 */
+ presenceWithID: (OFString*)ID;

/**
 * Creates a new XMPPPresence with a certain type
 *
 * \param type The value for the stanza's type attribute
 * \return A new autoreleased XMPPPresence
 */
+ presenceWithType: (OFString*)type;

/**
 * Creates a new XMPPPresence with a certain type and id
 *
 * \param type The value for the stanza's type attribute
 * \param ID The value for the stanza's id attribute
 * \return A new autoreleased XMPPPresence
 */
+ presenceWithType: (OFString*)type
		ID: (OFString*)ID;

/**
 * Initializes an already allocated XMPPPresence
 *
 * \return A initialized XMPPPresence
 */
- init;

/**
 * Initializes an already allocated XMPPPresence with a certain id
 *
 * \param ID The value for the stanza's id attribute
 * \return A initialized XMPPPresence
 */
- initWithID: (OFString*)ID;

/**
 * Initializes an already allocated XMPPPresence with a certain type
 *
 * \param type The value for the stanza's type attribute
 * \return A initialized XMPPPresence
 */
- initWithType: (OFString*)type;

/**
 * Initializes an already allocated XMPPPresence with a certain type and id
 *
 * \param type The value for the stanza's type attribute
 * \param ID The value for the stanza's id attribute
 * \return A initialized XMPPPresence
 */
- initWithType: (OFString*)type
	    ID: (OFString*)ID;

/**
 * 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
 *
 * \param status The text content of the status element
 */
- (void)addStatus: (OFString*)status;

/**
 * Adds a priority element to the presence stanza
 *
 * \param priority The text content of the priority element
 */
- (void)addPriority: (int8_t)priority;
@end



|


<
<
<

|






|







|







|









|






|







|







|









|






|






|





1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#import "XMPPStanza.h"

/**
 * \brief A class describing a presence stanza.
 */
@interface XMPPPresence: XMPPStanza



/**
 * Creates a new autoreleased XMPPPresence.
 *
 * \return A new autoreleased XMPPPresence
 */
+ presence;

/**
 * Creates a new autoreleased XMPPPresence with the specified id.
 *
 * \param ID The value for the stanza's id attribute
 * \return A new autoreleased XMPPPresence
 */
+ presenceWithID: (OFString*)ID;

/**
 * Creates a new autoreleased XMPPPresence with the specified type.
 *
 * \param type The value for the stanza's type attribute
 * \return A new autoreleased XMPPPresence
 */
+ presenceWithType: (OFString*)type;

/**
 * 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
 * \return A new autoreleased XMPPPresence
 */
+ presenceWithType: (OFString*)type
		ID: (OFString*)ID;

/**
 * Initializes an already allocated XMPPPresence.
 *
 * \return A initialized XMPPPresence
 */
- init;

/**
 * Initializes an already allocated XMPPPresence with the specified id.
 *
 * \param ID The value for the stanza's id attribute
 * \return A initialized XMPPPresence
 */
- initWithID: (OFString*)ID;

/**
 * Initializes an already allocated XMPPPresence with the specified type.
 *
 * \param type The value for the stanza's type attribute
 * \return A initialized XMPPPresence
 */
- initWithType: (OFString*)type;

/**
 * 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
 * \return A initialized XMPPPresence
 */
- initWithType: (OFString*)type
	    ID: (OFString*)ID;

/**
 * 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.
 *
 * \param status The text content of the status element
 */
- (void)addStatus: (OFString*)status;

/**
 * Adds a priority element to the presence stanza.
 *
 * \param priority The text content of the priority element
 */
- (void)addPriority: (int8_t)priority;
@end

Modified src/XMPPStanza.h from [aeb32fe0f4] to [f2881ecf2b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#import <ObjFW/ObjFW.h>

/**
 * \brief A class describing a XMPP Stanza
 */
@interface XMPPStanza: OFXMLElement
{
	/**
	 * The value of the stanza's from attribute
	 */
	OFString *from;

	/**
	 * The value of the stanza's to attribute
	 */
	OFString *to;

	/**
	 * The value of the stanza's type attribute
	 */
	OFString *type;

	/**
	 * The value of the stanza's id attribute
	 */
	OFString *ID;
}

@property (copy) OFString *from;
@property (copy) OFString *to;
@property (copy) OFString *type;
@property (copy) OFString *ID;

/**
 * Creates a new XMPPStanza with a certain name
 *
 * \param name The stanza's name (one of iq, message or presence)
 * \return A new autoreleased XMPPStanza
 */
+ stanzaWithName: (OFString*)name;

/**
 * Creates a new XMPPStanza with a certain 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 new autoreleased XMPPStanza
 */
+ stanzaWithName: (OFString*)name
	    type: (OFString*)type;

/**
 * Creates a new XMPPStanza with a certain 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 new autoreleased XMPPStanza
 */
+ stanzaWithName: (OFString*)name
	      ID: (OFString*)ID;

/**
 * Creates a new XMPPStanza with a certain 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
 * \param ID The value for the stanza's id attribute
 * \return A new autoreleased XMPPStanza
 */
+ stanzaWithName: (OFString*)name
	    type: (OFString*)type
	      ID: (OFString*)ID;

/**
 * Creates a new XMPPStanza from a OFXMLElement
 *
 * \param elem The element to base the XMPPStanza on
 * \return A new autoreleased XMPPStanza
 */
+ stanzaWithElement: (OFXMLElement*)elem;

/**
 * Initializes an already allocated XMPPStanza with a certain name
 *
 * \param name The stanza's name (one of iq, message or presence)
 * \return A initialized XMPPStanza
 */
- initWithName: (OFString*)name;

/**
 * Initializes an already allocated XMPPStanza with a certain 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;

/**
 * Initializes an already allocated XMPPStanza with a certain 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;

/**
 * Initializes an already allocated XMPPStanza with a certain 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
 * \param ID The value for the stanza's id attribute
 * \return A initialized XMPPStanza
 */
- initWithName: (OFString*)name
	    type: (OFString*)type
	      ID: (OFString*)ID;

/**
 * Initializes an already allocated XMPPStanza based on a OFXMLElement
 *
 * \param elem The element to base the XMPPStanza on
 * \return A initialized XMPPStanza
 */



|



<
|
<

<
<
|
<

<
<
|
<

<
<
|
<









|







|









|









|











|







|







|






|


|






|


|
>







|
|







1
2
3
4
5
6
7

8

9


10

11


12

13


14

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#import <ObjFW/ObjFW.h>

/**
 * \brief A class describing an XMPP Stanza.
 */
@interface XMPPStanza: OFXMLElement
{

	/// The value of the stanza's from attribute

	OFString *from;


	/// The value of the stanza's to attribute

	OFString *to;


	/// The value of the stanza's type attribute

	OFString *type;


	/// The value of the stanza's id attribute

	OFString *ID;
}

@property (copy) OFString *from;
@property (copy) OFString *to;
@property (copy) OFString *type;
@property (copy) OFString *ID;

/**
 * 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
 */
+ stanzaWithName: (OFString*)name;

/**
 * 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
 * \return A new autoreleased XMPPStanza
 */
+ stanzaWithName: (OFString*)name
	    type: (OFString*)type;

/**
 * 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
 * \return A new autoreleased XMPPStanza
 */
+ stanzaWithName: (OFString*)name
	      ID: (OFString*)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
 * \param ID The value for the stanza's id attribute
 * \return A new autoreleased XMPPStanza
 */
+ stanzaWithName: (OFString*)name
	    type: (OFString*)type
	      ID: (OFString*)ID;

/**
 * Creates a new autoreleased XMPPStanza from an OFXMLElement.
 *
 * \param elem The element to base the XMPPStanza on
 * \return A new autoreleased XMPPStanza
 */
+ stanzaWithElement: (OFXMLElement*)elem;

/**
 * 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
 */
- initWithName: (OFString*)name;

/**
 * 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;

/**
 * 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;

/**
 * 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
 * \param ID The value for the stanza's id attribute
 * \return A initialized XMPPStanza
 */
- initWithName: (OFString*)name
	  type: (OFString*)type
	    ID: (OFString*)ID;

/**
 * Initializes an already allocated XMPPStanza based on a OFXMLElement
 *
 * \param elem The element to base the XMPPStanza on
 * \return A initialized XMPPStanza
 */

Modified src/XMPPStanza.m from [1421b4edb3] to [3a525ca278].

61
62
63
64
65
66
67
68
69
70
71
72
73


74

75
76

77
78





79
80
81
82
83
84
85
86

87

88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126


127

128
129
130
131
132
133
134


135

136
137
138
139
140
141
142


143

144
145
146
147
148
149
150


151
152
153
154
			       ID: ID_];
}

- initWithName: (OFString*)name_
	  type: (OFString*)type_
	    ID: (OFString*)ID_
{
	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_];





	return self;
}

- initWithElement: (OFXMLElement*)elem
{
	self = [super initWithName: elem.name
			 namespace: elem.namespace];


	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







|
|
|



>
>
|
>
|
|
>
|
|
>
>
>
>
>








>
|
>

|
|
|
|
|
|
|
|
|
|
|

|
<
<
<
|
|
>
>
>




















>
>
|
>







>
>
|
>







>
>
|
>







>
>




61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
			       ID: ID_];
}

- initWithName: (OFString*)name_
	  type: (OFString*)type_
	    ID: (OFString*)ID_
{
	if (![name_ isEqual: @"iq"] &&
	    ![name_ isEqual: @"message"] &&
	    ![name_ isEqual: @"presence"])
		of_log(@"Invalid stanza name!");

	self = [super initWithName: name_];

	@try {
		[self setDefaultNamespace: @"jabber:client"];

		if (type_)
			[self setType: type_];

		if (ID_)
			[self setID: ID_];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- initWithElement: (OFXMLElement*)elem
{
	self = [super initWithName: elem.name
			 namespace: elem.namespace];

	@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 (el in elem.children)
			[self addChild: el];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	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];

	/* FIXME: Remove old attribute! */
	[self addAttributeWithName: @"from"
		       stringValue: from_];
}

- (void)setTo: (OFString*)to_
{
	OFString* old = to;
	to = [to_ copy];
	[old release];

	/* FIXME: Remove old attribute! */
	[self addAttributeWithName: @"to"
		       stringValue: to];
}

- (void)setType: (OFString*)type_
{
	OFString* old = type;
	type = [type_ copy];
	[old release];

	/* FIXME: Remove old attribute! */
	[self addAttributeWithName: @"type"
		       stringValue: type];
}

- (void)setID: (OFString*)ID_
{
	OFString* old = ID;
	ID = [ID_ copy];
	[old release];

	/* FIXME: Remove old attribute! */
	[self addAttributeWithName: @"id"
		       stringValue: ID];
}
@end

Modified tests/test.m from [2270757ce5] to [d49aed7d0d].

1
2
3
4
5
6



7
8
9
10
11
12
13
#include <assert.h>

#import <ObjFW/ObjFW.h>

#import "XMPPConnection.h"
#import "XMPPStanza.h"




@interface AppDelegate: OFObject
{
	XMPPConnection *conn;
}
@end







>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <assert.h>

#import <ObjFW/ObjFW.h>

#import "XMPPConnection.h"
#import "XMPPStanza.h"
#import "XMPPIQ.h"
#import "XMPPMessage.h"
#import "XMPPPresence.h"

@interface AppDelegate: OFObject
{
	XMPPConnection *conn;
}
@end

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
	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: @"<presence to='alice@example.com' "
			@"from='bob@example.org'><show>chat</show>"
			@"<status>Bored</status><priority>20</priority>"
			@"</presence>"]);

	XMPPMessage *msg = [XMPPMessage messageWithType: @"chat"];
	[msg addBody: @"Hello everyone"];
	msg.to = @"jdev@conference.jabber.org";
	msg.from = @"alice@example.com";
	assert([[msg stringValue] isEqual: @"<message type='chat' "
			@"to='jdev@conference.jabber.org' "
			@"from='alice@example.com'><body>Hello everyone</body>"
			@"</message>"]);

	XMPPIQ *iq = [XMPPIQ IQWithType: @"set" ID: @"128"];
	iq.to = @"juliet@capulet.lit";
	iq.from = @"romeo@montague.lit";
	assert([[iq stringValue] isEqual: @"<iq type='set' id='128' "
			@"to='juliet@capulet.lit' "
			@"from='romeo@montague.lit'/>"]);

	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];
	}







|
|
|






|
|
|





|
|









|
|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
	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: @"<presence to='alice@example.com' "
	    @"from='bob@example.org'><show>chat</show>"
	    @"<status>Bored</status><priority>20</priority>"
	    @"</presence>"]);

	XMPPMessage *msg = [XMPPMessage messageWithType: @"chat"];
	[msg addBody: @"Hello everyone"];
	msg.to = @"jdev@conference.jabber.org";
	msg.from = @"alice@example.com";
	assert([[msg stringValue] isEqual: @"<message type='chat' "
	    @"to='jdev@conference.jabber.org' "
	    @"from='alice@example.com'><body>Hello everyone</body>"
	    @"</message>"]);

	XMPPIQ *iq = [XMPPIQ IQWithType: @"set" ID: @"128"];
	iq.to = @"juliet@capulet.lit";
	iq.from = @"romeo@montague.lit";
	assert([[iq stringValue] isEqual: @"<iq type='set' id='128' "
	    @"to='juliet@capulet.lit' "
	    @"from='romeo@montague.lit'/>"]);

	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];
	}