Annotation of win32/gnome/gmime-x.x.x/gmime-filter-charset.c, revision 1.1

1.1     ! paf         1: /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
        !             2: /*
        !             3:  *  Authors: Jeffrey Stedfast <fejj@ximian.com>
        !             4:  *
        !             5:  *  Copyright 2002 Ximian, Inc. (www.ximian.com)
        !             6:  *
        !             7:  *  This program is free software; you can redistribute it and/or modify
        !             8:  *  it under the terms of the GNU General Public License as published by
        !             9:  *  the Free Software Foundation; either version 2 of the License, or
        !            10:  *  (at your option) any later version.
        !            11:  *
        !            12:  *  This program is distributed in the hope that it will be useful,
        !            13:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            15:  *  GNU General Public License for more details.
        !            16:  *
        !            17:  *  You should have received a copy of the GNU General Public License
        !            18:  *  along with this program; if not, write to the Free Software
        !            19:  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
        !            20:  *
        !            21:  */
        !            22: 
        !            23: 
        !            24: #ifdef HAVE_CONFIG_H
        !            25: #include <config.h>
        !            26: #endif
        !            27: 
        !            28: #include <errno.h>
        !            29: 
        !            30: #include "gmime-filter-charset.h"
        !            31: #include "gmime-charset.h"
        !            32: #include "gmime-iconv.h"
        !            33: 
        !            34: 
        !            35: static void filter_destroy (GMimeFilter *filter);
        !            36: static GMimeFilter *filter_copy (GMimeFilter *filter);
        !            37: static void filter_filter (GMimeFilter *filter, char *in, size_t len, 
        !            38:                           size_t prespace, char **out, 
        !            39:                           size_t *outlen, size_t *outprespace);
        !            40: static void filter_complete (GMimeFilter *filter, char *in, size_t len, 
        !            41:                             size_t prespace, char **out, 
        !            42:                             size_t *outlen, size_t *outprespace);
        !            43: static void filter_reset (GMimeFilter *filter);
        !            44: 
        !            45: static GMimeFilter filter_template = {
        !            46:        NULL, NULL, NULL, NULL,
        !            47:        0, 0, NULL, 0, 0,
        !            48:        filter_destroy,
        !            49:        filter_copy,
        !            50:        filter_filter,
        !            51:        filter_complete,
        !            52:        filter_reset,
        !            53: };
        !            54: 
        !            55: 
        !            56: /**
        !            57:  * g_mime_filter_charset_new:
        !            58:  * @from_charset:
        !            59:  * @to_charset:
        !            60:  *
        !            61:  * Creates a new GMimeFilterCharset filter.
        !            62:  *
        !            63:  * Returns a new charset filter.
        !            64:  **/
        !            65: GMimeFilter *
        !            66: g_mime_filter_charset_new (const char *from_charset, const char *to_charset)
        !            67: {
        !            68:        GMimeFilterCharset *new;
        !            69:        iconv_t cd;
        !            70:        
        !            71:        cd = g_mime_iconv_open (to_charset, from_charset);
        !            72:        if (cd == (iconv_t) -1)
        !            73:                return NULL;
        !            74:        
        !            75:        new = g_new (GMimeFilterCharset, 1);
        !            76:        new->from_charset = g_strdup (from_charset);
        !            77:        new->to_charset = g_strdup (to_charset);
        !            78:        new->cd = cd;
        !            79:        
        !            80:        g_mime_filter_construct (GMIME_FILTER (new), &filter_template);
        !            81:        
        !            82:        return GMIME_FILTER (new);
        !            83: }
        !            84: 
        !            85: 
        !            86: static void
        !            87: filter_destroy (GMimeFilter *filter)
        !            88: {
        !            89:        GMimeFilterCharset *charset = (GMimeFilterCharset *) filter;
        !            90:        
        !            91:        g_free (charset->from_charset);
        !            92:        g_free (charset->to_charset);
        !            93:        if (charset->cd != (iconv_t) -1)
        !            94:                g_mime_iconv_close (charset->cd);
        !            95:        g_free (filter);
        !            96: }
        !            97: 
        !            98: static GMimeFilter *
        !            99: filter_copy (GMimeFilter *filter)
        !           100: {
        !           101:        GMimeFilterCharset *charset = (GMimeFilterCharset *) filter;
        !           102:        
        !           103:        return g_mime_filter_charset_new (charset->from_charset, charset->to_charset);
        !           104: }
        !           105: 
        !           106: static void
        !           107: filter_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
        !           108:               char **out, size_t *outlen, size_t *outprespace)
        !           109: {
        !           110:        GMimeFilterCharset *charset = (GMimeFilterCharset *) filter;
        !           111:        size_t inleft, outleft, converted = 0;
        !           112:        char *inbuf;
        !           113:        char *outbuf;
        !           114:        
        !           115:        if (charset->cd == (iconv_t) -1)
        !           116:                goto noop;
        !           117:        
        !           118:        g_mime_filter_set_size (filter, len * 5 + 16, FALSE);
        !           119:        
        !           120:        inbuf = in;
        !           121:        inleft = len;
        !           122:        
        !           123:        do {
        !           124:                errno = 0;
        !           125:                outbuf = filter->outbuf + converted;
        !           126:                outleft = filter->outsize - converted;
        !           127:                
        !           128:                converted = g_mime_iconv (charset->cd, &inbuf, &inleft, &outbuf, &outleft);
        !           129:                if (converted == (size_t) -1) {
        !           130:                        if (errno != E2BIG && errno != EINVAL)
        !           131:                                goto noop;
        !           132:                }
        !           133:                
        !           134:                /*
        !           135:                 * E2BIG   There is not sufficient room at *outbuf.
        !           136:                 *
        !           137:                 * We just need to grow our outbuffer and try again.
        !           138:                 */
        !           139:                
        !           140:                converted = filter->outsize - outleft;
        !           141:                if (errno == E2BIG)
        !           142:                        g_mime_filter_set_size (filter, inleft * 5 + filter->outsize + 16, TRUE);
        !           143:                
        !           144:        } while (errno == E2BIG && inleft > 0);
        !           145:        
        !           146:        /*
        !           147:         * EINVAL  An  incomplete  multibyte sequence has been encoun­
        !           148:         *         tered in the input.
        !           149:         *
        !           150:         * This just means that we need to save the remainder
        !           151:         * of the input buffer for the next conversion.
        !           152:         */
        !           153:        
        !           154:        if (inleft > 0)
        !           155:                g_mime_filter_backup (filter, inbuf, inleft);
        !           156:        
        !           157:        *out = filter->outbuf;
        !           158:        *outlen = converted;
        !           159:        *outprespace = filter->outpre;
        !           160:        
        !           161:        return;
        !           162:        
        !           163:  noop:
        !           164:        
        !           165:        *out = in;
        !           166:        *outlen = len;
        !           167:        *outprespace = prespace;
        !           168: }
        !           169: 
        !           170: static void 
        !           171: filter_complete (GMimeFilter *filter, char *in, size_t len, size_t prespace,
        !           172:                 char **out, size_t *outlen, size_t *outprespace)
        !           173: {
        !           174:        GMimeFilterCharset *charset = (GMimeFilterCharset *) filter;
        !           175:        size_t inleft, outleft, converted = 0;
        !           176:        char *inbuf;
        !           177:        char *outbuf;
        !           178:        
        !           179:        if (charset->cd == (iconv_t) -1)
        !           180:                goto noop;
        !           181:        
        !           182:        g_mime_filter_set_size (filter, len * 5 + 16, FALSE);
        !           183:        
        !           184:        inbuf = in;
        !           185:        inleft = len;
        !           186:        
        !           187:        if (inleft > 0) {
        !           188:                do {
        !           189:                        outbuf = filter->outbuf + converted;
        !           190:                        outleft = filter->outsize - converted;
        !           191:                        
        !           192:                        converted = iconv (charset->cd, &inbuf, &inleft, &outbuf, &outleft);
        !           193:                        if (converted == (size_t) -1) {
        !           194:                                if (errno != E2BIG && errno != EINVAL)
        !           195:                                        goto noop;
        !           196:                        }
        !           197:                        
        !           198:                        /*
        !           199:                         * E2BIG   There is not sufficient room at *outbuf.
        !           200:                         *
        !           201:                         * We just need to grow our outbuffer and try again.
        !           202:                         */
        !           203:                        
        !           204:                        converted = filter->outsize - outleft;
        !           205:                        if (errno == E2BIG)
        !           206:                                g_mime_filter_set_size (filter, inleft * 5 + filter->outsize + 16, TRUE);
        !           207:                        
        !           208:                } while (errno == E2BIG);
        !           209:        } else {
        !           210:                outbuf = filter->outbuf;
        !           211:                outleft = filter->outsize;
        !           212:        }
        !           213:        
        !           214:        /*
        !           215:         * EINVAL  An  incomplete  multibyte sequence has been encoun­
        !           216:         *         tered in the input.
        !           217:         *
        !           218:         * This just means that we need to save the remainder
        !           219:         * of the input buffer for the next conversion.
        !           220:         */
        !           221:        
        !           222:        /* flush the iconv conversion */
        !           223:        iconv (charset->cd, NULL, NULL, &outbuf, &outleft);
        !           224:        
        !           225:        *out = filter->outbuf;
        !           226:        *outlen = filter->outsize - outleft;
        !           227:        *outprespace = filter->outpre;
        !           228:        
        !           229:        return;
        !           230:        
        !           231:  noop:
        !           232:        
        !           233:        *out = in;
        !           234:        *outlen = len;
        !           235:        *outprespace = prespace;
        !           236: }
        !           237: 
        !           238: static void
        !           239: filter_reset (GMimeFilter *filter)
        !           240: {
        !           241:        GMimeFilterCharset *charset = (GMimeFilterCharset *) filter;
        !           242:        
        !           243:        if (charset->cd != (iconv_t) -1)
        !           244:                iconv (charset->cd, NULL, NULL, NULL, NULL);
        !           245: }

E-mail: