Renamed project to GPGol.
[gpgol.git] / src / verify-dialog.c
1 /* verify-dialog.c
2  *      Copyright (C) 2005 g10 Code GmbH
3  *
4  * This file is part of GPGol.
5  * 
6  * GPGol is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  * 
11  * GPGol is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  * 
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301, USA.
20  */
21
22 #include <config.h>
23
24 #include <windows.h>
25 #include <time.h>
26 #include <gpgme.h>
27
28 #include "gpgol-ids.h"
29 #include "keycache.h"
30 #include "intern.h"
31
32 struct dialog_context
33 {
34   gpgme_verify_result_t res;
35   const char *filename;
36 };
37
38
39 static char*
40 get_timestamp (time_t l)
41 {
42     static char buf[64];
43     struct tm * tm;
44
45     if (l == 0) {
46         sprintf (buf, "????" "-??" "-?? ??" ":??" ":??");
47         return buf;
48     }
49         
50     tm = localtime (&l);
51     sprintf (buf, "%04d-%02d-%02d %02d:%02d:%02d",
52              tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
53              tm->tm_hour, tm->tm_min, tm->tm_sec);
54     return buf;
55 }
56
57
58 static int
59 load_akalist (HWND dlg, gpgme_key_t key)
60 {
61     gpgme_user_id_t u;
62     int n = 0;
63
64     u = key->uids;
65     if (!u->next)
66         return n;
67     for (u=u->next; u; u=u->next) {
68         SendDlgItemMessage (dlg, IDC_VRY_AKALIST, LB_ADDSTRING,
69                             0, (LPARAM)(const char*)u->uid);
70         n++;
71     }
72     return n;
73 }
74
75
76 static void 
77 load_sigbox (HWND dlg, gpgme_verify_result_t ctx)
78 {
79     gpgme_key_t key;
80     char *s, buf[2+16+1];
81     char *p;
82     int stat;
83     int valid, no_key = 0, n = 0;
84
85     s = get_timestamp (ctx->signatures->timestamp);
86     SetDlgItemText (dlg, IDC_VRY_TIME, s);
87
88     s = ctx->signatures->fpr;
89     if (strlen (s) == 40)
90         strncpy (buf+2, s+40-8, 8);
91     else if (strlen (s) == 32) /* MD5:RSAv3 */
92         strncpy (buf+2, s+32-8, 8);
93     else
94         strncpy (buf+2, s+8, 8);
95     buf[10] = 0;
96     buf[0] = '0'; 
97     buf[1] = 'x';
98     SetDlgItemText (dlg, IDC_VRY_KEYID, buf);
99     /*key = find_gpg_key (buf+2, 0);*/
100     key = get_gpg_key (buf+2);
101     
102     stat = ctx->signatures->summary;
103     if (stat & GPGME_SIGSUM_GREEN)
104         s = "Good signature";
105     else if (stat & GPGME_SIGSUM_RED)
106         s = "BAD signature!";
107     else if (stat & GPGME_SIGSUM_KEY_REVOKED)
108         s = "Good signature from revoked key";
109     else if (stat & GPGME_SIGSUM_KEY_EXPIRED)
110         s = "Good signature from expired key";
111     else if (stat & GPGME_SIGSUM_SIG_EXPIRED)
112         s = "Good expired signature";
113     else if (stat & GPGME_SIGSUM_KEY_MISSING) {
114         s = "Could not check signature: missing key";
115         no_key = 1;
116     }
117     else
118         s = "Verification error";
119     /* XXX: if we have a key we do _NOT_ trust, stat is 'wrong' */
120     SetDlgItemText (dlg, IDC_VRY_STATUS, s);
121     
122     if (key) {
123         s = (char*)gpgme_key_get_string_attr (key, GPGME_ATTR_USERID, NULL, 0);
124         SetDlgItemText (dlg, IDC_VRY_ISSUER, s);
125
126         n = load_akalist (dlg, key);
127         gpgme_key_release (key);
128         if (n == 0)
129             EnableWindow (GetDlgItem (dlg, IDC_VRY_AKALIST), FALSE);
130     }
131     else {
132         s = "User-ID not found";
133         SetDlgItemText (dlg, IDC_VRY_ISSUER, s);
134     }
135
136     switch (ctx->signatures->pubkey_algo) {
137     case GPGME_PK_RSA: s = "RSA"; break;
138     case GPGME_PK_DSA: s = "DSA"; break;
139     default:           s = "???"; break;
140     }
141     SetDlgItemText (dlg, IDC_VRY_PKALGO, s);
142
143     valid = ctx->signatures->validity;
144     if (stat & GPGME_SIGSUM_SIG_EXPIRED) {
145         char *fmt;
146
147         fmt = "Signature expired on %s";
148         s = get_timestamp (ctx->signatures->exp_timestamp);
149         p = xmalloc (strlen (s)+1+strlen (fmt)+2);
150         sprintf (p, fmt, s);
151         SetDlgItemText (dlg, IDC_VRY_HINT, s);
152         xfree (p);
153     }
154     else if (valid < GPGME_VALIDITY_MARGINAL) {
155         switch (valid) {
156         case GPGME_VALIDITY_NEVER:
157             s = "Signature issued by a key we do NOT trust.";
158             break;
159
160         default:
161             if (no_key)
162                 s = "";
163             else
164                 s = "Signature issued by a non-valid key.";
165             break;
166         }
167         SetDlgItemText (dlg, IDC_VRY_HINT, s);
168     }
169 }
170
171
172 static BOOL CALLBACK
173 verify_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
174 {
175     static struct dialog_context *ctx;
176
177     switch (msg) {
178     case WM_INITDIALOG:
179         ctx = (struct dialog_context *)lparam;
180         load_sigbox (dlg, ctx->res);
181         center_window (dlg, NULL);
182         SetForegroundWindow (dlg);
183         if (ctx->filename)
184           {
185             char *tmp = xmalloc (strlen (ctx->filename) + 100);
186             strcpy (stpcpy (stpcpy (tmp, "Verification Result ("),
187                             ctx->filename), ")");
188             SetWindowText (dlg, tmp);
189             xfree (tmp);
190           }
191         break;
192
193     case WM_COMMAND:
194         switch (LOWORD(wparam)) {
195         case IDOK:
196             EndDialog (dlg, TRUE);
197             break;
198         }
199         break;
200     }
201     return FALSE;
202 }
203
204
205 /* Display the verify dialog based on the gpgme result in
206    RES. FILENAME is used to modify the caption of the dialog; it may
207    be NULL. */
208 int
209 verify_dialog_box (gpgme_verify_result_t res, const char *filename)
210 {
211   struct dialog_context ctx;
212
213   memset (&ctx,0, sizeof ctx);
214   ctx.res = res;
215   ctx.filename = filename;
216
217   DialogBoxParam (glob_hinst, (LPCTSTR)IDD_VRY, GetDesktopWindow (),
218                   verify_dlg_proc, (LPARAM)&ctx);
219   return res->signatures->summary == GPGME_SIGSUM_GREEN? 0 : -1;
220 }