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

Contents of /trunk/Src/wptKeyManagerDlg.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 165 - (show annotations)
Tue Jan 24 10:10:15 2006 UTC (19 years, 1 month ago) by twoaday
File size: 62848 byte(s)
2006-01-21  Timo Schulz  <twoaday@freakmail.de>
                                                                                
        * wptKeyCache.cpp (keycache_next_key): Handle the case
        that there is a secret key without a public part.
        * wptKeyserver.cpp (kserver_save_conf): Save ports.
        * wptKeyserverDlg.cpp (keyserver_modify_dlg_proc):
        Reset keyserver name.
        * wptKeyPropsDlg.cpp (keyprops_dlg_proc): Just indicate
        an update, do not update the cache.
        * wptFileManagerDlg.cpp (file_import_dlg_proc): Use one
        dialog for both clipboard and file imports.
        * wptKeyManager.cpp (km_file_import, km_clip_import):
        Changes to support new update system.
        (gpg_clip_import): New.
        * wptKeyManagerDlg.cpp (km_gui_import): New.
        (find_keypos): Rewritten.
        (refresh_keylist): Improved error checking.
                                                                                
(for complete list of changes, see PTD/ChangeLog, Src/ChangeLog)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26