/* jcifs smb client library in Java * Copyright (C) 2000 "Michael B. Allen" <jcifs at samba dot org> * "Christopher R. Hertel" <jcifs at samba dot org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jcifs.netbios; import java.io.UnsupportedEncodingException; import jcifs.Config; import jcifs.util.Hexdump; public class Name { private static final int TYPE_OFFSET = 31; private static final int SCOPE_OFFSET = 33; private static final String DEFAULT_SCOPE = Config.getProperty( "jcifs.netbios.scope" ); static final String OEM_ENCODING = Config.getProperty( "jcifs.encoding", System.getProperty( "file.encoding" )); public String name, scope; public int hexCode; int srcHashCode; /* srcHashCode must be set by name resolution * routines before entry into addressCache */ Name() { } public Name( String name, int hexCode, String scope ) { if( name.length() > 15 ) { name = name.substring( 0, 15 ); } this.name = name.toUpperCase(); this.hexCode = hexCode; this.scope = scope != null && scope.length() > 0 ? scope : DEFAULT_SCOPE; this.srcHashCode = 0; } int writeWireFormat( byte[] dst, int dstIndex ) { // write 0x20 in first byte dst[dstIndex] = 0x20; // write name try { byte tmp[] = name.getBytes( Name.OEM_ENCODING ); int i; for( i = 0; i < tmp.length; i++ ) { dst[dstIndex + ( 2 * i + 1 )] = (byte)((( tmp[i] & 0xF0 ) >> 4 ) + 0x41 ); dst[dstIndex + ( 2 * i + 2 )] = (byte)(( tmp[i] & 0x0F ) + 0x41 ); } for( ; i < 15; i++ ) { dst[dstIndex + ( 2 * i + 1 )] = (byte)0x43; dst[dstIndex + ( 2 * i + 2 )] = (byte)0x41; } dst[dstIndex + TYPE_OFFSET] = (byte)((( hexCode & 0xF0 ) >> 4 ) + 0x41 ); dst[dstIndex + TYPE_OFFSET + 1] = (byte)(( hexCode & 0x0F ) + 0x41 ); } catch( UnsupportedEncodingException uee ) { } return SCOPE_OFFSET + writeScopeWireFormat( dst, dstIndex + SCOPE_OFFSET ); } int readWireFormat( byte[] src, int srcIndex ) { byte tmp[] = new byte[SCOPE_OFFSET]; int length = 15; for( int i = 0; i < 15; i++ ) { tmp[i] = (byte)((( src[srcIndex + ( 2 * i + 1 )] & 0xFF ) - 0x41 ) << 4 ); tmp[i] |= (byte)((( src[srcIndex + ( 2 * i + 2 )] & 0xFF ) - 0x41 ) & 0x0F ); if( tmp[i] != (byte)' ' ) { length = i + 1; } } try { name = new String( tmp, 0, length, Name.OEM_ENCODING ); } catch( UnsupportedEncodingException uee ) { } hexCode = (( src[srcIndex + TYPE_OFFSET] & 0xFF ) - 0x41 ) << 4; hexCode |= (( src[srcIndex + TYPE_OFFSET + 1] & 0xFF ) - 0x41 ) & 0x0F; return SCOPE_OFFSET + readScopeWireFormat( src, srcIndex + SCOPE_OFFSET ); } int writeScopeWireFormat( byte[] dst, int dstIndex ) { if( scope == null ) { dst[dstIndex] = (byte)0x00; return 1; } // copy new scope in dst[dstIndex++] = (byte)'.'; try { System.arraycopy( scope.getBytes( Name.OEM_ENCODING ), 0, dst, dstIndex, scope.length() ); } catch( UnsupportedEncodingException uee ) { } dstIndex += scope.length(); dst[dstIndex++] = (byte)0x00; // now go over scope backwards converting '.' to label length int i = dstIndex - 2; int e = i - scope.length(); int c = 0; do { if( dst[i] == '.' ) { dst[i] = (byte)c; c = 0; } else { c++; } } while( i-- > e ); return scope.length() + 2; } int readScopeWireFormat( byte[] src, int srcIndex ) { int start = srcIndex; int n; StringBuffer sb; if(( n = src[srcIndex++] & 0xFF ) == 0 ) { scope = null; return 1; } try { sb = new StringBuffer( new String( src, srcIndex, n, Name.OEM_ENCODING )); srcIndex += n; while(( n = src[srcIndex++] & 0xFF ) != 0 ) { sb.append( '.' ).append( new String( src, srcIndex, n, Name.OEM_ENCODING )); srcIndex += n; } scope = sb.toString(); } catch( UnsupportedEncodingException uee ) { } return srcIndex - start; } public int hashCode() { int result; result = name.hashCode(); result += 65599 * hexCode; result += 65599 * srcHashCode; /* hashCode is different depending * on where it came from */ if( scope != null && scope.length() != 0 ) { result += scope.hashCode(); } return result; } public boolean equals( Object obj ) { Name n; if( !( obj instanceof Name )) { return false; } n = (Name)obj; if( scope == null && n.scope == null ) { return name.equals( n.name ) && hexCode == n.hexCode; } return name.equals( n.name ) && hexCode == n.hexCode && scope.equals( n.scope ); } public String toString() { StringBuffer sb = new StringBuffer(); String n = name; // fix MSBROWSE name if( n == null ) { n = "null"; } else if( n.charAt( 0 ) == 0x01 ) { char c[] = n.toCharArray(); c[0] = '.'; c[1] = '.'; c[14] = '.'; n = new String( c ); } sb.append( n ).append( "<" ).append( Hexdump.toHexString( hexCode, 2 )).append( ">" ); if( scope != null ) { sb.append( "." ).append( scope ); } return sb.toString(); } }