/[winpt]/trunk/Src/wptMAPI.cpp
ViewVC logotype

Diff of /trunk/Src/wptMAPI.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 36 by werner, Thu Oct 27 15:25:13 2005 UTC revision 244 by twoaday, Mon Jul 3 14:10:21 2006 UTC
# Line 1  Line 1 
1  /* wptMAPI.cpp  /* wptMAPI.cpp - MAPI interface for sending keys.
2   *      Copyright (C) 2003, 2004 Timo Schulz   *      Copyright (C) 2003-2006 Timo Schulz
3   *   *
4   * This file is part of WinPT.   * This file is part of WinPT.
5   *   *
# Line 22  Line 22 
22  #endif  #endif
23    
24  #include <windows.h>  #include <windows.h>
 #include <windows.h>  
25  #include <stdio.h>  #include <stdio.h>
26  #include <mapi.h>  #include <mapi.h>
27    
28  extern HINSTANCE glob_hinst;  #include "resource.h"
   
 #include "../resource.h"  
29  #include "wptTypes.h"  #include "wptTypes.h"
30  #include "wptErrors.h"  #include "wptErrors.h"
31  #include "wptW32API.h"  #include "wptW32API.h"
32  #include "wptGPG.h"  #include "wptGPG.h"
33    #include "wptVersion.h"
34    #include "wptCommonCtl.h"
35    #include "wptKeyManager.h"
36    
37    
38  static LPMAPILOGON          mapi_logon = NULL;  static LPMAPILOGON          mapi_logon = NULL;
# Line 45  static int                 init = 0; Line 45  static int                 init = 0;
45  #define load_one_fnc(cast, hlib, name) (cast)GetProcAddress ((hlib), name)  #define load_one_fnc(cast, hlib, name) (cast)GetProcAddress ((hlib), name)
46    
47    
48    /* Table with all valid MAPI errors. */
49    struct mapi_err_s {
50        int err_no;
51        const char *msg;
52    } mapi_errors[] = {
53        {MAPI_E_FAILURE, "One or more unspecified errors occurred. "},
54        {MAPI_E_AMBIGUOUS_RECIPIENT, "A recipient matched more than one of the recipient descriptor structures and MAPI_DIALOG was not set. "},
55        {MAPI_E_ATTACHMENT_NOT_FOUND, "The specified attachment was not found. "},
56        {MAPI_E_ATTACHMENT_OPEN_FAILURE, "The specified attachment could not be opened. "},
57        {MAPI_E_BAD_RECIPTYPE, "The type of a recipient was not MAPI_TO, MAPI_CC, or MAPI_BCC. "},
58        {MAPI_E_INSUFFICIENT_MEMORY, "There was insufficient memory to proceed." },
59        {MAPI_E_INVALID_RECIPS, "One or more recipients were invalid or did not resolve to any address."},
60        {MAPI_E_LOGIN_FAILURE, "There was no default logon, and the user failed to log on successfully when the logon dialog box was displayed."},
61        {MAPI_E_TEXT_TOO_LARGE, "The text in the message was too large."},
62        {MAPI_E_TOO_MANY_FILES, "There were too many file attachments."},
63        {MAPI_E_TOO_MANY_RECIPIENTS, "There were too many recipients."},
64        {MAPI_E_UNKNOWN_RECIPIENT, "A recipient did not appear in the address list."},
65        {MAPI_E_USER_ABORT, "The user canceled one of the dialog boxes."},
66        {SUCCESS_SUCCESS, "The call succeeded and the message was sent."},
67        {0, NULL}
68    };
69    
70    
71    /* Return a human readable MAPI error based on the given error @err. */
72    const char*
73    mapi_strerror (int err)
74    {
75        int i;
76    
77        for (i=0; mapi_errors[i].msg; i++) {
78            if (err == mapi_errors[i].err_no)
79                return mapi_errors[i].msg;
80        }
81        return mapi_errors[0].msg;
82    }
83    
84    
85    /* Load MAPI library and set function pointers.
86       Return value: 0 on success. */
87  int  int
88  mapi_init (void)  mapi_init (void)
89  {  {
# Line 64  mapi_init (void) Line 103  mapi_init (void)
103      init = 1;      init = 1;
104    
105      return 0;      return 0;
106  } /* mapi_init */  }
107    
108    
109    /* Free library and cleanup. */
110  void  void
111  mapi_deinit (void)  mapi_deinit (void)
112  {  {
113      if (hlib) {      if (!hlib)
114          FreeLibrary (hlib);          return;
115          hlib = NULL;      FreeLibrary (hlib);
116          init = 0;      hlib = NULL;
117      }      init = 0;
118  } /* mapi_deinit */  }
119    
120    
121  #if 0 /* low:priority XXX port the code */  /* Send the file given in @ascfile via the MAPI mechanism. */
122  int  int
123  mapi_send_ascfile (char *ascfile)  mapi_send_ascfile (char *ascfile)
124  {  {
# Line 89  mapi_send_ascfile (char *ascfile) Line 130  mapi_send_ascfile (char *ascfile)
130    
131      rc = mapi_logon (0, NULL, NULL, MAPI_LOGON_UI, 0, &hd);      rc = mapi_logon (0, NULL, NULL, MAPI_LOGON_UI, 0, &hd);
132      if (rc != SUCCESS_SUCCESS) {      if (rc != SUCCESS_SUCCESS) {
133          MessageBox (NULL, _("MAPI Login failed."), "MAPI", MB_ICONWARNING|MB_OK);          MessageBox (NULL, mapi_strerror (rc), _("MAPI Login failed"), MB_WARN);
134          goto fail;          goto fail;
135      }      }
136      rc = mapi_send_documents (0, ";", ascfile, NULL, 0);      rc = mapi_send_documents (0, ";", ascfile, NULL, 0);
# Line 104  fail: Line 145  fail:
145  }  }
146    
147    
 int  
 mapi_send_pubkey (const char *keyid, char *keyfile)  
 {  
     LHANDLE hd;  
     const char * fmt;  
     char * keyinf = NULL;  
     int rc;  
   
     if (!init)  
         return 0;  
   
     fmt = _("GPG Public Key of %s");  
     keyinf = new char[strlen (fmt) + strlen (keyid) + 2];  
     if (!keyinf)  
         BUG (0);  
     sprintf (keyinf, fmt, keyid);  
     rc = mapi_logon (0, NULL, NULL, MAPI_LOGON_UI, 0, &hd);  
     if (rc != SUCCESS_SUCCESS) {  
         MessageBox (NULL, _("MAPI Login failed."), "MAPI", MB_ICONWARNING|MB_OK);  
         goto fail;  
     }  
     rc = mapi_send_documents (0, ";", keyfile, keyinf, 0);  
     if (rc == MAPI_E_USER_ABORT)  
         rc = SUCCESS_SUCCESS;  
     if (rc != SUCCESS_SUCCESS)  
         MessageBox (NULL, _("Could not sent mail."), "MAPI", MB_ICONERROR|MB_OK);  
   
 fail:  
     mapi_logoff (hd, 0, 0, 0);  
     free_if_alloc (keyinf);  
     return rc;  
 } /* mapi_send_pubkey */  
   
   
148  static void  static void
149  free_mapi_msg (MapiMessage * msg)  free_mapi_msg (MapiMessage *msg)
150  {  {
151      if (!msg)      if (!msg)
152          return;          return;
153      safe_free (msg->lpszSubject);      safe_free (msg->lpszSubject);
154      safe_free (msg->lpszNoteText);      safe_free (msg->lpszNoteText);
155      safe_free (msg);      safe_free (msg);
156  } /* free_mapi_msg */  }
157    
158    
159  static void  static void
160  free_recip_tab (MapiRecipDesc *recip, size_t n)  free_recip_tab (MapiRecipDesc *recip, DWORD n)
161  {  {
162      size_t i;      DWORD i;
163    
164      if (!recip)      if (!recip)
165          return;          return;
# Line 161  free_recip_tab (MapiRecipDesc *recip, si Line 168  free_recip_tab (MapiRecipDesc *recip, si
168      for (i=0; i < n; i++)      for (i=0; i < n; i++)
169          safe_free (recip[i].lpszName);          safe_free (recip[i].lpszName);
170      safe_free (recip);      safe_free (recip);
171  } /* free_recip_tab */  }
172    
173    
174  static void  static void
175  free_files_tab (MapiFileDesc * files, size_t n)  free_files_tab (MapiFileDesc *files, DWORD n)
176  {  {
177      size_t i;      DWORD i;
178    
179      if (!files)      if (!files)
180          return;          return;
# Line 178  free_files_tab (MapiFileDesc * files, si Line 185  free_files_tab (MapiFileDesc * files, si
185          safe_free (files[i].lpszPathName);          safe_free (files[i].lpszPathName);
186      }      }
187      safe_free (files);      safe_free (files);
188  } /* free_files_tab */  }
   
   
   
 static gpgme_recipients_t  
 conv_recipients (gpgme_recipients_t rset)  
 {  
     gpgme_recipients_t r;  
     gpgme_error_t rc;  
     void * ctx=NULL;  
     const char * s;  
   
     /* we need to convert the recipients to email addresses so  
        GPG can handle them. */  
     rc = gpgme_recipients_new (&r);  
     if (rc)  
         return NULL;  
     gpgme_recipients_enum_open (rset, &ctx);  
   
     while ((s=gpgme_recipients_enum_read (rset, &ctx))) {  
         char * p, * q, * buf;  
         if (!(p = strchr (s, '<')) || !(q = strchr (s, '>')))  
             continue;  
         buf = (char * )calloc (1, (q-s)-(p-s)+2);  
         if (!buf)  
             BUG (0);  
         strncpy (buf, s+(p-s)+1, (q-s)-(p-s)-1);  
         gpgme_recipients_add_name (r, buf);  
         safe_free (buf);  
     }  
     return r;  
 } /* conv_recipients */  
   
   
 static char *  
 secure_attachment (gpgme_recipients_t rset, const char *fname)  
 {  
     char tmpdir[512+32], * p;  
     gpgme_recipients_t addrs;  
     gpgme_ctx_t ctx;  
     gpgme_error_t rc;  
   
     if (strlen (fname) > 200)  
         BUG (0);  
     GetTempPath (sizeof tmpdir-200, tmpdir);  
     p = strrchr (fname, '\\');  
     if (!p)  
         strcat (tmpdir, fname);  
     else  
         strcat (tmpdir, fname+(p-fname)+1);  
     strcat (tmpdir, ".asc");  
   
     rc = gpgme_new (&ctx);  
     if (rc)  
         return NULL;  
     gpgme_set_armor (ctx, 1);  
     addrs = conv_recipients (rset);  
     if (!addrs) {  
         msg_box (NULL, _("No valid mail addresses found."), _("Secure Attachment"), MB_ERR);  
         gpgme_release (NULL);  
         return NULL;  
     }  
     rc = gpgme_op_file_encrypt (ctx, addrs, fname, tmpdir);  
     if (rc)  
         log_box (_("Secure Attachment"), MB_ERR, _("Could not encrypt '%s'"), fname);  
     gpgme_recipients_release (addrs);  
     gpgme_release (ctx);  
     return strdup (tmpdir);  
 } /* secure_attachment */  
   
   
 static gpgme_error_t  
 secure_message (gpgme_recipients_t rset, const char *data,  
                 char *enc_msg, size_t *r_enclen)  
 {  
     gpgme_recipients_t addrs;  
     gpgme_error_t rc;  
     gpgme_data_t in, out;  
     gpgme_ctx_t ctx;  
     char * p;  
     size_t n=0;  
   
     rc = gpgme_new (&ctx);  
     if (rc)  
         return NULL;  
     gpgme_set_armor (ctx, 1);  
   
     addrs = conv_recipients (rset);  
     rc = gpgme_data_new_from_mem (&in, data, strlen (data), 1);  
     if (rc) {  
         gpgme_release (ctx);  
         return rc;  
     }  
     gpgme_data_new (&out);  
     rc = gpgme_op_encrypt (ctx, addrs, GPGME_ENCRYPT_ALWAYS_TRUST, in, out);  
     if (rc)  
         log_box (_("Secure Message"), MB_ERR, "Could not encrypt the data");  
   
     *r_enc_msg = gpgme_data_release_and_get_mem (&n);  
     *r_enclen = n;  
   
     gpgme_data_release (in);  
     gpgme_release (ctx);  
     gpgme_recipients_release (addrs);  
   
     return rc;  
 } /* secure_message */  
189    
190    
191    /* Same as mapi_send_pubkey but there is an additional note. */
192  int  int
193  mapi_send_message (gpgme_recipients_t rset, const char * msgtxt,  mapi_send_pubkey_ext (winpt_key_t key, const char *keyfile, int flags)
                    const char * subject, const char **files, size_t nfiles)  
194  {  {
195      LHANDLE hd;      LHANDLE hd;
196      MapiMessage * msg;      MapiMessage *msg;
197      MapiRecipDesc * recip;      MapiRecipDesc *recip;
198      MapiFileDesc * attch;      MapiFileDesc *attch;
199      char * p;      char *p, *kinf;
200      const char * s;      const char *s;
     void * ctx=NULL;  
     size_t n, i=0, encmsg_len=0;  
201      int rc;      int rc;
202    
203      if (!init)      if (!init)
# Line 306  mapi_send_message (gpgme_recipients_t rs Line 205  mapi_send_message (gpgme_recipients_t rs
205    
206      rc = mapi_logon (0, NULL, NULL, MAPI_LOGON_UI, 0, &hd);      rc = mapi_logon (0, NULL, NULL, MAPI_LOGON_UI, 0, &hd);
207      if (rc != SUCCESS_SUCCESS) {      if (rc != SUCCESS_SUCCESS) {
208          MessageBox (NULL, "MAPI Login failed.", "MAPI", MB_ICONWARNING|MB_OK);          MessageBox (NULL, mapi_strerror (rc), _("MAPI Login failed"), MB_WARN);
209          return rc;          return rc;
210      }      }
211    
212      msg = (MapiMessage *)calloc (1, sizeof * msg);      msg = (MapiMessage *)calloc (1, sizeof *msg);
213      if (!msg)      if (!msg)
214          BUG (0);          BUG (0);
215      p = msg->lpszSubject = strdup (subject);      p = msg->lpszSubject = strdup ("OpenPGP Public Key");
216      if (!p)      if (!p)
217          BUG (0);          BUG (0);
218      p = msg->lpszNoteText = secure_message (rset, msgtxt, &p, &encmsg_len);  
219        s = "Attached is this OpenPGP public key:\n%s\n\n"
220            "Import this key via the clipboard or the Key Manager to\n"
221            "exchange encrypted mails with the key holder and to be able\n"
222            "to verify its signatures.\n"
223            "\n"
224            "If you don't have WinPT, you can download it at http://www.winpt.org";
225        kinf = km_key_get_info (key, 0);
226        p = (char*)malloc (strlen (s) + strlen (kinf) + 2);
227        sprintf (p, s, kinf);
228        free_if_alloc (kinf);
229    
230        p = msg->lpszNoteText = p;
231      if (!p)      if (!p)
232          BUG (0);          BUG (0);
     n = msg->nRecipCount = gpgme_recipients_count (rset);  
     recip = (MapiRecipDesc *)calloc (n+1, sizeof * recip);  
     if (!recip)  
         BUG (0);  
       
     gpgme_recipients_enum_open (rset, &ctx);  
     while ((s = gpgme_recipients_enum_read (rset, &ctx))) {  
         if (!i)  
             recip[i].ulRecipClass = MAPI_TO;  
         else  
             recip[i].ulRecipClass = MAPI_CC;      
         p = recip[i].lpszName = strdup (s);  
         if (!p)  
             BUG (0);  
         i++;  
     }  
     msg->lpRecips = recip;  
233    
234      if (nfiles) {      /* If the key was signed, we assume it shall be sent back to the owner. */
235          msg->nFileCount = nfiles;      if (flags) {
236          attch = (MapiFileDesc *)calloc (nfiles+1, sizeof * attch);          recip = (MapiRecipDesc *)calloc (1, sizeof *recip);
237          if (!attch)          if (!recip)
238                BUG (0);
239            recip[0].ulRecipClass = MAPI_TO;
240            p = recip[0].lpszName = strdup (key->ext->uids->uid);
241            if (!p)    
242              BUG (0);              BUG (0);
243          for (i=0; i < nfiles; i++) {          msg->lpRecips = recip;
244              char * p = secure_attachment (rset, *files);          msg->nRecipCount = 1;
             if (!p)  
                 continue;  
             attch[i].lpszFileName = strdup (*files);          
             attch[i].lpszPathName = strdup (p);  
             files++;  
             safe_free (p);  
         }  
         msg->lpFiles = attch;  
245      }      }
246        else {
247            msg->lpRecips = recip = NULL;
248            msg->nRecipCount = 0;
249        }
250    
251        msg->nFileCount = 1;
252        attch = (MapiFileDesc *)calloc (1, sizeof *attch);
253        if (!attch)
254            BUG (0);
255        attch[0].lpszFileName = strdup (keyfile);
256        attch[0].lpszPathName = strdup (keyfile);
257        msg->lpFiles = attch;
258    
259      rc = mapi_send_mail (hd, 0, msg, 0, 0);      rc = mapi_send_mail (hd, 0, msg, MAPI_DIALOG , 0);
260      if (rc == MAPI_E_USER_ABORT)      if (rc == MAPI_E_USER_ABORT)
261          rc = SUCCESS_SUCCESS;          rc = SUCCESS_SUCCESS;
262      if (rc != SUCCESS_SUCCESS)      if (rc != SUCCESS_SUCCESS)
263          MessageBox (NULL, _("Could not sent mail."), "MAPI", MB_ERR);          MessageBox (NULL, _("Could not sent mail."), "MAPI", MB_ERR);
264    
265      free_recip_tab (recip, n);      free_recip_tab (recip, 1);
266      free_files_tab (attch, nfiles);      free_files_tab (attch, 1);
267      free_mapi_msg (msg);      free_mapi_msg (msg);
     gpgme_free (p);  
268      mapi_logoff (hd, 0, 0, 0);      mapi_logoff (hd, 0, 0, 0);
269    
270      return 0;      return 0;
271  } /* mapi_send_message */  }
   
   
 static int  
 add_recipient (gpgme_recipients_t * r_rset, const char * addr)  
 {  
     gpg_keycache_t pub = keycache_get_ctx (1);  
     gpgme_key_t key;  
     gpgme_error_t rc;  
     const char * s;  
   
     if (!*r_rset)  
         gpgme_recipients_new (&(*r_rset));  
     rc = gpgme_keycache_find_key (pub, addr, 0, &key);  
     if (rc) {  
         log_box (_("Add Recipient"), MB_ERR, _("Could not find key for '%s'"), addr);  
         return -1;  
     }  
     s = key->uids->uid;  
     if (s)  
         gpgme_recipients_add_name (*r_rset, s);  
     return 0;  
 } /* add_recipient */  
   
   
 static int  
 add_all_recipients (HWND dlg, int itemid, gpgme_recipients_t * r_rset)  
 {      
     char buf[1024], * p;  
     int n=0;  
272    
     n = GetDlgItemText (dlg, itemid, buf, sizeof buf-10);  
     if (!n)  
         return -1;  
     p = strtok (buf, ";,");  
     while (p != NULL) {  
         add_recipient (&*r_rset, p);  
         p = strtok (NULL, ";,");  
     }  
     return 0;  
 } /* add_all_recipients */  
273    
274    
275  BOOL CALLBACK  int
276  winpt_mail_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  mapi_send_pubkey (const char *keyid, char *keyfile)
277  {  {
278      static gpgme_recipients_t rset=NULL;      winpt_key_s key;
     char subject[128];  
     char * msgbuf;  
     int n;  
   
     switch (msg) {  
     case WM_INITDIALOG:  
         center_window (dlg, NULL);  
         SetForegroundWindow (dlg);  
         break;  
   
     case WM_COMMAND:  
         switch (LOWORD (wparam)) {  
         case IDOK:  
             add_all_recipients (dlg, IDC_PMAIL_TO, &rset);  
             add_all_recipients (dlg, IDC_PMAIL_CC, &rset);  
             if (!gpgme_recipients_count (rset)) {  
                 msg_box (dlg, _("Please enter a recipient."), _("Mail"), MB_ERR);  
                 return FALSE;  
             }  
             n=GetDlgItemText (dlg, IDC_PMAIL_SUBJECT, subject, sizeof subject-1);  
             if (!n)  
                 strcpy (subject, "");  
             n = SendDlgItemMessage (dlg, IDC_PMAIL_MSG, WM_GETTEXTLENGTH, 0, 0);  
             if (!n) {  
                 msg_box (dlg, _("Please enter a message."), _("Mail"), MB_ERR);  
                 return FALSE;  
             }  
             msgbuf = (char * )calloc (1, n+2);  
             if (!msgbuf)  
                 BUG (0);  
             GetDlgItemText (dlg, IDC_PMAIL_MSG, msgbuf, n+1);  
             mapi_send_message (rset, msgbuf, subject, NULL, 0);  
             safe_free (msgbuf);  
             EndDialog (dlg, TRUE);  
             break;  
   
         case IDCANCEL:  
             EndDialog (dlg, FALSE);  
             break;  
         }  
         break;  
     }  
279    
280      return FALSE;      memset (&key, 0, sizeof (key));
281  } /* winpt_mail_proc */      if (winpt_get_pubkey (keyid, &key))
282  #endif          return -1;
283        return mapi_send_pubkey_ext (&key, keyfile, 0);
284    }

Legend:
Removed from v.36  
changed lines
  Added in v.244

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26