diff --git a/Network/Protocol/XMPP/Component.hs b/Network/Protocol/XMPP/Component.hs
new file mode 100644
--- /dev/null
+++ b/Network/Protocol/XMPP/Component.hs
@@ -0,0 +1,77 @@
+{- Copyright (C) 2010 Stephan Maka <stephan@spaceboyz.net>
+   
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+
+
+module Network.Protocol.XMPP.Component (
+	 ConnectedComponent
+	,Component
+	,componentConnect
+	,componentAuthenticate
+	,componentJID
+	) where
+
+import Control.Monad (when)
+import Network (HostName, PortID, connectTo)
+import Text.XML.HXT.Arrow ((>>>))
+import qualified Text.XML.HXT.Arrow as A
+import Text.XML.HXT.DOM.TypeDefs (XmlTree)
+import qualified Text.XML.HXT.DOM.XmlNode as XN
+import qualified Data.Digest.Pure.SHA as SHA
+
+import Network.Protocol.XMPP.JID (JID, jidParse, jidResource)
+import qualified Network.Protocol.XMPP.SASL as SASL
+import qualified Network.Protocol.XMPP.Stream as S
+import Network.Protocol.XMPP.Util (mkElement, mkQName)
+import Network.Protocol.XMPP.Stanzas (Stanza, stanzaToTree)
+import Network.Protocol.XMPP.Connection
+import qualified Data.ByteString.Lazy.Char8 as B (pack)
+
+data ConnectedComponent = ConnectedComponent JID S.Stream
+
+data Component = Component {
+	 componentJID :: JID
+	,componentStream :: S.Stream
+	}
+
+type Password = String
+
+componentConnect :: JID -> HostName -> PortID -> IO ConnectedComponent
+componentConnect jid host port = do
+	handle <- connectTo host port
+	stream <- S.beginStream jid "jabber:component:accept" handle
+	return $ ConnectedComponent jid stream
+
+componentAuthenticate :: ConnectedComponent -> Password -> IO Component
+componentAuthenticate (ConnectedComponent jid stream) password
+    = do let c = Component jid stream
+
+         let S.XMPPStreamID sid = S.streamID stream
+             hash = SHA.showDigest . SHA.sha1 . B.pack $ sid ++ password
+         putTree c $ mkElement ("", "handshake") [] [XN.mkText hash]
+
+         result <- getTree c
+         when (A.runLA (A.getChildren
+                        >>> A.hasQName (mkQName "jabber:component:accept" "handshake")
+                       ) result == []) $
+             error "Component handshake failed"
+
+         return c
+
+-------------------------------------------------------------------------------
+
+instance Connection Component where
+    getTree = S.getTree . componentStream
+    putTree = S.putTree . componentStream
diff --git a/Network/Protocol/XMPP/Connection.hs b/Network/Protocol/XMPP/Connection.hs
new file mode 100644
--- /dev/null
+++ b/Network/Protocol/XMPP/Connection.hs
@@ -0,0 +1,38 @@
+{- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>
+                      Stephan Maka <stephan@spaceboyz.net>
+   
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+
+module Network.Protocol.XMPP.Connection
+	( Connection
+	, getTree
+	, putTree
+	, putStanza
+	) where
+
+import Text.XML.HXT.DOM.TypeDefs (XmlTree)
+import Network.Protocol.XMPP.Stanzas (Stanza, stanzaToTree)
+
+-- |Provides the basic operations for XMPP connections.
+class Connection c where
+	-- |Receive XML
+	getTree :: c -> IO XmlTree
+	
+	-- |Send XML
+	putTree :: c -> XmlTree -> IO ()
+	
+	-- |Send a stanza, uses putTree by default
+	putStanza :: c -> Stanza -> IO ()
+	putStanza c = putTree c . stanzaToTree
diff --git a/network-protocol-xmpp.cabal b/network-protocol-xmpp.cabal
--- a/network-protocol-xmpp.cabal
+++ b/network-protocol-xmpp.cabal
@@ -1,5 +1,5 @@
 name: network-protocol-xmpp
-version: 0.2
+version: 0.2.1
 synopsis: Client <-> Server communication over XMPP
 license: GPL
 license-file: License.txt
@@ -14,13 +14,24 @@
 
 source-repository head
   type: darcs
-  location: http://patch-tag.com/r/jmillikin/network-protocol-xmpp/pullrepo
+  location: http://ianen.org/haskell/xmpp/
 
 library
-  build-depends: base >=3 && < 5, hxt, libxml-sax >= 0.2, hsgnutls, gsasl, network, bytestring, SHA
+  build-depends:
+    base >=3 && < 5,
+    hxt >= 8.5 && < 8.6,
+    libxml-sax >= 0.3 && < 0.4,
+    hsgnutls >= 0.2 && < 0.3,
+    gsasl >= 0.2 && < 0.3,
+    network >= 2.2 && < 2.3,
+    bytestring >= 0.9 && < 1.0,
+    SHA >= 1.4 && < 1.5
+
   exposed-modules:
     Network.Protocol.XMPP
     Network.Protocol.XMPP.Client
+    Network.Protocol.XMPP.Component
+    Network.Protocol.XMPP.Connection
     Network.Protocol.XMPP.JID
     Network.Protocol.XMPP.SASL
     Network.Protocol.XMPP.Stanzas
