diff options
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | alpine/arg.c | 21 | ||||
-rw-r--r-- | alpine/conftype.h | 1 | ||||
-rw-r--r-- | alpine/mailpart.c | 3 | ||||
-rw-r--r-- | alpine/osdep/mswin.rc | 8 | ||||
-rw-r--r-- | alpine/smime.c | 52 | ||||
-rwxr-xr-x | configure | 33 | ||||
-rw-r--r-- | configure.ac | 16 | ||||
-rw-r--r-- | doc/alpine.1 | 2 | ||||
-rw-r--r-- | doc/tech-notes/index.html | 2 | ||||
-rw-r--r-- | doc/tech-notes/tech-notes.txt | 2 | ||||
-rw-r--r-- | imap/src/c-client/rfc822.c | 94 | ||||
-rw-r--r-- | mapi/pmapi.c | 2 | ||||
-rw-r--r-- | mapi/pmapi.rc | 8 | ||||
-rw-r--r-- | pith/conftype.h | 10 | ||||
-rw-r--r-- | pith/filter.c | 209 | ||||
-rw-r--r-- | pith/mimedesc.c | 2 | ||||
-rw-r--r-- | pith/pine.hlp | 56 | ||||
-rw-r--r-- | pith/reply.c | 2 | ||||
-rw-r--r-- | pith/send.c | 5 | ||||
-rw-r--r-- | pith/smime.c | 21 | ||||
-rw-r--r-- | pith/smkeys.c | 132 | ||||
-rw-r--r-- | pith/smkeys.h | 2 | ||||
-rw-r--r-- | po/Makefile.in | 2 |
24 files changed, 514 insertions, 173 deletions
@@ -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; } @@ -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 </style> + <LI> HTML: <BR>, <BR />, and <BR/> are considered + the same inline tag; the same is valid for the <HR> 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 +"D" 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 +"D" 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 +"D" 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 |