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 | SUBDIRS = bin data lib po shell sugar services | ||||||
| 
 |  | ||||||
| ACLOCAL_AMFLAGS = -I m4 |  | ||||||
| 
 | 
 | ||||||
| bin_SCRIPTS = 			\
 | bin_SCRIPTS = 			\
 | ||||||
| 	sugar-emulator | 	sugar-emulator | ||||||
|  | |||||||
							
								
								
									
										22
									
								
								autogen.sh
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								autogen.sh
									
									
									
									
									
								
							| @ -1,20 +1,6 @@ | |||||||
| #!/bin/sh | #!/bin/sh | ||||||
| # Run this to generate all the initial makefiles, etc. | export ACLOCAL="aclocal -I m4" | ||||||
| 
 | 
 | ||||||
| srcdir=`dirname $0` | autoreconf -i | ||||||
| test -z "$srcdir" && srcdir=. | intltoolize | ||||||
| 
 | ./configure "$@" | ||||||
| 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 |  | ||||||
|  | |||||||
| @ -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]) | AC_PREREQ([2.59]) | ||||||
| 
 | 
 | ||||||
| GNOME_COMMON_INIT |  | ||||||
| GNOME_COMPILE_WARNINGS |  | ||||||
| 
 |  | ||||||
| AC_CONFIG_MACRO_DIR([m4]) | AC_CONFIG_MACRO_DIR([m4]) | ||||||
| AC_CONFIG_HEADERS([config.h]) |  | ||||||
| AC_CONFIG_SRCDIR([configure.ac]) | AC_CONFIG_SRCDIR([configure.ac]) | ||||||
| 
 | 
 | ||||||
| AM_INIT_AUTOMAKE([1.9 foreign dist-bzip2 no-dist-gzip]) | AM_INIT_AUTOMAKE([1.9 foreign dist-bzip2 no-dist-gzip]) | ||||||
| 
 | 
 | ||||||
| AM_MAINTAINER_MODE |  | ||||||
| 
 |  | ||||||
| AC_DISABLE_STATIC | AC_DISABLE_STATIC | ||||||
| AC_PROG_LIBTOOL | 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) | AC_PATH_PROG(PYGTK_CODEGEN, pygtk-codegen-2.0, no) | ||||||
| 
 | 
 | ||||||
| PKG_CHECK_MODULES(PYGTK, pygtk-2.0) | PKG_CHECK_MODULES(SHELL, pygtk-2.0 gtk+-2.0 gstreamer-0.10 gstreamer-plugins-base-0.10) | ||||||
| 
 |  | ||||||
| PKG_CHECK_MODULES(PYCAIRO, pycairo) |  | ||||||
| 
 | 
 | ||||||
| PKG_CHECK_MODULES(LIB, gtk+-2.0) | PKG_CHECK_MODULES(LIB, gtk+-2.0) | ||||||
| 
 | PKG_CHECK_MODULES(LIB_BINDINGS, pygtk-2.0) | ||||||
| PKG_CHECK_MODULES(SHELL, gtk+-2.0 gstreamer-0.10 gstreamer-plugins-base-0.10) |  | ||||||
| 
 | 
 | ||||||
| PYGTK_DEFSDIR=`$PKG_CONFIG --variable=defsdir pygtk-2.0` | PYGTK_DEFSDIR=`$PKG_CONFIG --variable=defsdir pygtk-2.0` | ||||||
| AC_SUBST(PYGTK_DEFSDIR) | 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 | # Setup GETTEXT | ||||||
| # | # | ||||||
| ALL_LINGUAS="it ha ig yo" | ALL_LINGUAS="it ha ig yo" | ||||||
| @ -79,10 +40,8 @@ AC_OUTPUT([ | |||||||
| Makefile | Makefile | ||||||
| bin/Makefile | bin/Makefile | ||||||
| data/Makefile | data/Makefile | ||||||
| browser/Makefile | lib/Makefile | ||||||
| browser/components/Makefile | lib/xdgmime/Makefile | ||||||
| browser/components/sessionstore/Makefile |  | ||||||
| browser/components/browserhelper/Makefile |  | ||||||
| services/Makefile | services/Makefile | ||||||
| services/presence/Makefile | services/presence/Makefile | ||||||
| services/clipboard/Makefile | services/clipboard/Makefile | ||||||
| @ -113,10 +72,9 @@ services/console/interface/logviewer/Makefile | |||||||
| services/console/interface/terminal/Makefile | services/console/interface/terminal/Makefile | ||||||
| sugar/Makefile | sugar/Makefile | ||||||
| sugar/activity/Makefile | sugar/activity/Makefile | ||||||
| sugar/browser/Makefile |  | ||||||
| sugar/clipboard/Makefile | sugar/clipboard/Makefile | ||||||
| sugar/graphics/Makefile | sugar/graphics/Makefile | ||||||
| sugar/p2p/Makefile | sugar/objects/Makefile | ||||||
| sugar/presence/Makefile | sugar/presence/Makefile | ||||||
| sugar/datastore/Makefile | sugar/datastore/Makefile | ||||||
| po/Makefile.in | po/Makefile.in | ||||||
|  | |||||||
| @ -8,9 +8,7 @@ sugar-xo.gtkrc: gtkrc.em | |||||||
| 
 | 
 | ||||||
| sugardir = $(pkgdatadir)/data | sugardir = $(pkgdatadir)/data | ||||||
| sugar_DATA =		\
 | sugar_DATA =		\
 | ||||||
| 	$(GTKRC_FILES)	\
 | 	$(GTKRC_FILES) | ||||||
| 	gecko-prefs.js	\
 |  | ||||||
| 	mime.types |  | ||||||
| 
 | 
 | ||||||
| GTKRC_FILES =		\
 | GTKRC_FILES =		\
 | ||||||
| 	sugar.gtkrc	\
 | 	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__ | #ifndef __SUGAR_ADDRESS_ENTRY_H__ | ||||||
| #define __SUGAR_ADDRESS_ENTRY_H__ | #define __SUGAR_ADDRESS_ENTRY_H__ | ||||||
| 
 | 
 | ||||||
| #include <glib-object.h> | #include <gtk/gtkentry.h> | ||||||
| 
 | 
 | ||||||
| G_BEGIN_DECLS | 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_LDFLAGS = -module -avoid-version | ||||||
| 
 | 
 | ||||||
| _extensions_la_CFLAGS =				\
 | _extensions_la_CFLAGS =				\
 | ||||||
| 	$(WARN_CFLAGS)				\
 |  | ||||||
| 	$(PYTHON_INCLUDES)			\
 | 	$(PYTHON_INCLUDES)			\
 | ||||||
| 	$(PYGTK_CFLAGS)				\
 |  | ||||||
| 	$(SHELL_CFLAGS)				\
 | 	$(SHELL_CFLAGS)				\
 | ||||||
| 	-I$(top_srcdir)/shell/extensions | 	-I$(top_srcdir)/shell/extensions | ||||||
| 
 | 
 | ||||||
| _extensions_la_LIBADD = 	\
 | _extensions_la_LIBADD = 	\
 | ||||||
| 	$(SHELL_LIBS) 		\
 | 	$(SHELL_LIBS) 		\
 | ||||||
| 	$(PYCAIRO_LIBS)		\
 |  | ||||||
| 	-lgstinterfaces-0.10	\
 | 	-lgstinterfaces-0.10	\
 | ||||||
| 	-lgstaudio-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_NAME = "org.laptop.Activity" | ||||||
| _SERVICE_PATH = "/org/laptop/Activity" | _SERVICE_PATH = "/org/laptop/Activity" | ||||||
|  | _SERVICE_INTERFACE = "org.laptop.Activity" | ||||||
| 
 | 
 | ||||||
| class HomeModel(gobject.GObject): | class HomeModel(gobject.GObject): | ||||||
|     """Model of the "Home" view (activity management) |     """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('window-closed', self._window_closed_cb) | ||||||
|         screen.connect('active-window-changed', |         screen.connect('active-window-changed', | ||||||
|                        self._active_window_changed_cb) |                        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): |     def get_current_activity(self): | ||||||
|         return self._current_activity |         return self._current_activity | ||||||
| @ -103,9 +110,31 @@ class HomeModel(gobject.GObject): | |||||||
|             self.emit('active-activity-changed', None) |             self.emit('active-activity-changed', None) | ||||||
|             self._notify_activity_activation(self._current_activity, 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): |     def _get_activity_by_xid(self, xid): | ||||||
|         for act in self._activities.values(): |         for act in self._activities.values(): | ||||||
|             if act.get_xid() == xid: |             if act.get_launched() and act.get_xid() == xid: | ||||||
|                 return act |                 return act | ||||||
|         return None |         return None | ||||||
| 
 | 
 | ||||||
| @ -168,8 +197,11 @@ class HomeModel(gobject.GObject): | |||||||
|         bus = dbus.SessionBus() |         bus = dbus.SessionBus() | ||||||
|         xid = window.get_xid() |         xid = window.get_xid() | ||||||
|         try: |         try: | ||||||
|             service = bus.get_object(_SERVICE_NAME + '%d' % xid, |             service = dbus.Interface( | ||||||
|                                      _SERVICE_PATH + "/%s" % xid) |                 bus.get_object(_SERVICE_NAME + '%d' % xid, | ||||||
|  |                                _SERVICE_PATH + "/%s" % xid), | ||||||
|  |                 _SERVICE_INTERFACE) | ||||||
|  |              | ||||||
|         except dbus.DBusException: |         except dbus.DBusException: | ||||||
|             service = None |             service = None | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| SUBDIRS = activity browser clipboard graphics p2p presence datastore | SUBDIRS = activity clipboard graphics objects presence datastore | ||||||
| 
 | 
 | ||||||
| sugardir = $(pythondir)/sugar | sugardir = $(pythondir)/sugar | ||||||
| sugar_PYTHON =		\
 | sugar_PYTHON =		\
 | ||||||
| @ -9,3 +9,40 @@ sugar_PYTHON =		\ | |||||||
|         ltihooks.py	\
 |         ltihooks.py	\
 | ||||||
| 	profile.py	\
 | 	profile.py	\
 | ||||||
| 	util.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_SERVICE_PATH = "/org/laptop/Activity" | ||||||
| _ACTIVITY_INTERFACE = "org.laptop.Activity" | _ACTIVITY_INTERFACE = "org.laptop.Activity" | ||||||
| 
 | 
 | ||||||
|  | _ACTIVITY_FACTORY_INTERFACE = "org.laptop.ActivityFactory" | ||||||
|  | 
 | ||||||
| def create_activity_id(): | def create_activity_id(): | ||||||
|     """Generate a new, unique ID for this activity""" |     """Generate a new, unique ID for this activity""" | ||||||
|     pservice = presenceservice.get_instance() |     pservice = presenceservice.get_instance() | ||||||
| @ -103,7 +105,7 @@ class ActivityCreationHandler(gobject.GObject): | |||||||
| 
 | 
 | ||||||
|         bus = dbus.SessionBus() |         bus = dbus.SessionBus() | ||||||
|         proxy_obj = bus.get_object(service_name, bundle.get_object_path(), follow_name_owner_changes=True) |         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(), |         factory.create(self._activity_handle.get_dict(), | ||||||
|                        reply_handler=self._reply_handler, |                        reply_handler=self._reply_handler, | ||||||
|  | |||||||
| @ -34,6 +34,8 @@ from sugar import logger | |||||||
| gobject.threads_init() | gobject.threads_init() | ||||||
| dbus.glib.threads_init() | dbus.glib.threads_init() | ||||||
| 
 | 
 | ||||||
|  | _ACTIVITY_FACTORY_INTERFACE = "org.laptop.ActivityFactory" | ||||||
|  | 
 | ||||||
| class ActivityFactoryService(dbus.service.Object): | class ActivityFactoryService(dbus.service.Object): | ||||||
|     """D-Bus service that creates instances of Python activities |     """D-Bus service that creates instances of Python activities | ||||||
|      |      | ||||||
| @ -92,7 +94,7 @@ class ActivityFactoryService(dbus.service.Object): | |||||||
|         object_path = '/' + service_name.replace('.', '/') |         object_path = '/' + service_name.replace('.', '/') | ||||||
|         dbus.service.Object.__init__(self, bus_name, object_path) |         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): |     def create(self, handle): | ||||||
|         """Create a new instance of this activity  |         """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) |         gobject.GObject.__init__(self) | ||||||
|         self.object_id = object_id |         self.object_id = object_id | ||||||
|         self._metadata = metadata |         self._metadata = metadata | ||||||
| @ -43,6 +43,8 @@ class DSObject(gobject.GObject): | |||||||
|         del self.metadata[key] |         del self.metadata[key] | ||||||
| 
 | 
 | ||||||
|     def get_metadata(self): |     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 |         return self._metadata | ||||||
|      |      | ||||||
|     def set_metadata(self, metadata): |     def set_metadata(self, metadata): | ||||||
| @ -53,6 +55,8 @@ class DSObject(gobject.GObject): | |||||||
|     metadata = property(get_metadata, set_metadata) |     metadata = property(get_metadata, set_metadata) | ||||||
| 
 | 
 | ||||||
|     def get_file_path(self): |     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 |         return self._file_path | ||||||
|      |      | ||||||
|     def set_file_path(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 |         # TODO: register the object for updates | ||||||
|     logging.debug('Written object %s to the datastore.' % ds_object.object_id) |     logging.debug('Written object %s to the datastore.' % ds_object.object_id) | ||||||
| 
 | 
 | ||||||
| def find(query, reply_handler=None, error_handler=None): | def find(query, sorting=None, limit=None, offset=None, reply_handler=None, | ||||||
|     object_ids = dbus_helpers.find(query, reply_handler, error_handler) |          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 = [] |     objects = [] | ||||||
|     for object_id in object_ids: |     for props in props_list: | ||||||
|         objects.append(get(object_id)) |         if props.has_key('filename') and props['filename']: | ||||||
|     return objects |             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 gobject | ||||||
| import gtk | import gtk | ||||||
| 
 | 
 | ||||||
|  | from sugar.graphics import units | ||||||
|  | 
 | ||||||
| class ComboBox(gtk.ComboBox): | class ComboBox(gtk.ComboBox): | ||||||
|     __gtype_name__ = 'SugarComboBox'     |     __gtype_name__ = 'SugarComboBox'     | ||||||
| 
 | 
 | ||||||
| @ -51,6 +53,7 @@ class ComboBox(gtk.ComboBox): | |||||||
|     def append_item(self, action_id, text, icon_name=None): |     def append_item(self, action_id, text, icon_name=None): | ||||||
|         if not self._icon_renderer and icon_name: |         if not self._icon_renderer and icon_name: | ||||||
|             self._icon_renderer = gtk.CellRendererPixbuf() |             self._icon_renderer = gtk.CellRendererPixbuf() | ||||||
|  |             self._icon_renderer.props.stock_size = units.microgrid_to_pixels(3) | ||||||
|             self.pack_start(self._icon_renderer, False) |             self.pack_start(self._icon_renderer, False) | ||||||
|             self.add_attribute(self._icon_renderer, 'icon-name', 2) |             self.add_attribute(self._icon_renderer, 'icon-name', 2) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -82,6 +82,9 @@ class StderrCatcher: | |||||||
|         _log_writer.write(STDERR_LEVEL, txt) |         _log_writer.write(STDERR_LEVEL, txt) | ||||||
|         sys.__stderr__.write(txt) |         sys.__stderr__.write(txt) | ||||||
| 
 | 
 | ||||||
|  |     def flush(self): | ||||||
|  |         sys.__stderr__.flush() | ||||||
|  | 
 | ||||||
| def __exception_handler(typ, exc, tb): | def __exception_handler(typ, exc, tb): | ||||||
|     trace = StringIO() |     trace = StringIO() | ||||||
|     traceback.print_exception(typ, exc, tb, None, trace) |     traceback.print_exception(typ, exc, tb, None, trace) | ||||||
|  | |||||||
| @ -1,5 +1,4 @@ | |||||||
| sugardir = $(pythondir)/sugar/objects | sugardir = $(pythondir)/sugar/objects | ||||||
| sugar_PYTHON =			\
 | sugar_PYTHON =		\
 | ||||||
| 	__init__.py		\
 | 	__init__.py	\
 | ||||||
| 	typeregistry.py		\
 | 	mime.py | ||||||
| 	typeinfo.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 | # along with this program; if not, write to the Free Software | ||||||
| # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA | ||||||
| 
 | 
 | ||||||
| import os | import sys | ||||||
| 
 | 
 | ||||||
| import pygtk | from sugar import objects | ||||||
| pygtk.require('2.0') |  | ||||||
| import gtk |  | ||||||
| import gobject |  | ||||||
| 
 | 
 | ||||||
| import sugar.browser | print 'MIME type for test.pdf (from extension):' | ||||||
|  | print objects.mime.get_from_file_name('test.pdf') | ||||||
| 
 | 
 | ||||||
| def _print_document(): | print '' | ||||||
|     #print browser.document |  | ||||||
|     pass |  | ||||||
| 
 | 
 | ||||||
| def _quit(window): | if len(sys.argv) > 1: | ||||||
|     sugar.browser.shutdown() |     print 'MIME type for file %s:' % sys.argv[1] | ||||||
|     gtk.main_quit() |     print objects.mime.get_for_file(sys.argv[1]) | ||||||
| 
 |  | ||||||
| # 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() |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Simon McVittie
						Simon McVittie