001 /** 002 * 003 * Copyright 2003-2006 The Apache Software Foundation 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.geronimo.mail.util; 019 020 import java.io.IOException; 021 import java.io.OutputStream; 022 023 public class HexEncoder 024 implements Encoder 025 { 026 protected final byte[] encodingTable = 027 { 028 (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', 029 (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f' 030 }; 031 032 /* 033 * set up the decoding table. 034 */ 035 protected final byte[] decodingTable = new byte[128]; 036 037 protected void initialiseDecodingTable() 038 { 039 for (int i = 0; i < encodingTable.length; i++) 040 { 041 decodingTable[encodingTable[i]] = (byte)i; 042 } 043 044 decodingTable['A'] = decodingTable['a']; 045 decodingTable['B'] = decodingTable['b']; 046 decodingTable['C'] = decodingTable['c']; 047 decodingTable['D'] = decodingTable['d']; 048 decodingTable['E'] = decodingTable['e']; 049 decodingTable['F'] = decodingTable['f']; 050 } 051 052 public HexEncoder() 053 { 054 initialiseDecodingTable(); 055 } 056 057 /** 058 * encode the input data producing a Hex output stream. 059 * 060 * @return the number of bytes produced. 061 */ 062 public int encode( 063 byte[] data, 064 int off, 065 int length, 066 OutputStream out) 067 throws IOException 068 { 069 for (int i = off; i < (off + length); i++) 070 { 071 int v = data[i] & 0xff; 072 073 out.write(encodingTable[(v >>> 4)]); 074 out.write(encodingTable[v & 0xf]); 075 } 076 077 return length * 2; 078 } 079 080 private boolean ignore( 081 char c) 082 { 083 return (c == '\n' || c =='\r' || c == '\t' || c == ' '); 084 } 085 086 /** 087 * decode the Hex encoded byte data writing it to the given output stream, 088 * whitespace characters will be ignored. 089 * 090 * @return the number of bytes produced. 091 */ 092 public int decode( 093 byte[] data, 094 int off, 095 int length, 096 OutputStream out) 097 throws IOException 098 { 099 byte[] bytes; 100 byte b1, b2; 101 int outLen = 0; 102 103 int end = off + length; 104 105 while (end > 0) 106 { 107 if (!ignore((char)data[end - 1])) 108 { 109 break; 110 } 111 112 end--; 113 } 114 115 int i = off; 116 while (i < end) 117 { 118 while (i < end && ignore((char)data[i])) 119 { 120 i++; 121 } 122 123 b1 = decodingTable[data[i++]]; 124 125 while (i < end && ignore((char)data[i])) 126 { 127 i++; 128 } 129 130 b2 = decodingTable[data[i++]]; 131 132 out.write((b1 << 4) | b2); 133 134 outLen++; 135 } 136 137 return outLen; 138 } 139 140 /** 141 * decode the Hex encoded String data writing it to the given output stream, 142 * whitespace characters will be ignored. 143 * 144 * @return the number of bytes produced. 145 */ 146 public int decode( 147 String data, 148 OutputStream out) 149 throws IOException 150 { 151 byte[] bytes; 152 byte b1, b2, b3, b4; 153 int length = 0; 154 155 int end = data.length(); 156 157 while (end > 0) 158 { 159 if (!ignore(data.charAt(end - 1))) 160 { 161 break; 162 } 163 164 end--; 165 } 166 167 int i = 0; 168 while (i < end) 169 { 170 while (i < end && ignore(data.charAt(i))) 171 { 172 i++; 173 } 174 175 b1 = decodingTable[data.charAt(i++)]; 176 177 while (i < end && ignore(data.charAt(i))) 178 { 179 i++; 180 } 181 182 b2 = decodingTable[data.charAt(i++)]; 183 184 out.write((b1 << 4) | b2); 185 186 length++; 187 } 188 189 return length; 190 } 191 }