diff --git a/patches/winemenubuilder-associations/0001-winemenubuilder-Create-.desktop-files-for-programs-t.patch b/patches/winemenubuilder-associations/0001-winemenubuilder-Create-.desktop-files-for-programs-t.patch new file mode 100644 index 00000000..1332b6f1 --- /dev/null +++ b/patches/winemenubuilder-associations/0001-winemenubuilder-Create-.desktop-files-for-programs-t.patch @@ -0,0 +1,266 @@ +From 88814d059f53ba2575568d252f4da7539ee50c01 Mon Sep 17 00:00:00 2001 +From: Alex Henrie +Date: Sun, 7 May 2023 22:34:15 -0600 +Subject: [PATCH] winemenubuilder: Create .desktop files for programs that open + URIs. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=22904 +--- + programs/winemenubuilder/winemenubuilder.c | 164 ++++++++++++--------- + 1 file changed, 96 insertions(+), 68 deletions(-) + +diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c +index c16d22e2a57..b06eae422ff 100644 +--- a/programs/winemenubuilder/winemenubuilder.c ++++ b/programs/winemenubuilder/winemenubuilder.c +@@ -1831,10 +1831,13 @@ static BOOL has_association_changed(LPCWSTR extensionW, const WCHAR *mimeType, c + ret = TRUE; + heap_free(value); + +- value = reg_get_valW(assocKey, extensionW, L"ProgID"); +- if (!value || wcscmp(value, progId)) +- ret = TRUE; +- heap_free(value); ++ if (progId) ++ { ++ value = reg_get_valW(assocKey, extensionW, L"ProgID"); ++ if (!value || wcscmp(value, progId)) ++ ret = TRUE; ++ heap_free(value); ++ } + + value = reg_get_valW(assocKey, extensionW, L"AppName"); + if (!value || wcscmp(value, appName)) +@@ -1878,7 +1881,7 @@ static void update_association(LPCWSTR extension, const WCHAR *mimeType, const W + } + + RegSetValueExW(subkey, L"MimeType", 0, REG_SZ, (const BYTE*) mimeType, (lstrlenW(mimeType) + 1) * sizeof(WCHAR)); +- RegSetValueExW(subkey, L"ProgID", 0, REG_SZ, (const BYTE*) progId, (lstrlenW(progId) + 1) * sizeof(WCHAR)); ++ if (progId) RegSetValueExW(subkey, L"ProgID", 0, REG_SZ, (const BYTE*) progId, (lstrlenW(progId) + 1) * sizeof(WCHAR)); + RegSetValueExW(subkey, L"AppName", 0, REG_SZ, (const BYTE*) appName, (lstrlenW(appName) + 1) * sizeof(WCHAR)); + RegSetValueExW(subkey, L"DesktopFile", 0, REG_SZ, (const BYTE*) desktopFile, (lstrlenW(desktopFile) + 1) * sizeof(WCHAR)); + if (openWithIcon) +@@ -1962,12 +1965,16 @@ static BOOL write_freedesktop_mime_type_entry(const WCHAR *packages_dir, const W + return ret; + } + +-static BOOL is_extension_banned(LPCWSTR extension) ++static BOOL is_type_banned(const WCHAR *win_type) + { + /* These are managed through external tools like wine.desktop, to evade malware created file type associations */ +- if (!wcsicmp(extension, L".com") || +- !wcsicmp(extension, L".exe") || +- !wcsicmp(extension, L".msi")) ++ if (!wcsicmp(win_type, L".com") || ++ !wcsicmp(win_type, L".exe") || ++ !wcsicmp(win_type, L".msi")) ++ return TRUE; ++ /* Associating a program with the file URI scheme is like associating it with all file types, which is not allowed ++ * for the same reasons */ ++ if (!wcsicmp(win_type, L"file")) + return TRUE; + return FALSE; + } +@@ -2041,11 +2048,15 @@ static BOOL write_freedesktop_association_entry(const WCHAR *desktopPath, const + if (prefix) + { + char *path = wine_get_unix_file_name( prefix ); +- fprintf(desktop, "Exec=env WINEPREFIX=\"%s\" wine start /ProgIDOpen %s %%f\n", path, escape(progId)); ++ fprintf(desktop, "Exec=env WINEPREFIX=\"%s\" wine start ", path); + heap_free( path ); + } + else +- fprintf(desktop, "Exec=wine start /ProgIDOpen %s %%f\n", escape(progId)); ++ fprintf(desktop, "Exec=wine start "); ++ if (progId) /* file association */ ++ fprintf(desktop, "/ProgIDOpen %s %%f\n", escape(progId)); ++ else /* protocol association */ ++ fprintf(desktop, "%%u\n"); + fprintf(desktop, "NoDisplay=true\n"); + fprintf(desktop, "StartupNotify=true\n"); + if (openWithIcon) +@@ -2073,12 +2084,19 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic + + for (i = 0; ; i++) + { +- WCHAR *extensionW; ++ WCHAR *winTypeW; ++ BOOL isProtocolType = FALSE; + +- if (!(extensionW = reg_enum_keyW(HKEY_CLASSES_ROOT, i))) ++ if (!(winTypeW = reg_enum_keyW(HKEY_CLASSES_ROOT, i))) + break; + +- if (extensionW[0] == '.' && !is_extension_banned(extensionW)) ++ if (winTypeW[0] != '.') ++ { ++ if (RegGetValueW(HKEY_CLASSES_ROOT, winTypeW, L"URL Protocol", RRF_RT_ANY, NULL, NULL, NULL) == ERROR_SUCCESS) ++ isProtocolType = TRUE; ++ } ++ ++ if ((winTypeW[0] == '.' || isProtocolType) && !is_type_banned(winTypeW)) + { + WCHAR *commandW = NULL; + WCHAR *executableW = NULL; +@@ -2092,7 +2110,7 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic + WCHAR *mimeProgId = NULL; + struct rb_string_entry *entry; + +- commandW = assoc_query(ASSOCSTR_COMMAND, extensionW, L"open"); ++ commandW = assoc_query(ASSOCSTR_COMMAND, winTypeW, L"open"); + if (commandW == NULL) + /* no command => no application is associated */ + goto end; +@@ -2101,78 +2119,88 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic + /* command is on the exclude list => desktop integration is not desirable */ + goto end; + +- wcslwr(extensionW); +- friendlyDocNameW = assoc_query(ASSOCSTR_FRIENDLYDOCNAME, extensionW, NULL); ++ iconW = assoc_query(ASSOCSTR_DEFAULTICON, winTypeW, NULL); + +- iconW = assoc_query(ASSOCSTR_DEFAULTICON, extensionW, NULL); ++ if (isProtocolType) ++ { ++ mimeType = heap_wprintf(L"x-scheme-handler/%s", winTypeW); ++ } ++ else ++ { ++ wcslwr(winTypeW); ++ friendlyDocNameW = assoc_query(ASSOCSTR_FRIENDLYDOCNAME, winTypeW, NULL); + +- contentTypeW = assoc_query(ASSOCSTR_CONTENTTYPE, extensionW, NULL); +- if (contentTypeW) +- wcslwr(contentTypeW); ++ contentTypeW = assoc_query(ASSOCSTR_CONTENTTYPE, winTypeW, NULL); ++ if (contentTypeW) ++ wcslwr(contentTypeW); + +- mimeType = freedesktop_mime_type_for_extension(&nativeMimeTypes, extensionW); ++ mimeType = freedesktop_mime_type_for_extension(&nativeMimeTypes, winTypeW); + +- if (mimeType == NULL) +- { +- if (contentTypeW != NULL && wcschr(contentTypeW, '/')) +- mimeType = xwcsdup(contentTypeW); +- else if (!(mimeType = get_special_mime_type(extensionW))) +- mimeType = heap_wprintf(L"application/x-wine-extension-%s", &extensionW[1]); +- +- /* GNOME seems to ignore the tag in MIME packages, +- * and the default name is more intuitive anyway. +- */ +- if (iconW) ++ if (mimeType == NULL) + { +- WCHAR *flattened_mime = slashes_to_minuses(mimeType); +- int index = 0; +- WCHAR *comma = wcsrchr(iconW, ','); +- if (comma) ++ if (contentTypeW != NULL && wcschr(contentTypeW, '/')) ++ mimeType = xwcsdup(contentTypeW); ++ else if (!(mimeType = get_special_mime_type(winTypeW))) ++ mimeType = heap_wprintf(L"application/x-wine-extension-%s", &winTypeW[1]); ++ ++ /* GNOME seems to ignore the tag in MIME packages, ++ * and the default name is more intuitive anyway. ++ */ ++ if (iconW) + { +- *comma = 0; +- index = wcstol(comma + 1, NULL, 10); ++ WCHAR *flattened_mime = slashes_to_minuses(mimeType); ++ int index = 0; ++ WCHAR *comma = wcsrchr(iconW, ','); ++ if (comma) ++ { ++ *comma = 0; ++ index = wcstol(comma + 1, NULL, 10); ++ } ++ extract_icon(iconW, index, flattened_mime, FALSE); ++ heap_free(flattened_mime); + } +- extract_icon(iconW, index, flattened_mime, FALSE); +- heap_free(flattened_mime); ++ ++ write_freedesktop_mime_type_entry(packages_dir, winTypeW, mimeType, friendlyDocNameW); ++ hasChanged = TRUE; + } + +- write_freedesktop_mime_type_entry(packages_dir, extensionW, mimeType, friendlyDocNameW); +- hasChanged = TRUE; ++ progIdW = reg_get_valW(HKEY_CLASSES_ROOT, winTypeW, NULL); ++ if (!progIdW) goto end; /* no progID => not a file type association */ ++ ++ /* Do not allow duplicate ProgIDs for a MIME type, it causes unnecessary duplication in Open dialogs */ ++ mimeProgId = heap_wprintf(L"%s=>%s", mimeType, progIdW); ++ if (wine_rb_get(&mimeProgidTree, mimeProgId)) ++ { ++ heap_free(mimeProgId); ++ goto end; ++ } ++ entry = xmalloc(sizeof(struct rb_string_entry)); ++ entry->string = mimeProgId; ++ if (wine_rb_put(&mimeProgidTree, mimeProgId, &entry->entry)) ++ { ++ WINE_ERR("error updating rb tree\n"); ++ goto end; ++ } + } + +- executableW = assoc_query(ASSOCSTR_EXECUTABLE, extensionW, L"open"); ++ executableW = assoc_query(ASSOCSTR_EXECUTABLE, winTypeW, L"open"); + if (executableW) + openWithIcon = compute_native_identifier(0, executableW, NULL); + +- friendlyAppName = assoc_query(ASSOCSTR_FRIENDLYAPPNAME, extensionW, L"open"); ++ friendlyAppName = assoc_query(ASSOCSTR_FRIENDLYAPPNAME, winTypeW, L"open"); + if (!friendlyAppName) friendlyAppName = L"A Wine application"; + +- progIdW = reg_get_valW(HKEY_CLASSES_ROOT, extensionW, NULL); +- if (!progIdW) goto end; /* no progID => not a file type association */ +- +- /* Do not allow duplicate ProgIDs for a MIME type, it causes unnecessary duplication in Open dialogs */ +- mimeProgId = heap_wprintf(L"%s=>%s", mimeType, progIdW); +- if (wine_rb_get(&mimeProgidTree, mimeProgId)) ++ if (has_association_changed(winTypeW, mimeType, progIdW, friendlyAppName, openWithIcon)) + { +- heap_free(mimeProgId); +- goto end; +- } +- entry = xmalloc(sizeof(struct rb_string_entry)); +- entry->string = mimeProgId; +- if (wine_rb_put(&mimeProgidTree, mimeProgId, &entry->entry)) +- { +- WINE_ERR("error updating rb tree\n"); +- goto end; +- } +- +- if (has_association_changed(extensionW, mimeType, progIdW, friendlyAppName, openWithIcon)) +- { +- WCHAR *desktopPath = heap_wprintf(L"%s\\wine-extension-%s.desktop", +- applications_dir, extensionW + 1 ); ++ WCHAR *desktopPath; ++ if (isProtocolType) ++ desktopPath = heap_wprintf(L"%s\\wine-protocol-%s.desktop", applications_dir, winTypeW); ++ else ++ desktopPath = heap_wprintf(L"%s\\wine-extension-%s.desktop", applications_dir, winTypeW + 1); + if (write_freedesktop_association_entry(desktopPath, friendlyAppName, mimeType, progIdW, openWithIcon)) + { + hasChanged = TRUE; +- update_association(extensionW, mimeType, progIdW, friendlyAppName, desktopPath, openWithIcon); ++ update_association(winTypeW, mimeType, progIdW, friendlyAppName, desktopPath, openWithIcon); + } + heap_free(desktopPath); + } +@@ -2189,7 +2217,7 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic + heap_free(mimeType); + heap_free(progIdW); + } +- heap_free(extensionW); ++ heap_free(winTypeW); + } + + wine_rb_destroy(&mimeProgidTree, winemenubuilder_rb_destroy, NULL); +-- +2.40.1 + diff --git a/patches/winemenubuilder-associations/0002-winecfg-Mention-protocol-associations.patch b/patches/winemenubuilder-associations/0002-winecfg-Mention-protocol-associations.patch new file mode 100644 index 00000000..58744daa --- /dev/null +++ b/patches/winemenubuilder-associations/0002-winecfg-Mention-protocol-associations.patch @@ -0,0 +1,25 @@ +From 1d91d62e04e11defa69177084e3b4d5e55e0eae8 Mon Sep 17 00:00:00 2001 +From: Alex Henrie +Date: Sun, 7 May 2023 22:34:15 -0600 +Subject: [PATCH] winecfg: Mention protocol associations. + +--- + programs/winecfg/winecfg.rc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/programs/winecfg/winecfg.rc b/programs/winecfg/winecfg.rc +index 3f18020e8a8..7e58f1553ce 100644 +--- a/programs/winecfg/winecfg.rc ++++ b/programs/winecfg/winecfg.rc +@@ -313,7 +313,7 @@ BEGIN + CONTROL "",IDC_SYSPARAM_SIZE_UD,UPDOWN_CLASSA,UDS_SETBUDDYINT | UDS_ALIGNRIGHT | WS_DISABLED, 185,75,15,13 + + GROUPBOX "MIME types",IDC_STATIC,8,95,244,23 +- CONTROL "Manage file &associations",IDC_ENABLE_FILE_ASSOCIATIONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,105,230,10 ++ CONTROL "Manage file and protocol &associations",IDC_ENABLE_FILE_ASSOCIATIONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,105,230,10 + + PUSHBUTTON "&Font...",IDC_SYSPARAM_FONT,190,75,55,13,WS_DISABLED + GROUPBOX "Folders",IDC_STATIC,8,120,244,94 +-- +2.40.1 + diff --git a/patches/winemenubuilder-associations/definition b/patches/winemenubuilder-associations/definition new file mode 100644 index 00000000..7c03b236 --- /dev/null +++ b/patches/winemenubuilder-associations/definition @@ -0,0 +1,2 @@ +# PR 2740 +Fixes: [22904] Register URL protocol handlers under linux.