diff options
author | Eduardo Chappa <chappa@washington.edu> | 2013-10-13 02:08:28 -0600 |
---|---|---|
committer | Eduardo Chappa <chappa@washington.edu> | 2013-10-13 02:08:28 -0600 |
commit | ee95edb6a42df4b45c82080c32f852781f289a02 (patch) | |
tree | 1fc71517846468677163b76dbf2400b59d7997b5 | |
parent | 30a979ab1460a57d466a6a5cc6adb96eac452ce4 (diff) | |
download | alpine-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-- | VERSION | 2 | ||||
-rw-r--r-- | alpine/mailcmd.c | 76 | ||||
-rw-r--r-- | autom4te.cache/output.0 | 20 | ||||
-rw-r--r-- | autom4te.cache/output.2 | 20 | ||||
-rwxr-xr-x | configure | 20 | ||||
-rw-r--r-- | pico/file.c | 16 | ||||
-rw-r--r-- | pico/fileio.c | 5 | ||||
-rw-r--r-- | pico/line.c | 6 | ||||
-rw-r--r-- | pith/mailcmd.c | 9 | ||||
-rw-r--r-- | pith/mailcmd.h | 2 | ||||
-rw-r--r-- | pith/msgno.c | 3 | ||||
-rw-r--r-- | pith/msgno.h | 2 | ||||
-rw-r--r-- | pith/pine.hlp | 68 | ||||
-rw-r--r-- | web/src/alpined.d/alpined.c | 16 |
14 files changed, 170 insertions, 95 deletions
@@ -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\\" @@ -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 <End of help on this topic> </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); } } |