From f36577b27b6f352f140cf1f25755d39661bd4072 Mon Sep 17 00:00:00 2001 From: hiro Date: Wed, 31 Aug 2005 06:10:31 +0000 Subject: made some core modules library (libsylph). git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@528 ee746299-78ed-0310-b773-934348b2243d --- libsylph/quoted-printable.c | 232 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 libsylph/quoted-printable.c (limited to 'libsylph/quoted-printable.c') diff --git a/libsylph/quoted-printable.c b/libsylph/quoted-printable.c new file mode 100644 index 00000000..cea0b704 --- /dev/null +++ b/libsylph/quoted-printable.c @@ -0,0 +1,232 @@ +/* + * 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 +#include + +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; +} -- cgit v1.2.3