summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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