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