"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "filter.c" between
s-nail-14.9.10.tar.xz and s-nail-14.9.11.tar.xz

About: S-nail is a mail processing system intended to provide the functionality of the POSIX mailx command and offers extensions for line editing, IDNA, MIME, S/MIME, SMTP and POP3 (and IMAP). It is usable as a mail batch language.

filter.c  (s-nail-14.9.10.tar.xz):filter.c  (s-nail-14.9.11.tar.xz)
/*@ S-nail - a mail user agent derived from Berkeley Mail. /*@ S-nail - a mail user agent derived from Berkeley Mail.
*@ Filter objects. *@ Filter objects.
* *
* Copyright (c) 2013 - 2018 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>. * Copyright (c) 2013 - 2018 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
* SPDX-License-Identifier: ISC
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
skipping to change at line 86 skipping to change at line 87
NYD_LEAVE; NYD_LEAVE;
return rv; return rv;
jerr: jerr:
rv = -1; rv = -1;
goto jleave; goto jleave;
} }
static ssize_t static ssize_t
_qf_add_data(struct quoteflt *self, wchar_t wc) _qf_add_data(struct quoteflt *self, wchar_t wc)
{ {
int w, l;
char *save_b; char *save_b;
ui32_t save_l, save_w; ui32_t save_l, save_w;
ssize_t rv = 0; ssize_t rv;
int w, l;
NYD_ENTER; NYD_ENTER;
rv = 0;
save_l = save_w = 0; /* silence cc */ save_l = save_w = 0; /* silence cc */
save_b = NULL; save_b = NULL;
/* <newline> ends state */ /* <newline> ends state */
if (wc == L'\n') if (wc == L'\n') {
w = 0;
goto jflush; goto jflush;
}
if (wc == L'\r') /* TODO CR should be stripped in lower level!! */ if (wc == L'\r') /* TODO CR should be stripped in lower level!! */
goto jleave; goto jleave;
/* Unroll <tab> to spaces */ /* Unroll <tab> to spaces */
if (wc == L'\t') { if (wc == L'\t') {
save_l = self->qf_datw; save_l = self->qf_datw;
save_w = (save_l + n_QUOTE_TAB_SPACES) & ~(n_QUOTE_TAB_SPACES - 1); save_w = (save_l + n_QUOTE_TAB_SPACES) & ~(n_QUOTE_TAB_SPACES - 1);
save_w -= save_l; save_w -= save_l;
while (save_w-- > 0) { while (save_w-- > 0) {
ssize_t j = _qf_add_data(self, L' '); ssize_t j = _qf_add_data(self, L' ');
if (j < 0) { if (j < 0) {
rv = j; rv = j;
break; break;
} }
rv += j; rv += j;
} }
goto jleave; goto jleave;
} }
/* To avoid that the last visual excesses *qfold-max*, which may happen for
* multi-column characters, use w as an indicator for this and move that
* thing to the next line */
w = wcwidth(wc); w = wcwidth(wc);
if (w == -1) { if (w == -1) {
w = 0;
jbad: jbad:
++self->qf_datw; ++self->qf_datw;
self->qf_dat.s[self->qf_dat.l++] = '?'; self->qf_dat.s[self->qf_dat.l++] = '?';
} else if (self->qf_datw > self->qf_qfold_max - w) {
w = -1;
goto jneednl;
} else { } else {
l = wctomb(self->qf_dat.s + self->qf_dat.l, wc); l = wctomb(self->qf_dat.s + self->qf_dat.l, wc);
if (l < 0) if (l < 0)
goto jbad; goto jbad;
self->qf_datw += (ui32_t)w; self->qf_datw += (ui32_t)w;
self->qf_dat.l += (size_t)l; self->qf_dat.l += (size_t)l;
} }
/* TODO The last visual may excess (adjusted!) *qfold-max* if it's a wide;
* TODO place it on the next line, break before */
if (self->qf_datw >= self->qf_qfold_max) { if (self->qf_datw >= self->qf_qfold_max) {
/* If we have seen a nice breakpoint during traversal, shuffle data /* If we have seen a nice breakpoint during traversal, shuffle data
* around a bit so as to restore the trailing part after flushing */ * around a bit so as to restore the trailing part after flushing */
jneednl:
if (self->qf_brkl > 0) { if (self->qf_brkl > 0) {
save_w = self->qf_datw - self->qf_brkw; save_w = self->qf_datw - self->qf_brkw;
save_l = self->qf_dat.l - self->qf_brkl; save_l = self->qf_dat.l - self->qf_brkl;
save_b = self->qf_dat.s + self->qf_brkl + 2; save_b = self->qf_dat.s + self->qf_brkl + 2;
memmove(save_b, save_b - 2, save_l); memmove(save_b, save_b - 2, save_l);
self->qf_dat.l = self->qf_brkl; self->qf_dat.l = self->qf_brkl;
} }
self->qf_dat.s[self->qf_dat.l++] = '\\'; self->qf_dat.s[self->qf_dat.l++] = '\\';
jflush: jflush:
skipping to change at line 158 skipping to change at line 169
if (save_b != NULL) { if (save_b != NULL) {
self->qf_brk_isws = FAL0; self->qf_brk_isws = FAL0;
self->qf_datw += save_w; self->qf_datw += save_w;
self->qf_dat.l = save_l; self->qf_dat.l = save_l;
memmove(self->qf_dat.s, save_b, save_l); memmove(self->qf_dat.s, save_b, save_l);
} }
} else if (self->qf_datw >= self->qf_qfold_min && !self->qf_brk_isws) { } else if (self->qf_datw >= self->qf_qfold_min && !self->qf_brk_isws) {
bool_t isws = (iswspace(wc) != 0); bool_t isws = (iswspace(wc) != 0);
if (isws || !self->qf_brk_isws || self->qf_brkl == 0) { if (isws || !self->qf_brk_isws || self->qf_brkl == 0) {
self->qf_brkl = self->qf_dat.l; if((self->qf_brk_isws = isws) ||
self->qf_brkw = self->qf_datw; self->qf_brkl < self->qf_qfold_maxnws){
self->qf_brk_isws = isws; self->qf_brkl = self->qf_dat.l;
self->qf_brkw = self->qf_datw;
}
} }
} }
/* Did we hold this back to avoid qf_fold_max excess? Then do it now */
if(rv >= 0 && w == -1){
ssize_t j = _qf_add_data(self, wc);
if(j < 0)
rv = j;
else
rv += j;
}
/* If state changed to prefix, perform full reset (note this implies that /* If state changed to prefix, perform full reset (note this implies that
* quoteflt_flush() performs too much work..) */ * quoteflt_flush() performs too much work..) */
if (wc == '\n') { else if (wc == '\n') {
self->qf_state = _QF_PREFIX; self->qf_state = _QF_PREFIX;
self->qf_wscnt = self->qf_datw = 0; self->qf_wscnt = self->qf_datw = 0;
self->qf_currq.l = 0; self->qf_currq.l = 0;
} }
jleave: jleave:
NYD_LEAVE; NYD_LEAVE;
return rv; return rv;
} }
static ssize_t static ssize_t
skipping to change at line 304 skipping to change at line 325
NYD_LEAVE; NYD_LEAVE;
return rv; return rv;
} }
#endif /* HAVE_QUOTE_FOLD */ #endif /* HAVE_QUOTE_FOLD */
FL struct quoteflt * FL struct quoteflt *
quoteflt_dummy(void) /* TODO LEGACY (until filters are plugged when needed) */ quoteflt_dummy(void) /* TODO LEGACY (until filters are plugged when needed) */
{ {
static struct quoteflt qf_i; static struct quoteflt qf_i;
qf_i.qf_bypass = TRU1;
return &qf_i; return &qf_i;
} }
FL void FL void
quoteflt_init(struct quoteflt *self, char const *prefix) quoteflt_init(struct quoteflt *self, char const *prefix, bool_t bypass)
{ {
#ifdef HAVE_QUOTE_FOLD #ifdef HAVE_QUOTE_FOLD
char const *xcp, *cp; char const *xcp, *cp;
#endif #endif
NYD_ENTER; NYD_ENTER;
memset(self, 0, sizeof *self); memset(self, 0, sizeof *self);
if ((self->qf_pfix = prefix) != NULL) if ((self->qf_pfix = prefix) != NULL)
self->qf_pfix_len = (ui32_t)strlen(prefix); self->qf_pfix_len = (ui32_t)strlen(prefix);
self->qf_bypass = bypass;
/* Check whether the user wants the more fancy quoting algorithm */ /* Check whether the user wants the more fancy quoting algorithm */
/* TODO *quote-fold*: n_QUOTE_MAX may excess it! */ /* TODO *quote-fold*: n_QUOTE_MAX may excess it! */
#ifdef HAVE_QUOTE_FOLD #ifdef HAVE_QUOTE_FOLD
if (self->qf_pfix_len > 0 && (cp = ok_vlook(quote_fold)) != NULL) { if (!bypass && (cp = ok_vlook(quote_fold)) != NULL) {
ui32_t qmin, qmax; ui32_t qmax, qmaxnws, qmin;
/* These magic values ensure we don't bail */ /* These magic values ensure we don't bail */
n_idec_ui32_cp(&qmax, cp, 10, &xcp); n_idec_ui32_cp(&qmax, cp, 10, &xcp);
if (qmax < self->qf_pfix_len + 6) if (qmax < self->qf_pfix_len + 6)
qmax = self->qf_pfix_len + 6; qmax = self->qf_pfix_len + 6;
--qmax; /* The newline escape */ qmaxnws = --qmax; /* The newline escape */
if (cp == xcp || *xcp == '\0') if (cp == xcp || *xcp == '\0')
qmin = (qmax >> 1) + (qmax >> 2) + (qmax >> 5); qmin = (qmax >> 1) + (qmax >> 2) + (qmax >> 5);
else { else {
n_idec_ui32_cp(&qmin, &xcp[1], 10, NULL); n_idec_ui32_cp(&qmin, &xcp[1], 10, &xcp);
if (qmin < qmax >> 1) if (qmin < qmax >> 1)
qmin = qmax >> 1; qmin = qmax >> 1;
else if (qmin > qmax - 2) else if (qmin > qmax - 2)
qmin = qmax - 2; qmin = qmax - 2;
if (cp != xcp && *xcp != '\0') {
n_idec_ui32_cp(&qmaxnws, &xcp[1], 10, &xcp);
if (qmaxnws > qmax || qmaxnws < qmin)
qmaxnws = qmax;
}
} }
self->qf_qfold_min = qmin; self->qf_qfold_min = qmin;
self->qf_qfold_max = qmax; self->qf_qfold_max = qmax;
self->qf_qfold_maxnws = qmaxnws;
self->qf_quote_chars = ok_vlook(quote_chars); self->qf_quote_chars = ok_vlook(quote_chars);
/* Add pad for takeover copies, reverse solidus and newline */ /* Add pad for takeover copies, reverse solidus and newline */
self->qf_dat.s = salloc((qmax + 3) * n_mb_cur_max); self->qf_dat.s = n_autorec_alloc((qmax + 3) * n_mb_cur_max);
self->qf_currq.s = salloc((n_QUOTE_MAX + 1) * n_mb_cur_max); self->qf_currq.s = n_autorec_alloc((n_QUOTE_MAX + 1) * n_mb_cur_max);
} }
#endif #endif
NYD_LEAVE; NYD_LEAVE;
} }
FL void FL void
quoteflt_destroy(struct quoteflt *self) /* xxx inline */ quoteflt_destroy(struct quoteflt *self) /* xxx inline */
{ {
NYD_ENTER; NYD_ENTER;
n_UNUSED(self); n_UNUSED(self);
skipping to change at line 389 skipping to change at line 419
ssize_t rv = 0; ssize_t rv = 0;
NYD_ENTER; NYD_ENTER;
self->qf_nl_last = (len > 0 && dat[len - 1] == '\n'); /* TODO HACK */ self->qf_nl_last = (len > 0 && dat[len - 1] == '\n'); /* TODO HACK */
if (len == 0) if (len == 0)
goto jleave; goto jleave;
/* Bypass? TODO Finally, this filter simply should not be used, then /* Bypass? TODO Finally, this filter simply should not be used, then
* (TODO It supercedes prefix_write() or something) */ * (TODO It supercedes prefix_write() or something) */
if (self->qf_pfix_len == 0) { if (self->qf_bypass) {
if (len != fwrite(dat, 1, len, self->qf_os)) if (len != fwrite(dat, 1, len, self->qf_os))
goto jerr; goto jerr;
rv = len; rv = len;
} }
/* Normal: place *indentprefix* at every BOL */ /* Normal: place *indentprefix* at every BOL */
else else
#ifdef HAVE_QUOTE_FOLD #ifdef HAVE_QUOTE_FOLD
if (self->qf_qfold_max == 0) if (self->qf_qfold_max == 0)
#endif #endif
{ {
void *vp; void *vp;
size_t ll; size_t ll;
bool_t pxok = (self->qf_qfold_min != 0); bool_t pxok = (self->qf_qfold_min != 0);
for (;;) { for (;;) {
if (!pxok) { if (!pxok && (ll = self->qf_pfix_len) > 0) {
ll = self->qf_pfix_len;
if (ll != fwrite(self->qf_pfix, 1, ll, self->qf_os)) if (ll != fwrite(self->qf_pfix, 1, ll, self->qf_os))
goto jerr; goto jerr;
rv += ll; rv += ll;
pxok = TRU1; pxok = TRU1;
} }
/* xxx Strictly speaking this is invalid, because only `/' and `.' are /* xxx Strictly speaking this is invalid, because only `/' and `.' are
* xxx mandated by POSIX.1-2008 as "invariant across all locales * xxx mandated by POSIX.1-2008 as "invariant across all locales
* xxx supported"; though there is no charset known which uses this * xxx supported"; though there is no charset known which uses this
* xxx control char as part of a multibyte character; note that S-nail * xxx control char as part of a multibyte character; note that S-nail
skipping to change at line 739 skipping to change at line 768
/* Then dump it */ /* Then dump it */
while ((hhp = self->hf_hrefs) != NULL) { while ((hhp = self->hf_hrefs) != NULL) {
self->hf_hrefs = hhp->hfh_next; self->hf_hrefs = hhp->hfh_next;
if (!(self->hf_flags & _HF_ERROR)) { if (!(self->hf_flags & _HF_ERROR)) {
int w = fprintf(self->hf_os, " [%u] %.*s\n", int w = fprintf(self->hf_os, " [%u] %.*s\n",
hhp->hfh_no, (int)hhp->hfh_len, hhp->hfh_dat); hhp->hfh_no, (int)hhp->hfh_len, hhp->hfh_dat);
if (w < 0) if (w < 0)
self->hf_flags |= _HF_ERROR; self->hf_flags |= _HF_ERROR;
} }
free(hhp); n_free(hhp);
} }
self->hf_flags |= (putc('\n', self->hf_os) == EOF) self->hf_flags |= (putc('\n', self->hf_os) == EOF)
? _HF_ERROR : _HF_NL_1 | _HF_NL_2; ? _HF_ERROR : _HF_NL_1 | _HF_NL_2;
self->hf_href_dist = (ui32_t)n_realscreenheight >> 1; self->hf_href_dist = (ui32_t)n_realscreenheight >> 1;
jleave: jleave:
NYD2_LEAVE; NYD2_LEAVE;
return self; return self;
} }
skipping to change at line 1322 skipping to change at line 1351
else else
jimg_put: jimg_put:
self = _hf_putbuf(self, param.s, param.l); self = _hf_putbuf(self, param.s, param.l);
self = _hf_putc(self, ']'); self = _hf_putc(self, ']');
break; break;
case _HFSA_HREF: case _HFSA_HREF:
self = _hf_param(self, &param, "href"); self = _hf_param(self, &param, "href");
/* Ignore non-external links */ /* Ignore non-external links */
if (param.s != NULL && *param.s != '#') { if (param.s != NULL && *param.s != '#') {
struct htmlflt_href *hhp = smalloc( struct htmlflt_href *hhp = n_alloc(
n_VSTRUCT_SIZEOF(struct htmlflt_href, hfh_dat) + param.l +1); n_VSTRUCT_SIZEOF(struct htmlflt_href, hfh_dat) + param.l +1);
hhp->hfh_next = self->hf_hrefs; hhp->hfh_next = self->hf_hrefs;
hhp->hfh_no = ++self->hf_href_no; hhp->hfh_no = ++self->hf_href_no;
hhp->hfh_len = (ui32_t)param.l; hhp->hfh_len = (ui32_t)param.l;
memcpy(hhp->hfh_dat, param.s, param.l); memcpy(hhp->hfh_dat, param.s, param.l);
snprintf(nobuf, sizeof nobuf, "[%u]", hhp->hfh_no); snprintf(nobuf, sizeof nobuf, "[%u]", hhp->hfh_no);
self->hf_flags = (f |= _HF_HREF); self->hf_flags = (f |= _HF_HREF);
self->hf_hrefs = hhp; self->hf_hrefs = hhp;
skipping to change at line 1470 skipping to change at line 1499
self = _hf_dump_hrefs(self); self = _hf_dump_hrefs(self);
rv = 1; rv = 1;
} }
goto jleave; goto jleave;
} }
/* Always ensure some initial buffer */ /* Always ensure some initial buffer */
if ((cp = self->hf_curr) != NULL) if ((cp = self->hf_curr) != NULL)
cp_max = self->hf_bmax; cp_max = self->hf_bmax;
else { else {
cp = self->hf_curr = self->hf_bdat = smalloc(LINESIZE); cp = self->hf_curr = self->hf_bdat = n_alloc(LINESIZE);
cp_max = self->hf_bmax = cp + LINESIZE -1; /* (Always room for NUL!) */ cp_max = self->hf_bmax = cp + LINESIZE -1; /* (Always room for NUL!) */
} }
hot = (cp != self->hf_bdat); hot = (cp != self->hf_bdat);
for (rv = (ssize_t)len; len > 0; --len) { for (rv = (ssize_t)len; len > 0; --len) {
ui32_t f = self->hf_flags; ui32_t f = self->hf_flags;
if (f & _HF_ERROR) if (f & _HF_ERROR)
break; break;
c = *dat++; c = *dat++;
skipping to change at line 1593 skipping to change at line 1622
f &= ~(_HF_NOPUT | _HF_ENT); f &= ~(_HF_NOPUT | _HF_ENT);
self->hf_flags = f; self->hf_flags = f;
self = _hf_check_ent(self, self->hf_bdat, self = _hf_check_ent(self, self->hf_bdat,
PTR2SIZE(cp + 1 - self->hf_bdat)); PTR2SIZE(cp + 1 - self->hf_bdat));
} else { } else {
/* We may need to grow the buffer */ /* We may need to grow the buffer */
if (PTRCMP(cp + 42/2, >=, cp_max)) { if (PTRCMP(cp + 42/2, >=, cp_max)) {
size_t i = PTR2SIZE(cp - self->hf_bdat), size_t i = PTR2SIZE(cp - self->hf_bdat),
m = PTR2SIZE(self->hf_bmax - self->hf_bdat) + LINESIZE; m = PTR2SIZE(self->hf_bmax - self->hf_bdat) + LINESIZE;
cp = self->hf_bdat = srealloc(self->hf_bdat, m); cp = self->hf_bdat = n_realloc(self->hf_bdat, m);
self->hf_bmax = cp + m -1; self->hf_bmax = cp_max = &cp[m -1];
self->hf_curr = (cp += i); self->hf_curr = (cp += i);
} }
*cp++ = c; *cp++ = c;
} }
} }
} }
self->hf_curr = cp; self->hf_curr = cp;
jleave: jleave:
NYD_LEAVE; NYD_LEAVE;
return (self->hf_flags & _HF_ERROR) ? -1 : rv; return (self->hf_flags & _HF_ERROR) ? -1 : rv;
skipping to change at line 1684 skipping to change at line 1713
} }
FL void FL void
htmlflt_reset(struct htmlflt *self, FILE *f) htmlflt_reset(struct htmlflt *self, FILE *f)
{ {
struct htmlflt_href *hfhp; struct htmlflt_href *hfhp;
NYD_ENTER; NYD_ENTER;
while ((hfhp = self->hf_hrefs) != NULL) { while ((hfhp = self->hf_hrefs) != NULL) {
self->hf_hrefs = hfhp->hfh_next; self->hf_hrefs = hfhp->hfh_next;
free(hfhp); n_free(hfhp);
} }
if (self->hf_bdat != NULL) if (self->hf_bdat != NULL)
free(self->hf_bdat); n_free(self->hf_bdat);
if (self->hf_line != NULL) if (self->hf_line != NULL)
free(self->hf_line); n_free(self->hf_line);
memset(self, 0, sizeof *self); memset(self, 0, sizeof *self);
if (f != NULL) { if (f != NULL) {
ui32_t sw = n_MAX(_HF_MINLEN, (ui32_t)n_scrnwidth); ui32_t sw = n_MAX(_HF_MINLEN, (ui32_t)n_scrnwidth);
self->hf_line = smalloc((size_t)sw * n_mb_cur_max +1); self->hf_line = n_alloc((size_t)sw * n_mb_cur_max +1);
self->hf_lmax = sw; self->hf_lmax = sw;
if (n_psonce & n_PSO_UNICODE) /* TODO not truly generic */ if (n_psonce & n_PSO_UNICODE) /* TODO not truly generic */
self->hf_flags = _HF_UTF8; self->hf_flags = _HF_UTF8;
self->hf_os = f; self->hf_os = f;
} }
NYD_LEAVE; NYD_LEAVE;
} }
FL ssize_t FL ssize_t
 End of changes. 34 change blocks. 
28 lines changed or deleted 57 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)