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

Contents of /trunk/Src/wptKeyManagerDlg.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26