    001/*
    002 * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.15/src/java/org/apache/commons/ssl/Util.java $
    003 * $Revision: 166 $
    004 * $Date: 2014-04-28 11:40:25 -0700 (Mon, 28 Apr 2014) $
    005 *
    006 * ====================================================================
    007 * Licensed to the Apache Software Foundation (ASF) under one
    008 * or more contributor license agreements.  See the NOTICE file
    009 * distributed with this work for additional information
    010 * regarding copyright ownership.  The ASF licenses this file
    011 * to you under the Apache License, Version 2.0 (the
    012 * "License"); you may not use this file except in compliance
    013 * with the License.  You may obtain a copy of the License at
    014 *
    015 *   http://www.apache.org/licenses/LICENSE-2.0
    016 *
    017 * Unless required by applicable law or agreed to in writing,
    018 * software distributed under the License is distributed on an
    019 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    020 * KIND, either express or implied.  See the License for the
    021 * specific language governing permissions and limitations
    022 * under the License.
    023 * ====================================================================
    024 *
    025 * This software consists of voluntary contributions made by many
    026 * individuals on behalf of the Apache Software Foundation.  For more
    027 * information on the Apache Software Foundation, please see
    028 * <http://www.apache.org/>.
    029 *
    030 */
    031
    032package org.apache.commons.ssl;
    033
    034import org.apache.commons.ssl.util.ByteArrayReadLine;
    035import org.apache.commons.ssl.util.IPAddressParser;
    036
    037import java.io.ByteArrayInputStream;
    038import java.io.IOException;
    039import java.io.InputStream;
    040import java.io.OutputStream;
    041import java.net.InetAddress;
    042import java.net.UnknownHostException;
    043import java.util.LinkedList;
    044import java.util.Map;
    045import java.util.StringTokenizer;
    046import java.util.TreeMap;
    047
    048/**
    049 * @author Credit Union Central of British Columbia
    050 * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
    051 * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
    052 * @since 28-Feb-2006
    053 */
    054public class Util {
    055    public final static int SIZE_KEY = 0;
    056    public final static int LAST_READ_KEY = 1;
    057
    058    public static boolean isYes(String yesString) {
    059        if (yesString == null) {
    060            return false;
    061        }
    062        String s = yesString.trim().toUpperCase();
    063        return "1".equals(s) || "YES".equals(s) || "TRUE".equals(s) ||
    064               "ENABLE".equals(s) || "ENABLED".equals(s) || "Y".equals(s) ||
    065               "ON".equals(s);
    066    }
    067
    068    public static String trim(final String s) {
    069        if (s == null || "".equals(s)) {
    070            return s;
    071        }
    072        int i = 0;
    073        int j = s.length() - 1;
    074        while (isWhiteSpace(s.charAt(i))) {
    075            i++;
    076        }
    077        while (isWhiteSpace(s.charAt(j))) {
    078            j--;
    079        }
    080        return j >= i ? s.substring(i, j + 1) : "";
    081    }
    082
    083    public static boolean isWhiteSpace(final char c) {
    084        switch (c) {
    085            case 0:
    086            case ' ':
    087            case '\t':
    088            case '\n':
    089            case '\r':
    090            case '\f':
    091                return true;
    092            default:
    093                return false;
    094        }
    095    }
    096
    097    public static void pipeStream(InputStream in, OutputStream out)
    098        throws IOException {
    099        pipeStream(in, out, true);
    100    }
    101
    102    public static void pipeStream(InputStream in, OutputStream out,
    103                                  boolean autoClose)
    104        throws IOException {
    105        byte[] buf = new byte[8192];
    106        IOException ioe = null;
    107        try {
    108            int bytesRead = in.read(buf);
    109            while (bytesRead >= 0) {
    110                if (bytesRead > 0) {
    111                    out.write(buf, 0, bytesRead);
    112                }
    113                bytesRead = in.read(buf);
    114            }
    115        }
    116        finally {
    117            // Probably it's best to let consumer call "close", but I'm usually
    118            // the consumer, and I want to be lazy.  [Julius, November 20th, 2006]
    119            try { in.close(); } catch (IOException e) { ioe = e; }
    120            if (autoClose) {
    121                try { out.close(); } catch (IOException e) { ioe = e; }
    122            }
    123        }
    124        if (ioe != null) {
    125            throw ioe;
    126        }
    127    }
    128
    129    public static byte[] streamToBytes(final ByteArrayInputStream in,
    130                                       int maxLength) {
    131        byte[] buf = new byte[maxLength];
    132        int[] status = fill(buf, 0, in);
    133        int size = status[SIZE_KEY];
    134        if (buf.length != size) {
    135            byte[] smallerBuf = new byte[size];
    136            System.arraycopy(buf, 0, smallerBuf, 0, size);
    137            buf = smallerBuf;
    138        }
    139        return buf;
    140    }
    141
    142    public static byte[] streamToBytes(final InputStream in, int maxLength)
    143        throws IOException {
    144        byte[] buf = new byte[maxLength];
    145        int[] status = fill(buf, 0, in);
    146        int size = status[SIZE_KEY];
    147        if (buf.length != size) {
    148            byte[] smallerBuf = new byte[size];
    149            System.arraycopy(buf, 0, smallerBuf, 0, size);
    150            buf = smallerBuf;
    151        }
    152        return buf;
    153    }
    154
    155    public static byte[] streamToBytes(final InputStream in) throws IOException {
    156        byte[] buf = new byte[4096];
    157        try {
    158            int[] status = fill(buf, 0, in);
    159            int size = status[SIZE_KEY];
    160            int lastRead = status[LAST_READ_KEY];
    161            while (lastRead != -1) {
    162                buf = resizeArray(buf);
    163                status = fill(buf, size, in);
    164                size = status[SIZE_KEY];
    165                lastRead = status[LAST_READ_KEY];
    166            }
    167            if (buf.length != size) {
    168                byte[] smallerBuf = new byte[size];
    169                System.arraycopy(buf, 0, smallerBuf, 0, size);
    170                buf = smallerBuf;
    171            }
    172        }
    173        finally {
    174            in.close();
    175        }
    176        return buf;
    177    }
    178
    179    public static byte[] streamToBytes(final ByteArrayInputStream in) {
    180        byte[] buf = new byte[4096];
    181        int[] status = fill(buf, 0, in);
    182        int size = status[SIZE_KEY];
    183        int lastRead = status[LAST_READ_KEY];
    184        while (lastRead != -1) {
    185            buf = resizeArray(buf);
    186            status = fill(buf, size, in);
    187            size = status[SIZE_KEY];
    188            lastRead = status[LAST_READ_KEY];
    189        }
    190        if (buf.length != size) {
    191            byte[] smallerBuf = new byte[size];
    192            System.arraycopy(buf, 0, smallerBuf, 0, size);
    193            buf = smallerBuf;
    194        }
    195        // in.close();  <-- this is a no-op on ByteArrayInputStream.
    196        return buf;
    197    }
    198
    199    public static int[] fill(final byte[] buf, final int offset,
    200                             final InputStream in)
    201        throws IOException {
    202        int read = in.read(buf, offset, buf.length - offset);
    203        int lastRead = read;
    204        if (read == -1) {
    205            read = 0;
    206        }
    207        while (lastRead != -1 && read + offset < buf.length) {
    208            lastRead = in.read(buf, offset + read, buf.length - read - offset);
    209            if (lastRead != -1) {
    210                read += lastRead;
    211            }
    212        }
    213        return new int[]{offset + read, lastRead};
    214    }
    215
    216    public static int[] fill(final byte[] buf, final int offset,
    217                             final ByteArrayInputStream in) {
    218        int read = in.read(buf, offset, buf.length - offset);
    219        int lastRead = read;
    220        if (read == -1) {
    221            read = 0;
    222        }
    223        while (lastRead != -1 && read + offset < buf.length) {
    224            lastRead = in.read(buf, offset + read, buf.length - read - offset);
    225            if (lastRead != -1) {
    226                read += lastRead;
    227            }
    228        }
    229        return new int[]{offset + read, lastRead};
    230    }
    231
    232    public static byte[] resizeArray(final byte[] bytes) {
    233        byte[] biggerBytes = new byte[bytes.length * 2];
    234        System.arraycopy(bytes, 0, biggerBytes, 0, bytes.length);
    235        return biggerBytes;
    236    }
    237
    238    public static String pad(String s, final int length, final boolean left) {
    239        if (s == null) {
    240            s = "";
    241        }
    242        int diff = length - s.length();
    243        if (diff == 0) {
    244            return s;
    245        } else if (diff > 0) {
    246            StringBuffer sb = new StringBuffer();
    247            if (left) {
    248                for (int i = 0; i < diff; i++) {
    249                    sb.append(' ');
    250                }
    251            }
    252            sb.append(s);
    253            if (!left) {
    254                for (int i = 0; i < diff; i++) {
    255                    sb.append(' ');
    256                }
    257            }
    258            return sb.toString();
    259        } else {
    260            return s;
    261        }
    262    }
    263
    264    public static Map parseArgs(final String[] cargs) {
    265        Map args = new TreeMap();
    266        Map ARGS_MATCH = Ping.ARGS_MATCH;
    267
    268        int l = cargs.length;
    269        final String[] EMPTY_VALUES = {""};
    270        for (int i = 0; i < l; i++) {
    271            String k = cargs[i];
    272            Ping.Arg a = (Ping.Arg) ARGS_MATCH.get(k);
    273            if (l > i + 1) {
    274                String v = cargs[++i];
    275                while (ARGS_MATCH.containsKey(v)) {
    276                    args.put(a, EMPTY_VALUES);
    277                    a = (Ping.Arg) ARGS_MATCH.get(v);
    278                    v = "";
    279                    if (l > i + 1) {
    280                        v = cargs[++i];
    281                    }
    282                }
    283                String[] values = new String[1];
    284                values[0] = v;
    285                args.put(a, values);
    286                if (l > i + 1 && !ARGS_MATCH.containsKey(cargs[i + 1])) {
    287                    LinkedList list = new LinkedList();
    288                    list.add(v);
    289                    while (l > i + 1 && !ARGS_MATCH.containsKey(cargs[i + 1])) {
    290                        v = cargs[++i];
    291                        list.add(v);
    292                    }
    293                    args.put(a, list.toArray(new String[list.size()]));
    294                }
    295            } else {
    296                args.put(a, EMPTY_VALUES);
    297            }
    298        }
    299        return args;
    300    }
    301
    302    public static HostPort toAddress(final String target,
    303                                     final int defaultPort)
    304        throws UnknownHostException {
    305        String host = target;
    306        int port = defaultPort;
    307        StringTokenizer st = new StringTokenizer(target, ":");
    308        if (st.hasMoreTokens()) {
    309            host = st.nextToken().trim();
    310        }
    311        if (st.hasMoreTokens()) {
    312            port = Integer.parseInt(st.nextToken().trim());
    313        }
    314        if (st.hasMoreTokens()) {
    315            throw new IllegalArgumentException("Invalid host: " + target);
    316        }
    317        return new HostPort(host, port);
    318    }
    319
    320    public static String cipherToAuthType(String cipher) {
    321        if (cipher == null) {
    322            return null;
    323        }
    324
    325        // SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA  ==> "DHE_DSS_EXPORT"
    326        // SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA      ==> "DHE_DSS"
    327        // SSL_RSA_WITH_3DES_EDE_CBC_SHA          ==> "RSA"
    328
    329        StringTokenizer st = new StringTokenizer(cipher.trim(), "_");
    330        if (st.hasMoreTokens()) {
    331            st.nextToken();  // always skip first token
    332        }
    333        if (st.hasMoreTokens()) {
    334            String tok = st.nextToken();
    335            StringBuffer buf = new StringBuffer();
    336            buf.append(tok);
    337            if (st.hasMoreTokens()) {
    338                tok = st.nextToken();
    339                while (!"WITH".equalsIgnoreCase(tok)) {
    340                    buf.append('_');
    341                    buf.append(tok);
    342                    tok = st.nextToken();
    343                }
    344            }
    345            return buf.toString();
    346        }
    347        throw new IllegalArgumentException("not a valid cipher: " + cipher);
    348    }
    349
    350    /**
    351     * Utility method to make sure IP-literals don't trigger reverse-DNS lookups.
    352     */
    353    public static InetAddress toInetAddress(String s) throws UnknownHostException {
    354        byte[] ip = IPAddressParser.parseIPv4Literal(s);
    355        if (ip == null) {
    356            ip = IPAddressParser.parseIPv6Literal(s);
    357        }
    358        if (ip != null) {
    359            // Strangely, this prevents Java's annoying SSL reverse-DNS lookup that it
    360            // normally does, even with literal IP addresses.
    361            return InetAddress.getByAddress(s, ip);
    362        } else {
    363            return InetAddress.getByName(s);
    364        }
    365    }
    366
    367    public static void main(String[] args) throws Exception {
    368        String s = "line1\n\rline2\n\rline3";
    369        ByteArrayInputStream in = new ByteArrayInputStream(s.getBytes());
    370        ByteArrayReadLine readLine = new ByteArrayReadLine(in);
    371        String line = readLine.next();
    372        while (line != null) {
    373            System.out.println(line);
    374            line = readLine.next();
    375        }
    376
    377        System.out.println("--------- test 2 ----------");
    378
    379        s = "line1\n\rline2\n\rline3\n\r\n\r";
    380        in = new ByteArrayInputStream(s.getBytes());
    381        readLine = new ByteArrayReadLine(in);
    382        line = readLine.next();
    383        while (line != null) {
    384            System.out.println(line);
    385            line = readLine.next();
    386        }
    387
    388    }
    389
    390
    391}