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 "passphrase.h"
43 #define DIM(v) (sizeof(v)/sizeof((v)[0]))
45 static char *content_names
[] = {
47 "Content-Disposition",
48 "Content-Transfer-Encoding",
52 /* stolen from rfc2015.c */
54 gpg_name_cmp(const char *a
, const char *b
)
56 for( ; *a
&& *b
; a
++, b
++) {
58 && toupper(*(unsigned char *)a
) != toupper(*(unsigned char *)b
))
66 pgptext_decrypt (MimeInfo
*partinfo
, FILE *fp
)
70 GpgmeData cipher
= NULL
, plain
= NULL
;
71 struct passphrase_cb_info_s info
;
73 memset (&info
, 0, sizeof info
);
75 err
= gpgme_new (&ctx
);
77 debug_print ("gpgme_new failed: %s\n", gpgme_strerror (err
));
81 err
= gpgme_data_new_from_filepart (&cipher
, NULL
, fp
,
82 partinfo
->fpos
, partinfo
->size
);
84 debug_print ("gpgme_data_new_from_filepart failed: %s\n",
85 gpgme_strerror (err
));
89 err
= gpgme_data_new (&plain
);
91 debug_print ("gpgme_new failed: %s\n", gpgme_strerror (err
));
95 if (!getenv("GPG_AGENT_INFO")) {
97 gpgme_set_passphrase_cb (ctx
, gpgmegtk_passphrase_cb
, (void *)&info
);
100 err
= gpgme_op_decrypt (ctx
, cipher
, plain
);
103 gpgme_data_release (cipher
);
105 gpgmegtk_free_passphrase();
106 debug_print ("decryption failed: %s\n", gpgme_strerror (err
));
107 gpgme_data_release (plain
);
111 debug_print ("decryption succeeded\n");
118 headerp(char *p
, char **names
)
127 if(p2
[-1] == ' ' || p2
[-1] == '\t') {
136 for(i
= 0 ; names
[i
] != NULL
; i
++) {
137 if(!gpg_name_cmp (names
[i
], p
))
142 return names
[i
] != NULL
;
145 MimeInfo
* pgptext_find_signature (MimeInfo
*mimeinfo
)
150 gboolean
pgptext_has_signature (MimeInfo
*mimeinfo
)
153 * check for the following strings:
154 * -----BEGIN PGP SIGNED MESSAGE-----
156 * -----BEGIN PGP SIGNATURE-----
157 * -----END PGP SIGNATURE-----
163 void pgptext_check_signature (MimeInfo
*mimeinfo
, FILE *fp
)
167 int pgptext_is_encrypted (MimeInfo
*mimeinfo
, MsgInfo
*msginfo
)
170 gchar
*file
, *tmpchk
;
172 gboolean has_begin_pgp_msg
= FALSE
;
173 gboolean has_end_pgp_msg
= FALSE
;
174 gchar
*check_begin_pgp_msg
= "-----BEGIN PGP MESSAGE-----\n";
175 gchar
*check_end_pgp_msg
= "-----END PGP MESSAGE-----\n";
177 g_return_val_if_fail(msginfo
!= NULL
, 0);
182 if ((fp
= procmsg_open_message(msginfo
)) == NULL
) return 0;
183 mimeinfo
= procmime_scan_mime_header(fp
);
185 if (!mimeinfo
) return 0;
187 file
= procmsg_get_message_file_path(msginfo
);
188 g_return_val_if_fail(file
!= NULL
, 0);
190 if (mimeinfo
->mime_type
!= MIME_TEXT
) {
191 if ((fp
= fopen(file
, "rb")) == NULL
) {
192 FILE_OP_ERROR(file
, "fopen");
197 if (mimeinfo
->mime_type
== MIME_MULTIPART
) {
198 if (fseek(fp
, mimeinfo
->fpos
, SEEK_SET
) < 0)
200 while (fgets(buf
, sizeof(buf
), fp
) != NULL
)
201 if (buf
[0] == '\r' || buf
[0] == '\n') break;
203 /* now check for a pgptext encrypted message */
204 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
205 tmpchk
= g_strnfill(sizeof(buf
), '\n');
206 memmove(tmpchk
, &buf
, sizeof(buf
));
208 if (strstr(tmpchk
, check_begin_pgp_msg
) != NULL
)
209 has_begin_pgp_msg
= TRUE
;
210 if (strstr(tmpchk
, check_end_pgp_msg
) != NULL
)
211 has_end_pgp_msg
= TRUE
;
217 if ((fp
= fopen(file
, "rb")) == NULL
) {
218 FILE_OP_ERROR(file
, "fopen");
223 if (fseek(fp
, mimeinfo
->fpos
, SEEK_SET
) < 0)
225 while (fgets(buf
, sizeof(buf
), fp
) != NULL
)
226 if (buf
[0] == '\r' || buf
[0] == '\n') break;
228 /* now check for a pgptext encrypted message */
229 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
230 tmpchk
= g_strnfill(sizeof(buf
), '\n');
231 memmove(tmpchk
, &buf
, sizeof(buf
));
233 if (strstr(tmpchk
, check_begin_pgp_msg
) != NULL
)
234 has_begin_pgp_msg
= TRUE
;
235 if (strstr(tmpchk
, check_end_pgp_msg
) != NULL
)
236 has_end_pgp_msg
= TRUE
;
245 /* do we have a proper message? */
246 if (has_begin_pgp_msg
&& has_end_pgp_msg
)
252 void pgptext_decrypt_message (MsgInfo
*msginfo
, MimeInfo
*mimeinfo
, FILE *fp
)
263 g_return_if_fail (mimeinfo
->mime_type
== MIME_TEXT
);
265 debug_print ("text/plain with pgptext encountered\n");
267 partinfo
= procmime_scan_message(msginfo
);
270 if (fseek(fp
, partinfo
->fpos
, SEEK_SET
) < 0)
272 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
273 partinfo
->fpos
= partinfo
->fpos
+ strlen(buf
);
274 if (buf
[0] == '\r' || buf
[0] == '\n') break;
277 while (fgets(buf
, sizeof(buf
), fp
) != NULL
)
278 partinfo
->size
= partinfo
->size
+ strlen(buf
);
280 plain
= pgptext_decrypt (partinfo
, fp
);
282 msginfo
->decryption_failed
= 1;
286 fname
= g_strdup_printf("%s%cplaintext.%08x",
287 get_mime_tmp_dir(), G_DIR_SEPARATOR
, ++id
);
289 if ((dstfp
= fopen(fname
, "wb")) == NULL
) {
290 FILE_OP_ERROR(fname
, "fopen");
292 msginfo
->decryption_failed
= 1;
296 /* write the orginal header to the new file */
297 if (fseek(fp
, mimeinfo
->fpos
, SEEK_SET
) < 0)
300 while (fgets(buf
, sizeof(buf
), fp
)) {
301 if (headerp (buf
, content_names
))
303 if (buf
[0] == '\r' || buf
[0] == '\n')
308 err
= gpgme_data_rewind (plain
);
310 debug_print ("gpgme_data_rewind failed: %s\n", gpgme_strerror (err
));
312 /* insert blank line to avoid some trouble... */
315 while (!(err
= gpgme_data_read (plain
, buf
, sizeof(buf
), &nread
))) {
316 fwrite (buf
, nread
, 1, dstfp
);
319 if (err
!= GPGME_EOF
) {
320 debug_print ("gpgme_data_read failed: %s\n", gpgme_strerror (err
));
325 msginfo
->plaintext_file
= fname
;
326 msginfo
->decryption_failed
= 0;
330 int pgptext_encrypt (const char *file
, GSList
*recp_list
)
335 int pgptext_sign (const char *file
, PrefsAccount
*ac
)
340 #endif /* USE_GPGME */