costin 01/02/19 19:12:14 Added: src/share/org/apache/tomcat/util/buf Ascii.java Base64.java ByteChunk.java CharChunk.java DateTool.java HexUtils.java MessageBytes.java Log: Moving files from tomcat.util in sub-packages. This avoids name polution and makes easy to understand the dependencies. Revision Changes Path 1.1 jakarta-tomcat/src/share/org/apache/tomcat/util/buf/Ascii.java Index: Ascii.java =================================================================== /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.tomcat.util.buf; /** * This class implements some basic ASCII character handling functions. * * @author [EMAIL PROTECTED] * @author James Todd [[EMAIL PROTECTED]] */ public final class Ascii { /* * Character translation tables. */ private static final byte[] toUpper = new byte[256]; private static final byte[] toLower = new byte[256]; /* * Character type tables. */ private static final boolean[] isAlpha = new boolean[256]; private static final boolean[] isUpper = new boolean[256]; private static final boolean[] isLower = new boolean[256]; private static final boolean[] isWhite = new boolean[256]; private static final boolean[] isDigit = new boolean[256]; /* * Initialize character translation and type tables. */ static { for (int i = 0; i < 256; i++) { toUpper[i] = (byte)i; toLower[i] = (byte)i; } for (int lc = 'a'; lc <= 'z'; lc++) { int uc = lc + 'A' - 'a'; toUpper[lc] = (byte)uc; toLower[uc] = (byte)lc; isAlpha[lc] = true; isAlpha[uc] = true; isLower[lc] = true; isUpper[uc] = true; } isWhite[ ' '] = true; isWhite['\t'] = true; isWhite['\r'] = true; isWhite['\n'] = true; isWhite['\f'] = true; isWhite['\b'] = true; for (int d = '0'; d <= '9'; d++) { isDigit[d] = true; } } /** * Returns the upper case equivalent of the specified ASCII character. */ public static int toUpper(int c) { return toUpper[c & 0xff] & 0xff; } /** * Returns the lower case equivalent of the specified ASCII character. */ public static int toLower(int c) { return toLower[c & 0xff] & 0xff; } /** * Returns true if the specified ASCII character is upper or lower case. */ public static boolean isAlpha(int c) { return isAlpha[c & 0xff]; } /** * Returns true if the specified ASCII character is upper case. */ public static boolean isUpper(int c) { return isUpper[c & 0xff]; } /** * Returns true if the specified ASCII character is lower case. */ public static boolean isLower(int c) { return isLower[c & 0xff]; } /** * Returns true if the specified ASCII character is white space. */ public static boolean isWhite(int c) { return isWhite[c & 0xff]; } /** * Returns true if the specified ASCII character is a digit. */ public static boolean isDigit(int c) { return isDigit[c & 0xff]; } /** * Parses an unsigned integer from the specified subarray of bytes. * @param b the bytes to parse * @param off the start offset of the bytes * @param len the length of the bytes * @exception NumberFormatException if the integer format was invalid */ public static int parseInt(byte[] b, int off, int len) throws NumberFormatException { int c; if (b == null || len <= 0 || !isDigit(c = b[off++])) { throw new NumberFormatException(); } int n = c - '0'; while (--len > 0) { if (!isDigit(c = b[off++])) { throw new NumberFormatException(); } n = n * 10 + c - '0'; } return n; } public static int parseInt(char[] b, int off, int len) throws NumberFormatException { int c; if (b == null || len <= 0 || !isDigit(c = b[off++])) { throw new NumberFormatException(); } int n = c - '0'; while (--len > 0) { if (!isDigit(c = b[off++])) { throw new NumberFormatException(); } n = n * 10 + c - '0'; } return n; } } 1.1 jakarta-tomcat/src/share/org/apache/tomcat/util/buf/Base64.java Index: Base64.java =================================================================== /* * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/buf/Base64.java,v 1.1 2001/02/20 03:12:13 costin Exp $ * $Revision: 1.1 $ * $Date: 2001/02/20 03:12:13 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.tomcat.util.buf; /** * This class provides encode/decode for RFC 2045 Base64 as * defined by RFC 2045, N. Freed and N. Borenstein. * RFC 2045: Multipurpose Internet Mail Extensions (MIME) * Part One: Format of Internet Message Bodies. Reference * 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt * This class is used by XML Schema binary format validation * * @author Jeffrey Rodriguez * @version $Revision: 1.1 $ $Date: 2001/02/20 03:12:13 $ */ public final class Base64 { static private final int BASELENGTH = 255; static private final int LOOKUPLENGTH = 63; static private final int TWENTYFOURBITGROUP = 24; static private final int EIGHTBIT = 8; static private final int SIXTEENBIT = 16; static private final int SIXBIT = 6; static private final int FOURBYTE = 4; static private final byte PAD = ( byte ) '='; static private byte [] base64Alphabet = new byte[BASELENGTH]; static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH]; static { for (int i = 0; i<BASELENGTH; i++ ) { base64Alphabet[i] = -1; } for ( int i = 'Z'; i >= 'A'; i-- ) { base64Alphabet[i] = (byte) (i-'A'); } for ( int i = 'z'; i>= 'a'; i--) { base64Alphabet[i] = (byte) ( i-'a' + 26); } for ( int i = '9'; i >= '0'; i--) { base64Alphabet[i] = (byte) (i-'0' + 52); } base64Alphabet['+'] = 62; base64Alphabet['/'] = 63; for (int i = 0; i<=25; i++ ) lookUpBase64Alphabet[i] = (byte) ('A'+i ); for (int i = 26, j = 0; i<=51; i++, j++ ) lookUpBase64Alphabet[i] = (byte) ('a'+ j ); for (int i = 52, j = 0; i<=61; i++, j++ ) lookUpBase64Alphabet[i] = (byte) ('0' + j ); } static boolean isBase64( byte octect ) { //shall we ignore white space? JEFF?? return(octect == PAD || base64Alphabet[octect] != -1 ); } static boolean isArrayByteBase64( byte[] arrayOctect ) { int length = arrayOctect.length; if ( length == 0 ) return false; for ( int i=0; i < length; i++ ) { if ( Base64.isBase64( arrayOctect[i] ) == false) return false; } return true; } /** * Encodes hex octects into Base64 * * @param binaryData Array containing binaryData * @return Encoded Base64 array */ public static byte[] encode( byte[] binaryData ) { int lengthDataBits = binaryData.length*EIGHTBIT; int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP; int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP; byte encodedData[] = null; if ( fewerThan24bits != 0 ) //data not divisible by 24 bit encodedData = new byte[ (numberTriplets + 1 )*4 ]; else // 16 or 8 bit encodedData = new byte[ numberTriplets*4 ]; byte k=0, l=0, b1=0,b2=0,b3=0; int encodedIndex = 0; int dataIndex = 0; int i = 0; for ( i = 0; i<numberTriplets; i++ ) { dataIndex = i*3; b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex + 1]; b3 = binaryData[dataIndex + 2]; l = (byte)(b2 & 0x0f); k = (byte)(b1 & 0x03); encodedIndex = i*4; encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; encodedData[encodedIndex+1] = lookUpBase64Alphabet[(b2 >>4 ) | ( k<<4 )]; encodedData[encodedIndex+2] = lookUpBase64Alphabet[ (l <<2 ) | ( b3>>6)]; encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ]; } // form integral number of 6-bit groups dataIndex = i*3; encodedIndex = i*4; if (fewerThan24bits == EIGHTBIT ) { b1 = binaryData[dataIndex]; k = (byte) ( b1 &0x03 ); encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ]; encodedData[encodedIndex + 2] = PAD; encodedData[encodedIndex + 3] = PAD; } else if ( fewerThan24bits == SIXTEENBIT ) { b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex +1 ]; l = ( byte ) ( b2 &0x0f ); k = ( byte ) ( b1 &0x03 ); encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ (b2 >>4 ) | ( k<<4 )]; encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ]; encodedData[encodedIndex + 3] = PAD; } return encodedData; } /** * Decodes Base64 data into octects * * @param binaryData Byte array containing Base64 data * @return Array containind decoded data. */ public byte[] decode( byte[] base64Data ) { int numberQuadruple = base64Data.length/FOURBYTE; byte decodedData[] = null; byte b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0; // Throw away anything not in base64Data // Adjust size int encodedIndex = 0; int dataIndex = 0; decodedData = new byte[ numberQuadruple*3 + 1 ]; for (int i = 0; i<numberQuadruple; i++ ) { dataIndex = i*4; marker0 = base64Data[dataIndex +2]; marker1 = base64Data[dataIndex +3]; b1 = base64Alphabet[base64Data[dataIndex]]; b2 = base64Alphabet[base64Data[dataIndex +1]]; if ( marker0 != PAD && marker1 != PAD ) { //No PAD e.g 3cQl b3 = base64Alphabet[ marker0 ]; b4 = base64Alphabet[ marker1 ]; decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ; decodedData[encodedIndex+1] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ); decodedData[encodedIndex+2] = (byte)( b3<<6 | b4 ); } else if ( marker0 == PAD ) { //Two PAD e.g. 3c[Pad][Pad] decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ; decodedData[encodedIndex+1] = (byte)((b2 & 0xf)<<4 ); decodedData[encodedIndex+2] = (byte) 0; } else if ( marker1 == PAD ) { //One PAD e.g. 3cQ[Pad] b3 = base64Alphabet[ marker0 ]; decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ); decodedData[encodedIndex+1] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ); decodedData[encodedIndex+2] = (byte)( b3<<6); } encodedIndex += 3; } return decodedData; } static final int base64[]= { 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 }; public static String base64Decode( String orig ) { char chars[]=orig.toCharArray(); StringBuffer sb=new StringBuffer(); int i=0; int shift = 0; // # of excess bits stored in accum int acc = 0; for (i=0; i<chars.length; i++) { int v = base64[ chars[i] & 0xFF ]; if ( v >= 64 ) { if( chars[i] != '=' ) System.out.println("Wrong char in base64: " + chars[i]); } else { acc= ( acc << 6 ) | v; shift += 6; if ( shift >= 8 ) { shift -= 8; sb.append( (char) ((acc >> shift) & 0xff)); } } } return sb.toString(); } } 1.1 jakarta-tomcat/src/share/org/apache/tomcat/util/buf/ByteChunk.java Index: ByteChunk.java =================================================================== /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.tomcat.util.buf; import java.text.*; import java.util.*; import java.io.Serializable; /** * This class is used to represent a chunk of bytes, and * utilities to manipulate byte[]. * * In a server it is very important to be able to operate on * the original byte[] without converting everything to chars. * Some protocols are ASCII only, and some allow different * non-UNICODE encodings. The encoding is not known beforehand, * and can even change during the execution of the protocol. * ( for example a multipart message may have parts with different * encoding ) * * For HTTP it is not very clear how the encoding of RequestURI * and mime values can be determined, but it is a great advantage * to be able to parse the request without converting to string. * * @author [EMAIL PROTECTED] * @author James Todd [[EMAIL PROTECTED]] * @author Costin Manolache */ public final class ByteChunk implements Cloneable, Serializable { // byte[] private byte[] bytes; private int bytesOff; private int bytesLen; private String enc; private boolean isSet=false; /** * Creates a new, uninitialized ByteChunk object. */ public ByteChunk() { } public ByteChunk getClone() { try { return (ByteChunk)this.clone(); } catch( Exception ex) { return null; } } public boolean isNull() { return ! isSet; // bytes==null; } /** * Resets the message bytes to an uninitialized state. */ public void recycle() { bytes = null; enc=null; isSet=false; } /** * Sets the message bytes to the specified subarray of bytes. * * @param b the ascii bytes * @param off the start offset of the bytes * @param len the length of the bytes */ public void setBytes(byte[] b, int off, int len) { bytes = b; bytesOff = off; bytesLen = len; isSet=true; } public void setEncoding( String enc ) { this.enc=enc; } // convert an int to byte[] public void setInt(int i) { // XXX TODO } // -------------------- Conversion and getters -------------------- public static boolean isUTF8Compatible(String enc) { if( enc==null ) return true; // add known encodings return false; } public String toString() { if (null == bytes) { return null; } String strValue=null; try { if( enc==null ) strValue=toStringUTF8(); else { strValue=new String(bytes, bytesOff, bytesLen, enc); // this will display when we implement I18N System.out.println("Converting from bytes to string using " + enc + ":" + strValue ); } return strValue; } catch (java.io.UnsupportedEncodingException e) { return null; // can't happen } } private char[] conversionBuff; private String toStringUTF8() { if( conversionBuff==null || bytesLen > conversionBuff.length ) { conversionBuff=new char[bytesLen]; } int j=bytesOff; for( int i=0; i< bytesLen; i++ ) { conversionBuff[i]=(char)bytes[j++]; } return new String( conversionBuff, 0, bytesLen); } public int getInt() { return Ascii.parseInt(bytes, bytesOff,bytesLen); } // -------------------- /** * Returns the message bytes. */ public byte[] getBytes() { return bytes; } /** * Returns the start offset of the bytes. */ public int getOffset() { return bytesOff; } /** * Returns the length of the bytes. */ public int getLength() { return bytesLen; } // -------------------- equals -------------------- /** * Compares the message bytes to the specified String object. * @param s the String to compare * @return true if the comparison succeeded, false otherwise */ public boolean equals(String s) { // XXX ENCODING - this only works if encoding is UTF8-compat // ( ok for tomcat, where we compare ascii - header names, etc )!!! byte[] b = bytes; int blen = bytesLen; if (b == null || blen != s.length()) { return false; } int boff = bytesOff; for (int i = 0; i < blen; i++) { if (b[boff++] != s.charAt(i)) { return false; } } return true; } /** * Compares the message bytes to the specified String object. * @param s the String to compare * @return true if the comparison succeeded, false otherwise */ public boolean equalsIgnoreCase(String s) { byte[] b = bytes; int blen = bytesLen; if (b == null || blen != s.length()) { return false; } int boff = bytesOff; for (int i = 0; i < blen; i++) { if (Ascii.toLower(b[boff++]) != Ascii.toLower(s.charAt(i))) { return false; } } return true; } public boolean equals( ByteChunk bb ) { return equals( bb.getBytes(), bb.getOffset(), bb.getLength()); } public boolean equals( byte b2[], int off2, int len2) { byte b1[]=bytes; if( b1==null && b2==null ) return true; int len=bytesLen; if ( len2 != len || b1==null || b2==null ) return false; int off1 = bytesOff; while ( len-- > 0) { if (b1[off1++] != b2[off2++]) { return false; } } return true; } public boolean equals( CharChunk cc ) { return equals( cc.getChars(), cc.getOffset(), cc.getLength()); } public boolean equals( char c2[], int off2, int len2) { // XXX works only for enc compatible with ASCII/UTF !!! byte b1[]=bytes; if( c2==null && b1==null ) return true; if (b1== null || c2==null || bytesLen != len2 ) { return false; } int off1 = bytesOff; int len=bytesLen; while ( len-- > 0) { if ( (char)b1[off1++] != c2[off2++]) { return false; } } return true; } /** * Returns true if the message bytes starts with the specified string. * @param s the string */ public boolean startsWith(String s) { // Works only if enc==UTF byte[] b = bytes; int blen = s.length(); if (b == null || blen > bytesLen) { return false; } int boff = bytesOff; for (int i = 0; i < blen; i++) { if (b[boff++] != s.charAt(i)) { return false; } } return true; } /** * Returns true if the message bytes starts with the specified string. * @param s the string */ public boolean startsWithIgnoreCase(String s, int pos) { byte[] b = bytes; int len = s.length(); if (b == null || len+pos > bytesLen) { return false; } int off = bytesOff+pos; for (int i = 0; i < len; i++) { if (Ascii.toLower( b[off++] ) != Ascii.toLower( s.charAt(i))) { return false; } } return true; } // based on ap_unescape_url ( util.c, Apache2.0 ) public int unescapeURL() { int end=bytesOff+ bytesLen; int idx= indexOf( bytes, bytesOff, end, '%' ); if( idx<0) return 0; for( int j=idx; j<end; j++, idx++ ) { if( bytes[ j ] != '%' ) { bytes[idx]=bytes[j]; } else { // read next 2 digits if( j+2 >= end ) { // invalid return 400; // BAD_REQUEST } byte b1= bytes[j+1]; byte b2=bytes[j+2]; if( !isHexDigit( b1 ) || ! isHexDigit(b2 )) return 400; j+=2; int res=x2c( b1, b2 ); if( res=='/' || res=='\0' ) return 400; bytes[idx]=(byte)res; bytesLen-=2; } } return 0; } public static boolean isHexDigit( int c ) { return ( ( c>='0' && c<='9' ) || ( c>='a' && c<='f' ) || ( c>='A' && c<='F' )); } public static int x2c( byte b1, byte b2 ) { int digit= (b1>='A') ? ( (b1 & 0xDF)-'A') + 10 : (b1 -'0'); digit*=16; digit +=(b2>='A') ? ( (b2 & 0xDF)-'A') + 10 : (b2 -'0'); return digit; } // -------------------- Hash code -------------------- // normal hash. public int hash() { return hashBytes( bytes, bytesOff, bytesLen); } // hash ignoring case public int hashIgnoreCase() { return hashBytesIC( bytes, bytesOff, bytesLen ); } private static int hashBytes( byte bytes[], int bytesOff, int bytesLen ) { int max=bytesOff+bytesLen; byte bb[]=bytes; int code=0; for (int i = bytesOff; i < max ; i++) { code = code * 37 + bb[i]; } return code; } private static int hashBytesIC( byte bytes[], int bytesOff, int bytesLen ) { int max=bytesOff+bytesLen; byte bb[]=bytes; int code=0; for (int i = bytesOff; i < max ; i++) { code = code * 37 + Ascii.toLower(bb[i]); } return code; } /** * Returns true if the message bytes starts with the specified string. * @param s the string */ public int indexOf(char c, int starting) { return indexOf( bytes, bytesOff+starting, bytesOff+bytesLen, c); } public static int indexOf( byte bytes[], int off, int end, char qq ) { // Works only for UTF while( off < end ) { byte b=bytes[off]; if( b==qq ) return off; off++; } return -1; } /** Find a character, no side effects. * @returns index of char if found, -1 if not */ public static int findChar( byte buf[], int start, int end, char c ) { byte b=(byte)c; int offset = start; while (offset < end) { if (buf[offset] == b) { return offset; } offset++; } return -1; } /** Find a character, no side effects. * @returns index of char if found, -1 if not */ public static int findChars( byte buf[], int start, int end, byte c[] ) { int clen=c.length; int offset = start; while (offset < end) { for( int i=0; i<clen; i++ ) if (buf[offset] == c[i]) { return offset; } offset++; } return -1; } /** Find the first character != c * @returns index of char if found, -1 if not */ public static int findNotChars( byte buf[], int start, int end, byte c[] ) { int clen=c.length; int offset = start; boolean found; while (offset < end) { found=true; for( int i=0; i<clen; i++ ) { if (buf[offset] == c[i]) { found=false; break; } } if( found ) { // buf[offset] != c[0..len] return offset; } offset++; } return -1; } } 1.1 jakarta-tomcat/src/share/org/apache/tomcat/util/buf/CharChunk.java Index: CharChunk.java =================================================================== /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.tomcat.util.buf; import java.text.*; import java.util.*; import java.io.Serializable; /** * Utilities to manipluate char chunks. While String is * the easiest way to manipulate chars ( search, substrings, etc), * it is known to not be the most efficient solution - Strings are * designed as imutable and secure objects. * * @author [EMAIL PROTECTED] * @author James Todd [[EMAIL PROTECTED]] * @author Costin Manolache */ public final class CharChunk implements Cloneable, Serializable { // char[] private char chars[]; private int charsOff; private int charsLen; private boolean isSet=false; /** * Creates a new, uninitialized CharChunk object. */ public CharChunk() { } public CharChunk getClone() { try { return (CharChunk)this.clone(); } catch( Exception ex) { return null; } } public boolean isNull() { return !isSet; } /** * Resets the message bytes to an uninitialized state. */ public void recycle() { // chars=null; isSet=false; } public void setChars( char[] c, int off, int len ) { recycle(); chars=c; charsOff=off; charsLen=len; } // -------------------- Conversion and getters -------------------- public String toString() { if( chars==null ) return null; return new String( chars, charsOff, charsLen); } public int getInt() { return Ascii.parseInt(chars, charsOff, charsLen); } public char[] getChars() { return chars; } /** * Returns the start offset of the bytes. */ public int getOffset() { return charsOff; } /** * Returns the length of the bytes. */ public int getLength() { return charsLen; } // -------------------- equals -------------------- /** * Compares the message bytes to the specified String object. * @param s the String to compare * @return true if the comparison succeeded, false otherwise */ public boolean equals(String s) { char[] c = chars; int len = charsLen; if (c == null || len != s.length()) { return false; } int off = charsOff; for (int i = 0; i < len; i++) { if (c[off++] != s.charAt(i)) { return false; } } return true; } /** * Compares the message bytes to the specified String object. * @param s the String to compare * @return true if the comparison succeeded, false otherwise */ public boolean equalsIgnoreCase(String s) { char[] c = chars; int len = charsLen; if (c == null || len != s.length()) { return false; } int off = charsOff; for (int i = 0; i < len; i++) { if (Ascii.toLower( c[off++] ) != Ascii.toLower( s.charAt(i))) { return false; } } return true; } public boolean equals(CharChunk cc) { return equals( cc.getChars(), cc.getOffset(), cc.getLength()); } public boolean equals(char b2[], int off2, int len2) { char b1[]=chars; if( b1==null && b2==null ) return true; if (b1== null || b2==null || charsLen != len2) { return false; } int off1 = charsOff; int len=charsLen; while ( len-- > 0) { if (b1[off1++] != b2[off2++]) { return false; } } return true; } public boolean equals(byte b2[], int off2, int len2) { char b1[]=chars; if( b2==null && b1==null ) return true; if (b1== null || b2==null || charsLen != len2) { return false; } int off1 = charsOff; int len=charsLen; while ( len-- > 0) { if ( b1[off1++] != (char)b2[off2++]) { return false; } } return true; } /** * Returns true if the message bytes starts with the specified string. * @param s the string */ public boolean startsWith(String s) { char[] c = chars; int len = s.length(); if (c == null || len > charsLen) { return false; } int off = charsOff; for (int i = 0; i < len; i++) { if (c[off++] != s.charAt(i)) { return false; } } return true; } /** * Returns true if the message bytes starts with the specified string. * @param s the string */ public boolean startsWithIgnoreCase(String s, int pos) { char[] c = chars; int len = s.length(); if (c == null || len+pos > charsLen) { return false; } int off = charsOff+pos; for (int i = 0; i < len; i++) { if (Ascii.toLower( c[off++] ) != Ascii.toLower( s.charAt(i))) { return false; } } return true; } // -------------------- Hash code -------------------- // normal hash. public int hash() { int code=0; for (int i = charsOff; i < charsOff + charsLen; i++) { code = code * 37 + chars[i]; } return code; } // hash ignoring case public int hashIgnoreCase() { int code=0; for (int i = charsOff; i < charsOff + charsLen; i++) { code = code * 37 + Ascii.toLower(chars[i]); } return code; } public int indexOf(char c) { return indexOf( c, charsOff); } /** * Returns true if the message bytes starts with the specified string. * @param s the string */ public int indexOf(char c, int starting) { return indexOf( chars, charsOff+starting, charsOff+charsLen, c ); } public static int indexOf( char chars[], int off, int end, char qq ) { while( off < end ) { char b=chars[off]; if( b==qq ) return off; off++; } return -1; } // based on ap_unescape_url ( util.c, Apache2.0 ) public int unescapeURL() { int end=charsOff+ charsLen; int idx= indexOf( chars, charsOff, end, '%' ); if( idx<0) return 0; for( int j=idx; j<end; j++, idx++ ) { if( chars[ j ] != '%' ) { chars[idx]=chars[j]; } else { // read next 2 digits if( j+2 >= end ) { // invalid return 400; // BAD_REQUEST } char b1= chars[j+1]; char b2=chars[j+2]; if( !isHexDigit( b1 ) || ! isHexDigit(b2 )) return 400; j+=2; int res=x2c( b1, b2 ); if( res=='/' || res=='\0' ) return 400; chars[idx]=(char)res; charsLen-=2; } } return 0; } public static boolean isHexDigit( int c ) { return ( ( c>='0' && c<='9' ) || ( c>='a' && c<='f' ) || ( c>='A' && c<='F' )); } public static int x2c( char b1, char b2 ) { int digit= (b1>='A') ? ( (b1 & 0xDF)-'A') + 10 : (b1 -'0'); digit*=16; digit +=(b2>='A') ? ( (b2 & 0xDF)-'A') + 10 : (b2 -'0'); return digit; } /** * This method decodes the given urlencoded string. * * @param str the url-encoded string * @return the decoded string * @exception IllegalArgumentException If a '%' is not * followed by a valid 2-digit hex number. * * @author: cut & paste from JServ, much faster that previous tomcat impl */ public final static String unescapeURL(String str) { // old code //System.out.println("XXX old unescape URL "+ str); if (str == null) return null; // pay for what you use - unencoded requests will not get // less overhead // XXX this should be in the caller ? if( str.indexOf( '+' ) <0 && str.indexOf( '%' ) < 0 ) return str; StringBuffer dec = new StringBuffer(); // decoded string output int strPos = 0; int strLen = str.length(); dec.ensureCapacity(str.length()); while (strPos < strLen) { int laPos; // lookahead position // look ahead to next URLencoded metacharacter, if any for (laPos = strPos; laPos < strLen; laPos++) { char laChar = str.charAt(laPos); if ((laChar == '+') || (laChar == '%')) { break; } } // if there were non-metacharacters, copy them all as a block if (laPos > strPos) { dec.append(str.substring(strPos,laPos)); strPos = laPos; } // shortcut out of here if we're at the end of the string if (strPos >= strLen) { break; } // process next metacharacter char metaChar = str.charAt(strPos); if (metaChar == '+') { dec.append(' '); strPos++; continue; } else if (metaChar == '%') { // We throw the original exception - the super will deal with // it // try { dec.append((char)Integer. parseInt(str.substring(strPos + 1, strPos + 3),16)); strPos += 3; } } return dec.toString(); } } 1.1 jakarta-tomcat/src/share/org/apache/tomcat/util/buf/DateTool.java Index: DateTool.java =================================================================== /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.tomcat.util.buf; import java.io.IOException; import java.io.OutputStream; import java.util.*; import java.text.*; import org.apache.tomcat.util.res.StringManager; /** * Common place for date utils. * * @author [EMAIL PROTECTED] * @author Jason Hunter [[EMAIL PROTECTED]] * @author James Todd [[EMAIL PROTECTED]] * @author Costin Manolache */ public class DateTool { /** US locale - all HTTP dates are in english */ public final static Locale LOCALE_US = Locale.US; /** GMT timezone - all HTTP dates are on GMT */ public final static TimeZone GMT_ZONE = TimeZone.getTimeZone("GMT"); /** format for RFC 1123 date string -- "Sun, 06 Nov 1994 08:49:37 GMT" */ public final static String RFC1123_PATTERN = "EEE, dd MMM yyyyy HH:mm:ss z"; // format for RFC 1036 date string -- "Sunday, 06-Nov-94 08:49:37 GMT" private final static String rfc1036Pattern = "EEEEEEEEE, dd-MMM-yy HH:mm:ss z"; // format for C asctime() date string -- "Sun Nov 6 08:49:37 1994" private final static String asctimePattern = "EEE MMM d HH:mm:ss yyyyy"; /** Pattern used for old cookies */ public final static String OLD_COOKIE_PATTERN = "EEE, dd-MMM-yyyy HH:mm:ss z"; /** DateFormat to be used to format dates */ public final static DateFormat rfc1123Format = new SimpleDateFormat(RFC1123_PATTERN, LOCALE_US); /** DateFormat to be used to format old netscape cookies */ public final static DateFormat oldCookieFormat = new SimpleDateFormat(OLD_COOKIE_PATTERN, LOCALE_US); public final static DateFormat rfc1036Format = new SimpleDateFormat(rfc1036Pattern, LOCALE_US); public final static DateFormat asctimeFormat = new SimpleDateFormat(asctimePattern, LOCALE_US); static { rfc1123Format.setTimeZone(GMT_ZONE); oldCookieFormat.setTimeZone(GMT_ZONE); rfc1036Format.setTimeZone(GMT_ZONE); asctimeFormat.setTimeZone(GMT_ZONE); } private static StringManager sm = StringManager.getManager("org.apache.tomcat.resources"); public static long parseDate( MessageBytes value ) { return parseDate( value.toString()); } public static long parseDate( String dateString ) { Date date=null; try { date = DateTool.rfc1123Format.parse(dateString); return date.getTime(); } catch (ParseException e) { } try { date = DateTool.rfc1036Format.parse(dateString); return date.getTime(); } catch (ParseException e) { } try { date = DateTool.asctimeFormat.parse(dateString); return date.getTime(); } catch (ParseException pe) { } String msg = sm.getString("httpDate.pe", dateString); throw new IllegalArgumentException(msg); } } 1.1 jakarta-tomcat/src/share/org/apache/tomcat/util/buf/HexUtils.java Index: HexUtils.java =================================================================== /* * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/buf/HexUtils.java,v 1.1 2001/02/20 03:12:13 costin Exp $ * $Revision: 1.1 $ * $Date: 2001/02/20 03:12:13 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.tomcat.util.buf; import java.io.ByteArrayOutputStream; import org.apache.tomcat.util.res.StringManager; /** * Library of utility methods useful in dealing with converting byte arrays * to and from strings of hexadecimal digits. * * @author Craig R. McClanahan */ public final class HexUtils { // Code from Ajp11, from Apache's JServ // Table for HEX to DEC byte translation public static final int[] DEC = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 00, 01, 02, 03, 04, 05, 06, 07, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; /** * The string manager for this package. */ private static StringManager sm = StringManager.getManager("org.apache.tomcat.resources"); /** * Convert a String of hexadecimal digits into the corresponding * byte array by encoding each two hexadecimal digits as a byte. * * @param digits Hexadecimal digits representation * * @exception IllegalArgumentException if an invalid hexadecimal digit * is found, or the input string contains an odd number of hexadecimal * digits */ public static byte[] convert(String digits) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); for (int i = 0; i < digits.length(); i += 2) { char c1 = digits.charAt(i); if ((i+1) >= digits.length()) throw new IllegalArgumentException (sm.getString("hexUtil.odd")); char c2 = digits.charAt(i + 1); byte b = 0; if ((c1 >= '0') && (c1 <= '9')) b += ((c1 - '0') * 16); else if ((c1 >= 'a') && (c1 <= 'f')) b += ((c1 - 'a' + 10) * 16); else if ((c1 >= 'A') && (c1 <= 'F')) b += ((c1 - 'A' + 10) * 16); else throw new IllegalArgumentException (sm.getString("hexUtil.bad")); if ((c2 >= '0') && (c2 <= '9')) b += (c2 - '0'); else if ((c2 >= 'a') && (c2 <= 'f')) b += (c2 - 'a' + 10); else if ((c2 >= 'A') && (c2 <= 'F')) b += (c2 - 'A' + 10); else throw new IllegalArgumentException (sm.getString("hexUtil.bad")); baos.write(b); } return (baos.toByteArray()); } /** * Convert a byte array into a printable format containing a * String of hexadecimal digit characters (two per byte). * * @param bytes Byte array representation */ public static String convert(byte bytes[]) { StringBuffer sb = new StringBuffer(bytes.length * 2); for (int i = 0; i < bytes.length; i++) { sb.append(convertDigit((int) (bytes[i] >> 4))); sb.append(convertDigit((int) (bytes[i] & 0x0f))); } return (sb.toString()); } /** * Convert 4 hex digits to an int, and return the number of converted * bytes. * * @param hex Byte array containing exactly four hexadecimal digits * * @exception IllegalArgumentException if an invalid hexadecimal digit * is included */ public static int convert2Int( byte[] hex ) { // Code from Ajp11, from Apache's JServ // assert b.length==4 // assert valid data int len; if(hex.length < 4 ) return 0; if( DEC[hex[0]]<0 ) throw new IllegalArgumentException(sm.getString("hexUtil.bad")); len = DEC[hex[0]]; len = len << 4; if( DEC[hex[1]]<0 ) throw new IllegalArgumentException(sm.getString("hexUtil.bad")); len += DEC[hex[1]]; len = len << 4; if( DEC[hex[2]]<0 ) throw new IllegalArgumentException(sm.getString("hexUtil.bad")); len += DEC[hex[2]]; len = len << 4; if( DEC[hex[3]]<0 ) throw new IllegalArgumentException(sm.getString("hexUtil.bad")); len += DEC[hex[3]]; return len; } /** * [Private] Convert the specified value (0 .. 15) to the corresponding * hexadecimal digit. * * @param value Value to be converted */ private static char convertDigit(int value) { value &= 0x0f; if (value >= 10) return ((char) (value - 10 + 'a')); else return ((char) (value + '0')); } } 1.1 jakarta-tomcat/src/share/org/apache/tomcat/util/buf/MessageBytes.java Index: MessageBytes.java =================================================================== /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.tomcat.util.buf; import java.text.*; import java.util.*; import java.io.Serializable; // XXX XXX Need StringBuffer support ! /** * This class is used to represent a subarray of bytes in an HTTP message. * * @author [EMAIL PROTECTED] * @author James Todd [[EMAIL PROTECTED]] * @author Costin Manolache */ public final class MessageBytes implements Cloneable, Serializable { public static final String DEFAULT_CHAR_ENCODING="8859_1"; // primary type ( whatever is set as original value ) private int type = T_NULL; public static final int T_NULL = 0; public static final int T_STR = 1; public static final int T_BYTES = 2; public static final int T_CHARS = 3; private int hashCode=0; private boolean hasHashCode=false; private boolean caseSensitive=true; ByteChunk byteC=new ByteChunk(); CharChunk charC=new CharChunk(); // String private String strValue; private boolean hasStrValue=false; // efficient int and date // XXX used only for headers - shouldn't be // stored here. private int intValue; private boolean hasIntValue=false; private Date dateValue; private boolean hasDateValue=false; /** * Creates a new, uninitialized MessageBytes object. */ public MessageBytes() { } public void setCaseSenitive( boolean b ) { caseSensitive=b; } public MessageBytes getClone() { try { return (MessageBytes)this.clone(); } catch( Exception ex) { return null; } } public boolean isNull() { return byteC.isNull() && charC.isNull() && ! hasStrValue; // bytes==null && strValue==null; } /** * Resets the message bytes to an uninitialized state. */ public void recycle() { type=T_NULL; byteC.recycle(); charC.recycle(); strValue=null; caseSensitive=true; hasStrValue=false; hasHashCode=false; hasIntValue=false; hasDateValue=false; } /** * Sets the message bytes to the specified subarray of bytes. * @param b the ascii bytes * @param off the start offset of the bytes * @param len the length of the bytes */ public void setBytes(byte[] b, int off, int len) { recycle(); // a new value is set, cached values must reset byteC.setBytes( b, off, len ); type=T_BYTES; } public void setEncoding( String enc ) { if( !byteC.isNull() ) { // if the encoding changes we need to reset the converion results charC.recycle(); hasStrValue=false; } byteC.setEncoding(enc); } public void setChars( char[] c, int off, int len ) { recycle(); charC.setChars( c, off, len ); type=T_CHARS; } public void setString( String s ) { recycle(); strValue=s; hasStrValue=true; type=T_STR; } public void setTime(long t) { // XXX replace it with a byte[] tool recycle(); if( dateValue==null) dateValue=new Date(t); else dateValue.setTime(t); strValue=DateTool.rfc1123Format.format(dateValue); hasStrValue=true; hasDateValue=true; type=T_STR; } /** Set the buffer to the representation of an int */ public void setInt(int i) { // XXX replace it with a byte[] tool recycle(); strValue=String.valueOf( i ); intValue=i; hasIntValue=true; hasStrValue=true; type=T_STR; } // -------------------- Conversion and getters -------------------- public String toString() { if( hasStrValue ) return strValue; hasStrValue=true; switch (type) { case T_CHARS: strValue=charC.toString(); return strValue; case T_BYTES: strValue=byteC.toString(); return strValue; } return null; } public long getTime() { if( hasDateValue ) { if( dateValue==null) return -1; return dateValue.getTime(); } long l=DateTool.parseDate( this ); if( dateValue==null) dateValue=new Date(l); else dateValue.setTime(l); hasDateValue=true; return l; } /** Convert the buffer to an int, cache the value */ public int getInt() { if( hasIntValue ) return intValue; switch (type) { case T_BYTES: intValue=byteC.getInt(); break; default: intValue=Integer.parseInt(toString()); } hasIntValue=true; return intValue; } //---------------------------------------- public int getType() { return type; } /** * Returns the message bytes. */ public ByteChunk getByteChunk() { return byteC; } public CharChunk getCharChunk() { return charC; } // Convert to bytes !!! public void toBytes() { // XXX todo - not used } public void toChars() { if( ! charC.isNull() ) { return; } // inefficient toString(); char cc[]=strValue.toCharArray(); charC.setChars(cc, 0, cc.length); } /** * Returns the length of the buffer. */ public int getLength() { if(type==T_BYTES) return byteC.getLength(); if(type==T_CHARS) { return charC.getLength(); } if(type==T_STR) return strValue.length(); toString(); return strValue.length(); } // -------------------- equals -------------------- /** * Compares the message bytes to the specified String object. * @param s the String to compare * @return true if the comparison succeeded, false otherwise */ public boolean equals(String s) { if( ! caseSensitive ) return equalsIgnoreCase( s ); switch (type) { case T_STR: if( strValue==null && s!=null) return false; return strValue.equals( s ); case T_CHARS: return charC.equals( s ); case T_BYTES: return byteC.equals( s ); default: return false; } } /** * Compares the message bytes to the specified String object. * @param s the String to compare * @return true if the comparison succeeded, false otherwise */ public boolean equalsIgnoreCase(String s) { switch (type) { case T_STR: if( strValue==null && s!=null) return false; return strValue.equalsIgnoreCase( s ); case T_CHARS: return charC.equalsIgnoreCase( s ); case T_BYTES: return byteC.equalsIgnoreCase( s ); default: return false; } } public int unescapeURL() { switch (type) { case T_STR: if( strValue==null ) return 0; strValue=CharChunk.unescapeURL( strValue ); case T_CHARS: return charC.unescapeURL(); case T_BYTES: return byteC.unescapeURL(); } return 0; } public boolean equals(MessageBytes mb) { switch (type) { case T_STR: return mb.equals( strValue ); } if( mb.type != T_CHARS && mb.type!= T_BYTES ) { // it's a string or int/date string value return equals( mb.toString() ); } // mb is either CHARS or BYTES. // this is either CHARS or BYTES // Deal with the 4 cases ( in fact 3, one is simetric) if( mb.type == T_CHARS && type==T_CHARS ) { return charC.equals( mb.charC ); } if( mb.type==T_BYTES && type== T_BYTES ) { return byteC.equals( mb.byteC ); } if( mb.type== T_CHARS && type== T_BYTES ) { return byteC.equals( mb.charC ); } if( mb.type== T_BYTES && type== T_CHARS ) { return mb.byteC.equals( charC ); } // can't happen return true; } /** * Returns true if the message bytes starts with the specified string. * @param s the string */ public boolean startsWith(String s) { switch (type) { case T_STR: return strValue.startsWith( s ); case T_CHARS: return charC.startsWith( s ); case T_BYTES: return byteC.startsWith( s ); default: return false; } } /** * Returns true if the message bytes starts with the specified string. * @param s the string */ public boolean startsWithIgnoreCase(String s, int pos) { switch (type) { case T_STR: if( strValue==null ) return false; if( strValue.length() < pos + s.length() ) return false; for( int i=0; i<s.length(); i++ ) { if( Ascii.toLower( s.charAt( i ) ) != Ascii.toLower( strValue.charAt( pos + i ))) { return false; } } return true; case T_CHARS: return charC.startsWithIgnoreCase( s, pos ); case T_BYTES: return byteC.startsWithIgnoreCase( s, pos ); default: return false; } } // -------------------- Hash code -------------------- public int hashCode() { if( hasHashCode ) return hashCode; int code = 0; if( caseSensitive ) code=hash(); else code=hashIgnoreCase(); hashCode=code; hasHashCode=true; return code; } // normal hash. private int hash() { int code=0; switch (type) { case T_STR: // We need to use the same hash function for (int i = 0; i < strValue.length(); i++) { code = code * 37 + strValue.charAt( i ); } return code; case T_CHARS: return charC.hash(); case T_BYTES: return byteC.hash(); default: return 0; } } // hash ignoring case private int hashIgnoreCase() { int code=0; switch (type) { case T_STR: for (int i = 0; i < strValue.length(); i++) { code = code * 37 + Ascii.toLower(strValue.charAt( i )); } return code; case T_CHARS: return charC.hashIgnoreCase(); case T_BYTES: return byteC.hashIgnoreCase(); default: return 0; } } public int indexOf(char c) { return indexOf( c, 0); } // Inefficient initial implementation. Will be replaced on the next // round of tune-up public int indexOf(String s, int starting) { toString(); return strValue.indexOf( s, starting ); } public int indexOfIgnoreCase(String s, int starting) { toString(); String upper=strValue.toUpperCase(); String sU=s.toUpperCase(); return upper.indexOf( sU, starting ); } /** * Returns true if the message bytes starts with the specified string. * @param s the string */ public int indexOf(char c, int starting) { switch (type) { case T_STR: return strValue.indexOf( c, starting ); case T_CHARS: return charC.indexOf( c, starting); case T_BYTES: return byteC.indexOf( c, starting ); default: return -1; } } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]