001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.coder;
020
021import lucee.commons.io.CharsetUtil;
022
023
024/**
025 * 
026 */
027public final class HexCoder {
028        
029        /**
030         * encodes a byte array to a String
031         * @param bytes
032         * @return encoed String
033         */
034        public static String encode(byte[] bytes) {
035                String retorno = "";
036                if (bytes==null || bytes.length==0) {
037                        return retorno;
038                }
039                for (int i=0; i<bytes.length; i++) {
040                        byte valor = bytes[i];
041                        int d1 = valor & 0xF;
042                        d1 += (d1 < 10) ? 48 : 55;
043                        int d2 = (valor & 0xF0) >> 4;
044                        d2 += (d2 < 10) ? 48 : 55;
045                        retorno = retorno + (char)d2 + (char)d1;
046                }
047                return retorno;
048        }
049
050        /**
051         * decodes back a String to a byte array
052         * @param hexa
053         * @return decoded byte array
054         * @throws CoderException
055         */
056        public static byte[] decode(String hexa) throws CoderException {
057                if (hexa == null) {
058                        throw new CoderException("can't decode empty String");
059                }
060                if ((hexa.length() % 2) != 0) {
061                        throw new CoderException("invalid hexadicimal String");
062                }
063                int tamArray = hexa.length() / 2;
064                byte[] retorno = new byte[tamArray];
065                for (int i=0; i<tamArray; i++) {
066                        retorno[i] = hexToByte(hexa.substring(i*2,i*2+2));
067                }
068                return retorno;
069        }
070
071        private static byte hexToByte(String hexa) throws CoderException {
072                if (hexa == null) {
073                        throw new CoderException("can't decode empty String");
074                }
075                if (hexa.length() != 2) {
076                        throw new CoderException("invalid hexadicimal String");
077                }
078                byte[] b = hexa.getBytes(CharsetUtil.UTF8);
079                byte valor = (byte) (hexDigitValue((char)b[0]) * 16 +
080                                                                hexDigitValue((char)b[1]));
081                return valor;
082        }
083
084        private static int hexDigitValue(char c) throws CoderException {
085                int retorno = 0;
086                if (c>='0' && c<='9') {
087                        retorno = (((byte)c) - 48);
088                }
089                else if (c>='A' && c<='F') {
090                        retorno = (((byte)c) - 55);
091                }
092                else if (c>='a' && c<='f') {
093                        retorno = (((byte)c) - 87);
094                }
095                else {
096                        throw new CoderException("invalid hexadicimal String");
097                }
098                return retorno;
099        }
100        
101}