summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduardo Chappa <chappa@washington.edu>2013-10-13 02:08:28 -0600
committerEduardo Chappa <chappa@washington.edu>2013-10-13 02:08:28 -0600
commitee95edb6a42df4b45c82080c32f852781f289a02 (patch)
tree1fc71517846468677163b76dbf2400b59d7997b5
parent30a979ab1460a57d466a6a5cc6adb96eac452ce4 (diff)
downloadalpine-ee95edb6a42df4b45c82080c32f852781f289a02.tar.xz
* Fixes in Pico so that it will crash in big files, instead of looping
forever. Todo: see how this can be improved. * Add support for UID EXPUNGE in selected folders.
-rw-r--r--VERSION2
-rw-r--r--alpine/mailcmd.c76
-rw-r--r--autom4te.cache/output.020
-rw-r--r--autom4te.cache/output.220
-rwxr-xr-xconfigure20
-rw-r--r--pico/file.c16
-rw-r--r--pico/fileio.c5
-rw-r--r--pico/line.c6
-rw-r--r--pith/mailcmd.c9
-rw-r--r--pith/mailcmd.h2
-rw-r--r--pith/msgno.c3
-rw-r--r--pith/msgno.h2
-rw-r--r--pith/pine.hlp68
-rw-r--r--web/src/alpined.d/alpined.c16
14 files changed, 170 insertions, 95 deletions
diff --git a/VERSION b/VERSION
index 9462efac..22ac5d0c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.11.8
+2.11.9
diff --git a/alpine/mailcmd.c b/alpine/mailcmd.c
index 57716e4e..1cffd586 100644
--- a/alpine/mailcmd.c
+++ b/alpine/mailcmd.c
@@ -88,7 +88,7 @@ int cmd_forward(struct pine *, MSGNO_S *, int);
int cmd_bounce(struct pine *, MSGNO_S *, int);
int cmd_save(struct pine *, MAILSTREAM *, MSGNO_S *, int, CmdWhere);
void role_compose(struct pine *);
-void cmd_expunge(struct pine *, MAILSTREAM *, MSGNO_S *);
+int cmd_expunge(struct pine *, MAILSTREAM *, MSGNO_S *, int);
int cmd_export(struct pine *, MSGNO_S *, int, int);
char *cmd_delete_action(struct pine *, MSGNO_S *, CmdWhere);
char *cmd_delete_view(struct pine *, MSGNO_S *);
@@ -1207,7 +1207,7 @@ get_out:
/*---------- Expunge ----------*/
case MC_EXPUNGE :
- cmd_expunge(state, stream, msgmap);
+ (void) cmd_expunge(state, stream, msgmap, MCMD_NONE);
break;
@@ -3137,18 +3137,43 @@ create_for_save_prompt(CONTEXT_S *context, char *folder, int sequence_sensitive)
Result:
----*/
-void
-cmd_expunge(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap)
+int
+cmd_expunge(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap, int agg)
{
long del_count, prefilter_del_count;
- int we_cancel = 0;
+ int we_cancel = 0, rv = 0;
char prompt[MAX_SCREEN_COLS+1];
+ char *sequence;
COLOR_PAIR *lastc = NULL;
dprint((2, "\n - expunge -\n"));
+ del_count = 0;
+
+ sequence = MCMD_ISAGG(agg) ? selected_sequence(stream, msgmap, NULL, 0) : NULL;
+
+ if(MCMD_ISAGG(agg)){
+ long i;
+ MESSAGECACHE *mc;
+ for(i = 1L; i <= stream->nmsgs; i++){
+ if((mc = mail_elt(stream, i)) != NULL
+ && mc->sequence && mc->deleted)
+ del_count++;
+ }
+ if(del_count == 0){
+ q_status_message(SM_ORDER, 0, 4,
+ _("No selected messages are deleted"));
+ return 0;
+ }
+ } else {
+ if(!any_messages(msgmap, NULL, "to Expunge"))
+ return rv;
+ }
+
if(IS_NEWS(stream) && stream->rdonly){
- if((del_count = count_flagged(stream, F_DEL)) > 0L){
+ if(!MCMD_ISAGG(agg))
+ del_count = count_flagged(stream, F_DEL);
+ if(del_count > 0L){
state->mangled_footer = 1;
snprintf(prompt, sizeof(prompt), "Exclude %ld message%s from %.*s", del_count,
plural(del_count), sizeof(prompt)-40,
@@ -3164,7 +3189,7 @@ cmd_expunge(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap)
if(F_ON(F_NEWS_CROSS_DELETE, state))
cross_delete_crossposts(stream);
- msgno_exclude_deleted(stream, msgmap);
+ msgno_exclude_deleted(stream, msgmap, sequence);
clear_index_cache(stream, 0);
/*
@@ -3188,19 +3213,21 @@ cmd_expunge(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap)
else
any_messages(NULL, "deleted", "to Exclude");
- return;
+ return del_count;
}
else if(READONLY_FOLDER(stream)){
q_status_message(SM_ORDER, 0, 4,
_("Can't expunge. Folder is read-only"));
- return;
+ return del_count;
}
- prefilter_del_count = count_flagged(stream, F_DEL|F_NOFILT);
-
- mail_expunge_prefilter(stream, MI_NONE);
+ if(!MCMD_ISAGG(agg)){
+ prefilter_del_count = count_flagged(stream, F_DEL|F_NOFILT);
+ mail_expunge_prefilter(stream, MI_NONE);
+ del_count = count_flagged(stream, F_DEL|F_NOFILT);
+ }
- if((del_count = count_flagged(stream, F_DEL|F_NOFILT)) != 0){
+ if(del_count != 0){
int ret;
snprintf(prompt, sizeof(prompt), "Expunge %ld message%s from %.*s", del_count,
@@ -3221,7 +3248,7 @@ cmd_expunge(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap)
cmd_cancelled("Expunge");
if(ret != 'y')
- return;
+ return 0;
}
dprint((8, "Expunge max:%ld cur:%ld kill:%d\n",
@@ -3243,9 +3270,12 @@ cmd_expunge(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap)
we_cancel = busy_cue(_("Expunging"), NULL, 1);
- if(cmd_expunge_work(stream, msgmap))
+ if(cmd_expunge_work(stream, msgmap, sequence))
state->mangled_body = 1;
+ if(sequence)
+ fs_give((void **)&sequence);
+
if(we_cancel)
cancel_busy_cue((sp_expunge_count(stream) > 0) ? 0 : -1);
@@ -3279,6 +3309,7 @@ cmd_expunge(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap)
q_status_message(SM_ORDER, 0, 3,
_("No messages marked deleted. No messages expunged."));
}
+ return del_count;
}
@@ -7070,6 +7101,13 @@ apply_command(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
sel_opts3[i++].label = "";
}
+ if(!is_imap_stream(stream) || LEVELUIDPLUS(stream)){ /* expunge selected messages */
+ sel_opts3[i].ch = 'x';
+ sel_opts3[i].rval = 'x';
+ sel_opts3[i].name = "X";
+ sel_opts3[i++].label = N_("Expunge");
+ }
+
sel_opts3[i].ch = KEY_DEL; /* also invisible */
sel_opts3[i].rval = 'd';
sel_opts3[i].name = "";
@@ -7080,7 +7118,7 @@ apply_command(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
snprintf(prompt, sizeof(prompt), "%s command : ",
(flags & AC_FROM_THREAD) ? "THREAD" : "APPLY");
prompt[sizeof(prompt)-1] = '\0';
- cmd = double_radio_buttons(prompt, q_line, sel_opts3, 'z', 'x', NO_HELP,
+ cmd = double_radio_buttons(prompt, q_line, sel_opts3, 'z', 'c', NO_HELP,
RB_SEQ_SENSITIVE);
if(isupper(cmd))
cmd = tolower(cmd);
@@ -7161,7 +7199,11 @@ apply_command(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
select_thread_stmp(state, stream, msgmap);
break;
- case 'x' : /* cancel */
+ case 'x' : /* Expunge */
+ rv = cmd_expunge(state, stream, msgmap, agg);
+ break;
+
+ case 'c' : /* cancel */
cmd_cancelled((flags & AC_FROM_THREAD) ? "Thread command"
: "Apply command");
break;
diff --git a/autom4te.cache/output.0 b/autom4te.cache/output.0
index c2b22ed5..c24157ea 100644
--- a/autom4te.cache/output.0
+++ b/autom4te.cache/output.0
@@ -1,7 +1,7 @@
@%:@! /bin/sh
@%:@ From configure.ac Rev:5 by chappa@washington.edu.
@%:@ Guess values for system-dependent variables and create Makefiles.
-@%:@ Generated by GNU Autoconf 2.69 for alpine 2.11.8.
+@%:@ Generated by GNU Autoconf 2.69 for alpine 2.11.9.
@%:@
@%:@ Report bugs to <chappa@washington.edu>.
@%:@
@@ -730,8 +730,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='alpine'
PACKAGE_TARNAME='alpine'
-PACKAGE_VERSION='2.11.8'
-PACKAGE_STRING='alpine 2.11.8'
+PACKAGE_VERSION='2.11.9'
+PACKAGE_STRING='alpine 2.11.9'
PACKAGE_BUGREPORT='chappa@washington.edu'
PACKAGE_URL=''
@@ -1594,7 +1594,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.11.8 to adapt to many kinds of systems.
+\`configure' configures alpine 2.11.9 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1664,7 +1664,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of alpine 2.11.8:";;
+ short | recursive ) echo "Configuration of alpine 2.11.9:";;
esac
cat <<\_ACEOF
@@ -1948,7 +1948,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-alpine configure 2.11.8
+alpine configure 2.11.9
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2554,7 +2554,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.11.8, which was
+It was created by alpine $as_me 2.11.9, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3375,7 +3375,7 @@ fi
# Define the identity of the package.
PACKAGE='alpine'
- VERSION='2.11.8'
+ VERSION='2.11.9'
cat >>confdefs.h <<_ACEOF
@@ -20221,7 +20221,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.11.8, which was
+This file was extended by alpine $as_me 2.11.9, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -20287,7 +20287,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.11.8
+alpine config.status 2.11.9
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/autom4te.cache/output.2 b/autom4te.cache/output.2
index c2b22ed5..c24157ea 100644
--- a/autom4te.cache/output.2
+++ b/autom4te.cache/output.2
@@ -1,7 +1,7 @@
@%:@! /bin/sh
@%:@ From configure.ac Rev:5 by chappa@washington.edu.
@%:@ Guess values for system-dependent variables and create Makefiles.
-@%:@ Generated by GNU Autoconf 2.69 for alpine 2.11.8.
+@%:@ Generated by GNU Autoconf 2.69 for alpine 2.11.9.
@%:@
@%:@ Report bugs to <chappa@washington.edu>.
@%:@
@@ -730,8 +730,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='alpine'
PACKAGE_TARNAME='alpine'
-PACKAGE_VERSION='2.11.8'
-PACKAGE_STRING='alpine 2.11.8'
+PACKAGE_VERSION='2.11.9'
+PACKAGE_STRING='alpine 2.11.9'
PACKAGE_BUGREPORT='chappa@washington.edu'
PACKAGE_URL=''
@@ -1594,7 +1594,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.11.8 to adapt to many kinds of systems.
+\`configure' configures alpine 2.11.9 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1664,7 +1664,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of alpine 2.11.8:";;
+ short | recursive ) echo "Configuration of alpine 2.11.9:";;
esac
cat <<\_ACEOF
@@ -1948,7 +1948,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-alpine configure 2.11.8
+alpine configure 2.11.9
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2554,7 +2554,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.11.8, which was
+It was created by alpine $as_me 2.11.9, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3375,7 +3375,7 @@ fi
# Define the identity of the package.
PACKAGE='alpine'
- VERSION='2.11.8'
+ VERSION='2.11.9'
cat >>confdefs.h <<_ACEOF
@@ -20221,7 +20221,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.11.8, which was
+This file was extended by alpine $as_me 2.11.9, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -20287,7 +20287,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.11.8
+alpine config.status 2.11.9
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure b/configure
index 8a27618f..f90d2d3a 100755
--- a/configure
+++ b/configure
@@ -1,7 +1,7 @@
#! /bin/sh
# From configure.ac Rev:5 by chappa@washington.edu.
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for alpine 2.11.8.
+# Generated by GNU Autoconf 2.69 for alpine 2.11.9.
#
# Report bugs to <chappa@washington.edu>.
#
@@ -730,8 +730,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='alpine'
PACKAGE_TARNAME='alpine'
-PACKAGE_VERSION='2.11.8'
-PACKAGE_STRING='alpine 2.11.8'
+PACKAGE_VERSION='2.11.9'
+PACKAGE_STRING='alpine 2.11.9'
PACKAGE_BUGREPORT='chappa@washington.edu'
PACKAGE_URL=''
@@ -1594,7 +1594,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.11.8 to adapt to many kinds of systems.
+\`configure' configures alpine 2.11.9 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1664,7 +1664,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of alpine 2.11.8:";;
+ short | recursive ) echo "Configuration of alpine 2.11.9:";;
esac
cat <<\_ACEOF
@@ -1948,7 +1948,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-alpine configure 2.11.8
+alpine configure 2.11.9
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2554,7 +2554,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.11.8, which was
+It was created by alpine $as_me 2.11.9, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3375,7 +3375,7 @@ fi
# Define the identity of the package.
PACKAGE='alpine'
- VERSION='2.11.8'
+ VERSION='2.11.9'
cat >>confdefs.h <<_ACEOF
@@ -20221,7 +20221,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.11.8, which was
+This file was extended by alpine $as_me 2.11.9, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -20287,7 +20287,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.11.8
+alpine config.status 2.11.9
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/pico/file.c b/pico/file.c
index 2493d02b..8185593b 100644
--- a/pico/file.c
+++ b/pico/file.c
@@ -519,7 +519,10 @@ readin(char fname[], /* name of file to read */
}
else{
if(newline){
- lnewline();
+ if(lnewline() == FALSE){
+ done++;
+ continue;
+ }
newline = 0;
}
@@ -530,7 +533,7 @@ readin(char fname[], /* name of file to read */
case FIOLNG :
for(linep = line; charsread-- > 0; linep++)
- linsert(1, *linep);
+ if(linsert(1, *linep) == FALSE) done++;
break;
@@ -975,8 +978,11 @@ ifile(char fname[])
}
else{
if(newline){
- lnewline();
- newline = 0;
+ if(lnewline() == FALSE){
+ done++;
+ continue;
+ }
+ newline = 0;
}
switch(s){
@@ -986,7 +992,7 @@ ifile(char fname[])
case FIOLNG :
for(linep = line; charsread-- > 0; linep++)
- linsert(1, *linep);
+ if(linsert(1, *linep) == FALSE) done++;
break;
diff --git a/pico/fileio.c b/pico/fileio.c
index 5cf124c0..91eacf9d 100644
--- a/pico/fileio.c
+++ b/pico/fileio.c
@@ -95,6 +95,7 @@ ffgetline(UCS buf[], size_t nbuf, size_t *charsreturned, int msg)
{
size_t i;
UCS ucs;
+ static int displayed = 0;
if(charsreturned)
*charsreturned = 0;
@@ -121,8 +122,10 @@ ffgetline(UCS buf[], size_t nbuf, size_t *charsreturned, int msg)
if(charsreturned)
*charsreturned = nbuf - 1;
- if(msg)
+ if(msg && displayed == 0){
emlwrite("File has long line", NULL);
+ displayed = 1;
+ }
return FIOLNG;
}
diff --git a/pico/line.c b/pico/line.c
index e5df3670..d1fb31e4 100644
--- a/pico/line.c
+++ b/pico/line.c
@@ -73,6 +73,7 @@ lalloc(int used)
register LINE *lp;
register int size;
EML eml;
+ static int displayed = 0;
if((size = (used+NBLOCK-1) & ~(NBLOCK-1)) > NLINE)
size *= 2;
@@ -80,9 +81,10 @@ lalloc(int used)
if (size == 0) /* Assume that an empty */
size = NBLOCK; /* line is for type-in. */
- if ((lp = (LINE *) malloc(sizeof(LINE)+(size*sizeof(CELL)))) == NULL) {
+ if (displayed == 0 && (lp = (LINE *) malloc(sizeof(LINE)+(size*sizeof(CELL)))) == NULL){
eml.s = comatose(size);
- emlwrite("Cannot allocate %s bytes", &eml);
+ emlwrite("Cannot allocate %s bytes (read file incomplete)", &eml);
+ displayed++;
return (NULL);
}
diff --git a/pith/mailcmd.c b/pith/mailcmd.c
index 78ba98ad..23ea51ba 100644
--- a/pith/mailcmd.c
+++ b/pith/mailcmd.c
@@ -281,7 +281,7 @@ cmd_undelete(struct pine *state, MSGNO_S *msgmap, int copts)
int
-cmd_expunge_work(MAILSTREAM *stream, MSGNO_S *msgmap)
+cmd_expunge_work(MAILSTREAM *stream, MSGNO_S *msgmap, char *seq)
{
long old_max_msgno;
int rv = 0;
@@ -289,7 +289,7 @@ cmd_expunge_work(MAILSTREAM *stream, MSGNO_S *msgmap)
old_max_msgno = mn_get_total(msgmap);
delete_filtered_msgs(stream);
ps_global->expunge_in_progress = 1;
- mail_expunge(stream);
+ mail_expunge_full(stream, seq, 0);
ps_global->expunge_in_progress = 0;
dprint((2,"expunge complete cur:%ld max:%ld\n",
@@ -861,7 +861,8 @@ do_broach_folder(char *newfolder, CONTEXT_S *new_context, MAILSTREAM **streamp,
if(IS_NEWS(ps_global->mail_stream)
&& ps_global->mail_stream->rdonly)
msgno_exclude_deleted(ps_global->mail_stream,
- sp_msgmap(ps_global->mail_stream));
+ sp_msgmap(ps_global->mail_stream),
+ NULL);
if(mn_get_total(ps_global->msgmap) > 0)
mn_set_cur(ps_global->msgmap,
@@ -996,7 +997,7 @@ do_broach_folder(char *newfolder, CONTEXT_S *new_context, MAILSTREAM **streamp,
* hidden from view...
*/
if(IS_NEWS(ps_global->mail_stream) && ps_global->mail_stream->rdonly)
- msgno_exclude_deleted(ps_global->mail_stream, ps_global->msgmap);
+ msgno_exclude_deleted(ps_global->mail_stream, ps_global->msgmap, NULL);
if(we_cancel && F_OFF(F_QUELL_FILTER_MSGS, ps_global))
cancel_busy_cue(0);
diff --git a/pith/mailcmd.h b/pith/mailcmd.h
index 9e99c6f3..84b7e213 100644
--- a/pith/mailcmd.h
+++ b/pith/mailcmd.h
@@ -57,7 +57,7 @@ void cmd_cancelled(char *);
void cmd_quota(struct pine *);
int cmd_delete(struct pine *, MSGNO_S *, int, char *(*)(struct pine *, MSGNO_S *));
int cmd_undelete(struct pine *, MSGNO_S *, int);
-int cmd_expunge_work(MAILSTREAM *, MSGNO_S *);
+int cmd_expunge_work(MAILSTREAM *, MSGNO_S *, char *);
CONTEXT_S *broach_get_folder(CONTEXT_S *, int *, char **);
int do_broach_folder(char *, CONTEXT_S *, MAILSTREAM **, unsigned long);
void expunge_and_close(MAILSTREAM *, char **, unsigned long);
diff --git a/pith/msgno.c b/pith/msgno.c
index 465a42e0..75669225 100644
--- a/pith/msgno.c
+++ b/pith/msgno.c
@@ -252,7 +252,7 @@ msgno_dec(MAILSTREAM *stream, MSGNO_S *msgs, int flags)
f -- flags to use a purge criteria
----*/
void
-msgno_exclude_deleted(MAILSTREAM *stream, MSGNO_S *msgs)
+msgno_exclude_deleted(MAILSTREAM *stream, MSGNO_S *msgs, char *sequence)
{
long i, rawno;
MESSAGECACHE *mc;
@@ -281,6 +281,7 @@ msgno_exclude_deleted(MAILSTREAM *stream, MSGNO_S *msgs)
for(i = msgs->max_msgno; i >= 1L; i--)
if((rawno = mn_m2raw(msgs, i)) > 0L && stream && rawno <= stream->nmsgs
&& (mc = mail_elt(stream, rawno))
+ && (sequence ? mc->sequence : 1)
&& ((mc->valid && mc->deleted) || (!mc->valid && mc->searched))){
msgno_exclude(stream, msgs, i, 0);
need_isort_reset++;
diff --git a/pith/msgno.h b/pith/msgno.h
index 00b669c1..873ed7bb 100644
--- a/pith/msgno.h
+++ b/pith/msgno.h
@@ -186,7 +186,7 @@ void msgno_reset_isort(MSGNO_S *);
void msgno_give(MSGNO_S **);
void msgno_inc(MAILSTREAM *, MSGNO_S *, int);
void msgno_dec(MAILSTREAM *, MSGNO_S *, int);
-void msgno_exclude_deleted(MAILSTREAM *, MSGNO_S *);
+void msgno_exclude_deleted(MAILSTREAM *, MSGNO_S *, char *);
void msgno_exclude(MAILSTREAM *, MSGNO_S *, long, int);
int msgno_include(MAILSTREAM *, MSGNO_S *, int);
void msgno_add_raw(MSGNO_S *, long);
diff --git a/pith/pine.hlp b/pith/pine.hlp
index 8e0feacb..ea85d75c 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 33 2013-10-05 22:46:52
+Alpine Commit 34 2013-10-13 00:44:53
============= h_news =================
<HTML>
<HEAD>
@@ -179,31 +179,36 @@ Additions include:
<P>
<UL>
- <LI> Alpine does not attempt to automatically reopen a collection that
- was not opened due to cancellation by the user. Instead, the user
- must try to open it explicitly.
+ <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.
+ <LI> Alpine does not attempt to automatically reopen a collection
+ that was not opened due to cancellation by the user.
+ Instead, the user must try to open it explicitly.
<LI> Alpine searches for a certificate that matches an email address in
- all addresses in a certificate (instead of just the first one) but
- when it tries to unlock the certificate, it asks for the password
- for the first email address in that certificate.
+ all addresses in a certificate (instead of just the first
+ one) but when it tries to unlock the certificate, it asks
+ for the password for the first email address in that
+ certificate.
<LI> Add /tls1, /tls1_1, /tls1_2 and /dtls1 to the definition of a
- server to use different ways to connect using ssl, for example
- {server.com/tls1} will attempt to connect to server.com at the ssl
- imap port (port 993) and establish a connection using TLSv1. These
- flags can be used in conjunction with the /ssl flag, the ssl flag
- is redundant. Conversely, however, the /ssl flag does not imply any
- of these flags; the /ssl flag means SSLv3 or, if not available,
+ server to use different ways to connect using ssl, for
+ example {server.com/tls1} will attempt to connect to
+ server.com at the ssl imap port (port 993) and establish a
+ connection using TLSv1. These flags can be used in
+ conjunction with the /ssl flag, the ssl flag is redundant.
+ Conversely, however, the /ssl flag does not imply any of
+ these flags; the /ssl flag means SSLv3 or, if not available,
SSLv2 in the SSL port.
- <LI> Experimental: Write the content-type of a message in lowercase, as some
- non-compliant servers do not understand uppercase content-type, such as
- those of GMX.de.
- <LI> Opening a folder updates recent count in maildrops (this already works
- for other types of folders)
- <LI> Automatically redraw screen after opening an attachment instead of
- simply clearing it.
- <LI> Pico: Justification works without need of a predefined quote string.
- This allows justification of blocks of text that are indented with
- spaces.
+ <LI> Experimental: Write the content-type of a message in
+ lowercase, as some non-compliant servers do not understand
+ uppercase content-type, such as those of GMX.de.
+ <LI> Opening a folder updates recent count in maildrops (this
+ already works for other types of folders)
+ <LI> Automatically redraw screen after opening an attachment
+ instead of simply clearing it.
+ <LI> Pico: Justification works without need of a predefined quote
+ string. This allows justification of blocks of text that are
+ indented with spaces.
</UL>
<P>
@@ -3182,7 +3187,6 @@ There are also additional details on
&lt;End of help on this topic&gt;
</BODY>
</HTML>
-
====== h_help_index ======
<HTML>
<HEAD>
@@ -5735,6 +5739,22 @@ the text from the current folder. With newsgroups or shared mailboxes,
you don't have permission to actually remove the message, so it is an
exclude -- Alpine removes the message from your view of the folder even
though it is not technically gone.
+
+<P> A selective expunge command is available in IMAP folders that support
+the UID EXPUNGE extension in <A
+HREF="http://tools.ietf.org/html/rfc4315">RFC 4315</A> as well as for all
+other folders (local folders in all formats, POP3 inbox, and newsgroups)
+as a subcommand of the apply command. If some selected messages are marked
+deleted, then the apply command will offer the eXpunge command, which when
+executed will only expunge those messages that are selected and deleted.
+
+<P>
+Observe that the expunge command (when not used from the apply command)
+will expunge/exclude all deleted messages from the folder, and so all
+messages marked deleted will be expunged, regardless of if they are
+selected or not. In other words, there is no protection against
+potentially expunging more messages than only those that have been
+selected and deleted.
<P>
The configuration features
diff --git a/web/src/alpined.d/alpined.c b/web/src/alpined.d/alpined.c
index 2132f95d..db9e86c0 100644
--- a/web/src/alpined.d/alpined.c
+++ b/web/src/alpined.d/alpined.c
@@ -4839,7 +4839,7 @@ PEFolderCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST
agg_select_all(stream, msgmap, NULL, 1);
errstr = peApplyFlag(stream, msgmap, 'd', 0, &count);
if(!errstr)
- (void) cmd_expunge_work(stream, msgmap);
+ (void) cmd_expunge_work(stream, msgmap, NULL);
}
}
else{
@@ -4864,7 +4864,7 @@ PEFolderCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST
if(!strucmp(what,"selected")){
if(any_lflagged(msgmap, MN_SLCT)){
if(!(errstr = peApplyFlag(stream, msgmap, 'd', 0, &count)))
- (void) cmd_expunge_work(stream, msgmap);
+ (void) cmd_expunge_work(stream, msgmap, NULL);
}
else
count = 0L;
@@ -4883,7 +4883,7 @@ PEFolderCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST
if(!errstr && uid){
/* uid is a UID here */
mail_flag(stream, long2string(uid), "\\DELETED", ST_SET | ST_UID);
- (void) cmd_expunge_work(stream, msgmap);
+ (void) cmd_expunge_work(stream, msgmap, NULL);
count = 1L;
}
}
@@ -5637,7 +5637,7 @@ PEMailboxCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST
ps_global->last_error[0] = '\0';
if(IS_NEWS(stream)
&& stream->rdonly){
- msgno_exclude_deleted(stream, msgmap);
+ msgno_exclude_deleted(stream, msgmap, NULL);
clear_index_cache(sp_inbox_stream(), 0);
/*
@@ -5651,7 +5651,7 @@ PEMailboxCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST
refresh_sort(ps_global->mail_stream, msgmap, FALSE);
}
else
- (void) cmd_expunge_work(stream, msgmap);
+ (void) cmd_expunge_work(stream, msgmap, NULL);
Tcl_SetResult(interp, ps_global->last_error, TCL_VOLATILE);
return(TCL_OK);
@@ -5683,7 +5683,7 @@ PEMailboxCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST
ps_global->last_error[0] = '\0';
if(IS_NEWS(stream) && stream->rdonly){
- msgno_exclude_deleted(stream, msgmap);
+ msgno_exclude_deleted(stream, msgmap, NULL);
clear_index_cache(sp_inbox_stream(), 0);
/*
@@ -5728,7 +5728,7 @@ PEMailboxCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST
/* then remove them */
if(n == tomove){
- (void) cmd_expunge_work(stream, msgmap);
+ (void) cmd_expunge_work(stream, msgmap, NULL);
}
restore_selected(msgmap);
@@ -6106,7 +6106,7 @@ PEMailboxCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST
return(TCL_OK);
}
else if(!strucmp(op, "excludedeleted")){
- msgno_exclude_deleted(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream));
+ msgno_exclude_deleted(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), NULL);
return(TCL_OK);
}
}