You've already forked wine-staging
							
							
				mirror of
				https://gitlab.winehq.org/wine/wine-staging.git
				synced 2025-09-12 18:50:20 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			392 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			392 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 0ae9f7c32cf873611ce5ed7f341f5979690f2318 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.
 | |
| 
 | |
| v2:
 | |
| Use new heap_* function.
 | |
| 
 | |
| Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=11770
 | |
| 
 | |
| 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        | 241 +++++++++++++++++++++++++++++++
 | |
|  4 files changed, 304 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 84ff227e1cb..4fd83830aea 100644
 | |
| --- a/dlls/winemapi/Makefile.in
 | |
| +++ b/dlls/winemapi/Makefile.in
 | |
| @@ -5,4 +5,5 @@ EXTRADLLFLAGS = -mno-cygwin
 | |
|  
 | |
|  C_SRCS = \
 | |
|  	main.c \
 | |
| -	sendmail.c
 | |
| +	sendmail.c \
 | |
| +	xdg-email.c
 | |
| diff --git a/dlls/winemapi/sendmail.c b/dlls/winemapi/sendmail.c
 | |
| index ca1b6c59df1..e288837a33d 100644
 | |
| --- a/dlls/winemapi/sendmail.c
 | |
| +++ b/dlls/winemapi/sendmail.c
 | |
| @@ -34,6 +34,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 */
 | |
| @@ -68,23 +70,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;
 | |
| @@ -289,6 +280,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..08a9b49cc7f
 | |
| --- /dev/null
 | |
| +++ b/dlls/winemapi/xdg-email.c
 | |
| @@ -0,0 +1,241 @@
 | |
| +/*
 | |
| + * 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 <stdarg.h>
 | |
| +
 | |
| +#define COBJMACROS
 | |
| +
 | |
| +#include "windef.h"
 | |
| +#include "winbase.h"
 | |
| +#include "winerror.h"
 | |
| +#include "winnls.h"
 | |
| +#include "mapi.h"
 | |
| +#include "process.h"
 | |
| +#include "wine/heap.h"
 | |
| +#include "wine/debug.h"
 | |
| +
 | |
| +#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.17.1
 | |
| 
 |