/* jcifs smb client library in Java
* Copyright (C) 2000 "Michael B. Allen" <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 com.knowgate.jcifs.smb;
import com.knowgate.jcifs.Config;
import com.knowgate.debug.DebugFile;
class SmbTree {
private static final String DEFAULT_SERVICE = Config.getProperty( "jcifs.smb.client.serviceType", "?????" );
private int tid;
private String share;
String service = DEFAULT_SERVICE;
SmbSession session;
boolean treeConnected, inDfs;
SmbTree( SmbSession session, String share, String service ) {
this.session = session;
this.share = share.toUpperCase();
if( service != null && service.startsWith( "??" ) == false ) {
this.service = service;
}
}
boolean matches( String share, String service ) {
return this.share.equalsIgnoreCase( share ) &&
( service == null || service.startsWith( "??" ) ||
this.service.equalsIgnoreCase( service ));
}
void sendTransaction( SmbComTransaction request,
SmbComTransactionResponse response ) throws SmbException {
// transactions are not batchable
treeConnect( null, null );
if( service.equals( "A:" ) == false ) {
switch( ((SmbComTransaction)request).subCommand & 0xFF ) {
case SmbComTransaction.NET_SHARE_ENUM:
case SmbComTransaction.NET_SERVER_ENUM2:
case SmbComTransaction.NET_SERVER_ENUM3:
case SmbComTransaction.TRANS_PEEK_NAMED_PIPE:
case SmbComTransaction.TRANS_WAIT_NAMED_PIPE:
case SmbComTransaction.TRANS_CALL_NAMED_PIPE:
case SmbComTransaction.TRANS_TRANSACT_NAMED_PIPE:
case SmbComTransaction.TRANS2_GET_DFS_REFERRAL:
break;
default:
throw new SmbException( "Invalid operation for " + service + " service" );
}
}
request.tid = tid;
if( inDfs && request.path != null && request.path.length() > 0 ) {
request.path = '\\' + session.transport().tconHostName + '\\' + share + request.path;
}
session.sendTransaction( request, response );
}
void send( ServerMessageBlock request,
ServerMessageBlock response ) throws SmbException {
if( response != null ) {
response.received = false;
}
treeConnect( request, response );
if( request == null || (response != null && response.received )) {
return;
}
if( service.equals( "A:" ) == false ) {
switch( request.command ) {
case ServerMessageBlock.SMB_COM_OPEN_ANDX:
case ServerMessageBlock.SMB_COM_NT_CREATE_ANDX:
case ServerMessageBlock.SMB_COM_READ_ANDX:
case ServerMessageBlock.SMB_COM_WRITE_ANDX:
case ServerMessageBlock.SMB_COM_CLOSE:
case ServerMessageBlock.SMB_COM_TREE_DISCONNECT:
break;
default:
throw new SmbException( "Invalid operation for " + service + " service" );
}
}
request.tid = tid;
if( inDfs && request.path != null && request.path.length() > 0 ) {
request.flags2 = ServerMessageBlock.FLAGS2_RESOLVE_PATHS_IN_DFS;
request.path = '\\' + session.transport().tconHostName + '\\' + share + request.path;
}
session.send( request, response );
}
void treeConnect( ServerMessageBlock andx,
ServerMessageBlock andxResponse ) throws SmbException {
String unc;
synchronized( session.transport() ) {
if( treeConnected ) {
return;
}
/* The hostname to use in the path is only known for
* sure if the NetBIOS session has been successfully
* established.
*/
session.transport.negotiate();
unc = "\\\\" + session.transport.tconHostName + '\\' + share;
/*
* Tree Connect And X Request / Response
*/
if( DebugFile.trace )
DebugFile.writeln( "treeConnect: unc=" + unc + ",service=" + service );
SmbComTreeConnectAndXResponse response =
new SmbComTreeConnectAndXResponse( andxResponse );
SmbComTreeConnectAndX request =
new SmbComTreeConnectAndX( session, unc, service, andx );
session.send( request, response );
tid = response.tid;
service = response.service;
inDfs = response.shareIsInDfs;
treeConnected = true;
}
}
void treeDisconnect( boolean inError ) {
synchronized( session.transport ) {
if( treeConnected == false ) {
return;
}
if( !inError ) {
try {
send( new SmbComTreeDisconnect(), null );
} catch( SmbException se ) {
}
}
treeConnected = false;
}
}
public String toString() {
return "SmbTree[share=" + share +
",service=" + service +
",tid=" + tid +
",inDfs=" + inDfs +
",treeConnected=" + treeConnected + "]";
}
}