これでできるんじゃないだろうか*1。 明らかにハックなので、鍵選択で PGP と混在させた場合も考えてないし、署名 + 暗号化のケースも作ってないし、なにより関数名が pgp_encrypt のまま。
diff -u src/rfc2015.c src/rfc2015.c
--- src/rfc2015.c (working copy)
+++ src/rfc2015.c (working copy)
@@ -39,6 +39,8 @@
#include "procmime.h"
#include "procheader.h"
#include "base64.h"
+#define B64_LINE_SIZE 57
+#define B64_BUFFSIZE 77
#include "uuencode.h"
#include "unmime.h"
#include "codeconv.h"
@@ -373,7 +375,6 @@
struct passphrase_cb_info_s info;
gpgme_verify_result_t verifyresult = NULL;
const gchar *result = NULL;
- const gchar *filename;
memset(&info, 0, sizeof info);
@@ -400,6 +401,7 @@
goto leave;
}
} else {
+ gchar *filename;
filename = procmime_get_tmp_file_name(partinfo);
if (procmime_get_part_fp(filename, fp, partinfo) < 0) {
g_warning("Can't get the S/MIME data file.");
@@ -853,7 +855,15 @@
if (!err)
err = gpgme_data_new(&cipher);
if (!err) {
- gpgme_set_armor(ctx, 1);
+ if ((*kset)->protocol == GPGME_PROTOCOL_OpenPGP) {
+ gpgme_set_armor(ctx, 1);
+ debug_print("pgp_encrypt(): PGP\n");
+ } else {
+ err = gpgme_set_protocol(ctx, (*kset)->protocol);
+ debug_print("pgp_encrypt(): S/MIME\n");
+ }
+ }
+ if (!err) {
err = (gpgme_data_seek(plain, 0, SEEK_SET) == -1) ?
gpgme_error_from_errno(errno) : 0;
if (!err) {
@@ -940,6 +950,7 @@
ssize_t bytesRW = 0;
gint mime_version_seen = 0;
gchar *boundary;
+ gboolean smime;
boundary = generate_mime_boundary("Encrypt");
@@ -949,6 +960,7 @@
debug_print("error creating recipient list\n");
goto failure;
}
+ smime = ((*kset)->protocol == GPGME_PROTOCOL_CMS);
/* Open the source file */
if ((fp = g_fopen(file, "rb")) == NULL) {
@@ -1083,7 +1095,16 @@
if (!mime_version_seen)
fputs("MIME-Version: 1.0\r\n", fp);
+ if (smime)
fprintf(fp,
+ "Content-Type: application/pkcs7-mime;"
+ " smime-type=\"enveloped-data\";\r\n"
+ " name=\"smime.p7m\"\r\n"
+ "Content-Disposition: attachment; filename=\"smime.p7m\"\r\n"
+ "Content-Transfer-Encoding: base64\r\n"
+ "\r\n");
+ else
+ fprintf(fp,
"Content-Type: multipart/encrypted;"
" protocol=\"application/pgp-encrypted\";\r\n"
" boundary=\"%s\"\r\n"
@@ -1111,7 +1132,19 @@
bytesRW = gpgme_data_read(cipher, buf, BUFFSIZE);
while (bytesRW > 0) {
- fwrite(buf, bytesRW, 1, fp);
+ if (smime) {
+ gchar outbuf[B64_BUFFSIZE];
+ gint l;
+
+ for (i = 0; i < bytesRW; i += B64_LINE_SIZE) {
+ l = MIN(B64_LINE_SIZE, bytesRW - i);
+ base64_encode(outbuf, (guchar *)buf + i, l);
+ fputs(outbuf, fp);
+ fputc('\n', fp);
+ }
+ } else {
+ fwrite(buf, bytesRW, 1, fp);
+ }
bytesRW = gpgme_data_read(cipher, buf, BUFFSIZE);
}
@@ -1122,6 +1155,7 @@
}
/* and the final boundary */
+ if (!smime)
fprintf(fp,
"\r\n"
"--%s--\r\n",
only in patch2:
--- src/select-keys.c (revision 2362)
+++ src/select-keys.c (working copy)
@@ -159,6 +159,7 @@
const char *text[N_COL_TITLES];
char *algo_buf;
int row;
+ gboolean uid_shown = FALSE;
/* first check whether the key is capable of encryption which is not
* the case for revoked, expired or sign-only keys */
@@ -175,9 +176,15 @@
text[COL_KEYID] = s;
s = key->uids->name;
+ if (!(s && *s) && key->protocol == GPGME_PROTOCOL_CMS) {
+ s = key->uids->uid;
+ uid_shown = TRUE;
+ }
text[COL_NAME] = s;
s = key->uids->email;
+ if (!(s && *s) && key->protocol == GPGME_PROTOCOL_CMS && key->uids->next)
+ s = (uid_shown ? (key->uids->next ? key->uids->next->uid : NULL) : key->uids->uid);
text[COL_EMAIL] = s;
switch (key->uids->validity)
@@ -218,6 +225,7 @@
gpgme_error_t err;
gpgme_key_t key;
int running=0;
+ int smime;
g_return_if_fail (sk);
clist = sk->clist;
@@ -235,6 +243,15 @@
while (gtk_events_pending ())
gtk_main_iteration ();
+ for (smime = 0; smime < 2; smime++) {
+ if (smime) {
+ err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS);
+ if (err) {
+ debug_print ("** gpgme_set_protocol(GPGME_PROTOCOL_CMS) failed: %s",
+ gpgme_strerror(err));
+ continue;
+ }
+ }
err = gpgme_op_keylist_start (ctx, pattern, 0);
if (err) {
debug_print ("** gpgme_op_keylist_start(%s) failed: %s",
@@ -257,6 +274,7 @@
gpgme_strerror (err));
gpgme_op_keylist_end(ctx);
}
+ }
sk->select_ctx = NULL;
gpgme_release (ctx);
/*gtk_clist_thaw (select_keys.clist);*/
@@ -421,7 +439,8 @@
row = GPOINTER_TO_INT(sk->clist->selection->data);
key = gtk_clist_get_row_data(sk->clist, row);
if (key) {
- if ( key->uids->validity < GPGME_VALIDITY_FULL ) {
+ if ( key->uids->validity < GPGME_VALIDITY_FULL &&
+ key->protocol == GPGME_PROTOCOL_OpenPGP ) {
use_key = use_untrusted(key);
if (!use_key) {
debug_print ("** Key untrusted, will not encrypt");
gpgme のほうで base64 エンコードしてくれたりは、しないのかな。
*1 なぜか、ちょっと前まで動いていたのに、"Not implemented" エラーが出るようになっちゃったので、わからない