diff --git a/Makefile.am b/Makefile.am
index 24d5ef08..b47df4d7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,4 @@
-SUBDIRS = bin browser data po shell sugar services
-
-ACLOCAL_AMFLAGS = -I m4
+SUBDIRS = bin data lib po shell sugar services
 
 bin_SCRIPTS = 			\
 	sugar-emulator
diff --git a/autogen.sh b/autogen.sh
index 4a02f438..eaf5ff8b 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,20 +1,6 @@
 #!/bin/sh
-# Run this to generate all the initial makefiles, etc.
+export ACLOCAL="aclocal -I m4"
 
-srcdir=`dirname $0`
-test -z "$srcdir" && srcdir=.
-
-PKG_NAME="sugar"
-
-(test -f $srcdir/README) || {
-    echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
-    echo " top-level $PKG_NAME directory"
-    exit 1
-}
-
-which gnome-autogen.sh || {
-    echo "You need to install gnome-common from the GNOME CVS"
-    exit 1
-}
-
-REQUIRED_AUTOMAKE_VERSION=1.9 USE_GNOME2_MACROS=1 . gnome-autogen.sh
+autoreconf -i
+intltoolize
+./configure "$@"
diff --git a/browser/GeckoBrowserPersist.cpp b/browser/GeckoBrowserPersist.cpp
deleted file mode 100644
index 0a4b7f32..00000000
--- a/browser/GeckoBrowserPersist.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-#include <config.h>
-
-#include <stdio.h>
-
-#include <gtkmozembed.h>
-#include <gtkmozembed_internal.h>
-#include <nsIRequest.h>
-#include <nsNetUtil.h>
-#include <nsISeekableStream.h>
-#include <nsIHttpChannel.h>
-#include <nsIUploadChannel.h>
-#include <nsIWebBrowser.h>
-#include <nsISHistory.h>
-#include <nsIHistoryEntry.h>
-#include <nsISHEntry.h>
-#include <nsIInputStream.h>
-#include <nsIWebNavigation.h>
-
-#include "GeckoBrowserPersist.h"
-
-GeckoBrowserPersist::GeckoBrowserPersist(SugarBrowser *browser)
-    :   mBrowser(browser)
-{
-}
-
-GeckoBrowserPersist::~GeckoBrowserPersist()
-{
-}
-
-static nsresult
-NewURI(const char *uri, nsIURI **result)
-{
-    nsresult rv;
-
-    nsCOMPtr<nsIServiceManager> mgr;
-    NS_GetServiceManager (getter_AddRefs (mgr));
-    NS_ENSURE_TRUE(mgr, FALSE);
-
-    nsCOMPtr<nsIIOService> ioService;
-    rv = mgr->GetServiceByContractID ("@mozilla.org/network/io-service;1",
-                                      NS_GET_IID (nsIIOService),
-                                      getter_AddRefs(ioService));
-    NS_ENSURE_SUCCESS(rv, FALSE);
-
-    nsCString cSpec(uri);
-    return ioService->NewURI (cSpec, nsnull, nsnull, result);
-}
-
-static nsresult
-GetPostData(SugarBrowser *browser, nsIInputStream **postData)
-{
-    nsCOMPtr<nsIWebBrowser> webBrowser;
-    gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(browser),
-                                    getter_AddRefs(webBrowser));
-    NS_ENSURE_TRUE(webBrowser, NS_ERROR_FAILURE);
-
-    nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(webBrowser));
-    NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
-
-    PRInt32 sindex;
-
-    nsCOMPtr<nsISHistory> sessionHistory;
-    webNav->GetSessionHistory(getter_AddRefs(sessionHistory));
-    NS_ENSURE_TRUE(sessionHistory, NS_ERROR_FAILURE);
-
-    nsCOMPtr<nsIHistoryEntry> entry;
-    sessionHistory->GetIndex(&sindex);
-    sessionHistory->GetEntryAtIndex(sindex, PR_FALSE, getter_AddRefs(entry));
-
-    nsCOMPtr<nsISHEntry> shEntry(do_QueryInterface(entry));
-    if (shEntry) {
-        shEntry->GetPostData(postData);
-    }
-
-    return NS_OK;
-}
-
-bool
-GeckoBrowserPersist::SaveURI(const char *uri, const char *filename)
-{
-    nsresult rv;
-
-    nsCOMPtr<nsIURI> sourceURI;
-    rv = NewURI(uri, getter_AddRefs(sourceURI));
-    NS_ENSURE_SUCCESS(rv, FALSE);
-
-    nsCOMPtr<nsILocalFile> destFile = do_CreateInstance("@mozilla.org/file/local;1");
-    NS_ENSURE_TRUE(destFile, FALSE);
-
-    destFile->InitWithNativePath(nsCString(filename));
-
-    nsCOMPtr<nsIInputStream> postData;
-    GetPostData(mBrowser, getter_AddRefs(postData));
-    
-    nsCOMPtr<nsIChannel> inputChannel;
-    rv = NS_NewChannel(getter_AddRefs(inputChannel), sourceURI,
-            nsnull, nsnull, nsnull, nsIRequest::LOAD_NORMAL);
-    NS_ENSURE_SUCCESS(rv, FALSE);
-    
-    nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(inputChannel));
-    if (httpChannel) {
-        nsCOMPtr<nsISeekableStream> stream(do_QueryInterface(postData));
-        if (stream)
-        {
-            // Rewind the postdata stream
-            stream->Seek(nsISeekableStream::NS_SEEK_SET, 0);
-            nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
-            NS_ASSERTION(uploadChannel, "http must support nsIUploadChannel");
-            // Attach the postdata to the http channel
-            uploadChannel->SetUploadStream(postData, EmptyCString(), -1);
-        }
-    }
-    
-    nsCOMPtr<nsIInputStream> stream;
-    rv = inputChannel->Open(getter_AddRefs(stream));
-    NS_ENSURE_SUCCESS(rv, FALSE);
-    
-    nsCOMPtr<nsIFileOutputStream> fileOutputStream =
-        do_CreateInstance(NS_LOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
-    NS_ENSURE_SUCCESS(rv, FALSE);
-    
-    rv = fileOutputStream->Init(destFile, -1, -1, 0);
-    NS_ENSURE_SUCCESS(rv, FALSE);
-
-    // Read data from the input and write to the output
-    char buffer[8192];
-    PRUint32 bytesRead;
-    PRUint32 bytesRemaining;
-    PRBool cancel = PR_FALSE;
-    PRBool readError;
-            
-    rv = stream->Available(&bytesRemaining);
-    NS_ENSURE_SUCCESS(rv, FALSE);
-    
-    while (!cancel && bytesRemaining)
-    {
-        readError = PR_TRUE;
-        rv = stream->Read(buffer, PR_MIN(sizeof(buffer), bytesRemaining), &bytesRead);
-        if (NS_SUCCEEDED(rv))
-        {
-            readError = PR_FALSE;
-            // Write out the data until something goes wrong, or, it is
-            // all written.  We loop because for some errors (e.g., disk
-            // full), we get NS_OK with some bytes written, then an error.
-            // So, we want to write again in that case to get the actual
-            // error code.
-            const char *bufPtr = buffer; // Where to write from.
-            while (NS_SUCCEEDED(rv) && bytesRead)
-            {
-                PRUint32 bytesWritten = 0;
-                rv = fileOutputStream->Write(bufPtr, bytesRead, &bytesWritten);
-                if (NS_SUCCEEDED(rv))
-                {
-                    bytesRead -= bytesWritten;
-                    bufPtr += bytesWritten;
-                    bytesRemaining -= bytesWritten;
-                    // Force an error if (for some reason) we get NS_OK but
-                    // no bytes written.
-                    if (!bytesWritten)
-                    {
-                        rv = NS_ERROR_FAILURE;
-                        cancel = PR_TRUE;
-                    }
-                }
-                else
-                {
-                    // Disaster - can't write out the bytes - disk full / permission?
-                    cancel = PR_TRUE;
-                }
-            }
-        }
-        else
-        {
-            // Disaster - can't read the bytes - broken link / file error?
-            cancel = PR_TRUE;
-        }
-    }
-    NS_ENSURE_SUCCESS(rv, FALSE);
-
-    stream->Close();
-
-    return TRUE;
-}
diff --git a/browser/GeckoBrowserPersist.h b/browser/GeckoBrowserPersist.h
deleted file mode 100644
index e9767893..00000000
--- a/browser/GeckoBrowserPersist.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __GECKO_BROWSER_PERSIST_H__
-#define __GECKO_BROWSER_PERSIST_H__
-
-#include "sugar-browser.h"
-
-class GeckoBrowserPersist
-{
-public:
-    GeckoBrowserPersist(SugarBrowser *browser);
-    ~GeckoBrowserPersist();
-
-    bool SaveURI(const char *uri, const char *filename);
-private:
-    SugarBrowser    *mBrowser;
-protected:
-    /* additional members */
-};
-
-#endif // __GECKO_BROWSER_PERSIST_H__
diff --git a/browser/GeckoContentHandler.cpp b/browser/GeckoContentHandler.cpp
deleted file mode 100644
index 8b6c9fb6..00000000
--- a/browser/GeckoContentHandler.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-#include <nsCExternalHandlerService.h>
-#include <nsIFile.h>
-#include <nsIFactory.h>
-#include <nsILocalFile.h>
-#include <nsStringAPI.h>
-
-#include <nsComponentManagerUtils.h>
-
-#include "GeckoContentHandler.h"
-
-class GeckoContentHandler : public nsIHelperAppLauncherDialog
-{
-public:
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSIHELPERAPPLAUNCHERDIALOG
-
-    GeckoContentHandler();
-    virtual ~GeckoContentHandler();
-};
-
-GeckoContentHandler::GeckoContentHandler()
-{
-
-}
-
-GeckoContentHandler::~GeckoContentHandler()
-{
-
-}
-
-NS_IMPL_ISUPPORTS1(GeckoContentHandler, nsIHelperAppLauncherDialog)
-
-NS_IMETHODIMP
-GeckoContentHandler::Show (nsIHelperAppLauncher *aLauncher,
-						   nsISupports *aContext,
-						   PRUint32 aReason)
-{
-	aLauncher->SaveToDisk(NULL, PR_FALSE);
-
-	return NS_OK;
-}
-
-#include <glib.h>
-NS_IMETHODIMP
-GeckoContentHandler::PromptForSaveToFile (nsIHelperAppLauncher *aLauncher,			    
-										  nsISupports *aWindowContext,
-										  const PRUnichar *aDefaultFile,
-										  const PRUnichar *aSuggestedFileExtension,
-										  nsILocalFile **_retval)
-{
-	char *filename = NULL;
-	nsCString defaultFile;
-
-	NS_UTF16ToCString(nsString(aDefaultFile), NS_CSTRING_ENCODING_UTF8, defaultFile);
-
-	nsCOMPtr <nsILocalFile> destFile(do_CreateInstance("@mozilla.org/file/local;1"));
-	NS_ENSURE_TRUE(destFile, NS_ERROR_FAILURE);
-
-	const char * suggested = defaultFile.get();
-	if (strlen(suggested) > 0) {
-		filename = g_build_path("/", g_get_tmp_dir (), suggested, NULL);
-	} else {
-		filename = tempnam(NULL, NULL);
-	}
-
-	if (filename == NULL)
-		return NS_ERROR_OUT_OF_MEMORY;
-
-	destFile->InitWithNativePath(nsCString(filename));
-	g_free(filename);
-
-	NS_IF_ADDREF(*_retval = destFile);
-	return NS_OK;
-}
-
-//*****************************************************************************
-// GeckoContentHandlerFactory
-//*****************************************************************************
-
-class GeckoContentHandlerFactory : public nsIFactory {
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIFACTORY
-
-  GeckoContentHandlerFactory();
-  virtual ~GeckoContentHandlerFactory();
-};
-
-//*****************************************************************************
-
-NS_IMPL_ISUPPORTS1(GeckoContentHandlerFactory, nsIFactory)
-
-GeckoContentHandlerFactory::GeckoContentHandlerFactory() {
-}
-
-GeckoContentHandlerFactory::~GeckoContentHandlerFactory() {
-}
-
-NS_IMETHODIMP
-GeckoContentHandlerFactory::CreateInstance(nsISupports *aOuter,
-                                           const nsIID & aIID,
-                                           void **aResult)
-{
-    NS_ENSURE_ARG_POINTER(aResult);
-
-    *aResult = NULL;
-    GeckoContentHandler *inst = new GeckoContentHandler;
-    if (!inst)
-        return NS_ERROR_OUT_OF_MEMORY;
-
-    nsresult rv = inst->QueryInterface(aIID, aResult);
-    if (rv != NS_OK) {
-        // We didn't get the right interface, so clean up
-        delete inst;
-    }
-
-    return rv;
-}
-
-NS_IMETHODIMP
-GeckoContentHandlerFactory::LockFactory(PRBool lock)
-{
-    return NS_OK;
-}
-
-//*****************************************************************************
-
-nsresult
-NS_NewGeckoContentHandlerFactory(nsIFactory** aFactory)
-{
-    NS_ENSURE_ARG_POINTER(aFactory);
-    *aFactory = nsnull;
-
-    GeckoContentHandlerFactory *result = new GeckoContentHandlerFactory;
-    if (!result)
-        return NS_ERROR_OUT_OF_MEMORY;
-
-    NS_ADDREF(result);
-    *aFactory = result;
-
-    return NS_OK;
-}
diff --git a/browser/GeckoContentHandler.h b/browser/GeckoContentHandler.h
deleted file mode 100644
index 103166ce..00000000
--- a/browser/GeckoContentHandler.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __GECKO_CONTENT_HANDLER_H__
-#define __GECKO_CONTENT_HANDLER_H__
-
-#include <nsCOMPtr.h>
-#include <nsIHelperAppLauncherDialog.h>
-
-#define GECKOCONTENTHANDLER_CID			     	 \
-{ /* 2321843e-6377-11db-967b-00e08161165f */         \
-    0x2321843e,                                      \
-    0x6377,                                          \
-    0x11db,                                          \
-    {0x96, 0x7b, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f}  \
-}
-
-class nsIFactory;
-
-extern "C" NS_EXPORT nsresult NS_NewGeckoContentHandlerFactory(nsIFactory** aFactory);
-
-#endif /* __GECKO_CONTENT_HANDLER_H */
diff --git a/browser/GeckoDirectoryProvider.cpp b/browser/GeckoDirectoryProvider.cpp
deleted file mode 100644
index f59d26a6..00000000
--- a/browser/GeckoDirectoryProvider.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-#include "GeckoDirectoryProvider.h"
-
-#include <nsCOMPtr.h>
-#include <nsIIOService.h>
-#include <nsNetUtil.h>
-#include <nsArrayEnumerator.h>
-#include <nsILocalFile.h>
-#include <nsDirectoryServiceDefs.h>
-#include <nsIToolkitChromeRegistry.h>
-#include <nsIDirectoryService.h>
-#include <nsCOMArray.h>
-
-#include <glib.h>
-
-NS_IMPL_ISUPPORTS2 (GeckoDirectoryProvider,
-                    nsIDirectoryServiceProvider,
-                    nsIDirectoryServiceProvider2)
-
-GeckoDirectoryProvider::GeckoDirectoryProvider(const char *sugar_path,
-                                               const char *profile_path)
-{
-    mComponentPath = g_build_filename
-            (sugar_path, "mozilla", "components", NULL);
-    mCompregPath = g_build_filename
-            (profile_path, "compreg.dat", NULL);
-}
-
-GeckoDirectoryProvider::~GeckoDirectoryProvider()
-{
-    if(mComponentPath)
-        g_free(mComponentPath);
-    if(mCompregPath)
-        g_free(mCompregPath);
-}
-
-/* nsIFile getFile (in string prop, out PRBool persistent); */
-NS_IMETHODIMP
-GeckoDirectoryProvider::GetFile (const char *prop,
-                                 PRBool *persistent,
-                                 nsIFile **_retval)
-{
-    nsresult rv = NS_ERROR_FAILURE;
-    nsCOMPtr<nsILocalFile> file;
-
-    if (!strcmp(prop, NS_XPCOM_COMPONENT_REGISTRY_FILE)) {
-        rv = NS_NewNativeLocalFile(nsDependentCString(mCompregPath),
-                                   PR_TRUE,
-                                   getter_AddRefs(file));
-    }
-
-    if (NS_SUCCEEDED(rv) && file) {
-        NS_ADDREF(*_retval = file);
-        return NS_OK;
-    }
-
-    return NS_ERROR_FAILURE;
-}
-
-/* nsISimpleEnumerator getFiles (in string aProperty); */
-NS_IMETHODIMP
-GeckoDirectoryProvider::GetFiles (const char *aProperty, nsISimpleEnumerator **aResult)
-{
-    nsresult rv = NS_ERROR_FAILURE;
-
-    if (!strcmp(aProperty, NS_XPCOM_COMPONENT_DIR_LIST)) {
-        if (mComponentPath) {
-            nsCOMPtr<nsILocalFile> componentDir;
-            rv = NS_NewNativeLocalFile(nsDependentCString(mComponentPath),
-                                       PR_TRUE,
-                                       getter_AddRefs(componentDir));
-            NS_ENSURE_SUCCESS (rv, rv);
-
-            nsCOMArray<nsIFile> array;
-
-            rv = array.AppendObject (componentDir);
-            NS_ENSURE_SUCCESS (rv, rv);
-
-            rv = NS_NewArrayEnumerator (aResult, array);
-            NS_ENSURE_SUCCESS (rv, rv);
-
-            rv = NS_SUCCESS_AGGREGATE_RESULT;
-        }
-    }
-    
-    return rv;
-}
diff --git a/browser/GeckoDirectoryProvider.h b/browser/GeckoDirectoryProvider.h
deleted file mode 100644
index db6ccc92..00000000
--- a/browser/GeckoDirectoryProvider.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2007, One Laptop Per Child
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-#ifndef GECKO_DIRECTORY_PROVIDER_H
-#define GECKO_DIRECTORY_PROVIDER_H
-    
-#include <nsIDirectoryService.h>
-
-class GeckoDirectoryProvider : public nsIDirectoryServiceProvider2
-{
-    public:
-        NS_DECL_ISUPPORTS
-        NS_DECL_NSIDIRECTORYSERVICEPROVIDER
-        NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
-
-        GeckoDirectoryProvider(const char *sugar_path,
-                               const char *profile_path);
-        virtual ~GeckoDirectoryProvider();
-
-    private:
-        char *mComponentPath;
-        char *mCompregPath;
-};
-
-#endif /* GECKO_DIRECTORY_PROVIDER_H */
diff --git a/browser/GeckoDocumentObject.cpp b/browser/GeckoDocumentObject.cpp
deleted file mode 100644
index 260b964b..00000000
--- a/browser/GeckoDocumentObject.cpp
+++ /dev/null
@@ -1,237 +0,0 @@
-#include <config.h>
-
-#include <unistd.h>
-
-#include <glib.h>
-#include <imgICache.h>
-#include <nsComponentManagerUtils.h>
-#include <nsCOMPtr.h>
-#include <nsIDOMHTMLElement.h>
-#include <nsIInterfaceRequestorUtils.h>
-#include <nsIIOService.h>
-#include <nsILocalFile.h>
-#include <nsIMIMEHeaderParam.h>
-#include <nsIProperties.h>
-#include <nsISupportsPrimitives.h>
-#include <nsIURI.h>
-#include <nsIURL.h>
-#include <nsServiceManagerUtils.h>
-#include <nsStringAPI.h>
-
-#include "GeckoDocumentObject.h"
-#include "GeckoBrowserPersist.h"
-                    
-GeckoDocumentObject::GeckoDocumentObject(SugarBrowser *browser, nsIDOMNode *node)
-    :   mBrowser(browser),
-        mNode(node),
-        mImage(NULL)
-{
-}
-
-GeckoDocumentObject::~GeckoDocumentObject()
-{
-}
-
-bool GeckoDocumentObject::IsImage()
-{
-    if(mImage) {
-        return true;
-    }
-
-    nsresult rv;
-
-    PRUint16 type;
-    rv = mNode->GetNodeType(&type);
-    if(NS_FAILED(rv)) return rv;
-
-    nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(mNode);
-    if ((nsIDOMNode::ELEMENT_NODE == type) && element) {
-        nsString uTag;
-        rv = element->GetLocalName(uTag);
-        if(NS_FAILED(rv)) return rv;
-
-        nsCString tag;
-        NS_UTF16ToCString (uTag, NS_CSTRING_ENCODING_UTF8, tag);
-
-        if (g_ascii_strcasecmp (tag.get(), "img") == 0) {
-            nsCOMPtr <nsIDOMHTMLImageElement> imagePtr;
-            imagePtr = do_QueryInterface(mNode, &rv);
-            if(NS_FAILED(rv)) return rv;
-            
-            mImage = imagePtr;
-
-            return true;
-        }
-    }
-    
-    return false;
-}
-
-static nsresult
-NewURI(const char *uri, nsIURI **result)
-{
-    nsresult rv;
-
-    nsCOMPtr<nsIServiceManager> mgr;
-    NS_GetServiceManager (getter_AddRefs (mgr));
-    NS_ENSURE_TRUE(mgr, FALSE);
-
-    nsCOMPtr<nsIIOService> ioService;
-    rv = mgr->GetServiceByContractID ("@mozilla.org/network/io-service;1",
-                                      NS_GET_IID (nsIIOService),
-                                      getter_AddRefs(ioService));
-    NS_ENSURE_SUCCESS(rv, FALSE);
-
-    nsCString cSpec(uri);
-    return ioService->NewURI (cSpec, nsnull, nsnull, result);
-}
-
-static nsresult
-FilenameFromContentDisposition(nsCString contentDisposition, nsCString &fileName)
-{
-    nsresult rv;
-    nsCString fallbackCharset;
-
-    nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar =
-        do_GetService("@mozilla.org/network/mime-hdrparam;1");
-    NS_ENSURE_TRUE(mimehdrpar, NS_ERROR_FAILURE);
-
-    nsString aFileName;
-    rv = mimehdrpar->GetParameter (contentDisposition, "filename",
-                                   fallbackCharset, PR_TRUE, nsnull,
-                                   aFileName);
-
-    if (NS_FAILED(rv) || !fileName.Length()) {
-        rv = mimehdrpar->GetParameter (contentDisposition, "name",
-                                       fallbackCharset, PR_TRUE, nsnull,
-                                       aFileName);
-    }
-
-    if (NS_SUCCEEDED(rv) && fileName.Length()) {
-        NS_UTF16ToCString (aFileName, NS_CSTRING_ENCODING_UTF8, fileName);
-    }
-
-    return NS_OK;
-}
-
-static nsresult
-GetImageProperties(char *imgURIStr, nsIProperties **properties)
-{
-    nsresult rv;
-
-    nsCOMPtr<nsIURI> imageURI;
-    rv = NewURI(imgURIStr, getter_AddRefs(imageURI));
-    if(NS_FAILED(rv)) return rv;
-
-    nsCOMPtr<nsIServiceManager> mgr;
-    NS_GetServiceManager(getter_AddRefs(mgr));
-    NS_ENSURE_TRUE(mgr, NS_ERROR_FAILURE);
-
-    nsCOMPtr<imgICache> imgCache;
-    rv = mgr->GetServiceByContractID("@mozilla.org/image/cache;1",
-                                     NS_GET_IID(imgICache),
-                                     getter_AddRefs(imgCache));
-    if(NS_FAILED(rv)) return rv;
-
-    imgCache->FindEntryProperties(imageURI, properties);
-    NS_ENSURE_TRUE(mgr, NS_ERROR_FAILURE);
-    return NS_OK;
-}
-
-char *
-GeckoDocumentObject::GetImageName()
-{
-    if(!IsImage()) {
-        return NULL;
-    }
-
-    if(mImageName.Length()) {
-        return g_strdup(mImageName.get());
-    }
-
-    nsresult rv;
-    char *imgURIStr = GetImageURI();
-
-    nsCOMPtr<nsIProperties> imgProperties;
-    rv = GetImageProperties(imgURIStr, getter_AddRefs(imgProperties));
-    NS_ENSURE_SUCCESS(rv, NULL);
-    if (imgProperties) {
-        nsCOMPtr<nsISupportsCString> dispositionCString;
-        imgProperties->Get("content-disposition",
-                           NS_GET_IID(nsISupportsCString),
-                           getter_AddRefs(dispositionCString));
-        if (dispositionCString) {
-            nsCString contentDisposition;
-            dispositionCString->GetData(contentDisposition);
-            FilenameFromContentDisposition(contentDisposition, mImageName);
-        }
-    }
-
-    if (!mImageName.Length()) {
-        nsCOMPtr<nsIURI> imageURI;
-        rv = NewURI(imgURIStr, getter_AddRefs(imageURI));
-        NS_ENSURE_SUCCESS(rv, NULL);
-
-        nsCOMPtr<nsIURL> url(do_QueryInterface(imageURI));
-        if (url) {
-            url->GetFileName(mImageName);
-        }
-    }
-
-    return mImageName.Length() ? g_strdup(mImageName.get()) : NULL;
-}
-
-char *
-GeckoDocumentObject::GetImageMimeType()
-{
-    if(!IsImage()) {
-        return NULL;
-    }
-
-    if(mImageMimeType.Length()) {
-        return g_strdup(mImageMimeType.get());
-    }
-
-    nsresult rv;
-    char *imgURIStr = GetImageURI();
-
-    nsCOMPtr<nsIProperties> imgProperties;
-    rv = GetImageProperties(imgURIStr, getter_AddRefs(imgProperties));
-    NS_ENSURE_SUCCESS(rv, NULL);
-    if (imgProperties) {
-        nsCOMPtr<nsISupportsCString> typeCString;
-        imgProperties->Get("type",
-                           NS_GET_IID(nsISupportsCString),
-                           getter_AddRefs(typeCString));
-        if (typeCString) {
-            typeCString->GetData(mImageMimeType);
-        }
-    }
-
-    return mImageMimeType.Length() ? g_strdup(mImageMimeType.get()) : NULL;
-}
-
-char *
-GeckoDocumentObject::GetImageURI()
-{
-    if(!IsImage()) {
-        return NULL;
-    }
-
-    if(!mImageURI.Length()) {
-        nsresult rv;
-        nsString img;    
-        rv = mImage->GetSrc(img);
-        if (NS_FAILED(rv)) return NULL;
-
-        NS_UTF16ToCString (img, NS_CSTRING_ENCODING_UTF8, mImageURI);
-    }
-    return g_strdup(mImageURI.get());
-}
-
-bool
-GeckoDocumentObject::SaveImage(const char *filename)
-{
-    GeckoBrowserPersist browserPersist(mBrowser);
-    return browserPersist.SaveURI(mImageURI.get(), filename);
-}
diff --git a/browser/GeckoDocumentObject.h b/browser/GeckoDocumentObject.h
deleted file mode 100644
index 5f4069fc..00000000
--- a/browser/GeckoDocumentObject.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef __GECKO_DOCUMENT_OBJECT_H__
-#define __GECKO_DOCUMENT_OBJECT_H__
-
-#include <nsIDOMNode.h>
-#include <nsIDOMHTMLImageElement.h>
-
-#include "sugar-browser.h"
-
-class GeckoDocumentObject
-{
-public:
-    GeckoDocumentObject(SugarBrowser *browser, nsIDOMNode *node);
-    ~GeckoDocumentObject();
-
-    bool IsImage();
-    char *GetImageURI();
-    char *GetImageName();
-    char *GetImageMimeType();
-    bool SaveImage(const char *filename);
-private:
-    SugarBrowser                        *mBrowser;
-    nsCOMPtr<nsIDOMNode>                 mNode;
-    nsCOMPtr<nsIDOMHTMLImageElement>     mImage;
-    nsCString                            mImageURI;
-    nsCString                            mImageName;
-    nsCString                            mImageMimeType;
-protected:
-    /* additional members */
-};
-
-#endif // __GECKO_DOCUMENT_OBJECT_H__
diff --git a/browser/GeckoDownload.cpp b/browser/GeckoDownload.cpp
deleted file mode 100644
index 2ec1fe4e..00000000
--- a/browser/GeckoDownload.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-#include "config.h"
-
-#include <nsIFactory.h>
-#include <nsIFile.h>
-#include <nsIFileURL.h>
-#include <nsServiceManagerUtils.h>
-#include <nsIMIMEService.h>
-
-#include "sugar-download-manager.h"
-
-#include "GeckoDownload.h"
-
-#define APPLICATION_OCTET_STREAM "application/octet-stream"
-
-class GeckoDownload : public nsITransfer
-{
-public:
-    GeckoDownload();
-	virtual ~GeckoDownload();
-
-	NS_DECL_ISUPPORTS
-	NS_DECL_NSIWEBPROGRESSLISTENER
-	NS_DECL_NSIWEBPROGRESSLISTENER2
-	NS_DECL_NSITRANSFER
-
-protected:
-	nsIURI			*mSource;
-	nsCString		mTargetFileName;
-	nsIMIMEInfo		*mMIMEInfo;
-	nsILocalFile	*mTempFile;
-};
-
-GeckoDownload::GeckoDownload ()
-{
-}
-
-GeckoDownload::~GeckoDownload ()
-{
-}
-
-NS_IMPL_ISUPPORTS3 (GeckoDownload,
-					nsIWebProgressListener,
-					nsIWebProgressListener2,
-					nsITransfer)
-
-NS_IMETHODIMP
-GeckoDownload::Init (nsIURI *aSource,
-					 nsIURI *aTarget,
-					 const nsAString &aDisplayName,
-					 nsIMIMEInfo *aMIMEInfo,
-					 PRTime aStartTime,
-					 nsILocalFile *aTempFile,
-					 nsICancelable *aCancelable)
-{
-    mSource = aSource;
-    mMIMEInfo = aMIMEInfo;
-    mTempFile = aTempFile;
-
-    nsresult rv;
-
-    nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aTarget);
-    NS_ENSURE_TRUE(fileURL, NS_ERROR_FAILURE);
-
-    nsCOMPtr<nsIFile> file;
-    rv = fileURL->GetFile(getter_AddRefs(file));
-    NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
-
-    file->GetNativePath (mTargetFileName);
-
-    return NS_OK; 
-}
-
-NS_IMETHODIMP 
-GeckoDownload::OnStateChange(nsIWebProgress *aWebProgress,
-	                          nsIRequest *aRequest,
-                              PRUint32 aStateFlags,
-                              nsresult aStatus)
-{
-    SugarDownloadManager *download_manager = sugar_get_download_manager();
-
-    if(aStateFlags == STATE_START) {
-
-        nsCString url;
-        nsCString mimeType;
-
-        mMIMEInfo->GetMIMEType(mimeType);
-        mSource->GetSpec(url);
-
-        /* If the file is application/octet-stream, look up a better mime type
-           from the extension. */
-        if(mimeType.Equals(APPLICATION_OCTET_STREAM)) {
-            nsresult rv;
-            nsCOMPtr<nsIMIMEService> mimeService(
-                do_GetService("@mozilla.org/mime;1", &rv));
-            NS_ENSURE_SUCCESS(rv, rv);
-            
-            const char *fileExt = strrchr(mTargetFileName.get(), '.');
-            if(fileExt) {
-                nsCString contentType;
-
-                mimeService->GetTypeFromExtension(nsCString(fileExt),
-                                                   contentType);
-                if(!contentType.IsEmpty()) {
-                    mimeType = contentType;
-                }
-            }
-        }
-
-        sugar_download_manager_download_started(download_manager,
-                                                 url.get(),
-                                                 mimeType.get(),
-                                                 mTargetFileName.get());
-
-    } else if(aStateFlags == STATE_STOP) {
-        
-        if(NS_SUCCEEDED(aStatus)) {
-            sugar_download_manager_download_completed(download_manager,
-                                                       mTargetFileName.get());
-        } else {
-            sugar_download_manager_download_cancelled(download_manager,
-                                                       mTargetFileName.get());
-        }
-    }
-
-    return NS_OK; 
-}
-
-NS_IMETHODIMP
-GeckoDownload::OnProgressChange (nsIWebProgress *aWebProgress,
-								 nsIRequest *aRequest,
-								 PRInt32 aCurSelfProgress,
-								 PRInt32 aMaxSelfProgress,
-								 PRInt32 aCurTotalProgress,
-								 PRInt32 aMaxTotalProgress)
-{
-	return OnProgressChange64 (aWebProgress,
-							   aRequest,
-							   aCurSelfProgress,
-							   aMaxSelfProgress,
-							   aCurTotalProgress,
-							   aMaxTotalProgress);
-}
-
-NS_IMETHODIMP
-GeckoDownload::OnProgressChange64 (nsIWebProgress *aWebProgress,
-								   nsIRequest *aRequest,
-								   PRInt64 aCurSelfProgress,
-								   PRInt64 aMaxSelfProgress,
-								   PRInt64 aCurTotalProgress,
-								   PRInt64 aMaxTotalProgress)
-{	
-	SugarDownloadManager *download_manager = sugar_get_download_manager ();
-	PRInt32 percentComplete =
-		(PRInt32)(((float)aCurSelfProgress / (float)aMaxSelfProgress) * 100.0);
-
-	sugar_download_manager_update_progress (download_manager,
-											mTargetFileName.get (),
-											percentComplete);
-
-	return NS_OK;
-}
-
-NS_IMETHODIMP
-GeckoDownload::OnLocationChange (nsIWebProgress *aWebProgress,
-								 nsIRequest *aRequest,
-								 nsIURI *location)
-{
-	return NS_OK;
-}
-
-NS_IMETHODIMP 
-GeckoDownload::OnStatusChange (nsIWebProgress *aWebProgress,
-							   nsIRequest *aRequest,
-							   nsresult aStatus, 
-							   const PRUnichar *aMessage)
-{
-	return NS_OK;
-}
-
-NS_IMETHODIMP 
-GeckoDownload::OnSecurityChange (nsIWebProgress *aWebProgress,
-								 nsIRequest *aRequest,
-								 PRUint32 state)
-{
-	return NS_OK;
-}
-
-NS_IMETHODIMP
-GeckoDownload::OnRefreshAttempted (nsIWebProgress *aWebProgress,
-                                   nsIURI *aRefreshURI,
-                                   PRInt32 aMillis,
-                                   PRBool aSameURI,
-                                   PRBool *_retval)
-{
-	return NS_OK;
-}
-
-//*****************************************************************************
-// GeckoDownloadFactory
-//*****************************************************************************
-
-class GeckoDownloadFactory : public nsIFactory {
-public:
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSIFACTORY
-
-    GeckoDownloadFactory();
-    virtual ~GeckoDownloadFactory();
-};
-
-//*****************************************************************************
-
-NS_IMPL_ISUPPORTS1(GeckoDownloadFactory, nsIFactory)
-
-GeckoDownloadFactory::GeckoDownloadFactory() {
-}
-
-GeckoDownloadFactory::~GeckoDownloadFactory() {
-}
-
-NS_IMETHODIMP
-GeckoDownloadFactory::CreateInstance(nsISupports *aOuter, const nsIID & aIID, void **aResult)
-{
-    NS_ENSURE_ARG_POINTER(aResult);
-
-    *aResult = NULL;
-    GeckoDownload *inst = new GeckoDownload;
-    if (!inst)
-        return NS_ERROR_OUT_OF_MEMORY;
-
-    nsresult rv = inst->QueryInterface(aIID, aResult);
-    if (rv != NS_OK) {
-        // We didn't get the right interface, so clean up
-        delete inst;
-    }
-
-    return rv;
-}
-
-NS_IMETHODIMP
-GeckoDownloadFactory::LockFactory(PRBool lock)
-{
-    return NS_OK;
-}
-
-//*****************************************************************************
-
-nsresult
-NS_NewGeckoDownloadFactory(nsIFactory** aFactory)
-{
-    NS_ENSURE_ARG_POINTER(aFactory);
-    *aFactory = nsnull;
-
-    GeckoDownloadFactory *result = new GeckoDownloadFactory;
-    if (!result)
-        return NS_ERROR_OUT_OF_MEMORY;
-
-    NS_ADDREF(result);
-    *aFactory = result;
-
-    return NS_OK;
-}
diff --git a/browser/GeckoDownload.h b/browser/GeckoDownload.h
deleted file mode 100644
index dd788f0a..00000000
--- a/browser/GeckoDownload.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef __GECKO_DOWNLOAD_H__
-#define __GECKO_DOWNLOAD_H__
-
-#include <nsCOMPtr.h>
-#include <nsIInterfaceRequestor.h>
-#include <nsITransfer.h>
-#include <nsIWebProgressListener.h>
-#include <nsIMIMEInfo.h>
-#include <nsIURL.h>
-#include <nsILocalFile.h>
-#include <nsStringAPI.h>
-
-#define GECKODOWNLOAD_CID							 \
-{ /* b1813bbe-6518-11db-967e-00e08161165f */         \
-	0xb1813bbe,                                      \
-	0x6518,                                          \
-	0x11db,                                          \
-	{0x96, 0x7e, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f} \
-}
-
-class nsIFactory;
-
-extern "C" NS_EXPORT nsresult NS_NewGeckoDownloadFactory(nsIFactory** aFactory);
-
-#endif // __GECKO_DOWNLOAD_H__
diff --git a/browser/GeckoDragDropHooks.cpp b/browser/GeckoDragDropHooks.cpp
deleted file mode 100644
index 995ee87f..00000000
--- a/browser/GeckoDragDropHooks.cpp
+++ /dev/null
@@ -1,214 +0,0 @@
-#include <config.h>
-
-#include <sys/time.h>
-#include <time.h>
-
-#include <glib.h>
-#include <nsStringAPI.h>
-#include <nsCOMPtr.h>
-#include <nsITransferable.h>
-#include <nsISupportsPrimitives.h>
-#include <nsIDOMEventTarget.h>
-#include <nsComponentManagerUtils.h>
-#include <nsServiceManagerUtils.h>
-#include <nsIInterfaceRequestorUtils.h>
-#include <nsIDOMMouseEvent.h>
-#include <nsIMIMEService.h>
-
-#include "GeckoDragDropHooks.h"
-#include "GeckoDocumentObject.h"
-
-#define TEXT_URI_LIST   "text/uri-list"
-#define TEXT_X_MOZ_URL  "text/x-moz-url"
-#define FILE_LOCALHOST  "file://"
-
-//*****************************************************************************
-// UriListDataProvider
-//*****************************************************************************
-
-class UriListDataProvider : public nsIFlavorDataProvider
-{
-public:
-    UriListDataProvider(GeckoDocumentObject *mDocumentObject);
-    virtual ~UriListDataProvider();
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSIFLAVORDATAPROVIDER
-private:
-    GeckoDocumentObject *mDocumentObject;
-    nsCString            mFilePath;
-};
-
-//*****************************************************************************
-
-NS_IMPL_ISUPPORTS1(UriListDataProvider, nsIFlavorDataProvider)                                                   
-
-UriListDataProvider::UriListDataProvider(GeckoDocumentObject *documentObject)
-    :   mDocumentObject(documentObject)
-{
-}
-
-UriListDataProvider::~UriListDataProvider()
-{
-    if(mFilePath.Length()) {
-        remove(mFilePath.get());
-    }
-    
-    delete mDocumentObject;
-}
-
-NS_IMETHODIMP
-UriListDataProvider::GetFlavorData(nsITransferable *aTransferable,
-                                   const char *aFlavor, nsISupports **aData,
-                                   PRUint32 *aDataLen)
-{
-    NS_ENSURE_ARG_POINTER(aData && aDataLen);
-
-    nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
-    char *image_name;
-    char *mime_type;
-    char *file_ext;
-    nsCString mime_ext;
-    timeval timestamp;
-
-    *aData = nsnull;
-    *aDataLen = 0;
-    
-    if(g_ascii_strcasecmp(aFlavor, TEXT_URI_LIST) != 0) {
-        return rv;
-    }
-
-    gettimeofday(&timestamp, NULL);
-    
-    mFilePath.Append(g_get_tmp_dir());
-    mFilePath.Append("/");
-    mFilePath.AppendInt(timestamp.tv_sec);
-    mFilePath.AppendInt(timestamp.tv_usec);
-
-    image_name = mDocumentObject->GetImageName();
-    file_ext = strrchr(image_name, '.');
-    mime_type = mDocumentObject->GetImageMimeType();
-    
-    nsCOMPtr<nsIMIMEService> mimeService(do_GetService("@mozilla.org/mime;1",
-                                                       &rv));
-    NS_ENSURE_SUCCESS(rv, rv);
-    rv = mimeService->GetPrimaryExtension(nsCString(mime_type),
-                                          EmptyCString(),
-                                          mime_ext);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if(!file_ext) {
-        mFilePath.Append(image_name);
-        mFilePath.Append(".");
-        mFilePath.Append(mime_ext);    
-    } else if(strcmp(file_ext, mime_ext.get())) {
-        image_name[strlen(file_ext)] = 0;
-        mFilePath.Append(image_name);
-        mFilePath.Append(".");
-        mFilePath.Append(mime_ext);
-    } else {
-        mFilePath.Append(image_name);
-    }
-
-    g_free(mime_type);
-    g_free(image_name);
-
-    if(!mDocumentObject->SaveImage(mFilePath.get())) {
-        return NS_ERROR_FAILURE;
-    }
-
-    nsCString localURI(FILE_LOCALHOST);
-    localURI.Append(mFilePath);
-
-    nsString localURI16;
-    NS_CStringToUTF16(localURI, NS_CSTRING_ENCODING_UTF8, localURI16);
-
-    nsCOMPtr<nsISupportsString> localURIData(do_CreateInstance(
-                "@mozilla.org/supports-string;1", &rv));
-    if(NS_FAILED(rv)) return rv;
-
-    rv = localURIData->SetData(localURI16);
-    if(NS_FAILED(rv)) return rv;
-
-    CallQueryInterface(localURIData, aData);
-    *aDataLen = sizeof(nsISupportsString*);
-
-    // FIXME: Why do we need this? Is there a leak in mozilla?
-    this->Release();
-
-    return rv;
-}
-
-//*****************************************************************************
-// GeckoDragDropHooks
-//*****************************************************************************
-
-NS_IMPL_ISUPPORTS1(GeckoDragDropHooks, nsIClipboardDragDropHooks)
-
-GeckoDragDropHooks::GeckoDragDropHooks(SugarBrowser *browser)
-    :   mBrowser(browser)
-{
-}
-
-GeckoDragDropHooks::~GeckoDragDropHooks()
-{
-}
-
-NS_IMETHODIMP
-GeckoDragDropHooks::AllowStartDrag(nsIDOMEvent *event, PRBool *_retval)
-{
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-GeckoDragDropHooks::AllowDrop(nsIDOMEvent *event, nsIDragSession *session,
-                              PRBool *_retval)
-{
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-GeckoDragDropHooks::OnCopyOrDrag(nsIDOMEvent *aEvent, nsITransferable *trans,
-                                 PRBool *_retval)
-{
-    nsresult rv;
-
-    *_retval = true;
-
-    nsCOMPtr<nsIDOMMouseEvent> mouseEvent;
-    mouseEvent = do_QueryInterface(aEvent, &rv);
-    if(NS_FAILED(rv)) return rv;
-
-    nsCOMPtr<nsIDOMEventTarget> eventTarget;
-    rv = mouseEvent->GetTarget(getter_AddRefs(eventTarget));
-    if(NS_FAILED(rv)) return rv;
-
-    nsCOMPtr<nsIDOMNode> targetNode;
-    targetNode = do_QueryInterface(eventTarget, &rv);
-    if(NS_FAILED(rv)) return rv;
-
-    GeckoDocumentObject *documentObject = new GeckoDocumentObject(mBrowser,
-                                                                  targetNode);
-    if(documentObject->IsImage()) {
-        rv = trans->RemoveDataFlavor(TEXT_X_MOZ_URL);
-        if(NS_FAILED(rv)) return rv;
-
-        rv = trans->AddDataFlavor(TEXT_URI_LIST);
-        if(NS_FAILED(rv)) return rv;
-
-        UriListDataProvider *rawPtr = new UriListDataProvider(documentObject);
-        nsCOMPtr<nsISupports> dataProvider(do_QueryInterface(rawPtr, &rv));
-        if(NS_FAILED(rv)) return rv;
-
-        rv = trans->SetTransferData(TEXT_URI_LIST, dataProvider, 0);
-        if(NS_FAILED(rv)) return rv;
-    }
-
-    return rv;
-}
-
-NS_IMETHODIMP
-GeckoDragDropHooks::OnPasteOrDrop(nsIDOMEvent *event, nsITransferable *trans,
-                                  PRBool *_retval)
-{
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
diff --git a/browser/GeckoDragDropHooks.h b/browser/GeckoDragDropHooks.h
deleted file mode 100644
index c551c0e5..00000000
--- a/browser/GeckoDragDropHooks.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef __GECKO_DRAG_DROP_HOOKS_H__
-#define __GECKO_DRAG_DROP_HOOKS_H__
-
-#include <nsIClipboardDragDropHooks.h>
-
-#include "sugar-browser.h"
-
-class GeckoDragDropHooks : public nsIClipboardDragDropHooks
-{
-public:
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSICLIPBOARDDRAGDROPHOOKS
-
-    GeckoDragDropHooks(SugarBrowser *browser);
-
-private:
-    ~GeckoDragDropHooks();
-
-    SugarBrowser *mBrowser;
-
-protected:
-    /* additional members */
-};
-
-#endif // __GECKO_DRAG_DROP_HOOKS_H__
diff --git a/browser/Makefile.am b/browser/Makefile.am
deleted file mode 100644
index 8d398d45..00000000
--- a/browser/Makefile.am
+++ /dev/null
@@ -1,83 +0,0 @@
-SUBDIRS = components
-
-libsugarbrowser_la_CPPFLAGS =					\
-	$(WARN_CFLAGS)						\
-	$(LIB_CFLAGS)						\
-	$(GECKO_CFLAGS)						\
-	$(NSPR_CFLAGS)						\
-	-I$(MOZILLA_INCLUDE_DIR)/chrome				\
-	-I$(MOZILLA_INCLUDE_DIR)/commandhandler			\
-	-I$(MOZILLA_INCLUDE_DIR)/content			\
-	-I$(MOZILLA_INCLUDE_DIR)/dom				\
-	-I$(MOZILLA_INCLUDE_DIR)/docshell			\
-	-I$(MOZILLA_INCLUDE_DIR)/exthandler			\
-	-I$(MOZILLA_INCLUDE_DIR)/gtkembedmoz			\
-	-I$(MOZILLA_INCLUDE_DIR)/imglib2			\
-	-I$(MOZILLA_INCLUDE_DIR)/mimetype   			\
-	-I$(MOZILLA_INCLUDE_DIR)/necko				\
-	-I$(MOZILLA_INCLUDE_DIR)/pref				\
-	-I$(MOZILLA_INCLUDE_DIR)/shistory			\
-	-I$(MOZILLA_INCLUDE_DIR)/uriloader			\
-	-I$(MOZILLA_INCLUDE_DIR)/webbrwsr			\
-	-I$(MOZILLA_INCLUDE_DIR)/webbrowserpersist		\
-	-I$(MOZILLA_INCLUDE_DIR)/widget				\
-	-I$(MOZILLA_INCLUDE_DIR)/xpcom				\
-	-I$(top_builddir)/browser/components/sessionstore	\
-	-I$(top_builddir)/browser/components/browserhelper	\
-	-DPLUGIN_DIR=\"$(libdir)/mozilla/plugins\"		\
-	-DSHARE_DIR=\"$(pkgdatadir)\"
-	
-noinst_LTLIBRARIES = libsugarbrowser.la
-
-libsugarbrowser_la_LIBADD = \
-	$(LIB_LIBS) 		\
-	$(GECKO_LIBS)
-
-libsugarbrowser_la_SOURCES =		\
-	$(BUILT_SOURCES)		\
-	GeckoBrowserPersist.h		\
-	GeckoBrowserPersist.cpp		\
-	GeckoContentHandler.h		\
-	GeckoContentHandler.cpp		\
-	GeckoDocumentObject.h		\
-	GeckoDocumentObject.cpp		\
-	GeckoDirectoryProvider.h	\
-	GeckoDirectoryProvider.cpp	\
-	GeckoDragDropHooks.h		\
-	GeckoDragDropHooks.cpp		\
-	GeckoDownload.h			\
-	GeckoDownload.cpp		\
-	sugar-address-entry.c		\
-	sugar-address-entry.h		\
-	sugar-browser.h			\
-	sugar-browser.cpp		\
-	sugar-download.h		\
-	sugar-download.c		\
-	sugar-download-manager.h	\
-	sugar-download-manager.c
-
-BUILT_SOURCES = 		\
-	sugar-marshal.c		\
-	sugar-marshal.h
-
-stamp_files = \
-	stamp-sugar-marshal.c		\
-	stamp-sugar-marshal.h
-
-sugar-marshal.c: stamp-sugar-marshal.c
-	@true
-stamp-sugar-marshal.c: sugar-marshal.list
-	$(GLIB_GENMARSHAL) --prefix=sugar_marshal $(srcdir)/sugar-marshal.list --header --body > sugar-marshal.c \
-	&& echo timestamp > $(@F)
-
-sugar-marshal.h: stamp-sugar-marshal.h
-	@true
-stamp-sugar-marshal.h: sugar-marshal.list
-	$(GLIB_GENMARSHAL) --prefix=sugar_marshal $(srcdir)/sugar-marshal.list --header > sugar-marshal.h \
-	&& echo timestamp > $(@F)
-
-CLEANFILES = $(stamp_files) $(BUILT_SOURCES)
-DISTCLEANFILES = $(stamp_files) $(BUILT_SOURCES)
-MAINTAINERCLEANFILES = $(stamp_files) $(BUILT_SOURCES)
-
-EXTRA_DIST = sugar-marshal.list
diff --git a/browser/components/Makefile.am b/browser/components/Makefile.am
deleted file mode 100644
index 765dbeca..00000000
--- a/browser/components/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-SUBDIRS = browserhelper sessionstore
diff --git a/browser/components/browserhelper/.gitignore b/browser/components/browserhelper/.gitignore
deleted file mode 100644
index f722dc50..00000000
--- a/browser/components/browserhelper/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-nsIBrowserHelper.h
-nsIBrowserHelper.xpt
-stamp-nsIBrowserHelper.h
-stamp-nsIBrowserHelper.xpt
diff --git a/browser/components/browserhelper/Makefile.am b/browser/components/browserhelper/Makefile.am
deleted file mode 100644
index 0fda2f8a..00000000
--- a/browser/components/browserhelper/Makefile.am
+++ /dev/null
@@ -1,32 +0,0 @@
-sessionstoredir = $(pkgdatadir)/mozilla/components
-
-sessionstore_DATA =		\
-	nsIBrowserHelper.xpt	\
-	nsBrowserHelper.js
-
-BUILT_SOURCES = \
-	nsIBrowserHelper.xpt	\
-	nsIBrowserHelper.h
-
-stamp_files = \
-	stamp-nsIBrowserHelper.xpt	\
-	stamp-nsIBrowserHelper.h
-
-nsIBrowserHelper.xpt: stamp-nsIBrowserHelper.xpt
-	@true
-stamp-nsIBrowserHelper.xpt: nsIBrowserHelper.idl
-	$(XPIDL) -m typelib -w -v -I $(MOZILLA_IDL_DIR) -e nsIBrowserHelper.xpt \
-	$(srcdir)/nsIBrowserHelper.idl \
-	&& echo timestamp > $(@F)
-
-nsIBrowserHelper.h: stamp-nsIBrowserHelper.h
-	@true
-stamp-nsIBrowserHelper.h: nsIBrowserHelper.idl
-	$(XPIDL) -m header -w -v -I $(MOZILLA_IDL_DIR) -e nsIBrowserHelper.h \
-	$(srcdir)/nsIBrowserHelper.idl \
-	&& echo timestamp > $(@F)
-
-CLEANFILES = $(stamp_files) $(BUILT_SOURCES)
-DISTCLEANFILES = $(stamp_files) $(BUILT_SOURCES)
-MAINTAINERCLEANFILES = $(stamp_files) $(BUILT_SOURCES)
-EXTRA_DIST = nsIBrowserHelper.idl nsBrowserHelper.js
diff --git a/browser/components/browserhelper/nsBrowserHelper.js b/browser/components/browserhelper/nsBrowserHelper.js
deleted file mode 100644
index f726ddff..00000000
--- a/browser/components/browserhelper/nsBrowserHelper.js
+++ /dev/null
@@ -1,100 +0,0 @@
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-
-const CID = Components.ID("{475e1194-92bc-4e03-92f3-5ad6ccddaca3}");
-const CONTRACT_ID = "@laptop.org/browser/browserhelper;1";
-const CLASS_NAME = "Browser Helper";
-
-var browsers = [];
-
-function BrowserHelperService() {
-}
-
-BrowserHelperService.prototype = {
-
-/* ........ nsIBrowserHelper API .............. */
-
-  getBrowser: function bh_getBrowser(aId) {
-    return browsers[aId]
-  },
-
-  registerBrowser: function bh_registerBrowser(aId, aBrowser) {
-    browsers[aId] = aBrowser;
-  },
-
-  unregisterBrowser: function bh_unregisterBrowser(aId) {
-    browsers.pop(aId)
-  },
-
-  QueryInterface: function(aIID) {
-    if (!aIID.equals(Ci.nsISupports) && 
-      !aIID.equals(Ci.nsIBrowserHelper)) {
-      Components.returnCode = Cr.NS_ERROR_NO_INTERFACE;
-      return null;
-    }
-    
-    return this;
-  }
-}
-
-/* :::::::: Service Registration & Initialization ::::::::::::::: */
-
-/* ........ nsIModule .............. */
-
-const BrowserHelperModule = {
-
-  getClassObject: function(aCompMgr, aCID, aIID) {
-    if (aCID.equals(CID)) {
-      return BrowserHelperFactory;
-    }
-    
-    Components.returnCode = Cr.NS_ERROR_NOT_REGISTERED;
-    return null;
-  },
-
-  registerSelf: function(aCompMgr, aFileSpec, aLocation, aType) {
-    aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
-    aCompMgr.registerFactoryLocation(CID, CLASS_NAME, CONTRACT_ID, aFileSpec, aLocation, aType);
-  },
-
-  unregisterSelf: function(aCompMgr, aLocation, aType) {
-    aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
-    aCompMgr.unregisterFactoryLocation(CID, aLocation);
-  },
-
-  canUnload: function(aCompMgr) {
-    return true;
-  }
-}
-
-/* ........ nsIFactory .............. */
-
-const BrowserHelperFactory = {
-
-  createInstance: function(aOuter, aIID) {
-    if (aOuter != null) {
-      Components.returnCode = Cr.NS_ERROR_NO_AGGREGATION;
-      return null;
-    }
-    
-    return (new BrowserHelperService()).QueryInterface(aIID);
-  },
-
-  lockFactory: function(aLock) { },
-
-  QueryInterface: function(aIID) {
-    if (!aIID.equals(Ci.nsISupports) && !aIID.equals(Ci.nsIModule) &&
-        !aIID.equals(Ci.nsIFactory) && !aIID.equals(Ci.nsIBrowserHelper)) {
-      Components.returnCode = Cr.NS_ERROR_NO_INTERFACE;
-      return null;
-    }
-    
-    return this;
-  }
-};
-
-function NSGetModule(aComMgr, aFileSpec) {
-  dump("nsBrowserHelper: NSGetModule\n")
-  return BrowserHelperModule;
-}
diff --git a/browser/components/browserhelper/nsIBrowserHelper.idl b/browser/components/browserhelper/nsIBrowserHelper.idl
deleted file mode 100644
index abe52b3c..00000000
--- a/browser/components/browserhelper/nsIBrowserHelper.idl
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "nsISupports.idl"
-
-interface nsIWebBrowser;
-
-[scriptable, uuid(475e1194-92bc-4e03-92f3-5ad6ccddaca3)]
-interface nsIBrowserHelper : nsISupports
-{
-  nsIWebBrowser getBrowser(in long id);
-
-  void registerBrowser(in long id, in nsIWebBrowser browser);
-
-  void unregisterBrowser(in long id); 
-};
diff --git a/browser/components/sessionstore/.gitignore b/browser/components/sessionstore/.gitignore
deleted file mode 100644
index 3e245c10..00000000
--- a/browser/components/sessionstore/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-nsISessionStore.h
-nsISessionStore.xpt
-stamp-nsISessionStore.h
-stamp-nsISessionStore.xpt
diff --git a/browser/components/sessionstore/Makefile.am b/browser/components/sessionstore/Makefile.am
deleted file mode 100644
index 75f46ff1..00000000
--- a/browser/components/sessionstore/Makefile.am
+++ /dev/null
@@ -1,32 +0,0 @@
-sessionstoredir = $(pkgdatadir)/mozilla/components
-
-sessionstore_DATA =		\
-	nsISessionStore.xpt	\
-	nsSessionStore.js
-
-BUILT_SOURCES = \
-	nsISessionStore.xpt	\
-	nsISessionStore.h
-
-stamp_files = \
-	stamp-nsISessionStore.xpt	\
-	stamp-nsISessionStore.h
-
-nsISessionStore.xpt: stamp-nsISessionStore.xpt
-	@true
-stamp-nsISessionStore.xpt: nsISessionStore.idl
-	$(XPIDL) -m typelib -w -v -I $(MOZILLA_IDL_DIR) -e nsISessionStore.xpt \
-	$(srcdir)/nsISessionStore.idl \
-	&& echo timestamp > $(@F)
-
-nsISessionStore.h: stamp-nsISessionStore.h
-	@true
-stamp-nsISessionStore.h: nsISessionStore.idl
-	$(XPIDL) -m header -w -v -I $(MOZILLA_IDL_DIR) -e nsISessionStore.h \
-	$(srcdir)/nsISessionStore.idl \
-	&& echo timestamp > $(@F)
-
-CLEANFILES = $(stamp_files) $(BUILT_SOURCES)
-DISTCLEANFILES = $(stamp_files) $(BUILT_SOURCES)
-MAINTAINERCLEANFILES = $(stamp_files) $(BUILT_SOURCES)
-EXTRA_DIST = nsISessionStore.idl nsSessionStore.js
diff --git a/browser/components/sessionstore/nsISessionStore.idl b/browser/components/sessionstore/nsISessionStore.idl
deleted file mode 100644
index 97f9668e..00000000
--- a/browser/components/sessionstore/nsISessionStore.idl
+++ /dev/null
@@ -1,63 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Session Restore component.
- *
- * The Initial Developer of the Original Code is
- * Simon Bünzli <zeniko@gmail.com>
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Dietrich Ayala <dietrich@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsISupports.idl"
-
-interface nsIWebBrowser;
-
-/**
- * nsISessionStore keeps track of the current browsing state - i.e.
- * tab history, cookies, scroll state, form data, POSTDATA and window features
- * - and allows to restore everything into one window.
- */
-
-[scriptable, uuid(11852a90-20de-11db-a98b-0800200c9a66)]
-interface nsISessionStore : nsISupports
-{
-  /**
-   * @param aBrowser     is the browser whose state is to be returned.
-   * 
-   * @return a JSON string representing the session state.
-   */
-  AString getBrowserState(in nsIWebBrowser aBrowser);
-
-  /**
-   * @param aBrowser        is the browser whose state is to be set.
-   * @param aState          is a JSON string representing a session state.
-   */
-  void setBrowserState(in nsIWebBrowser aBrowser, in AString aState);
-};
diff --git a/browser/components/sessionstore/nsSessionStore.js b/browser/components/sessionstore/nsSessionStore.js
deleted file mode 100644
index 0ce34017..00000000
--- a/browser/components/sessionstore/nsSessionStore.js
+++ /dev/null
@@ -1,541 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the nsSessionStore component.
- *
- * The Initial Developer of the Original Code is
- * Simon Bünzli <zeniko@gmail.com>
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Dietrich Ayala <autonome@gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/*
- * Heavily adapted to xulrunner for the OLPC from the firefox code in
- * http://lxr.mozilla.org/seamonkey/source/browser/components/sessionstore.
- *
- * May 2007 Tomeu Vizoso
- */
-
-/**
- * Session Storage and Restoration
- * 
- * Overview
- * This service keeps track of a user's session, storing the various bits
- * required to return the browser to it's current state. The relevant data is 
- * stored in memory, and is periodically saved to disk in a file in the 
- * profile directory. The service is started at first window load, in
- * delayedStartup, and will restore the session from the data received from
- * the nsSessionStartup service.
- */
-
-/* :::::::: Constants and Helpers ::::::::::::::: */
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-
-const CID = Components.ID("{5280606b-2510-4fe0-97ef-9b5a22eafe6b}");
-const CONTRACT_ID = "@mozilla.org/browser/sessionstore;1";
-const CLASS_NAME = "Browser Session Store Service";
-
-// sandbox to evaluate JavaScript code from non-trustable sources
-var EVAL_SANDBOX = new Components.utils.Sandbox("about:blank");
-
-function debug(aMsg) {
-  aMsg = ("SessionStore: " + aMsg).replace(/\S{80}/g, "$&\n");
-  Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
-                                     .logStringMessage(aMsg);
-}
-
-/* :::::::: The Service ::::::::::::::: */
-
-function SessionStoreService() {
-}
-
-SessionStoreService.prototype = {
-
-/* ........ nsISessionStore API .............. */
-
-  getBrowserState: function sss_getBrowserState(aBrowser) {
-    dump("nsSessionStore::getBrowserState\n")
-    return this._toJSONString(this._getWindowState(aBrowser));
-  },
-
-  setBrowserState: function sss_setBrowserState(aBrowser, aState) {
-    dump("nsSessionStore::setBrowserState\n")
-    this.restoreWindow(aBrowser, "(" + aState + ")");
-  },
-
-/* ........ Saving Functionality .............. */
-
-  /**
-   * Store all session data for a window
-   * @param aSHistory
-   *        nsISHistory reference
-   */
-  _saveWindowHistory: function sss_saveWindowHistory(aSHistory) {
-    var entries = [];
-    dump("nsSessionStore._saveWindowHistory " + aSHistory.count);
-    for (var i = 0; i < aSHistory.count; i++) {
-      entries.push(this._serializeHistoryEntry(aSHistory.getEntryAtIndex(i, false)));
-    }
-
-    return entries;
-  },
-
-  /**
-   * Get an object that is a serialized representation of a History entry
-   * Used for data storage
-   * @param aEntry
-   *        nsISHEntry instance
-   * @returns object
-   */
-  _serializeHistoryEntry: function sss_serializeHistoryEntry(aEntry) {
-    var entry = { url: aEntry.URI.spec, children: [] };
-    
-    if (aEntry.title && aEntry.title != entry.url) {
-      entry.title = aEntry.title;
-    }
-    if (aEntry.isSubFrame) {
-      entry.subframe = true;
-    }
-    if (!(aEntry instanceof Ci.nsISHEntry)) {
-      return entry;
-    }
-    
-    var cacheKey = aEntry.cacheKey;
-    if (cacheKey && cacheKey instanceof Ci.nsISupportsPRUint32) {
-      entry.cacheKey = cacheKey.data;
-    }
-    entry.ID = aEntry.ID;
-    
-    var x = {}, y = {};
-    aEntry.getScrollPosition(x, y);
-    entry.scroll = x.value + "," + y.value;
-    
-    try {
-      var prefPostdata = this._prefBranch.getIntPref("sessionstore.postdata");
-      if (prefPostdata && aEntry.postData && this._checkPrivacyLevel(aEntry.URI.schemeIs("https"))) {
-        aEntry.postData.QueryInterface(Ci.nsISeekableStream).
-                        seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
-        var stream = Cc["@mozilla.org/scriptableinputstream;1"].
-                     createInstance(Ci.nsIScriptableInputStream);
-        stream.init(aEntry.postData);
-        var postdata = stream.read(stream.available());
-        if (prefPostdata == -1 || postdata.replace(/^(Content-.*\r\n)+(\r\n)*/, "").length <= prefPostdata) {
-          entry.postdata = postdata;
-        }
-      }
-    }
-    catch (ex) { debug(ex); } // POSTDATA is tricky - especially since some extensions don't get it right
-    
-    if (!(aEntry instanceof Ci.nsISHContainer)) {
-      return entry;
-    }
-    
-    for (var i = 0; i < aEntry.childCount; i++) {
-      var child = aEntry.GetChildAt(i);
-      if (child) {
-        entry.children.push(this._serializeHistoryEntry(child));
-      }
-      else { // to maintain the correct frame order, insert a dummy entry 
-        entry.children.push({ url: "about:blank" });
-      }
-    }
-    
-    return entry;
-  },
-
-  /**
-   * serialize session data for a window 
-   * @param aBrowser
-   *        Browser reference
-   * @returns string
-   */
-  _getWindowState: function sss_getWindowState(aBrowser) {
-    dump("nsSessionStore::_getWindowState: " + aBrowser + "\n")
-    windowState = this._collectWindowData(aBrowser);
-
-    /*    
-    this._updateCookies(windowState);
-    */
-
-    return windowState;
-  },
-
-  _collectWindowData: function sss_collectWindowData(aBrowser) {
-    dump("nsSessionStore::_collectWindowData\n")
-    aBrowser.QueryInterface(Ci.nsIWebNavigation);
-    historyState = this._saveWindowHistory(aBrowser.sessionHistory);
-    /*
-    this._updateTextAndScrollData(aWindow);
-    this._updateCookieHosts(aWindow);
-    this._updateWindowFeatures(aWindow);
-    */
-    
-    return {history: historyState/*, textAndScroll: textAndScrollState*/};
-  },
-
-/* ........ Restoring Functionality .............. */
-
-  /**
-   * restore features to a single window
-   * @param aBrowser
-   *        Browser reference
-   * @param aState
-   *        JS object or its eval'able source
-   */
-  restoreWindow: function sss_restoreWindow(aBrowser, aState) {
-    try {
-      var winData = typeof aState == "string" ? this._safeEval(aState) : aState;
-    }
-    catch (ex) { // invalid state object - don't restore anything 
-      debug(ex);
-      dump(ex);
-      return;
-    }
-    
-    this.restoreHistoryPrecursor(aBrowser, winData.history);
-  },
-
-  /**
-   * Manage history restoration for a window
-   * @param aBrowser
-   *        Browser reference
-   * @param aHistoryData
-   *        History data to be restored
-   */
-  restoreHistoryPrecursor: function sss_restoreHistoryPrecursor(aBrowser, aHistoryData) {
-    /*
-    // make sure that all browsers and their histories are available
-    // - if one's not, resume this check in 100ms (repeat at most 10 times)
-    for (var t = aIx; t < aTabs.length; t++) {
-      try {
-        if (!tabbrowser.getBrowserForTab(aTabs[t]._tab).webNavigation.sessionHistory) {
-          throw new Error();
-        }
-      }
-      catch (ex) { // in case browser or history aren't ready yet 
-        if (aCount < 10) {
-          var restoreHistoryFunc = function(self) {
-            self.restoreHistoryPrecursor(aWindow, aTabs, aSelectTab, aIx, aCount + 1);
-          }
-          aWindow.setTimeout(restoreHistoryFunc, 100, this);
-          return;
-        }
-      }
-    }
-    */
-
-    // helper hash for ensuring unique frame IDs
-    var aIdMap = { used: {} };
-    this.restoreHistory(aBrowser, aHistoryData, aIdMap);
-  },
-
-  /**
-   * Restory history for a window
-   * @param aBrowser
-   *        Browser reference
-   * @param aHistoryData
-   *        History data to be restored
-   * @param aIdMap
-   *        Hash for ensuring unique frame IDs
-   */
-  restoreHistory: function sss_restoreHistory(aBrowser, aHistoryData, aIdMap) {
-    dump("nsSessionStore::restoreHistory\n")
-
-    aBrowser.QueryInterface(Ci.nsIWebNavigation);
-    aSHistory = aBrowser.sessionHistory;
-    aSHistory.QueryInterface(Ci.nsISHistoryInternal);
-    
-    if (aSHistory.count > 0) {
-      aSHistory.PurgeHistory(aSHistory.count);
-    }
-    
-    if (!aHistoryData) {
-      aHistoryData = [];
-    }
-    
-    for (var i = 0; i < aHistoryData.length; i++) {
-      aSHistory.addEntry(this._deserializeHistoryEntry(aHistoryData[i], aIdMap), true);
-    }
-    
-    /*
-    // make sure to reset the capabilities and attributes, in case this tab gets reused
-    var disallow = (aHistoryData.disallow)?aHistoryData.disallow.split(","):[];
-    CAPABILITIES.forEach(function(aCapability) {
-      browser.docShell["allow" + aCapability] = disallow.indexOf(aCapability) == -1;
-    });
-    Array.filter(tab.attributes, function(aAttr) {
-      return (_this.xulAttributes.indexOf(aAttr.name) > -1);
-    }).forEach(tab.removeAttribute, tab);
-    if (aHistoryData.xultab) {
-      aHistoryData.xultab.split(" ").forEach(function(aAttr) {
-        if (/^([^\s=]+)=(.*)/.test(aAttr)) {
-          tab.setAttribute(RegExp.$1, decodeURI(RegExp.$2));
-        }
-      });
-    }
-    */
-    try {
-      aBrowser.gotoIndex(aHistoryData.length - 1);
-    }
-    catch (ex) { dump(ex + "\n"); } // ignore an invalid aHistoryData.index
-  },
-
-  /**
-   * expands serialized history data into a session-history-entry instance
-   * @param aEntry
-   *        Object containing serialized history data for a URL
-   * @param aIdMap
-   *        Hash for ensuring unique frame IDs
-   * @returns nsISHEntry
-   */
-  _deserializeHistoryEntry: function sss_deserializeHistoryEntry(aEntry, aIdMap) {
-    var shEntry = Cc["@mozilla.org/browser/session-history-entry;1"].
-                  createInstance(Ci.nsISHEntry);
-    
-    var ioService = Cc["@mozilla.org/network/io-service;1"].
-                    getService(Ci.nsIIOService);
-    shEntry.setURI(ioService.newURI(aEntry.url, null, null));
-    shEntry.setTitle(aEntry.title || aEntry.url);
-    shEntry.setIsSubFrame(aEntry.subframe || false);
-    shEntry.loadType = Ci.nsIDocShellLoadInfo.loadHistory;
-    
-    if (aEntry.cacheKey) {
-      var cacheKey = Cc["@mozilla.org/supports-PRUint32;1"].
-                     createInstance(Ci.nsISupportsPRUint32);
-      cacheKey.data = aEntry.cacheKey;
-      shEntry.cacheKey = cacheKey;
-    }
-    if (aEntry.ID) {
-      // get a new unique ID for this frame (since the one from the last
-      // start might already be in use)
-      var id = aIdMap[aEntry.ID] || 0;
-      if (!id) {
-        for (id = Date.now(); aIdMap.used[id]; id++);
-        aIdMap[aEntry.ID] = id;
-        aIdMap.used[id] = true;
-      }
-      shEntry.ID = id;
-    }
-    
-    var scrollPos = (aEntry.scroll || "0,0").split(",");
-    scrollPos = [parseInt(scrollPos[0]) || 0, parseInt(scrollPos[1]) || 0];
-    shEntry.setScrollPosition(scrollPos[0], scrollPos[1]);
-    
-    if (aEntry.postdata) {
-      var stream = Cc["@mozilla.org/io/string-input-stream;1"].
-                   createInstance(Ci.nsIStringInputStream);
-      stream.setData(aEntry.postdata, -1);
-      shEntry.postData = stream;
-    }
-    
-    if (aEntry.children && shEntry instanceof Ci.nsISHContainer) {
-      for (var i = 0; i < aEntry.children.length; i++) {
-        shEntry.AddChild(this._deserializeHistoryEntry(aEntry.children[i], aIdMap), i);
-      }
-    }
-    
-    return shEntry;
-  },
-
-/* ........ Auxiliary Functions .............. */
-
-  /**
-   * don't save sensitive data if the user doesn't want to
-   * (distinguishes between encrypted and non-encrypted sites)
-   * @param aIsHTTPS
-   *        Bool is encrypted
-   * @returns bool
-   */
-  _checkPrivacyLevel: function sss_checkPrivacyLevel(aIsHTTPS) {
-    return this._prefBranch.getIntPref("sessionstore.privacy_level") < (aIsHTTPS ? PRIVACY_ENCRYPTED : PRIVACY_FULL);
-  },
-
-  /**
-   * safe eval'ing
-   */
-  _safeEval: function sss_safeEval(aStr) {
-    return Components.utils.evalInSandbox(aStr, EVAL_SANDBOX);
-  },
-
-  /**
-   * Converts a JavaScript object into a JSON string
-   * (see http://www.json.org/ for the full grammar).
-   *
-   * The inverse operation consists of eval("(" + JSON_string + ")");
-   * and should be provably safe.
-   *
-   * @param aJSObject is the object to be converted
-   * @return the object's JSON representation
-   */
-  _toJSONString: function sss_toJSONString(aJSObject) {
-    // these characters have a special escape notation
-    const charMap = { "\b": "\\b", "\t": "\\t", "\n": "\\n", "\f": "\\f",
-                      "\r": "\\r", '"': '\\"', "\\": "\\\\" };
-    // we use a single string builder for efficiency reasons
-    var parts = [];
-    
-    // this recursive function walks through all objects and appends their
-    // JSON representation to the string builder
-    function jsonIfy(aObj) {
-      if (typeof aObj == "boolean") {
-        parts.push(aObj ? "true" : "false");
-      }
-      else if (typeof aObj == "number" && isFinite(aObj)) {
-        // there is no representation for infinite numbers or for NaN!
-        parts.push(aObj.toString());
-      }
-      else if (typeof aObj == "string") {
-        aObj = aObj.replace(/[\\"\x00-\x1F\u0080-\uFFFF]/g, function($0) {
-          // use the special escape notation if one exists, otherwise
-          // produce a general unicode escape sequence
-          return charMap[$0] ||
-            "\\u" + ("0000" + $0.charCodeAt(0).toString(16)).slice(-4);
-        });
-        parts.push('"' + aObj + '"')
-      }
-      else if (aObj == null) {
-        parts.push("null");
-      }
-      else if (aObj instanceof Array || aObj instanceof EVAL_SANDBOX.Array) {
-        parts.push("[");
-        for (var i = 0; i < aObj.length; i++) {
-          jsonIfy(aObj[i]);
-          parts.push(",");
-        }
-        if (parts[parts.length - 1] == ",")
-          parts.pop(); // drop the trailing colon
-        parts.push("]");
-      }
-      else if (typeof aObj == "object") {
-        parts.push("{");
-        for (var key in aObj) {
-          jsonIfy(key.toString());
-          parts.push(":");
-          jsonIfy(aObj[key]);
-          parts.push(",");
-        }
-        if (parts[parts.length - 1] == ",")
-          parts.pop(); // drop the trailing colon
-        parts.push("}");
-      }
-      else {
-        throw new Error("No JSON representation for this object!");
-      }
-    }
-    jsonIfy(aJSObject);
-    
-    var newJSONString = parts.join(" ");
-    // sanity check - so that API consumers can just eval this string
-    if (/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
-      newJSONString.replace(/"(\\.|[^"\\])*"/g, "")
-    ))
-      throw new Error("JSON conversion failed unexpectedly!");
-    
-    return newJSONString;
-  },
-
-/* ........ QueryInterface .............. */
-
-  QueryInterface: function(aIID) {
-    if (!aIID.equals(Ci.nsISupports) && 
-      !aIID.equals(Ci.nsIObserver) && 
-      !aIID.equals(Ci.nsISupportsWeakReference) && 
-      !aIID.equals(Ci.nsIDOMEventListener) &&
-      !aIID.equals(Ci.nsISessionStore)) {
-      Components.returnCode = Cr.NS_ERROR_NO_INTERFACE;
-      return null;
-    }
-    
-    return this;
-  }
-};
-
-/* :::::::: Service Registration & Initialization ::::::::::::::: */
-
-/* ........ nsIModule .............. */
-
-const SessionStoreModule = {
-
-  getClassObject: function(aCompMgr, aCID, aIID) {
-    if (aCID.equals(CID)) {
-      return SessionStoreFactory;
-    }
-    
-    Components.returnCode = Cr.NS_ERROR_NOT_REGISTERED;
-    return null;
-  },
-
-  registerSelf: function(aCompMgr, aFileSpec, aLocation, aType) {
-    aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
-    aCompMgr.registerFactoryLocation(CID, CLASS_NAME, CONTRACT_ID, aFileSpec, aLocation, aType);
-  },
-
-  unregisterSelf: function(aCompMgr, aLocation, aType) {
-    aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
-    aCompMgr.unregisterFactoryLocation(CID, aLocation);
-  },
-
-  canUnload: function(aCompMgr) {
-    return true;
-  }
-}
-
-/* ........ nsIFactory .............. */
-
-const SessionStoreFactory = {
-
-  createInstance: function(aOuter, aIID) {
-    if (aOuter != null) {
-      Components.returnCode = Cr.NS_ERROR_NO_AGGREGATION;
-      return null;
-    }
-    
-    return (new SessionStoreService()).QueryInterface(aIID);
-  },
-
-  lockFactory: function(aLock) { },
-
-  QueryInterface: function(aIID) {
-    if (!aIID.equals(Ci.nsISupports) && !aIID.equals(Ci.nsIModule) &&
-        !aIID.equals(Ci.nsIFactory) && !aIID.equals(Ci.nsISessionStore)) {
-      Components.returnCode = Cr.NS_ERROR_NO_INTERFACE;
-      return null;
-    }
-    
-    return this;
-  }
-};
-
-function NSGetModule(aComMgr, aFileSpec) {
-  dump("nsSessionStore: NSGetModule\n")
-  return SessionStoreModule;
-}
diff --git a/browser/sugar-browser.cpp b/browser/sugar-browser.cpp
deleted file mode 100644
index 46501831..00000000
--- a/browser/sugar-browser.cpp
+++ /dev/null
@@ -1,962 +0,0 @@
-/*
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <config.h>
-
-#include "sugar-browser.h"
-#include "sugar-marshal.h"
-#include "GeckoContentHandler.h"
-#include "GeckoDownload.h"
-#include "GeckoDragDropHooks.h"
-#include "GeckoDocumentObject.h"
-#include "GeckoBrowserPersist.h"
-#include "GeckoDirectoryProvider.h"
-
-#include <gdk/gdkx.h>
-#include <gtkmozembed_internal.h>
-#include <nsCOMPtr.h>
-#include <nsIPrefService.h>
-#include <nsServiceManagerUtils.h>
-#include <nsStringAPI.h>
-#include <nsILocalFile.h>
-#include <nsIWebBrowser.h>
-#include <nsIWebBrowserFocus.h>
-#include <nsIWebBrowserPersist.h>
-#include <nsIDOMWindow.h>
-#include <nsIDOMWindowUtils.h>
-#include <nsIDOMDocument.h>
-#include <nsIDOMMouseEvent.h>
-#include <nsIGenericFactory.h>
-#include <nsIHelperAppLauncherDialog.h>
-#include <nsIComponentRegistrar.h>
-#include <nsIDOMNode.h>
-#include <nsIDOMEventTarget.h>
-#include <nsIDOMHTMLImageElement.h>
-#include <nsIIOService.h>
-#include <nsComponentManagerUtils.h>
-#include <imgICache.h>
-#include <nsIProperties.h>
-#include <nsIWebNavigation.h>
-#include <nsISupportsPrimitives.h>
-#include <nsIInterfaceRequestorUtils.h>
-#include <nsIMIMEHeaderParam.h>
-#include <nsISHistory.h>
-#include <nsIHistoryEntry.h>
-#include <nsISHEntry.h>
-#include <nsIInputStream.h>
-#include <nsICommandManager.h>
-#include <nsIClipboardDragDropHooks.h>
-
-#include "nsISessionStore.h"
-#include "nsIBrowserHelper.h"
-
-#define SUGAR_PATH "SUGAR_PATH"
-
-enum {
-	PROP_0,
-	PROP_PROGRESS,
-	PROP_TITLE,
-	PROP_ADDRESS,
-	PROP_CAN_GO_BACK,
-	PROP_CAN_GO_FORWARD,
-	PROP_LOADING,
-    PROP_DOCUMENT_METADATA
-};
-
-enum {
-    MOUSE_CLICK,
-    N_SIGNALS
-};
-
-static int last_instance_id = 0;
-
-static guint signals[N_SIGNALS];
-
-static GObjectClass *parent_class = NULL;
-
-static const nsModuleComponentInfo sSugarComponents[] = {
-	{
-		"Gecko Content Handler",
-		GECKOCONTENTHANDLER_CID,
-		NS_IHELPERAPPLAUNCHERDLG_CONTRACTID,
-		NULL
-	},
-	{
-		"Gecko Download",
-		GECKODOWNLOAD_CID,
-		NS_TRANSFER_CONTRACTID,
-		NULL
-	}
-};
-
-int (*old_handler) (Display *, XErrorEvent *);
-
-static int
-error_handler (Display *d, XErrorEvent *e)
-{
-    gchar buf[64];
-    gchar *msg;
-
-    XGetErrorText(d, e->error_code, buf, 63);
-
-    msg =
-    g_strdup_printf("The program '%s' received an X Window System error.\n"
-                    "This probably reflects a bug in the program.\n"
-                    "The error was '%s'.\n"
-                    "  (Details: serial %ld error_code %d request_code %d minor_code %d)\n",
-                    g_get_prgname (),
-                    buf,
-                    e->serial, 
-                    e->error_code, 
-                    e->request_code,
-                    e->minor_code);
-
-    g_warning ("%s", msg);
-
-    return 0;
-    /*return (*old_handler)(d, e);*/
-}
-
-static void
-setup_plugin_path ()
-{
-    const char *user_path;
-    char *new_path;
-
-    user_path = g_getenv ("MOZ_PLUGIN_PATH");
-    new_path = g_strconcat (user_path ? user_path : "",
-                            user_path ? ":" : "",
-                            PLUGIN_DIR,
-                            (char *) NULL);
-    g_setenv ("MOZ_PLUGIN_PATH", new_path, TRUE);
-    g_free (new_path);
-}
-
-static gboolean
-setup_directory_provider(const char *full_prof_path)
-{
-    const char *prefix = g_getenv("SUGAR_PREFIX");
-    if (prefix == NULL) {
-        g_print("The SUGAR_PREFIX environment variable is not set.");
-        exit(1);
-    }
-    
-    char *components_path = g_build_filename(prefix, "share/sugar", NULL);
-
-    GeckoDirectoryProvider *dirProvider =
-        new GeckoDirectoryProvider(components_path, full_prof_path);
-    if (!dirProvider) {
-        g_warning ("failed to create GeckoDirectoryProvider");
-        return FALSE;
-    }
-
-    g_free(components_path);
-    
-    NS_ADDREF (dirProvider);
-
-    nsCOMPtr<nsIDirectoryServiceProvider> dp (do_QueryInterface (dirProvider));
-    NS_RELEASE (dirProvider);
-    dirProvider = nsnull;
-
-    if (!dp) return FALSE;
-
-    gtk_moz_embed_set_directory_service_provider(dp);
-    
-    return TRUE;
-}
-
-gboolean
-sugar_browser_startup(const char *profile_path, const char *profile_name)
-{
-	nsresult rv;
-
-    setup_plugin_path();
-
-	gtk_moz_embed_set_profile_path(profile_path, profile_name);
-
-    old_handler = XSetErrorHandler(error_handler);
-
-    char *full_prof_path = g_build_filename(profile_path, profile_name, NULL);
-    if (!setup_directory_provider(full_prof_path)) {
-        return FALSE;
-    }
-    g_free(full_prof_path);
-
-    gtk_moz_embed_push_startup();
-
-	nsCOMPtr<nsIPrefService> prefService;
-	prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
-	NS_ENSURE_TRUE(prefService, FALSE);
-
-	/* Read our predefined default prefs */
-	nsCString pathToPrefs(g_getenv(SUGAR_PATH));
-	pathToPrefs.Append("/data/gecko-prefs.js");
-
-	nsCOMPtr<nsILocalFile> file;
-	NS_NewNativeLocalFile(pathToPrefs, PR_TRUE, getter_AddRefs(file));
-	NS_ENSURE_TRUE(file, FALSE);
-
-	rv = prefService->ReadUserPrefs (file);
-	if (NS_FAILED(rv)) {
-		g_warning ("failed to read default preferences, error: %x", rv);
-		return FALSE;
-	}
-
-	nsCOMPtr<nsIPrefBranch> pref;
-	prefService->GetBranch ("", getter_AddRefs(pref));
-	NS_ENSURE_TRUE(pref, FALSE);
-
-	nsCString pathToMimeTypes(g_getenv(SUGAR_PATH));
-	pathToMimeTypes.Append("/data/mime.types");
-
-    pref->SetCharPref ("helpers.private_mime_types_file", pathToMimeTypes.get());
-
-	rv = prefService->ReadUserPrefs (nsnull);
-	if (NS_FAILED(rv)) {
-		g_warning ("failed to read user preferences, error: %x", rv);
-	}
-
-	nsCOMPtr<nsIComponentRegistrar> componentRegistrar;
-	NS_GetComponentRegistrar(getter_AddRefs(componentRegistrar));
-	NS_ENSURE_TRUE (componentRegistrar, FALSE);
-
-    nsCOMPtr<nsIFactory> contentHandlerFactory;
-    rv = NS_NewGeckoContentHandlerFactory(getter_AddRefs(contentHandlerFactory));
-    rv = componentRegistrar->RegisterFactory(sSugarComponents[0].mCID,
-                                             sSugarComponents[0].mDescription,
-                                             sSugarComponents[0].mContractID,
-                                             contentHandlerFactory);
-	if (NS_FAILED(rv)) {
-		g_warning ("Failed to register factory for %s\n", sSugarComponents[0].mDescription);
-		return FALSE;
-	}
-
-    nsCOMPtr<nsIFactory> downloadFactory;
-    rv = NS_NewGeckoDownloadFactory(getter_AddRefs(downloadFactory));
-    rv = componentRegistrar->RegisterFactory(sSugarComponents[1].mCID,
-                                             sSugarComponents[1].mDescription,
-                                             sSugarComponents[1].mContractID,
-                                             downloadFactory);
-	if (NS_FAILED(rv)) {
-		g_warning ("Failed to register factory for %s\n", sSugarComponents[1].mDescription);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-void
-sugar_browser_shutdown(void)
-{
-    gtk_moz_embed_pop_startup();
-}
-
-G_DEFINE_TYPE(SugarBrowser, sugar_browser, GTK_TYPE_MOZ_EMBED)
-
-static nsresult
-FilenameFromContentDisposition(nsCString contentDisposition, nsCString &fileName)
-{
-    nsresult rv;
-
-    nsCString fallbackCharset;
-
-    nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar =
-        do_GetService("@mozilla.org/network/mime-hdrparam;1");
-    NS_ENSURE_TRUE(mimehdrpar, NS_ERROR_FAILURE);
-
-    nsString aFileName;
-    rv = mimehdrpar->GetParameter (contentDisposition, "filename",
-                                   fallbackCharset, PR_TRUE, nsnull,
-                                   aFileName);
-
-    if (NS_FAILED(rv) || !fileName.Length()) {
-        rv = mimehdrpar->GetParameter (contentDisposition, "name",
-                                       fallbackCharset, PR_TRUE, nsnull,
-                                       aFileName);
-    }
-
-    if (NS_SUCCEEDED(rv) && fileName.Length()) {
-        NS_UTF16ToCString (aFileName, NS_CSTRING_ENCODING_UTF8, fileName);
-    }
-
-    return NS_OK;
-}
-
-static SugarBrowserMetadata *
-sugar_browser_get_document_metadata(SugarBrowser *browser)
-{
-    SugarBrowserMetadata *metadata = sugar_browser_metadata_new();
-
-	nsCOMPtr<nsIWebBrowser> webBrowser;
-	gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(browser),
-									getter_AddRefs(webBrowser));
-	NS_ENSURE_TRUE(webBrowser, metadata);
-
-    nsCOMPtr<nsIDOMWindow> DOMWindow;
-    webBrowser->GetContentDOMWindow(getter_AddRefs(DOMWindow));
-	NS_ENSURE_TRUE(DOMWindow, metadata);
-
-    nsCOMPtr<nsIDOMWindowUtils> DOMWindowUtils(do_GetInterface(DOMWindow));
-	NS_ENSURE_TRUE(DOMWindowUtils, metadata);
-
-    const PRUnichar contentDispositionLiteral[] =
-        {'c', 'o', 'n', 't', 'e', 'n', 't', '-', 'd', 'i', 's', 'p',
-         'o', 's', 'i', 't', 'i', 'o', 'n', '\0'};
-
-    nsString contentDisposition;
-    DOMWindowUtils->GetDocumentMetadata(nsString(contentDispositionLiteral),
-                                        contentDisposition);
-
-    nsCString cContentDisposition;
-    NS_UTF16ToCString (contentDisposition, NS_CSTRING_ENCODING_UTF8,
-                       cContentDisposition);
-
-    nsCString fileName;
-    FilenameFromContentDisposition(cContentDisposition, fileName);
-
-    if (!fileName.Length()) {
-        nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(webBrowser));
-        if (webNav) {
-            nsCOMPtr<nsIURI> docURI;
-            webNav->GetCurrentURI (getter_AddRefs(docURI));
-
-            nsCOMPtr<nsIURL> url(do_QueryInterface(docURI));
-            if (url) {
-                url->GetFileName(fileName);
-            }
-        }
-    }
-
-    if (fileName.Length()) {
-        metadata->filename = g_strdup(fileName.get());
-    }
-
-    return metadata;
-}
-
-static void
-sugar_browser_get_property(GObject         *object,
-						   guint            prop_id,
-						   GValue          *value,
-						   GParamSpec      *pspec)
-{
-	SugarBrowser *browser = SUGAR_BROWSER(object);
-
-	switch (prop_id) {
-	    case PROP_PROGRESS:
-			g_value_set_double(value, browser->progress);
-		break;
-	    case PROP_ADDRESS:
-			g_value_set_string(value, browser->address);
-		break;
-	    case PROP_TITLE:
-			g_value_set_string(value, browser->title);
-		break;
-	    case PROP_CAN_GO_BACK:
-			g_value_set_boolean(value, browser->can_go_back);
-		break;
-	    case PROP_CAN_GO_FORWARD:
-			g_value_set_boolean(value, browser->can_go_forward);
-		break;
-	    case PROP_LOADING:
-			g_value_set_boolean(value, browser->loading);
-		break;
-	    case PROP_DOCUMENT_METADATA:
-            SugarBrowserMetadata *metadata;
-            metadata = sugar_browser_get_document_metadata(browser);
-			g_value_set_boxed(value, metadata);
-		break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static void
-sugar_browser_realize(GtkWidget *widget)
-{
-    SugarBrowser *browser = SUGAR_BROWSER(widget);
-
-    GTK_WIDGET_CLASS(parent_class)->realize(widget);
-
-    GtkMozEmbed *embed = GTK_MOZ_EMBED(widget);
-    nsCOMPtr<nsIWebBrowser> webBrowser;
-    gtk_moz_embed_get_nsIWebBrowser(embed, getter_AddRefs(webBrowser));
-    NS_ENSURE_TRUE(webBrowser, );
-    
-    nsCOMPtr<nsIBrowserHelper> browserHelper;
-    browserHelper = do_GetService("@laptop.org/browser/browserhelper;1");
-    if (browserHelper) {
-        browserHelper->RegisterBrowser(browser->instance_id, webBrowser);
-    } else {
-        g_warning ("Failed to get nsIBrowserHelper");
-    }
-
-    nsCOMPtr<nsICommandManager> commandManager = do_GetInterface(webBrowser);
-    if (commandManager) {
-        nsresult rv;
-        nsIClipboardDragDropHooks *rawPtr = new GeckoDragDropHooks(
-            SUGAR_BROWSER(widget));
-        nsCOMPtr<nsIClipboardDragDropHooks> geckoDragDropHooks(
-            do_QueryInterface(rawPtr, &rv));
-        NS_ENSURE_SUCCESS(rv, );
-
-        nsCOMPtr<nsIDOMWindow> DOMWindow = do_GetInterface(webBrowser); 
-        nsCOMPtr<nsICommandParams> cmdParamsObj = do_CreateInstance(
-            NS_COMMAND_PARAMS_CONTRACTID, &rv);
-        NS_ENSURE_SUCCESS(rv, );
-        cmdParamsObj->SetISupportsValue("addhook", geckoDragDropHooks);
-        commandManager->DoCommand("cmd_clipboardDragDropHook", cmdParamsObj,
-                                  DOMWindow);
-    }
-}
-
-static void
-sugar_browser_dispose(GObject *object)
-{
-    SugarBrowser *browser = SUGAR_BROWSER(object);
-
-    GtkMozEmbed *embed = GTK_MOZ_EMBED(object);
-    nsCOMPtr<nsIWebBrowser> webBrowser;
-    gtk_moz_embed_get_nsIWebBrowser(embed, getter_AddRefs(webBrowser));
-    NS_ENSURE_TRUE(webBrowser, );
-
-    nsCOMPtr<nsIBrowserHelper> browserHelper;
-    browserHelper = do_GetService("@laptop.org/browser/browserhelper;1");
-    if (browserHelper) {
-        browserHelper->UnregisterBrowser(browser->instance_id);
-    } else {
-        g_warning ("Failed to get nsIBrowserHelper");
-    }
-}
-
-static void
-sugar_browser_class_init(SugarBrowserClass *browser_class)
-{
-    GObjectClass    *gobject_class = G_OBJECT_CLASS(browser_class);
-    GtkWidgetClass  *widget_class = GTK_WIDGET_CLASS(browser_class);
-
-    parent_class = (GObjectClass *) g_type_class_peek_parent(browser_class);
-
-    gobject_class->get_property = sugar_browser_get_property;
-    gobject_class->dispose = sugar_browser_dispose;
-    widget_class->realize = sugar_browser_realize;
-
-    signals[MOUSE_CLICK] = g_signal_new ("mouse_click",
-                                SUGAR_TYPE_BROWSER,
-                                G_SIGNAL_RUN_LAST,
-                                G_STRUCT_OFFSET(SugarBrowser, mouse_click),
-                                g_signal_accumulator_true_handled, NULL,
-                                sugar_marshal_BOOLEAN__BOXED,
-                                G_TYPE_BOOLEAN,
-                                1,
-                                SUGAR_TYPE_BROWSER_EVENT);
-
-	g_object_class_install_property(gobject_class, PROP_PROGRESS,
-                                    g_param_spec_double ("progress",
-                                                         "Progress",
-                                                         "Progress",
-                                                         0.0, 1.0, 0.0,
-                                                         G_PARAM_READABLE));
-
-	g_object_class_install_property (gobject_class, PROP_ADDRESS,
-									 g_param_spec_string ("address",
-														  "Address",
-														  "Address",
-                                                          "",
-														  G_PARAM_READABLE));
-
-	g_object_class_install_property (gobject_class, PROP_TITLE,
-									 g_param_spec_string ("title",
-														  "Title",
-														  "Title",
-                                                          "",
-														  G_PARAM_READABLE));
-
-	g_object_class_install_property (gobject_class, PROP_CAN_GO_BACK,
-									 g_param_spec_boolean ("can-go-back",
-														   "Can go back",
-														   "Can go back",
-														   FALSE,
-														   G_PARAM_READABLE));
-
-	g_object_class_install_property (gobject_class, PROP_CAN_GO_FORWARD,
-									 g_param_spec_boolean ("can-go-forward",
-														   "Can go forward",
-														   "Can go forward",
-														   FALSE,
-														   G_PARAM_READABLE));
-
-	g_object_class_install_property (gobject_class, PROP_LOADING,
-									 g_param_spec_boolean ("loading",
-														   "Loading",
-														   "Loading",
-														   FALSE,
-														   G_PARAM_READABLE));
-
-    g_object_class_install_property(gobject_class, PROP_DOCUMENT_METADATA,
-                                    g_param_spec_boxed("document-metadata",
-                                                       "Document Metadata",
-                                                       "Document metadata",
-                                                       SUGAR_TYPE_BROWSER_METADATA,
-                                                       G_PARAM_READABLE));
-
-}
-
-SugarBrowser *
-sugar_browser_create_window(SugarBrowser *browser)
-{
-	return SUGAR_BROWSER_GET_CLASS(browser)->create_window(browser);
-}
-
-static void
-update_navigation_properties(SugarBrowser *browser)
-{
-	GtkMozEmbed *embed = GTK_MOZ_EMBED(browser);
-	gboolean can_go_back;
-	gboolean can_go_forward;
-
-	can_go_back = gtk_moz_embed_can_go_back(embed);
-	if (can_go_back != browser->can_go_back) {
-		browser->can_go_back = can_go_back;
-		g_object_notify (G_OBJECT(browser), "can-go-back");
-	}
-
-	can_go_forward = gtk_moz_embed_can_go_forward(embed);
-	if (can_go_forward != browser->can_go_forward) {
-		browser->can_go_forward = can_go_forward;
-		g_object_notify (G_OBJECT(browser), "can-go-forward");
-	}
-}
-
-static void
-new_window_cb(GtkMozEmbed  *embed,
-			  GtkMozEmbed **newEmbed,
-              guint         chromemask)
-{
-	SugarBrowser *browser;
-
-	browser = sugar_browser_create_window(SUGAR_BROWSER(embed));
-
-	*newEmbed = GTK_MOZ_EMBED(browser);
-}
-
-static void
-sugar_browser_set_progress(SugarBrowser *browser, float progress)
-{
-	g_return_if_fail(SUGAR_IS_BROWSER(browser));
-
-	browser->progress = progress;
-	g_object_notify (G_OBJECT(browser), "progress");
-}
-
-static void
-sugar_browser_set_loading(SugarBrowser *browser, gboolean loading)
-{
-	g_return_if_fail(SUGAR_IS_BROWSER(browser));
-
-	browser->loading = loading;
-	g_object_notify (G_OBJECT(browser), "loading");
-}
-
-static void
-net_state_cb(GtkMozEmbed *embed, const char *aURI, gint state, guint status)
-{
-	SugarBrowser *browser = SUGAR_BROWSER(embed);
-
-	if (state & GTK_MOZ_EMBED_FLAG_IS_NETWORK) {
-		if (state & GTK_MOZ_EMBED_FLAG_START) {
-			browser->total_requests = 0;
-			browser->current_requests = 0;
-
-			sugar_browser_set_progress(browser, 0.03);
-			sugar_browser_set_loading(browser, TRUE);
-            update_navigation_properties(browser);
-		} else if (state & GTK_MOZ_EMBED_FLAG_STOP) {
-			sugar_browser_set_progress(browser, 1.0);
-			sugar_browser_set_loading(browser, FALSE);
-            update_navigation_properties(browser);
-		}
-	}
-
-	if (state & GTK_MOZ_EMBED_FLAG_IS_REQUEST) {
-		float progress;
-
-		if (state & GTK_MOZ_EMBED_FLAG_START) {
-			browser->total_requests++;
-		}
-		else if (state & GTK_MOZ_EMBED_FLAG_STOP)
-		{
-			browser->current_requests++;
-		}
-
-		progress = float(browser->current_requests) /
-				   float(browser->total_requests);
-		if (progress > browser->progress) {
-			sugar_browser_set_progress(browser, progress);
-		}
-	}
-}
-
-static void
-title_cb(GtkMozEmbed *embed)
-{
-	SugarBrowser *browser = SUGAR_BROWSER(embed);
-
-	g_free(browser->title);
-	browser->title = gtk_moz_embed_get_title(embed);
-
-	g_object_notify (G_OBJECT(browser), "title");
-}
-
-static void
-location_cb(GtkMozEmbed *embed)
-{
-	SugarBrowser *browser = SUGAR_BROWSER(embed);
-
-	g_free(browser->address);
-	browser->address = gtk_moz_embed_get_location(embed);
-
-	g_object_notify (G_OBJECT(browser), "address");
-
-	update_navigation_properties(browser);
-}
-
-static gboolean
-dom_mouse_click_cb(GtkMozEmbed *embed, nsIDOMMouseEvent *mouseEvent)
-{
-    SugarBrowser *browser = SUGAR_BROWSER(embed);
-    SugarBrowserEvent *event;
-    gint return_value = FALSE;
-
-    nsCOMPtr<nsIDOMEventTarget> eventTarget;
-    mouseEvent->GetTarget(getter_AddRefs(eventTarget));
-    NS_ENSURE_TRUE(mouseEvent, FALSE);
-
-    nsCOMPtr<nsIDOMNode> targetNode;
-    targetNode = do_QueryInterface(eventTarget);
-    NS_ENSURE_TRUE(targetNode, FALSE);
-
-    event = sugar_browser_event_new();
-
-    GeckoDocumentObject documentObject(browser, targetNode);
-    if(documentObject.IsImage()) {
-        event->image_uri = documentObject.GetImageURI();
-        event->image_name = documentObject.GetImageName();
-    }
-
-    PRUint16 btn = 0;
-    mouseEvent->GetButton (&btn);
-    event->button = btn + 1;
-
-    g_signal_emit(browser, signals[MOUSE_CLICK], 0, event, &return_value);
-
-    sugar_browser_event_free(event);
-
-    return return_value;
-}
-
-static void
-sugar_browser_init(SugarBrowser *browser)
-{
-    browser->instance_id = last_instance_id;
-    last_instance_id++;
-    
-	browser->title = NULL;
-	browser->address = NULL;
-	browser->progress = 0.0;
-
-	g_signal_connect(G_OBJECT(browser), "new-window",
-					 G_CALLBACK(new_window_cb), NULL);
-	g_signal_connect(G_OBJECT(browser), "net-state-all",
-					 G_CALLBACK(net_state_cb), NULL);
-	g_signal_connect(G_OBJECT(browser), "title",
-					 G_CALLBACK(title_cb), NULL);
-	g_signal_connect(G_OBJECT(browser), "location",
-					 G_CALLBACK(location_cb), NULL);
-/*	g_signal_connect(G_OBJECT(browser), "dom-mouse-click",
-					 G_CALLBACK(dom_mouse_click_cb), NULL);
-*/
-}
-
-int
-sugar_browser_get_instance_id(SugarBrowser *browser)
-{
-    return browser->instance_id;
-}
-
-void
-sugar_browser_scroll_pixels(SugarBrowser *browser,
-                            int           dx,
-                            int           dy)
-{
-	nsCOMPtr<nsIWebBrowser> webBrowser;
-	gtk_moz_embed_get_nsIWebBrowser (GTK_MOZ_EMBED(browser),
-									 getter_AddRefs(webBrowser));
-	NS_ENSURE_TRUE (webBrowser, );
-
-	nsCOMPtr<nsIWebBrowserFocus> webBrowserFocus;
-	webBrowserFocus = do_QueryInterface (webBrowser);
-	NS_ENSURE_TRUE (webBrowserFocus, );
-
-	nsCOMPtr<nsIDOMWindow> DOMWindow;
-	webBrowserFocus->GetFocusedWindow (getter_AddRefs(DOMWindow));
-	if (!DOMWindow) {
-		webBrowser->GetContentDOMWindow (getter_AddRefs(DOMWindow));
-	}
-	NS_ENSURE_TRUE (DOMWindow, );
-
-	DOMWindow->ScrollBy (dx, dy);
-}
-
-void
-sugar_browser_grab_focus(SugarBrowser *browser)
-{
-	GtkWidget *child;
-
-	child = gtk_bin_get_child(GTK_BIN(browser));
-
-	if (child != NULL) {
-		gtk_widget_grab_focus (child);
-	} else {
-		g_warning ("Need to realize the embed before grabbing focus!\n");
-	}
-}
-
-gboolean
-sugar_browser_save_uri(SugarBrowser *browser,
-                       const char   *uri,
-                       const char   *filename)
-{
-    GeckoBrowserPersist browserPersist(browser);
-    return browserPersist.SaveURI(uri, filename);
-}
-
-gboolean
-sugar_browser_save_document(SugarBrowser *browser,
-                            const char   *filename)
-{
-    nsresult rv;
-
-    nsCString cFile(filename);
-
-    nsCOMPtr<nsILocalFile> destFile = do_CreateInstance("@mozilla.org/file/local;1");
-    NS_ENSURE_TRUE(destFile, FALSE);
-
-    destFile->InitWithNativePath(cFile);
-
-    GString *path = g_string_new (filename);
-    char *dot_pos = strchr (path->str, '.');
-    if (dot_pos) {
-        g_string_truncate (path, dot_pos - path->str);
-    }
-    g_string_append (path, " Files");
-
-    nsCOMPtr<nsILocalFile> filesFolder;    
-    filesFolder = do_CreateInstance ("@mozilla.org/file/local;1");
-    filesFolder->InitWithNativePath (nsCString(path->str));
-
-    g_string_free (path, TRUE);
-
-	nsCOMPtr<nsIWebBrowser> webBrowser;
-	gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(browser),
-									getter_AddRefs(webBrowser));
-	NS_ENSURE_TRUE(webBrowser, FALSE);
-
-    nsCOMPtr<nsIDOMWindow> DOMWindow;
-    webBrowser->GetContentDOMWindow(getter_AddRefs(DOMWindow));
-	NS_ENSURE_TRUE(DOMWindow, FALSE);
-
-    nsCOMPtr<nsIDOMDocument> DOMDocument;
-    DOMWindow->GetDocument (getter_AddRefs(DOMDocument));
-	NS_ENSURE_TRUE(DOMDocument, FALSE);
-
-	nsCOMPtr<nsIWebBrowserPersist> webPersist = do_QueryInterface (webBrowser);
-	NS_ENSURE_TRUE(webPersist, FALSE);
-
-    rv = webPersist->SaveDocument(DOMDocument, destFile, filesFolder, nsnull, 0, 0);
-    NS_ENSURE_SUCCESS(rv, FALSE);
-
-    return TRUE;
-}
-
-char *
-sugar_browser_get_session(SugarBrowser *browser)
-{
-    nsCOMPtr<nsIWebBrowser> webBrowser;
-    gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(browser),
-                                    getter_AddRefs(webBrowser));
-    if (!webBrowser) {
-        g_warning ("failed to get nsIWebBrowser");
-        return NULL;
-    }
-
-    nsCOMPtr<nsISessionStore> sessionStore;
-    sessionStore = do_GetService("@mozilla.org/browser/sessionstore;1");
-    if (!sessionStore) {
-        g_warning ("failed to get nsISessionStore");
-        return NULL;
-    }
-
-    nsString session;
-    nsresult rv = sessionStore->GetBrowserState(webBrowser, session);
-    if (NS_FAILED(rv)) {
-        g_warning ("failed to get browser state");
-        return NULL;
-    }
-
-    nsCString sessionUTF8;
-    NS_UTF16ToCString (session, NS_CSTRING_ENCODING_UTF8, sessionUTF8);
-
-    return g_strdup(sessionUTF8.get());
-}
-
-gboolean
-sugar_browser_set_session(SugarBrowser *browser,
-                          const char   *session)
-{
-    nsCOMPtr<nsIWebBrowser> webBrowser;
-    gtk_moz_embed_get_nsIWebBrowser(GTK_MOZ_EMBED(browser),
-                                    getter_AddRefs(webBrowser));
-    if (!webBrowser) {
-        g_warning ("failed to get nsIWebBrowser");
-        return FALSE;
-    }
-
-    nsCOMPtr<nsISessionStore> sessionStore;
-    sessionStore = do_GetService("@mozilla.org/browser/sessionstore;1");
-    if (!sessionStore) {
-        g_warning ("failed to get nsISessionStore");
-        return FALSE;
-    }
-
-    nsCString sessionUTF8(session);
-    nsString sessionUTF16;
-    NS_CStringToUTF16(sessionUTF8, NS_CSTRING_ENCODING_UTF8, sessionUTF16);
-    nsresult rv = sessionStore->SetBrowserState(webBrowser, sessionUTF16);
-    if (NS_FAILED(rv)) {
-        g_warning ("failed to set browser state");
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-GType
-sugar_browser_event_get_type(void)
-{
-    static GType type = 0;
-
-    if (G_UNLIKELY(type == 0)) {
-        type = g_boxed_type_register_static("SugarBrowserEvent",
-                            (GBoxedCopyFunc)sugar_browser_event_copy,
-                            (GBoxedFreeFunc)sugar_browser_event_free);
-    }
-
-    return type;
-}
-
-SugarBrowserEvent *
-sugar_browser_event_new(void)
-{
-    SugarBrowserEvent *event;
-
-    event = g_new0(SugarBrowserEvent, 1);
-
-    return event;
-}
-
-SugarBrowserEvent *
-sugar_browser_event_copy(SugarBrowserEvent *event)
-{
-    SugarBrowserEvent *copy;
-
-    g_return_val_if_fail(event != NULL, NULL);
-
-    copy = g_new0(SugarBrowserEvent, 1);
-    copy->button = event->button;
-    copy->image_uri = g_strdup(event->image_uri);
-    copy->image_name = g_strdup(event->image_name);
-
-    return copy;
-}
-
-void
-sugar_browser_event_free(SugarBrowserEvent *event)
-{
-    g_return_if_fail(event != NULL);
-
-    if (event->image_uri) {
-        g_free(event->image_uri);
-    }
-    if (event->image_name) {
-        g_free(event->image_name);
-    }
-
-    g_free(event);
-}
-
-GType
-sugar_browser_metadata_get_type(void)
-{
-    static GType type = 0;
-
-    if (G_UNLIKELY(type == 0)) {
-        type = g_boxed_type_register_static("SugarBrowserMetadata",
-                            (GBoxedCopyFunc)sugar_browser_metadata_copy,
-                            (GBoxedFreeFunc)sugar_browser_metadata_free);
-    }
-
-    return type;
-}
-
-SugarBrowserMetadata *
-sugar_browser_metadata_new(void)
-{
-    SugarBrowserMetadata *metadata;
-
-    metadata = g_new0(SugarBrowserMetadata, 1);
-
-    return metadata;
-}
-
-SugarBrowserMetadata *
-sugar_browser_metadata_copy(SugarBrowserMetadata *metadata)
-{
-    SugarBrowserMetadata *copy;
-
-    g_return_val_if_fail(metadata != NULL, NULL);
-
-    copy = g_new0(SugarBrowserMetadata, 1);
-    copy->filename = g_strdup(metadata->filename);
-
-    return copy;
-}
-
-void
-sugar_browser_metadata_free(SugarBrowserMetadata *metadata)
-{
-    g_return_if_fail(metadata != NULL);
-
-    if (metadata->filename) {
-        g_free(metadata->filename);
-    }
-
-    g_free(metadata);
-}
diff --git a/browser/sugar-browser.h b/browser/sugar-browser.h
deleted file mode 100644
index 779bba5a..00000000
--- a/browser/sugar-browser.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __SUGAR_BROWSER_H__
-#define __SUGAR_BROWSER_H__
-
-#include <gtkmozembed.h>
-
-G_BEGIN_DECLS
-
-typedef struct _SugarBrowser         SugarBrowser;
-typedef struct _SugarBrowserClass    SugarBrowserClass;
-typedef struct _SugarBrowserEvent    SugarBrowserEvent;
-typedef struct _SugarBrowserMetadata SugarBrowserMetadata;
-
-#define SUGAR_TYPE_BROWSER				(sugar_browser_get_type())
-#define SUGAR_BROWSER(object)	    	(G_TYPE_CHECK_INSTANCE_CAST((object), SUGAR_TYPE_BROWSER, SugarBrowser))
-#define SUGAR_BROWSER_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), SUGAR_TYPE_BROWSER, SugarBrowserClass))
-#define SUGAR_IS_BROWSER(object)		(G_TYPE_CHECK_INSTANCE_TYPE((object), SUGAR_TYPE_BROWSER))
-#define SUGAR_IS_BROWSER_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), SUGAR_TYPE_BROWSER))
-#define SUGAR_BROWSER_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), SUGAR_TYPE_BROWSER, SugarBrowserClass))
-
-struct _SugarBrowser {
-	GtkMozEmbed base_instance;
-
-    int instance_id;
-	int total_requests;
-	int current_requests;
-	float progress;
-	char *address;
-	char *title;
-	gboolean can_go_back;
-	gboolean can_go_forward;
-	gboolean loading;
-
-    gboolean (* mouse_click) (SugarBrowser      *browser,
-                              SugarBrowserEvent *event);
-};
-
-struct _SugarBrowserClass {
-	GtkMozEmbedClass base_class;
-
-	SugarBrowser * (* create_window) (SugarBrowser *browser);
-};
-
-GType			sugar_browser_get_type		  (void);
-int             sugar_browser_get_instance_id (SugarBrowser *browser);
-SugarBrowser   *sugar_browser_create_window	  (SugarBrowser *browser);
-void			sugar_browser_scroll_pixels   (SugarBrowser *browser,
-                            				   int           dx,
-                            				   int           dy);
-void			sugar_browser_grab_focus	  (SugarBrowser *browser);
-gboolean        sugar_browser_save_uri        (SugarBrowser *browser,
-                                               const char   *uri,
-                                               const char   *filename);
-gboolean        sugar_browser_save_document   (SugarBrowser *browser,
-                                               const char   *filename);
-char           *sugar_browser_get_session     (SugarBrowser *browser);
-gboolean        sugar_browser_set_session     (SugarBrowser *browser,
-                                               const char   *session);
-
-gboolean        sugar_browser_startup         (const char *profile_path,
-                                               const char *profile_name);
-void            sugar_browser_shutdown        (void);
-
-#define SUGAR_TYPE_BROWSER_EVENT (sugar_browser_event_get_type())
-
-struct _SugarBrowserEvent {
-    int   button;
-    char *image_uri;
-    char *image_name;
-};
-
-GType                sugar_browser_event_get_type (void);
-SugarBrowserEvent   *sugar_browser_event_new      (void);
-SugarBrowserEvent   *sugar_browser_event_copy     (SugarBrowserEvent *event);
-void                 sugar_browser_event_free     (SugarBrowserEvent *event);
-
-#define SUGAR_TYPE_BROWSER_METADATA (sugar_browser_metadata_get_type())
-
-struct _SugarBrowserMetadata {
-    char *filename;
-};
-
-GType                 sugar_browser_metadata_get_type (void);
-SugarBrowserMetadata *sugar_browser_metadata_new      (void);
-SugarBrowserMetadata *sugar_browser_metadata_copy     (SugarBrowserMetadata *event);
-void                  sugar_browser_metadata_free     (SugarBrowserMetadata *event);
-
-G_END_DECLS
-
-#endif
diff --git a/browser/sugar-download-manager.c b/browser/sugar-download-manager.c
deleted file mode 100644
index ead3bc82..00000000
--- a/browser/sugar-download-manager.c
+++ /dev/null
@@ -1,165 +0,0 @@
-#include "sugar-marshal.h"
-#include "sugar-download.h"
-#include "sugar-download-manager.h"
-
-enum {
-  DOWNLOAD_STARTED,
-  DOWNLOAD_COMPLETED,
-  DOWNLOAD_CANCELLED,
-  DOWNLOAD_PROGRESS,
-  LAST_SIGNAL
-};
-static guint signals[LAST_SIGNAL] = { 0 };
-
-static void	sugar_download_manager_finalize (GObject *object);
-static void sugar_download_remove_download (gpointer key, gpointer value, gpointer user_data);
-
-G_DEFINE_TYPE (SugarDownloadManager, sugar_download_manager, G_TYPE_OBJECT)
-
-SugarDownloadManager *DownloadManager = NULL;
-
-static void
-sugar_download_manager_init (SugarDownloadManager *download_manager)
-{
-	download_manager->downloads = g_hash_table_new (g_str_hash, g_str_equal);
-}
-
-static void
-sugar_download_manager_class_init (SugarDownloadManagerClass *download_manager_class)
-{
-	GObjectClass *gobject_class = G_OBJECT_CLASS (download_manager_class);
-
-	gobject_class->finalize = sugar_download_manager_finalize;
-  
-	signals[DOWNLOAD_STARTED] =
-		g_signal_new ("download-started",
-					  G_OBJECT_CLASS_TYPE (download_manager_class),
-		  			  G_SIGNAL_RUN_LAST,
-		  			  G_STRUCT_OFFSET (SugarDownloadManagerClass, handle_content),
-					  NULL, NULL,
-					  sugar_marshal_VOID__OBJECT,
-					  G_TYPE_NONE, 1,
-					  G_TYPE_OBJECT);
-					  
-	signals[DOWNLOAD_COMPLETED] =
-		g_signal_new ("download-completed",
-					  G_OBJECT_CLASS_TYPE (download_manager_class),
-		  			  G_SIGNAL_RUN_LAST,
-		  			  G_STRUCT_OFFSET (SugarDownloadManagerClass, handle_content),
-					  NULL, NULL,
-					  sugar_marshal_VOID__OBJECT,
-					  G_TYPE_NONE, 1,
-					  G_TYPE_OBJECT);
-					  
-	signals[DOWNLOAD_CANCELLED] =
-		g_signal_new ("download-cancelled",
-					  G_OBJECT_CLASS_TYPE (download_manager_class),
-		  			  G_SIGNAL_RUN_LAST,
-		  			  G_STRUCT_OFFSET (SugarDownloadManagerClass, handle_content),
-					  NULL, NULL,
-					  sugar_marshal_VOID__OBJECT,
-					  G_TYPE_NONE, 1,
-					  G_TYPE_OBJECT);
-					  
-	signals[DOWNLOAD_PROGRESS] =
-		g_signal_new ("download-progress",
-					  G_OBJECT_CLASS_TYPE (download_manager_class),
-		  			  G_SIGNAL_RUN_LAST,
-		  			  G_STRUCT_OFFSET (SugarDownloadManagerClass, handle_content),
-					  NULL, NULL,
-					  sugar_marshal_VOID__OBJECT,
-					  G_TYPE_NONE, 1,
-					  G_TYPE_OBJECT);
-}
-
-static void
-sugar_download_manager_finalize (GObject *object)
-{
-	SugarDownloadManager *download_manager = SUGAR_DOWNLOAD_MANAGER (object);
-	g_hash_table_foreach (download_manager->downloads, sugar_download_remove_download, NULL);
-	g_hash_table_destroy (download_manager->downloads);
-}
-
-static void
-sugar_download_remove_download (gpointer key, gpointer value, gpointer user_data)
-{
-  g_free (value);
-}
-
-SugarDownloadManager *
-sugar_get_download_manager ()
-{  
-	if (DownloadManager == NULL)
-		DownloadManager = g_object_new (SUGAR_TYPE_DOWNLOAD_MANAGER, NULL);
- 	
-	return DownloadManager;
-}
-
-void
-sugar_download_manager_download_started (SugarDownloadManager *download_manager,
-										 const char *url,
-										 const char *mime_type,
-										 const char *file_name)
-{
-	SugarDownload *download = (SugarDownload *) g_hash_table_lookup (
-			download_manager->downloads,
-			file_name);
-
-	g_return_if_fail (download == NULL);
-
-	download = g_object_new (SUGAR_TYPE_DOWNLOAD, NULL);
-	sugar_download_set_url (download, url);
-	sugar_download_set_mime_type (download, mime_type);
-	sugar_download_set_file_name (download, file_name);
-	
-	g_hash_table_insert (download_manager->downloads,
-						 (gpointer)file_name,
-						 download);
-
-	g_signal_emit (download_manager, signals[DOWNLOAD_STARTED], 0, download);
-}
-
-void
-sugar_download_manager_download_completed (SugarDownloadManager *download_manager,
-										   const char *file_name)
-{
-	SugarDownload *download = (SugarDownload *) g_hash_table_lookup (
-			download_manager->downloads,
-			file_name);
-
-	g_return_if_fail (download);
-	
-	g_signal_emit (download_manager, signals[DOWNLOAD_COMPLETED], 0, download);
-	
-	g_hash_table_remove (download_manager->downloads, file_name);
-}
-
-void sugar_download_manager_download_cancelled (SugarDownloadManager *download_manager,
-												const char *file_name)
-{
-	SugarDownload *download = (SugarDownload *) g_hash_table_lookup (
-			download_manager->downloads,
-			file_name);
-
-	g_return_if_fail (download);
-	
-	g_signal_emit (download_manager, signals[DOWNLOAD_CANCELLED], 0, download);
-
-	g_hash_table_remove (download_manager->downloads, file_name);
-}
-
-void
-sugar_download_manager_update_progress (SugarDownloadManager *download_manager,
-										const char *file_name,
-										const int percent)
-{
-	SugarDownload *download = (SugarDownload *) g_hash_table_lookup (
-			download_manager->downloads,
-			file_name);
-
-	g_return_if_fail (download);
-	
-	sugar_download_set_percent (download, percent);
-
-	g_signal_emit (download_manager, signals [DOWNLOAD_PROGRESS], 0, download);
-}
diff --git a/browser/sugar-download-manager.h b/browser/sugar-download-manager.h
deleted file mode 100644
index c58436bc..00000000
--- a/browser/sugar-download-manager.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef __SUGAR_DOWNLOAD_MANAGER_H__
-#define __SUGAR_DOWNLOAD_MANAGER_H__
-
-#include <glib-object.h>
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-typedef struct _SugarDownloadManager SugarDownloadManager;
-typedef struct _SugarDownloadManagerClass SugarDownloadManagerClass;
-
-#define SUGAR_TYPE_DOWNLOAD_MANAGER				 (sugar_download_manager_get_type())
-#define SUGAR_DOWNLOAD_MANAGER(object)			 (G_TYPE_CHECK_INSTANCE_CAST((object), SUGAR_TYPE_DOWNLOAD_MANAGER, SugarDownloadManager))
-#define SUGAR_DOWNLOAD_MANAGER_CLASS(klass) 	 (G_TYPE_CHECK_CLASS_CAST((klass), SUGAR_TYPE_DOWNLOAD_MANAGER, SugarDownloadManagerClass))
-#define SUGAR_IS_DOWNLOAD_MANAGER(object)		 (G_TYPE_CHECK_INSTANCE_TYPE((object), SUGAR_TYPE_DOWNLOAD_MANAGER))
-#define SUGAR_IS_DOWNLOAD_MANAGER_CLASS(klass) 	 (G_TYPE_CHECK_CLASS_TYPE((klass), SUGAR_TYPE_DOWNLOAD_MANAGER))
-#define SUGAR_DOWNLOAD_MANAGER_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), SUGAR_TYPE_DOWNLOAD_MANAGER, SugarDownloadManagerClass))
-
-struct _SugarDownloadManager {
-	GObject		base_instance;
-	
-	GHashTable	*downloads;
-};
-
-struct _SugarDownloadManagerClass {
-	GObjectClass base_class;
-	
-	void (* handle_content) (char *url, char *tmp_file_name);
-	
-};
-
-GType sugar_download_manager_get_type(void);
-
-SugarDownloadManager *sugar_get_download_manager(void);
-
-void sugar_download_manager_download_started(
-	SugarDownloadManager *download_manager,
-	const char *url,
-	const char *mime_type,
-	const char *tmp_file_name);
-
-void sugar_download_manager_download_completed(
-	SugarDownloadManager *download_manager,
-	const char *tmp_file_name);
-	
-void sugar_download_manager_download_cancelled(
-	SugarDownloadManager *download_manager,
-	const char *tmp_file_name);
-
-void sugar_download_manager_update_progress(
-	SugarDownloadManager *download_manager,
-	const char *tmp_file_name,
-	const int percent);
-
-G_END_DECLS
-
-#endif
diff --git a/browser/sugar-download.c b/browser/sugar-download.c
deleted file mode 100644
index 01ad809e..00000000
--- a/browser/sugar-download.c
+++ /dev/null
@@ -1,108 +0,0 @@
-#include "sugar-download.h"
-
-static void	sugar_download_finalize (GObject *object);
-
-G_DEFINE_TYPE (SugarDownload, sugar_download, G_TYPE_OBJECT)
-
-static void
-sugar_download_init (SugarDownload *download)
-{
-	download->file_name = NULL;
-	download->url = NULL;
-	download->mime_type = NULL;
-	download->percent = 0;
-}
-
-static void
-sugar_download_class_init (SugarDownloadClass *download_class)
-{
-	GObjectClass *gobject_class = G_OBJECT_CLASS (download_class);
-
-	gobject_class->finalize = sugar_download_finalize;
-}
-
-void
-sugar_download_set_file_name (SugarDownload *download, const gchar *file_name)
-{
-	gchar *new_file_name;
-  
-	g_return_if_fail (SUGAR_IS_DOWNLOAD (download));
-
-	new_file_name = g_strdup (file_name);
-	g_free (download->file_name);
-	download->file_name = new_file_name;
-}
-
-void
-sugar_download_set_url (SugarDownload *download, const gchar *url)
-{
-	gchar *new_url;
-  
-	g_return_if_fail (SUGAR_IS_DOWNLOAD (download));
-
-	new_url = g_strdup (url);
-	g_free (download->url);
-	download->url = new_url;
-}
-
-void
-sugar_download_set_mime_type (SugarDownload *download, const gchar *mime_type)
-{
-	gchar *new_mime_type;
-  
-	g_return_if_fail (SUGAR_IS_DOWNLOAD (download));
-
-	new_mime_type = g_strdup (mime_type);
-	g_free (download->mime_type);
-	download->mime_type = new_mime_type;
-}
-
-void
-sugar_download_set_percent (SugarDownload *download, const gint percent)
-{
-	g_return_if_fail (SUGAR_IS_DOWNLOAD (download));
-
-	download->percent = percent;
-}
-
-const gchar *
-sugar_download_get_file_name (SugarDownload *download)
-{
-	g_return_val_if_fail (SUGAR_IS_DOWNLOAD (download), NULL);
-  
-	return download->file_name;
-}
-
-const gchar *
-sugar_download_get_url (SugarDownload *download)
-{
-	g_return_val_if_fail (SUGAR_IS_DOWNLOAD (download), NULL);
-  
-	return download->url;
-}
-
-const gchar *
-sugar_download_get_mime_type (SugarDownload *download)
-{
-	g_return_val_if_fail (SUGAR_IS_DOWNLOAD (download), NULL);
-  
-	return download->mime_type;
-}
-
-gint
-sugar_download_get_percent (SugarDownload *download)
-{
-	g_return_val_if_fail (SUGAR_IS_DOWNLOAD (download), -1);
-  
-	return download->percent;
-}
-
-static void
-sugar_download_finalize (GObject *object)
-{
-	SugarDownload *download = SUGAR_DOWNLOAD (object);
-	
-	g_free (download->file_name);
-	g_free (download->url);
-	g_free (download->mime_type);
-}
diff --git a/browser/sugar-download.h b/browser/sugar-download.h
deleted file mode 100644
index ac3760b8..00000000
--- a/browser/sugar-download.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef __SUGAR_DOWNLOAD_H__
-#define __SUGAR_DOWNLOAD_H__
-
-#include <glib-object.h>
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-typedef struct _SugarDownload SugarDownload;
-typedef struct _SugarDownloadClass SugarDownloadClass;
-
-#define SUGAR_TYPE_DOWNLOAD				 (sugar_download_get_type())
-#define SUGAR_DOWNLOAD(object)			 (G_TYPE_CHECK_INSTANCE_CAST((object), SUGAR_TYPE_DOWNLOAD, SugarDownload))
-#define SUGAR_DOWNLOAD_CLASS(klass) 	 (G_TYPE_CHECK_CLASS_CAST((klass), SUGAR_TYPE_DOWNLOAD, SugarDownloadClass))
-#define SUGAR_IS_DOWNLOAD(object)		 (G_TYPE_CHECK_INSTANCE_TYPE((object), SUGAR_TYPE_DOWNLOAD))
-#define SUGAR_IS_DOWNLOAD_CLASS(klass) 	 (G_TYPE_CHECK_CLASS_TYPE((klass), SUGAR_TYPE_DOWNLOAD))
-#define SUGAR_DOWNLOAD_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), SUGAR_TYPE_DOWNLOAD, SugarDownloadClass))
-
-struct _SugarDownload {
-	GObject	base_instance;
-	
-	gchar	*file_name;
-	gchar	*url;
-	gchar	*mime_type;
-	gint	 percent;
-};
-
-struct _SugarDownloadClass {
-	GObjectClass base_class;
-};
-
-GType sugar_download_get_type(void);
-
-void	sugar_download_set_file_name	(SugarDownload	*download,
-										 const gchar	*file_name);
-void	sugar_download_set_url			(SugarDownload	*download,
-										 const gchar	*url);
-void	sugar_download_set_mime_type	(SugarDownload	*download,
-										 const gchar	*mime_type);
-void	sugar_download_set_percent		(SugarDownload	*download,
-										 const gint		 percent);
-
-const gchar *sugar_download_get_file_name	(SugarDownload	*download);
-const gchar *sugar_download_get_url			(SugarDownload	*download);
-const gchar *sugar_download_get_mime_type	(SugarDownload	*download);
-gint		 sugar_download_get_percent		(SugarDownload	*download);
-
-G_END_DECLS
-
-#endif /* __SUGAR_DOWNLOAD_H__ */
diff --git a/browser/sugar-marshal.list b/browser/sugar-marshal.list
deleted file mode 100644
index 81b3ae12..00000000
--- a/browser/sugar-marshal.list
+++ /dev/null
@@ -1,4 +0,0 @@
-VOID:OBJECT,STRING,LONG,LONG
-VOID:OBJECT,LONG
-VOID:OBJECT
-BOOLEAN:BOXED
diff --git a/configure.ac b/configure.ac
index ecfb7b1c..3966d46b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,17 +2,11 @@ AC_INIT([Sugar],[0.63],[],[sugar])
 
 AC_PREREQ([2.59])
 
-GNOME_COMMON_INIT
-GNOME_COMPILE_WARNINGS
-
 AC_CONFIG_MACRO_DIR([m4])
-AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_SRCDIR([configure.ac])
 
 AM_INIT_AUTOMAKE([1.9 foreign dist-bzip2 no-dist-gzip])
 
-AM_MAINTAINER_MODE
-
 AC_DISABLE_STATIC
 AC_PROG_LIBTOOL
 
@@ -23,47 +17,14 @@ AM_CHECK_PYTHON_HEADERS(,[AC_MSG_ERROR(could not find Python headers)])
 
 AC_PATH_PROG(PYGTK_CODEGEN, pygtk-codegen-2.0, no)
 
-PKG_CHECK_MODULES(PYGTK, pygtk-2.0)
-
-PKG_CHECK_MODULES(PYCAIRO, pycairo)
+PKG_CHECK_MODULES(SHELL, pygtk-2.0 gtk+-2.0 gstreamer-0.10 gstreamer-plugins-base-0.10)
 
 PKG_CHECK_MODULES(LIB, gtk+-2.0)
-
-PKG_CHECK_MODULES(SHELL, gtk+-2.0 gstreamer-0.10 gstreamer-plugins-base-0.10)
+PKG_CHECK_MODULES(LIB_BINDINGS, pygtk-2.0)
 
 PYGTK_DEFSDIR=`$PKG_CONFIG --variable=defsdir pygtk-2.0`
 AC_SUBST(PYGTK_DEFSDIR)
 
-#
-# Mozilla
-#
-
-AC_ARG_WITH(libxul_sdk,
-	AC_HELP_STRING([--with-libxul-sdk=DIR], [Path to libxul SDK]))
-
-if test -d "$with_libxul_sdk"; then
-
-# xulrunner 1.9
-
-GECKO_CFLAGS="-I$with_libxul_sdk/sdk/include -DXPCOM_GLUE"
-XPCOMGLUE_LIBS="-L$with_libxul_sdk/sdk/lib -lxpcomglue"
-MOZILLA_INCLUDE_DIR="$with_libxul_sdk/include"
-XPIDL="$with_libxul_sdk/sdk/bin/xpidl"
-MOZILLA_IDL_DIR="$with_libxul_sdk/sdk/idl"
-
-AC_SUBST(XPCOMGLUE_LIBS)
-AC_SUBST(GECKO_CFLAGS)
-AC_SUBST(MOZILLA_INCLUDE_DIR)
-AC_SUBST(XPIDL)
-AC_SUBST(MOZILLA_IDL_DIR)
-
-else
-
-AC_MSG_ERROR([Must specify the xulrunner sdk dir (--with-libxul-sdk)])
-
-fi
-
-#
 # Setup GETTEXT
 #
 ALL_LINGUAS="it ha ig yo"
@@ -79,10 +40,8 @@ AC_OUTPUT([
 Makefile
 bin/Makefile
 data/Makefile
-browser/Makefile
-browser/components/Makefile
-browser/components/sessionstore/Makefile
-browser/components/browserhelper/Makefile
+lib/Makefile
+lib/xdgmime/Makefile
 services/Makefile
 services/presence/Makefile
 services/clipboard/Makefile
@@ -113,10 +72,9 @@ services/console/interface/logviewer/Makefile
 services/console/interface/terminal/Makefile
 sugar/Makefile
 sugar/activity/Makefile
-sugar/browser/Makefile
 sugar/clipboard/Makefile
 sugar/graphics/Makefile
-sugar/p2p/Makefile
+sugar/objects/Makefile
 sugar/presence/Makefile
 sugar/datastore/Makefile
 po/Makefile.in
diff --git a/data/Makefile.am b/data/Makefile.am
index 830030ac..b2fd17ae 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -8,9 +8,7 @@ sugar-xo.gtkrc: gtkrc.em
 
 sugardir = $(pkgdatadir)/data
 sugar_DATA =		\
-	$(GTKRC_FILES)	\
-	gecko-prefs.js	\
-	mime.types
+	$(GTKRC_FILES)
 
 GTKRC_FILES =		\
 	sugar.gtkrc	\
diff --git a/data/gecko-prefs.js b/data/gecko-prefs.js
deleted file mode 100644
index ee613826..00000000
--- a/data/gecko-prefs.js
+++ /dev/null
@@ -1,97 +0,0 @@
-// Disable onload popups
-user_pref("dom.disable_open_during_load", true);
-
-// Disable usless security warnings
-user_pref("security.warn_entering_secure", false);
-user_pref("security.warn_entering_secure.show_once", true);
-user_pref("security.warn_leaving_secure", false);
-user_pref("security.warn_leaving_secure.show_once", false);
-user_pref("security.warn_submit_insecure", false);
-user_pref("security.warn_submit_insecure.show_once", false);
-user_pref("security.warn_viewing_mixed", true);
-user_pref("security.warn_viewing_mixed.show_once", false);
-user_pref("security.warn_entering_weak", true);
-user_pref("security.warn_entering_weak.show_once", false);
-
-// Set some style properties to not follow our dark gtk theme
-user_pref("ui.-moz-field", "#FFFFFF");
-user_pref("ui.-moz-fieldtext", "#000000");
-user_pref("ui.buttonface", "#D3D3DD");
-user_pref("ui.buttontext", "#000000");
-
-// Fonts
-user_pref("font.size.unit", "pt");
-
-// Layout:
-// 1024x768 -> (96 * 6) / 1024 * 201 = 113 dpi
-// 800x600  -> (96 * 6) /  800 * 201 = 144 dpi
-//
-// Fonts:
-// 7  pt ->  7 / 12 * 201 = 117 dpi
-// 8  pt ->  8 / 12 * 201 = 134 dpi
-// 9  pt ->  9 / 12 * 201 = 150 dpi
-
-user_pref("layout.css.dpi", 134);
-
-user_pref("font.default.ar", "sans-serif");
-user_pref("font.size.variable.ar", 12);
-user_pref("font.size.fixed.ar", 9);
-
-user_pref("font.default.el", "serif");
-user_pref("font.size.variable.el", 12);
-user_pref("font.size.fixed.el", 9);
-
-user_pref("font.default.he", "sans-serif");
-user_pref("font.size.variable.he", 12);
-user_pref("font.size.fixed.he", 9);
-
-user_pref("font.default.ja", "sans-serif");
-user_pref("font.size.variable.ja", 12);
-user_pref("font.size.fixed.ja", 12);
-
-user_pref("font.default.ko", "sans-serif");
-user_pref("font.size.variable.ko", 12);
-user_pref("font.size.fixed.ko", 12);
-
-user_pref("font.default.th", "serif");
-user_pref("font.size.variable.th", 12);
-user_pref("font.size.fixed.th", 9);
-
-user_pref("font.default.tr", "serif");
-user_pref("font.size.variable.tr", 12);
-user_pref("font.size.fixed.tr", 9);
-
-user_pref("font.default.x-baltic", "serif");
-user_pref("font.size.variable.x-baltic", 12);
-user_pref("font.size.fixed.x-baltic", 9);
-
-user_pref("font.default.x-central-euro", "serif");
-user_pref("font.size.variable.x-central-euro", 12);
-user_pref("font.size.fixed.x-central-euro", 9);
-
-user_pref("font.default.x-cyrillic", "serif");
-user_pref("font.size.variable.x-cyrillic", 12);
-user_pref("font.size.fixed.x-cyrillic", 9);
-
-user_pref("font.default.x-unicode", "serif");
-user_pref("font.size.variable.x-unicode", 12);
-user_pref("font.size.fixed.x-unicode", 9);
-
-user_pref("font.default.x-western", "serif");
-user_pref("font.size.variable.x-western", 12);
-user_pref("font.size.fixed.x-western", 9);
-
-user_pref("font.default.zh-CN", "sans-serif");
-user_pref("font.size.variable.zh-CN", 12);
-user_pref("font.size.fixed.zh-CN", 12);
-
-user_pref("font.default.zh-TW", "sans-serif");
-user_pref("font.size.variable.zh-TW", 12);
-user_pref("font.size.fixed.zh-TW", 12);
-
-user_pref("font.default.zh-HK", "sans-serif");
-user_pref("font.size.variable.zh-HK", 12);
-user_pref("font.size.fixed.zh-HK", 12);
-
-// Enable error pages (xulrunner is missing this pref)
-user_pref("browser.xul.error_pages.enabled", true);
diff --git a/data/mime.types b/data/mime.types
deleted file mode 100644
index a6ffcb2b..00000000
--- a/data/mime.types
+++ /dev/null
@@ -1,3 +0,0 @@
-application/x-squeak-project	pr
-application/x-abiword		abw
-application/vnd.olpc-x-sugar	xo
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 00000000..f709c585
--- /dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,14 @@
+SUBDIRS = xdgmime
+
+libsugar_la_CPPFLAGS =		\
+	$(LIB_CFLAGS)
+	
+noinst_LTLIBRARIES = libsugar.la
+
+libsugar_la_LIBADD = 					\
+	$(LIB_LIBS)					\
+	$(top_builddir)/lib/xdgmime/libxdgmime.la
+
+libsugar_la_SOURCES =			\
+	sugar-address-entry.c		\
+	sugar-address-entry.h
diff --git a/browser/sugar-address-entry.c b/lib/sugar-address-entry.c
similarity index 100%
rename from browser/sugar-address-entry.c
rename to lib/sugar-address-entry.c
diff --git a/browser/sugar-address-entry.h b/lib/sugar-address-entry.h
similarity index 98%
rename from browser/sugar-address-entry.h
rename to lib/sugar-address-entry.h
index bf1838d1..1ebc3611 100644
--- a/browser/sugar-address-entry.h
+++ b/lib/sugar-address-entry.h
@@ -20,7 +20,7 @@
 #ifndef __SUGAR_ADDRESS_ENTRY_H__
 #define __SUGAR_ADDRESS_ENTRY_H__
 
-#include <glib-object.h>
+#include <gtk/gtkentry.h>
 
 G_BEGIN_DECLS
 
diff --git a/lib/xdgmime/ChangeLog b/lib/xdgmime/ChangeLog
new file mode 100644
index 00000000..d04c59a6
--- /dev/null
+++ b/lib/xdgmime/ChangeLog
@@ -0,0 +1,378 @@
+2007-01-22  Matthias Clasen  <mclasen@redhat.com>
+
+	* === 2.10.9 ===
+
+2007-01-17  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.10.8 ===
+
+2007-01-07  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmimecache.c (cache_glob_node_lookup_suffix): Don't return "" 
+	as match.  (fd.o #9544, Yevgen Muntyan)
+
+2007-01-07  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmimecache.c (_xdg_mime_cache_list_mime_parents): Fix 
+	several problems with this function.  (fd.o #9560, Yevgen Muntyan)
+
+2007-01-05  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.10.7 ===
+
+2006-10-03  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.10.6 ===
+
+2006-10-02  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.10.5 ===
+
+2006-09-22  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.10.4 ===
+
+2006-09-04  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.10.3 ===
+
+2006-08-17  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.10.2 ===
+
+2006-07-23  Matthias Clasen  <mclasen@redhat.com>
+	
+	* === Released 2.10.1 ===
+
+2006-07-20  Matthias Clasen  <mclasen@redhat.com>
+
+	Fix a thinko that leads to constantly reloading
+	the mime data if a mime.cache is present.  Patch
+	by Yevgen Muntyan, bugs.freedesktop.org #7495
+	
+	* xdgmime.c (xdg_check_dir): Look for mime.cache first.
+	(xdg_check_file): Report existance of the file separately.
+	
+2006-07-20  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmime.c (xdg_mime_shutdown): Unref the caches.
+	Patch by Yevgen Muntyan, bugs.freedesktop.org #7496
+
+	* xdgmimemagic.c: 
+	* xdgmime.c: 
+	* xdgmime.h: Add xdg_init-free versions of some
+	functions and use them internally, so that we don't
+	reload caches and clobber data structures in the
+	middle of an operation.  Patch by Joe Shaw,
+	bugs.freedesktop.org #6824
+
+2006-07-19  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmimeglob.c (_xdg_glob_hash_node_lookup_file_name):
+	Don't return NULL as a mimetype, ever, patch
+	by Yevgen Muntyan, bugs.freedesktop.org #5241
+
+2006-07-02  Matthias Clasen  <mclasen@redhat.com>
+	
+	* === Released 2.10.0 ===
+
+2006-06-21  Matthias Clasen  <mclasen@redhat.com>
+	
+	* === Released 2.9.4 ===
+
+2006-06-12  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.9.3 ===
+
+2006-06-05  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.9.2 ===
+
+2006-05-16  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.9.1 ====
+
+2006-05-04  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.9.0 ===
+
+2006-04-03  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmime.[hc]: Move xdg_mime_type_unknown to .rodata.
+
+2006-03-06  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmimemagic.c: Remove superfluous extern errno 
+	declaration.  (#333605, Tommi Komulainen)
+
+2006-02-27  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmime.h (xdg_mime_dump): Don't export xdg_mime_dump.
+
+2005-12-01  Matthias Clasen  <mclasen@redhat.com>
+
+	* Merge upstream changes to handle duplicate glob
+	patterns.
+
+2005-11-04  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmime.c (xdg_mime_list_mime_parents): Prevent
+	a segfault.  
+
+2005-10-18  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmimecache.c: Make magic comparisons work correctly
+	in the cache.
+
+2005-10-17  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmime.c (xdg_mime_get_mime_type_for_file): Remove
+	a debugging printf.
+
+2005-09-01  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmime.h:
+	* xdgmime.c (xdg_mime_get_mime_type_for_file): Take
+	a struct statbuf * as argument.
+
+	* test-mime.c (main): Adjust.
+
+2005-08-24  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.8.2 ===
+
+	* === Released 2.8.1 ===
+
+2005-08-13  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.8.0 ===
+
+2005-08-07  Matthias Clasen  <mclasen@redhat.com>
+
+	* Rename caches to _caches, so it doesn't
+	get exported. Also don't export n_caches.
+
+2005-08-02  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.7.5 ===
+
+2005-07-22  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.7.4 === 
+
+2005-07-15  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.7.3 ===
+	
+2005-07-08  Matthias Clasen  <mclasen@redhat.com>
+	
+	* === Released 2.7.2 ===
+
+2005-07-01  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.7.1 ===
+	
+2005-06-20  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmimecache.c: Handle missing MAP_FAILED.  (#308449, Georg
+	Schwarz)
+
+2005-06-20  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.7.0 ===
+
+2005-06-10  Federico Mena Quintero  <federico@ximian.com>
+
+	* xdgmime.c (xdg_mime_init_from_directory): Pass the correct size
+	to realloc().  Fixes https://bugs.freedesktop.org/show_bug.cgi?id=3506.
+
+2005-06-09  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmimemagic.c: Don't declare errno, including errno.h 
+	is enough.  (#304164, Joerg Sonnenberger)
+
+2005-05-20  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmimecache.c (GET_UINT32): Don't rely on C99 
+	types.  (#304924, John Ehresman)
+
+2005-04-29  Matthias Clasen  <mclasen@redhat.com>
+
+	* Sync to upstream.
+
+2005-04-08  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmimecache.c (cache_magic_matchlet_compare_to_data) 
+	(cache_magic_matchlet_compare): Use cache->buffer, not 
+	cache.  
+
+Tue Apr  5 16:00:04 2005  Manish Singh  <yosh@gimp.org>
+
+	* Makefile.am: add xdgmimecache.[ch].
+
+2005-03-28  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmimeglob.c: Sync to latest upstream,
+	including fixes for matching against multiple
+	extensions (eg .tar.gz) and for suffix
+	patterns which don't start with a dot.
+
+Sat Mar 19 23:52:33 2005  Manish Singh  <yosh@gimp.org>
+
+	* xdgmimeglob.c (_xdg_glob_hash_insert_text): cast away the constness
+	in the call to free().
+
+2005-03-20  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmimeglob.c (_xdg_glob_hash_insert_text): Don't 
+	leak node->mime_type if we are reusing an existing
+	node.  (#170774, Kjartan Maraas)
+
+2005-01-08  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.6.1 ===
+	
+2004-12-16  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.6.0 ===
+
+2004-12-13  Marco Pesenti Gritti  <marco@gnome.org>
+
+	* xdgmimeglob.c: (_xdg_glob_hash_lookup_file_name):
+
+	Resync with upstream again
+
+Fri Dec 10 13:58:38 2004  Manish Singh  <yosh@gimp.org>
+
+	* xdgmime.h: wrap new API in XDG_ENTRY().
+
+2004-12-09  Marco Pesenti Gritti  <marco@gnome.org>
+
+	* xdgmime.c: (xdg_mime_unalias_mime_type),
+	(xdg_mime_mime_type_equal), (xdg_mime_mime_type_subclass),
+	(xdg_mime_get_mime_parents):
+	* xdgmime.h:
+	* xdgmimealias.c: (_xdg_mime_alias_list_lookup):
+	* xdgmimeglob.c: (_xdg_glob_hash_node_lookup_file_name):
+	* xdgmimeint.c: (_xdg_ucs4_to_lower):
+	* xdgmimeint.h:
+	* xdgmimemagic.c: (_xdg_mime_magic_read_from_file):
+	* xdgmimeparent.c: (_xdg_mime_parent_list_lookup):
+
+	Resync with upstream
+
+2004-12-09  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmimealias.c (_xdg_mime_alias_read_from_file): 
+	* xdgmimeparent.c (_xdg_mime_parent_read_from_file): Make
+	repeated calls accumulate the results, don't call qsort()
+	on empty arrays.  (#160838, Mariano Suárez-Alvarez)
+
+2004-12-02  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.5.6 ===
+
+2004-11-29  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmimeparent.c (_xdg_mime_parent_list_lookup): 
+	* xdgmimealias.c (_xdg_mime_alias_list_lookup): Protect 
+	against stupid bsearch() implementations.  (#159737,
+	Morten Welinder)
+ 
+2004-11-24  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmimeparent.c (_xdg_mime_parent_read_from_file): 
+	Initialize the parent field of the newly allocate list 
+	entry.  (#159330, Alex Larsson)
+
+Fri Nov 19 15:10:32 2004  Manish Singh  <yosh@gimp.org>
+
+	* xdgmime.c: Don't put /* within a comment.
+
+2004-11-09  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmime.h: Prefix all symbols.
+
+2004-11-08  Matthias Clasen  <mclasen@redhat.com>
+
+	* xdgmime.c (xdg_mime_mime_type_subclass): Enable matching
+	of supertypes as text/*.
+
+	* Sync from upstream
+
+2004-10-27  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.5.4 ===
+
+2004-09-19  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.5.3 ===
+
+2004-08-25  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.5.2 ===
+
+Wed Aug 11 20:44:35 2004  Matthias Clasen  <maclas@gmx.de>
+
+	* xdgmime.h (xdg_mime_shutdown): Add the XDG_PREFIX to
+	this function as well.
+
+2004-08-01  Matthias Clasen  <mclasen@redhat.com>
+
+	* === Released 2.5.1 ===
+
+Tue Jul 20 22:24:35 2004  Matthias Clasen  <maclas@gmx.de>
+
+	* xdgmimeglob.h: Remove trailing commas from 
+	enumerations. (#148035)
+
+Sun Jul 18 20:17:41 2004  Soeren Sandmann  <sandmann@daimi.au.dk>
+
+	* === Released 2.5.0 ==
+
+Thu May 27 15:23:17 2004  Jonathan Blandford  <jrb@gnome.org>
+
+	* Sync from upstream
+
+Fri Apr 30 00:19:11 2004  Matthias Clasen  <maclas@gmx.de>
+
+	* xdgmimemagic.c (_xdg_mime_magic_read_a_number): Make sure
+	the static string is long enough.  (#136323, Morten Welinder)
+
+2004-03-12  Morten Welinder  <terra@gnome.org>
+
+	* *.c: Make sure to include <config.h>  (#137001)
+
+Wed Mar 10 22:48:15 2004  Jonathan Blandford  <jrb@gnome.org>
+
+	* Sync from upstream
+
+Sun Feb  8 19:05:16 2004  Manish Singh  <yosh@gimp.org>
+
+	* xdgmimeint.h: declare _xdg_utf8_skip as extern to prevent multiple
+	definitions.
+
+Wed Jan 21 09:33:13 2004  Jonathan Blandford  <jrb@gnome.org>
+
+	* libgnomevfs/xdgmimeglob.c:
+	* libgnomevfs/xdgmimemagic.c: Sync from upstream
+
+Tue Jan 20 13:07:04 2004  Jonathan Blandford  <jrb@gnome.org>
+
+	* xdgmime.c: resync with upstream sources.
+
+Fri Oct 24 16:54:57 2003  Owen Taylor  <otaylor@redhat.com>
+
+	* Makefile.am (libxdgmime_la_SOURCES): Add .h files to 
+	SOURCES.
+
+Fri Oct 24 16:02:32 2003  Owen Taylor  <otaylor@redhat.com>
+
+	* *.[ch]: Relicense to be dual AFL/LGPL (and thus also
+	GPL) rather than AFL/GPL. Also update AFL version to 1.2.
+
+Tue Jul 22 15:37:45 2003  Jonathan Blandford  <jrb@gnome.org>
+
+	* xdgmime/xdgmime.c (xdg_mime_init): use XDG_DATA_HOME instead of
+	XDG_CONFIG_HOME.
+
diff --git a/lib/xdgmime/Makefile.am b/lib/xdgmime/Makefile.am
new file mode 100644
index 00000000..3cf173d0
--- /dev/null
+++ b/lib/xdgmime/Makefile.am
@@ -0,0 +1,19 @@
+INCLUDES = -DXDG_PREFIX=sugar_mime
+
+noinst_LTLIBRARIES = libxdgmime.la
+
+libxdgmime_la_SOURCES = \
+	xdgmime.c 	\
+	xdgmime.h	\
+	xdgmimealias.c	\
+	xdgmimealias.h	\
+	xdgmimecache.c	\
+	xdgmimecache.h	\
+	xdgmimeglob.c 	\
+	xdgmimeglob.h 	\
+	xdgmimeint.c 	\
+	xdgmimeint.h 	\
+	xdgmimemagic.c  \
+	xdgmimemagic.h	\
+	xdgmimeparent.c	\
+	xdgmimeparent.h
diff --git a/lib/xdgmime/xdgmime.c b/lib/xdgmime/xdgmime.c
new file mode 100644
index 00000000..1d2007cb
--- /dev/null
+++ b/lib/xdgmime/xdgmime.c
@@ -0,0 +1,850 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* xdgmime.c: XDG Mime Spec mime resolver.  Based on version 0.11 of the spec.
+ *
+ * More info can be found at http://www.freedesktop.org/standards/
+ * 
+ * Copyright (C) 2003,2004  Red Hat, Inc.
+ * Copyright (C) 2003,2004  Jonathan Blandford <jrb@alum.mit.edu>
+ *
+ * Licensed under the Academic Free License version 2.0
+ * Or under the following terms:
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "xdgmime.h"
+#include "xdgmimeint.h"
+#include "xdgmimeglob.h"
+#include "xdgmimemagic.h"
+#include "xdgmimealias.h"
+#include "xdgmimeparent.h"
+#include "xdgmimecache.h"
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <assert.h>
+
+typedef struct XdgDirTimeList XdgDirTimeList;
+typedef struct XdgCallbackList XdgCallbackList;
+
+static int need_reread = TRUE;
+static time_t last_stat_time = 0;
+
+static XdgGlobHash *global_hash = NULL;
+static XdgMimeMagic *global_magic = NULL;
+static XdgAliasList *alias_list = NULL;
+static XdgParentList *parent_list = NULL;
+static XdgDirTimeList *dir_time_list = NULL;
+static XdgCallbackList *callback_list = NULL;
+
+XdgMimeCache **_caches = NULL;
+static int n_caches = 0;
+
+const char xdg_mime_type_unknown[] = "application/octet-stream";
+
+
+enum
+{
+  XDG_CHECKED_UNCHECKED,
+  XDG_CHECKED_VALID,
+  XDG_CHECKED_INVALID
+};
+
+struct XdgDirTimeList
+{
+  time_t mtime;
+  char *directory_name;
+  int checked;
+  XdgDirTimeList *next;
+};
+
+struct XdgCallbackList
+{
+  XdgCallbackList *next;
+  XdgCallbackList *prev;
+  int              callback_id;
+  XdgMimeCallback  callback;
+  void            *data;
+  XdgMimeDestroy   destroy;
+};
+
+/* Function called by xdg_run_command_on_dirs.  If it returns TRUE, further
+ * directories aren't looked at */
+typedef int (*XdgDirectoryFunc) (const char *directory,
+				 void       *user_data);
+
+static XdgDirTimeList *
+xdg_dir_time_list_new (void)
+{
+  XdgDirTimeList *retval;
+
+  retval = calloc (1, sizeof (XdgDirTimeList));
+  retval->checked = XDG_CHECKED_UNCHECKED;
+
+  return retval;
+}
+
+static void
+xdg_dir_time_list_free (XdgDirTimeList *list)
+{
+  XdgDirTimeList *next;
+
+  while (list)
+    {
+      next = list->next;
+      free (list->directory_name);
+      free (list);
+      list = next;
+    }
+}
+
+static int
+xdg_mime_init_from_directory (const char *directory)
+{
+  char *file_name;
+  struct stat st;
+  XdgDirTimeList *list;
+
+  assert (directory != NULL);
+
+  file_name = malloc (strlen (directory) + strlen ("/mime/mime.cache") + 1);
+  strcpy (file_name, directory); strcat (file_name, "/mime/mime.cache");
+  if (stat (file_name, &st) == 0)
+    {
+      XdgMimeCache *cache = _xdg_mime_cache_new_from_file (file_name);
+
+      if (cache != NULL)
+	{
+	  list = xdg_dir_time_list_new ();
+	  list->directory_name = file_name;
+	  list->mtime = st.st_mtime;
+	  list->next = dir_time_list;
+	  dir_time_list = list;
+
+	  _caches = realloc (_caches, sizeof (XdgMimeCache *) * (n_caches + 2));
+	  _caches[n_caches] = cache;
+          _caches[n_caches + 1] = NULL;
+	  n_caches++;
+
+	  return FALSE;
+	}
+    }
+  free (file_name);
+
+  file_name = malloc (strlen (directory) + strlen ("/mime/globs") + 1);
+  strcpy (file_name, directory); strcat (file_name, "/mime/globs");
+  if (stat (file_name, &st) == 0)
+    {
+      _xdg_mime_glob_read_from_file (global_hash, file_name);
+
+      list = xdg_dir_time_list_new ();
+      list->directory_name = file_name;
+      list->mtime = st.st_mtime;
+      list->next = dir_time_list;
+      dir_time_list = list;
+    }
+  else
+    {
+      free (file_name);
+    }
+
+  file_name = malloc (strlen (directory) + strlen ("/mime/magic") + 1);
+  strcpy (file_name, directory); strcat (file_name, "/mime/magic");
+  if (stat (file_name, &st) == 0)
+    {
+      _xdg_mime_magic_read_from_file (global_magic, file_name);
+
+      list = xdg_dir_time_list_new ();
+      list->directory_name = file_name;
+      list->mtime = st.st_mtime;
+      list->next = dir_time_list;
+      dir_time_list = list;
+    }
+  else
+    {
+      free (file_name);
+    }
+
+  file_name = malloc (strlen (directory) + strlen ("/mime/aliases") + 1);
+  strcpy (file_name, directory); strcat (file_name, "/mime/aliases");
+  _xdg_mime_alias_read_from_file (alias_list, file_name);
+  free (file_name);
+
+  file_name = malloc (strlen (directory) + strlen ("/mime/subclasses") + 1);
+  strcpy (file_name, directory); strcat (file_name, "/mime/subclasses");
+  _xdg_mime_parent_read_from_file (parent_list, file_name);
+  free (file_name);
+
+  return FALSE; /* Keep processing */
+}
+
+/* Runs a command on all the directories in the search path */
+static void
+xdg_run_command_on_dirs (XdgDirectoryFunc  func,
+			 void             *user_data)
+{
+  const char *xdg_data_home;
+  const char *xdg_data_dirs;
+  const char *ptr;
+
+  xdg_data_home = getenv ("XDG_DATA_HOME");
+  if (xdg_data_home)
+    {
+      if ((func) (xdg_data_home, user_data))
+	return;
+    }
+  else
+    {
+      const char *home;
+
+      home = getenv ("HOME");
+      if (home != NULL)
+	{
+	  char *guessed_xdg_home;
+	  int stop_processing;
+
+	  guessed_xdg_home = malloc (strlen (home) + strlen ("/.local/share/") + 1);
+	  strcpy (guessed_xdg_home, home);
+	  strcat (guessed_xdg_home, "/.local/share/");
+	  stop_processing = (func) (guessed_xdg_home, user_data);
+	  free (guessed_xdg_home);
+
+	  if (stop_processing)
+	    return;
+	}
+    }
+
+  xdg_data_dirs = getenv ("XDG_DATA_DIRS");
+  if (xdg_data_dirs == NULL)
+    xdg_data_dirs = "/usr/local/share/:/usr/share/";
+
+  ptr = xdg_data_dirs;
+
+  while (*ptr != '\000')
+    {
+      const char *end_ptr;
+      char *dir;
+      int len;
+      int stop_processing;
+
+      end_ptr = ptr;
+      while (*end_ptr != ':' && *end_ptr != '\000')
+	end_ptr ++;
+
+      if (end_ptr == ptr)
+	{
+	  ptr++;
+	  continue;
+	}
+
+      if (*end_ptr == ':')
+	len = end_ptr - ptr;
+      else
+	len = end_ptr - ptr + 1;
+      dir = malloc (len + 1);
+      strncpy (dir, ptr, len);
+      dir[len] = '\0';
+      stop_processing = (func) (dir, user_data);
+      free (dir);
+
+      if (stop_processing)
+	return;
+
+      ptr = end_ptr;
+    }
+}
+
+/* Checks file_path to make sure it has the same mtime as last time it was
+ * checked.  If it has a different mtime, or if the file doesn't exist, it
+ * returns FALSE.
+ *
+ * FIXME: This doesn't protect against permission changes.
+ */
+static int
+xdg_check_file (const char *file_path,
+                int        *exists)
+{
+  struct stat st;
+
+  /* If the file exists */
+  if (stat (file_path, &st) == 0)
+    {
+      XdgDirTimeList *list;
+
+      if (exists)
+        *exists = TRUE;
+
+      for (list = dir_time_list; list; list = list->next)
+	{
+	  if (! strcmp (list->directory_name, file_path) &&
+	      st.st_mtime == list->mtime)
+	    {
+	      if (list->checked == XDG_CHECKED_UNCHECKED)
+		list->checked = XDG_CHECKED_VALID;
+	      else if (list->checked == XDG_CHECKED_VALID)
+		list->checked = XDG_CHECKED_INVALID;
+
+	      return (list->checked != XDG_CHECKED_VALID);
+	    }
+	}
+      return TRUE;
+    }
+
+  if (exists)
+    *exists = FALSE;
+
+  return FALSE;
+}
+
+static int
+xdg_check_dir (const char *directory,
+	       int        *invalid_dir_list)
+{
+  int invalid, exists;
+  char *file_name;
+
+  assert (directory != NULL);
+
+  /* Check the mime.cache file */
+  file_name = malloc (strlen (directory) + strlen ("/mime/mime.cache") + 1);
+  strcpy (file_name, directory); strcat (file_name, "/mime/mime.cache");
+  invalid = xdg_check_file (file_name, &exists);
+  free (file_name);
+  if (invalid)
+    {
+      *invalid_dir_list = TRUE;
+      return TRUE;
+    }
+  else if (exists)
+    {
+      return FALSE;
+    }
+
+  /* Check the globs file */
+  file_name = malloc (strlen (directory) + strlen ("/mime/globs") + 1);
+  strcpy (file_name, directory); strcat (file_name, "/mime/globs");
+  invalid = xdg_check_file (file_name, NULL);
+  free (file_name);
+  if (invalid)
+    {
+      *invalid_dir_list = TRUE;
+      return TRUE;
+    }
+
+  /* Check the magic file */
+  file_name = malloc (strlen (directory) + strlen ("/mime/magic") + 1);
+  strcpy (file_name, directory); strcat (file_name, "/mime/magic");
+  invalid = xdg_check_file (file_name, NULL);
+  free (file_name);
+  if (invalid)
+    {
+      *invalid_dir_list = TRUE;
+      return TRUE;
+    }
+
+  return FALSE; /* Keep processing */
+}
+
+/* Walks through all the mime files stat()ing them to see if they've changed.
+ * Returns TRUE if they have. */
+static int
+xdg_check_dirs (void)
+{
+  XdgDirTimeList *list;
+  int invalid_dir_list = FALSE;
+
+  for (list = dir_time_list; list; list = list->next)
+    list->checked = XDG_CHECKED_UNCHECKED;
+
+  xdg_run_command_on_dirs ((XdgDirectoryFunc) xdg_check_dir,
+			   &invalid_dir_list);
+
+  if (invalid_dir_list)
+    return TRUE;
+
+  for (list = dir_time_list; list; list = list->next)
+    {
+      if (list->checked != XDG_CHECKED_VALID)
+	return TRUE;
+    }
+
+  return FALSE;
+}
+
+/* We want to avoid stat()ing on every single mime call, so we only look for
+ * newer files every 5 seconds.  This will return TRUE if we need to reread the
+ * mime data from disk.
+ */
+static int
+xdg_check_time_and_dirs (void)
+{
+  struct timeval tv;
+  time_t current_time;
+  int retval = FALSE;
+
+  gettimeofday (&tv, NULL);
+  current_time = tv.tv_sec;
+
+  if (current_time >= last_stat_time + 5)
+    {
+      retval = xdg_check_dirs ();
+      last_stat_time = current_time;
+    }
+
+  return retval;
+}
+
+/* Called in every public function.  It reloads the hash function if need be.
+ */
+static void
+xdg_mime_init (void)
+{
+  if (xdg_check_time_and_dirs ())
+    {
+      xdg_mime_shutdown ();
+    }
+
+  if (need_reread)
+    {
+      global_hash = _xdg_glob_hash_new ();
+      global_magic = _xdg_mime_magic_new ();
+      alias_list = _xdg_mime_alias_list_new ();
+      parent_list = _xdg_mime_parent_list_new ();
+
+      xdg_run_command_on_dirs ((XdgDirectoryFunc) xdg_mime_init_from_directory,
+			       NULL);
+
+      need_reread = FALSE;
+    }
+}
+
+const char *
+xdg_mime_get_mime_type_for_data (const void *data,
+				 size_t      len)
+{
+  const char *mime_type;
+
+  xdg_mime_init ();
+
+  if (_caches)
+    return _xdg_mime_cache_get_mime_type_for_data (data, len);
+
+  mime_type = _xdg_mime_magic_lookup_data (global_magic, data, len, NULL, 0);
+
+  if (mime_type)
+    return mime_type;
+
+  return XDG_MIME_TYPE_UNKNOWN;
+}
+
+const char *
+xdg_mime_get_mime_type_for_file (const char  *file_name,
+                                 struct stat *statbuf)
+{
+  const char *mime_type;
+  /* currently, only a few globs occur twice, and none
+   * more often, so 5 seems plenty.
+   */
+  const char *mime_types[5];
+  FILE *file;
+  unsigned char *data;
+  int max_extent;
+  int bytes_read;
+  struct stat buf;
+  const char *base_name;
+  int n;
+
+  if (file_name == NULL)
+    return NULL;
+  if (! _xdg_utf8_validate (file_name))
+    return NULL;
+
+  xdg_mime_init ();
+
+  if (_caches)
+    return _xdg_mime_cache_get_mime_type_for_file (file_name, statbuf);
+
+  base_name = _xdg_get_base_name (file_name);
+  n = _xdg_glob_hash_lookup_file_name (global_hash, base_name, mime_types, 5);
+
+  if (n == 1)
+    return mime_types[0];
+
+  if (!statbuf)
+    {
+      if (stat (file_name, &buf) != 0)
+	return XDG_MIME_TYPE_UNKNOWN;
+
+      statbuf = &buf;
+    }
+
+  if (!S_ISREG (statbuf->st_mode))
+    return XDG_MIME_TYPE_UNKNOWN;
+
+  /* FIXME: Need to make sure that max_extent isn't totally broken.  This could
+   * be large and need getting from a stream instead of just reading it all
+   * in. */
+  max_extent = _xdg_mime_magic_get_buffer_extents (global_magic);
+  data = malloc (max_extent);
+  if (data == NULL)
+    return XDG_MIME_TYPE_UNKNOWN;
+        
+  file = fopen (file_name, "r");
+  if (file == NULL)
+    {
+      free (data);
+      return XDG_MIME_TYPE_UNKNOWN;
+    }
+
+  bytes_read = fread (data, 1, max_extent, file);
+  if (ferror (file))
+    {
+      free (data);
+      fclose (file);
+      return XDG_MIME_TYPE_UNKNOWN;
+    }
+
+  mime_type = _xdg_mime_magic_lookup_data (global_magic, data, bytes_read,
+					   mime_types, n);
+
+  free (data);
+  fclose (file);
+
+  if (mime_type)
+    return mime_type;
+
+  return XDG_MIME_TYPE_UNKNOWN;
+}
+
+const char *
+xdg_mime_get_mime_type_from_file_name (const char *file_name)
+{
+  const char *mime_type;
+
+  xdg_mime_init ();
+
+  if (_caches)
+    return _xdg_mime_cache_get_mime_type_from_file_name (file_name);
+
+  if (_xdg_glob_hash_lookup_file_name (global_hash, file_name, &mime_type, 1))
+    return mime_type;
+  else
+    return XDG_MIME_TYPE_UNKNOWN;
+}
+
+int
+xdg_mime_is_valid_mime_type (const char *mime_type)
+{
+  /* FIXME: We should make this a better test
+   */
+  return _xdg_utf8_validate (mime_type);
+}
+
+void
+xdg_mime_shutdown (void)
+{
+  XdgCallbackList *list;
+
+  /* FIXME: Need to make this (and the whole library) thread safe */
+  if (dir_time_list)
+    {
+      xdg_dir_time_list_free (dir_time_list);
+      dir_time_list = NULL;
+    }
+	
+  if (global_hash)
+    {
+      _xdg_glob_hash_free (global_hash);
+      global_hash = NULL;
+    }
+  if (global_magic)
+    {
+      _xdg_mime_magic_free (global_magic);
+      global_magic = NULL;
+    }
+
+  if (alias_list)
+    {
+      _xdg_mime_alias_list_free (alias_list);
+      alias_list = NULL;
+    }
+
+  if (parent_list)
+    {
+      _xdg_mime_parent_list_free (parent_list);
+      parent_list = NULL;
+    }
+  
+  if (_caches)
+    {
+      int i;
+
+      for (i = 0; i < n_caches; i++)
+        _xdg_mime_cache_unref (_caches[i]);
+      free (_caches);
+      _caches = NULL;
+      n_caches = 0;
+    }
+
+  for (list = callback_list; list; list = list->next)
+    (list->callback) (list->data);
+
+  need_reread = TRUE;
+}
+
+int
+xdg_mime_get_max_buffer_extents (void)
+{
+  xdg_mime_init ();
+  
+  if (_caches)
+    return _xdg_mime_cache_get_max_buffer_extents ();
+
+  return _xdg_mime_magic_get_buffer_extents (global_magic);
+}
+
+const char *
+_xdg_mime_unalias_mime_type (const char *mime_type)
+{
+  const char *lookup;
+
+  if (_caches)
+    return _xdg_mime_cache_unalias_mime_type (mime_type);
+
+  if ((lookup = _xdg_mime_alias_list_lookup (alias_list, mime_type)) != NULL)
+    return lookup;
+
+  return mime_type;
+}
+
+const char *
+xdg_mime_unalias_mime_type (const char *mime_type)
+{
+  xdg_mime_init ();
+
+  return _xdg_mime_unalias_mime_type (mime_type);
+}
+
+int
+_xdg_mime_mime_type_equal (const char *mime_a,
+			   const char *mime_b)
+{
+  const char *unalias_a, *unalias_b;
+
+  unalias_a = _xdg_mime_unalias_mime_type (mime_a);
+  unalias_b = _xdg_mime_unalias_mime_type (mime_b);
+
+  if (strcmp (unalias_a, unalias_b) == 0)
+    return 1;
+
+  return 0;
+}
+
+int
+xdg_mime_mime_type_equal (const char *mime_a,
+			  const char *mime_b)
+{
+  xdg_mime_init ();
+
+  return _xdg_mime_mime_type_equal (mime_a, mime_b);
+}
+
+int
+xdg_mime_media_type_equal (const char *mime_a,
+			   const char *mime_b)
+{
+  char *sep;
+
+  xdg_mime_init ();
+
+  sep = strchr (mime_a, '/');
+  
+  if (sep && strncmp (mime_a, mime_b, sep - mime_a + 1) == 0)
+    return 1;
+
+  return 0;
+}
+
+#if 1
+static int
+xdg_mime_is_super_type (const char *mime)
+{
+  int length;
+  const char *type;
+
+  length = strlen (mime);
+  type = &(mime[length - 2]);
+
+  if (strcmp (type, "/*") == 0)
+    return 1;
+
+  return 0;
+}
+#endif
+
+int
+_xdg_mime_mime_type_subclass (const char *mime,
+			      const char *base)
+{
+  const char *umime, *ubase;
+  const char **parents;
+
+  if (_caches)
+    return _xdg_mime_cache_mime_type_subclass (mime, base);
+
+  umime = _xdg_mime_unalias_mime_type (mime);
+  ubase = _xdg_mime_unalias_mime_type (base);
+
+  if (strcmp (umime, ubase) == 0)
+    return 1;
+
+#if 1  
+  /* Handle supertypes */
+  if (xdg_mime_is_super_type (ubase) &&
+      xdg_mime_media_type_equal (umime, ubase))
+    return 1;
+#endif
+
+  /*  Handle special cases text/plain and application/octet-stream */
+  if (strcmp (ubase, "text/plain") == 0 && 
+      strncmp (umime, "text/", 5) == 0)
+    return 1;
+
+  if (strcmp (ubase, "application/octet-stream") == 0)
+    return 1;
+  
+  parents = _xdg_mime_parent_list_lookup (parent_list, umime);
+  for (; parents && *parents; parents++)
+    {
+      if (_xdg_mime_mime_type_subclass (*parents, ubase))
+	return 1;
+    }
+
+  return 0;
+}
+
+int
+xdg_mime_mime_type_subclass (const char *mime,
+			     const char *base)
+{
+  xdg_mime_init ();
+
+  return _xdg_mime_mime_type_subclass (mime, base);
+}
+
+char **
+xdg_mime_list_mime_parents (const char *mime)
+{
+  const char **parents;
+  char **result;
+  int i, n;
+
+  if (_caches)
+    return _xdg_mime_cache_list_mime_parents (mime);
+
+  parents = xdg_mime_get_mime_parents (mime);
+
+  if (!parents)
+    return NULL;
+
+  for (i = 0; parents[i]; i++) ;
+  
+  n = (i + 1) * sizeof (char *);
+  result = (char **) malloc (n);
+  memcpy (result, parents, n);
+
+  return result;
+}
+
+const char **
+xdg_mime_get_mime_parents (const char *mime)
+{
+  const char *umime;
+
+  xdg_mime_init ();
+
+  umime = _xdg_mime_unalias_mime_type (mime);
+
+  return _xdg_mime_parent_list_lookup (parent_list, umime);
+}
+
+void 
+xdg_mime_dump (void)
+{
+  printf ("*** ALIASES ***\n\n");
+  _xdg_mime_alias_list_dump (alias_list);
+  printf ("\n*** PARENTS ***\n\n");
+  _xdg_mime_parent_list_dump (parent_list);
+}
+
+
+/* Registers a function to be called every time the mime database reloads its files
+ */
+int
+xdg_mime_register_reload_callback (XdgMimeCallback  callback,
+				   void            *data,
+				   XdgMimeDestroy   destroy)
+{
+  XdgCallbackList *list_el;
+  static int callback_id = 1;
+
+  /* Make a new list element */
+  list_el = calloc (1, sizeof (XdgCallbackList));
+  list_el->callback_id = callback_id;
+  list_el->callback = callback;
+  list_el->data = data;
+  list_el->destroy = destroy;
+  list_el->next = callback_list;
+  if (list_el->next)
+    list_el->next->prev = list_el;
+
+  callback_list = list_el;
+  callback_id ++;
+
+  return callback_id - 1;
+}
+
+void
+xdg_mime_remove_callback (int callback_id)
+{
+  XdgCallbackList *list;
+
+  for (list = callback_list; list; list = list->next)
+    {
+      if (list->callback_id == callback_id)
+	{
+	  if (list->next)
+	    list->next = list->prev;
+
+	  if (list->prev)
+	    list->prev->next = list->next;
+	  else
+	    callback_list = list->next;
+
+	  /* invoke the destroy handler */
+	  (list->destroy) (list->data);
+	  free (list);
+	  return;
+	}
+    }
+}
diff --git a/lib/xdgmime/xdgmime.h b/lib/xdgmime/xdgmime.h
new file mode 100644
index 00000000..d8172be2
--- /dev/null
+++ b/lib/xdgmime/xdgmime.h
@@ -0,0 +1,111 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* xdgmime.h: XDG Mime Spec mime resolver.  Based on version 0.11 of the spec.
+ *
+ * More info can be found at http://www.freedesktop.org/standards/
+ * 
+ * Copyright (C) 2003  Red Hat, Inc.
+ * Copyright (C) 2003  Jonathan Blandford <jrb@alum.mit.edu>
+ *
+ * Licensed under the Academic Free License version 2.0
+ * Or under the following terms:
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __XDG_MIME_H__
+#define __XDG_MIME_H__
+
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifdef XDG_PREFIX
+#define XDG_ENTRY(func) _XDG_ENTRY2(XDG_PREFIX,func)
+#define _XDG_ENTRY2(prefix,func) _XDG_ENTRY3(prefix,func)
+#define _XDG_ENTRY3(prefix,func) prefix##_##func
+#endif
+
+typedef void (*XdgMimeCallback) (void *user_data);
+typedef void (*XdgMimeDestroy)  (void *user_data);
+
+  
+#ifdef XDG_PREFIX
+#define xdg_mime_get_mime_type_for_data       XDG_ENTRY(get_mime_type_for_data)
+#define xdg_mime_get_mime_type_for_file       XDG_ENTRY(get_mime_type_for_file)
+#define xdg_mime_get_mime_type_from_file_name XDG_ENTRY(get_mime_type_from_file_name)
+#define xdg_mime_is_valid_mime_type           XDG_ENTRY(is_valid_mime_type)
+#define xdg_mime_mime_type_equal              XDG_ENTRY(mime_type_equal)
+#define xdg_mime_media_type_equal             XDG_ENTRY(media_type_equal)
+#define xdg_mime_mime_type_subclass           XDG_ENTRY(mime_type_subclass)
+#define xdg_mime_get_mime_parents             XDG_ENTRY(get_mime_parents)
+#define xdg_mime_list_mime_parents            XDG_ENTRY(list_mime_parents)
+#define xdg_mime_unalias_mime_type            XDG_ENTRY(unalias_mime_type)
+#define xdg_mime_get_max_buffer_extents       XDG_ENTRY(get_max_buffer_extents)
+#define xdg_mime_shutdown                     XDG_ENTRY(shutdown)
+#define xdg_mime_dump                         XDG_ENTRY(dump)
+#define xdg_mime_register_reload_callback     XDG_ENTRY(register_reload_callback)
+#define xdg_mime_remove_callback              XDG_ENTRY(remove_callback)
+#define xdg_mime_type_unknown                 XDG_ENTRY(type_unknown)
+#endif
+
+extern const char xdg_mime_type_unknown[];
+#define XDG_MIME_TYPE_UNKNOWN xdg_mime_type_unknown
+
+const char  *xdg_mime_get_mime_type_for_data       (const void *data,
+						    size_t      len);
+const char  *xdg_mime_get_mime_type_for_file       (const char *file_name,
+                                                    struct stat *statbuf);
+const char  *xdg_mime_get_mime_type_from_file_name (const char *file_name);
+int          xdg_mime_is_valid_mime_type           (const char *mime_type);
+int          xdg_mime_mime_type_equal              (const char *mime_a,
+						    const char *mime_b);
+int          xdg_mime_media_type_equal             (const char *mime_a,
+						    const char *mime_b);
+int          xdg_mime_mime_type_subclass           (const char *mime_a,
+						    const char *mime_b);
+  /* xdg_mime_get_mime_parents() is deprecated since it does
+   * not work correctly with caches. Use xdg_mime_list_parents() 
+   * instead, but notice that that function expects you to free
+   * the array it returns. 
+   */
+const char **xdg_mime_get_mime_parents		   (const char *mime);
+char **      xdg_mime_list_mime_parents		   (const char *mime);
+const char  *xdg_mime_unalias_mime_type		   (const char *mime);
+int          xdg_mime_get_max_buffer_extents       (void);
+void         xdg_mime_shutdown                     (void);
+void         xdg_mime_dump                         (void);
+int          xdg_mime_register_reload_callback     (XdgMimeCallback  callback,
+						    void            *data,
+						    XdgMimeDestroy   destroy);
+void         xdg_mime_remove_callback              (int              callback_id);
+
+   /* Private versions of functions that don't call xdg_mime_init () */
+int          _xdg_mime_mime_type_equal             (const char *mime_a,
+						    const char *mime_b);
+int          _xdg_mime_media_type_equal            (const char *mime_a,
+						    const char *mime_b);
+int          _xdg_mime_mime_type_subclass          (const char *mime,
+						    const char *base);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __XDG_MIME_H__ */
diff --git a/lib/xdgmime/xdgmimealias.c b/lib/xdgmime/xdgmimealias.c
new file mode 100644
index 00000000..2dd70f1d
--- /dev/null
+++ b/lib/xdgmime/xdgmimealias.c
@@ -0,0 +1,184 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* xdgmimealias.c: Private file.  Datastructure for storing the aliases.
+ *
+ * More info can be found at http://www.freedesktop.org/standards/
+ *
+ * Copyright (C) 2004  Red Hat, Inc.
+ * Copyright (C) 2004  Matthias Clasen <mclasen@redhat.com>
+ *
+ * Licensed under the Academic Free License version 2.0
+ * Or under the following terms:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "xdgmimealias.h"
+#include "xdgmimeint.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <fnmatch.h>
+
+#ifndef	FALSE
+#define	FALSE	(0)
+#endif
+
+#ifndef	TRUE
+#define	TRUE	(!FALSE)
+#endif
+
+typedef struct XdgAlias XdgAlias;
+
+struct XdgAlias 
+{
+  char *alias;
+  char *mime_type;
+};
+
+struct XdgAliasList
+{
+  struct XdgAlias *aliases;
+  int n_aliases;
+};
+
+XdgAliasList *
+_xdg_mime_alias_list_new (void)
+{
+  XdgAliasList *list;
+
+  list = malloc (sizeof (XdgAliasList));
+
+  list->aliases = NULL;
+  list->n_aliases = 0;
+
+  return list;
+}
+
+void         
+_xdg_mime_alias_list_free (XdgAliasList *list)
+{
+  int i;
+
+  if (list->aliases)
+    {
+      for (i = 0; i < list->n_aliases; i++)
+	{
+	  free (list->aliases[i].alias);
+	  free (list->aliases[i].mime_type);
+	}
+      free (list->aliases);
+    }
+  free (list);
+}
+
+static int
+alias_entry_cmp (const void *v1, const void *v2)
+{
+  return strcmp (((XdgAlias *)v1)->alias, ((XdgAlias *)v2)->alias);
+}
+
+const char  *
+_xdg_mime_alias_list_lookup (XdgAliasList *list,
+			     const char   *alias)
+{
+  XdgAlias *entry;
+  XdgAlias key;
+
+  if (list->n_aliases > 0)
+    {
+      key.alias = (char *)alias;
+      key.mime_type = 0;
+
+      entry = bsearch (&key, list->aliases, list->n_aliases,
+		       sizeof (XdgAlias), alias_entry_cmp);
+      if (entry)
+        return entry->mime_type;
+    }
+
+  return NULL;
+}
+
+void
+_xdg_mime_alias_read_from_file (XdgAliasList *list,
+				const char   *file_name)
+{
+  FILE *file;
+  char line[255];
+  int alloc;
+
+  file = fopen (file_name, "r");
+
+  if (file == NULL)
+    return;
+
+  /* FIXME: Not UTF-8 safe.  Doesn't work if lines are greater than 255 chars.
+   * Blah */
+  alloc = list->n_aliases + 16;
+  list->aliases = realloc (list->aliases, alloc * sizeof (XdgAlias));
+  while (fgets (line, 255, file) != NULL)
+    {
+      char *sep;
+      if (line[0] == '#')
+	continue;
+
+      sep = strchr (line, ' ');
+      if (sep == NULL)
+	continue;
+      *(sep++) = '\000';
+      sep[strlen (sep) -1] = '\000';
+      if (list->n_aliases == alloc)
+	{
+	  alloc <<= 1;
+	  list->aliases = realloc (list->aliases, 
+				   alloc * sizeof (XdgAlias));
+	}
+      list->aliases[list->n_aliases].alias = strdup (line);
+      list->aliases[list->n_aliases].mime_type = strdup (sep);
+      list->n_aliases++;
+    }
+  list->aliases = realloc (list->aliases, 
+			   list->n_aliases * sizeof (XdgAlias));
+
+  fclose (file);  
+  
+  if (list->n_aliases > 1)
+    qsort (list->aliases, list->n_aliases, 
+           sizeof (XdgAlias), alias_entry_cmp);
+}
+
+
+void
+_xdg_mime_alias_list_dump (XdgAliasList *list)
+{
+  int i;
+
+  if (list->aliases)
+    {
+      for (i = 0; i < list->n_aliases; i++)
+	{
+	  printf ("%s %s\n", 
+		  list->aliases[i].alias,
+		  list->aliases[i].mime_type);
+	}
+    }
+}
+
+
diff --git a/lib/xdgmime/xdgmimealias.h b/lib/xdgmime/xdgmimealias.h
new file mode 100644
index 00000000..3df18d66
--- /dev/null
+++ b/lib/xdgmime/xdgmimealias.h
@@ -0,0 +1,50 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* xdgmimealias.h: Private file.  Datastructure for storing the aliases.
+ *
+ * More info can be found at http://www.freedesktop.org/standards/
+ *
+ * Copyright (C) 2004  Red Hat, Inc.
+ * Copyright (C) 200  Matthias Clasen <mclasen@redhat.com>
+ *
+ * Licensed under the Academic Free License version 2.0
+ * Or under the following terms:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __XDG_MIME_ALIAS_H__
+#define __XDG_MIME_ALIAS_H__
+
+#include "xdgmime.h"
+
+typedef struct XdgAliasList XdgAliasList;
+
+#ifdef XDG_PREFIX
+#define _xdg_mime_alias_read_from_file        XDG_ENTRY(alias_read_from_file)
+#define _xdg_mime_alias_list_new              XDG_ENTRY(alias_list_new)
+#define _xdg_mime_alias_list_free             XDG_ENTRY(alias_list_free)
+#define _xdg_mime_alias_list_lookup           XDG_ENTRY(alias_list_lookup)
+#endif
+
+void          _xdg_mime_alias_read_from_file (XdgAliasList *list,
+					      const char   *file_name);
+XdgAliasList *_xdg_mime_alias_list_new       (void);
+void          _xdg_mime_alias_list_free      (XdgAliasList *list);
+const char   *_xdg_mime_alias_list_lookup    (XdgAliasList *list,
+					      const char  *alias);
+void          _xdg_mime_alias_list_dump      (XdgAliasList *list);
+
+#endif /* __XDG_MIME_ALIAS_H__ */
diff --git a/lib/xdgmime/xdgmimecache.c b/lib/xdgmime/xdgmimecache.c
new file mode 100644
index 00000000..8804eab5
--- /dev/null
+++ b/lib/xdgmime/xdgmimecache.c
@@ -0,0 +1,895 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* xdgmimealias.c: Private file.  mmappable caches for mime data
+ *
+ * More info can be found at http://www.freedesktop.org/standards/
+ *
+ * Copyright (C) 2005  Matthias Clasen <mclasen@redhat.com>
+ *
+ * Licensed under the Academic Free License version 2.0
+ * Or under the following terms:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <fnmatch.h>
+#include <assert.h>
+
+#include <netinet/in.h> /* for ntohl/ntohs */
+
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "xdgmimecache.h"
+#include "xdgmimeint.h"
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef	FALSE
+#define	FALSE	(0)
+#endif
+
+#ifndef	TRUE
+#define	TRUE	(!FALSE)
+#endif
+
+#ifndef _O_BINARY
+#define _O_BINARY 0
+#endif
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *) -1)
+#endif
+
+#define MAJOR_VERSION 1
+#define MINOR_VERSION 0
+
+struct _XdgMimeCache
+{
+  int ref_count;
+
+  size_t  size;
+  char   *buffer;
+};
+
+#define GET_UINT16(cache,offset) (ntohs(*(xdg_uint16_t*)((cache) + (offset))))
+#define GET_UINT32(cache,offset) (ntohl(*(xdg_uint32_t*)((cache) + (offset))))
+
+XdgMimeCache *
+_xdg_mime_cache_ref (XdgMimeCache *cache)
+{
+  cache->ref_count++;
+  return cache;
+}
+
+void
+_xdg_mime_cache_unref (XdgMimeCache *cache)
+{
+  cache->ref_count--;
+
+  if (cache->ref_count == 0)
+    {
+#ifdef HAVE_MMAP
+      munmap (cache->buffer, cache->size);
+#endif
+      free (cache);
+    }
+}
+
+XdgMimeCache *
+_xdg_mime_cache_new_from_file (const char *file_name)
+{
+  XdgMimeCache *cache = NULL;
+
+#ifdef HAVE_MMAP
+  int fd = -1;
+  struct stat st;
+  char *buffer = NULL;
+
+  /* Open the file and map it into memory */
+  fd = open (file_name, O_RDONLY|_O_BINARY, 0);
+
+  if (fd < 0)
+    return NULL;
+  
+  if (fstat (fd, &st) < 0 || st.st_size < 4)
+    goto done;
+
+  buffer = (char *) mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+
+  if (buffer == MAP_FAILED)
+    goto done;
+
+  /* Verify version */
+  if (GET_UINT16 (buffer, 0) != MAJOR_VERSION ||
+      GET_UINT16 (buffer, 2) != MINOR_VERSION)
+    {
+      munmap (buffer, st.st_size);
+
+      goto done;
+    }
+  
+  cache = (XdgMimeCache *) malloc (sizeof (XdgMimeCache));
+  cache->ref_count = 1;
+  cache->buffer = buffer;
+  cache->size = st.st_size;
+
+ done:
+  if (fd != -1)
+    close (fd);
+
+#endif  /* HAVE_MMAP */
+
+  return cache;
+}
+
+static int
+cache_magic_matchlet_compare_to_data (XdgMimeCache *cache, 
+				      xdg_uint32_t  offset,
+				      const void   *data,
+				      size_t        len)
+{
+  xdg_uint32_t range_start = GET_UINT32 (cache->buffer, offset);
+  xdg_uint32_t range_length = GET_UINT32 (cache->buffer, offset + 4);
+  xdg_uint32_t data_length = GET_UINT32 (cache->buffer, offset + 12);
+  xdg_uint32_t data_offset = GET_UINT32 (cache->buffer, offset + 16);
+  xdg_uint32_t mask_offset = GET_UINT32 (cache->buffer, offset + 20);
+  
+  int i, j;
+
+  for (i = range_start; i <= range_start + range_length; i++)
+    {
+      int valid_matchlet = TRUE;
+      
+      if (i + data_length > len)
+	return FALSE;
+
+      if (mask_offset)
+	{
+	  for (j = 0; j < data_length; j++)
+	    {
+	      if ((((unsigned char *)cache->buffer)[data_offset + j] & ((unsigned char *)cache->buffer)[mask_offset + j]) !=
+		  ((((unsigned char *) data)[j + i]) & ((unsigned char *)cache->buffer)[mask_offset + j]))
+		{
+		  valid_matchlet = FALSE;
+		  break;
+		}
+	    }
+	}
+      else
+	{
+	  for (j = 0; j < data_length; j++)
+	    {
+	      if (((unsigned char *)cache->buffer)[data_offset + j] != ((unsigned char *) data)[j + i])
+		{
+		  valid_matchlet = FALSE;
+		  break;
+		}
+	    }
+	}
+      
+      if (valid_matchlet)
+	return TRUE;
+    }
+  
+  return FALSE;  
+}
+
+static int
+cache_magic_matchlet_compare (XdgMimeCache *cache, 
+			      xdg_uint32_t  offset,
+			      const void   *data,
+			      size_t        len)
+{
+  xdg_uint32_t n_children = GET_UINT32 (cache->buffer, offset + 24);
+  xdg_uint32_t child_offset = GET_UINT32 (cache->buffer, offset + 28);
+
+  int i;
+  
+  if (cache_magic_matchlet_compare_to_data (cache, offset, data, len))
+    {
+      if (n_children == 0)
+	return TRUE;
+      
+      for (i = 0; i < n_children; i++)
+	{
+	  if (cache_magic_matchlet_compare (cache, child_offset + 32 * i,
+					    data, len))
+	    return TRUE;
+	}
+    }
+  
+  return FALSE;  
+}
+
+static const char *
+cache_magic_compare_to_data (XdgMimeCache *cache, 
+			     xdg_uint32_t  offset,
+			     const void   *data, 
+			     size_t        len, 
+			     int          *prio)
+{
+  xdg_uint32_t priority = GET_UINT32 (cache->buffer, offset);
+  xdg_uint32_t mimetype_offset = GET_UINT32 (cache->buffer, offset + 4);
+  xdg_uint32_t n_matchlets = GET_UINT32 (cache->buffer, offset + 8);
+  xdg_uint32_t matchlet_offset = GET_UINT32 (cache->buffer, offset + 12);
+
+  int i;
+
+  for (i = 0; i < n_matchlets; i++)
+    {
+      if (cache_magic_matchlet_compare (cache, matchlet_offset + i * 32, 
+					data, len))
+	{
+	  *prio = priority;
+	  
+	  return cache->buffer + mimetype_offset;
+	}
+    }
+
+  return NULL;
+}
+
+static const char *
+cache_magic_lookup_data (XdgMimeCache *cache, 
+			 const void   *data, 
+			 size_t        len, 
+			 int          *prio,
+			 const char   *mime_types[],
+			 int           n_mime_types)
+{
+  xdg_uint32_t list_offset;
+  xdg_uint32_t n_entries;
+  xdg_uint32_t offset;
+
+  int j, n;
+
+  *prio = 0;
+
+  list_offset = GET_UINT32 (cache->buffer, 24);
+  n_entries = GET_UINT32 (cache->buffer, list_offset);
+  offset = GET_UINT32 (cache->buffer, list_offset + 8);
+  
+  for (j = 0; j < n_entries; j++)
+    {
+      const char *match;
+
+      match = cache_magic_compare_to_data (cache, offset + 16 * j, 
+					   data, len, prio);
+      if (match)
+	return match;
+      else
+	{
+	  xdg_uint32_t mimetype_offset;
+	  const char *non_match;
+	  
+	  mimetype_offset = GET_UINT32 (cache->buffer, offset + 16 * j + 4);
+	  non_match = cache->buffer + mimetype_offset;
+
+	  for (n = 0; n < n_mime_types; n++)
+	    {
+	      if (mime_types[n] && 
+		  xdg_mime_mime_type_equal (mime_types[n], non_match))
+		mime_types[n] = NULL;
+	    }
+	}
+    }
+
+  return NULL;
+}
+
+static const char *
+cache_alias_lookup (const char *alias)
+{
+  const char *ptr;
+  int i, min, max, mid, cmp;
+
+  for (i = 0; _caches[i]; i++)
+    {
+      XdgMimeCache *cache = _caches[i];
+      xdg_uint32_t list_offset = GET_UINT32 (cache->buffer, 4);
+      xdg_uint32_t n_entries = GET_UINT32 (cache->buffer, list_offset);
+      xdg_uint32_t offset;
+
+      min = 0; 
+      max = n_entries - 1;
+      while (max >= min) 
+	{
+	  mid = (min + max) / 2;
+
+	  offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * mid);
+	  ptr = cache->buffer + offset;
+	  cmp = strcmp (ptr, alias);
+	  
+	  if (cmp < 0)
+	    min = mid + 1;
+	  else if (cmp > 0)
+	    max = mid - 1;
+	  else
+	    {
+	      offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * mid + 4);
+	      return cache->buffer + offset;
+	    }
+	}
+    }
+
+  return NULL;
+}
+
+static int
+cache_glob_lookup_literal (const char *file_name,
+			   const char *mime_types[],
+			   int         n_mime_types)
+{
+  const char *ptr;
+  int i, min, max, mid, cmp;
+
+  for (i = 0; _caches[i]; i++)
+    {
+      XdgMimeCache *cache = _caches[i];
+      xdg_uint32_t list_offset = GET_UINT32 (cache->buffer, 12);
+      xdg_uint32_t n_entries = GET_UINT32 (cache->buffer, list_offset);
+      xdg_uint32_t offset;
+
+      min = 0; 
+      max = n_entries - 1;
+      while (max >= min) 
+	{
+	  mid = (min + max) / 2;
+
+	  offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * mid);
+	  ptr = cache->buffer + offset;
+	  cmp = strcmp (ptr, file_name);
+	  
+	  if (cmp < 0)
+	    min = mid + 1;
+	  else if (cmp > 0)
+	    max = mid - 1;
+	  else
+	    {
+	      offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * mid + 4);
+	      mime_types[0] = (const char *)(cache->buffer + offset);
+	      
+	      return 1;
+	    }
+	}
+    }
+
+  return 0;
+}
+
+static int
+cache_glob_lookup_fnmatch (const char *file_name,
+			   const char *mime_types[],
+			   int         n_mime_types)
+{
+  const char *mime_type;
+  const char *ptr;
+
+  int i, j, n;
+
+  n = 0;
+  for (i = 0; _caches[i]; i++)
+    {
+      XdgMimeCache *cache = _caches[i];
+
+      xdg_uint32_t list_offset = GET_UINT32 (cache->buffer, 20);
+      xdg_uint32_t n_entries = GET_UINT32 (cache->buffer, list_offset);
+
+      for (j = 0; j < n_entries && n < n_mime_types; j++)
+	{
+	  xdg_uint32_t offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * j);
+	  xdg_uint32_t mimetype_offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * j + 4);
+	  ptr = cache->buffer + offset;
+	  mime_type = cache->buffer + mimetype_offset;
+
+	  /* FIXME: Not UTF-8 safe */
+	  if (fnmatch (ptr, file_name, 0) == 0)
+	    mime_types[n++] = mime_type;
+	}
+
+      if (n > 0)
+	return n;
+    }
+  
+  return 0;
+}
+
+static int
+cache_glob_node_lookup_suffix (XdgMimeCache *cache,
+			       xdg_uint32_t  n_entries,
+			       xdg_uint32_t  offset,
+			       const char   *suffix, 
+			       int           ignore_case,
+			       const char   *mime_types[],
+			       int           n_mime_types)
+{
+  xdg_unichar_t character;
+  xdg_unichar_t match_char;
+  xdg_uint32_t mimetype_offset;
+  xdg_uint32_t n_children;
+  xdg_uint32_t child_offset; 
+
+  int min, max, mid, n, i;
+
+  character = _xdg_utf8_to_ucs4 (suffix);
+  if (ignore_case)
+    character = _xdg_ucs4_to_lower (character);
+
+  min = 0;
+  max = n_entries - 1;
+  while (max >= min)
+    {
+      mid = (min + max) /  2;
+
+      match_char = GET_UINT32 (cache->buffer, offset + 16 * mid);
+
+      if (match_char < character)
+	min = mid + 1;
+      else if (match_char > character)
+	max = mid - 1;
+      else 
+	{
+	  suffix = _xdg_utf8_next_char (suffix);
+	  if (*suffix == '\0')
+	    {
+	      mimetype_offset = GET_UINT32 (cache->buffer, offset + 16 * mid + 4);
+	      n = 0;
+	      if (mimetype_offset)
+		mime_types[n++] = cache->buffer + mimetype_offset;
+	      
+	      n_children = GET_UINT32 (cache->buffer, offset + 16 * mid + 8);
+	      child_offset = GET_UINT32 (cache->buffer, offset + 16 * mid + 12);
+	      i = 0;
+	      while (n < n_mime_types && i < n_children)
+		{
+		  match_char = GET_UINT32 (cache->buffer, child_offset + 16 * i);
+		  mimetype_offset = GET_UINT32 (cache->buffer, offset + 16 * i + 4);
+		  if (match_char != 0)
+		    break;
+
+		  mime_types[n++] = cache->buffer + mimetype_offset;
+		  i++;
+		}
+
+	      return n;
+	    }
+	  else
+	    {
+	      n_children = GET_UINT32 (cache->buffer, offset + 16 * mid + 8);
+	      child_offset = GET_UINT32 (cache->buffer, offset + 16 * mid + 12);
+      
+	      return cache_glob_node_lookup_suffix (cache, 
+						    n_children, child_offset,
+						    suffix, ignore_case,
+						    mime_types,
+						    n_mime_types);
+	    }
+	}
+    }
+
+  return 0;
+}
+
+static int
+cache_glob_lookup_suffix (const char *suffix, 
+			  int         ignore_case,
+			  const char *mime_types[],
+			  int         n_mime_types)
+{
+  int i, n;
+
+  for (i = 0; _caches[i]; i++)
+    {
+      XdgMimeCache *cache = _caches[i];
+
+      xdg_uint32_t list_offset = GET_UINT32 (cache->buffer, 16);
+      xdg_uint32_t n_entries = GET_UINT32 (cache->buffer, list_offset);
+      xdg_uint32_t offset = GET_UINT32 (cache->buffer, list_offset + 4);
+
+      n = cache_glob_node_lookup_suffix (cache, 
+					 n_entries, offset, 
+					 suffix, ignore_case,
+					 mime_types,
+					 n_mime_types);
+      if (n > 0)
+	return n;
+    }
+
+  return 0;
+}
+
+static void
+find_stopchars (char *stopchars)
+{
+  int i, j, k, l;
+ 
+  k = 0;
+  for (i = 0; _caches[i]; i++)
+    {
+      XdgMimeCache *cache = _caches[i];
+
+      xdg_uint32_t list_offset = GET_UINT32 (cache->buffer, 16);
+      xdg_uint32_t n_entries = GET_UINT32 (cache->buffer, list_offset);
+      xdg_uint32_t offset = GET_UINT32 (cache->buffer, list_offset + 4);
+
+      for (j = 0; j < n_entries; j++)
+	{
+	  xdg_uint32_t match_char = GET_UINT32 (cache->buffer, offset);
+	  
+	  if (match_char < 128)
+	    {
+	      for (l = 0; l < k; l++)
+		if (stopchars[l] == match_char)
+		  break;
+	      if (l == k)
+		{
+		  stopchars[k] = (char) match_char;
+		  k++;
+		}
+	    }
+
+	  offset += 16;
+	}
+    }
+
+  stopchars[k] = '\0';
+}
+
+static int
+cache_glob_lookup_file_name (const char *file_name, 
+			     const char *mime_types[],
+			     int         n_mime_types)
+{
+  const char *ptr;
+  char stopchars[128];
+  int n;
+  
+  assert (file_name != NULL);
+
+  /* First, check the literals */
+  n = cache_glob_lookup_literal (file_name, mime_types, n_mime_types);
+  if (n > 0)
+    return n;
+
+  find_stopchars (stopchars);
+
+  /* Next, check suffixes */
+  ptr = strpbrk (file_name, stopchars);
+  while (ptr)
+    {
+      n = cache_glob_lookup_suffix (ptr, FALSE, mime_types, n_mime_types);
+      if (n > 0)
+	return n;
+      
+      n = cache_glob_lookup_suffix (ptr, TRUE, mime_types, n_mime_types);
+      if (n > 0)
+	return n;
+
+      ptr = strpbrk (ptr + 1, stopchars);
+    }
+  
+  /* Last, try fnmatch */
+  return cache_glob_lookup_fnmatch (file_name, mime_types, n_mime_types);
+}
+
+int
+_xdg_mime_cache_get_max_buffer_extents (void)
+{
+  xdg_uint32_t offset;
+  xdg_uint32_t max_extent;
+  int i;
+
+  max_extent = 0;
+  for (i = 0; _caches[i]; i++)
+    {
+      XdgMimeCache *cache = _caches[i];
+
+      offset = GET_UINT32 (cache->buffer, 24);
+      max_extent = MAX (max_extent, GET_UINT32 (cache->buffer, offset + 4));
+    }
+
+  return max_extent;
+}
+
+static const char *
+cache_get_mime_type_for_data (const void *data,
+			      size_t      len,
+			      const char *mime_types[],
+			      int         n_mime_types)
+{
+  const char *mime_type;
+  int i, n, priority;
+
+  priority = 0;
+  mime_type = NULL;
+  for (i = 0; _caches[i]; i++)
+    {
+      XdgMimeCache *cache = _caches[i];
+
+      int prio;
+      const char *match;
+
+      match = cache_magic_lookup_data (cache, data, len, &prio, 
+				       mime_types, n_mime_types);
+      if (prio > priority)
+	{
+	  priority = prio;
+	  mime_type = match;
+	}
+    }
+
+  if (priority > 0)
+    return mime_type;
+
+  for (n = 0; n < n_mime_types; n++)
+    {
+      if (mime_types[n])
+	return mime_types[n];
+    }
+
+  return XDG_MIME_TYPE_UNKNOWN;
+}
+
+const char *
+_xdg_mime_cache_get_mime_type_for_data (const void *data,
+					size_t      len)
+{
+  return cache_get_mime_type_for_data (data, len, NULL, 0);
+}
+
+const char *
+_xdg_mime_cache_get_mime_type_for_file (const char  *file_name,
+					struct stat *statbuf)
+{
+  const char *mime_type;
+  const char *mime_types[2];
+  FILE *file;
+  unsigned char *data;
+  int max_extent;
+  int bytes_read;
+  struct stat buf;
+  const char *base_name;
+  int n;
+
+  if (file_name == NULL)
+    return NULL;
+
+  if (! _xdg_utf8_validate (file_name))
+    return NULL;
+
+  base_name = _xdg_get_base_name (file_name);
+  n = cache_glob_lookup_file_name (base_name, mime_types, 2);
+
+  if (n == 1)
+    return mime_types[0];
+
+  if (!statbuf)
+    {
+      if (stat (file_name, &buf) != 0)
+	return XDG_MIME_TYPE_UNKNOWN;
+
+      statbuf = &buf;
+    }
+
+  if (!S_ISREG (statbuf->st_mode))
+    return XDG_MIME_TYPE_UNKNOWN;
+
+  /* FIXME: Need to make sure that max_extent isn't totally broken.  This could
+   * be large and need getting from a stream instead of just reading it all
+   * in. */
+  max_extent = _xdg_mime_cache_get_max_buffer_extents ();
+  data = malloc (max_extent);
+  if (data == NULL)
+    return XDG_MIME_TYPE_UNKNOWN;
+        
+  file = fopen (file_name, "r");
+  if (file == NULL)
+    {
+      free (data);
+      return XDG_MIME_TYPE_UNKNOWN;
+    }
+
+  bytes_read = fread (data, 1, max_extent, file);
+  if (ferror (file))
+    {
+      free (data);
+      fclose (file);
+      return XDG_MIME_TYPE_UNKNOWN;
+    }
+
+  mime_type = cache_get_mime_type_for_data (data, bytes_read,
+					    mime_types, n);
+
+  free (data);
+  fclose (file);
+
+  return mime_type;
+}
+
+const char *
+_xdg_mime_cache_get_mime_type_from_file_name (const char *file_name)
+{
+  const char *mime_type;
+
+  if (cache_glob_lookup_file_name (file_name, &mime_type, 1))
+    return mime_type;
+  else
+    return XDG_MIME_TYPE_UNKNOWN;
+}
+
+#if 1
+static int
+is_super_type (const char *mime)
+{
+  int length;
+  const char *type;
+
+  length = strlen (mime);
+  type = &(mime[length - 2]);
+
+  if (strcmp (type, "/*") == 0)
+    return 1;
+
+  return 0;
+}
+#endif
+
+int
+_xdg_mime_cache_mime_type_subclass (const char *mime,
+				    const char *base)
+{
+  const char *umime, *ubase;
+
+  int i, j, min, max, med, cmp;
+  
+  umime = _xdg_mime_cache_unalias_mime_type (mime);
+  ubase = _xdg_mime_cache_unalias_mime_type (base);
+
+  if (strcmp (umime, ubase) == 0)
+    return 1;
+
+  /* We really want to handle text/ * in GtkFileFilter, so we just
+   * turn on the supertype matching
+   */
+#if 1
+  /* Handle supertypes */
+  if (is_super_type (ubase) &&
+      xdg_mime_media_type_equal (umime, ubase))
+    return 1;
+#endif
+
+  /*  Handle special cases text/plain and application/octet-stream */
+  if (strcmp (ubase, "text/plain") == 0 && 
+      strncmp (umime, "text/", 5) == 0)
+    return 1;
+
+  if (strcmp (ubase, "application/octet-stream") == 0)
+    return 1;
+ 
+  for (i = 0; _caches[i]; i++)
+    {
+      XdgMimeCache *cache = _caches[i];
+      
+      xdg_uint32_t list_offset = GET_UINT32 (cache->buffer, 8);
+      xdg_uint32_t n_entries = GET_UINT32 (cache->buffer, list_offset);
+      xdg_uint32_t offset, n_parents, parent_offset;
+
+      min = 0; 
+      max = n_entries - 1;
+      while (max >= min)
+	{
+	  med = (min + max)/2;
+	  
+	  offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * med);
+	  cmp = strcmp (cache->buffer + offset, umime);
+	  if (cmp < 0)
+	    min = med + 1;
+	  else if (cmp > 0)
+	    max = med - 1;
+	  else
+	    {
+	      offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * med + 4);
+	      n_parents = GET_UINT32 (cache->buffer, offset);
+	      
+	      for (j = 0; j < n_parents; j++)
+		{
+		  parent_offset = GET_UINT32 (cache->buffer, offset + 4 + 4 * j);
+		  if (_xdg_mime_cache_mime_type_subclass (cache->buffer + parent_offset, ubase))
+		    return 1;
+		}
+
+	      break;
+	    }
+	}
+    }
+
+  return 0;
+}
+
+const char *
+_xdg_mime_cache_unalias_mime_type (const char *mime)
+{
+  const char *lookup;
+  
+  lookup = cache_alias_lookup (mime);
+  
+  if (lookup)
+    return lookup;
+  
+  return mime;  
+}
+
+char **
+_xdg_mime_cache_list_mime_parents (const char *mime)
+{
+  int i, j, k, p;
+  char *all_parents[128]; /* we'll stop at 128 */ 
+  char **result;
+
+  mime = xdg_mime_unalias_mime_type (mime);
+
+  p = 0;
+  for (i = 0; _caches[i]; i++)
+    {
+      XdgMimeCache *cache = _caches[i];
+  
+      xdg_uint32_t list_offset = GET_UINT32 (cache->buffer, 8);
+      xdg_uint32_t n_entries = GET_UINT32 (cache->buffer, list_offset);
+
+      for (j = 0; j < n_entries; j++)
+	{
+	  xdg_uint32_t mimetype_offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * j);
+	  xdg_uint32_t parents_offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * j + 4);
+
+	  if (strcmp (cache->buffer + mimetype_offset, mime) == 0)
+	    {
+	      xdg_uint32_t parent_mime_offset;
+	      xdg_uint32_t n_parents = GET_UINT32 (cache->buffer, parents_offset);
+
+	      for (k = 0; k < n_parents && p < 127; k++)
+		{
+		  parent_mime_offset = GET_UINT32 (cache->buffer, parents_offset + 4 + 4 * k);
+		  all_parents[p++] = cache->buffer + parent_mime_offset;
+		}
+
+	      break;
+	    }
+	}
+    }
+  all_parents[p++] = 0;
+  
+  result = (char **) malloc (p * sizeof (char *));
+  memcpy (result, all_parents, p * sizeof (char *));
+
+  return result;
+}
+
diff --git a/lib/xdgmime/xdgmimecache.h b/lib/xdgmime/xdgmimecache.h
new file mode 100644
index 00000000..61793cb7
--- /dev/null
+++ b/lib/xdgmime/xdgmimecache.h
@@ -0,0 +1,63 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* xdgmimecache.h: Private file.  Datastructure for mmapped caches.
+ *
+ * More info can be found at http://www.freedesktop.org/standards/
+ *
+ * Copyright (C) 2005  Matthias Clasen <mclasen@redhat.com>
+ *
+ * Licensed under the Academic Free License version 2.0
+ * Or under the following terms:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __XDG_MIME_CACHE_H__
+#define __XDG_MIME_CACHE_H__
+
+#include "xdgmime.h"
+
+typedef struct _XdgMimeCache XdgMimeCache;
+
+#ifdef XDG_PREFIX
+#define _xdg_mime_cache_new_from_file        XDG_ENTRY(cache_new_from_file)
+#define _xdg_mime_cache_ref                  XDG_ENTRY(cache_ref)
+#define _xdg_mime_cache_unref                XDG_ENTRY(cache_unref)
+#endif
+
+extern XdgMimeCache **_caches;
+
+XdgMimeCache *_xdg_mime_cache_new_from_file (const char   *file_name);
+XdgMimeCache *_xdg_mime_cache_ref           (XdgMimeCache *cache);
+void          _xdg_mime_cache_unref         (XdgMimeCache *cache);
+
+
+const char  *_xdg_mime_cache_get_mime_type_for_data       (const void *data,
+		 				           size_t      len);
+const char  *_xdg_mime_cache_get_mime_type_for_file       (const char  *file_name,
+							   struct stat *statbuf);
+const char  *_xdg_mime_cache_get_mime_type_from_file_name (const char *file_name);
+int          _xdg_mime_cache_is_valid_mime_type           (const char *mime_type);
+int          _xdg_mime_cache_mime_type_equal              (const char *mime_a,
+						           const char *mime_b);
+int          _xdg_mime_cache_media_type_equal             (const char *mime_a,
+							   const char *mime_b);
+int          _xdg_mime_cache_mime_type_subclass           (const char *mime_a,
+							   const char *mime_b);
+char       **_xdg_mime_cache_list_mime_parents		  (const char *mime);
+const char  *_xdg_mime_cache_unalias_mime_type            (const char *mime);
+int          _xdg_mime_cache_get_max_buffer_extents       (void);
+
+#endif /* __XDG_MIME_CACHE_H__ */
diff --git a/lib/xdgmime/xdgmimeglob.c b/lib/xdgmime/xdgmimeglob.c
new file mode 100644
index 00000000..95d9587f
--- /dev/null
+++ b/lib/xdgmime/xdgmimeglob.c
@@ -0,0 +1,547 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* xdgmimeglob.c: Private file.  Datastructure for storing the globs.
+ *
+ * More info can be found at http://www.freedesktop.org/standards/
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ * Copyright (C) 2003  Jonathan Blandford <jrb@alum.mit.edu>
+ *
+ * Licensed under the Academic Free License version 2.0
+ * Or under the following terms:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "xdgmimeglob.h"
+#include "xdgmimeint.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <fnmatch.h>
+
+#ifndef	FALSE
+#define	FALSE	(0)
+#endif
+
+#ifndef	TRUE
+#define	TRUE	(!FALSE)
+#endif
+
+typedef struct XdgGlobHashNode XdgGlobHashNode;
+typedef struct XdgGlobList XdgGlobList;
+
+struct XdgGlobHashNode
+{
+  xdg_unichar_t character;
+  const char *mime_type;
+  XdgGlobHashNode *next;
+  XdgGlobHashNode *child;
+};
+struct XdgGlobList
+{
+  const char *data;
+  const char *mime_type;
+  XdgGlobList *next;
+};
+
+struct XdgGlobHash
+{
+  XdgGlobList *literal_list;
+  XdgGlobHashNode *simple_node;
+  XdgGlobList *full_list;
+};
+
+
+/* XdgGlobList
+ */
+static XdgGlobList *
+_xdg_glob_list_new (void)
+{
+  XdgGlobList *new_element;
+
+  new_element = calloc (1, sizeof (XdgGlobList));
+
+  return new_element;
+}
+
+/* Frees glob_list and all of it's children */
+static void
+_xdg_glob_list_free (XdgGlobList *glob_list)
+{
+  XdgGlobList *ptr, *next;
+
+  ptr = glob_list;
+
+  while (ptr != NULL)
+    {
+      next = ptr->next;
+
+      if (ptr->data)
+	free ((void *) ptr->data);
+      if (ptr->mime_type)
+	free ((void *) ptr->mime_type);
+      free (ptr);
+
+      ptr = next;
+    }
+}
+
+static XdgGlobList *
+_xdg_glob_list_append (XdgGlobList *glob_list,
+		       void        *data,
+		       const char  *mime_type)
+{
+  XdgGlobList *new_element;
+  XdgGlobList *tmp_element;
+
+  new_element = _xdg_glob_list_new ();
+  new_element->data = data;
+  new_element->mime_type = mime_type;
+  if (glob_list == NULL)
+    return new_element;
+
+  tmp_element = glob_list;
+  while (tmp_element->next != NULL)
+    tmp_element = tmp_element->next;
+
+  tmp_element->next = new_element;
+
+  return glob_list;
+}
+
+#if 0
+static XdgGlobList *
+_xdg_glob_list_prepend (XdgGlobList *glob_list,
+			void        *data,
+			const char  *mime_type)
+{
+  XdgGlobList *new_element;
+
+  new_element = _xdg_glob_list_new ();
+  new_element->data = data;
+  new_element->next = glob_list;
+  new_element->mime_type = mime_type;
+
+  return new_element;
+}
+#endif
+
+/* XdgGlobHashNode
+ */
+
+static XdgGlobHashNode *
+_xdg_glob_hash_node_new (void)
+{
+  XdgGlobHashNode *glob_hash_node;
+
+  glob_hash_node = calloc (1, sizeof (XdgGlobHashNode));
+
+  return glob_hash_node;
+}
+
+static void
+_xdg_glob_hash_node_dump (XdgGlobHashNode *glob_hash_node,
+			  int depth)
+{
+  int i;
+  for (i = 0; i < depth; i++)
+    printf (" ");
+
+  printf ("%c", (char)glob_hash_node->character);
+  if (glob_hash_node->mime_type)
+    printf (" - %s\n", glob_hash_node->mime_type);
+  else
+    printf ("\n");
+  if (glob_hash_node->child)
+    _xdg_glob_hash_node_dump (glob_hash_node->child, depth + 1);
+  if (glob_hash_node->next)
+    _xdg_glob_hash_node_dump (glob_hash_node->next, depth);
+}
+
+static XdgGlobHashNode *
+_xdg_glob_hash_insert_text (XdgGlobHashNode *glob_hash_node,
+			    const char      *text,
+			    const char      *mime_type)
+{
+  XdgGlobHashNode *node;
+  xdg_unichar_t character;
+
+  character = _xdg_utf8_to_ucs4 (text);
+
+  if ((glob_hash_node == NULL) ||
+      (character < glob_hash_node->character))
+    {
+      node = _xdg_glob_hash_node_new ();
+      node->character = character;
+      node->next = glob_hash_node;
+      glob_hash_node = node;
+    }
+  else if (character == glob_hash_node->character)
+    {
+      node = glob_hash_node;
+    }
+  else
+    {
+      XdgGlobHashNode *prev_node;
+      int found_node = FALSE;
+
+      /* Look for the first character of text in glob_hash_node, and insert it if we
+       * have to.*/
+      prev_node = glob_hash_node;
+      node = prev_node->next;
+
+      while (node != NULL)
+	{
+	  if (character < node->character)
+	    {
+	      node = _xdg_glob_hash_node_new ();
+	      node->character = character;
+	      node->next = prev_node->next;
+	      prev_node->next = node;
+
+	      found_node = TRUE;
+	      break;
+	    }
+	  else if (character == node->character)
+	    {
+	      found_node = TRUE;
+	      break;
+	    }
+	  prev_node = node;
+	  node = node->next;
+	}
+
+      if (! found_node)
+	{
+	  node = _xdg_glob_hash_node_new ();
+	  node->character = character;
+	  node->next = prev_node->next;
+	  prev_node->next = node;
+	}
+    }
+
+  text = _xdg_utf8_next_char (text);
+  if (*text == '\000')
+    {
+      if (node->mime_type)
+	{
+	  if (strcmp (node->mime_type, mime_type))
+	    {
+	      XdgGlobHashNode *child;
+	      int found_node = FALSE;
+	      
+	      child = node->child;
+	      while (child && child->character == '\0')
+		{
+		  if (strcmp (child->mime_type, mime_type) == 0)
+		    {
+		      found_node = TRUE;
+		      break;
+		    }
+		  child = child->next;
+		}
+
+	      if (!found_node)
+		{
+		  child = _xdg_glob_hash_node_new ();
+		  child->character = '\000';
+		  child->mime_type = mime_type;
+		  child->child = NULL;
+		  child->next = node->child;
+		  node->child = child;
+		}
+	    }
+	}
+      else
+	{
+	  node->mime_type = mime_type;
+	}
+    }
+  else
+    {
+      node->child = _xdg_glob_hash_insert_text (node->child, text, mime_type);
+    }
+  return glob_hash_node;
+}
+
+static int
+_xdg_glob_hash_node_lookup_file_name (XdgGlobHashNode *glob_hash_node,
+				      const char      *file_name,
+				      int              ignore_case,
+				      const char      *mime_types[],
+				      int              n_mime_types)
+{
+  int n;
+  XdgGlobHashNode *node;
+  xdg_unichar_t character;
+
+  if (glob_hash_node == NULL)
+    return 0;
+
+  character = _xdg_utf8_to_ucs4 (file_name);
+  if (ignore_case)
+    character = _xdg_ucs4_to_lower(character);
+
+  for (node = glob_hash_node; node && character >= node->character; node = node->next)
+    {
+      if (character == node->character)
+	{
+	  file_name = _xdg_utf8_next_char (file_name);
+	  if (*file_name == '\000')
+	    {
+	      n = 0;
+              if (node->mime_type)
+	        mime_types[n++] = node->mime_type;
+	      node = node->child;
+	      while (n < n_mime_types && node && node->character == 0)
+		{
+                  if (node->mime_type)
+		    mime_types[n++] = node->mime_type;
+		  node = node->next;
+		}
+	    }
+	  else
+	    {
+	      n = _xdg_glob_hash_node_lookup_file_name (node->child,
+							file_name,
+							ignore_case,
+							mime_types,
+							n_mime_types);
+	    }
+	  return n;
+	}
+    }
+
+  return 0;
+}
+
+int
+_xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash,
+				 const char  *file_name,
+				 const char  *mime_types[],
+				 int          n_mime_types)
+{
+  XdgGlobList *list;
+  const char *ptr;
+  char stopchars[128];
+  int i, n;
+  XdgGlobHashNode *node;
+
+  /* First, check the literals */
+
+  assert (file_name != NULL && n_mime_types > 0);
+
+  for (list = glob_hash->literal_list; list; list = list->next)
+    {
+      if (strcmp ((const char *)list->data, file_name) == 0)
+	{
+	  mime_types[0] = list->mime_type;
+	  return 1;
+	}
+    }
+
+  i = 0;
+  for (node = glob_hash->simple_node; node; node = node->next)
+    {
+      if (node->character < 128)
+ 	stopchars[i++] = (char)node->character;
+    }
+  stopchars[i] = '\0';
+ 
+  ptr = strpbrk (file_name, stopchars);
+  while (ptr)
+    {
+      n = _xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, ptr, FALSE,
+						mime_types, n_mime_types);
+      if (n > 0)
+	return n;
+      
+      n = _xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, ptr, TRUE,
+						mime_types, n_mime_types);
+      if (n > 0)
+	return n;
+      
+      ptr = strpbrk (ptr + 1, stopchars);
+    }
+
+  /* FIXME: Not UTF-8 safe */
+  n = 0;
+  for (list = glob_hash->full_list; list && n < n_mime_types; list = list->next)
+    {
+      if (fnmatch ((const char *)list->data, file_name, 0) == 0)
+	mime_types[n++] = list->mime_type;
+    }
+
+  return n;
+}
+
+
+
+/* XdgGlobHash
+ */
+
+XdgGlobHash *
+_xdg_glob_hash_new (void)
+{
+  XdgGlobHash *glob_hash;
+
+  glob_hash = calloc (1, sizeof (XdgGlobHash));
+
+  return glob_hash;
+}
+
+
+static void
+_xdg_glob_hash_free_nodes (XdgGlobHashNode *node)
+{
+  if (node)
+    {
+      if (node->child)
+       _xdg_glob_hash_free_nodes (node->child);
+      if (node->next)
+       _xdg_glob_hash_free_nodes (node->next);
+      if (node->mime_type)
+	free ((void *) node->mime_type);
+      free (node);
+    }
+}
+
+void
+_xdg_glob_hash_free (XdgGlobHash *glob_hash)
+{
+  _xdg_glob_list_free (glob_hash->literal_list);
+  _xdg_glob_list_free (glob_hash->full_list);
+  _xdg_glob_hash_free_nodes (glob_hash->simple_node);
+  free (glob_hash);
+}
+
+XdgGlobType
+_xdg_glob_determine_type (const char *glob)
+{
+  const char *ptr;
+  int maybe_in_simple_glob = FALSE;
+  int first_char = TRUE;
+
+  ptr = glob;
+
+  while (*ptr != '\000')
+    {
+      if (*ptr == '*' && first_char)
+	maybe_in_simple_glob = TRUE;
+      else if (*ptr == '\\' || *ptr == '[' || *ptr == '?' || *ptr == '*')
+	  return XDG_GLOB_FULL;
+
+      first_char = FALSE;
+      ptr = _xdg_utf8_next_char (ptr);
+    }
+  if (maybe_in_simple_glob)
+    return XDG_GLOB_SIMPLE;
+  else
+    return XDG_GLOB_LITERAL;
+}
+
+/* glob must be valid UTF-8 */
+void
+_xdg_glob_hash_append_glob (XdgGlobHash *glob_hash,
+			    const char  *glob,
+			    const char  *mime_type)
+{
+  XdgGlobType type;
+
+  assert (glob_hash != NULL);
+  assert (glob != NULL);
+
+  type = _xdg_glob_determine_type (glob);
+
+  switch (type)
+    {
+    case XDG_GLOB_LITERAL:
+      glob_hash->literal_list = _xdg_glob_list_append (glob_hash->literal_list, strdup (glob), strdup (mime_type));
+      break;
+    case XDG_GLOB_SIMPLE:
+      glob_hash->simple_node = _xdg_glob_hash_insert_text (glob_hash->simple_node, glob + 1, strdup (mime_type));
+      break;
+    case XDG_GLOB_FULL:
+      glob_hash->full_list = _xdg_glob_list_append (glob_hash->full_list, strdup (glob), strdup (mime_type));
+      break;
+    }
+}
+
+void
+_xdg_glob_hash_dump (XdgGlobHash *glob_hash)
+{
+  XdgGlobList *list;
+  printf ("LITERAL STRINGS\n");
+  if (glob_hash->literal_list == NULL)
+    {
+      printf ("    None\n");
+    }
+  else
+    {
+      for (list = glob_hash->literal_list; list; list = list->next)
+	printf ("    %s - %s\n", (char *)list->data, list->mime_type);
+    }
+  printf ("\nSIMPLE GLOBS\n");
+  _xdg_glob_hash_node_dump (glob_hash->simple_node, 4);
+
+  printf ("\nFULL GLOBS\n");
+  if (glob_hash->full_list == NULL)
+    {
+      printf ("    None\n");
+    }
+  else
+    {
+      for (list = glob_hash->full_list; list; list = list->next)
+	printf ("    %s - %s\n", (char *)list->data, list->mime_type);
+    }
+}
+
+
+void
+_xdg_mime_glob_read_from_file (XdgGlobHash *glob_hash,
+			       const char  *file_name)
+{
+  FILE *glob_file;
+  char line[255];
+
+  glob_file = fopen (file_name, "r");
+
+  if (glob_file == NULL)
+    return;
+
+  /* FIXME: Not UTF-8 safe.  Doesn't work if lines are greater than 255 chars.
+   * Blah */
+  while (fgets (line, 255, glob_file) != NULL)
+    {
+      char *colon;
+      if (line[0] == '#')
+	continue;
+
+      colon = strchr (line, ':');
+      if (colon == NULL)
+	continue;
+      *(colon++) = '\000';
+      colon[strlen (colon) -1] = '\000';
+      _xdg_glob_hash_append_glob (glob_hash, colon, line);
+    }
+
+  fclose (glob_file);
+}
diff --git a/lib/xdgmime/xdgmimeglob.h b/lib/xdgmime/xdgmimeglob.h
new file mode 100644
index 00000000..25a1f20e
--- /dev/null
+++ b/lib/xdgmime/xdgmimeglob.h
@@ -0,0 +1,67 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* xdgmimeglob.h: Private file.  Datastructure for storing the globs.
+ *
+ * More info can be found at http://www.freedesktop.org/standards/
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ * Copyright (C) 2003  Jonathan Blandford <jrb@alum.mit.edu>
+ *
+ * Licensed under the Academic Free License version 2.0
+ * Or under the following terms:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __XDG_MIME_GLOB_H__
+#define __XDG_MIME_GLOB_H__
+
+#include "xdgmime.h"
+
+typedef struct XdgGlobHash XdgGlobHash;
+
+typedef enum
+{
+  XDG_GLOB_LITERAL, /* Makefile */
+  XDG_GLOB_SIMPLE,  /* *.gif */
+  XDG_GLOB_FULL     /* x*.[ch] */
+} XdgGlobType;
+
+  
+#ifdef XDG_PREFIX
+#define _xdg_mime_glob_read_from_file         XDG_ENTRY(glob_read_from_file)
+#define _xdg_glob_hash_new                    XDG_ENTRY(hash_new)
+#define _xdg_glob_hash_free                   XDG_ENTRY(hash_free)
+#define _xdg_glob_hash_lookup_file_name       XDG_ENTRY(hash_lookup_file_name)
+#define _xdg_glob_hash_append_glob            XDG_ENTRY(hash_append_glob)
+#define _xdg_glob_determine_type              XDG_ENTRY(determine_type)
+#define _xdg_glob_hash_dump                   XDG_ENTRY(hash_dump)
+#endif
+
+void         _xdg_mime_glob_read_from_file   (XdgGlobHash *glob_hash,
+					      const char  *file_name);
+XdgGlobHash *_xdg_glob_hash_new              (void);
+void         _xdg_glob_hash_free             (XdgGlobHash *glob_hash);
+int          _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash,
+					      const char  *text,
+					      const char  *mime_types[],
+					      int          n_mime_types);
+void         _xdg_glob_hash_append_glob      (XdgGlobHash *glob_hash,
+					      const char  *glob,
+					      const char  *mime_type);
+XdgGlobType  _xdg_glob_determine_type        (const char  *glob);
+void         _xdg_glob_hash_dump             (XdgGlobHash *glob_hash);
+
+#endif /* __XDG_MIME_GLOB_H__ */
diff --git a/lib/xdgmime/xdgmimeint.c b/lib/xdgmime/xdgmimeint.c
new file mode 100644
index 00000000..4a0ac4cc
--- /dev/null
+++ b/lib/xdgmime/xdgmimeint.c
@@ -0,0 +1,154 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* xdgmimeint.c: Internal defines and functions.
+ *
+ * More info can be found at http://www.freedesktop.org/standards/
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ * Copyright (C) 2003  Jonathan Blandford <jrb@alum.mit.edu>
+ *
+ * Licensed under the Academic Free License version 2.0
+ * Or under the following terms:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "xdgmimeint.h"
+#include <ctype.h>
+#include <string.h>
+
+#ifndef	FALSE
+#define	FALSE	(0)
+#endif
+
+#ifndef	TRUE
+#define	TRUE	(!FALSE)
+#endif
+
+static const char _xdg_utf8_skip_data[256] = {
+  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+  3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
+};
+
+const char * const _xdg_utf8_skip = _xdg_utf8_skip_data;
+
+
+
+/* Returns the number of unprocessed characters. */
+xdg_unichar_t
+_xdg_utf8_to_ucs4(const char *source)
+{
+  xdg_unichar_t ucs32;
+  if( ! ( *source & 0x80 ) )
+    {
+      ucs32 = *source;
+    }
+  else
+    {
+      int bytelength = 0;
+      xdg_unichar_t result;
+      if ( ! (*source & 0x40) )
+	{
+	  ucs32 = *source;
+	}
+      else
+	{
+	  if ( ! (*source & 0x20) )
+	    {
+	      result = *source++ & 0x1F;
+	      bytelength = 2;
+	    }
+	  else if ( ! (*source & 0x10) )
+	    {
+	      result = *source++ & 0x0F;
+	      bytelength = 3;
+	    }
+	  else if ( ! (*source & 0x08) )
+	    {
+	      result = *source++ & 0x07;
+	      bytelength = 4;
+	    }
+	  else if ( ! (*source & 0x04) )
+	    {
+	      result = *source++ & 0x03;
+	      bytelength = 5;
+	    }
+	  else if ( ! (*source & 0x02) )
+	    {
+	      result = *source++ & 0x01;
+	      bytelength = 6;
+	    }
+	  else
+	    {
+	      result = *source++;
+	      bytelength = 1;
+	    }
+
+	  for ( bytelength --; bytelength > 0; bytelength -- )
+	    {
+	      result <<= 6;
+	      result |= *source++ & 0x3F;
+	    }
+	  ucs32 = result;
+	}
+    }
+  return ucs32;
+}
+
+
+/* hullo.  this is great code.  don't rewrite it */
+
+xdg_unichar_t
+_xdg_ucs4_to_lower (xdg_unichar_t source)
+{
+  /* FIXME: Do a real to_upper sometime */
+  /* CaseFolding-3.2.0.txt has a table of rules. */
+  if ((source & 0xFF) == source)
+    return (xdg_unichar_t) tolower ((unsigned char) source);
+  return source;
+}
+
+int
+_xdg_utf8_validate (const char *source)
+{
+  /* FIXME: actually write */
+  return TRUE;
+}
+
+const char *
+_xdg_get_base_name (const char *file_name)
+{
+  const char *base_name;
+
+  if (file_name == NULL)
+    return NULL;
+
+  base_name = strrchr (file_name, '/');
+
+  if (base_name == NULL)
+    return file_name;
+  else
+    return base_name + 1;
+}
diff --git a/lib/xdgmime/xdgmimeint.h b/lib/xdgmime/xdgmimeint.h
new file mode 100644
index 00000000..28814871
--- /dev/null
+++ b/lib/xdgmime/xdgmimeint.h
@@ -0,0 +1,73 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* xdgmimeint.h: Internal defines and functions.
+ *
+ * More info can be found at http://www.freedesktop.org/standards/
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ * Copyright (C) 2003  Jonathan Blandford <jrb@alum.mit.edu>
+ *
+ * Licensed under the Academic Free License version 2.0
+ * Or under the following terms:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __XDG_MIME_INT_H__
+#define __XDG_MIME_INT_H__
+
+#include "xdgmime.h"
+
+
+#ifndef	FALSE
+#define	FALSE (0)
+#endif
+
+#ifndef	TRUE
+#define	TRUE (!FALSE)
+#endif
+
+/* FIXME: Needs to be configure check */
+typedef unsigned int   xdg_unichar_t;
+typedef unsigned char  xdg_uchar8_t;
+typedef unsigned short xdg_uint16_t;
+typedef unsigned int   xdg_uint32_t;
+
+#ifdef XDG_PREFIX
+#define _xdg_utf8_skip   XDG_ENTRY(utf8_skip)
+#define _xdg_utf8_to_ucs4   XDG_ENTRY(utf8_to_ucs4)
+#define _xdg_ucs4_to_lower   XDG_ENTRY(ucs4_to_lower)
+#define _xdg_utf8_validate   XDG_ENTRY(utf8_validate)
+#define _xdg_get_base_name   XDG_ENTRY(get_ase_name)
+#endif
+
+#define SWAP_BE16_TO_LE16(val) (xdg_uint16_t)(((xdg_uint16_t)(val) << 8)|((xdg_uint16_t)(val) >> 8))
+
+#define SWAP_BE32_TO_LE32(val) (xdg_uint32_t)((((xdg_uint32_t)(val) & 0xFF000000U) >> 24) |	\
+					      (((xdg_uint32_t)(val) & 0x00FF0000U) >> 8) |	\
+					      (((xdg_uint32_t)(val) & 0x0000FF00U) << 8) |	\
+					      (((xdg_uint32_t)(val) & 0x000000FFU) << 24))
+/* UTF-8 utils
+ */
+extern const char *const _xdg_utf8_skip;
+#define _xdg_utf8_next_char(p) (char *)((p) + _xdg_utf8_skip[*(unsigned char *)(p)])
+#define _xdg_utf8_char_size(p) (int) (_xdg_utf8_skip[*(unsigned char *)(p)])
+
+xdg_unichar_t  _xdg_utf8_to_ucs4  (const char    *source);
+xdg_unichar_t  _xdg_ucs4_to_lower (xdg_unichar_t  source);
+int            _xdg_utf8_validate (const char    *source);
+const char    *_xdg_get_base_name (const char    *file_name);
+
+#endif /* __XDG_MIME_INT_H__ */
diff --git a/lib/xdgmime/xdgmimemagic.c b/lib/xdgmime/xdgmimemagic.c
new file mode 100644
index 00000000..6088edb2
--- /dev/null
+++ b/lib/xdgmime/xdgmimemagic.c
@@ -0,0 +1,807 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* xdgmimemagic.: Private file.  Datastructure for storing magic files.
+ *
+ * More info can be found at http://www.freedesktop.org/standards/
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ * Copyright (C) 2003  Jonathan Blandford <jrb@alum.mit.edu>
+ *
+ * Licensed under the Academic Free License version 2.0
+ * Or under the following terms:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include "xdgmimemagic.h"
+#include "xdgmimeint.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+
+#ifndef	FALSE
+#define	FALSE	(0)
+#endif
+
+#ifndef	TRUE
+#define	TRUE	(!FALSE)
+#endif
+
+#if !defined getc_unlocked && !defined HAVE_GETC_UNLOCKED
+# define getc_unlocked(fp) getc (fp)
+#endif
+
+typedef struct XdgMimeMagicMatch XdgMimeMagicMatch;
+typedef struct XdgMimeMagicMatchlet XdgMimeMagicMatchlet;
+
+typedef enum
+{
+  XDG_MIME_MAGIC_SECTION,
+  XDG_MIME_MAGIC_MAGIC,
+  XDG_MIME_MAGIC_ERROR,
+  XDG_MIME_MAGIC_EOF
+} XdgMimeMagicState;
+
+struct XdgMimeMagicMatch
+{
+  const char *mime_type;
+  int priority;
+  XdgMimeMagicMatchlet *matchlet;
+  XdgMimeMagicMatch *next;
+};
+
+
+struct XdgMimeMagicMatchlet
+{
+  int indent;
+  int offset;
+  unsigned int value_length;
+  unsigned char *value;
+  unsigned char *mask;
+  unsigned int range_length;
+  unsigned int word_size;
+  XdgMimeMagicMatchlet *next;
+};
+
+
+struct XdgMimeMagic
+{
+  XdgMimeMagicMatch *match_list;
+  int max_extent;
+};
+
+static XdgMimeMagicMatch *
+_xdg_mime_magic_match_new (void)
+{
+  return calloc (1, sizeof (XdgMimeMagicMatch));
+}
+
+
+static XdgMimeMagicMatchlet *
+_xdg_mime_magic_matchlet_new (void)
+{
+  XdgMimeMagicMatchlet *matchlet;
+
+  matchlet = malloc (sizeof (XdgMimeMagicMatchlet));
+
+  matchlet->indent = 0;
+  matchlet->offset = 0;
+  matchlet->value_length = 0;
+  matchlet->value = NULL;
+  matchlet->mask = NULL;
+  matchlet->range_length = 1;
+  matchlet->word_size = 1;
+  matchlet->next = NULL;
+
+  return matchlet;
+}
+
+
+static void
+_xdg_mime_magic_matchlet_free (XdgMimeMagicMatchlet *mime_magic_matchlet)
+{
+  if (mime_magic_matchlet)
+    {
+      if (mime_magic_matchlet->next)
+	_xdg_mime_magic_matchlet_free (mime_magic_matchlet->next);
+      if (mime_magic_matchlet->value)
+	free (mime_magic_matchlet->value);
+      if (mime_magic_matchlet->mask)
+	free (mime_magic_matchlet->mask);
+      free (mime_magic_matchlet);
+    }
+}
+
+
+/* Frees mime_magic_match and the remainder of its list
+ */
+static void
+_xdg_mime_magic_match_free (XdgMimeMagicMatch *mime_magic_match)
+{
+  XdgMimeMagicMatch *ptr, *next;
+
+  ptr = mime_magic_match;
+  while (ptr)
+    {
+      next = ptr->next;
+
+      if (ptr->mime_type)
+	free ((void *) ptr->mime_type);
+      if (ptr->matchlet)
+	_xdg_mime_magic_matchlet_free (ptr->matchlet);
+      free (ptr);
+
+      ptr = next;
+    }
+}
+
+/* Reads in a hunk of data until a newline character or a '\000' is hit.  The
+ * returned string is null terminated, and doesn't include the newline.
+ */
+static unsigned char *
+_xdg_mime_magic_read_to_newline (FILE *magic_file,
+				 int  *end_of_file)
+{
+  unsigned char *retval;
+  int c;
+  int len, pos;
+
+  len = 128;
+  pos = 0;
+  retval = malloc (len);
+  *end_of_file = FALSE;
+
+  while (TRUE)
+    {
+      c = getc_unlocked (magic_file);
+      if (c == EOF)
+	{
+	  *end_of_file = TRUE;
+	  break;
+	}
+      if (c == '\n' || c == '\000')
+	break;
+      retval[pos++] = (unsigned char) c;
+      if (pos % 128 == 127)
+	{
+	  len = len + 128;
+	  retval = realloc (retval, len);
+	}
+    }
+
+  retval[pos] = '\000';
+  return retval;
+}
+
+/* Returns the number read from the file, or -1 if no number could be read.
+ */
+static int
+_xdg_mime_magic_read_a_number (FILE *magic_file,
+			       int  *end_of_file)
+{
+  /* LONG_MAX is about 20 characters on my system */
+#define MAX_NUMBER_SIZE 30
+  char number_string[MAX_NUMBER_SIZE + 1];
+  int pos = 0;
+  int c;
+  long retval = -1;
+
+  while (TRUE)
+    {
+      c = getc_unlocked (magic_file);
+
+      if (c == EOF)
+	{
+	  *end_of_file = TRUE;
+	  break;
+	}
+      if (! isdigit (c))
+	{
+	  ungetc (c, magic_file);
+	  break;
+	}
+      number_string[pos] = (char) c;
+      pos++;
+      if (pos == MAX_NUMBER_SIZE)
+	break;
+    }
+  if (pos > 0)
+    {
+      number_string[pos] = '\000';
+      errno = 0;
+      retval = strtol (number_string, NULL, 10);
+
+      if ((retval < INT_MIN) || (retval > INT_MAX) || (errno != 0))
+	return -1;
+    }
+
+  return retval;
+}
+
+/* Headers are of the format:
+ * [<priority>:<mime-type>]
+ */
+static XdgMimeMagicState
+_xdg_mime_magic_parse_header (FILE *magic_file, XdgMimeMagicMatch *match)
+{
+  int c;
+  char *buffer;
+  char *end_ptr;
+  int end_of_file = 0;
+
+  assert (magic_file != NULL);
+  assert (match != NULL);
+
+  c = getc_unlocked (magic_file);
+  if (c == EOF)
+    return XDG_MIME_MAGIC_EOF;
+  if (c != '[')
+    return XDG_MIME_MAGIC_ERROR;
+
+  match->priority = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
+  if (end_of_file)
+    return XDG_MIME_MAGIC_EOF;
+  if (match->priority == -1)
+    return XDG_MIME_MAGIC_ERROR;
+
+  c = getc_unlocked (magic_file);
+  if (c == EOF)
+    return XDG_MIME_MAGIC_EOF;
+  if (c != ':')
+    return XDG_MIME_MAGIC_ERROR;
+
+  buffer = (char *)_xdg_mime_magic_read_to_newline (magic_file, &end_of_file);
+  if (end_of_file)
+    return XDG_MIME_MAGIC_EOF;
+
+  end_ptr = buffer;
+  while (*end_ptr != ']' && *end_ptr != '\000' && *end_ptr != '\n')
+    end_ptr++;
+  if (*end_ptr != ']')
+    {
+      free (buffer);
+      return XDG_MIME_MAGIC_ERROR;
+    }
+  *end_ptr = '\000';
+
+  match->mime_type = strdup (buffer);
+  free (buffer);
+
+  return XDG_MIME_MAGIC_MAGIC;
+}
+
+static XdgMimeMagicState
+_xdg_mime_magic_parse_error (FILE *magic_file)
+{
+  int c;
+
+  while (1)
+    {
+      c = getc_unlocked (magic_file);
+      if (c == EOF)
+	return XDG_MIME_MAGIC_EOF;
+      if (c == '\n')
+	return XDG_MIME_MAGIC_SECTION;
+    }
+}
+
+/* Headers are of the format:
+ * [ indent ] ">" start-offset "=" value
+ * [ "&" mask ] [ "~" word-size ] [ "+" range-length ] "\n"
+ */
+static XdgMimeMagicState
+_xdg_mime_magic_parse_magic_line (FILE              *magic_file,
+				  XdgMimeMagicMatch *match)
+{
+  XdgMimeMagicMatchlet *matchlet;
+  int c;
+  int end_of_file;
+  int indent = 0;
+  int bytes_read;
+
+  assert (magic_file != NULL);
+
+  /* Sniff the buffer to make sure it's a valid line */
+  c = getc_unlocked (magic_file);
+  if (c == EOF)
+    return XDG_MIME_MAGIC_EOF;
+  else if (c == '[')
+    {
+      ungetc (c, magic_file);
+      return XDG_MIME_MAGIC_SECTION;
+    }
+  else if (c == '\n')
+    return XDG_MIME_MAGIC_MAGIC;
+
+  /* At this point, it must be a digit or a '>' */
+  end_of_file = FALSE;
+  if (isdigit (c))
+    {
+      ungetc (c, magic_file);
+      indent = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
+      if (end_of_file)
+	return XDG_MIME_MAGIC_EOF;
+      if (indent == -1)
+	return XDG_MIME_MAGIC_ERROR;
+      c = getc_unlocked (magic_file);
+      if (c == EOF)
+	return XDG_MIME_MAGIC_EOF;
+    }
+
+  if (c != '>')
+    return XDG_MIME_MAGIC_ERROR;
+
+  matchlet = _xdg_mime_magic_matchlet_new ();
+  matchlet->indent = indent;
+  matchlet->offset = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
+  if (end_of_file)
+    {
+      _xdg_mime_magic_matchlet_free (matchlet);
+      return XDG_MIME_MAGIC_EOF;
+    }
+  if (matchlet->offset == -1)
+    {
+      _xdg_mime_magic_matchlet_free (matchlet);
+      return XDG_MIME_MAGIC_ERROR;
+    }
+  c = getc_unlocked (magic_file);
+  if (c == EOF)
+    {
+      _xdg_mime_magic_matchlet_free (matchlet);
+      return XDG_MIME_MAGIC_EOF;
+    }
+  else if (c != '=')
+    {
+      _xdg_mime_magic_matchlet_free (matchlet);
+      return XDG_MIME_MAGIC_ERROR;
+    }
+
+  /* Next two bytes determine how long the value is */
+  matchlet->value_length = 0;
+  c = getc_unlocked (magic_file);
+  if (c == EOF)
+    {
+      _xdg_mime_magic_matchlet_free (matchlet);
+      return XDG_MIME_MAGIC_EOF;
+    }
+  matchlet->value_length = c & 0xFF;
+  matchlet->value_length = matchlet->value_length << 8;
+
+  c = getc_unlocked (magic_file);
+  if (c == EOF)
+    {
+      _xdg_mime_magic_matchlet_free (matchlet);
+      return XDG_MIME_MAGIC_EOF;
+    }
+  matchlet->value_length = matchlet->value_length + (c & 0xFF);
+
+  matchlet->value = malloc (matchlet->value_length);
+
+  /* OOM */
+  if (matchlet->value == NULL)
+    {
+      _xdg_mime_magic_matchlet_free (matchlet);
+      return XDG_MIME_MAGIC_ERROR;
+    }
+  bytes_read = fread (matchlet->value, 1, matchlet->value_length, magic_file);
+  if (bytes_read != matchlet->value_length)
+    {
+      _xdg_mime_magic_matchlet_free (matchlet);
+      if (feof (magic_file))
+	return XDG_MIME_MAGIC_EOF;
+      else
+	return XDG_MIME_MAGIC_ERROR;
+    }
+
+  c = getc_unlocked (magic_file);
+  if (c == '&')
+    {
+      matchlet->mask = malloc (matchlet->value_length);
+      /* OOM */
+      if (matchlet->mask == NULL)
+	{
+	  _xdg_mime_magic_matchlet_free (matchlet);
+	  return XDG_MIME_MAGIC_ERROR;
+	}
+      bytes_read = fread (matchlet->mask, 1, matchlet->value_length, magic_file);
+      if (bytes_read != matchlet->value_length)
+	{
+	  _xdg_mime_magic_matchlet_free (matchlet);
+	  if (feof (magic_file))
+	    return XDG_MIME_MAGIC_EOF;
+	  else
+	    return XDG_MIME_MAGIC_ERROR;
+	}
+      c = getc_unlocked (magic_file);
+    }
+
+  if (c == '~')
+    {
+      matchlet->word_size = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
+      if (end_of_file)
+	{
+	  _xdg_mime_magic_matchlet_free (matchlet);
+	  return XDG_MIME_MAGIC_EOF;
+	}
+      if (matchlet->word_size != 0 &&
+	  matchlet->word_size != 1 &&
+	  matchlet->word_size != 2 &&
+	  matchlet->word_size != 4)
+	{
+	  _xdg_mime_magic_matchlet_free (matchlet);
+	  return XDG_MIME_MAGIC_ERROR;
+	}
+      c = getc_unlocked (magic_file);
+    }
+
+  if (c == '+')
+    {
+      matchlet->range_length = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
+      if (end_of_file)
+	{
+	  _xdg_mime_magic_matchlet_free (matchlet);
+	  return XDG_MIME_MAGIC_EOF;
+	}
+      if (matchlet->range_length == -1)
+	{
+	  _xdg_mime_magic_matchlet_free (matchlet);
+	  return XDG_MIME_MAGIC_ERROR;
+	}
+      c = getc_unlocked (magic_file);
+    }
+
+
+  if (c == '\n')
+    {
+      /* We clean up the matchlet, byte swapping if needed */
+      if (matchlet->word_size > 1)
+	{
+	  int i;
+	  if (matchlet->value_length % matchlet->word_size != 0)
+	    {
+	      _xdg_mime_magic_matchlet_free (matchlet);
+	      return XDG_MIME_MAGIC_ERROR;
+	    }
+	  /* FIXME: need to get this defined in a <config.h> style file */
+#if LITTLE_ENDIAN
+	  for (i = 0; i < matchlet->value_length; i = i + matchlet->word_size)
+	    {
+	      if (matchlet->word_size == 2)
+		*((xdg_uint16_t *) matchlet->value + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->value + i)));
+	      else if (matchlet->word_size == 4)
+		*((xdg_uint32_t *) matchlet->value + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->value + i)));
+	      if (matchlet->mask)
+		{
+		  if (matchlet->word_size == 2)
+		    *((xdg_uint16_t *) matchlet->mask + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->mask + i)));
+		  else if (matchlet->word_size == 4)
+		    *((xdg_uint32_t *) matchlet->mask + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->mask + i)));
+
+		}
+	    }
+#endif
+	}
+
+      matchlet->next = match->matchlet;
+      match->matchlet = matchlet;
+
+
+      return XDG_MIME_MAGIC_MAGIC;
+    }
+
+  _xdg_mime_magic_matchlet_free (matchlet);
+  if (c == EOF)
+    return XDG_MIME_MAGIC_EOF;
+
+  return XDG_MIME_MAGIC_ERROR;
+}
+
+static int
+_xdg_mime_magic_matchlet_compare_to_data (XdgMimeMagicMatchlet *matchlet,
+					  const void           *data,
+					  size_t                len)
+{
+  int i, j;
+  for (i = matchlet->offset; i < matchlet->offset + matchlet->range_length; i++)
+    {
+      int valid_matchlet = TRUE;
+
+      if (i + matchlet->value_length > len)
+	return FALSE;
+
+      if (matchlet->mask)
+	{
+	  for (j = 0; j < matchlet->value_length; j++)
+	    {
+	      if ((matchlet->value[j] & matchlet->mask[j]) !=
+		  ((((unsigned char *) data)[j + i]) & matchlet->mask[j]))
+		{
+		  valid_matchlet = FALSE;
+		  break;
+		}
+	    }
+	}
+      else
+	{
+	  for (j = 0; j <  matchlet->value_length; j++)
+	    {
+	      if (matchlet->value[j] != ((unsigned char *) data)[j + i])
+		{
+		  valid_matchlet = FALSE;
+		  break;
+		}
+	    }
+	}
+      if (valid_matchlet)
+	return TRUE;
+    }
+  return FALSE;
+}
+
+static int
+_xdg_mime_magic_matchlet_compare_level (XdgMimeMagicMatchlet *matchlet,
+					const void           *data,
+					size_t                len,
+					int                   indent)
+{
+  while ((matchlet != NULL) && (matchlet->indent == indent))
+    {
+      if (_xdg_mime_magic_matchlet_compare_to_data (matchlet, data, len))
+	{
+	  if ((matchlet->next == NULL) ||
+	      (matchlet->next->indent <= indent))
+	    return TRUE;
+
+	  if (_xdg_mime_magic_matchlet_compare_level (matchlet->next,
+						      data,
+						      len,
+						      indent + 1))
+	    return TRUE;
+	}
+
+      do
+	{
+	  matchlet = matchlet->next;
+	}
+      while (matchlet && matchlet->indent > indent);
+    }
+
+  return FALSE;
+}
+
+static int
+_xdg_mime_magic_match_compare_to_data (XdgMimeMagicMatch *match,
+				       const void        *data,
+				       size_t             len)
+{
+  return _xdg_mime_magic_matchlet_compare_level (match->matchlet, data, len, 0);
+}
+
+static void
+_xdg_mime_magic_insert_match (XdgMimeMagic      *mime_magic,
+			      XdgMimeMagicMatch *match)
+{
+  XdgMimeMagicMatch *list;
+
+  if (mime_magic->match_list == NULL)
+    {
+      mime_magic->match_list = match;
+      return;
+    }
+
+  if (match->priority > mime_magic->match_list->priority)
+    {
+      match->next = mime_magic->match_list;
+      mime_magic->match_list = match;
+      return;
+    }
+
+  list = mime_magic->match_list;
+  while (list->next != NULL)
+    {
+      if (list->next->priority < match->priority)
+	{
+	  match->next = list->next;
+	  list->next = match;
+	  return;
+	}
+      list = list->next;
+    }
+  list->next = match;
+  match->next = NULL;
+}
+
+XdgMimeMagic *
+_xdg_mime_magic_new (void)
+{
+  return calloc (1, sizeof (XdgMimeMagic));
+}
+
+void
+_xdg_mime_magic_free (XdgMimeMagic *mime_magic)
+{
+  if (mime_magic) {
+    _xdg_mime_magic_match_free (mime_magic->match_list);
+    free (mime_magic);
+  }
+}
+
+int
+_xdg_mime_magic_get_buffer_extents (XdgMimeMagic *mime_magic)
+{
+  return mime_magic->max_extent;
+}
+
+const char *
+_xdg_mime_magic_lookup_data (XdgMimeMagic *mime_magic,
+			     const void   *data,
+			     size_t        len,
+                             const char   *mime_types[],
+                             int           n_mime_types)
+{
+  XdgMimeMagicMatch *match;
+  const char *mime_type;
+  int n;
+
+  mime_type = NULL;
+  for (match = mime_magic->match_list; match; match = match->next)
+    {
+      if (_xdg_mime_magic_match_compare_to_data (match, data, len))
+	{
+	  if ((mime_type == NULL) || (_xdg_mime_mime_type_subclass (match->mime_type, mime_type))) {
+	    mime_type = match->mime_type;
+	  }
+	}
+      else 
+	{
+	  for (n = 0; n < n_mime_types; n++)
+	    {
+	      if (mime_types[n] && 
+		  _xdg_mime_mime_type_equal (mime_types[n], match->mime_type))
+		mime_types[n] = NULL;
+	    }
+	}
+    }
+
+  if (mime_type == NULL)
+    {
+      for (n = 0; n < n_mime_types; n++)
+	{
+	  if (mime_types[n])
+	    mime_type = mime_types[n];
+	}
+    }
+
+  return mime_type;
+}
+
+static void
+_xdg_mime_update_mime_magic_extents (XdgMimeMagic *mime_magic)
+{
+  XdgMimeMagicMatch *match;
+  int max_extent = 0;
+
+  for (match = mime_magic->match_list; match; match = match->next)
+    {
+      XdgMimeMagicMatchlet *matchlet;
+
+      for (matchlet = match->matchlet; matchlet; matchlet = matchlet->next)
+	{
+	  int extent;
+
+	  extent = matchlet->value_length + matchlet->offset + matchlet->range_length;
+	  if (max_extent < extent)
+	    max_extent = extent;
+	}
+    }
+
+  mime_magic->max_extent = max_extent;
+}
+
+static XdgMimeMagicMatchlet *
+_xdg_mime_magic_matchlet_mirror (XdgMimeMagicMatchlet *matchlets)
+{
+  XdgMimeMagicMatchlet *new_list;
+  XdgMimeMagicMatchlet *tmp;
+
+  if ((matchlets == NULL) || (matchlets->next == NULL))
+    return matchlets;
+
+  new_list = NULL;
+  tmp = matchlets;
+  while (tmp != NULL)
+    {
+      XdgMimeMagicMatchlet *matchlet;
+
+      matchlet = tmp;
+      tmp = tmp->next;
+      matchlet->next = new_list;
+      new_list = matchlet;
+    }
+
+  return new_list;
+
+}
+
+static void
+_xdg_mime_magic_read_magic_file (XdgMimeMagic *mime_magic,
+				 FILE         *magic_file)
+{
+  XdgMimeMagicState state;
+  XdgMimeMagicMatch *match = NULL; /* Quiet compiler */
+
+  state = XDG_MIME_MAGIC_SECTION;
+
+  while (state != XDG_MIME_MAGIC_EOF)
+    {
+      switch (state)
+	{
+	case XDG_MIME_MAGIC_SECTION:
+	  match = _xdg_mime_magic_match_new ();
+	  state = _xdg_mime_magic_parse_header (magic_file, match);
+	  if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR)
+	    _xdg_mime_magic_match_free (match);
+	  break;
+	case XDG_MIME_MAGIC_MAGIC:
+	  state = _xdg_mime_magic_parse_magic_line (magic_file, match);
+	  if (state == XDG_MIME_MAGIC_SECTION ||
+	      (state == XDG_MIME_MAGIC_EOF && match->mime_type))
+	    {
+	      match->matchlet = _xdg_mime_magic_matchlet_mirror (match->matchlet);
+	      _xdg_mime_magic_insert_match (mime_magic, match);
+	    }
+	  else if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR)
+	    _xdg_mime_magic_match_free (match);
+	  break;
+	case XDG_MIME_MAGIC_ERROR:
+	  state = _xdg_mime_magic_parse_error (magic_file);
+	  break;
+	case XDG_MIME_MAGIC_EOF:
+	default:
+	  /* Make the compiler happy */
+	  assert (0);
+	}
+    }
+  _xdg_mime_update_mime_magic_extents (mime_magic);
+}
+
+void
+_xdg_mime_magic_read_from_file (XdgMimeMagic *mime_magic,
+				const char   *file_name)
+{
+  FILE *magic_file;
+  char header[12];
+
+  magic_file = fopen (file_name, "r");
+
+  if (magic_file == NULL)
+    return;
+
+  if (fread (header, 1, 12, magic_file) == 12)
+    {
+      if (memcmp ("MIME-Magic\0\n", header, 12) == 0)
+        _xdg_mime_magic_read_magic_file (mime_magic, magic_file);
+    }
+
+  fclose (magic_file);
+}
diff --git a/lib/xdgmime/xdgmimemagic.h b/lib/xdgmime/xdgmimemagic.h
new file mode 100644
index 00000000..16578962
--- /dev/null
+++ b/lib/xdgmime/xdgmimemagic.h
@@ -0,0 +1,56 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* xdgmimemagic.h: Private file.  Datastructure for storing the magic files.
+ *
+ * More info can be found at http://www.freedesktop.org/standards/
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ * Copyright (C) 2003  Jonathan Blandford <jrb@alum.mit.edu>
+ *
+ * Licensed under the Academic Free License version 2.0
+ * Or under the following terms:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __XDG_MIME_MAGIC_H__
+#define __XDG_MIME_MAGIC_H__
+
+#include <unistd.h>
+#include "xdgmime.h"
+typedef struct XdgMimeMagic XdgMimeMagic;
+
+#ifdef XDG_PREFIX
+#define _xdg_mime_glob_read_from_file             XDG_ENTRY(glob_read_from_file)
+#define _xdg_mime_magic_new                       XDG_ENTRY(magic_new)
+#define _xdg_mime_magic_read_from_file            XDG_ENTRY(magic_read_from_file)
+#define _xdg_mime_magic_free                      XDG_ENTRY(magic_free)
+#define _xdg_mime_magic_get_buffer_extents        XDG_ENTRY(magic_get_buffer_extents)
+#define _xdg_mime_magic_lookup_data               XDG_ENTRY(magic_lookup_data)
+#endif
+
+
+XdgMimeMagic *_xdg_mime_magic_new                (void);
+void          _xdg_mime_magic_read_from_file     (XdgMimeMagic *mime_magic,
+						  const char   *file_name);
+void          _xdg_mime_magic_free               (XdgMimeMagic *mime_magic);
+int           _xdg_mime_magic_get_buffer_extents (XdgMimeMagic *mime_magic);
+const char   *_xdg_mime_magic_lookup_data        (XdgMimeMagic *mime_magic,
+						  const void   *data,
+						  size_t        len,
+						  const char   *mime_types[],
+						  int           n_mime_types);
+
+#endif /* __XDG_MIME_MAGIC_H__ */
diff --git a/lib/xdgmime/xdgmimeparent.c b/lib/xdgmime/xdgmimeparent.c
new file mode 100644
index 00000000..511bbacb
--- /dev/null
+++ b/lib/xdgmime/xdgmimeparent.c
@@ -0,0 +1,219 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* xdgmimealias.c: Private file.  Datastructure for storing the hierarchy.
+ *
+ * More info can be found at http://www.freedesktop.org/standards/
+ *
+ * Copyright (C) 2004  Red Hat, Inc.
+ * Copyright (C) 2004  Matthias Clasen <mclasen@redhat.com>
+ *
+ * Licensed under the Academic Free License version 2.0
+ * Or under the following terms:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "xdgmimeparent.h"
+#include "xdgmimeint.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <fnmatch.h>
+
+#ifndef	FALSE
+#define	FALSE	(0)
+#endif
+
+#ifndef	TRUE
+#define	TRUE	(!FALSE)
+#endif
+
+typedef struct XdgMimeParents XdgMimeParents;
+
+struct XdgMimeParents
+{
+  char *mime;
+  char **parents;
+  int n_parents;
+};
+
+struct XdgParentList
+{
+  struct XdgMimeParents *parents;
+  int n_mimes;
+};
+
+XdgParentList *
+_xdg_mime_parent_list_new (void)
+{
+  XdgParentList *list;
+
+  list = malloc (sizeof (XdgParentList));
+
+  list->parents = NULL;
+  list->n_mimes = 0;
+
+  return list;
+}
+
+void         
+_xdg_mime_parent_list_free (XdgParentList *list)
+{
+  int i;
+  char **p;
+
+  if (list->parents)
+    {
+      for (i = 0; i < list->n_mimes; i++)
+	{
+	  for (p = list->parents[i].parents; *p; p++)
+	    free (*p);
+
+	  free (list->parents[i].parents);
+	  free (list->parents[i].mime);
+	}
+      free (list->parents);
+    }
+  free (list);
+}
+
+static int
+parent_entry_cmp (const void *v1, const void *v2)
+{
+  return strcmp (((XdgMimeParents *)v1)->mime, ((XdgMimeParents *)v2)->mime);
+}
+
+const char **
+_xdg_mime_parent_list_lookup (XdgParentList *list,
+			      const char    *mime)
+{
+  XdgMimeParents *entry;
+  XdgMimeParents key;
+
+  if (list->n_mimes > 0)
+    {
+      key.mime = (char *)mime;
+      key.parents = NULL;
+
+      entry = bsearch (&key, list->parents, list->n_mimes,
+		       sizeof (XdgMimeParents), &parent_entry_cmp);
+      if (entry)
+        return (const char **)entry->parents;
+    }
+
+  return NULL;
+}
+
+void
+_xdg_mime_parent_read_from_file (XdgParentList *list,
+				 const char    *file_name)
+{
+  FILE *file;
+  char line[255];
+  int i, alloc;
+  XdgMimeParents *entry;
+
+  file = fopen (file_name, "r");
+
+  if (file == NULL)
+    return;
+
+  /* FIXME: Not UTF-8 safe.  Doesn't work if lines are greater than 255 chars.
+   * Blah */
+  alloc = list->n_mimes + 16;
+  list->parents = realloc (list->parents, alloc * sizeof (XdgMimeParents));
+  while (fgets (line, 255, file) != NULL)
+    {
+      char *sep;
+      if (line[0] == '#')
+	continue;
+
+      sep = strchr (line, ' ');
+      if (sep == NULL)
+	continue;
+      *(sep++) = '\000';
+      sep[strlen (sep) -1] = '\000';
+      entry = NULL;
+      for (i = 0; i < list->n_mimes; i++)
+	{
+	  if (strcmp (list->parents[i].mime, line) == 0)
+	    {
+	      entry = &(list->parents[i]);
+	      break;
+	    }
+	}
+      
+      if (!entry)
+	{
+	  if (list->n_mimes == alloc)
+	    {
+	      alloc <<= 1;
+	      list->parents = realloc (list->parents, 
+				       alloc * sizeof (XdgMimeParents));
+	    }
+	  list->parents[list->n_mimes].mime = strdup (line);
+	  list->parents[list->n_mimes].parents = NULL;
+	  entry = &(list->parents[list->n_mimes]);
+	  list->n_mimes++;
+	}
+
+      if (!entry->parents)
+	{
+	  entry->n_parents = 1;
+	  entry->parents = malloc ((entry->n_parents + 1) * sizeof (char *));
+	}
+      else
+	{
+	  entry->n_parents += 1;
+	  entry->parents = realloc (entry->parents, 
+				    (entry->n_parents + 2) * sizeof (char *));
+	}
+      entry->parents[entry->n_parents - 1] = strdup (sep);
+      entry->parents[entry->n_parents] = NULL;
+    }
+
+  list->parents = realloc (list->parents, 
+			   list->n_mimes * sizeof (XdgMimeParents));
+
+  fclose (file);  
+  
+  if (list->n_mimes > 1)
+    qsort (list->parents, list->n_mimes, 
+           sizeof (XdgMimeParents), &parent_entry_cmp);
+}
+
+
+void         
+_xdg_mime_parent_list_dump (XdgParentList *list)
+{
+  int i;
+  char **p;
+
+  if (list->parents)
+    {
+      for (i = 0; i < list->n_mimes; i++)
+	{
+	  for (p = list->parents[i].parents; *p; p++)
+	    printf ("%s %s\n", list->parents[i].mime, *p);
+	}
+    }
+}
+
+
diff --git a/lib/xdgmime/xdgmimeparent.h b/lib/xdgmime/xdgmimeparent.h
new file mode 100644
index 00000000..da29452c
--- /dev/null
+++ b/lib/xdgmime/xdgmimeparent.h
@@ -0,0 +1,50 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* xdgmimeparent.h: Private file.  Datastructure for storing the hierarchy.
+ *
+ * More info can be found at http://www.freedesktop.org/standards/
+ *
+ * Copyright (C) 2004  Red Hat, Inc.
+ * Copyright (C) 200  Matthias Clasen <mclasen@redhat.com>
+ *
+ * Licensed under the Academic Free License version 2.0
+ * Or under the following terms:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __XDG_MIME_PARENT_H__
+#define __XDG_MIME_PARENT_H__
+
+#include "xdgmime.h"
+
+typedef struct XdgParentList XdgParentList;
+
+#ifdef XDG_PREFIX
+#define _xdg_mime_parent_read_from_file        XDG_ENTRY(parent_read_from_file)
+#define _xdg_mime_parent_list_new              XDG_ENTRY(parent_list_new)
+#define _xdg_mime_parent_list_free             XDG_ENTRY(parent_list_free)
+#define _xdg_mime_parent_list_lookup           XDG_ENTRY(parent_list_lookup)
+#endif
+
+void          _xdg_mime_parent_read_from_file (XdgParentList *list,
+					       const char    *file_name);
+XdgParentList *_xdg_mime_parent_list_new       (void);
+void           _xdg_mime_parent_list_free      (XdgParentList *list);
+const char   **_xdg_mime_parent_list_lookup    (XdgParentList *list,
+						const char    *mime);
+void           _xdg_mime_parent_list_dump      (XdgParentList *list);
+
+#endif /* __XDG_MIME_PARENT_H__ */
diff --git a/shell/extensions/.gitignore b/shell/extensions/.gitignore
new file mode 100644
index 00000000..0ab98701
--- /dev/null
+++ b/shell/extensions/.gitignore
@@ -0,0 +1,2 @@
+stamp-sugar-shell-marshal.*
+sugar-shell-marshal.*
diff --git a/shell/extensions/Makefile.am b/shell/extensions/Makefile.am
index 4cee6d60..a151f87d 100644
--- a/shell/extensions/Makefile.am
+++ b/shell/extensions/Makefile.am
@@ -9,15 +9,12 @@ pkgpyexec_LTLIBRARIES = _extensions.la
 _extensions_la_LDFLAGS = -module -avoid-version
 
 _extensions_la_CFLAGS =				\
-	$(WARN_CFLAGS)				\
 	$(PYTHON_INCLUDES)			\
-	$(PYGTK_CFLAGS)				\
 	$(SHELL_CFLAGS)				\
 	-I$(top_srcdir)/shell/extensions
 
 _extensions_la_LIBADD = 	\
 	$(SHELL_LIBS) 		\
-	$(PYCAIRO_LIBS)		\
 	-lgstinterfaces-0.10	\
 	-lgstaudio-0.10
 
diff --git a/shell/extensions/stamp-sugar-shell-marshal.c b/shell/extensions/stamp-sugar-shell-marshal.c
deleted file mode 100644
index 9788f702..00000000
--- a/shell/extensions/stamp-sugar-shell-marshal.c
+++ /dev/null
@@ -1 +0,0 @@
-timestamp
diff --git a/shell/extensions/stamp-sugar-shell-marshal.h b/shell/extensions/stamp-sugar-shell-marshal.h
deleted file mode 100644
index 9788f702..00000000
--- a/shell/extensions/stamp-sugar-shell-marshal.h
+++ /dev/null
@@ -1 +0,0 @@
-timestamp
diff --git a/shell/extensions/sugar-shell-marshal.c b/shell/extensions/sugar-shell-marshal.c
deleted file mode 100644
index fa8df7d3..00000000
--- a/shell/extensions/sugar-shell-marshal.c
+++ /dev/null
@@ -1,104 +0,0 @@
-
-#ifndef __sugar_shell_marshal_MARSHAL_H__
-#define __sugar_shell_marshal_MARSHAL_H__
-
-#include	<glib-object.h>
-
-G_BEGIN_DECLS
-
-#ifdef G_ENABLE_DEBUG
-#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
-#define g_marshal_value_peek_char(v)     g_value_get_char (v)
-#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
-#define g_marshal_value_peek_int(v)      g_value_get_int (v)
-#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
-#define g_marshal_value_peek_long(v)     g_value_get_long (v)
-#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
-#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
-#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
-#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
-#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
-#define g_marshal_value_peek_float(v)    g_value_get_float (v)
-#define g_marshal_value_peek_double(v)   g_value_get_double (v)
-#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
-#define g_marshal_value_peek_param(v)    g_value_get_param (v)
-#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
-#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
-#define g_marshal_value_peek_object(v)   g_value_get_object (v)
-#else /* !G_ENABLE_DEBUG */
-/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
- *          Do not access GValues directly in your code. Instead, use the
- *          g_value_get_*() functions
- */
-#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
-#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
-#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
-#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
-#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
-#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
-#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
-#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
-#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
-#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
-#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
-#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
-#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
-#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
-#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
-#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
-#endif /* !G_ENABLE_DEBUG */
-
-
-/* BOOLEAN:UINT,UINT (./sugar-shell-marshal.list:1) */
-extern void sugar_shell_marshal_BOOLEAN__UINT_UINT (GClosure     *closure,
-                                                    GValue       *return_value,
-                                                    guint         n_param_values,
-                                                    const GValue *param_values,
-                                                    gpointer      invocation_hint,
-                                                    gpointer      marshal_data);
-void
-sugar_shell_marshal_BOOLEAN__UINT_UINT (GClosure     *closure,
-                                        GValue       *return_value,
-                                        guint         n_param_values,
-                                        const GValue *param_values,
-                                        gpointer      invocation_hint,
-                                        gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__UINT_UINT) (gpointer     data1,
-                                                       guint        arg_1,
-                                                       guint        arg_2,
-                                                       gpointer     data2);
-  register GMarshalFunc_BOOLEAN__UINT_UINT callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__UINT_UINT) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_uint (param_values + 1),
-                       g_marshal_value_peek_uint (param_values + 2),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-G_END_DECLS
-
-#endif /* __sugar_shell_marshal_MARSHAL_H__ */
-
diff --git a/shell/extensions/sugar-shell-marshal.h b/shell/extensions/sugar-shell-marshal.h
deleted file mode 100644
index 30386bc8..00000000
--- a/shell/extensions/sugar-shell-marshal.h
+++ /dev/null
@@ -1,20 +0,0 @@
-
-#ifndef __sugar_shell_marshal_MARSHAL_H__
-#define __sugar_shell_marshal_MARSHAL_H__
-
-#include	<glib-object.h>
-
-G_BEGIN_DECLS
-
-/* BOOLEAN:UINT,UINT (./sugar-shell-marshal.list:1) */
-extern void sugar_shell_marshal_BOOLEAN__UINT_UINT (GClosure     *closure,
-                                                    GValue       *return_value,
-                                                    guint         n_param_values,
-                                                    const GValue *param_values,
-                                                    gpointer      invocation_hint,
-                                                    gpointer      marshal_data);
-
-G_END_DECLS
-
-#endif /* __sugar_shell_marshal_MARSHAL_H__ */
-
diff --git a/shell/model/homemodel.py b/shell/model/homemodel.py
index a3afdc4d..92afc23f 100644
--- a/shell/model/homemodel.py
+++ b/shell/model/homemodel.py
@@ -26,6 +26,7 @@ from sugar.activity import bundleregistry
 
 _SERVICE_NAME = "org.laptop.Activity"
 _SERVICE_PATH = "/org/laptop/Activity"
+_SERVICE_INTERFACE = "org.laptop.Activity"
 
 class HomeModel(gobject.GObject):
     """Model of the "Home" view (activity management)
@@ -68,6 +69,12 @@ class HomeModel(gobject.GObject):
         screen.connect('window-closed', self._window_closed_cb)
         screen.connect('active-window-changed',
                        self._active_window_changed_cb)
+        bus = dbus.SessionBus()
+        bus.add_signal_receiver(
+            self._dbus_name_owner_changed_cb, 
+            'NameOwnerChanged', 
+            'org.freedesktop.DBus', 
+            'org.freedesktop.DBus')
 
     def get_current_activity(self):
         return self._current_activity
@@ -103,9 +110,31 @@ class HomeModel(gobject.GObject):
             self.emit('active-activity-changed', None)
             self._notify_activity_activation(self._current_activity, None)
 
+    def _dbus_name_owner_changed_cb(self, name, old, new):
+        """Detect new activity instances on the DBus
+
+        Normally, new activities are detected by
+        the _window_opened_cb callback. However, if the
+        window is opened before the dbus service is up,
+        a RawHomeWindow is created. In here we create
+        a proper HomeActivity replacing the RawHomeWindow.
+        """
+        if name.startswith(_SERVICE_NAME) and new and not old:
+            xid = name[len(_SERVICE_NAME):]
+            if not xid.isdigit():
+                return
+            logging.debug("Activity instance launch detected: %s" % name)
+            xid = int(xid)
+            act = self._get_activity_by_xid(xid)
+            if isinstance(act, HomeRawWindow):
+                logging.debug("Removing bogus raw activity %s for window %i" 
+                              % (act.get_activity_id(), xid))
+                self._internal_remove_activity(act)
+                self._add_activity(act.get_window())
+
     def _get_activity_by_xid(self, xid):
         for act in self._activities.values():
-            if act.get_xid() == xid:
+            if act.get_launched() and act.get_xid() == xid:
                 return act
         return None
 
@@ -168,8 +197,11 @@ class HomeModel(gobject.GObject):
         bus = dbus.SessionBus()
         xid = window.get_xid()
         try:
-            service = bus.get_object(_SERVICE_NAME + '%d' % xid,
-                                     _SERVICE_PATH + "/%s" % xid)
+            service = dbus.Interface(
+                bus.get_object(_SERVICE_NAME + '%d' % xid,
+                               _SERVICE_PATH + "/%s" % xid),
+                _SERVICE_INTERFACE)
+            
         except dbus.DBusException:
             service = None
 
diff --git a/sugar/Makefile.am b/sugar/Makefile.am
index 9e8db383..d4f91ea9 100644
--- a/sugar/Makefile.am
+++ b/sugar/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = activity browser clipboard graphics p2p presence datastore
+SUBDIRS = activity clipboard graphics objects presence datastore
 
 sugardir = $(pythondir)/sugar
 sugar_PYTHON =		\
@@ -9,3 +9,40 @@ sugar_PYTHON =		\
         ltihooks.py	\
 	profile.py	\
 	util.py
+
+INCLUDES = 				\
+	$(LIB_CFLAGS)			\
+	$(LIB_BINDINGS_CFLAGS)		\
+	$(PYTHON_INCLUDES)		\
+	-I$(top_srcdir)/lib		\
+	-I$(top_srcdir)/lib/xdgmime
+
+pkgpyexecdir = $(pythondir)/sugar
+
+pkgpyexec_LTLIBRARIES = _sugarext.la
+
+_sugarext_la_LDFLAGS = -module -avoid-version
+_sugarext_la_LIBADD =			\
+	$(LIB_BINDINGS_LIBS)		\
+	$(LIB_LIBS)			\
+	$(top_builddir)/lib/libsugar.la
+
+_sugarext_la_SOURCES = 		\
+	_sugarextmodule.c
+
+nodist__sugarext_la_SOURCES = _sugarext.c
+
+_sugarext.c: _sugarext.defs _sugarext.override
+
+CLEANFILES = _sugarext.c
+EXTRA_DIST = _sugarext.override _sugarext.defs
+
+.defs.c:
+	(cd $(srcdir)\
+	 && $(PYGTK_CODEGEN) \
+	    --register $(PYGTK_DEFSDIR)/gdk-types.defs \
+	    --register $(PYGTK_DEFSDIR)/gtk-types.defs \
+	    --override $*.override \
+	    --prefix py$* $*.defs) > gen-$*.c \
+	&& cp gen-$*.c $*.c \
+	&& rm -f gen-$*.c
diff --git a/sugar/_sugarext.c b/sugar/_sugarext.c
new file mode 100644
index 00000000..be9854c3
--- /dev/null
+++ b/sugar/_sugarext.c
@@ -0,0 +1,152 @@
+/* -- THIS FILE IS GENERATED - DO NOT EDIT *//* -*- Mode: C; c-basic-offset: 4 -*- */
+
+#include <Python.h>
+
+
+
+#line 4 "_sugarext.override"
+#include <Python.h>
+
+#include "pygobject.h"
+#include "sugar-address-entry.h"
+#include "xdgmime.h"
+
+#include <pygtk/pygtk.h>
+#include <glib.h>
+
+#line 18 "_sugarext.c"
+
+
+/* ---------- types from other modules ---------- */
+static PyTypeObject *_PyGtkEntry_Type;
+#define PyGtkEntry_Type (*_PyGtkEntry_Type)
+
+
+/* ---------- forward type declarations ---------- */
+PyTypeObject G_GNUC_INTERNAL PySugarAddressEntry_Type;
+
+#line 29 "_sugarext.c"
+
+
+
+/* ----------- SugarAddressEntry ----------- */
+
+PyTypeObject G_GNUC_INTERNAL PySugarAddressEntry_Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,                                 /* ob_size */
+    "_sugarext.AddressEntry",                   /* tp_name */
+    sizeof(PyGObject),          /* tp_basicsize */
+    0,                                 /* tp_itemsize */
+    /* methods */
+    (destructor)0,        /* tp_dealloc */
+    (printfunc)0,                      /* tp_print */
+    (getattrfunc)0,       /* tp_getattr */
+    (setattrfunc)0,       /* tp_setattr */
+    (cmpfunc)0,           /* tp_compare */
+    (reprfunc)0,             /* tp_repr */
+    (PyNumberMethods*)0,     /* tp_as_number */
+    (PySequenceMethods*)0, /* tp_as_sequence */
+    (PyMappingMethods*)0,   /* tp_as_mapping */
+    (hashfunc)0,             /* tp_hash */
+    (ternaryfunc)0,          /* tp_call */
+    (reprfunc)0,              /* tp_str */
+    (getattrofunc)0,     /* tp_getattro */
+    (setattrofunc)0,     /* tp_setattro */
+    (PyBufferProcs*)0,  /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,                      /* tp_flags */
+    NULL,                        /* Documentation string */
+    (traverseproc)0,     /* tp_traverse */
+    (inquiry)0,             /* tp_clear */
+    (richcmpfunc)0,   /* tp_richcompare */
+    offsetof(PyGObject, weakreflist),             /* tp_weaklistoffset */
+    (getiterfunc)0,          /* tp_iter */
+    (iternextfunc)0,     /* tp_iternext */
+    (struct PyMethodDef*)NULL, /* tp_methods */
+    (struct PyMemberDef*)0,              /* tp_members */
+    (struct PyGetSetDef*)0,  /* tp_getset */
+    NULL,                              /* tp_base */
+    NULL,                              /* tp_dict */
+    (descrgetfunc)0,    /* tp_descr_get */
+    (descrsetfunc)0,    /* tp_descr_set */
+    offsetof(PyGObject, inst_dict),                 /* tp_dictoffset */
+    (initproc)0,             /* tp_init */
+    (allocfunc)0,           /* tp_alloc */
+    (newfunc)0,               /* tp_new */
+    (freefunc)0,             /* tp_free */
+    (inquiry)0              /* tp_is_gc */
+};
+
+
+
+/* ----------- functions ----------- */
+
+static PyObject *
+_wrap_sugar_mime_get_mime_type_from_file_name(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { "filename", NULL };
+    char *filename;
+    const gchar *ret;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"s:get_mime_type_from_file_name", kwlist, &filename))
+        return NULL;
+    
+    ret = sugar_mime_get_mime_type_from_file_name(filename);
+    
+    if (ret)
+        return PyString_FromString(ret);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+#line 23 "_sugarext.override"
+static PyObject *
+_wrap_sugar_mime_get_mime_type_for_file(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { "filename", NULL };
+    char *filename;
+    const gchar *ret;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"s:get_mime_type_for_file", kwlist, &filename))
+        return NULL;
+    
+    ret = sugar_mime_get_mime_type_for_file(filename, NULL);
+    
+    if (ret)
+        return PyString_FromString(ret);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+#line 120 "_sugarext.c"
+
+
+const PyMethodDef py_sugarext_functions[] = {
+    { "get_mime_type_from_file_name", (PyCFunction)_wrap_sugar_mime_get_mime_type_from_file_name, METH_VARARGS|METH_KEYWORDS,
+      NULL },
+    { "get_mime_type_for_file", (PyCFunction)_wrap_sugar_mime_get_mime_type_for_file, METH_VARARGS|METH_KEYWORDS,
+      NULL },
+    { NULL, NULL, 0, NULL }
+};
+
+/* initialise stuff extension classes */
+void
+py_sugarext_register_classes(PyObject *d)
+{
+    PyObject *module;
+
+    if ((module = PyImport_ImportModule("gtk")) != NULL) {
+        _PyGtkEntry_Type = (PyTypeObject *)PyObject_GetAttrString(module, "Entry");
+        if (_PyGtkEntry_Type == NULL) {
+            PyErr_SetString(PyExc_ImportError,
+                "cannot import name Entry from gtk");
+            return ;
+        }
+    } else {
+        PyErr_SetString(PyExc_ImportError,
+            "could not import gtk");
+        return ;
+    }
+
+
+#line 151 "_sugarext.c"
+    pygobject_register_class(d, "SugarAddressEntry", SUGAR_TYPE_ADDRESS_ENTRY, &PySugarAddressEntry_Type, Py_BuildValue("(O)", &PyGtkEntry_Type));
+}
diff --git a/sugar/_sugarext.defs b/sugar/_sugarext.defs
new file mode 100644
index 00000000..db0c5b32
--- /dev/null
+++ b/sugar/_sugarext.defs
@@ -0,0 +1,27 @@
+;; -*- scheme -*-
+; object definitions
+
+(define-object AddressEntry
+  (in-module "Sugar")
+  (parent "GtkEntry")
+  (c-name "SugarAddressEntry")
+  (gtype-id "SUGAR_TYPE_ADDRESS_ENTRY")
+)
+
+; functions
+
+(define-function get_mime_type_from_file_name 
+  (c-name "sugar_mime_get_mime_type_from_file_name")
+  (return-type "const-char*")
+  (parameters
+    '("const-char*" "filename")
+  )
+)
+
+(define-function get_mime_type_for_file
+  (c-name "sugar_mime_get_mime_type_for_file")
+  (return-type "const-char*")
+  (parameters
+    '("const-char*" "filename")
+  )
+)
diff --git a/sugar/_sugarext.override b/sugar/_sugarext.override
new file mode 100644
index 00000000..16deb710
--- /dev/null
+++ b/sugar/_sugarext.override
@@ -0,0 +1,40 @@
+/* -*- Mode: C; c-basic-offset: 4 -*- */
+%%
+headers
+#include <Python.h>
+
+#include "pygobject.h"
+#include "sugar-address-entry.h"
+#include "xdgmime.h"
+
+#include <pygtk/pygtk.h>
+#include <glib.h>
+
+%%
+modulename _sugarext
+%%
+import gtk.Entry as PyGtkEntry_Type
+%%
+ignore-glob
+  *_get_type
+  _*
+%%
+override sugar_mime_get_mime_type_for_file kwargs
+static PyObject *
+_wrap_sugar_mime_get_mime_type_for_file(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { "filename", NULL };
+    char *filename;
+    const gchar *ret;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"s:get_mime_type_for_file", kwlist, &filename))
+        return NULL;
+    
+    ret = sugar_mime_get_mime_type_for_file(filename, NULL);
+    
+    if (ret)
+        return PyString_FromString(ret);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+%%
diff --git a/sugar/_sugarextmodule.c b/sugar/_sugarextmodule.c
new file mode 100644
index 00000000..e813e007
--- /dev/null
+++ b/sugar/_sugarextmodule.c
@@ -0,0 +1,27 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* include this first, before NO_IMPORT_PYGOBJECT is defined */
+#include <pygobject.h>
+
+void py_sugarext_register_classes (PyObject *d);
+
+extern PyMethodDef py_sugarext_functions[];
+
+DL_EXPORT(void)
+init_sugarext(void)
+{
+    PyObject *m, *d;
+
+    init_pygobject ();
+
+    m = Py_InitModule ("_sugarext", py_sugarext_functions);
+    d = PyModule_GetDict (m);
+
+    py_sugarext_register_classes (d);
+
+    if (PyErr_Occurred ()) {
+        Py_FatalError ("can't initialise module _sugarext");
+    }
+}
diff --git a/sugar/activity/activityfactory.py b/sugar/activity/activityfactory.py
index 3368b179..a78c474b 100644
--- a/sugar/activity/activityfactory.py
+++ b/sugar/activity/activityfactory.py
@@ -31,6 +31,8 @@ _ACTIVITY_SERVICE_NAME = "org.laptop.Activity"
 _ACTIVITY_SERVICE_PATH = "/org/laptop/Activity"
 _ACTIVITY_INTERFACE = "org.laptop.Activity"
 
+_ACTIVITY_FACTORY_INTERFACE = "org.laptop.ActivityFactory"
+
 def create_activity_id():
     """Generate a new, unique ID for this activity"""
     pservice = presenceservice.get_instance()
@@ -103,7 +105,7 @@ class ActivityCreationHandler(gobject.GObject):
 
         bus = dbus.SessionBus()
         proxy_obj = bus.get_object(service_name, bundle.get_object_path(), follow_name_owner_changes=True)
-        factory = dbus.Interface(proxy_obj, "com.redhat.Sugar.ActivityFactory")
+        factory = dbus.Interface(proxy_obj, _ACTIVITY_FACTORY_INTERFACE)
 
         factory.create(self._activity_handle.get_dict(),
                        reply_handler=self._reply_handler,
diff --git a/sugar/activity/activityfactoryservice.py b/sugar/activity/activityfactoryservice.py
index 21e7d5b6..4f614234 100644
--- a/sugar/activity/activityfactoryservice.py
+++ b/sugar/activity/activityfactoryservice.py
@@ -34,6 +34,8 @@ from sugar import logger
 gobject.threads_init()
 dbus.glib.threads_init()
 
+_ACTIVITY_FACTORY_INTERFACE = "org.laptop.ActivityFactory"
+
 class ActivityFactoryService(dbus.service.Object):
     """D-Bus service that creates instances of Python activities
     
@@ -92,7 +94,7 @@ class ActivityFactoryService(dbus.service.Object):
         object_path = '/' + service_name.replace('.', '/')
         dbus.service.Object.__init__(self, bus_name, object_path)
 
-    @dbus.service.method("com.redhat.Sugar.ActivityFactory", in_signature="a{ss}")
+    @dbus.service.method("org.laptop.ActivityFactory", in_signature="a{ss}")
     def create(self, handle):
         """Create a new instance of this activity 
         
diff --git a/sugar/browser/Makefile.am b/sugar/browser/Makefile.am
deleted file mode 100644
index f829ed6b..00000000
--- a/sugar/browser/Makefile.am
+++ /dev/null
@@ -1,47 +0,0 @@
-sugardir = $(pythondir)/sugar/browser
-sugar_PYTHON =		\
-	__init__.py
-
-INCLUDES =					\
-	$(PYTHON_INCLUDES)			\
-	$(PYGTK_CFLAGS)				\
-	$(PYCAIRO_CFLAGS)			\
-	$(LIB_CFLAGS)				\
-	$(GECKO_CFLAGS)				\
-	$(NSPR_CFLAGS)				\
-	-I$(MOZILLA_INCLUDE_DIR)/gtkembedmoz	\
-	-I$(top_srcdir)/browser
-
-pkgpyexecdir = $(pythondir)/sugar/browser
-
-pkgpyexec_LTLIBRARIES = _sugarbrowser.la
-
-_sugarbrowser_la_LDFLAGS = -module -avoid-version $(GECKO_LDFLAGS)
-_sugarbrowser_la_LIBADD =				\
-	$(LIB_LIBS)					\
-	$(PYCAIRO_LIBS)					\
-	$(GECKO_LIBS)					\
-	$(XPCOMGLUE_LIBS)				\
-	$(top_builddir)/browser/libsugarbrowser.la
-
-_sugarbrowser_la_SOURCES = 	\
-	_sugarbrowsermodule.c	\
-	xulrunner.cpp		\
-	xulrunner.h
-
-nodist__sugarbrowser_la_SOURCES = _sugarbrowser.c
-
-_sugar.c: _sugarbrowser.defs gtkmozembed.defs _sugarbrowser.override gtkmozembed.override
-
-CLEANFILES = _sugarbrowser.c
-EXTRA_DIST = _sugarbrowser.override _sugarbrowser.defs gtkmozembed.defs gtkmozembed.override
-
-.defs.c:
-	(cd $(srcdir)\
-	 && $(PYGTK_CODEGEN) \
-	    --register $(PYGTK_DEFSDIR)/gdk-types.defs \
-	    --register $(PYGTK_DEFSDIR)/gtk-types.defs \
-	    --override $*.override \
-	    --prefix py$* $*.defs) > gen-$*.c \
-	&& cp gen-$*.c $*.c \
-	&& rm -f gen-$*.c
diff --git a/sugar/browser/__init__.py b/sugar/browser/__init__.py
deleted file mode 100644
index b240a106..00000000
--- a/sugar/browser/__init__.py
+++ /dev/null
@@ -1,31 +0,0 @@
-"""Sugar's web-browser activity
-
-XUL Runner and gtkmozembed and is produced by the PyGTK
-.defs system.
-"""
-
-try:
-    from sugar.browser import _sugarbrowser
-except ImportError:
-    from sugar import ltihooks
-    from sugar.browser import _sugarbrowser
-
-from _sugarbrowser import AddressEntry
-from _sugarbrowser import startup, shutdown, get_download_manager
-
-class Browser(_sugarbrowser.Browser):
-    def __init__(self):
-        _sugarbrowser.Browser.__init__(self)
-
-    def get_browser(self):
-        from xpcom import components
-        cls = components.classes["@laptop.org/browser/browserhelper;1"]
-        browser_helper = cls.getService(components.interfaces.nsIBrowserHelper)
-        print self.get_instance_id()
-        return browser_helper.getBrowser(self.get_instance_id())
-        
-    def get_document(self):
-        return self.browser.contentDOMWindow.document
-    
-    document = property(get_document)
-    browser = property(get_browser)
diff --git a/sugar/browser/_sugarbrowser.defs b/sugar/browser/_sugarbrowser.defs
deleted file mode 100644
index 036a34c8..00000000
--- a/sugar/browser/_sugarbrowser.defs
+++ /dev/null
@@ -1,206 +0,0 @@
-;; -*- scheme -*-
-; object definitions ...
-
-(define-boxed SugarBrowserEvent
-  (in-module "Sugar")
-  (c-name "SugarBrowserEvent")
-  (gtype-id "SUGAR_TYPE_BROWSER_EVENT")
-  (copy-func "sugar_browser_event_copy")
-  (release-func "sugar_browser_event_free")
-)
-
-(define-boxed SugarBrowserMetadata
-  (in-module "Sugar")
-  (c-name "SugarBrowserMetadata")
-  (gtype-id "SUGAR_TYPE_BROWSER_METADATA")
-  (copy-func "sugar_browser_metadata_copy")
-  (release-func "sugar_browser_metadata_free")
-)
-
-(define-object AddressEntry
-  (in-module "Sugar")
-  (parent "GtkEntry")
-  (c-name "SugarAddressEntry")
-  (gtype-id "SUGAR_TYPE_ADDRESS_ENTRY")
-)
-
-(define-object Browser
-  (in-module "Sugar")
-  (parent "GtkMozEmbed")
-  (c-name "SugarBrowser")
-  (gtype-id "SUGAR_TYPE_BROWSER")
-)
-
-(define-object DownloadManager
-  (in-module "Sugar")
-  (parent "GObject")
-  (c-name "SugarDownloadManager")
-  (gtype-id "SUGAR_TYPE_DOWNLOAD_MANAGER")
-)
-
-(define-object Download
-  (in-module "Sugar")
-  (parent "GObject")
-  (c-name "SugarDownload")
-  (gtype-id "SUGAR_TYPE_DOWNLOAD")
-)
-
-;; Enumerations and flags ...
-
-
-;; From sugar-address-entry.h
-
-(define-function sugar_address_entry_get_type
-  (c-name "sugar_address_entry_get_type")
-  (return-type "GType")
-)
-
-;; From sugar-browser.h
-
-(define-function sugar_browser_get_type
-  (c-name "sugar_browser_get_type")
-  (return-type "GType")
-)
-
-(define-function startup
-  (c-name "sugar_browser_startup")
-  (parameters
-    '("const-char*" "profile_path")
-    '("const-char*" "profile_name")
-  )
-  (return-type "gboolean")
-)
-
-(define-function shutdown
-  (c-name "sugar_browser_shutdown")
-  (return-type "none")
-)
-
-(define-method grab_focus
-  (of-object "SugarBrowser")
-  (c-name "sugar_browser_grab_focus")
-  (return-type "none")
-)
-
-(define-method save_uri
-  (of-object "SugarBrowser")
-  (c-name "sugar_browser_save_uri")
-  (return-type "gboolean")
-  (parameters
-    '("const-char*" "uri")
-    '("const-char*" "filename")
-  )
-)
-
-(define-method save_document
-  (of-object "SugarBrowser")
-  (c-name "sugar_browser_save_document")
-  (return-type "gboolean")
-  (parameters
-    '("const-char*" "filename")
-  )
-)
-
-(define-method create_window
-  (of-object "SugarBrowser")
-  (c-name "sugar_browser_create_window")
-  (return-type "SugarBrowser*")
-)
-
-(define-virtual create_window
-  (of-object "SugarBrowser")
-  (c-name "sugar_browser_create_window")
-  (return-type "SugarBrowser*")
-)
-
-(define-method get_session
-  (of-object "SugarBrowser")
-  (c-name "sugar_browser_get_session")
-  (return-type "char*")
-)
-
-(define-method set_session
-  (of-object "SugarBrowser")
-  (c-name "sugar_browser_set_session")
-  (return-type "none")
-  (parameters
-    '("const-char*" "session")
-  )
-)
-
-(define-method get_instance_id
-  (of-object "SugarBrowser")
-  (c-name "sugar_browser_get_instance_id")
-  (return-type "int")
-)
-
-;; From sugar-key-grabber.h
-
-(define-function sugar_key_grabber_get_type
-  (c-name "sugar_key_grabber_get_type")
-  (return-type "GType")
-)
-
-(define-method grab
-  (of-object "SugarKeyGrabber")
-  (c-name "sugar_key_grabber_grab")
-  (return-type "none")
-  (parameters
-    '("const-char*" "key")
-  )
-)
-
-(define-method get_key
-  (of-object "SugarKeyGrabber")
-  (c-name "sugar_key_grabber_get_key")
-  (return-type "char*")
-  (parameters
-    '("guint" "keycode")
-    '("guint" "state")
-  )
-)
-
-;; From sugar-download-manager.h
-
-(define-function sugar_download_manager_get_type
-  (c-name "sugar_download_manager_get_type")
-  (return-type "GType")
-)
-
-(define-function get_download_manager
-  (c-name "sugar_get_download_manager")
-  (return-type "SugarDownloadManager*")
-)
-
-;; From sugar-download.h
-
-(define-function sugar_download_get_type
-  (c-name "sugar_download_get_type")
-  (return-type "GType")
-)
-
-(define-method get_file_name
-  (of-object "SugarDownload")
-  (c-name "sugar_download_get_file_name")
-  (return-type "const-gchar*")
-)
-
-(define-method get_url
-  (of-object "SugarDownload")
-  (c-name "sugar_download_get_url")
-  (return-type "const-gchar*")
-)
-
-(define-method get_mime_type
-  (of-object "SugarDownload")
-  (c-name "sugar_download_get_mime_type")
-  (return-type "const-gchar*")
-)
-
-(define-method get_percent
-  (of-object "SugarDownload")
-  (c-name "sugar_download_get_percent")
-  (return-type "gint")
-)
-
-(include "gtkmozembed.defs")
diff --git a/sugar/browser/_sugarbrowser.override b/sugar/browser/_sugarbrowser.override
deleted file mode 100644
index 2234f91e..00000000
--- a/sugar/browser/_sugarbrowser.override
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*- */
-%%
-headers
-#include <Python.h>
-
-#include "pygobject.h"
-#include "sugar-browser.h"
-#include "sugar-address-entry.h"
-#include "sugar-download-manager.h"
-#include "sugar-download.h"
-
-#include <pygtk/pygtk.h>
-#include <glib.h>
-
-%%
-modulename _sugarbrowser
-%%
-import gobject.GObject as PyGObject_Type
-import gtk.Entry as PyGtkEntry_Type
-import gtk.gdk.Screen as PyGdkScreen_Type
-import gtk.gdk.Pixbuf as PyGdkPixbuf_Type
-import hippo.CanvasImage as HippoCanvasImage_Type
-%%
-ignore-glob
-  *_get_type
-  _*
-%%
-include
-  gtkmozembed.override
-%%
-override-slot SugarBrowserMetadata.tp_getattr
-static PyObject *
-_wrap_sugar_browser_metadata_tp_getattr(PyObject *self, char *attr)
-{
-    SugarBrowserMetadata *metadata = pyg_boxed_get(self, SugarBrowserMetadata);
-
-    if (!strcmp(attr, "__members__"))
-        return Py_BuildValue("[s]", "filename");
-    else if (!strcmp(attr, "filename")) {
-        if (metadata->filename) {
-            return PyString_FromString(metadata->filename);
-        } else {
-            Py_INCREF(Py_None);
-            return Py_None;
-        }
-    }
-
-    return NULL;
-}
-%%
-override-slot SugarBrowserEvent.tp_getattr
-static PyObject *
-_wrap_sugar_browser_event_tp_getattr(PyObject *self, char *attr)
-{
-    SugarBrowserEvent *event = pyg_boxed_get(self, SugarBrowserEvent);
-
-    if (!strcmp(attr, "__members__"))
-        return Py_BuildValue("[sss]", "image_uri", "button", "image_name");
-    else if (!strcmp(attr, "image_uri")) {
-        if (event->image_uri) {
-            return PyString_FromString(event->image_uri);
-        } else {
-            Py_INCREF(Py_None);
-            return Py_None;
-        }
-    }
-    else if (!strcmp(attr, "image_name")) {
-        if (event->image_name) {
-            return PyString_FromString(event->image_name);
-        } else {
-            Py_INCREF(Py_None);
-            return Py_None;
-        }
-    }
-    else if (!strcmp(attr, "button"))
-        return PyInt_FromLong(event->button);
-
-    return NULL;
-}
-%%
diff --git a/sugar/browser/_sugarbrowsermodule.c b/sugar/browser/_sugarbrowsermodule.c
deleted file mode 100644
index 653bbfaf..00000000
--- a/sugar/browser/_sugarbrowsermodule.c
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "xulrunner.h"
-
-/* include this first, before NO_IMPORT_PYGOBJECT is defined */
-#include <pygobject.h>
-
-void py_sugarbrowser_register_classes (PyObject *d);
-
-extern PyMethodDef py_sugarbrowser_functions[];
-
-DL_EXPORT(void)
-init_sugarbrowser(void)
-{
-    PyObject *m, *d;
-
-    xulrunner_startup();
-
-    init_pygobject ();
-
-    m = Py_InitModule ("_sugarbrowser", py_sugarbrowser_functions);
-    d = PyModule_GetDict (m);
-
-    py_sugarbrowser_register_classes (d);
-    py_sugarbrowser_add_constants(m, "GTK_MOZ_EMBED_");
-
-    if (PyErr_Occurred ()) {
-        Py_FatalError ("can't initialise module _sugarbrowser");
-    }
-}
diff --git a/sugar/browser/browser.py b/sugar/browser/browser.py
deleted file mode 100644
index 8b137891..00000000
--- a/sugar/browser/browser.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/sugar/browser/gtkmozembed.defs b/sugar/browser/gtkmozembed.defs
deleted file mode 100644
index 5e9dd242..00000000
--- a/sugar/browser/gtkmozembed.defs
+++ /dev/null
@@ -1,475 +0,0 @@
-;; -*- scheme -*-
-; object definitions ...
-(define-object MozEmbed
-  (in-module "Gtk")
-  (parent "GtkBin")
-  (c-name "GtkMozEmbed")
-  (gtype-id "GTK_TYPE_MOZ_EMBED")
-)
-
-; (define-object MozEmbedSingle
-;   (in-module "Gtk")
-;   (parent "GtkObject")
-;   (c-name "GtkMozEmbedSingle")
-;   (gtype-id "GTK_TYPE_MOZ_EMBED_SINGLE")
-; )
-
-;; Enumerations and flags ...
-
-(define-enum MozEmbedProgressFlags
-  (in-module "Gtk")
-  (c-name "GtkMozEmbedProgressFlags")
-  (values
-    '("start" "GTK_MOZ_EMBED_FLAG_START")
-    '("redirecting" "GTK_MOZ_EMBED_FLAG_REDIRECTING")
-    '("transferring" "GTK_MOZ_EMBED_FLAG_TRANSFERRING")
-    '("negotiating" "GTK_MOZ_EMBED_FLAG_NEGOTIATING")
-    '("stop" "GTK_MOZ_EMBED_FLAG_STOP")
-    '("is-request" "GTK_MOZ_EMBED_FLAG_IS_REQUEST")
-    '("is-document" "GTK_MOZ_EMBED_FLAG_IS_DOCUMENT")
-    '("is-network" "GTK_MOZ_EMBED_FLAG_IS_NETWORK")
-    '("is-window" "GTK_MOZ_EMBED_FLAG_IS_WINDOW")
-  )
-)
-
-(define-enum MozEmbedStatusFlags
-  (in-module "Gtk")
-  (c-name "GtkMozEmbedStatusFlags")
-  (values
-    '("dns" "GTK_MOZ_EMBED_STATUS_FAILED_DNS")
-    '("connect" "GTK_MOZ_EMBED_STATUS_FAILED_CONNECT")
-    '("timeout" "GTK_MOZ_EMBED_STATUS_FAILED_TIMEOUT")
-    '("usercanceled" "GTK_MOZ_EMBED_STATUS_FAILED_USERCANCELED")
-  )
-)
-
-(define-enum MozEmbedReloadFlags
-  (in-module "Gtk")
-  (c-name "GtkMozEmbedReloadFlags")
-  (values
-    '("normal" "GTK_MOZ_EMBED_FLAG_RELOADNORMAL")
-    '("bypasscache" "GTK_MOZ_EMBED_FLAG_RELOADBYPASSCACHE")
-    '("bypassproxy" "GTK_MOZ_EMBED_FLAG_RELOADBYPASSPROXY")
-    '("bypassproxyandcache" "GTK_MOZ_EMBED_FLAG_RELOADBYPASSPROXYANDCACHE")
-    '("charsetchange" "GTK_MOZ_EMBED_FLAG_RELOADCHARSETCHANGE")
-  )
-)
-
-(define-enum MozEmbedChromeFlags
-  (in-module "Gtk")
-  (c-name "GtkMozEmbedChromeFlags")
-  (values
-    '("defaultchrome" "GTK_MOZ_EMBED_FLAG_DEFAULTCHROME")
-    '("windowborderson" "GTK_MOZ_EMBED_FLAG_WINDOWBORDERSON")
-    '("windowcloseon" "GTK_MOZ_EMBED_FLAG_WINDOWCLOSEON")
-    '("windowresizeon" "GTK_MOZ_EMBED_FLAG_WINDOWRESIZEON")
-    '("menubaron" "GTK_MOZ_EMBED_FLAG_MENUBARON")
-    '("toolbaron" "GTK_MOZ_EMBED_FLAG_TOOLBARON")
-    '("locationbaron" "GTK_MOZ_EMBED_FLAG_LOCATIONBARON")
-    '("statusbaron" "GTK_MOZ_EMBED_FLAG_STATUSBARON")
-    '("personaltoolbaron" "GTK_MOZ_EMBED_FLAG_PERSONALTOOLBARON")
-    '("scrollbarson" "GTK_MOZ_EMBED_FLAG_SCROLLBARSON")
-    '("titlebaron" "GTK_MOZ_EMBED_FLAG_TITLEBARON")
-    '("extrachromeon" "GTK_MOZ_EMBED_FLAG_EXTRACHROMEON")
-    '("allchrome" "GTK_MOZ_EMBED_FLAG_ALLCHROME")
-    '("windowraised" "GTK_MOZ_EMBED_FLAG_WINDOWRAISED")
-    '("windowlowered" "GTK_MOZ_EMBED_FLAG_WINDOWLOWERED")
-    '("centerscreen" "GTK_MOZ_EMBED_FLAG_CENTERSCREEN")
-    '("dependent" "GTK_MOZ_EMBED_FLAG_DEPENDENT")
-    '("modal" "GTK_MOZ_EMBED_FLAG_MODAL")
-    '("openasdialog" "GTK_MOZ_EMBED_FLAG_OPENASDIALOG")
-    '("openaschrome" "GTK_MOZ_EMBED_FLAG_OPENASCHROME")
-  )
-)
-
-
-;; From /usr/include/mozilla-1.2b/gtkembedmoz/gtkmozembed.h
-
-(define-function gtk_moz_embed_get_type
-  (c-name "gtk_moz_embed_get_type")
-  (return-type "GtkType")
-)
-
-(define-function gtk_moz_embed_new
-  (c-name "gtk_moz_embed_new")
-  (is-constructor-of "GtkMozEmbed")
-  (return-type "GtkWidget*")
-)
-
-(define-function push_startup
-  (c-name "gtk_moz_embed_push_startup")
-  (return-type "none")
-)
-
-(define-function pop_startup
-  (c-name "gtk_moz_embed_pop_startup")
-  (return-type "none")
-)
-
-(define-function gtk_moz_embed_set_comp_path
-  (c-name "gtk_moz_embed_set_comp_path_deprecated")
-  (return-type "none")
-  (parameters
-    '("char*" "aPath")
-  )
-  (deprecated "renamed to gtkmozembed.set_comp_path")
-)
-
-(define-function set_comp_path
-  (c-name "gtk_moz_embed_set_comp_path")
-  (return-type "none")
-  (parameters
-    '("char*" "aPath")
-  )
-)
-
-(define-function gtk_moz_embed_set_profile_path
-  (c-name "gtk_moz_embed_set_profile_path_deprecated")
-  (return-type "none")
-  (parameters
-    '("char*" "aDir")
-    '("char*" "aName")
-  )
-  (deprecated "renamed to gtkmozembed.set_profile_path")
-)
-
-(define-function set_profile_path
-  (c-name "gtk_moz_embed_set_profile_path")
-  (return-type "none")
-  (parameters
-    '("char*" "aDir")
-    '("char*" "aName")
-  )
-)
-
-(define-method load_url
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_load_url")
-  (return-type "none")
-  (parameters
-    '("const-char*" "url")
-  )
-)
-
-(define-method stop_load
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_stop_load")
-  (return-type "none")
-)
-
-(define-method can_go_back
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_can_go_back")
-  (return-type "gboolean")
-)
-
-(define-method can_go_forward
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_can_go_forward")
-  (return-type "gboolean")
-)
-
-(define-method go_back
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_go_back")
-  (return-type "none")
-)
-
-(define-method go_forward
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_go_forward")
-  (return-type "none")
-)
-
-(define-method render_data
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_render_data")
-  (return-type "none")
-  (parameters
-    '("const-char*" "data")
-    '("guint32" "len")
-    '("const-char*" "base_uri")
-    '("const-char*" "mime_type")
-  )
-)
-
-(define-method open_stream
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_open_stream")
-  (return-type "none")
-  (parameters
-    '("const-char*" "base_uri")
-    '("const-char*" "mime_type")
-  )
-)
-
-(define-method append_data
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_append_data")
-  (return-type "none")
-  (parameters
-    '("const-char*" "data")
-    '("guint32" "len")
-  )
-)
-
-(define-method close_stream
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_close_stream")
-  (return-type "none")
-)
-
-(define-method get_link_message
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_get_link_message")
-  (return-type "char*")
-)
-
-(define-method get_js_status
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_get_js_status")
-  (return-type "char*")
-)
-
-(define-method get_title
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_get_title")
-  (return-type "char*")
-)
-
-(define-method get_location
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_get_location")
-  (return-type "char*")
-)
-
-(define-method reload
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_reload")
-  (return-type "none")
-  (parameters
-    '("gint32" "flags")
-  )
-)
-
-(define-method set_chrome_mask
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_set_chrome_mask")
-  (return-type "none")
-  (parameters
-    '("guint32" "flags")
-  )
-)
-
-(define-method get_chrome_mask
-  (of-object "GtkMozEmbed")
-  (c-name "gtk_moz_embed_get_chrome_mask")
-  (return-type "guint32")
-)
-
-; (define-function gtk_moz_embed_progress_flags_get_type
-;   (c-name "gtk_moz_embed_progress_flags_get_type")
-;   (return-type "GtkType")
-; )
-
-; (define-function gtk_moz_embed_status_enums_get_type
-;   (c-name "gtk_moz_embed_status_enums_get_type")
-;   (return-type "GtkType")
-; )
-
-; (define-function gtk_moz_embed_reload_flags_get_type
-;   (c-name "gtk_moz_embed_reload_flags_get_type")
-;   (return-type "GtkType")
-; )
-
-; (define-function gtk_moz_embed_chrome_flags_get_type
-;   (c-name "gtk_moz_embed_chrome_flags_get_type")
-;   (return-type "GtkType")
-; )
-
-(define-function gtk_moz_embed_single_get
-  (c-name "gtk_moz_embed_single_get")
-  (return-type "GtkMozEmbedSingle*")
-)
-
-
-(define-virtual link_message
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-)
-(define-virtual js_status
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-)
-(define-virtual location
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-)
-(define-virtual title
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-)
-(define-virtual progress
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-  (parameters
-    '("gint" "curprogress")
-    '("gint" "maxprogress")
-  )
-)
-(define-virtual progress_all
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-  (parameters
-    '("const-char*" "aURI")
-    '("gint" "curprogress")
-    '("gint" "maxprogress")
-  )
-)
-(define-virtual net_state
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-  (parameters
-    '("gint" "state")
-    '("guint" "status")
-  )
-)
-(define-virtual net_state_all
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-  (parameters
-    '("const-char*" "aURI")
-    '("gint" "state")
-    '("guint" "status")
-  )
-)
-(define-virtual net_start
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-)
-(define-virtual net_stop
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-)
-(define-virtual new_window
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-  (parameters
-    '("GtkMozEmbed**" "newEmbed")
-    '("guint" "chromemask")
-  )
-)
-(define-virtual visibility
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-  (parameters
-    '("gboolean" "visibility")
-  )
-)
-(define-virtual destroy_brsr
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-)
-(define-virtual open_uri
-  (of-object "GtkMozEmbed")
-  (return-type "gint")
-  (parameters
-    '("const-char*" "aURI")
-  )
-)
-(define-virtual size_to
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-  (parameters
-    '("gint" "width")
-    '("gint" "height")
-  )
-)
-(define-virtual dom_key_down
-  (of-object "GtkMozEmbed")
-  (return-type "gint")
-  (parameters
-    '("gpointer" "dom_event")
-  )
-)
-(define-virtual dom_key_press
-  (of-object "GtkMozEmbed")
-  (return-type "gint")
-  (parameters
-    '("gpointer" "dom_event")
-  )
-)
-(define-virtual dom_key_up
-  (of-object "GtkMozEmbed")
-  (return-type "gint")
-  (parameters
-    '("gpointer" "dom_event")
-  )
-)
-(define-virtual dom_mouse_down
-  (of-object "GtkMozEmbed")
-  (return-type "gint")
-  (parameters
-    '("gpointer" "dom_event")
-  )
-)
-(define-virtual dom_mouse_up
-  (of-object "GtkMozEmbed")
-  (return-type "gint")
-  (parameters
-    '("gpointer" "dom_event")
-  )
-)
-(define-virtual dom_mouse_click
-  (of-object "GtkMozEmbed")
-  (return-type "gint")
-  (parameters
-    '("gpointer" "dom_event")
-  )
-)
-(define-virtual dom_mouse_dbl_click
-  (of-object "GtkMozEmbed")
-  (return-type "gint")
-  (parameters
-    '("gpointer" "dom_event")
-  )
-)
-(define-virtual dom_mouse_over
-  (of-object "GtkMozEmbed")
-  (return-type "gint")
-  (parameters
-    '("gpointer" "dom_event")
-  )
-)
-(define-virtual dom_mouse_out
-  (of-object "GtkMozEmbed")
-  (return-type "gint")
-  (parameters
-    '("gpointer" "dom_event")
-  )
-)
-(define-virtual security_change
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-  (parameters
-    '("gpointer" "request")
-    '("guint" "state")
-  )
-)
-(define-virtual status_change
-  (of-object "GtkMozEmbed")
-  (return-type "none")
-  (parameters
-    '("gpointer" "request")
-    '("gint" "status")
-    '("gpointer" "message")
-  )
-)
-(define-virtual new_window_orphan
-  (of-object "GtkMozEmbedSingle")
-  (return-type "none")
-  (parameters
-    '("GtkMozEmbed**" "newEmbed")
-    '("guint" "chromemask")
-  )
-)
diff --git a/sugar/browser/gtkmozembed.override b/sugar/browser/gtkmozembed.override
deleted file mode 100644
index 579af10b..00000000
--- a/sugar/browser/gtkmozembed.override
+++ /dev/null
@@ -1,50 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4 -*- */
-%%
-headers
-#include <Python.h>
-
-#define NO_IMPORT_PYGOBJECT
-#include <pygobject.h>
-
-#include <gtkmozembed.h>
-
-%%
-import gobject.GObject as PyGObject_Type
-import gtk.Object as PyGtkObject_Type
-import gtk.Bin as PyGtkBin_Type
-%%
-ignore-glob
-  *_get_type
-  _*
-%%
-override gtk_moz_embed_set_comp_path_deprecated kwargs
-static PyObject *
-_wrap_gtk_moz_embed_set_comp_path_deprecated(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-    static char *kwlist[] = { "aPath", NULL };
-    char *aPath;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:gtk_moz_embed_set_comp_path", kwlist, &aPath))
-        return NULL;
-    if (PyErr_Warn(PyExc_DeprecationWarning, "renamed to gtkmozembed.set_comp_path") < 0)
-        return NULL;
-    gtk_moz_embed_set_comp_path(aPath);
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-%%
-override gtk_moz_embed_set_profile_path_deprecated kwargs
-static PyObject *
-_wrap_gtk_moz_embed_set_profile_path_deprecated(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-    static char *kwlist[] = { "aDir", "aName", NULL };
-    char *aDir, *aName;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss:gtk_moz_embed_set_profile_path", kwlist, &aDir, &aName))
-        return NULL;
-    if (PyErr_Warn(PyExc_DeprecationWarning, "renamed to gtkmozembed.set_profile_path") < 0)
-        return NULL;
-    gtk_moz_embed_set_profile_path(aDir, aName);
-    Py_INCREF(Py_None);
-    return Py_None;
-}
diff --git a/sugar/browser/xulrunner.cpp b/sugar/browser/xulrunner.cpp
deleted file mode 100644
index a03604dc..00000000
--- a/sugar/browser/xulrunner.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <config.h>
-
-#include <string.h>
-
-#include "gtkmozembed_glue.cpp"
-
-extern "C" int
-xulrunner_startup(void)
-{
-    static const GREVersionRange greVersion = {
-        "1.9a", PR_TRUE,
-        "2", PR_TRUE
-    };
-
-    char xpcomPath[PATH_MAX];
-
-    nsresult rv = GRE_GetGREPathWithProperties(&greVersion, 1, nsnull, 0,
-                                               xpcomPath, sizeof(xpcomPath));
-    if (NS_FAILED(rv)) {
-        fprintf(stderr, "Couldn't find a compatible GRE.\n");
-        return 1;
-    }
-    
-    rv = XPCOMGlueStartup(xpcomPath);
-    if (NS_FAILED(rv)) {
-        fprintf(stderr, "Couldn't start XPCOM.");
-        return 1;
-    }
-
-    rv = GTKEmbedGlueStartup();
-    if (NS_FAILED(rv)) {
-        fprintf(stderr, "Couldn't find GTKMozEmbed symbols.");
-        return 1;
-    }
-
-    char *lastSlash = strrchr(xpcomPath, '/');
-    if (lastSlash)
-        *lastSlash = '\0';
-
-    gtk_moz_embed_set_path(xpcomPath);
-}
diff --git a/sugar/browser/xulrunner.h b/sugar/browser/xulrunner.h
deleted file mode 100644
index 49980671..00000000
--- a/sugar/browser/xulrunner.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-int xulrunner_startup (void);
diff --git a/sugar/datastore/datastore.py b/sugar/datastore/datastore.py
index 9d656707..82f50266 100644
--- a/sugar/datastore/datastore.py
+++ b/sugar/datastore/datastore.py
@@ -25,7 +25,7 @@ class DSObject(gobject.GObject):
                     ([]))
     }
 
-    def __init__(self, object_id, metadata, file_path):
+    def __init__(self, object_id, metadata=None, file_path=None):
         gobject.GObject.__init__(self)
         self.object_id = object_id
         self._metadata = metadata
@@ -43,6 +43,8 @@ class DSObject(gobject.GObject):
         del self.metadata[key]
 
     def get_metadata(self):
+        if self._metadata is None and not self.object_id is None:
+            self.set_metadata(dbus_helpers.get_properties(self.object_id))
         return self._metadata
     
     def set_metadata(self, metadata):
@@ -53,6 +55,8 @@ class DSObject(gobject.GObject):
     metadata = property(get_metadata, set_metadata)
 
     def get_file_path(self):
+        if self._file_path is None and not self.object_id is None:
+            self.set_file_path(dbus_helpers.get_filename(self.object_id))
         return self._file_path
     
     def set_file_path(self, file_path):
@@ -88,9 +92,30 @@ def write(ds_object, reply_handler=None, error_handler=None):
         # TODO: register the object for updates
     logging.debug('Written object %s to the datastore.' % ds_object.object_id)
 
-def find(query, reply_handler=None, error_handler=None):
-    object_ids = dbus_helpers.find(query, reply_handler, error_handler)
+def find(query, sorting=None, limit=None, offset=None, reply_handler=None,
+         error_handler=None):
+    if sorting:
+        query['order_by'] = sorting
+    if limit:
+        query['limit'] = limit
+    if offset:
+        query['offset'] = offset
+    
+    props_list, total_count = dbus_helpers.find(query, reply_handler, error_handler)
+    
     objects = []
-    for object_id in object_ids:
-        objects.append(get(object_id))
-    return objects
+    for props in props_list:
+        if props.has_key('filename') and props['filename']:
+            file_path = props['filename']
+            del props['filename']
+        else:
+            file_path = None
+
+        object_id = props['uid']
+        del props['uid']
+
+        ds_object = DSObject(object_id, props, file_path)
+        objects.append(ds_object)
+
+    return objects, total_count
+
diff --git a/sugar/graphics/__init__.py b/sugar/graphics/__init__.py
index 0a148b4c..75edace6 100644
--- a/sugar/graphics/__init__.py
+++ b/sugar/graphics/__init__.py
@@ -1 +1,7 @@
-"""Hippo-based graphics/controls for use in Sugar"""
+"""Graphics/controls for use in Sugar"""
+try:
+    from sugar._sugarext import AddressEntry
+except ImportError:
+    from sugar import ltihooks
+    from sugar._sugarext import AddressEntry
+
diff --git a/sugar/graphics/combobox.py b/sugar/graphics/combobox.py
index ce8628a0..284b1a19 100644
--- a/sugar/graphics/combobox.py
+++ b/sugar/graphics/combobox.py
@@ -19,6 +19,8 @@ import logging
 import gobject
 import gtk
 
+from sugar.graphics import units
+
 class ComboBox(gtk.ComboBox):
     __gtype_name__ = 'SugarComboBox'    
 
@@ -51,6 +53,7 @@ class ComboBox(gtk.ComboBox):
     def append_item(self, action_id, text, icon_name=None):
         if not self._icon_renderer and icon_name:
             self._icon_renderer = gtk.CellRendererPixbuf()
+            self._icon_renderer.props.stock_size = units.microgrid_to_pixels(3)
             self.pack_start(self._icon_renderer, False)
             self.add_attribute(self._icon_renderer, 'icon-name', 2)
 
diff --git a/sugar/logger.py b/sugar/logger.py
index d6b6d43d..fa2e28fb 100644
--- a/sugar/logger.py
+++ b/sugar/logger.py
@@ -82,6 +82,9 @@ class StderrCatcher:
         _log_writer.write(STDERR_LEVEL, txt)
         sys.__stderr__.write(txt)
 
+    def flush(self):
+        sys.__stderr__.flush()
+
 def __exception_handler(typ, exc, tb):
     trace = StringIO()
     traceback.print_exception(typ, exc, tb, None, trace)
diff --git a/sugar/objects/Makefile.am b/sugar/objects/Makefile.am
index c93713b5..35d4ddc0 100644
--- a/sugar/objects/Makefile.am
+++ b/sugar/objects/Makefile.am
@@ -1,5 +1,4 @@
 sugardir = $(pythondir)/sugar/objects
-sugar_PYTHON =			\
-	__init__.py		\
-	typeregistry.py		\
-	typeinfo.py
+sugar_PYTHON =		\
+	__init__.py	\
+	mime.py
diff --git a/sugar/objects/__init__.py b/sugar/objects/__init__.py
new file mode 100644
index 00000000..8f3e5528
--- /dev/null
+++ b/sugar/objects/__init__.py
@@ -0,0 +1 @@
+from sugar.objects import mime
diff --git a/sugar/objects/mime.py b/sugar/objects/mime.py
new file mode 100644
index 00000000..b50ada40
--- /dev/null
+++ b/sugar/objects/mime.py
@@ -0,0 +1,11 @@
+try:
+    from sugar import _sugarext
+except ImportError:
+    from sugar import ltihooks
+    from sugar import _sugarext
+
+def get_for_file(file_name):
+    return _sugarext.get_mime_type_for_file(file_name)
+        
+def get_from_file_name(file_name):
+    return _sugarext.get_mime_type_from_file_name(file_name)
diff --git a/sugar/objects/typeinfo.py b/sugar/objects/typeinfo.py
deleted file mode 100644
index 8ac84710..00000000
--- a/sugar/objects/typeinfo.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (C) 2007, Red Hat, Inc.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library 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
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-class TypeInfo(object):
-    def __init__(self, info_dict=None):
-        self.type_id = None
-        self.name = None
-        self.icon = 'theme:stock-missing'
-        self.parent = None
-        self.formats = []
-        
-        if info_dict:
-            self._read_from_dict(info_dict)            
-
-    def get_default_activity(self):
-        return None
-    
-    def get_activities(self):
-        return []
-
-    def _read_from_config(self, section, items, l_items):
-        self.type_id = section
-
-        for item in items:
-            if item[0] == 'name':
-                self.name = item[1]
-            elif item[0] == 'icon':
-                self.icon = item[1]
-            elif item[0] == 'parent':
-                self.parent = item[1]            
-            elif item[0] == 'formats':
-                self.formats = item[1].split(';')
-                
-        for item in litems:
-            if item[0] == 'name':
-                self.name = item[1]
-                
-        return (self.name and self.parent and self.formats)
-        
-    def _read_from_dict(self, info_dict):
-        self.type_id = info_dict['type_id']
-        self.name = info_dict['name']
-        self.icon = info_dict['icon']
-        self.formats = info_dict['formats']
diff --git a/sugar/objects/typeregistry.py b/sugar/objects/typeregistry.py
deleted file mode 100644
index 8d24b397..00000000
--- a/sugar/objects/typeregistry.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# Copyright (C) 2007, Red Hat, Inc.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library 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
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-from gettext import gettext as _
-from ConfigParser import ConfigParser
-
-from sugar.objects.typeinfo import TypeInfo
-from sugar.activity import bundleregistry
-
-_text_type = {
-    'type_id' : 'Text',
-    'name'    : _('Text'),
-    'icon'    : 'theme:object-text',
-    'formats' : [ 'text/plain', 'application/pdf' ]
-}
-
-_image_type = {
-    'type_id' : 'Image',
-    'name'    : _('Image'),
-    'icon'    : 'theme:object-image',
-    'formats' : [ 'image/jpeg', 'image/gif', 'image/png' ]
-}
-
-class _RootNode(_TypeNode):
-    def __init__(self):
-        _TypeNode.__init__('')
-    
-    def append_primitive(self, info_dict):
-        self.append(TypeInfo(info_dict))
-
-class _TypeNode(list):
-    def __init__(self, type_info):
-        self.type_info = type_info
-
-    def get_node_from_type(self, type_id):
-        for node in self:
-            if node.type_info.type_id == type_id:
-                return node
-
-        for node in self:
-            child = node.get_node_from_type()
-            if child:
-                return child
-
-        return None
-
-class TypeRegistry(object):
-    def __init__(self):
-        self._tree = _RootNode()
-        self._tree.append_primitive(_image_type)
-        self._tree.append_primitive(_text_type)
-
-        self._bundle_registry = bundleregistry.get_registry()
-        for bundle in self._bundle_registry:
-            self._read_from_bundle(bundle)
-        self._bundle_registry.connect('bundle-added', self._bundle_added_cb)
-
-    def _bundle_added_cb (self, registry, bundle):
-        self._read_from_bundle(bundle)
-
-    def _read_from_bundle(self, bundle):
-        cp = ConfigParser()
-        path = bundle.get_path()
-        cp.read([os.path.join(path, 'activity', 'object_types.info')])
-        items = cp.items()
-
-        cp = ConfigParser()
-        path = bundle.get_locale_path()
-        cp.read([os.path.join(path, 'object_types.linfo')])
-        l_items = cp.items()
-        
-        for section in cp.sections():
-            type_info = TypeInfo()
-            if type_info.read_from_config(section, items, l_items):
-                parent_node = self._tree.get_node_from_type(type_info.parent)
-                if parent_node:
-                    parent_node.append(_TypeNode(type_info))
-                    return True
-
-        return False       
-        
-def get_registry():
-    return _type_registry
-
-_type_registry = TypeRegistry()
diff --git a/sugar/p2p/Makefile.am b/sugar/p2p/Makefile.am
deleted file mode 100644
index 6ec45539..00000000
--- a/sugar/p2p/Makefile.am
+++ /dev/null
@@ -1,8 +0,0 @@
-sugardir = $(pythondir)/sugar/p2p
-sugar_PYTHON =			\
-	__init__.py		\
-	NotificationListener.py	\
-	Notifier.py		\
-	Stream.py		\
-	MostlyReliablePipe.py	\
-	network.py
diff --git a/sugar/p2p/MostlyReliablePipe.py b/sugar/p2p/MostlyReliablePipe.py
deleted file mode 100644
index 604eadae..00000000
--- a/sugar/p2p/MostlyReliablePipe.py
+++ /dev/null
@@ -1,1394 +0,0 @@
-# Copyright (C) 2006, Red Hat, Inc.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library 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
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-# FIXME tests use initialized variables, any better
-# what to shut up pylint for those?
-# pylint: disable-msg = W0612
-
-import socket
-import time
-import sha
-import struct
-import StringIO
-import binascii
-import random
-
-import gtk
-import gobject
-
-
-def _stringify_sha(sha_hash):
-    print_sha = ""
-    for char in sha_hash:
-        print_sha = print_sha + binascii.b2a_hex(char)
-    return print_sha
-
-def _sha_data(data):
-    sha_hash = sha.new()
-    sha_hash.update(data)
-    return sha_hash.digest()
-
-_UDP_DATAGRAM_SIZE = 512
-
-class SegmentBase(object):
-    _MAGIC = 0xbaea4304
-
-    # 4: magic (0xbaea4304)
-    # 1: type
-    # 2: segment number
-    # 2: total segments
-    # 2: message sequence number
-    #20: total data sha1
-    _HEADER_TEMPLATE = "! IbHHH20s"
-    _HEADER_LEN = struct.calcsize(_HEADER_TEMPLATE)
-    _MTU = _UDP_DATAGRAM_SIZE - _HEADER_LEN
-
-    # Message segment packet types
-    _SEGMENT_TYPE_DATA = 0
-    _SEGMENT_TYPE_RETRANSMIT = 1
-    _SEGMENT_TYPE_ACK = 2
-
-    def magic():
-        return SegmentBase._MAGIC
-    magic = staticmethod(magic)
-
-    def header_template():
-        return SegmentBase._HEADER_TEMPLATE
-    header_template = staticmethod(header_template)
-
-    def type_data():
-        return SegmentBase._SEGMENT_TYPE_DATA
-    type_data = staticmethod(type_data)
-
-    def type_retransmit():
-        return SegmentBase._SEGMENT_TYPE_RETRANSMIT
-    type_retransmit = staticmethod(type_retransmit)
-
-    def type_ack():
-        return SegmentBase._SEGMENT_TYPE_ACK
-    type_ack = staticmethod(type_ack)
-
-    def header_len():
-        """Return the header size of SegmentBase packets."""
-        return SegmentBase._HEADER_LEN
-    header_len = staticmethod(header_len)
-
-    def mtu():
-        """Return the SegmentBase packet MTU."""
-        return SegmentBase._MTU
-    mtu = staticmethod(mtu)
-
-    def __init__(self, segno, total_segs, msg_seq_num, master_sha):
-        self._type = None
-        self._transmits = 0
-        self._last_transmit = 0
-        self._data = None
-        self._data_len = 0
-        self.userdata = None
-        self._stime = time.time()
-        self._addr = None
-
-        # Sanity checks on the message attributes
-        if not segno or not isinstance(segno, int):
-            raise ValueError("Segment number must be in integer.")
-        if segno < 1 or segno > 65535:
-            raise ValueError("Segment number must be between 1 and 65535 inclusive.")
-        if not total_segs or not isinstance(total_segs, int):
-            raise ValueError("Message segment total must be an integer.")
-        if total_segs < 1 or total_segs > 65535:
-            raise ValueError("Message must have between 1 and 65535 segments inclusive.")
-        if segno > total_segs:
-            raise ValueError("Segment number cannot be larger than message segment total.")
-        if not msg_seq_num or not isinstance(msg_seq_num, int):
-            raise ValueError("Message sequnce number must be an integer.")
-        if msg_seq_num < 1 or msg_seq_num > 65535:
-            raise ValueError("Message sequence number must be between 1 and 65535 inclusive.")
-        if not master_sha or not isinstance(master_sha, str) or len(master_sha) != 20:
-            raise ValueError("Message SHA1 checksum invalid.")
-
-        self._segno = segno
-        self._total_segs = total_segs
-        self._msg_seq_num = msg_seq_num
-        self._master_sha = master_sha
-
-    def _validate_address(addr):
-        if not addr or not isinstance(addr, tuple):
-            raise ValueError("Address must be a tuple.")
-        if len(addr) != 2 or not isinstance(addr[0], str) or not isinstance(addr[1], int):
-            raise ValueError("Address format was invalid.")
-        if addr[1] < 1 or addr[1] > 65535:
-            raise ValueError("Address port was invalid.")
-    _validate_address = staticmethod(_validate_address)
-
-    def new_from_data(addr, data):
-        """Static constructor for creation from a packed data stream."""
-        SegmentBase._validate_address(addr)
-
-        # Verify minimum length
-        if not data:
-            raise ValueError("Segment data is invalid.")
-        data_len = len(data)
-        if data_len < SegmentBase.header_len() + 1:
-            raise ValueError("Segment is less then minimum required length")
-        if data_len > _UDP_DATAGRAM_SIZE:
-            raise ValueError("Segment data is larger than allowed.")
-        stream = StringIO.StringIO(data)
-
-        # Determine and verify the length of included data
-        stream.seek(0, 2)
-        data_len = stream.tell() - SegmentBase._HEADER_LEN
-        stream.seek(0)
-
-        if data_len < 1:
-            raise ValueError("Segment must have some data.")
-        if data_len > SegmentBase._MTU:
-            raise ValueError("Data length must not be larger than the MTU (%s)." % SegmentBase._MTU)
-
-        # Read the first header attributes
-        (magic, seg_type, segno, total_segs, msg_seq_num, master_sha) = struct.unpack(SegmentBase._HEADER_TEMPLATE,
-                stream.read(SegmentBase._HEADER_LEN))
-
-        # Sanity checks on the message attributes
-        if magic != SegmentBase._MAGIC:
-            raise ValueError("Segment does not have the correct magic.")
-
-        # if the segment is the only one in the message, validate the data
-        if segno == 1 and total_segs == 1:
-            data_sha = _sha_data(stream.read(data_len))
-            if data_sha != master_sha:
-                raise ValueError("Single segment message SHA checksums didn't match.")
-            stream.seek(SegmentBase._HEADER_LEN)
-
-        if seg_type == SegmentBase._SEGMENT_TYPE_DATA:
-            segment = DataSegment(segno, total_segs, msg_seq_num, master_sha)
-        elif seg_type == SegmentBase._SEGMENT_TYPE_RETRANSMIT:
-            segment = RetransmitSegment(segno, total_segs, msg_seq_num, master_sha)
-        elif seg_type == SegmentBase._SEGMENT_TYPE_ACK:
-            segment = AckSegment(segno, total_segs, msg_seq_num, master_sha)
-        else:
-            raise ValueError("Segment has invalid type.")
-
-        # Segment specific data interpretation
-        segment._addr = addr
-        segment._unpack_data(stream, data_len)
-
-        return segment
-    new_from_data = staticmethod(new_from_data)
-
-    def stime(self):
-        return self._stime
-
-    def address(self):
-        return self._addr
-
-    def segment_number(self):
-        return self._segno
-
-    def total_segments(self):
-        return self._total_segs
-
-    def message_sequence_number(self):
-        return self._msg_seq_num
-
-    def data(self):
-        return self._data
-
-    def master_sha(self):
-        return self._master_sha
-
-    def segment_type(self):
-        return self._type
-
-    def packetize(self):
-        """Return a correctly formatted message that can be immediately sent."""
-        header = struct.pack(self._HEADER_TEMPLATE, self._MAGIC, self._type,
-                self._segno, self._total_segs, self._msg_seq_num, self._master_sha)
-        return header + self._data
-
-    def transmits(self):
-        return self._transmits
-
-    def inc_transmits(self):
-        self._transmits = self._transmits + 1
-        self._last_transmit = time.time()
-
-    def last_transmit(self):
-        return self._last_transmit
-
-class DataSegment(SegmentBase):
-    """A message segment that encapsulates random data."""
-
-    def __init__(self, segno, total_segs, msg_seq_num, master_sha):
-        SegmentBase.__init__(self, segno, total_segs, msg_seq_num, master_sha)
-        self._type = SegmentBase._SEGMENT_TYPE_DATA
-
-    def _get_template_for_len(length):
-        return "! %ds" % length
-    _get_template_for_len = staticmethod(_get_template_for_len)
-
-    def _unpack_data(self, stream, data_len):
-        """Unpack the data stream, called by constructor."""
-        self._data_len = data_len
-        template = DataSegment._get_template_for_len(self._data_len)
-        self._data = struct.unpack(template, stream.read(self._data_len))[0]
-
-    def new_from_parts(segno, total_segs, msg_seq_num, master_sha, data):
-        """Construct a new message segment from individual attributes."""
-        if not data:
-            raise ValueError("Must have valid data.")
-        segment = DataSegment(segno, total_segs, msg_seq_num, master_sha)
-        segment._data_len = len(data)
-        template = DataSegment._get_template_for_len(segment._data_len)
-        segment._data = struct.pack(template, data)
-        return segment
-    new_from_parts = staticmethod(new_from_parts)
-
-
-class RetransmitSegment(SegmentBase):
-    """A message segment that encapsulates a retransmission request."""
-
-    # Retransmission data format:
-    #  2: message sequence number
-    # 20: total data sha1
-    #  2: segment number
-    _RT_DATA_TEMPLATE = "! H20sH"
-    _RT_DATA_LEN = struct.calcsize(_RT_DATA_TEMPLATE)
-
-    def data_template():
-        return RetransmitSegment._RT_DATA_TEMPLATE
-    data_template = staticmethod(data_template)
-
-    def __init__(self, segno, total_segs, msg_seq_num, master_sha):
-        """Should not be called directly."""
-        if segno != 1 or total_segs != 1:
-            raise ValueError("Retransmission request messages must have only one segment.")
-
-        SegmentBase.__init__(self, segno, total_segs, msg_seq_num, master_sha)
-        self._type = SegmentBase._SEGMENT_TYPE_RETRANSMIT
-
-    def _verify_data(rt_msg_seq_num, rt_master_sha, rt_segment_number):
-        # Sanity checks on the message attributes
-        if not rt_segment_number or not isinstance(rt_segment_number, int):
-            raise ValueError("RT Segment number must be in integer.")
-        if rt_segment_number < 1 or rt_segment_number > 65535:
-            raise ValueError("RT Segment number must be between 1 and 65535 inclusive.")
-        if not rt_msg_seq_num or not isinstance(rt_msg_seq_num, int):
-            raise ValueError("RT Message sequnce number must be an integer.")
-        if rt_msg_seq_num < 1 or rt_msg_seq_num > 65535:
-            raise ValueError("RT Message sequence number must be between 1 and 65535 inclusive.")
-        if not rt_master_sha or not isinstance(rt_master_sha, str) or len(rt_master_sha) != 20:
-            raise ValueError("RT Message SHA1 checksum invalid.")
-    _verify_data = staticmethod(_verify_data)
-
-    def _make_rtms_data(rt_msg_seq_num, rt_master_sha, rt_segment_number):
-        """Pack retransmission request payload."""
-        data = struct.pack(RetransmitSegment._RT_DATA_TEMPLATE, rt_msg_seq_num,
-                rt_master_sha, rt_segment_number)
-        return (data, _sha_data(data))
-    _make_rtms_data = staticmethod(_make_rtms_data)
-
-    def new_from_parts(addr, msg_seq_num, rt_msg_seq_num, rt_master_sha, rt_segment_number):
-        """Static constructor for creation from individual attributes."""
-
-        RetransmitSegment._verify_data(rt_msg_seq_num, rt_master_sha, rt_segment_number)
-        (data, data_sha) = RetransmitSegment._make_rtms_data(rt_msg_seq_num,
-                rt_master_sha, rt_segment_number)
-        segment = RetransmitSegment(1, 1, msg_seq_num, data_sha)
-        segment._data_len = RetransmitSegment._RT_DATA_LEN
-        segment._data = data
-        SegmentBase._validate_address(addr)
-        segment._addr = addr
-
-        segment._rt_msg_seq_num = rt_msg_seq_num
-        segment._rt_master_sha = rt_master_sha
-        segment._rt_segment_number = rt_segment_number
-        return segment
-    new_from_parts = staticmethod(new_from_parts)
-
-    def _unpack_data(self, stream, data_len):
-        if data_len != self._RT_DATA_LEN:
-            raise ValueError("Retransmission request data had invalid length.")
-        data = stream.read(data_len)
-        (rt_msg_seq_num, rt_master_sha, rt_seg_no) = struct.unpack(self._RT_DATA_TEMPLATE, data)
-        RetransmitSegment._verify_data(rt_msg_seq_num, rt_master_sha, rt_seg_no)
-
-        self._data = data
-        self._data_len = data_len
-        self._rt_msg_seq_num = rt_msg_seq_num
-        self._rt_master_sha = rt_master_sha
-        self._rt_segment_number = rt_seg_no
-
-    def rt_msg_seq_num(self):
-        return self._rt_msg_seq_num
-
-    def rt_master_sha(self):
-        return self._rt_master_sha
-
-    def rt_segment_number(self):
-        return self._rt_segment_number    
-
-
-class AckSegment(SegmentBase):
-    """A message segment that encapsulates a message acknowledgement."""
-
-    # Ack data format:
-    #  2: acked message sequence number
-    # 20: acked message total data sha1
-    #  4: acked message source IP address
-    _ACK_DATA_TEMPLATE = "! H20s4s"
-    _ACK_DATA_LEN = struct.calcsize(_ACK_DATA_TEMPLATE)
-
-    def data_template():
-        return AckSegment._ACK_DATA_TEMPLATE
-    data_template = staticmethod(data_template)
-
-    def __init__(self, segno, total_segs, msg_seq_num, master_sha):
-        """Should not be called directly."""
-        if segno != 1 or total_segs != 1:
-            raise ValueError("Acknowledgement messages must have only one segment.")
-
-        SegmentBase.__init__(self, segno, total_segs, msg_seq_num, master_sha)
-        self._type = SegmentBase._SEGMENT_TYPE_ACK
-
-    def _verify_data(ack_msg_seq_num, ack_master_sha, ack_addr):
-        # Sanity checks on the message attributes
-        if not ack_msg_seq_num or not isinstance(ack_msg_seq_num, int):
-            raise ValueError("Ack message sequnce number must be an integer.")
-        if ack_msg_seq_num < 1 or ack_msg_seq_num > 65535:
-            raise ValueError("Ack message sequence number must be between 1 and 65535 inclusive.")
-        if not ack_master_sha or not isinstance(ack_master_sha, str) or len(ack_master_sha) != 20:
-            raise ValueError("Ack message SHA1 checksum invalid.")
-        if not isinstance(ack_addr, str):
-            raise ValueError("Ack message invalid address type.")
-        try:
-            foo = socket.inet_aton(ack_addr)
-        except socket.error:
-            raise ValueError("Ack message invalid address.")
-    _verify_data = staticmethod(_verify_data)
-
-    def _make_ack_data(ack_msg_seq_num, ack_master_sha, ack_addr):
-        """Pack an ack payload."""
-        addr_data = socket.inet_aton(ack_addr)
-        data = struct.pack(AckSegment._ACK_DATA_TEMPLATE, ack_msg_seq_num,
-                ack_master_sha, addr_data)
-        return (data, _sha_data(data))
-    _make_ack_data = staticmethod(_make_ack_data)
-
-    def new_from_parts(addr, msg_seq_num, ack_msg_seq_num, ack_master_sha, ack_addr):
-        """Static constructor for creation from individual attributes."""
-
-        AckSegment._verify_data(ack_msg_seq_num, ack_master_sha, ack_addr)
-        (data, data_sha) = AckSegment._make_ack_data(ack_msg_seq_num,
-                ack_master_sha, ack_addr)
-        segment = AckSegment(1, 1, msg_seq_num, data_sha)
-        segment._data_len = AckSegment._ACK_DATA_LEN
-        segment._data = data
-        SegmentBase._validate_address(addr)
-        segment._addr = addr
-
-        segment._ack_msg_seq_num = ack_msg_seq_num
-        segment._ack_master_sha = ack_master_sha
-        segment._ack_addr = ack_addr
-        return segment
-    new_from_parts = staticmethod(new_from_parts)
-
-    def _unpack_data(self, stream, data_len):
-        if data_len != self._ACK_DATA_LEN:
-            raise ValueError("Ack segment data had invalid length.")
-        data = stream.read(data_len)
-        (ack_msg_seq_num, ack_master_sha, ack_addr_data) = struct.unpack(self._ACK_DATA_TEMPLATE, data)
-        try:
-            ack_addr = socket.inet_ntoa(ack_addr_data)
-        except socket.error:
-            raise ValueError("Ack segment data had invalid address.")
-        AckSegment._verify_data(ack_msg_seq_num, ack_master_sha, ack_addr)
-
-        self._data = data
-        self._data_len = data_len
-        self._ack_msg_seq_num = ack_msg_seq_num
-        self._ack_master_sha = ack_master_sha
-        self._ack_addr = ack_addr
-
-    def ack_msg_seq_num(self):
-        return self._ack_msg_seq_num
-
-    def ack_master_sha(self):
-        return self._ack_master_sha
-
-    def ack_addr(self):
-        return self._ack_addr
-
-class Message(object):
-    """Tracks an entire message object, which is composed of a number
-    of individual segments."""
-    def __init__(self, src_addr, msg_seq_num, msg_sha, total_segments):
-        self._rt_target = 0
-        self._next_rt_time = 0
-        self._last_incoming_time = 0
-        self._segments = {}
-        self._complete = False
-        self._dispatched_time = 0
-        self._data = None
-        self._data_sha = None
-        self._src_addr = src_addr
-        self._msg_seq_num = msg_seq_num
-        self._msg_sha = msg_sha
-        self._total_segments = total_segments
-        self._rt_tries = {}
-        for i in range(1, self._total_segments + 1):
-            self._rt_tries[i] = 0
-
-    def __del__(self):
-        self.clear()
-
-    def sha(self):
-        return self._msg_sha
-
-    def source_address(self):
-        return self._src_addr
-
-    def clear(self):
-        for key in self._segments.keys()[:]:
-            del self._segments[key]
-            del self._rt_tries[key]
-        self._segments = {}
-        self._rt_tries = {}
-
-    def has_segment(self, segno):
-        return self._segments.has_key(segno)
-
-    def first_missing(self):
-        for i in range(1, self._total_segments + 1):
-            if not self._segments.has_key(i):
-                return i
-        return 0
-
-    _DEF_RT_REQUEST_INTERVAL = 0.09 # 70ms (in seconds)
-    def update_rt_wait(self, now):
-        """now argument should be in seconds."""
-        wait = self._DEF_RT_REQUEST_INTERVAL
-        if self._last_incoming_time > now - 0.02:
-            msg_completeness = float(len(self._segments)) / float(self._total_segments)
-            wait = wait + (self._DEF_RT_REQUEST_INTERVAL * (1.0 - msg_completeness))
-        self._next_rt_time = now + wait
-
-    def add_segment(self, segment):
-        if self.complete():
-            return
-        segno = segment.segment_number()
-        if self._segments.has_key(segno):
-            return
-        self._segments[segno] = segment
-        self._rt_tries[segno] = 0
-        now = time.time()
-        self._last_incoming_time = now
-
-        num_segs = len(self._segments)
-        if num_segs == self._total_segments:
-            self._complete = True
-            self._next_rt_time = 0
-            self._data = ''
-            for seg in self._segments.values():
-                self._data = self._data + seg.data()
-            self._data_sha = _sha_data(self._data)
-        elif segno == num_segs or num_segs == 1:
-            # If we're not missing segments, push back retransmit request
-            self.update_rt_wait(now)
-
-    def get_retransmit_message(self, msg_seq_num, segno):
-        if segno < 1 or segno > self._total_segments:
-            return None
-        seg = RetransmitSegment.new_from_parts(self._src_addr, msg_seq_num,
-                self._msg_seq_num, self._msg_sha, segno)
-        self._rt_tries[segno] = self._rt_tries[segno] + 1
-        self.update_rt_wait(time.time())
-        return seg
-
-    def complete(self):
-        return self._complete
-
-    def dispatch_time(self):
-        return self._dispatch_time
-
-    def set_dispatch_time(self):
-        self._dispatch_time = time.time()
-
-    def data(self):
-        return (self._data, self._data_sha)
-
-    def last_incoming_time(self):
-        return self._last_incoming_time
-
-    def next_rt_time(self):
-        return self._next_rt_time
-
-    def rt_tries(self, segno):
-        if self._rt_tries.has_key(segno):
-            return self._rt_tries[segno]
-        return 0
-
-
-def _get_local_interfaces():
-    import array
-    import struct
-    import fcntl
-    import socket
-
-    max_possible = 4
-    bytes = max_possible * 32
-    SIOCGIFCONF = 0x8912
-    names = array.array('B', '\0' * bytes)
-
-    sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-    ifreq = struct.pack('iL', bytes, names.buffer_info()[0])
-    result = fcntl.ioctl(sockfd.fileno(), SIOCGIFCONF, ifreq)
-    sockfd.close()
-
-    outbytes = struct.unpack('iL', result)[0]
-    namestr = names.tostring()
-
-    return [namestr[i:i+32].split('\0', 1)[0] for i in range(0, outbytes, 32)]
-
-def _get_local_ip_addresses():
-    """Call Linux specific bits to retrieve our own IP address."""
-    import socket
-    import sys
-    import fcntl
-    import struct
-
-    intfs = _get_local_interfaces()
-
-    ips = []
-    SIOCGIFADDR = 0x8915
-    sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-    for intf in intfs:
-        if intf == "lo":
-            continue
-        try:
-            ifreq = (intf + '\0'*32)[:32]
-            result = fcntl.ioctl(sockfd.fileno(), SIOCGIFADDR, ifreq)
-            addr = socket.inet_ntoa(result[20:24])
-            ips.append(addr)
-        except IOError, exc:
-            print "Error getting IP address: %s" % exc
-    sockfd.close()
-    return ips
-
-
-class MostlyReliablePipe(object):
-    """Implement Mostly-Reliable UDP.  We don't actually care about guaranteeing
-    delivery or receipt, just a better effort than no effort at all."""
-
-    _UDP_MSG_SIZE = SegmentBase.mtu() + SegmentBase.header_len()
-    _SEGMENT_TTL = 120 # 2 minutes
-
-    def __init__(self, local_addr, remote_addr, port, data_cb, user_data=None):
-        self._local_addr = local_addr
-        self._remote_addr = remote_addr
-        self._port = port
-        self._data_cb = data_cb
-        self._user_data = user_data
-        self._started = False
-        self._send_worker = 0
-        self._seq_counter = 0
-        self._drop_prob = 0
-        self._rt_check_worker_id = 0
-
-        self._outgoing = []
-        self._sent = {}
-
-        self._incoming = {}  # (message sha, # of segments) -> [segment1, segment2, ...]
-        self._dispatched = {}
-        self._acks = {} # (message sequence #, master sha, source addr) -> received timestamp
-        self._ack_check_worker_id = 0
-
-        self._local_ips = _get_local_ip_addresses()
-
-        self._setup_listener()
-        self._setup_sender()
-
-    def __del__(self):
-        if self._send_worker > 0:
-            gobject.source_remove(self._send_worker)
-            self._send_worker = 0
-        if self._rt_check_worker_id > 0:
-            gobject.source_remove(self._rt_check_worker_id)
-            self._rt_check_worker_id = 0
-        if self._ack_check_worker_id > 0:
-            gobject.source_remove(self._ack_check_worker_id)
-            self._ack_check_worker_id = 0
-
-    def _setup_sender(self):
-        """Setup the send socket for multicast."""
-        self._send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-        # Make the socket multicast-aware, and set TTL.
-        self._send_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 20) # Change TTL (=20) to suit
-
-    def _setup_listener(self):
-        """Set up the listener socket for multicast traffic."""
-        # Listener socket
-        self._listen_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-
-        # Set some options to make it multicast-friendly
-        self._listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-        self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, 20)
-        self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1)
-
-    def start(self):
-        """Let the listener socket start listening for network data."""
-        # Set some more multicast options
-        self._listen_sock.bind((self._local_addr, self._port))
-        self._listen_sock.settimeout(2)
-# Disable for now to try to fix "cannot assign requested address" errors
-#        intf = socket.gethostbyname(socket.gethostname())
-#        self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF,
-#                socket.inet_aton(intf) + socket.inet_aton('0.0.0.0'))
-        self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP,
-                socket.inet_aton(self._remote_addr) + socket.inet_aton('0.0.0.0'))
-
-        # Watch the listener socket for data
-        gobject.io_add_watch(self._listen_sock, gobject.IO_IN, self._handle_incoming_data)
-        gobject.timeout_add(self._SEGMENT_TTL * 1000, self._segment_ttl_worker)
-        self._rt_check_worker_id = gobject.timeout_add(50, self._retransmit_check_worker)
-        self._ack_check_worker_id = gobject.timeout_add(50, self._ack_check_worker)
-
-        self._started = True
-
-    def _segment_ttl_worker(self):
-        """Cull already-sent message segments that are past their TTL."""
-        now = time.time()
-        for key in self._sent.keys()[:]:
-            segment = self._sent[key]
-            if segment.stime() < now - self._SEGMENT_TTL:
-                if segment.userdata:
-                    gobject.source_remove(segment.userdata)
-                del self._sent[key]
-
-        # Cull incomplete incoming segment chains that haven't gotten any data
-        # for a long time either
-        for msg_key in self._incoming.keys()[:]:
-            message = self._incoming[msg_key]
-            if message.last_incoming_time() < now - self._SEGMENT_TTL:
-                del self._incoming[msg_key]
-
-        # Remove already received and dispatched messages after a while
-        for msg_key in self._dispatched.keys()[:]:
-            message = self._dispatched[msg_key]
-            if message.dispatch_time() < now - (self._SEGMENT_TTL*2):
-                del self._dispatched[msg_key]
-
-        # Remove received acks after a while
-        for ack_key in self._acks.keys()[:]:
-            ack_time = self._acks[ack_key]
-            if ack_time < now - (self._SEGMENT_TTL*2):
-                del self._acks[ack_key]
-
-        return True
-
-    _MAX_SEGMENT_RETRIES = 10
-    def _retransmit_request(self, message):
-        """Returns true if the message has exceeded it's retry limit."""
-        first_missing = message.first_missing()
-        if first_missing > 0:
-            num_retries = message.rt_tries(first_missing)
-            if num_retries > self._MAX_SEGMENT_RETRIES:
-                return True
-            msg_seq = self._next_msg_seq()
-            seg = message.get_retransmit_message(msg_seq, first_missing)
-            if seg:
-                print "(MRP): Requesting retransmit of %d by %s" % (first_missing, message.source_address())
-                self._outgoing.append(seg)
-                self._schedule_send_worker()
-        return False
-
-    def _retransmit_check_worker(self):
-        """Periodically check for and send retransmit requests for message
-        segments that got lost."""
-        try:
-            now = time.time()
-            for key in self._incoming.keys()[:]:
-                message = self._incoming[key]
-                if message.complete():
-                    continue
-                next_rt = message.next_rt_time()
-                if next_rt == 0 or next_rt > now:
-                    continue
-                if self._retransmit_request(message):
-                    # Kill the message, too many retries
-                    print "(MRP): Dropped message %s, exceeded retries." % _stringify_sha(message.sha())
-                    self._dispatched[key] = message
-                    message.set_dispatch_time()
-                    del self._incoming[key]
-        except KeyboardInterrupt:
-            return False
-        return True
-
-    def _process_incoming_data(self, segment):
-        """Handle a new message segment.  First checks if there is only one
-        segment to the message, and if the checksum from the header matches
-        that computed from the data, dispatches it.  Otherwise, it adds the
-        new segment to the list of other segments for that message, and 
-        checks to see if the message is complete.  If all segments are present,
-        the message is reassembled and dispatched."""
-
-        msg_sha = segment.master_sha()
-        nsegs = segment.total_segments()
-        addr = segment.address()
-        segno = segment.segment_number()
-
-        msg_seq_num = segment.message_sequence_number()
-        msg_key = (addr[0], msg_seq_num, msg_sha, nsegs)
-
-        if self._dispatched.has_key(msg_key):
-            # We already dispatched this message, this segment is useless
-            return
-        # First segment in the message
-        if not self._incoming.has_key(msg_key):
-            self._incoming[msg_key] = Message((addr[0], self._port), msg_seq_num, msg_sha, nsegs)
-            # Acknowledge the message if it didn't come from us
-            if addr[0] not in self._local_ips:
-                ack_key = (msg_seq_num, msg_sha, addr[0])
-                if not self._acks.has_key(ack_key):
-                    self._send_ack_for_message(msg_seq_num, msg_sha, addr[0])
-
-        message = self._incoming[msg_key]
-        # Look for a dupe, and if so, drop the new segment
-        if message.has_segment(segno):
-            return
-        message.add_segment(segment)
-
-        # Dispatch the message if all segments are present and the sha is correct
-        if message.complete():
-            (msg_data, complete_data_sha) = message.data()
-            if msg_sha == complete_data_sha:
-                self._data_cb(addr, msg_data, self._user_data)
-            self._dispatched[msg_key] = message
-            message.set_dispatch_time()
-            del self._incoming[msg_key]
-            return
-
-    def _segment_retransmit_cb(self, key, segment):
-        """Add a segment ot the outgoing queue and schedule its transmission."""
-        del self._sent[key]
-        self._outgoing.append(segment)
-        self._schedule_send_worker()
-        return False
-
-    def _schedule_segment_retransmit(self, key, segment, when, now):
-        """Schedule retransmission of a segment if one is not already scheduled."""
-        if segment.userdata:
-            # Already scheduled for retransmit
-            return
-
-        if when <= now:
-            # Immediate retransmission
-            self._segment_retransmit_cb(key, segment)
-        else:
-            # convert time to milliseconds
-            timeout = int((when - now) * 1000)
-            segment.userdata = gobject.timeout_add(timeout, self._segment_retransmit_cb,
-                key, segment)
-
-    _STD_RETRANSMIT_INTERVAL = 0.05  # 50ms (in seconds)
-    def _process_retransmit_request(self, segment):
-        """Validate and process a retransmission request."""
-        key = (segment.rt_msg_seq_num(), segment.rt_master_sha(), segment.rt_segment_number())
-        if not self._sent.has_key(key):
-            # Either we don't know about the segment, or it was already culled
-            return
-
-        # Calculate next retransmission time and schedule packet for retransmit
-        segment = self._sent[key]
-        # only retransmit segments every 150ms or more
-        now = time.time()
-        next_transmit = max(now, segment.last_transmit() + self._STD_RETRANSMIT_INTERVAL)
-        self._schedule_segment_retransmit(key, segment, next_transmit, now)
-
-    def _ack_check_worker(self):
-        """Periodically check for messages that haven't received an ack
-        yet, and retransmit them."""
-        try:
-            now = time.time()
-            for key in self._sent.keys()[:]:
-                segment = self._sent[key]
-                # We only care about retransmitting the first segment
-                # of a message, since if other machines don't have the
-                # rest of the segments, they'll issue retransmit requests
-                if segment.segment_number() != 1:
-                    continue
-                if segment.last_transmit() > now - 0.150: # 150ms
-                    # Was just retransmitted recently, wait longer
-                    # before retransmitting it
-                    continue
-                ack_key = None
-                for ip in self._local_ips:
-                    ack_key = (segment.message_sequence_number(), segment.master_sha(), ip)
-                    if self._acks.has_key(ack_key):
-                        break
-                    ack_key = None
-                # If the segment already has been acked, don't send it
-                # again unless somebody explicitly requests a retransmit
-                if ack_key is not None:
-                    continue
-
-                del self._sent[key]
-                self._outgoing.append(segment)
-                self._schedule_send_worker()
-        except KeyboardInterrupt:
-            return False
-        return True
-
-    def _send_ack_for_message(self, ack_msg_seq_num, ack_msg_sha, ack_addr):
-        """Send an ack segment for a message."""
-        msg_seq_num = self._next_msg_seq()
-        full_remote_addr = (self._remote_addr, self._port)
-        ack = AckSegment.new_from_parts(full_remote_addr, msg_seq_num,
-            ack_msg_seq_num, ack_msg_sha, ack_addr)
-        self._outgoing.append(ack)
-        self._schedule_send_worker()
-        self._process_incoming_ack(ack)
-
-    def _process_incoming_ack(self, segment):
-        """Save the ack so that we don't send an ack when we start getting the segments
-        the ack was acknowledging."""
-        # If the ack is supposed to be for a message we sent, only accept it if
-        # we actually sent the message to which it refers
-        ack_addr = segment.ack_addr()
-        ack_master_sha = segment.ack_master_sha()
-        ack_msg_seq_num = segment.ack_msg_seq_num()
-        if ack_addr in self._local_ips:
-            sent_key = (ack_msg_seq_num, ack_master_sha, 1)
-            if not self._sent.has_key(sent_key):
-                return
-        ack_key = (ack_msg_seq_num, ack_master_sha, ack_addr)
-        if not self._acks.has_key(ack_key):
-            self._acks[ack_key] = time.time()
-
-    def set_drop_probability(self, prob=4):
-        """Debugging function to randomly drop incoming packets.
-        The prob argument should be an integer between 1 and 10 to drop,
-        or 0 to drop none.  Higher numbers drop more packets."""
-        if not isinstance(prob, int):
-            raise ValueError("Drop probability must be an integer.")
-        if prob < 1 or prob > 10:
-            raise ValueError("Drop probability must be between 1 and 10 inclusive.")
-        self._drop_prob = prob
-
-    def _handle_incoming_data(self, source, condition):
-        """Handle incoming network data by making a message segment out of it
-        sending it off to the processing function."""
-        if not (condition & gobject.IO_IN):
-            return True
-        msg = {}
-        data, addr = source.recvfrom(self._UDP_MSG_SIZE)
-
-        should_drop = False
-        p = random.random() * 10.0
-        if self._drop_prob > 0 and p <= self._drop_prob:
-            should_drop = True
-
-        try:
-            segment = SegmentBase.new_from_data(addr, data)
-            if should_drop:
-                print "(MRP): Dropped segment %d." % segment.segment_number()
-            else:
-                stype = segment.segment_type()
-                if stype == SegmentBase.type_data():
-                    self._process_incoming_data(segment)
-                elif stype == SegmentBase.type_retransmit():
-                    self._process_retransmit_request(segment)
-                elif stype == SegmentBase.type_ack():
-                    self._process_incoming_ack(segment)
-        except ValueError, exc:
-            print "(MRP): Bad segment: %s" % exc
-        return True
-
-    def _next_msg_seq(self):
-        self._seq_counter = self._seq_counter + 1
-        if self._seq_counter > 65535:
-            self._seq_counter = 1
-        return self._seq_counter
-
-    def send(self, data):
-        """Break data up into chunks and queue for later transmission."""
-        if not self._started:
-            raise Exception("Can't send anything until started!")
-
-        msg_seq = self._next_msg_seq()
-
-        # Pack the data into network byte order
-        template = "! %ds" % len(str(data))
-        data = struct.pack(template, str(data))
-        master_sha = _sha_data(data)
-
-        # Split up the data into segments
-        left = length = len(data)
-        mtu = SegmentBase.mtu()
-        nmessages = length / mtu
-        if length % mtu > 0:
-            nmessages = nmessages + 1
-        seg_num = 1
-        while left > 0:
-            seg = DataSegment.new_from_parts(seg_num, nmessages,
-                    msg_seq, master_sha, data[:mtu])
-            self._outgoing.append(seg)
-            seg_num = seg_num + 1
-            data = data[mtu:]
-            left = left - mtu
-        self._schedule_send_worker()
-
-    def _schedule_send_worker(self):
-        if len(self._outgoing) > 0 and self._send_worker == 0:
-            self._send_worker = gobject.timeout_add(50, self._send_worker_cb)
-
-    def _send_worker_cb(self):
-        """Send all queued segments that have yet to be transmitted."""
-        self._send_worker = 0
-        nsent = 0
-        for segment in self._outgoing:
-            packet = segment.packetize()
-            segment.inc_transmits()
-            addr = (self._remote_addr, self._port)
-            if segment.address():
-                addr = segment.address()
-            self._send_sock.sendto(packet, addr)
-            if segment.userdata:
-                gobject.source_remove(segment.userdata)
-            segment.userdata = None  # Retransmission GSource
-            key = (segment.message_sequence_number(), segment.master_sha(), segment.segment_number())
-            self._sent[key] = segment
-            nsent = nsent + 1
-            if nsent > 10:
-                break
-        self._outgoing = self._outgoing[nsent:]
-        if len(self._outgoing):
-            self._schedule_send_worker()
-        return False
-
-
-#################################################################
-# Tests
-#################################################################
-
-import unittest
-
-
-class SegmentBaseTestCase(unittest.TestCase):
-    _DEF_SEGNO = 1
-    _DEF_TOT_SEGS = 5
-    _DEF_MSG_SEQ_NUM = 4556
-    _DEF_MASTER_SHA = "12345678901234567890"
-    _DEF_SEG_TYPE = 0
-
-    _DEF_ADDRESS = ('123.3.2.1', 3333)
-    _SEG_MAGIC = 0xbaea4304
-
-
-class SegmentBaseInitTestCase(SegmentBaseTestCase):
-    def _test_init_fail(self, segno, total_segs, msg_seq_num, master_sha, fail_msg):
-        try:
-            seg = SegmentBase(segno, total_segs, msg_seq_num, master_sha)
-        except ValueError, exc:
-            pass
-        else:
-            self.fail("expected a ValueError for %s." % fail_msg)
-
-    def testSegmentBase(self):
-        assert SegmentBase.magic() == self._SEG_MAGIC, "Segment magic wasn't correct!"
-        assert SegmentBase.header_len() > 0, "header size was not greater than zero."
-        assert SegmentBase.mtu() > 0, "MTU was not greater than zero."
-        assert SegmentBase.mtu() + SegmentBase.header_len() == _UDP_DATAGRAM_SIZE, "MTU + header size didn't equal expected %d." % _UDP_DATAGRAM_SIZE
-
-    def testGoodInit(self):
-        seg = SegmentBase(self._DEF_SEGNO, self._DEF_TOT_SEGS, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA)
-        assert seg.stime() < time.time(), "segment start time is less than now!"
-        assert not seg.address(), "Segment address was not None after init."
-        assert seg.segment_number() == self._DEF_SEGNO, "Segment number wasn't correct after init."
-        assert seg.total_segments() == self._DEF_TOT_SEGS, "Total segments wasn't correct after init."
-        assert seg.message_sequence_number() == self._DEF_MSG_SEQ_NUM, "Message sequence number wasn't correct after init."
-        assert seg.master_sha() == self._DEF_MASTER_SHA, "Message master SHA wasn't correct after init."
-        assert seg.segment_type() == None, "Segment type was not None after init."
-        assert seg.transmits() == 0, "Segment transmits was not 0 after init."
-        assert seg.last_transmit() == 0, "Segment last transmit was  not 0 after init."
-        assert seg.data() == None, "Segment data was not None after init."
-
-    def testSegmentNumber(self):
-        self._test_init_fail(0, self._DEF_TOT_SEGS, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, "invalid segment number")
-        self._test_init_fail(65536, self._DEF_TOT_SEGS, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, "invalid segment number")
-        self._test_init_fail(None, self._DEF_TOT_SEGS, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, "invalid segment number")
-        self._test_init_fail("", self._DEF_TOT_SEGS, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, "invalid segment number")
-
-    def testTotalMessageSegmentNumber(self):
-        self._test_init_fail(self._DEF_SEGNO, 0, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, "invalid total segments")
-        self._test_init_fail(self._DEF_SEGNO, 65536, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, "invalid total segments")
-        self._test_init_fail(self._DEF_SEGNO, None, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, "invalid total segments")
-        self._test_init_fail(self._DEF_SEGNO, "", self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, "invalid total segments")
-
-    def testMessageSequenceNumber(self):
-        self._test_init_fail(self._DEF_SEGNO, self._DEF_TOT_SEGS, 0, self._DEF_MASTER_SHA, "invalid message sequence number")
-        self._test_init_fail(self._DEF_SEGNO, self._DEF_TOT_SEGS, 65536, self._DEF_MASTER_SHA, "invalid message sequence number")
-        self._test_init_fail(self._DEF_SEGNO, self._DEF_TOT_SEGS, None, self._DEF_MASTER_SHA, "invalid message sequence number")
-        self._test_init_fail(self._DEF_SEGNO, self._DEF_TOT_SEGS, "", self._DEF_MASTER_SHA, "invalid message sequence number")
-
-    def testMasterSHA(self):
-        self._test_init_fail(self._DEF_SEGNO, self._DEF_TOT_SEGS, self._DEF_MSG_SEQ_NUM, "1" * 19, "invalid SHA1 data hash")
-        self._test_init_fail(self._DEF_SEGNO, self._DEF_TOT_SEGS, self._DEF_MSG_SEQ_NUM, "1" * 21, "invalid SHA1 data hash")
-        self._test_init_fail(self._DEF_SEGNO, self._DEF_TOT_SEGS, self._DEF_MSG_SEQ_NUM, None, "invalid SHA1 data hash")
-        self._test_init_fail(self._DEF_SEGNO, self._DEF_TOT_SEGS, self._DEF_MSG_SEQ_NUM, 1234, "invalid SHA1 data hash")
-
-    def _testNewFromDataFail(self, addr, data, fail_msg):
-        try:
-            seg = SegmentBase.new_from_data(addr, data)
-        except ValueError, exc:
-            pass
-        else:
-            self.fail("expected a ValueError about %s." % fail_msg)
-
-    def testNewFromDataAddress(self):
-        self._testNewFromDataFail(None, None, "bad address")
-        self._testNewFromDataFail('', None, "bad address")
-        self._testNewFromDataFail((''), None, "bad address")
-        self._testNewFromDataFail((1), None, "bad address")
-        self._testNewFromDataFail(('', ''), None, "bad address")
-        self._testNewFromDataFail((1, 3333), None, "bad address")
-        self._testNewFromDataFail(('', 0), None, "bad address")
-        self._testNewFromDataFail(('', 65536), None, "bad address")
-
-    def testNewFromDataData(self):
-        """Only test generic new_from_data() bits, not type-specific ones."""
-        self._testNewFromDataFail(self._DEF_ADDRESS, None, "invalid data")
-
-        really_short_data = "111"
-        self._testNewFromDataFail(self._DEF_ADDRESS, really_short_data, "data too short")
-
-        only_header_data = "1" * SegmentBase.header_len()
-        self._testNewFromDataFail(self._DEF_ADDRESS, only_header_data, "data too short")
-
-        too_much_data = "1" * (_UDP_DATAGRAM_SIZE + 1)
-        self._testNewFromDataFail(self._DEF_ADDRESS, too_much_data, "too much data")
-
-        header_template = SegmentBase.header_template()
-        bad_magic_data = struct.pack(header_template, 0x12345678, self._DEF_SEG_TYPE, 
-                self._DEF_SEGNO, self._DEF_TOT_SEGS, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA)
-        self._testNewFromDataFail(self._DEF_ADDRESS, bad_magic_data, "invalid magic")
-
-        bad_type_data = struct.pack(header_template, self._SEG_MAGIC, -1, self._DEF_SEGNO,
-                self._DEF_TOT_SEGS, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA)
-        self._testNewFromDataFail(self._DEF_ADDRESS, bad_type_data, "invalid segment type")
-
-        # Test master_sha that doesn't match data's SHA
-        header = struct.pack(header_template, self._SEG_MAGIC, self._DEF_SEG_TYPE, 1, 1,
-                self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA)
-        data = struct.pack("! 15s", "7" * 15)
-        self._testNewFromDataFail(self._DEF_ADDRESS, header + data, "single-segment message SHA mismatch")
-
-    def addToSuite(suite):
-        suite.addTest(SegmentBaseInitTestCase("testGoodInit"))
-        suite.addTest(SegmentBaseInitTestCase("testSegmentNumber"))
-        suite.addTest(SegmentBaseInitTestCase("testTotalMessageSegmentNumber"))
-        suite.addTest(SegmentBaseInitTestCase("testMessageSequenceNumber"))
-        suite.addTest(SegmentBaseInitTestCase("testMasterSHA"))
-        suite.addTest(SegmentBaseInitTestCase("testNewFromDataAddress"))
-        suite.addTest(SegmentBaseInitTestCase("testNewFromDataData"))
-    addToSuite = staticmethod(addToSuite)
-
-
-class DataSegmentTestCase(SegmentBaseTestCase):
-    """Test DataSegment class specific initialization and stuff."""
-
-    def testInit(self):
-        seg = DataSegment(self._DEF_SEGNO, self._DEF_TOT_SEGS, self._DEF_MSG_SEQ_NUM,
-                self._DEF_MASTER_SHA)
-        assert seg.segment_type() == SegmentBase.type_data(), "Segment wasn't a data segment."
-
-    def testNewFromParts(self):
-        try:
-            seg = DataSegment.new_from_parts(self._DEF_SEGNO, self._DEF_TOT_SEGS,
-                    self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, None)
-        except ValueError, exc:
-            pass
-        else:
-            self.fail("Expected ValueError about invalid data.")
-
-        # Ensure message data is same as we stuff in after object is instantiated
-        payload = "How are you today?"
-        seg = DataSegment.new_from_parts(self._DEF_SEGNO, self._DEF_TOT_SEGS, self._DEF_MSG_SEQ_NUM,
-                self._DEF_MASTER_SHA, payload)
-        assert seg.data() == payload, "Data after segment creation didn't match expected."
-
-    def testNewFromData(self):
-        """Test DataSegment's new_from_data() functionality."""
-
-        # Make sure something valid actually works
-        header_template = SegmentBase.header_template()
-        payload_str = "How are you today?"
-        payload = struct.pack("! %ds" % len(payload_str), payload_str)
-        payload_sha = _sha_data(payload)
-        header = struct.pack(header_template, self._SEG_MAGIC, SegmentBase.type_data(), self._DEF_SEGNO,
-                self._DEF_TOT_SEGS, self._DEF_MSG_SEQ_NUM, payload_sha)
-        seg = SegmentBase.new_from_data(self._DEF_ADDRESS, header + payload)
-
-        assert seg.address() == self._DEF_ADDRESS, "Segment address did not match expected."
-        assert seg.segment_type() == SegmentBase.type_data(), "Segment type did not match expected."
-        assert seg.segment_number() == self._DEF_SEGNO, "Segment number did not match expected."
-        assert seg.total_segments() == self._DEF_TOT_SEGS, "Total segments did not match expected."
-        assert seg.message_sequence_number() == self._DEF_MSG_SEQ_NUM, "Message sequence number did not match expected."
-        assert seg.master_sha() == payload_sha, "Message master SHA did not match expected."
-        assert seg.data() == payload, "Segment data did not match expected payload."
-
-    def addToSuite(suite):
-        suite.addTest(DataSegmentTestCase("testInit"))
-        suite.addTest(DataSegmentTestCase("testNewFromParts"))
-        suite.addTest(DataSegmentTestCase("testNewFromData"))
-    addToSuite = staticmethod(addToSuite)
-
-
-class RetransmitSegmentTestCase(SegmentBaseTestCase):
-    """Test RetransmitSegment class specific initialization and stuff."""
-
-    def _test_init_fail(self, segno, total_segs, msg_seq_num, master_sha, fail_msg):
-        try:
-            seg = RetransmitSegment(segno, total_segs, msg_seq_num, master_sha)
-        except ValueError, exc:
-            pass
-        else:
-            self.fail("expected a ValueError for %s." % fail_msg)
-
-    def testInit(self):
-        self._test_init_fail(0, 1, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, "invalid segment number")
-        self._test_init_fail(2, 1, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, "invalid segment number")
-        self._test_init_fail(1, 0, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, "invalid number of total segments")
-        self._test_init_fail(1, 2, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, "invalid number of total segments")
-
-        # Something that's supposed to work
-        seg = RetransmitSegment(1, 1, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA)
-        assert seg.segment_type() == SegmentBase.type_retransmit(), "Segment wasn't a retransmit segment."
-
-    def _test_new_from_parts_fail(self, msg_seq_num, rt_msg_seq_num, rt_master_sha, rt_segment_number, fail_msg):
-        try:
-            seg = RetransmitSegment.new_from_parts(self._DEF_ADDRESS, msg_seq_num, rt_msg_seq_num,
-                        rt_master_sha, rt_segment_number)
-        except ValueError, exc:
-            pass
-        else:
-            self.fail("expected a ValueError for %s." % fail_msg)
-
-    def testNewFromParts(self):
-        """Test RetransmitSegment's new_from_parts() functionality."""
-        self._test_new_from_parts_fail(0, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA,
-                self._DEF_SEGNO, "invalid message sequence number")
-        self._test_new_from_parts_fail(65536, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA,
-                self._DEF_SEGNO, "invalid message sequence number")
-        self._test_new_from_parts_fail(None, self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA,
-                self._DEF_SEGNO, "invalid message sequence number")
-        self._test_new_from_parts_fail("", self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA,
-                self._DEF_SEGNO, "invalid message sequence number")
-
-        self._test_new_from_parts_fail(self._DEF_MSG_SEQ_NUM, 0, self._DEF_MASTER_SHA,
-                self._DEF_SEGNO, "invalid retransmit message sequence number")
-        self._test_new_from_parts_fail(self._DEF_MSG_SEQ_NUM, 65536, self._DEF_MASTER_SHA,
-                self._DEF_SEGNO, "invalid retransmit message sequence number")
-        self._test_new_from_parts_fail(self._DEF_MSG_SEQ_NUM, None, self._DEF_MASTER_SHA,
-                self._DEF_SEGNO, "invalid retransmit message sequence number")
-        self._test_new_from_parts_fail(self._DEF_MSG_SEQ_NUM, "", self._DEF_MASTER_SHA,
-                self._DEF_SEGNO, "invalid retransmit message sequence number")
-
-        self._test_new_from_parts_fail(self._DEF_MSG_SEQ_NUM, self._DEF_MSG_SEQ_NUM, "1" * 19,
-                self._DEF_SEGNO, "invalid retransmit message master SHA")
-        self._test_new_from_parts_fail(self._DEF_MSG_SEQ_NUM, self._DEF_MSG_SEQ_NUM, "1" * 21,
-                self._DEF_SEGNO, "invalid retransmit message master SHA")
-        self._test_new_from_parts_fail(self._DEF_MSG_SEQ_NUM, self._DEF_MSG_SEQ_NUM, None,
-                self._DEF_SEGNO, "invalid retransmit message master SHA")
-        self._test_new_from_parts_fail(self._DEF_MSG_SEQ_NUM, self._DEF_MSG_SEQ_NUM, 1234,
-                self._DEF_SEGNO, "invalid retransmit message master SHA")
-
-        self._test_new_from_parts_fail(self._DEF_MSG_SEQ_NUM, self._DEF_MSG_SEQ_NUM,
-                self._DEF_MASTER_SHA, 0, "invalid retransmit message segment number")
-        self._test_new_from_parts_fail(self._DEF_MSG_SEQ_NUM, self._DEF_MSG_SEQ_NUM,
-                self._DEF_MASTER_SHA, 65536, "invalid retransmit message segment number")
-        self._test_new_from_parts_fail(self._DEF_MSG_SEQ_NUM, self._DEF_MSG_SEQ_NUM,
-                self._DEF_MASTER_SHA, None, "invalid retransmit message segment number")
-        self._test_new_from_parts_fail(self._DEF_MSG_SEQ_NUM, self._DEF_MSG_SEQ_NUM,
-                self._DEF_MASTER_SHA, "", "invalid retransmit message segment number")
-
-        # Ensure message data is same as we stuff in after object is instantiated
-        seg = RetransmitSegment.new_from_parts(self._DEF_ADDRESS, self._DEF_MSG_SEQ_NUM, self._DEF_MSG_SEQ_NUM,
-                self._DEF_MASTER_SHA, self._DEF_SEGNO)
-        assert seg.rt_msg_seq_num() == self._DEF_MSG_SEQ_NUM, "RT message sequence number after segment creation didn't match expected."
-        assert seg.rt_master_sha() == self._DEF_MASTER_SHA, "RT master SHA after segment creation didn't match expected."
-        assert seg.rt_segment_number() == self._DEF_SEGNO, "RT segment number after segment creation didn't match expected."
-
-    def _new_from_data(self, rt_msg_seq_num, rt_master_sha, rt_segment_number):
-        payload = struct.pack(RetransmitSegment.data_template(), rt_msg_seq_num, rt_master_sha, rt_segment_number)
-        payload_sha = _sha_data(payload)
-        header_template = SegmentBase.header_template()
-        header = struct.pack(header_template, self._SEG_MAGIC, SegmentBase.type_retransmit(), 1, 1,
-                self._DEF_MSG_SEQ_NUM, payload_sha)
-        return header + payload
-
-    def _test_new_from_data_fail(self, rt_msg_seq_num, rt_master_sha, rt_segment_number, fail_msg):
-        try:
-            packet = self._new_from_data(rt_msg_seq_num, rt_master_sha, rt_segment_number)
-            seg = SegmentBase.new_from_data(self._DEF_ADDRESS, packet)
-        except ValueError, exc:
-            pass
-        else:
-            self.fail("Expected a ValueError about %s." % fail_msg)
-
-    def testNewFromData(self):
-        """Test DataSegment's new_from_data() functionality."""
-        self._test_new_from_data_fail(0, self._DEF_MASTER_SHA, self._DEF_SEGNO, "invalid RT message sequence number")
-        self._test_new_from_data_fail(65536, self._DEF_MASTER_SHA, self._DEF_SEGNO, "invalid RT message sequence number")
-        
-        self._test_new_from_data_fail(self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, 0, "invalid RT segment number")
-        self._test_new_from_data_fail(self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, 65536, "invalid RT segment number")
-
-        # Ensure something that should work
-        packet = self._new_from_data(self._DEF_MSG_SEQ_NUM, self._DEF_MASTER_SHA, self._DEF_SEGNO)
-        seg = SegmentBase.new_from_data(self._DEF_ADDRESS, packet)
-        assert seg.segment_type() == SegmentBase.type_retransmit(), "Segment wasn't expected type."
-        assert seg.rt_msg_seq_num() == self._DEF_MSG_SEQ_NUM, "Segment RT message sequence number didn't match expected."
-        assert seg.rt_master_sha() == self._DEF_MASTER_SHA, "Segment RT master SHA didn't match expected."
-        assert seg.rt_segment_number() == self._DEF_SEGNO, "Segment RT segment number didn't match expected."
-
-    def testPartsToData(self):
-        seg = RetransmitSegment.new_from_parts(self._DEF_ADDRESS, self._DEF_MSG_SEQ_NUM, self._DEF_MSG_SEQ_NUM,
-                self._DEF_MASTER_SHA, self._DEF_SEGNO)
-        new_seg = SegmentBase.new_from_data(self._DEF_ADDRESS, seg.packetize())
-        assert new_seg.rt_msg_seq_num() == self._DEF_MSG_SEQ_NUM, "Segment RT message sequence number didn't match expected."
-        assert new_seg.rt_master_sha() == self._DEF_MASTER_SHA, "Segment RT master SHA didn't match expected."
-        assert new_seg.rt_segment_number() == self._DEF_SEGNO, "Segment RT segment number didn't match expected."
-
-    def addToSuite(suite):
-        suite.addTest(RetransmitSegmentTestCase("testInit"))
-        suite.addTest(RetransmitSegmentTestCase("testNewFromParts"))
-        suite.addTest(RetransmitSegmentTestCase("testNewFromData"))
-        suite.addTest(RetransmitSegmentTestCase("testPartsToData"))
-    addToSuite = staticmethod(addToSuite)
-
-
-class SHAUtilsTestCase(unittest.TestCase):
-    def testSHA(self):
-        data = "235jklqt3hjwasdv879wfe89723rqjh32tr3hwaejksdvd89udsv89dsgiougjktqjhk23tjht23hjt3qhjewagthjasgdgsd"
-        data_sha = _sha_data(data)
-        assert len(data_sha) == 20, "SHA wasn't correct size."
-        known_sha = "\xee\x9e\xb9\x1d\xe8\x96\x75\xcb\x12\xf1\x25\x22\x0f\x76\xf7\xf3\xc8\x4e\xbf\xcd"
-        assert data_sha == known_sha, "SHA didn't match known SHA."
-
-    def testStringifySHA(self):
-        data = "jlkwjlkaegdjlksgdjklsdgajklganjtwn23n325n23tjwgeajkga nafDA fwqnjlqtjkl23tjk2365jlk235jkl2356jlktjkltewjlktewjklewtjklaggsda"
-        data_known_sha = "9650c23db78092a0ffda4577c87ebf36d25c868e"
-        assert _stringify_sha(_sha_data(data)) == data_known_sha, "SHA stringify didn't return correct SHA."
-        # Do it twice for kicks
-        assert _stringify_sha(_sha_data(data)) == data_known_sha, "SHA stringify didn't return correct SHA."
-
-    def addToSuite(suite):
-        suite.addTest(SHAUtilsTestCase("testSHA"))
-        suite.addTest(SHAUtilsTestCase("testStringifySHA"))
-    addToSuite = staticmethod(addToSuite)
-
-
-
-def unit_test():
-    suite = unittest.TestSuite()
-    SegmentBaseInitTestCase.addToSuite(suite)
-    DataSegmentTestCase.addToSuite(suite)
-    RetransmitSegmentTestCase.addToSuite(suite)
-    SHAUtilsTestCase.addToSuite(suite)
-
-    runner = unittest.TextTestRunner()
-    runner.run(suite)
-
-
-
-def got_data(addr, data, user_data=None):
-    print "Got data from %s, writing to %s." % (addr, user_data)
-    fl = open(user_data, "w+")
-    fl.write(data)
-    fl.close()    
-
-def simple_test():
-    import sys
-    pipe = MostlyReliablePipe('', '224.0.0.222', 2293, got_data, sys.argv[2])
-#    pipe.set_drop_probability(4)
-    pipe.start()
-    fl = open(sys.argv[1], "r")
-    data = fl.read()
-    fl.close()
-    msg = """The said Eliza, John, and Georgiana were now clustered round their mama in the drawing-room: 
-she lay reclined on a sofa by the fireside, and with her darlings about her (for the time neither 
-quarrelling nor crying) looked perfectly happy. Me, she had dispensed from joining the group; saying, 
-'She regretted to be under the necessity of keeping me at a distance; but that until she heard from 
-Bessie, and could discover by her own observation, that I was endeavouring in good earnest to acquire 
-a more sociable and childlike disposition, a more attractive and sprightly manner -- something lighter, 
-franker, more natural, as it were -- she really must exclude me from privileges intended only for
- contented, happy, little children.'"""
-    pipe.send(data)
-    try:
-        gtk.main()
-    except KeyboardInterrupt:
-        print 'Ctrl+C pressed, exiting...'
-
-
-
-def net_test_got_data(addr, data, user_data=None):
-    # Don't report data if we are a sender
-    if user_data:
-        return
-    print "%s (%s)" % (data, addr)
-
-idstamp = 0
-def transmit_data(pipe):
-    global idstamp
-    msg = "Message #%d" % idstamp
-    print "Sending '%s'" % msg
-    pipe.send(msg)
-    idstamp = idstamp + 1
-    return True
-
-def network_test():
-    import sys, os
-    send = False
-    if len(sys.argv) != 2:
-        print "Need one arg, either 'send' or 'recv'"
-        os._exit(1)
-    if sys.argv[1] == "send":
-        send = True
-    elif sys.argv[1] == "recv":
-        send = False
-    else:
-        print "Arg should be either 'send' or 'recv'"
-        os._exit(1)
-
-    pipe = MostlyReliablePipe('', '224.0.0.222', 2293, net_test_got_data, send)
-    pipe.start()
-    if send:
-        gobject.timeout_add(1000, transmit_data, pipe)
-    try:
-        gtk.main()
-    except KeyboardInterrupt:
-        print 'Ctrl+C pressed, exiting...'
-
-
-def main():
-#    unit_test()
-#    simple_test()
-    network_test()
-
-if __name__ == "__main__":
-    main()
-
diff --git a/sugar/p2p/NotificationListener.py b/sugar/p2p/NotificationListener.py
deleted file mode 100644
index 42668adc..00000000
--- a/sugar/p2p/NotificationListener.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (C) 2006, Red Hat, Inc.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library 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
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-import logging
-
-from sugar.p2p.Notifier import Notifier
-from sugar.p2p import network
-
-class NotificationListener:
-    def __init__(self, service):
-        logging.debug('Start notification listener. Service %s, address %s, port %s' % (service.get_type(), service.get_address(), service.get_port()))
-        server = network.GroupServer(service.get_address(),
-                                     service.get_port(),
-                                     self._recv_multicast)
-        server.start()
-        
-        self._listeners = []
-    
-    def add_listener(self, listener):
-        self._listeners.append(listener)
-    
-    def _recv_multicast(self, msg):
-        for listener in self._listeners:
-            listener(msg)
diff --git a/sugar/p2p/Notifier.py b/sugar/p2p/Notifier.py
deleted file mode 100644
index 69d0af6b..00000000
--- a/sugar/p2p/Notifier.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2006, Red Hat, Inc.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library 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
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-from sugar.p2p import network
-
-class Notifier:
-    def __init__(self, service):
-        address = service.get_address()
-        port = service.get_port()
-        self._client = network.GroupClient(address, port)
-        
-    def notify(self, msg):
-        self._client.send_msg(msg)
diff --git a/sugar/p2p/Stream.py b/sugar/p2p/Stream.py
deleted file mode 100644
index b3239b30..00000000
--- a/sugar/p2p/Stream.py
+++ /dev/null
@@ -1,160 +0,0 @@
-# Copyright (C) 2006, Red Hat, Inc.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library 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
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-import xmlrpclib
-import socket
-import traceback
-import random
-import logging
-
-import network
-from MostlyReliablePipe import MostlyReliablePipe
-from sugar.presence import Service
-
-def is_multicast_address(address):
-    """Simple numerical check for whether an IP4 address
-    is in the range for multicast addresses or not."""
-    if not address:
-        return False
-    if address[3] != '.':
-        return False
-    first = int(float(address[:3]))
-    if first >= 224 and first <= 239:
-        return True
-    return False
-
-class Stream(object):
-    def __init__(self, service):
-        if not service.get_port():
-            raise ValueError("service must have an address.")
-        self._service = service
-        self._reader_port = self._service.get_port()
-        self._writer_port = self._reader_port
-        self._address = self._service.get_address()
-        self._callback = None
-
-    def new_from_service(service, start_reader=True):
-        if is_multicast_address(service.get_address()):
-            return MulticastStream(service)
-        else:
-            return UnicastStream(service, start_reader)
-    new_from_service = staticmethod(new_from_service)
-
-    def set_data_listener(self, callback):
-        self._callback = callback
-
-    def _recv(self, address, data):
-        if self._callback:
-            self._callback(address, data)
-
-
-class UnicastStreamWriter(object):
-    def __init__(self, stream, service):
-        # set up the writer
-        self._service = service
-        if not service.get_address():
-            raise ValueError("service must have a valid address.")
-        self._address = self._service.get_address()
-        self._port = self._service.get_port()
-        self._xmlrpc_addr = "http://%s:%d" % (self._address, self._port)
-        self._writer = network.GlibServerProxy(self._xmlrpc_addr)
-
-    def write(self, xmlrpc_data):
-        """Write some data to the default endpoint of this pipe on the remote server."""
-        try:
-            self._writer.message(None, None, xmlrpc_data)
-            return True
-        except (socket.error, xmlrpclib.Fault, xmlrpclib.ProtocolError):
-            traceback.print_exc()
-        return False
-
-    def custom_request(self, method_name, request_cb, user_data, *args):
-        """Call a custom XML-RPC method on the remote server."""
-        try:
-            method = getattr(self._writer, method_name)
-            method(request_cb, user_data, *args)
-            return True
-        except (socket.error, xmlrpclib.Fault, xmlrpclib.ProtocolError):
-            traceback.print_exc()
-        return False
-
-
-class UnicastStream(Stream):
-    def __init__(self, service, start_reader=True):
-        """Initializes the stream.  If the 'start_reader' argument is True,
-        the stream will initialize and start a new stream reader, if it
-        is False, no reader will be created and the caller must call the
-        start_reader() method to start the stream reader and be able to
-        receive any data from the stream."""
-        Stream.__init__(self, service)
-        if start_reader:
-            self.start_reader()
-
-    def start_reader(self):
-        """Start the stream's reader, which for UnicastStream objects is
-        and XMLRPC server.  If there's a port conflict with some other
-        service, the reader will try to find another port to use instead.
-        Returns the port number used for the reader."""
-        # Set up the reader
-        self._reader = network.GlibXMLRPCServer(("", self._reader_port))
-        self._reader.register_function(self._message, "message")
-
-    def _message(self, message):
-        """Called by the XMLRPC server when network data arrives."""
-        address = network.get_authinfo()
-        self._recv(address, message)
-        return True
-
-    def register_reader_handler(self, handler, name):
-        """Register a custom message handler with the reader.  This call
-        adds a custom XMLRPC method call with the name 'name' to the reader's
-        XMLRPC server, which then calls the 'handler' argument back when
-        a method call for it arrives over the network."""
-        if name == "message":
-            raise ValueError("Handler name 'message' is a reserved handler.")
-        self._reader.register_function(handler, name)
-
-    def new_writer(self, service):
-        """Return a new stream writer object."""
-        return UnicastStreamWriter(self, service)
-
-
-class MulticastStream(Stream):
-    def __init__(self, service):
-        Stream.__init__(self, service)
-        self._service = service
-        self._internal_start_reader()
-
-    def start_reader(self):
-        return self._reader_port
-
-    def _internal_start_reader(self):
-        logging.debug('Start multicast stream, address %s, port %d' % (self._address, self._reader_port))
-        if not self._service.get_address():
-            raise ValueError("service must have a valid address.")
-        self._pipe = MostlyReliablePipe('', self._address, self._reader_port,
-                self._recv_data_cb)
-        self._pipe.start()
-
-    def write(self, data):
-        self._pipe.send(data)
-
-    def _recv_data_cb(self, address, data, user_data=None):
-        self._recv(address[0], data)
-
-    def new_writer(self, service=None):
-        return self
diff --git a/sugar/p2p/__init__.py b/sugar/p2p/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/sugar/p2p/network.py b/sugar/p2p/network.py
deleted file mode 100644
index 2270e165..00000000
--- a/sugar/p2p/network.py
+++ /dev/null
@@ -1,579 +0,0 @@
-# Copyright (C) 2006, Red Hat, Inc.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library 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
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-# pylint: disable-msg = W0221
-
-import socket
-import os
-import threading
-import traceback
-import xmlrpclib
-import sys
-import httplib
-import urllib
-import fcntl
-
-import gobject
-import SimpleXMLRPCServer
-import SimpleHTTPServer
-import SocketServer
-
-
-__authinfos = {}
-
-def _add_authinfo(authinfo):
-    __authinfos[threading.currentThread()] = authinfo
-
-def get_authinfo():
-    return __authinfos.get(threading.currentThread())
-
-def _del_authinfo():
-    del __authinfos[threading.currentThread()]
-
-
-class GlibTCPServer(SocketServer.TCPServer):
-    """GlibTCPServer
-
-    Integrate socket accept into glib mainloop.
-    """
-
-    allow_reuse_address = True
-    request_queue_size = 20
-
-    def __init__(self, server_address, RequestHandlerClass):
-        SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass)
-        self.socket.setblocking(0)  # Set nonblocking
-
-        # Watch the listener socket for data
-        gobject.io_add_watch(self.socket, gobject.IO_IN, self._handle_accept)
-
-    def _handle_accept(self, source, condition):
-        """Process incoming data on the server's socket by doing an accept()
-        via handle_request()."""
-        if not (condition & gobject.IO_IN):
-            return True
-        self.handle_request()
-        return True
-
-
-class ChunkedGlibHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
-    """RequestHandler class that integrates with Glib mainloop.  It writes
-       the specified file to the client in chunks, returning control to the
-       mainloop between chunks.
-    """
-
-    CHUNK_SIZE = 4096
-
-    def __init__(self, request, client_address, server):
-        self._file = None
-        self._srcid = 0
-        SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, request, client_address, server)
-
-    def log_request(self, code='-', size='-'):
-        pass
-
-    def do_GET(self):
-        """Serve a GET request."""
-        self._file = self.send_head()
-        if self._file:
-            self._srcid = gobject.io_add_watch(self.wfile, gobject.IO_OUT | gobject.IO_ERR, self._send_next_chunk)
-        else:
-            self._file.close()
-            self._cleanup()
-
-    def _send_next_chunk(self, source, condition):
-        if condition & gobject.IO_ERR:
-            self._cleanup()
-            return False
-        if not (condition & gobject.IO_OUT):
-            self._cleanup()
-            return False
-        data = self._file.read(self.CHUNK_SIZE)
-        count = os.write(self.wfile.fileno(), data)
-        if count != len(data) or len(data) != self.CHUNK_SIZE:
-            self._cleanup()
-            return False
-        return True
-
-    def _cleanup(self):
-        if self._file:
-            self._file.close()
-        if self._srcid > 0:
-            gobject.source_remove(self._srcid)
-            self._srcid = 0
-        if not self.wfile.closed:
-            self.wfile.flush()
-        self.wfile.close()
-        self.rfile.close()
-        
-    def finish(self):
-        """Close the sockets when we're done, not before"""
-        pass
-
-    def send_head(self):
-        """Common code for GET and HEAD commands.
-
-        This sends the response code and MIME headers.
-
-        Return value is either a file object (which has to be copied
-        to the outputfile by the caller unless the command was HEAD,
-        and must be closed by the caller under all circumstances), or
-        None, in which case the caller has nothing further to do.
-
-        ** [dcbw] modified to send Content-disposition filename too
-        """
-        path = self.translate_path(self.path)
-        f = None
-        if os.path.isdir(path):
-            for index in "index.html", "index.htm":
-                index = os.path.join(path, index)
-                if os.path.exists(index):
-                    path = index
-                    break
-            else:
-                return self.list_directory(path)
-        ctype = self.guess_type(path)
-        try:
-            # Always read in binary mode. Opening files in text mode may cause
-            # newline translations, making the actual size of the content
-            # transmitted *less* than the content-length!
-            f = open(path, 'rb')
-        except IOError:
-            self.send_error(404, "File not found")
-            return None
-        self.send_response(200)
-        self.send_header("Content-type", ctype)
-        self.send_header("Content-Length", str(os.fstat(f.fileno())[6]))
-        self.send_header("Content-Disposition", 'attachment; filename="%s"' % os.path.basename(path))
-        self.end_headers()
-        return f
-
-class GlibURLDownloader(gobject.GObject):
-    """Grabs a URL in chunks, returning to the mainloop after each chunk"""
-
-    __gsignals__ = {
-        'finished': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
-                         ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])),
-        'error':    (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
-                         ([gobject.TYPE_PYOBJECT]))
-    }
-
-    CHUNK_SIZE = 4096
-
-    def __init__(self, url, destdir=None):
-        self._url = url
-        if not destdir:
-            destdir = "/tmp"
-        self._destdir = destdir
-        self._srcid = 0
-        self._fname = None
-        self._outf = None
-        gobject.GObject.__init__(self)
-
-    def start(self):
-        self._info = urllib.urlopen(self._url)
-        self._suggested_fname = self._get_filename_from_headers(self._info.headers)
-        import tempfile
-        garbage, path = urllib.splittype(self._url)
-        garbage, path = urllib.splithost(path or "")
-        path, garbage = urllib.splitquery(path or "")
-        path, garbage = urllib.splitattr(path or "")
-        suffix = os.path.splitext(path)[1]
-        (self._outf, self._fname) = tempfile.mkstemp(suffix=suffix, dir=self._destdir)
-
-        fcntl.fcntl(self._info.fp.fileno(), fcntl.F_SETFD, os.O_NDELAY)
-        self._srcid = gobject.io_add_watch(self._info.fp.fileno(),
-                                           gobject.IO_IN | gobject.IO_ERR,
-                                           self._read_next_chunk)
-
-    def _get_filename_from_headers(self, headers):
-        if not headers.has_key("Content-Disposition"):
-            return None
-
-        ftag = "filename="
-        data = headers["Content-Disposition"]
-        fidx = data.find(ftag)
-        if fidx < 0:
-            return None
-        fname = data[fidx+len(ftag):]
-        if fname[0] == '"' or fname[0] == "'":
-            fname = fname[1:]
-        if fname[len(fname)-1] == '"' or fname[len(fname)-1] == "'":
-            fname = fname[:len(fname)-1]
-        return fname
-
-    def _read_next_chunk(self, source, condition):
-        if condition & gobject.IO_ERR:
-            self.cleanup()
-            os.remove(self._fname)
-            self.emit("error", "Error downloading file.")
-            return False
-        elif not (condition & gobject.IO_IN):
-            # shouldn't get here, but...
-            return True
-
-        try:
-            data = self._info.fp.read(self.CHUNK_SIZE)
-            count = os.write(self._outf, data)
-            if len(data) < self.CHUNK_SIZE:
-                self.cleanup()
-                self.emit("finished", self._fname, self._suggested_fname)
-                return False
-            if count < len(data):
-                self.cleanup()
-                self.emit("error", "Error writing to download file.")
-                return False
-        except Exception, err:
-            self.cleanup()
-            self.emit("error", "Error downloading file: %s" % err)
-            return False
-        return True
-
-    def cleanup(self):
-        if self._srcid > 0:
-            gobject.source_remove(self._srcid)
-            self._srcid = 0
-        del self._info
-        self._info = None
-        os.close(self._outf)
-        self._outf = None
-
-
-class GlibXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
-    """ GlibXMLRPCRequestHandler
-    
-    The stock SimpleXMLRPCRequestHandler and server don't allow any way to pass
-    the client's address and/or SSL certificate into the function that actually
-    _processes_ the request.  So we have to store it in a thread-indexed dict.
-    """
-
-    def do_POST(self):
-        _add_authinfo(self.client_address)
-        try:
-            SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.do_POST(self)
-        except socket.timeout:
-            pass
-        except socket.error, e:
-            print "Error (%s): socket error - '%s'" % (self.client_address, e)
-        except:
-            print "Error while processing POST:"
-            traceback.print_exc()
-        _del_authinfo()
-
-class GlibXMLRPCServer(GlibTCPServer, SimpleXMLRPCServer.SimpleXMLRPCDispatcher):
-    """GlibXMLRPCServer
-    
-    Use nonblocking sockets and handle the accept via glib rather than
-    blocking on accept().
-    """
-
-    def __init__(self, addr, requestHandler=GlibXMLRPCRequestHandler,
-                 logRequests=0, allow_none=False):
-        self.logRequests = logRequests
-        if sys.version_info[:3] >= (2, 5, 0):
-            SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding="utf-8")
-        else:
-            SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self)
-        GlibTCPServer.__init__(self, addr, requestHandler)
-
-    def _marshaled_dispatch(self, data, dispatch_method = None):
-        """Dispatches an XML-RPC method from marshalled (XML) data.
-
-        XML-RPC methods are dispatched from the marshalled (XML) data
-        using the _dispatch method and the result is returned as
-        marshalled data. For backwards compatibility, a dispatch
-        function can be provided as an argument (see comment in
-        SimpleXMLRPCRequestHandler.do_POST) but overriding the
-        existing method through subclassing is the prefered means
-        of changing method dispatch behavior.
-        """
-
-        params, method = xmlrpclib.loads(data)
-
-        # generate response
-        try:
-            if dispatch_method is not None:
-                response = dispatch_method(method, params)
-            else:
-                response = self._dispatch(method, params)
-            # wrap response in a singleton tuple
-            response = (response,)
-            response = xmlrpclib.dumps(response, methodresponse=1)
-        except xmlrpclib.Fault, fault:
-            response = xmlrpclib.dumps(fault)
-        except:
-            print "Exception while processing request:"
-            traceback.print_exc()
-
-            # report exception back to server
-            response = xmlrpclib.dumps(
-                xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value))
-                )
-
-        return response
-
-
-class GlibHTTP(httplib.HTTP):
-    """Subclass HTTP so we can return it's connection class' socket."""
-    def connect(self, host=None, port=None):
-        httplib.HTTP.connect(self, host, port)
-        self._conn.sock.setblocking(0)
-
-class GlibXMLRPCTransport(xmlrpclib.Transport):
-    """Integrate the request with the glib mainloop rather than blocking."""
-    ##
-    # Connect to server.
-    #
-    # @param host Target host.
-    # @return A connection handle.
-
-    def __init__(self, use_datetime=0):
-        if sys.version_info[:3] >= (2, 5, 0):
-            xmlrpclib.Transport.__init__(self, use_datetime)
-
-    def make_connection(self, host):
-        """Use our own connection object so we can get its socket."""
-        # create a HTTP connection object from a host descriptor
-        host, extra_headers, x509 = self.get_host_info(host)
-        return GlibHTTP(host)
-
-    ##
-    # Send a complete request, and parse the response.
-    #
-    # @param host Target host.
-    # @param handler Target PRC handler.
-    # @param request_body XML-RPC request body.
-    # @param verbose Debugging flag.
-    # @return Parsed response.
-
-    def start_request(self, host, handler, request_body, verbose=0, reply_handler=None, error_handler=None, user_data=None):
-        """Do the first half of the request by sending data to the remote
-        server.  The bottom half bits get run when the remote server's response
-        actually comes back."""
-        # issue XML-RPC request
-
-        h = self.make_connection(host)
-        if verbose:
-            h.set_debuglevel(1)
-
-        self.send_request(h, handler, request_body)
-        self.send_host(h, host)
-        self.send_user_agent(h)
-        self.send_content(h, request_body)
-
-        # Schedule a GIOWatch so we don't block waiting for the response
-        gobject.io_add_watch(h._conn.sock, gobject.IO_IN, self._finish_request,
-                h, host, handler, verbose, reply_handler, error_handler, user_data)
-
-    def _finish_request(self, source, condition, h, host, handler, verbose, reply_handler=None, error_handler=None, user_data=None):
-        """Parse and return response when the remote server actually returns it."""
-        if not (condition & gobject.IO_IN):
-            return True
-
-        try:
-            errcode, errmsg, headers = h.getreply()
-        except socket.error, err:
-            if err[0] != 104:
-                raise socket.error(err)
-            else:
-                if error_handler:
-                    gobject.idle_add(error_handler, err, user_data)
-                return False
-                
-        if errcode != 200:
-            raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers)
-        self.verbose = verbose        
-        response = self._parse_response(h.getfile(), h._conn.sock)
-        if reply_handler:
-            # Coerce to a list so we can append user data
-            response = response[0]
-            if not isinstance(response, list):
-                response = [response]
-            response.append(user_data)
-            gobject.idle_add(reply_handler, *response)
-        return False
-
-class _Method:
-    """Right, so python people thought it would be funny to make this
-    class private to xmlrpclib.py..."""
-    # some magic to bind an XML-RPC method to an RPC server.
-    # supports "nested" methods (e.g. examples.getStateName)
-    def __init__(self, send, name):
-        self.__send = send
-        self.__name = name
-    def __getattr__(self, name):
-        return _Method(self.__send, "%s.%s" % (self.__name, name))
-    def __call__(self, *args, **kwargs):
-        return self.__send(self.__name, *args, **kwargs)
-
-
-class GlibServerProxy(xmlrpclib.ServerProxy):
-    """Subclass xmlrpclib.ServerProxy so we can run the XML-RPC request
-    in two parts, integrated with the glib mainloop, such that we don't
-    block anywhere.
-    
-    Using this object is somewhat special; it requires more arguments to each
-    XML-RPC request call than the normal xmlrpclib.ServerProxy object:
-    
-    client = GlibServerProxy("http://127.0.0.1:8888")
-    user_data = "bar"
-    xmlrpc_arg1 = "test"
-    xmlrpc_arg2 = "foo"
-    client.test(xmlrpc_test_cb, user_data, xmlrpc_arg1, xmlrpc_arg2)
-
-    Here, 'xmlrpc_test_cb' is the callback function, which has the following
-    signature:
-    
-    def xmlrpc_test_cb(result_status, response, user_data=None):
-        ...
-    """
-    def __init__(self, uri, encoding=None, verbose=0, allow_none=0):
-        self._transport = GlibXMLRPCTransport()
-        self._encoding = encoding
-        self._verbose = verbose
-        self._allow_none = allow_none
-        xmlrpclib.ServerProxy.__init__(self, uri, self._transport, encoding, verbose, allow_none)
-
-        # get the url
-        import urllib
-        urltype, uri = urllib.splittype(uri)
-        if urltype not in ("http", "https"):
-            raise IOError, "unsupported XML-RPC protocol"
-        self._host, self._handler = urllib.splithost(uri)
-        if not self._handler:
-            self._handler = "/RPC2"
-
-    def __request(self, methodname, *args, **kwargs):
-        """Call the method on the remote server.  We just start the request here
-        and the transport itself takes care of scheduling the response callback
-        when the remote server returns the response.  We don't want to block anywhere."""
-
-        request = xmlrpclib.dumps(args, methodname, encoding=self._encoding,
-                        allow_none=self._allow_none)
-
-        reply_hdl = kwargs.get("reply_handler")
-        err_hdl = kwargs.get("error_handler")
-        udata = kwargs.get("user_data")
-        try:
-            response = self._transport.start_request(
-                self._host,
-                self._handler,
-                request,
-                verbose=self._verbose,
-                reply_handler=reply_hdl,
-                error_handler=err_hdl,
-                user_data=udata
-                )
-        except socket.error, exc:
-            if err_hdl:
-                gobject.idle_add(err_hdl, exc, udata)
-
-    def __getattr__(self, name):
-        # magic method dispatcher
-        return _Method(self.__request, name)
-
-
-class GroupServer(object):
-
-    _MAX_MSG_SIZE = 500
-
-    def __init__(self, address, port, data_cb):
-        self._address = address
-        self._port = port
-        self._data_cb = data_cb
-
-        self._setup_listener()
-
-    def _setup_listener(self):
-        # Listener socket
-        self._listen_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-
-        # Set some options to make it multicast-friendly
-        self._listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-        self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, 20)
-        self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1)
-
-    def start(self):
-        # Set some more multicast options
-        self._listen_sock.bind(('', self._port))
-        self._listen_sock.settimeout(2)
-        intf = socket.gethostbyname(socket.gethostname())
-        self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(intf) + socket.inet_aton('0.0.0.0'))
-        self._listen_sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(self._address) + socket.inet_aton('0.0.0.0'))
-
-        # Watch the listener socket for data
-        gobject.io_add_watch(self._listen_sock, gobject.IO_IN, self._handle_incoming_data)
-
-    def _handle_incoming_data(self, source, condition):
-        if not (condition & gobject.IO_IN):
-            return True
-        msg = {}
-        msg['data'], (msg['addr'], msg['port']) = source.recvfrom(self._MAX_MSG_SIZE)
-        if self._data_cb:
-            self._data_cb(msg)
-        return True
-
-class GroupClient(object):
-
-    _MAX_MSG_SIZE = 500
-
-    def __init__(self, address, port):
-        self._address = address
-        self._port = port
-
-        self._send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-        # Make the socket multicast-aware, and set TTL.
-        self._send_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 20) # Change TTL (=20) to suit
-
-    def send_msg(self, data):
-        self._send_sock.sendto(data, (self._address, self._port))
-
-
-class Test(object):
-    def test(self, arg1, arg2):
-        print "Request got %s, %s" % (arg1, arg2)
-        return "success", "bork"
-
-def xmlrpc_success_cb(response, resp2, loop):
-    print "Response was %s %s" % (response, resp2)
-    loop.quit()
-
-def xmlrpc_error_cb(err, loop):
-    print "Error: %s" % err
-    loop.quit()
-
-def xmlrpc_test(loop):
-    client = GlibServerProxy("http://127.0.0.1:8888")
-    client.test("bar", "baz",
-                reply_handler=xmlrpc_success_cb,
-                error_handler=xmlrpc_error_cb,
-                user_data=loop)
-
-def main():
-    loop = gobject.MainLoop()
-    server = GlibXMLRPCServer(("", 8888))
-    inst = Test()
-    server.register_instance(inst)
-    gobject.idle_add(xmlrpc_test, loop)
-    try:
-        loop.run()
-    except KeyboardInterrupt:
-        print 'Ctrl+C pressed, exiting...'
-    print "Done."
-
-if __name__ == "__main__":
-    main()
diff --git a/tests/test-datastore.py b/tests/test-datastore.py
deleted file mode 100755
index d3e84781..00000000
--- a/tests/test-datastore.py
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2006, Red Hat, Inc.
-#
-# 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 2 of the License, or
-# (at your option) 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, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-import unittest
-from sugar.datastore import datastore
-from sugar import util
-import dbus
-
-class NotFoundError(dbus.DBusException): pass
-
-_ds = datastore.get_instance()
-
-class DataStoreTestCase(unittest.TestCase):
-    _TEST_DATA = "adsfkjadsfadskjasdkjf"
-    _TEST_PROPS = {'foo': 1, 'bar': 'baz'}
-    def _create_test_object(self, activity_id=None):
-        obj = _ds.create(self._TEST_DATA, self._TEST_PROPS, activity_id=activity_id)
-        self.assert_(obj)
-        return obj
-
-    def testObjectCreate(self):
-        obj = self._create_test_object()
-        self.assert_(obj.uid())
-        _ds.delete(obj)
-
-    def testObjectCreateWithActivityId(self):
-        # Try known good create
-        act_id = util.unique_id('afdkjakjddasf')
-        obj = self._create_test_object(act_id)
-        self.assert_(obj.uid())
-        _ds.delete(obj)
-
-    def testObjectCreateWithBadActivityId(self):
-        # try malformed activity id
-        try:
-            uid = self._create_test_object("adfadf")
-        except ValueError:
-            pass
-        else:
-            self.fail("Expected ValueError")
-
-    def testObjectGetActivityObject(self):
-        # create a new object
-        act_id = util.unique_id('afdkjakjddasf')
-        obj = self._create_test_object(act_id)
-        self.assert_(obj.uid())
-        obj2 = _ds.get(activity_id=act_id)
-        self.assert_(obj2)
-        _ds.delete(obj)
-
-    def testObjectGet(self):
-        # create a new object
-        obj = self._create_test_object()
-        self.assert_(obj.uid())
-        obj2 = _ds.get(obj.uid())
-        self.assert_(obj2)
-        _ds.delete(obj)
-
-    def testObjectDelete(self):
-        obj = self._create_test_object()
-        uid = obj.uid()
-        _ds.delete(obj)
-        try:
-            _ds.get(uid)
-        except dbus.DBusException, e:
-            if str(e).find("NotFoundError:") < 0:
-                self.fail("Expected a NotFoundError")
-        else:
-            self.fail("Expected a NotFoundError.")
-
-    def testObjectFind(self):
-        obj = self._create_test_object()
-        found = _ds.find(self._TEST_PROPS)
-        self.assert_(obj in found)
-        _ds.delete(obj)
-
-    def testObjectGetData(self):
-        obj = self._create_test_object()
-        data = obj.get_data()
-        self.assert_(data == self._TEST_DATA)
-        _ds.delete(obj)
-
-    _OTHER_DATA = "532532532532532;lkjkjkjfsakjfakjfdsakj"
-    def testObjectSetData(self):
-        obj = self._create_test_object()
-        data = obj.get_data()
-        self.assert_(data == self._TEST_DATA)
-        obj.set_data(self._OTHER_DATA)
-        data = obj.get_data()
-        self.assert_(data == self._OTHER_DATA)
-        _ds.delete(obj)
-
-    def testObjectGetProperties(self):
-        obj = self._create_test_object()
-        props = obj.get_properties()
-        for (key, value) in props.items():
-            if key == 'uid':
-                continue
-            self.assert_(key in self._TEST_PROPS)
-            self.assert_(str(self._TEST_PROPS[key]) == str(value))
-        for (key, value) in self._TEST_PROPS.items():
-            self.assert_(key in props)
-            self.assert_(str(props[key]) == str(value))
-        _ds.delete(obj)
-
-def main():
-    dsTestSuite = unittest.TestSuite()
-    dsTestSuite.addTest(DataStoreTestCase('testObjectCreate'))
-    dsTestSuite.addTest(DataStoreTestCase('testObjectCreateWithActivityId'))
-    dsTestSuite.addTest(DataStoreTestCase('testObjectCreateWithBadActivityId'))
-    dsTestSuite.addTest(DataStoreTestCase('testObjectGet'))
-    dsTestSuite.addTest(DataStoreTestCase('testObjectGetActivityObject'))
-    dsTestSuite.addTest(DataStoreTestCase('testObjectDelete'))
-    dsTestSuite.addTest(DataStoreTestCase('testObjectFind'))
-    dsTestSuite.addTest(DataStoreTestCase('testObjectGetData'))
-    dsTestSuite.addTest(DataStoreTestCase('testObjectSetData'))
-    dsTestSuite.addTest(DataStoreTestCase('testObjectGetProperties'))
-    unittest.TextTestRunner(verbosity=2).run(dsTestSuite)
-
-
-if __name__ == "__main__":
-    main()
diff --git a/tests/test-datastore2.py b/tests/test-datastore2.py
deleted file mode 100755
index e8747587..00000000
--- a/tests/test-datastore2.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2006, One Laptop Per Child
-#
-# 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 2 of the License, or
-# (at your option) 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, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-from sugar.datastore import datastore
-from sugar.datastore.datastore import Text
-
-# Write a text object
-metadata = { 'date'    : 1000900000,
-             'title'   : 'Thai history',
-             'preview' : 'The subject of thai history...',
-             'icon-color' : '#C2B00C,#785C78',
-           }
-text = Text(metadata)
-f = open("/tmp/hello.txt", 'w')
-try:
-    f.write('The subject of thai history blah blah blah, blah blah blah and blah.')
-finally:
-    f.close()
-text.set_file_path(f.name)
-handle = datastore.write(text)
-
-# Read back that object
-thing = datastore.read(handle)
-metadata = thing.get_metadata()
-print metadata
-
-file_path = thing.get_file_path()
-f = open(file_path)
-try:
-    print f.read()
-finally:
-    f.close()
-
-# Retrieve all the objects
-objects = datastore.find('')
-for obj in objects:
-    print obj.get_metadata()['title']
diff --git a/tests/test-browser.py b/tests/test-mime.py
similarity index 59%
rename from tests/test-browser.py
rename to tests/test-mime.py
index ce9a3cf3..a7f185e9 100755
--- a/tests/test-browser.py
+++ b/tests/test-mime.py
@@ -16,37 +16,15 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-import os
+import sys
 
-import pygtk
-pygtk.require('2.0')
-import gtk
-import gobject
+from sugar import objects
 
-import sugar.browser
+print 'MIME type for test.pdf (from extension):'
+print objects.mime.get_from_file_name('test.pdf')
 
-def _print_document():
-    #print browser.document
-    pass
+print ''
 
-def _quit(window):
-    sugar.browser.shutdown()
-    gtk.main_quit()
-
-# Main window
-window = gtk.Window()
-window.connect("destroy", _quit)
-
-sugar.browser.startup(os.path.expanduser('~/.sugar-browser-test'), 'test')
-
-browser = sugar.browser.Browser()
-window.add(browser)
-browser.show()
-
-browser.load_url('about:blank')
-
-gobject.idle_add(_print_document)
-
-window.show()
-
-gtk.main()
+if len(sys.argv) > 1:
+    print 'MIME type for file %s:' % sys.argv[1]
+    print objects.mime.get_for_file(sys.argv[1])