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

Diff of /trunk/Src/wptCardDlg.cpp

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

revision 30 by twoaday, Sat Oct 22 10:17:59 2005 UTC revision 36 by werner, Thu Oct 27 15:25:13 2005 UTC
# Line 1  Line 1 
1  /* wptCardDlg.cpp - Smart Card support  /* wptCardDlg.cpp - Smart Card support
2   *      Copyright (C) 2003, 2004, 2005 Timo Schulz   *      Copyright (C) 2003, 2004, 2005 Timo Schulz
3   *      Copyright (C) 2005 g10 Code GmbH   *      Copyright (C) 2005 g10 Code GmbH
4   *   *
5   * This file is part of WinPT.   * This file is part of WinPT.
6   *   *
7   * WinPT is free software; you can redistribute it and/or modify   * WinPT is free software; you can redistribute it and/or modify
8   * it under the terms of the GNU General Public License as published by   * it under the terms of the GNU General Public License as published by
9   * the Free Software Foundation; either version 2 of the License, or   * the Free Software Foundation; either version 2 of the License, or
10   * (at your option) any later version.   * (at your option) any later version.
11   *   *
12   * WinPT is distributed in the hope that it will be useful,   * WinPT is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Public License for more details.   * GNU General Public License for more details.
16   *   *
17   * You should have received a copy of the GNU General Public License   * You should have received a copy of the GNU General Public License
18   * along with WinPT; if not, write to the Free Software Foundation,   * along with WinPT; if not, write to the Free Software Foundation,
19   * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA   * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20   */   */
21    
22  #include <windows.h>  #ifdef HAVE_CONFIG_H
23  #include <commctrl.h>  #include <config.h>
24  #include <ctype.h>  #endif
25    
26  #include "../resource.h"  #include <windows.h>
27  #include "gpgme.h"  #include <windows.h>
28  #include "wptTypes.h"  #include <commctrl.h>
29  #include "wptW32API.h"  #include <ctype.h>
30  #include "wptErrors.h"  
31  #include "wptRegistry.h"  #include "../resource.h"
32  #include "wptVersion.h"  #include "gpgme.h"
33  #include "wptCommonCtl.h"  #include "wptTypes.h"
34  #include "wptDlgs.h"  #include "wptW32API.h"
35  #include "wptGPG.h"  #include "wptErrors.h"
36  #include "wptUTF8.h"  #include "wptRegistry.h"
37  #include "wptCardEdit.h"  #include "wptVersion.h"
38  #include "wptCard.h"  #include "wptCommonCtl.h"
39  #include "wptContext.h"  #include "wptDlgs.h"
40    #include "wptGPG.h"
41  int keygen_check_date (SYSTEMTIME * st);  #include "wptUTF8.h"
42    #include "wptCardEdit.h"
43  static const char * sex[] = {"Male", "Female", "Undefined", NULL};  #include "wptCard.h"
44  static const char * lang[] = {"Undefined", "cs", "de", "en", "es", "fr", "hu",  #include "wptContext.h"
45                                "it", "nl", "pt", "ro", "ru", "zh", "at",  
46                                NULL};  int keygen_check_date (SYSTEMTIME * st);
47    
48  static pin_cb_ctx_s pincb;  static const char * sex[] = {"Male", "Female", "Undefined", NULL};
49    static const char * lang[] = {"Undefined", "cs", "de", "en", "es", "fr", "hu",
50  struct {                                "it", "nl", "pt", "ro", "ru", "zh", "at",
51      int ctlid;                                NULL};
52      const char * err;  
53  } attr_tab[] = {  static pin_cb_ctx_s pincb;
54      {IDC_CEDIT_AID,    ""},  
55      {IDC_CEDIT_VENDOR, "No Vendor"},  struct {
56      {IDC_CEDIT_VERSION,"No Version"},      int ctlid;
57      {IDC_CEDIT_SERIAL, "No Serial-No"},      const char * err;
58      {IDC_CEDIT_NAME,   "No Name"},  } attr_tab[] = {
59      {IDC_CEDIT_NAME2,  "No Surname"},      {IDC_CEDIT_AID,    ""},
60      {IDC_CEDIT_KEYURL, "No Key-URL"},      {IDC_CEDIT_VENDOR, "No Vendor"},
61      {IDC_CEDIT_LOGIN,  "No Login name"},          {IDC_CEDIT_VERSION,"No Version"},
62      {0},      {IDC_CEDIT_SERIAL, "No Serial-No"},
63  };      {IDC_CEDIT_NAME,   "No Name"},
64        {IDC_CEDIT_NAME2,  "No Surname"},
65        {IDC_CEDIT_KEYURL, "No Key-URL"},
66        {IDC_CEDIT_LOGIN,  "No Login name"},    
67  /* XXX: simplify code. */      {0},
68  char*  };
69  get_printable_version (const char *version)  
70  {  
71      static char buf[16];  
72      char tmp_maj[3]={0}, tmp_min[3]={0};  /* XXX: simplify code. */
73    char*
74      strncpy (tmp_maj, version, 2);  get_printable_version (const char *version)
75      strncpy (tmp_min, version+2, 2);  {
76      sprintf (buf, "%d.%d", atoi (tmp_maj), atoi (tmp_min));      static char buf[16];
77      return buf;      char tmp_maj[3]={0}, tmp_min[3]={0};
78  }  
79        strncpy (tmp_maj, version, 2);
80  /* Return all card attributes from @card. @n contains      strncpy (tmp_min, version+2, 2);
81     the number of items which were returned. */      sprintf (buf, "%d.%d", atoi (tmp_maj), atoi (tmp_min));
82  char**      return buf;
83  card_get_items (gpg_card_t card, int *n)  }
84  {  
85      char **p;  /* Return all card attributes from @card. @n contains
86       the number of items which were returned. */
87      *n= 8;  char**
88      p = (char **)calloc (*n+1, sizeof (char*));  card_get_items (gpg_card_t card, int *n)
89      if (!p)  {
90          BUG (0);      char **p;
91      p[0] = card->aid;  
92      p[1] = card->vendor;      *n= 8;
93      p[2] = get_printable_version (card->version);      p = (char **)calloc (*n+1, sizeof (char*));
94      p[3] = card->serial;      if (!p)
95      p[4] = card->givenname;          BUG (0);
96      p[5] = card->surname;      p[0] = card->aid;
97      p[6] = card->url;      p[1] = card->vendor;
98      p[7] = card->login;      p[2] = get_printable_version (card->version);
99      return p;      p[3] = card->serial;
100  }      p[4] = card->givenname;
101        p[5] = card->surname;
102        p[6] = card->url;
103  static int      p[7] = card->login;
104  idx_from_lang (const char * _lang)      return p;
105  {  }
106      const char * s;  
107      int i;  
108    static int
109      if (!_lang)  idx_from_lang (const char * _lang)
110          return 0;  {
111      for (i=0; (s = lang[i]); i++) {      const char * s;
112          if (!strcmp (_lang, s ))      int i;
113              return i;  
114      }      if (!_lang)
115      return 0;          return 0;
116  }      for (i=0; (s = lang[i]); i++) {
117            if (!strcmp (_lang, s ))
118                return i;
119  #if 0 /* @unused@ */      }
120  int      return 0;
121  show_card_status (void)  }
122  {  
123      int rc = 0;  
124      int cardstat;  #if 0 /* @unused@ */
125    int
126      cardstat = pcsc_get_card_status ();  show_card_status (void)
127      if ((cardstat & CARD_STATE_UNAWARE) || (cardstat & CARD_STATE_UNAVAIL))  {
128          rc = WPTERR_NOREADER;      int rc = 0;
129      else if (cardstat & CARD_STATE_EMPTY)      int cardstat;
130          rc = WPTERR_NOCARD;      
131      if (rc) {      cardstat = pcsc_get_card_status ();
132          msg_box (NULL, winpt_strerror (rc), _("Card Manager"), MB_ERR);      if ((cardstat & CARD_STATE_UNAWARE) || (cardstat & CARD_STATE_UNAVAIL))
133          return -1;          rc = WPTERR_NOREADER;
134      }      else if (cardstat & CARD_STATE_EMPTY)
135      return 0;          rc = WPTERR_NOCARD;    
136  } /* show_card_status */      if (rc) {
137  #endif          msg_box (NULL, winpt_strerror (rc), _("Card Manager"), MB_ERR);
138            return -1;
139  /* Check if there is a card in the reader and analyze the      }
140     returned information.      return 0;
141     Return value: card context or NULL on error. */  } /* show_card_status */
142  gpg_card_t  #endif
143  gpg_card_load (void)  
144  {  /* Check if there is a card in the reader and analyze the
145      gpgme_error_t err;     returned information.
146      GpgCardEdit *ce;     Return value: card context or NULL on error. */
147      gpg_card_t card = NULL;  gpg_card_t
148      struct card_cb_s cb = {0};  gpg_card_load (void)
149        {
150      ce = new GpgCardEdit ();      gpgme_error_t err;
151      if (!ce)      GpgCardEdit *ce;
152          BUG (0);      gpg_card_t card = NULL;
153      memset (&cb, 0, sizeof (cb));      struct card_cb_s cb = {0};
154      ce->setCallback (card_callback, &cb);      
155      err = ce->getCardStatus (&card);      ce = new GpgCardEdit ();
156      if (err) {      if (!ce)
157          msg_box (NULL, gpgme_strerror (err), _("Card Manager"), MB_ERR);          BUG (0);
158          goto leave;      memset (&cb, 0, sizeof (cb));
159      }      ce->setCallback (card_callback, &cb);
160        err = ce->getCardStatus (&card);
161      if (!card->aid || strncmp (card->aid, "D276000124", 10)) {      if (err) {
162          msg_box (NULL, winpt_strerror (WPTERR_NOPGPCARD), "WinPT", MB_ERR);          msg_box (NULL, gpgme_strerror (err), _("Card Manager"), MB_ERR);
163          gpg_card_release (card);          goto leave;
164          card = NULL;      }
165      }  
166      else {      if (!card->aid || strncmp (card->aid, "D276000124", 10)) {
167          struct winpt_key_s key;          msg_box (NULL, winpt_strerror (WPTERR_NOPGPCARD), "WinPT", MB_ERR);
168          memset (&key, 0, sizeof (key));          gpg_card_release (card);
169          winpt_get_pubkey (card->fpr[1]+32, &key);          card = NULL;
170          if (key.ext) {      }
171              key.ext->card_type = strdup (card->card_type);      else {
172              if (!key.ext->card_type)          struct winpt_key_s key;
173                  BUG (NULL);          memset (&key, 0, sizeof (key));
174              /* memory will be released in gpg_keycache_release (). */          winpt_get_pubkey (card->fpr[1]+32, &key);
175          }          if (key.ext) {
176      }              key.ext->card_type = strdup (card->card_type);
177                if (!key.ext->card_type)
178  leave:                  BUG (NULL);
179      delete ce;              /* memory will be released in gpg_keycache_release (). */
180      return card;          }
181  }      }
182    
183    leave:
184  /* Print human friendly fingerprint to control @id in the      delete ce;
185     dialog @dlg. @fpr contains the raw fingerprint. */      return card;
186  static void  }
187  print_fpr (HWND dlg, int id, const char * fpr)  
188  {  
189      char buf[128], dig[2];      /* Print human friendly fingerprint to control @id in the
190      size_t i, c;     dialog @dlg. @fpr contains the raw fingerprint. */
191    static void
192      if (!fpr)  print_fpr (HWND dlg, int id, const char * fpr)
193          strcpy (buf, _("No Fingerprint"));  {
194      else {      char buf[128], dig[2];    
195          memset (buf, 0, sizeof (buf));      size_t i, c;
196          for( i=0, c=0; i < strlen (fpr); i++) {  
197              dig[0] = fpr[i]; dig[1] = 0;      if (!fpr)
198              strcat (buf, dig);          strcpy (buf, _("No Fingerprint"));
199              if (++c == 4) {      else {
200                  strcat (buf, " ");          memset (buf, 0, sizeof (buf));
201                  c=0;          for( i=0, c=0; i < strlen (fpr); i++) {
202              }              dig[0] = fpr[i]; dig[1] = 0;
203          }              strcat (buf, dig);
204      }              if (++c == 4) {
205      SetDlgItemText (dlg, id, buf);                  strcat (buf, " ");
206  }                  c=0;
207                }
208            }
209  /* Fill in all card information from @card. into the corresponding      }
210     dialog item fields in the dialog @dlg.      SetDlgItemText (dlg, id, buf);
211     Return value: 0 on success. */  }
212  static int  
213  card_status (HWND dlg, gpg_card_t card)  
214  {  /* Fill in all card information from @card. into the corresponding
215      static int fprbuf[] = {IDC_CEDIT_FPR1, IDC_CEDIT_FPR2, IDC_CEDIT_FPR3, 0};     dialog item fields in the dialog @dlg.
216      static int fprtime[] = {IDC_CEDIT_SIG_FPRTIME, IDC_CEDIT_DEC_FPRTIME, IDC_CEDIT_AUTH_FPRTIME, 0};     Return value: 0 on success. */
217      const char *s;  static int
218      char **attrs;  card_status (HWND dlg, gpg_card_t card)
219      char cardinf[128];  {
220      int idx=0, n=0;      static int fprbuf[] = {IDC_CEDIT_FPR1, IDC_CEDIT_FPR2, IDC_CEDIT_FPR3, 0};
221        static int fprtime[] = {IDC_CEDIT_SIG_FPRTIME, IDC_CEDIT_DEC_FPRTIME, IDC_CEDIT_AUTH_FPRTIME, 0};
222      if (!card->aid) {      const char *s;
223          msg_box( dlg, _("No OpenPGP smart card detected."), "WinPT", MB_ERR );      char **attrs;
224          return -1;      char cardinf[128];
225      }      int idx=0, n=0;
226      SetDlgItemText (dlg, IDC_CEDIT_AID, card->aid);  
227      SetDlgItemInt (dlg, IDC_CEDIT_SIGCOUNT, card->sig_count, TRUE);      if (!card->aid) {
228            msg_box( dlg, _("No OpenPGP smart card detected."), "WinPT", MB_ERR );
229      for (idx=0; fprbuf[idx]; idx++) {          return -1;
230          print_fpr (dlg, fprbuf[idx], card->fpr[idx]);      }
231          SetDlgItemText (dlg, fprtime[idx], card->fpr_created_str[idx]);      SetDlgItemText (dlg, IDC_CEDIT_AID, card->aid);
232      }      SetDlgItemInt (dlg, IDC_CEDIT_SIGCOUNT, card->sig_count, TRUE);
233    
234      attrs = card_get_items (card, &n);      for (idx=0; fprbuf[idx]; idx++) {
235      for (idx=1; attr_tab[idx].ctlid; idx++) {          print_fpr (dlg, fprbuf[idx], card->fpr[idx]);
236          s = attrs[idx];          SetDlgItemText (dlg, fprtime[idx], card->fpr_created_str[idx]);
237          SetDlgItemText (dlg, attr_tab[idx].ctlid, s && *s? s : attr_tab[idx].err);      }
238      }  
239      free (attrs);      attrs = card_get_items (card, &n);
240        for (idx=1; attr_tab[idx].ctlid; idx++) {
241      idx = idx_from_lang (card->lang);              s = attrs[idx];
242      SendDlgItemMessage (dlg, IDC_CEDIT_LANG, CB_SETCURSEL, (WPARAM)idx, 0);          SetDlgItemText (dlg, attr_tab[idx].ctlid, s && *s? s : attr_tab[idx].err);
243        }
244      switch (card->sex) {      free (attrs);
245      case 'm': idx=0; break;  
246      case 'f': idx=1; break;      idx = idx_from_lang (card->lang);    
247      default :      SendDlgItemMessage (dlg, IDC_CEDIT_LANG, CB_SETCURSEL, (WPARAM)idx, 0);
248      case 'u': idx=2; break;  
249      }      switch (card->sex) {
250      SendDlgItemMessage (dlg, IDC_CEDIT_SEX, CB_SETCURSEL, (WPARAM)idx, 0);      case 'm': idx=0; break;
251        case 'f': idx=1; break;
252      s = card->serial;      default :
253      while (s && *s == '0') s++;      case 'u': idx=2; break;
254      _snprintf (cardinf, sizeof (cardinf)-1,      }
255                 "Card Edit - %s serial no. %s version %s",      SendDlgItemMessage (dlg, IDC_CEDIT_SEX, CB_SETCURSEL, (WPARAM)idx, 0);
256                 card->card_type, s, get_printable_version (card->version));  
257      SetWindowText (dlg, cardinf);      s = card->serial;
258        while (s && *s == '0') s++;
259      return 0;      _snprintf (cardinf, sizeof (cardinf)-1,
260  }                 "Card Edit - %s serial no. %s version %s",
261                   card->card_type, s, get_printable_version (card->version));
262        SetWindowText (dlg, cardinf);
263  /* Initialize the enum combox boxes in dialog @dlg. */  
264  static void      return 0;
265  prepare_dialog (HWND dlg)  }
266  {  
267      const char * s;  
268      int i;  /* Initialize the enum combox boxes in dialog @dlg. */
269    static void
270      for (i=0; (s = sex[i]); i++)  prepare_dialog (HWND dlg)
271          SendDlgItemMessage (dlg, IDC_CEDIT_SEX, CB_ADDSTRING, 0, (LPARAM) s);  {
272      SendDlgItemMessage (dlg, IDC_CEDIT_SEX, CB_SETCURSEL, 0, 0);      const char * s;
273      for (i=0; (s = lang[i]); i++)      int i;
274          SendDlgItemMessage (dlg, IDC_CEDIT_LANG, CB_ADDSTRING, 0, (LPARAM)s);  
275      SendDlgItemMessage (dlg, IDC_CEDIT_LANG, CB_SETCURSEL, 0, 0);      for (i=0; (s = sex[i]); i++)
276  }          SendDlgItemMessage (dlg, IDC_CEDIT_SEX, CB_ADDSTRING, 0, (LPARAM) s);
277        SendDlgItemMessage (dlg, IDC_CEDIT_SEX, CB_SETCURSEL, 0, 0);
278        for (i=0; (s = lang[i]); i++)
279  /* Return 0 if the given string @str has the proper format. */          SendDlgItemMessage (dlg, IDC_CEDIT_LANG, CB_ADDSTRING, 0, (LPARAM)s);
280  static int      SendDlgItemMessage (dlg, IDC_CEDIT_LANG, CB_SETCURSEL, 0, 0);
281  check_string (const char *str, int flags)  }
282  {  
283      size_t i;  
284      for (i=0; i < strlen (str); i++) {  /* Return 0 if the given string @str has the proper format. */
285          if (flags & 0x02 && !isalpha (str[i]))  static int
286              return -1;  check_string (const char *str, int flags)
287      }  {
288      return 0;      size_t i;
289  }      for (i=0; i < strlen (str); i++) {
290            if (flags & 0x02 && !isalpha (str[i]))
291                return -1;
292  static int      }
293  do_proc_card_cmds (HWND dlg, struct pin_cb_ctx_s *pincb, gpg_card_t card)      return 0;
294  {  }
295      static struct {  
296          int id;  
297          int cmd;  static int
298          int us_ascii;  do_proc_card_cmds (HWND dlg, struct pin_cb_ctx_s *pincb, gpg_card_t card)
299          int changed;  {
300      } idctl[] = {      static struct {
301          {IDC_CEDIT_NAME,  GPG_EDITCARD_NAME,  1,  0},          int id;
302          {IDC_CEDIT_LANG2, GPG_EDITCARD_LANG,  1,  0},          int cmd;
303          {IDC_CEDIT_SEX2,  GPG_EDITCARD_SEX,   1|1,0},          int us_ascii;
304          {IDC_CEDIT_KEYURL,GPG_EDITCARD_KEYURL,1|4,0},          int changed;
305          {IDC_CEDIT_LOGIN, GPG_EDITCARD_LOGIN, 1,  0},      } idctl[] = {
306          {0}          {IDC_CEDIT_NAME,  GPG_EDITCARD_NAME,  1,  0},
307      };              {IDC_CEDIT_LANG2, GPG_EDITCARD_LANG,  1,  0},
308      gpgme_error_t err;          {IDC_CEDIT_SEX2,  GPG_EDITCARD_SEX,   1|1,0},
309      GpgCardEdit *ce;          {IDC_CEDIT_KEYURL,GPG_EDITCARD_KEYURL,1|4,0},
310      char buf[256], tmp[128];          {IDC_CEDIT_LOGIN, GPG_EDITCARD_LOGIN, 1,  0},
311      int errc=0, use_arg2 = 0;          {0}
312      int i, id, n=0;      };    
313        gpgme_error_t err;
314      /* XXX rewrite the entire function */      GpgCardEdit *ce;
315      for( i=0; idctl[i].id; i++ ) /* reset */      char buf[256], tmp[128];
316          idctl[i].changed = 0;      int errc=0, use_arg2 = 0;
317            int i, id, n=0;
318      if( SendMessage( GetDlgItem( dlg, IDC_CEDIT_LANG2 ), WM_GETTEXTLENGTH, 0, 0 ) ) {  
319          idctl[1].changed = 1;      /* XXX rewrite the entire function */
320          n++;      for( i=0; idctl[i].id; i++ ) /* reset */
321      }          idctl[i].changed = 0;
322      if( SendMessage( GetDlgItem( dlg, IDC_CEDIT_SEX2 ), WM_GETTEXTLENGTH, 0, 0 ) ) {      
323          idctl[2].changed = 1;      if( SendMessage( GetDlgItem( dlg, IDC_CEDIT_LANG2 ), WM_GETTEXTLENGTH, 0, 0 ) ) {
324          n++;          idctl[1].changed = 1;
325      }          n++;
326            }
327      if( SendDlgItemMessage( dlg, IDC_CEDIT_NAME2, EM_GETMODIFY, 0, 0 ) ) {      if( SendMessage( GetDlgItem( dlg, IDC_CEDIT_SEX2 ), WM_GETTEXTLENGTH, 0, 0 ) ) {
328          idctl[0].changed = 1;          idctl[2].changed = 1;
329          n++;          n++;
330      }      }
331      for( i=0; (id = idctl[i].id); i++ ) {      
332          if( SendDlgItemMessage( dlg, id, EM_GETMODIFY, 0, 0 ) ) {      if( SendDlgItemMessage( dlg, IDC_CEDIT_NAME2, EM_GETMODIFY, 0, 0 ) ) {
333              idctl[i].changed = 1;          idctl[0].changed = 1;
334              n++;          n++;
335          }      }
336      }      for( i=0; (id = idctl[i].id); i++ ) {
337      if (!pincb || !card) /* just return the changed elements */          if( SendDlgItemMessage( dlg, id, EM_GETMODIFY, 0, 0 ) ) {
338          return n;              idctl[i].changed = 1;
339      if (!n)              n++;
340          return 0;          }
341      if (!pincb->apin) {      }
342          msg_box (dlg, _("No PINs found."), _("Card Edit"), MB_ERR);      if (!pincb || !card) /* just return the changed elements */
343          return 0;          return n;
344      }      if (!n)
345                return 0;
346      ce = new GpgCardEdit ();      if (!pincb->apin) {
347      if (!ce)          msg_box (dlg, _("No PINs found."), _("Card Edit"), MB_ERR);
348          BUG (NULL);          return 0;
349      ce->setAdminPIN (pincb->apin);      }
350      /*ce->setPIN (pincb->upin);*/      
351      for( i=0; idctl[i].id; i++ ) {      ce = new GpgCardEdit ();
352          if( idctl[i].changed ) {      if (!ce)
353              GetDlgItemText( dlg, idctl[i].id, buf, sizeof (buf)-1 );          BUG (NULL);
354              if (idctl[i].us_ascii && is_8bit_string (buf)) {      ce->setAdminPIN (pincb->apin);
355                  msg_box (dlg, _("Only plain ASCII is currently allowed."),      /*ce->setPIN (pincb->upin);*/
356                           _("Card Edit"), MB_ERR);      for( i=0; idctl[i].id; i++ ) {
357                  errc--; continue;          if( idctl[i].changed ) {
358              }              GetDlgItemText( dlg, idctl[i].id, buf, sizeof (buf)-1 );
359              if( (idctl[i].us_ascii & 2) && check_string( buf, 2 ) ) {              if (idctl[i].us_ascii && is_8bit_string (buf)) {
360                  msg_box( dlg, _("Only alphabetic characters are allowed."),                  msg_box (dlg, _("Only plain ASCII is currently allowed."),
361                           _("Card Edit"), MB_ERR );                           _("Card Edit"), MB_ERR);
362                  errc--; continue;                  errc--; continue;
363              }              }
364              if ((idctl[i].us_ascii & 4) &&              if( (idctl[i].us_ascii & 2) && check_string( buf, 2 ) ) {
365                  (!strchr (buf, ':') || !strstr (buf, "//"))) {                  msg_box( dlg, _("Only alphabetic characters are allowed."),
366                  /* XXX: better URL check. */                           _("Card Edit"), MB_ERR );
367                  msg_box (dlg, _("Invalid URL."), _("Card Edit"), MB_ERR);                  errc--; continue;
368                  errc--; continue;              }
369              }              if ((idctl[i].us_ascii & 4) &&
370              if( idctl[i].cmd == GPG_EDITCARD_NAME ) {                  (!strchr (buf, ':') || !strstr (buf, "//"))) {
371                  /* The "name" command actually needs two fields */                  /* XXX: better URL check. */
372                  GetDlgItemText( dlg, IDC_CEDIT_NAME2, tmp, sizeof tmp-1 );                  msg_box (dlg, _("Invalid URL."), _("Card Edit"), MB_ERR);
373                  use_arg2 = 1;                  errc--; continue;
374              }              }
375              else              if( idctl[i].cmd == GPG_EDITCARD_NAME ) {
376                  use_arg2 = 0;                  /* The "name" command actually needs two fields */
377              err = ce->doCmd (idctl[i].cmd, buf, use_arg2? tmp : NULL);                  GetDlgItemText( dlg, IDC_CEDIT_NAME2, tmp, sizeof tmp-1 );
378              if (err) {                  use_arg2 = 1;
379                  log_box (_("Card Edit"), MB_ERR,              }
380                           _("Could not modify card attribute: %s"),              else
381                           gpgme_strerror (err));                  use_arg2 = 0;
382                  errc--;              err = ce->doCmd (idctl[i].cmd, buf, use_arg2? tmp : NULL);
383                  /* If no card is inserted, we leave the loop. */              if (err) {
384                  if (gpgme_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)                  log_box (_("Card Edit"), MB_ERR,
385                      break;                           _("Could not modify card attribute: %s"),
386              }                           gpgme_strerror (err));
387          }                  errc--;
388      }                  /* If no card is inserted, we leave the loop. */
389      if (!errc) {                  if (gpgme_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)
390          /* if the operation(s) succeeded, reset the modify flag for each control */                      break;
391          for( i = 0; idctl[i].id; i++ )              }
392              SendDlgItemMessage( dlg, idctl[i].id, EM_SETMODIFY, (WPARAM)(UINT)FALSE, 0 );          }
393          msg_box( dlg, _("Card attribute changed."), _("Card Edit"), MB_OK );      }
394          SetDlgItemText( dlg, IDC_CEDIT_LANG2, "" );      if (!errc) {
395          SetDlgItemText( dlg, IDC_CEDIT_SEX2, "" );          /* if the operation(s) succeeded, reset the modify flag for each control */
396      }          for( i = 0; idctl[i].id; i++ )
397      delete ce;              SendDlgItemMessage( dlg, idctl[i].id, EM_SETMODIFY, (WPARAM)(UINT)FALSE, 0 );
398      return errc;          msg_box( dlg, _("Card attribute changed."), _("Card Edit"), MB_OK );
399  } /* do_proc_card_cmds */          SetDlgItemText( dlg, IDC_CEDIT_LANG2, "" );
400            SetDlgItemText( dlg, IDC_CEDIT_SEX2, "" );
401        }
402  /* Cleanup pin callback @ctx. */      delete ce;
403  void      return errc;
404  free_pincb (struct pin_cb_ctx_s *ctx)  } /* do_proc_card_cmds */
405  {  
406      if (!ctx)  
407          return;  /* Cleanup pin callback @ctx. */
408      free_if_alloc (ctx->info_text);  void
409      sfree_if_alloc (ctx->upin);  free_pincb (struct pin_cb_ctx_s *ctx)
410      sfree_if_alloc (ctx->apin);  {
411  }      if (!ctx)
412            return;
413        free_if_alloc (ctx->info_text);
414  /* Request a PIN from the user. @which decided if the      sfree_if_alloc (ctx->upin);
415     normal PIN or the admin PIN will be requested.      sfree_if_alloc (ctx->apin);
416     @card is used to show some information to the user.  }
417     @pincb is the actuall callback context.  
418     Return value: 0 on success. */  
419  static int  /* Request a PIN from the user. @which decided if the
420  do_askpin (HWND dlg, int which, gpg_card_t card,     normal PIN or the admin PIN will be requested.
421             struct pin_cb_ctx_s *pincb)     @card is used to show some information to the user.
422  {     @pincb is the actuall callback context.
423      const char * s, * fmt;     Return value: 0 on success. */
424      const char * n1, * n2, * serial;  static int
425      char * p;  do_askpin (HWND dlg, int which, gpg_card_t card,
426      size_t n;             struct pin_cb_ctx_s *pincb)
427    {
428      if( (which == CARD_ADMIN_PIN && pincb->apin) ||      const char * s, * fmt;
429          (which == CARD_USER_PIN && pincb->upin) )      const char * n1, * n2, * serial;
430          return 0;      char * p;
431            size_t n;
432      if (which == CARD_ADMIN_PIN)  
433          s = _("Please enter the 'Admin PIN'");      if( (which == CARD_ADMIN_PIN && pincb->apin) ||
434      else if (which == CARD_USER_PIN)          (which == CARD_USER_PIN && pincb->upin) )
435          s = _("Please enter the 'User PIN'");          return 0;
436      else      
437          s = _("Please enter the PIN");      if (which == CARD_ADMIN_PIN)
438      pincb->which = which;          s = _("Please enter the 'Admin PIN'");
439      free_if_alloc( pincb->info_text );      else if (which == CARD_USER_PIN)
440      if( card ) {          s = _("Please enter the 'User PIN'");
441          fmt = _("%s\nName: %s %s\nSerial-No: %s\n");      else
442          n1 = card->givenname;          s = _("Please enter the PIN");
443          n2 = card->surname;      pincb->which = which;
444          if( !n1 || !n2 ) {      free_if_alloc( pincb->info_text );
445              n1 = "No"; n2 = "Name";      if( card ) {
446          }              fmt = _("%s\nName: %s %s\nSerial-No: %s\n");
447          serial = card->serial;          n1 = card->givenname;
448          if (!serial)          n2 = card->surname;
449              serial = "No Serial ID";          if( !n1 || !n2 ) {
450          n = strlen( n1 ) + strlen( n2 ) + strlen( fmt ) + strlen( serial ) + 3;              n1 = "No"; n2 = "Name";
451          p = pincb->info_text = new char[strlen( s )+n+1 ];          }    
452          if( !p )          serial = card->serial;
453              BUG (0);          if (!serial)
454          sprintf( p, fmt, s, n1, n2, serial );              serial = "No Serial ID";
455      }          n = strlen( n1 ) + strlen( n2 ) + strlen( fmt ) + strlen( serial ) + 3;
456      else {          p = pincb->info_text = new char[strlen( s )+n+1 ];
457          p = pincb->info_text = m_strdup (s);          if( !p )
458          if (!p)              BUG (0);
459              BUG (0);          sprintf( p, fmt, s, n1, n2, serial );
460      }      }
461      DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_PIN, dlg,      else {
462                      pin_cb_dlg_proc, (LPARAM)pincb);          p = pincb->info_text = m_strdup (s);
463      if (!pincb->apin && !pincb->upin) {          if (!p)
464          safe_free (pincb->info_text);              BUG (0);
465          return -1;      }
466      }      DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_PIN, dlg,
467      return 0;                      pin_cb_dlg_proc, (LPARAM)pincb);
468  }      if (!pincb->apin && !pincb->upin) {
469            safe_free (pincb->info_text);
470            return -1;
471  /* Dialog box procedure for card edit. */      }
472  BOOL CALLBACK      return 0;
473  card_edit_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  }
474  {  
475      static gpg_card_t card;      
476      char tmp[128];  /* Dialog box procedure for card edit. */
477      size_t n=0;  BOOL CALLBACK
478    card_edit_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
479      switch (msg) {  {
480      case WM_INITDIALOG:      static gpg_card_t card;    
481          card = (gpg_card_t)lparam;      char tmp[128];
482          if (!card)      size_t n=0;
483              BUG (0);  
484          prepare_dialog (dlg);      switch (msg) {
485          if (card_status (dlg, card ))      case WM_INITDIALOG:
486              EndDialog (dlg, TRUE);          card = (gpg_card_t)lparam;
487          center_window (dlg, NULL);          if (!card)
488          SetForegroundWindow (dlg);              BUG (0);
489          return TRUE;          prepare_dialog (dlg);
490            if (card_status (dlg, card ))
491      case WM_DESTROY:              EndDialog (dlg, TRUE);
492          free_pincb (&pincb);          center_window (dlg, NULL);
493          memset (&pincb, 0, sizeof pincb);          SetForegroundWindow (dlg);
494          break;          return TRUE;
495    
496      case WM_COMMAND:      case WM_DESTROY:
497          switch( HIWORD( wparam ) ) {          free_pincb (&pincb);
498          case CBN_KILLFOCUS:          memset (&pincb, 0, sizeof pincb);
499          case CBN_EDITCHANGE:          break;
500          case CBN_EDITUPDATE:  
501              int ctlid = GetDlgCtrlID( (HWND)lparam );      case WM_COMMAND:
502              int dstid = 0;          switch( HIWORD( wparam ) ) {
503            case CBN_KILLFOCUS:
504              switch (ctlid) {          case CBN_EDITCHANGE:
505              case IDC_CEDIT_LANG: dstid = IDC_CEDIT_LANG2; break;          case CBN_EDITUPDATE:
506              case IDC_CEDIT_SEX:  dstid = IDC_CEDIT_SEX2; break;              int ctlid = GetDlgCtrlID( (HWND)lparam );
507              }                    int dstid = 0;
508              GetDlgItemText (dlg, ctlid, tmp, sizeof (tmp)-1);  
509              SetDlgItemText (dlg, dstid, tmp);              switch (ctlid) {
510              break;              case IDC_CEDIT_LANG: dstid = IDC_CEDIT_LANG2; break;
511          }              case IDC_CEDIT_SEX:  dstid = IDC_CEDIT_SEX2; break;
512          switch (LOWORD (wparam)) {              }      
513          case IDC_CEDIT_CHPIN:              GetDlgItemText (dlg, ctlid, tmp, sizeof (tmp)-1);
514              DialogBoxParam( glob_hinst, (LPCTSTR)IDD_WINPT_CARD_CHPIN, dlg,              SetDlgItemText (dlg, dstid, tmp);
515                              card_changepin_dlg_proc, NULL );              break;
516              break;          }
517            switch (LOWORD (wparam)) {
518          case IDC_CEDIT_NEWKEYS:          case IDC_CEDIT_CHPIN:
519              if (item_get_text_length (dlg, IDC_CEDIT_FPR1) > 0) {              DialogBoxParam( glob_hinst, (LPCTSTR)IDD_WINPT_CARD_CHPIN, dlg,
520                  int id = msg_box (dlg,                              card_changepin_dlg_proc, NULL );
521                      _("This operation will override the keys on the card.\n"              break;
522                        "Still proceed?"), _("Card Edit"), MB_WARN|MB_YESNO);  
523                  if (id == IDNO)          case IDC_CEDIT_NEWKEYS:
524                      return TRUE;              if (item_get_text_length (dlg, IDC_CEDIT_FPR1) > 0) {
525              }                  int id = msg_box (dlg,
526              DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_CARD_KEYGEN,                      _("This operation will override the keys on the card.\n"
527                              glob_hwnd, card_keygen_dlg_proc, NULL);                        "Still proceed?"), _("Card Edit"), MB_WARN|MB_YESNO);
528              break;                  if (id == IDNO)
529                        return TRUE;
530          case IDOK:              }
531              n = do_proc_card_cmds (dlg, NULL, NULL);              DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_CARD_KEYGEN,
532              if (n) {                              glob_hwnd, card_keygen_dlg_proc, NULL);
533                  if (do_askpin (dlg, CARD_ADMIN_PIN, card, &pincb))              break;
534                      EndDialog (dlg, FALSE);  
535              }          case IDOK:
536              do_proc_card_cmds (dlg, &pincb, card);              n = do_proc_card_cmds (dlg, NULL, NULL);
537              free_pincb (&pincb);              if (n) {
538              if (!n)                  if (do_askpin (dlg, CARD_ADMIN_PIN, card, &pincb))
539                  EndDialog (dlg, TRUE);                      EndDialog (dlg, FALSE);
540              break;              }
541                do_proc_card_cmds (dlg, &pincb, card);
542          case IDCANCEL:              free_pincb (&pincb);
543              EndDialog( dlg, FALSE );              if (!n)
544              break;                  EndDialog (dlg, TRUE);
545          }              break;
546          break;  
547      }          case IDCANCEL:
548                EndDialog( dlg, FALSE );
549      return FALSE;              break;
550  }          }
551            break;
552        }
553  static int /* fixme: works only roughly */  
554  calc_days (int y2, int m2, int d2,      return FALSE;
555             int y1, int m1, int d1)  }
556    
557  {  
558      int n=0;  static int /* fixme: works only roughly */
559        calc_days (int y2, int m2, int d2,
560      if ((y2-y1) > 0)             int y1, int m1, int d1)
561          n += (y2-y1)*365;  
562      if ((m2-m1) > 0)  {
563          n += (m2-m1)*30;      int n=0;
564      if ((d2-d1) > 0)      
565          n += (d2-d1);      if ((y2-y1) > 0)
566      else if ((d2-d1) < 0)          n += (y2-y1)*365;
567          n -= (d1-d2);      if ((m2-m1) > 0)
568      return n;          n += (m2-m1)*30;
569  }      if ((d2-d1) > 0)
570            n += (d2-d1);
571        else if ((d2-d1) < 0)
572  /* Dialog box procedure for the key generation on cards. */          n -= (d1-d2);
573  BOOL CALLBACK      return n;
574  card_keygen_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  }
575  {  
576      gpgme_error_t err;  
577      GpgCardEdit *ce;  /* Dialog box procedure for the key generation on cards. */
578      char name[128], email[128], comment[128];  BOOL CALLBACK
579      char pass[128];  card_keygen_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
580      int card_flags = GPG_CARDFLAG_NONE;  {
581      int expires=0, valid;      gpgme_error_t err;
582      size_t n;      GpgCardEdit *ce;
583        char name[128], email[128], comment[128];
584      switch (msg) {      char pass[128];
585      case WM_INITDIALOG:      int card_flags = GPG_CARDFLAG_NONE;
586          center_window (dlg, NULL);      int expires=0, valid;
587          CheckDlgButton (dlg, IDC_CKEYGEN_REPLACE, BST_CHECKED);      size_t n;
588          CheckDlgButton (dlg, IDC_CKEYGEN_NEVER, BST_CHECKED);  
589          CheckDlgButton (dlg, IDC_CKEYGEN_BACKUP, BST_CHECKED);      switch (msg) {
590          EnableWindow (GetDlgItem (dlg, IDC_CKEYGEN_VALID), FALSE);      case WM_INITDIALOG:
591          SendDlgItemMessage (dlg, IDC_CKEYGEN_ALG, CB_ADDSTRING, 0,          center_window (dlg, NULL);
592                              (LPARAM)(const char*)"RSA");          CheckDlgButton (dlg, IDC_CKEYGEN_REPLACE, BST_CHECKED);
593          SendDlgItemMessage (dlg, IDC_CKEYGEN_ALG, CB_SETCURSEL, 0, 0);          CheckDlgButton (dlg, IDC_CKEYGEN_NEVER, BST_CHECKED);
594          SetFocus (GetDlgItem (dlg, IDC_CKEYGEN_NAME));          CheckDlgButton (dlg, IDC_CKEYGEN_BACKUP, BST_CHECKED);
595          SetForegroundWindow (dlg);          EnableWindow (GetDlgItem (dlg, IDC_CKEYGEN_VALID), FALSE);
596          return FALSE;          SendDlgItemMessage (dlg, IDC_CKEYGEN_ALG, CB_ADDSTRING, 0,
597                                (LPARAM)(const char*)"RSA");
598      case WM_SYSCOMMAND:          SendDlgItemMessage (dlg, IDC_CKEYGEN_ALG, CB_SETCURSEL, 0, 0);
599          if (LOWORD (wparam) == SC_CLOSE)          SetFocus (GetDlgItem (dlg, IDC_CKEYGEN_NAME));
600              EndDialog (dlg, TRUE);          SetForegroundWindow (dlg);
601          return FALSE;          SetDlgItemText (dlg, IDC_CKEYGEN_NAMEINF, _("&Name"));
602            SetDlgItemText (dlg, IDC_CKEYGEN_CMTINF, _("&Comment (optional)"));
603      case WM_COMMAND:          SetDlgItemText (dlg, IDC_CKEYGEN_EXPDATEINF, _("&Expire date"));
604          if (HIWORD (wparam) == BN_CLICKED &&          SetDlgItemText (dlg, IDC_CKEYGEN_PWDINF, _("Off-card passphrase"));
605              (LOWORD (wparam) == IDC_CKEYGEN_BACKUP) ||          SetDlgItemText (dlg, IDC_CKEYGEN_NEVER, _("&Never"));
606               LOWORD (wparam) == IDC_CKEYGEN_NEVER) {          SetDlgItemText (dlg, IDC_CKEYGEN_MAILINF, _("Email &address"));
607              EnableWindow (GetDlgItem (dlg, IDC_CKEYGEN_VALID),          SetWindowText (dlg, _("Card Key Generation"));
608                            IsDlgButtonChecked (dlg, IDC_CKEYGEN_NEVER)? 0: 1);          return FALSE;
609              EnableWindow (GetDlgItem (dlg, IDC_CKEYGEN_PASS),  
610                            IsDlgButtonChecked (dlg, IDC_CKEYGEN_BACKUP)? 1 : 0);      case WM_SYSCOMMAND:
611              return TRUE;          if (LOWORD (wparam) == SC_CLOSE)
612          }                    EndDialog (dlg, TRUE);
613            return FALSE;
614          switch (LOWORD (wparam)) {  
615          case IDOK:      case WM_COMMAND:
616              n = item_get_text_length (dlg, IDC_CKEYGEN_NAME);          if (HIWORD (wparam) == BN_CLICKED &&
617              if (!n) {              (LOWORD (wparam) == IDC_CKEYGEN_BACKUP) ||
618                  msg_box (dlg, _("Please enter your name."), _("Card Edit"), MB_ERR);               LOWORD (wparam) == IDC_CKEYGEN_NEVER) {
619                  return TRUE;              EnableWindow (GetDlgItem (dlg, IDC_CKEYGEN_VALID),
620              }                            IsDlgButtonChecked (dlg, IDC_CKEYGEN_NEVER)? 0: 1);
621              if (n < 5) {              EnableWindow (GetDlgItem (dlg, IDC_CKEYGEN_PASS),
622                  msg_box (dlg, _("Name must be at least 5 characters long."),                            IsDlgButtonChecked (dlg, IDC_CKEYGEN_BACKUP)? 1 : 0);
623                           _("Card Edit"), MB_INFO);              return TRUE;
624                  return TRUE;          }      
625              }  
626              n = item_get_text_length (dlg, IDC_CKEYGEN_EMAIL);          switch (LOWORD (wparam)) {
627              if (!n) {          case IDOK:
628                  msg_box (dlg, _("Please enter your e-mail address."),              n = item_get_text_length (dlg, IDC_CKEYGEN_NAME);
629                           _("Card Edit"), MB_ERR);              if (!n) {
630                  return TRUE;                  msg_box (dlg, _("Please enter your name."), _("Card Edit"), MB_ERR);
631              }                  return TRUE;
632              GetDlgItemText (dlg, IDC_CKEYGEN_NAME, name, sizeof (name)-1);              }
633              GetDlgItemText (dlg, IDC_CKEYGEN_EMAIL, email, sizeof (email)-1);              if (n < 5) {
634              if (!strchr (email, '@') || n < 3) {                  msg_box (dlg, _("Name must be at least 5 characters long."),
635                  msg_box (dlg, _("Please enter a valid e-mail address."),                           _("Card Edit"), MB_INFO);
636                           _("Card Edit"), MB_ERR);                  return TRUE;
637                  return TRUE;              }
638              }              n = item_get_text_length (dlg, IDC_CKEYGEN_EMAIL);
639              n = GetDlgItemText (dlg, IDC_CKEYGEN_PASS, pass, sizeof (pass)-1);              if (!n) {
640              if (!n && IsDlgButtonChecked (dlg, IDC_CKEYGEN_BACKUP)) {                  msg_box (dlg, _("Please enter your e-mail address."),
641                  msg_box (dlg, _("Please enter an off-card passphrase."), _("Card Edit"), MB_ERR);                           _("Card Edit"), MB_ERR);
642                  return TRUE;                  return TRUE;
643              }              }
644              n = item_get_text_length (dlg, IDC_CKEYGEN_COMMENT);              GetDlgItemText (dlg, IDC_CKEYGEN_NAME, name, sizeof (name)-1);
645              if (n > 0)              GetDlgItemText (dlg, IDC_CKEYGEN_EMAIL, email, sizeof (email)-1);
646                  GetDlgItemText (dlg, IDC_CKEYGEN_COMMENT, comment, sizeof (comment)-1);              if (!strchr (email, '@') || n < 3) {
647              if (is_8bit_string (name) || n > 0 && is_8bit_string (comment)) {                  msg_box (dlg, _("Please enter a valid e-mail address."),
648                  msg_box (dlg, _("Please use plain ASCII charset for the fields."),                           _("Card Edit"), MB_ERR);
649                           _("Card Edit"), MB_INFO);                  return TRUE;
650                  return TRUE;              }
651              }              n = GetDlgItemText (dlg, IDC_CKEYGEN_PASS, pass, sizeof (pass)-1);
652              memset (&pincb, 0, sizeof (pincb));              if (!n && IsDlgButtonChecked (dlg, IDC_CKEYGEN_BACKUP)) {
653              if (do_askpin (dlg, CARD_ADMIN_PIN, NULL, &pincb)) {                  msg_box (dlg, _("Please enter an off-card passphrase."), _("Card Edit"), MB_ERR);
654                  free_pincb (&pincb);                  return TRUE;
655                  return TRUE;              }
656              }              n = item_get_text_length (dlg, IDC_CKEYGEN_COMMENT);
657              if (do_askpin (dlg, CARD_USER_PIN, NULL, &pincb)) {              if (n > 0)
658                  free_pincb (&pincb);                  GetDlgItemText (dlg, IDC_CKEYGEN_COMMENT, comment, sizeof (comment)-1);
659                  return TRUE;              if (is_8bit_string (name) || n > 0 && is_8bit_string (comment)) {
660              }                  msg_box (dlg, _("Please use plain ASCII charset for the fields."),
661              ce = new GpgCardEdit ();                           _("Card Edit"), MB_INFO);
662              if (!ce)                  return TRUE;
663                  BUG (0);              }
664                            memset (&pincb, 0, sizeof (pincb));
665              expires = !IsDlgButtonChecked (dlg, IDC_CKEYGEN_NEVER);              if (do_askpin (dlg, CARD_ADMIN_PIN, NULL, &pincb)) {
666              if (expires) {                  free_pincb (&pincb);
667                  SYSTEMTIME st, ct;                  return TRUE;
668                  DateTime_GetSystemtime (GetDlgItem (dlg, IDC_CKEYGEN_VALID), &st);              }
669                  if (!keygen_check_date (&st)) {              if (do_askpin (dlg, CARD_USER_PIN, NULL, &pincb)) {
670                      msg_box (dlg, _("The date you have chosen lies in the past."),                  free_pincb (&pincb);
671                               _("Card Edit"), MB_ERR);                  return TRUE;
672                      free_pincb (&pincb);              }
673                      delete ce;              ce = new GpgCardEdit ();
674                      return TRUE;              if (!ce)
675                  }                  BUG (0);
676                  GetSystemTime (&ct);              
677                  /* XXX this is not very precise */              expires = !IsDlgButtonChecked (dlg, IDC_CKEYGEN_NEVER);
678                  valid = calc_days (st.wYear, st.wMonth, st.wDay,              if (expires) {
679                                     ct.wYear, ct.wMonth, ct.wDay);                  SYSTEMTIME st, ct;
680              }                  DateTime_GetSystemtime (GetDlgItem (dlg, IDC_CKEYGEN_VALID), &st);
681              if (IsDlgButtonChecked (dlg, IDC_CKEYGEN_REPLACE))                  if (!keygen_check_date (&st)) {
682                  card_flags |= GPG_CARDFLAG_REPLACE;                      msg_box (dlg, _("The date you have chosen lies in the past."),
683              if (IsDlgButtonChecked (dlg, IDC_CKEYGEN_BACKUP))                               _("Card Edit"), MB_ERR);
684                  card_flags |= GPG_CARDFLAG_BAKENC;                      free_pincb (&pincb);
685              ce->setKeygenPassphrase (pass);                      delete ce;
686              ce->setPIN (pincb.upin);                      return TRUE;
687              ce->setAdminPIN (pincb.apin);                  }
688                                GetSystemTime (&ct);
689              SetCursor (LoadCursor (NULL, IDC_WAIT));                  /* XXX this is not very precise */
690              err = ce->genKey (card_flags, name, email, n? comment: NULL,                  valid = calc_days (st.wYear, st.wMonth, st.wDay,
691                                expires? valid : 0, NULL);                                     ct.wYear, ct.wMonth, ct.wDay);
692                            }
693              SetCursor (LoadCursor (NULL, IDC_ARROW));              if (IsDlgButtonChecked (dlg, IDC_CKEYGEN_REPLACE))
694                                card_flags |= GPG_CARDFLAG_REPLACE;
695              if (gpgme_err_code (err) == GPG_ERR_CANCELED)              if (IsDlgButtonChecked (dlg, IDC_CKEYGEN_BACKUP))
696                  msg_box (dlg, _("Operation was canceled. It seems that there are "                  card_flags |= GPG_CARDFLAG_BAKENC;
697                                  "existing\nkeys on the cards. You need to mark the "              ce->setKeygenPassphrase (pass);
698                                  "'Overwrite' flag."), _("Card Edit"), MB_INFO);              ce->setPIN (pincb.upin);
699              else              ce->setAdminPIN (pincb.apin);
700              if (err)              
701                  msg_box (dlg, "The operation does not succeed.\n"              SetCursor (LoadCursor (NULL, IDC_WAIT));
702                                "Please make sure you entered the right PIN's."              err = ce->genKey (card_flags, name, email, n? comment: NULL,
703                                , _("Card Edit"), MB_ERR);                                expires? valid : 0, NULL);
704              else              
705                  msg_box (dlg, _("Keys successfully created."),              SetCursor (LoadCursor (NULL, IDC_ARROW));
706                           _("Card Edit"), MB_OK);              
707              wipememory (pass, sizeof (pass));              if (gpgme_err_code (err) == GPG_ERR_CANCELED)
708              free_pincb (&pincb);                  msg_box (dlg, _("Operation was canceled. It seems that there are "
709              delete ce;                                  "existing\nkeys on the cards. You need to mark the "
710              return TRUE;                                  "'Overwrite' flag."), _("Card Edit"), MB_INFO);
711                else
712          case IDCANCEL:              if (err)
713              EndDialog (dlg, FALSE);                  msg_box (dlg, "The operation does not succeed.\n"
714              return FALSE;                                "Please make sure you entered the right PIN's."
715          }                                , _("Card Edit"), MB_ERR);
716          break;              else
717      }                  msg_box (dlg, _("Keys successfully created."),
718      return FALSE;                           _("Card Edit"), MB_OK);
719  }              wipememory (pass, sizeof (pass));
720                free_pincb (&pincb);
721                delete ce;
722  /* Check if the given pinlen is valid.              return TRUE;
723     @which decided what PIN will be used.  
724     @pinlen is the pin length entered by the user.          case IDCANCEL:
725     Return value: 0 on success. */              EndDialog (dlg, FALSE);
726  static int              return FALSE;
727  check_pin_len (int which, int flag, int pinlen)          }
728  {          break;
729      if (!pinlen) {      }
730          if (flag)      return FALSE;
731              msg_box (NULL, _("Please enter the old card PIN."), _("Card Edit"), MB_ERR);  }
732          else  
733              msg_box (NULL, _("Please enter the new card PIN."), _("Card Edit"), MB_ERR);  
734          return -1;  /* Check if the given pinlen is valid.
735      }     @which decided what PIN will be used.
736      if (which == CARD_ADMIN_PIN     @pinlen is the pin length entered by the user.
737          && pinlen < 8) {     Return value: 0 on success. */
738          msg_box (NULL, _("Admin PIN must be minimal 8 characters."), _("Card Edit"), MB_ERR);  static int
739          return -1;  check_pin_len (int which, int flag, int pinlen)
740      }  {
741      if (which == CARD_USER_PIN      if (!pinlen) {
742          && pinlen < 6) {          if (flag)
743          msg_box (NULL, _("PIN must be minimal 6 characters."), _("Card Edit"), MB_ERR);              msg_box (NULL, _("Please enter the old card PIN."), _("Card Edit"), MB_ERR);
744          return -1;          else
745      }              msg_box (NULL, _("Please enter the new card PIN."), _("Card Edit"), MB_ERR);
746      return 0;          return -1;
747  }      }
748        if (which == CARD_ADMIN_PIN
749  /* Dialog box procedure to change the PIN. */          && pinlen < 8) {
750  BOOL CALLBACK          msg_box (NULL, _("Admin PIN must be minimal 8 characters."), _("Card Edit"), MB_ERR);
751  card_changepin_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)          return -1;
752  {          }
753      static int hide = 1;      if (which == CARD_USER_PIN
754      gpgme_error_t err;          && pinlen < 6) {
755      GpgCardEdit *ce;              msg_box (NULL, _("PIN must be minimal 6 characters."), _("Card Edit"), MB_ERR);
756      char pold[128], pnew[128], pnew2[128];          return -1;
757      int which;      }
758      size_t n;      return 0;
759    }
760      switch( msg ) {  
761      case WM_INITDIALOG:  /* Dialog box procedure to change the PIN. */
762          hide = 1;  BOOL CALLBACK
763          CheckDlgButton (dlg, IDC_CHPIN_HIDE, BST_CHECKED);  card_changepin_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
764          center_window (dlg, NULL);  {    
765          CheckDlgButton (dlg, IDC_CHPIN_ISWORK, BST_CHECKED);      static int hide = 1;
766          SetForegroundWindow (dlg);      gpgme_error_t err;
767          break;      GpgCardEdit *ce;    
768        char pold[128], pnew[128], pnew2[128];
769      case WM_COMMAND:      int which;
770          if (HIWORD (wparam) == BN_CLICKED && LOWORD (wparam) == IDC_CHPIN_HIDE) {                size_t n;
771              HWND hwnd;  
772              hide ^= 1;      switch( msg ) {
773              hwnd = GetDlgItem (dlg, IDC_CHPIN_OLDPIN);      case WM_INITDIALOG:
774              SendMessage (hwnd, EM_SETPASSWORDCHAR, hide? '*' : 0, 0);          hide = 1;
775              SetFocus (hwnd);          CheckDlgButton (dlg, IDC_CHPIN_HIDE, BST_CHECKED);
776              hwnd = GetDlgItem (dlg, IDC_CHPIN_NEWPIN);          center_window (dlg, NULL);
777              SendMessage (hwnd, EM_SETPASSWORDCHAR, hide? '*' : 0, 0);          CheckDlgButton (dlg, IDC_CHPIN_ISWORK, BST_CHECKED);
778              SetFocus (hwnd);          SetWindowText (dlg, _("Change Card PIN"));
779              hwnd = GetDlgItem (dlg, IDC_CHPIN_NEWPIN2);          SetForegroundWindow (dlg);
780              SendMessage (hwnd, EM_SETPASSWORDCHAR, hide? '*' : 0, 0);          break;
781              SetFocus (hwnd);  
782          }      case WM_COMMAND:
783          switch( LOWORD( wparam ) ) {          if (HIWORD (wparam) == BN_CLICKED && LOWORD (wparam) == IDC_CHPIN_HIDE) {          
784          case IDOK:              HWND hwnd;
785              if (IsDlgButtonChecked (dlg, IDC_CHPIN_ISADMIN))              hide ^= 1;
786                  which = CARD_ADMIN_PIN;              hwnd = GetDlgItem (dlg, IDC_CHPIN_OLDPIN);
787              else if (IsDlgButtonChecked (dlg, IDC_CHPIN_ISWORK))              SendMessage (hwnd, EM_SETPASSWORDCHAR, hide? '*' : 0, 0);
788                  which = CARD_USER_PIN;              SetFocus (hwnd);
789                hwnd = GetDlgItem (dlg, IDC_CHPIN_NEWPIN);
790              n = item_get_text_length (dlg, IDC_CHPIN_OLDPIN);              SendMessage (hwnd, EM_SETPASSWORDCHAR, hide? '*' : 0, 0);
791              if (check_pin_len (which, 1, n))              SetFocus (hwnd);
792                  return TRUE;              hwnd = GetDlgItem (dlg, IDC_CHPIN_NEWPIN2);
793              n = item_get_text_length (dlg, IDC_CHPIN_NEWPIN);              SendMessage (hwnd, EM_SETPASSWORDCHAR, hide? '*' : 0, 0);
794              if (check_pin_len (which, 0, n))              SetFocus (hwnd);
795                  return TRUE;          }
796              n = item_get_text_length (dlg, IDC_CHPIN_NEWPIN2);          switch( LOWORD( wparam ) ) {
797              if (check_pin_len (which, 0, n))          case IDOK:
798                  return TRUE;              if (IsDlgButtonChecked (dlg, IDC_CHPIN_ISADMIN))
799              GetDlgItemText (dlg, IDC_CHPIN_OLDPIN, pold, sizeof (pold)-1);                  which = CARD_ADMIN_PIN;
800              GetDlgItemText (dlg, IDC_CHPIN_NEWPIN, pnew, sizeof (pnew)-1);              else if (IsDlgButtonChecked (dlg, IDC_CHPIN_ISWORK))
801              GetDlgItemText (dlg, IDC_CHPIN_NEWPIN2, pnew2, sizeof (pnew2)-1);                  which = CARD_USER_PIN;
802              if (strcmp (pnew, pnew2)) {  
803                  msg_box (dlg, _("Passphrases do not match. Please try again."),              n = item_get_text_length (dlg, IDC_CHPIN_OLDPIN);
804                           _("Card Edit"), MB_ERR);              if (check_pin_len (which, 1, n))
805                  return TRUE;                  return TRUE;
806              }              n = item_get_text_length (dlg, IDC_CHPIN_NEWPIN);
807                if (check_pin_len (which, 0, n))
808              ce = new GpgCardEdit ();                  return TRUE;
809              if (!ce)              n = item_get_text_length (dlg, IDC_CHPIN_NEWPIN2);
810                  BUG (0);              if (check_pin_len (which, 0, n))
811              if (which == CARD_ADMIN_PIN)                  return TRUE;
812                  ce->setAdminPIN (pold);              GetDlgItemText (dlg, IDC_CHPIN_OLDPIN, pold, sizeof (pold)-1);
813              else              GetDlgItemText (dlg, IDC_CHPIN_NEWPIN, pnew, sizeof (pnew)-1);
814                  ce->setPIN (pold);              GetDlgItemText (dlg, IDC_CHPIN_NEWPIN2, pnew2, sizeof (pnew2)-1);
815              ce->setNewPIN (pnew);              if (strcmp (pnew, pnew2)) {
816              err = ce->changePIN (which == CARD_ADMIN_PIN? GPG_EDITCARD_CHAPIN :                  msg_box (dlg, _("Passphrases do not match. Please try again."),
817                                   GPG_EDITCARD_CHUPIN);                           _("Card Edit"), MB_ERR);
818              if (err)                  return TRUE;
819                  msg_box (dlg, gpgme_strerror (err), _("Card Edit"), MB_ERR);              }
820              else {  
821                  msg_box (dlg, _("PIN successfully changed."),              ce = new GpgCardEdit ();
822                           _("Card Edit"), MB_OK);              if (!ce)
823                  SetDlgItemText (dlg, IDC_CHPIN_NEWPIN, "");                  BUG (0);
824                  SetDlgItemText (dlg, IDC_CHPIN_OLDPIN, "");              if (which == CARD_ADMIN_PIN)
825                  SetDlgItemText (dlg, IDC_CHPIN_NEWPIN2, "");                  ce->setAdminPIN (pold);
826              }              else
827              wipememory (pold, sizeof (pold));                  ce->setPIN (pold);
828              wipememory (pnew, sizeof (pnew));              ce->setNewPIN (pnew);
829              wipememory (pnew2, sizeof (pnew2));              err = ce->changePIN (which == CARD_ADMIN_PIN? GPG_EDITCARD_CHAPIN :
830              delete ce;                                   GPG_EDITCARD_CHUPIN);
831              break;              if (err)
832                    msg_box (dlg, gpgme_strerror (err), _("Card Edit"), MB_ERR);
833          case IDCANCEL:              else {
834              SetDlgItemText (dlg, IDC_CHPIN_NEWPIN, "");                  msg_box (dlg, _("PIN successfully changed."),
835              SetDlgItemText (dlg, IDC_CHPIN_OLDPIN, "");                           _("Card Edit"), MB_OK);
836              SetDlgItemText (dlg, IDC_CHPIN_NEWPIN2, "");                  SetDlgItemText (dlg, IDC_CHPIN_NEWPIN, "");
837              EndDialog (dlg, FALSE);                  SetDlgItemText (dlg, IDC_CHPIN_OLDPIN, "");
838              break;                  SetDlgItemText (dlg, IDC_CHPIN_NEWPIN2, "");
839          }              }
840          break;              wipememory (pold, sizeof (pold));
841      }              wipememory (pnew, sizeof (pnew));
842                wipememory (pnew2, sizeof (pnew2));
843      return FALSE;              delete ce;
844  }              break;
845    
846            case IDCANCEL:
847                SetDlgItemText (dlg, IDC_CHPIN_NEWPIN, "");
848                SetDlgItemText (dlg, IDC_CHPIN_OLDPIN, "");
849                SetDlgItemText (dlg, IDC_CHPIN_NEWPIN2, "");
850                EndDialog (dlg, FALSE);
851                break;
852            }
853            break;
854        }
855    
856        return FALSE;
857    }

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26