summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduardo Chappa <chappa@washington.edu>2014-06-20 23:23:19 -0600
committerEduardo Chappa <chappa@washington.edu>2014-06-20 23:23:19 -0600
commit121a42f3d82c1b98c384857960d14b2057a95c41 (patch)
tree3dbd271cc59b33cee35acd5a3dd55a997c7848bc
parent60b67de2ba4be4d2bfeeeea685869e9a5a7363c0 (diff)
downloadalpine-121a42f3d82c1b98c384857960d14b2057a95c41.tar.xz
* new version 2.19.9992
* Alpine would not parse options from the command line, such as -patterns-filters2, correctly. * Add /usr/local/include as a path to find include and libs files for openssl in FreeBSD. * Management certificate screen now prints, in addition to the e-mail address of the owner of the certificates, the dates of validity and the MD5 hash of such certificates. * crash when processing message/rfc822 attachments that are encoded in base64. * Openssl: if /usr/local/ssl exists, assume that this is the intended place where ssl libraries, include files and certificates are located. Typically, distributions do not use this directory, so its existence indicates that Openssl has been specially installed there, so it is probably a preferred place to get the system Openssl files. * Postponed messages whose content-type is text/html, text/enriched and text/richtext are sent with that content-type, even though, after resuming composition, Alpine had changed its type to text/plain. * HTML: <BR>, <BR />, and <BR/&> are considered the same inline tag; the same is valid for the <HR> tag.
-rw-r--r--VERSION2
-rw-r--r--alpine/arg.c21
-rw-r--r--alpine/conftype.h1
-rw-r--r--alpine/mailpart.c3
-rw-r--r--alpine/osdep/mswin.rc8
-rw-r--r--alpine/smime.c52
-rwxr-xr-xconfigure33
-rw-r--r--configure.ac16
-rw-r--r--doc/alpine.12
-rw-r--r--doc/tech-notes/index.html2
-rw-r--r--doc/tech-notes/tech-notes.txt2
-rw-r--r--imap/src/c-client/rfc822.c94
-rw-r--r--mapi/pmapi.c2
-rw-r--r--mapi/pmapi.rc8
-rw-r--r--pith/conftype.h10
-rw-r--r--pith/filter.c209
-rw-r--r--pith/mimedesc.c2
-rw-r--r--pith/pine.hlp56
-rw-r--r--pith/reply.c2
-rw-r--r--pith/send.c5
-rw-r--r--pith/smime.c21
-rw-r--r--pith/smkeys.c132
-rw-r--r--pith/smkeys.h2
-rw-r--r--po/Makefile.in2
24 files changed, 514 insertions, 173 deletions
diff --git a/VERSION b/VERSION
index 52397008..93bd5449 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.19.9991
+2.19.9992
diff --git a/alpine/arg.c b/alpine/arg.c
index b256de62..592adb64 100644
--- a/alpine/arg.c
+++ b/alpine/arg.c
@@ -4,8 +4,8 @@ static char rcsid[] = "$Id: arg.c 900 2008-01-05 01:13:26Z hubert@u.washington.e
/*
* ========================================================================
- * Copyright 2006-2008 University of Washington
* Copyright 2013-2014 Eduardo Chappa
+ * Copyright 2006-2008 University of Washington
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1190,13 +1190,21 @@ pinerc_cmdline_opt(char *arg)
if(!arg || !arg[0])
return 0;
+ if((value = strchr(arg, '=')) != NULL){
+ i = value - arg;
+ arg[i] = '\0';
+ }
+ else
+ i = -1;
+
for(v = ps_global->vars; v->name != NULL; v++){
- if(v->is_used && struncmp(v->name, arg, strlen(v->name)) == 0){
+ if(v->is_used && strucmp(v->name, arg) == 0){
p1 = arg + strlen(v->name);
+ if(i > 0) arg[i] = '=';
- /*----- Skip to '=' -----*/
+ /*----- Skip to '=' -----*/
while(*p1 && (*p1 == '\t' || *p1 == ' '))
- p1++;
+ p1++;
if(*p1 != '='){
char buf[MAILTMPLEN];
@@ -1208,8 +1216,11 @@ pinerc_cmdline_opt(char *arg)
p1++;
break;
- }
+ }
}
+
+
+ if(i > 0) arg[i] = '=';
/* no match, check for a feature name used directly */
if(v->name == NULL){
diff --git a/alpine/conftype.h b/alpine/conftype.h
index f6d98704..6333c819 100644
--- a/alpine/conftype.h
+++ b/alpine/conftype.h
@@ -64,6 +64,7 @@ typedef struct conf_line {
struct smime_data {
WhichCerts ctype;
int deleted;
+ char address[MAILTMPLEN];
} s;
#endif /* SMIME */
struct context_and_screen {
diff --git a/alpine/mailpart.c b/alpine/mailpart.c
index 56ee8afa..0a7e1b5e 100644
--- a/alpine/mailpart.c
+++ b/alpine/mailpart.c
@@ -2704,6 +2704,9 @@ format_msg_att(long int msgno, ATTACH_S **a, HANDLE_S **handlesp, gf_io_t pc, in
&& gf_puts("text segment]", pc)
&& gf_puts(NEWLINE, pc)))
rv = 0;
+
+ ++(*a);
+
}
else if((*a)->body->subtype
&& strucmp((*a)->body->subtype, "external-body") == 0) {
diff --git a/alpine/osdep/mswin.rc b/alpine/osdep/mswin.rc
index 370044fe..97c7e06d 100644
--- a/alpine/osdep/mswin.rc
+++ b/alpine/osdep/mswin.rc
@@ -244,8 +244,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,19,9991,0
- PRODUCTVERSION 2,19,9991,0
+ FILEVERSION 2,19,9992,0
+ PRODUCTVERSION 2,19,9992,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -267,12 +267,12 @@ BEGIN
#else
VALUE "FileDescription", "Alpine\0"
#endif
- VALUE "FileVersion", "2.19.9991\0"
+ VALUE "FileVersion", "2.19.9992\0"
VALUE "InternalName", "alpine\0"
VALUE "LegalCopyright", "Copyright 2006-2009 University of Washington, Copyright 2013-2014\0"
VALUE "OriginalFilename", "alpine.exe\0"
VALUE "ProductName", "alpine\0"
- VALUE "ProductVersion", "2.19.9991\0"
+ VALUE "ProductVersion", "2.19.9992\0"
END
END
BLOCK "VarFileInfo"
diff --git a/alpine/smime.c b/alpine/smime.c
index caf0581a..2987d9bf 100644
--- a/alpine/smime.c
+++ b/alpine/smime.c
@@ -1211,12 +1211,12 @@ manage_certs_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned flags)
if(PATHCERTDIR(ctype) == NULL)
return 0;
- if((cert = get_cert_for((*cl)->value+3, ctype)) == NULL){
+ if((cert = get_cert_for((*cl)->d.s.address, ctype)) == NULL){
q_status_message(SM_ORDER, 1, 3, _("Problem Reading Certificate"));
rv = 0;
}
else{
- display_certificate_information(ps, cert, (*cl)->value+3, ctype, (*cl)->varmem);
+ display_certificate_information(ps, cert, (*cl)->d.s.address, ctype, (*cl)->varmem);
rv = 10 + (*cl)->varmem;
}
break;
@@ -1288,6 +1288,20 @@ manage_certs_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned flags)
return rv;
}
+void
+smime_setup_size(char **s, size_t n)
+{
+ char *t = *s;
+ *t++ = ' ';
+ *t++ = '%';
+ *t++ = '-';
+ sprintf(t+strlen(t), "%d.%d", n, n);
+ t += strlen(t);
+ *t++ = 's';
+ *t++ = ' ';
+ *s = t;
+}
+
void smime_manage_certs_init(struct pine *ps, CONF_S **ctmp, CONF_S **first_line, WhichCerts ctype, int fline)
{
char tmp[200];
@@ -1329,6 +1343,28 @@ void smime_manage_certs_init(struct pine *ps, CONF_S **ctmp, CONF_S **first_line
if(data){
CertList *cl; int i;
+ int s, e, df, dt, md5; /* sizes of certain fields */
+ int nf; /* number of fields */
+ char u[MAILTMPLEN], *t;
+
+ for(cl = data, e = 0; cl; cl = cl->next)
+ if(cl->name && strlen(cl->name) > e)
+ e = strlen(cl->name);
+
+ if(ctype != Private)
+ e -= 4; /* remove extension length */
+ nf = 5; /* there are 5 fields */
+ s = 3; /* status has fixed size */
+ df = dt = 8; /* date from and date to have fixed size */
+ md5 = ps->ttyo->screen_cols - s - df - dt - e - 2*nf;
+
+ memset(u, '\0', sizeof(u));
+ t = u;
+ smime_setup_size(&t, s);
+ smime_setup_size(&t, e);
+ smime_setup_size(&t, df);
+ smime_setup_size(&t, dt);
+ smime_setup_size(&t, md5);
for(cl = data, i = 0; cl; cl = cl->next)
if(cl->name){
@@ -1343,10 +1379,16 @@ void smime_manage_certs_init(struct pine *ps, CONF_S **ctmp, CONF_S **first_line
(*ctmp)->help = ctype == Public ? h_config_smime_manage_public_menu
: (ctype == Private ? h_config_smime_manage_private_menu
: h_config_smime_manage_cacerts_menu);
- snprintf(tmp, sizeof(tmp), " %s\t%s", (*ctmp)->d.s.deleted ? "D" : " ", cl->name);
+ if(ctype != Private)
+ cl->name[strlen(cl->name) - 4] = '\0';
+ strncpy((*ctmp)->d.s.address, cl->name, sizeof((*ctmp)->d.s.address));
+ (*ctmp)->d.s.address[sizeof((*ctmp)->d.s.address) - 1] = '\0';
+ snprintf(tmp, sizeof(tmp), u,
+ (*ctmp)->d.s.deleted ? "D" : " ",
+ cl->name, DATEFROMCERT(cl), DATETOCERT(cl), MD5CERT(cl));
+ if(ctype != Private)
+ cl->name[strlen(cl->name)] = '.';
(*ctmp)->value = cpystr(tmp);
- for(s = (*ctmp)->value; s && (t = strstr(s, ext)) != NULL; s = t+1);
- if(s) *(s-1) = '\0';
if(i == fline+1 && first_line && !*first_line)
*first_line = *ctmp;
}
diff --git a/configure b/configure
index 67d6ea38..4be02ec0 100755
--- a/configure
+++ b/configure
@@ -1,7 +1,7 @@
#! /bin/sh
# From configure.ac Rev:14 by chappa@washington.edu.
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for alpine 2.19.9991.
+# Generated by GNU Autoconf 2.69 for alpine 2.19.9992.
#
# Report bugs to <chappa@washington.edu>.
#
@@ -730,8 +730,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='alpine'
PACKAGE_TARNAME='alpine'
-PACKAGE_VERSION='2.19.9991'
-PACKAGE_STRING='alpine 2.19.9991'
+PACKAGE_VERSION='2.19.9992'
+PACKAGE_STRING='alpine 2.19.9992'
PACKAGE_BUGREPORT='chappa@washington.edu'
PACKAGE_URL=''
@@ -1596,7 +1596,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures alpine 2.19.9991 to adapt to many kinds of systems.
+\`configure' configures alpine 2.19.9992 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1666,7 +1666,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of alpine 2.19.9991:";;
+ short | recursive ) echo "Configuration of alpine 2.19.9992:";;
esac
cat <<\_ACEOF
@@ -1953,7 +1953,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-alpine configure 2.19.9991
+alpine configure 2.19.9992
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2559,7 +2559,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by alpine $as_me 2.19.9991, which was
+It was created by alpine $as_me 2.19.9992, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3380,7 +3380,7 @@ fi
# Define the identity of the package.
PACKAGE='alpine'
- VERSION='2.19.9991'
+ VERSION='2.19.9992'
cat >>confdefs.h <<_ACEOF
@@ -15652,6 +15652,8 @@ fi
if test "x$with_ssl" = "xno" ; then
alpine_SSLTYPE="none"
+elif test -d /usr/local/ssl ; then
+ alpine_SSLDIR="/usr/local/ssl"
else
case $host in
*-linux-gnu*)
@@ -15720,6 +15722,8 @@ else
alpine_SSLLIB="/sw/lib"
alpine_SSLCERTS="/sw/etc/ssl/certs"
alpine_SSLKEYS="/sw/etc/ssl/private"
+ elif test -d /usr/local/ssl ; then
+ alpine_SSLDIR="/usr/local/ssl"
elif test -d /System/Library/OpenSSL ; then
alpine_SSLDIR="/System/Library/OpenSSL"
alpine_SSLCERTS="$alpine_SSLDIR/certs"
@@ -15751,8 +15755,13 @@ else
alpine_SSLDIR="/etc/ssl"
alpine_SSLCERTS="$alpine_SSLDIR/certs"
alpine_SSLKEYS="$alpine_SSLDIR/private"
- alpine_SSLINCLUDE="/usr/include/openssl"
- alpine_SSLLIB="/usr/lib"
+ if test -d /usr/local/include/openssl ; then
+ alpine_SSLINCLUDE="/usr/local/include/openssl"
+ alpine_SSLLIB="/usr/local/lib"
+ else
+ alpine_SSLINCLUDE="/usr/include/openssl"
+ alpine_SSLLIB="/usr/lib"
+ fi
;;
*-*-openbsd*)
alpine_SSLDIR="/etc/ssl"
@@ -20355,7 +20364,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by alpine $as_me 2.19.9991, which was
+This file was extended by alpine $as_me 2.19.9992, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -20421,7 +20430,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-alpine config.status 2.19.9991
+alpine config.status 2.19.9992
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 672a0bdb..5796364f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -715,6 +715,11 @@ AC_ARG_WITH(ssl,
if test "x$with_ssl" = "xno" ; then
alpine_SSLTYPE="none"
+elif test -d /usr/local/ssl ; then
+dnl When the system has openssl installed in its default location
+dnl instead of the one used by the distribution assume that this
+dnl is the one intended to be used.
+ alpine_SSLDIR="/usr/local/ssl"
else
dnl preload c-client default locations/options
case $host in
@@ -787,6 +792,8 @@ dnl find it anywhere else.
alpine_SSLLIB="/sw/lib"
alpine_SSLCERTS="/sw/etc/ssl/certs"
alpine_SSLKEYS="/sw/etc/ssl/private"
+ elif test -d /usr/local/ssl ; then
+ alpine_SSLDIR="/usr/local/ssl"
elif test -d /System/Library/OpenSSL ; then
alpine_SSLDIR="/System/Library/OpenSSL"
alpine_SSLCERTS="$alpine_SSLDIR/certs"
@@ -818,8 +825,13 @@ dnl find it anywhere else.
alpine_SSLDIR="/etc/ssl"
alpine_SSLCERTS="$alpine_SSLDIR/certs"
alpine_SSLKEYS="$alpine_SSLDIR/private"
- alpine_SSLINCLUDE="/usr/include/openssl"
- alpine_SSLLIB="/usr/lib"
+ if test -d /usr/local/include/openssl ; then
+ alpine_SSLINCLUDE="/usr/local/include/openssl"
+ alpine_SSLLIB="/usr/local/lib"
+ else
+ alpine_SSLINCLUDE="/usr/include/openssl"
+ alpine_SSLLIB="/usr/lib"
+ fi
;;
*-*-openbsd*)
alpine_SSLDIR="/etc/ssl"
diff --git a/doc/alpine.1 b/doc/alpine.1
index a0e78957..52d8140c 100644
--- a/doc/alpine.1
+++ b/doc/alpine.1
@@ -1,4 +1,4 @@
-.TH alpine 1 "Version 2.19.9991"
+.TH alpine 1 "Version 2.19.9992"
.SH NAME
alpine \- an Alternatively Licensed Program for Internet News and Email
.SH SYNTAX
diff --git a/doc/tech-notes/index.html b/doc/tech-notes/index.html
index 3ec86306..78e9d2aa 100644
--- a/doc/tech-notes/index.html
+++ b/doc/tech-notes/index.html
@@ -3,7 +3,7 @@
<BODY>
<H1>Alpine Technical Notes</H1>
-Version 2.19.9991, May 2014
+Version 2.19.9992, June 2014
<H2><A NAME="TOC">Table of Contents</A></H2><P>
diff --git a/doc/tech-notes/tech-notes.txt b/doc/tech-notes/tech-notes.txt
index 356e49c5..885789eb 100644
--- a/doc/tech-notes/tech-notes.txt
+++ b/doc/tech-notes/tech-notes.txt
@@ -1,7 +1,7 @@
Alpine Technical Notes
- Version 2.19.9991, May 2014
+ Version 2.19.9992, June 2014
Table of Contents
diff --git a/imap/src/c-client/rfc822.c b/imap/src/c-client/rfc822.c
index 03e92ca3..93663e65 100644
--- a/imap/src/c-client/rfc822.c
+++ b/imap/src/c-client/rfc822.c
@@ -1,4 +1,5 @@
/* ========================================================================
+ * Copyright 2013-2014 Eduardo Chappa
* Copyright 2008-2010 Mark Crispin
* ========================================================================
*/
@@ -36,6 +37,10 @@
#include "c-client.h"
+/* internal prototype */
+void initialize_body(BODY *b, char *h, char *t);
+
+
/* Support for deprecated features in earlier specifications. Note that this
* module follows RFC 2822, and all use of "rfc822" in function names is
* for compatibility. Only the code identified by the conditionals below
@@ -259,6 +264,23 @@ void rfc822_parse_msg_full (ENVELOPE **en,BODY **bdy,char *s,unsigned long i,
/* now parse the body */
if (body) rfc822_parse_content (body,bs,host,depth,flags);
}
+
+void
+initialize_body(BODY *b, char *h, char *t)
+{
+ if(b->type==TYPEMULTIPART){
+ PART *p;
+ cpytxt(&b->mime.text, h+b->mime.offset, b->mime.text.size);
+ cpytxt(&b->contents.text, t + b->contents.offset, b->size.bytes);
+
+ for(p=b->nested.part; p; p=p->next)
+ initialize_body((BODY *)p, h, t);
+ }
+ else {
+ cpytxt(&b->mime.text, h+b->mime.offset, b->mime.text.size);
+ cpytxt(&b->contents.text, t + b->contents.offset, b->size.bytes);
+ }
+}
/* Parse a message body content
* Accepts: pointer to body structure
@@ -337,33 +359,65 @@ void rfc822_parse_content (BODY *body,STRING *bs,char *h,unsigned long depth,
case ENC7BIT: /* these are valid nested encodings */
case ENC8BIT:
case ENCBINARY:
+ case ENCBASE64: /* message/rfc822 message encoded as base64 */
break;
default:
MM_LOG ("Ignoring nested encoding of message contents",PARSE);
}
- /* hunt for blank line */
+
for (c = '\012',j = 0; (i > j) && ((c != '\012') || (CHR(bs) != '\012'));
j++) if ((c1 = SNX (bs)) != '\015') c = c1;
- if (i > j) { /* unless no more text */
- c1 = SNX (bs); /* body starts here */
- j++; /* advance count */
+
+ switch(body->encoding){
+ case ENCBASE64:
+ SETPOS (bs,body->contents.offset);
+ s = (char *) fs_get ((size_t) j + 1);
+ for (s1 = s,k = j; k--; *s1++ = SNX (bs));
+ s[j] = '\0'; /* decode encoded text */
+ if((s1 = strstr(s, "--")) != NULL)
+ *(s1-2) = '\0';
+ s1 = (char *) rfc822_base64 (s, strlen(s), &k);
+ if(s1){
+ char *t = strstr(s1, "\r\n\r\n");
+
+ if(t != NULL){
+ char *u;
+ STRING b;
+
+ t += 4;
+ u = cpystr(t);
+ INIT(&b, mail_string, t, strlen(t));
+ rfc822_parse_msg_full(&body->nested.msg->env, &body->nested.msg->body, t,
+ strlen(t), &b, BADHOST, 0, 0);
+ initialize_body(body->nested.msg->body, u, u);
+ }
+ fs_give((void **)&s1);
+ }
+ fs_give((void **)&s);
+ break;
+
+ default:
+ if (i > j) { /* unless no more text */
+ c1 = SNX (bs); /* body starts here */
+ j++; /* advance count */
+ }
+ /* note body text offset and header size */
+ body->nested.msg->header.text.size = j;
+ body->nested.msg->text.text.size = body->contents.text.size - j;
+ body->nested.msg->text.offset = GETPOS (bs);
+ body->nested.msg->full.offset = body->nested.msg->header.offset =
+ body->contents.offset;
+ body->nested.msg->full.text.size = body->contents.text.size;
+ /* copy header string */
+ SETPOS (bs,body->contents.offset);
+ s = (char *) fs_get ((size_t) j + 1);
+ for (s1 = s,k = j; k--; *s1++ = SNX (bs));
+ s[j] = '\0'; /* tie off string (not really necessary) */
+ /* now parse the body */
+ rfc822_parse_msg_full (&body->nested.msg->env,&body->nested.msg->body,s,
+ j,bs,h,depth+1,flags);
+ fs_give ((void **) &s); /* free header string */
}
- /* note body text offset and header size */
- body->nested.msg->header.text.size = j;
- body->nested.msg->text.text.size = body->contents.text.size - j;
- body->nested.msg->text.offset = GETPOS (bs);
- body->nested.msg->full.offset = body->nested.msg->header.offset =
- body->contents.offset;
- body->nested.msg->full.text.size = body->contents.text.size;
- /* copy header string */
- SETPOS (bs,body->contents.offset);
- s = (char *) fs_get ((size_t) j + 1);
- for (s1 = s,k = j; k--; *s1++ = SNX (bs));
- s[j] = '\0'; /* tie off string (not really necessary) */
- /* now parse the body */
- rfc822_parse_msg_full (&body->nested.msg->env,&body->nested.msg->body,s,
- j,bs,h,depth+1,flags);
- fs_give ((void **) &s); /* free header string */
/* restore position */
SETPOS (bs,body->contents.offset);
}
diff --git a/mapi/pmapi.c b/mapi/pmapi.c
index 036e19ef..acbc2d5b 100644
--- a/mapi/pmapi.c
+++ b/mapi/pmapi.c
@@ -1952,7 +1952,7 @@ BOOL APIENTRY DllMain(
now = time((time_t *)0);
tm_now = localtime(&now);
- fprintf(ms_global->dfd, "pmapi32.dll for Alpine Version 2.19.9991\r\n");
+ fprintf(ms_global->dfd, "pmapi32.dll for Alpine Version 2.19.9992\r\n");
fprintf(ms_global->dfd, " Build date: %s\r\n", datestamp);
fprintf(ms_global->dfd,
" please report all bugs to chappa@gmx.com\r\n");
diff --git a/mapi/pmapi.rc b/mapi/pmapi.rc
index 815a7a4e..31505bfc 100644
--- a/mapi/pmapi.rc
+++ b/mapi/pmapi.rc
@@ -98,8 +98,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,19,9991,0
- PRODUCTVERSION 2,19,9991,0
+ FILEVERSION 2,19,9992,0
+ PRODUCTVERSION 2,19,9992,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x29L
@@ -117,14 +117,14 @@ BEGIN
VALUE "Comments", "alpine info: http://patches.freeiz.com/alpine\0"
VALUE "CompanyName", "Patches for Alpine\0"
VALUE "FileDescription", "Simple MAPI DLL for Alpine for Windows\0"
- VALUE "FileVersion", "2.19.9991\0"
+ VALUE "FileVersion", "2.19.9992\0"
VALUE "InternalName", "pmapi32\0"
VALUE "LegalCopyright", "Copyright ? University of Washington 2006-2009, Eduardo Chappa 2013-2014\0"
VALUE "LegalTrademarks", "Apache License, Version 2.0\0"
VALUE "OriginalFilename", "pmapi32.dll\0"
VALUE "PrivateBuild", " \0"
VALUE "ProductName", "Simple MAPI for Alpine for Windows\0"
- VALUE "ProductVersion", "2.19.9991\0"
+ VALUE "ProductVersion", "2.19.9992\0"
VALUE "SpecialBuild", " \0"
END
END
diff --git a/pith/conftype.h b/pith/conftype.h
index 8ba7941c..11bf778f 100644
--- a/pith/conftype.h
+++ b/pith/conftype.h
@@ -676,6 +676,9 @@ typedef enum {Public, Private, CACert} WhichCerts;
typedef struct certdata {
unsigned deleted:1; /* certificate is marked deleted */
unsigned renew:1; /* we must renew this list, set at top cert */
+ char *date_from; /* date from which certificate is valid */
+ char *date_to; /* date certificate expires */
+ char *md5; /* MD5 Hash */
} CertData;
typedef struct certlist {
@@ -740,8 +743,11 @@ typedef struct smime_stuff {
: ((X) == Private ? ".key" \
: ((X) == CACert ? ".crt" : ""))))
-#define DELETEDCERT(X) ((X)->data.deleted)
-#define RENEWCERT(X) ((X)->data.renew)
+#define DELETEDCERT(X) ((X)->data.deleted)
+#define RENEWCERT(X) ((X)->data.renew)
+#define DATEFROMCERT(X) ((X)->data.date_from)
+#define DATETOCERT(X) ((X)->data.date_to)
+#define MD5CERT(X) ((X)->data.md5)
#endif /* SMIME */
diff --git a/pith/filter.c b/pith/filter.c
index c60416b1..d1848f87 100644
--- a/pith/filter.c
+++ b/pith/filter.c
@@ -2803,8 +2803,10 @@ typedef struct handler_s {
*/
typedef struct _element_properties {
char *element;
+ size_t len;
int (*handler)(HANDLER_S *, int, int);
unsigned blocklevel:1;
+ unsigned alternate:1;
} ELPROP_S;
/*
@@ -3549,96 +3551,96 @@ static struct html_entities {
* Table of supported elements and corresponding handlers
*/
static ELPROP_S html_element_table[] = {
- {"HTML"}, /* HTML ignore if seen? */
- {"HEAD", html_head}, /* slurp until <BODY> ? */
- {"TITLE", html_title}, /* Document Title */
- {"BASE", html_base}, /* HREF base */
- {"BODY", html_body}, /* HTML BODY */
- {"A", html_a}, /* Anchor */
- {"ABBR", html_abbr}, /* Abbreviation */
- {"IMG", html_img}, /* Image */
- {"MAP", html_map}, /* Image Map */
- {"AREA", html_area}, /* Image Map Area */
- {"HR", html_hr, 1}, /* Horizontal Rule */
- {"BR", html_br}, /* Line Break */
- {"P", html_p, 1}, /* Paragraph */
- {"OL", html_ol, 1}, /* Ordered List */
- {"UL", html_ul, 1}, /* Unordered List */
- {"MENU", html_menu}, /* Menu List */
- {"DIR", html_dir}, /* Directory List */
- {"LI", html_li}, /* ... List Item */
- {"DL", html_dl, 1}, /* Definition List */
- {"DT", html_dt}, /* ... Def. Term */
- {"DD", html_dd}, /* ... Def. Definition */
- {"I", html_i}, /* Italic Text */
- {"EM", html_em}, /* Typographic Emphasis */
- {"STRONG", html_strong}, /* STRONG Typo Emphasis */
- {"VAR", html_i}, /* Variable Name */
- {"B", html_b}, /* Bold Text */
- {"U", html_u}, /* Underline Text */
- {"S", html_s}, /* Strike-Through Text */
- {"STRIKE", html_s}, /* Strike-Through Text */
- {"BIG", html_big}, /* Big Font Text */
- {"SMALL", html_small}, /* Small Font Text */
- {"FONT", html_font}, /* Font display directives */
- {"BLOCKQUOTE", html_blockquote, 1}, /* Blockquote */
- {"ADDRESS", html_address, 1}, /* Address */
- {"CENTER", html_center}, /* Centered Text v3.2 */
- {"DIV", html_div, 1}, /* Document Division 3.2 */
- {"SPAN", html_span}, /* Text Span */
- {"H1", html_h1, 1}, /* Headings... */
- {"H2", html_h2, 1},
- {"H3", html_h3,1},
- {"H4", html_h4, 1},
- {"H5", html_h5, 1},
- {"H6", html_h6, 1},
- {"PRE", html_pre, 1}, /* Preformatted Text */
- {"KBD", html_kbd}, /* Keyboard Input (NO OP) */
- {"DFN", html_dfn}, /* Definition (NO OP) */
- {"VAR", html_var}, /* Variable (NO OP) */
- {"TT", html_tt}, /* Typetype (NO OP) */
- {"SAMP", html_samp}, /* Sample Text (NO OP) */
- {"CITE", html_cite}, /* Citation (NO OP) */
- {"CODE", html_code}, /* Code Text (NO OP) */
- {"INS", html_ins}, /* Text Inseted (NO OP) */
- {"DEL", html_del}, /* Text Deleted (NO OP) */
- {"SUP", html_sup}, /* Text Superscript (NO OP) */
- {"SUB", html_sub}, /* Text Superscript (NO OP) */
- {"STYLE", html_style}, /* CSS Definitions */
+ {"HTML", 4}, /* HTML ignore if seen? */
+ {"HEAD", 4, html_head}, /* slurp until <BODY> ? */
+ {"TITLE", 5, html_title}, /* Document Title */
+ {"BASE", 4, html_base}, /* HREF base */
+ {"BODY", 4, html_body}, /* HTML BODY */
+ {"A", 1, html_a}, /* Anchor */
+ {"ABBR", 4, html_abbr}, /* Abbreviation */
+ {"IMG", 3, html_img}, /* Image */
+ {"MAP", 3, html_map}, /* Image Map */
+ {"AREA", 4, html_area}, /* Image Map Area */
+ {"HR", 2, html_hr, 1, 1}, /* Horizontal Rule */
+ {"BR", 2, html_br, 0, 1}, /* Line Break */
+ {"P", 1, html_p, 1}, /* Paragraph */
+ {"OL", 2, html_ol, 1}, /* Ordered List */
+ {"UL", 2, html_ul, 1}, /* Unordered List */
+ {"MENU", 4, html_menu}, /* Menu List */
+ {"DIR", 3, html_dir}, /* Directory List */
+ {"LI", 2, html_li}, /* ... List Item */
+ {"DL", 2, html_dl, 1}, /* Definition List */
+ {"DT", 2, html_dt}, /* ... Def. Term */
+ {"DD", 2, html_dd}, /* ... Def. Definition */
+ {"I", 1, html_i}, /* Italic Text */
+ {"EM", 2, html_em}, /* Typographic Emphasis */
+ {"STRONG", 6, html_strong}, /* STRONG Typo Emphasis */
+ {"VAR", 3, html_i}, /* Variable Name */
+ {"B", 1, html_b}, /* Bold Text */
+ {"U", 1, html_u}, /* Underline Text */
+ {"S", 1, html_s}, /* Strike-Through Text */
+ {"STRIKE", 6, html_s}, /* Strike-Through Text */
+ {"BIG", 3, html_big}, /* Big Font Text */
+ {"SMALL", 5, html_small}, /* Small Font Text */
+ {"FONT", 4, html_font}, /* Font display directives */
+ {"BLOCKQUOTE", 10, html_blockquote, 1}, /* Blockquote */
+ {"ADDRESS", 7, html_address, 1}, /* Address */
+ {"CENTER", 6, html_center}, /* Centered Text v3.2 */
+ {"DIV", 3, html_div, 1}, /* Document Division 3.2 */
+ {"SPAN", 4, html_span}, /* Text Span */
+ {"H1", 2, html_h1, 1}, /* Headings... */
+ {"H2", 2, html_h2, 1},
+ {"H3", 2, html_h3,1},
+ {"H4", 2, html_h4, 1},
+ {"H5", 2, html_h5, 1},
+ {"H6", 2, html_h6, 1},
+ {"PRE", 3, html_pre, 1}, /* Preformatted Text */
+ {"KBD", 3, html_kbd}, /* Keyboard Input (NO OP) */
+ {"DFN", 3, html_dfn}, /* Definition (NO OP) */
+ {"VAR", 3, html_var}, /* Variable (NO OP) */
+ {"TT", 2, html_tt}, /* Typetype (NO OP) */
+ {"SAMP", 4, html_samp}, /* Sample Text (NO OP) */
+ {"CITE", 4, html_cite}, /* Citation (NO OP) */
+ {"CODE", 4, html_code}, /* Code Text (NO OP) */
+ {"INS", 3, html_ins}, /* Text Inseted (NO OP) */
+ {"DEL", 3, html_del}, /* Text Deleted (NO OP) */
+ {"SUP", 3, html_sup}, /* Text Superscript (NO OP) */
+ {"SUB", 3, html_sub}, /* Text Superscript (NO OP) */
+ {"STYLE", 5, html_style}, /* CSS Definitions */
/*----- Handlers below UNIMPLEMENTED (and won't until later) -----*/
- {"FORM", html_form, 1}, /* form within a document */
- {"INPUT", html_input}, /* One input field, options */
- {"BUTTON", html_button}, /* Push Button */
- {"OPTION", html_option}, /* One option within Select */
- {"OPTION", html_optgroup}, /* Option Group Definition */
- {"SELECT", html_select}, /* Selection from a set */
- {"TEXTAREA", html_textarea}, /* A multi-line input field */
- {"LABEL", html_label}, /* Control Label */
- {"FIELDSET", html_fieldset, 1}, /* Fieldset Control Group */
+ {"FORM", 4, html_form, 1}, /* form within a document */
+ {"INPUT", 5, html_input}, /* One input field, options */
+ {"BUTTON", 6, html_button}, /* Push Button */
+ {"OPTION", 6, html_option}, /* One option within Select */
+ {"OPTION", 6, html_optgroup}, /* Option Group Definition */
+ {"SELECT", 6, html_select}, /* Selection from a set */
+ {"TEXTAREA", 8, html_textarea}, /* A multi-line input field */
+ {"LABEL", 5, html_label}, /* Control Label */
+ {"FIELDSET", 8, html_fieldset, 1}, /* Fieldset Control Group */
/*----- Handlers below NEVER TO BE IMPLEMENTED -----*/
- {"SCRIPT", html_script}, /* Embedded scripting statements */
- {"APPLET", NULL}, /* Embedded applet statements */
- {"OBJECT", NULL}, /* Embedded object statements */
- {"LINK", NULL}, /* References to external data */
- {"PARAM", NULL}, /* Applet/Object parameters */
+ {"SCRIPT", 6, html_script}, /* Embedded scripting statements */
+ {"APPLET", 6, NULL}, /* Embedded applet statements */
+ {"OBJECT", 6, NULL}, /* Embedded object statements */
+ {"LINK", 4, NULL}, /* References to external data */
+ {"PARAM", 5, NULL}, /* Applet/Object parameters */
/*----- Handlers below provide limited support for RFC 1942 Tables -----*/
- {"TABLE", html_table, 1}, /* Table */
- {"CAPTION", html_caption}, /* Table Caption */
- {"TR", html_tr}, /* Table Table Row */
- {"TD", html_td}, /* Table Table Data */
- {"TH", html_th}, /* Table Table Head */
- {"THEAD", html_thead}, /* Table Table Head */
- {"TBODY", html_tbody}, /* Table Table Body */
- {"TFOOT", html_tfoot}, /* Table Table Foot */
- {"COL", html_col}, /* Table Column Attibutes */
- {"COLGROUP", html_colgroup}, /* Table Column Group Attibutes */
-
- {NULL, NULL}
+ {"TABLE", 5, html_table, 1}, /* Table */
+ {"CAPTION", 7, html_caption}, /* Table Caption */
+ {"TR", 2, html_tr}, /* Table Table Row */
+ {"TD", 2, html_td}, /* Table Table Data */
+ {"TH", 2, html_th}, /* Table Table Head */
+ {"THEAD", 5, html_thead}, /* Table Table Head */
+ {"TBODY", 5, html_tbody}, /* Table Table Body */
+ {"TFOOT", 5, html_tfoot}, /* Table Table Foot */
+ {"COL", 3, html_col}, /* Table Column Attibutes */
+ {"COLGROUP", 8, html_colgroup}, /* Table Column Group Attibutes */
+
+ {NULL, 0, NULL}
};
@@ -3646,15 +3648,15 @@ static ELPROP_S html_element_table[] = {
* Table of supported RSS 2.0 elements
*/
static ELPROP_S rss_element_table[] = {
- {"RSS", rss_rss}, /* RSS 2.0 version */
- {"CHANNEL", rss_channel}, /* RSS 2.0 Channel */
- {"TITLE", rss_title}, /* RSS 2.0 Title */
- {"IMAGE", rss_image}, /* RSS 2.0 Channel Image */
- {"LINK", rss_link}, /* RSS 2.0 Channel/Item Link */
- {"DESCRIPTION", rss_description}, /* RSS 2.0 Channel/Item Description */
- {"ITEM", rss_item}, /* RSS 2.0 Channel ITEM */
- {"TTL", rss_ttl}, /* RSS 2.0 Item TTL */
- {NULL, NULL}
+ {"RSS", 3, rss_rss}, /* RSS 2.0 version */
+ {"CHANNEL", 7, rss_channel}, /* RSS 2.0 Channel */
+ {"TITLE", 5, rss_title}, /* RSS 2.0 Title */
+ {"IMAGE", 5, rss_image}, /* RSS 2.0 Channel Image */
+ {"LINK", 4, rss_link}, /* RSS 2.0 Channel/Item Link */
+ {"DESCRIPTION", 11, rss_description}, /* RSS 2.0 Channel/Item Description */
+ {"ITEM", 4, rss_item}, /* RSS 2.0 Channel ITEM */
+ {"TTL", 3, rss_ttl}, /* RSS 2.0 Item TTL */
+ {NULL, 0, NULL}
};
@@ -7167,9 +7169,14 @@ ELPROP_S *
element_properties(FILTER_S *fd, char *el_name)
{
register ELPROP_S *el_table = ELEMENTS(fd);
+ size_t len_name = strlen(el_name);
for(; el_table->element; el_table++)
- if(!strucmp(el_name, el_table->element))
+ if(!strucmp(el_name, el_table->element)
+ || (el_table->alternate
+ && len_name == el_table->len + 1
+ && el_name[el_table->len] == '/'
+ && !struncmp(el_name, el_table->element, el_table->len)))
return(el_table);
return(NULL);
@@ -7427,6 +7434,24 @@ html_element_collector(FILTER_S *fd, int ch)
if(!ED(fd)->hit_equal)
ED(fd)->hit_equal = (ch == '=');
}
+ else if(ch == '/' && ED(fd)->len && !ED(fd)->element){
+ ELPROP_S *ep;
+ ep = element_properties(fd, ED(fd)->buf);
+ if(ep){
+ if(!ep->alternate)
+ ED(fd)->badform = 1;
+ else{
+ if(ED(fd)->len < ((ED(fd)->element || !ED(fd)->hit_equal)
+ ? HTML_BUF_LEN:MAX_ELEMENT)){
+ ED(fd)->buf[(ED(fd)->len)++] = ch; /* add this exception */
+ }
+ else
+ ED(fd)->overrun = 1;
+ }
+ }
+ else
+ ED(fd)->badform = 1;
+ }
else
ED(fd)->badform = 1; /* unrecognized data?? */
diff --git a/pith/mimedesc.c b/pith/mimedesc.c
index 8a1d7f7d..67d52ae6 100644
--- a/pith/mimedesc.c
+++ b/pith/mimedesc.c
@@ -277,7 +277,7 @@ describe_mime(struct mail_bodystruct *body, char *prefix, int num,
snprintf(a->number, ll, "%s%d",prefix, num);
a->number[ll-1] = '\0';
(a+1)->description = NULL;
- if(body->type == TYPEMESSAGE && body->encoding <= ENCBINARY
+ if(body->type == TYPEMESSAGE && body->encoding <= ENCBASE64
&& body->subtype && strucmp(body->subtype, "rfc822") == 0){
body = body->nested.msg->body;
snprintf(numx, sizeof(numx), "%.*s%d.", sizeof(numx)-20, prefix, num);
diff --git a/pith/pine.hlp b/pith/pine.hlp
index 90be0132..cb0a6d63 100644
--- a/pith/pine.hlp
+++ b/pith/pine.hlp
@@ -140,7 +140,7 @@ with help text for the config screen and the composer that didn't have any
reasonable place to be called from.
Dummy change to get revision in pine.hlp
============= h_revision =================
-Alpine Commit 64 2014-05-31 21:36:57
+Alpine Commit 65 2014-06-20 23:23:15
============= h_news =================
<HTML>
<HEAD>
@@ -205,6 +205,10 @@ Additions include:
<LI> S/MIME: Forwarding a message will include the signed part as part
of the text and not as a multipart message, just as the reply
command does.
+ <LI> HTML: Style tag in body of html message causes Alpine to not write
+ its content until a new &lt;/style&gt;
+ <LI> HTML: &lt;BR&gt;, &lt;BR /&gt;, and &lt;BR/&gt; are considered
+ the same inline tag; the same is valid for the &lt;HR&gt; tag.
<LI> Add support to selective expunge through a subcommand of the
select-apply commands. Read more in the <A
HREF="h_index_cmd_expunge">help</A> for the expunge command.
@@ -296,6 +300,10 @@ Bugs that have been addressed include:
an index was based on scores that needed information from a remote
addressbook in the same server as the folder opened. Reported by
Peter Koellner.
+ <LI> Crash in message/rfc822 attachments encoded in base64.
+ <LI> Postponed messages whose content-type is text/html, text/enriched and
+ text/richtext are sent with that content-type, even though, after
+ resuming composition, Alpine had changed its type to text/plain.
<LI> Alpine cannot handle correctly some characters in the Windows-1256
character set, which might lead to a crash or a corruption in the
screen. Work was done to contain the bug. A more complete fix will
@@ -35154,8 +35162,20 @@ and private information about your key, with the <B>B</B> and
UNIX Alpine only.
<P>
-This screen allows you to manage your public certificates. Available commands and
-a short description of what they do follows.
+This screen allows you to manage your public certificates.
+<P>
+The format of this screen is as follows. There are five fields: The
+leftmost field is normally empty, but it could contain the letter
+&quot;D&quot; to indicate that that certificate has been marked for
+deletion. The next field is the e-mail address of the owner of the
+certificate, shown in its entirety. The third field is the first day of
+validity for that certificate; the fourth field in the last day that that
+certificate is valid, and the fifth field is what can be displayed of the
+MD5 hash of the certificate. You can use any of the last three fields to
+distinguish between two certificates for the same owner.
+<P>
+Available commands in this screen and a short description of what they
+do follows.
<UL>
<LI> <B>I</B> Imports a public certificate to this collection.
<LI> <B>V</B> View information about a certificate such as the name of the person the
@@ -35189,8 +35209,20 @@ All commands provide feedback to let you know about their success or failure.
UNIX Alpine only.
<P>
-This screen allows you to manage your private key. Available commands and
-a short description of what they do follows.
+This screen allows you to manage your private key.
+<P>
+The format of this screen is as follows. There are five fields: The
+leftmost field is normally empty, but it could contain the letter
+&quot;D&quot; to indicate that that certificate has been marked for
+deletion. The next field is the e-mail address of the owner of the
+certificate, shown in its entirety. The third field is the first day of
+validity for that certificate; the fourth field in the last day that that
+certificate is valid, and the fifth field is what can be displayed of the
+MD5 hash of the public certificate corresponding to this private key. You
+can use any of the last three fields to distinguish between two
+certificates for the same owner.
+<P>
+Available commands and a short description of what they do follows.
<UL>
<LI> <B>I</B> Imports a new public key to this collection.
<LI> <B>V</B> View information about the public certificate corresponding to this
@@ -35225,7 +35257,19 @@ All commands provide feedback to let you know about their success or failure.
UNIX Alpine only.
<P>
This screen allows you to manage your collection of certificates that you
-trust. Available commands and a short description of what they do follows.
+trust.
+<P>
+The format of this screen is as follows. There are five fields: The
+leftmost field is normally empty, but it could contain the letter
+&quot;D&quot; to indicate that that certificate has been marked for
+deletion. The next field is the e-mail address of the owner of the
+certificate, shown in its entirety. The third field is the first day of
+validity for that certificate; the fourth field in the last day that that
+certificate is valid, and the fifth field is what can be displayed of the
+MD5 hash of the certificate. You can use any of the last three fields to
+distinguish between two certificates for the same owner.
+<P>
+Available commands and a short description of what they do follows.
<UL>
<LI> <B>I</B> Imports a trusted certificate to this collection. This is
done by reading the certificate and validating it. Once a certificate
diff --git a/pith/reply.c b/pith/reply.c
index 2a8ab158..ec8293db 100644
--- a/pith/reply.c
+++ b/pith/reply.c
@@ -46,9 +46,7 @@ static char rcsid[] = "$Id: reply.c 1074 2008-06-04 00:08:43Z hubert@u.washingto
#include "../pith/ablookup.h"
#include "../pith/mailcmd.h"
#include "../pith/margin.h"
-#ifdef SMIME
#include "../pith/smime.h"
-#endif /* SMIME */
/*
diff --git a/pith/send.c b/pith/send.c
index b01ff7e5..e829d19c 100644
--- a/pith/send.c
+++ b/pith/send.c
@@ -890,7 +890,10 @@ redraft_work(MAILSTREAM **streamp, long int cont_msg, ENVELOPE **outgoing,
else{
*body = mail_newbody();
(*body)->type = TYPETEXT;
- if(b->subtype)
+ if(b->subtype /* these types are transformed to text/plain */
+ && strucmp(b->subtype, "richtext")
+ && strucmp(b->subtype, "enriched")
+ && strucmp(b->subtype, "html"))
(*body)->subtype = cpystr(b->subtype);
if((charset = parameter_val(b->parameter,"charset")) != NULL){
diff --git a/pith/smime.c b/pith/smime.c
index 44cc1955..f29e37df 100644
--- a/pith/smime.c
+++ b/pith/smime.c
@@ -903,6 +903,8 @@ CertList *
certlist_from_personal_certs(PERSONAL_CERT *pc)
{
CertList *cl;
+ X509 *x;
+ char buf[MAXPATH];
if(pc == NULL)
return NULL;
@@ -910,12 +912,21 @@ certlist_from_personal_certs(PERSONAL_CERT *pc)
cl = fs_get(sizeof(CertList));
memset((void *)cl, 0, sizeof(CertList));
cl->name = cpystr(pc->name);
+ x = get_cert_for(pc->name, Public);
+ if(x){
+ if(x->cert_info){
+ cl->data.date_from = smime_get_date(x->cert_info->validity->notBefore);
+ cl->data.date_to = smime_get_date(x->cert_info->validity->notAfter);
+ get_fingerprint(x, EVP_md5(), buf, sizeof(buf), NULL);
+ cl->data.md5 = cpystr(buf);
+ }
+ X509_free(x);
+ }
cl->next = certlist_from_personal_certs(pc->next);
return cl;
}
-
void
renew_cert_data(CertList **data, WhichCerts ctype)
{
@@ -928,8 +939,10 @@ renew_cert_data(CertList **data, WhichCerts ctype)
free_personal_certs(&pc);
setup_privatekey_storage();
*data = certlist_from_personal_certs((PERSONAL_CERT *)ps_global->smime->personal_certs);
- if(data && *data)
+ if(data && *data){
+ resort_certificates(data, ctype);
RENEWCERT(*data) = 0;
+ }
ps_global->smime->privatecertlist = *data;
}
if(ps_global->smime->privatecertlist)
@@ -948,8 +961,10 @@ renew_cert_data(CertList **data, WhichCerts ctype)
add_certs_in_dir(lookup, PATHCERTDIR(ctype), EXTCERT(ctype), data);
else /* if(SMHOLDERTYPE(ctype) == Container) */
*data = mem_to_certlist(CONTENTCERTLIST(ctype), ctype);
- if(data && *data)
+ if(data && *data){
+ resort_certificates(data, ctype);
RENEWCERT(*data) = 0;
+ }
if(ctype == Public)
ps_global->smime->publiccertlist = *data;
else
diff --git a/pith/smkeys.c b/pith/smkeys.c
index 18ed6f1b..437cba6f 100644
--- a/pith/smkeys.c
+++ b/pith/smkeys.c
@@ -32,6 +32,7 @@ static char rcsid[] = "$Id: smkeys.c 1266 2009-07-14 18:39:12Z hubert@u.washingt
#include "../pith/busy.h"
#include "../pith/osdep/lstcmpnt.h"
#include "../pith/util.h"
+#include "../pith/mailindx.h"
#include "smkeys.h"
#ifdef APPLEKEYCHAIN
@@ -45,6 +46,57 @@ static char rcsid[] = "$Id: smkeys.c 1266 2009-07-14 18:39:12Z hubert@u.washingt
/* internal prototypes */
static char *emailstrclean(char *string);
static int mem_add_extra_cacerts(char *contents, X509_LOOKUP *lookup);
+int compare_certs(const void *data1, const void *data2);
+
+int
+compare_certs(const void *data1, const void *data2)
+{
+ int rv;
+ char *s;
+
+ CertList *cl1 = *(CertList **) data1;
+ CertList *cl2 = *(CertList **) data2;
+
+ if((s = strchr(cl1->name, '@')) != NULL)
+ *s = '\0';
+
+ if((s = strchr(cl2->name, '@')) != NULL)
+ *s = '\0';
+
+ if((rv = strucmp(cl1->name, cl2->name)) == 0)
+ rv = strucmp(cl1->name + strlen(cl1->name) + 1, cl2->name + strlen(cl2->name) + 1);
+ cl1->name[strlen(cl1->name)] = '@';
+ cl2->name[strlen(cl2->name)] = '@';
+ return rv;
+}
+
+void
+resort_certificates(CertList **data, WhichCerts ctype)
+{
+ int i, j;
+ CertList *cl = *data;
+ CertList **cll;
+ char *s, *t;
+
+ for(i = 0; cl; cl = cl->next, i++)
+ if(ctype != Private){ /* ctype == Public or ctype == CACerts */
+ for(t = s = cl->name; t = strstr(s, ".crt"); s = t+1);
+ if (s) *(s-1) = '\0';
+ }
+ j = i;
+ cll = fs_get(i*sizeof(CertList *));
+ for(cl = *data, i = 0; cl; cl = cl->next, i++)
+ cll[i] = cl;
+ qsort((void *)cll, j, sizeof(CertList *), compare_certs);
+ for(i = 0; i < j - 1; i++){
+ cll[i]->next = cll[i+1];
+ if(ctype != Private)
+ cll[i]->name[strlen(cll[i]->name)]= '.'; /* restore ".crt" part */
+ }
+ cll[j-1]->next = NULL;
+ *data = cll[0];
+}
+
/* given a certificate and an email address, add the
* extension and md5 key to the name. return an allocated
@@ -56,11 +108,9 @@ smime_name(char *email, X509 *x, WhichCerts ctype)
char bufx[256];
char *rv;
- snprintf(bufx, sizeof(bufx), "%08lx",X509_subject_name_hash(x));
- rv = cpystr(bufx);
-// get_fingerprint(x, EVP_md5(), bufx, sizeof(bufx), NULL);
-// rv = fs_get(strlen(email) + 4 + 2 + strlen(bufx) + 1);
-// sprintf(rv, "%s%s.%s", email, EXTCERT(ctype), bufx);
+ get_fingerprint(x, EVP_md5(), bufx, sizeof(bufx), NULL);
+ rv = fs_get(strlen(email) + 4 + 2 + strlen(bufx) + 1);
+ sprintf(rv, "%s%s.%s", email, EXTCERT(ctype), bufx);
return rv;
}
@@ -128,8 +178,48 @@ emailstrclean(char *string)
}
+char *
+smime_get_date(ASN1_GENERALIZEDTIME *tm)
+{
+ BIO *mb = BIO_new(BIO_s_mem());
+ char iobuf[4096];
+ char date[MAILTMPLEN];
+ char buf[MAILTMPLEN];
+ char *m, *d, *t, *y, *z;
+
+ (void) BIO_reset(mb);
+ ASN1_UTCTIME_print(mb, tm);
+ (void) BIO_flush(mb);
+ BIO_read(mb, iobuf, sizeof(iobuf));
+
+ /* openssl returns the date in the format:
+ * "MONTH (as name) DAY (as number) TIME(hh:mm:ss) YEAR GMT"
+ */
+ m = iobuf;
+ d = strchr(iobuf, ' ');
+ *d++ = '\0';
+ while(*d == ' ') d++;
+ t = strchr(d+1, ' ');
+ *t++ = '\0';
+ while(*t == ' ') t++;
+ y = strchr(t+1, ' ');
+ *y++ = '\0';
+ while(*y == ' ') y++;
+ z = strchr(y+1, ' ');
+ *z++ = '\0';
+ while(*z == ' ') z++;
+
+ snprintf(date, sizeof(date), "%s %s %s %s (%s)", d, m, y, t, z);
+ date[sizeof(date)-1] = '\0';
+ date_str((char *) date, iSDateS1, 1, buf, sizeof(buf), 0);
+ if(buf[strlen(buf) - 1] == '!')
+ buf[strlen(buf) - 1] = '\0';
+
+ return cpystr(buf);
+}
+
/*
- * Add a lookup for each "*.crt" file in the given directory.
+ * Add a lookup for each "*.crt*" file in the given directory.
*/
int
add_certs_in_dir(X509_LOOKUP *lookup, char *path, char *ext, CertList **cdata)
@@ -150,14 +240,29 @@ add_certs_in_dir(X509_LOOKUP *lookup, char *path, char *ext, CertList **cdata)
ret = -1;
} else {
if(cdata){
+ BIO *in;
+ X509 *x;
+
cert = fs_get(sizeof(CertList));
memset((void *)cert, 0, sizeof(CertList));
cert->name = cpystr(d->d_name);
+ /* read buf into a bio and fill the CertData structure */
+ if((in = BIO_new_file(buf, "r"))!=0){
+ x = PEM_read_bio_X509(in, NULL, NULL, NULL);
+ if(x && x->cert_info){
+ cert->data.date_from = smime_get_date(x->cert_info->validity->notBefore);
+ cert->data.date_to = smime_get_date(x->cert_info->validity->notAfter);
+ get_fingerprint(x, EVP_md5(), buf, sizeof(buf), NULL);
+ cert->data.md5 = cpystr(buf);
+ X509_free(x);
+ }
+ BIO_free(in);
+ }
if(*cdata == NULL)
*cdata = cert;
else{
for (cl = *cdata; cl && cl->next; cl = cl->next);
- cl->next = cert;
+ cl->next = cert;
}
}
@@ -211,6 +316,7 @@ get_ca_store(void)
X509_STORE_free(store);
return NULL;
}
+ resort_certificates(&ps_global->smime->cacertlist, CACert);
}
if(!(lookup=X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()))){
@@ -966,13 +1072,23 @@ void
free_certlist(CertList **cl)
{
if(cl && *cl){
- free_certlist(&(*cl)->next);
+ if((*cl)->data.date_from)
+ fs_give((void **) &(*cl)->data.date_from);
+
+ if((*cl)->data.date_to)
+ fs_give((void **) &(*cl)->data.date_to);
+
+ if((*cl)->data.md5)
+ fs_give((void **) &(*cl)->data.md5);
+
if((*cl)->name)
fs_give((void **) &(*cl)->name);
if((*cl)->x509_cert)
X509_free((X509 *) (*cl)->x509_cert);
+ free_certlist(&(*cl)->next);
+
fs_give((void **) cl);
}
}
diff --git a/pith/smkeys.h b/pith/smkeys.h
index 0fe8faad..5214a369 100644
--- a/pith/smkeys.h
+++ b/pith/smkeys.h
@@ -61,6 +61,8 @@ void get_fingerprint(X509 *cert, const EVP_MD *type, char *buf, size_t ma
int certlist_to_file(char *filename, CertList *certlist);
int load_cert_for_key(char *pathdir, EVP_PKEY *pkey, char **certfile, X509 **pcert);
char *smime_name(char *email, X509 *x, WhichCerts ctype);
+char *smime_get_date(ASN1_GENERALIZEDTIME *tm);
+void resort_certificates(CertList **data, WhichCerts ctype);
#endif /* PITH_SMKEYS_INCLUDED */
diff --git a/po/Makefile.in b/po/Makefile.in
index 4b532b75..858d6983 100644
--- a/po/Makefile.in
+++ b/po/Makefile.in
@@ -11,7 +11,7 @@
# Origin: gettext-0.16
PACKAGE = alpine
-VERSION = 2.19.999
+VERSION = 2.19.9999
PACKAGE_BUGREPORT = chappa@washington.edu
SHELL = /bin/sh