From 28e917644aba34cc803f5e509f8dd7e62f726b85d5f08d4063fdd17f2bbfe180 Mon Sep 17 00:00:00 2001 From: OBS User buildservice-autocommit Date: Thu, 30 Jun 2022 11:18:11 +0000 Subject: [PATCH] Updating link to change in openSUSE:Factory/alpine revision 56.0 OBS-URL: https://build.opensuse.org/package/show/server:mail/alpine?expand=0&rev=999e2ea8b36d85950ddb53f2f40ba78d --- UPDATING.txt | 4 +- alpine-2.25.1.tar.xz | 3 - alpine-2.26.tar.xz | 3 + alpine-2.26.tar.xz.sig | Bin 0 -> 566 bytes alpine.changes | 23 + alpine.spec | 14 +- chappa-DelText.patch | 29 +- chappa-colortext.patch | 132 +- chappa-fancy.patch | 666 ++-- chappa-fillpara.patch | 535 +-- chappa-fromheader.patch | 68 +- chappa-insertpat.patch | 20 +- chappa-maildir.patch | 7634 ++++++++++++++++++++------------------- chappa-rules.patch | 533 ++- 14 files changed, 4951 insertions(+), 4713 deletions(-) delete mode 100644 alpine-2.25.1.tar.xz create mode 100644 alpine-2.26.tar.xz create mode 100644 alpine-2.26.tar.xz.sig diff --git a/UPDATING.txt b/UPDATING.txt index 7de150e..9f85f86 100644 --- a/UPDATING.txt +++ b/UPDATING.txt @@ -4,8 +4,8 @@ Some features of Alpine do not exist in the release tarball but are only provided as patches (but by the same author..). So when there is a new release, the out-of-tree patches on the website get updated too. - version="2.25" - for i in WrtAcc colortext fancy fillpara fromheader insertpat maildir rules DelText; do + version="2.26" + for i in colortext fancy fillpara fromheader insertpat maildir rules DelText; do wget -O- "http://alpine.x10host.com/alpine/patches/alpine-$version/$i.patch.gz" | gzip -cd >"chappa-$i.patch"; done diff --git a/alpine-2.25.1.tar.xz b/alpine-2.25.1.tar.xz deleted file mode 100644 index 8357ce5..0000000 --- a/alpine-2.25.1.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:27f8360208a7eca7111e80c115ab94bdba1f40f666642bc0e0cae2732db7f2a0 -size 5388788 diff --git a/alpine-2.26.tar.xz b/alpine-2.26.tar.xz new file mode 100644 index 0000000..dd9f4c4 --- /dev/null +++ b/alpine-2.26.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0779c2be6c47d30554854a3e14ef5e36539502b331068851329275898a9baba +size 7517628 diff --git a/alpine-2.26.tar.xz.sig b/alpine-2.26.tar.xz.sig new file mode 100644 index 0000000000000000000000000000000000000000000000000000000000000000..2dd2f1b0236f24ad902fe7b142c9934b61138e9cb049db0766ff4b0103b78a68 GIT binary patch literal 566 zcmV-60?GY}0y6{v0SEvc79j+C%oJn`AY?PFEm0r7uukdff?2Hv0%Dm`SpW(N5WcWZ z>FR=6t!{D;|4&gqbht$Gd-IW{d25B1d9gFd>UiCidQ2YsnnUM2yg)L6+o@5ltqoZG zN=3LAZaFzu)O-YThK4@(3(RZ&$#kI*0YYWr{} z1(%H9VP(v71&2l)SRqX#Q}b||@sx0e^RNFosu3)FtO^?E+4h|atMAP=DXJ;^mz(0f z5FqQX`>kHNT@E!!m>hFxGduVSK;9KUumS&HMqvpQpQaa0i7|eW(m7BCd5TW0{{Z_J zp0vm~jnG5}uN1N5fwFYHmWD~e7h|OHQ*q3}nG0MnT;&iP(QO_T14;uow|;4R54-?j zQyT6;upUBqisaETU{do(Ff@eCd(BxuC8%oBm52C&w4&>b%x-ZXe9J&U%Zmcv1EFhm ziu0^vl}1)1@+!FxVGw7*rm%p415yPqhIY`sKn$9tuNI-jKU8o|miZ)CF^p3d&+P8u z32u~AvJXYni5r4uN}+<6W%~_a@pDkp)tHT-{wL5hxDB@egzQ1SXK?WQ!^wkDB0xb9 ze4|rc#pbKd4V1l10#_^Jxi@p2L%0=bUn<6KQ>Yga<*$PFYtAU9kIW$O)%X-C6BO$? E;R)6U@&Et; literal 0 HcmV?d00001 diff --git a/alpine.changes b/alpine.changes index cc1349e..21c828f 100644 --- a/alpine.changes +++ b/alpine.changes @@ -1,3 +1,26 @@ +------------------------------------------------------------------- +Fri Jun 10 15:51:07 UTC 2022 - Jan Engelhardt + +- Update to release 2.26 + * Alpine is built with password file support by default. If + Alpine is built with SMIME support and the password file does + not exist, then Alpine will create it by default and encrypt + it. + * In the past, Alpine did not recognize images embedded in an + HTML file, so now it does and a link to open them is given. + Additionally, Alpine did not pass these images to an external + browser for display using the external command; it does so now. + * Support for code_verifier and code_challenge when generating + a refresh token and access token in Gmail and Outlook using + the S256 method and plain method. + * Changed the redirect_uri scheme for Gmail, as Google is + deprecating the use of oob. Changed to http://localhost. + Users are supposed to enter the URL they see in their browser + in place of the code. + * Added support to the LDAP attribute "userCertificate"; + * If new mail has arrived when a user is closing a mailbox, + Alpine will also announce how many new messages have arrived. + ------------------------------------------------------------------- Tue Mar 15 10:46:48 UTC 2022 - Jan Engelhardt diff --git a/alpine.spec b/alpine.spec index 920f291..5218b9c 100644 --- a/alpine.spec +++ b/alpine.spec @@ -16,20 +16,22 @@ # +# grep '\*version' for new pico version number +# grep 'PILOT_VERSION' for new pilot version number Name: alpine # For debugging only: %define build_vanilla 0 -Version: 2.25.1 +Version: 2.26 Release: 0 Summary: Mail User Agent License: Apache-2.0 Group: Productivity/Networking/Email/Clients -URL: http://alpine.x10host.com/alpine/ +URL: https://alpineapp.email/ #Git-Clone: https://repo.or.cz/alpine.git -Source: %name-%version.tar.xz -#Source: http://alpine.x10host.com/alpine/release/src/alpine-%%version.tar.xz -#Source2: http://alpine.x10host.com/alpine/release/src/sig/alpine-%%version.tar.xz.sig +#Source: %name-%version.tar.xz +Source: https://alpineapp.email/alpine/release/src/alpine-%version.tar.xz +Source2: https://alpineapp.email/alpine/release/src/sig/alpine-%version.tar.xz.sig Source3: %name.png Source4: %name.desktop Source9: UPDATING.txt @@ -88,7 +90,7 @@ command. %package -n pico Summary: A small, easy to use editor Group: Productivity/Editors/Other -Version: 5.07 +Version: 5.09 Release: 0 %description -n pico diff --git a/chappa-DelText.patch b/chappa-DelText.patch index 28c8a35..0361a71 100644 --- a/chappa-DelText.patch +++ b/chappa-DelText.patch @@ -1,13 +1,13 @@ --- pico/basic.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ pico/efunc.h | 1 + - pico/search.c | 8 ++++++-- - 3 files changed, 57 insertions(+), 2 deletions(-) + pico/search.c | 7 ++++++- + 3 files changed, 57 insertions(+), 1 deletion(-) -Index: alpine-2.25.1/pico/basic.c +Index: alpine-2.26/pico/basic.c =================================================================== ---- alpine-2.25.1.orig/pico/basic.c -+++ alpine-2.25.1/pico/basic.c +--- alpine-2.26.orig/pico/basic.c ++++ alpine-2.26/pico/basic.c @@ -772,7 +772,57 @@ scrolldownline(int f, int n) return (scrollforw (1, FALSE)); } @@ -66,10 +66,10 @@ Index: alpine-2.25.1/pico/basic.c /* * Scroll to a position. -Index: alpine-2.25.1/pico/efunc.h +Index: alpine-2.26/pico/efunc.h =================================================================== ---- alpine-2.25.1.orig/pico/efunc.h -+++ alpine-2.25.1/pico/efunc.h +--- alpine-2.26.orig/pico/efunc.h ++++ alpine-2.26/pico/efunc.h @@ -56,6 +56,7 @@ extern int gotobop(int, int); extern int gotoeop(int, int); extern int forwpage(int, int); @@ -78,20 +78,19 @@ Index: alpine-2.25.1/pico/efunc.h extern int scrollupline(int, int); extern int scrolldownline(int, int); extern int scrollto(int, int); -Index: alpine-2.25.1/pico/search.c +Index: alpine-2.26/pico/search.c =================================================================== ---- alpine-2.25.1.orig/pico/search.c -+++ alpine-2.25.1/pico/search.c -@@ -69,7 +69,7 @@ EXTRAKEYS menu_srchpat[] = { +--- alpine-2.26.orig/pico/search.c ++++ alpine-2.26/pico/search.c +@@ -69,6 +69,7 @@ EXTRAKEYS menu_srchpat[] = { {"^O", N_("End of Para"), (CTRL|'O')}, {"^U", N_("FullJustify"), (CTRL|'U')}, {"^P", N_("Delete Para"), (CTRL|'P')}, -- {NULL, NULL, 0} + {"^X", N_("Del End"), (CTRL|'X')}, + {NULL, NULL, 0} }; - #define EXACTSR_KEY 1 /* toggle an exact or approximate search */ -@@ -282,7 +282,11 @@ forwsearch(int f, int n) +@@ -282,7 +283,11 @@ forwsearch(int f, int n) break; case (CTRL|'X'): diff --git a/chappa-colortext.patch b/chappa-colortext.patch index e152761..ffe8716 100644 --- a/chappa-colortext.patch +++ b/chappa-colortext.patch @@ -1,9 +1,9 @@ -diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.colortext/alpine/confscroll.c -*** alpine-2.25/alpine/confscroll.c 2021-09-18 09:02:36.346783285 -0600 ---- alpine-2.25.colortext/alpine/confscroll.c 2021-09-18 09:03:19.255079499 -0600 +diff -rc alpine-2.26/alpine/confscroll.c alpine-2.26.colortext/alpine/confscroll.c +*** alpine-2.26/alpine/confscroll.c 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.colortext/alpine/confscroll.c 2022-06-02 18:15:04.147118665 -0600 *************** -*** 5248,5253 **** ---- 5248,5256 ---- +*** 5246,5251 **** +--- 5246,5254 ---- clear_index_cache(ps->mail_stream, 0); } @@ -13,12 +13,12 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.colortext/alpine/confscroll else if(var == &ps->vars[V_INIT_CMD_LIST]){ if(!revert) q_status_message(SM_ASYNC, 0, 3, -diff -rc alpine-2.25/pith/conf.c alpine-2.25.colortext/pith/conf.c -*** alpine-2.25/pith/conf.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.colortext/pith/conf.c 2021-09-18 09:03:19.267079582 -0600 +diff -rc alpine-2.26/pith/conf.c alpine-2.26.colortext/pith/conf.c +*** alpine-2.26/pith/conf.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.colortext/pith/conf.c 2022-06-02 18:15:04.151118655 -0600 *************** -*** 233,238 **** ---- 233,240 ---- +*** 229,234 **** +--- 229,236 ---- CONF_TXT_T cf_text_fillcol[] = "Specifies the column of the screen where the composer should wrap."; @@ -28,8 +28,8 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.colortext/pith/conf.c CONF_TXT_T cf_text_quotereplstr[] = "Specifies the string to replace quotes with when viewing a message."; *************** -*** 589,594 **** ---- 591,598 ---- +*** 585,590 **** +--- 587,594 ---- #endif /* _WINDOWS */ {"composer-wrap-column", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL, cf_text_fillcol}, @@ -39,8 +39,8 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.colortext/pith/conf.c NULL, cf_text_replystr}, {"reply-leadin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, *************** -*** 866,871 **** ---- 870,877 ---- +*** 864,869 **** +--- 868,875 ---- {"incoming-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0}, {"signature-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0}, {"signature-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0}, @@ -61,8 +61,8 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.colortext/pith/conf.c set_current_val(&vars[V_HISTORY], TRUE, TRUE); set_current_val(&vars[V_SMTP_SERVER], TRUE, TRUE); *************** -*** 6684,6689 **** ---- 6692,6698 ---- +*** 6685,6690 **** +--- 6693,6699 ---- set_color_val(&vars[V_IND_OP_FORE_COLOR], 0); set_color_val(&vars[V_INCUNSEEN_FORE_COLOR], 0); set_color_val(&vars[V_SIGNATURE_FORE_COLOR], 0); @@ -71,8 +71,8 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.colortext/pith/conf.c set_current_val(&ps->vars[V_INDEX_TOKEN_COLORS], TRUE, TRUE); set_current_val(&ps->vars[V_VIEW_HDR_COLORS], TRUE, TRUE); *************** -*** 7933,7938 **** ---- 7942,7949 ---- +*** 7934,7939 **** +--- 7943,7950 ---- return(h_config_scroll_margin); case V_DEADLETS : return(h_config_deadlets); @@ -82,8 +82,8 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.colortext/pith/conf.c return(h_config_composer_wrap_column); case V_TCPOPENTIMEO : *************** -*** 8116,8121 **** ---- 8127,8135 ---- +*** 8119,8124 **** +--- 8130,8138 ---- case V_SIGNATURE_FORE_COLOR : case V_SIGNATURE_BACK_COLOR : return(h_config_signature_color); @@ -93,9 +93,9 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.colortext/pith/conf.c case V_PROMPT_FORE_COLOR : case V_PROMPT_BACK_COLOR : return(h_config_prompt_color); -diff -rc alpine-2.25/pith/conf.h alpine-2.25.colortext/pith/conf.h -*** alpine-2.25/pith/conf.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.colortext/pith/conf.h 2021-09-18 09:03:19.283079692 -0600 +diff -rc alpine-2.26/pith/conf.h alpine-2.26.colortext/pith/conf.h +*** alpine-2.26/pith/conf.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.colortext/pith/conf.h 2022-06-02 18:15:04.187118567 -0600 *************** *** 176,181 **** --- 176,183 ---- @@ -118,9 +118,9 @@ diff -rc alpine-2.25/pith/conf.h alpine-2.25.colortext/pith/conf.h #define VAR_PROMPT_FORE_COLOR vars[V_PROMPT_FORE_COLOR].current_val.p #define VAR_PROMPT_BACK_COLOR vars[V_PROMPT_BACK_COLOR].current_val.p #define VAR_VIEW_HDR_COLORS vars[V_VIEW_HDR_COLORS].current_val.l -diff -rc alpine-2.25/pith/conftype.h alpine-2.25.colortext/pith/conftype.h -*** alpine-2.25/pith/conftype.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.colortext/pith/conftype.h 2021-09-18 09:03:19.315079913 -0600 +diff -rc alpine-2.26/pith/conftype.h alpine-2.26.colortext/pith/conftype.h +*** alpine-2.26/pith/conftype.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.colortext/pith/conftype.h 2022-06-02 18:15:04.235118450 -0600 *************** *** 83,88 **** --- 83,89 ---- @@ -132,8 +132,8 @@ diff -rc alpine-2.25/pith/conftype.h alpine-2.25.colortext/pith/conftype.h , V_REPLY_INTRO , V_QUOTE_REPLACE_STRING *************** -*** 244,249 **** ---- 245,252 ---- +*** 246,251 **** +--- 247,254 ---- , V_INCUNSEEN_BACK_COLOR , V_SIGNATURE_FORE_COLOR , V_SIGNATURE_BACK_COLOR @@ -142,12 +142,12 @@ diff -rc alpine-2.25/pith/conftype.h alpine-2.25.colortext/pith/conftype.h , V_PROMPT_FORE_COLOR , V_PROMPT_BACK_COLOR , V_HEADER_GENERAL_FORE_COLOR -diff -rc alpine-2.25/pith/mailview.c alpine-2.25.colortext/pith/mailview.c -*** alpine-2.25/pith/mailview.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.colortext/pith/mailview.c 2021-09-18 09:03:19.367080271 -0600 +diff -rc alpine-2.26/pith/mailview.c alpine-2.26.colortext/pith/mailview.c +*** alpine-2.26/pith/mailview.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.colortext/pith/mailview.c 2022-06-02 18:15:04.251118410 -0600 *************** -*** 636,641 **** ---- 636,649 ---- +*** 632,637 **** +--- 632,645 ---- if((flgs & FM_DISPLAY) && !(flgs & FM_NOCOLOR) && pico_usingcolor() @@ -163,8 +163,8 @@ diff -rc alpine-2.25/pith/mailview.c alpine-2.25.colortext/pith/mailview.c && ps_global->VAR_SIGNATURE_BACK_COLOR){ gf_link_filter(gf_line_test, gf_line_test_opt(color_signature, &is_in_sig)); *************** -*** 2868,2873 **** ---- 2876,3065 ---- +*** 2864,2869 **** +--- 2872,3061 ---- return(color_pair); } @@ -295,7 +295,7 @@ diff -rc alpine-2.25/pith/mailview.c alpine-2.25.colortext/pith/mailview.c + else + return; + for (i = 0; isspace((unsigned char) p[ival->end - i - 1]); i++); -+ ival->end -= i; ++ ival->end -= i; + if (ival->next) + remove_spaces_ival(&(ival->next), p); + } @@ -325,7 +325,7 @@ diff -rc alpine-2.25/pith/mailview.c alpine-2.25.colortext/pith/mailview.c + int done = 0, begin_color = 0; + + while (!done){ -+ if (i = any_color_in_string(p)){ ++ if ((i = any_color_in_string(p))){ + begin_color = (begin_color + 1) % 2; + if (begin_color){ + p[i - 1] = '\0'; @@ -355,9 +355,9 @@ diff -rc alpine-2.25/pith/mailview.c alpine-2.25.colortext/pith/mailview.c /* * The argument fieldname is something like "Subject:..." or "Subject". -diff -rc alpine-2.25/pith/mailview.h alpine-2.25.colortext/pith/mailview.h -*** alpine-2.25/pith/mailview.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.colortext/pith/mailview.h 2021-09-18 09:03:19.379080355 -0600 +diff -rc alpine-2.26/pith/mailview.h alpine-2.26.colortext/pith/mailview.h +*** alpine-2.26/pith/mailview.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.colortext/pith/mailview.h 2022-06-02 18:15:04.263118380 -0600 *************** *** 30,35 **** --- 30,41 ---- @@ -391,12 +391,12 @@ diff -rc alpine-2.25/pith/mailview.h alpine-2.25.colortext/pith/mailview.h /* * BUG: BELOW IS UNIX/PC ONLY since config'd browser means nothing to webpine -diff -rc alpine-2.25/pith/pine.hlp alpine-2.25.colortext/pith/pine.hlp -*** alpine-2.25/pith/pine.hlp 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.colortext/pith/pine.hlp 2021-09-18 09:03:19.399080492 -0600 +diff -rc alpine-2.26/pith/pine.hlp alpine-2.26.colortext/pith/pine.hlp +*** alpine-2.26/pith/pine.hlp 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.colortext/pith/pine.hlp 2022-06-02 18:15:04.299118293 -0600 *************** -*** 5134,5139 **** ---- 5134,5140 ---- +*** 5290,5295 **** +--- 5290,5296 ----
  • OPTION:
  • OPTION:
  • OPTION: @@ -405,8 +405,8 @@ diff -rc alpine-2.25/pith/pine.hlp alpine-2.25.colortext/pith/pine.hlp
  • OPTION: Print-Font-Char-Set
  • OPTION: Print-Font-Name *************** -*** 5162,5167 **** ---- 5163,5169 ---- +*** 5318,5323 **** +--- 5319,5325 ----
  • OPTION:
  • OPTION:
  • OPTION: Signature Color @@ -415,8 +415,8 @@ diff -rc alpine-2.25/pith/pine.hlp alpine-2.25.colortext/pith/pine.hlp
  • OPTION:
  • OPTION: *************** -*** 25004,25009 **** ---- 25006,25048 ---- +*** 25158,25163 **** +--- 25160,25202 ---- <End of help on this topic> @@ -461,8 +461,8 @@ diff -rc alpine-2.25/pith/pine.hlp alpine-2.25.colortext/pith/pine.hlp *************** -*** 33616,33621 **** ---- 33655,33684 ---- +*** 33778,33783 **** +--- 33817,33846 ----

    Descriptions of the available commands @@ -493,12 +493,12 @@ diff -rc alpine-2.25/pith/pine.hlp alpine-2.25.colortext/pith/pine.hlp

    Look here to see the available Editing and Navigation commands. -diff -rc alpine-2.25/pith/state.c alpine-2.25.colortext/pith/state.c -*** alpine-2.25/pith/state.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.colortext/pith/state.c 2021-09-18 09:03:19.403080521 -0600 +diff -rc alpine-2.26/pith/state.c alpine-2.26.colortext/pith/state.c +*** alpine-2.26/pith/state.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.colortext/pith/state.c 2022-06-02 18:15:04.299118293 -0600 *************** -*** 144,149 **** ---- 144,152 ---- +*** 140,145 **** +--- 140,148 ---- if((*pps)->html_dir_list != NULL) free_html_log(&(*pps)->html_dir_list); @@ -508,12 +508,12 @@ diff -rc alpine-2.25/pith/state.c alpine-2.25.colortext/pith/state.c if((*pps)->ui.homedir) fs_give((void **)&(*pps)->ui.homedir); -diff -rc alpine-2.25/pith/state.h alpine-2.25.colortext/pith/state.h -*** alpine-2.25/pith/state.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.colortext/pith/state.h 2021-09-18 09:03:19.407080548 -0600 +diff -rc alpine-2.26/pith/state.h alpine-2.26.colortext/pith/state.h +*** alpine-2.26/pith/state.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.colortext/pith/state.h 2022-06-02 18:15:04.303118282 -0600 *************** -*** 349,354 **** ---- 349,356 ---- +*** 351,356 **** +--- 351,358 ---- char *display_charmap; /* needs to be freed */ char *keyboard_charmap; /* needs to be freed */ void *input_cs; @@ -522,12 +522,12 @@ diff -rc alpine-2.25/pith/state.h alpine-2.25.colortext/pith/state.h char *posting_charmap; /* needs to be freed */ -diff -rc alpine-2.25/pith/text.c alpine-2.25.colortext/pith/text.c -*** alpine-2.25/pith/text.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.colortext/pith/text.c 2021-09-18 09:03:19.415080603 -0600 +diff -rc alpine-2.26/pith/text.c alpine-2.26.colortext/pith/text.c +*** alpine-2.26/pith/text.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.colortext/pith/text.c 2022-06-02 18:15:04.315118253 -0600 *************** -*** 171,176 **** ---- 171,185 ---- +*** 167,172 **** +--- 167,181 ---- gf_url_hilite_opt(&uh,handlesp,0)); } diff --git a/chappa-fancy.patch b/chappa-fancy.patch index 5e6abe4..78598fe 100644 --- a/chappa-fancy.patch +++ b/chappa-fancy.patch @@ -1,9 +1,9 @@ -diff -rc alpine-2.25/alpine/arg.c alpine-2.25.fancy/alpine/arg.c -*** alpine-2.25/alpine/arg.c 2021-09-18 09:02:36.346783285 -0600 ---- alpine-2.25.fancy/alpine/arg.c 2021-09-18 09:03:09.487012066 -0600 +diff -rc alpine-2.26/alpine/arg.c alpine-2.26.fancy/alpine/arg.c +*** alpine-2.26/alpine/arg.c 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.fancy/alpine/arg.c 2022-06-02 18:14:51.007150883 -0600 *************** -*** 70,75 **** ---- 70,76 ---- +*** 66,71 **** +--- 66,72 ---- #endif /* SMIME inside PASSFILE */ #endif static char args_err_missing_sort[] = N_("missing argument for option \"-sort\""); @@ -12,8 +12,8 @@ diff -rc alpine-2.25/alpine/arg.c alpine-2.25.fancy/alpine/arg.c static char args_err_missing_flag_num[] = N_("Non numeric argument for flag \"%c\""); static char args_err_missing_debug_num[] = N_("Non numeric argument for \"%s\""); *************** -*** 119,124 **** ---- 120,126 ---- +*** 115,120 **** +--- 116,122 ---- N_(" -z \t\tSuspend - allow use of ^Z suspension"), N_(" -r \t\tRestricted - can only send mail to oneself"), N_(" -sort \tSort - Specify sort order of folder:"), @@ -22,8 +22,8 @@ diff -rc alpine-2.25/alpine/arg.c alpine-2.25.fancy/alpine/arg.c N_("\t\t\tfrom, size, score, to, cc, /reverse"), N_(" -i\t\tIndex - Go directly to index, bypassing main menu"), *************** -*** 285,290 **** ---- 287,293 ---- +*** 281,286 **** +--- 283,289 ---- char *cmd_list = NULL; char *debug_str = NULL; char *sort = NULL; @@ -32,8 +32,8 @@ diff -rc alpine-2.25/alpine/arg.c alpine-2.25.fancy/alpine/arg.c char *lc = NULL; XOAUTH2_INFO_S x; *************** -*** 508,513 **** ---- 511,527 ---- +*** 504,509 **** +--- 507,523 ---- goto Loop; } @@ -51,11 +51,11 @@ diff -rc alpine-2.25/alpine/arg.c alpine-2.25.fancy/alpine/arg.c else if(strcmp(*av, "url") == 0){ if(args->action == aaFolder && !args->data.folder){ args->action = aaURL; -diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c -*** alpine-2.25/alpine/confscroll.c 2021-09-18 09:02:36.346783285 -0600 ---- alpine-2.25.fancy/alpine/confscroll.c 2021-09-18 09:03:09.487012066 -0600 +diff -rc alpine-2.26/alpine/confscroll.c alpine-2.26.fancy/alpine/confscroll.c +*** alpine-2.26/alpine/confscroll.c 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.fancy/alpine/confscroll.c 2022-06-02 18:14:51.007150883 -0600 *************** -*** 140,146 **** +*** 136,142 **** char *radio_pretty_value(struct pine *, CONF_S *); char *sigfile_pretty_value(struct pine *, CONF_S *); char *color_pretty_value(struct pine *, CONF_S *); @@ -63,7 +63,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c int longest_feature_name(void); COLOR_PAIR *sample_color(struct pine *, struct variable *); COLOR_PAIR *sampleexc_color(struct pine *, struct variable *); ---- 140,146 ---- +--- 136,142 ---- char *radio_pretty_value(struct pine *, CONF_S *); char *sigfile_pretty_value(struct pine *, CONF_S *); char *color_pretty_value(struct pine *, CONF_S *); @@ -72,7 +72,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c COLOR_PAIR *sample_color(struct pine *, struct variable *); COLOR_PAIR *sampleexc_color(struct pine *, struct variable *); *************** -*** 288,294 **** +*** 284,290 **** CONF_S *ctmp; if(!(cl && *cl && @@ -80,7 +80,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c standard_radio_var(ps, (*cl)->var) || (*cl)->var == startup_ptr))) return; ---- 288,295 ---- +--- 284,291 ---- CONF_S *ctmp; if(!(cl && *cl && @@ -90,7 +90,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c (*cl)->var == startup_ptr))) return; *************** -*** 2958,2964 **** +*** 2956,2962 **** } set_current_val((*cl)->var, TRUE, TRUE); @@ -98,7 +98,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c ps->def_sort = def_sort; ps->def_sort_rev = def_sort_rev; } ---- 2959,2965 ---- +--- 2957,2963 ---- } set_current_val((*cl)->var, TRUE, TRUE); @@ -107,8 +107,8 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c ps->def_sort_rev = def_sort_rev; } *************** -*** 2967,2972 **** ---- 2968,3004 ---- +*** 2965,2970 **** +--- 2966,3002 ---- ps->mangled_body = 1; /* BUG: redraw it all for now? */ rv = 1; } @@ -147,7 +147,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c q_status_message(SM_ORDER | SM_DING, 3, 6, "Programmer botch! Unknown radiobutton type."); *************** -*** 3830,3836 **** +*** 3828,3834 **** else if(standard_radio_var(ps, v) || v == startup_ptr) return(radio_pretty_value(ps, cl)); else if(v == &ps->vars[V_SORT_KEY]) @@ -155,7 +155,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c else if(v == &ps->vars[V_SIGNATURE_FILE]) return(sigfile_pretty_value(ps, cl)); else if(v == &ps->vars[V_USE_ONLY_DOMAIN_NAME]) ---- 3862,3870 ---- +--- 3860,3868 ---- else if(standard_radio_var(ps, v) || v == startup_ptr) return(radio_pretty_value(ps, cl)); else if(v == &ps->vars[V_SORT_KEY]) @@ -166,7 +166,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c return(sigfile_pretty_value(ps, cl)); else if(v == &ps->vars[V_USE_ONLY_DOMAIN_NAME]) *************** -*** 4361,4374 **** +*** 4359,4372 **** char * @@ -181,7 +181,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c { char tmp[6*MAXPATH]; char *pvalnorm, *pvalexc, *pval; ---- 4395,4408 ---- +--- 4393,4406 ---- char * @@ -197,7 +197,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c char tmp[6*MAXPATH]; char *pvalnorm, *pvalexc, *pval; *************** -*** 4418,4424 **** +*** 4416,4422 **** } else if(fixed){ pval = v->fixed_val.p; @@ -205,7 +205,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c is_the_one = (var_sort_rev == line_sort_rev && var_sort == line_sort); utf8_snprintf(tmp, sizeof(tmp), "(%c) %s%-*w%*s%s", ---- 4452,4458 ---- +--- 4450,4456 ---- } else if(fixed){ pval = v->fixed_val.p; @@ -214,7 +214,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c utf8_snprintf(tmp, sizeof(tmp), "(%c) %s%-*w%*s%s", *************** -*** 4429,4437 **** +*** 4427,4435 **** is_the_one ? " (value is fixed)" : ""); } else if(is_set_for_this_level){ @@ -224,7 +224,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c the_exc_one = (editing_normal_which_isnt_except && pvalexc && exc_sort_rev == line_sort_rev && exc_sort == line_sort); utf8_snprintf(tmp, sizeof(tmp), "(%c) %s%-*w%*s%s", ---- 4463,4471 ---- +--- 4461,4469 ---- is_the_one ? " (value is fixed)" : ""); } else if(is_set_for_this_level){ @@ -235,7 +235,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c exc_sort_rev == line_sort_rev && exc_sort == line_sort); utf8_snprintf(tmp, sizeof(tmp), "(%c) %s%-*w%*s%s", *************** -*** 4449,4455 **** +*** 4447,4453 **** } else{ if(pvalexc){ @@ -243,7 +243,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c is_the_one = (exc_sort_rev == line_sort_rev && exc_sort == line_sort); utf8_snprintf(tmp, sizeof(tmp), "( ) %s%-*w%*s%s", ---- 4483,4489 ---- +--- 4481,4487 ---- } else{ if(pvalexc){ @@ -252,7 +252,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c exc_sort == line_sort); utf8_snprintf(tmp, sizeof(tmp), "( ) %s%-*w%*s%s", *************** -*** 4460,4466 **** +*** 4458,4464 **** } else{ pval = v->current_val.p; @@ -260,7 +260,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c is_the_one = ((pval || default_ok) && var_sort_rev == line_sort_rev && var_sort == line_sort); ---- 4494,4500 ---- +--- 4492,4498 ---- } else{ pval = v->current_val.p; @@ -269,7 +269,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c var_sort_rev == line_sort_rev && var_sort == line_sort); *************** -*** 5616,5624 **** +*** 5614,5622 **** else if(revert && var == &ps->vars[V_SORT_KEY]){ int def_sort_rev; @@ -279,7 +279,7 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c else if(var == &ps->vars[V_THREAD_MORE_CHAR] || var == &ps->vars[V_THREAD_EXP_CHAR] || var == &ps->vars[V_THREAD_LASTREPLY_CHAR]){ ---- 5650,5664 ---- +--- 5648,5662 ---- else if(revert && var == &ps->vars[V_SORT_KEY]){ int def_sort_rev; @@ -295,11 +295,11 @@ diff -rc alpine-2.25/alpine/confscroll.c alpine-2.25.fancy/alpine/confscroll.c else if(var == &ps->vars[V_THREAD_MORE_CHAR] || var == &ps->vars[V_THREAD_EXP_CHAR] || var == &ps->vars[V_THREAD_LASTREPLY_CHAR]){ -diff -rc alpine-2.25/alpine/confscroll.h alpine-2.25.fancy/alpine/confscroll.h -*** alpine-2.25/alpine/confscroll.h 2021-09-18 09:02:36.346783285 -0600 ---- alpine-2.25.fancy/alpine/confscroll.h 2021-09-18 09:03:09.487012066 -0600 +diff -rc alpine-2.26/alpine/confscroll.h alpine-2.26.fancy/alpine/confscroll.h +*** alpine-2.26/alpine/confscroll.h 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.fancy/alpine/confscroll.h 2022-06-02 18:14:51.007150883 -0600 *************** -*** 97,103 **** +*** 111,117 **** int radiobutton_tool(struct pine *, int, CONF_S **, unsigned); int yesno_tool(struct pine *, int, CONF_S **, unsigned); int text_toolit(struct pine *, int, CONF_S **, unsigned, int); @@ -307,7 +307,7 @@ diff -rc alpine-2.25/alpine/confscroll.h alpine-2.25.fancy/alpine/confscroll.h int exclude_config_var(struct pine *, struct variable *, int); int config_exit_cmd(unsigned); int simple_exit_cmd(unsigned); ---- 97,103 ---- +--- 111,117 ---- int radiobutton_tool(struct pine *, int, CONF_S **, unsigned); int yesno_tool(struct pine *, int, CONF_S **, unsigned); int text_toolit(struct pine *, int, CONF_S **, unsigned, int); @@ -315,11 +315,11 @@ diff -rc alpine-2.25/alpine/confscroll.h alpine-2.25.fancy/alpine/confscroll.h int exclude_config_var(struct pine *, struct variable *, int); int config_exit_cmd(unsigned); int simple_exit_cmd(unsigned); -diff -rc alpine-2.25/alpine/keymenu.c alpine-2.25.fancy/alpine/keymenu.c -*** alpine-2.25/alpine/keymenu.c 2021-09-18 09:02:36.346783285 -0600 ---- alpine-2.25.fancy/alpine/keymenu.c 2021-09-18 09:03:09.487012066 -0600 +diff -rc alpine-2.26/alpine/keymenu.c alpine-2.26.fancy/alpine/keymenu.c +*** alpine-2.26/alpine/keymenu.c 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.fancy/alpine/keymenu.c 2022-06-02 18:14:51.007150883 -0600 *************** -*** 679,688 **** +*** 675,684 **** RCOMPOSE_MENU, HOMEKEY_MENU, ENDKEY_MENU, @@ -330,7 +330,7 @@ diff -rc alpine-2.25/alpine/keymenu.c alpine-2.25.fancy/alpine/keymenu.c {"@", N_("Quota"), {MC_QUOTA,1,{'@'}}, KS_NONE}, NULL_MENU}; INST_KEY_MENU(index_keymenu, index_keys); ---- 679,703 ---- +--- 675,699 ---- RCOMPOSE_MENU, HOMEKEY_MENU, ENDKEY_MENU, @@ -357,7 +357,7 @@ diff -rc alpine-2.25/alpine/keymenu.c alpine-2.25.fancy/alpine/keymenu.c NULL_MENU}; INST_KEY_MENU(index_keymenu, index_keys); *************** -*** 757,765 **** +*** 753,761 **** RCOMPOSE_MENU, HOMEKEY_MENU, ENDKEY_MENU, @@ -367,7 +367,7 @@ diff -rc alpine-2.25/alpine/keymenu.c alpine-2.25.fancy/alpine/keymenu.c NULL_MENU}; INST_KEY_MENU(thread_keymenu, thread_keys); ---- 772,793 ---- +--- 768,789 ---- RCOMPOSE_MENU, HOMEKEY_MENU, ENDKEY_MENU, @@ -391,7 +391,7 @@ diff -rc alpine-2.25/alpine/keymenu.c alpine-2.25.fancy/alpine/keymenu.c INST_KEY_MENU(thread_keymenu, thread_keys); *************** -*** 927,933 **** +*** 923,929 **** NULL_MENU, NULL_MENU, NULL_MENU, @@ -399,7 +399,7 @@ diff -rc alpine-2.25/alpine/keymenu.c alpine-2.25.fancy/alpine/keymenu.c INST_KEY_MENU(view_keymenu, view_keys); ---- 955,974 ---- +--- 951,970 ---- NULL_MENU, NULL_MENU, NULL_MENU, @@ -420,9 +420,9 @@ diff -rc alpine-2.25/alpine/keymenu.c alpine-2.25.fancy/alpine/keymenu.c INST_KEY_MENU(view_keymenu, view_keys); -diff -rc alpine-2.25/alpine/keymenu.h alpine-2.25.fancy/alpine/keymenu.h -*** alpine-2.25/alpine/keymenu.h 2021-09-18 09:02:36.346783285 -0600 ---- alpine-2.25.fancy/alpine/keymenu.h 2021-09-18 09:03:09.523012315 -0600 +diff -rc alpine-2.26/alpine/keymenu.h alpine-2.26.fancy/alpine/keymenu.h +*** alpine-2.26/alpine/keymenu.h 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.fancy/alpine/keymenu.h 2022-06-02 18:14:51.051150774 -0600 *************** *** 220,225 **** --- 220,238 ---- @@ -445,11 +445,11 @@ diff -rc alpine-2.25/alpine/keymenu.h alpine-2.25.fancy/alpine/keymenu.h /* Commands for S/MIME screens */ #define MC_TRUST 900 -diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c -*** alpine-2.25/alpine/mailcmd.c 2021-09-18 09:02:36.346783285 -0600 ---- alpine-2.25.fancy/alpine/mailcmd.c 2021-09-18 09:03:09.523012315 -0600 +diff -rc alpine-2.26/alpine/mailcmd.c alpine-2.26.fancy/alpine/mailcmd.c +*** alpine-2.26/alpine/mailcmd.c 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.fancy/alpine/mailcmd.c 2022-06-02 18:14:51.079150706 -0600 *************** -*** 114,120 **** +*** 110,116 **** char *choose_a_rule(int); int select_by_keyword(MAILSTREAM *, SEARCHSET **); char *choose_a_keyword(void); @@ -457,7 +457,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c int print_index(struct pine *, MSGNO_S *, int); /* ---- 114,120 ---- +--- 110,116 ---- char *choose_a_rule(int); int select_by_keyword(MAILSTREAM *, SEARCHSET **); char *choose_a_keyword(void); @@ -466,7 +466,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c /* *************** -*** 1438,1444 **** +*** 1437,1443 **** if(any_messages(msgmap, NULL, NULL)){ if(any_lflagged(msgmap, MN_SLCT) > 0L){ if(apply_command(state, stream, msgmap, 0, @@ -474,7 +474,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c if(F_ON(F_AUTO_UNSELECT, state)){ agg_select_all(stream, msgmap, NULL, 0); unzoom_index(state, stream, msgmap); ---- 1438,1444 ---- +--- 1437,1443 ---- if(any_messages(msgmap, NULL, NULL)){ if(any_lflagged(msgmap, MN_SLCT) > 0L){ if(apply_command(state, stream, msgmap, 0, @@ -483,7 +483,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c agg_select_all(stream, msgmap, NULL, 0); unzoom_index(state, stream, msgmap); *************** -*** 1456,1478 **** +*** 1455,1477 **** /*-------- Sort command -------*/ case MC_SORT : @@ -507,7 +507,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c } state->mangled_footer = 1; ---- 1456,1490 ---- +--- 1455,1489 ---- /*-------- Sort command -------*/ case MC_SORT : @@ -544,8 +544,8 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c state->mangled_footer = 1; *************** -*** 3315,3320 **** ---- 3327,3336 ---- +*** 3314,3319 **** +--- 3326,3335 ---- if(SORT_IS_THREADED(msgmap)) refresh_sort(stream, msgmap, SRT_NON); @@ -557,8 +557,8 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c state->mangled_header = 1; q_status_message2(SM_ORDER, 0, 4, *************** -*** 3416,3421 **** ---- 3432,3440 ---- +*** 3415,3420 **** +--- 3431,3439 ---- */ if(SORT_IS_THREADED(msgmap)) refresh_sort(stream, msgmap, SRT_NON); @@ -569,7 +569,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c else{ if(del_count){ *************** -*** 7334,7340 **** +*** 7333,7339 **** * Maybe it makes sense to zoom after a select but not after a colon * command even though they are very similar. */ @@ -577,7 +577,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c } else{ if((all_selected = ---- 7353,7359 ---- +--- 7352,7358 ---- * Maybe it makes sense to zoom after a select but not after a colon * command even though they are very similar. */ @@ -586,7 +586,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c else{ if((all_selected = *************** -*** 7390,7396 **** +*** 7389,7395 **** ----*/ int apply_command(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap, @@ -594,7 +594,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c { int i = 8, /* number of static entries in sel_opts3 */ rv = 0, ---- 7409,7415 ---- +--- 7408,7414 ---- ----*/ int apply_command(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap, @@ -603,7 +603,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c int i = 8, /* number of static entries in sel_opts3 */ rv = 0, *************** -*** 7557,7565 **** +*** 7556,7564 **** collapse_or_expand(state, stream, msgmap, F_ON(F_SLASH_COLL_ENTIRE, ps_global) ? 0L @@ -613,7 +613,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c case ':' : select_thread_stmp(state, stream, msgmap); break; ---- 7576,7594 ---- +--- 7575,7593 ---- collapse_or_expand(state, stream, msgmap, F_ON(F_SLASH_COLL_ENTIRE, ps_global) ? 0L @@ -634,7 +634,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c select_thread_stmp(state, stream, msgmap); break; *************** -*** 9605,9614 **** +*** 9604,9613 **** Returns 0 if it was cancelled, 1 otherwise. ----*/ int @@ -645,7 +645,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c int deefault = 'a', retval = 1; HelpType help; ESCKEY_S sorts[14]; ---- 9634,9643 ---- +--- 9633,9642 ---- Returns 0 if it was cancelled, 1 otherwise. ----*/ int @@ -657,7 +657,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c HelpType help; ESCKEY_S sorts[14]; *************** -*** 9641,9657 **** +*** 9640,9656 **** strncpy(prompt, _("Choose type of sort, or 'R' to reverse current sort : "), sizeof(prompt)); @@ -675,7 +675,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c } sorts[i].ch = 'r'; ---- 9670,9695 ---- +--- 9669,9694 ---- strncpy(prompt, _("Choose type of sort, or 'R' to reverse current sort : "), sizeof(prompt)); @@ -703,7 +703,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c sorts[i].ch = 'r'; *************** -*** 9675,9682 **** +*** 9674,9681 **** state->mangled_body = 1; /* signal screen's changed */ if(s == 'r') *rev = !mn_get_revsort(state->msgmap); @@ -712,7 +712,7 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c if(F_ON(F_SHOW_SORT, ps_global)) ps_global->mangled_header = 1; ---- 9713,9729 ---- +--- 9712,9728 ---- state->mangled_body = 1; /* signal screen's changed */ if(s == 'r') *rev = !mn_get_revsort(state->msgmap); @@ -731,8 +731,8 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c if(F_ON(F_SHOW_SORT, ps_global)) ps_global->mangled_header = 1; *************** -*** 10060,10062 **** ---- 10107,10484 ---- +*** 10059,10061 **** +--- 10106,10484 ---- } #endif /* _WINDOWS */ @@ -946,11 +946,12 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c + if (collapsed && special + && ((F_OFF(F_ENHANCED_THREAD, state) && !thrd->next) + || F_ON(F_ENHANCED_THREAD, state))){ -+ if (thrd->toploose) ++ if (thrd->toploose){ + if (thrd->rawno != thrd->toploose) + set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno),MN_CHID, 0); + else + set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno),MN_COLL, 0); ++ } + } + else{ + rv = 0; @@ -1111,9 +1112,9 @@ diff -rc alpine-2.25/alpine/mailcmd.c alpine-2.25.fancy/alpine/mailcmd.c + expand_thread(state, stream, msgmap, 0); + } + -diff -rc alpine-2.25/alpine/mailcmd.h alpine-2.25.fancy/alpine/mailcmd.h -*** alpine-2.25/alpine/mailcmd.h 2021-09-18 09:02:36.346783285 -0600 ---- alpine-2.25.fancy/alpine/mailcmd.h 2021-09-18 09:03:09.523012315 -0600 +diff -rc alpine-2.26/alpine/mailcmd.h alpine-2.26.fancy/alpine/mailcmd.h +*** alpine-2.26/alpine/mailcmd.h 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.fancy/alpine/mailcmd.h 2022-06-02 18:14:51.087150687 -0600 *************** *** 90,96 **** int ask_mailbox_reopen(struct pine *, int *); @@ -1155,12 +1156,12 @@ diff -rc alpine-2.25/alpine/mailcmd.h alpine-2.25.fancy/alpine/mailcmd.h ! int expand_this_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int, int); #endif /* PINE_MAILCMD_INCLUDED */ -diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c -*** alpine-2.25/alpine/mailindx.c 2021-09-18 09:02:36.346783285 -0600 ---- alpine-2.25.fancy/alpine/mailindx.c 2021-09-18 09:03:09.523012315 -0600 +diff -rc alpine-2.26/alpine/mailindx.c alpine-2.26.fancy/alpine/mailindx.c +*** alpine-2.26/alpine/mailindx.c 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.fancy/alpine/mailindx.c 2022-06-02 18:14:51.131150578 -0600 *************** -*** 564,569 **** ---- 564,570 ---- +*** 560,565 **** +--- 560,566 ---- /*---------- Scroll line up ----------*/ case MC_CHARUP : @@ -1169,8 +1170,8 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c (style == MsgIndex || style == MultiMsgIndex *************** -*** 581,586 **** ---- 582,588 ---- +*** 577,582 **** +--- 578,584 ---- /*---------- Scroll line down ----------*/ case MC_CHARDOWN : @@ -1179,8 +1180,8 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c * Special Page framing handling here. If we * did something that should scroll-by-a-line, frame *************** -*** 798,803 **** ---- 800,806 ---- +*** 794,799 **** +--- 796,802 ---- case MC_THRDINDX : @@ -1189,7 +1190,7 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c PINETHRD_S *thrd, *topthrd; for(i = 1L; i > 0L && i <= mn_get_total(msgmap);){ *************** -*** 865,871 **** +*** 861,867 **** && mp.col == id.plus_col && style != ThreadIndex){ collapse_or_expand(state, stream, msgmap, @@ -1197,7 +1198,7 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c } else if (mp.doubleclick){ if(mp.button == M_BUTTON_LEFT){ ---- 868,874 ---- +--- 864,870 ---- && mp.col == id.plus_col && style != ThreadIndex){ collapse_or_expand(state, stream, msgmap, @@ -1206,7 +1207,7 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c else if (mp.doubleclick){ if(mp.button == M_BUTTON_LEFT){ *************** -*** 974,982 **** +*** 970,978 **** case MC_COLLAPSE : @@ -1216,7 +1217,7 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c case MC_DELETE : case MC_UNDELETE : case MC_REPLY : ---- 977,1081 ---- +--- 973,1076 ---- case MC_COLLAPSE : @@ -1240,8 +1241,7 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c + case MC_OTHREAD : + if (SEP_THRDINDX()) + goto view_a_thread; -+ else -+ if (THREADING()){ ++ else if (THREADING()){ + if (any_messages(ps_global->msgmap, NULL, "to expand a thread")) + expand_thread(state, stream,msgmap, 1); + } @@ -1323,7 +1323,7 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c case MC_UNDELETE : case MC_REPLY : *************** -*** 997,1009 **** +*** 993,1005 **** if(rawno) thrd = fetch_thread(stream, rawno); @@ -1337,7 +1337,7 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c /* increment current */ if(cmd == MC_DELETE){ advance_cur_after_delete(state, stream, msgmap, ---- 1096,1107 ---- +--- 1091,1102 ---- if(rawno) thrd = fetch_thread(stream, rawno); @@ -1351,8 +1351,8 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c if(cmd == MC_DELETE){ advance_cur_after_delete(state, stream, msgmap, *************** -*** 2696,2701 **** ---- 2794,2800 ---- +*** 2692,2697 **** +--- 2789,2795 ---- n = mn_raw2m(msgs, thrd->rawno); while(thrd){ @@ -1361,7 +1361,7 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c && (++m % lines_per_page) == 1L) t = n; *************** -*** 2764,2774 **** +*** 2760,2770 **** /* n is the end of this thread */ while(thrd){ @@ -1373,21 +1373,21 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c else thrd = NULL; } ---- 2863,2874 ---- +--- 2858,2869 ---- /* n is the end of this thread */ while(thrd){ + unsigned long next = 0L, branch = 0L; n = mn_raw2m(msgs, thrd->rawno); -! if(branch = get_branch(stream,thrd)) +! if((branch = get_branch(stream,thrd))) ! thrd = fetch_thread(stream, branch); -! else if(next = get_next(stream,thrd)) +! else if((next = get_next(stream,thrd))) ! thrd = fetch_thread(stream, next); else thrd = NULL; } *************** -*** 2876,2882 **** +*** 2872,2878 **** void thread_command(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap, @@ -1395,7 +1395,7 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c { PINETHRD_S *thrd = NULL; unsigned long rawno, save_branch; ---- 2976,2982 ---- +--- 2971,2977 ---- void thread_command(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap, @@ -1404,7 +1404,7 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c PINETHRD_S *thrd = NULL; unsigned long rawno, save_branch; *************** -*** 2925,2931 **** +*** 2921,2927 **** cancel_busy_cue(0); (void ) apply_command(state, stream, msgmap, preloadkeystroke, flags, @@ -1412,7 +1412,7 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c /* restore the original flags */ copy_lflags(stream, msgmap, MN_STMP, MN_SLCT); ---- 3025,3031 ---- +--- 3020,3026 ---- cancel_busy_cue(0); (void ) apply_command(state, stream, msgmap, preloadkeystroke, flags, @@ -1421,7 +1421,7 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c /* restore the original flags */ copy_lflags(stream, msgmap, MN_STMP, MN_SLCT); *************** -*** 3442,3448 **** +*** 3438,3444 **** if(set){ sort_folder(ps_global->mail_stream, ps_global->msgmap, order & 0x000000ff, @@ -1429,7 +1429,7 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c mswin_beginupdate(); update_titlebar_message(); update_titlebar_status(); ---- 3542,3548 ---- +--- 3537,3543 ---- if(set){ sort_folder(ps_global->mail_stream, ps_global->msgmap, order & 0x000000ff, @@ -1437,9 +1437,9 @@ diff -rc alpine-2.25/alpine/mailindx.c alpine-2.25.fancy/alpine/mailindx.c mswin_beginupdate(); update_titlebar_message(); update_titlebar_status(); -diff -rc alpine-2.25/alpine/mailindx.h alpine-2.25.fancy/alpine/mailindx.h -*** alpine-2.25/alpine/mailindx.h 2021-09-18 09:02:36.346783285 -0600 ---- alpine-2.25.fancy/alpine/mailindx.h 2021-09-18 09:03:09.523012315 -0600 +diff -rc alpine-2.26/alpine/mailindx.h alpine-2.26.fancy/alpine/mailindx.h +*** alpine-2.26/alpine/mailindx.h 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.fancy/alpine/mailindx.h 2022-06-02 18:14:51.143150549 -0600 *************** *** 103,109 **** void paint_index_hline(MAILSTREAM *, long, ICE_S *); @@ -1457,12 +1457,12 @@ diff -rc alpine-2.25/alpine/mailindx.h alpine-2.25.fancy/alpine/mailindx.h COLOR_PAIR *apply_rev_color(COLOR_PAIR *, int); #ifdef _WINDOWS int index_sort_callback(int, long); -diff -rc alpine-2.25/alpine/mailview.c alpine-2.25.fancy/alpine/mailview.c -*** alpine-2.25/alpine/mailview.c 2021-09-18 09:02:36.350783312 -0600 ---- alpine-2.25.fancy/alpine/mailview.c 2021-09-18 09:03:09.523012315 -0600 +diff -rc alpine-2.26/alpine/mailview.c alpine-2.26.fancy/alpine/mailview.c +*** alpine-2.26/alpine/mailview.c 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.fancy/alpine/mailview.c 2022-06-02 18:14:51.167150490 -0600 *************** -*** 3496,3501 **** ---- 3496,3547 ---- +*** 3670,3675 **** +--- 3670,3721 ---- print_to_printer(sparms); break; @@ -1473,7 +1473,7 @@ diff -rc alpine-2.25/alpine/mailview.c alpine-2.25.fancy/alpine/mailview.c + "to move to other thread")) + move_thread(ps_global, ps_global->mail_stream, ps_global->msgmap, + cmd == MC_NEXTHREAD ? 1 : -1); -+ done = 1; ++ done = 1; + } + else + q_status_message(SM_ORDER, 0, 1, @@ -1515,11 +1515,11 @@ diff -rc alpine-2.25/alpine/mailview.c alpine-2.25.fancy/alpine/mailview.c /* ------- First handle on Line ------ */ case MC_GOTOBOL : -diff -rc alpine-2.25/alpine/roleconf.c alpine-2.25.fancy/alpine/roleconf.c -*** alpine-2.25/alpine/roleconf.c 2021-09-18 09:02:36.350783312 -0600 ---- alpine-2.25.fancy/alpine/roleconf.c 2021-09-18 09:03:09.527012342 -0600 +diff -rc alpine-2.26/alpine/roleconf.c alpine-2.26.fancy/alpine/roleconf.c +*** alpine-2.26/alpine/roleconf.c 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.fancy/alpine/roleconf.c 2022-06-02 18:14:51.175150471 -0600 *************** -*** 4477,4487 **** +*** 4473,4483 **** ctmp->tool = role_sort_tool; ctmp->valoffset = rindent; ctmp->flags |= CF_NOSELECT; @@ -1531,7 +1531,7 @@ diff -rc alpine-2.25/alpine/roleconf.c alpine-2.25.fancy/alpine/roleconf.c /* allow user to set their default sort order */ new_confline(&ctmp)->var = &sort_act_var; ---- 4477,4487 ---- +--- 4473,4483 ---- ctmp->tool = role_sort_tool; ctmp->valoffset = rindent; ctmp->flags |= CF_NOSELECT; @@ -1544,7 +1544,7 @@ diff -rc alpine-2.25/alpine/roleconf.c alpine-2.25.fancy/alpine/roleconf.c /* allow user to set their default sort order */ new_confline(&ctmp)->var = &sort_act_var; *************** -*** 4491,4497 **** +*** 4487,4493 **** ctmp->tool = role_sort_tool; ctmp->valoffset = rindent; ctmp->varmem = -1; @@ -1552,7 +1552,7 @@ diff -rc alpine-2.25/alpine/roleconf.c alpine-2.25.fancy/alpine/roleconf.c for(j = 0; j < 2; j++){ for(i = 0; ps->sort_types[i] != EndofList; i++){ ---- 4491,4497 ---- +--- 4487,4493 ---- ctmp->tool = role_sort_tool; ctmp->valoffset = rindent; ctmp->varmem = -1; @@ -1561,7 +1561,7 @@ diff -rc alpine-2.25/alpine/roleconf.c alpine-2.25.fancy/alpine/roleconf.c for(j = 0; j < 2; j++){ for(i = 0; ps->sort_types[i] != EndofList; i++){ *************** -*** 4503,4509 **** +*** 4499,4505 **** ctmp->valoffset = rindent; ctmp->varmem = i + (j * EndofList); ctmp->value = generalized_sort_pretty_value(ps, ctmp, @@ -1569,7 +1569,7 @@ diff -rc alpine-2.25/alpine/roleconf.c alpine-2.25.fancy/alpine/roleconf.c } } ---- 4503,4509 ---- +--- 4499,4505 ---- ctmp->valoffset = rindent; ctmp->varmem = i + (j * EndofList); ctmp->value = generalized_sort_pretty_value(ps, ctmp, @@ -1578,7 +1578,7 @@ diff -rc alpine-2.25/alpine/roleconf.c alpine-2.25.fancy/alpine/roleconf.c } *************** -*** 5436,5442 **** +*** 5432,5438 **** (*result)->patgrp->stat_boy = PAT_STAT_EITHER; if(sort_act){ @@ -1586,7 +1586,7 @@ diff -rc alpine-2.25/alpine/roleconf.c alpine-2.25.fancy/alpine/roleconf.c (*result)->action->sort_is_set = 1; (*result)->action->sortorder = def_sort; (*result)->action->revsort = (def_sort_rev ? 1 : 0); ---- 5436,5442 ---- +--- 5432,5438 ---- (*result)->patgrp->stat_boy = PAT_STAT_EITHER; if(sort_act){ @@ -1594,11 +1594,11 @@ diff -rc alpine-2.25/alpine/roleconf.c alpine-2.25.fancy/alpine/roleconf.c (*result)->action->sort_is_set = 1; (*result)->action->sortorder = def_sort; (*result)->action->revsort = (def_sort_rev ? 1 : 0); -diff -rc alpine-2.25/alpine/setup.c alpine-2.25.fancy/alpine/setup.c -*** alpine-2.25/alpine/setup.c 2021-09-18 09:02:36.350783312 -0600 ---- alpine-2.25.fancy/alpine/setup.c 2021-09-18 09:03:09.527012342 -0600 +diff -rc alpine-2.26/alpine/setup.c alpine-2.26.fancy/alpine/setup.c +*** alpine-2.26/alpine/setup.c 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.fancy/alpine/setup.c 2022-06-02 18:14:51.207150392 -0600 *************** -*** 262,268 **** +*** 258,264 **** ctmpa->flags |= CF_NOSELECT; ctmpa->value = cpystr("--- ----------------------"); @@ -1606,7 +1606,7 @@ diff -rc alpine-2.25/alpine/setup.c alpine-2.25.fancy/alpine/setup.c for(j = 0; j < 2; j++){ for(i = 0; ps->sort_types[i] != EndofList; i++){ ---- 262,268 ---- +--- 258,264 ---- ctmpa->flags |= CF_NOSELECT; ctmpa->value = cpystr("--- ----------------------"); @@ -1615,8 +1615,8 @@ diff -rc alpine-2.25/alpine/setup.c alpine-2.25.fancy/alpine/setup.c for(j = 0; j < 2; j++){ for(i = 0; ps->sort_types[i] != EndofList; i++){ *************** -*** 277,282 **** ---- 277,331 ---- +*** 273,278 **** +--- 273,327 ---- } } } @@ -1673,8 +1673,8 @@ diff -rc alpine-2.25/alpine/setup.c alpine-2.25.fancy/alpine/setup.c ctmpa->keymenu = &config_yesno_keymenu; ctmpa->tool = yesno_tool; *************** -*** 469,474 **** ---- 518,532 ---- +*** 465,470 **** +--- 514,528 ---- } } @@ -1690,12 +1690,12 @@ diff -rc alpine-2.25/alpine/setup.c alpine-2.25.fancy/alpine/setup.c treat_color_vars_as_text = 0; free_saved_config(ps, &vsave, expose_hidden_config); #ifdef _WINDOWS -diff -rc alpine-2.25/pith/conf.c alpine-2.25.fancy/pith/conf.c -*** alpine-2.25/pith/conf.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fancy/pith/conf.c 2021-09-18 09:03:09.527012342 -0600 +diff -rc alpine-2.26/pith/conf.c alpine-2.26.fancy/pith/conf.c +*** alpine-2.26/pith/conf.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fancy/pith/conf.c 2022-06-02 18:14:51.247150294 -0600 *************** -*** 207,212 **** ---- 207,214 ---- +*** 203,208 **** +--- 203,210 ---- CONF_TXT_T cf_text_sort_key[] = "Sets presentation order of messages in Index. Choices:\n# Subject, From, Arrival, Date, Size, To, Cc, OrderedSubj, Score, and Thread.\n# Order may be reversed by appending /Reverse. Default: \"Arrival\"."; @@ -1705,8 +1705,8 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.fancy/pith/conf.c CONF_TXT_T cf_text_folder_sort_rule[] = "Sets presentation order of folder list entries. Choices: alphabetical,\n# alpha-with-dirs-last, alpha-with-dirs-first.\n# Default: \"alpha-with-directories-last\"."; *************** -*** 545,550 **** ---- 547,554 ---- +*** 541,546 **** +--- 543,550 ---- NULL, cf_text_fcc_name_rule}, {"sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL, cf_text_sort_key}, @@ -1716,7 +1716,7 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.fancy/pith/conf.c "Address Book Sort Rule", cf_text_addrbook_sort_rule}, {"folder-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, *************** -*** 1617,1623 **** +*** 1615,1621 **** register struct variable *vars = ps->vars; int obs_header_in_reply = 0, /* the obs_ variables are to */ obs_old_style_reply = 0, /* support backwards compatibility */ @@ -1724,7 +1724,7 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.fancy/pith/conf.c long rvl; PINERC_S *fixedprc = NULL; FeatureLevel obs_feature_level; ---- 1621,1627 ---- +--- 1619,1625 ---- register struct variable *vars = ps->vars; int obs_header_in_reply = 0, /* the obs_ variables are to */ obs_old_style_reply = 0, /* support backwards compatibility */ @@ -1743,7 +1743,7 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.fancy/pith/conf.c GLO_FCC_RULE = cpystr(DF_FCC_RULE); GLO_AB_SORT_RULE = cpystr(DF_AB_SORT_RULE); *************** -*** 2645,2651 **** +*** 2647,2653 **** set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE); set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE); set_current_val(&vars[V_SORT_KEY], TRUE, TRUE); @@ -1751,7 +1751,7 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.fancy/pith/conf.c snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY); init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf); ps->def_sort = SortArrival; ---- 2650,2656 ---- +--- 2652,2658 ---- set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE); set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE); set_current_val(&vars[V_SORT_KEY], TRUE, TRUE); @@ -1760,8 +1760,8 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.fancy/pith/conf.c init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf); ps->def_sort = SortArrival; *************** -*** 2654,2659 **** ---- 2659,2675 ---- +*** 2656,2661 **** +--- 2661,2677 ---- else ps->def_sort_rev = def_sort_rev; @@ -1780,8 +1780,8 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.fancy/pith/conf.c {NAMEVAL_S *v; int i; for(i = 0; (v = save_msg_rules(i)); i++) *************** -*** 3079,3084 **** ---- 3095,3102 ---- +*** 3081,3086 **** +--- 3097,3104 ---- F_COLOR_LINE_IMPORTANT, h_config_color_thrd_import, PREF_INDX, 0}, {"thread-sorts-by-arrival", "Thread Sorts by Arrival", F_THREAD_SORTS_BY_ARRIVAL, h_config_thread_sorts_by_arrival, PREF_INDX, 0}, @@ -1791,8 +1791,8 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.fancy/pith/conf.c /* Viewer prefs */ {"enable-msg-view-addresses", "Enable Message View Address Links", *************** -*** 7875,7880 **** ---- 7893,7900 ---- +*** 7876,7881 **** +--- 7894,7901 ---- return(h_config_fcc_rule); case V_SORT_KEY : return(h_config_sort_key); @@ -1801,9 +1801,9 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.fancy/pith/conf.c case V_AB_SORT_RULE : return(h_config_ab_sort_rule); case V_FLD_SORT_RULE : -diff -rc alpine-2.25/pith/conf.h alpine-2.25.fancy/pith/conf.h -*** alpine-2.25/pith/conf.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fancy/pith/conf.h 2021-09-18 09:03:09.527012342 -0600 +diff -rc alpine-2.26/pith/conf.h alpine-2.26.fancy/pith/conf.h +*** alpine-2.26/pith/conf.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fancy/pith/conf.h 2022-06-02 18:14:51.259150264 -0600 *************** *** 155,160 **** --- 155,163 ---- @@ -1816,9 +1816,9 @@ diff -rc alpine-2.25/pith/conf.h alpine-2.25.fancy/pith/conf.h #define VAR_AB_SORT_RULE vars[V_AB_SORT_RULE].current_val.p #define GLO_AB_SORT_RULE vars[V_AB_SORT_RULE].global_val.p #define VAR_FLD_SORT_RULE vars[V_FLD_SORT_RULE].current_val.p -diff -rc alpine-2.25/pith/conftype.h alpine-2.25.fancy/pith/conftype.h -*** alpine-2.25/pith/conftype.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fancy/pith/conftype.h 2021-09-18 09:03:09.527012342 -0600 +diff -rc alpine-2.26/pith/conftype.h alpine-2.26.fancy/pith/conftype.h +*** alpine-2.26/pith/conftype.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fancy/pith/conftype.h 2022-06-02 18:14:51.303150157 -0600 *************** *** 59,64 **** --- 59,65 ---- @@ -1830,8 +1830,8 @@ diff -rc alpine-2.25/pith/conftype.h alpine-2.25.fancy/pith/conftype.h , V_FLD_SORT_RULE , V_GOTO_DEFAULT_RULE *************** -*** 528,533 **** ---- 529,535 ---- +*** 530,535 **** +--- 531,537 ---- F_QUELL_TIMEZONE, F_QUELL_USERAGENT, F_COLOR_LINE_IMPORTANT, @@ -1840,19 +1840,19 @@ diff -rc alpine-2.25/pith/conftype.h alpine-2.25.fancy/pith/conftype.h F_ENABLE_FULL_HDR_AND_TEXT, F_QUELL_FULL_HDR_RESET, *************** -*** 793,797 **** ---- 795,800 ---- +*** 795,799 **** +--- 797,802 ---- /* exported prototypes */ + #define DF_THREAD_SORT_KEY "thread" #endif /* PITH_CONFTYPE_INCLUDED */ -diff -rc alpine-2.25/pith/flag.c alpine-2.25.fancy/pith/flag.c -*** alpine-2.25/pith/flag.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fancy/pith/flag.c 2021-09-18 09:03:09.527012342 -0600 +diff -rc alpine-2.26/pith/flag.c alpine-2.26.fancy/pith/flag.c +*** alpine-2.26/pith/flag.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fancy/pith/flag.c 2022-06-02 18:14:51.319150118 -0600 *************** -*** 592,605 **** +*** 588,601 **** was_invisible = (pelt->hidden || pelt->colhid) ? 1 : 0; @@ -1867,7 +1867,7 @@ diff -rc alpine-2.25/pith/flag.c alpine-2.25.fancy/pith/flag.c } if(topthrd){ ---- 592,607 ---- +--- 588,603 ---- was_invisible = (pelt->hidden || pelt->colhid) ? 1 : 0; @@ -1884,9 +1884,9 @@ diff -rc alpine-2.25/pith/flag.c alpine-2.25.fancy/pith/flag.c } if(topthrd){ -diff -rc alpine-2.25/pith/indxtype.h alpine-2.25.fancy/pith/indxtype.h -*** alpine-2.25/pith/indxtype.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fancy/pith/indxtype.h 2021-09-18 09:03:09.527012342 -0600 +diff -rc alpine-2.26/pith/indxtype.h alpine-2.26.fancy/pith/indxtype.h +*** alpine-2.26/pith/indxtype.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fancy/pith/indxtype.h 2022-06-02 18:14:51.331150088 -0600 *************** *** 78,84 **** iKey, iKeyInit, @@ -1904,12 +1904,12 @@ diff -rc alpine-2.25/pith/indxtype.h alpine-2.25.fancy/pith/indxtype.h iNewsAndTo, iToAndNews, iNewsAndRecips, iRecipsAndNews, iFromTo, iFromToNotNews, iFrom, iTo, iSender, iCc, iNews, iRecips, iCurNews, iArrow, -diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c -*** alpine-2.25/pith/mailindx.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fancy/pith/mailindx.c 2021-09-18 09:03:09.527012342 -0600 +diff -rc alpine-2.26/pith/mailindx.c alpine-2.26.fancy/pith/mailindx.c +*** alpine-2.26/pith/mailindx.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fancy/pith/mailindx.c 2022-06-02 18:14:51.347150049 -0600 *************** -*** 229,234 **** ---- 229,235 ---- +*** 225,230 **** +--- 225,231 ---- case iSTime: case iKSize: case iSize: @@ -1918,8 +1918,8 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c (*answer)[column].req_width = 7; break; *************** -*** 456,461 **** ---- 457,463 ---- +*** 452,457 **** +--- 453,459 ---- {"FROMORTONOTNEWS", iFromToNotNews, FOR_INDEX}, {"SIZE", iSize, FOR_INDEX}, {"SIZECOMMA", iSizeComma, FOR_INDEX}, @@ -1928,7 +1928,7 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c {"KSIZE", iKSize, FOR_INDEX}, {"SUBJECT", iSubject, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE}, *************** -*** 954,960 **** +*** 950,956 **** iSDateTimeS1, iSDateTimeS2, iSDateTimeS3, iSDateTimeS4, iSDateTimeIso24, iSDateTimeIsoS24, iSDateTimeS124, iSDateTimeS224, iSDateTimeS324, iSDateTimeS424, @@ -1936,7 +1936,7 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c iPrio, iPrioBang, iPrioAlpha, iInit, iAtt, iTime24, iTime12, iTimezone, iMonAbb, iYear, iYear2Digit, iDay2Digit, iMon2Digit, iDayOfWeekAbb, iScore, iMonLong, iDayOfWeek ---- 956,962 ---- +--- 952,958 ---- iSDateTimeS1, iSDateTimeS2, iSDateTimeS3, iSDateTimeS4, iSDateTimeIso24, iSDateTimeIsoS24, iSDateTimeS124, iSDateTimeS224, iSDateTimeS324, iSDateTimeS424, @@ -1945,8 +1945,8 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c iAtt, iTime24, iTime12, iTimezone, iMonAbb, iYear, iYear2Digit, iDay2Digit, iMon2Digit, iDayOfWeekAbb, iScore, iMonLong, iDayOfWeek *************** -*** 1147,1152 **** ---- 1149,1155 ---- +*** 1143,1148 **** +--- 1145,1151 ---- case iTime12: case iSize: case iKSize: @@ -1955,7 +1955,7 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c cdesc->adjustment = Right; break; *************** -*** 1241,1247 **** +*** 1237,1243 **** cdesc->ctype != iNothing; cdesc++) if(cdesc->ctype == iSize || cdesc->ctype == iKSize || @@ -1963,7 +1963,7 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c cdesc->ctype == iSizeComma || cdesc->ctype == iDescripSize){ if(cdesc->actual_length == 0){ if((fix=cdesc->width) > 0){ /* had this reserved */ ---- 1244,1250 ---- +--- 1240,1246 ---- cdesc->ctype != iNothing; cdesc++) if(cdesc->ctype == iSize || cdesc->ctype == iKSize || @@ -1972,7 +1972,7 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c if(cdesc->actual_length == 0){ if((fix=cdesc->width) > 0){ /* had this reserved */ *************** -*** 1627,1636 **** +*** 1623,1632 **** /* find next thread which is visible */ do{ @@ -1983,7 +1983,7 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c else thrd = NULL; } while(thrd ---- 1630,1641 ---- +--- 1626,1637 ---- /* find next thread which is visible */ do{ @@ -1997,7 +1997,7 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c thrd = NULL; } while(thrd *************** -*** 2042,2054 **** +*** 2038,2050 **** */ ice = copy_ice(ice); @@ -2011,7 +2011,7 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c /* calculate contents of the required fields */ for(cdesc = ps_global->index_disp_format; cdesc->ctype != iNothing; cdesc++) ---- 2047,2056 ---- +--- 2043,2052 ---- */ ice = copy_ice(ice); @@ -2023,8 +2023,8 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c /* calculate contents of the required fields */ for(cdesc = ps_global->index_disp_format; cdesc->ctype != iNothing; cdesc++) *************** -*** 2550,2556 **** ---- 2552,2581 ---- +*** 2546,2552 **** +--- 2548,2577 ---- break; @@ -2056,7 +2056,7 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c if((l = fetch_size(idata)) < 10*1000L) snprintf(str, sizeof(str), "(%lu)", l); *************** -*** 5582,5591 **** +*** 5578,5587 **** if(pith_opt_condense_thread_cue) width = (*pith_opt_condense_thread_cue)(thd, ice, &str, &strsize, width, @@ -2067,7 +2067,7 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c /* * width is < available strsize and ---- 5607,5614 ---- +--- 5603,5610 ---- if(pith_opt_condense_thread_cue) width = (*pith_opt_condense_thread_cue)(thd, ice, &str, &strsize, width, @@ -2077,7 +2077,7 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c /* * width is < available strsize and *************** -*** 6211,6221 **** +*** 6207,6217 **** border = str + width; if(pith_opt_condense_thread_cue) width = (*pith_opt_condense_thread_cue)(thd, ice, &str, &strsize, width, @@ -2089,7 +2089,7 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c fptr = str; if(thd) ---- 6234,6241 ---- +--- 6230,6237 ---- border = str + width; if(pith_opt_condense_thread_cue) width = (*pith_opt_condense_thread_cue)(thd, ice, &str, &strsize, width, @@ -2098,11 +2098,11 @@ diff -rc alpine-2.25/pith/mailindx.c alpine-2.25.fancy/pith/mailindx.c fptr = str; if(thd) -diff -rc alpine-2.25/pith/pattern.c alpine-2.25.fancy/pith/pattern.c -*** alpine-2.25/pith/pattern.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fancy/pith/pattern.c 2021-09-18 09:03:09.531012370 -0600 +diff -rc alpine-2.26/pith/pattern.c alpine-2.26.fancy/pith/pattern.c +*** alpine-2.26/pith/pattern.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fancy/pith/pattern.c 2022-06-02 18:14:51.359150020 -0600 *************** -*** 1756,1762 **** +*** 1753,1759 **** SortOrder def_sort; int def_sort_rev; @@ -2110,7 +2110,7 @@ diff -rc alpine-2.25/pith/pattern.c alpine-2.25.fancy/pith/pattern.c action->sort_is_set = 1; action->sortorder = def_sort; action->revsort = (def_sort_rev ? 1 : 0); ---- 1756,1762 ---- +--- 1753,1759 ---- SortOrder def_sort; int def_sort_rev; @@ -2118,12 +2118,12 @@ diff -rc alpine-2.25/pith/pattern.c alpine-2.25.fancy/pith/pattern.c action->sort_is_set = 1; action->sortorder = def_sort; action->revsort = (def_sort_rev ? 1 : 0); -diff -rc alpine-2.25/pith/pine.hlp alpine-2.25.fancy/pith/pine.hlp -*** alpine-2.25/pith/pine.hlp 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fancy/pith/pine.hlp 2021-09-18 09:03:09.655013226 -0600 +diff -rc alpine-2.26/pith/pine.hlp alpine-2.26.fancy/pith/pine.hlp +*** alpine-2.26/pith/pine.hlp 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fancy/pith/pine.hlp 2022-06-02 18:14:51.399149922 -0600 *************** -*** 5165,5170 **** ---- 5165,5171 ---- +*** 5321,5326 **** +--- 5321,5327 ----

  • OPTION:
  • OPTION:
  • OPTION: @@ -2132,8 +2132,8 @@ diff -rc alpine-2.25/pith/pine.hlp alpine-2.25.fancy/pith/pine.hlp
  • OPTION:
  • OPTION: *************** -*** 7106,7111 **** ---- 7107,7269 ---- +*** 7262,7267 **** +--- 7263,7425 ---- <End of help on this topic> @@ -2298,8 +2298,8 @@ diff -rc alpine-2.25/pith/pine.hlp alpine-2.25.fancy/pith/pine.hlp *************** -*** 20685,20690 **** ---- 20843,20856 ---- +*** 20839,20844 **** +--- 20997,21010 ----

    @@ -2315,8 +2315,8 @@ diff -rc alpine-2.25/pith/pine.hlp alpine-2.25.fancy/pith/pine.hlp

    This token represents the total size, in bytes, of the message. *************** -*** 24401,24406 **** ---- 24567,24611 ---- +*** 24555,24560 **** +--- 24721,24765 ---- <End of help on this topic> @@ -2363,8 +2363,8 @@ diff -rc alpine-2.25/pith/pine.hlp alpine-2.25.fancy/pith/pine.hlp *************** -*** 32466,32471 **** ---- 32671,32693 ---- +*** 32604,32609 **** +--- 32809,32831 ---- <End of help on this topic> @@ -2388,11 +2388,11 @@ diff -rc alpine-2.25/pith/pine.hlp alpine-2.25.fancy/pith/pine.hlp ====== h_config_news_cross_deletes ===== -diff -rc alpine-2.25/pith/sort.c alpine-2.25.fancy/pith/sort.c -*** alpine-2.25/pith/sort.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fancy/pith/sort.c 2021-09-18 09:03:09.659013253 -0600 +diff -rc alpine-2.26/pith/sort.c alpine-2.26.fancy/pith/sort.c +*** alpine-2.26/pith/sort.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fancy/pith/sort.c 2022-06-02 18:14:51.399149922 -0600 *************** -*** 91,97 **** +*** 87,93 **** ----*/ void sort_folder(MAILSTREAM *stream, MSGNO_S *msgmap, SortOrder new_sort, @@ -2400,7 +2400,7 @@ diff -rc alpine-2.25/pith/sort.c alpine-2.25.fancy/pith/sort.c { long raw_current, i, j; unsigned long *sort = NULL; ---- 91,97 ---- +--- 87,93 ---- ----*/ void sort_folder(MAILSTREAM *stream, MSGNO_S *msgmap, SortOrder new_sort, @@ -2409,8 +2409,8 @@ diff -rc alpine-2.25/pith/sort.c alpine-2.25.fancy/pith/sort.c long raw_current, i, j; unsigned long *sort = NULL; *************** -*** 101,106 **** ---- 101,115 ---- +*** 97,102 **** +--- 97,111 ---- int current_rev; MESSAGECACHE *mc; @@ -2427,7 +2427,7 @@ diff -rc alpine-2.25/pith/sort.c alpine-2.25.fancy/pith/sort.c sort_name(new_sort), new_rev ? "/reverse" : "")); *************** -*** 530,549 **** +*** 526,545 **** * argument also means arrival/reverse. */ int @@ -2448,7 +2448,7 @@ diff -rc alpine-2.25/pith/sort.c alpine-2.25.fancy/pith/sort.c *def_sort_rev = 1; return(0); } ---- 539,558 ---- +--- 535,554 ---- * argument also means arrival/reverse. */ int @@ -2470,7 +2470,7 @@ diff -rc alpine-2.25/pith/sort.c alpine-2.25.fancy/pith/sort.c return(0); } *************** -*** 572,578 **** +*** 568,574 **** if(ps_global->sort_types[x] == EndofList) return(-1); @@ -2478,7 +2478,7 @@ diff -rc alpine-2.25/pith/sort.c alpine-2.25.fancy/pith/sort.c *def_sort_rev = reverse; return(0); } ---- 581,587 ---- +--- 577,583 ---- if(ps_global->sort_types[x] == EndofList) return(-1); @@ -2487,7 +2487,7 @@ diff -rc alpine-2.25/pith/sort.c alpine-2.25.fancy/pith/sort.c return(0); } *************** -*** 689,695 **** +*** 685,691 **** /* set default order */ the_sort_order = ps_global->def_sort; @@ -2495,7 +2495,7 @@ diff -rc alpine-2.25/pith/sort.c alpine-2.25.fancy/pith/sort.c if(ps_global->mail_stream && nonempty_patterns(rflags, &pstate)){ for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){ ---- 698,706 ---- +--- 694,702 ---- /* set default order */ the_sort_order = ps_global->def_sort; @@ -2506,7 +2506,7 @@ diff -rc alpine-2.25/pith/sort.c alpine-2.25.fancy/pith/sort.c if(ps_global->mail_stream && nonempty_patterns(rflags, &pstate)){ for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){ *************** -*** 702,710 **** +*** 698,706 **** && pat->action->sort_is_set){ the_sort_order = pat->action->sortorder; sort_is_rev = pat->action->revsort; @@ -2516,7 +2516,7 @@ diff -rc alpine-2.25/pith/sort.c alpine-2.25.fancy/pith/sort.c sort_folder(ps_global->mail_stream, ps_global->msgmap, ! the_sort_order, sort_is_rev, flags); } ---- 713,727 ---- +--- 709,723 ---- && pat->action->sort_is_set){ the_sort_order = pat->action->sortorder; sort_is_rev = pat->action->revsort; @@ -2532,9 +2532,9 @@ diff -rc alpine-2.25/pith/sort.c alpine-2.25.fancy/pith/sort.c sort_folder(ps_global->mail_stream, ps_global->msgmap, ! the_sort_order, sort_is_rev, flags, 1); } -diff -rc alpine-2.25/pith/sort.h alpine-2.25.fancy/pith/sort.h -*** alpine-2.25/pith/sort.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fancy/pith/sort.h 2021-09-18 09:03:09.675013364 -0600 +diff -rc alpine-2.26/pith/sort.h alpine-2.26.fancy/pith/sort.h +*** alpine-2.26/pith/sort.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fancy/pith/sort.h 2022-06-02 18:14:51.407149902 -0600 *************** *** 23,29 **** @@ -2571,12 +2571,12 @@ diff -rc alpine-2.25/pith/sort.h alpine-2.25.fancy/pith/sort.h void reset_sort_order(unsigned); -diff -rc alpine-2.25/pith/state.c alpine-2.25.fancy/pith/state.c -*** alpine-2.25/pith/state.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fancy/pith/state.c 2021-09-18 09:03:09.675013364 -0600 +diff -rc alpine-2.26/pith/state.c alpine-2.26.fancy/pith/state.c +*** alpine-2.26/pith/state.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fancy/pith/state.c 2022-06-02 18:14:51.411149892 -0600 *************** -*** 75,80 **** ---- 75,81 ---- +*** 71,76 **** +--- 71,77 ---- p = (struct pine *)fs_get(sizeof (struct pine)); memset((void *) p, 0, sizeof(struct pine)); @@ -2584,12 +2584,12 @@ diff -rc alpine-2.25/pith/state.c alpine-2.25.fancy/pith/state.c p->def_sort = SortArrival; p->sort_types[0] = SortSubject; p->sort_types[1] = SortArrival; -diff -rc alpine-2.25/pith/state.h alpine-2.25.fancy/pith/state.h -*** alpine-2.25/pith/state.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fancy/pith/state.h 2021-09-18 09:03:09.675013364 -0600 +diff -rc alpine-2.26/pith/state.h alpine-2.26.fancy/pith/state.h +*** alpine-2.26/pith/state.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fancy/pith/state.h 2022-06-02 18:14:51.415149883 -0600 *************** -*** 149,154 **** ---- 149,156 ---- +*** 151,156 **** +--- 151,158 ---- unsigned unseen_in_view:1; unsigned start_in_context:1; /* start fldr_scrn in current cntxt */ unsigned def_sort_rev:1; /* true if reverse sort is default */ @@ -2599,8 +2599,8 @@ diff -rc alpine-2.25/pith/state.h alpine-2.25.fancy/pith/state.h unsigned tcptimeout:1; /* a tcp timeout is in progress */ *************** -*** 313,318 **** ---- 315,323 ---- +*** 315,320 **** +--- 317,325 ---- EditWhich ew_for_srch_take; SortOrder def_sort, /* Default sort type */ @@ -2610,11 +2610,11 @@ diff -rc alpine-2.25/pith/state.h alpine-2.25.fancy/pith/state.h sort_types[22]; int last_expire_year, last_expire_month; -diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c -*** alpine-2.25/pith/thread.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fancy/pith/thread.c 2021-09-18 09:03:09.715013639 -0600 +diff -rc alpine-2.26/pith/thread.c alpine-2.26.fancy/pith/thread.c +*** alpine-2.26/pith/thread.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fancy/pith/thread.c 2022-06-02 18:14:51.415149883 -0600 *************** -*** 30,41 **** +*** 26,37 **** #include "../pith/mailcmd.h" #include "../pith/ablookup.h" @@ -2627,7 +2627,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c void make_thrdflags_consistent(MAILSTREAM *, MSGNO_S *, PINETHRD_S *, int); THREADNODE *collapse_threadnode_tree(THREADNODE *); THREADNODE *collapse_threadnode_tree_sorted(THREADNODE *); ---- 30,47 ---- +--- 26,43 ---- #include "../pith/mailcmd.h" #include "../pith/ablookup.h" @@ -2647,8 +2647,8 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c THREADNODE *collapse_threadnode_tree(THREADNODE *); THREADNODE *collapse_threadnode_tree_sorted(THREADNODE *); *************** -*** 43,48 **** ---- 49,55 ---- +*** 39,44 **** +--- 45,51 ---- THREADNODE *insert_tree_in_place(THREADNODE *, THREADNODE *); unsigned long branch_greatest_num(THREADNODE *, int); long calculate_visible_threads(MAILSTREAM *); @@ -2657,7 +2657,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c PINETHRD_S * *************** -*** 95,114 **** +*** 91,110 **** set_flags_for_thread(MAILSTREAM *stream, MSGNO_S *msgmap, int f, PINETHRD_S *thrd, int v) { PINETHRD_S *nthrd, *bthrd; @@ -2678,7 +2678,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(bthrd) set_flags_for_thread(stream, msgmap, f, bthrd, v); } ---- 102,123 ---- +--- 98,119 ---- set_flags_for_thread(MAILSTREAM *stream, MSGNO_S *msgmap, int f, PINETHRD_S *thrd, int v) { PINETHRD_S *nthrd, *bthrd; @@ -2689,20 +2689,20 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c set_lflag(stream, msgmap, mn_raw2m(msgmap, thrd->rawno), f, v); -! if(next = get_next(stream,thrd)){ +! if((next = get_next(stream,thrd))){ ! nthrd = fetch_thread(stream, next); if(nthrd) set_flags_for_thread(stream, msgmap, f, nthrd, v); } ! -! if(branch = get_branch(stream, thrd)){ +! if((branch = get_branch(stream, thrd))){ ! bthrd = fetch_thread(stream, branch); if(bthrd) set_flags_for_thread(stream, msgmap, f, bthrd, v); } *************** -*** 122,128 **** +*** 118,124 **** MESSAGECACHE *mc; PINELT_S *peltp; @@ -2710,7 +2710,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c return; ps_global->view_skipped_index = 0; ---- 131,137 ---- +--- 127,133 ---- MESSAGECACHE *mc; PINELT_S *peltp; @@ -2719,7 +2719,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c ps_global->view_skipped_index = 0; *************** -*** 155,161 **** +*** 151,157 **** PINETHRD_S *thrd = NULL; unsigned long msgno, rawno; int un_view_thread = 0; @@ -2727,7 +2727,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c char *dup_chk = NULL; ---- 164,170 ---- +--- 160,166 ---- PINETHRD_S *thrd = NULL; unsigned long msgno, rawno; int un_view_thread = 0; @@ -2736,7 +2736,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c *************** -*** 168,177 **** +*** 164,173 **** * way. If the dummy node is at the top-level, then its children are * promoted to the top-level as separate threads. */ @@ -2747,7 +2747,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c /* dup_chk is like sort with an origin of 1 */ dup_chk = (char *) fs_get((mn_get_nmsgs(g_sort.msgmap)+1) * sizeof(char)); ---- 177,187 ---- +--- 173,183 ---- * way. If the dummy node is at the top-level, then its children are * promoted to the top-level as separate threads. */ @@ -2760,7 +2760,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c /* dup_chk is like sort with an origin of 1 */ dup_chk = (char *) fs_get((mn_get_nmsgs(g_sort.msgmap)+1) * sizeof(char)); *************** -*** 182,188 **** +*** 178,184 **** (void) sort_thread_flatten(collapsed_tree, stream, &g_sort.msgmap->sort[1], dup_chk, mn_get_nmsgs(g_sort.msgmap), @@ -2768,7 +2768,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c /* reset the inverse array */ msgno_reset_isort(g_sort.msgmap); ---- 192,198 ---- +--- 188,194 ---- (void) sort_thread_flatten(collapsed_tree, stream, &g_sort.msgmap->sort[1], dup_chk, mn_get_nmsgs(g_sort.msgmap), @@ -2777,7 +2777,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c /* reset the inverse array */ msgno_reset_isort(g_sort.msgmap); *************** -*** 340,351 **** +*** 336,347 **** else{ thrd = fetch_head_thread(stream); while(thrd){ @@ -2790,7 +2790,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(thrd->next){ PINETHRD_S *nthrd; ---- 350,363 ---- +--- 346,359 ---- else{ thrd = fetch_head_thread(stream); while(thrd){ @@ -2806,7 +2806,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(thrd->next){ PINETHRD_S *nthrd; *************** -*** 359,367 **** +*** 355,363 **** MN_COLL)); } @@ -2816,7 +2816,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c thrd = NULL; } } ---- 371,380 ---- +--- 367,376 ---- MN_COLL)); } @@ -2828,7 +2828,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c } } *************** -*** 412,418 **** +*** 408,414 **** int a_parent_is_collapsed) { PINETHRD_S *nthrd, *bthrd; @@ -2836,7 +2836,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(!thrd) return; ---- 425,431 ---- +--- 421,427 ---- int a_parent_is_collapsed) { PINETHRD_S *nthrd, *bthrd; @@ -2845,7 +2845,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(!thrd) return; *************** -*** 430,437 **** +*** 426,433 **** set_lflag(stream, msgmap, msgno, MN_CHID, 0); } @@ -2854,17 +2854,17 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(nthrd) make_thrdflags_consistent(stream, msgmap, nthrd, a_parent_is_collapsed ---- 443,450 ---- +--- 439,446 ---- set_lflag(stream, msgmap, msgno, MN_CHID, 0); } -! if(next = get_next(stream, thrd)){ +! if((next = get_next(stream, thrd))){ ! nthrd = fetch_thread(stream, next); if(nthrd) make_thrdflags_consistent(stream, msgmap, nthrd, a_parent_is_collapsed *************** -*** 440,447 **** +*** 436,443 **** MN_COLL)); } @@ -2873,17 +2873,17 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(bthrd) make_thrdflags_consistent(stream, msgmap, bthrd, a_parent_is_collapsed); ---- 453,460 ---- +--- 449,456 ---- MN_COLL)); } -! if(branch = get_branch(stream, thrd)){ +! if((branch = get_branch(stream, thrd))){ ! bthrd = fetch_thread(stream, branch); if(bthrd) make_thrdflags_consistent(stream, msgmap, bthrd, a_parent_is_collapsed); *************** -*** 488,496 **** +*** 484,492 **** long * sort_thread_flatten(THREADNODE *node, MAILSTREAM *stream, long *entry, char *dup_chk, long maxno, @@ -2893,7 +2893,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(node){ if(node->num > 0L && node->num <= maxno){ /* holes happen */ ---- 501,510 ---- +--- 497,506 ---- long * sort_thread_flatten(THREADNODE *node, MAILSTREAM *stream, long *entry, char *dup_chk, long maxno, @@ -2905,8 +2905,8 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(node){ if(node->num > 0L && node->num <= maxno){ /* holes happen */ *************** -*** 498,503 **** ---- 512,520 ---- +*** 494,499 **** +--- 508,516 ---- *entry = node->num; dup_chk[node->num] = 1; @@ -2917,7 +2917,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c * Build a richer threading structure that will help us paint * and operate on threads and subthreads. *************** -*** 506,525 **** +*** 502,521 **** if(newthrd){ entry++; @@ -2938,7 +2938,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c } return(entry); ---- 523,573 ---- +--- 519,569 ---- if(newthrd){ entry++; @@ -2991,7 +2991,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c return(entry); *************** -*** 788,794 **** +*** 784,790 **** */ void collapse_or_expand(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap, @@ -2999,7 +2999,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c { int collapsed, adjust_current = 0; PINETHRD_S *thrd = NULL, *nthrd; ---- 836,842 ---- +--- 832,838 ---- */ void collapse_or_expand(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap, @@ -3008,7 +3008,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c int collapsed, adjust_current = 0; PINETHRD_S *thrd = NULL, *nthrd; *************** -*** 841,847 **** +*** 837,843 **** if(!thrd) return; @@ -3016,7 +3016,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(collapsed){ msgno = mn_raw2m(msgmap, thrd->rawno); ---- 889,895 ---- +--- 885,891 ---- if(!thrd) return; @@ -3025,7 +3025,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(collapsed){ msgno = mn_raw2m(msgmap, thrd->rawno); *************** -*** 859,871 **** +*** 855,867 **** msgno = mn_raw2m(msgmap, thrd->rawno); if(msgno > 0L && msgno <= mn_get_total(msgmap)){ set_lflag(stream, msgmap, msgno, MN_COLL, 1); @@ -3039,7 +3039,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c q_status_message(SM_ORDER, 0, 1, _("No thread to collapse or expand on this line")); ---- 907,919 ---- +--- 903,915 ---- msgno = mn_raw2m(msgmap, thrd->rawno); if(msgno > 0L && msgno <= mn_get_total(msgmap)){ set_lflag(stream, msgmap, msgno, MN_COLL, 1); @@ -3054,7 +3054,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c _("No thread to collapse or expand on this line")); *************** -*** 952,969 **** +*** 948,965 **** unsigned long count = 0; PINETHRD_S *nthrd, *bthrd; MESSAGECACHE *mc; @@ -3073,7 +3073,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(bthrd) count += count_flags_in_thread(stream, bthrd, flags); } ---- 1000,1018 ---- +--- 996,1014 ---- unsigned long count = 0; PINETHRD_S *nthrd, *bthrd; MESSAGECACHE *mc; @@ -3082,19 +3082,19 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) return count; -! if(next = get_next(stream, thrd)){ +! if((next = get_next(stream, thrd))){ ! nthrd = fetch_thread(stream, next); if(nthrd) count += count_flags_in_thread(stream, nthrd, flags); } -! if(branch = get_branch(stream, thrd)){ +! if((branch = get_branch(stream, thrd))){ ! bthrd = fetch_thread(stream, branch); if(bthrd) count += count_flags_in_thread(stream, bthrd, flags); } *************** -*** 1051,1070 **** +*** 1047,1066 **** mark_msgs_in_thread(MAILSTREAM *stream, PINETHRD_S *thrd, MSGNO_S *msgmap) { int count = 0; @@ -3115,7 +3115,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(bthrd) count += mark_msgs_in_thread(stream, bthrd, msgmap); } ---- 1100,1120 ---- +--- 1096,1116 ---- mark_msgs_in_thread(MAILSTREAM *stream, PINETHRD_S *thrd, MSGNO_S *msgmap) { int count = 0; @@ -3126,19 +3126,19 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) return count; -! if(next = get_next(stream, thrd)){ +! if((next = get_next(stream, thrd))){ ! nthrd = fetch_thread(stream, next); if(nthrd) count += mark_msgs_in_thread(stream, nthrd, msgmap); } -! if(branch = get_branch(stream, thrd)){ +! if((branch = get_branch(stream, thrd))){ ! bthrd = fetch_thread(stream, branch); if(bthrd) count += mark_msgs_in_thread(stream, bthrd, msgmap); } *************** -*** 1098,1104 **** +*** 1094,1100 **** /* flags to set or clear */ /* set or clear? */ { @@ -3146,7 +3146,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c PINETHRD_S *nthrd, *bthrd; if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) ---- 1148,1154 ---- +--- 1144,1150 ---- /* flags to set or clear */ /* set or clear? */ { @@ -3155,7 +3155,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) *************** -*** 1122,1135 **** +*** 1118,1131 **** if(msgno > 0L && flags == MN_CHID2 && v == 1) clear_index_cache_ent(stream, msgno, 0); @@ -3170,23 +3170,23 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(bthrd) set_thread_lflags(stream, bthrd, msgmap, flags, v); } ---- 1172,1185 ---- +--- 1168,1181 ---- if(msgno > 0L && flags == MN_CHID2 && v == 1) clear_index_cache_ent(stream, msgno, 0); -! if(next = get_next(stream, thrd)){ +! if((next = get_next(stream, thrd))){ ! nthrd = fetch_thread(stream, next); if(nthrd) set_thread_lflags(stream, nthrd, msgmap, flags, v); } -! if(branch = get_branch(stream,thrd)){ +! if((branch = get_branch(stream,thrd))){ ! bthrd = fetch_thread(stream, branch); if(bthrd) set_thread_lflags(stream, bthrd, msgmap, flags, v); } *************** -*** 1218,1236 **** +*** 1214,1232 **** char to_us = ' '; char branch_to_us = ' '; PINETHRD_S *nthrd, *bthrd; @@ -3206,7 +3206,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c bthrd = fetch_thread(stream, thrd->branch); if(bthrd) branch_to_us = to_us_symbol_for_thread(stream, bthrd, consider_flagged); ---- 1268,1287 ---- +--- 1264,1283 ---- char to_us = ' '; char branch_to_us = ' '; PINETHRD_S *nthrd, *bthrd; @@ -3216,7 +3216,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) return to_us; -! if(next = get_next(stream,thrd)){ +! if((next = get_next(stream,thrd))){ ! nthrd = fetch_thread(stream, next); if(nthrd) to_us = to_us_symbol_for_thread(stream, nthrd, consider_flagged); @@ -3228,7 +3228,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(bthrd) branch_to_us = to_us_symbol_for_thread(stream, bthrd, consider_flagged); *************** -*** 1280,1286 **** +*** 1276,1282 **** break; } @@ -3236,7 +3236,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c to_us = '+'; if(to_us == ' ' && F_ON(F_MARK_FOR_CC,ps_global)) ---- 1331,1337 ---- +--- 1327,1333 ---- break; } @@ -3245,7 +3245,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(to_us == ' ' && F_ON(F_MARK_FOR_CC,ps_global)) *************** -*** 1328,1334 **** +*** 1324,1330 **** set_lflag(stream, msgmap, msgno, flags, v); @@ -3253,7 +3253,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c nthrd = fetch_thread(stream, thrd->next); if(nthrd) set_thread_subtree(stream, nthrd, msgmap, v, flags); ---- 1379,1386 ---- +--- 1375,1382 ---- set_lflag(stream, msgmap, msgno, flags, v); @@ -3263,7 +3263,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(nthrd) set_thread_subtree(stream, nthrd, msgmap, v, flags); *************** -*** 1368,1375 **** +*** 1364,1371 **** if(rawno) thrd = fetch_thread(stream, rawno); @@ -3272,7 +3272,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(!thrd) return 0; ---- 1420,1427 ---- +--- 1416,1423 ---- if(rawno) thrd = fetch_thread(stream, rawno); @@ -3282,7 +3282,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(!thrd) return 0; *************** -*** 1433,1439 **** +*** 1429,1435 **** thrd = fetch_thread(stream, rawno); if(thrd && thrd->top) @@ -3290,7 +3290,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(!topthrd) return 0; ---- 1485,1491 ---- +--- 1481,1487 ---- thrd = fetch_thread(stream, rawno); if(thrd && thrd->top) @@ -3299,8 +3299,8 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(!topthrd) return 0; *************** -*** 1539,1544 **** ---- 1591,1597 ---- +*** 1535,1540 **** +--- 1587,1593 ---- set_search_bit_for_thread(MAILSTREAM *stream, PINETHRD_S *thrd, SEARCHSET **msgset) { PINETHRD_S *nthrd, *bthrd; @@ -3309,7 +3309,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c if(!(stream && thrd)) return; *************** -*** 1547,1561 **** +*** 1543,1557 **** && (!(msgset && *msgset) || in_searchset(*msgset, thrd->rawno))) mm_searched(stream, thrd->rawno); @@ -3325,17 +3325,17 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c set_search_bit_for_thread(stream, bthrd, msgset); } } ---- 1600,2221 ---- +--- 1596,2217 ---- && (!(msgset && *msgset) || in_searchset(*msgset, thrd->rawno))) mm_searched(stream, thrd->rawno); -! if(next= get_next(stream, thrd)){ +! if((next= get_next(stream, thrd))){ ! nthrd = fetch_thread(stream, next); if(nthrd) set_search_bit_for_thread(stream, nthrd, msgset); } -! if(branch = get_branch(stream, thrd)){ +! if((branch = get_branch(stream, thrd))){ ! bthrd = fetch_thread(stream, branch); if(bthrd) set_search_bit_for_thread(stream, bthrd, msgset); @@ -3431,7 +3431,7 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c + if(!thrd) + return -1; + -+ while(collapsed = this_thread_is_kolapsed(state, stream, msgmap, rawno)) ++ while((collapsed = this_thread_is_kolapsed(state, stream, msgmap, rawno))) + if (F_OFF(F_ENHANCED_THREAD, state) + || (move_next_this_thread(state, stream, msgmap, 0) <= 0) + || !(rawno = mn_m2raw(msgmap, mn_get_cur(msgmap))) @@ -3948,9 +3948,9 @@ diff -rc alpine-2.25/pith/thread.c alpine-2.25.fancy/pith/thread.c + || sort == SortSize; + } + -diff -rc alpine-2.25/pith/thread.h alpine-2.25.fancy/pith/thread.h -*** alpine-2.25/pith/thread.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fancy/pith/thread.h 2021-09-18 09:03:09.727013722 -0600 +diff -rc alpine-2.26/pith/thread.h alpine-2.26.fancy/pith/thread.h +*** alpine-2.26/pith/thread.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fancy/pith/thread.h 2022-06-02 18:14:51.415149883 -0600 *************** *** 38,43 **** --- 38,44 ---- @@ -4011,11 +4011,11 @@ diff -rc alpine-2.25/pith/thread.h alpine-2.25.fancy/pith/thread.h ! int allowed_thread_key(SortOrder sort); #endif /* PITH_THREAD_INCLUDED */ -diff -rc alpine-2.25/web/src/alpined.d/alpined.c alpine-2.25.fancy/web/src/alpined.d/alpined.c -*** alpine-2.25/web/src/alpined.d/alpined.c 2021-09-18 09:02:36.402783672 -0600 ---- alpine-2.25.fancy/web/src/alpined.d/alpined.c 2021-09-18 09:03:09.739013805 -0600 +diff -rc alpine-2.26/web/src/alpined.d/alpined.c alpine-2.26.fancy/web/src/alpined.d/alpined.c +*** alpine-2.26/web/src/alpined.d/alpined.c 2022-06-02 18:14:00.503274719 -0600 +--- alpine-2.26.fancy/web/src/alpined.d/alpined.c 2022-06-02 18:14:51.423149863 -0600 *************** -*** 2755,2761 **** +*** 2751,2757 **** init_save_defaults(); break; case V_SORT_KEY: @@ -4023,7 +4023,7 @@ diff -rc alpine-2.25/web/src/alpined.d/alpined.c alpine-2.25.fancy/web/src/alpin break; case V_VIEW_HDR_COLORS : set_custom_spec_colors(wps_global); ---- 2755,2761 ---- +--- 2751,2757 ---- init_save_defaults(); break; case V_SORT_KEY: @@ -4032,7 +4032,7 @@ diff -rc alpine-2.25/web/src/alpined.d/alpined.c alpine-2.25.fancy/web/src/alpin case V_VIEW_HDR_COLORS : set_custom_spec_colors(wps_global); *************** -*** 6331,6337 **** +*** 6327,6333 **** && mn_get_revsort(sp_msgmap(wps_global->mail_stream)) == reversed)) sort_folder(wps_global->mail_stream, sp_msgmap(wps_global->mail_stream), wps_global->sort_types[i], @@ -4040,7 +4040,7 @@ diff -rc alpine-2.25/web/src/alpined.d/alpined.c alpine-2.25.fancy/web/src/alpin break; } ---- 6331,6337 ---- +--- 6327,6333 ---- && mn_get_revsort(sp_msgmap(wps_global->mail_stream)) == reversed)) sort_folder(wps_global->mail_stream, sp_msgmap(wps_global->mail_stream), wps_global->sort_types[i], diff --git a/chappa-fillpara.patch b/chappa-fillpara.patch index ef1efe1..856fabd 100644 --- a/chappa-fillpara.patch +++ b/chappa-fillpara.patch @@ -1,9 +1,9 @@ -diff -rc alpine-2.25/alpine/mailview.c alpine-2.25.fillpara/alpine/mailview.c -*** alpine-2.25/alpine/mailview.c 2021-09-18 09:02:36.350783312 -0600 ---- alpine-2.25.fillpara/alpine/mailview.c 2021-09-18 09:03:13.523039928 -0600 +diff -rc alpine-2.26/alpine/mailview.c alpine-2.26.fillpara/alpine/mailview.c +*** alpine-2.26/alpine/mailview.c 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.fillpara/alpine/mailview.c 2022-06-02 18:14:56.983136230 -0600 *************** -*** 205,211 **** ---- 205,219 ---- +*** 203,209 **** +--- 203,217 ---- int pcpine_view_cursor(int, long); #endif @@ -20,8 +20,8 @@ diff -rc alpine-2.25/alpine/mailview.c alpine-2.25.fillpara/alpine/mailview.c /*---------------------------------------------------------------------- Format a buffer with the text of the current message for browser *************** -*** 296,301 **** ---- 304,320 ---- +*** 294,299 **** +--- 302,318 ---- else ps->unseen_in_view = !mc->seen; @@ -40,8 +40,8 @@ diff -rc alpine-2.25/alpine/mailview.c alpine-2.25.fillpara/alpine/mailview.c store = so_get(src, NULL, EDIT_ACCESS); *************** -*** 480,485 **** ---- 499,506 ---- +*** 478,483 **** +--- 497,504 ---- } while(ps->next_screen == SCREEN_FUN_NULL); @@ -50,11 +50,11 @@ diff -rc alpine-2.25/alpine/mailview.c alpine-2.25.fillpara/alpine/mailview.c if(we_cancel) cancel_busy_cue(-1); -diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c -*** alpine-2.25/pico/basic.c 2021-09-18 09:02:36.386783561 -0600 ---- alpine-2.25.fillpara/pico/basic.c 2021-09-18 09:03:13.523039928 -0600 +diff -rc alpine-2.26/pico/basic.c alpine-2.26.fillpara/pico/basic.c +*** alpine-2.26/pico/basic.c 2022-06-02 18:14:00.487274758 -0600 +--- alpine-2.26.fillpara/pico/basic.c 2022-06-02 18:14:56.983136230 -0600 *************** -*** 26,34 **** +*** 22,30 **** * framing, are hard. */ #include "headers.h" @@ -64,7 +64,7 @@ diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c /* * Move the cursor to the ---- 26,35 ---- +--- 22,31 ---- * framing, are hard. */ #include "headers.h" @@ -76,7 +76,7 @@ diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c /* * Move the cursor to the *************** -*** 285,291 **** +*** 281,287 **** gotobop(int f, int n) { int quoted, qlen; @@ -84,7 +84,7 @@ diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c if (n < 0) /* the other way...*/ return(gotoeop(f, -n)); ---- 286,292 ---- +--- 282,288 ---- gotobop(int f, int n) { int quoted, qlen; @@ -93,8 +93,8 @@ diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c if (n < 0) /* the other way...*/ return(gotoeop(f, -n)); *************** -*** 297,302 **** ---- 298,311 ---- +*** 293,298 **** +--- 294,307 ---- curwp->w_dotp = lback(curwp->w_dotp); curwp->w_doto = 0; } @@ -110,7 +110,7 @@ diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c /* scan line by line until we come to a line ending with * a or or *************** -*** 304,321 **** +*** 300,317 **** * PLUS: if there's a quote string, a quoted-to-non-quoted * line transition. */ @@ -129,7 +129,7 @@ diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c if(n){ /* keep looking */ if(lback(curwp->w_dotp) == curbp->b_linep) ---- 313,371 ---- +--- 309,367 ---- * PLUS: if there's a quote string, a quoted-to-non-quoted * line transition. */ @@ -152,7 +152,7 @@ diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c + /* + * Ok, we made it here and we assume that we are at the begining + * of the paragraph. Let's double check this now. In order to do -+ * so we shell check if the first line was indented in a special ++ * so we shall check if the first line was indented in a special + * way. + */ + if(lback(curwp->w_dotp) == curbp->b_linep) @@ -175,14 +175,14 @@ diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c + ind_str, NLINE, 1) + && (strlenis(qstr2) + + strlenis(ind_str) >= strlenis(qstr))) -+ || (lback(curwp->w_dotp) != curbp->b_linep ++ || ((lback(curwp->w_dotp) != curbp->b_linep + && llength(lback(curwp->w_dotp)) > qlen + && (quoted == quote_match(default_qstr(glo_quote_str, 1), + lback(curwp->w_dotp), pqstr, NLINE, 0)) + && !strcmp(qstr, pqstr) + && !ISspace(lgetc(curwp->w_dotp, qlen).c) -+ && (strlenis(qstr2) > strlenis(qstr))) -+ && !qstr2[i] && !qstr[j]) ++ && strlenis(qstr2) > strlenis(qstr)) ++ && !qstr2[i] && !qstr[j])) + curwp->w_dotp = lback(curwp->w_dotp); + } + @@ -190,7 +190,7 @@ diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c /* keep looking */ if(lback(curwp->w_dotp) == curbp->b_linep) *************** -*** 328,334 **** +*** 324,330 **** else{ /* leave cursor on first word in para */ curwp->w_doto = 0; @@ -198,7 +198,7 @@ diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c if(++curwp->w_doto >= llength(curwp->w_dotp)){ curwp->w_doto = 0; curwp->w_dotp = lforw(curwp->w_dotp); ---- 378,384 ---- +--- 374,380 ---- else{ /* leave cursor on first word in para */ curwp->w_doto = 0; @@ -207,7 +207,7 @@ diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c curwp->w_doto = 0; curwp->w_dotp = lforw(curwp->w_dotp); *************** -*** 351,358 **** +*** 347,354 **** int gotoeop(int f, int n) { @@ -216,7 +216,7 @@ diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c if (n < 0) /* the other way...*/ return(gotobop(f, -n)); ---- 401,409 ---- +--- 397,405 ---- int gotoeop(int f, int n) { @@ -227,7 +227,7 @@ diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c if (n < 0) /* the other way...*/ return(gotobop(f, -n)); *************** -*** 365,388 **** +*** 361,384 **** break; } @@ -252,7 +252,7 @@ diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c curwp->w_dotp = lforw(curwp->w_dotp); curwp->w_doto = llength(curwp->w_dotp); ---- 416,485 ---- +--- 412,481 ---- break; } @@ -323,9 +323,9 @@ diff -rc alpine-2.25/pico/basic.c alpine-2.25.fillpara/pico/basic.c curwp->w_dotp = lforw(curwp->w_dotp); curwp->w_doto = llength(curwp->w_dotp); -diff -rc alpine-2.25/pico/efunc.h alpine-2.25.fillpara/pico/efunc.h -*** alpine-2.25/pico/efunc.h 2021-09-18 09:02:36.386783561 -0600 ---- alpine-2.25.fillpara/pico/efunc.h 2021-09-18 09:03:13.527039955 -0600 +diff -rc alpine-2.26/pico/efunc.h alpine-2.26.fillpara/pico/efunc.h +*** alpine-2.26/pico/efunc.h 2022-06-02 18:14:00.487274758 -0600 +--- alpine-2.26.fillpara/pico/efunc.h 2022-06-02 18:14:56.983136230 -0600 *************** *** 253,262 **** extern int fillpara(int, int); @@ -355,11 +355,11 @@ diff -rc alpine-2.25/pico/efunc.h alpine-2.25.fillpara/pico/efunc.h #endif /* EFUNC_H */ + -diff -rc alpine-2.25/pico/line.c alpine-2.25.fillpara/pico/line.c -*** alpine-2.25/pico/line.c 2021-09-18 09:02:36.386783561 -0600 ---- alpine-2.25.fillpara/pico/line.c 2021-09-18 09:03:13.575040287 -0600 +diff -rc alpine-2.26/pico/line.c alpine-2.26.fillpara/pico/line.c +*** alpine-2.26/pico/line.c 2022-06-02 18:14:00.487274758 -0600 +--- alpine-2.26.fillpara/pico/line.c 2022-06-02 18:14:57.007136171 -0600 *************** -*** 612,627 **** +*** 608,623 **** lisblank(LINE *line) { int n = 0; @@ -376,7 +376,7 @@ diff -rc alpine-2.25/pico/line.c alpine-2.25.fillpara/pico/line.c return(FALSE); return(TRUE); ---- 612,623 ---- +--- 608,619 ---- lisblank(LINE *line) { int n = 0; @@ -389,9 +389,9 @@ diff -rc alpine-2.25/pico/line.c alpine-2.25.fillpara/pico/line.c return(FALSE); return(TRUE); -diff -rc alpine-2.25/pico/osdep/color.h alpine-2.25.fillpara/pico/osdep/color.h -*** alpine-2.25/pico/osdep/color.h 2021-09-18 09:02:36.386783561 -0600 ---- alpine-2.25.fillpara/pico/osdep/color.h 2021-09-18 09:03:13.579040315 -0600 +diff -rc alpine-2.26/pico/osdep/color.h alpine-2.26.fillpara/pico/osdep/color.h +*** alpine-2.26/pico/osdep/color.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fillpara/pico/osdep/color.h 2022-06-02 18:14:57.007136171 -0600 *************** *** 33,38 **** --- 33,39 ---- @@ -402,12 +402,12 @@ diff -rc alpine-2.25/pico/osdep/color.h alpine-2.25.fillpara/pico/osdep/color.h #endif /* PICO_OSDEP_COLOR_INCLUDED */ -diff -rc alpine-2.25/pico/search.c alpine-2.25.fillpara/pico/search.c -*** alpine-2.25/pico/search.c 2021-09-18 09:02:36.386783561 -0600 ---- alpine-2.25.fillpara/pico/search.c 2021-09-18 09:03:13.579040315 -0600 +diff -rc alpine-2.26/pico/search.c alpine-2.26.fillpara/pico/search.c +*** alpine-2.26/pico/search.c 2022-06-02 18:14:00.487274758 -0600 +--- alpine-2.26.fillpara/pico/search.c 2022-06-02 18:14:57.015136151 -0600 *************** -*** 36,41 **** ---- 36,42 ---- +*** 32,37 **** +--- 32,38 ---- int readpattern(char *, int, int); int replace_pat(UCS *, int *, int); int replace_all(UCS *, UCS *, int); @@ -416,7 +416,7 @@ diff -rc alpine-2.25/pico/search.c alpine-2.25.fillpara/pico/search.c void reverse_buffer(void); void reverse_ucs4(UCS *); *************** -*** 71,77 **** +*** 67,73 **** {"^W", N_("Start of Para"), (CTRL|'W')}, {"^O", N_("End of Para"), (CTRL|'O')}, {"^U", N_("FullJustify"), (CTRL|'U')}, @@ -424,7 +424,7 @@ diff -rc alpine-2.25/pico/search.c alpine-2.25.fillpara/pico/search.c {NULL, NULL, 0} }; ---- 72,78 ---- +--- 68,74 ---- {"^W", N_("Start of Para"), (CTRL|'W')}, {"^O", N_("End of Para"), (CTRL|'O')}, {"^U", N_("FullJustify"), (CTRL|'U')}, @@ -433,7 +433,7 @@ diff -rc alpine-2.25/pico/search.c alpine-2.25.fillpara/pico/search.c }; *************** -*** 220,228 **** +*** 216,224 **** case (CTRL|'P'): if(flags & SR_ORIGMEN){ @@ -443,7 +443,7 @@ diff -rc alpine-2.25/pico/search.c alpine-2.25.fillpara/pico/search.c if(flags & SR_FORWARD){ flags &= ~SR_FORWARD; flags |= SR_BACKWRD; ---- 221,231 ---- +--- 217,227 ---- case (CTRL|'P'): if(flags & SR_ORIGMEN){ @@ -456,8 +456,8 @@ diff -rc alpine-2.25/pico/search.c alpine-2.25.fillpara/pico/search.c flags &= ~SR_FORWARD; flags |= SR_BACKWRD; *************** -*** 1420,1422 **** ---- 1423,1447 ---- +*** 1416,1418 **** +--- 1419,1443 ---- if(bsearch) reverse_ucs4(orig); return utf8; } @@ -483,11 +483,11 @@ diff -rc alpine-2.25/pico/search.c alpine-2.25.fillpara/pico/search.c + return(TRUE); + } + -diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c -*** alpine-2.25/pico/word.c 2021-09-18 09:02:36.386783561 -0600 ---- alpine-2.25.fillpara/pico/word.c 2021-09-18 09:03:13.583040342 -0600 +diff -rc alpine-2.26/pico/word.c alpine-2.26.fillpara/pico/word.c +*** alpine-2.26/pico/word.c 2022-06-02 18:14:00.487274758 -0600 +--- alpine-2.26.fillpara/pico/word.c 2022-06-02 18:14:57.019136141 -0600 *************** -*** 25,34 **** +*** 21,30 **** */ #include "headers.h" @@ -498,7 +498,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c int setquotelevelinregion(int quotelevel, REGION *addedregion); int is_user_separator(UCS c); ---- 25,34 ---- +--- 21,30 ---- */ #include "headers.h" @@ -510,7 +510,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c int is_user_separator(UCS c); *************** -*** 431,555 **** +*** 427,551 **** return 0; } @@ -636,7 +636,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c /* Justify the entire buffer instead of just a paragraph */ int ---- 431,595 ---- +--- 427,591 ---- return 0; } @@ -803,8 +803,8 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c /* Justify the entire buffer instead of just a paragraph */ int *************** -*** 804,809 **** ---- 844,850 ---- +*** 800,805 **** +--- 840,846 ---- } if(action == 'R' && curwp->w_markp){ @@ -813,7 +813,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c thisflag |= CFFILL; *************** -*** 815,835 **** +*** 811,831 **** swap_mark_and_dot_if_mark_comes_first(); /* determine if we're justifying quoted text or not */ @@ -835,7 +835,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c /* * Justfiy the current paragraph. ---- 856,881 ---- +--- 852,877 ---- swap_mark_and_dot_if_mark_comes_first(); /* determine if we're justifying quoted text or not */ @@ -863,7 +863,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c /* * Justfiy the current paragraph. *************** -*** 841,856 **** +*** 837,852 **** if(gotoeop(FALSE, 1) == FALSE) return(FALSE); @@ -880,7 +880,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c /* let yank() know that it may be restoring a paragraph */ thisflag |= (CFFILL | CFFLPA); ---- 887,902 ---- +--- 883,898 ---- if(gotoeop(FALSE, 1) == FALSE) return(FALSE); @@ -898,7 +898,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c thisflag |= (CFFILL | CFFLPA); *************** -*** 864,872 **** +*** 860,868 **** /* * Fillregion moves dot to the end of the filled region. */ @@ -908,7 +908,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c set_last_region_added(&addedregion); /* Leave cursor on first char of first line after justified region */ ---- 910,924 ---- +--- 906,920 ---- /* * Fillregion moves dot to the end of the filled region. */ @@ -925,7 +925,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c /* Leave cursor on first char of first line after justified region */ *************** -*** 908,923 **** +*** 904,919 **** * can delete it and restore the saved part. */ int @@ -942,7 +942,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c REGION region; /* if region starts midline insert a newline */ ---- 960,975 ---- +--- 956,971 ---- * can delete it and restore the saved part. */ int @@ -960,8 +960,8 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c /* if region starts midline insert a newline */ *************** -*** 928,933 **** ---- 980,1014 ---- +*** 924,929 **** +--- 976,1010 ---- if(curwp->w_marko > 0 && curwp->w_marko < llength(curwp->w_markp)) ends_midline++; @@ -998,7 +998,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c fdelete(); if(!getregion(®ion, curwp->w_markp, curwp->w_marko)) *************** -*** 944,971 **** +*** 940,967 **** /* Now insert it back wrapped */ spaces = word_len = word_ind = line_len = same_word = 0; @@ -1027,7 +1027,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c /* then digest the rest... */ while((c = fremove(i++)) >= 0){ ---- 1025,1060 ---- +--- 1021,1056 ---- /* Now insert it back wrapped */ spaces = word_len = word_ind = line_len = same_word = 0; @@ -1065,7 +1065,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c /* then digest the rest... */ while((c = fremove(i++)) >= 0){ *************** -*** 986,1006 **** +*** 982,1002 **** case TAB : case ' ' : @@ -1087,7 +1087,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c linsert(1, ' '); /* need padding? */ line_len++; } ---- 1075,1096 ---- +--- 1071,1092 ---- case TAB : case ' ' : @@ -1111,7 +1111,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c line_len++; } *************** -*** 1022,1029 **** +*** 1018,1025 **** if(word_ind + 1 >= NSTRING){ /* Magic! Fake that we output a wrapped word */ @@ -1120,7 +1120,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c linsert(1, ' '); line_len = fpnewline(qstr); } ---- 1112,1119 ---- +--- 1108,1115 ---- if(word_ind + 1 >= NSTRING){ /* Magic! Fake that we output a wrapped word */ @@ -1130,7 +1130,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c line_len = fpnewline(qstr); } *************** -*** 1045,1056 **** +*** 1041,1052 **** } if(word_len){ @@ -1143,7 +1143,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c linsert(1, ' '); for(j = 0; j < word_ind; j++) ---- 1135,1146 ---- +--- 1131,1142 ---- } if(word_len){ @@ -1157,7 +1157,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c for(j = 0; j < word_ind; j++) *************** -*** 1108,1118 **** +*** 1104,1114 **** int len; lnewline(); @@ -1169,7 +1169,7 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c linsert(1, *quote); } ---- 1198,1208 ---- +--- 1194,1204 ---- int len; lnewline(); @@ -1182,8 +1182,8 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c } *************** -*** 1256,1260 **** ---- 1346,1390 ---- +*** 1252,1256 **** +--- 1342,1386 ---- markregion(1); } @@ -1229,12 +1229,12 @@ diff -rc alpine-2.25/pico/word.c alpine-2.25.fillpara/pico/word.c + return get_indent_raw_line(q, GLine, buf, buflen, k, plb); + } + -diff -rc alpine-2.25/pith/charconv/utf8.c alpine-2.25.fillpara/pith/charconv/utf8.c -*** alpine-2.25/pith/charconv/utf8.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/charconv/utf8.c 2021-09-18 09:03:13.583040342 -0600 +diff -rc alpine-2.26/pith/charconv/utf8.c alpine-2.26.fillpara/pith/charconv/utf8.c +*** alpine-2.26/pith/charconv/utf8.c 2022-06-02 18:14:00.495274738 -0600 +--- alpine-2.26.fillpara/pith/charconv/utf8.c 2022-06-02 18:14:57.019136141 -0600 *************** -*** 1117,1122 **** ---- 1117,1172 ---- +*** 1113,1118 **** +--- 1113,1168 ---- /* @@ -1291,9 +1291,9 @@ diff -rc alpine-2.25/pith/charconv/utf8.c alpine-2.25.fillpara/pith/charconv/utf * Copy UTF-8 characters from src into dst. * This is intended to be used if you want to truncate a string at * the start instead of the end. For example, you have a long string -diff -rc alpine-2.25/pith/charconv/utf8.h alpine-2.25.fillpara/pith/charconv/utf8.h -*** alpine-2.25/pith/charconv/utf8.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/charconv/utf8.h 2021-09-18 09:03:13.583040342 -0600 +diff -rc alpine-2.26/pith/charconv/utf8.h alpine-2.26.fillpara/pith/charconv/utf8.h +*** alpine-2.26/pith/charconv/utf8.h 2022-06-02 18:14:00.495274738 -0600 +--- alpine-2.26.fillpara/pith/charconv/utf8.h 2022-06-02 18:14:57.023136132 -0600 *************** *** 82,87 **** --- 82,88 ---- @@ -1304,11 +1304,11 @@ diff -rc alpine-2.25/pith/charconv/utf8.h alpine-2.25.fillpara/pith/charconv/utf size_t utf8_to_width_rhs(char *, char *, size_t, unsigned); int utf8_snprintf(char *, size_t, char *, ...); size_t utf8_to_width(char *, char *, size_t, unsigned, unsigned *); -diff -rc alpine-2.25/pith/color.c alpine-2.25.fillpara/pith/color.c -*** alpine-2.25/pith/color.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/color.c 2021-09-18 09:03:13.583040342 -0600 +diff -rc alpine-2.26/pith/color.c alpine-2.26.fillpara/pith/color.c +*** alpine-2.26/pith/color.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fillpara/pith/color.c 2022-06-02 18:14:57.023136132 -0600 *************** -*** 21,27 **** +*** 17,23 **** #include "../pith/state.h" #include "../pith/conf.h" #include "../pith/filter.h" @@ -1316,7 +1316,7 @@ diff -rc alpine-2.25/pith/color.c alpine-2.25.fillpara/pith/color.c char * color_embed(char *fg, char *bg) ---- 21,28 ---- +--- 17,24 ---- #include "../pith/state.h" #include "../pith/conf.h" #include "../pith/filter.h" @@ -1326,7 +1326,7 @@ diff -rc alpine-2.25/pith/color.c alpine-2.25.fillpara/pith/color.c char * color_embed(char *fg, char *bg) *************** -*** 70,92 **** +*** 66,88 **** struct quote_colors *next; }; @@ -1350,7 +1350,7 @@ diff -rc alpine-2.25/pith/color.c alpine-2.25.fillpara/pith/color.c struct quote_colors *c; /* ---- 71,180 ---- +--- 67,176 ---- struct quote_colors *next; }; @@ -1462,7 +1462,7 @@ diff -rc alpine-2.25/pith/color.c alpine-2.25.fillpara/pith/color.c /* *************** -*** 135,141 **** +*** 131,137 **** free_color_pair(&col); cp = NULL; @@ -1470,7 +1470,7 @@ diff -rc alpine-2.25/pith/color.c alpine-2.25.fillpara/pith/color.c cp = (cp && cp->next) ? cp->next : colors; if(countem > 0) ---- 223,229 ---- +--- 219,225 ---- free_color_pair(&col); cp = NULL; @@ -1479,7 +1479,7 @@ diff -rc alpine-2.25/pith/color.c alpine-2.25.fillpara/pith/color.c if(countem > 0) *************** -*** 145,154 **** +*** 141,150 **** countem = (countem == 1) ? 0 : countem; @@ -1490,7 +1490,7 @@ diff -rc alpine-2.25/pith/color.c alpine-2.25.fillpara/pith/color.c } if(colors){ ---- 233,241 ---- +--- 229,237 ---- countem = (countem == 1) ? 0 : countem; @@ -1501,7 +1501,7 @@ diff -rc alpine-2.25/pith/color.c alpine-2.25.fillpara/pith/color.c if(colors){ *************** -*** 211,217 **** +*** 207,213 **** } } @@ -1509,7 +1509,7 @@ diff -rc alpine-2.25/pith/color.c alpine-2.25.fillpara/pith/color.c } ---- 298,304 ---- +--- 294,300 ---- } } @@ -1517,9 +1517,9 @@ diff -rc alpine-2.25/pith/color.c alpine-2.25.fillpara/pith/color.c } -diff -rc alpine-2.25/pith/color.h alpine-2.25.fillpara/pith/color.h -*** alpine-2.25/pith/color.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/color.h 2021-09-18 09:03:13.583040342 -0600 +diff -rc alpine-2.26/pith/color.h alpine-2.26.fillpara/pith/color.h +*** alpine-2.26/pith/color.h 2022-06-02 18:14:00.495274738 -0600 +--- alpine-2.26.fillpara/pith/color.h 2022-06-02 18:14:57.027136121 -0600 *************** *** 22,27 **** --- 22,45 ---- @@ -1557,12 +1557,12 @@ diff -rc alpine-2.25/pith/color.h alpine-2.25.fillpara/pith/color.h int color_a_quote(long, char *, LT_INS_S **, void *); void free_spec_colors(SPEC_COLOR_S **); -diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c -*** alpine-2.25/pith/filter.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/filter.c 2021-09-18 09:03:13.591040398 -0600 +diff -rc alpine-2.26/pith/filter.c alpine-2.26.fillpara/pith/filter.c +*** alpine-2.26/pith/filter.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fillpara/pith/filter.c 2022-06-02 18:14:57.031136112 -0600 *************** -*** 46,51 **** ---- 46,52 ---- +*** 42,47 **** +--- 42,48 ---- #include "../pith/conf.h" #include "../pith/store.h" #include "../pith/color.h" @@ -1571,8 +1571,8 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c #include "../pith/pipe.h" #include "../pith/status.h" *************** -*** 9454,9459 **** ---- 9455,9465 ---- +*** 9503,9508 **** +--- 9504,9514 ---- margin_r, indent; char special[256]; @@ -1585,8 +1585,8 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c #define WRAP_MARG_L(F) (((WRAP_S *)(F)->opt)->margin_l) *************** -*** 9495,9500 **** ---- 9501,9512 ---- +*** 9544,9549 **** +--- 9550,9561 ---- #define WRAP_COLOR(F) (((WRAP_S *)(F)->opt)->color) #define WRAP_COLOR_SET(F) ((WRAP_COLOR(F)) && (WRAP_COLOR(F)->fg[0])) #define WRAP_SPACES(F) (((WRAP_S *)(F)->opt)->spaces) @@ -1600,8 +1600,8 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c if((F)->linep == WRAP_LASTC(F)){ \ size_t offset = (F)->linep - (F)->line; \ *************** -*** 9572,9577 **** ---- 9584,9591 ---- +*** 9621,9626 **** +--- 9633,9640 ---- case CCR : /* CRLF or CR in text ? */ state = BOL; /* either way, handle start */ @@ -1611,7 +1611,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c /* wrapped line? */ if(f->f2 == 0 && WRAP_SPC_LEN(f) && WRAP_TRL_SPC(f)){ *************** -*** 9665,9671 **** +*** 9714,9720 **** case BOL : if(WRAP_FLOW(f)){ @@ -1619,7 +1619,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c WRAP_FL_QC(f) = 1; /* init it */ state = FL_QLEV; /* go collect it */ } ---- 9679,9689 ---- +--- 9728,9738 ---- case BOL : if(WRAP_FLOW(f)){ @@ -1632,7 +1632,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c state = FL_QLEV; /* go collect it */ } *************** -*** 9679,9685 **** +*** 9728,9734 **** } /* quote level change implies new paragraph */ @@ -1640,7 +1640,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c WRAP_FL_QD(f) = 0; if(WRAP_HARD(f) == 0){ WRAP_HARD(f) = 1; ---- 9697,9712 ---- +--- 9746,9761 ---- } /* quote level change implies new paragraph */ @@ -1658,7 +1658,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c if(WRAP_HARD(f) == 0){ WRAP_HARD(f) = 1; *************** -*** 9731,9738 **** +*** 9780,9787 **** break; case FL_QLEV : @@ -1667,7 +1667,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c } else { /* if EMBEDed, process it and return here */ ---- 9758,9769 ---- +--- 9807,9818 ---- break; case FL_QLEV : @@ -1681,7 +1681,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c else { /* if EMBEDed, process it and return here */ *************** -*** 9744,9750 **** +*** 9793,9799 **** } /* quote level change signals new paragraph */ @@ -1689,7 +1689,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c WRAP_FL_QD(f) = WRAP_FL_QC(f); if(WRAP_HARD(f) == 0){ /* add hard newline */ WRAP_HARD(f) = 1; /* hard newline */ ---- 9775,9790 ---- +--- 9824,9839 ---- } /* quote level change signals new paragraph */ @@ -1707,8 +1707,8 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c if(WRAP_HARD(f) == 0){ /* add hard newline */ WRAP_HARD(f) = 1; /* hard newline */ *************** -*** 9801,9806 **** ---- 9841,9853 ---- +*** 9850,9855 **** +--- 9890,9902 ---- state = FL_SIG; break; @@ -1723,7 +1723,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c state = DFL; goto case_dfl; /* handle c like DFL */ *************** -*** 9817,9823 **** +*** 9866,9872 **** &eob); /* note any embedded*/ wrap_eol(f, 1, &ip, &eib, &op, &eob); /* plunk down newline */ @@ -1731,7 +1731,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c &op, &eob); /* write any prefix */ } ---- 9864,9870 ---- +--- 9913,9919 ---- &eob); /* note any embedded*/ wrap_eol(f, 1, &ip, &eib, &op, &eob); /* plunk down newline */ @@ -1740,7 +1740,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c } *************** -*** 10314,10320 **** +*** 10363,10369 **** wrap_flush_embed(f, &ip, &eib, &op, &eob); wrap_eol(f, 1, &ip, &eib, &op, &eob); /* plunk down newline */ @@ -1748,7 +1748,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c &eob); /* write any prefix */ } ---- 10361,10367 ---- +--- 10410,10416 ---- wrap_flush_embed(f, &ip, &eib, &op, &eob); wrap_eol(f, 1, &ip, &eib, &op, &eob); /* plunk down newline */ @@ -1757,8 +1757,8 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c } *************** -*** 10387,10392 **** ---- 10434,10446 ---- +*** 10436,10441 **** +--- 10483,10495 ---- if(WRAP_COLOR(f)) free_color_pair(&WRAP_COLOR(f)); @@ -1773,7 +1773,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c so_give(&WRAP_SPACES(f)); fs_give((void **) &f->opt); /* free wrap widths struct */ *************** -*** 10737,10743 **** +*** 10786,10792 **** { int j, i; COLOR_PAIR *col = NULL; @@ -1781,7 +1781,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c if(ps_global->VAR_QUOTE_REPLACE_STRING){ get_pair(ps_global->VAR_QUOTE_REPLACE_STRING, &prefix, &last_prefix, 0, 0); ---- 10791,10798 ---- +--- 10840,10847 ---- { int j, i; COLOR_PAIR *col = NULL; @@ -1791,7 +1791,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c if(ps_global->VAR_QUOTE_REPLACE_STRING){ get_pair(ps_global->VAR_QUOTE_REPLACE_STRING, &prefix, &last_prefix, 0, 0); *************** -*** 10746,10755 **** +*** 10795,10804 **** last_prefix = NULL; } } @@ -1802,7 +1802,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c && ps_global->VAR_QUOTE1_FORE_COLOR && ps_global->VAR_QUOTE1_BACK_COLOR && (col = new_color_pair(ps_global->VAR_QUOTE1_FORE_COLOR, ---- 10801,10822 ---- +--- 10850,10871 ---- last_prefix = NULL; } } @@ -1826,7 +1826,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c && ps_global->VAR_QUOTE1_BACK_COLOR && (col = new_color_pair(ps_global->VAR_QUOTE1_FORE_COLOR, *************** -*** 10757,10763 **** +*** 10806,10812 **** && pico_is_good_colorpair(col)){ GF_COLOR_PUTC(f, col); } @@ -1834,7 +1834,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c && ps_global->VAR_QUOTE2_FORE_COLOR && ps_global->VAR_QUOTE2_BACK_COLOR && (col = new_color_pair(ps_global->VAR_QUOTE2_FORE_COLOR, ---- 10824,10830 ---- +--- 10873,10879 ---- && pico_is_good_colorpair(col)){ GF_COLOR_PUTC(f, col); } @@ -1843,7 +1843,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c && ps_global->VAR_QUOTE2_BACK_COLOR && (col = new_color_pair(ps_global->VAR_QUOTE2_FORE_COLOR, *************** -*** 10765,10771 **** +*** 10814,10820 **** && pico_is_good_colorpair(col)){ GF_COLOR_PUTC(f, col); } @@ -1851,7 +1851,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c && ps_global->VAR_QUOTE3_FORE_COLOR && ps_global->VAR_QUOTE3_BACK_COLOR && (col = new_color_pair(ps_global->VAR_QUOTE3_FORE_COLOR, ---- 10832,10838 ---- +--- 10881,10887 ---- && pico_is_good_colorpair(col)){ GF_COLOR_PUTC(f, col); } @@ -1860,7 +1860,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c && ps_global->VAR_QUOTE3_BACK_COLOR && (col = new_color_pair(ps_global->VAR_QUOTE3_FORE_COLOR, *************** -*** 10779,10821 **** +*** 10828,10870 **** } } @@ -1904,7 +1904,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c return 0; } ---- 10846,10892 ---- +--- 10895,10941 ---- } } @@ -1953,8 +1953,8 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c return 0; } *************** -*** 10847,10852 **** ---- 10918,10929 ---- +*** 10896,10901 **** +--- 10967,10978 ---- wrap->hdr_color = (GFW_HDRCOLOR & flags) == GFW_HDRCOLOR; wrap->for_compose = (GFW_FORCOMPOSE & flags) == GFW_FORCOMPOSE; wrap->handle_soft_hyphen = (GFW_SOFTHYPHEN & flags) == GFW_SOFTHYPHEN; @@ -1968,8 +1968,8 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c return((void *) wrap); } *************** -*** 11290,11296 **** ---- 11367,11581 ---- +*** 11339,11345 **** +--- 11416,11630 ---- } \ } @@ -2022,7 +2022,7 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c + register int l;\ + \ + for (gline = cline = line; gline && cline; ){\ -+ if(cline = strchr(gline,'\012'))\ ++ if((cline = strchr(gline,'\012')) != NULL)\ + *cline = '\0';\ + done = (*((LINETEST_S *) (F)->opt)->f)((F)->n++, gline, &ins,\ + ((LINETEST_S *) (F)->opt)->local);\ @@ -2185,9 +2185,9 @@ diff -rc alpine-2.25/pith/filter.c alpine-2.25.fillpara/pith/filter.c /* * this simple filter accumulates characters until a newline, offers it -diff -rc alpine-2.25/pith/filter.h alpine-2.25.fillpara/pith/filter.h -*** alpine-2.25/pith/filter.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/filter.h 2021-09-18 09:03:13.591040398 -0600 +diff -rc alpine-2.26/pith/filter.h alpine-2.26.fillpara/pith/filter.h +*** alpine-2.26/pith/filter.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fillpara/pith/filter.h 2022-06-02 18:14:57.031136112 -0600 *************** *** 217,222 **** --- 217,223 ---- @@ -2198,9 +2198,9 @@ diff -rc alpine-2.25/pith/filter.h alpine-2.25.fillpara/pith/filter.h void *gf_url_hilite_opt(URL_HILITE_S *, HANDLE_S **, int); void free_filter_module_globals(void); -diff -rc alpine-2.25/pith/filttype.h alpine-2.25.fillpara/pith/filttype.h -*** alpine-2.25/pith/filttype.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/filttype.h 2021-09-18 09:03:13.591040398 -0600 +diff -rc alpine-2.26/pith/filttype.h alpine-2.26.fillpara/pith/filttype.h +*** alpine-2.26/pith/filttype.h 2022-06-02 18:14:00.495274738 -0600 +--- alpine-2.26.fillpara/pith/filttype.h 2022-06-02 18:14:57.031136112 -0600 *************** *** 36,41 **** --- 36,43 ---- @@ -2212,11 +2212,11 @@ diff -rc alpine-2.25/pith/filttype.h alpine-2.25.fillpara/pith/filttype.h void *opt; /* optional per instance data */ void *data; /* misc internal data pointer */ unsigned char queue[1 + GF_MAXBUF]; -diff -rc alpine-2.25/pith/mailview.c alpine-2.25.fillpara/pith/mailview.c -*** alpine-2.25/pith/mailview.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/mailview.c 2021-09-18 09:03:13.603040480 -0600 +diff -rc alpine-2.26/pith/mailview.c alpine-2.26.fillpara/pith/mailview.c +*** alpine-2.26/pith/mailview.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fillpara/pith/mailview.c 2022-06-02 18:14:57.035136102 -0600 *************** -*** 55,61 **** +*** 51,57 **** #include "../pith/escapes.h" #include "../pith/keyword.h" #include "../pith/smime.h" @@ -2224,7 +2224,7 @@ diff -rc alpine-2.25/pith/mailview.c alpine-2.25.fillpara/pith/mailview.c #define FBUF_LEN (50) ---- 55,65 ---- +--- 51,61 ---- #include "../pith/escapes.h" #include "../pith/keyword.h" #include "../pith/smime.h" @@ -2237,7 +2237,7 @@ diff -rc alpine-2.25/pith/mailview.c alpine-2.25.fillpara/pith/mailview.c #define FBUF_LEN (50) *************** -*** 638,644 **** +*** 634,640 **** && pico_usingcolor() && ps_global->VAR_SIGNATURE_FORE_COLOR && ps_global->VAR_SIGNATURE_BACK_COLOR){ @@ -2245,7 +2245,7 @@ diff -rc alpine-2.25/pith/mailview.c alpine-2.25.fillpara/pith/mailview.c } if((flgs & FM_DISPLAY) ---- 642,648 ---- +--- 638,644 ---- && pico_usingcolor() && ps_global->VAR_SIGNATURE_FORE_COLOR && ps_global->VAR_SIGNATURE_BACK_COLOR){ @@ -2254,7 +2254,7 @@ diff -rc alpine-2.25/pith/mailview.c alpine-2.25.fillpara/pith/mailview.c if((flgs & FM_DISPLAY) *************** -*** 646,653 **** +*** 642,649 **** && pico_usingcolor() && ps_global->VAR_QUOTE1_FORE_COLOR && ps_global->VAR_QUOTE1_BACK_COLOR){ @@ -2263,7 +2263,7 @@ diff -rc alpine-2.25/pith/mailview.c alpine-2.25.fillpara/pith/mailview.c if(!(flgs & FM_NOWRAP)){ wrapflags = (flgs & FM_DISPLAY) ? (GFW_HANDLES|GFW_SOFTHYPHEN) : GFW_NONE; ---- 650,659 ---- +--- 646,655 ---- && pico_usingcolor() && ps_global->VAR_QUOTE1_FORE_COLOR && ps_global->VAR_QUOTE1_BACK_COLOR){ @@ -2275,7 +2275,7 @@ diff -rc alpine-2.25/pith/mailview.c alpine-2.25.fillpara/pith/mailview.c if(!(flgs & FM_NOWRAP)){ wrapflags = (flgs & FM_DISPLAY) ? (GFW_HANDLES|GFW_SOFTHYPHEN) : GFW_NONE; *************** -*** 1463,1489 **** +*** 1459,1485 **** color_signature(long int linenum, char *line, LT_INS_S **ins, void *is_in_sig) { struct variable *vars = ps_global->vars; @@ -2303,7 +2303,7 @@ diff -rc alpine-2.25/pith/mailview.c alpine-2.25.fillpara/pith/mailview.c if(*in_sig_block != OUT_SIG_BLOCK && VAR_SIGNATURE_FORE_COLOR && VAR_SIGNATURE_BACK_COLOR && (col = new_color_pair(VAR_SIGNATURE_FORE_COLOR, ---- 1469,1556 ---- +--- 1465,1552 ---- color_signature(long int linenum, char *line, LT_INS_S **ins, void *is_in_sig) { struct variable *vars = ps_global->vars; @@ -2327,7 +2327,7 @@ diff -rc alpine-2.25/pith/mailview.c alpine-2.25.fillpara/pith/mailview.c + PLine[sizeof(PLine)-1] = '\0'; + } + -+ if(p = strchr(tmp_20k_buf, '\015')) *p = '\0'; ++ if((p = strchr(tmp_20k_buf, '\015')) != NULL) *p = '\0'; + strncpy(NLine, tmp_20k_buf, sizeof(NLine)); + NLine[sizeof(NLine) - 1] = '\0'; + if (p) *p = '\015'; @@ -2393,8 +2393,8 @@ diff -rc alpine-2.25/pith/mailview.c alpine-2.25.fillpara/pith/mailview.c && VAR_SIGNATURE_FORE_COLOR && VAR_SIGNATURE_BACK_COLOR && (col = new_color_pair(VAR_SIGNATURE_FORE_COLOR, *************** -*** 2043,2048 **** ---- 2110,2186 ---- +*** 2039,2044 **** +--- 2106,2182 ---- } @@ -2472,9 +2472,9 @@ diff -rc alpine-2.25/pith/mailview.c alpine-2.25.fillpara/pith/mailview.c #define UES_LEN 12 #define UES_MAX 32 -diff -rc alpine-2.25/pith/mailview.h alpine-2.25.fillpara/pith/mailview.h -*** alpine-2.25/pith/mailview.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/mailview.h 2021-09-18 09:03:13.603040480 -0600 +diff -rc alpine-2.26/pith/mailview.h alpine-2.26.fillpara/pith/mailview.h +*** alpine-2.26/pith/mailview.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fillpara/pith/mailview.h 2022-06-02 18:14:57.035136102 -0600 *************** *** 146,151 **** --- 146,152 ---- @@ -2485,11 +2485,11 @@ diff -rc alpine-2.25/pith/mailview.h alpine-2.25.fillpara/pith/mailview.h int scroll_handle_start_color(char *, size_t, int *); int scroll_handle_end_color(char *, size_t, int *, int); int width_at_this_position(unsigned char *, unsigned long); -diff -rc alpine-2.25/pith/osdep/color.c alpine-2.25.fillpara/pith/osdep/color.c -*** alpine-2.25/pith/osdep/color.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/osdep/color.c 2021-09-18 09:03:13.611040536 -0600 +diff -rc alpine-2.26/pith/osdep/color.c alpine-2.26.fillpara/pith/osdep/color.c +*** alpine-2.26/pith/osdep/color.c 2022-06-02 18:14:00.495274738 -0600 +--- alpine-2.26.fillpara/pith/osdep/color.c 2022-06-02 18:14:57.039136093 -0600 *************** -*** 32,38 **** +*** 28,34 **** #include #include "./color.h" @@ -2497,7 +2497,7 @@ diff -rc alpine-2.25/pith/osdep/color.c alpine-2.25.fillpara/pith/osdep/color.c /* ---- 32,40 ---- +--- 28,36 ---- #include #include "./color.h" @@ -2508,8 +2508,8 @@ diff -rc alpine-2.25/pith/osdep/color.c alpine-2.25.fillpara/pith/osdep/color.c /* *************** -*** 92,94 **** ---- 94,1375 ---- +*** 88,90 **** +--- 90,1372 ---- { return(pico_set_colors(col ? col->fg : NULL, col ? col->bg : NULL, flags)); } @@ -2533,8 +2533,8 @@ diff -rc alpine-2.25/pith/osdep/color.c alpine-2.25.fillpara/pith/osdep/color.c + allowed_after_period(next((word),(k)))) ||\ + (c) == RPAREN || (c) == '}' || (c) == ']' ||\ + ISspace(c) || is_a_digit(c) || \ -+ ((c) == '-' ) && \ -+ allowed_after_dash(next((word),(k)))) \ ++ (((c) == '-' ) && \ ++ allowed_after_dash(next((word),(k))))) \ + ? 1 : 0) + #define allowed_after_period(c) (((c) == RPAREN || (c) == '}' || (c) == ']' ||\ + ISspace(c) || (c) == '-' || \ @@ -2566,9 +2566,9 @@ diff -rc alpine-2.25/pith/osdep/color.c alpine-2.25.fillpara/pith/osdep/color.c + ((c) == LPAREN) || ((c) == '/')|| ((c) == '`') ||\ + ((c) == '{') || ((c) == '\\') || (iscontrol((c))) ||\ + (((c) >= '0') && ((c) <= '9')) || ((c) == '?')) -+ #define is_cletter(c) ((((c) >= 'a') && ((c) <= 'z'))) ||\ ++ #define is_cletter(c) (((((c) >= 'a') && ((c) <= 'z'))) ||\ + ((((c) >= 'A') && ((c) <= 'Z'))||\ -+ is8bit(c)) ++ is8bit(c))) + #define is_cnumber(c) ((c) >= '0' && (c) <= '9') + #define allwd_after_word(c) (((c) == ' ') || ((c) == '>') || is_cletter(c)) + #define allwd_after_qsword(c) (((c) != '\\') && ((c) != RPAREN) && ((c) != '/')) @@ -2626,8 +2626,8 @@ diff -rc alpine-2.25/pith/osdep/color.c alpine-2.25.fillpara/pith/osdep/color.c + if(!strncmp(list1[i], word, k) && ISspace(word[k])) + rv++; + -+ if(rv) -+ return rv; ++ if(rv) ++ return rv; + + for(i = 0; rv == 0 && list2[i] && (k = strlen(list2[i])) && k <= j; i++) + if(!strncmp(list2[i], word, k) && (!word[k] || ISspace(word[k]))) @@ -3215,7 +3215,7 @@ diff -rc alpine-2.25/pith/osdep/color.c alpine-2.25.fillpara/pith/osdep/color.c + * strange is coming. We need to confirm if this is a + * good choice later. For now we will let it pass. + */ -+ if (isaword(word,i,j) || isamailbox(word,i,j)){ ++ if (isaword(word,i,j) || isamailbox(word,i,j)){ + int offset; + QStrType qstype; + @@ -3243,15 +3243,15 @@ diff -rc alpine-2.25/pith/osdep/color.c alpine-2.25.fillpara/pith/osdep/color.c + return qs_add(qs, word, qstype, i, j, offset, 1); + } + finished++; -+ } -+ else{ -+ if(i > 0) -+ return qs_add(qs, word, qsNormal, 0, i, 0, 1); -+ else if(!forbidden(c)) -+ return qs_add(qs, word, qsChar, 0, 1, 0, 1); -+ else /* chao pescao */ -+ finished++; -+ } ++ } ++ else{ ++ if(i > 0) ++ return qs_add(qs, word, qsNormal, 0, i, 0, 1); ++ else if(!forbidden(c)) ++ return qs_add(qs, word, qsChar, 0, 1, 0, 1); ++ else /* chao pescao */ ++ finished++; ++ } + break; + } /* End Switch */ + } /* End while */ @@ -3263,7 +3263,7 @@ diff -rc alpine-2.25/pith/osdep/color.c alpine-2.25.fillpara/pith/osdep/color.c + int + isaword(char word[NSTRING], int i, int j) + { -+ return i <= j && is_cletter(word[i]) ? ++ return (i <= j && is_cletter(word[i])) ? + (i < j ? isaword(word,i+1,j) : 1) : 0; + } + @@ -3363,7 +3363,7 @@ diff -rc alpine-2.25/pith/osdep/color.c alpine-2.25.fillpara/pith/osdep/color.c + */ + flatten_qstring(pl, pbuf, NSTRING); + emptypl = (!PLine || !PLine[0] || -+ (pl && value_is_space(pbuf)) && !PLine[strlen(pbuf)]) ? 1 : 0; ++ (pl && value_is_space(pbuf) && !PLine[strlen(pbuf)])) ? 1 : 0; + if (emptypl){ + flatten_qstring(nl, nbuf, NSTRING); + emptynl = (!NLine || !NLine[0] || @@ -3469,26 +3469,26 @@ diff -rc alpine-2.25/pith/osdep/color.c alpine-2.25.fillpara/pith/osdep/color.c + cl = qs_remove_trailing_spaces(cl); + else + if (NewC > NewN){ -+ int agree = 0; -+ for (j = 0; (j < n) && (GLine[j] == NLine[j]); j++); -+ clength = j; ++ int agree = 0; ++ for (j = 0; (j < n) && (GLine[j] == NLine[j]); j++); ++ clength = j; + /* clength is the common length in which Gline and Nline agree */ + /* j < n means that they do not agree fully */ + /* GLine = " \tText" + NLine = " Text" */ -+ if(j == n) -+ agree++; -+ if (clength < n){ /* see if buf and nbuf are padded with spaces and tabs */ -+ for (i = clength; i < n && ISspace(NLine[i]); i++); -+ if (i == n){/* padded NLine until the end of spaces? */ -+ for (i = clength; i < c && ISspace(GLine[i]); i++); ++ if(j == n) ++ agree++; ++ if (clength < n){ /* see if buf and nbuf are padded with spaces and tabs */ ++ for (i = clength; i < n && ISspace(NLine[i]); i++); ++ if (i == n){/* padded NLine until the end of spaces? */ ++ for (i = clength; i < c && ISspace(GLine[i]); i++); + if (i == c) /* Padded CLine until the end of spaces? */ + agree++; -+ } -+ } -+ if (agree){ -+ for (j = clength; j < c && ISspace(GLine[j]); j++); -+ if (j == c){ ++ } ++ } ++ if (agree){ ++ for (j = clength; j < c && ISspace(GLine[j]); j++); ++ if (j == c){ + /* + * If we get here, it means that the current line has the same + * quote string (visually) than the next line, but both of them @@ -3535,15 +3535,15 @@ diff -rc alpine-2.25/pith/osdep/color.c alpine-2.25.fillpara/pith/osdep/color.c + * " More Text" (NLine) n = 3 + * + */ -+ for (j = 0; (j < p) && (GLine[j] == PLine[j]); j++); -+ if ((p != c || j != p) && NLine[n]) -+ if(!get_indent_raw_line(q, PLine, nbuf, NSTRING, p, plb) -+ || NewP + strlenis(nbuf) != NewC){ -+ free_qs(&cl); -+ free_qs(&pl); -+ return nl; -+ } -+ } ++ for (j = 0; (j < p) && (GLine[j] == PLine[j]); j++); ++ if ((p != c || j != p) && NLine[n]) ++ if(!get_indent_raw_line(q, PLine, nbuf, NSTRING, p, plb) ++ || NewP + strlenis(nbuf) != NewC){ ++ free_qs(&cl); ++ free_qs(&pl); ++ return nl; ++ } ++ } + } + } + @@ -3626,7 +3626,8 @@ diff -rc alpine-2.25/pith/osdep/color.c alpine-2.25.fillpara/pith/osdep/color.c + switch (c = (unsigned char) now(word,i)){ + case NBSP: + case TAB : -+ case ' ' : for (; ISspace(word[i]); i++); ++ case ' ' : for (; ISspace(word[i]); i++) ++ ; + if (!is_indent_char(now(word,i))) + finished++; + break; @@ -3792,9 +3793,9 @@ diff -rc alpine-2.25/pith/osdep/color.c alpine-2.25.fillpara/pith/osdep/color.c + return allowed_qstr; + } + -diff -rc alpine-2.25/pith/osdep/color.h alpine-2.25.fillpara/pith/osdep/color.h -*** alpine-2.25/pith/osdep/color.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/osdep/color.h 2021-09-18 09:03:13.615040563 -0600 +diff -rc alpine-2.26/pith/osdep/color.h alpine-2.26.fillpara/pith/osdep/color.h +*** alpine-2.26/pith/osdep/color.h 2022-06-02 18:14:00.495274738 -0600 +--- alpine-2.26.fillpara/pith/osdep/color.h 2022-06-02 18:14:57.039136093 -0600 *************** *** 17,22 **** --- 17,40 ---- @@ -3845,12 +3846,12 @@ diff -rc alpine-2.25/pith/osdep/color.h alpine-2.25.fillpara/pith/osdep/color.h ! void record_quote_string (QSTRING_S *); #endif /* PITH_OSDEP_COLOR_INCLUDED */ -diff -rc alpine-2.25/pith/pine.hlp alpine-2.25.fillpara/pith/pine.hlp -*** alpine-2.25/pith/pine.hlp 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/pine.hlp 2021-09-18 09:03:13.627040646 -0600 +diff -rc alpine-2.26/pith/pine.hlp alpine-2.26.fillpara/pith/pine.hlp +*** alpine-2.26/pith/pine.hlp 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fillpara/pith/pine.hlp 2022-06-02 18:14:57.059136043 -0600 *************** -*** 8354,8359 **** ---- 8354,8399 ---- +*** 8510,8515 **** +--- 8510,8555 ---- "type the character ^".

    @@ -3897,12 +3898,12 @@ diff -rc alpine-2.25/pith/pine.hlp alpine-2.25.fillpara/pith/pine.hlp <End of help on this topic> -diff -rc alpine-2.25/pith/reply.c alpine-2.25.fillpara/pith/reply.c -*** alpine-2.25/pith/reply.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/reply.c 2021-09-18 09:03:13.631040673 -0600 +diff -rc alpine-2.26/pith/reply.c alpine-2.26.fillpara/pith/reply.c +*** alpine-2.26/pith/reply.c 2022-06-02 18:14:00.495274738 -0600 +--- alpine-2.26.fillpara/pith/reply.c 2022-06-02 18:14:57.059136043 -0600 *************** -*** 2838,2843 **** ---- 2838,2846 ---- +*** 2834,2839 **** +--- 2834,2842 ---- if(flow_res && ps_global->reply.use_flowed) wrapflags |= GFW_FLOW_RESULT; @@ -3913,7 +3914,7 @@ diff -rc alpine-2.25/pith/reply.c alpine-2.25.fillpara/pith/reply.c /* * The 80 will cause longer lines than what is likely *************** -*** 2931,2937 **** +*** 2927,2933 **** dq.do_color = 0; dq.delete_all = 1; @@ -3921,7 +3922,7 @@ diff -rc alpine-2.25/pith/reply.c alpine-2.25.fillpara/pith/reply.c filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq); } ---- 2934,2940 ---- +--- 2930,2936 ---- dq.do_color = 0; dq.delete_all = 1; @@ -3929,12 +3930,12 @@ diff -rc alpine-2.25/pith/reply.c alpine-2.25.fillpara/pith/reply.c filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq); } -diff -rc alpine-2.25/pith/state.c alpine-2.25.fillpara/pith/state.c -*** alpine-2.25/pith/state.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/state.c 2021-09-18 09:03:13.631040673 -0600 +diff -rc alpine-2.26/pith/state.c alpine-2.26.fillpara/pith/state.c +*** alpine-2.26/pith/state.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fillpara/pith/state.c 2022-06-02 18:14:57.059136043 -0600 *************** -*** 235,240 **** ---- 235,242 ---- +*** 231,236 **** +--- 231,238 ---- if((*pps)->kw_colors) free_spec_colors(&(*pps)->kw_colors); @@ -3943,12 +3944,12 @@ diff -rc alpine-2.25/pith/state.c alpine-2.25.fillpara/pith/state.c if((*pps)->atmts){ int i; -diff -rc alpine-2.25/pith/state.h alpine-2.25.fillpara/pith/state.h -*** alpine-2.25/pith/state.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/state.h 2021-09-18 09:03:13.631040673 -0600 +diff -rc alpine-2.26/pith/state.h alpine-2.26.fillpara/pith/state.h +*** alpine-2.26/pith/state.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fillpara/pith/state.h 2022-06-02 18:14:57.087135974 -0600 *************** -*** 262,267 **** ---- 262,269 ---- +*** 264,269 **** +--- 264,271 ---- SPEC_COLOR_S *hdr_colors; /* list of configured colors for view */ SPEC_COLOR_S *index_token_colors; /* list of configured colors for index */ @@ -3957,11 +3958,11 @@ diff -rc alpine-2.25/pith/state.h alpine-2.25.fillpara/pith/state.h short init_context; struct { -diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c -*** alpine-2.25/pith/text.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fillpara/pith/text.c 2021-09-18 09:03:13.643040757 -0600 +diff -rc alpine-2.26/pith/text.c alpine-2.26.fillpara/pith/text.c +*** alpine-2.26/pith/text.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fillpara/pith/text.c 2022-06-02 18:14:57.091135965 -0600 *************** -*** 92,98 **** +*** 88,94 **** char *err, *charset; int filtcnt = 0, error_found = 0, column, wrapit; int is_in_sig = OUT_SIG_BLOCK; @@ -3969,7 +3970,7 @@ diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c int is_delsp_yes = 0; int filt_only_c0 = 0; char *parmval; ---- 92,98 ---- +--- 88,94 ---- char *err, *charset; int filtcnt = 0, error_found = 0, column, wrapit; int is_in_sig = OUT_SIG_BLOCK; @@ -3978,7 +3979,7 @@ diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c int filt_only_c0 = 0; char *parmval; *************** -*** 180,186 **** +*** 176,182 **** && pico_usingcolor() && VAR_SIGNATURE_FORE_COLOR && VAR_SIGNATURE_BACK_COLOR){ @@ -3986,7 +3987,7 @@ diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c filters[filtcnt++].data = gf_line_test_opt(color_signature, &is_in_sig); } ---- 180,186 ---- +--- 176,182 ---- && pico_usingcolor() && VAR_SIGNATURE_FORE_COLOR && VAR_SIGNATURE_BACK_COLOR){ @@ -3995,7 +3996,7 @@ diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c &is_in_sig); } *************** -*** 198,206 **** +*** 194,202 **** && pico_usingcolor() && VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR){ @@ -4005,7 +4006,7 @@ diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c } } else if(!strucmp(att->body->subtype, "richtext")){ ---- 198,206 ---- +--- 194,202 ---- && pico_usingcolor() && VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR){ @@ -4016,8 +4017,8 @@ diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c } else if(!strucmp(att->body->subtype, "richtext")){ *************** -*** 281,286 **** ---- 281,291 ---- +*** 277,282 **** +--- 277,287 ---- } } @@ -4030,7 +4031,7 @@ diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c * If the message is not flowed, we do the quote suppression before * the wrapping, because the wrapping does not preserve the quote *************** -*** 305,311 **** +*** 301,307 **** dq.handlesp = handlesp; dq.do_color = (!(flags & FM_NOCOLOR) && pico_usingcolor()); @@ -4038,7 +4039,7 @@ diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq); } if(ps_global->VAR_QUOTE_REPLACE_STRING ---- 310,316 ---- +--- 306,312 ---- dq.handlesp = handlesp; dq.do_color = (!(flags & FM_NOCOLOR) && pico_usingcolor()); @@ -4047,7 +4048,7 @@ diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c } if(ps_global->VAR_QUOTE_REPLACE_STRING *************** -*** 364,370 **** +*** 360,366 **** dq.handlesp = handlesp; dq.do_color = (!(flags & FM_NOCOLOR) && pico_usingcolor()); @@ -4055,7 +4056,7 @@ diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq); } ---- 369,375 ---- +--- 365,371 ---- dq.handlesp = handlesp; dq.do_color = (!(flags & FM_NOCOLOR) && pico_usingcolor()); @@ -4064,7 +4065,7 @@ diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c } *************** -*** 569,575 **** +*** 565,571 **** { DELQ_S *dq; char *lp; @@ -4072,7 +4073,7 @@ diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c size_t len = 0; dq = (DELQ_S *) local; ---- 574,580 ---- +--- 570,576 ---- { DELQ_S *dq; char *lp; @@ -4081,8 +4082,8 @@ diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c dq = (DELQ_S *) local; *************** -*** 589,594 **** ---- 594,601 ---- +*** 585,590 **** +--- 590,597 ---- for(i = dq->indent_length; i > 0 && !not_a_quote && *lp; i--) if(*lp++ != SPACE) not_a_quote++; @@ -4092,7 +4093,7 @@ diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c /* skip over leading tags */ while(!not_a_quote *************** -*** 628,640 **** +*** 624,636 **** } } @@ -4106,7 +4107,7 @@ diff -rc alpine-2.25/pith/text.c alpine-2.25.fillpara/pith/text.c not_a_quote++; if(not_a_quote){ ---- 635,646 ---- +--- 631,642 ---- } } diff --git a/chappa-fromheader.patch b/chappa-fromheader.patch index ff1d5c5..0375a28 100644 --- a/chappa-fromheader.patch +++ b/chappa-fromheader.patch @@ -1,8 +1,8 @@ -diff -rc alpine-2.25/alpine/send.c alpine-2.25.fromheader/alpine/send.c -*** alpine-2.25/alpine/send.c 2021-09-18 09:02:36.350783312 -0600 ---- alpine-2.25.fromheader/alpine/send.c 2021-09-18 09:03:16.987063842 -0600 +diff -rc alpine-2.26/alpine/send.c alpine-2.26.fromheader/alpine/send.c +*** alpine-2.26/alpine/send.c 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.fromheader/alpine/send.c 2022-06-02 18:14:58.723131963 -0600 *************** -*** 908,914 **** +*** 907,913 **** 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KS_NONE}, {"From : ", "From", h_composer_from, 10, 0, NULL, build_address, NULL, NULL, addr_book_compose, "To AddrBk", NULL, abook_nickname_complete, @@ -10,7 +10,7 @@ diff -rc alpine-2.25/alpine/send.c alpine-2.25.fromheader/alpine/send.c {"Reply-To: ", "Reply To", h_composer_reply_to, 10, 0, NULL, build_address, NULL, NULL, addr_book_compose, "To AddrBk", NULL, abook_nickname_complete, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, KS_TOADDRBOOK}, ---- 908,914 ---- +--- 907,913 ---- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KS_NONE}, {"From : ", "From", h_composer_from, 10, 0, NULL, build_address, NULL, NULL, addr_book_compose, "To AddrBk", NULL, abook_nickname_complete, @@ -19,8 +19,8 @@ diff -rc alpine-2.25/alpine/send.c alpine-2.25.fromheader/alpine/send.c build_address, NULL, NULL, addr_book_compose, "To AddrBk", NULL, abook_nickname_complete, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, KS_TOADDRBOOK}, *************** -*** 2372,2377 **** ---- 2372,2382 ---- +*** 2371,2376 **** +--- 2371,2381 ---- he->rich_header = 0; } } @@ -33,7 +33,7 @@ diff -rc alpine-2.25/alpine/send.c alpine-2.25.fromheader/alpine/send.c he_from = he; break; *************** -*** 3109,3115 **** +*** 3108,3114 **** if(outgoing->return_path) mail_free_address(&outgoing->return_path); @@ -41,7 +41,7 @@ diff -rc alpine-2.25/alpine/send.c alpine-2.25.fromheader/alpine/send.c /* * Don't ever believe the sender that is there. ---- 3114,3122 ---- +--- 3113,3121 ---- if(outgoing->return_path) mail_free_address(&outgoing->return_path); @@ -51,12 +51,12 @@ diff -rc alpine-2.25/alpine/send.c alpine-2.25.fromheader/alpine/send.c /* * Don't ever believe the sender that is there. -diff -rc alpine-2.25/pith/conf.c alpine-2.25.fromheader/pith/conf.c -*** alpine-2.25/pith/conf.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fromheader/pith/conf.c 2021-09-18 09:03:16.991063870 -0600 +diff -rc alpine-2.26/pith/conf.c alpine-2.26.fromheader/pith/conf.c +*** alpine-2.26/pith/conf.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fromheader/pith/conf.c 2022-06-02 18:14:58.727131952 -0600 *************** -*** 2989,2994 **** ---- 2989,2996 ---- +*** 2991,2996 **** +--- 2991,2998 ---- F_NO_FCC_ATTACH, h_config_no_fcc_attach, PREF_SEND, 0}, {"fcc-on-bounce", "Include Fcc When Bouncing Messages", F_FCC_ON_BOUNCE, h_config_fcc_on_bounce, PREF_SEND, 0}, @@ -65,12 +65,12 @@ diff -rc alpine-2.25/pith/conf.c alpine-2.25.fromheader/pith/conf.c {"mark-fcc-seen", NULL, F_MARK_FCC_SEEN, h_config_mark_fcc_seen, PREF_SEND, 0}, {"fcc-only-without-confirm", "Send to Fcc Only Without Confirming", -diff -rc alpine-2.25/pith/conftype.h alpine-2.25.fromheader/pith/conftype.h -*** alpine-2.25/pith/conftype.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fromheader/pith/conftype.h 2021-09-18 09:03:16.991063870 -0600 +diff -rc alpine-2.26/pith/conftype.h alpine-2.26.fromheader/pith/conftype.h +*** alpine-2.26/pith/conftype.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fromheader/pith/conftype.h 2022-06-02 18:15:00.011128806 -0600 *************** -*** 412,417 **** ---- 412,418 ---- +*** 414,419 **** +--- 414,420 ---- F_AUTO_REPLY_TO, F_VERBOSE_POST, F_FCC_ON_BOUNCE, @@ -78,12 +78,12 @@ diff -rc alpine-2.25/pith/conftype.h alpine-2.25.fromheader/pith/conftype.h F_SEND_WO_CONFIRM, F_USE_SENDER_NOT_X, F_BLANK_KEYMENU, -diff -rc alpine-2.25/pith/pine.hlp alpine-2.25.fromheader/pith/pine.hlp -*** alpine-2.25/pith/pine.hlp 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fromheader/pith/pine.hlp 2021-09-18 09:03:17.047064257 -0600 +diff -rc alpine-2.26/pith/pine.hlp alpine-2.26.fromheader/pith/pine.hlp +*** alpine-2.26/pith/pine.hlp 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fromheader/pith/pine.hlp 2022-06-02 18:15:00.063128678 -0600 *************** -*** 30313,30318 **** ---- 30313,30334 ---- +*** 30451,30456 **** +--- 30451,30472 ---- <End of help on this topic> @@ -106,11 +106,11 @@ diff -rc alpine-2.25/pith/pine.hlp alpine-2.25.fromheader/pith/pine.hlp ====== h_config_use_sender_not_x ===== -diff -rc alpine-2.25/pith/send.c alpine-2.25.fromheader/pith/send.c -*** alpine-2.25/pith/send.c 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fromheader/pith/send.c 2021-09-18 09:03:17.047064257 -0600 +diff -rc alpine-2.26/pith/send.c alpine-2.26.fromheader/pith/send.c +*** alpine-2.26/pith/send.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fromheader/pith/send.c 2022-06-02 18:15:00.063128678 -0600 *************** -*** 53,59 **** +*** 49,55 **** /* name::type::canedit::writehdr::localcopy::rcptto */ PINEFIELD pf_template[] = { {"X-Auth-Received", FreeText, 0, 1, 1, 0}, /* N_AUTHRCVD */ @@ -118,7 +118,7 @@ diff -rc alpine-2.25/pith/send.c alpine-2.25.fromheader/pith/send.c {"Reply-To", Address, 0, 1, 1, 0}, {TONAME, Address, 1, 1, 1, 1}, {CCNAME, Address, 1, 1, 1, 1}, ---- 53,59 ---- +--- 49,55 ---- /* name::type::canedit::writehdr::localcopy::rcptto */ PINEFIELD pf_template[] = { {"X-Auth-Received", FreeText, 0, 1, 1, 0}, /* N_AUTHRCVD */ @@ -127,7 +127,7 @@ diff -rc alpine-2.25/pith/send.c alpine-2.25.fromheader/pith/send.c {TONAME, Address, 1, 1, 1, 1}, {CCNAME, Address, 1, 1, 1, 1}, *************** -*** 1227,1233 **** +*** 1223,1229 **** } pf->type = pf_template[i].type; @@ -135,7 +135,7 @@ diff -rc alpine-2.25/pith/send.c alpine-2.25.fromheader/pith/send.c pf->rcptto = pf_template[i].rcptto; pf->writehdr = pf_template[i].writehdr; pf->localcopy = pf_template[i].localcopy; ---- 1227,1233 ---- +--- 1223,1229 ---- } pf->type = pf_template[i].type; @@ -143,9 +143,9 @@ diff -rc alpine-2.25/pith/send.c alpine-2.25.fromheader/pith/send.c pf->rcptto = pf_template[i].rcptto; pf->writehdr = pf_template[i].writehdr; pf->localcopy = pf_template[i].localcopy; -diff -rc alpine-2.25/pith/send.h alpine-2.25.fromheader/pith/send.h -*** alpine-2.25/pith/send.h 2021-09-18 09:02:36.390783589 -0600 ---- alpine-2.25.fromheader/pith/send.h 2021-09-18 09:03:17.087064532 -0600 +diff -rc alpine-2.26/pith/send.h alpine-2.26.fromheader/pith/send.h +*** alpine-2.26/pith/send.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.fromheader/pith/send.h 2022-06-02 18:15:00.071128658 -0600 *************** *** 159,164 **** --- 159,166 ---- diff --git a/chappa-insertpat.patch b/chappa-insertpat.patch index 6d2afa0..e647c69 100644 --- a/chappa-insertpat.patch +++ b/chappa-insertpat.patch @@ -1,9 +1,9 @@ -diff -rc alpine-2.25/pico/display.c alpine-2.25.insertpat/pico/display.c -*** alpine-2.25/pico/display.c 2021-09-18 09:02:36.386783561 -0600 ---- alpine-2.25.insertpat/pico/display.c 2021-09-18 09:03:18.847076682 -0600 +diff -rc alpine-2.26/pico/display.c alpine-2.26.insertpat/pico/display.c +*** alpine-2.26/pico/display.c 2022-06-02 18:14:00.487274758 -0600 +--- alpine-2.26.insertpat/pico/display.c 2022-06-02 18:15:03.495120264 -0600 *************** -*** 2200,2205 **** ---- 2200,2217 ---- +*** 2196,2201 **** +--- 2196,2213 ---- continue; @@ -22,12 +22,12 @@ diff -rc alpine-2.25/pico/display.c alpine-2.25.insertpat/pico/display.c case (CTRL|'G') : /* CTRL-G help */ if(term.t_mrow == 0 && km_popped == 0){ movecursor(term.t_nrow-2, 0); -diff -rc alpine-2.25/pico/search.c alpine-2.25.insertpat/pico/search.c -*** alpine-2.25/pico/search.c 2021-09-18 09:02:36.386783561 -0600 ---- alpine-2.25.insertpat/pico/search.c 2021-09-18 09:03:18.847076682 -0600 +diff -rc alpine-2.26/pico/search.c alpine-2.26.insertpat/pico/search.c +*** alpine-2.26/pico/search.c 2022-06-02 18:14:00.487274758 -0600 +--- alpine-2.26.insertpat/pico/search.c 2022-06-02 18:15:03.499120253 -0600 *************** -*** 122,127 **** ---- 122,131 ---- +*** 118,123 **** +--- 118,127 ---- N_("~ Hitting only ~R~e~t~u~r~n or at the prompt will cause the"), N_(" search to be made with the default value."), " ", diff --git a/chappa-maildir.patch b/chappa-maildir.patch index 9ebbd1b..8ea8375 100644 --- a/chappa-maildir.patch +++ b/chappa-maildir.patch @@ -1,3714 +1,3952 @@ ---- - README.maildir | 149 ++ - alpine/alpine.c | 5 - alpine/confscroll.c | 6 - imap/src/c-client/mail.c | 11 - imap/src/c-client/mail.h | 4 - imap/src/osdep/unix/Makefile | 7 - imap/src/osdep/unix/dummy.c | 48 - imap/src/osdep/unix/maildir.c | 2671 ++++++++++++++++++++++++++++++++++++++++++ - imap/src/osdep/unix/maildir.h | 226 +++ - imap/src/osdep/unix/os_cyg.h | 1 - pith/conf.c | 30 - pith/conf.h | 4 - pith/conftype.h | 6 - pith/init.c | 3 - pith/pattern.c | 30 - pith/pine.hlp | 139 ++ - pith/send.c | 10 - 17 files changed, 3334 insertions(+), 16 deletions(-) - -Index: alpine-2.25.1/README.maildir -=================================================================== ---- /dev/null -+++ alpine-2.25.1/README.maildir -@@ -0,0 +1,149 @@ -+--------------------------------------- -+ -+Maildir Driver for Alpine 2.0 -+By Eduardo Chappa -+ -+ -+--------------------------------------- -+1. General Information About This Patch -+--------------------------------------- -+ -+This patch adds support for the maildir format to Alpine. We take the -+approach that this patch is one more driver among the number of formats -+supported by Alpine (more generally c-client). This approach differs from -+older versions of similar patches, in that once a maildir patch was -+applied, it was assumed that all your folders would be created in the -+maildir format. -+ -+This patch does not assume that maildir is a preferred format, instead -+puts maildir in equal footing with other formats (mbox, mbx, mix, etc), -+and so a maildir folder in the mail/ collection is treated in the same way -+as any other folder in any other format. In other words, just by reading -+the name of a folder, or opening it, or doing any operation with it, you -+can not know in which format the folder is. -+ -+This implies that if you want to add a folder in the maildir format to the -+mail/ collection, then you must add by pressing "A" in the folder list -+collection and enter "#driver.md/mail/name_maildir_folder". -+ -+If you only want to use maildir, however, you can do so too. In this case, -+you must create a maildir collection. In that collection, only maildir -+folders will be listed. If there is any folder in any other format, that -+folder will be ignored. In another words, any folder listed there is in -+maildir format and can be accessed through that collection, conversely, -+any folder not listed there is not in maildir format and there is no way -+to access it using this collection. -+ -+In order to create a maildir collection, you could press M S L, and "A" to -+add a collection. Fill in the required fields as follows: -+ -+Nickname : Anything -+Server : -+Path : #md/relative/path/to/maildir/collection/ -+View : -+ -+For example, if "path" is set to "#md/mail/", then Alpine will look for your -+maildir folders that are in ~/mail/. -+ -+The code in this patch is mostly based in code for the unix driver plus -+some combinations of the mh, mbx and nntp drivers for the c-client -+library. Those drivers were designed by Mark Crispin, and bugs in this -+code are not his bugs, but my own. -+ -+ I got all the specification for this patch from -+http://cr.yp.to/proto/maildir.html. If you know of a place with a better -+specification for maildir format please let me know. The method this patch -+uses to create a unique filename for a message is one of the "old -+fashioned" methods. I realize that this is old fashioned, but it is -+portable, and portability is the main reason why I decided to use an old -+fashioned method (most methods are not portable. See the word -+"Unfortunately" in that document). -+ -+-------------- -+2. Other Goals -+-------------- -+ -+ It is intended that this code will work well with any application -+written using the c-client library. Of paramount importance is to make the -+associated imap server work well when the server accesses a folder in -+Maildir format. The program mailutil should also work flawlessly with this -+implemetation of the driver. -+ -+ It is intended that this driver be fast and stable. We intend not to -+patch Alpine to make this driver do its work, unless such patching is for -+fixing bugs in Alpine or to pass parameters to the driver. -+ -+------------------------------------------------------------------------ -+3. What are the known bugs of this implementation of the Maildir driver? -+------------------------------------------------------------------------ -+ -+ I don't know any at this time. There have been bugs before, though, but -+I try to fix bugs as soon as they are reported. -+ -+---------- -+4. On UIDs -+---------- -+ -+ This patch keeps uids in the name of the file that contains the message, -+by adding a ",u=" string to the file name to save the uid of a message. A -+file is kept between sessions to save information on the last uid assigned -+and its time of validity. Only one session with writing access can write -+uids, all others must wait for the other session to assign them. The -+session assigning uids creates a ".uidtemp" file which other sessions must -+not disturb. -+ -+ Uid support appeared in Alpine 1.00 (snapshot 925), and is experimental, -+please report any problems. -+ -+---------------------------------------------- -+5. Configuring Alpine and Setting up a Maildir -+---------------------------------------------- -+ -+Once this approach was chosen, it implied the following: -+ -+ * This patch assumes that your INBOX is located at "$HOME/Maildir". -+ This is a directory which should have three subdirectories "cur", -+ "tmp" and "new". Mail is delivered to 'new' and read from 'cur'. I -+ have added a configuration option "maildir-location" which can be -+ used to tell Alpine where your Maildir inbox is, in case your system -+ does not use the above directory (e.g. your system may use -+ "~/.maildir"). In this case define that variable to be the name of -+ the directory where your e-mail is being delivered (e.g. -+ ".maildir"). -+ -+ * If you want to use the above configuration as your inbox, you must -+ define your inbox-path as "#md/inbox" (no quotes). You can define -+ the inbox-path like above even if you have changed the -+ maildir-location variable. That's the whole point of that variable. -+ -+------------------------------------------- -+6. What about Courier/Dovecot file systems? -+------------------------------------------- -+ -+In a courier file system all folders are subfolders of a root folder -+called INBOX. Normally INBOX is located at ~/Maildir and subfolders are -+"dot" directories in ~/Maildir. For example ~/Maildir/.Trash is a -+subfolder of INBOX and is accessed with the nickname "INBOX.Trash". -+ -+You can not access folders in this way unless you preceed them with the -+string "#mc/". The purpose of the string "#mc/" is to warn Alpine that a -+collection in the Courier format is going to be accessed. Therefore, you -+can SELECT a folder like "#mc/INBOX.Trash", but not "INBOX.Trash" -+ -+You can access a collection through a server, but if you want to access a -+collection of folders created using the Courier server, you MUST edit your -+".pinerc" file and enter the definition of the collection as follows: -+ -+folder-collections="Anything you want" #mc/INBOX.[] -+ -+You can replace the string "#mc/INBOX." by something different, for example -+"#mc/Courier/." will make Alpine search for your collection in ~/Courier. -+ -+You can not add this setting directly into Alpine because Alpine fails to -+accept this value from its input, but it takes it correctly when it is -+added through the ".pinerc" file. -+ -+You can access your inbox as "#mc/INBOX" or "#md/INBOX". Both definitions -+point to the same place. -+ -+Last Updated May 28, 2011 -Index: alpine-2.25.1/alpine/alpine.c -=================================================================== ---- alpine-2.25.1.orig/alpine/alpine.c -+++ alpine-2.25.1/alpine/alpine.c -@@ -593,6 +593,11 @@ main(int argc, char **argv) - if(F_ON(F_MAILDROPS_PRESERVE_STATE, ps_global)) - mail_parameters(NULL, SET_SNARFPRESERVE, (void *) TRUE); - -+#ifndef _WINDOWS -+ rv = F_ON(F_COURIER_FOLDER_LIST, ps_global) ? 1 : 0; -+ mail_parameters(NULL,SET_COURIERSTYLE, (void *) &rv); -+#endif -+ - rvl = 0L; - if(pine_state->VAR_NNTPRANGE){ - if(!SVAR_NNTPRANGE(pine_state, rvl, tmp_20k_buf, SIZEOF_20KBUF)) -Index: alpine-2.25.1/alpine/confscroll.c -=================================================================== ---- alpine-2.25.1.orig/alpine/confscroll.c -+++ alpine-2.25.1/alpine/confscroll.c -@@ -5602,6 +5602,12 @@ fix_side_effects(struct pine *ps, struct - (void *)var->current_val.p); - } - #endif -+#ifndef _WINDOWS -+ else if(var == &ps->vars[V_MAILDIR_LOCATION]){ -+ if(var->current_val.p && var->current_val.p[0]) -+ mail_parameters(NULL, SET_MDINBOXPATH, (void *)var->current_val.p); -+ } -+#endif - else if(revert && standard_radio_var(ps, var)){ - - cur_rule_value(var, TRUE, FALSE); -Index: alpine-2.25.1/imap/src/c-client/mail.c -=================================================================== ---- alpine-2.25.1.orig/imap/src/c-client/mail.c -+++ alpine-2.25.1/imap/src/c-client/mail.c -@@ -1071,7 +1071,7 @@ long mail_create (MAILSTREAM *stream,cha - MAILSTREAM *ts; - char *s,*t,tmp[MAILTMPLEN]; - size_t i; -- DRIVER *d; -+ DRIVER *d, *md; - /* never allow names with newlines */ - if ((s = strpbrk (mailbox,"\015\012")) != NULL) { - MM_LOG ("Can't create mailbox with such a name",ERROR); -@@ -1095,6 +1095,8 @@ long mail_create (MAILSTREAM *stream,cha - return NIL; - } - -+ /* Hack, we should do this better, but it works */ -+ for (md = maildrivers; md && strcmp (md->name, "md"); md = md->next); - /* see if special driver hack */ - if ((mailbox[0] == '#') && ((mailbox[1] == 'd') || (mailbox[1] == 'D')) && - ((mailbox[2] == 'r') || (mailbox[2] == 'R')) && -@@ -1125,6 +1127,13 @@ long mail_create (MAILSTREAM *stream,cha - (((*mailbox == '{') || (*mailbox == '#')) && - (stream = mail_open (NIL,mailbox,OP_PROTOTYPE | OP_SILENT)))) - d = stream->dtb; -+ else if(mailbox[0] == '#' -+ && (mailbox[1] == 'm' || mailbox[1] == 'M') -+ && (mailbox[2] == 'd' || mailbox[2] == 'D' -+ || mailbox[2] == 'c' || mailbox[2] == 'C') -+ && mailbox[3] == '/' -+ && mailbox[4] != '\0') -+ return (*md->create)(stream, mailbox); - else if ((*mailbox != '{') && (ts = default_proto (NIL))) d = ts->dtb; - else { /* failed utterly */ - sprintf (tmp,"Can't create mailbox %.80s: indeterminate format",mailbox); -Index: alpine-2.25.1/imap/src/c-client/mail.h -=================================================================== ---- alpine-2.25.1.orig/imap/src/c-client/mail.h -+++ alpine-2.25.1/imap/src/c-client/mail.h -@@ -389,6 +389,10 @@ - #define SET_SCANCONTENTS (long) 573 - #define GET_MHALLOWINBOX (long) 574 - #define SET_MHALLOWINBOX (long) 575 -+#define GET_COURIERSTYLE (long) 576 -+#define SET_COURIERSTYLE (long) 577 -+#define SET_MDINBOXPATH (long) 578 -+#define GET_MDINBOXPATH (long) 579 - - /* Driver flags */ - -Index: alpine-2.25.1/imap/src/osdep/unix/Makefile -=================================================================== ---- alpine-2.25.1.orig/imap/src/osdep/unix/Makefile -+++ alpine-2.25.1/imap/src/osdep/unix/Makefile -@@ -146,7 +146,7 @@ DEFAULTAUTHENTICATORS=ext md5 pla log be - # However, mh needs to be before any sysinbox formats (such as mmdf or unix) - # since otherwise INBOX won't work correctly when mh_allow_inbox is set. - # --DEFAULTDRIVERS=imap nntp pop3 mix mx mbx tenex mtx mh mmdf unix news phile -+DEFAULTDRIVERS=maildir courier imap nntp pop3 mix mx mbx tenex mtx mh mmdf unix news phile - CHUNKSIZE=65536 - - # Normally no need to change any of these -@@ -155,7 +155,7 @@ ARCHIVE=c-client.a - BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o utf8aux.o siglocal.o \ - dummy.o pseudo.o netmsg.o flstring.o fdstring.o \ - rfc822.o nntp.o smtp.o imap4r1.o http.o json.o pop3.o \ -- unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o mix.o sha.o -+ unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o mix.o sha.o maildir.o - CFLAGS=-g - - CAT=cat -@@ -292,7 +292,7 @@ cvx: # Convex - - cyg: # Cygwin - note that most local file drivers don't work!! - $(BUILD) `$(CAT) SPECIALS` OS=$@ \ -- DEFAULTDRIVERS="imap nntp pop3 mbx unix phile" \ -+ DEFAULTDRIVERS="imap nntp pop3 mbx unix maildir phile" \ - SIGTYPE=psx CHECKPW=cyg LOGINPW=cyg CRXTYPE=std \ - SPOOLDIR=/var \ - ACTIVEFILE=/usr/local/news/lib/active \ -@@ -922,6 +922,7 @@ utf8aux.o: mail.h misc.h osdep.h utf8.h - json.o: mail.h misc.h osdep.h utf8.h json.h - http.o: mail.h misc.h osdep.h utf8.h http.h json.h - sha.o: mail.h misc.h osdep.h sha.h sha-private.h hash.h hmac.c sha1.c sha224-256.c sha384-512.c usha.c -+maildir.o: mail.h misc.h osdep.h maildir.h dummy.h - - # OS-dependent - -Index: alpine-2.25.1/imap/src/osdep/unix/dummy.c -=================================================================== ---- alpine-2.25.1.orig/imap/src/osdep/unix/dummy.c -+++ alpine-2.25.1/imap/src/osdep/unix/dummy.c -@@ -104,13 +104,19 @@ MAILSTREAM dummyproto = {&dummydriver}; - * Accepts: mailbox name - * Returns: our driver if name is valid, NIL otherwise - */ -- -+char * maildir_remove_root(char *); - DRIVER *dummy_valid (char *name) - { -- char *s,tmp[MAILTMPLEN]; -+ char *s,tmp[MAILTMPLEN], *rname; - struct stat sbuf; -+ -+ if(strlen(name) > MAILTMPLEN) -+ name[MAILTMPLEN] = '\0'; -+ -+ strcpy(tmp, name); -+ rname = maildir_remove_root(tmp); - /* must be valid local mailbox */ -- if (name && *name && (*name != '{') && (s = mailboxfile (tmp,name))) { -+ if (rname && *rname && (*rname != '{') && (s = mailboxfile (tmp,rname))) { - /* indeterminate clearbox INBOX */ - if (!*s) return &dummydriver; - else if (!stat (s,&sbuf)) switch (sbuf.st_mode & S_IFMT) { -@@ -119,8 +125,9 @@ DRIVER *dummy_valid (char *name) - return &dummydriver; - } - /* blackbox INBOX does not exist yet */ -- else if (!compare_cstring (name,"INBOX")) return &dummydriver; -+ else if (!compare_cstring (rname,"INBOX")) return &dummydriver; - } -+ if(rname) fs_give((void **)&rname); - return NIL; - } - -@@ -453,6 +460,8 @@ long dummy_create (MAILSTREAM *stream,ch - { - char *s,tmp[MAILTMPLEN]; - long ret = NIL; -+ if(!strncmp(mailbox,"#md/",4) || !strncmp(mailbox,"#mc/", 4)) -+ return maildir_create(stream, mailbox); - /* validate name */ - if (!(compare_cstring (mailbox,"INBOX") && (s = dummy_file (tmp,mailbox)))) { - sprintf (tmp,"Can't create %.80s: invalid name",mailbox); -@@ -518,6 +527,14 @@ long dummy_delete (MAILSTREAM *stream,ch - { - struct stat sbuf; - char *s,tmp[MAILTMPLEN]; -+ if (!strncmp(mailbox,"#md/",4) || !strncmp(mailbox,"#mc/", 4) -+ || is_valid_maildir(&mailbox)){ -+ char tmp[MAILTMPLEN] = {'\0'}; -+ strcpy(tmp, mailbox); -+ if(tmp[strlen(tmp) - 1] != '/') -+ tmp[strlen(tmp)] = '/'; -+ return maildir_delete(stream, tmp); -+ } - if (!(s = dummy_file (tmp,mailbox))) { - sprintf (tmp,"Can't delete - invalid name: %.80s",mailbox); - MM_LOG (tmp,ERROR); -@@ -543,12 +560,23 @@ long dummy_delete (MAILSTREAM *stream,ch - long dummy_rename (MAILSTREAM *stream,char *old,char *newname) - { - struct stat sbuf; -- char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN]; -+ char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN], *rold, *rnewname; -+ -+ if(strlen(old) > MAILTMPLEN) -+ old[MAILTMPLEN] = '\0'; -+ -+ if(strlen(newname) > MAILTMPLEN) -+ newname[MAILTMPLEN] = '\0'; -+ -+ strcpy(tmp, old); -+ rold = maildir_remove_root(tmp); -+ strcpy(tmp, newname); -+ rnewname = maildir_remove_root(tmp); - /* no trailing / allowed */ -- if (!dummy_file (oldname,old) || !(s = dummy_file (mbx,newname)) || -+ if (!dummy_file (oldname,rold) || !(s = dummy_file (mbx,rnewname)) || - stat (oldname,&sbuf) || ((s = strrchr (s,'/')) && !s[1] && - ((sbuf.st_mode & S_IFMT) != S_IFDIR))) { -- sprintf (mbx,"Can't rename %.80s to %.80s: invalid name",old,newname); -+ sprintf (mbx,"Can't rename %.80s to %.80s: invalid name",rold,rnewname); - MM_LOG (mbx,ERROR); - return NIL; - } -@@ -564,14 +592,16 @@ long dummy_rename (MAILSTREAM *stream,ch - } - } - /* rename of non-ex INBOX creates dest */ -- if (!compare_cstring (old,"INBOX") && stat (oldname,&sbuf)) -+ if (!compare_cstring (rold,"INBOX") && stat (oldname,&sbuf)) - return dummy_create (NIL,mbx); - if (rename (oldname,mbx)) { -- sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %.80s",old,newname, -+ sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %.80s",rold,rnewname, - strerror (errno)); - MM_LOG (tmp,ERROR); - return NIL; - } -+ if(rold) fs_give((void **)&rold); -+ if(rnewname) fs_give((void **)&rnewname); - return T; /* return success */ - } - -Index: alpine-2.25.1/imap/src/osdep/unix/maildir.c -=================================================================== ---- /dev/null -+++ alpine-2.25.1/imap/src/osdep/unix/maildir.c -@@ -0,0 +1,2671 @@ -+/* -+ * Maildir driver for Alpine 2.20 -+ * -+ * Written by Eduardo Chappa -+ * Last Update: June 10, 2014 -+ * -+ */ -+ -+#include -+#include -+#include -+extern int errno; /* just in case */ -+#include "mail.h" -+#include -+#include -+#include -+#include "osdep.h" -+#include "rfc822.h" -+#include "fdstring.h" -+#include "misc.h" -+#include "dummy.h" -+#include "maildir.h" -+ -+/* Driver dispatch used by MAIL */ -+DRIVER maildirdriver = { -+ "md", /* driver name, yes it's md, not maildir */ -+ DR_MAIL|DR_LOCAL|DR_NAMESPACE|DR_DIRFMT, /* driver flags */ -+ (DRIVER *) NIL, /* next driver */ -+ maildir_valid, /* mailbox is valid for us */ -+ maildir_parameters, /* manipulate parameters */ -+ NIL, /* scan mailboxes */ -+ maildir_list, /* find mailboxes */ -+ maildir_lsub, /* find subscribed mailboxes */ -+ maildir_sub, /* subscribe to mailbox */ -+ maildir_unsub, /* unsubscribe from mailbox */ -+ maildir_create, /* create mailbox */ -+ maildir_delete, /* delete mailbox */ -+ maildir_rename, /* rename mailbox */ -+ mail_status_default, /* status of mailbox */ -+ maildir_open, /* open mailbox */ -+ maildir_close, /* close mailbox */ -+ maildir_fast, /* fetch message "fast" attributes */ -+ NIL, /* fetch message flags */ -+ NIL, /* fetch overview */ -+ NIL, /* fetch message structure */ -+ maildir_header, /* fetch message header */ -+ maildir_text, /* fetch message body */ -+ NIL, /* fetch partial message text */ -+ NIL, /* unique identifier */ -+ NIL, /* message number */ -+ NIL, /* modify flags */ -+ maildir_flagmsg, /* per-message modify flags */ -+ NIL, /* search for message based on criteria */ -+ NIL, /* sort messages */ -+ NIL, /* thread messages */ -+ maildir_ping, /* ping mailbox to see if still alive */ -+ maildir_check, /* check for new messages */ -+ maildir_expunge, /* expunge deleted messages */ -+ maildir_copy, /* copy messages to another mailbox */ -+ maildir_append, /* append string message to mailbox */ -+ NIL /* garbage collect stream */ -+}; -+ -+ -+DRIVER courierdriver = { -+ "mc", /* Why a separate driver? So that createproto will work */ -+ DR_MAIL|DR_LOCAL|DR_NAMESPACE|DR_DIRFMT, /* driver flags */ -+ (DRIVER *) NIL, /* next driver */ -+ maildir_valid, /* mailbox is valid for us */ -+ maildir_parameters, /* manipulate parameters */ -+ NIL, /* scan mailboxes */ -+ courier_list, /* find mailboxes */ -+ maildir_lsub, /* find subscribed mailboxes */ -+ maildir_sub, /* subscribe to mailbox */ -+ maildir_unsub, /* unsubscribe from mailbox */ -+ maildir_create, /* create mailbox */ -+ maildir_delete, /* delete mailbox */ -+ maildir_rename, /* rename mailbox */ -+ mail_status_default, /* status of mailbox */ -+ maildir_open, /* open mailbox */ -+ maildir_close, /* close mailbox */ -+ maildir_fast, /* fetch message "fast" attributes */ -+ NIL, /* fetch message flags */ -+ NIL, /* fetch overview */ -+ NIL, /* fetch message structure */ -+ maildir_header, /* fetch message header */ -+ maildir_text, /* fetch message body */ -+ NIL, /* fetch partial message text */ -+ NIL, /* unique identifier */ -+ NIL, /* message number */ -+ NIL, /* modify flags */ -+ maildir_flagmsg, /* per-message modify flags */ -+ NIL, /* search for message based on criteria */ -+ NIL, /* sort messages */ -+ NIL, /* thread messages */ -+ maildir_ping, /* ping mailbox to see if still alive */ -+ maildir_check, /* check for new messages */ -+ maildir_expunge, /* expunge deleted messages */ -+ maildir_copy, /* copy messages to another mailbox */ -+ maildir_append, /* append string message to mailbox */ -+ NIL /* garbage collect stream */ -+}; -+ -+MAILSTREAM maildirproto = {&maildirdriver}; /* prototype stream */ -+MAILSTREAM courierproto = {&courierdriver}; /* prototype stream */ -+ -+long maildir_dirfmttest (char *name) -+{ -+ int i; -+ for (i = 0; mdstruct[i] && strcmp(name, mdstruct[i]); i++); -+ return (i < EndDir) || !strcmp(name, MDDIR) -+ || !strncmp(name, MDUIDLAST, strlen(MDUIDLAST)) -+ || !strncmp(name, MDUIDTEMP, strlen(MDUIDTEMP)) ? LONGT : NIL; -+} -+ -+void -+md_domain_name(void) -+{ -+ int i, j; -+ -+ strcpy(mdlocaldomain, mylocalhost ()); -+ for (i = 0; mdlocaldomain[i] != '\0' ;) -+ if(mdlocaldomain[i] == '/' || mdlocaldomain[i] == ':'){ -+ for(j = strlen(mdlocaldomain); j >= i; j--) -+ mdlocaldomain[j+4] = mdlocaldomain[j]; -+ mdlocaldomain[i++] = '\\'; -+ mdlocaldomain[i++] = '0'; -+ if(mdlocaldomain[i] == '/'){ -+ mdlocaldomain[i++] = '5'; -+ mdlocaldomain[i++] = '7'; -+ } else { -+ mdlocaldomain[i++] = '7'; -+ mdlocaldomain[i++] = '2'; -+ } -+ } -+ else -+ i++; -+} -+ -+char * -+myrootdir(char *name) -+{ -+return myhomedir(); -+} -+ -+char * -+mdirpath(void) -+{ -+ char *path = maildir_parameters(GET_MDINBOXPATH, NIL); -+ return path ? (path[0] ? path : ".") : "Maildir"; -+} -+ -+/* remove the "#md/" or "#mc/" part from a folder name -+ * memory freed by caller -+ */ -+char * -+maildir_remove_root (char *name) -+{ -+ int courier = IS_COURIER(name), offset; -+ char realname[MAILTMPLEN]; -+ -+ offset = maildir_valid_name(name) ? (name[3] == '/' ? 4 : 3) : 0; -+ if(courier) -+ courier_realname(name+offset, realname); -+ else -+ strcpy(realname, name+offset); -+ return cpystr(realname); -+} -+ -+ -+/* Check validity of the name, we accept: -+ * a) #md/directory/folder -+ * b) #md/inbox -+ * A few considerations: We can only accept as valid -+ * a) names that start with #md/ and the directory exists or -+ * b) names that do not start with #md/ but are maildir directories (have -+ * the /cur, /tmp and /new structure) -+ */ -+int maildir_valid_name (char *name) -+{ -+ char tmpname[MAILTMPLEN] = {'\0'}; -+ -+ if (mdfpath) -+ fs_give((void **)&mdfpath); -+ if (name && (name[0] != '#')) -+ snprintf(tmpname, sizeof(tmpname), "%s%s",MDPREFIX(CCLIENT), name); -+ mdfpath = cpystr(tmpname[0] ? tmpname : name); -+ -+ return IS_CCLIENT(name) || IS_COURIER(name); -+} -+ -+/* Check if the directory whose path is given by name is a valid maildir -+ * directory (contains /cur, /tmp and /new) -+ */ -+int maildir_valid_dir (char *name) -+{ -+ int len; -+ DirNamesType i; -+ struct stat sbuf; -+ char tmp[MAILTMPLEN]; -+ -+ if(name[strlen(name) - 1] == '/') -+ name[strlen(name) - 1] = '\0'; -+ len = strlen(name); -+ for (i = Cur; i != EndDir; i++){ -+ MDFLD(tmp, name, i); -+ if (stat(tmp, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode)) -+ break; -+ } -+ name[len] = '\0'; -+ return (i == EndDir) ? T : NIL; -+} -+ -+void courier_realname(char *name, char *realname) -+{ -+ int i,j; -+ -+ if(!name) -+ return; -+ -+ for (i = 0, j = 0; i < MAILTMPLEN && j < strlen(name); j++, i++){ -+ realname[i] = name[j]; -+ if(name[j] == '/' && name[j+1] != '.' && name[j+1] != '%' -+ && name[j+1] != '*') -+ realname[++i] = '.'; -+ } -+ if(realname[i-1] == '.') -+ i--; -+ realname[i] = '\0'; -+} -+ -+ -+/* given a maildir folder, return its path. Memory freed by caller. Directory -+ * does not contain the trailing slash "/". On error NULL is returned. -+ */ -+int maildir_file_path (char *name, char *tmp, size_t sizeoftmp) -+{ -+ char *maildirpath = mdirpath(), *rname; -+ int courier = IS_COURIER(name); -+ -+ /* There are several ways in which the path can come, so we will handle -+ them here. First we deal with #mc/ or #md/ prefix by removing the -+ prefix, if any */ -+ -+ if(strlen(name) >= MAILTMPLEN) -+ name[MAILTMPLEN] = '\0'; -+ strcpy(tmp, name); -+ rname = maildir_remove_root(tmp); -+ tmp[0] = '\0'; /* just in case something fails */ -+ -+ if (strlen(myrootdir(rname)) + -+ max(strlen(rname), strlen(maildirpath)) > sizeoftmp){ -+ errno = ENAMETOOLONG; -+ snprintf(tmp, sizeoftmp, "Error opening \"%s\": %s", rname, strerror (errno)); -+ mm_log(tmp,ERROR); -+ if(rname) fs_give((void **)&rname); -+ return NIL; -+ } -+ -+ /* There are two ways in which the name can come here, either as a -+ full path or not. If it is not a full path it can come in two ways, -+ either as a file system path (Maildir/.Drafts) or as a maildir path -+ (INBOX.Drafts) -+ */ -+ -+ if(*rname == '/'){ /* full path */ -+ strncpy(tmp, rname, sizeoftmp); /* do nothing */ -+ tmp[sizeoftmp-1] = '\0'; -+ } -+ else -+ snprintf (tmp, sizeoftmp, "%s/%s%s%s", myrootdir (rname), -+ strncmp (ucase (strcpy (tmp, rname)), "INBOX", 5) -+ ? rname : maildirpath, -+ strncmp (ucase (strcpy (tmp, rname)), "INBOX", 5) -+ ? "" : (courier ? "/" : ""), -+ strncmp (ucase (strcpy (tmp, rname)), "INBOX", 5) -+ ? "" : (*(rname+5) == MDSEPARATOR(courier) ? rname+5 : "")); -+ if(rname) fs_give((void **)&rname); -+ return tmp[0] ? T : NIL; -+} -+ -+/* This function is given a full path for a mailbox and returns -+ * if it is a valid maildir transformed to canonical notation -+ */ -+int -+is_valid_maildir (char **name) -+{ -+ if (!strncmp(*name, myrootdir (*name), strlen(myrootdir(*name)))){ -+ (*name) += strlen(myrootdir(*name)); -+ if (**name == '/') (*name)++; -+ } -+ return maildir_valid(*name) ? T : NIL; -+} -+ -+/* Check validity of mailbox. This routine does not send errors to log, other -+ * routines calling this one may do so, though -+ */ -+ -+DRIVER *maildir_valid (char *name) -+{ -+ char tmpname[MAILTMPLEN]; -+ -+ maildir_file_path(name, tmpname, sizeof(tmpname)); -+ -+ return maildir_valid_dir(tmpname) -+ ? (IS_COURIER(name) ? &courierdriver : &maildirdriver) : NIL; -+} -+ -+void maildir_fast (MAILSTREAM *stream,char *sequence,long flags) -+{ -+ unsigned long i; -+ MESSAGECACHE *elt; -+ /* get sequence */ -+ if (stream && LOCAL && ((flags & FT_UID) ? -+ mail_uid_sequence (stream,sequence) : -+ mail_sequence (stream,sequence))) -+ for (i = 1L; i <= stream->nmsgs; i++) { -+ if ((elt = mail_elt (stream,i))->sequence && (elt->valid = T) && -+ !(elt->day && elt->rfc822_size)) { -+ ENVELOPE **env = NIL; -+ ENVELOPE *e = NIL; -+ if (!stream->scache) env = &elt->private.msg.env; -+ else if (stream->msgno == i) env = &stream->env; -+ else env = &e; -+ if (!*env || !elt->rfc822_size) { -+ STRING bs; -+ unsigned long hs; -+ char *ht = (*stream->dtb->header) (stream,i,&hs,NIL); -+ -+ if (!*env) rfc822_parse_msg (env,NIL,ht,hs,NIL,BADHOST, -+ stream->dtb->flags); -+ if (!elt->rfc822_size) { -+ (*stream->dtb->text) (stream,i,&bs,FT_PEEK); -+ elt->rfc822_size = hs + SIZE (&bs) - GETPOS (&bs); -+ } -+ } -+ -+ if (!elt->day && *env && (*env)->date) -+ mail_parse_date (elt,(*env)->date); -+ -+ if (!elt->day) elt->day = elt->month = 1; -+ mail_free_envelope (&e); -+ } -+ } -+} -+ -+int -+maildir_eliminate_duplicate (char *name, struct direct ***flist, unsigned long *nfiles) -+{ -+ int i, j, k, error = 0, scanr; -+ char new[MAILTMPLEN], old[MAILTMPLEN], tmp[MAILTMPLEN], *str; -+ struct direct **names = NIL; -+ -+ if((scanr = maildir_doscandir(name, &names, CCLIENT)) < 0) -+ return -1; -+ -+ if(nfiles) *nfiles = scanr; -+ for(i = 0, j = 1, k = 0; j < scanr; i++, j++){ -+ if(k) -+ names[i] = names[i+k]; -+ if(same_maildir_file(names[i]->d_name, names[j]->d_name)){ -+ int d, f, r, s; -+ maildir_getflag(names[i]->d_name, &d, &f, &r, &s, NIL); -+ snprintf(old, sizeof(old), "%s/%s", name, names[i]->d_name); -+ snprintf(new, sizeof(new), "%s/.%s", name, names[i]->d_name); -+ if(rename(old, new) < 0 && errno != EEXIST) -+ error++; -+ if(!error){ -+ for(; j < scanr -+ && same_maildir_file(names[i]->d_name, names[j]->d_name) -+ ; j++, k++){ -+ maildir_getflag(names[j]->d_name, (d ? NIL : &d), -+ (f ? NIL : &f), (r ? NIL : &r), (s ? NIL : &s), NIL); -+ snprintf(tmp, sizeof(tmp), "%s/%s", name, names[j]->d_name); -+ if(unlink(tmp) < 0){ /* Hmmm... a problem, let's see */ -+ struct stat sbuf; -+ if (stat(tmp, &sbuf) == 0 && (sbuf.st_mode & S_IFMT) == S_IFREG) -+ error++; -+ } -+ } -+ if((str = strrchr(names[i]->d_name,FLAGSEP)) != NULL) *str = '\0'; -+ snprintf (old, sizeof(old), "%s/%s%s%s%s%s%s", name, names[i]->d_name, MDSEP(2), -+ MDFLAG(Draft, d), MDFLAG(Flagged, f), MDFLAG(Replied, r), -+ MDFLAG(Seen, s)); -+ if(rename(new, old) < 0) -+ error++; -+ } -+ } -+ -+ } -+ if(k > 0) -+ fs_give((void **)&names); -+ else -+ *flist = names; -+ return error ? -1 : k; -+} -+ -+int -+maildir_doscandir(char *name, struct direct ***flist, int flag) -+{ -+return scandir(name, flist, -+ flag == CCLIENT ? maildir_select : courier_dir_select, -+ flag == CCLIENT ? maildir_namesort : courier_dir_sort); -+} -+ -+/* -+ * return all files in a given directory. This is a separate call -+ * so that if there are warnings during compilation this only appears once. -+ */ -+unsigned long -+maildir_scandir (char *name, struct direct ***flist, -+ unsigned long *nfiles, int *scand, int flag) -+{ -+ struct stat sbuf; -+ int rv = -2; /* impossible value */ -+ -+ if (scand) -+ *scand = -1; /* assume error for safety */ -+ *nfiles = 0; -+ if((stat(name,&sbuf) < 0) -+ || (flag == CCLIENT -+ && ((rv = maildir_eliminate_duplicate(name, flist, nfiles)) < 0))) -+ return 0L; -+ -+ if (scand && (rv > 0 || rv == -2)) -+ *nfiles = maildir_doscandir(name, flist, flag); -+ -+ if(scand) *scand = *nfiles; -+ -+ return (unsigned long) sbuf.st_ctime; -+} -+ -+/* Does a message with given name exists (or was it removed)? -+ * Returns: 1 - yes, such message exist, -+ * 0 - No, that message does not exist anymore -+ * -+ * Parameters: stream, name of mailbox, new name if his message does not -+ * exist. -+ */ -+ -+int maildir_message_exists(MAILSTREAM *stream, char *name, char *newfile) -+{ -+ char tmp[MAILTMPLEN]; -+ int gotit = NIL; -+ DIR *dir; -+ struct direct *d; -+ struct stat sbuf; -+ -+ /* First check directly if it exists, if not there, look for it */ -+ snprintf(tmp, sizeof(tmp), "%s/%s", LOCAL->path[Cur], name); -+ if ((stat(tmp, &sbuf) == 0) && ((sbuf.st_mode & S_IFMT) == S_IFREG)) -+ return T; -+ -+ if (!(dir = opendir (LOCAL->path[Cur]))) -+ return NIL; -+ -+ while ((d = readdir(dir)) && gotit == NIL){ -+ if (d->d_name[0] == '.') -+ continue; -+ if (same_maildir_file(d->d_name, name)){ -+ gotit = T; -+ strcpy(newfile, d->d_name); -+ } -+ } -+ closedir(dir); -+ return gotit; -+} -+ -+/* Maildir open */ +diff -rc alpine-2.26/alpine/alpine.c alpine-2.26.maildir/alpine/alpine.c +*** alpine-2.26/alpine/alpine.c 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.maildir/alpine/alpine.c 2022-06-02 18:14:52.219147911 -0600 +*************** +*** 593,598 **** +--- 593,603 ---- + if(F_ON(F_MAILDROPS_PRESERVE_STATE, ps_global)) + mail_parameters(NULL, SET_SNARFPRESERVE, (void *) TRUE); + ++ #ifndef _WINDOWS ++ rv = F_ON(F_COURIER_FOLDER_LIST, ps_global) ? 1 : 0; ++ mail_parameters(NULL,SET_COURIERSTYLE, (void *) &rv); ++ #endif + -+MAILSTREAM *maildir_open (MAILSTREAM *stream) -+{ -+ char tmp[MAILTMPLEN]; -+ struct stat sbuf; -+ -+ if (!stream) return &maildirproto; -+ if (stream->local) fatal ("maildir recycle stream"); -+ md_domain_name(); /* get domain name for maildir files in mdlocaldomain */ -+ if(mypid == (pid_t) 0) -+ mypid = getpid(); -+ if (!stream->rdonly){ -+ stream->perm_seen = stream->perm_deleted = stream->perm_flagged = -+ stream->perm_answered = stream->perm_draft = T; -+ } -+ stream->local = (MAILDIRLOCAL *) fs_get (sizeof (MAILDIRLOCAL)); -+ memset(LOCAL, 0, sizeof(MAILDIRLOCAL)); -+ LOCAL->fd = -1; -+ -+ LOCAL->courier = IS_COURIER(stream->mailbox); -+ strcpy(tmp, stream->mailbox); -+ if (maildir_file_path (stream->mailbox, tmp, sizeof(tmp))) -+ LOCAL->dir = cpystr (tmp); -+ LOCAL->candouid = maildir_can_assign_uid(stream); -+ maildir_read_uid(stream, &stream->uid_last, &stream->uid_validity); -+ if (LOCAL->dir){ -+ LOCAL->path = (char **) fs_get(EndDir*sizeof(char *)); -+ MDFLD(tmp, LOCAL->dir, Cur); LOCAL->path[Cur] = cpystr (tmp); -+ MDFLD(tmp, LOCAL->dir, New); LOCAL->path[New] = cpystr (tmp); -+ MDFLD(tmp, LOCAL->dir, Tmp); LOCAL->path[Tmp] = cpystr (tmp); -+ if (stat (LOCAL->path[Cur],&sbuf) < 0) { -+ snprintf (tmp, sizeof(tmp), "Can't open folder %s: %s", -+ stream->mailbox,strerror (errno)); -+ mm_log (tmp,ERROR); -+ maildir_close(stream, 0); -+ return NIL; + rvl = 0L; + if(pine_state->VAR_NNTPRANGE){ + if(!SVAR_NNTPRANGE(pine_state, rvl, tmp_20k_buf, SIZEOF_20KBUF)) +diff -rc alpine-2.26/alpine/confscroll.c alpine-2.26.maildir/alpine/confscroll.c +*** alpine-2.26/alpine/confscroll.c 2022-06-02 18:14:00.463274817 -0600 +--- alpine-2.26.maildir/alpine/confscroll.c 2022-06-02 18:14:52.223147900 -0600 +*************** +*** 5565,5570 **** +--- 5565,5576 ---- + (void *)var->current_val.p); + } + #endif ++ #ifndef _WINDOWS ++ else if(var == &ps->vars[V_MAILDIR_LOCATION]){ ++ if(var->current_val.p && var->current_val.p[0]) ++ mail_parameters(NULL, SET_MDINBOXPATH, (void *)var->current_val.p); + } -+ } -+ -+ if(maildir_file_path (stream->mailbox, tmp, sizeof(tmp))){ -+ fs_give ((void **) &stream->mailbox); -+ stream->mailbox = cpystr(tmp); -+ } -+ -+ LOCAL->buf = (char *) fs_get (CHUNKSIZE); -+ LOCAL->buflen = CHUNKSIZE - 1; -+ stream->sequence++; -+ stream->nmsgs = stream->recent = 0L; -+ -+ maildir_parse_folder(stream, 1); -+ -+ return stream; -+} -+ -+/* Maildir initial parsing of the folder */ -+void -+maildir_parse_folder (MAILSTREAM *stream, int full) -+{ -+ char tmp[MAILTMPLEN]; -+ struct direct **namescur = NIL, **namesnew = NIL; -+ unsigned long i, nfilescur = 0L, nfilesnew = 0L, oldpos, newpos, total; -+ int scan_err, rescan, loop = 0; -+ -+ if (!stream) /* what??? */ -+ return; -+ -+ MM_CRITICAL(stream); -+ -+ maildir_scandir (LOCAL->path[New], &namesnew, &nfilesnew, &scan_err, CCLIENT); -+ if (scan_err < 0) -+ maildir_abort(stream); -+ -+ /* Scan old messages first, escoba! */ -+ if(stream->rdonly || -+ (LOCAL && ((maildir_initial_check(stream, Cur) == 0) -+ || nfilesnew > 0L))){ -+ LOCAL->scantime = maildir_scandir (LOCAL->path[Cur], &namescur, &nfilescur, -+ &scan_err, CCLIENT); -+ if (scan_err < 0){ -+ if(namesnew){ -+ for(i = 0L; i < nfilesnew; i++) -+ fs_give((void **)&namesnew[i]); -+ fs_give((void **) &namesnew); -+ } -+ maildir_abort(stream); -+ } ++ #endif + else if(revert && standard_radio_var(ps, var)){ + + cur_rule_value(var, TRUE, FALSE); +diff -rc alpine-2.26/imap/src/c-client/mail.c alpine-2.26.maildir/imap/src/c-client/mail.c +*** alpine-2.26/imap/src/c-client/mail.c 2022-06-02 18:14:00.471274797 -0600 +--- alpine-2.26.maildir/imap/src/c-client/mail.c 2022-06-02 18:14:52.223147900 -0600 +*************** +*** 1071,1077 **** + MAILSTREAM *ts; + char *s,*t,tmp[MAILTMPLEN]; + size_t i; +! DRIVER *d; + /* never allow names with newlines */ + if ((s = strpbrk (mailbox,"\015\012")) != NULL) { + MM_LOG ("Can't create mailbox with such a name",ERROR); +--- 1071,1077 ---- + MAILSTREAM *ts; + char *s,*t,tmp[MAILTMPLEN]; + size_t i; +! DRIVER *d, *md; + /* never allow names with newlines */ + if ((s = strpbrk (mailbox,"\015\012")) != NULL) { + MM_LOG ("Can't create mailbox with such a name",ERROR); +*************** +*** 1095,1100 **** +--- 1095,1102 ---- + return NIL; + } + ++ /* Hack, we should do this better, but it works */ ++ for (md = maildrivers; md && strcmp (md->name, "md"); md = md->next); + /* see if special driver hack */ + if ((mailbox[0] == '#') && ((mailbox[1] == 'd') || (mailbox[1] == 'D')) && + ((mailbox[2] == 'r') || (mailbox[2] == 'R')) && +*************** +*** 1125,1130 **** +--- 1127,1139 ---- + (((*mailbox == '{') || (*mailbox == '#')) && + (stream = mail_open (NIL,mailbox,OP_PROTOTYPE | OP_SILENT)))) + d = stream->dtb; ++ else if(mailbox[0] == '#' ++ && (mailbox[1] == 'm' || mailbox[1] == 'M') ++ && (mailbox[2] == 'd' || mailbox[2] == 'D' ++ || mailbox[2] == 'c' || mailbox[2] == 'C') ++ && mailbox[3] == '/' ++ && mailbox[4] != '\0') ++ return (*md->create)(stream, mailbox); + else if ((*mailbox != '{') && (ts = default_proto (NIL))) d = ts->dtb; + else { /* failed utterly */ + sprintf (tmp,"Can't create mailbox %.80s: indeterminate format",mailbox); +diff -rc alpine-2.26/imap/src/c-client/mail.h alpine-2.26.maildir/imap/src/c-client/mail.h +*** alpine-2.26/imap/src/c-client/mail.h 2022-06-02 18:14:00.471274797 -0600 +--- alpine-2.26.maildir/imap/src/c-client/mail.h 2022-06-02 18:14:52.239147861 -0600 +*************** +*** 389,394 **** +--- 389,398 ---- + #define SET_SCANCONTENTS (long) 573 + #define GET_MHALLOWINBOX (long) 574 + #define SET_MHALLOWINBOX (long) 575 ++ #define GET_COURIERSTYLE (long) 576 ++ #define SET_COURIERSTYLE (long) 577 ++ #define SET_MDINBOXPATH (long) 578 ++ #define GET_MDINBOXPATH (long) 579 + + /* Driver flags */ + +diff -rc alpine-2.26/imap/src/osdep/unix/dummy.c alpine-2.26.maildir/imap/src/osdep/unix/dummy.c +*** alpine-2.26/imap/src/osdep/unix/dummy.c 2022-06-02 18:14:00.475274788 -0600 +--- alpine-2.26.maildir/imap/src/osdep/unix/dummy.c 2022-06-02 18:14:52.243147852 -0600 +*************** +*** 33,38 **** +--- 33,39 ---- + #include + #include + #include "dummy.h" ++ #include "maildir.h" + #include "misc.h" + + /* Function prototypes */ +*************** +*** 104,116 **** + * Accepts: mailbox name + * Returns: our driver if name is valid, NIL otherwise + */ +! + DRIVER *dummy_valid (char *name) + { +! char *s,tmp[MAILTMPLEN]; + struct stat sbuf; + /* must be valid local mailbox */ +! if (name && *name && (*name != '{') && (s = mailboxfile (tmp,name))) { + /* indeterminate clearbox INBOX */ + if (!*s) return &dummydriver; + else if (!stat (s,&sbuf)) switch (sbuf.st_mode & S_IFMT) { +--- 105,123 ---- + * Accepts: mailbox name + * Returns: our driver if name is valid, NIL otherwise + */ +! char * maildir_remove_root(char *); + DRIVER *dummy_valid (char *name) + { +! char *s,tmp[MAILTMPLEN], *rname; + struct stat sbuf; ++ ++ if(strlen(name) > MAILTMPLEN) ++ name[MAILTMPLEN] = '\0'; ++ ++ strcpy(tmp, name); ++ rname = maildir_remove_root(tmp); + /* must be valid local mailbox */ +! if (rname && *rname && (*rname != '{') && (s = mailboxfile (tmp,rname))) { + /* indeterminate clearbox INBOX */ + if (!*s) return &dummydriver; + else if (!stat (s,&sbuf)) switch (sbuf.st_mode & S_IFMT) { +*************** +*** 119,126 **** + return &dummydriver; + } + /* blackbox INBOX does not exist yet */ +! else if (!compare_cstring (name,"INBOX")) return &dummydriver; + } + return NIL; + } + +--- 126,134 ---- + return &dummydriver; + } + /* blackbox INBOX does not exist yet */ +! else if (!compare_cstring (rname,"INBOX")) return &dummydriver; + } ++ if(rname) fs_give((void **)&rname); + return NIL; + } + +*************** +*** 453,458 **** +--- 461,468 ---- + { + char *s,tmp[MAILTMPLEN]; + long ret = NIL; ++ if(!strncmp(mailbox,"#md/",4) || !strncmp(mailbox,"#mc/", 4)) ++ return maildir_create(stream, mailbox); + /* validate name */ + if (!(compare_cstring (mailbox,"INBOX") && (s = dummy_file (tmp,mailbox)))) { + sprintf (tmp,"Can't create %.80s: invalid name",mailbox); +*************** +*** 518,523 **** +--- 528,541 ---- + { + struct stat sbuf; + char *s,tmp[MAILTMPLEN]; ++ if (!strncmp(mailbox,"#md/",4) || !strncmp(mailbox,"#mc/", 4) ++ || is_valid_maildir(&mailbox)){ ++ char tmp[MAILTMPLEN] = {'\0'}; ++ strcpy(tmp, mailbox); ++ if(tmp[strlen(tmp) - 1] != '/') ++ tmp[strlen(tmp)] = '/'; ++ return maildir_delete(stream, tmp); + } -+ if(LOCAL && (maildir_initial_check(stream, New) == 0) -+ && (nfilescur > 0L)){ -+ while(LOCAL && loop < 10){ -+ if(nfilesnew == 0L) -+ maildir_scandir (LOCAL->path[New], &namesnew, &nfilesnew, &scan_err, CCLIENT); -+ if (scan_err < 0){ -+ if(namesnew){ -+ for(i = 0L; i < nfilesnew; i++) -+ fs_give((void **)&namesnew[i]); -+ fs_give((void **) &namesnew); -+ } -+ maildir_abort(stream); -+ break; -+ } -+ for(i = 0L, rescan = 0, newpos = oldpos = 0L; -+ newpos < nfilescur && i < nfilesnew; i++){ -+ if(maildir_message_in_list(namesnew[i]->d_name, namescur, oldpos, -+ nfilescur - 1L, &newpos)){ -+ oldpos = newpos; -+ snprintf(tmp, sizeof(tmp), "%s/%s", LOCAL->path[New], namesnew[i]->d_name); -+ if(unlink(tmp) < 0) -+ scan_err = -1; -+ rescan++; -+ } -+ else -+ newpos = oldpos; -+ } -+ if(scan_err < 0) -+ maildir_abort(stream); -+ if(rescan == 0) -+ break; -+ else{ /* restart */ -+ if(namesnew){ -+ for(i = 0L; i < nfilesnew; i++) -+ fs_give((void **)&namesnew[i]); -+ fs_give((void **) &namesnew); -+ } -+ nfilesnew = 0L; -+ loop++; -+ } -+ } -+ } -+ if(loop == 10) -+ maildir_abort(stream); -+ if(LOCAL){ -+ if(stream->rdonly) -+ stream->recent = 0L; -+ total = namescur || stream->rdonly -+ ? maildir_parse_dir(stream, 0L, Cur, namescur, -+ nfilescur, full) : stream->nmsgs; -+ stream->nmsgs = maildir_parse_dir(stream, total, New, namesnew, -+ nfilesnew, full); -+ } -+ if(namesnew){ -+ for(i = 0L; i < nfilesnew; i++) -+ fs_give((void **)&namesnew[i]); -+ fs_give((void **) &namesnew); -+ } -+ if(namescur){ -+ for(i = 0L; i < nfilescur; i++) -+ fs_give((void **)&namescur[i]); -+ fs_give((void **) &namescur); -+ } -+ MM_NOCRITICAL(stream); -+} -+ -+int -+maildir_initial_check (MAILSTREAM *stream, DirNamesType dirtype) -+{ -+ char *tmp; -+ struct stat sbuf; -+ -+ if (access (LOCAL->path[dirtype], R_OK|W_OK|X_OK) != 0){ -+ maildir_abort(stream); -+ return -1; -+ } -+ -+ if (dirtype != New && -+ (stat(LOCAL->path[Cur], &sbuf) < 0 || sbuf.st_ctime == LOCAL->scantime)) -+ return -1; -+ return 0; -+} -+ -+ -+/* Return the number of messages in the directory, while filling the -+ * elt structure. -+ */ -+ -+unsigned long -+maildir_parse_dir(MAILSTREAM *stream, unsigned long nmsgs, -+ DirNamesType dirtype, struct direct **names, -+ unsigned long nfiles, int full) -+{ -+ char tmp[MAILTMPLEN], file[MAILTMPLEN], newfile[MAILTMPLEN], *mdstr; -+ struct stat sbuf; -+ unsigned long i, new = 0L, l, uid_last; -+ unsigned long recent = stream ? stream->recent : 0L; -+ int d = 0, f = 0, r = 0, s = 0, t = 0; -+ int we_compute, in_list; -+ int silent = stream ? stream->silent : NIL; -+ MESSAGECACHE *elt; -+ -+ if (dirtype == Cur && !stream->rdonly) -+ for (i = 1L; i <= stream->nmsgs;){ -+ elt = mail_elt(stream, i); -+ in_list = elt && elt->private.spare.ptr && nfiles > 0L -+ ? (MDPOS(elt) < nfiles -+ ? same_maildir_file(MDFILE(elt), names[MDPOS(elt)]->d_name) -+ : NIL) -+ || maildir_message_in_list(MDFILE(elt), names, 0L, -+ nfiles - 1L, &MDPOS(elt)) -+ : NIL; -+ if (!in_list){ -+ if (elt->private.spare.ptr) -+ maildir_free_file ((void **) &elt->private.spare.ptr); -+ -+ if (elt->recent) --recent; -+ mail_expunged(stream,i); -+ } -+ else i++; -+ } -+ -+ stream->silent = T; -+ uid_last = 0L; -+ for (we_compute = 0, i = l = 1L; l <= nfiles; l++){ -+ unsigned long pos, uid; -+ if (dirtype == New && !stream->rdonly){ /* move new messages to cur */ -+ pos = l - 1L; -+ snprintf (file, sizeof(file), "%s/%s", LOCAL->path[New], names[pos]->d_name); -+ if(lstat(file,&sbuf) == 0) -+ switch(sbuf.st_mode & S_IFMT){ -+ case S_IFREG: -+ strcpy(tmp, names[pos]->d_name); -+ if((mdstr = strstr(tmp,MDSEP(3))) -+ || (mdstr = strstr(tmp,MDSEP(2)))) -+ *(mdstr+1) = '2'; -+ else -+ strcat(tmp, MDSEP(2)); -+ snprintf(newfile, sizeof(newfile), "%s/%s", LOCAL->path[Cur], tmp); -+ if(rename (file, newfile) != 0){ -+ mm_log("Unable to read new mail!", WARN); -+ continue; -+ } -+ unlink (file); -+ new++; -+ break; -+ case S_IFLNK: /* clean up, clean up, everybody, everywhere */ -+ if(unlink(file) < 0){ -+ if(LOCAL->link == NIL){ -+ mm_log("Unable to remove symbolic link", WARN); -+ LOCAL->link = T; -+ } -+ } -+ continue; -+ break; -+ default: -+ if(LOCAL && LOCAL->link == NIL){ -+ mm_log("Unrecognized file or link in folder", WARN); -+ LOCAL->link = T; -+ } -+ continue; -+ break; -+ } -+ } -+ mail_exists(stream, i + nmsgs); -+ elt = mail_elt(stream, i + nmsgs); -+ pos = (elt && elt->private.spare.ptr) ? MDPOS(elt) : l - 1L; -+ if (dirtype == New) elt->recent = T; -+ maildir_getflag(names[pos]->d_name, &d, &f, &r ,&s, &t); -+ if (elt->private.spare.ptr) -+ maildir_free_file_only ((void **)&elt->private.spare.ptr); -+ else{ -+ maildir_get_file((MAILDIRFILE **)&elt->private.spare.ptr); -+ we_compute++; -+ } -+ MDFILE(elt) = cpystr(names[pos]->d_name); -+ MDPOS(elt) = pos; -+ MDLOC(elt) = dirtype; -+ if (dirtype == Cur){ /* deal with UIDs */ -+ if(elt->private.uid == 0L) -+ elt->private.uid = maildir_get_uid(MDFILE(elt)); -+ if(elt->private.uid <= uid_last){ -+ uid = (we_compute ? uid_last : stream->uid_last) + 1L; -+ if(LOCAL->candouid) -+ maildir_assign_uid(stream, i + nmsgs, uid); -+ else -+ elt->private.uid = uid; -+ } -+ else -+ uid = elt->private.uid; -+ uid_last = uid; -+ if(uid_last > stream->uid_last) -+ stream->uid_last = uid_last; -+ } -+ if(dirtype == New && !stream->rdonly){ -+ maildir_free_file_only((void **)&elt->private.spare.ptr); -+ MDFILE(elt) = cpystr(tmp); -+ MDSIZE(elt) = sbuf.st_size; -+ MDMTIME(elt) = sbuf.st_mtime; -+ MDLOC(elt) = Cur; -+ } -+ if (elt->draft != d || elt->flagged != f || -+ elt->answered != r || elt->seen != s || elt->deleted != t){ -+ elt->draft = d; elt->flagged = f; elt->answered = r; -+ elt->seen = s; elt->deleted = t; -+ if (!we_compute && !stream->rdonly) -+ MM_FLAGS(stream, i+nmsgs); -+ } -+ maildir_get_date(stream, i+nmsgs); -+ elt->valid = T; -+ i++; -+ } -+ stream->silent = silent; -+ if(LOCAL->candouid && dirtype == Cur) -+ maildir_read_uid(stream, NULL, &stream->uid_validity); -+ if (dirtype == New && stream->rdonly) -+ new = nfiles; -+ mail_exists(stream, nmsgs + ((dirtype == New) ? new : nfiles)); -+ mail_recent(stream, recent + ((dirtype == New) ? new : 0L)); -+ -+ return (nmsgs + (dirtype == New ? new : nfiles)); -+} -+ -+long maildir_ping (MAILSTREAM *stream) -+{ -+ maildir_parse_folder(stream, 0); -+ if(stream && LOCAL){ -+ if(LOCAL->candouid < 0) -+ LOCAL->candouid++; -+ else if(LOCAL->candouid) -+ maildir_uid_renew_tempfile(stream); -+ else /* try again to get uids */ -+ LOCAL->candouid = maildir_can_assign_uid(stream); -+ } -+ return stream && LOCAL ? LONGT : NIL; -+} -+ -+int maildir_select (const struct direct *name) -+{ -+ return (name->d_name[0] != '.'); -+} -+ -+/* -+ * Unfortunately, there is no way to sort by arrival in this driver, this -+ * means that opening a folder in this driver using the scandir function -+ * will always make this driver slower than any driver that has a natural -+ * way of sorting by arrival (like a flat file format, "mbox", "mbx", etc). -+ */ -+int maildir_namesort (const struct direct **d1, const struct direct **d2) -+{ -+ const struct direct *e1 = *(const struct direct **) d1; -+ const struct direct *e2 = *(const struct direct **) d2; -+ -+ return comp_maildir_file((char *) e1->d_name, (char *) e2->d_name); -+} -+ -+/* Maildir close */ -+ -+void maildir_close (MAILSTREAM *stream, long options) -+{ -+ MESSAGECACHE *elt; -+ unsigned long i; -+ int silent = stream ? stream->silent : 0; -+ mailcache_t mc = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL); -+ -+ if (!stream) return; -+ -+ for (i = 1L; i <= stream->nmsgs; i++) -+ if((elt = (MESSAGECACHE *) (*mc)(stream,i,CH_ELT)) && elt->private.spare.ptr) -+ maildir_free_file ((void **) &elt->private.spare.ptr); -+ stream->silent = T; -+ if (options & CL_EXPUNGE) maildir_expunge (stream, NIL, NIL); -+ maildir_abort(stream); -+ if (mdfpath) fs_give((void **)&mdfpath); -+ if (mypid) mypid = (pid_t) 0; -+ stream->silent = silent; -+} -+ -+void maildir_check (MAILSTREAM *stream) -+{ -+ if (maildir_ping (stream)) mm_log ("Check completed",(long) NIL); -+} -+ -+long maildir_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs, long flags) -+{ -+ char tmp[MAILTMPLEN]; -+ unsigned long i; -+ MESSAGECACHE *elt; -+ char *s; -+ /* UID call "impossible" */ -+ if (flags & FT_UID || !LOCAL) return NIL; -+ elt = mail_elt (stream, msgno); -+ -+ if (!(flags & FT_PEEK) && !elt->seen){ -+ elt->seen = T; -+ maildir_flagmsg (stream, elt); -+ MM_FLAGS(stream, elt->msgno); -+ } -+ -+ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), MDLOC(elt)); -+ if (LOCAL->fd < 0) /* if file closed ? */ -+ LOCAL->fd = open(tmp,O_RDONLY,NIL); -+ -+ if (LOCAL->fd < 0 && (errno == EACCES || errno == ENOENT)){ -+ INIT (bs, mail_string, "", 0); -+ elt->rfc822_size = 0L; -+ return NIL; -+ } -+ -+ s = maildir_text_work(stream, elt, &i, flags); -+ INIT (bs, mail_string, s, i); -+ return LONGT; -+} -+ -+char *maildir_text_work (MAILSTREAM *stream,MESSAGECACHE *elt, -+ unsigned long *length,long flags) -+{ -+ FDDATA d; -+ STRING bs; -+ char *s,tmp[CHUNK]; -+ unsigned long msgno = elt->msgno; -+ static int try = 0; -+ -+ if (length) -+ *length = 0L; -+ LOCAL->buf[0] = '\0'; -+ -+ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), MDLOC(elt)); -+ if (LOCAL->fd < 0) /* if file closed ? */ -+ LOCAL->fd = open(tmp,O_RDONLY,NIL); -+ -+ if (LOCAL->fd < 0){ /* flag change? */ -+ if (try < 5){ -+ try++; -+ if (maildir_update_elt_maildirp(stream, msgno) > 0) -+ try = 0; -+ return maildir_text_work(stream, mail_elt(stream, msgno),length, flags); -+ } -+ try = 0; -+ return NULL; -+ } -+ -+ lseek (LOCAL->fd, elt->private.msg.text.offset,L_SET); -+ -+ if (flags & FT_INTERNAL) { /* initial data OK? */ -+ if (elt->private.msg.text.text.size > LOCAL->buflen) { -+ fs_give ((void **) &LOCAL->buf); -+ LOCAL->buf = (char *) fs_get ((LOCAL->buflen = -+ elt->private.msg.text.text.size) + 1); -+ } -+ read (LOCAL->fd,LOCAL->buf,elt->private.msg.text.text.size); -+ LOCAL->buf[*length = elt->private.msg.text.text.size] = '\0'; -+ } -+ else { -+ if (elt->rfc822_size > LOCAL->buflen) { -+ fs_give ((void **) &LOCAL->buf); -+ LOCAL->buf = (char *) fs_get ((LOCAL->buflen = elt->rfc822_size) + 1); -+ } -+ d.fd = LOCAL->fd; /* yes, set up file descriptor */ -+ d.pos = elt->private.msg.text.offset; -+ d.chunk = tmp; /* initial buffer chunk */ -+ d.chunksize = CHUNK; -+ INIT (&bs,fd_string,&d,elt->private.msg.text.text.size); -+ for (s = LOCAL->buf; SIZE (&bs);) switch (CHR (&bs)) { -+ case '\r': /* carriage return seen */ -+ *s++ = SNX (&bs); /* copy it and any succeeding LF */ -+ if (SIZE (&bs) && (CHR (&bs) == '\n')) *s++ = SNX (&bs); -+ break; -+ case '\n': -+ *s++ = '\r'; /* insert a CR */ -+ default: -+ *s++ = SNX (&bs); /* copy characters */ -+ } -+ *s = '\0'; /* tie off buffer */ -+ *length = s - (char *) LOCAL->buf; /* calculate length */ -+ } -+ close(LOCAL->fd); LOCAL->fd = -1; -+ return LOCAL->buf; -+} -+ -+/* maildir parse, fill the elt structure... well not all of it... */ -+unsigned long maildir_parse_message(MAILSTREAM *stream, unsigned long msgno, -+ DirNamesType dirtype) -+{ -+ char *b, *s, *t, c; -+ char tmp[MAILTMPLEN]; -+ struct stat sbuf; -+ unsigned long i, len; -+ int d, f, r, se, dt; -+ MESSAGECACHE *elt; -+ -+ elt = mail_elt (stream,msgno); -+ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), dirtype); -+ if(stat(tmp, &sbuf) == 0) -+ MDSIZE(elt) = sbuf.st_size; -+ -+ maildir_get_date(stream, msgno); -+ maildir_getflag(MDFILE(elt), &d, &f, &r ,&se, &dt); -+ elt->draft = d; elt->flagged = f; elt->answered = r; elt->seen = se; -+ elt->deleted = dt; elt->valid = T; -+ if (LOCAL->fd < 0) /* if file closed ? */ -+ LOCAL->fd = open(tmp,O_RDONLY,NIL); -+ -+ if (LOCAL->fd >= 0){ -+ s = (char *) fs_get (MDSIZE(elt) + 1); -+ read (LOCAL->fd,s,MDSIZE(elt)); -+ s[MDSIZE(elt)] = '\0'; -+ t = s + strlen(s); /* make t point to the end of s */ -+ for (i = 0L, b = s; b < t && !(i && (*b == '\n')); i = (*b++ == '\n')); -+ len = (*b ? ++b : b) - s; -+ elt->private.msg.header.text.size = -+ elt->private.msg.text.offset = len; -+ elt->private.msg.text.text.size = MDSIZE(elt) - len; -+ for (i = 0L, b = s, c = *b; b && -+ ((c < '\016' && ((c == '\012' && ++i) -+ ||(c == '\015' && *(b+1) == '\012' && ++b && (i +=2)))) -+ || b < t); i++, c= *++b); -+ elt->rfc822_size = i; -+ fs_give ((void **) &s); -+ close(LOCAL->fd); LOCAL->fd = -1; -+ } -+ return elt->rfc822_size; -+} -+ -+int -+maildir_update_elt_maildirp(MAILSTREAM *stream, unsigned long msgno) -+{ -+ struct direct **names = NIL; -+ unsigned long i, nfiles, pos; -+ int d = 0, f = 0 , r = 0, s = 0, t = 0, in_list, scan_err; -+ MESSAGECACHE *elt; -+ -+ maildir_scandir (LOCAL->path[Cur], &names, &nfiles, &scan_err, CCLIENT); -+ -+ elt = mail_elt (stream,msgno); -+ -+ in_list = nfiles > 0L -+ ? maildir_message_in_list(MDFILE(elt), names, 0L, nfiles - 1L, &pos) -+ : NIL; -+ -+ if (in_list && pos >= 0L && pos < nfiles -+ && !strcmp(MDFILE(elt), names[pos]->d_name)){ -+ in_list = NIL; -+ maildir_abort(stream); -+ } -+ -+ if (in_list && pos >= 0L && pos < nfiles){ -+ maildir_free_file_only((void **)&elt->private.spare.ptr); -+ MDFILE(elt) = cpystr(names[pos]->d_name); -+ maildir_getflag(MDFILE(elt), &d, &f, &r ,&s, &t); -+ if (elt->draft != d || elt->flagged != f || -+ elt->answered != r || elt->seen != s || elt->deleted != t){ -+ elt->draft = d; elt->flagged = f; elt->answered = r; -+ elt->seen = s; elt->deleted = t; -+ MM_FLAGS(stream, msgno); -+ } -+ } -+ for (i = 0L; i < nfiles; i++) -+ fs_give((void **) &names[i]); -+ if (names) -+ fs_give((void **) &names); -+ return in_list ? 1 : -1; -+} -+ -+/* Maildir fetch message header */ -+ -+char *maildir_header (MAILSTREAM *stream,unsigned long msgno, -+ unsigned long *length, long flags) -+{ -+ char tmp[MAILTMPLEN], *s; -+ MESSAGECACHE *elt; -+ static int try = 0; -+ -+ if (length) *length = 0; -+ if (flags & FT_UID || !LOCAL) return ""; /* UID call "impossible" */ -+ elt = mail_elt (stream,msgno); -+ if(elt->private.msg.header.text.size == 0) -+ maildir_parse_message(stream, msgno, MDLOC(elt)); -+ -+ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), MDLOC(elt)); -+ if (LOCAL->fd < 0) -+ LOCAL->fd = open (tmp,O_RDONLY,NIL); -+ -+ if (LOCAL->fd < 0 && errno == EACCES){ -+ mm_log ("Message exists but can not be read. Envelope and body lost!",ERROR); -+ return NULL; -+ } -+ -+ if (LOCAL->fd < 0){ /* flag change? */ -+ if (try < 5){ -+ try++; -+ if (maildir_update_elt_maildirp(stream, msgno) > 0) -+ try = 0; -+ return maildir_header(stream, msgno, length, flags); -+ } -+ try = 0; -+ return NULL; -+ } -+ -+ if (flags & FT_INTERNAL){ -+ if(elt->private.msg.header.text.size > LOCAL->buflen){ -+ fs_give ((void **) &LOCAL->buf); -+ LOCAL->buf = (char *) fs_get ((LOCAL->buflen = -+ elt->private.msg.header.text.size) + 1); -+ } -+ read (LOCAL->fd, (void *)LOCAL->buf, elt->private.msg.header.text.size); -+ LOCAL->buf[*length = elt->private.msg.header.text.size] = '\0'; -+ } -+ else{ -+ s = (char *) fs_get(elt->private.msg.header.text.size+1); -+ read (LOCAL->fd, (void *)s, elt->private.msg.header.text.size); -+ s[elt->private.msg.header.text.size] = '\0'; -+ *length = strcrlfcpy (&LOCAL->buf,&LOCAL->buflen,s, -+ elt->private.msg.header.text.size); -+ fs_give ((void **) &s); -+ } -+ elt->private.msg.text.offset = elt->private.msg.header.text.size; -+ elt->private.msg.text.text.size = MDSIZE(elt) - elt->private.msg.text.offset; -+ close(LOCAL->fd); LOCAL->fd = -1; -+ return LOCAL->buf; -+} -+ -+/* Maildir find list of subscribed mailboxes -+ * Accepts: mail stream -+ * pattern to search -+ */ -+ -+void maildir_list (MAILSTREAM *stream,char *ref, char *pat) -+{ -+ char *s,test[MAILTMPLEN],file[MAILTMPLEN]; -+ long i = 0L; -+ -+ if((!pat || !*pat) && maildir_canonicalize (test,ref,"*") -+ && maildir_valid_name(test)){ /* there is a #md/ leading here */ -+ for (i = 3L; test[i] && test[i] != '/'; i++); -+ if ((s = strchr (test+i+1,'/')) != NULL) *++s = '\0'; -+ else test[0] = '\0'; -+ mm_list (stream,'/',test, LATT_NOSELECT); -+ } -+ else if (maildir_canonicalize (test,ref,pat)) { -+ if (test[3] == '/') { /* looking down levels? */ -+ /* yes, found any wildcards? */ -+ if ((s = strpbrk (test,"%*")) != NULL){ -+ /* yes, copy name up to that point */ -+ strncpy (file,test+4,i = s - (test+4)); -+ file[i] = '\0'; /* tie off */ -+ } -+ else strcpy (file,test+4);/* use just that name then */ -+ /* find directory name */ -+ if ((s = strrchr (file, '/')) != NULL){ -+ *s = '\0'; /* found, tie off at that point */ -+ s = file; -+ } -+ /* do the work */ -+ if(IS_COURIER(test)) -+ courier_list_work (stream,s,test,0); -+ else -+ maildir_list_work (stream,s,test,0); -+ } -+ /* always an INBOX */ -+ if (!compare_cstring (test,"#MD/INBOX")) -+ mm_list (stream,NIL,"#MD/INBOX",LATT_NOINFERIORS); -+ if (!compare_cstring (test,"#MC/INBOX")) -+ mm_list (stream,NIL,"#MC/INBOX",LATT_NOINFERIORS); -+ } -+} -+ -+void courier_list (MAILSTREAM *stream,char *ref, char *pat) -+{ -+/* I am too lazy to do anything. Do you care to ask maildir list, please? -+ The real reason why this is a dummy function is because we do not want to -+ see the same folder listed twice. -+*/ -+} -+ -+/* For those that want to hide things, we give them a chance to do so */ -+void *maildir_parameters (long function, void *value) -+{ -+ void *ret = NIL; -+ switch ((int) function) { -+ case SET_MDINBOXPATH: -+ if(strlen((char *) value ) > 49) -+ strcpy(myMdInboxDir, "Maildir"); -+ else -+ strcpy(myMdInboxDir, (char *) value); -+ case GET_MDINBOXPATH: -+ if (myMdInboxDir[0] == '\0') strcpy(myMdInboxDir,"Maildir"); -+ ret = (void *) myMdInboxDir; -+ break; -+ case SET_COURIERSTYLE: -+ CourierStyle = (long) value; -+ case GET_COURIERSTYLE: -+ ret = (void *) CourierStyle; -+ break; -+ case GET_DIRFMTTEST: -+ ret = (void *) maildir_dirfmttest; -+ break; -+ default: -+ break; -+ } -+ return ret; -+} -+ -+int maildir_create_folder(char *mailbox) -+{ -+ char tmp[MAILTMPLEN], err[MAILTMPLEN]; -+ DirNamesType i; -+ -+ for (i = Cur; i != EndDir; i++){ -+ MDFLD(tmp, mailbox, i); -+ if (mkdir(tmp, 0700) && errno != EEXIST){ /* try to make new dir */ -+ snprintf (err, sizeof(err), "Can't create %s: %s", tmp, strerror(errno)); -+ mm_log (err,ERROR); -+ return NIL; -+ } -+ } -+ return T; -+} -+ -+int maildir_create_work(char *mailbox, int loop) -+{ -+ char *s, c, err[MAILTMPLEN], tmp[MAILTMPLEN], tmp2[MAILTMPLEN], mbx[MAILTMPLEN]; -+ int fnlen, create_dir = 0, courier, mv; -+ struct stat sbuf; -+ long style = *(long *) maildir_parameters(GET_COURIERSTYLE, NIL); -+ -+ courier = IS_COURIER(mailbox); -+ strcpy(mbx, mailbox); -+ mv = maildir_valid(mbx) ? 1 : 0; -+ maildir_file_path(mailbox, tmp, sizeof(tmp)); -+ if (mailbox[strlen(mailbox) - 1] == MDSEPARATOR(courier)){ -+ create_dir++; -+ mailbox[strlen(mailbox) - 1] = '\0'; -+ } -+ -+ if(!loop && courier){ -+ if(mv){ -+ if(create_dir){ -+ if(style == CCLIENT) -+ strcpy (err,"Can not create directory: folder exists. Create subfolder"); -+ else -+ strcpy(err,"Folder and Directory already exist"); + if (!(s = dummy_file (tmp,mailbox))) { + sprintf (tmp,"Can't delete - invalid name: %.80s",mailbox); + MM_LOG (tmp,ERROR); +*************** +*** 543,554 **** + long dummy_rename (MAILSTREAM *stream,char *old,char *newname) + { + struct stat sbuf; +! char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN]; + /* no trailing / allowed */ +! if (!dummy_file (oldname,old) || !(s = dummy_file (mbx,newname)) || + stat (oldname,&sbuf) || ((s = strrchr (s,'/')) && !s[1] && + ((sbuf.st_mode & S_IFMT) != S_IFDIR))) { +! sprintf (mbx,"Can't rename %.80s to %.80s: invalid name",old,newname); + MM_LOG (mbx,ERROR); + return NIL; + } +--- 561,583 ---- + long dummy_rename (MAILSTREAM *stream,char *old,char *newname) + { + struct stat sbuf; +! char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN], *rold, *rnewname; +! +! if(strlen(old) > MAILTMPLEN) +! old[MAILTMPLEN] = '\0'; +! +! if(strlen(newname) > MAILTMPLEN) +! newname[MAILTMPLEN] = '\0'; +! +! strcpy(tmp, old); +! rold = maildir_remove_root(tmp); +! strcpy(tmp, newname); +! rnewname = maildir_remove_root(tmp); + /* no trailing / allowed */ +! if (!dummy_file (oldname,rold) || !(s = dummy_file (mbx,rnewname)) || + stat (oldname,&sbuf) || ((s = strrchr (s,'/')) && !s[1] && + ((sbuf.st_mode & S_IFMT) != S_IFDIR))) { +! sprintf (mbx,"Can't rename %.80s to %.80s: invalid name",rold,rnewname); + MM_LOG (mbx,ERROR); + return NIL; + } +*************** +*** 564,577 **** + } + } + /* rename of non-ex INBOX creates dest */ +! if (!compare_cstring (old,"INBOX") && stat (oldname,&sbuf)) + return dummy_create (NIL,mbx); + if (rename (oldname,mbx)) { +! sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %.80s",old,newname, + strerror (errno)); + MM_LOG (tmp,ERROR); + return NIL; + } + return T; /* return success */ + } + +--- 593,608 ---- + } + } + /* rename of non-ex INBOX creates dest */ +! if (!compare_cstring (rold,"INBOX") && stat (oldname,&sbuf)) + return dummy_create (NIL,mbx); + if (rename (oldname,mbx)) { +! sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %.80s",rold,rnewname, + strerror (errno)); + MM_LOG (tmp,ERROR); + return NIL; + } ++ if(rold) fs_give((void **)&rold); ++ if(rnewname) fs_give((void **)&rnewname); + return T; /* return success */ + } + +diff -rc alpine-2.26/imap/src/osdep/unix/maildir.c alpine-2.26.maildir/imap/src/osdep/unix/maildir.c +*** alpine-2.26/imap/src/osdep/unix/maildir.c 2022-06-02 18:14:52.323147655 -0600 +--- alpine-2.26.maildir/imap/src/osdep/unix/maildir.c 2022-06-02 18:14:52.251147832 -0600 +*************** +*** 0 **** +--- 1,2865 ---- ++ /* ++ * Maildir driver for Alpine 2.25 ++ * ++ * Written by Eduardo Chappa ++ * Last Update: October 16, 2021. ++ * ++ */ ++ ++ #include ++ #include ++ #include ++ extern int errno; /* just in case */ ++ #include "mail.h" ++ #include ++ #include ++ #include ++ #include "osdep.h" ++ #include "rfc822.h" ++ #include "fdstring.h" ++ #include "misc.h" ++ #include "dummy.h" ++ #include "maildir.h" ++ ++ /* ++ * A few definitions that try to make this module portable to other ++ * platforms (e.g. Cygwin). This module is based on the information from ++ * http://cr.yp.to/proto/maildir.html ++ */ ++ ++ /* First we deal with the separator character */ ++ #ifndef FLAGSEP ++ #define FLAGSEP ':' ++ #endif ++ #define SIZESEP ',' ++ ++ const char sep1[] = {FLAGSEP, '1', ',', '\0'}; /* experimental semantics*/ ++ const char sep2[] = {FLAGSEP, '2', ',', '\0'}; /* Flags Information */ ++ const char sep3[] = {FLAGSEP, '3', ',', '\0'}; /* Grrrr.... */ ++ const char *sep[] = { sep1, sep2, sep3, NULL}; ++ #define MDSEP(i) sep[((i) - 1)] ++ ++ /* Now we deal with flags. Woohoo! */ ++ const int mdimapflags[] = {Draft, Flagged, Replied, Seen, Trashed, EmptyFlag, EndFlags}; ++ const int mdkwdflags[] = {Passed, EmptyFlag, EndFlags}; ++ ++ /* this array lists the codes for mdflgnms (maildir flag names) above */ ++ const char *mdflags[] = { "D", "F", "P", "R", "S", "T", "", NULL}; ++ /* and as characters too */ ++ const char cmdflags[] = { 'D', 'F', 'P', 'R', 'S', 'T', '0', '\0'}; ++ ++ /* MDFLAG(Seen, elt->seen) */ ++ #define MDFLAG(i,j) mdflags[j ? (i) : EmptyFlag] ++ /* MDFLAGC(Seen) */ ++ #define MDFLAGC(i) cmdflags[(i)] ++ ++ /* Now we deal with the directory structure */ ++ char *mdstruct[] = {"cur", "tmp", "new", NULL}; ++ #define MDNAME(i) mdstruct[(i)] ++ #define MDFLD(X, Y, i) do { snprintf((X), sizeof((X)), "%.*s/%.*s", \ ++ (int) (sizeof((X)) - 6), (Y), \ ++ 3, mdstruct[(i)]); \ ++ (X)[sizeof((X)) - 1] = '\0'; \ ++ } while(0) ++ ++ #define MSGPATH(X, Y, Z,i) do { snprintf((X), sizeof((X)), "%.*s/%.*s/%.*s", \ ++ (int) strlen((Y)), (Y), \ ++ 3, mdstruct[(i)], \ ++ (int)(sizeof((X)) - strlen((Y)) - 3 - 3), (Z)); \ ++ (X)[sizeof((X)) - 1] = '\0'; \ ++ } while(0) ++ ++ /* Files associated to a maildir directory */ ++ ++ #define MDUIDVALIDITY ".uidvalidity" /* support for old maildirs */ ++ #define MDDIR ".mdir" /* this folder is a directory */ ++ #define MDUIDLAST ".uidlast" /* last assigned uid */ ++ #define MDUIDTEMP ".uidtemp" /* We assign uid's no one else */ ++ ++ /* Support of Courier Structure */ ++ #define CCLIENT 0 ++ #define COURIER 1 ++ #define IS_CCLIENT(t) \ ++ (((t) && (t)[0] == '#' && ((t)[1] == 'm' || (t)[1] == 'M')\ ++ && ((t)[2] == 'd' || (t)[2] == 'D')\ ++ && (t)[3] == '/' && (t)[4] != '\0') ? 1 : 0) ++ ++ #define IS_COURIER(t) \ ++ (((t) && (t)[0] == '#' && ((t)[1] == 'm' || (t)[1] == 'M')\ ++ && ((t)[2] == 'c' || (t)[2] == 'C')\ ++ && (t)[3] == '/' && (t)[4] != '\0') ? 1 : 0) ++ #define MDPREFIX(s) ((s) ? "#mc/" : "#md/") ++ #define MDSEPARATOR(s) ((s) ? '.' : '/') ++ ++ /* UID Support */ ++ ++ #define MAXTEMPUID (unsigned long) 180L ++ const char mduid[] = {',','u','=','\0'}; ++ #define MDUIDSEP mduid ++ ++ /* Now we deal with messages filenames */ ++ char mdlocaldomain[MAILTMPLEN+1] = {'\0'}; ++ pid_t mypid = (pid_t) 0; ++ static char *mdfpath = NULL; ++ static char myMdInboxDir[50] = { '\0' };/* Location of the Maildir INBOX */ ++ static long CourierStyle = CCLIENT; ++ ++ #define CHUNK 16384 /* from unix.h */ ++ ++ /* In gdb this is the *(struct maildir_local *)stream->local structure */ ++ typedef struct maildir_local { ++ unsigned int dirty : 1; /* diskcopy needs updating */ ++ unsigned int courier : 1; /* It is Courier style file system */ ++ unsigned int link : 1; /* There is a symbolic link */ ++ int candouid; /* we can assign uids and no one else */ ++ char *uidtempfile; /* path to uid temp file */ ++ int fd; /* fd of open message */ ++ char *dir; /* mail directory name */ ++ char **path; /* path to directories cur, new and tmp */ ++ unsigned char *buf; /* temporary buffer */ ++ unsigned long buflen; /* current size of temporary buffer */ ++ time_t scantime; /* last time directory scanned */ ++ } MAILDIRLOCAL; ++ ++ /* Convenient access to local data */ ++ #define LOCAL ((MAILDIRLOCAL *) stream->local) ++ ++ #define MDFILE(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->name) ++ #define MDLOC(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->loc) ++ #define MDPOS(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->pos) ++ #define MDSIZE(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->size) ++ #define MDATIME(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->atime) ++ #define MDMTIME(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->mtime) ++ #define MDCTIME(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->ctime) ++ ++ /* Driver dispatch used by MAIL */ ++ DRIVER maildirdriver = { ++ "md", /* driver name, yes it's md, not maildir */ ++ DR_MAIL|DR_LOCAL|DR_NAMESPACE|DR_DIRFMT, /* driver flags */ ++ (DRIVER *) NIL, /* next driver */ ++ maildir_valid, /* mailbox is valid for us */ ++ maildir_parameters, /* manipulate parameters */ ++ NIL, /* scan mailboxes */ ++ maildir_list, /* find mailboxes */ ++ maildir_lsub, /* find subscribed mailboxes */ ++ maildir_sub, /* subscribe to mailbox */ ++ maildir_unsub, /* unsubscribe from mailbox */ ++ maildir_create, /* create mailbox */ ++ maildir_delete, /* delete mailbox */ ++ maildir_rename, /* rename mailbox */ ++ mail_status_default, /* status of mailbox */ ++ maildir_open, /* open mailbox */ ++ maildir_close, /* close mailbox */ ++ maildir_fast, /* fetch message "fast" attributes */ ++ NIL, /* fetch message flags */ ++ NIL, /* fetch overview */ ++ NIL, /* fetch message structure */ ++ maildir_header, /* fetch message header */ ++ maildir_text, /* fetch message body */ ++ NIL, /* fetch partial message text */ ++ NIL, /* unique identifier */ ++ NIL, /* message number */ ++ NIL, /* modify flags */ ++ maildir_flagmsg, /* per-message modify flags */ ++ NIL, /* search for message based on criteria */ ++ NIL, /* sort messages */ ++ NIL, /* thread messages */ ++ maildir_ping, /* ping mailbox to see if still alive */ ++ maildir_check, /* check for new messages */ ++ maildir_expunge, /* expunge deleted messages */ ++ maildir_copy, /* copy messages to another mailbox */ ++ maildir_append, /* append string message to mailbox */ ++ NIL /* garbage collect stream */ ++ }; ++ ++ ++ DRIVER courierdriver = { ++ "mc", /* Why a separate driver? So that createproto will work */ ++ DR_MAIL|DR_LOCAL|DR_NAMESPACE|DR_DIRFMT, /* driver flags */ ++ (DRIVER *) NIL, /* next driver */ ++ maildir_valid, /* mailbox is valid for us */ ++ maildir_parameters, /* manipulate parameters */ ++ NIL, /* scan mailboxes */ ++ courier_list, /* find mailboxes */ ++ maildir_lsub, /* find subscribed mailboxes */ ++ maildir_sub, /* subscribe to mailbox */ ++ maildir_unsub, /* unsubscribe from mailbox */ ++ maildir_create, /* create mailbox */ ++ maildir_delete, /* delete mailbox */ ++ maildir_rename, /* rename mailbox */ ++ mail_status_default, /* status of mailbox */ ++ maildir_open, /* open mailbox */ ++ maildir_close, /* close mailbox */ ++ maildir_fast, /* fetch message "fast" attributes */ ++ NIL, /* fetch message flags */ ++ NIL, /* fetch overview */ ++ NIL, /* fetch message structure */ ++ maildir_header, /* fetch message header */ ++ maildir_text, /* fetch message body */ ++ NIL, /* fetch partial message text */ ++ NIL, /* unique identifier */ ++ NIL, /* message number */ ++ NIL, /* modify flags */ ++ maildir_flagmsg, /* per-message modify flags */ ++ NIL, /* search for message based on criteria */ ++ NIL, /* sort messages */ ++ NIL, /* thread messages */ ++ maildir_ping, /* ping mailbox to see if still alive */ ++ maildir_check, /* check for new messages */ ++ maildir_expunge, /* expunge deleted messages */ ++ maildir_copy, /* copy messages to another mailbox */ ++ maildir_append, /* append string message to mailbox */ ++ NIL /* garbage collect stream */ ++ }; ++ ++ MAILSTREAM maildirproto = {&maildirdriver}; /* prototype stream */ ++ MAILSTREAM courierproto = {&courierdriver}; /* prototype stream */ ++ ++ long maildir_dirfmttest (char *name) ++ { ++ int i; ++ for (i = 0; mdstruct[i] && strcmp(name, mdstruct[i]); i++); ++ return (i < EndDir) || !strcmp(name, MDDIR) ++ || !strncmp(name, MDUIDLAST, strlen(MDUIDLAST)) ++ || !strncmp(name, MDUIDTEMP, strlen(MDUIDTEMP)) ? LONGT : NIL; ++ } ++ ++ void ++ md_domain_name(void) ++ { ++ int i, j; ++ ++ strcpy(mdlocaldomain, mylocalhost ()); ++ for (i = 0; mdlocaldomain[i] != '\0' ;) ++ if(mdlocaldomain[i] == '/' || mdlocaldomain[i] == ':'){ ++ for(j = strlen(mdlocaldomain); j >= i; j--) ++ mdlocaldomain[j+4] = mdlocaldomain[j]; ++ mdlocaldomain[i++] = '\\'; ++ mdlocaldomain[i++] = '0'; ++ if(mdlocaldomain[i] == '/'){ ++ mdlocaldomain[i++] = '5'; ++ mdlocaldomain[i++] = '7'; ++ } else { ++ mdlocaldomain[i++] = '7'; ++ mdlocaldomain[i++] = '2'; ++ } + } + else -+ strcpy (err, "Can't create mailbox: mailbox already exists"); -+ } -+ else{ -+ if(create_dir) -+ strcpy(err, "Can not create directory. Cread folder instead"); -+ else -+ err[0] = '\0'; -+ } -+ if(err[0]){ -+ mm_log (err,ERROR); -+ return NIL; -+ } -+ } -+ -+ fnlen = strlen(tmp); -+ if ((s = strrchr(mailbox,MDSEPARATOR(courier))) != NULL){ -+ c = *++s; -+ *s = '\0'; -+ if ((stat(tmp,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) && -+ !maildir_create_work (mailbox, ++loop)) -+ return NIL; -+ *s = c; -+ } -+ tmp[fnlen] = '\0'; -+ -+ if (mkdir(tmp,0700) && errno != EEXIST) -+ return NIL; -+ -+ if (create_dir) -+ mailbox[fnlen] = '/'; -+ -+ if (create_dir){ -+ if(style == CCLIENT){ -+ if(!courier){ -+ FILE *fp = NULL; -+ snprintf(tmp2, sizeof(tmp2), "%s%s", tmp, MDDIR); -+ if ((fp = fopen(tmp2,"w")) == NULL){ -+ snprintf (err, sizeof(err), "Problem creating %s: %s", tmp2, strerror(errno)); -+ mm_log (err,ERROR); -+ return NIL; -+ } -+ fclose(fp); -+ } -+ } -+ return T; -+ } -+ else -+ return maildir_create_folder(tmp); -+} -+ -+long maildir_create (MAILSTREAM *stream,char *mailbox) -+{ -+ char tmp[MAILTMPLEN], err[MAILTMPLEN]; -+ int rv, create_dir; -+ -+ create_dir = mailbox ? -+ (mailbox[strlen(mailbox) - 1] == -+ MDSEPARATOR(IS_COURIER(mailbox))) : 0; -+ maildir_file_path(mailbox, tmp, sizeof(tmp)); -+ strcpy(tmp, mailbox); -+ rv = maildir_create_work(mailbox, 0); -+ strcpy(mailbox, tmp); -+ if (rv == 0){ -+ snprintf (err, sizeof(err), "Can't create %s %s", -+ (create_dir ? "directory" : "mailbox"), mailbox); -+ mm_log (err,ERROR); -+ } -+ return rv ? LONGT : NIL; -+} -+ -+#define MAXTRY 10000 -+void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt) -+{ -+ char oldfile[MAILTMPLEN],newfile[MAILTMPLEN],fn[MAILTMPLEN]; -+ char *s; -+ int ren, try = 0; -+ -+ if (elt->valid){ -+ for (try = 1; try > 0 && try < MAXTRY; try++){ -+ /* build the new filename */ -+ snprintf (oldfile, sizeof(oldfile), "%s/%s",LOCAL->path[Cur], MDFILE(elt)); -+ fn[0] = '\0'; -+ if ((ren = maildir_message_exists(stream, MDFILE(elt), fn)) == 0){ -+ errno = ENOENT; -+ try = MAXTRY; -+ } -+ if (*fn) /* new oldfile! */ -+ snprintf (oldfile,sizeof(oldfile),"%s/%s", LOCAL->path[Cur], fn); -+ if ((s = strrchr (MDFILE(elt), FLAGSEP))) *s = '\0'; -+ snprintf (fn, sizeof(fn), "%s%s%s%s%s%s%s", MDFILE(elt), MDSEP(2), -+ MDFLAG(Draft, elt->draft), MDFLAG(Flagged, elt->flagged), -+ MDFLAG(Replied, elt->answered), MDFLAG(Seen, elt->seen), -+ MDFLAG(Trashed, elt->deleted)); -+ snprintf (newfile, sizeof(newfile), "%s/%s",LOCAL->path[Cur],fn); -+ if (ren != 0 && rename (oldfile,newfile) >= 0) -+ try = -1; -+ } -+ -+ if (try > 0){ -+ snprintf(oldfile, sizeof(oldfile), "Unable to write flags to disk: %s", -+ (errno == ENOENT) ? "message is gone!" : strerror (errno)); -+ mm_log(oldfile,ERROR); -+ return; -+ } -+#ifdef __CYGWIN__ -+ utime(LOCAL->path[Cur], NIL); /* make sure next scan will catch the change */ -+#endif -+ maildir_free_file_only ((void **) &elt->private.spare.ptr); -+ MDFILE(elt) = cpystr (fn); -+ } -+} -+ -+long maildir_expunge (MAILSTREAM *stream, char *sequence, long options) -+{ -+ long ret; -+ MESSAGECACHE *elt; -+ unsigned long i, n = 0L; -+ unsigned long recent = stream->recent; -+ char tmp[MAILTMPLEN]; -+ -+ mm_critical (stream); /* go critical */ -+ ret = sequence ? ((options & EX_UID) ? -+ mail_uid_sequence (stream,sequence) : -+ mail_sequence (stream,sequence)) : LONGT; -+ if(ret == 0L) -+ return 0L; -+ for (i = 1L; i <= stream->nmsgs;){ -+ elt = mail_elt (stream,i); -+ if (elt->deleted && (sequence ? elt->sequence : T)){ -+ snprintf (tmp, sizeof(tmp), "%s/%s", LOCAL->path[Cur], MDFILE(elt)); -+ if (unlink (tmp) < 0) {/* try to delete the message */ -+ snprintf (tmp, sizeof(tmp), "Expunge of message %ld failed, aborted: %s",i, -+ strerror (errno)); -+ if (!stream->silent) -+ mm_log (tmp,WARN); -+ break; -+ } -+ if (elt->private.spare.ptr) -+ maildir_free_file ((void **) &elt->private.spare.ptr); -+ if (elt->recent) --recent;/* if recent, note one less recent message */ -+ mail_expunged (stream,i); /* notify upper levels */ -+ n++; /* count up one more expunged message */ -+ } -+ else i++; -+ } -+ if(n){ /* output the news if any expunged */ -+ snprintf (tmp, sizeof(tmp), "Expunged %ld messages", n); -+ if (!stream->silent) -+ mm_log (tmp,(long) NIL); -+ } -+ else -+ if (!stream->silent) -+ mm_log ("No messages deleted, so no update needed",(long) NIL); -+ mm_nocritical (stream); /* release critical */ -+ /* notify upper level of new mailbox size */ -+ mail_exists (stream, stream->nmsgs); -+ mail_recent (stream, recent); -+ return ret; -+} -+ -+long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options) -+{ -+ STRING st; -+ MESSAGECACHE *elt; -+ unsigned long len; -+ int fd; -+ unsigned long i; -+ struct stat sbuf; -+ char tmp[MAILTMPLEN], flags[MAILTMPLEN], path[MAILTMPLEN], *s; -+ /* copy the messages */ -+ if ((options & CP_UID) ? mail_uid_sequence (stream, sequence) : -+ mail_sequence (stream,sequence)) -+ for (i = 1L; i <= stream->nmsgs; i++) -+ if ((elt = mail_elt (stream,i))->sequence){ -+ MSGPATH(path, LOCAL->dir, MDFILE(elt), MDLOC(elt)); -+ if (((fd = open (path,O_RDONLY,NIL)) < 0) -+ ||((!elt->rfc822_size && -+ ((stat(path, &sbuf) < 0) || !S_ISREG (sbuf.st_mode))))) -+ return NIL; -+ if(!elt->rfc822_size) -+ MDSIZE(elt) = sbuf.st_size; -+ s = (char *) fs_get(MDSIZE(elt) + 1); -+ read (fd,s,MDSIZE(elt)); -+ s[MDSIZE(elt)] = '\0'; -+ close (fd); -+ len = strcrlfcpy (&LOCAL->buf,&LOCAL->buflen, s, MDSIZE(elt)); -+ INIT (&st,mail_string, LOCAL->buf, len); -+ elt->rfc822_size = len; -+ fs_give ((void **)&s); -+ -+ flags[0] = flags[1] = '\0'; -+ if (elt->seen) strcat (flags," \\Seen"); -+ if (elt->draft) strcat (flags," \\Draft"); -+ if (elt->deleted) strcat (flags," \\Deleted"); -+ if (elt->flagged) strcat (flags," \\Flagged"); -+ if (elt->answered) strcat (flags," \\Answered"); -+ flags[0] = '('; /* open list */ -+ strcat (flags,")"); /* close list */ -+ mail_date (tmp,elt); /* generate internal date */ -+ if (!mail_append_full (NIL, mailbox, flags, tmp, &st)) -+ return NIL; -+ if (options & CP_MOVE) elt->deleted = T; -+ } -+ return LONGT; /* return success */ -+} -+ -+long maildir_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data) -+{ -+ int fd, k, done, fail; -+ STRING *message; -+ char c,*s, *flags, *date; -+ char tmp[MAILTMPLEN],file[MAILTMPLEN],path1[MAILTMPLEN],path2[MAILTMPLEN]; -+ MESSAGECACHE elt; -+ long i, size = 0L, ret = LONGT, f; -+ unsigned long uf, ti; -+ static unsigned int transact = 0; -+ struct stat sbuf; -+ -+ if (!maildir_valid(mailbox)) { -+ snprintf (tmp, sizeof(tmp), "Not a valid Maildir mailbox: %s", mailbox); -+ mm_log (tmp,ERROR); -+ return NIL; -+ } -+ -+ if (!*mdlocaldomain) -+ md_domain_name(); /* get domain name for maildir files in mdlocaldomain now! */ -+ -+ if (mypid == (pid_t) 0) -+ mypid = getpid(); -+ -+ if (!stream){ -+ stream = &maildirproto; -+ -+ for (k = 0; k < NUSERFLAGS && stream->user_flags[k]; ++k) -+ fs_give ((void **) &stream->user_flags[k]); ++ i++; + } -+ -+ if (!(*af)(stream, data, &flags, &date, &message)) return NIL; -+ -+ mm_critical (stream); /* go critical */ -+ do { -+ fail = done = 0; /* we have not determined name of message file yet */ -+ if (!SIZE (message)) { /* guard against zero-length */ -+ mm_log ("Append of zero-length message", ERROR); -+ ret = NIL; -+ break; -+ } -+ -+ if (date && !mail_parse_date(&elt,date)){ -+ snprintf (tmp, sizeof(tmp), "Bad date in append: %.80s", date); -+ mm_log (tmp, ERROR); -+ ret = NIL; -+ break; -+ } -+ -+ if(date){ -+ struct tm tm; -+ -+ tm.tm_sec = elt.seconds; -+ tm.tm_min = elt.minutes; -+ tm.tm_hour = elt.hours; -+ tm.tm_mday = elt.day; -+ tm.tm_mon = elt.month - 1; -+ tm.tm_year = BASEYEAR + elt.year - 1900; -+ -+ ti = mktime(&tm); -+ } else ti = time(0); -+ -+ f = mail_parse_flags (stream,flags,&uf); -+ do { -+ /* build file name we will use */ -+ snprintf (file, sizeof(file), "%lu.%d_%09u.%s%s%s%s%s%s", -+ ti, mypid, transact++, mdlocaldomain, (f ? MDSEP(2) : ""), -+ MDFLAG(Draft, f&fDRAFT), MDFLAG(Flagged, f&fFLAGGED), -+ MDFLAG(Replied, f&fANSWERED), MDFLAG(Seen, f&fSEEN)); -+ /* build tmp file name */ -+ if (maildir_file_path(mailbox, tmp, sizeof(tmp))) /* copy in TMP */ -+ MSGPATH(path1, tmp, file, Tmp); -+ /* build final filename to use */ -+ if (maildir_file_path(mailbox, tmp, sizeof(tmp))) -+ MSGPATH(path2, tmp, file, New); /* copy in NEW */ -+ if(stat(path1, &sbuf) < 0 && errno == ENOENT -+ && stat(path2, &sbuf) < 0 && errno == ENOENT) -+ done++; -+ else -+ fail++; -+ if(fail == 1000){ -+ snprintf (tmp, sizeof(tmp), "Failure to create append message name"); -+ mm_log (tmp, ERROR); -+ return NIL; -+ } -+ } while (done == 0); -+ -+ if ((fd = open (path1,O_WRONLY|O_CREAT|O_EXCL,S_IREAD|S_IWRITE)) < 0) { -+ snprintf (tmp, sizeof(tmp), "Can't open append mailbox: %s", strerror (errno)); -+ mm_log (tmp, ERROR); -+ return NIL; -+ } -+ for (size = 0,i = SIZE (message),s = (char *) fs_get (i + 1); i; --i) -+ if ((c = SNX (message)) != '\015') s[size++] = c; -+ if ((write (fd, s, size) < 0) || fsync (fd)) { -+ unlink (path1); /* delete message */ -+ snprintf (tmp, sizeof(tmp), "Message append failed: %s", strerror (errno)); -+ mm_log (tmp, ERROR); -+ ret = NIL; -+ } -+ fs_give ((void **) &s); /* flush the buffer */ -+ close (fd); /* close the file */ -+ -+ if (rename (path1,path2) < 0) { -+ snprintf (tmp, sizeof(tmp), "Message append failed: %s", strerror (errno)); -+ mm_log (tmp, ERROR); -+ ret = NIL; -+ } -+ unlink (path1); -+ if(date){ -+ time_t tp[2]; -+ tp[0] = tp[1] = ti; -+ utime (path2,tp); -+ } -+ -+ if (ret) -+ if (!(*af) (stream,data,&flags,&date,&message)) ret = NIL; -+ -+ } while (ret && message); /* write the data */ -+ mm_nocritical (stream); /* release critical */ -+ return ret; -+} -+ -+long maildir_delete (MAILSTREAM *stream,char *mailbox) -+{ -+ DIR *dirp; -+ struct direct *d; -+ int i, remove_dir = 0, mddir = 0, rv, error = 0; -+ char tmp[MAILTMPLEN],tmp2[MAILTMPLEN], realname[MAILTMPLEN]; -+ struct stat sbuf; -+ int courier = IS_COURIER(mailbox); -+ -+ if (mailbox[strlen(mailbox) - 1] == MDSEPARATOR(courier)){ -+ remove_dir++; -+ mailbox[strlen(mailbox) -1] = '\0'; -+ } -+ -+ if (!maildir_valid(mailbox)){ -+ maildir_file_path(mailbox, tmp, sizeof(tmp)); -+ if (stat(tmp, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode)){ -+ snprintf(tmp, sizeof(tmp), "Can not remove %s", mailbox); -+ error++; -+ } -+ } -+ -+ if (!error && remove_dir && !maildir_dir_is_empty(mailbox)){ -+ snprintf(tmp, sizeof(tmp), "Can not remove directory %s/: directory not empty", mailbox); -+ error++; -+ } -+ -+ if(error){ -+ mm_log (tmp,ERROR); -+ return NIL; -+ } -+ -+ maildir_close(stream,0); /* even if stream was NULL */ -+ -+ maildir_file_path(mailbox, realname, sizeof(realname)); -+ -+ if (remove_dir){ -+ snprintf(tmp, sizeof(tmp), "%s/%s", realname, MDDIR); -+ if ((rv = stat (tmp,&sbuf)) == 0 && S_ISREG(sbuf.st_mode)) -+ rv = unlink(tmp); -+ else if (errno == ENOENT) -+ rv = 0; -+ if (rv != 0){ -+ snprintf(tmp, sizeof(tmp), "Can not remove %s/%s: %s", tmp2, MDDIR, strerror(errno)); -+ mm_log (tmp,ERROR); -+ return NIL; -+ } -+ if (!maildir_valid(realname) && rmdir(realname) != 0){ -+ snprintf(tmp, sizeof(tmp), "Can not remove %s/: %s", mailbox, strerror(errno)); -+ mm_log (tmp, ERROR); -+ return NIL; -+ } -+ return LONGT; -+ } -+ /* else remove just the folder. Remove all hidden files, except MDDIR */ -+ for (i = Cur; i != EndDir; i++){ -+ MDFLD(tmp, realname, i); -+ -+ if (!(dirp = opendir (tmp))){ -+ snprintf(tmp, sizeof(tmp), "Can not read %s/: %s", mailbox, strerror(errno)); -+ mm_log (tmp, ERROR); -+ return NIL; -+ } -+ -+ while ((d = readdir(dirp)) != NULL){ -+ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..")){ -+ snprintf(tmp2, sizeof(tmp2), "%s/%s", tmp, d->d_name); -+ if (unlink(tmp2) != 0){ -+ snprintf(tmp2, sizeof(tmp2), "Can not remove %s: %s", mailbox, strerror(errno)); -+ mm_log (tmp2, ERROR); -+ return NIL; -+ } -+ } -+ } -+ closedir(dirp); -+ if (rmdir(tmp) != 0){ -+ snprintf(tmp, sizeof(tmp), "Can not remove %s: %s", mailbox, strerror(errno)); -+ mm_log (tmp, ERROR); -+ return NIL; -+ } -+ } -+ /* -+ * ok we have removed all subdirectories of the folder mailbox, Remove the -+ * hidden files. -+ */ -+ -+ if(!(dirp = opendir (realname))){ -+ snprintf(tmp, sizeof(tmp), "Can not read %s/: %s", realname, strerror(errno)); -+ mm_log (tmp, ERROR); -+ return NIL; -+ } -+ -+ while ((d = readdir(dirp)) != NULL){ -+ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..") -+ && (!strcmp(d->d_name, MDDIR) -+ || !strncmp(d->d_name, MDUIDLAST, strlen(MDUIDLAST)) -+ || !strncmp(d->d_name, MDUIDTEMP, strlen(MDUIDTEMP)))){ -+ if(strcmp(d->d_name, MDDIR) == 0) -+ mddir++; -+ snprintf(tmp, sizeof(tmp), "%s/%s", realname, d->d_name); -+ if (unlink(tmp) != 0) -+ error++; -+ } -+ } -+ closedir(dirp); -+ if (error || -+ (maildir_dir_is_empty(mailbox) && mddir == 0 && rmdir(realname) < 0)){ -+ snprintf(tmp, sizeof(tmp), "Can not remove folder %s: %s", mailbox, strerror(errno)); -+ mm_log (tmp, ERROR); -+ return NIL; -+ } -+ return LONGT; -+} -+ -+long maildir_rename (MAILSTREAM *stream, char *old, char *new) -+{ -+ char tmp[MAILTMPLEN], tmpnew[MAILTMPLEN], realold[MAILTMPLEN]; -+ char realnew[MAILTMPLEN]; -+ int courier = IS_COURIER(old) && IS_COURIER(new); -+ int i; -+ long rv = LONGT; -+ COURIER_S *cdir; -+ -+ if((IS_COURIER(old) || IS_COURIER(new)) && !courier){ -+ snprintf (tmp, sizeof(tmp), "Can't rename mailbox %s to %s", old, new); -+ mm_log (tmp, ERROR); -+ return NIL; -+ } -+ -+ if (!maildir_valid(old)){ -+ snprintf (tmp, sizeof(tmp), "Can't rename mailbox %s: folder not in maildir format",old); -+ mm_log (tmp, ERROR); -+ return NIL; -+ } -+ maildir_file_path(old, realold, sizeof(realold)); -+ if (!maildir_valid_name(new) && new[0] == '#'){ -+ snprintf (tmp, sizeof(tmp), "Cannot rename mailbox %s: folder not in maildir format", new); -+ mm_log (tmp, ERROR); -+ return NIL; -+ } -+ maildir_file_path(new, realnew, sizeof(realnew)); -+ if (access(tmpnew,F_OK) == 0){ /* new mailbox name must not exist */ -+ snprintf (tmp, sizeof(tmp), "Cannot rename to mailbox %s: destination already exists", new); -+ mm_log (tmp, ERROR); -+ return NIL; -+ } -+ -+ if(!courier){ -+ if (rename(realold, realnew)){ /* try to rename the directory */ -+ snprintf(tmp, sizeof(tmp), "Can't rename mailbox %s to %s: %s", old, new, -+ strerror(errno)); -+ mm_log(tmp,ERROR); -+ return NIL; -+ } -+ return LONGT; /* return success */ -+ } -+ -+ cdir = courier_list_dir(old); -+ for (i = 0; cdir && i < cdir->total; i++){ -+ if(strstr(cdir->data[i]->name, old)){ -+ snprintf(tmp, sizeof(tmp), "%s%s", new, cdir->data[i]->name+strlen(old)); -+ maildir_file_path(cdir->data[i]->name, realold, sizeof(realold)); -+ maildir_file_path(tmp, realnew, sizeof(realnew)); -+ if (rename(realold, realnew)){ -+ snprintf (tmp, sizeof(tmp), "Can't rename mailbox %s to %s: %s", old, new, -+ strerror(errno)); -+ mm_log(tmp,ERROR); -+ rv = NIL; -+ } -+ } -+ } -+ courier_free_cdir(&cdir); -+ return rv; -+} -+ -+long maildir_sub(MAILSTREAM *stream,char *mailbox) -+{ -+ return sm_subscribe(mailbox); -+} -+ -+long maildir_unsub(MAILSTREAM *stream,char *mailbox) -+{ -+ return sm_unsubscribe(mailbox); -+} -+ -+void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat) -+{ -+ void *sdb = NIL; -+ char *s, test[MAILTMPLEN], tmp[MAILTMPLEN]; -+ /* get canonical form of name */ -+ if (maildir_canonicalize (test, ref, pat) && (s = sm_read (tmp, &sdb))) { -+ do if (pmatch_full (s, test, '/')) mm_lsub (stream, '/', s, NIL); -+ while ((s = sm_read (tmp, &sdb)) != NULL); /* until no more subscriptions */ -+ } -+} -+ -+long maildir_canonicalize (char *pattern,char *ref,char *pat) -+{ -+ if (ref && *ref) { /* have a reference */ -+ strcpy (pattern,ref); /* copy reference to pattern */ -+ /* # overrides mailbox field in reference */ -+ if (*pat == '#') strcpy (pattern,pat); -+ /* pattern starts, reference ends, with / */ -+ else if ((*pat == '/') && (pattern[strlen (pattern) - 1] == '/')) -+ strcat (pattern,pat + 1); /* append, omitting one of the period */ -+ -+ else strcat (pattern,pat); /* anything else is just appended */ -+ } -+ else strcpy (pattern,pat); /* just have basic name */ -+ return maildir_valid_name(pattern) ? LONGT : NIL; -+} -+ -+void maildir_list_work (MAILSTREAM *stream,char *dir,char *pat,long level) -+{ -+ DIR *dp; -+ struct direct *d; -+ struct stat sbuf; -+ char curdir[MAILTMPLEN],name[MAILTMPLEN], tmp[MAILTMPLEN]; -+ char realpat[MAILTMPLEN]; -+ long i; -+ char *maildirpath = mdirpath(); -+ -+ snprintf(curdir, sizeof(curdir), "%s/%s/", myrootdir(pat), dir ? dir : maildirpath); -+ if ((dp = opendir (curdir)) != NULL){ -+ if (dir) snprintf (name, sizeof(name), "%s%s/",MDPREFIX(CCLIENT),dir); -+ else strcpy (name, pat); -+ -+ if (level == 0 && !strpbrk(pat,"%*")){ -+ if(maildir_valid(pat)){ -+ i = maildir_contains_folder(pat, NULL) -+ ? LATT_HASCHILDREN -+ : (maildir_is_dir(pat, NULL) -+ ? LATT_HASNOCHILDREN : LATT_NOINFERIORS); -+ maildir_file_path(pat, realpat, sizeof(realpat)); -+ i += maildir_any_new_msgs(realpat) -+ ? LATT_MARKED : LATT_UNMARKED; -+ mm_list (stream,'/', pat, i); -+ } -+ else -+ if(pat[strlen(pat) - 1] == '/') -+ mm_list (stream,'/', pat, LATT_NOSELECT); -+ } -+ -+ while ((d = readdir (dp)) != NULL) -+ if(strcmp(d->d_name, ".") && strcmp(d->d_name,"..") -+ && strcmp(d->d_name, MDNAME(Cur)) -+ && strcmp(d->d_name, MDNAME(Tmp)) -+ && strcmp(d->d_name, MDNAME(New))){ -+ -+ if (dir) snprintf (tmp, sizeof(tmp), "%s%s", name,d->d_name); -+ else strcpy(tmp, d->d_name); -+ -+ if(pmatch_full (tmp, pat,'/')){ -+ snprintf(tmp, sizeof(tmp), "%s/%s/%s", myrootdir(d->d_name), -+ (dir ? dir : maildirpath), d->d_name); -+ if(stat (tmp,&sbuf) == 0 -+ && ((sbuf.st_mode & S_IFMT) == S_IFDIR)){ -+ if (dir) snprintf (tmp, sizeof(tmp), "%s%s", name,d->d_name); -+ else strcpy(tmp, d->d_name); -+ i = maildir_valid(tmp) -+ ? (maildir_contains_folder(dir, d->d_name) -+ ? LATT_HASCHILDREN -+ : (maildir_is_dir(dir, d->d_name) -+ ? LATT_HASNOCHILDREN : LATT_NOINFERIORS)) -+ : LATT_NOSELECT; -+ i += maildir_any_new_msgs(tmp) -+ ? LATT_MARKED : LATT_UNMARKED; -+ mm_list (stream,'/',tmp, i); -+ strcat (tmp, "/"); -+ if(dmatch (tmp, pat,'/') && -+ (level < (long) mail_parameters (NIL,GET_LISTMAXLEVEL,NIL))){ -+ snprintf(tmp, sizeof(tmp), "%s/%s",dir,d->d_name); -+ maildir_list_work (stream,tmp,pat,level+1); -+ } -+ } -+ } -+ } -+ closedir (dp); -+ } -+} -+ -+void courier_list_work (MAILSTREAM *stream, char *dir, char *pat, long level) -+{ -+ char c, curdir[MAILTMPLEN], tmp[MAILTMPLEN]; -+ char realname[MAILTMPLEN], realpat[MAILTMPLEN] = {'\0'}; -+ int i, found; -+ long style = *(long *) maildir_parameters(GET_COURIERSTYLE, NIL), j; -+ char *maildirpath = mdirpath(); -+ COURIER_S *cdir; -+ -+ if(!strpbrk(pat,"%*")){ /* a mailbox */ -+ maildir_file_path(pat, curdir, sizeof(curdir)); -+ i = strlen(curdir) - 1; -+ if(curdir[i] == '/') -+ curdir[i] = '\0'; -+ cdir = courier_list_dir(curdir); -+ if(cdir){ -+ found = 0; j = 0L; -+ if(maildir_valid_name(pat)){ -+ for(i = 0; !found && i < cdir->total; i++) -+ if(strstr(curdir, cdir->data[i]->name)){ -+ if(strlen(curdir) < strlen(cdir->data[i]->name)) -+ found += 2; -+ else if(strlen(curdir) == strlen(cdir->data[i]->name)) -+ found -= 1; -+ } -+ if(found > 0) -+ j = LATT_HASCHILDREN; -+ else if(found == 0) -+ j = (style == COURIER) ? LATT_HASNOCHILDREN : LATT_NOINFERIORS; -+ } -+ else -+ j = LATT_NOSELECT; -+ j += maildir_any_new_msgs(curdir) ? LATT_MARKED : LATT_UNMARKED; -+ if (found) -+ mm_list (stream, '.', pat, j); -+ courier_free_cdir(&cdir); -+ } -+ return; -+ } -+ -+ strcpy(tmp,pat + 4); /* a directory */ -+ j = strlen(pat) - 1; -+ maildir_file_path(pat, realpat, sizeof(realpat)); -+ c = pat[j]; -+ pat[j] = '\0'; -+ realname[0] = '\0'; -+ if(dir) -+ maildir_file_path(dir, realname, sizeof(realname)); -+ snprintf(curdir, sizeof(curdir), "%s%s%s/%s", (dir ? "" : myrootdir(pat)), (dir ? "" : "/"), -+ (dir ? realname : maildirpath), (dir ? "" : ".")); -+ snprintf(tmp, sizeof(tmp), "%s%s/.", MDPREFIX(COURIER), dir ? dir : maildirpath); -+ if (level == 0 && tmp && pmatch_full (tmp, realpat, '.')) -+ mm_list (stream,'.', tmp, LATT_NOSELECT); -+ -+ cdir = courier_list_dir(pat); -+ pat[j] = c; -+ for (i = 0; cdir && i < cdir->total; i++) -+ if(pmatch_full (cdir->data[i]->name, pat, '.')){ -+ snprintf(tmp, sizeof(tmp), "%s.", cdir->data[i]->name); -+ courier_list_info(&cdir, tmp, i); -+ mm_list (stream,'.',cdir->data[i]->name, cdir->data[i]->attribute); -+ } -+ courier_free_cdir(&cdir); -+} -+ -+int -+same_maildir_file(char *name1, char *name2) -+{ -+ char tmp1[MAILTMPLEN], tmp2[MAILTMPLEN]; -+ char *s; -+ -+ strcpy(tmp1, name1 ? name1 : ""); -+ strcpy(tmp2, name2 ? name2 : ""); -+ if ((s = strrchr(tmp1, FLAGSEP)) != NULL) -+ *s = '\0'; -+ if (((s = strrchr(tmp1, SIZESEP)) != NULL) && (strchr(s,'.') == NULL)) -+ *s = '\0'; -+ if ((s = strrchr(tmp2, FLAGSEP)) != NULL) -+ *s = '\0'; -+ if (((s = strrchr(tmp2, SIZESEP)) != NULL) && (strchr(s,'.') == NULL)) -+ *s = '\0'; -+ -+ return !strcmp(tmp1, tmp2); -+} -+ -+unsigned long antoul(char *seed) -+{ -+ int i, error = 0; -+ unsigned long val = 0L, rv1 = 0L, t; -+ char c, *p; -+ if(!seed) -+ return 0L; -+ t = strtoul(seed, &p, 10); -+ if(p && (*p == '.' || *p == '_')) -+ return t; -+ /* else */ -+ if((p = strchr(seed,'.')) != NULL) -+ *p = '\0'; -+ error = (strlen(seed) > 6); /* too long */ -+ for(i= strlen(seed)-1; error == 0 && i >= 0; i--){ -+ c = seed[i]; -+ if (c >= 'A' && c <= 'Z') val = c - 'A'; -+ else if (c >= 'a' && c <= 'z') val = c - 'a' + 26; -+ else if (c >= '0' && c <= '9') val = c - '0' + 26 + 26; -+ else if (c == '-') val = c - '-' + 26 + 26 + 10; -+ else if (c == '_') val = c - '_' + 26 + 26 + 10 + 1; -+ else error++; -+ rv1 = val + (rv1 << 6); ++ ++ char * ++ myrootdir(char *name) ++ { ++ return myhomedir(); + } -+ if(p) -+ *p = '.'; -+ return error ? 0L : rv1; -+} -+ -+unsigned long mdfntoul (char *name) -+{ -+ unsigned long t; -+ char *r, last; -+ -+ if((*name == '_') && ((r = strpbrk(name,".,%+")) != NULL)){ /* Grrr!!! */ -+ last = *r; -+ *r = '\0'; -+ t = antoul(r+1); -+ *r = last; -+ } -+ else -+ t = antoul(name); -+ return t; -+} -+ -+int comp_maildir_file(char *name1, char *name2) -+{ -+ int uset1 = 1, uset2 = 1, i, j, cmp; -+ unsigned long t1, t2; -+ char *s1, *s2; -+ -+ if (!(name1 && *name1)) -+ return (name2 && *name2) ? (*name2 == FLAGSEP ? 0 : -1) : 0; -+ -+ if (!(name2 && *name2)) -+ return (name1 && *name1) ? (*name1 == FLAGSEP ? 0 : 1) : 0; -+ -+ if((cmp = strcmp(name1,name2)) == 0) -+ return 0; -+ -+ t1 = strtoul(name1, &s1, 10); -+ t2 = strtoul(name2, &s2, 10); -+ -+ if(!s1 || *s1 != '.') -+ uset1 = 0; -+ -+ if(!s2 || *s2 != '.') -+ uset2 = 0; -+ -+ if(uset1 && uset2) /* normal sort order */ -+ return (t1 < t2) ? -1 : (t1 > t2 ? 1 : (cmp < 0 ? -1 : 1)); -+ -+ /* If we make it here we say Grrrr.... first, then we try to figure out -+ * how to sort this mess. -+ * These are the rules. -+ * If there is a number at the beginning it is bigger than anything else. -+ * If there are digits, then the number of digits decides which one is bigger. -+ */ -+ -+ for(i = 0; isdigit(name1[i]); i++); -+ for(j = 0; isdigit(name2[j]); j++); -+ -+ return(uset1 ? 1 -+ : (uset2 ? -1 -+ : (i < j ? -1 : (i > j ? 1 : (cmp < 0 ? -1 : 1))))); -+} -+ -+void -+maildir_getflag(char *name, int *d, int *f, int *r ,int *s, int *t) -+{ -+ char tmp[MAILTMPLEN], *b; -+ int offset = 0; -+ int tmpd, tmpf, tmpr, tmps, tmpt; -+ -+ if(d) *d = 0; -+ if(f) *f = 0; -+ if(r) *r = 0; -+ if(s) *s = 0; -+ if(t) *t = 0; -+ -+ tmpd = tmpf = tmpr = tmps = tmpt = NIL; /* no flags set by default */ -+ strcpy(tmp,name); -+ while ((b = strrchr(tmp+offset, FLAGSEP)) != NULL){ -+ char flag,last; -+ int k; -+ if (!++b) break; -+ switch (*b){ -+ case '1': -+ case '2': -+ case '3': flag = *b; b += 2; -+ for (k = 0; b[k] && b[k] != FLAGSEP && b[k] != ','; k++); -+ last = b[k]; -+ b[k] = '\0'; -+ if (flag == '2' || flag == '3'){ -+ tmpd = strchr (b, MDFLAGC(Draft)) ? T : NIL; -+ tmpf = strchr (b, MDFLAGC(Flagged)) ? T : NIL; -+ tmpr = strchr (b, MDFLAGC(Replied)) ? T : NIL; -+ tmps = strchr (b, MDFLAGC(Seen)) ? T : NIL; -+ tmpt = strchr (b, MDFLAGC(Trashed)) ? T : NIL; -+ } -+ b[k] = last; -+ b += k; -+ for (; tmp[offset] && tmp[offset] != FLAGSEP; offset++); -+ offset++; -+ break; -+ default: break; /* Should we crash?... Nahhh */ -+ } -+ } -+ if(d) *d = tmpd; -+ if(f) *f = tmpf; -+ if(r) *r = tmpr; -+ if(s) *s = tmps; -+ if(t) *t = tmpt; -+} -+ -+int -+maildir_message_in_list(char *msgname, struct direct **names, -+ unsigned long bottom, unsigned long top, unsigned long *pos) -+{ -+ unsigned long middle = (bottom + top)/2; -+ int test; -+ -+ if (!msgname) -+ return NIL; -+ -+ if (pos) *pos = middle; -+ -+ if (same_maildir_file(msgname, names[middle]->d_name)) -+ return T; -+ -+ if (middle == bottom){ /* 0 <= 0 < 1 */ -+ int rv = NIL; -+ if (same_maildir_file(msgname, names[middle]->d_name)){ -+ rv = T; -+ if (pos) *pos = middle; -+ } -+ else -+ if (same_maildir_file(msgname, names[top]->d_name)){ -+ rv = T; -+ if (pos) *pos = top; -+ } -+ return rv; -+ } -+ -+ test = comp_maildir_file(msgname, names[middle]->d_name); -+ -+ if (top <= bottom) -+ return test ? NIL : T; -+ -+ if (test < 0 ) /* bottom < msgname < middle */ -+ return maildir_message_in_list(msgname, names, bottom, middle, pos); -+ else if (test > 0) /* middle < msgname < top */ -+ return maildir_message_in_list(msgname, names, middle, top, pos); -+ else return T; -+} -+ -+void -+maildir_abort(MAILSTREAM *stream) -+{ -+ if (LOCAL){ -+ DirNamesType i; -+ -+ if(LOCAL->candouid) -+ maildir_read_uid(stream, NULL, &stream->uid_validity); -+ if (LOCAL->dir) fs_give ((void **) &LOCAL->dir); -+ for (i = Cur; i < EndDir; i++) -+ if(LOCAL->path[i]) fs_give ((void **) &LOCAL->path[i]); -+ fs_give ((void **) &LOCAL->path); -+ if (LOCAL->buf) fs_give ((void **) &LOCAL->buf); -+ if(LOCAL->uidtempfile){ -+ unlink(LOCAL->uidtempfile); -+ fs_give ((void **) &LOCAL->uidtempfile); -+ } -+ fs_give ((void **) &stream->local); -+ } -+ if (mdfpath) fs_give((void **)&mdfpath); -+ stream->dtb = NIL; -+} -+ -+int -+maildir_contains_folder(char *dirname, char *name) -+{ -+ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN]; -+ int rv = 0; -+ DIR *dir; -+ struct direct *d; -+ -+ maildir_file_path(dirname, tmp2, sizeof(tmp2)); -+ if(name){ -+ strcat(tmp2,"/"); -+ strcat(tmp2, name); -+ } -+ -+ if (!(dir = opendir (tmp2))) -+ return NIL; -+ -+ while ((d = readdir(dir)) != NULL){ -+ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..") -+ && strcmp(d->d_name, MDNAME(Cur)) -+ && strcmp(d->d_name, MDNAME(Tmp)) -+ && strcmp(d->d_name, MDNAME(New))){ -+ -+ snprintf(tmp, sizeof(tmp), "%s/%s", tmp2, d->d_name); -+ if(maildir_valid(tmp)){ -+ rv++; -+ break; -+ } -+ } -+ } -+ closedir(dir); -+ return rv; -+} -+ -+int -+maildir_is_dir(char *dirname, char *name) -+{ -+ char tmp[MAILTMPLEN]; -+ struct stat sbuf; -+ -+ maildir_file_path(dirname, tmp, sizeof(tmp)); -+ if(name){ -+ strcat(tmp, "/"); -+ strcat(tmp, name); -+ } -+ strcat(tmp, "/"); -+ strcat(tmp, MDDIR); -+ -+ return ((stat(tmp, &sbuf) == 0) && S_ISREG (sbuf.st_mode)) ? 1 : 0; -+} -+ -+int -+maildir_dir_is_empty(char *mailbox) -+{ -+ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN], tmp3[MAILTMPLEN],*s; -+ int rv = 1, courier = IS_COURIER(mailbox); -+ DIR *dir; -+ struct direct *d; -+ struct stat sbuf; -+ -+ maildir_file_path(mailbox, tmp2, sizeof(tmp2)); -+ -+ if(courier){ -+ strcpy(tmp3, tmp2); -+ if(s = strrchr(tmp2, '/')) -+ *s = '\0'; -+ } -+ -+ if (!(dir = opendir (tmp2))) -+ return rv; -+ -+ if(courier){ -+ while((d = readdir(dir)) != NULL){ -+ snprintf(tmp, sizeof(tmp), "%s/%s", tmp2, d->d_name); -+ if(!strncmp(tmp, tmp3, strlen(tmp3)) -+ && tmp[strlen(tmp3)] == '.'){ -+ rv = 0; -+ break; -+ } -+ } -+ } -+ else -+ while ((d = readdir(dir)) != NULL){ -+ snprintf(tmp, sizeof(tmp), "%s/%s", tmp2, d->d_name); -+ if (strcmp(d->d_name, ".") -+ && strcmp(d->d_name,"..") -+ && strcmp(d->d_name, MDNAME(Cur)) -+ && strcmp(d->d_name, MDNAME(Tmp)) -+ && strcmp(d->d_name, MDNAME(New)) -+ && strcmp(d->d_name, MDDIR) -+ && strcmp(d->d_name, MDUIDVALIDITY) -+ && !(d->d_name[0] == '.' -+ && stat (tmp,&sbuf) == 0 -+ && S_ISREG(sbuf.st_mode))){ -+ rv = 0; -+ break; -+ } -+ } -+ closedir(dir); -+ return rv; -+} -+ -+void -+maildir_get_file (MAILDIRFILE **mdfile) -+{ -+ MAILDIRFILE *md; -+ -+ md = (MAILDIRFILE *) fs_get(sizeof(MAILDIRFILE)); -+ memset(md, 0, sizeof(MAILDIRFILE)); -+ *mdfile = md; -+} -+ -+void -+maildir_free_file (void **mdfile) -+{ -+ MAILDIRFILE *md = (mdfile && *mdfile) ? (MAILDIRFILE *) *mdfile : NULL; -+ -+ if (md){ -+ if (md->name) fs_give((void **)&md->name); -+ fs_give((void **)&md); -+ } -+} -+ -+void -+maildir_free_file_only (void **mdfile) -+{ -+ MAILDIRFILE *md = (mdfile && *mdfile) ? (MAILDIRFILE *) *mdfile : NULL; -+ -+ if (md && md->name) -+ fs_give((void **)&md->name); -+} -+ -+int -+maildir_any_new_msgs(char *mailbox) -+{ -+ char tmp[MAILTMPLEN]; -+ int rv = NIL; -+ DIR *dir; -+ struct direct *d; -+ -+ MDFLD(tmp, mailbox, New); -+ -+ if (!(dir = opendir (tmp))) -+ return rv; -+ -+ while ((d = readdir(dir)) != NULL){ -+ if (d->d_name[0] == '.') -+ continue; -+ rv = T; -+ break; -+ } -+ closedir(dir); -+ return rv; -+} -+ -+ -+void -+maildir_get_date(MAILSTREAM *stream, unsigned long msgno) -+{ -+ MESSAGECACHE *elt; -+ struct tm *t; -+ time_t ti; -+ int i,k; -+ -+ elt = mail_elt (stream,msgno); -+ if(elt && elt->year != 0) -+ return; -+ if ((ti = mdfntoul(MDFILE(elt))) > 0L && (t = gmtime(&ti))){ -+ i = t->tm_hour * 60 + t->tm_min; -+ k = t->tm_yday; -+ t = localtime(&ti); -+ i = t->tm_hour * 60 + t->tm_min - i; -+ if((k = t->tm_yday - k) != 0) -+ i += ((k < 0) == (abs (k) == 1)) ? -24*60 : 24*60; -+ k = abs (i); -+ elt->hours = t->tm_hour; -+ elt->minutes = t->tm_min; -+ elt->seconds = t->tm_sec; -+ elt->day = t->tm_mday; elt->month = t->tm_mon + 1; -+ elt->year = t->tm_year - (BASEYEAR - 1900); -+ elt->zoccident = (k == i) ? 0 : 1; -+ elt->zhours = k/60; -+ elt->zminutes = k % 60; -+ } -+} -+ -+/* Support for Courier Style directories -+ When this code is complete there will be two types of support, which -+ will be configurable. The problem is the following: In Courier style -+ folder structure, a "folder" may have a subfolder called -+ "folder.subfolder", which is not natural in the file system in the -+ sense that I can not stat for "folder.subfolder" wihtout knowing what -+ "subfolder" is. It needs to be guessed. Because of this I need to look -+ in the list of folders if there is a folder with a name -+ "folder.subfolder", before I can say if the folder is dual or not. One -+ can avoid this annoyance if one ignores the problem by declaring that -+ every folder is dual. I will however code as the default the more -+ complicated idea of scaning the containing directory each time it is -+ modified and search for subfolders, and list the entries it found. -+ */ -+ -+int courier_dir_select (const struct direct *name) -+{ -+ return name->d_name[0] == '.' && (strlen(name->d_name) > 2 -+ || (strlen(name->d_name) == 2 && name->d_name[1] != '.')); -+} -+ -+int courier_dir_sort (const struct direct **d1, const struct direct **d2) -+{ -+ const struct direct *e1 = *(const struct direct **) d1; -+ const struct direct *e2 = *(const struct direct **) d2; -+ -+ return strcmp((char *) e1->d_name, (char *) e2->d_name); -+} -+ -+void courier_free_cdir (COURIER_S **cdir) -+{ -+ int i; -+ -+ if (!*cdir) -+ return; -+ -+ if ((*cdir)->path) fs_give((void **)&((*cdir)->path)); -+ for (i = 0; i < (*cdir)->total; i++) -+ if((*cdir)->data[i]->name) fs_give((void **)&((*cdir)->data[i]->name)); -+ fs_give((void **)&((*cdir)->data)); -+ fs_give((void **)&(*cdir)); -+} -+ -+COURIER_S *courier_get_cdir (int total) -+{ -+ COURIER_S *cdir; -+ -+ cdir = (COURIER_S *)fs_get(sizeof(COURIER_S)); -+ memset(cdir, 0, sizeof(COURIER_S)); -+ cdir->data = (COURIERLOCAL **) fs_get(total*sizeof(COURIERLOCAL *)); -+ memset(cdir->data, 0, sizeof(COURIERLOCAL *)); -+ cdir->total = total; -+ return cdir; -+} -+ -+int courier_search_list(COURIERLOCAL **data, char *name, int first, int last) -+{ -+ int try = (first + last)/2; -+ -+ if(!strstr(data[try]->name, name)){ -+ if(first == try) /* first == last || first + 1 == last */ -+ return strstr(data[last]->name, name) ? 1 : 0; -+ if(strcmp(data[try]->name, name) < 0) /*data[try] < name < data[end] */ -+ return courier_search_list(data, name, try, last); -+ else /* data[begin] < name < data[try] */ -+ return courier_search_list(data, name, first, try); -+ } -+ return 1; -+} -+ -+/* Lists all directories that are subdirectories of a given directory */ -+ -+COURIER_S *courier_list_dir(char *curdir) -+{ -+ struct direct **names = NIL; -+ struct stat sbuf; -+ unsigned long ndir; -+ COURIER_S *cdir = NULL; -+ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN], pathname[MAILTMPLEN], -+ realname[MAILTMPLEN]; -+ int i, j, scand, td; -+ -+ /* There are two cases, either curdir is -+ #mc/INBOX. #mc/INBOX.foo -+ or -+ #mc/Maildir/. #mc/Maildir/.foo -+ */ -+ strcpy(tmp,curdir + 4); -+ if(!strncmp(ucase(tmp), "INBOX", 5)) -+ strcpy(tmp, "#mc/INBOX."); -+ else{ -+ strcpy(tmp, curdir); -+ for (i = strlen(tmp) - 1; tmp[i] && tmp[i] != '/'; i--); -+ tmp[i+2] = '\0'; /* keep the last "." intact */ -+ } -+ maildir_file_path(tmp, realname, sizeof(realname)); -+ maildir_scandir (realname, &names, &ndir, &scand, COURIER); -+ -+ if (scand > 0){ -+ cdir = courier_get_cdir(ndir); -+ cdir->path = cpystr(realname); -+ for(i = 0, j = 0; i < ndir; i++){ -+ td = realname[strlen(realname) - 1] == '.' -+ && *names[i]->d_name == '.'; -+ snprintf(tmp2, sizeof(tmp2), "%s%s", tmp, names[i]->d_name+1); -+ snprintf(pathname, sizeof(pathname), "%s%s", realname, names[i]->d_name + td); -+ if(stat(pathname, &sbuf) == 0 && S_ISDIR(sbuf.st_mode)){ -+ cdir->data[j] = (COURIERLOCAL *) fs_get(sizeof(COURIERLOCAL)); -+ cdir->data[j++]->name = cpystr(tmp2); -+ } -+ fs_give((void **)&names[i]); -+ } -+ cdir->total = j; -+ if(cdir->total == 0) -+ courier_free_cdir(&cdir); -+ } -+ if(names) -+ fs_give((void **) &names); -+ return cdir; -+} -+ -+void -+courier_list_info(COURIER_S **cdirp, char *data, int i) -+{ -+ long style = *(long *) maildir_parameters(GET_COURIERSTYLE, NIL); -+ COURIER_S *cdir = *cdirp; -+ -+ if(maildir_valid(cdir->data[i]->name)){ -+ if(courier_search_list(cdir->data, data, 0, cdir->total - 1)) -+ cdir->data[i]->attribute = LATT_HASCHILDREN; -+ else -+ cdir->data[i]->attribute = (style == COURIER) -+ ? LATT_HASNOCHILDREN : LATT_NOINFERIORS; -+ } ++ ++ char * ++ mdirpath(void) ++ { ++ char *path = maildir_parameters(GET_MDINBOXPATH, NIL); ++ return path ? (path[0] ? path : ".") : "Maildir"; ++ } ++ ++ /* remove the "#md/" or "#mc/" part from a folder name ++ * memory freed by caller ++ */ ++ char * ++ maildir_remove_root (char *name) ++ { ++ int courier = IS_COURIER(name), offset; ++ char realname[MAILTMPLEN]; ++ ++ offset = maildir_valid_name(name) ? (name[3] == '/' ? 4 : 3) : 0; ++ if(courier) ++ courier_realname(name+offset, realname); + else -+ cdir->data[i]->attribute = LATT_NOSELECT; -+ cdir->data[i]->attribute += maildir_any_new_msgs(cdir->data[i]->name) -+ ? LATT_MARKED : LATT_UNMARKED; -+} -+ -+/* UID Support */ -+/* Yes, I know I procastinated a lot about this, but here it is finally */ -+ -+/* return code: -+ bigger than zero: this session can assign uids -+ zero: this session will not assign uid -+ smaller than zero: this session temporarily suspends assigning uids -+ */ -+int -+maildir_can_assign_uid (MAILSTREAM *stream) -+{ -+ unsigned int rv = 0; -+ int ownuid, existuid; -+ unsigned long t; -+ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN], *p, *s; -+ DIR *dir; -+ struct direct *d; -+ -+ if(!stream || stream->rdonly -+ || !LOCAL || !LOCAL->dir || !(dir = opendir(LOCAL->dir))) -+ return 0; -+ -+ if(mypid == (pid_t) 0) -+ mypid = getpid(); -+ -+ snprintf(tmp, sizeof(tmp), "%s.%d", MDUIDTEMP, mypid); -+ -+ ownuid = existuid = 0; -+ s = NULL; -+ while ((d = readdir(dir)) != NULL){ -+ if(strncmp(d->d_name, tmp, strlen(tmp)) == 0){ -+ existuid++; ownuid++; -+ if(ownuid > 1){ -+ snprintf(tmp2, sizeof(tmp), "%s/%s", LOCAL->dir, d->d_name); -+ unlink(tmp2); -+ if(s){ -+ snprintf(tmp2, sizeof(tmp2), "%s/%s", LOCAL->dir, s); -+ unlink(tmp2); -+ fs_give((void **)&s); -+ } -+ } -+ else -+ s = cpystr(d->d_name); ++ strcpy(realname, name+offset); ++ return cpystr(realname); ++ } ++ ++ ++ /* Check validity of the name, we accept: ++ * a) #md/directory/folder ++ * b) #md/inbox ++ * A few considerations: We can only accept as valid ++ * a) names that start with #md/ and the directory exists or ++ * b) names that do not start with #md/ but are maildir directories (have ++ * the /cur, /tmp and /new structure) ++ */ ++ int maildir_valid_name (char *name) ++ { ++ char tmpname[MAILTMPLEN] = {'\0'}; ++ ++ if (mdfpath) ++ fs_give((void **)&mdfpath); ++ if (name && (name[0] != '#')) ++ snprintf(tmpname, sizeof(tmpname), "%s%s",MDPREFIX(CCLIENT), name); ++ mdfpath = cpystr(tmpname[0] ? tmpname : name); ++ ++ return IS_CCLIENT(name) || IS_COURIER(name); ++ } ++ ++ /* Check if the directory whose path is given by name is a valid maildir ++ * directory (contains /cur, /tmp and /new) ++ */ ++ int maildir_valid_dir (char *name) ++ { ++ int len; ++ DirNamesType i; ++ struct stat sbuf; ++ char tmp[MAILTMPLEN]; ++ ++ if(name[strlen(name) - 1] == '/') ++ name[strlen(name) - 1] = '\0'; ++ len = strlen(name); ++ for (i = Cur; i != EndDir; i++){ ++ MDFLD(tmp, name, i); ++ if (stat(tmp, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode)) ++ break; + } -+ else if(strncmp(d->d_name, MDUIDTEMP, strlen(MDUIDTEMP)) == 0) -+ existuid++; -+ } -+ -+ closedir(dir); -+ if(s) -+ fs_give((void **)&s); -+ -+ if(ownuid == 1 && existuid == 1) -+ rv = 1; -+ -+ if(ownuid == 0 && existuid == 0){ /* nobody owns the uid? */ -+ FILE *fp; -+ snprintf(tmp, sizeof(tmp), "%s/%s.%d.%lu", LOCAL->dir, MDUIDTEMP, mypid, time(0)); -+ if(fp = fopen(tmp, "w")){ -+ fclose(fp); -+ if(LOCAL->uidtempfile) -+ fs_give((void **)&LOCAL->uidtempfile); -+ LOCAL->uidtempfile = cpystr(tmp); -+ } -+ rv = 1; -+ } -+ -+ if(ownuid == 0 && existuid > 0) /* someone else owns uid assignment */ -+ return 0; -+ -+ /* if we own the uid, check that we do not own it more than once -+ * or that we share ownership. If any of these situations happens, -+ * give up the ownership until we can recover it -+ */ -+ -+ if(ownuid > 0){ -+ if(ownuid > 1) /* impossible, two lock files for the same session */ -+ return (-1)*ownuid; -+ -+ if(ownuid != existuid){ /* lock files for different sessions */ -+ if(LOCAL->uidtempfile){ -+ unlink(LOCAL->uidtempfile); -+ fs_give((void **)&LOCAL->uidtempfile); -+ } -+ return (-1)*ownuid; -+ } -+ } -+ -+ return rv; -+} -+ -+void -+maildir_read_uid(MAILSTREAM *stream, unsigned long *uid_last, -+ unsigned long *uid_validity) -+{ -+ int createuid, deleteuid = 0; -+ char tmp[MAILTMPLEN], *s = NULL; -+ DIR *dir; -+ struct direct *d; -+ -+ if(uid_last) *uid_last = 0L; -+ if(uid_last && uid_validity) *uid_validity = time(0); -+ if(!stream || !LOCAL || !LOCAL->dir || !(dir = opendir(LOCAL->dir))) -+ return; -+ -+ while ((d = readdir(dir)) != NULL){ -+ if(!strncmp(d->d_name, MDUIDLAST, strlen(MDUIDLAST))) -+ break; -+ } -+ createuid = d == NULL ? 1 : 0; -+ if(uid_last == NULL) -+ deleteuid++; -+ if(d){ -+ if(uid_last){ -+ s = d->d_name + strlen(MDUIDLAST) + 1; -+ *uid_last = strtoul(s, &s, 10); -+ if(!s || *s != '.'){ -+ deleteuid++; -+ createuid++; -+ *uid_last = 0L; -+ } ++ name[len] = '\0'; ++ return (i == EndDir) ? T : NIL; ++ } ++ ++ void courier_realname(char *name, char *realname) ++ { ++ int i,j; ++ ++ if(!name) ++ return; ++ ++ for (i = 0, j = 0; i < MAILTMPLEN && j < strlen(name); j++, i++){ ++ realname[i] = name[j]; ++ if(name[j] == '/' && name[j+1] != '.' && name[j+1] != '%' ++ && name[j+1] != '*') ++ realname[++i] = '.'; ++ } ++ if(realname[i-1] == '.') ++ i--; ++ realname[i] = '\0'; ++ } ++ ++ ++ /* given a maildir folder, return its path. Memory freed by caller. Directory ++ * does not contain the trailing slash "/". On error NULL is returned. ++ */ ++ int maildir_file_path (char *name, char *tmp, size_t sizeoftmp) ++ { ++ char *maildirpath = mdirpath(), *rname; ++ int courier = IS_COURIER(name); ++ ++ /* There are several ways in which the path can come, so we will handle ++ them here. First we deal with #mc/ or #md/ prefix by removing the ++ prefix, if any */ ++ ++ if(strlen(name) >= MAILTMPLEN) ++ name[MAILTMPLEN] = '\0'; ++ strcpy(tmp, name); ++ rname = maildir_remove_root(tmp); ++ tmp[0] = '\0'; /* just in case something fails */ ++ ++ if (strlen(myrootdir(rname)) + ++ max(strlen(rname), strlen(maildirpath)) > sizeoftmp){ ++ errno = ENAMETOOLONG; ++ snprintf(tmp, sizeoftmp, "Error opening \"%s\": %s", rname, strerror (errno)); ++ mm_log(tmp,ERROR); ++ if(rname) fs_give((void **)&rname); ++ return NIL; + } -+ if(s && *s == '.'){ -+ if(uid_validity){ -+ s++; -+ *uid_validity = strtoul(s, &s, 10); -+ if(s && *s != '\0'){ -+ *uid_validity = time(0); -+ deleteuid++; -+ createuid++; -+ } -+ } ++ ++ /* There are two ways in which the name can come here, either as a ++ full path or not. If it is not a full path it can come in two ways, ++ either as a file system path (Maildir/.Drafts) or as a maildir path ++ (INBOX.Drafts) ++ */ ++ ++ if(*rname == '/'){ /* full path */ ++ strncpy(tmp, rname, sizeoftmp); /* do nothing */ ++ tmp[sizeoftmp-1] = '\0'; ++ } ++ else ++ snprintf (tmp, sizeoftmp, "%s/%s%s%s", myrootdir (rname), ++ strncmp (ucase (strcpy (tmp, rname)), "INBOX", 5) ++ ? rname : maildirpath, ++ strncmp (ucase (strcpy (tmp, rname)), "INBOX", 5) ++ ? "" : (courier ? "/" : ""), ++ strncmp (ucase (strcpy (tmp, rname)), "INBOX", 5) ++ ? "" : (*(rname+5) == MDSEPARATOR(courier) ? rname+5 : "")); ++ if(rname) fs_give((void **)&rname); ++ return tmp[0] ? T : NIL; ++ } ++ ++ /* This function is given a full path for a mailbox and returns ++ * if it is a valid maildir transformed to canonical notation ++ */ ++ int ++ is_valid_maildir (char **name) ++ { ++ if (!strncmp(*name, myrootdir (*name), strlen(myrootdir(*name)))){ ++ (*name) += strlen(myrootdir(*name)); ++ if (**name == '/') (*name)++; ++ } ++ return maildir_valid(*name) ? T : NIL; ++ } ++ ++ /* Check validity of mailbox. This routine does not send errors to log, other ++ * routines calling this one may do so, though ++ */ ++ ++ DRIVER *maildir_valid (char *name) ++ { ++ char tmpname[MAILTMPLEN]; ++ ++ maildir_file_path(name, tmpname, sizeof(tmpname)); ++ ++ return maildir_valid_dir(tmpname) ++ ? (IS_COURIER(name) ? &courierdriver : &maildirdriver) : NIL; ++ } ++ ++ void maildir_fast (MAILSTREAM *stream,char *sequence,long flags) ++ { ++ unsigned long i; ++ MESSAGECACHE *elt; ++ /* get sequence */ ++ if (stream && LOCAL && ((flags & FT_UID) ? ++ mail_uid_sequence (stream,sequence) : ++ mail_sequence (stream,sequence))) ++ for (i = 1L; i <= stream->nmsgs; i++) { ++ if ((elt = mail_elt (stream,i))->sequence && (elt->valid = T) && ++ !(elt->day && elt->rfc822_size)) { ++ ENVELOPE **env = NIL; ++ ENVELOPE *e = NIL; ++ if (!stream->scache) env = &elt->private.msg.env; ++ else if (stream->msgno == i) env = &stream->env; ++ else env = &e; ++ if (!*env || !elt->rfc822_size) { ++ STRING bs; ++ unsigned long hs; ++ char *ht = (*stream->dtb->header) (stream,i,&hs,NIL); ++ ++ if (!*env) rfc822_parse_msg (env,NIL,ht,hs,NIL,BADHOST, ++ stream->dtb->flags); ++ if (!elt->rfc822_size) { ++ (*stream->dtb->text) (stream,i,&bs,FT_PEEK); ++ elt->rfc822_size = hs + SIZE (&bs) - GETPOS (&bs); ++ } ++ } ++ ++ if (!elt->day && *env && (*env)->date) ++ mail_parse_date (elt,(*env)->date); ++ ++ if (!elt->day) elt->day = elt->month = 1; ++ mail_free_envelope (&e); ++ } ++ } ++ } ++ ++ int ++ maildir_eliminate_duplicate (char *name, struct direct ***flist, unsigned long *nfiles) ++ { ++ int i, j, k, error = 0, scanr; ++ char new[MAILTMPLEN], old[MAILTMPLEN], tmp[MAILTMPLEN], *str; ++ struct direct **names = NIL; ++ ++ if((scanr = maildir_doscandir(name, &names, CCLIENT)) < 0) ++ return -1; ++ ++ if(nfiles) *nfiles = scanr; ++ for(i = 0, j = 1, k = 0; j < scanr; i++, j++){ ++ if(k) ++ names[i] = names[i+k]; ++ if(same_maildir_file(names[i]->d_name, names[j]->d_name)){ ++ int d, f, r, s; ++ maildir_getflag(names[i]->d_name, &d, &f, &r, &s, NIL); ++ snprintf(old, sizeof(old), "%s/%s", name, names[i]->d_name); ++ snprintf(new, sizeof(new), "%s/.%s", name, names[i]->d_name); ++ if(rename(old, new) < 0 && errno != EEXIST) ++ error++; ++ if(!error){ ++ for(; j < scanr ++ && same_maildir_file(names[i]->d_name, names[j]->d_name) ++ ; j++, k++){ ++ maildir_getflag(names[j]->d_name, (d ? NIL : &d), ++ (f ? NIL : &f), (r ? NIL : &r), (s ? NIL : &s), NIL); ++ snprintf(tmp, sizeof(tmp), "%s/%s", name, names[j]->d_name); ++ if(unlink(tmp) < 0){ /* Hmmm... a problem, let's see */ ++ struct stat sbuf; ++ if (stat(tmp, &sbuf) == 0 && (sbuf.st_mode & S_IFMT) == S_IFREG) ++ error++; ++ } ++ } ++ if((str = strrchr(names[i]->d_name,FLAGSEP)) != NULL) *str = '\0'; ++ snprintf (old, sizeof(old), "%s/%s%s%s%s%s%s", name, names[i]->d_name, MDSEP(2), ++ MDFLAG(Draft, d), MDFLAG(Flagged, f), MDFLAG(Replied, r), ++ MDFLAG(Seen, s)); ++ if(rename(new, old) < 0) ++ error++; ++ } ++ } ++ ++ } ++ if(k > 0) ++ fs_give((void **)&names); ++ else ++ *flist = names; ++ return error ? -1 : k; ++ } ++ ++ int ++ maildir_doscandir(char *name, struct direct ***flist, int flag) ++ { ++ return scandir(name, flist, ++ flag == CCLIENT ? maildir_select : courier_dir_select, ++ flag == CCLIENT ? maildir_namesort : courier_dir_sort); ++ } ++ ++ /* ++ * return all files in a given directory. This is a separate call ++ * so that if there are warnings during compilation this only appears once. ++ */ ++ unsigned long ++ maildir_scandir (char *name, struct direct ***flist, ++ unsigned long *nfiles, int *scand, int flag) ++ { ++ struct stat sbuf; ++ int rv = -2; /* impossible value */ ++ ++ if (scand) ++ *scand = -1; /* assume error for safety */ ++ *nfiles = 0; ++ if((stat(name,&sbuf) < 0) ++ || (flag == CCLIENT ++ && ((rv = maildir_eliminate_duplicate(name, flist, nfiles)) < 0))) ++ return 0L; ++ ++ if (scand && (rv > 0 || rv == -2)) ++ *nfiles = maildir_doscandir(name, flist, flag); ++ ++ if(scand) *scand = *nfiles; ++ ++ return (unsigned long) sbuf.st_ctime; ++ } ++ ++ /* Does a message with given name exists (or was it removed)? ++ * Returns: 1 - yes, such message exist, ++ * 0 - No, that message does not exist anymore ++ * ++ * Parameters: stream, name of mailbox, new name if his message does not ++ * exist. ++ */ ++ ++ int maildir_message_exists(MAILSTREAM *stream, char *name, char *newfile) ++ { ++ char tmp[MAILTMPLEN]; ++ int gotit = NIL; ++ DIR *dir; ++ struct direct *d; ++ struct stat sbuf; ++ ++ /* First check directly if it exists, if not there, look for it */ ++ snprintf(tmp, sizeof(tmp), "%s/%s", LOCAL->path[Cur], name); ++ if ((stat(tmp, &sbuf) == 0) && ((sbuf.st_mode & S_IFMT) == S_IFREG)) ++ return T; ++ ++ if (!(dir = opendir (LOCAL->path[Cur]))) ++ return NIL; ++ ++ while ((d = readdir(dir)) && gotit == NIL){ ++ if (d->d_name[0] == '.') ++ continue; ++ if (same_maildir_file(d->d_name, name)){ ++ gotit = T; ++ strcpy(newfile, d->d_name); ++ } ++ } ++ closedir(dir); ++ return gotit; ++ } ++ ++ /* Maildir open */ ++ ++ MAILSTREAM *maildir_open (MAILSTREAM *stream) ++ { ++ char tmp[MAILTMPLEN]; ++ struct stat sbuf; ++ ++ if (!stream) return &maildirproto; ++ if (stream->local) fatal ("maildir recycle stream"); ++ md_domain_name(); /* get domain name for maildir files in mdlocaldomain */ ++ if(mypid == (pid_t) 0) ++ mypid = getpid(); ++ if (!stream->rdonly){ ++ stream->perm_seen = stream->perm_deleted = stream->perm_flagged = ++ stream->perm_answered = stream->perm_draft = T; ++ } ++ stream->local = (MAILDIRLOCAL *) fs_get (sizeof (MAILDIRLOCAL)); ++ memset(LOCAL, 0, sizeof(MAILDIRLOCAL)); ++ LOCAL->fd = -1; ++ ++ LOCAL->courier = IS_COURIER(stream->mailbox); ++ strcpy(tmp, stream->mailbox); ++ if (maildir_file_path (stream->mailbox, tmp, sizeof(tmp))) ++ LOCAL->dir = cpystr (tmp); ++ LOCAL->candouid = maildir_can_assign_uid(stream); ++ maildir_read_uid(stream, &stream->uid_last, &stream->uid_validity); ++ if (LOCAL->dir){ ++ LOCAL->path = (char **) fs_get(EndDir*sizeof(char *)); ++ MDFLD(tmp, LOCAL->dir, Cur); LOCAL->path[Cur] = cpystr (tmp); ++ MDFLD(tmp, LOCAL->dir, New); LOCAL->path[New] = cpystr (tmp); ++ MDFLD(tmp, LOCAL->dir, Tmp); LOCAL->path[Tmp] = cpystr (tmp); ++ if (stat (LOCAL->path[Cur],&sbuf) < 0) { ++ snprintf (tmp, sizeof(tmp), "Can't open folder %s: %s", ++ stream->mailbox,strerror (errno)); ++ mm_log (tmp,ERROR); ++ maildir_close(stream, 0); ++ return NIL; ++ } ++ } ++ ++ if(maildir_file_path (stream->mailbox, tmp, sizeof(tmp))){ ++ fs_give ((void **) &stream->mailbox); ++ stream->mailbox = cpystr(tmp); ++ } ++ ++ LOCAL->buf = (char *) fs_get (CHUNKSIZE); ++ LOCAL->buflen = CHUNKSIZE - 1; ++ stream->sequence++; ++ stream->nmsgs = stream->recent = 0L; ++ ++ maildir_parse_folder(stream, 1); ++ ++ return stream; ++ } ++ ++ /* Maildir initial parsing of the folder */ ++ void ++ maildir_parse_folder (MAILSTREAM *stream, int full) ++ { ++ char tmp[MAILTMPLEN]; ++ struct direct **namescur = NIL, **namesnew = NIL; ++ unsigned long i, nfilescur = 0L, nfilesnew = 0L, oldpos, newpos, total; ++ int scan_err, rescan, loop = 0; ++ ++ if (!stream) /* what??? */ ++ return; ++ ++ MM_CRITICAL(stream); ++ ++ maildir_scandir (LOCAL->path[New], &namesnew, &nfilesnew, &scan_err, CCLIENT); ++ if (scan_err < 0){ ++ if(namesnew){ ++ for(i = 0L; i < nfilesnew; i++) ++ fs_give((void **)&namesnew[i]); ++ fs_give((void **) &namesnew); ++ } ++ maildir_abort(stream); ++ } ++ ++ /* Scan old messages first, escoba! */ ++ if(stream->rdonly ++ || (LOCAL && ((maildir_initial_check(stream, Cur) == 0) ++ || nfilesnew > 0L))){ ++ LOCAL->scantime = maildir_scandir (LOCAL->path[Cur], &namescur, &nfilescur, ++ &scan_err, CCLIENT); ++ if (scan_err < 0){ ++ if(namescur){ ++ for(i = 0L; i < nfilescur; i++) ++ fs_give((void **)&namescur[i]); ++ fs_give((void **) &namescur); ++ } ++ maildir_abort(stream); ++ } ++ } ++ if(LOCAL && (maildir_initial_check(stream, New) == 0) && (nfilescur > 0L)){ ++ while(LOCAL && loop < 10){ ++ if(nfilesnew == 0L) ++ maildir_scandir (LOCAL->path[New], &namesnew, &nfilesnew, &scan_err, CCLIENT); ++ if (scan_err < 0){ ++ if(namesnew){ ++ for(i = 0L; i < nfilesnew; i++) ++ fs_give((void **)&namesnew[i]); ++ fs_give((void **) &namesnew); ++ } ++ maildir_abort(stream); ++ break; ++ } ++ for(i = 0L, rescan = 0, newpos = oldpos = 0L; ++ newpos < nfilescur && i < nfilesnew; i++){ ++ if(maildir_message_in_list(namesnew[i]->d_name, namescur, oldpos, ++ nfilescur - 1L, &newpos)){ ++ oldpos = newpos; ++ snprintf(tmp, sizeof(tmp), "%s/%s", LOCAL->path[New], namesnew[i]->d_name); ++ if(unlink(tmp) < 0) ++ scan_err = -1; ++ rescan++; ++ } ++ else ++ newpos = oldpos; ++ } ++ if(scan_err < 0) ++ maildir_abort(stream); ++ if(rescan == 0) ++ break; ++ else{ /* restart */ ++ if(namesnew){ ++ for(i = 0L; i < nfilesnew; i++) ++ fs_give((void **)&namesnew[i]); ++ fs_give((void **) &namesnew); ++ } ++ nfilesnew = 0L; ++ loop++; ++ } ++ } ++ } ++ if(loop == 10) ++ maildir_abort(stream); ++ if(LOCAL){ ++ if(stream->rdonly) ++ stream->recent = 0L; ++ total = namescur || stream->rdonly ++ ? maildir_parse_dir(stream, 0L, Cur, namescur, ++ nfilescur, full) : stream->nmsgs; ++ stream->nmsgs = maildir_parse_dir(stream, total, New, namesnew, ++ nfilesnew, full); ++ } ++ if(namesnew){ ++ for(i = 0L; i < nfilesnew; i++) ++ fs_give((void **)&namesnew[i]); ++ fs_give((void **) &namesnew); ++ } ++ if(namescur){ ++ for(i = 0L; i < nfilescur; i++) ++ fs_give((void **)&namescur[i]); ++ fs_give((void **) &namescur); ++ } ++ MM_NOCRITICAL(stream); ++ } ++ ++ int ++ maildir_initial_check (MAILSTREAM *stream, DirNamesType dirtype) ++ { ++ char *tmp; ++ struct stat sbuf; ++ ++ if (access (LOCAL->path[dirtype], R_OK|W_OK|X_OK) != 0){ ++ maildir_abort(stream); ++ return -1; ++ } ++ ++ if (dirtype != New && ++ (stat(LOCAL->path[Cur], &sbuf) < 0 || sbuf.st_ctime == LOCAL->scantime)) ++ return -1; ++ return 0; ++ } ++ ++ ++ /* Return the number of messages in the directory, while filling the ++ * elt structure. ++ */ ++ ++ unsigned long ++ maildir_parse_dir(MAILSTREAM *stream, unsigned long nmsgs, ++ DirNamesType dirtype, struct direct **names, ++ unsigned long nfiles, int full) ++ { ++ char tmp[MAILTMPLEN], file[MAILTMPLEN], newfile[MAILTMPLEN], *mdstr; ++ struct stat sbuf; ++ unsigned long i, new = 0L, l, uid_last; ++ unsigned long recent = stream ? stream->recent : 0L; ++ int d = 0, f = 0, r = 0, s = 0, t = 0; ++ int we_compute, in_list, len; ++ int silent = stream ? stream->silent : NIL; ++ MESSAGECACHE *elt; ++ ++ if (dirtype == Cur && !stream->rdonly) ++ for (i = 1L; i <= stream->nmsgs;){ ++ elt = mail_elt(stream, i); ++ in_list = elt && elt->private.spare.ptr && nfiles > 0L ++ ? (MDPOS(elt) < nfiles ++ ? same_maildir_file(MDFILE(elt), names[MDPOS(elt)]->d_name) ++ : NIL) ++ || maildir_message_in_list(MDFILE(elt), names, 0L, ++ nfiles - 1L, &MDPOS(elt)) ++ : NIL; ++ if (!in_list){ ++ if (elt->private.spare.ptr) ++ maildir_free_file ((void **) &elt->private.spare.ptr); ++ ++ if (elt->recent) --recent; ++ mail_expunged(stream,i); ++ } ++ else i++; ++ } ++ ++ stream->silent = T; ++ uid_last = 0L; ++ len = LOCAL->path[Cur] ? (int) strlen(LOCAL->path[Cur]) : 0; ++ for (we_compute = 0, i = l = 1L; l <= nfiles; l++){ ++ unsigned long pos, uid; ++ if (dirtype == New && !stream->rdonly){ /* move new messages to cur */ ++ pos = l - 1L; ++ snprintf (file, sizeof(file), "%s/%s", LOCAL->path[New], names[pos]->d_name); ++ if(lstat(file,&sbuf) == 0) ++ switch(sbuf.st_mode & S_IFMT){ ++ case S_IFREG: ++ strcpy(tmp, names[pos]->d_name); ++ if((mdstr = strstr(tmp,MDSEP(3))) ++ || (mdstr = strstr(tmp,MDSEP(2)))) ++ *(mdstr+1) = '2'; ++ else ++ strcat(tmp, MDSEP(2)); ++ snprintf(newfile, sizeof(newfile), "%.*s/%.*s", ++ len, LOCAL->path[Cur] ? LOCAL->path[Cur] : "", ++ (int) sizeof(newfile) - len, tmp); ++ newfile[sizeof(newfile)-1] = '\0'; ++ if(rename (file, newfile) != 0){ ++ mm_log("Unable to read new mail!", WARN); ++ continue; ++ } ++ unlink (file); ++ new++; ++ break; ++ case S_IFLNK: /* clean up, clean up, everybody, everywhere */ ++ if(unlink(file) < 0){ ++ if(LOCAL->link == NIL){ ++ mm_log("Unable to remove symbolic link", WARN); ++ LOCAL->link = T; ++ } ++ } ++ continue; ++ break; ++ default: ++ if(LOCAL && LOCAL->link == NIL){ ++ mm_log("Unrecognized file or link in folder", WARN); ++ LOCAL->link = T; ++ } ++ continue; ++ break; ++ } ++ } ++ mail_exists(stream, i + nmsgs); ++ elt = mail_elt(stream, i + nmsgs); ++ pos = (elt && elt->private.spare.ptr) ? MDPOS(elt) : l - 1L; ++ if (dirtype == New) elt->recent = T; ++ maildir_getflag(names[pos]->d_name, &d, &f, &r ,&s, &t); ++ if (elt->private.spare.ptr) ++ maildir_free_file_only ((void **)&elt->private.spare.ptr); ++ else{ ++ maildir_get_file((MAILDIRFILE **)&elt->private.spare.ptr); ++ we_compute++; ++ } ++ MDFILE(elt) = cpystr(names[pos]->d_name); ++ MDPOS(elt) = pos; ++ MDLOC(elt) = dirtype; ++ if (dirtype == Cur){ /* deal with UIDs */ ++ if(elt->private.uid == 0L) ++ elt->private.uid = maildir_get_uid(MDFILE(elt)); ++ if(elt->private.uid <= uid_last){ ++ uid = (we_compute ? uid_last : stream->uid_last) + 1L; ++ if(LOCAL->candouid) ++ maildir_assign_uid(stream, i + nmsgs, uid); ++ else ++ elt->private.uid = uid; ++ } ++ else ++ uid = elt->private.uid; ++ uid_last = uid; ++ if(uid_last > stream->uid_last) ++ stream->uid_last = uid_last; ++ } ++ if(dirtype == New && !stream->rdonly){ ++ maildir_free_file_only((void **)&elt->private.spare.ptr); ++ MDFILE(elt) = cpystr(tmp); ++ MDSIZE(elt) = sbuf.st_size; ++ MDMTIME(elt) = sbuf.st_mtime; ++ MDLOC(elt) = Cur; ++ } ++ if (elt->draft != d || elt->flagged != f || ++ elt->answered != r || elt->seen != s || elt->deleted != t){ ++ elt->draft = d; elt->flagged = f; elt->answered = r; ++ elt->seen = s; elt->deleted = t; ++ if (!we_compute && !stream->rdonly) ++ MM_FLAGS(stream, i+nmsgs); ++ } ++ maildir_get_date(stream, i+nmsgs); ++ elt->valid = T; ++ i++; ++ } ++ stream->silent = silent; ++ if(LOCAL->candouid && dirtype == Cur) ++ maildir_read_uid(stream, NULL, &stream->uid_validity); ++ if (dirtype == New && stream->rdonly) ++ new = nfiles; ++ mail_exists(stream, nmsgs + ((dirtype == New) ? new : nfiles)); ++ mail_recent(stream, recent + ((dirtype == New) ? new : 0L)); ++ ++ return (nmsgs + (dirtype == New ? new : nfiles)); ++ } ++ ++ long maildir_ping (MAILSTREAM *stream) ++ { ++ maildir_parse_folder(stream, 0); ++ if(stream && LOCAL){ ++ if(LOCAL->candouid < 0) ++ LOCAL->candouid++; ++ else if(LOCAL->candouid) ++ maildir_uid_renew_tempfile(stream); ++ else /* try again to get uids */ ++ LOCAL->candouid = maildir_can_assign_uid(stream); ++ } ++ return stream && LOCAL ? LONGT : NIL; ++ } ++ ++ int maildir_select (const struct direct *name) ++ { ++ return (name->d_name[0] != '.'); ++ } ++ ++ /* ++ * Unfortunately, there is no way to sort by arrival in this driver, this ++ * means that opening a folder in this driver using the scandir function ++ * will always make this driver slower than any driver that has a natural ++ * way of sorting by arrival (like a flat file format, "mbox", "mbx", etc). ++ */ ++ int maildir_namesort (const struct direct **d1, const struct direct **d2) ++ { ++ const struct direct *e1 = *(const struct direct **) d1; ++ const struct direct *e2 = *(const struct direct **) d2; ++ ++ return comp_maildir_file((char *) e1->d_name, (char *) e2->d_name); ++ } ++ ++ /* Maildir close */ ++ ++ void maildir_close (MAILSTREAM *stream, long options) ++ { ++ MESSAGECACHE *elt; ++ unsigned long i; ++ int silent = stream ? stream->silent : 0; ++ mailcache_t mc = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL); ++ ++ if (!stream) return; ++ ++ for (i = 1L; i <= stream->nmsgs; i++) ++ if((elt = (MESSAGECACHE *) (*mc)(stream,i,CH_ELT)) && elt->private.spare.ptr) ++ maildir_free_file ((void **) &elt->private.spare.ptr); ++ stream->silent = T; ++ if (options & CL_EXPUNGE) maildir_expunge (stream, NIL, NIL); ++ maildir_abort(stream); ++ if (mdfpath) fs_give((void **)&mdfpath); ++ if (mypid) mypid = (pid_t) 0; ++ stream->silent = silent; ++ } ++ ++ void maildir_check (MAILSTREAM *stream) ++ { ++ if (maildir_ping (stream)) mm_log ("Check completed",(long) NIL); ++ } ++ ++ long maildir_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs, long flags) ++ { ++ char tmp[MAILTMPLEN]; ++ unsigned long i; ++ MESSAGECACHE *elt; ++ char *s; ++ /* UID call "impossible" */ ++ if (flags & FT_UID || !LOCAL) return NIL; ++ elt = mail_elt (stream, msgno); ++ ++ if (!(flags & FT_PEEK) && !elt->seen){ ++ elt->seen = T; ++ maildir_flagmsg (stream, elt); ++ MM_FLAGS(stream, elt->msgno); ++ } ++ ++ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), MDLOC(elt)); ++ ++ if (LOCAL->fd < 0) /* if file closed ? */ ++ LOCAL->fd = open(tmp,O_RDONLY,NIL); ++ ++ if (LOCAL->fd < 0 && (errno == EACCES || errno == ENOENT)){ ++ INIT (bs, mail_string, "", 0); ++ elt->rfc822_size = 0L; ++ return NIL; ++ } ++ ++ s = maildir_text_work(stream, elt, &i, flags); ++ INIT (bs, mail_string, s, i); ++ return LONGT; ++ } ++ ++ char *maildir_text_work (MAILSTREAM *stream,MESSAGECACHE *elt, ++ unsigned long *length,long flags) ++ { ++ FDDATA d; ++ STRING bs; ++ char *s,tmp[CHUNK]; ++ unsigned long msgno = elt->msgno; ++ ++ if (length) ++ *length = 0L; ++ LOCAL->buf[0] = '\0'; ++ ++ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), MDLOC(elt)); ++ if (LOCAL->fd < 0 && ((LOCAL->fd = open (tmp,O_RDONLY,NIL)) < 0)) ++ return maildir_update_elt_maildirp(stream, msgno) > 0 ++ ? maildir_text_work(stream, mail_elt(stream, msgno),length, flags) ++ : NULL; ++ ++ lseek (LOCAL->fd, elt->private.msg.text.offset,L_SET); ++ ++ if (flags & FT_INTERNAL) { /* initial data OK? */ ++ if (elt->private.msg.text.text.size > LOCAL->buflen) { ++ fs_give ((void **) &LOCAL->buf); ++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen = ++ elt->private.msg.text.text.size) + 1); ++ } ++ read (LOCAL->fd,LOCAL->buf,elt->private.msg.text.text.size); ++ LOCAL->buf[*length = elt->private.msg.text.text.size] = '\0'; ++ } ++ else { ++ if (elt->rfc822_size > LOCAL->buflen) { ++ fs_give ((void **) &LOCAL->buf); ++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen = elt->rfc822_size) + 1); ++ } ++ d.fd = LOCAL->fd; /* yes, set up file descriptor */ ++ d.pos = elt->private.msg.text.offset; ++ d.chunk = tmp; /* initial buffer chunk */ ++ d.chunksize = CHUNK; ++ INIT (&bs,fd_string,&d,elt->private.msg.text.text.size); ++ for (s = LOCAL->buf; SIZE (&bs);) switch (CHR (&bs)) { ++ case '\r': /* carriage return seen */ ++ *s++ = SNX (&bs); /* copy it and any succeeding LF */ ++ if (SIZE (&bs) && (CHR (&bs) == '\n')) *s++ = SNX (&bs); ++ break; ++ case '\n': ++ *s++ = '\r'; /* insert a CR */ ++ default: ++ *s++ = SNX (&bs); /* copy characters */ ++ } ++ *s = '\0'; /* tie off buffer */ ++ *length = s - (char *) LOCAL->buf; /* calculate length */ ++ } ++ close(LOCAL->fd); LOCAL->fd = -1; ++ return LOCAL->buf; ++ } ++ ++ /* maildir parse, fill the elt structure... well not all of it... */ ++ unsigned long maildir_parse_message(MAILSTREAM *stream, unsigned long msgno, ++ DirNamesType dirtype) ++ { ++ char *b, *s, *t, c; ++ char tmp[MAILTMPLEN]; ++ struct stat sbuf; ++ unsigned long i, len; ++ int d, f, r, se, dt; ++ MESSAGECACHE *elt; ++ ++ elt = mail_elt (stream,msgno); ++ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), dirtype); ++ if(stat(tmp, &sbuf) == 0) ++ MDSIZE(elt) = sbuf.st_size; ++ ++ maildir_get_date(stream, msgno); ++ maildir_getflag(MDFILE(elt), &d, &f, &r ,&se, &dt); ++ elt->draft = d; elt->flagged = f; elt->answered = r; elt->seen = se; ++ elt->deleted = dt; elt->valid = T; ++ if (LOCAL->fd < 0) /* if file closed ? */ ++ LOCAL->fd = open(tmp,O_RDONLY,NIL); ++ ++ if (LOCAL->fd >= 0){ ++ s = (char *) fs_get (MDSIZE(elt) + 1); ++ read (LOCAL->fd,s,MDSIZE(elt)); ++ s[MDSIZE(elt)] = '\0'; ++ t = s + strlen(s); /* make t point to the end of s */ ++ for (i = 0L, b = s; b < t && !(i && (*b == '\n')); i = (*b++ == '\n')); ++ len = (*b ? ++b : b) - s; ++ elt->private.msg.header.text.size = ++ elt->private.msg.text.offset = len; ++ elt->private.msg.text.text.size = MDSIZE(elt) - len; ++ for (i = 0L, b = s, c = *b; b && ++ ((c < '\016' && ((c == '\012' && ++i) ++ ||(c == '\015' && *(b+1) == '\012' && ++b && (i +=2)))) ++ || b < t); i++, c= *++b); ++ elt->rfc822_size = i; ++ fs_give ((void **) &s); ++ close(LOCAL->fd); LOCAL->fd = -1; ++ } ++ return elt->rfc822_size; ++ } ++ ++ int ++ maildir_update_elt_maildirp(MAILSTREAM *stream, unsigned long msgno) ++ { ++ struct direct **names = NIL; ++ unsigned long i, nfiles, pos; ++ int d = 0, f = 0 , r = 0, s = 0, t = 0, in_list, scan_err; ++ MESSAGECACHE *elt; ++ ++ maildir_scandir (LOCAL->path[Cur], &names, &nfiles, &scan_err, CCLIENT); ++ ++ if(scan_err < 0) return -1; ++ ++ elt = mail_elt (stream,msgno); ++ ++ in_list = nfiles > 0L ++ ? maildir_message_in_list(MDFILE(elt), names, 0L, nfiles - 1L, &pos) ++ : 0; ++ ++ if (in_list && pos >= 0L && pos < nfiles ++ && strcmp(MDFILE(elt), names[pos]->d_name)){ ++ maildir_free_file_only((void **)&elt->private.spare.ptr); ++ MDFILE(elt) = cpystr(names[pos]->d_name); ++ maildir_getflag(MDFILE(elt), &d, &f, &r ,&s, &t); ++ if (elt->draft != d || elt->flagged != f || ++ elt->answered != r || elt->seen != s || elt->deleted != t){ ++ elt->draft = d; elt->flagged = f; elt->answered = r; ++ elt->seen = s; elt->deleted = t; ++ MM_FLAGS(stream, msgno); ++ } ++ } ++ else in_list = 0; /* we did not update the file name */ ++ ++ for (i = 0L; i < nfiles; i++) ++ fs_give((void **) &names[i]); ++ if (names) ++ fs_give((void **) &names); ++ return in_list ? 1 : -1; ++ } ++ ++ /* Maildir fetch message header */ ++ ++ char *maildir_header (MAILSTREAM *stream,unsigned long msgno, ++ unsigned long *length, long flags) ++ { ++ char tmp[MAILTMPLEN], *s = NULL; ++ MESSAGECACHE *elt; ++ ++ if (length) *length = 0; ++ if (flags & FT_UID || !LOCAL) return ""; /* UID call "impossible" */ ++ elt = mail_elt (stream,msgno); ++ if(elt->private.msg.header.text.size == 0) ++ maildir_parse_message(stream, msgno, MDLOC(elt)); ++ ++ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), MDLOC(elt)); ++ if (LOCAL->fd < 0 && ((LOCAL->fd = open (tmp,O_RDONLY,NIL)) < 0)){ ++ if(errno == EACCES) ++ mm_log ("Message exists but can not be read. Envelope and body lost!",ERROR); ++ return maildir_update_elt_maildirp(stream, msgno) > 0 ++ ? maildir_header(stream, msgno, length, flags) ++ : NULL; ++ } ++ ++ if (flags & FT_INTERNAL){ ++ if(elt->private.msg.header.text.size > LOCAL->buflen){ ++ fs_give ((void **) &LOCAL->buf); ++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen = ++ elt->private.msg.header.text.size) + 1); ++ } ++ read (LOCAL->fd, (void *)LOCAL->buf, elt->private.msg.header.text.size); ++ LOCAL->buf[*length = elt->private.msg.header.text.size] = '\0'; ++ } ++ else{ ++ s = (char *) fs_get(elt->private.msg.header.text.size+1); ++ read (LOCAL->fd, (void *)s, elt->private.msg.header.text.size); ++ s[elt->private.msg.header.text.size] = '\0'; ++ *length = strcrlfcpy (&LOCAL->buf,&LOCAL->buflen,s, ++ elt->private.msg.header.text.size); ++ fs_give ((void **) &s); ++ } ++ elt->private.msg.text.offset = elt->private.msg.header.text.size; ++ elt->private.msg.text.text.size = MDSIZE(elt) - elt->private.msg.text.offset; ++ close(LOCAL->fd); LOCAL->fd = -1; ++ return LOCAL->buf; ++ } ++ ++ /* Maildir find list of subscribed mailboxes ++ * Accepts: mail stream ++ * pattern to search ++ */ ++ ++ void maildir_list (MAILSTREAM *stream,char *ref, char *pat) ++ { ++ char *s,test[MAILTMPLEN],file[MAILTMPLEN]; ++ long i = 0L; ++ ++ if((!pat || !*pat) && maildir_canonicalize (test,ref,"*") ++ && maildir_valid_name(test)){ /* there is a #md/ leading here */ ++ for (i = 3L; test[i] && test[i] != '/'; i++); ++ if ((s = strchr (test+i+1,'/')) != NULL) *++s = '\0'; ++ else test[0] = '\0'; ++ mm_list (stream,'/',test, LATT_NOSELECT); ++ } ++ else if (maildir_canonicalize (test,ref,pat)) { ++ if (test[3] == '/') { /* looking down levels? */ ++ /* yes, found any wildcards? */ ++ if ((s = strpbrk (test,"%*")) != NULL){ ++ /* yes, copy name up to that point */ ++ strncpy (file,test+4,i = s - (test+4)); ++ file[i] = '\0'; /* tie off */ ++ } ++ else strcpy (file,test+4);/* use just that name then */ ++ /* find directory name */ ++ if ((s = strrchr (file, '/')) != NULL){ ++ *s = '\0'; /* found, tie off at that point */ ++ s = file; ++ } ++ /* do the work */ ++ if(IS_COURIER(test)) ++ courier_list_work (stream,s,test,0); ++ else ++ maildir_list_work (stream,s,test,0); ++ } ++ /* always an INBOX */ ++ if (!compare_cstring (test,"#MD/INBOX")) ++ mm_list (stream,NIL,"#MD/INBOX",LATT_NOINFERIORS); ++ if (!compare_cstring (test,"#MC/INBOX")) ++ mm_list (stream,NIL,"#MC/INBOX",LATT_NOINFERIORS); ++ } ++ } ++ ++ void courier_list (MAILSTREAM *stream,char *ref, char *pat) ++ { ++ /* I am too lazy to do anything. Do you care to ask maildir list, please? ++ The real reason why this is a dummy function is because we do not want to ++ see the same folder listed twice. ++ */ ++ } ++ ++ /* For those that want to hide things, we give them a chance to do so */ ++ void *maildir_parameters (long function, void *value) ++ { ++ void *ret = NIL; ++ switch ((int) function) { ++ case SET_MDINBOXPATH: ++ if(strlen((char *) value ) > 49) ++ strcpy(myMdInboxDir, "Maildir"); ++ else ++ strcpy(myMdInboxDir, (char *) value); ++ case GET_MDINBOXPATH: ++ if (myMdInboxDir[0] == '\0') strcpy(myMdInboxDir,"Maildir"); ++ ret = (void *) myMdInboxDir; ++ break; ++ case SET_COURIERSTYLE: ++ CourierStyle = * (long *) value; /* fix by Chris Caputo */ ++ case GET_COURIERSTYLE: ++ ret = (void *) &CourierStyle; /* fix by Chris Caputo */ ++ break; ++ case GET_DIRFMTTEST: ++ ret = (void *) maildir_dirfmttest; ++ break; ++ default: ++ break; ++ } ++ return ret; ++ } ++ ++ int maildir_create_folder(char *mailbox) ++ { ++ char tmp[MAILTMPLEN], err[MAILTMPLEN]; ++ DirNamesType i; ++ ++ for (i = Cur; i != EndDir; i++){ ++ int len; ++ MDFLD(tmp, mailbox, i); ++ len = (int) strlen(tmp); ++ if (mkdir(tmp, 0700) && errno != EEXIST){ /* try to make new dir */ ++ snprintf (err, sizeof(err), "Can't create %.*s: %.*s", len, tmp, (int)(sizeof(err) - len - 16), strerror(errno)); ++ err[sizeof(err) - 1] = '\0'; ++ mm_log (err,ERROR); ++ return NIL; ++ } ++ } ++ return T; ++ } ++ ++ int maildir_create_work(char *mailbox, int loop) ++ { ++ char *s, c, err[MAILTMPLEN], tmp[MAILTMPLEN], tmp2[MAILTMPLEN], mbx[MAILTMPLEN]; ++ int fnlen, create_dir = 0, courier, mv; ++ struct stat sbuf; ++ long style = *(long *) maildir_parameters(GET_COURIERSTYLE, NIL); ++ ++ courier = IS_COURIER(mailbox); ++ strcpy(mbx, mailbox); ++ mv = maildir_valid(mbx) ? 1 : 0; ++ maildir_file_path(mailbox, tmp, sizeof(tmp)); ++ if (mailbox[strlen(mailbox) - 1] == MDSEPARATOR(courier)){ ++ create_dir++; ++ mailbox[strlen(mailbox) - 1] = '\0'; ++ } ++ ++ if(!loop && courier){ ++ if(mv){ ++ if(create_dir){ ++ if(style == CCLIENT) ++ strcpy (err,"Can not create directory: folder exists. Create subfolder"); ++ else ++ strcpy(err,"Folder and Directory already exist"); ++ } ++ else ++ strcpy (err, "Can't create mailbox: mailbox already exists"); + } + else{ -+ deleteuid++; -+ createuid++; ++ if(create_dir) ++ strcpy(err, "Can not create directory. Cread folder instead"); ++ else ++ err[0] = '\0'; + } -+ } -+ if(deleteuid){ -+ snprintf(tmp, sizeof(tmp), "%s/%s", LOCAL->dir, d->d_name); -+ unlink(tmp); -+ } -+ if(createuid) -+ maildir_write_uid(stream, (uid_last ? *uid_last : stream->uid_last), -+ uid_validity ? *uid_validity : time(0)); -+ closedir(dir); -+} -+ -+void -+maildir_write_uid(MAILSTREAM *stream, unsigned long uid_last, -+ unsigned long uid_validity) -+{ -+ char tmp[MAILTMPLEN]; -+ FILE *fp; -+ -+ if(!stream || stream->rdonly || !LOCAL || !LOCAL->dir) -+ return; -+ -+ snprintf(tmp, sizeof(tmp), "%s/%s.%010lu.%010lu", LOCAL->dir, MDUIDLAST, -+ uid_last, uid_validity); -+ if(fp = fopen(tmp, "w")) -+ fclose(fp); -+} -+ -+unsigned long -+maildir_get_uid(char *name) -+{ -+ char *s; -+ unsigned long rv = 0L; -+ -+ if(!name || (s = strstr(name,MDUIDSEP)) == NULL) -+ return rv; -+ -+ s += strlen(MDUIDSEP); -+ rv = strtoul(s, NULL, 10); -+ return rv; -+} -+ -+ -+void -+maildir_delete_uid(MAILSTREAM *stream, unsigned long msgno) -+{ -+ char old[MAILTMPLEN], new[MAILTMPLEN], *s, *t; -+ MESSAGECACHE *elt; -+ -+ elt = mail_elt(stream, msgno); -+ if(!stream || !elt || !elt->private.spare.ptr || !LOCAL || !LOCAL->dir) -+ return; -+ -+ snprintf(old, sizeof(old), "%s/%s/%s", LOCAL->dir, MDNAME(Cur), MDFILE(elt)); -+ t = MDFILE(elt); -+ if(s = strstr(MDFILE(elt), MDUIDSEP)){ -+ *s = '\0'; -+ s += strlen(MDUIDSEP); -+ strtoul(s, &s, 10); -+ snprintf(new, sizeof(new), "%s/%s/%s%s", LOCAL->dir, MDNAME(Cur), t, s); -+ if(rename(old, new) == 0){ -+ maildir_free_file_only ((void **)&elt->private.spare.ptr); -+ s = strrchr(new, '/'); -+ MDFILE(elt) = cpystr(s+1); ++ if(err[0]){ ++ mm_log (err,ERROR); ++ return NIL; + } -+ elt->private.uid = 0L; -+ } -+} -+ -+void -+maildir_assign_uid(MAILSTREAM *stream, unsigned long msgno, unsigned long uid) -+{ -+ int createuid, deleteuid = 0; -+ char old[MAILTMPLEN], new[MAILTMPLEN], *s, *t; -+ MESSAGECACHE *elt; -+ -+ elt = mail_elt(stream, msgno); -+ if(!stream || !elt || !elt->private.spare.ptr || !LOCAL || !LOCAL->dir) -+ return; -+ -+ maildir_delete_uid(stream, msgno); -+ snprintf(old, sizeof(old), "%s/%s/%s", LOCAL->dir, MDNAME(Cur), MDFILE(elt)); -+ t = MDFILE(elt); -+ if((s = strrchr(MDFILE(elt),FLAGSEP)) != NULL){ -+ *s++ = '\0'; -+ snprintf(new, sizeof(new), "%s/%s/%s%s%lu%c%s", -+ LOCAL->dir, MDNAME(Cur), t, MDUIDSEP, uid, FLAGSEP, s); -+ if(rename(old, new) == 0){ -+ maildir_free_file_only ((void **)&elt->private.spare.ptr); -+ s = strrchr(new, '/'); -+ MDFILE(elt) = cpystr(s+1); -+ stream->uid_validity = time(0); -+ } -+ elt->private.uid = uid; -+ } -+} -+ -+void -+maildir_uid_renew_tempfile(MAILSTREAM *stream) -+{ -+ char tmp[MAILTMPLEN]; -+ -+ if(!stream || stream->rdonly -+ || !LOCAL || !LOCAL->candouid || !LOCAL->dir || !LOCAL->uidtempfile) -+ return; -+ -+ if(mypid == (pid_t) 0) -+ mypid = getpid(); -+ -+ snprintf(tmp, sizeof(tmp), "%s/%s.%d.%lu", LOCAL->dir, MDUIDTEMP, mypid, time(0)); -+ if(rename(LOCAL->uidtempfile, tmp) == 0){ -+ fs_give((void **)&LOCAL->uidtempfile); -+ LOCAL->uidtempfile = cpystr(tmp); -+ } -+} -Index: alpine-2.25.1/imap/src/osdep/unix/maildir.h -=================================================================== ---- /dev/null -+++ alpine-2.25.1/imap/src/osdep/unix/maildir.h -@@ -0,0 +1,226 @@ -+/* -+ * A few definitions that try to make this module portable to other -+ * platforms (e.g. Cygwin). This module is based on the information from -+ * http://cr.yp.to/proto/maildir.html -+ */ -+ -+/* First we deal with the separator character */ -+#ifndef FLAGSEP -+#define FLAGSEP ':' -+#endif -+#define SIZESEP ',' -+ -+const char sep1[] = {FLAGSEP, '1', ',', '\0'}; /* experimental semantics*/ -+const char sep2[] = {FLAGSEP, '2', ',', '\0'}; /* Flags Information */ -+const char sep3[] = {FLAGSEP, '3', ',', '\0'}; /* Grrrr.... */ -+ -+const char *sep[] = { sep1, sep2, sep3, NULL}; -+ -+#define MDSEP(i) sep[((i) - 1)] -+ -+/* Now we deal with flags. Woohoo! */ -+typedef enum {Draft, Flagged, Passed, Replied, Seen, Trashed, -+ EmptyFlag, EndFlags} MdFlagNamesType; -+const int mdimapflags[] = {Draft, Flagged, Replied, Seen, Trashed, EmptyFlag, EndFlags}; -+const int mdkwdflags[] = {Passed, EmptyFlag, EndFlags}; -+ -+/* this array lists the codes for mdflgnms (maildir flag names) above */ -+const char *mdflags[] = { "D", "F", "P", "R", "S", "T", "", NULL}; -+/* and as characters too */ -+const char cmdflags[] = { 'D', 'F', 'P', 'R', 'S', 'T', '0', '\0'}; -+ -+/* MDFLAG(Seen, elt->seen) */ -+#define MDFLAG(i,j) mdflags[j ? (i) : EmptyFlag] -+/* MDFLAGC(Seen) */ -+#define MDFLAGC(i) cmdflags[(i)] -+ -+/* Now we deal with the directory structure */ -+typedef enum {Cur, Tmp, New, EndDir} DirNamesType; -+char *mdstruct[] = {"cur", "tmp", "new", NULL}; -+#define MDNAME(i) mdstruct[(i)] -+#define MDFLD(tmp, dir, i) sprintf((tmp),"%s/%s", (dir), mdstruct[(i)]) -+#define MSGPATH(tmp, dir, msg,i) sprintf((tmp),"%s/%s/%s", (dir), mdstruct[(i)],(msg)) -+ -+/* Files associated to a maildir directory */ -+ -+#define MDUIDVALIDITY ".uidvalidity" /* support for old maildirs */ -+#define MDDIR ".mdir" /* this folder is a directory */ -+#define MDUIDLAST ".uidlast" /* last assigned uid */ -+#define MDUIDTEMP ".uidtemp" /* We assign uid's no one else */ -+ -+ -+ -+/* Support of Courier Structure */ -+#define CCLIENT 0 -+#define COURIER 1 -+#define IS_CCLIENT(t) \ -+ (((t) && (t)[0] == '#' && ((t)[1] == 'm' || (t)[1] == 'M')\ -+ && ((t)[2] == 'd' || (t)[2] == 'D')\ -+ && (t)[3] == '/' && (t)[4] != '\0') ? 1 : 0) -+ -+#define IS_COURIER(t) \ -+ (((t) && (t)[0] == '#' && ((t)[1] == 'm' || (t)[1] == 'M')\ -+ && ((t)[2] == 'c' || (t)[2] == 'C')\ -+ && (t)[3] == '/' && (t)[4] != '\0') ? 1 : 0) -+#define MDPREFIX(s) ((s) ? "#mc/" : "#md/") -+#define MDSEPARATOR(s) ((s) ? '.' : '/') -+ -+/* UID Support */ -+ -+#define MAXTEMPUID (unsigned long) 180L -+const char mduid[] = {',','u','=','\0'}; -+#define MDUIDSEP mduid -+ -+ -+/* Now we deal with messages filenames */ -+char mdlocaldomain[MAILTMPLEN+1] = {'\0'}; -+pid_t mypid = (pid_t) 0; -+static char *mdfpath = NULL; -+static char myMdInboxDir[50] = { '\0' };/* Location of the Maildir INBOX */ -+static long CourierStyle = CCLIENT; -+ -+#define CHUNK 16384 /* from unix.h */ -+ -+typedef struct courier_local { -+ char *name; /* name of directory/folder */ -+ int attribute; /* attributes (children/marked/etc) */ -+} COURIERLOCAL; -+ -+typedef struct courier { -+ char *path; /* Path to collection */ -+ time_t scantime; /* time at which information was generated */ -+ int total; /* total number of elements in data */ -+ COURIERLOCAL **data; -+} COURIER_S; -+ -+/* In gdb this is the *(struct maildir_local *)stream->local structure */ -+typedef struct maildir_local { -+ unsigned int dirty : 1; /* diskcopy needs updating */ -+ unsigned int courier : 1; /* It is Courier style file system */ -+ unsigned int link : 1; /* There is a symbolic link */ -+ int candouid; /* we can assign uids and no one else */ -+ char *uidtempfile; /* path to uid temp file */ -+ int fd; /* fd of open message */ -+ char *dir; /* mail directory name */ -+ char **path; /* path to directories cur, new and tmp */ -+ unsigned char *buf; /* temporary buffer */ -+ unsigned long buflen; /* current size of temporary buffer */ -+ time_t scantime; /* last time directory scanned */ -+} MAILDIRLOCAL; -+ -+/* Convenient access to local data */ -+#define LOCAL ((MAILDIRLOCAL *) stream->local) -+ -+typedef struct maildir_file_info { -+ char *name; /* name of the file */ -+ DirNamesType loc; /* location of this file */ -+ unsigned long pos; /* place in list where this file is listed */ -+ off_t size; /* size in bytes, on disk */ -+ time_t atime; /* last access time */ -+ time_t mtime; /* last modified time */ -+ time_t ctime; /* last changed time */ -+} MAILDIRFILE; -+ -+#define MDFILE(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->name) -+#define MDLOC(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->loc) -+#define MDPOS(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->pos) -+#define MDSIZE(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->size) -+#define MDATIME(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->atime) -+#define MDMTIME(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->mtime) -+#define MDCTIME(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->ctime) -+ -+/* Function prototypes */ -+ -+DRIVER *maildir_valid (char *name); -+MAILSTREAM *maildir_open (MAILSTREAM *stream); -+void maildir_close (MAILSTREAM *stream, long options); -+long maildir_ping (MAILSTREAM *stream); -+void maildir_check (MAILSTREAM *stream); -+long maildir_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags); -+char *maildir_header (MAILSTREAM *stream,unsigned long msgno, -+ unsigned long *length, long flags); -+void maildir_list (MAILSTREAM *stream,char *ref,char *pat); -+void *maildir_parameters (long function,void *value); -+int maildir_create_folder (char *mailbox); -+long maildir_create (MAILSTREAM *stream,char *mailbox); -+void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt); /*check */ -+long maildir_expunge (MAILSTREAM *stream, char *sequence, long options); -+long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options); -+long maildir_append (MAILSTREAM *stream,char *mailbox, append_t af, void *data); -+long maildir_delete (MAILSTREAM *stream,char *mailbox); -+long maildir_rename (MAILSTREAM *stream,char *old,char *new); -+long maildir_sub (MAILSTREAM *stream,char *mailbox); -+long maildir_unsub (MAILSTREAM *stream,char *mailbox); -+void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat); -+void courier_list (MAILSTREAM *stream,char *ref, char *pat); -+ -+/* utility functions */ -+void courier_realname (char *name, char *realname); -+long maildir_dirfmttest (char *name); -+char *maildir_file (char *dst,char *name); -+int maildir_select (const struct direct *name); -+int maildir_namesort (const struct direct **d1, const struct direct **d2); -+unsigned long antoul (char *seed); -+unsigned long mdfntoul (char *name); -+int courier_dir_select (const struct direct *name); -+int courier_dir_sort (const struct direct **d1, const struct direct **d2); -+long maildir_canonicalize (char *pattern,char *ref,char *pat); -+void maildir_list_work (MAILSTREAM *stream,char *subdir,char *pat,long level); -+void courier_list_work (MAILSTREAM *stream,char *subdir,char *pat,long level); -+int maildir_file_path(char *name, char *tmp, size_t sizeoftmp); -+int maildir_valid_name (char *name); -+int maildir_valid_dir (char *name); -+int is_valid_maildir (char **name); -+int maildir_message_exists(MAILSTREAM *stream,char *name, char *tmp); -+char *maildir_remove_root(char *name); -+char *maildir_text_work (MAILSTREAM *stream,MESSAGECACHE *elt, unsigned long *length,long flags); -+unsigned long maildir_parse_message(MAILSTREAM *stream, unsigned long msgno, -+ DirNamesType dirtype); -+int maildir_eliminate_duplicate (char *name, struct direct ***flist, -+ unsigned long *nfiles); -+int maildir_doscandir (char *name, struct direct ***flist, int flag); -+unsigned long maildir_scandir (char *name, struct direct ***flist, -+ unsigned long *nfiles, int *scand, int flag); -+void maildir_parse_folder (MAILSTREAM *stream, int full); -+void md_domain_name (void); -+char *myrootdir (char *name); -+char *mdirpath (void); -+int maildir_initial_check (MAILSTREAM *stream, DirNamesType dirtype); -+unsigned long maildir_parse_dir(MAILSTREAM *stream, unsigned long nmsgs, -+ DirNamesType dirtype, struct direct **names, unsigned long nfiles, int full); -+int same_maildir_file(char *name1, char *name2); -+int comp_maildir_file(char *name1, char *name2); -+int maildir_message_in_list(char *msgname, struct direct **names, -+ unsigned long bottom, unsigned long top, unsigned long *pos); -+void maildir_getflag(char *name, int *d, int *f, int *r ,int *s, int *t); -+int maildir_update_elt_maildirp(MAILSTREAM *stream, unsigned long msgno); -+void maildir_abort (MAILSTREAM *stream); -+int maildir_contains_folder(char *dirname, char *name); -+int maildir_is_dir(char *dirname, char *name); -+int maildir_dir_is_empty(char *mailbox); -+int maildir_create_work (char *mailbox, int loop); -+void maildir_get_file (MAILDIRFILE **mdfile); -+void maildir_free_file (void **mdfile); -+void maildir_free_file_only (void **mdfile); -+int maildir_any_new_msgs(char *mailbox); -+void maildir_get_date(MAILSTREAM *stream, unsigned long msgno); -+void maildir_fast (MAILSTREAM *stream,char *sequence,long flags); -+ -+/* Courier server support */ -+void courier_free_cdir (COURIER_S **cdir); -+COURIER_S *courier_get_cdir (int total); -+int courier_search_list(COURIERLOCAL **data, char *name, int first, int last); -+COURIER_S *courier_list_dir(char *curdir); -+void courier_list_info(COURIER_S **cdirp, char *data, int i); -+ -+/* UID Support */ -+int maildir_can_assign_uid (MAILSTREAM *stream); -+void maildir_read_uid(MAILSTREAM *stream, unsigned long *uid_last, -+ unsigned long *uid_validity); -+void maildir_write_uid(MAILSTREAM *stream, unsigned long uid_last, -+ unsigned long uid_validity); -+unsigned long maildir_get_uid(char *name); -+void maildir_delete_uid(MAILSTREAM *stream, unsigned long msgno); -+void maildir_assign_uid(MAILSTREAM *stream, unsigned long msgno, unsigned long uid); -+void maildir_uid_renew_tempfile(MAILSTREAM *stream); -+ -Index: alpine-2.25.1/imap/src/osdep/unix/os_cyg.h -=================================================================== ---- alpine-2.25.1.orig/imap/src/osdep/unix/os_cyg.h -+++ alpine-2.25.1/imap/src/osdep/unix/os_cyg.h -@@ -47,6 +47,7 @@ - #define setpgrp setpgid - - #define SYSTEMUID 18 /* Cygwin returns this for SYSTEM */ -+#define FLAGSEP ';' - #define geteuid Geteuid - uid_t Geteuid (void); - -Index: alpine-2.25.1/pith/conf.c -=================================================================== ---- alpine-2.25.1.orig/pith/conf.c -+++ alpine-2.25.1/pith/conf.c -@@ -455,6 +455,9 @@ CONF_TXT_T cf_text_window_position[] = " - - CONF_TXT_T cf_text_newsrc_path[] = "Full path and name of NEWSRC file"; - -+#ifndef _WINDOWS -+CONF_TXT_T cf_text_maildir_location[] = "Location relative to your HOME directory of the directory where your INBOX\n# for the maildir format is located. Default value is \"Maildir\". If your\n# inbox is located at \"~/Maildir\" you do not need to change this value.\n# A common value is also \".maildir\""; -+#endif - - /*---------------------------------------------------------------------- - These are the variables that control a number of pine functions. They -@@ -663,6 +666,10 @@ static struct variable variables[] = { - NULL, cf_text_news_active}, - {"news-spool-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, - NULL, cf_text_news_spooldir}, -+#ifndef _WINDOWS -+{"maildir-location", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, -+ "Maildir Location", cf_text_maildir_location}, -+#endif - {"upload-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, - NULL, cf_text_upload_cmd}, - {"upload-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, -@@ -2409,6 +2416,12 @@ init_vars(struct pine *ps, void (*cmds_f - mail_parameters(NULL, SET_NEWSSPOOL, - (void *)VAR_NEWS_SPOOL_DIR); - -+#ifndef _WINDOWS -+ set_current_val(&vars[V_MAILDIR_LOCATION], TRUE, TRUE); -+ if(VAR_MAILDIR_LOCATION && VAR_MAILDIR_LOCATION[0]) -+ mail_parameters(NULL, SET_MDINBOXPATH, (void *)VAR_MAILDIR_LOCATION); -+#endif -+ - /* guarantee a save default */ - set_current_val(&vars[V_DEFAULT_SAVE_FOLDER], TRUE, TRUE); - if(!VAR_DEFAULT_SAVE_FOLDER || !VAR_DEFAULT_SAVE_FOLDER[0]) -@@ -3061,6 +3074,10 @@ feature_list(int index) - F_SORT_DEFAULT_SAVE_ALPHA, h_config_sort_save_alpha, PREF_FLDR, 0}, - {"vertical-folder-list", "Use Vertical Folder List", - F_VERTICAL_FOLDER_LIST, h_config_vertical_list, PREF_FLDR, 0}, -+#ifndef _WINDOWS -+ {"use-courier-folder-list", "Courier Style Folder List", -+ F_COURIER_FOLDER_LIST, h_config_courier_list, PREF_FLDR, 0}, -+#endif - - /* Addr book */ - {"combined-addrbook-display", "Combined Address Book Display", -@@ -7244,7 +7261,7 @@ toggle_feature(struct pine *ps, struct v - int just_flip_value, EditWhich ew) - { - char **vp, *p, **lval, ***alval; -- int og, on_before, was_set; -+ int og, on_before, was_set, i; - char *err; - long l; - -@@ -7297,6 +7314,13 @@ toggle_feature(struct pine *ps, struct v - - break; - -+#ifndef _WINDOWS -+ case F_COURIER_FOLDER_LIST: -+ i = F_ON(f->id ,ps) ? 1 : 0; -+ mail_parameters(NULL,SET_COURIERSTYLE, (void *) &i); -+ break; /* COURIER == 1, CCLIENT == 0, see maildir.h */ -+#endif -+ - case F_COLOR_LINE_IMPORTANT : - case F_DATES_TO_LOCAL : - clear_index_cache(ps->mail_stream, 0); -@@ -8105,6 +8129,10 @@ config_help(int var, int feature) - return(h_config_newmailwidth); - case V_NEWSRC_PATH : - return(h_config_newsrc_path); -+#ifndef _WINDOWS -+ case V_MAILDIR_LOCATION : -+ return(h_config_maildir_location); -+#endif - case V_BROWSER : - return(h_config_browser); - case V_HISTORY : -Index: alpine-2.25.1/pith/conf.h -=================================================================== ---- alpine-2.25.1.orig/pith/conf.h -+++ alpine-2.25.1/pith/conf.h -@@ -270,6 +270,10 @@ - #define GLO_NEWS_ACTIVE_PATH vars[V_NEWS_ACTIVE_PATH].global_val.p - #define VAR_NEWS_SPOOL_DIR vars[V_NEWS_SPOOL_DIR].current_val.p - #define GLO_NEWS_SPOOL_DIR vars[V_NEWS_SPOOL_DIR].global_val.p -+#ifndef _WINDOWS -+#define VAR_MAILDIR_LOCATION vars[V_MAILDIR_LOCATION].current_val.p -+#define GLO_MAILDIR_LOCATION vars[V_MAILDIR_LOCATION].global_val.p -+#endif - #define VAR_DISABLE_DRIVERS vars[V_DISABLE_DRIVERS].current_val.l - #define VAR_DISABLE_AUTHS vars[V_DISABLE_AUTHS].current_val.l - #define VAR_REMOTE_ABOOK_METADATA vars[V_REMOTE_ABOOK_METADATA].current_val.p -Index: alpine-2.25.1/pith/conftype.h -=================================================================== ---- alpine-2.25.1.orig/pith/conftype.h -+++ alpine-2.25.1/pith/conftype.h -@@ -120,6 +120,9 @@ typedef enum { V_PERSONAL_NAME = 0 - , V_NEWSRC_PATH - , V_NEWS_ACTIVE_PATH - , V_NEWS_SPOOL_DIR -+#ifndef _WINDOWS -+ , V_MAILDIR_LOCATION -+#endif - , V_UPLOAD_CMD - , V_UPLOAD_CMD_PREFIX - , V_DOWNLOAD_CMD -@@ -414,6 +417,9 @@ typedef enum { - F_PASS_C1_CONTROL_CHARS, - F_SINGLE_FOLDER_LIST, - F_VERTICAL_FOLDER_LIST, -+#ifndef _WINDOWS -+ F_COURIER_FOLDER_LIST, -+#endif - F_TAB_CHK_RECENT, - F_AUTO_REPLY_TO, - F_VERBOSE_POST, -Index: alpine-2.25.1/pith/init.c -=================================================================== ---- alpine-2.25.1.orig/pith/init.c -+++ alpine-2.25.1/pith/init.c -@@ -404,6 +404,9 @@ get_mail_list(CONTEXT_S *list_cntxt, cha - && stricmp(filename, folder_base)){ - #else - if(strncmp(filename, folder_base, folder_base_len) == 0 -+#ifndef _WINDOWS -+ && filename[folder_base_len] != list_cntxt->dir->delim -+#endif - && strcmp(filename, folder_base)){ - #endif - #endif -Index: alpine-2.25.1/pith/pattern.c -=================================================================== ---- alpine-2.25.1.orig/pith/pattern.c -+++ alpine-2.25.1/pith/pattern.c -@@ -46,7 +46,9 @@ - #include "../pith/icache.h" - #include "../pith/ablookup.h" - #include "../pith/keyword.h" -- -+#ifndef _WINDOWS -+int maildir_file_path(char *name, char *tmp, size_t sizeoftmp); -+#endif /* _WINDOWS */ - - /* - * Internal prototypes -@@ -5485,6 +5487,15 @@ match_pattern_folder_specific(PATTERN_S - break; - - case '#': -+#ifndef _WINDOWS -+ if(!struncmp(patfolder, "#md/", 4) -+ || !struncmp(patfolder, "#mc/", 4)){ -+ maildir_file_path(patfolder, tmp1, sizeof(tmp1)); -+ if(!strcmp(tmp1, stream->mailbox)) -+ match++; -+ break; -+ } -+#endif - if(!strcmp(patfolder, stream->mailbox)) - match++; - -@@ -7905,7 +7916,7 @@ move_filtered_msgs(MAILSTREAM *stream, M - int we_cancel = 0, width; - CONTEXT_S *save_context = NULL; - char buf[MAX_SCREEN_COLS+1], sbuf[MAX_SCREEN_COLS+1]; -- char *save_ref = NULL; -+ char *save_ref = NULL, *save_dstfldr = NULL, *save_dstfldr2 = NULL; - #define FILTMSG_MAX 30 - - if(!stream) -@@ -7939,6 +7950,16 @@ move_filtered_msgs(MAILSTREAM *stream, M - if(F_OFF(F_QUELL_FILTER_MSGS, ps_global)) - we_cancel = busy_cue(buf, NULL, 0); - -+#ifndef _WINDOWS -+ if(!struncmp(dstfldr, "#md/", 4) || !struncmp(dstfldr, "#mc/", 4)){ -+ char tmp1[MAILTMPLEN]; -+ maildir_file_path(dstfldr, tmp1, sizeof(tmp1)); -+ save_dstfldr2 = dstfldr; -+ save_dstfldr = cpystr(tmp1); -+ dstfldr = save_dstfldr; + } -+#endif -+ - if(!is_absolute_path(dstfldr) - && !(save_context = default_save_context(ps_global->context_list))) - save_context = ps_global->context_list; -@@ -8002,6 +8023,11 @@ move_filtered_msgs(MAILSTREAM *stream, M - if(we_cancel) - cancel_busy_cue(buf[0] ? 0 : -1); - -+ if(save_dstfldr){ -+ fs_give((void **)&save_dstfldr); -+ dstfldr = save_dstfldr2; ++ ++ fnlen = strlen(tmp); ++ if ((s = strrchr(mailbox,MDSEPARATOR(courier))) != NULL){ ++ c = *++s; ++ *s = '\0'; ++ if ((stat(tmp,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) && ++ !maildir_create_work (mailbox, ++loop)) ++ return NIL; ++ *s = c; ++ } ++ tmp[fnlen] = '\0'; ++ ++ if (mkdir(tmp,0700) && errno != EEXIST) ++ return NIL; ++ ++ if (create_dir) ++ mailbox[fnlen] = '/'; ++ ++ if (create_dir){ ++ if(style == CCLIENT){ ++ if(!courier){ ++ FILE *fp = NULL; ++ int len = (int) (sizeof(tmp2) - strlen(MDDIR)) - 1; ++ snprintf(tmp2, sizeof(tmp2), "%.*s%.*s", len, tmp, (int) strlen(MDDIR), MDDIR); ++ tmp2[sizeof(tmp2) - 1] = '\0'; ++ if ((fp = fopen(tmp2,"w")) == NULL){ ++ snprintf (err, sizeof(err), "Problem creating %.*s: %.*s", ++ len, tmp2, ++ (int) sizeof(err) - len - 19, strerror(errno)); ++ err[sizeof(err) - 1] = '\0'; ++ mm_log (err,ERROR); ++ return NIL; ++ } ++ fclose(fp); ++ } ++ } ++ return T; ++ } ++ else ++ return maildir_create_folder(tmp); ++ } ++ ++ long maildir_create (MAILSTREAM *stream,char *mailbox) ++ { ++ char tmp[MAILTMPLEN], err[MAILTMPLEN]; ++ int rv, create_dir; ++ ++ create_dir = mailbox ? ++ (mailbox[strlen(mailbox) - 1] == ++ MDSEPARATOR(IS_COURIER(mailbox))) : 0; ++ maildir_file_path(mailbox, tmp, sizeof(tmp)); ++ strcpy(tmp, mailbox); ++ rv = maildir_create_work(mailbox, 0); ++ strcpy(mailbox, tmp); ++ if (rv == 0){ ++ snprintf (err, sizeof(err), "Can't create %s %s", ++ (create_dir ? "directory" : "mailbox"), mailbox); ++ mm_log (err,ERROR); ++ } ++ return rv ? LONGT : NIL; ++ } ++ ++ #define MAXTRY 10000 ++ void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt) ++ { ++ char oldfile[MAILTMPLEN],newfile[MAILTMPLEN],fn[MAILTMPLEN]; ++ char *s; ++ int ren, try = 0; ++ ++ if (elt->valid){ ++ for (try = 1; try > 0 && try < MAXTRY; try++){ ++ /* build the new filename */ ++ snprintf (oldfile, sizeof(oldfile), "%s/%s",LOCAL->path[Cur], MDFILE(elt)); ++ fn[0] = '\0'; ++ if ((ren = maildir_message_exists(stream, MDFILE(elt), fn)) == 0){ ++ errno = ENOENT; ++ try = MAXTRY; ++ } ++ if (*fn){ /* new oldfile! */ ++ snprintf (oldfile,sizeof(oldfile),"%.*s/%.*s", ++ (int) strlen(LOCAL->path[Cur]), LOCAL->path[Cur], ++ (int) (sizeof(oldfile) - strlen(LOCAL->path[Cur])),fn); ++ oldfile[sizeof(oldfile) - 1] = '\0'; ++ } ++ if ((s = strrchr (MDFILE(elt), FLAGSEP))) *s = '\0'; ++ snprintf (fn, sizeof(fn), "%s%s%s%s%s%s%s", MDFILE(elt), MDSEP(2), ++ MDFLAG(Draft, elt->draft), MDFLAG(Flagged, elt->flagged), ++ MDFLAG(Replied, elt->answered), MDFLAG(Seen, elt->seen), ++ MDFLAG(Trashed, elt->deleted)); ++ snprintf (newfile, sizeof(newfile), "%.*s/%.*s", ++ (int) strlen(LOCAL->path[Cur]), LOCAL->path[Cur], ++ (int) (sizeof(newfile) - strlen(LOCAL->path[Cur]) - 4), fn); ++ newfile[sizeof(newfile) - 1] = '\0'; ++ if (ren != 0 && rename (oldfile,newfile) >= 0) ++ try = -1; ++ } ++ ++ if (try > 0){ ++ snprintf(oldfile, sizeof(oldfile), "Unable to write flags to disk: %s", ++ (errno == ENOENT) ? "message is gone!" : strerror (errno)); ++ mm_log(oldfile,ERROR); ++ return; ++ } ++ #ifdef __CYGWIN__ ++ utime(LOCAL->path[Cur], NIL); /* make sure next scan will catch the change */ ++ #endif ++ maildir_free_file_only ((void **) &elt->private.spare.ptr); ++ MDFILE(elt) = cpystr (fn); ++ } ++ } ++ ++ long maildir_expunge (MAILSTREAM *stream, char *sequence, long options) ++ { ++ long ret; ++ MESSAGECACHE *elt; ++ unsigned long i, n = 0L; ++ unsigned long recent = stream->recent; ++ char tmp[MAILTMPLEN]; ++ ++ mm_critical (stream); /* go critical */ ++ ret = sequence ? ((options & EX_UID) ? ++ mail_uid_sequence (stream,sequence) : ++ mail_sequence (stream,sequence)) : LONGT; ++ if(ret == 0L) ++ return 0L; ++ for (i = 1L; i <= stream->nmsgs;){ ++ elt = mail_elt (stream,i); ++ if (elt->deleted && (sequence ? elt->sequence : T)){ ++ snprintf (tmp, sizeof(tmp), "%s/%s", LOCAL->path[Cur], MDFILE(elt)); ++ if (unlink (tmp) < 0) {/* try to delete the message */ ++ snprintf (tmp, sizeof(tmp), "Expunge of message %ld failed, aborted: %s",i, ++ strerror (errno)); ++ if (!stream->silent) ++ mm_log (tmp,WARN); ++ break; ++ } ++ if (elt->private.spare.ptr) ++ maildir_free_file ((void **) &elt->private.spare.ptr); ++ if (elt->recent) --recent;/* if recent, note one less recent message */ ++ mail_expunged (stream,i); /* notify upper levels */ ++ n++; /* count up one more expunged message */ ++ } ++ else i++; ++ } ++ if(n){ /* output the news if any expunged */ ++ snprintf (tmp, sizeof(tmp), "Expunged %ld messages", n); ++ if (!stream->silent) ++ mm_log (tmp,(long) NIL); ++ } ++ else ++ if (!stream->silent) ++ mm_log ("No messages deleted, so no update needed",(long) NIL); ++ mm_nocritical (stream); /* release critical */ ++ /* notify upper level of new mailbox size */ ++ mail_exists (stream, stream->nmsgs); ++ mail_recent (stream, recent); ++ return ret; ++ } ++ ++ long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options) ++ { ++ STRING st; ++ MESSAGECACHE *elt; ++ unsigned long len; ++ int fd; ++ unsigned long i; ++ struct stat sbuf; ++ char tmp[MAILTMPLEN], flags[MAILTMPLEN], path[MAILTMPLEN], *s; ++ /* copy the messages */ ++ if ((options & CP_UID) ? mail_uid_sequence (stream, sequence) : ++ mail_sequence (stream,sequence)) ++ for (i = 1L; i <= stream->nmsgs; i++) ++ if ((elt = mail_elt (stream,i))->sequence){ ++ MSGPATH(path, LOCAL->dir, MDFILE(elt), MDLOC(elt)); ++ if (((fd = open (path,O_RDONLY,NIL)) < 0) ++ ||((!elt->rfc822_size && ++ ((stat(path, &sbuf) < 0) || !S_ISREG (sbuf.st_mode))))) ++ return NIL; ++ if(!elt->rfc822_size) MDSIZE(elt) = sbuf.st_size; ++ s = (char *) fs_get(MDSIZE(elt) + 1); ++ read (fd,s,MDSIZE(elt)); ++ s[MDSIZE(elt)] = '\0'; ++ close (fd); ++ len = strcrlfcpy (&LOCAL->buf,&LOCAL->buflen, s, MDSIZE(elt)); ++ INIT (&st,mail_string, LOCAL->buf, len); ++ elt->rfc822_size = len; ++ fs_give ((void **)&s); ++ ++ flags[0] = flags[1] = '\0'; ++ if (elt->seen) strcat (flags," \\Seen"); ++ if (elt->draft) strcat (flags," \\Draft"); ++ if (elt->deleted) strcat (flags," \\Deleted"); ++ if (elt->flagged) strcat (flags," \\Flagged"); ++ if (elt->answered) strcat (flags," \\Answered"); ++ flags[0] = '('; /* open list */ ++ strcat (flags,")"); /* close list */ ++ mail_date (tmp,elt); /* generate internal date */ ++ if (!mail_append_full (NIL, mailbox, flags, tmp, &st)) ++ return NIL; ++ if (options & CP_MOVE) elt->deleted = T; ++ } ++ return LONGT; /* return success */ ++ } ++ ++ long maildir_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data) ++ { ++ int fd, k, done, fail; ++ STRING *message; ++ char c,*s, *flags, *date; ++ char tmp[MAILTMPLEN],file[MAILTMPLEN],path1[MAILTMPLEN],path2[MAILTMPLEN]; ++ MESSAGECACHE elt; ++ long i, size = 0L, ret = LONGT, f; ++ unsigned long uf, ti; ++ static unsigned int transact = 0; ++ struct stat sbuf; ++ ++ if (!maildir_valid(mailbox)) { ++ snprintf (tmp, sizeof(tmp), "Not a valid Maildir mailbox: %s", mailbox); ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ ++ if (!*mdlocaldomain) ++ md_domain_name(); /* get domain name for maildir files in mdlocaldomain now! */ ++ ++ if (mypid == (pid_t) 0) ++ mypid = getpid(); ++ ++ if (!stream){ ++ stream = &maildirproto; ++ ++ for (k = 0; k < NUSERFLAGS && stream->user_flags[k]; ++k) ++ fs_give ((void **) &stream->user_flags[k]); ++ } ++ ++ if (!(*af)(stream, data, &flags, &date, &message)) return NIL; ++ ++ mm_critical (stream); /* go critical */ ++ do { ++ fail = done = 0; /* we have not determined name of message file yet */ ++ if (!SIZE (message)) { /* guard against zero-length */ ++ mm_log ("Append of zero-length message", ERROR); ++ ret = NIL; ++ break; ++ } ++ ++ if (date && !mail_parse_date(&elt,date)){ ++ snprintf (tmp, sizeof(tmp), "Bad date in append: %.80s", date); ++ mm_log (tmp, ERROR); ++ ret = NIL; ++ break; ++ } ++ ++ if(date){ ++ struct tm tm; ++ ++ tm.tm_sec = elt.seconds; ++ tm.tm_min = elt.minutes; ++ tm.tm_hour = elt.hours; ++ tm.tm_mday = elt.day; ++ tm.tm_mon = elt.month - 1; ++ tm.tm_year = BASEYEAR + elt.year - 1900; ++ ++ ti = mktime(&tm); ++ } else ti = time(0); ++ ++ f = mail_parse_flags (stream,flags,&uf); ++ do { ++ /* build file name we will use, fix by Chris Caputo */ ++ snprintf (file, sizeof(file), "%lu.%d_%09u.%.*s%.*s%.*s%.*s%.*s%.*s", ++ ti, mypid, transact++, ++ (int)(sizeof(file) - 50), mdlocaldomain, (int) strlen(MDSEP(2)), (f ? MDSEP(2) : ""), ++ 1, MDFLAG(Draft, f&fDRAFT), 1, MDFLAG(Flagged, f&fFLAGGED), ++ 1, MDFLAG(Replied, f&fANSWERED), 1, MDFLAG(Seen, f&fSEEN)); ++ /* build tmp file name */ ++ if (maildir_file_path(mailbox, tmp, sizeof(tmp))) /* copy in TMP */ ++ MSGPATH(path1, tmp, file, Tmp); ++ /* build final filename to use */ ++ if (maildir_file_path(mailbox, tmp, sizeof(tmp))) ++ MSGPATH(path2, tmp, file, New); /* copy in NEW */ ++ if(stat(path1, &sbuf) < 0 && errno == ENOENT ++ && stat(path2, &sbuf) < 0 && errno == ENOENT) ++ done++; ++ else ++ fail++; ++ if(fail == 1000){ ++ snprintf (tmp, sizeof(tmp), "Failure to create append message name"); ++ mm_log (tmp, ERROR); ++ return NIL; ++ } ++ } while (done == 0); ++ ++ if ((fd = open (path1,O_WRONLY|O_CREAT|O_EXCL,S_IREAD|S_IWRITE)) < 0) { ++ snprintf (tmp, sizeof(tmp), "Can't open append mailbox: %s", strerror (errno)); ++ mm_log (tmp, ERROR); ++ return NIL; ++ } ++ for (size = 0,i = SIZE (message),s = (char *) fs_get (i + 1); i; --i) ++ if ((c = SNX (message)) != '\015') s[size++] = c; ++ if ((write (fd, s, size) < 0) || fsync (fd)) { ++ unlink (path1); /* delete message */ ++ snprintf (tmp, sizeof(tmp), "Message append failed: %s", strerror (errno)); ++ mm_log (tmp, ERROR); ++ ret = NIL; ++ } ++ fs_give ((void **) &s); /* flush the buffer */ ++ close (fd); /* close the file */ ++ ++ if (rename (path1,path2) < 0) { ++ snprintf (tmp, sizeof(tmp), "Message append failed: %s", strerror (errno)); ++ mm_log (tmp, ERROR); ++ ret = NIL; ++ } ++ unlink (path1); ++ if(date){ ++ time_t tp[2]; ++ tp[0] = tp[1] = ti; ++ utime (path2,tp); ++ } ++ ++ if (ret) ++ if (!(*af) (stream,data,&flags,&date,&message)) ret = NIL; ++ ++ } while (ret && message); /* write the data */ ++ mm_nocritical (stream); /* release critical */ ++ return ret; ++ } ++ ++ long maildir_delete (MAILSTREAM *stream,char *mailbox) ++ { ++ DIR *dirp; ++ struct direct *d; ++ int i, remove_dir = 0, mddir = 0, rv, error = 0, len; ++ char tmp[MAILTMPLEN],tmp2[MAILTMPLEN], realname[MAILTMPLEN]; ++ struct stat sbuf; ++ int courier = IS_COURIER(mailbox); ++ ++ if (mailbox[strlen(mailbox) - 1] == MDSEPARATOR(courier)){ ++ remove_dir++; ++ mailbox[strlen(mailbox) -1] = '\0'; ++ } ++ ++ if (!maildir_valid(mailbox)){ ++ maildir_file_path(mailbox, tmp, sizeof(tmp)); ++ if (stat(tmp, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode)){ ++ snprintf(tmp, sizeof(tmp), "Can not remove %s", mailbox); ++ error++; ++ } ++ } ++ ++ if (!error && remove_dir && !maildir_dir_is_empty(mailbox)){ ++ snprintf(tmp, sizeof(tmp), "Can not remove directory %s/: directory not empty", mailbox); ++ error++; ++ } ++ ++ if(error){ ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ ++ maildir_close(stream,0); /* even if stream was NULL */ ++ ++ maildir_file_path(mailbox, realname, sizeof(realname)); ++ ++ if (remove_dir){ ++ snprintf(tmp, sizeof(tmp), "%.*s/%.*s", (int) (sizeof(tmp) - strlen(MDDIR) - 2), realname, (int) strlen(MDDIR), MDDIR); ++ tmp[sizeof(tmp) - 1] = '\0'; ++ if ((rv = stat (tmp,&sbuf)) == 0 && S_ISREG(sbuf.st_mode)) ++ rv = unlink(tmp); ++ else if (errno == ENOENT) ++ rv = 0; ++ if (rv != 0){ ++ len = (int) strlen(tmp2); ++ snprintf(tmp, sizeof(tmp), "Can not remove %.*s/%.*s: %.*s", ++ len, tmp2, ++ (int) strlen(MDDIR), MDDIR, ++ (int) (sizeof(tmp) - strlen(MDDIR)) - len - 19, strerror(errno)); ++ tmp[sizeof(tmp) - 1] = '\0'; ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ if (!maildir_valid(realname) && rmdir(realname) != 0){ ++ len = (int) strlen(mailbox); ++ snprintf(tmp, sizeof(tmp), "Can not remove %.*s/: %.*s", ++ len, mailbox, ++ (int)(sizeof(tmp) - len - 19), strerror(errno)); ++ tmp[sizeof(tmp)-1] = '\0'; ++ mm_log (tmp, ERROR); ++ return NIL; ++ } ++ return LONGT; ++ } ++ /* else remove just the folder. Remove all hidden files, except MDDIR */ ++ for (i = Cur; i != EndDir; i++){ ++ MDFLD(tmp, realname, i); ++ ++ if (!(dirp = opendir (tmp))){ ++ len = (int) strlen(mailbox); ++ snprintf(tmp, sizeof(tmp), "Can not read %.*s/: %.*s", ++ len, mailbox, ++ (int)(sizeof(tmp) - len - 19), strerror(errno)); ++ tmp[sizeof(tmp)-1] = '\0'; ++ mm_log (tmp, ERROR); ++ return NIL; ++ } ++ ++ while ((d = readdir(dirp)) != NULL){ ++ len = (int) strlen(tmp); ++ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..")){ ++ snprintf(tmp2, sizeof(tmp2), "%.*s/%.*s", ++ len, tmp, ++ (int) (sizeof(tmp) - len) -1, d->d_name); ++ tmp2[sizeof(tmp2) - 1] = '\0'; ++ if (unlink(tmp2) != 0){ ++ len = (int) strlen(mailbox); ++ snprintf(tmp2, sizeof(tmp2), "Can not remove %.*s: %.*s", ++ len, mailbox, ++ (int)(sizeof(tmp2) - len - 18), strerror(errno)); ++ tmp2[sizeof(tmp2)-1] = '\0'; ++ mm_log (tmp2, ERROR); ++ return NIL; ++ } ++ } ++ } ++ closedir(dirp); ++ if (rmdir(tmp) != 0){ ++ len = (int) strlen(mailbox); ++ snprintf(tmp, sizeof(tmp), "Can not remove %.*s: %.*s", ++ len, mailbox, ++ (int)(sizeof(tmp) - len - 18), strerror(errno)); ++ tmp[sizeof(tmp)-1] = '\0'; ++ mm_log (tmp, ERROR); ++ return NIL; ++ } ++ } ++ /* ++ * ok we have removed all subdirectories of the folder mailbox, Remove the ++ * hidden files. ++ */ ++ ++ if(!(dirp = opendir (realname))){ ++ len = (int) strlen(realname); ++ snprintf(tmp, sizeof(tmp), "Can not read %.*s/: %.*s", ++ len, realname, ++ (int)(sizeof(tmp) - len - 16), strerror(errno)); ++ tmp[sizeof(tmp)-1] = '\0'; ++ mm_log (tmp, ERROR); ++ return NIL; ++ } ++ ++ while ((d = readdir(dirp)) != NULL){ ++ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..") ++ && (!strcmp(d->d_name, MDDIR) ++ || !strncmp(d->d_name, MDUIDLAST, strlen(MDUIDLAST)) ++ || !strncmp(d->d_name, MDUIDTEMP, strlen(MDUIDTEMP)))){ ++ if(strcmp(d->d_name, MDDIR) == 0) ++ mddir++; ++ len = (int) strlen(realname); ++ snprintf(tmp, sizeof(tmp), "%.*s/%.*s", ++ len, realname, ++ (int)(sizeof(tmp) - len - 2), strerror(errno)); ++ tmp[sizeof(tmp)-1] = '\0'; ++ if (unlink(tmp) != 0) ++ error++; ++ } ++ } ++ closedir(dirp); ++ if (error || ++ (maildir_dir_is_empty(mailbox) && mddir == 0 && rmdir(realname) < 0)){ ++ len = (int) strlen(mailbox); ++ snprintf(tmp, sizeof(tmp), "Can not remove folder %.*s: %.*s", ++ len, mailbox, ++ (int)(sizeof(tmp) - len - 16), strerror(errno)); ++ tmp[sizeof(tmp)-1] = '\0'; ++ mm_log (tmp, ERROR); ++ return NIL; ++ } ++ return LONGT; ++ } ++ ++ long maildir_rename (MAILSTREAM *stream, char *old, char *new) ++ { ++ char tmp[MAILTMPLEN], tmpnew[MAILTMPLEN], realold[MAILTMPLEN]; ++ char realnew[MAILTMPLEN]; ++ int courier = IS_COURIER(old) && IS_COURIER(new); ++ int i, len; ++ long rv = LONGT; ++ COURIER_S *cdir; ++ ++ if((IS_COURIER(old) || IS_COURIER(new)) && !courier){ ++ len = (int) strlen(old); ++ snprintf (tmp, sizeof(tmp), "Can't rename mailbox %.*s to %.*s", ++ len, old, ++ (int) sizeof(tmp) - len - 26, new); ++ tmp[sizeof(tmp) - 1] = '\0'; ++ mm_log (tmp, ERROR); ++ return NIL; ++ } ++ ++ if (!maildir_valid(old)){ ++ snprintf (tmp, sizeof(tmp), "Can't rename mailbox %.*s: folder not in maildir format", ++ (int) sizeof(tmp) - 52, old); ++ tmp[sizeof(tmp) - 1] = '\0'; ++ mm_log (tmp, ERROR); ++ return NIL; ++ } ++ maildir_file_path(old, realold, sizeof(realold)); ++ if (!maildir_valid_name(new) && new[0] == '#'){ ++ snprintf (tmp, sizeof(tmp), "Cannot rename mailbox %.*s: folder not in maildir format", ++ (int) sizeof(tmp) - 53, new); ++ tmp[sizeof(tmp) - 1] = '\0'; ++ mm_log (tmp, ERROR); ++ return NIL; ++ } ++ maildir_file_path(new, realnew, sizeof(realnew)); ++ if (access(tmpnew,F_OK) == 0){ /* new mailbox name must not exist */ ++ snprintf (tmp, sizeof(tmp), "Cannot rename to mailbox %.*s: destination already exists", ++ (int)(sizeof(tmp) - 54), new); ++ tmp[sizeof(tmp) - 1] = '\0'; ++ mm_log (tmp, ERROR); ++ return NIL; ++ } ++ ++ if(!courier){ ++ if (rename(realold, realnew)){ /* try to rename the directory */ ++ int len2 = (int) strlen(new); ++ len = (int) strlen(old); ++ snprintf(tmp, sizeof(tmp), "Can't rename mailbox %.*s to %.*s: %.*s", ++ len, old, ++ len2, new, ++ (int) sizeof(tmp) - len - len2 - 28, strerror(errno)); ++ tmp[sizeof(tmp) - 1] = '\0'; ++ mm_log(tmp,ERROR); ++ return NIL; ++ } ++ return LONGT; /* return success */ ++ } ++ ++ cdir = courier_list_dir(old); ++ for (i = 0; cdir && i < cdir->total; i++){ ++ if(strstr(cdir->data[i]->name, old)){ ++ len = (int) strlen(new); ++ snprintf(tmp, sizeof(tmp), "%.*s%.*s", ++ len, new, ++ (int) sizeof(tmp) - len - 1, cdir->data[i]->name+strlen(old)); ++ tmp[sizeof(tmp) - 1] = '\0'; ++ maildir_file_path(cdir->data[i]->name, realold, sizeof(realold)); ++ maildir_file_path(tmp, realnew, sizeof(realnew)); ++ if (rename(realold, realnew)){ ++ int len2 = (int) strlen(new); ++ len = (int) strlen(old); ++ snprintf (tmp, sizeof(tmp), "Can't rename mailbox %.*s to %.*s: %.*s", ++ len, old, ++ len2, new, ++ (int) sizeof(tmp) - len - len2 - 28, strerror(errno)); ++ tmp[sizeof(tmp) - 1] = '\0'; ++ mm_log(tmp,ERROR); ++ rv = NIL; ++ } ++ } ++ } ++ courier_free_cdir(&cdir); ++ return rv; ++ } ++ ++ long maildir_sub(MAILSTREAM *stream,char *mailbox) ++ { ++ return sm_subscribe(mailbox); ++ } ++ ++ long maildir_unsub(MAILSTREAM *stream,char *mailbox) ++ { ++ return sm_unsubscribe(mailbox); ++ } ++ ++ void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat) ++ { ++ void *sdb = NIL; ++ char *s, test[MAILTMPLEN], tmp[MAILTMPLEN]; ++ /* get canonical form of name */ ++ if (maildir_canonicalize (test, ref, pat) && (s = sm_read (tmp, &sdb))) { ++ do if (pmatch_full (s, test, '/')) mm_lsub (stream, '/', s, NIL); ++ while ((s = sm_read (tmp, &sdb)) != NULL); /* until no more subscriptions */ ++ } ++ } ++ ++ long maildir_canonicalize (char *pattern,char *ref,char *pat) ++ { ++ if (ref && *ref) { /* have a reference */ ++ strcpy (pattern,ref); /* copy reference to pattern */ ++ /* # overrides mailbox field in reference */ ++ if (*pat == '#') strcpy (pattern,pat); ++ /* pattern starts, reference ends, with / */ ++ else if ((*pat == '/') && (pattern[strlen (pattern) - 1] == '/')) ++ strcat (pattern,pat + 1); /* append, omitting one of the period */ ++ ++ else strcat (pattern,pat); /* anything else is just appended */ ++ } ++ else strcpy (pattern,pat); /* just have basic name */ ++ return maildir_valid_name(pattern) ? LONGT : NIL; ++ } ++ ++ void maildir_list_work (MAILSTREAM *stream,char *dir,char *pat,long level) ++ { ++ DIR *dp; ++ struct direct *d; ++ struct stat sbuf; ++ char curdir[MAILTMPLEN],name[MAILTMPLEN], tmp[MAILTMPLEN]; ++ char realpat[MAILTMPLEN]; ++ long i; ++ int len; ++ char *maildirpath = mdirpath(); ++ ++ snprintf(curdir, sizeof(curdir), "%s/%s/", myrootdir(pat), dir ? dir : maildirpath); ++ if ((dp = opendir (curdir)) != NULL){ ++ if (dir) snprintf (name, sizeof(name), "%s%s/",MDPREFIX(CCLIENT),dir); ++ else strcpy (name, pat); ++ ++ if (level == 0 && !strpbrk(pat,"%*")){ ++ if(maildir_valid(pat)){ ++ i = maildir_contains_folder(pat, NULL) ++ ? LATT_HASCHILDREN ++ : (maildir_is_dir(pat, NULL) ++ ? LATT_HASNOCHILDREN : LATT_NOINFERIORS); ++ maildir_file_path(pat, realpat, sizeof(realpat)); ++ i += maildir_any_new_msgs(realpat) ++ ? LATT_MARKED : LATT_UNMARKED; ++ mm_list (stream,'/', pat, i); ++ } ++ else ++ if(pat[strlen(pat) - 1] == '/') ++ mm_list (stream,'/', pat, LATT_NOSELECT); ++ } ++ ++ len = (int) strlen(name); ++ while ((d = readdir (dp)) != NULL) ++ if(strcmp(d->d_name, ".") && strcmp(d->d_name,"..") ++ && strcmp(d->d_name, MDNAME(Cur)) ++ && strcmp(d->d_name, MDNAME(Tmp)) ++ && strcmp(d->d_name, MDNAME(New))){ ++ ++ if (dir) snprintf (tmp, sizeof(tmp), "%.*s%.*s", len, name,(int) sizeof(tmp) - len - 1, d->d_name); ++ else strcpy(tmp, d->d_name); ++ tmp[sizeof(tmp) - 1] = '\0'; ++ ++ if(pmatch_full (tmp, pat,'/')){ ++ snprintf(tmp, sizeof(tmp), "%s/%s/%s", myrootdir(d->d_name), ++ (dir ? dir : maildirpath), d->d_name); ++ if(stat (tmp,&sbuf) == 0 ++ && ((sbuf.st_mode & S_IFMT) == S_IFDIR)){ ++ if (dir) snprintf (tmp, sizeof(tmp), "%.*s%.*s", len, name, (int) sizeof(tmp) - len - 1, d->d_name); ++ else strcpy(tmp, d->d_name); ++ tmp[sizeof(tmp) - 1] = '\0'; ++ i = maildir_valid(tmp) ++ ? (maildir_contains_folder(dir, d->d_name) ++ ? LATT_HASCHILDREN ++ : (maildir_is_dir(dir, d->d_name) ++ ? LATT_HASNOCHILDREN : LATT_NOINFERIORS)) ++ : LATT_NOSELECT; ++ i += maildir_any_new_msgs(tmp) ++ ? LATT_MARKED : LATT_UNMARKED; ++ mm_list (stream,'/',tmp, i); ++ strcat (tmp, "/"); ++ if(dmatch (tmp, pat,'/') && ++ (level < (long) mail_parameters (NIL,GET_LISTMAXLEVEL,NIL))){ ++ snprintf(tmp, sizeof(tmp), "%s/%s",dir,d->d_name); ++ maildir_list_work (stream,tmp,pat,level+1); ++ } ++ } ++ } ++ } ++ closedir (dp); ++ } ++ } ++ ++ void courier_list_work (MAILSTREAM *stream, char *dir, char *pat, long level) ++ { ++ char c, curdir[MAILTMPLEN], tmp[MAILTMPLEN]; ++ char realname[MAILTMPLEN], realpat[MAILTMPLEN] = {'\0'}; ++ int i, found; ++ long style = *(long *) maildir_parameters(GET_COURIERSTYLE, NIL), j; ++ char *maildirpath = mdirpath(); ++ COURIER_S *cdir; ++ ++ if(!strpbrk(pat,"%*")){ /* a mailbox */ ++ maildir_file_path(pat, curdir, sizeof(curdir)); ++ i = strlen(curdir) - 1; ++ if(curdir[i] == '/') ++ curdir[i] = '\0'; ++ cdir = courier_list_dir(curdir); ++ if(cdir){ ++ found = 0; j = 0L; ++ if(maildir_valid_name(pat)){ ++ for(i = 0; !found && i < cdir->total; i++) ++ if(strstr(curdir, cdir->data[i]->name)){ ++ if(strlen(curdir) < strlen(cdir->data[i]->name)) ++ found += 2; ++ else if(strlen(curdir) == strlen(cdir->data[i]->name)) ++ found -= 1; ++ } ++ if(found > 0) ++ j = LATT_HASCHILDREN; ++ else if(found == 0) ++ j = (style == COURIER) ? LATT_HASNOCHILDREN : LATT_NOINFERIORS; ++ } ++ else ++ j = LATT_NOSELECT; ++ j += maildir_any_new_msgs(curdir) ? LATT_MARKED : LATT_UNMARKED; ++ if (found) ++ mm_list (stream, '.', pat, j); ++ courier_free_cdir(&cdir); ++ } ++ return; ++ } ++ ++ strcpy(tmp,pat + 4); /* a directory */ ++ j = strlen(pat) - 1; ++ maildir_file_path(pat, realpat, sizeof(realpat)); ++ c = pat[j]; ++ pat[j] = '\0'; ++ realname[0] = '\0'; ++ if(dir) ++ maildir_file_path(dir, realname, sizeof(realname)); ++ snprintf(curdir, sizeof(curdir), "%s%s%s/%s", (dir ? "" : myrootdir(pat)), (dir ? "" : "/"), ++ (dir ? realname : maildirpath), (dir ? "" : ".")); ++ snprintf(tmp, sizeof(tmp), "%s%s/.", MDPREFIX(COURIER), dir ? dir : maildirpath); ++ if (level == 0 && tmp && pmatch_full (tmp, realpat, '.')) ++ mm_list (stream,'.', tmp, LATT_NOSELECT); ++ ++ cdir = courier_list_dir(pat); ++ pat[j] = c; ++ for (i = 0; cdir && i < cdir->total; i++) ++ if(pmatch_full (cdir->data[i]->name, pat, '.')){ ++ snprintf(tmp, sizeof(tmp), "%s.", cdir->data[i]->name); ++ courier_list_info(&cdir, tmp, i); ++ mm_list (stream,'.',cdir->data[i]->name, cdir->data[i]->attribute); + } -+ - return(buf[0] != '\0'); - } - -Index: alpine-2.25.1/pith/pine.hlp -=================================================================== ---- alpine-2.25.1.orig/pith/pine.hlp -+++ alpine-2.25.1/pith/pine.hlp -@@ -23888,6 +23888,102 @@ your account's home directory). - <End of help on this topic> - - -+====== h_config_maildir_location ====== -+ -+ -+OPTION: <!--#echo var="VAR_maildir-location"--> -+ -+ -+

    OPTION:

    -+ -+

    -+This option should be used only if you have a Maildir folder which you -+want to use as your INBOX. If this is not your case (or don't know what -+this is), you can safely ignore this option. -+ -+

    -+This option overrides the default directory Pine uses to find the location of -+your INBOX, in case this is in Maildir format. The default value of this -+option is "Maildir", but in some systems, this directory could have been -+renamed (e.g. to ".maildir"). If this is your case use this option to change -+the default. -+ -+

    -+The value of this option is prefixed with the "~/" string to determine the -+full path to your INBOX. -+ -+

    -+You should probably read a few tips that -+teach you how to configure your maildir for optimal performance. This -+version also has support for the -+Courier style file system when a maildir collection is accessed locally. -+ -+

    -+

    -+<End of help on this topic> -+ -+ -+====== h_config_maildir ===== -+ -+ -+Maildir Support -+ -+ -+

    Maildir Support

    -+ -+This version of Alpine has been enhanced with Maildir support. This text is -+intended to be a reference on its support. -+

    -+ -+A Maildir folder is a directory that contains three directories called -+cur, tmp and new. A program that delivers mail (e.g. postfix) will put new -+mail in the new directory. A program that reads mail will look for for old -+messages in the cur directory, while it will look for new mail in the new -+directory. -+

    -+ -+In order to use maildir support it is better to set your inbox-path to the -+value "#md/inbox" (without quotes). This assumes that your mail -+delivery agent is delivering new mail to ~/Maildir/new. If the directory -+where new mail is being delivered is not called "Maildir", you can set the -+name of the subdirectory of home where it is being delivered in the configuration -+variable. Most of the time you will not have to worry about the -+ variable, because it will probably be set by your -+administrator in the pine.conf configuration file. -+

    -+ -+One of the advantages of the Maildir support of this version of Alpine is -+that you do not have to stop using folders in another styles (mbox, mbx, -+etc.). This is desirable since the usage of a specific mail storage system -+is a personal decision. Folders in the maildir format that are part of the -+Mail collection will be recognized without any extra configuration of your -+part. If your mail/ collection is located under the mail/ directory, then -+creating a new maildir folder in this collection is done by pressing "A" -+and entering the string "#driver.md/mail/newfolder". Observe that adding a -+new folder as "newfolder" may not create such folder in maildir format. -+ -+

    -+If you would like to have all folders created in the maildir format by -+default, you do so by adding a Maildir Collection. In order to convert -+your current mail/ collection into a maildir collection, edit the -+collection and change the path variable from "mail/" to -+"#md/mail". In a maildir collection folders of any other format -+are ignored. -+ -+

    Finally, This version also has -+support for the Courier style file system -+when a maildir collection is accessed locally. -+ -+

    -+

    -+<End of help on this topic> -+ -+ - ====== h_config_literal_sig ===== - - -@@ -32170,6 +32266,49 @@ than across the columns as is the defaul -

    - <End of help on this topic> - -+ -+====== h_config_courier_list ===== -+ -+ -+FEATURE: <!--#echo var="FEAT_courier-folder-list"--> -+ -+ -+

    FEATURE:

    -+ -+In a maildir collection, a folder could be used as a directory to store -+folders. In the Courier server if you create a folder, then a directory -+with the same name is created. If you use this patch to access a -+collection created by the Courier server, then the display of such -+collection will look confusing. The best way to access a maildir -+collection created by the Courier server is by using the "#mc/" -+prefix instead of the "#md/" prefix. If you use this alternate -+prefix, then this feature applies to you, otherwise you can safely ignore -+the text that follows. -+

    -+Depending on if you have enabled the option -+ -+a folder may be listed as "folder[.]", or as two entries in the -+list by "folder" and "folder.". -+

    -+If this option is disabled, Pine will list local folders that are in Courier -+style format, as "folder", and those that are also directories as -+"folder[.]". This makes the default display cleaner. -+

    -+If this feature is enabled then creating folders in a maildir collection -+will create a directory with the same name. If this feature is disabled, then -+a folder is considered a directory only if it contains subfolders, so you can -+not create a directory with the same name as an exisiting folder unless -+you create a subfolder of that folder first (e.g. if you have a folder -+called "foo" simply add "foo.bar" directly. This will -+create the directory "foo" and the subfolder "bar" of it). -+

    -+Observe that this feature works only for maildir collections that are accessed -+locally. If a collection is accessed remotely then this feature has no value, -+as the report is created in a server, and Pine only reports what received -+from the server in this case. -+

    -+<End of help on this topic> -+ - - ====== h_config_verbose_post ===== - -Index: alpine-2.25.1/pith/send.c -=================================================================== ---- alpine-2.25.1.orig/pith/send.c -+++ alpine-2.25.1/pith/send.c -@@ -43,6 +43,9 @@ - - #include "../c-client/smtp.h" - #include "../c-client/nntp.h" -+#ifndef _WINDOWS -+int maildir_file_path(char *name, char *tmp, size_t sizeoftmp); -+#endif /* _WINDOWS */ - - - /* this is used in pine_send and pine_simple_send */ -@@ -246,6 +249,13 @@ postponed_stream(MAILSTREAM **streamp, c - - if(exists & FEX_ISFILE){ - context_apply(tmp, p_cntxt, mbox, sizeof(tmp)); -+#ifndef _WINDOWS -+ if (!struncmp(tmp, "#md/",4) || !struncmp(tmp, "#mc/", 4)){ -+ char tmp2[MAILTMPLEN]; -+ maildir_file_path(tmp, tmp2, sizeof(tmp2)); -+ strcpy(tmp, tmp2); -+ } -+#endif - if(!(IS_REMOTE(tmp) || is_absolute_path(tmp))){ - /* - * The mbox is relative to the home directory. ++ courier_free_cdir(&cdir); ++ } ++ ++ int ++ same_maildir_file(char *name1, char *name2) ++ { ++ char tmp1[MAILTMPLEN], tmp2[MAILTMPLEN]; ++ char *s; ++ ++ strcpy(tmp1, name1 ? name1 : ""); ++ strcpy(tmp2, name2 ? name2 : ""); ++ if ((s = strrchr(tmp1, FLAGSEP)) != NULL) ++ *s = '\0'; ++ if (((s = strrchr(tmp1, SIZESEP)) != NULL) && (strchr(s,'.') == NULL)) ++ *s = '\0'; ++ if ((s = strrchr(tmp2, FLAGSEP)) != NULL) ++ *s = '\0'; ++ if (((s = strrchr(tmp2, SIZESEP)) != NULL) && (strchr(s,'.') == NULL)) ++ *s = '\0'; ++ ++ return !strcmp(tmp1, tmp2); ++ } ++ ++ unsigned long antoul(char *seed) ++ { ++ int i, error = 0; ++ unsigned long val = 0L, rv1 = 0L, t; ++ char c, *p; ++ if(!seed) ++ return 0L; ++ t = strtoul(seed, &p, 10); ++ if(p && (*p == '.' || *p == '_')) ++ return t; ++ /* else */ ++ if((p = strchr(seed,'.')) != NULL) ++ *p = '\0'; ++ error = (strlen(seed) > 6); /* too long */ ++ for(i= strlen(seed)-1; error == 0 && i >= 0; i--){ ++ c = seed[i]; ++ if (c >= 'A' && c <= 'Z') val = c - 'A'; ++ else if (c >= 'a' && c <= 'z') val = c - 'a' + 26; ++ else if (c >= '0' && c <= '9') val = c - '0' + 26 + 26; ++ else if (c == '-') val = c - '-' + 26 + 26 + 10; ++ else if (c == '_') val = c - '_' + 26 + 26 + 10 + 1; ++ else error++; ++ rv1 = val + (rv1 << 6); ++ } ++ if(p) ++ *p = '.'; ++ return error ? 0L : rv1; ++ } ++ ++ unsigned long mdfntoul (char *name) ++ { ++ unsigned long t; ++ char *r, last; ++ ++ if((*name == '_') && ((r = strpbrk(name,".,%+")) != NULL)){ /* Grrr!!! */ ++ last = *r; ++ *r = '\0'; ++ t = antoul(r+1); ++ *r = last; ++ } ++ else ++ t = antoul(name); ++ return t; ++ } ++ ++ int comp_maildir_file(char *name1, char *name2) ++ { ++ int uset1 = 1, uset2 = 1, i, j, cmp; ++ unsigned long t1, t2; ++ char *s1, *s2; ++ ++ if (!(name1 && *name1)) ++ return (name2 && *name2) ? (*name2 == FLAGSEP ? 0 : -1) : 0; ++ ++ if (!(name2 && *name2)) ++ return (name1 && *name1) ? (*name1 == FLAGSEP ? 0 : 1) : 0; ++ ++ if((cmp = strcmp(name1,name2)) == 0) ++ return 0; ++ ++ t1 = strtoul(name1, &s1, 10); ++ t2 = strtoul(name2, &s2, 10); ++ ++ if(!s1 || *s1 != '.') ++ uset1 = 0; ++ ++ if(!s2 || *s2 != '.') ++ uset2 = 0; ++ ++ if(uset1 && uset2) /* normal sort order */ ++ return (t1 < t2) ? -1 : (t1 > t2 ? 1 : (cmp < 0 ? -1 : 1)); ++ ++ /* If we make it here we say Grrrr.... first, then we try to figure out ++ * how to sort this mess. ++ * These are the rules. ++ * If there is a number at the beginning it is bigger than anything else. ++ * If there are digits, then the number of digits decides which one is bigger. ++ */ ++ ++ for(i = 0; isdigit(name1[i]); i++); ++ for(j = 0; isdigit(name2[j]); j++); ++ ++ return(uset1 ? 1 ++ : (uset2 ? -1 ++ : (i < j ? -1 : (i > j ? 1 : (cmp < 0 ? -1 : 1))))); ++ } ++ ++ void ++ maildir_getflag(char *name, int *d, int *f, int *r ,int *s, int *t) ++ { ++ char tmp[MAILTMPLEN], *b; ++ int offset = 0; ++ int tmpd, tmpf, tmpr, tmps, tmpt; ++ int done = 0; /* fix by Chris Caputo */ ++ ++ if(d) *d = 0; ++ if(f) *f = 0; ++ if(r) *r = 0; ++ if(s) *s = 0; ++ if(t) *t = 0; ++ ++ tmpd = tmpf = tmpr = tmps = tmpt = NIL; /* no flags set by default */ ++ strcpy(tmp,name); ++ while (!done && (b = strrchr(tmp+offset, FLAGSEP)) != NULL){ /* fix by Chris Caputo */ ++ char flag,last; ++ int k; ++ if (!++b) break; ++ switch (*b){ ++ case '1': ++ case '2': ++ case '3': flag = *b; b += 2; ++ for (k = 0; b[k] && b[k] != FLAGSEP && b[k] != ','; k++); ++ last = b[k]; ++ b[k] = '\0'; ++ if (flag == '2' || flag == '3'){ ++ tmpd = strchr (b, MDFLAGC(Draft)) ? T : NIL; ++ tmpf = strchr (b, MDFLAGC(Flagged)) ? T : NIL; ++ tmpr = strchr (b, MDFLAGC(Replied)) ? T : NIL; ++ tmps = strchr (b, MDFLAGC(Seen)) ? T : NIL; ++ tmpt = strchr (b, MDFLAGC(Trashed)) ? T : NIL; ++ } ++ b[k] = last; ++ b += k; ++ break; ++ default: done++; /* fix by Chris Caputo */ ++ break; ++ } ++ offset++; ++ for (; tmp[offset] && tmp[offset] != FLAGSEP; offset++); ++ } ++ if(d) *d = tmpd; ++ if(f) *f = tmpf; ++ if(r) *r = tmpr; ++ if(s) *s = tmps; ++ if(t) *t = tmpt; ++ } ++ ++ int ++ maildir_message_in_list(char *msgname, struct direct **names, ++ unsigned long bottom, unsigned long top, unsigned long *pos) ++ { ++ unsigned long middle = (bottom + top)/2; ++ int test; ++ ++ if (!msgname) ++ return NIL; ++ ++ if (pos) *pos = middle; ++ ++ if (same_maildir_file(msgname, names[middle]->d_name)) ++ return T; ++ ++ if (middle == bottom){ /* 0 <= 0 < 1 */ ++ int rv = NIL; ++ if (same_maildir_file(msgname, names[middle]->d_name)){ ++ rv = T; ++ if (pos) *pos = middle; ++ } ++ else ++ if (same_maildir_file(msgname, names[top]->d_name)){ ++ rv = T; ++ if (pos) *pos = top; ++ } ++ return rv; ++ } ++ ++ test = comp_maildir_file(msgname, names[middle]->d_name); ++ ++ if (top <= bottom) ++ return test ? NIL : T; ++ ++ if (test < 0 ) /* bottom < msgname < middle */ ++ return maildir_message_in_list(msgname, names, bottom, middle, pos); ++ else if (test > 0) /* middle < msgname < top */ ++ return maildir_message_in_list(msgname, names, middle, top, pos); ++ else return T; ++ } ++ ++ void ++ maildir_abort(MAILSTREAM *stream) ++ { ++ if (LOCAL){ ++ DirNamesType i; ++ ++ if(LOCAL->candouid) ++ maildir_read_uid(stream, NULL, &stream->uid_validity); ++ if (LOCAL->dir) fs_give ((void **) &LOCAL->dir); ++ for (i = Cur; i < EndDir; i++) ++ if(LOCAL->path[i]) fs_give ((void **) &LOCAL->path[i]); ++ fs_give ((void **) &LOCAL->path); ++ if (LOCAL->buf) fs_give ((void **) &LOCAL->buf); ++ if(LOCAL->uidtempfile){ ++ unlink(LOCAL->uidtempfile); ++ fs_give ((void **) &LOCAL->uidtempfile); ++ } ++ fs_give ((void **) &stream->local); ++ } ++ if (mdfpath) fs_give((void **)&mdfpath); ++ stream->dtb = NIL; ++ } ++ ++ int ++ maildir_contains_folder(char *dirname, char *name) ++ { ++ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN]; ++ int rv = 0, len; ++ DIR *dir; ++ struct direct *d; ++ ++ maildir_file_path(dirname, tmp2, sizeof(tmp2)); ++ if(name){ ++ strcat(tmp2,"/"); ++ strcat(tmp2, name); ++ } ++ ++ if (!(dir = opendir (tmp2))) ++ return NIL; ++ ++ len = (int) strlen(tmp2); ++ ++ while ((d = readdir(dir)) != NULL){ ++ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..") ++ && strcmp(d->d_name, MDNAME(Cur)) ++ && strcmp(d->d_name, MDNAME(Tmp)) ++ && strcmp(d->d_name, MDNAME(New))){ ++ ++ snprintf(tmp, sizeof(tmp), "%.*s/%.*s", len, tmp2, (int) sizeof(tmp) - len - 2, d->d_name); ++ tmp[sizeof(tmp) - 1] = '\0'; ++ if(maildir_valid(tmp)){ ++ rv++; ++ break; ++ } ++ } ++ } ++ closedir(dir); ++ return rv; ++ } ++ ++ int ++ maildir_is_dir(char *dirname, char *name) ++ { ++ char tmp[MAILTMPLEN]; ++ struct stat sbuf; ++ ++ maildir_file_path(dirname, tmp, sizeof(tmp)); ++ if(name){ ++ strcat(tmp, "/"); ++ strcat(tmp, name); ++ } ++ strcat(tmp, "/"); ++ strcat(tmp, MDDIR); ++ ++ return ((stat(tmp, &sbuf) == 0) && S_ISREG (sbuf.st_mode)) ? 1 : 0; ++ } ++ ++ int ++ maildir_dir_is_empty(char *mailbox) ++ { ++ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN], tmp3[MAILTMPLEN],*s; ++ int rv = 1, courier = IS_COURIER(mailbox), len; ++ DIR *dir; ++ struct direct *d; ++ struct stat sbuf; ++ ++ maildir_file_path(mailbox, tmp2, sizeof(tmp2)); ++ ++ if(courier){ ++ strcpy(tmp3, tmp2); ++ if((s = strrchr(tmp2, '/')) != NULL) ++ *s = '\0'; ++ } ++ ++ if (!(dir = opendir (tmp2))) ++ return rv; ++ ++ len = (int) strlen(tmp2); ++ ++ if(courier){ ++ while((d = readdir(dir)) != NULL){ ++ snprintf(tmp, sizeof(tmp), "%.*s/%.*s", len, tmp2, (int)(sizeof(tmp) - len - 2),d->d_name); ++ tmp[sizeof(tmp) - 1] = '\0'; ++ if(!strncmp(tmp, tmp3, strlen(tmp3)) ++ && tmp[strlen(tmp3)] == '.'){ ++ rv = 0; ++ break; ++ } ++ } ++ } ++ else ++ while ((d = readdir(dir)) != NULL){ ++ snprintf(tmp, sizeof(tmp), "%.*s/%.*s", len, tmp2, (int)(sizeof(tmp) - len - 2), d->d_name); ++ tmp[sizeof(tmp) - 1] = '\0'; ++ if (strcmp(d->d_name, ".") ++ && strcmp(d->d_name,"..") ++ && strcmp(d->d_name, MDNAME(Cur)) ++ && strcmp(d->d_name, MDNAME(Tmp)) ++ && strcmp(d->d_name, MDNAME(New)) ++ && strcmp(d->d_name, MDDIR) ++ && strcmp(d->d_name, MDUIDVALIDITY) ++ && strncmp(d->d_name, MDUIDTEMP, 8) ++ && strcmp(d->d_name, ".mbsyncstate") ++ && strcmp(d->d_name, ".mbsyncstate") ++ && strcmp(d->d_name, ".mbsyncstate.new") ++ && strcmp(d->d_name, ".mbsyncstate.journal") ++ && strcmp(d->d_name, ".mbsyncstate.lock") ++ && !(d->d_name[0] == '.' ++ && stat (tmp,&sbuf) == 0 ++ && S_ISREG(sbuf.st_mode))){ ++ rv = 0; ++ break; ++ } ++ } ++ closedir(dir); ++ return rv; ++ } ++ ++ void ++ maildir_get_file (MAILDIRFILE **mdfile) ++ { ++ MAILDIRFILE *md; ++ ++ md = (MAILDIRFILE *) fs_get(sizeof(MAILDIRFILE)); ++ memset(md, 0, sizeof(MAILDIRFILE)); ++ *mdfile = md; ++ } ++ ++ void ++ maildir_free_file (void **mdfile) ++ { ++ MAILDIRFILE *md = (mdfile && *mdfile) ? (MAILDIRFILE *) *mdfile : NULL; ++ ++ if (md){ ++ if (md->name) fs_give((void **)&md->name); ++ fs_give((void **)&md); ++ } ++ } ++ ++ void ++ maildir_free_file_only (void **mdfile) ++ { ++ MAILDIRFILE *md = (mdfile && *mdfile) ? (MAILDIRFILE *) *mdfile : NULL; ++ ++ if (md && md->name) ++ fs_give((void **)&md->name); ++ } ++ ++ int ++ maildir_any_new_msgs(char *mailbox) ++ { ++ char tmp[MAILTMPLEN]; ++ int rv = NIL; ++ DIR *dir; ++ struct direct *d; ++ ++ MDFLD(tmp, mailbox, New); ++ ++ if (!(dir = opendir (tmp))) ++ return rv; ++ ++ while ((d = readdir(dir)) != NULL){ ++ if (d->d_name[0] == '.') ++ continue; ++ rv = T; ++ break; ++ } ++ closedir(dir); ++ return rv; ++ } ++ ++ ++ void ++ maildir_get_date(MAILSTREAM *stream, unsigned long msgno) ++ { ++ MESSAGECACHE *elt; ++ struct tm *t; ++ time_t ti; ++ int i,k; ++ ++ elt = mail_elt (stream,msgno); ++ if(elt && elt->year != 0) ++ return; ++ if ((ti = mdfntoul(MDFILE(elt))) > 0L && (t = gmtime(&ti))){ ++ i = t->tm_hour * 60 + t->tm_min; ++ k = t->tm_yday; ++ t = localtime(&ti); ++ i = t->tm_hour * 60 + t->tm_min - i; ++ if((k = t->tm_yday - k) != 0) ++ i += ((k < 0) == (abs (k) == 1)) ? -24*60 : 24*60; ++ k = abs (i); ++ elt->hours = t->tm_hour; ++ elt->minutes = t->tm_min; ++ elt->seconds = t->tm_sec; ++ elt->day = t->tm_mday; elt->month = t->tm_mon + 1; ++ elt->year = t->tm_year - (BASEYEAR - 1900); ++ elt->zoccident = (k == i) ? 0 : 1; ++ elt->zhours = k/60; ++ elt->zminutes = k % 60; ++ } ++ } ++ ++ /* Support for Courier Style directories ++ When this code is complete there will be two types of support, which ++ will be configurable. The problem is the following: In Courier style ++ folder structure, a "folder" may have a subfolder called ++ "folder.subfolder", which is not natural in the file system in the ++ sense that I can not stat for "folder.subfolder" wihtout knowing what ++ "subfolder" is. It needs to be guessed. Because of this I need to look ++ in the list of folders if there is a folder with a name ++ "folder.subfolder", before I can say if the folder is dual or not. One ++ can avoid this annoyance if one ignores the problem by declaring that ++ every folder is dual. I will however code as the default the more ++ complicated idea of scaning the containing directory each time it is ++ modified and search for subfolders, and list the entries it found. ++ */ ++ ++ int courier_dir_select (const struct direct *name) ++ { ++ return name->d_name[0] == '.' && (strlen(name->d_name) > 2 ++ || (strlen(name->d_name) == 2 && name->d_name[1] != '.')); ++ } ++ ++ int courier_dir_sort (const struct direct **d1, const struct direct **d2) ++ { ++ const struct direct *e1 = *(const struct direct **) d1; ++ const struct direct *e2 = *(const struct direct **) d2; ++ ++ return strcmp((char *) e1->d_name, (char *) e2->d_name); ++ } ++ ++ void courier_free_cdir (COURIER_S **cdir) ++ { ++ int i; ++ ++ if (!*cdir) ++ return; ++ ++ if ((*cdir)->path) fs_give((void **)&((*cdir)->path)); ++ for (i = 0; i < (*cdir)->total; i++) ++ if((*cdir)->data[i]->name) fs_give((void **)&((*cdir)->data[i]->name)); ++ fs_give((void **)&((*cdir)->data)); ++ fs_give((void **)&(*cdir)); ++ } ++ ++ COURIER_S *courier_get_cdir (int total) ++ { ++ COURIER_S *cdir; ++ ++ cdir = (COURIER_S *)fs_get(sizeof(COURIER_S)); ++ memset(cdir, 0, sizeof(COURIER_S)); ++ cdir->data = (COURIERLOCAL **) fs_get(total*sizeof(COURIERLOCAL *)); ++ memset(cdir->data, 0, sizeof(COURIERLOCAL *)); ++ cdir->total = total; ++ return cdir; ++ } ++ ++ int courier_search_list(COURIERLOCAL **data, char *name, int first, int last) ++ { ++ int try = (first + last)/2; ++ ++ if(!strstr(data[try]->name, name)){ ++ if(first == try) /* first == last || first + 1 == last */ ++ return strstr(data[last]->name, name) ? 1 : 0; ++ if(strcmp(data[try]->name, name) < 0) /*data[try] < name < data[end] */ ++ return courier_search_list(data, name, try, last); ++ else /* data[begin] < name < data[try] */ ++ return courier_search_list(data, name, first, try); ++ } ++ return 1; ++ } ++ ++ /* Lists all directories that are subdirectories of a given directory */ ++ ++ COURIER_S *courier_list_dir(char *curdir) ++ { ++ struct direct **names = NIL; ++ struct stat sbuf; ++ unsigned long ndir; ++ COURIER_S *cdir = NULL; ++ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN], pathname[MAILTMPLEN], ++ realname[MAILTMPLEN]; ++ int i, j, scand, td; ++ ++ /* There are two cases, either curdir is ++ #mc/INBOX. #mc/INBOX.foo ++ or ++ #mc/Maildir/. #mc/Maildir/.foo ++ */ ++ strcpy(tmp,curdir + 4); ++ if(!strncmp(ucase(tmp), "INBOX", 5)) ++ strcpy(tmp, "#mc/INBOX."); ++ else{ ++ strcpy(tmp, curdir); ++ for (i = strlen(tmp) - 1; tmp[i] && tmp[i] != '/'; i--); ++ tmp[i+2] = '\0'; /* keep the last "." intact */ ++ } ++ maildir_file_path(tmp, realname, sizeof(realname)); ++ maildir_scandir (realname, &names, &ndir, &scand, COURIER); ++ ++ if (scand > 0){ ++ cdir = courier_get_cdir(ndir); ++ cdir->path = cpystr(realname); ++ for(i = 0, j = 0; i < ndir; i++){ ++ td = realname[strlen(realname) - 1] == '.' ++ && *names[i]->d_name == '.'; ++ snprintf(tmp2, sizeof(tmp2), "%s%s", tmp, names[i]->d_name+1); ++ snprintf(pathname, sizeof(pathname), "%s%s", realname, names[i]->d_name + td); ++ if(stat(pathname, &sbuf) == 0 && S_ISDIR(sbuf.st_mode)){ ++ cdir->data[j] = (COURIERLOCAL *) fs_get(sizeof(COURIERLOCAL)); ++ cdir->data[j++]->name = cpystr(tmp2); ++ } ++ fs_give((void **)&names[i]); ++ } ++ cdir->total = j; ++ if(cdir->total == 0) ++ courier_free_cdir(&cdir); ++ } ++ if(names) ++ fs_give((void **) &names); ++ return cdir; ++ } ++ ++ void ++ courier_list_info(COURIER_S **cdirp, char *data, int i) ++ { ++ long style = *(long *) maildir_parameters(GET_COURIERSTYLE, NIL); ++ COURIER_S *cdir = *cdirp; ++ ++ if(maildir_valid(cdir->data[i]->name)){ ++ if(courier_search_list(cdir->data, data, 0, cdir->total - 1)) ++ cdir->data[i]->attribute = LATT_HASCHILDREN; ++ else ++ cdir->data[i]->attribute = (style == COURIER) ++ ? LATT_HASNOCHILDREN : LATT_NOINFERIORS; ++ } ++ else ++ cdir->data[i]->attribute = LATT_NOSELECT; ++ cdir->data[i]->attribute += maildir_any_new_msgs(cdir->data[i]->name) ++ ? LATT_MARKED : LATT_UNMARKED; ++ } ++ ++ /* UID Support */ ++ /* Yes, I know I procastinated a lot about this, but here it is finally */ ++ ++ /* return code: ++ bigger than zero: this session can assign uids ++ zero: this session will not assign uid ++ smaller than zero: this session temporarily suspends assigning uids ++ */ ++ int ++ maildir_can_assign_uid (MAILSTREAM *stream) ++ { ++ unsigned int rv = 0; ++ int ownuid, existuid; ++ unsigned long t; ++ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN], *p, *s; ++ DIR *dir; ++ struct direct *d; ++ ++ if(!stream || stream->rdonly ++ || !LOCAL || !LOCAL->dir || !(dir = opendir(LOCAL->dir))) ++ return 0; ++ ++ if(mypid == (pid_t) 0) ++ mypid = getpid(); ++ ++ snprintf(tmp, sizeof(tmp), "%s.%d", MDUIDTEMP, mypid); ++ ++ ownuid = existuid = 0; ++ s = NULL; ++ while ((d = readdir(dir)) != NULL){ ++ if(strncmp(d->d_name, tmp, strlen(tmp)) == 0){ ++ existuid++; ownuid++; ++ if(ownuid > 1){ ++ snprintf(tmp2, sizeof(tmp), "%s/%s", LOCAL->dir, d->d_name); ++ unlink(tmp2); ++ if(s){ ++ snprintf(tmp2, sizeof(tmp2), "%s/%s", LOCAL->dir, s); ++ unlink(tmp2); ++ fs_give((void **)&s); ++ } ++ } ++ else ++ s = cpystr(d->d_name); ++ } ++ else if(strncmp(d->d_name, MDUIDTEMP, strlen(MDUIDTEMP)) == 0) ++ existuid++; ++ } ++ ++ closedir(dir); ++ if(s) ++ fs_give((void **)&s); ++ ++ if(ownuid == 1 && existuid == 1) ++ rv = 1; ++ ++ if(ownuid == 0 && existuid == 0){ /* nobody owns the uid? */ ++ FILE *fp; ++ snprintf(tmp, sizeof(tmp), "%s/%s.%d.%lu", LOCAL->dir, MDUIDTEMP, mypid, time(0)); ++ if((fp = fopen(tmp, "w")) != NULL){ ++ fclose(fp); ++ if(LOCAL->uidtempfile) ++ fs_give((void **)&LOCAL->uidtempfile); ++ LOCAL->uidtempfile = cpystr(tmp); ++ } ++ rv = 1; ++ } ++ ++ if(ownuid == 0 && existuid > 0) /* someone else owns uid assignment */ ++ return 0; ++ ++ /* if we own the uid, check that we do not own it more than once ++ * or that we share ownership. If any of these situations happens, ++ * give up the ownership until we can recover it ++ */ ++ ++ if(ownuid > 0){ ++ if(ownuid > 1) /* impossible, two lock files for the same session */ ++ return (-1)*ownuid; ++ ++ if(ownuid != existuid){ /* lock files for different sessions */ ++ if(LOCAL->uidtempfile){ ++ unlink(LOCAL->uidtempfile); ++ fs_give((void **)&LOCAL->uidtempfile); ++ } ++ return (-1)*ownuid; ++ } ++ } ++ ++ return rv; ++ } ++ ++ void ++ maildir_read_uid(MAILSTREAM *stream, unsigned long *uid_last, ++ unsigned long *uid_validity) ++ { ++ int createuid, deleteuid = 0; ++ char tmp[MAILTMPLEN], *s = NULL; ++ DIR *dir; ++ struct direct *d; ++ ++ if(uid_last) *uid_last = 0L; ++ if(uid_last && uid_validity) *uid_validity = time(0); ++ if(!stream || !LOCAL || !LOCAL->dir || !(dir = opendir(LOCAL->dir))) ++ return; ++ ++ while ((d = readdir(dir)) != NULL){ ++ if(!strncmp(d->d_name, MDUIDLAST, strlen(MDUIDLAST))) ++ break; ++ } ++ createuid = d == NULL ? 1 : 0; ++ if(uid_last == NULL) ++ deleteuid++; ++ if(d){ ++ if(uid_last){ ++ s = d->d_name + strlen(MDUIDLAST) + 1; ++ *uid_last = strtoul(s, &s, 10); ++ if(!s || *s != '.'){ ++ deleteuid++; ++ createuid++; ++ *uid_last = 0L; ++ } ++ } ++ if(s && *s == '.'){ ++ if(uid_validity){ ++ s++; ++ *uid_validity = strtoul(s, &s, 10); ++ if(s && *s != '\0'){ ++ *uid_validity = time(0); ++ deleteuid++; ++ createuid++; ++ } ++ } ++ } ++ else{ ++ deleteuid++; ++ createuid++; ++ } ++ } ++ if(deleteuid){ ++ snprintf(tmp, sizeof(tmp), "%s/%s", LOCAL->dir, d->d_name); ++ unlink(tmp); ++ } ++ if(createuid) ++ maildir_write_uid(stream, (uid_last ? *uid_last : stream->uid_last), ++ uid_validity ? *uid_validity : time(0)); ++ closedir(dir); ++ } ++ ++ void ++ maildir_write_uid(MAILSTREAM *stream, unsigned long uid_last, ++ unsigned long uid_validity) ++ { ++ char tmp[MAILTMPLEN]; ++ FILE *fp; ++ ++ if(!stream || stream->rdonly || !LOCAL || !LOCAL->dir) ++ return; ++ ++ snprintf(tmp, sizeof(tmp), "%s/%s.%010lu.%010lu", LOCAL->dir, MDUIDLAST, ++ uid_last, uid_validity); ++ if((fp = fopen(tmp, "w")) != NULL) ++ fclose(fp); ++ } ++ ++ unsigned long ++ maildir_get_uid(char *name) ++ { ++ char *s; ++ unsigned long rv = 0L; ++ ++ if(!name || (s = strstr(name,MDUIDSEP)) == NULL) ++ return rv; ++ ++ s += strlen(MDUIDSEP); ++ rv = strtoul(s, NULL, 10); ++ return rv; ++ } ++ ++ ++ void ++ maildir_delete_uid(MAILSTREAM *stream, unsigned long msgno) ++ { ++ char old[MAILTMPLEN], new[MAILTMPLEN], *s, *t; ++ MESSAGECACHE *elt; ++ ++ elt = mail_elt(stream, msgno); ++ if(!stream || !elt || !elt->private.spare.ptr || !LOCAL || !LOCAL->dir) ++ return; ++ ++ snprintf(old, sizeof(old), "%s/%s/%s", LOCAL->dir, MDNAME(Cur), MDFILE(elt)); ++ t = MDFILE(elt); ++ if((s = strstr(MDFILE(elt), MDUIDSEP)) != NULL){ ++ *s = '\0'; ++ s += strlen(MDUIDSEP); ++ strtoul(s, &s, 10); ++ snprintf(new, sizeof(new), "%s/%s/%s%s", LOCAL->dir, MDNAME(Cur), t, s); ++ if(rename(old, new) == 0){ ++ maildir_free_file_only ((void **)&elt->private.spare.ptr); ++ s = strrchr(new, '/'); ++ MDFILE(elt) = cpystr(s+1); ++ } ++ elt->private.uid = 0L; ++ } ++ } ++ ++ void ++ maildir_assign_uid(MAILSTREAM *stream, unsigned long msgno, unsigned long uid) ++ { ++ int createuid, deleteuid = 0; ++ char old[MAILTMPLEN], new[MAILTMPLEN], *s, *t; ++ MESSAGECACHE *elt; ++ ++ elt = mail_elt(stream, msgno); ++ if(!stream || !elt || !elt->private.spare.ptr || !LOCAL || !LOCAL->dir) ++ return; ++ ++ maildir_delete_uid(stream, msgno); ++ snprintf(old, sizeof(old), "%s/%s/%s", LOCAL->dir, MDNAME(Cur), MDFILE(elt)); ++ t = MDFILE(elt); ++ if((s = strrchr(MDFILE(elt),FLAGSEP)) != NULL){ ++ *s++ = '\0'; ++ snprintf(new, sizeof(new), "%s/%s/%s%s%lu%c%s", ++ LOCAL->dir, MDNAME(Cur), t, MDUIDSEP, uid, FLAGSEP, s); ++ if(rename(old, new) == 0){ ++ maildir_free_file_only ((void **)&elt->private.spare.ptr); ++ s = strrchr(new, '/'); ++ MDFILE(elt) = cpystr(s+1); ++ stream->uid_validity = time(0); ++ } ++ elt->private.uid = uid; ++ } ++ } ++ ++ void ++ maildir_uid_renew_tempfile(MAILSTREAM *stream) ++ { ++ char tmp[MAILTMPLEN]; ++ ++ if(!stream || stream->rdonly ++ || !LOCAL || !LOCAL->candouid || !LOCAL->dir || !LOCAL->uidtempfile) ++ return; ++ ++ if(mypid == (pid_t) 0) ++ mypid = getpid(); ++ ++ snprintf(tmp, sizeof(tmp), "%s/%s.%d.%lu", LOCAL->dir, MDUIDTEMP, mypid, time(0)); ++ if(rename(LOCAL->uidtempfile, tmp) == 0){ ++ fs_give((void **)&LOCAL->uidtempfile); ++ LOCAL->uidtempfile = cpystr(tmp); ++ } ++ } +diff -rc alpine-2.26/imap/src/osdep/unix/maildir.h alpine-2.26.maildir/imap/src/osdep/unix/maildir.h +*** alpine-2.26/imap/src/osdep/unix/maildir.h 2022-06-02 18:14:52.323147655 -0600 +--- alpine-2.26.maildir/imap/src/osdep/unix/maildir.h 2022-06-02 18:14:52.251147832 -0600 +*************** +*** 0 **** +--- 1,122 ---- ++ typedef enum {Draft, Flagged, Passed, Replied, Seen, Trashed, ++ EmptyFlag, EndFlags} MdFlagNamesType; ++ ++ typedef enum {Cur, Tmp, New, EndDir} DirNamesType; ++ ++ typedef struct courier_local { ++ char *name; /* name of directory/folder */ ++ int attribute; /* attributes (children/marked/etc) */ ++ } COURIERLOCAL; ++ ++ typedef struct courier { ++ char *path; /* Path to collection */ ++ time_t scantime; /* time at which information was generated */ ++ int total; /* total number of elements in data */ ++ COURIERLOCAL **data; ++ } COURIER_S; ++ ++ typedef struct maildir_file_info { ++ char *name; /* name of the file */ ++ DirNamesType loc; /* location of this file */ ++ unsigned long pos; /* place in list where this file is listed */ ++ off_t size; /* size in bytes, on disk */ ++ time_t atime; /* last access time */ ++ time_t mtime; /* last modified time */ ++ time_t ctime; /* last changed time */ ++ } MAILDIRFILE; ++ ++ /* Function prototypes */ ++ ++ DRIVER *maildir_valid (char *name); ++ MAILSTREAM *maildir_open (MAILSTREAM *stream); ++ void maildir_close (MAILSTREAM *stream, long options); ++ long maildir_ping (MAILSTREAM *stream); ++ void maildir_check (MAILSTREAM *stream); ++ long maildir_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags); ++ char *maildir_header (MAILSTREAM *stream,unsigned long msgno, ++ unsigned long *length, long flags); ++ void maildir_list (MAILSTREAM *stream,char *ref,char *pat); ++ void *maildir_parameters (long function,void *value); ++ int maildir_create_folder (char *mailbox); ++ long maildir_create (MAILSTREAM *stream,char *mailbox); ++ void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt); /*check */ ++ long maildir_expunge (MAILSTREAM *stream, char *sequence, long options); ++ long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options); ++ long maildir_append (MAILSTREAM *stream,char *mailbox, append_t af, void *data); ++ long maildir_delete (MAILSTREAM *stream,char *mailbox); ++ long maildir_rename (MAILSTREAM *stream,char *old,char *new); ++ long maildir_sub (MAILSTREAM *stream,char *mailbox); ++ long maildir_unsub (MAILSTREAM *stream,char *mailbox); ++ void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat); ++ void courier_list (MAILSTREAM *stream,char *ref, char *pat); ++ ++ /* utility functions */ ++ void courier_realname (char *name, char *realname); ++ long maildir_dirfmttest (char *name); ++ char *maildir_file (char *dst,char *name); ++ int maildir_select (const struct direct *name); ++ int maildir_namesort (const struct direct **d1, const struct direct **d2); ++ unsigned long antoul (char *seed); ++ unsigned long mdfntoul (char *name); ++ int courier_dir_select (const struct direct *name); ++ int courier_dir_sort (const struct direct **d1, const struct direct **d2); ++ long maildir_canonicalize (char *pattern,char *ref,char *pat); ++ void maildir_list_work (MAILSTREAM *stream,char *subdir,char *pat,long level); ++ void courier_list_work (MAILSTREAM *stream,char *subdir,char *pat,long level); ++ int maildir_file_path(char *name, char *tmp, size_t sizeoftmp); ++ int maildir_valid_name (char *name); ++ int maildir_valid_dir (char *name); ++ int is_valid_maildir (char **name); ++ int maildir_message_exists(MAILSTREAM *stream,char *name, char *tmp); ++ char *maildir_remove_root(char *name); ++ char *maildir_text_work (MAILSTREAM *stream,MESSAGECACHE *elt, unsigned long *length,long flags); ++ unsigned long maildir_parse_message(MAILSTREAM *stream, unsigned long msgno, ++ DirNamesType dirtype); ++ int maildir_eliminate_duplicate (char *name, struct direct ***flist, ++ unsigned long *nfiles); ++ int maildir_doscandir (char *name, struct direct ***flist, int flag); ++ unsigned long maildir_scandir (char *name, struct direct ***flist, ++ unsigned long *nfiles, int *scand, int flag); ++ void maildir_parse_folder (MAILSTREAM *stream, int full); ++ void md_domain_name (void); ++ char *myrootdir (char *name); ++ char *mdirpath (void); ++ int maildir_initial_check (MAILSTREAM *stream, DirNamesType dirtype); ++ unsigned long maildir_parse_dir(MAILSTREAM *stream, unsigned long nmsgs, ++ DirNamesType dirtype, struct direct **names, unsigned long nfiles, int full); ++ int same_maildir_file(char *name1, char *name2); ++ int comp_maildir_file(char *name1, char *name2); ++ int maildir_message_in_list(char *msgname, struct direct **names, ++ unsigned long bottom, unsigned long top, unsigned long *pos); ++ void maildir_getflag(char *name, int *d, int *f, int *r ,int *s, int *t); ++ int maildir_update_elt_maildirp(MAILSTREAM *stream, unsigned long msgno); ++ void maildir_abort (MAILSTREAM *stream); ++ int maildir_contains_folder(char *dirname, char *name); ++ int maildir_is_dir(char *dirname, char *name); ++ int maildir_dir_is_empty(char *mailbox); ++ int maildir_create_work (char *mailbox, int loop); ++ void maildir_get_file (MAILDIRFILE **mdfile); ++ void maildir_free_file (void **mdfile); ++ void maildir_free_file_only (void **mdfile); ++ int maildir_any_new_msgs(char *mailbox); ++ void maildir_get_date(MAILSTREAM *stream, unsigned long msgno); ++ void maildir_fast (MAILSTREAM *stream,char *sequence,long flags); ++ ++ /* Courier server support */ ++ void courier_free_cdir (COURIER_S **cdir); ++ COURIER_S *courier_get_cdir (int total); ++ int courier_search_list(COURIERLOCAL **data, char *name, int first, int last); ++ COURIER_S *courier_list_dir(char *curdir); ++ void courier_list_info(COURIER_S **cdirp, char *data, int i); ++ ++ /* UID Support */ ++ int maildir_can_assign_uid (MAILSTREAM *stream); ++ void maildir_read_uid(MAILSTREAM *stream, unsigned long *uid_last, ++ unsigned long *uid_validity); ++ void maildir_write_uid(MAILSTREAM *stream, unsigned long uid_last, ++ unsigned long uid_validity); ++ unsigned long maildir_get_uid(char *name); ++ void maildir_delete_uid(MAILSTREAM *stream, unsigned long msgno); ++ void maildir_assign_uid(MAILSTREAM *stream, unsigned long msgno, unsigned long uid); ++ void maildir_uid_renew_tempfile(MAILSTREAM *stream); ++ +diff -rc alpine-2.26/imap/src/osdep/unix/Makefile alpine-2.26.maildir/imap/src/osdep/unix/Makefile +*** alpine-2.26/imap/src/osdep/unix/Makefile 2022-06-02 18:14:00.475274788 -0600 +--- alpine-2.26.maildir/imap/src/osdep/unix/Makefile 2022-06-02 18:14:52.255147822 -0600 +*************** +*** 146,152 **** + # However, mh needs to be before any sysinbox formats (such as mmdf or unix) + # since otherwise INBOX won't work correctly when mh_allow_inbox is set. + # +! DEFAULTDRIVERS=imap nntp pop3 mix mx mbx tenex mtx mh mmdf unix news phile + CHUNKSIZE=65536 + + # Normally no need to change any of these +--- 146,152 ---- + # However, mh needs to be before any sysinbox formats (such as mmdf or unix) + # since otherwise INBOX won't work correctly when mh_allow_inbox is set. + # +! DEFAULTDRIVERS=maildir courier imap nntp pop3 mix mx mbx tenex mtx mh mmdf unix news phile + CHUNKSIZE=65536 + + # Normally no need to change any of these +*************** +*** 155,161 **** + BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o utf8aux.o siglocal.o \ + dummy.o pseudo.o netmsg.o flstring.o fdstring.o \ + rfc822.o nntp.o smtp.o imap4r1.o http.o json.o pop3.o \ +! unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o mix.o sha.o + CFLAGS=-g + + CAT=cat +--- 155,163 ---- + BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o utf8aux.o siglocal.o \ + dummy.o pseudo.o netmsg.o flstring.o fdstring.o \ + rfc822.o nntp.o smtp.o imap4r1.o http.o json.o pop3.o \ +! unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o mix.o \ +! maildir.o sha.o +! + CFLAGS=-g + + CAT=cat +*************** +*** 292,298 **** + + cyg: # Cygwin - note that most local file drivers don't work!! + $(BUILD) `$(CAT) SPECIALS` OS=$@ \ +! DEFAULTDRIVERS="imap nntp pop3 mbx unix phile" \ + SIGTYPE=psx CHECKPW=cyg LOGINPW=cyg CRXTYPE=std \ + SPOOLDIR=/var \ + ACTIVEFILE=/usr/local/news/lib/active \ +--- 294,300 ---- + + cyg: # Cygwin - note that most local file drivers don't work!! + $(BUILD) `$(CAT) SPECIALS` OS=$@ \ +! DEFAULTDRIVERS="imap nntp pop3 mbx unix maildir phile" \ + SIGTYPE=psx CHECKPW=cyg LOGINPW=cyg CRXTYPE=std \ + SPOOLDIR=/var \ + ACTIVEFILE=/usr/local/news/lib/active \ +*************** +*** 922,927 **** +--- 924,930 ---- + json.o: mail.h misc.h osdep.h utf8.h json.h + http.o: mail.h misc.h osdep.h utf8.h http.h json.h + sha.o: mail.h misc.h osdep.h sha.h sha-private.h hash.h hmac.c sha1.c sha224-256.c sha384-512.c usha.c ++ maildir.o: mail.h misc.h osdep.h maildir.h dummy.h + + # OS-dependent + +diff -rc alpine-2.26/imap/src/osdep/unix/os_cyg.h alpine-2.26.maildir/imap/src/osdep/unix/os_cyg.h +*** alpine-2.26/imap/src/osdep/unix/os_cyg.h 2022-06-02 18:14:00.475274788 -0600 +--- alpine-2.26.maildir/imap/src/osdep/unix/os_cyg.h 2022-06-02 18:14:52.255147822 -0600 +*************** +*** 47,52 **** +--- 47,53 ---- + #define setpgrp setpgid + + #define SYSTEMUID 18 /* Cygwin returns this for SYSTEM */ ++ #define FLAGSEP ';' + #define geteuid Geteuid + uid_t Geteuid (void); + +diff -rc alpine-2.26/pith/conf.c alpine-2.26.maildir/pith/conf.c +*** alpine-2.26/pith/conf.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.maildir/pith/conf.c 2022-06-02 18:14:52.259147813 -0600 +*************** +*** 451,456 **** +--- 451,459 ---- + + CONF_TXT_T cf_text_newsrc_path[] = "Full path and name of NEWSRC file"; + ++ #ifndef _WINDOWS ++ CONF_TXT_T cf_text_maildir_location[] = "Location relative to your HOME directory of the directory where your INBOX\n# for the maildir format is located. Default value is \"Maildir\". If your\n# inbox is located at \"~/Maildir\" you do not need to change this value.\n# A common value is also \".maildir\""; ++ #endif + + /*---------------------------------------------------------------------- + These are the variables that control a number of pine functions. They +*************** +*** 655,660 **** +--- 658,667 ---- + NULL, cf_text_news_active}, + {"news-spool-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, + NULL, cf_text_news_spooldir}, ++ #ifndef _WINDOWS ++ {"maildir-location", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, ++ "Maildir Location", cf_text_maildir_location}, ++ #endif + {"upload-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, + NULL, cf_text_upload_cmd}, + {"upload-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, +*************** +*** 2396,2401 **** +--- 2403,2414 ---- + mail_parameters(NULL, SET_NEWSSPOOL, + (void *)VAR_NEWS_SPOOL_DIR); + ++ #ifndef _WINDOWS ++ set_current_val(&vars[V_MAILDIR_LOCATION], TRUE, TRUE); ++ if(VAR_MAILDIR_LOCATION && VAR_MAILDIR_LOCATION[0]) ++ mail_parameters(NULL, SET_MDINBOXPATH, (void *)VAR_MAILDIR_LOCATION); ++ #endif ++ + /* guarantee a save default */ + set_current_val(&vars[V_DEFAULT_SAVE_FOLDER], TRUE, TRUE); + if(!VAR_DEFAULT_SAVE_FOLDER || !VAR_DEFAULT_SAVE_FOLDER[0]) +*************** +*** 3037,3042 **** +--- 3050,3059 ---- + F_SORT_DEFAULT_SAVE_ALPHA, h_config_sort_save_alpha, PREF_FLDR, 0}, + {"vertical-folder-list", "Use Vertical Folder List", + F_VERTICAL_FOLDER_LIST, h_config_vertical_list, PREF_FLDR, 0}, ++ #ifndef _WINDOWS ++ {"use-courier-folder-list", "Courier Style Folder List", ++ F_COURIER_FOLDER_LIST, h_config_courier_list, PREF_FLDR, 0}, ++ #endif + + /* Addr book */ + {"combined-addrbook-display", "Combined Address Book Display", +*************** +*** 7217,7223 **** + int just_flip_value, EditWhich ew) + { + char **vp, *p, **lval, ***alval; +! int og, on_before, was_set; + char *err; + long l; + +--- 7234,7240 ---- + int just_flip_value, EditWhich ew) + { + char **vp, *p, **lval, ***alval; +! int og, on_before, was_set, i; + char *err; + long l; + +*************** +*** 7270,7275 **** +--- 7287,7299 ---- + + break; + ++ #ifndef _WINDOWS ++ case F_COURIER_FOLDER_LIST: ++ i = F_ON(f->id ,ps) ? 1 : 0; ++ mail_parameters(NULL,SET_COURIERSTYLE, (void *) &i); ++ break; /* COURIER == 1, CCLIENT == 0, see maildir.h */ ++ #endif ++ + case F_COLOR_LINE_IMPORTANT : + case F_DATES_TO_LOCAL : + clear_index_cache(ps->mail_stream, 0); +*************** +*** 8074,8079 **** +--- 8098,8107 ---- + return(h_config_newmailwidth); + case V_NEWSRC_PATH : + return(h_config_newsrc_path); ++ #ifndef _WINDOWS ++ case V_MAILDIR_LOCATION : ++ return(h_config_maildir_location); ++ #endif + case V_BROWSER : + return(h_config_browser); + case V_HISTORY : +diff -rc alpine-2.26/pith/conf.h alpine-2.26.maildir/pith/conf.h +*** alpine-2.26/pith/conf.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.maildir/pith/conf.h 2022-06-02 18:14:52.263147802 -0600 +*************** +*** 265,270 **** +--- 265,274 ---- + #define GLO_NEWS_ACTIVE_PATH vars[V_NEWS_ACTIVE_PATH].global_val.p + #define VAR_NEWS_SPOOL_DIR vars[V_NEWS_SPOOL_DIR].current_val.p + #define GLO_NEWS_SPOOL_DIR vars[V_NEWS_SPOOL_DIR].global_val.p ++ #ifndef _WINDOWS ++ #define VAR_MAILDIR_LOCATION vars[V_MAILDIR_LOCATION].current_val.p ++ #define GLO_MAILDIR_LOCATION vars[V_MAILDIR_LOCATION].global_val.p ++ #endif + #define VAR_DISABLE_DRIVERS vars[V_DISABLE_DRIVERS].current_val.l + #define VAR_DISABLE_AUTHS vars[V_DISABLE_AUTHS].current_val.l + #define VAR_REMOTE_ABOOK_METADATA vars[V_REMOTE_ABOOK_METADATA].current_val.p +diff -rc alpine-2.26/pith/conftype.h alpine-2.26.maildir/pith/conftype.h +*** alpine-2.26/pith/conftype.h 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.maildir/pith/conftype.h 2022-06-02 18:14:52.275147774 -0600 +*************** +*** 118,123 **** +--- 118,126 ---- + , V_NEWSRC_PATH + , V_NEWS_ACTIVE_PATH + , V_NEWS_SPOOL_DIR ++ #ifndef _WINDOWS ++ , V_MAILDIR_LOCATION ++ #endif + , V_UPLOAD_CMD + , V_UPLOAD_CMD_PREFIX + , V_DOWNLOAD_CMD +*************** +*** 410,415 **** +--- 413,421 ---- + F_PASS_C1_CONTROL_CHARS, + F_SINGLE_FOLDER_LIST, + F_VERTICAL_FOLDER_LIST, ++ #ifndef _WINDOWS ++ F_COURIER_FOLDER_LIST, ++ #endif + F_TAB_CHK_RECENT, + F_AUTO_REPLY_TO, + F_VERBOSE_POST, +diff -rc alpine-2.26/pith/headers.h alpine-2.26.maildir/pith/headers.h +*** alpine-2.26/pith/headers.h 2022-06-02 18:14:00.495274738 -0600 +--- alpine-2.26.maildir/pith/headers.h 2022-06-02 18:14:52.275147774 -0600 +*************** +*** 32,37 **** +--- 32,38 ---- + #include "../c-client/utf8.h" /* for CHARSET and such*/ + #include "../c-client/imap4r1.h" + #include "../c-client/http.h" /* for http support */ ++ #include "../c-client/maildir.h" + + /* include osdep protos and def'ns */ + #include "osdep/bldpath.h" +diff -rc alpine-2.26/pith/init.c alpine-2.26.maildir/pith/init.c +*** alpine-2.26/pith/init.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.maildir/pith/init.c 2022-06-02 18:14:52.283147754 -0600 +*************** +*** 404,409 **** +--- 404,412 ---- + && stricmp(filename, folder_base)){ + #else + if(strncmp(filename, folder_base, folder_base_len) == 0 ++ #ifndef _WINDOWS ++ && filename[folder_base_len] != list_cntxt->dir->delim ++ #endif + && strcmp(filename, folder_base)){ + #endif + #endif +diff -rc alpine-2.26/pith/pattern.c alpine-2.26.maildir/pith/pattern.c +*** alpine-2.26/pith/pattern.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.maildir/pith/pattern.c 2022-06-02 18:14:52.291147734 -0600 +*************** +*** 46,52 **** + #include "../pith/icache.h" + #include "../pith/ablookup.h" + #include "../pith/keyword.h" +! + + /* + * Internal prototypes +--- 46,54 ---- + #include "../pith/icache.h" + #include "../pith/ablookup.h" + #include "../pith/keyword.h" +! #ifndef _WINDOWS +! int maildir_file_path(char *name, char *tmp, size_t sizeoftmp); +! #endif /* _WINDOWS */ + + /* + * Internal prototypes +*************** +*** 5485,5490 **** +--- 5487,5501 ---- + break; + + case '#': ++ #ifndef _WINDOWS ++ if(!struncmp(patfolder, "#md/", 4) ++ || !struncmp(patfolder, "#mc/", 4)){ ++ maildir_file_path(patfolder, tmp1, sizeof(tmp1)); ++ if(!strcmp(tmp1, stream->mailbox)) ++ match++; ++ break; ++ } ++ #endif + if(!strcmp(patfolder, stream->mailbox)) + match++; + +*************** +*** 7905,7911 **** + int we_cancel = 0, width; + CONTEXT_S *save_context = NULL; + char buf[MAX_SCREEN_COLS+1], sbuf[MAX_SCREEN_COLS+1]; +! char *save_ref = NULL; + #define FILTMSG_MAX 30 + + if(!stream) +--- 7916,7922 ---- + int we_cancel = 0, width; + CONTEXT_S *save_context = NULL; + char buf[MAX_SCREEN_COLS+1], sbuf[MAX_SCREEN_COLS+1]; +! char *save_ref = NULL, *save_dstfldr = NULL, *save_dstfldr2 = NULL; + #define FILTMSG_MAX 30 + + if(!stream) +*************** +*** 7939,7944 **** +--- 7950,7965 ---- + if(F_OFF(F_QUELL_FILTER_MSGS, ps_global)) + we_cancel = busy_cue(buf, NULL, 0); + ++ #ifndef _WINDOWS ++ if(!struncmp(dstfldr, "#md/", 4) || !struncmp(dstfldr, "#mc/", 4)){ ++ char tmp1[MAILTMPLEN]; ++ maildir_file_path(dstfldr, tmp1, sizeof(tmp1)); ++ save_dstfldr2 = dstfldr; ++ save_dstfldr = cpystr(tmp1); ++ dstfldr = save_dstfldr; ++ } ++ #endif ++ + if(!is_absolute_path(dstfldr) + && !(save_context = default_save_context(ps_global->context_list))) + save_context = ps_global->context_list; +*************** +*** 8002,8007 **** +--- 8023,8033 ---- + if(we_cancel) + cancel_busy_cue(buf[0] ? 0 : -1); + ++ if(save_dstfldr){ ++ fs_give((void **)&save_dstfldr); ++ dstfldr = save_dstfldr2; ++ } ++ + return(buf[0] != '\0'); + } + +diff -rc alpine-2.26/pith/pine.hlp alpine-2.26.maildir/pith/pine.hlp +*** alpine-2.26/pith/pine.hlp 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.maildir/pith/pine.hlp 2022-06-02 18:14:52.299147715 -0600 +*************** +*** 23793,23798 **** +--- 23793,23894 ---- + <End of help on this topic> + + ++ ====== h_config_maildir_location ====== ++ ++ ++ OPTION: <!--#echo var="VAR_maildir-location"--> ++ ++ ++

    OPTION:

    ++ ++

    ++ This option should be used only if you have a Maildir folder which you ++ want to use as your INBOX. If this is not your case (or don't know what ++ this is), you can safely ignore this option. ++ ++

    ++ This option overrides the default directory Pine uses to find the location of ++ your INBOX, in case this is in Maildir format. The default value of this ++ option is "Maildir", but in some systems, this directory could have been ++ renamed (e.g. to ".maildir"). If this is your case use this option to change ++ the default. ++ ++

    ++ The value of this option is prefixed with the "~/" string to determine the ++ full path to your INBOX. ++ ++

    ++ You should probably read a few tips that ++ teach you how to configure your maildir for optimal performance. This ++ version also has support for the ++ Courier style file system when a maildir collection is accessed locally. ++ ++

    ++

    ++ <End of help on this topic> ++ ++ ++ ====== h_config_maildir ===== ++ ++ ++ Maildir Support ++ ++ ++

    Maildir Support

    ++ ++ This version of Alpine has been enhanced with Maildir support. This text is ++ intended to be a reference on its support. ++

    ++ ++ A Maildir folder is a directory that contains three directories called ++ cur, tmp and new. A program that delivers mail (e.g. postfix) will put new ++ mail in the new directory. A program that reads mail will look for for old ++ messages in the cur directory, while it will look for new mail in the new ++ directory. ++

    ++ ++ In order to use maildir support it is better to set your inbox-path to the ++ value "#md/inbox" (without quotes). This assumes that your mail ++ delivery agent is delivering new mail to ~/Maildir/new. If the directory ++ where new mail is being delivered is not called "Maildir", you can set the ++ name of the subdirectory of home where it is being delivered in the configuration ++ variable. Most of the time you will not have to worry about the ++ variable, because it will probably be set by your ++ administrator in the pine.conf configuration file. ++

    ++ ++ One of the advantages of the Maildir support of this version of Alpine is ++ that you do not have to stop using folders in another styles (mbox, mbx, ++ etc.). This is desirable since the usage of a specific mail storage system ++ is a personal decision. Folders in the maildir format that are part of the ++ Mail collection will be recognized without any extra configuration of your ++ part. If your mail/ collection is located under the mail/ directory, then ++ creating a new maildir folder in this collection is done by pressing "A" ++ and entering the string "#driver.md/mail/newfolder". Observe that adding a ++ new folder as "newfolder" may not create such folder in maildir format. ++ ++

    ++ If you would like to have all folders created in the maildir format by ++ default, you do so by adding a Maildir Collection. In order to convert ++ your current mail/ collection into a maildir collection, edit the ++ collection and change the path variable from "mail/" to ++ "#md/mail". In a maildir collection folders of any other format ++ are ignored. ++ ++

    Finally, This version also has ++ support for the Courier style file system ++ when a maildir collection is accessed locally. ++ ++

    ++

    ++ <End of help on this topic> ++ ++ + ====== h_config_literal_sig ===== + + +*************** +*** 31999,32004 **** +--- 32095,32143 ---- +

    + <End of help on this topic> + ++ ++ ====== h_config_courier_list ===== ++ ++ ++ FEATURE: <!--#echo var="FEAT_courier-folder-list"--> ++ ++ ++

    FEATURE:

    ++ ++ In a maildir collection, a folder could be used as a directory to store ++ folders. In the Courier server if you create a folder, then a directory ++ with the same name is created. If you use this patch to access a ++ collection created by the Courier server, then the display of such ++ collection will look confusing. The best way to access a maildir ++ collection created by the Courier server is by using the "#mc/" ++ prefix instead of the "#md/" prefix. If you use this alternate ++ prefix, then this feature applies to you, otherwise you can safely ignore ++ the text that follows. ++

    ++ Depending on if you have enabled the option ++ ++ a folder may be listed as "folder[.]", or as two entries in the ++ list by "folder" and "folder.". ++

    ++ If this option is disabled, Pine will list local folders that are in Courier ++ style format, as "folder", and those that are also directories as ++ "folder[.]". This makes the default display cleaner. ++

    ++ If this feature is enabled then creating folders in a maildir collection ++ will create a directory with the same name. If this feature is disabled, then ++ a folder is considered a directory only if it contains subfolders, so you can ++ not create a directory with the same name as an exisiting folder unless ++ you create a subfolder of that folder first (e.g. if you have a folder ++ called "foo" simply add "foo.bar" directly. This will ++ create the directory "foo" and the subfolder "bar" of it). ++

    ++ Observe that this feature works only for maildir collections that are accessed ++ locally. If a collection is accessed remotely then this feature has no value, ++ as the report is created in a server, and Pine only reports what received ++ from the server in this case. ++

    ++ <End of help on this topic> ++ + + ====== h_config_verbose_post ===== + +diff -rc alpine-2.26/pith/send.c alpine-2.26.maildir/pith/send.c +*** alpine-2.26/pith/send.c 2022-06-02 18:14:00.491274749 -0600 +--- alpine-2.26.maildir/pith/send.c 2022-06-02 18:14:52.303147704 -0600 +*************** +*** 43,48 **** +--- 43,51 ---- + + #include "../c-client/smtp.h" + #include "../c-client/nntp.h" ++ #ifndef _WINDOWS ++ int maildir_file_path(char *name, char *tmp, size_t sizeoftmp); ++ #endif /* _WINDOWS */ + + + /* this is used in pine_send and pine_simple_send */ +*************** +*** 246,251 **** +--- 249,261 ---- + + if(exists & FEX_ISFILE){ + context_apply(tmp, p_cntxt, mbox, sizeof(tmp)); ++ #ifndef _WINDOWS ++ if (!struncmp(tmp, "#md/",4) || !struncmp(tmp, "#mc/", 4)){ ++ char tmp2[MAILTMPLEN]; ++ maildir_file_path(tmp, tmp2, sizeof(tmp2)); ++ strcpy(tmp, tmp2); ++ } ++ #endif + if(!(IS_REMOTE(tmp) || is_absolute_path(tmp))){ + /* + * The mbox is relative to the home directory. +diff -rc alpine-2.26/README.maildir alpine-2.26.maildir/README.maildir +*** alpine-2.26/README.maildir 2022-06-02 18:14:52.327147646 -0600 +--- alpine-2.26.maildir/README.maildir 2022-06-02 18:14:52.303147704 -0600 +*************** +*** 0 **** +--- 1,149 ---- ++ --------------------------------------- ++ ++ Maildir Driver for Alpine 2.0 ++ By Eduardo Chappa ++ ++ ++ --------------------------------------- ++ 1. General Information About This Patch ++ --------------------------------------- ++ ++ This patch adds support for the maildir format to Alpine. We take the ++ approach that this patch is one more driver among the number of formats ++ supported by Alpine (more generally c-client). This approach differs from ++ older versions of similar patches, in that once a maildir patch was ++ applied, it was assumed that all your folders would be created in the ++ maildir format. ++ ++ This patch does not assume that maildir is a preferred format, instead ++ puts maildir in equal footing with other formats (mbox, mbx, mix, etc), ++ and so a maildir folder in the mail/ collection is treated in the same way ++ as any other folder in any other format. In other words, just by reading ++ the name of a folder, or opening it, or doing any operation with it, you ++ can not know in which format the folder is. ++ ++ This implies that if you want to add a folder in the maildir format to the ++ mail/ collection, then you must add by pressing "A" in the folder list ++ collection and enter "#driver.md/mail/name_maildir_folder". ++ ++ If you only want to use maildir, however, you can do so too. In this case, ++ you must create a maildir collection. In that collection, only maildir ++ folders will be listed. If there is any folder in any other format, that ++ folder will be ignored. In another words, any folder listed there is in ++ maildir format and can be accessed through that collection, conversely, ++ any folder not listed there is not in maildir format and there is no way ++ to access it using this collection. ++ ++ In order to create a maildir collection, you could press M S L, and "A" to ++ add a collection. Fill in the required fields as follows: ++ ++ Nickname : Anything ++ Server : ++ Path : #md/relative/path/to/maildir/collection/ ++ View : ++ ++ For example, if "path" is set to "#md/mail/", then Alpine will look for your ++ maildir folders that are in ~/mail/. ++ ++ The code in this patch is mostly based in code for the unix driver plus ++ some combinations of the mh, mbx and nntp drivers for the c-client ++ library. Those drivers were designed by Mark Crispin, and bugs in this ++ code are not his bugs, but my own. ++ ++ I got all the specification for this patch from ++ http://cr.yp.to/proto/maildir.html. If you know of a place with a better ++ specification for maildir format please let me know. The method this patch ++ uses to create a unique filename for a message is one of the "old ++ fashioned" methods. I realize that this is old fashioned, but it is ++ portable, and portability is the main reason why I decided to use an old ++ fashioned method (most methods are not portable. See the word ++ "Unfortunately" in that document). ++ ++ -------------- ++ 2. Other Goals ++ -------------- ++ ++ It is intended that this code will work well with any application ++ written using the c-client library. Of paramount importance is to make the ++ associated imap server work well when the server accesses a folder in ++ Maildir format. The program mailutil should also work flawlessly with this ++ implemetation of the driver. ++ ++ It is intended that this driver be fast and stable. We intend not to ++ patch Alpine to make this driver do its work, unless such patching is for ++ fixing bugs in Alpine or to pass parameters to the driver. ++ ++ ------------------------------------------------------------------------ ++ 3. What are the known bugs of this implementation of the Maildir driver? ++ ------------------------------------------------------------------------ ++ ++ I don't know any at this time. There have been bugs before, though, but ++ I try to fix bugs as soon as they are reported. ++ ++ ---------- ++ 4. On UIDs ++ ---------- ++ ++ This patch keeps uids in the name of the file that contains the message, ++ by adding a ",u=" string to the file name to save the uid of a message. A ++ file is kept between sessions to save information on the last uid assigned ++ and its time of validity. Only one session with writing access can write ++ uids, all others must wait for the other session to assign them. The ++ session assigning uids creates a ".uidtemp" file which other sessions must ++ not disturb. ++ ++ Uid support appeared in Alpine 1.00 (snapshot 925), and is experimental, ++ please report any problems. ++ ++ ---------------------------------------------- ++ 5. Configuring Alpine and Setting up a Maildir ++ ---------------------------------------------- ++ ++ Once this approach was chosen, it implied the following: ++ ++ * This patch assumes that your INBOX is located at "$HOME/Maildir". ++ This is a directory which should have three subdirectories "cur", ++ "tmp" and "new". Mail is delivered to 'new' and read from 'cur'. I ++ have added a configuration option "maildir-location" which can be ++ used to tell Alpine where your Maildir inbox is, in case your system ++ does not use the above directory (e.g. your system may use ++ "~/.maildir"). In this case define that variable to be the name of ++ the directory where your e-mail is being delivered (e.g. ++ ".maildir"). ++ ++ * If you want to use the above configuration as your inbox, you must ++ define your inbox-path as "#md/inbox" (no quotes). You can define ++ the inbox-path like above even if you have changed the ++ maildir-location variable. That's the whole point of that variable. ++ ++ ------------------------------------------- ++ 6. What about Courier/Dovecot file systems? ++ ------------------------------------------- ++ ++ In a courier file system all folders are subfolders of a root folder ++ called INBOX. Normally INBOX is located at ~/Maildir and subfolders are ++ "dot" directories in ~/Maildir. For example ~/Maildir/.Trash is a ++ subfolder of INBOX and is accessed with the nickname "INBOX.Trash". ++ ++ You can not access folders in this way unless you preceed them with the ++ string "#mc/". The purpose of the string "#mc/" is to warn Alpine that a ++ collection in the Courier format is going to be accessed. Therefore, you ++ can SELECT a folder like "#mc/INBOX.Trash", but not "INBOX.Trash" ++ ++ You can access a collection through a server, but if you want to access a ++ collection of folders created using the Courier server, you MUST edit your ++ ".pinerc" file and enter the definition of the collection as follows: ++ ++ folder-collections="Anything you want" #mc/INBOX.[] ++ ++ You can replace the string "#mc/INBOX." by something different, for example ++ "#mc/Courier/." will make Alpine search for your collection in ~/Courier. ++ ++ You can not add this setting directly into Alpine because Alpine fails to ++ accept this value from its input, but it takes it correctly when it is ++ added through the ".pinerc" file. ++ ++ You can access your inbox as "#mc/INBOX" or "#md/INBOX". Both definitions ++ point to the same place. ++ ++ Last Updated May 28, 2011 diff --git a/chappa-rules.patch b/chappa-rules.patch index ea46b3d..6725217 100644 --- a/chappa-rules.patch +++ b/chappa-rules.patch @@ -8,7 +8,7 @@ alpine/mailcmd.c | 18 alpine/mailindx.c | 6 alpine/mailpart.c | 12 - alpine/mailview.c | 3 + alpine/mailview.c | 2 alpine/osdep/termin.gen.c | 41 + alpine/reply.c | 102 ++ alpine/roleconf.c | 5 @@ -23,12 +23,12 @@ pith/indxtype.h | 34 pith/mailcmd.c | 435 +++++++++--- pith/mailcmd.h | 8 - pith/mailindx.c | 340 +++++++-- + pith/mailindx.c | 336 +++++++-- pith/mailindx.h | 3 pith/makefile.wnt | 5 pith/pine.hlp | 1150 +++++++++++++++++++++++++++++++++ pith/reply.c | 279 +++++++- - pith/rules.c | 1565 ++++++++++++++++++++++++++++++++++++++++++++++ + pith/rules.c | 1566 ++++++++++++++++++++++++++++++++++++++++++++++ pith/rules.h | 154 ++++ pith/rulestype.h | 94 ++ pith/save.c | 2 @@ -39,13 +39,13 @@ pith/state.h | 11 pith/string.c | 58 + pith/string.h | 2 - 40 files changed, 4488 insertions(+), 298 deletions(-) + 40 files changed, 4486 insertions(+), 296 deletions(-) -Index: alpine-2.25/alpine/adrbkcmd.c +Index: alpine-2.26/alpine/adrbkcmd.c =================================================================== ---- alpine-2.25.orig/alpine/adrbkcmd.c -+++ alpine-2.25/alpine/adrbkcmd.c -@@ -4129,6 +4129,8 @@ ab_compose_internal(BuildTo bldto, int a +--- alpine-2.26.orig/alpine/adrbkcmd.c ++++ alpine-2.26/alpine/adrbkcmd.c +@@ -4125,6 +4125,8 @@ ab_compose_internal(BuildTo bldto, int a * won't do anything, but will cause compose_mail to think there's * already a role so that it won't try to confirm the default. */ @@ -54,7 +54,7 @@ Index: alpine-2.25/alpine/adrbkcmd.c if(role) role = copy_action(role); else{ -@@ -4136,6 +4138,7 @@ ab_compose_internal(BuildTo bldto, int a +@@ -4132,6 +4134,7 @@ ab_compose_internal(BuildTo bldto, int a memset((void *)role, 0, sizeof(*role)); role->nick = cpystr("Default Role"); } @@ -62,11 +62,11 @@ Index: alpine-2.25/alpine/adrbkcmd.c } compose_mail(addr, fcc, role, NULL, NULL); -Index: alpine-2.25/alpine/alpine.c +Index: alpine-2.26/alpine/alpine.c =================================================================== ---- alpine-2.25.orig/alpine/alpine.c -+++ alpine-2.25/alpine/alpine.c -@@ -506,6 +506,7 @@ main(int argc, char **argv) +--- alpine-2.26.orig/alpine/alpine.c ++++ alpine-2.26/alpine/alpine.c +@@ -502,6 +502,7 @@ main(int argc, char **argv) /* Set up optional for user-defined display filtering */ pine_state->tools.display_filter = dfilter; pine_state->tools.display_filter_trigger = dfilter_trigger; @@ -74,7 +74,7 @@ Index: alpine-2.25/alpine/alpine.c #ifdef _WINDOWS if(ps_global->install_flag){ -@@ -3281,6 +3282,9 @@ goodnight_gracey(struct pine *pine_state +@@ -3290,6 +3291,9 @@ goodnight_gracey(struct pine *pine_state extern KBESC_T *kbesc; dprint((2, "goodnight_gracey:\n")); @@ -84,11 +84,11 @@ Index: alpine-2.25/alpine/alpine.c /* We want to do this here before we close up the streams */ trim_remote_adrbks(); -Index: alpine-2.25/alpine/confscroll.c +Index: alpine-2.26/alpine/confscroll.c =================================================================== ---- alpine-2.25.orig/alpine/confscroll.c -+++ alpine-2.25/alpine/confscroll.c -@@ -52,6 +52,7 @@ static char rcsid[] = "$Id: confscroll.c +--- alpine-2.26.orig/alpine/confscroll.c ++++ alpine-2.26/alpine/confscroll.c +@@ -48,6 +48,7 @@ #include "../pith/tempfile.h" #include "../pith/pattern.h" #include "../pith/charconv/utf8.h" @@ -96,7 +96,7 @@ Index: alpine-2.25/alpine/confscroll.c #define CONFIG_SCREEN_HELP_TITLE _("HELP FOR SETUP CONFIGURATION") -@@ -2463,6 +2464,9 @@ delete: +@@ -2461,6 +2462,9 @@ delete: * Now go and set the current_val based on user_val changes * above. Turn off command line settings... */ @@ -106,7 +106,7 @@ Index: alpine-2.25/alpine/confscroll.c set_current_val((*cl)->var, TRUE, FALSE); fix_side_effects(ps, (*cl)->var, 0); -@@ -5260,6 +5264,35 @@ fix_side_effects(struct pine *ps, struct +@@ -5258,6 +5262,35 @@ fix_side_effects(struct pine *ps, struct var == &ps->vars[V_ABOOK_FORMATS]){ addrbook_reset(); } @@ -142,11 +142,11 @@ Index: alpine-2.25/alpine/confscroll.c else if(var == &ps->vars[V_INDEX_FORMAT]){ reset_index_format(); clear_index_cache(ps->mail_stream, 0); -Index: alpine-2.25/alpine/dispfilt.c +Index: alpine-2.26/alpine/dispfilt.c =================================================================== ---- alpine-2.25.orig/alpine/dispfilt.c -+++ alpine-2.25/alpine/dispfilt.c -@@ -461,3 +461,63 @@ df_valid_test(struct mail_bodystruct *bo +--- alpine-2.26.orig/alpine/dispfilt.c ++++ alpine-2.26/alpine/dispfilt.c +@@ -457,3 +457,63 @@ df_valid_test(struct mail_bodystruct *bo return(passed); } @@ -210,10 +210,10 @@ Index: alpine-2.25/alpine/dispfilt.c + + return(status); +} -Index: alpine-2.25/alpine/dispfilt.h +Index: alpine-2.26/alpine/dispfilt.h =================================================================== ---- alpine-2.25.orig/alpine/dispfilt.h -+++ alpine-2.25/alpine/dispfilt.h +--- alpine-2.26.orig/alpine/dispfilt.h ++++ alpine-2.26/alpine/dispfilt.h @@ -25,7 +25,7 @@ char *dfilter_trigger(BODY *, char *, si char *expand_filter_tokens(char *, ENVELOPE *, char **, char **, char **, int *, int *, int *); char *filter_session_key(void); @@ -223,11 +223,11 @@ Index: alpine-2.25/alpine/dispfilt.h #endif /* PINE_DISPFILT_INCLUDED */ -Index: alpine-2.25/alpine/folder.c +Index: alpine-2.26/alpine/folder.c =================================================================== ---- alpine-2.25.orig/alpine/folder.c -+++ alpine-2.25/alpine/folder.c -@@ -248,7 +248,7 @@ folder_screen(struct pine *ps) +--- alpine-2.26.orig/alpine/folder.c ++++ alpine-2.26/alpine/folder.c +@@ -244,7 +244,7 @@ folder_screen(struct pine *ps) dprint((1, "=== folder_screen called ====\n")); mailcap_free(); /* free resources we won't be using for a while */ ps->next_screen = SCREEN_FUN_NULL; @@ -236,7 +236,7 @@ Index: alpine-2.25/alpine/folder.c /* Initialize folder state and dispatches */ memset(&fs, 0, sizeof(FSTATE_S)); fs.context = cntxt; -@@ -345,6 +345,7 @@ folder_screen(struct pine *ps) +@@ -341,6 +341,7 @@ folder_screen(struct pine *ps) pine_mail_close(*fs.cache_streamp); ps->prev_screen = folder_screen; @@ -244,11 +244,11 @@ Index: alpine-2.25/alpine/folder.c } -Index: alpine-2.25/alpine/mailcmd.c +Index: alpine-2.26/alpine/mailcmd.c =================================================================== ---- alpine-2.25.orig/alpine/mailcmd.c -+++ alpine-2.25/alpine/mailcmd.c -@@ -73,6 +73,7 @@ static char rcsid[] = "$Id: mailcmd.c 12 +--- alpine-2.26.orig/alpine/mailcmd.c ++++ alpine-2.26/alpine/mailcmd.c +@@ -69,6 +69,7 @@ #include "../pith/tempfile.h" #include "../pith/search.h" #include "../pith/margin.h" @@ -256,7 +256,7 @@ Index: alpine-2.25/alpine/mailcmd.c #ifdef _WINDOWS #include "../pico/osdep/mswin.h" #endif -@@ -2722,6 +2723,9 @@ role_compose(struct pine *state) +@@ -2721,6 +2722,9 @@ role_compose(struct pine *state) role->nick = cpystr("Default Role"); } @@ -266,7 +266,7 @@ Index: alpine-2.25/alpine/mailcmd.c state->redrawer = NULL; switch(action){ case 'c': -@@ -2772,12 +2776,12 @@ save_prompt(struct pine *state, CONTEXT_ +@@ -2771,12 +2775,12 @@ save_prompt(struct pine *state, CONTEXT_ char *nmsgs, ENVELOPE *env, long int rawmsgno, char *section, SaveDel *dela, SavePreserveOrder *prea) { @@ -281,7 +281,7 @@ Index: alpine-2.25/alpine/mailcmd.c HelpType help; SaveDel del = DontAsk; SavePreserveOrder pre = DontAskPreserve; -@@ -2785,6 +2789,7 @@ save_prompt(struct pine *state, CONTEXT_ +@@ -2784,6 +2788,7 @@ save_prompt(struct pine *state, CONTEXT_ static HISTORY_S *history = NULL; CONTEXT_S *tc; ESCKEY_S ekey[10]; @@ -289,7 +289,7 @@ Index: alpine-2.25/alpine/mailcmd.c if(!cntxt) alpine_panic("no context ptr in save_prompt"); -@@ -2794,6 +2799,15 @@ save_prompt(struct pine *state, CONTEXT_ +@@ -2793,6 +2798,15 @@ save_prompt(struct pine *state, CONTEXT_ if(!(folder = save_get_default(state, env, rawmsgno, section, cntxt))) return(0); /* message expunged! */ @@ -305,11 +305,11 @@ Index: alpine-2.25/alpine/mailcmd.c /* how many context's can be saved to... */ for(tc = state->context_list; tc; tc = tc->next) if(!NEWS_TEST(tc)) -Index: alpine-2.25/alpine/mailindx.c +Index: alpine-2.26/alpine/mailindx.c =================================================================== ---- alpine-2.25.orig/alpine/mailindx.c -+++ alpine-2.25/alpine/mailindx.c -@@ -229,6 +229,8 @@ mail_index_screen(struct pine *state) +--- alpine-2.26.orig/alpine/mailindx.c ++++ alpine-2.26/alpine/mailindx.c +@@ -225,6 +225,8 @@ mail_index_screen(struct pine *state) state->prev_screen = mail_index_screen; state->next_screen = SCREEN_FUN_NULL; @@ -318,7 +318,7 @@ Index: alpine-2.25/alpine/mailindx.c if(THRD_AUTO_VIEW() && sp_viewing_a_thread(state->mail_stream) && state->view_skipped_index -@@ -240,10 +242,14 @@ mail_index_screen(struct pine *state) +@@ -236,10 +238,14 @@ mail_index_screen(struct pine *state) adjust_cur_to_visible(state->mail_stream, state->msgmap); @@ -333,11 +333,11 @@ Index: alpine-2.25/alpine/mailindx.c } -Index: alpine-2.25/alpine/mailpart.c +Index: alpine-2.26/alpine/mailpart.c =================================================================== ---- alpine-2.25.orig/alpine/mailpart.c -+++ alpine-2.25/alpine/mailpart.c -@@ -182,7 +182,7 @@ attachment_screen(struct pine *ps) +--- alpine-2.26.orig/alpine/mailpart.c ++++ alpine-2.26/alpine/mailpart.c +@@ -178,7 +178,7 @@ attachment_screen(struct pine *ps) maxnumwid = 0, maxsizewid = 0, old_cols = -1, km_popped = 0, expbits, last_type = TYPEOTHER; long msgno; @@ -346,7 +346,7 @@ Index: alpine-2.25/alpine/mailpart.c OtherMenu what; ATTACH_S *a; ATDISP_S *current = NULL, *ctmp = NULL; -@@ -191,6 +191,10 @@ attachment_screen(struct pine *ps) +@@ -187,6 +187,10 @@ attachment_screen(struct pine *ps) ps->prev_screen = attachment_screen; ps->next_screen = SCREEN_FUN_NULL; @@ -357,7 +357,7 @@ Index: alpine-2.25/alpine/mailpart.c ps->some_quoting_was_suppressed = 0; if(ps->ttyo->screen_rows - HEADER_ROWS(ps) - FOOTER_ROWS(ps) < 1){ -@@ -911,6 +915,12 @@ attachment_screen(struct pine *ps) +@@ -907,6 +911,12 @@ attachment_screen(struct pine *ps) if(screen.titlecolor) free_color_pair(&screen.titlecolor); @@ -370,11 +370,11 @@ Index: alpine-2.25/alpine/mailpart.c } -Index: alpine-2.25/alpine/mailview.c +Index: alpine-2.26/alpine/mailview.c =================================================================== ---- alpine-2.25.orig/alpine/mailview.c -+++ alpine-2.25/alpine/mailview.c -@@ -252,6 +252,8 @@ mail_view_screen(struct pine *ps) +--- alpine-2.26.orig/alpine/mailview.c ++++ alpine-2.26/alpine/mailview.c +@@ -250,6 +250,8 @@ mail_view_screen(struct pine *ps) ps->prev_screen = mail_view_screen; ps->force_prefer_plain = ps->force_no_prefer_plain = 0; @@ -383,19 +383,11 @@ Index: alpine-2.25/alpine/mailview.c if(ps->ttyo->screen_rows - HEADER_ROWS(ps) - FOOTER_ROWS(ps) < 1){ q_status_message(SM_ORDER | SM_DING, 0, 3, _("Screen too small to view message")); -@@ -498,6 +500,7 @@ mail_view_screen(struct pine *ps) - #endif - } - while(ps->next_screen == SCREEN_FUN_NULL); -+ strcpy(ps->screen_name, "unknown"); - - if (prefix && *prefix) - fs_give((void **)&prefix); -Index: alpine-2.25/alpine/osdep/termin.gen.c +Index: alpine-2.26/alpine/osdep/termin.gen.c =================================================================== ---- alpine-2.25.orig/alpine/osdep/termin.gen.c -+++ alpine-2.25/alpine/osdep/termin.gen.c -@@ -33,6 +33,8 @@ static char rcsid[] = "$Id: termin.gen.c +--- alpine-2.26.orig/alpine/osdep/termin.gen.c ++++ alpine-2.26/alpine/osdep/termin.gen.c +@@ -29,6 +29,8 @@ #include "../../pith/newmail.h" #include "../../pith/conf.h" #include "../../pith/busy.h" @@ -404,7 +396,7 @@ Index: alpine-2.25/alpine/osdep/termin.gen.c #include "../../pico/estruct.h" #include "../../pico/pico.h" -@@ -72,7 +74,8 @@ int pcpine_oe_cursor(int, long); +@@ -68,7 +70,8 @@ int pcpine_oe_cursor(int, long); * Generic tty input routines */ @@ -414,7 +406,7 @@ Index: alpine-2.25/alpine/osdep/termin.gen.c /*---------------------------------------------------------------------- Read a character from keyboard with timeout Input: none -@@ -114,6 +117,41 @@ read_command(char **utf8str) +@@ -110,6 +113,41 @@ read_command(char **utf8str) *utf8str = NULL; ucs = read_char(tm); @@ -456,7 +448,7 @@ Index: alpine-2.25/alpine/osdep/termin.gen.c if(ucs != NO_OP_COMMAND && ucs != NO_OP_IDLE && ucs != KEY_RESIZE) zero_new_mail_count(); -@@ -1159,6 +1197,7 @@ process_config_input(UCS *ch) +@@ -1155,6 +1193,7 @@ process_config_input(UCS *ch) if(ps_global->initial_cmds && !*ps_global->initial_cmds && ps_global->free_initial_cmds){ fs_give((void **) &ps_global->free_initial_cmds); ps_global->initial_cmds = NULL; @@ -464,11 +456,11 @@ Index: alpine-2.25/alpine/osdep/termin.gen.c } return(ret); -Index: alpine-2.25/alpine/reply.c +Index: alpine-2.26/alpine/reply.c =================================================================== ---- alpine-2.25.orig/alpine/reply.c -+++ alpine-2.25/alpine/reply.c -@@ -62,7 +62,8 @@ The evolution continues... +--- alpine-2.26.orig/alpine/reply.c ++++ alpine-2.26/alpine/reply.c +@@ -58,7 +58,8 @@ The evolution continues... #include "../pith/tempfile.h" #include "../pith/busy.h" #include "../pith/ablookup.h" @@ -478,7 +470,7 @@ Index: alpine-2.25/alpine/reply.c /* * Internal Prototypes -@@ -109,11 +110,12 @@ reply(struct pine *pine_state, ACTION_S +@@ -105,11 +106,12 @@ reply(struct pine *pine_state, ACTION_S long msgno, j, totalm, rflags, *seq = NULL; int i, include_text = 0, times = -1, warned = 0, rv = 0, flags = RSF_QUERY_REPLY_ALL, reply_raw_body = 0; @@ -492,7 +484,7 @@ Index: alpine-2.25/alpine/reply.c #if defined(DOS) && !defined(_WINDOWS) char *reserve; #endif -@@ -139,6 +141,69 @@ reply(struct pine *pine_state, ACTION_S +@@ -135,6 +137,69 @@ reply(struct pine *pine_state, ACTION_S && F_ON(F_ENABLE_FULL_HDR_AND_TEXT, ps_global)) reply_raw_body = 1; @@ -562,7 +554,7 @@ Index: alpine-2.25/alpine/reply.c /* * We may have to loop through first to figure out what default * reply-indent-string to offer... -@@ -287,8 +352,18 @@ reply(struct pine *pine_state, ACTION_S +@@ -283,8 +348,18 @@ reply(struct pine *pine_state, ACTION_S outgoing->subject = cpystr("Re: several messages"); } } @@ -583,7 +575,7 @@ Index: alpine-2.25/alpine/reply.c } /* fill reply header */ -@@ -307,13 +382,7 @@ reply(struct pine *pine_state, ACTION_S +@@ -303,13 +378,7 @@ reply(struct pine *pine_state, ACTION_S if(sp_expunge_count(pine_state->mail_stream)) /* cur msg expunged */ goto done_early; @@ -598,7 +590,7 @@ Index: alpine-2.25/alpine/reply.c rflags = ROLE_REPLY; if(!ps_global->reply.role_chosen && nonempty_patterns(rflags, &dummy)){ /* setup default role */ -@@ -724,6 +793,9 @@ reply(struct pine *pine_state, ACTION_S +@@ -720,6 +789,9 @@ reply(struct pine *pine_state, ACTION_S if(prefix) fs_give((void **)&prefix); @@ -608,7 +600,7 @@ Index: alpine-2.25/alpine/reply.c if(fcc) fs_give((void **) &fcc); -@@ -1594,9 +1666,14 @@ forward(struct pine *ps, ACTION_S *role_ +@@ -1590,9 +1662,14 @@ forward(struct pine *ps, ACTION_S *role_ } } @@ -624,7 +616,7 @@ Index: alpine-2.25/alpine/reply.c outgoing->message_id = generate_message_id(role); -@@ -1830,6 +1907,7 @@ forward(struct pine *ps, ACTION_S *role_ +@@ -1826,6 +1903,7 @@ forward(struct pine *ps, ACTION_S *role_ #if defined(DOS) && !defined(_WINDOWS) free((void *)reserve); #endif @@ -632,11 +624,11 @@ Index: alpine-2.25/alpine/reply.c pine_send(outgoing, &body, "FORWARD MESSAGE", role, NULL, &reply, redraft_pos, NULL, NULL, 0); -Index: alpine-2.25/alpine/roleconf.c +Index: alpine-2.26/alpine/roleconf.c =================================================================== ---- alpine-2.25.orig/alpine/roleconf.c -+++ alpine-2.25/alpine/roleconf.c -@@ -7706,6 +7706,11 @@ role_text_tool_inick(struct pine *ps, in +--- alpine-2.26.orig/alpine/roleconf.c ++++ alpine-2.26/alpine/roleconf.c +@@ -7702,6 +7702,11 @@ role_text_tool_inick(struct pine *ps, in if(apval) *apval = (role && role->nick) ? cpystr(role->nick) : NULL; @@ -648,11 +640,11 @@ Index: alpine-2.25/alpine/roleconf.c if((*cl)->value) fs_give((void **)&((*cl)->value)); -Index: alpine-2.25/alpine/send.c +Index: alpine-2.26/alpine/send.c =================================================================== ---- alpine-2.25.orig/alpine/send.c -+++ alpine-2.25/alpine/send.c -@@ -63,7 +63,7 @@ static char rcsid[] = "$Id: send.c 1142 +--- alpine-2.26.orig/alpine/send.c ++++ alpine-2.26/alpine/send.c +@@ -59,7 +59,7 @@ #include "../pith/mimetype.h" #include "../pith/send.h" #include "../pith/smime.h" @@ -661,7 +653,7 @@ Index: alpine-2.25/alpine/send.c typedef struct body_particulars { unsigned short type, encoding, had_csp; -@@ -236,6 +236,11 @@ alt_compose_screen(struct pine *pine_sta +@@ -232,6 +232,11 @@ alt_compose_screen(struct pine *pine_sta role->nick = cpystr("Default Role"); } @@ -673,7 +665,7 @@ Index: alpine-2.25/alpine/send.c pine_state->redrawer = NULL; compose_mail(NULL, NULL, role, NULL, NULL); free_action(&role); -@@ -445,8 +450,12 @@ compose_mail(char *given_to, char *fcc_a +@@ -441,8 +446,12 @@ compose_mail(char *given_to, char *fcc_a ps_global->next_screen = prev_screen; ps_global->redrawer = redraw; @@ -687,7 +679,7 @@ Index: alpine-2.25/alpine/send.c } break; -@@ -639,9 +648,14 @@ compose_mail(char *given_to, char *fcc_a +@@ -638,9 +647,14 @@ compose_mail(char *given_to, char *fcc_a } } @@ -703,7 +695,7 @@ Index: alpine-2.25/alpine/send.c outgoing->message_id = generate_message_id(role); /* -@@ -2486,6 +2500,26 @@ pine_send(ENVELOPE *outgoing, struct mai +@@ -2485,6 +2499,26 @@ pine_send(ENVELOPE *outgoing, struct mai removing_trailing_white_space(pf->textbuf); (void)removing_double_quotes(pf->textbuf); build_address(pf->textbuf, &addr, NULL, NULL, NULL); @@ -730,10 +722,10 @@ Index: alpine-2.25/alpine/send.c rfc822_parse_adrlist(pf->addr, addr, ps_global->maildomain); fs_give((void **)&addr); -Index: alpine-2.25/pith/Makefile.am +Index: alpine-2.26/pith/Makefile.am =================================================================== ---- alpine-2.25.orig/pith/Makefile.am -+++ alpine-2.25/pith/Makefile.am +--- alpine-2.26.orig/pith/Makefile.am ++++ alpine-2.26/pith/Makefile.am @@ -26,7 +26,7 @@ libpith_a_SOURCES = ablookup.c abdlc.c a filter.c flag.c folder.c handle.c help.c helpindx.c hist.c icache.c ical.c imap.c init.c \ keyword.c ldap.c list.c mailcap.c mailcmd.c mailindx.c maillist.c mailview.c \ @@ -743,11 +735,11 @@ Index: alpine-2.25/pith/Makefile.am state.c status.c store.c stream.c string.c strlst.c takeaddr.c tempfile.c text.c \ thread.c adjtime.c url.c util.c helptext.c smkeys.c smime.c -Index: alpine-2.25/pith/Makefile.in +Index: alpine-2.26/pith/Makefile.in =================================================================== ---- alpine-2.25.orig/pith/Makefile.in -+++ alpine-2.25/pith/Makefile.in -@@ -142,7 +142,7 @@ am_libpith_a_OBJECTS = ablookup.$(OBJEXT +--- alpine-2.26.orig/pith/Makefile.in ++++ alpine-2.26/pith/Makefile.in +@@ -143,7 +143,7 @@ am_libpith_a_OBJECTS = ablookup.$(OBJEXT mimedesc.$(OBJEXT) mimetype.$(OBJEXT) msgno.$(OBJEXT) \ newmail.$(OBJEXT) news.$(OBJEXT) pattern.$(OBJEXT) \ pipe.$(OBJEXT) readfile.$(OBJEXT) remote.$(OBJEXT) \ @@ -756,7 +748,7 @@ Index: alpine-2.25/pith/Makefile.in search.$(OBJEXT) sequence.$(OBJEXT) send.$(OBJEXT) \ sort.$(OBJEXT) state.$(OBJEXT) status.$(OBJEXT) \ store.$(OBJEXT) stream.$(OBJEXT) string.$(OBJEXT) \ -@@ -441,7 +441,7 @@ libpith_a_SOURCES = ablookup.c abdlc.c a +@@ -450,7 +450,7 @@ libpith_a_SOURCES = ablookup.c abdlc.c a filter.c flag.c folder.c handle.c help.c helpindx.c hist.c icache.c ical.c imap.c init.c \ keyword.c ldap.c list.c mailcap.c mailcmd.c mailindx.c maillist.c mailview.c \ margin.c mimedesc.c mimetype.c msgno.c newmail.c news.c pattern.c pipe.c \ @@ -765,7 +757,7 @@ Index: alpine-2.25/pith/Makefile.in state.c status.c store.c stream.c string.c strlst.c takeaddr.c tempfile.c text.c \ thread.c adjtime.c url.c util.c helptext.c smkeys.c smime.c -@@ -575,6 +575,7 @@ distclean-compile: +@@ -584,6 +584,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/url.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ @@ -773,11 +765,11 @@ Index: alpine-2.25/pith/Makefile.in .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -Index: alpine-2.25/pith/adrbklib.c +Index: alpine-2.26/pith/adrbklib.c =================================================================== ---- alpine-2.25.orig/pith/adrbklib.c -+++ alpine-2.25/pith/adrbklib.c -@@ -5138,8 +5138,14 @@ init_addrbooks(OpenStatus want_status, i +--- alpine-2.26.orig/pith/adrbklib.c ++++ alpine-2.26/pith/adrbklib.c +@@ -5134,8 +5134,14 @@ init_addrbooks(OpenStatus want_status, i if(as.cur >= as.how_many_personals) pab->type |= GLOBAL; @@ -794,11 +786,11 @@ Index: alpine-2.25/pith/adrbklib.c /* global address books are forced readonly */ if(pab->type & GLOBAL && pab->access != NoAccess) pab->access = ReadOnly; -Index: alpine-2.25/pith/conf.c +Index: alpine-2.26/pith/conf.c =================================================================== ---- alpine-2.25.orig/pith/conf.c -+++ alpine-2.25/pith/conf.c -@@ -29,6 +29,7 @@ static char rcsid[] = "$Id: conf.c 1266 +--- alpine-2.26.orig/pith/conf.c ++++ alpine-2.26/pith/conf.c +@@ -25,6 +25,7 @@ #include "../pith/remote.h" #include "../pith/keyword.h" #include "../pith/mailview.h" @@ -806,7 +798,7 @@ Index: alpine-2.25/pith/conf.c #include "../pith/list.h" #include "../pith/status.h" #include "../pith/ldap.h" -@@ -225,6 +226,36 @@ CONF_TXT_T cf_text_unk_character_set[] = +@@ -221,6 +222,36 @@ CONF_TXT_T cf_text_unk_character_set[] = CONF_TXT_T cf_text_editor[] = "Specifies the program invoked by ^_ in the Composer,\n# or the \"enable-alternate-editor-implicitly\" feature."; @@ -843,7 +835,7 @@ Index: alpine-2.25/pith/conf.c CONF_TXT_T cf_text_speller[] = "Specifies the program invoked by ^T in the Composer."; #ifdef _WINDOWS -@@ -576,6 +607,34 @@ static struct variable variables[] = { +@@ -572,6 +603,34 @@ static struct variable variables[] = { NULL, cf_text_thread_exp_char}, {"threading-lastreply-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, "Threading Last Reply Character", cf_text_thread_lastreply_char}, @@ -878,7 +870,7 @@ Index: alpine-2.25/pith/conf.c #ifndef _WINDOWS {"display-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL, cf_text_disp_char_set}, -@@ -2777,6 +2836,7 @@ init_vars(struct pine *ps, void (*cmds_f +@@ -2779,6 +2838,7 @@ init_vars(struct pine *ps, void (*cmds_f if(cmds_f) (*cmds_f)(ps, VAR_INIT_CMD_LIST); @@ -886,7 +878,7 @@ Index: alpine-2.25/pith/conf.c #ifdef _WINDOWS mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global)); #endif /* _WINDOWS */ -@@ -3233,6 +3293,8 @@ feature_list(int index) +@@ -3235,6 +3295,8 @@ feature_list(int index) F_FORCE_LOW_SPEED, h_config_force_low_speed, PREF_OS_LWSD, 0}, {"auto-move-read-msgs", "Auto Move Read Messages", F_AUTO_READ_MSGS, h_config_auto_read_msgs, PREF_MISC, 0}, @@ -895,7 +887,7 @@ Index: alpine-2.25/pith/conf.c {"auto-unselect-after-apply", NULL, F_AUTO_UNSELECT, h_config_auto_unselect, PREF_MISC, 0}, {"auto-unzoom-after-apply", NULL, -@@ -7934,6 +7996,34 @@ config_help(int var, int feature) +@@ -7935,6 +7997,34 @@ config_help(int var, int feature) return(h_config_ab_sort_rule); case V_FLD_SORT_RULE : return(h_config_fld_sort_rule); @@ -930,10 +922,10 @@ Index: alpine-2.25/pith/conf.c case V_POST_CHAR_SET : return(h_config_post_char_set); case V_UNK_CHAR_SET : -Index: alpine-2.25/pith/conf.h +Index: alpine-2.26/pith/conf.h =================================================================== ---- alpine-2.25.orig/pith/conf.h -+++ alpine-2.25/pith/conf.h +--- alpine-2.26.orig/pith/conf.h ++++ alpine-2.26/pith/conf.h @@ -162,6 +162,46 @@ #define GLO_AB_SORT_RULE vars[V_AB_SORT_RULE].global_val.p #define VAR_FLD_SORT_RULE vars[V_FLD_SORT_RULE].current_val.p @@ -981,10 +973,10 @@ Index: alpine-2.25/pith/conf.h #ifndef _WINDOWS #define VAR_CHAR_SET vars[V_CHAR_SET].current_val.p #define GLO_CHAR_SET vars[V_CHAR_SET].global_val.p -Index: alpine-2.25/pith/conftype.h +Index: alpine-2.26/pith/conftype.h =================================================================== ---- alpine-2.25.orig/pith/conftype.h -+++ alpine-2.25/pith/conftype.h +--- alpine-2.26.orig/pith/conftype.h ++++ alpine-2.26/pith/conftype.h @@ -71,6 +71,20 @@ typedef enum { V_PERSONAL_NAME = 0 , V_THREAD_MORE_CHAR , V_THREAD_EXP_CHAR @@ -1006,7 +998,7 @@ Index: alpine-2.25/pith/conftype.h #ifndef _WINDOWS , V_CHAR_SET , V_OLD_CHAR_SET -@@ -349,6 +363,7 @@ typedef enum { +@@ -351,6 +365,7 @@ typedef enum { F_FULL_AUTO_EXPUNGE, F_EXPUNGE_MANUALLY, F_AUTO_READ_MSGS, @@ -1014,11 +1006,11 @@ Index: alpine-2.25/pith/conftype.h F_AUTO_FCC_ONLY, F_READ_IN_NEWSRC_ORDER, F_SELECT_WO_CONFIRM, -Index: alpine-2.25/pith/detoken.c +Index: alpine-2.26/pith/detoken.c =================================================================== ---- alpine-2.25.orig/pith/detoken.c -+++ alpine-2.25/pith/detoken.c -@@ -25,7 +25,7 @@ static char rcsid[] = "$Id: detoken.c 76 +--- alpine-2.26.orig/pith/detoken.c ++++ alpine-2.26/pith/detoken.c +@@ -21,7 +21,7 @@ #include "../pith/reply.h" #include "../pith/mailindx.h" #include "../pith/options.h" @@ -1027,7 +1019,7 @@ Index: alpine-2.25/pith/detoken.c /* * Hook to read signature from local file -@@ -91,6 +91,8 @@ detoken(ACTION_S *role, ENVELOPE *env, i +@@ -87,6 +87,8 @@ detoken(ACTION_S *role, ENVELOPE *env, i if(is_sig){ /* @@ -1036,7 +1028,7 @@ Index: alpine-2.25/pith/detoken.c * If role->litsig is set, we use it; * Else, if VAR_LITERAL_SIG is set, we use that; * Else, if role->sig is set, we use that; -@@ -104,14 +106,25 @@ detoken(ACTION_S *role, ENVELOPE *env, i +@@ -100,14 +102,25 @@ detoken(ACTION_S *role, ENVELOPE *env, i * there is no reason to mix them, so we don't provide support to * do so. */ @@ -1070,7 +1062,7 @@ Index: alpine-2.25/pith/detoken.c } else if(role && role->template) sigfile = role->template; -@@ -302,7 +315,7 @@ top: +@@ -298,7 +311,7 @@ top: } } } @@ -1079,10 +1071,10 @@ Index: alpine-2.25/pith/detoken.c repl = get_reply_data(env, role, pt->ctype, subbuf, sizeof(subbuf)-1); -Index: alpine-2.25/pith/indxtype.h +Index: alpine-2.26/pith/indxtype.h =================================================================== ---- alpine-2.25.orig/pith/indxtype.h -+++ alpine-2.25/pith/indxtype.h +--- alpine-2.26.orig/pith/indxtype.h ++++ alpine-2.26/pith/indxtype.h @@ -84,6 +84,11 @@ typedef enum {iNothing, iStatus, iFStatu iCurNews, iArrow, iMailbox, iAddress, iInit, iCursorPos, @@ -1131,11 +1123,11 @@ Index: alpine-2.25/pith/indxtype.h #define DEFAULT_REPLY_INTRO "default" -Index: alpine-2.25/pith/mailcmd.c +Index: alpine-2.26/pith/mailcmd.c =================================================================== ---- alpine-2.25.orig/pith/mailcmd.c -+++ alpine-2.25/pith/mailcmd.c -@@ -39,6 +39,7 @@ static char rcsid[] = "$Id: mailcmd.c 11 +--- alpine-2.26.orig/pith/mailcmd.c ++++ alpine-2.26/pith/mailcmd.c +@@ -35,6 +35,7 @@ #include "../pith/ablookup.h" #include "../pith/search.h" #include "../pith/charconv/utf8.h" @@ -1143,7 +1135,7 @@ Index: alpine-2.25/pith/mailcmd.c #ifdef _WINDOWS #include "../pico/osdep/mswin.h" -@@ -665,6 +666,7 @@ do_broach_folder(char *newfolder, CONTEX +@@ -661,6 +662,7 @@ do_broach_folder(char *newfolder, CONTEX strncpy(ps_global->cur_folder, p, sizeof(ps_global->cur_folder)-1); ps_global->cur_folder[sizeof(ps_global->cur_folder)-1] = '\0'; ps_global->context_current = ps_global->context_list; @@ -1151,7 +1143,7 @@ Index: alpine-2.25/pith/mailcmd.c reset_index_format(); clear_index_cache(ps_global->mail_stream, 0); /* MUST sort before restoring msgno! */ -@@ -991,6 +993,7 @@ do_broach_folder(char *newfolder, CONTEX +@@ -1001,6 +1003,7 @@ do_broach_folder(char *newfolder, CONTEX clear_index_cache(ps_global->mail_stream, 0); reset_index_format(); @@ -1159,7 +1151,7 @@ Index: alpine-2.25/pith/mailcmd.c /* * Start news reading with messages the user's marked deleted -@@ -1114,7 +1117,10 @@ do_broach_folder(char *newfolder, CONTEX +@@ -1124,7 +1127,10 @@ do_broach_folder(char *newfolder, CONTEX if(!cur_already_set && mn_get_total(ps_global->msgmap) > 0L){ @@ -1171,7 +1163,7 @@ Index: alpine-2.25/pith/mailcmd.c if(ps_global->start_entry > 0){ mn_set_cur(ps_global->msgmap, mn_get_revsort(ps_global->msgmap) -@@ -1136,124 +1142,7 @@ do_broach_folder(char *newfolder, CONTEX +@@ -1146,124 +1152,7 @@ do_broach_folder(char *newfolder, CONTEX else use_this_startup_rule = ps_global->inc_startup_rule; @@ -1297,7 +1289,7 @@ Index: alpine-2.25/pith/mailcmd.c } else if(IS_NEWS(ps_global->mail_stream)){ /* -@@ -1431,9 +1320,11 @@ expunge_and_close(MAILSTREAM *stream, ch +@@ -1441,9 +1330,11 @@ expunge_and_close(MAILSTREAM *stream, ch /* Save read messages? */ if(VAR_READ_MESSAGE_FOLDER && VAR_READ_MESSAGE_FOLDER[0] && sp_flagged(stream, SP_INBOX) @@ -1310,7 +1302,7 @@ Index: alpine-2.25/pith/mailcmd.c || (pith_opt_read_msg_prompt && (*pith_opt_read_msg_prompt)(seen_not_del, VAR_READ_MESSAGE_FOLDER))) /* move inbox's read messages */ -@@ -1716,6 +1607,9 @@ move_read_msgs(MAILSTREAM *stream, char +@@ -1726,6 +1617,9 @@ move_read_msgs(MAILSTREAM *stream, char char *bufp = NULL; MESSAGECACHE *mc; @@ -1320,7 +1312,7 @@ Index: alpine-2.25/pith/mailcmd.c if(!is_absolute_path(dstfldr) && !(save_context = default_save_context(ps_global->context_list))) save_context = ps_global->context_list; -@@ -1755,8 +1649,9 @@ move_read_msgs(MAILSTREAM *stream, char +@@ -1765,8 +1659,9 @@ move_read_msgs(MAILSTREAM *stream, char snprintf(buf, buflen, "Moving %s read message%s to \"%s\"", comatose(searched), plural(searched), dstfldr); we_cancel = busy_cue(buf, NULL, 0); @@ -1332,7 +1324,7 @@ Index: alpine-2.25/pith/mailcmd.c strncpy(bufp = buf + 1, "Moved", MIN(5,buflen)); /* change Moving to Moved */ buf[buflen-1] = '\0'; -@@ -1794,7 +1689,9 @@ move_read_incoming(MAILSTREAM *stream, C +@@ -1804,7 +1699,9 @@ move_read_incoming(MAILSTREAM *stream, C && ((context_isambig(folder) && folder_is_nick(folder, FOLDERS(context), 0)) || folder_index(folder, context, FI_FOLDER) > 0) @@ -1343,7 +1335,7 @@ Index: alpine-2.25/pith/mailcmd.c for(; f && *archive; archive++){ char *p; -@@ -2760,3 +2657,295 @@ get_uname(char *mailbox, char *target, i +@@ -2770,3 +2667,295 @@ get_uname(char *mailbox, char *target, i return(*target ? target : NULL); } @@ -1390,9 +1382,9 @@ Index: alpine-2.25/pith/mailcmd.c + comatose(num), plural(num), folder_to_save[i]); + we_cancel = busy_cue(buf, NULL, 1); + ps_global->exiting = 1; -+ if(success = save(ps_global, stream,save_context, folder_to_save[i], -+ msgmap, SV_DELETE | SV_FIX_DELS)) -+ nmsgs += success; ++ if((success = save(ps_global, stream,save_context, folder_to_save[i], ++ msgmap, SV_DELETE | SV_FIX_DELS))) ++ nmsgs += success; + if(we_cancel) + cancel_busy_cue(success ? 0 : -1); + for (j = i; j <= stream_nmsgs ; j++) @@ -1480,7 +1472,7 @@ Index: alpine-2.25/pith/mailcmd.c + + rule = get_result_rule(V_THREAD_INDEX_STYLE_RULES, FOR_THREAD, NULL); + if (rule || ps_global->VAR_THREAD_INDEX_STYLE){ -+ for(i = 0; v = thread_index_styles(i); i++) ++ for(i = 0; (v = thread_index_styles(i)) != NULL; i++) + if(!strucmp(rule ? rule->result : ps_global->VAR_THREAD_INDEX_STYLE, + rule ? (v ? v->name : "" ) : S_OR_L(v))){ + ps_global->thread_index_style = v->value; @@ -1506,7 +1498,7 @@ Index: alpine-2.25/pith/mailcmd.c + int i; + NAMEVAL_S *v; + -+ for(i = 0; v = incoming_startup_rules(i); i++) ++ for(i = 0; (v = incoming_startup_rules(i)) != NULL; i++) + if(!strucmp(rule_result, v->name)){ + startup_rule = v->value; + break; @@ -1639,10 +1631,10 @@ Index: alpine-2.25/pith/mailcmd.c + + } +} -Index: alpine-2.25/pith/mailcmd.h +Index: alpine-2.26/pith/mailcmd.h =================================================================== ---- alpine-2.25.orig/pith/mailcmd.h -+++ alpine-2.25/pith/mailcmd.h +--- alpine-2.26.orig/pith/mailcmd.h ++++ alpine-2.26/pith/mailcmd.h @@ -42,6 +42,8 @@ #define DB_FROMTAB 0x02 /* opening because of TAB command */ #define DB_INBOXWOCNTXT 0x04 /* interpret inbox as one true inbox */ @@ -1666,11 +1658,11 @@ Index: alpine-2.25/pith/mailcmd.h void cross_delete_crossposts(MAILSTREAM *); long zoom_index(struct pine *, MAILSTREAM *, MSGNO_S *, int); int unzoom_index(struct pine *, MAILSTREAM *, MSGNO_S *); -Index: alpine-2.25/pith/mailindx.c +Index: alpine-2.26/pith/mailindx.c =================================================================== ---- alpine-2.25.orig/pith/mailindx.c -+++ alpine-2.25/pith/mailindx.c -@@ -41,6 +41,7 @@ static char rcsid[] = "$Id: mailindx.c 1 +--- alpine-2.26.orig/pith/mailindx.c ++++ alpine-2.26/pith/mailindx.c +@@ -37,6 +37,7 @@ #include "../pith/send.h" #include "../pith/options.h" #include "../pith/ablookup.h" @@ -1678,13 +1670,13 @@ Index: alpine-2.25/pith/mailindx.c #ifdef _WINDOWS #include "../pico/osdep/mswin.h" #endif -@@ -379,6 +380,13 @@ reset_index_format(void) +@@ -375,6 +376,13 @@ reset_index_format(void) PAT_STATE pstate; PAT_S *pat; int we_set_it = 0; + char *rule; + -+ if(rule = get_rule_result(FOR_INDEX, ps_global->cur_folder, V_INDEX_RULES)){ ++ if((rule = get_rule_result(FOR_INDEX, ps_global->cur_folder, V_INDEX_RULES)) != NULL){ + init_index_format(rule, &ps_global->index_disp_format); + fs_give((void **)&rule); + return; @@ -1692,25 +1684,7 @@ Index: alpine-2.25/pith/mailindx.c if(ps_global->mail_stream && nonempty_patterns(rflags, &pstate)){ for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){ -@@ -452,7 +460,7 @@ free_hdrtok(HEADER_TOK_S **hdrtok) - static INDEX_PARSE_T itokens[] = { - {"STATUS", iStatus, FOR_INDEX}, - {"MSGNO", iMessNo, FOR_INDEX}, -- {"DATE", iDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE}, -+ {"DATE", iDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE}, - {"FROMORTO", iFromTo, FOR_INDEX}, - {"FROMORTONOTNEWS", iFromToNotNews, FOR_INDEX}, - {"SIZE", iSize, FOR_INDEX}, -@@ -460,7 +468,7 @@ static INDEX_PARSE_T itokens[] = { - {"SIZETHREAD", iSizeThread, FOR_INDEX}, - {"SIZENARROW", iSizeNarrow, FOR_INDEX}, - {"KSIZE", iKSize, FOR_INDEX}, -- {"SUBJECT", iSubject, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE}, -+ {"SUBJECT", iSubject, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_TRIM}, - {"SHORTSUBJECT", iShortSubject, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE}, - {"FULLSTATUS", iFStatus, FOR_INDEX}, - {"IMAPSTATUS", iIStatus, FOR_INDEX}, -@@ -472,56 +480,60 @@ static INDEX_PARSE_T itokens[] = { +@@ -468,56 +476,60 @@ static INDEX_PARSE_T itokens[] = { {"SUBJECTTEXT", iSubjectText, FOR_INDEX}, {"SUBJKEYTEXT", iSubjKeyText, FOR_INDEX}, {"SUBJKEYINITTEXT", iSubjKeyInitText, FOR_INDEX}, @@ -1815,7 +1789,7 @@ Index: alpine-2.25/pith/mailindx.c {"RECIPS", iRecips, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE}, {"NEWS", iNews, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE}, {"TOANDNEWS", iToAndNews, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE}, -@@ -530,56 +542,71 @@ static INDEX_PARSE_T itokens[] = { +@@ -526,56 +538,71 @@ static INDEX_PARSE_T itokens[] = { {"NEWSANDRECIPS", iNewsAndRecips, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE}, {"MSGID", iMsgID, FOR_REPLY_INTRO|FOR_TEMPLATE}, {"CURNEWS", iCurNews, FOR_REPLY_INTRO|FOR_TEMPLATE}, @@ -1926,7 +1900,7 @@ Index: alpine-2.25/pith/mailindx.c {NULL, iNothing, FOR_NOTHING} }; -@@ -2486,6 +2513,24 @@ format_index_index_line(INDEXDATA_S *ida +@@ -2482,6 +2509,24 @@ format_index_index_line(INDEXDATA_S *ida from_str(cdesc->ctype, idata, str, sizeof(str), ice); break; @@ -1951,16 +1925,16 @@ Index: alpine-2.25/pith/mailindx.c case iTo: if(((field = ((addr = fetch_to(idata)) ? "To" -@@ -3880,7 +3925,17 @@ try_again: +@@ -3876,7 +3921,17 @@ try_again: if(p > buf){ size_t l; + ENVELOPE *env; + char *rule_result; -+ if(rule_result = find_value((delete_quotes ++ if((rule_result = find_value((delete_quotes + ? "_OPENINGTEXTNQ_" : "_OPENINGTEXT_"), -+ buf, PROCESS_SP, idata, 4)){ ++ buf, PROCESS_SP, idata, 4)) != NULL){ + collspaces(rule_result); + strncpy(buf, rule_result, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; @@ -1969,7 +1943,7 @@ Index: alpine-2.25/pith/mailindx.c l = strlen(buf); l += 100; firsttext = fs_get((l+1) * sizeof(char)); -@@ -5459,10 +5514,10 @@ subj_str(INDEXDATA_S *idata, char *str, +@@ -5455,10 +5510,10 @@ subj_str(INDEXDATA_S *idata, char *str, { char *subject, *origsubj, *origstr, *rawsubj, *sptr = NULL; char *p, *border, *q = NULL, *free_subj = NULL; @@ -1982,11 +1956,11 @@ Index: alpine-2.25/pith/mailindx.c int save; int do_subj = 0, truncated_tree = 0; PINETHRD_S *thd, *thdorig; -@@ -5518,6 +5573,14 @@ subj_str(INDEXDATA_S *idata, char *str, +@@ -5514,6 +5569,14 @@ subj_str(INDEXDATA_S *idata, char *str, * to free it at the end of this routine. */ -+ if (rule_result = find_value("_SUBJECT_", origsubj, PROCESS_SP, idata, 4)){ ++ if ((rule_result = find_value("_SUBJECT_", origsubj, PROCESS_SP, idata, 4)) != NULL){ + if(origsubj) + fs_give((void **)&origsubj); + we_clear++; @@ -1997,7 +1971,7 @@ Index: alpine-2.25/pith/mailindx.c if(shorten) shorten_subject(origsubj); -@@ -5956,6 +6019,9 @@ subj_str(INDEXDATA_S *idata, char *str, +@@ -5952,6 +6015,9 @@ subj_str(INDEXDATA_S *idata, char *str, if(free_subj) fs_give((void **) &free_subj); @@ -2007,7 +1981,7 @@ Index: alpine-2.25/pith/mailindx.c } -@@ -6321,16 +6387,33 @@ from_str(IndexColType ctype, INDEXDATA_S +@@ -6317,16 +6383,33 @@ from_str(IndexColType ctype, INDEXDATA_S ? "To" : (addr = fetch_cc(idata)) ? "Cc" @@ -2022,7 +1996,7 @@ Index: alpine-2.25/pith/mailindx.c + set_index_addr(idata, field, addr, "To: ", + strsize-1, fptr); + else{ -+ sprintf(str, "%-*.*s", strsize-1, strsize-1, ++ sprintf(str, "%-*.*s", (int)(strsize-1), (int) (strsize-1), + rule_result); + fs_give((void **)&rule_result); + } @@ -2037,17 +2011,17 @@ Index: alpine-2.25/pith/mailindx.c + char *rule_result; + rule_result = find_value("_FROM_", NULL, 0, idata, 1); + if (!rule_result) -+ sprintf(str, "To: %-*.*s", strsize-1-4, -+ strsize-1-4, newsgroups); ++ sprintf(str, "To: %-*.*s", (int) (strsize-1-4), ++ (int) (strsize-1-4), newsgroups); + else{ -+ sprintf(str, "%-*.*s", strsize-1, strsize-1, ++ sprintf(str, "%-*.*s", (int) (strsize-1), (int) (strsize-1), + rule_result); + fs_give((void **)&rule_result); + } break; } -@@ -6343,7 +6426,15 @@ from_str(IndexColType ctype, INDEXDATA_S +@@ -6339,7 +6422,15 @@ from_str(IndexColType ctype, INDEXDATA_S break; case iFrom: @@ -2057,14 +2031,14 @@ Index: alpine-2.25/pith/mailindx.c + if (!rule_result) + set_index_addr(idata, "From", fetch_from(idata), NULL, strsize-1, fptr); + else{ -+ sprintf(str, "%-*.*s", strsize-1, strsize-1, rule_result); ++ sprintf(str, "%-*.*s", (int) (strsize-1), (int) (strsize-1), rule_result); + fs_give((void **)&rule_result); + } + } break; case iAddress: -@@ -6641,3 +6732,64 @@ set_print_format(IELEM_S *ielem, int wid +@@ -6637,3 +6728,64 @@ set_print_format(IELEM_S *ielem, int wid } } } @@ -2129,10 +2103,10 @@ Index: alpine-2.25/pith/mailindx.c + } + return rule_result; +} -Index: alpine-2.25/pith/mailindx.h +Index: alpine-2.26/pith/mailindx.h =================================================================== ---- alpine-2.25.orig/pith/mailindx.h -+++ alpine-2.25/pith/mailindx.h +--- alpine-2.26.orig/pith/mailindx.h ++++ alpine-2.26/pith/mailindx.h @@ -30,6 +30,9 @@ extern void (*setup_header_widths)(MAIL @@ -2143,10 +2117,10 @@ Index: alpine-2.25/pith/mailindx.h int msgline_hidden(MAILSTREAM *, MSGNO_S *, long, int); void adjust_cur_to_visible(MAILSTREAM *, MSGNO_S *); unsigned long line_hash(char *); -Index: alpine-2.25/pith/makefile.wnt +Index: alpine-2.26/pith/makefile.wnt =================================================================== ---- alpine-2.25.orig/pith/makefile.wnt -+++ alpine-2.25/pith/makefile.wnt +--- alpine-2.26.orig/pith/makefile.wnt ++++ alpine-2.26/pith/makefile.wnt @@ -46,7 +46,8 @@ HFILES= ../include/system.h ../include/g init.h keyword.h ldap.h list.h mailcap.h mailcmd.h mailindx.h maillist.h \ mailpart.h mailview.h margin.h mimedesc.h mimetype.h msgno.h newmail.h news.h \ @@ -2166,11 +2140,11 @@ Index: alpine-2.25/pith/makefile.wnt smime.obj smkeys.obj sort.obj state.obj status.obj store.obj stream.obj string.obj strlst.obj \ takeaddr.obj tempfile.obj text.obj thread.obj adjtime.obj url.obj util.obj -Index: alpine-2.25/pith/pine.hlp +Index: alpine-2.26/pith/pine.hlp =================================================================== ---- alpine-2.25.orig/pith/pine.hlp -+++ alpine-2.25/pith/pine.hlp -@@ -4760,6 +4760,7 @@ There are also additional details on +--- alpine-2.26.orig/pith/pine.hlp ++++ alpine-2.26/pith/pine.hlp +@@ -4916,6 +4916,7 @@ There are also additional details on

  • FEATURE:
  • FEATURE:
  • FEATURE: @@ -2178,7 +2152,7 @@ Index: alpine-2.25/pith/pine.hlp
  • FEATURE:
  • FEATURE:
  • FEATURE: -@@ -20292,6 +20293,7 @@ This set of special tokens may be used i +@@ -20446,6 +20447,7 @@ This set of special tokens may be used i "" option, in the "" option, in signature files, @@ -2186,7 +2160,7 @@ Index: alpine-2.25/pith/pine.hlp in template files used in "roles", and in the folder name that is the target of a Filter Rule. -@@ -20304,7 +20306,7 @@ and in the target of Filter Rules. +@@ -20458,7 +20460,7 @@ and in the target of Filter Rules.

    @@ -2195,7 +2169,7 @@ Index: alpine-2.25/pith/pine.hlp

    SUBJECT
    -@@ -20338,6 +20340,22 @@ email address, never the personal name. +@@ -20492,6 +20494,22 @@ email address, never the personal name. For example, "mailbox@domain".
  • @@ -2218,7 +2192,7 @@ Index: alpine-2.25/pith/pine.hlp
    MAILBOX
    This is the same as the "ADDRESS" except that the -@@ -20385,6 +20403,15 @@ are unavailable) of the persons specifie +@@ -20539,6 +20557,15 @@ are unavailable) of the persons specifie message's "Cc:" header field.
    @@ -2234,7 +2208,7 @@ Index: alpine-2.25/pith/pine.hlp
    RECIPS
    This token represents the personal names (or email addresses if the names -@@ -20393,6 +20420,14 @@ message's "To:" header field a +@@ -20547,6 +20574,14 @@ message's "To:" header field a the message's "Cc:" header field.
    @@ -2249,7 +2223,7 @@ Index: alpine-2.25/pith/pine.hlp
    NEWSANDRECIPS
    This token represents the newsgroups from the -@@ -21525,6 +21560,110 @@ This is an end of line marker. +@@ -21679,6 +21714,110 @@ This is an end of line marker.

    @@ -2360,7 +2334,7 @@ Index: alpine-2.25/pith/pine.hlp

    Token Available Only for Templates and Signatures

    -@@ -25015,6 +25154,922 @@ character sets Alpine knows about by usi +@@ -25169,6 +25308,922 @@ character sets Alpine knows about by usi <End of help on this topic> @@ -3283,7 +3257,7 @@ Index: alpine-2.25/pith/pine.hlp ====== h_config_char_set ===== -@@ -28767,6 +29822,76 @@ the From field is used to show the relat +@@ -28921,6 +29976,76 @@ the From field is used to show the relat <End of help on this topic> @@ -3360,7 +3334,7 @@ Index: alpine-2.25/pith/pine.hlp ====== h_config_pruning_rule ===== -@@ -32449,6 +33574,29 @@ automatically transfer all read messages +@@ -32587,6 +33712,29 @@ automatically transfer all read messages them as deleted in the INBOX. Messages in the INBOX marked with an "N" (meaning New, or unseen) are not affected.

    @@ -3390,11 +3364,11 @@ Index: alpine-2.25/pith/pine.hlp

    -Index: alpine-2.25/pith/reply.c +Index: alpine-2.26/pith/reply.c =================================================================== ---- alpine-2.25.orig/pith/reply.c -+++ alpine-2.25/pith/reply.c -@@ -47,6 +47,8 @@ static char rcsid[] = "$Id: reply.c 1074 +--- alpine-2.26.orig/pith/reply.c ++++ alpine-2.26/pith/reply.c +@@ -43,6 +43,8 @@ #include "../pith/mailcmd.h" #include "../pith/margin.h" #include "../pith/smime.h" @@ -3403,7 +3377,7 @@ Index: alpine-2.25/pith/reply.c /* -@@ -864,8 +866,27 @@ char * +@@ -860,8 +862,27 @@ char * reply_quote_str(ENVELOPE *env) { char *prefix, *repl, *p, buf[MAX_PREFIX+1], pbf[MAX_SUBSTITUTION+1]; @@ -3425,14 +3399,14 @@ Index: alpine-2.25/pith/reply.c + reply_string[sizeof(reply_string)-1] = '\0'; + } + else -+ strncpy(reply_string,"> ",sizeof("> ")); ++ strncpy(reply_string,"> ", 3); + } + + strncpy(buf, reply_string, sizeof(buf)-1); buf[sizeof(buf)-1] = '\0'; /* set up the prefix to quote included text */ -@@ -917,10 +938,29 @@ reply_quote_str(ENVELOPE *env) +@@ -913,10 +934,29 @@ reply_quote_str(ENVELOPE *env) int reply_quote_str_contains_tokens(void) { @@ -3466,7 +3440,7 @@ Index: alpine-2.25/pith/reply.c } -@@ -1486,6 +1526,10 @@ get_addr_data(ENVELOPE *env, IndexColTyp +@@ -1482,6 +1522,10 @@ get_addr_data(ENVELOPE *env, IndexColTyp buf[0] = '\0'; switch(type){ @@ -3477,7 +3451,7 @@ Index: alpine-2.25/pith/reply.c case iFrom: addr = env ? env->from : NULL; break; -@@ -1898,22 +1942,194 @@ get_reply_data(ENVELOPE *env, ACTION_S * +@@ -1894,22 +1938,194 @@ get_reply_data(ENVELOPE *env, ACTION_S * break; @@ -3677,7 +3651,7 @@ Index: alpine-2.25/pith/reply.c case iNewLine: if(maxlen >= strlen(NEWLINE)){ strncpy(buf, NEWLINE, maxlen); -@@ -1941,6 +2157,11 @@ get_reply_data(ENVELOPE *env, ACTION_S * +@@ -1937,6 +2153,11 @@ get_reply_data(ENVELOPE *env, ACTION_S * break; @@ -3689,7 +3663,7 @@ Index: alpine-2.25/pith/reply.c case iNews: case iCurNews: get_news_data(env, type, buf, maxlen); -@@ -1990,6 +2211,14 @@ get_reply_data(ENVELOPE *env, ACTION_S * +@@ -1986,6 +2207,14 @@ get_reply_data(ENVELOPE *env, ACTION_S * break; @@ -3704,7 +3678,7 @@ Index: alpine-2.25/pith/reply.c case iSubject: case iShortSubject: if(env && env->subject){ -@@ -2052,7 +2281,18 @@ reply_delimiter(ENVELOPE *env, ACTION_S +@@ -2048,7 +2277,18 @@ reply_delimiter(ENVELOPE *env, ACTION_S if(!env) return; @@ -3724,7 +3698,7 @@ Index: alpine-2.25/pith/reply.c buf[MAX_DELIM] = '\0'; /* preserve exact default behavior from before */ if(!strcmp(buf, DEFAULT_REPLY_INTRO)){ -@@ -2311,6 +2551,7 @@ forward_subject(ENVELOPE *env, int flags +@@ -2307,6 +2547,7 @@ forward_subject(ENVELOPE *env, int flags { size_t l; char *p, buftmp[MAILTMPLEN]; @@ -3732,7 +3706,7 @@ Index: alpine-2.25/pith/reply.c if(!env) return(NULL); -@@ -2318,9 +2559,19 @@ forward_subject(ENVELOPE *env, int flags +@@ -2314,9 +2555,19 @@ forward_subject(ENVELOPE *env, int flags dprint((9, "checking subject: \"%s\"\n", env->subject ? env->subject : "NULL")); @@ -3755,11 +3729,11 @@ Index: alpine-2.25/pith/reply.c /* decode any 8bit (copy to the temp buffer if decoding doesn't) */ if(rfc1522_decode_to_utf8((unsigned char *) tmp_20k_buf, SIZEOF_20KBUF, buftmp) == (unsigned char *) buftmp) -Index: alpine-2.25/pith/rules.c +Index: alpine-2.26/pith/rules.c =================================================================== --- /dev/null -+++ alpine-2.25/pith/rules.c -@@ -0,0 +1,1565 @@ ++++ alpine-2.26/pith/rules.c +@@ -0,0 +1,1566 @@ +/* This module was written by + * + * Eduardo Chappa (chappa@washington.edu) @@ -4257,8 +4231,9 @@ Index: alpine-2.25/pith/rules.c + p++; + if(level < 0) error++; + break; -+ case '_' : for(s = p+1; *s >= 'A' && *s <= 'Z'; s++); -+ for(i = 0; token_rules[i] != NULL; i++) ++ case '_' : for (s = p+1; *s >= 'A' && *s <= 'Z'; s++) ++ ; ++ for (i = 0; token_rules[i] != NULL; i++) + if(!strncmp(token_rules[i], p, s-p)) + break; + if(token_rules[i] == NULL) @@ -5325,10 +5300,10 @@ Index: alpine-2.25/pith/rules.c + env = pine_mail_fetchenvelope(idata->stream, idata->rawno); + return env; +} -Index: alpine-2.25/pith/rules.h +Index: alpine-2.26/pith/rules.h =================================================================== --- /dev/null -+++ alpine-2.25/pith/rules.h ++++ alpine-2.26/pith/rules.h @@ -0,0 +1,154 @@ +/* Included file rules.h */ + @@ -5484,10 +5459,10 @@ Index: alpine-2.25/pith/rules.h +#define RELAXED 0x2 + +#endif /* PITH_RULES_INCLUDED */ -Index: alpine-2.25/pith/rulestype.h +Index: alpine-2.26/pith/rulestype.h =================================================================== --- /dev/null -+++ alpine-2.25/pith/rulestype.h ++++ alpine-2.26/pith/rulestype.h @@ -0,0 +1,94 @@ +#ifndef PITH_RULESTYPE_INCLUDED +#define PITH_RULESTYPE_INCLUDED @@ -5583,11 +5558,11 @@ Index: alpine-2.25/pith/rulestype.h + + +#endif /* PITH_RULESTYPE_INCLUDED */ -Index: alpine-2.25/pith/save.c +Index: alpine-2.26/pith/save.c =================================================================== ---- alpine-2.25.orig/pith/save.c -+++ alpine-2.25/pith/save.c -@@ -955,7 +955,7 @@ save(struct pine *state, MAILSTREAM *str +--- alpine-2.26.orig/pith/save.c ++++ alpine-2.26/pith/save.c +@@ -951,7 +951,7 @@ save(struct pine *state, MAILSTREAM *str *date = '\0'; rv = save_fetch_append(stream, mn_m2raw(msgmap, i), @@ -5596,11 +5571,11 @@ Index: alpine-2.25/pith/save.c mc ? mc->rfc822_size : 0L, flags, date, so); if(flags) -Index: alpine-2.25/pith/send.c +Index: alpine-2.26/pith/send.c =================================================================== ---- alpine-2.25.orig/pith/send.c -+++ alpine-2.25/pith/send.c -@@ -44,6 +44,7 @@ static char rcsid[] = "$Id: send.c 1204 +--- alpine-2.26.orig/pith/send.c ++++ alpine-2.26/pith/send.c +@@ -40,6 +40,7 @@ #include "../pith/ablookup.h" #include "../pith/sort.h" #include "../pith/smime.h" @@ -5608,7 +5583,7 @@ Index: alpine-2.25/pith/send.c #include "../c-client/smtp.h" #include "../c-client/nntp.h" -@@ -1695,9 +1696,9 @@ call_mailer(METAENV *header, struct mail +@@ -1691,9 +1692,9 @@ call_mailer(METAENV *header, struct mail char error_buf[200], *error_mess = NULL, *postcmd; ADDRESS *a; ENVELOPE *fake_env = NULL; @@ -5620,7 +5595,7 @@ Index: alpine-2.25/pith/send.c BODY *bp = NULL; PINEFIELD *pf; BODY *origBody = body; -@@ -1852,20 +1853,49 @@ call_mailer(METAENV *header, struct mail +@@ -1848,20 +1849,49 @@ call_mailer(METAENV *header, struct mail * OK, who posts what? We tried an mta_handoff above, but there * was either none specified or we decided not to use it. So, * if there's an smtp-server defined anywhere, @@ -5682,11 +5657,11 @@ Index: alpine-2.25/pith/send.c } else if((postcmd = smtp_command(ps_global->c_client_error, sizeof(ps_global->c_client_error))) != NULL){ char *cmdlist[2]; -Index: alpine-2.25/pith/sort.c +Index: alpine-2.26/pith/sort.c =================================================================== ---- alpine-2.25.orig/pith/sort.c -+++ alpine-2.25/pith/sort.c -@@ -30,7 +30,7 @@ static char rcsid[] = "$Id: sort.c 1142 +--- alpine-2.26.orig/pith/sort.c ++++ alpine-2.26/pith/sort.c +@@ -26,7 +26,7 @@ #include "../pith/signal.h" #include "../pith/busy.h" #include "../pith/icache.h" @@ -5695,7 +5670,7 @@ Index: alpine-2.25/pith/sort.c /* * global place to store mail_sort and mail_thread results -@@ -695,7 +695,21 @@ reset_sort_order(unsigned int flags) +@@ -691,7 +691,21 @@ reset_sort_order(unsigned int flags) PAT_S *pat; SortOrder the_sort_order; int sort_is_rev; @@ -5718,15 +5693,15 @@ Index: alpine-2.25/pith/sort.c /* set default order */ the_sort_order = ps_global->def_sort; sort_is_rev = the_sort_order == SortThread -@@ -718,6 +732,7 @@ reset_sort_order(unsigned int flags) +@@ -714,6 +728,7 @@ reset_sort_order(unsigned int flags) : pat->action->revsort; } } -+ } ++ } if(the_sort_order == SortThread && !(flags & SRT_MAN)) ps_global->thread_cur_sort = ps_global->thread_def_sort; -@@ -725,3 +740,39 @@ reset_sort_order(unsigned int flags) +@@ -721,3 +736,39 @@ reset_sort_order(unsigned int flags) sort_folder(ps_global->mail_stream, ps_global->msgmap, the_sort_order, sort_is_rev, flags, 1); } @@ -5766,10 +5741,10 @@ Index: alpine-2.25/pith/sort.c + return is_rev || rev ? SortScore : EndofList; + return EndofList; +} -Index: alpine-2.25/pith/sort.h +Index: alpine-2.26/pith/sort.h =================================================================== ---- alpine-2.25.orig/pith/sort.h -+++ alpine-2.25/pith/sort.h +--- alpine-2.26.orig/pith/sort.h ++++ alpine-2.26/pith/sort.h @@ -45,6 +45,6 @@ char *sort_name(SortOrder); void sort_folder(MAILSTREAM *, MSGNO_S *, SortOrder, int, unsigned, int); int decode_sort(char *, SortOrder *, int *, int); @@ -5778,11 +5753,11 @@ Index: alpine-2.25/pith/sort.h +SortOrder translate(char *, int); #endif /* PITH_SORT_INCLUDED */ -Index: alpine-2.25/pith/state.c +Index: alpine-2.26/pith/state.c =================================================================== ---- alpine-2.25.orig/pith/state.c -+++ alpine-2.25/pith/state.c -@@ -35,6 +35,7 @@ static char rcsid[] = "$Id: state.c 1074 +--- alpine-2.26.orig/pith/state.c ++++ alpine-2.26/pith/state.c +@@ -31,6 +31,7 @@ #include "../pith/smime.h" #include "../pith/ical.h" #include "../pith/bldaddr.h" @@ -5790,7 +5765,7 @@ Index: alpine-2.25/pith/state.c /* * Globals referenced throughout pine... -@@ -258,6 +259,9 @@ free_pine_struct(struct pine **pps) +@@ -254,6 +255,9 @@ free_pine_struct(struct pine **pps) if((*pps)->id) free_id(&(*pps)->id); @@ -5800,10 +5775,10 @@ Index: alpine-2.25/pith/state.c free_vars(*pps); fs_give((void **) pps); -Index: alpine-2.25/pith/state.h +Index: alpine-2.26/pith/state.h =================================================================== ---- alpine-2.25.orig/pith/state.h -+++ alpine-2.25/pith/state.h +--- alpine-2.26.orig/pith/state.h ++++ alpine-2.26/pith/state.h @@ -33,7 +33,7 @@ #include "../pith/stream.h" #include "../pith/color.h" @@ -5825,7 +5800,7 @@ Index: alpine-2.25/pith/state.h unsigned read_predicted:1; char cur_folder[MAXPATH+1]; -@@ -369,6 +374,7 @@ struct pine { +@@ -371,6 +376,7 @@ struct pine { struct { char *(*display_filter)(char *, STORE_S *, gf_io_t, FILTLIST_S *); char *(*display_filter_trigger)(BODY *, char *, size_t); @@ -5833,7 +5808,7 @@ Index: alpine-2.25/pith/state.h } tools; KEYWORD_S *keywords; -@@ -379,6 +385,9 @@ struct pine { +@@ -381,6 +387,9 @@ struct pine { char last_error[500]; INIT_ERR_S *init_errs; @@ -5843,11 +5818,11 @@ Index: alpine-2.25/pith/state.h PRINT_S *print; #ifdef SMIME -Index: alpine-2.25/pith/string.c +Index: alpine-2.26/pith/string.c =================================================================== ---- alpine-2.25.orig/pith/string.c -+++ alpine-2.25/pith/string.c -@@ -20,6 +20,7 @@ static char rcsid[] = "$Id: string.c 910 +--- alpine-2.26.orig/pith/string.c ++++ alpine-2.26/pith/string.c +@@ -16,6 +16,7 @@ string.c Misc extra and useful string functions - rplstr replace a substring with another string @@ -5855,7 +5830,7 @@ Index: alpine-2.25/pith/string.c - sqzspaces Squeeze out the extra blanks in a string - sqznewlines Squeeze out \n and \r. - removing_trailing_white_space -@@ -131,6 +132,31 @@ rplstr(char *os, size_t oslen, int dl, c +@@ -127,6 +128,31 @@ rplstr(char *os, size_t oslen, int dl, c return(x3); } @@ -5887,9 +5862,9 @@ Index: alpine-2.25/pith/string.c /*---------------------------------------------------------------------- -@@ -2997,3 +3023,35 @@ convert_decimal_to_alpha (char *rn, size - if(i < len) rn[i] = '\0'; - rn[len-1] = '\0'; +@@ -3041,3 +3067,35 @@ remove_quotes(unsigned char *name) + } + } } + + @@ -5923,10 +5898,10 @@ Index: alpine-2.25/pith/string.c + } +} + -Index: alpine-2.25/pith/string.h +Index: alpine-2.26/pith/string.h =================================================================== ---- alpine-2.25.orig/pith/string.h -+++ alpine-2.25/pith/string.h +--- alpine-2.26.orig/pith/string.h ++++ alpine-2.26/pith/string.h @@ -87,6 +87,7 @@ struct date { /* exported prototypes */