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

Contents of /trunk/Src/wptKeyManagerDlg.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 255 - (show annotations)
Tue Aug 1 16:37:23 2006 UTC (18 years, 7 months ago) by twoaday
File size: 64440 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 int i;
526
527 nkeys = listview_count_items (lv, 0);
528 for (i = 0; i < nkeys; i++) {
529 if (km_check_for_seckey (lv, i, NULL))
530 nsec++;
531 }
532 _snprintf (txt_sec, sizeof (txt_sec)-1, _("%d secret keys"), nsec);
533 _snprintf (txt_pub, sizeof (txt_pub)-1, _("%d keys"), nkeys);
534 SendMessage (sb, SB_SETTEXT, 1, (LPARAM)txt_sec);
535 SendMessage (sb, SB_SETTEXT, 2, (LPARAM)txt_pub);
536 }
537
538
539 long CALLBACK
540 separator_wnd_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
541 {
542 static POINT last_mouse_pos;
543 PAINTSTRUCT ps;
544 RECT rect;
545 HPEN hpen;
546
547 if (msg == WM_CREATE)
548 SetWindowLong (hwnd, GWL_USERDATA,
549 (long)(((CREATESTRUCT*)lparam)->lpCreateParams));
550
551 switch (msg) {
552 case WM_PAINT:
553 GetClientRect (hwnd, &rect);
554 BeginPaint (hwnd, &ps);
555
556 /* Background */
557 FillRect (ps.hdc, &rect, (HBRUSH)(COLOR_3DFACE+1));
558
559 /* The lines from the light into the dark */
560 MoveToEx (ps.hdc, 0,0, NULL);
561 hpen = CreatePen (PS_SOLID, 0, GetSysColor (COLOR_3DHILIGHT));
562 if (hpen != NULL) {
563 SelectObject (ps.hdc, (LPVOID)hpen);
564 LineTo (ps.hdc, rect.right, 0);
565 DeleteObject (hpen);
566 }
567 MoveToEx (ps.hdc, 0, 1, NULL);
568 hpen = CreatePen (PS_SOLID, 0, GetSysColor (COLOR_3DLIGHT));
569 if (hpen != NULL) {
570 SelectObject (ps.hdc, (LPVOID)hpen);
571 LineTo (ps.hdc, rect.right, rect.bottom);
572 DeleteObject (hpen);
573 }
574
575 MoveToEx (ps.hdc, 0, rect.bottom-1, NULL);
576 hpen = CreatePen (PS_SOLID, 0, GetSysColor(COLOR_3DSHADOW));
577 if (hpen != NULL) {
578 SelectObject (ps.hdc, (LPVOID)hpen);
579 LineTo (ps.hdc, rect.right, rect.bottom-1);
580 DeleteObject (hpen);
581 }
582 MoveToEx (ps.hdc, 0, rect.bottom, NULL);
583 hpen = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW));
584 if (hpen != NULL) {
585 SelectObject (ps.hdc, (LPVOID)hpen);
586 LineTo (ps.hdc, rect.right, rect.bottom);
587 DeleteObject (hpen);
588 }
589
590 EndPaint (hwnd, &ps);
591 return 0;
592
593 case WM_LBUTTONDOWN:
594 last_mouse_pos.x = LOWORD (lparam);
595 last_mouse_pos.y = HIWORD (lparam);
596 ClientToScreen (hwnd, &last_mouse_pos);
597 SetCapture (hwnd);
598 return 0;
599
600 case WM_LBUTTONUP:
601 ReleaseCapture ();
602 return 0;
603
604 case WM_MOUSEMOVE:
605 if (wparam == MK_LBUTTON) {
606 struct km_info_s *kmi;
607 POINT p;
608
609 kmi = (struct km_info_s *)GetWindowLong (hwnd, GWL_USERDATA);
610 if (kmi == NULL)
611 break;
612
613 /* Calculate mouse movement */
614 p.x = LOWORD (lparam);
615 p.y = HIWORD (lparam);
616 ClientToScreen (hwnd, &p);
617
618 GetWindowRect (hwnd, &rect);
619 rect.top += (short)(p.y - last_mouse_pos.y);
620 rect.bottom += (short)(p.y - last_mouse_pos.y);
621
622 last_mouse_pos.y = p.y;
623
624 /* Apply mouse movement to window. Beware the MoveWindow is relaive
625 to parent NOT screen */
626 MapWindowPoints (NULL, GetParent(hwnd), (POINT*)&rect, 2);
627 kmi->ypos_sep = rect.top;
628 kmi->ypercent_sep = 0; /* This forces do_resize_window to use abs. position */
629 do_resize_window (GetParent (hwnd), kmi);
630 return 0;
631 }
632 }
633
634 return DefWindowProc (hwnd, msg, wparam, lparam);
635 }
636
637
638 /* Register the separator window with @dlg as the parent window. */
639 static HWND
640 regist_sep_wnd (HWND dlg, struct km_info_s *kmi)
641 {
642 WNDCLASS wndclass;
643 HWND h;
644
645 memset (&wndclass, 0, sizeof (wndclass));
646 wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
647 wndclass.lpfnWndProc = separator_wnd_proc;
648 wndclass.cbClsExtra = 0;
649 wndclass.cbWndExtra = sizeof (long);
650 wndclass.hInstance = glob_hinst;
651 wndclass.hIcon = NULL;
652 wndclass.hCursor = LoadCursor (NULL, IDC_SIZENS);
653 wndclass.hbrBackground = (HBRUSH) GetStockObject (LTGRAY_BRUSH);
654 wndclass.lpszMenuName = 0;
655 wndclass.lpszClassName = WINDOWCLASS_SEPARATOR_CHILD;
656 RegisterClass (&wndclass);
657
658 h = CreateWindowEx (WS_EX_WINDOWEDGE, WINDOWCLASS_SEPARATOR_CHILD, NULL,
659 WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
660 0, 400, 2000, 5, dlg, (HMENU) 0, glob_hinst, kmi);
661 if (!h)
662 BUG (NULL);
663 ShowWindow (h, SW_SHOW);
664 return h;
665 }
666
667
668 #define enable_button(hwnd, cid, item_selected) \
669 SendMessage ((hwnd), TB_ENABLEBUTTON, (cid), MAKELONG ((item_selected), 0))
670
671
672 /* Interactive modification of the dialog item which depend if an item
673 is selected or not and what kind of item. @lv is the list view with
674 the items. */
675 void
676 update_ui_items (HWND hwnd, listview_ctrl_t lv)
677 {
678 HWND tb_hwnd;
679 HMENU hmenu;
680 int mult_resids[] = {ID_KEYMISC_PROPS, ID_KEYMISC_SIGN, ID_KEYMISC_EDITKEY,
681 ID_KEYMISC_CHECKSIGS, ID_KEYMISC_REVCERT, 0};
682 int key_selected;
683 int key_has_sec;
684 int key_inv = 0;
685 int i, state=0;
686
687 /* Get some states */
688 key_selected = SendMessage (GetDlgItem (hwnd, IDC_KEYMISC_KEYLIST),
689 LVM_GETSELECTEDCOUNT, 0, 0)
690 ? TRUE : FALSE;
691 key_has_sec = FALSE;
692 if (key_selected) {
693 i = listview_get_curr_pos (lv);
694 key_has_sec = km_check_for_seckey (lv, i, NULL) ? TRUE : FALSE;
695 key_inv = km_get_key_status (lv, i) & KM_FLAG_REVOKED ||
696 km_get_key_status (lv, i) & KM_FLAG_EXPIRED;
697 }
698
699 /* Enable / disable toolbar buttons */
700 tb_hwnd = GetDlgItem (hwnd, IDR_WINPT_KMTB);
701 enable_button (tb_hwnd, ID_KEYMISC_DELETE, key_selected);
702 enable_button (tb_hwnd, ID_KEYMISC_PROPS, key_selected);
703 enable_button (tb_hwnd, ID_KEYMISC_SIGN, key_selected && !key_inv);
704 enable_button (tb_hwnd, ID_KEYMISC_EXPORT, key_selected);
705 enable_button (tb_hwnd, ID_KEYCTX_COPY, key_selected);
706 enable_button (tb_hwnd, ID_KEYCTX_PASTE, clip_contains_pgpkey ());
707
708 /* Enable / disable menu items */
709 state = key_selected? MF_ENABLED : MF_DISABLED|MF_GRAYED;
710 hmenu = GetMenu (hwnd);
711 set_menu_state (hmenu, ID_KEYMISC_EXPORT, state);
712 set_menu_state (hmenu, ID_KEYMISC_DELETE, state);
713 set_menu_state (hmenu, ID_KEYMISC_PROPS, state);
714 set_menu_state (hmenu, ID_KEYMISC_EDITKEY, state);
715 set_menu_state (hmenu, ID_KEYMISC_CHECKSIGS, state);
716 set_menu_state (hmenu, ID_KEYMISC_SIGN,
717 key_selected && !key_inv ? MF_ENABLED : MF_GRAYED);
718 set_menu_state (hmenu, ID_KEYMISC_EXPORT_PRIVKEY,
719 key_selected && key_has_sec? MF_ENABLED : MF_GRAYED);
720 set_menu_state (hmenu, ID_KEYMISC_REVCERT,
721 key_selected && key_has_sec? MF_ENABLED : MF_GRAYED);
722
723 /* Disable some menu items when multiple keys are selected. */
724 if (listview_count_items (lv, 1) > 1) {
725 for (i=0; mult_resids[i] != 0; i++)
726 set_menu_state (hmenu, mult_resids[i], MF_GRAYED);
727 }
728
729 /* Disable all secret-key functions when no secret key is available. */
730 if (!secret_key_available ()) {
731 enable_button (tb_hwnd, ID_KEYMISC_SIGN, FALSE);
732 set_menu_state (hmenu, ID_KEYMISC_SIGN, MF_GRAYED);
733 }
734 }
735
736
737 /* Disable some context menu items when multiple keys are selected. */
738 static void
739 popup_multiple (HWND dlg, HMENU hm)
740 {
741 int resids[] = {
742 ID_KEYCTX_EDIT,
743 ID_KEYCTX_SIGN,
744 ID_KEYCTX_REV,
745 ID_KEYCTX_ENABLE,
746 ID_KEYCTX_DISABLE,
747 ID_KEYCTX_ADDKEY,
748 ID_KEYCTX_ADDPHOTO,
749 ID_KEYCTX_ADDUID,
750 ID_KEYCTX_ADDREV,
751 ID_KEYCTX_LISTSIGS,
752 ID_KEYCTX_MAXTRUST,
753 ID_KEYCTX_PROPS,
754 ID_KEYCTX_SENDMAIL,
755 0};
756 int i;
757 for (i=0; i < resids[i] != 0; i++)
758 set_menu_state (hm, resids[i], MF_GRAYED);
759 }
760
761
762 /* The items which are shown when GPG is in read-only mode. */
763 static void
764 popup_gpg_readonly (HWND dlg, HMENU hm)
765 {
766 int resids[] = {
767 ID_KEYCTX_PASTE,
768 ID_KEYCTX_EDIT,
769 ID_KEYCTX_SIGN,
770 ID_KEYCTX_REV,
771 ID_KEYCTX_DEL,
772 ID_KEYCTX_ENABLE,
773 ID_KEYCTX_DISABLE,
774 ID_KEYCTX_RECVFROM,
775 ID_KEYCTX_ADDKEY,
776 ID_KEYCTX_ADDPHOTO,
777 ID_KEYCTX_ADDUID,
778 ID_KEYCTX_ADDREV,
779 0
780 };
781 int i;
782
783 if (gpg_read_only == 0)
784 return;
785 for (i=0; resids[i] != 0; i++)
786 set_menu_state (hm, resids[i], MF_GRAYED);
787 }
788
789
790 /* Change the 'Edit' menu based on the current state. */
791 static void
792 change_edit_menu (listview_ctrl_t lv, HMENU hm, int id)
793 {
794 enum item { EDIT_MENU = 1 };
795 int no_sel;
796
797 if (id != EDIT_MENU)
798 return;
799
800 if (!clip_contains_pgpkey ())
801 set_menu_state (hm, ID_KEYMISC_PASTE, MF_GRAYED);
802 else
803 set_menu_state (hm, ID_KEYMISC_PASTE, MF_ENABLED);
804 no_sel = listview_get_curr_pos (lv) == -1? 1 : 0;
805 set_menu_state (hm, ID_KEYMISC_DELETE2, no_sel? MF_GRAYED: MF_ENABLED);
806 set_menu_state (hm, ID_KEYMISC_COPY, no_sel? MF_GRAYED : MF_ENABLED);
807 }
808
809
810
811 /* Show limited key menu entries when GPG is in read-only mode. */
812 static void
813 change_key_menu (HMENU hm, int id)
814 {
815 int key_resids[] = {
816 ID_KEYMISC_SIGN,
817 ID_KEYMISC_DELETE,
818 ID_KEYMISC_REVCERT,
819 ID_KEYMISC_IMPORT_HTTP,
820 ID_KEYMISC_IMPORT,
821 ID_KEYMISC_REFRESH_KEYS,
822 ID_KEYMISC_REBUILD,
823 ID_KEYMISC_KEYWIZARD,
824 ID_KEYMISC_CARDNEW,
825 ID_KEYMISC_NEWKEY,
826 0,
827 };
828 int edit_resids[] = {
829 ID_KEYMISC_PASTE,
830 ID_KEYMISC_OT,
831 ID_KEYMISC_EDITKEY,
832 0
833 };
834 int *resids;
835 int i;
836
837
838 if (gpg_read_only == 0)
839 return;
840 switch (id) {
841 case 0: return;
842 case 3: resids = key_resids; break;
843 case 1: resids = edit_resids;break;
844 default:resids = edit_resids; break;
845 }
846
847 for (i=0; resids[i] != 0; i++)
848 set_menu_state (hm, resids[i], MF_GRAYED);
849 }
850
851
852 /* Reload a single key in the cache. */
853 static void
854 update_key (listview_ctrl_t lv, int pos, const char *keyid, int keypair)
855 {
856 struct winpt_key_s key;
857
858 keycache_update (0, keyid);
859 if (keypair)
860 keycache_update (1, keyid);
861
862 /* because we replaced the key item, we need to update the
863 address of the pointer in the ListView control. */
864 memset (&key, 0, sizeof (key));
865 winpt_get_pubkey (keyid, &key);
866 keylist_upd_key (lv, pos, key.ext, key.ctx);
867 keyring_check_last_access ();
868 }
869
870
871 /* Setup status bar for the main window @dlg. */
872 static HWND
873 setup_status_bar (HWND dlg, listview_ctrl_t lv)
874 {
875 HWND statbar;
876 RECT r;
877 int partpos[3];
878 int i;
879
880 GetClientRect (dlg, &r);
881 for (i=1; i <= 3; i++)
882 partpos[i-1] = r.right/3*i;
883 statbar = CreateStatusWindow (WS_CHILD | WS_VISIBLE | CCS_BOTTOM,
884 "WinPT_Status_Bar", dlg, KM_SEPARATOR_ID);
885 if (!statbar)
886 BUG (NULL);
887 ShowWindow (statbar, SW_SHOW);
888 SendMessage (statbar, SB_SETPARTS, (WPARAM)3, (LPARAM)partpos);
889
890 update_default_key_str (statbar);
891 update_status_bar (statbar, lv);
892 return statbar;
893 }
894
895
896 /* Remove or add columns which depends on the state of @checked. */
897 void
898 modify_listview_columns (km_info_s *kmi, UINT m_uid, BOOL checked)
899 {
900 UINT resids[] = {
901 0,
902 ID_KEYMISC_VIEWKEYID,
903 ID_KEYMISC_VIEWTYPE,
904 0,
905 ID_KEYMISC_VIEWCIPHER,
906 0,
907 0,
908 ID_KEYMISC_VIEWCREAT,
909 ID_KEYMISC_VIEWDESC,
910 -1
911 };
912 listview_column_s cols[] = {
913 {0, 240, (char *)_("User ID")},
914 {1, 78, (char *)_("Key ID")},
915 {2, 52, (char *)_("Type")},
916 {3, 66, (char *)_("Size")},
917 {4, 60, (char *)_("Cipher")},
918 {5, 66, (char *)_("Validity")},
919 {6, 58, (char *)_("Trust")},
920 {7, 72, (char *)_("Creation")},
921 {8, 160,(char *)_("Description")},
922 {0, 0, NULL}
923 };
924 UINT pos;
925
926 for (pos=0; resids[pos] != -1; pos++) {
927 if (m_uid == resids[pos])
928 break;
929 }
930 if (!checked)
931 listview_del_column (kmi->lv, (int)pos);
932 else {
933 listview_add_column (kmi->lv, &cols[pos]);
934 keylist_upd_col (kmi->lv, pos);
935 }
936 }
937
938
939 /* Helper to handle the help file. If @check is 1
940 the existence of the file is checked.
941 Otherwise the help file will be loaded. */
942 static bool
943 start_help (HWND dlg, int check)
944 {
945 DWORD n;
946 char path[MAX_PATH+1+32];
947
948 n = GetModuleFileName (NULL, path, sizeof (path)-1-32);
949 if (!n)
950 return false;
951 path[n] = 0;
952 while (n-- && path[n] != '\\')
953 ;
954 path[n+1] = 0;
955 strcat (path, "winpt.chm");
956 if (!check)
957 ShellExecute (dlg, "open", path, NULL, NULL, SW_SHOW);
958 return file_exist_check (path) == 0? true : false;
959 }
960
961
962 /* Translate all menu strings. */
963 static void
964 translate_menu_strings (HWND dlg)
965 {
966 HMENU menu;
967
968 menu = LoadMenu (glob_hinst, (LPCSTR)IDR_WINPT_KEYMISC);
969 set_menu_text_bypos (menu, 0, _("File"));
970 set_menu_text_bypos (menu, 1, _("Edit"));
971 set_menu_text_bypos (menu, 2, _("View"));
972 set_menu_text_bypos (menu, 3, _("Key"));
973 set_menu_text_bypos (menu, 4, _("Groups"));
974
975 set_menu_text (menu, ID_KEYMISC_EDITKEY, _("Edit"));
976 set_menu_text (menu, ID_KEYMISC_MAIL, _("Send Mail..."));
977 set_menu_text (menu, ID_KEYMISC_OT, _("Ownertrust")); /* XXX */
978 set_menu_text (menu, ID_KEYMISC_COPY, _("&Copy\tCtrl+C"));
979 set_menu_text (menu, ID_KEYMISC_PASTE, _("&Paste\tCtrl+V"));
980 set_menu_text (menu, ID_KEYMISC_FIND, _("Search...\tCtrl+F"));
981 set_menu_text (menu, ID_KEYMISC_SELALL, _("Select All\tCtrl+A"));
982 set_menu_text (menu, ID_KEYMISC_QUIT, _("&Quit"));
983 set_menu_text (menu, ID_KEYMISC_UID, _("User ID"));
984 set_menu_text (menu, ID_KEYMISC_NEWKEY, _("&Expert"));
985 set_menu_text (menu, ID_KEYMISC_KEYWIZARD, _("&Normal"));
986 set_menu_text (menu, ID_KEYMISC_EDIT, _("Edit"));
987 set_menu_text (menu, ID_KEYMISC_SIGN, _("&Sign"));
988 set_menu_text (menu, ID_KEYMISC_DELETE, _("&Delete"));
989 set_menu_text (menu, ID_KEYMISC_DELETE2, _("&Delete"));
990 set_menu_text (menu, ID_KEYMISC_REVCERT, _("&Revoke Cert"));
991 set_menu_text (menu, ID_KEYMISC_CHECKSIGS, _("&List Signatures"));
992 set_menu_text (menu, ID_KEYMISC_TRUSTPATH, _("List Trust Path"));
993 set_menu_text (menu, ID_KEYMISC_EXPORT, _("&Export..."));
994 set_menu_text (menu, ID_KEYMISC_IMPORT, _("&Import..."));
995 set_menu_text (menu, ID_KEYMISC_PROPS, _("&Properties"));
996 set_menu_text (menu, ID_KEYMISC_GPGOPT, _("GPG &Options"));
997 set_menu_text (menu, ID_KEYMISC_GPGPREFS, _("&GPG Preferences"));
998 set_menu_text (menu, ID_KEYMISC_WINPTPREFS, _("&WinPT Preferences"));
999 set_menu_text (menu, ID_KEYMISC_SENDRECV, _("Keyserver") );
1000 set_menu_text (menu, ID_KEYMISC_EXPORT_PRIVKEY, _("E&xport Secret Key"));
1001 set_menu_text (menu, ID_KEYMISC_RECACHE, _("Re&load Key Cache"));
1002 set_menu_text (menu, ID_KEYMISC_REBUILD, _("R&everify Signatures"));
1003 set_menu_text (menu, ID_KEYMISC_REFRESH_KEYS, _("Refresh &Keys (Keyserver)"));
1004 set_menu_text (menu, ID_KEYMISC_INFO, _("Info") );
1005 set_menu_text (menu, ID_KEYMISC_HELP, _("&Help"));
1006
1007 set_menu_text (menu, ID_KEYMISC_VIEWKEYID, _("Key ID"));
1008 set_menu_text (menu, ID_KEYMISC_VIEWCIPHER, _("Cipher"));
1009 set_menu_text (menu, ID_KEYMISC_VIEWTYPE, _("Type"));
1010 set_menu_text (menu, ID_KEYMISC_VIEWCREAT, _("Creation"));
1011
1012 if (!start_help (NULL, 1))
1013 set_menu_state (menu, ID_KEYMISC_HELP, MF_GRAYED);
1014
1015 SetMenu (dlg, menu);
1016 }
1017
1018
1019 /* Translate popup menu strings. */
1020 static void
1021 translate_popupmenu_strings (HMENU popup)
1022 {
1023 set_menu_text (popup, ID_KEYCTX_UID_COPY, _("Copy User ID to Clipboard"));
1024 set_menu_text (popup, ID_KEYCTX_KEYID_COPY, _("Copy Key ID to Clipboard"));
1025 set_menu_text (popup, ID_KEYCTX_FPR_COPY, _("Copy Fingerprint to Clipboard"));
1026 set_menu_text (popup, ID_KEYCTX_KINFO_COPY, _("Copy Key Info to Clipboard"));
1027 set_menu_text (popup, ID_KEYCTX_EMAIL_COPY, _("Copy E-Mail to Clipboard"));
1028 set_menu_text (popup, ID_KEYCTX_COPY, _("Copy Key to Clipboard"));
1029 set_menu_text (popup, ID_KEYCTX_PASTE, _("Paste Key from Clipboard"));
1030 set_menu_text (popup, ID_KEYCTX_RECVFROM, _("Refresh from Keyserver"));
1031 set_menu_text (popup, ID_KEYCTX_MAXTRUST, _("Set Implicit &Trust"));
1032 set_menu_text (popup, ID_KEYCTX_LISTSIGS, _("&List Signatures"));
1033 set_menu_text (popup, ID_KEYCTX_PROPS, _("&Properties"));
1034 set_menu_text (popup, ID_KEYCTX_EDIT, _("Key Edit"));
1035 set_menu_text (popup, ID_KEYCTX_DEL, _("&Delete"));
1036 set_menu_text (popup, ID_KEYCTX_REV, _("&Revoke Cert"));
1037 set_menu_text (popup, ID_KEYCTX_SIGN, _("&Sign"));
1038 set_menu_text (popup, ID_KEYCTX_ENABLE, _("&Enable"));
1039 set_menu_text (popup, ID_KEYCTX_DISABLE, _("&Disable"));
1040 set_menu_text (popup, ID_KEYCTX_RECVFROM, _("Re&fresh from Keyserver"));
1041 set_menu_text (popup, ID_KEYCTX_SETPREFKS, _("Set preferred Keyserver URL"));
1042 set_menu_text (popup, ID_KEYCTX_SENDMAIL, _("Send Key to Mail Recipient"));
1043 set_menu_text (popup, ID_KEYCTX_SETDEFKEY, _("Set as Default Key"));
1044
1045 set_menu_text (popup, ID_KEYCTX_ADDKEY, _("Key..."));
1046 set_menu_text (popup, ID_KEYCTX_ADDUID, _("User ID..."));
1047 set_menu_text (popup, ID_KEYCTX_ADDPHOTO, _("Photo ID..."));
1048 set_menu_text (popup, ID_KEYCTX_ADDREV, _("Revoker..."));
1049
1050 /* change popup texts */
1051 set_menu_text_bypos (popup, 0, _("Key Attributes"));
1052 set_menu_text_bypos (popup, 6, _("Add"));
1053 set_menu_text_bypos (popup, 19, _("Send to Keyserver"));
1054 }
1055
1056
1057 /* Return true if the cache contain marked keys. */
1058 static bool
1059 updated_keys_avail (void)
1060 {
1061 gpg_keycache_t kc = keycache_get_ctx (1);
1062 struct keycache_s *k;
1063
1064 for (k = kc->item; k; k = k->next) {
1065 if (k->flags)
1066 return true;
1067 }
1068 return false;
1069 }
1070
1071
1072 /* Find the index of the key identified by @key. */
1073 static int
1074 find_keypos (listview_ctrl_t lv, gpgme_key_t key)
1075 {
1076 char keyid[32+1];
1077 int i;
1078
1079 for (i=0; i < listview_count_items (lv, 0); i++) {
1080 listview_get_item_text (lv, i, KM_COL_KEYID, keyid, sizeof (keyid)-1);
1081 if (!strcmp (key->subkeys->keyid+8, keyid+2))
1082 return i;
1083 }
1084 return -1;
1085 }
1086
1087
1088 /* Add all recently updated keys in the cache to the list
1089 and refresh all GUI elements. */
1090 static void
1091 refresh_keylist (struct km_info_s *kmi)
1092 {
1093 struct keycache_s *ctx;
1094 gpg_keycache_t kc;
1095 int status=0, pos;
1096
1097 kc = keycache_get_ctx (1);
1098 while (!gpg_keycache_next_updated_key (kc, &ctx, &status)) {
1099 if (status == KC_FLAG_ADD)
1100 keylist_add_key (kmi->lv, KEYLIST_LIST, ctx, ctx->key);
1101 else {
1102 pos = find_keypos (kmi->lv, ctx->key);
1103 if (pos != -1)
1104 keylist_upd_key (kmi->lv, pos, ctx, ctx->key);
1105 }
1106 }
1107 keylist_sort (kmi->lv, kmi->keylist_sortby);
1108 update_status_bar (kmi->statbar, kmi->lv);
1109 keyring_check_last_access ();
1110 }
1111
1112
1113 /* Reload the key cache. */
1114 static void
1115 keycache_reload (HWND dlg)
1116 {
1117 refresh_cache_s rcs;
1118
1119 memset (&rcs, 0, sizeof rcs);
1120 rcs.kr_reload = rcs.kr_update = 1;
1121 rcs.tr_update = 0;
1122 DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYCACHE, dlg,
1123 keycache_dlg_proc, (LPARAM)&rcs);
1124 }
1125
1126
1127 /* Check if the secret keyring contains at least one
1128 key with ultimate trust.
1129 Return value: 0 on success. */
1130 int
1131 check_ultimate_trusted_key (gpg_keycache_t _sec)
1132 {
1133 struct keycache_s *n;
1134 int nkeys = 0;
1135
1136 for (n = _sec->item; n; n = n->next) {
1137 if (n->pubpart &&
1138 n->pubpart->key->owner_trust == GPGME_VALIDITY_ULTIMATE)
1139 return 0;
1140 nkeys++;
1141 }
1142
1143 /* if we do not have any secret keys, it does not make sense
1144 to return an error. */
1145 if (nkeys == 0)
1146 return 0;
1147 return -1;
1148 }
1149
1150
1151 static void
1152 reload_keylist (struct km_info_s *kmi)
1153 {
1154 gpg_keycache_t c;
1155
1156 c = keycache_get_ctx (1);
1157 keycache_reload (kmi->dlg);
1158 keylist_reload (kmi->lv, c, KEYLIST_LIST, kmi->keylist_sortby);
1159 update_status_bar (kmi->statbar, kmi->lv);
1160 keyring_check_last_access ();
1161 }
1162
1163
1164 /* Reload the entire key cache and update the listview. */
1165 static void
1166 reload_keycache (struct km_info_s *kmi)
1167 {
1168 refresh_cache_s rcs = {0};
1169 gpg_keycache_t c;
1170
1171 rcs.kr_reload = rcs.kr_update = 1;
1172 rcs.tr_update = 0;
1173 DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYCACHE, kmi->dlg,
1174 keycache_dlg_proc, (LPARAM)&rcs);
1175 c = keycache_get_ctx (1);
1176 keylist_reload (kmi->lv, c, KEYLIST_LIST, kmi->keylist_sortby);
1177 update_status_bar (kmi->statbar, kmi->lv);
1178 SetForegroundWindow (kmi->dlg);
1179 }
1180
1181
1182 /* Handle all import request. */
1183 static void
1184 km_gui_import (struct km_info_s *kmi, int cmd_id, void *param)
1185 {
1186 int newkeys=0, newsks=0;
1187 int err = 0;
1188
1189 switch (cmd_id) {
1190 case ID_KEYMISC_PASTE:
1191 err = km_clip_import (kmi->dlg, &newkeys, &newsks);
1192 break;
1193
1194 case ID_KEYMISC_IMPORT:
1195 err = km_file_import (kmi->dlg, NULL, &newkeys, &newsks);
1196 break;
1197
1198 case WM_DROPFILES:
1199 err = km_dropped_file_import (kmi->dlg, (HDROP)param,
1200 &newkeys, &newsks);
1201 break;
1202
1203 default:
1204 err = 1;
1205 break;
1206 }
1207
1208 if (!err && !newsks && (newkeys > 0 && newkeys < KM_PRELOAD_KEYS))
1209 refresh_keylist (kmi);
1210 else if (!err) /* avoid to spawn too much processes. */
1211 reload_keylist (kmi);
1212
1213 SetForegroundWindow (kmi->dlg);
1214 }
1215
1216
1217 /* Copy the requested key information (@what) to the clipboard.
1218 If multiple items were selected, each key info is copied to
1219 the clipboard. The data is separated by \r\n. */
1220 static void
1221 copy_key_info (int what, struct km_info_s *kmi)
1222 {
1223 gpgme_data_t out;
1224 gpgme_key_t key;
1225 struct keycache_s *kci = NULL;
1226 size_t n=0;
1227 char *p, tmp[256];
1228 int i=0, end = listview_count_items (kmi->lv, 0);
1229 bool single = false;
1230
1231 /* Do not iterate over the entire list if just one item is selected. */
1232 n = listview_count_items (kmi->lv, 1);
1233 if (n == 1) {
1234 i = kmi->lv_idx;
1235 end = i+1;
1236 single = true;
1237 }
1238
1239 gpgme_data_new (&out);
1240 for (; i < end; i++) {
1241 if (!listview_get_item_state (kmi->lv, i))
1242 continue;
1243 switch (what) {
1244
1245 case ID_KEYCTX_EMAIL_COPY:
1246 key = km_get_key_ptr (kmi->lv, i, NULL);
1247 gpgme_data_write (out, key->uids->email, strlen (key->uids->email));
1248 if (!single) gpgme_data_write (out, "\r\n", 2);
1249 break;
1250
1251 case ID_KEYCTX_UID_COPY:
1252 key = km_get_key_ptr (kmi->lv, i, &kci);
1253 gpgme_data_write (out, kci->uids->uid, strlen (kci->uids->uid));
1254 if (!single) gpgme_data_write (out, "\r\n", 2);
1255 break;
1256
1257 case ID_KEYCTX_KEYID_COPY:
1258 key = km_get_key_ptr (kmi->lv, i, NULL);
1259 gpgme_data_write (out, "0x", 2);
1260 gpgme_data_write (out, key->subkeys->keyid+8, 8);
1261 if (!single) gpgme_data_write (out, "\r\n", 2);
1262 break;
1263
1264 case ID_KEYCTX_FPR_COPY:
1265 key = km_get_key_ptr (kmi->lv, i, NULL);
1266 gpgme_data_write (out, key->subkeys->fpr, strlen (key->subkeys->fpr));
1267 if (!single) gpgme_data_write (out, "\r\n", 2);
1268 break;
1269
1270 case ID_KEYCTX_KINFO_COPY:
1271 key = km_get_key_ptr (kmi->lv, i, NULL);
1272 key_get_clip_info (key->subkeys->keyid+8, tmp, sizeof (tmp)-1);
1273 gpgme_data_write (out, tmp, strlen (tmp));
1274 if (!single) gpgme_data_write (out, "\r\n", 2);
1275 break;
1276 }
1277 }
1278 gpgme_data_write (out, "\0", 1);
1279 p = gpgme_data_release_and_get_mem (out, &n);
1280 set_clip_text (NULL, p, n);
1281 gpgme_free (p);
1282 }
1283
1284
1285 /* Dialog box procedure for the Key Manager. */
1286 BOOL CALLBACK
1287 keymanager_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
1288 {
1289 HWND kl;
1290 HMENU hm;
1291 RECT r;
1292 gpg_keycache_t c;
1293 gpgme_key_t key;
1294 km_info_t kmi = NULL;
1295 struct genkey_s genkey;
1296 struct winpt_key_s k = {0};
1297 struct URL_ctx_s *url;
1298 char type[32], *name;
1299 const char *t, *host;
1300 WORD port = 0;
1301 int l_idx = 0, i=0, rc;
1302
1303 if ((msg != WM_INITDIALOG)
1304 && ((kmi = (km_info_t)GetWindowLong (dlg, GWL_USERDATA)) == NULL))
1305 return FALSE;
1306
1307 /* handle dynamic popup items in the keyserver menu. */
1308 if (msg == WM_COMMAND && LOWORD (wparam) >= WM_APP &&
1309 LOWORD (wparam) <= WM_APP+MAX_KEYSERVERS) {
1310 l_idx = LOWORD (wparam)-WM_APP;
1311 if (l_idx < 0)
1312 return TRUE;
1313 host = kserver_get_hostname (l_idx, 0, &port);
1314 if (host != NULL)
1315 km_send_to_keyserver (kmi->lv, dlg, host, port);
1316 return TRUE;
1317 }
1318
1319 switch (msg) {
1320 case WM_INITDIALOG:
1321 kmi = new struct km_info_s;
1322 memset (kmi, 0, sizeof (struct km_info_s));
1323 kmi->lv_idx = -1;
1324 kmi->hwnd_sep = regist_sep_wnd (dlg, kmi);
1325 imagelist_load (dlg);
1326 translate_menu_strings (dlg);
1327 SetWindowText (dlg, _("Key Manager"));
1328
1329 c = keycache_get_ctx (KEYCACHE_PUB);
1330 kl = GetDlgItem (dlg, IDC_KEYMISC_KEYLIST);
1331 kmi->keylist_sortby = KEY_SORT_USERID;
1332 Header_SetImageList(ListView_GetHeader (kl), glob_imagelist);
1333 kmi->lv = keylist_load (GetDlgItem (dlg, IDC_KEYMISC_KEYLIST), c,
1334 NULL, KEYLIST_LIST, kmi->keylist_sortby);
1335 if (check_ultimate_trusted_key (keycache_get_ctx (0))) {
1336 msg_box (dlg, _("No ultimately trusted key found.\n"
1337 "Please set at least one secret key to ultimate trust."),
1338 _("Key Manager"), MB_WARN);
1339 }
1340 /* init subclassing for the listview */
1341 keylist_proc.opaque = kmi;
1342 keylist_proc.dlg = dlg;
1343 keylist_proc.current = (WNDPROC)keylist_subclass_proc;
1344 keylist_proc.old = (WNDPROC)GetWindowLong(kl, GWL_WNDPROC);
1345 if (keylist_proc.old) {
1346 if (!SetWindowLong (kl, GWL_WNDPROC, (LONG)keylist_proc.current)) {
1347 msg_box (dlg, "Could not set keylist window procedure.",
1348 _("Key Manager"), MB_ERR);
1349 BUG (NULL);
1350 }
1351 }
1352 kmi->statbar = setup_status_bar (dlg, kmi->lv);
1353 SetWindowLong (dlg, GWL_USERDATA, (LONG)kmi);
1354 kmi->toolbar = create_toolbar (dlg, kmi);
1355 kmi->dlg = dlg;
1356
1357 do_center_window (dlg, kmi);
1358 do_resize_window (dlg, kmi);
1359 restore_window_size (dlg, kmi);
1360 update_ui_items (dlg, kmi->lv);
1361 restore_column_info (kmi);
1362 keylist_sort (kmi->lv, kmi->keylist_sortby);
1363
1364 SetDlgItemText (dlg, IDC_KEYMISC_GTEXT, _("Groups"));
1365 SetDlgItemText (dlg, ID_GROUP_SHOW, _("&Show"));
1366 SetDlgItemText (dlg, ID_GROUP_NEW, _("&New..."));
1367 SetClassLong (dlg, GCL_HICON, (LONG)LoadIcon (glob_hinst,
1368 (LPCTSTR)IDI_WINPT));
1369 SetForegroundWindow (dlg);
1370 kmi->magic = SetTimer (dlg, 1, 1000, NULL);
1371 return TRUE;
1372
1373 case WM_TIMER:
1374 KillTimer (dlg, kmi->magic);
1375 SetForegroundWindow (dlg);
1376 break;
1377
1378 case WM_DESTROY:
1379 save_column_info (kmi);
1380 if (kmi->lv) {
1381 keylist_delete (kmi->lv);
1382 kmi->lv = NULL;
1383 }
1384 imagelist_destroy ();
1385
1386 ltoa (kmi->pos_x, type, 10);
1387 set_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Pos_X", type);
1388 ltoa (kmi->pos_y, type, 10);
1389 set_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Pos_Y", type);
1390
1391 GetWindowRect (dlg, &r);
1392 sprintf (type, "%d", (int)(r.bottom-r.top));
1393 set_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Size_Width",
1394 type);
1395 sprintf (type, "%d", (int)(r.right-r.left));
1396 set_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "KM_Size_Height",
1397 type);
1398
1399 /* Remove runtime information.
1400 This should be the last action taken here. */
1401 delete kmi;
1402 kmi = NULL;
1403 SetWindowLong (dlg, GWL_USERDATA, 0);
1404 return FALSE;
1405
1406 case WM_MOVE:
1407 GetWindowRect (dlg, &r);
1408 kmi->pos_x = r.left;
1409 kmi->pos_y = r.top;
1410 break;
1411
1412
1413 case WM_RBUTTONUP:
1414 do_create_minpopup (dlg);
1415 break;
1416
1417 case WM_NOTIFY:
1418 NMHDR *notify;
1419 POINT p;
1420 HMENU popup;
1421
1422 notify = (NMHDR *)lparam;
1423 if (!notify)
1424 break;
1425 switch (notify->code) {
1426 case TBN_QUERYDELETE:
1427 SetWindowLong (dlg, DWL_MSGRESULT, TRUE);
1428 return TRUE;
1429
1430 case TBN_QUERYINSERT:
1431 SetWindowLong (dlg, DWL_MSGRESULT, TRUE);
1432 return TRUE;
1433
1434 case TBN_GETBUTTONINFO:
1435 LPTBNOTIFY lpTbNotify;
1436 lpTbNotify = (LPTBNOTIFY)lparam;
1437 if (lpTbNotify->iItem < (sizeof(tbb) / sizeof(tb_button_s))) {
1438 lpTbNotify->tbButton.iBitmap = imagelist_getindex (tbb[lpTbNotify->iItem].icon);
1439 lpTbNotify->tbButton.idCommand = tbb[lpTbNotify->iItem].command;
1440 lpTbNotify->tbButton.fsState = TBSTATE_ENABLED;
1441 lpTbNotify->tbButton.fsStyle = TBSTYLE_BUTTON;
1442 lpTbNotify->tbButton.iString = 0;
1443 strncpy (lpTbNotify->pszText, tbb[lpTbNotify->iItem].text, lpTbNotify->cchText);
1444 SetWindowLong(dlg, DWL_MSGRESULT, TRUE);
1445 }
1446 return TRUE;
1447
1448 case TBN_RESET: /* Restore last saved toolbar status */
1449 TBSAVEPARAMS tbsp;
1450
1451 tbsp.hkr = HKEY_CURRENT_USER;
1452 tbsp.pszSubKey = "Software\\WinPT";
1453 tbsp.pszValueName = "KM_toolbar";
1454 SendMessage (notify->hwndFrom, TB_SAVERESTORE, FALSE, (LPARAM)&tbsp);
1455 break;
1456
1457 case TBN_BEGINADJUST: /* User is about to change the toolbar. Save it */
1458 tbsp.hkr = HKEY_CURRENT_USER;
1459 tbsp.pszSubKey = "Software\\WinPT";
1460 tbsp.pszValueName = "KM_toolbar";
1461 SendMessage (notify->hwndFrom, TB_SAVERESTORE, TRUE, (LPARAM)&tbsp);
1462 break;
1463
1464 case TBN_ENDADJUST: /* User has finished customizing the toolbar. Save it. */
1465 tbsp.hkr = HKEY_CURRENT_USER;
1466 tbsp.pszSubKey = "Software\\WinPT";
1467 tbsp.pszValueName = "KM_toolbar";
1468 SendMessage (notify->hwndFrom, TB_SAVERESTORE, TRUE, (LPARAM)&tbsp);
1469 break;
1470
1471 case TTN_GETDISPINFO:
1472 LPTOOLTIPTEXT lpttt;
1473 lpttt = (LPTOOLTIPTEXT)lparam;
1474
1475 lpttt->hinst = NULL;
1476 switch (lpttt->hdr.idFrom) {
1477 case ID_KEYMISC_KEYWIZARD:
1478 lpttt->lpszText = (char*)_("Generate new key pair");
1479 break;
1480
1481 case ID_KEYMISC_SENDRECV:
1482 lpttt->lpszText = (char*)_("Search for a specific key");
1483 break;
1484
1485 case ID_KEYMISC_DELETE:
1486 lpttt->lpszText = (char *)_("Delete key from keyring");
1487 break;
1488
1489 case ID_KEYMISC_PROPS:
1490 lpttt->lpszText = (char *)_("Show key properties");
1491 break;
1492
1493 case ID_KEYMISC_SIGN:
1494 lpttt->lpszText = (char *)_("Sign key");
1495 break;
1496
1497 case ID_KEYCTX_COPY:
1498 lpttt->lpszText = (char *)_("Copy key to clipboard");
1499 break;
1500
1501 case ID_KEYCTX_PASTE:
1502 lpttt->lpszText = (char*)_("Paste key from clipboard");
1503 break;
1504
1505 case ID_KEYMISC_IMPORT:
1506 lpttt->lpszText = (char *)_("Import key to keyring");
1507 break;
1508
1509 case ID_KEYMISC_EXPORT:
1510 lpttt->lpszText = (char *)_("Export key to a file");
1511 break;
1512 }
1513 return TRUE;
1514
1515 case LVN_ITEMCHANGED:
1516 if (((LPNMLISTVIEW)lparam)->uNewState) { /* item selected? */
1517 kmi->lv_idx = listview_get_curr_pos (kmi->lv);
1518 update_ui_items (dlg, kmi->lv);
1519 return TRUE;
1520 }
1521 break;
1522
1523 case NM_RCLICK:
1524 if (!wait_for_progress_cb (0))
1525 break;
1526 if (notify->idFrom == IDC_KEYMISC_KEYLIST) {
1527 l_idx =listview_get_curr_pos (kmi->lv);
1528 if (l_idx == -1)
1529 return TRUE; /* Popup only when a item was selected */
1530 GetCursorPos (&p);
1531 hm = LoadMenu (glob_hinst, MAKEINTRESOURCE (IDR_WINPT_KEYMISC_CTX));
1532 popup = GetSubMenu (hm, 0);
1533 translate_popupmenu_strings (popup);
1534
1535 if (km_check_for_seckey (kmi->lv, l_idx, &i))
1536 set_menu_state (popup, ID_KEYCTX_SETDEFKEY, MF_ENABLED);
1537 if (i == 0)
1538 set_menu_state (popup, ID_KEYCTX_MAXTRUST, MF_ENABLED);
1539 if (!km_check_for_seckey (kmi->lv, l_idx, NULL) ||
1540 (km_get_key_status (kmi->lv, l_idx) & KM_FLAG_REVOKED)) {
1541 set_menu_state (popup, ID_KEYCTX_REV, MF_DISABLED|MF_GRAYED);
1542 set_menu_state (popup, ID_KEYCTX_ADDKEY, MF_DISABLED|MF_GRAYED);
1543 set_menu_state (popup, ID_KEYCTX_ADDUID, MF_DISABLED|MF_GRAYED);
1544 set_menu_state (popup, ID_KEYCTX_ADDREV, MF_DISABLED|MF_GRAYED);
1545 set_menu_state (popup, ID_KEYCTX_ADDPHOTO, MF_DISABLED|MF_GRAYED );
1546 set_menu_state (popup, ID_KEYCTX_SETPREFKS, MF_DISABLED|MF_GRAYED);
1547 }
1548 else if (km_check_for_seckey (kmi->lv, l_idx, NULL) &&
1549 km_key_is_v3 (kmi->lv, l_idx)) {
1550 /* PGP 2 keys, version 3 have no no support for photo-id's,
1551 designated revokers and secondary keys. */
1552 set_menu_state (popup, ID_KEYCTX_ADDKEY, MF_DISABLED|MF_GRAYED);
1553 set_menu_state (popup, ID_KEYCTX_ADDREV, MF_DISABLED|MF_GRAYED);
1554 set_menu_state (popup, ID_KEYCTX_ADDPHOTO, MF_DISABLED|MF_GRAYED);
1555 }
1556 if (km_get_key_status( kmi->lv, l_idx ) & KM_FLAG_DISABLED)
1557 set_menu_state (popup, ID_KEYCTX_DISABLE, MF_DISABLED|MF_GRAYED);
1558 else
1559 set_menu_state (popup, ID_KEYCTX_ENABLE, MF_DISABLED|MF_GRAYED);
1560 if (km_get_key_status (kmi->lv, l_idx) & KM_FLAG_REVOKED ||
1561 km_get_key_status (kmi->lv, l_idx) & KM_FLAG_EXPIRED)
1562 set_menu_state (popup, ID_KEYCTX_SIGN, MF_DISABLED|MF_GRAYED);
1563 if (!clip_contains_pgpkey ())
1564 set_menu_state (popup, ID_KEYCTX_PASTE, MF_DISABLED|MF_GRAYED);
1565 if (mapi_init ())
1566 set_menu_state (popup, ID_KEYCTX_SENDMAIL, MF_DISABLED|MF_GRAYED);
1567 if (!secret_key_available ())
1568 set_menu_state (popup, ID_KEYCTX_SIGN, MF_DISABLED|MF_GRAYED);
1569
1570 /* Override 'Default Keyserver' with the actual name. */
1571 host = kserver_get_hostname (0, -1, &port);
1572 if (!host)
1573 host = DEF_HKP_KEYSERVER;
1574 set_menu_text (popup, ID_KEYCTX_KS_DEFAULT, host);
1575 {
1576 HMENU ks = GetSubMenu (popup, 19);
1577 for (i=0; server[i].name != NULL; i++)
1578 insert_menu_item (ks, i+2, WM_APP+i, server[i].name);
1579 }
1580 popup_gpg_readonly (dlg, popup);
1581 if (listview_count_items (kmi->lv, 1) > 1)
1582 popup_multiple (dlg, popup);
1583 TrackPopupMenu (popup, TPM_RIGHTALIGN, p.x, p.y, 0, dlg, NULL);
1584 DestroyMenu (popup);
1585 DestroyMenu (hm);
1586 return TRUE;
1587 }
1588 break;
1589
1590 case LVN_COLUMNCLICK:
1591 if (notify->idFrom == IDC_KEYMISC_KEYLIST) {
1592 NMLISTVIEW *nft = (LPNMLISTVIEW) lparam;
1593 int sortby = 0;
1594
1595 if (!wait_for_progress_cb (0))
1596 break;
1597 switch (nft->iSubItem) {
1598 case 0: sortby = KEY_SORT_USERID; break;
1599 case 1: sortby = KEY_SORT_KEYID; break;
1600 case 2: sortby = KEY_SORT_IS_SECRET; break;
1601 case 3: sortby = KEY_SORT_LEN; break;
1602 case 5: sortby = KEY_SORT_VALIDITY; break;
1603 case 6: sortby = KEY_SORT_OTRUST; break;
1604 case 7: sortby = KEY_SORT_CREATED; break;
1605 case 8: sortby = KEY_SORT_ALGO; break;
1606 default: return TRUE; /*sortby userid.*/
1607 }
1608
1609 if ((kmi->keylist_sortby & ~KEYLIST_SORT_DESC) == sortby)
1610 kmi->keylist_sortby ^= KEYLIST_SORT_DESC;
1611 else
1612 kmi->keylist_sortby = sortby;
1613 keylist_sort (kmi->lv, kmi->keylist_sortby);
1614 return TRUE;
1615 }
1616 break;
1617 }
1618 break;
1619
1620 case WM_WINDOWPOSCHANGING:
1621 if (((WINDOWPOS*)lparam)->cx < 400)
1622 ((WINDOWPOS*)lparam)->cx = 400;
1623 if (((WINDOWPOS*)lparam)->cy < 200)
1624 ((WINDOWPOS*)lparam)->cy = 200;
1625 return TRUE;
1626
1627 case WM_SIZE:
1628 do_resize_window (dlg, kmi);
1629 return TRUE;
1630
1631 case WM_SYSCOMMAND:
1632 if (LOWORD (wparam) == SC_CLOSE)
1633 EndDialog (dlg, TRUE);
1634 return FALSE;
1635
1636 case WM_MENUSELECT:
1637 change_edit_menu (kmi->lv, (HMENU)lparam, LOWORD (wparam));
1638 change_key_menu ((HMENU)lparam, LOWORD (wparam));
1639 break;
1640
1641 case WM_INITMENUPOPUP:
1642 hm = (HMENU)wparam;
1643 if ((UINT)LOWORD (lparam) == 3)
1644 set_menu_text_bypos (hm, 0, _("New"));
1645 else if ((UINT)LOWORD (lparam) == 1)
1646 set_menu_text_bypos (hm, 8, _("Preferences..."));
1647 return FALSE;
1648
1649 case WM_COMMAND:
1650 /* Allow at least 'Exit' in such a case. */
1651 if (gnupg_access_keyring (1) && LOWORD (wparam) != ID_KEYMISC_QUIT) {
1652 msg_box (dlg, _("Could not access public keyring"),
1653 _("Key Manager"), MB_ERR);
1654 return FALSE;
1655 }
1656
1657 /*wait_for_progress_cb ();*/
1658 switch (LOWORD (wparam)) {
1659 case ID_KEYMISC_QUIT:
1660 EndDialog (dlg, TRUE);
1661 return TRUE;
1662
1663 case ID_KEYMISC_FIND:
1664 km_find_key (dlg, kmi->lv);
1665 break;
1666
1667 case ID_KEYMISC_DELETE:
1668 case ID_KEYMISC_DELETE2:
1669 if (!km_delete_keys (kmi->lv, dlg))
1670 update_status_bar (kmi->statbar, kmi->lv);
1671 return TRUE;
1672
1673 case ID_KEYMISC_SIGN:
1674 if (kmi->lv_idx == -1) {
1675 msg_box (dlg, _("Please select a key."),
1676 _("Key Manager"), MB_ERR);
1677 return TRUE;
1678 }
1679 if (km_check_key_status (kmi->lv, kmi->lv_idx))
1680 return TRUE;
1681 km_get_key (kmi->lv, kmi->lv_idx, &k);
1682 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYSIGN, dlg,
1683 keysign_dlg_proc, (LPARAM)&k,
1684 _("Key Signing"), IDS_WINPT_KEYSIGN);
1685 if (k.update)
1686 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 0);
1687 return TRUE;
1688
1689 case ID_KEYMISC_REVCERT:
1690 if (kmi->lv_idx == -1) {
1691 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
1692 return TRUE;
1693 }
1694
1695 {
1696 char state[64];
1697 listview_get_item_text (kmi->lv, kmi->lv_idx, 5,
1698 state, sizeof (state) -1);
1699 if (strchr (state, 'R' )) {
1700 msg_box (dlg, _("Key already revoked!"),
1701 _("Key Manager"), MB_INFO);
1702 return TRUE;
1703 }
1704 }
1705
1706 km_get_key (kmi->lv, kmi->lv_idx, &k);
1707 if (!k.key_pair) {
1708 msg_box (dlg, _("There is no secret key available!"),
1709 _("Key Manager"), MB_ERR);
1710 return TRUE;
1711 }
1712 dialog_box_param(glob_hinst, (LPCSTR)IDD_WINPT_KEYREVOKE, dlg,
1713 key_revoke_dlg_proc, (LPARAM)&k,
1714 _("Key Revocation Cert"), IDS_WINPT_KEYREVOKE);
1715 return TRUE;
1716
1717 case ID_KEYMISC_TRUSTPATH:
1718 if (kmi->lv_idx == -1) {
1719 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
1720 return TRUE;
1721 }
1722 km_get_key (kmi->lv, kmi->lv_idx, &k);
1723 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYTRUST, dlg,
1724 keytrust_dlg_proc, (LPARAM)&k,
1725 _("List Trust Path"), IDS_WINPT_KEYTRUST);
1726 return TRUE;
1727
1728 case ID_KEYMISC_CHECKSIGS:
1729 if (kmi->lv_idx == -1) {
1730 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
1731 return TRUE;
1732 }
1733 km_get_key (kmi->lv, kmi->lv_idx, &k);
1734 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYSIG_TREE, dlg,
1735 sigtree_dlg_proc, (LPARAM)&k,
1736 _("Key Signature List"), IDS_WINPT_KEYSIG);
1737 if (k.update)
1738 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 0);
1739 if (updated_keys_avail ())
1740 refresh_keylist (kmi);
1741 return TRUE;
1742
1743 case ID_KEYMISC_PROPS:
1744 if (kmi->lv_idx == -1) {
1745 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
1746 return TRUE;
1747 }
1748 km_get_key (kmi->lv, kmi->lv_idx, &k);
1749 k.callback.ctl = kmi->lv;
1750 k.callback.idx = kmi->lv_idx;
1751 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYPROPS, dlg,
1752 keyprops_dlg_proc, (LPARAM)&k,
1753 _("Key Properties"), IDS_WINPT_KEYPROPS);
1754 if (k.update)
1755 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, k.key_pair);
1756 return TRUE;
1757
1758 case ID_KEYMISC_RECACHE:
1759 if (updated_keys_avail ())
1760 l_idx = IDYES;
1761 else {
1762 l_idx = log_box (_("Key Manager"), MB_YESNO,
1763 _("This is only useful when the keyring has been "
1764 "modified (sign a key...).\n"
1765 "Do you really want to reload the keycache?"));
1766 }
1767 if (l_idx == IDYES)
1768 reload_keycache (kmi);
1769 return TRUE;
1770
1771 case ID_KEYMISC_REBUILD:
1772 name = NULL;
1773 gpg_rebuild_cache (&name);
1774 if (name != NULL) {
1775 char *line = strchr (name, '\n');
1776 show_msg (dlg, 2000, line? name + (line-name)+1 : name);
1777 safe_free (name);
1778 }
1779 SetForegroundWindow (dlg);
1780 return TRUE;
1781
1782 case ID_KEYMISC_NEWKEY:
1783 memset (&genkey, 0, sizeof (genkey));
1784 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYGEN, dlg,
1785 keygen_dlg_proc, (LPARAM)&genkey, _("Key Generation"),
1786 IDS_WINPT_KEYGEN);
1787 if (genkey.cancel == 0)
1788 refresh_keylist (kmi);
1789 return TRUE;
1790
1791 case ID_KEYMISC_CARDNEW:
1792 if (!scard_support) {
1793 msg_box (dlg, _("Smart Card support is not available."),
1794 _("Key Manager"), MB_INFO);
1795 return TRUE;
1796 }
1797 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_CARD_KEYGEN, dlg,
1798 card_keygen_dlg_proc, 0, _("Card Key Generation"),
1799 IDS_WINPT_CARD_KEYGEN);
1800 if (updated_keys_avail ())
1801 send_cmd_id (dlg, ID_KEYMISC_RECACHE);
1802 return TRUE;
1803
1804 case ID_KEYMISC_KEYWIZARD:
1805 memset (&genkey, 0, sizeof (genkey));
1806 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYWIZARD, dlg,
1807 keygen_wizard_dlg_proc, (LPARAM)&genkey,
1808 _("Key Generation Wizard"),
1809 IDS_WINPT_KEYWIZARD);
1810 if (genkey.cancel == 0)
1811 refresh_keylist (kmi);
1812 return TRUE;
1813
1814 case ID_KEYMISC_SENDRECV:
1815 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYSERVER, dlg,
1816 keyserver_dlg_proc, 0, _("Keyserver Access"),
1817 IDS_WINPT_KEYSERVER);
1818 refresh_keylist (kmi);
1819 return TRUE;
1820
1821 case ID_KEYMISC_WINPTPREFS:
1822 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_PREFS,
1823 dlg, prefs_dlg_proc, 0,
1824 _("WinPT Preferences"), 0);
1825 break;
1826
1827 case ID_KEYMISC_GPGPREFS:
1828 rc = dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_GPGPREFS,
1829 dlg, gpgprefs_dlg_proc, 0,
1830 _("GnuPG Preferences"), IDS_WINPT_GPGPREFS);
1831 if (rc == TRUE) {
1832 reload_keycache (kmi);
1833 update_default_key_str (kmi->statbar);
1834 }
1835 return TRUE;
1836
1837 case ID_KEYMISC_GPGOPT:
1838 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_GPGOPT, dlg,
1839 gpgopt_dlg_proc, 0, _("GnuPG Options"),
1840 IDS_WINPT_GPGOPT);
1841 return TRUE;
1842
1843 case ID_KEYMISC_IMPORT:
1844 km_gui_import (kmi, LOWORD (wparam), NULL);
1845 return TRUE;
1846
1847 case ID_KEYMISC_IMPORT_HTTP:
1848 url = (struct URL_ctx_s*)get_http_file_dlg (dlg);
1849 if (url && url->cancel == 0) {
1850 km_http_import (dlg, url->url);
1851 refresh_keylist (kmi);
1852 }
1853 free_if_alloc (url);
1854 break;
1855
1856 case ID_KEYMISC_EXPORT:
1857 if (kmi->lv_idx == -1) {
1858 msg_box (dlg, _("Please select a key."),
1859 _("Key Manager"), MB_ERR);
1860 return TRUE;
1861 }
1862 if (listview_count_items (kmi->lv, 1) > 1)
1863 name = m_strdup ("Exported_GPG_Keys.asc");
1864 else {
1865 key = km_get_key_ptr (kmi->lv, kmi->lv_idx, NULL);
1866 name = km_gen_export_filename (key->subkeys->keyid+8, 0);
1867 }
1868 t = get_filesave_dlg (dlg, _("Choose Name for Key File"), NULL, name);
1869 free_if_alloc (name);
1870 if (t == NULL)
1871 return TRUE;
1872 km_file_export (dlg, kmi->lv, t);
1873 return TRUE;
1874
1875 case ID_KEYMISC_EXPORT_PRIVKEY:
1876 if (kmi->lv_idx == -1) {
1877 msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
1878 return TRUE;
1879 }
1880 if( !km_check_for_seckey( kmi->lv, kmi->lv_idx, NULL ) ) {
1881 msg_box (dlg, _("There is no corresponding secret key for this key."),
1882 _("Key Manager"), MB_ERR);
1883 return TRUE;
1884 }
1885 if (listview_count_items (kmi->lv, 1) > 1) {
1886 msg_box (dlg, _("You can only export one secret key."),
1887 _("Key Manager"), MB_ERR);
1888 return TRUE;
1889 }
1890 i = msg_box (dlg,
1891 _("This operation will export your *SECRET* key!\n\n"
1892 "Never send this key to ANYONE, it should be available\n"
1893 "ONLY on your machine and you may use this function\n"
1894 "to copy the key to a safe place.\n\n"
1895 "Do you really want to export the key?"),
1896 _("WARNING"), MB_INFO|MB_YESNO);
1897 if (i == IDYES) {
1898 key = km_get_key_ptr (kmi->lv, kmi->lv_idx, NULL);
1899 name = km_gen_export_filename (key->subkeys->keyid+8, 1);
1900 t = get_filesave_dlg (dlg, _("Choose Name for Key File"), NULL, name);
1901 if (t != NULL)
1902 km_privkey_export (dlg, kmi->lv, t);
1903 }
1904 return TRUE;
1905
1906 case ID_KEYMISC_INFO:
1907 dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_ABOUT, dlg,
1908 about_winpt_dlg_proc, 0, _("About WinPT"),
1909 IDS_WINPT_ABOUT);
1910 break;
1911
1912 case ID_KEYMISC_DEVWWW:
1913 ShellExecute (dlg, "open", "http://wald.intevation.org/projects/winpt",
1914 NULL, NULL, SW_SHOW);
1915 break;
1916
1917 case ID_KEYMISC_WEBSITE:
1918 ShellExecute (dlg, "open", "http://www.winpt.org",
1919 NULL, NULL, SW_SHOW);
1920 break;
1921
1922 case ID_KEYMISC_HELP:
1923 start_help (dlg, 0);
1924 break;
1925
1926 case ID_KEYMISC_OT:
1927 dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_OWNERTRUST,
1928 dlg, ownertrust_dlg_proc, 0,
1929 _("Ownertrust"), IDS_WINPT_OWNERTRUST);
1930 break;
1931
1932 case ID_KEYMISC_EDITKEY:
1933 if (km_get_key (kmi->lv, kmi->lv_idx, &k))
1934 break;
1935 dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT, dlg,
1936 keyedit_main_dlg_proc, (LPARAM)&k,
1937 _("Key Edit"), IDS_KEYCTX_EDIT);
1938 if (k.update)
1939 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 1);
1940 break;
1941
1942 case ID_KEYMISC_COPY:
1943 km_clip_export (dlg, kmi->lv);
1944 break;
1945
1946 case ID_KEYMISC_SELALL:
1947 listview_select_all (kmi->lv);
1948 break;
1949
1950 case ID_KEYMISC_PASTE:
1951 km_gui_import (kmi, LOWORD (wparam), NULL);
1952 break;
1953
1954 case ID_KEYCTX_SETPREFKS:
1955 if (km_get_key (kmi->lv, kmi->lv_idx, &k))
1956 break;
1957 keyedit_set_pref_keyserver (&k, dlg);
1958 break;
1959
1960 case ID_KEYMISC_REFRESH_KEYS:
1961 if (listview_count_items (kmi->lv, 1) == 0) {
1962 msg_box (dlg, _("No key was selected, select all by default."),
1963 _("Key Manager"), MB_INFO);
1964 listview_select_all (kmi->lv);
1965 }
1966 if (!km_refresh_from_keyserver (kmi->lv, dlg))
1967 msg_box (dlg, _("Keyserver refresh finished."),
1968 _("Key Manager"), MB_OK);
1969 break;
1970
1971 /** Context menu **/
1972 case ID_KEYCTX_EDIT:
1973 send_cmd_id( dlg, ID_KEYMISC_EDITKEY );
1974 break;
1975
1976 case ID_KEYCTX_PROPS:
1977 send_cmd_id( dlg, ID_KEYMISC_PROPS );
1978 break;
1979
1980 case ID_KEYCTX_UIDS:
1981 send_cmd_id( dlg, ID_KEYMISC_UID );
1982 break;
1983
1984 case ID_KEYCTX_SIGN:
1985 send_cmd_id( dlg, ID_KEYMISC_SIGN );
1986 break;
1987
1988 case ID_KEYCTX_DEL:
1989 send_cmd_id (dlg, ID_KEYMISC_DELETE);
1990 break;
1991
1992 case ID_KEYCTX_REV:
1993 send_cmd_id( dlg, ID_KEYMISC_REVCERT );
1994 break;
1995
1996 case ID_KEYCTX_SENDMAIL:
1997 km_send_to_mail_recipient (kmi->lv, dlg);
1998 break;
1999
2000 case ID_KEYCTX_KS_DEFAULT:
2001 host = kserver_get_hostname (0, -1, &port);
2002 km_send_to_keyserver (kmi->lv, dlg, host, port);
2003 break;
2004
2005 case ID_KEYCTX_ADDKEY:
2006 km_get_key (kmi->lv, kmi->lv_idx, &k);
2007 keyedit_add_subkey (&k, dlg, NULL);
2008 if (k.update)
2009 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 1);
2010 break;
2011
2012 case ID_KEYCTX_ADDUID:
2013 km_get_key (kmi->lv, kmi->lv_idx, &k);
2014 keyedit_add_userid (&k, dlg, NULL);
2015 if (k.update)
2016 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 1);
2017 break;
2018
2019 case ID_KEYCTX_ADDREV:
2020 km_get_key (kmi->lv, kmi->lv_idx, &k);
2021 keyedit_add_revoker (&k, dlg);
2022 if (k.update)
2023 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 1);
2024 break;
2025
2026 case ID_KEYCTX_ADDPHOTO:
2027 km_get_key (kmi->lv, kmi->lv_idx, &k);
2028 keyedit_add_photo (&k, dlg);
2029 if (k.update)
2030 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 1);
2031 break;
2032
2033 case ID_KEYCTX_RECVFROM:
2034 km_refresh_from_keyserver (kmi->lv, dlg);
2035 if (updated_keys_avail ())
2036 refresh_keylist (kmi);
2037 break;
2038
2039 case ID_KEYCTX_UID_COPY:
2040 case ID_KEYCTX_KEYID_COPY:
2041 case ID_KEYCTX_FPR_COPY:
2042 case ID_KEYCTX_KINFO_COPY:
2043 case ID_KEYCTX_EMAIL_COPY:
2044 copy_key_info (LOWORD (wparam), kmi);
2045 break;
2046
2047 case ID_KEYCTX_COPY:
2048 send_cmd_id (dlg, ID_KEYMISC_COPY);
2049 break;
2050
2051 case ID_KEYCTX_PASTE:
2052 send_cmd_id (dlg, ID_KEYMISC_PASTE);
2053 break;
2054
2055 case ID_KEYCTX_DISABLE:
2056 case ID_KEYCTX_ENABLE:
2057 i = LOWORD (wparam) == ID_KEYCTX_ENABLE? 1 : 0;
2058 if (km_get_key (kmi->lv, kmi->lv_idx, &k))
2059 break;
2060 rc = km_enable_disable_key (kmi->lv, dlg, kmi->lv_idx, i);
2061 if (!rc)
2062 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 0);
2063 break;
2064
2065 case ID_KEYCTX_LISTSIGS:
2066 send_cmd_id (dlg, ID_KEYMISC_CHECKSIGS);
2067 break;
2068
2069 case ID_KEYCTX_MAXTRUST:
2070 if (km_get_key (kmi->lv, kmi->lv_idx, &k))
2071 break;
2072 rc = km_set_implicit_trust (dlg, kmi->lv, kmi->lv_idx);
2073 if (!rc)
2074 update_key (kmi->lv, kmi->lv_idx, k.tmp_keyid, 0);
2075 break;
2076
2077 case ID_KEYCTX_SETDEFKEY:
2078 if (!km_check_key_status (kmi->lv, kmi->lv_idx)) {
2079 key = km_get_key_ptr (kmi->lv, kmi->lv_idx, NULL);
2080 rc = set_gnupg_default_key (key->subkeys->keyid+8);
2081 if (rc)
2082 msg_box (dlg, winpt_strerror (rc), _("Key Manager"), MB_ERR);
2083 update_default_key_str (kmi->statbar);
2084 }
2085 break;
2086
2087 case ID_KEYMISC_VIEWKEYID:
2088 case ID_KEYMISC_VIEWCIPHER:
2089 case ID_KEYMISC_VIEWTYPE:
2090 case ID_KEYMISC_VIEWCREAT:
2091 case ID_KEYMISC_VIEWDESC:
2092 hm = GetMenu (dlg);
2093 i = get_menu_state (hm, LOWORD (wparam));
2094 set_menu_state (hm, LOWORD (wparam),
2095 i & MFS_CHECKED? MFS_UNCHECKED : MFS_CHECKED);
2096 modify_listview_columns (kmi, LOWORD (wparam), !(i & MFS_CHECKED));
2097 break;
2098
2099 case ID_GROUP_NEW:
2100 case ID_GROUP_PASTE:
2101 case ID_GROUP_DELETE:
2102 case ID_GROUP_SHOW:
2103 /* XXX: Implement group manager. */
2104 return TRUE;
2105 }
2106
2107 break;
2108 }
2109
2110 return FALSE;
2111 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26