-Mon Jan 19 22:06:54 EST 2004
-jcifs-0.7.19 released
+Tue Feb 10 23:44:45 EST 2004
+jcifs-0.8.0 released
+
+This completes the 0.8 beta cycle. There is no technical difference between
+this release and 0.8.0b1.
+
+Mon Nov 24 04:06:55 EST 2003
+jcifs-0.8.0b1 released
+
+Some work on NetworkExplorer and DFS referrals has been performed but it
+still doesn't work right. Currently if a DFS referral is encountered the
+DfsReferral will be thrown into NetworkExplorer which then sends an HTTP
+redirect. The problem is that when the SmbTransports close after being idle
+for jcifs.smb.client.soTimeout, attempting to access servers with NPAs in
+the session can cause a succession of authentication failures which on my
+network equates to your account being locked (like mine is right now :)
+
+An artifact of this work is that NetworkExplorer will store the
+NtlmPasswordAuthentication objects in the HttpSession as npa-servername
+where 'servername' is the name of the server that supplied the challenge.
+
+And all of the fixes to the 0.7 series since 0.7.15 are included:
It was discovered that SmbComNTCreateAndX as well as SmbComReadAndx
commands did not calculate MAC response signitures properly. In one case a
optimization, was not being properly factored into the signature. These
issues have been fixed.
-Wed Jan 7 19:24:59 EST 2004
-jcifs-0.7.18 released
-
Only SMBs that follow authentication need to be actually signed if SMB
signing is enabled. Because it was assumed that SMBs would follow
authentication an Exception was coded to be thrown if password hashes are
will now work with these containers albeit possibly not to their greatest
potential.
-
-Tue Dec 23 03:43:15 EST 2003
-jcifs-0.7.17 released
-
JCIFS will now suppress the harmess "exception reading from socket input"
message being written to the log. Specifically when using the NTLM HTTP
Filter under load jCIFS would periodically write exceptions to the log like
socket to the server. This is harmless. JCIFS will automatically reconnect
and proceed as usual.
-Dec 9 18:13:25 EST 2003
-jcifs-0.7.16 released
-
If NT SMBs are not negotiated jCIFS will now use SMB_COM_WRITE as opposed
to SMB_COM_WRITE_ANDX. This was done to support NetWare 6 which apparently
does not implement this ANDX command.
+jcifs-0.8.0b released
+
+This is the first beta release of the 0.8 series. There have been
+significant additions to this package. The most noteable is Distributed
+FileSystem (DFS) support. This client fully supports DFS with deep paths,
+multiple redirects, you name it. This functionality required pervasive
+changes so DFS users should proceed with caution and report any problems to
+the mailing list. Support for setting file attributes has been added as is
+the long awaited RandomAccessFile.
+
+o DFS - DFS support is thorough. All DFS operations are completely
+ transparent. It Just Works. The client can be redirected an infinate
+ number of times. It will reuse mappings established by other callers.
+ Components of a path that do not fall within the DFS space and deep paths
+ are handled properly. Also, note the new <tt>getDfsPath</tt> method can
+ be used to determine if a file or directory falls within a DFS space.
+ This support required pervasive changes so proceed with caution and run
+ your unit tests with files that span DFS volumes. Please report any
+ problems to the jCIFS mailing list.
+
+o Random Access Files - The <tt>SmbRandomAccessFile</tt> class has been
+ added. All features of the analygous <tt>java.io.RandomAccessFile</tt>
+ class are supported and should function as a drop in replacement. Notice
+ it is now possible to set the size of a file with the
+ <tt>SmbRandomAccessFile.setLength()</tt> method.
+
+o File Filters - Support for <tt>SmbFilenameFilter</tt> and
+ <tt>SmbFileFilter</tt> is complete. Because CIFS servers can accept
+ attributes and a wildcard expression for filtering entries on the server
+ side, a <tt>DosFileFilter</tt> is provided that will accept these
+ parameters and pass them to the server. The <tt>DosFileFilter</tt> can
+ also be extended to create highly sophisticated and efficient file
+ filters. Because of this work the <tt>list()</tt> and <tt>listFiles</tt>
+ methods have been refactored and actually reduced in size.
+
+o Complete copyTo - The <tt>SmbFile.copyTo</tt> operation will now copy all
+ file attributes as well as create and last write times. Directories
+ copied using this method should be indistinquishable from the original
+ minus ACLs. This method can now copy entire shares whereas previously
+ only sud-directories could be specified.
+
+o Setting Attributes and Times - It is now possible to set file attribites,
+ the create time, and last write time in a variety of ways. The new
+ methods are <tt>setCreateTime</tt>, <tt>setLastModified</tt>,
+ <tt>getAttributes</tt>, <tt>setAttributes</tt>, <tt>setReadOnly</tt>, and
+ <tt>setReadWrite</tt>.
+
+o Complete Delete - The <tt>SmbFile.delete()</tt> method will now
+ completely delete directories regardless of wheather or not there are
+ read-only files in them.
+
+o The createNewFile Method - An <tt>SmbFile.createFile</tt> method has been
+ added.
+
Thu Oct 23 01:18:29 EDT 2003
jcifs-0.7.15 released
Wed Sep 17 21:21:31 EDT 2003
+jcifs-0.7.13 released
+
JCIFS now supports SMB signing. If a server requires SMB signing (Windows
2003 requires it by default) or if the server supports signing and the
jcifs.smb.client.signingPreferred property is true signing will be
Mon Sep 1 19:04:11 EDT 2003
+jcifs-0.7.12 released
+
CIFS permits multiple users to be logged in over the same transport
(socket). JCIFS takes advantage of this and reuses existing transports
whenever possible. It was reported that a user using the NTLM Servlet
Thu Jul 10 22:07:09 EDT 2003
+jcifs-0.7.11 released
+
Support for LMv2 authentication has been added. See the Overview page in
the API documentation regarding the jcifs.smb.lmCompatibility property.
Some additonal "cleanup" has also been performed. One side-effect that
Thu Jul 3 20:59:25 EDT 2003
+jcifs-0.7.10 released
+
There have been two small bug fixes in the SMB layer; the count field in
the SMB_COM_WRITE_ANDX response was being ignored. Apparently the count
specified in the request is always honored or we would have seen plenty of
Thu Jun 12 00:18:05 EDT 2003
+jcifs-0.7.9 released
+
It was discovered that if a server responds to the NBT session setup but
not to the SMB_COM_NEGOTIATE request the client will hang indefinately.
This is not a likely thing to occur because servers usually respond or not
-Mon Jan 19 22:06:54 EST 2004
-jcifs-0.7.19 released
+Tue Feb 10 23:44:45 EST 2004
+jcifs-0.8.0 released
-SMB signature varification was not working properly and has been fixed.
+This completes the 0.8 beta cycle. There is no technical difference between
+this release and 0.8.0b1.
-Wed Jan 7 19:24:59 EST 2004
-jcifs-0.7.18 released
+Tue Feb 3 00:54:04 EST 2004
+jcifs-0.8.0b1 released
-The NTLM HTTP Authentication Filter should now work with domain controllers
-that negotiate signing as well as without generating the benign "exception
-reading from socket input" Exception. Also, the NtlmPasswordAuthentication
-class is now Serializable to increase compatability with certain Servlet
-containers.
+There has been some work in trying to get NetworkExplorer to work with DFS
+and all fixes from the 0.7 series since 0.7.15 have been incorporated.
-Tue Dec 23 03:43:15 EST 2003
-jcifs-0.7.17 released
+Mon Nov 24 04:06:55 EST 2003
-JCIFS will now suppress the harmess "exception reading from socket input"
-message being written to the log.
+jcifs-0.8.0b released
-Tue Dec 9 18:13:25 EST 2003
-jcifs-0.7.16 released
+This is the first beta release of the 0.8 series. There have been
+significant additions to this package including DFS support, random access
+files, filename and file filters, setting attributes and times, and copyTo
+and delete improvements.
-An issue regarding writing to NetWare 6 servers has been resolved.
+Thu Oct 23 01:18:29 EDT 2003
+
+jcifs-0.7.15 released
+
+The NTLM HTTP Authentication behavoir has been modified to permit load
+balancing between many domain controllers. The jcifs.smb.client.ssnLimit
+property default value has also been changed to 250 from 100.
+
+Mon Oct 6 23:53:28 EDT 2003
+
+jcifs-0.7.14 released
+
+Eric's latest signing patch has been merged, a few adjustments have been
+made to eliminate a concurrency issue, and a fix for browse servers that
+return zero length server names has been incorporated.
+
+Wed Sep 17 21:21:31 EDT 2003
+
+SMB signing is now supported and there have been some adjustments to
+SmbFile.hashCode() and SmbFile.equals()
+
+Mon Sep 1 19:18:52 EDT 2003
+
+Added code to logoff 1/10th of all sessions over a transport if
+jcifs.smb.client.ssnLimit is reached (fix for ERRSVR/90 errors).
+
+Thu Jul 10 22:07:09 EDT 2003
+
+Support for LMv2 authentication has been added.
+
+Thu Jul 3 20:59:25 EDT 2003
+
+There have been minor bug fixes in the NTLM code and SMB layer as well as
+documentation updates.
+
+Thu Jun 12 00:22:05 EDT 2003
+
+jcifs-0.7.9 released
+
+A bug that could cause a connection to hang indefinately has been fixed and
+some NTLM HTTP authentication tweeking has been applied.
+
+Wed May 28 19:09:17 EDT 2003
+
+jcifs-0.7.8 released
+
+A bug in the new ntlm http client code that would cause it to hang for ~60
+seconds before retreiving the target document has been fixed.
+
+Tue May 27 21:40:58 EDT 2003
+
+jcifs-0.7.7 released
+
+A deadlock has been identified and fixed, NTLM authentication for HTTP and
+HTTPS clients has been added (the inverse of the NtlmHttpFilter), the
+SmbFileInputStream.skip() method will skip without reading, and there have
+two other small fixes.
+
+Wed Apr 16 22:46:07 EDT 2003
+
+jcifs-0.7.6 released
+
+The isDirectory method has been changed to return false if the target does
+not exist. Previously this would return true which is inconsistent with
+java.io.File.
+
+Wed Apr 2 23:56:26 EST 2003
+
+jcifs-0.7.5 released
+
+More refinement to the NTLM HTTP authentication code has been applied.
+There is also a fix for listing hosts from Windows ME/98/95 local master
+browsers.
+
+Wed Mar 26 19:17:24 EST 2003
+
+jcifs-0.7.4 released
+
+Some NtlmHttpFilter issues were reported by several users of Win98 clients.
+Eric has provided a new NtlmSsp.java that works correctly with these
+clients.
+
+Wed Feb 12 01:23:02 EST 2003
+
+A security issue regarding the SmbSession.logon() method used by NTLM HTTP
+Authentication has been fixed and a modification has been made to trigger
+MSIE to redisplay the Network Password dialog repeatedly until correct
+credentials are supplied. The change was made in the core jcifs.smb package
+however so test this in your dev environments.
+
+Wed Feb 5 00:41:32 EST 2003
+
+The jcifs-0.7.0 and 0.7.1 releases will incorrectly throw an
+ArrayIndexOutOfBounds exception if a write of 1501 to 1504 is performed.
+This release fixes that bug. You may also set jcifs.smb.client.snd_buf_size
+= 1300 as a temporary work-around. It is also now possible to specify a
+"ShareAccess" with SmbFileOutputStream and SmbFile to restrict other
+processes from accessing files jCIFS opens. Also, SmbFileOutputStream now
+supports writing files larger than 4GB.
+
+Wed Jan 15 22:34:14 EST 2003
+
+jcifs-0.7.1 released
+
+Three bugs have been fixed regarding filenames with '#' signs in them, the
+getInputStream(), getLastModified(), getDate(), and getContentLength()
+methods of the URLConnection implementation, and isExists() incorrectly
+returning false.
+
+Thu Jan 9 00:06:23 EST 2003
+
+jcifs-0.7.0 released
+
+This is the 0.7.0 release of jCIFS, the Java SMB client. There is new
+functionality specifically targeting Web applications as well as some
+critical SMB URL fixes and feature improvements:
+
+o The new jcifs.http package is very handy when building Web applications
+ that need to integrate with MS corporate intranets. Adding a hyperlink to
+ a document on a network drive is easy with Network Explorer (pictured
+ right) and will transparently negotiate credentials with MSIE to browse
+ SMB resources (really, no password dialog necessary). This package also
+ boasts an NTLM HTTP Authentication servlet Filter for authenticating MSIE
+ clients. These are useful features because many of the tasks surrounding
+ user management now fall back to computer support and HR. It is not
+ necessary to add and remove users as they join and leave the company.
+ Perhaps most important from the user's perspective; they do not need to
+ enter a username or password if their workstation is a member of an NTLM
+ domain. The password hashes generated when they logged on to their
+ workstation will be negotiated during the initial request for a session,
+ passed through jCIFS, and validated against a PDC or BDC. This also makes
+ the user's domain, username, and password available for managing session
+ information, profiles, preferences, etc.
+
+o The functionality used to authenticate and manage arbitrary creadentials
+ has been exposed in the SmbSession and NtlmPasswordAuthentication
+ classes. This permits NTLM password authentication to be integrated into
+ applications without requiring Microsoft components or JNI.
+
+o With the introduction of the jcifs.encoding property the client is now
+ truely internationalized. It has been used successfully on OS/390 with
+ native EBCDIC character encoding. See the Sun JRE documentation for a
+ list of supported encodings.
+
+o The URL issues remaining in the 0.6 series have been fixed in 0.7 by
+ converting all SMB URL handling internally to use the java.net.URL class
+ (Note: directories must now have a trailing slash and Java 1.3 is
+ required). Also a deadlock in the name service code was identified and
+ fixed (repaired in 0.6.8 as well).
+
+o A copyTo() method has been added to SmbFile that is very fast at copying
+ large directories across hosts.
+
+o There have been numerous other changes including the mkdirs() and
+ getType() methods, plain text password support (disabled by default), the
+ available() method and close() fix for Named Pipes, reading files larger
+ than 4 GB, the NtlmAuthenticator class, and more.
+
+All documentation has been completely reviewed and updated.
+
+--8<--
+
+ jCIFS
+ Common Internet File System Client in 100% Java
+ http://jcifs.samba.org
+
+
+This is the jCIFS SMB client library written in Java. In short, it will
+enable Java applications to remotely access shared directories on SMB file
+servers(i.e. a Microsoft Windows "share"). It is a fairly religious
+implementation of the CIFS specification supporting Unicode, batching,
+multiplexing, encrypted authentication, transactions, named pipes,
+domain/workgroup/server/share/directory/file enumeration, RAPs and more. It
+is licensed under LGPL which means commercial organizations can
+legitimately use it with their propertietary code (you just can't modify
+the library itself without providing the source for those changes to it's
+users, see the LGPL for details).
+
+REQUIREMENTS:
+
+Java 1.3 or above - http://java.sun.com/products/
+
+INSTALLATION:
+
+Just add the jar file to you classpath as you would with any other jar.
+More specifically:
+
+UNIX:
+
+Go to http://jcifs.samba.org and download the latest jar. If you download
+the tgz archive you also get the source code and javadoc API documentation
+(see critical properties discussed on the Overview page). Put it someplace
+reasonable and extract it. For example:
+
+ $ gunzip jcifs-0.7.0.tgz
+ $ tar -xvf jcifs-0.7.0.tar
+
+Add the jar to your classpath. There are two ways to do this. One is to
+explicitly set it on the command line when you run your application like:
+
+ $ java -cp myjars/jcifs-0.7.0.jar MyApplication
+
+but a more robust solution is to export it in your ~/.profile or
+~/.bash_profile like:
+
+ CLASSPATH=$CLASSPATH:/home/produser/myapp/myjars/jcifs-0.7.0.jar
+ export CLASSPATH
+
+WINDOWS:
+
+Go to http://jcifs.samba.org and download the latest jar. If you download
+the zip archive you also get the source code and javadoc API documentation
+(see critical properties discussed on the Overview page). Put it someplace
+reasonable and extract it with something like Winzip.
+
+Add the jar to your classpath. There are two ways to do this. One is to
+explicitly set it on the command line when you run your application like:
+
+ C:\> java -cp myjars\jcifs-0.7.0.jar MyApplication
+
+but a more robust solution would be to change your system environment but
+I'm not confident I can tell you accurately how to do that.
+
+It is also common that the CLASSPATH be specified in a shell script or
+batch file. See the build.bat batch file that runs the Ant build tool as an
+example.
+
+USING JCIFS:
+
+In general the public API is extremely simple. The jcifs.smb.SmbFile,
+jcifs.smb.SmbFileInputStream, and jcifs.smb.SmbFileOutputStream classes are
+analogous to the java.io.File, java.io.FileInputStream, and
+java.io.FileOutputStream classes so if you know how to use those it should
+be obvious how to use jCIFS provided you set any necessary properties(such
+as WINS) and understand the smb:// URL syntax.
+
+Here's an example to retrieve a file:
+
+ import jcifs.smb.*;
+
+ jcifs.Config.setProperty( "wins", "192.168.1.230" );
+ SmbFileInputStream in = new SmbFileInputStream(
+ "smb://username:password@host/c/My Documents/report.txt" );
+ byte[] b = new byte[8192];
+ int n;
+ while(( n = in.read( b )) > 0 ) {
+ System.out.write( b, 0, n );
+ }
+
+You can also write, rename, list contents of a directory, enumerate shares,
+communicate with Win32 Named Pipe Servers, ...etc.
+
+The protocol handler for java.net.URL is also in place which means you
+retrieve files using the URL class as you would with other protocols. For
+example:
+
+ jcifs.Config.registerSmbURLHandler(); //ensure protocol handler is loaded
+ URL url = new URL( "smb://user:pass@host/share/dir/file.doc" );
+ InputStream in = url.openStream();
+
+There are many example programs in the jcifs_0.7.0/examples/ directory. To
+execute the Put example you might do:
+
+ $ java -cp examples:jcifs-0.7.0.jar -Djcifs.properties=jcifs.prp \
+ Put smb://usr:pass@host/share/dir/file.doc
+ ##########
+ 582K transfered
+
+This will also work with whatever else uses the URL class internally. For
+example if you use RMI you can serve class files from an SMB share and use
+the codebase property:
+
+ -Djava.rmi.server.codebase=smb://mymachine/c/download/myapp.jar
+
+See the extensive API documentation included in the distribution.
+
+BUILDING JCIFS FROM SOURCE:
+
+If you wish to modify and/or build the jCIFS source simply download the
+ant.tgz or ant.zip available at http://jcifs.samba.org and extract it in
+the jcifs_0.7.0 directory. Edit the build.sh or build.bat file to
+appropriately reflect the location of the JDK on your system and bootstrap
+the Ant build tool. Now type:
+
+ $ ./build.sh
+
+You will be presented with a list of target arguments. The build file is a
+standard Ant build.xml config. You may also integrate the package into your
+existing Ant installation or get the latest version of Ant here:
+
+ http://jakarta.apache.org/ant/
+
+WHAT IS SMB AND CIFS?
+
+Server Message Block (SMB) is an application layer networking protocol for
+file and print sharing. It is the de-facto networking protocol for
+Microsoft Windows platforms. The Common Internet File System (CIFS) is the
+more generic name for all that encompasses the protocol and its many
+layers. Collectively this is the networking protocol used when you "Map
+Network Drive...", issue "net use * \\server\share" commands, use smbclient
+on UNIX, smbfs on Linux, Sharity, OS2, server vendors such as Network
+Appliance, EMC, and Novell NetWare.
+
+WHY DO YOU NEED JCIFS?
+
+This client is 100% Java and will work the same in a variety of
+environments from Palm Pilots and applets to any UNIX that supports Java.
+Naturally you can choose to run your applications on a platform that
+supports mapping or mounting remote volumes into the local filesystem but
+this assumes you know what shares you are accessing in advance and what
+platform your application is running on(do you use /mnt/pnt or H:\dir). The
+latency involed makes this approach unsatisfactory for certain applications
+(e.g. Web Gateway). Using locally mapped filesystems is also not portable,
+unstable due to unnecessary dependencies, and more difficult to manage. The
+JCIFS infrastructure is also highly extensible. If there is a demand it
+will include a great deal of additional functionality not available through
+a filesystem API such as printing, RPC, NT file change notification, etc.
+
+ACKNOWLEDGEMENTS
+
+Special thanks to the Samba organization and Christopher R. Hertel for
+starting the JCIFS project.
+
+
+Mon Nov 24 04:06:55 EST 2003
+
+jcifs-0.8.0b released
+
+This is the first beta release of the 0.8 series. There have been
+significant additions to this package including DFS support, random access
+files, filename and file filters, setting attributes and times, and copyTo
+and delete improvements.
+
+Thu Oct 23 01:18:29 EDT 2003
jcifs-0.7.15 released
<target name="jar" depends="smb">
<copy file="src/jcifs/util/mime.map" tofile="build/jcifs/util/mime.map" overwrite="yes"/>
<copy file="src/jcifs/http/ne.css" tofile="build/jcifs/http/ne.css" overwrite="yes"/>
- <jar jarfile="jcifs-0.7.19.jar" basedir="build"/>
+ <jar jarfile="jcifs-0.8.0.jar" basedir="build"/>
</target>
<target name="tgz">
- <copy todir="dist_tmp/jcifs_0.7.19">
+ <copy todir="dist_tmp/jcifs_0.8.0">
<fileset dir="." excludes="ant,**/.*,build,jcifs.prp,**/*.tgz,**/*.zip"/>
</copy>
- <tar tarfile="jcifs-0.7.19.tar" basedir="dist_tmp"/>
- <gzip src="jcifs-0.7.19.tar" zipfile="jcifs-0.7.19.tgz"/>
- <delete file="jcifs-0.7.19.tar"/>
+ <tar tarfile="jcifs-0.8.0.tar" basedir="dist_tmp"/>
+ <gzip src="jcifs-0.8.0.tar" zipfile="jcifs-0.8.0.tgz"/>
+ <delete file="jcifs-0.8.0.tar"/>
<delete dir="dist_tmp"/>
</target>
<target name="zip">
- <copy todir="dist_tmp/jcifs_0.7.19">
+ <copy todir="dist_tmp/jcifs_0.8.0">
<fileset dir="." excludes="ant,**/.*,build,jcifs.prp,**/*.tgz,**/*.zip"/>
</copy>
<fixcrlf srcdir="dist_tmp" cr="add" tab="remove" tablength="4" excludes="**/*.jar,**/*.exe"/>
- <zip zipfile="jcifs-0.7.19.zip" basedir="dist_tmp"/>
+ <zip zipfile="jcifs-0.8.0.zip" basedir="dist_tmp"/>
<delete dir="dist_tmp"/>
</target>
<target name="javadoc">
<delete dir="docs/api"/>
<mkdir dir="docs/api"/>
- <javadoc sourcefiles="jcifs/netbios/NbtAddress,jcifs/smb/SmbFile,jcifs/smb/SmbException,jcifs/smb/SmbAuthException,jcifs/smb/SmbNamedPipe,jcifs/smb/SmbFileInputStream,jcifs/smb/SmbFileOutputStream,jcifs/UniAddress,jcifs/Config,jcifs/util/PropertiesTree,jcifs/util/Log,jcifs/smb/SmbSession,jcifs/smb/NtlmPasswordAuthentication,jcifs/http/NtlmSsp,jcifs/http/NtlmHttpFilter,jcifs/http/NetworkExplorer,jcifs/http/NtlmServlet,jcifs/smb/NtlmAuthenticator"
+ <javadoc sourcefiles="jcifs/netbios/NbtAddress,jcifs/smb/SmbFile,jcifs/smb/SmbException,jcifs/smb/SmbAuthException,jcifs/smb/SmbNamedPipe,jcifs/smb/SmbFileInputStream,jcifs/smb/SmbFileOutputStream,jcifs/UniAddress,jcifs/Config,jcifs/util/PropertiesTree,jcifs/util/Log,jcifs/smb/SmbSession,jcifs/smb/NtlmPasswordAuthentication,jcifs/http/NtlmSsp,jcifs/http/NtlmHttpFilter,jcifs/http/NetworkExplorer,jcifs/http/NtlmServlet,jcifs/smb/NtlmAuthenticator,jcifs/smb/DosFileFilter,jcifs/smb/SmbRandomAccessFile,jcifs/smb/SmbFilenameFilter,jcifs/smb/SmbFileFilter"
sourcepath="src"
destdir="docs/api"
overview="docs/overview.html"
author="true"
version="true"
use="true"
- windowtitle="jcifs API">
+ windowtitle="jCIFS API">
<!-- link href="http://java.sun.com/products/jdk/1.2/docs/api/"/-->
</javadoc>
<copy file="docs/allclasses-frame.html" tofile="docs/api/allclasses-frame.html" overwrite="yes"/>
byte[] msg;
int i = 0;
- while( i++ < 10 ) {
+ while( i++ < 5 ) {
msg = new String( "this is msg #" + i ).getBytes();
out.write( msg );
+ System.out.write( msg );
Thread.sleep( 17000 );
}
import jcifs.util.Log;
import java.util.Date;
-public class AuthListFiles implements AuthHandler {
+public class AuthListFiles extends NtlmAuthenticator {
public static String readLine() throws Exception {
int c;
}
public AuthListFiles( String[] argv ) throws Exception {
- SmbFile.setAuthHandler( this );
+ NtlmAuthenticator.setDefault( this );
SmbFile file = new SmbFile( argv[0] );
for( int i = 0; i < files.length; i++ ) {
System.out.print( " " + files[i].getName() );
}
+ System.out.println();
}
- public boolean authenticate( AuthInfo authInfo ) {
- System.out.println( authInfo.exception.getMessage() + " for " + authInfo.target );
+ protected NtlmPasswordAuthentication getNtlmPasswordAuthentication() {
+ System.out.println( getRequestingException().getMessage() + " for " + getRequestingURL() );
System.out.print( "username: " );
- int i;
try {
- String user = readLine();
- if((i = user.indexOf( '\\' )) != -1 ) {
- authInfo.domain = user.substring( 0, i );
- authInfo.username = user.substring( i + 1 );
- } else {
- authInfo.username = user;
+ int i;
+ String username = readLine();
+ String domain = null, password;
+
+ if(( i = username.indexOf( '\\' )) != -1 ) {
+ domain = username.substring( 0, i );
+ username = username.substring( i + 1 );
}
System.out.print( "password: " );
- authInfo.password = readLine();
- if( authInfo.password.length() > 0 ) {
- return true;
+ password = readLine();
+ if( password.length() == 0 ) {
+ return null;
}
+ return new NtlmPasswordAuthentication( domain, username, password );
} catch( Exception e ) {
}
- return false;
+ return null;
}
+++ /dev/null
-import jcifs.netbios.NbtAddress;
-import jcifs.util.*;
-import jcifs.smb.*;
-import jcifs.util.Log;
-import java.util.Date;
-
-public class Break implements AuthHandler {
-
- public Break( String[] argv ) throws Exception {
- SmbFile.setAuthHandler( this );
- System.out.println( "listed " + (new SmbFile( argv[0] ).listFiles()).length + " files" );
- }
-
- public boolean authenticate( AuthInfo authInfo ) {
- authInfo.domain = "mydom";
- authInfo.username = "miallen";
- authInfo.password = "wwcWww";
- System.out.println( authInfo.exception.getMessage() + ", trying new credentials" );
- return true;
- }
-
-
- public static void main( String[] argv ) throws Exception {
- for( int i = 0; i < 10; i++ ) {
- new Break( argv );
- Thread.sleep( 4000 );
- }
- }
-}
+++ /dev/null
-import jcifs.smb.SmbFile;\r
-\r
-public class CopyTo5 {\r
-\r
- public static void main( String argv[] ) throws Exception {\r
- if( argv.length < 7 ) {\r
- System.err.println( "CopyTo <src directory> <dst directory> <f1> <f2> <f3> <f4> <f5>" );\r
- System.exit( 1 );\r
- }\r
- SmbFile srcdir = new SmbFile( argv[0] );\r
- SmbFile dstdir = new SmbFile( argv[1] );\r
-\r
- SmbFile sf1 = new SmbFile( srcdir, argv[2] );\r
- SmbFile df1 = new SmbFile( dstdir, argv[2] );\r
- sf1.copyTo( df1 );\r
-\r
- SmbFile sf2 = new SmbFile( srcdir, argv[3] );\r
- SmbFile df2 = new SmbFile( dstdir, argv[3] );\r
- sf2.copyTo( df2 );\r
-\r
- SmbFile sf3 = new SmbFile( srcdir, argv[4] );\r
- SmbFile df3 = new SmbFile( dstdir, argv[4] );\r
- sf3.copyTo( df3 );\r
-\r
- SmbFile sf4 = new SmbFile( srcdir, argv[5] );\r
- SmbFile df4 = new SmbFile( dstdir, argv[5] );\r
- sf4.copyTo( df4 );\r
-\r
- SmbFile sf5 = new SmbFile( srcdir, argv[6] );\r
- SmbFile df5 = new SmbFile( dstdir, argv[6] );\r
- sf5.copyTo( df5 );\r
- }\r
-}\r
-\r
public static void main( String argv[] ) throws Exception {
- SmbFileOutputStream out = new SmbFileOutputStream( argv[0], true );
+ SmbFileOutputStream out = new SmbFileOutputStream( argv[0], false );
out.close();
}
}
-import jcifs.smb.SmbFile;
-import jcifs.smb.SmbException;
+import jcifs.smb.*;
public class Delete {
public static void main( String argv[] ) throws Exception {
SmbFile f = new SmbFile( argv[0] );
+ System.out.println( f.length() + " bytes" );
if( f.exists() ) {
System.out.println( argv[0] + " exists" );
} else {
--- /dev/null
+import java.util.*;
+import java.text.*;
+import java.net.*;
+import jcifs.smb.SmbFile;
+
+public class FileInfo {
+
+ static final String TYPES[] = {
+ "TYPE_COMM",
+ "TYPE_FILESYSTEM",
+ "TYPE_NAMED_PIPE",
+ "TYPE_PRINTER",
+ "TYPE_SERVER",
+ "TYPE_SHARE",
+ "TYPE_WORKGROUP"
+ };
+
+ public static void main( String argv[] ) throws Exception {
+ int i, start, end;;
+ SimpleDateFormat sdf = new SimpleDateFormat( "MM/dd/yy hh:mm:ss a" );
+ GregorianCalendar cal = new GregorianCalendar();
+ SmbFile f;
+
+ if( argv.length < 2 ) {
+ throw new IllegalArgumentException( "usage: FileInfo <url> <opindex>" );
+ }
+
+ if( argv.length == 3 ) {
+ SmbFile tmp = new SmbFile( argv[0] );
+ f = new SmbFile( tmp.toString(), argv[1] );
+ start = Integer.parseInt( argv[2] );
+ } else {
+ f = new SmbFile( argv[0] );
+ start = Integer.parseInt( argv[1] );
+ }
+
+ sdf.setCalendar( cal );
+
+ i = end = start;
+ do {
+ switch( i ) {
+ case 0:
+ System.out.println( " toString: " + f.toString() );
+ break;
+ case 1:
+ System.out.println( " toURL: " + f.toURL() );
+ break;
+ case 2:
+ System.out.println( " getName: " + f.getName() );
+ break;
+ case 3:
+ System.out.println( " length: " + f.length() );
+ break;
+ case 4:
+ System.out.println( " getLastModified: " + sdf.format( new Date( f.getLastModified() )));
+ break;
+ case 5:
+ System.out.println( " isHidden: " + f.isHidden() );
+ break;
+ case 6:
+ System.out.println( " isFile: " + f.isFile() );
+ break;
+ case 7:
+ System.out.println( " isDirectory: " + f.isDirectory() );
+ break;
+ case 8:
+ System.out.println( " hashCode: " + f.hashCode() );
+ break;
+ case 9:
+ System.out.println( " getUncPath: " + f.getUncPath() );
+ break;
+ case 10:
+ System.out.println( " getType: " + TYPES[f.getType()] );
+ break;
+ case 11:
+ System.out.println( " getShare: " + f.getShare() );
+ break;
+ case 12:
+ System.out.println( " getServer: " + f.getServer() );
+ break;
+ case 13:
+ System.out.println( " getPath: " + f.getPath() );
+ break;
+ case 14:
+ System.out.println( " getParent: " + f.getParent() );
+ break;
+ case 15:
+ System.out.println( " lastModified: " + sdf.format( new Date( f.lastModified() )));
+ break;
+ case 16:
+ System.out.println( "getDiskFreeSpace: " + f.getDiskFreeSpace() );
+ break;
+ case 17:
+ System.out.println( " getDate: " + sdf.format( new Date( f.getDate() )));
+ break;
+ case 18:
+ System.out.println( "getContentLength: " + f.getContentLength() );
+ break;
+ case 19:
+ System.out.println( "getCanonicalPath: " + f.getCanonicalPath() );
+ break;
+ case 20:
+ System.out.println( " exists: " + f.exists() );
+ break;
+ case 21:
+ System.out.println( " canRead: " + f.canRead() );
+ break;
+ case 22:
+ System.out.println( " canWrite: " + f.canWrite() );
+ break;
+ }
+ i++;
+ if( i == 23 ) {
+ i = 0;
+ }
+ } while( i != end );
+ }
+}
+
--- /dev/null
+import jcifs.netbios.NbtAddress;
+import jcifs.smb.*;
+import jcifs.util.Log;
+import java.util.Date;
+
+public class FilterFiles {
+
+ static class ShortFilenameFilter implements SmbFilenameFilter {
+ public boolean accept( SmbFile dir, String name ) throws SmbException {
+ return name.length() < 9;
+ }
+ }
+ static class BigFileFilter implements SmbFileFilter {
+ public boolean accept( SmbFile file ) throws SmbException {
+ return file.length() > 0x1FFFFL;
+ }
+ }
+
+ public static void main( String[] argv ) throws Exception {
+
+ SmbFile file = new SmbFile( argv[0] );
+ BigFileFilter filter = new BigFileFilter();
+ DosFileFilter everything = new DosFileFilter( "*",
+ SmbFile.ATTR_DIRECTORY | SmbFile.ATTR_HIDDEN | SmbFile.ATTR_SYSTEM );
+
+ long t1 = System.currentTimeMillis();
+ SmbFile[] files = file.listFiles( everything );
+ long t2 = System.currentTimeMillis() - t1;
+
+ for( int i = 0; i < files.length; i++ ) {
+ System.out.print( " " + files[i].getName() );
+ }
+ System.out.println();
+ System.out.println( files.length + " files in " + t2 + "ms" );
+ }
+}
+
--- /dev/null
+import jcifs.smb.SmbFile;
+
+public class GetDfsPath {
+
+ public static void main( String argv[] ) throws Exception {
+
+ SmbFile f = new SmbFile( argv[0] );
+ System.out.println( f.getDfsPath() );
+ }
+}
+
public static void main( String argv[] ) throws Exception {
- System.in.read();
-
jcifs.Config.registerSmbURLHandler();
URL url = new URL( argv[0] );
--- /dev/null
+import java.net.*;
+
+public class HttpURL {
+
+ public static void main( String[] args ) throws Exception {
+ jcifs.Config.registerSmbURLHandler();
+
+ URL u = new URL( new URL( args[0] ), args[1] );
+ System.out.println( u );
+ }
+}
--- /dev/null
+JAVA_HOME=/usr/local/java
+CLASSPATH=../build:.
+
+.SUFFIXES: .java .class
+
+CLASSFILES=AllocInfo.class Append.class AuthListFiles.class CallNamedPipe.class CifsTime.class CopyTo.class CreateFile.class Delete.class Equals.class Exists.class FileInfo.class FileOps.class FilterFiles.class Format.class GetDate.class GetDfsPath.class Get.class GetType.class GetURL.class GrowWrite.class HttpURL.class Interleave.class IsDir.class Length.class ListFiles.class List.class ListTypes.class LogTest.class Mkdir.class NodeStatus.class OpenExclusive.class PeekNamedPipe.class PipeTalk.class Put.class Query.class RenameTo.class SetAttrs.class SetTime.class SlowRead.class SlowWrite.class SmbCrawler.class SmbShell.class SmbTableFile.class SmbTableFileRecord.class T2Crawler.class TestRandomAccess.class TestSmbURL.class TestUnicode.class ThreadedNbtQuery.class ThreadedSmbCrawler.class ThreadedUniQuery.class Torture1.class Torture2.class TortureTest5.class TransactNamedPipe.class URLTest.class VerifyGuest.class VerifyIO.class VerifyReads.class
+
+all: ${CLASSFILES}
+
+.java.class:
+ ${JAVA_HOME}/bin/javac -classpath ${CLASSPATH} $<
+
+clean:
+ ${RM} *.class
--- /dev/null
+import jcifs.smb.*;
+
+public class SetAttrs {
+
+ public static void main( String argv[] ) throws Exception {
+ if( argv.length < 2 ) {
+ System.err.println( "usage: SetAttrs <smburl> <hexval>" );
+ return;
+ }
+
+ SmbFile f = new SmbFile( argv[0] );
+ SmbFileInputStream in = new SmbFileInputStream( f );
+ int attrs = Integer.parseInt( argv[1], 16 );
+
+ f.setAttributes( attrs );
+ }
+}
+
--- /dev/null
+import jcifs.smb.SmbFile;
+import jcifs.smb.SmbException;
+
+public class SetTime {
+
+ public static void main( String argv[] ) throws Exception {
+ SmbFile f = new SmbFile( argv[0] );
+ long time = f.getLastModified();
+ f.setLastModified( time + 65000 ); /* add 1 minute and 5 seconds */
+ }
+}
+
--- /dev/null
+/* jcifs smb client library in Java
+ * Copyright (C) 2003 "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
+ */
+
+import jcifs.smb.*;
+import java.io.*;
+
+public class SmbTableFile extends SmbRandomAccessFile {
+
+ static final byte BYTE_FULL = (byte)0xFF;
+
+ byte[] hdr = new byte[512];
+ byte[] buf = new byte[1024];
+ char[] cbuf = new char[512];
+ int recordSize, row;
+
+ public SmbTableFile( SmbFile file, String mode, int recordSize ) throws IOException {
+ super( file, mode );
+ this.recordSize = recordSize;
+ read( hdr, 0, 512 );
+ }
+ public SmbTableFile( String url, String mode, int shareAccess, int recordSize ) throws IOException {
+ super( url, mode, shareAccess );
+ this.recordSize = recordSize;
+ read( hdr, 0, 512 );
+ }
+
+ public void insert( SmbTableFileRecord tfr ) throws IOException {
+ int i, b = 0;
+
+ /* Find an unset bit it in the bitmap
+ */
+ for( i = 128; i < 512; i++ ) {
+ if( hdr[i] != BYTE_FULL ) {
+ /* bitwise complement inverts each bit
+ * mask with 0xFF ensures we only use 8 bits of int b
+ */
+ b = ~hdr[i] & 0xFF;
+ /* clever trick to isolate first bit on
+ */
+ b = b & -b;
+ break;
+ }
+ }
+ if( i == 512 ) {
+ throw new IOException( "No more space in " + this );
+ }
+ /* convert power of two to position
+ */
+ switch( b ) {
+ case 1: b = 0; break;
+ case 2: b = 1; break;
+ case 4: b = 2; break;
+ case 8: b = 3; break;
+ case 16: b = 4; break;
+ case 32: b = 5; break;
+ case 64: b = 6; break;
+ case 128: b = 7; break;
+ }
+ tfr.rowid = (i - 128) * 8 + b;
+ update( tfr );
+ }
+ public void update( SmbTableFileRecord tfr ) throws IOException {
+ int i;
+
+ seek( 512L + tfr.rowid * recordSize );
+ tfr.encode( this );
+
+ i = 128 + tfr.rowid / 8;
+ seek( i );
+ hdr[i] |= 1 << (tfr.rowid % 8);
+ write( hdr[i] );
+ }
+ public void get( SmbTableFileRecord tfr ) throws IOException {
+ seek( 512L + tfr.rowid * recordSize );
+ tfr.decode( this );
+ }
+ public void iterate() {
+ row = 0;
+ }
+ public boolean next( SmbTableFileRecord tfr ) throws IOException {
+ int i, b;
+
+ i = 128 + row / 8; /* Search bitmap for next bit that is on */
+ b = 1 << (row % 8);
+ for( ; i < 512; i++ ) {
+ if(( hdr[i] & -b ) != 0 ) {
+ b = hdr[i] & -b;
+ b = b & -b;
+ break;
+ }
+ b = 1;
+ }
+ if( i == 512 ) { /* Are no more on bits, return */
+ return false;
+ }
+ switch( b ) {
+ case 1: b = 0; break;
+ case 2: b = 1; break;
+ case 4: b = 2; break;
+ case 8: b = 3; break;
+ case 16: b = 4; break;
+ case 32: b = 5; break;
+ case 64: b = 6; break;
+ case 128: b = 7; break;
+ }
+ tfr.rowid = (i - 128) * 8 + b; /* Set rowid and get */
+ get( tfr );
+
+ row = tfr.rowid + 1; /* Iterate row for next caller */
+
+ return true;
+ }
+}
--- /dev/null
+/* jcifs smb client library in Java
+ * Copyright (C) 2003 "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
+ */
+
+import jcifs.smb.SmbException;
+
+public abstract class SmbTableFileRecord {
+ public int rowid;
+ public abstract void encode( SmbTableFile tf ) throws SmbException;
+ public abstract void decode( SmbTableFile tf ) throws SmbException;
+}
--- /dev/null
+import jcifs.smb.*;
+
+public class TestRandomAccess {
+
+ public static class TestRecord extends SmbTableFileRecord {
+
+ boolean f1; /* 1 byte */
+ byte f2; /* 1 byte */
+ int f3; /* 1 byte */
+ short f4; /* 2 bytes */
+ int f5; /* 2 bytes */
+ char f6; /* 2 bytes */
+ int f7; /* 4 bytes */
+ long f8; /* 8 bytes */
+ float f9; /* 4 bytes */
+ double f10; /* 8 bytes */
+ String f11; /* 95 bytes max */
+ /* 128 bytes total */
+
+ public TestRecord() {
+ }
+ public TestRecord( boolean f1, byte f2, int f3, short f4,
+ int f5, char f6, int f7, long f8,
+ float f9, double f10, String f11 ) {
+ this.f1 = f1;
+ this.f2 = f2;
+ this.f3 = f3;
+ this.f4 = f4;
+ this.f5 = f5;
+ this.f6 = f6;
+ this.f7 = f7;
+ this.f8 = f8;
+ this.f9 = f9;
+ this.f10 = f10;
+ this.f11 = f11;
+ }
+
+ public void encode( SmbTableFile tf ) throws SmbException {
+ tf.writeBoolean( f1 );
+ tf.writeByte( f2 );
+ tf.writeByte( f3 );
+ tf.writeShort( f4 );
+ tf.writeShort( f5 );
+ tf.writeChar( f6 );
+ tf.writeInt( f7 );
+ tf.writeLong( f8 );
+ tf.writeFloat( f9 );
+ tf.writeDouble( f10 );
+ tf.writeUTF( f11 );
+ }
+ public void decode( SmbTableFile tf ) throws SmbException {
+ f1 = tf.readBoolean();
+ f2 = tf.readByte();
+ f3 = tf.readUnsignedByte();
+ f4 = tf.readShort();
+ f5 = tf.readUnsignedShort();
+ f6 = tf.readChar();
+ f7 = tf.readInt();
+ f8 = tf.readLong();
+ f9 = tf.readFloat();
+ f10 = tf.readDouble();
+ f11 = tf.readUTF();
+ }
+ public boolean equals( Object obj ) {
+ if( obj instanceof TestRecord ) {
+ TestRecord r = (TestRecord)obj;
+
+ return r.f1 == f1 &&
+ r.f2 == f2 &&
+ r.f3 == f3 &&
+ r.f4 == f4 &&
+ r.f5 == f5 &&
+ r.f6 == f6 &&
+ r.f7 == f7 &&
+ r.f8 == f8 &&
+ r.f9 == f9 &&
+ r.f10 == f10 &&
+ f11.equals( r.f11 );
+ }
+ return false;
+ }
+ }
+
+ public static void main( String[] argv ) throws Exception {
+ if( argv.length < 2 ) {
+ System.err.println( "usage: TestRandomAccess <url> <N> (1 for read or 2 for write with <index>)" );
+ return;
+ }
+ SmbTableFile stf;
+ int op = Integer.parseInt( argv[1] );
+
+ TestRecord r1 = new TestRecord( true, (byte)0x12, 0x34, (short)0x1122,
+ 0x3344, '\u04c1', 0x11112222, 0x1111111122222222L,
+ 0.1122f, 3344.1, "The surface is smooth like glass" );
+
+ if( op == 3 ) {
+ stf = new SmbTableFile( argv[0], "rw", 0, 128 );
+ int newLength = Integer.parseInt( argv[2] );
+ stf.setLength( newLength );
+ System.out.println( "truncated to " + newLength );
+ } else if( op == 1 ) {
+ SmbFile file = new SmbFile( argv[0], null, SmbFile.FILE_SHARE_READ );
+ stf = new SmbTableFile( file, "rw", 128 );
+ stf.insert( r1 );
+ System.out.println( "rowid: " + r1.rowid );
+ } else {
+ if( argv.length < 3 ) {
+ System.err.println( "usage: TestRandomAccess <url> <N> (1 for read or 2 for write with <index>)" );
+ return;
+ }
+ stf = new SmbTableFile( argv[0], "r", 0, 128 );
+ TestRecord r2 = new TestRecord();
+ r2.rowid = Integer.parseInt( argv[2] );
+ stf.get( r2 );
+ System.out.println( "r1.equals( r2 ) = " + r1.equals( r2 ));
+ }
+
+ stf.close();
+ }
+}
+
}
}
if( f1.isDirectory() != f2.isDirectory() ) {
- System.err.println( "directory comparison failed: " + f1.isDirectory() + " " + f2.isDirectory() );
+ System.err.println( "directory comparison failed: " + f1.getName() + ": " + f1.isDirectory() + " " + f2.isDirectory() );
}
if( f1.isFile() != f2.isFile() ) {
- System.err.println( "file comparison failed: " + f1.isFile() + " " + f2.isFile() );
+ System.err.println( "file comparison failed: " + f1.getName() + ": " + f1.isFile() + " " + f2.isFile() );
}
if( f1.getType() != f2.getType() ) {
System.err.println( "type comparison failed: " + f1.getName() + " " + f2.getName() );
System.err.println( "name comparison failed: " + f1.getName() + " " + f2.getName() );
}
if( f1.length() != f2.length() ) {
- System.err.println( "length comparison failed: " + f1.length() + " " + f2.length() );
+ System.err.println( "length comparison failed: " + f1.getName() + ": " + f1.length() + " " + f2.length() );
+ }
+ if( f1.getAttributes() != f2.getAttributes() ) {
+ System.err.println( "attribute comparison failed: " + f1.getName() + ": " + Log.getHexString( f1.getAttributes(), 4 ) + " " + Log.getHexString( f2.getAttributes(), 4 ));
+ }
+ if( Math.abs( f1.createTime() - f2.createTime() ) > 1000 ) {
+ System.err.println( "create time comparison failed: " + f1.getName() + ": " + f1.createTime() + " " + f2.createTime() );
+ }
+ if( Math.abs( f1.lastModified() - f2.lastModified() ) > 1000 ) {
+ System.err.println( "last modified comparison failed: " + f1.getName() + ": " + f1.lastModified() + " " + f2.lastModified() );
}
} catch( Exception x ) {
System.err.println( "Exception comparing: " + f1 + " | " + f2 );
--- /dev/null
+#!/bin/sh
+
+JAVA_HOME=/usr/local/java
+CLASSPATH=../build:.
+PROPERTIES=../../miallen.prp
+RUN="${JAVA_HOME}/bin/java -cp ${CLASSPATH} -Djcifs.properties=${PROPERTIES}"
+
+SERVER=miallen2
+SHARE=pub
+WRITE_DIR=test
+SRC_DIR=test/variety
+FILE1=test/variety/Batch2/crash.bmp
+
+URL_SHARE=smb://${SERVER}/${SHARE}/
+URL_WRITE_DIR=${URL_SHARE}${WRITE_DIR}/
+
+set -x
+
+$RUN AllocInfo ${URL_SHARE}
+#$RUN Append ${URL_WRITE_DIR}Append.txt
+$RUN AuthListFiles smb://bogus\@${SERVER}/${SHARE}/
+$RUN CopyTo ${URL_SHARE}${SRC_DIR}/ ${URL_SHARE}${WRITE_DIR}/CopyTo/
+$RUN CreateFile ${URL_WRITE_DIR}CreateFile.txt
+$RUN Delete ${URL_WRITE_DIR}CreateFile.txt
+$RUN Equals ${URL_WRITE_DIR}CreateFile.txt ${URL_SHARE}${WRITE_DIR}../${WRITE_DIR}/CreateFile.txt
+$RUN Exists ${URL_WRITE_DIR}
+$RUN FileInfo ${URL_SHARE}${FILE1} 0
+$RUN FileOps ${URL_WRITE_DIR}
+$RUN FilterFiles ${URL_SHARE}${SRC_DIR}/
+$RUN GetDate ${URL_SHARE}${FILE1}
+$RUN Get ${URL_SHARE}${FILE1}
+$RUN GetType ${URL_SHARE}
+$RUN GrowWrite ${URL_WRITE_DIR}GrowWrite.txt
+$RUN GetURL ${URL_WRITE_DIR}Append.txt
+$RUN HttpURL ${URL_WRITE_DIR}Append.txt
+$RUN Interleave ${URL_WRITE_DIR} 3
+$RUN IsDir ${URL_SHARE}${SRC_DIR}/
+$RUN Length ${URL_SHARE}${FILE1}
+$RUN ListFiles ${URL_WRITE_DIR}
+$RUN List ${URL_WRITE_DIR}
+$RUN ListTypes ${URL_WRITE_DIR}
+$RUN Mkdir ${URL_WRITE_DIR}Mkdir
+$RUN NodeStatus ${SERVER}
+$RUN Put ${URL_WRITE_DIR}Makefile
+$RUN Query ${SERVER}
+$RUN RenameTo ${URL_WRITE_DIR}Makefile ${URL_WRITE_DIR}/Makefile.txt
+$RUN SetAttrs ${URL_WRITE_DIR}Makefile.txt FFFF
+$RUN SetTime ${URL_WRITE_DIR}Makefile.txt
+$RUN SlowWrite ${URL_WRITE_DIR}SlowWrite.txt
+$RUN SlowRead ${URL_WRITE_DIR}SlowWrite.txt
+$RUN SmbCrawler ${URL_WRITE_DIR} 1000
+$RUN T2Crawler ${URL_WRITE_DIR} 3 1000
+$RUN TestRandomAccess ${URL_WRITE_DIR}TestRandomAccess.bin 1
+$RUN TestRandomAccess ${URL_WRITE_DIR}TestRandomAccess.bin 2 0
+$RUN TestRandomAccess ${URL_WRITE_DIR}TestRandomAccess.bin 3 1234
+
+
import jcifs.smb.*;
import jcifs.netbios.NbtAddress;
import jcifs.util.MimeMap;
+import jcifs.util.Base64;
/**
* This servlet may be used to "browse" the entire hierarchy of resources
public class NetworkExplorer extends HttpServlet {
- MimeMap mimeMap;
- String style;
- NtlmSsp ntlmSsp;
- boolean useNtlmSsp;
+ private MimeMap mimeMap;
+ private String style;
+ private NtlmSsp ntlmSsp;
+ private boolean credentialsSupplied;
+ private boolean enableBasic;
+ private boolean insecureBasic;
+ private String realm, defaultDomain;
public void init() throws ServletException {
InputStream is;
int n;
String name;
- for( Enumeration e = getInitParameterNames(); e.hasMoreElements(); ) {
+ Config.setProperty( "jcifs.smb.client.soTimeout", "300000" );
+ Config.setProperty( "jcifs.smb.client.attrExpirationPeriod", "120000" );
+
+ Enumeration e = getInitParameterNames();
+ while( e.hasMoreElements() ) {
name = (String)e.nextElement();
if( name.startsWith( "jcifs." )) {
Config.setProperty( name, getInitParameter( name ));
}
}
+ if( Config.getProperty( "jcifs.smb.client.username" ) == null ) {
+ ntlmSsp = new NtlmSsp();
+ } else {
+ credentialsSupplied = true;
+ }
+
try {
mimeMap = new MimeMap();
is = getClass().getClassLoader().getResourceAsStream( "jcifs/http/ne.css" );
} catch( IOException ioe ) {
throw new ServletException( ioe.getMessage() );
}
- Config.setProperty( "jcifs.smb.client.attrExpirationPeriod", "120000" );
- if( Config.getProperty( "jcifs.smb.client.username" ) == null ) {
- ntlmSsp = new NtlmSsp();
- useNtlmSsp = true;
- }
+ enableBasic = Config.getBoolean("jcifs.http.enableBasic", false );
+ insecureBasic = Config.getBoolean("jcifs.http.insecureBasic", false );
+ realm = Config.getProperty("jcifs.http.basicRealm");
+ if (realm == null) realm = "jCIFS";
+ defaultDomain = Config.getProperty("jcifs.smb.client.domain");
}
- String parseServerAndShare( String pathInfo ) {
- char[] out = new char[256];
- char ch;
- int len, p, i;
-
- if( pathInfo == null ) {
- return null;
- }
- len = pathInfo.length();
-
- p = i = 0;
- while( p < len && pathInfo.charAt( p ) == '/' ) {
- p++;
- }
- if( p == len ) {
- return null;
- }
- out[i++] = pathInfo.charAt( p++ );
- while( p < len && ( ch = pathInfo.charAt( p++ )) != '/' ) {
- out[i++] = ch;
- }
- if( p < len ) {
- out[i++] = '/';
- while( p < len && pathInfo.charAt( p ) == '/' ) {
- p++;
- }
- if( p == len ) {
- return new String( out, 0, i - 1 );
- }
- while( p < len && ( ch = pathInfo.charAt( p++ )) != '/' ) {
- out[i++] = ch;
- }
- }
- return new String( out, 0, i );
- }
void doFile( HttpServletRequest req,
HttpServletResponse resp, SmbFile file ) throws IOException {
byte[] buf = new byte[8192];
out.println( "</BODY></HTML>" );
out.close();
}
+ String parseServerAndShare( String pathInfo ) {
+ char[] out = new char[256];
+ char ch;
+ int len, p, i;
+
+ if( pathInfo == null ) {
+ return null;
+ }
+ len = pathInfo.length();
+
+ p = i = 0;
+ while( p < len && pathInfo.charAt( p ) == '/' ) {
+ p++;
+ }
+ if( p == len ) {
+ return null;
+ }
+ do { /* collect server name */
+ out[i++] = (ch = pathInfo.charAt( p++ ));
+ } while( p < len && ch != '/' );
+ while( p < len && pathInfo.charAt( p ) == '/' ) {
+ p++;
+ }
+ if( p < len ) { /* then there must be a share */
+ out[i++] = '/';
+ do { /* collect the share name */
+ out[i++] = (ch = pathInfo.charAt( p++ ));
+ } while( p < len && ch != '/' );
+ }
+ return new String( out, 0, i );
+ }
public void doGet( HttpServletRequest req,
- HttpServletResponse resp ) throws IOException, ServletException {
- NtlmPasswordAuthentication ntlm;
+ HttpServletResponse resp ) throws IOException, ServletException {
UniAddress dc;
- byte[] challenge;
- String pathInfo, s;
- SmbFile file;
+ String msg, pathInfo, server = null;
+ boolean offerBasic, possibleWorkgroup = true;
+ NtlmPasswordAuthentication ntlm = null;
+ HttpSession ssn = req.getSession( false );
- s = null;
if(( pathInfo = req.getPathInfo() ) != null ) {
- s = parseServerAndShare( pathInfo );
+ int i;
+ server = parseServerAndShare( pathInfo );
+ if( server != null && ( i = server.indexOf( '/' )) > 0 ) {
+ server = server.substring( 0, i ).toLowerCase();
+ possibleWorkgroup = false;
+ }
}
- if( useNtlmSsp ) {
- String msg = req.getHeader( "Authorization" );
- if( msg == null || msg.startsWith( "NTLM " ) == false ) {
- resp.setHeader( "WWW-Authenticate", "NTLM" );
- resp.setStatus( HttpServletResponse.SC_UNAUTHORIZED );
- resp.flushBuffer();
- return;
- }
+ msg = req.getHeader( "Authorization" );
+ offerBasic = enableBasic && (insecureBasic || req.isSecure());
- if( pathInfo == null || s == null ) {
- s = NbtAddress.getByName( NbtAddress.MASTER_BROWSER_NAME, 0x01, null ).getHostAddress();
- dc = UniAddress.getByName( s );
- } else {
- int i = s.indexOf( '/' );
- if( i > 0 ) {
- s = s.substring( 0, i );
+ if( msg != null && (msg.startsWith( "NTLM " ) || (offerBasic && msg.startsWith("Basic ")))) {
+
+ if( msg.startsWith("NTLM ")) {
+ byte[] challenge;
+
+ if( pathInfo == null || server == null ) {
+ String mb = NbtAddress.getByName( NbtAddress.MASTER_BROWSER_NAME, 0x01, null ).getHostAddress();
+ dc = UniAddress.getByName( mb );
+ } else {
+ dc = UniAddress.getByName( server, possibleWorkgroup );
}
- dc = UniAddress.getByName( s, i == -1 );
+
+ challenge = SmbSession.getChallenge( dc );
+ if(( ntlm = NtlmSsp.authenticate( req, resp, challenge )) == null ) {
+ return;
+ }
+ } else {
+ String auth = new String( Base64.decode( msg.substring(6) ), "US-ASCII" );
+ int index = auth.indexOf( ':' );
+ String user = (index != -1) ? auth.substring(0, index) : auth;
+ String password = (index != -1) ? auth.substring(index + 1) : "";
+ index = user.indexOf('\\');
+ if (index == -1) index = user.indexOf('/');
+ String domain = (index != -1) ? user.substring(0, index) : defaultDomain;
+ user = (index != -1) ? user.substring(index + 1) : user;
+ ntlm = new NtlmPasswordAuthentication(domain, user, password);
}
- challenge = SmbSession.getChallenge( dc );
- /* Be carefull what you put before this. It's called 3 times in a row
- * before doAuthentication returns a good NtlmPasswordAuthentication
- * object.
- */
+ req.getSession().setAttribute( "npa-" + server, ntlm );
- if(( ntlm = ntlmSsp.doAuthentication( req, resp, challenge )) == null ) {
+ } else if( !credentialsSupplied ) {
+ if( ssn != null ) {
+ ntlm = (NtlmPasswordAuthentication)ssn.getAttribute( "npa-" + server );
+ }
+ if( ntlm == null ) {
+ resp.setHeader( "WWW-Authenticate", "NTLM" );
+ if (offerBasic) {
+ resp.addHeader( "WWW-Authenticate", "Basic realm=\"" + realm + "\"");
+ }
+ resp.setHeader( "Connection", "close" );
+ resp.setStatus( HttpServletResponse.SC_UNAUTHORIZED );
+ resp.flushBuffer();
return;
}
- file = new SmbFile( "smb:/" + pathInfo , ntlm );
- } else if( s == null ) {
- file = new SmbFile( "smb://" );
- } else {
- file = new SmbFile( "smb:/" + pathInfo );
}
try {
+ SmbFile file;
+
+ if( ntlm != null ) {
+ file = new SmbFile( "smb:/" + pathInfo , ntlm );
+ } else if( server == null ) {
+ file = new SmbFile( "smb://" );
+ } else {
+ file = new SmbFile( "smb:/" + pathInfo );
+ }
+
if( file.isDirectory() ) {
doDirectory( req, resp, file );
} else {
doFile( req, resp, file );
}
} catch( SmbAuthException sae ) {
+ if( ssn != null ) {
+ ssn.removeAttribute( "npa-" + server );
+ }
resp.setHeader( "WWW-Authenticate", "NTLM" );
+ if (offerBasic) {
+ resp.addHeader( "WWW-Authenticate", "Basic realm=\"" + realm + "\"");
+ }
resp.setHeader( "Connection", "close" );
resp.setStatus( HttpServletResponse.SC_UNAUTHORIZED );
resp.flushBuffer();
return;
+ } catch( DfsReferral dr ) {
+ StringBuffer redir = req.getRequestURL();
+ String qs = req.getQueryString();
+if( true ) {
+ throw new RuntimeException( "DFS referrals with NetworkExplorer are currently disabled because they can lead to account lockout." );
+}
+ redir = new StringBuffer( redir.substring( 0, redir.length() - req.getPathInfo().length() ));
+ redir.append( dr.node.replace( '\\', '/' ));
+ redir.append( '/' );
+ if( qs != null ) {
+ redir.append( req.getQueryString() );
+ }
+ resp.sendRedirect( redir.toString() );
+ resp.flushBuffer();
+ return;
}
}
}
--- /dev/null
+/* jcifs smb client library in Java
+ * Copyright (C) 2003 "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 jcifs.smb;
+
+public class DfsReferral extends SmbException {
+
+ public String path; // Path relative to tree from which this referral was thrown
+ public String node; // Server and share
+ public String server; // Server
+ public String share; // Share
+ public String nodepath; // Path relative to tree
+ public boolean resolveHashes;
+
+ public String toString() {
+ return "DfsReferral[path=" + path +
+ ",node=" + node +
+ ",server=" + server +
+ ",share=" + share +
+ ",nodepath=" + nodepath +
+ ",resolveHashes=" + resolveHashes + "]";
+ }
+}
--- /dev/null
+/* jcifs smb client library in Java
+ * Copyright (C) 2003 "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 jcifs.smb;
+
+public class DosFileFilter implements SmbFileFilter {
+
+ protected String wildcard;
+ protected int attributes;
+
+ public DosFileFilter( String wildcard, int attributes ) {
+ this.wildcard = wildcard;
+ this.attributes = attributes;
+ }
+
+ /**
+ * This always returns <tt>true</tt> as the wildcard and
+ * attributes members are passed to the server which uses them to
+ * filter on behalf of the client. Sub-classes might overload this
+ * method to further filter the list however.
+ */
+ public boolean accept( SmbFile file ) throws SmbException {
+ return true;
+ }
+}
--- /dev/null
+package jcifs.smb;
+
+interface FileEntry {
+
+ String getName();
+ int getType();
+ int getAttributes();
+ long createTime();
+ long lastModified();
+ long length();
+}
interface Info {
int getAttributes();
+ long getCreateTime();
long getLastWriteTime();
long getSize();
}
class NetServerEnum2Response extends SmbComTransactionResponse {
- class ServerInfo1 {
+ class ServerInfo1 implements FileEntry {
String name;
int versionMajor;
int versionMinor;
int type;
String commentOrMasterBrowser;
+ public String getName() {
+ return name;
+ }
+ public int getType() {
+ return (type & 0x80000000) != 0 ? SmbFile.TYPE_WORKGROUP : SmbFile.TYPE_SERVER;
+ }
+ public int getAttributes() {
+ return SmbFile.ATTR_READONLY | SmbFile.ATTR_DIRECTORY;
+ }
+ public long createTime() {
+ return 0L;
+ }
+ public long lastModified() {
+ return 0L;
+ }
+ public long length() {
+ return 0L;
+ }
+
public String toString() {
return new String( "ServerInfo1[" +
"name=" + name +
}
}
- ServerInfo1[] results;
- int status, converter, entriesReturned, totalAvailableEntries;
+ int converter, totalAvailableEntries;
NetServerEnum2Response() {
}
bufferIndex += 2;
converter = readInt2( buffer, bufferIndex );
bufferIndex += 2;
- entriesReturned = readInt2( buffer, bufferIndex );
+ numEntries = readInt2( buffer, bufferIndex );
bufferIndex += 2;
totalAvailableEntries = readInt2( buffer, bufferIndex );
bufferIndex += 2;
}
int readDataWireFormat( byte[] buffer, int bufferIndex, int len ) {
int start = bufferIndex;
+ ServerInfo1 e;
- results = new ServerInfo1[entriesReturned];
- for( int i = 0; i < entriesReturned; i++ ) {
- results[i] = new ServerInfo1();
- results[i].name = readString( buffer, bufferIndex, 16, false );
+ results = new ServerInfo1[numEntries];
+ for( int i = 0; i < numEntries; i++ ) {
+ results[i] = e = new ServerInfo1();
+ e.name = readString( buffer, bufferIndex, 16, false );
bufferIndex += 16;
- results[i].versionMajor = (int)( buffer[bufferIndex++] & 0xFF );
- results[i].versionMinor = (int)( buffer[bufferIndex++] & 0xFF );
- results[i].type = readInt4( buffer, bufferIndex );
+ e.versionMajor = (int)( buffer[bufferIndex++] & 0xFF );
+ e.versionMinor = (int)( buffer[bufferIndex++] & 0xFF );
+ e.type = readInt4( buffer, bufferIndex );
bufferIndex += 4;
int off = readInt4( buffer, bufferIndex );
bufferIndex += 4;
off = ( off & 0xFFFF ) - converter;
off = start + off;
- results[i].commentOrMasterBrowser = readString( buffer, off, 48, false );
-Log.println( Log.WARNINGS, "net server enum response entry", results[i] );
+ e.commentOrMasterBrowser = readString( buffer, off, 48, false );
+Log.println( Log.WARNINGS, "net server enum response entry", e );
}
return bufferIndex - start;
super.toString() +
",status=" + status +
",converter=" + converter +
- ",entriesReturned=" + entriesReturned +
+ ",entriesReturned=" + numEntries +
",totalAvailableEntries=" + totalAvailableEntries + "]" );
}
}
class NetShareEnumResponse extends SmbComTransactionResponse {
- class ShareInfo1 {
+ class ShareInfo1 implements FileEntry {
String netName;
int type;
String remark;
+ public String getName() {
+ return netName;
+ }
+ public int getType() {
+ switch( type ) {
+ case 1:
+ return SmbFile.TYPE_PRINTER;
+ case 3:
+ return SmbFile.TYPE_NAMED_PIPE;
+ }
+ return SmbFile.TYPE_SHARE;
+ }
+ public int getAttributes() {
+ return SmbFile.ATTR_READONLY | SmbFile.ATTR_DIRECTORY;
+ }
+ public long createTime() {
+ return 0L;
+ }
+ public long lastModified() {
+ return 0L;
+ }
+ public long length() {
+ return 0L;
+ }
+
public String toString() {
return new String( "ShareInfo1[" +
"netName=" + netName +
}
}
- ShareInfo1[] results;
- int status, converter, entriesReturned, totalAvailableEntries;
+ int converter, totalAvailableEntries;
NetShareEnumResponse() {
}
bufferIndex += 2;
converter = readInt2( buffer, bufferIndex );
bufferIndex += 2;
- entriesReturned = readInt2( buffer, bufferIndex );
+ numEntries = readInt2( buffer, bufferIndex );
bufferIndex += 2;
totalAvailableEntries = readInt2( buffer, bufferIndex );
bufferIndex += 2;
}
int readDataWireFormat( byte[] buffer, int bufferIndex, int len ) {
int start = bufferIndex;
+ ShareInfo1 e;
useUnicode = false;
- results = new ShareInfo1[entriesReturned];
- for( int i = 0; i < entriesReturned; i++ ) {
- results[i] = new ShareInfo1();
- results[i].netName = readString( buffer, bufferIndex, 13, false );
+ results = new ShareInfo1[numEntries];
+ for( int i = 0; i < numEntries; i++ ) {
+ results[i] = e = new ShareInfo1();
+ e.netName = readString( buffer, bufferIndex, 13, false );
bufferIndex += 14;
- results[i].type = readInt2( buffer, bufferIndex );
+ e.type = readInt2( buffer, bufferIndex );
bufferIndex += 2;
int off = readInt4( buffer, bufferIndex );
bufferIndex += 4;
off = ( off & 0xFFFF ) - converter;
off = start + off;
- results[i].remark = readString( buffer, off, 128, false );
-Log.println( Log.WARNINGS, "smb warning", results[i] );
+ e.remark = readString( buffer, off, 128, false );
+Log.println( Log.WARNINGS, "smb warning", e );
}
return bufferIndex - start;
super.toString() +
",status=" + status +
",converter=" + converter +
- ",entriesReturned=" + entriesReturned +
+ ",entriesReturned=" + numEntries +
",totalAvailableEntries=" + totalAvailableEntries + "]" );
}
}
}
}
}
+ static void writeTime( long t, byte[] dst, int dstIndex ) {
+
+ synchronized( TZ ) {
+ if( TZ.inDaylightTime( new Date() )) {
+ // in DST
+ if( TZ.inDaylightTime( new Date( t ))) {
+ // t also in DST so no correction
+ } else {
+ // t not in DST so subtract 1 hour
+ t -= 3600000;
+ }
+ } else {
+ // not in DST
+ if( TZ.inDaylightTime( new Date( t ))) {
+ // t is in DST so add 1 hour
+ t += 3600000;
+ } else {
+ // t isn't in DST either
+ }
+ }
+ }
+
+ t = (t + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L;
+
+ writeLong( t, dst, dstIndex );
+ }
static long readUTime( byte[] buffer, int bufferIndex ) {
return readInt4( buffer, bufferIndex ) * 1000L;
}
- static void writeTime( long t, byte[] dst, int dstIndex ) {
+ static void writeUTime( long t, byte[] dst, int dstIndex ) {
if( t == 0L || t == 0xFFFFFFFFFFFFFFFFL ) {
writeInt4( 0xFFFFFFFF, dst, dstIndex );
return;
long responseTimeout = 1;
int verifySequence;
boolean verifyFailed;
+ NtlmPasswordAuthentication auth = null;
+ String path;
ServerMessageBlock() {
flags = (byte)( FLAGS_PATH_NAMES_CASELESS | FLAGS_PATH_NAMES_CANONICALIZED );
public SmbAuthException( int code ) {
super( code );
}
+ public SmbAuthException( int errorClass, int errorCode ) {
+ super( errorClass, errorCode );
+ }
}
int writeParameterWordsWireFormat( byte[] dst, int dstIndex ) {
writeInt2( fid, dst, dstIndex );
dstIndex += 2;
- writeTime( lastWriteTime, dst, dstIndex );
+ writeUTime( lastWriteTime, dst, dstIndex );
return 6;
}
int writeBytesWireFormat( byte[] dst, int dstIndex ) {
class SmbComCreateDirectory extends ServerMessageBlock {
- String directoryName;
-
SmbComCreateDirectory( String directoryName ) {
- this.directoryName = directoryName;
+ this.path = directoryName;
command = SMB_COM_CREATE_DIRECTORY;
}
int start = dstIndex;
dst[dstIndex++] = (byte)0x04;
- dstIndex += writeString( directoryName, dst, dstIndex );
+ dstIndex += writeString( path, dst, dstIndex );
return dstIndex - start;
}
public String toString() {
return new String( "SmbComCreateDirectory[" +
super.toString() +
- ",directoryName=" + directoryName + "]" );
+ ",directoryName=" + path + "]" );
}
}
SmbComDelete( String fileName ) {
this.fileName = fileName;
command = SMB_COM_DELETE;
- searchAttributes = ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY;
+ searchAttributes = ATTR_HIDDEN | ATTR_SYSTEM;
}
int writeParameterWordsWireFormat( byte[] dst, int dstIndex ) {
class SmbComDeleteDirectory extends ServerMessageBlock {
- String directoryName;
-
SmbComDeleteDirectory( String directoryName ) {
- this.directoryName = directoryName;
+ this.path = directoryName;
command = SMB_COM_DELETE_DIRECTORY;
}
int start = dstIndex;
dst[dstIndex++] = (byte)0x04;
- dstIndex += writeString( directoryName, dst, dstIndex );
+ dstIndex += writeString( path, dst, dstIndex );
return dstIndex - start;
}
public String toString() {
return new String( "SmbComDeleteDirectory[" +
super.toString() +
- ",directoryName=" + directoryName + "]" );
+ ",directoryName=" + path + "]" );
}
}
static final int SECURITY_CONTEXT_TRACKING = 0x01;
static final int SECURITY_EFFECTIVE_ONLY = 0x02;
- String name;
int flags,
rootDirectoryFid,
desiredAccess,
long allocationSize;
byte securityFlags;
- SmbComNTCreateAndX( String name, int flags, ServerMessageBlock andx, int shareAccess ) {
+ SmbComNTCreateAndX( String name, int flags,
+ int shareAccess,
+ int extFileAttributes,
+ int createOptions,
+ ServerMessageBlock andx ) {
super( andx );
- this.name = name;
+ this.path = name;
command = SMB_COM_NT_CREATE_ANDX;
// desiredAccess
desiredAccess |= FILE_READ_EA | FILE_READ_ATTRIBUTES;
// extFileAttributes
- extFileAttributes = ATTR_NORMAL;
+ this.extFileAttributes = extFileAttributes;
// shareAccess
this.shareAccess = shareAccess;
}
}
- createOptions = 0x0040; // see netmon
+ this.createOptions = createOptions | 0x0040;
impersonationLevel = 0x02; // As seen on NT :~)
securityFlags = (byte)0x03; // SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY
}
dst[dstIndex++] = (byte)0x00;
// name length without counting null termination
- writeInt2( ( useUnicode ? name.length() * 2 : name.length() ), dst, dstIndex );
+ writeInt2( ( useUnicode ? path.length() * 2 : path.length() ), dst, dstIndex );
dstIndex += 2;
writeInt4( flags, dst, dstIndex );
dstIndex += 4;
return dstIndex - start;
}
int writeBytesWireFormat( byte[] dst, int dstIndex ) {
- return writeString( name, dst, dstIndex );
+ return writeString( path, dst, dstIndex );
}
int readParameterWordsWireFormat( byte[] buffer, int bufferIndex ) {
return 0;
",createOptions=0x" + Log.getHexString( createOptions, 8 ) +
",impersonationLevel=0x" + Log.getHexString( impersonationLevel, 4 ) +
",securityFlags=0x" + Log.getHexString( securityFlags, 2 ) +
- ",name=" + name + "]" );
+ ",name=" + path + "]" );
}
}
bufferIndex += 8;
changeTime = readTime( buffer, bufferIndex );
bufferIndex += 8;
-/* file attributes */
+ extFileAttributes = readInt4( buffer, bufferIndex );
+ bufferIndex += 4;
+/* file attributes? */
bufferIndex += 4;
allocationSize = readLong( buffer, bufferIndex );
bufferIndex += 8;
creationTime,
openFunction,
allocationSize;
- String fileName;
// flags is NOT the same as flags member
SmbComOpenAndX( String fileName, int flags, ServerMessageBlock andx ) {
super( andx );
- this.fileName = fileName;
+ this.path = fileName;
command = SMB_COM_OPEN_ANDX;
- // flags
-//why!! flags = 0;
-
// desiredAccess
desiredAccess = ( flags >>> 16 ) & 0x3;
if( desiredAccess == 0x3 ) {
- desiredAccess = 0x4;
+ desiredAccess = 0x2; /* Mmm, I thought 0x03 was RDWR */
}
desiredAccess |= SHARING_DENY_NONE;
desiredAccess &= ~0x1; // Win98 doesn't like GENERIC_READ ?! -- get Access Denied.
if( useUnicode ) {
dst[dstIndex++] = (byte)'\0';
}
- dstIndex += writeString( fileName, dst, dstIndex );
+ dstIndex += writeString( path, dst, dstIndex );
return dstIndex - start;
}
",creationTime=" + new Date( creationTime ) +
",openFunction=0x" + Log.getHexString( openFunction, 2 ) +
",allocationSize=" + allocationSize +
- ",fileName=" + fileName + "]" );
+ ",fileName=" + path + "]" );
}
}
class SmbComQueryInformation extends ServerMessageBlock {
- String filename;
-
SmbComQueryInformation( String filename ) {
- this.filename = filename;
+ path = filename;
command = SMB_COM_QUERY_INFORMATION;
}
int writeBytesWireFormat( byte[] dst, int dstIndex ) {
int start = dstIndex;
dst[dstIndex++] = (byte)0x04;
- dstIndex += writeString( filename, dst, dstIndex );
+ dstIndex += writeString( path, dst, dstIndex );
return dstIndex - start;
}
int readParameterWordsWireFormat( byte[] buffer, int bufferIndex ) {
public String toString() {
return new String( "SmbComQueryInformation[" +
super.toString() +
- ",filename=" + filename + "]" );
+ ",filename=" + path + "]" );
}
}
class SmbComQueryInformationResponse extends ServerMessageBlock implements Info {
int fileAttributes = 0x0000;
- long lastWriteTime = 0, serverTimeZoneOffset;
+ long lastWriteTime = 0L;
+ long serverTimeZoneOffset;
int fileSize = 0;
SmbComQueryInformationResponse( long serverTimeZoneOffset ) {
public int getAttributes() {
return fileAttributes;
}
+ public long getCreateTime() {
+ return lastWriteTime + serverTimeZoneOffset;
+ }
public long getLastWriteTime() {
return lastWriteTime + serverTimeZoneOffset;
}
static final byte TRANS2_FIND_NEXT2 = (byte)0x02;
static final byte TRANS2_QUERY_FS_INFORMATION = (byte)0x03;
static final byte TRANS2_QUERY_PATH_INFORMATION = (byte)0x05;
+ static final byte TRANS2_GET_DFS_REFERRAL = (byte)0x10;
+ static final byte TRANS2_SET_FILE_INFORMATION = (byte)0x08;
static final int NET_SHARE_ENUM = 0x0000;
static final int NET_SERVER_ENUM2 = 0x0068;
SmbComTransaction.TRANSACTION_BUF_SIZE ) - 512;
}
+ public void reset() {
+ isPrimary = hasMore = true;
+ }
+ public void reset( int key, String lastName ) {
+ reset();
+ }
public boolean hasMoreElements() {
return hasMore;
}
int bufParameterStart;
int bufDataStart;
+ /* for doNetEnum and doFindFirstNext */
+ int status;
+ int numEntries;
+ FileEntry[] results;
+
SmbComTransactionResponse() {
txn_buf = null;
}
return 0;
}
int readParameterWordsWireFormat( byte[] buffer, int bufferIndex ) {
- supportSearchBits = ( buffer[bufferIndex] & SMB_SUPPORT_SEARCH_BITS ) ==
- SMB_SUPPORT_SEARCH_BITS ? true : false;
- shareIsInDfs = ( buffer[bufferIndex] & SMB_SHARE_IS_IN_DFS ) ==
- SMB_SHARE_IS_IN_DFS ? true : false;
+ supportSearchBits = ( buffer[bufferIndex] & SMB_SUPPORT_SEARCH_BITS ) == SMB_SUPPORT_SEARCH_BITS;
+ shareIsInDfs = ( buffer[bufferIndex] & SMB_SHARE_IS_IN_DFS ) == SMB_SHARE_IS_IN_DFS;
return 2;
}
int readBytesWireFormat( byte[] buffer, int bufferIndex ) {
*/
public static final int ERRbadpw = 2;
/**
+ * Reserved (a.k.a. STATUS_PATH_NOT_COVERED)
+ */
+ public static final int ERRreserved = 3;
+/**
* The client does not have the necessary access rights for the requested function
*/
public static final int ERRaccess = 4;
public static final int ERRunknownHost = 5004;
public static final int ERRinappro = 5005;
public static final int ERRunknownType = 5006;
- public static final int ERRimpossible = 5007;
+ public static final int ERRdfs = 5007;
+ public static final int ERRhashesExternal = 5008;
+ public static final int ERRimpossible = 5009;
int errorClass;
int errorCode;
case ERRbadpw:
result += "Bad password";
break;
+ case ERRreserved:
+ result += "Reserved";
+ break;
case ERRinvnid:
result += "The Tid specified was invalid";
break;
case ERRunknownType:
result += "Unknown resource type";
break;
+ case ERRdfs:
+ result += "Invalid DFS operation";
+ break;
+ case ERRhashesExternal:
+ result += "The password hashes are external.";
+ break;
default:
result += "No description available [ERRCLI/" + errorCode + "]";
}
static final int O_TRUNC = 0x0002;
// file attribute encoding
- static final int ATTR_READONLY = 0x01;
- static final int ATTR_HIDDEN = 0x02;
- static final int ATTR_SYSTEM = 0x04;
- static final int ATTR_VOLUME = 0x08;
- static final int ATTR_DIRECTORY = 0x10;
- static final int ATTR_ARCHIVE = 0x20;
+ public static final int ATTR_READONLY = 0x01;
+ public static final int ATTR_HIDDEN = 0x02;
+ public static final int ATTR_SYSTEM = 0x04;
+ public static final int ATTR_VOLUME = 0x08;
+ public static final int ATTR_DIRECTORY = 0x10;
+ public static final int ATTR_ARCHIVE = 0x20;
+
+ // extended file attribute encoding(others same as above)
+ static final int ATTR_COMPRESSED = 0x800;
+ static final int ATTR_NORMAL = 0x080;
+ static final int ATTR_TEMPORARY = 0x100;
+
+ static final int ATTR_GET_MASK = 0x3F;
+ static final int ATTR_SET_MASK = 0x27;
static final int DEFAULT_ATTR_EXPIRATION_PERIOD = 5000;
+ static final int HASH_DOT = ".".hashCode();
+ static final int HASH_DOT_DOT = "..".hashCode();
+
static long attrExpirationPeriod;
static {
String share; // Can be null
int fid; // Initially 0; set by open()
int type;
+ long createTime;
long lastModified;
int attributes;
long attrExpiration;
boolean isExists;
int shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
SmbComBlankResponse blank_resp = new SmbComBlankResponse();
+ DfsReferral dfsReferral = null; // Only used by getDfsPath()
/**
this( new URL( null, url, Handler.SMB_HANDLER ), auth );
}
/**
+ * Constructs an SmbFile representing a file on an SMB network.
+The second parameter may be constructed explicitly or retreived with <tt>HttpServletRequest.getUserPrincipal()</tt> if NTLM HTTP authentication has been successfully negotiated.
+The <tt>shareAccess</tt> parameter controls what permissions other clients have when trying to access the same file while this instance is still open. This value is either <tt>FILE_NO_SHARE</tt> or any combination of <tt>FILE_SHARE_READ</tt>, <tt>FILE_SHARE_WRITE</tt>, and <tt>FILE_SHARE_DELETE</tt> logically OR'd together.
+ *
+ * @param url A URL string
+ * @param auth The credentials the client should use for authentication
+ * @param shareAccess Specifies what access other clients have while this file is open.
+ * @throws MalformedURLException
+ * If the <code>url</code> parameter does not follow the prescribed syntax
+ */
+ public SmbFile( String url, NtlmPasswordAuthentication auth, int shareAccess )
+ throws MalformedURLException {
+ this( new URL( null, url, Handler.SMB_HANDLER ), auth );
+ if ((shareAccess & ~(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)) != 0) {
+ throw new RuntimeException( "Illegal shareAccess parameter" );
+ }
+ this.shareAccess = shareAccess;
+ }
+/**
* Constructs an SmbFile representing a resource on an SMB network such
* as a file or directory. The second parameter is a relative path from
* the <code>context</code>. See the description above for examples of
getUncPath0();
}
SmbFile( SmbFile context, String name, int type,
- int attributes, long lastModified, long size )
+ int attributes, long createTime, long lastModified, long size )
throws MalformedURLException, UnknownHostException {
- this( context, name + (( attributes & ATTR_DIRECTORY ) > 0 ? "/" : "" ));
+ this( new URL( context.url, name + (( attributes & ATTR_DIRECTORY ) > 0 ? "/" : "" )));
if( context.share != null ) {
this.tree = context.tree;
}
}
this.type = type;
this.attributes = attributes;
+ this.createTime = createTime;
this.lastModified = lastModified;
this.size = size;
isExists = true;
attrExpiration = sizeExpiration =
System.currentTimeMillis() + attrExpirationPeriod;
}
-
void sendTransaction( SmbComTransaction request,
SmbComTransactionResponse response ) throws SmbException {
- connect0();
- tree.sendTransaction( request, response );
+ for( ;; ) {
+ connect0();
+ if( tree.inDfs ) {
+ DfsReferral dr = tree.session.transport.lookupReferral( unc );
+ if( dr != null ) {
+ UniAddress addr;
+ SmbTransport trans;
+
+ try {
+ addr = UniAddress.getByName( dr.server );
+ } catch( UnknownHostException uhe ) {
+ throw new SmbException( SmbException.ERRCLI, SmbException.ERRdfs, "unknown host: " + dr.server );
+ }
+
+ trans = SmbTransport.getSmbTransport( addr, 0 );
+ tree = trans.getSmbSession( auth ).getSmbTree( dr.share, null );
+ unc = request.path = dr.nodepath + unc.substring( dr.path.length() );
+ dfsReferral = dr; /* for getDfsPath */
+ }
+ }
+ if( tree.inDfs ) {
+ request.flags2 |= ServerMessageBlock.FLAGS2_RESOLVE_PATHS_IN_DFS;
+ } else {
+ request.flags2 &= ~ServerMessageBlock.FLAGS2_RESOLVE_PATHS_IN_DFS;
+ }
+ try {
+ tree.sendTransaction( request, response );
+ break;
+ } catch( DfsReferral dr ) {
+ if( dr.resolveHashes ) {
+ throw dr;
+ }
+ request.reset();
+ }
+ }
}
void send( ServerMessageBlock request,
ServerMessageBlock response ) throws SmbException {
- connect0();
- tree.send( request, response );
+ for( ;; ) {
+ connect0();
+ if( tree.inDfs ) {
+ DfsReferral dr = tree.session.transport.lookupReferral( unc );
+ if( dr != null ) {
+ UniAddress addr;
+ SmbTransport trans;
+
+ try {
+ addr = UniAddress.getByName( dr.server );
+ } catch( UnknownHostException uhe ) {
+ throw new SmbException( SmbException.ERRCLI, SmbException.ERRdfs, "unknown host: " + dr.server );
+ }
+
+ trans = SmbTransport.getSmbTransport( addr, 0 );
+ tree = trans.getSmbSession( auth ).getSmbTree( dr.share, null );
+ unc = request.path = dr.nodepath + unc.substring( dr.path.length() );
+ dfsReferral = dr; /* for getDfsPath */
+ }
+ request.flags2 |= ServerMessageBlock.FLAGS2_RESOLVE_PATHS_IN_DFS;
+ } else {
+ request.flags2 &= ~ServerMessageBlock.FLAGS2_RESOLVE_PATHS_IN_DFS;
+ }
+ try {
+ tree.send( request, response );
+ break;
+ } catch( DfsReferral dr ) {
+ if( dr.resolveHashes ) {
+ throw dr;
+ }
+ }
+ }
}
UniAddress getAddress() throws UnknownHostException {
boolean isConnected() {
return (connected = tree != null && tree.treeConnected);
}
- void open( int flags ) throws SmbException {
- if( isOpen() ) {
- return;
- }
+ int open0( int flags, int attrs, int options ) throws SmbException {
+ int f;
+
connect0();
Log.println( Log.WARNINGS, "smb open warning: ", unc );
/*
* Open AndX Request / Response
*/
-
if( tree.session.transport.hasCapability( ServerMessageBlock.CAP_NT_SMBS )) {
SmbComNTCreateAndXResponse response = new SmbComNTCreateAndXResponse();
- send( new SmbComNTCreateAndX( unc, flags, null, shareAccess ), response );
- fid = response.fid;
+ send( new SmbComNTCreateAndX( unc, flags, shareAccess, attrs, options, null ), response );
+ f = response.fid;
+ attributes = response.extFileAttributes & 0x3F;
+ attrExpiration = System.currentTimeMillis() + attrExpirationPeriod;
+ isExists = true;
} else {
SmbComOpenAndXResponse response = new SmbComOpenAndXResponse();
send( new SmbComOpenAndX( unc, flags, null ), response );
- fid = response.fid;
+ f = response.fid;
}
+ return f;
+ }
+ void open( int flags, int attrs, int options ) throws SmbException {
+ if( isOpen() ) {
+ return;
+ }
+ fid = open0( flags, attrs, options );
opened = true;
}
boolean isOpen() {
return opened && isConnected();
}
- void close() throws SmbException {
- close( 0L );
- }
- void close( long lastWriteTime ) throws SmbException {
- if( isOpen() == false ) {
- return;
- }
+ void close( int f, long lastWriteTime ) throws SmbException {
- opened = false;
-
- Log.println( Log.WARNINGS, "smb close warning", " fid=" + fid );
+ Log.println( Log.WARNINGS, "smb close warning", " fid=" + f );
/*
* Close Request / Response
*/
- send( new SmbComClose( fid, lastWriteTime ), blank_resp );
+ send( new SmbComClose( f, lastWriteTime ), blank_resp );
+ }
+ void close( long lastWriteTime ) throws SmbException {
+ if( isOpen() == false ) {
+ return;
+ }
+ close( fid, lastWriteTime );
+ opened = false;
+ }
+ void close() throws SmbException {
+ close( 0L );
}
/**
*
* @return The UNC path.
*/
-
public String getUncPath() {
- String path = getUncPath0();
+ getUncPath0();
if( share == null ) {
return "\\\\" + url.getHost();
}
- return "\\\\" + url.getHost() + "\\" + share + path;
+ return "\\\\" + url.getHost() + canon.replace( '/', '\\' );
}
/**
* Returns the full URL of this SMB resource with '.' and '..' components
try {
addr = getAddress();
} catch( UnknownHostException uhe ) {
- throw new SmbException( SmbException.ERRCLI |
+ throw new SmbException( SmbException.ERRCLI,
SmbException.ERRunknownHost,
"Unknown host: " + uhe.getMessage() );
}
* to(overrides negotiatedCapabilities).
*/
+ /* We really should do the referral before this in case
+ * the redirected target has different capabilities. But
+ * the way we have been doing that is to call exists() which
+ * calls this method so another technique will be necessary
+ * to support DFS referral _to_ Win95/98/ME.
+ */
+
if( tree.session.transport.hasCapability( ServerMessageBlock.CAP_NT_SMBS )) {
/*
}
attributes = ATTR_READONLY | ATTR_DIRECTORY;
+ createTime = 0L;
lastModified = 0L;
isExists = false;
try {
if( url.getHost().length() == 0 ) {
} else if( share == null ) {
- if( true || type == TYPE_WORKGROUP ) {
+ if( type == TYPE_WORKGROUP ) {
UniAddress.getByName( url.getHost(), true );
} else {
UniAddress.getByName( url.getHost() ).getHostName();
Info info = queryPath( getUncPath0(),
Trans2QueryPathInformationResponse.SMB_QUERY_FILE_BASIC_INFO );
attributes = info.getAttributes();
+ createTime = info.getCreateTime();
lastModified = info.getLastWriteTime();
}
}
/**
+ * Retrieves the DFS path or <tt>null</tt> if the path specified does not fall within a DFS volume.
+ */
+
+ public String getDfsPath() throws SmbException {
+ connect0();
+ if( tree.inDfs ) {
+ exists();
+ }
+ if( dfsReferral == null ) {
+ return null;
+ }
+ return "smb:/" + (new String( dfsReferral.node + unc )).replace( '\\', '/' );
+ }
+
+/**
+ * Retrieve the time this <code>SmbFile</code> was created. The value returned is suitable
+ * for constructing a {@link java.util.Date} object and is adjusted for
+ * the servers timezone differential. Times should be the same as those
+ * reported using the properties dialog of the Windows Explorer program.
+ *
+ * For Win95/98/Me this is actually the last write time. It is currently
+ * not possible to retrieve the create time from files on these systems.
+ *
+ * @return The number of milliseconds since the 00:00:00 GMT, January 1,
+ * 1970 as a <code>long</code> value
+ */
+
+ public long createTime() throws SmbException {
+ if( getUncPath0().length() > 1 ) {
+ exists();
+ return createTime;
+ }
+ return 0L;
+ }
+/**
* Retrieve the last time the file represented by this
* <code>SmbFile</code> was modified. The value returned is suitable
* for constructing a {@link java.util.Date} object and is adjusted for
*/
public String[] list() throws SmbException {
- ArrayList list = new ArrayList();
-
- connect0();
-
- if( url.getHost().length() == 0 ) {
- NetServerEnum2Response response = new NetServerEnum2Response();
- sendTransaction( new NetServerEnum2(
- tree.session.transport.server.oemDomainName,
- NetServerEnum2.SV_TYPE_DOMAIN_ENUM ), response );
-
- if( response.status != SmbException.NERR_Success &&
- response.status != SmbException.ERROR_MORE_DATA ) {
- throw new SmbException( SmbException.ERRRAP,
- response.status, response.toString() );
- }
-
- for( int i = 0; i < response.entriesReturned; i++ ) {
- if( response.results[i].name.length() > 0 ) {
- list.add( response.results[i].name );
- }
- }
- return (String[])list.toArray( new String[list.size()] );
- } else if( share == null ) {
- if( getType() == TYPE_WORKGROUP ) {
- NetServerEnum2Response response = new NetServerEnum2Response();
- sendTransaction( new NetServerEnum2( url.getHost(),
- NetServerEnum2.SV_TYPE_ALL ), response );
-
- if( response.status != SmbException.NERR_Success &&
- response.status != SmbException.ERROR_MORE_DATA ) {
- throw new SmbException( SmbException.ERRRAP, response.status );
- }
-
- for( int i = 0; i < response.entriesReturned; i++ ) {
- if( response.results[i].name.length() > 0 ) {
- list.add( response.results[i].name );
- }
- }
-
- return (String[])list.toArray( new String[list.size()] );
- } else {
- NetShareEnumResponse response = new NetShareEnumResponse();
- sendTransaction( new NetShareEnum(), response );
-
- if( response.status != SmbException.NERR_Success &&
- response.status != SmbException.ERROR_MORE_DATA ) {
- throw new SmbException( SmbException.ERRRAP, response.status );
- }
-
- for( int i = 0; i < response.entriesReturned; i++ ) {
- list.add( response.results[i].netName );
- }
-
- return (String[])list.toArray( new String[list.size()] );
- }
- } else {
- return list( unc );
- }
+ return list( "*", ATTR_DIRECTORY | ATTR_SYSTEM, null, null );
}
- String[] list( String dirPath ) throws SmbException {
- int sid, count, i;
- String filename;
- ArrayList list = new ArrayList();
-
- Log.println( Log.WARNINGS, "smb find warning",
- " find with path=" + dirPath );
-
- Trans2FindFirst2Response response = new Trans2FindFirst2Response();
- sendTransaction( new Trans2FindFirst2( dirPath + "\\*" ), response );
-
- sid = response.sid;
- count = response.searchCount;
-
- int h1 = new String( "." ).hashCode();
- int h2 = new String( ".." ).hashCode();
-
- for( i = 0; i < count; i++ ) {
- filename = response.results[i].filename;
- if( filename.length() < 3 ) {
- int h = filename.hashCode();
- if( h == h1 || h == h2 ) {
- continue;
- }
- }
- list.add( filename );
- }
-
- /* only difference between first2 and next2
- * responses is subCommand so let's recycle
- */
- response.subCommand = SmbComTransaction.TRANS2_FIND_NEXT2;
-
- while( response.isEndOfSearch == false && response.searchCount > 0 ) {
- response.reset();
- sendTransaction( new Trans2FindNext2( sid, response.resumeKey,
- response.lastName ), response );
- count = response.searchCount;
-
- for( i = 0; i < count; i++ ) {
- filename = response.results[i].filename;
- if( filename.length() < 3 ) {
- int h = filename.hashCode();
- if( h == h1 || h == h2 ) {
- continue;
- }
- }
- list.add( filename );
- }
- }
-
- send( new SmbComFindClose2( sid ), blank_resp );
-
- return (String[])list.toArray( new String[list.size()] );
+ public String[] list( SmbFilenameFilter filter ) throws SmbException {
+ return list( "*", ATTR_DIRECTORY | ATTR_SYSTEM, filter, null );
}
/**
*/
public SmbFile[] listFiles() throws SmbException {
- return listFiles( "*" );
+ return listFiles( "*", ATTR_DIRECTORY | ATTR_SYSTEM, null, null );
}
/**
*/
public SmbFile[] listFiles( String wildcard ) throws SmbException {
+ return listFiles( wildcard, ATTR_DIRECTORY | ATTR_SYSTEM, null, null );
+ }
+ public SmbFile[] listFiles( SmbFilenameFilter filter ) throws SmbException {
+ return listFiles( "*", ATTR_DIRECTORY | ATTR_SYSTEM, filter, null );
+ }
+ public SmbFile[] listFiles( SmbFileFilter filter ) throws SmbException {
+ return listFiles( "*", ATTR_DIRECTORY | ATTR_SYSTEM, null, filter );
+ }
+ String[] list( String wildcard, int searchAttributes,
+ SmbFilenameFilter fnf, SmbFileFilter ff ) throws SmbException {
ArrayList list = new ArrayList();
- if( url.toString().lastIndexOf( '/' ) != ( url.toString().length() - 1 )) {
+ try {
+ if( url.getHost().length() == 0 || share == null ) {
+ doNetEnum( list, false, wildcard, searchAttributes, fnf, ff );
+ } else {
+ doFindFirstNext( list, false, wildcard, searchAttributes, fnf, ff );
+ }
+ } catch( UnknownHostException uhe ) {
throw new SmbException( SmbException.ERRCLI,
- SmbException.ERRlistFiles, url.toString() + " directory must end with '/'" );
+ SmbException.ERRunknownHost, url.toString() );
+ } catch( MalformedURLException mue ) {
+ throw new SmbException( SmbException.ERRCLI,
+ SmbException.ERRlistFiles, url.toString() );
}
- try {
- if( url.getHost().length() == 0 ) {
- connect0();
-
- NetServerEnum2Response response = new NetServerEnum2Response();
- sendTransaction( new NetServerEnum2(
- tree.session.transport.server.oemDomainName,
- NetServerEnum2.SV_TYPE_DOMAIN_ENUM ), response );
-
- if( response.status != SmbException.NERR_Success &&
- response.status != SmbException.ERROR_MORE_DATA ) {
- throw new SmbException( SmbException.ERRRAP,
- response.status, response.toString() );
- }
- for( int i = 0; i < response.entriesReturned; i++ ) {
- if( response.results[i].name.length() > 0 ) {
- list.add( new SmbFile( this,
- response.results[i].name,
- TYPE_WORKGROUP,
- ATTR_READONLY | ATTR_DIRECTORY,
- 0L,
- 0L ));
- }
- }
-//System.err.println( "ret=" + ret.length + ",ret[0]=" + ret[0] + ",name=" + response.results[0].name );
-
- return (SmbFile[])list.toArray(new SmbFile[list.size()]);
- } else if( share == null ) {
- if( getType() == TYPE_WORKGROUP ) {
- NetServerEnum2Response response = new NetServerEnum2Response();
- sendTransaction( new NetServerEnum2( url.getHost(),
- NetServerEnum2.SV_TYPE_ALL ), response );
-
- if( response.status != SmbException.NERR_Success &&
- response.status != SmbException.ERROR_MORE_DATA ) {
- throw new SmbException( SmbException.ERRRAP, response.status );
- }
-
- for( int i = 0; i < response.entriesReturned; i++ ) {
- if( response.results[i].name.length() > 0 ) {
- list.add( new SmbFile( this,
- response.results[i].name,
- TYPE_SERVER,
- ATTR_READONLY | ATTR_DIRECTORY,
- 0L,
- 0L ));
- }
- }
+ return (String[])list.toArray(new String[list.size()]);
+ }
+ SmbFile[] listFiles( String wildcard, int searchAttributes,
+ SmbFilenameFilter fnf, SmbFileFilter ff ) throws SmbException {
+ ArrayList list = new ArrayList();
- return (SmbFile[])list.toArray(new SmbFile[list.size()]);
- } else {
- NetShareEnumResponse response = new NetShareEnumResponse();
- sendTransaction( new NetShareEnum(), response );
-
- if( response.status != SmbException.NERR_Success &&
- response.status != SmbException.ERROR_MORE_DATA ) {
- throw new SmbException( SmbException.ERRRAP, response.status );
- }
+ if( ff != null && ff instanceof DosFileFilter ) {
+ DosFileFilter dff = (DosFileFilter)ff;
+ if( dff.wildcard != null ) {
+ wildcard = dff.wildcard;
+ }
+ searchAttributes = dff.attributes;
+ }
- for( int i = 0; i < response.entriesReturned; i++ ) {
- int shareType = response.results[i].type;
- switch( shareType ) {
- case 1:
- shareType = TYPE_PRINTER;
- break;
- case 3:
- shareType = TYPE_NAMED_PIPE;
- break;
- default:
- shareType = TYPE_SHARE;
- break;
- }
- list.add( new SmbFile( this,
- response.results[i].netName,
- shareType,
- ATTR_READONLY | ATTR_DIRECTORY,
- 0L,
- 0L ));
- }
- return (SmbFile[])list.toArray(new SmbFile[list.size()]);
- }
+ try {
+ if( url.getHost().length() == 0 || share == null ) {
+ doNetEnum( list, true, wildcard, searchAttributes, fnf, ff );
} else {
- return listFiles( getUncPath0(), wildcard );
+ doFindFirstNext( list, true, wildcard, searchAttributes, fnf, ff );
}
} catch( UnknownHostException uhe ) {
throw new SmbException( SmbException.ERRCLI,
throw new SmbException( SmbException.ERRCLI,
SmbException.ERRlistFiles, url.toString() );
}
+
+ return (SmbFile[])list.toArray(new SmbFile[list.size()]);
}
- SmbFile[] listFiles( String dirPath, String wildcard ) throws SmbException {
- int sid, count, i;
- String base, filename;
- ArrayList list = new ArrayList();
+ void doNetEnum( ArrayList list,
+ boolean files,
+ String wildcard,
+ int searchAttributes,
+ SmbFilenameFilter fnf,
+ SmbFileFilter ff ) throws SmbException, UnknownHostException, MalformedURLException {
+ SmbComTransaction req;
+ SmbComTransactionResponse resp;
+ int listType = url.getAuthority().length() == 0 ? 0 : getType();
- Log.println( Log.WARNINGS, "smb find warning",
- " find with path=" + dirPath );
+ if( url.toString().lastIndexOf( '/' ) != ( url.toString().length() - 1 )) {
+ throw new SmbException( SmbException.ERRCLI,
+ SmbException.ERRlistFiles, url.toString() + " directory must end with '/'" );
+ }
- Trans2FindFirst2Response response = new Trans2FindFirst2Response();
- if( dirPath.equals( "\\" )) {
- filename = "\\" + wildcard;
- } else {
- filename = dirPath + "\\" + wildcard;
+ switch( listType ) {
+ case 0:
+ connect0();
+ req = new NetServerEnum2( tree.session.transport.server.oemDomainName,
+ NetServerEnum2.SV_TYPE_DOMAIN_ENUM );
+ resp = new NetServerEnum2Response();
+ break;
+ case TYPE_WORKGROUP:
+ req = new NetServerEnum2( url.getHost(), NetServerEnum2.SV_TYPE_ALL );
+ resp = new NetServerEnum2Response();
+ break;
+ case TYPE_SERVER:
+ req = new NetShareEnum();
+ resp = new NetShareEnumResponse();
+ break;
+ default:
+ throw new SmbException( SmbException.ERRCLI,
+ SmbException.ERRlistFiles, "invalid list operation: " + url.toString() );
}
- sendTransaction( new Trans2FindFirst2( filename ), response );
- sid = response.sid;
- count = response.searchCount;
+ sendTransaction( req, resp );
- int h1 = new String( "." ).hashCode();
- int h2 = new String( ".." ).hashCode();
- try {
- for( i = 0; i < count; i++ ) {
- filename = response.results[i].filename;
- if( filename.length() < 3 ) {
- int h = filename.hashCode();
- if( h == h1 || h == h2 ) {
- continue;
- }
+ if( resp.status != SmbException.NERR_Success &&
+ resp.status != SmbException.ERROR_MORE_DATA ) {
+ throw new SmbException( SmbException.ERRRAP, resp.status, resp.toString() );
+ }
+
+ for( int i = 0; i < resp.numEntries; i++ ) {
+ FileEntry e = resp.results[i];
+ String name = e.getName();
+ if( fnf != null && fnf.accept( this, name ) == false ) {
+ continue;
+ }
+ if( name.length() > 0 ) {
+ SmbFile f = new SmbFile( this, name,
+ listType == 0 ? TYPE_WORKGROUP : listType,
+ ATTR_READONLY | ATTR_DIRECTORY, 0L, 0L, 0L );
+ if( ff != null && ff.accept( f ) == false ) {
+ continue;
+ }
+ if( files ) {
+ list.add( f );
+ } else {
+ list.add( name );
}
- list.add( new SmbFile( this,
- filename,
- TYPE_FILESYSTEM,
- response.results[i].extFileAttributes,
- response.results[i].lastWriteTime,
- response.results[i].endOfFile ));
}
+ }
+ }
+ void doFindFirstNext( ArrayList list,
+ boolean files,
+ String wildcard,
+ int searchAttributes,
+ SmbFilenameFilter fnf,
+ SmbFileFilter ff ) throws SmbException, UnknownHostException, MalformedURLException {
+ SmbComTransaction req;
+ Trans2FindFirst2Response resp;
+ int sid;
+ String path = getUncPath0();
- /* only difference between first2 and next2
- * responses is subCommand so let's recycle
- */
- response.subCommand = SmbComTransaction.TRANS2_FIND_NEXT2;
-
- while( response.isEndOfSearch == false && response.searchCount > 0 ) {
- response.reset();
- sendTransaction( new Trans2FindNext2( sid, response.resumeKey,
- response.lastName ), response );
- count = response.searchCount;
-
- for( i = 0; i < count; i++ ) {
- filename = response.results[i].filename;
- if( filename.length() < 3 ) {
- int h = filename.hashCode();
- if( h == h1 || h == h2 ) {
- continue;
- }
+ if( url.toString().lastIndexOf( '/' ) != ( url.toString().length() - 1 )) {
+ throw new SmbException( SmbException.ERRCLI,
+ SmbException.ERRlistFiles, url.toString() + " directory must end with '/'" );
+ }
+
+ req = new Trans2FindFirst2( path, wildcard, searchAttributes );
+ resp = new Trans2FindFirst2Response();
+
+ Log.println( Log.WARNINGS, "smb find warning",
+ " find with path=" + req.path );
+
+ sendTransaction( req, resp );
+
+ sid = resp.sid;
+ req = new Trans2FindNext2( sid, resp.resumeKey, resp.lastName );
+
+ /* The only difference between first2 and next2 responses is subCommand
+ * so let's recycle the response object.
+ */
+ resp.subCommand = SmbComTransaction.TRANS2_FIND_NEXT2;
+
+ for( ;; ) {
+ for( int i = 0; i < resp.numEntries; i++ ) {
+ FileEntry e = resp.results[i];
+ String name = e.getName();
+ if( name.length() < 3 ) {
+ int h = name.hashCode();
+ if( h == HASH_DOT || h == HASH_DOT_DOT ) {
+ continue;
+ }
+ }
+ if( fnf != null && fnf.accept( this, name ) == false ) {
+ continue;
+ }
+ if( name.length() > 0 ) {
+ SmbFile f = new SmbFile( this, name, TYPE_FILESYSTEM,
+ e.getAttributes(), e.createTime(), e.lastModified(), e.length() );
+ if( ff != null && ff.accept( f ) == false ) {
+ continue;
+ }
+ if( files ) {
+ list.add( f );
+ } else {
+ list.add( name );
}
- list.add( new SmbFile( this,
- filename,
- TYPE_FILESYSTEM,
- response.results[i].extFileAttributes,
- response.results[i].lastWriteTime,
- response.results[i].endOfFile ));
}
}
- } catch( UnknownHostException uhe ) {
- throw new SmbException( SmbException.ERRCLI,
- SmbException.ERRunknownHost, url.toString() );
- } catch( MalformedURLException mue ) {
- throw new SmbException( SmbException.ERRCLI,
- SmbException.ERRlistFiles, "Malformed URL: " + url.toString() );
+
+ if( resp.isEndOfSearch || resp.numEntries == 0 ) {
+ break;
+ }
+
+ req.reset( resp.resumeKey, resp.lastName );
+ resp.reset();
+ sendTransaction( req, resp );
}
send( new SmbComFindClose2( sid ), blank_resp );
-
- return (SmbFile[])list.toArray(new SmbFile[list.size()]);
}
+
/**
* Changes the name of the file this <code>SmbFile</code> represents to the name
* designated by the <code>SmbFile</code> argument(Remember:
}
connect0();
dest.connect0();
+
+ if( tree.inDfs ) { /* This ensures that each path is
+ * resolved independantly to deal with the case where files
+ * have the same base path but ultimately turn out to be
+ * on different servers because of DFS. It also eliminates
+ * manipulating the SMB path which is problematic because
+ * there are really two that would need to be prefixed
+ * with host and share as DFS requires.
+ */
+ exists();
+ dest.exists();
+ }
if( tree != dest.tree ) {
throw new SmbException( SmbException.ERRDOS,
SmbException.ERRnoaccess,
if( attrExpiration < System.currentTimeMillis() ) {
attributes = ATTR_READONLY | ATTR_DIRECTORY;
+ createTime = 0L;
lastModified = 0L;
isExists = false;
Info info = queryPath( getUncPath0(),
Trans2QueryPathInformationResponse.SMB_QUERY_FILE_BASIC_INFO );
attributes = info.getAttributes();
+ createTime = info.getCreateTime();
lastModified = info.getLastWriteTime();
/* If any of the above fails, isExists will not be set true
}
}
- files = listFiles();
+ files = listFiles( "*", ATTR_DIRECTORY | ATTR_HIDDEN | ATTR_SYSTEM, null, null );
try {
for( i = 0; i < files.length; i++ ) {
ndest = new SmbFile( dest,
files[i].getName(),
files[i].type,
files[i].attributes,
+ files[i].createTime,
files[i].lastModified,
files[i].size );
files[i].copyTo0( ndest, b, bsize, w, req, resp );
}
} else {
int off;
+ long mtime;
- open( SmbFile.O_RDONLY );
- dest.open( SmbFile.O_CREAT | SmbFile.O_WRONLY | SmbFile.O_TRUNC );
+ open( SmbFile.O_RDONLY, ATTR_NORMAL, 0 );
+ try {
+ dest.open( SmbFile.O_CREAT | SmbFile.O_WRONLY | SmbFile.O_TRUNC |
+ SmbComNTCreateAndX.FILE_WRITE_ATTRIBUTES << 16, attributes, 0 );
+ } catch( SmbAuthException sae ) {
+ if(( dest.attributes & ATTR_READONLY ) != 0 ) {
+ /* Remove READONLY and try again
+ */
+ dest.setPathInformation( dest.attributes & ~ATTR_READONLY, 0L, 0L );
+ dest.open( SmbFile.O_CREAT | SmbFile.O_WRONLY | SmbFile.O_TRUNC |
+ SmbComNTCreateAndX.FILE_WRITE_ATTRIBUTES << 16, attributes, 0 );
+ } else {
+ throw sae;
+ }
+ }
i = off = 0;
for( ;; ) {
i = i == 1 ? 0 : 1;
off += resp.dataLength;
}
- dest.close( lastModified - tree.session.transport.server.serverTimeZone * 60 * 1000 );
+
+ mtime = lastModified - tree.session.transport.server.serverTimeZone * 60 * 1000;
+ /* It doesn't look like the createTime should be adjusted (shrug)
+ */
+ dest.sendTransaction( new Trans2SetFileInformation( dest.fid, attributes, createTime, mtime ),
+ new Trans2SetFileInformationResponse() );
+ dest.close( mtime );
close();
}
}
/**
- * This method will copy the file or directory and it's subcontents represented by this <tt>SmbFile</tt> to the location specified by the <tt>dest</tt> parameter. This file and the destination file do not need to be on the same host. This operation does not copy extended file attibutes and files copied to NT 4.0 will not preserve file modification times.
-*/
+ * This method will copy the file or directory and it's subcontents
+ * represented by this <tt>SmbFile</tt> to the location specified by the
+ * <tt>dest</tt> parameter. This file and the destination file do not
+ * need to be on the same host. This operation does not copy extended
+ * file attibutes such as ACLs but regular attributes and create and
+ * last write times will be preserved.
+ */
public void copyTo( SmbFile dest ) throws SmbException {
SmbComReadAndX req;
SmbComReadAndXResponse resp;
/* Should be able to copy an entire share actually
*/
- if( getUncPath0().length() == 1 || dest.getUncPath0().length() == 1 ) {
+ if( share == null || dest.share == null) {
throw new SmbException( SmbException.ERRDOS,
SmbException.ERRnoaccess,
"Cannot copyTo workgroups, servers, or shares" );
connect0();
dest.connect0();
+ if( tree.inDfs ) {
+ /* At this point the maxBufferSize values are from the server
+ * exporting the volumes, not the one that we will actually
+ * end up performing IO with. If the server hosting the
+ * actual files has a smaller maxBufSize this could be
+ * incorrect. To handle this properly it is necessary
+ * to redirect the tree to the target server first before
+ * establishing buffer size. These exists() calls facilitate
+ * that.
+ */
+ exists();
+ dest.exists();
+ }
+
w = new WriterThread();
w.setDaemon( true );
w.start();
/**
* This method will delete the file or directory specified by this
* <code>SmbFile</code>. If the target is a directory, the contents of
- * the directory will be deleted as well. If the resource or sub-resource
- * is marked read-only or is locked the operation will fail. There is currently no functionality to set the attributes of a file, break locks, or disconnect users.
+ * the directory will be deleted as well. If a file within the directory or
+ * it's sub-directories is marked read-only, the read-only status will be removed and the file will be deleted.
*
* @throws SmbException
*/
public void delete() throws SmbException {
- delete( getUncPath0() );
+ if( tree == null || tree.inDfs ) {
+ exists(); /* This is necessary to ensure we
+ * pass a path adjusted for DFS */
+ }
+ getUncPath0();
+ delete( unc );
}
void delete( String fileName ) throws SmbException {
if( getUncPath0().length() == 1 ) {
SmbException.ERRnoaccess );
}
+ if( System.currentTimeMillis() > attrExpiration ) {
+ attributes = ATTR_READONLY | ATTR_DIRECTORY;
+ createTime = 0L;
+ lastModified = 0L;
+ isExists = false;
+
+ Info info = queryPath( getUncPath0(),
+ Trans2QueryPathInformationResponse.SMB_QUERY_FILE_BASIC_INFO );
+ attributes = info.getAttributes();
+ createTime = info.getCreateTime();
+ lastModified = info.getLastWriteTime();
+
+ attrExpiration = System.currentTimeMillis() + attrExpirationPeriod;
+ isExists = true;
+ }
+
+ if(( attributes & ATTR_READONLY ) != 0 ) {
+ setReadWrite();
+ }
+
/*
* Delete or Delete Directory Request / Response
*/
- if( isDirectory() ) {
+ if(( attributes & ATTR_DIRECTORY ) != 0 ) {
/* Recursively delete directory contents
*/
- SmbFile[] l = listFiles( fileName, "*" );
+ SmbFile[] l = listFiles( "*", ATTR_DIRECTORY | ATTR_HIDDEN | ATTR_SYSTEM, null, null );
for( int i = 0; i < l.length; i++ ) {
l[i].delete();
mkdir();
}
+ public void createNewFile() throws SmbException {
+ if( getUncPath0().length() == 1 ) {
+ throw new SmbException( SmbException.ERRDOS,
+ SmbException.ERRnoaccess );
+ }
+ close( open0( O_RDWR | O_EXCL, ATTR_NORMAL, 0 ), 0L );
+ }
+
+ void setPathInformation( int attrs, long ctime, long mtime ) throws SmbException {
+ int f = open0( O_RDONLY | SmbComNTCreateAndX.FILE_WRITE_ATTRIBUTES << 16, attrs, 0 );
+
+ sendTransaction( new Trans2SetFileInformation( f, attrs, ctime, mtime ), new Trans2SetFileInformationResponse() );
+
+ close( f, 0L );
+
+ attrExpiration = 0;
+ }
+
+ public void setCreateTime( long time ) throws SmbException {
+ if( getUncPath0().length() == 1 ) {
+ throw new SmbException( SmbException.ERRDOS,
+ SmbException.ERRnoaccess );
+ }
+
+ setPathInformation( 0, time, 0L );
+ }
+ public void setLastModified( long time ) throws SmbException {
+ if( getUncPath0().length() == 1 ) {
+ throw new SmbException( SmbException.ERRDOS,
+ SmbException.ERRnoaccess );
+ }
+
+ setPathInformation( 0, 0L, time );
+ }
+
+ public int getAttributes() throws SmbException {
+ if( getUncPath0().length() == 1 ) {
+ return 0;
+ }
+ exists();
+ return attributes & ATTR_GET_MASK;
+ }
+
+ public void setAttributes( int attrs ) throws SmbException {
+ if( getUncPath0().length() == 1 ) {
+ throw new SmbException( SmbException.ERRDOS,
+ SmbException.ERRnoaccess );
+ }
+
+ setPathInformation( attrs & ATTR_SET_MASK, 0L, 0L );
+ }
+
+ public void setReadOnly() throws SmbException {
+ setAttributes( getAttributes() | ATTR_READONLY );
+ }
+
+ public void setReadWrite() throws SmbException {
+ setAttributes( getAttributes() & ~ATTR_READONLY );
+ }
+
/**
* Returns a {@link java.net.URL} for this <code>SmbFile</code>. The
* <code>URL</code> may be used as any other <code>URL</code> might to
--- /dev/null
+/* jcifs smb client library in Java
+ * Copyright (C) 2003 "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 jcifs.smb;
+
+public interface SmbFileFilter {
+ public boolean accept( SmbFile file ) throws SmbException;
+}
SmbFileInputStream( SmbFile file, int openFlags ) throws SmbException, MalformedURLException, UnknownHostException {
this.file = file;
this.openFlags = openFlags;
- file.open( openFlags );
+ file.open( openFlags, SmbFile.ATTR_NORMAL, 0 );
readSize = Math.min( file.tree.session.transport.rcv_buf_size - 70,
file.tree.session.transport.server.maxBufferSize - 70 );
}
long start = fp;
// ensure file is open
- file.open( openFlags );
+ file.open( openFlags, SmbFile.ATTR_NORMAL, 0 );
//Log.println( Log.WARNINGS, "smb read warning", " fid=" + file.fid + ",off=" + off + ",len=" + len );
}
pipe = (SmbNamedPipe)file;
- file.open(( pipe.pipeType & 0xFF0000 ) | SmbFile.O_EXCL );
+ file.open(( pipe.pipeType & 0xFF0000 ) | SmbFile.O_EXCL, SmbFile.ATTR_NORMAL, 0 );
req = new TransPeekNamedPipe( file.unc, file.fid );
resp = new TransPeekNamedPipeResponse( pipe );
fp = 0L;\r
}\r
}\r
- file.open( openFlags );\r
+ file.open( openFlags, SmbFile.ATTR_NORMAL, 0 );\r
writeSize = Math.min( file.tree.session.transport.snd_buf_size - 70,\r
file.tree.session.transport.server.maxBufferSize - 70 );\r
\r
\r
// ensure file is open\r
if( file.isOpen() == false ) {\r
- file.open( openFlags );\r
+ file.open( openFlags, SmbFile.ATTR_NORMAL, 0 );\r
if( append ) {\r
fp = file.length();\r
}\r
--- /dev/null
+/* jcifs smb client library in Java
+ * Copyright (C) 2003 "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 jcifs.smb;
+
+public interface SmbFilenameFilter {
+ public boolean accept( SmbFile dir, String name ) throws SmbException;
+}
--- /dev/null
+/* jcifs smb client library in Java
+ * Copyright (C) 2003 "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 jcifs.smb;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.UnknownHostException;
+import jcifs.util.Encdec;
+
+public class SmbRandomAccessFile implements DataOutput, DataInput {
+
+ private static final int WRITE_OPTIONS = 0x0842;
+
+ SmbFile file;
+ long fp;
+ int openFlags, readSize, writeSize, ch, options = 0;
+ byte[] tmp = new byte[8];
+ SmbComWriteAndXResponse write_andx_resp = null;
+
+ public SmbRandomAccessFile( String url, String mode, int shareAccess )
+ throws SmbException, MalformedURLException, UnknownHostException {
+ this( new SmbFile( url, "", null, shareAccess ), mode );
+ }
+ public SmbRandomAccessFile( SmbFile file, String mode )
+ throws SmbException, MalformedURLException, UnknownHostException {
+ this.file = file;
+ if( mode.equals( "r" )) {
+ this.openFlags = SmbFile.O_CREAT | SmbFile.O_RDONLY;
+ } else if( mode.equals( "rw" )) {
+ this.openFlags = SmbFile.O_CREAT | SmbFile.O_RDWR | SmbFile.O_APPEND;
+ write_andx_resp = new SmbComWriteAndXResponse();
+ options = WRITE_OPTIONS;
+ } else {
+ throw new IllegalArgumentException( "Invalid mode" );
+ }
+ file.open( openFlags, SmbFile.ATTR_NORMAL, options );
+ readSize = Math.min( file.tree.session.transport.rcv_buf_size - 70,
+ file.tree.session.transport.server.maxBufferSize - 70 );
+ writeSize = Math.min( file.tree.session.transport.snd_buf_size - 70,
+ file.tree.session.transport.server.maxBufferSize - 70 );
+ fp = 0L;
+ }
+
+ public int read() throws SmbException {
+ if( read( tmp, 0, 1 ) == -1 ) {
+ return -1;
+ }
+ return tmp[0] & 0xFF;
+ }
+ public int read( byte b[] ) throws SmbException {
+ return read( b, 0, b.length );
+ }
+ public int read( byte b[], int off, int len ) throws SmbException {
+ if( len <= 0 ) {
+ return 0;
+ }
+ long start = fp;
+
+ // ensure file is open
+ if( file.isOpen() == false ) {
+ file.open( openFlags, SmbFile.ATTR_NORMAL, options );
+ }
+
+ int r, n;
+ SmbComReadAndXResponse response = new SmbComReadAndXResponse( b, off );
+ do {
+ r = len > readSize ? readSize : len;
+ file.send( new SmbComReadAndX( file.fid, fp, r, null ), response );
+ if(( n = response.dataLength ) <= 0 ) {
+ return (int)((fp - start) > 0L ? fp - start : -1);
+ }
+ fp += n;
+ len -= n;
+ response.off += n;
+ } while( len > 0 && n == r );
+
+ return (int)(fp - start);
+ }
+ public final void readFully( byte b[] ) throws SmbException {
+ readFully( b, 0, b.length );
+ }
+ public final void readFully( byte b[], int off, int len ) throws SmbException {
+ int n = 0, count;
+
+ do {
+ count = this.read( b, off + n, len - n );
+ if( count < 0 ) throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, "EOF" );
+ n += count;
+ fp += count;
+ } while( n < len );
+ }
+ public int skipBytes( int n ) throws SmbException {
+ if (n > 0) {
+ fp += n;
+ return n;
+ }
+ return 0;
+ }
+
+ public void write( int b ) throws SmbException {
+ tmp[0] = (byte)b;
+ write( tmp, 0, 1 );
+ }
+ public void write( byte b[] ) throws SmbException {
+ write( b, 0, b.length );
+ }
+ public void write( byte b[], int off, int len ) throws SmbException {
+ if( len <= 0 ) {
+ return;
+ }
+
+ // ensure file is open
+ if( file.isOpen() == false ) {
+ file.open( openFlags, SmbFile.ATTR_NORMAL, options );
+ }
+
+ int w;
+ do {
+ w = len > writeSize ? writeSize : len;
+ file.send( new SmbComWriteAndX( file.fid, fp, len - w, b, off, w, null ), write_andx_resp );
+ fp += write_andx_resp.count;
+ len -= write_andx_resp.count;
+ off += write_andx_resp.count;
+ } while( len > 0 );
+ }
+ public long getFilePointer() throws SmbException {
+ return fp;
+ }
+ public void seek( long pos ) throws SmbException {
+ fp = pos;
+ }
+ public long length() throws SmbException {
+ return file.length();
+ }
+ public void setLength( long newLength ) throws SmbException {
+ // ensure file is open
+ if( file.isOpen() == false ) {
+ file.open( openFlags, SmbFile.ATTR_NORMAL, options );
+ }
+ SmbComWriteResponse rsp = new SmbComWriteResponse();
+ file.send( new SmbComWrite( file.fid, (int)(newLength & 0xFFFFFFFFL), 0, tmp, 0, 0 ), rsp );
+ }
+ public void close() throws SmbException {
+ file.close();
+ }
+
+ public final boolean readBoolean() throws SmbException {
+ if((read( tmp, 0, 1 )) < 0 ) {
+ throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, "EOF" );
+ }
+ return tmp[0] != (byte)0x00;
+ }
+ public final byte readByte() throws SmbException {
+ if((read( tmp, 0, 1 )) < 0 ) {
+ throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, "EOF" );
+ }
+ return tmp[0];
+ }
+ public final int readUnsignedByte() throws SmbException {
+ if((read( tmp, 0, 1 )) < 0 ) {
+ throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, "EOF" );
+ }
+ return tmp[0] & 0xFF;
+ }
+ public final short readShort() throws SmbException {
+ if((read( tmp, 0, 2 )) < 0 ) {
+ throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, "EOF" );
+ }
+ return Encdec.dec_uint16be( tmp, 0 );
+ }
+ public final int readUnsignedShort() throws SmbException {
+ if((read( tmp, 0, 2 )) < 0 ) {
+ throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, "EOF" );
+ }
+ return Encdec.dec_uint16be( tmp, 0 );
+ }
+ public final char readChar() throws SmbException {
+ if((read( tmp, 0, 2 )) < 0 ) {
+ throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, "EOF" );
+ }
+ return (char)Encdec.dec_uint16be( tmp, 0 );
+ }
+ public final int readInt() throws SmbException {
+ if((read( tmp, 0, 4 )) < 0 ) {
+ throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, "EOF" );
+ }
+ return Encdec.dec_uint32be( tmp, 0 );
+ }
+ public final long readLong() throws SmbException {
+ if((read( tmp, 0, 8 )) < 0 ) {
+ throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, "EOF" );
+ }
+ return Encdec.dec_uint64be( tmp, 0 );
+ }
+ public final float readFloat() throws SmbException {
+ if((read( tmp, 0, 4 )) < 0 ) {
+ throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, "EOF" );
+ }
+ return Encdec.dec_floatbe( tmp, 0 );
+ }
+ public final double readDouble() throws SmbException {
+ if((read( tmp, 0, 8 )) < 0 ) {
+ throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, "EOF" );
+ }
+ return Encdec.dec_doublebe( tmp, 0 );
+ }
+ public final String readLine() throws SmbException {
+ StringBuffer input = new StringBuffer();
+ int c = -1;
+ boolean eol = false;
+
+ while (!eol) {
+ switch( c = read() ) {
+ case -1:
+ case '\n':
+ eol = true;
+ break;
+ case '\r':
+ eol = true;
+ long cur = fp;
+ if( read() != '\n' ) {
+ fp = cur;
+ }
+ break;
+ default:
+ input.append( (char)c );
+ break;
+ }
+ }
+
+ if ((c == -1) && (input.length() == 0)) {
+ return null;
+ }
+
+ return input.toString();
+ }
+
+ public final String readUTF() throws SmbException {
+ int size = readUnsignedShort();
+ byte[] b = new byte[size];
+ read( b, 0, size );
+ try {
+ return Encdec.dec_utf8( b, 0, size );
+ } catch( IOException ioe ) {
+ throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, ioe.getMessage() );
+ }
+ }
+ public final void writeBoolean( boolean v ) throws SmbException {
+ tmp[0] = (byte)(v ? 1 : 0);
+ write( tmp, 0, 1 );
+ }
+ public final void writeByte( int v ) throws SmbException {
+ tmp[0] = (byte)v;
+ write( tmp, 0, 1 );
+ }
+ public final void writeShort( int v ) throws SmbException {
+ Encdec.enc_uint16be( (short)v, tmp, 0 );
+ write( tmp, 0, 2 );
+ }
+ public final void writeChar( int v ) throws SmbException {
+ Encdec.enc_uint16be( (short)v, tmp, 0 );
+ write( tmp, 0, 2 );
+ }
+ public final void writeInt( int v ) throws SmbException {
+ Encdec.enc_uint32be( v, tmp, 0 );
+ write( tmp, 0, 4 );
+ }
+ public final void writeLong( long v ) throws SmbException {
+ Encdec.enc_uint64be( v, tmp, 0 );
+ write( tmp, 0, 8 );
+ }
+ public final void writeFloat( float v ) throws SmbException {
+ Encdec.enc_floatbe( v, tmp, 0 );
+ write( tmp, 0, 4 );
+ }
+ public final void writeDouble( double v ) throws SmbException {
+ Encdec.enc_doublebe( v, tmp, 0 );
+ write( tmp, 0, 8 );
+ }
+ public final void writeBytes( String s ) throws SmbException {
+ int len = s.length();
+ byte[] b = new byte[len];
+ s.getBytes( 0, len, b, 0 );
+ write( b, 0, len );
+ }
+ public final void writeChars( String s ) throws SmbException {
+ int clen = s.length();
+ int blen = 2 * clen;
+ byte[] b = new byte[blen];
+ char[] c = new char[clen];
+ s.getChars( 0, clen, c, 0 );
+ for( int i = 0, j = 0; i < clen; i++ ) {
+ b[j++] = (byte)(c[i] >>> 8);
+ b[j++] = (byte)(c[i] >>> 0);
+ }
+ write( b, 0, blen );
+ }
+ public final void writeUTF( String str ) throws SmbException {
+ int len = str.length();
+ int ch, size = 0;
+ byte[] dst;
+
+ for( int i = 0; i < len; i++ ) {
+ ch = str.charAt( i );
+ size += ch > 0x07F ? (ch > 0x7FF ? 3 : 2) : 1;
+ }
+ dst = new byte[size];
+ writeShort( size );
+ try {
+ Encdec.enc_utf8( str, dst, 0, size );
+ } catch( IOException ioe ) {
+ throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, ioe.getMessage() );
+ }
+ write( dst, 0, size );
+ }
+}
+
// transactions are not batchable
sessionSetup( null, null );
request.uid = uid;
+ request.auth = auth;
transport.sendTransaction( request, response );
}
void send( ServerMessageBlock request,
return;
}
request.uid = uid;
+ request.auth = auth;
transport.send( request, response );
}
void sessionSetup( ServerMessageBlock andx,
ServerMessageBlock andxResponse ) throws SmbException {
synchronized( transport ) {
- SmbComSessionSetupAndXResponse response = null;
-
if( sessionSetup ) {
return;
}
* Session Setup And X Request / Response
*/
- response = new SmbComSessionSetupAndXResponse( andxResponse );
- transport.send( new SmbComSessionSetupAndX( this, andx ), response );
+ SmbComSessionSetupAndX request = new SmbComSessionSetupAndX( this, andx );
+ SmbComSessionSetupAndXResponse response = new SmbComSessionSetupAndXResponse( andxResponse );
+ request.auth = auth;
+ transport.send( request, response );
uid = response.uid;
sessionSetup = true;
static final int FLAGS_OFFSET = 9;
static final int FLAGS_RESPONSE = 0x80;
+ static final int ST_GROUND = 0;
+ static final int ST_NEGOTIATING = 1;
+
private NbtSocket socket; // should become UniSocket?
private InputStream in;
private OutputStream out;
int ssnLimit = Config.getInt( "jcifs.smb.client.ssnLimit", DEFAULT_SSN_LIMIT );
+ int state;
+
ClientProperties client = new ClientProperties();
ServerProperties server = new ServerProperties();
+ LinkedList referrals = new LinkedList();
+
class ClientProperties {
int maxMpxCount = Config.getInt( "jcifs.smb.client.maxMpxCount",
DEFAULT_MAX_MPX_COUNT );
* but we could do raw and mpx
*/
int flags2 = Config.getInt( "jcifs.smb.client.flags2",
- ServerMessageBlock.FLAGS2_LONG_FILENAMES | ServerMessageBlock.FLAGS2_UNICODE );
+ ServerMessageBlock.FLAGS2_LONG_FILENAMES |
+ ServerMessageBlock.FLAGS2_EXTENDED_ATTRIBUTES |
+ ServerMessageBlock.FLAGS2_UNICODE );
int capabilities = Config.getInt( "jcifs.smb.client.capabilities",
- ServerMessageBlock.CAP_UNICODE | ServerMessageBlock.CAP_NT_SMBS );
+ ServerMessageBlock.CAP_UNICODE |
+ ServerMessageBlock.CAP_NT_SMBS);
String nativeOs = Config.getProperty( "jcifs.smb.client.nativeOs",
System.getProperty( "os.name" ));
String nativeLanMan = Config.getProperty( "jcifs.smb.client.nativeLanMan", "jCIFS" );
sessions = new LinkedList();
responseTable = new Hashtable();
outLock = new Object();
- negotiated = false;
+ state = ST_GROUND;
}
synchronized SmbSession getSmbSession() {
localPort == this.localPort;
}
boolean hasCapability( int cap ) throws SmbException {
- negotiate();
+ if (state == ST_GROUND) {
+ negotiate();
+ }
return (negotiatedCapabilities & cap) == cap;
}
void ensureOpen() throws IOException {
in = null;
out = null;
socket = null;
- negotiated = false;
thread = null;
responseTable.clear();
+ state = ST_GROUND;
}
public void run() {
int mid, l, i, n, m;
}
Log.printHexDump( "smb received", rcv_buf, 0, response.length );
if( useSigning ) {
- int length = response.length;
response.verifyFailed = verify(rcv_buf, 0, response);
}
}
return false;
- }
+ }
+ synchronized DfsReferral getDfsReferral( NtlmPasswordAuthentication auth, String path ) throws SmbException {
+ String subpath, node, host;
+ DfsReferral dr = new DfsReferral();
+ int p, n, i, s;
+ UniAddress addr;
+
+ SmbTree ipc = getSmbSession( auth ).getSmbTree( "IPC$", null );
+ Trans2GetDfsReferralResponse resp = new Trans2GetDfsReferralResponse();
+ ipc.sendTransaction( new Trans2GetDfsReferral( path ), resp );
+
+ subpath = path.substring( 0, resp.pathConsumed );
+ node = resp.referral.node;
+ if( subpath.charAt( 0 ) != '\\' ||
+ (i = subpath.indexOf( '\\', 1 )) < 2 ||
+ (p = subpath.indexOf( '\\', i + 1 )) < (i + 2) ||
+ node.charAt( 0 ) != '\\' ||
+ (s = node.indexOf( '\\', 1 )) < 2) {
+ throw new SmbException( SmbException.ERRCLI, SmbException.ERRdfs, "Invalid DFS path: " + path );
+ }
+ if ((n = node.indexOf( '\\', s + 1 )) == -1) {
+ n = node.length();
+ }
+
+ dr.path = subpath.substring( p );
+ dr.node = node.substring( 0, n );
+ dr.nodepath = node.substring( n );
+ dr.server = node.substring( 1, s );
+ dr.share = node.substring( s, n );
+ dr.resolveHashes = auth.hashesExternal; /* NTLM HTTP Authentication must be re-negotiated
+ * with challenge from 'server' to access DFS vol. */
+ return dr;
+ }
+ synchronized DfsReferral lookupReferral( String unc ) {
+ DfsReferral dr;
+ ListIterator iter = referrals.listIterator();
+ int i, len;
+
+ while( iter.hasNext() ) {
+ dr = (DfsReferral)iter.next();
+ len = dr.path.length();
+ for( i = 0; i < len && i < unc.length(); i++ ) {
+ if( dr.path.charAt( i ) != unc.charAt( i )) {
+ break;
+ }
+ }
+ if( i == len ) {
+ return dr;
+ }
+ }
+ return null;
+ }
void send( ServerMessageBlock request,
ServerMessageBlock response ) throws SmbException {
Integer mid = null;
- negotiate();
+ if (state == ST_GROUND) {
+ negotiate();
+ }
- request.flags2 = client.flags2;
+ request.flags2 |= client.flags2;
request.mid = aquireMid();
request.useUnicode = useUnicode;
throw new SmbException( response.errorCode );
case SmbException.ERRSRV:
switch(( response.errorCode >> 16 ) & 0xFFFF ) {
+ case SmbException.ERRreserved:
+ if( request.auth == null ) {
+ throw new SmbException( response.errorCode );
+ }
+ DfsReferral dr = getDfsReferral( request.auth, request.path );
+ referrals.add( dr );
+ throw dr;
case SmbException.ERRbadpw:
case SmbException.ERRaccess:
case SmbException.ERRaccountExpired:
negotiate();
- request.flags2 = client.flags2;
+ request.flags2 |= client.flags2;
request.mid = aquireMid();
mid = new Integer( request.mid );
request.useUnicode = useUnicode;
throw new SmbException( response.errorCode );
case SmbException.ERRSRV:
switch(( interimResponse.errorCode >> 16 ) & 0xFFFF ) {
+ case SmbException.ERRreserved:
+ if( request.auth == null ) {
+ throw new SmbException( response.errorCode );
+ }
+ DfsReferral dr = getDfsReferral( request.auth, request.path );
+ referrals.add( dr );
+ throw dr;
case SmbException.ERRbadpw:
case SmbException.ERRaccess:
case SmbException.ERRaccountExpired:
throw new SmbException( response.errorCode );
case SmbException.ERRSRV:
switch(( response.errorCode >> 16 ) & 0xFFFF ) {
+ case SmbException.ERRreserved:
+ if( request.auth == null ) {
+ throw new SmbException( response.errorCode );
+ }
+ DfsReferral dr = getDfsReferral( request.auth, request.path );
+ referrals.add( dr );
+ throw dr;
case SmbException.ERRbadpw:
case SmbException.ERRaccess:
case SmbException.ERRaccountExpired:
}
synchronized void negotiate() throws SmbException {
- if( negotiated ) {
+ if( state >= ST_NEGOTIATING ) {
return;
}
- /* we must set this here rather than later because this
- * calls send() which calls negotiate so we don't want to
- * end up in a loop. The alternative would be to inline
- * the send routine here but this seems okay for now
- */
- negotiated = true;
+ state = ST_NEGOTIATING;
Log.println( Log.WARNINGS, "smb negotiation warning",
" requesting negotiation with " + address );
package jcifs.smb;
import java.io.IOException;
+import java.net.UnknownHostException;
import jcifs.UniAddress;
import jcifs.netbios.NbtAddress;
-import java.net.UnknownHostException;
class SmbTree {
String share;
String service = jcifs.Config.getProperty( "jcifs.smb.client.serviceType", "?????" );
SmbSession session;
- boolean treeConnected;
+ boolean treeConnected, inDfs;
SmbTree( SmbSession session, String share, String service ) {
this.session = session;
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( SmbException.ERRCLI, SmbException.ERRioe,
}
}
request.tid = tid;
+ if( inDfs && request.path != null && request.path.length() > 0 ) {
+ request.path = '\\' + session.transport.server.tconHostName + '\\' + share + request.path;
+ }
session.sendTransaction( request, response );
}
void send( ServerMessageBlock request,
}
if( service.equals( "A:" ) == false ) {
switch( request.command ) {
- case ServerMessageBlock.SMB_COM_WRITE:
case ServerMessageBlock.SMB_COM_OPEN_ANDX:
case ServerMessageBlock.SMB_COM_NT_CREATE_ANDX:
case ServerMessageBlock.SMB_COM_READ_ANDX:
}
}
request.tid = tid;
+ if( inDfs && request.path != null && request.path.length() > 0 ) {
+ request.flags2 = ServerMessageBlock.FLAGS2_RESOLVE_PATHS_IN_DFS;
+ request.path = '\\' + session.transport.server.tconHostName + '\\' + share + request.path;
+ }
session.send( request, response );
}
void treeConnect( ServerMessageBlock andx,
session.transport.negotiate();
- unc = "\\\\" + session.transport.server.tconHostName + "\\" + share;
+ unc = "\\\\" + session.transport.server.tconHostName + '\\' + share;
Log.println( Log.WARNINGS, "smb tree connect warning",
" requesting tree connect with unc=" + unc +
tid = response.tid;
service = response.service;
+ inDfs = response.shareIsInDfs;
treeConnected = true;
}
}
public String toString() {
return "SmbTree[share=" + share +
",service=" + service +
- ",tid=" + tid + "]";
+ ",tid=" + tid +
+ ",inDfs=" + inDfs +
+ ",treeConnected=" + treeConnected + "]";
}
}
int flags;
int informationLevel;
int searchStorageType = 0;
- String filename;
-
- Trans2FindFirst2( String filename ) {
- this.filename = filename;
+ String wildcard;
+
+ Trans2FindFirst2( String filename, String wildcard, int searchAttributes ) {
+ if( filename.equals( "\\" )) {
+ this.path = filename;
+ } else {
+ this.path = filename + "\\";
+ }
+ this.wildcard = wildcard;
+ this.searchAttributes = searchAttributes & SmbFile.ATTR_GET_MASK;
command = SMB_COM_TRANSACTION2;
subCommand = TRANS2_FIND_FIRST2;
- searchAttributes = ATTR_DIRECTORY | ATTR_HIDDEN | ATTR_SYSTEM;
searchCount = Config.getInt( "jcifs.smb.client.listCount", DEFAULT_SEARCH_COUNT );
flags = 0x00;
informationLevel = SMB_FILE_BOTH_DIRECTORY_INFO;
dstIndex += 2;
writeInt4( searchStorageType, dst, dstIndex );
dstIndex += 4;
- dstIndex += writeString( filename, dst, dstIndex );
+ dstIndex += writeString( path + wildcard, dst, dstIndex );
return dstIndex - start;
}
",flags=0x" + Log.getHexString( flags, 2 ) +
",informationLevel=0x" + Log.getHexString( informationLevel, 3 ) +
",searchStorageType=" + searchStorageType +
- ",filename=" + filename + "]" );
+ ",filename=" + path + "]" );
}
}
static final int SMB_FILE_NAMES_INFO = 0x103;
static final int SMB_FILE_BOTH_DIRECTORY_INFO = 0x104;
- class SmbFindFileBothDirectoryInfo {
+ class SmbFindFileBothDirectoryInfo implements FileEntry {
int nextEntryOffset;
int fileIndex;
long creationTime;
String shortName;
String filename;
+ public String getName() {
+ return filename;
+ }
+ public int getType() {
+ return SmbFile.TYPE_FILESYSTEM;
+ }
+ public int getAttributes() {
+ return extFileAttributes;
+ }
+ public long createTime() {
+ return creationTime;
+ }
+ public long lastModified() {
+ return lastWriteTime;
+ }
+ public long length() {
+ return endOfFile;
+ }
+
public String toString() {
return new String( "SmbFindFileBothDirectoryInfo[" +
"nextEntryOffset=" + nextEntryOffset +
}
int sid;
- int searchCount;
boolean isEndOfSearch;
int eaErrorOffset;
int lastNameOffset, lastNameBufferIndex;
String lastName;
int resumeKey;
- SmbFindFileBothDirectoryInfo[] results;
Trans2FindFirst2Response() {
command = SMB_COM_TRANSACTION2;
sid = readInt2( buffer, bufferIndex );
bufferIndex += 2;
}
- searchCount = readInt2( buffer, bufferIndex );
+ numEntries = readInt2( buffer, bufferIndex );
bufferIndex += 2;
isEndOfSearch = ( buffer[bufferIndex] & 0x01 ) == 0x01 ? true : false;
bufferIndex += 2;
}
int readDataWireFormat( byte[] buffer, int bufferIndex, int len ) {
int start = bufferIndex;
+ SmbFindFileBothDirectoryInfo e;
lastNameBufferIndex = bufferIndex + lastNameOffset;
- results = new SmbFindFileBothDirectoryInfo[searchCount];
-
- for( int i = 0; i < searchCount; i++ ) {
- results[i] = new SmbFindFileBothDirectoryInfo();
-
- results[i].nextEntryOffset = readInt4( buffer, bufferIndex );
- results[i].fileIndex = readInt4( buffer, bufferIndex + 4 );
- // results[i].creationTime = readTime( buffer, bufferIndex + 8 );
- // results[i].lastAccessTime = readTime( buffer, bufferIndex + 16 );
- results[i].lastWriteTime = readTime( buffer, bufferIndex + 24 );
- // results[i].changeTime = readTime( buffer, bufferIndex + 32 );
- results[i].endOfFile = readLong( buffer, bufferIndex + 40 );
- // results[i].allocationSize = readLong( buffer, bufferIndex + 48 );
- results[i].extFileAttributes = readInt4( buffer, bufferIndex + 56 );
- results[i].fileNameLength = readInt4( buffer, bufferIndex + 60 );
- // results[i].eaSize = readInt4( buffer, bufferIndex + 64 );
- // results[i].shortNameLength = buffer[bufferIndex + 68] & 0xFF;
+ results = new SmbFindFileBothDirectoryInfo[numEntries];
+ for( int i = 0; i < numEntries; i++ ) {
+ results[i] = e = new SmbFindFileBothDirectoryInfo();
+
+ e.nextEntryOffset = readInt4( buffer, bufferIndex );
+ e.fileIndex = readInt4( buffer, bufferIndex + 4 );
+ e.creationTime = readTime( buffer, bufferIndex + 8 );
+ // e.lastAccessTime = readTime( buffer, bufferIndex + 16 );
+ e.lastWriteTime = readTime( buffer, bufferIndex + 24 );
+ // e.changeTime = readTime( buffer, bufferIndex + 32 );
+ e.endOfFile = readLong( buffer, bufferIndex + 40 );
+ // e.allocationSize = readLong( buffer, bufferIndex + 48 );
+ e.extFileAttributes = readInt4( buffer, bufferIndex + 56 );
+ e.fileNameLength = readInt4( buffer, bufferIndex + 60 );
+ // e.eaSize = readInt4( buffer, bufferIndex + 64 );
+ // e.shortNameLength = buffer[bufferIndex + 68] & 0xFF;
/* With NT, the shortName is in Unicode regardless of what is negotiated.
*/
- // results[i].shortName = readString( buffer, bufferIndex + 70,
- // results[i].shortNameLength );
- results[i].filename = readString( buffer, bufferIndex + 94,
- results[i].fileNameLength );
+ // e.shortName = readString( buffer, bufferIndex + 70, e.shortNameLength );
+ e.filename = readString( buffer, bufferIndex + 94, e.fileNameLength );
-//Log.println( Log.DEBUGGING, "Trans2FindFirst2/Next2Response debugging", "bufferIndex=" + bufferIndex + ",lastNameBufferIndex=" + lastNameBufferIndex + ",nextEntryOffet=" + ( bufferIndex + results[i].nextEntryOffset ));
+//Log.println( Log.DEBUGGING, "Trans2FindFirst2/Next2Response debugging", "bufferIndex=" + bufferIndex + ",lastNameBufferIndex=" + lastNameBufferIndex + ",nextEntryOffet=" + ( bufferIndex + e.nextEntryOffset ));
/* lastNameOffset ends up pointing to either to
* the exact location of the filename(e.g. Win98)
* entry and the next entry.
*/
- if( lastNameBufferIndex >= bufferIndex &&
- ( results[i].nextEntryOffset == 0 ||
- lastNameBufferIndex < ( bufferIndex + results[i].nextEntryOffset ))) {
- lastName = results[i].filename;
- resumeKey = results[i].fileIndex;
+ if( lastNameBufferIndex >= bufferIndex && ( e.nextEntryOffset == 0 ||
+ lastNameBufferIndex < ( bufferIndex + e.nextEntryOffset ))) {
+ lastName = e.filename;
+ resumeKey = e.fileIndex;
}
-//Log.println( Log.DEBUGGING, "info entry", results[i].toString() );
+//Log.println( Log.DEBUGGING, "info entry", e );
- bufferIndex += results[i].nextEntryOffset;
+ bufferIndex += e.nextEntryOffset;
}
}
return new String( c + super.toString() +
",sid=" + sid +
- ",searchCount=" + searchCount +
+ ",searchCount=" + numEntries +
",isEndOfSearch=" + isEndOfSearch +
",eaErrorOffset=" + eaErrorOffset +
",lastNameOffset=" + lastNameOffset +
maxSetupCount = 0;
}
+ public void reset( int resumeKey, String lastName ) {
+ super.reset();
+ this.resumeKey = resumeKey;
+ this.filename = lastName;
+ flags2 = 0;
+ }
+
int writeSetupWireFormat( byte[] dst, int dstIndex ) {
dst[dstIndex++] = subCommand;
dst[dstIndex++] = (byte)0x00;
--- /dev/null
+/* 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 jcifs.smb;
+
+class Trans2GetDfsReferral extends SmbComTransaction {
+
+ int maxReferralLevel = 3;
+
+ Trans2GetDfsReferral( String filename ) {
+ path = filename;
+ command = SMB_COM_TRANSACTION2;
+ subCommand = TRANS2_GET_DFS_REFERRAL;
+ totalDataCount = 0;
+ maxParameterCount = 0;
+ maxDataCount = 4096;
+ maxSetupCount = (byte)0x00;
+ }
+
+ int writeSetupWireFormat( byte[] dst, int dstIndex ) {
+ dst[dstIndex++] = subCommand;
+ dst[dstIndex++] = (byte)0x00;
+ return 2;
+ }
+ int writeParametersWireFormat( byte[] dst, int dstIndex ) {
+ int start = dstIndex;
+
+ writeInt2( maxReferralLevel, dst, dstIndex );
+ dstIndex += 2;
+ dstIndex += writeString( path, dst, dstIndex );
+
+ return dstIndex - start;
+ }
+ int writeDataWireFormat( byte[] dst, int dstIndex ) {
+ return 0;
+ }
+ int readSetupWireFormat( byte[] buffer, int bufferIndex, int len ) {
+ return 0;
+ }
+ int readParametersWireFormat( byte[] buffer, int bufferIndex, int len ) {
+ return 0;
+ }
+ int readDataWireFormat( byte[] buffer, int bufferIndex, int len ) {
+ return 0;
+ }
+ public String toString() {
+ return new String( "Trans2GetDfsReferral[" + super.toString() +
+ ",maxReferralLevel=0x" + maxReferralLevel +
+ ",filename=" + path + "]" );
+ }
+}
--- /dev/null
+/* jcifs smb client library in Java
+ * Copyright (C) 2003 "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 jcifs.smb;
+
+import java.util.Date;
+
+class Trans2GetDfsReferralResponse extends SmbComTransactionResponse {
+
+ class Referral {
+ int version;
+ int size;
+ int serverType;
+ int flags;
+ int proximity;
+ int ttl;
+ int pathOffset;
+ int altPathOffset;
+ int nodeOffset;
+ String path;
+ String altPath;
+ String node;
+
+ int readWireFormat( byte[] buffer, int bufferIndex, int len ) {
+ int start = bufferIndex;
+
+ version = readInt2( buffer, bufferIndex );
+if( version != 3 && version != 1 ) {
+ throw new RuntimeException( "Version " + version + " referral not supported. Please report this to jcifs at samba dot org." );
+}
+ bufferIndex += 2;
+ size = readInt2( buffer, bufferIndex );
+ bufferIndex += 2;
+ serverType = readInt2( buffer, bufferIndex );
+ bufferIndex += 2;
+ flags = readInt2( buffer, bufferIndex );
+ bufferIndex += 2;
+ if( version == 3 ) {
+ proximity = readInt2( buffer, bufferIndex );
+ bufferIndex += 2;
+ ttl = readInt2( buffer, bufferIndex );
+ bufferIndex += 2;
+ pathOffset = readInt2( buffer, bufferIndex );
+ bufferIndex += 2;
+ altPathOffset = readInt2( buffer, bufferIndex );
+ bufferIndex += 2;
+ nodeOffset = readInt2( buffer, bufferIndex );
+ bufferIndex += 2;
+
+ path = readString( buffer, start + pathOffset, len, (flags2 & FLAGS2_UNICODE) != 0);
+ node = readString( buffer, start + nodeOffset, len, (flags2 & FLAGS2_UNICODE) != 0);
+ } else if( version == 1 ) {
+ node = readString( buffer, bufferIndex, len, (flags2 & FLAGS2_UNICODE) != 0);
+ }
+
+ return size;
+ }
+
+ public String toString() {
+ return new String( "Referral[" +
+ "version=" + version + ",size=" + size +
+ ",serverType=" + serverType + ",flags=" + flags +
+ ",proximity=" + proximity + ",ttl=" + ttl +
+ ",pathOffset=" + pathOffset + ",altPathOffset=" + altPathOffset +
+ ",nodeOffset=" + nodeOffset + ",path=" + path + ",altPath=" + altPath +
+ ",node=" + node + "]" );
+ }
+ }
+
+ int pathConsumed;
+ int numReferrals;
+ int flags;
+ Referral referral;
+
+ Trans2GetDfsReferralResponse() {
+ subCommand = SmbComTransaction.TRANS2_GET_DFS_REFERRAL;
+ }
+
+ int writeSetupWireFormat( byte[] dst, int dstIndex ) {
+ return 0;
+ }
+ int writeParametersWireFormat( byte[] dst, int dstIndex ) {
+ return 0;
+ }
+ int writeDataWireFormat( byte[] dst, int dstIndex ) {
+ return 0;
+ }
+ int readSetupWireFormat( byte[] buffer, int bufferIndex, int len ) {
+ return 0;
+ }
+ int readParametersWireFormat( byte[] buffer, int bufferIndex, int len ) {
+ return 0;
+ }
+ int readDataWireFormat( byte[] buffer, int bufferIndex, int len ) {
+ int start = bufferIndex;
+
+ pathConsumed = readInt2( buffer, bufferIndex );
+ bufferIndex += 2;
+ /* Samba 2.2.8a will reply with Unicode paths even though
+ * ASCII is negotiated so we must use flags2 (probably
+ * should anyway).
+ */
+ if((flags2 & FLAGS2_UNICODE) != 0) {
+ pathConsumed /= 2;
+ }
+ numReferrals = readInt2( buffer, bufferIndex );
+ bufferIndex += 2;
+ flags = readInt2( buffer, bufferIndex );
+ bufferIndex += 4;
+
+ referral = new Referral();
+ while( numReferrals-- > 0 ) {
+ bufferIndex += referral.readWireFormat( buffer, bufferIndex, len );
+ }
+
+ return bufferIndex - start;
+ }
+ public String toString() {
+ return new String( "Trans2GetDfsReferralResponse[" +
+ super.toString() + ",pathConsumed=" + pathConsumed +
+ ",numReferrals=" + numReferrals + ",flags=" + flags +
+ "," + referral + "]" );
+ }
+}
class Trans2QueryPathInformation extends SmbComTransaction {
int informationLevel;
- String filename;
Trans2QueryPathInformation( String filename, int informationLevel ) {
- this.filename = filename;
+ path = filename;
this.informationLevel = informationLevel;
command = SMB_COM_TRANSACTION2;
subCommand = TRANS2_QUERY_PATH_INFORMATION;
dst[dstIndex++] = (byte)0x00;
dst[dstIndex++] = (byte)0x00;
dst[dstIndex++] = (byte)0x00;
- dstIndex += writeString( filename, dst, dstIndex );
+ dstIndex += writeString( path, dst, dstIndex );
return dstIndex - start;
}
public String toString() {
return new String( "Trans2QueryPathInformation[" + super.toString() +
",informationLevel=0x" + Log.getHexString( informationLevel, 3 ) +
- ",filename=" + filename + "]" );
+ ",filename=" + path + "]" );
}
}
static final int SMB_QUERY_FILE_STANDARD_INFO = 0x102;
class SmbQueryFileBasicInfo implements Info {
- long creationTime;
+ long createTime;
long lastAccessTime;
long lastWriteTime;
long changeTime;
public int getAttributes() {
return attributes;
}
+ public long getCreateTime() {
+ return createTime;
+ }
public long getLastWriteTime() {
return lastWriteTime;
}
}
public String toString() {
return new String( "SmbQueryFileBasicInfo[" +
- "creationTime=" + new Date( creationTime ) +
+ "createTime=" + new Date( createTime ) +
",lastAccessTime=" + new Date( lastAccessTime ) +
",lastWriteTime=" + new Date( lastWriteTime ) +
",changeTime=" + new Date( changeTime ) +
public int getAttributes() {
return 0;
}
+ public long getCreateTime() {
+ return 0L;
+ }
public long getLastWriteTime() {
- return 0;
+ return 0L;
}
public long getSize() {
return endOfFile;
int start = bufferIndex;
SmbQueryFileBasicInfo info = new SmbQueryFileBasicInfo();
- info.creationTime = readTime( buffer, bufferIndex );
+ info.createTime = readTime( buffer, bufferIndex );
bufferIndex += 8;
info.lastAccessTime = readTime( buffer, bufferIndex );
bufferIndex += 8;
--- /dev/null
+/* jcifs smb client library in Java
+ * Copyright (C) 2003 "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 jcifs.smb;
+
+class Trans2SetFileInformation extends SmbComTransaction {
+
+ static final int SMB_FILE_BASIC_INFO = 0x101;
+
+ int fid;
+ int attributes;
+ long createTime, lastWriteTime;
+
+ Trans2SetFileInformation( int fid, int attributes, long createTime, long lastWriteTime ) {
+ this.fid = fid;
+ this.attributes = attributes;
+ this.createTime = createTime;
+ this.lastWriteTime = lastWriteTime;
+ command = SMB_COM_TRANSACTION2;
+ subCommand = TRANS2_SET_FILE_INFORMATION;
+ maxParameterCount = 6;
+ maxDataCount = 0;
+ maxSetupCount = (byte)0x00;
+ }
+
+ int writeSetupWireFormat( byte[] dst, int dstIndex ) {
+ dst[dstIndex++] = subCommand;
+ dst[dstIndex++] = (byte)0x00;
+ return 2;
+ }
+ int writeParametersWireFormat( byte[] dst, int dstIndex ) {
+ int start = dstIndex;
+
+ writeInt2( fid, dst, dstIndex );
+ dstIndex += 2;
+ writeInt2( SMB_FILE_BASIC_INFO, dst, dstIndex );
+ dstIndex += 2;
+ writeInt2( 0, dst, dstIndex );
+ dstIndex += 2;
+
+ return dstIndex - start;
+ }
+ int writeDataWireFormat( byte[] dst, int dstIndex ) {
+ int start = dstIndex;
+
+ writeTime( createTime, dst, dstIndex ); dstIndex += 8;
+ writeLong( 0L, dst, dstIndex ); dstIndex += 8;
+ writeTime( lastWriteTime, dst, dstIndex ); dstIndex += 8;
+ writeLong( 0L, dst, dstIndex ); dstIndex += 8;
+/* Samba 2.2.7 needs ATTR_NORMAL
+ */
+ writeInt2( 0x80 | attributes, dst, dstIndex ); dstIndex += 2;
+ /* 6 zeros observed with NT */
+ writeLong( 0L, dst, dstIndex ); dstIndex += 6;
+
+ /* Also observed 4 byte alignment but we stick
+ * with the default for jCIFS which is 2 */
+
+ return dstIndex - start;
+ }
+ int readSetupWireFormat( byte[] buffer, int bufferIndex, int len ) {
+ return 0;
+ }
+ int readParametersWireFormat( byte[] buffer, int bufferIndex, int len ) {
+ return 0;
+ }
+ int readDataWireFormat( byte[] buffer, int bufferIndex, int len ) {
+ return 0;
+ }
+ public String toString() {
+ return new String( "Trans2SetFileInformation[" + super.toString() +
+ ",fid=" + fid + "]" );
+ }
+}
--- /dev/null
+/* jcifs smb client library in Java
+ * Copyright (C) 2003 "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 jcifs.smb;
+
+class Trans2SetFileInformationResponse extends SmbComTransactionResponse {
+
+ Trans2SetFileInformationResponse() {
+ subCommand = SmbComTransaction.TRANS2_SET_FILE_INFORMATION;
+ }
+
+ int writeSetupWireFormat( byte[] dst, int dstIndex ) {
+ return 0;
+ }
+ int writeParametersWireFormat( byte[] dst, int dstIndex ) {
+ return 0;
+ }
+ int writeDataWireFormat( byte[] dst, int dstIndex ) {
+ return 0;
+ }
+ int readSetupWireFormat( byte[] buffer, int bufferIndex, int len ) {
+ return 0;
+ }
+ int readParametersWireFormat( byte[] buffer, int bufferIndex, int len ) {
+ return 0;
+ }
+ int readDataWireFormat( byte[] buffer, int bufferIndex, int len ) {
+ return 0;
+ }
+ public String toString() {
+ return new String( "Trans2SetFileInformationResponse[" +
+ super.toString() + "]" );
+ }
+}
new TransCallNamedPipeResponse( pipe ));
} else if(( pipe.pipeType & SmbNamedPipe.PIPE_TYPE_TRANSACT ) ==
SmbNamedPipe.PIPE_TYPE_TRANSACT ) {
- pipe.open(( pipe.pipeType & 0xFF0000 ) | SmbFile.O_EXCL );
+ pipe.open(( pipe.pipeType & 0xFF0000 ) | SmbFile.O_EXCL, SmbFile.ATTR_NORMAL, 0 );
pipe.sendTransaction( new TransTransactNamedPipe( pipe.fid, b, off, len ),
new TransTransactNamedPipeResponse( pipe ));
}
--- /dev/null
+/* encdec - encode and decode integers, times, and
+ * internationalized strings to and from popular binary formats
+ * http://www.ioplex.com/~miallen/encdec/
+ * Copyright (c) 2003 Michael B. Allen <mballen@erols.com>
+ *
+ * The GNU Library General Public License
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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.util;
+
+import java.util.Date;
+import java.io.IOException;
+
+public class Encdec {
+
+ public static final long MILLISECONDS_BETWEEN_1970_AND_1601 = 11644473600000L;
+ public static final long SEC_BETWEEEN_1904_AND_1970 = 2082844800L;
+ public static final int TIME_1970_SEC_32BE = 1;
+ public static final int TIME_1970_SEC_32LE = 2;
+ public static final int TIME_1904_SEC_32BE = 3;
+ public static final int TIME_1904_SEC_32LE = 4;
+ public static final int TIME_1601_NANOS_64LE = 5;
+ public static final int TIME_1601_NANOS_64BE = 6;
+ public static final int TIME_1970_MILLIS_64BE = 7;
+ public static final int TIME_1970_MILLIS_64LE = 8;
+
+ /* Encode integers
+ */
+
+ public static int enc_uint16be( short s, byte[] dst, int di ) {
+ dst[di++] = (byte)((s >> 8) & 0xFF);
+ dst[di] = (byte)(s & 0xFF);
+ return 2;
+ }
+ public static int enc_uint32be( int i, byte[] dst, int di ) {
+ dst[di++] = (byte)((i >> 24) & 0xFF);
+ dst[di++] = (byte)((i >> 16) & 0xFF);
+ dst[di++] = (byte)((i >> 8) & 0xFF);
+ dst[di] = (byte)(i & 0xFF);
+ return 4;
+ }
+ public static int enc_uint16le( short s, byte[] dst, int di )
+ {
+ dst[di++] = (byte)(s & 0xFF);
+ dst[di] = (byte)((s >> 8) & 0xFF);
+ return 2;
+ }
+ public static int enc_uint32le( int i, byte[] dst, int di )
+ {
+ dst[di++] = (byte)(i & 0xFF);
+ dst[di++] = (byte)((i >> 8) & 0xFF);
+ dst[di++] = (byte)((i >> 16) & 0xFF);
+ dst[di] = (byte)((i >> 24) & 0xFF);
+ return 4;
+ }
+
+ /* Decode integers
+ */
+
+ public static short dec_uint16be( byte[] src, int si )
+ {
+ return (short)(((src[si] & 0xFF) << 8) | (src[si + 1] & 0xFF));
+ }
+ public static int dec_uint32be( byte[] src, int si )
+ {
+ return ((src[si] & 0xFF) << 24) | ((src[si + 1] & 0xFF) << 16) |
+ ((src[si + 2] & 0xFF) << 8) | (src[si + 3] & 0xFF);
+ }
+ public static short dec_uint16le( byte[] src, int si )
+ {
+ return (short)((src[si] & 0xFF) | ((src[si + 1] & 0xFF) << 8));
+ }
+ public static int dec_uint32le( byte[] src, int si )
+ {
+ return (src[si] & 0xFF) | ((src[si + 1] & 0xFF) << 8) |
+ ((src[si + 2] & 0xFF) << 16) | ((src[si + 3] & 0xFF) << 24);
+ }
+
+ /* Encode and decode 64 bit integers
+ */
+
+ public static int enc_uint64be( long l, byte[] dst, int di )
+ {
+ enc_uint32be( (int)(l & 0xFFFFFFFFL), dst, di + 4 );
+ enc_uint32be( (int)(( l >> 32L ) & 0xFFFFFFFFL), dst, di );
+ return 8;
+ }
+ public static int enc_uint64le( long l, byte[] dst, int di )
+ {
+ enc_uint32le( (int)(l & 0xFFFFFFFFL), dst, di );
+ enc_uint32le( (int)(( l >> 32L ) & 0xFFFFFFFFL), dst, di + 4 );
+ return 8;
+ }
+ public static long dec_uint64be( byte[] src, int si )
+ {
+ long l;
+ l = dec_uint32be( src, si ) & 0xFFFFFFFFL;
+ l <<= 32L;
+ l |= dec_uint32be( src, si + 4 ) & 0xFFFFFFFFL;
+ return l;
+ }
+ public static long dec_uint64le( byte[] src, int si )
+ {
+ long l;
+ l = dec_uint32le( src, si + 4 ) & 0xFFFFFFFFL;
+ l <<= 32L;
+ l |= dec_uint32le( src, si ) & 0xFFFFFFFFL;
+ return l;
+ }
+
+ /* Encode floats
+ */
+
+ public static int enc_floatle( float f, byte[] dst, int di )
+ {
+ return enc_uint32le( Float.floatToIntBits( f ), dst, di );
+ }
+ public static int enc_floatbe( float f, byte[] dst, int di )
+ {
+ return enc_uint32be( Float.floatToIntBits( f ), dst, di );
+ }
+
+ /* Decode floating point numbers
+ */
+
+ public static float dec_floatle( byte[] src, int si )
+ {
+ return Float.intBitsToFloat( dec_uint32le( src, si ));
+ }
+ public static float dec_floatbe( byte[] src, int si )
+ {
+ return Float.intBitsToFloat( dec_uint32be( src, si ));
+ }
+
+ /* Encode and decode doubles
+ */
+
+ public static int enc_doublele( double d, byte[] dst, int di )
+ {
+ return enc_uint64le( Double.doubleToLongBits( d ), dst, di );
+ }
+ public static int enc_doublebe( double d, byte[] dst, int di )
+ {
+ return enc_uint64be( Double.doubleToLongBits( d ), dst, di );
+ }
+ public static double dec_doublele( byte[] src, int si )
+ {
+ return Double.longBitsToDouble( dec_uint64le( src, si ));
+ }
+ public static double dec_doublebe( byte[] src, int si )
+ {
+ return Double.longBitsToDouble( dec_uint64be( src, si ));
+ }
+
+ /* Encode times
+ */
+
+ public static int enc_time( Date date, byte[] dst, int di, int enc )
+ {
+ long t;
+
+ switch( enc ) {
+ case TIME_1970_SEC_32BE:
+ return enc_uint32be( (int)(date.getTime() / 1000L), dst, di );
+ case TIME_1970_SEC_32LE:
+ return enc_uint32le( (int)(date.getTime() / 1000L), dst, di );
+ case TIME_1904_SEC_32BE:
+ return enc_uint32be( (int)((date.getTime() / 1000L +
+ SEC_BETWEEEN_1904_AND_1970) & 0xFFFFFFFF), dst, di );
+ case TIME_1904_SEC_32LE:
+ return enc_uint32le( (int)((date.getTime() / 1000L +
+ SEC_BETWEEEN_1904_AND_1970) & 0xFFFFFFFF), dst, di );
+ case TIME_1601_NANOS_64BE:
+ t = (date.getTime() + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L;
+ return enc_uint64be( t, dst, di );
+ case TIME_1601_NANOS_64LE:
+ t = (date.getTime() + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L;
+ return enc_uint64le( t, dst, di );
+ case TIME_1970_MILLIS_64BE:
+ return enc_uint64be( date.getTime(), dst, di );
+ case TIME_1970_MILLIS_64LE:
+ return enc_uint64le( date.getTime(), dst, di );
+ default:
+ throw new IllegalArgumentException( "Unsupported time encoding" );
+ }
+ }
+
+ /* Decode times
+ */
+
+ public static Date dec_time( byte[] src, int si, int enc )
+ {
+ long t;
+
+ switch( enc ) {
+ case TIME_1970_SEC_32BE:
+ return new Date( dec_uint32be( src, si ) * 1000L );
+ case TIME_1970_SEC_32LE:
+ return new Date( dec_uint32le( src, si ) * 1000L );
+ case TIME_1904_SEC_32BE:
+ return new Date((( dec_uint32be( src, si ) & 0xFFFFFFFFL) -
+ SEC_BETWEEEN_1904_AND_1970 ) * 1000L );
+ case TIME_1904_SEC_32LE:
+ return new Date((( dec_uint32le( src, si ) & 0xFFFFFFFFL) -
+ SEC_BETWEEEN_1904_AND_1970 ) * 1000L );
+ case TIME_1601_NANOS_64BE:
+ t = dec_uint64be( src, si );
+ return new Date( t / 10000L - MILLISECONDS_BETWEEN_1970_AND_1601);
+ case TIME_1601_NANOS_64LE:
+ t = dec_uint64le( src, si );
+ return new Date( t / 10000L - MILLISECONDS_BETWEEN_1970_AND_1601);
+ case TIME_1970_MILLIS_64BE:
+ return new Date( dec_uint64be( src, si ));
+ case TIME_1970_MILLIS_64LE:
+ return new Date( dec_uint64le( src, si ));
+ default:
+ throw new IllegalArgumentException( "Unsupported time encoding" );
+ }
+ }
+
+ public static int enc_utf8( String str, byte[] dst, int di, int dlim ) throws IOException {
+ int start = di, ch;
+ int strlen = str.length();
+
+ for( int i = 0; di < dlim && i < strlen; i++ ) {
+ ch = str.charAt( i );
+ if ((ch >= 0x0001) && (ch <= 0x007F)) {
+ dst[di++] = (byte)ch;
+ } else if (ch > 0x07FF) {
+ if((dlim - di) < 3 ) {
+ break;
+ }
+ dst[di++] = (byte)(0xE0 | ((ch >> 12) & 0x0F));
+ dst[di++] = (byte)(0x80 | ((ch >> 6) & 0x3F));
+ dst[di++] = (byte)(0x80 | ((ch >> 0) & 0x3F));
+ } else {
+ if((dlim - di) < 2 ) {
+ break;
+ }
+ dst[di++] = (byte)(0xC0 | ((ch >> 6) & 0x1F));
+ dst[di++] = (byte)(0x80 | ((ch >> 0) & 0x3F));
+ }
+ }
+
+ return di - start;
+ }
+ public static String dec_utf8( byte[] src, int si, int slim ) throws IOException {
+ char[] uni = new char[slim - si];
+ int ui = 0, ch;
+
+ for( ui = 0; si < slim && (ch = src[si++] & 0xFF) != 0; ui++ ) {
+ if( ch < 0x80 ) {
+ uni[ui] = (char)ch;
+ } else if((ch & 0xE0) == 0xC0 ) {
+ if((slim - si) < 2 ) {
+ break;
+ }
+ uni[ui] = (char)((ch & 0x1F) << 6);
+ ch = src[si++] & 0xFF;
+ uni[ui] |= ch & 0x3F;
+ if ((ch & 0xC0) != 0x80 || uni[ui] < 0x80 ) {
+ throw new IOException( "Invalid UTF-8 sequence" );
+ }
+ } else if((ch & 0xF0) == 0xE0 ) {
+ if((slim - si) < 3 ) {
+ break;
+ }
+ uni[ui] = (char)((ch & 0x0F) << 12);
+ ch = src[si++] & 0xFF;
+ if ((ch & 0xC0) != 0x80 ) {
+ throw new IOException( "Invalid UTF-8 sequence" );
+ } else {
+ uni[ui] |= (ch & 0x3F) << 6;
+ ch = src[si++] & 0xFF;
+ uni[ui] |= ch & 0x3F;
+ if ((ch & 0xC0) != 0x80 || uni[ui] < 0x800) {
+ throw new IOException( "Invalid UTF-8 sequence" );
+ }
+ }
+ } else {
+ throw new IOException( "Unsupported UTF-8 sequence" );
+ }
+ }
+
+ return new String( uni, 0, ui );
+ }
+}