[PATCH] winemapi: Directly use xdg-email if available, enabling file attachments.
Jeremy White
jwhite at codeweavers.com
Wed Nov 16 17:04:14 CST 2016
Signed-off-by: Jeremy White <jwhite at codeweavers.com>
---
This addresses https://bugs.winehq.org/show_bug.cgi?id=11770 for systems with xdg-email.
And perhaps it is even sent to the correct list this time...
---
dlls/winemapi/Makefile.in | 3 +-
dlls/winemapi/sendmail.c | 45 +++++---
dlls/winemapi/winemapi_private.h | 28 +++++
dlls/winemapi/xdg-email.c | 230 +++++++++++++++++++++++++++++++++++++++
4 files changed, 291 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 813ee42..d6f79b4 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 03a29ba..f7a63ca 100644
--- a/dlls/winemapi/sendmail.c
+++ b/dlls/winemapi/sendmail.c
@@ -36,6 +36,8 @@
#include "shlwapi.h"
#include "wine/debug.h"
+#include "winemapi_private.h"
+
WINE_DEFAULT_DEBUG_CHANNEL(winemapi);
/* Escapes a string for use in mailto: URL */
@@ -70,23 +72,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;
@@ -291,6 +282,32 @@ 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)
+{
+ 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 0000000..ac76ab3
--- /dev/null
+++ b/dlls/winemapi/winemapi_private.h
@@ -0,0 +1,28 @@
+/*
+ *
+ * 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 0000000..6008d6e
--- /dev/null
+++ b/dlls/winemapi/xdg-email.c
@@ -0,0 +1,230 @@
+/*
+ * 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/debug.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "winemapi_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(winemapi);
+
+static void add_argument(char **argv, int *argc, const char *arg, const char *param)
+{
+ argv[(*argc)] = HeapAlloc(GetProcessHeap(), 0, strlen(arg) + 1);
+ strcpy(argv[(*argc)++], arg);
+ if (param)
+ {
+ argv[(*argc)] = HeapAlloc(GetProcessHeap(), 0, 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)
+{
+ WCHAR *fullname, *p;
+ char *unixpath;
+ int namelen = 1;
+
+ if (path)
+ namelen += strlen(path) + 1;
+ if (file)
+ namelen += strlen(file);
+
+ p = fullname = HeapAlloc(GetProcessHeap(), 0, namelen * sizeof(WCHAR));
+ ZeroMemory(fullname, namelen * sizeof(WCHAR));
+ if (path)
+ {
+ MultiByteToWideChar(CP_ACP, 0, path, -1, p, namelen);
+ p += namelen;
+ MultiByteToWideChar(CP_ACP, 0, "\\", 1, p, 1);
+ p ++;
+ }
+ if (file)
+ MultiByteToWideChar(CP_ACP, 0, file, -1, p, namelen - (p - fullname));
+
+ unixpath = wine_get_unix_file_name(fullname);
+ if (!unixpath)
+ TRACE("Cannot find unix path of '%s'; not attaching.\n", debugstr_w(fullname));
+ HeapFree(GetProcessHeap(), 0, fullname);
+ if (!unixpath)
+ return;
+
+ add_argument(argv, argc, "--attach", unixpath);
+ HeapFree(GetProcessHeap(), 0, unixpath);
+}
+
+/**************************************************************************
+ * 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 = HeapAlloc(GetProcessHeap(), 0, len + strlen("xdg-email") + 1 + 1);
+ memcpy(test, p, len);
+ strcpy(test + len, "/");
+ strcat(test, "xdg-email");
+
+ rc = access(test, X_OK);
+ HeapFree(GetProcessHeap(), 0, 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 = HeapAlloc(GetProcessHeap(), 0, (max_args + 1) * sizeof(*argv));
+ ZeroMemory(argv, (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:
+ HeapFree(GetProcessHeap(), 0, argv);
+ return ret;
+}
+
--
2.1.4
More information about the wine-patches
mailing list