Index: /pjproject/trunk/pjlib-util/src/pjlib-util-test/encryption.c
===================================================================
--- /pjproject/trunk/pjlib-util/src/pjlib-util-test/encryption.c	(revision 3355)
+++ /pjproject/trunk/pjlib-util/src/pjlib-util-test/encryption.c	(revision 3356)
@@ -495,4 +495,10 @@
 }
 
+enum
+{
+    ENCODE = 1,
+    DECODE = 2,
+    ENCODE_DECODE = 3
+};
 
 /*
@@ -503,46 +509,68 @@
     const char *base256;
     const char *base64;
+    unsigned flag;
 } base64_test_vec[] = 
 {
     {
 	"",
-	""
+	"",
+	ENCODE_DECODE
     },
     {
 	"f",
-	"Zg=="
+	"Zg==",
+	ENCODE_DECODE
     },
     {
 	"fo",
-	"Zm8="
+	"Zm8=",
+	ENCODE_DECODE
     },
     {
 	"foo",
-	"Zm9v"
+	"Zm9v",
+	ENCODE_DECODE
     },
     {
 	"foob",
-	"Zm9vYg=="
+	"Zm9vYg==",
+	ENCODE_DECODE
     },
     {
 	"fooba",
 	"Zm9vYmE=",
+	ENCODE_DECODE
     },
     {
 	"foobar",
-	"Zm9vYmFy"
+	"Zm9vYmFy",
+	ENCODE_DECODE
     },
     {
 	"\x14\xfb\x9c\x03\xd9\x7e",
-	"FPucA9l+"
+	"FPucA9l+",
+	ENCODE_DECODE
     },
     {
 	"\x14\xfb\x9c\x03\xd9",
-	"FPucA9k="
+	"FPucA9k=",
+	ENCODE_DECODE
     },
     {
 	"\x14\xfb\x9c\x03",
-	"FPucAw=="
-    }
+	"FPucAw==",
+	ENCODE_DECODE
+    },
+    /* with whitespaces */
+    {
+	"foobar",
+	"Zm9v\r\nYmFy",
+	DECODE
+    },
+    {
+    	"foobar",
+    	"\nZ\r\nm 9\tv\nYm\nF\ny\n",
+    	DECODE
+    },
 };
 
@@ -557,36 +585,41 @@
 
     for (i=0; i<PJ_ARRAY_SIZE(base64_test_vec); ++i) {
+	pj_str_t input;
+	int out_len;
+
 	/* Encode test */
-	pj_str_t input;
-	int out_len = sizeof(output);
-
-	rc = pj_base64_encode((pj_uint8_t*)base64_test_vec[i].base256, 
-			      strlen(base64_test_vec[i].base256),
-			      output, &out_len);
-	if (rc != PJ_SUCCESS)
-	    return -90;
-
-	if (out_len != (int)strlen(base64_test_vec[i].base64))
-	    return -91;
-
-	output[out_len] = '\0';
-	if (strcmp(output, base64_test_vec[i].base64) != 0)
-	    return -92;
+	if (base64_test_vec[i].flag & ENCODE) {
+	    out_len = sizeof(output);
+	    rc = pj_base64_encode((pj_uint8_t*)base64_test_vec[i].base256,
+				  strlen(base64_test_vec[i].base256),
+				  output, &out_len);
+	    if (rc != PJ_SUCCESS)
+		return -90;
+
+	    if (out_len != (int)strlen(base64_test_vec[i].base64))
+		return -91;
+
+	    output[out_len] = '\0';
+	    if (strcmp(output, base64_test_vec[i].base64) != 0)
+		return -92;
+	}
 
 	/* Decode test */
-	out_len = sizeof(output);
-	input.ptr = (char*)base64_test_vec[i].base64;
-	input.slen = strlen(base64_test_vec[i].base64);
-	rc = pj_base64_decode(&input, (pj_uint8_t*)output, &out_len);
-	if (rc != PJ_SUCCESS)
-	    return -95;
-
-	if (out_len != (int)strlen(base64_test_vec[i].base256))
-	    return -96;
-
-	output[out_len] = '\0';
-
-	if (strcmp(output, base64_test_vec[i].base256) != 0)
-	    return -97;
+	if (base64_test_vec[i].flag & DECODE) {
+	    out_len = sizeof(output);
+	    input.ptr = (char*)base64_test_vec[i].base64;
+	    input.slen = strlen(base64_test_vec[i].base64);
+	    rc = pj_base64_decode(&input, (pj_uint8_t*)output, &out_len);
+	    if (rc != PJ_SUCCESS)
+		return -95;
+
+	    if (out_len != (int)strlen(base64_test_vec[i].base256))
+		return -96;
+
+	    output[out_len] = '\0';
+
+	    if (strcmp(output, base64_test_vec[i].base256) != 0)
+		return -97;
+	}
     }
 
Index: /pjproject/trunk/pjlib-util/src/pjlib-util/base64.c
===================================================================
--- /pjproject/trunk/pjlib-util/src/pjlib-util/base64.c	(revision 3355)
+++ /pjproject/trunk/pjlib-util/src/pjlib-util/base64.c	(revision 3356)
@@ -48,5 +48,7 @@
 	return (63);
     else {
-	pj_assert(!"Should not happen as '=' should have been filtered");
+	/* It *may* happen on bad input, so this is not a good idea.
+	 * pj_assert(!"Should not happen as '=' should have been filtered");
+	 */
 	return INV;
     }
@@ -125,6 +127,6 @@
     const char *buf = input->ptr;
     int len = input->slen;
-    int i, j;
-    int c1, c2, c3, c4;
+    int i, j, k;
+    int c[4];
 
     PJ_ASSERT_RETURN(input && out && out_len, PJ_EINVAL);
@@ -136,40 +138,26 @@
 		     PJ_ETOOSMALL);
 
-    for (i=0, j=0; i+3 < len; i+=4) {
-	c1 = base256_char(buf[i]);
-	c2 = base256_char(buf[i+1]);
-	c3 = base256_char(buf[i+2]);
-	c4 = base256_char(buf[i+3]);
+    for (i=0, j=0; i<len; ) {
+	/* Fill up c, silently ignoring invalid characters */
+	for (k=0; k<4 && i<len; ++k) {
+	    do {
+		c[k] = base256_char(buf[i++]);
+	    } while (c[k]==INV && i<len);
+	}
 
-	out[j++] = (pj_uint8_t)((c1<<2) | ((c2 & 0x30)>>4));
-	out[j++] = (pj_uint8_t)(((c2 & 0x0F)<<4) | ((c3 & 0x3C)>>2));
-	out[j++] = (pj_uint8_t)(((c3 & 0x03)<<6) | (c4 & 0x3F));
-    }
-
-    if (i < len) {
-	c1 = base256_char(buf[i]);
-
-	if (i+1 < len)
-	    c2 = base256_char(buf[i+1]);
-	else 
-	    c2 = (INV);
-
-	if (i+2 < len)
-	    c3 = base256_char(buf[i+2]);
-	else
-	    c3 = (INV);
-
-	c4 = (INV);
-
-	if (c2 != INV) {
-	    out[j++] = (pj_uint8_t)((c1<<2) | ((c2 & 0x30)>>4));
-	    if (c3 != INV) {
-		out[j++] = (pj_uint8_t)(((c2 & 0x0F)<<4) | ((c3 & 0x3C)>>2));
-		if (c4 != INV) {
-		    out[j++] = (pj_uint8_t)(((c3 & 0x03)<<6) | (c4 & 0x3F));
+	if (k<4) {
+	    if (k > 1) {
+		out[j++] = (pj_uint8_t)((c[0]<<2) | ((c[1] & 0x30)>>4));
+		if (k > 2) {
+		    out[j++] = (pj_uint8_t)
+			       (((c[1] & 0x0F)<<4) | ((c[2] & 0x3C)>>2));
 		}
 	    }
+	    break;
 	}
-	
+
+	out[j++] = (pj_uint8_t)((c[0]<<2) | ((c[1] & 0x30)>>4));
+	out[j++] = (pj_uint8_t)(((c[1] & 0x0F)<<4) | ((c[2] & 0x3C)>>2));
+	out[j++] = (pj_uint8_t)(((c[2] & 0x03)<<6) | (c[3] & 0x3F));
     }
 
