Line data Source code
1 : // Copyright (C) 2009 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : // 15 : // This code is based heavily on Robert Harder's <rob@iharder.net> 16 : // public domain Base64 class, version 2.1. 17 : // 18 : 19 : package com.google.gerrit.httpd; 20 : 21 : /** Base64 encoder which uses a language safe within HTTP cookies. */ 22 : class CookieBase64 { 23 : private static final char[] enc; 24 : 25 : static { 26 1 : enc = new char[64]; 27 1 : int o = 0; 28 1 : o = fill(enc, o, 'a', 'z'); 29 1 : o = fill(enc, o, 'A', 'Z'); 30 1 : o = fill(enc, o, '0', '9'); 31 1 : enc[o++] = '-'; 32 1 : enc[o] = '.'; 33 1 : } 34 : 35 : private static int fill(char[] out, int o, char f, int l) { 36 1 : for (char c = f; c <= l; c++) { 37 1 : out[o++] = c; 38 : } 39 1 : return o; 40 : } 41 : 42 : static String encode(byte[] in) { 43 1 : final StringBuilder out = new StringBuilder(in.length * 4 / 3); 44 1 : final int len2 = in.length - 2; 45 1 : int d = 0; 46 1 : for (; d < len2; d += 3) { 47 1 : encode3to4(out, in, d, 3); 48 : } 49 1 : if (d < in.length) { 50 1 : encode3to4(out, in, d, in.length - d); 51 : } 52 1 : return out.toString(); 53 : } 54 : 55 : private static void encode3to4(StringBuilder out, byte[] in, int inOffset, int numSigBytes) { 56 : // 1 2 3 57 : // 01234567890123456789012345678901 Bit position 58 : // --------000000001111111122222222 Array position from threeBytes 59 : // --------| || || || | Six bit groups to index ALPHABET 60 : // >>18 >>12 >> 6 >> 0 Right shift necessary 61 : // 0x3f 0x3f 0x3f Additional AND 62 : 63 : // Create buffer with zero-padding if there are only one or two 64 : // significant bytes passed in the array. 65 : // We have to shift left 24 in order to flush out the 1's that appear 66 : // when Java treats a value as negative that is cast from a byte to an int. 67 : // 68 : int inBuff = 69 1 : (numSigBytes > 0 ? ((in[inOffset] << 24) >>> 8) : 0) 70 1 : | (numSigBytes > 1 ? ((in[inOffset + 1] << 24) >>> 16) : 0) 71 1 : | (numSigBytes > 2 ? ((in[inOffset + 2] << 24) >>> 24) : 0); 72 : 73 1 : switch (numSigBytes) { 74 : case 3: 75 1 : out.append(enc[(inBuff >>> 18)]); 76 1 : out.append(enc[(inBuff >>> 12) & 0x3f]); 77 1 : out.append(enc[(inBuff >>> 6) & 0x3f]); 78 1 : out.append(enc[inBuff & 0x3f]); 79 1 : break; 80 : 81 : case 2: 82 0 : out.append(enc[(inBuff >>> 18)]); 83 0 : out.append(enc[(inBuff >>> 12) & 0x3f]); 84 0 : out.append(enc[(inBuff >>> 6) & 0x3f]); 85 0 : break; 86 : 87 : case 1: 88 1 : out.append(enc[(inBuff >>> 18)]); 89 1 : out.append(enc[(inBuff >>> 12) & 0x3f]); 90 1 : break; 91 : 92 : default: 93 : break; 94 : } 95 1 : } 96 : 97 : private CookieBase64() {} 98 : }