X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/2e768e3cc0ce768373d3320eca4cdd08b8cf646a..9b706433f:/sbr/fmt_scan.c?ds=sidebyside diff --git a/sbr/fmt_scan.c b/sbr/fmt_scan.c index dad7a3c6..e4d79d57 100644 --- a/sbr/fmt_scan.c +++ b/sbr/fmt_scan.c @@ -25,7 +25,6 @@ # include #endif -extern int fmt_norm; /* defined in sbr/fmt_def.c = AD_NAME */ struct mailname fmt_mnull = { NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, NULL, NULL }; @@ -48,7 +47,6 @@ match (char *str, char *sub) int c1, c2; char *s1, *s2; -#ifdef LOCALE while ((c1 = *sub)) { c1 = (isascii((unsigned char) c1) && isalpha((unsigned char) c1) && isupper((unsigned char) c1)) ? tolower((unsigned char) c1) : c1; @@ -72,19 +70,6 @@ match (char *str, char *sub) if (! c1) return 1; } -#else - while ((c1 = *sub)) { - while ((c2 = *str++) && (c1 | 040) != (c2 | 040)) - ; - if (! c2) - return 0; - s1 = sub + 1; s2 = str; - while ((c1 = *s1++) && (c1 | 040) == (*s2++ | 040)) - ; - if (! c1) - return 1; - } -#endif return 1; } @@ -134,6 +119,7 @@ cptrimmed(char **dest, char **ep, char *str, unsigned int wid, char fill, int char_len; /* bytes in current character */ int w; wchar_t wide_char; + char *altstr = NULL; #endif char *sp; /* current position in source string */ char *cp = *dest; /* current position in destination string */ @@ -154,6 +140,17 @@ cptrimmed(char **dest, char **ep, char *str, unsigned int wid, char fill, #ifdef MULTIBYTE_SUPPORT char_len = mbtowc(&wide_char, sp, end); + /* + * See the relevant comments in cpstripped() to explain what's + * going on here; we want to handle the case where we get + * characters that mbtowc() cannot handle + */ + + if (char_len < 0) { + altstr = "?"; + char_len = mbtowc(&wide_char, altstr, 1); + } + if (char_len <= 0) break; @@ -164,11 +161,11 @@ cptrimmed(char **dest, char **ep, char *str, unsigned int wid, char fill, * widths, so use the column width to bump the end pointer when * appropriate. */ - if (char_len > 1 && epmax - *ep >= char_len - w) { + if (w >= 0 && char_len > 1 && epmax - *ep >= char_len - w) { *ep += char_len - w; } - if (cp + w > *ep) + if (w >= 0 && cp + w > *ep) break; end -= char_len; @@ -196,9 +193,10 @@ cptrimmed(char **dest, char **ep, char *str, unsigned int wid, char fill, #ifdef MULTIBYTE_SUPPORT if (w >= 0 && remaining >= w) { - strncpy(cp, sp, char_len); + strncpy(cp, altstr ? altstr : sp, char_len); cp += char_len; remaining -= w; + altstr = NULL; } sp += char_len; #else @@ -239,6 +237,7 @@ cpstripped (char **dest, char **end, char *max, char *str) #ifdef MULTIBYTE_SUPPORT int char_len, w; wchar_t wide_char; + char *altstr = NULL; #endif /* MULTIBYTE_SUPPORT */ if (!str) @@ -265,10 +264,23 @@ cpstripped (char **dest, char **end, char *max, char *str) * by the number of "extra" bytes in this character. That's the * character length (char_len) minus the column width (w). */ - if (char_len > 1 && max - *end >= char_len - w) { + if (w >= 0 && char_len > 1 && max - *end >= char_len - w) { *end += char_len - w; } + /* + * If mbrtowc() failed, then we have a character that isn't valid + * in the current encoding. Replace it with a '?'. We do that by + * setting the alstr variable to the value of the replacement string; + * altstr is used below when the bytes are copied into the output + * buffer. + */ + + if (char_len < 0) { + altstr = "?"; + char_len = mbtowc(&wide_char, altstr, 1); + } + if (char_len <= 0 || *dest + char_len > *end) break; @@ -293,9 +305,10 @@ cpstripped (char **dest, char **end, char *max, char *str) prevCtrl = 0; #ifdef MULTIBYTE_SUPPORT - memcpy(*dest, str, char_len); + memcpy(*dest, altstr ? altstr : str, char_len); str += char_len; *dest += char_len; + altstr = NULL; #else /* MULTIBYE_SUPPORT */ *(*dest)++ = *str++ #endif /* MULTIBYTE_SUPPORT */ @@ -440,29 +453,31 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat, scanl + max - 1); break; case FT_STRLIT: - sp = str; - while ((c = *sp++) && cp < ep) - *cp++ = c; + if (str) { + sp = str; + while ((c = *sp++) && cp < ep) + *cp++ = c; + } break; - case FT_STRLITZ: { - size_t len = strlen (str); - - /* Don't want to emit part of an escape sequence. So if - there isn't enough room in the buffer for the entire - string, skip it completely. */ - if (cp - scanl + len + 1 < max) { - for (sp = str; *sp; *cp++ = *sp++) continue; - - /* This string doesn't count against the width. So - increase ep the same amount as cp, only if the - scan buffer will always be large enough. */ - if (ep - scanl + len + 1 < max) { - ep += len; + case FT_STRLITZ: + if (str) { + size_t len = strlen (str); + + /* Don't want to emit part of an escape sequence. So if + there isn't enough room in the buffer for the entire + string, skip it completely. */ + if (cp - scanl + len + 1 < max) { + for (sp = str; *sp; *cp++ = *sp++) continue; + + /* This string doesn't count against the width. + So increase ep the same amount as cp, only if the + scan buffer will always be large enough. */ + if (ep - scanl + len + 1 < max) { + ep += len; + } } } - break; - } case FT_STRFW: adios (NULL, "internal error (FT_STRFW)"); @@ -491,6 +506,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat, case FT_IF_S: if (!(value = (str && *str))) { + if (callbacks && callbacks->trace_func) + callbacks->trace_func(callbacks->trace_context, fmt, value, + str, scanl); fmt += fmt->f_skip; continue; } @@ -498,6 +516,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat, case FT_IF_S_NULL: if (!(value = (str == NULL || *str == 0))) { + if (callbacks && callbacks->trace_func) + callbacks->trace_func(callbacks->trace_context, fmt, value, + str, scanl); fmt += fmt->f_skip; continue; } @@ -505,6 +526,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat, case FT_IF_V_EQ: if (value != fmt->f_value) { + if (callbacks && callbacks->trace_func) + callbacks->trace_func(callbacks->trace_context, fmt, value, + str, scanl); fmt += fmt->f_skip; continue; } @@ -512,6 +536,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat, case FT_IF_V_NE: if (value == fmt->f_value) { + if (callbacks && callbacks->trace_func) + callbacks->trace_func(callbacks->trace_context, fmt, value, + str, scanl); fmt += fmt->f_skip; continue; } @@ -519,6 +546,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat, case FT_IF_V_GT: if (value <= fmt->f_value) { + if (callbacks && callbacks->trace_func) + callbacks->trace_func(callbacks->trace_context, fmt, value, + str, scanl); fmt += fmt->f_skip; continue; } @@ -526,6 +556,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat, case FT_IF_MATCH: if (!(value = (str && match (str, fmt->f_text)))) { + if (callbacks && callbacks->trace_func) + callbacks->trace_func(callbacks->trace_context, fmt, value, + str, scanl); fmt += fmt->f_skip; continue; } @@ -540,6 +573,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat, case FT_IF_AMATCH: if (!(value = (str && uprf (str, fmt->f_text)))) { + if (callbacks && callbacks->trace_func) + callbacks->trace_func(callbacks->trace_context, fmt, value, + str, scanl); fmt += fmt->f_skip; continue; } @@ -570,6 +606,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat, break; case FT_GOTO: + if (callbacks && callbacks->trace_func) + callbacks->trace_func(callbacks->trace_context, fmt, value, + str, scanl); fmt += fmt->f_skip; continue; @@ -840,32 +879,10 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat, /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */ case FT_LS_UNQUOTE: if (str) { - int m; strncpy(buffer, str, sizeof(buffer)); /* strncpy doesn't NUL-terminate if it fills the buffer */ buffer[sizeof(buffer)-1] = '\0'; - str = buffer; - - /* we will parse from buffer to buffer2 */ - n = 0; /* n is the input position in str */ - m = 0; /* m is the ouput position in buffer2 */ - - while ( str[n] != '\0') { - switch ( str[n] ) { - case '\\': - n++; - if ( str[n] != '\0') - buffer2[m++] = str[n++]; - break; - case '"': - n++; - break; - default: - buffer2[m++] = str[n++]; - break; - } - } - buffer2[m] = '\0'; + unquote_string(buffer, buffer2); str = buffer2; } break; @@ -981,7 +998,7 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat, if (comp->c_mn != &fmt_mnull) mnfree (comp->c_mn); if ((sp = comp->c_text) && (sp = getname(sp)) && - (mn = getm (sp, NULL, 0, fmt_norm, NULL))) { + (mn = getm (sp, NULL, 0, NULL, 0))) { comp->c_mn = mn; while (getname("")) ; @@ -1003,7 +1020,7 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat, if (comp->c_mn != &fmt_mnull) mnfree (comp->c_mn); if ((sp = comp->c_text) && (sp = getname(sp)) && - (mn = getm (sp, NULL, 0, AD_NAME, NULL))) { + (mn = getm (sp, NULL, 0, NULL, 0))) { comp->c_mn = mn; if (ismymbox(mn)) comp->c_flags |= CF_TRUE; @@ -1011,7 +1028,7 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat, comp->c_flags &= ~CF_TRUE; while ((sp = getname(sp))) if ((comp->c_flags & CF_TRUE) == 0 && - (mn = getm (sp, NULL, 0, AD_NAME, NULL))) + (mn = getm (sp, NULL, 0, NULL, 0))) if (ismymbox(mn)) comp->c_flags |= CF_TRUE; } else { @@ -1048,7 +1065,7 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat, there isn't enough room in the buffer for the entire string, skip it completely. Need room for null terminator, and maybe trailing newline (added below). */ - if (cp - scanl + strlen (str) + 1 < max) { + if (str && (cp - scanl + strlen (str) + 1 < max)) { for (sp = str; *sp; *cp++ = *sp++) continue; } if (callbacks && callbacks->trace_func)