From c5bb67eab6f97ae0f5f7e673ff0ba9b1111191f4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 9 Oct 2010 11:52:51 +0200
Subject: Added EchoBot walkthrough example.


diff --git a/BuildTools/Copyrighter.py b/BuildTools/Copyrighter.py
index 7f4d9f9..b83c3d6 100755
--- a/BuildTools/Copyrighter.py
+++ b/BuildTools/Copyrighter.py
@@ -136,7 +136,7 @@ elif sys.argv[1] == "check-all-copyrights" :
   for (path, dirs, files) in os.walk(".") :
     if "3rdParty" in path or ".sconf" in path or "Swift.app" in path :
       continue
-    for filename in [os.path.join(path, file) for file in files if (file.endswith(".cpp") or file.endswith(".h")) and not "ui_" in file and not "moc_" in file and not "qrc_" in file and not "BuildVersion.h" in file] :
+    for filename in [os.path.join(path, file) for file in files if (file.endswith(".cpp") or file.endswith(".h")) and not "ui_" in file and not "moc_" in file and not "qrc_" in file and not "BuildVersion.h" in file and not "Swiften.h" in file ] :
       ok &= check_copyright(filename) 
   if not ok :
     sys.exit(-1)
diff --git a/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/.gitignore b/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/.gitignore
new file mode 100644
index 0000000..28275ad
--- /dev/null
+++ b/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/.gitignore
@@ -0,0 +1,2 @@
+EchoBot?
+*.cpp.xml
diff --git a/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/EchoBot1.cpp b/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/EchoBot1.cpp
new file mode 100644
index 0000000..584ec9d
--- /dev/null
+++ b/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/EchoBot1.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/Swiften.h"
+
+using namespace Swift;
+
+int main(int, char*) {
+	SimpleEventLoop eventLoop;
+
+	Client client(JID("echobot@wonderland.lit"), "mypass");
+	client.connect();
+
+	eventLoop.run();
+
+	return 0;
+}
diff --git a/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/EchoBot2.cpp b/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/EchoBot2.cpp
new file mode 100644
index 0000000..a03c3db
--- /dev/null
+++ b/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/EchoBot2.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <iostream>
+#include <boost/bind.hpp>
+
+#include "Swiften/Swiften.h"
+
+using namespace Swift;
+using namespace boost;
+
+Client* client;
+
+void handleConnected() {
+	std::cout << "Connected" << std::endl;
+}
+
+void handleMessageReceived(Message::ref message) {
+	// Echo back the incoming message
+	message->setTo(message->getFrom());
+	message->setFrom(JID());
+	client->sendMessage(message);
+}
+
+int main(int, char*) {
+	SimpleEventLoop eventLoop;
+
+	client = new Client(JID("echobot@wonderland.lit"), "mypass");
+	client->onConnected.connect(&handleConnected);
+	client->onMessageReceived.connect(bind(&handleMessageReceived, _1));
+	client->connect();
+
+	eventLoop.run();
+
+	delete client;
+	return 0;
+}
diff --git a/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/EchoBot3.cpp b/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/EchoBot3.cpp
new file mode 100644
index 0000000..a9c611f
--- /dev/null
+++ b/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/EchoBot3.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <iostream>
+#include <boost/bind.hpp>
+
+#include "Swiften/Swiften.h"
+
+using namespace Swift;
+using namespace boost;
+
+class EchoBot {
+	public:
+		EchoBot() {
+			client = new Client(JID("echobot@wonderland.lit"), "mypass");
+			client->onConnected.connect(bind(&EchoBot::handleConnected, this));
+			client->onMessageReceived.connect(
+					bind(&EchoBot::handleMessageReceived, this, _1));
+			tracer = new ClientXMLTracer(client);
+			client->connect();
+		}
+
+		~EchoBot() {
+			delete tracer;
+			delete client;
+		}
+	
+	private:
+		void handleConnected() {
+			std::cout << "Connected" << std::endl;
+		}
+
+		void handleMessageReceived(Message::ref message) {
+			// Echo back the incoming message
+			message->setTo(message->getFrom());
+			message->setFrom(JID());
+			client->sendMessage(message);
+		}
+	
+	private:
+		Client* client;
+		ClientXMLTracer* tracer;
+};
+
+int main(int, char*) {
+	SimpleEventLoop eventLoop;
+	EchoBot bot;
+	eventLoop.run();
+	return 0;
+}
diff --git a/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/EchoBot4.cpp b/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/EchoBot4.cpp
new file mode 100644
index 0000000..b01fecd
--- /dev/null
+++ b/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/EchoBot4.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+//...
+#include <iostream>
+#include <boost/bind.hpp>
+
+#include "Swiften/Swiften.h"
+
+using namespace Swift;
+using namespace boost;
+//...
+class EchoBot {
+	public:
+		EchoBot() {
+			//...
+			client = new Client(JID("echobot@wonderland.lit"), "mypass");
+			client->onConnected.connect(bind(&EchoBot::handleConnected, this));
+			client->onMessageReceived.connect(
+					bind(&EchoBot::handleMessageReceived, this, _1));
+			//...
+			client->onPresenceReceived.connect(
+					bind(&EchoBot::handlePresenceReceived, this, _1));
+			//...
+			tracer = new ClientXMLTracer(client);
+			client->connect();
+			//...
+		}
+
+		//...
+		~EchoBot() {
+			delete tracer;
+			delete client;
+		}
+	
+	private:
+		//...
+		void handlePresenceReceived(Presence::ref presence) {
+			// Automatically approve subscription requests
+			if (presence->getType() == Presence::Subscribe) {
+				Presence::ref response = Presence::create();
+				response->setTo(presence->getFrom());
+				response->setType(Presence::Subscribed);
+				client->sendPresence(response);
+			}
+		}
+
+		void handleConnected() {
+			// Request the roster
+			GetRosterRequest::ref rosterRequest = 
+					GetRosterRequest::create(client->getIQRouter());
+			rosterRequest->onResponse.connect(
+					bind(&EchoBot::handleRosterReceived, this, _2));
+			rosterRequest->send();
+		}
+
+		void handleRosterReceived(const optional<ErrorPayload>& error) {
+			if (error) {
+				std::cerr << "Error receiving roster. Continuing anyway.";
+			}
+			// Send initial available presence
+			client->sendPresence(Presence::create("Send me a message"));
+		}
+		//...
+		
+		void handleMessageReceived(Message::ref message) {
+			// Echo back the incoming message
+			message->setTo(message->getFrom());
+			message->setFrom(JID());
+			client->sendMessage(message);
+		}
+
+	private:
+		Client* client;
+		ClientXMLTracer* tracer;
+		//...
+};
+//...
+
+int main(int, char*) {
+	SimpleEventLoop eventLoop;
+	EchoBot bot;
+	eventLoop.run();
+	return 0;
+}
+//...
diff --git a/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/EchoBot5.cpp b/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/EchoBot5.cpp
new file mode 100644
index 0000000..72d0eb1
--- /dev/null
+++ b/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/EchoBot5.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+//...
+#include <iostream>
+#include <boost/bind.hpp>
+
+#include "Swiften/Swiften.h"
+
+using namespace Swift;
+using namespace boost;
+//...
+class EchoBot {
+	public:
+		EchoBot() {
+			//...
+			client = new Client(JID("echobot@wonderland.lit"), "mypass");
+			client->onConnected.connect(bind(&EchoBot::handleConnected, this));
+			client->onMessageReceived.connect(
+					bind(&EchoBot::handleMessageReceived, this, _1));
+			client->onPresenceReceived.connect(
+					bind(&EchoBot::handlePresenceReceived, this, _1));
+			tracer = new ClientXMLTracer(client);
+			//...
+			softwareVersionResponder = new SoftwareVersionResponder(
+					"EchoBot", "1.0", client->getIQRouter());
+			//...
+			client->connect();
+			//...
+		}
+
+		~EchoBot() {
+			delete softwareVersionResponder;
+			//...
+			delete tracer;
+			delete client;
+			//...
+		}
+		//...
+	
+	private:
+		void handlePresenceReceived(Presence::ref presence) {
+			// Automatically approve subscription requests
+			if (presence->getType() == Presence::Subscribe) {
+				Presence::ref response = Presence::create();
+				response->setTo(presence->getFrom());
+				response->setType(Presence::Subscribed);
+				client->sendPresence(response);
+			}
+		}
+
+		void handleConnected() {
+			// Request the roster
+			GetRosterRequest::ref rosterRequest = 
+					GetRosterRequest::create(client->getIQRouter());
+			rosterRequest->onResponse.connect(
+					bind(&EchoBot::handleRosterReceived, this, _2));
+			rosterRequest->send();
+		}
+
+		void handleRosterReceived(const optional<ErrorPayload>& error) {
+			if (error) {
+				std::cerr << "Error receiving roster. Continuing anyway.";
+			}
+			// Send initial available presence
+			client->sendPresence(Presence::create("Send me a message"));
+		}
+		
+		void handleMessageReceived(Message::ref message) {
+			// Echo back the incoming message
+			message->setTo(message->getFrom());
+			message->setFrom(JID());
+			client->sendMessage(message);
+		}
+
+		//...
+	private:
+		//...
+		Client* client;
+		ClientXMLTracer* tracer;
+		//...
+		SoftwareVersionResponder* softwareVersionResponder;
+};
+//...
+
+int main(int, char*) {
+	SimpleEventLoop eventLoop;
+	EchoBot bot;
+	eventLoop.run();
+	return 0;
+}
+//...
diff --git a/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/SConscript b/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/SConscript
new file mode 100644
index 0000000..ceead6b
--- /dev/null
+++ b/Documentation/SwiftenDevelopersGuide/Examples/EchoBot/SConscript
@@ -0,0 +1,15 @@
+Import("env")
+
+example_env = env.Clone()
+example_env.MergeFlags(example_env["SWIFTEN_FLAGS"])
+example_env.MergeFlags(example_env["LIBIDN_FLAGS"])
+example_env.MergeFlags(example_env["BOOST_FLAGS"])
+example_env.MergeFlags(example_env.get("SQLITE_FLAGS", {}))
+example_env.MergeFlags(example_env["ZLIB_FLAGS"])
+example_env.MergeFlags(example_env["OPENSSL_FLAGS"])
+example_env.MergeFlags(example_env.get("LIBXML_FLAGS", ""))
+example_env.MergeFlags(example_env.get("EXPAT_FLAGS", ""))
+example_env.MergeFlags(example_env["PLATFORM_FLAGS"])
+
+for i in range(1,6) :
+	example_env.Program("EchoBot" + str(i), ["EchoBot" + str(i) + ".cpp"])
diff --git a/Documentation/SwiftenDevelopersGuide/Examples/SConscript b/Documentation/SwiftenDevelopersGuide/Examples/SConscript
new file mode 100644
index 0000000..1284b34
--- /dev/null
+++ b/Documentation/SwiftenDevelopersGuide/Examples/SConscript
@@ -0,0 +1 @@
+SConscript(dirs = ["EchoBot"])
diff --git a/Documentation/SwiftenDevelopersGuide/SConscript b/Documentation/SwiftenDevelopersGuide/SConscript
index 145663f..fb08a8f 100644
--- a/Documentation/SwiftenDevelopersGuide/SConscript
+++ b/Documentation/SwiftenDevelopersGuide/SConscript
@@ -2,4 +2,89 @@ Import("env")
 
 env.Tool("DocBook", toolpath = ["#/BuildTools/DocBook/SCons"])
 
+################################################################################
+# Code generation helper
+################################################################################
+
+import sys, re, os.path
+
+def generateDocBookCode(env, target, source) :
+	# Strips empty lines from the beginning & end of a program
+	def stripEmptyLines(program) :
+		programLines = program.split('\n')
+		newProgramLines = []
+		inProgram = False
+		for line in programLines :
+			if not re.match("^\s*$", line) or inProgram :
+				inProgram = True
+				newProgramLines.append(line)
+		return '\n'.join(newProgramLines).rstrip()
+
+	def createCallouts(program, calloutPrefix) :
+		newProgramLines = []
+		calloutLines = []
+		nextID = 0
+		for line in program.split("\n") :
+			# FIXME: Takes the largest match
+			m = re.match(".*\/* \(\*\) (.*) \*/.*", line)
+			if m :
+				cobID = "cob-" + calloutPrefix + "-" + str(nextID)
+				coID = "co-" + calloutPrefix + "-" + str(nextID)
+				nextID += 1
+				line = re.sub("/\*.*\*/", "]]><co id=\"%(cobID)s\" linkends=\"%(coID)s\"/><![CDATA[" % {"cobID" : cobID, "coID" : coID}, line)
+				calloutLines.append("<callout arearefs=\"%(cobID)s\" id=\"%(coID)s\"><para>%(text)s</para></callout>" % {"cobID": cobID, "coID": coID, "text": m.group(1)})
+			newProgramLines.append(line)
+		callouts = "<calloutlist>" + "\n".join(calloutLines) + "</calloutlist>" if len(calloutLines) > 0 else ""
+		return ("\n".join(newProgramLines), callouts)
+			
+	# Parse program
+	filename = source[0].abspath
+	filenameBase = os.path.basename(filename).replace(".cpp", "")
+	inputfile = open(filename)
+	program = ""
+	programs = {}
+	programName = ""
+	inEllipsis = False
+	for line in inputfile.readlines() :
+		if inEllipsis :
+			if "//..." in line :
+				inEllipsis = False
+		else :
+			if line.startswith("/*") or line.startswith(" *") :
+				continue
+			if "//..." in line :
+				inEllipsis = True
+				line = line.replace("//...", "]]>&#x2026;<![CDATA[")
+			else :
+				m = re.match("^/// (.*)", line)
+				if m :
+					if programName :
+						programs[programName] = program
+					program = ""
+					programName = m.group(1).strip().replace(" ", "")
+					continue
+			line = re.sub("\t", "  ", line)
+			program += line
+	programs[programName] = program
+	inputfile.close()
+
+	for programName, program in programs.items() :
+		program = stripEmptyLines(program)
+		(program, callouts) = createCallouts(program, filenameBase + "-" + programName)
+
+		document = "<foo><programlisting><![CDATA[" + program + "]]></programlisting>" + callouts + "</foo>"
+
+		# Generate code
+		output = open(target[0].abspath, 'w')
+		output.write(document)
+		output.close()
+
+################################################################################
+
 env.DocBook("Swiften Developers Guide.xml")
+
+for i in range(1, 6) :
+	source = "Examples/EchoBot/EchoBot" + str(i) + ".cpp"
+	env.Command(source + ".xml", source, Action(generateDocBookCode, cmdstr = "$GENCOMSTR"))
+
+SConscript(dirs = ["Examples"])
diff --git a/Documentation/SwiftenDevelopersGuide/Swiften Developers Guide.xml b/Documentation/SwiftenDevelopersGuide/Swiften Developers Guide.xml
index e0a63ae..1df3781 100644
--- a/Documentation/SwiftenDevelopersGuide/Swiften Developers Guide.xml	
+++ b/Documentation/SwiftenDevelopersGuide/Swiften Developers Guide.xml	
@@ -6,44 +6,322 @@
 
   <chapter>
     <title>Introduction</title>
+    <section>
+      <title>Prerequisites</title>
+      <para>
+        We assume that the reader is familiar with the basics of the
+        XMPP protocol. For an overview of the XMPP protocol and its
+        workings, see
+        <citetitle>XMPP: The Definitive Guide</citetitle> 
+        <citation><biblioref linkend="XMPP-TDG"/></citation>
+      </para>
+    </section>
 
-    <para>
-      This is an introduction
-    </para>
-
-    <sect1>
-      <title>Section</title>
-
+    <section>
+      <title>Boost</title>
       <para>
-        This is a section
+        Swiften makes heavy use of <emphasis>Boost</emphasis> (<ulink url="http://boost.org"><uri>http://boost.org</uri></ulink>) libraries, including <emphasis>Signal</emphasis>,
+        <emphasis>Bind</emphasis>, <emphasis>Optional</emphasis>, and 
+        <emphasis>Smart Pointers</emphasis>. We
+        introduce the basic usage of these libraries in our API throughout
+        this manual. For detailed documentation, we refer to the Boost
+        website.
       </para>
-    </sect1>
+    </section>
   </chapter>
 
   <chapter>
     <title>Tutorial: Writing an Echo Bot</title>
     
     <para>
-      In this chapter, we build a simple echo bot, illustrating how
-      to use and extend Swiften for your own purposes.
+      In this chapter, we guide you through the Swiften API by building an
+      example XMPP application: an EchoBot. This example program, taken from
+      <citetitle>XMPP: The Definitive Guide</citetitle> 
+      <citation><biblioref linkend="XMPP-TDG"/></citation>, connects to
+      an XMPP server, logs in, and responds to all incoming messages with
+      the exact same message. We build up our application using Swiften's
+      basic building blocks for XMPP development, to help get a good
+      understanding of how Swiften fundamental classes work and can be
+      extended. In the last stage of this example, we 
+      introduce some of Swiften's convenience classes for standard
+      XMPP tasks such as roster management.
     </para>
 
     <sect1>
-      <title>Setting up the build environment</title>
+      <title>Connecting to a server: Clients &amp; event loops</title>
+      <para>
+        As a first step, we create an application that connects to a server.
+        The code can be seen in <xref linkend="Example-EchoBot1"/>.
+      </para>
+      <example id="Example-EchoBot1">
+        <title>Connecting to a server</title>
+        <include xmlns="http://www.w3.org/2001/XInclude" href="Examples/EchoBot/EchoBot1.cpp.xml" xpointer="xpointer(//programlisting|//calloutlist)"/>
+      </example>
+      <para>
+        The first thing this program does is construct an 
+        <emphasis>Event Loop</emphasis>. An event loop is a seemingly infinite
+        loop that waits for external events (e.g. incoming network packets,
+        timers being activated, input happening) to happen; when such an event 
+        comes in, it notifies interested parties of this event, and then 
+        continues listening for the next event. Since many application 
+        frameworks (such as Qt, GLib, Cocoa) use their own event loop,
+        Swiften comes prepackaged with classes that integrate with these
+        event loops. These classes can be found in 
+        <literal>Swiften/EventLoop</literal>. 
+        In this example, however, we don't use such a framework,
+        so we use Swiften's own <literal>SimpleEventLoop</literal>. This
+        class is used by simply instantiating it at the beginning of the
+        application, and calling <literal>run()</literal> after everything
+        is set up, which will go into an infinite loop. Apart from constructing
+        and (if necessary) starting the event loop, you will probably have
+        no other contact with it in the rest of the application.
+      </para>
+
+      <para>
+        Swiften's central class for implementing XMPP applications is
+        <literal>Client</literal>. This class handles all the interaction
+        with the XMPP network. After constructing it with the JID and
+        password with which we want to connect, we call 
+        <literal>connect()</literal> to instruct the client to connect to 
+        the XMPP server with the given credentials. Note that this call returns
+        immediately; it is only when starting the event loop that network
+        the actual connection process will start.
+      </para>
+    </sect1>
+
+    <sect1>
+      <title>Building EchoBot</title>
+      <remark>TODO: Explain linking against the static library.</remark>
+    </sect1>
+
+    <sect1>
+      <title>Reacting to events: Signals, Slots &amp; Bind</title>
+      <para>
+        Up to this point, our client doesn't do anything useful. In this
+        section, we make the client react to XMPP events. The code can
+        be seen in <xref linkend="Example-EchoBot2"/>.
+      </para>
+      <example id="Example-EchoBot2">
+        <title>Reacting to events: Notify whenever the client is connected to the network, and echo back incoming messages</title>
+        <include xmlns="http://www.w3.org/2001/XInclude" href="Examples/EchoBot/EchoBot2.cpp.xml" xpointer="xpointer(//programlisting|//calloutlist)"/>
+      </example>
+
+      <para>
+        A first thing we want to do is print out a message when the client
+        is connected to the server. Swiften uses the 
+        <emphasis>signal/slot</emphasis> paradigm for notifying interested
+        parties of events. A <emphasis>signal</emphasis> is an object 
+        representing a type of event. For example, <literal>Client</literal>
+        has an <literal>onConnected</literal> signal for notifying whenever
+        the client is connected to the network. If you are interested in 
+        a particular signal, you connect a <emphasis>slot</emphasis> to the 
+        signal. A slot represents a callback that will be called whenever a 
+        signal is emitted. Since we want to print out a message whenever
+        we're connected to the network, we connect to the client's signal,
+        and tell it to call <literal>handleConnected</literal> (which prints
+        out a message):
+        <programlisting>client->onConnected.connect(&amp;handleConnected)</programlisting>
+      </para>
+
+      <para>
+        Another event we're interested in is whenever a message comes in. 
+        For this purpose, <literal>Client</literal> provides a signal called
+        <literal>onMessageReceived</literal>. The major difference with the
+        previous <literal>onConnected</literal> signal is that this signal
+        also can provide extra information to the callback: the actual
+        message received. A signal can provide this extra information through
+        one or more arguments, which will be passed to the slot's parameters.
+        To be able to handle parameters to slots, there needs to be a more 
+        general representation of callbacks than just function pointers. This
+        is where Boost's <literal>bind</literal> comes in: <literal>bind</literal> 
+        provides a way to construct <emphasis>functors</emphasis> (callbacks, slots, &hellip;), by combining function pointers and parameter values. 
+        For example, to connect the signal to our slot, we call:
+        <programlisting>client->onMessageReceived.connect(bind(&amp;handleMessageReceived, _1))</programlisting>
+        This is essentially saying: when the 
+        <literal>onMessageReceived</literal> signal is emitted, call
+        <literal>handleMessageReceived</literal>, and pass it the first
+        parameter provided by the slot (which, in this case, is the actual
+        message received).
+      </para>
+      
       <para>
+        The implementation of <literal>handleMessageReceived</literal> should be straightforward: put the <emphasis>To</emphasis> address in place of the <emphasis>From</emphasis> address, and send the message to the server. One
+        thing to note is that <literal>Message::ref</literal> represents a
+        <emphasis>shared pointer</emphasis> to a <literal>Message</literal>
+        stanza. Shared pointers behave the same as regular pointers, except that,
+        when the last copy of the pointer goes away, the object it points to is
+        deleted as well. <literal>Message::ref</literal> is in fact a
+        typedef for <literal>boost::shared_ptr&lt;Message&gt;</literal>. 
+        Although Swiften tends to prefer the use of the <literal>::ref</literal>
+        notation, you will see both forms used intermixed.
+      </para>
+
+      <para>
+        Before moving on to the next step, we are going to rearrange our
+        code a bit, to make it a bit cleaner. Instead of using global 
+        variables, we are going to create an <literal>EchoBot</literal>
+        class with the current code in it. The resulting code can be found
+        in <xref linkend="Example-EchoBot3"/>.
+      </para>
+      <example id="Example-EchoBot3">
+        <title>Creating an EchoBot class</title>
+        <include xmlns="http://www.w3.org/2001/XInclude" href="Examples/EchoBot/EchoBot3.cpp.xml" xpointer="xpointer(//programlisting|//calloutlist)"/>
+      </example>
+      <para>
+        The important thing to consider in this step are the changes to the signal
+        connections. Since we are now passing member variables of a class
+        to the signal, we need to use <literal>bind</literal> to pass
+        in the actual object on which this member variable is called as
+        the first parameter.
+      </para>
+      <para>
+        The only thing we added to this version is the 
+        <literal>ClientXMLTracer</literal>. This class will dump all
+        incoming and outgoing XMPP messages to the console, which can be handy
+        for debugging our bot.
       </para>
     </sect1>
 
     <sect1>
-      <title>Connecting to the network</title>
+      <title>Presence Management: Requests</title>
       <para>
+        The current version of our EchoBot does what it is supposed to do:
+        it answers all incoming messages. However, although users can add
+        the bot to their contact list, they will not see when it is 
+        online, since the bot doesn't do any presence handling yet. In 
+        this section, we explain the different steps involved in adding
+        presence management, resulting in the code in 
+        <xref linkend="Example-EchoBot4"/>.
+      </para>
+      <example id="Example-EchoBot4">
+        <title>Adding presence management: Requesting the initial roster, and auto-approving incoming subscription requests.</title>
+        <include xmlns="http://www.w3.org/2001/XInclude" href="Examples/EchoBot/EchoBot4.cpp.xml" xpointer="xpointer(//programlisting|//calloutlist)"/>
+      </example>
+      <para>
+        First of all, our bot needs to listen to incoming subscription requests
+        from users who want to add it to their roster, and automatically 
+        approve them. This is done by connecting to 
+        the <literal>onPresenceReceived</literal> signal, checking whether
+        the incoming presence is a subscription request, and if so, 
+        respond to it with an approval (in <literal>handlePresenceReceived</literal>).
+      </para>
+
+      <para>
+        The first version of the XMPP protocol states that a client will not 
+        get any presence
+        subscriptions until it requests the roster. To make sure we handle
+        this, we want to make sure our bot requests the roster at login.
+        After getting the <literal>onConnected</literal> signal, we 
+        therefore send a 
+        <emphasis>request</emphasis> to retrieve the roster. Swiften's
+        <literal>Request</literal> classes correspond to XMPP IQ Get or
+        Set actions. Swiften provides a set of built-in request classes for
+        the most common tasks in <literal>Swiften/Queries/Requests</literal>,
+        and can be easily extended to use add your own (see <xref linkend="Section-Extending"/>). Requests have an <literal>onResponse</literal> signal,
+        which is emitted when a response comes in. This signal has 2 parameters:
+        the actual response data (the <emphasis>Payload</emphasis>), and an
+        optional error payload in case there was an error executing the
+        request. To use a <literal>Request</literal> class, you construct
+        it with the correct parameters, connect to the 
+        <literal>onResponse</literal> signal, and then send the request by
+        calling <literal>send()</literal> on it. In this case, we're not
+        interested in the actual payload of the response (passed as the
+        first parameter), so we pass it a slot with only the second parameter
+        (the error payload). When we get the roster back, we send initial
+        presence to all our subscribers, announcing them we're online.
       </para>
     </sect1>
 
     <sect1>
-      <title>T</title>
+      <title>Publishing version information: Responders</title>
       <para>
+        Most XMPP clients have support for querying software version information
+        of a client through 
+        <citation><biblioref linkend="XEP-0092"/></citation>. These clients
+        send out an IQ-Get request to an entity, which responds with the
+        requested information. We would like our bot to listen to these 
+        requests, and respond with the correct information. Swiften uses
+        <literal>Responder</literal> classes for the purpose of responding
+        to IQ requests, and are therefore the dual of the 
+        <literal>Request</literal> clients discussed in the previous section.
       </para>
+
+      <example id="Example-EchoBot5">
+        <title>Adding presence management: Requesting the initial roster, and auto-approving incoming subscription requests.</title>
+        <include xmlns="http://www.w3.org/2001/XInclude" href="Examples/EchoBot/EchoBot5.cpp.xml" xpointer="xpointer(//programlisting|//calloutlist)"/>
+      </example>
+
+      <para>
+        Using <literal>SoftwareVersionResponder</literal> is pretty 
+        straightforward, as can be seen in <xref linkend="Example-EchoBot5"/>: 
+        simply construct the responder with the correct
+        parameters, and it will automatically respond to the incoming 
+        requests. Other <literal>Responder</literal> classes may provide
+        signals to notify of incoming requests, or may have some other
+        behavior. For a detailed explanation of responders, see 
+        <xref linkend="Section-CustomQueries"/>.
+      </para>
+    </sect1>
+
+    <sect1 id="Section-Extending">
+      <title>Extending Swiften with new payloads: Payloads, Parsers, and Serializers</title>
+      <para>
+        Swiften uses abstract datastructures for all the data that is received
+        and sent over the XMPP network. The declaration of these datastructures
+        can all be found in <literal>Swiften/Elements</literal>. For 
+        representing the XMPP stanzas, Swiften uses the 
+        <literal>Message</literal>, <literal>Presence</literal>, and 
+        <literal>IQ</literal> classes. Each stanza can have an arbitrary
+        amount of child <emphasis>payloads</emphasis>, represented by the
+        <literal>Payload</literal> class. A payload typically corresponds
+        to a (namespaced) child XML element of a stanza; for example, the
+        <literal>&lt;query xmlns="jabber:iq:roster"/&gt;</literal> 
+        element used for managing the roster is represented as a
+        <literal>RosterPayload</literal>.
+      </para>
+
+      <remark>TODO</remark>
+    </sect1>
+
+    <sect1 id="Section-CustomQueries">
+      <title>Extending Swiften with new queries and responders</title>
+      <remark>TODO</remark>
+    </sect1>
+
+    <sect1>
+      <title>Using Swiften's convenience classes</title>
+      <remark>TODO</remark>
     </sect1>
   </chapter>
+
+  <bibliography>
+    <title>Bibliography</title>
+
+    <biblioentry id="XMPP-TDG">
+      <abbrev>XMPP-TDG</abbrev>
+      <title><ulink url="http://oreilly.com/catalog/9780596157197/">XMPP: The
+      Definitive Guide</ulink></title>
+      <author>
+        <firstname>Peter</firstname>
+        <surname>Saint-Andre</surname>
+      </author>
+      <author>
+        <firstname>Kevin</firstname>
+        <surname>Smith</surname>
+      </author>
+      <author>
+        <firstname>Remko</firstname>
+        <surname>Tronçon</surname>
+      </author>
+    </biblioentry>
+
+    <biblioentry id='XEP-0092'>
+      <abbrev>XEP-0092</abbrev>
+      <title><ulink url='http://www.xmpp.org/extensions/xep-0092.html'>Software Version</ulink></title>
+      <author>
+        <firstname>Peter</firstname>
+        <surname>Saint-Andre</surname>
+      </author>
+    </biblioentry>
+  </bibliography>
 </book>
diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp
index 9619722..de74150 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.cpp
+++ b/Swift/Controllers/Chat/ChatControllerBase.cpp
@@ -62,7 +62,7 @@ void ChatControllerBase::setAvailableServerFeatures(boost::shared_ptr<DiscoInfo>
 	if (iqRouter_->isAvailable() && info->hasFeature(DiscoInfo::SecurityLabels)) {
 		//chatWindow_->setSecurityLabelsEnabled(true);
 		//chatWindow_->setSecurityLabelsError();
-		boost::shared_ptr<GetSecurityLabelsCatalogRequest> request(new GetSecurityLabelsCatalogRequest(JID(toJID_.toBare()), iqRouter_));
+		GetSecurityLabelsCatalogRequest::ref request = GetSecurityLabelsCatalogRequest::create(JID(toJID_.toBare()), iqRouter_);
 		request->onResponse.connect(boost::bind(&ChatControllerBase::handleSecurityLabelsCatalogResponse, this, _1, _2));
 		request->send();
 		//labelsEnabled_ = true;
diff --git a/Swift/Controllers/Chat/MUCSearchController.cpp b/Swift/Controllers/Chat/MUCSearchController.cpp
index 304de85..dc81031 100644
--- a/Swift/Controllers/Chat/MUCSearchController.cpp
+++ b/Swift/Controllers/Chat/MUCSearchController.cpp
@@ -63,7 +63,7 @@ void MUCSearchController::handleAddService(const JID& jid, bool userTriggered) {
 		//Set Window to say error this isn't valid
 		return;
 	}
-	boost::shared_ptr<GetDiscoInfoRequest> discoInfoRequest(new GetDiscoInfoRequest(jid, iqRouter_));
+	GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(jid, iqRouter_);
 	discoInfoRequest->onResponse.connect(boost::bind(&MUCSearchController::handleDiscoInfoResponse, this, _1, _2, jid));
 	discoInfoRequest->send();
 }
@@ -79,7 +79,7 @@ void MUCSearchController::handleDiscoInfoResponse(boost::shared_ptr<DiscoInfo> i
 		handleDiscoError(jid, error.get());
 		return;
 	}
-	boost::shared_ptr<GetDiscoItemsRequest> discoItemsRequest(new GetDiscoItemsRequest(jid, iqRouter_));
+	GetDiscoItemsRequest::ref discoItemsRequest = GetDiscoItemsRequest::create(jid, iqRouter_);
 	bool mucService = false;
 	bool couldContainServices = false;
 	String name;
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index 06b231c..ddf9848 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -306,7 +306,7 @@ void MainController::handleConnected() {
 	
 	xmppRosterController_->requestRoster();
 
-	boost::shared_ptr<GetDiscoInfoRequest> discoInfoRequest(new GetDiscoInfoRequest(JID(), client_->getIQRouter()));
+	GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(JID(), client_->getIQRouter());
 	discoInfoRequest->onResponse.connect(boost::bind(&MainController::handleServerDiscoInfoResponse, this, _1, _2));
 	discoInfoRequest->send();
 
diff --git a/Swift/Controllers/RosterController.cpp b/Swift/Controllers/RosterController.cpp
index 15ed6a4..e79fad1 100644
--- a/Swift/Controllers/RosterController.cpp
+++ b/Swift/Controllers/RosterController.cpp
@@ -162,7 +162,7 @@ void RosterController::handleUIEvent(boost::shared_ptr<UIEvent> event) {
 		item.setJID(addContactEvent->getJID());
 		boost::shared_ptr<RosterPayload> roster(new RosterPayload());
 		roster->addItem(item);
-		boost::shared_ptr<SetRosterRequest> request(new SetRosterRequest(roster, iqRouter_));
+		SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_);
 		request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
 		request->send();
 		presenceSender_->requestSubscription(addContactEvent->getJID());
@@ -173,7 +173,7 @@ void RosterController::handleUIEvent(boost::shared_ptr<UIEvent> event) {
 		RosterItemPayload item(removeEvent->getJID(), "", RosterItemPayload::Remove);
 		boost::shared_ptr<RosterPayload> roster(new RosterPayload());
 		roster->addItem(item);
-		boost::shared_ptr<SetRosterRequest> request(new SetRosterRequest(roster, iqRouter_));
+		SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_);
 		request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
 		request->send();
 
@@ -186,7 +186,7 @@ void RosterController::handleUIEvent(boost::shared_ptr<UIEvent> event) {
 		item.setGroups(xmppRoster_->getGroupsForJID(contact));
 		boost::shared_ptr<RosterPayload> roster(new RosterPayload());
 		roster->addItem(item);
-		boost::shared_ptr<SetRosterRequest> request(new SetRosterRequest(roster, iqRouter_));
+		SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_);
 		request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
 		request->send();
 		return;
@@ -210,7 +210,7 @@ void RosterController::handleUIEvent(boost::shared_ptr<UIEvent> event) {
 		item.setGroups(newGroups);
 		boost::shared_ptr<RosterPayload> roster(new RosterPayload());
 		roster->addItem(item);
-		boost::shared_ptr<SetRosterRequest> request(new SetRosterRequest(roster, iqRouter_));
+		SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_);
 		request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
 		request->send();
 		return;
diff --git a/Swiften/.gitignore b/Swiften/.gitignore
index 9eca6c8..c21d6aa 100644
--- a/Swiften/.gitignore
+++ b/Swiften/.gitignore
@@ -1,2 +1,3 @@
 *.a
 *.o
+Swiften.h
diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h
index 7e55289..5432920 100644
--- a/Swiften/Client/Client.h
+++ b/Swiften/Client/Client.h
@@ -22,6 +22,7 @@
 #include "Swiften/Client/StanzaChannel.h"
 #include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 #include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h"
+#include "Swiften/Base/Shared.h"
 
 namespace Swift {
 	class IQRouter;
diff --git a/Swiften/Client/ClientXMLTracer.h b/Swiften/Client/ClientXMLTracer.h
index 8bcb6e7..f3cfd08 100644
--- a/Swiften/Client/ClientXMLTracer.h
+++ b/Swiften/Client/ClientXMLTracer.h
@@ -6,6 +6,8 @@
 
 #pragma once
 
+#include <boost/bind.hpp>
+
 #include "Swiften/Client/Client.h"
 
 namespace Swift {
diff --git a/Swiften/Disco/CapsManager.cpp b/Swiften/Disco/CapsManager.cpp
index a5023d3..a9920a2 100644
--- a/Swiften/Disco/CapsManager.cpp
+++ b/Swiften/Disco/CapsManager.cpp
@@ -69,7 +69,7 @@ void CapsManager::handleDiscoInfoReceived(const JID& from, const String& hash, D
 }
 
 void CapsManager::requestDiscoInfo(const JID& jid, const String& node, const String& hash) {
-	boost::shared_ptr<GetDiscoInfoRequest> request(new GetDiscoInfoRequest(jid, node + "#" + hash, iqRouter));
+	GetDiscoInfoRequest::ref request = GetDiscoInfoRequest::create(jid, node + "#" + hash, iqRouter);
 	request->onResponse.connect(boost::bind(&CapsManager::handleDiscoInfoReceived, this, jid, hash, _1, _2));
 	requestedDiscoInfos.insert(hash);
 	request->send();
diff --git a/Swiften/Elements/Presence.h b/Swiften/Elements/Presence.h
index 7297339..45638b9 100644
--- a/Swiften/Elements/Presence.h
+++ b/Swiften/Elements/Presence.h
@@ -22,6 +22,18 @@ namespace Swift {
 				setStatus(status);
 			}
 
+			static ref create() {
+				return ref(new Presence());
+			}
+
+			static ref create(const String& status) {
+				return ref(new Presence(status));
+			}
+
+			static ref create(Presence::ref presence) {
+				return ref(new Presence(*presence));
+			}
+
 			Type getType() const { return type_; }
 			void setType(Type type) { type_ = type; }
 
diff --git a/Swiften/Elements/RosterPayload.h b/Swiften/Elements/RosterPayload.h
index 58c5726..0c987c4 100644
--- a/Swiften/Elements/RosterPayload.h
+++ b/Swiften/Elements/RosterPayload.h
@@ -4,17 +4,17 @@
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
 
-#ifndef SWIFTEN_RosterPayload_H
-#define SWIFTEN_RosterPayload_H
+#pragma once
 
 #include <vector>
 #include <boost/optional.hpp>
 
 #include "Swiften/Elements/RosterItemPayload.h"
 #include "Swiften/Elements/Payload.h"
+#include "Swiften/Base/Shared.h"
 
 namespace Swift {
-	class RosterPayload : public Payload {
+	class RosterPayload : public Payload, public Shared<RosterPayload> {
 		public:
 			typedef std::vector<RosterItemPayload> RosterItemPayloads;
 
@@ -35,5 +35,3 @@ namespace Swift {
 			RosterItemPayloads items_;
 	};
 }
-
-#endif
diff --git a/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp b/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp
index af08a9c..3d814a8 100644
--- a/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp
+++ b/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp
@@ -41,7 +41,7 @@ void handleServerDiscoInfoResponse(boost::shared_ptr<DiscoInfo> /*info*/, const
 
 void handleConnected() {
 	exitCode = NO_RESPONSE;
-	boost::shared_ptr<GetDiscoInfoRequest> discoInfoRequest(new GetDiscoInfoRequest(JID(), client->getIQRouter()));
+	GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(JID(), client->getIQRouter());
 	discoInfoRequest->onResponse.connect(handleServerDiscoInfoResponse);
 	discoInfoRequest->send();
 }
diff --git a/Swiften/Examples/EchoBot/.gitignore b/Swiften/Examples/EchoBot/.gitignore
deleted file mode 100644
index 9200f42..0000000
--- a/Swiften/Examples/EchoBot/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-EchoBot
diff --git a/Swiften/Examples/EchoBot/EchoBot.cpp b/Swiften/Examples/EchoBot/EchoBot.cpp
deleted file mode 100644
index 0474287..0000000
--- a/Swiften/Examples/EchoBot/EchoBot.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include <boost/bind.hpp>
-#include <iostream>
-
-#include "Swiften/Client/Client.h"
-#include "Swiften/EventLoop/SimpleEventLoop.h"
-#include "Swiften/Queries/Requests/GetRosterRequest.h"
-
-using namespace Swift;
-using namespace boost;
-
-class EchoBot {
-	public:
-		EchoBot(const JID& jid, const String& pass) {
-			client = new Client(jid, pass);
-			client->onConnected.connect(bind(&EchoBot::handleConnected, this));
-			client->onMessageReceived.connect(bind(&EchoBot::handleMessageReceived, this, _1));
-			client->connect();
-		}
-
-		~EchoBot() {
-			delete client;
-		}
-
-	private:
-		void handleConnected() {
-			shared_ptr<GetRosterRequest> rosterRequest(new GetRosterRequest(client->getIQRouter()));
-			rosterRequest->onResponse.connect(bind(&EchoBot::handleRosterReceived, this, _2));
-			rosterRequest->send();
-		}
-
-		void handleRosterReceived(const optional<ErrorPayload>& error) {
-			if (error) {
-				std::cerr << "Error receiving roster. Continuing anyway.";
-			}
-			client->sendPresence(shared_ptr<Presence>(new Presence("Send me a message")));
-		}
-
-		void handleMessageReceived(shared_ptr<Message> message) {
-			message->setTo(message->getFrom());
-			message->setFrom(JID());
-			client->sendMessage(message);
-		}
-
-	private:
-		Client* client;
-};
-
-int main(int argc, char* argv[]) {
-	if (argc != 3) {
-		std::cerr << "Usage: " << argv[0] << " <jid> <pass>" << std::endl;
-		return -1;
-	}
-	SimpleEventLoop eventLoop;
-	EchoBot bot(JID(argv[1]), argv[2]);
-	eventLoop.run();
-	return 0;
-}
diff --git a/Swiften/Examples/EchoBot/SConscript b/Swiften/Examples/EchoBot/SConscript
deleted file mode 100644
index fb7749d..0000000
--- a/Swiften/Examples/EchoBot/SConscript
+++ /dev/null
@@ -1,14 +0,0 @@
-Import("env")
-
-myenv = env.Clone()
-myenv.MergeFlags(myenv["SWIFTEN_FLAGS"])
-myenv.MergeFlags(myenv["LIBIDN_FLAGS"])
-myenv.MergeFlags(myenv["BOOST_FLAGS"])
-myenv.MergeFlags(myenv.get("SQLITE_FLAGS", {}))
-myenv.MergeFlags(myenv["ZLIB_FLAGS"])
-myenv.MergeFlags(myenv["OPENSSL_FLAGS"])
-myenv.MergeFlags(myenv.get("LIBXML_FLAGS", ""))
-myenv.MergeFlags(myenv.get("EXPAT_FLAGS", ""))
-myenv.MergeFlags(myenv["PLATFORM_FLAGS"])
-
-myenv.Program("EchoBot", ["EchoBot.cpp"])
diff --git a/Swiften/Examples/SConscript b/Swiften/Examples/SConscript
index 64d1859..61bedfb 100644
--- a/Swiften/Examples/SConscript
+++ b/Swiften/Examples/SConscript
@@ -6,6 +6,5 @@ SConscript(dirs = [
 	"SendMessage",
 	"ConnectivityTest",
 	"LinkLocalTool",
-	"EchoBot",
 	"ParserTester",
 ])
diff --git a/Swiften/MUC/MUCBookmarkManager.cpp b/Swiften/MUC/MUCBookmarkManager.cpp
index 64615e4..0f5f3bb 100644
--- a/Swiften/MUC/MUCBookmarkManager.cpp
+++ b/Swiften/MUC/MUCBookmarkManager.cpp
@@ -19,7 +19,7 @@ namespace Swift {
 MUCBookmarkManager::MUCBookmarkManager(IQRouter* iqRouter) {
 	iqRouter_ = iqRouter;
 	ready_ = false;
-	boost::shared_ptr<GetPrivateStorageRequest<Storage> > request(new GetPrivateStorageRequest<Storage>(iqRouter_));
+	GetPrivateStorageRequest<Storage>::ref request = GetPrivateStorageRequest<Storage>::create(iqRouter_);
 	request->onResponse.connect(boost::bind(&MUCBookmarkManager::handleBookmarksReceived, this, _1, _2));
 	request->send();
 }
@@ -106,7 +106,7 @@ void MUCBookmarkManager::flush() {
 	}
 
 	// Send an iq to save the storage element
-	boost::shared_ptr<SetPrivateStorageRequest<Storage> > request(new SetPrivateStorageRequest<Storage>(storage, iqRouter_));
+	SetPrivateStorageRequest<Storage>::ref request = SetPrivateStorageRequest<Storage>::create(storage, iqRouter_);
 	// FIXME: We should care about the result
 	//request->onResponse.connect(boost::bind(&MUCBookmarkManager::handleBookmarksSet, this, _1, _2));
 	request->send();
diff --git a/Swiften/Queries/Request.h b/Swiften/Queries/Request.h
index 450e311..9184dea 100644
--- a/Swiften/Queries/Request.h
+++ b/Swiften/Queries/Request.h
@@ -21,6 +21,9 @@
 namespace Swift {
 	class Request : public IQHandler, public boost::enable_shared_from_this<Request> {
 		public:
+			void send();
+
+		protected:
 			Request(
 					IQ::Type type, 
 					const JID& receiver, 
@@ -31,9 +34,6 @@ namespace Swift {
 					const JID& receiver, 
 					IQRouter* router);
 
-			void send();
-
-		protected:
 			virtual void setPayload(boost::shared_ptr<Payload> p) {
 				payload_ = p;
 			}
diff --git a/Swiften/Queries/Requests/GetDiscoInfoRequest.h b/Swiften/Queries/Requests/GetDiscoInfoRequest.h
index 9ec1050..d1ed279 100644
--- a/Swiften/Queries/Requests/GetDiscoInfoRequest.h
+++ b/Swiften/Queries/Requests/GetDiscoInfoRequest.h
@@ -10,8 +10,17 @@
 #include "Swiften/Elements/DiscoInfo.h"
 
 namespace Swift {
-	class GetDiscoInfoRequest : public GenericRequest<DiscoInfo> {
+	class GetDiscoInfoRequest : public GenericRequest<DiscoInfo>, public Shared<GetDiscoInfoRequest> {
 		public:
+			static ref create(const JID& jid, IQRouter* router) {
+				return ref(new GetDiscoInfoRequest(jid, router));
+			}
+
+			static ref create(const JID& jid, const String& node, IQRouter* router) {
+				return ref(new GetDiscoInfoRequest(jid, node, router));
+			}
+
+		private:
 			GetDiscoInfoRequest(const JID& jid, IQRouter* router) :
 					GenericRequest<DiscoInfo>(IQ::Get, jid, boost::shared_ptr<DiscoInfo>(new DiscoInfo()), router) {
 			}
diff --git a/Swiften/Queries/Requests/GetDiscoItemsRequest.h b/Swiften/Queries/Requests/GetDiscoItemsRequest.h
index 453eab4..ed565ac 100644
--- a/Swiften/Queries/Requests/GetDiscoItemsRequest.h
+++ b/Swiften/Queries/Requests/GetDiscoItemsRequest.h
@@ -10,8 +10,13 @@
 #include "Swiften/Elements/DiscoItems.h"
 
 namespace Swift {
-	class GetDiscoItemsRequest : public GenericRequest<DiscoItems> {
+	class GetDiscoItemsRequest : public GenericRequest<DiscoItems>, public Shared<GetDiscoItemsRequest> {
 		public:
+			static ref create(const JID& jid, IQRouter* router) {
+				return ref(new GetDiscoItemsRequest(jid, router));
+			}
+
+		private:
 			GetDiscoItemsRequest(const JID& jid, IQRouter* router) :
 					GenericRequest<DiscoItems>(IQ::Get, jid, boost::shared_ptr<DiscoItems>(new DiscoItems()), router) {
 			}
diff --git a/Swiften/Queries/Requests/GetPrivateStorageRequest.h b/Swiften/Queries/Requests/GetPrivateStorageRequest.h
index d44d5d8..b593495 100644
--- a/Swiften/Queries/Requests/GetPrivateStorageRequest.h
+++ b/Swiften/Queries/Requests/GetPrivateStorageRequest.h
@@ -17,6 +17,13 @@ namespace Swift {
 	template<typename PAYLOAD_TYPE>
 	class GetPrivateStorageRequest : public Request {
 		public:
+			typedef boost::shared_ptr<GetPrivateStorageRequest<PAYLOAD_TYPE> > ref;
+
+			static ref create(IQRouter* router) {
+				return ref(new GetPrivateStorageRequest(router));
+			}
+
+		private:
 			GetPrivateStorageRequest(IQRouter* router) : Request(IQ::Get, JID(), boost::shared_ptr<PrivateStorage>(new PrivateStorage(boost::shared_ptr<Payload>(new PAYLOAD_TYPE()))), router) {
 			}
 
diff --git a/Swiften/Queries/Requests/GetRosterRequest.h b/Swiften/Queries/Requests/GetRosterRequest.h
index 59cefe4..271b2fb 100644
--- a/Swiften/Queries/Requests/GetRosterRequest.h
+++ b/Swiften/Queries/Requests/GetRosterRequest.h
@@ -8,10 +8,16 @@
 
 #include "Swiften/Queries/GenericRequest.h"
 #include "Swiften/Elements/RosterPayload.h"
+#include "Swiften/Base/Shared.h"
 
 namespace Swift {
-	class GetRosterRequest : public GenericRequest<RosterPayload> {
+	class GetRosterRequest : public GenericRequest<RosterPayload>, public Shared<GetRosterRequest> {
 		public:
+			static ref create(IQRouter* router) {
+				return ref(new GetRosterRequest(router));
+			}
+
+		private:
 			GetRosterRequest(IQRouter* router) :
 					GenericRequest<RosterPayload>(IQ::Get, JID(), boost::shared_ptr<Payload>(new RosterPayload()), router) {
 			}
diff --git a/Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h b/Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h
index 41225fb..ec04f80 100644
--- a/Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h
+++ b/Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h
@@ -8,10 +8,16 @@
 
 #include "Swiften/Queries/GenericRequest.h"
 #include "Swiften/Elements/SecurityLabelsCatalog.h"
+#include "Swiften/Base/Shared.h"
 
 namespace Swift {
-	class GetSecurityLabelsCatalogRequest : public GenericRequest<SecurityLabelsCatalog> {
+	class GetSecurityLabelsCatalogRequest : public GenericRequest<SecurityLabelsCatalog>, public Shared<GetSecurityLabelsCatalogRequest> {
 		public:
+			static ref create(const JID& recipient, IQRouter* router) {
+				return ref(new GetSecurityLabelsCatalogRequest(recipient, router));
+			}
+
+		private:
 			GetSecurityLabelsCatalogRequest(
 					const JID& recipient, 
 					IQRouter* router) :
diff --git a/Swiften/Queries/Requests/GetVCardRequest.h b/Swiften/Queries/Requests/GetVCardRequest.h
index f369cdc..2c40cd1 100644
--- a/Swiften/Queries/Requests/GetVCardRequest.h
+++ b/Swiften/Queries/Requests/GetVCardRequest.h
@@ -13,6 +13,11 @@
 namespace Swift {
 	class GetVCardRequest : public GenericRequest<VCard>, public Shared<GetVCardRequest> {
 		public:
+			static ref create(const JID& jid, IQRouter* router) {
+				return ref(new GetVCardRequest(jid, router));
+			}
+
+		private:
 			GetVCardRequest(const JID& jid, IQRouter* router) : GenericRequest<VCard>(IQ::Get, jid, boost::shared_ptr<Payload>(new VCard()), router) {
 			}
 	};
diff --git a/Swiften/Queries/Requests/SetPrivateStorageRequest.h b/Swiften/Queries/Requests/SetPrivateStorageRequest.h
index ebdfca8..1931f3a 100644
--- a/Swiften/Queries/Requests/SetPrivateStorageRequest.h
+++ b/Swiften/Queries/Requests/SetPrivateStorageRequest.h
@@ -17,6 +17,13 @@ namespace Swift {
 	template<typename PAYLOAD_TYPE>
 	class SetPrivateStorageRequest : public Request {
 		public:
+			typedef boost::shared_ptr<SetPrivateStorageRequest<PAYLOAD_TYPE> > ref;
+
+			static ref create(boost::shared_ptr<PAYLOAD_TYPE> payload, IQRouter* router) {
+				return ref(new SetPrivateStorageRequest<PAYLOAD_TYPE>(payload, router));
+			}
+
+		private:
 			SetPrivateStorageRequest(boost::shared_ptr<PAYLOAD_TYPE> payload, IQRouter* router) : Request(IQ::Set, JID(), boost::shared_ptr<PrivateStorage>(new PrivateStorage(payload)), router) {
 			}
 
diff --git a/Swiften/Queries/Requests/SetRosterRequest.h b/Swiften/Queries/Requests/SetRosterRequest.h
index 1f47cfe..7b1bf8c 100644
--- a/Swiften/Queries/Requests/SetRosterRequest.h
+++ b/Swiften/Queries/Requests/SetRosterRequest.h
@@ -11,10 +11,16 @@
 
 #include "Swiften/Queries/Request.h"
 #include "Swiften/Elements/RosterPayload.h"
+#include "Swiften/Base/Shared.h"
 
 namespace Swift {
-	class SetRosterRequest : public Request {
+	class SetRosterRequest : public Request, public Shared<SetRosterRequest> {
 		public:
+			static ref create(RosterPayload::ref payload, IQRouter* router) {
+				return ref(new SetRosterRequest(payload, router));
+			}
+
+		private:
 			SetRosterRequest(boost::shared_ptr<RosterPayload> payload, IQRouter* router) : Request(IQ::Set, JID(), boost::shared_ptr<RosterPayload>(payload), router) {
 			}
 
diff --git a/Swiften/Queries/Requests/UnitTest/GetPrivateStorageRequestTest.cpp b/Swiften/Queries/Requests/UnitTest/GetPrivateStorageRequestTest.cpp
index d90a114..fe8b0a0 100644
--- a/Swiften/Queries/Requests/UnitTest/GetPrivateStorageRequestTest.cpp
+++ b/Swiften/Queries/Requests/UnitTest/GetPrivateStorageRequestTest.cpp
@@ -45,8 +45,8 @@ class GetPrivateStorageRequestTest : public CppUnit::TestFixture
 		}
 
 		void testSend() {
-			GetPrivateStorageRequest<MyPayload> request(router);
-			request.send();
+			GetPrivateStorageRequest<MyPayload>::ref request = GetPrivateStorageRequest<MyPayload>::create(router);
+			request->send();
 
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel->iqs_.size()));
 			CPPUNIT_ASSERT_EQUAL(JID(), channel->iqs_[0]->getTo());
@@ -58,9 +58,9 @@ class GetPrivateStorageRequestTest : public CppUnit::TestFixture
 		}
 
 		void testHandleResponse() {
-			GetPrivateStorageRequest<MyPayload> testling(router);
-			testling.onResponse.connect(boost::bind(&GetPrivateStorageRequestTest::handleResponse, this, _1, _2));
-			testling.send();
+			GetPrivateStorageRequest<MyPayload>::ref testling = GetPrivateStorageRequest<MyPayload>::create(router);
+			testling->onResponse.connect(boost::bind(&GetPrivateStorageRequestTest::handleResponse, this, _1, _2));
+			testling->send();
 			channel->onIQReceived(createResponse("test-id", "foo"));
 
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(responses.size()));
@@ -68,9 +68,9 @@ class GetPrivateStorageRequestTest : public CppUnit::TestFixture
 		}
 
 		void testHandleResponse_Error() {
-			GetPrivateStorageRequest<MyPayload> testling(router);
-			testling.onResponse.connect(boost::bind(&GetPrivateStorageRequestTest::handleResponse, this, _1, _2));
-			testling.send();
+			GetPrivateStorageRequest<MyPayload>::ref testling = GetPrivateStorageRequest<MyPayload>::create(router);
+			testling->onResponse.connect(boost::bind(&GetPrivateStorageRequestTest::handleResponse, this, _1, _2));
+			testling->send();
 			channel->onIQReceived(createError("test-id"));
 
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(responses.size()));
diff --git a/Swiften/Roster/XMPPRosterController.cpp b/Swiften/Roster/XMPPRosterController.cpp
index dca74c0..7743ec8 100644
--- a/Swiften/Roster/XMPPRosterController.cpp
+++ b/Swiften/Roster/XMPPRosterController.cpp
@@ -29,7 +29,7 @@ XMPPRosterController::XMPPRosterController(IQRouter* iqRouter, XMPPRoster* xmppR
 
 void XMPPRosterController::requestRoster() {
 	xmppRoster_->clear();
-	boost::shared_ptr<GetRosterRequest> rosterRequest(new GetRosterRequest(iqRouter_));
+	GetRosterRequest::ref rosterRequest = GetRosterRequest::create(iqRouter_);
 	rosterRequest->onResponse.connect(boost::bind(&XMPPRosterController::handleRosterReceived, this, _1));
 	rosterRequest->send();
 }
diff --git a/Swiften/SConscript b/Swiften/SConscript
index c5ad9a6..7665fb0 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -1,3 +1,5 @@
+import os
+
 Import("env")
 
 ################################################################################
@@ -244,3 +246,19 @@ if env["SCONS_STAGE"] == "build" :
 			File("StringCodecs/UnitTest/PBKDF2Test.cpp"),
 			File("VCards/UnitTest/VCardManagerTest.cpp"),
 		])
+	
+	# Generate the Swiften header
+	swiften_header = "#pragma once\n"
+	top_path = env.Dir("..").abspath
+	public_dirs = ["Queries", "Client", "Elements"]
+	for public_dir in public_dirs :
+		for root, dirs, files in os.walk(env.Dir(public_dir).abspath) :
+			if root.endswith("UnitTest") :
+				continue
+			for file in files :
+				if not file.endswith(".h") :
+					continue
+				swiften_header += "#include \"" + os.path.relpath(os.path.join(root, file), top_path) + "\"\n"
+	for file in ["EventLoop/SimpleEventLoop.h"] :
+				swiften_header += "#include \"Swiften/" + file + "\"\n"		
+	swiften_env.WriteVal("Swiften.h", swiften_env.Value(swiften_header))
\ No newline at end of file
diff --git a/Swiften/VCards/VCardManager.cpp b/Swiften/VCards/VCardManager.cpp
index 673b937..c189717 100644
--- a/Swiften/VCards/VCardManager.cpp
+++ b/Swiften/VCards/VCardManager.cpp
@@ -34,7 +34,7 @@ void VCardManager::requestVCard(const JID& requestedJID) {
 	if (requestedVCards.find(jid) != requestedVCards.end()) {
 		return;
 	}
-	GetVCardRequest::ref request(new GetVCardRequest(jid, iqRouter));
+	GetVCardRequest::ref request = GetVCardRequest::create(jid, iqRouter);
 	request->onResponse.connect(boost::bind(&VCardManager::handleVCardReceived, this, jid, _1, _2));
 	request->send();
 	requestedVCards.insert(jid);
-- 
cgit v0.10.2-6-g49f6