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

Contents of /trunk/Src/wptKeyManagerDlg.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26