#include "config.h"
#include "libutil/mem_pool.h"
#include "libutil/regexp.h"
+#include "libutil/hash.h"
#include "libserver/task.h"
#include "mime_encoding.h"
#include "message.h"
#define RSPAMD_CHARSET_FLAG_UTF (1 << 0)
#define RSPAMD_CHARSET_FLAG_ASCII (1 << 1)
+#define RSPAMD_CHARSET_CACHE_SIZE 32
+
#define SET_PART_RAW(part) ((part)->flags &= ~RSPAMD_MIME_TEXT_PART_FLAG_UTF)
#define SET_PART_UTF(part) ((part)->flags |= RSPAMD_MIME_TEXT_PART_FLAG_UTF)
return g_quark_from_static_string ("iconv error");
}
+static UConverter *
+rspamd_mime_get_converter_cached (const gchar *enc, UErrorCode *err)
+{
+ const gchar *canon_name;
+ static rspamd_lru_hash_t *cache;
+ UConverter *conv;
+
+ if (cache == NULL) {
+ cache = rspamd_lru_hash_new_full (RSPAMD_CHARSET_CACHE_SIZE, g_free,
+ (GDestroyNotify)ucnv_close, rspamd_str_hash,
+ rspamd_str_equal);
+ }
+
+ canon_name = ucnv_getStandardName (enc, "IANA", err);
+
+ if (canon_name == NULL) {
+ return NULL;
+ }
+
+ conv = rspamd_lru_hash_lookup (cache, (gpointer)canon_name, 0);
+
+ if (conv == NULL) {
+ conv = ucnv_open (canon_name, err);
+
+ if (conv != NULL) {
+ ucnv_setToUCallBack (conv,
+ UCNV_TO_U_CALLBACK_SUBSTITUTE,
+ UCNV_SUB_STOP_ON_ILLEGAL,
+ NULL,
+ NULL,
+ err);
+ rspamd_lru_hash_insert (cache, g_strdup (canon_name), conv, 0, 0);
+ }
+ }
+
+ return conv;
+}
+
static void
rspamd_mime_encoding_substitute_init (void)
{
&uc_err);
}
- conv = ucnv_open (in_enc, &uc_err);
+ conv = rspamd_mime_get_converter_cached (in_enc, &uc_err);
if (conv == NULL) {
g_set_error (err, rspamd_iconv_error_quark (), EINVAL,
return NULL;
}
- ucnv_setToUCallBack (conv,
- UCNV_TO_U_CALLBACK_SUBSTITUTE,
- UCNV_SUB_STOP_ON_ILLEGAL,
- NULL,
- NULL,
- &uc_err);
-
tmp_buf = g_new (UChar, len + 1);
uc_err = U_ZERO_ERROR;
r = ucnv_toUChars (conv, tmp_buf, len + 1, input, len, &uc_err);
"cannot convert data to unicode from %s: %s",
in_enc, u_errorName (uc_err));
g_free (tmp_buf);
- ucnv_close (conv);
return NULL;
}
"cannot convert data from unicode from %s: %s",
in_enc, u_errorName (uc_err));
g_free (tmp_buf);
- ucnv_close (conv);
return NULL;
}
msg_info_pool ("converted from %s to UTF-8 inlen: %z, outlen: %d",
in_enc, len, r);
g_free (tmp_buf);
- ucnv_close (conv);
if (olen) {
*olen = r;
&uc_err);
}
- conv = ucnv_open (enc, &uc_err);
+ conv = rspamd_mime_get_converter_cached (enc, &uc_err);
if (conv == NULL) {
return FALSE;
}
- ucnv_setToUCallBack (conv,
- UCNV_TO_U_CALLBACK_SUBSTITUTE,
- UCNV_SUB_STOP_ON_ILLEGAL,
- NULL,
- NULL,
- &uc_err);
-
tmp_buf = g_new (UChar, in->len + 1);
uc_err = U_ZERO_ERROR;
r = ucnv_toUChars (conv, tmp_buf, in->len + 1, in->data, in->len, &uc_err);
if (uc_err != U_ZERO_ERROR) {
g_free (tmp_buf);
- ucnv_close (conv);
return FALSE;
}
if (uc_err != U_ZERO_ERROR) {
g_free (tmp_buf);
- ucnv_close (conv);
return FALSE;
}
g_free (tmp_buf);
- ucnv_close (conv);
out->len = r;
return TRUE;