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

Contents of /trunk/Src/wptKeyManagerDlg.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 256 - (show annotations)
Sat Aug 5 10:31:06 2006 UTC (18 years, 6 months ago) by twoaday
File size: 64394 byte(s)
1.0.0pre3 release.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26