/[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 77 by twoaday, Mon Nov 14 15:01:01 2005 UTC revision 317 by twoaday, Fri May 25 14:53:02 2007 UTC
# Line 1  Line 1 
1  /* wptMAPI.cpp  /* wptMAPI.cpp - MAPI interface for sending keys.
2   *      Copyright (C) 2003, 2004, 2005 Timo Schulz   *      Copyright (C) 2003-2006 Timo Schulz
3   *   *
4   * This file is part of WinPT.   * This file is part of WinPT.
5   *   *
# Line 25  Line 25 
25  #include <stdio.h>  #include <stdio.h>
26  #include <mapi.h>  #include <mapi.h>
27    
 extern HINSTANCE glob_hinst;  
   
28  #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 44  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.  /* Load MAPI library and set function pointers.
86     Return value: 0 on success. */     Return value: 0 on success. */
87  int  int
# Line 72  mapi_init (void) Line 110  mapi_init (void)
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  }  }
119    
120    
# Line 92  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);
137      if (rc == MAPI_E_USER_ABORT)      if (rc == MAPI_E_USER_ABORT)
138          rc = SUCCESS_SUCCESS;          rc = SUCCESS_SUCCESS;
139      if (rc != SUCCESS_SUCCESS)      if (rc != SUCCESS_SUCCESS)
140          MessageBox (NULL, _("Could not sent mail."), "MAPI", MB_ICONERROR|MB_OK);          MessageBox (NULL, _("Could not send mail."), "MAPI", MB_ICONERROR|MB_OK);
141    
142  fail:  fail:
143      mapi_logoff (hd, 0, 0, 0);      mapi_logoff (hd, 0, 0, 0);
# Line 107  fail: Line 145  fail:
145  }  }
146    
147    
 /* Send a public key stored in @keyfile with the keyid @keyid  
    via the MAPI mechanism to a mail recipient.  
    Return value: SUCCESS_SUCCESS on succes. */  
 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;  
 }  
   
   
 #if 0 /* low:priority XXX port the code */  
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 168  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 185  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 313  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.eu";
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);              BUG (0);
239          for (i=0; i < nfiles; i++) {          recip[0].ulRecipClass = MAPI_TO;
240              char * p = secure_attachment (rset, *files);          p = recip[0].lpszName = strdup (key->ext->uids->uid);
241              if (!p)          if (!p)    
242                  continue;              BUG (0);
243              attch[i].lpszFileName = strdup (*files);                  msg->lpRecips = recip;
244              attch[i].lpszPathName = strdup (p);          msg->nRecipCount = 1;
245              files++;      }
246              safe_free (p);      else {
247          }          msg->lpRecips = recip = NULL;
248          msg->lpFiles = attch;          msg->nRecipCount = 0;
249      }      }
250    
251      rc = mapi_send_mail (hd, 0, msg, 0, 0);      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, 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 */  
272    
273    
 static int  
 add_all_recipients (HWND dlg, int itemid, gpgme_recipients_t * r_rset)  
 {      
     char buf[1024], * p;  
     int n=0;  
274    
275      n = GetDlgItemText (dlg, itemid, buf, sizeof buf-10);  int
276      if (!n)  mapi_send_pubkey (const char *keyid, char *keyfile)
         return -1;  
     p = strtok (buf, ";,");  
     while (p != NULL) {  
         add_recipient (&*r_rset, p);  
         p = strtok (NULL, ";,");  
     }  
     return 0;  
 } /* add_all_recipients */  
   
   
 BOOL CALLBACK  
 winpt_mail_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  
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.77  
changed lines
  Added in v.317

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26