Call camel_iconv_init(). (camel_shutdown): Call camel_iconv_shutdown().

2003-02-20  Jeffrey Stedfast  <fejj@ximian.com>

	* camel.c (camel_init): Call camel_iconv_init().
	(camel_shutdown): Call camel_iconv_shutdown().

	* camel-sasl-digest-md5.c (digest_response): Updated to use
	camel-iconv and the new camel-charset-map functions.

	* camel-mime-utils.c: Updated to use camel-iconv and the new
	camel-charset-map functions.

	* camel-mime-part-utils.c (check_html_charset): Use
	camel_charset_canonical_name() instead of e_iconv_charset_name()
	which is longer available.
	(convert_buffer): Use camel-iconv.
	(simple_data_wrapper_construct_from_parser): Since
	camel_charset_iso_to_windows() returns the charset in it's
	canonical format, no need to re-canonicalise it.

	* camel-mime-part.c (process_header): Use
	camel_charset_canonical_name() instead of e_iconv_charset_name()
	which is longer available.

	* camel-mime-message.c (process_header): Use
	camel_charset_canonical_name() instead of e_iconv_charset_name()
	which is longer available.

	* camel-mime-filter-charset.c: Use camel-iconv.

	* camel-folder-summary.c (message_info_new): Use
	camel_charset_canonical_name() instead of e_iconv_charset_name()
	which is longer available.
	(content_info_new): Use camel_charset_locale_name().
	(camel_message_info_new_from_header): Same as message_info_new().

	* camel-search-private.c: Use g_alloca() instead of alloca().

	* camel-filter-search.c (check_header): Use
	camel_charset_canonical_name() instead of e_iconv_charset_name()
	which is longer available.

	* camel-charset-map.c (camel_charset_locale_name): New function,
	replaces e_iconv_locale_charset().
	(camel_charset_canonical_name): New function, similar to
	e_iconv_charset_name() but instead of returning the iconv-friendly
	name, it returns the canonical name. (g_iconv will do the
	iconv-friendly name conversions for us).

svn path=/trunk/; revision=19977
This commit is contained in:
Jeffrey Stedfast
2003-02-20 21:04:19 +00:00
committed by Jeffrey Stedfast
parent 08c781ab88
commit abada7e2cd
16 changed files with 757 additions and 119 deletions

View File

@ -1,3 +1,51 @@
2003-02-20 Jeffrey Stedfast <fejj@ximian.com>
* camel.c (camel_init): Call camel_iconv_init().
(camel_shutdown): Call camel_iconv_shutdown().
* camel-sasl-digest-md5.c (digest_response): Updated to use
camel-iconv and the new camel-charset-map functions.
* camel-mime-utils.c: Updated to use camel-iconv and the new
camel-charset-map functions.
* camel-mime-part-utils.c (check_html_charset): Use
camel_charset_canonical_name() instead of e_iconv_charset_name()
which is longer available.
(convert_buffer): Use camel-iconv.
(simple_data_wrapper_construct_from_parser): Since
camel_charset_iso_to_windows() returns the charset in it's
canonical format, no need to re-canonicalise it.
* camel-mime-part.c (process_header): Use
camel_charset_canonical_name() instead of e_iconv_charset_name()
which is longer available.
* camel-mime-message.c (process_header): Use
camel_charset_canonical_name() instead of e_iconv_charset_name()
which is longer available.
* camel-mime-filter-charset.c: Use camel-iconv.
* camel-folder-summary.c (message_info_new): Use
camel_charset_canonical_name() instead of e_iconv_charset_name()
which is longer available.
(content_info_new): Use camel_charset_locale_name().
(camel_message_info_new_from_header): Same as message_info_new().
* camel-search-private.c: Use g_alloca() instead of alloca().
* camel-filter-search.c (check_header): Use
camel_charset_canonical_name() instead of e_iconv_charset_name()
which is longer available.
* camel-charset-map.c (camel_charset_locale_name): New function,
replaces e_iconv_locale_charset().
(camel_charset_canonical_name): New function, similar to
e_iconv_charset_name() but instead of returning the iconv-friendly
name, it returns the canonical name. (g_iconv will do the
iconv-friendly name conversions for us).
2003-02-20 Jeffrey Stedfast <fejj@ximian.com>
* camel-filter-search.c (run_command): Redirect program's stdout

View File

@ -47,6 +47,7 @@ libcamel_la_SOURCES = \
camel-gpg-context.c \
camel-html-parser.c \
camel-http-stream.c \
camel-iconv.c \
camel-index.c \
camel-internet-address.c \
camel-lock.c \
@ -148,6 +149,7 @@ libcamelinclude_HEADERS = \
camel-folder.h \
camel-gpg-context.h \
camel-http-stream.h \
camel-iconv.h \
camel-index.h \
camel-internet-address.h \
camel-i18n.h \

View File

@ -3,9 +3,10 @@
/*
* Authors:
* Michael Zucchi <notzed@ximian.com>
* Jeffrey Stedfast <fejj@ximian.com>
* Dan Winship <danw@ximian.com>
*
* Copyright 2000, 2001 Ximian, Inc. (www.ximian.com)
* Copyright 2000, 2003 Ximian, Inc. (www.ximian.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@ -22,12 +23,15 @@
* USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/*
if you want to build the charset map, compile this with something like:
@ -200,16 +204,16 @@ int main (void)
#include "camel-charset-map.h"
#include "camel-charset-map-private.h"
#include "string-utils.h"
#include <glib.h>
#include <glib/gunicode.h>
#include <locale.h>
#include <string.h>
#include <ctype.h>
#include <glib.h>
#ifdef ENABLE_THREADS
#include <pthread.h>
#endif
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#ifdef HAVE_CODESET
#include <langinfo.h>
#endif
void
@ -295,9 +299,179 @@ camel_charset_best (const char *in, int len)
}
#ifdef G_THREADS_ENABLED
static GStaticMutex lock = G_STATIC_MUTEX_INIT;
#define LOCK() g_static_mutex_lock(&lock)
#define UNLOCK() g_static_mutex_unlock(&lock)
#else
#define LOCK()
#define UNLOCK()
#endif
static char *locale_charset = NULL;
static GHashTable *canon_charsets = NULL;
static void
canon_charsets_init (int keep)
{
char *locale;
LOCK ();
if (canon_charsets != NULL) {
if (!keep)
UNLOCK ();
return;
}
canon_charsets = g_hash_table_new (g_str_hash, g_str_equal);
locale = setlocale (LC_ALL, NULL);
if (!locale || !strcmp (locale, "C") || !strcmp (locale, "POSIX")) {
/* The locale "C" or "POSIX" is a portable locale; its
* LC_CTYPE part corresponds to the 7-bit ASCII character
* set.
*/
locale_charset = NULL;
} else {
#ifdef HAVE_CODESET
locale_charset = g_strdup (nl_langinfo (CODESET));
g_ascii_strdown (locale_charset, -1);
#else
/* A locale name is typically of the form language[_terri-
* tory][.codeset][@modifier], where language is an ISO 639
* language code, territory is an ISO 3166 country code, and
* codeset is a character set or encoding identifier like
* ISO-8859-1 or UTF-8.
*/
char *codeset, *p;
codeset = strchr (locale, '.');
if (codeset) {
codeset++;
/* ; is a hack for debian systems and / is a hack for Solaris systems */
for (p = codeset; *p && !strchr ("@;/", *p); p++)
;
locale_charset = g_strndup (codeset, p - codeset);
g_ascii_strdown (locale_charset, -1);
} else {
/* charset unknown */
locale_charset = NULL;
}
#endif
}
if (!keep)
UNLOCK ();
}
/**
* camel_charset_locale_name:
*
* Returns the name of the system's locale charset.
**/
const char *
camel_charset_locale_name (void)
{
canon_charsets_init (FALSE);
return locale_charset;
}
/**
* camel_charset_canonical_name:
* @charset: charset to canonicalise
*
* Returns the charset in its canonical format. This is currently only
* needed for iso charsets but also handles canonicalisation of
* windows charsets. May need to expand this to handle canincalisation
* of more charsets in the future?
**/
const char *
camel_charset_canonical_name (const char *charset)
{
char *name, *canon, *tmp;
if (charset == NULL)
return NULL;
name = g_alloca (strlen (charset));
strcpy (name, charset);
g_ascii_strdown (name, -1);
canon_charsets_init (TRUE);
canon = g_hash_table_lookup (canon_charsets, name);
if (canon != NULL) {
UNLOCK ();
return canon;
}
/* Unknown, try canonicalise some basic charset types to something that should work */
if (strncmp (name, "iso", 3) == 0) {
/* Convert iso-nnnn-n or isonnnn-n or iso_nnnn-n to iso-nnnn-n or isonnnn-n */
int iso, codepage;
char *p;
tmp = name + 3;
if (*tmp == '-' || *tmp == '_')
tmp++;
iso = strtoul (tmp, &p, 10);
if (iso == 10646) {
/* they all become iso-10646 */
canon = g_strdup ("iso-10646");
} else {
/* iso-8859-# */
tmp = p;
if (*tmp == '-' || *tmp == '_')
tmp++;
codepage = strtoul (tmp, &p, 10);
if (p > tmp) {
/* codepage is numeric */
canon = g_strdup_printf ("iso-%d-%d", iso, codepage);
} else {
/* codepage is a string - probably iso-2022-jp or something */
canon = g_strdup_printf ("iso-%d-%s", iso, p);
}
}
} else if (strncmp (name, "windows-", 8) == 0) {
/* Convert windows-#### and windows-cp#### to windows-cp#### */
tmp = name + 8;
if (!strncmp (tmp, "cp", 2))
tmp += 2;
canon = g_strdup_printf ("windows-cp%s", tmp);
} else if (strncmp (name, "microsoft-", 10) == 0) {
/* Convert microsoft-#### or microsoft-cp#### to windows-cp#### */
tmp = name + 10;
if (!strncmp (tmp, "cp", 2))
tmp += 2;
canon = g_strdup_printf ("windows-cp%s", tmp);
} else if (strncmp (name, "cp125", 5) == 0) {
/* Convert cp125# to windows-cp#### */
canon = g_strdup_printf ("windows-%s", name);
} else {
/* Just assume its ok enough as is, case and all */
canon = g_strdup (charset);
}
g_hash_table_insert (canon_charsets, g_strdup (name), canon);
UNLOCK ();
return canon;
}
/**
* camel_charset_iso_to_windows:
* @isocharset: an ISO charset
* @isocharset: a canonicalised ISO charset
*
* Returns the equivalent Windows charset.
**/
@ -351,4 +525,3 @@ camel_charset_iso_to_windows (const char *isocharset)
}
#endif /* !BUILD_MAP */

View File

@ -37,7 +37,11 @@ struct _CamelCharset {
void camel_charset_init(CamelCharset *);
void camel_charset_step(CamelCharset *, const char *in, int len);
const char *camel_charset_best_name(CamelCharset *);
const char *camel_charset_locale_name (void);
const char *camel_charset_canonical_name (const char *charset);
const char *camel_charset_best_name (CamelCharset *);
/* helper function */
const char *camel_charset_best(const char *in, int len);

View File

@ -42,15 +42,9 @@
#include <signal.h>
#include <sys/wait.h>
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
#include <gal/util/e-iconv.h>
#include "e-util/e-sexp.h"
#include "camel-charset-map.h"
#include "camel-mime-message.h"
#include "camel-provider.h"
#include "camel-session.h"
@ -167,8 +161,10 @@ check_header (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMess
type = CAMEL_SEARCH_TYPE_ADDRESS_ENCODED;
else {
ct = camel_mime_part_get_content_type (CAMEL_MIME_PART (message));
if (ct)
charset = e_iconv_charset_name(header_content_type_param(ct, "charset"));
if (ct) {
charset = header_content_type_param (ct, "charset");
charset = camel_charset_canonical_name (charset);
}
}
}

View File

@ -33,10 +33,9 @@
#include <errno.h>
#include <stdlib.h>
#include <gal/util/e-iconv.h>
#include "camel-folder-summary.h"
#include <camel/camel-charset-map.h>
#include <camel/camel-file-utils.h>
#include <camel/camel-mime-filter.h>
#include <camel/camel-mime-filter-index.h>
@ -1575,9 +1574,9 @@ message_info_new(CamelFolderSummary *s, struct _header_raw *h)
&& (charset = header_content_type_param(ct, "charset"))
&& (strcasecmp(charset, "us-ascii") == 0))
charset = NULL;
charset = e_iconv_charset_name(charset);
charset = camel_charset_canonicalname (charset);
subject = summary_format_string(h, "subject", charset);
from = summary_format_address(h, "from");
to = summary_format_address(h, "to");
@ -1837,7 +1836,7 @@ content_info_new (CamelFolderSummary *s, struct _header_raw *h)
ci = camel_folder_summary_content_info_new (s);
charset = e_iconv_locale_charset();
charset = camel_charset_locale_name ();
ci->id = header_msgid_decode (header_raw_find (&h, "content-id", NULL));
ci->description = header_decode_string (header_raw_find (&h, "content-description", NULL), NULL);
ci->encoding = header_content_encoding_decode (header_raw_find (&h, "content-transfer-encoding", NULL));
@ -2562,8 +2561,8 @@ camel_message_info_new_from_header (struct _header_raw *header)
&& (charset = header_content_type_param(ct, "charset"))
&& (strcasecmp(charset, "us-ascii") == 0))
charset = NULL;
charset = e_iconv_charset_name(charset);
charset = camel_charset_canonical_name (charset);
subject = summary_format_string(header, "subject", charset);
from = summary_format_address(header, "from");

365
camel/camel-iconv.c Normal file
View File

@ -0,0 +1,365 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Authors: Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright 2003 Ximian, Inc. (www.ximian.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "e-util/e-memory.h"
#include "camel/camel-charset-map.h"
#define ICONV_CACHE_SIZE (16)
struct _iconv_cache_bucket {
struct _iconv_cache_bucket *next;
struct _iconv_cache_bucket *prev;
guint32 refcount;
gboolean used;
iconv_t cd;
char *key;
};
static EMemChunk *cache_chunk;
static struct _iconv_cache_bucket *iconv_cache_buckets;
static GHashTable *iconv_cache;
static GHashTable *iconv_open_hash;
static unsigned int iconv_cache_size = 0;
#ifdef G_THREADS_ENABLED
static GStaticMutex iconv_cache_lock = G_STATIC_MUTEX_INIT;
#define ICONV_CACHE_LOCK() g_static_mutex_lock (&iconv_cache_lock)
#define ICONV_CACHE_UNLOCK() g_static_mutex_unlock (&iconv_cache_lock)
#else
#define ICONV_CACHE_LOCK()
#define ICONV_CACHE_UNLOCK()
#endif /* G_THREADS_ENABLED */
/* caller *must* hold the iconv_cache_lock to call any of the following functions */
/**
* iconv_cache_bucket_new:
* @key: cache key
* @cd: iconv descriptor
*
* Creates a new cache bucket, inserts it into the cache and
* increments the cache size.
*
* Returns a pointer to the newly allocated cache bucket.
**/
static struct _iconv_cache_bucket *
iconv_cache_bucket_new (const char *key, iconv_t cd)
{
struct _iconv_cache_bucket *bucket;
bucket = e_memchunk_alloc (cache_chunk);
bucket->next = NULL;
bucket->prev = NULL;
bucket->key = g_strdup (key);
bucket->refcount = 1;
bucket->used = TRUE;
bucket->cd = cd;
g_hash_table_insert (iconv_cache, bucket->key, bucket);
/* FIXME: Since iconv_cache_expire_unused() traverses the list
from head to tail, perhaps it might be better to append new
nodes rather than prepending? This way older cache buckets
expire first? */
bucket->next = iconv_cache_buckets;
iconv_cache_buckets = bucket;
iconv_cache_size++;
return bucket;
}
/**
* iconv_cache_bucket_expire:
* @bucket: cache bucket
*
* Expires a single cache bucket @bucket. This should only ever be
* called on a bucket that currently has no used iconv descriptors
* open.
**/
static void
iconv_cache_bucket_expire (struct _iconv_cache_bucket *bucket)
{
g_hash_table_remove (iconv_cache, bucket->key);
if (bucket->prev) {
bucket->prev->next = bucket->next;
if (bucket->next)
bucket->next->prev = bucket->prev;
} else {
iconv_cache_buckets = bucket->next;
if (bucket->next)
bucket->next->prev = NULL;
}
g_free (bucket->key);
iconv_close (bucket->cd);
e_memchunk_free (cache_chunk, bucket);
iconv_cache_size--;
}
/**
* iconv_cache_expire_unused:
*
* Expires as many unused cache buckets as it needs to in order to get
* the total number of buckets < ICONV_CACHE_SIZE.
**/
static void
iconv_cache_expire_unused (void)
{
struct _iconv_cache_bucket *bucket, *next;
bucket = iconv_cache_buckets;
while (bucket && iconv_cache_size >= ICONV_CACHE_SIZE) {
next = bucket->next;
if (bucket->refcount == 0)
iconv_cache_bucket_expire (bucket);
bucket = next;
}
}
void
camel_iconv_shutdown (void)
{
struct _iconv_cache_bucket *bucket, *next;
bucket = iconv_cache_buckets;
while (bucket) {
next = bucket->next;
g_free (bucket->key);
g_iconv_close (bucket->cd);
e_memchunk_free (cache_chunk, bucket);
bucket = next;
}
g_hash_table_destroy (iconv_cache);
g_hash_table_destroy (iconv_open_hash);
e_memchunk_destroy (cache_chunk);
}
/**
* camel_iconv_init:
*
* Initialize Camel's iconv cache. This *MUST* be called before any
* camel-iconv interfaces will work correctly.
**/
void
camel_iconv_init (void)
{
static int initialized = FALSE;
if (initialized)
return;
iconv_cache_buckets = NULL;
iconv_cache = g_hash_table_new (g_str_hash, g_str_equal);
iconv_open_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
cache_chunk = e_memchunk_new (ICONV_CACHE_SIZE, sizeof (struct _iconv_cache_bucket));
initialized = TRUE;
}
/**
* camel_iconv_open:
* @to: charset to convert to
* @from: charset to convert from
*
* Allocates a coversion descriptor suitable for converting byte
* sequences from charset @from to charset @to. The resulting
* descriptor can be used with iconv (or the camel_iconv wrapper) any
* number of times until closed using camel_iconv_close.
*
* Returns a new conversion descriptor for use with iconv on success
* or (iconv_t) -1 on fail as well as setting an appropriate errno
* value.
**/
iconv_t
camel_iconv_open (const char *to, const char *from)
{
struct _iconv_cache_bucket *bucket;
iconv_t cd;
char *key;
if (from == NULL || to == NULL) {
errno = EINVAL;
return (iconv_t) -1;
}
if (!strcasecmp (from, "x-unknown"))
from = camel_charset_locale_name ();
/* Even tho g_iconv_open will find the appropriate charset
* format(s) for the to/from charset strings, we still convert
* them to their canonical format here so that our key is in a
* standard format */
from = camel_charset_canonical_name (from);
to = camel_charset_canonical_name (to);
key = g_alloca (strlen (from) + strlen (to) + 2);
sprintf (key, "%s:%s", from, to);
ICONV_CACHE_LOCK ();
bucket = g_hash_table_lookup (iconv_cache, key);
if (bucket) {
if (bucket->used) {
cd = g_iconv_open (to, from);
if (cd == (iconv_t) -1)
goto exception;
} else {
/* Apparently iconv on Solaris <= 7 segfaults if you pass in
* NULL for anything but inbuf; work around that. (NULL outbuf
* or NULL *outbuf is allowed by Unix98.)
*/
size_t inleft = 0, outleft = 0;
char *outbuf = NULL;
cd = bucket->cd;
bucket->used = TRUE;
/* reset the descriptor */
g_iconv (cd, NULL, &inleft, &outbuf, &outleft);
}
bucket->refcount++;
} else {
cd = g_iconv_open (to, from);
if (cd == (iconv_t) -1)
goto exception;
iconv_cache_expire_unused ();
bucket = iconv_cache_bucket_new (key, cd);
}
g_hash_table_insert (iconv_open_hash, cd, bucket->key);
ICONV_CACHE_UNLOCK ();
return cd;
exception:
ICONV_CACHE_UNLOCK ();
if (errno == EINVAL)
g_warning ("Conversion from '%s' to '%s' is not supported", from, to);
else
g_warning ("Could not open converter from '%s' to '%s': %s",
from, to, g_strerror (errno));
return cd;
}
/**
* camel_iconv:
* @cd: conversion descriptor
* @inbuf: address of input buffer
* @inleft: input bytes left
* @outbuf: address of output buffer
* @outleft: output bytes left
*
* Read `man 3 iconv`
**/
size_t
camel_iconv (iconv_t cd, const char **inbuf, size_t *inleft, char **outbuf, size_t *outleft)
{
return iconv (cd, (ICONV_CONST char **) inbuf, inleft, outbuf, outleft);
}
/**
* camel_iconv_close:
* @cd: iconv conversion descriptor
*
* Closes the iconv descriptor @cd.
*
* Returns 0 on success or -1 on fail as well as setting an
* appropriate errno value.
**/
int
camel_iconv_close (iconv_t cd)
{
struct _iconv_cache_bucket *bucket;
const char *key;
if (cd == (iconv_t) -1)
return 0;
ICONV_CACHE_LOCK ();
key = g_hash_table_lookup (iconv_open_hash, cd);
if (key) {
g_hash_table_remove (iconv_open_hash, cd);
bucket = g_hash_table_lookup (iconv_cache, key);
g_assert (bucket);
bucket->refcount--;
if (cd == bucket->cd)
bucket->used = FALSE;
else
g_iconv_close (cd);
if (!bucket->refcount && iconv_cache_size > ICONV_CACHE_SIZE) {
/* expire this cache bucket */
iconv_cache_bucket_expire (bucket);
}
} else {
ICONV_CACHE_UNLOCK ();
g_warning ("This iconv context wasn't opened using camel_iconv_open()");
return g_iconv_close (cd);
}
ICONV_CACHE_UNLOCK ();
return 0;
}

48
camel/camel-iconv.h Normal file
View File

@ -0,0 +1,48 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Authors: Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright 2003 Ximian, Inc. (www.ximian.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __CAMEL_ICONV_H__
#define __CAMEL_ICONV_H__
#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus */
#include <sys/types.h>
#include <iconv.h>
void camel_iconv_init (void);
void camel_iconv_shutdown (void);
iconv_t camel_iconv_open (const char *to, const char *from);
size_t camel_iconv (iconv_t cd, const char **inbuf, size_t *inleft, char **outbuf, size_t *outleft);
int camel_iconv_close (iconv_t cd);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __CAMEL_ICONV_H__ */

View File

@ -20,15 +20,16 @@
*/
#include <iconv.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <gal/util/e-iconv.h>
#include "camel-mime-filter-charset.h"
#include "camel-charset-map.h"
#include "camel-iconv.h"
#define d(x)
@ -63,8 +64,8 @@ camel_mime_filter_charset_finalize(CamelObject *o)
g_free(f->from);
g_free(f->to);
if (f->ic != (iconv_t)-1) {
e_iconv_close(f->ic);
if (f->ic != (iconv_t) -1) {
camel_iconv_close (f->ic);
f->ic = (iconv_t) -1;
}
}
@ -76,11 +77,11 @@ reset(CamelMimeFilter *mf)
char buf[16];
char *buffer;
size_t outlen = 16;
/* what happens with the output bytes if this resets the state? */
if (f->ic != (iconv_t) -1) {
buffer = buf;
e_iconv(f->ic, NULL, 0, &buffer, &outlen);
camel_iconv (f->ic, NULL, 0, &buffer, &outlen);
}
}
@ -104,7 +105,7 @@ complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out,
if (inleft > 0) {
do {
converted = e_iconv (charset->ic, &inbuf, &inleft, &outbuf, &outleft);
converted = camel_iconv (charset->ic, &inbuf, &inleft, &outbuf, &outleft);
if (converted == (size_t) -1) {
if (errno == E2BIG) {
/*
@ -144,7 +145,7 @@ complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out,
}
/* flush the iconv conversion */
e_iconv (charset->ic, NULL, NULL, &outbuf, &outleft);
camel_iconv (charset->ic, NULL, NULL, &outbuf, &outleft);
*out = mf->outbuf;
*outlen = mf->outsize - outleft;
@ -178,7 +179,7 @@ filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, s
inleft = len;
do {
converted = e_iconv (charset->ic, &inbuf, &inleft, &outbuf, &outleft);
converted = camel_iconv (charset->ic, &inbuf, &inleft, &outbuf, &outleft);
if (converted == (size_t) -1) {
if (errno == E2BIG || errno == EINVAL)
break;
@ -248,19 +249,21 @@ camel_mime_filter_charset_init (CamelMimeFilterCharset *obj)
CamelMimeFilterCharset *
camel_mime_filter_charset_new (void)
{
CamelMimeFilterCharset *new = CAMEL_MIME_FILTER_CHARSET (camel_object_new (camel_mime_filter_charset_get_type ()));
return new;
return CAMEL_MIME_FILTER_CHARSET (camel_object_new (camel_mime_filter_charset_get_type ()));
}
CamelMimeFilterCharset *
camel_mime_filter_charset_new_convert (const char *from_charset, const char *to_charset)
{
CamelMimeFilterCharset *new = CAMEL_MIME_FILTER_CHARSET (camel_object_new (camel_mime_filter_charset_get_type ()));
CamelMimeFilterCharset *new;
new->ic = e_iconv_open (to_charset, from_charset);
new = CAMEL_MIME_FILTER_CHARSET (camel_object_new (camel_mime_filter_charset_get_type ()));
new->ic = camel_iconv_open (to_charset, from_charset);
if (new->ic == (iconv_t) -1) {
g_warning ("Cannot create charset conversion from %s to %s: %s", from_charset, to_charset, strerror (errno));
camel_object_unref ((CamelObject *)new);
g_warning ("Cannot create charset conversion from %s to %s: %s",
from_charset, to_charset, g_strerror (errno));
camel_object_unref (new);
new = NULL;
} else {
new->from = g_strdup (from_charset);

View File

@ -30,11 +30,9 @@
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <gal/util/e-iconv.h>
#include <errno.h>
#include "camel-charset-map.h"
#include "camel-mime-message.h"
#include "camel-multipart.h"
#include "camel-stream-mem.h"
@ -544,9 +542,10 @@ process_header (CamelMedium *medium, const char *header_name, const char *header
break;
case HEADER_SUBJECT:
g_free (message->subject);
if (((CamelMimePart *)message)->content_type)
charset = e_iconv_charset_name(header_content_type_param(((CamelMimePart *)message)->content_type, "charset"));
else
if (((CamelMimePart *) message)->content_type) {
charset = header_content_type_param (((CamelMimePart *) message)->content_type, "charset");
charset = camel_charset_canonical_name (charset);
} else
charset = NULL;
message->subject = g_strstrip (header_decode_string (header_value, charset));
break;

View File

@ -31,10 +31,11 @@
#include <unistd.h>
#include <errno.h>
#include <gal/util/e-iconv.h>
#include <glib/gunicode.h>
#include "string-utils.h"
#include "camel-iconv.h"
#include "camel-charset-map.h"
#include "camel-mime-part-utils.h"
#include "camel-mime-message.h"
#include "camel-multipart.h"
@ -49,7 +50,6 @@
#include "camel-mime-filter-crlf.h"
#include "camel-mime-filter-save.h"
#include "camel-html-parser.h"
#include "camel-charset-map.h"
#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))
#include <stdio.h>*/
@ -87,7 +87,7 @@ check_html_charset(char *buffer, int length)
&& (val = camel_html_parser_attr(hp, "content"))
&& (ct = header_content_type_decode(val))) {
charset = header_content_type_param(ct, "charset");
charset = e_iconv_charset_name (charset);
charset = camel_charset_canonical_name (charset);
header_content_type_unref(ct);
}
break;
@ -97,7 +97,7 @@ check_html_charset(char *buffer, int length)
}
} while (charset == NULL && state != CAMEL_HTML_PARSER_EOF);
camel_object_unref((CamelObject *)hp);
camel_object_unref (hp);
return charset;
}
@ -113,12 +113,12 @@ convert_buffer (GByteArray *in, const char *to, const char *from)
if (in->len == 0)
return g_byte_array_new();
d(printf("converting buffer from %s to %s:\n", from, to));
d(fwrite(in->data, 1, (int)in->len, stdout));
d(printf("\n"));
cd = e_iconv_open(to, from);
cd = camel_iconv_open(to, from);
if (cd == (iconv_t) -1) {
g_warning ("Cannot convert from '%s' to '%s': %s", from, to, strerror (errno));
return NULL;
@ -135,7 +135,7 @@ convert_buffer (GByteArray *in, const char *to, const char *from)
outbuf = out->data + converted;
outleft = outlen - converted;
converted = e_iconv (cd, &inbuf, &inleft, &outbuf, &outleft);
converted = camel_iconv (cd, &inbuf, &inleft, &outbuf, &outleft);
if (converted == (size_t) -1) {
if (errno != E2BIG && errno != EINVAL)
goto fail;
@ -164,17 +164,17 @@ convert_buffer (GByteArray *in, const char *to, const char *from)
*/
/* flush the iconv conversion */
e_iconv (cd, NULL, NULL, &outbuf, &outleft);
camel_iconv (cd, NULL, NULL, &outbuf, &outleft);
/* now set the true length on the GByteArray */
converted = outbuf - (char *)out->data;
g_byte_array_set_size (out, converted);
d(printf("converted data:\n"));
d(fwrite(out->data, 1, (int)out->len, stdout));
d(printf("\n"));
e_iconv_close (cd);
camel_iconv_close (cd);
return out;
@ -183,7 +183,7 @@ convert_buffer (GByteArray *in, const char *to, const char *from)
g_byte_array_free (out, TRUE);
e_iconv_close (cd);
camel_iconv_close (cd);
return NULL;
}
@ -262,7 +262,7 @@ simple_data_wrapper_construct_from_parser (CamelDataWrapper *dw, CamelMimeParser
ct = camel_mime_parser_content_type (mp);
if (header_content_type_is (ct, "text", "*")) {
charset = header_content_type_param (ct, "charset");
charset = e_iconv_charset_name (charset);
charset = camel_charset_canonical_name (charset);
if (fdec) {
d(printf ("Adding CRLF conversion filter\n"));
@ -313,10 +313,8 @@ simple_data_wrapper_construct_from_parser (CamelDataWrapper *dw, CamelMimeParser
*/
if (!strncasecmp (charset, "iso-8859", 8)) {
/* check for Windows-specific chars... */
if (broken_windows_charset (buffer, charset)) {
if (broken_windows_charset (buffer, charset))
charset = camel_charset_iso_to_windows (charset);
charset = e_iconv_charset_name (charset);
}
}
out = convert_buffer (buffer, "UTF-8", charset);

View File

@ -29,11 +29,8 @@
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <gal/util/e-iconv.h>
#include "camel-mime-parser.h"
#include "camel-stream-mem.h"
#include "camel-stream-filter.h"
@ -223,9 +220,10 @@ process_header(CamelMedium *medium, const char *header_name, const char *header_
switch (header_type) {
case HEADER_DESCRIPTION: /* raw header->utf8 conversion */
g_free (mime_part->description);
if (mime_part->content_type)
charset = e_iconv_charset_name(header_content_type_param(mime_part->content_type, "charset"));
else
if (mime_part->content_type) {
charset = header_content_type_param (mime_part->content_type, "charset");
charset = camel_charset_canonical_name (charset);
} else
charset = NULL;
mime_part->description = g_strstrip (header_decode_string (header_value, charset));
break;

View File

@ -39,8 +39,6 @@
#define MAXHOSTNAMELEN 1024
#endif
#include <iconv.h>
#include <time.h>
#include <ctype.h>
@ -49,9 +47,9 @@
#include <glib.h>
#include <glib/gunicode.h>
#include <gal/util/e-iconv.h>
#include "e-time-utils.h"
#include "camel-iconv.h"
#include "camel-mime-utils.h"
#include "camel-charset-map.h"
#include "camel-service.h" /* for camel_gethostbyname() */
@ -1051,7 +1049,7 @@ rfc2047_decode_word(const char *in, size_t len)
if (p)
*p = '\0';
charset = e_iconv_charset_name (encname);
charset = camel_charset_canonical_name (encname);
inbuf = decword;
@ -1060,21 +1058,21 @@ rfc2047_decode_word(const char *in, size_t len)
outbuf = outbase;
retry:
ic = e_iconv_open ("UTF-8", charset);
ic = camel_iconv_open ("UTF-8", charset);
if (ic != (iconv_t) -1) {
ret = e_iconv (ic, &inbuf, &inlen, &outbuf, &outlen);
ret = camel_iconv (ic, &inbuf, &inlen, &outbuf, &outlen);
if (ret != (size_t) -1) {
e_iconv (ic, NULL, 0, &outbuf, &outlen);
camel_iconv (ic, NULL, 0, &outbuf, &outlen);
*outbuf = 0;
decoded = g_strdup (outbase);
}
e_iconv_close (ic);
camel_iconv_close (ic);
} else {
w(g_warning ("Cannot decode charset, header display may be corrupt: %s: %s",
charset, strerror (errno)));
if (!retried) {
charset = e_iconv_locale_charset ();
charset = camel_charset_locale_name ();
if (!charset)
charset = "iso-8859-1";
@ -1122,24 +1120,24 @@ append_8bit (GString *out, const char *inbuf, size_t inlen, const char *charset)
size_t outlen;
iconv_t ic;
ic = e_iconv_open ("UTF-8", charset);
ic = camel_iconv_open ("UTF-8", charset);
if (ic == (iconv_t) -1)
return FALSE;
outlen = inlen * 6 + 16;
outbuf = outbase = g_malloc(outlen);
if (e_iconv(ic, &inbuf, &inlen, &outbuf, &outlen) == (size_t) -1) {
if (camel_iconv (ic, &inbuf, &inlen, &outbuf, &outlen) == (size_t) -1) {
w(g_warning("Conversion to '%s' failed: %s", charset, strerror (errno)));
g_free(outbase);
e_iconv_close(ic);
camel_iconv_close (ic);
return FALSE;
}
*outbuf = 0;
g_string_append(out, outbase);
g_free(outbase);
e_iconv_close(ic);
camel_iconv_close (ic);
return TRUE;
@ -1152,9 +1150,9 @@ header_decode_text (const char *in, size_t inlen, const char *default_charset)
GString *out;
const char *inptr, *inend, *start, *chunk, *locale_charset;
char *dword = NULL;
locale_charset = e_iconv_locale_charset();
locale_charset = camel_charset_locale_name ();
out = g_string_new("");
inptr = in;
inend = inptr + inlen;
@ -1233,7 +1231,7 @@ rfc2047_encode_word(GString *outstring, const char *in, size_t len, const char *
ascii = alloca (bufflen);
if (strcasecmp (type, "UTF-8") != 0)
ic = e_iconv_open (type, "UTF-8");
ic = camel_iconv_open (type, "UTF-8");
while (inlen) {
size_t convlen, proclen;
@ -1281,13 +1279,13 @@ rfc2047_encode_word(GString *outstring, const char *in, size_t len, const char *
hopefully-small-enough chunks, and leave it at that */
convlen = MIN(inlen, CAMEL_FOLD_PREENCODED);
p = inptr;
if (e_iconv (ic, &inptr, &convlen, &out, &outlen) == (size_t) -1) {
if (camel_iconv (ic, &inptr, &convlen, &out, &outlen) == (size_t) -1) {
w(g_warning("Conversion problem: conversion truncated: %s", strerror (errno)));
/* blah, we include it anyway, better than infinite loop ... */
inptr = p + convlen;
} else {
/* make sure we flush out any shift state */
e_iconv(ic, NULL, 0, &out, &outlen);
camel_iconv (ic, NULL, 0, &out, &outlen);
}
inlen -= (inptr - p);
}
@ -1312,7 +1310,7 @@ rfc2047_encode_word(GString *outstring, const char *in, size_t len, const char *
}
if (ic != (iconv_t) -1)
e_iconv_close(ic);
camel_iconv_close (ic);
}
@ -1869,7 +1867,7 @@ rfc2184_decode (const char *in, size_t len)
return NULL;
encoding = g_strndup (in, inptr - in);
charset = e_iconv_charset_name (encoding);
charset = camel_charset_canonical_name (encoding);
g_free (encoding);
inptr = memchr (inptr + 1, '\'', inend - inptr - 1);
@ -1886,22 +1884,22 @@ rfc2184_decode (const char *in, size_t len)
inbuf = decword = hex_decode (inptr, inend - inptr);
inlen = strlen (inbuf);
ic = e_iconv_open ("UTF-8", charset);
ic = camel_iconv_open ("UTF-8", charset);
if (ic != (iconv_t) -1) {
size_t ret;
outlen = inlen * 6 + 16;
outbuf = outbase = g_malloc (outlen);
ret = e_iconv (ic, &inbuf, &inlen, &outbuf, &outlen);
ret = camel_iconv (ic, &inbuf, &inlen, &outbuf, &outlen);
if (ret != (size_t) -1) {
e_iconv (ic, NULL, 0, &outbuf, &outlen);
camel_iconv (ic, NULL, 0, &outbuf, &outlen);
*outbuf = '\0';
g_free (decoded);
decoded = outbase;
}
e_iconv_close (ic);
camel_iconv_close (ic);
} else {
decoded = decword;
}
@ -2041,21 +2039,21 @@ header_decode_param (const char **in, char **paramp, char **valuep, int *is_rfc2
inbuf = value;
inlen = strlen (inbuf);
charset = e_iconv_locale_charset ();
ic = e_iconv_open ("UTF-8", charset ? charset : "ISO-8859-1");
charset = camel_charset_locale_name ();
ic = camel_iconv_open ("UTF-8", charset ? charset : "ISO-8859-1");
if (ic != (iconv_t) -1) {
size_t ret;
outlen = inlen * 6 + 16;
outbuf = outbase = g_malloc (outlen);
ret = e_iconv (ic, &inbuf, &inlen, &outbuf, &outlen);
ret = camel_iconv (ic, &inbuf, &inlen, &outbuf, &outlen);
if (ret != (size_t) -1) {
e_iconv (ic, NULL, 0, &outbuf, &outlen);
camel_iconv (ic, NULL, 0, &outbuf, &outlen);
*outbuf = '\0';
}
e_iconv_close (ic);
camel_iconv_close (ic);
g_free (value);
value = outbase;
@ -2970,7 +2968,7 @@ header_encode_param (const unsigned char *in, gboolean *encoded)
charset = "iso-8859-1";
if (strcasecmp (charset, "UTF-8") != 0)
cd = e_iconv_open (charset, "UTF-8");
cd = camel_iconv_open (charset, "UTF-8");
if (cd == (iconv_t) -1) {
charset = "UTF-8";
@ -2986,13 +2984,13 @@ header_encode_param (const unsigned char *in, gboolean *encoded)
outptr = outbuf = g_malloc (outleft);
inbuf = in;
if (e_iconv (cd, &inbuf, &inleft, &outptr, &outleft) == (size_t) -1) {
if (camel_iconv (cd, &inbuf, &inleft, &outptr, &outleft) == (size_t) -1) {
w(g_warning ("Conversion problem: conversion truncated: %s", strerror (errno)));
} else {
e_iconv (cd, NULL, 0, &outptr, &outleft);
camel_iconv (cd, NULL, 0, &outptr, &outleft);
}
e_iconv_close (cd);
camel_iconv_close (cd);
inptr = outbuf;
inend = outptr;

View File

@ -28,12 +28,13 @@
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <iconv.h>
#include "camel-sasl-digest-md5.h"
#include "camel-mime-utils.h"
#include "camel-charset-map.h"
#include <e-util/md5-utils.h>
#include <gal/util/e-iconv.h>
#include "camel-iconv.h"
#include "camel-charset-map.h"
#include "camel-mime-utils.h"
#include "camel-sasl-digest-md5.h"
#define d(x)
@ -695,21 +696,21 @@ digest_response (struct _DigestResponse *resp)
char *username, *outbuf;
const char *charset;
size_t len, outlen;
const char *buf;
const char *inbuf;
iconv_t cd;
charset = e_iconv_locale_charset();
charset = camel_charset_locale_name ();
if (!charset)
charset = "iso-8859-1";
cd = e_iconv_open (resp->charset, charset);
cd = camel_iconv_open (resp->charset, charset);
len = strlen (resp->username);
outlen = 2 * len; /* plenty of space */
outbuf = username = g_malloc0 (outlen + 1);
buf = resp->username;
if (cd == (iconv_t) -1 || e_iconv (cd, &buf, &len, &outbuf, &outlen) == (size_t) -1) {
inbuf = resp->username;
if (cd == (iconv_t) -1 || camel_iconv (cd, &inbuf, &len, &outbuf, &outlen) == (size_t) -1) {
/* We can't convert to UTF-8 - pretend we never got a charset param? */
g_free (resp->charset);
resp->charset = NULL;
@ -720,7 +721,7 @@ digest_response (struct _DigestResponse *resp)
}
if (cd != (iconv_t) -1)
e_iconv_close (cd);
camel_iconv_close (cd);
g_byte_array_append (buffer, username, strlen (username));
g_free (username);

View File

@ -29,6 +29,7 @@
#include <config.h>
#endif
#include <glib.h>
#include <sys/types.h>
#include <regex.h>
#include <string.h>
@ -225,7 +226,7 @@ camel_ustrstrcase (const char *haystack, const char *needle)
if (strlen (haystack) == 0)
return NULL;
puni = nuni = alloca (sizeof (gunichar) * strlen (needle));
puni = nuni = g_alloca (sizeof (gunichar) * strlen (needle));
p = needle;
while ((u = utf8_get (&p)))
@ -419,12 +420,12 @@ camel_search_header_match (const char *value, const char *match, camel_search_ma
vdom = strchr(value, '@');
mdom = strchr(match, '@');
if (mdom == NULL && vdom != NULL) {
v = alloca(vdom-value+1);
v = g_alloca(vdom-value+1);
memcpy(v, value, vdom-value);
v[vdom-value] = 0;
value = (char *)v;
} else if (mdom != NULL && vdom == NULL) {
v = alloca(mdom-match+1);
v = g_alloca(mdom-match+1);
memcpy(v, match, mdom-match);
v[mdom-match] = 0;
match = (char *)v;

View File

@ -36,6 +36,7 @@
#endif /* HAVE_NSS */
#include "camel.h"
#include "camel-iconv.h"
#include "camel-certdb.h"
#include "camel-mime-utils.h"
@ -57,6 +58,8 @@ camel_shutdown (void)
camel_certdb_save (certdb);
camel_object_unref (certdb);
}
camel_iconv_shutdown ();
}
gint
@ -79,7 +82,9 @@ camel_init (const char *configdir, gboolean nss_init)
/* initialise global camel_object_type */
camel_object_get_type();
camel_mime_utils_init();
camel_iconv_init ();
camel_mime_utils_init ();
#ifdef HAVE_NSS
if (nss_init) {