[Winpt-commits] r340 - trunk/Src
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Sun Nov 27 14:15:10 CET 2011
Author: twoaday
Date: 2011-11-27 14:15:07 +0100 (Sun, 27 Nov 2011)
New Revision: 340
Added:
trunk/Src/wptBalloonPop.cpp
trunk/Src/wptDNSKeys.cpp
trunk/Src/wptJPG.cpp
trunk/Src/wptKeyEditDlgs.cpp
Removed:
trunk/Src/wptKeyEditDlgs.cpp
trunk/Src/wptMDSumDlg.cpp
Modified:
trunk/Src/ChangeLog
trunk/Src/Makefile.am
trunk/Src/wptCurrWnd.cpp
trunk/Src/wptGPG.cpp
trunk/Src/wptKeyCache.cpp
trunk/Src/wptKeyserver.cpp
trunk/Src/wptMAPI.cpp
trunk/Src/wptPassphraseCB.cpp
trunk/Src/wptPassphraseDlg.cpp
trunk/Src/wptUtil.cpp
Log:
Modified: trunk/Src/ChangeLog
===================================================================
--- trunk/Src/ChangeLog 2011-11-27 12:45:44 UTC (rev 339)
+++ trunk/Src/ChangeLog 2011-11-27 13:15:07 UTC (rev 340)
@@ -1,3 +1,9 @@
+2011-11-25 Timo Schulz <twoaday at gmx.net>
+
+ * WinPT.cpp (check_os_version): New. Separated
+ function to check the OS verson.
+ Removed emulate utf8 bug legacy code.
+
2007-08-03 Timo Schulz <twoaday at gmx.net>
* wptMainproc.cpp (wpt_main_proc): A single click
Modified: trunk/Src/Makefile.am
===================================================================
--- trunk/Src/Makefile.am 2011-11-27 12:45:44 UTC (rev 339)
+++ trunk/Src/Makefile.am 2011-11-27 13:15:07 UTC (rev 340)
@@ -17,8 +17,8 @@
AM_CPPFLAGS = -I$(top_srcdir)/Include \
-I$(top_srcdir)/Gnupg -I$(top_srcdir)/PTD \
-DWIN32 -D_WINDOWS -D_MBCS
-AM_CFLAGS = -fexceptions $(GPGME_CFLAGS)
-AM_CXXFLAGS = -fexceptions $(GPGME_CFLAGS)
+AM_CFLAGS = -fstack-protector-all -fexceptions $(GPGME_CFLAGS)
+AM_CXXFLAGS = -fstack-protector-all -fexceptions $(GPGME_CFLAGS)
AM_LDFLAGS = -mwindows
resource_files = \
@@ -62,7 +62,6 @@
wptKeysigDlg.cpp \
wptKeysignDlg.cpp \
wptKeyTrustPathDlg.cpp \
- wptMDSumDlg.cpp \
wptOwnertrustDlg.cpp \
wptPassphraseDlg.cpp \
wptPINDlg.cpp \
@@ -132,5 +131,3 @@
.rc.o:
$(WINDRES) -I $(srcdir) -I . -I $(top_srcdir)/Ico \
-I $(top_srcdir)/icons `test -f '$<' || echo '$(srcdir)/'`$< $@
-
-
Added: trunk/Src/wptBalloonPop.cpp
===================================================================
--- trunk/Src/wptBalloonPop.cpp 2011-11-27 12:45:44 UTC (rev 339)
+++ trunk/Src/wptBalloonPop.cpp 2011-11-27 13:15:07 UTC (rev 340)
@@ -0,0 +1,280 @@
+/* wptBalloonPop.cpp - Balloon Popup-Box
+ * Copyright (C) 2009 Timo Schulz
+ *
+ * This file is part of WinPT.
+ *
+ * WinPT is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * WinPT is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+
+/* The idea is to use a balloon style 'error message' which
+ points to the control the error happened at. For instance
+ if no valid E-Mail address was entered, the balloon message
+ contains an error description with an arrow to the edit field
+ the address was supposed to be entered in. */
+
+#include <windows.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "wptTypes.h"
+
+#define BT_WINDOWNAME "WinPT_BalloonPop"
+#define BT_TIMER_IDENTIFIER 23
+#define BT_IOFFSET 8
+
+
+extern HINSTANCE glob_hinst;
+
+struct balloon_ctx_s {
+ LPCTSTR text;
+ LPCTSTR icon_name;
+ POINT pos;
+ HWND hwnd;
+};
+static struct balloon_ctx_s glob_msg;
+static BOOL window_class_registered = FALSE;
+
+
+static void
+display_balloon_text (HWND hwnd, HDC hdc, const char *text)
+{
+ RECT rc;
+ memset (&rc, 0, sizeof (rc));
+ GetClientRect(hwnd, &rc);
+
+ POINT pts[3];
+ pts[0].x = rc.left + BT_IOFFSET;
+ pts[0].y = rc.top;
+ pts[1].x = pts[0].x;
+ pts[1].y = pts[0].y + BT_IOFFSET;
+ pts[2].x = pts[1].x + BT_IOFFSET;
+ pts[2].y = pts[1].y;
+
+ // we merge three regions here:
+ // 1) basis
+ // 2) rounded box
+ // 3) arrow
+ HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
+ HRGN hrgn1 = CreateRoundRectRgn(rc.left,
+ rc.top + BT_IOFFSET,
+ rc.right,
+ rc.bottom,
+ 15, 15);
+ HRGN hrgn2 = CreatePolygonRgn(&pts[0], 3, ALTERNATE);
+ CombineRgn(hrgn, hrgn1, hrgn2, RGN_OR);
+
+ // fill the region and draw a frame around it
+ FillRgn (hdc, hrgn, GetSysColorBrush(COLOR_INFOBK));
+ FrameRgn (hdc, hrgn, (HBRUSH)GetStockObject (DKGRAY_BRUSH), 1, 1);
+
+ rc.top = rc.top + BT_IOFFSET*2;
+ rc.bottom = rc.bottom - BT_IOFFSET;
+ rc.left = rc.left + BT_IOFFSET;
+ rc.right = rc.right - BT_IOFFSET;
+
+ // FIXME: calculate best position
+ HICON hicon = LoadIcon (NULL, glob_msg.icon_name);
+ if (hicon != NULL) {
+ DrawIconEx (hdc, 5, 20, hicon, 28, 28, 0, NULL, DI_NORMAL);
+ DestroyIcon (hicon);
+ }
+
+ SetTextColor (hdc, GetSysColor (COLOR_INFOTEXT));
+ DrawText (hdc, text, strlen (text), &rc, DT_VCENTER + DT_NOCLIP);
+}
+
+
+// window procedure for the balloon tip.
+static LRESULT CALLBACK
+window_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ switch (msg) {
+ case WM_PAINT:
+ RECT rc;
+ GetWindowRect (hwnd, &rc);
+
+ POINT curpos;
+ curpos.x = glob_msg.pos.x;
+ curpos.y = glob_msg.pos.y;
+
+ rc.right = curpos.x - BT_IOFFSET + 6 + rc.right - rc.left;
+ rc.bottom = curpos.y + 20 + rc.bottom - rc.top;
+ rc.left = curpos.x - BT_IOFFSET + 6;
+ rc.top = curpos.y + 20;
+ MoveWindow (hwnd, rc.left, rc.top, rc.right - rc.left,
+ rc.bottom - rc.top, FALSE);
+
+ HDC hdc;
+ PAINTSTRUCT ps;
+ hdc = BeginPaint (hwnd, &ps);
+
+ LOGFONT lf;
+ memset (&lf, 0, sizeof (lf));
+ lf.lfHeight = 13;
+ lf.lfWeight = FW_NORMAL;
+ lf.lfQuality = ANTIALIASED_QUALITY;
+ strcpy (lf.lfFaceName, "MS Sans Serif");
+
+ HFONT hfont;
+ hfont = CreateFontIndirect(&lf);
+ HFONT hfont_old;
+ hfont_old = (HFONT)SelectObject(ps.hdc, hfont);
+
+ DrawText (ps.hdc, glob_msg.text, strlen (glob_msg.text),
+ &rc, DT_VCENTER+DT_NOCLIP+DT_CALCRECT);
+ rc.right = rc.right + 2*BT_IOFFSET;
+ rc.bottom = rc.bottom + 3*BT_IOFFSET;
+
+ ShowWindow (hwnd, SW_SHOWNA);
+ MoveWindow(hwnd, rc.left, rc.top, rc.right - rc.left,
+ rc.bottom - rc.top, TRUE);
+ SetBkMode(ps.hdc, TRANSPARENT);
+ display_balloon_text (hwnd, ps.hdc, glob_msg.text);
+
+ // restore old font object
+ SelectObject(ps.hdc, hfont_old);
+ DeleteObject (hfont);
+ EndPaint (hwnd, &ps);
+ break;
+
+ case WM_LBUTTONUP:
+ ShowWindow (hwnd, SW_HIDE);
+ break;
+
+ default:
+ return DefWindowProc (hwnd, msg, wparam, lparam);
+ }
+
+ return FALSE;
+}
+
+
+/* Callback procedure to hide the baloon window after the
+ time has been expired */
+static VOID CALLBACK
+popup_timer_proc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ ShowWindow (hwnd, SW_HIDE);
+}
+
+
+/* Register our new window class */
+static void
+register_window_class (HINSTANCE hinst)
+{
+ WNDCLASS wclass;
+ memset (&wclass, 0, sizeof (wclass));
+ wclass.style = CS_HREDRAW | CS_VREDRAW;
+ wclass.lpfnWndProc = window_proc;
+ wclass.hInstance = hinst;
+ wclass.lpszClassName = BT_WINDOWNAME;
+
+ if (!RegisterClass (&wclass))
+ abort ();
+}
+
+
+static LPCTSTR
+format_text (LPCTSTR string)
+{
+ const int off = 12;
+ static char buf[2048];
+ int n = strlen (string), pos=0, i;
+
+ memset (buf, 0, DIM (buf));
+ // FIXME: rewrite the function
+ if (n > 1600)
+ abort ();
+
+ buf[pos++] = '\n';
+ for (i=0; i < off; i++)
+ buf[pos++] = ' ';
+ for (i=0; i < n; i++) {
+ buf[pos++] = string[i];
+ if (string[i] == '\n') {
+ for (int j=0; j < off; j++)
+ buf[pos++] = ' ';
+ }
+ }
+ buf[pos++] = '\n';
+ return buf;
+}
+
+
+/* Display a baloon message box at the given X- Y-coordinates */
+HWND
+show_balloon_msg_pos (HWND hparwnd, int millis, int x, int y,
+ LPCTSTR string, LPCTSTR icon_name)
+{
+ if (!window_class_registered) {
+ register_window_class (glob_hinst);
+ window_class_registered = TRUE;
+ }
+
+ // if no icon is requsted, print the text as it is.
+ if (!icon_name)
+ glob_msg.text = string;
+ else
+ glob_msg.text = format_text (string);
+ glob_msg.icon_name = icon_name;
+
+ if (x > 0 && y > 0) { // use specific coordinates
+ glob_msg.pos.x = x;
+ glob_msg.pos.y = y;
+ }
+ else { // point to the lower left region of the control
+ RECT rect;
+ GetWindowRect (hparwnd, &rect);
+ glob_msg.pos.x = rect.left;
+ glob_msg.pos.y = rect.bottom - 20;
+ }
+
+ // we use a persistent window for the balloon messages
+ // instead of destroy/create we hide the window whenever it
+ // is unused.
+ if (!glob_msg.hwnd) {
+ glob_msg.hwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
+ BT_WINDOWNAME, BT_WINDOWNAME,
+ WS_POPUP, 1, 1, 1, 1,
+ NULL, NULL, glob_hinst, NULL);
+ if (!glob_msg.hwnd)
+ BUG (0);
+ }
+
+ // ensure 'parent' never loses focus.
+ HWND hwnd = glob_msg.hwnd;
+ ShowWindow (hwnd, SW_SHOW);
+ UpdateWindow (hwnd);
+ EnableWindow (hparwnd, TRUE);
+ SetActiveWindow (NULL);
+
+ // show message for a fixed amount of time
+ SetTimer (hwnd, BT_TIMER_IDENTIFIER, millis, popup_timer_proc);
+
+ return hwnd;
+}
+
+
+/* Show message at the default position for 5 seconds */
+void
+show_balloon_msg (HWND hparwnd, LPCTSTR string, LPCTSTR icon_name)
+{
+ show_balloon_msg_pos (hparwnd, 5000, 0, 0, string ,icon_name);
+}
+
+
+/* Disable the message box (hide the window) */
+void
+balloon_msg_disable (void)
+{
+ ShowWindow (glob_msg.hwnd, SW_HIDE);
+}
Modified: trunk/Src/wptCurrWnd.cpp
===================================================================
--- trunk/Src/wptCurrWnd.cpp 2011-11-27 12:45:44 UTC (rev 339)
+++ trunk/Src/wptCurrWnd.cpp 2011-11-27 13:15:07 UTC (rev 340)
@@ -1,5 +1,5 @@
/* wptCurrWnd.cpp - Current window code
- * Copyright (C) 2001-2004, 2006, 2007 Timo Schulz
+ * Copyright (C) 2001-2004, 2006, 2007, 2011 Timo Schulz
*
* This file is part of WinPT.
*
@@ -29,9 +29,9 @@
/* PTD prototypes from the DLL. */
-extern "C" HWND PTD_get_curr_hwnd (void);
-extern "C" BOOL PTD_keyb_send (UINT *keys, UINT n_keys);
-extern "C" int PTD_is_used (void);
+extern "C" HWND PTD_get_current_window (void);
+extern "C" BOOL PTD_keyboard_send_keys (UINT *keys, UINT n_keys);
+extern "C" int PTD_is_hook_used (void);
/* Clear the clipboard contents. */
@@ -73,12 +73,12 @@
{
unsigned int keys[4];
- if (PTD_is_used ()) {
+ if (PTD_is_hook_used ()) {
keys[0] = VK_CONTROL | 0x8000;
keys[1] = 'A' | 0x8000;
keys[2] = 'A';
keys[3] = VK_CONTROL;
- PTD_keyb_send (keys, 4);
+ PTD_keyboard_send_keys (keys, 4);
}
else {
@@ -96,12 +96,12 @@
{
unsigned int keys[4];
- if (PTD_is_used ()) {
+ if (PTD_is_hook_used ()) {
keys[0] = VK_CONTROL | 0x8000;
keys[1] = 'V' | 0x8000;
keys[2] = 'V';
keys[3] = VK_CONTROL;
- PTD_keyb_send (keys, 4);
+ PTD_keyboard_send_keys (keys, 4);
}
else {
KEYDOWN (VK_CONTROL, 0x1d);
@@ -118,12 +118,12 @@
{
unsigned int keys[4];
- if (PTD_is_used ()) {
+ if (PTD_is_hook_used ()) {
keys[0] = VK_CONTROL | 0x8000;
keys[1] = 'C' | 0x8000;
keys[2] = 'C';
keys[3] = VK_CONTROL;
- PTD_keyb_send (keys, 4);
+ PTD_keyboard_send_keys (keys, 4);
}
else {
KEYDOWN (VK_CONTROL, 0x1d);
@@ -153,7 +153,7 @@
prev = GetForegroundWindow ();
else {
*r_main = GetNextWindow (main, GW_HWNDNEXT);
- return PTD_get_curr_hwnd ();
+ return PTD_get_current_window ();
}
SetForegroundWindow (prev);
@@ -161,6 +161,7 @@
GetWindowThreadProcessId (prev, NULL),
TRUE);
fg = GetFocus ();
+
AttachThreadInput (GetCurrentThreadId (),
GetWindowThreadProcessId (prev, NULL),
FALSE);
@@ -175,8 +176,7 @@
in @ctx.
A return value of 0 indicates a problem. */
int
-copy_window_content (HWND old_hwnd, HWND *r_main, HWND *r_focus,
- int use_hotkey)
+copy_window_content (HWND old_hwnd, HWND *r_main, HWND *r_focus, int use_hotkey)
{
HWND hwnd;
int rc;
@@ -196,14 +196,14 @@
if the clipboard contains some text. */
SendMessage (hwnd, WM_COPY, 0, 0);
if (!clip_check ()) {
- rc = 0;
+ rc = WPTERR_SUCESS;
goto leave;
}
/* Then the check if the window is an edit control */
window_msg_em_set_pos (hwnd, 0);
SendMessage (hwnd, WM_COPY, 0, 0);
if (!clip_check ()) {
- rc = 0;
+ rc = WPTERR_SUCESS;
goto leave;
}
@@ -211,7 +211,7 @@
window_msg_selectall ();
window_msg_copy ();
if (!clip_check ())
- rc = 0;
+ rc = WPTERR_SUCESS;
leave:
AttachThreadInput (GetCurrentThreadId (),
Copied: trunk/Src/wptDNSKeys.cpp (from rev 332, trunk/PTD/wptDNSKeys.cpp)
===================================================================
--- trunk/PTD/wptDNSKeys.cpp 2009-09-26 10:02:36 UTC (rev 332)
+++ trunk/Src/wptDNSKeys.cpp 2011-11-27 13:15:07 UTC (rev 340)
@@ -0,0 +1,192 @@
+#error "do not use it"
+/* wptDNSKeys.cpp - Support for retrieving keys via DNS
+ * Copyright (C) 2006 Timo Schulz
+ *
+ * This file is part of WinPT.
+ *
+ * WinPT is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WinPT is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WinPT; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <windows.h>
+#include <windns.h>
+
+#include "wptDNSKeys.h"
+
+
+/* typedef for the function signature. */
+typedef DNS_STATUS (*dns_query_fnc) (LPSTR, WORD, DWORD, PIP4_ARRAY,
+ PDNS_RECORD*, PVOID *);
+
+typedef void (*dns_record_list_free_fnc) (PDNS_RECORD, DNS_FREE_TYPE);
+
+/* function pointer. */
+static dns_query_fnc dns_query = NULL;
+static dns_record_list_free_fnc dns_record_free = NULL;
+
+/* hinstance handle to the DLL. */
+static HINSTANCE dns_api = NULL;
+
+/* 1 if the DNS api is not available. */
+static int dns_failed = 0;
+
+
+
+/* Initialize the DNS sub system. We do this via dynamic loading
+ because older NT/9X systems do not have this API. */
+static int
+dns_init (void)
+{
+ if (dns_query)
+ return 0;
+ if (dns_failed)
+ return -1;
+ dns_api = LoadLibrary ("dnsapi");
+ if (!dns_api) {
+ dns_failed = 1;
+ return -1;
+ }
+ dns_query = (dns_query_fnc)GetProcAddress (dns_api, "DnsQuery_A");
+ if (!dns_query) {
+ dns_failed = 1;
+ return -1;
+ }
+ dns_record_free = (dns_record_list_free_fnc)
+ GetProcAddress (dns_api, "DnsRecordListFree");
+ if (!dns_record_free) {
+ dns_failed = 1;
+ return -1;
+ }
+ return 0;
+}
+
+
+/* Cleanup static structs. */
+void
+dns_cleanup (void)
+{
+ if (dns_api != NULL)
+ FreeLibrary (dns_api);
+ dns_api = NULL;
+ dns_failed = 0;
+}
+
+
+/* build a DNS name for the PKA lookup. */
+static char*
+email_get_pka_addr (const char *uid)
+{
+ const char *fmt = "._pka.";
+ char *bo;
+ char *pka;
+ int pos=0;
+
+ /* check that the @uid really contains an email address. */
+ if ((bo=strchr (uid, '<')) && strchr (uid, '>'))
+ uid += (bo-uid+1);
+ if (!strchr (uid, '@'))
+ return NULL;
+
+ /* create the user at _pka.domain-part.tlp string. */
+ pka = (char*)calloc (1, strlen (uid)+strlen (fmt)+1);
+ while (uid && *uid != '@')
+ pka[pos++] = *uid++;
+ uid++;
+ strcat (pka, fmt); pos += strlen (fmt);
+ while (uid && *uid && *uid != '>')
+ pka[pos++] = *uid++;
+ return pka;
+}
+
+
+/* Convert the returned data from the PKA (txt) record. */
+pka_info_t
+parse_pka_data (const char *data)
+{
+ enum pka_col_t { COL_VER=1, COL_FPR, COL_URI };
+ pka_info_t pka;
+ char *p;
+ int pos = 1;
+
+ if (strncmp (data, "v=pka1;", 8))
+ return NULL;
+ pka = (pka_info_t)calloc (1, sizeof *pka);
+ p = strtok ((char*)data, ";");
+ while (p != NULL) {
+ switch (pos) {
+ case COL_VER:
+ pka->ver = 1;
+ break;
+
+ case COL_FPR:
+ pka->fpr = strdup (p+strlen ("fpr="));
+ break;
+
+ case COL_URI: /* optional */
+ pka->uri = strdup (p+strlen ("uri="));
+ break;
+
+ default:
+ break;
+ }
+ pos++;
+ }
+ if (pos != 3) {
+ dns_free_pka_record (pka);
+ pka = NULL;
+ }
+ return pka;
+}
+
+
+/* Retrieve a PKA record from the DNS.
+ @userid is used to extract the email address. */
+extern "C" int
+dns_get_pka_record (const char *userid, pka_info_t *r_pka)
+{
+ DNS_STATUS err;
+ DNS_RECORD *rec;
+ char *addr;
+
+ *r_pka = NULL;
+ if (dns_init ())
+ return -1;
+ addr = email_get_pka_addr (userid);
+ if (!addr)
+ return -1;
+ err = dns_query (addr, DNS_TYPE_TEXT, 0, NULL, &rec, NULL);
+ if (err) {
+ free (addr);
+ return -1;
+ }
+ *r_pka = parse_pka_data (rec->Data.Txt.pStringArray[0]);
+
+ dns_record_free (rec, DnsFreeRecordList);
+ free (addr);
+ return 0;
+}
+
+
+/* Release the memory of the @pka structure. */
+extern "C" void
+dns_free_pka_record (pka_info_t pka)
+{
+ if (pka->fpr != NULL)
+ free (pka->fpr);
+ pka->fpr = NULL;
+ if (pka->uri != NULL)
+ free (pka->uri);
+ pka->uri = NULL;
+ free (pka);
+}
Modified: trunk/Src/wptGPG.cpp
===================================================================
--- trunk/Src/wptGPG.cpp 2011-11-27 12:45:44 UTC (rev 339)
+++ trunk/Src/wptGPG.cpp 2011-11-27 13:15:07 UTC (rev 340)
@@ -27,7 +27,7 @@
#include "wptGPG.h"
#include "wptGPGME.h"
-#include "wptGpgCmds.h"
+#include "wptGPGCmds.h"
#include "wptTypes.h"
#include "wptNLS.h"
#include "wptRegistry.h"
Added: trunk/Src/wptJPG.cpp
===================================================================
--- trunk/Src/wptJPG.cpp 2011-11-27 12:45:44 UTC (rev 339)
+++ trunk/Src/wptJPG.cpp 2011-11-27 13:15:07 UTC (rev 340)
@@ -0,0 +1,303 @@
+/* wptJPG.cpp - Routines for showing JPG pictures
+ * Copyright (C) 2005-2006, 2008-2009, 2011 Timo Schulz
+ * Copyright (C) 2001 Dr.Yovav Gad
+ *
+ * This file is part of WinPT.
+ *
+ * WinPT is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WinPT is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*-----------------------------------------------------------------------------
+ * Picture (Implementations) Version 1.00
+ * Author: Dr. Yovav Gad, EMail: Sources at SuperMain.com
+ * Web: www.SuperMain.com
+ *
+ * This version uses a stripped down and heavily modified version of
+ * Picture.cpp and Picture.h.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <windows.h>
+#include <ocidl.h>
+#include <olectl.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "wptJPG.h"
+#include "wptErrors.h"
+#include "wptTypes.h"
+
+#define HIMETRIC_INCH 2540
+#define ERROR_TITLE "WinPT - CJPG Error"
+
+
+/* Constructor to create an empty JPG container. */
+CJPG::CJPG (void)
+{
+ m_IPicture = NULL;
+ m_Height = 0;
+ m_Weight = 0;
+ m_Width = 0;
+}
+
+
+/* Deconstructor. Free all internal data. */
+CJPG::~CJPG (void)
+{
+ if (m_IPicture != NULL)
+ freePictureData ();
+}
+
+
+
+/* Free the allocated memory that holdes the IPicture Interface data
+ and clear picture information. */
+void
+CJPG::freePictureData (void)
+{
+ if (m_IPicture != NULL) {
+ m_IPicture->Release();
+ m_IPicture = NULL;
+ }
+ m_Height = 0;
+ m_Weight = 0;
+ m_Width = 0;
+}
+
+
+/* Open a JPG File And Load It Into IPicture (Interface) */
+BOOL
+CJPG::load (LPCSTR filepath)
+{
+ FILE *fp;
+
+ if (m_IPicture != NULL)
+ freePictureData ();
+
+ fp = fopen (filepath, "rb");
+ if (!fp) {
+ MessageBox (NULL, strerror (errno), ERROR_TITLE, MB_OK|MB_ICONSTOP);
+ return FALSE;
+ }
+
+ /* avoid to load empty JPG files and make sure we still can
+ access the file handle. */
+ struct stat st;
+ if (fstat (fileno (fp), &st) || st.st_size == 0) {
+ fclose (fp);
+ return FALSE;
+ }
+ BYTE *buffer = new BYTE[st.st_size];
+ if (!buffer)
+ BUG (0);
+ memset (buffer, 0, st.st_size);
+ int n = fread (buffer, 1, st.st_size, fp);
+ fclose (fp);
+
+ /* not the entire file were read in, so abort here. */
+ if (n != st.st_size) {
+ delete []buffer;
+ return FALSE;
+ }
+ if (!loadPictureData (buffer, st.st_size)) {
+ delete []buffer;
+ return FALSE;
+ }
+ delete [] buffer;
+
+ m_Weight = st.st_size; /* Update Picture Size Info... */
+ if (m_IPicture == NULL) {
+ m_Height = 0;
+ m_Width = 0;
+ return FALSE;
+ }
+ m_IPicture->get_Height (&m_Height);
+ m_IPicture->get_Width (&m_Width);
+ /* Calculate Its Size On a "Standard" (96 DPI) Device Context */
+ m_Height = MulDiv (m_Height, 96, HIMETRIC_INCH);
+ m_Width = MulDiv (m_Width, 96, HIMETRIC_INCH);
+ return TRUE;
+}
+
+
+
+/* read the picture data from a source (file / resource)
+ and load it into the current IPicture object in use */
+BOOL
+CJPG::loadPictureData (BYTE *buffer, int nsize)
+{
+ BOOL result = FALSE;
+
+ HGLOBAL hglobal;
+ hglobal = GlobalAlloc (GMEM_MOVEABLE, nsize);
+ if (hglobal == NULL)
+ BUG (0);
+
+ void *data;
+ data = GlobalLock (hglobal);
+ memcpy (data, buffer, nsize);
+ GlobalUnlock (hglobal);
+
+ IStream *stream = NULL;
+ if (CreateStreamOnHGlobal (hglobal, TRUE, &stream) != S_OK) {
+ GlobalFree (hglobal);
+ return result;
+ }
+
+ HRESULT hr;
+ hr = OleLoadPicture (stream, nsize, FALSE, IID_IPicture,
+ (LPVOID *)&m_IPicture);
+ if (hr == E_NOINTERFACE) {
+ MessageBox (NULL, "IPicture interface is not supported",
+ ERROR_TITLE, MB_OK|MB_ICONSTOP);
+ }
+ else if (hr == E_POINTER) {
+ MessageBox (NULL, "The provided stream is not valid",
+ ERROR_TITLE, MB_ERR);
+ }
+ else { /* S_OK */
+ stream->Release ();
+ stream = NULL;
+ result = TRUE;
+ }
+
+ GlobalFree (hglobal);
+ return result;
+}
+
+
+/* Draw the loaded picture direct to the client DC */
+BOOL
+CJPG::show (HDC pDC, POINT *leftTop, POINT *widthHeight,
+ int magnifyX, int magnifyY)
+
+{
+ RECT drawRect;
+ HRESULT hr;
+ long width = 0;
+ long height = 0;
+
+ if (pDC == NULL || m_IPicture == NULL)
+ return FALSE;
+
+ m_IPicture->get_Width (&width);
+ m_IPicture->get_Height (&height);
+
+ if (magnifyX == 0)
+ magnifyX = 0;
+ if (magnifyY == 0)
+ magnifyY = 0;
+ magnifyX = int(MulDiv (width, GetDeviceCaps(pDC, LOGPIXELSX), HIMETRIC_INCH) * magnifyX);
+ magnifyY = int(MulDiv (height, GetDeviceCaps(pDC, LOGPIXELSY), HIMETRIC_INCH) * magnifyY);
+
+ drawRect.left = leftTop->x;
+ drawRect.top = leftTop->y;
+ drawRect.right = magnifyX;
+ drawRect.bottom = magnifyY;
+
+ hr = m_IPicture->Render (pDC,
+ leftTop->x, // Left
+ leftTop->y, // Top
+ widthHeight->x +magnifyX, // Width
+ widthHeight->y +magnifyY, // Height
+ 0,
+ height,
+ width,
+ -height,
+ &drawRect);
+ if (SUCCEEDED (hr))
+ return TRUE;
+ return FALSE;
+}
+
+
+/* Get the original picture pixel size (ignore what current DC is using)
+ pointer to a Device Context is needed for pixel calculation, */
+BOOL
+CJPG::updateSizeOnDC (HDC pDC)
+
+{
+ if(pDC == NULL || m_IPicture == NULL) {
+ m_Height = 0;
+ m_Width = 0;
+ return FALSE;
+ }
+
+ m_IPicture->get_Height (&m_Height);
+ m_IPicture->get_Width (&m_Width);
+
+ /* Get Current DPI - Dot Per Inch */
+ int CurrentDPI_X = GetDeviceCaps (pDC, LOGPIXELSX);
+ int CurrentDPI_Y = GetDeviceCaps (pDC, LOGPIXELSY);
+
+ m_Height = MulDiv (m_Height, CurrentDPI_Y, HIMETRIC_INCH);
+ m_Width = MulDiv (m_Width, CurrentDPI_X, HIMETRIC_INCH);
+
+ return TRUE;
+}
+
+
+/* Return height of the current image. */
+LONG
+CJPG::getHeight (void)
+{
+ return m_Height;
+}
+
+
+/* Return weight of the current image. */
+LONG
+CJPG::getWeight (void)
+{
+ return m_Weight;
+}
+
+
+/* Return width of the current image. */
+LONG
+CJPG::getWidth (void)
+{
+ return m_Width;
+}
+
+/* Display a JPG picture in the given window at the given point. */
+int
+jpg_show (HWND hwnd, POINT *p, LPCSTR name)
+{
+ CJPG jpg;
+ BOOL rc;
+
+ rc = jpg.load (name);
+ if (!rc)
+ return WPTERR_GENERAL;
+ HDC hdc = GetWindowDC (hwnd);
+ rc = jpg.updateSizeOnDC (hdc);
+ if (!rc) {
+ ReleaseDC (hwnd, hdc);
+ return WPTERR_GENERAL;
+ }
+
+ POINT sizewnd;
+ RECT rwnd;
+ GetWindowRect (hwnd, &rwnd);
+ sizewnd.x = rwnd.right - rwnd.left;
+ sizewnd.y = rwnd.bottom - rwnd.top;
+ rc = jpg.show (hdc, p, &sizewnd, 0, 0);
+
+ ReleaseDC (hwnd, hdc);
+ jpg.freePictureData ();
+ return rc == TRUE? WPTERR_SUCESS : WPTERR_GENERAL;
+}
Modified: trunk/Src/wptKeyCache.cpp
===================================================================
--- trunk/Src/wptKeyCache.cpp 2011-11-27 12:45:44 UTC (rev 339)
+++ trunk/Src/wptKeyCache.cpp 2011-11-27 13:15:07 UTC (rev 340)
@@ -1012,6 +1012,9 @@
}
+/* FIXME: rewrite the subpacket part */
+void unhexify_buffer (const char *in, char **r_out);
+
static gpgme_error_t
decode_subpacket (const char *subpkt_data, int *type,
char **out, WORD *outlen)
Deleted: trunk/Src/wptKeyEditDlgs.cpp
===================================================================
--- trunk/Src/wptKeyEditDlgs.cpp 2011-11-27 12:45:44 UTC (rev 339)
+++ trunk/Src/wptKeyEditDlgs.cpp 2011-11-27 13:15:07 UTC (rev 340)
@@ -1,2277 +0,0 @@
-/* wptKeyEditDlgs.cpp - GPG key edit dialogs
- * Copyright (C) 2002-2009 Timo Schulz
- *
- * This file is part of WinPT.
- *
- * WinPT is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * WinPT is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <windows.h>
-#include <commctrl.h>
-#include <time.h>
-#include <assert.h>
-
-#include "resource.h"
-#include "wptTypes.h"
-#include "wptW32API.h"
-#include "wptVersion.h"
-#include "wptGPG.h"
-#include "wptCommonCtl.h"
-#include "wptContext.h"
-#include "wptDlgs.h"
-#include "wptNLS.h"
-#include "wptUTF8.h"
-#include "wptErrors.h"
-#include "wptKeylist.h"
-#include "wptKeyManager.h"
-#include "wptRegistry.h"
-#include "wptKeyEdit.h"
-#include "wptKeyserver.h"
-#include "StringBuffer.h"
-
-
-/* All edit key commands. */
-enum keyedit_commands {
- CMD_ADDKEY = 0,
- CMD_ADDUID,
- CMD_ADDPHOTO,
- CMD_ADDREVOKER,
- CMD_DELUID,
- CMD_DELKEY,
- CMD_EXPIRE,
- CMD_SHOWPREF,
- CMD_SETPREF,
- CMD_PASSWD,
- CMD_PRIMARY,
- CMD_TRUST,
- CMD_REVUID,
- CMD_REVKEY,
- CMD_DISABLE,
- CMD_ENABLE,
- CMD_SIGN,
- CMD_LSIGN,
- CMD_CHECK,
- CMD_CLEAN,
- CMD_MINIMIZE
-};
-
-struct cmdlist_s {
- const char *name;
- unsigned int need_pair:1;
- int id;
-} cmdlist[] = {
- {"ADDKEY", 1, CMD_ADDKEY},
- {"ADDUID", 1, CMD_ADDUID},
- {"ADDPHOTO", 1, CMD_ADDPHOTO},
- {"ADDREVOKER", 1, CMD_ADDREVOKER},
- {"DELUID", 1, CMD_DELUID},
- {"DELKEY", 1, CMD_DELKEY},
- {"EXPIRE", 1, CMD_EXPIRE},
- {"SHOWPREF", 0, CMD_SHOWPREF},
- {"PASSWD", 1, CMD_PASSWD},
- {"PRIMARY", 1, CMD_PRIMARY},
- {"TRUST", 0, CMD_TRUST},
- {"REVUID", 1, CMD_REVUID},
- {"REVKEY", 1, CMD_REVKEY},
- {"DISABLE", 0, CMD_DISABLE},
- {"ENABLE", 0, CMD_ENABLE},
- {"SIGN", 0, CMD_SIGN},
- {"LSIGN", 0, CMD_LSIGN},
- {"CHECK", 0, CMD_CHECK},
- {"CLEAN", 0, CMD_CLEAN},
- {"MINIMIZE", 0, CMD_MINIMIZE},
- {NULL, 0}
-};
-
-
-/* Symbolic ids for the subkey columns. */
-enum subk_col_t {
- SUBK_COL_DESC = 0,
- SUBK_COL_KEYID = 1,
- SUBK_COL_CREATION = 2,
- SUBK_COL_EXPIRES = 3,
- SUBK_COL_STATUS = 4,
- SUBK_COL_C_FLAG = 5,
- SUBK_COL_S_FLAG = 6,
- SUBK_COL_E_FLAG = 7,
- SUBK_COL_A_FLAG = 8
-};
-
-/* Symbolic ids for the userid columns. */
-enum uid_col_t {
- UID_COL_VALID = 0,
- UID_COL_NAME = 1,
- UID_COL_EMAIL = 2,
- UID_COL_CREATION = 3
-};
-
-/* Key edit callback context. */
-struct keyedit_cb_s {
- HWND parent; /* parent window handle. */
- const char *keyid; /* key ID of the key. */
- const char *pass; /* pointer to the passphrase. */
- listview_ctrl_t lv;
- int lv_pos;
- void *opaque;
- unsigned int finished:1;
- unsigned int is_protected:1;
-};
-typedef struct keyedit_cb_s *keyedit_cb_t;
-
-
-/* Key generation callback context. */
-struct keygen_cb_s {
- int bits;
- int algo;
- DWORD expire; /* date of expiration or '0' for infinite valid. */
- char *fpr;
- char *name;
- char *comment;
- char *email;
-};
-typedef struct keygen_cb_s *keygen_cb_t;
-
-/* Subclass context for the subkey list. */
-static subclass_s keyedit_subkey_proc;
-
-/* Subclass context for the user-id list. */
-static subclass_s keyedit_uid_proc;
-
-int keygen_check_date (SYSTEMTIME *st);
-void get_userid_preflist (const char *old_prefs, char **r_prefs, int *r_flags);
-char* get_subkey_keyid (const char *keyid);
-void ComboBox_AddString_utf8 (HWND cb, const char *txt);
-
-
-/* Associate each key with a combo box entry.
- Skip the key in @k. */
-static void
-do_init_keylist (HWND dlg, const char *keyid)
-{
- gpg_keycache_t pub;
- gpgme_key_t key;
- const char *s, *kid;
- int i, n;
-
- pub = keycache_get_ctx (1);
- gpg_keycache_rewind (pub);
- while (!gpg_keycache_next_key (pub, 0, &key)) {
- if (!key_is_useable (key) || key->invalid)
- continue;
- s = key->uids->uid;
- kid = key->subkeys->keyid;
- if (!s || !strcmp (kid+8, keyid))
- continue;
- ComboBox_AddString_utf8 (GetDlgItem (dlg, IDC_ADDREV_KEYLIST), s);
- }
-
- gpg_keycache_rewind (pub);
- /* In the second loop, we set a key pointer for each element. */
- n = SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_GETCOUNT, 0, 0);
- for (i = 0; i < n; i++) {
- gpg_keycache_next_key (pub, 0, &key);
- SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_SETITEMDATA,
- (WPARAM)(int)i, (LPARAM)key);
- }
- SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_SETCURSEL, 0, 0);
-}
-
-
-/* Add a new user-id to the list view @lv. */
-static void
-do_add_new_userid (listview_ctrl_t lv,
- const char *utf8_name, const char *email,
- const char *utf8_comment)
-{
- StringBuffer p;
- char *native;
-
- if (utf8_comment != NULL)
- p = p + utf8_name + " (" + utf8_comment + ")";
- else
- p = p + utf8_name;
- native = utf8_to_native (p.getBuffer ());
-
- listview_add_item (lv, "");
- listview_add_sub_item (lv, 0, UID_COL_VALID, _("Ultimate" ));
- listview_add_sub_item (lv, 0, UID_COL_NAME, native);
- listview_add_sub_item (lv, 0, UID_COL_EMAIL, email && *email? email : "");
- listview_add_sub_item (lv, 0, UID_COL_CREATION,
- get_key_created (time (NULL)));
- free_if_alloc (native);
-}
-
-
-static void
-do_add_new_subkey (listview_ctrl_t lv, keygen_cb_t keygen, unsigned int flags)
-{
- char info[128], keyid[32];
- const char *expdate, *s, *kid;
- int n;
-
- expdate = keygen->expire? get_key_expire_date (keygen->expire) : _("Never");
- _snprintf (info, DIM (info)-1, "%d-bit %s", keygen->bits,
- get_key_pubalgo ((gpgme_pubkey_algo_t)keygen->algo));
- kid = get_keyid_from_fpr (keygen->fpr);
- _snprintf (keyid, DIM (keyid)-1, "0x%s", kid);
- s = get_key_created (time (NULL));
- n = listview_count_items (lv, 0);
- listview_add_item_pos (lv, n);
- listview_add_sub_item (lv, n, SUBK_COL_DESC, info);
- listview_add_sub_item (lv, n, SUBK_COL_KEYID, keyid);
- listview_add_sub_item (lv, n, SUBK_COL_CREATION, s);
- listview_add_sub_item (lv, n, SUBK_COL_EXPIRES, expdate);
- if (flags & KM_FLAG_REVOKED)
- s = _("Revoked");
- else if (flags & KM_FLAG_EXPIRED)
- s = _("Expired");
- else
- s = _("OK");
- listview_add_sub_item (lv, n, SUBK_COL_STATUS, s);
-}
-
-
-/* Try to find the GPG edit key index which belongs to the user ID
- given by the email address @email, @name is used as a fallback.
- If @r_inf != NULL, the info context will be returned.
- Return value: index of the user ID or -1 on error. */
-static int
-do_find_userid (const char *keyid, const char *email,
- const char *name, gpg_uid_info_t *r_inf)
-{
- GpgKeyEdit ke;
- gpgme_error_t err;
- gpg_uid_info_t inf, ui;
- int pos = -1;
-
- ke.setKeyID (keyid);
- err = ke.getUseridInfo (&inf);
- if (err) {
- log_box (_("user ID"), MB_ERR,
- _("Could not get key information for: \"%s\":\n%s"),
- name, gpgme_strerror (err));
- return -1;
- }
-
- for (ui = inf; ui; ui = ui->next) {
- if (name && email && ui->email && ui->name) {
- if (!strcmp (ui->email, email) &&
- !strncmp (ui->name, name, strlen (name))) {
- pos = ui->index;
- break;
- }
- continue;
- }
- if (email && ui->email) {
- if (!strcmp (ui->email, email)) {
- pos = ui->index;
- break;
- }
- /* The email address is more unique, use the name just
- as the fallbck when no email address is available. */
- continue;
- }
- if (ui->name && name && !strcmp (ui->name, name)) {
- pos = ui->index;
- break;
- }
- }
- if (r_inf)
- *r_inf = inf;
- else
- gpg_uid_info_release (inf);
- return pos;
-}
-
-
-/* Return true if @fname is a JPEG file. */
-bool
-is_jpg_file (const char *fname)
-{
- FILE *fp;
- BYTE buf[10];
- int n;
-
- fp = fopen (fname, "rb");
- if (!fp)
- return false;
- n = fread (buf, 1, DIM (buf), fp);
- fclose (fp);
- if (n < (int)DIM (buf))
- return false;
- return buf[6] == 'J' && buf[7] == 'F' &&
- buf[8] == 'I' && buf[9] == 'F';
-}
-
-
-/* Dialog box procedure to add a photo. */
-BOOL CALLBACK
-keyedit_addphoto_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
-{
- static keyedit_cb_t cb;
- gpgme_error_t err;
- const char *s;
- char file[128];
- int id;
-
- switch (msg) {
- case WM_INITDIALOG:
- cb = (keyedit_cb_t)lparam;
- if (!cb)
- BUG (NULL);
- SetDlgItemText (dlg, IDC_ADDPHOTO_INF, _("Remember that the image is stored within your public key. If you use a very large picture, your key will become very large as well! Keeping the image close to 240x288 is advised."));
- SetDlgItemText (dlg, IDC_ADDPHOTO_FILEINF, _("Pick an image to use for your photo ID.\nThe image must be a JPEG file."));
- SetDlgItemText (dlg, IDC_ADDPHOTO_PWDINF, _("Passphrase"));
- SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
- SetWindowText (dlg, _("Add Photo ID"));
- SetForegroundWindow (dlg);
- break;
-
- case WM_DESTROY:
- balloon_msg_disable ();
- break;
-
- case WM_COMMAND:
- switch( LOWORD (wparam)) {
- case IDC_ADDPHOTO_SELFILE:
- s = get_fileopen_dlg (dlg, _("Select Image File"),
- "JPEG Files (*.jpg, *.jpeg)\0*.jpg;*.jpeg\0\0",
- NULL);
- if (s && !is_jpg_file (s)) {
- log_box (_("Add Photo ID"), MB_ERR,
- _("'%s' is not a valid JPEG file."), s);
- return FALSE;
- }
- if (s && *s)
- SetDlgItemText (dlg, IDC_ADDPHOTO_FILE, s);
- break;
-
- case IDOK:
- if (!GetDlgItemText (dlg, IDC_ADDPHOTO_FILE, file, sizeof (file)-1)){
- show_balloon_msg (GetDlgItem (dlg, IDC_ADDPHOTO_FILE),
- _("Please enter a file name."), IDI_ERROR);
- return FALSE;
- }
- if (get_file_size (file) == 0 || get_file_size (file) > 6144) {
- id = msg_box (dlg, _("The JPEG is really large.\n"
- "Are you sure you want to use it?"),
- _("Add Photo ID"), MB_YESNO|MB_INFO);
- if (id == IDNO)
- return TRUE;
- }
-
- {
- GpgKeyEdit ke;
-
- ke.setKeyID (cb->keyid);
- if (cb->pass)
- ke.setPassphrase (cb->pass);
- else
- ke.setNoPassphrase (true);
- err = ke.addPhotoid (file);
- }
- if (err) {
- msg_box (dlg, gpgme_strerror (err), _("Add Photo ID"), MB_ERR);
- return FALSE;
- }
- else {
- cb->finished = 1;
- msg_box (dlg, _("Photo successfully added."),
- _("GnuPG Status"), MB_OK);
- }
- EndDialog (dlg, TRUE);
- break;
-
- case IDCANCEL:
- EndDialog (dlg, FALSE);
- break;
- }
- break;
- }
- return FALSE;
-}
-
-
-/* Dialog box procedure to add a designated revoker. */
-BOOL CALLBACK
-keyedit_addrevoker_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
-{
- static keyedit_cb_t cb;
- gpgme_error_t err;
- char *uid=NULL;
-
- switch (msg) {
- case WM_INITDIALOG:
- cb = (keyedit_cb_t)lparam;
- if (!cb)
- BUG (NULL);
- do_init_keylist (dlg, cb->keyid);
- SetDlgItemText (dlg, IDC_ADDREV_INF,
- _("Appointing a key as designated revoker cannot be undone."));
- SetDlgItemText (dlg, IDC_ADDREV_KEYINF, _("Public key:"));
- SetDlgItemText (dlg, IDC_ADDREV_PWDINF, _("Passphrase"));
- SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
- SetWindowText (dlg, _("Add Revoker"));
- SetForegroundWindow (dlg);
- center_window (dlg, cb->parent);
- break;
-
- case WM_DESTROY:
- balloon_msg_disable ();
- break;
-
- case WM_COMMAND:
- switch (LOWORD (wparam)) {
- case IDOK:
- if (!GetDlgItemText_utf8 (dlg, IDC_ADDREV_KEYLIST, &uid)) {
- show_balloon_msg (GetDlgItem (dlg, IDC_ADDREV_KEYLIST),
- _("Please select a user ID."), IDI_ERROR);
- return FALSE;
- }
-
- {
- GpgKeyEdit ke;
-
- ke.setKeyID (cb->keyid);
- if (cb->pass)
- ke.setPassphrase (cb->pass);
- else
- ke.setNoPassphrase (true);
- err = ke.addDesignatedRevoker (uid);
- }
-
- safe_free (uid);
- if (err) {
- msg_box (dlg, gpgme_strerror (err), _("Add Revoker"), MB_ERR);
- return TRUE;
- }
- else {
- cb->finished = 1;
- msg_box (dlg, _("Revoker successfully addded."),
- _("GnuPG Status"), MB_OK);
- }
- EndDialog (dlg, TRUE);
- break;
-
- case IDCANCEL:
- EndDialog (dlg, FALSE);
- break;
- }
- break;
- }
- return FALSE;
-}
-
-
-/* Dialog box procedure to add a new user-ID. */
-BOOL CALLBACK
-keyedit_adduid_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
-{
- static keyedit_cb_t ctx;
- keygen_cb_t keygen;
- gpgme_error_t err;
- char *utf8_name = NULL;
- char *utf8_comment = NULL;
- char email[128];
- int rc;
-
- switch (msg) {
- case WM_INITDIALOG:
- ctx = (keyedit_cb_t)lparam;
- if (!ctx)
- dlg_fatal_error(dlg, "Could not get dialog param!");
- SetWindowText (dlg, _("Add user ID"));
- SetDlgItemText (dlg, IDC_ADDUID_INFNAME, _("&Name:"));
- SetDlgItemText (dlg, IDC_ADDUID_INFEMAIL, _("&Email:"));
- SetDlgItemText (dlg, IDC_ADDUID_INFCOMMENT, _("&Comment:"));
- SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
- SetForegroundWindow (dlg);
- center_window (dlg, ctx->parent);
- return FALSE;
-
- case WM_DESTROY:
- balloon_msg_disable ();
- break;
-
- case WM_COMMAND:
- switch ( LOWORD( wparam ) ) {
- case IDOK:
- keygen = (keygen_cb_t)ctx->opaque;
- rc = GetDlgItemText_utf8 (dlg, IDC_ADDUID_NAME, &utf8_name);
- if (!rc || rc < 5) {
- show_balloon_msg (GetDlgItem (dlg, IDC_ADDUID_NAME),
- _("Please enter a name (min. 5 chars.)"),
- IDI_ERROR);
- free_if_alloc (utf8_name);
- return FALSE;
- }
- if (strchr (utf8_name, '@')) {
- show_balloon_msg (GetDlgItem (dlg, IDC_ADDUID_NAME),
- _("Please enter the email address in the email field and not in the name field"),
- IDI_WARNING);
- free_if_alloc (utf8_name);
- return FALSE;
- }
-
- if( !GetDlgItemText (dlg, IDC_ADDUID_EMAIL, email, DIM (email) -1)) {
- show_balloon_msg (GetDlgItem (dlg, IDC_ADDUID_EMAIL),
- _("Please enter an email address."),IDI_ERROR);
- free_if_alloc (utf8_name);
- return FALSE;
- }
- if (check_email_address (email)) {
- show_balloon_msg (GetDlgItem (dlg, IDC_ADDUID_EMAIL),
- _("Invalid email address."), IDI_ERROR);
- free_if_alloc (utf8_name);
- return FALSE;
- }
-
- rc = GetDlgItemText_utf8 (dlg, IDC_ADDUID_COMMENT, &utf8_comment);
- {
- GpgKeyEdit ke;
-
- ke.setKeyID (ctx->keyid);
- if (ctx->is_protected)
- ke.setPassphrase (ctx->pass);
- else
- ke.setNoPassphrase (true);
- err = ke.addUserid (utf8_name, utf8_comment, email);
- }
- if (err)
- msg_box (dlg, gpgme_strerror (err), _("UserID"), MB_ERR);
- else {
- msg_box (dlg, _("user ID successfully added."), _("GnuPG Status"), MB_OK);
- ctx->finished = 1;
- /* The caller releases this items later. */
- keygen->name = utf8_name;
- keygen->comment = utf8_comment;
- keygen->email = m_strdup (email);
- }
- EndDialog (dlg, TRUE);
- return TRUE;
-
- case IDCANCEL:
- EndDialog (dlg, FALSE);
- return FALSE;
- }
- break;
- }
-
- return FALSE;
-}
-
-
-/* Initalize a combo box with default key sizes. */
-static void
-init_keysize_box (HWND dlg, int ctlid)
-{
- /* Array with standard key-length in bits. */
- const char *sizelist[] = {
- "2048", "3072", "4096", NULL
- };
-
- for (int i=0; sizelist[i] != NULL; i++)
- SendDlgItemMessage (dlg, ctlid, CB_ADDSTRING, 0,
- (LPARAM)(char*)sizelist[i]);
- SendDlgItemMessage (dlg, ctlid, CB_SETCURSEL, (WPARAM)0, 0);
-}
-
-
-static int
-get_keysize_from_box (HWND dlg, int ctlid)
-{
- int pos;
- char buf[32];
-
- pos = SendDlgItemMessage (dlg, ctlid, CB_GETCURSEL, 0, 0);
- if (pos == CB_ERR)
- return -1;
- SendDlgItemMessage (dlg, ctlid, CB_GETLBTEXT, pos, (LPARAM)(char*)buf);
- return atoi (buf);
-}
-
-
-/* Create a time_t from a system time @st. */
-time_t
-w32_mktime (SYSTEMTIME *st)
-{
- struct tm tm;
-
- memset (&tm, 0, sizeof (tm));
- tm.tm_year = st->wYear-1900;
- tm.tm_mday = st->wDay;
- tm.tm_mon = st->wMonth-1;
- return mktime (&tm);
-}
-
-
-/* Dialog procedure for adding a new secondary key. */
-BOOL CALLBACK
-keyedit_addsubkey_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
-{
- static keyedit_cb_t ctx;
- keygen_cb_t keygen;
- gpgme_error_t err;
- SYSTEMTIME st;
- HWND hwnd;
- int index, size, valid;
-
- switch (msg) {
- case WM_INITDIALOG:
- ctx = (keyedit_cb_t)lparam;
- if (!ctx)
- BUG (NULL);
- SetWindowText (dlg, _("Add Subkey"));
- SetDlgItemText (dlg, IDC_ADDSUBKEY_INFALGO, _("Key type:"));
- SetDlgItemText (dlg, IDC_ADDSUBKEY_INFSIZE, _("Size in bits:"));
- SetDlgItemText (dlg, IDC_ADDSUBKEY_INFVALID, _("Key expiration:"));
- SetDlgItemText (dlg, IDC_ADDSUBKEY_EXPIRE, _("&Never"));
- SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
-
- hwnd = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);
- listbox_add_string (hwnd, _("DSA (sign only)"));
- listbox_add_string (hwnd, _("ElGamal (encrypt only)"));
- listbox_add_string (hwnd, _("RSA (sign only)"));
- listbox_add_string (hwnd, _("RSA (encrypt only)"));
- CheckDlgButton (dlg, IDC_ADDSUBKEY_EXPIRE, BST_CHECKED);
- EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);
- EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_SIZE), FALSE);
- init_keysize_box (dlg, IDC_ADDSUBKEY_SIZE);
- SetForegroundWindow (dlg);
- center_window (dlg, ctx->parent);
- return FALSE;
-
- case WM_DESTROY:
- balloon_msg_disable ();
- break;
-
- case WM_COMMAND:
- if (HIWORD (wparam) == BN_CLICKED &&
- LOWORD (wparam) == IDC_ADDSUBKEY_EXPIRE) {
- if (IsDlgButtonChecked (dlg, IDC_ADDSUBKEY_EXPIRE))
- EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);
- else
- EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), TRUE);
- }
- if (HIWORD (wparam) == LBN_SELCHANGE &&
- LOWORD (wparam) == IDC_ADDSUBKEY_ALGO) {
- /* If DSA is selected, we disable the selection box since it
- is hardocded to 2048-bit. */
- index = SendMessage ((HWND)lparam, LB_GETCURSEL, 0, 0);
- EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_SIZE),
- index != 0? TRUE : FALSE);
- }
-
- switch (LOWORD (wparam)) {
- case IDOK:
- keygen = (keygen_cb_t)ctx->opaque;
- if (!keygen)
- BUG (NULL);
- hwnd = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);
- int map[4];
- /* this is for GPG 1.4.9 */
- map[0] = 2;
- map[1] = 4;
- map[2] = 5;
- map[3] = 6;
- /* >1.4.10 changed the menu IDs. */
- if (gpgver[0] == 1 && gpgver[1] >= 4 && gpgver[2] > 9) {
- map[0] = 3;
- map[1] = 5;
- map[2] = 4;
- map[3] = 6;
- }
-
- /* Map combo box numbers to GPG answers. */
- switch (listbox_get_cursel (hwnd)) {
- case 0:
- case 1:
- case 2:
- case 3:
- break;
- default:
- show_balloon_msg (GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO),
- _("Please select one entry."), IDI_ERROR);
- return FALSE;
- }
- index = map[listbox_get_cursel (hwnd)];
- size = get_keysize_from_box (dlg, IDC_ADDSUBKEY_SIZE);
- if (index == 2) /* DSA */
- size = 2048;
-
- hwnd = GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE);
- DateTime_GetSystemtime (hwnd, &st);
- valid = w32_mktime (&st) - time (NULL);
- valid /= 86400;
-
- keygen->bits = size;
- switch (index) {
- case 2: keygen->algo = GPGME_PK_DSA; break;
- case 4: keygen->algo = GPGME_PK_ELG_E; break;
- case 5: keygen->algo = GPGME_PK_RSA_S; break;
- case 6: keygen->algo = GPGME_PK_RSA_E; break;
- }
- if (valid > 0)
- keygen->expire = time (NULL) + valid*24*60*60;
-
- {
- GpgKeyEdit ke;
-
- ke.setKeyID (ctx->keyid);
- ke.setCallback (keygen_cb, NULL);
- if (ctx->is_protected)
- ke.setPassphrase (ctx->pass);
- else
- ke.setNoPassphrase (true);
- keygen_cb_dlg_create ();
- err = ke.addSubkey ((gpgme_pubkey_algo_t)index, size, valid);
- }
- keygen->fpr = get_subkey_keyid (ctx->keyid);
- keygen_cb_dlg_destroy (1);
- if (err)
- msg_box (dlg, gpgme_strerror (err), _("Add Subkey"), MB_ERR);
- else {
- msg_box (dlg, _("Subkey successfully added."),
- _("GnuPG Status"), MB_OK);
- ctx->finished = 1;
- }
- EndDialog (dlg, TRUE);
- return TRUE;
-
- case IDCANCEL:
- EndDialog (dlg, FALSE);
- return FALSE;
- }
- break;
- }
-
- return FALSE;
-}
-
-
-BOOL
-keyedit_add_userid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
-{
- keyedit_cb_s cb;
- keygen_cb_s keygen;
- char *pass = NULL;
- int cancel = 0;
-
- if (!k->key_pair) {
- msg_box (dlg, _("There is no secret key available!"),
- _("Add user ID"), MB_ERR);
- return FALSE;
- }
-
- if (k->is_protected) {
- pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
- if (cancel)
- return FALSE;
- }
-
- memset (&keygen, 0, sizeof (keygen));
- memset (&cb, 0, sizeof (cb));
- cb.parent = dlg;
- cb.opaque = &keygen;
- cb.is_protected = k->is_protected;
- cb.pass = pass;
- cb.keyid = k->keyid;
- dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDUID,
- dlg, keyedit_adduid_dlg_proc,
- (LPARAM)&cb, _("Add user ID"),
- IDS_WINPT_KEYEDIT_ADDUID);
- if (lv != NULL && cb.finished)
- do_add_new_userid (lv, keygen.name, keygen.email, keygen.comment);
- if (cb.finished)
- k->update = 1;
-
- free_if_alloc (keygen.name);
- free_if_alloc (keygen.email);
- free_if_alloc (keygen.comment);
- sfree_if_alloc (pass);
- return TRUE;
-}
-
-
-/* Return the keyID of the last subkey. */
-char*
-get_subkey_keyid (const char *keyid)
-{
- gpgme_error_t err;
- gpgme_key_t key;
- gpgme_ctx_t ctx;
- gpgme_subkey_t subk;
- char *kid = NULL;
-
- err = gpgme_new (&ctx);
- if (err)
- return NULL;
- err = gpgme_get_key (ctx, keyid, &key, 0);
- gpgme_release (ctx);
- if (err)
- return NULL;
- subk = get_nth_key (key, count_subkeys (key));
- if (subk != NULL)
- kid = strdup (subk->keyid);
- gpgme_key_release (key);
- return kid;
-}
-
-
-BOOL
-keyedit_add_subkey (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
-{
- keyedit_cb_s cb;
- keygen_cb_s keygen;
- char *pass = NULL;
- int cancel = 0;
-
- if (!k->key_pair) {
- msg_box (dlg, _("There is no secret key available!"),
- _("Add Subkey"), MB_ERR);
- return FALSE;
- }
- if (k->is_protected) {
- pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
- if (cancel)
- return FALSE;
- }
-
- memset (&keygen, 0, sizeof (keygen));
- memset (&cb, 0, sizeof (cb));
- cb.keyid = k->keyid;
- cb.is_protected = k->is_protected;
- cb.pass = pass;
- cb.opaque = &keygen;
- dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDSUBKEY,
- dlg, keyedit_addsubkey_dlg_proc,
- (LPARAM)&cb, _("Add Subkey"),
- IDS_WINPT_KEYEDIT_ADDSUBKEY);
- if (lv != NULL && cb.finished)
- do_add_new_subkey (lv, &keygen, 0);
- if (cb.finished)
- k->update = 1;
-
- safe_free (keygen.fpr);
- sfree_if_alloc (pass);
- return cb.finished? TRUE: FALSE;
-}
-
-
-/* Set the preferred keyserver of the given key @k. */
-BOOL
-keyedit_set_pref_keyserver (winpt_key_t k, HWND dlg)
-{
- GpgKeyEdit ke;
- gpgme_error_t err;
- struct URL_ctx_s *url;
- char *pass = NULL;
-
- url = (struct URL_ctx_s *)get_keyserver_URL_dlg (dlg);
- if (url == NULL || url->cancel == 1) {
- delete url;
- return FALSE;
- }
-
- pass = request_key_passphrase (k->ctx, _("Key Edit"), &url->cancel);
- if (url->cancel) {
- delete url;
- return FALSE;
- }
-
- ke.setKeyID (k->keyid);
- if (k->is_protected)
- ke.setPassphrase (pass);
- else
- ke.setNoPassphrase (true);
- err = ke.setPreferredKeyserver (-1, url->url);
- if (!err)
- msg_box (dlg, _("Preferred keyserver successfully set."),
- _("Key Edit"), MB_OK);
- else
- msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);
-
- keyserver_set_default (url->url, 0);
- sfree_if_alloc (pass);
- delete url;
- return err == 0? 0 : WPTERR_GENERAL;
-}
-
-
-/* Add a photo-ID to the key specified in @k. @dlg is the handle of
- the calling dialog. */
-BOOL
-keyedit_add_photo (winpt_key_t k, HWND dlg)
-{
- keyedit_cb_s cb;
- char *pass = NULL;
- int cancel;
-
- if (!k->key_pair) {
- msg_box (dlg, _("There is no secret key available!"),
- _("Add Photo ID"), MB_ERR);
- return FALSE;
- }
-
- memset (&cb, 0, sizeof (cb));
- if (k->is_protected) {
- pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
- if (cancel)
- return FALSE;
- }
- cb.parent = dlg;
- cb.pass = pass;
- cb.keyid = k->keyid;
- DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDPHOTO, dlg,
- keyedit_addphoto_dlg_proc, (LPARAM)&cb);
-
- if (cb.finished)
- k->update = 1;
- sfree_if_alloc (pass);
- return TRUE;
-}
-
-
-BOOL
-keyedit_add_revoker (winpt_key_t k, HWND dlg)
-{
- keyedit_cb_s cb;
- char *pass = NULL;
- int cancel;
-
- if (!k->key_pair) {
- msg_box (dlg, _("There is no secret key available!"), _("Add Revoker"), MB_ERR);
- return FALSE;
- }
-
- if (k->is_protected) {
- pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
- if (cancel)
- return FALSE;
- }
-
- memset (&cb, 0, sizeof (cb));
- cb.parent = dlg;
- cb.is_protected = k->is_protected;
- cb.keyid = k->keyid;
- cb.pass = pass;
- DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDREV, dlg,
- keyedit_addrevoker_dlg_proc, (LPARAM)&cb);
-
- if (cb.finished)
- k->update = 1;
- sfree_if_alloc (pass);
- return TRUE;
-}
-
-
-/* Change ownertrust of the given key @key.
- Return TRUE if the ownertrust was changed. */
-BOOL
-keyedit_change_ownertrust (winpt_key_t key, HWND dlg)
-{
- int rc;
-
- rc = dialog_box_param (glob_hinst,
- (LPCSTR)IDD_WINPT_KEYEDIT_OWNERTRUST,
- dlg, keyedit_ownertrust_dlg_proc,
- (LPARAM)key, _("Change Ownertrust"),
- IDS_WINPT_KEYEDIT_OWNERTRUST);
- if (rc == TRUE) {
- msg_box (dlg, _("Key status changed."), _("Key Edit"), MB_OK);
- key->update = 1;
- }
- return rc;
-}
-
-
-/* Check if the given key is supposed to have IDEA
- for secret key protection. */
-static int
-is_idea_protect_algo (const char *keyid)
-{
- winpt_key_s k;
- const unsigned char *sym_prefs;
- size_t n;
-
- memset (&k, 0, sizeof (k));
- if (winpt_get_pubkey (keyid, &k))
- BUG (NULL);
- if (!k.is_v3)
- return 0;
- sym_prefs = k.ext->sym_prefs;
- /* Assume that only v3 keys have no symmetric cipher
- preferences and thus IDEA is explicit. */
- if (!sym_prefs)
- return 1;
- for (n = 0; sym_prefs[n]; n++)
- ;
- if ((n == 0 || n == 1) && *sym_prefs == 0x01)
- return 1;
- return 0;
-}
-
-
-BOOL
-keyedit_change_passwd (winpt_key_t k, HWND dlg)
-{
- gpgme_error_t err;
- GpgKeyEdit ke;
- char *old_pass = NULL;
- char *new_pass = NULL;
- int cancel = 0;
-
- if (!k->key_pair) {
- msg_box (dlg, _("There is no secret key available!"),
- _("Key Edit"), MB_ERR);
- return FALSE;
- }
-
- if (!idea_available && is_idea_protect_algo (k->keyid)) {
- msg_box (dlg, _("Cannot change passphrase because the key\n"
- "is protected with the IDEA encryption algorithm."),
- _("Key Edit"), MB_ERR);
- return FALSE;
- }
-
- if (k->is_protected) {
- old_pass = request_passphrase (_("Current (old) Passphrase"),
- PASSDLG_INIT, &cancel);
- if (cancel)
- return FALSE;
- }
- new_pass = request_passphrase2 (_("New Passphrase" ),
- PASSDLG_INIT|PASSDLG_WARN_UTF8, &cancel);
- if (cancel) {
- sfree_if_alloc (old_pass);
- return FALSE;
- }
-
- if (strlen (new_pass) == 0) {
- cancel = msg_box (dlg, _("Are you sure that you really don't want a passphrase?\n"
- "This is propably a bad idea, continue?"),
- _("Key Edit"), MB_WARN_ASK);
- if (cancel != IDYES) {
- sfree_if_alloc (old_pass);
- sfree_if_alloc (new_pass);
- return FALSE;
- }
- }
-
- ke.setKeyID (k->keyid);
- ke.setPassphrase (k->is_protected? old_pass : NULL);
- if (!k->is_protected)
- ke.setNoPassphrase (true);
- err = ke.changePassphrase (new_pass, 1);
- if (err)
- msg_box (dlg, gpgme_strerror (err), _("Change Password"), MB_ERR);
- else
- msg_box (dlg, _("Passphrase successfully changed."), _("GnuPG Status"), MB_OK);
- sfree_if_alloc (old_pass);
- sfree_if_alloc (new_pass);
-
- return TRUE;
-}
-
-
-/* Initialize sub key list from key @k and return
- the new listview control. */
-listview_ctrl_t
-subkey_list_init (HWND dlg, winpt_key_t k)
-{
- LV_ITEM lvi;
- gpgme_subkey_t sub;
- struct listview_column_s cols[] = {
- {0, 80, (char *)_("Description")},
- {1, 78, (char *)_("Key ID")},
- {2, 66, (char *)_("Creation")},
- {3, 66, (char *)_("Expires")},
- {4, 64, (char *)_("Status")},
- {5, 16, (char *) "C"/*ertify*/},
- {6, 16, (char *) "S"/*ign*/},
- {7, 16, (char *) "E"/*ncrypt*/},
- {8, 16, (char *) "A"/*uth*/},
- {0, 0, 0}
- };
- listview_ctrl_t lv;
- char buf[256], tmp[128];
- const char *t;
- int nkeys = 0, i;
-
- nkeys = count_subkeys (k->ctx);
- if (!nkeys)
- BUG (NULL); /* should never happen. */
-
- listview_new (&lv, GetDlgItem (dlg, IDC_KEYEDIT_KEYLIST));
- for (i = 0; cols[i].fieldname != NULL; i++)
- listview_add_column (lv, &cols[i]);
-
- for (i = 0, sub = k->ctx->subkeys; i < nkeys; i++, sub = sub->next) {
- listview_add_item (lv, "");
- listview_add_sub_item (lv, 0, 1, "");
- memset (&lvi, 0, sizeof (lvi));
- lvi.mask = LVIF_PARAM;
- lvi.lParam = (LPARAM)sub;
- if (ListView_SetItem (lv->ctrl, &lvi) == FALSE)
- BUG (NULL);
- }
-
- listview_set_ext_style (lv);
- for (i = 0, sub = k->ctx->subkeys; i < nkeys; i++, sub = sub->next) {
- _snprintf (buf, DIM (buf)-1, "%d-bit %s", sub->length,
- get_key_pubalgo (sub->pubkey_algo));
- listview_add_sub_item (lv, i, SUBK_COL_DESC, buf);
- t = sub->keyid;
- assert (t != NULL);
- _snprintf (tmp, DIM (tmp)-1, "0x%s", t+8);
- listview_add_sub_item (lv, i, SUBK_COL_KEYID, tmp);
-
- t = get_key_created (sub->timestamp);
- if (!t)
- t = "????" "-??" "-??";
- listview_add_sub_item (lv, i, SUBK_COL_CREATION, t);
-
- if (sub->expires) {
- t = get_key_created (sub->expires);
- listview_add_sub_item (lv, i, SUBK_COL_EXPIRES, t);
- }
- else
- listview_add_sub_item (lv, i, SUBK_COL_EXPIRES, _("Never"));
- if (sub->expired)
- t = _("Expired");
- else if (sub->revoked)
- t = _("Revoked");
- else
- t = _("OK");
- listview_add_sub_item (lv, i, SUBK_COL_STATUS, t);
-
- if (sub->can_certify) t = "*"; else t = "";
- listview_add_sub_item (lv, i, SUBK_COL_C_FLAG, t);
- if (sub->can_sign) t = "*"; else t = "";
- listview_add_sub_item (lv, i, SUBK_COL_S_FLAG, t);
- if (sub->can_encrypt) t = "*"; else t = "";
- listview_add_sub_item (lv, i, SUBK_COL_E_FLAG, t);
- if (sub->can_authenticate) t = "*"; else t = "";
- listview_add_sub_item (lv, i, SUBK_COL_A_FLAG, t);
- }
- return lv;
-}
-
-
-static listview_ctrl_t
-userid_list_init (HWND dlg, winpt_key_t k)
-{
- listview_ctrl_t lv = NULL;
- gpgme_key_sig_t ks;
- struct native_uid_s *u;
- int nuids = 0, j, u_attr;
- struct listview_column_s cols[] = {
- {0, 72, (char *)_("Validity")},
- {1, 150, (char *)_("Name")},
- {2, 110, (char *)_("Email")},
- {3, 76, (char *)_("Creation")},
- {0, 0, 0}
- };
- const char *attr;
-
- nuids = count_userids (k->ctx);
- if (!nuids)
- BUG (NULL); /* should never happen. */
-
- listview_new (&lv, GetDlgItem (dlg, IDC_KEYEDIT_UIDLIST));
- for (j = 0; cols[j].fieldname != NULL; j++)
- listview_add_column (lv, &cols[j]);
-
- for (j = 0; j < nuids; j++) {
- listview_add_item (lv, " ");
- listview_add_sub_item (lv, 0, 1, " " );
- }
-
- listview_set_ext_style (lv);
- for (j = 0, u=k->ext->uids; j < nuids; u=u->next, j++) {
- if (u->revoked)
- attr = _("Revoked");
- else {
- u_attr = (int)u->validity;
- attr = get_key_trust2 (NULL, u_attr, 0, 0);
- }
- listview_add_sub_item (lv, j, UID_COL_VALID, (char *)attr);
- /* XXX: add comment if available */
- listview_add_sub_item (lv, j, UID_COL_NAME,
- u->name? u->name : _("Invalid user ID"));
- if (u->email)
- listview_add_sub_item (lv, j, UID_COL_EMAIL, u->email);
-
- ks = get_selfsig (u->signatures, k->keyid, 1);
- if (ks)
- listview_add_sub_item (lv, j, UID_COL_CREATION,
- get_key_created (ks->timestamp));
- }
- if (!k->key_pair) {
- CheckDlgButton (dlg, IDC_KEYUID_ADD, BST_INDETERMINATE);
- CheckDlgButton (dlg, IDC_KEYUID_REVOKE, BST_INDETERMINATE);
- }
- return lv;
-}
-
-
-static void
-do_init_cmdlist (HWND dlg, int is_keypair)
-{
- const char *s;
- int i;
-
- for (i = 0; (s=cmdlist[i].name); i++) {
- if (is_keypair)
- SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_ADDSTRING, 0,
- (LPARAM)(char *)s);
- else if (!cmdlist[i].need_pair)
- SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_ADDSTRING, 0,
- (LPARAM)(char *)s);
- }
- SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_SETCURSEL, 0, 0);
-}
-
-
-/* Return 1 if the requested command is RFC2440. */
-static int
-is_cmd_openpgp (int cmdid)
-{
- switch (cmdid) {
- case CMD_ADDKEY:
- case CMD_ADDPHOTO:
- case CMD_ADDREVOKER:
- case CMD_SETPREF:
- return 1;
- }
- return 0;
-}
-
-
-/* Display a message box with a short description of the commands. */
-static void
-do_show_help (HWND dlg)
-{
- const char *help;
-
- help =
- _(
- "ADDUID\t\t\tadd a user ID\r\n"
- "ADDPHOTO\t\t\tadd a photo ID\r\n"
- "DELUID\t\t\tdelete a user ID\r\n"
- "ADDKEY\t\t\tadd a secondary key\r\n"
- "DELKEY\t\t\tdelete a secondary key\r\n"
- "ADDREVOKER\t\t\tadd a revocation key\r\n"
- "EXPIRE\t\t\tchange the expire date\r\n"
- "SHOWPREF\t\t\tlist preferences (verbose)\r\n"
- "PASSWD\t\t\tchange the passphrase\r\n"
- "PRIMARY\t\t\tflag user ID as primary\r\n"
- "TRUST\t\t\tchange the ownertrust\r\n"
- "REVUID\t\t\trevoke a user ID\r\n"
- "REVKEY\t\t\trevoke a secondary key\r\n"
- "DISABLE\t\t\tdisable a key\r\n"
- "ENABLE\t\t\tenable a key\r\n"
- "SIGN\t\t\tsign a user-id (exportable)\r\n"
- "LSIGN\t\t\tsign a user-id (non-exportable)\r\n"
- "CLEAN\t\t\tremove unusable signatures from key\r\n"
- "MINIMIZE\t\t\tremove all signatures from key\r\n"
- );
- msg_box (dlg, help, _("Key Edit Help"), MB_OK);
-}
-
-
-static gpgme_subkey_t
-get_subkey_bypos (const char *keyid, int idx)
-{
- gpgme_key_t key;
-
- if (get_pubkey (keyid, &key))
- return NULL;
- return get_nth_key (key, idx);
-}
-
-
-
-static int
-do_editkey_delkey (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
-{
- gpgme_error_t err;
- gpgme_subkey_t subk;
- GpgKeyEdit ke;
- int pos, id;
- const char *warn;
- char tmp[64];
-
- if (!k->key_pair)
- return FALSE;
-
- if (listview_count_items (lv, 0) == 1) {
- show_balloon_msg (lv->ctrl, _("Primary key can not be deleted!"),
- IDI_ERROR);
- return FALSE;
- }
- pos = listview_get_curr_pos (lv);
- if (pos == -1) {
- show_balloon_msg (lv->ctrl, _("Please select a key."), IDI_ERROR);
- return FALSE;
- }
- if (pos == 0) {
- show_balloon_msg (lv->ctrl, _("Primary key can not be deleted!"),
- IDI_ERROR);
- return FALSE;
- }
-
- listview_get_item_text (lv, pos, 0, tmp, DIM (tmp) -1);
- subk = get_subkey_bypos (k->keyid, pos);
- /* Issue different warning for the different key capabilities. */
- if (subk->can_encrypt)
- warn = _("Anything encrypted to the selected subkey cannot be\n"
- "decrypted any longer.");
- else if (subk->can_sign || subk->can_certify)
- warn = _("Anything signed by the selected subkey cannot be\n"
- "verified any longer.");
- else
- warn = ""; /* just get rid of the warning. */
-
- id = log_box (_("Key Edit"), MB_YESNO|MB_ICONWARNING,
- _("\"Subkey %s, ID 0x%s.\"\n\n%s\n\n"
- "Do you really want to DELETE this subkey?"),
- tmp, subk->keyid+8, warn);
- if (id == IDNO)
- return FALSE;
-
- ke.setKeyID (k->keyid);
- err = ke.delKey (pos);
- if (err)
- msg_box (dlg, gpgme_strerror (err), _("Delete Subkey"), MB_ERR);
- else {
- listview_del_item (lv, pos);
- k->update = 1;
- status_box (dlg, _("Subkey successfully deleted."), _("GnuPG Status"));
- }
- return err? FALSE : TRUE;
-}
-
-
-/* Set the expiration date for the selected key in list view @lv.
- Return value: TRUE on success. */
-static int
-do_editkey_expire (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
-{
- gpgme_error_t err;
- GpgKeyEdit ke;
- date_s udd = {0};
- char buf[256], * pass = NULL;
- time_t exp;
- int pos, cancel = 0;
-
- if (!k->key_pair) {
- msg_box (dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR);
- return FALSE;
- }
- pos = listview_get_curr_pos (lv);
- if (pos == -1) {
- msg_box (dlg, _("Please select a key."), _("Key Edit"), MB_ERR);
- return FALSE;
- }
-
- /* If a key already expired, it is possible the user wants to
- set a new expiration date.. */
- listview_get_item_text (lv, pos, SUBK_COL_STATUS, buf, DIM (buf)-1);
- if (!strcmp (buf, _("Expired"))) {
- cancel = msg_box (dlg, _("Key already expired.\n\n"
- "Do you want to change the expiration date?"),
- _("Key Edit"), MB_QUEST_ASK);
- if (cancel == IDNO)
- return FALSE;
- cancel = 0;
- }
-
- memset (&udd, 0, sizeof (udd));
- udd.text = _("Key Expiration Date");
- dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_DATE, dlg,
- date_dlg_proc, (LPARAM)&udd,
- _("Key Expiration Date"), IDS_WINPT_DATE);
- if (udd.cancel == 1)
- return FALSE;
- if (!keygen_check_date (&udd.st)) {
- msg_box (dlg, _("The date you have chosen has already passed."),
- _("Key Edit"), MB_ERR);
- return FALSE;
- }
- if (k->is_protected) {
- pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
- if (cancel)
- return FALSE;
- }
- exp = w32_mktime (&udd.st);
-
- ke.setKeyID (k->keyid);
- if (k->is_protected)
- ke.setPassphrase (pass);
- else
- ke.setNoPassphrase (true);
- err = ke.setKeyExpireDate (pos, exp, false);
- if (err)
- msg_box (dlg, gpgme_strerror (err), _("Expire Subkey"), MB_ERR);
- else {
- _snprintf (buf, DIM (buf)-1, "%s", get_key_created (exp));
- listview_add_sub_item (lv, pos, SUBK_COL_EXPIRES, buf);
- k->update = 1;
- msg_box (dlg, _("Subkey expire date successfully set."),
- _("GnuPG Status"), MB_OK);
- }
- sfree_if_alloc (pass);
- return TRUE;
-}
-
-
-/* Revoke the selected key in the list view @lv. @k contains
- control information about the global key.
- Return value: TRUE on success. */
-static int
-do_editkey_revoke (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
-{
- gpgme_error_t err;
- GpgKeyEdit ke;
- char buf[256];
- char *pass = NULL;
- int j, cancel = 0;
-
- if (!k->key_pair) {
- msg_box (dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR);
- return FALSE;
- }
-
- if ((j = listview_get_curr_pos (lv)) == -1) {
- msg_box( dlg, _("Please select a key."), _("Key Edit"), MB_ERR );
- return FALSE;
- }
- else if (listview_count_items (lv, 0) == 1) {
- msg_box( dlg, _("No subkeys were found, if you want to revoke the\n"
- "whole key, please use the Key Manager command directly.\n\n"
- "This command is only available to revoke single subkeys"),
- _("Key Edit"), MB_INFO );
- return FALSE;
- }
-
- listview_get_item_text (lv, j, SUBK_COL_STATUS, buf, DIM (buf)-1);
- if (!strcmp (buf, _("Revoked"))) {
- msg_box (dlg, _("Key already revoked."), _("Key Edit"), MB_ERR);
- return FALSE;
- }
-
- if (k->is_protected) {
- pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
- if (cancel)
- return FALSE;
- }
-
- ke.setKeyID (k->keyid);
- if (k->is_protected)
- ke.setPassphrase (pass);
- else
- ke.setNoPassphrase (true);
- err = ke.revokeSubkey (j, 0, NULL);
- if (err)
- msg_box( dlg, gpgme_strerror (err), _("Revoke Subkey"), MB_ERR);
- else {
- listview_add_sub_item (lv, j, SUBK_COL_STATUS, _("Revoked"));
- k->update = 1;
- msg_box( dlg, _("Subkey successfully revoked."), _("GnuPG Status"), MB_OK );
- }
- sfree_if_alloc (pass);
- return TRUE;
-}
-
-
-/* Revoked the selected userid in list view @lv.
- Return value: TRUE on success. */
-int
-do_editkey_revuid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
-{
- gpgme_error_t err;
- GpgKeyEdit ke;
- char buf[128], email[128];
- char inf[512];
- char *pass = NULL;
- int cancel = 0, id = 0, j;
-
- if (!k->key_pair) {
- msg_box (dlg, _("There is no secret key available!"),
- _("Revoke user ID"), MB_ERR);
- return FALSE;
- }
-
- if (listview_count_items (lv, 0) == 1) {
- msg_box (dlg, _("Key has only one user ID."), _("Key Edit"), MB_ERR);
- return FALSE;
- }
-
- if( (j = listview_get_curr_pos( lv )) == -1 ) {
- msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );
- return FALSE;
- }
-
- listview_get_item_text( lv, j, UID_COL_VALID, buf, DIM (buf) - 1);
- if (strstr (buf, _("Revoked"))) {
- msg_box (dlg, _("This user ID has been already revoked."),
- _("Key Edit"), MB_INFO);
- return FALSE;
- }
-
- listview_get_item_text (lv, j, UID_COL_NAME, buf, sizeof buf -1);
- _snprintf (inf, DIM (inf) -1, _("user ID \"%s\".\n\n"
- "Do you really want to revoke this user ID?"), buf);
- if (msg_box (dlg, inf, _("Key Edit"), MB_WARN_ASK) == IDNO)
- return FALSE;
- if (k->is_protected) {
- pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
- if (cancel)
- return FALSE;
- }
- listview_get_item_text (lv, j, UID_COL_EMAIL, email, DIM (email)-1);
- listview_get_item_text (lv, j, UID_COL_NAME, buf, DIM (buf)-1);
- id = do_find_userid (k->keyid, email, buf, NULL);
- if (id == -1)
- BUG (NULL);
-
- ke.setKeyID (k->keyid);
- if (k->is_protected)
- ke.setPassphrase (pass);
- else
- ke.setNoPassphrase (true);
- err = ke.revokeUserid (id);
- if (err)
- msg_box (dlg, gpgme_strerror (err), _("Revoke User ID"), MB_ERR);
- else {
- listview_add_sub_item (lv, j, 0, _("Revoked"));
- k->update = 1;
- status_box (dlg, _("User ID successfully revoked"), _("GnuPG Status"));
- }
- sfree_if_alloc (pass);
- return err? FALSE : TRUE;
-}
-
-
-static int
-do_editkey_primary (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
-{
- gpgme_error_t err;
- GpgKeyEdit ke;
- int j, id, cancel=0;
- char valid[32];
- char buf[256], *pass = NULL;
-
- if (listview_count_items (lv, 0) == 1)
- return TRUE;
- if ((j = listview_get_curr_pos (lv)) == -1) {
- msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
- return FALSE;
- }
- listview_get_item_text (lv, j, UID_COL_VALID, valid, DIM (valid)-1);
- if (!strcmp (valid, _("Revoked")))
- return FALSE;
- listview_get_item_text (lv, j, UID_COL_EMAIL, buf, DIM (buf)-1);
- id = do_find_userid (k->keyid, buf, NULL, NULL);
- if (id == -1)
- BUG (NULL);
- if (k->is_protected) {
- pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
- if (cancel)
- return FALSE;
- }
-
- ke.setKeyID (k->keyid);
- if (k->is_protected)
- ke.setPassphrase (pass);
- else
- ke.setNoPassphrase (true);
- err = ke.setPrimaryUserid (id);
- if (err)
- msg_box (dlg, gpgme_strerror (err), _("Primary"), MB_ERR);
- else {
- k->update = 1;
- status_box (dlg, _("User ID successfully flagged"), _("GnuPG Status"));
- }
-
- sfree_if_alloc (pass);
- return err? FALSE : TRUE;
-}
-
-
-
-#define CIPHER 11
-#define HASH 11
-#define COMPR 4
-
-static int
-parse_preflist (HWND dlg, const char *list)
-{
- char buf[128] = {0};
- char *p, *pbuf = buf;
- const char *ciphers[CIPHER] = {"", "IDEA", "3DES",
- "CAST5", "BLOWFISH", "", "",
- "AES", "AES192", "AES256", "TWOFISH"};
- const char *hash[HASH] = {"", "MD5", "SHA1", "RMD160", "",
- "", "", "", "SHA256", "SHA384", "SHA512"};
- const char *compress[COMPR] = {"", "ZIP", "ZLIB", "BZIP2"};
- int n=0;
-
- strncpy (buf, list, 127);
- p = strtok (pbuf, " ");
- while (p != NULL) {
- int algid = atol (p+1);
- n++;
- switch (*p) {
- case 'S':
- SendDlgItemMessage (dlg, IDC_SHOWPREF_CIPHERS, LB_ADDSTRING, 0,
- (LPARAM)(const char*)ciphers[algid % CIPHER]);
- break;
-
- case 'H':
- SendDlgItemMessage (dlg, IDC_SHOWPREF_HASH, LB_ADDSTRING, 0,
- (LPARAM)(const char*)hash[algid % HASH]);
- break;
-
- case 'Z':
- SendDlgItemMessage (dlg, IDC_SHOWPREF_ZIP, LB_ADDSTRING, 0,
- (LPARAM)(const char*)compress[algid % COMPR]);
- break;
-
- default:
- n--;
- }
- p = strtok (NULL, " ");
- }
- return n;
-}
-
-
-/* Dialog box procedure to show the key preferences. */
-BOOL CALLBACK
-showpref_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
-{
- static keyedit_cb_t cb = NULL;
- gpg_uid_info_t inf=NULL, u;
- gpgme_key_t key;
- char buf[128];
- int pos;
-
- switch (msg) {
- case WM_INITDIALOG:
- cb = (keyedit_cb_t)lparam;
- if (!cb)
- BUG (NULL);
- key = (gpgme_key_t)cb->opaque;
- listview_get_item_text (cb->lv, cb->lv_pos,
- UID_COL_EMAIL, buf, DIM (buf)-1);
- pos = do_find_userid (cb->keyid, buf, NULL, &inf);
- if (pos < 0 || !inf) {
- gpg_uid_info_release (inf);
- EndDialog (dlg, FALSE);
- break;
- }
- for (u=inf; u; u = u->next) {
- if (u->index == pos && u->prefs && *u->prefs) {
- _snprintf (buf, DIM (buf)-1, "%s", u->name);
- SetDlgItemText (dlg, IDC_SHOWPREF_INFO, buf);
- if (parse_preflist (dlg, u->prefs) <= 0)
- pos = -1;
- if (u->flags.mdc)
- CheckDlgButton (dlg, IDC_SHOWPREF_MDC, BST_CHECKED);
- break;
- }
- }
- gpg_uid_info_release (inf);
- if (pos == -1) {
- msg_box (dlg, _("No preferences available."), _("Key Edit"), MB_ERR);
- EndDialog (dlg, FALSE);
- break;
- }
- SetDlgItemText (dlg, IDC_SHOWPREF_MDC, _("MDC feature"));
- SetDlgItemText (dlg, IDC_SHOWPREF_PREFINF, _("Preferences"));
- SetDlgItemText (dlg, IDC_SHOWPREF_UIDHINT, _("user ID:"));
- SetWindowText (dlg, _("Key Preferences"));
- SetForegroundWindow (dlg);
- center_window (dlg, cb->parent);
- break;
-
- case WM_COMMAND:
- switch (LOWORD (wparam)) {
- case IDOK:
- EndDialog (dlg, TRUE);
- break;
-
- case IDCANCEL:
- EndDialog (dlg, FALSE);
- break;
- }
- break;
- }
- return FALSE;
-}
-
-
-static int
-do_editkey_showpref (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
-{
- struct keyedit_cb_s cb;
- char status[32];
-
- if (k->is_v3)
- return TRUE;
-
- if (listview_get_curr_pos (lv) == -1) {
- msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
- return FALSE;
- }
- memset (&cb, 0, sizeof (cb));
- cb.parent = dlg;
- cb.opaque = k->ctx;
- cb.keyid = k->keyid;
- cb.lv = lv;
- cb.lv_pos = listview_get_curr_pos (lv);
-
- listview_get_item_text (lv, cb.lv_pos, UID_COL_VALID,
- status, DIM (status)-1);
- if (!strcmp (status, _("Revoked")))
- return TRUE;
-
- DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_SHOWPREF, dlg,
- showpref_dlg_proc, (LPARAM)&cb);
- return TRUE;
-}
-
-
-static int
-do_editkey_deluid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
-{
- gpgme_error_t err;
- GpgKeyEdit ke;
- char email[128], name[128];
- char inf[384];
- int pos, id = 0;
-
- if (!k->key_pair)
- return FALSE;
-
- if (listview_count_items (lv, 0) == 1) {
- msg_box (dlg, _("Primary user ID can not be deleted!"),
- _("Key Edit"), MB_ERR);
- return FALSE;
- }
- pos = listview_get_curr_pos (lv);
- if (pos == -1) {
- msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
- return FALSE;
- }
-
- listview_get_item_text (lv, pos, UID_COL_NAME, name, DIM(name) -1);
- _snprintf (inf, DIM (inf)-1, _("user ID \"%s\".\n\n"
- "All signatures on this user ID will be also deleted."
- "\n\n"
- "Do you really want to DELETE this user ID?"),
- name);
- if (msg_box (dlg, inf, _("Key Edit"), MB_YESNO|MB_ICONWARNING) == IDNO)
- return FALSE;
-
- listview_get_item_text (lv, pos, UID_COL_EMAIL, email, DIM (email)-1);
- listview_get_item_text (lv, pos, UID_COL_NAME, name, DIM (name)-1);
- id = do_find_userid (k->keyid, email, name, NULL);
- if (id == -1)
- BUG (NULL);
-
- ke.setKeyID (k->keyid);
- err = ke.delUserid (id);
- if (err)
- msg_box (dlg, gpgme_strerror (err), _("Delete User ID"), MB_ERR);
- else {
- listview_del_item (lv, pos);
- k->update = 1;
- status_box (dlg, _("User ID successfully deleted"), _("GnuPG Status"));
- }
- return err? FALSE : TRUE;
-}
-
-
-/* Subclass routine for the subkey listview control to allow shortcuts. */
-static BOOL CALLBACK
-subkey_subclass_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
-{
- int virt_key = 0;
- winpt_key_t key;
-
- switch (msg) {
- case WM_KEYUP:
- virt_key = (int)wparam;
- key = (winpt_key_t)keyedit_subkey_proc.opaque;
- if (!key || !key->key_pair)
- break;
-
- switch (virt_key) {
- case VK_DELETE:
- SendDlgItemMessage (keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,
- CB_SETCURSEL, CMD_DELKEY, 0);
- send_cmd_id (keyedit_subkey_proc.dlg, IDOK);
- break;
-
- case VK_INSERT:
- SendDlgItemMessage (keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,
- CB_SETCURSEL, CMD_ADDKEY, 0);
- send_cmd_id (keyedit_subkey_proc.dlg, IDOK);
- break;
- }
- }
- return CallWindowProc (keyedit_subkey_proc.old, dlg, msg, wparam, lparam);
-}
-
-
-static BOOL CALLBACK
-uid_subclass_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
-{
- int virt_key = 0;
- winpt_key_t key;
-
- switch (msg) {
- case WM_KEYUP:
- virt_key = (int)wparam;
- key = (winpt_key_t)keyedit_uid_proc.opaque;
- if (!key || !key->key_pair)
- break;
-
- switch (virt_key) {
- case VK_DELETE:
- SendDlgItemMessage (keyedit_uid_proc.dlg, IDC_KEYEDIT_CMD,
- CB_SETCURSEL, CMD_DELUID, 0);
- send_cmd_id (keyedit_uid_proc.dlg, IDOK);
- break;
-
- case VK_INSERT:
- SendDlgItemMessage (keyedit_uid_proc.dlg, IDC_KEYEDIT_CMD,
- CB_SETCURSEL, CMD_ADDUID, 0);
- send_cmd_id (keyedit_uid_proc.dlg, IDOK);
- break;
- }
- }
- return CallWindowProc (keyedit_uid_proc.old, dlg, msg, wparam, lparam);
-}
-
-
-/* Enable the key @k when @enable is 1, disable it otherwise. */
-static void
-do_editkey_enable_disable (winpt_key_t k, HWND dlg,
- listview_ctrl_t lv, int enable)
-{
- gpgme_error_t err;
- gpgme_key_t key;
- GpgKeyEdit ke;
-
- // FIXME: We had to duplicate the code here since the key manager
- // code uses the listview to get the pointer to the key!
- key = k->ctx;
- ke.setKeyID (key->subkeys->keyid);
-
- err = enable? ke.enable () : ke.disable ();
- if (!err) {
- show_msg (dlg, 1500, _("Key status changed."));
- k->update = 1;
- }
- else
- msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
-}
-
-
-static void
-do_editkey_minimize (winpt_key_t k, HWND dlg)
-{
- gpgme_error_t err;
- GpgKeyEdit ke;
-
- ke.setKeyID (k->keyid);
- err = ke.minimizeKey ();
- if (err)
- msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);
- else {
- msg_box (dlg, _("Finished to compact key."), _("Key Edit"), MB_OK);
- k->update = 1;
- }
-}
-
-
-static void
-do_editkey_clean (winpt_key_t k, HWND dlg)
-{
- gpgme_error_t err;
- GpgKeyEdit ke;
-
- ke.setKeyID (k->keyid);
- err = ke.cleanKey ();
- if (err)
- msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);
- else {
- msg_box (dlg, _("Finished to compact key."), _("Key Edit"), MB_OK);
- k->update = 1;
- }
-}
-
-
-/* Start the dialog to list and display the status of all
- signatures for this key. */
-static void
-do_editkey_check (winpt_key_t k, HWND dlg)
-{
- if (!k->ctx)
- get_pubkey (k->keyid, &k->ctx);
- if (!k->uid && k->ctx)
- k->uid = k->ctx->uids->uid;
- DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYSIG_TREE, dlg,
- sigtree_dlg_proc, (LPARAM)k);
-}
-
-
-static int
-do_editkey_sign_userid (winpt_key_t k, HWND dlg, listview_ctrl_t lv, int mode)
-{
- gpgme_error_t err;
- winpt_key_s signer;
- GpgKeyEdit ke;
- char *pass = NULL;
- char *defkey;
- char email[64], name[128], valid[32];
- int uid_index;
- int cancel = 0;
-
- uid_index = listview_get_curr_pos (lv);
- if (uid_index == -1) {
- msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
- return FALSE;
- }
- listview_get_item_text (lv, uid_index, UID_COL_VALID, valid, DIM (valid)-1);
- if (!strcmp (valid, _("Revoked")))
- return TRUE;
- if (mode == CMD_SIGN) {
- cancel = msg_box (dlg, _("Do you really want to make this sig exportable?"),
- _("Key Edit"), MB_QUEST_ASK);
- if (cancel == IDNO)
- return FALSE;
- }
- listview_get_item_text (lv, uid_index, UID_COL_EMAIL, email, DIM (email)-1);
- listview_get_item_text (lv, uid_index, UID_COL_NAME, name, DIM (name)-1);
- uid_index = do_find_userid (k->keyid, email, name, NULL);
-
- defkey = get_gnupg_default_key ();
- memset (&signer, 0, sizeof (signer));
- if (winpt_get_seckey (defkey, &signer)) {
- log_debug ("do_editkey_sign_userid: no default secret key.\r\n");
- free_if_alloc (defkey);
- return FALSE;
- }
- if (signer.is_protected) {
- pass = request_key_passphrase (signer.ctx, _("Key Edit"), &cancel);
- if (cancel)
- return FALSE;
- }
- ke.setKeyID (k->keyid);
- if (signer.is_protected)
- ke.setPassphrase (pass);
- else
- ke.setNoPassphrase (true);
- ke.setLocalUser (signer.ctx);
- err = ke.signUserid (uid_index,
- mode == CMD_SIGN? GPG_EDITKEY_SIGN : GPG_EDITKEY_LSIGN,
- 0, NULL);
- if (!err) {
- msg_box (dlg, _("Key successfully signed."), _("Key Edit"), MB_OK);
- k->update = 1;
- }
- else
- msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);
-
- sfree_if_alloc (pass);
- return !err? TRUE : FALSE;
-}
-
-
-static int
-lookup_cmd (HWND dlg)
-{
- char buf[64];
- int i;
-
- i = SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_GETCURSEL, 0, 0);
- if (i == LB_ERR)
- return LB_ERR;
- GetDlgItemText (dlg, IDC_KEYEDIT_CMD, buf, DIM (buf)-1);
- for (i=0; cmdlist[i].name != NULL; i++) {
- if (!strcmp (buf, cmdlist[i].name))
- return cmdlist[i].id;
- }
- return LB_ERR;
-}
-
-
-
-gpgme_error_t key_get_revokers (winpt_key_t key, int reload,
- gpg_desig_rev_t *r_rev);
-
-/* Check if the key supports designated revokers and if
- secret keys exist to generate such a revoke cert. */
-static bool
-check_desig_rev (winpt_key_t key)
-{
- gpg_desig_rev_t rev, u;
- struct winpt_key_s sk;
-
- if (!key->ext->gloflags.has_desig_rev)
- return false;
- key_get_revokers (key, 0, &rev);
- for (u = rev; u; u = u->next) {
- memset (&sk, 0, sizeof (sk));
- if (!winpt_get_seckey (u->fpr+32, &sk))
- return true;
- }
- return false;
-}
-
-
-/* Use the gpg --desig-revoker command to create a revocation
- cert for a key that lists our key as a designated revoker. */
-static void
-gen_desig_revoke_cert (winpt_key_t key, HWND dlg)
-{
- const char *warn;
- char *inf, *p;
- int id;
-
- inf = km_key_get_info (key, 0);
- warn = _("Your keys is listed as a designated revoker for the key\n\n"
- "%s\n\n"
- "Are you sure you want to create a revocation certificate\n"
- "which allows you to revoke the key listed above?");
- p = new char[strlen (inf)+1+strlen (warn)+1];
- sprintf (p, warn, inf);
- free_if_alloc (inf);
-
- id = msg_box (dlg, p, _("Key Edit"), MB_YESNO|MB_ICONWARNING);
- free_if_alloc (p);
- if (id == IDNO)
- return;
-
- key->internal = 1;
- DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYREVOKE, dlg,
- key_revoke_dlg_proc, (LPARAM)key);
-}
-
-
-/* Create tooltip control for the listview header. */
-static HWND
-create_header_tooltip (HWND dlg)
-{
- TOOLINFO ti;
- HWND tt;
-
- tt = CreateWindow (TOOLTIPS_CLASS, (LPSTR) NULL, TTS_ALWAYSTIP|TTS_BALLOON ,
- CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT,
- NULL, (HMENU) NULL, glob_hinst, NULL);
- if (!tt)
- BUG (NULL);
- memset (&ti, 0, sizeof (ti));
- ti.cbSize = sizeof (TOOLINFO);
- ti.uFlags = TTF_IDISHWND|TTF_SUBCLASS;
- ti.hwnd = dlg;
- ti.uId = (UINT) ListView_GetHeader (GetDlgItem (dlg, IDC_KEYEDIT_KEYLIST));
- ti.hinst = 0;
- ti.lpszText = (char*)_("Capabilties: C = Certify, S = Sign, E = Encrypt, A = Authenticate");
- SendMessage(tt, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
- return tt;
-}
-
-
-#define TTM_POPUP (WM_USER+34)
-
-/* Dialog box procedure for the edit key dialog. */
-BOOL CALLBACK
-keyedit_main_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
-{
- static winpt_key_t k;
- static listview_ctrl_t lvsub = NULL;
- static listview_ctrl_t lvuid = NULL;
- static HWND tt = NULL;
- int cmd;
- HWND item;
-
- switch (msg) {
- case WM_INITDIALOG:
- k = (winpt_key_t)lparam;
- if (!k)
- BUG (NULL);
- do_init_cmdlist (dlg, k->key_pair);
- lvsub = subkey_list_init (dlg, k);
- lvuid = userid_list_init (dlg, k);
- item = GetDlgItem (dlg, IDC_KEYEDIT_KEYLIST);
- keyedit_subkey_proc.opaque = (void*)k;
- keyedit_subkey_proc.dlg = dlg;
- keyedit_subkey_proc.current = (WNDPROC)subkey_subclass_proc;
- keyedit_subkey_proc.old = (WNDPROC)GetWindowLong (item, GWL_WNDPROC);
- if (keyedit_subkey_proc.old) {
- if (!SetWindowLong (item, GWL_WNDPROC,
- (LONG)keyedit_subkey_proc.current)) {
- msg_box (dlg, "Could not set subkey window procedure.",
- _("Key Edit"), MB_ERR);
- BUG (NULL);
- }
- }
- tt = create_header_tooltip (dlg);
-
- item = GetDlgItem (dlg, IDC_KEYEDIT_UIDLIST);
- keyedit_uid_proc.opaque = (void*)k;
- keyedit_uid_proc.dlg = dlg;
- keyedit_uid_proc.current = (WNDPROC)uid_subclass_proc;
- keyedit_uid_proc.old = (WNDPROC)GetWindowLong (item, GWL_WNDPROC);
- if (keyedit_uid_proc.old) {
- if (!SetWindowLong (item, GWL_WNDPROC,
- (LONG)keyedit_uid_proc.current)) {
- msg_box (dlg, "Could not set user ID window procedure.",
- _("Key Edit"), MB_ERR);
- BUG (NULL);
- }
- }
- if (k->ctx->revoked || k->ctx->expired) {
- EnableWindow (GetDlgItem (dlg, IDC_KEYEDIT_CMD), FALSE);
- EnableWindow (GetDlgItem (dlg, IDOK), FALSE);
- }
- SetDlgItemText (dlg, IDC_KEYEDIT_CMDINF, _("Command>"));
- SetDlgItemText (dlg, IDCANCEL, _("&Close"));
- SetDlgItemText (dlg, IDC_KEYEDIT_HELP, _("&Help"));
- SetDlgItemText (dlg, IDC_KEYEDIT_REVOKE, _("&Revoke..."));
- SetDlgItemText (dlg, IDOK, _("&OK"));
- if (!check_desig_rev (k))
- ShowWindow (GetDlgItem (dlg, IDC_KEYEDIT_REVOKE), SW_HIDE);
- if (k->is_v3)
- SetWindowText (dlg, _("Key Edit (PGP 2.6.x mode)"));
- else
- SetWindowText (dlg, _("Key Edit"));
- SetForegroundWindow (dlg);
- center_window (dlg, NULL);
- return TRUE;
-
- case WM_DESTROY:
- if (lvsub) {
- listview_release (lvsub);
- lvsub = NULL;
- }
- if (lvuid) {
- listview_release (lvuid);
- lvuid = NULL;
- }
- if (tt != NULL)
- DestroyWindow (tt);
-
- balloon_msg_disable ();
- break;
-
- case WM_NOTIFY:
- NMHDR *notify;
- notify = (NMHDR *)lparam;
- if (!notify || notify->idFrom != IDC_KEYEDIT_UIDLIST)
- break;
- if (notify->code == NM_DBLCLK)
- do_editkey_showpref (k, dlg, lvuid);
- else if (notify->code == NM_RCLICK && k->key_pair) {
- if (listview_count_items (lvuid, 0) == 1)
- break;
- HMENU hm = LoadMenu (glob_hinst, MAKEINTRESOURCE (IDR_WINPT_KEYEDIT));
- HMENU popup = GetSubMenu (hm, 0);
- POINT p;
-
- set_menu_text (popup, ID_KEYEDIT_UID_PRIM, _("Flag user ID as &primary"));
- set_menu_text (popup, ID_KEYEDIT_UID_DEL, _("&Delete user ID"));
- set_menu_text (popup, ID_KEYEDIT_UID_REV, _("&Revoke user ID"));
- GetCursorPos (&p);
- TrackPopupMenu (popup, TPM_RIGHTALIGN, p.x, p.y, 0, dlg, NULL);
- DestroyMenu (hm);
- DestroyMenu (popup);
- }
- break;
-
- case WM_COMMAND:
- switch (LOWORD (wparam)) {
- case IDOK:
- cmd = lookup_cmd (dlg);
- if (cmd == LB_ERR) {
- msg_box (dlg, _("Please select a command."), _("Key Edit"), MB_INFO);
- return FALSE;
- }
- if (k->is_v3 && is_cmd_openpgp (cmd)) {
- msg_box (dlg, _("This command cannot be used with PGP 2 (v3) keys.\n"),
- _("Key Edit"), MB_ERR);
- return FALSE;
- }
- switch (cmd) {
- case CMD_SHOWPREF: do_editkey_showpref (k, dlg, lvuid); break;
- case CMD_DELKEY: do_editkey_delkey (k, dlg, lvsub); break;
- case CMD_ADDKEY: keyedit_add_subkey (k, dlg, lvsub); break;
- case CMD_EXPIRE: do_editkey_expire (k, dlg, lvsub); break;
- case CMD_REVKEY: do_editkey_revoke (k, dlg, lvsub); break;
- case CMD_SETPREF:/*do_editkey_setpref (k, dlg, lvuid);*/ break;
- case CMD_ADDUID: keyedit_add_userid( k, dlg, lvuid ); break;
- case CMD_ADDREVOKER: keyedit_add_revoker( k, dlg ); break;
- case CMD_ADDPHOTO: keyedit_add_photo( k, dlg ); break;
- case CMD_REVUID: do_editkey_revuid( k, dlg, lvuid ); break;
- case CMD_DELUID: do_editkey_deluid( k, dlg, lvuid ); break;
- case CMD_PASSWD: keyedit_change_passwd (k, dlg); break;
- case CMD_PRIMARY: do_editkey_primary (k, dlg, lvuid); break;
- case CMD_ENABLE: do_editkey_enable_disable (k, dlg, lvsub, 1); break;
- case CMD_DISABLE: do_editkey_enable_disable (k, dlg, lvsub, 0); break;
- case CMD_CHECK: do_editkey_check (k, dlg); break;
- case CMD_TRUST: keyedit_change_ownertrust (k, dlg); break;
- case CMD_SIGN:
- case CMD_LSIGN: do_editkey_sign_userid (k, dlg,
- lvuid, cmd);
- break;
- case CMD_CLEAN: do_editkey_clean (k, dlg); break;
- case CMD_MINIMIZE: do_editkey_minimize (k, dlg); break;
- }
- break;
-
- case IDCANCEL:
- EndDialog (dlg, FALSE);
- break;
-
- case IDC_KEYEDIT_HELP:
- do_show_help (dlg);
- break;
-
- case IDC_KEYEDIT_REVOKE:
- gen_desig_revoke_cert (k, dlg);
- break;
-
- case ID_KEYEDIT_UID_PRIM:
- do_editkey_primary (k, dlg, lvuid);
- break;
-
- case ID_KEYEDIT_UID_DEL:
- do_editkey_deluid (k, dlg, lvuid);
- break;
-
- case ID_KEYEDIT_UID_REV:
- do_editkey_revuid (k, dlg, lvuid);
- break;
- }
- break;
- }
- return FALSE;
-}
Added: trunk/Src/wptKeyEditDlgs.cpp
===================================================================
--- trunk/Src/wptKeyEditDlgs.cpp 2011-11-27 12:45:44 UTC (rev 339)
+++ trunk/Src/wptKeyEditDlgs.cpp 2011-11-27 13:15:07 UTC (rev 340)
@@ -0,0 +1,2247 @@
+/* wptKeyEditDlgs.cpp - GPG key edit dialogs
+ * Copyright (C) 2002-2009 Timo Schulz
+ *
+ * This file is part of WinPT.
+ *
+ * WinPT is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WinPT is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <windows.h>
+#include <commctrl.h>
+#include <time.h>
+#include <assert.h>
+
+#include "resource.h"
+#include "wptTypes.h"
+#include "wptW32API.h"
+#include "wptVersion.h"
+#include "wptGPG.h"
+#include "wptCommonCtl.h"
+#include "wptContext.h"
+#include "wptDlgs.h"
+#include "wptNLS.h"
+#include "wptUTF8.h"
+#include "wptErrors.h"
+#include "wptKeylist.h"
+#include "wptKeyManager.h"
+#include "wptRegistry.h"
+#include "wptKeyEdit.h"
+#include "wptKeyserver.h"
+#include "StringBuffer.h"
+
+
+/* All edit key commands. */
+enum keyedit_commands {
+ CMD_ADDKEY = 0,
+ CMD_ADDUID,
+ CMD_ADDPHOTO,
+ CMD_ADDREVOKER,
+ CMD_DELUID,
+ CMD_DELKEY,
+ CMD_EXPIRE,
+ CMD_SHOWPREF,
+ CMD_SETPREF,
+ CMD_PASSWD,
+ CMD_PRIMARY,
+ CMD_TRUST,
+ CMD_REVUID,
+ CMD_REVKEY,
+ CMD_DISABLE,
+ CMD_ENABLE,
+ CMD_SIGN,
+ CMD_LSIGN,
+ CMD_CHECK,
+ CMD_CLEAN,
+ CMD_MINIMIZE
+};
+
+struct cmdlist_s {
+ const char *name;
+ unsigned int need_pair:1;
+ int id;
+} cmdlist[] = {
+ {"ADDKEY", 1, CMD_ADDKEY},
+ {"ADDUID", 1, CMD_ADDUID},
+ {"ADDPHOTO", 1, CMD_ADDPHOTO},
+ {"ADDREVOKER", 1, CMD_ADDREVOKER},
+ {"DELUID", 1, CMD_DELUID},
+ {"DELKEY", 1, CMD_DELKEY},
+ {"EXPIRE", 1, CMD_EXPIRE},
+ {"SHOWPREF", 0, CMD_SHOWPREF},
+ {"PASSWD", 1, CMD_PASSWD},
+ {"PRIMARY", 1, CMD_PRIMARY},
+ {"TRUST", 0, CMD_TRUST},
+ {"REVUID", 1, CMD_REVUID},
+ {"REVKEY", 1, CMD_REVKEY},
+ {"DISABLE", 0, CMD_DISABLE},
+ {"ENABLE", 0, CMD_ENABLE},
+ {"SIGN", 0, CMD_SIGN},
+ {"LSIGN", 0, CMD_LSIGN},
+ {"CHECK", 0, CMD_CHECK},
+ {"CLEAN", 0, CMD_CLEAN},
+ {"MINIMIZE", 0, CMD_MINIMIZE},
+ {NULL, 0}
+};
+
+
+/* Symbolic ids for the subkey columns. */
+enum subk_col_t {
+ SUBK_COL_DESC = 0,
+ SUBK_COL_KEYID = 1,
+ SUBK_COL_CREATION = 2,
+ SUBK_COL_EXPIRES = 3,
+ SUBK_COL_STATUS = 4,
+ SUBK_COL_C_FLAG = 5,
+ SUBK_COL_S_FLAG = 6,
+ SUBK_COL_E_FLAG = 7,
+ SUBK_COL_A_FLAG = 8
+};
+
+/* Symbolic ids for the userid columns. */
+enum uid_col_t {
+ UID_COL_VALID = 0,
+ UID_COL_NAME = 1,
+ UID_COL_EMAIL = 2,
+ UID_COL_CREATION = 3
+};
+
+/* Key edit callback context. */
+struct keyedit_cb_s {
+ HWND parent; /* parent window handle. */
+ const char *keyid; /* key ID of the key. */
+ const char *pass; /* pointer to the passphrase. */
+ listview_ctrl_t lv;
+ int lv_pos;
+ void *opaque;
+ unsigned int finished:1;
+ unsigned int is_protected:1;
+};
+typedef struct keyedit_cb_s *keyedit_cb_t;
+
+
+/* Key generation callback context. */
+struct keygen_cb_s {
+ int bits;
+ int algo;
+ DWORD expire; /* date of expiration or '0' for infinite valid. */
+ char *fpr;
+ char *name;
+ char *comment;
+ char *email;
+};
+typedef struct keygen_cb_s *keygen_cb_t;
+
+/* Subclass context for the subkey list. */
+static subclass_s keyedit_subkey_proc;
+
+/* Subclass context for the user-id list. */
+static subclass_s keyedit_uid_proc;
+
+int keygen_check_date (SYSTEMTIME *st);
+void get_userid_preflist (const char *old_prefs, char **r_prefs, int *r_flags);
+char* get_subkey_keyid (const char *keyid);
+void ComboBox_AddString_utf8 (HWND cb, const char *txt);
+
+void set_gpg_auto_passphrase_cb (passphrase_cb_s *cb, const char *title);
+gpgme_error_t passphrase_cb (void *hook, const char *uid_hint,
+ const char *passphrase_info,
+ int prev_was_bad, int fd);
+
+/* Associate each key with a combo box entry.
+ Skip the key in @k. */
+static void
+do_init_keylist (HWND dlg, const char *keyid)
+{
+ gpg_keycache_t pub;
+ gpgme_key_t key;
+ const char *s, *kid;
+ int i, n;
+
+ pub = keycache_get_ctx (1);
+ gpg_keycache_rewind (pub);
+ while (!gpg_keycache_next_key (pub, 0, &key)) {
+ if (!key_is_useable (key) || key->invalid)
+ continue;
+ s = key->uids->uid;
+ kid = key->subkeys->keyid;
+ if (!s || !strcmp (kid+8, keyid))
+ continue;
+ ComboBox_AddString_utf8 (GetDlgItem (dlg, IDC_ADDREV_KEYLIST), s);
+ }
+
+ gpg_keycache_rewind (pub);
+ /* In the second loop, we set a key pointer for each element. */
+ n = SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_GETCOUNT, 0, 0);
+ for (i = 0; i < n; i++) {
+ gpg_keycache_next_key (pub, 0, &key);
+ SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_SETITEMDATA,
+ (WPARAM)(int)i, (LPARAM)key);
+ }
+ SendDlgItemMessage (dlg, IDC_ADDREV_KEYLIST, CB_SETCURSEL, 0, 0);
+}
+
+
+/* Add a new user-id to the list view @lv. */
+static void
+do_add_new_userid (listview_ctrl_t lv,
+ const char *utf8_name, const char *email,
+ const char *utf8_comment)
+{
+ StringBuffer p;
+ char *native;
+
+ if (utf8_comment != NULL)
+ p = p + utf8_name + " (" + utf8_comment + ")";
+ else
+ p = p + utf8_name;
+ native = utf8_to_native (p.getBuffer ());
+
+ listview_add_item (lv, "");
+ listview_add_sub_item (lv, 0, UID_COL_VALID, _("Ultimate" ));
+ listview_add_sub_item (lv, 0, UID_COL_NAME, native);
+ listview_add_sub_item (lv, 0, UID_COL_EMAIL, email && *email? email : "");
+ listview_add_sub_item (lv, 0, UID_COL_CREATION,
+ get_key_created (time (NULL)));
+ free_if_alloc (native);
+}
+
+
+static void
+do_add_new_subkey (listview_ctrl_t lv, keygen_cb_t keygen, unsigned int flags)
+{
+ char info[128], keyid[32];
+ const char *expdate, *s, *kid;
+ int n;
+
+ expdate = keygen->expire? get_key_expire_date (keygen->expire) : _("Never");
+ _snprintf (info, DIM (info)-1, "%d-bit %s", keygen->bits,
+ get_key_pubalgo ((gpgme_pubkey_algo_t)keygen->algo));
+ kid = get_keyid_from_fpr (keygen->fpr);
+ _snprintf (keyid, DIM (keyid)-1, "0x%s", kid);
+ s = get_key_created (time (NULL));
+ n = listview_count_items (lv, 0);
+ listview_add_item_pos (lv, n);
+ listview_add_sub_item (lv, n, SUBK_COL_DESC, info);
+ listview_add_sub_item (lv, n, SUBK_COL_KEYID, keyid);
+ listview_add_sub_item (lv, n, SUBK_COL_CREATION, s);
+ listview_add_sub_item (lv, n, SUBK_COL_EXPIRES, expdate);
+ if (flags & KM_FLAG_REVOKED)
+ s = _("Revoked");
+ else if (flags & KM_FLAG_EXPIRED)
+ s = _("Expired");
+ else
+ s = _("OK");
+ listview_add_sub_item (lv, n, SUBK_COL_STATUS, s);
+}
+
+
+/* Try to find the GPG edit key index which belongs to the user ID
+ given by the email address @email, @name is used as a fallback.
+ If @r_inf != NULL, the info context will be returned.
+ Return value: index of the user ID or -1 on error. */
+static int
+do_find_userid (const char *keyid, const char *email,
+ const char *name, gpg_uid_info_t *r_inf)
+{
+ GpgKeyEdit ke;
+ gpgme_error_t err;
+ gpg_uid_info_t inf, ui;
+ int pos = -1;
+
+ ke.setKeyID (keyid);
+ err = ke.getUseridInfo (&inf);
+ if (err) {
+ log_box (_("user ID"), MB_ERR,
+ _("Could not get key information for: \"%s\":\n%s"),
+ name, gpgme_strerror (err));
+ return -1;
+ }
+
+ for (ui = inf; ui; ui = ui->next) {
+ if (name && email && ui->email && ui->name) {
+ if (!strcmp (ui->email, email) &&
+ !strncmp (ui->name, name, strlen (name))) {
+ pos = ui->index;
+ break;
+ }
+ continue;
+ }
+ if (email && ui->email) {
+ if (!strcmp (ui->email, email)) {
+ pos = ui->index;
+ break;
+ }
+ /* The email address is more unique, use the name just
+ as the fallbck when no email address is available. */
+ continue;
+ }
+ if (ui->name && name && !strcmp (ui->name, name)) {
+ pos = ui->index;
+ break;
+ }
+ }
+ if (r_inf)
+ *r_inf = inf;
+ else
+ gpg_uid_info_release (inf);
+ return pos;
+}
+
+
+/* Return true if @fname is a JPEG file. */
+bool
+is_jpg_file (const char *fname)
+{
+ FILE *fp;
+ BYTE buf[10];
+ int n;
+
+ fp = fopen (fname, "rb");
+ if (!fp)
+ return false;
+ n = fread (buf, 1, DIM (buf), fp);
+ fclose (fp);
+ if (n < (int)DIM (buf))
+ return false;
+ return buf[6] == 'J' && buf[7] == 'F' &&
+ buf[8] == 'I' && buf[9] == 'F';
+}
+
+
+/* Dialog box procedure to add a photo. */
+BOOL CALLBACK
+keyedit_addphoto_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ static keyedit_cb_t cb;
+ gpgme_error_t err;
+ const char *s;
+ char file[128];
+ int id;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ cb = (keyedit_cb_t)lparam;
+ if (!cb)
+ BUG (NULL);
+ SetDlgItemText (dlg, IDC_ADDPHOTO_INF, _("Remember that the image is stored within your public key. If you use a very large picture, your key will become very large as well! Keeping the image close to 240x288 is advised."));
+ SetDlgItemText (dlg, IDC_ADDPHOTO_FILEINF, _("Pick an image to use for your photo ID.\nThe image must be a JPEG file."));
+ SetDlgItemText (dlg, IDC_ADDPHOTO_PWDINF, _("Passphrase"));
+ SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
+ SetWindowText (dlg, _("Add Photo ID"));
+ SetForegroundWindow (dlg);
+ break;
+
+ case WM_DESTROY:
+ balloon_msg_disable ();
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD (wparam)) {
+ case IDC_ADDPHOTO_SELFILE:
+ s = get_fileopen_dlg (dlg, _("Select Image File"),
+ "JPEG Files (*.jpg, *.jpeg)\0*.jpg;*.jpeg\0\0",
+ NULL);
+ if (s && !is_jpg_file (s)) {
+ log_box (_("Add Photo ID"), MB_ERR,
+ _("'%s' is not a valid JPEG file."), s);
+ return FALSE;
+ }
+ if (s && *s)
+ SetDlgItemText (dlg, IDC_ADDPHOTO_FILE, s);
+ break;
+
+ case IDOK:
+ if (!GetDlgItemText (dlg, IDC_ADDPHOTO_FILE, file, DIM (file)-1)){
+ show_balloon_msg (GetDlgItem (dlg, IDC_ADDPHOTO_FILE),
+ _("Please enter a file name."), IDI_ERROR);
+ return FALSE;
+ }
+ if (get_file_size (file) == 0 || get_file_size (file) > 6144) {
+ id = msg_box (dlg, _("The JPEG is really large.\n"
+ "Are you sure you want to use it?"),
+ _("Add Photo ID"), MB_YESNO|MB_INFO);
+ if (id == IDNO)
+ return TRUE;
+ }
+
+ {
+ GpgKeyEdit ke;
+ passphrase_cb_s pcb;
+
+ set_gpg_auto_passphrase_cb (&pcb, _("Add Revoker"));
+
+ ke.setPassphraseCallback (passphrase_cb, (void*)&pcb);
+ ke.setKeyID (cb->keyid);
+ err = ke.addPhotoid (file);
+
+ release_gpg_passphrase_cb (&pcb);
+ }
+ if (err) {
+ msg_box (dlg, gpgme_strerror (err), _("Add Photo ID"), MB_ERR);
+ return FALSE;
+ }
+ else {
+ cb->finished = 1;
+ msg_box (dlg, _("Photo successfully added."),
+ _("GnuPG Status"), MB_OK);
+ }
+ EndDialog (dlg, TRUE);
+ break;
+
+ case IDCANCEL:
+ EndDialog (dlg, FALSE);
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+/* Dialog box procedure to add a designated revoker. */
+BOOL CALLBACK
+keyedit_addrevoker_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ static keyedit_cb_t cb;
+ gpgme_error_t err;
+ char *uid=NULL;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ cb = (keyedit_cb_t)lparam;
+ if (!cb)
+ BUG (NULL);
+ do_init_keylist (dlg, cb->keyid);
+ SetDlgItemText (dlg, IDC_ADDREV_INF,
+ _("Appointing a key as designated revoker cannot be undone."));
+ SetDlgItemText (dlg, IDC_ADDREV_KEYINF, _("Public key:"));
+ SetDlgItemText (dlg, IDC_ADDREV_PWDINF, _("Passphrase"));
+ SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
+ SetWindowText (dlg, _("Add Revoker"));
+ SetForegroundWindow (dlg);
+ center_window (dlg, cb->parent);
+ break;
+
+ case WM_DESTROY:
+ balloon_msg_disable ();
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD (wparam)) {
+ case IDOK:
+ if (!GetDlgItemText_utf8 (dlg, IDC_ADDREV_KEYLIST, &uid)) {
+ show_balloon_msg (GetDlgItem (dlg, IDC_ADDREV_KEYLIST),
+ _("Please select a user ID."), IDI_ERROR);
+ return FALSE;
+ }
+
+ {
+ GpgKeyEdit ke;
+ passphrase_cb_s pcb;
+
+ set_gpg_auto_passphrase_cb (&pcb, _("Add Revoker"));
+
+ ke.setPassphraseCallback (passphrase_cb, (void*)&pcb);
+ ke.setKeyID (cb->keyid);
+ err = ke.addDesignatedRevoker (uid);
+
+ release_gpg_passphrase_cb (&pcb);
+ }
+
+ safe_free (uid);
+ if (err) {
+ msg_box (dlg, gpgme_strerror (err), _("Add Revoker"), MB_ERR);
+ return TRUE;
+ }
+ else {
+ cb->finished = 1;
+ msg_box (dlg, _("Revoker successfully addded."),
+ _("GnuPG Status"), MB_OK);
+ }
+ EndDialog (dlg, TRUE);
+ break;
+
+ case IDCANCEL:
+ EndDialog (dlg, FALSE);
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+/* Dialog box procedure to add a new user-ID. */
+BOOL CALLBACK
+keyedit_adduid_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ static keyedit_cb_t ctx;
+ keygen_cb_t keygen;
+ gpgme_error_t err;
+ char *utf8_name = NULL;
+ char *utf8_comment = NULL;
+ char email[128];
+ int rc;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ ctx = (keyedit_cb_t)lparam;
+ if (!ctx)
+ dlg_fatal_error(dlg, "Could not get dialog param!");
+ SetWindowText (dlg, _("Add user ID"));
+ SetDlgItemText (dlg, IDC_ADDUID_INFNAME, _("&Name:"));
+ SetDlgItemText (dlg, IDC_ADDUID_INFEMAIL, _("&Email:"));
+ SetDlgItemText (dlg, IDC_ADDUID_INFCOMMENT, _("&Comment:"));
+ SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
+ SetForegroundWindow (dlg);
+ center_window (dlg, ctx->parent);
+ return FALSE;
+
+ case WM_DESTROY:
+ balloon_msg_disable ();
+ break;
+
+ case WM_COMMAND:
+ switch ( LOWORD( wparam ) ) {
+ case IDOK:
+ keygen = (keygen_cb_t)ctx->opaque;
+ rc = GetDlgItemText_utf8 (dlg, IDC_ADDUID_NAME, &utf8_name);
+ if (!rc || rc < 5) {
+ show_balloon_msg (GetDlgItem (dlg, IDC_ADDUID_NAME),
+ _("Please enter a name (min. 5 chars.)"),
+ IDI_ERROR);
+ free_if_alloc (utf8_name);
+ return FALSE;
+ }
+ if (strchr (utf8_name, '@')) {
+ show_balloon_msg (GetDlgItem (dlg, IDC_ADDUID_NAME),
+ _("Please enter the email address in the email field and not in the name field"),
+ IDI_WARNING);
+ free_if_alloc (utf8_name);
+ return FALSE;
+ }
+
+ if( !GetDlgItemText (dlg, IDC_ADDUID_EMAIL, email, DIM (email) -1)) {
+ show_balloon_msg (GetDlgItem (dlg, IDC_ADDUID_EMAIL),
+ _("Please enter an email address."),IDI_ERROR);
+ free_if_alloc (utf8_name);
+ return FALSE;
+ }
+ if (check_email_address (email)) {
+ show_balloon_msg (GetDlgItem (dlg, IDC_ADDUID_EMAIL),
+ _("Invalid email address."), IDI_ERROR);
+ free_if_alloc (utf8_name);
+ return FALSE;
+ }
+
+ rc = GetDlgItemText_utf8 (dlg, IDC_ADDUID_COMMENT, &utf8_comment);
+ {
+ GpgKeyEdit ke;
+ passphrase_cb_s pcb;
+
+ set_gpg_auto_passphrase_cb (&pcb, _("Add Revoker"));
+
+ ke.setPassphraseCallback (passphrase_cb, (void*)&pcb);
+ ke.setKeyID (ctx->keyid);
+ err = ke.addUserid (utf8_name, utf8_comment, email);
+
+ release_gpg_passphrase_cb (&pcb);
+ }
+ if (err)
+ msg_box (dlg, gpgme_strerror (err), _("UserID"), MB_ERR);
+ else {
+ msg_box (dlg, _("user ID successfully added."), _("GnuPG Status"), MB_OK);
+ ctx->finished = 1;
+ /* The caller releases this items later. */
+ keygen->name = utf8_name;
+ keygen->comment = utf8_comment;
+ keygen->email = m_strdup (email);
+ }
+ EndDialog (dlg, TRUE);
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog (dlg, FALSE);
+ return FALSE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+/* Initalize a combo box with default key sizes. */
+static void
+init_keysize_box (HWND dlg, int ctlid)
+{
+ /* Array with standard key-length in bits. */
+ const char *sizelist[] = {
+ "2048", "3072", "4096", NULL
+ };
+
+ for (int i=0; sizelist[i] != NULL; i++)
+ SendDlgItemMessage (dlg, ctlid, CB_ADDSTRING, 0,
+ (LPARAM)(char*)sizelist[i]);
+ SendDlgItemMessage (dlg, ctlid, CB_SETCURSEL, (WPARAM)0, 0);
+}
+
+
+static int
+get_keysize_from_box (HWND dlg, int ctlid)
+{
+ int pos;
+ char buf[32];
+
+ pos = SendDlgItemMessage (dlg, ctlid, CB_GETCURSEL, 0, 0);
+ if (pos == CB_ERR)
+ return -1;
+ SendDlgItemMessage (dlg, ctlid, CB_GETLBTEXT, pos, (LPARAM)(char*)buf);
+ return atoi (buf);
+}
+
+
+/* Create a time_t from a system time @st. */
+time_t
+w32_mktime (SYSTEMTIME *st)
+{
+ struct tm tm;
+
+ memset (&tm, 0, sizeof (tm));
+ tm.tm_year = st->wYear-1900;
+ tm.tm_mday = st->wDay;
+ tm.tm_mon = st->wMonth-1;
+ return mktime (&tm);
+}
+
+
+/* Dialog procedure for adding a new secondary key. */
+BOOL CALLBACK
+keyedit_addsubkey_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ static keyedit_cb_t ctx;
+ keygen_cb_t keygen;
+ gpgme_error_t err;
+ SYSTEMTIME st;
+ HWND hwnd;
+ int index, size, valid;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ ctx = (keyedit_cb_t)lparam;
+ if (!ctx)
+ BUG (NULL);
+ SetWindowText (dlg, _("Add Subkey"));
+ SetDlgItemText (dlg, IDC_ADDSUBKEY_INFALGO, _("Key type:"));
+ SetDlgItemText (dlg, IDC_ADDSUBKEY_INFSIZE, _("Size in bits:"));
+ SetDlgItemText (dlg, IDC_ADDSUBKEY_INFVALID, _("Key expiration:"));
+ SetDlgItemText (dlg, IDC_ADDSUBKEY_EXPIRE, _("&Never"));
+ SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
+
+ hwnd = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);
+ listbox_add_string (hwnd, _("DSA (sign only)"));
+ listbox_add_string (hwnd, _("ElGamal (encrypt only)"));
+ listbox_add_string (hwnd, _("RSA (sign only)"));
+ listbox_add_string (hwnd, _("RSA (encrypt only)"));
+ CheckDlgButton (dlg, IDC_ADDSUBKEY_EXPIRE, BST_CHECKED);
+ EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);
+ EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_SIZE), FALSE);
+ init_keysize_box (dlg, IDC_ADDSUBKEY_SIZE);
+ SetForegroundWindow (dlg);
+ center_window (dlg, ctx->parent);
+ return FALSE;
+
+ case WM_DESTROY:
+ balloon_msg_disable ();
+ break;
+
+ case WM_COMMAND:
+ if (HIWORD (wparam) == BN_CLICKED &&
+ LOWORD (wparam) == IDC_ADDSUBKEY_EXPIRE) {
+ if (IsDlgButtonChecked (dlg, IDC_ADDSUBKEY_EXPIRE))
+ EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), FALSE);
+ else
+ EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE), TRUE);
+ }
+ if (HIWORD (wparam) == LBN_SELCHANGE &&
+ LOWORD (wparam) == IDC_ADDSUBKEY_ALGO) {
+ /* If DSA is selected, we disable the selection box since it
+ is hardocded to 2048-bit. */
+ index = SendMessage ((HWND)lparam, LB_GETCURSEL, 0, 0);
+ EnableWindow (GetDlgItem (dlg, IDC_ADDSUBKEY_SIZE),
+ index != 0? TRUE : FALSE);
+ }
+
+ switch (LOWORD (wparam)) {
+ case IDOK:
+ keygen = (keygen_cb_t)ctx->opaque;
+ if (!keygen)
+ BUG (NULL);
+ hwnd = GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO);
+ int map[4];
+ /* this is for GPG 1.4.9 */
+ map[0] = 2;
+ map[1] = 4;
+ map[2] = 5;
+ map[3] = 6;
+ /* >1.4.10 changed the menu IDs. */
+ if (gpgver[0] == 1 && gpgver[1] >= 4 && gpgver[2] > 9) {
+ map[0] = 3;
+ map[1] = 5;
+ map[2] = 4;
+ map[3] = 6;
+ }
+
+ /* Map combo box numbers to GPG answers. */
+ switch (listbox_get_cursel (hwnd)) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ break;
+ default:
+ show_balloon_msg (GetDlgItem (dlg, IDC_ADDSUBKEY_ALGO),
+ _("Please select one entry."), IDI_ERROR);
+ return FALSE;
+ }
+ index = map[listbox_get_cursel (hwnd)];
+ size = get_keysize_from_box (dlg, IDC_ADDSUBKEY_SIZE);
+ if (index == 2) /* DSA */
+ size = 2048;
+
+ hwnd = GetDlgItem (dlg, IDC_ADDSUBKEY_EXPDATE);
+ DateTime_GetSystemtime (hwnd, &st);
+ valid = w32_mktime (&st) - time (NULL);
+ valid /= 86400;
+
+ keygen->bits = size;
+ switch (index) {
+ case 2: keygen->algo = GPGME_PK_DSA; break;
+ case 4: keygen->algo = GPGME_PK_ELG_E; break;
+ case 5: keygen->algo = GPGME_PK_RSA_S; break;
+ case 6: keygen->algo = GPGME_PK_RSA_E; break;
+ }
+ if (valid > 0)
+ keygen->expire = time (NULL) + valid*24*60*60;
+
+ {
+ GpgKeyEdit ke;
+ passphrase_cb_s pcb;
+
+ set_gpg_auto_passphrase_cb (&pcb, _("Add Revoker"));
+
+ ke.setPassphraseCallback (passphrase_cb, (void*)&pcb);
+ ke.setKeyID (ctx->keyid);
+ ke.setCallback (keygen_cb, NULL);
+ keygen_cb_dlg_create ();
+ err = ke.addSubkey ((gpgme_pubkey_algo_t)index, size, valid);
+
+ release_gpg_passphrase_cb (&pcb);
+ }
+ keygen->fpr = get_subkey_keyid (ctx->keyid);
+ keygen_cb_dlg_destroy (1);
+ if (err)
+ msg_box (dlg, gpgme_strerror (err), _("Add Subkey"), MB_ERR);
+ else {
+ msg_box (dlg, _("Subkey successfully added."),
+ _("GnuPG Status"), MB_OK);
+ ctx->finished = 1;
+ }
+ EndDialog (dlg, TRUE);
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog (dlg, FALSE);
+ return FALSE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+BOOL
+keyedit_add_userid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
+{
+ keyedit_cb_s cb;
+ keygen_cb_s keygen;
+
+ if (!k->key_pair) {
+ msg_box (dlg, _("There is no secret key available!"),
+ _("Add user ID"), MB_ERR);
+ return FALSE;
+ }
+
+ memset (&keygen, 0, sizeof (keygen));
+ memset (&cb, 0, sizeof (cb));
+ cb.parent = dlg;
+ cb.opaque = &keygen;
+ cb.keyid = k->keyid;
+ dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDUID,
+ dlg, keyedit_adduid_dlg_proc,
+ (LPARAM)&cb, _("Add user ID"),
+ IDS_WINPT_KEYEDIT_ADDUID);
+ if (lv != NULL && cb.finished)
+ do_add_new_userid (lv, keygen.name, keygen.email, keygen.comment);
+ if (cb.finished)
+ k->update = 1;
+
+ free_if_alloc (keygen.name);
+ free_if_alloc (keygen.email);
+ free_if_alloc (keygen.comment);
+ return TRUE;
+}
+
+
+/* Return the keyID of the last subkey. */
+char*
+get_subkey_keyid (const char *keyid)
+{
+ gpgme_error_t err;
+ gpgme_key_t key;
+ gpgme_ctx_t ctx;
+ gpgme_subkey_t subk;
+ char *kid = NULL;
+
+ err = gpgme_new (&ctx);
+ if (err)
+ return NULL;
+ err = gpgme_get_key (ctx, keyid, &key, 0);
+ gpgme_release (ctx);
+ if (err)
+ return NULL;
+ subk = get_nth_key (key, count_subkeys (key));
+ if (subk != NULL)
+ kid = strdup (subk->keyid);
+ gpgme_key_release (key);
+ return kid;
+}
+
+
+BOOL
+keyedit_add_subkey (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
+{
+ keyedit_cb_s cb;
+ keygen_cb_s keygen;
+
+ if (!k->key_pair) {
+ msg_box (dlg, _("There is no secret key available!"),
+ _("Add Subkey"), MB_ERR);
+ return FALSE;
+ }
+
+ memset (&keygen, 0, sizeof (keygen));
+ memset (&cb, 0, sizeof (cb));
+ cb.keyid = k->keyid;
+ cb.opaque = &keygen;
+ dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_ADDSUBKEY,
+ dlg, keyedit_addsubkey_dlg_proc,
+ (LPARAM)&cb, _("Add Subkey"),
+ IDS_WINPT_KEYEDIT_ADDSUBKEY);
+ if (lv != NULL && cb.finished)
+ do_add_new_subkey (lv, &keygen, 0);
+ if (cb.finished)
+ k->update = 1;
+
+ safe_free (keygen.fpr);
+ return cb.finished? TRUE: FALSE;
+}
+
+
+/* Set the preferred keyserver of the given key @k. */
+BOOL
+keyedit_set_pref_keyserver (winpt_key_t k, HWND dlg)
+{
+ GpgKeyEdit ke;
+ gpgme_error_t err;
+ struct URL_ctx_s *url;
+ char *pass = NULL;
+
+ url = (struct URL_ctx_s *)get_keyserver_URL_dlg (dlg);
+ if (url == NULL || url->cancel == 1) {
+ delete url;
+ return FALSE;
+ }
+
+ pass = request_key_passphrase (k->ctx, _("Key Edit"), &url->cancel);
+ if (url->cancel) {
+ delete url;
+ return FALSE;
+ }
+
+ ke.setKeyID (k->keyid);
+ if (k->is_protected)
+ ke.setPassphrase (pass);
+ else
+ ke.setNoPassphrase (true);
+ err = ke.setPreferredKeyserver (-1, url->url);
+ if (!err)
+ msg_box (dlg, _("Preferred keyserver successfully set."),
+ _("Key Edit"), MB_OK);
+ else
+ msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);
+
+ keyserver_set_default (url->url, 0);
+ sfree_if_alloc (pass);
+ delete url;
+ return err == 0? 0 : WPTERR_GENERAL;
+}
+
+
+/* Add a photo-ID to the key specified in @k. @dlg is the handle of
+ the calling dialog. */
+BOOL
+keyedit_add_photo (winpt_key_t k, HWND dlg)
+{
+ keyedit_cb_s cb;
+
+ if (!k->key_pair) {
+ msg_box (dlg, _("There is no secret key available!"),
+ _("Add Photo ID"), MB_ERR);
+ return FALSE;
+ }
+
+ memset (&cb, 0, sizeof (cb));
+ cb.parent = dlg;
+ cb.keyid = k->keyid;
+ DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDPHOTO, dlg,
+ keyedit_addphoto_dlg_proc, (LPARAM)&cb);
+
+ if (cb.finished)
+ k->update = 1;
+ return TRUE;
+}
+
+
+BOOL
+keyedit_add_revoker (winpt_key_t k, HWND dlg)
+{
+ keyedit_cb_s cb;
+
+ if (!k->key_pair) {
+ msg_box (dlg, _("There is no secret key available!"), _("Add Revoker"), MB_ERR);
+ return FALSE;
+ }
+
+ memset (&cb, 0, sizeof (cb));
+ cb.parent = dlg;
+ cb.keyid = k->keyid;
+ DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_ADDREV, dlg,
+ keyedit_addrevoker_dlg_proc, (LPARAM)&cb);
+ if (cb.finished)
+ k->update = 1;
+ return TRUE;
+}
+
+
+/* Change ownertrust of the given key @key.
+ Return TRUE if the ownertrust was changed. */
+BOOL
+keyedit_change_ownertrust (winpt_key_t key, HWND dlg)
+{
+ int rc;
+
+ rc = dialog_box_param (glob_hinst,
+ (LPCSTR)IDD_WINPT_KEYEDIT_OWNERTRUST,
+ dlg, keyedit_ownertrust_dlg_proc,
+ (LPARAM)key, _("Change Ownertrust"),
+ IDS_WINPT_KEYEDIT_OWNERTRUST);
+ if (rc == TRUE) {
+ msg_box (dlg, _("Key status changed."), _("Key Edit"), MB_OK);
+ key->update = 1;
+ }
+ return rc;
+}
+
+
+/* Check if the given key is supposed to have IDEA
+ for secret key protection. */
+static int
+is_idea_protect_algo (const char *keyid)
+{
+ winpt_key_s k;
+ const unsigned char *sym_prefs;
+ size_t n;
+
+ memset (&k, 0, sizeof (k));
+ if (winpt_get_pubkey (keyid, &k))
+ BUG (NULL);
+ if (!k.is_v3)
+ return 0;
+ sym_prefs = k.ext->sym_prefs;
+ /* Assume that only v3 keys have no symmetric cipher
+ preferences and thus IDEA is explicit. */
+ if (!sym_prefs)
+ return 1;
+ for (n = 0; sym_prefs[n]; n++)
+ ;
+ if ((n == 0 || n == 1) && *sym_prefs == 0x01)
+ return 1;
+ return 0;
+}
+
+
+BOOL
+keyedit_change_passwd (winpt_key_t k, HWND dlg)
+{
+ gpgme_error_t err;
+ GpgKeyEdit ke;
+ char *old_pass = NULL;
+ char *new_pass = NULL;
+ int cancel = 0;
+
+ if (!k->key_pair) {
+ msg_box (dlg, _("There is no secret key available!"),
+ _("Key Edit"), MB_ERR);
+ return FALSE;
+ }
+
+ if (!idea_available && is_idea_protect_algo (k->keyid)) {
+ msg_box (dlg, _("Cannot change passphrase because the key\n"
+ "is protected with the IDEA encryption algorithm."),
+ _("Key Edit"), MB_ERR);
+ return FALSE;
+ }
+
+ if (k->is_protected) {
+ old_pass = request_passphrase (_("Current (old) Passphrase"),
+ PASSDLG_INIT, &cancel);
+ if (cancel)
+ return FALSE;
+ }
+ new_pass = request_passphrase2 (_("New Passphrase" ),
+ PASSDLG_INIT|PASSDLG_WARN_UTF8, &cancel);
+ if (cancel) {
+ sfree_if_alloc (old_pass);
+ return FALSE;
+ }
+
+ if (strlen (new_pass) == 0) {
+ cancel = msg_box (dlg, _("Are you sure that you really don't want a passphrase?\n"
+ "This is propably a bad idea, continue?"),
+ _("Key Edit"), MB_WARN_ASK);
+ if (cancel != IDYES) {
+ sfree_if_alloc (old_pass);
+ sfree_if_alloc (new_pass);
+ return FALSE;
+ }
+ }
+
+ ke.setKeyID (k->keyid);
+ ke.setPassphrase (k->is_protected? old_pass : NULL);
+ if (!k->is_protected)
+ ke.setNoPassphrase (true);
+ err = ke.changePassphrase (new_pass, 1);
+ if (err)
+ msg_box (dlg, gpgme_strerror (err), _("Change Password"), MB_ERR);
+ else
+ msg_box (dlg, _("Passphrase successfully changed."), _("GnuPG Status"), MB_OK);
+ sfree_if_alloc (old_pass);
+ sfree_if_alloc (new_pass);
+
+ return TRUE;
+}
+
+
+/* Initialize sub key list from key @k and return
+ the new listview control. */
+listview_ctrl_t
+subkey_list_init (HWND dlg, winpt_key_t k)
+{
+ LV_ITEM lvi;
+ gpgme_subkey_t sub;
+ struct listview_column_s cols[] = {
+ {0, 80, (char *)_("Description")},
+ {1, 78, (char *)_("Key ID")},
+ {2, 66, (char *)_("Creation")},
+ {3, 66, (char *)_("Expires")},
+ {4, 64, (char *)_("Status")},
+ {5, 16, (char *) "C"/*ertify*/},
+ {6, 16, (char *) "S"/*ign*/},
+ {7, 16, (char *) "E"/*ncrypt*/},
+ {8, 16, (char *) "A"/*uth*/},
+ {0, 0, 0}
+ };
+ listview_ctrl_t lv;
+ char buf[256], tmp[128];
+ const char *t;
+ int nkeys = 0, i;
+
+ nkeys = count_subkeys (k->ctx);
+ if (!nkeys)
+ BUG (NULL); /* should never happen. */
+
+ listview_new (&lv, GetDlgItem (dlg, IDC_KEYEDIT_KEYLIST));
+ for (i = 0; cols[i].fieldname != NULL; i++)
+ listview_add_column (lv, &cols[i]);
+
+ for (i = 0, sub = k->ctx->subkeys; i < nkeys; i++, sub = sub->next) {
+ listview_add_item (lv, "");
+ listview_add_sub_item (lv, 0, 1, "");
+ memset (&lvi, 0, sizeof (lvi));
+ lvi.mask = LVIF_PARAM;
+ lvi.lParam = (LPARAM)sub;
+ if (ListView_SetItem (lv->ctrl, &lvi) == FALSE)
+ BUG (NULL);
+ }
+
+ listview_set_ext_style (lv);
+ for (i = 0, sub = k->ctx->subkeys; i < nkeys; i++, sub = sub->next) {
+ _snprintf (buf, DIM (buf)-1, "%d-bit %s", sub->length,
+ get_key_pubalgo (sub->pubkey_algo));
+ listview_add_sub_item (lv, i, SUBK_COL_DESC, buf);
+ t = sub->keyid;
+ assert (t != NULL);
+ _snprintf (tmp, DIM (tmp)-1, "0x%s", t+8);
+ listview_add_sub_item (lv, i, SUBK_COL_KEYID, tmp);
+
+ t = get_key_created (sub->timestamp);
+ if (!t)
+ t = "????" "-??" "-??";
+ listview_add_sub_item (lv, i, SUBK_COL_CREATION, t);
+
+ if (sub->expires) {
+ t = get_key_created (sub->expires);
+ listview_add_sub_item (lv, i, SUBK_COL_EXPIRES, t);
+ }
+ else
+ listview_add_sub_item (lv, i, SUBK_COL_EXPIRES, _("Never"));
+ if (sub->expired)
+ t = _("Expired");
+ else if (sub->revoked)
+ t = _("Revoked");
+ else
+ t = _("OK");
+ listview_add_sub_item (lv, i, SUBK_COL_STATUS, t);
+
+ if (sub->can_certify) t = "*"; else t = "";
+ listview_add_sub_item (lv, i, SUBK_COL_C_FLAG, t);
+ if (sub->can_sign) t = "*"; else t = "";
+ listview_add_sub_item (lv, i, SUBK_COL_S_FLAG, t);
+ if (sub->can_encrypt) t = "*"; else t = "";
+ listview_add_sub_item (lv, i, SUBK_COL_E_FLAG, t);
+ if (sub->can_authenticate) t = "*"; else t = "";
+ listview_add_sub_item (lv, i, SUBK_COL_A_FLAG, t);
+ }
+ return lv;
+}
+
+
+static listview_ctrl_t
+userid_list_init (HWND dlg, winpt_key_t k)
+{
+ listview_ctrl_t lv = NULL;
+ gpgme_key_sig_t ks;
+ struct native_uid_s *u;
+ int nuids = 0, j, u_attr;
+ struct listview_column_s cols[] = {
+ {0, 72, (char *)_("Validity")},
+ {1, 150, (char *)_("Name")},
+ {2, 110, (char *)_("Email")},
+ {3, 76, (char *)_("Creation")},
+ {0, 0, 0}
+ };
+ const char *attr;
+
+ nuids = count_userids (k->ctx);
+ if (!nuids)
+ BUG (NULL); /* should never happen. */
+
+ listview_new (&lv, GetDlgItem (dlg, IDC_KEYEDIT_UIDLIST));
+ for (j = 0; cols[j].fieldname != NULL; j++)
+ listview_add_column (lv, &cols[j]);
+
+ for (j = 0; j < nuids; j++) {
+ listview_add_item (lv, " ");
+ listview_add_sub_item (lv, 0, 1, " " );
+ }
+
+ listview_set_ext_style (lv);
+ for (j = 0, u=k->ext->uids; j < nuids; u=u->next, j++) {
+ if (u->revoked)
+ attr = _("Revoked");
+ else {
+ u_attr = (int)u->validity;
+ attr = get_key_trust2 (NULL, u_attr, 0, 0);
+ }
+ listview_add_sub_item (lv, j, UID_COL_VALID, (char *)attr);
+ /* XXX: add comment if available */
+ listview_add_sub_item (lv, j, UID_COL_NAME,
+ u->name? u->name : _("Invalid user ID"));
+ if (u->email)
+ listview_add_sub_item (lv, j, UID_COL_EMAIL, u->email);
+
+ ks = get_selfsig (u->signatures, k->keyid, 1);
+ if (ks)
+ listview_add_sub_item (lv, j, UID_COL_CREATION,
+ get_key_created (ks->timestamp));
+ }
+ if (!k->key_pair) {
+ CheckDlgButton (dlg, IDC_KEYUID_ADD, BST_INDETERMINATE);
+ CheckDlgButton (dlg, IDC_KEYUID_REVOKE, BST_INDETERMINATE);
+ }
+ return lv;
+}
+
+
+static void
+do_init_cmdlist (HWND dlg, int is_keypair)
+{
+ const char *s;
+ int i;
+
+ for (i = 0; (s=cmdlist[i].name); i++) {
+ if (is_keypair)
+ SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_ADDSTRING, 0,
+ (LPARAM)(char *)s);
+ else if (!cmdlist[i].need_pair)
+ SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_ADDSTRING, 0,
+ (LPARAM)(char *)s);
+ }
+ SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_SETCURSEL, 0, 0);
+}
+
+
+/* Return 1 if the requested command is RFC2440. */
+static int
+is_cmd_openpgp (int cmdid)
+{
+ switch (cmdid) {
+ case CMD_ADDKEY:
+ case CMD_ADDPHOTO:
+ case CMD_ADDREVOKER:
+ case CMD_SETPREF:
+ return 1;
+ }
+ return 0;
+}
+
+
+/* Display a message box with a short description of the commands. */
+static void
+do_show_help (HWND dlg)
+{
+ const char *help;
+
+ help =
+ _(
+ "ADDUID\t\t\tadd a user ID\r\n"
+ "ADDPHOTO\t\t\tadd a photo ID\r\n"
+ "DELUID\t\t\tdelete a user ID\r\n"
+ "ADDKEY\t\t\tadd a secondary key\r\n"
+ "DELKEY\t\t\tdelete a secondary key\r\n"
+ "ADDREVOKER\t\t\tadd a revocation key\r\n"
+ "EXPIRE\t\t\tchange the expire date\r\n"
+ "SHOWPREF\t\t\tlist preferences (verbose)\r\n"
+ "PASSWD\t\t\tchange the passphrase\r\n"
+ "PRIMARY\t\t\tflag user ID as primary\r\n"
+ "TRUST\t\t\tchange the ownertrust\r\n"
+ "REVUID\t\t\trevoke a user ID\r\n"
+ "REVKEY\t\t\trevoke a secondary key\r\n"
+ "DISABLE\t\t\tdisable a key\r\n"
+ "ENABLE\t\t\tenable a key\r\n"
+ "SIGN\t\t\tsign a user-id (exportable)\r\n"
+ "LSIGN\t\t\tsign a user-id (non-exportable)\r\n"
+ "CLEAN\t\t\tremove unusable signatures from key\r\n"
+ "MINIMIZE\t\t\tremove all signatures from key\r\n"
+ );
+ msg_box (dlg, help, _("Key Edit Help"), MB_OK);
+}
+
+
+static gpgme_subkey_t
+get_subkey_bypos (const char *keyid, int idx)
+{
+ gpgme_key_t key;
+
+ if (get_pubkey (keyid, &key))
+ return NULL;
+ return get_nth_key (key, idx);
+}
+
+
+
+static int
+do_editkey_delkey (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
+{
+ gpgme_error_t err;
+ gpgme_subkey_t subk;
+ GpgKeyEdit ke;
+ int pos, id;
+ const char *warn;
+ char tmp[64];
+
+ if (!k->key_pair)
+ return FALSE;
+
+ if (listview_count_items (lv, 0) == 1) {
+ show_balloon_msg (lv->ctrl, _("Primary key can not be deleted!"),
+ IDI_ERROR);
+ return FALSE;
+ }
+ pos = listview_get_curr_pos (lv);
+ if (pos == -1) {
+ show_balloon_msg (lv->ctrl, _("Please select a key."), IDI_ERROR);
+ return FALSE;
+ }
+ if (pos == 0) {
+ show_balloon_msg (lv->ctrl, _("Primary key can not be deleted!"),
+ IDI_ERROR);
+ return FALSE;
+ }
+
+ listview_get_item_text (lv, pos, 0, tmp, DIM (tmp) -1);
+ subk = get_subkey_bypos (k->keyid, pos);
+ /* Issue different warning for the different key capabilities. */
+ if (subk->can_encrypt)
+ warn = _("Anything encrypted to the selected subkey cannot be\n"
+ "decrypted any longer.");
+ else if (subk->can_sign || subk->can_certify)
+ warn = _("Anything signed by the selected subkey cannot be\n"
+ "verified any longer.");
+ else
+ warn = ""; /* just get rid of the warning. */
+
+ id = log_box (_("Key Edit"), MB_YESNO|MB_ICONWARNING,
+ _("\"Subkey %s, ID 0x%s.\"\n\n%s\n\n"
+ "Do you really want to DELETE this subkey?"),
+ tmp, subk->keyid+8, warn);
+ if (id == IDNO)
+ return FALSE;
+
+ ke.setKeyID (k->keyid);
+ err = ke.delKey (pos);
+ if (err)
+ msg_box (dlg, gpgme_strerror (err), _("Delete Subkey"), MB_ERR);
+ else {
+ listview_del_item (lv, pos);
+ k->update = 1;
+ status_box (dlg, _("Subkey successfully deleted."), _("GnuPG Status"));
+ }
+ return err? FALSE : TRUE;
+}
+
+
+/* Set the expiration date for the selected key in list view @lv.
+ Return value: TRUE on success. */
+static int
+do_editkey_expire (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
+{
+ gpgme_error_t err;
+ GpgKeyEdit ke;
+ date_s udd = {0};
+ char buf[256], * pass = NULL;
+ time_t exp;
+ int pos, cancel = 0;
+
+ if (!k->key_pair) {
+ msg_box (dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR);
+ return FALSE;
+ }
+ pos = listview_get_curr_pos (lv);
+ if (pos == -1) {
+ msg_box (dlg, _("Please select a key."), _("Key Edit"), MB_ERR);
+ return FALSE;
+ }
+
+ /* If a key already expired, it is possible the user wants to
+ set a new expiration date.. */
+ listview_get_item_text (lv, pos, SUBK_COL_STATUS, buf, DIM (buf)-1);
+ if (!strcmp (buf, _("Expired"))) {
+ cancel = msg_box (dlg, _("Key already expired.\n\n"
+ "Do you want to change the expiration date?"),
+ _("Key Edit"), MB_QUEST_ASK);
+ if (cancel == IDNO)
+ return FALSE;
+ cancel = 0;
+ }
+
+ memset (&udd, 0, sizeof (udd));
+ udd.text = _("Key Expiration Date");
+ dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_DATE, dlg,
+ date_dlg_proc, (LPARAM)&udd,
+ _("Key Expiration Date"), IDS_WINPT_DATE);
+ if (udd.cancel == 1)
+ return FALSE;
+ if (!keygen_check_date (&udd.st)) {
+ msg_box (dlg, _("The date you have chosen has already passed."),
+ _("Key Edit"), MB_ERR);
+ return FALSE;
+ }
+ if (k->is_protected) {
+ pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
+ if (cancel)
+ return FALSE;
+ }
+ exp = w32_mktime (&udd.st);
+
+ ke.setKeyID (k->keyid);
+ if (k->is_protected)
+ ke.setPassphrase (pass);
+ else
+ ke.setNoPassphrase (true);
+ err = ke.setKeyExpireDate (pos, exp, false);
+ if (err)
+ msg_box (dlg, gpgme_strerror (err), _("Expire Subkey"), MB_ERR);
+ else {
+ _snprintf (buf, DIM (buf)-1, "%s", get_key_created (exp));
+ listview_add_sub_item (lv, pos, SUBK_COL_EXPIRES, buf);
+ k->update = 1;
+ msg_box (dlg, _("Subkey expire date successfully set."),
+ _("GnuPG Status"), MB_OK);
+ }
+ sfree_if_alloc (pass);
+ return TRUE;
+}
+
+
+/* Revoke the selected key in the list view @lv. @k contains
+ control information about the global key.
+ Return value: TRUE on success. */
+static int
+do_editkey_revoke (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
+{
+ gpgme_error_t err;
+ GpgKeyEdit ke;
+ char buf[256];
+ char *pass = NULL;
+ int j, cancel = 0;
+
+ if (!k->key_pair) {
+ msg_box (dlg, _("There is no secret key available!"), _("Key Edit"), MB_ERR);
+ return FALSE;
+ }
+
+ if ((j = listview_get_curr_pos (lv)) == -1) {
+ msg_box( dlg, _("Please select a key."), _("Key Edit"), MB_ERR );
+ return FALSE;
+ }
+ else if (listview_count_items (lv, 0) == 1) {
+ msg_box( dlg, _("No subkeys were found, if you want to revoke the\n"
+ "whole key, please use the Key Manager command directly.\n\n"
+ "This command is only available to revoke single subkeys"),
+ _("Key Edit"), MB_INFO );
+ return FALSE;
+ }
+
+ listview_get_item_text (lv, j, SUBK_COL_STATUS, buf, DIM (buf)-1);
+ if (!strcmp (buf, _("Revoked"))) {
+ msg_box (dlg, _("Key already revoked."), _("Key Edit"), MB_ERR);
+ return FALSE;
+ }
+
+ if (k->is_protected) {
+ pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
+ if (cancel)
+ return FALSE;
+ }
+
+ ke.setKeyID (k->keyid);
+ if (k->is_protected)
+ ke.setPassphrase (pass);
+ else
+ ke.setNoPassphrase (true);
+ err = ke.revokeSubkey (j, 0, NULL);
+ if (err)
+ msg_box( dlg, gpgme_strerror (err), _("Revoke Subkey"), MB_ERR);
+ else {
+ listview_add_sub_item (lv, j, SUBK_COL_STATUS, _("Revoked"));
+ k->update = 1;
+ msg_box( dlg, _("Subkey successfully revoked."), _("GnuPG Status"), MB_OK );
+ }
+ sfree_if_alloc (pass);
+ return TRUE;
+}
+
+
+/* Revoked the selected userid in list view @lv.
+ Return value: TRUE on success. */
+int
+do_editkey_revuid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
+{
+ gpgme_error_t err;
+ GpgKeyEdit ke;
+ char buf[128], email[128];
+ char inf[512];
+ char *pass = NULL;
+ int cancel = 0, id = 0, j;
+
+ if (!k->key_pair) {
+ msg_box (dlg, _("There is no secret key available!"),
+ _("Revoke user ID"), MB_ERR);
+ return FALSE;
+ }
+
+ if (listview_count_items (lv, 0) == 1) {
+ msg_box (dlg, _("Key has only one user ID."), _("Key Edit"), MB_ERR);
+ return FALSE;
+ }
+
+ if( (j = listview_get_curr_pos( lv )) == -1 ) {
+ msg_box( dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR );
+ return FALSE;
+ }
+
+ listview_get_item_text( lv, j, UID_COL_VALID, buf, DIM (buf) - 1);
+ if (strstr (buf, _("Revoked"))) {
+ msg_box (dlg, _("This user ID has been already revoked."),
+ _("Key Edit"), MB_INFO);
+ return FALSE;
+ }
+
+ listview_get_item_text (lv, j, UID_COL_NAME, buf, DIM (buf) -1);
+ _snprintf (inf, DIM (inf) -1, _("user ID \"%s\".\n\n"
+ "Do you really want to revoke this user ID?"), buf);
+ if (msg_box (dlg, inf, _("Key Edit"), MB_WARN_ASK) == IDNO)
+ return FALSE;
+ if (k->is_protected) {
+ pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
+ if (cancel)
+ return FALSE;
+ }
+ listview_get_item_text (lv, j, UID_COL_EMAIL, email, DIM (email)-1);
+ listview_get_item_text (lv, j, UID_COL_NAME, buf, DIM (buf)-1);
+ id = do_find_userid (k->keyid, email, buf, NULL);
+ if (id == -1)
+ BUG (NULL);
+
+ ke.setKeyID (k->keyid);
+ if (k->is_protected)
+ ke.setPassphrase (pass);
+ else
+ ke.setNoPassphrase (true);
+ err = ke.revokeUserid (id);
+ if (err)
+ msg_box (dlg, gpgme_strerror (err), _("Revoke User ID"), MB_ERR);
+ else {
+ listview_add_sub_item (lv, j, 0, _("Revoked"));
+ k->update = 1;
+ status_box (dlg, _("User ID successfully revoked"), _("GnuPG Status"));
+ }
+ sfree_if_alloc (pass);
+ return err? FALSE : TRUE;
+}
+
+
+static int
+do_editkey_primary (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
+{
+ gpgme_error_t err;
+ GpgKeyEdit ke;
+ int j, id, cancel=0;
+ char valid[32];
+ char buf[256], *pass = NULL;
+
+ if (listview_count_items (lv, 0) == 1)
+ return TRUE;
+ if ((j = listview_get_curr_pos (lv)) == -1) {
+ msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
+ return FALSE;
+ }
+ listview_get_item_text (lv, j, UID_COL_VALID, valid, DIM (valid)-1);
+ if (!strcmp (valid, _("Revoked")))
+ return FALSE;
+ listview_get_item_text (lv, j, UID_COL_EMAIL, buf, DIM (buf)-1);
+ id = do_find_userid (k->keyid, buf, NULL, NULL);
+ if (id == -1)
+ BUG (NULL);
+ if (k->is_protected) {
+ pass = request_key_passphrase (k->ctx, _("Key Edit"), &cancel);
+ if (cancel)
+ return FALSE;
+ }
+
+ ke.setKeyID (k->keyid);
+ if (k->is_protected)
+ ke.setPassphrase (pass);
+ else
+ ke.setNoPassphrase (true);
+ err = ke.setPrimaryUserid (id);
+ if (err)
+ msg_box (dlg, gpgme_strerror (err), _("Primary"), MB_ERR);
+ else {
+ k->update = 1;
+ status_box (dlg, _("User ID successfully flagged"), _("GnuPG Status"));
+ }
+
+ sfree_if_alloc (pass);
+ return err? FALSE : TRUE;
+}
+
+
+
+#define CIPHER 11
+#define HASH 11
+#define COMPR 4
+
+static int
+parse_preflist (HWND dlg, const char *list)
+{
+ char buf[128] = {0};
+ char *p, *pbuf = buf;
+ const char *ciphers[CIPHER] = {"", "IDEA", "3DES",
+ "CAST5", "BLOWFISH", "", "",
+ "AES", "AES192", "AES256", "TWOFISH"};
+ const char *hash[HASH] = {"", "MD5", "SHA1", "RMD160", "",
+ "", "", "", "SHA256", "SHA384", "SHA512"};
+ const char *compress[COMPR] = {"", "ZIP", "ZLIB", "BZIP2"};
+ int n=0;
+
+ strncpy (buf, list, 127);
+ p = strtok (pbuf, " ");
+ while (p != NULL) {
+ int algid = atol (p+1);
+ n++;
+ switch (*p) {
+ case 'S':
+ SendDlgItemMessage (dlg, IDC_SHOWPREF_CIPHERS, LB_ADDSTRING, 0,
+ (LPARAM)(const char*)ciphers[algid % CIPHER]);
+ break;
+
+ case 'H':
+ SendDlgItemMessage (dlg, IDC_SHOWPREF_HASH, LB_ADDSTRING, 0,
+ (LPARAM)(const char*)hash[algid % HASH]);
+ break;
+
+ case 'Z':
+ SendDlgItemMessage (dlg, IDC_SHOWPREF_ZIP, LB_ADDSTRING, 0,
+ (LPARAM)(const char*)compress[algid % COMPR]);
+ break;
+
+ default:
+ n--;
+ }
+ p = strtok (NULL, " ");
+ }
+ return n;
+}
+
+
+/* Dialog box procedure to show the key preferences. */
+BOOL CALLBACK
+showpref_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ static keyedit_cb_t cb = NULL;
+ gpg_uid_info_t inf=NULL, u;
+ gpgme_key_t key;
+ char buf[128];
+ int pos;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ cb = (keyedit_cb_t)lparam;
+ if (!cb)
+ BUG (NULL);
+ key = (gpgme_key_t)cb->opaque;
+ listview_get_item_text (cb->lv, cb->lv_pos,
+ UID_COL_EMAIL, buf, DIM (buf)-1);
+ pos = do_find_userid (cb->keyid, buf, NULL, &inf);
+ if (pos < 0 || !inf) {
+ gpg_uid_info_release (inf);
+ EndDialog (dlg, FALSE);
+ break;
+ }
+ for (u=inf; u; u = u->next) {
+ if (u->index == pos && u->prefs && *u->prefs) {
+ _snprintf (buf, DIM (buf)-1, "%s", u->name);
+ SetDlgItemText (dlg, IDC_SHOWPREF_INFO, buf);
+ if (parse_preflist (dlg, u->prefs) <= 0)
+ pos = -1;
+ if (u->flags.mdc)
+ CheckDlgButton (dlg, IDC_SHOWPREF_MDC, BST_CHECKED);
+ break;
+ }
+ }
+ gpg_uid_info_release (inf);
+ if (pos == -1) {
+ msg_box (dlg, _("No preferences available."), _("Key Edit"), MB_ERR);
+ EndDialog (dlg, FALSE);
+ break;
+ }
+ SetDlgItemText (dlg, IDC_SHOWPREF_MDC, _("MDC feature"));
+ SetDlgItemText (dlg, IDC_SHOWPREF_PREFINF, _("Preferences"));
+ SetDlgItemText (dlg, IDC_SHOWPREF_UIDHINT, _("user ID:"));
+ SetWindowText (dlg, _("Key Preferences"));
+ SetForegroundWindow (dlg);
+ center_window (dlg, cb->parent);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD (wparam)) {
+ case IDOK:
+ EndDialog (dlg, TRUE);
+ break;
+
+ case IDCANCEL:
+ EndDialog (dlg, FALSE);
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+static int
+do_editkey_showpref (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
+{
+ struct keyedit_cb_s cb;
+ char status[32];
+
+ if (k->is_v3)
+ return TRUE;
+
+ if (listview_get_curr_pos (lv) == -1) {
+ msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
+ return FALSE;
+ }
+ memset (&cb, 0, sizeof (cb));
+ cb.parent = dlg;
+ cb.opaque = k->ctx;
+ cb.keyid = k->keyid;
+ cb.lv = lv;
+ cb.lv_pos = listview_get_curr_pos (lv);
+
+ listview_get_item_text (lv, cb.lv_pos, UID_COL_VALID,
+ status, DIM (status)-1);
+ if (!strcmp (status, _("Revoked")))
+ return TRUE;
+
+ DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYEDIT_SHOWPREF, dlg,
+ showpref_dlg_proc, (LPARAM)&cb);
+ return TRUE;
+}
+
+
+static int
+do_editkey_deluid (winpt_key_t k, HWND dlg, listview_ctrl_t lv)
+{
+ gpgme_error_t err;
+ GpgKeyEdit ke;
+ char email[128], name[128];
+ char inf[384];
+ int pos, id = 0;
+
+ if (!k->key_pair)
+ return FALSE;
+
+ if (listview_count_items (lv, 0) == 1) {
+ msg_box (dlg, _("Primary user ID can not be deleted!"),
+ _("Key Edit"), MB_ERR);
+ return FALSE;
+ }
+ pos = listview_get_curr_pos (lv);
+ if (pos == -1) {
+ msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
+ return FALSE;
+ }
+
+ listview_get_item_text (lv, pos, UID_COL_NAME, name, DIM(name) -1);
+ _snprintf (inf, DIM (inf)-1, _("user ID \"%s\".\n\n"
+ "All signatures on this user ID will be also deleted."
+ "\n\n"
+ "Do you really want to DELETE this user ID?"),
+ name);
+ if (msg_box (dlg, inf, _("Key Edit"), MB_YESNO|MB_ICONWARNING) == IDNO)
+ return FALSE;
+
+ listview_get_item_text (lv, pos, UID_COL_EMAIL, email, DIM (email)-1);
+ listview_get_item_text (lv, pos, UID_COL_NAME, name, DIM (name)-1);
+ id = do_find_userid (k->keyid, email, name, NULL);
+ if (id == -1)
+ BUG (NULL);
+
+ ke.setKeyID (k->keyid);
+ err = ke.delUserid (id);
+ if (err)
+ msg_box (dlg, gpgme_strerror (err), _("Delete User ID"), MB_ERR);
+ else {
+ listview_del_item (lv, pos);
+ k->update = 1;
+ status_box (dlg, _("User ID successfully deleted"), _("GnuPG Status"));
+ }
+ return err? FALSE : TRUE;
+}
+
+
+/* Subclass routine for the subkey listview control to allow shortcuts. */
+static BOOL CALLBACK
+subkey_subclass_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ int virt_key = 0;
+ winpt_key_t key;
+
+ switch (msg) {
+ case WM_KEYUP:
+ virt_key = (int)wparam;
+ key = (winpt_key_t)keyedit_subkey_proc.opaque;
+ if (!key || !key->key_pair)
+ break;
+
+ switch (virt_key) {
+ case VK_DELETE:
+ SendDlgItemMessage (keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,
+ CB_SETCURSEL, CMD_DELKEY, 0);
+ send_cmd_id (keyedit_subkey_proc.dlg, IDOK);
+ break;
+
+ case VK_INSERT:
+ SendDlgItemMessage (keyedit_subkey_proc.dlg, IDC_KEYEDIT_CMD,
+ CB_SETCURSEL, CMD_ADDKEY, 0);
+ send_cmd_id (keyedit_subkey_proc.dlg, IDOK);
+ break;
+ }
+ }
+ return CallWindowProc (keyedit_subkey_proc.old, dlg, msg, wparam, lparam);
+}
+
+
+static BOOL CALLBACK
+uid_subclass_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ int virt_key = 0;
+ winpt_key_t key;
+
+ switch (msg) {
+ case WM_KEYUP:
+ virt_key = (int)wparam;
+ key = (winpt_key_t)keyedit_uid_proc.opaque;
+ if (!key || !key->key_pair)
+ break;
+
+ switch (virt_key) {
+ case VK_DELETE:
+ SendDlgItemMessage (keyedit_uid_proc.dlg, IDC_KEYEDIT_CMD,
+ CB_SETCURSEL, CMD_DELUID, 0);
+ send_cmd_id (keyedit_uid_proc.dlg, IDOK);
+ break;
+
+ case VK_INSERT:
+ SendDlgItemMessage (keyedit_uid_proc.dlg, IDC_KEYEDIT_CMD,
+ CB_SETCURSEL, CMD_ADDUID, 0);
+ send_cmd_id (keyedit_uid_proc.dlg, IDOK);
+ break;
+ }
+ }
+ return CallWindowProc (keyedit_uid_proc.old, dlg, msg, wparam, lparam);
+}
+
+
+/* Enable the key @k when @enable is 1, disable it otherwise. */
+static void
+do_editkey_enable_disable (winpt_key_t k, HWND dlg,
+ listview_ctrl_t lv, int enable)
+{
+ gpgme_error_t err;
+ gpgme_key_t key;
+ GpgKeyEdit ke;
+
+ // FIXME: We had to duplicate the code here since the key manager
+ // code uses the listview to get the pointer to the key!
+ key = k->ctx;
+ ke.setKeyID (key->subkeys->keyid);
+
+ err = enable? ke.enable () : ke.disable ();
+ if (!err) {
+ show_msg (dlg, 1500, _("Key status changed."));
+ k->update = 1;
+ }
+ else
+ msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
+}
+
+
+static void
+do_editkey_minimize (winpt_key_t k, HWND dlg)
+{
+ gpgme_error_t err;
+ GpgKeyEdit ke;
+
+ ke.setKeyID (k->keyid);
+ err = ke.minimizeKey ();
+ if (err)
+ msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);
+ else {
+ msg_box (dlg, _("Finished to compact key."), _("Key Edit"), MB_OK);
+ k->update = 1;
+ }
+}
+
+
+static void
+do_editkey_clean (winpt_key_t k, HWND dlg)
+{
+ gpgme_error_t err;
+ GpgKeyEdit ke;
+
+ ke.setKeyID (k->keyid);
+ err = ke.cleanKey ();
+ if (err)
+ msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);
+ else {
+ msg_box (dlg, _("Finished to compact key."), _("Key Edit"), MB_OK);
+ k->update = 1;
+ }
+}
+
+
+/* Start the dialog to list and display the status of all
+ signatures for this key. */
+static void
+do_editkey_check (winpt_key_t k, HWND dlg)
+{
+ if (!k->ctx)
+ get_pubkey (k->keyid, &k->ctx);
+ if (!k->uid && k->ctx)
+ k->uid = k->ctx->uids->uid;
+ DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYSIG_TREE, dlg,
+ sigtree_dlg_proc, (LPARAM)k);
+}
+
+
+static int
+do_editkey_sign_userid (winpt_key_t k, HWND dlg, listview_ctrl_t lv, int mode)
+{
+ gpgme_error_t err;
+ winpt_key_s signer;
+ GpgKeyEdit ke;
+ char *pass = NULL;
+ char *defkey;
+ char email[64], name[128], valid[32];
+ int uid_index;
+ int cancel = 0;
+
+ uid_index = listview_get_curr_pos (lv);
+ if (uid_index == -1) {
+ msg_box (dlg, _("Please select a user ID."), _("Key Edit"), MB_ERR);
+ return FALSE;
+ }
+ listview_get_item_text (lv, uid_index, UID_COL_VALID, valid, DIM (valid)-1);
+ if (!strcmp (valid, _("Revoked")))
+ return TRUE;
+ if (mode == CMD_SIGN) {
+ cancel = msg_box (dlg, _("Do you really want to make this sig exportable?"),
+ _("Key Edit"), MB_QUEST_ASK);
+ if (cancel == IDNO)
+ return FALSE;
+ }
+ listview_get_item_text (lv, uid_index, UID_COL_EMAIL, email, DIM (email)-1);
+ listview_get_item_text (lv, uid_index, UID_COL_NAME, name, DIM (name)-1);
+ uid_index = do_find_userid (k->keyid, email, name, NULL);
+
+ defkey = get_gnupg_default_key ();
+ memset (&signer, 0, sizeof (signer));
+ if (winpt_get_seckey (defkey, &signer)) {
+ log_debug ("do_editkey_sign_userid: no default secret key.\r\n");
+ free_if_alloc (defkey);
+ return FALSE;
+ }
+ if (signer.is_protected) {
+ pass = request_key_passphrase (signer.ctx, _("Key Edit"), &cancel);
+ if (cancel)
+ return FALSE;
+ }
+ ke.setKeyID (k->keyid);
+ if (signer.is_protected)
+ ke.setPassphrase (pass);
+ else
+ ke.setNoPassphrase (true);
+ ke.setLocalUser (signer.ctx);
+ err = ke.signUserid (uid_index,
+ mode == CMD_SIGN? GPG_EDITKEY_SIGN : GPG_EDITKEY_LSIGN,
+ 0, NULL);
+ if (!err) {
+ msg_box (dlg, _("Key successfully signed."), _("Key Edit"), MB_OK);
+ k->update = 1;
+ }
+ else
+ msg_box (dlg, gpgme_strerror (err), _("Key Edit"), MB_ERR);
+
+ sfree_if_alloc (pass);
+ return !err? TRUE : FALSE;
+}
+
+
+static int
+lookup_cmd (HWND dlg)
+{
+ char buf[64];
+ int i;
+
+ i = SendDlgItemMessage (dlg, IDC_KEYEDIT_CMD, CB_GETCURSEL, 0, 0);
+ if (i == LB_ERR)
+ return LB_ERR;
+ GetDlgItemText (dlg, IDC_KEYEDIT_CMD, buf, DIM (buf)-1);
+ for (i=0; cmdlist[i].name != NULL; i++) {
+ if (!strcmp (buf, cmdlist[i].name))
+ return cmdlist[i].id;
+ }
+ return LB_ERR;
+}
+
+
+
+gpgme_error_t key_get_revokers (winpt_key_t key, int reload,
+ gpg_desig_rev_t *r_rev);
+
+/* Check if the key supports designated revokers and if
+ secret keys exist to generate such a revoke cert. */
+static bool
+check_desig_rev (winpt_key_t key)
+{
+ gpg_desig_rev_t rev, u;
+ struct winpt_key_s sk;
+
+ if (!key->ext->gloflags.has_desig_rev)
+ return false;
+ key_get_revokers (key, 0, &rev);
+ for (u = rev; u; u = u->next) {
+ memset (&sk, 0, sizeof (sk));
+ if (!winpt_get_seckey (u->fpr+32, &sk))
+ return true;
+ }
+ return false;
+}
+
+
+/* Use the gpg --desig-revoker command to create a revocation
+ cert for a key that lists our key as a designated revoker. */
+static void
+gen_desig_revoke_cert (winpt_key_t key, HWND dlg)
+{
+ const char *warn;
+ char *inf, *p;
+ int id;
+
+ inf = km_key_get_info (key, 0);
+ warn = _("Your keys is listed as a designated revoker for the key\n\n"
+ "%s\n\n"
+ "Are you sure you want to create a revocation certificate\n"
+ "which allows you to revoke the key listed above?");
+ p = new char[strlen (inf)+1+strlen (warn)+1];
+ sprintf (p, warn, inf);
+ free_if_alloc (inf);
+
+ id = msg_box (dlg, p, _("Key Edit"), MB_YESNO|MB_ICONWARNING);
+ free_if_alloc (p);
+ if (id == IDNO)
+ return;
+
+ key->internal = 1;
+ DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYREVOKE, dlg,
+ key_revoke_dlg_proc, (LPARAM)key);
+}
+
+
+/* Create tooltip control for the listview header. */
+static HWND
+create_header_tooltip (HWND dlg)
+{
+ TOOLINFO ti;
+ HWND tt;
+
+ tt = CreateWindow (TOOLTIPS_CLASS, (LPSTR) NULL, TTS_ALWAYSTIP|TTS_BALLOON ,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ NULL, (HMENU) NULL, glob_hinst, NULL);
+ if (!tt)
+ BUG (NULL);
+ memset (&ti, 0, sizeof (ti));
+ ti.cbSize = sizeof (TOOLINFO);
+ ti.uFlags = TTF_IDISHWND|TTF_SUBCLASS;
+ ti.hwnd = dlg;
+ ti.uId = (UINT) ListView_GetHeader (GetDlgItem (dlg, IDC_KEYEDIT_KEYLIST));
+ ti.hinst = 0;
+ ti.lpszText = (char*)_("Capabilties: C = Certify, S = Sign, E = Encrypt, A = Authenticate");
+ SendMessage(tt, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
+ return tt;
+}
+
+
+#define TTM_POPUP (WM_USER+34)
+
+/* Dialog box procedure for the edit key dialog. */
+BOOL CALLBACK
+keyedit_main_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ static winpt_key_t k;
+ static listview_ctrl_t lvsub = NULL;
+ static listview_ctrl_t lvuid = NULL;
+ static HWND tt = NULL;
+ int cmd;
+ HWND item;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ k = (winpt_key_t)lparam;
+ if (!k)
+ BUG (NULL);
+ do_init_cmdlist (dlg, k->key_pair);
+ lvsub = subkey_list_init (dlg, k);
+ lvuid = userid_list_init (dlg, k);
+ item = GetDlgItem (dlg, IDC_KEYEDIT_KEYLIST);
+ keyedit_subkey_proc.opaque = (void*)k;
+ keyedit_subkey_proc.dlg = dlg;
+ keyedit_subkey_proc.current = (WNDPROC)subkey_subclass_proc;
+ keyedit_subkey_proc.old = (WNDPROC)GetWindowLong (item, GWL_WNDPROC);
+ if (keyedit_subkey_proc.old) {
+ if (!SetWindowLong (item, GWL_WNDPROC,
+ (LONG)keyedit_subkey_proc.current)) {
+ msg_box (dlg, "Could not set subkey window procedure.",
+ _("Key Edit"), MB_ERR);
+ BUG (NULL);
+ }
+ }
+ tt = create_header_tooltip (dlg);
+
+ item = GetDlgItem (dlg, IDC_KEYEDIT_UIDLIST);
+ keyedit_uid_proc.opaque = (void*)k;
+ keyedit_uid_proc.dlg = dlg;
+ keyedit_uid_proc.current = (WNDPROC)uid_subclass_proc;
+ keyedit_uid_proc.old = (WNDPROC)GetWindowLong (item, GWL_WNDPROC);
+ if (keyedit_uid_proc.old) {
+ if (!SetWindowLong (item, GWL_WNDPROC,
+ (LONG)keyedit_uid_proc.current)) {
+ msg_box (dlg, "Could not set user ID window procedure.",
+ _("Key Edit"), MB_ERR);
+ BUG (NULL);
+ }
+ }
+ if (k->ctx->revoked || k->ctx->expired) {
+ EnableWindow (GetDlgItem (dlg, IDC_KEYEDIT_CMD), FALSE);
+ EnableWindow (GetDlgItem (dlg, IDOK), FALSE);
+ }
+ SetDlgItemText (dlg, IDC_KEYEDIT_CMDINF, _("Command>"));
+ SetDlgItemText (dlg, IDCANCEL, _("&Close"));
+ SetDlgItemText (dlg, IDC_KEYEDIT_HELP, _("&Help"));
+ SetDlgItemText (dlg, IDC_KEYEDIT_REVOKE, _("&Revoke..."));
+ SetDlgItemText (dlg, IDOK, _("&OK"));
+ if (!check_desig_rev (k))
+ ShowWindow (GetDlgItem (dlg, IDC_KEYEDIT_REVOKE), SW_HIDE);
+ if (k->is_v3)
+ SetWindowText (dlg, _("Key Edit (PGP 2.6.x mode)"));
+ else
+ SetWindowText (dlg, _("Key Edit"));
+ SetForegroundWindow (dlg);
+ center_window (dlg, NULL);
+ return TRUE;
+
+ case WM_DESTROY:
+ if (lvsub) {
+ listview_release (lvsub);
+ lvsub = NULL;
+ }
+ if (lvuid) {
+ listview_release (lvuid);
+ lvuid = NULL;
+ }
+ if (tt != NULL)
+ DestroyWindow (tt);
+
+ balloon_msg_disable ();
+ break;
+
+ case WM_NOTIFY:
+ NMHDR *notify;
+ notify = (NMHDR *)lparam;
+ if (!notify || notify->idFrom != IDC_KEYEDIT_UIDLIST)
+ break;
+ if (notify->code == NM_DBLCLK)
+ do_editkey_showpref (k, dlg, lvuid);
+ else if (notify->code == NM_RCLICK && k->key_pair) {
+ if (listview_count_items (lvuid, 0) == 1)
+ break;
+ HMENU hm = LoadMenu (glob_hinst, MAKEINTRESOURCE (IDR_WINPT_KEYEDIT));
+ HMENU popup = GetSubMenu (hm, 0);
+ POINT p;
+
+ set_menu_text (popup, ID_KEYEDIT_UID_PRIM, _("Flag user ID as &primary"));
+ set_menu_text (popup, ID_KEYEDIT_UID_DEL, _("&Delete user ID"));
+ set_menu_text (popup, ID_KEYEDIT_UID_REV, _("&Revoke user ID"));
+ GetCursorPos (&p);
+ TrackPopupMenu (popup, TPM_RIGHTALIGN, p.x, p.y, 0, dlg, NULL);
+ DestroyMenu (hm);
+ DestroyMenu (popup);
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD (wparam)) {
+ case IDOK:
+ cmd = lookup_cmd (dlg);
+ if (cmd == LB_ERR) {
+ msg_box (dlg, _("Please select a command."), _("Key Edit"), MB_INFO);
+ return FALSE;
+ }
+ if (k->is_v3 && is_cmd_openpgp (cmd)) {
+ msg_box (dlg, _("This command cannot be used with PGP 2 (v3) keys.\n"),
+ _("Key Edit"), MB_ERR);
+ return FALSE;
+ }
+ switch (cmd) {
+ case CMD_SHOWPREF: do_editkey_showpref (k, dlg, lvuid); break;
+ case CMD_DELKEY: do_editkey_delkey (k, dlg, lvsub); break;
+ case CMD_ADDKEY: keyedit_add_subkey (k, dlg, lvsub); break;
+ case CMD_EXPIRE: do_editkey_expire (k, dlg, lvsub); break;
+ case CMD_REVKEY: do_editkey_revoke (k, dlg, lvsub); break;
+ case CMD_SETPREF:/*do_editkey_setpref (k, dlg, lvuid);*/ break;
+ case CMD_ADDUID: keyedit_add_userid( k, dlg, lvuid ); break;
+ case CMD_ADDREVOKER: keyedit_add_revoker( k, dlg ); break;
+ case CMD_ADDPHOTO: keyedit_add_photo( k, dlg ); break;
+ case CMD_REVUID: do_editkey_revuid( k, dlg, lvuid ); break;
+ case CMD_DELUID: do_editkey_deluid( k, dlg, lvuid ); break;
+ case CMD_PASSWD: keyedit_change_passwd (k, dlg); break;
+ case CMD_PRIMARY: do_editkey_primary (k, dlg, lvuid); break;
+ case CMD_ENABLE: do_editkey_enable_disable (k, dlg, lvsub, 1); break;
+ case CMD_DISABLE: do_editkey_enable_disable (k, dlg, lvsub, 0); break;
+ case CMD_CHECK: do_editkey_check (k, dlg); break;
+ case CMD_TRUST: keyedit_change_ownertrust (k, dlg); break;
+ case CMD_SIGN:
+ case CMD_LSIGN: do_editkey_sign_userid (k, dlg,
+ lvuid, cmd);
+ break;
+ case CMD_CLEAN: do_editkey_clean (k, dlg); break;
+ case CMD_MINIMIZE: do_editkey_minimize (k, dlg); break;
+ }
+ break;
+
+ case IDCANCEL:
+ EndDialog (dlg, FALSE);
+ break;
+
+ case IDC_KEYEDIT_HELP:
+ do_show_help (dlg);
+ break;
+
+ case IDC_KEYEDIT_REVOKE:
+ gen_desig_revoke_cert (k, dlg);
+ break;
+
+ case ID_KEYEDIT_UID_PRIM:
+ do_editkey_primary (k, dlg, lvuid);
+ break;
+
+ case ID_KEYEDIT_UID_DEL:
+ do_editkey_deluid (k, dlg, lvuid);
+ break;
+
+ case ID_KEYEDIT_UID_REV:
+ do_editkey_revuid (k, dlg, lvuid);
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
Modified: trunk/Src/wptKeyserver.cpp
===================================================================
--- trunk/Src/wptKeyserver.cpp 2011-11-27 12:45:44 UTC (rev 339)
+++ trunk/Src/wptKeyserver.cpp 2011-11-27 13:15:07 UTC (rev 340)
@@ -60,6 +60,36 @@
static size_t default_socket_timeout = 6;
+/* Remove %AB sequences from the input buffer @in
+ and store the raw data in @out. */
+void
+unhexify_buffer (const char *in, char **r_out)
+{
+ char temp[3], *out;
+ size_t len, pos, i=0;
+
+ len = strlen (in);
+ out = new char[len+1];
+ if (!out)
+ BUG (0);
+ memset (out, 0, len+1);
+ for (pos = 0; pos < len; pos++) {
+ if (in[pos] == '%' && in[pos+1] == '%')
+ out[i++] = '%';
+ else if (in[pos] == '%') {
+ temp[0] = in[++pos];
+ temp[1] = in[++pos];
+ temp[2] = 0;
+ out[i++] = (char)strtoul (temp, NULL, 16);
+ }
+ else
+ out[i++] = in[pos];
+ }
+ out[i] = 0;
+ *r_out = out;
+}
+
+
/* Wrapper for safe memory allocation. */
static char*
safe_alloc (DWORD n)
Modified: trunk/Src/wptMAPI.cpp
===================================================================
--- trunk/Src/wptMAPI.cpp 2011-11-27 12:45:44 UTC (rev 339)
+++ trunk/Src/wptMAPI.cpp 2011-11-27 13:15:07 UTC (rev 340)
@@ -211,7 +211,7 @@
"exchange encrypted mails with the key holder and to be able\n"
"to verify its signatures.\n"
"\n"
- "If you don't have WinPT, you can download it at http://winpt.gnupt.de");
+ "If you do not have WinPT, you can download it at http://winpt.gnupt.de");
kinf = km_key_get_info (key, 0);
p = (char*)malloc (strlen (s) + strlen (kinf) + 2);
sprintf (p, s, kinf);
Deleted: trunk/Src/wptMDSumDlg.cpp
===================================================================
--- trunk/Src/wptMDSumDlg.cpp 2011-11-27 12:45:44 UTC (rev 339)
+++ trunk/Src/wptMDSumDlg.cpp 2011-11-27 13:15:07 UTC (rev 340)
@@ -1,285 +0,0 @@
-#if 0 /*UNUSED*/
-/* wptMDSumDlg.cpp - Dialog to show hash values for files
- * Copyright (C) 2003, 2005, 2006, 2008 Timo Schulz
- *
- * This file is part of WinPT.
- *
- * WinPT is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * WinPT is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <windows.h>
-#include <stdio.h>
-
-#include "resource.h"
-#include "wptTypes.h"
-#include "wptW32API.h"
-#include "wptGPG.h"
-#include "wptCommonCtl.h"
-#include "wptContext.h"
-#include "wptNLS.h"
-#include "wptErrors.h"
-
-
-/* maximum hash size in octets (sha512=64) */
-#define MAX_HASHSIZE 64
-
-/* Symbolic column IDs. */
-enum md_col_t {COL_MD=0, COL_NAME};
-
-
-/* A model which represents the contents of the list view. */
-struct hashlist_model_s {
- struct hashlist_model_s *next;
- char *name;
- BYTE *md;
- DWORD mdlen;
-};
-typedef struct hashlist_model_s *hashlist_model_t;
-
-
-/* Release the file list @hm. */
-static void
-hashmodel_release (hashlist_model_t hm)
-{
- hashlist_model_t t;
-
- while (hm) {
- t = hm->next;
- free_if_alloc (hm->name);
- free_if_alloc (hm->md);
- free_if_alloc (hm);
- hm = t;
- }
-}
-
-
-/* Add a new file with the name @name to the list @hm. */
-static hashlist_model_t
-hashmodel_add_file (hashlist_model_t *hm, const char *name,
- const BYTE *mdbuf, size_t mdlen)
-{
- hashlist_model_t t, n;
-
- t = new hashlist_model_s;
- memset (t, 0, sizeof *t);
- t->name = m_strdup (name);
- t->mdlen = mdlen;
- t->md = new BYTE[mdlen];
- memcpy (t->md, mdbuf, mdlen);
- if (!*hm)
- *hm = t;
- else {
- for (n = *hm; n->next; n=n->next)
- ;
- n->next = t;
- }
- return t;
-}
-
-
-/* Return a printable digest of the buffer @mdbuf. */
-static const char*
-printable_digest (BYTE *mdbuf, size_t n, char *mdasc, size_t maxlen)
-{
- if (n*4 > maxlen)
- return NULL;
- for (size_t i = 0; i < n; i++)
- sprintf (mdasc+2*i, "%02X", mdbuf[i]);
- return mdasc;
-}
-
-
-static const char*
-id2algo (gpgme_hash_algo_t mdalgo)
-{
- switch (mdalgo) {
- case GPGME_MD_MD5: return "MD5";
- case GPGME_MD_SHA1: return "SHA1";
- case GPGME_MD_RMD160: return "RMD160";
- case GPGME_MD_SHA256: return "SHA256";
- case GPGME_MD_SHA384: return "SHA384";
- case GPGME_MD_SHA512: return "SHA512";
- default: break;
- }
- return "";
-}
-
-
-/* Hash the selected file from the FM listview control in @md.
- Add the results to the listview @lv. */
-static void
-hash_selected_files (md_file_s *md, listview_ctrl_t lv, hashlist_model_t *r_fl)
-{
- hashlist_model_t item;
- BYTE mdbuf[MAX_HASHSIZE];
- char fname[MAX_PATH+1];
- char mdasc[4*MAX_HASHSIZE+1];
- size_t n;
- int i;
-
- for (i = 0; i < listview_count_items (md->lv, 0); i++) {
- if (!listview_get_item_state (md->lv, i))
- continue;
- listview_get_item_text (md->lv, i, 1, fname, DIM (fname)-1);
- if (!gpg_md_hash_file (md->mdalgo, fname, mdbuf, &n)) {
- const char *pmd = printable_digest(mdbuf, n, mdasc, DIM(mdasc)-1);
- item = hashmodel_add_file (r_fl, fname, mdbuf, n);
- listview_add_item2 (lv, "", (void*)item);
- listview_add_sub_item (lv, 0, COL_MD, pmd);
- listview_add_sub_item (lv, 0, COL_NAME, fname);
- }
- }
-}
-
-
-/* Return 1 if there is a tool available to check the file.
- (sha1sum, md5sum). */
-static int
-tool_avail (gpgme_hash_algo_t mdalgo)
-{
- if (mdalgo == GPGME_MD_SHA1 || mdalgo == GPGME_MD_MD5)
- return 1;
- return 0;
-}
-
-
-/* Sorting callback. */
-static int CALLBACK
-sort_cb (LPARAM first, LPARAM second, LPARAM param)
-{
- hashlist_model_t a, b;
- int sortby = (int)param;
- int cmpres = 0;
-
- a = (hashlist_model_t)first;
- b = (hashlist_model_t)second;
- if (sortby == COL_NAME)
- cmpres = stricmp (a->name, b->name);
- else
- cmpres = memcmp (a->md, b->md, a->mdlen);
- return cmpres;
-}
-
-
-/* Dialog box procedure to show and calculate file digests. */
-BOOL CALLBACK
-mdsum_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
-{
- static listview_ctrl_t lv;
- static struct md_file_s *md;
- static hashlist_model_t hm = NULL;
- struct listview_column_s cols[] = {
- {0, 264, (char *)_("Digest")},
- {1, 160, (char *)_("Name")},
- {0, 0, 0}
- };
- gpgme_data_t sumlist = NULL;
- const char *name, *algname;
- char fname[MAX_PATH+64], mdasc[MAX_HASHSIZE*4];
- int i;
-
- switch (msg) {
- case WM_INITDIALOG:
- md = (md_file_s *)lparam;
- if (!md)
- BUG (NULL);
- listview_new (&lv, GetDlgItem (dlg, IDC_MDSUM_LIST));
- for (i = 0; i < cols[i].width; i++)
- listview_add_column (lv, &cols[i]);
- hash_selected_files (md, lv, &hm);
- SetDlgItemText (dlg, IDC_MDSUM_COPY, _("&Save..."));
- SetDlgItemText (dlg, IDOK, _("&Close"));
- SetDlgItemText (dlg, IDC_MDSUM_TOCLIP, _("Save to clipboard"));
- SetWindowText (dlg, _("Print Message Digest"));
- SetForegroundWindow (dlg);
- break;
-
- case WM_DESTROY:
- if (lv) {
- listview_release (lv);
- lv = NULL;
- }
- if (hm) {
- hashmodel_release (hm);
- hm = NULL;
- }
- break;
-
- case WM_NOTIFY:
- if (((NMHDR *)lparam)->code == LVN_COLUMNCLICK) {
- NMLISTVIEW *nft = (LPNMLISTVIEW) lparam;
- ListView_SortItems (lv->ctrl, sort_cb, nft->iSubItem);
- }
- break;
-
- case WM_COMMAND:
- switch (LOWORD (wparam)) {
- case IDOK:
- EndDialog (dlg, TRUE);
- break;
-
- case IDCANCEL:
- EndDialog (dlg, FALSE);
- break;
-
- case IDC_MDSUM_COPY:
- algname = id2algo ((gpgme_hash_algo_t)md->mdalgo);
- if (gpgme_data_new (&sumlist))
- BUG(0);
- if (!tool_avail ((gpgme_hash_algo_t)md->mdalgo)) {
- const char *s;
-
- s = "#warning '";
- gpgme_data_write (sumlist, s, strlen (s));
- gpgme_data_write (sumlist, algname, strlen (algname));
- s = " ' sum is not yet available\r\n";
- gpgme_data_write (sumlist, s, strlen (s));
- }
- for (i = 0; i < listview_count_items (lv, 0); i++) {
- listview_get_item_text (lv, i, COL_MD, mdasc, DIM (mdasc)-1);
- listview_get_item_text (lv, i, COL_NAME, fname, DIM (fname)-1);
-
- gpgme_data_write (sumlist, mdasc, strlen (mdasc));
- gpgme_data_write (sumlist, " ", 1);
- gpgme_data_write (sumlist, fname, strlen (fname));
- gpgme_data_write (sumlist, "\r\n", 2);
- }
- if (IsDlgButtonChecked (dlg, IDC_MDSUM_TOCLIP)) {
- gpg_data_release_to_clipboard (sumlist, 0);
- break;
- }
- _snprintf (fname, DIM (fname)-1, "%s_sums.txt", algname);
- name = get_filesave_dlg (dlg, _("Select File to Save Checksums"),
- NULL, fname);
- if (name && *name) {
- gpgme_error_t err;
-
- err = gpg_data_release_and_set_file (sumlist, name);
- if (!err) {
- log_box (_("File Manager"), MB_OK,
- _("Checksums successfully saved in '%s'"), name);
- sumlist = NULL;
- }
- else
- msg_box (dlg, gpgme_strerror (err), _("File Manager"), MB_ERR);
- }
- if (sumlist)
- gpgme_data_release (sumlist);
- break;
- }
- break;
- }
- return FALSE;
-}
-#endif
Modified: trunk/Src/wptPassphraseCB.cpp
===================================================================
--- trunk/Src/wptPassphraseCB.cpp 2011-11-27 12:45:44 UTC (rev 339)
+++ trunk/Src/wptPassphraseCB.cpp 2011-11-27 13:15:07 UTC (rev 340)
@@ -194,10 +194,7 @@
else {
char *p = new char[n+2];
SafeGetDlgItemText (dlg, item_ctrl_id (c->gpg_cmd), p, n+1);
- if (emulate_utf8_bug)
- c->pwd = native_to_utf8 (p);
- else
- c->pwd = m_strdup (p);
+ c->pwd = m_strdup (p);
sfree_if_alloc (p);
}
if (c->gpg != NULL) {
Modified: trunk/Src/wptPassphraseDlg.cpp
===================================================================
--- trunk/Src/wptPassphraseDlg.cpp 2011-11-27 12:45:44 UTC (rev 339)
+++ trunk/Src/wptPassphraseDlg.cpp 2011-11-27 13:15:07 UTC (rev 340)
@@ -238,10 +238,8 @@
*ret_cancel = 1;
return NULL;
}
- if (emulate_utf8_bug)
- p = native_to_utf8 (pass.pwd);
- else
- p = m_strdup (pass.pwd);
+
+ p = m_strdup (pass.pwd);
wipememory (pass.pwd, sizeof (pass.pwd));
return p;
}
@@ -271,10 +269,7 @@
*ret_cancel = 1;
return NULL;
}
- if (emulate_utf8_bug)
- p = native_to_utf8 (pass.pwd);
- else
- p = m_strdup (pass.pwd);
+ p = m_strdup (pass.pwd);
wipememory (pass.pwd, sizeof (pass.pwd));
return p;
}
Modified: trunk/Src/wptUtil.cpp
===================================================================
--- trunk/Src/wptUtil.cpp 2011-11-27 12:45:44 UTC (rev 339)
+++ trunk/Src/wptUtil.cpp 2011-11-27 13:15:07 UTC (rev 340)
@@ -153,36 +153,8 @@
}
-/* Remove %AB sequences from the input buffer @in
- and store the raw data in @out. */
-void
-unhexify_buffer (const char *in, char **r_out)
-{
- char temp[3], *out;
- size_t len, pos, i=0;
- len = strlen (in);
- out = new char[len+1];
- if (!out)
- BUG (0);
- memset (out, 0, len+1);
- for (pos = 0; pos < len; pos++) {
- if (in[pos] == '%' && in[pos+1] == '%')
- out[i++] = '%';
- else if (in[pos] == '%') {
- temp[0] = in[++pos];
- temp[1] = in[++pos];
- temp[2] = 0;
- out[i++] = (char)strtoul (temp, NULL, 16);
- }
- else
- out[i++] = in[pos];
- }
- out[i] = 0;
- *r_out = out;
-}
-
/* Safe strdup version (C++ version). */
char*
m_strdup (const char *str)
More information about the Winpt-commits
mailing list