ObjXMPP  Check-in [d7038ec36d]

Overview
Comment:Adjust to recent ObjFW changes.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: d7038ec36d10898b73b44fde116504ee11ad9ef1af1d54a6dc949121c4c16e20
User & Date: js on 2011-04-23 20:40:32
Other Links: manifest | tags
Context
2011-04-23
22:41
Correctly handle stream restart. check-in: 758ecec9ee user: js tags: trunk
20:40
Adjust to recent ObjFW changes. check-in: d7038ec36d user: js tags: trunk
2011-04-15
00:51
Don't answer to IQs of type "error" or "result" check-in: 0e2d960203 user: florob@babelmonkeys.de tags: trunk
Changes

Modified src/XMPPConnection.h from [660f92f7a3] to [72439fbdc3].

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







-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+







@protocol XMPPConnectionDelegate
#ifndef XMPP_CONNECTION_M
    <OFObject>
#endif
#ifdef OF_HAVE_OPTIONAL_PROTOCOLS
@optional
#endif
- (void)connectionWasAuthenticated: (XMPPConnection*)conn;
- (void)connection: (XMPPConnection*)conn
     wasBoundToJID: (XMPPJID*)jid;
- (void)connectionDidReceiveRoster: (XMPPConnection*)conn;
- (BOOL)connection: (XMPPConnection*)conn
- (void)connectionWasAuthenticated: (XMPPConnection*)connection;
- (void)connection: (XMPPConnection*)connection
     wasBoundToJID: (XMPPJID*)JID;
- (void)connectionDidReceiveRoster: (XMPPConnection*)connection;
- (BOOL)connection: (XMPPConnection*)connection
      didReceiveIQ: (XMPPIQ*)iq;
-   (void)connection: (XMPPConnection*)conn
  didReceivePresence: (XMPPPresence*)pres;
-  (void)connection: (XMPPConnection*)conn
  didReceiveMessage: (XMPPMessage*)msg;
-     (void)connection: (XMPPConnection*)conn
-   (void)connection: (XMPPConnection*)connection
  didReceivePresence: (XMPPPresence*)presence;
-  (void)connection: (XMPPConnection*)connection
  didReceiveMessage: (XMPPMessage*)message;
-     (void)connection: (XMPPConnection*)connection
  didReceiveRosterItem: (XMPPRosterItem*)rosterItem;
- (void)connectionWasClosed: (XMPPConnection*)conn;
- (void)connectionWillUpgradeToTLS: (XMPPConnection*)conn;
- (void)connectionDidUpgradeToTLS: (XMPPConnection*)conn;
- (void)connectionWasClosed: (XMPPConnection*)connection;
- (void)connectionWillUpgradeToTLS: (XMPPConnection*)connection;
- (void)connectionDidUpgradeToTLS: (XMPPConnection*)connection;
@end

/**
 * \brief A class which abstracts a connection to an XMPP service.
 */
@interface XMPPConnection: OFObject
#ifdef OF_HAVE_OPTONAL_PROTOCOLS
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
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







-
-
-
+
+
+

-
-
+
+









-
+

-
+







- (void)handleConnection;

/**
 * Parses the specified buffer.
 *
 * This is useful for handling multiple connections at once.
 *
 * \param buf The buffer to parse
 * \param size The size of the buffer. If size is 0, it is assumed that the
 *	       connection was closed.
 * \param buffer The buffer to parse
 * \param length The length of the buffer. If length is 0, it is assumed that
 *		 the connection was closed.
 */
- (void)parseBuffer: (const char*)buf
	   withSize: (size_t)size;
- (void)parseBuffer: (const char*)buffer
	 withLength: (size_t)length;

/**
 * \return The socket used by the XMPPConnection
 */
- (OFTCPSocket*)socket;

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

/**
 * Generates a new, unique stanza ID.
 *
 * \return A new, generated, unique stanza ID.
 */
- (OFString*)generateStanzaID;
160
161
162
163
164
165
166
167
168
169
170
171





172
173
174
175



176
177
178
179
180
181
182
183
184
160
161
162
163
164
165
166





167
168
169
170
171
172



173
174
175
176
177
178
179
180
181
182
183
184







-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+









- (void)setPort: (uint16_t)port;
- (uint16_t)port;
- (void)setDelegate: (id <XMPPConnectionDelegate>)delegate;
- (id <XMPPConnectionDelegate>)delegate;
- (XMPPRoster*)roster;

- (void)XMPP_startStream;
- (void)XMPP_handleStream: (OFXMLElement*)elem;
- (void)XMPP_handleTLS: (OFXMLElement*)elem;
- (void)XMPP_handleSASL: (OFXMLElement*)elem;
- (void)XMPP_handleStanza: (OFXMLElement*)elem;
- (void)XMPP_sendAuth: (OFString*)name;
- (void)XMPP_handleStream: (OFXMLElement*)element;
- (void)XMPP_handleTLS: (OFXMLElement*)element;
- (void)XMPP_handleSASL: (OFXMLElement*)element;
- (void)XMPP_handleStanza: (OFXMLElement*)element;
- (void)XMPP_sendAuth: (OFString*)authName;
- (void)XMPP_handleIQ: (XMPPIQ*)iq;
- (void)XMPP_handleMessage: (XMPPMessage*)msg;
- (void)XMPP_handlePresence: (XMPPPresence*)pres;
- (void)XMPP_handleFeatures: (OFXMLElement*)elem;
- (void)XMPP_handleMessage: (XMPPMessage*)message;
- (void)XMPP_handlePresence: (XMPPPresence*)presence;
- (void)XMPP_handleFeatures: (OFXMLElement*)element;
- (void)XMPP_sendResourceBind;
- (void)XMPP_handleResourceBind: (XMPPIQ*)iq;
- (void)XMPP_sendSession;
- (void)XMPP_handleSession: (XMPPIQ*)iq;
- (void)XMPP_handleRoster: (XMPPIQ*)iq;
@end

@interface OFObject (XMPPConnectionDelegate) <XMPPConnectionDelegate>
@end

Modified src/XMPPConnection.m from [095d6e4f35] to [9e2fd410e9].

210
211
212
213
214
215
216
217

218
219
220
221


222
223

224
225
226
227
228


229
230
231
232
233


234
235

236
237
238
239
240


241
242
243
244
245
246
247
248

249
250
251


252
253
254
255
256
257
258
210
211
212
213
214
215
216

217
218
219


220
221
222

223
224
225
226


227
228
229
230
231


232
233
234

235
236
237
238


239
240
241
242
243
244
245
246
247

248
249


250
251
252
253
254
255
256
257
258







-
+


-
-
+
+

-
+



-
-
+
+



-
-
+
+

-
+



-
-
+
+







-
+

-
-
+
+







	[self XMPP_startStream];

	[pool release];
}

- (void)handleConnection
{
	char buf[512];
	char buffer[512];

	for (;;) {
		size_t len = [sock readNBytes: 512
				   intoBuffer: buf];
		size_t length = [sock readNBytes: 512
				      intoBuffer: buffer];

		if (len < 1 && [delegate respondsToSelector:
		if (length < 1 && [delegate respondsToSelector:
		    @selector(connectionWasClosed:)])
			[delegate connectionWasClosed: self];

		[parser parseBuffer: buf
			   withSize: len];
		[parser parseBuffer: buffer
			 withLength: length];
	}
}

- (void)parseBuffer: (const char*)buf
	   withSize: (size_t)size
- (void)parseBuffer: (const char*)buffer
	 withLength: (size_t)length
{
	if (size < 1 && [delegate respondsToSelector:
	if (length < 1 && [delegate respondsToSelector:
	    @selector(connectionWasClosed:)])
		[delegate connectionWasClosed: self];

	[parser parseBuffer: buf
		   withSize: size];
	[parser parseBuffer: buffer
		 withLength: length];
}

- (OFTCPSocket*)socket
{
	return [[sock retain] autorelease];
}

- (void)sendStanza: (OFXMLElement*)elem
- (void)sendStanza: (OFXMLElement*)element
{
	of_log(@"Out: %@", elem);
	[sock writeString: [elem XMLString]];
	of_log(@"Out: %@", element);
	[sock writeString: [element XMLString]];
}

- (OFString*)generateStanzaID
{
	return [OFString stringWithFormat: @"objxmpp_%u", lastID++];
}

295
296
297
298
299
300
301
302
303


304
305
306
307
308
309



310
311

312
313
314


315
316
317


318
319
320


321
322
323


324
325
326
327
328
329
330
331
332
333
334
335
336
337

338
339
340


341
342
343
344

345
346

347
348
349
350

351
352

353
354
355
356
357
358
359
360

361
362
363


364
365
366
367

368
369
370
371
372
373
374


375
376
377


378
379
380


381
382
383


384
385
386


387
388
389


390
391
392


393
394
395


396
397
398


399
400
401


402
403
404


405
406
407


408
409
410


411
412
413


414
415
416


417
418
419


420
421
422


423
424
425


426
427
428


429
430
431


432
433
434


435
436
437


438
439
440


441
442
443


444
445
446


447
448
449
450
451
452



453
454
455
456
457
458
459
460
461
462
463
464
465

466
467

468
469
470
471
472
473
474
295
296
297
298
299
300
301


302
303
304
305
306



307
308
309
310

311
312


313
314
315


316
317
318


319
320
321


322
323
324
325
326
327
328
329
330
331
332
333
334
335
336

337
338


339
340
341
342
343

344
345

346
347
348
349

350
351

352
353
354
355
356
357
358
359

360
361


362
363
364
365
366

367
368
369
370
371
372


373
374
375


376
377
378


379
380
381


382
383
384


385
386
387


388
389
390


391
392
393


394
395
396


397
398
399


400
401
402


403
404
405


406
407
408


409
410
411


412
413
414


415
416
417


418
419
420


421
422
423


424
425
426


427
428
429


430
431
432


433
434
435


436
437
438


439
440
441


442
443
444


445
446
447
448
449
450


451
452
453

454
455
456
457
458
459
460
461
462
463
464

465
466

467
468
469
470
471
472
473
474







-
-
+
+



-
-
-
+
+
+

-
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+













-
+

-
-
+
+



-
+

-
+



-
+

-
+







-
+

-
-
+
+



-
+





-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+




-
-
+
+
+
-











-
+

-
+







	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
- (void)elementBuilder: (OFXMLElementBuilder*)builder
       didBuildElement: (OFXMLElement*)element
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];

	[elem setDefaultNamespace: XMPP_NS_CLIENT];
	[elem setPrefix: @"stream"
	   forNamespace: XMPP_NS_STREAM];
	[element setDefaultNamespace: XMPP_NS_CLIENT];
	[element setPrefix: @"stream"
	      forNamespace: XMPP_NS_STREAM];

	of_log(@"In:  %@", elem);
	of_log(@"In:  %@", element);

	if ([[elem namespace] isEqual: XMPP_NS_CLIENT])
		[self XMPP_handleStanza: elem];
	if ([[element namespace] isEqual: XMPP_NS_CLIENT])
		[self XMPP_handleStanza: element];

	if ([[elem namespace] isEqual: XMPP_NS_STREAM])
		[self XMPP_handleStream: elem];
	if ([[element namespace] isEqual: XMPP_NS_STREAM])
		[self XMPP_handleStream: element];

	if ([[elem namespace] isEqual: XMPP_NS_STARTTLS])
		[self XMPP_handleTLS: elem];
	if ([[element namespace] isEqual: XMPP_NS_STARTTLS])
		[self XMPP_handleTLS: element];

	if ([[elem namespace] isEqual: XMPP_NS_SASL])
		[self XMPP_handleSASL: elem];
	if ([[element namespace] isEqual: XMPP_NS_SASL])
		[self XMPP_handleSASL: element];

	[pool release];
}

- (void)XMPP_startStream
{
	[sock writeFormat: @"<?xml version='1.0'?>\n"
			   @"<stream:stream to='%@' "
			   @"xmlns='" XMPP_NS_CLIENT @"' "
			   @"xmlns:stream='" XMPP_NS_STREAM @"' "
			   @"version='1.0'>", server];
}

- (void)XMPP_handleStanza: (OFXMLElement*)elem
- (void)XMPP_handleStanza: (OFXMLElement*)element
{
	if ([[elem name] isEqual: @"iq"]) {
		[self XMPP_handleIQ: [XMPPIQ stanzaWithElement: elem]];
	if ([[element name] isEqual: @"iq"]) {
		[self XMPP_handleIQ: [XMPPIQ stanzaWithElement: element]];
		return;
	}

	if ([[elem name] isEqual: @"message"]) {
	if ([[element name] isEqual: @"message"]) {
		[self XMPP_handleMessage:
		    [XMPPMessage stanzaWithElement: elem]];
		    [XMPPMessage stanzaWithElement: element]];
		return;
	}

	if ([[elem name] isEqual: @"presence"]) {
	if ([[element name] isEqual: @"presence"]) {
		[self XMPP_handlePresence:
		    [XMPPPresence stanzaWithElement: elem]];
		    [XMPPPresence stanzaWithElement: element]];
		return;
	}

	assert(0);
}


- (void)XMPP_handleStream: (OFXMLElement*)elem
- (void)XMPP_handleStream: (OFXMLElement*)element
{
	if ([[elem name] isEqual: @"features"]) {
		[self XMPP_handleFeatures: elem];
	if ([[element name] isEqual: @"features"]) {
		[self XMPP_handleFeatures: element];
		return;
	}

	if ([[elem name] isEqual: @"error"]) {
	if ([[element name] isEqual: @"error"]) {
		OFString *condition, *reason;
		[parser setDelegate: self];
		[sock writeString: @"</stream:stream>"];
		[sock close];

		if ([elem elementForName: @"bad-format"
			       namespace: XMPP_NS_XMPP_STREAM])
		if ([element elementForName: @"bad-format"
				  namespace: XMPP_NS_XMPP_STREAM])
			condition = @"bad-format";
		else if ([elem elementForName: @"bad-namespace-prefix"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"bad-namespace-prefix"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"bad-namespace-prefix";
		else if ([elem elementForName: @"conflict"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"conflict"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"conflict";
		else if ([elem elementForName: @"connection-timeout"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"connection-timeout"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"connection-timeout";
		else if ([elem elementForName: @"host-gone"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"host-gone"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"host-gone";
		else if ([elem elementForName: @"host-unknown"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"host-unknown"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"host-unknown";
		else if ([elem elementForName: @"improper-addressing"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"improper-addressing"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"improper-addressing";
		else if ([elem elementForName: @"internal-server-error"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"internal-server-error"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"internal-server-error";
		else if ([elem elementForName: @"invalid-from"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"invalid-from"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"invalid-from";
		else if ([elem elementForName: @"invalid-namespace"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"invalid-namespace"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"invalid-namespace";
		else if ([elem elementForName: @"invalid-xml"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"invalid-xml"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"invalid-xml";
		else if ([elem elementForName: @"not-authorized"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"not-authorized"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"not-authorized";
		else if ([elem elementForName: @"not-well-formed"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"not-well-formed"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"not-well-formed";
		else if ([elem elementForName: @"policy-violation"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"policy-violation"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"policy-violation";
		else if ([elem elementForName: @"remote-connection-failed"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"remote-connection-failed"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"remote-connection-failed";
		else if ([elem elementForName: @"reset"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"reset"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"reset";
		else if ([elem elementForName: @"resource-constraint"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"resource-constraint"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"resource-constraint";
		else if ([elem elementForName: @"restricted-xml"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"restricted-xml"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"restricted-xml";
		else if ([elem elementForName: @"see-other-host"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"see-other-host"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"see-other-host";
		else if ([elem elementForName: @"system-shutdown"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"system-shutdown"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"system-shutdown";
		else if ([elem elementForName: @"undefined-condition"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"undefined-condition"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"undefined-condition";
		else if ([elem elementForName: @"unsupported-encoding"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"unsupported-encoding"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"unsupported-encoding";
		else if ([elem elementForName: @"unsupported-feature"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"unsupported-feature"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"unsupported-feature";
		else if ([elem elementForName: @"unsupported-stanza-type"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"unsupported-stanza-type"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"unsupported-stanza-type";
		else if ([elem elementForName: @"unsupported-version"
				    namespace: XMPP_NS_XMPP_STREAM])
		else if ([element elementForName: @"unsupported-version"
				       namespace: XMPP_NS_XMPP_STREAM])
			condition = @"unsupported-version";
		else
			condition = @"undefined";

		reason = [[elem elementForName: @"text"
				     namespace: XMPP_NS_XMPP_STREAM]
		reason = [[element
		    elementForName: @"text"
			 namespace: XMPP_NS_XMPP_STREAM] stringValue];
				stringValue];

		@throw [XMPPStreamErrorException newWithClass: isa
						   connection: self
						    condition: condition
						       reason: reason];
		return;
	}

	assert(0);
}

- (void)XMPP_handleTLS: (OFXMLElement*)elem
- (void)XMPP_handleTLS: (OFXMLElement*)element
{
	if ([[elem name] isEqual: @"proceed"]) {
	if ([[element name] isEqual: @"proceed"]) {
		/* FIXME: Catch errors here */
		SSLSocket *newSock;

		if ([delegate respondsToSelector:
		    @selector(connectionWillUpgradeToTLS:)])
			[delegate connectionWillUpgradeToTLS: self];

482
483
484
485
486
487
488
489

490
491
492
493
494
495
496

497
498

499
500
501


502
503
504
505
506

507
508
509


510
511
512
513
514
515
516
517
518
519



520
521
522
523
524
525
526
527
528
529
530
531
532

533
534
535
536
537
538

539
540
541
542
543
544
545
482
483
484
485
486
487
488

489
490
491
492
493
494
495

496
497

498
499


500
501

502
503
504

505



506
507

508
509
510
511
512
513



514
515
516

517
518
519
520
521
522
523
524
525
526
527

528
529
530
531
532
533

534
535
536
537
538
539
540
541







-
+






-
+

-
+

-
-
+
+
-



-
+
-
-
-
+
+
-






-
-
-
+
+
+
-











-
+





-
+








		/* Stream restart */
		[parser setDelegate: self];
		[self XMPP_startStream];
		return;
	}

	if ([[elem name] isEqual: @"failure"])
	if ([[element name] isEqual: @"failure"])
		/* TODO: Find/create an exception to throw here */
		@throw [OFException newWithClass: isa];

	assert(0);
}

- (void)XMPP_handleSASL: (OFXMLElement*)elem
- (void)XMPP_handleSASL: (OFXMLElement*)element
{
	if ([[elem name] isEqual: @"challenge"]) {
	if ([[element name] isEqual: @"challenge"]) {
		OFXMLElement *responseTag;
		OFDataArray *challenge =
		    [OFDataArray dataArrayWithBase64EncodedString:
		OFDataArray *challenge = [OFDataArray
		    dataArrayWithBase64EncodedString: [element stringValue]];
		    [elem stringValue]];
		OFDataArray *response = [authModule
		    calculateResponseWithChallenge: challenge];

		responseTag = [OFXMLElement
		responseTag = [OFXMLElement  elementWithName: @"response"
		    elementWithName: @"response"
			  namespace: XMPP_NS_SASL];
		[responseTag addChild:
						   namespace: XMPP_NS_SASL];
		[responseTag addChild: [OFXMLElement elementWithCharacters:
		    [OFXMLElement elementWithCharacters:
		    [response stringByBase64Encoding]]];

		[self sendStanza: responseTag];
		return;
	}

	if ([[elem name] isEqual: @"success"]) {
		[authModule parseServerFinalMessage:
		    [OFDataArray dataArrayWithBase64EncodedString:
	if ([[element name] isEqual: @"success"]) {
		[authModule parseServerFinalMessage: [OFDataArray
		    dataArrayWithBase64EncodedString: [element stringValue]]];
			[elem stringValue]]];

		if ([delegate respondsToSelector:
		    @selector(connectionWasAuthenticated:)])
			[delegate connectionWasAuthenticated: self];

		/* Stream restart */
		[parser setDelegate: self];
		[self XMPP_startStream];
		return;
	}

	if ([[elem name] isEqual: @"failure"]) {
	if ([[element name] isEqual: @"failure"]) {
		of_log(@"Auth failed!");
		// FIXME: Do more parsing/handling
		@throw [XMPPAuthFailedException
		    newWithClass: isa
		      connection: self
			  reason: [elem XMLString]];
			  reason: [element XMLString]];
	}

	assert(0);
}

- (void)XMPP_handleIQ: (XMPPIQ*)iq
{
583
584
585
586
587
588
589
590

591
592
593
594
595

596
597
598

599
600
601
602
603

604
605
606

607
608
609
610
611
612
613
614
615








616
617
618
619
620
621
622
579
580
581
582
583
584
585

586
587
588
589
590

591
592
593

594
595
596
597
598

599
600
601

602
603








604
605
606
607
608
609
610
611
612
613
614
615
616
617
618







-
+




-
+


-
+




-
+


-
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+







					namespace: XMPP_NS_STANZAS]];
		[iq addChild: error];

		[self sendStanza: iq];
	}
}

- (void)XMPP_handleMessage: (XMPPMessage*)msg
- (void)XMPP_handleMessage: (XMPPMessage*)message
{
	if ([delegate respondsToSelector:
	     @selector(connection:didReceiveMessage:)])
		[delegate connection: self
		   didReceiveMessage: msg];
		   didReceiveMessage: message];
}

- (void)XMPP_handlePresence: (XMPPPresence*)pres
- (void)XMPP_handlePresence: (XMPPPresence*)presence
{
	if ([delegate respondsToSelector:
	     @selector(connection:didReceivePresence:)])
		[delegate connection: self
		  didReceivePresence: pres];
		  didReceivePresence: presence];
}

- (void)XMPP_handleFeatures: (OFXMLElement*)elem
- (void)XMPP_handleFeatures: (OFXMLElement*)element
{
	OFXMLElement *starttls = [elem elementForName: @"starttls"
					    namespace: XMPP_NS_STARTTLS];
	OFXMLElement *bind = [elem elementForName: @"bind"
					namespace: XMPP_NS_BIND];
	OFXMLElement *session = [elem elementForName: @"session"
					   namespace: XMPP_NS_SESSION];
	OFXMLElement *mechs = [elem elementForName: @"mechanisms"
					 namespace: XMPP_NS_SASL];
	OFXMLElement *starttls = [element elementForName: @"starttls"
					       namespace: XMPP_NS_STARTTLS];
	OFXMLElement *bind = [element elementForName: @"bind"
					   namespace: XMPP_NS_BIND];
	OFXMLElement *session = [element elementForName: @"session"
					      namespace: XMPP_NS_SESSION];
	OFXMLElement *mechs = [element elementForName: @"mechanisms"
					    namespace: XMPP_NS_SASL];
	OFMutableArray *mechanisms = [OFMutableArray array];

	if (starttls != nil) {
		[self sendStanza:
		    [OFXMLElement elementWithName: @"starttls"
					namespace: XMPP_NS_STARTTLS]];
		return;
657
658
659
660
661
662
663
664

665
666
667
668
669
670
671

672
673
674
675
676
677
678
653
654
655
656
657
658
659

660
661
662
663
664
665
666

667
668
669
670
671
672
673
674







-
+






-
+







		[self XMPP_sendResourceBind];
		return;
	}

	assert(0);
}

- (void)XMPP_sendAuth: (OFString*)name
- (void)XMPP_sendAuth: (OFString*)authName
{
	OFXMLElement *authTag;

	authTag = [OFXMLElement elementWithName: @"auth"
				      namespace: XMPP_NS_SASL];
	[authTag addAttributeWithName: @"mechanism"
			  stringValue: name];
			  stringValue: authName];
	[authTag addChild: [OFXMLElement elementWithCharacters:
	    [[authModule clientFirstMessage] stringByBase64Encoding]]];

	[self sendStanza: authTag];
}

- (void)XMPP_sendResourceBind
694
695
696
697
698
699
700
701
702


703
704
705
706
707


708
709

710
711
712
713



714
715
716
717
718
719
720
690
691
692
693
694
695
696


697
698
699
700
701


702
703
704

705
706



707
708
709
710
711
712
713
714
715
716







-
-
+
+



-
-
+
+

-
+

-
-
-
+
+
+







	[iq addChild: bind];

	[self sendStanza: iq];
}

- (void)XMPP_handleResourceBind: (XMPPIQ*)iq
{
	OFXMLElement *bindElem;
	OFXMLElement *jidElem;
	OFXMLElement *bindElement;
	OFXMLElement *jidElement;

	assert([[iq type] isEqual: @"result"]);

	bindElem = [iq elementForName: @"bind"
			    namespace: XMPP_NS_BIND];
	bindElement = [iq elementForName: @"bind"
			       namespace: XMPP_NS_BIND];

	assert(bindElem != nil);
	assert(bindElement != nil);

	jidElem = [bindElem elementForName: @"jid"
				 namespace: XMPP_NS_BIND];
	JID = [[XMPPJID alloc] initWithString: [jidElem stringValue]];
	jidElement = [bindElement elementForName: @"jid"
				       namespace: XMPP_NS_BIND];
	JID = [[XMPPJID alloc] initWithString: [jidElement stringValue]];

	[bindID release];
	bindID = nil;

	if (needsSession) {
		[self XMPP_sendSession];
		return;
763
764
765
766
767
768
769
770
771


772
773
774
775
776
777
778


779
780
781
782
783
784
785
786


787
788
789

790
791
792


793
794
795
796
797

798
799

800
801
802



803
804
805
806
807
808

809
810
811
812
813



814
815

816
817

818
819
820
821
822
823
824
759
760
761
762
763
764
765


766
767
768
769
770
771
772


773
774
775
776
777
778
779
780


781
782
783
784

785
786


787
788
789
790
791
792

793
794

795
796


797
798
799
800
801
802
803
804
805
806
807
808



809
810
811


812


813
814
815
816
817
818
819
820







-
-
+
+





-
-
+
+






-
-
+
+


-
+

-
-
+
+




-
+

-
+

-
-
+
+
+






+


-
-
-
+
+
+
-
-
+
-
-
+







	[iq addChild: [OFXMLElement elementWithName: @"query"
					  namespace: XMPP_NS_ROSTER]];
	[self sendStanza: iq];
}

- (void)XMPP_handleRoster: (XMPPIQ*)iq
{
	OFXMLElement *rosterElem;
	OFXMLElement *elem;
	OFXMLElement *rosterElement;
	OFXMLElement *element;
	XMPPRosterItem *rosterItem = nil;
	OFString *subscription;
	OFEnumerator *enumerator;
	BOOL isPush = ![[iq ID] isEqual: rosterID];

	rosterElem = [iq elementForName: @"query"
			      namespace: XMPP_NS_ROSTER];
	rosterElement = [iq elementForName: @"query"
				 namespace: XMPP_NS_ROSTER];

	if (isPush)
		assert([[iq type] isEqual: @"set"]);
	else
		assert([[iq type] isEqual: @"result"]);

	enumerator = [[rosterElem children] objectEnumerator];
	while ((elem = [enumerator nextObject]) != nil) {
	enumerator = [[rosterElement children] objectEnumerator];
	while ((element = [enumerator nextObject]) != nil) {
		OFMutableArray *groups = [OFMutableArray array];
		OFEnumerator *groupEnumerator;
		OFXMLElement *groupElem;
		OFXMLElement *groupElement;

		if (![[elem name] isEqual: @"item"] ||
		    ![[elem namespace] isEqual: XMPP_NS_ROSTER])
		if (![[element name] isEqual: @"item"] ||
		    ![[element namespace] isEqual: XMPP_NS_ROSTER])
			continue;

		rosterItem = [XMPPRosterItem rosterItem];
		[rosterItem setJID: [XMPPJID JIDWithString:
		    [[elem attributeForName: @"jid"] stringValue]]];
		    [[element attributeForName: @"jid"] stringValue]]];
		[rosterItem setName:
		    [[elem attributeForName: @"name"] stringValue]];
		    [[element attributeForName: @"name"] stringValue]];

		subscription = [[elem attributeForName:
			@"subscription"] stringValue];
		subscription = [[element attributeForName:
		    @"subscription"] stringValue];

		if (![subscription isEqual: @"none"] &&
		    ![subscription isEqual: @"to"] &&
		    ![subscription isEqual: @"from"] &&
		    ![subscription isEqual: @"both"] &&
		    (![subscription isEqual: @"remove"] || !isPush))
			subscription = @"none";

		[rosterItem setSubscription: subscription];

		groupEnumerator =
		    [[elem elementsForName: @"group"
				 namespace: XMPP_NS_ROSTER]
		groupEnumerator = [[element
		    elementsForName: @"group"
			  namespace: XMPP_NS_ROSTER] objectEnumerator];
			objectEnumerator];
		while ((groupElem = [groupEnumerator nextObject])
		while ((groupElement = [groupEnumerator nextObject]) != nil)
				!= nil)
			[groups addObject: [groupElem stringValue]];
			[groups addObject: [groupElement stringValue]];

		if ([groups count] > 0)
			[rosterItem setGroups: groups];

		if ([subscription isEqual: @"remove"])
			[roster XMPP_deleteRosterItem: rosterItem];
		else
875
876
877
878
879
880
881
882






883
884
885
886

887
888
889
890
891
892
893
894
895

896
897
898
899
900
901
902


903
904
905
906
907


908
909
910
911

912
913
914
915
916

917
918
919
920

921
922
923
924

925
926
927
871
872
873
874
875
876
877

878
879
880
881
882
883
884
885
886

887

888
889
890





891
892
893
894
895
896


897
898
899
900
901


902
903
904
905
906

907
908
909
910
911

912
913
914
915

916
917
918
919

920
921
922
923







-
+
+
+
+
+
+



-
+
-



-
-
-
-
-
+





-
-
+
+



-
-
+
+



-
+




-
+



-
+



-
+



- (XMPPRoster*)roster
{
	return [[roster retain] autorelease];
}
@end

@implementation OFObject (XMPPConnectionDelegate)
- (void)connectionWasAuthenticated: (XMPPConnection*)conn
- (void)connectionWasAuthenticated: (XMPPConnection*)connection
{
}

- (void)connection: (XMPPConnection*)connection
     wasBoundToJID: (XMPPJID*)JID
{
}

- (void)connection: (XMPPConnection*)conn
- (void)connectionDidReceiveRoster: (XMPPConnection*)connection
     wasBoundToJID: (XMPPJID*)jid
{
}

- (void)connectionDidReceiveRoster: (XMPPConnection*)conn
{
}

- (BOOL)connection: (XMPPConnection*)conn
- (BOOL)connection: (XMPPConnection*)connection
      didReceiveIQ: (XMPPIQ*)iq
{
	return NO;
}

-   (void)connection: (XMPPConnection*)conn
  didReceivePresence: (XMPPPresence*)pres
-   (void)connection: (XMPPConnection*)connection
  didReceivePresence: (XMPPPresence*)presence
{
}

-  (void)connection: (XMPPConnection*)conn
  didReceiveMessage: (XMPPMessage*)msg
-  (void)connection: (XMPPConnection*)connection
  didReceiveMessage: (XMPPMessage*)message
{
}

-     (void)connection: (XMPPConnection*)conn
-     (void)connection: (XMPPConnection*)connection
  didReceiveRosterItem: (XMPPRosterItem*)rosterItem
{
}

- (void)connectionWasClosed: (XMPPConnection*)conn
- (void)connectionWasClosed: (XMPPConnection*)connection
{
}

- (void)connectionWillUpgradeToTLS: (XMPPConnection*)conn
- (void)connectionWillUpgradeToTLS: (XMPPConnection*)connection
{
}

- (void)connectionDidUpgradeToTLS: (XMPPConnection*)conn
- (void)connectionDidUpgradeToTLS: (XMPPConnection*)connection
{
}
@end

Modified src/XMPPSCRAMAuth.m from [582a13eb09] to [8d48b44617].

261
262
263
264
265
266
267
268

269
270
271
272
273
274
275
261
262
263
264
265
266
267

268
269
270
271
272
273
274
275







-
+







				      data: tmpArray];

	/*
	 * IETF RFC 5802:
	 * StoredKey := H(ClientKey)
	 */
	[hash updateWithBuffer: (void*) clientKey
			ofSize: [hashType digestSize]];
			length: [hashType digestSize]];
	tmpArray = [OFDataArray dataArrayWithItemSize: 1];
	[tmpArray addNItems: [hashType digestSize]
		 fromCArray: [hash digest]];

	/*
	 * IETF RFC 5802:
	 * ClientSignature := HMAC(StoredKey, AuthMessage)
374
375
376
377
378
379
380
381

382
383
384
385
386
387
388
374
375
376
377
378
379
380

381
382
383
384
385
386
387
388







-
+







	size_t i, kSize, blockSize = [hashType blockSize];
	uint8_t *kCArray, *kI = NULL, *kO = NULL;
	OFHash *hash;

	if ([key itemSize] * [key count] > blockSize) {
		hash = [[[hashType alloc] init] autorelease];
		[hash updateWithBuffer: [key cArray]
				ofSize: [key itemSize] * [key count]];
				length: [key itemSize] * [key count]];
		[k addNItems: [hashType digestSize]
		  fromCArray: [hash digest]];
	} else
		[k addNItems: [key itemSize] * [key count]
		  fromCArray: [key cArray]];

	@try {
403
404
405
406
407
408
409
410

411
412
413
414
415
416
417
418
419
420
421
422
423

424
425
426
427
428
429
430
403
404
405
406
407
408
409

410
411
412
413
414
415
416
417
418
419
420
421
422

423
424
425
426
427
428
429
430







-
+












-
+







		[k addNItems: blockSize
		  fromCArray: kI];
		[k addNItems: [data itemSize] * [data count]
		  fromCArray: [data cArray]];

		hash = [[[hashType alloc] init] autorelease];
		[hash updateWithBuffer: [k cArray]
				ofSize: [k count]];
				length: [k count]];
		k = [OFDataArray dataArrayWithItemSize: 1];
		[k addNItems: blockSize
		  fromCArray: kO];
		[k addNItems: [hashType digestSize]
		   fromCArray: [hash digest]];
	} @finally {
		[self freeMemory: kI];
		[self freeMemory: kO];
	}

	hash = [[[hashType alloc] init] autorelease];
	[hash updateWithBuffer: [k cArray]
			ofSize: [k count]];
			length: [k count]];

	[hash retain];
	[pool release];

	return [hash digest];
}