diff options
author | Eduardo Chappa <chappa@washington.edu> | 2013-05-31 17:08:22 -0600 |
---|---|---|
committer | Eduardo Chappa <chappa@washington.edu> | 2013-05-31 17:08:22 -0600 |
commit | 81e994d7907f850506ddc248f84761a54995e58c (patch) | |
tree | 3bc4993b48ddeec45dee51323437200ab975887c /pico/word.c | |
parent | 077522d7e058133f9de99d0d74481566b21c5a98 (diff) | |
download | alpine-81e994d7907f850506ddc248f84761a54995e58c.tar.xz |
* Fix not allow remote execution by adding PIPE_NOSHELL to the opening of a url by
a browser.
Diffstat (limited to 'pico/word.c')
-rw-r--r-- | pico/word.c | 334 |
1 files changed, 268 insertions, 66 deletions
diff --git a/pico/word.c b/pico/word.c index 145fc1d1..62fa84ea 100644 --- a/pico/word.c +++ b/pico/word.c @@ -25,10 +25,10 @@ static char rcsid[] = "$Id: word.c 769 2007-10-24 00:15:40Z hubert@u.washington. */ #include "headers.h" - +#include "../pith/osdep/color.h" int fpnewline(UCS *quote); -int fillregion(UCS *qstr, REGION *addedregion); +int fillregion(UCS *qstr, UCS *istr, REGION *addedregion); int setquotelevelinregion(int quotelevel, REGION *addedregion); int is_user_separator(UCS c); @@ -431,42 +431,156 @@ is_user_separator(UCS c) return 0; } +/* Support of indentation of paragraphs */ +#define is_indent_char(c) (((c) == '.' || (c) == '}' || (c) == RPAREN || \ + (c) == '*' || (c) == '+' || is_a_digit(c) || \ + ISspace(c) || (c) == '-' || \ + (c) == ']') ? 1 : 0) +#define allowed_after_digit(c,word,k) ((((c) == '.' && \ + allowed_after_period(next((word),(k)))) ||\ + (c) == RPAREN || (c) == '}' || (c) == ']' ||\ + ISspace(c) || is_a_digit(c) || \ + ((c) == '-' ) && \ + allowed_after_dash(next((word),(k)))) \ + ? 1 : 0) +#define allowed_after_period(c) (((c) == RPAREN || (c) == '}' || (c) == ']' ||\ + ISspace(c) || (c) == '-' || \ + is_a_digit(c)) ? 1 : 0) +#define allowed_after_parenth(c) (ISspace(c) ? 1 : 0) +#define allowed_after_space(c) (ISspace(c) ? 1 : 0) +#define allowed_after_braces(c) (ISspace(c) ? 1 : 0) +#define allowed_after_star(c) ((ISspace(c) || (c) == RPAREN ||\ + (c) == ']' || (c) == '}') ? 1 : 0) +#define allowed_after_dash(c) ((ISspace(c) || is_a_digit(c)) ? 1 : 0) +#define EOLchar(c) (((c) == '.' || (c) == ':' || (c) == '?' ||\ + (c) == '!') ? 1 : 0) + +int indent_match(char **, LINE *, char *, int, int); + +/* Extended justification support */ +#define is_cquote(c) ((c) == '>' || (c) == '|' || (c) == ']' || (c) == ':') +#define is_cword(c) ((((c) >= 'a') && ((c) <= 'z')) || \ + (((c) >= 'A') && ((c) <= 'Z')) || \ + (((c) >= '0') && ((c) <= '9')) || \ + ((c) == ' ') || ((c) == '?') || \ + ((c) == '@') || ((c) == '.') || \ + ((c) == '!') || ((c) == '\'') || \ + ((c) == ',') || ((c) == '\"') ? 1 : 0) +#define isaquote(c) ((c) == '\"' || (c) == '\'') +#define is8bit(c) ((((int) (c)) & 0x80) ? 1 : 0) +#define iscontrol(c) (iscntrl(((int) (c)) & 0x7f) ? 1 : 0) +#define forbidden(c) (((c) == '\"') || ((c) == '\'') || ((c) == '$') ||\ + ((c) == ',') || ((c) == '.') || ((c) == '-') ||\ + ((c) == LPAREN) || ((c) == '/')|| ((c) == '`') ||\ + ((c) == '{') || ((c) == '\\') || (iscontrol((c))) ||\ + (((c) >= '0') && ((c) <= '9')) || ((c) == '?')) +#define is_cletter(c) ((((c) >= 'a') && ((c) <= 'z'))) ||\ + ((((c) >= 'A') && ((c) <= 'Z'))||\ + 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)) +#define before(word,i) (((i) > 0) ? (word)[(i) - 1] : 0) +#define next(w,i) ((((w)[(i)]) != 0) ? ((w)[(i) + 1]) : 0) +#define now(w,i) ((w)[(i)]) +#define is_qsword(c) (((c) == ':') || ((c) == RPAREN) ? 1 : 0) +#define is_colon(c) (((c) == ':') ? 1 : 0) +#define is_rarrow(c) (((c) == '>') ? 1 : 0) +#define is_tilde(c) (((c) == '~') ? 1 : 0) +#define is_dash(c) (((c) == '-') ? 1 : 0) +#define is_pound(c) (((c) == '#') ? 1 : 0) +#define is_a_digit(c) ((((c) >= '0') && ((c) <= '9')) ? 1 : 0) +#define is_allowed(c) (is_cquote(c) || is_cword(c) || is_dash(c) || \ + is_pound(c)) +#define qs_allowed(a) (((a)->qstype != qsGdb) && ((a)->qstype != qsProg)) + +/* Internal justification functions */ +QSTRING_S *qs_quote_match(char **, LINE *, char *, int); +int ucs4_strlenis(UCS *); +void linencpy(char *, LINE *, int); + +void +linencpy(word, l, buflen) + char word[NSTRING]; + LINE *l; + int buflen; +{ + int i; + UCS ucs_word[NSTRING]; + char *utf_word; + + word[0] = '\0'; + if(l){ + for (i = 0; i < buflen && i < llength(l) + && (ucs_word[i] = lgetc(l,i).c); i++); + ucs_word[i == buflen ? i-1 : i] = '\0'; + utf_word = ucs4_to_utf8_cpystr(ucs_word); + strncpy(word, utf_word, (NSTRING < buflen ? NSTRING : buflen)); + word[NSTRING-1] = '\0'; + if(utf_word) fs_give((void **)&utf_word); + } +} + + /* + * This function returns the quote string as a structure. In this way we + * have two ways to get the quote string: as a char * or as a QSTRING_S * + * directly. + */ +QSTRING_S * +qs_quote_match(char **q, LINE *l, char *rqstr, int rqstrlen) +{ + char GLine[NSTRING], NLine[NSTRING], PLine[NSTRING]; + LINE *nl = l != curbp->b_linep ? lforw(l) : NULL; + LINE *pl = lback(l) != curbp->b_linep ? lback(l) : NULL; + int plb = 1; + + linencpy(GLine, l, NSTRING); + linencpy(NLine, nl, NSTRING); + + if (pl){ + linencpy(PLine, pl, NSTRING); + if(lback(pl) != curbp->b_linep){ + char PPLine[NSTRING]; + + linencpy(PPLine, lback(pl), NSTRING); + plb = line_isblank(q, PLine, GLine, PPLine, NSTRING); + } + } + return do_quote_match(q, GLine, NLine, PLine, rqstr, rqstrlen, plb); +} /* * Return number of quotes if whatever starts the line matches the quote string + * rqstr is a pointer to raw qstring; buf points to processed qstring */ int -quote_match(UCS *q, LINE *l, UCS *buf, size_t buflen) +quote_match(char **q, LINE *l, char *buf, size_t buflen, int raw) { - register int i, n, j, qb; - - *buf = '\0'; - if(*q == '\0') - return(1); - - qb = (ucs4_strlen(q) > 1 && q[ucs4_strlen(q)-1] == ' ') ? 1 : 0; - for(n = 0, j = 0; ;){ - for(i = 0; j <= llength(l) && qb ? q[i+1] : q[i]; i++, j++) - if(q[i] != lgetc(l, j).c) - return(n); - - n++; - if((!qb && q[i] == '\0') || (qb && q[i+1] == '\0')){ - if(ucs4_strlen(buf) + ucs4_strlen(q) + 1 < buflen){ - ucs4_strncat(buf, q, buflen-ucs4_strlen(q)-1); - buf[buflen-1] = '\0'; - if(qb && (j > llength(l) || lgetc(l, j).c != ' ')) - buf[ucs4_strlen(buf)-1] = '\0'; - } - } - if(j > llength(l)) - return(n); - else if(qb && lgetc(l, j).c == ' ') - j++; + QSTRING_S *qs; + char rqstr[NSTRING]; + + qs = qs_quote_match(q, l, rqstr, NSTRING); + if(qs) + record_quote_string(qs); + flatten_qstring(qs, buf, buflen); + if (qs) free_qs(&qs); + + if(raw){ + strncpy(buf, rqstr, buflen < NSTRING ? buflen : NSTRING); + buf[buflen-1] = '\0'; } - return(n); /* never reached */ + + return buf && buf[0] ? strlen(buf) : 0; } +int ucs4_strlenis(UCS *ucs_qstr) +{ + char *str = ucs4_to_utf8_cpystr(ucs_qstr); + int i = (int) strlenis(str); + + if(str) fs_give((void **)&str); + return i; +} /* Justify the entire buffer instead of just a paragraph */ int @@ -721,6 +835,7 @@ fillpara(int f, int n) } if(action == 'R' && curwp->w_markp){ + char qstrfl[NSTRING]; /* let yank() know that it may be restoring a paragraph */ thisflag |= CFFILL; @@ -733,21 +848,25 @@ fillpara(int f, int n) /* determine if we're justifying quoted text or not */ qstr = (glo_quote_str - && quote_match(glo_quote_str, - curwp->w_doto > 0 ? curwp->w_dotp->l_fp : curwp->w_dotp, - qstr2, NSTRING) - && *qstr2) ? qstr2 : NULL; - + && quote_match(default_qstr(glo_quote_str, 1), + (curwp->w_doto > 0 ? curwp->w_dotp->l_fp : curwp->w_dotp), + qstrfl, NSTRING, 0) + && *qstrfl) ? utf8_to_ucs4_cpystr(qstrfl) : NULL; /* * Fillregion moves dot to the end of the filled region. */ - if(!fillregion(qstr, &addedregion)) + if(!fillregion(qstr, NULL, &addedregion)) return(FALSE); set_last_region_added(&addedregion); + + if(qstr) + fs_give((void **)&qstr); } else if(action == 'P'){ + char ind_str[NSTRING], qstrfl[NSTRING]; + UCS *istr; /* * Justfiy the current paragraph. @@ -759,17 +878,16 @@ fillpara(int f, int n) if(gotoeop(FALSE, 1) == FALSE) return(FALSE); - /* determine if we're justifying quoted text or not */ - qstr = (glo_quote_str - && quote_match(glo_quote_str, - curwp->w_dotp, qstr2, NSTRING) - && *qstr2) ? qstr2 : NULL; - setmark(0,0); /* mark last line of para */ /* jump back to the beginning of the paragraph */ gotobop(FALSE, 1); + istr = indent_match(default_qstr(glo_quote_str, 1), curwp->w_dotp, ind_str, NSTRING, 0) + && *ind_str ? utf8_to_ucs4_cpystr(ind_str) : NULL; + qstr = (quote_match(default_qstr(glo_quote_str, 1), curwp->w_dotp, qstrfl, NSTRING, 0) + && *qstrfl) ? utf8_to_ucs4_cpystr(qstrfl) : NULL; + /* let yank() know that it may be restoring a paragraph */ thisflag |= (CFFILL | CFFLPA); @@ -783,9 +901,15 @@ fillpara(int f, int n) /* * Fillregion moves dot to the end of the filled region. */ - if(!fillregion(qstr, &addedregion)) + if(!fillregion(qstr, istr, &addedregion)) return(FALSE); + if(qstr) + fs_give((void **)&qstr); + + if(istr) + fs_give((void **)&istr); + set_last_region_added(&addedregion); /* Leave cursor on first char of first line after justified region */ @@ -827,16 +951,16 @@ fillpara(int f, int n) * can delete it and restore the saved part. */ int -fillregion(UCS *qstr, REGION *addedregion) +fillregion(UCS *qstr, UCS *istr, REGION *addedregion) { long c, sz, last_char = 0; - int i, j, qlen, same_word, + int i, j, qlen, same_word, qi, pqi, qlenis, spaces, word_len, word_ind, line_len, ww; int starts_midline = 0; int ends_midline = 0; int offset_into_start; LINE *line_before_start, *lp; - UCS line_last, word[NSTRING]; + UCS line_last, word[NSTRING], quoid[NSTRING], qstr2[NSTRING]; REGION region; /* if region starts midline insert a newline */ @@ -847,6 +971,35 @@ fillregion(UCS *qstr, REGION *addedregion) if(curwp->w_marko > 0 && curwp->w_marko < llength(curwp->w_markp)) ends_midline++; + for (i = 0; (i < NSTRING) && qstr && (quoid[i] = qstr[i]); i++); + for (j = 0; ((i + j) < NSTRING) && istr && (quoid[i] = istr[j]); i++,j++); + quoid[i] = '\0'; + qi = ucs4_strlen(quoid); + if (istr) /* strip trailing spaces */ + for (;ISspace(quoid[qi - 1]); qi--); + quoid[qi] = '\0'; /* we have closed quoid at "X" in the first line */ + + if (ucs4_strlenis(quoid) > fillcol) + return FALSE; /* Too wide, we can't justify this! */ + + if (qstr && istr){ + for (i = ucs4_strlen(qstr) - 1; ISspace(qstr[i]); i--); + qstr[i + 1] = '\0'; /* qstrfl */ + } + qlen = ucs4_strlen(qstr); /* qstrfl*/ + qlenis = ucs4_strlenis(qstr); + + for(i = 0, qstr2[0] = '\0'; qstr && qstr[i] && (qstr2[i] = qstr[i]); i++); + + if (istr && ((j = ucs4_strlenis(quoid) - ucs4_strlenis(qstr)) > 0)){ + pqi = ucs4_strlen(qstr); + for (i = 0; (i < j) && (qstr2[pqi + i] = ' '); i++); + if (ISspace(istr[ucs4_strlen(istr) - 1])) + qstr2[pqi + i++] = ' '; + qstr2[pqi + i] = '\0'; + qstr = qstr2; + } + /* cut the paragraph into our fill buffer */ fdelete(); if(!getregion(®ion, curwp->w_markp, curwp->w_marko)) @@ -863,28 +1016,36 @@ fillregion(UCS *qstr, REGION *addedregion) /* Now insert it back wrapped */ spaces = word_len = word_ind = line_len = same_word = 0; - qlen = qstr ? ucs4_strlen(qstr) : 0; /* Beginning with leading quoting... */ - if(qstr){ - i = 0; - while(qstr[i]){ - ww = wcellwidth(qstr[i]); - line_len += (ww >= 0 ? ww : 1); - linsert(1, qstr[i++]); - } + if(qstr || istr){ + for(i = 0; quoid[i] != '\0' ; i++) + linsert(1, quoid[i]); line_last = ' '; /* no word-flush space! */ + line_len = ucs4_strlenis(quoid); /* we demand a recount! */ } /* remove first leading quotes if any */ if(starts_midline) i = 0; - else - for(i = qlen; (c = fremove(i)) == ' ' || c == TAB; i++){ + else{ + if(qstr || istr){ + for (i = 0; (c = fremove(i)) != '\0'; i++){ + word[i] = c; + word[i+1] = '\0'; + if(ucs4_strlenis(word) >= ucs4_strlenis(quoid)) + break; + } + i++; + } + else + i = 0; + for(; ISspace(c = fremove(i)); i++){ linsert(1, line_last = (UCS) c); line_len += ((c == TAB) ? (~line_len & 0x07) + 1 : 1); } + } /* then digest the rest... */ while((c = fremove(i++)) >= 0){ @@ -905,21 +1066,22 @@ fillregion(UCS *qstr, REGION *addedregion) case TAB : case ' ' : + case NBSP: spaces++; break; default : if(spaces){ /* flush word? */ - if((line_len - qlen > 0) + if((line_len - qlenis > 0) && line_len + word_len + 1 > fillcol - && ((ucs4_isspace(line_last)) + && ((ISspace(line_last)) || (linsert(1, ' '))) && same_word == 0 && (line_len = fpnewline(qstr))) line_last = ' '; /* no word-flush space! */ if(word_len){ /* word to write? */ - if(line_len && !ucs4_isspace(line_last)){ + if(line_len && !ISspace(line_last)){ linsert(1, ' '); /* need padding? */ line_len++; } @@ -941,8 +1103,8 @@ fillregion(UCS *qstr, REGION *addedregion) if(word_ind + 1 >= NSTRING){ /* Magic! Fake that we output a wrapped word */ - if((line_len - qlen > 0) && same_word == 0){ - if(!ucs4_isspace(line_last)) + if((line_len - qlenis > 0) && same_word == 0){ + if(!ISspace(line_last)) linsert(1, ' '); line_len = fpnewline(qstr); } @@ -964,12 +1126,12 @@ fillregion(UCS *qstr, REGION *addedregion) } if(word_len){ - if((line_len - qlen > 0) && (line_len + word_len + 1 > fillcol) && same_word == 0){ - if(!ucs4_isspace(line_last)) + if((line_len - qlenis > 0) && (line_len + word_len + 1 > fillcol) && same_word == 0){ + if(!ISspace(line_last)) linsert(1, ' '); (void) fpnewline(qstr); } - else if(line_len && !ucs4_isspace(line_last)) + else if(line_len && !ISspace(line_last)) linsert(1, ' '); for(j = 0; j < word_ind; j++) @@ -1027,11 +1189,11 @@ fpnewline(UCS *quote) int len; lnewline(); - for(len = 0; quote && *quote; quote++){ + for(len = ucs4_strlenis(quote); quote && *quote; quote++){ int ww; - ww = wcellwidth(*quote); - len += (ww >= 0 ? ww : 1); +/* ww = wcellwidth(*quote); + len += (ww >= 0 ? ww : 1);*/ linsert(1, *quote); } @@ -1175,5 +1337,45 @@ setquotelevelinregion(int quotelevel, REGION *addedregion) markregion(1); } + /* + * This puts us at the end of the quoted region instead + * of on the following line. This makes it convenient + * for the user to follow a quotelevel adjustment with + * a Justify if desired. + */ + if(backuptoprevline){ + curwp->w_doto = 0; + backchar(0, 1); + } + + if(ends_midline){ /* doesn't need fixing otherwise */ + unmarkbuffer(); + markregion(1); + } + return (TRUE); } + +/* + * If there is an indent string this function returns + * its length + */ +int +indent_match(char **q, LINE *l, char *buf, int buflen, int raw) +{ + char GLine[NSTRING]; + int i, k, plb; + + k = quote_match(q,l, buf, buflen, raw); + linencpy(GLine, l, NSTRING); + plb = (lback(l) != curbp->b_linep) ? lisblank(lback(l)) : 1; + if (!plb){ + i = llength(lback(l)) - 1; + for (; i >= 0 && ISspace(lgetc(lback(l), i).c); i--); + if (EOLchar(lgetc(lback(l), i).c)) + plb++; + } + + return get_indent_raw_line(q, GLine, buf, buflen, k, plb); +} + |