/* * Copyright (C) 2000 Helix Code Inc. * * Authors: Michael Zucchi * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "camel-mime-filter-bestenc.h" static void camel_mime_filter_bestenc_class_init (CamelMimeFilterBestencClass *klass); static void camel_mime_filter_bestenc_init (CamelMimeFilter *obj); static CamelMimeFilterClass *camel_mime_filter_bestenc_parent; CamelType camel_mime_filter_bestenc_get_type (void) { static CamelType type = CAMEL_INVALID_TYPE; if (type == CAMEL_INVALID_TYPE) { type = camel_type_register (camel_mime_filter_get_type (), "CamelMimeFilterBestenc", sizeof (CamelMimeFilterBestenc), sizeof (CamelMimeFilterBestencClass), (CamelObjectClassInitFunc) camel_mime_filter_bestenc_class_init, NULL, (CamelObjectInitFunc) camel_mime_filter_bestenc_init, NULL); } return type; } static void reset(CamelMimeFilter *mf) { CamelMimeFilterBestenc *f = (CamelMimeFilterBestenc *)mf; f->count0 = 0; f->count8 = 0; f->countline = 0; f->total = 0; f->lastc = ~0; f->crlfnoorder = FALSE; camel_charset_init(&f->charset); } static void filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace) { CamelMimeFilterBestenc *f = (CamelMimeFilterBestenc *)mf; register unsigned char *p, *pend; f->total += len; if (f->flags & CAMEL_BESTENC_GET_ENCODING) { register unsigned int /* hopefully reg's are assinged in the order they appear? */ c, lastc=f->lastc, countline=f->countline, count0=f->count0, count8 = f->count8; /* See rfc2045 section 2 for definitions of 7bit/8bit/binary */ p = in; pend = p + len; while (pflags & CAMEL_BESTENC_LF_IS_CRLF)) { f->crlfnoorder = TRUE; } /* check for end of line */ if (c == '\n') { /* check for wild '\n's in canonical format stream */ if (lastc == '\r' || (f->flags & CAMEL_BESTENC_LF_IS_CRLF)) { if (countline > f->maxline) f->maxline = countline; countline = 0; } else { f->crlfnoorder = TRUE; } } else { countline++; } lastc = c; } f->count8 = count8; f->count0 = count0; f->countline = countline; f->lastc = lastc; } if (f->flags & CAMEL_BESTENC_GET_CHARSET) camel_charset_step(&f->charset, in, len); *out = in; *outlen = len; *outprespace = prespace; } static void complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace) { CamelMimeFilterBestenc *f = (CamelMimeFilterBestenc *)mf; filter(mf, in, len, prespace, out, outlen, outprespace); if (f->countline > f->maxline) f->maxline = f->countline; f->countline = 0; } static void camel_mime_filter_bestenc_class_init (CamelMimeFilterBestencClass *klass) { CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass; camel_mime_filter_bestenc_parent = (CamelMimeFilterClass *)(camel_type_get_global_classfuncs (camel_mime_filter_get_type ())); filter_class->reset = reset; filter_class->filter = filter; filter_class->complete = complete; } static void camel_mime_filter_bestenc_init (CamelMimeFilter *f) { reset(f); } /** * camel_mime_filter_bestenc_new: * @flags: A bitmask of data required. * * Create a new CamelMimeFilterBestenc object. * * Return value: **/ CamelMimeFilterBestenc * camel_mime_filter_bestenc_new (unsigned int flags) { CamelMimeFilterBestenc *new = (CamelMimeFilterBestenc *)camel_object_new(camel_mime_filter_bestenc_get_type()); new->flags = flags; return new; } /** * camel_mime_filter_bestenc_get_best_encoding: * @f: * @required: maximum level of output encoding allowed. * * Return the best encoding, given specific constraints, that can be used to * encode a stream of bytes. * * Return value: **/ CamelMimePartEncodingType camel_mime_filter_bestenc_get_best_encoding(CamelMimeFilterBestenc *f, CamelBestencEncoding required) { CamelMimePartEncodingType bestenc; #if 0 printf("count0 = %d, count8 = %d, total = %d\n", f->count0, f->count8, f->total); printf("maxline = %d, crlfnoorder = %s\n", f->maxline, f->crlfnoorder?"TRUE":"FALSE"); printf(" %d%% require encoding?\n", (f->count0+f->count8)*100 / f->total); #endif /* if we need to encode, see how we do it */ if (required == CAMEL_BESTENC_BINARY) bestenc = CAMEL_MIME_PART_ENCODING_BINARY; else if (f->count8 + f->count0 >= (f->total*17/100)) bestenc = CAMEL_MIME_PART_ENCODING_BASE64; else bestenc = CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE; /* if we have nocrlf order, or long lines, we need to encode always */ if (f->crlfnoorder || f->maxline >= 998) return bestenc; /* if we have no 8 bit chars or nul's, we can just use 7 bit */ if (f->count8 + f->count0 == 0) return CAMEL_MIME_PART_ENCODING_7BIT; /* otherwise, we see if we can use 8 bit, or not */ switch(required) { case CAMEL_BESTENC_7BIT: return bestenc; case CAMEL_BESTENC_8BIT: case CAMEL_BESTENC_BINARY: if (f->count0 == 0) return CAMEL_MIME_PART_ENCODING_8BIT; else return bestenc; } return CAMEL_MIME_PART_ENCODING_DEFAULT; } /** * camel_mime_filter_bestenc_get_best_charset: * @f: * * Gets the best charset that can be used to contain this content. * * Return value: **/ const char * camel_mime_filter_bestenc_get_best_charset(CamelMimeFilterBestenc *f) { return camel_charset_best_name(&f->charset); } /** * camel_mime_filter_bestenc_set_flags: * @f: * @flags: * * Set the flags for subsequent operations. **/ void camel_mime_filter_bestenc_set_flags(CamelMimeFilterBestenc *f, unsigned int flags) { f->flags = flags; }