diff options
author | hiro <hiro@ee746299-78ed-0310-b773-934348b2243d> | 2005-08-31 06:10:31 +0000 |
---|---|---|
committer | hiro <hiro@ee746299-78ed-0310-b773-934348b2243d> | 2005-08-31 06:10:31 +0000 |
commit | f36577b27b6f352f140cf1f25755d39661bd4072 (patch) | |
tree | 664d196337dc86ddafc6218c8c9f19055e22e155 /src | |
parent | 6ae811ae5e6a0463dadc9ebb6f833dc5154700bd (diff) |
made some core modules library (libsylph).
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@528 ee746299-78ed-0310-b773-934348b2243d
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 18 | ||||
-rw-r--r-- | src/base64.c | 168 | ||||
-rw-r--r-- | src/base64.h | 46 | ||||
-rw-r--r-- | src/codeconv.c | 1982 | ||||
-rw-r--r-- | src/codeconv.h | 239 | ||||
-rw-r--r-- | src/prefs.c | 465 | ||||
-rw-r--r-- | src/prefs.h | 80 | ||||
-rw-r--r-- | src/quoted-printable.c | 232 | ||||
-rw-r--r-- | src/quoted-printable.h | 36 | ||||
-rw-r--r-- | src/session.c | 793 | ||||
-rw-r--r-- | src/session.h | 205 | ||||
-rw-r--r-- | src/socket.c | 1397 | ||||
-rw-r--r-- | src/socket.h | 124 | ||||
-rw-r--r-- | src/ssl.c | 175 | ||||
-rw-r--r-- | src/ssl.h | 58 | ||||
-rw-r--r-- | src/stringtable.c | 163 | ||||
-rw-r--r-- | src/stringtable.h | 38 | ||||
-rw-r--r-- | src/unmime.c | 134 | ||||
-rw-r--r-- | src/unmime.h | 27 | ||||
-rw-r--r-- | src/utils.c | 3436 | ||||
-rw-r--r-- | src/utils.h | 493 | ||||
-rw-r--r-- | src/uuencode.c | 101 | ||||
-rw-r--r-- | src/uuencode.h | 24 | ||||
-rw-r--r-- | src/xml.c | 656 | ||||
-rw-r--r-- | src/xml.h | 108 |
25 files changed, 4 insertions, 11194 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 5da41db1..b81e23cf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,7 +26,6 @@ sylpheed_SOURCES = \ gtkshruler.c gtkshruler.h \ menu.c menu.h \ stock_pixmap.c stock_pixmap.h \ - prefs.c prefs.h \ prefs_ui.c prefs_ui.h \ prefs_common.c prefs_common.h \ prefs_filter.c prefs_filter.h \ @@ -76,17 +75,8 @@ sylpheed_SOURCES = \ grouplistdialog.c grouplistdialog.h \ about.c about.h \ setup.c setup.h \ - utils.c utils.h \ gtkutils.c gtkutils.h \ - codeconv.c codeconv.h \ - unmime.c unmime.h \ - base64.c base64.h \ - quoted-printable.c quoted-printable.h \ - uuencode.c uuencode.h \ md5.c md5.h \ - socket.c socket.h \ - ssl.c ssl.h \ - session.c session.h \ smtp.c smtp.h \ pop.c pop.h \ mh.c mh.h \ @@ -99,7 +89,6 @@ sylpheed_SOURCES = \ nntp.c nntp.h \ news.c news.h \ imap.c imap.h \ - xml.c xml.h \ html.c html.h \ procmime.c procmime.h \ rfc2015.c rfc2015.h \ @@ -108,7 +97,6 @@ sylpheed_SOURCES = \ sigstatus.c sigstatus.h \ simple-gettext.c \ manual.c manual.h \ - stringtable.c stringtable.h \ eggtrayicon.c eggtrayicon.h \ trayicon.c trayicon.h \ quote_fmt_lex.l quote_fmt_lex.h \ @@ -132,14 +120,16 @@ INCLUDES = \ $(GTK_CFLAGS) \ $(GDK_PIXBUF_CFLAGS) \ $(GPGME_CFLAGS) \ - -I$(includedir) + -I$(includedir) \ + -I$(top_srcdir)/libsylph sylpheed_LDADD = \ $(INTLLIBS) \ $(GTK_LIBS) \ $(GPGME_LIBS) \ $(LDAP_LIBS) \ - $(LIBICONV) + $(LIBICONV) \ + ../libsylph/libsylph.la AM_CPPFLAGS = \ -DLOCALEDIR=\""$(localedir)"\" \ diff --git a/src/base64.c b/src/base64.c deleted file mode 100644 index 484cd286..00000000 --- a/src/base64.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2002 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <glib.h> -#include <ctype.h> -#include <string.h> - -#include "base64.h" - -static const gchar base64char[64] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -static const gchar base64val[128] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 -}; - -#define BASE64VAL(c) (isascii((guchar)c) ? base64val[(gint)(c)] : -1) - -void base64_encode(gchar *out, const guchar *in, gint inlen) -{ - const guchar *inp = in; - gchar *outp = out; - - while (inlen >= 3) { - *outp++ = base64char[(inp[0] >> 2) & 0x3f]; - *outp++ = base64char[((inp[0] & 0x03) << 4) | - ((inp[1] >> 4) & 0x0f)]; - *outp++ = base64char[((inp[1] & 0x0f) << 2) | - ((inp[2] >> 6) & 0x03)]; - *outp++ = base64char[inp[2] & 0x3f]; - - inp += 3; - inlen -= 3; - } - - if (inlen > 0) { - *outp++ = base64char[(inp[0] >> 2) & 0x3f]; - if (inlen == 1) { - *outp++ = base64char[(inp[0] & 0x03) << 4]; - *outp++ = '='; - } else { - *outp++ = base64char[((inp[0] & 0x03) << 4) | - ((inp[1] >> 4) & 0x0f)]; - *outp++ = base64char[((inp[1] & 0x0f) << 2)]; - } - *outp++ = '='; - } - - *outp = '\0'; -} - -gint base64_decode(guchar *out, const gchar *in, gint inlen) -{ - const gchar *inp = in; - guchar *outp = out; - gchar buf[4]; - - if (inlen < 0) - inlen = G_MAXINT; - - while (inlen >= 4 && *inp != '\0') { - buf[0] = *inp++; - inlen--; - if (BASE64VAL(buf[0]) == -1) break; - - buf[1] = *inp++; - inlen--; - if (BASE64VAL(buf[1]) == -1) break; - - buf[2] = *inp++; - inlen--; - if (buf[2] != '=' && BASE64VAL(buf[2]) == -1) break; - - buf[3] = *inp++; - inlen--; - if (buf[3] != '=' && BASE64VAL(buf[3]) == -1) break; - - *outp++ = ((BASE64VAL(buf[0]) << 2) & 0xfc) | - ((BASE64VAL(buf[1]) >> 4) & 0x03); - if (buf[2] != '=') { - *outp++ = ((BASE64VAL(buf[1]) & 0x0f) << 4) | - ((BASE64VAL(buf[2]) >> 2) & 0x0f); - if (buf[3] != '=') { - *outp++ = ((BASE64VAL(buf[2]) & 0x03) << 6) | - (BASE64VAL(buf[3]) & 0x3f); - } - } - } - - return outp - out; -} - -Base64Decoder *base64_decoder_new(void) -{ - Base64Decoder *decoder; - - decoder = g_new0(Base64Decoder, 1); - return decoder; -} - -void base64_decoder_free(Base64Decoder *decoder) -{ - g_free(decoder); -} - -gint base64_decoder_decode(Base64Decoder *decoder, - const gchar *in, guchar *out) -{ - gint len, total_len = 0; - gint buf_len; - gchar buf[4]; - - g_return_val_if_fail(decoder != NULL, -1); - g_return_val_if_fail(in != NULL, -1); - g_return_val_if_fail(out != NULL, -1); - - buf_len = decoder->buf_len; - memcpy(buf, decoder->buf, sizeof(buf)); - - for (;;) { - while (buf_len < 4) { - gchar c = *in; - - in++; - if (c == '\0') break; - if (c == '\r' || c == '\n') continue; - if (c != '=' && BASE64VAL(c) == -1) - return -1; - buf[buf_len++] = c; - } - if (buf_len < 4 || buf[0] == '=' || buf[1] == '=') { - decoder->buf_len = buf_len; - memcpy(decoder->buf, buf, sizeof(buf)); - return total_len; - } - len = base64_decode(out, buf, 4); - out += len; - total_len += len; - buf_len = 0; - if (len < 3) { - decoder->buf_len = 0; - return total_len; - } - } -} diff --git a/src/base64.h b/src/base64.h deleted file mode 100644 index 4aa55758..00000000 --- a/src/base64.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2002 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __BASE64_H__ -#define __BASE64_H__ - -#include <glib.h> - -typedef struct _Base64Decoder Base64Decoder; - -struct _Base64Decoder -{ - gint buf_len; - gchar buf[4]; -}; - -void base64_encode (gchar *out, - const guchar *in, - gint inlen); -gint base64_decode (guchar *out, - const gchar *in, - gint inlen); - -Base64Decoder *base64_decoder_new (void); -void base64_decoder_free (Base64Decoder *decoder); -gint base64_decoder_decode (Base64Decoder *decoder, - const gchar *in, - guchar *out); - -#endif /* __BASE64_H__ */ diff --git a/src/codeconv.c b/src/codeconv.c deleted file mode 100644 index 4eb68b78..00000000 --- a/src/codeconv.c +++ /dev/null @@ -1,1982 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "defs.h" - -#include <glib.h> -#include <glib/gi18n.h> -#include <string.h> -#include <ctype.h> -#include <stdlib.h> -#include <errno.h> - -#if HAVE_LOCALE_H -# include <locale.h> -#endif - -#include <iconv.h> - -#include "codeconv.h" -#include "unmime.h" -#include "base64.h" -#include "quoted-printable.h" -#include "utils.h" -#include "prefs_common.h" - -typedef enum -{ - JIS_ASCII, - JIS_KANJI, - JIS_HWKANA, - JIS_AUXKANJI -} JISState; - -#define SUBST_CHAR '_' -#define ESC '\033' - -#define iseuckanji(c) \ - (((c) & 0xff) >= 0xa1 && ((c) & 0xff) <= 0xfe) -#define iseuchwkana1(c) \ - (((c) & 0xff) == 0x8e) -#define iseuchwkana2(c) \ - (((c) & 0xff) >= 0xa1 && ((c) & 0xff) <= 0xdf) -#define iseucaux(c) \ - (((c) & 0xff) == 0x8f) -#define issjiskanji1(c) \ - ((((c) & 0xff) >= 0x81 && ((c) & 0xff) <= 0x9f) || \ - (((c) & 0xff) >= 0xe0 && ((c) & 0xff) <= 0xfc)) -#define issjiskanji2(c) \ - ((((c) & 0xff) >= 0x40 && ((c) & 0xff) <= 0x7e) || \ - (((c) & 0xff) >= 0x80 && ((c) & 0xff) <= 0xfc)) -#define issjishwkana(c) \ - (((c) & 0xff) >= 0xa1 && ((c) & 0xff) <= 0xdf) - -#define K_IN() \ - if (state != JIS_KANJI) { \ - *out++ = ESC; \ - *out++ = '$'; \ - *out++ = 'B'; \ - state = JIS_KANJI; \ - } - -#define K_OUT() \ - if (state != JIS_ASCII) { \ - *out++ = ESC; \ - *out++ = '('; \ - *out++ = 'B'; \ - state = JIS_ASCII; \ - } - -#define HW_IN() \ - if (state != JIS_HWKANA) { \ - *out++ = ESC; \ - *out++ = '('; \ - *out++ = 'I'; \ - state = JIS_HWKANA; \ - } - -#define AUX_IN() \ - if (state != JIS_AUXKANJI) { \ - *out++ = ESC; \ - *out++ = '$'; \ - *out++ = '('; \ - *out++ = 'D'; \ - state = JIS_AUXKANJI; \ - } - -static gchar *conv_jistoeuc(const gchar *inbuf, gint *error); -static gchar *conv_euctojis(const gchar *inbuf, gint *error); -static gchar *conv_sjistoeuc(const gchar *inbuf, gint *error); - -static gchar *conv_jistoutf8(const gchar *inbuf, gint *error); -static gchar *conv_sjistoutf8(const gchar *inbuf, gint *error); -static gchar *conv_euctoutf8(const gchar *inbuf, gint *error); -static gchar *conv_anytoutf8(const gchar *inbuf, gint *error); - -static gchar *conv_utf8toeuc(const gchar *inbuf, gint *error); -static gchar *conv_utf8tojis(const gchar *inbuf, gint *error); - -/* static void conv_unreadable_eucjp(gchar *str); */ -static void conv_unreadable_8bit(gchar *str); -/* static void conv_unreadable_latin(gchar *str); */ - -static gchar *conv_jistodisp(const gchar *inbuf, gint *error); -static gchar *conv_sjistodisp(const gchar *inbuf, gint *error); -static gchar *conv_euctodisp(const gchar *inbuf, gint *error); - -static gchar *conv_anytodisp(const gchar *inbuf, gint *error); -static gchar *conv_ustodisp(const gchar *inbuf, gint *error); -static gchar *conv_noconv(const gchar *inbuf, gint *error); - -static gchar *conv_jistoeuc(const gchar *inbuf, gint *error) -{ - gchar *outbuf; - const guchar *in = (guchar *)inbuf; - guchar *out; - JISState state = JIS_ASCII; - gint error_ = 0; - - outbuf = g_malloc(strlen(inbuf) * 2 + 1); - out = (guchar *)outbuf; - - while (*in != '\0') { - if (*in == ESC) { - in++; - if (*in == '$') { - if (*(in + 1) == '@' || *(in + 1) == 'B') { - state = JIS_KANJI; - in += 2; - } else if (*(in + 1) == '(' && - *(in + 2) == 'D') { - state = JIS_AUXKANJI; - in += 3; - } else { - /* unknown escape sequence */ - error_ = -1; - state = JIS_ASCII; - } - } else if (*in == '(') { - if (*(in + 1) == 'B' || *(in + 1) == 'J') { - state = JIS_ASCII; - in += 2; - } else if (*(in + 1) == 'I') { - state = JIS_HWKANA; - in += 2; - } else { - /* unknown escape sequence */ - error_ = -1; - state = JIS_ASCII; - } - } else { - /* unknown escape sequence */ - error_ = -1; - state = JIS_ASCII; - } - } else if (*in == 0x0e) { - state = JIS_HWKANA; - in++; - } else if (*in == 0x0f) { - state = JIS_ASCII; - in++; - } else { - switch (state) { - case JIS_ASCII: - *out++ = *in++; - break; - case JIS_KANJI: - *out++ = *in++ | 0x80; - if (*in == '\0') break; - *out++ = *in++ | 0x80; - break; - case JIS_HWKANA: - *out++ = 0x8e; - *out++ = *in++ | 0x80; - break; - case JIS_AUXKANJI: - *out++ = 0x8f; - *out++ = *in++ | 0x80; - if (*in == '\0') break; - *out++ = *in++ | 0x80; - break; - } - } - } - - *out = '\0'; - - if (error) - *error = error_; - - return outbuf; -} - -#define JIS_HWDAKUTEN 0x5e -#define JIS_HWHANDAKUTEN 0x5f - -static gint conv_jis_hantozen(guchar *outbuf, guchar jis_code, guchar sound_sym) -{ - static guint16 h2z_tbl[] = { - /* 0x20 - 0x2f */ - 0x0000, 0x2123, 0x2156, 0x2157, 0x2122, 0x2126, 0x2572, 0x2521, - 0x2523, 0x2525, 0x2527, 0x2529, 0x2563, 0x2565, 0x2567, 0x2543, - /* 0x30 - 0x3f */ - 0x213c, 0x2522, 0x2524, 0x2526, 0x2528, 0x252a, 0x252b, 0x252d, - 0x252f, 0x2531, 0x2533, 0x2535, 0x2537, 0x2539, 0x253b, 0x253d, - /* 0x40 - 0x4f */ - 0x253f, 0x2541, 0x2544, 0x2546, 0x2548, 0x254a, 0x254b, 0x254c, - 0x254d, 0x254e, 0x254f, 0x2552, 0x2555, 0x2558, 0x255b, 0x255e, - /* 0x50 - 0x5f */ - 0x255f, 0x2560, 0x2561, 0x2562, 0x2564, 0x2566, 0x2568, 0x2569, - 0x256a, 0x256b, 0x256c, 0x256d, 0x256f, 0x2573, 0x212b, 0x212c - }; - - static guint16 dakuten_tbl[] = { - /* 0x30 - 0x3f */ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x252c, 0x252e, - 0x2530, 0x2532, 0x2534, 0x2536, 0x2538, 0x253a, 0x253c, 0x253e, - /* 0x40 - 0x4f */ - 0x2540, 0x2542, 0x2545, 0x2547, 0x2549, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x2550, 0x2553, 0x2556, 0x2559, 0x255c, 0x0000 - }; - - static guint16 handakuten_tbl[] = { - /* 0x4a - 0x4e */ - 0x2551, 0x2554, 0x2557, 0x255a, 0x255d - }; - - guint16 out_code; - - jis_code &= 0x7f; - sound_sym &= 0x7f; - - if (jis_code < 0x21 || jis_code > 0x5f) - return 0; - - if (sound_sym == JIS_HWDAKUTEN && - jis_code >= 0x36 && jis_code <= 0x4e) { - out_code = dakuten_tbl[jis_code - 0x30]; - if (out_code != 0) { - *outbuf = out_code >> 8; - *(outbuf + 1) = out_code & 0xff; - return 2; - } - } - - if (sound_sym == JIS_HWHANDAKUTEN && - jis_code >= 0x4a && jis_code <= 0x4e) { - out_code = handakuten_tbl[jis_code - 0x4a]; - *outbuf = out_code >> 8; - *(outbuf + 1) = out_code & 0xff; - return 2; - } - - out_code = h2z_tbl[jis_code - 0x20]; - *outbuf = out_code >> 8; - *(outbuf + 1) = out_code & 0xff; - return 1; -} - -static gchar *conv_euctojis(const gchar *inbuf, gint *error) -{ - gchar *outbuf; - const guchar *in = (guchar *)inbuf; - guchar *out; - JISState state = JIS_ASCII; - gint error_ = 0; - - outbuf = g_malloc(strlen(inbuf) * 3 + 4); - out = (guchar *)outbuf; - - while (*in != '\0') { - if (isascii(*in)) { - K_OUT(); - *out++ = *in++; - } else if (iseuckanji(*in)) { - if (iseuckanji(*(in + 1))) { - K_IN(); - *out++ = *in++ & 0x7f; - *out++ = *in++ & 0x7f; - } else { - error_ = -1; - K_OUT(); - *out++ = SUBST_CHAR; - in++; - if (*in != '\0' && !isascii(*in)) { - *out++ = SUBST_CHAR; - in++; - } - } - } else if (iseuchwkana1(*in)) { - if (iseuchwkana2(*(in + 1))) { - if (prefs_common.allow_jisx0201_kana) { - HW_IN(); - in++; - *out++ = *in++ & 0x7f; - } else { - guchar jis_ch[2]; - gint len; - - if (iseuchwkana1(*(in + 2)) && - iseuchwkana2(*(in + 3))) - len = conv_jis_hantozen - (jis_ch, - *(in + 1), *(in + 3)); - else - len = conv_jis_hantozen - (jis_ch, - *(in + 1), '\0'); - if (len == 0) - in += 2; - else { - K_IN(); - in += len * 2; - *out++ = jis_ch[0]; - *out++ = jis_ch[1]; - } - } - } else { - error_ = -1; - K_OUT(); - in++; - if (*in != '\0' && !isascii(*in)) { - *out++ = SUBST_CHAR; - in++; - } - } - } else if (iseucaux(*in)) { - in++; - if (iseuckanji(*in) && iseuckanji(*(in + 1))) { - AUX_IN(); - *out++ = *in++ & 0x7f; - *out++ = *in++ & 0x7f; - } else { - error_ = -1; - K_OUT(); - if (*in != '\0' && !isascii(*in)) { - *out++ = SUBST_CHAR; - in++; - if (*in != '\0' && !isascii(*in)) { - *out++ = SUBST_CHAR; - in++; - } - } - } - } else { - error_ = -1; - K_OUT(); - *out++ = SUBST_CHAR; - in++; - } - } - - K_OUT(); - *out = '\0'; - - if (error) - *error = error_; - - return outbuf; -} - -static gchar *conv_sjistoeuc(const gchar *inbuf, gint *error) -{ - gchar *outbuf; - const guchar *in = (guchar *)inbuf; - guchar *out; - gint error_ = 0; - - outbuf = g_malloc(strlen(inbuf) * 2 + 1); - out = (guchar *)outbuf; - - while (*in != '\0') { - if (isascii(*in)) { - *out++ = *in++; - } else if (issjiskanji1(*in)) { - if (issjiskanji2(*(in + 1))) { - guchar out1 = *in; - guchar out2 = *(in + 1); - guchar row; - - row = out1 < 0xa0 ? 0x70 : 0xb0; - if (out2 < 0x9f) { - out1 = (out1 - row) * 2 - 1; - out2 -= out2 > 0x7f ? 0x20 : 0x1f; - } else { - out1 = (out1 - row) * 2; - out2 -= 0x7e; - } - - *out++ = out1 | 0x80; - *out++ = out2 | 0x80; - in += 2; - } else { - error_ = -1; - *out++ = SUBST_CHAR; - in++; - if (*in != '\0' && !isascii(*in)) { - *out++ = SUBST_CHAR; - in++; - } - } - } else if (issjishwkana(*in)) { - *out++ = 0x8e; - *out++ = *in++; - } else { - error_ = -1; - *out++ = SUBST_CHAR; - in++; - } - } - - *out = '\0'; - - if (error) - *error = error_; - - return outbuf; -} - -static gchar *conv_jistoutf8(const gchar *inbuf, gint *error) -{ - gchar *eucstr, *utf8str; - gint e_error = 0, u_error = 0; - - eucstr = conv_jistoeuc(inbuf, &e_error); - utf8str = conv_euctoutf8(eucstr, &u_error); - g_free(eucstr); - - if (error) - *error = (e_error | u_error); - - return utf8str; -} - -static gchar *conv_sjistoutf8(const gchar *inbuf, gint *error) -{ - gchar *utf8str; - - utf8str = conv_iconv_strdup(inbuf, CS_SHIFT_JIS, CS_UTF_8, error); - if (!utf8str) - utf8str = g_strdup(inbuf); - - return utf8str; -} - -static gchar *conv_euctoutf8(const gchar *inbuf, gint *error) -{ - static iconv_t cd = (iconv_t)-1; - static gboolean iconv_ok = TRUE; - - if (cd == (iconv_t)-1) { - if (!iconv_ok) { - if (error) - *error = -1; - return g_strdup(inbuf); - } - - cd = iconv_open(CS_UTF_8, CS_EUC_JP_MS); - if (cd == (iconv_t)-1) { - cd = iconv_open(CS_UTF_8, CS_EUC_JP); - if (cd == (iconv_t)-1) { - g_warning("conv_euctoutf8(): %s\n", - g_strerror(errno)); - iconv_ok = FALSE; - if (error) - *error = -1; - return g_strdup(inbuf); - } - } - } - - return conv_iconv_strdup_with_cd(inbuf, cd, error); -} - -static gchar *conv_anytoutf8(const gchar *inbuf, gint *error) -{ - switch (conv_guess_ja_encoding(inbuf)) { - case C_ISO_2022_JP: - return conv_jistoutf8(inbuf, error); - case C_SHIFT_JIS: - return conv_sjistoutf8(inbuf, error); - case C_EUC_JP: - return conv_euctoutf8(inbuf, error); - default: - if (error) - *error = 0; - return g_strdup(inbuf); - } -} - -static gchar *conv_utf8toeuc(const gchar *inbuf, gint *error) -{ - static iconv_t cd = (iconv_t)-1; - static gboolean iconv_ok = TRUE; - - if (cd == (iconv_t)-1) { - if (!iconv_ok) { - if (error) - *error = -1; - return g_strdup(inbuf); - } - - cd = iconv_open(CS_EUC_JP_MS, CS_UTF_8); - if (cd == (iconv_t)-1) { - cd = iconv_open(CS_EUC_JP, CS_UTF_8); - if (cd == (iconv_t)-1) { - g_warning("conv_utf8toeuc(): %s\n", - g_strerror(errno)); - iconv_ok = FALSE; - if (error) - *error = -1; - return g_strdup(inbuf); - } - } - } - - return conv_iconv_strdup_with_cd(inbuf, cd, error); -} - -static gchar *conv_utf8tojis(const gchar *inbuf, gint *error) -{ - gchar *eucstr, *jisstr; - gint e_error = 0, j_error = 0; - - eucstr = conv_utf8toeuc(inbuf, &e_error); - jisstr = conv_euctojis(eucstr, &j_error); - g_free(eucstr); - - if (error) - *error = (e_error | j_error); - - return jisstr; -} - -#if 0 -static gchar valid_eucjp_tbl[][96] = { - /* 0xa2a0 - 0xa2ff */ - { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0 }, - - /* 0xa3a0 - 0xa3ff */ - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }, - - /* 0xa4a0 - 0xa4ff */ - { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - - /* 0xa5a0 - 0xa5ff */ - { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - - /* 0xa6a0 - 0xa6ff */ - { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - - /* 0xa7a0 - 0xa7ff */ - { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - - /* 0xa8a0 - 0xa8ff */ - { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } -}; - -static gboolean isprintableeuckanji(guchar c1, guchar c2) -{ - if (c1 <= 0xa0 || c1 >= 0xf5) - return FALSE; - if (c2 <= 0xa0 || c2 == 0xff) - return FALSE; - - if (c1 >= 0xa9 && c1 <= 0xaf) - return FALSE; - - if (c1 >= 0xa2 && c1 <= 0xa8) - return (gboolean)valid_eucjp_tbl[c1 - 0xa2][c2 - 0xa0]; - - if (c1 == 0xcf) { - if (c2 >= 0xd4 && c2 <= 0xfe) - return FALSE; - } else if (c1 == 0xf4) { - if (c2 >= 0xa7 && c2 <= 0xfe) - return FALSE; - } - - return TRUE; -} - -static void conv_unreadable_eucjp(gchar *str) -{ - register guchar *p = str; - - while (*p != '\0') { - if (isascii(*p)) { - /* convert CR+LF -> LF */ - if (*p == '\r' && *(p + 1) == '\n') - memmove(p, p + 1, strlen(p)); - /* printable 7 bit code */ - p++; - } else if (iseuckanji(*p)) { - if (isprintableeuckanji(*p, *(p + 1))) { - /* printable euc-jp code */ - p += 2; - } else { - /* substitute unprintable code */ - *p++ = SUBST_CHAR; - if (*p != '\0') { - if (isascii(*p)) - p++; - else - *p++ = SUBST_CHAR; - } - } - } else if (iseuchwkana1(*p)) { - if (iseuchwkana2(*(p + 1))) - /* euc-jp hankaku kana */ - p += 2; - else - *p++ = SUBST_CHAR; - } else if (iseucaux(*p)) { - if (iseuckanji(*(p + 1)) && iseuckanji(*(p + 2))) { - /* auxiliary kanji */ - p += 3; - } else - *p++ = SUBST_CHAR; - } else - /* substitute unprintable 1 byte code */ - *p++ = SUBST_CHAR; - } -} -#endif - -static void conv_unreadable_8bit(gchar *str) -{ - register gchar *p = str; - - while (*p != '\0') { - /* convert CR+LF -> LF */ - if (*p == '\r' && *(p + 1) == '\n') - memmove(p, p + 1, strlen(p)); - else if (!isascii(*(guchar *)p)) *p = SUBST_CHAR; - p++; - } -} - -#if 0 -static void conv_unreadable_latin(gchar *str) -{ - register guchar *p = str; - - while (*p != '\0') { - /* convert CR+LF -> LF */ - if (*p == '\r' && *(p + 1) == '\n') - memmove(p, p + 1, strlen(p)); - else if ((*p & 0xff) >= 0x7f && (*p & 0xff) <= 0x9f) - *p = SUBST_CHAR; - p++; - } -} -#endif - -#define NCV '\0' - -void conv_mb_alnum(gchar *str) -{ - static guchar char_tbl[] = { - /* 0xa0 - 0xaf */ - NCV, ' ', NCV, NCV, ',', '.', NCV, ':', - ';', '?', '!', NCV, NCV, NCV, NCV, NCV, - /* 0xb0 - 0xbf */ - NCV, NCV, NCV, NCV, NCV, NCV, NCV, NCV, - NCV, NCV, NCV, NCV, NCV, NCV, NCV, NCV, - /* 0xc0 - 0xcf */ - NCV, NCV, NCV, NCV, NCV, NCV, NCV, NCV, - NCV, NCV, '(', ')', NCV, NCV, '[', ']', - /* 0xd0 - 0xdf */ - '{', '}', NCV, NCV, NCV, NCV, NCV, NCV, - NCV, NCV, NCV, NCV, '+', '-', NCV, NCV, - /* 0xe0 - 0xef */ - NCV, '=', NCV, '<', '>', NCV, NCV, NCV, - NCV, NCV, NCV, NCV, NCV, NCV, NCV, NCV - }; - - register guchar *p = (guchar *)str; - register gint len; - - len = strlen(str); - - while (len > 1) { - if (*p == 0xa3) { - register guchar ch = *(p + 1); - - if (ch >= 0xb0 && ch <= 0xfa) { - /* [a-zA-Z] */ - *p = ch & 0x7f; - p++; - len--; - memmove(p, p + 1, len); - len--; - } else { - p += 2; - len -= 2; - } - } else if (*p == 0xa1) { - register guchar ch = *(p + 1); - - if (ch >= 0xa0 && ch <= 0xef && - NCV != char_tbl[ch - 0xa0]) { - *p = char_tbl[ch - 0xa0]; - p++; - len--; - memmove(p, p + 1, len); - len--; - } else { - p += 2; - len -= 2; - } - } else if (iseuckanji(*p)) { - p += 2; - len -= 2; - } else { - p++; - len--; - } - } -} - -CharSet conv_guess_ja_encoding(const gchar *str) -{ - const guchar *p = (const guchar *)str; - CharSet guessed = C_US_ASCII; - - while (*p != '\0') { - if (*p == ESC && (*(p + 1) == '$' || *(p + 1) == '(')) { - if (guessed == C_US_ASCII) - return C_ISO_2022_JP; - p += 2; - } else if (isascii(*p)) { - p++; - } else if (iseuckanji(*p) && iseuckanji(*(p + 1))) { - if (*p >= 0xfd && *p <= 0xfe) - return C_EUC_JP; - else if (guessed == C_SHIFT_JIS) { - if ((issjiskanji1(*p) && - issjiskanji2(*(p + 1))) || - issjishwkana(*p)) - guessed = C_SHIFT_JIS; - else - guessed = C_EUC_JP; - } else - guessed = C_EUC_JP; - p += 2; - } else if (issjiskanji1(*p) && issjiskanji2(*(p + 1))) { - if (iseuchwkana1(*p) && iseuchwkana2(*(p + 1))) - guessed = C_SHIFT_JIS; - else - return C_SHIFT_JIS; - p += 2; - } else if (issjishwkana(*p)) { - guessed = C_SHIFT_JIS; - p++; - } else { - p++; - } - } - - return guessed; -} - -static gchar *conv_jistodisp(const gchar *inbuf, gint *error) -{ - return conv_jistoutf8(inbuf, error); -} - -static gchar *conv_sjistodisp(const gchar *inbuf, gint *error) -{ - return conv_sjistoutf8(inbuf, error); -} - -static gchar *conv_euctodisp(const gchar *inbuf, gint *error) -{ - return conv_euctoutf8(inbuf, error); -} - -gchar *conv_utf8todisp(const gchar *inbuf, gint *error) -{ - if (g_utf8_validate(inbuf, -1, NULL) == TRUE) { - if (error) - *error = 0; - return g_strdup(inbuf); - } else - return conv_ustodisp(inbuf, error); -} - -static gchar *conv_anytodisp(const gchar *inbuf, gint *error) -{ - gchar *outbuf; - - outbuf = conv_anytoutf8(inbuf, error); - if (g_utf8_validate(outbuf, -1, NULL) != TRUE) { - if (error) - *error = -1; - conv_unreadable_8bit(outbuf); - } - - return outbuf; -} - -static gchar *conv_ustodisp(const gchar *inbuf, gint *error) -{ - gchar *outbuf; - - outbuf = g_strdup(inbuf); - conv_unreadable_8bit(outbuf); - if (error) - *error = 0; - - return outbuf; -} - -gchar *conv_localetodisp(const gchar *inbuf, gint *error) -{ - gchar *str; - - str = conv_iconv_strdup(inbuf, conv_get_locale_charset_str(), - CS_INTERNAL, error); - if (!str) - str = conv_utf8todisp(inbuf, NULL); - - return str; -} - -static gchar *conv_noconv(const gchar *inbuf, gint *error) -{ - if (error) - *error = 0; - return g_strdup(inbuf); -} - -static const gchar * -conv_get_fallback_for_private_encoding(const gchar *encoding) -{ - if (encoding && (encoding[0] == 'X' || encoding[0] == 'x') && - encoding[1] == '-') { - if (!g_ascii_strcasecmp(encoding, CS_X_GBK)) - return CS_GBK; - } - - return encoding; -} - -CodeConverter *conv_code_converter_new(const gchar *src_encoding, - const gchar *dest_encoding) -{ - CodeConverter *conv; - - src_encoding = conv_get_fallback_for_private_encoding(src_encoding); - - conv = g_new0(CodeConverter, 1); - conv->code_conv_func = - conv_get_code_conv_func(src_encoding, dest_encoding); - conv->src_encoding = g_strdup(src_encoding); - conv->dest_encoding = g_strdup(dest_encoding); - - return conv; -} - -void conv_code_converter_destroy(CodeConverter *conv) -{ - g_free(conv->src_encoding); - g_free(conv->dest_encoding); - g_free(conv); -} - -gchar *conv_convert(CodeConverter *conv, const gchar *inbuf) -{ - if (conv->code_conv_func != conv_noconv) - return conv->code_conv_func(inbuf, NULL); - else - return conv_iconv_strdup - (inbuf, conv->src_encoding, conv->dest_encoding, NULL); -} - -gchar *conv_codeset_strdup_full(const gchar *inbuf, - const gchar *src_encoding, - const gchar *dest_encoding, - gint *error) -{ - CodeConvFunc conv_func; - - src_encoding = conv_get_fallback_for_private_encoding(src_encoding); - - conv_func = conv_get_code_conv_func(src_encoding, dest_encoding); - if (conv_func != conv_noconv) - return conv_func(inbuf, error); - - return conv_iconv_strdup(inbuf, src_encoding, dest_encoding, error); -} - -CodeConvFunc conv_get_code_conv_func(const gchar *src_encoding, - const gchar *dest_encoding) -{ - CodeConvFunc code_conv = conv_noconv; - CharSet src_charset; - CharSet dest_charset; - - if (!src_encoding) - src_charset = conv_get_locale_charset(); - else - src_charset = conv_get_charset_from_str(src_encoding); - - /* auto detection mode */ - if (!src_encoding && !dest_encoding) { - if (conv_is_ja_locale()) - return conv_anytodisp; - else - return conv_noconv; - } - - dest_charset = conv_get_charset_from_str(dest_encoding); - - if (dest_charset == C_US_ASCII) - return conv_ustodisp; - - switch (src_charset) { - case C_US_ASCII: - case C_ISO_8859_1: - case C_ISO_8859_2: - case C_ISO_8859_3: - case C_ISO_8859_4: - case C_ISO_8859_5: - case C_ISO_8859_6: - case C_ISO_8859_7: - case C_ISO_8859_8: - case C_ISO_8859_9: - case C_ISO_8859_10: - case C_ISO_8859_11: - case C_ISO_8859_13: - case C_ISO_8859_14: - case C_ISO_8859_15: - break; - case C_ISO_2022_JP: - case C_ISO_2022_JP_2: - case C_ISO_2022_JP_3: - if (dest_charset == C_AUTO) - code_conv = conv_jistodisp; - else if (dest_charset == C_EUC_JP) - code_conv = conv_jistoeuc; - else if (dest_charset == C_UTF_8) - code_conv = conv_jistoutf8; - break; - case C_SHIFT_JIS: - if (dest_charset == C_AUTO) - code_conv = conv_sjistodisp; - else if (dest_charset == C_EUC_JP) - code_conv = conv_sjistoeuc; - else if (dest_charset == C_UTF_8) - code_conv = conv_sjistoutf8; - break; - case C_EUC_JP: - if (dest_charset == C_AUTO) - code_conv = conv_euctodisp; - else if (dest_charset == C_ISO_2022_JP || - dest_charset == C_ISO_2022_JP_2 || - dest_charset == C_ISO_2022_JP_3) - code_conv = conv_euctojis; - else if (dest_charset == C_UTF_8) - code_conv = conv_euctoutf8; - break; - case C_UTF_8: - if (dest_charset == C_EUC_JP) - code_conv = conv_utf8toeuc; - else if (dest_charset == C_ISO_2022_JP || - dest_charset == C_ISO_2022_JP_2 || - dest_charset == C_ISO_2022_JP_3) - code_conv = conv_utf8tojis; - break; - default: - break; - } - - return code_conv; -} - -gchar *conv_iconv_strdup(const gchar *inbuf, - const gchar *src_code, const gchar *dest_code, - gint *error) -{ - iconv_t cd; - gchar *outbuf; - - if (!src_code) - src_code = conv_get_locale_charset_str(); - if (!dest_code) - dest_code = CS_INTERNAL; - - cd = iconv_open(dest_code, src_code); - if (cd == (iconv_t)-1) { - if (error) - *error = -1; - return NULL; - } - - outbuf = conv_iconv_strdup_with_cd(inbuf, cd, error); - - iconv_close(cd); - - return outbuf; -} - -gchar *conv_iconv_strdup_with_cd(const gchar *inbuf, iconv_t cd, gint *error) -{ - const gchar *inbuf_p; - gchar *outbuf; - gchar *outbuf_p; - size_t in_size; - size_t in_left; - size_t out_size; - size_t out_left; - size_t n_conv; - size_t len; - gint error_ = 0; - - inbuf_p = inbuf; - in_size = strlen(inbuf); - in_left = in_size; - out_size = (in_size + 1) * 2; - outbuf = g_malloc(out_size); - outbuf_p = outbuf; - out_left = out_size; - -#define EXPAND_BUF() \ -{ \ - len = outbuf_p - outbuf; \ - out_size *= 2; \ - outbuf = g_realloc(outbuf, out_size); \ - outbuf_p = outbuf + len; \ - out_left = out_size - len; \ -} - - while ((n_conv = iconv(cd, (ICONV_CONST gchar **)&inbuf_p, &in_left, - &outbuf_p, &out_left)) == (size_t)-1) { - if (EILSEQ == errno) { - /* g_print("iconv(): at %d: %s\n", in_size - in_left, g_strerror(errno)); */ - error_ = -1; - inbuf_p++; - in_left--; - if (out_left == 0) { - EXPAND_BUF(); - } - *outbuf_p++ = SUBST_CHAR; - out_left--; - } else if (EINVAL == errno) { - error_ = -1; - break; - } else if (E2BIG == errno) { - EXPAND_BUF(); - } else { - g_warning("conv_iconv_strdup(): %s\n", - g_strerror(errno)); - error_ = -1; - break; - } - } - - while ((n_conv = iconv(cd, NULL, NULL, &outbuf_p, &out_left)) == - (size_t)-1) { - if (E2BIG == errno) { - EXPAND_BUF(); - } else { - g_warning("conv_iconv_strdup(): %s\n", - g_strerror(errno)); - error_ = -1; - break; - } - } - -#undef EXPAND_BUF - - len = outbuf_p - outbuf; - outbuf = g_realloc(outbuf, len + 1); - outbuf[len] = '\0'; - - if (error) - *error = error_; - - return outbuf; -} - -static const struct { - CharSet charset; - gchar *const name; -} charsets[] = { - {C_US_ASCII, CS_US_ASCII}, - {C_US_ASCII, CS_ANSI_X3_4_1968}, - {C_UTF_8, CS_UTF_8}, - {C_UTF_7, CS_UTF_7}, - {C_ISO_8859_1, CS_ISO_8859_1}, - {C_ISO_8859_2, CS_ISO_8859_2}, - {C_ISO_8859_3, CS_ISO_8859_3}, - {C_ISO_8859_4, CS_ISO_8859_4}, - {C_ISO_8859_5, CS_ISO_8859_5}, - {C_ISO_8859_6, CS_ISO_8859_6}, - {C_ISO_8859_7, CS_ISO_8859_7}, - {C_ISO_8859_8, CS_ISO_8859_8}, - {C_ISO_8859_9, CS_ISO_8859_9}, - {C_ISO_8859_10, CS_ISO_8859_10}, - {C_ISO_8859_11, CS_ISO_8859_11}, - {C_ISO_8859_13, CS_ISO_8859_13}, - {C_ISO_8859_14, CS_ISO_8859_14}, - {C_ISO_8859_15, CS_ISO_8859_15}, - {C_BALTIC, CS_BALTIC}, - {C_CP1250, CS_CP1250}, - {C_CP1251, CS_CP1251}, - {C_CP1252, CS_CP1252}, - {C_CP1253, CS_CP1253}, - {C_CP1254, CS_CP1254}, - {C_CP1255, CS_CP1255}, - {C_CP1256, CS_CP1256}, - {C_CP1257, CS_CP1257}, - {C_CP1258, CS_CP1258}, - {C_WINDOWS_1250, CS_WINDOWS_1250}, - {C_WINDOWS_1251, CS_WINDOWS_1251}, - {C_WINDOWS_1252, CS_WINDOWS_1252}, - {C_WINDOWS_1253, CS_WINDOWS_1253}, - {C_WINDOWS_1254, CS_WINDOWS_1254}, - {C_WINDOWS_1255, CS_WINDOWS_1255}, - {C_WINDOWS_1256, CS_WINDOWS_1256}, - {C_WINDOWS_1257, CS_WINDOWS_1257}, - {C_WINDOWS_1258, CS_WINDOWS_1258}, - {C_KOI8_R, CS_KOI8_R}, - {C_KOI8_T, CS_KOI8_T}, - {C_KOI8_U, CS_KOI8_U}, - {C_ISO_2022_JP, CS_ISO_2022_JP}, - {C_ISO_2022_JP_2, CS_ISO_2022_JP_2}, - {C_ISO_2022_JP_3, CS_ISO_2022_JP_3}, - {C_EUC_JP, CS_EUC_JP}, - {C_EUC_JP, CS_EUCJP}, - {C_EUC_JP_MS, CS_EUC_JP_MS}, - {C_SHIFT_JIS, CS_SHIFT_JIS}, - {C_SHIFT_JIS, CS_SHIFT__JIS}, - {C_SHIFT_JIS, CS_SJIS}, - {C_ISO_2022_KR, CS_ISO_2022_KR}, - {C_EUC_KR, CS_EUC_KR}, - {C_ISO_2022_CN, CS_ISO_2022_CN}, - {C_EUC_CN, CS_EUC_CN}, - {C_GB2312, CS_GB2312}, - {C_GBK, CS_GBK}, - {C_EUC_TW, CS_EUC_TW}, - {C_BIG5, CS_BIG5}, - {C_BIG5_HKSCS, CS_BIG5_HKSCS}, - {C_TIS_620, CS_TIS_620}, - {C_WINDOWS_874, CS_WINDOWS_874}, - {C_GEORGIAN_PS, CS_GEORGIAN_PS}, - {C_TCVN5712_1, CS_TCVN5712_1}, -}; - -static const struct { - gchar *const locale; - CharSet charset; - CharSet out_charset; -} locale_table[] = { - {"ja_JP.eucJP" , C_EUC_JP , C_ISO_2022_JP}, - {"ja_JP.EUC-JP" , C_EUC_JP , C_ISO_2022_JP}, - {"ja_JP.EUC" , C_EUC_JP , C_ISO_2022_JP}, - {"ja_JP.ujis" , C_EUC_JP , C_ISO_2022_JP}, - {"ja_JP.SJIS" , C_SHIFT_JIS , C_ISO_2022_JP}, - {"ja_JP.JIS" , C_ISO_2022_JP , C_ISO_2022_JP}, -#ifdef G_OS_WIN32 - {"ja_JP" , C_SHIFT_JIS , C_ISO_2022_JP}, -#else - {"ja_JP" , C_EUC_JP , C_ISO_2022_JP}, -#endif - {"ko_KR.EUC-KR" , C_EUC_KR , C_EUC_KR}, - {"ko_KR" , C_EUC_KR , C_EUC_KR}, - {"zh_CN.GB2312" , C_GB2312 , C_GB2312}, - {"zh_CN.GBK" , C_GBK , C_GBK}, - {"zh_CN" , C_GB2312 , C_GB2312}, - {"zh_HK" , C_BIG5_HKSCS , C_BIG5_HKSCS}, - {"zh_TW.eucTW" , C_EUC_TW , C_BIG5}, - {"zh_TW.EUC-TW" , C_EUC_TW , C_BIG5}, - {"zh_TW.Big5" , C_BIG5 , C_BIG5}, - {"zh_TW" , C_BIG5 , C_BIG5}, - - {"ru_RU.KOI8-R" , C_KOI8_R , C_KOI8_R}, - {"ru_RU.KOI8R" , C_KOI8_R , C_KOI8_R}, - {"ru_RU.CP1251" , C_WINDOWS_1251, C_KOI8_R}, - {"ru_RU" , C_ISO_8859_5 , C_KOI8_R}, - {"tg_TJ" , C_KOI8_T , C_KOI8_T}, - {"ru_UA" , C_KOI8_U , C_KOI8_U}, - {"uk_UA.CP1251" , C_WINDOWS_1251, C_KOI8_U}, - {"uk_UA" , C_KOI8_U , C_KOI8_U}, - - {"be_BY" , C_WINDOWS_1251, C_WINDOWS_1251}, - {"bg_BG" , C_WINDOWS_1251, C_WINDOWS_1251}, - - {"yi_US" , C_WINDOWS_1255, C_WINDOWS_1255}, - - {"af_ZA" , C_ISO_8859_1 , C_ISO_8859_1}, - {"br_FR" , C_ISO_8859_1 , C_ISO_8859_1}, - {"ca_ES" , C_ISO_8859_1 , C_ISO_8859_1}, - {"da_DK" , C_ISO_8859_1 , C_ISO_8859_1}, - {"de_AT" , C_ISO_8859_1 , C_ISO_8859_1}, - {"de_BE" , C_ISO_8859_1 , C_ISO_8859_1}, - {"de_CH" , C_ISO_8859_1 , C_ISO_8859_1}, - {"de_DE" , C_ISO_8859_1 , C_ISO_8859_1}, - {"de_LU" , C_ISO_8859_1 , C_ISO_8859_1}, - {"en_AU" , C_ISO_8859_1 , C_ISO_8859_1}, - {"en_BW" , C_ISO_8859_1 , C_ISO_8859_1}, - {"en_CA" , C_ISO_8859_1 , C_ISO_8859_1}, - {"en_DK" , C_ISO_8859_1 , C_ISO_8859_1}, - {"en_GB" , C_ISO_8859_1 , C_ISO_8859_1}, - {"en_HK" , C_ISO_8859_1 , C_ISO_8859_1}, - {"en_IE" , C_ISO_8859_1 , C_ISO_8859_1}, - {"en_NZ" , C_ISO_8859_1 , C_ISO_8859_1}, - {"en_PH" , C_ISO_8859_1 , C_ISO_8859_1}, - {"en_SG" , C_ISO_8859_1 , C_ISO_8859_1}, - {"en_US" , C_ISO_8859_1 , C_ISO_8859_1}, - {"en_ZA" , C_ISO_8859_1 , C_ISO_8859_1}, - {"en_ZW" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_AR" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_BO" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_CL" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_CO" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_CR" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_DO" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_EC" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_ES" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_GT" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_HN" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_MX" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_NI" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_PA" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_PE" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_PR" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_PY" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_SV" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_US" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_UY" , C_ISO_8859_1 , C_ISO_8859_1}, - {"es_VE" , C_ISO_8859_1 , C_ISO_8859_1}, - {"et_EE" , C_ISO_8859_1 , C_ISO_8859_1}, - {"eu_ES" , C_ISO_8859_1 , C_ISO_8859_1}, - {"fi_FI" , C_ISO_8859_1 , C_ISO_8859_1}, - {"fo_FO" , C_ISO_8859_1 , C_ISO_8859_1}, - {"fr_BE" , C_ISO_8859_1 , C_ISO_8859_1}, - {"fr_CA" , C_ISO_8859_1 , C_ISO_8859_1}, - {"fr_CH" , C_ISO_8859_1 , C_ISO_8859_1}, - {"fr_FR" , C_ISO_8859_1 , C_ISO_8859_1}, - {"fr_LU" , C_ISO_8859_1 , C_ISO_8859_1}, - {"ga_IE" , C_ISO_8859_1 , C_ISO_8859_1}, - {"gl_ES" , C_ISO_8859_1 , C_ISO_8859_1}, - {"gv_GB" , C_ISO_8859_1 , C_ISO_8859_1}, - {"id_ID" , C_ISO_8859_1 , C_ISO_8859_1}, - {"is_IS" , C_ISO_8859_1 , C_ISO_8859_1}, - {"it_CH" , C_ISO_8859_1 , C_ISO_8859_1}, - {"it_IT" , C_ISO_8859_1 , C_ISO_8859_1}, - {"kl_GL" , C_ISO_8859_1 , C_ISO_8859_1}, - {"kw_GB" , C_ISO_8859_1 , C_ISO_8859_1}, - {"ms_MY" , C_ISO_8859_1 , C_ISO_8859_1}, - {"nl_BE" , C_ISO_8859_1 , C_ISO_8859_1}, - {"nl_NL" , C_ISO_8859_1 , C_ISO_8859_1}, - {"nn_NO" , C_ISO_8859_1 , C_ISO_8859_1}, - {"no_NO" , C_ISO_8859_1 , C_ISO_8859_1}, - {"oc_FR" , C_ISO_8859_1 , C_ISO_8859_1}, - {"pt_BR" , C_ISO_8859_1 , C_ISO_8859_1}, - {"pt_PT" , C_ISO_8859_1 , C_ISO_8859_1}, - {"sq_AL" , C_ISO_8859_1 , C_ISO_8859_1}, - {"sv_FI" , C_ISO_8859_1 , C_ISO_8859_1}, - {"sv_SE" , C_ISO_8859_1 , C_ISO_8859_1}, - {"tl_PH" , C_ISO_8859_1 , C_ISO_8859_1}, - {"uz_UZ" , C_ISO_8859_1 , C_ISO_8859_1}, - {"wa_BE" , C_ISO_8859_1 , C_ISO_8859_1}, - - {"bs_BA" , C_ISO_8859_2 , C_ISO_8859_2}, - {"cs_CZ" , C_ISO_8859_2 , C_ISO_8859_2}, - {"hr_HR" , C_ISO_8859_2 , C_ISO_8859_2}, - {"hu_HU" , C_ISO_8859_2 , C_ISO_8859_2}, - {"pl_PL" , C_ISO_8859_2 , C_ISO_8859_2}, - {"ro_RO" , C_ISO_8859_2 , C_ISO_8859_2}, - {"sk_SK" , C_ISO_8859_2 , C_ISO_8859_2}, - {"sl_SI" , C_ISO_8859_2 , C_ISO_8859_2}, - - {"sr_YU@cyrillic" , C_ISO_8859_5 , C_ISO_8859_5}, - {"sr_YU" , C_ISO_8859_2 , C_ISO_8859_2}, - - {"mt_MT" , C_ISO_8859_3 , C_ISO_8859_3}, - - {"lt_LT.iso88594" , C_ISO_8859_4 , C_ISO_8859_4}, - {"lt_LT.ISO8859-4" , C_ISO_8859_4 , C_ISO_8859_4}, - {"lt_LT.ISO_8859-4" , C_ISO_8859_4 , C_ISO_8859_4}, - {"lt_LT" , C_ISO_8859_13 , C_ISO_8859_13}, - - {"mk_MK" , C_ISO_8859_5 , C_ISO_8859_5}, - - {"ar_AE" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_BH" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_DZ" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_EG" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_IQ" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_JO" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_KW" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_LB" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_LY" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_MA" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_OM" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_QA" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_SA" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_SD" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_SY" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_TN" , C_ISO_8859_6 , C_ISO_8859_6}, - {"ar_YE" , C_ISO_8859_6 , C_ISO_8859_6}, - - {"el_GR" , C_ISO_8859_7 , C_ISO_8859_7}, - {"he_IL" , C_ISO_8859_8 , C_ISO_8859_8}, - {"iw_IL" , C_ISO_8859_8 , C_ISO_8859_8}, - {"tr_TR" , C_ISO_8859_9 , C_ISO_8859_9}, - - {"lv_LV" , C_ISO_8859_13 , C_ISO_8859_13}, - {"mi_NZ" , C_ISO_8859_13 , C_ISO_8859_13}, - - {"cy_GB" , C_ISO_8859_14 , C_ISO_8859_14}, - - {"ar_IN" , C_UTF_8 , C_UTF_8}, - {"en_IN" , C_UTF_8 , C_UTF_8}, - {"se_NO" , C_UTF_8 , C_UTF_8}, - {"ta_IN" , C_UTF_8 , C_UTF_8}, - {"te_IN" , C_UTF_8 , C_UTF_8}, - {"ur_PK" , C_UTF_8 , C_UTF_8}, - - {"th_TH" , C_TIS_620 , C_TIS_620}, - /* {"th_TH" , C_WINDOWS_874}, */ - /* {"th_TH" , C_ISO_8859_11}, */ - - {"ka_GE" , C_GEORGIAN_PS , C_GEORGIAN_PS}, - {"vi_VN.TCVN" , C_TCVN5712_1 , C_TCVN5712_1}, - - {"C" , C_US_ASCII , C_US_ASCII}, - {"POSIX" , C_US_ASCII , C_US_ASCII}, - {"ANSI_X3.4-1968" , C_US_ASCII , C_US_ASCII}, -}; - -static GHashTable *conv_get_charset_to_str_table(void) -{ - static GHashTable *table; - gint i; - - if (table) - return table; - - table = g_hash_table_new(NULL, g_direct_equal); - - for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) { - if (g_hash_table_lookup(table, GUINT_TO_POINTER(charsets[i].charset)) - == NULL) { - g_hash_table_insert - (table, GUINT_TO_POINTER(charsets[i].charset), - charsets[i].name); - } - } - - return table; -} - -static GHashTable *conv_get_charset_from_str_table(void) -{ - static GHashTable *table; - gint i; - - if (table) - return table; - - table = g_hash_table_new(str_case_hash, str_case_equal); - - for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) { - g_hash_table_insert(table, charsets[i].name, - GUINT_TO_POINTER(charsets[i].charset)); - } - - return table; -} - -const gchar *conv_get_charset_str(CharSet charset) -{ - GHashTable *table; - - table = conv_get_charset_to_str_table(); - return g_hash_table_lookup(table, GUINT_TO_POINTER(charset)); -} - -CharSet conv_get_charset_from_str(const gchar *charset) -{ - GHashTable *table; - - if (!charset) return C_AUTO; - - table = conv_get_charset_from_str_table(); - return GPOINTER_TO_UINT(g_hash_table_lookup(table, charset)); -} - -CharSet conv_get_locale_charset(void) -{ - static CharSet cur_charset = -1; - const gchar *cur_locale; - const gchar *p; - gint i; - - if (cur_charset != -1) - return cur_charset; - - cur_locale = conv_get_current_locale(); - if (!cur_locale) { - cur_charset = C_US_ASCII; - return cur_charset; - } - - if (strcasestr(cur_locale, "UTF-8")) { - cur_charset = C_UTF_8; - return cur_charset; - } - - if ((p = strcasestr(cur_locale, "@euro")) && p[5] == '\0') { - cur_charset = C_ISO_8859_15; - return cur_charset; - } - - for (i = 0; i < sizeof(locale_table) / sizeof(locale_table[0]); i++) { - const gchar *p; - - /* "ja_JP.EUC" matches with "ja_JP.eucJP", "ja_JP.EUC" and - "ja_JP". "ja_JP" matches with "ja_JP.xxxx" and "ja" */ - if (!g_ascii_strncasecmp(cur_locale, locale_table[i].locale, - strlen(locale_table[i].locale))) { - cur_charset = locale_table[i].charset; - return cur_charset; - } else if ((p = strchr(locale_table[i].locale, '_')) && - !strchr(p + 1, '.')) { - if (strlen(cur_locale) == 2 && - !g_ascii_strncasecmp(cur_locale, - locale_table[i].locale, 2)) { - cur_charset = locale_table[i].charset; - return cur_charset; - } - } - } - - cur_charset = C_AUTO; - return cur_charset; -} - -const gchar *conv_get_locale_charset_str(void) -{ - static const gchar *codeset = NULL; - - if (!codeset) - codeset = conv_get_charset_str(conv_get_locale_charset()); - - return codeset ? codeset : CS_INTERNAL; -} - -CharSet conv_get_internal_charset(void) -{ - return C_INTERNAL; -} - -const gchar *conv_get_internal_charset_str(void) -{ - return CS_INTERNAL; -} - -CharSet conv_get_outgoing_charset(void) -{ - static CharSet out_charset = -1; - const gchar *cur_locale; - const gchar *p; - gint i; - - if (out_charset != -1) - return out_charset; - - cur_locale = conv_get_current_locale(); - if (!cur_locale) { - out_charset = C_AUTO; - return out_charset; - } - - if ((p = strcasestr(cur_locale, "@euro")) && p[5] == '\0') { - out_charset = C_ISO_8859_15; - return out_charset; - } - - for (i = 0; i < sizeof(locale_table) / sizeof(locale_table[0]); i++) { - const gchar *p; - - if (!g_ascii_strncasecmp(cur_locale, locale_table[i].locale, - strlen(locale_table[i].locale))) { - out_charset = locale_table[i].out_charset; - break; - } else if ((p = strchr(locale_table[i].locale, '_')) && - !strchr(p + 1, '.')) { - if (strlen(cur_locale) == 2 && - !g_ascii_strncasecmp(cur_locale, - locale_table[i].locale, 2)) { - out_charset = locale_table[i].out_charset; - break; - } - } - } - - return out_charset; -} - -const gchar *conv_get_outgoing_charset_str(void) -{ - CharSet out_charset; - const gchar *str; - - out_charset = conv_get_outgoing_charset(); - str = conv_get_charset_str(out_charset); - - return str ? str : CS_UTF_8; -} - -gboolean conv_is_multibyte_encoding(CharSet encoding) -{ - switch (encoding) { - case C_EUC_JP: - case C_EUC_JP_MS: - case C_EUC_KR: - case C_EUC_TW: - case C_EUC_CN: - case C_ISO_2022_JP: - case C_ISO_2022_JP_2: - case C_ISO_2022_JP_3: - case C_ISO_2022_KR: - case C_ISO_2022_CN: - case C_SHIFT_JIS: - case C_GB2312: - case C_GBK: - case C_BIG5: - case C_UTF_8: - case C_UTF_7: - return TRUE; - default: - return FALSE; - } -} - -const gchar *conv_get_current_locale(void) -{ - static const gchar *cur_locale; - - if (!cur_locale) { -#ifdef G_OS_WIN32 - cur_locale = g_win32_getlocale(); -#else - cur_locale = g_getenv("LC_ALL"); - if (!cur_locale) cur_locale = g_getenv("LC_CTYPE"); - if (!cur_locale) cur_locale = g_getenv("LANG"); - if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL); -#endif /* G_OS_WIN32 */ - - debug_print("current locale: %s\n", - cur_locale ? cur_locale : "(none)"); - } - - return cur_locale; -} - -gboolean conv_is_ja_locale(void) -{ - static gint is_ja_locale = -1; - const gchar *cur_locale; - - if (is_ja_locale != -1) - return is_ja_locale != 0; - - is_ja_locale = 0; - cur_locale = conv_get_current_locale(); - if (cur_locale) { - if (g_ascii_strncasecmp(cur_locale, "ja", 2) == 0) - is_ja_locale = 1; - } - - return is_ja_locale != 0; -} - -gchar *conv_unmime_header(const gchar *str, const gchar *default_encoding) -{ - gchar *buf; - gchar *decoded_str; - - if (is_ascii_str(str)) - return unmime_header(str); - - if (default_encoding) { - buf = conv_codeset_strdup - (str, default_encoding, CS_INTERNAL); - if (buf) { - decoded_str = unmime_header(buf); - g_free(buf); - return decoded_str; - } - } - - if (conv_is_ja_locale()) - buf = conv_anytodisp(str, NULL); - else - buf = conv_localetodisp(str, NULL); - - decoded_str = unmime_header(buf); - g_free(buf); - - return decoded_str; -} - -#define MAX_LINELEN 76 -#define MAX_HARD_LINELEN 996 -#define MIMESEP_BEGIN "=?" -#define MIMESEP_END "?=" - -#define B64LEN(len) ((len) / 3 * 4 + ((len) % 3 ? 4 : 0)) - -#define LBREAK_IF_REQUIRED(cond, is_plain_text) \ -{ \ - if (len - (destp - dest) < MAX_LINELEN + 2) { \ - *destp = '\0'; \ - return; \ - } \ - \ - if ((cond) && *srcp) { \ - if (destp > dest && left < MAX_LINELEN - 1) { \ - if (g_ascii_isspace(*(destp - 1))) \ - destp--; \ - else if (is_plain_text && \ - g_ascii_isspace(*srcp)) \ - srcp++; \ - if (*srcp) { \ - *destp++ = '\n'; \ - *destp++ = ' '; \ - left = MAX_LINELEN - 1; \ - } \ - } \ - } \ -} - -void conv_encode_header(gchar *dest, gint len, const gchar *src, - gint header_len, gboolean addr_field, - const gchar *out_encoding) -{ - const gchar *cur_encoding; - gint mimestr_len; - gchar *mimesep_enc; - gint left; - const gchar *srcp = src; - gchar *destp = dest; - gboolean use_base64; - - g_return_if_fail(g_utf8_validate(src, -1, NULL) == TRUE); - - if (MB_CUR_MAX > 1) { - use_base64 = TRUE; - mimesep_enc = "?B?"; - } else { - use_base64 = FALSE; - mimesep_enc = "?Q?"; - } - - cur_encoding = CS_INTERNAL; - if (!out_encoding) - out_encoding = conv_get_outgoing_charset_str(); - if (!strcmp(out_encoding, CS_US_ASCII)) - out_encoding = CS_ISO_8859_1; - - mimestr_len = strlen(MIMESEP_BEGIN) + strlen(out_encoding) + - strlen(mimesep_enc) + strlen(MIMESEP_END); - - left = MAX_LINELEN - header_len; - - while (*srcp) { - LBREAK_IF_REQUIRED(left <= 0, TRUE); - - while (g_ascii_isspace(*srcp)) { - *destp++ = *srcp++; - left--; - LBREAK_IF_REQUIRED(left <= 0, TRUE); - } - - /* output as it is if the next word is ASCII string */ - if (!is_next_nonascii(srcp)) { - gint word_len; - - word_len = get_next_word_len(srcp); - LBREAK_IF_REQUIRED(left < word_len, TRUE); - while (word_len > 0) { - LBREAK_IF_REQUIRED(left + (MAX_HARD_LINELEN - MAX_LINELEN) <= 0, TRUE) - *destp++ = *srcp++; - left--; - word_len--; - } - - continue; - } - - /* don't include parentheses in encoded strings */ - if (addr_field && (*srcp == '(' || *srcp == ')')) { - LBREAK_IF_REQUIRED(left < 2, FALSE); - *destp++ = *srcp++; - left--; - } - - while (1) { - gint mb_len = 0; - gint cur_len = 0; - gchar *part_str; - gchar *out_str; - gchar *enc_str; - const gchar *p = srcp; - gint out_str_len; - gint out_enc_str_len; - gint mime_block_len; - gboolean cont = FALSE; - - while (*p != '\0') { - if (g_ascii_isspace(*p) && - !is_next_nonascii(p + 1)) - break; - /* don't include parentheses in encoded - strings */ - if (addr_field && (*p == '(' || *p == ')')) - break; - - mb_len = g_utf8_skip[*(guchar *)p]; - - Xstrndup_a(part_str, srcp, cur_len + mb_len, ); - out_str = conv_codeset_strdup - (part_str, cur_encoding, out_encoding); - if (!out_str) { - g_warning("conv_encode_header(): code conversion failed\n"); - conv_unreadable_8bit(part_str); - out_str = g_strdup(part_str); - } - out_str_len = strlen(out_str); - - if (use_base64) - out_enc_str_len = B64LEN(out_str_len); - else - out_enc_str_len = - qp_get_q_encoding_len - ((guchar *)out_str); - - g_free(out_str); - - if (mimestr_len + out_enc_str_len <= left) { - cur_len += mb_len; - p += mb_len; - } else if (cur_len == 0) { - LBREAK_IF_REQUIRED(1, FALSE); - continue; - } else { - cont = TRUE; - break; - } - } - - if (cur_len > 0) { - Xstrndup_a(part_str, srcp, cur_len, ); - out_str = conv_codeset_strdup - (part_str, cur_encoding, out_encoding); - if (!out_str) { - g_warning("conv_encode_header(): code conversion failed\n"); - conv_unreadable_8bit(part_str); - out_str = g_strdup(part_str); - } - out_str_len = strlen(out_str); - - if (use_base64) - out_enc_str_len = B64LEN(out_str_len); - else - out_enc_str_len = - qp_get_q_encoding_len - ((guchar *)out_str); - - Xalloca(enc_str, out_enc_str_len + 1, ); - if (use_base64) - base64_encode(enc_str, - (guchar *)out_str, - out_str_len); - else - qp_q_encode(enc_str, (guchar *)out_str); - - g_free(out_str); - - /* output MIME-encoded string block */ - mime_block_len = mimestr_len + strlen(enc_str); - g_snprintf(destp, mime_block_len + 1, - MIMESEP_BEGIN "%s%s%s" MIMESEP_END, - out_encoding, mimesep_enc, enc_str); - destp += mime_block_len; - srcp += cur_len; - - left -= mime_block_len; - } - - LBREAK_IF_REQUIRED(cont, FALSE); - - if (cur_len == 0) - break; - } - } - - *destp = '\0'; -} - -#undef LBREAK_IF_REQUIRED - -gint conv_copy_file(const gchar *src, const gchar *dest, const gchar *encoding) -{ - FILE *src_fp, *dest_fp; - gchar buf[BUFFSIZE]; - CodeConverter *conv; - gboolean err = FALSE; - - if ((src_fp = g_fopen(src, "rb")) == NULL) { - FILE_OP_ERROR(src, "fopen"); - return -1; - } - if ((dest_fp = g_fopen(dest, "wb")) == NULL) { - FILE_OP_ERROR(dest, "fopen"); - fclose(src_fp); - return -1; - } - - if (change_file_mode_rw(dest_fp, dest) < 0) { - FILE_OP_ERROR(dest, "chmod"); - g_warning("can't change file mode\n"); - } - - conv = conv_code_converter_new(encoding, NULL); - - while (fgets(buf, sizeof(buf), src_fp) != NULL) { - gchar *outbuf; - - outbuf = conv_convert(conv, buf); - if (outbuf) { - fputs(outbuf, dest_fp); - g_free(outbuf); - } else - fputs(buf, dest_fp); - } - - conv_code_converter_destroy(conv); - - if (ferror(src_fp)) { - FILE_OP_ERROR(src, "fgets"); - err = TRUE; - } - fclose(src_fp); - if (fclose(dest_fp) == EOF) { - FILE_OP_ERROR(dest, "fclose"); - err = TRUE; - } - if (err) { - g_unlink(dest); - return -1; - } - - return 0; -} - -gint conv_copy_dir(const gchar *src, const gchar *dest, const gchar *encoding) -{ - GDir *dir; - const gchar *dir_name; - gchar *src_file; - gchar *dest_file; - - if ((dir = g_dir_open(src, 0, NULL)) == NULL) { - g_warning("failed to open directory: %s\n", src); - return -1; - } - - if (make_dir_hier(dest) < 0) { - g_dir_close(dir); - return -1; - } - - while ((dir_name = g_dir_read_name(dir)) != NULL) { - src_file = g_strconcat(src, G_DIR_SEPARATOR_S, dir_name, NULL); - dest_file = g_strconcat(dest, G_DIR_SEPARATOR_S, dir_name, - NULL); - if (is_file_exist(src_file)) - conv_copy_file(src_file, dest_file, encoding); - g_free(dest_file); - g_free(src_file); - } - - g_dir_close(dir); - - return 0; -} - -gchar *conv_filename_from_utf8(const gchar *utf8_file) -{ - gchar *fs_file; - GError *error = NULL; - - fs_file = g_filename_from_utf8(utf8_file, -1, NULL, NULL, &error); - if (error) { - g_warning("failed to convert encoding of file name: %s\n", - error->message); - g_error_free(error); - } - if (!fs_file) - fs_file = g_strdup(utf8_file); - - return fs_file; -} - -gchar *conv_filename_to_utf8(const gchar *fs_file) -{ - gchar *utf8_file; - GError *error = NULL; - - utf8_file = g_filename_to_utf8(fs_file, -1, NULL, NULL, &error); - if (error) { - g_warning("failed to convert encoding of file name: %s\n", - error->message); - g_error_free(error); - } - if (!utf8_file) - utf8_file = g_strdup(fs_file); - - return utf8_file; -} diff --git a/src/codeconv.h b/src/codeconv.h deleted file mode 100644 index 833b1402..00000000 --- a/src/codeconv.h +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __CODECONV_H__ -#define __CODECONV_H__ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <glib.h> -#include <iconv.h> - -typedef struct _CodeConverter CodeConverter; - -typedef enum -{ - C_AUTO, - C_US_ASCII, - C_UTF_8, - C_UTF_7, - C_ISO_8859_1, - C_ISO_8859_2, - C_ISO_8859_3, - C_ISO_8859_4, - C_ISO_8859_5, - C_ISO_8859_6, - C_ISO_8859_7, - C_ISO_8859_8, - C_ISO_8859_9, - C_ISO_8859_10, - C_ISO_8859_11, - C_ISO_8859_13, - C_ISO_8859_14, - C_ISO_8859_15, - C_BALTIC, - C_CP1250, - C_CP1251, - C_CP1252, - C_CP1253, - C_CP1254, - C_CP1255, - C_CP1256, - C_CP1257, - C_CP1258, - C_WINDOWS_1250, - C_WINDOWS_1251, - C_WINDOWS_1252, - C_WINDOWS_1253, - C_WINDOWS_1254, - C_WINDOWS_1255, - C_WINDOWS_1256, - C_WINDOWS_1257, - C_WINDOWS_1258, - C_KOI8_R, - C_KOI8_T, - C_KOI8_U, - C_ISO_2022_JP, - C_ISO_2022_JP_2, - C_ISO_2022_JP_3, - C_EUC_JP, - C_EUC_JP_MS, - C_SHIFT_JIS, - C_ISO_2022_KR, - C_EUC_KR, - C_ISO_2022_CN, - C_EUC_CN, - C_GB2312, - C_GBK, - C_EUC_TW, - C_BIG5, - C_BIG5_HKSCS, - C_TIS_620, - C_WINDOWS_874, - C_GEORGIAN_PS, - C_TCVN5712_1 -} CharSet; - -typedef gchar *(*CodeConvFunc) (const gchar *inbuf, gint *error); - -struct _CodeConverter -{ - CodeConvFunc code_conv_func; - gchar *src_encoding; - gchar *dest_encoding; -}; - -#define CS_AUTO "AUTO" -#define CS_US_ASCII "US-ASCII" -#define CS_ANSI_X3_4_1968 "ANSI_X3.4-1968" -#define CS_UTF_8 "UTF-8" -#define CS_UTF_7 "UTF-7" -#define CS_ISO_8859_1 "ISO-8859-1" -#define CS_ISO_8859_2 "ISO-8859-2" -#define CS_ISO_8859_3 "ISO-8859-3" -#define CS_ISO_8859_4 "ISO-8859-4" -#define CS_ISO_8859_5 "ISO-8859-5" -#define CS_ISO_8859_6 "ISO-8859-6" -#define CS_ISO_8859_7 "ISO-8859-7" -#define CS_ISO_8859_8 "ISO-8859-8" -#define CS_ISO_8859_9 "ISO-8859-9" -#define CS_ISO_8859_10 "ISO-8859-10" -#define CS_ISO_8859_11 "ISO-8859-11" -#define CS_ISO_8859_13 "ISO-8859-13" -#define CS_ISO_8859_14 "ISO-8859-14" -#define CS_ISO_8859_15 "ISO-8859-15" -#define CS_BALTIC "BALTIC" -#define CS_CP1250 "CP1250" -#define CS_CP1251 "CP1251" -#define CS_CP1252 "CP1252" -#define CS_CP1253 "CP1253" -#define CS_CP1254 "CP1254" -#define CS_CP1255 "CP1255" -#define CS_CP1256 "CP1256" -#define CS_CP1257 "CP1257" -#define CS_CP1258 "CP1258" -#define CS_WINDOWS_1250 "Windows-1250" -#define CS_WINDOWS_1251 "Windows-1251" -#define CS_WINDOWS_1252 "Windows-1252" -#define CS_WINDOWS_1253 "Windows-1253" -#define CS_WINDOWS_1254 "Windows-1254" -#define CS_WINDOWS_1255 "Windows-1255" -#define CS_WINDOWS_1256 "Windows-1256" -#define CS_WINDOWS_1257 "Windows-1257" -#define CS_WINDOWS_1258 "Windows-1258" -#define CS_KOI8_R "KOI8-R" -#define CS_KOI8_T "KOI8-T" -#define CS_KOI8_U "KOI8-U" -#define CS_ISO_2022_JP "ISO-2022-JP" -#define CS_ISO_2022_JP_2 "ISO-2022-JP-2" -#define CS_ISO_2022_JP_3 "ISO-2022-JP-3" -#define CS_EUC_JP "EUC-JP" -#define CS_EUCJP "EUCJP" -#define CS_EUC_JP_MS "EUC-JP-MS" -#define CS_SHIFT_JIS "Shift_JIS" -#define CS_SHIFT__JIS "SHIFT-JIS" -#define CS_SJIS "SJIS" -#define CS_X_SJIS "X-SJIS" -#define CS_ISO_2022_KR "ISO-2022-KR" -#define CS_EUC_KR "EUC-KR" -#define CS_ISO_2022_CN "ISO-2022-CN" -#define CS_EUC_CN "EUC-CN" -#define CS_GB2312 "GB2312" -#define CS_GBK "GBK" -#define CS_X_GBK "X-GBK" -#define CS_EUC_TW "EUC-TW" -#define CS_BIG5 "Big5" -#define CS_BIG5_HKSCS "BIG5-HKSCS" -#define CS_TIS_620 "TIS-620" -#define CS_WINDOWS_874 "Windows-874" -#define CS_GEORGIAN_PS "GEORGIAN-PS" -#define CS_TCVN5712_1 "TCVN5712-1" - -#define C_INTERNAL C_UTF_8 -#define CS_INTERNAL CS_UTF_8 - -//void conv_mb_alnum(gchar *str); - -CharSet conv_guess_ja_encoding (const gchar *str); - -gchar *conv_utf8todisp (const gchar *inbuf, - gint *error); -gchar *conv_localetodisp (const gchar *inbuf, - gint *error); - -CodeConverter *conv_code_converter_new (const gchar *src_encoding, - const gchar *dest_encoding); -void conv_code_converter_destroy (CodeConverter *conv); -gchar *conv_convert (CodeConverter *conv, - const gchar *inbuf); - -#define conv_codeset_strdup(inbuf, src_code, dest_code) \ - (conv_codeset_strdup_full(inbuf, src_code, dest_code, NULL)) - -gchar *conv_codeset_strdup_full (const gchar *inbuf, - const gchar *src_encoding, - const gchar *dest_encoding, - gint *error); - -CodeConvFunc conv_get_code_conv_func (const gchar *src_encoding, - const gchar *dest_encoding); - -gchar *conv_iconv_strdup (const gchar *inbuf, - const gchar *src_encoding, - const gchar *dest_encoding, - gint *error); -gchar *conv_iconv_strdup_with_cd (const gchar *inbuf, - iconv_t cd, - gint *error); - -const gchar *conv_get_charset_str (CharSet charset); -CharSet conv_get_charset_from_str (const gchar *charset); -CharSet conv_get_locale_charset (void); -const gchar *conv_get_locale_charset_str (void); -CharSet conv_get_internal_charset (void); -const gchar *conv_get_internal_charset_str (void); -CharSet conv_get_outgoing_charset (void); -const gchar *conv_get_outgoing_charset_str (void); -gboolean conv_is_multibyte_encoding (CharSet encoding); - -const gchar *conv_get_current_locale (void); -gboolean conv_is_ja_locale (void); - -gchar *conv_unmime_header (const gchar *str, - const gchar *default_encoding); -void conv_encode_header (gchar *dest, - gint len, - const gchar *src, - gint header_len, - gboolean addr_field, - const gchar *out_encoding); - -gint conv_copy_file (const gchar *src, - const gchar *dest, - const gchar *src_encoding); -gint conv_copy_dir (const gchar *src, - const gchar *dest, - const gchar *src_encoding); - -gchar *conv_filename_from_utf8 (const gchar *utf8_file); -gchar *conv_filename_to_utf8 (const gchar *fs_file); - -#endif /* __CODECONV_H__ */ diff --git a/src/prefs.c b/src/prefs.c deleted file mode 100644 index 4579df4f..00000000 --- a/src/prefs.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <glib.h> -#include <glib/gi18n.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include "prefs.h" -#include "codeconv.h" -#include "utils.h" - -typedef enum -{ - DUMMY_PARAM -} DummyEnum; - -void prefs_read_config(PrefParam *param, const gchar *label, - const gchar *rcfile, const gchar *encoding) -{ - FILE *fp; - gchar buf[PREFSBUFSIZE]; - gchar *block_label; - - g_return_if_fail(param != NULL); - g_return_if_fail(label != NULL); - g_return_if_fail(rcfile != NULL); - - debug_print("Reading configuration...\n"); - - prefs_set_default(param); - - if ((fp = g_fopen(rcfile, "rb")) == NULL) { - if (ENOENT != errno) FILE_OP_ERROR(rcfile, "fopen"); - return; - } - - block_label = g_strdup_printf("[%s]", label); - - /* search aiming block */ - while (fgets(buf, sizeof(buf), fp) != NULL) { - gint val; - - if (encoding) { - gchar *conv_str; - - conv_str = conv_codeset_strdup - (buf, encoding, CS_INTERNAL); - if (!conv_str) - conv_str = g_strdup(buf); - val = strncmp - (conv_str, block_label, strlen(block_label)); - g_free(conv_str); - } else - val = strncmp(buf, block_label, strlen(block_label)); - if (val == 0) { - debug_print("Found %s\n", block_label); - break; - } - } - g_free(block_label); - - while (fgets(buf, sizeof(buf), fp) != NULL) { - strretchomp(buf); - /* reached next block */ - if (buf[0] == '[') break; - - if (encoding) { - gchar *conv_str; - - conv_str = conv_codeset_strdup - (buf, encoding, CS_INTERNAL); - if (!conv_str) - conv_str = g_strdup(buf); - prefs_config_parse_one_line(param, conv_str); - g_free(conv_str); - } else - prefs_config_parse_one_line(param, buf); - } - - debug_print("Finished reading configuration.\n"); - fclose(fp); -} - -void prefs_config_parse_one_line(PrefParam *param, const gchar *buf) -{ - gint i; - gint name_len; - const gchar *value; - - for (i = 0; param[i].name != NULL; i++) { - name_len = strlen(param[i].name); - if (g_ascii_strncasecmp(buf, param[i].name, name_len)) - continue; - if (buf[name_len] != '=') - continue; - value = buf + name_len + 1; - /* debug_print("%s = %s\n", param[i].name, value); */ - - switch (param[i].type) { - case P_STRING: - g_free(*((gchar **)param[i].data)); - *((gchar **)param[i].data) = - *value ? g_strdup(value) : NULL; - break; - case P_INT: - *((gint *)param[i].data) = - (gint)atoi(value); - break; - case P_BOOL: - *((gboolean *)param[i].data) = - (*value == '0' || *value == '\0') - ? FALSE : TRUE; - break; - case P_ENUM: - *((DummyEnum *)param[i].data) = - (DummyEnum)atoi(value); - break; - case P_USHORT: - *((gushort *)param[i].data) = - (gushort)atoi(value); - break; - default: - break; - } - } -} - -#define TRY(func) \ -if (!(func)) \ -{ \ - g_warning(_("failed to write configuration to file\n")); \ - if (orig_fp) fclose(orig_fp); \ - prefs_file_close_revert(pfile); \ - g_free(rcpath); \ - g_free(block_label); \ - return; \ -} \ - -void prefs_write_config(PrefParam *param, const gchar *label, - const gchar *rcfile) -{ - FILE *orig_fp; - PrefFile *pfile; - gchar *rcpath; - gchar buf[PREFSBUFSIZE]; - gchar *block_label = NULL; - gboolean block_matched = FALSE; - - g_return_if_fail(param != NULL); - g_return_if_fail(label != NULL); - g_return_if_fail(rcfile != NULL); - - rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, rcfile, NULL); - if ((orig_fp = g_fopen(rcpath, "rb")) == NULL) { - if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen"); - } - - if ((pfile = prefs_file_open(rcpath)) == NULL) { - g_warning(_("failed to write configuration to file\n")); - if (orig_fp) fclose(orig_fp); - g_free(rcpath); - return; - } - - block_label = g_strdup_printf("[%s]", label); - - /* search aiming block */ - if (orig_fp) { - while (fgets(buf, sizeof(buf), orig_fp) != NULL) { - gint val; - - val = strncmp(buf, block_label, strlen(block_label)); - if (val == 0) { - debug_print(_("Found %s\n"), block_label); - block_matched = TRUE; - break; - } else - TRY(fputs(buf, pfile->fp) != EOF); - } - } - - TRY(fprintf(pfile->fp, "%s\n", block_label) > 0); - g_free(block_label); - block_label = NULL; - - /* write all param data to file */ - TRY(prefs_file_write_param(pfile, param) == 0); - - if (block_matched) { - while (fgets(buf, sizeof(buf), orig_fp) != NULL) { - /* next block */ - if (buf[0] == '[') { - TRY(fputc('\n', pfile->fp) != EOF && - fputs(buf, pfile->fp) != EOF); - break; - } - } - while (fgets(buf, sizeof(buf), orig_fp) != NULL) - TRY(fputs(buf, pfile->fp) != EOF); - } - - if (orig_fp) fclose(orig_fp); - if (prefs_file_close(pfile) < 0) - g_warning(_("failed to write configuration to file\n")); - g_free(rcpath); - - debug_print(_("Configuration is saved.\n")); -} - -gint prefs_file_write_param(PrefFile *pfile, PrefParam *param) -{ - gint i; - gchar buf[PREFSBUFSIZE]; - - for (i = 0; param[i].name != NULL; i++) { - switch (param[i].type) { - case P_STRING: - g_snprintf(buf, sizeof(buf), "%s=%s\n", param[i].name, - *((gchar **)param[i].data) ? - *((gchar **)param[i].data) : ""); - break; - case P_INT: - g_snprintf(buf, sizeof(buf), "%s=%d\n", param[i].name, - *((gint *)param[i].data)); - break; - case P_BOOL: - g_snprintf(buf, sizeof(buf), "%s=%d\n", param[i].name, - *((gboolean *)param[i].data)); - break; - case P_ENUM: - g_snprintf(buf, sizeof(buf), "%s=%d\n", param[i].name, - *((DummyEnum *)param[i].data)); - break; - case P_USHORT: - g_snprintf(buf, sizeof(buf), "%s=%d\n", param[i].name, - *((gushort *)param[i].data)); - break; - default: - buf[0] = '\0'; - } - - if (buf[0] != '\0') { - if (fputs(buf, pfile->fp) == EOF) { - perror("fputs"); - return -1; - } - } - } - - return 0; -} - -PrefFile *prefs_file_open(const gchar *path) -{ - PrefFile *pfile; - gchar *tmppath; - FILE *fp; - - g_return_val_if_fail(path != NULL, NULL); - - tmppath = g_strconcat(path, ".tmp", NULL); - if ((fp = g_fopen(tmppath, "wb")) == NULL) { - FILE_OP_ERROR(tmppath, "fopen"); - g_free(tmppath); - return NULL; - } - - if (change_file_mode_rw(fp, tmppath) < 0) - FILE_OP_ERROR(tmppath, "chmod"); - - g_free(tmppath); - - pfile = g_new(PrefFile, 1); - pfile->fp = fp; - pfile->path = g_strdup(path); - - return pfile; -} - -gint prefs_file_close(PrefFile *pfile) -{ - FILE *fp; - gchar *path; - gchar *tmppath; - gchar *bakpath = NULL; - - g_return_val_if_fail(pfile != NULL, -1); - - fp = pfile->fp; - path = pfile->path; - g_free(pfile); - - tmppath = g_strconcat(path, ".tmp", NULL); - if (fclose(fp) == EOF) { - FILE_OP_ERROR(tmppath, "fclose"); - g_unlink(tmppath); - g_free(path); - g_free(tmppath); - return -1; - } - - if (is_file_exist(path)) { - bakpath = g_strconcat(path, ".bak", NULL); - if (rename_force(path, bakpath) < 0) { - FILE_OP_ERROR(path, "rename"); - g_unlink(tmppath); - g_free(path); - g_free(tmppath); - g_free(bakpath); - return -1; - } - } - - if (rename_force(tmppath, path) < 0) { - FILE_OP_ERROR(tmppath, "rename"); - g_unlink(tmppath); - g_free(path); - g_free(tmppath); - g_free(bakpath); - return -1; - } - - g_free(path); - g_free(tmppath); - g_free(bakpath); - return 0; -} - -gint prefs_file_close_revert(PrefFile *pfile) -{ - gchar *tmppath; - - g_return_val_if_fail(pfile != NULL, -1); - - tmppath = g_strconcat(pfile->path, ".tmp", NULL); - fclose(pfile->fp); - if (g_unlink(tmppath) < 0) - FILE_OP_ERROR(tmppath, "unlink"); - g_free(tmppath); - g_free(pfile->path); - g_free(pfile); - - return 0; -} - -void prefs_set_default(PrefParam *param) -{ - gint i; - - g_return_if_fail(param != NULL); - - for (i = 0; param[i].name != NULL; i++) { - if (!param[i].data) continue; - - switch (param[i].type) { - case P_STRING: - if (param[i].defval != NULL) { - if (!g_ascii_strncasecmp(param[i].defval, "ENV_", 4)) { - const gchar *envstr; - gchar *tmp = NULL; - - envstr = g_getenv(param[i].defval + 4); - if (envstr) { - tmp = conv_codeset_strdup - (envstr, - conv_get_locale_charset_str(), - CS_UTF_8); - if (!tmp) { - g_warning("failed to convert character set."); - tmp = g_strdup(envstr); - } - } - *((gchar **)param[i].data) = tmp; - } else if (param[i].defval[0] == '~') - *((gchar **)param[i].data) = - g_strconcat(get_home_dir(), - param[i].defval + 1, - NULL); - else if (param[i].defval[0] != '\0') - *((gchar **)param[i].data) = - g_strdup(param[i].defval); - else - *((gchar **)param[i].data) = NULL; - } else - *((gchar **)param[i].data) = NULL; - break; - case P_INT: - if (param[i].defval != NULL) - *((gint *)param[i].data) = - (gint)atoi(param[i].defval); - else - *((gint *)param[i].data) = 0; - break; - case P_BOOL: - if (param[i].defval != NULL) { - if (!g_ascii_strcasecmp(param[i].defval, "TRUE")) - *((gboolean *)param[i].data) = TRUE; - else - *((gboolean *)param[i].data) = - atoi(param[i].defval) ? TRUE : FALSE; - } else - *((gboolean *)param[i].data) = FALSE; - break; - case P_ENUM: - if (param[i].defval != NULL) - *((DummyEnum*)param[i].data) = - (DummyEnum)atoi(param[i].defval); - else - *((DummyEnum *)param[i].data) = 0; - break; - case P_USHORT: - if (param[i].defval != NULL) - *((gushort *)param[i].data) = - (gushort)atoi(param[i].defval); - else - *((gushort *)param[i].data) = 0; - break; - default: - break; - } - } -} - -void prefs_free(PrefParam *param) -{ - gint i; - - g_return_if_fail(param != NULL); - - for (i = 0; param[i].name != NULL; i++) { - if (!param[i].data) continue; - - switch (param[i].type) { - case P_STRING: - g_free(*((gchar **)param[i].data)); - break; - default: - break; - } - } -} diff --git a/src/prefs.h b/src/prefs.h deleted file mode 100644 index f062d1eb..00000000 --- a/src/prefs.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __PREFS_H__ -#define __PREFS_H__ - -#include <glib.h> -#include <stdio.h> - -typedef struct _PrefParam PrefParam; -typedef struct _PrefFile PrefFile; - -#define PREFSBUFSIZE 1024 - -#define P_WID(wid) ((gpointer *)(wid)) - -typedef enum -{ - P_STRING, - P_INT, - P_BOOL, - P_ENUM, - P_USHORT, - P_OTHER -} PrefType; - -typedef void (*DataSetFunc) (PrefParam *pparam); -typedef void (*WidgetSetFunc) (PrefParam *pparam); - -struct _PrefParam { - gchar *name; - gchar *defval; - gpointer data; - PrefType type; - gpointer *widget; - DataSetFunc data_set_func; - WidgetSetFunc widget_set_func; -}; - -struct _PrefFile { - FILE *fp; - gchar *path; -}; - -void prefs_read_config (PrefParam *param, - const gchar *label, - const gchar *rcfile, - const gchar *encoding); -void prefs_config_parse_one_line(PrefParam *param, - const gchar *buf); -void prefs_write_config (PrefParam *param, - const gchar *label, - const gchar *rcfile); - -PrefFile *prefs_file_open (const gchar *path); -gint prefs_file_write_param (PrefFile *pfile, - PrefParam *param); -gint prefs_file_close (PrefFile *pfile); -gint prefs_file_close_revert (PrefFile *pfile); - -void prefs_set_default (PrefParam *param); -void prefs_free (PrefParam *param); - -#endif /* __PREFS_H__ */ diff --git a/src/quoted-printable.c b/src/quoted-printable.c deleted file mode 100644 index cea0b704..00000000 --- a/src/quoted-printable.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2003 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <glib.h> -#include <ctype.h> - -static gboolean get_hex_value(guchar *out, gchar c1, gchar c2); -static void get_hex_str(gchar *out, guchar ch); - -#define MAX_LINELEN 76 - -#define IS_LBREAK(p) \ - (*(p) == '\0' || *(p) == '\n' || (*(p) == '\r' && *((p) + 1) == '\n')) - -#define SOFT_LBREAK_IF_REQUIRED(n) \ - if (len + (n) > MAX_LINELEN || \ - (len + (n) == MAX_LINELEN && (!IS_LBREAK(inp + 1)))) { \ - *outp++ = '='; \ - *outp++ = '\n'; \ - len = 0; \ - } - -void qp_encode_line(gchar *out, const guchar *in) -{ - const guchar *inp = in; - gchar *outp = out; - guchar ch; - gint len = 0; - - while (*inp != '\0') { - ch = *inp; - - if (IS_LBREAK(inp)) { - *outp++ = '\n'; - len = 0; - if (*inp == '\r') - inp++; - inp++; - } else if (ch == '\t' || ch == ' ') { - if (IS_LBREAK(inp + 1)) { - SOFT_LBREAK_IF_REQUIRED(3); - *outp++ = '='; - get_hex_str(outp, ch); - outp += 2; - len += 3; - inp++; - } else { - SOFT_LBREAK_IF_REQUIRED(1); - *outp++ = *inp++; - len++; - } - } else if ((ch >= 33 && ch <= 60) || (ch >= 62 && ch <= 126)) { - SOFT_LBREAK_IF_REQUIRED(1); - *outp++ = *inp++; - len++; - } else { - SOFT_LBREAK_IF_REQUIRED(3); - *outp++ = '='; - get_hex_str(outp, ch); - outp += 2; - len += 3; - inp++; - } - } - - if (len > 0) - *outp++ = '\n'; - - *outp = '\0'; -} - -gint qp_decode_line(gchar *str) -{ - gchar *inp = str, *outp = str; - - while (*inp != '\0') { - if (*inp == '=') { - if (inp[1] && inp[2] && - get_hex_value((guchar *)outp, inp[1], inp[2]) - == TRUE) { - inp += 3; - } else if (inp[1] == '\0' || g_ascii_isspace(inp[1])) { - /* soft line break */ - break; - } else { - /* broken QP string */ - *outp = *inp++; - } - } else { - *outp = *inp++; - } - outp++; - } - - *outp = '\0'; - - return outp - str; -} - -gint qp_decode_q_encoding(guchar *out, const gchar *in, gint inlen) -{ - const gchar *inp = in; - guchar *outp = out; - - if (inlen < 0) - inlen = G_MAXINT; - - while (inp - in < inlen && *inp != '\0') { - if (*inp == '=' && inp + 3 - in <= inlen) { - if (get_hex_value(outp, inp[1], inp[2]) == TRUE) { - inp += 3; - } else { - *outp = *inp++; - } - } else if (*inp == '_') { - *outp = ' '; - inp++; - } else { - *outp = *inp++; - } - outp++; - } - - *outp = '\0'; - - return outp - out; -} - -gint qp_get_q_encoding_len(const guchar *str) -{ - const guchar *inp = str; - gint len = 0; - - while (*inp != '\0') { - if (*inp == 0x20) - len++; - else if (*inp == '=' || *inp == '?' || *inp == '_' || - *inp < 32 || *inp > 127 || g_ascii_isspace(*inp)) - len += 3; - else - len++; - - inp++; - } - - return len; -} - -void qp_q_encode(gchar *out, const guchar *in) -{ - const guchar *inp = in; - gchar *outp = out; - - while (*inp != '\0') { - if (*inp == 0x20) - *outp++ = '_'; - else if (*inp == '=' || *inp == '?' || *inp == '_' || - *inp < 32 || *inp > 127 || g_ascii_isspace(*inp)) { - *outp++ = '='; - get_hex_str(outp, *inp); - outp += 2; - } else - *outp++ = *inp; - - inp++; - } - - *outp = '\0'; -} - -#define HEX_TO_INT(val, hex) \ -{ \ - gchar c = hex; \ - \ - if ('0' <= c && c <= '9') { \ - val = c - '0'; \ - } else if ('a' <= c && c <= 'f') { \ - val = c - 'a' + 10; \ - } else if ('A' <= c && c <= 'F') { \ - val = c - 'A' + 10; \ - } else { \ - val = -1; \ - } \ -} - -static gboolean get_hex_value(guchar *out, gchar c1, gchar c2) -{ - gint hi, lo; - - HEX_TO_INT(hi, c1); - HEX_TO_INT(lo, c2); - - if (hi == -1 || lo == -1) - return FALSE; - - *out = (hi << 4) + lo; - return TRUE; -} - -#define INT_TO_HEX(hex, val) \ -{ \ - if ((val) < 10) \ - hex = '0' + (val); \ - else \ - hex = 'A' + (val) - 10; \ -} - -static void get_hex_str(gchar *out, guchar ch) -{ - gchar hex; - - INT_TO_HEX(hex, ch >> 4); - *out++ = hex; - INT_TO_HEX(hex, ch & 0x0f); - *out++ = hex; -} diff --git a/src/quoted-printable.h b/src/quoted-printable.h deleted file mode 100644 index e5abf4f7..00000000 --- a/src/quoted-printable.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2003 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __QUOTED_PRINTABLE_H__ -#define __QUOTED_PRINTABLE_H__ - -#include <glib.h> - -void qp_encode_line (gchar *out, - const guchar *in); -gint qp_decode_line (gchar *str); - -gint qp_decode_q_encoding (guchar *out, - const gchar *in, - gint inlen); -gint qp_get_q_encoding_len (const guchar *str); -void qp_q_encode (gchar *out, - const guchar *in); - -#endif /* __QUOTED_PRINTABLE_H__ */ diff --git a/src/session.c b/src/session.c deleted file mode 100644 index 6e7fa4e9..00000000 --- a/src/session.c +++ /dev/null @@ -1,793 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "defs.h" - -#include <glib.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <time.h> -#include <errno.h> - -#include "session.h" -#include "utils.h" - -static gint session_connect_cb (SockInfo *sock, - gpointer data); -static gint session_close (Session *session); - -static gboolean session_timeout_cb (gpointer data); - -static gboolean session_recv_msg_idle_cb (gpointer data); -static gboolean session_recv_data_idle_cb (gpointer data); - -static gboolean session_read_msg_cb (SockInfo *source, - GIOCondition condition, - gpointer data); -static gboolean session_read_data_cb (SockInfo *source, - GIOCondition condition, - gpointer data); -static gboolean session_write_msg_cb (SockInfo *source, - GIOCondition condition, - gpointer data); -static gboolean session_write_data_cb (SockInfo *source, - GIOCondition condition, - gpointer data); - - -void session_init(Session *session) -{ - session->type = SESSION_UNKNOWN; - session->sock = NULL; - session->server = NULL; - session->port = 0; -#if USE_SSL - session->ssl_type = SSL_NONE; -#endif - session->nonblocking = TRUE; - session->state = SESSION_READY; - session->last_access_time = time(NULL); - - g_get_current_time(&session->tv_prev); - - session->conn_id = 0; - - session->io_tag = 0; - - session->read_buf_p = session->read_buf; - session->read_buf_len = 0; - - session->read_msg_buf = g_string_sized_new(1024); - session->read_data_buf = g_byte_array_new(); - - session->write_buf = NULL; - session->write_buf_p = NULL; - session->write_buf_len = 0; - - session->write_data = NULL; - session->write_data_p = NULL; - session->write_data_len = 0; - - session->timeout_tag = 0; - session->timeout_interval = 0; - - session->data = NULL; -} - -gint session_connect(Session *session, const gchar *server, gushort port) -{ -#ifdef G_OS_UNIX - session->server = g_strdup(server); - session->port = port; - - session->conn_id = sock_connect_async(server, port, session_connect_cb, - session); - if (session->conn_id < 0) { - g_warning("can't connect to server."); - session_close(session); - return -1; - } - - return 0; -#else - SockInfo *sock; - - session->server = g_strdup(server); - session->port = port; - - sock = sock_connect(server, port); - if (sock == NULL) { - g_warning("can't connect to server."); - session_close(session); - return -1; - } - - return session_connect_cb(sock, session); -#endif -} - -static gint session_connect_cb(SockInfo *sock, gpointer data) -{ - Session *session = SESSION(data); - - session->conn_id = 0; - - if (!sock) { - g_warning("can't connect to server."); - session->state = SESSION_ERROR; - return -1; - } - - session->sock = sock; - -#if USE_SSL - if (session->ssl_type == SSL_TUNNEL) { - sock_set_nonblocking_mode(sock, FALSE); - if (!ssl_init_socket(sock)) { - g_warning("can't initialize SSL."); - session->state = SESSION_ERROR; - return -1; - } - } -#endif - - sock_set_nonblocking_mode(sock, session->nonblocking); - - debug_print("session (%p): connected\n", session); - - session->state = SESSION_RECV; - session->io_tag = sock_add_watch(session->sock, G_IO_IN, - session_read_msg_cb, - session); - - return 0; -} - -gint session_disconnect(Session *session) -{ - session_close(session); - return 0; -} - -void session_destroy(Session *session) -{ - g_return_if_fail(session != NULL); - g_return_if_fail(session->destroy != NULL); - - session_close(session); - session->destroy(session); - g_free(session->server); - g_string_free(session->read_msg_buf, TRUE); - g_byte_array_free(session->read_data_buf, TRUE); - g_free(session->read_data_terminator); - g_free(session->write_buf); - - debug_print("session (%p): destroyed\n", session); - - g_free(session); -} - -gboolean session_is_connected(Session *session) -{ - return (session->state == SESSION_READY || - session->state == SESSION_SEND || - session->state == SESSION_RECV); -} - -void session_set_access_time(Session *session) -{ - session->last_access_time = time(NULL); -} - -void session_set_timeout(Session *session, guint interval) -{ - if (session->timeout_tag > 0) - g_source_remove(session->timeout_tag); - - session->timeout_interval = interval; - if (interval > 0) - session->timeout_tag = - g_timeout_add(interval, session_timeout_cb, session); - else - session->timeout_tag = 0; -} - -static gboolean session_timeout_cb(gpointer data) -{ - Session *session = SESSION(data); - - g_warning("session timeout.\n"); - - if (session->io_tag > 0) { - g_source_remove(session->io_tag); - session->io_tag = 0; - } - - session->timeout_tag = 0; - session->state = SESSION_TIMEOUT; - - return FALSE; -} - -void session_set_recv_message_notify(Session *session, - RecvMsgNotify notify_func, gpointer data) -{ - session->recv_msg_notify = notify_func; - session->recv_msg_notify_data = data; -} - -void session_set_recv_data_progressive_notify - (Session *session, - RecvDataProgressiveNotify notify_func, - gpointer data) -{ - session->recv_data_progressive_notify = notify_func, - session->recv_data_progressive_notify_data = data; -} - -void session_set_recv_data_notify(Session *session, RecvDataNotify notify_func, - gpointer data) -{ - session->recv_data_notify = notify_func; - session->recv_data_notify_data = data; -} - -void session_set_send_data_progressive_notify - (Session *session, - SendDataProgressiveNotify notify_func, - gpointer data) -{ - session->send_data_progressive_notify = notify_func; - session->send_data_progressive_notify_data = data; -} - -void session_set_send_data_notify(Session *session, SendDataNotify notify_func, - gpointer data) -{ - session->send_data_notify = notify_func; - session->send_data_notify_data = data; -} - -static gint session_close(Session *session) -{ - g_return_val_if_fail(session != NULL, -1); - -#ifdef G_OS_UNIX - if (session->conn_id > 0) { - sock_connect_async_cancel(session->conn_id); - session->conn_id = 0; - debug_print("session (%p): connection cancelled\n", session); - } -#endif - - session_set_timeout(session, 0); - - if (session->io_tag > 0) { - g_source_remove(session->io_tag); - session->io_tag = 0; - } - - if (session->sock) { - sock_close(session->sock); - session->sock = NULL; - session->state = SESSION_DISCONNECTED; - debug_print("session (%p): closed\n", session); - } - - return 0; -} - -#if USE_SSL -gint session_start_tls(Session *session) -{ - gboolean nb_mode; - - nb_mode = sock_is_nonblocking_mode(session->sock); - - if (nb_mode) - sock_set_nonblocking_mode(session->sock, FALSE); - - if (!ssl_init_socket_with_method(session->sock, SSL_METHOD_TLSv1)) { - g_warning("can't start TLS session.\n"); - if (nb_mode) - sock_set_nonblocking_mode(session->sock, TRUE); - return -1; - } - - if (nb_mode) - sock_set_nonblocking_mode(session->sock, session->nonblocking); - - return 0; -} -#endif - -gint session_send_msg(Session *session, SessionMsgType type, const gchar *msg) -{ - gboolean ret; - - g_return_val_if_fail(session->write_buf == NULL, -1); - g_return_val_if_fail(msg != NULL, -1); - g_return_val_if_fail(msg[0] != '\0', -1); - - session->state = SESSION_SEND; - session->write_buf = g_strconcat(msg, "\r\n", NULL); - session->write_buf_p = session->write_buf; - session->write_buf_len = strlen(msg) + 2; - - ret = session_write_msg_cb(session->sock, G_IO_OUT, session); - - if (ret == TRUE) - session->io_tag = sock_add_watch(session->sock, G_IO_OUT, - session_write_msg_cb, session); - else if (session->state == SESSION_ERROR) - return -1; - - return 0; -} - -gint session_recv_msg(Session *session) -{ - g_return_val_if_fail(session->read_msg_buf->len == 0, -1); - - session->state = SESSION_RECV; - - if (session->read_buf_len > 0) - g_idle_add(session_recv_msg_idle_cb, session); - else - session->io_tag = sock_add_watch(session->sock, G_IO_IN, - session_read_msg_cb, session); - - return 0; -} - -static gboolean session_recv_msg_idle_cb(gpointer data) -{ - Session *session = SESSION(data); - gboolean ret; - - ret = session_read_msg_cb(session->sock, G_IO_IN, session); - - if (ret == TRUE) - session->io_tag = sock_add_watch(session->sock, G_IO_IN, - session_read_msg_cb, session); - - return FALSE; -} - -gint session_send_data(Session *session, const guchar *data, guint size) -{ - gboolean ret; - - g_return_val_if_fail(session->write_data == NULL, -1); - g_return_val_if_fail(data != NULL, -1); - g_return_val_if_fail(size != 0, -1); - - session->state = SESSION_SEND; - - session->write_data = data; - session->write_data_p = session->write_data; - session->write_data_len = size; - g_get_current_time(&session->tv_prev); - - ret = session_write_data_cb(session->sock, G_IO_OUT, session); - - if (ret == TRUE) - session->io_tag = sock_add_watch(session->sock, G_IO_OUT, - session_write_data_cb, - session); - else if (session->state == SESSION_ERROR) - return -1; - - return 0; -} - -gint session_recv_data(Session *session, guint size, const gchar *terminator) -{ - g_return_val_if_fail(session->read_data_buf->len == 0, -1); - - session->state = SESSION_RECV; - - g_free(session->read_data_terminator); - session->read_data_terminator = g_strdup(terminator); - g_get_current_time(&session->tv_prev); - - if (session->read_buf_len > 0) - g_idle_add(session_recv_data_idle_cb, session); - else - session->io_tag = sock_add_watch(session->sock, G_IO_IN, - session_read_data_cb, session); - - return 0; -} - -static gboolean session_recv_data_idle_cb(gpointer data) -{ - Session *session = SESSION(data); - gboolean ret; - - ret = session_read_data_cb(session->sock, G_IO_IN, session); - - if (ret == TRUE) - session->io_tag = sock_add_watch(session->sock, G_IO_IN, - session_read_data_cb, session); - - return FALSE; -} - -static gboolean session_read_msg_cb(SockInfo *source, GIOCondition condition, - gpointer data) -{ - Session *session = SESSION(data); - gchar buf[SESSION_BUFFSIZE]; - gint line_len; - gchar *newline; - gchar *msg; - gint ret; - - g_return_val_if_fail(condition == G_IO_IN, FALSE); - - session_set_timeout(session, session->timeout_interval); - - if (session->read_buf_len == 0) { - gint read_len; - - read_len = sock_read(session->sock, session->read_buf, - SESSION_BUFFSIZE - 1); - - if (read_len == 0) { - g_warning("sock_read: received EOF\n"); - session->state = SESSION_EOF; - return FALSE; - } - - if (read_len < 0) { - switch (errno) { - case EAGAIN: - return TRUE; - default: - g_warning("sock_read: %s\n", g_strerror(errno)); - session->state = SESSION_ERROR; - return FALSE; - } - } - - session->read_buf_len = read_len; - } - - if ((newline = memchr(session->read_buf_p, '\n', session->read_buf_len)) - != NULL) - line_len = newline - session->read_buf_p + 1; - else - line_len = session->read_buf_len; - - if (line_len == 0) - return TRUE; - - memcpy(buf, session->read_buf_p, line_len); - buf[line_len] = '\0'; - - g_string_append(session->read_msg_buf, buf); - - session->read_buf_len -= line_len; - if (session->read_buf_len == 0) - session->read_buf_p = session->read_buf; - else - session->read_buf_p += line_len; - - /* incomplete read */ - if (buf[line_len - 1] != '\n') - return TRUE; - - /* complete */ - if (session->io_tag > 0) { - g_source_remove(session->io_tag); - session->io_tag = 0; - } - - /* callback */ - msg = g_strdup(session->read_msg_buf->str); - strretchomp(msg); - g_string_truncate(session->read_msg_buf, 0); - - ret = session->recv_msg(session, msg); - session->recv_msg_notify(session, msg, session->recv_msg_notify_data); - - g_free(msg); - - if (ret < 0) - session->state = SESSION_ERROR; - - return FALSE; -} - -static gboolean session_read_data_cb(SockInfo *source, GIOCondition condition, - gpointer data) -{ - Session *session = SESSION(data); - GByteArray *data_buf; - gint terminator_len; - gboolean complete = FALSE; - guint data_len; - gint ret; - - g_return_val_if_fail(condition == G_IO_IN, FALSE); - - session_set_timeout(session, session->timeout_interval); - - if (session->read_buf_len == 0) { - gint read_len; - - read_len = sock_read(session->sock, session->read_buf, - SESSION_BUFFSIZE); - - if (read_len == 0) { - g_warning("sock_read: received EOF\n"); - session->state = SESSION_EOF; - return FALSE; - } - - if (read_len < 0) { - switch (errno) { - case EAGAIN: - return TRUE; - default: - g_warning("sock_read: %s\n", g_strerror(errno)); - session->state = SESSION_ERROR; - return FALSE; - } - } - - session->read_buf_len = read_len; - } - - data_buf = session->read_data_buf; - terminator_len = strlen(session->read_data_terminator); - - if (session->read_buf_len == 0) - return TRUE; - - g_byte_array_append(data_buf, session->read_buf_p, - session->read_buf_len); - - session->read_buf_len = 0; - session->read_buf_p = session->read_buf; - - /* check if data is terminated */ - if (data_buf->len >= terminator_len) { - if (memcmp(data_buf->data, session->read_data_terminator, - terminator_len) == 0) - complete = TRUE; - else if (data_buf->len >= terminator_len + 2 && - memcmp(data_buf->data + data_buf->len - - (terminator_len + 2), "\r\n", 2) == 0 && - memcmp(data_buf->data + data_buf->len - - terminator_len, session->read_data_terminator, - terminator_len) == 0) - complete = TRUE; - } - - /* incomplete read */ - if (!complete) { - GTimeVal tv_cur; - - g_get_current_time(&tv_cur); - if (tv_cur.tv_sec - session->tv_prev.tv_sec > 0 || - tv_cur.tv_usec - session->tv_prev.tv_usec > - UI_REFRESH_INTERVAL) { - session->recv_data_progressive_notify - (session, data_buf->len, 0, - session->recv_data_progressive_notify_data); - g_get_current_time(&session->tv_prev); - } - return TRUE; - } - - /* complete */ - if (session->io_tag > 0) { - g_source_remove(session->io_tag); - session->io_tag = 0; - } - - data_len = data_buf->len - terminator_len; - - /* callback */ - ret = session->recv_data_finished(session, (gchar *)data_buf->data, - data_len); - - g_byte_array_set_size(data_buf, 0); - - session->recv_data_notify(session, data_len, - session->recv_data_notify_data); - - if (ret < 0) - session->state = SESSION_ERROR; - - return FALSE; -} - -static gint session_write_buf(Session *session) -{ - gint write_len; - gint to_write_len; - - g_return_val_if_fail(session->write_buf != NULL, -1); - g_return_val_if_fail(session->write_buf_p != NULL, -1); - g_return_val_if_fail(session->write_buf_len > 0, -1); - - to_write_len = session->write_buf_len - - (session->write_buf_p - session->write_buf); - to_write_len = MIN(to_write_len, SESSION_BUFFSIZE); - - write_len = sock_write(session->sock, session->write_buf_p, - to_write_len); - - if (write_len < 0) { - switch (errno) { - case EAGAIN: - write_len = 0; - break; - default: - g_warning("sock_write: %s\n", g_strerror(errno)); - session->state = SESSION_ERROR; - return -1; - } - } - - /* incomplete write */ - if (session->write_buf_p - session->write_buf + write_len < - session->write_buf_len) { - session->write_buf_p += write_len; - return 1; - } - - g_free(session->write_buf); - session->write_buf = NULL; - session->write_buf_p = NULL; - session->write_buf_len = 0; - - return 0; -} - -static gint session_write_data(Session *session) -{ - gint write_len; - gint to_write_len; - - g_return_val_if_fail(session->write_data != NULL, -1); - g_return_val_if_fail(session->write_data_p != NULL, -1); - g_return_val_if_fail(session->write_data_len > 0, -1); - - to_write_len = session->write_data_len - - (session->write_data_p - session->write_data); - to_write_len = MIN(to_write_len, SESSION_BUFFSIZE); - - write_len = sock_write(session->sock, session->write_data_p, - to_write_len); - - if (write_len < 0) { - switch (errno) { - case EAGAIN: - write_len = 0; - break; - default: - g_warning("sock_write: %s\n", g_strerror(errno)); - session->state = SESSION_ERROR; - return -1; - } - } - - /* incomplete write */ - if (session->write_data_p - session->write_data + write_len < - session->write_data_len) { - session->write_data_p += write_len; - return 1; - } - - session->write_data = NULL; - session->write_data_p = NULL; - session->write_data_len = 0; - - return 0; -} - -static gboolean session_write_msg_cb(SockInfo *source, GIOCondition condition, - gpointer data) -{ - Session *session = SESSION(data); - gint ret; - - g_return_val_if_fail(condition == G_IO_OUT, FALSE); - g_return_val_if_fail(session->write_buf != NULL, FALSE); - g_return_val_if_fail(session->write_buf_p != NULL, FALSE); - g_return_val_if_fail(session->write_buf_len > 0, FALSE); - - ret = session_write_buf(session); - - if (ret < 0) { - session->state = SESSION_ERROR; - return FALSE; - } else if (ret > 0) - return TRUE; - - if (session->io_tag > 0) { - g_source_remove(session->io_tag); - session->io_tag = 0; - } - - session_recv_msg(session); - - return FALSE; -} - -static gboolean session_write_data_cb(SockInfo *source, - GIOCondition condition, gpointer data) -{ - Session *session = SESSION(data); - guint write_data_len; - gint ret; - - g_return_val_if_fail(condition == G_IO_OUT, FALSE); - g_return_val_if_fail(session->write_data != NULL, FALSE); - g_return_val_if_fail(session->write_data_p != NULL, FALSE); - g_return_val_if_fail(session->write_data_len > 0, FALSE); - - write_data_len = session->write_data_len; - - ret = session_write_data(session); - - if (ret < 0) { - session->state = SESSION_ERROR; - return FALSE; - } else if (ret > 0) { - GTimeVal tv_cur; - - g_get_current_time(&tv_cur); - if (tv_cur.tv_sec - session->tv_prev.tv_sec > 0 || - tv_cur.tv_usec - session->tv_prev.tv_usec > - UI_REFRESH_INTERVAL) { - session_set_timeout(session, session->timeout_interval); - session->send_data_progressive_notify - (session, - session->write_data_p - session->write_data, - write_data_len, - session->send_data_progressive_notify_data); - g_get_current_time(&session->tv_prev); - } - return TRUE; - } - - if (session->io_tag > 0) { - g_source_remove(session->io_tag); - session->io_tag = 0; - } - - /* callback */ - ret = session->send_data_finished(session, write_data_len); - session->send_data_notify(session, write_data_len, - session->send_data_notify_data); - - return FALSE; -} diff --git a/src/session.h b/src/session.h deleted file mode 100644 index 9ed0eaf4..00000000 --- a/src/session.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __SESSION_H__ -#define __SESSION_H__ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <glib.h> - -#include <time.h> -#include <unistd.h> - -#include "socket.h" - -#define SESSION_BUFFSIZE 4096 - -typedef struct _Session Session; - -#define SESSION(obj) ((Session *)obj) - -typedef enum { - SESSION_UNKNOWN, - SESSION_IMAP, - SESSION_NEWS, - SESSION_SMTP, - SESSION_POP3 -} SessionType; - -typedef enum { - SESSION_READY, - SESSION_SEND, - SESSION_RECV, - SESSION_EOF, - SESSION_TIMEOUT, - SESSION_ERROR, - SESSION_DISCONNECTED -} SessionState; - -typedef enum -{ - SESSION_MSG_NORMAL, - SESSION_MSG_SEND_DATA, - SESSION_MSG_RECV_DATA, - SESSION_MSG_CONTROL, - SESSION_MSG_ERROR, - SESSION_MSG_UNKNOWN -} SessionMsgType; - -typedef gint (*RecvMsgNotify) (Session *session, - const gchar *msg, - gpointer user_data); -typedef gint (*RecvDataProgressiveNotify) (Session *session, - guint cur_len, - guint total_len, - gpointer user_data); -typedef gint (*RecvDataNotify) (Session *session, - guint len, - gpointer user_data); -typedef gint (*SendDataProgressiveNotify) (Session *session, - guint cur_len, - guint total_len, - gpointer user_data); -typedef gint (*SendDataNotify) (Session *session, - guint len, - gpointer user_data); - -struct _Session -{ - SessionType type; - - SockInfo *sock; - - gchar *server; - gushort port; - -#if USE_SSL - SSLType ssl_type; -#endif - - gboolean nonblocking; - - SessionState state; - - time_t last_access_time; - GTimeVal tv_prev; - - gint conn_id; - - gint io_tag; - - gchar read_buf[SESSION_BUFFSIZE]; - gchar *read_buf_p; - gint read_buf_len; - - GString *read_msg_buf; - GByteArray *read_data_buf; - gchar *read_data_terminator; - - /* buffer for short messages */ - gchar *write_buf; - gchar *write_buf_p; - gint write_buf_len; - - /* buffer for large data */ - const guchar *write_data; - const guchar *write_data_p; - gint write_data_len; - - guint timeout_tag; - guint timeout_interval; - - gpointer data; - - /* virtual methods to parse server responses */ - gint (*recv_msg) (Session *session, - const gchar *msg); - - gint (*send_data_finished) (Session *session, - guint len); - gint (*recv_data_finished) (Session *session, - guchar *data, - guint len); - - void (*destroy) (Session *session); - - /* notification functions */ - RecvMsgNotify recv_msg_notify; - RecvDataProgressiveNotify recv_data_progressive_notify; - RecvDataNotify recv_data_notify; - SendDataProgressiveNotify send_data_progressive_notify; - SendDataNotify send_data_notify; - - gpointer recv_msg_notify_data; - gpointer recv_data_progressive_notify_data; - gpointer recv_data_notify_data; - gpointer send_data_progressive_notify_data; - gpointer send_data_notify_data; -}; - -void session_init (Session *session); -gint session_connect (Session *session, - const gchar *server, - gushort port); -gint session_disconnect (Session *session); -void session_destroy (Session *session); -gboolean session_is_connected (Session *session); - -void session_set_access_time (Session *session); - -void session_set_timeout (Session *session, - guint interval); - -void session_set_recv_message_notify (Session *session, - RecvMsgNotify notify_func, - gpointer data); -void session_set_recv_data_progressive_notify - (Session *session, - RecvDataProgressiveNotify notify_func, - gpointer data); -void session_set_recv_data_notify (Session *session, - RecvDataNotify notify_func, - gpointer data); -void session_set_send_data_progressive_notify - (Session *session, - SendDataProgressiveNotify notify_func, - gpointer data); -void session_set_send_data_notify (Session *session, - SendDataNotify notify_func, - gpointer data); - -#if USE_SSL -gint session_start_tls (Session *session); -#endif - -gint session_send_msg (Session *session, - SessionMsgType type, - const gchar *msg); -gint session_recv_msg (Session *session); -gint session_send_data (Session *session, - const guchar *data, - guint size); -gint session_recv_data (Session *session, - guint size, - const gchar *terminator); - -#endif /* __SESSION_H__ */ diff --git a/src/socket.c b/src/socket.c deleted file mode 100644 index 17063ab1..00000000 --- a/src/socket.c +++ /dev/null @@ -1,1397 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <glib.h> -#include <sys/time.h> -#include <sys/types.h> -#ifdef G_OS_WIN32 -# include <winsock2.h> -#else -# if HAVE_SYS_WAIT_H -# include <sys/wait.h> -# endif -# include <sys/socket.h> -# include <sys/un.h> -# include <netinet/in.h> -# include <arpa/inet.h> -# include <netdb.h> -#endif /* G_OS_WIN32 */ -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#include <stdarg.h> -#include <fcntl.h> -#include <errno.h> -#include <signal.h> -#include <setjmp.h> -#if HAVE_SYS_SELECT_H -# include <sys/select.h> -#endif - -#include "socket.h" -#if USE_SSL -# include "ssl.h" -#endif - -#define BUFFSIZE 8192 - -typedef gint (*SockAddrFunc) (GList *addr_list, - gpointer data); - -typedef struct _SockConnectData SockConnectData; -typedef struct _SockLookupData SockLookupData; -typedef struct _SockAddrData SockAddrData; -typedef struct _SockSource SockSource; - -struct _SockConnectData { - gint id; - gchar *hostname; - gushort port; - GList *addr_list; - GList *cur_addr; - SockLookupData *lookup_data; - GIOChannel *channel; - guint io_tag; - SockConnectFunc func; - gpointer data; -}; - -struct _SockLookupData { - gchar *hostname; - pid_t child_pid; - GIOChannel *channel; - guint io_tag; - SockAddrFunc func; - gpointer data; -}; - -struct _SockAddrData { - gint family; - gint socktype; - gint protocol; - gint addr_len; - struct sockaddr *addr; -}; - -struct _SockSource { - GSource parent; - SockInfo *sock; -}; - -static guint io_timeout = 60; - -static GList *sock_connect_data_list = NULL; - -static gboolean sock_prepare (GSource *source, - gint *timeout); -static gboolean sock_check (GSource *source); -static gboolean sock_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data); - -GSourceFuncs sock_watch_funcs = { - sock_prepare, - sock_check, - sock_dispatch, - NULL -}; - -static gint sock_connect_with_timeout (gint sock, - const struct sockaddr *serv_addr, - gint addrlen, - guint timeout_secs); - -#ifndef INET6 -static gint sock_connect_by_hostname (gint sock, - const gchar *hostname, - gushort port); -#else -static gint sock_connect_by_getaddrinfo (const gchar *hostname, - gushort port); -#endif - -#ifdef G_OS_UNIX -static void sock_address_list_free (GList *addr_list); - -static gboolean sock_connect_async_cb (GIOChannel *source, - GIOCondition condition, - gpointer data); -static gint sock_connect_async_get_address_info_cb - (GList *addr_list, - gpointer data); - -static gint sock_connect_address_list_async (SockConnectData *conn_data); - -static gboolean sock_get_address_info_async_cb (GIOChannel *source, - GIOCondition condition, - gpointer data); -static SockLookupData *sock_get_address_info_async - (const gchar *hostname, - gushort port, - SockAddrFunc func, - gpointer data); -static gint sock_get_address_info_async_cancel (SockLookupData *lookup_data); -#endif /* G_OS_UNIX */ - - -gint sock_init(void) -{ -#ifdef G_OS_WIN32 - WSADATA wsadata; - gint result; - - result = WSAStartup(MAKEWORD(2, 2), &wsadata); - if (result != NO_ERROR) { - g_warning("WSAStartup() failed\n"); - return -1; - } -#endif - return 0; -} - -gint sock_cleanup(void) -{ -#ifdef G_OS_WIN32 - WSACleanup(); -#endif - return 0; -} - -gint sock_set_io_timeout(guint sec) -{ - io_timeout = sec; - return 0; -} - -gint fd_connect_unix(const gchar *path) -{ -#ifdef G_OS_UNIX - gint sock; - struct sockaddr_un addr; - - sock = socket(PF_UNIX, SOCK_STREAM, 0); - if (sock < 0) { - perror("sock_connect_unix(): socket"); - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1); - - if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - fd_close(sock); - return -1; - } - - return sock; -#else - return -1; -#endif -} - -gint fd_open_unix(const gchar *path) -{ -#ifdef G_OS_UNIX - gint sock; - struct sockaddr_un addr; - - sock = socket(PF_UNIX, SOCK_STREAM, 0); - - if (sock < 0) { - perror("sock_open_unix(): socket"); - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1); - - if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - perror("bind"); - fd_close(sock); - return -1; - } - - if (listen(sock, 1) < 0) { - perror("listen"); - fd_close(sock); - return -1; - } - - return sock; -#else - return -1; -#endif -} - -gint fd_accept(gint sock) -{ -#ifdef G_OS_UNIX - struct sockaddr_in caddr; - guint caddr_len; - - caddr_len = sizeof(caddr); - return accept(sock, (struct sockaddr *)&caddr, &caddr_len); -#else - return -1; -#endif -} - - -static gint set_nonblocking_mode(gint fd, gboolean nonblock) -{ -#ifdef G_OS_UNIX - gint flags; - - flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) { - perror("fcntl"); - return -1; - } - - if (nonblock) - flags |= O_NONBLOCK; - else - flags &= ~O_NONBLOCK; - - return fcntl(fd, F_SETFL, flags); -#else - return -1; -#endif -} - -gint sock_set_nonblocking_mode(SockInfo *sock, gboolean nonblock) -{ - g_return_val_if_fail(sock != NULL, -1); - - return set_nonblocking_mode(sock->sock, nonblock); -} - -static gboolean is_nonblocking_mode(gint fd) -{ -#ifdef G_OS_UNIX - gint flags; - - flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) { - perror("fcntl"); - return FALSE; - } - - return ((flags & O_NONBLOCK) != 0); -#else - return FALSE; -#endif -} - -gboolean sock_is_nonblocking_mode(SockInfo *sock) -{ - g_return_val_if_fail(sock != NULL, FALSE); - - return is_nonblocking_mode(sock->sock); -} - - -static gboolean sock_prepare(GSource *source, gint *timeout) -{ - *timeout = 1; - return FALSE; -} - -static gboolean sock_check(GSource *source) -{ - SockInfo *sock = ((SockSource *)source)->sock; - struct timeval timeout = {0, 0}; - fd_set fds; - GIOCondition condition = sock->condition; - -#if USE_SSL - if (sock->ssl) { - if (condition & G_IO_IN) { - if (SSL_pending(sock->ssl) > 0) - return TRUE; - if (SSL_want_write(sock->ssl)) - condition |= G_IO_OUT; - } - - if (condition & G_IO_OUT) { - if (SSL_want_read(sock->ssl)) - condition |= G_IO_IN; - } - } -#endif - - FD_ZERO(&fds); - FD_SET(sock->sock, &fds); - - select(sock->sock + 1, - (condition & G_IO_IN) ? &fds : NULL, - (condition & G_IO_OUT) ? &fds : NULL, - NULL, &timeout); - - return FD_ISSET(sock->sock, &fds) != 0; -} - -static gboolean sock_dispatch(GSource *source, GSourceFunc callback, - gpointer user_data) -{ - SockInfo *sock = ((SockSource *)source)->sock; - - return sock->callback(sock, sock->condition, sock->data); -} - -static gboolean sock_watch_cb(GIOChannel *source, GIOCondition condition, - gpointer data) -{ - SockInfo *sock = (SockInfo *)data; - - if ((condition & sock->condition) == 0) - return TRUE; - - return sock->callback(sock, sock->condition, sock->data); -} - -guint sock_add_watch(SockInfo *sock, GIOCondition condition, SockFunc func, - gpointer data) -{ - sock->callback = func; - sock->condition = condition; - sock->data = data; - -#if USE_SSL - if (sock->ssl) { - GSource *source; - - source = g_source_new(&sock_watch_funcs, sizeof(SockSource)); - ((SockSource *)source)->sock = sock; - g_source_set_priority(source, G_PRIORITY_DEFAULT); - g_source_set_can_recurse(source, FALSE); - return g_source_attach(source, NULL); - } -#endif - - return g_io_add_watch(sock->sock_ch, condition, sock_watch_cb, sock); -} - -static gint fd_check_io(gint fd, GIOCondition cond) -{ - struct timeval timeout; - fd_set fds; - - if (is_nonblocking_mode(fd)) - return 0; - - timeout.tv_sec = io_timeout; - timeout.tv_usec = 0; - - FD_ZERO(&fds); - FD_SET(fd, &fds); - - if (cond == G_IO_IN) { - select(fd + 1, &fds, NULL, NULL, - io_timeout > 0 ? &timeout : NULL); - } else { - select(fd + 1, NULL, &fds, NULL, - io_timeout > 0 ? &timeout : NULL); - } - - if (FD_ISSET(fd, &fds)) { - return 0; - } else { - g_warning("Socket IO timeout\n"); - return -1; - } -} - -#ifdef G_OS_UNIX -static sigjmp_buf jmpenv; - -static void timeout_handler(gint sig) -{ - siglongjmp(jmpenv, 1); -} -#endif - -static gint sock_connect_with_timeout(gint sock, - const struct sockaddr *serv_addr, - gint addrlen, - guint timeout_secs) -{ - gint ret; -#ifdef G_OS_UNIX - void (*prev_handler)(gint); - - alarm(0); - prev_handler = signal(SIGALRM, timeout_handler); - if (sigsetjmp(jmpenv, 1)) { - alarm(0); - signal(SIGALRM, prev_handler); - errno = ETIMEDOUT; - return -1; - } - alarm(timeout_secs); -#endif - - ret = connect(sock, serv_addr, addrlen); - -#ifdef G_OS_UNIX - alarm(0); - signal(SIGALRM, prev_handler); -#endif - - return ret; -} - -struct hostent *my_gethostbyname(const gchar *hostname) -{ - struct hostent *hp; -#ifdef G_OS_UNIX - void (*prev_handler)(gint); - - alarm(0); - prev_handler = signal(SIGALRM, timeout_handler); - if (sigsetjmp(jmpenv, 1)) { - alarm(0); - signal(SIGALRM, prev_handler); - fprintf(stderr, "%s: host lookup timed out.\n", hostname); - errno = 0; - return NULL; - } - alarm(io_timeout); -#endif - - if ((hp = gethostbyname(hostname)) == NULL) { -#ifdef G_OS_UNIX - alarm(0); - signal(SIGALRM, prev_handler); -#endif - fprintf(stderr, "%s: unknown host.\n", hostname); - errno = 0; - return NULL; - } - -#ifdef G_OS_UNIX - alarm(0); - signal(SIGALRM, prev_handler); -#endif - - return hp; -} - -#ifndef INET6 -static gint my_inet_aton(const gchar *hostname, struct in_addr *inp) -{ -#if HAVE_INET_ATON - return inet_aton(hostname, inp); -#else -#if HAVE_INET_ADDR - guint32 inaddr; - - inaddr = inet_addr(hostname); - if (inaddr != -1) { - memcpy(inp, &inaddr, sizeof(inaddr)); - return 1; - } else - return 0; -#else - return 0; -#endif -#endif /* HAVE_INET_ATON */ -} - -static gint sock_connect_by_hostname(gint sock, const gchar *hostname, - gushort port) -{ - struct hostent *hp; - struct sockaddr_in ad; - - memset(&ad, 0, sizeof(ad)); - ad.sin_family = AF_INET; - ad.sin_port = htons(port); - - if (!my_inet_aton(hostname, &ad.sin_addr)) { - if ((hp = my_gethostbyname(hostname)) == NULL) { - fprintf(stderr, "%s: unknown host.\n", hostname); - errno = 0; - return -1; - } - - if (hp->h_length != 4 && hp->h_length != 8) { - fprintf(stderr, "illegal address length received for host %s\n", hostname); - errno = 0; - return -1; - } - - memcpy(&ad.sin_addr, hp->h_addr, hp->h_length); - } - - return sock_connect_with_timeout(sock, (struct sockaddr *)&ad, - sizeof(ad), io_timeout); -} - -#else /* INET6 */ -static gint sock_connect_by_getaddrinfo(const gchar *hostname, gushort port) -{ - gint sock = -1, gai_error; - struct addrinfo hints, *res, *ai; - gchar port_str[6]; - - memset(&hints, 0, sizeof(hints)); - /* hints.ai_flags = AI_CANONNAME; */ - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - /* convert port from integer to string. */ - g_snprintf(port_str, sizeof(port_str), "%d", port); - - if ((gai_error = getaddrinfo(hostname, port_str, &hints, &res)) != 0) { - fprintf(stderr, "getaddrinfo for %s:%s failed: %s\n", - hostname, port_str, gai_strerror(gai_error)); - return -1; - } - - for (ai = res; ai != NULL; ai = ai->ai_next) { - sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sock < 0) - continue; - - if (sock_connect_with_timeout - (sock, ai->ai_addr, ai->ai_addrlen, io_timeout) == 0) - break; - - fd_close(sock); - } - - if (res != NULL) - freeaddrinfo(res); - - if (ai == NULL) - return -1; - - return sock; -} -#endif /* !INET6 */ - -SockInfo *sock_connect(const gchar *hostname, gushort port) -{ -#ifdef G_OS_WIN32 - SOCKET sock; -#else - gint sock; -#endif - SockInfo *sockinfo; - -#ifdef INET6 - if ((sock = sock_connect_by_getaddrinfo(hostname, port)) < 0) - return NULL; -#else -#ifdef G_OS_WIN32 - if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { - g_warning("socket() failed: %ld\n", WSAGetLastError()); -#else - if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket"); -#endif /* G_OS_WIN32 */ - return NULL; - } - - if (sock_connect_by_hostname(sock, hostname, port) < 0) { - if (errno != 0) perror("connect"); - fd_close(sock); - return NULL; - } -#endif /* INET6 */ - - sockinfo = g_new0(SockInfo, 1); - sockinfo->sock = sock; - sockinfo->sock_ch = g_io_channel_unix_new(sock); - sockinfo->hostname = g_strdup(hostname); - sockinfo->port = port; - sockinfo->state = CONN_ESTABLISHED; - - g_usleep(100000); - - return sockinfo; -} - -#ifdef G_OS_UNIX -static void sock_address_list_free(GList *addr_list) -{ - GList *cur; - - for (cur = addr_list; cur != NULL; cur = cur->next) { - SockAddrData *addr_data = (SockAddrData *)cur->data; - g_free(addr_data->addr); - g_free(addr_data); - } - - g_list_free(addr_list); -} - -/* asynchronous TCP connection */ - -static gboolean sock_connect_async_cb(GIOChannel *source, - GIOCondition condition, gpointer data) -{ - SockConnectData *conn_data = (SockConnectData *)data; - gint fd; - gint val; - guint len; - SockInfo *sockinfo; - - fd = g_io_channel_unix_get_fd(source); - - conn_data->io_tag = 0; - conn_data->channel = NULL; - g_io_channel_unref(source); - - len = sizeof(val); - if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &val, &len) < 0) { - perror("getsockopt"); - fd_close(fd); - sock_connect_address_list_async(conn_data); - return FALSE; - } - - if (val != 0) { - fd_close(fd); - sock_connect_address_list_async(conn_data); - return FALSE; - } - - sockinfo = g_new0(SockInfo, 1); - sockinfo->sock = fd; - sockinfo->sock_ch = g_io_channel_unix_new(fd); - sockinfo->hostname = g_strdup(conn_data->hostname); - sockinfo->port = conn_data->port; - sockinfo->state = CONN_ESTABLISHED; - - conn_data->func(sockinfo, conn_data->data); - - sock_connect_async_cancel(conn_data->id); - - return FALSE; -} - -static gint sock_connect_async_get_address_info_cb(GList *addr_list, - gpointer data) -{ - SockConnectData *conn_data = (SockConnectData *)data; - - conn_data->addr_list = addr_list; - conn_data->cur_addr = addr_list; - conn_data->lookup_data = NULL; - - return sock_connect_address_list_async(conn_data); -} - -gint sock_connect_async(const gchar *hostname, gushort port, - SockConnectFunc func, gpointer data) -{ - static gint id = 1; - SockConnectData *conn_data; - - conn_data = g_new0(SockConnectData, 1); - conn_data->id = id++; - conn_data->hostname = g_strdup(hostname); - conn_data->port = port; - conn_data->addr_list = NULL; - conn_data->cur_addr = NULL; - conn_data->io_tag = 0; - conn_data->func = func; - conn_data->data = data; - - conn_data->lookup_data = sock_get_address_info_async - (hostname, port, sock_connect_async_get_address_info_cb, - conn_data); - - if (conn_data->lookup_data == NULL) { - g_free(conn_data->hostname); - g_free(conn_data); - return -1; - } - - sock_connect_data_list = g_list_append(sock_connect_data_list, - conn_data); - - return conn_data->id; -} - -gint sock_connect_async_cancel(gint id) -{ - SockConnectData *conn_data = NULL; - GList *cur; - - for (cur = sock_connect_data_list; cur != NULL; cur = cur->next) { - if (((SockConnectData *)cur->data)->id == id) { - conn_data = (SockConnectData *)cur->data; - break; - } - } - - if (conn_data) { - sock_connect_data_list = g_list_remove(sock_connect_data_list, - conn_data); - - if (conn_data->lookup_data) - sock_get_address_info_async_cancel - (conn_data->lookup_data); - - if (conn_data->io_tag > 0) - g_source_remove(conn_data->io_tag); - if (conn_data->channel) { - g_io_channel_shutdown(conn_data->channel, FALSE, NULL); - g_io_channel_unref(conn_data->channel); - } - - sock_address_list_free(conn_data->addr_list); - g_free(conn_data->hostname); - g_free(conn_data); - } else { - g_warning("sock_connect_async_cancel: id %d not found.\n", id); - return -1; - } - - return 0; -} - -static gint sock_connect_address_list_async(SockConnectData *conn_data) -{ - SockAddrData *addr_data; - gint sock = -1; - - for (; conn_data->cur_addr != NULL; - conn_data->cur_addr = conn_data->cur_addr->next) { - addr_data = (SockAddrData *)conn_data->cur_addr->data; - - if ((sock = socket(addr_data->family, addr_data->socktype, - addr_data->protocol)) < 0) { - perror("socket"); - continue; - } - - set_nonblocking_mode(sock, TRUE); - - if (connect(sock, addr_data->addr, addr_data->addr_len) < 0) { - if (EINPROGRESS == errno) { - break; - } else { - perror("connect"); - fd_close(sock); - } - } else - break; - } - - if (conn_data->cur_addr == NULL) { - g_warning("sock_connect_address_list_async: " - "connection to %s:%d failed\n", - conn_data->hostname, conn_data->port); - conn_data->func(NULL, conn_data->data); - sock_connect_async_cancel(conn_data->id); - return -1; - } - - conn_data->cur_addr = conn_data->cur_addr->next; - - conn_data->channel = g_io_channel_unix_new(sock); - conn_data->io_tag = g_io_add_watch(conn_data->channel, G_IO_OUT, - sock_connect_async_cb, conn_data); - - return 0; -} - -/* asynchronous DNS lookup */ - -static gboolean sock_get_address_info_async_cb(GIOChannel *source, - GIOCondition condition, - gpointer data) -{ - SockLookupData *lookup_data = (SockLookupData *)data; - GList *addr_list = NULL; - SockAddrData *addr_data; - gsize bytes_read; - gint ai_member[4]; - struct sockaddr *addr; - - for (;;) { - if (g_io_channel_read(source, (gchar *)ai_member, - sizeof(ai_member), &bytes_read) - != G_IO_ERROR_NONE) { - g_warning("sock_get_address_info_async_cb: " - "address length read error\n"); - break; - } - - if (bytes_read == 0 || bytes_read != sizeof(ai_member)) - break; - - if (ai_member[0] == AF_UNSPEC) { - g_warning("DNS lookup failed\n"); - break; - } - - addr = g_malloc(ai_member[3]); - if (g_io_channel_read(source, (gchar *)addr, ai_member[3], - &bytes_read) - != G_IO_ERROR_NONE) { - g_warning("sock_get_address_info_async_cb: " - "address data read error\n"); - g_free(addr); - break; - } - - if (bytes_read != ai_member[3]) { - g_warning("sock_get_address_info_async_cb: " - "incomplete address data\n"); - g_free(addr); - break; - } - - addr_data = g_new0(SockAddrData, 1); - addr_data->family = ai_member[0]; - addr_data->socktype = ai_member[1]; - addr_data->protocol = ai_member[2]; - addr_data->addr_len = ai_member[3]; - addr_data->addr = addr; - - addr_list = g_list_append(addr_list, addr_data); - } - - g_io_channel_shutdown(source, FALSE, NULL); - g_io_channel_unref(source); - - kill(lookup_data->child_pid, SIGKILL); - waitpid(lookup_data->child_pid, NULL, 0); - - lookup_data->func(addr_list, lookup_data->data); - - g_free(lookup_data->hostname); - g_free(lookup_data); - - return FALSE; -} - -static SockLookupData *sock_get_address_info_async(const gchar *hostname, - gushort port, - SockAddrFunc func, - gpointer data) -{ - SockLookupData *lookup_data = NULL; - gint pipe_fds[2]; - pid_t pid; - - if (pipe(pipe_fds) < 0) { - perror("pipe"); - func(NULL, data); - return NULL; - } - - if ((pid = fork()) < 0) { - perror("fork"); - func(NULL, data); - return NULL; - } - - /* child process */ - if (pid == 0) { -#ifdef INET6 - gint gai_err; - struct addrinfo hints, *res, *ai; - gchar port_str[6]; -#else /* !INET6 */ - struct hostent *hp; - gchar **addr_list_p; - struct sockaddr_in ad; -#endif /* INET6 */ - gint ai_member[4] = {AF_UNSPEC, 0, 0, 0}; - - close(pipe_fds[0]); - -#ifdef INET6 - memset(&hints, 0, sizeof(hints)); - /* hints.ai_flags = AI_CANONNAME; */ - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - g_snprintf(port_str, sizeof(port_str), "%d", port); - - gai_err = getaddrinfo(hostname, port_str, &hints, &res); - if (gai_err != 0) { - g_warning("getaddrinfo for %s:%s failed: %s\n", - hostname, port_str, gai_strerror(gai_err)); - fd_write_all(pipe_fds[1], (gchar *)ai_member, - sizeof(ai_member)); - close(pipe_fds[1]); - _exit(1); - } - - for (ai = res; ai != NULL; ai = ai->ai_next) { - ai_member[0] = ai->ai_family; - ai_member[1] = ai->ai_socktype; - ai_member[2] = ai->ai_protocol; - ai_member[3] = ai->ai_addrlen; - - fd_write_all(pipe_fds[1], (gchar *)ai_member, - sizeof(ai_member)); - fd_write_all(pipe_fds[1], (gchar *)ai->ai_addr, - ai->ai_addrlen); - } - - if (res != NULL) - freeaddrinfo(res); -#else /* !INET6 */ - hp = my_gethostbyname(hostname); - if (hp == NULL || hp->h_addrtype != AF_INET) { - fd_write_all(pipe_fds[1], (gchar *)ai_member, - sizeof(ai_member)); - close(pipe_fds[1]); - _exit(1); - } - - ai_member[0] = AF_INET; - ai_member[1] = SOCK_STREAM; - ai_member[2] = IPPROTO_TCP; - ai_member[3] = sizeof(ad); - - memset(&ad, 0, sizeof(ad)); - ad.sin_family = AF_INET; - ad.sin_port = htons(port); - - for (addr_list_p = hp->h_addr_list; *addr_list_p != NULL; - addr_list_p++) { - memcpy(&ad.sin_addr, *addr_list_p, hp->h_length); - fd_write_all(pipe_fds[1], (gchar *)ai_member, - sizeof(ai_member)); - fd_write_all(pipe_fds[1], (gchar *)&ad, sizeof(ad)); - } -#endif /* INET6 */ - - close(pipe_fds[1]); - - _exit(0); - } else { - close(pipe_fds[1]); - - lookup_data = g_new0(SockLookupData, 1); - lookup_data->hostname = g_strdup(hostname); - lookup_data->child_pid = pid; - lookup_data->func = func; - lookup_data->data = data; - - lookup_data->channel = g_io_channel_unix_new(pipe_fds[0]); - lookup_data->io_tag = g_io_add_watch - (lookup_data->channel, G_IO_IN, - sock_get_address_info_async_cb, lookup_data); - } - - return lookup_data; -} - -static gint sock_get_address_info_async_cancel(SockLookupData *lookup_data) -{ - if (lookup_data->io_tag > 0) - g_source_remove(lookup_data->io_tag); - if (lookup_data->channel) { - g_io_channel_shutdown(lookup_data->channel, FALSE, NULL); - g_io_channel_unref(lookup_data->channel); - } - - if (lookup_data->child_pid > 0) { - kill(lookup_data->child_pid, SIGKILL); - waitpid(lookup_data->child_pid, NULL, 0); - } - - g_free(lookup_data->hostname); - g_free(lookup_data); - - return 0; -} -#endif /* G_OS_UNIX */ - - -gint sock_printf(SockInfo *sock, const gchar *format, ...) -{ - va_list args; - gchar buf[BUFFSIZE]; - - va_start(args, format); - g_vsnprintf(buf, sizeof(buf), format, args); - va_end(args); - - return sock_write_all(sock, buf, strlen(buf)); -} - -gint sock_read(SockInfo *sock, gchar *buf, gint len) -{ - g_return_val_if_fail(sock != NULL, -1); - -#if USE_SSL - if (sock->ssl) - return ssl_read(sock->ssl, buf, len); -#endif - return fd_read(sock->sock, buf, len); -} - -gint fd_read(gint fd, gchar *buf, gint len) -{ - if (fd_check_io(fd, G_IO_IN) < 0) - return -1; - -#ifdef G_OS_WIN32 - return recv(fd, buf, len, 0); -#else - return read(fd, buf, len); -#endif -} - -#if USE_SSL -gint ssl_read(SSL *ssl, gchar *buf, gint len) -{ - gint err, ret; - - if (SSL_pending(ssl) == 0) { - if (fd_check_io(SSL_get_rfd(ssl), G_IO_IN) < 0) - return -1; - } - - ret = SSL_read(ssl, buf, len); - - switch ((err = SSL_get_error(ssl, ret))) { - case SSL_ERROR_NONE: - return ret; - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - errno = EAGAIN; - return -1; - case SSL_ERROR_ZERO_RETURN: - return 0; - default: - g_warning("SSL_read() returned error %d, ret = %d\n", err, ret); - if (ret == 0) - return 0; - return -1; - } -} -#endif - -gint sock_write(SockInfo *sock, const gchar *buf, gint len) -{ - g_return_val_if_fail(sock != NULL, -1); - -#if USE_SSL - if (sock->ssl) - return ssl_write(sock->ssl, buf, len); -#endif - return fd_write(sock->sock, buf, len); -} - -gint fd_write(gint fd, const gchar *buf, gint len) -{ - if (fd_check_io(fd, G_IO_OUT) < 0) - return -1; - -#ifdef G_OS_WIN32 - return send(fd, buf, len, 0); -#else - return write(fd, buf, len); -#endif -} - -#if USE_SSL -gint ssl_write(SSL *ssl, const gchar *buf, gint len) -{ - gint ret; - - ret = SSL_write(ssl, buf, len); - - switch (SSL_get_error(ssl, ret)) { - case SSL_ERROR_NONE: - return ret; - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - errno = EAGAIN; - return -1; - default: - return -1; - } -} -#endif - -gint sock_write_all(SockInfo *sock, const gchar *buf, gint len) -{ - g_return_val_if_fail(sock != NULL, -1); - -#if USE_SSL - if (sock->ssl) - return ssl_write_all(sock->ssl, buf, len); -#endif - return fd_write_all(sock->sock, buf, len); -} - -gint fd_write_all(gint fd, const gchar *buf, gint len) -{ - gint n, wrlen = 0; - - while (len) { - n = fd_write(fd, buf, len); - if (n <= 0) - return -1; - len -= n; - wrlen += n; - buf += n; - } - - return wrlen; -} - -#if USE_SSL -gint ssl_write_all(SSL *ssl, const gchar *buf, gint len) -{ - gint n, wrlen = 0; - - while (len) { - n = ssl_write(ssl, buf, len); - if (n <= 0) - return -1; - len -= n; - wrlen += n; - buf += n; - } - - return wrlen; -} -#endif - -gint fd_recv(gint fd, gchar *buf, gint len, gint flags) -{ - if (fd_check_io(fd, G_IO_IN) < 0) - return -1; - - return recv(fd, buf, len, flags); -} - -gint fd_gets(gint fd, gchar *buf, gint len) -{ - gchar *newline, *bp = buf; - gint n; - - if (--len < 1) - return -1; - do { - if ((n = fd_recv(fd, bp, len, MSG_PEEK)) <= 0) - return -1; - if ((newline = memchr(bp, '\n', n)) != NULL) - n = newline - bp + 1; - if ((n = fd_read(fd, bp, n)) < 0) - return -1; - bp += n; - len -= n; - } while (!newline && len); - - *bp = '\0'; - return bp - buf; -} - -#if USE_SSL -gint ssl_gets(SSL *ssl, gchar *buf, gint len) -{ - gchar *newline, *bp = buf; - gint n; - - if (--len < 1) - return -1; - do { - if ((n = ssl_peek(ssl, bp, len)) <= 0) - return -1; - if ((newline = memchr(bp, '\n', n)) != NULL) - n = newline - bp + 1; - if ((n = ssl_read(ssl, bp, n)) < 0) - return -1; - bp += n; - len -= n; - } while (!newline && len); - - *bp = '\0'; - return bp - buf; -} -#endif - -gint sock_gets(SockInfo *sock, gchar *buf, gint len) -{ - g_return_val_if_fail(sock != NULL, -1); - -#if USE_SSL - if (sock->ssl) - return ssl_gets(sock->ssl, buf, len); -#endif - return fd_gets(sock->sock, buf, len); -} - -gint fd_getline(gint fd, gchar **line) -{ - gchar buf[BUFFSIZE]; - gchar *str = NULL; - gint len; - gulong size = 0; - gulong cur_offset = 0; - - while ((len = fd_gets(fd, buf, sizeof(buf))) > 0) { - size += len; - str = g_realloc(str, size + 1); - memcpy(str + cur_offset, buf, len + 1); - cur_offset += len; - if (buf[len - 1] == '\n') - break; - } - - *line = str; - - if (!str) - return -1; - else - return (gint)size; -} - -#if USE_SSL -gint ssl_getline(SSL *ssl, gchar **line) -{ - gchar buf[BUFFSIZE]; - gchar *str = NULL; - gint len; - gulong size = 0; - gulong cur_offset = 0; - - while ((len = ssl_gets(ssl, buf, sizeof(buf))) > 0) { - size += len; - str = g_realloc(str, size + 1); - memcpy(str + cur_offset, buf, len + 1); - cur_offset += len; - if (buf[len - 1] == '\n') - break; - } - - *line = str; - - if (!str) - return -1; - else - return (gint)size; -} -#endif - -gint sock_getline(SockInfo *sock, gchar **line) -{ - g_return_val_if_fail(sock != NULL, -1); - g_return_val_if_fail(line != NULL, -1); - -#if USE_SSL - if (sock->ssl) - return ssl_getline(sock->ssl, line); -#endif - return fd_getline(sock->sock, line); -} - -gint sock_puts(SockInfo *sock, const gchar *buf) -{ - gint ret; - - if ((ret = sock_write_all(sock, buf, strlen(buf))) < 0) - return ret; - return sock_write_all(sock, "\r\n", 2); -} - -/* peek at the socket data without actually reading it */ -#if USE_SSL -gint ssl_peek(SSL *ssl, gchar *buf, gint len) -{ - gint err, ret; - - if (SSL_pending(ssl) == 0) { - if (fd_check_io(SSL_get_rfd(ssl), G_IO_IN) < 0) - return -1; - } - - ret = SSL_peek(ssl, buf, len); - - switch ((err = SSL_get_error(ssl, ret))) { - case SSL_ERROR_NONE: - return ret; - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - errno = EAGAIN; - return -1; - case SSL_ERROR_ZERO_RETURN: - return 0; - default: - g_warning("SSL_peek() returned error %d, ret = %d\n", err, ret); - if (ret == 0) - return 0; - return -1; - } -} -#endif - -gint sock_peek(SockInfo *sock, gchar *buf, gint len) -{ - g_return_val_if_fail(sock != NULL, -1); - -#if USE_SSL - if (sock->ssl) - return ssl_peek(sock->ssl, buf, len); -#endif - return fd_recv(sock->sock, buf, len, MSG_PEEK); -} - -gint sock_close(SockInfo *sock) -{ - if (!sock) - return 0; - -#if USE_SSL - if (sock->ssl) - ssl_done_socket(sock); -#endif - - if (sock->sock_ch) { - g_io_channel_shutdown(sock->sock_ch, FALSE, NULL); - g_io_channel_unref(sock->sock_ch); - } - - g_free(sock->hostname); - g_free(sock); - - return 0; -} - -gint fd_close(gint fd) -{ -#ifdef G_OS_WIN32 - return closesocket(fd); -#else - return close(fd); -#endif -} diff --git a/src/socket.h b/src/socket.h deleted file mode 100644 index 5721a304..00000000 --- a/src/socket.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __SOCKET_H__ -#define __SOCKET_H__ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <glib.h> -#if HAVE_NETDB_H -# include <netdb.h> -#endif - -typedef struct _SockInfo SockInfo; - -#if USE_SSL -# include "ssl.h" -#endif - -typedef enum -{ - CONN_READY, - CONN_LOOKUPSUCCESS, - CONN_ESTABLISHED, - CONN_LOOKUPFAILED, - CONN_FAILED -} ConnectionState; - -typedef gint (*SockConnectFunc) (SockInfo *sock, - gpointer data); -typedef gboolean (*SockFunc) (SockInfo *sock, - GIOCondition condition, - gpointer data); - -struct _SockInfo -{ - gint sock; -#if USE_SSL - SSL *ssl; -#endif - GIOChannel *sock_ch; - - gchar *hostname; - gushort port; - ConnectionState state; - gpointer data; - - SockFunc callback; - GIOCondition condition; -}; - -gint sock_init (void); -gint sock_cleanup (void); - -gint sock_set_io_timeout (guint sec); - -gint sock_set_nonblocking_mode (SockInfo *sock, gboolean nonblock); -gboolean sock_is_nonblocking_mode (SockInfo *sock); - -guint sock_add_watch (SockInfo *sock, GIOCondition condition, - SockFunc func, gpointer data); - -struct hostent *my_gethostbyname (const gchar *hostname); - -SockInfo *sock_connect (const gchar *hostname, gushort port); -#ifdef G_OS_UNIX -gint sock_connect_async (const gchar *hostname, gushort port, - SockConnectFunc func, gpointer data); -gint sock_connect_async_cancel (gint id); -#endif - -/* Basic I/O functions */ -gint sock_printf (SockInfo *sock, const gchar *format, ...) - G_GNUC_PRINTF(2, 3); -gint sock_read (SockInfo *sock, gchar *buf, gint len); -gint sock_write (SockInfo *sock, const gchar *buf, gint len); -gint sock_write_all (SockInfo *sock, const gchar *buf, gint len); -gint sock_gets (SockInfo *sock, gchar *buf, gint len); -gint sock_getline (SockInfo *sock, gchar **line); -gint sock_puts (SockInfo *sock, const gchar *buf); -gint sock_peek (SockInfo *sock, gchar *buf, gint len); -gint sock_close (SockInfo *sock); - -/* Functions to directly work on FD. They are needed for pipes */ -gint fd_connect_unix (const gchar *path); -gint fd_open_unix (const gchar *path); -gint fd_accept (gint sock); - -gint fd_read (gint sock, gchar *buf, gint len); -gint fd_write (gint sock, const gchar *buf, gint len); -gint fd_write_all (gint sock, const gchar *buf, gint len); -gint fd_gets (gint sock, gchar *buf, gint len); -gint fd_getline (gint sock, gchar **line); -gint fd_close (gint sock); - -/* Functions for SSL */ -#if USE_SSL -gint ssl_read (SSL *ssl, gchar *buf, gint len); -gint ssl_write (SSL *ssl, const gchar *buf, gint len); -gint ssl_write_all (SSL *ssl, const gchar *buf, gint len); -gint ssl_gets (SSL *ssl, gchar *buf, gint len); -gint ssl_getline (SSL *ssl, gchar **line); -gint ssl_peek (SSL *ssl, gchar *buf, gint len); -#endif - -#endif /* __SOCKET_H__ */ diff --git a/src/ssl.c b/src/ssl.c deleted file mode 100644 index b57c60a9..00000000 --- a/src/ssl.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#if USE_SSL - -#include "defs.h" - -#include <glib.h> -#include <glib/gi18n.h> - -#include "utils.h" -#include "ssl.h" - -static SSL_CTX *ssl_ctx_SSLv23; -static SSL_CTX *ssl_ctx_TLSv1; - -void ssl_init(void) -{ - gchar *certs_dir; - - SSL_library_init(); - SSL_load_error_strings(); - - certs_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, "certs", NULL); - if (!is_dir_exist(certs_dir)) { - debug_print("%s doesn't exist, or not a directory.\n", - certs_dir); - g_free(certs_dir); - certs_dir = NULL; - } - - ssl_ctx_SSLv23 = SSL_CTX_new(SSLv23_client_method()); - if (ssl_ctx_SSLv23 == NULL) { - debug_print(_("SSLv23 not available\n")); - } else { - debug_print(_("SSLv23 available\n")); - if (certs_dir && - !SSL_CTX_load_verify_locations(ssl_ctx_SSLv23, NULL, - certs_dir)) - g_warning("SSLv23 SSL_CTX_load_verify_locations failed.\n"); - } - - ssl_ctx_TLSv1 = SSL_CTX_new(TLSv1_client_method()); - if (ssl_ctx_TLSv1 == NULL) { - debug_print(_("TLSv1 not available\n")); - } else { - debug_print(_("TLSv1 available\n")); - if (certs_dir && - !SSL_CTX_load_verify_locations(ssl_ctx_TLSv1, NULL, - certs_dir)) - g_warning("TLSv1 SSL_CTX_load_verify_locations failed.\n"); - } - - g_free(certs_dir); -} - -void ssl_done(void) -{ - if (ssl_ctx_SSLv23) { - SSL_CTX_free(ssl_ctx_SSLv23); - } - - if (ssl_ctx_TLSv1) { - SSL_CTX_free(ssl_ctx_TLSv1); - } -} - -gboolean ssl_init_socket(SockInfo *sockinfo) -{ - return ssl_init_socket_with_method(sockinfo, SSL_METHOD_SSLv23); -} - -gboolean ssl_init_socket_with_method(SockInfo *sockinfo, SSLMethod method) -{ - X509 *server_cert; - gint ret; - - switch (method) { - case SSL_METHOD_SSLv23: - if (!ssl_ctx_SSLv23) { - g_warning(_("SSL method not available\n")); - return FALSE; - } - sockinfo->ssl = SSL_new(ssl_ctx_SSLv23); - break; - case SSL_METHOD_TLSv1: - if (!ssl_ctx_TLSv1) { - g_warning(_("SSL method not available\n")); - return FALSE; - } - sockinfo->ssl = SSL_new(ssl_ctx_TLSv1); - break; - default: - g_warning(_("Unknown SSL method *PROGRAM BUG*\n")); - return FALSE; - break; - } - - if (sockinfo->ssl == NULL) { - g_warning(_("Error creating ssl context\n")); - return FALSE; - } - - SSL_set_fd(sockinfo->ssl, sockinfo->sock); - if ((ret = SSL_connect(sockinfo->ssl)) == -1) { - g_warning(_("SSL connect failed (%s)\n"), - ERR_error_string(ERR_get_error(), NULL)); - return FALSE; - } - - /* Get the cipher */ - - debug_print(_("SSL connection using %s\n"), - SSL_get_cipher(sockinfo->ssl)); - - /* Get server's certificate (note: beware of dynamic allocation) */ - - if ((server_cert = SSL_get_peer_certificate(sockinfo->ssl)) != NULL) { - gchar *str; - glong verify_result; - - debug_print(_("Server certificate:\n")); - - if ((str = X509_NAME_oneline(X509_get_subject_name(server_cert), 0, 0)) != NULL) { - debug_print(_(" Subject: %s\n"), str); - g_free(str); - } - - if ((str = X509_NAME_oneline(X509_get_issuer_name(server_cert), 0, 0)) != NULL) { - debug_print(_(" Issuer: %s\n"), str); - g_free(str); - } - - verify_result = SSL_get_verify_result(sockinfo->ssl); - if (verify_result == X509_V_OK) - debug_print("SSL verify OK\n"); - else - g_warning("%s: SSL certificate verify failed (%ld: %s)\n", - sockinfo->hostname, verify_result, - X509_verify_cert_error_string(verify_result)); - - X509_free(server_cert); - } - - return TRUE; -} - -void ssl_done_socket(SockInfo *sockinfo) -{ - if (sockinfo->ssl) { - SSL_free(sockinfo->ssl); - } -} - -#endif /* USE_SSL */ diff --git a/src/ssl.h b/src/ssl.h deleted file mode 100644 index 6c13ddac..00000000 --- a/src/ssl.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2002 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __SSL_H__ -#define __SSL_H__ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#if USE_SSL - -#include <glib.h> -#include <openssl/crypto.h> -#include <openssl/x509.h> -#include <openssl/pem.h> -#include <openssl/ssl.h> -#include <openssl/err.h> - -#include "socket.h" - -typedef enum { - SSL_METHOD_SSLv23, - SSL_METHOD_TLSv1 -} SSLMethod; - -typedef enum { - SSL_NONE, - SSL_TUNNEL, - SSL_STARTTLS -} SSLType; - -void ssl_init (void); -void ssl_done (void); -gboolean ssl_init_socket (SockInfo *sockinfo); -gboolean ssl_init_socket_with_method (SockInfo *sockinfo, - SSLMethod method); -void ssl_done_socket (SockInfo *sockinfo); - -#endif /* USE_SSL */ - -#endif /* __SSL_H__ */ diff --git a/src/stringtable.c b/src/stringtable.c deleted file mode 100644 index da5e0ea4..00000000 --- a/src/stringtable.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2001 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <glib.h> -#include <string.h> - -#include "stringtable.h" -#include "utils.h" - -/* alfons - hashed string table (I wasn't content with GStringChunk; - * can't recall why :-) */ - -#if 0 -#define XXX_DEBUG \ - debug_print -#else -#define XXX_DEBUG \ - if (0) debug_print -#endif - -typedef struct StringEntry_ { - gint ref_count; - gchar *string; -} StringEntry; - -static StringEntry *string_entry_new(const gchar *str) -{ - StringEntry *entry; - - entry = g_new0(StringEntry, 1); - entry->ref_count = 1; - entry->string = g_strdup(str); - return entry; -} - -static void string_entry_free(StringEntry *entry) -{ - g_return_if_fail(entry != NULL); - - g_free(entry->string); - g_free(entry); -} - -StringTable *string_table_new(void) -{ - StringTable *strtable; - - strtable = g_new0(StringTable, 1); - g_return_val_if_fail(strtable != NULL, NULL); - strtable->hash_table = g_hash_table_new(g_str_hash, g_str_equal); - g_return_val_if_fail(strtable->hash_table, NULL); - return strtable; -} - -gchar *string_table_lookup_string(StringTable *table, const gchar *str) -{ - StringEntry *entry; - - entry = g_hash_table_lookup(table->hash_table, str); - - if (entry) { - return entry->string; - } else { - return NULL; - } -} - -gchar *string_table_insert_string(StringTable *table, const gchar *str) -{ - StringEntry *entry; - - entry = g_hash_table_lookup(table->hash_table, str); - - if (entry) { - entry->ref_count++; - XXX_DEBUG ("ref++ for %s (%d)\n", entry->string, - entry->ref_count); - } else { - entry = string_entry_new(str); - XXX_DEBUG ("inserting %s\n", str); - /* insert entry->string instead of str, since it can be - * invalid pointer after this. */ - g_hash_table_insert(table->hash_table, entry->string, entry); - } - - return entry->string; -} - -void string_table_free_string(StringTable *table, const gchar *str) -{ - StringEntry *entry; - - entry = g_hash_table_lookup(table->hash_table, str); - - if (entry) { - entry->ref_count--; - if (entry->ref_count <= 0) { - XXX_DEBUG ("refcount of string %s dropped to zero\n", - entry->string); - g_hash_table_remove(table->hash_table, str); - string_entry_free(entry); - } else { - XXX_DEBUG ("ref-- for %s (%d)\n", entry->string, - entry->ref_count); - } - } -} - -static gboolean string_table_remove_for_each_fn(gchar *key, StringEntry *entry, - gpointer user_data) -{ - g_return_val_if_fail(key != NULL, TRUE); - g_return_val_if_fail(entry != NULL, TRUE); - - string_entry_free(entry); - - return TRUE; -} - -void string_table_free(StringTable *table) -{ - g_return_if_fail(table != NULL); - g_return_if_fail(table->hash_table != NULL); - - g_hash_table_foreach_remove(table->hash_table, - (GHRFunc)string_table_remove_for_each_fn, - NULL); - g_hash_table_destroy(table->hash_table); - g_free(table); -} - -static void string_table_stats_for_each_fn(gchar *key, StringEntry *entry, - guint *totals) -{ - if (entry->ref_count > 1) { - *totals += strlen(key) * (entry->ref_count - 1); - } -} - -void string_table_get_stats(StringTable *table) -{ - guint totals = 0; - - g_hash_table_foreach(table->hash_table, - (GHFunc)string_table_stats_for_each_fn, &totals); - XXX_DEBUG ("TOTAL UNSPILLED %d (%dK)\n", totals, totals / 1024); -} diff --git a/src/stringtable.h b/src/stringtable.h deleted file mode 100644 index 337ef2c7..00000000 --- a/src/stringtable.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * sylpheed -- a gtk+ based, lightweight, and fast e-mail client - * copyright (c) 1999-2001 hiroyuki yamamoto - * - * 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 place - suite 330, boston, ma 02111-1307, usa. - */ - -#ifndef STRINGTABLE_H__ -#define STRINGTABLE_H__ - -#include <glib.h> - -typedef struct { - GHashTable *hash_table; -} StringTable; - -StringTable *string_table_new (void); -void string_table_free (StringTable *table); - -gchar *string_table_lookup_string (StringTable *table, const gchar *str); -gchar *string_table_insert_string (StringTable *table, const gchar *str); -void string_table_free_string (StringTable *table, const gchar *str); - -void string_table_get_stats (StringTable *table); - -#endif /* STRINGTABLE_H__ */ diff --git a/src/unmime.c b/src/unmime.c deleted file mode 100644 index 23d787a3..00000000 --- a/src/unmime.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <glib.h> -#include <string.h> -#include <ctype.h> - -#include "codeconv.h" -#include "base64.h" -#include "quoted-printable.h" - -#define ENCODED_WORD_BEGIN "=?" -#define ENCODED_WORD_END "?=" - -/* Decodes headers based on RFC2045 and RFC2047. */ - -gchar *unmime_header(const gchar *encoded_str) -{ - const gchar *p = encoded_str; - const gchar *eword_begin_p, *encoding_begin_p, *text_begin_p, - *eword_end_p; - gchar charset[32]; - gchar encoding; - gchar *conv_str; - GString *outbuf; - gchar *out_str; - gsize out_len; - - outbuf = g_string_sized_new(strlen(encoded_str) * 2); - - while (*p != '\0') { - gchar *decoded_text = NULL; - gint len; - - eword_begin_p = strstr(p, ENCODED_WORD_BEGIN); - if (!eword_begin_p) { - g_string_append(outbuf, p); - break; - } - encoding_begin_p = strchr(eword_begin_p + 2, '?'); - if (!encoding_begin_p) { - g_string_append(outbuf, p); - break; - } - text_begin_p = strchr(encoding_begin_p + 1, '?'); - if (!text_begin_p) { - g_string_append(outbuf, p); - break; - } - eword_end_p = strstr(text_begin_p + 1, ENCODED_WORD_END); - if (!eword_end_p) { - g_string_append(outbuf, p); - break; - } - - if (p == encoded_str) { - g_string_append_len(outbuf, p, eword_begin_p - p); - p = eword_begin_p; - } else { - /* ignore spaces between encoded words */ - const gchar *sp; - - for (sp = p; sp < eword_begin_p; sp++) { - if (!g_ascii_isspace(*sp)) { - g_string_append_len - (outbuf, p, eword_begin_p - p); - p = eword_begin_p; - break; - } - } - } - - len = MIN(sizeof(charset) - 1, - encoding_begin_p - (eword_begin_p + 2)); - memcpy(charset, eword_begin_p + 2, len); - charset[len] = '\0'; - encoding = g_ascii_toupper(*(encoding_begin_p + 1)); - - if (encoding == 'B') { - decoded_text = g_malloc - (eword_end_p - (text_begin_p + 1) + 1); - len = base64_decode(decoded_text, text_begin_p + 1, - eword_end_p - (text_begin_p + 1)); - decoded_text[len] = '\0'; - } else if (encoding == 'Q') { - decoded_text = g_malloc - (eword_end_p - (text_begin_p + 1) + 1); - len = qp_decode_q_encoding - (decoded_text, text_begin_p + 1, - eword_end_p - (text_begin_p + 1)); - } else { - g_string_append_len(outbuf, p, eword_end_p + 2 - p); - p = eword_end_p + 2; - continue; - } - - /* convert to UTF-8 */ - conv_str = conv_codeset_strdup(decoded_text, charset, NULL); - if (!conv_str) - conv_str = conv_utf8todisp(decoded_text, NULL); - g_string_append(outbuf, conv_str); - g_free(conv_str); - - g_free(decoded_text); - - p = eword_end_p + 2; - } - - out_str = outbuf->str; - out_len = outbuf->len; - g_string_free(outbuf, FALSE); - - return g_realloc(out_str, out_len + 1); -} diff --git a/src/unmime.h b/src/unmime.h deleted file mode 100644 index be9f390e..00000000 --- a/src/unmime.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __UNMIME_H__ -#define __UNMIME_H__ - -#include <glib.h> - -gchar *unmime_header (const gchar *encoded_str); - -#endif /* __UNMIME_H__ */ diff --git a/src/utils.c b/src/utils.c deleted file mode 100644 index dc72b814..00000000 --- a/src/utils.c +++ /dev/null @@ -1,3436 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "defs.h" - -#include <glib.h> -#include <glib/gi18n.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> - -#if (HAVE_WCTYPE_H && HAVE_WCHAR_H) -# include <wchar.h> -# include <wctype.h> -#endif -#include <stdlib.h> -#include <sys/stat.h> -#include <unistd.h> -#include <stdarg.h> -#include <sys/types.h> -#if HAVE_SYS_WAIT_H -# include <sys/wait.h> -#endif -#include <dirent.h> -#include <time.h> - -#ifdef G_OS_WIN32 -# include <direct.h> -# include <io.h> -#endif - -#include "utils.h" -#include "socket.h" - -#define BUFFSIZE 8192 - -static gboolean debug_mode = FALSE; - - -#if !GLIB_CHECK_VERSION(2, 7, 0) && !defined(G_OS_UNIX) -gint g_chdir(const gchar *path) -{ -#ifdef G_OS_WIN32 - if (G_WIN32_HAVE_WIDECHAR_API()) { - wchar_t *wpath; - gint retval; - gint save_errno; - - wpath = g_utf8_to_utf16(path, -1, NULL, NULL, NULL); - if (wpath == NULL) { - errno = EINVAL; - return -1; - } - - retval = _wchdir(wpath); - save_errno = errno; - - g_free(wpath); - - errno = save_errno; - return retval; - } else { - gchar *cp_path; - gint retval; - gint save_errno; - - cp_path = g_locale_from_utf8(path, -1, NULL, NULL, NULL); - if (cp_path == NULL) { - errno = EINVAL; - return -1; - } - - retval = chdir(cp_path); - save_errno = errno; - - g_free(cp_path); - - errno = save_errno; - return retval; - } -#else - return chdir(path); -#endif -} - -gint g_chmod(const gchar *path, gint mode) -{ -#ifdef G_OS_WIN32 - if (G_WIN32_HAVE_WIDECHAR_API()) { - wchar_t *wpath; - gint retval; - gint save_errno; - - wpath = g_utf8_to_utf16(path, -1, NULL, NULL, NULL); - if (wpath == NULL) { - errno = EINVAL; - return -1; - } - - retval = _wchmod(wpath, mode); - save_errno = errno; - - g_free(wpath); - - errno = save_errno; - return retval; - } else { - gchar *cp_path; - gint retval; - gint save_errno; - - cp_path = g_locale_from_utf8(path, -1, NULL, NULL, NULL); - if (cp_path == NULL) { - errno = EINVAL; - return -1; - } - - retval = chmod(cp_path, mode); - save_errno = errno; - - g_free(cp_path); - - errno = save_errno; - return retval; - } -#else - return chmod(path, mode); -#endif -} -#endif /* GLIB_CHECK_VERSION && G_OS_UNIX */ - -void list_free_strings(GList *list) -{ - list = g_list_first(list); - - while (list != NULL) { - g_free(list->data); - list = list->next; - } -} - -void slist_free_strings(GSList *list) -{ - while (list != NULL) { - g_free(list->data); - list = list->next; - } -} - -static void hash_free_strings_func(gpointer key, gpointer value, gpointer data) -{ - g_free(key); -} - -void hash_free_strings(GHashTable *table) -{ - g_hash_table_foreach(table, hash_free_strings_func, NULL); -} - -static void hash_free_value_mem_func(gpointer key, gpointer value, - gpointer data) -{ - g_free(value); -} - -void hash_free_value_mem(GHashTable *table) -{ - g_hash_table_foreach(table, hash_free_value_mem_func, NULL); -} - -gint str_case_equal(gconstpointer v, gconstpointer v2) -{ - return g_ascii_strcasecmp((const gchar *)v, (const gchar *)v2) == 0; -} - -guint str_case_hash(gconstpointer key) -{ - const gchar *p = key; - guint h = *p; - - if (h) { - h = g_ascii_tolower(h); - for (p += 1; *p != '\0'; p++) - h = (h << 5) - h + g_ascii_tolower(*p); - } - - return h; -} - -void ptr_array_free_strings(GPtrArray *array) -{ - gint i; - gchar *str; - - g_return_if_fail(array != NULL); - - for (i = 0; i < array->len; i++) { - str = g_ptr_array_index(array, i); - g_free(str); - } -} - -gboolean str_find(const gchar *haystack, const gchar *needle) -{ - return strstr(haystack, needle) != NULL ? TRUE : FALSE; -} - -gboolean str_case_find(const gchar *haystack, const gchar *needle) -{ - return strcasestr(haystack, needle) != NULL ? TRUE : FALSE; -} - -gboolean str_find_equal(const gchar *haystack, const gchar *needle) -{ - return strcmp(haystack, needle) == 0; -} - -gboolean str_case_find_equal(const gchar *haystack, const gchar *needle) -{ - return g_ascii_strcasecmp(haystack, needle) == 0; -} - -gint to_number(const gchar *nstr) -{ - register const gchar *p; - - if (*nstr == '\0') return -1; - - for (p = nstr; *p != '\0'; p++) - if (!g_ascii_isdigit(*p)) return -1; - - return atoi(nstr); -} - -/* convert integer into string, - nstr must be not lower than 11 characters length */ -gchar *itos_buf(gchar *nstr, gint n) -{ - g_snprintf(nstr, 11, "%d", n); - return nstr; -} - -/* convert integer into string */ -gchar *itos(gint n) -{ - static gchar nstr[11]; - - return itos_buf(nstr, n); -} - -gchar *to_human_readable(off_t size) -{ - static gchar str[10]; - - if (size < 1024) - g_snprintf(str, sizeof(str), _("%dB"), (gint)size); - else if (size >> 10 < 1024) - g_snprintf(str, sizeof(str), _("%.1fKB"), (gfloat)size / (1 << 10)); - else if (size >> 20 < 1024) - g_snprintf(str, sizeof(str), _("%.2fMB"), (gfloat)size / (1 << 20)); - else - g_snprintf(str, sizeof(str), _("%.2fGB"), (gfloat)size / (1 << 30)); - - return str; -} - -/* strcmp with NULL-checking */ -gint strcmp2(const gchar *s1, const gchar *s2) -{ - if (s1 == NULL || s2 == NULL) - return -1; - else - return strcmp(s1, s2); -} - -/* compare paths */ -gint path_cmp(const gchar *s1, const gchar *s2) -{ - gint len1, len2; -#ifdef G_OS_WIN32 - gchar *s1_, *s2_; -#endif - - if (s1 == NULL || s2 == NULL) return -1; - if (*s1 == '\0' || *s2 == '\0') return -1; - - len1 = strlen(s1); - len2 = strlen(s2); - -#ifdef G_OS_WIN32 - Xstrdup_a(s1_, s1, return -1); - Xstrdup_a(s2_, s2, return -1); - subst_char(s1_, '/', G_DIR_SEPARATOR); - subst_char(s2_, '/', G_DIR_SEPARATOR); - if (s1_[len1 - 1] == G_DIR_SEPARATOR) len1--; - if (s2_[len2 - 1] == G_DIR_SEPARATOR) len2--; - - return strncmp(s1_, s2_, MAX(len1, len2)); -#else - if (s1[len1 - 1] == G_DIR_SEPARATOR) len1--; - if (s2[len2 - 1] == G_DIR_SEPARATOR) len2--; - - return strncmp(s1, s2, MAX(len1, len2)); -#endif -} - -/* remove trailing return code */ -gchar *strretchomp(gchar *str) -{ - register gchar *s; - - if (!*str) return str; - - for (s = str + strlen(str) - 1; - s >= str && (*s == '\n' || *s == '\r'); - s--) - *s = '\0'; - - return str; -} - -/* remove trailing character */ -gchar *strtailchomp(gchar *str, gchar tail_char) -{ - register gchar *s; - - if (!*str) return str; - if (tail_char == '\0') return str; - - for (s = str + strlen(str) - 1; s >= str && *s == tail_char; s--) - *s = '\0'; - - return str; -} - -/* remove CR (carriage return) */ -gchar *strcrchomp(gchar *str) -{ - register gchar *s; - - if (!*str) return str; - - s = str + strlen(str) - 1; - if (*s == '\n' && s > str && *(s - 1) == '\r') { - *(s - 1) = '\n'; - *s = '\0'; - } - - return str; -} - -/* Similar to `strstr' but this function ignores the case of both strings. */ -gchar *strcasestr(const gchar *haystack, const gchar *needle) -{ - register size_t haystack_len, needle_len; - - haystack_len = strlen(haystack); - needle_len = strlen(needle); - - if (haystack_len < needle_len || needle_len == 0) - return NULL; - - while (haystack_len >= needle_len) { - if (!g_ascii_strncasecmp(haystack, needle, needle_len)) - return (gchar *)haystack; - else { - haystack++; - haystack_len--; - } - } - - return NULL; -} - -gpointer my_memmem(gconstpointer haystack, size_t haystacklen, - gconstpointer needle, size_t needlelen) -{ - const gchar *haystack_ = (const gchar *)haystack; - const gchar *needle_ = (const gchar *)needle; - const gchar *haystack_cur = (const gchar *)haystack; - - if (needlelen == 1) - return memchr(haystack_, *needle_, haystacklen); - - while ((haystack_cur = memchr(haystack_cur, *needle_, haystacklen)) - != NULL) { - if (haystacklen - (haystack_cur - haystack_) < needlelen) - break; - if (memcmp(haystack_cur + 1, needle_ + 1, needlelen - 1) == 0) - return (gpointer)haystack_cur; - else - haystack_cur++; - } - - return NULL; -} - -/* Copy no more than N characters of SRC to DEST, with NULL terminating. */ -gchar *strncpy2(gchar *dest, const gchar *src, size_t n) -{ - register const gchar *s = src; - register gchar *d = dest; - - while (--n && *s) - *d++ = *s++; - *d = '\0'; - - return dest; -} - -#if !HAVE_ISWALNUM -int iswalnum(wint_t wc) -{ - return g_ascii_isalnum((int)wc); -} -#endif - -#if !HAVE_ISWSPACE -int iswspace(wint_t wc) -{ - return g_ascii_isspace((int)wc); -} -#endif - -#if !HAVE_TOWLOWER -wint_t towlower(wint_t wc) -{ - if (wc >= L'A' && wc <= L'Z') - return wc + L'a' - L'A'; - - return wc; -} -#endif - -#if !HAVE_WCSLEN -size_t wcslen(const wchar_t *s) -{ - size_t len = 0; - - while (*s != L'\0') - ++len, ++s; - - return len; -} -#endif - -#if !HAVE_WCSCPY -/* Copy SRC to DEST. */ -wchar_t *wcscpy(wchar_t *dest, const wchar_t *src) -{ - wint_t c; - wchar_t *s = dest; - - do { - c = *src++; - *dest++ = c; - } while (c != L'\0'); - - return s; -} -#endif - -#if !HAVE_WCSNCPY -/* Copy no more than N wide-characters of SRC to DEST. */ -wchar_t *wcsncpy (wchar_t *dest, const wchar_t *src, size_t n) -{ - wint_t c; - wchar_t *s = dest; - - do { - c = *src++; - *dest++ = c; - if (--n == 0) - return s; - } while (c != L'\0'); - - /* zero fill */ - do - *dest++ = L'\0'; - while (--n > 0); - - return s; -} -#endif - -/* Duplicate S, returning an identical malloc'd string. */ -wchar_t *wcsdup(const wchar_t *s) -{ - wchar_t *new_str; - - if (s) { - new_str = g_new(wchar_t, wcslen(s) + 1); - wcscpy(new_str, s); - } else - new_str = NULL; - - return new_str; -} - -/* Duplicate no more than N wide-characters of S, - returning an identical malloc'd string. */ -wchar_t *wcsndup(const wchar_t *s, size_t n) -{ - wchar_t *new_str; - - if (s) { - new_str = g_new(wchar_t, n + 1); - wcsncpy(new_str, s, n); - new_str[n] = (wchar_t)0; - } else - new_str = NULL; - - return new_str; -} - -wchar_t *strdup_mbstowcs(const gchar *s) -{ - wchar_t *new_str; - - if (s) { - new_str = g_new(wchar_t, strlen(s) + 1); - if (mbstowcs(new_str, s, strlen(s) + 1) < 0) { - g_free(new_str); - new_str = NULL; - } else - new_str = g_realloc(new_str, - sizeof(wchar_t) * (wcslen(new_str) + 1)); - } else - new_str = NULL; - - return new_str; -} - -gchar *strdup_wcstombs(const wchar_t *s) -{ - gchar *new_str; - size_t len; - - if (s) { - len = wcslen(s) * MB_CUR_MAX + 1; - new_str = g_new(gchar, len); - if (wcstombs(new_str, s, len) < 0) { - g_free(new_str); - new_str = NULL; - } else - new_str = g_realloc(new_str, strlen(new_str) + 1); - } else - new_str = NULL; - - return new_str; -} - -/* Compare S1 and S2, ignoring case. */ -gint wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n) -{ - wint_t c1; - wint_t c2; - - while (n--) { - c1 = towlower(*s1++); - c2 = towlower(*s2++); - if (c1 != c2) - return c1 - c2; - else if (c1 == 0 && c2 == 0) - break; - } - - return 0; -} - -/* Find the first occurrence of NEEDLE in HAYSTACK, ignoring case. */ -wchar_t *wcscasestr(const wchar_t *haystack, const wchar_t *needle) -{ - register size_t haystack_len, needle_len; - - haystack_len = wcslen(haystack); - needle_len = wcslen(needle); - - if (haystack_len < needle_len || needle_len == 0) - return NULL; - - while (haystack_len >= needle_len) { - if (!wcsncasecmp(haystack, needle, needle_len)) - return (wchar_t *)haystack; - else { - haystack++; - haystack_len--; - } - } - - return NULL; -} - -gint get_mbs_len(const gchar *s) -{ - const gchar *p = s; - gint mb_len; - gint len = 0; - - if (!p) - return -1; - - while (*p != '\0') { - mb_len = g_utf8_skip[*(guchar *)p]; - if (mb_len == 0) - break; - else - len++; - - p += mb_len; - } - - return len; -} - -/* Examine if next block is non-ASCII string */ -gboolean is_next_nonascii(const gchar *s) -{ - const gchar *p; - - /* skip head space */ - for (p = s; *p != '\0' && g_ascii_isspace(*p); p++) - ; - for (; *p != '\0' && !g_ascii_isspace(*p); p++) { - if (*(guchar *)p > 127 || *(guchar *)p < 32) - return TRUE; - } - - return FALSE; -} - -gint get_next_word_len(const gchar *s) -{ - gint len = 0; - - for (; *s != '\0' && !g_ascii_isspace(*s); s++, len++) - ; - - return len; -} - -/* compare subjects */ -gint subject_compare(const gchar *s1, const gchar *s2) -{ - gchar *str1, *str2; - - if (!s1 || !s2) return -1; - if (!*s1 || !*s2) return -1; - - Xstrdup_a(str1, s1, return -1); - Xstrdup_a(str2, s2, return -1); - - trim_subject_for_compare(str1); - trim_subject_for_compare(str2); - - if (!*str1 || !*str2) return -1; - - return strcmp(str1, str2); -} - -gint subject_compare_for_sort(const gchar *s1, const gchar *s2) -{ - gchar *str1, *str2; - - if (!s1 || !s2) return -1; - - Xstrdup_a(str1, s1, return -1); - Xstrdup_a(str2, s2, return -1); - - trim_subject_for_sort(str1); - trim_subject_for_sort(str2); - - return g_ascii_strcasecmp(str1, str2); -} - -void trim_subject_for_compare(gchar *str) -{ - gchar *srcp; - - eliminate_parenthesis(str, '[', ']'); - eliminate_parenthesis(str, '(', ')'); - g_strstrip(str); - - while (!g_ascii_strncasecmp(str, "Re:", 3)) { - srcp = str + 3; - while (g_ascii_isspace(*srcp)) srcp++; - memmove(str, srcp, strlen(srcp) + 1); - } -} - -void trim_subject_for_sort(gchar *str) -{ - gchar *srcp; - - g_strstrip(str); - - while (!g_ascii_strncasecmp(str, "Re:", 3)) { - srcp = str + 3; - while (g_ascii_isspace(*srcp)) srcp++; - memmove(str, srcp, strlen(srcp) + 1); - } -} - -void trim_subject(gchar *str) -{ - register gchar *srcp, *destp; - gchar op, cl; - gint in_brace; - - destp = str; - while (!g_ascii_strncasecmp(destp, "Re:", 3)) { - destp += 3; - while (g_ascii_isspace(*destp)) destp++; - } - - if (*destp == '[') { - op = '['; - cl = ']'; - } else if (*destp == '(') { - op = '('; - cl = ')'; - } else - return; - - srcp = destp + 1; - in_brace = 1; - while (*srcp) { - if (*srcp == op) - in_brace++; - else if (*srcp == cl) - in_brace--; - srcp++; - if (in_brace == 0) - break; - } - while (g_ascii_isspace(*srcp)) srcp++; - memmove(destp, srcp, strlen(srcp) + 1); -} - -void eliminate_parenthesis(gchar *str, gchar op, gchar cl) -{ - register gchar *srcp, *destp; - gint in_brace; - - srcp = destp = str; - - while ((destp = strchr(destp, op))) { - in_brace = 1; - srcp = destp + 1; - while (*srcp) { - if (*srcp == op) - in_brace++; - else if (*srcp == cl) - in_brace--; - srcp++; - if (in_brace == 0) - break; - } - while (g_ascii_isspace(*srcp)) srcp++; - memmove(destp, srcp, strlen(srcp) + 1); - } -} - -void extract_parenthesis(gchar *str, gchar op, gchar cl) -{ - register gchar *srcp, *destp; - gint in_brace; - - srcp = destp = str; - - while ((srcp = strchr(destp, op))) { - if (destp > str) - *destp++ = ' '; - memmove(destp, srcp + 1, strlen(srcp)); - in_brace = 1; - while(*destp) { - if (*destp == op) - in_brace++; - else if (*destp == cl) - in_brace--; - - if (in_brace == 0) - break; - - destp++; - } - } - *destp = '\0'; -} - -void extract_parenthesis_with_skip_quote(gchar *str, gchar quote_chr, - gchar op, gchar cl) -{ - register gchar *srcp, *destp; - gint in_brace; - gboolean in_quote = FALSE; - - srcp = destp = str; - - while ((srcp = strchr_with_skip_quote(destp, quote_chr, op))) { - if (destp > str) - *destp++ = ' '; - memmove(destp, srcp + 1, strlen(srcp)); - in_brace = 1; - while(*destp) { - if (*destp == op && !in_quote) - in_brace++; - else if (*destp == cl && !in_quote) - in_brace--; - else if (*destp == quote_chr) - in_quote ^= TRUE; - - if (in_brace == 0) - break; - - destp++; - } - } - *destp = '\0'; -} - -void eliminate_quote(gchar *str, gchar quote_chr) -{ - register gchar *srcp, *destp; - - srcp = destp = str; - - while ((destp = strchr(destp, quote_chr))) { - if ((srcp = strchr(destp + 1, quote_chr))) { - srcp++; - while (g_ascii_isspace(*srcp)) srcp++; - memmove(destp, srcp, strlen(srcp) + 1); - } else { - *destp = '\0'; - break; - } - } -} - -void extract_quote(gchar *str, gchar quote_chr) -{ - register gchar *p; - - if ((str = strchr(str, quote_chr))) { - if ((p = strchr(str + 1, quote_chr))) { - *p = '\0'; - memmove(str, str + 1, p - str); - } - } -} - -void eliminate_address_comment(gchar *str) -{ - register gchar *srcp, *destp; - gint in_brace; - - srcp = destp = str; - - while ((destp = strchr(destp, '"'))) { - if ((srcp = strchr(destp + 1, '"'))) { - srcp++; - if (*srcp == '@') { - destp = srcp + 1; - } else { - while (g_ascii_isspace(*srcp)) srcp++; - memmove(destp, srcp, strlen(srcp) + 1); - } - } else { - *destp = '\0'; - break; - } - } - - srcp = destp = str; - - while ((destp = strchr_with_skip_quote(destp, '"', '('))) { - in_brace = 1; - srcp = destp + 1; - while (*srcp) { - if (*srcp == '(') - in_brace++; - else if (*srcp == ')') - in_brace--; - srcp++; - if (in_brace == 0) - break; - } - while (g_ascii_isspace(*srcp)) srcp++; - memmove(destp, srcp, strlen(srcp) + 1); - } -} - -gchar *strchr_with_skip_quote(const gchar *str, gint quote_chr, gint c) -{ - gboolean in_quote = FALSE; - - while (*str) { - if (*str == c && !in_quote) - return (gchar *)str; - if (*str == quote_chr) - in_quote ^= TRUE; - str++; - } - - return NULL; -} - -gchar *strrchr_with_skip_quote(const gchar *str, gint quote_chr, gint c) -{ - gboolean in_quote = FALSE; - const gchar *p; - - p = str + strlen(str) - 1; - while (p >= str) { - if (*p == c && !in_quote) - return (gchar *)p; - if (*p == quote_chr) - in_quote ^= TRUE; - p--; - } - - return NULL; -} - -void extract_address(gchar *str) -{ - eliminate_address_comment(str); - if (strchr_with_skip_quote(str, '"', '<')) - extract_parenthesis_with_skip_quote(str, '"', '<', '>'); - g_strstrip(str); -} - -void extract_list_id_str(gchar *str) -{ - if (strchr_with_skip_quote(str, '"', '<')) - extract_parenthesis_with_skip_quote(str, '"', '<', '>'); - g_strstrip(str); -} - -GSList *address_list_append(GSList *addr_list, const gchar *str) -{ - gchar *work; - gchar *workp; - - if (!str) return addr_list; - - Xstrdup_a(work, str, return addr_list); - - eliminate_address_comment(work); - workp = work; - - while (workp && *workp) { - gchar *p, *next; - - if ((p = strchr_with_skip_quote(workp, '"', ','))) { - *p = '\0'; - next = p + 1; - } else - next = NULL; - - if (strchr_with_skip_quote(workp, '"', '<')) - extract_parenthesis_with_skip_quote - (workp, '"', '<', '>'); - - g_strstrip(workp); - if (*workp) - addr_list = g_slist_append(addr_list, g_strdup(workp)); - - workp = next; - } - - return addr_list; -} - -GSList *references_list_prepend(GSList *msgid_list, const gchar *str) -{ - const gchar *strp; - - if (!str) return msgid_list; - strp = str; - - while (strp && *strp) { - const gchar *start, *end; - gchar *msgid; - - if ((start = strchr(strp, '<')) != NULL) { - end = strchr(start + 1, '>'); - if (!end) break; - } else - break; - - msgid = g_strndup(start + 1, end - start - 1); - g_strstrip(msgid); - if (*msgid) - msgid_list = g_slist_prepend(msgid_list, msgid); - else - g_free(msgid); - - strp = end + 1; - } - - return msgid_list; -} - -GSList *references_list_append(GSList *msgid_list, const gchar *str) -{ - GSList *list; - - list = references_list_prepend(NULL, str); - list = g_slist_reverse(list); - msgid_list = g_slist_concat(msgid_list, list); - - return msgid_list; -} - -GSList *newsgroup_list_append(GSList *group_list, const gchar *str) -{ - gchar *work; - gchar *workp; - - if (!str) return group_list; - - Xstrdup_a(work, str, return group_list); - - workp = work; - - while (workp && *workp) { - gchar *p, *next; - - if ((p = strchr_with_skip_quote(workp, '"', ','))) { - *p = '\0'; - next = p + 1; - } else - next = NULL; - - g_strstrip(workp); - if (*workp) - group_list = g_slist_append(group_list, - g_strdup(workp)); - - workp = next; - } - - return group_list; -} - -GList *add_history(GList *list, const gchar *str) -{ - GList *old; - - g_return_val_if_fail(str != NULL, list); - - old = g_list_find_custom(list, (gpointer)str, (GCompareFunc)strcmp2); - if (old) { - g_free(old->data); - list = g_list_remove(list, old->data); - } else if (g_list_length(list) >= MAX_HISTORY_SIZE) { - GList *last; - - last = g_list_last(list); - if (last) { - g_free(last->data); - g_list_remove(list, last->data); - } - } - - list = g_list_prepend(list, g_strdup(str)); - - return list; -} - -void remove_return(gchar *str) -{ - register gchar *p = str; - - while (*p) { - if (*p == '\n' || *p == '\r') - memmove(p, p + 1, strlen(p)); - else - p++; - } -} - -void remove_space(gchar *str) -{ - register gchar *p = str; - register gint spc; - - while (*p) { - spc = 0; - while (g_ascii_isspace(*(p + spc))) - spc++; - if (spc) - memmove(p, p + spc, strlen(p + spc) + 1); - else - p++; - } -} - -void unfold_line(gchar *str) -{ - register gchar *p = str; - register gint spc; - - while (*p) { - if (*p == '\n' || *p == '\r') { - *p++ = ' '; - spc = 0; - while (g_ascii_isspace(*(p + spc))) - spc++; - if (spc) - memmove(p, p + spc, strlen(p + spc) + 1); - } else - p++; - } -} - -void subst_char(gchar *str, gchar orig, gchar subst) -{ - register gchar *p = str; - - while (*p) { - if (*p == orig) - *p = subst; - p++; - } -} - -void subst_chars(gchar *str, gchar *orig, gchar subst) -{ - register gchar *p = str; - - while (*p) { - if (strchr(orig, *p) != NULL) - *p = subst; - p++; - } -} - -void subst_null(gchar *str, gint len, gchar subst) -{ - register gchar *p = str; - - while (len--) { - if (*p == '\0') - *p = subst; - p++; - } -} - -void subst_for_filename(gchar *str) -{ - subst_chars(str, " \t\r\n\"'/\\", '_'); -} - -gboolean is_header_line(const gchar *str) -{ - if (str[0] == ':') return FALSE; - - while (*str != '\0' && *str != ' ') { - if (*str == ':') - return TRUE; - str++; - } - - return FALSE; -} - -gboolean is_ascii_str(const gchar *str) -{ - const guchar *p = (const guchar *)str; - - while (*p != '\0') { - if (*p != '\t' && *p != ' ' && - *p != '\r' && *p != '\n' && - (*p < 32 || *p >= 127)) - return FALSE; - p++; - } - - return TRUE; -} - -gint get_quote_level(const gchar *str) -{ - const gchar *first_pos; - const gchar *last_pos; - const gchar *p = str; - gint quote_level = -1; - - /* speed up line processing by only searching to the last '>' */ - if ((first_pos = strchr(str, '>')) != NULL) { - /* skip a line if it contains a '<' before the initial '>' */ - if (memchr(str, '<', first_pos - str) != NULL) - return -1; - last_pos = strrchr(first_pos, '>'); - } else - return -1; - - while (p <= last_pos) { - while (p < last_pos) { - if (g_ascii_isspace(*p)) - p++; - else - break; - } - - if (*p == '>') - quote_level++; - else if (*p != '-' && !g_ascii_isspace(*p) && p <= last_pos) { - /* any characters are allowed except '-' and space */ - while (*p != '-' && *p != '>' && !g_ascii_isspace(*p) && - p < last_pos) - p++; - if (*p == '>') - quote_level++; - else - break; - } - - p++; - } - - return quote_level; -} - -gint check_line_length(const gchar *str, gint max_chars, gint *line) -{ - const gchar *p = str, *q; - gint cur_line = 0, len; - - while ((q = strchr(p, '\n')) != NULL) { - len = q - p + 1; - if (len > max_chars) { - if (line) - *line = cur_line; - return -1; - } - p = q + 1; - ++cur_line; - } - - len = strlen(p); - if (len > max_chars) { - if (line) - *line = cur_line; - return -1; - } - - return 0; -} - -gchar *strstr_with_skip_quote(const gchar *haystack, const gchar *needle) -{ - register guint haystack_len, needle_len; - gboolean in_squote = FALSE, in_dquote = FALSE; - - haystack_len = strlen(haystack); - needle_len = strlen(needle); - - if (haystack_len < needle_len || needle_len == 0) - return NULL; - - while (haystack_len >= needle_len) { - if (!in_squote && !in_dquote && - !strncmp(haystack, needle, needle_len)) - return (gchar *)haystack; - - /* 'foo"bar"' -> foo"bar" - "foo'bar'" -> foo'bar' */ - if (*haystack == '\'') { - if (in_squote) - in_squote = FALSE; - else if (!in_dquote) - in_squote = TRUE; - } else if (*haystack == '\"') { - if (in_dquote) - in_dquote = FALSE; - else if (!in_squote) - in_dquote = TRUE; - } - - haystack++; - haystack_len--; - } - - return NULL; -} - -gchar *strchr_parenthesis_close(const gchar *str, gchar op, gchar cl) -{ - const gchar *p; - gchar quote_chr = '"'; - gint in_brace; - gboolean in_quote = FALSE; - - p = str; - - if ((p = strchr_with_skip_quote(p, quote_chr, op))) { - p++; - in_brace = 1; - while (*p) { - if (*p == op && !in_quote) - in_brace++; - else if (*p == cl && !in_quote) - in_brace--; - else if (*p == quote_chr) - in_quote ^= TRUE; - - if (in_brace == 0) - return (gchar *)p; - - p++; - } - } - - return NULL; -} - -gchar **strsplit_parenthesis(const gchar *str, gchar op, gchar cl, - gint max_tokens) -{ - GSList *string_list = NULL, *slist; - gchar **str_array; - const gchar *s_op, *s_cl; - guint i, n = 1; - - g_return_val_if_fail(str != NULL, NULL); - - if (max_tokens < 1) - max_tokens = G_MAXINT; - - s_op = strchr_with_skip_quote(str, '"', op); - if (!s_op) return NULL; - str = s_op; - s_cl = strchr_parenthesis_close(str, op, cl); - if (s_cl) { - do { - guint len; - gchar *new_string; - - str++; - len = s_cl - str; - new_string = g_new(gchar, len + 1); - strncpy(new_string, str, len); - new_string[len] = 0; - string_list = g_slist_prepend(string_list, new_string); - n++; - str = s_cl + 1; - - while (*str && g_ascii_isspace(*str)) str++; - if (*str != op) { - string_list = g_slist_prepend(string_list, - g_strdup("")); - n++; - s_op = strchr_with_skip_quote(str, '"', op); - if (!--max_tokens || !s_op) break; - str = s_op; - } else - s_op = str; - s_cl = strchr_parenthesis_close(str, op, cl); - } while (--max_tokens && s_cl); - } - - str_array = g_new(gchar*, n); - - i = n - 1; - - str_array[i--] = NULL; - for (slist = string_list; slist; slist = slist->next) - str_array[i--] = slist->data; - - g_slist_free(string_list); - - return str_array; -} - -gchar **strsplit_with_quote(const gchar *str, const gchar *delim, - gint max_tokens) -{ - GSList *string_list = NULL, *slist; - gchar **str_array, *s, *new_str; - guint i, n = 1, len; - - g_return_val_if_fail(str != NULL, NULL); - g_return_val_if_fail(delim != NULL, NULL); - - if (max_tokens < 1) - max_tokens = G_MAXINT; - - s = strstr_with_skip_quote(str, delim); - if (s) { - guint delimiter_len = strlen(delim); - - do { - len = s - str; - new_str = g_strndup(str, len); - - if (new_str[0] == '\'' || new_str[0] == '\"') { - if (new_str[len - 1] == new_str[0]) { - new_str[len - 1] = '\0'; - memmove(new_str, new_str + 1, len - 1); - } - } - string_list = g_slist_prepend(string_list, new_str); - n++; - str = s + delimiter_len; - s = strstr_with_skip_quote(str, delim); - } while (--max_tokens && s); - } - - if (*str) { - new_str = g_strdup(str); - if (new_str[0] == '\'' || new_str[0] == '\"') { - len = strlen(str); - if (new_str[len - 1] == new_str[0]) { - new_str[len - 1] = '\0'; - memmove(new_str, new_str + 1, len - 1); - } - } - string_list = g_slist_prepend(string_list, new_str); - n++; - } - - str_array = g_new(gchar*, n); - - i = n - 1; - - str_array[i--] = NULL; - for (slist = string_list; slist; slist = slist->next) - str_array[i--] = slist->data; - - g_slist_free(string_list); - - return str_array; -} - -gchar *get_abbrev_newsgroup_name(const gchar *group, gint len) -{ - gchar *abbrev_group; - gchar *ap; - const gchar *p = group; - const gchar *last; - - last = group + strlen(group); - abbrev_group = ap = g_malloc(strlen(group) + 1); - - while (*p) { - while (*p == '.') - *ap++ = *p++; - if ((ap - abbrev_group) + (last - p) > len && strchr(p, '.')) { - *ap++ = *p++; - while (*p != '.') p++; - } else { - strcpy(ap, p); - return abbrev_group; - } - } - - *ap = '\0'; - return abbrev_group; -} - -gchar *trim_string(const gchar *str, gint len) -{ - const gchar *p = str; - gint mb_len; - gchar *new_str; - gint new_len = 0; - - if (!str) return NULL; - if (strlen(str) <= len) - return g_strdup(str); - if (g_utf8_validate(str, -1, NULL) == FALSE) - return g_strdup(str); - - while (*p != '\0') { - mb_len = g_utf8_skip[*(guchar *)p]; - if (mb_len == 0) - break; - else if (new_len + mb_len > len) - break; - - new_len += mb_len; - p += mb_len; - } - - Xstrndup_a(new_str, str, new_len, return g_strdup(str)); - return g_strconcat(new_str, "...", NULL); -} - -gchar *trim_string_before(const gchar *str, gint len) -{ - const gchar *p = str; - gint mb_len; - gint new_len; - - if (!str) return NULL; - if ((new_len = strlen(str)) <= len) - return g_strdup(str); - if (g_utf8_validate(str, -1, NULL) == FALSE) - return g_strdup(str); - - while (*p != '\0') { - mb_len = g_utf8_skip[*(guchar *)p]; - if (mb_len == 0) - break; - - new_len -= mb_len; - p += mb_len; - - if (new_len <= len) - break; - } - - return g_strconcat("...", p, NULL); -} - -GList *uri_list_extract_filenames(const gchar *uri_list) -{ - GList *result = NULL; - const gchar *p, *q; - gchar *file; - - p = uri_list; - - while (p) { - if (*p != '#') { - while (g_ascii_isspace(*p)) p++; - if (!strncmp(p, "file:", 5)) { - p += 5; - while (*p == '/' && *(p + 1) == '/') p++; - q = p; - while (*q && *q != '\n' && *q != '\r') q++; - - if (q > p) { - q--; - while (q > p && g_ascii_isspace(*q)) - q--; - file = g_malloc(q - p + 2); - strncpy(file, p, q - p + 1); - file[q - p + 1] = '\0'; - decode_uri(file, file); - result = g_list_append(result,file); - } - } - } - p = strchr(p, '\n'); - if (p) p++; - } - - return result; -} - -#define HEX_TO_INT(val, hex) \ -{ \ - gchar c = hex; \ - \ - if ('0' <= c && c <= '9') { \ - val = c - '0'; \ - } else if ('a' <= c && c <= 'f') { \ - val = c - 'a' + 10; \ - } else if ('A' <= c && c <= 'F') { \ - val = c - 'A' + 10; \ - } else { \ - val = 0; \ - } \ -} - -/* Converts two-digit hexadecimal to decimal. Used for unescaping escaped - * characters. - */ -static gint axtoi(const gchar *hex_str) -{ - gint hi, lo; - - HEX_TO_INT(hi, hex_str[0]); - HEX_TO_INT(lo, hex_str[1]); - - return (hi << 4) + lo; -} - -gboolean is_uri_string(const gchar *str) -{ - return (g_ascii_strncasecmp(str, "http://", 7) == 0 || - g_ascii_strncasecmp(str, "https://", 8) == 0 || - g_ascii_strncasecmp(str, "ftp://", 6) == 0 || - g_ascii_strncasecmp(str, "www.", 4) == 0); -} - -gchar *get_uri_path(const gchar *uri) -{ - if (g_ascii_strncasecmp(uri, "http://", 7) == 0) - return (gchar *)(uri + 7); - else if (g_ascii_strncasecmp(uri, "https://", 8) == 0) - return (gchar *)(uri + 8); - else if (g_ascii_strncasecmp(uri, "ftp://", 6) == 0) - return (gchar *)(uri + 6); - else - return (gchar *)uri; -} - -gint get_uri_len(const gchar *str) -{ - const gchar *p; - - if (is_uri_string(str)) { - for (p = str; *p != '\0'; p++) { - if (!g_ascii_isgraph(*p) || strchr("()<>\"", *p)) - break; - } - return p - str; - } - - return 0; -} - -/* Decodes URL-Encoded strings (i.e. strings in which spaces are replaced by - * plusses, and escape characters are used) - * Note: decoded_uri and encoded_uri can point the same location - */ -void decode_uri(gchar *decoded_uri, const gchar *encoded_uri) -{ - gchar *dec = decoded_uri; - const gchar *enc = encoded_uri; - - while (*enc) { - if (*enc == '%') { - enc++; - if (isxdigit((guchar)enc[0]) && - isxdigit((guchar)enc[1])) { - *dec = axtoi(enc); - dec++; - enc += 2; - } - } else { - if (*enc == '+') - *dec = ' '; - else - *dec = *enc; - dec++; - enc++; - } - } - - *dec = '\0'; -} - -gchar *encode_uri(const gchar *filename) -{ - gchar *uri; - - uri = g_filename_to_uri(filename, NULL, NULL); - if (!uri) - uri = g_strconcat("file://", filename, NULL); - - return uri; -} - -gint scan_mailto_url(const gchar *mailto, gchar **to, gchar **cc, gchar **bcc, - gchar **subject, gchar **body) -{ - gchar *tmp_mailto; - gchar *p; - - Xstrdup_a(tmp_mailto, mailto, return -1); - - if (!strncmp(tmp_mailto, "mailto:", 7)) - tmp_mailto += 7; - - p = strchr(tmp_mailto, '?'); - if (p) { - *p = '\0'; - p++; - } - - if (to && !*to) - *to = g_strdup(tmp_mailto); - - while (p) { - gchar *field, *value; - - field = p; - - p = strchr(p, '='); - if (!p) break; - *p = '\0'; - p++; - - value = p; - - p = strchr(p, '&'); - if (p) { - *p = '\0'; - p++; - } - - if (*value == '\0') continue; - - if (cc && !*cc && !g_ascii_strcasecmp(field, "cc")) { - *cc = g_strdup(value); - } else if (bcc && !*bcc && !g_ascii_strcasecmp(field, "bcc")) { - *bcc = g_strdup(value); - } else if (subject && !*subject && - !g_ascii_strcasecmp(field, "subject")) { - *subject = g_malloc(strlen(value) + 1); - decode_uri(*subject, value); - } else if (body && !*body && - !g_ascii_strcasecmp(field, "body")) { - *body = g_malloc(strlen(value) + 1); - decode_uri(*body, value); - } - } - - return 0; -} - -const gchar *get_home_dir(void) -{ -#ifdef G_OS_WIN32 - static const gchar *home_dir = NULL; - - if (!home_dir) { - home_dir = g_get_home_dir(); - if (!home_dir) - home_dir = "C:\\Sylpheed"; - } - - return home_dir; -#else - return g_get_home_dir(); -#endif -} - -const gchar *get_rc_dir(void) -{ - static gchar *rc_dir = NULL; - - if (!rc_dir) -#ifdef G_OS_WIN32 - rc_dir = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, - "Application Data", G_DIR_SEPARATOR_S, - RC_DIR, NULL); -#else - rc_dir = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, - RC_DIR, NULL); -#endif - - return rc_dir; -} - -const gchar *get_old_rc_dir(void) -{ - static gchar *old_rc_dir = NULL; - - if (!old_rc_dir) - old_rc_dir = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, - OLD_RC_DIR, NULL); - - return old_rc_dir; -} - -const gchar *get_mail_base_dir(void) -{ -#ifdef G_OS_WIN32 - static gchar *mail_base_dir = NULL; - - if (!mail_base_dir) - mail_base_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, - "Mailboxes", NULL); - - return mail_base_dir; -#else - return get_home_dir(); -#endif -} - -const gchar *get_news_cache_dir(void) -{ - static gchar *news_cache_dir = NULL; - - if (!news_cache_dir) - news_cache_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, - NEWS_CACHE_DIR, NULL); - - return news_cache_dir; -} - -const gchar *get_imap_cache_dir(void) -{ - static gchar *imap_cache_dir = NULL; - - if (!imap_cache_dir) - imap_cache_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, - IMAP_CACHE_DIR, NULL); - - return imap_cache_dir; -} - -const gchar *get_mime_tmp_dir(void) -{ - static gchar *mime_tmp_dir = NULL; - - if (!mime_tmp_dir) - mime_tmp_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, - MIME_TMP_DIR, NULL); - - return mime_tmp_dir; -} - -const gchar *get_template_dir(void) -{ - static gchar *template_dir = NULL; - - if (!template_dir) - template_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, - TEMPLATE_DIR, NULL); - - return template_dir; -} - -const gchar *get_tmp_dir(void) -{ - static gchar *tmp_dir = NULL; - - if (!tmp_dir) - tmp_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, - TMP_DIR, NULL); - - return tmp_dir; -} - -gchar *get_tmp_file(void) -{ - gchar *tmp_file; - static guint32 id = 0; - - tmp_file = g_strdup_printf("%s%ctmpfile.%08x", - get_tmp_dir(), G_DIR_SEPARATOR, id++); - - return tmp_file; -} - -const gchar *get_domain_name(void) -{ -#ifdef G_OS_UNIX - static gchar *domain_name = NULL; - - if (!domain_name) { - gchar buf[128] = ""; - struct hostent *hp; - - if (gethostname(buf, sizeof(buf)) < 0) { - perror("gethostname"); - domain_name = "unknown"; - } else { - buf[sizeof(buf) - 1] = '\0'; - if ((hp = my_gethostbyname(buf)) == NULL) { - perror("gethostbyname"); - domain_name = g_strdup(buf); - } else { - domain_name = g_strdup(hp->h_name); - } - } - - debug_print("domain name = %s\n", domain_name); - } - - return domain_name; -#else - return "unknown"; -#endif -} - -off_t get_file_size(const gchar *file) -{ - struct stat s; - - if (g_stat(file, &s) < 0) { - FILE_OP_ERROR(file, "stat"); - return -1; - } - - return s.st_size; -} - -off_t get_file_size_as_crlf(const gchar *file) -{ - FILE *fp; - off_t size = 0; - gchar buf[BUFFSIZE]; - - if ((fp = g_fopen(file, "rb")) == NULL) { - FILE_OP_ERROR(file, "fopen"); - return -1; - } - - while (fgets(buf, sizeof(buf), fp) != NULL) { - strretchomp(buf); - size += strlen(buf) + 2; - } - - if (ferror(fp)) { - FILE_OP_ERROR(file, "fgets"); - size = -1; - } - - fclose(fp); - - return size; -} - -off_t get_left_file_size(FILE *fp) -{ - glong pos; - glong end; - off_t size; - - if ((pos = ftell(fp)) < 0) { - perror("ftell"); - return -1; - } - if (fseek(fp, 0L, SEEK_END) < 0) { - perror("fseek"); - return -1; - } - if ((end = ftell(fp)) < 0) { - perror("fseek"); - return -1; - } - size = end - pos; - if (fseek(fp, pos, SEEK_SET) < 0) { - perror("fseek"); - return -1; - } - - return size; -} - -gboolean file_exist(const gchar *file, gboolean allow_fifo) -{ - struct stat s; - - if (file == NULL) - return FALSE; - - if (g_stat(file, &s) < 0) { - if (ENOENT != errno) FILE_OP_ERROR(file, "stat"); - return FALSE; - } - - if (S_ISREG(s.st_mode) || (allow_fifo && S_ISFIFO(s.st_mode))) - return TRUE; - - return FALSE; -} - -gboolean is_dir_exist(const gchar *dir) -{ - if (dir == NULL) - return FALSE; - - return g_file_test(dir, G_FILE_TEST_IS_DIR); -} - -gboolean is_file_entry_exist(const gchar *file) -{ - if (file == NULL) - return FALSE; - - return g_file_test(file, G_FILE_TEST_EXISTS); -} - -gboolean dirent_is_regular_file(struct dirent *d) -{ -#ifdef HAVE_DIRENT_D_TYPE - if (d->d_type == DT_REG) - return TRUE; - else if (d->d_type != DT_UNKNOWN) - return FALSE; -#endif - - return g_file_test(d->d_name, G_FILE_TEST_IS_REGULAR); -} - -gboolean dirent_is_directory(struct dirent *d) -{ -#ifdef HAVE_DIRENT_D_TYPE - if (d->d_type == DT_DIR) - return TRUE; - else if (d->d_type != DT_UNKNOWN) - return FALSE; -#endif - - return g_file_test(d->d_name, G_FILE_TEST_IS_DIR); -} - -gint change_dir(const gchar *dir) -{ - gchar *prevdir = NULL; - - if (debug_mode) - prevdir = g_get_current_dir(); - - if (g_chdir(dir) < 0) { - FILE_OP_ERROR(dir, "chdir"); - if (debug_mode) g_free(prevdir); - return -1; - } else if (debug_mode) { - gchar *cwd; - - cwd = g_get_current_dir(); - if (strcmp(prevdir, cwd) != 0) - g_print("current dir: %s\n", cwd); - g_free(cwd); - g_free(prevdir); - } - - return 0; -} - -gint make_dir(const gchar *dir) -{ - if (g_mkdir(dir, S_IRWXU) < 0) { - FILE_OP_ERROR(dir, "mkdir"); - return -1; - } - if (g_chmod(dir, S_IRWXU) < 0) - FILE_OP_ERROR(dir, "chmod"); - - return 0; -} - -gint make_dir_hier(const gchar *dir) -{ - gchar *parent_dir; - const gchar *p; - - for (p = dir; (p = strchr(p, G_DIR_SEPARATOR)) != NULL; p++) { - parent_dir = g_strndup(dir, p - dir); - if (*parent_dir != '\0') { - if (!is_dir_exist(parent_dir)) { - if (make_dir(parent_dir) < 0) { - g_free(parent_dir); - return -1; - } - } - } - g_free(parent_dir); - } - - if (!is_dir_exist(dir)) { - if (make_dir(dir) < 0) - return -1; - } - - return 0; -} - -gint remove_all_files(const gchar *dir) -{ - GDir *dp; - const gchar *dir_name; - gchar *prev_dir; - - prev_dir = g_get_current_dir(); - - if (g_chdir(dir) < 0) { - FILE_OP_ERROR(dir, "chdir"); - g_free(prev_dir); - return -1; - } - - if ((dp = g_dir_open(".", 0, NULL)) == NULL) { - g_warning("failed to open directory: %s\n", dir); - g_free(prev_dir); - return -1; - } - - while ((dir_name = g_dir_read_name(dp)) != NULL) { - if (g_unlink(dir_name) < 0) - FILE_OP_ERROR(dir_name, "unlink"); - } - - g_dir_close(dp); - - if (g_chdir(prev_dir) < 0) { - FILE_OP_ERROR(prev_dir, "chdir"); - g_free(prev_dir); - return -1; - } - - g_free(prev_dir); - - return 0; -} - -gint remove_numbered_files(const gchar *dir, guint first, guint last) -{ - GDir *dp; - const gchar *dir_name; - gchar *prev_dir; - gint file_no; - - prev_dir = g_get_current_dir(); - - if (g_chdir(dir) < 0) { - FILE_OP_ERROR(dir, "chdir"); - g_free(prev_dir); - return -1; - } - - if ((dp = g_dir_open(".", 0, NULL)) == NULL) { - g_warning("failed to open directory: %s\n", dir); - g_free(prev_dir); - return -1; - } - - while ((dir_name = g_dir_read_name(dp)) != NULL) { - file_no = to_number(dir_name); - if (file_no > 0 && first <= file_no && file_no <= last) { - if (is_dir_exist(dir_name)) - continue; - if (g_unlink(dir_name) < 0) - FILE_OP_ERROR(dir_name, "unlink"); - } - } - - g_dir_close(dp); - - if (g_chdir(prev_dir) < 0) { - FILE_OP_ERROR(prev_dir, "chdir"); - g_free(prev_dir); - return -1; - } - - g_free(prev_dir); - - return 0; -} - -gint remove_all_numbered_files(const gchar *dir) -{ - return remove_numbered_files(dir, 0, UINT_MAX); -} - -gint remove_expired_files(const gchar *dir, guint hours) -{ - GDir *dp; - const gchar *dir_name; - struct stat s; - gchar *prev_dir; - gint file_no; - time_t mtime, now, expire_time; - - prev_dir = g_get_current_dir(); - - if (g_chdir(dir) < 0) { - FILE_OP_ERROR(dir, "chdir"); - g_free(prev_dir); - return -1; - } - - if ((dp = g_dir_open(".", 0, NULL)) == NULL) { - g_warning("failed to open directory: %s\n", dir); - g_free(prev_dir); - return -1; - } - - now = time(NULL); - expire_time = hours * 60 * 60; - - while ((dir_name = g_dir_read_name(dp)) != NULL) { - file_no = to_number(dir_name); - if (file_no > 0) { - if (g_stat(dir_name, &s) < 0) { - FILE_OP_ERROR(dir_name, "stat"); - continue; - } - if (S_ISDIR(s.st_mode)) - continue; - mtime = MAX(s.st_mtime, s.st_atime); - if (now - mtime > expire_time) { - if (g_unlink(dir_name) < 0) - FILE_OP_ERROR(dir_name, "unlink"); - } - } - } - - g_dir_close(dp); - - if (g_chdir(prev_dir) < 0) { - FILE_OP_ERROR(prev_dir, "chdir"); - g_free(prev_dir); - return -1; - } - - g_free(prev_dir); - - return 0; -} - -static gint remove_dir_recursive_real(const gchar *dir) -{ - struct stat s; - GDir *dp; - const gchar *dir_name; - gchar *prev_dir; - - if (g_stat(dir, &s) < 0) { - FILE_OP_ERROR(dir, "stat"); - if (ENOENT == errno) return 0; - return -1; - } - - if (!S_ISDIR(s.st_mode)) { - if (g_unlink(dir) < 0) { - FILE_OP_ERROR(dir, "unlink"); - return -1; - } - - return 0; - } - - prev_dir = g_get_current_dir(); - /* g_print("prev_dir = %s\n", prev_dir); */ - - if (g_chdir(dir) < 0) { - FILE_OP_ERROR(dir, "chdir"); - g_free(prev_dir); - return -1; - } - - if ((dp = g_dir_open(".", 0, NULL)) == NULL) { - g_warning("failed to open directory: %s\n", dir); - g_chdir(prev_dir); - g_free(prev_dir); - return -1; - } - - /* remove all files in the directory */ - while ((dir_name = g_dir_read_name(dp)) != NULL) { - /* g_print("removing %s\n", dir_name); */ - - if (is_dir_exist(dir_name)) { - if (remove_dir_recursive_real(dir_name) < 0) { - g_warning("can't remove directory\n"); - return -1; - } - } else { - if (g_unlink(dir_name) < 0) - FILE_OP_ERROR(dir_name, "unlink"); - } - } - - g_dir_close(dp); - - if (g_chdir(prev_dir) < 0) { - FILE_OP_ERROR(prev_dir, "chdir"); - g_free(prev_dir); - return -1; - } - - g_free(prev_dir); - - if (g_rmdir(dir) < 0) { - FILE_OP_ERROR(dir, "rmdir"); - return -1; - } - - return 0; -} - -gint remove_dir_recursive(const gchar *dir) -{ - gchar *cur_dir; - gint ret; - - cur_dir = g_get_current_dir(); - - if (g_chdir(dir) < 0) { - FILE_OP_ERROR(dir, "chdir"); - ret = -1; - goto leave; - } - if (g_chdir("..") < 0) { - FILE_OP_ERROR(dir, "chdir"); - ret = -1; - goto leave; - } - - ret = remove_dir_recursive_real(dir); - -leave: - if (is_dir_exist(cur_dir)) { - if (g_chdir(cur_dir) < 0) { - FILE_OP_ERROR(cur_dir, "chdir"); - } - } - - g_free(cur_dir); - - return ret; -} - -gint rename_force(const gchar *oldpath, const gchar *newpath) -{ -#ifndef G_OS_UNIX - if (!is_file_entry_exist(oldpath)) { - errno = ENOENT; - return -1; - } - if (is_file_exist(newpath)) { - if (g_unlink(newpath) < 0) - FILE_OP_ERROR(newpath, "unlink"); - } -#endif - return g_rename(oldpath, newpath); -} - -gint copy_file(const gchar *src, const gchar *dest, gboolean keep_backup) -{ - FILE *src_fp, *dest_fp; - gint n_read; - gchar buf[BUFSIZ]; - gchar *dest_bak = NULL; - gboolean err = FALSE; - - if ((src_fp = g_fopen(src, "rb")) == NULL) { - FILE_OP_ERROR(src, "fopen"); - return -1; - } - if (is_file_exist(dest)) { - dest_bak = g_strconcat(dest, ".bak", NULL); - if (rename_force(dest, dest_bak) < 0) { - FILE_OP_ERROR(dest, "rename"); - fclose(src_fp); - g_free(dest_bak); - return -1; - } - } - - if ((dest_fp = g_fopen(dest, "wb")) == NULL) { - FILE_OP_ERROR(dest, "fopen"); - fclose(src_fp); - if (dest_bak) { - if (rename_force(dest_bak, dest) < 0) - FILE_OP_ERROR(dest_bak, "rename"); - g_free(dest_bak); - } - return -1; - } - - if (change_file_mode_rw(dest_fp, dest) < 0) { - FILE_OP_ERROR(dest, "chmod"); - g_warning(_("can't change file mode\n")); - } - - while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), src_fp)) > 0) { - if (n_read < sizeof(buf) && ferror(src_fp)) - break; - if (fwrite(buf, n_read, 1, dest_fp) < 1) { - g_warning(_("writing to %s failed.\n"), dest); - fclose(dest_fp); - fclose(src_fp); - g_unlink(dest); - if (dest_bak) { - if (rename_force(dest_bak, dest) < 0) - FILE_OP_ERROR(dest_bak, "rename"); - g_free(dest_bak); - } - return -1; - } - } - - if (ferror(src_fp)) { - FILE_OP_ERROR(src, "fread"); - err = TRUE; - } - fclose(src_fp); - if (fclose(dest_fp) == EOF) { - FILE_OP_ERROR(dest, "fclose"); - err = TRUE; - } - - if (err) { - g_unlink(dest); - if (dest_bak) { - if (rename_force(dest_bak, dest) < 0) - FILE_OP_ERROR(dest_bak, "rename"); - g_free(dest_bak); - } - return -1; - } - - if (keep_backup == FALSE && dest_bak) - g_unlink(dest_bak); - - g_free(dest_bak); - - return 0; -} - -gint copy_dir(const gchar *src, const gchar *dest) -{ - GDir *dir; - const gchar *dir_name; - gchar *src_file; - gchar *dest_file; - - if ((dir = g_dir_open(src, 0, NULL)) == NULL) { - g_warning("failed to open directory: %s\n", src); - return -1; - } - - if (make_dir_hier(dest) < 0) { - g_dir_close(dir); - return -1; - } - - while ((dir_name = g_dir_read_name(dir)) != NULL) { - src_file = g_strconcat(src, G_DIR_SEPARATOR_S, dir_name, NULL); - dest_file = g_strconcat(dest, G_DIR_SEPARATOR_S, dir_name, - NULL); - if (is_file_exist(src_file)) - copy_file(src_file, dest_file, FALSE); - g_free(dest_file); - g_free(src_file); - } - - g_dir_close(dir); - - return 0; -} - -gint move_file(const gchar *src, const gchar *dest, gboolean overwrite) -{ - if (overwrite == FALSE && is_file_exist(dest)) { - g_warning("move_file(): file %s already exists.", dest); - return -1; - } - - if (rename_force(src, dest) == 0) return 0; - - if (EXDEV != errno) { - FILE_OP_ERROR(src, "rename"); - return -1; - } - - if (copy_file(src, dest, FALSE) < 0) return -1; - - g_unlink(src); - - return 0; -} - -gint copy_file_part(FILE *fp, off_t offset, size_t length, const gchar *dest) -{ - FILE *dest_fp; - gint n_read; - gint bytes_left, to_read; - gchar buf[BUFSIZ]; - gboolean err = FALSE; - - if (fseek(fp, offset, SEEK_SET) < 0) { - perror("fseek"); - return -1; - } - - if ((dest_fp = g_fopen(dest, "wb")) == NULL) { - FILE_OP_ERROR(dest, "fopen"); - return -1; - } - - if (change_file_mode_rw(dest_fp, dest) < 0) { - FILE_OP_ERROR(dest, "chmod"); - g_warning("can't change file mode\n"); - } - - bytes_left = length; - to_read = MIN(bytes_left, sizeof(buf)); - - while ((n_read = fread(buf, sizeof(gchar), to_read, fp)) > 0) { - if (n_read < to_read && ferror(fp)) - break; - if (fwrite(buf, n_read, 1, dest_fp) < 1) { - g_warning(_("writing to %s failed.\n"), dest); - fclose(dest_fp); - g_unlink(dest); - return -1; - } - bytes_left -= n_read; - if (bytes_left == 0) - break; - to_read = MIN(bytes_left, sizeof(buf)); - } - - if (ferror(fp)) { - perror("fread"); - err = TRUE; - } - if (fclose(dest_fp) == EOF) { - FILE_OP_ERROR(dest, "fclose"); - err = TRUE; - } - - if (err) { - g_unlink(dest); - return -1; - } - - return 0; -} - -/* convert line endings into CRLF. If the last line doesn't end with - * linebreak, add it. - */ -gchar *canonicalize_str(const gchar *str) -{ - const gchar *p; - guint new_len = 0; - gchar *out, *outp; - - for (p = str; *p != '\0'; ++p) { - if (*p != '\r') { - ++new_len; - if (*p == '\n') - ++new_len; - } - } - if (p == str || *(p - 1) != '\n') - new_len += 2; - - out = outp = g_malloc(new_len + 1); - for (p = str; *p != '\0'; ++p) { - if (*p != '\r') { - if (*p == '\n') - *outp++ = '\r'; - *outp++ = *p; - } - } - if (p == str || *(p - 1) != '\n') { - *outp++ = '\r'; - *outp++ = '\n'; - } - *outp = '\0'; - - return out; -} - -gint canonicalize_file(const gchar *src, const gchar *dest) -{ - FILE *src_fp, *dest_fp; - gchar buf[BUFFSIZE]; - gint len; - gboolean err = FALSE; - gboolean last_linebreak = FALSE; - - if ((src_fp = g_fopen(src, "rb")) == NULL) { - FILE_OP_ERROR(src, "fopen"); - return -1; - } - - if ((dest_fp = g_fopen(dest, "wb")) == NULL) { - FILE_OP_ERROR(dest, "fopen"); - fclose(src_fp); - return -1; - } - - if (change_file_mode_rw(dest_fp, dest) < 0) { - FILE_OP_ERROR(dest, "chmod"); - g_warning("can't change file mode\n"); - } - - while (fgets(buf, sizeof(buf), src_fp) != NULL) { - gint r = 0; - - len = strlen(buf); - if (len == 0) break; - last_linebreak = FALSE; - - if (buf[len - 1] != '\n') { - last_linebreak = TRUE; - r = fputs(buf, dest_fp); - } else if (len > 1 && buf[len - 1] == '\n' && buf[len - 2] == '\r') { - r = fputs(buf, dest_fp); - } else { - if (len > 1) { - r = fwrite(buf, len - 1, 1, dest_fp); - if (r != 1) - r = EOF; - } - if (r != EOF) - r = fputs("\r\n", dest_fp); - } - - if (r == EOF) { - g_warning("writing to %s failed.\n", dest); - fclose(dest_fp); - fclose(src_fp); - g_unlink(dest); - return -1; - } - } - - if (last_linebreak == TRUE) { - if (fputs("\r\n", dest_fp) == EOF) - err = TRUE; - } - - if (ferror(src_fp)) { - FILE_OP_ERROR(src, "fgets"); - err = TRUE; - } - fclose(src_fp); - if (fclose(dest_fp) == EOF) { - FILE_OP_ERROR(dest, "fclose"); - err = TRUE; - } - - if (err) { - g_unlink(dest); - return -1; - } - - return 0; -} - -gint canonicalize_file_replace(const gchar *file) -{ - gchar *tmp_file; - - tmp_file = get_tmp_file(); - - if (canonicalize_file(file, tmp_file) < 0) { - g_free(tmp_file); - return -1; - } - - if (move_file(tmp_file, file, TRUE) < 0) { - g_warning("can't replace %s .\n", file); - g_unlink(tmp_file); - g_free(tmp_file); - return -1; - } - - g_free(tmp_file); - return 0; -} - -gint uncanonicalize_file(const gchar *src, const gchar *dest) -{ - FILE *src_fp, *dest_fp; - gchar buf[BUFFSIZE]; - gboolean err = FALSE; - - if ((src_fp = g_fopen(src, "rb")) == NULL) { - FILE_OP_ERROR(src, "fopen"); - return -1; - } - - if ((dest_fp = g_fopen(dest, "wb")) == NULL) { - FILE_OP_ERROR(dest, "fopen"); - fclose(src_fp); - return -1; - } - - if (change_file_mode_rw(dest_fp, dest) < 0) { - FILE_OP_ERROR(dest, "chmod"); - g_warning("can't change file mode\n"); - } - - while (fgets(buf, sizeof(buf), src_fp) != NULL) { - strcrchomp(buf); - if (fputs(buf, dest_fp) == EOF) { - g_warning("writing to %s failed.\n", dest); - fclose(dest_fp); - fclose(src_fp); - g_unlink(dest); - return -1; - } - } - - if (ferror(src_fp)) { - FILE_OP_ERROR(src, "fgets"); - err = TRUE; - } - fclose(src_fp); - if (fclose(dest_fp) == EOF) { - FILE_OP_ERROR(dest, "fclose"); - err = TRUE; - } - - if (err) { - g_unlink(dest); - return -1; - } - - return 0; -} - -gint uncanonicalize_file_replace(const gchar *file) -{ - gchar *tmp_file; - - tmp_file = get_tmp_file(); - - if (uncanonicalize_file(file, tmp_file) < 0) { - g_free(tmp_file); - return -1; - } - - if (move_file(tmp_file, file, TRUE) < 0) { - g_warning("can't replace %s .\n", file); - g_unlink(tmp_file); - g_free(tmp_file); - return -1; - } - - g_free(tmp_file); - return 0; -} - -gchar *normalize_newlines(const gchar *str) -{ - const gchar *p = str; - gchar *out, *outp; - - out = outp = g_malloc(strlen(str) + 1); - for (p = str; *p != '\0'; ++p) { - if (*p == '\r') { - if (*(p + 1) != '\n') - *outp++ = '\n'; - } else - *outp++ = *p; - } - - *outp = '\0'; - - return out; -} - -gchar *get_outgoing_rfc2822_str(FILE *fp) -{ - gchar buf[BUFFSIZE]; - GString *str; - gchar *ret; - - str = g_string_new(NULL); - - /* output header part */ - while (fgets(buf, sizeof(buf), fp) != NULL) { - strretchomp(buf); - if (!g_ascii_strncasecmp(buf, "Bcc:", 4)) { - gint next; - - for (;;) { - next = fgetc(fp); - if (next == EOF) - break; - else if (next != ' ' && next != '\t') { - ungetc(next, fp); - break; - } - if (fgets(buf, sizeof(buf), fp) == NULL) - break; - } -#if 0 - } else if (!g_ascii_strncasecmp(buf, "Date:", 5)) { - get_rfc822_date(buf, sizeof(buf)); - g_string_append_printf(str, "Date: %s\r\n", buf); -#endif - } else { - g_string_append(str, buf); - g_string_append(str, "\r\n"); - if (buf[0] == '\0') - break; - } - } - - /* output body part */ - while (fgets(buf, sizeof(buf), fp) != NULL) { - strretchomp(buf); - if (buf[0] == '.') - g_string_append_c(str, '.'); - g_string_append(str, buf); - g_string_append(str, "\r\n"); - } - - ret = str->str; - g_string_free(str, FALSE); - - return ret; -} - -/* - * Create a new boundary in a way that it is very unlikely that this - * will occur in the following text. It would be easy to ensure - * uniqueness if everything is either quoted-printable or base64 - * encoded (note that conversion is allowed), but because MIME bodies - * may be nested, it may happen that the same boundary has already - * been used. We avoid scanning the message for conflicts and hope the - * best. - * - * boundary := 0*69<bchars> bcharsnospace - * bchars := bcharsnospace / " " - * bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / - * "+" / "_" / "," / "-" / "." / - * "/" / ":" / "=" / "?" - * - * some special characters removed because of buggy MTAs - */ - -gchar *generate_mime_boundary(const gchar *prefix) -{ - static gchar tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "1234567890+_./="; - gchar buf_uniq[17]; - gchar buf_date[64]; - gint i; - - for (i = 0; i < sizeof(buf_uniq) - 1; i++) - buf_uniq[i] = tbl[g_random_int_range(0, sizeof(tbl) - 1)]; - buf_uniq[i] = '\0'; - - get_rfc822_date(buf_date, sizeof(buf_date)); - subst_char(buf_date, ' ', '_'); - subst_char(buf_date, ',', '_'); - subst_char(buf_date, ':', '_'); - - return g_strdup_printf("%s=_%s_%s", prefix ? prefix : "Multipart", - buf_date, buf_uniq); -} - -gint change_file_mode_rw(FILE *fp, const gchar *file) -{ -#if HAVE_FCHMOD - return fchmod(fileno(fp), S_IRUSR|S_IWUSR); -#else - return g_chmod(file, S_IRUSR|S_IWUSR); -#endif -} - -FILE *my_tmpfile(void) -{ -#if HAVE_MKSTEMP - const gchar suffix[] = ".XXXXXX"; - const gchar *tmpdir; - guint tmplen; - const gchar *progname; - guint proglen; - gchar *fname; - gint fd; - FILE *fp; - - tmpdir = get_tmp_dir(); - tmplen = strlen(tmpdir); - progname = g_get_prgname(); - proglen = strlen(progname); - Xalloca(fname, tmplen + 1 + proglen + sizeof(suffix), - return tmpfile()); - - memcpy(fname, tmpdir, tmplen); - fname[tmplen] = G_DIR_SEPARATOR; - memcpy(fname + tmplen + 1, progname, proglen); - memcpy(fname + tmplen + 1 + proglen, suffix, sizeof(suffix)); - - fd = mkstemp(fname); - if (fd < 0) - return tmpfile(); - - g_unlink(fname); - - fp = fdopen(fd, "w+b"); - if (!fp) - close(fd); - else - return fp; -#endif /* HAVE_MKSTEMP */ - - return tmpfile(); -} - -FILE *str_open_as_stream(const gchar *str) -{ - FILE *fp; - size_t len; - - g_return_val_if_fail(str != NULL, NULL); - - fp = my_tmpfile(); - if (!fp) { - FILE_OP_ERROR("str_open_as_stream", "my_tmpfile"); - return NULL; - } - - len = strlen(str); - if (len == 0) return fp; - - if (fwrite(str, len, 1, fp) != 1) { - FILE_OP_ERROR("str_open_as_stream", "fwrite"); - fclose(fp); - return NULL; - } - - rewind(fp); - return fp; -} - -gint str_write_to_file(const gchar *str, const gchar *file) -{ - FILE *fp; - size_t len; - - g_return_val_if_fail(str != NULL, -1); - g_return_val_if_fail(file != NULL, -1); - - if ((fp = g_fopen(file, "wb")) == NULL) { - FILE_OP_ERROR(file, "fopen"); - return -1; - } - - len = strlen(str); - if (len == 0) { - fclose(fp); - return 0; - } - - if (fwrite(str, len, 1, fp) != 1) { - FILE_OP_ERROR(file, "fwrite"); - fclose(fp); - g_unlink(file); - return -1; - } - - if (fclose(fp) == EOF) { - FILE_OP_ERROR(file, "fclose"); - g_unlink(file); - return -1; - } - - return 0; -} - -gchar *file_read_to_str(const gchar *file) -{ - FILE *fp; - gchar *str; - - g_return_val_if_fail(file != NULL, NULL); - - if ((fp = g_fopen(file, "rb")) == NULL) { - FILE_OP_ERROR(file, "fopen"); - return NULL; - } - - str = file_read_stream_to_str(fp); - - fclose(fp); - - return str; -} - -gchar *file_read_stream_to_str(FILE *fp) -{ - GByteArray *array; - guchar buf[BUFSIZ]; - gint n_read; - gchar *str; - - g_return_val_if_fail(fp != NULL, NULL); - - array = g_byte_array_new(); - - while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) { - if (n_read < sizeof(buf) && ferror(fp)) - break; - g_byte_array_append(array, buf, n_read); - } - - if (ferror(fp)) { - FILE_OP_ERROR("file stream", "fread"); - g_byte_array_free(array, TRUE); - return NULL; - } - - buf[0] = '\0'; - g_byte_array_append(array, buf, 1); - str = (gchar *)array->data; - g_byte_array_free(array, FALSE); - - return str; -} - -gint execute_async(gchar *const argv[]) -{ - g_return_val_if_fail(argv != NULL && argv[0] != NULL, -1); - - if (g_spawn_async(NULL, (gchar **)argv, NULL, G_SPAWN_SEARCH_PATH, - NULL, NULL, NULL, FALSE) == FALSE) { - g_warning("Can't execute command: %s\n", argv[0]); - return -1; - } - - return 0; -} - -gint execute_sync(gchar *const argv[]) -{ - gint status; - - g_return_val_if_fail(argv != NULL && argv[0] != NULL, -1); - - if (g_spawn_sync(NULL, (gchar **)argv, NULL, G_SPAWN_SEARCH_PATH, - NULL, NULL, NULL, NULL, &status, NULL) == FALSE) { - g_warning("Can't execute command: %s\n", argv[0]); - return -1; - } - -#ifdef G_OS_UNIX - if (WIFEXITED(status)) - return WEXITSTATUS(status); - else - return -1; -#else - return status; -#endif -} - -gint execute_command_line(const gchar *cmdline, gboolean async) -{ - gchar **argv; - gint ret; - - debug_print("execute_command_line(): executing: %s\n", cmdline); - - argv = strsplit_with_quote(cmdline, " ", 0); - - if (async) - ret = execute_async(argv); - else - ret = execute_sync(argv); - - g_strfreev(argv); - - return ret; -} - -gchar *get_command_output(const gchar *cmdline) -{ - gchar *child_stdout; - gint status; - - g_return_val_if_fail(cmdline != NULL, NULL); - - debug_print("get_command_output(): executing: %s\n", cmdline); - - if (g_spawn_command_line_sync(cmdline, &child_stdout, NULL, &status, - NULL) == FALSE) { - g_warning("Can't execute command: %s\n", cmdline); - return NULL; - } - - return child_stdout; -} - -gint open_uri(const gchar *uri, const gchar *cmdline) -{ - gchar buf[BUFFSIZE]; - gchar *p; - - g_return_val_if_fail(uri != NULL, -1); - - if (cmdline && - (p = strchr(cmdline, '%')) && *(p + 1) == 's' && - !strchr(p + 2, '%')) - g_snprintf(buf, sizeof(buf), cmdline, uri); - else { - if (cmdline) - g_warning("Open URI command line is invalid " - "(there must be only one '%%s'): %s", - cmdline); - g_snprintf(buf, sizeof(buf), DEFAULT_BROWSER_CMD, uri); - } - - execute_command_line(buf, TRUE); - - return 0; -} - -time_t remote_tzoffset_sec(const gchar *zone) -{ - static gchar ustzstr[] = "PSTPDTMSTMDTCSTCDTESTEDT"; - gchar zone3[4]; - gchar *p; - gchar c; - gint iustz; - gint offset; - time_t remoteoffset; - - strncpy(zone3, zone, 3); - zone3[3] = '\0'; - remoteoffset = 0; - - if (sscanf(zone, "%c%d", &c, &offset) == 2 && - (c == '+' || c == '-')) { - remoteoffset = ((offset / 100) * 60 + (offset % 100)) * 60; - if (c == '-') - remoteoffset = -remoteoffset; - } else if (!strncmp(zone, "UT" , 2) || - !strncmp(zone, "GMT", 2)) { - remoteoffset = 0; - } else if (strlen(zone3) == 3) { - for (p = ustzstr; *p != '\0'; p += 3) { - if (!g_ascii_strncasecmp(p, zone3, 3)) { - iustz = ((gint)(p - ustzstr) / 3 + 1) / 2 - 8; - remoteoffset = iustz * 3600; - break; - } - } - if (*p == '\0') - return -1; - } else if (strlen(zone3) == 1) { - switch (zone[0]) { - case 'Z': remoteoffset = 0; break; - case 'A': remoteoffset = -1; break; - case 'B': remoteoffset = -2; break; - case 'C': remoteoffset = -3; break; - case 'D': remoteoffset = -4; break; - case 'E': remoteoffset = -5; break; - case 'F': remoteoffset = -6; break; - case 'G': remoteoffset = -7; break; - case 'H': remoteoffset = -8; break; - case 'I': remoteoffset = -9; break; - case 'K': remoteoffset = -10; break; /* J is not used */ - case 'L': remoteoffset = -11; break; - case 'M': remoteoffset = -12; break; - case 'N': remoteoffset = 1; break; - case 'O': remoteoffset = 2; break; - case 'P': remoteoffset = 3; break; - case 'Q': remoteoffset = 4; break; - case 'R': remoteoffset = 5; break; - case 'S': remoteoffset = 6; break; - case 'T': remoteoffset = 7; break; - case 'U': remoteoffset = 8; break; - case 'V': remoteoffset = 9; break; - case 'W': remoteoffset = 10; break; - case 'X': remoteoffset = 11; break; - case 'Y': remoteoffset = 12; break; - default: remoteoffset = 0; break; - } - remoteoffset = remoteoffset * 3600; - } else - return -1; - - return remoteoffset; -} - -time_t tzoffset_sec(time_t *now) -{ - struct tm gmt, *lt; - gint off; - - gmt = *gmtime(now); - lt = localtime(now); - - off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min; - - if (lt->tm_year < gmt.tm_year) - off -= 24 * 60; - else if (lt->tm_year > gmt.tm_year) - off += 24 * 60; - else if (lt->tm_yday < gmt.tm_yday) - off -= 24 * 60; - else if (lt->tm_yday > gmt.tm_yday) - off += 24 * 60; - - if (off >= 24 * 60) /* should be impossible */ - off = 23 * 60 + 59; /* if not, insert silly value */ - if (off <= -24 * 60) - off = -(23 * 60 + 59); - - return off * 60; -} - -/* calculate timezone offset */ -gchar *tzoffset(time_t *now) -{ - static gchar offset_string[6]; - struct tm gmt, *lt; - gint off; - gchar sign = '+'; - - gmt = *gmtime(now); - lt = localtime(now); - - off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min; - - if (lt->tm_year < gmt.tm_year) - off -= 24 * 60; - else if (lt->tm_year > gmt.tm_year) - off += 24 * 60; - else if (lt->tm_yday < gmt.tm_yday) - off -= 24 * 60; - else if (lt->tm_yday > gmt.tm_yday) - off += 24 * 60; - - if (off < 0) { - sign = '-'; - off = -off; - } - - if (off >= 24 * 60) /* should be impossible */ - off = 23 * 60 + 59; /* if not, insert silly value */ - - sprintf(offset_string, "%c%02d%02d", sign, off / 60, off % 60); - - return offset_string; -} - -void get_rfc822_date(gchar *buf, gint len) -{ - struct tm *lt; - time_t t; - gchar day[4], mon[4]; - gint dd, hh, mm, ss, yyyy; - - t = time(NULL); - lt = localtime(&t); - - sscanf(asctime(lt), "%3s %3s %d %d:%d:%d %d\n", - day, mon, &dd, &hh, &mm, &ss, &yyyy); - g_snprintf(buf, len, "%s, %d %s %d %02d:%02d:%02d %s", - day, dd, mon, yyyy, hh, mm, ss, tzoffset(&t)); -} - -/* just a wrapper to suppress the warning of gcc about %c */ -size_t my_strftime(gchar *s, size_t max, const gchar *format, - const struct tm *tm) -{ - return strftime(s, max, format, tm); -} - -static FILE *log_fp = NULL; - -void set_log_file(const gchar *filename) -{ - if (log_fp) return; - log_fp = g_fopen(filename, "wb"); - if (!log_fp) - FILE_OP_ERROR(filename, "fopen"); -} - -void close_log_file(void) -{ - if (log_fp) { - fclose(log_fp); - log_fp = NULL; - } -} - -static guint log_verbosity_count = 0; - -void set_log_verbosity(gboolean verbose) -{ - if (verbose) - log_verbosity_count++; - else if (log_verbosity_count > 0) - log_verbosity_count--; -} - -gboolean get_debug_mode(void) -{ - return debug_mode; -} - -void set_debug_mode(gboolean enable) -{ - debug_mode = enable; -} - -static void log_dummy_func(const gchar *str) -{ -} - -static LogFunc log_print_ui_func = log_dummy_func; -static LogFunc log_message_ui_func = log_dummy_func; -static LogFunc log_warning_ui_func = log_dummy_func; -static LogFunc log_error_ui_func = log_dummy_func; - -static LogFunc log_show_status_func = log_dummy_func; - -void set_log_ui_func(LogFunc print_func, LogFunc message_func, - LogFunc warning_func, LogFunc error_func) -{ - log_print_ui_func = print_func; - log_message_ui_func = message_func; - log_warning_ui_func = warning_func; - log_error_ui_func = error_func; -} - -void set_log_show_status_func(LogFunc status_func) -{ - log_show_status_func = status_func; -} - -void debug_print(const gchar *format, ...) -{ - va_list args; - gchar buf[BUFFSIZE]; - - if (!debug_mode) return; - - va_start(args, format); - g_vsnprintf(buf, sizeof(buf), format, args); - va_end(args); - - g_print("%s", buf); -} - -#define TIME_LEN 11 - -void log_print(const gchar *format, ...) -{ - va_list args; - gchar buf[BUFFSIZE + TIME_LEN]; - time_t t; - - time(&t); - strftime(buf, TIME_LEN + 1, "[%H:%M:%S] ", localtime(&t)); - - va_start(args, format); - g_vsnprintf(buf + TIME_LEN, BUFFSIZE, format, args); - va_end(args); - - if (debug_mode) fputs(buf, stdout); - log_print_ui_func(buf); - if (log_fp) { - fputs(buf, log_fp); - fflush(log_fp); - } - if (log_verbosity_count) - log_show_status_func(buf + TIME_LEN); -} - -void log_message(const gchar *format, ...) -{ - va_list args; - gchar buf[BUFFSIZE + TIME_LEN]; - time_t t; - - time(&t); - strftime(buf, TIME_LEN + 1, "[%H:%M:%S] ", localtime(&t)); - - va_start(args, format); - g_vsnprintf(buf + TIME_LEN, BUFFSIZE, format, args); - va_end(args); - - if (debug_mode) g_message("%s", buf + TIME_LEN); - log_message_ui_func(buf + TIME_LEN); - if (log_fp) { - fwrite(buf, TIME_LEN, 1, log_fp); - fputs("* message: ", log_fp); - fputs(buf + TIME_LEN, log_fp); - fflush(log_fp); - } - log_show_status_func(buf + TIME_LEN); -} - -void log_warning(const gchar *format, ...) -{ - va_list args; - gchar buf[BUFFSIZE + TIME_LEN]; - time_t t; - - time(&t); - strftime(buf, TIME_LEN + 1, "[%H:%M:%S] ", localtime(&t)); - - va_start(args, format); - g_vsnprintf(buf + TIME_LEN, BUFFSIZE, format, args); - va_end(args); - - g_warning("%s", buf); - log_warning_ui_func(buf + TIME_LEN); - if (log_fp) { - fwrite(buf, TIME_LEN, 1, log_fp); - fputs("** warning: ", log_fp); - fputs(buf + TIME_LEN, log_fp); - fflush(log_fp); - } -} - -void log_error(const gchar *format, ...) -{ - va_list args; - gchar buf[BUFFSIZE + TIME_LEN]; - time_t t; - - time(&t); - strftime(buf, TIME_LEN + 1, "[%H:%M:%S] ", localtime(&t)); - - va_start(args, format); - g_vsnprintf(buf + TIME_LEN, BUFFSIZE, format, args); - va_end(args); - - g_warning("%s", buf); - log_error_ui_func(buf + TIME_LEN); - if (log_fp) { - fwrite(buf, TIME_LEN, 1, log_fp); - fputs("*** error: ", log_fp); - fputs(buf + TIME_LEN, log_fp); - fflush(log_fp); - } -} diff --git a/src/utils.h b/src/utils.h deleted file mode 100644 index fbda26a3..00000000 --- a/src/utils.h +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __UTILS_H__ -#define __UTILS_H__ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <glib.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <dirent.h> -#include <time.h> -#if HAVE_ALLOCA_H -# include <alloca.h> -#endif -#if HAVE_WCHAR_H -# include <wchar.h> -#endif - -/* Wrappers for C library function that take pathname arguments. */ -#if GLIB_CHECK_VERSION(2, 6, 0) -# include <glib/gstdio.h> -#else - -#define g_open open -#define g_rename rename -#define g_mkdir mkdir -#define g_stat stat -#define g_lstat lstat -#define g_unlink unlink -#define g_remove remove -#define g_rmdir rmdir -#define g_fopen fopen -#define g_freopen freopen - -#endif /* GLIB_CHECK_VERSION */ - -#if !GLIB_CHECK_VERSION(2, 7, 0) - -#ifdef G_OS_UNIX -#define g_chdir chdir -#define g_chmod chmod -#else -gint g_chdir (const gchar *path); -gint g_chmod (const gchar *path, - gint mode); -#endif /* G_OS_UNIX */ - -#endif /* !GLIB_CHECK_VERSION */ - -/* The AC_CHECK_SIZEOF() in configure fails for some machines. - * we provide some fallback values here */ -#if !SIZEOF_UNSIGNED_SHORT - #undef SIZEOF_UNSIGNED_SHORT - #define SIZEOF_UNSIGNED_SHORT 2 -#endif -#if !SIZEOF_UNSIGNED_INT - #undef SIZEOF_UNSIGNED_INT - #define SIZEOF_UNSIGNED_INT 4 -#endif -#if !SIZEOF_UNSIGNED_LONG - #undef SIZEOF_UNSIGNED_LONG - #define SIZEOF_UNSIGNED_LONG 4 -#endif - -#ifndef HAVE_U32_TYPEDEF - #undef u32 /* maybe there is a macro with this name */ - typedef guint32 u32; - #define HAVE_U32_TYPEDEF -#endif - -#ifndef BIG_ENDIAN_HOST - #if (G_BYTE_ORDER == G_BIG_ENDIAN) - #define BIG_ENDIAN_HOST 1 - #endif -#endif - -#define CHDIR_RETURN_IF_FAIL(dir) \ -{ \ - if (change_dir(dir) < 0) return; \ -} - -#define CHDIR_RETURN_VAL_IF_FAIL(dir, val) \ -{ \ - if (change_dir(dir) < 0) return val; \ -} - -#define Xalloca(ptr, size, iffail) \ -{ \ - if ((ptr = alloca(size)) == NULL) { \ - g_warning("can't allocate memory\n"); \ - iffail; \ - } \ -} - -#define Xstrdup_a(ptr, str, iffail) \ -{ \ - gchar *__tmp; \ - \ - if ((__tmp = alloca(strlen(str) + 1)) == NULL) { \ - g_warning("can't allocate memory\n"); \ - iffail; \ - } else \ - strcpy(__tmp, str); \ - \ - ptr = __tmp; \ -} - -#define Xstrndup_a(ptr, str, len, iffail) \ -{ \ - gchar *__tmp; \ - \ - if ((__tmp = alloca(len + 1)) == NULL) { \ - g_warning("can't allocate memory\n"); \ - iffail; \ - } else { \ - strncpy(__tmp, str, len); \ - __tmp[len] = '\0'; \ - } \ - \ - ptr = __tmp; \ -} - -#define Xstrcat_a(ptr, str1, str2, iffail) \ -{ \ - gchar *__tmp; \ - gint len1, len2; \ - \ - len1 = strlen(str1); \ - len2 = strlen(str2); \ - if ((__tmp = alloca(len1 + len2 + 1)) == NULL) { \ - g_warning("can't allocate memory\n"); \ - iffail; \ - } else { \ - memcpy(__tmp, str1, len1); \ - memcpy(__tmp + len1, str2, len2 + 1); \ - } \ - \ - ptr = __tmp; \ -} - -#define AUTORELEASE_STR(str, iffail) \ -{ \ - gchar *__str; \ - Xstrdup_a(__str, str, iffail); \ - g_free(str); \ - str = __str; \ -} - -#define FILE_OP_ERROR(file, func) \ -{ \ - fprintf(stderr, "%s: ", file); \ - fflush(stderr); \ - perror(func); \ -} - -typedef void (*LogFunc) (const gchar *str); - -/* for macro expansion */ -#define Str(x) #x -#define Xstr(x) Str(x) - -void list_free_strings (GList *list); -void slist_free_strings (GSList *list); - -void hash_free_strings (GHashTable *table); -void hash_free_value_mem (GHashTable *table); - -gint str_case_equal (gconstpointer v, - gconstpointer v2); -guint str_case_hash (gconstpointer key); - -void ptr_array_free_strings (GPtrArray *array); - -typedef gboolean (*StrFindFunc) (const gchar *haystack, - const gchar *needle); - -gboolean str_find (const gchar *haystack, - const gchar *needle); -gboolean str_case_find (const gchar *haystack, - const gchar *needle); -gboolean str_find_equal (const gchar *haystack, - const gchar *needle); -gboolean str_case_find_equal (const gchar *haystack, - const gchar *needle); - -/* number-string conversion */ -gint to_number (const gchar *nstr); -gchar *itos_buf (gchar *nstr, - gint n); -gchar *itos (gint n); -gchar *to_human_readable (off_t size); - -/* alternative string functions */ -gint strcmp2 (const gchar *s1, - const gchar *s2); -gint path_cmp (const gchar *s1, - const gchar *s2); -gchar *strretchomp (gchar *str); -gchar *strtailchomp (gchar *str, - gchar tail_char); -gchar *strcrchomp (gchar *str); -gchar *strcasestr (const gchar *haystack, - const gchar *needle); -gpointer my_memmem (gconstpointer haystack, - size_t haystacklen, - gconstpointer needle, - size_t needlelen); -gchar *strncpy2 (gchar *dest, - const gchar *src, - size_t n); - -/* wide-character functions */ -#if !HAVE_ISWALNUM -int iswalnum (wint_t wc); -#endif -#if !HAVE_ISWSPACE -int iswspace (wint_t wc); -#endif -#if !HAVE_TOWLOWER -wint_t towlower (wint_t wc); -#endif - -#if !HAVE_WCSLEN -size_t wcslen (const wchar_t *s); -#endif -#if !HAVE_WCSCPY -wchar_t *wcscpy (wchar_t *dest, - const wchar_t *src); -#endif -#if !HAVE_WCSNCPY -wchar_t *wcsncpy (wchar_t *dest, - const wchar_t *src, - size_t n); -#endif - -wchar_t *wcsdup (const wchar_t *s); -wchar_t *wcsndup (const wchar_t *s, - size_t n); -wchar_t *strdup_mbstowcs (const gchar *s); -gchar *strdup_wcstombs (const wchar_t *s); -gint wcsncasecmp (const wchar_t *s1, - const wchar_t *s2, - size_t n); -wchar_t *wcscasestr (const wchar_t *haystack, - const wchar_t *needle); -gint get_mbs_len (const gchar *s); - -gboolean is_next_nonascii (const gchar *s); -gint get_next_word_len (const gchar *s); - -/* functions for string parsing */ -gint subject_compare (const gchar *s1, - const gchar *s2); -gint subject_compare_for_sort (const gchar *s1, - const gchar *s2); -void trim_subject_for_compare (gchar *str); -void trim_subject_for_sort (gchar *str); -void trim_subject (gchar *str); -void eliminate_parenthesis (gchar *str, - gchar op, - gchar cl); -void extract_parenthesis (gchar *str, - gchar op, - gchar cl); - -void extract_parenthesis_with_skip_quote (gchar *str, - gchar quote_chr, - gchar op, - gchar cl); - -void eliminate_quote (gchar *str, - gchar quote_chr); -void extract_quote (gchar *str, - gchar quote_chr); -void eliminate_address_comment (gchar *str); -gchar *strchr_with_skip_quote (const gchar *str, - gint quote_chr, - gint c); -gchar *strrchr_with_skip_quote (const gchar *str, - gint quote_chr, - gint c); -void extract_address (gchar *str); -void extract_list_id_str (gchar *str); - -GSList *address_list_append (GSList *addr_list, - const gchar *str); -GSList *references_list_prepend (GSList *msgid_list, - const gchar *str); -GSList *references_list_append (GSList *msgid_list, - const gchar *str); -GSList *newsgroup_list_append (GSList *group_list, - const gchar *str); - -GList *add_history (GList *list, - const gchar *str); - -void remove_return (gchar *str); -void remove_space (gchar *str); -void unfold_line (gchar *str); -void subst_char (gchar *str, - gchar orig, - gchar subst); -void subst_chars (gchar *str, - gchar *orig, - gchar subst); -void subst_null (gchar *str, - gint len, - gchar subst); -void subst_for_filename (gchar *str); -gboolean is_header_line (const gchar *str); -gboolean is_ascii_str (const gchar *str); -gint get_quote_level (const gchar *str); -gint check_line_length (const gchar *str, - gint max_chars, - gint *line); - -gchar *strstr_with_skip_quote (const gchar *haystack, - const gchar *needle); -gchar *strchr_parenthesis_close (const gchar *str, - gchar op, - gchar cl); - -gchar **strsplit_parenthesis (const gchar *str, - gchar op, - gchar cl, - gint max_tokens); -gchar **strsplit_with_quote (const gchar *str, - const gchar *delim, - gint max_tokens); - -gchar *get_abbrev_newsgroup_name (const gchar *group, - gint len); -gchar *trim_string (const gchar *str, - gint len); -gchar *trim_string_before (const gchar *str, - gint len); - -GList *uri_list_extract_filenames (const gchar *uri_list); -gboolean is_uri_string (const gchar *str); -gchar *get_uri_path (const gchar *uri); -gint get_uri_len (const gchar *str); -void decode_uri (gchar *decoded_uri, - const gchar *encoded_uri); -gchar *encode_uri (const gchar *filename); -gint scan_mailto_url (const gchar *mailto, - gchar **to, - gchar **cc, - gchar **bcc, - gchar **subject, - gchar **body); - -/* return static strings */ -const gchar *get_home_dir (void); -const gchar *get_rc_dir (void); -const gchar *get_old_rc_dir (void); -const gchar *get_mail_base_dir (void); -const gchar *get_news_cache_dir (void); -const gchar *get_imap_cache_dir (void); -const gchar *get_mime_tmp_dir (void); -const gchar *get_template_dir (void); -const gchar *get_tmp_dir (void); -gchar *get_tmp_file (void); -const gchar *get_domain_name (void); - -/* file / directory handling */ -off_t get_file_size (const gchar *file); -off_t get_file_size_as_crlf (const gchar *file); -off_t get_left_file_size (FILE *fp); - -gboolean file_exist (const gchar *file, - gboolean allow_fifo); -gboolean is_dir_exist (const gchar *dir); -gboolean is_file_entry_exist (const gchar *file); -gboolean dirent_is_regular_file (struct dirent *d); -gboolean dirent_is_directory (struct dirent *d); - -#define is_file_exist(file) file_exist(file, FALSE) -#define is_file_or_fifo_exist(file) file_exist(file, TRUE) - -gint change_dir (const gchar *dir); -gint make_dir (const gchar *dir); -gint make_dir_hier (const gchar *dir); -gint remove_all_files (const gchar *dir); -gint remove_numbered_files (const gchar *dir, - guint first, - guint last); -gint remove_all_numbered_files (const gchar *dir); -gint remove_expired_files (const gchar *dir, - guint hours); -gint remove_dir_recursive (const gchar *dir); -gint rename_force (const gchar *oldpath, - const gchar *newpath); -gint copy_file (const gchar *src, - const gchar *dest, - gboolean keep_backup); -gint copy_dir (const gchar *src, - const gchar *dest); -gint move_file (const gchar *src, - const gchar *dest, - gboolean overwrite); -gint copy_file_part (FILE *fp, - off_t offset, - size_t length, - const gchar *dest); - -gchar *canonicalize_str (const gchar *str); -gint canonicalize_file (const gchar *src, - const gchar *dest); -gint canonicalize_file_replace (const gchar *file); -gint uncanonicalize_file (const gchar *src, - const gchar *dest); -gint uncanonicalize_file_replace(const gchar *file); - -gchar *normalize_newlines (const gchar *str); - -gchar *get_outgoing_rfc2822_str (FILE *fp); -gchar *generate_mime_boundary (const gchar *prefix); - -gint change_file_mode_rw (FILE *fp, - const gchar *file); -FILE *my_tmpfile (void); -FILE *str_open_as_stream (const gchar *str); -gint str_write_to_file (const gchar *str, - const gchar *file); -gchar *file_read_to_str (const gchar *file); -gchar *file_read_stream_to_str (FILE *fp); - -/* process execution */ -gint execute_async (gchar *const argv[]); -gint execute_sync (gchar *const argv[]); -gint execute_command_line (const gchar *cmdline, - gboolean async); -gchar *get_command_output (const gchar *cmdline); - -/* open URI with external browser */ -gint open_uri(const gchar *uri, const gchar *cmdline); - -/* time functions */ -time_t remote_tzoffset_sec (const gchar *zone); -time_t tzoffset_sec (time_t *now); -gchar *tzoffset (time_t *now); -void get_rfc822_date (gchar *buf, - gint len); - -size_t my_strftime (gchar *s, - size_t max, - const gchar *format, - const struct tm *tm); - -/* logging */ -void set_log_file (const gchar *filename); -void close_log_file (void); -void set_log_verbosity (gboolean verbose); -gboolean get_debug_mode (void); -void set_debug_mode (gboolean enable); - -void set_log_ui_func (LogFunc print_func, - LogFunc message_func, - LogFunc warning_func, - LogFunc error_func); - -void set_log_show_status_func (LogFunc status_func); - -void debug_print (const gchar *format, ...) G_GNUC_PRINTF(1, 2); -void log_print (const gchar *format, ...) G_GNUC_PRINTF(1, 2); -void log_message (const gchar *format, ...) G_GNUC_PRINTF(1, 2); -void log_warning (const gchar *format, ...) G_GNUC_PRINTF(1, 2); -void log_error (const gchar *format, ...) G_GNUC_PRINTF(1, 2); - -#endif /* __UTILS_H__ */ diff --git a/src/uuencode.c b/src/uuencode.c deleted file mode 100644 index e0b2e79a..00000000 --- a/src/uuencode.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999,2000 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <ctype.h> - -#define UUDECODE(c) (c=='`' ? 0 : c - ' ') -#define N64(i) (i & ~63) - -const char uudigit[64] = -{ - '`', '!', '"', '#', '$', '%', '&', '\'', - '(', ')', '*', '+', ',', '-', '.', '/', - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', ':', ';', '<', '=', '>', '?', - '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', '[', '\\', ']', '^', '_' -}; - -int touufrombits(unsigned char *out, const unsigned char *in, int inlen) -{ - int len; - - if (inlen > 45) return -1; - len = (inlen * 4 + 2) / 3 + 1; - *out++ = uudigit[inlen]; - - for (; inlen >= 3; inlen -= 3) { - *out++ = uudigit[in[0] >> 2]; - *out++ = uudigit[((in[0] << 4) & 0x30) | (in[1] >> 4)]; - *out++ = uudigit[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; - *out++ = uudigit[in[2] & 0x3f]; - in += 3; - } - - if (inlen > 0) { - *out++ = uudigit[(in[0] >> 2)]; - if (inlen == 1) { - *out++ = uudigit[((in[0] << 4) & 0x30)]; - } else { - *out++ = uudigit[(((in[0] << 4) & 0x30) | (in[1] >> 4))] ; - *out++ = uudigit[((in[1] << 2) & 0x3c)]; - } - } - *out = '\0'; - - return len; -} - -int fromuutobits(char *out, const char *in) -{ - int len, outlen, inlen; - register unsigned char digit1, digit2; - - outlen = UUDECODE(in[0]); - in += 1; - if(outlen < 0 || outlen > 45) - return -2; - if(outlen == 0) - return 0; - inlen = (outlen * 4 + 2) / 3; - len = 0; - - for( ; inlen>0; inlen-=4) { - digit1 = UUDECODE(in[0]); - if (N64(digit1)) return -1; - digit2 = UUDECODE(in[1]); - if (N64(digit2)) return -1; - out[len++] = (digit1 << 2) | (digit2 >> 4); - if (inlen > 2) { - digit1 = UUDECODE(in[2]); - if (N64(digit1)) return -1; - out[len++] = (digit2 << 4) | (digit1 >> 2); - if (inlen > 3) { - digit2 = UUDECODE(in[3]); - if (N64(digit2)) return -1; - out[len++] = (digit1 << 6) | digit2; - } - } - in += 4; - } - - return len == outlen ? len : -3; -} diff --git a/src/uuencode.h b/src/uuencode.h deleted file mode 100644 index 3658ebc6..00000000 --- a/src/uuencode.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999,2000 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -void touufrombits(unsigned char *, const unsigned char *, int); -int fromuutobits(char *, const char *); - -#define X_UUENCODE_END_LINE '`' -#define UUENCODE_END_LINE ' ' diff --git a/src/xml.c b/src/xml.c deleted file mode 100644 index e9c4adf8..00000000 --- a/src/xml.c +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <glib.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> - -#include "xml.h" -#include "main.h" -#include "utils.h" -#include "codeconv.h" - -#define SPARSE_MEMORY -/* if this is defined all attr.names and tag.names are stored - * in a hash table */ -#if defined(SPARSE_MEMORY) -#include "stringtable.h" - -static StringTable *xml_string_table; - -static void xml_string_table_create(void) -{ - if (xml_string_table == NULL) - xml_string_table = string_table_new(); -} -#define XML_STRING_ADD(str) \ - string_table_insert_string(xml_string_table, (str)) -#define XML_STRING_FREE(str) \ - string_table_free_string(xml_string_table, (str)) - -#define XML_STRING_TABLE_CREATE() \ - xml_string_table_create() - -#else /* !SPARSE_MEMORY */ - -#define XML_STRING_ADD(str) \ - g_strdup(str) -#define XML_STRING_FREE(str) \ - g_free(str) - -#define XML_STRING_TABLE_CREATE() - -#endif /* SPARSE_MEMORY */ - -static void xml_free_tag (XMLTag *tag); -static gint xml_get_parenthesis (XMLFile *file, - gchar *buf, - gint len); - -XMLFile *xml_open_file(const gchar *path) -{ - XMLFile *newfile; - - g_return_val_if_fail(path != NULL, NULL); - - XML_STRING_TABLE_CREATE(); - - newfile = g_new(XMLFile, 1); - - newfile->fp = g_fopen(path, "rb"); - if (!newfile->fp) { - g_free(newfile); - return NULL; - } - - newfile->buf = g_string_new(NULL); - newfile->bufp = newfile->buf->str; - - newfile->dtd = NULL; - newfile->encoding = NULL; - newfile->tag_stack = NULL; - newfile->level = 0; - newfile->is_empty_element = FALSE; - - return newfile; -} - -void xml_close_file(XMLFile *file) -{ - g_return_if_fail(file != NULL); - - if (file->fp) fclose(file->fp); - - g_string_free(file->buf, TRUE); - - g_free(file->dtd); - g_free(file->encoding); - - while (file->tag_stack != NULL) - xml_pop_tag(file); - - g_free(file); -} - -static GNode *xml_build_tree(XMLFile *file, GNode *parent, guint level) -{ - GNode *node = NULL; - XMLNode *xmlnode; - XMLTag *tag; - - while (xml_parse_next_tag(file) == 0) { - if (file->level < level) break; - if (file->level == level) { - g_warning("xml_build_tree(): Parse error\n"); - break; - } - - tag = xml_get_current_tag(file); - if (!tag) break; - xmlnode = xml_node_new(xml_copy_tag(tag), NULL); - xmlnode->element = xml_get_element(file); - if (!parent) - node = g_node_new(xmlnode); - else - node = g_node_append_data(parent, xmlnode); - - xml_build_tree(file, node, file->level); - if (file->level == 0) break; - } - - return node; -} - -GNode *xml_parse_file(const gchar *path) -{ - XMLFile *file; - GNode *node; - - file = xml_open_file(path); - g_return_val_if_fail(file != NULL, NULL); - - xml_get_dtd(file); - - node = xml_build_tree(file, NULL, file->level); - - xml_close_file(file); - -#if defined(SPARSE_MEMORY) - if (get_debug_mode()) - string_table_get_stats(xml_string_table); -#endif - - return node; -} - -gint xml_get_dtd(XMLFile *file) -{ - gchar buf[XMLBUFSIZE]; - gchar *bufp = buf; - - if (xml_get_parenthesis(file, buf, sizeof(buf)) < 0) return -1; - - if ((*bufp++ == '?') && - (bufp = strcasestr(bufp, "xml")) && - (bufp = strcasestr(bufp + 3, "version")) && - (bufp = strchr(bufp + 7, '?'))) { - file->dtd = g_strdup(buf); - if ((bufp = strcasestr(buf, "encoding=\""))) { - bufp += 9; - extract_quote(bufp, '"'); - file->encoding = g_strdup(bufp); - } else - file->encoding = g_strdup(CS_INTERNAL); - } else { - g_warning("Can't get xml dtd\n"); - return -1; - } - - return 0; -} - -gint xml_parse_next_tag(XMLFile *file) -{ - gchar buf[XMLBUFSIZE]; - gchar *bufp = buf; - gchar *tag_str; - XMLTag *tag; - gint len; - - if (file->is_empty_element == TRUE) { - file->is_empty_element = FALSE; - xml_pop_tag(file); - return 0; - } - - if (xml_get_parenthesis(file, buf, sizeof(buf)) < 0) { - g_warning("xml_parse_next_tag(): Can't parse next tag\n"); - return -1; - } - - /* end-tag */ - if (buf[0] == '/') { - if (strcmp(xml_get_current_tag(file)->tag, buf + 1) != 0) { - g_warning("xml_parse_next_tag(): Tag name mismatch: %s\n", buf); - return -1; - } - xml_pop_tag(file); - return 0; - } - - tag = xml_tag_new(NULL); - xml_push_tag(file, tag); - - len = strlen(buf); - if (len > 0 && buf[len - 1] == '/') { - file->is_empty_element = TRUE; - buf[len - 1] = '\0'; - g_strchomp(buf); - } - if (strlen(buf) == 0) { - g_warning("xml_parse_next_tag(): Tag name is empty\n"); - return -1; - } - - while (*bufp != '\0' && !g_ascii_isspace(*bufp)) bufp++; - if (*bufp == '\0') { - tag_str = conv_codeset_strdup(buf, file->encoding, CS_INTERNAL); - if (tag_str) { - tag->tag = XML_STRING_ADD(tag_str); - g_free(tag_str); - } else - tag->tag = XML_STRING_ADD(buf); - return 0; - } else { - *bufp++ = '\0'; - tag_str = conv_codeset_strdup(buf, file->encoding, CS_INTERNAL); - if (tag_str) { - tag->tag = XML_STRING_ADD(tag_str); - g_free(tag_str); - } else - tag->tag = XML_STRING_ADD(buf); - } - - /* parse attributes ( name=value ) */ - while (*bufp) { - XMLAttr *attr; - gchar *attr_name; - gchar *attr_value; - gchar *utf8_attr_name; - gchar *utf8_attr_value; - gchar *p; - gchar quote; - - while (g_ascii_isspace(*bufp)) bufp++; - attr_name = bufp; - if ((p = strchr(attr_name, '=')) == NULL) { - g_warning("xml_parse_next_tag(): Syntax error in tag\n"); - return -1; - } - bufp = p; - *bufp++ = '\0'; - while (g_ascii_isspace(*bufp)) bufp++; - - if (*bufp != '"' && *bufp != '\'') { - g_warning("xml_parse_next_tag(): Syntax error in tag\n"); - return -1; - } - quote = *bufp; - bufp++; - attr_value = bufp; - if ((p = strchr(attr_value, quote)) == NULL) { - g_warning("xml_parse_next_tag(): Syntax error in tag\n"); - return -1; - } - bufp = p; - *bufp++ = '\0'; - - g_strchomp(attr_name); - xml_unescape_str(attr_value); - utf8_attr_name = conv_codeset_strdup - (attr_name, file->encoding, CS_INTERNAL); - utf8_attr_value = conv_codeset_strdup - (attr_value, file->encoding, CS_INTERNAL); - if (!utf8_attr_name) - utf8_attr_name = g_strdup(attr_name); - if (!utf8_attr_value) - utf8_attr_value = g_strdup(attr_value); - - attr = xml_attr_new(utf8_attr_name, utf8_attr_value); - xml_tag_add_attr(tag, attr); - - g_free(utf8_attr_value); - g_free(utf8_attr_name); - } - - return 0; -} - -void xml_push_tag(XMLFile *file, XMLTag *tag) -{ - g_return_if_fail(tag != NULL); - - file->tag_stack = g_list_prepend(file->tag_stack, tag); - file->level++; -} - -void xml_pop_tag(XMLFile *file) -{ - XMLTag *tag; - - if (!file->tag_stack) return; - - tag = (XMLTag *)file->tag_stack->data; - - xml_free_tag(tag); - file->tag_stack = g_list_remove(file->tag_stack, tag); - file->level--; -} - -XMLTag *xml_get_current_tag(XMLFile *file) -{ - if (file->tag_stack) - return (XMLTag *)file->tag_stack->data; - else - return NULL; -} - -GList *xml_get_current_tag_attr(XMLFile *file) -{ - XMLTag *tag; - - tag = xml_get_current_tag(file); - if (!tag) return NULL; - - return tag->attr; -} - -gchar *xml_get_element(XMLFile *file) -{ - gchar *str; - gchar *new_str; - gchar *end; - - while ((end = strchr(file->bufp, '<')) == NULL) - if (xml_read_line(file) < 0) return NULL; - - if (end == file->bufp) - return NULL; - - str = g_strndup(file->bufp, end - file->bufp); - /* this is not XML1.0 strict */ - g_strstrip(str); - xml_unescape_str(str); - - file->bufp = end; - xml_truncate_buf(file); - - if (str[0] == '\0') { - g_free(str); - return NULL; - } - - new_str = conv_codeset_strdup(str, file->encoding, CS_INTERNAL); - if (!new_str) - new_str = g_strdup(str); - g_free(str); - - return new_str; -} - -gint xml_read_line(XMLFile *file) -{ - gchar buf[XMLBUFSIZE]; - gint index; - - if (fgets(buf, sizeof(buf), file->fp) == NULL) - return -1; - - index = file->bufp - file->buf->str; - - g_string_append(file->buf, buf); - - file->bufp = file->buf->str + index; - - return 0; -} - -void xml_truncate_buf(XMLFile *file) -{ - gint len; - - len = file->bufp - file->buf->str; - if (len > 0) { - g_string_erase(file->buf, 0, len); - file->bufp = file->buf->str; - } -} - -gboolean xml_compare_tag(XMLFile *file, const gchar *name) -{ - XMLTag *tag; - - tag = xml_get_current_tag(file); - - if (tag && strcmp(tag->tag, name) == 0) - return TRUE; - else - return FALSE; -} - -XMLNode *xml_node_new(XMLTag *tag, const gchar *text) -{ - XMLNode *node; - - node = g_new(XMLNode, 1); - node->tag = tag; - node->element = g_strdup(text); - - return node; -} - -XMLTag *xml_tag_new(const gchar *tag) -{ - XMLTag *new_tag; - - new_tag = g_new(XMLTag, 1); - if (tag) - new_tag->tag = XML_STRING_ADD(tag); - else - new_tag->tag = NULL; - new_tag->attr = NULL; - - return new_tag; -} - -XMLAttr *xml_attr_new(const gchar *name, const gchar *value) -{ - XMLAttr *new_attr; - - new_attr = g_new(XMLAttr, 1); - new_attr->name = XML_STRING_ADD(name); - new_attr->value = g_strdup(value); - - return new_attr; -} - -void xml_tag_add_attr(XMLTag *tag, XMLAttr *attr) -{ - tag->attr = g_list_append(tag->attr, attr); -} - -XMLTag *xml_copy_tag(XMLTag *tag) -{ - XMLTag *new_tag; - XMLAttr *attr; - GList *list; - - new_tag = xml_tag_new(tag->tag); - for (list = tag->attr; list != NULL; list = list->next) { - attr = xml_copy_attr((XMLAttr *)list->data); - xml_tag_add_attr(new_tag, attr); - } - - return new_tag; -} - -XMLAttr *xml_copy_attr(XMLAttr *attr) -{ - return xml_attr_new(attr->name, attr->value); -} - -gint xml_unescape_str(gchar *str) -{ - gchar *start; - gchar *end; - gchar *p = str; - gchar *esc_str; - gchar ch; - gint len; - - while ((start = strchr(p, '&')) != NULL) { - if ((end = strchr(start + 1, ';')) == NULL) { - g_warning("Unescaped `&' appeared\n"); - p = start + 1; - continue; - } - len = end - start + 1; - if (len < 3) { - p = end + 1; - continue; - } - - Xstrndup_a(esc_str, start, len, return -1); - if (!strcmp(esc_str, "<")) - ch = '<'; - else if (!strcmp(esc_str, ">")) - ch = '>'; - else if (!strcmp(esc_str, "&")) - ch = '&'; - else if (!strcmp(esc_str, "'")) - ch = '\''; - else if (!strcmp(esc_str, """)) - ch = '\"'; - else { - p = end + 1; - continue; - } - - *start = ch; - memmove(start + 1, end + 1, strlen(end + 1) + 1); - p = start + 1; - } - - return 0; -} - -gint xml_file_put_escape_str(FILE *fp, const gchar *str) -{ - const gchar *p; - - g_return_val_if_fail(fp != NULL, -1); - - if (!str) return 0; - - for (p = str; *p != '\0'; p++) { - switch (*p) { - case '<': - fputs("<", fp); - break; - case '>': - fputs(">", fp); - break; - case '&': - fputs("&", fp); - break; - case '\'': - fputs("'", fp); - break; - case '\"': - fputs(""", fp); - break; - default: - fputc(*p, fp); - } - } - - return 0; -} - -gint xml_file_put_xml_decl(FILE *fp) -{ - g_return_val_if_fail(fp != NULL, -1); - - fprintf(fp, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", CS_INTERNAL); - return 0; -} - -gint xml_file_put_node(FILE *fp, XMLNode *node) -{ - GList *cur; - - g_return_val_if_fail(fp != NULL, -1); - g_return_val_if_fail(node != NULL, -1); - - fprintf(fp, "<%s", node->tag->tag); - - for (cur = node->tag->attr; cur != NULL; cur = cur->next) { - XMLAttr *attr = (XMLAttr *)cur->data; - fprintf(fp, " %s=\"", attr->name); - xml_file_put_escape_str(fp, attr->value); - fputs("\"", fp); - } - - if (node->element) { - fputs(">", fp); - xml_file_put_escape_str(fp, node->element); - fprintf(fp, "</%s>\n", node->tag->tag); - } else { - fputs(" />\n", fp); - } - - return 0; -} - -void xml_free_node(XMLNode *node) -{ - if (!node) return; - - xml_free_tag(node->tag); - g_free(node->element); - g_free(node); -} - -static gboolean xml_free_func(GNode *node, gpointer data) -{ - XMLNode *xmlnode = node->data; - - xml_free_node(xmlnode); - return FALSE; -} - -void xml_free_tree(GNode *node) -{ - g_return_if_fail(node != NULL); - - g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, xml_free_func, - NULL); - - g_node_destroy(node); -} - -static void xml_free_tag(XMLTag *tag) -{ - if (!tag) return; - - XML_STRING_FREE(tag->tag); - while (tag->attr != NULL) { - XMLAttr *attr = (XMLAttr *)tag->attr->data; - XML_STRING_FREE(attr->name); - g_free(attr->value); - g_free(attr); - tag->attr = g_list_remove(tag->attr, tag->attr->data); - } - g_free(tag); -} - -static gint xml_get_parenthesis(XMLFile *file, gchar *buf, gint len) -{ - gchar *start; - gchar *end; - - buf[0] = '\0'; - - while ((start = strchr(file->bufp, '<')) == NULL) - if (xml_read_line(file) < 0) return -1; - - start++; - file->bufp = start; - - while ((end = strchr(file->bufp, '>')) == NULL) - if (xml_read_line(file) < 0) return -1; - - strncpy2(buf, file->bufp, MIN(end - file->bufp + 1, len)); - g_strstrip(buf); - file->bufp = end + 1; - xml_truncate_buf(file); - - return 0; -} diff --git a/src/xml.h b/src/xml.h deleted file mode 100644 index b41449a4..00000000 --- a/src/xml.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2004 Hiroyuki Yamamoto - * - * 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 Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __XML_H__ -#define __XML_H__ - -#include <glib.h> -#include <stdio.h> - -#define XMLBUFSIZE 8192 - -typedef struct _XMLAttr XMLAttr; -typedef struct _XMLTag XMLTag; -typedef struct _XMLNode XMLNode; -typedef struct _XMLFile XMLFile; - -struct _XMLAttr -{ - gchar *name; - gchar *value; -}; - -struct _XMLTag -{ - gchar *tag; - GList *attr; -}; - -struct _XMLNode -{ - XMLTag *tag; - gchar *element; -}; - -struct _XMLFile -{ - FILE *fp; - - GString *buf; - gchar *bufp; - - gchar *dtd; - gchar *encoding; - - GList *tag_stack; - guint level; - - gboolean is_empty_element; -}; - -XMLFile *xml_open_file (const gchar *path); -void xml_close_file (XMLFile *file); -GNode *xml_parse_file (const gchar *path); - -gint xml_get_dtd (XMLFile *file); -gint xml_parse_next_tag (XMLFile *file); -void xml_push_tag (XMLFile *file, - XMLTag *tag); -void xml_pop_tag (XMLFile *file); - -XMLTag *xml_get_current_tag (XMLFile *file); -GList *xml_get_current_tag_attr(XMLFile *file); -gchar *xml_get_element (XMLFile *file); - -gint xml_read_line (XMLFile *file); -void xml_truncate_buf (XMLFile *file); -gboolean xml_compare_tag (XMLFile *file, - const gchar *name); - -XMLNode *xml_node_new (XMLTag *tag, - const gchar *text); -XMLTag *xml_tag_new (const gchar *tag); -XMLAttr *xml_attr_new (const gchar *name, - const gchar *value); -void xml_tag_add_attr (XMLTag *tag, - XMLAttr *attr); - -XMLTag *xml_copy_tag (XMLTag *tag); -XMLAttr *xml_copy_attr (XMLAttr *attr); - -gint xml_unescape_str (gchar *str); -gint xml_file_put_escape_str (FILE *fp, - const gchar *str); - -gint xml_file_put_xml_decl (FILE *fp); -gint xml_file_put_node (FILE *fp, - XMLNode *node); - -void xml_free_node (XMLNode *node); -void xml_free_tree (GNode *node); - -#endif /* __XML_H__ */ |