2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001 Jens Jahnke <jan0sch@gmx.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 #include "procheader.h"
44 #include "prefs_common.h"
45 #include "passphrase.h"
46 #include "select-keys.h"
47 #include "sigstatus.h"
52 #define DIM(v) (sizeof(v)/sizeof((v)[0]))
54 static char *content_names[] = {
56 "Content-Disposition",
57 "Content-Transfer-Encoding",
61 static char *mime_version_name[] = {
67 struct passphrase_cb_info_s {
73 passphrase_cb (void *opaque, const char *desc, void *r_hd)
75 struct passphrase_cb_info_s *info = opaque;
76 GpgmeCtx ctx = info ? info->c : NULL;
80 /* FIXME: cleanup by looking at *r_hd */
84 gpgmegtk_set_passphrase_grab (prefs_common.passphrase_grab);
85 g_message ("%% requesting passphrase for `%s': ", desc );
86 pass = gpgmegtk_passphrase_mbox (desc);
88 g_message ("%% cancel passphrase entry");
92 g_message ("%% sending passphrase");
98 pgptext_decrypt (MimeInfo *partinfo, FILE *fp)
102 GpgmeData cipher = NULL, plain = NULL;
103 struct passphrase_cb_info_s info;
105 memset (&info, 0, sizeof info);
107 err = gpgme_new (&ctx);
109 g_message ("gpgme_new failed: %s", gpgme_strerror (err));
113 err = gpgme_data_new_from_filepart (&cipher, NULL, fp,
114 partinfo->fpos, partinfo->size);
116 g_message ("gpgme_data_new_from_filepart failed: %s",
117 gpgme_strerror (err));
121 err = gpgme_data_new (&plain);
123 g_message ("gpgme_new failed: %s", gpgme_strerror (err));
127 if (!getenv("GPG_AGENT_INFO")) {
129 gpgme_set_passphrase_cb (ctx, passphrase_cb, &info);
132 err = gpgme_op_decrypt (ctx, cipher, plain);
135 gpgme_data_release (cipher);
137 g_warning ("** decryption failed: %s", gpgme_strerror (err));
138 gpgme_data_release (plain);
142 g_message ("** decryption succeeded");
149 headerp(char *p, char **names)
158 if(p2[-1] == ' ' || p2[-1] == '\t') {
167 for(i = 0 ; names[i] != NULL; i++) {
168 if(!name_cmp (names[i], p))
173 return names[i] != NULL;
176 MimeInfo * pgptext_find_signature (MimeInfo *mimeinfo)
180 gboolean pgptext_has_signature (MimeInfo *mimeinfo)
183 * check for the following strings:
184 * -----BEGIN PGP SIGNED MESSAGE-----
186 * -----BEGIN PGP SIGNATURE-----
187 * -----END PGP SIGNATURE-----
193 void pgptext_check_signature (MimeInfo *mimeinfo, FILE *fp)
197 int pgptext_is_encrypted (MimeInfo *mimeinfo, MsgInfo *msginfo)
200 gchar *file, *tmpchk;
202 gboolean has_begin_pgp_msg = FALSE;
203 gboolean has_end_pgp_msg = FALSE;
204 gchar *check_begin_pgp_msg = "-----BEGIN PGP MESSAGE-----\n";
205 gchar *check_end_pgp_msg = "-----END PGP MESSAGE-----\n";
207 g_return_if_fail(msginfo != NULL);
212 if ((fp = procmsg_open_message(msginfo)) == NULL) return;
213 mimeinfo = procmime_scan_mime_header(fp);
215 if (!mimeinfo) return;
217 file = procmsg_get_message_file_path(msginfo);
218 g_return_if_fail(file != NULL);
220 if (mimeinfo->mime_type != MIME_TEXT) {
221 if ((fp = fopen(file, "r")) == NULL) {
222 FILE_OP_ERROR(file, "fopen");
226 if (mimeinfo->mime_type == MIME_MULTIPART) {
227 if (fseek(fp, mimeinfo->fpos, SEEK_SET) < 0)
229 while (fgets(buf, sizeof(buf), fp) != NULL)
230 if (buf[0] == '\r' || buf[0] == '\n') break;
232 /* now check for a pgptext encrypted message */
233 while (fgets(buf, sizeof(buf), fp) != NULL) {
234 tmpchk = g_strnfill(sizeof(buf), '\n');
235 memmove(tmpchk, &buf, sizeof(buf));
237 if (strstr(tmpchk, check_begin_pgp_msg) != NULL)
238 has_begin_pgp_msg = TRUE;
239 if (strstr(tmpchk, check_end_pgp_msg) != NULL)
240 has_end_pgp_msg = TRUE;
246 if ((fp = fopen(file, "r")) == NULL) {
247 FILE_OP_ERROR(file, "fopen");
251 if (fseek(fp, mimeinfo->fpos, SEEK_SET) < 0)
253 while (fgets(buf, sizeof(buf), fp) != NULL)
254 if (buf[0] == '\r' || buf[0] == '\n') break;
256 /* now check for a pgptext encrypted message */
257 while (fgets(buf, sizeof(buf), fp) != NULL) {
258 tmpchk = g_strnfill(sizeof(buf), '\n');
259 memmove(tmpchk, &buf, sizeof(buf));
261 if (strstr(tmpchk, check_begin_pgp_msg) != NULL)
262 has_begin_pgp_msg = TRUE;
263 if (strstr(tmpchk, check_end_pgp_msg) != NULL)
264 has_end_pgp_msg = TRUE;
273 /* do we have a proper message? */
274 if (has_begin_pgp_msg && has_end_pgp_msg)
280 void pgptext_decrypt_message (MsgInfo *msginfo, MimeInfo *mimeinfo, FILE *fp)
293 g_return_if_fail (mimeinfo->mime_type == MIME_TEXT);
295 g_message ("** text/plain with pgptext encountered");
297 partinfo = procmime_scan_message(msginfo);
300 if (fseek(fp, partinfo->fpos, SEEK_SET) < 0)
302 while (fgets(buf, sizeof(buf), fp) != NULL) {
303 partinfo->fpos = partinfo->fpos + strlen(buf);
304 if (buf[0] == '\r' || buf[0] == '\n') break;
307 while (fgets(buf, sizeof(buf), fp) != NULL)
308 partinfo->size = partinfo->size + strlen(buf);
310 plain = pgptext_decrypt (partinfo, fp);
312 msginfo->decryption_failed = 1;
316 fname = g_strdup_printf("%s%cplaintext.%08x",
317 get_mime_tmp_dir(), G_DIR_SEPARATOR, ++id);
319 if ((dstfp = fopen(fname, "w")) == NULL) {
320 FILE_OP_ERROR(fname, "fopen");
322 msginfo->decryption_failed = 1;
326 /* write the orginal header to the new file */
327 if (fseek(fp, mimeinfo->fpos, SEEK_SET) < 0)
330 while (fgets(buf, sizeof(buf), fp)) {
331 if (headerp (buf, content_names))
333 if (buf[0] == '\r' || buf[0] == '\n')
338 err = gpgme_data_rewind (plain);
340 g_message ("** gpgme_data_rewind failed: %s", gpgme_strerror (err));
342 /* insert blank line to avoid some trouble... */
345 while (!(err = gpgme_data_read (plain, buf, sizeof(buf), &nread))) {
346 fwrite (buf, nread, 1, dstfp);
349 if (err != GPGME_EOF) {
350 g_warning ("** gpgme_data_read failed: %s", gpgme_strerror (err));
355 msginfo->plaintext_file = fname;
356 msginfo->decryption_failed = 0;
360 int pgptext_encrypt (const char *file, GSList *recp_list)
364 int pgptext_sign (const char *file, PrefsAccount *ac)
368 #endif /* USE_GPGME */