summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduardo Chappa <chappa@washington.edu>2015-03-15 22:39:54 -0600
committerEduardo Chappa <chappa@washington.edu>2015-03-15 22:39:54 -0600
commit955a543f9ac3bb29b88a42d0520ac68324c2f6fa (patch)
tree89d5f69fe3569b97a96ca0b901f8886c3457524c
parentc2af1608456087b5d9475e3b288a12554214c221 (diff)
downloadalpine-955a543f9ac3bb29b88a42d0520ac68324c2f6fa.tar.xz
* new version 2.20.3
* SMIME: If a message contains a RFC822 atachment that is signed/decrypted add the ability to view its SMIME information. * SMIME: The ^E command that gives information on the certificate is only available for messages that have a signed or encrypted part. * Fix vulnerability in regex library. This only affects those who use this library, such as the windows version of Alpine. See http://www.kb.cert.org/vuls/id/695940. * HTML: Add support for decoding entities in hexadecimal notation. Suggested by Tulipánt Gergely. * Pico: Add the ability to search for strings in the beginning or end of a line. In the search menu, pressing Ctrl-^ toggles the prompt to search for a string at the beginning of a line. Another press of Ctrl-^ toggles the prompt to search for a string at the end of a line, and pressing Ctrl-^ one more time searches for the string anywhere in the text.
-rw-r--r--alpine/keymenu.c20
-rw-r--r--alpine/keymenu.h2
-rw-r--r--alpine/mailcmd.c2
-rw-r--r--alpine/mailpart.c33
-rw-r--r--alpine/smime.c89
-rw-r--r--alpine/smime.h3
-rw-r--r--doc/alpine.110
-rw-r--r--pico/browse.c18
-rw-r--r--pico/estruct.h7
-rw-r--r--pico/osdep/altedit.c2
-rw-r--r--pico/osdep/spell.c2
-rw-r--r--pico/search.c132
-rw-r--r--pith/filter.c18
-rw-r--r--pith/osdep/pipe.c2
-rw-r--r--pith/pine.hlp23
-rw-r--r--pith/smime.c3
-rw-r--r--po/Makefile.in2
-rw-r--r--regex/regcomp.c7
18 files changed, 308 insertions, 67 deletions
diff --git a/alpine/keymenu.c b/alpine/keymenu.c
index 06ef373e..92b90e6f 100644
--- a/alpine/keymenu.c
+++ b/alpine/keymenu.c
@@ -813,7 +813,25 @@ struct key att_view_keys[] =
{"%", N_("Print"), {MC_PRINTMSG,1,{'%'}}, KS_PRINT},
NULL_MENU,
REPLY_MENU,
- FORWARD_MENU};
+ FORWARD_MENU,
+
+ HELP_MENU,
+ OTHER_MENU,
+ HOMEKEY_MENU,
+ ENDKEY_MENU,
+ NULL_MENU,
+ NULL_MENU,
+#ifdef SMIME
+ {"^D","Decrypt", {MC_DECRYPT,1,{ctrl('d')},KS_NONE}},
+ {"^E","Security", {MC_SECURITY,1,{ctrl('e')},KS_NONE}},
+#else
+ NULL_MENU,
+ NULL_MENU,
+#endif
+ NULL_MENU,
+ NULL_MENU,
+ NULL_MENU,
+ NULL_MENU};
INST_KEY_MENU(att_view_keymenu, att_view_keys);
diff --git a/alpine/keymenu.h b/alpine/keymenu.h
index 58fe0bb7..eaffd29e 100644
--- a/alpine/keymenu.h
+++ b/alpine/keymenu.h
@@ -519,6 +519,8 @@ struct key_menu {
#define ATV_PRINT_KEY 20
#define ATV_REPLY_KEY 22
#define ATV_FORWARD_KEY 23
+#define ATV_DECRYPT_KEY (ATV_PIPE_KEY + 14)
+#define ATV_SECURITY_KEY (ATV_DECRYPT_KEY + 1)
#define VIEW_ATT_KEY 3
#define VIEW_FULL_HEADERS_KEY 32
#define VIEW_VIEW_HANDLE 26
diff --git a/alpine/mailcmd.c b/alpine/mailcmd.c
index a418891a..2fcd2165 100644
--- a/alpine/mailcmd.c
+++ b/alpine/mailcmd.c
@@ -1476,7 +1476,7 @@ get_out:
break;
case MC_SECURITY:
- state->next_screen = smime_info_screen;
+ smime_info_screen(state);
break;
#endif
diff --git a/alpine/mailpart.c b/alpine/mailpart.c
index a1064cf1..e7fd43b9 100644
--- a/alpine/mailpart.c
+++ b/alpine/mailpart.c
@@ -39,6 +39,7 @@ static char rcsid[] = "$Id: mailpart.c 1074 2008-06-04 00:08:43Z hubert@u.washin
#include "signal.h"
#include "send.h"
#include "busy.h"
+#include "smime.h"
#include "../pith/state.h"
#include "../pith/conf.h"
#include "../pith/store.h"
@@ -2522,6 +2523,15 @@ scroll_attachment(char *title, STORE_S *store, SourceType src, HANDLE_S *handles
clrbitn(ATV_REPLY_KEY, sargs.keys.bitmap);
clrbitn(ATV_EXPORT_KEY, sargs.keys.bitmap);
}
+#ifdef SMIME
+ if(!(ps_global->smime && ps_global->smime->need_passphrase))
+ clrbitn(ATV_DECRYPT_KEY, sargs.keys.bitmap);
+
+ if(F_ON(F_DONT_DO_SMIME, ps_global) || !MIME_MSG_A(a)){
+ clrbitn(ATV_DECRYPT_KEY, sargs.keys.bitmap);
+ clrbitn(ATV_SECURITY_KEY, sargs.keys.bitmap);
+ }
+#endif
sargs.use_indexline_color = 1;
@@ -2536,6 +2546,18 @@ scroll_attachment(char *title, STORE_S *store, SourceType src, HANDLE_S *handles
return(scrolltool(&sargs));
}
+void
+display_smime_info_att(struct pine *ps, ATTACH_S *a)
+{
+ if(smime_check(a->body->nested.msg->body) == 0){
+ q_status_message(SM_ORDER | SM_DING, 0, 3,
+ _("Not a signed or encrypted message"));
+ return;
+ }
+
+ display_smime_info(ps, a->body->nested.msg->env, a->body->nested.msg->body);
+}
+
int
process_attachment_cmd(int cmd, MSGNO_S *msgmap, SCROLL_S *sparms)
@@ -2634,6 +2656,17 @@ process_attachment_cmd(int cmd, MSGNO_S *msgmap, SCROLL_S *sparms)
rv = 1;
break;
+#ifdef SMIME
+ case MC_DECRYPT:
+ if(ps_global->smime && ps_global->smime->need_passphrase)
+ smime_get_passphrase();
+ break;
+
+ case MC_SECURITY:
+ display_smime_info_att(ps_global, sparms->proc.data.p);
+ break;
+#endif
+
default:
alpine_panic("Unexpected command case");
break;
diff --git a/alpine/smime.c b/alpine/smime.c
index 6c175d34..6f2665c7 100644
--- a/alpine/smime.c
+++ b/alpine/smime.c
@@ -97,40 +97,40 @@ smime_get_passphrase(void)
return rc; /* better return rc and make the caller check its return value */
}
+int
+smime_check(BODY *body)
+{
+ int rv = 0;
+ PKCS7 *p7 = NULL;
+
+ if(body->type == TYPEMULTIPART){
+ PART *p;
+
+ for(p=body->nested.part; p && rv == 0; p=p->next)
+ rv += smime_check(&p->body);
+ }
+ if(rv > 0) return rv;
+ if(body->sparep)
+ p7 = get_smime_sparep_type(body->sparep) == P7Type
+ ? (PKCS7 *)get_smime_sparep_data(body->sparep)
+ : NULL;
+ if(p7 && (PKCS7_type_is_signed(p7) || PKCS7_type_is_enveloped(p7)))
+ rv += 1;
+ return rv;
+}
+
void
-smime_info_screen(struct pine *ps)
-{
- long msgno;
- OtherMenu what;
- int offset = 0;
- BODY *body;
- ENVELOPE *env;
+display_smime_info(struct pine *ps, ENVELOPE *env, BODY *body)
+{
+ OtherMenu what = FirstMenu;
HANDLE_S *handles = NULL;
SCROLL_S scrollargs;
STORE_S *store = NULL;
-
- ps->prev_screen = smime_info_screen;
- ps->next_screen = SCREEN_FUN_NULL;
-
- if(mn_total_cur(ps->msgmap) > 1L){
- q_status_message(SM_ORDER | SM_DING, 0, 3,
- _("Can only view one message's information at a time."));
- return;
- }
- /* else check for existence of smime bits */
+ long msgno;
+ int offset = 0;
msgno = mn_m2raw(ps->msgmap, mn_get_cur(ps->msgmap));
-
- env = mail_fetch_structure(ps->mail_stream, msgno, &body, 0);
- if(!env || !body){
- q_status_message(SM_ORDER, 0, 3,
- _("Can't fetch body of message."));
- return;
- }
-
- what = FirstMenu;
-
store = so_get(CharStar, NULL, EDIT_ACCESS);
while(ps->next_screen == SCREEN_FUN_NULL){
@@ -183,6 +183,41 @@ smime_info_screen(struct pine *ps)
so_give(&store);
}
+void
+smime_info_screen(struct pine *ps)
+{
+ long msgno;
+ BODY *body;
+ ENVELOPE *env;
+
+/* ps->prev_screen = smime_info_screen;
+ ps->next_screen = SCREEN_FUN_NULL; */
+
+ msgno = mn_m2raw(ps->msgmap, mn_get_cur(ps->msgmap));
+
+ env = mail_fetch_structure(ps->mail_stream, msgno, &body, 0);
+
+ if(!env || !body){
+ q_status_message(SM_ORDER, 0, 3,
+ _("Can't fetch body of message."));
+ return;
+ }
+
+ if(smime_check(body) == 0){
+ q_status_message(SM_ORDER | SM_DING, 0, 3,
+ _("Not a signed or encrypted message"));
+ return;
+ }
+
+ if(mn_total_cur(ps->msgmap) > 1L){
+ q_status_message(SM_ORDER | SM_DING, 0, 3,
+ _("Can only view one message's information at a time."));
+ return;
+ }
+
+ display_smime_info(ps, env, body);
+}
+
void
format_smime_info(int pass, BODY *body, long msgno, gf_io_t pc)
diff --git a/alpine/smime.h b/alpine/smime.h
index d0367e0e..b584be2e 100644
--- a/alpine/smime.h
+++ b/alpine/smime.h
@@ -29,7 +29,8 @@ int smime_certificate_error_ask(int error);
void smime_info_screen(struct pine *ps);
void smime_config_screen(struct pine *, int edit_exceptions);
int smime_related_var(struct pine *, struct variable *);
-
+void display_smime_info(struct pine *, ENVELOPE *, BODY *);
+int smime_check(BODY *); /* check that the message is smime */
#endif /* PINE_SMIME_INCLUDED */
#endif /* SMIME */
diff --git a/doc/alpine.1 b/doc/alpine.1
index 66e0d8d8..c75cbcc3 100644
--- a/doc/alpine.1
+++ b/doc/alpine.1
@@ -291,6 +291,8 @@ uses the following environment variables:
.br
~/.addressbook Default address book file.
.br
+~/.signature File used for signature, appended to every message.
+.br
~/.pine-debug[1-4] Diagnostic log for debugging.
.br
~/.pinerc Personal alpine config file.
@@ -313,11 +315,17 @@ uses the following environment variables:
.br
/usr/local/lib/pine.conf.fixed Non-overridable configuration file.
.br
+~/.alpine-smime/ca Directory that contains Certificate Authority files.
+.br
+~/.alpine-smime/private Directory that contains private key(s).
+.br
+~/.alpine-smime/public Directory that contains public key(s).
+.br
/tmp/.\\usr\\spool\\mail\\xxxx Per-folder mailbox lock files.
.br
~/.pine-interrupted-mail Message which was interrupted.
.br
-~/mail/postponed-msgs For postponed messages.
+~/mail/postponed-msgs For postponed messages (drafts)
.br
~/mail/sent-mail Outgoing message archive (FCC).
.br
diff --git a/pico/browse.c b/pico/browse.c
index 96f078f4..d30ad2d1 100644
--- a/pico/browse.c
+++ b/pico/browse.c
@@ -317,7 +317,7 @@ FileBrowse(char *dir, size_t dirlen, char *fn, size_t fnlen,
UCS c, new_c;
int status, i, j;
int row, col, crow, ccol;
- int bsearch; /* search forward by default */
+ int flags;
char *p, *envp, child[NLINE], tmp[NLINE];
struct bmaster *mp;
struct fcell *tp;
@@ -1597,11 +1597,11 @@ FileBrowse(char *dir, size_t dirlen, char *fn, size_t fnlen,
case 'w': /* Where is */
case 'W':
case (CTRL|'W'):
- bsearch = i = 0;
+ i = 0;
+ flags = SR_FORWARD;
while(!i){
-
- switch(readpattern(_("File name to find"), FALSE, bsearch)){
+ switch(readpattern(_("File name to find"), FALSE, flags)){
case HELPCH:
emlwrite(_("\007No help yet!"), NULL);
/* remove break and sleep after help text is installed */
@@ -1611,7 +1611,13 @@ FileBrowse(char *dir, size_t dirlen, char *fn, size_t fnlen,
PaintBrowser(gmp, 0, &crow, &ccol);
break;
case (CTRL|'P'):
- bsearch = bsearch == 0 ? 1 : 0;
+ if(flags & SR_FORWARD){
+ flags &= ~SR_FORWARD;
+ flags |= SR_BACKWRD;
+ } else {
+ flags &= ~SR_BACKWRD;
+ flags |= SR_FORWARD;
+ }
break;
case (CTRL|'Y'): /* first first cell */
for(tp = gmp->top; tp->prev; tp = tp->prev)
@@ -1673,7 +1679,7 @@ FileBrowse(char *dir, size_t dirlen, char *fn, size_t fnlen,
if(pat && pat[0])
utf8 = ucs4_to_utf8_cpystr(pat);
- if(utf8 && (tp = FindCell(gmp, utf8, bsearch)) != NULL){
+ if(utf8 && (tp = FindCell(gmp, utf8, flags & SR_BACKWRD)) != NULL){
PlaceCell(gmp, gmp->current, &row, &col);
PaintCell(row, col, gmp->cpf, gmp->current, 0);
gmp->current = tp;
diff --git a/pico/estruct.h b/pico/estruct.h
index 410dfc02..ff3261c0 100644
--- a/pico/estruct.h
+++ b/pico/estruct.h
@@ -84,6 +84,13 @@
#define CFFLBF 0x0010 /* Last cmd was full buf fill */
#define CFFLPA 0x0020 /* Last cmd was paragraph fill */
+/* Constants for search type */
+#define SR_FORWARD 0x0001 /* search forward */
+#define SR_BACKWRD 0x0010 /* search backward */
+#define SR_BEGLINE 0x0100 /* search pattern at beginning of line */
+#define SR_ENDLINE 0x1000 /* search pattern at end of line */
+
+
/*
* macros to help filter character input
*/
diff --git a/pico/osdep/altedit.c b/pico/osdep/altedit.c
index ff7a6da8..25e49416 100644
--- a/pico/osdep/altedit.c
+++ b/pico/osdep/altedit.c
@@ -60,7 +60,6 @@ int alt_editor_valid(char *, char *, size_t);
int alt_editor_valid_fp(char *);
#endif /* _WINDOWS */
-
/*
* alt_editor - fork off an alternate editor for mail message composition
* if one is configured and passed from pine. If not, only
@@ -549,7 +548,6 @@ pathcat(char *buf, char **path, char *file)
return(TRUE);
}
-
#ifdef SIGCHLD
/*
* child_handler - handle child status change signal
diff --git a/pico/osdep/spell.c b/pico/osdep/spell.c
index 59efe282..e9aaa39f 100644
--- a/pico/osdep/spell.c
+++ b/pico/osdep/spell.c
@@ -285,7 +285,7 @@ movetoword(UCS *w)
olddotp = curwp->w_dotp;
curwp->w_bufp->b_mode |= MDEXACT; /* case sensitive */
- while(forscan(&i, w, 0, NULL, 0, 1) == TRUE){
+ while(forscan(&i, w, SR_FORWARD, NULL, 0, 1) == TRUE){
if(i)
break; /* wrap NOT allowed! */
diff --git a/pico/search.c b/pico/search.c
index 2cb0fc02..f2a5389f 100644
--- a/pico/search.c
+++ b/pico/search.c
@@ -114,7 +114,7 @@ eq(UCS bc, UCS pc)
int
forwsearch(int f, int n)
{
- int status, bsearch;
+ int status, flags;
int wrapt = FALSE, wrapt2 = FALSE;
int repl_mode = FALSE;
UCS defpat[NPAT];
@@ -130,15 +130,15 @@ forwsearch(int f, int n)
FWS_RETURN(0);
defpat[0] = '\0';
- bsearch = 0; /* search forward by default */
+ flags = SR_FORWARD; /* search forward by default */
/* ask the user for the text of a pattern */
while(1){
if (gmode & MDREPLACE)
- status = srpat("Search", defpat, NPAT, repl_mode, bsearch);
+ status = srpat("Search", defpat, NPAT, repl_mode, flags);
else
- status = readpattern("Search", TRUE, bsearch);
+ status = readpattern("Search", TRUE, flags);
switch(status){
case TRUE: /* user typed something */
@@ -166,7 +166,13 @@ forwsearch(int f, int n)
break;
case (CTRL|'P'):
- bsearch = bsearch == 0 ? 1 : 0;
+ if(flags & SR_FORWARD){
+ flags &= ~SR_FORWARD;
+ flags |= SR_BACKWRD;
+ } else {
+ flags &= ~SR_BACKWRD;
+ flags |= SR_FORWARD;
+ }
break;
case (CTRL|'V'):
@@ -179,6 +185,18 @@ forwsearch(int f, int n)
mlerase();
FWS_RETURN(TRUE);
+ case (CTRL|'^'):
+ if(!(flags & (SR_BEGLINE|SR_ENDLINE))){
+ flags |= SR_BEGLINE;
+ } else if (flags & SR_BEGLINE){
+ flags &= ~SR_BEGLINE;
+ flags |= SR_ENDLINE;
+ } else {
+ flags &= ~SR_ENDLINE;
+ flags |= SR_FORWARD;
+ }
+ break;
+
case (CTRL|'T') :
switch(status = readnumpat(_("Search to Line Number : "))){
case -1 :
@@ -269,7 +287,7 @@ forwsearch(int f, int n)
}
}
- reverse_all(defpat, bsearch);
+ reverse_all(defpat, flags & SR_BACKWRD);
/*
* This code is kind of dumb. What I want is successive C-W 's to
@@ -295,7 +313,7 @@ forwsearch(int f, int n)
/* search for the pattern */
while (n-- > 0) {
- if((status = forscan(&wrapt,defpat, bsearch, NULL,0,PTBEG)) == FALSE)
+ if((status = forscan(&wrapt,defpat, flags, NULL,0,PTBEG)) == FALSE)
break;
}
@@ -306,7 +324,7 @@ forwsearch(int f, int n)
x[0] = '\0';
- utf8 = sucs4_to_utf8_cpystr(defpat ? defpat : x, bsearch);
+ utf8 = sucs4_to_utf8_cpystr(defpat ? defpat : x, flags & SR_BACKWRD);
/* TRANSLATORS: reporting the result of a failed search */
eml.s = utf8;
emlwrite(_("\"%s\" not found"), &eml);
@@ -314,7 +332,7 @@ forwsearch(int f, int n)
fs_give((void **) &utf8);
}
else if((gmode & MDREPLACE) && repl_mode == TRUE){
- status = replace_pat(defpat, &wrapt2, bsearch); /* replace pattern */
+ status = replace_pat(defpat, &wrapt2, flags & SR_BACKWRD); /* replace pattern */
if (wrapt == TRUE || wrapt2 == TRUE){
eml.s = (status == ABORT) ? "cancelled but wrapped" : "Wrapped";
emlwrite("Replacement %s", &eml);
@@ -327,7 +345,7 @@ forwsearch(int f, int n)
emlwrite("", NULL);
}
- reverse_all(defpat, bsearch);
+ reverse_all(defpat, flags & SR_BACKWRD);
if(curwp->w_doto == -1){
curwp->w_doto = 0;
curwp->w_flag |= WFMOVE;
@@ -348,10 +366,15 @@ replace_pat(UCS *defpat, int *wrapt, int bsearch)
char utf8tmp[NPMT];
UCS prompt[NPMT];
UCS *promptp;
+ int flags;
- if(bsearch)
+ if(bsearch){
+ flags = SR_BACKWRD;
curwp->w_doto -= ucs4_strlen(defpat) - 1;
- forscan(wrapt, defpat, bsearch, NULL, 0, PTBEG); /* go to word to be replaced */
+ }
+ else flags = SR_FORWARD;
+
+ forscan(wrapt, defpat, flags, NULL, 0, PTBEG); /* go to word to be replaced */
lpat[0] = '\0';
@@ -558,18 +581,23 @@ replace_all(UCS *orig, UCS *repl, int bsearch)
LINE *stop_line = curwp->w_dotp;
int stop_offset = curwp->w_doto;
EML eml;
+ int flags;
/* similar to replace_pat. When we come here, if bsearch is set,
* the cursor is at the end of the match, so we must bring it back
* to the beginning.
*/
if(bsearch){
+ flags = SR_BACKWRD;
curwp->w_doto -= ucs4_strlen(orig) - 1;
curwp->w_flag |= WFMOVE;
}
+ else
+ flags = SR_FORWARD;
+
stop_offset = curwp->w_doto;
while (1)
- if (forscan(&wrapt, orig, bsearch, stop_line, stop_offset, PTBEG)){
+ if (forscan(&wrapt, orig, flags, stop_line, stop_offset, PTBEG)){
curwp->w_flag |= WFMOVE; /* put cursor back */
reverse_all(orig, bsearch); /* undo reverse buffer and pattern */
@@ -653,15 +681,22 @@ replace_all(UCS *orig, UCS *repl, int bsearch)
/* Read a replacement pattern. Modeled after readpattern(). */
int
-srpat(char *utf8prompt, UCS *defpat, size_t defpatlen, int repl_mode, int bsearch)
+srpat(char *utf8prompt, UCS *defpat, size_t defpatlen, int repl_mode, int flags)
{
register int s;
int i = 0;
+ int bsearch;
+ int bol;
+ int eol;
UCS *b;
UCS prompt[NPMT];
UCS *promptp;
EXTRAKEYS menu_pat[9];
+ bsearch = flags & SR_BACKWRD;
+ bol = flags & SR_BEGLINE;
+ eol = flags & SR_ENDLINE;
+
menu_pat[i = 0].name = "^Y";
menu_pat[i].label = N_("FirstLine");
menu_pat[i].key = (CTRL|'Y');
@@ -677,6 +712,11 @@ srpat(char *utf8prompt, UCS *defpat, size_t defpatlen, int repl_mode, int bsearc
menu_pat[i].key = (CTRL|'R');
KS_OSDATASET(&menu_pat[i], KS_NONE);
+ menu_pat[++i].name = "^^";
+ menu_pat[i].label = bol ? N_("End Line") : eol ? N_("Anywhere") : N_("Bgn Line") ;
+ menu_pat[i].key = (CTRL|'^');
+ KS_OSDATASET(&menu_pat[i], KS_NONE);
+
if(!repl_mode){
menu_pat[++i].name = "^T";
menu_pat[i].label = N_("LineNumber");
@@ -720,6 +760,17 @@ srpat(char *utf8prompt, UCS *defpat, size_t defpatlen, int repl_mode, int bsearc
if(b) ucs4_strncat(prompt, b, ucs4_strlen(b));
prompt[NPMT-1] = '\0';
}
+ if(bol){
+ fs_give((void **) &b);
+ b = utf8_to_ucs4_cpystr(N_(" at start of line"));
+ if(b) ucs4_strncat(prompt, b, ucs4_strlen(b));
+ prompt[NPMT-1] = '\0';
+ } else if(eol){
+ fs_give((void **) &b);
+ b = utf8_to_ucs4_cpystr(N_(" at end of line"));
+ if(b) ucs4_strncat(prompt, b, ucs4_strlen(b));
+ prompt[NPMT-1] = '\0';
+ }
if(b) fs_give((void **) &b);
}
@@ -833,15 +884,20 @@ readnumpat(char *utf8prompt)
int
-readpattern(char *utf8prompt, int text_mode, int bsearch)
+readpattern(char *utf8prompt, int text_mode, int flags)
{
register int s;
int i;
+ int bsearch, bol, eol;
UCS *b;
UCS tpat[NPAT+20];
UCS *tpatp;
EXTRAKEYS menu_pat[8];
+ bsearch = flags & SR_BACKWRD;
+ bol = flags & SR_BEGLINE;
+ eol = flags & SR_ENDLINE;
+
menu_pat[i = 0].name = "^Y";
menu_pat[i].label = N_("FirstLine");
menu_pat[i].key = (CTRL|'Y');
@@ -852,7 +908,17 @@ readpattern(char *utf8prompt, int text_mode, int bsearch)
menu_pat[i].key = (CTRL|'V');
KS_OSDATASET(&menu_pat[i], KS_NONE);
+ menu_pat[++i].name = "^^";
+ menu_pat[i].label = bol ? N_("End Line") : eol ? N_("Anywhere") : N_("Bgn Line") ;
+ menu_pat[i].key = (CTRL|'^');
+ KS_OSDATASET(&menu_pat[i], KS_NONE);
+
if(text_mode){
+ menu_pat[++i].name = "^^";
+ menu_pat[i].label = N_("Begn of Line");
+ menu_pat[i].key = (CTRL|'^');
+ KS_OSDATASET(&menu_pat[i], KS_NONE);
+
menu_pat[++i].name = "^T";
menu_pat[i].label = N_("LineNumber");
menu_pat[i].key = (CTRL|'T');
@@ -891,6 +957,17 @@ readpattern(char *utf8prompt, int text_mode, int bsearch)
if(b) ucs4_strncat(tpat, b, ucs4_strlen(b));
tpat[NPAT+20-1] = '\0';
}
+ if(bol){
+ fs_give((void **) &b);
+ b = utf8_to_ucs4_cpystr(N_(" at start of line"));
+ if(b) ucs4_strncat(tpat, b, ucs4_strlen(b));
+ tpat[NPAT+20-1] = '\0';
+ } else if (eol){
+ fs_give((void **) &b);
+ b = utf8_to_ucs4_cpystr(N_(" at end of line"));
+ if(b) ucs4_strncat(tpat, b, ucs4_strlen(b));
+ tpat[NPAT+20-1] = '\0';
+ }
if(b) fs_give((void **) &b);
}
@@ -1010,7 +1087,7 @@ void reverse_ucs4(UCS *s)
int
forscan(int *wrapt, /* boolean indicating search wrapped */
UCS *patrn, /* string to scan for */
- int bsearch, /* search backwards */
+ int flags, /* direction and position */
LINE *limitp, /* stop searching if reached */
int limito, /* stop searching if reached */
int leavep) /* place to leave point
@@ -1028,7 +1105,14 @@ forscan(int *wrapt, /* boolean indicating search wrapped */
UCS *patptr; /* pointer into pattern */
int stopoff; /* offset to stop search */
LINE *stopline; /* line to stop search */
-
+ int ftest; /* position of first character of test */
+ int bsearch;
+ int bol;
+ int eol;
+
+ bsearch = flags & SR_BACKWRD;
+ bol = flags & SR_BEGLINE;
+ eol = flags & SR_ENDLINE;
*wrapt = FALSE;
/* if bsearch is set we return the match at the beginning of the
@@ -1091,8 +1175,20 @@ forscan(int *wrapt, /* boolean indicating search wrapped */
else
c = lgetc(curline, curoff++).c; /* get the char */
+ if(bol)
+ ftest = bsearch == 0 ? 1 : llength(curline) - ucs4_strlen(patrn) + 1;
+ else if (eol)
+ ftest = bsearch == 0 ? llength(curline) - ucs4_strlen(patrn) + 1 : 1;
/* test it against first char in pattern */
- if (eq(c, patrn[0]) != FALSE) { /* if we find it..*/
+ if (eq(c, patrn[0]) != FALSE /* if we find it..*/
+ && ((bol == 0 && eol == 0) /* ...and if it is anywhere */
+ || (bol != 0 /* ...or is at the begin or line */
+ && ((bsearch == 0 && curoff == ftest) /* and search forward and found at beginning of line */
+ || (bsearch != 0 && curoff == ftest))) /* or search backward and found at end of line */
+ || (eol != 0 /* ...or is at the end or line */
+ && ((bsearch == 0 && curoff == ftest) /* and search forward and found at beginning of line */
+ || (bsearch != 0 && curoff == ftest))) /* or search backward and found at end of line */
+ )){
/* setup match pointers */
matchline = curline;
matchoff = curoff;
diff --git a/pith/filter.c b/pith/filter.c
index 69413bf4..70a89f17 100644
--- a/pith/filter.c
+++ b/pith/filter.c
@@ -7743,6 +7743,9 @@ html_element_output(FILTER_S *f, int ch)
html_output(f, ch);
}
+#define ISHEX_DIGIT(X) (isdigit((X)) || \
+ ((X) >= 'a' && (X) <= 'f') || \
+ ((X) >= 'A' && (X) <= 'F'))
/*
* collect html entity and return its UCS value when done.
@@ -7772,6 +7775,9 @@ html_entity_collector(FILTER_S *f, int ch, UCS *ucs, char **alt)
else if((len == 0)
? (isalpha((unsigned char) ch) || ch == '#')
: ((isdigit((unsigned char) ch)
+ || (len == 1 && (unsigned char) ch == 'x')
+ || (len == 1 &&(unsigned char) ch == 'X')
+ || (len > 1 && isxdigit((unsigned char) ch))
|| (isalpha((unsigned char) ch) && buf[0] != '#')))){
buf[len++] = ch;
return(HTML_MOREDATA);
@@ -7779,14 +7785,18 @@ html_entity_collector(FILTER_S *f, int ch, UCS *ucs, char **alt)
else if(ch == ';' || ASCII_ISSPACE((unsigned char) ch)){
buf[len] = '\0'; /* got something! */
if(buf[0] == '#'){
- *ucs = (UCS) strtoul(&buf[1], NULL, 10);
+ if(buf[1] == 'x' || buf[1] == 'X')
+ *ucs = (UCS) strtoul(&buf[2], NULL, 16);
+ else
+ *ucs = (UCS) strtoul(&buf[1], NULL, 10);
+
if(alt){
*alt = NULL;
for(i = 0; i < sizeof(entity_tab)/sizeof(struct html_entities); i++)
- if(entity_tab[i].value == *ucs){
- *alt = entity_tab[i].plain;
+ if(entity_tab[i].value == *ucs){
+ *alt = entity_tab[i].plain;
break;
- }
+ }
}
len = 0;
diff --git a/pith/osdep/pipe.c b/pith/osdep/pipe.c
index 56c4a239..ed9eda0e 100644
--- a/pith/osdep/pipe.c
+++ b/pith/osdep/pipe.c
@@ -741,7 +741,7 @@ process_reap(pid_t pid, int *esp, int flags)
wflags |= WNOHANG;
#endif
- while (((rv = waitpid(pid, &wstatus, wflags)) < 0) && (errno != ECHILD));
+ while (((rv = waitpid(pid, &wstatus, wflags)) < 0) && (errno != ECHILD));
#elif HAVE_WAIT4
diff --git a/pith/pine.hlp b/pith/pine.hlp
index 4b0acfeb..31e20a0a 100644
--- a/pith/pine.hlp
+++ b/pith/pine.hlp
@@ -140,7 +140,7 @@ with help text for the config screen and the composer that didn't have any
reasonable place to be called from.
Dummy change to get revision in pine.hlp
============= h_revision =================
-Alpine Commit 69 2015-02-28 15:59:49
+Alpine Commit 70 2015-03-15 22:39:47
============= h_news =================
<HTML>
<HEAD>
@@ -186,6 +186,22 @@ Additions include:
<LI> When Alpine sends an attachment, it will set the boundary attribute
in lower case, as some SMTP servers, such as those of libero.it
reject messages if the boundary attribute is in uppercase.
+ <LI> SMIME: The ^E command that gives infromation on the certificate
+ is only available for messages that have a signed or encrypted
+ part.
+
+ <LI> SMIME: If a message contains a RFC822 atachment that is
+ signed/decrypted add the ability to view its SMIME information.
+
+ <LI> HTML: Add support for decoding entities in hexadecimal notation.
+ Suggested by Tulip&aacute;nt Gergely.
+
+ <LI> Pico: Add the ability to search for strings in the beginning or end
+ of a line. In the search menu, pressing Ctrl-^ toggles the prompt
+ to search for a string at the beginning of a line. Another press of
+ Ctrl-^ toggles the prompt to search for a string at the end of a
+ line, and pressing Ctrl-^ one more time searches for the string
+ anywhere in the text.
</UL>
<P>
@@ -195,6 +211,11 @@ Bugs that have been addressed include:
a RFC822 attached message. Reported by Holger Trapp and Bj&ouml;rn
Krellner.
+ <LI> Fix vulnerability in regex library. This only affects those who use
+ this library, such as the windows version of Alpine. See
+ <A HREF="http://www.kb.cert.org/vuls/id/695940">http://www.kb.cert.org/vuls/id/695940</A>
+ for more details.
+
<LI> Alpine would not set include and lib paths for OpenSSL if this was
installed in /usr/local/ssl.
diff --git a/pith/smime.c b/pith/smime.c
index 3482e045..99c80c03 100644
--- a/pith/smime.c
+++ b/pith/smime.c
@@ -560,18 +560,17 @@ load_pkey_with_prompt(char *fpath, char *text, char *prompt)
in = text ? BIO_new_mem_buf(text, strlen(text)) : BIO_new_file(fpath, "r");
if(in != NULL){
pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, "");
- BIO_free(in);
if(pkey != NULL) return pkey;
}
if(pith_smime_enter_password)
while(pkey == NULL && rc != 1){
- in = text ? BIO_new_mem_buf(text, strlen(text)) : BIO_new_file(fpath, "r");
if(in != NULL){
do {
rc = (*pith_smime_enter_password)(prompt, (char *)pass, sizeof(pass));
} while (rc!=0 && rc!=1 && rc>0);
+ (void) BIO_reset(in);
pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, (char *)pass);
BIO_free(in);
}
diff --git a/po/Makefile.in b/po/Makefile.in
index 7990eef9..90bc5c3f 100644
--- a/po/Makefile.in
+++ b/po/Makefile.in
@@ -11,7 +11,7 @@
# Origin: gettext-0.16
PACKAGE = alpine
-VERSION = 2.20.2
+VERSION = 2.20.3
PACKAGE_BUGREPORT = chappa@washington.edu
SHELL = /bin/sh
diff --git a/regex/regcomp.c b/regex/regcomp.c
index 0747190a..0d083167 100644
--- a/regex/regcomp.c
+++ b/regex/regcomp.c
@@ -183,6 +183,7 @@ regcomp(regex_t *preg, const char *pattern, int cflags)
register struct parse *p = &pa;
register int i;
register size_t len;
+ register size_t maxlen;
#ifdef REDEBUG
# define GOODFLAGS(f) (f)
#else
@@ -205,7 +206,13 @@ regcomp(regex_t *preg, const char *pattern, int cflags)
(NC-1)*sizeof(cat_t));
if (g == NULL)
return(REG_ESPACE);
+ maxlen = ((size_t)-1 >> 1) / sizeof(sop) * 2 / 3;
+ if (len >= maxlen) {
+ free((char *)g);
+ return(REG_ESPACE);
+ }
p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */
+ assert(p->ssize >= len);
p->strip = (sop *)malloc(p->ssize * sizeof(sop));
p->slen = 0;
if (p->strip == NULL) {