001/*
002 * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Util.java $
003 * $Revision: 121 $
004 * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
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 java.io.ByteArrayInputStream;
035import java.io.IOException;
036import java.io.InputStream;
037import java.io.OutputStream;
038import java.net.UnknownHostException;
039import java.util.LinkedList;
040import java.util.Map;
041import java.util.StringTokenizer;
042import java.util.TreeMap;
043
044/**
045 * @author Credit Union Central of British Columbia
046 * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
047 * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
048 * @since 28-Feb-2006
049 */
050public class Util {
051    public final static int SIZE_KEY = 0;
052    public final static int LAST_READ_KEY = 1;
053
054    public static boolean isYes(String yesString) {
055        if (yesString == null) {
056            return false;
057        }
058        String s = yesString.trim().toUpperCase();
059        return "1".equals(s) || "YES".equals(s) || "TRUE".equals(s) ||
060               "ENABLE".equals(s) || "ENABLED".equals(s) || "Y".equals(s) ||
061               "ON".equals(s);
062    }
063
064    public static String trim(final String s) {
065        if (s == null || "".equals(s)) {
066            return s;
067        }
068        int i = 0;
069        int j = s.length() - 1;
070        while (isWhiteSpace(s.charAt(i))) {
071            i++;
072        }
073        while (isWhiteSpace(s.charAt(j))) {
074            j--;
075        }
076        return j >= i ? s.substring(i, j + 1) : "";
077    }
078
079    public static boolean isWhiteSpace(final char c) {
080        switch (c) {
081            case 0:
082            case ' ':
083            case '\t':
084            case '\n':
085            case '\r':
086            case '\f':
087                return true;
088            default:
089                return false;
090        }
091    }
092
093    public static void pipeStream(InputStream in, OutputStream out)
094        throws IOException {
095        pipeStream(in, out, true);
096    }
097
098    public static void pipeStream(InputStream in, OutputStream out,
099                                  boolean autoClose)
100        throws IOException {
101        byte[] buf = new byte[4096];
102        IOException ioe = null;
103        try {
104            int bytesRead = in.read(buf);
105            while (bytesRead >= 0) {
106                if (bytesRead > 0) {
107                    out.write(buf, 0, bytesRead);
108                }
109                bytesRead = in.read(buf);
110            }
111        }
112        finally {
113            // Probably it's best to let consumer call "close", but I'm usually
114            // the consumer, and I want to be lazy.  [Julius, November 20th, 2006]
115            try { in.close(); } catch (IOException e) { ioe = e; }
116            if (autoClose) {
117                try { out.close(); } catch (IOException e) { ioe = e; }
118            }
119        }
120        if (ioe != null) {
121            throw ioe;
122        }
123    }
124
125    public static byte[] streamToBytes(final ByteArrayInputStream in,
126                                       int maxLength) {
127        byte[] buf = new byte[maxLength];
128        int[] status = fill(buf, 0, in);
129        int size = status[SIZE_KEY];
130        if (buf.length != size) {
131            byte[] smallerBuf = new byte[size];
132            System.arraycopy(buf, 0, smallerBuf, 0, size);
133            buf = smallerBuf;
134        }
135        return buf;
136    }
137
138    public static byte[] streamToBytes(final InputStream in, int maxLength)
139        throws IOException {
140        byte[] buf = new byte[maxLength];
141        int[] status = fill(buf, 0, in);
142        int size = status[SIZE_KEY];
143        if (buf.length != size) {
144            byte[] smallerBuf = new byte[size];
145            System.arraycopy(buf, 0, smallerBuf, 0, size);
146            buf = smallerBuf;
147        }
148        return buf;
149    }
150
151    public static byte[] streamToBytes(final InputStream in) throws IOException {
152        byte[] buf = new byte[4096];
153        try {
154            int[] status = fill(buf, 0, in);
155            int size = status[SIZE_KEY];
156            int lastRead = status[LAST_READ_KEY];
157            while (lastRead != -1) {
158                buf = resizeArray(buf);
159                status = fill(buf, size, in);
160                size = status[SIZE_KEY];
161                lastRead = status[LAST_READ_KEY];
162            }
163            if (buf.length != size) {
164                byte[] smallerBuf = new byte[size];
165                System.arraycopy(buf, 0, smallerBuf, 0, size);
166                buf = smallerBuf;
167            }
168        }
169        finally {
170            in.close();
171        }
172        return buf;
173    }
174
175    public static byte[] streamToBytes(final ByteArrayInputStream in) {
176        byte[] buf = new byte[4096];
177        int[] status = fill(buf, 0, in);
178        int size = status[SIZE_KEY];
179        int lastRead = status[LAST_READ_KEY];
180        while (lastRead != -1) {
181            buf = resizeArray(buf);
182            status = fill(buf, size, in);
183            size = status[SIZE_KEY];
184            lastRead = status[LAST_READ_KEY];
185        }
186        if (buf.length != size) {
187            byte[] smallerBuf = new byte[size];
188            System.arraycopy(buf, 0, smallerBuf, 0, size);
189            buf = smallerBuf;
190        }
191        // in.close();  <-- this is a no-op on ByteArrayInputStream.
192        return buf;
193    }
194
195    public static int[] fill(final byte[] buf, final int offset,
196                             final InputStream in)
197        throws IOException {
198        int read = in.read(buf, offset, buf.length - offset);
199        int lastRead = read;
200        if (read == -1) {
201            read = 0;
202        }
203        while (lastRead != -1 && read + offset < buf.length) {
204            lastRead = in.read(buf, offset + read, buf.length - read - offset);
205            if (lastRead != -1) {
206                read += lastRead;
207            }
208        }
209        return new int[]{offset + read, lastRead};
210    }
211
212    public static int[] fill(final byte[] buf, final int offset,
213                             final ByteArrayInputStream in) {
214        int read = in.read(buf, offset, buf.length - offset);
215        int lastRead = read;
216        if (read == -1) {
217            read = 0;
218        }
219        while (lastRead != -1 && read + offset < buf.length) {
220            lastRead = in.read(buf, offset + read, buf.length - read - offset);
221            if (lastRead != -1) {
222                read += lastRead;
223            }
224        }
225        return new int[]{offset + read, lastRead};
226    }
227
228    public static byte[] resizeArray(final byte[] bytes) {
229        byte[] biggerBytes = new byte[bytes.length * 2];
230        System.arraycopy(bytes, 0, biggerBytes, 0, bytes.length);
231        return biggerBytes;
232    }
233
234    public static String pad(String s, final int length, final boolean left) {
235        if (s == null) {
236            s = "";
237        }
238        int diff = length - s.length();
239        if (diff == 0) {
240            return s;
241        } else if (diff > 0) {
242            StringBuffer sb = new StringBuffer();
243            if (left) {
244                for (int i = 0; i < diff; i++) {
245                    sb.append(' ');
246                }
247            }
248            sb.append(s);
249            if (!left) {
250                for (int i = 0; i < diff; i++) {
251                    sb.append(' ');
252                }
253            }
254            return sb.toString();
255        } else {
256            return s;
257        }
258    }
259
260    public static Map parseArgs(final String[] cargs) {
261        Map args = new TreeMap();
262        Map ARGS_MATCH = Ping.ARGS_MATCH;
263
264        int l = cargs.length;
265        final String[] EMPTY_VALUES = {""};
266        for (int i = 0; i < l; i++) {
267            String k = cargs[i];
268            Ping.Arg a = (Ping.Arg) ARGS_MATCH.get(k);
269            if (l > i + 1) {
270                String v = cargs[++i];
271                while (ARGS_MATCH.containsKey(v)) {
272                    args.put(a, EMPTY_VALUES);
273                    a = (Ping.Arg) ARGS_MATCH.get(v);
274                    v = "";
275                    if (l > i + 1) {
276                        v = cargs[++i];
277                    }
278                }
279                String[] values = new String[1];
280                values[0] = v;
281                args.put(a, values);
282                if (l > i + 1 && !ARGS_MATCH.containsKey(cargs[i + 1])) {
283                    LinkedList list = new LinkedList();
284                    list.add(v);
285                    while (l > i + 1 && !ARGS_MATCH.containsKey(cargs[i + 1])) {
286                        v = cargs[++i];
287                        list.add(v);
288                    }
289                    args.put(a, list.toArray(new String[list.size()]));
290                }
291            } else {
292                args.put(a, EMPTY_VALUES);
293            }
294        }
295        return args;
296    }
297
298    public static String readLine(final InputStream in) throws IOException {
299        StringBuffer buf = new StringBuffer(64);
300        int b = in.read();
301        while (b != -1) {
302            char c = (char) b;
303            if (c == '\n' || c == '\r') {
304                if (buf.length() >= 1) {
305                    return buf.toString();
306                }
307            } else {
308                buf.append(c);
309            }
310            b = in.read();
311        }
312        return buf.length() >= 1 ? buf.toString() : null;
313    }
314
315    public static String readLine(final ByteArrayInputStream in) {
316        StringBuffer buf = new StringBuffer(64);
317        int b = in.read();
318        while (b != -1) {
319            char c = (char) b;
320            if (c == '\n' || c == '\r') {
321                if (buf.length() >= 1) {
322                    return buf.toString();
323                }
324            } else {
325                buf.append(c);
326            }
327            b = in.read();
328        }
329        return buf.length() >= 1 ? buf.toString() : null;
330    }
331
332    public static HostPort toAddress(final String target,
333                                     final int defaultPort)
334        throws UnknownHostException {
335        String host = target;
336        int port = defaultPort;
337        StringTokenizer st = new StringTokenizer(target, ":");
338        if (st.hasMoreTokens()) {
339            host = st.nextToken().trim();
340        }
341        if (st.hasMoreTokens()) {
342            port = Integer.parseInt(st.nextToken().trim());
343        }
344        if (st.hasMoreTokens()) {
345            throw new IllegalArgumentException("Invalid host: " + target);
346        }
347        return new HostPort(host, port);
348    }
349
350    public static String cipherToAuthType(String cipher) {
351        if (cipher == null) {
352            return null;
353        }
354
355        // SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA  ==> "DHE_DSS_EXPORT"
356        // SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA      ==> "DHE_DSS"
357        // SSL_RSA_WITH_3DES_EDE_CBC_SHA          ==> "RSA"
358
359        StringTokenizer st = new StringTokenizer(cipher.trim(), "_");
360        if (st.hasMoreTokens()) {
361            st.nextToken();  // always skip first token
362        }
363        if (st.hasMoreTokens()) {
364            String tok = st.nextToken();
365            StringBuffer buf = new StringBuffer();
366            buf.append(tok);
367            if (st.hasMoreTokens()) {
368                tok = st.nextToken();
369                while (!"WITH".equalsIgnoreCase(tok)) {
370                    buf.append('_');
371                    buf.append(tok);
372                    tok = st.nextToken();
373                }
374            }
375            return buf.toString();
376        }
377        throw new IllegalArgumentException("not a valid cipher: " + cipher);
378    }
379
380
381    public static void main(String[] args) throws Exception {
382        String s = "line1\n\rline2\n\rline3";
383        InputStream in = new ByteArrayInputStream(s.getBytes());
384        String line = readLine(in);
385        while (line != null) {
386            System.out.println(line);
387            line = readLine(in);
388        }
389
390        System.out.println("--------- test 2 ----------");
391
392        s = "line1\n\rline2\n\rline3\n\r\n\r";
393        in = new ByteArrayInputStream(s.getBytes());
394        line = readLine(in);
395        while (line != null) {
396            System.out.println(line);
397            line = readLine(in);
398        }
399
400    }
401
402
403}