Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar
This commit is contained in:
		
						commit
						677eb1629c
					
				| @ -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 | ||||
|  | ||||
							
								
								
									
										22
									
								
								autogen.sh
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								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 "$@" | ||||
|  | ||||
| @ -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; | ||||
| } | ||||
| @ -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__
 | ||||
| @ -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; | ||||
| } | ||||
| @ -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 */ | ||||
| @ -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; | ||||
| } | ||||
| @ -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 */ | ||||
| @ -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); | ||||
| } | ||||
| @ -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__
 | ||||
| @ -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; | ||||
| } | ||||
| @ -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__
 | ||||
| @ -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(×tamp, 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; | ||||
| } | ||||
| @ -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__
 | ||||
| @ -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 | ||||
| @ -1 +0,0 @@ | ||||
| SUBDIRS = browserhelper sessionstore | ||||
							
								
								
									
										4
									
								
								browser/components/browserhelper/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								browser/components/browserhelper/.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,4 +0,0 @@ | ||||
| nsIBrowserHelper.h | ||||
| nsIBrowserHelper.xpt | ||||
| stamp-nsIBrowserHelper.h | ||||
| stamp-nsIBrowserHelper.xpt | ||||
| @ -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 | ||||
| @ -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; | ||||
| } | ||||
| @ -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);  | ||||
| }; | ||||
							
								
								
									
										4
									
								
								browser/components/sessionstore/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								browser/components/sessionstore/.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,4 +0,0 @@ | ||||
| nsISessionStore.h | ||||
| nsISessionStore.xpt | ||||
| stamp-nsISessionStore.h | ||||
| stamp-nsISessionStore.xpt | ||||
| @ -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 | ||||
| @ -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); | ||||
| }; | ||||
| @ -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; | ||||
| } | ||||
| @ -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); | ||||
| } | ||||
| @ -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 | ||||
| @ -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); | ||||
| } | ||||
| @ -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 | ||||
| @ -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); | ||||
| } | ||||
| @ -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__ */ | ||||
| @ -1,4 +0,0 @@ | ||||
| VOID:OBJECT,STRING,LONG,LONG | ||||
| VOID:OBJECT,LONG | ||||
| VOID:OBJECT | ||||
| BOOLEAN:BOXED | ||||
							
								
								
									
										52
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								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 | ||||
|  | ||||
| @ -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	\
 | ||||
|  | ||||
| @ -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); | ||||
| @ -1,3 +0,0 @@ | ||||
| application/x-squeak-project	pr | ||||
| application/x-abiword		abw | ||||
| application/vnd.olpc-x-sugar	xo | ||||
							
								
								
									
										14
									
								
								lib/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								lib/Makefile.am
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||
| @ -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 | ||||
| 
 | ||||
							
								
								
									
										378
									
								
								lib/xdgmime/ChangeLog
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										378
									
								
								lib/xdgmime/ChangeLog
									
									
									
									
									
										Normal file
									
								
							| @ -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. | ||||
| 
 | ||||
							
								
								
									
										19
									
								
								lib/xdgmime/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								lib/xdgmime/Makefile.am
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||
							
								
								
									
										850
									
								
								lib/xdgmime/xdgmime.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										850
									
								
								lib/xdgmime/xdgmime.c
									
									
									
									
									
										Normal file
									
								
							| @ -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; | ||||
| 	} | ||||
|     } | ||||
| } | ||||
							
								
								
									
										111
									
								
								lib/xdgmime/xdgmime.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								lib/xdgmime/xdgmime.h
									
									
									
									
									
										Normal file
									
								
							| @ -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__ */ | ||||
							
								
								
									
										184
									
								
								lib/xdgmime/xdgmimealias.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								lib/xdgmime/xdgmimealias.c
									
									
									
									
									
										Normal file
									
								
							| @ -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); | ||||
| 	} | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										50
									
								
								lib/xdgmime/xdgmimealias.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								lib/xdgmime/xdgmimealias.h
									
									
									
									
									
										Normal file
									
								
							| @ -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__ */ | ||||
							
								
								
									
										895
									
								
								lib/xdgmime/xdgmimecache.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										895
									
								
								lib/xdgmime/xdgmimecache.c
									
									
									
									
									
										Normal file
									
								
							| @ -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; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										63
									
								
								lib/xdgmime/xdgmimecache.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								lib/xdgmime/xdgmimecache.h
									
									
									
									
									
										Normal file
									
								
							| @ -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__ */ | ||||
							
								
								
									
										547
									
								
								lib/xdgmime/xdgmimeglob.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										547
									
								
								lib/xdgmime/xdgmimeglob.c
									
									
									
									
									
										Normal file
									
								
							| @ -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); | ||||
| } | ||||
							
								
								
									
										67
									
								
								lib/xdgmime/xdgmimeglob.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								lib/xdgmime/xdgmimeglob.h
									
									
									
									
									
										Normal file
									
								
							| @ -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__ */ | ||||
							
								
								
									
										154
									
								
								lib/xdgmime/xdgmimeint.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								lib/xdgmime/xdgmimeint.c
									
									
									
									
									
										Normal file
									
								
							| @ -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; | ||||
| } | ||||
							
								
								
									
										73
									
								
								lib/xdgmime/xdgmimeint.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								lib/xdgmime/xdgmimeint.h
									
									
									
									
									
										Normal file
									
								
							| @ -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__ */ | ||||
							
								
								
									
										807
									
								
								lib/xdgmime/xdgmimemagic.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										807
									
								
								lib/xdgmime/xdgmimemagic.c
									
									
									
									
									
										Normal file
									
								
							| @ -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); | ||||
| } | ||||
							
								
								
									
										56
									
								
								lib/xdgmime/xdgmimemagic.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								lib/xdgmime/xdgmimemagic.h
									
									
									
									
									
										Normal file
									
								
							| @ -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__ */ | ||||
							
								
								
									
										219
									
								
								lib/xdgmime/xdgmimeparent.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								lib/xdgmime/xdgmimeparent.c
									
									
									
									
									
										Normal file
									
								
							| @ -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); | ||||
| 	} | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										50
									
								
								lib/xdgmime/xdgmimeparent.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								lib/xdgmime/xdgmimeparent.h
									
									
									
									
									
										Normal file
									
								
							| @ -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__ */ | ||||
							
								
								
									
										2
									
								
								shell/extensions/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								shell/extensions/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| stamp-sugar-shell-marshal.* | ||||
| sugar-shell-marshal.* | ||||
| @ -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 | ||||
| 
 | ||||
|  | ||||
| @ -1 +0,0 @@ | ||||
| timestamp | ||||
| @ -1 +0,0 @@ | ||||
| timestamp | ||||
| @ -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__ */ | ||||
| 
 | ||||
| @ -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__ */ | ||||
| 
 | ||||
| @ -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 | ||||
| 
 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
							
								
								
									
										152
									
								
								sugar/_sugarext.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								sugar/_sugarext.c
									
									
									
									
									
										Normal file
									
								
							| @ -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)); | ||||
| } | ||||
							
								
								
									
										27
									
								
								sugar/_sugarext.defs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								sugar/_sugarext.defs
									
									
									
									
									
										Normal file
									
								
							| @ -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") | ||||
|   ) | ||||
| ) | ||||
							
								
								
									
										40
									
								
								sugar/_sugarext.override
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								sugar/_sugarext.override
									
									
									
									
									
										Normal file
									
								
							| @ -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; | ||||
| } | ||||
| %% | ||||
							
								
								
									
										27
									
								
								sugar/_sugarextmodule.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								sugar/_sugarextmodule.c
									
									
									
									
									
										Normal file
									
								
							| @ -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"); | ||||
|     } | ||||
| } | ||||
| @ -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, | ||||
|  | ||||
| @ -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  | ||||
|          | ||||
|  | ||||
| @ -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 | ||||
| @ -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) | ||||
| @ -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") | ||||
| @ -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; | ||||
| } | ||||
| %% | ||||
| @ -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"); | ||||
|     } | ||||
| } | ||||
| @ -1 +0,0 @@ | ||||
| 
 | ||||
| @ -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") | ||||
|   ) | ||||
| ) | ||||
| @ -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; | ||||
| } | ||||
| @ -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); | ||||
| } | ||||
| @ -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); | ||||
| @ -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 | ||||
| 
 | ||||
|  | ||||
| @ -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 | ||||
| 
 | ||||
|  | ||||
| @ -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) | ||||
| 
 | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -1,5 +1,4 @@ | ||||
| sugardir = $(pythondir)/sugar/objects | ||||
| sugar_PYTHON =		\
 | ||||
| 	__init__.py	\
 | ||||
| 	typeregistry.py		\
 | ||||
| 	typeinfo.py | ||||
| 	mime.py | ||||
|  | ||||
							
								
								
									
										1
									
								
								sugar/objects/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								sugar/objects/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| from sugar.objects import mime | ||||
							
								
								
									
										11
									
								
								sugar/objects/mime.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								sugar/objects/mime.py
									
									
									
									
									
										Normal file
									
								
							| @ -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) | ||||
| @ -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'] | ||||
| @ -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() | ||||
| @ -1,8 +0,0 @@ | ||||
| sugardir = $(pythondir)/sugar/p2p | ||||
| sugar_PYTHON =			\
 | ||||
| 	__init__.py		\
 | ||||
| 	NotificationListener.py	\
 | ||||
| 	Notifier.py		\
 | ||||
| 	Stream.py		\
 | ||||
| 	MostlyReliablePipe.py	\
 | ||||
| 	network.py | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -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) | ||||
| @ -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) | ||||
| @ -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 | ||||
| @ -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() | ||||
| @ -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() | ||||
| @ -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'] | ||||
| @ -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]) | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Simon McVittie
						Simon McVittie