Index: libedataserverui/e-passwords.c
===================================================================
--- libedataserverui/e-passwords.c	(revision 8036)
+++ libedataserverui/e-passwords.c	(working copy)
@@ -110,9 +110,34 @@ static EDList request_list = E_DLIST_INI
 static int idle_id;
 static int ep_online_state = TRUE;
 
-static char *decode_base64 (char *base64);
-static int base64_encode_close(unsigned char *in, int inlen, gboolean break_lines, unsigned char *out, int *state, int *save);
-static int base64_encode_step(unsigned char *in, int len, gboolean break_lines, unsigned char *out, int *state, int *save);
+static gchar *
+ep_password_encode (const gchar *password)
+{
+	/* XXX The previous Base64 encoding function did not encode the
+	 * password's trailing nul byte.  This makes decoding the Base64
+	 * string into a nul-terminated password more difficult, but we
+	 * continue to do it this way for backward-compatibility. */
+
+	gsize length = strlen (password);
+	return g_base64_encode ((const guchar *) password, length);
+}
+
+static gchar *
+ep_password_decode (const gchar *encoded_password)
+{
+	/* XXX The previous Base64 encoding function did not encode the
+	 * password's trailing nul byte, so we have to append a nul byte
+	 * to the decoded data to make it a nul-terminated string. */
+
+	gchar *password;
+	gsize length;
+
+	password = (gchar *) g_base64_decode (encoded_password, &length);
+	password = g_realloc (password, length + 1);
+	password[length] = '\0';
+
+	return password;
+}
 
 static gboolean
 ep_idle_dispatch(void *data)
@@ -411,16 +436,11 @@ ep_remember_password_file(EPassMsg *msg)
 {
 	gpointer okey, value;
 	char *path, *pass64;
-	int len, state, save;
 
 	if (g_hash_table_lookup_extended (passwords, msg->key, &okey, &value)) {
 		/* add it to the on-disk cache of passwords */
 		path = password_path (msg->component, okey);
-
-		len = strlen (value);
-		pass64 = g_malloc0 ((len + 2) * 4 / 3 + 1);
-		state = save = 0;
-		base64_encode_close (value, len, FALSE, (guchar *)pass64, &state, &save);
+		pass64 = ep_password_encode (value);
 
 		gnome_config_private_set_string (path, pass64);
 		g_free (path);
@@ -651,7 +671,7 @@ ep_get_password_file (EPassMsg *msg)
 		encoded = gnome_config_private_get_string_with_default (path, NULL);
 		g_free (path);
 		if (encoded) {
-			msg->password = decode_base64 (encoded);
+			msg->password = ep_password_decode (encoded);
 			g_free (encoded);
 		}
 	}
@@ -1126,212 +1146,3 @@ e_passwords_ask_password (const char *ti
 	
 	return passwd;
 }
-
-
-
-static char *base64_alphabet =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-static unsigned char camel_mime_base64_rank[256] = {
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
-	 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255,  0,255,255,
-	255,  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,255,255,255,255,255,
-	255, 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,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-	255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-};
-
-/* call this when finished encoding everything, to
-   flush off the last little bit */
-static int
-base64_encode_close(unsigned char *in, int inlen, gboolean break_lines, unsigned char *out, int *state, int *save)
-{
-	int c1, c2;
-	unsigned char *outptr = out;
-
-	if (inlen>0)
-		outptr += base64_encode_step(in, inlen, break_lines, outptr, state, save);
-
-	c1 = ((unsigned char *)save)[1];
-	c2 = ((unsigned char *)save)[2];
-	
-	switch (((char *)save)[0]) {
-	case 2:
-		outptr[2] = base64_alphabet[ ( (c2 &0x0f) << 2 ) ];
-		g_assert(outptr[2] != 0);
-		goto skip;
-	case 1:
-		outptr[2] = '=';
-	skip:
-		outptr[0] = base64_alphabet[ c1 >> 2 ];
-		outptr[1] = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 )];
-		outptr[3] = '=';
-		outptr += 4;
-		break;
-	}
-	if (break_lines)
-		*outptr++ = '\n';
-
-	*save = 0;
-	*state = 0;
-
-	return outptr-out;
-}
-
-/*
-  performs an 'encode step', only encodes blocks of 3 characters to the
-  output at a time, saves left-over state in state and save (initialise to
-  0 on first invocation).
-*/
-static int
-base64_encode_step(unsigned char *in, int len, gboolean break_lines, unsigned char *out, int *state, int *save)
-{
-	register unsigned char *inptr, *outptr;
-
-	if (len<=0)
-		return 0;
-
-	inptr = in;
-	outptr = out;
-
-	if (len + ((char *)save)[0] > 2) {
-		unsigned char *inend = in+len-2;
-		register int c1, c2, c3;
-		register int already;
-
-		already = *state;
-
-		switch (((char *)save)[0]) {
-		case 1:	c1 = ((unsigned char *)save)[1]; goto skip1;
-		case 2:	c1 = ((unsigned char *)save)[1];
-			c2 = ((unsigned char *)save)[2]; goto skip2;
-		}
-		
-		/* yes, we jump into the loop, no i'm not going to change it, it's beautiful! */
-		while (inptr < inend) {
-			c1 = *inptr++;
-		skip1:
-			c2 = *inptr++;
-		skip2:
-			c3 = *inptr++;
-			*outptr++ = base64_alphabet[ c1 >> 2 ];
-			*outptr++ = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 ) ];
-			*outptr++ = base64_alphabet[ ( (c2 &0x0f) << 2 ) | (c3 >> 6) ];
-			*outptr++ = base64_alphabet[ c3 & 0x3f ];
-			/* this is a bit ugly ... */
-			if (break_lines && (++already)>=19) {
-				*outptr++='\n';
-				already = 0;
-			}
-		}
-
-		((char *)save)[0] = 0;
-		len = 2-(inptr-inend);
-		*state = already;
-	}
-
-	if (len>0) {
-		register char *saveout;
-
-		/* points to the slot for the next char to save */
-		saveout = & (((char *)save)[1]) + ((char *)save)[0];
-
-		/* len can only be 0 1 or 2 */
-		switch(len) {
-		case 2:	*saveout++ = *inptr++;
-		case 1:	*saveout++ = *inptr++;
-		}
-		((char *)save)[0]+=len;
-	}
-
-	return outptr-out;
-}
-
-
-/**
- * base64_decode_step: decode a chunk of base64 encoded data
- * @in: input stream
- * @len: max length of data to decode
- * @out: output stream
- * @state: holds the number of bits that are stored in @save
- * @save: leftover bits that have not yet been decoded
- *
- * Decodes a chunk of base64 encoded data
- **/
-static int
-base64_decode_step(unsigned char *in, int len, unsigned char *out, int *state, unsigned int *save)
-{
-	register unsigned char *inptr, *outptr;
-	unsigned char *inend, c;
-	register unsigned int v;
-	int i;
-
-	inend = in+len;
-	outptr = out;
-
-	/* convert 4 base64 bytes to 3 normal bytes */
-	v=*save;
-	i=*state;
-	inptr = in;
-	while (inptr<inend) {
-		c = camel_mime_base64_rank[*inptr++];
-		if (c != 0xff) {
-			v = (v<<6) | c;
-			i++;
-			if (i==4) {
-				*outptr++ = v>>16;
-				*outptr++ = v>>8;
-				*outptr++ = v;
-				i=0;
-			}
-		}
-	}
-
-	*save = v;
-	*state = i;
-
-	/* quick scan back for '=' on the end somewhere */
-	/* fortunately we can drop 1 output char for each trailing = (upto 2) */
-	i=2;
-	while (inptr>in && i) {
-		inptr--;
-		if (camel_mime_base64_rank[*inptr] != 0xff) {
-			if (*inptr == '=')
-				outptr--;
-			i--;
-		}
-	}
-
-	/* if i!= 0 then there is a truncation error! */
-	return outptr-out;
-}
-
-static char *
-decode_base64 (char *base64)
-{
-	guchar *plain;
-	char *pad = "==";
-	int len, out, state;
-	unsigned int save;
-	
-	len = strlen (base64);
-	plain = g_malloc0 (len);
-	state = save = 0;
-	out = base64_decode_step ((guchar *)base64, len, plain, &state, &save);
-	if (len % 4) {
-		base64_decode_step ((guchar *)pad, 4 - len % 4, plain + out,
-				    &state, &save);
-	}
-	
-	return (char *)plain;
-}
