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

Contents of /trunk/Src/wptKeyManagerDlg.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 333 - (show annotations)
Tue Oct 13 10:51:21 2009 UTC (15 years, 4 months ago) by twoaday
File size: 67302 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26