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: