summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduardo Chappa <chappa@washington.edu>2014-12-07 19:42:37 -0700
committerEduardo Chappa <chappa@washington.edu>2014-12-07 19:42:37 -0700
commit20d433c77e32dc05c2accf8ab943c2a7d9738239 (patch)
tree4cf7be2b55ec529067a2867eb29ebcfe6c5758aa
parent121a42f3d82c1b98c384857960d14b2057a95c41 (diff)
downloadalpine-20d433c77e32dc05c2accf8ab943c2a7d9738239.tar.xz
* new version 2.19.9993
* Aggregate operations allows bouncing a list of messages using a role. Suggested by Ulf-Dietrich Braumann. * Compilation error of module pith/reply.c if SMIME is not defined (as in Windows Alpine). There was a misplaced parenthesis. * Update to S/MIME to explain how to use a PKCS12 certificate in Alpine. * Fix error in compare_certs function, that would modify the name of the certificates after sorting them, and return when no certificates are given. * When replying to several messages, subject will be decoded first, and then stripped from re/fwd before they are compared to determine the subject of the replied message. * Add $(LIBINTL) to the flags to link rpdump, rpload, alpined and alpineldap because MAC OSX 10.8 x86_64 needs it. * When the download of an attachment is interrumpted, Alpine stills caches what was downloaded, making the download incomplete for subsequent calls of Alpine attempting to open the attachment. In the future, Alpine will not cache any downloaded part of the attachment when it is interrupted.
-rw-r--r--VERSION2
-rw-r--r--alpine/Makefile.am4
-rw-r--r--alpine/Makefile.in14
-rw-r--r--alpine/adrbkcmd.c10
-rw-r--r--alpine/alpine.c6
-rw-r--r--alpine/confscroll.c6
-rw-r--r--alpine/folder.c2
-rw-r--r--alpine/help.c4
-rw-r--r--alpine/imap.c2
-rw-r--r--alpine/mailcmd.c60
-rw-r--r--alpine/mailpart.c2
-rw-r--r--alpine/mailview.c4
-rw-r--r--alpine/newuser.c2
-rw-r--r--alpine/osdep/mswin.rc8
-rw-r--r--alpine/radio.c18
-rw-r--r--alpine/remote.c2
-rw-r--r--alpine/reply.c8
-rw-r--r--alpine/roleconf.c2
-rw-r--r--alpine/send.c10
-rw-r--r--alpine/send.h2
-rw-r--r--alpine/signal.c2
-rw-r--r--alpine/smime.c8
-rwxr-xr-xconfigure30
-rw-r--r--configure.ac8
-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/osdep/unix/Makefile3
-rw-r--r--imap/src/osdep/unix/env_unix.c3
-rw-r--r--mapi/pmapi.c2
-rw-r--r--mapi/pmapi.rc8
-rw-r--r--pith/adrbklib.c8
-rw-r--r--pith/charconv/filesys.c2
-rw-r--r--pith/charset.c6
-rw-r--r--pith/conf.c8
-rw-r--r--pith/conftype.h10
-rw-r--r--pith/detach.c12
-rw-r--r--pith/filter.c8
-rw-r--r--pith/folder.c2
-rw-r--r--pith/imap.c2
-rw-r--r--pith/ldap.c2
-rw-r--r--pith/mailcap.c2
-rw-r--r--pith/mailcmd.c2
-rw-r--r--pith/mailindx.c6
-rw-r--r--pith/mimetype.c2
-rw-r--r--pith/pattern.c8
-rw-r--r--pith/pine.hlp71
-rw-r--r--pith/reply.c37
-rw-r--r--pith/reply.h1
-rw-r--r--pith/save.c2
-rw-r--r--pith/send.c8
-rw-r--r--pith/smime.c27
-rw-r--r--pith/smkeys.c270
-rw-r--r--pith/smkeys.h8
-rw-r--r--pith/sort.c2
-rw-r--r--pith/stream.c2
-rw-r--r--pith/string.c2
-rw-r--r--pith/util.h2
-rw-r--r--web/src/alpined.d/Makefile.am4
-rw-r--r--web/src/alpined.d/Makefile.in12
-rw-r--r--web/src/alpined.d/signal.c2
-rw-r--r--web/src/alpined.d/stubs.c2
62 files changed, 567 insertions, 203 deletions
diff --git a/VERSION b/VERSION
index 93bd5449..7fd53bc9 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.19.9992
+2.19.9993
diff --git a/alpine/Makefile.am b/alpine/Makefile.am
index c80a97ff..8e25cd55 100644
--- a/alpine/Makefile.am
+++ b/alpine/Makefile.am
@@ -24,6 +24,10 @@ alpine_SOURCES = addrbook.c adrbkcmd.c after.c alpine.c arg.c busy.c colorconf.c
alpine_LDADD = $(LDADD) $(INTLLIBS)
+rpdump_LDADD = $(LDADD) $(INTLLIBS)
+
+rpload_LDADD = $(LDADD) $(INTLLIBS)
+
nodist_alpine_SOURCES = date.c
rpdump_SOURCES = rpdump.c
diff --git a/alpine/Makefile.in b/alpine/Makefile.in
index 77d07f13..14f96548 100644
--- a/alpine/Makefile.in
+++ b/alpine/Makefile.in
@@ -90,18 +90,10 @@ am__DEPENDENCIES_1 =
alpine_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1)
am_rpdump_OBJECTS = rpdump.$(OBJEXT)
rpdump_OBJECTS = $(am_rpdump_OBJECTS)
-rpdump_LDADD = $(LDADD)
-rpdump_DEPENDENCIES = ../pico/libpico.a ../pico/osdep/libpicoosd.a \
- ../pith/libpith.a ../pith/osdep/libpithosd.a \
- ../pith/charconv/libpithcc.a osdep/libpineosd.a \
- ../c-client/c-client.a
+rpdump_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1)
am_rpload_OBJECTS = rpload.$(OBJEXT)
rpload_OBJECTS = $(am_rpload_OBJECTS)
-rpload_LDADD = $(LDADD)
-rpload_DEPENDENCIES = ../pico/libpico.a ../pico/osdep/libpicoosd.a \
- ../pith/libpith.a ../pith/osdep/libpithosd.a \
- ../pith/charconv/libpithcc.a osdep/libpineosd.a \
- ../c-client/c-client.a
+rpload_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1)
DEFAULT_INCLUDES =
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -325,6 +317,8 @@ alpine_SOURCES = addrbook.c adrbkcmd.c after.c alpine.c arg.c busy.c colorconf.c
roleconf.c send.c setup.c signal.c status.c takeaddr.c titlebar.c smime.c newmail.c
alpine_LDADD = $(LDADD) $(INTLLIBS)
+rpdump_LDADD = $(LDADD) $(INTLLIBS)
+rpload_LDADD = $(LDADD) $(INTLLIBS)
nodist_alpine_SOURCES = date.c
rpdump_SOURCES = rpdump.c
rpload_SOURCES = rpload.c
diff --git a/alpine/adrbkcmd.c b/alpine/adrbkcmd.c
index e1c1d5fd..aa2f97ed 100644
--- a/alpine/adrbkcmd.c
+++ b/alpine/adrbkcmd.c
@@ -530,7 +530,7 @@ process_abook_view_cmd(int cmd, MSGNO_S *msgmap, SCROLL_S *sparms)
break;
default:
- panic("Unexpected command in process_abook_view_cmd");
+ alpine_panic("Unexpected command in process_abook_view_cmd");
break;
}
@@ -2639,7 +2639,7 @@ convert_to_remote_config(struct pine *ps, int edit_exceptions)
}
if(!ps->prc)
- panic("NULL prc in convert_to_remote_config");
+ alpine_panic("NULL prc in convert_to_remote_config");
dprint((2, "convert_to_remote_config\n"));
@@ -5016,7 +5016,7 @@ write_single_vcard_entry(struct pine *ps, gf_io_t pc, VCARD_INFO_S *vinfo)
break;
default:
- panic("can't happen in write_single_vcard_entry");
+ alpine_panic("can't happen in write_single_vcard_entry");
}
for(; ll && *ll; ll++){
@@ -5149,7 +5149,7 @@ write_single_tab_entry(gf_io_t pc, VCARD_INFO_S *vinfo)
break;
default:
- panic("can't happen in write_single_tab_entry");
+ alpine_panic("can't happen in write_single_tab_entry");
}
if(i)
@@ -7371,7 +7371,7 @@ process_ldap_cmd(int cmd, MSGNO_S *msgmap, SCROLL_S *sparms)
break;
default:
- panic("Unexpected command in process_ldap_cmd");
+ alpine_panic("Unexpected command in process_ldap_cmd");
break;
}
diff --git a/alpine/alpine.c b/alpine/alpine.c
index cb818498..1babffbf 100644
--- a/alpine/alpine.c
+++ b/alpine/alpine.c
@@ -50,8 +50,8 @@ static char rcsid[] = "$Id: alpine.c 1266 2009-07-14 18:39:12Z hubert@u.washingt
#include "init.h"
#include "remote.h"
#include "pattern.h"
-#include "newuser.h"
#include "setup.h"
+#include "newuser.h"
#include "adrbkcmd.h"
#include "signal.h"
#include "kblock.h"
@@ -2328,7 +2328,7 @@ choose_setup_cmd(int cmd, MSGNO_S *msgmap, SCROLL_S *sparms)
break;
default:
- panic("Unexpected command in choose_setup_cmd");
+ alpine_panic("Unexpected command in choose_setup_cmd");
break;
}
@@ -3324,7 +3324,7 @@ pine_gets_bytes(int reset)
This is also called from imap routines and fs_get and fs_resize.
----*/
void
-panic(char *message)
+alpine_panic(char *message)
{
char buf[256];
diff --git a/alpine/confscroll.c b/alpine/confscroll.c
index 8d1940a9..54e27666 100644
--- a/alpine/confscroll.c
+++ b/alpine/confscroll.c
@@ -4613,11 +4613,13 @@ toggle_feature_bit(struct pine *ps, int index, struct variable *var, CONF_S *cl,
ps->pass_ctrl_chars = F_ON(F_PASS_CONTROL_CHARS,ps_global) ? 1 : 0;
break;
+#ifdef SMIME
case F_USE_CERT_STORE_ONLY:
if(F_OFF(F_USE_CERT_STORE_ONLY, ps))
q_status_message(SM_ORDER | SM_DING, 3, 4,
"Disabling this feature should only be done for testing. Press \"?\" for help");
break;
+#endif /* SMIME */
case F_PASS_C1_CONTROL_CHARS :
ps->pass_c1_ctrl_chars = F_ON(F_PASS_C1_CONTROL_CHARS,ps_global) ? 1 : 0;
@@ -5264,7 +5266,7 @@ fix_side_effects(struct pine *ps, struct variable *var, int revert)
}
else{
if(reset_character_set_stuff(&err) == -1)
- panic(err ? err : "trouble with Character-Set");
+ alpine_panic(err ? err : "trouble with Character-Set");
else if(err){
q_status_message(SM_ORDER | SM_DING, 3, 5, err);
fs_give((void **) &err);
@@ -5280,7 +5282,7 @@ fix_side_effects(struct pine *ps, struct variable *var, int revert)
}
else{
if(reset_character_set_stuff(&err) == -1)
- panic(err ? err : "trouble with Character-Set");
+ alpine_panic(err ? err : "trouble with Character-Set");
else if(err){
q_status_message(SM_ORDER | SM_DING, 3, 5, err);
fs_give((void **) &err);
diff --git a/alpine/folder.c b/alpine/folder.c
index 6890b6f2..55176901 100644
--- a/alpine/folder.c
+++ b/alpine/folder.c
@@ -1024,7 +1024,7 @@ context_edit_screen(struct pine *ps, char *func, char *def_nick,
strncat(servpart, "#news.", sizeof(servpart)-1-strlen(servpart));
}
else
- panic("Unexpected invalid server");
+ alpine_panic("Unexpected invalid server");
}
else
servpart[0] = '\0';
diff --git a/alpine/help.c b/alpine/help.c
index aa7a8d70..a5cbdb8b 100644
--- a/alpine/help.c
+++ b/alpine/help.c
@@ -432,7 +432,7 @@ help_processor(int cmd, MSGNO_S *msgmap, SCROLL_S *sparms)
break;
default :
- panic("Unhandled case");
+ alpine_panic("Unhandled case");
}
return(rv);
@@ -899,7 +899,7 @@ journal_processor(int cmd, MSGNO_S *msgmap, SCROLL_S *sparms)
break;
default:
- panic("Unexpected command in journal_processor");
+ alpine_panic("Unexpected command in journal_processor");
break;
}
diff --git a/alpine/imap.c b/alpine/imap.c
index 009a9036..5e2e1384 100644
--- a/alpine/imap.c
+++ b/alpine/imap.c
@@ -1842,7 +1842,7 @@ answer_cert_failure(int cmd, MSGNO_S *msgmap, SCROLL_S *sparms)
break;
default:
- panic("Unexpected command in answer_cert_failure");
+ alpine_panic("Unexpected command in answer_cert_failure");
break;
}
diff --git a/alpine/mailcmd.c b/alpine/mailcmd.c
index bde099c6..163fdff6 100644
--- a/alpine/mailcmd.c
+++ b/alpine/mailcmd.c
@@ -1502,7 +1502,7 @@ get_out:
/*--------- Default, unknown command ----------*/
default:
- panic("Unexpected command case");
+ alpine_panic("Unexpected command case");
break;
}
@@ -2366,12 +2366,62 @@ int
cmd_bounce(struct pine *state, MSGNO_S *msgmap, int aopt)
{
int rv = 0;
+ ACTION_S *role = NULL;
if(any_messages(msgmap, NULL, "to Bounce")){
if(MCMD_ISAGG(aopt) && !pseudo_selected(state->mail_stream, msgmap))
return rv;
- rv = bounce(state, NULL);
+ if(MCMD_ISAGG(aopt)){ /* check for possible role */
+ PAT_STATE pstate;
+ int action;
+
+ if(nonempty_patterns(ROLE_DO_ROLES, &pstate) && first_pattern(&pstate)){
+ static ESCKEY_S yesno_opts[] = {
+ {'y', 'y', "Y", N_("Yes")},
+ {'n', 'n', "N", N_("No")},
+ {-1, 0, NULL, NULL}
+ };
+
+ action = radio_buttons(_("Bounce messages using a role? "),
+ -FOOTER_ROWS(state), yesno_opts,
+ 'y', 'x', h_role_compose, RB_NORM);
+ if(action == 'y'){
+ void (*prev_screen)(struct pine *) = NULL, (*redraw)(void) = NULL;
+
+ redraw = state->redrawer;
+ state->redrawer = NULL;
+ prev_screen = state->prev_screen;
+ role = NULL;
+ state->next_screen = SCREEN_FUN_NULL;
+
+ if(role_select_screen(state, &role, MC_BOUNCE) < 0)
+ cmd_cancelled(_("Bounce"));
+ else{
+ if(role)
+ role = combine_inherited_role(role);
+ else{
+ role = (ACTION_S *) fs_get(sizeof(*role));
+ memset((void *) role, 0, sizeof(*role));
+ role->nick = cpystr("Default Role");
+ }
+ }
+
+ if(redraw)
+ (*redraw)();
+
+ state->next_screen = prev_screen;
+ state->redrawer = redraw;
+ state->mangled_screen = 1;
+ }
+ }
+ }
+
+ rv = bounce(state, role);
+
+ if(role)
+ free_action(&role);
+
if(MCMD_ISAGG(aopt))
restore_selected(msgmap);
@@ -2696,7 +2746,7 @@ save_prompt(struct pine *state, CONTEXT_S **cntxt, char *nfldr, size_t len_nfldr
ESCKEY_S ekey[10];
if(!cntxt)
- panic("no context ptr in save_prompt");
+ alpine_panic("no context ptr in save_prompt");
init_hist(&history, HISTSIZE);
@@ -3079,7 +3129,7 @@ save_prompt(struct pine *state, CONTEXT_S **cntxt, char *nfldr, size_t len_nfldr
break;
default :
- panic("Unhandled case");
+ alpine_panic("Unhandled case");
break;
}
@@ -5772,7 +5822,7 @@ broach_folder(int qline, int allow_list, int *notrealinbox, CONTEXT_S **context)
break;
default :
- panic("Unhandled case");
+ alpine_panic("Unhandled case");
break;
}
diff --git a/alpine/mailpart.c b/alpine/mailpart.c
index 0a7e1b5e..14bd94e1 100644
--- a/alpine/mailpart.c
+++ b/alpine/mailpart.c
@@ -2635,7 +2635,7 @@ process_attachment_cmd(int cmd, MSGNO_S *msgmap, SCROLL_S *sparms)
break;
default:
- panic("Unexpected command case");
+ alpine_panic("Unexpected command case");
break;
}
diff --git a/alpine/mailview.c b/alpine/mailview.c
index 639d5c89..fe23da71 100644
--- a/alpine/mailview.c
+++ b/alpine/mailview.c
@@ -985,7 +985,7 @@ scroll_handle_launch(HANDLE_S *handle, int force)
default :
- panic("Unexpected HANDLE type");
+ alpine_panic("Unexpected HANDLE type");
}
return(0);
@@ -1088,7 +1088,7 @@ scroll_handle_reframe(int key, int center)
}
if(l == start_line)
- panic("Internal Error: no handle found");
+ alpine_panic("Internal Error: no handle found");
else
start_line = l;
}
diff --git a/alpine/newuser.c b/alpine/newuser.c
index 0d14a9d6..0c526eec 100644
--- a/alpine/newuser.c
+++ b/alpine/newuser.c
@@ -197,7 +197,7 @@ nuov_processor(int cmd, MSGNO_S *msgmap, SCROLL_S *sparms)
break;
default :
- panic("Unhandled case");
+ alpine_panic("Unhandled case");
}
return(rv);
diff --git a/alpine/osdep/mswin.rc b/alpine/osdep/mswin.rc
index 97c7e06d..181709fd 100644
--- a/alpine/osdep/mswin.rc
+++ b/alpine/osdep/mswin.rc
@@ -244,8 +244,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,19,9992,0
- PRODUCTVERSION 2,19,9992,0
+ FILEVERSION 2,19,9993,0
+ PRODUCTVERSION 2,19,9993,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -267,12 +267,12 @@ BEGIN
#else
VALUE "FileDescription", "Alpine\0"
#endif
- VALUE "FileVersion", "2.19.9992\0"
+ VALUE "FileVersion", "2.19.9993\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.9992\0"
+ VALUE "ProductVersion", "2.19.9993\0"
END
END
BLOCK "VarFileInfo"
diff --git a/alpine/radio.c b/alpine/radio.c
index 909617ee..2a946ebc 100644
--- a/alpine/radio.c
+++ b/alpine/radio.c
@@ -280,7 +280,7 @@ radio_buttons(char *utf8prompt, int line, ESCKEY_S *esc_list, int dflt,
if(flags & RB_RET_HELP){
if(help_text != NO_HELP)
- panic("RET_HELP and help in radio_buttons!");
+ alpine_panic("RET_HELP and help in radio_buttons!");
button_list[b].ch = '?';
button_list[b].rval = 3;
@@ -360,7 +360,7 @@ radio_buttons(char *utf8prompt, int line, ESCKEY_S *esc_list, int dflt,
clrbitmap(bitmap);
memset(fkey_table, NO_OP_COMMAND, 12 * sizeof(int));
if(flags & RB_RET_HELP && help_text != NO_HELP)
- panic("RET_HELP and help in radio_buttons!");
+ alpine_panic("RET_HELP and help in radio_buttons!");
/* if shown, always at position 0 */
if(help_text != NO_HELP || flags & RB_RET_HELP){
@@ -398,7 +398,7 @@ radio_buttons(char *utf8prompt, int line, ESCKEY_S *esc_list, int dflt,
&& esc_list[i-start].label[0] != '\0'){ /* visible */
if(i == 12){ /* special case where we put it in help slot */
if(help_text != NO_HELP)
- panic("Programming botch in radio_buttons(): too many keys");
+ alpine_panic("Programming botch in radio_buttons(): too many keys");
if(esc_list[i-start].ch != -2)
setbitn(0, bitmap); /* the help slot */
@@ -420,7 +420,7 @@ radio_buttons(char *utf8prompt, int line, ESCKEY_S *esc_list, int dflt,
rb_keymenu.keys[0].label = esc_list[i-start].label;
}
else
- panic("Botch in radio_buttons(): too many keys");
+ alpine_panic("Botch in radio_buttons(): too many keys");
}
}
else{
@@ -823,16 +823,16 @@ construct_combined_esclist(ESCKEY_S *list1, ESCKEY_S *list2)
*/
for(i=0; list1 && list1[i].ch != -1; i++){
if(list1[i].rval == list[j].rval)
- panic("1bad rval in d_r");
+ alpine_panic("1bad rval in d_r");
if(F_OFF(F_USE_FK,ps_global) && list1[i].ch == list[j].ch)
- panic("1bad ch in ccl");
+ alpine_panic("1bad ch in ccl");
}
for(i=0; list2 && list2[i].ch != -1; i++){
if(list2[i].rval == list[j].rval)
- panic("2bad rval in d_r");
+ alpine_panic("2bad rval in d_r");
if(F_OFF(F_USE_FK,ps_global) && list2[i].ch == list[j].ch)
- panic("2bad ch in ccl");
+ alpine_panic("2bad ch in ccl");
}
j++;
@@ -840,7 +840,7 @@ construct_combined_esclist(ESCKEY_S *list1, ESCKEY_S *list2)
/* the visible set */
for(i=0; list1 && list1[i].ch != -1; i++){
if(i >= KEYS_PER_LIST && list1[i].label[0] != '\0')
- panic("too many visible keys in ccl");
+ alpine_panic("too many visible keys in ccl");
list[j++] = list1[i];
}
diff --git a/alpine/remote.c b/alpine/remote.c
index 057aa46b..d4ef467b 100644
--- a/alpine/remote.c
+++ b/alpine/remote.c
@@ -248,7 +248,7 @@ rd_answer_forge_warning(int cmd, MSGNO_S *msgmap, SCROLL_S *sparms)
break;
default:
- panic("Unexpected command in rd_answer_forge_warning");
+ alpine_panic("Unexpected command in rd_answer_forge_warning");
break;
}
diff --git a/alpine/reply.c b/alpine/reply.c
index 23d40b18..317a793f 100644
--- a/alpine/reply.c
+++ b/alpine/reply.c
@@ -280,7 +280,7 @@ reply(struct pine *pine_state, ACTION_S *role_arg)
* if reply to more than one message, and all subjects
* match, so be it. otherwise set it to something generic...
*/
- if(strucmp(outgoing->subject,
+ if(!same_subject(outgoing->subject,
reply_subject(env->subject,tmp_20k_buf,SIZEOF_20KBUF))){
fs_give((void **)&outgoing->subject);
outgoing->subject = cpystr("Re: several messages");
@@ -1847,7 +1847,11 @@ bounce(struct pine *pine_state, ACTION_S *role)
if(mn_total_cur(pine_state->msgmap) > 1L){
save_toptr = &save_to;
- snprintf(tmp_20k_buf, SIZEOF_20KBUF, _("BOUNCE (redirect) %ld messages to : "),
+ if(role)
+ snprintf(tmp_20k_buf, SIZEOF_20KBUF, _("BOUNCE (redirect) %ld messages (using role %s) to : "),
+ mn_total_cur(pine_state->msgmap), role->nick);
+ else
+ snprintf(tmp_20k_buf, SIZEOF_20KBUF, _("BOUNCE (redirect) %ld messages to : "),
mn_total_cur(pine_state->msgmap));
tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
prmpt_who = cpystr(tmp_20k_buf);
diff --git a/alpine/roleconf.c b/alpine/roleconf.c
index 2cf9229b..6baa202e 100644
--- a/alpine/roleconf.c
+++ b/alpine/roleconf.c
@@ -5930,7 +5930,7 @@ setup_dummy_pattern_var(struct variable *v, char *name, PATTERN_S *defpat)
char ***alval;
if(!(v && name))
- panic("setup_dummy_pattern_var");
+ alpine_panic("setup_dummy_pattern_var");
v->name = (char *) fs_get(strlen(name)+NOTLEN+1);
snprintf(v->name, strlen(name)+NOTLEN+1, "%s%s", (defpat && defpat->not) ? NOT : "", name);
diff --git a/alpine/send.c b/alpine/send.c
index 7923d180..ebcf5789 100644
--- a/alpine/send.c
+++ b/alpine/send.c
@@ -5490,9 +5490,9 @@ Returns: none
void
phone_home(char *addr)
{
- char tmp[MAX_ADDRESS];
- ENVELOPE *outgoing;
- BODY *body;
+ char tmp[MAX_ADDRESS];
+ ENVELOPE *outgoing;
+ BODY *body;
outgoing = mail_newenvelope();
if(!addr || !strindex(addr, '@')){
@@ -5523,13 +5523,13 @@ phone_home(char *addr)
&& ps_global->VAR_NNTP_SERVER[0][0])
so_puts((STORE_S *)body->contents.text.data, " and NNTP");
- (void)pine_simple_send(outgoing, &body, NULL,NULL,NULL,NULL, SS_NULLRP);
+ (void) pine_simple_send(outgoing, &body, NULL,NULL,NULL,NULL, SS_NULLRP);
q_status_message(SM_ORDER, 1, 3, "Thanks for being counted!");
}
else
q_status_message(SM_ORDER | SM_DING, 3, 4,
- "Problem creating space for message text.");
+ "Problem creating space for message text.");
mail_free_envelope(&outgoing);
pine_free_body(&body);
diff --git a/alpine/send.h b/alpine/send.h
index 6ef8c3a9..b14ccc5c 100644
--- a/alpine/send.h
+++ b/alpine/send.h
@@ -42,7 +42,7 @@ int pine_simple_send(ENVELOPE *, BODY **, ACTION_S *, char *, char *, char *
void pine_send(ENVELOPE *, BODY **, char *, ACTION_S *, char *, REPLY_S *,
REDRAFT_POS_S *, char *, PINEFIELD *, int);
int upload_msg_to_pico(char *, size_t, long *);
-void phone_home(char *);
+void phone_home(char *);
void create_message_body(BODY **, PATMT *, int);
char *pine_send_status(int, char *, char *, size_t, int *);
int confirm_daemon_send(void);
diff --git a/alpine/signal.c b/alpine/signal.c
index 8f73c26d..cdad2294 100644
--- a/alpine/signal.c
+++ b/alpine/signal.c
@@ -188,7 +188,7 @@ auger_in_signal(int sig)
snprintf(buf, sizeof(buf), "Received abort signal(sig=%d)", sig);
buf[sizeof(buf)-1] = '\0';
- panic(buf); /* clean up and get out */
+ alpine_panic(buf); /* clean up and get out */
exit(-1); /* in case panic doesn't kill us */
}
diff --git a/alpine/smime.c b/alpine/smime.c
index 2987d9bf..dc3063de 100644
--- a/alpine/smime.c
+++ b/alpine/smime.c
@@ -1352,7 +1352,7 @@ void smime_manage_certs_init(struct pine *ps, CONF_S **ctmp, CONF_S **first_line
e = strlen(cl->name);
if(ctype != Private)
- e -= 4; /* remove extension length */
+ e -= 4; /* remove extension length FIX FIX FIX */
nf = 5; /* there are 5 fields */
s = 3; /* status has fixed size */
df = dt = 8; /* date from and date to have fixed size */
@@ -1379,14 +1379,14 @@ 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);
- if(ctype != Private)
- cl->name[strlen(cl->name) - 4] = '\0';
+ if(ctype != Private && SMHOLDERTYPE(ctype) == Directory)
+ cl->name[strlen(cl->name) - 4] = '\0'; /* FIX FIX FIX */
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)
+ if(ctype != Private && SMHOLDERTYPE(ctype) == Directory)
cl->name[strlen(cl->name)] = '.';
(*ctmp)->value = cpystr(tmp);
if(i == fline+1 && first_line && !*first_line)
diff --git a/configure b/configure
index 4be02ec0..558256e8 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.9992.
+# Generated by GNU Autoconf 2.69 for alpine 2.19.9993.
#
# 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.9992'
-PACKAGE_STRING='alpine 2.19.9992'
+PACKAGE_VERSION='2.19.9993'
+PACKAGE_STRING='alpine 2.19.9993'
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.9992 to adapt to many kinds of systems.
+\`configure' configures alpine 2.19.9993 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.9992:";;
+ short | recursive ) echo "Configuration of alpine 2.19.9993:";;
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.9992
+alpine configure 2.19.9993
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.9992, which was
+It was created by alpine $as_me 2.19.9993, 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.9992'
+ VERSION='2.19.9993'
cat >>confdefs.h <<_ACEOF
@@ -15656,7 +15656,7 @@ elif test -d /usr/local/ssl ; then
alpine_SSLDIR="/usr/local/ssl"
else
case $host in
- *-linux-gnu*)
+ *-linux-gnu*|*-k*bsd*-gnu*|*-gnu*)
if test -f /etc/fedora-release -o -f /etc/redhat-release -o -f /etc/redhat_version ; then
alpine_SSLTYPE="nopwd"
if test -d /etc/pki/tls ; then
@@ -16035,7 +16035,7 @@ fi
alpine_PAM="none"
case "$host" in
- *-linux-gnu*|*-k*bsd*-gnu*)
+ *-linux-gnu*|*-k*bsd*-gnu*|*-gnu*)
alpine_path_delim="/"
alpine_mode_readonly="(0600)"
if test -f /etc/fedora-release ; then
@@ -16850,8 +16850,8 @@ fi
exit 1
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Openssl library version >= 1.0.0c" >&5
-$as_echo_n "checking Openssl library version >= 1.0.0c... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking Openssl library version >= 1.0.1c" >&5
+$as_echo_n "checking Openssl library version >= 1.0.1c... " >&6; }
if test "$cross_compiling" = yes; then :
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
@@ -16885,7 +16885,7 @@ fi
if test "x$alpine_SSLTYPE" = "xnone" ; then
- as_fn_error $? "Install openssl version >= 1.0.0c" "$LINENO" 5
+ as_fn_error $? "Install openssl version >= 1.0.1c" "$LINENO" 5
exit 1
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing TLSv1_2_client_method" >&5
@@ -20364,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.9992, which was
+This file was extended by alpine $as_me 2.19.9993, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -20430,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.9992
+alpine config.status 2.19.9993
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 5796364f..9eb95311 100644
--- a/configure.ac
+++ b/configure.ac
@@ -723,7 +723,7 @@ dnl is the one intended to be used.
else
dnl preload c-client default locations/options
case $host in
- *-linux-gnu*)
+ *-linux-gnu*|*-k*bsd*-gnu*|*-gnu*)
if test -f /etc/fedora-release -o -f /etc/redhat-release -o -f /etc/redhat_version ; then
alpine_SSLTYPE="nopwd"
if test -d /etc/pki/tls ; then
@@ -1055,7 +1055,7 @@ dnl Tests and assignments below are mostly to coax the appropriate
dnl build from c-client. Most of this will go away when c-client
dnl adopts configure
case "$host" in
- *-linux-gnu*|*-k*bsd*-gnu*)
+ *-linux-gnu*|*-k*bsd*-gnu*|*-gnu*)
alpine_path_delim="/"
alpine_mode_readonly="(0600)"
if test -f /etc/fedora-release ; then
@@ -1364,7 +1364,7 @@ if test "x$alpine_SSLTYPE" != "xnone" ; then
exit 1
fi
- AC_MSG_CHECKING([Openssl library version >= 1.0.0c])
+ AC_MSG_CHECKING([Openssl library version >= 1.0.1c])
AC_RUN_IFELSE(
[AC_LANG_SOURCE([[
#include <stdio.h>
@@ -1382,7 +1382,7 @@ int main(void) {
[ alpine_SSLTYPE="none" ])
if test "x$alpine_SSLTYPE" = "xnone" ; then
- AC_MSG_ERROR(Install openssl version >= 1.0.0c)
+ AC_MSG_ERROR(Install openssl version >= 1.0.1c)
exit 1
fi
AC_SEARCH_LIBS(TLSv1_2_client_method,ssl,
diff --git a/doc/alpine.1 b/doc/alpine.1
index 52d8140c..4bb4d7f1 100644
--- a/doc/alpine.1
+++ b/doc/alpine.1
@@ -1,4 +1,4 @@
-.TH alpine 1 "Version 2.19.9992"
+.TH alpine 1 "Version 2.19.9993"
.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 78e9d2aa..028cdef5 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.9992, June 2014
+Version 2.19.9993, December 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 885789eb..6edddaf7 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.9992, June 2014
+ Version 2.19.9993, December 2014
Table of Contents
diff --git a/imap/src/osdep/unix/Makefile b/imap/src/osdep/unix/Makefile
index a38d15fb..14975c82 100644
--- a/imap/src/osdep/unix/Makefile
+++ b/imap/src/osdep/unix/Makefile
@@ -110,6 +110,7 @@ LOCKPGM=
LOCKPGM1=/usr/libexec/mlock
LOCKPGM2=/usr/sbin/mlock
LOCKPGM3=/etc/mlock
+LOCKPGM4=/usr/bin/mlock
# Default formats for creating new mailboxes and for empty mailboxes in the
@@ -984,7 +985,7 @@ onceenv:
-DACTIVEFILE=\"$(ACTIVEFILE)\" -DNEWSSPOOL=\"$(NEWSSPOOL)\" \
-DRSHPATH=\"$(RSHPATH)\" -DLOCKPGM=\"$(LOCKPGM)\" \
-DLOCKPGM1=\"$(LOCKPGM1)\" -DLOCKPGM2=\"$(LOCKPGM2)\" \
- -DLOCKPGM3=\"$(LOCKPGM3)\" > OSCFLAGS
+ -DLOCKPGM3=\"$(LOCKPGM3)\" -DLOCKPGM4=\"$(LOCKPGM4)\" > OSCFLAGS
echo $(BASELDFLAGS) $(EXTRALDFLAGS) > LDFLAGS
echo "$(ARRC) $(ARCHIVE) $(BINARIES);$(RANLIB) $(ARCHIVE)" > ARCHIVE
echo $(OS) > OSTYPE
diff --git a/imap/src/osdep/unix/env_unix.c b/imap/src/osdep/unix/env_unix.c
index b13d5066..d1bb1f02 100644
--- a/imap/src/osdep/unix/env_unix.c
+++ b/imap/src/osdep/unix/env_unix.c
@@ -1203,7 +1203,8 @@ long dotlock_lock (char *file,DOTLOCK *base,int fd)
if (closedBox || !lockpgm); /* can't do on closed box or disabled */
else if ((*lockpgm && stat (lockpgm,&sb)) ||
(!*lockpgm && stat (lockpgm = LOCKPGM1,&sb) &&
- stat (lockpgm = LOCKPGM2,&sb) && stat (lockpgm = LOCKPGM3,&sb)))
+ stat (lockpgm = LOCKPGM2,&sb) && stat (lockpgm = LOCKPGM3,&sb) &&
+ stat (lockpgm = LOCKPGM4,&sb)))
lockpgm = NIL; /* disable if can't find lockpgm */
else if (pipe (pi) >= 0) { /* make command pipes */
long cf;
diff --git a/mapi/pmapi.c b/mapi/pmapi.c
index acbc2d5b..529aafb4 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.9992\r\n");
+ fprintf(ms_global->dfd, "pmapi32.dll for Alpine Version 2.19.9993\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 31505bfc..01afc647 100644
--- a/mapi/pmapi.rc
+++ b/mapi/pmapi.rc
@@ -98,8 +98,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,19,9992,0
- PRODUCTVERSION 2,19,9992,0
+ FILEVERSION 2,19,9993,0
+ PRODUCTVERSION 2,19,9993,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.9992\0"
+ VALUE "FileVersion", "2.19.9993\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.9992\0"
+ VALUE "ProductVersion", "2.19.9993\0"
VALUE "SpecialBuild", " \0"
END
END
diff --git a/pith/adrbklib.c b/pith/adrbklib.c
index bdd505fb..3b0f17e8 100644
--- a/pith/adrbklib.c
+++ b/pith/adrbklib.c
@@ -4343,7 +4343,7 @@ exp_set_expanded(EXPANDED_S *exp_head, a_c_arg_t n)
nn = (adrbk_cntr_t)n;
if(!exp_head)
- panic("exp_head not set in exp_set_expanded");
+ alpine_panic("exp_head not set in exp_set_expanded");
for(e = exp_head; e->next; e = e->next)
if(e->next->ent >= nn)
@@ -4375,7 +4375,7 @@ exp_unset_expanded(EXPANDED_S *exp_head, a_c_arg_t n)
nn = (adrbk_cntr_t)n;
if(!exp_head)
- panic("exp_head not set in exp_unset_expanded");
+ alpine_panic("exp_head not set in exp_unset_expanded");
for(e = exp_head; e->next; e = e->next)
if(e->next->ent >= nn)
@@ -4407,7 +4407,7 @@ exp_del_nth(EXPANDED_S *exp_head, a_c_arg_t n)
nn = (adrbk_cntr_t)n;
if(!exp_head)
- panic("exp_head not set in exp_del_nth");
+ alpine_panic("exp_head not set in exp_del_nth");
e = exp_head->next;
while(e && e->ent < nn)
@@ -4447,7 +4447,7 @@ exp_add_nth(EXPANDED_S *exp_head, a_c_arg_t n)
nn = (adrbk_cntr_t)n;
if(!exp_head)
- panic("exp_head not set in exp_add_nth");
+ alpine_panic("exp_head not set in exp_add_nth");
e = exp_head->next;
while(e && e->ent < nn)
diff --git a/pith/charconv/filesys.c b/pith/charconv/filesys.c
index 63ac7b13..95da1e4b 100644
--- a/pith/charconv/filesys.c
+++ b/pith/charconv/filesys.c
@@ -4,8 +4,8 @@ static char rcsid[] = "$Id: filesys.c 770 2007-10-24 00:23:09Z hubert@u.washingt
/*
* ========================================================================
- * Copyright 2006-2007 University of Washington
* Copyright 2013-2014 Eduardo Chappa
+ * Copyright 2006-2007 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.
diff --git a/pith/charset.c b/pith/charset.c
index 6c16d624..db41adf6 100644
--- a/pith/charset.c
+++ b/pith/charset.c
@@ -424,7 +424,7 @@ rfc1522_copy_and_transliterate(unsigned char *rv,
if(utf8_charset(cset)){
if(!utf8_text(&src, cset, &xsrc, 0L)){
/* should not happen */
- panic("c-client failed to transliterate recognized characterset");
+ alpine_panic("c-client failed to transliterate recognized characterset");
}
}
else{
@@ -451,7 +451,7 @@ rfc1522_copy_and_transliterate(unsigned char *rv,
if(!(cs->type == CT_ASCII || cs->type == CT_UTF8)){
if(!utf8_text_cs(&src, cs, &xsrc, 0L, 0L)){
/* should not happen */
- panic("c-client failed to transliterate recognized characterset");
+ alpine_panic("c-client failed to transliterate recognized characterset");
}
}
}
@@ -461,7 +461,7 @@ rfc1522_copy_and_transliterate(unsigned char *rv,
&& utf8_charset(cset)){
if(!utf8_text(&src, cset, &xsrc, 0L)){
/* should not happen */
- panic("c-client failed to transliterate recognized character set");
+ alpine_panic("c-client failed to transliterate recognized character set");
}
}
else{
diff --git a/pith/conf.c b/pith/conf.c
index 81eed75b..d6083f01 100644
--- a/pith/conf.c
+++ b/pith/conf.c
@@ -1845,7 +1845,7 @@ init_vars(struct pine *ps, void (*cmds_f) (struct pine *, char **))
*/
if(reset_character_set_stuff(&err) == -1)
- panic(err ? err : "trouble with character set setup");
+ alpine_panic(err ? err : "trouble with character set setup");
else if(err){
init_error(ps, SM_ORDER | SM_DING, 3, 5, err);
fs_give((void **) &err);
@@ -2646,7 +2646,7 @@ convert_configvar_to_utf8(struct variable *v, char *fromcharset)
case 4: valptr = v->global_val.l; break;
case 5: valptr = v->fixed_val.l; break;
case 6: valptr = v->cmdline_val.l; break;
- default: panic("bad case in convert_configvar");
+ default: alpine_panic("bad case in convert_configvar");
}
if(valptr){
@@ -2672,7 +2672,7 @@ convert_configvar_to_utf8(struct variable *v, char *fromcharset)
case 4: valptr = &v->global_val.p; break;
case 5: valptr = &v->fixed_val.p; break;
case 6: valptr = &v->cmdline_val.p; break;
- default: panic("bad case in convert_configvar");
+ default: alpine_panic("bad case in convert_configvar");
}
if(valptr && *valptr && (*valptr)[0]){
@@ -7606,7 +7606,7 @@ panic1(char *message, char *arg)
snprintf(buf1, sizeof(buf1), "%.*s", MAX(sizeof(buf1) - 1 - strlen(message), 0), arg);
snprintf(buf2, sizeof(buf2), message, buf1);
- panic(buf2);
+ alpine_panic(buf2);
}
diff --git a/pith/conftype.h b/pith/conftype.h
index 11bf778f..d1931609 100644
--- a/pith/conftype.h
+++ b/pith/conftype.h
@@ -709,20 +709,28 @@ typedef struct smime_stuff {
char *publicpath;
char *publiccontent;
CertList *publiccertlist;
+ CertList *backuppubliccertlist;
SmimeHolderType privatetype;
char *privatepath;
char *privatecontent;
CertList *privatecertlist;
- void *personal_certs; /* this is type (PERSONAL_CERT *) */
+ CertList *backupprivatecertlist;
+ void *backuppersonal_certs; /* this is type (PERSONAL_CERT *) */
+ void *personal_certs; /* this is type (PERSONAL_CERT *) */
SmimeHolderType catype;
char *capath;
char *cacontent;
CertList *cacertlist;
+ CertList *backupcacertlist;
} SMIME_STUFF_S;
+#define BACKUPDATACERT(X) (((X) == Public ? ps_global->smime->backuppubliccertlist \
+ : ((X) == Private ? ps_global->smime->backupprivatecertlist \
+ : ps_global->smime->backupcacertlist)))
+
#define DATACERT(X) (((X) == Public ? ps_global->smime->publiccertlist \
: ((X) == Private ? ps_global->smime->privatecertlist \
: ps_global->smime->cacertlist)))
diff --git a/pith/detach.c b/pith/detach.c
index aebadae6..5c4b08e7 100644
--- a/pith/detach.c
+++ b/pith/detach.c
@@ -83,7 +83,7 @@ int df_trigger_cmp(long, char *, LT_INS_S **, void *);
int df_trigger_cmp_text(char *, char *);
int df_trigger_cmp_lwsp(char *, char *);
int df_trigger_cmp_start(char *, char *);
-int fetch_readc_cleanup(void);
+int fetch_readc_cleanup(int);
char *fetch_gets(readfn_t, void *, unsigned long, GETS_DATA *);
int fetch_readc(unsigned char *);
@@ -644,7 +644,7 @@ fetch_readc_init(FETCH_READC_S *frd, MAILSTREAM *stream, long int msgno,
int
-fetch_readc_cleanup(void)
+fetch_readc_cleanup(int store)
{
if(g_fr_desc){
if(g_fr_desc->we_turned_on)
@@ -653,7 +653,7 @@ fetch_readc_cleanup(void)
if(g_fr_desc->chunk && g_fr_desc->free_me)
fs_give((void **) &g_fr_desc->chunk);
- if(g_fr_desc->cache){
+ if(g_fr_desc->cache && store){
SIZEDTEXT text;
text.size = g_fr_desc->size;
@@ -695,7 +695,7 @@ fetch_readc(unsigned char *c)
extern void gf_error(char *);
if(ps_global->intr_pending){
- (void) fetch_readc_cleanup();
+ (void) fetch_readc_cleanup(0);
/* TRANSLATORS: data transfer was interrupted by something */
gf_error(g_fr_desc->error ? g_fr_desc->error :_("Transfer interrupted!"));
/* no return */
@@ -822,13 +822,13 @@ fetch_readc(unsigned char *c)
mail_parameters(g_fr_desc->stream, SET_GETS, old_gets);
if(!rv){
- (void) fetch_readc_cleanup();
+ (void) fetch_readc_cleanup(0);
gf_error("Partial fetch failed!");
/* no return */
}
}
else /* clean up and return done. */
- return(fetch_readc_cleanup());
+ return(fetch_readc_cleanup(1));
}
*c = *g_fr_desc->chunkp++;
diff --git a/pith/filter.c b/pith/filter.c
index d1848f87..5fd63c71 100644
--- a/pith/filter.c
+++ b/pith/filter.c
@@ -364,10 +364,10 @@ gf_clear_so_readc(STORE_S *so)
fs_give((void **) &sp);
}
else
- panic("Programmer botch: Can't unstack store readc");
+ alpine_panic("Programmer botch: Can't unstack store readc");
}
else
- panic("Programmer botch: NULL store clearing store readc");
+ alpine_panic("Programmer botch: NULL store clearing store readc");
}
@@ -398,10 +398,10 @@ gf_clear_so_writec(STORE_S *so)
fs_give((void **) &sp);
}
else
- panic("Programmer botch: Can't unstack store writec");
+ alpine_panic("Programmer botch: Can't unstack store writec");
}
else
- panic("Programmer botch: NULL store clearing store writec");
+ alpine_panic("Programmer botch: NULL store clearing store writec");
}
diff --git a/pith/folder.c b/pith/folder.c
index da0ea6d5..afc5f070 100644
--- a/pith/folder.c
+++ b/pith/folder.c
@@ -592,7 +592,7 @@ init_folders(struct pine *ps)
* collection???
*/
if(!prime)
- panic(_("No folder collections defined"));
+ alpine_panic(_("No folder collections defined"));
/*
* At this point, insert the INBOX mapping as the leading
diff --git a/pith/imap.c b/pith/imap.c
index 90219992..4b81bc09 100644
--- a/pith/imap.c
+++ b/pith/imap.c
@@ -643,7 +643,7 @@ mm_nocritical(MAILSTREAM *stream)
void
mm_fatal(char *message)
{
- panic(message);
+ alpine_panic(message);
}
diff --git a/pith/ldap.c b/pith/ldap.c
index 6fc96303..e3d0fa59 100644
--- a/pith/ldap.c
+++ b/pith/ldap.c
@@ -1700,7 +1700,7 @@ our_ldap_set_option(LDAP *ld, int option, void *optdata)
break;
default:
- panic("LDAP function not implemented");
+ alpine_panic("LDAP function not implemented");
}
#endif
diff --git a/pith/mailcap.c b/pith/mailcap.c
index 38dd6b68..77e1412d 100644
--- a/pith/mailcap.c
+++ b/pith/mailcap.c
@@ -248,7 +248,7 @@ mc_process_file(char *file)
return;
default:
- panic("Programmer botch in mc_process_file");
+ alpine_panic("Programmer botch in mc_process_file");
/*NOTREACHED*/
}
diff --git a/pith/mailcmd.c b/pith/mailcmd.c
index 3f310e22..44a03fb8 100644
--- a/pith/mailcmd.c
+++ b/pith/mailcmd.c
@@ -1250,7 +1250,7 @@ first_recent:
break;
default:
- panic("Unexpected incoming startup case");
+ alpine_panic("Unexpected incoming startup case");
break;
}
diff --git a/pith/mailindx.c b/pith/mailindx.c
index d420250a..afc241e1 100644
--- a/pith/mailindx.c
+++ b/pith/mailindx.c
@@ -1210,7 +1210,7 @@ setup_index_header_widths(MAILSTREAM *stream)
break;
default:
- panic("Unhandled fixed case in setup_index_header");
+ alpine_panic("Unhandled fixed case in setup_index_header");
break;
}
}
@@ -3319,7 +3319,7 @@ simple_index_line(char *buf, size_t buflen, ICE_S *ice, long int msgno)
IELEM_S *ielem;
if(!buf)
- panic("NULL buf in simple_index_line()");
+ alpine_panic("NULL buf in simple_index_line()");
if(buflen > 0)
buf[0] = '\0';
@@ -5093,7 +5093,7 @@ prio_str(INDEXDATA_S *idata, IndexColType ctype, ICE_S *ice)
break;
default:
- panic("Unhandled case in prio_str");
+ alpine_panic("Unhandled case in prio_str");
break;
}
diff --git a/pith/mimetype.c b/pith/mimetype.c
index 0d6f0e26..cd6cf751 100644
--- a/pith/mimetype.c
+++ b/pith/mimetype.c
@@ -176,7 +176,7 @@ mt_srch_mime_type(MT_OPERATORPROC mt_operator, MT_MAP_T *mt_map)
}
}
else
- panic("Unhandled mime type search");
+ alpine_panic("Unhandled mime type search");
}
/* if we still can not find the type, but it is a .docx (or alike) extension
diff --git a/pith/pattern.c b/pith/pattern.c
index 0b2eaf58..757d0b2f 100644
--- a/pith/pattern.c
+++ b/pith/pattern.c
@@ -1295,9 +1295,9 @@ parse_patgrp_slash(char *str, PATGRP_S *patgrp)
char *p;
if(!patgrp)
- panic("NULL patgrp to parse_patgrp_slash");
+ alpine_panic("NULL patgrp to parse_patgrp_slash");
else if(!(str && *str)){
- panic("NULL or empty string to parse_patgrp_slash");
+ alpine_panic("NULL or empty string to parse_patgrp_slash");
patgrp->bogus = 1;
}
else if(!strncmp(str, "/NICK=", 6))
@@ -1516,9 +1516,9 @@ parse_action_slash(char *str, ACTION_S *action)
NAMEVAL_S *v;
if(!action)
- panic("NULL action to parse_action_slash");
+ alpine_panic("NULL action to parse_action_slash");
else if(!(str && *str))
- panic("NULL or empty string to parse_action_slash");
+ alpine_panic("NULL or empty string to parse_action_slash");
else if(!strncmp(str, "/ROLE=1", 7))
action->is_a_role = 1;
else if(!strncmp(str, "/OTHER=1", 8))
diff --git a/pith/pine.hlp b/pith/pine.hlp
index cb0a6d63..c22dbd84 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 65 2014-06-20 23:23:15
+Alpine Commit 66 2014-12-07 19:42:29
============= h_news =================
<HTML>
<HEAD>
@@ -257,8 +257,14 @@ Additions include:
by James Jerkins.
<LI> Replace tabs by spaces in From and Subject fields to control for
size in screen of these fields. Change only in index screen display.
+ <LI> Aggregate operations allows bouncing a list of messages using a role.
+ Suggested by Ulf-Dietrich Braumann.
+ <LI> Makefile: Add $(LIBINTL) to the flags to link rpdump, rpload,
+ alpined and alpineldap because MAC OSX 10.8 x86_64 needs it. Reported by
+ Charles M. Register.
</UL>
+
<P>
Bugs that have been addressed include:
<UL>
@@ -294,6 +300,9 @@ Bugs that have been addressed include:
that contains 8bit if the option "Enable 8bit ESMTP Negotiation" is
enabled, the message contains 8bit characters and the smtp server
supports 8bit sending.
+ <LI> When replying to several messages, subject will be decoded first,
+ and then stripped from re/fwd before they are compared to determine
+ the subject of the replied message.
<LI> Crash when tcp connection to NNTP server was lost after connection
had been established, but lost immediately afterwards.
<LI> Crash with message &quot;lock when already locked&quot;, when painting
@@ -333,6 +342,11 @@ Bugs that have been addressed include:
<LI> Move SSL configurations from UW-IMAP to configure script, and
update OpenSSL configuration for Mac OS X.
<LI> Remove -lregex from linker flags when building --with-supplied-regex.
+ <LI> When the download of an attachment is interrumpted, Alpine stills
+ caches what was downloaded, making the download incomplete for
+ subsequent calls of Alpine attempting to open the attachment. In the
+ future, Alpine will not cache any downloaded part of the attachment
+ when it is interrupted.
</UL>
<P>
@@ -18714,7 +18728,7 @@ It has the format MMM DD. For example, &quot;Oct 23&quot;.
The feature
<A HREF="h_config_dates_to_local"><!--#echo var="FEAT_convert-dates-to-localtime"--></A>,
which adjusts for the timezone the message was sent from,
-may have an affect on the value of this token as well as the values of
+may have an effect on the value of this token as well as the values of
all of the other DATE or TIME tokens.
Some of the DATE and TIME tokens are displayed in a locale-specific
way unless the option
@@ -34310,18 +34324,41 @@ which gives you some information about the certificate used to sign or encrypt t
<H2>MISCELLANEOUS</H2>
-You may have access to a private certificate in the PKCS12 format,
-which would sometimes be in a file with a &quot;.p12&quot; suffix.
-The UNIX shell command
+If you have access to a private certificate in the PKCS12 format, which
+would sometimes be in a file with a &quot;.p12&quot; extension, then you can
+use the following commands to generate private keys, public and certificate
+authorities certificates. In the examples below, we assume that the
+certificate in the p12 format is called &quot;certificate.p12&quot;, and
+that your email address is &quot;your@address.com&quot;.
+
+<P>
+In order to create a private key use the command
+<P>
+<CENTER><SAMP>openssl pkcs12 -in certificate.p12 -out your@address.com.key</SAMP></CENTER>
<P>
-<CENTER><SAMP>openssl pkcs12 -in file.p12 -out file.pem</SAMP></CENTER>
+In order to create a public certificate use the command
<P>
-may work to convert that from the PKCS12 format to the PEM format.
-Then that file could be placed in the &quot;<SAMP>private</SAMP>&quot;
-directory with a filename of your email address followed by the
-suffix &quot;<SAMP>.key</SAMP>&quot;.
+<CENTER><SAMP>
+openssl pkcs12 -in certificate.p12 -clcerts -nokeys -out your@address.com.crt
+</SAMP></CENTER>
+<P>
+In order to create a certificate authority certificate use the command
+<P>
+<CENTER><SAMP>
+openssl pkcs12 -in certificate.p12 -cacerts -nokeys -out certificate-ca.crt
+</SAMP></CENTER>
+
+<P> If the previous command produces an empty file, it means that the
+certificate authority was not included in the .p12 file, so you will have
+to get it from some other sources. You will need these certificates, so
+that you can validate correctly signatures.
<P>
+After you have exported these certificates and keys, you can use the import
+command in Alpine, from the S/MIME configuration screen,
+to import these certificates into Alpine. They will be available for use
+as soon as you import them.
+<P>
&lt;End of help on this topic&gt;
</BODY>
</HTML>
@@ -35168,11 +35205,15 @@ 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.
+certificate, shown in its entirety. The third and fourth field are the
+first and last day validity for that certificate, respectively. The date
+is displayed in the user's locale unless the option
+<A HREF="h_config_disable_index_locale_dates"><!--#echo var="FEAT_disable-index-locale-dates"--></A>
+is set. In this case, the month, day and year are represented by two
+digits, and the format used is mm/dd/yy. Finally, 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.
diff --git a/pith/reply.c b/pith/reply.c
index ec8293db..0b3aaa62 100644
--- a/pith/reply.c
+++ b/pith/reply.c
@@ -67,6 +67,39 @@ int (*pith_opt_reply_to_all_prompt)(int *);
char *(*pith_opt_user_agent_prefix)(void);
+/* compare two subjects and return if they are the same.
+ We compare stripped subjects, that is, those that do
+ not have re/fwd. Before we compare the subjects, we
+ decode them in case they were encoded.
+ Return value: 0 - not the same subject, 1 - same subject.
+*/
+
+int
+same_subject(char *s, char *t)
+{
+ int rv = 0;
+ int i, j, len;
+ char *s1, *s2; /* holds decoded subjects from s and t */
+ char *u, *v;
+
+ if (s == NULL || t == NULL)
+ return s == t ? 1 : 0;
+
+ i = strlen(s); j = strlen(t);
+ len = i < j ? j : i;
+ u = fs_get(6*len+1);
+ v = fs_get(6*len+1);
+ s1 = (char *) rfc1522_decode_to_utf8(u, 6*len + 1, s);
+ s2 = (char *) rfc1522_decode_to_utf8(v, 6*len + 1, t);
+ mail_strip_subject(s1, &u);
+ mail_strip_subject(s2, &v);
+
+ rv = !strucmp(u, v);
+
+ fs_give((void **) &u);
+ fs_give((void **) &v);
+ return rv;
+}
/*
* reply_harvest -
@@ -2259,9 +2292,9 @@ forward_body(MAILSTREAM *stream, ENVELOPE *env, struct mail_bodystruct *orig_bod
&& orig_body->nested.part->body.subtype
&& (!strucmp(orig_body->nested.part->body.subtype, OUR_PKCS7_ENCLOSURE_SUBTYPE)
|| !strucmp(orig_body->nested.part->body.subtype, "signed")))
- || !strucmp(orig_body->subtype, OUR_PKCS7_ENCLOSURE_SUBTYPE))
+ || !strucmp(orig_body->subtype, OUR_PKCS7_ENCLOSURE_SUBTYPE)
#endif /* SMIME */
- ){
+ )){
/* only operate on the signed data (not the signature) */
body = forward_body(stream, env, &orig_body->nested.part->body,
msgno,
diff --git a/pith/reply.h b/pith/reply.h
index 5a5ea516..ae6dbfed 100644
--- a/pith/reply.h
+++ b/pith/reply.h
@@ -101,6 +101,7 @@ int sigdashes_are_present(char *);
char *signature_path(char *, char *, size_t);
char *simple_read_remote_file(char *, char *);
BODY *forward_multi_alt(MAILSTREAM *, ENVELOPE *, BODY *, long, char *, void *, gf_io_t, int);
+int same_subject(char *, char *s);
#endif /* PITH_REPLY_INCLUDED */
diff --git a/pith/save.c b/pith/save.c
index c25d81f0..117dcc32 100644
--- a/pith/save.c
+++ b/pith/save.c
@@ -240,7 +240,7 @@ save_get_fldr_from_env(char *fbuf, int nfbuf, ENVELOPE *e, struct pine *state,
break;
default:
- panic(botch);
+ alpine_panic(botch);
break;
}
diff --git a/pith/send.c b/pith/send.c
index e829d19c..d98f5c65 100644
--- a/pith/send.c
+++ b/pith/send.c
@@ -429,7 +429,7 @@ redraft_work(MAILSTREAM **streamp, long int cont_msg, ENVELOPE **outgoing,
fields[++i] = "X-Our-ReplyTo"; /* ReplyTo is real */
fields[++i] = "Lcc"; /* Lcc: too... */
if(++i != FIELD_COUNT)
- panic("Fix FIELD_COUNT");
+ alpine_panic("Fix FIELD_COUNT");
for(pf = *custom; pf && pf->name; pf = pf->next)
if(!pf->standard)
@@ -1689,7 +1689,7 @@ ADDRESS *
phone_home_from(void)
{
ADDRESS *addr = mail_newaddr();
- char tmp[32];
+ char tmp[32];
/* garble up mailbox name */
snprintf(tmp, sizeof(tmp), "hash_%08u", phone_home_hash(ps_global->VAR_USER_ID));
@@ -1718,7 +1718,7 @@ phone_home_hash(char *s)
h = ((h+1) * ((unsigned char) *s)) & (PH_MAXHASH - 1);
}
-
+
return (h);
}
@@ -3108,7 +3108,7 @@ encode_header_value(char *d, size_t dlen, unsigned char *s, char *charset, int e
return((char *)s);
if(dlen < SIZEOF_20KBUF)
- panic("bad call to encode_header_value");
+ alpine_panic("bad call to encode_header_value");
if(!encode_all){
/*
diff --git a/pith/smime.c b/pith/smime.c
index f29e37df..46e4278b 100644
--- a/pith/smime.c
+++ b/pith/smime.c
@@ -473,7 +473,7 @@ smime_expunge_cert(WhichCerts ctype)
removed = 0;
}
}
- else { /* SMHOLDERTYPE(ctype) == Container */
+ else if(SMHOLDERTYPE(ctype) == Container){
char *prefix= ctype == CACert ? CACERTSTORELEADER : EMAILADDRLEADER;
char tmp[MAILTMPLEN], *s, *t;
@@ -495,6 +495,7 @@ smime_expunge_cert(WhichCerts ctype)
}
else
removed = 0;
+ } else { /* unhandled case */
}
if(removed > 0){
@@ -972,6 +973,7 @@ renew_cert_data(CertList **data, WhichCerts ctype)
}
}
}
+ setup_certs_backup_by_type(ctype);
}
void
@@ -1013,6 +1015,7 @@ smime_init(void)
setup_storage_locations();
s_cert_store = get_ca_store();
+ setup_certs_backup_by_type(CACert);
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
@@ -1080,7 +1083,7 @@ get_personal_certs(char *path)
pc->name = cpystr(buf2);
/* Try to load the key with an empty password */
- pc->key = load_key(pc, "");
+ pc->key = load_key(pc, "", SM_NORMALCERT);
pc->next = result;
result = pc;
@@ -1156,6 +1159,7 @@ setup_privatekey_storage(void)
if(ps_global->smime->privatetype == Directory)
ps_global->smime->personal_certs = get_personal_certs(path);
}
+ setup_certs_backup_by_type(Private);
}
@@ -2030,7 +2034,7 @@ load_private_key(PERSONAL_CERT *pcert)
ERR_clear_error();
- if(!(pcert->key = load_key(pcert, password))){
+ if(!(pcert->key = load_key(pcert, password, SM_NORMALCERT))){
long err = ERR_get_error();
/* Couldn't load key... */
@@ -3586,12 +3590,21 @@ free_smime_struct(SMIME_STUFF_S **smime)
if((*smime)->publiccertlist)
free_certlist(&(*smime)->publiccertlist);
+ if((*smime)->backuppubliccertlist)
+ free_certlist(&(*smime)->backuppubliccertlist);
+
if((*smime)->cacertlist)
free_certlist(&(*smime)->cacertlist);
+ if((*smime)->backupcacertlist)
+ free_certlist(&(*smime)->backupcacertlist);
+
if((*smime)->privatecertlist)
free_certlist(&(*smime)->privatecertlist);
+ if((*smime)->backupprivatecertlist)
+ free_certlist(&(*smime)->backupprivatecertlist);
+
if((*smime)->publiccontent)
fs_give((void **) &(*smime)->publiccontent);
@@ -3606,6 +3619,14 @@ free_smime_struct(SMIME_STUFF_S **smime)
(*smime)->personal_certs = NULL;
}
+ if((*smime)->backuppersonal_certs){
+ PERSONAL_CERT *pc;
+
+ pc = (PERSONAL_CERT *) (*smime)->backuppersonal_certs;
+ free_personal_certs(&pc);
+ (*smime)->backuppersonal_certs = NULL;
+ }
+
if((*smime)->privatecontent)
fs_give((void **) &(*smime)->privatecontent);
diff --git a/pith/smkeys.c b/pith/smkeys.c
index 437cba6f..9f6570c3 100644
--- a/pith/smkeys.c
+++ b/pith/smkeys.c
@@ -33,6 +33,7 @@ static char rcsid[] = "$Id: smkeys.c 1266 2009-07-14 18:39:12Z hubert@u.washingt
#include "../pith/osdep/lstcmpnt.h"
#include "../pith/util.h"
#include "../pith/mailindx.h"
+#include "../pith/readfile.h"
#include "smkeys.h"
#ifdef APPLEKEYCHAIN
@@ -46,27 +47,228 @@ 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_by_name(const void *data1, const void *data2);
+#define SMIME_BACKUP_DIR ".backup"
+#define MAX_TRY_BACKUP 100
+
+/* return value: 0 - success, -1 error
+ * Call this function after setting up paths in ps_global->smime
+ * and reading certificates names in certlist.
+ */
int
-compare_certs(const void *data1, const void *data2)
+setup_certs_backup_by_type(WhichCerts ctype)
{
- int rv;
+ int rv = 0; /* assume success */
+ int len;
+ int i, done;
+ char *d;
+ char p[MAXPATH+1]; /* path to where the backup is */
+ char buf[MAXPATH+1], buf2[MAXPATH+1];
+ struct stat sbuf;
+ CertList *data, *cl;
+ DIR *dirp;
+ struct dirent *df; /* file in the directory */
+ CertList *cert, *cl2;
+ X509 *x;
+ BIO *in;
+
+ return rv; /* remove when this function is complete */
+
+ if(SMHOLDERTYPE(ctype) == Directory){
+ d = PATHCERTDIR(ctype);
+ if(d != NULL){
+ len = strlen(d) + strlen(S_FILESEP) + strlen(SMIME_BACKUP_DIR) + 1;
+ snprintf(p, MAXPATH, "%s%s%s", d, S_FILESEP, SMIME_BACKUP_DIR);
+ p[MAXPATH] = '\0';
+ if(our_stat(p, &sbuf) < 0){
+ if(our_mkpath(p, 0700) != 0)
+ return -1;
+ } else if((sbuf.st_mode & S_IFMT) != S_IFDIR){
+ for(i = 0, done = 0; done == 0 && i < MAX_TRY_BACKUP; i++){
+ snprintf(buf2, len+2, "%s%d", p, i);
+ if(our_stat(buf2, &sbuf) < 0){
+ if(our_mkpath(buf2, 0700) == 0)
+ done++;
+ }
+ else if((sbuf.st_mode & S_IFMT) == S_IFDIR)
+ done++;
+ if(done){
+ strncpy(p, buf2, MAXPATH);
+ p[MAXPATH] = '\0';
+ }
+ }
+ if(done == 0)
+ return -1;
+ }
+ /* if we are here, we have a backup directory where to
+ * backup certificates/keys, so now we will go
+ * through the list of certificates and back them up
+ * if we need to.
+ */
+ data = BACKUPDATACERT(ctype);
+ for(cl = DATACERT(ctype); cl; cl = cl->next){
+ char clname[MAXPATH+1];
+
+ snprintf(clname, MAXPATH, "%s%s", cl->name, ctype == Private ? ".key" : "");
+ clname[MAXPATH] = '\0';
+ len = strlen(d) + strlen(clname) + 2;
+ if(len < MAXPATH){
+ snprintf(buf, len, "%s%s%s", d, S_FILESEP, clname);
+ buf[sizeof(buf)-1] = '\0';
+ len = strlen(p) + strlen(clname) + strlen(cl->data.md5) + 3;
+ if(len < MAXPATH){
+ snprintf(buf2, len, "%s%s%s.%s", p, S_FILESEP, clname, cl->data.md5);
+ buf2[sizeof(buf2)-1] = '\0';
+ done = 0; /* recycle done: it means we have a file that may be a certifificate*/
+ if(stat(buf2, &sbuf) < 0){
+ if (our_copy(buf2, buf) == 0)
+ done++;
+ } else if((sbuf.st_mode & S_IFMT) == S_IFREG)
+ done++;
+
+ if(done){
+ switch(ctype){
+ case Public:
+ case CACert:
+ if((in = BIO_new_file(buf2, "r"))!=0){
+ cert = fs_get(sizeof(CertList));
+ memset((void *)cert, 0, sizeof(CertList));
+ cert->x509_cert = PEM_read_bio_X509(in, NULL, NULL, NULL);
+ if(cl->data.date_from != NULL)
+ cert->data.date_from = cpystr(cl->data.date_from);
+ if(cl->data.date_to != NULL)
+ cert->data.date_to = cpystr(cl->data.date_to);
+ if(cl->data.md5 != NULL)
+ cert->data.md5 = cpystr(cl->data.md5);
+ snprintf(buf2, len, "%s.%s", cl->name, cl->data.md5);
+ buf2[sizeof(buf2)-1] = '\0';
+ cert->name = cpystr(buf2);
+ if(data == NULL)
+ data = cert;
+ else{
+ for (cl2 = data; cl2 && cl2->next; cl2 = cl2->next);
+ cl2->next = cert;
+ }
+ BIO_free(in);
+ }
+ break;
+
+ case Private: break;
+ default: alpine_panic("Bad ctype (0)");
+ }
+ }
+ }
+ }
+ }
+ /* if we are here, it means we just loaded the backup variable with
+ * a copy of the data that comes from the certlist not coming from
+ * backup. Now we are going to load the contents of the .backup
+ * directory.
+ */
+
+ /* Here is the plan: read the backup directory (in the variable "p")
+ * and attempt to add it. If already there, skip it; otherwise continue
+ */
+
+ if((dirp = opendir(p)) != NULL){
+ while((df=readdir(dirp)) != NULL){
+ if(df->d_name && *df->d_name == '.') /* no hidden files here */
+ continue;
+
+ /* make sure that we have a file */
+ snprintf(buf2, sizeof(buf2), "%s%s%s", p, S_FILESEP, df->d_name);
+ buf2[sizeof(buf2)-1] = '\0';
+ if(our_stat(buf2, &sbuf) == 0
+ && (sbuf.st_mode & S_IFMT) != S_IFREG)
+ continue;
+
+ /* make sure it is not already in the list */
+ for(cl = data; cl; cl = cl->next)
+ if(strcmp(cl->name, df->d_name) == 0)
+ break;
+ if(cl != NULL)
+ continue;
+
+ /* ok, if it is not in the list, and it is a certificate. Add it */
+ switch(ctype){
+ case Public:
+ case CACert:
+ if((in = BIO_new_file(buf2, "r"))!=0){
+ x = PEM_read_bio_X509(in, NULL, NULL, NULL);
+ if(x && x->cert_info){ /* for now copy this information */
+ cert = fs_get(sizeof(CertList));
+ memset((void *)cert, 0, sizeof(CertList));
+ cert->x509_cert = x;
+ 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);
+ cert->name = cpystr(df->d_name);
+ /* we will use the cert->data.md5 variable to find a backup
+ certificate, not the name */
+ if(data == NULL)
+ data = cert;
+ else{
+ for (cl2 = data; cl2 && cl2->next; cl2 = cl2->next);
+ cl2->next = cert;
+ }
+ }
+ BIO_free(in);
+ }
+ break;
+
+ case Private:
+ /* here we must check it is a key of some cert....*/
+ break;
+
+ default: alpine_panic("Bad ctype (1)");
+ } /* end switch */
+ }
+ closedir(dirp);
+ }
+
+ /* Now that we are here, we have all the information in the backup
+ * directory
+ */
+
+ switch(ctype){
+ case Public : ps_global->smime->backuppubliccertlist = data; break;
+ case Private: ps_global->smime->backupprivatecertlist = data; break;
+ case CACert : ps_global->smime->backupcacertlist = data; break;
+ default : alpine_panic("Bad ctype (n)");
+ }
+ }
+ } else if(SMHOLDERTYPE(ctype) == Container){
+
+ } /* else APPLEKEYCHAIN */
+ return rv;
+}
+
+int
+compare_certs_by_name(const void *data1, const void *data2)
+{
+ int rv, i, j;
char *s;
-
+
CertList *cl1 = *(CertList **) data1;
CertList *cl2 = *(CertList **) data2;
-
- if((s = strchr(cl1->name, '@')) != NULL)
+
+ i = j = -1;
+ if((s = strchr(cl1->name, '@')) != NULL){
+ i = s - cl1->name;
*s = '\0';
-
- if((s = strchr(cl2->name, '@')) != NULL)
+ }
+
+ if((s = strchr(cl2->name, '@')) != NULL){
+ j = s - cl2->name;
*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)] = '@';
+ rv = strucmp(cl1->name + i + 1, cl2->name + j + 1);
+ if(i >= 0) cl1->name[i] = '@';
+ if(j >= 0) cl2->name[j] = '@';
return rv;
}
@@ -78,6 +280,9 @@ resort_certificates(CertList **data, WhichCerts ctype)
CertList **cll;
char *s, *t;
+ if(cl == NULL)
+ return;
+
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);
@@ -87,34 +292,19 @@ resort_certificates(CertList **data, WhichCerts ctype)
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);
+ qsort((void *)cll, j, sizeof(CertList *), compare_certs_by_name);
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 */
}
+ if(ctype != Private)
+ cll[j-1]->name[strlen(cll[j-1]->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
- * name, freed by caller
- */
-char *
-smime_name(char *email, X509 *x, WhichCerts ctype)
-{
- char bufx[256];
- char *rv;
-
- 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;
-}
-
void
get_fingerprint(X509 *cert, const EVP_MD *type, char *buf, size_t maxLen, char *s)
{
@@ -186,6 +376,8 @@ smime_get_date(ASN1_GENERALIZEDTIME *tm)
char date[MAILTMPLEN];
char buf[MAILTMPLEN];
char *m, *d, *t, *y, *z;
+ struct date smd;
+ struct tm smtm;
(void) BIO_reset(mb);
ASN1_UTCTIME_print(mb, tm);
@@ -211,9 +403,17 @@ smime_get_date(ASN1_GENERALIZEDTIME *tm)
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';
+ if(F_ON(F_DATES_TO_LOCAL,ps_global)){
+ parse_date(convert_date_to_local(date), &smd);
+ memset(&smtm, 0, sizeof(smtm));
+ smtm.tm_year = MIN(MAX(smd.year-1900, 0), 2000) % 100 - 1900;
+ smtm.tm_mon = MIN(MAX(smd.month-1, 0), 11);
+ smtm.tm_mday = MIN(MAX(smd.day, 1), 31);
+ our_strftime(buf, sizeof(buf), "%x", &smtm);
+ }
+ else
+ snprintf(buf, sizeof(buf), "%s/%s/%s", m, d, y + strlen(y) - 2);
+ buf[sizeof(buf)-1] = '\0';
return cpystr(buf);
}
@@ -334,7 +534,7 @@ get_ca_store(void)
EVP_PKEY *
-load_key(PERSONAL_CERT *pc, char *pass)
+load_key(PERSONAL_CERT *pc, char *pass, int flag)
{
BIO *in;
EVP_PKEY *key = NULL;
@@ -853,7 +1053,7 @@ mem_to_personal_certs(char *contents)
pc->name = cpystr(name);
pc->keytext = keytext; /* a pointer into contents */
- pc->key = load_key(pc, "");
+ pc->key = load_key(pc, "", SM_NORMALCERT);
pc->next = result;
result = pc;
diff --git a/pith/smkeys.h b/pith/smkeys.h
index 5214a369..37a92a90 100644
--- a/pith/smkeys.h
+++ b/pith/smkeys.h
@@ -43,6 +43,9 @@ typedef struct personal_cert {
struct personal_cert *next;
} PERSONAL_CERT;
+/* flags that tell us where to look for certificates/keys */
+#define SM_NORMALCERT 0x1 /* look in normal user defined directory */
+#define SM_BACKUPCERT 0x2 /* look in backup directory */
/* exported protoypes */
int add_certs_in_dir(X509_LOOKUP *lookup, char *path, char *ext, CertList **cdata);
@@ -51,7 +54,7 @@ PERSONAL_CERT *get_personal_certs(char *d);
X509 *get_cert_for(char *email, WhichCerts ctype);
void save_cert_for(char *email, X509 *cert, WhichCerts ctype);
char **get_x509_subject_email(X509 *x);
-EVP_PKEY *load_key(PERSONAL_CERT *pc, char *pass);
+EVP_PKEY *load_key(PERSONAL_CERT *pc, char *pass, int flag);
CertList *mem_to_certlist(char *contents, WhichCerts ctype);
void add_to_end_of_certlist(CertList **cl, char *name, X509 *cert);
void free_certlist(CertList **cl);
@@ -60,10 +63,9 @@ void free_personal_certs(PERSONAL_CERT **pc);
void get_fingerprint(X509 *cert, const EVP_MD *type, char *buf, size_t maxLen, char *s);
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);
-
+int setup_certs_backup_by_type(WhichCerts ctype);
#endif /* PITH_SMKEYS_INCLUDED */
#endif /* SMIME */
diff --git a/pith/sort.c b/pith/sort.c
index b18699e5..890204af 100644
--- a/pith/sort.c
+++ b/pith/sort.c
@@ -488,7 +488,7 @@ sort_sort_callback(MAILSTREAM *stream, long unsigned int *list, long unsigned in
dprint((2, "sort_sort_callback\n"));
if(mn_get_total(g_sort.msgmap) < nmsgs)
- panic("Message count shrank after sort!");
+ alpine_panic("Message count shrank after sort!");
/* copy ulongs to array of longs */
for(i = nmsgs; i > 0; i--)
diff --git a/pith/stream.c b/pith/stream.c
index 5201a440..e03c7748 100644
--- a/pith/stream.c
+++ b/pith/stream.c
@@ -1729,7 +1729,7 @@ pine_mail_partial_fetch_wrapper(MAILSTREAM *stream, long unsigned int msgno,
* partial text.
*/
if(!str_to_free)
- panic("Programmer botch: partial fetch attempt w/o string pointer");
+ alpine_panic("Programmer botch: partial fetch attempt w/o string pointer");
else
*str_to_free = (char *) new_text.data;
}
diff --git a/pith/string.c b/pith/string.c
index 6ad1045a..2d7a02b2 100644
--- a/pith/string.c
+++ b/pith/string.c
@@ -2674,7 +2674,7 @@ add_escapes(char *src, char *quote_these_chars, int quoting_char,
char *ans = NULL;
if(!quote_these_chars)
- panic("bad arg to add_escapes");
+ alpine_panic("bad arg to add_escapes");
if(src){
char *q, *p, *qchar;
diff --git a/pith/util.h b/pith/util.h
index defbca6c..701ed061 100644
--- a/pith/util.h
+++ b/pith/util.h
@@ -56,7 +56,7 @@ int *cpyint(int);
/* currently mandatory to implement stubs */
/* called when we detect a serious program error */
-void panic(char *);
+void alpine_panic(char *);
/* called when testing to see if panic state is in effect */
int panicking(void);
diff --git a/web/src/alpined.d/Makefile.am b/web/src/alpined.d/Makefile.am
index 9101e4fb..524cb7e1 100644
--- a/web/src/alpined.d/Makefile.am
+++ b/web/src/alpined.d/Makefile.am
@@ -27,6 +27,10 @@ alpineldap_SOURCES = alpineldap.c busy.c color.c imap.c ldap.c remote.c \
signal.c debug.c status.c stubs.c \
alpined.h color.h ldap.h
+alpined_LDADD = $(LDADD) $(INTLLIBS)
+
+alpineldap_LDADD = $(LDADD) $(INTLLIBS)
+
LDADD = local.o \
@top_srcdir@/pith/libpith.a \
@top_srcdir@/pith/osdep/libpithosd.a \
diff --git a/web/src/alpined.d/Makefile.in b/web/src/alpined.d/Makefile.in
index 9824ba6e..1d542067 100644
--- a/web/src/alpined.d/Makefile.in
+++ b/web/src/alpined.d/Makefile.in
@@ -105,22 +105,18 @@ am_alpined_OBJECTS = alpined.$(OBJEXT) busy.$(OBJEXT) color.$(OBJEXT) \
signal.$(OBJEXT) debug.$(OBJEXT) status.$(OBJEXT) \
stubs.$(OBJEXT)
alpined_OBJECTS = $(am_alpined_OBJECTS)
-alpined_LDADD = $(LDADD)
am__DEPENDENCIES_1 =
-alpined_DEPENDENCIES = local.o @top_srcdir@/pith/libpith.a \
+am__DEPENDENCIES_2 = local.o @top_srcdir@/pith/libpith.a \
@top_srcdir@/pith/osdep/libpithosd.a \
@top_srcdir@/pith/charconv/libpithcc.a \
@top_srcdir@/c-client/c-client.a $(am__DEPENDENCIES_1)
+alpined_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
am_alpineldap_OBJECTS = alpineldap.$(OBJEXT) busy.$(OBJEXT) \
color.$(OBJEXT) imap.$(OBJEXT) ldap.$(OBJEXT) remote.$(OBJEXT) \
signal.$(OBJEXT) debug.$(OBJEXT) status.$(OBJEXT) \
stubs.$(OBJEXT)
alpineldap_OBJECTS = $(am_alpineldap_OBJECTS)
-alpineldap_LDADD = $(LDADD)
-alpineldap_DEPENDENCIES = local.o @top_srcdir@/pith/libpith.a \
- @top_srcdir@/pith/osdep/libpithosd.a \
- @top_srcdir@/pith/charconv/libpithcc.a \
- @top_srcdir@/c-client/c-client.a $(am__DEPENDENCIES_1)
+alpineldap_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
DEFAULT_INCLUDES =
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -312,6 +308,8 @@ alpineldap_SOURCES = alpineldap.c busy.c color.c imap.c ldap.c remote.c \
signal.c debug.c status.c stubs.c \
alpined.h color.h ldap.h
+alpined_LDADD = $(LDADD) $(INTLLIBS)
+alpineldap_LDADD = $(LDADD) $(INTLLIBS)
LDADD = local.o \
@top_srcdir@/pith/libpith.a \
@top_srcdir@/pith/osdep/libpithosd.a \
diff --git a/web/src/alpined.d/signal.c b/web/src/alpined.d/signal.c
index 3bdb7b41..52d8e600 100644
--- a/web/src/alpined.d/signal.c
+++ b/web/src/alpined.d/signal.c
@@ -128,7 +128,7 @@ auger_in_signal(int sig)
(void) unlink(peSocketName);
snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Abort: signal %d", sig);
- panic(tmp_20k_buf); /* clean up and get out */
+ alpine_panic(tmp_20k_buf); /* clean up and get out */
exit(-1); /* in case panic doesn't kill us */
}
diff --git a/web/src/alpined.d/stubs.c b/web/src/alpined.d/stubs.c
index 10b79914..c25b305e 100644
--- a/web/src/alpined.d/stubs.c
+++ b/web/src/alpined.d/stubs.c
@@ -100,7 +100,7 @@ exec_mailcap_test_cmd(cmd)
This is also called from imap routines and fs_get and fs_resize.
----*/
void
-panic(message)
+alpine_panic(message)
char *message;
{
in_panic = 1;