mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
397 lines
11 KiB
Diff
397 lines
11 KiB
Diff
From 57e066e3be063d122243daa149ef327c2594901a Mon Sep 17 00:00:00 2001
|
|
From: Jeremy White <jwhite@codeweavers.com>
|
|
Date: Thu, 29 Mar 2018 11:58:25 +1100
|
|
Subject: [PATCH] winemapi: Directly use xdg-email if available, enabling file
|
|
attachments.
|
|
|
|
This addresses https://bugs.winehq.org/show_bug.cgi?id=11770 for systems with xdg-email.
|
|
|
|
v2:
|
|
Use new heap_* function.
|
|
|
|
Signed-off-by: Jeremy White <jwhite@codeweavers.com>
|
|
---
|
|
dlls/winemapi/Makefile.in | 3 +-
|
|
dlls/winemapi/sendmail.c | 48 ++++--
|
|
dlls/winemapi/winemapi_private.h | 27 ++++
|
|
dlls/winemapi/xdg-email.c | 246 +++++++++++++++++++++++++++++++
|
|
4 files changed, 309 insertions(+), 15 deletions(-)
|
|
create mode 100644 dlls/winemapi/winemapi_private.h
|
|
create mode 100644 dlls/winemapi/xdg-email.c
|
|
|
|
diff --git a/dlls/winemapi/Makefile.in b/dlls/winemapi/Makefile.in
|
|
index 813ee42b349..d6f79b403da 100644
|
|
--- a/dlls/winemapi/Makefile.in
|
|
+++ b/dlls/winemapi/Makefile.in
|
|
@@ -3,4 +3,5 @@ IMPORTS = shlwapi shell32 mapi32
|
|
|
|
C_SRCS = \
|
|
main.c \
|
|
- sendmail.c
|
|
+ sendmail.c \
|
|
+ xdg-email.c
|
|
diff --git a/dlls/winemapi/sendmail.c b/dlls/winemapi/sendmail.c
|
|
index cfb27e55c95..d5625686e9e 100644
|
|
--- a/dlls/winemapi/sendmail.c
|
|
+++ b/dlls/winemapi/sendmail.c
|
|
@@ -37,6 +37,8 @@
|
|
#include "winternl.h"
|
|
#include "wine/debug.h"
|
|
|
|
+#include "winemapi_private.h"
|
|
+
|
|
WINE_DEFAULT_DEBUG_CHANNEL(winemapi);
|
|
|
|
/* Escapes a string for use in mailto: URL */
|
|
@@ -71,23 +73,12 @@ static char *escape_string(char *in, char *empty_string)
|
|
}
|
|
|
|
/**************************************************************************
|
|
- * MAPISendMail
|
|
+ * BrowserSendMail
|
|
*
|
|
- * Send a message using a native mail client.
|
|
- *
|
|
- * PARAMS
|
|
- * session [I] Handle to a MAPI session.
|
|
- * uiparam [I] Parent window handle.
|
|
- * message [I] Pointer to a MAPIMessage structure.
|
|
- * flags [I] Flags.
|
|
- * reserved [I] Reserved, pass 0.
|
|
- *
|
|
- * RETURNS
|
|
- * Success: SUCCESS_SUCCESS
|
|
- * Failure: MAPI_E_FAILURE
|
|
+ * Send an email by forming a mailto uri and invoking a browser.
|
|
*
|
|
*/
|
|
-ULONG WINAPI MAPISendMail(LHANDLE session, ULONG_PTR uiparam,
|
|
+static ULONG BrowserSendMail(LHANDLE session, ULONG_PTR uiparam,
|
|
lpMapiMessage message, FLAGS flags, ULONG reserved)
|
|
{
|
|
ULONG ret = MAPI_E_FAILURE;
|
|
@@ -292,6 +283,35 @@ exit:
|
|
return ret;
|
|
}
|
|
|
|
+/**************************************************************************
|
|
+ * MAPISendMail
|
|
+ *
|
|
+ * Send a message using a native mail client.
|
|
+ *
|
|
+ * PARAMS
|
|
+ * session [I] Handle to a MAPI session.
|
|
+ * uiparam [I] Parent window handle.
|
|
+ * message [I] Pointer to a MAPIMessage structure.
|
|
+ * flags [I] Flags.
|
|
+ * reserved [I] Reserved, pass 0.
|
|
+ *
|
|
+ * RETURNS
|
|
+ * Success: SUCCESS_SUCCESS
|
|
+ * Failure: MAPI_E_FAILURE
|
|
+ *
|
|
+ */
|
|
+ULONG WINAPI MAPISendMail(LHANDLE session, ULONG_PTR uiparam,
|
|
+ lpMapiMessage message, FLAGS flags, ULONG reserved)
|
|
+{
|
|
+ TRACE("(0x%08lx 0x%08lx %p 0x%08x 0x%08x)\n", session, uiparam,
|
|
+ message, flags, reserved);
|
|
+
|
|
+ if (XDGMailAvailable())
|
|
+ return XDGSendMail(session, uiparam, message, flags, reserved);
|
|
+
|
|
+ return BrowserSendMail(session, uiparam, message, flags, reserved);
|
|
+}
|
|
+
|
|
ULONG WINAPI MAPISendDocuments(ULONG_PTR uiparam, LPSTR delim, LPSTR paths,
|
|
LPSTR filenames, ULONG reserved)
|
|
{
|
|
diff --git a/dlls/winemapi/winemapi_private.h b/dlls/winemapi/winemapi_private.h
|
|
new file mode 100644
|
|
index 00000000000..a8bb8c5e075
|
|
--- /dev/null
|
|
+++ b/dlls/winemapi/winemapi_private.h
|
|
@@ -0,0 +1,27 @@
|
|
+/*
|
|
+ *
|
|
+ * Copyright 2016 Jeremy White
|
|
+ *
|
|
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
+ */
|
|
+
|
|
+#ifndef __WINEMAPI_PRIVATE_INCLUDED__
|
|
+#define __WINEMAPI_PRIVATE_INCLUDED__
|
|
+
|
|
+ULONG XDGSendMail(LHANDLE session, ULONG_PTR uiparam,
|
|
+ lpMapiMessage message, FLAGS flags, ULONG reserved);
|
|
+BOOLEAN XDGMailAvailable(void);
|
|
+
|
|
+#endif /* __WINEMAPI_PRIVATE_INCLUDED__ */
|
|
diff --git a/dlls/winemapi/xdg-email.c b/dlls/winemapi/xdg-email.c
|
|
new file mode 100644
|
|
index 00000000000..6b420663a26
|
|
--- /dev/null
|
|
+++ b/dlls/winemapi/xdg-email.c
|
|
@@ -0,0 +1,246 @@
|
|
+/*
|
|
+ * MAPISendMail implementation for xdg-email
|
|
+ *
|
|
+ * Copyright 2016 Jeremy White for CodeWeavers
|
|
+ *
|
|
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
+ */
|
|
+
|
|
+#include "config.h"
|
|
+#include "wine/port.h"
|
|
+
|
|
+#include <stdarg.h>
|
|
+
|
|
+#define COBJMACROS
|
|
+
|
|
+#include "windef.h"
|
|
+#include "winbase.h"
|
|
+#include "winerror.h"
|
|
+#include "winnls.h"
|
|
+#include "mapi.h"
|
|
+#include "wine/heap.h"
|
|
+#include "wine/debug.h"
|
|
+#ifdef HAVE_UNISTD_H
|
|
+#include <unistd.h>
|
|
+#endif
|
|
+
|
|
+#include "winemapi_private.h"
|
|
+
|
|
+WINE_DEFAULT_DEBUG_CHANNEL(winemapi);
|
|
+
|
|
+static inline WCHAR *heap_strdupAtoW(const char *str)
|
|
+{
|
|
+ LPWSTR ret = NULL;
|
|
+
|
|
+ if(str) {
|
|
+ DWORD len;
|
|
+
|
|
+ len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
|
|
+ ret = heap_alloc(len*sizeof(WCHAR));
|
|
+ if(ret)
|
|
+ MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void add_argument(char **argv, int *argc, const char *arg, const char *param)
|
|
+{
|
|
+ argv[(*argc)] = heap_alloc(strlen(arg) + 1);
|
|
+ strcpy(argv[(*argc)++], arg);
|
|
+ if (param)
|
|
+ {
|
|
+ argv[(*argc)] = heap_alloc(strlen(param) + 1);
|
|
+ strcpy(argv[(*argc)++], param);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void add_target(char **argv, int *argc, ULONG class, const char *address)
|
|
+{
|
|
+ static const char smtp[] = "smtp:";
|
|
+
|
|
+ if (!strncasecmp(address, smtp, sizeof(smtp) - 1))
|
|
+ address += sizeof(smtp) - 1;
|
|
+
|
|
+ switch (class)
|
|
+ {
|
|
+ case MAPI_ORIG:
|
|
+ TRACE("From: %s\n (unused)", debugstr_a(address));
|
|
+ break;
|
|
+
|
|
+ case MAPI_TO:
|
|
+ TRACE("To: %s\n", debugstr_a(address));
|
|
+ add_argument(argv, argc, address, NULL);
|
|
+ break;
|
|
+
|
|
+ case MAPI_CC:
|
|
+ TRACE("CC: %s\n", debugstr_a(address));
|
|
+ add_argument(argv, argc, "--cc", address);
|
|
+ break;
|
|
+
|
|
+ case MAPI_BCC:
|
|
+ TRACE("BCC: %s\n", debugstr_a(address));
|
|
+ add_argument(argv, argc, "--bcc", address);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ TRACE("Unknown recipient class: %d\n", class);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void add_file(char **argv, int *argc, const char *path, const char *file)
|
|
+{
|
|
+ char fullname[MAX_PATH] = {0};
|
|
+ WCHAR *fullnameW;
|
|
+ char *unixpath;
|
|
+
|
|
+ if (path)
|
|
+ {
|
|
+ strcpy(fullname, path);
|
|
+ strcat(fullname, "\\");
|
|
+ }
|
|
+ if (file)
|
|
+ strcat(fullname, file);
|
|
+
|
|
+ fullnameW = heap_strdupAtoW(fullname);
|
|
+ if(!fullnameW)
|
|
+ {
|
|
+ ERR("Out of memory\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ unixpath = wine_get_unix_file_name(fullnameW);
|
|
+ if (unixpath)
|
|
+ {
|
|
+ add_argument(argv, argc, "--attach", unixpath);
|
|
+ heap_free(unixpath);
|
|
+ }
|
|
+ else
|
|
+ ERR("Cannot find unix path of '%s'; not attaching.\n", debugstr_w(fullnameW));
|
|
+
|
|
+ heap_free(fullnameW);
|
|
+}
|
|
+
|
|
+/**************************************************************************
|
|
+ * XDGIsAvailable
|
|
+ *
|
|
+ */
|
|
+BOOLEAN XDGMailAvailable(void)
|
|
+{
|
|
+#ifdef HAVE_UNISTD_H
|
|
+ char *p, *q, *test;
|
|
+ int len;
|
|
+ int rc;
|
|
+
|
|
+ for (p = getenv("PATH"); p; p = q)
|
|
+ {
|
|
+ while (*p == ':')
|
|
+ p++;
|
|
+
|
|
+ if (!*p)
|
|
+ break;
|
|
+
|
|
+ q = strchr(p, ':');
|
|
+ len = q ? q - p : strlen(p);
|
|
+
|
|
+ test = heap_alloc(len + strlen("xdg-email") + 2); /* '/' + NULL */
|
|
+ if(!test)
|
|
+ break;
|
|
+ memcpy(test, p, len);
|
|
+ strcpy(test + len, "/");
|
|
+ strcat(test, "xdg-email");
|
|
+
|
|
+ rc = access(test, X_OK);
|
|
+ heap_free(test);
|
|
+
|
|
+ if (rc == 0)
|
|
+ return TRUE;
|
|
+ }
|
|
+#endif
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+/**************************************************************************
|
|
+ * XDGSendMail
|
|
+ *
|
|
+ * Send a message using xdg-email mail client.
|
|
+ *
|
|
+ */
|
|
+ULONG XDGSendMail(LHANDLE session, ULONG_PTR uiparam,
|
|
+ lpMapiMessage message, FLAGS flags, ULONG reserved)
|
|
+{
|
|
+ int i;
|
|
+ int argc = 0;
|
|
+ int max_args;
|
|
+ char **argv = NULL;
|
|
+ ULONG ret = MAPI_E_FAILURE;
|
|
+
|
|
+ TRACE("(0x%08lx 0x%08lx %p 0x%08x 0x%08x)\n", session, uiparam, message, flags, reserved);
|
|
+
|
|
+ if (!message)
|
|
+ return MAPI_E_FAILURE;
|
|
+
|
|
+ max_args = 1 + (2 + message->nRecipCount + message->nFileCount) * 2;
|
|
+ argv = heap_alloc_zero( (max_args + 1) * sizeof(*argv));
|
|
+
|
|
+ add_argument(argv, &argc, "xdg-email", NULL);
|
|
+
|
|
+ if (message->lpOriginator)
|
|
+ TRACE("From: %s (unused)\n", debugstr_a(message->lpOriginator->lpszAddress));
|
|
+
|
|
+ for (i = 0; i < message->nRecipCount; i++)
|
|
+ {
|
|
+ if (!message->lpRecips)
|
|
+ {
|
|
+ WARN("Recipient %d missing\n", i);
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ if (message->lpRecips[i].lpszAddress)
|
|
+ add_target(argv, &argc, message->lpRecips[i].ulRecipClass,
|
|
+ message->lpRecips[i].lpszAddress);
|
|
+ else
|
|
+ FIXME("Name resolution and entry identifiers not supported\n");
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < message->nFileCount; i++)
|
|
+ {
|
|
+ TRACE("File Path: %s, name %s\n", debugstr_a(message->lpFiles[i].lpszPathName),
|
|
+ debugstr_a(message->lpFiles[i].lpszFileName));
|
|
+ add_file(argv, &argc, message->lpFiles[i].lpszPathName, message->lpFiles[i].lpszFileName);
|
|
+ }
|
|
+
|
|
+ if (message->lpszSubject)
|
|
+ {
|
|
+ TRACE("Subject: %s\n", debugstr_a(message->lpszSubject));
|
|
+ add_argument(argv, &argc, "--subject", message->lpszSubject);
|
|
+ }
|
|
+
|
|
+ if (message->lpszNoteText)
|
|
+ {
|
|
+ TRACE("Body: %s\n", debugstr_a(message->lpszNoteText));
|
|
+ add_argument(argv, &argc, "--body", message->lpszNoteText);
|
|
+ }
|
|
+
|
|
+ TRACE("Executing xdg-email; parameters:\n");
|
|
+ for (i = 0; argv[i] && i <= max_args; i++)
|
|
+ TRACE(" %d: [%s]\n", i, argv[i]);
|
|
+ if (_spawnvp(_P_WAIT, "xdg-email", (const char **) argv) == 0)
|
|
+ ret = SUCCESS_SUCCESS;
|
|
+
|
|
+exit:
|
|
+ heap_free(argv);
|
|
+ return ret;
|
|
+}
|
|
--
|
|
2.20.1
|
|
|