static void filter_complete (GMimeFilter *filter, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace) { GMimeFilterYenc *yenc = (GMimeFilterYenc *) filter; const unsigned char *inbuf; unsigned char *outbuf; size_t newlen = 0; if (yenc->encode) { /* won't go to more than 2 * (x + 2) + 62 */ g_mime_filter_set_size (filter, (len + 2) * 2 + 62, FALSE); outbuf = (unsigned char *) filter->outbuf; inbuf = (const unsigned char *) in; newlen = g_mime_yencode_close (inbuf, len, outbuf, ¥c->state, ¥c->pcrc, ¥c->crc); g_assert (newlen <= (len + 2) * 2 + 62); } else { if ((yenc->state & GMIME_YDECODE_STATE_DECODE) && !(yenc->state & GMIME_YDECODE_STATE_END)) { /* all yEnc headers have been found so we can now start decoding */ g_mime_filter_set_size (filter, len + 3, FALSE); outbuf = (unsigned char *) filter->outbuf; inbuf = (const unsigned char *) in; newlen = g_mime_ydecode_step (inbuf, len, outbuf, ¥c->state, ¥c->pcrc, ¥c->crc); g_assert (newlen <= len + 3); } else { newlen = 0; } } *outprespace = filter->outpre; *out = filter->outbuf; *outlen = newlen; }
static void filter_filter (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace, char **outbuf, size_t *outlen, size_t *outprespace) { GMimeFilterReply *reply = (GMimeFilterReply *) filter; register const char *inptr = inbuf; const char *inend = inbuf + inlen; char *outptr; (void) prespace; if (reply->encode) { g_mime_filter_set_size (filter, 3 * inlen, FALSE); outptr = filter->outbuf; while (inptr < inend) { if (reply->saw_nl) { *outptr++ = '>'; *outptr++ = ' '; reply->saw_nl = FALSE; } if (*inptr == '\n') reply->saw_nl = TRUE; else reply->saw_nl = FALSE; if (*inptr != '\r') *outptr++ = *inptr; inptr++; } } else { g_mime_filter_set_size (filter, inlen + 1, FALSE); outptr = filter->outbuf; while (inptr < inend) { if (reply->saw_nl) { if (*inptr == '>') reply->saw_angle = TRUE; else *outptr++ = *inptr; reply->saw_nl = FALSE; } else if (reply->saw_angle) { if (*inptr == ' ') ; else *outptr++ = *inptr; reply->saw_angle = FALSE; } else if (*inptr != '\r') { if (*inptr == '\n') reply->saw_nl = TRUE; *outptr++ = *inptr; } inptr++; } } *outlen = outptr - filter->outbuf; *outprespace = filter->outpre; *outbuf = filter->outbuf; }
static char * check_size (GMimeFilter *filter, char *outptr, char **outend, size_t len) { size_t outleft = (size_t) (*outend - outptr); size_t offset; if (outleft >= len) return outptr; offset = outptr - filter->outbuf; g_mime_filter_set_size (filter, filter->outsize + len, TRUE); *outend = filter->outbuf + filter->outsize; return filter->outbuf + offset; }
static void convert (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace, char **outbuf, size_t *outlen, size_t *outprespace, gboolean flush) { GMimeFilterDos2Unix *dos2unix = (GMimeFilterDos2Unix *) filter; register const char *inptr = inbuf; const char *inend = inbuf + inlen; size_t expected = inlen; char *outptr; if (flush && dos2unix->ensure_newline) expected++; if (dos2unix->pc == '\r') expected++; g_mime_filter_set_size (filter, expected, FALSE); outptr = filter->outbuf; while (inptr < inend) { if (*inptr == '\n') { *outptr++ = *inptr; } else { if (dos2unix->pc == '\r') *outptr++ = dos2unix->pc; if (*inptr != '\r') *outptr++ = *inptr; } dos2unix->pc = *inptr++; } if (flush && dos2unix->ensure_newline && dos2unix->pc != '\n') dos2unix->pc = *outptr++ = '\n'; *outlen = outptr - filter->outbuf; *outprespace = filter->outpre; *outbuf = filter->outbuf; }
static void html_convert (GMimeFilter *filter, char *in, size_t inlen, size_t prespace, char **out, size_t *outlen, size_t *outprespace, gboolean flush) { (void) (prespace); GMimeFilterHTMLBQ *html = (GMimeFilterHTMLBQ *) filter; register char *inptr, *outptr; char *start, *outend; const char *inend; int depth; g_mime_filter_set_size (filter, inlen * 2 + 6, FALSE); start = inptr = in; inend = in + inlen; outptr = filter->outbuf; outend = filter->outbuf + filter->outsize; if (html->flags & GMIME_FILTER_HTML_PRE && !html->pre_open) { outptr = g_stpcpy (outptr, "<pre>"); html->pre_open = TRUE; } do { while (inptr < inend && *inptr != '\n') inptr++; if (inptr == inend && !flush) break; html->column = 0; depth = citation_depth (start, inend); if (html->flags & GMIME_FILTER_HTML_BQ_BLOCKQUOTE_CITATION) { if (html->prev_cit_depth < depth) { while (html->prev_cit_depth < depth) { html->prev_cit_depth++; char bq[33]; int ldepth = html->prev_cit_depth > 999 ? 999 : html->prev_cit_depth; g_snprintf (bq, 31, "<blockquote class=\"level_%03d\">", ldepth); outptr = check_size (filter, outptr, &outend, 31); outptr = g_stpcpy (outptr, bq); } /* remove '>' */ while (*start == '>' && start < inptr) start++; /* remove leading space */ if (*start == ' ' && start < inptr) start++; } else if (html->prev_cit_depth > depth) { /* close quotes */ while (html->prev_cit_depth > depth) { outptr = check_size (filter, outptr, &outend, 14); outptr = g_stpcpy (outptr, "</blockquote>"); html->prev_cit_depth--; } /* remove '>' */ while (*start == '>' && start < inptr) start++; /* remove leading space */ if (*start == ' ' && start < inptr) start++; } else if (depth > 0) { /* we are still at the same depth: remove '>' */ while (*start == '>' && start < inptr) start++; /* remove leading space */ if (*start == ' ' && start < inptr) start++; } else if (*start == '>') { /* >From line */ start++; } } else if (html->flags & GMIME_FILTER_HTML_MARK_CITATION) { if (depth > 0) { char font[25]; /* FIXME: we could easily support multiple colour depths here */ g_snprintf (font, 25, "<font color=\"#%06x\">", (html->colour & 0xffffff)); outptr = check_size (filter, outptr, &outend, 25); outptr = g_stpcpy (outptr, font); } else if (*start == '>') { /* >From line */ start++; } } else if (html->flags & GMIME_FILTER_HTML_CITE) { outptr = check_size (filter, outptr, &outend, 6); outptr = g_stpcpy (outptr, "> "); html->column += 2; } #define CONVERT_URLS_OR_ADDRESSES (GMIME_FILTER_HTML_CONVERT_URLS | GMIME_FILTER_HTML_CONVERT_ADDRESSES) if (html->flags & CONVERT_URLS_OR_ADDRESSES) { size_t matchlen, buflen, len; urlmatch_t match; len = inptr - start; do { if (url_scanner_scan (html->scanner, start, len, &match)) { /* write out anything before the first regex match */ outptr = writeln (filter, start, start + match.um_so, outptr, &outend); start += match.um_so; len -= match.um_so; matchlen = match.um_eo - match.um_so; buflen = 20 + strlen (match.prefix) + matchlen + matchlen; outptr = check_size (filter, outptr, &outend, buflen); /* write out the href tag */ outptr = g_stpcpy (outptr, "<a href=\""); outptr = g_stpcpy (outptr, match.prefix); memcpy (outptr, start, matchlen); outptr += matchlen; outptr = g_stpcpy (outptr, "\">"); /* now write the matched string */ memcpy (outptr, start, matchlen); html->column += matchlen; outptr += matchlen; start += matchlen; len -= matchlen; /* close the href tag */ outptr = g_stpcpy (outptr, "</a>"); } else { /* nothing matched so write out the remainder of this line buffer */ outptr = writeln (filter, start, start + len, outptr, &outend); break; } } while (len > 0); } else { outptr = writeln (filter, start, inptr, outptr, &outend); } if (!(html->flags & GMIME_FILTER_HTML_BQ_BLOCKQUOTE_CITATION) && (html->flags & GMIME_FILTER_HTML_MARK_CITATION) && (depth > 0)) { outptr = check_size (filter, outptr, &outend, 8); outptr = g_stpcpy (outptr, "</font>"); } if (html->flags & GMIME_FILTER_HTML_CONVERT_NL) { outptr = check_size (filter, outptr, &outend, 5); outptr = g_stpcpy (outptr, "<br>"); } if (inptr < inend) *outptr++ = '\n'; start = ++inptr; } while (inptr < inend); if (flush) { if (html->pre_open) { /* close the pre-tag */ outptr = check_size (filter, outptr, &outend, 10); outptr = g_stpcpy (outptr, "</pre>"); } if ((html->flags & GMIME_FILTER_HTML_BQ_BLOCKQUOTE_CITATION) && (html->prev_cit_depth > 0)) { /* close open blockquotes */ while (html->prev_cit_depth > 0) { outptr = check_size (filter, outptr, &outend, 14); outptr = g_stpcpy (outptr, "</blockquote>"); html->prev_cit_depth--; } } } else if (start < inend) { /* backup */ g_mime_filter_backup (filter, start, (unsigned) (inend - start)); } *out = filter->outbuf; *outlen = outptr - filter->outbuf; *outprespace = filter->outpre; }
static void filter_filter(GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace, char **outbuf, size_t *outlen, size_t *outprespace) { GMimeFilterHeader *self = GMIME_FILTER_HEADER(filter); g_mime_filter_set_size(filter, inlen, FALSE); if (self->headers_done) { memcpy(filter->outbuf, inbuf, inlen); *outlen = inlen; } else { gchar *newline; gchar *outptr; outptr = filter->outbuf; *outlen = 0U; newline = memchr(inbuf, '\n', inlen); while ((newline != NULL) && !self->headers_done) { size_t count; /* number of chars in this line */ count = (newline - inbuf) + 1U; /* check for for folded header continuation */ if ((inbuf[0] == ' ') || (inbuf[0] == '\t')) { /* nothing to do, do not change the state */ } else if (newline == inbuf) { self->headers_done = TRUE; } else if (((count >= 4U) && (g_ascii_strncasecmp(inbuf, "Bcc:", 4U) == 0)) || ((count >= 7U) && (g_ascii_strncasecmp(inbuf, "Status:", 7U) == 0)) || ((count >= 9U) && (g_ascii_strncasecmp(inbuf, "X-Status:", 9U) == 0)) || ((count >= 8U) && (g_ascii_strncasecmp(inbuf, "X-Balsa-", 8U) == 0))) { self->drop_header = TRUE; } else { self->drop_header = FALSE; } /* copy if we want to keep this header */ if (!self->drop_header) { memcpy(outptr, inbuf, count); outptr = &outptr[count]; *outlen += count; } /* adjust */ inbuf = &inbuf[count]; inlen -= count; if (!self->headers_done && (inlen > 0)) { newline = memchr(inbuf, '\n', inlen); } else { newline = NULL; } } /* back up left-over data */ if (inlen > 0U) { g_mime_filter_backup(filter, inbuf, inlen); } } *outprespace = filter->outpre; *outbuf = filter->outbuf; }
static void filter_filter (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace, char **outbuf, size_t *outlen, size_t *outprespace) { GMimeFilterCRLF *crlf = (GMimeFilterCRLF *) filter; register const char *inptr = inbuf; const char *inend = inbuf + inlen; char *outptr; if (crlf->encode) { g_mime_filter_set_size (filter, 3 * inlen, FALSE); outptr = filter->outbuf; while (inptr < inend) { if (*inptr == '\r') { crlf->saw_cr = TRUE; } else if (*inptr == '\n') { crlf->saw_lf = TRUE; if (!crlf->saw_cr) *outptr++ = '\r'; crlf->saw_cr = FALSE; } else { if (crlf->dots && *inptr == '.' && crlf->saw_lf) *outptr++ = '.'; crlf->saw_cr = FALSE; crlf->saw_lf = FALSE; } *outptr++ = *inptr++; } } else { g_mime_filter_set_size (filter, inlen + 1, FALSE); outptr = filter->outbuf; while (inptr < inend) { if (*inptr == '\r') { crlf->saw_dot = FALSE; crlf->saw_cr = TRUE; } else { if (crlf->saw_cr) { crlf->saw_cr = FALSE; if (*inptr == '\n') { crlf->saw_lf = TRUE; *outptr++ = *inptr++; continue; } else *outptr++ = '\r'; } if (!(crlf->dots && crlf->saw_dot && *inptr == '.')) *outptr++ = *inptr; } if (crlf->dots && *inptr == '.') { if (crlf->saw_lf) { crlf->saw_dot = TRUE; } else if (crlf->saw_dot) { crlf->saw_dot = FALSE; } } crlf->saw_lf = FALSE; inptr++; } } *outlen = outptr - filter->outbuf; *outprespace = filter->outpre; *outbuf = filter->outbuf; }
/* here we do all of the basic yEnc filtering */ static void filter_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace) { GMimeFilterYenc *yenc = (GMimeFilterYenc *) filter; const unsigned char *inbuf; unsigned char *outbuf; size_t newlen = 0; if (yenc->encode) { /* won't go to more than 2 * (x + 2) + 62 */ g_mime_filter_set_size (filter, (len + 2) * 2 + 62, FALSE); outbuf = (unsigned char *) filter->outbuf; inbuf = (const unsigned char *) in; newlen = g_mime_yencode_step (inbuf, len, outbuf, ¥c->state, ¥c->pcrc, ¥c->crc); g_assert (newlen <= (len + 2) * 2 + 62); } else { if (!(yenc->state & GMIME_YDECODE_STATE_DECODE)) { register char *inptr, *inend; size_t left; inptr = in; inend = inptr + len; /* we cannot start decoding until we have found an =ybegin line */ if (!(yenc->state & GMIME_YDECODE_STATE_BEGIN)) { while (inptr < inend) { left = inend - inptr; if (left < 8) { if (!strncmp (inptr, "=ybegin ", left)) g_mime_filter_backup (filter, inptr, left); break; } else if (!strncmp (inptr, "=ybegin ", 8)) { for (in = inptr; inptr < inend && *inptr != '\n'; inptr++); if (inptr < inend) { inptr++; yenc->state |= GMIME_YDECODE_STATE_BEGIN; /* we can start ydecoding if the next line isn't a ypart... */ in = inptr; len = inend - in; } else { /* we don't have enough... */ g_mime_filter_backup (filter, in, left); } break; } /* go to the next line */ while (inptr < inend && *inptr != '\n') inptr++; if (inptr < inend) inptr++; } } left = inend - inptr; if ((yenc->state & GMIME_YDECODE_STATE_BEGIN) && left > 0) { /* we have found an '=ybegin' line but we may yet have an "=ypart" line to yield before decoding the content */ if (left < 7 && !strncmp (inptr, "=ypart ", left)) { g_mime_filter_backup (filter, inptr, left); } else if (!strncmp (inptr, "=ypart ", 7)) { for (in = inptr; inptr < inend && *inptr != '\n'; inptr++); if (inptr < inend) { inptr++; yenc->state |= GMIME_YDECODE_STATE_PART | GMIME_YDECODE_STATE_DECODE; in = inptr; len = inend - in; } else { g_mime_filter_backup (filter, in, left); } } else { /* guess it doesn't have a =ypart line */ yenc->state |= GMIME_YDECODE_STATE_DECODE; } } } if ((yenc->state & GMIME_YDECODE_STATE_DECODE) && !(yenc->state & GMIME_YDECODE_STATE_END)) { /* all yEnc headers have been found so we can now start decoding */ g_mime_filter_set_size (filter, len + 3, FALSE); outbuf = (unsigned char *) filter->outbuf; inbuf = (const unsigned char *) in; newlen = g_mime_ydecode_step (inbuf, len, outbuf, ¥c->state, ¥c->pcrc, ¥c->crc); g_assert (newlen <= len + 3); } else { newlen = 0; } } *outprespace = filter->outpre; *out = filter->outbuf; *outlen = newlen; }