/*
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail team
+ * Copyright (C) 1999-2009 Hiroyuki Yamamoto and the Claws Mail team
*
* 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
*/
#include <glib.h>
static const gchar base64char[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static const gchar base64val[128] = {
+static const signed char 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,
}
gint base64_decoder_decode(Base64Decoder *decoder,
- const gchar *in, guchar *out)
+ const gchar *in, guchar *out, gint inlen)
{
+ const gchar *in_end = in + inlen;
gint len, total_len = 0;
+ gboolean in_more = inlen > 0;
+ gboolean got_eq = FALSE;
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);
+ cm_return_val_if_fail(decoder != NULL, -1);
+ cm_return_val_if_fail(in != NULL, -1);
+ cm_return_val_if_fail(out != NULL, -1);
+ /* Start with previous saved tail */
buf_len = decoder->buf_len;
memcpy(buf, decoder->buf, sizeof(buf));
- for (;;) {
- while (buf_len < 4) {
+ while (in_more) {
+ while (buf_len < 4 && in_more) {
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;
+ got_eq = (c == '=');
+ if (got_eq || BASE64VAL(c) >= 0)
+ buf[buf_len++] = c;
+ in_more = (in < in_end) && !(got_eq && (buf_len == 4));
}
- 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;
+ if (buf_len == 4) {
+ len = base64_decode(out, buf, 4);
+ out += len;
+ total_len += len;
+ buf_len = 0;
}
}
+ if (buf_len < 4) {
+ /* Save tail for next iteration call. It wll be ignored if ends here. */
+ decoder->buf_len = buf_len;
+ memcpy(decoder->buf, buf, buf_len);
+ }
+ return total_len;
}