src/share/classes/java/util/Base64.java

Print this page

        

*** 62,72 **** * <li><b>MIME</b> * <p> Uses the "The Base64 Alphabet" as specified in Table 1 of * RFC 2045 for encoding and decoding operation. The encoded output * must be represented in lines of no more than 76 characters each * and uses a carriage return {@code '\r'} followed immediately by ! * a linefeed {@code '\n'} as the line separator. All line separators * or other characters not found in the base64 alphabet table are * ignored in decoding operation.</p></li> * </ul> * * <p> Unless otherwise noted, passing a {@code null} argument to a --- 62,73 ---- * <li><b>MIME</b> * <p> Uses the "The Base64 Alphabet" as specified in Table 1 of * RFC 2045 for encoding and decoding operation. The encoded output * must be represented in lines of no more than 76 characters each * and uses a carriage return {@code '\r'} followed immediately by ! * a linefeed {@code '\n'} as the line separator. No line separator ! * is added to the end of the encoded output. All line separators * or other characters not found in the base64 alphabet table are * ignored in decoding operation.</p></li> * </ul> * * <p> Unless otherwise noted, passing a {@code null} argument to a
*** 612,621 **** --- 613,629 ---- /** * This class implements a decoder for decoding byte data using the * Base64 encoding scheme as specified in RFC 4648 and RFC 2045. * + * <p> The Base64 padding character {@code '='} is accepted and + * interpreted as the end of the encoded byte data, but is not + * required. So if the final unit of the encoded byte data only has + * two or three Base64 characters (without the corresponding padding + * character(s) padded), they are decoded as if followed by padding + * character(s). + * * <p> Instances of {@link Decoder} class are safe for use by * multiple concurrent threads. * * <p> Unless otherwise noted, passing a {@code null} argument to * a method of this class will cause a
*** 855,864 **** --- 863,875 ---- } /** * Returns an input stream for decoding {@link Base64} encoded byte stream. * + * <p> The {@code read} methods of the returned {@code InputStream} will + * throw {@code IOException} when reading bytes that cannot be decoded. + * * <p> Closing the returned input stream will close the underlying * input stream. * * @param is * the input stream
*** 881,897 **** byte[] da = dst.array(); int dp = dst.arrayOffset() + dst.position(); int dl = dst.arrayOffset() + dst.limit(); int dp0 = dp; int mark = sp; - boolean padding = false; try { while (sp < sl) { int b = sa[sp++] & 0xff; if ((b = base64[b]) < 0) { if (b == -2) { // padding byte ! padding = true; break; } if (isMIME) // skip if for rfc2045 continue; else --- 892,911 ---- byte[] da = dst.array(); int dp = dst.arrayOffset() + dst.position(); int dl = dst.arrayOffset() + dst.limit(); int dp0 = dp; int mark = sp; try { while (sp < sl) { int b = sa[sp++] & 0xff; if ((b = base64[b]) < 0) { if (b == -2) { // padding byte ! if (shiftto == 6 && (sp == sl || sa[sp++] != '=') || ! shiftto == 18) { ! throw new IllegalArgumentException( ! "Input byte array has wrong 4-byte ending unit"); ! } break; } if (isMIME) // skip if for rfc2045 continue; else
*** 913,940 **** } } if (shiftto == 6) { if (dl - dp < 1) return dp - dp0; - if (padding && (sp + 1 != sl || sa[sp++] != '=')) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); da[dp++] = (byte)(bits >> 16); - mark = sp; } else if (shiftto == 0) { if (dl - dp < 2) return dp - dp0; - if (padding && sp != sl) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); da[dp++] = (byte)(bits >> 16); da[dp++] = (byte)(bits >> 8); ! mark = sp; ! } else if (padding || shiftto != 18) { throw new IllegalArgumentException( "Last unit does not have enough valid bits"); } return dp - dp0; } finally { src.position(mark); dst.position(dp); } --- 927,953 ---- } } if (shiftto == 6) { if (dl - dp < 1) return dp - dp0; da[dp++] = (byte)(bits >> 16); } else if (shiftto == 0) { if (dl - dp < 2) return dp - dp0; da[dp++] = (byte)(bits >> 16); da[dp++] = (byte)(bits >> 8); ! } else if (shiftto == 12) { throw new IllegalArgumentException( "Last unit does not have enough valid bits"); } + while (sp < sl) { + if (isMIME && base64[sa[sp++]] < 0) + continue; + throw new IllegalArgumentException( + "Input byte array has incorrect ending byte at " + sp); + } + mark = sp; return dp - dp0; } finally { src.position(mark); dst.position(dp); }
*** 948,965 **** int sl = src.limit(); int dp = dst.position(); int dl = dst.limit(); int dp0 = dp; int mark = sp; - boolean padding = false; - try { while (sp < sl) { int b = src.get(sp++) & 0xff; if ((b = base64[b]) < 0) { if (b == -2) { // padding byte ! padding = true; break; } if (isMIME) // skip if for rfc2045 continue; else --- 961,980 ---- int sl = src.limit(); int dp = dst.position(); int dl = dst.limit(); int dp0 = dp; int mark = sp; try { while (sp < sl) { int b = src.get(sp++) & 0xff; if ((b = base64[b]) < 0) { if (b == -2) { // padding byte ! if (shiftto == 6 && (sp == sl || src.get(sp++) != '=') || ! shiftto == 18) { ! throw new IllegalArgumentException( ! "Input byte array has wrong 4-byte ending unit"); ! } break; } if (isMIME) // skip if for rfc2045 continue; else
*** 981,1008 **** } } if (shiftto == 6) { if (dl - dp < 1) return dp - dp0; - if (padding && (sp + 1 != sl || src.get(sp++) != '=')) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); dst.put(dp++, (byte)(bits >> 16)); - mark = sp; } else if (shiftto == 0) { if (dl - dp < 2) return dp - dp0; - if (padding && sp != sl) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); dst.put(dp++, (byte)(bits >> 16)); dst.put(dp++, (byte)(bits >> 8)); ! mark = sp; ! } else if (padding || shiftto != 18) { throw new IllegalArgumentException( "Last unit does not have enough valid bits"); } return dp - dp0; } finally { src.position(mark); dst.position(dp); } --- 996,1022 ---- } } if (shiftto == 6) { if (dl - dp < 1) return dp - dp0; dst.put(dp++, (byte)(bits >> 16)); } else if (shiftto == 0) { if (dl - dp < 2) return dp - dp0; dst.put(dp++, (byte)(bits >> 16)); dst.put(dp++, (byte)(bits >> 8)); ! } else if (shiftto == 12) { throw new IllegalArgumentException( "Last unit does not have enough valid bits"); } + while (sp < sl) { + if (isMIME && base64[src.get(sp++)] < 0) + continue; + throw new IllegalArgumentException( + "Input byte array has incorrect ending byte at " + sp); + } + mark = sp; return dp - dp0; } finally { src.position(mark); dst.position(dp); }
*** 1046,1061 **** private int decode0(byte[] src, int sp, int sl, byte[] dst) { int[] base64 = isURL ? fromBase64URL : fromBase64; int dp = 0; int bits = 0; int shiftto = 18; // pos of first byte of 4-byte atom - boolean padding = false; while (sp < sl) { int b = src[sp++] & 0xff; if ((b = base64[b]) < 0) { ! if (b == -2) { // padding byte ! padding = true; break; } if (isMIME) // skip if for rfc2045 continue; else --- 1060,1083 ---- private int decode0(byte[] src, int sp, int sl, byte[] dst) { int[] base64 = isURL ? fromBase64URL : fromBase64; int dp = 0; int bits = 0; int shiftto = 18; // pos of first byte of 4-byte atom while (sp < sl) { int b = src[sp++] & 0xff; if ((b = base64[b]) < 0) { ! if (b == -2) { // padding byte '=' ! // xx= shiftto==6&&sp==sl missing last = ! // xx=y shiftto==6 last is not = ! // = shiftto==18 unnecessary padding ! // x= shiftto==12 be taken care later ! // together with single x, invalid anyway ! if (shiftto == 6 && (sp == sl || src[sp++] != '=') || ! shiftto == 18) { ! throw new IllegalArgumentException( ! "Input byte array has wrong 4-byte ending unit"); ! } break; } if (isMIME) // skip if for rfc2045 continue; else
*** 1071,1096 **** dst[dp++] = (byte)(bits); shiftto = 18; bits = 0; } } ! // reach end of byte arry or hit padding '=' characters. ! // if '=' presents, they must be the last one or two. ! if (shiftto == 6) { // xx== ! if (padding && (sp + 1 != sl || src[sp] != '=')) ! throw new IllegalArgumentException( ! "Input byte array has wrong 4-byte ending unit"); dst[dp++] = (byte)(bits >> 16); ! } else if (shiftto == 0) { // xxx= ! if (padding && sp != sl) ! throw new IllegalArgumentException( ! "Input byte array has wrong 4-byte ending unit"); dst[dp++] = (byte)(bits >> 16); dst[dp++] = (byte)(bits >> 8); ! } else if (padding || shiftto != 18) { throw new IllegalArgumentException( ! "last unit does not have enough bytes"); } return dp; } } --- 1093,1119 ---- dst[dp++] = (byte)(bits); shiftto = 18; bits = 0; } } ! // reached end of byte array or hit padding '=' characters. ! if (shiftto == 6) { dst[dp++] = (byte)(bits >> 16); ! } else if (shiftto == 0) { dst[dp++] = (byte)(bits >> 16); dst[dp++] = (byte)(bits >> 8); ! } else if (shiftto == 12) { ! throw new IllegalArgumentException( ! "Last unit does not have enough valid bits"); ! } ! // anything left is invalid, if is not MIME. ! // if MIME, ignore all non-base64 character ! while (sp < sl) { ! if (isMIME && base64[src[sp++]] < 0) ! continue; throw new IllegalArgumentException( ! "Input byte array has incorrect ending byte at " + sp); } return dp; } }
*** 1250,1261 **** } while (len > 0) { int v = is.read(); if (v == -1) { eof = true; ! if (nextin != 18) ! throw new IOException("Base64 stream has un-decoded dangling byte(s)."); if (off == oldOff) return -1; else return off - oldOff; } --- 1273,1298 ---- } while (len > 0) { int v = is.read(); if (v == -1) { eof = true; ! if (nextin != 18) { ! if (nextin == 12) ! throw new IOException("Base64 stream has one un-decoded dangling byte."); ! // treat ending xx/xxx without padding character legal. ! // same logic as v == 'v' below ! b[off++] = (byte)(bits >> (16)); ! len--; ! if (nextin == 0) { // only one padding byte ! if (len == 0) { // no enough output space ! bits >>= 8; // shift to lowest byte ! nextout = 0; ! } else { ! b[off++] = (byte) (bits >> 8); ! } ! } ! } if (off == oldOff) return -1; else return off - oldOff; }