Damjan Jovanovic : winemenubuilder: Add MIME types to freedesktop.
Alexandre Julliard
julliard at winehq.org
Mon May 25 10:06:34 CDT 2009
Module: wine
Branch: master
Commit: c1fa150cebc4c7e5685fa7f4f59ab6c453d12250
URL: http://source.winehq.org/git/wine.git/?a=commit;h=c1fa150cebc4c7e5685fa7f4f59ab6c453d12250
Author: Damjan Jovanovic <damjan.jov at gmail.com>
Date: Tue May 19 21:40:41 2009 +0200
winemenubuilder: Add MIME types to freedesktop.
---
programs/winemenubuilder/Makefile.in | 2 +-
programs/winemenubuilder/winemenubuilder.c | 182 +++++++++++++++++++++++++++-
2 files changed, 178 insertions(+), 6 deletions(-)
diff --git a/programs/winemenubuilder/Makefile.in b/programs/winemenubuilder/Makefile.in
index 050b3b3..0931bdf 100644
--- a/programs/winemenubuilder/Makefile.in
+++ b/programs/winemenubuilder/Makefile.in
@@ -5,7 +5,7 @@ SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = winemenubuilder.exe
APPMODE = -mwindows
-IMPORTS = uuid shell32 ole32 user32 advapi32 kernel32
+IMPORTS = uuid shell32 shlwapi ole32 user32 advapi32 kernel32
C_SRCS = \
winemenubuilder.c
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c
index 58e84c6..2e63168 100644
--- a/programs/winemenubuilder/winemenubuilder.c
+++ b/programs/winemenubuilder/winemenubuilder.c
@@ -64,6 +64,7 @@
#endif
#include <errno.h>
#include <stdarg.h>
+#include <fnmatch.h>
#define COBJMACROS
@@ -74,6 +75,7 @@
#include <appmgmt.h>
#include <tlhelp32.h>
#include <intshcut.h>
+#include <shlwapi.h>
#include "wine/unicode.h"
#include "wine/debug.h"
@@ -1251,6 +1253,38 @@ static HRESULT get_cmdline( IShellLinkW *sl, LPWSTR szPath, DWORD pathSize,
return hr;
}
+static WCHAR* assoc_query(ASSOCSTR assocStr, LPCWSTR name, LPCWSTR extra)
+{
+ HRESULT hr;
+ WCHAR *value = NULL;
+ DWORD size = 0;
+ hr = AssocQueryStringW(0, assocStr, name, extra, NULL, &size);
+ if (SUCCEEDED(hr))
+ {
+ value = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
+ if (value)
+ {
+ hr = AssocQueryStringW(0, assocStr, name, extra, value, &size);
+ if (FAILED(hr))
+ {
+ HeapFree(GetProcessHeap(), 0, value);
+ value = NULL;
+ }
+ }
+ }
+ return value;
+}
+
+static char* wchars_to_utf8_chars(LPCWSTR string)
+{
+ char *ret;
+ INT size = WideCharToMultiByte(CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL);
+ ret = HeapAlloc(GetProcessHeap(), 0, size);
+ if (ret)
+ WideCharToMultiByte(CP_UTF8, 0, string, -1, ret, size, NULL, NULL);
+ return ret;
+}
+
static BOOL next_line(FILE *file, char **line, int *size)
{
int pos = 0;
@@ -1316,9 +1350,17 @@ static BOOL add_mimes(const char *xdg_data_dir, struct list *mime_types)
if (mime_type_entry)
{
*pos = 0;
- mime_type_entry->mimeType = line;
- mime_type_entry->glob = pos + 1;
- list_add_tail(mime_types, &mime_type_entry->entry);
+ mime_type_entry->mimeType = heap_printf("%s", line);
+ mime_type_entry->glob = heap_printf("%s", pos + 1);
+ if (mime_type_entry->mimeType && mime_type_entry->glob)
+ list_add_tail(mime_types, &mime_type_entry->entry);
+ else
+ {
+ HeapFree(GetProcessHeap(), 0, mime_type_entry->mimeType);
+ HeapFree(GetProcessHeap(), 0, mime_type_entry->glob);
+ HeapFree(GetProcessHeap(), 0, mime_type_entry);
+ ret = FALSE;
+ }
}
else
ret = FALSE;
@@ -1341,6 +1383,7 @@ static void free_native_mime_types(struct list *native_mime_types)
LIST_FOR_EACH_ENTRY_SAFE(mime_type_entry, mime_type_entry2, native_mime_types, struct xdg_mime_type, entry)
{
list_remove(&mime_type_entry->entry);
+ HeapFree(GetProcessHeap(), 0, mime_type_entry->glob);
HeapFree(GetProcessHeap(), 0, mime_type_entry->mimeType);
HeapFree(GetProcessHeap(), 0, mime_type_entry);
}
@@ -1398,16 +1441,130 @@ static BOOL build_native_mime_types(const char *xdg_data_home, struct list **mim
return ret;
}
+static BOOL write_freedesktop_mime_type_entry(const char *packages_dir, const char *dot_extension,
+ const char *mime_type, const char *comment)
+{
+ BOOL ret = FALSE;
+ char *filename;
+
+ WINE_TRACE("writing MIME type %s, extension=%s, comment=%s\n", wine_dbgstr_a(mime_type),
+ wine_dbgstr_a(dot_extension), wine_dbgstr_a(comment));
+
+ filename = heap_printf("%s/x-wine-extension-%s.xml", packages_dir, &dot_extension[1]);
+ if (filename)
+ {
+ FILE *packageFile = fopen(filename, "w");
+ if (packageFile)
+ {
+ fprintf(packageFile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ fprintf(packageFile, "<mime-info xmlns=\"http://www.freedesktop.org/standards/shared-mime-info\">\n");
+ fprintf(packageFile, " <mime-type type=\"%s\">\n", mime_type);
+ fprintf(packageFile, " <glob pattern=\"*%s\"/>\n", dot_extension);
+ if (comment)
+ fprintf(packageFile, " <comment>%s</comment>\n", comment);
+ fprintf(packageFile, " </mime-type>\n");
+ fprintf(packageFile, "</mime-info>\n");
+ ret = TRUE;
+ fclose(packageFile);
+ }
+ else
+ WINE_ERR("error writing file %s\n", filename);
+ HeapFree(GetProcessHeap(), 0, filename);
+ }
+ else
+ WINE_ERR("out of memory\n");
+ return ret;
+}
+
static BOOL generate_associations(const char *xdg_data_home, const char *packages_dir, const char *applications_dir)
{
struct list *nativeMimeTypes = NULL;
+ LSTATUS ret = 0;
+ int i;
+ BOOL hasChanged = FALSE;
if (!build_native_mime_types(xdg_data_home, &nativeMimeTypes))
{
WINE_ERR("could not build native MIME types\n");
return FALSE;
}
- return TRUE;
+
+ for (i = 0; ; i++)
+ {
+ WCHAR *extensionW = NULL;
+ DWORD size = 1024;
+
+ do
+ {
+ HeapFree(GetProcessHeap(), 0, extensionW);
+ extensionW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
+ if (extensionW == NULL)
+ {
+ WINE_ERR("out of memory\n");
+ ret = ERROR_OUTOFMEMORY;
+ break;
+ }
+ ret = RegEnumKeyExW(HKEY_CLASSES_ROOT, i, extensionW, &size, NULL, NULL, NULL, NULL);
+ size *= 2;
+ } while (ret == ERROR_MORE_DATA);
+
+ if (ret == ERROR_SUCCESS && extensionW[0] == '.')
+ {
+ char *extensionA = NULL;
+ WCHAR *commandW = NULL;
+ WCHAR *friendlyDocNameW = NULL;
+ char *friendlyDocNameA = NULL;
+ WCHAR *contentTypeW = NULL;
+ char *mimeTypeA = NULL;
+
+ extensionA = wchars_to_utf8_chars(extensionW);
+ if (extensionA == NULL)
+ {
+ WINE_ERR("out of memory\n");
+ goto end;
+ }
+
+ commandW = assoc_query(ASSOCSTR_COMMAND, extensionW, NULL);
+ if (commandW == NULL)
+ /* no command -> unusable extension */
+ goto end;
+
+ friendlyDocNameW = assoc_query(ASSOCSTR_FRIENDLYDOCNAME, extensionW, NULL);
+ if (friendlyDocNameW)
+ {
+ friendlyDocNameA = wchars_to_utf8_chars(friendlyDocNameW);
+ if (friendlyDocNameA == NULL)
+ {
+ WINE_ERR("out of memory\n");
+ goto end;
+ }
+ }
+
+ contentTypeW = assoc_query(ASSOCSTR_CONTENTTYPE, extensionW, NULL);
+ if (contentTypeW == NULL)
+ goto end;
+
+ mimeTypeA = wchars_to_utf8_chars(contentTypeW);
+ if (mimeTypeA == NULL)
+ goto end;
+
+ write_freedesktop_mime_type_entry(packages_dir, extensionA, mimeTypeA, friendlyDocNameA);
+
+ end:
+ HeapFree(GetProcessHeap(), 0, extensionA);
+ HeapFree(GetProcessHeap(), 0, commandW);
+ HeapFree(GetProcessHeap(), 0, friendlyDocNameW);
+ HeapFree(GetProcessHeap(), 0, friendlyDocNameA);
+ HeapFree(GetProcessHeap(), 0, contentTypeW);
+ HeapFree(GetProcessHeap(), 0, mimeTypeA);
+ }
+ HeapFree(GetProcessHeap(), 0, extensionW);
+ if (ret != ERROR_SUCCESS)
+ break;
+ }
+
+ free_native_mime_types(nativeMimeTypes);
+ return hasChanged;
}
static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
@@ -1841,6 +1998,7 @@ static void RefreshFileTypeAssociations(void)
char *mime_dir = NULL;
char *packages_dir = NULL;
char *applications_dir = NULL;
+ BOOL hasChanged;
hSem = CreateSemaphoreA( NULL, 1, 1, "winemenubuilder_semaphore");
if( WAIT_OBJECT_0 != MsgWaitForMultipleObjects( 1, &hSem, FALSE, INFINITE, QS_ALLINPUT ) )
@@ -1875,7 +2033,21 @@ static void RefreshFileTypeAssociations(void)
}
create_directories(applications_dir);
- generate_associations(xdg_data_dir, packages_dir, applications_dir);
+ hasChanged = generate_associations(xdg_data_dir, packages_dir, applications_dir);
+ if (hasChanged)
+ {
+ char *command = heap_printf("update-mime-database %s", mime_dir);
+ if (command)
+ {
+ system(command);
+ HeapFree(GetProcessHeap(), 0, command);
+ }
+ else
+ {
+ WINE_ERR("out of memory\n");
+ goto end;
+ }
+ }
end:
if (hSem)
More information about the wine-cvs
mailing list