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

Contents of /trunk/Src/wptKeyManagerDlg.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 262 - (show annotations)
Sat Sep 30 10:24:34 2006 UTC (18 years, 5 months ago) by twoaday
File size: 64032 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 /* Return true if the cache contain marked keys. */
1055 static bool
1056 updated_keys_avail (void)
1057 {
1058 gpg_keycache_t kc = keycache_get_ctx (1);
1059 struct keycache_s *k;
1060
1061 for (k = kc->item; k; k = k->next) {
1062 if (k->flags)
1063 return true;
1064 }
1065 return false;
1066 }
1067
1068
1069 /* Find the index of the key identified by @key. */
1070 static int
1071 find_keypos (listview_ctrl_t lv, gpgme_key_t key)
1072 {
1073 char keyid[32+1];
1074 int i;
1075
1076 for (i=0; i < listview_count_items (lv, 0); i++) {
1077 listview_get_item_text (lv, i, KM_COL_KEYID, keyid, sizeof (keyid)-1);
1078 if (!strcmp (key->subkeys->keyid+8, keyid+2))
1079 return i;
1080 }
1081 return -1;
1082 }
1083
1084
1085 /* Add all recently updated keys in the cache to the list
1086 and refresh all GUI elements. */
1087 static void
1088 refresh_keylist (struct km_info_s *kmi)
1089 {
1090 struct keycache_s *ctx;
1091 gpg_keycache_t kc;
1092 int status=0, pos;
1093
1094 kc = keycache_get_ctx (1);
1095 while (!gpg_keycache_next_updated_key (kc, &ctx, &status)) {
1096 if (status == KC_FLAG_ADD)
1097 keylist_add_key (kmi->lv, KEYLIST_LIST, ctx, ctx->key);
1098 else {
1099 pos = find_keypos (kmi->lv, ctx->key);
1100 if (pos != -1)
1101 keylist_upd_key (kmi->lv, pos, ctx, ctx->key);
1102 }
1103 }
1104 keylist_sort (kmi->lv, kmi->keylist_sortby);
1105 update_status_bar (kmi->statbar, kmi->lv);
1106 keyring_check_last_access ();
1107 SetForegroundWindow (kmi->dlg);
1108 }
1109
1110
1111 /* Reload the key cache. */
1112 static void
1113 keycache_reload (HWND dlg)
1114 {
1115 refresh_cache_s rcs;
1116
1117 memset (&rcs, 0, sizeof rcs);
1118 rcs.kr_reload = rcs.kr_update = 1;
1119 rcs.tr_update = 0;
1120 DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYCACHE, dlg,
1121 keycache_dlg_proc, (LPARAM)&rcs);
1122 }
1123
1124
1125 /* Check if the secret keyring contains at least one
1126 key with ultimate trust.
1127 Return value: 0 on success. */
1128 int
1129 check_ultimate_trusted_key (gpg_keycache_t _sec)
1130 {
1131 struct keycache_s *n;
1132 int nkeys = 0;
1133
1134 for (n = _sec->item; n; n = n->next) {
1135 if (n->pubpart &&
1136 n->pubpart->key->owner_trust == GPGME_VALIDITY_ULTIMATE)
1137 return 0;
1138 nkeys++;
1139 }
1140
1141 /* if we do not have any secret keys, it does not make sense
1142 to return an error. */
1143 if (nkeys == 0)
1144 return 0;
1145 return -1;
1146 }
1147
1148
1149 /* Reload the entire key cache and update the listview. */
1150 static void
1151 reload_keycache (struct km_info_s *kmi)
1152 {
1153 gpg_keycache_t c;
1154
1155 keycache_reload (kmi->dlg);
1156 c = keycache_get_ctx (1);
1157 keylist_reload (kmi->lv, c, KEYLIST_LIST, kmi->keylist_sortby);
1158 update_status_bar (kmi->statbar, kmi->lv);
1159 SetForegroundWindow (kmi->dlg);
1160 keyring_check_last_access ();
1161 }
1162
1163
1164 /* Handle all import request. */
1165 static void
1166 km_gui_import (struct km_info_s *kmi, int cmd_id, void *param)
1167 {
1168 int newkeys = 0, newsks = 0;
1169 int err = 0;
1170
1171 switch (cmd_id) {
1172 case ID_KEYMISC_PASTE:
1173 err = km_clip_import (kmi->dlg, &newkeys, &newsks);
1174 break;
1175
1176 case ID_KEYMISC_IMPORT:
1177 err = km_file_import (kmi->dlg, NULL, &newkeys, &newsks);
1178 break;
1179
1180 case WM_DROPFILES:
1181 err = km_dropped_file_import (kmi->dlg, (HDROP)param,
1182 &newkeys, &newsks);
1183 break;
1184
1185 default:
1186 err = 1;
1187 break;
1188 }
1189
1190 if (!err && !newsks && (newkeys > 0 && newkeys < KM_PRELOAD_KEYS))
1191 refresh_keylist (kmi);
1192 else if (!err) /* avoid to spawn too much processes. */
1193 reload_keycache (kmi);
1194 SetForegroundWindow (kmi->dlg);
1195 }
1196
1197
1198 /* Copy the requested key information (@what) to the clipboard.
1199 If multiple items were selected, each key info is copied to
1200 the clipboard. The data is separated by \r\n. */
1201 static void
1202 copy_key_info (int what, struct km_info_s *kmi)
1203 {
1204 gpgme_data_t out;
1205 gpgme_key_t key;
1206 struct keycache_s *kci = NULL;
1207 size_t n=0;
1208 char *p, tmp[256];
1209 int i=0, end = listview_count_items (kmi->lv, 0);
1210 bool single = false;
1211
1212 /* Do not iterate over the entire list if just one item is selected. */
1213 n = listview_count_items (kmi->lv, 1);
1214 if (n == 1) {
1215 i = kmi->lv_idx;
1216 end = i+1;
1217 single = true;
1218 }
1219
1220 gpgme_data_new (&out);
1221 for (; i < end; i++) {
1222 if (!listview_get_item_state (kmi->lv, i))
1223 continue;
1224 switch (what) {
1225
1226 case ID_KEYCTX_EMAIL_COPY:
1227 key = km_get_key_ptr (kmi->lv, i, NULL);
1228 gpgme_data_write (out, key->uids->email, strlen (key->uids->email));
1229 if (!single) gpgme_data_write (out, "\r\n", 2);
1230 break;
1231
1232 case ID_KEYCTX_UID_COPY:
1233 key = km_get_key_ptr (kmi->lv, i, &kci);
1234 gpgme_data_write (out, kci->uids->uid, strlen (kci->uids->uid));
1235 if (!single) gpgme_data_write (out, "\r\n", 2);
1236 break;
1237
1238 case ID_KEYCTX_KEYID_COPY:
1239 key = km_get_key_ptr (kmi->lv, i, NULL);
1240 gpgme_data_write (out, "0x", 2);
1241 gpgme_data_write (out, key->subkeys->keyid+8, 8);
1242 if (!single) gpgme_data_write (out, "\r\n", 2);
1243 break;
1244
1245 case ID_KEYCTX_FPR_COPY:
1246 key = km_get_key_ptr (kmi->lv, i, NULL);
1247 gpgme_data_write (out, key->subkeys->fpr, strlen (key->subkeys->fpr));
1248 if (!single) gpgme_data_write (out, "\r\n", 2);
1249 break;
1250
1251 case ID_KEYCTX_KINFO_COPY:
1252 key = km_get_key_ptr (kmi->lv, i, NULL);
1253 key_get_clip_info (key->subkeys->keyid+8, tmp, sizeof (tmp)-1);
1254 gpgme_data_write (out, tmp, strlen (tmp));
1255 if (!single) gpgme_data_write (out, "\r\n", 2);
1256 break;
1257 }
1258 }
1259 gpgme_data_write (out, "\0", 1);
1260 p = gpgme_data_release_and_get_mem (out, &n);
1261 set_clip_text (NULL, p, n);
1262 gpgme_free (p);
1263 }
1264
1265
1266 /* Dialog box procedure for the Key Manager. */
1267 BOOL CALLBACK
1268 keymanager_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1269 {
1270 HWND kl;
1271 HMENU hm;
1272 RECT r;
1273 gpg_keycache_t c;
1274 gpgme_key_t key;
1275 km_info_t kmi = NULL;
1276 struct genkey_s genkey;
1277 struct winpt_key_s k = {0};
1278 struct URL_ctx_s *url;
1279 char type[32], *name;
1280 const char *t, *host;
1281 WORD port = 0;
1282 int l_idx = 0, i=0, rc;
1283
1284 if ((msg != WM_INITDIALOG)
1285 && ((kmi = (km_info_t)GetWindowLong (dlg, GWL_USERDATA)) == NULL))
1286 return FALSE;
1287
1288 /* handle dynamic popup items in the keyserver menu. */
1289 if (msg == WM_COMMAND && LOWORD (wparam) >= WM_APP &&
1290 LOWORD (wparam) <= WM_APP+MAX_KEYSERVERS) {
1291 l_idx = LOWORD (wparam)-WM_APP;
1292 if (l_idx < 0)
1293 return TRUE;
1294 host = kserver_get_hostname (l_idx, 0, &port);
1295 if (host != NULL)
1296 km_send_to_keyserver (kmi->lv, dlg, host, port);
1297 return TRUE;
1298 }
1299
1300 switch (msg) {
1301 case WM_INITDIALOG:
1302 kmi = new struct km_info_s;
1303 memset (kmi, 0, sizeof (struct km_info_s));
1304 kmi->lv_idx = -1;
1305 kmi->hwnd_sep = regist_sep_wnd (dlg, kmi);
1306 imagelist_load (dlg);
1307 translate_menu_strings (dlg);
1308 SetWindowText (dlg, _("Key Manager"));
1309
1310 c = keycache_get_ctx (KEYCACHE_PUB);
1311 kl = GetDlgItem (dlg, IDC_KEYMISC_KEYLIST);
1312 kmi->keylist_sortby = KEY_SORT_USERID;
1313 Header_SetImageList(ListView_GetHeader (kl), glob_imagelist);
1314 kmi->lv = keylist_load (GetDlgItem (dlg, IDC_KEYMISC_KEYLIST), c,
1315 NULL, KEYLIST_LIST, kmi->keylist_sortby);
1316 if (check_ultimate_trusted_key (keycache_get_ctx (0))) {
1317 msg_box (dlg, _("No ultimately trusted key found.\n"
1318 "Please set at least one secret key to ultimate trust."),
1319 _("Key Manager"), MB_WARN);
1320 }
1321 /* init subclassing for the listview */
1322 keylist_proc.opaque = kmi;
1323 keylist_proc.dlg = dlg;
1324 keylist_proc.current = (WNDPROC)keylist_subclass_proc;
1325 keylist_proc.old = (WNDPROC)GetWindowLong(kl, GWL_WNDPROC);
1326 if (keylist_proc.old) {
1327 if (!SetWindowLong (kl, GWL_WNDPROC, (LONG)keylist_proc.current)) {
1328 msg_box (dlg, "Could not set keylist window procedure.",
1329 _("Key Manager"), MB_ERR);
1330 BUG (NULL);
1331 }
1332 }
1333 kmi->statbar = setup_status_bar (dlg, kmi->lv);
1334 SetWindowLong (dlg, GWL_USERDATA, (LONG)kmi);
1335 kmi->toolbar = create_toolbar (dlg, kmi);
1336 kmi->dlg = dlg;
1337
1338 do_center_window (dlg, kmi);
1339 do_resize_window (dlg, kmi);
1340 restore_window_size (dlg, kmi);
1341 update_ui_items (dlg, kmi->lv);
1342 restore_column_info (kmi);
1343 keylist_sort (kmi->lv, kmi->keylist_sortby);
1344
1345 SendMessage (dlg, WM_SETICON, (WPARAM)ICON_SMALL,
1346 (LPARAM)LoadIcon (glob_hinst, (LPCTSTR)IDI_WINPT));
1347 SetDlgItemText (dlg, IDC_KEYMISC_GTEXT, _("Groups"));
1348 SetDlgItemText (dlg, ID_GROUP_SHOW, _("&Show"));
1349 SetDlgItemText (dlg, ID_GROUP_NEW, _("&New..."));
1350 SetForegroundWindow (dlg);
1351 kmi->magic = SetTimer (dlg, 1, 1000, NULL);
1352 return TRUE;
1353
1354
1355 case WM_TIMER:
1356 KillTimer (dlg, kmi->magic);
1357 SetForegroundWindow (dlg);
1358 break;
1359
1360 case WM_DESTROY:
1361 save_column_info (kmi);
1362 if (kmi->lv) {
1363 keylist_delete (kmi->lv);
1364 kmi->lv = NULL;
1365 }
1366 imagelist_destroy ();
1367
1368 ltoa (kmi->pos_x, type, 10);
1369 set_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Pos_X", type);
1370 ltoa (kmi->pos_y, type, 10);
1371 set_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Pos_Y", type);
1372
1373 GetWindowRect (dlg, &r);
1374 sprintf (type, "%d", (int)(r.bottom-r.top));
1375 set_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Size_Width",
1376 type);
1377 sprintf (type, "%d", (int)(r.right-r.left));
1378 set_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Size_Height",
1379 type);
1380
1381 /* Remove runtime information.
1382 This should be the last action taken here. */
1383 delete kmi;
1384 kmi = NULL;
1385 SetWindowLong (dlg, GWL_USERDATA, 0);
1386 return FALSE;
1387
1388 case WM_MOVE:
1389 GetWindowRect (dlg, &r);
1390 kmi->pos_x = r.left;
1391 kmi->pos_y = r.top;
1392 break;
1393
1394
1395 case WM_RBUTTONUP:
1396 do_create_minpopup (dlg);
1397 break;
1398
1399 case WM_NOTIFY:
1400 NMHDR *notify;
1401 POINT p;
1402 HMENU popup;
1403
1404 notify = (NMHDR *)lparam;
1405 if (!notify)
1406 break;
1407 switch (notify->code) {
1408 case TBN_QUERYDELETE:
1409 SetWindowLong (dlg, DWL_MSGRESULT, TRUE);
1410 return TRUE;
1411
1412 case TBN_QUERYINSERT:
1413 SetWindowLong (dlg, DWL_MSGRESULT, TRUE);
1414 return TRUE;
1415
1416 case TBN_GETBUTTONINFO:
1417 LPTBNOTIFY lpTbNotify;
1418 lpTbNotify = (LPTBNOTIFY)lparam;
1419 if (lpTbNotify->iItem < (sizeof(tbb) / sizeof(tb_button_s))) {
1420 lpTbNotify->tbButton.iBitmap = imagelist_getindex (tbb[lpTbNotify->iItem].icon);
1421 lpTbNotify->tbButton.idCommand = tbb[lpTbNotify->iItem].command;
1422 lpTbNotify->tbButton.fsState = TBSTATE_ENABLED;
1423 lpTbNotify->tbButton.fsStyle = TBSTYLE_BUTTON;
1424 lpTbNotify->tbButton.iString = 0;
1425 strncpy (lpTbNotify->pszText, tbb[lpTbNotify->iItem].text, lpTbNotify->cchText);
1426 SetWindowLong(dlg, DWL_MSGRESULT, TRUE);
1427 }
1428 return TRUE;
1429
1430 case TBN_RESET: /* Restore last saved toolbar status */
1431 TBSAVEPARAMS tbsp;
1432
1433 tbsp.hkr = HKEY_CURRENT_USER;
1434 tbsp.pszSubKey = "Software\\WinPT";
1435 tbsp.pszValueName = "KM_toolbar";
1436 SendMessage (notify->hwndFrom, TB_SAVERESTORE, FALSE, (LPARAM)&tbsp);
1437 break;
1438
1439 case TBN_BEGINADJUST: /* User is about to change the toolbar. Save it */
1440 tbsp.hkr = HKEY_CURRENT_USER;
1441 tbsp.pszSubKey = "Software\\WinPT";
1442 tbsp.pszValueName = "KM_toolbar";
1443 SendMessage (notify->hwndFrom, TB_SAVERESTORE, TRUE, (LPARAM)&tbsp);
1444 break;
1445
1446 case TBN_ENDADJUST: /* User has finished customizing the toolbar. Save it. */
1447 tbsp.hkr = HKEY_CURRENT_USER;
1448 tbsp.pszSubKey = "Software\\WinPT";
1449 tbsp.pszValueName = "KM_toolbar";
1450 SendMessage (notify->hwndFrom, TB_SAVERESTORE, TRUE, (LPARAM)&tbsp);
1451 break;
1452
1453 case TTN_GETDISPINFO:
1454 LPTOOLTIPTEXT lpttt;
1455 lpttt = (LPTOOLTIPTEXT)lparam;
1456
1457 lpttt->hinst = NULL;
1458 switch (lpttt->hdr.idFrom) {
1459 case ID_KEYMISC_KEYWIZARD:
1460 lpttt->lpszText = (char*)_("Generate new key pair");
1461 break;
1462
1463 case ID_KEYMISC_SENDRECV:
1464 lpttt->lpszText = (char*)_("Search for a specific key");
1465 break;
1466
1467 case ID_KEYMISC_DELETE:
1468 lpttt->lpszText = (char *)_("Delete key from keyring");
1469 break;
1470
1471 case ID_KEYMISC_PROPS:
1472 lpttt->lpszText = (char *)_("Show key properties");
1473 break;
1474
1475 case ID_KEYMISC_SIGN:
1476 lpttt->lpszText = (char *)_("Sign key");
1477 break;
1478
1479 case ID_KEYCTX_COPY:
1480 lpttt->lpszText = (char *)_("Copy key to clipboard");
1481 break;
1482
1483 case ID_KEYCTX_PASTE:
1484 lpttt->lpszText = (char*)_("Paste key from clipboard");
1485 break;
1486
1487 case ID_KEYMISC_IMPORT:
1488 lpttt->lpszText = (char *)_("Import key to keyring");
1489 break;
1490
1491 case ID_KEYMISC_EXPORT:
1492 lpttt->lpszText = (char *)_("Export key to a file");
1493 break;
1494 }
1495 return TRUE;
1496
1497 case LVN_ITEMCHANGED:
1498 if (((LPNMLISTVIEW)lparam)->uNewState) { /* item selected? */
1499 kmi->lv_idx = listview_get_curr_pos (kmi->lv);
1500 update_ui_items (dlg, kmi->lv);
1501 return TRUE;
1502 }
1503 break;
1504
1505 case NM_RCLICK:
1506 if (!wait_for_progress_cb (0))
1507 break;
1508 if (notify->idFrom == IDC_KEYMISC_KEYLIST) {
1509 l_idx =listview_get_curr_pos (kmi->lv);
1510 if (l_idx == -1)
1511 return TRUE; /* Popup only when a item was selected */
1512 GetCursorPos (&p);
1513 hm = LoadMenu (glob_hinst, MAKEINTRESOURCE (IDR_WINPT_KEYMISC_CTX));
1514 popup = GetSubMenu (hm, 0);
1515 translate_popupmenu_strings (popup);
1516
1517 if (km_check_for_seckey (kmi->lv, l_idx, &i))
1518 set_menu_state (popup, ID_KEYCTX_SETDEFKEY, MF_ENABLED);
1519 if (i == 0)
1520 set_menu_state (popup, ID_KEYCTX_MAXTRUST, MF_ENABLED);
1521 if (!km_check_for_seckey (kmi->lv, l_idx, NULL) ||
1522 (km_get_key_status (kmi->lv, l_idx) & KM_FLAG_REVOKED)) {
1523 set_menu_state (popup, ID_KEYCTX_REV, MF_DISABLED|MF_GRAYED);
1524 set_menu_state (popup, ID_KEYCTX_ADDKEY, MF_DISABLED|MF_GRAYED);
1525 set_menu_state (popup, ID_KEYCTX_ADDUID, MF_DISABLED|MF_GRAYED);
1526 set_menu_state (popup, ID_KEYCTX_ADDREV, MF_DISABLED|MF_GRAYED);
1527 set_menu_state (popup, ID_KEYCTX_ADDPHOTO, MF_DISABLED|MF_GRAYED );
1528 set_menu_state (popup, ID_KEYCTX_SETPREFKS, MF_DISABLED|MF_GRAYED);
1529 }
1530 else if (km_check_for_seckey (kmi->lv, l_idx, NULL) &&
1531 km_key_is_v3 (kmi->lv, l_idx)) {
1532 /* PGP 2 keys, version 3 have no no support for photo-id's,
1533 designated revokers and secondary keys. */
1534 set_menu_state (popup, ID_KEYCTX_ADDKEY, MF_DISABLED|MF_GRAYED);
1535 set_menu_state (popup, ID_KEYCTX_ADDREV, MF_DISABLED|MF_GRAYED);
1536 set_menu_state (popup, ID_KEYCTX_ADDPHOTO, MF_DISABLED|MF_GRAYED);
1537 }
1538 if (km_get_key_status( kmi->lv, l_idx ) & KM_FLAG_DISABLED)
1539 set_menu_state (popup, ID_KEYCTX_DISABLE, MF_DISABLED|MF_GRAYED);
1540 else
1541 set_menu_state (popup, ID_KEYCTX_ENABLE, MF_DISABLED|MF_GRAYED);
1542 if (km_get_key_status (kmi->lv, l_idx) & KM_FLAG_REVOKED ||
1543 km_get_key_status (kmi->lv, l_idx) & KM_FLAG_EXPIRED)
1544 set_menu_state (popup, ID_KEYCTX_SIGN, MF_DISABLED|MF_GRAYED);
1545 if (!clip_contains_pgpkey ())
1546 set_menu_state (popup, ID_KEYCTX_PASTE, MF_DISABLED|MF_GRAYED);
1547 if (mapi_init ())
1548 set_menu_state (popup, ID_KEYCTX_SENDMAIL, MF_DISABLED|MF_GRAYED);
1549 if (!secret_key_available ())
1550 set_menu_state (popup, ID_KEYCTX_SIGN, MF_DISABLED|MF_GRAYED);
1551
1552 /* Override 'Default Keyserver' with the actual name. */
1553 host = kserver_get_hostname (0, -1, &port);
1554 if (!host)
1555 host = DEF_HKP_KEYSERVER;
1556 set_menu_text (popup, ID_KEYCTX_KS_DEFAULT, host);
1557 {
1558 HMENU ks = GetSubMenu (popup, 19);
1559 for (i=0; server[i].name != NULL; i++)
1560 insert_menu_item (ks, i+2, WM_APP+i, server[i].name);
1561 }
1562 popup_gpg_readonly (dlg, popup);
1563 if (listview_count_items (kmi->lv, 1) > 1)
1564 popup_multiple (dlg, popup);
1565 TrackPopupMenu (popup, TPM_RIGHTALIGN, p.x, p.y, 0, dlg, NULL);
1566 DestroyMenu (popup);
1567 DestroyMenu (hm);
1568 return TRUE;
1569 }
1570 break;
1571
1572 case LVN_COLUMNCLICK:
1573 if (notify->idFrom == IDC_KEYMISC_KEYLIST) {
1574 NMLISTVIEW *nft = (LPNMLISTVIEW) lparam;
1575 int sortby = 0;
1576
1577 if (!wait_for_progress_cb (0))
1578 break;
1579 switch (nft->iSubItem) {
1580 case 0: sortby = KEY_SORT_USERID; break;
1581 case 1: sortby = KEY_SORT_KEYID; break;
1582 case 2: sortby = KEY_SORT_IS_SECRET; break;
1583 case 3: sortby = KEY_SORT_LEN; break;
1584 case 5: sortby = KEY_SORT_VALIDITY; break;
1585 case 6: sortby = KEY_SORT_OTRUST; break;
1586 case 7: sortby = KEY_SORT_CREATED; break;
1587 case 8: sortby = KEY_SORT_ALGO; break;
1588 default: return TRUE; /*sortby userid.*/
1589 }
1590
1591 if ((kmi->keylist_sortby & ~KEYLIST_SORT_DESC) == sortby)
1592 kmi->keylist_sortby ^= KEYLIST_SORT_DESC;
1593 else
1594 kmi->keylist_sortby = sortby;
1595 keylist_sort (kmi->lv, kmi->keylist_sortby);
1596 return TRUE;
1597 }
1598 break;
1599 }
1600 break;
1601
1602 case WM_WINDOWPOSCHANGING:
1603 if (((WINDOWPOS*)lparam)->cx < 400)
1604 ((WINDOWPOS*)lparam)->cx = 400;
1605 if (((WINDOWPOS*)lparam)->cy < 200)
1606 ((WINDOWPOS*)lparam)->cy = 200;
1607 return TRUE;
1608
1609 case WM_SIZE:
1610 do_resize_window (dlg, kmi);
1611 return TRUE;
1612
1613 case WM_SYSCOMMAND:
1614 if (LOWORD (wparam) == SC_CLOSE)
1615 EndDialog (dlg, TRUE);
1616 return FALSE;
1617
1618 case WM_MENUSELECT:
1619 change_edit_menu (kmi->lv, (HMENU)lparam, LOWORD (wparam));
1620 change_key_menu ((HMENU)lparam, LOWORD (wparam));
1621 break;
1622
1623 case WM_INITMENUPOPUP:
1624 hm = (HMENU)wparam;
1625 if ((UINT)LOWORD (lparam) == 3)
1626 set_menu_text_bypos (hm, 0, _("New"));
1627 else if ((UINT)LOWORD (lparam) == 1)
1628 set_menu_text_bypos (hm, 8, _("Preferences..."));
1629 return FALSE;
1630
1631 case WM_COMMAND:
1632 /* Allow at least 'Exit' in such a case. */
1633 if (gnupg_access_keyring (1) && LOWORD (wparam) != ID_KEYMISC_QUIT) {
1634 msg_box (dlg, _("Could not access public keyring"),
1635 _("Key Manager"), MB_ERR);
1636 return FALSE;
1637 }
1638
1639 /*wait_for_progress_cb ();*/
1640 switch (LOWORD (wparam)) {
1641 case ID_KEYMISC_QUIT:
1642 EndDialog (dlg, TRUE);
1643 return TRUE;
1644
1645 case ID_KEYMISC_FIND:
1646 km_find_key (dlg, kmi->lv);
1647 break;
1648
1649 case ID_KEYMISC_DELETE:
1650 case ID_KEYMISC_DELETE2:
1651 if (!km_delete_keys (kmi->lv, dlg))
1652 update_status_bar (kmi->statbar, kmi->lv);
1653 return TRUE;
1654
1655 case ID_KEYMISC_SIGN:
1656 if (kmi->lv_idx == -1) {
1657 msg_box (dlg, _("Please select a key."),
1658 _("Key Manager"), MB_ERR);
1659 return TRUE;
1660 }
1661 if (km_check_key_status (kmi->lv, kmi->lv_idx))
1662 return TRUE;
1663 km_get_key (kmi->lv, kmi->lv_idx, &k);
1664 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYSIGN, dlg,
1665 keysign_dlg_proc, (LPARAM)&k,
1666 _("Key Signing"), IDS_WINPT_KEYSIGN);
1667 if (k.update)
1668 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 0);
1669 return TRUE;
1670
1671 case ID_KEYMISC_REVCERT:
1672 if (kmi->lv_idx == -1) {
1673 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
1674 return TRUE;
1675 }
1676
1677 {
1678 char state[64];
1679 listview_get_item_text (kmi->lv, kmi->lv_idx, 5,
1680 state, sizeof (state) -1);
1681 if (strchr (state, 'R' )) {
1682 msg_box (dlg, _("Key already revoked!"),
1683 _("Key Manager"), MB_INFO);
1684 return TRUE;
1685 }
1686 }
1687
1688 km_get_key (kmi->lv, kmi->lv_idx, &k);
1689 if (!k.key_pair) {
1690 msg_box (dlg, _("There is no secret key available!"),
1691 _("Key Manager"), MB_ERR);
1692 return TRUE;
1693 }
1694 dialog_box_param(glob_hinst, (LPCSTR)IDD_WINPT_KEYREVOKE, dlg,
1695 key_revoke_dlg_proc, (LPARAM)&k,
1696 _("Key Revocation Cert"), IDS_WINPT_KEYREVOKE);
1697 return TRUE;
1698
1699 case ID_KEYMISC_TRUSTPATH:
1700 if (kmi->lv_idx == -1) {
1701 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
1702 return TRUE;
1703 }
1704 km_get_key (kmi->lv, kmi->lv_idx, &k);
1705 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYTRUST, dlg,
1706 keytrust_dlg_proc, (LPARAM)&k,
1707 _("List Trust Path"), IDS_WINPT_KEYTRUST);
1708 return TRUE;
1709
1710 case ID_KEYMISC_CHECKSIGS:
1711 if (kmi->lv_idx == -1) {
1712 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
1713 return TRUE;
1714 }
1715 km_get_key (kmi->lv, kmi->lv_idx, &k);
1716 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYSIG_TREE, dlg,
1717 sigtree_dlg_proc, (LPARAM)&k,
1718 _("Key Signature List"), IDS_WINPT_KEYSIG);
1719 if (k.update)
1720 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 0);
1721 if (updated_keys_avail ())
1722 refresh_keylist (kmi);
1723 return TRUE;
1724
1725 case ID_KEYMISC_PROPS:
1726 if (kmi->lv_idx == -1) {
1727 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
1728 return TRUE;
1729 }
1730 km_get_key (kmi->lv, kmi->lv_idx, &k);
1731 k.callback.ctl = kmi->lv;
1732 k.callback.idx = kmi->lv_idx;
1733 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYPROPS, dlg,
1734 keyprops_dlg_proc, (LPARAM)&k,
1735 _("Key Properties"), IDS_WINPT_KEYPROPS);
1736 if (k.update)
1737 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, k.key_pair);
1738 return TRUE;
1739
1740 case ID_KEYMISC_RECACHE:
1741 if (updated_keys_avail ())
1742 l_idx = IDYES;
1743 else {
1744 l_idx = log_box (_("Key Manager"), MB_YESNO,
1745 _("This is only useful when the keyring has been "
1746 "modified (sign a key...).\n"
1747 "Do you really want to reload the keycache?"));
1748 }
1749 if (l_idx == IDYES)
1750 reload_keycache (kmi);
1751 return TRUE;
1752
1753 case ID_KEYMISC_REBUILD:
1754 name = NULL;
1755 gpg_rebuild_cache (&name);
1756 if (name != NULL) {
1757 char *line = strchr (name, '\n');
1758 show_msg (dlg, 2000, line? name + (line-name)+1 : name);
1759 safe_free (name);
1760 }
1761 SetForegroundWindow (dlg);
1762 return TRUE;
1763
1764 case ID_KEYMISC_NEWKEY:
1765 memset (&genkey, 0, sizeof (genkey));
1766 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYGEN, dlg,
1767 keygen_dlg_proc, (LPARAM)&genkey, _("Key Generation"),
1768 IDS_WINPT_KEYGEN);
1769 if (genkey.cancel == 0)
1770 refresh_keylist (kmi);
1771 return TRUE;
1772
1773 case ID_KEYMISC_CARDNEW:
1774 if (!scard_support) {
1775 msg_box (dlg, _("Smart Card support is not available."),
1776 _("Key Manager"), MB_INFO);
1777 return TRUE;
1778 }
1779 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_CARD_KEYGEN, dlg,
1780 card_keygen_dlg_proc, 0, _("Card Key Generation"),
1781 IDS_WINPT_CARD_KEYGEN);
1782 if (updated_keys_avail ())
1783 send_cmd_id (dlg, ID_KEYMISC_RECACHE);
1784 return TRUE;
1785
1786 case ID_KEYMISC_KEYWIZARD:
1787 memset (&genkey, 0, sizeof (genkey));
1788 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYWIZARD, dlg,
1789 keygen_wizard_dlg_proc, (LPARAM)&genkey,
1790 _("Key Generation Wizard"),
1791 IDS_WINPT_KEYWIZARD);
1792 if (genkey.cancel == 0)
1793 refresh_keylist (kmi);
1794 return TRUE;
1795
1796 case ID_KEYMISC_SENDRECV:
1797 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYSERVER, dlg,
1798 keyserver_dlg_proc, 0, _("Keyserver Access"),
1799 IDS_WINPT_KEYSERVER);
1800 refresh_keylist (kmi);
1801 return TRUE;
1802
1803 case ID_KEYMISC_WINPTPREFS:
1804 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_PREFS,
1805 dlg, prefs_dlg_proc, 0,
1806 _("WinPT Preferences"), 0);
1807 break;
1808
1809 case ID_KEYMISC_GPGPREFS:
1810 rc = dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_GPGPREFS,
1811 dlg, gpgprefs_dlg_proc, 0,
1812 _("GnuPG Preferences"), IDS_WINPT_GPGPREFS);
1813 if (rc == TRUE) {
1814 reload_keycache (kmi);
1815 update_default_key_str (kmi->statbar);
1816 }
1817 return TRUE;
1818
1819 case ID_KEYMISC_GPGOPT:
1820 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_GPGOPT, dlg,
1821 gpgopt_dlg_proc, 0, _("GnuPG Options"),
1822 IDS_WINPT_GPGOPT);
1823 return TRUE;
1824
1825 case ID_KEYMISC_IMPORT:
1826 km_gui_import (kmi, LOWORD (wparam), NULL);
1827 return TRUE;
1828
1829 case ID_KEYMISC_IMPORT_HTTP:
1830 url = (struct URL_ctx_s*)get_http_file_dlg (dlg);
1831 if (url && url->cancel == 0) {
1832 km_http_import (dlg, url->url);
1833 refresh_keylist (kmi);
1834 }
1835 free_if_alloc (url);
1836 break;
1837
1838 case ID_KEYMISC_EXPORT:
1839 if (kmi->lv_idx == -1) {
1840 msg_box (dlg, _("Please select a key."),
1841 _("Key Manager"), MB_ERR);
1842 return TRUE;
1843 }
1844 if (listview_count_items (kmi->lv, 1) > 1)
1845 name = m_strdup ("Exported_GPG_Keys.asc");
1846 else {
1847 key = km_get_key_ptr (kmi->lv, kmi->lv_idx, NULL);
1848 name = km_gen_export_filename (key->subkeys->keyid+8, 0);
1849 }
1850 t = get_filesave_dlg (dlg, _("Choose Name for Key File"), NULL, name);
1851 free_if_alloc (name);
1852 if (t == NULL)
1853 return TRUE;
1854 km_file_export (dlg, kmi->lv, t);
1855 return TRUE;
1856
1857 case ID_KEYMISC_EXPORT_PRIVKEY:
1858 if (kmi->lv_idx == -1) {
1859 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
1860 return TRUE;
1861 }
1862 if( !km_check_for_seckey( kmi->lv, kmi->lv_idx, NULL ) ) {
1863 msg_box (dlg, _("There is no corresponding secret key for this key."),
1864 _("Key Manager"), MB_ERR);
1865 return TRUE;
1866 }
1867 if (listview_count_items (kmi->lv, 1) > 1) {
1868 msg_box (dlg, _("You can only export one secret key."),
1869 _("Key Manager"), MB_ERR);
1870 return TRUE;
1871 }
1872 i = msg_box (dlg,
1873 _("This operation will export your *SECRET* key!\n\n"
1874 "Never send this key to ANYONE, it should be available\n"
1875 "ONLY on your machine and you may use this function\n"
1876 "to copy the key to a safe place.\n\n"
1877 "Do you really want to export the key?"),
1878 _("WARNING"), MB_INFO|MB_YESNO);
1879 if (i == IDYES) {
1880 key = km_get_key_ptr (kmi->lv, kmi->lv_idx, NULL);
1881 name = km_gen_export_filename (key->subkeys->keyid+8, 1);
1882 t = get_filesave_dlg (dlg, _("Choose Name for Key File"), NULL, name);
1883 if (t != NULL)
1884 km_privkey_export (dlg, kmi->lv, t);
1885 }
1886 return TRUE;
1887
1888 case ID_KEYMISC_INFO:
1889 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_ABOUT, dlg,
1890 about_winpt_dlg_proc, 0, _("About WinPT"),
1891 IDS_WINPT_ABOUT);
1892 break;
1893
1894 case ID_KEYMISC_DEVWWW:
1895 ShellExecute (dlg, "open", "http://wald.intevation.org/projects/winpt",
1896 NULL, NULL, SW_SHOW);
1897 break;
1898
1899 case ID_KEYMISC_WEBSITE:
1900 ShellExecute (dlg, "open", "http://www.winpt.org",
1901 NULL, NULL, SW_SHOW);
1902 break;
1903
1904 case ID_KEYMISC_HELP:
1905 start_help (dlg, 0);
1906 break;
1907
1908 case ID_KEYMISC_OT:
1909 dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_OWNERTRUST,
1910 dlg, ownertrust_dlg_proc, 0,
1911 _("Ownertrust"), IDS_WINPT_OWNERTRUST);
1912 break;
1913
1914 case ID_KEYMISC_EDITKEY:
1915 if (km_get_key (kmi->lv, kmi->lv_idx, &k))
1916 break;
1917 dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT, dlg,
1918 keyedit_main_dlg_proc, (LPARAM)&k,
1919 _("Key Edit"), IDS_KEYCTX_EDIT);
1920 if (k.update)
1921 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 1);
1922 break;
1923
1924 case ID_KEYMISC_COPY:
1925 km_clip_export (dlg, kmi->lv);
1926 break;
1927
1928 case ID_KEYMISC_SELALL:
1929 listview_select_all (kmi->lv);
1930 break;
1931
1932 case ID_KEYMISC_PASTE:
1933 km_gui_import (kmi, LOWORD (wparam), NULL);
1934 break;
1935
1936 case ID_KEYCTX_SETPREFKS:
1937 if (km_get_key (kmi->lv, kmi->lv_idx, &k))
1938 break;
1939 keyedit_set_pref_keyserver (&k, dlg);
1940 break;
1941
1942 case ID_KEYMISC_REFRESH_KEYS:
1943 if (listview_count_items (kmi->lv, 1) == 0) {
1944 msg_box (dlg, _("No key was selected, select all by default."),
1945 _("Key Manager"), MB_INFO);
1946 listview_select_all (kmi->lv);
1947 }
1948 if (!km_refresh_from_keyserver (kmi->lv, dlg))
1949 msg_box (dlg, _("Keyserver refresh finished."),
1950 _("Key Manager"), MB_OK);
1951 break;
1952
1953 /** Context menu **/
1954 case ID_KEYCTX_EDIT:
1955 send_cmd_id( dlg, ID_KEYMISC_EDITKEY );
1956 break;
1957
1958 case ID_KEYCTX_PROPS:
1959 send_cmd_id( dlg, ID_KEYMISC_PROPS );
1960 break;
1961
1962 case ID_KEYCTX_UIDS:
1963 send_cmd_id( dlg, ID_KEYMISC_UID );
1964 break;
1965
1966 case ID_KEYCTX_SIGN:
1967 send_cmd_id( dlg, ID_KEYMISC_SIGN );
1968 break;
1969
1970 case ID_KEYCTX_DEL:
1971 send_cmd_id (dlg, ID_KEYMISC_DELETE);
1972 break;
1973
1974 case ID_KEYCTX_REV:
1975 send_cmd_id( dlg, ID_KEYMISC_REVCERT );
1976 break;
1977
1978 case ID_KEYCTX_SENDMAIL:
1979 km_send_to_mail_recipient (kmi->lv, dlg);
1980 break;
1981
1982 case ID_KEYCTX_KS_DEFAULT:
1983 host = kserver_get_hostname (0, -1, &port);
1984 km_send_to_keyserver (kmi->lv, dlg, host, port);
1985 break;
1986
1987 case ID_KEYCTX_ADDKEY:
1988 km_get_key (kmi->lv, kmi->lv_idx, &k);
1989 keyedit_add_subkey (&k, dlg, NULL);
1990 if (k.update)
1991 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 1);
1992 break;
1993
1994 case ID_KEYCTX_ADDUID:
1995 km_get_key (kmi->lv, kmi->lv_idx, &k);
1996 keyedit_add_userid (&k, dlg, NULL);
1997 if (k.update)
1998 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 1);
1999 break;
2000
2001 case ID_KEYCTX_ADDREV:
2002 km_get_key (kmi->lv, kmi->lv_idx, &k);
2003 keyedit_add_revoker (&k, dlg);
2004 if (k.update)
2005 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 1);
2006 break;
2007
2008 case ID_KEYCTX_ADDPHOTO:
2009 km_get_key (kmi->lv, kmi->lv_idx, &k);
2010 keyedit_add_photo (&k, dlg);
2011 if (k.update)
2012 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 1);
2013 break;
2014
2015 case ID_KEYCTX_RECVFROM:
2016 km_refresh_from_keyserver (kmi->lv, dlg);
2017 if (updated_keys_avail ())
2018 refresh_keylist (kmi);
2019 break;
2020
2021 case ID_KEYCTX_UID_COPY:
2022 case ID_KEYCTX_KEYID_COPY:
2023 case ID_KEYCTX_FPR_COPY:
2024 case ID_KEYCTX_KINFO_COPY:
2025 case ID_KEYCTX_EMAIL_COPY:
2026 copy_key_info (LOWORD (wparam), kmi);
2027 break;
2028
2029 case ID_KEYCTX_COPY:
2030 send_cmd_id (dlg, ID_KEYMISC_COPY);
2031 break;
2032
2033 case ID_KEYCTX_PASTE:
2034 send_cmd_id (dlg, ID_KEYMISC_PASTE);
2035 break;
2036
2037 case ID_KEYCTX_DISABLE:
2038 case ID_KEYCTX_ENABLE:
2039 i = LOWORD (wparam) == ID_KEYCTX_ENABLE? 1 : 0;
2040 if (km_get_key (kmi->lv, kmi->lv_idx, &k))
2041 break;
2042 rc = km_enable_disable_key (kmi->lv, dlg, kmi->lv_idx, i);
2043 if (!rc)
2044 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 0);
2045 break;
2046
2047 case ID_KEYCTX_LISTSIGS:
2048 send_cmd_id (dlg, ID_KEYMISC_CHECKSIGS);
2049 break;
2050
2051 case ID_KEYCTX_MAXTRUST:
2052 if (km_get_key (kmi->lv, kmi->lv_idx, &k))
2053 break;
2054 rc = km_set_implicit_trust (dlg, kmi->lv, kmi->lv_idx);
2055 if (!rc)
2056 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 0);
2057 break;
2058
2059 case ID_KEYCTX_SETDEFKEY:
2060 if (!km_check_key_status (kmi->lv, kmi->lv_idx)) {
2061 key = km_get_key_ptr (kmi->lv, kmi->lv_idx, NULL);
2062 rc = set_gnupg_default_key (key->subkeys->keyid+8);
2063 if (rc)
2064 msg_box (dlg, winpt_strerror (rc), _("Key Manager"), MB_ERR);
2065 update_default_key_str (kmi->statbar);
2066 }
2067 break;
2068
2069 case ID_KEYMISC_VIEWKEYID:
2070 case ID_KEYMISC_VIEWCIPHER:
2071 case ID_KEYMISC_VIEWTYPE:
2072 case ID_KEYMISC_VIEWCREAT:
2073 case ID_KEYMISC_VIEWDESC:
2074 hm = GetMenu (dlg);
2075 i = get_menu_state (hm, LOWORD (wparam));
2076 set_menu_state (hm, LOWORD (wparam),
2077 i & MFS_CHECKED? MFS_UNCHECKED : MFS_CHECKED);
2078 modify_listview_columns (kmi, LOWORD (wparam), !(i & MFS_CHECKED));
2079 break;
2080
2081 case ID_GROUP_NEW:
2082 case ID_GROUP_PASTE:
2083 case ID_GROUP_DELETE:
2084 case ID_GROUP_SHOW:
2085 /* XXX: Implement group manager. */
2086 return TRUE;
2087 }
2088
2089 break;
2090 }
2091
2092 return FALSE;
2093 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26