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

Contents of /trunk/Src/wptKeyManagerDlg.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 244 - (show annotations)
Mon Jul 3 14:10:21 2006 UTC (18 years, 8 months ago) by twoaday
File size: 63693 byte(s)


1 /* wptKeyManagerDlg.cpp - WinPT Key Manager
2 * Copyright (C) 2000-2006 Timo Schulz
3 * Copyright (C) 2004 Andreas Jobs
4 *
5 * This file is part of WinPT.
6 *
7 * 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
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * WinPT is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with WinPT; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 */
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <windows.h>
26 #include <commctrl.h>
27
28 #include "resource.h"
29 #include "wptTypes.h"
30 #include "wptGPG.h"
31 #include "wptCommonCtl.h"
32 #include "wptContext.h" /* for passphrase_s */
33 #include "wptDlgs.h"
34 #include "wptW32API.h"
35 #include "wptVersion.h"
36 #include "wptKeylist.h"
37 #include "wptNLS.h"
38 #include "wptErrors.h"
39 #include "wptHotkey.h"
40 #include "wptKeyManager.h"
41 #include "wptKeyserver.h"
42 #include "wptKeyEdit.h"
43 #include "wptRegistry.h"
44 #include "wptUTF8.h"
45
46 /* Name and ID of the separator window. */
47 #define KM_SEPARATOR_ID 10000
48 #define WINDOWCLASS_SEPARATOR_CHILD "WINPT_SEP_CHILD"
49
50 /* Virtual key codes. */
51 #ifndef VK_F
52 #define VK_F 70
53 #endif
54 #ifndef VK_A
55 #define VK_A 65
56 #endif
57 #ifndef VK_C
58 #define VK_C 67
59 #endif
60 #ifndef VK_P
61 #define VK_P 80
62 #endif
63
64 static subclass_s keylist_proc;
65
66 /* Handle to the global image list. */
67 HIMAGELIST glob_imagelist;
68
69 struct km_info_s {
70 /* Window positions */
71 int pos_x, pos_y;
72 int ypos_sep;
73 int ypercent_sep;
74
75 /* Different kind of windows. */
76 HWND dlg;
77 HWND hwnd_sep;
78 HWND toolbar;
79 HWND statbar;
80
81 listview_ctrl_t lv;
82 int lv_idx;
83 int keylist_sortby;
84 int magic;
85
86 unsigned int enable_groups:1;
87 };
88 typedef struct km_info_s *km_info_t;
89
90 /* Toolbar button structure. */
91 struct mybuttons {
92 long icon;
93 long command;
94 char *text;
95 };
96
97 struct mybuttons myb[] = {
98 {IMI_KEY_DELETE, ID_KEYMISC_DELETE, "Delete"},
99 {IMI_KEY_PROPS, ID_KEYMISC_PROPS, "Properties"},
100 {IMI_KEY_SIGN, ID_KEYMISC_SIGN, "Sign"},
101 {IMI_KEY_IMPORT, ID_KEYMISC_IMPORT, "Import"},
102 {IMI_KEY_EXPORT, ID_KEYMISC_EXPORT, "Export"},
103 };
104
105
106 static void km_gui_import (struct km_info_s *kmi, int cmd_id, void *param);
107 void key_get_clip_info (const char *keyid, char *buf, size_t buflen);
108
109
110 /* Subclass the keylist listview control to allow extended commands. */
111 static BOOL CALLBACK
112 keylist_subclass_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
113 {
114 struct listview_ctrl_s lv;
115 struct km_info_s *kmi;
116
117 switch (msg) {
118 case WM_DROPFILES:
119 kmi = (km_info_s *)keylist_proc.opaque;
120 km_gui_import (kmi, WM_DROPFILES, (void*)wparam);
121 break;
122
123 case WM_LBUTTONDBLCLK:
124 send_cmd_id (keylist_proc.dlg, ID_KEYMISC_PROPS);
125 break;
126
127 case WM_KEYUP:
128 int virt_key = (int)wparam;
129 switch (virt_key) {
130 case VK_SPACE:
131 send_cmd_id (keylist_proc.dlg, ID_KEYMISC_PROPS);
132 break;
133
134 case VK_DELETE:
135 send_cmd_id (keylist_proc.dlg, ID_KEYMISC_DELETE);
136 break;
137
138 case VK_INSERT:
139 send_cmd_id (keylist_proc.dlg, ID_KEYMISC_PASTE);
140 break;
141
142 case VK_A:
143 if (GetAsyncKeyState (VK_CONTROL)) {
144 lv.ctrl = GetDlgItem (keylist_proc.dlg, IDC_KEYMISC_KEYLIST);
145 listview_select_all (&lv);
146 }
147 break;
148
149 case VK_C:
150 if (GetAsyncKeyState (VK_CONTROL)) {
151 lv.ctrl = GetDlgItem (keylist_proc.dlg, IDC_KEYMISC_KEYLIST);
152 km_clip_export (keylist_proc.dlg, &lv);
153 }
154 break;
155
156 case VK_P:
157 if (GetAsyncKeyState (VK_CONTROL))
158 send_cmd_id (keylist_proc.dlg, ID_KEYMISC_PASTE);
159 break;
160
161 case VK_F:
162 if (GetAsyncKeyState (VK_CONTROL)) {
163 lv.ctrl = GetDlgItem (keylist_proc.dlg, IDC_KEYMISC_KEYLIST);
164 km_find_key (dlg, &lv);
165 }
166 break;
167 }
168 break;
169 }
170
171 return CallWindowProc (keylist_proc.old, dlg, msg, wparam, lparam);
172 }
173
174
175 #define ico2idx(ico) imagelist_getindex ((ico))
176
177 /* Create a new toolbar window with a pre-defined list of buttons. */
178 static HWND
179 create_toolbar (HWND dlg, struct km_info_s *kmi)
180 {
181 HWND tbwnd;
182 TBSAVEPARAMS tbsp;
183 TBBUTTON tb_buttons[] = {
184 {ico2idx (IMI_KEY_NEW), ID_KEYMISC_KEYWIZARD, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L},
185 {ico2idx (IMI_KEY_DELETE), ID_KEYMISC_DELETE, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, 0},
186 {ico2idx (IMI_KEY_PROPS), ID_KEYMISC_PROPS, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, 0},
187 {ico2idx (IMI_KEY_SIGN), ID_KEYMISC_SIGN, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, 0},
188 {ico2idx (IMI_KEY_SEARCH), ID_KEYMISC_SENDRECV, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, 0},
189 {0, 0, 0, TBSTYLE_SEP, {0}, 0L, 0},
190 {ico2idx (IMI_KEY_FILE_IMPORT), ID_KEYMISC_IMPORT, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, 0},
191 {ico2idx (IMI_KEY_FILE_EXPORT), ID_KEYMISC_EXPORT, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, 0},
192 {ico2idx (IMI_KEY_IMPORT), ID_KEYCTX_PASTE, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, 0},
193 {ico2idx (IMI_KEY_EXPORT), ID_KEYCTX_COPY, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, 0},
194 };
195
196 tbwnd = CreateWindowEx (0, TOOLBARCLASSNAME, NULL,
197 WS_CHILD|TBSTYLE_TOOLTIPS|TBSTYLE_FLAT|CCS_ADJUSTABLE,
198 0, 0, 0, 0, dlg, (HMENU)IDR_WINPT_KMTB, glob_hinst, NULL);
199 if (!tbwnd)
200 BUG (0);
201 SendMessage (tbwnd, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
202 SendMessage (tbwnd, TB_SETIMAGELIST, 0, (LPARAM)glob_imagelist);
203 SendMessage (tbwnd, TB_AUTOSIZE, 0, 0);
204 ShowWindow (tbwnd, SW_SHOW);
205
206 /* Restore toolbar */
207 tbsp.hkr = HKEY_CURRENT_USER;
208 tbsp.pszSubKey = "Software\\WinPT";
209 tbsp.pszValueName = "KM_toolbar";
210 if (SendMessage (tbwnd, TB_SAVERESTORE, FALSE, (LPARAM)&tbsp) == 0)
211 SendMessage (tbwnd, TB_ADDBUTTONS,
212 sizeof (tb_buttons) / sizeof (tb_buttons[0]),
213 (LONG)&tb_buttons[0]);
214
215 return tbwnd;
216 }
217
218
219 /* Restore the width of the columns from the registry.
220 If no bitstring was found, the default size is used. */
221 int
222 restore_column_info (struct km_info_s *kmi)
223 {
224 WORD *buf;
225 HKEY root;
226 DWORD type;
227 DWORD size = kmi->lv->cols*sizeof (WORD), i;
228 LONG ec;
229
230 ec = RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\WinPT", 0,
231 KEY_ALL_ACCESS, &root);
232 if (ec != ERROR_SUCCESS)
233 return -1;
234
235 buf = new WORD[size/2];
236 if (!buf)
237 BUG (NULL);
238 ec = RegQueryValueEx (root, "KMColumnSize", NULL, &type,
239 (BYTE*)buf, &size);
240 if (ec != ERROR_SUCCESS) {
241 RegCloseKey (root);
242 free_if_alloc (buf);
243 return -1;
244 }
245
246 /* check for garbled values. */
247 for (i=0; i < size/2; i++) {
248 if (buf[i] == 0 || buf[i] > 512) {
249 free_if_alloc (buf);
250 return -1;
251 }
252 }
253 for (i=0; i < size/2; i++)
254 listview_set_column_width (kmi->lv, i, buf[i]);
255 free_if_alloc (buf);
256
257 size = sizeof (kmi->keylist_sortby);
258 ec = RegQueryValueEx (root, "KMSortBy", NULL, &type,
259 (BYTE*)&kmi->keylist_sortby, &size);
260 if (ec != ERROR_SUCCESS)
261 kmi->keylist_sortby = KEY_SORT_USERID;
262 RegCloseKey (root);
263 return 0;
264 }
265
266
267 /* Save the current column width to the registry. */
268 int
269 save_column_info (struct km_info_s *kmi)
270 {
271 HKEY root;
272 WORD *buf;
273 LONG ec;
274 int i;
275
276 buf = new WORD[kmi->lv->cols];
277 if (!buf)
278 BUG (NULL);
279 for (i=0; i < kmi->lv->cols; i++) {
280 LVCOLUMN lvc;
281
282 memset (&lvc, 0, sizeof (lvc));
283 lvc.mask = LVCF_WIDTH;
284 ListView_GetColumn (kmi->lv->ctrl, i, &lvc);
285 buf[i] = lvc.cx;
286 }
287
288 ec = RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\WinPT", 0,
289 KEY_ALL_ACCESS, &root);
290 if (ec != ERROR_SUCCESS) {
291 free_if_alloc (buf);
292 return -1;
293 }
294
295 ec = RegSetValueEx (root, "KMColumnSize", 0, REG_BINARY,
296 (const BYTE*)buf, 2*kmi->lv->cols);
297 if (ec == ERROR_SUCCESS) {
298 ec = RegSetValueEx (root, "KMSortBy", 0, REG_DWORD_BIG_ENDIAN,
299 (const BYTE*)&kmi->keylist_sortby,
300 sizeof (kmi->keylist_sortby));
301 }
302 RegCloseKey (root);
303 free_if_alloc (buf);
304 return ec == ERROR_SUCCESS? 0 : -1;
305 }
306
307
308 /* Restore the original size of the dialog. */
309 static void
310 restore_window_size (HWND dlg, struct km_info_s *kmi)
311 {
312 char *p;
313 int height = 0, width = 0;
314
315 /* Restore the original window size. */
316 p = get_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Size_Width");
317 if (p) {
318 width = atoi (p);
319 free_if_alloc (p);
320 }
321 p = get_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Size_Height");
322 if (p) {
323 height = atoi (p);
324 free_if_alloc (p);
325 }
326 if (height > 0 && width > 0)
327 SetWindowPos (dlg, HWND_TOP, kmi->pos_x, kmi->pos_y,
328 height, width, SWP_SHOWWINDOW);
329 }
330
331
332 /* Center window @dlg. */
333 static void
334 do_center_window (HWND dlg, struct km_info_s *kmi)
335 {
336 RECT rect;
337 char *p;
338 int pos_x = 0;
339 int pos_y = 0;
340
341 /* Find bottom of keylist */
342 GetWindowRect (GetDlgItem(dlg, IDC_KEYMISC_KEYLIST), &rect);
343 MapWindowPoints (NULL, dlg, (POINT*)&rect, 2);
344
345 kmi->ypos_sep = rect.bottom;
346
347 p = get_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Pos_X");
348 if (p && !strcmp (p, " ")) {
349 free_if_alloc (p);
350 center_window (dlg, NULL);
351 return;
352 }
353 else if (p)
354 pos_x = atoi (p);
355
356 p = get_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Pos_Y");
357 if (p && !strcmp (p, " ")) {
358 free_if_alloc (p);
359 center_window (dlg, NULL);
360 return;
361 }
362 else if (p)
363 pos_y = atoi (p);
364
365 if (!pos_y && !pos_x) {
366 center_window (dlg, NULL);
367 return;
368 }
369
370 if (pos_x < 0 || pos_y < 0)
371 pos_x = pos_y = 0;
372 if (pos_x > GetSystemMetrics (SM_CXSCREEN)
373 || pos_y > GetSystemMetrics (SM_CYSCREEN)) {
374 pos_x = pos_y = 0;
375 }
376 kmi->pos_x = pos_x;
377 kmi->pos_y = pos_y;
378
379 GetClientRect (dlg, &rect);
380 MoveWindow (dlg, pos_x, pos_y, rect.right, rect.bottom, TRUE);
381 }
382
383
384 /* Resize the key manager window with the information from @kmi. */
385 static void
386 do_resize_window (HWND dlg, struct km_info_s *kmi)
387 {
388 HWND h;
389 RECT rclient, rect;
390 BOOL bRepaint = FALSE;
391
392 /* Get rect of client area and make life easier */
393 GetClientRect (dlg, &rclient);
394
395 /* Move toolbar to the top of the window */
396 if (kmi->toolbar) {
397 GetWindowRect (kmi->toolbar, &rect);
398 ScreenToClient (dlg, (POINT*)&rect);
399 ScreenToClient (dlg, (POINT*)&(rect.right));
400
401 rclient.top += rect.bottom - rect.top;
402 MoveWindow (kmi->toolbar, 0, 0, rclient.right - rclient.left,
403 rect.bottom - rect.top, bRepaint);
404 }
405
406 /* Move statusbar to the bottom of the window */
407 if (kmi->statbar) {
408 GetWindowRect (kmi->statbar, &rect);
409 ScreenToClient (dlg, (POINT*)&rect);
410 ScreenToClient (dlg, (POINT*)&(rect.right));
411
412 rclient.bottom -= rect.bottom - rect.top;
413 MoveWindow (kmi->statbar, 0, rclient.bottom,
414 rclient.right - rclient.left,
415 rect.bottom - rect.top, bRepaint);
416 }
417
418 /* Obtain separator information and move it to the desired posistion */
419 if (kmi->ypercent_sep)
420 kmi->ypos_sep = (rclient.bottom - rclient.top) * kmi->ypercent_sep / 100;
421 else
422 kmi->ypercent_sep = kmi->ypos_sep * 100 / (rclient.bottom - rclient.top);
423
424 /* Don't move away */
425 if (kmi->ypos_sep+5 > rclient.bottom)
426 kmi->ypos_sep = rclient.bottom - 5;
427 if (kmi->ypos_sep < rclient.top)
428 kmi->ypos_sep = rclient.top;
429 MoveWindow (kmi->hwnd_sep, 0, kmi->ypos_sep,
430 (rclient.right - rclient.left), 5, bRepaint);
431
432 /* Place the keylist above the separator */
433 h = GetDlgItem (dlg, IDC_KEYMISC_KEYLIST);
434 MoveWindow (h, rclient.left, rclient.top, rclient.right - rclient.left,
435 kmi->ypos_sep - rclient.top, bRepaint);
436 rclient.top = kmi->ypos_sep + 5 + 8;
437
438 if (kmi->enable_groups != 0) {
439 /* Place the group text and the group box below the separator */
440 h = GetDlgItem (dlg, IDC_KEYMISC_GTEXT);
441 MoveWindow (h, rclient.left, rclient.top, 100, 14, bRepaint);
442 rclient.top += 18;
443
444 h = GetDlgItem (dlg, IDC_KEYMISC_GROUP);
445 MoveWindow (h, rclient.left, rclient.top,
446 rclient.right - rclient.left,
447 (rclient.bottom < rclient.top) ?
448 0 : rclient.bottom - rclient.top, bRepaint);
449 }
450
451 /* Repaint the whole thing */
452 InvalidateRect (dlg, NULL, TRUE);
453 }
454
455
456 /* Return true if the clipboard contains an OpenPGP key. */
457 static bool
458 clip_contains_pgpkey (void)
459 {
460 char *ctxt;
461 bool val = false;
462
463 ctxt = get_clip_text (NULL);
464 if (!ctxt || strlen (ctxt) < 512)
465 val = false;
466 else if (strstr (ctxt, "BEGIN PGP") && strstr (ctxt, "KEY BLOCK") &&
467 strstr (ctxt, "END PGP"))
468 val = true;
469 free_if_alloc (ctxt);
470 return val;
471 }
472
473
474 /* Show a mini popup menu to import keys. */
475 static void
476 do_create_minpopup (HWND dlg)
477 {
478 HMENU hm;
479 POINT p;
480
481 if (gpg_read_only || !clip_contains_pgpkey ())
482 return;
483 hm = CreatePopupMenu ();
484 if (!hm)
485 BUG (0);
486 insert_menu_item (hm, 0, ID_KEYCTX_PASTE, _("Paste Key from Clipboard"));
487 GetCursorPos (&p);
488 TrackPopupMenu (hm, 0, p.x, p.y, 0, dlg, NULL);
489 DestroyMenu (hm);
490 }
491
492
493 /* Update the default key entry in the status bar for dialog @dlg. */
494 void
495 update_default_key_str (HWND dlg)
496 {
497 const char *fmt;
498 char *keyid;
499 char defkeyinf[128];
500
501 keyid = get_gnupg_default_key ();
502 if (!keyid)
503 return;
504 if ((keyid[0] >= 'A' && keyid[0] <= 'Z') ||
505 (keyid[0] >= 'a' && keyid[0] <= 'z') ||
506 (keyid[0] == '0' && keyid[1] == 'x'))
507 fmt = _("Default Key: %s");
508 else
509 fmt = _("Default Key: 0x%s");
510 _snprintf (defkeyinf, sizeof (defkeyinf) - 1, fmt, keyid);
511 SendMessage (dlg, SB_SETTEXT, 0, (LPARAM)defkeyinf);
512 gpg_keycache_set_default_key (keycache_get_ctx (0), keyid);
513 free_if_alloc (keyid);
514 }
515
516
517 /* Count all keys and show from @lv results in the status bar @sb. */
518 void
519 update_status_bar (HWND sb, listview_ctrl_t lv)
520 {
521 char txt_sec[128], txt_pub[128];
522 int nkeys = 0, nsec = 0;
523 int i;
524
525 nkeys = listview_count_items (lv, 0);
526 for (i = 0; i < nkeys; i++) {
527 if (km_check_for_seckey (lv, i, NULL))
528 nsec++;
529 }
530 _snprintf (txt_sec, sizeof (txt_sec)-1, _("%d secret keys"), nsec);
531 _snprintf (txt_pub, sizeof (txt_pub)-1, _("%d keys"), nkeys);
532 SendMessage (sb, SB_SETTEXT, 1, (LPARAM)txt_sec);
533 SendMessage (sb, SB_SETTEXT, 2, (LPARAM)txt_pub);
534 }
535
536
537 long CALLBACK
538 separator_wnd_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
539 {
540 static POINT last_mouse_pos;
541
542 if (msg == WM_CREATE)
543 SetWindowLong (hwnd, GWL_USERDATA,
544 (long)(((CREATESTRUCT*)lparam)->lpCreateParams));
545
546 switch (msg) {
547 case WM_PAINT:
548 PAINTSTRUCT ps;
549 RECT rect;
550 HPEN hpen;
551
552 GetClientRect (hwnd, &rect);
553 BeginPaint (hwnd, &ps);
554
555 /* Background */
556 FillRect (ps.hdc, &rect, (HBRUSH)(COLOR_3DFACE+1));
557
558 /* The lines from the light into the dark */
559 MoveToEx (ps.hdc, 0,0, NULL);
560 hpen = CreatePen (PS_SOLID, 0, GetSysColor (COLOR_3DHILIGHT));
561 if (hpen != NULL) {
562 SelectObject (ps.hdc, (LPVOID)hpen);
563 LineTo (ps.hdc, rect.right, 0);
564 DeleteObject (hpen);
565 }
566 MoveToEx (ps.hdc, 0, 1, NULL);
567 hpen = CreatePen (PS_SOLID, 0, GetSysColor (COLOR_3DLIGHT));
568 if (hpen != NULL) {
569 SelectObject (ps.hdc, (LPVOID)hpen);
570 LineTo (ps.hdc, rect.right, rect.bottom);
571 DeleteObject (hpen);
572 }
573
574 MoveToEx (ps.hdc, 0, rect.bottom-1, NULL);
575 hpen = CreatePen (PS_SOLID, 0, GetSysColor(COLOR_3DSHADOW));
576 if (hpen != NULL) {
577 SelectObject (ps.hdc, (LPVOID)hpen);
578 LineTo (ps.hdc, rect.right, rect.bottom-1);
579 DeleteObject (hpen);
580 }
581 MoveToEx (ps.hdc, 0, rect.bottom, NULL);
582 hpen = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW));
583 if (hpen != NULL) {
584 SelectObject (ps.hdc, (LPVOID)hpen);
585 LineTo (ps.hdc, rect.right, rect.bottom);
586 DeleteObject (hpen);
587 }
588
589 EndPaint (hwnd, &ps);
590 return 0;
591
592 case WM_LBUTTONDOWN:
593 last_mouse_pos.x = LOWORD (lparam);
594 last_mouse_pos.y = HIWORD (lparam);
595 ClientToScreen (hwnd, &last_mouse_pos);
596 SetCapture (hwnd);
597 return 0;
598
599 case WM_LBUTTONUP:
600 ReleaseCapture ();
601 return 0;
602
603 case WM_MOUSEMOVE:
604 if (wparam == MK_LBUTTON) {
605 struct km_info_s *kmi;
606 POINT p;
607 RECT r;
608
609 kmi = (struct km_info_s *)GetWindowLong (hwnd, GWL_USERDATA);
610 if (kmi == NULL)
611 break;
612
613 /* Calculate mouse movement */
614 p.x = LOWORD (lparam);
615 p.y = HIWORD (lparam);
616 ClientToScreen (hwnd, &p);
617
618 GetWindowRect (hwnd, &r);
619 r.top += (short)(p.y - last_mouse_pos.y);
620 r.bottom += (short)(p.y - last_mouse_pos.y);
621
622 last_mouse_pos.y = p.y;
623
624 /* Apply mouse movement to window. Beware the MoveWindow is relaive
625 to parent NOT screen */
626 MapWindowPoints (NULL, GetParent(hwnd), (POINT*)&r, 2);
627 kmi->ypos_sep = r.top;
628 kmi->ypercent_sep = 0; /* This forces do_resize_window to use abs. position */
629 do_resize_window (GetParent (hwnd), kmi);
630 return 0;
631 }
632 }
633
634 return DefWindowProc (hwnd, msg, wparam, lparam);
635 }
636
637
638 /* Register the separator window with @dlg as the parent window. */
639 static HWND
640 regist_sep_wnd (HWND dlg, struct km_info_s *kmi)
641 {
642 WNDCLASS wndclass;
643 HWND h;
644
645 wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
646 wndclass.lpfnWndProc = separator_wnd_proc;
647 wndclass.cbClsExtra = 0;
648 wndclass.cbWndExtra = sizeof (long);
649 wndclass.hInstance = glob_hinst;
650 wndclass.hIcon = NULL;
651 wndclass.hCursor = LoadCursor (NULL, IDC_SIZENS);
652 wndclass.hbrBackground = (HBRUSH) GetStockObject (LTGRAY_BRUSH);
653 wndclass.lpszMenuName = 0;
654 wndclass.lpszClassName = WINDOWCLASS_SEPARATOR_CHILD;
655 RegisterClass (&wndclass);
656
657 h = CreateWindowEx (WS_EX_WINDOWEDGE, WINDOWCLASS_SEPARATOR_CHILD, NULL,
658 WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
659 0, 400, 2000, 5, dlg, (HMENU) 0, glob_hinst, kmi);
660 ShowWindow (h, SW_SHOW);
661 return h;
662 }
663
664
665 #define enable_button(hwnd, cid, item_selected) \
666 SendMessage ((hwnd), TB_ENABLEBUTTON, (cid), MAKELONG ((item_selected), 0))
667
668
669 /* Interactive modification of the dialog item which depend if an item
670 is selected or not and what kind of item. @lv is the list view with
671 the items. */
672 void
673 update_ui_items (HWND hwnd, listview_ctrl_t lv)
674 {
675 HWND tb_hwnd;
676 HMENU hmenu;
677 int mult_resids[] = {ID_KEYMISC_PROPS, ID_KEYMISC_SIGN, ID_KEYMISC_EDITKEY,
678 ID_KEYMISC_CHECKSIGS, ID_KEYMISC_REVCERT, 0};
679 int key_selected = 0;
680 int key_has_sec = 0;
681 int key_inv = 0;
682 int i, state=0;
683
684 /* Get some states */
685 key_selected = SendMessage (GetDlgItem (hwnd, IDC_KEYMISC_KEYLIST),
686 LVM_GETSELECTEDCOUNT, 0, 0)
687 ? TRUE : FALSE;
688 key_has_sec = FALSE;
689 if (key_selected) {
690 i = listview_get_curr_pos (lv);
691 key_has_sec = km_check_for_seckey (lv, i, NULL) ? TRUE : FALSE;
692 key_inv = km_get_key_status (lv, i) & KM_FLAG_REVOKED ||
693 km_get_key_status (lv, i) & KM_FLAG_EXPIRED;
694 }
695
696 /* Enable / disable toolbar buttons */
697 tb_hwnd = GetDlgItem (hwnd, IDR_WINPT_KMTB);
698 enable_button (tb_hwnd, ID_KEYMISC_DELETE, key_selected);
699 enable_button (tb_hwnd, ID_KEYMISC_PROPS, key_selected);
700 enable_button (tb_hwnd, ID_KEYMISC_SIGN, key_selected && !key_inv);
701 enable_button (tb_hwnd, ID_KEYMISC_EXPORT, key_selected);
702 enable_button (tb_hwnd, ID_KEYCTX_COPY, key_selected);
703 enable_button (tb_hwnd, ID_KEYCTX_PASTE, clip_contains_pgpkey ());
704
705 /* Enable / disable menu items */
706 state = key_selected? MF_ENABLED : MF_DISABLED|MF_GRAYED;
707 hmenu = GetMenu (hwnd);
708 set_menu_state (hmenu, ID_KEYMISC_EXPORT, state);
709 set_menu_state (hmenu, ID_KEYMISC_DELETE, state);
710 set_menu_state (hmenu, ID_KEYMISC_PROPS, state);
711 set_menu_state (hmenu, ID_KEYMISC_EDITKEY, state);
712 set_menu_state (hmenu, ID_KEYMISC_CHECKSIGS, state);
713 set_menu_state (hmenu, ID_KEYMISC_SIGN,
714 key_selected && !key_inv ? MF_ENABLED : MF_GRAYED);
715 set_menu_state (hmenu, ID_KEYMISC_EXPORT_PRIVKEY,
716 key_selected && key_has_sec? MF_ENABLED : MF_GRAYED);
717 set_menu_state (hmenu, ID_KEYMISC_REVCERT,
718 key_selected && key_has_sec? MF_ENABLED : MF_GRAYED);
719
720 /* Disable some menu items when multiple keys are selected. */
721 if (listview_count_items (lv, 1) > 1) {
722 for (i=0; mult_resids[i] != 0; i++)
723 set_menu_state (hmenu, mult_resids[i], MF_GRAYED);
724 }
725
726 /* Disable all secret-key functions when no secret key is available. */
727 if (!secret_key_available ()) {
728 enable_button (tb_hwnd, ID_KEYMISC_SIGN, FALSE);
729 set_menu_state (hmenu, ID_KEYMISC_SIGN, MF_GRAYED);
730 }
731 }
732
733
734 /* Disable some context menu items when multiple keys are selected. */
735 static void
736 popup_multiple (HWND dlg, HMENU hm)
737 {
738 int resids[] = {
739 ID_KEYCTX_EDIT,
740 ID_KEYCTX_SIGN,
741 ID_KEYCTX_REV,
742 ID_KEYCTX_ENABLE,
743 ID_KEYCTX_DISABLE,
744 ID_KEYCTX_ADDKEY,
745 ID_KEYCTX_ADDPHOTO,
746 ID_KEYCTX_ADDUID,
747 ID_KEYCTX_ADDREV,
748 ID_KEYCTX_LISTSIGS,
749 ID_KEYCTX_MAXTRUST,
750 ID_KEYCTX_PROPS,
751 ID_KEYCTX_SENDMAIL,
752 0};
753 int i;
754 for (i=0; i < resids[i] != 0; i++)
755 set_menu_state (hm, resids[i], MF_GRAYED);
756 }
757
758
759 /* The items which are shown when GPG is in read-only mode. */
760 static void
761 popup_gpg_readonly (HWND dlg, HMENU hm)
762 {
763 int resids[] = {
764 ID_KEYCTX_PASTE,
765 ID_KEYCTX_EDIT,
766 ID_KEYCTX_SIGN,
767 ID_KEYCTX_REV,
768 ID_KEYCTX_DEL,
769 ID_KEYCTX_ENABLE,
770 ID_KEYCTX_DISABLE,
771 ID_KEYCTX_RECVFROM,
772 ID_KEYCTX_ADDKEY,
773 ID_KEYCTX_ADDPHOTO,
774 ID_KEYCTX_ADDUID,
775 ID_KEYCTX_ADDREV,
776 0
777 };
778 int i;
779
780 if (gpg_read_only == 0)
781 return;
782 for (i=0; resids[i] != 0; i++)
783 set_menu_state (hm, resids[i], MF_GRAYED);
784 }
785
786
787 /* Change the 'Edit' menu based on the current state. */
788 static void
789 change_edit_menu (listview_ctrl_t lv, HMENU hm, int id)
790 {
791 enum item { EDIT_MENU = 1 };
792 int no_sel;
793
794 if (id != EDIT_MENU)
795 return;
796
797 if (!clip_contains_pgpkey ())
798 set_menu_state (hm, ID_KEYMISC_PASTE, MF_GRAYED);
799 else
800 set_menu_state (hm, ID_KEYMISC_PASTE, MF_ENABLED);
801 no_sel = listview_get_curr_pos (lv) == -1? 1 : 0;
802 set_menu_state (hm, ID_KEYMISC_DELETE2, no_sel? MF_GRAYED: MF_ENABLED);
803 set_menu_state (hm, ID_KEYMISC_COPY, no_sel? MF_GRAYED : MF_ENABLED);
804 }
805
806
807
808 /* Show limited key menu entries when GPG is in read-only mode. */
809 static void
810 change_key_menu (HMENU hm, int id)
811 {
812 int key_resids[] = {
813 ID_KEYMISC_SIGN,
814 ID_KEYMISC_DELETE,
815 ID_KEYMISC_REVCERT,
816 ID_KEYMISC_IMPORT_HTTP,
817 ID_KEYMISC_IMPORT,
818 ID_KEYMISC_REFRESH_KEYS,
819 ID_KEYMISC_REBUILD,
820 ID_KEYMISC_KEYWIZARD,
821 ID_KEYMISC_CARDNEW,
822 ID_KEYMISC_NEWKEY,
823 0,
824 };
825 int edit_resids[] = {
826 ID_KEYMISC_PASTE,
827 ID_KEYMISC_OT,
828 ID_KEYMISC_EDITKEY,
829 0
830 };
831 int *resids;
832 int i;
833
834
835 if (gpg_read_only == 0)
836 return;
837 switch (id) {
838 case 0: return;
839 case 3: resids = key_resids; break;
840 case 1: resids = edit_resids;break;
841 default:resids = edit_resids; break;
842 }
843
844 for (i=0; resids[i] != 0; i++)
845 set_menu_state (hm, resids[i], MF_GRAYED);
846 }
847
848
849 /* Reload a single key in the cache. */
850 static void
851 update_key (listview_ctrl_t lv, int pos, const char *keyid, int keypair)
852 {
853 struct winpt_key_s key;
854
855 keycache_update (0, keyid);
856 if (keypair)
857 keycache_update (1, keyid);
858
859 /* because we replaced the key item, we need to update the
860 address of the pointer in the ListView control. */
861 memset (&key, 0, sizeof (key));
862 winpt_get_pubkey (keyid, &key);
863 keylist_upd_key (lv, pos, key.ext, key.ctx);
864 keyring_check_last_access ();
865 }
866
867
868 /* Setup status bar for the main window @dlg. */
869 static HWND
870 setup_status_bar (HWND dlg, listview_ctrl_t lv)
871 {
872 HWND statbar;
873 RECT r;
874 int partpos[3];
875 int i;
876
877 GetClientRect (dlg, &r);
878 for (i=1; i <= 3; i++)
879 partpos[i-1] = r.right/3*i;
880 statbar = CreateStatusWindow (WS_CHILD | WS_VISIBLE | CCS_BOTTOM,
881 "status bar", dlg, KM_SEPARATOR_ID);
882
883 ShowWindow (statbar, SW_SHOW);
884 SendMessage (statbar, SB_SETPARTS, (WPARAM)3, (LPARAM)partpos);
885
886 update_default_key_str (statbar);
887 update_status_bar (statbar, lv);
888
889 return statbar;
890 }
891
892
893 /* Remove or add columns which depends on the state of @checked. */
894 void
895 modify_listview_columns (km_info_s *kmi, UINT m_uid, BOOL checked)
896 {
897 UINT resids[] = {
898 0,
899 ID_KEYMISC_VIEWKEYID,
900 ID_KEYMISC_VIEWTYPE,
901 0,
902 ID_KEYMISC_VIEWCIPHER,
903 0,
904 0,
905 ID_KEYMISC_VIEWCREAT,
906 ID_KEYMISC_VIEWDESC,
907 -1
908 };
909 listview_column_s cols[] = {
910 {0, 240, (char *)_("User ID")},
911 {1, 78, (char *)_("Key ID")},
912 {2, 52, (char *)_("Type")},
913 {3, 66, (char *)_("Size")},
914 {4, 60, (char *)_("Cipher")},
915 {5, 66, (char *)_("Validity")},
916 {6, 58, (char *)_("Trust")},
917 {7, 72, (char *)_("Creation")},
918 {8, 160,(char *)_("Description")},
919 {0, 0, NULL}
920 };
921 UINT pos;
922
923 for (pos=0; resids[pos] != -1; pos++) {
924 if (m_uid == resids[pos])
925 break;
926 }
927 if (!checked)
928 listview_del_column (kmi->lv, (int)pos);
929 else {
930 listview_add_column (kmi->lv, &cols[pos]);
931 keylist_upd_col (kmi->lv, pos);
932 }
933 }
934
935
936 /* Helper to handle the help file. If @check is 1
937 the existence of the file is checked.
938 Otherwise the help file will be loaded. */
939 static bool
940 start_help (HWND dlg, int check)
941 {
942 DWORD n;
943 char path[MAX_PATH+1+32];
944
945 n = GetModuleFileName (NULL, path, sizeof (path)-1-32);
946 if (!n)
947 return false;
948 path[n] = 0;
949 while (n-- && path[n] != '\\')
950 ;
951 path[n+1] = 0;
952 strcat (path, "winpt.chm");
953 if (!check)
954 ShellExecute (dlg, "open", path, NULL, NULL, SW_SHOW);
955 return file_exist_check (path) == 0? true : false;
956 }
957
958 /* Translate all menu strings. */
959 static void
960 translate_menu_strings (HWND dlg)
961 {
962 HMENU menu;
963
964 menu = LoadMenu (glob_hinst, (LPCSTR)IDR_WINPT_KEYMISC);
965 set_menu_text_bypos (menu, 0, _("File"));
966 set_menu_text_bypos (menu, 1, _("Edit"));
967 set_menu_text_bypos (menu, 2, _("View"));
968 set_menu_text_bypos (menu, 3, _("Key"));
969 set_menu_text_bypos (menu, 4, _("Groups"));
970
971 set_menu_text (menu, ID_KEYMISC_EDITKEY, _("Edit"));
972 set_menu_text (menu, ID_KEYMISC_MAIL, _("Send Mail..."));
973 set_menu_text (menu, ID_KEYMISC_OT, _("Ownertrust")); /* XXX */
974 set_menu_text (menu, ID_KEYMISC_COPY, _("&Copy\tCtrl+C"));
975 set_menu_text (menu, ID_KEYMISC_PASTE, _("&Paste\tCtrl+V"));
976 set_menu_text (menu, ID_KEYMISC_FIND, _("Search...\tCtrl+F"));
977 set_menu_text (menu, ID_KEYMISC_SELALL, _("Select All\tCtrl+A"));
978 set_menu_text (menu, ID_KEYMISC_QUIT, _("&Quit"));
979 set_menu_text (menu, ID_KEYMISC_UID, _("User ID"));
980 set_menu_text (menu, ID_KEYMISC_NEWKEY, _("&Expert"));
981 set_menu_text (menu, ID_KEYMISC_KEYWIZARD, _("&Normal"));
982 set_menu_text (menu, ID_KEYMISC_EDIT, _("Edit"));
983 set_menu_text (menu, ID_KEYMISC_SIGN, _("&Sign"));
984 set_menu_text (menu, ID_KEYMISC_DELETE, _("&Delete"));
985 set_menu_text (menu, ID_KEYMISC_DELETE2, _("&Delete"));
986 set_menu_text (menu, ID_KEYMISC_REVCERT, _("&Revoke Cert"));
987 set_menu_text (menu, ID_KEYMISC_CHECKSIGS, _("&List Signatures"));
988 set_menu_text (menu, ID_KEYMISC_TRUSTPATH, _("List Trust Path"));
989 set_menu_text (menu, ID_KEYMISC_EXPORT, _("&Export..."));
990 set_menu_text (menu, ID_KEYMISC_IMPORT, _("&Import..."));
991 set_menu_text (menu, ID_KEYMISC_PROPS, _("&Properties"));
992 set_menu_text (menu, ID_KEYMISC_GPGOPT, _("Options"));
993 set_menu_text (menu, ID_KEYMISC_GPGPREFS, _("Preferences"));
994 set_menu_text (menu, ID_KEYMISC_SENDRECV, _("Keyserver") );
995 set_menu_text (menu, ID_KEYMISC_EXPORT_PRIVKEY, _("E&xport Secret Key"));
996 set_menu_text (menu, ID_KEYMISC_RECACHE, _("Re&load Key Cache"));
997 set_menu_text (menu, ID_KEYMISC_REBUILD, _("R&everify Signatures"));
998 set_menu_text (menu, ID_KEYMISC_REFRESH_KEYS, _("Refresh &Keys (Keyserver)"));
999 set_menu_text (menu, ID_KEYMISC_INFO, _("Info") );
1000 set_menu_text (menu, ID_KEYMISC_HELP, _("&Help"));
1001
1002 set_menu_text (menu, ID_KEYMISC_VIEWKEYID, _("Key ID"));
1003 set_menu_text (menu, ID_KEYMISC_VIEWCIPHER, _("Cipher"));
1004 set_menu_text (menu, ID_KEYMISC_VIEWTYPE, _("Type"));
1005 set_menu_text (menu, ID_KEYMISC_VIEWCREAT, _("Creation"));
1006
1007 if (!start_help (NULL, 1))
1008 set_menu_state (menu, ID_KEYMISC_HELP, MF_GRAYED);
1009
1010 SetMenu (dlg, menu);
1011 }
1012
1013
1014 /* Translate popup menu strings. */
1015 static void
1016 translate_popupmenu_strings (HMENU popup)
1017 {
1018 set_menu_text (popup, ID_KEYCTX_UID_COPY, _("Copy User ID to Clipboard"));
1019 set_menu_text (popup, ID_KEYCTX_KEYID_COPY, _("Copy Key ID to Clipboard"));
1020 set_menu_text (popup, ID_KEYCTX_FPR_COPY, _("Copy Fingerprint to Clipboard"));
1021 set_menu_text (popup, ID_KEYCTX_KINFO_COPY, _("Copy Key Info to Clipboard"));
1022 set_menu_text (popup, ID_KEYCTX_COPY, _("Copy Key to Clipboard"));
1023 set_menu_text (popup, ID_KEYCTX_PASTE, _("Paste Key from Clipboard"));
1024 set_menu_text (popup, ID_KEYCTX_RECVFROM, _("Refresh from Keyserver"));
1025 set_menu_text (popup, ID_KEYCTX_MAXTRUST, _("Set Implicit &Trust"));
1026 set_menu_text (popup, ID_KEYCTX_LISTSIGS, _("&List Signatures"));
1027 set_menu_text (popup, ID_KEYCTX_PROPS, _("&Properties"));
1028 set_menu_text (popup, ID_KEYCTX_EDIT, _("Key Edit"));
1029 set_menu_text (popup, ID_KEYCTX_DEL, _("&Delete"));
1030 set_menu_text (popup, ID_KEYCTX_REV, _("&Revoke Cert"));
1031 set_menu_text (popup, ID_KEYCTX_SIGN, _("&Sign"));
1032 set_menu_text (popup, ID_KEYCTX_ENABLE, _("&Enable"));
1033 set_menu_text (popup, ID_KEYCTX_DISABLE, _("&Disable"));
1034 set_menu_text (popup, ID_KEYCTX_RECVFROM, _("Re&fresh from Keyserver"));
1035 set_menu_text (popup, ID_KEYCTX_SETPREFKS, _("Set preferred Keyserver URL"));
1036 set_menu_text (popup, ID_KEYCTX_SENDMAIL, _("Send Key to Mail Recipient"));
1037 set_menu_text (popup, ID_KEYCTX_SETDEFKEY, _("Set as Default Key"));
1038
1039 set_menu_text (popup, ID_KEYCTX_ADDKEY, _("Key..."));
1040 set_menu_text (popup, ID_KEYCTX_ADDUID, _("User ID..."));
1041 set_menu_text (popup, ID_KEYCTX_ADDPHOTO, _("Photo ID..."));
1042 set_menu_text (popup, ID_KEYCTX_ADDREV, _("Revoker..."));
1043
1044 /* change popup texts */
1045 set_menu_text_bypos (popup, 0, _("Key Attributes"));
1046 set_menu_text_bypos (popup, 6, _("Add"));
1047 set_menu_text_bypos (popup, 19, _("Send to Keyserver"));
1048 }
1049
1050
1051 /* Return true if the cache contain marked keys. */
1052 static bool
1053 updated_keys_avail (void)
1054 {
1055 gpg_keycache_t kc = keycache_get_ctx (1);
1056 struct keycache_s *k;
1057
1058 for (k = kc->item; k; k = k->next) {
1059 if (k->flags)
1060 return true;
1061 }
1062 return false;
1063 }
1064
1065
1066 /* Find the index of the key identified by @key. */
1067 static int
1068 find_keypos (listview_ctrl_t lv, gpgme_key_t key)
1069 {
1070 char keyid[16+1];
1071 int i;
1072
1073 for (i=0; i < listview_count_items (lv, 0); i++) {
1074 listview_get_item_text (lv, i, KM_COL_KEYID, keyid, sizeof (keyid)-1);
1075 if (!strcmp (key->subkeys->keyid+8, keyid+2))
1076 return i;
1077 }
1078 return -1;
1079 }
1080
1081
1082 /* Add all recently updated keys in the cache to the list
1083 and refresh all GUI elements. */
1084 static void
1085 refresh_keylist (struct km_info_s *kmi)
1086 {
1087 struct keycache_s *ctx;
1088 gpg_keycache_t kc;
1089 int status=0, pos;
1090
1091 kc = keycache_get_ctx (1);
1092 while (!gpg_keycache_next_updated_key (kc, &ctx, &status)) {
1093 if (status == KC_FLAG_ADD)
1094 keylist_add_key (kmi->lv, KEYLIST_LIST, ctx, ctx->key);
1095 else {
1096 pos = find_keypos (kmi->lv, ctx->key);
1097 if (pos != -1)
1098 keylist_upd_key (kmi->lv, pos, ctx, ctx->key);
1099 }
1100 }
1101 keylist_sort (kmi->lv, kmi->keylist_sortby);
1102 update_status_bar (kmi->statbar, kmi->lv);
1103 keyring_check_last_access ();
1104 }
1105
1106
1107 /* Reload the key cache. */
1108 static void
1109 keycache_reload (HWND dlg)
1110 {
1111 refresh_cache_s rcs;
1112
1113 memset (&rcs, 0, sizeof rcs);
1114 rcs.kr_reload = rcs.kr_update = 1;
1115 rcs.tr_update = 0;
1116 DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYCACHE, dlg,
1117 keycache_dlg_proc, (LPARAM)&rcs);
1118 }
1119
1120
1121 /* Check if the secret keyring contains at least one
1122 key with ultimate trust.
1123 Return value: 0 on success. */
1124 int
1125 check_ultimate_trusted_key (gpg_keycache_t _sec)
1126 {
1127 struct keycache_s *n;
1128 int nkeys = 0;
1129
1130 for (n = _sec->item; n; n = n->next) {
1131 if (n->pubpart &&
1132 n->pubpart->key->owner_trust == GPGME_VALIDITY_ULTIMATE)
1133 return 0;
1134 nkeys++;
1135 }
1136
1137 /* if we do not have any secret keys, it does not make sense
1138 to return an error. */
1139 if (nkeys == 0)
1140 return 0;
1141 return -1;
1142 }
1143
1144
1145 static void
1146 reload_keylist (struct km_info_s *kmi)
1147 {
1148 gpg_keycache_t c;
1149
1150 c = keycache_get_ctx (1);
1151 keycache_reload (kmi->dlg);
1152 keylist_reload (kmi->lv, c, KEYLIST_LIST, kmi->keylist_sortby);
1153 update_status_bar (kmi->statbar, kmi->lv);
1154 keyring_check_last_access ();
1155 }
1156
1157
1158 /* Reload the entire key cache and update the listview. */
1159 static void
1160 reload_keycache (struct km_info_s *kmi)
1161 {
1162 refresh_cache_s rcs = {0};
1163 gpg_keycache_t c;
1164
1165 rcs.kr_reload = rcs.kr_update = 1;
1166 rcs.tr_update = 0;
1167 DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYCACHE, kmi->dlg,
1168 keycache_dlg_proc, (LPARAM)&rcs);
1169 c = keycache_get_ctx (1);
1170 keylist_reload (kmi->lv, c, KEYLIST_LIST, kmi->keylist_sortby);
1171 update_status_bar (kmi->statbar, kmi->lv);
1172 SetForegroundWindow (kmi->dlg);
1173 }
1174
1175
1176 /* Handle all import request. */
1177 static void
1178 km_gui_import (struct km_info_s *kmi, int cmd_id, void *param)
1179 {
1180 int newkeys=0, newsks=0;
1181 int err = 0;
1182
1183 switch (cmd_id) {
1184 case ID_KEYMISC_PASTE:
1185 err = km_clip_import (kmi->dlg, &newkeys, &newsks);
1186 break;
1187
1188 case ID_KEYMISC_IMPORT:
1189 err = km_file_import (kmi->dlg, NULL, &newkeys, &newsks);
1190 break;
1191
1192 case WM_DROPFILES:
1193 err = km_dropped_file_import (kmi->dlg, (HDROP)param,
1194 &newkeys, &newsks);
1195 break;
1196
1197 default:
1198 err = 1;
1199 break;
1200 }
1201
1202 if (!err && !newsks && (newkeys > 0 && newkeys < KM_PRELOAD_KEYS))
1203 refresh_keylist (kmi);
1204 else if (!err) /* avoid to spawn too much processes. */
1205 reload_keylist (kmi);
1206
1207 SetForegroundWindow (kmi->dlg);
1208 }
1209
1210
1211 /* Copy the requested key information (@what) to the clipboard.
1212 If multiple items were selected, each key info is copied to
1213 the clipboard. The data is separated by \r\n. */
1214 static void
1215 copy_key_info (int what, struct km_info_s *kmi)
1216 {
1217 gpgme_data_t out;
1218 gpgme_key_t key;
1219 struct keycache_s *kci = NULL;
1220 size_t n=0;
1221 char *p, tmp[256];
1222 int i=0, end = listview_count_items (kmi->lv, 0);
1223 bool single = false;
1224
1225 /* Do not iterate over the entire list if just one item is selected. */
1226 n = listview_count_items (kmi->lv, 1);
1227 if (n == 1) {
1228 i = kmi->lv_idx;
1229 end = i+1;
1230 single = true;
1231 }
1232
1233 gpgme_data_new (&out);
1234 for (; i < end; i++) {
1235 if (!listview_get_item_state (kmi->lv, i))
1236 continue;
1237 switch (what) {
1238 case ID_KEYCTX_UID_COPY:
1239 key = km_get_key_ptr (kmi->lv, i, &kci);
1240 gpgme_data_write (out, kci->uids->uid, strlen (kci->uids->uid));
1241 if (!single) gpgme_data_write (out, "\r\n", 2);
1242 break;
1243
1244 case ID_KEYCTX_KEYID_COPY:
1245 key = km_get_key_ptr (kmi->lv, i, NULL);
1246 gpgme_data_write (out, "0x", 2);
1247 gpgme_data_write (out, key->subkeys->keyid+8, 8);
1248 if (!single) gpgme_data_write (out, "\r\n", 2);
1249 break;
1250
1251 case ID_KEYCTX_FPR_COPY:
1252 key = km_get_key_ptr (kmi->lv, i, NULL);
1253 gpgme_data_write (out, key->subkeys->fpr, strlen (key->subkeys->fpr));
1254 if (!single) gpgme_data_write (out, "\r\n", 2);
1255 break;
1256
1257 case ID_KEYCTX_KINFO_COPY:
1258 key = km_get_key_ptr (kmi->lv, i, NULL);
1259 key_get_clip_info (key->subkeys->keyid+8, tmp, sizeof (tmp)-1);
1260 gpgme_data_write (out, tmp, strlen (tmp));
1261 if (!single) gpgme_data_write (out, "\r\n", 2);
1262 break;
1263 }
1264 }
1265 gpgme_data_write (out, "\0", 1);
1266 p = gpgme_data_release_and_get_mem (out, &n);
1267 set_clip_text (NULL, p, n);
1268 gpgme_free (p);
1269 }
1270
1271
1272 /* Dialog box procedure for the Key Manager. */
1273 BOOL CALLBACK
1274 keymanager_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1275 {
1276 HWND kl;
1277 HMENU hm;
1278 RECT r;
1279 gpg_keycache_t c;
1280 gpgme_key_t key;
1281 km_info_t kmi = NULL;
1282 struct genkey_s genkey;
1283 struct winpt_key_s k = {0};
1284 struct URL_ctx_s *url;
1285 char type[32], *name;
1286 const char *t, *host;
1287 WORD port = 0;
1288 int l_idx = 0, i=0, rc;
1289
1290 if ((msg != WM_INITDIALOG)
1291 && ((kmi = (km_info_t)GetWindowLong (dlg, GWL_USERDATA)) == NULL))
1292 return FALSE;
1293
1294 /* handle dynamic popup items in the keyserver menu. */
1295 if (msg == WM_COMMAND && LOWORD (wparam) >= WM_APP &&
1296 LOWORD (wparam) <= WM_APP+MAX_KEYSERVERS) {
1297 l_idx = LOWORD (wparam)-WM_APP;
1298 if (l_idx < 0)
1299 return TRUE;
1300 host = kserver_get_hostname (l_idx, 0, &port);
1301 if (host != NULL)
1302 km_send_to_keyserver (kmi->lv, dlg, host, port);
1303 return TRUE;
1304 }
1305
1306 switch (msg) {
1307 case WM_INITDIALOG:
1308 kmi = new struct km_info_s;
1309 memset (kmi, 0, sizeof (struct km_info_s));
1310 kmi->lv_idx = -1;
1311 kmi->hwnd_sep = regist_sep_wnd (dlg, kmi);
1312 imagelist_load (dlg);
1313 translate_menu_strings (dlg);
1314 SetWindowText (dlg, _("Key Manager"));
1315
1316 c = keycache_get_ctx (KEYCACHE_PUB);
1317 kl = GetDlgItem (dlg, IDC_KEYMISC_KEYLIST);
1318 kmi->keylist_sortby = KEY_SORT_USERID;
1319 Header_SetImageList(ListView_GetHeader (kl), glob_imagelist);
1320 kmi->lv = keylist_load (GetDlgItem (dlg, IDC_KEYMISC_KEYLIST), c,
1321 NULL, KEYLIST_LIST, kmi->keylist_sortby);
1322 if (check_ultimate_trusted_key (keycache_get_ctx (0))) {
1323 msg_box (dlg, _("No ultimately trusted key found.\n"
1324 "Please set at least one secret key to ultimate trust."),
1325 _("Key Manager"), MB_WARN);
1326 }
1327 /* init subclassing for the listview */
1328 keylist_proc.opaque = kmi;
1329 keylist_proc.dlg = dlg;
1330 keylist_proc.current = (WNDPROC)keylist_subclass_proc;
1331 keylist_proc.old = (WNDPROC)GetWindowLong(kl, GWL_WNDPROC);
1332 if (keylist_proc.old) {
1333 if (!SetWindowLong (kl, GWL_WNDPROC, (LONG)keylist_proc.current)) {
1334 msg_box (dlg, "Could not set keylist window procedure.",
1335 _("Key Manager"), MB_ERR);
1336 BUG (NULL);
1337 }
1338 }
1339 kmi->statbar = setup_status_bar (dlg, kmi->lv);
1340 SetWindowLong (dlg, GWL_USERDATA, (LONG)kmi);
1341 kmi->toolbar = create_toolbar (dlg, kmi);
1342 kmi->dlg = dlg;
1343
1344 do_center_window (dlg, kmi);
1345 do_resize_window (dlg, kmi);
1346 restore_window_size (dlg, kmi);
1347 update_ui_items (dlg, kmi->lv);
1348 restore_column_info (kmi);
1349 keylist_sort (kmi->lv, kmi->keylist_sortby);
1350
1351 SetDlgItemText (dlg, IDC_KEYMISC_GTEXT, _("Groups"));
1352 SetDlgItemText (dlg, ID_GROUP_SHOW, _("&Show"));
1353 SetDlgItemText (dlg, ID_GROUP_NEW, _("&New..."));
1354 SetClassLong (dlg, GCL_HICON, (LONG)LoadIcon (glob_hinst,
1355 (LPCTSTR)IDI_WINPT));
1356 SetForegroundWindow (dlg);
1357 kmi->magic = SetTimer (dlg, 1, 1000, NULL);
1358 return TRUE;
1359
1360 case WM_TIMER:
1361 KillTimer (dlg, kmi->magic);
1362 SetForegroundWindow (dlg);
1363 break;
1364
1365 case WM_DESTROY:
1366 save_column_info (kmi);
1367 if (kmi->lv) {
1368 keylist_delete (kmi->lv);
1369 kmi->lv = NULL;
1370 }
1371 imagelist_destroy ();
1372
1373 ltoa (kmi->pos_x, type, 10);
1374 set_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Pos_X", type);
1375 ltoa (kmi->pos_y, type, 10);
1376 set_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Pos_Y", type);
1377
1378 GetWindowRect (dlg, &r);
1379 sprintf (type, "%d", (int)(r.bottom-r.top));
1380 set_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Size_Width",
1381 type);
1382 sprintf (type, "%d", (int)(r.right-r.left));
1383 set_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Size_Height",
1384 type);
1385
1386 /* Remove runtime information. This should be the last action taken here. */
1387 delete kmi;
1388 kmi = NULL;
1389 SetWindowLong (dlg, GWL_USERDATA, 0);
1390 return FALSE;
1391
1392 case WM_MOVE:
1393 GetWindowRect (dlg, &r);
1394 kmi->pos_x = r.left;
1395 kmi->pos_y = r.top;
1396 break;
1397
1398
1399 case WM_RBUTTONUP:
1400 do_create_minpopup (dlg);
1401 break;
1402
1403 case WM_NOTIFY:
1404 NMHDR *notify;
1405 POINT p;
1406 HMENU popup;
1407
1408 notify = (NMHDR *)lparam;
1409 if (!notify)
1410 break;
1411 switch (notify->code) {
1412 case TBN_QUERYDELETE:
1413 SetWindowLong (dlg, DWL_MSGRESULT, TRUE);
1414 return TRUE;
1415
1416 case TBN_QUERYINSERT:
1417 SetWindowLong (dlg, DWL_MSGRESULT, TRUE);
1418 return TRUE;
1419
1420 case TBN_GETBUTTONINFO:
1421 LPTBNOTIFY lpTbNotify;
1422 lpTbNotify = (LPTBNOTIFY)lparam;
1423 if (lpTbNotify->iItem < (sizeof(myb) / sizeof(mybuttons))) {
1424 lpTbNotify->tbButton.iBitmap = imagelist_getindex (myb[lpTbNotify->iItem].icon);
1425 lpTbNotify->tbButton.idCommand = myb[lpTbNotify->iItem].command;
1426 lpTbNotify->tbButton.fsState = TBSTATE_ENABLED;
1427 lpTbNotify->tbButton.fsStyle = TBSTYLE_BUTTON;
1428 lpTbNotify->tbButton.iString = 0;
1429 strncpy (lpTbNotify->pszText, myb[lpTbNotify->iItem].text, lpTbNotify->cchText);
1430 SetWindowLong(dlg, DWL_MSGRESULT, TRUE);
1431 }
1432 return TRUE;
1433
1434 case TBN_RESET: /* Restore last saved toolbar status */
1435 TBSAVEPARAMS tbsp;
1436
1437 tbsp.hkr = HKEY_CURRENT_USER;
1438 tbsp.pszSubKey = "Software\\WinPT";
1439 tbsp.pszValueName = "KM_toolbar";
1440 SendMessage (notify->hwndFrom, TB_SAVERESTORE, FALSE, (LPARAM)&tbsp);
1441 break;
1442
1443 case TBN_BEGINADJUST: /* User is about to change the toolbar. Save it */
1444 tbsp.hkr = HKEY_CURRENT_USER;
1445 tbsp.pszSubKey = "Software\\WinPT";
1446 tbsp.pszValueName = "KM_toolbar";
1447 SendMessage (notify->hwndFrom, TB_SAVERESTORE, TRUE, (LPARAM)&tbsp);
1448 break;
1449
1450 case TBN_ENDADJUST: /* User has finished customizing the toolbar. Save it. */
1451 tbsp.hkr = HKEY_CURRENT_USER;
1452 tbsp.pszSubKey = "Software\\WinPT";
1453 tbsp.pszValueName = "KM_toolbar";
1454 SendMessage (notify->hwndFrom, TB_SAVERESTORE, TRUE, (LPARAM)&tbsp);
1455 break;
1456
1457 case TTN_GETDISPINFO:
1458 LPTOOLTIPTEXT lpttt;
1459 lpttt = (LPTOOLTIPTEXT)lparam;
1460
1461 lpttt->hinst = NULL;
1462 switch (lpttt->hdr.idFrom) {
1463 case ID_KEYMISC_KEYWIZARD:
1464 lpttt->lpszText = (char*)_("Generate new key pair");
1465 break;
1466
1467 case ID_KEYMISC_SENDRECV:
1468 lpttt->lpszText = (char*)_("Search for a specific key");
1469 break;
1470
1471 case ID_KEYMISC_DELETE:
1472 lpttt->lpszText = (char *)_("Delete key from keyring");
1473 break;
1474
1475 case ID_KEYMISC_PROPS:
1476 lpttt->lpszText = (char *)_("Show key properties");
1477 break;
1478
1479 case ID_KEYMISC_SIGN:
1480 lpttt->lpszText = (char *)_("Sign key");
1481 break;
1482
1483 case ID_KEYCTX_COPY:
1484 lpttt->lpszText = (char *)_("Copy key to clipboard");
1485 break;
1486
1487 case ID_KEYCTX_PASTE:
1488 lpttt->lpszText = (char*)_("Paste key from clipboard");
1489 break;
1490
1491 case ID_KEYMISC_IMPORT:
1492 lpttt->lpszText = (char *)_("Import key to keyring");
1493 break;
1494
1495 case ID_KEYMISC_EXPORT:
1496 lpttt->lpszText = (char *)_("Export key to a file");
1497 break;
1498 }
1499 return TRUE;
1500
1501 case LVN_ITEMCHANGED:
1502 if (((LPNMLISTVIEW)lparam)->uNewState) { /* item selected? */
1503 kmi->lv_idx = listview_get_curr_pos (kmi->lv);
1504 update_ui_items (dlg, kmi->lv);
1505 return TRUE;
1506 }
1507 break;
1508
1509 case NM_RCLICK:
1510 if (!wait_for_progress_cb (0))
1511 break;
1512 if (notify->idFrom == IDC_KEYMISC_KEYLIST) {
1513 l_idx =listview_get_curr_pos (kmi->lv);
1514 if (l_idx == -1)
1515 return TRUE; /* Popup only when a item was selected */
1516 GetCursorPos (&p);
1517 hm = LoadMenu (glob_hinst, MAKEINTRESOURCE (IDR_WINPT_KEYMISC_CTX));
1518 popup = GetSubMenu (hm, 0);
1519 translate_popupmenu_strings (popup);
1520
1521 if (km_check_for_seckey (kmi->lv, l_idx, &i))
1522 set_menu_state (popup, ID_KEYCTX_SETDEFKEY, MF_ENABLED);
1523 if (i == 0)
1524 set_menu_state (popup, ID_KEYCTX_MAXTRUST, MF_ENABLED);
1525 if (!km_check_for_seckey (kmi->lv, l_idx, NULL) ||
1526 (km_get_key_status (kmi->lv, l_idx) & KM_FLAG_REVOKED)) {
1527 set_menu_state (popup, ID_KEYCTX_REV, MF_DISABLED|MF_GRAYED);
1528 set_menu_state (popup, ID_KEYCTX_ADDKEY, MF_DISABLED|MF_GRAYED);
1529 set_menu_state (popup, ID_KEYCTX_ADDUID, MF_DISABLED|MF_GRAYED);
1530 set_menu_state (popup, ID_KEYCTX_ADDREV, MF_DISABLED|MF_GRAYED);
1531 set_menu_state (popup, ID_KEYCTX_ADDPHOTO, MF_DISABLED|MF_GRAYED );
1532 set_menu_state (popup, ID_KEYCTX_SETPREFKS, MF_DISABLED|MF_GRAYED);
1533 }
1534 else if (km_check_for_seckey (kmi->lv, l_idx, NULL) &&
1535 km_key_is_v3 (kmi->lv, l_idx)) {
1536 /* PGP 2 keys, version 3 have no no support for photo-id's,
1537 designated revokers and secondary keys. */
1538 set_menu_state (popup, ID_KEYCTX_ADDKEY, MF_DISABLED|MF_GRAYED);
1539 set_menu_state (popup, ID_KEYCTX_ADDREV, MF_DISABLED|MF_GRAYED);
1540 set_menu_state (popup, ID_KEYCTX_ADDPHOTO, MF_DISABLED|MF_GRAYED);
1541 }
1542 if (km_get_key_status( kmi->lv, l_idx ) & KM_FLAG_DISABLED)
1543 set_menu_state (popup, ID_KEYCTX_DISABLE, MF_DISABLED|MF_GRAYED);
1544 else
1545 set_menu_state (popup, ID_KEYCTX_ENABLE, MF_DISABLED|MF_GRAYED);
1546 if (km_get_key_status (kmi->lv, l_idx) & KM_FLAG_REVOKED ||
1547 km_get_key_status (kmi->lv, l_idx) & KM_FLAG_EXPIRED)
1548 set_menu_state (popup, ID_KEYCTX_SIGN, MF_DISABLED|MF_GRAYED);
1549 if (!clip_contains_pgpkey ())
1550 set_menu_state (popup, ID_KEYCTX_PASTE, MF_DISABLED|MF_GRAYED);
1551 if (mapi_init ())
1552 set_menu_state (popup, ID_KEYCTX_SENDMAIL, MF_DISABLED|MF_GRAYED);
1553 if (!secret_key_available ())
1554 set_menu_state (popup, ID_KEYCTX_SIGN, MF_DISABLED|MF_GRAYED);
1555
1556 /* Override 'Default Keyserver' with the actual name. */
1557 host = kserver_get_hostname (0, -1, &port);
1558 if (!host)
1559 host = DEF_HKP_KEYSERVER;
1560 set_menu_text (popup, ID_KEYCTX_KS_DEFAULT, host);
1561 {
1562 HMENU ks = GetSubMenu (popup, 19);
1563 for (i=0; server[i].name != NULL; i++)
1564 insert_menu_item (ks, i+2, WM_APP+i, server[i].name);
1565 }
1566 popup_gpg_readonly (dlg, popup);
1567 if (listview_count_items (kmi->lv, 1) > 1)
1568 popup_multiple (dlg, popup);
1569 TrackPopupMenu (popup, TPM_RIGHTALIGN, p.x, p.y, 0, dlg, NULL);
1570 DestroyMenu (popup);
1571 DestroyMenu (hm);
1572 return TRUE;
1573 }
1574 break;
1575
1576 case LVN_COLUMNCLICK:
1577 if (notify->idFrom == IDC_KEYMISC_KEYLIST) {
1578 NMLISTVIEW *nft = (LPNMLISTVIEW) lparam;
1579 int sortby = 0;
1580
1581 if (!wait_for_progress_cb (0))
1582 break;
1583 switch (nft->iSubItem) {
1584 case 0: sortby = KEY_SORT_USERID; break;
1585 case 1: sortby = KEY_SORT_KEYID; break;
1586 case 2: sortby = KEY_SORT_IS_SECRET; break;
1587 case 3: sortby = KEY_SORT_LEN; break;
1588 case 5: sortby = KEY_SORT_VALIDITY; break;
1589 case 6: sortby = KEY_SORT_OTRUST; break;
1590 case 7: sortby = KEY_SORT_CREATED; break;
1591 case 8: sortby = KEY_SORT_ALGO; break;
1592 default: return TRUE; /*sortby userid.*/
1593 }
1594
1595 if ((kmi->keylist_sortby & ~KEYLIST_SORT_DESC) == sortby)
1596 kmi->keylist_sortby ^= KEYLIST_SORT_DESC;
1597 else
1598 kmi->keylist_sortby = sortby;
1599 keylist_sort (kmi->lv, kmi->keylist_sortby);
1600 return TRUE;
1601 }
1602 break;
1603 }
1604 break;
1605
1606 case WM_WINDOWPOSCHANGING:
1607 if (((WINDOWPOS*)lparam)->cx < 400)
1608 ((WINDOWPOS*)lparam)->cx = 400;
1609 if (((WINDOWPOS*)lparam)->cy < 200)
1610 ((WINDOWPOS*)lparam)->cy = 200;
1611 return TRUE;
1612
1613 case WM_SIZE:
1614 do_resize_window (dlg, kmi);
1615 return TRUE;
1616
1617 case WM_SYSCOMMAND:
1618 if (LOWORD (wparam) == SC_CLOSE)
1619 EndDialog (dlg, TRUE);
1620 return FALSE;
1621
1622 case WM_MENUSELECT:
1623 change_edit_menu (kmi->lv, (HMENU)lparam, LOWORD (wparam));
1624 change_key_menu ((HMENU)lparam, LOWORD (wparam));
1625 break;
1626
1627 case WM_INITMENUPOPUP:
1628 if ((UINT)LOWORD (lparam) == 3) {
1629 HMENU h = (HMENU)wparam;
1630 set_menu_text_bypos (h, 0, _("New"));
1631 }
1632 /* XXX: before we can use it, we need to find a way to
1633 update the gpg access timestamp after each operation.
1634 if (keyring_check_last_access ())
1635 reload_keylist (kmi);
1636 */
1637 return FALSE;
1638
1639 case WM_COMMAND:
1640 /* Allow at least 'Exit' in such a case. */
1641 if (gnupg_access_keyring (1) && LOWORD (wparam) != ID_KEYMISC_QUIT) {
1642 msg_box (dlg, _("Could not access public keyring"),
1643 _("Key Manager"), MB_ERR);
1644 return FALSE;
1645 }
1646
1647 /*wait_for_progress_cb ();*/
1648 switch (LOWORD (wparam)) {
1649 case ID_KEYMISC_QUIT:
1650 EndDialog (dlg, TRUE);
1651 return TRUE;
1652
1653 case ID_KEYMISC_FIND:
1654 km_find_key (dlg, kmi->lv);
1655 break;
1656
1657 case ID_KEYMISC_DELETE:
1658 case ID_KEYMISC_DELETE2:
1659 if (!km_delete_keys (kmi->lv, dlg))
1660 update_status_bar (kmi->statbar, kmi->lv);
1661 return TRUE;
1662
1663 case ID_KEYMISC_SIGN:
1664 if (kmi->lv_idx == -1) {
1665 msg_box (dlg, _("Please select a key."),
1666 _("Key Manager"), MB_ERR);
1667 return TRUE;
1668 }
1669 if (km_check_key_status (kmi->lv, kmi->lv_idx))
1670 return TRUE;
1671 km_get_key (kmi->lv, kmi->lv_idx, &k);
1672 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYSIGN, dlg,
1673 keysign_dlg_proc, (LPARAM)&k,
1674 _("Key Signing"), IDS_WINPT_KEYSIGN);
1675 if (k.update)
1676 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 0);
1677 return TRUE;
1678
1679 case ID_KEYMISC_REVCERT:
1680 if (kmi->lv_idx == -1) {
1681 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
1682 return TRUE;
1683 }
1684
1685 {
1686 char state[64];
1687 listview_get_item_text (kmi->lv, kmi->lv_idx, 5,
1688 state, sizeof (state) -1);
1689 if (strchr (state, 'R' )) {
1690 msg_box (dlg, _("Key already revoked!"),
1691 _("Key Manager"), MB_INFO);
1692 return TRUE;
1693 }
1694 }
1695
1696 km_get_key (kmi->lv, kmi->lv_idx, &k);
1697 if (!k.key_pair) {
1698 msg_box (dlg, _("There is no secret key available!"),
1699 _("Key Manager"), MB_ERR);
1700 return TRUE;
1701 }
1702 dialog_box_param(glob_hinst, (LPCSTR)IDD_WINPT_KEYREVOKE, dlg,
1703 key_revoke_dlg_proc, (LPARAM)&k,
1704 _("Key Revocation Cert"), IDS_WINPT_KEYREVOKE);
1705 return TRUE;
1706
1707 case ID_KEYMISC_TRUSTPATH:
1708 if (kmi->lv_idx == -1) {
1709 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
1710 return TRUE;
1711 }
1712 km_get_key (kmi->lv, kmi->lv_idx, &k);
1713 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYTRUST, dlg,
1714 keytrust_dlg_proc, (LPARAM)&k,
1715 _("List Trust Path"), IDS_WINPT_KEYTRUST);
1716 return TRUE;
1717
1718 case ID_KEYMISC_CHECKSIGS:
1719 if (kmi->lv_idx == -1) {
1720 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
1721 return TRUE;
1722 }
1723 km_get_key (kmi->lv, kmi->lv_idx, &k);
1724 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYSIG_TREE, dlg,
1725 sigtree_dlg_proc, (LPARAM)&k,
1726 _("Key Signature List"), IDS_WINPT_KEYSIG);
1727 if (k.update)
1728 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 0);
1729 if (updated_keys_avail ())
1730 refresh_keylist (kmi);
1731 return TRUE;
1732
1733 case ID_KEYMISC_PROPS:
1734 if (kmi->lv_idx == -1) {
1735 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
1736 return TRUE;
1737 }
1738 km_get_key (kmi->lv, kmi->lv_idx, &k);
1739 k.callback.ctl = kmi->lv;
1740 k.callback.idx = kmi->lv_idx;
1741 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYPROPS, dlg,
1742 keyprops_dlg_proc, (LPARAM)&k,
1743 _("Key Properties"), IDS_WINPT_KEYPROPS);
1744 if (k.update)
1745 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, k.key_pair);
1746 return TRUE;
1747
1748 case ID_KEYMISC_RECACHE:
1749 if (updated_keys_avail ())
1750 l_idx = IDYES;
1751 else {
1752 l_idx = log_box (_("Key Manager"), MB_YESNO,
1753 _("This is only useful when the keyring has been "
1754 "modified (sign a key...).\n"
1755 "Do you really want to reload the keycache?"));
1756 }
1757 if (l_idx == IDYES)
1758 reload_keycache (kmi);
1759 return TRUE;
1760
1761 case ID_KEYMISC_REBUILD:
1762 name = NULL;
1763 gpg_rebuild_cache (&name);
1764 if (name != NULL) {
1765 char *line = strchr (name, '\n');
1766 show_msg (dlg, 2000, line? name + (line-name)+1 : name);
1767 safe_free (name);
1768 }
1769 SetForegroundWindow (dlg);
1770 return TRUE;
1771
1772 case ID_KEYMISC_NEWKEY:
1773 memset (&genkey, 0, sizeof (genkey));
1774 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYGEN, dlg,
1775 keygen_dlg_proc, (LPARAM)&genkey, _("Key Generation"),
1776 IDS_WINPT_KEYGEN);
1777 if (genkey.cancel == 0)
1778 refresh_keylist (kmi);
1779 return TRUE;
1780
1781 case ID_KEYMISC_CARDNEW:
1782 if (!scard_support) {
1783 msg_box (dlg, _("Smart Card support is not available."),
1784 _("Key Manager"), MB_INFO);
1785 return TRUE;
1786 }
1787 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_CARD_KEYGEN, dlg,
1788 card_keygen_dlg_proc, 0, _("Card Key Generation"),
1789 IDS_WINPT_CARD_KEYGEN);
1790 if (updated_keys_avail ())
1791 send_cmd_id (dlg, ID_KEYMISC_RECACHE);
1792 return TRUE;
1793
1794 case ID_KEYMISC_KEYWIZARD:
1795 memset (&genkey, 0, sizeof (genkey));
1796 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYWIZARD, dlg,
1797 keygen_wizard_dlg_proc, (LPARAM)&genkey,
1798 _("Key Generation Wizard"),
1799 IDS_WINPT_KEYWIZARD);
1800 if (genkey.cancel == 0)
1801 refresh_keylist (kmi);
1802 return TRUE;
1803
1804 case ID_KEYMISC_SENDRECV:
1805 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYSERVER, dlg,
1806 keyserver_dlg_proc, 0, _("Keyserver Access"),
1807 IDS_WINPT_KEYSERVER);
1808 refresh_keylist (kmi);
1809 return TRUE;
1810
1811 case ID_KEYMISC_GPGPREFS:
1812 rc = dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_GPGPREFS,
1813 dlg, gpgprefs_dlg_proc, 0,
1814 _("GnuPG Preferences"), IDS_WINPT_GPGPREFS);
1815 if (rc == TRUE) {
1816 reload_keycache (kmi);
1817 update_default_key_str (kmi->statbar);
1818 }
1819 return TRUE;
1820
1821 case ID_KEYMISC_GPGOPT:
1822 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_GPGOPT, dlg,
1823 gpgopt_dlg_proc, 0, _("GnuPG Options"),
1824 IDS_WINPT_GPGOPT);
1825 return TRUE;
1826
1827 case ID_KEYMISC_IMPORT:
1828 km_gui_import (kmi, LOWORD (wparam), NULL);
1829 return TRUE;
1830
1831 case ID_KEYMISC_IMPORT_HTTP:
1832 url = (struct URL_ctx_s*)get_http_file_dlg (dlg);
1833 if (url && url->cancel == 0) {
1834 km_http_import (dlg, url->url);
1835 refresh_keylist (kmi);
1836 }
1837 free_if_alloc (url);
1838 break;
1839
1840 case ID_KEYMISC_EXPORT:
1841 if (kmi->lv_idx == -1) {
1842 msg_box (dlg, _("Please select a key."),
1843 _("Key Manager"), MB_ERR);
1844 return TRUE;
1845 }
1846 if (listview_count_items (kmi->lv, 1) > 1)
1847 name = m_strdup ("Exported_GPG_Keys.asc");
1848 else {
1849 key = km_get_key_ptr (kmi->lv, kmi->lv_idx, NULL);
1850 name = km_gen_export_filename (key->subkeys->keyid+8, 0);
1851 }
1852 t = get_filesave_dlg (dlg, _("Choose Name for Key File"), NULL, name);
1853 free_if_alloc (name);
1854 if (t == NULL)
1855 return TRUE;
1856 km_file_export (dlg, kmi->lv, t);
1857 return TRUE;
1858
1859 case ID_KEYMISC_EXPORT_PRIVKEY:
1860 if (kmi->lv_idx == -1) {
1861 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
1862 return TRUE;
1863 }
1864 if( !km_check_for_seckey( kmi->lv, kmi->lv_idx, NULL ) ) {
1865 msg_box (dlg, _("There is no corresponding secret key for this key."),
1866 _("Key Manager"), MB_ERR);
1867 return TRUE;
1868 }
1869 if (listview_count_items (kmi->lv, 1) > 1) {
1870 msg_box (dlg, _("You can only export one secret key."),
1871 _("Key Manager"), MB_ERR);
1872 return TRUE;
1873 }
1874 i = msg_box (dlg,
1875 _("This operation will export your *SECRET* key!\n\n"
1876 "Never send this key to ANYONE, it should be available\n"
1877 "ONLY on your machine and you may use this function\n"
1878 "to copy the key to a safe place.\n\n"
1879 "Do you really want to export the key?"),
1880 _("WARNING"), MB_INFO|MB_YESNO);
1881 if (i == IDYES) {
1882 key = km_get_key_ptr (kmi->lv, kmi->lv_idx, NULL);
1883 name = km_gen_export_filename (key->subkeys->keyid+8, 1);
1884 t = get_filesave_dlg (dlg, _("Choose Name for Key File"), NULL, name);
1885 if (t != NULL)
1886 km_privkey_export (dlg, kmi->lv, t);
1887 }
1888 return TRUE;
1889
1890 case ID_KEYMISC_INFO:
1891 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_ABOUT, dlg,
1892 about_winpt_dlg_proc, 0, _("About WinPT"),
1893 IDS_WINPT_ABOUT);
1894 break;
1895
1896 case ID_KEYMISC_WEBSITE:
1897 ShellExecute (dlg, "open", "http://www.winpt.org",
1898 NULL, NULL, SW_SHOW);
1899 break;
1900
1901 case ID_KEYMISC_HELP:
1902 start_help (dlg, 0);
1903 break;
1904
1905 case ID_KEYMISC_OT:
1906 dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_OWNERTRUST,
1907 dlg, ownertrust_dlg_proc, 0,
1908 _("Ownertrust"), IDS_WINPT_OWNERTRUST);
1909 break;
1910
1911 case ID_KEYMISC_EDITKEY:
1912 if (km_get_key (kmi->lv, kmi->lv_idx, &k))
1913 break;
1914 dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT, dlg,
1915 keyedit_main_dlg_proc, (LPARAM)&k,
1916 _("Key Edit"), IDS_KEYCTX_EDIT);
1917 if (k.update)
1918 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 1);
1919 break;
1920
1921 case ID_KEYMISC_COPY:
1922 km_clip_export (dlg, kmi->lv);
1923 break;
1924
1925 case ID_KEYMISC_SELALL:
1926 listview_select_all (kmi->lv);
1927 break;
1928
1929 case ID_KEYMISC_PASTE:
1930 km_gui_import (kmi, LOWORD (wparam), NULL);
1931 break;
1932
1933 case ID_KEYCTX_SETPREFKS:
1934 if (km_get_key (kmi->lv, kmi->lv_idx, &k))
1935 break;
1936 keyedit_set_pref_keyserver (&k, dlg);
1937 break;
1938
1939 case ID_KEYMISC_REFRESH_KEYS:
1940 if (listview_count_items (kmi->lv, 1) == 0) {
1941 msg_box (dlg, _("No key was selected, select all by default."),
1942 _("Key Manager"), MB_INFO);
1943 listview_select_all (kmi->lv);
1944 }
1945 if (!km_refresh_from_keyserver (kmi->lv, dlg))
1946 msg_box (dlg, _("Keyserver refresh finished."),
1947 _("Key Manager"), MB_OK);
1948 break;
1949
1950 /** Context menu **/
1951 case ID_KEYCTX_EDIT:
1952 send_cmd_id( dlg, ID_KEYMISC_EDITKEY );
1953 break;
1954
1955 case ID_KEYCTX_PROPS:
1956 send_cmd_id( dlg, ID_KEYMISC_PROPS );
1957 break;
1958
1959 case ID_KEYCTX_UIDS:
1960 send_cmd_id( dlg, ID_KEYMISC_UID );
1961 break;
1962
1963 case ID_KEYCTX_SIGN:
1964 send_cmd_id( dlg, ID_KEYMISC_SIGN );
1965 break;
1966
1967 case ID_KEYCTX_DEL:
1968 send_cmd_id (dlg, ID_KEYMISC_DELETE);
1969 break;
1970
1971 case ID_KEYCTX_REV:
1972 send_cmd_id( dlg, ID_KEYMISC_REVCERT );
1973 break;
1974
1975 case ID_KEYCTX_SENDMAIL:
1976 km_send_to_mail_recipient (kmi->lv, dlg);
1977 break;
1978
1979 case ID_KEYCTX_KS_DEFAULT:
1980 host = kserver_get_hostname (0, -1, &port);
1981 km_send_to_keyserver (kmi->lv, dlg, host, port);
1982 break;
1983
1984 case ID_KEYCTX_ADDKEY:
1985 km_get_key (kmi->lv, kmi->lv_idx, &k);
1986 keyedit_add_subkey (&k, dlg, NULL);
1987 if (k.update)
1988 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 1);
1989 break;
1990
1991 case ID_KEYCTX_ADDUID:
1992 km_get_key (kmi->lv, kmi->lv_idx, &k);
1993 keyedit_add_userid (&k, dlg, NULL);
1994 if (k.update)
1995 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 1);
1996 break;
1997
1998 case ID_KEYCTX_ADDREV:
1999 km_get_key (kmi->lv, kmi->lv_idx, &k);
2000 keyedit_add_revoker (&k, dlg);
2001 if (k.update)
2002 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 1);
2003 break;
2004
2005 case ID_KEYCTX_ADDPHOTO:
2006 km_get_key (kmi->lv, kmi->lv_idx, &k);
2007 keyedit_add_photo (&k, dlg);
2008 if (k.update)
2009 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 1);
2010 break;
2011
2012 case ID_KEYCTX_RECVFROM:
2013 km_refresh_from_keyserver (kmi->lv, dlg);
2014 if (updated_keys_avail ())
2015 refresh_keylist (kmi);
2016 break;
2017
2018 case ID_KEYCTX_UID_COPY:
2019 case ID_KEYCTX_KEYID_COPY:
2020 case ID_KEYCTX_FPR_COPY:
2021 case ID_KEYCTX_KINFO_COPY:
2022 copy_key_info (LOWORD (wparam), kmi);
2023 break;
2024
2025 case ID_KEYCTX_COPY:
2026 send_cmd_id (dlg, ID_KEYMISC_COPY);
2027 break;
2028
2029 case ID_KEYCTX_PASTE:
2030 send_cmd_id (dlg, ID_KEYMISC_PASTE);
2031 break;
2032
2033 case ID_KEYCTX_DISABLE:
2034 case ID_KEYCTX_ENABLE:
2035 i = LOWORD (wparam) == ID_KEYCTX_ENABLE? 1 : 0;
2036 if (km_get_key (kmi->lv, kmi->lv_idx, &k))
2037 break;
2038 rc = km_enable_disable_key (kmi->lv, dlg, kmi->lv_idx, i);
2039 if (!rc)
2040 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 0);
2041 break;
2042
2043 case ID_KEYCTX_LISTSIGS:
2044 send_cmd_id (dlg, ID_KEYMISC_CHECKSIGS);
2045 break;
2046
2047 case ID_KEYCTX_MAXTRUST:
2048 if (km_get_key (kmi->lv, kmi->lv_idx, &k))
2049 break;
2050 rc = km_set_implicit_trust (dlg, kmi->lv, kmi->lv_idx);
2051 if (!rc)
2052 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 0);
2053 break;
2054
2055 case ID_KEYCTX_SETDEFKEY:
2056 if (!km_check_key_status (kmi->lv, kmi->lv_idx)) {
2057 key = km_get_key_ptr (kmi->lv, kmi->lv_idx, NULL);
2058 rc = set_gnupg_default_key (key->subkeys->keyid+8);
2059 if (rc)
2060 msg_box (dlg, winpt_strerror (rc), _("Key Manager"), MB_ERR);
2061 update_default_key_str (kmi->statbar);
2062 }
2063 break;
2064
2065 case ID_KEYMISC_VIEWKEYID:
2066 case ID_KEYMISC_VIEWCIPHER:
2067 case ID_KEYMISC_VIEWTYPE:
2068 case ID_KEYMISC_VIEWCREAT:
2069 case ID_KEYMISC_VIEWDESC:
2070 hm = GetMenu (dlg);
2071 i = get_menu_state (hm, LOWORD (wparam));
2072 set_menu_state (hm, LOWORD (wparam),
2073 i & MFS_CHECKED? MFS_UNCHECKED : MFS_CHECKED);
2074 modify_listview_columns (kmi, LOWORD (wparam), !(i & MFS_CHECKED));
2075 break;
2076
2077 case ID_GROUP_NEW:
2078 case ID_GROUP_PASTE:
2079 case ID_GROUP_DELETE:
2080 case ID_GROUP_SHOW:
2081 /* XXX: Implement group manager. */
2082 return TRUE;
2083 }
2084
2085 break;
2086 }
2087
2088 return FALSE;
2089 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26