--- /dev/null
+/*
+ * Copyright (c) 2010, 2011, Jonathan Schleifer <js@webkeks.org>
+ * Copyright (c) 2011, Florian Zeitz <florob@babelmonkeys.de>
+ *
+ * https://webkeks.org/hg/objxmpp/
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+
+#import <ObjFW/ObjFW.h>
+#import <ObjXMPP/ObjXMPP.h>
+
+#import "PEPThread.h"
+
+#define NS_DISCO_INFO @"http://jabber.org/protocol/disco#info"
+
+@interface AppDelegate: OFObject
+#ifdef OF_HAVE_OPTIONAL_PROTOCOLS
+ <OFApplicationDelegate, XMPPConnectionDelegate>
+#endif
+
+OFString *discoID;
+PEPThread *pepper;
+@end
+
+OF_APPLICATION_DELEGATE(AppDelegate)
+
+@implementation AppDelegate
+- (void)applicationDidFinishLaunching
+{
+ XMPPConnection *conn;
+ OFArray *arguments = [OFApplication arguments];
+
+ conn = [[XMPPConnection alloc] init];
+ [conn setDelegate: self];
+
+ if ([arguments count] != 3) {
+ of_log(@"Invalid count of command line arguments!");
+ [OFApplication terminateWithStatus: 1];
+ }
+
+ [conn setDomain: [arguments objectAtIndex: 0]];
+ [conn setUsername: [arguments objectAtIndex: 1]];
+ [conn setPassword: [arguments objectAtIndex: 2]];
+ [conn setResource: @"ObjXMPP"];
+
+ @try {
+ [conn connect];
+ [conn handleConnection];
+ } @catch (id e) {
+ of_log(@"%@", e);
+ }
+}
+
+- (void)connectionWasAuthenticated: (XMPPConnection*)conn
+{
+ of_log(@"Auth successful");
+}
+
+- (void)connection: (XMPPConnection*)conn
+ wasBoundToJID: (XMPPJID*)jid
+{
+ XMPPPresence *pres;
+ XMPPIQ *disco;
+
+ of_log(@"Bound to JID: %@", [jid fullJID]);
+
+ pres = [XMPPPresence presence];
+ [pres addPriority: 0];
+ [pres addStatus: @"Hello I'm MPDbot!"];
+ [conn sendStanza: pres];
+
+ discoID = [[conn generateStanzaID] retain];
+ disco = [XMPPIQ IQWithType: @"get"
+ ID: discoID];
+ disco.to = [XMPPJID JIDWithString: [[conn JID] bareJID]];
+ [disco addChild: [OFXMLElement
+ elementWithName: @"query"
+ namespace: NS_DISCO_INFO]];
+
+ [conn sendStanza: disco];
+}
+
+- (BOOL)connection: (XMPPConnection*)conn
+ didReceiveIQ: (XMPPIQ*)iq
+{
+ OFXMLElement *query = [iq elementForName: @"query"
+ namespace: NS_DISCO_INFO];
+ if ([[iq ID] isEqual: discoID]) {
+ for (OFXMLElement *identity
+ in [query elementsForName: @"identity"
+ namespace: NS_DISCO_INFO]) {
+ if ([[[identity attributeForName: @"category"]
+ stringValue] isEqual: @"pubsub"] &&
+ [[[identity attributeForName: @"type"] stringValue]
+ isEqual: @"pep"]) {
+ pepper = [[PEPThread alloc]
+ initWithObject: conn];
+ [pepper start];
+ return YES;
+ }
+ }
+ }
+
+ return NO;
+}
+
+- (void)connection: (XMPPConnection*)conn
+ didReceiveMessage: (XMPPMessage*)msg
+{
+ of_log(@"Message: %@", msg);
+}
+
+- (void)connection: (XMPPConnection*)conn
+ didReceivePresence: (XMPPPresence*)pres
+{
+ of_log(@"Presence: %@", pres);
+}
+
+- (void)connectionWasClosed: (XMPPConnection*)conn
+{
+ of_log(@"Connection was closed!");
+}
+@end