14fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy/**************************************************************** 24fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Licensed to the Apache Software Foundation (ASF) under one * 34fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * or more contributor license agreements. See the NOTICE file * 44fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * distributed with this work for additional information * 54fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * regarding copyright ownership. The ASF licenses this file * 64fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * to you under the Apache License, Version 2.0 (the * 74fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * "License"); you may not use this file except in compliance * 84fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * with the License. You may obtain a copy of the License at * 94fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * * 104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * http://www.apache.org/licenses/LICENSE-2.0 * 114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * * 124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Unless required by applicable law or agreed to in writing, * 134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * software distributed under the License is distributed on an * 144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * KIND, either express or implied. See the License for the * 164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * specific language governing permissions and limitations * 174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * under the License. * 184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy ****************************************************************/ 194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedypackage org.apache.james.mime4j.decoder; 214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.IOException; 234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.InputStream; 244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy//BEGIN android-changed: Stubbing out logging 264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport org.apache.james.mime4j.Log; 274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport org.apache.james.mime4j.LogFactory; 284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy//END android-changed 294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy/** 314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Performs Quoted-Printable decoding on an underlying stream. 324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @version $Id: QuotedPrintableInputStream.java,v 1.3 2004/11/29 13:15:47 ntherning Exp $ 364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedypublic class QuotedPrintableInputStream extends InputStream { 384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private static Log log = LogFactory.getLog(QuotedPrintableInputStream.class); 394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private InputStream stream; 414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy ByteQueue byteq = new ByteQueue(); 424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy ByteQueue pushbackq = new ByteQueue(); 434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private byte state = 0; 444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public QuotedPrintableInputStream(InputStream stream) { 464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy this.stream = stream; 474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Closes the underlying stream. 514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException on I/O errors. 534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public void close() throws IOException { 554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy stream.close(); 564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public int read() throws IOException { 594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy fillBuffer(); 604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (byteq.count() == 0) 614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return -1; 624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy else { 634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byte val = byteq.dequeue(); 644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (val >= 0) 654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return val; 664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy else 674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return val & 0xFF; 684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Pulls bytes out of the underlying stream and places them in the 734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * pushback queue. This is necessary (vs. reading from the 744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * underlying stream directly) to detect and filter out "transport 754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * padding" whitespace, i.e., all whitespace that appears immediately 764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * before a CRLF. 774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException Underlying stream threw IOException. 794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private void populatePushbackQueue() throws IOException { 814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //Debug.verify(pushbackq.count() == 0, "PopulatePushbackQueue called when pushback queue was not empty!"); 824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (pushbackq.count() != 0) 844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return; 854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy while (true) { 874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int i = stream.read(); 884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy switch (i) { 894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy case -1: 904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy // stream is done 914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy pushbackq.clear(); // discard any whitespace preceding EOF 924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return; 934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy case ' ': 944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy case '\t': 954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy pushbackq.enqueue((byte)i); 964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; 974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy case '\r': 984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy case '\n': 994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy pushbackq.clear(); // discard any whitespace preceding EOL 1004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy pushbackq.enqueue((byte)i); 1014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return; 1024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy default: 1034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy pushbackq.enqueue((byte)i); 1044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return; 1054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Causes the pushback queue to get populated if it is empty, then 1114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * consumes and decodes bytes out of it until one or more bytes are 1124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * in the byte queue. This decoding step performs the actual QP 1134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * decoding. 1144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 1154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException Underlying stream threw IOException. 1164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private void fillBuffer() throws IOException { 1184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byte msdChar = 0; // first digit of escaped num 1194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy while (byteq.count() == 0) { 1204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (pushbackq.count() == 0) { 1214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy populatePushbackQueue(); 1224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (pushbackq.count() == 0) 1234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return; 1244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byte b = (byte)pushbackq.dequeue(); 1274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy switch (state) { 1294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy case 0: // start state, no bytes pending 1304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (b != '=') { 1314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byteq.enqueue(b); 1324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; // state remains 0 1334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 1344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy state = 1; 1354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; 1364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy case 1: // encountered "=" so far 1384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (b == '\r') { 1394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy state = 2; 1404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; 1414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else if ((b >= '0' && b <= '9') || (b >= 'A' && b <= 'F') || (b >= 'a' && b <= 'f')) { 1424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy state = 3; 1434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy msdChar = b; // save until next digit encountered 1444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; 1454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else if (b == '=') { 1464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /* 1474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Special case when == is encountered. 1484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Emit one = and stay in this state. 1494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (log.isWarnEnabled()) { 1514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy log.warn("Malformed MIME; got =="); 1524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byteq.enqueue((byte)'='); 1544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; 1554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 1564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (log.isWarnEnabled()) { 1574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy log.warn("Malformed MIME; expected \\r or " 1584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy + "[0-9A-Z], got " + b); 1594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy state = 0; 1614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byteq.enqueue((byte)'='); 1624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byteq.enqueue(b); 1634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; 1644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy case 2: // encountered "=\r" so far 1664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (b == '\n') { 1674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy state = 0; 1684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; 1694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 1704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (log.isWarnEnabled()) { 1714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy log.warn("Malformed MIME; expected " 1724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy + (int)'\n' + ", got " + b); 1734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy state = 0; 1754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byteq.enqueue((byte)'='); 1764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byteq.enqueue((byte)'\r'); 1774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byteq.enqueue(b); 1784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; 1794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy case 3: // encountered =<digit> so far; expecting another <digit> to complete the octet 1814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if ((b >= '0' && b <= '9') || (b >= 'A' && b <= 'F') || (b >= 'a' && b <= 'f')) { 1824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byte msd = asciiCharToNumericValue(msdChar); 1834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byte low = asciiCharToNumericValue(b); 1844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy state = 0; 1854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byteq.enqueue((byte)((msd << 4) | low)); 1864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; 1874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 1884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (log.isWarnEnabled()) { 1894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy log.warn("Malformed MIME; expected " 1904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy + "[0-9A-Z], got " + b); 1914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy state = 0; 1934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byteq.enqueue((byte)'='); 1944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byteq.enqueue(msdChar); 1954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byteq.enqueue(b); 1964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; 1974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy default: // should never happen 1994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy log.error("Illegal state: " + state); 2004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy state = 0; 2014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byteq.enqueue(b); 2024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; 2034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 2084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Converts '0' => 0, 'A' => 10, etc. 2094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param c ASCII character value. 2104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return Numeric value of hexadecimal character. 2114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private byte asciiCharToNumericValue(byte c) { 2134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (c >= '0' && c <= '9') { 2144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return (byte)(c - '0'); 2154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else if (c >= 'A' && c <= 'Z') { 2164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return (byte)(0xA + (c - 'A')); 2174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else if (c >= 'a' && c <= 'z') { 2184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return (byte)(0xA + (c - 'a')); 2194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 2204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /* 2214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This should never happen since all calls to this method 2224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * are preceded by a check that c is in [0-9A-Za-z] 2234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy throw new IllegalArgumentException((char) c 2254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy + " is not a hexadecimal digit"); 2264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy} 230