Source Code Cross Referenced for SmbFile.java in  » Net » jCIFS » jcifs » smb » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » jCIFS » jcifs.smb 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* jcifs smb client library in Java
0002:         * Copyright (C) 2000  "Michael B. Allen" <jcifs at samba dot org>
0003:         * 
0004:         * This library is free software; you can redistribute it and/or
0005:         * modify it under the terms of the GNU Lesser General Public
0006:         * License as published by the Free Software Foundation; either
0007:         * version 2.1 of the License, or (at your option) any later version.
0008:         * 
0009:         * This library is distributed in the hope that it will be useful,
0010:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012:         * Lesser General Public License for more details.
0013:         * 
0014:         * You should have received a copy of the GNU Lesser General Public
0015:         * License along with this library; if not, write to the Free Software
0016:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0017:         */
0018:
0019:        package jcifs.smb;
0020:
0021:        import java.net.URLConnection;
0022:        import java.net.URL;
0023:        import java.net.MalformedURLException;
0024:        import java.net.UnknownHostException;
0025:        import java.io.IOException;
0026:        import java.io.InputStream;
0027:        import java.io.OutputStream;
0028:        import java.util.ArrayList;
0029:        import java.security.Principal;
0030:        import jcifs.Config;
0031:        import jcifs.util.LogStream;
0032:        import jcifs.UniAddress;
0033:        import jcifs.netbios.NbtAddress;
0034:
0035:        import java.util.Date;
0036:
0037:        /**
0038:         * This class represents a resource on an SMB network. Mainly these
0039:         * resources are files and directories however an <code>SmbFile</code>
0040:         * may also refer to servers and workgroups. If the resource is a file or
0041:         * directory the methods of <code>SmbFile</code> follow the behavior of
0042:         * the well known {@link java.io.File} class. One fundamental difference
0043:         * is the usage of a URL scheme [1] to specify the target file or
0044:         * directory. SmbFile URLs have the following syntax:
0045:         *
0046:         * <blockquote><pre>
0047:         *     smb://[[[domain;]username[:password]@]server[:port]/[[share/[dir/]file]]][?[param=value[param2=value2[...]]]
0048:         * </pre></blockquote>
0049:         *
0050:         * This example:
0051:         *
0052:         * <blockquote><pre>
0053:         *     smb://storage15/public/foo.txt
0054:         * </pre></blockquote>
0055:         *
0056:         * would reference the file <code>foo.txt</code> in the share
0057:         * <code>public</code> on the server <code>storage15</code>. In addition
0058:         * to referencing files and directories, jCIFS can also address servers,
0059:         * and workgroups.
0060:         * <p>
0061:         * <font color="#800000"><i>Important: all SMB URLs that represent
0062:         * workgroups, servers, shares, or directories require a trailing slash '/'.
0063:         * </i></font>
0064:         * <p>
0065:         * When using the <tt>java.net.URL</tt> class with
0066:         * 'smb://' URLs it is necessary to first call the static
0067:         * <tt>jcifs.Config.registerSmbURLHandler();</tt> method. This is required
0068:         * to register the SMB protocol handler.
0069:         * <p>
0070:         * The userinfo component of the SMB URL (<tt>domain;user:pass</tt>) must
0071:         * be URL encoded if it contains reserved characters. According to RFC 2396
0072:         * these characters are non US-ASCII characters and most meta characters
0073:         * however jCIFS will work correctly with anything but '@' which is used
0074:         * to delimit the userinfo component from the server and '%' which is the
0075:         * URL escape character itself.
0076:         * <p>
0077:         * The server
0078:         * component may a traditional NetBIOS name, a DNS name, or IP
0079:         * address. These name resolution mechanisms and their resolution order
0080:         * can be changed (See <a href="../../../resolver.html">Setting Name
0081:         * Resolution Properties</a>). The servername and path components are
0082:         * not case sensitive but the domain, username, and password components
0083:         * are. It is also likely that properties must be specified for jcifs
0084:         * to function (See <a href="../../overview-summary.html#scp">Setting
0085:         * JCIFS Properties</a>). Here are some examples of SMB URLs with brief
0086:         * descriptions of what they do:
0087:         *
0088:         * <p>[1] This URL scheme is based largely on the <i>SMB
0089:         * Filesharing URL Scheme</i> IETF draft.
0090:         * 
0091:         * <p><table border="1" cellpadding="3" cellspacing="0" width="100%">
0092:         * <tr bgcolor="#ccccff">
0093:         * <td colspan="2"><b>SMB URL Examples</b></td>
0094:         * <tr><td width="20%"><b>URL</b></td><td><b>Description</b></td></tr>
0095:         * 
0096:         * <tr><td width="20%"><code>smb://users-nyc;miallen:mypass@angus/tmp/</code></td><td>
0097:         * This URL references a share called <code>tmp</code> on the server
0098:         * <code>angus</code> as user <code>miallen</code> who's password is
0099:         * <code>mypass</code>.
0100:         * </td></tr>
0101:         * 
0102:         * <tr><td width="20%">
0103:         * <code>smb://Administrator:P%40ss@msmith1/c/WINDOWS/Desktop/foo.txt</code></td><td>
0104:         * A relativly sophisticated example that references a file
0105:         * <code>msmith1</code>'s desktop as user <code>Administrator</code>. Notice the '@' is URL encoded with the '%40' hexcode escape.
0106:         * </td></tr>
0107:         * 
0108:         * <tr><td width="20%"><code>smb://angus/</code></td><td>
0109:         * This references only a server. The behavior of some methods is different
0110:         * in this context(e.g. you cannot <code>delete</code> a server) however
0111:         * as you might expect the <code>list</code> method will list the available
0112:         * shares on this server.
0113:         * </td></tr>
0114:         * 
0115:         * <tr><td width="20%"><code>smb://myworkgroup/</code></td><td>
0116:         * This syntactically is identical to the above example. However if
0117:         * <code>myworkgroup</code> happends to be a workgroup(which is indeed
0118:         * suggested by the name) the <code>list</code> method will return
0119:         * a list of servers that have registered themselves as members of
0120:         * <code>myworkgroup</code>.
0121:         * </td></tr>
0122:         * 
0123:         * <tr><td width="20%"><code>smb://</code></td><td>
0124:         * Just as <code>smb://server/</code> lists shares and
0125:         * <code>smb://workgroup/</code> lists servers, the <code>smb://</code>
0126:         * URL lists all available workgroups on a netbios LAN. Again,
0127:         * in this context many methods are not valid and return default
0128:         * values(e.g. <code>isHidden</code> and <code>renameTo</code> will always
0129:         * return false).
0130:         * </td></tr>
0131:         * 
0132:         * <tr><td width="20%"><code>smb://angus.foo.net/d/jcifs/pipes.doc</code></td><td>
0133:         * The server name may also be a DNS name as it is in this example. See
0134:         * <a href="../../../resolver.html">Setting Name Resolution Properties</a>
0135:         * for details.
0136:         * </td></tr>
0137:         * 
0138:         * <tr><td width="20%"><code>smb://192.168.1.15/ADMIN$/</code></td><td>
0139:         * The server name may also be an IP address. See <a
0140:         * href="../../../resolver.html">Setting Name Resolution Properties</a>
0141:         * for details.
0142:         * </td></tr>
0143:         * 
0144:         * <tr><td width="20%">
0145:         * <code>smb://domain;username:password@server/share/path/to/file.txt</code></td><td>
0146:         * A prototypical example that uses all the fields.
0147:         * </td></tr>
0148:         * 
0149:         * <tr><td width="20%"><code>smb://myworkgroup/angus/ &lt;-- ILLEGAL </code></td><td>
0150:         * Despite the hierarchial relationship between workgroups, servers, and
0151:         * filesystems this example is not valid.
0152:         * </td></tr>
0153:         *
0154:         * <tr><td width="20%">
0155:         * <code>smb://server/share/path/to/dir &lt;-- ILLEGAL </code></td><td>
0156:         * URLs that represent workgroups, servers, shares, or directories require a trailing slash '/'.
0157:         * </td></tr>
0158:         *
0159:         * <tr><td width="20%">
0160:         * <code>smb://MYGROUP/?SERVER=192.168.10.15</code></td><td>
0161:         * SMB URLs support some query string parameters. In this example
0162:         * the <code>SERVER</code> parameter is used to override the
0163:         * server name service lookup to contact the server 192.168.10.15
0164:         * (presumably known to be a master
0165:         * browser) for the server list in workgroup <code>MYGROUP</code>.
0166:         * </td></tr>
0167:         *
0168:         * </table>
0169:         * 
0170:         * <p>A second constructor argument may be specified to augment the URL
0171:         * for better programmatic control when processing many files under
0172:         * a common base. This is slightly different from the corresponding
0173:         * <code>java.io.File</code> usage; a '/' at the beginning of the second
0174:         * parameter will still use the server component of the first parameter. The
0175:         * examples below illustrate the resulting URLs when this second contructor
0176:         * argument is used.
0177:         *
0178:         * <p><table border="1" cellpadding="3" cellspacing="0" width="100%">
0179:         * <tr bgcolor="#ccccff">
0180:         * <td colspan="3">
0181:         * <b>Examples Of SMB URLs When Augmented With A Second Constructor Parameter</b></td>
0182:         * <tr><td width="20%">
0183:         * <b>First Parameter</b></td><td><b>Second Parameter</b></td><td><b>Result</b></td></tr>
0184:         *
0185:         * <tr><td width="20%"><code>
0186:         *  smb://host/share/a/b/
0187:         * </code></td><td width="20%"><code>
0188:         *  c/d/
0189:         * </code></td><td><code>
0190:         *  smb://host/share/a/b/c/d/
0191:         * </code></td></tr>
0192:         * 
0193:         * <tr><td width="20%"><code>
0194:         *  smb://host/share/foo/bar/
0195:         * </code></td><td width="20%"><code>
0196:         *  /share2/zig/zag
0197:         * </code></td><td><code>
0198:         *  smb://host/share2/zig/zag
0199:         * </code></td></tr>
0200:         * 
0201:         * <tr><td width="20%"><code>
0202:         *  smb://host/share/foo/bar/
0203:         * </code></td><td width="20%"><code>
0204:         *  ../zip/
0205:         * </code></td><td><code>
0206:         *  smb://host/share/foo/zip/
0207:         * </code></td></tr>
0208:         * 
0209:         * <tr><td width="20%"><code>
0210:         *  smb://host/share/zig/zag
0211:         * </code></td><td width="20%"><code>
0212:         *  smb://foo/bar/
0213:         * </code></td><td><code>
0214:         *  smb://foo/bar/
0215:         * </code></td></tr>
0216:         * 
0217:         * <tr><td width="20%"><code>
0218:         *  smb://host/share/foo/
0219:         * </code></td><td width="20%"><code>
0220:         *  ../.././.././../foo/
0221:         * </code></td><td><code>
0222:         *  smb://host/foo/
0223:         * </code></td></tr>
0224:         * 
0225:         * <tr><td width="20%"><code>
0226:         *  smb://host/share/zig/zag
0227:         * </code></td><td width="20%"><code>
0228:         *  /
0229:         * </code></td><td><code>
0230:         *  smb://host/
0231:         * </code></td></tr>
0232:         * 
0233:         * <tr><td width="20%"><code>
0234:         *  smb://server/
0235:         * </code></td><td width="20%"><code>
0236:         *  ../
0237:         * </code></td><td><code>
0238:         *  smb://server/
0239:         * </code></td></tr>
0240:         * 
0241:         * <tr><td width="20%"><code>
0242:         *  smb://
0243:         * </code></td><td width="20%"><code>
0244:         *  myworkgroup/
0245:         * </code></td><td><code>
0246:         *  smb://myworkgroup/
0247:         * </code></td></tr>
0248:         * 
0249:         * <tr><td width="20%"><code>
0250:         *  smb://myworkgroup/
0251:         * </code></td><td width="20%"><code>
0252:         *  angus/
0253:         * </code></td><td><code>
0254:         *  smb://myworkgroup/angus/ &lt;-- ILLEGAL<br>(But if you first create an <tt>SmbFile</tt> with 'smb://workgroup/' and use and use it as the first parameter to a constructor that accepts it with a second <tt>String</tt> parameter jCIFS will factor out the 'workgroup'.)
0255:         * </code></td></tr>
0256:         * 
0257:         * </table>
0258:         *
0259:         * <p>Instances of the <code>SmbFile</code> class are immutable; that is,
0260:         * once created, the abstract pathname represented by an SmbFile object
0261:         * will never change.
0262:         *
0263:         * @see       java.io.File
0264:         */
0265:
0266:        public class SmbFile extends URLConnection {
0267:
0268:            // these are shifted for use in flags
0269:            static final int O_RDONLY = 0x010000;
0270:            static final int O_WRONLY = 0x020000;
0271:            static final int O_RDWR = 0x030000;
0272:            static final int O_APPEND = 0x040000;
0273:
0274:            // share access
0275:            /**
0276:             * When specified as the <tt>shareAccess</tt> constructor parameter,
0277:             * other SMB clients (including other threads making calls into jCIFS)
0278:             * will not be permitted to access the target file and will receive "The
0279:             * file is being accessed by another process" message.
0280:             */
0281:            public static final int FILE_NO_SHARE = 0x00;
0282:            /**
0283:             * When specified as the <tt>shareAccess</tt> constructor parameter,
0284:             * other SMB clients will be permitted to read from the target file while
0285:             * this file is open. This constant may be logically OR'd with other share
0286:             * access flags.
0287:             */
0288:            public static final int FILE_SHARE_READ = 0x01;
0289:            /**
0290:             * When specified as the <tt>shareAccess</tt> constructor parameter,
0291:             * other SMB clients will be permitted to write to the target file while
0292:             * this file is open. This constant may be logically OR'd with other share
0293:             * access flags.
0294:             */
0295:            public static final int FILE_SHARE_WRITE = 0x02;
0296:            /**
0297:             * When specified as the <tt>shareAccess</tt> constructor parameter,
0298:             * other SMB clients will be permitted to delete the target file while
0299:             * this file is open. This constant may be logically OR'd with other share
0300:             * access flags.
0301:             */
0302:            public static final int FILE_SHARE_DELETE = 0x04;
0303:
0304:            // Open Function Encoding
0305:            // create if the file does not exist
0306:            static final int O_CREAT = 0x0010;
0307:            // fail if the file exists
0308:            static final int O_EXCL = 0x0001;
0309:            // truncate if the file exists
0310:            static final int O_TRUNC = 0x0002;
0311:
0312:            // file attribute encoding
0313:            /** 
0314:             * A file with this bit on as returned by <tt>getAttributes()</tt> or set
0315:             * with <tt>setAttributes()</tt> will be read-only
0316:             */
0317:            public static final int ATTR_READONLY = 0x01;
0318:            /** 
0319:             * A file with this bit on as returned by <tt>getAttributes()</tt> or set
0320:             * with <tt>setAttributes()</tt> will be hidden
0321:             */
0322:            public static final int ATTR_HIDDEN = 0x02;
0323:            /**
0324:             * A file with this bit on as returned by <tt>getAttributes()</tt> or set
0325:             * with <tt>setAttributes()</tt> will be a system file
0326:             */
0327:            public static final int ATTR_SYSTEM = 0x04;
0328:            /**
0329:             * A file with this bit on as returned by <tt>getAttributes()</tt> is
0330:             * a volume
0331:             */
0332:            public static final int ATTR_VOLUME = 0x08;
0333:            /**
0334:             * A file with this bit on as returned by <tt>getAttributes()</tt> is
0335:             * a directory
0336:             */
0337:            public static final int ATTR_DIRECTORY = 0x10;
0338:            /**
0339:             * A file with this bit on as returned by <tt>getAttributes()</tt> or set
0340:             * with <tt>setAttributes()</tt> is an archived file
0341:             */
0342:            public static final int ATTR_ARCHIVE = 0x20;
0343:
0344:            // extended file attribute encoding(others same as above)
0345:            static final int ATTR_COMPRESSED = 0x800;
0346:            static final int ATTR_NORMAL = 0x080;
0347:            static final int ATTR_TEMPORARY = 0x100;
0348:
0349:            static final int ATTR_GET_MASK = 0x7FFF;
0350:            static final int ATTR_SET_MASK = 0x27;
0351:
0352:            static final int DEFAULT_ATTR_EXPIRATION_PERIOD = 5000;
0353:
0354:            static final int HASH_DOT = ".".hashCode();
0355:            static final int HASH_DOT_DOT = "..".hashCode();
0356:
0357:            static LogStream log = LogStream.getInstance();
0358:            static long attrExpirationPeriod;
0359:
0360:            static {
0361:                try {
0362:                    Class.forName("jcifs.Config");
0363:                } catch (ClassNotFoundException cnfe) {
0364:                    cnfe.printStackTrace();
0365:                }
0366:                attrExpirationPeriod = Config.getLong(
0367:                        "jcifs.smb.client.attrExpirationPeriod",
0368:                        DEFAULT_ATTR_EXPIRATION_PERIOD);
0369:            }
0370:
0371:            /**
0372:             * Returned by {@link #getType()} if the resource this <tt>SmbFile</tt>
0373:             * represents is a regular file or directory.
0374:             */
0375:            public static final int TYPE_FILESYSTEM = 0x01;
0376:            /**
0377:             * Returned by {@link #getType()} if the resource this <tt>SmbFile</tt>
0378:             * represents is a workgroup.
0379:             */
0380:            public static final int TYPE_WORKGROUP = 0x02;
0381:            /**
0382:             * Returned by {@link #getType()} if the resource this <tt>SmbFile</tt>
0383:             * represents is a server.
0384:             */
0385:            public static final int TYPE_SERVER = 0x04;
0386:            /**
0387:             * Returned by {@link #getType()} if the resource this <tt>SmbFile</tt>
0388:             * represents is a share.
0389:             */
0390:            public static final int TYPE_SHARE = 0x08;
0391:            /**
0392:             * Returned by {@link #getType()} if the resource this <tt>SmbFile</tt>
0393:             * represents is a named pipe.
0394:             */
0395:            public static final int TYPE_NAMED_PIPE = 0x10;
0396:            /**
0397:             * Returned by {@link #getType()} if the resource this <tt>SmbFile</tt>
0398:             * represents is a printer.
0399:             */
0400:            public static final int TYPE_PRINTER = 0x20;
0401:            /**
0402:             * Returned by {@link #getType()} if the resource this <tt>SmbFile</tt>
0403:             * represents is a communications device.
0404:             */
0405:            public static final int TYPE_COMM = 0x40;
0406:
0407:            private String canon; // Initially null; set by getUncPath; dir must end with '/'
0408:            private String share; // Can be null
0409:            private long createTime;
0410:            private long lastModified;
0411:            private int attributes;
0412:            private long attrExpiration;
0413:            private long size;
0414:            private long sizeExpiration;
0415:            private NtlmPasswordAuthentication auth; // Cannot be null
0416:            private boolean isExists;
0417:            private int shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE
0418:                    | FILE_SHARE_DELETE;
0419:            private SmbComBlankResponse blank_resp = null;
0420:            private DfsReferral dfsReferral = null; // Only used by getDfsPath()
0421:
0422:            SmbTree tree = null; // Initially null; may be !tree.treeConnected
0423:            String unc; // Initially null; set by getUncPath; never ends with '/'
0424:            int fid; // Initially 0; set by open()
0425:            int type;
0426:            boolean opened;
0427:
0428:            /** 
0429:             * Constructs an SmbFile representing a resource on an SMB network such as
0430:             * a file or directory. See the description and examples of smb URLs above.
0431:             *
0432:             * @param   url A URL string
0433:             * @throws  MalformedURLException
0434:             *          If the <code>parent</code> and <code>child</code> parameters
0435:             *          do not follow the prescribed syntax
0436:             */
0437:
0438:            public SmbFile(String url) throws MalformedURLException {
0439:                this (new URL(null, url, Handler.SMB_HANDLER));
0440:            }
0441:
0442:            /**
0443:             * Constructs an SmbFile representing a resource on an SMB network such
0444:             * as a file or directory. The second parameter is a relative path from
0445:             * the <code>parent SmbFile</code>. See the description above for examples
0446:             * of using the second <code>name</code> parameter.
0447:             *
0448:             * @param   context A base <code>SmbFile</code>
0449:             * @param   name A path string relative to the <code>parent</code> paremeter
0450:             * @throws  MalformedURLException
0451:             *          If the <code>parent</code> and <code>child</code> parameters
0452:             *          do not follow the prescribed syntax
0453:             * @throws  UnknownHostException
0454:             *          If the server or workgroup of the <tt>context</tt> file cannot be determined
0455:             */
0456:
0457:            public SmbFile(SmbFile context, String name)
0458:                    throws MalformedURLException, UnknownHostException {
0459:                this (context.isWorkgroup0() ? new URL(null, "smb://" + name,
0460:                        Handler.SMB_HANDLER) : new URL(context.url, name,
0461:                        Handler.SMB_HANDLER), context.auth);
0462:            }
0463:
0464:            /**
0465:             * Constructs an SmbFile representing a resource on an SMB network such
0466:             * as a file or directory. The second parameter is a relative path from
0467:             * the <code>parent</code>. See the description above for examples of
0468:             * using the second <code>chile</code> parameter.
0469:             *
0470:             * @param   context A URL string
0471:             * @param   name A path string relative to the <code>context</code> paremeter
0472:             * @throws  MalformedURLException
0473:             *          If the <code>context</code> and <code>name</code> parameters
0474:             *          do not follow the prescribed syntax
0475:             */
0476:
0477:            public SmbFile(String context, String name)
0478:                    throws MalformedURLException {
0479:                this (new URL(new URL(null, context, Handler.SMB_HANDLER), name,
0480:                        Handler.SMB_HANDLER));
0481:            }
0482:
0483:            /**
0484:             * Constructs an SmbFile representing a resource on an SMB network such
0485:             * as a file or directory.
0486:             *
0487:             * @param   url A URL string
0488:             * @param   auth The credentials the client should use for authentication
0489:             * @throws  MalformedURLException
0490:             *          If the <code>url</code> parameter does not follow the prescribed syntax
0491:             */
0492:            public SmbFile(String url, NtlmPasswordAuthentication auth)
0493:                    throws MalformedURLException {
0494:                this (new URL(null, url, Handler.SMB_HANDLER), auth);
0495:            }
0496:
0497:            /**
0498:             * Constructs an SmbFile representing a file on an SMB network. The
0499:             * <tt>shareAccess</tt> parameter controls what permissions other
0500:             * clients have when trying to access the same file while this instance
0501:             * is still open. This value is either <tt>FILE_NO_SHARE</tt> or any
0502:             * combination of <tt>FILE_SHARE_READ</tt>, <tt>FILE_SHARE_WRITE</tt>,
0503:             * and <tt>FILE_SHARE_DELETE</tt> logically OR'd together.
0504:             *
0505:             * @param   url A URL string
0506:             * @param   auth The credentials the client should use for authentication
0507:             * @param   shareAccess Specifies what access other clients have while this file is open.
0508:             * @throws  MalformedURLException
0509:             *          If the <code>url</code> parameter does not follow the prescribed syntax
0510:             */
0511:            public SmbFile(String url, NtlmPasswordAuthentication auth,
0512:                    int shareAccess) throws MalformedURLException {
0513:                this (new URL(null, url, Handler.SMB_HANDLER), auth);
0514:                if ((shareAccess & ~(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)) != 0) {
0515:                    throw new RuntimeException("Illegal shareAccess parameter");
0516:                }
0517:                this .shareAccess = shareAccess;
0518:            }
0519:
0520:            /**
0521:             * Constructs an SmbFile representing a resource on an SMB network such
0522:             * as a file or directory. The second parameter is a relative path from
0523:             * the <code>context</code>. See the description above for examples of
0524:             * using the second <code>name</code> parameter.
0525:             *
0526:             * @param   context A URL string
0527:             * @param   name A path string relative to the <code>context</code> paremeter
0528:             * @param   auth The credentials the client should use for authentication
0529:             * @throws  MalformedURLException
0530:             *          If the <code>context</code> and <code>name</code> parameters
0531:             *          do not follow the prescribed syntax
0532:             */
0533:            public SmbFile(String context, String name,
0534:                    NtlmPasswordAuthentication auth)
0535:                    throws MalformedURLException {
0536:                this (new URL(new URL(null, context, Handler.SMB_HANDLER), name,
0537:                        Handler.SMB_HANDLER), auth);
0538:            }
0539:
0540:            /**
0541:             * Constructs an SmbFile representing a resource on an SMB network such
0542:             * as a file or directory. The second parameter is a relative path from
0543:             * the <code>context</code>. See the description above for examples of
0544:             * using the second <code>name</code> parameter. The <tt>shareAccess</tt>
0545:             * parameter controls what permissions other clients have when trying
0546:             * to access the same file while this instance is still open. This
0547:             * value is either <tt>FILE_NO_SHARE</tt> or any combination
0548:             * of <tt>FILE_SHARE_READ</tt>, <tt>FILE_SHARE_WRITE</tt>, and
0549:             * <tt>FILE_SHARE_DELETE</tt> logically OR'd together.
0550:             *
0551:             * @param   context A URL string
0552:             * @param   name A path string relative to the <code>context</code> paremeter
0553:             * @param   auth The credentials the client should use for authentication
0554:             * @param   shareAccess Specifies what access other clients have while this file is open.
0555:             * @throws  MalformedURLException
0556:             *          If the <code>context</code> and <code>name</code> parameters
0557:             *          do not follow the prescribed syntax
0558:             */
0559:            public SmbFile(String context, String name,
0560:                    NtlmPasswordAuthentication auth, int shareAccess)
0561:                    throws MalformedURLException {
0562:                this (new URL(new URL(null, context, Handler.SMB_HANDLER), name,
0563:                        Handler.SMB_HANDLER), auth);
0564:                if ((shareAccess & ~(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)) != 0) {
0565:                    throw new RuntimeException("Illegal shareAccess parameter");
0566:                }
0567:                this .shareAccess = shareAccess;
0568:            }
0569:
0570:            /**
0571:             * Constructs an SmbFile representing a resource on an SMB network such
0572:             * as a file or directory. The second parameter is a relative path from
0573:             * the <code>context</code>. See the description above for examples of
0574:             * using the second <code>name</code> parameter. The <tt>shareAccess</tt>
0575:             * parameter controls what permissions other clients have when trying
0576:             * to access the same file while this instance is still open. This
0577:             * value is either <tt>FILE_NO_SHARE</tt> or any combination
0578:             * of <tt>FILE_SHARE_READ</tt>, <tt>FILE_SHARE_WRITE</tt>, and
0579:             * <tt>FILE_SHARE_DELETE</tt> logically OR'd together.
0580:             *
0581:             * @param   context A base <code>SmbFile</code>
0582:             * @param   name A path string relative to the <code>context</code> file path
0583:             * @param   shareAccess Specifies what access other clients have while this file is open.
0584:             * @throws  MalformedURLException
0585:             *          If the <code>context</code> and <code>name</code> parameters
0586:             *          do not follow the prescribed syntax
0587:             */
0588:            public SmbFile(SmbFile context, String name, int shareAccess)
0589:                    throws MalformedURLException, UnknownHostException {
0590:                this (context.isWorkgroup0() ? new URL(null, "smb://" + name,
0591:                        Handler.SMB_HANDLER) : new URL(context.url, name,
0592:                        Handler.SMB_HANDLER), context.auth);
0593:                if ((shareAccess & ~(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)) != 0) {
0594:                    throw new RuntimeException("Illegal shareAccess parameter");
0595:                }
0596:                this .shareAccess = shareAccess;
0597:            }
0598:
0599:            /**
0600:             * Constructs an SmbFile representing a resource on an SMB network such
0601:             * as a file or directory from a <tt>URL</tt> object.
0602:             *
0603:             * @param   url The URL of the target resource
0604:             */
0605:            public SmbFile(URL url) {
0606:                this (url, new NtlmPasswordAuthentication(url.getUserInfo()));
0607:            }
0608:
0609:            /**
0610:             * Constructs an SmbFile representing a resource on an SMB network such
0611:             * as a file or directory from a <tt>URL</tt> object and an
0612:             * <tt>NtlmPasswordAuthentication</tt> object.
0613:             *
0614:             * @param   url The URL of the target resource
0615:             * @param   auth The credentials the client should use for authentication
0616:             */
0617:            public SmbFile(URL url, NtlmPasswordAuthentication auth) {
0618:                super (url);
0619:                this .auth = auth == null ? new NtlmPasswordAuthentication(url
0620:                        .getUserInfo()) : auth;
0621:
0622:                getUncPath0();
0623:            }
0624:
0625:            SmbFile(SmbFile context, String name, int type, int attributes,
0626:                    long createTime, long lastModified, long size)
0627:                    throws MalformedURLException, UnknownHostException {
0628:                this (context.isWorkgroup0() ? new URL(null, "smb://" + name
0629:                        + "/", Handler.SMB_HANDLER) : new URL(context.url, name
0630:                        + ((attributes & ATTR_DIRECTORY) > 0 ? "/" : "")));
0631:
0632:                /* why was this removed before? DFS? copyTo? Am I going around in circles? */
0633:                auth = context.auth;
0634:
0635:                if (context.share != null) {
0636:                    this .tree = context.tree;
0637:                }
0638:                int last = name.length() - 1;
0639:                if (name.charAt(last) == '/') {
0640:                    name = name.substring(0, last);
0641:                }
0642:                if (context.share == null) {
0643:                    this .unc = "\\";
0644:                } else if (context.unc.equals("\\")) {
0645:                    this .unc = '\\' + name;
0646:                } else {
0647:                    this .unc = context.unc + '\\' + name;
0648:                }
0649:                /* why? am I going around in circles?
0650:                 *  this.type = type == TYPE_WORKGROUP ? 0 : type;
0651:                 */
0652:                this .type = type;
0653:                this .attributes = attributes;
0654:                this .createTime = createTime;
0655:                this .lastModified = lastModified;
0656:                this .size = size;
0657:                isExists = true;
0658:
0659:                attrExpiration = sizeExpiration = System.currentTimeMillis()
0660:                        + attrExpirationPeriod;
0661:            }
0662:
0663:            private SmbComBlankResponse blank_resp() {
0664:                if (blank_resp == null) {
0665:                    blank_resp = new SmbComBlankResponse();
0666:                }
0667:                return blank_resp;
0668:            }
0669:
0670:            void sendTransaction(SmbComTransaction request,
0671:                    SmbComTransactionResponse response) throws SmbException {
0672:                for (;;) {
0673:                    connect0();
0674:                    if (tree.inDfs) {
0675:                        DfsReferral dr = tree.session.transport
0676:                                .lookupReferral(unc);
0677:                        if (dr != null) {
0678:                            UniAddress addr;
0679:                            SmbTransport trans;
0680:
0681:                            try {
0682:                                addr = UniAddress.getByName(dr.server);
0683:                            } catch (UnknownHostException uhe) {
0684:                                throw new SmbException(dr.server, uhe);
0685:                            }
0686:
0687:                            trans = SmbTransport.getSmbTransport(addr, 0);
0688:                            tree = trans.getSmbSession(auth).getSmbTree(
0689:                                    dr.share, null);
0690:                            unc = dr.nodepath + unc.substring(dr.path.length());
0691:                            if (request.path.charAt(request.path.length() - 1) == '\\') {
0692:                                request.path = unc + '\\';
0693:                            } else {
0694:                                request.path = unc;
0695:                            }
0696:                            dfsReferral = dr; /* for getDfsPath */
0697:                        }
0698:                    }
0699:                    if (tree.inDfs) {
0700:                        request.flags2 |= ServerMessageBlock.FLAGS2_RESOLVE_PATHS_IN_DFS;
0701:                    } else {
0702:                        request.flags2 &= ~ServerMessageBlock.FLAGS2_RESOLVE_PATHS_IN_DFS;
0703:                    }
0704:                    try {
0705:                        tree.sendTransaction(request, response);
0706:                        break;
0707:                    } catch (DfsReferral dr) {
0708:                        if (dr.resolveHashes) {
0709:                            throw dr;
0710:                        }
0711:                        request.reset();
0712:                    }
0713:                }
0714:            }
0715:
0716:            void send(ServerMessageBlock request, ServerMessageBlock response)
0717:                    throws SmbException {
0718:                for (;;) {
0719:                    connect0();
0720:                    if (tree.inDfs) {
0721:                        DfsReferral dr = tree.session.transport
0722:                                .lookupReferral(unc);
0723:                        if (dr != null) {
0724:                            UniAddress addr;
0725:                            SmbTransport trans;
0726:
0727:                            try {
0728:                                addr = UniAddress.getByName(dr.server);
0729:                            } catch (UnknownHostException uhe) {
0730:                                throw new SmbException(dr.server, uhe);
0731:                            }
0732:
0733:                            trans = SmbTransport.getSmbTransport(addr, url
0734:                                    .getPort());
0735:                            tree = trans.getSmbSession(auth).getSmbTree(
0736:                                    dr.share, null);
0737:                            unc = request.path = dr.nodepath
0738:                                    + unc.substring(dr.path.length());
0739:                            dfsReferral = dr; /* for getDfsPath */
0740:                        }
0741:                        request.flags2 |= ServerMessageBlock.FLAGS2_RESOLVE_PATHS_IN_DFS;
0742:                    } else {
0743:                        request.flags2 &= ~ServerMessageBlock.FLAGS2_RESOLVE_PATHS_IN_DFS;
0744:                    }
0745:                    try {
0746:                        tree.send(request, response);
0747:                        break;
0748:                    } catch (DfsReferral dr) {
0749:                        if (dr.resolveHashes) {
0750:                            throw dr;
0751:                        }
0752:                    }
0753:                }
0754:            }
0755:
0756:            static String queryLookup(String query, String param) {
0757:                char in[] = query.toCharArray();
0758:                int i, ch, st, eq;
0759:
0760:                st = eq = 0;
0761:                for (i = 0; i < in.length; i++) {
0762:                    ch = in[i];
0763:                    if (ch == '&') {
0764:                        if (eq > st) {
0765:                            String p = new String(in, st, eq - st);
0766:                            if (p.equalsIgnoreCase(param)) {
0767:                                eq++;
0768:                                return new String(in, eq, i - eq);
0769:                            }
0770:                        }
0771:                        st = i + 1;
0772:                    } else if (ch == '=') {
0773:                        eq = i;
0774:                    }
0775:                }
0776:                if (eq > st) {
0777:                    String p = new String(in, st, eq - st);
0778:                    if (p.equalsIgnoreCase(param)) {
0779:                        eq++;
0780:                        return new String(in, eq, in.length - eq);
0781:                    }
0782:                }
0783:
0784:                return null;
0785:            }
0786:
0787:            UniAddress getAddress() throws UnknownHostException {
0788:                String host = url.getHost();
0789:                String path = url.getPath();
0790:                String query = url.getQuery();
0791:
0792:                if (query != null) {
0793:                    String server = queryLookup(query, "server");
0794:                    if (server != null && server.length() > 0) {
0795:                        return UniAddress.getByName(server);
0796:                    }
0797:                }
0798:
0799:                if (host.length() == 0) {
0800:                    try {
0801:                        NbtAddress addr = NbtAddress.getByName(
0802:                                NbtAddress.MASTER_BROWSER_NAME, 0x01, null);
0803:                        return UniAddress.getByName(addr.getHostAddress());
0804:                    } catch (UnknownHostException uhe) {
0805:                        if (NtlmPasswordAuthentication.DEFAULT_DOMAIN
0806:                                .equals("?")) {
0807:                            throw uhe;
0808:                        }
0809:                        return UniAddress
0810:                                .getByName(
0811:                                        NtlmPasswordAuthentication.DEFAULT_DOMAIN,
0812:                                        true);
0813:                    }
0814:                } else if (path.length() == 0 || path.equals("/")) {
0815:                    return UniAddress.getByName(host, true);
0816:                } else {
0817:                    return UniAddress.getByName(host);
0818:                }
0819:            }
0820:
0821:            void connect0() throws SmbException {
0822:                try {
0823:                    connect();
0824:                } catch (UnknownHostException uhe) {
0825:                    throw new SmbException("Failed to connect to server", uhe);
0826:                } catch (SmbException se) {
0827:                    throw se;
0828:                } catch (IOException ioe) {
0829:                    throw new SmbException("Failed to connect to server", ioe);
0830:                }
0831:            }
0832:
0833:            /**
0834:             * It is not necessary to call this method directly. This is the
0835:             * <tt>URLConnection</tt> implementation of <tt>connect()</tt>.
0836:             */
0837:            public void connect() throws IOException {
0838:                SmbTransport trans;
0839:                SmbSession ssn;
0840:                UniAddress addr;
0841:
0842:                if (isConnected()) {
0843:                    return;
0844:                }
0845:
0846:                getUncPath0();
0847:                addr = getAddress();
0848:
0849:                trans = SmbTransport.getSmbTransport(addr, url.getPort());
0850:                ssn = trans.getSmbSession(auth);
0851:                tree = ssn.getSmbTree(share, null);
0852:
0853:                try {
0854:                    tree.treeConnect(null, null);
0855:                } catch (SmbAuthException sae) {
0856:                    NtlmPasswordAuthentication a;
0857:
0858:                    if (share == null) { // IPC$ - try "anonymous" credentials
0859:                        ssn = trans
0860:                                .getSmbSession(NtlmPasswordAuthentication.NULL);
0861:                        tree = ssn.getSmbTree(null, null);
0862:                        tree.treeConnect(null, null);
0863:                    } else if ((a = NtlmAuthenticator
0864:                            .requestNtlmPasswordAuthentication(url.toString(),
0865:                                    sae)) != null) {
0866:                        auth = a;
0867:                        ssn = trans.getSmbSession(auth);
0868:                        tree = ssn.getSmbTree(share, null);
0869:                        tree.treeConnect(null, null);
0870:                    } else {
0871:                        throw sae;
0872:                    }
0873:                }
0874:            }
0875:
0876:            boolean isConnected() {
0877:                return (connected = tree != null && tree.treeConnected);
0878:            }
0879:
0880:            int open0(int flags, int attrs, int options) throws SmbException {
0881:                int f;
0882:
0883:                connect0();
0884:
0885:                if (log.level > 2)
0886:                    log.println("open0: " + unc);
0887:
0888:                /*
0889:                 * NT Create AndX / Open AndX Request / Response
0890:                 */
0891:
0892:                if (tree.session.transport
0893:                        .hasCapability(ServerMessageBlock.CAP_NT_SMBS)) {
0894:                    SmbComNTCreateAndXResponse response = new SmbComNTCreateAndXResponse();
0895:                    send(new SmbComNTCreateAndX(unc, flags, shareAccess, attrs,
0896:                            options, null), response);
0897:                    f = response.fid;
0898:                    attributes = response.extFileAttributes & ATTR_GET_MASK;
0899:                    attrExpiration = System.currentTimeMillis()
0900:                            + attrExpirationPeriod;
0901:                    isExists = true;
0902:                } else {
0903:                    SmbComOpenAndXResponse response = new SmbComOpenAndXResponse();
0904:                    send(new SmbComOpenAndX(unc, flags, null), response);
0905:                    f = response.fid;
0906:                }
0907:
0908:                return f;
0909:            }
0910:
0911:            void open(int flags, int attrs, int options) throws SmbException {
0912:                if (isOpen()) {
0913:                    return;
0914:                }
0915:                fid = open0(flags, attrs, options);
0916:                opened = true;
0917:            }
0918:
0919:            boolean isOpen() {
0920:                return opened && isConnected();
0921:            }
0922:
0923:            void close(int f, long lastWriteTime) throws SmbException {
0924:
0925:                if (log.level > 2)
0926:                    log.println("close: " + f);
0927:
0928:                /*
0929:                 * Close Request / Response
0930:                 */
0931:
0932:                send(new SmbComClose(f, lastWriteTime), blank_resp());
0933:            }
0934:
0935:            void close(long lastWriteTime) throws SmbException {
0936:                if (isOpen() == false) {
0937:                    return;
0938:                }
0939:                close(fid, lastWriteTime);
0940:                opened = false;
0941:            }
0942:
0943:            void close() throws SmbException {
0944:                close(0L);
0945:            }
0946:
0947:            /**
0948:             * Returns the <tt>NtlmPasswordAuthentication</tt> object used as
0949:             * credentials with this file or pipe. This can be used to retrieve the
0950:             * username for example:
0951:             * <tt>
0952:             * String username = f.getPrincipal().getName();
0953:             * </tt>
0954:             * The <tt>Principal</tt> object returned will never be <tt>null</tt>
0955:             * however the username can be <tt>null</tt> indication anonymous
0956:             * credentials were used (e.g. some IPC$ services).
0957:             */
0958:
0959:            public Principal getPrincipal() {
0960:                return auth;
0961:            }
0962:
0963:            /**
0964:             * Returns the last component of the target URL. This will
0965:             * effectively be the name of the file or directory represented by this
0966:             * <code>SmbFile</code> or in the case of URLs that only specify a server
0967:             * or workgroup, the server or workgroup will be returned. The name of
0968:             * the root URL <code>smb://</code> is also <code>smb://</code>. If this
0969:             * <tt>SmbFile</tt> refers to a workgroup, server, share, or directory,
0970:             * the name will include a trailing slash '/' so that composing new
0971:             * <tt>SmbFile</tt>s will maintain the trailing slash requirement.
0972:             *
0973:             * @return  The last component of the URL associated with this SMB
0974:             *          resource or <code>smb://</code> if the resource is <code>smb://</code>
0975:             *          itself.
0976:             */
0977:
0978:            public String getName() {
0979:                getUncPath0();
0980:                if (canon.length() > 1) {
0981:                    int i = canon.length() - 2;
0982:                    while (canon.charAt(i) != '/') {
0983:                        i--;
0984:                    }
0985:                    return canon.substring(i + 1);
0986:                } else if (share != null) {
0987:                    return share + '/';
0988:                } else if (url.getHost().length() > 0) {
0989:                    return url.getHost() + '/';
0990:                } else {
0991:                    return "smb://";
0992:                }
0993:            }
0994:
0995:            /**
0996:             * Everything but the last component of the URL representing this SMB
0997:             * resource is effectivly it's parent. The root URL <code>smb://</code>
0998:             * does not have a parent. In this case <code>smb://</code> is returned.
0999:             *
1000:             * @return   The parent directory of this SMB resource or
1001:             *           <code>smb://</code> if the resource refers to the root of the URL
1002:             *           hierarchy which incedentally is also <code>smb://</code>.
1003:             */
1004:
1005:            public String getParent() {
1006:                String str = url.getAuthority();
1007:
1008:                if (str.length() > 0) {
1009:                    StringBuffer sb = new StringBuffer("smb://");
1010:
1011:                    sb.append(str);
1012:
1013:                    getUncPath0();
1014:                    if (canon.length() > 1) {
1015:                        sb.append(canon);
1016:                    } else {
1017:                        sb.append('/');
1018:                    }
1019:
1020:                    str = sb.toString();
1021:
1022:                    int i = str.length() - 2;
1023:                    while (str.charAt(i) != '/') {
1024:                        i--;
1025:                    }
1026:
1027:                    return str.substring(0, i + 1);
1028:                }
1029:
1030:                return "smb://";
1031:            }
1032:
1033:            /**
1034:             * Returns the full uncanonicalized URL of this SMB resource. An
1035:             * <code>SmbFile</code> constructed with the result of this method will
1036:             * result in an <code>SmbFile</code> that is equal to the original.
1037:             *
1038:             * @return  The uncanonicalized full URL of this SMB resource.
1039:             */
1040:
1041:            public String getPath() {
1042:                return url.toString();
1043:            }
1044:
1045:            String getUncPath0() {
1046:                if (unc == null) {
1047:                    char[] in = url.getPath().toCharArray();
1048:                    char[] out = new char[in.length];
1049:                    int length = in.length, i, o, state, s;
1050:
1051:                    /* The canonicalization routine
1052:                     */
1053:                    state = 0;
1054:                    o = 0;
1055:                    for (i = 0; i < length; i++) {
1056:                        switch (state) {
1057:                        case 0:
1058:                            if (in[i] != '/') {
1059:                                return null;
1060:                            }
1061:                            out[o++] = in[i];
1062:                            state = 1;
1063:                            break;
1064:                        case 1:
1065:                            if (in[i] == '/') {
1066:                                break;
1067:                            } else if (in[i] == '.'
1068:                                    && ((i + 1) >= length || in[i + 1] == '/')) {
1069:                                i++;
1070:                                break;
1071:                            } else if ((i + 1) < length && in[i] == '.'
1072:                                    && in[i + 1] == '.'
1073:                                    && ((i + 2) >= length || in[i + 2] == '/')) {
1074:                                i += 2;
1075:                                if (o == 1)
1076:                                    break;
1077:                                do {
1078:                                    o--;
1079:                                } while (o > 1 && out[o - 1] != '/');
1080:                                break;
1081:                            }
1082:                            state = 2;
1083:                        case 2:
1084:                            if (in[i] == '/') {
1085:                                state = 1;
1086:                            }
1087:                            out[o++] = in[i];
1088:                            break;
1089:                        }
1090:                    }
1091:
1092:                    canon = new String(out, 0, o);
1093:
1094:                    if (o > 1) {
1095:                        o--;
1096:                        i = canon.indexOf('/', 1);
1097:                        if (i < 0) {
1098:                            share = canon.substring(1);
1099:                            unc = "\\";
1100:                        } else if (i == o) {
1101:                            share = canon.substring(1, i);
1102:                            unc = "\\";
1103:                        } else {
1104:                            share = canon.substring(1, i);
1105:                            unc = canon.substring(i, out[o] == '/' ? o : o + 1);
1106:                            unc = unc.replace('/', '\\');
1107:                        }
1108:                    } else {
1109:                        share = null;
1110:                        unc = "\\";
1111:                    }
1112:                }
1113:                return unc;
1114:            }
1115:
1116:            /**
1117:             * Retuns the Windows UNC style path with backslashs intead of forward slashes.
1118:             *
1119:             * @return  The UNC path.
1120:             */
1121:            public String getUncPath() {
1122:                getUncPath0();
1123:                if (share == null) {
1124:                    return "\\\\" + url.getHost();
1125:                }
1126:                return "\\\\" + url.getHost() + canon.replace('/', '\\');
1127:            }
1128:
1129:            /**
1130:             * Returns the full URL of this SMB resource with '.' and '..' components
1131:             * factored out. An <code>SmbFile</code> constructed with the result of
1132:             * this method will result in an <code>SmbFile</code> that is equal to
1133:             * the original.
1134:             *
1135:             * @return  The canonicalized URL of this SMB resource.
1136:             */
1137:
1138:            public String getCanonicalPath() {
1139:                String str = url.getAuthority();
1140:                getUncPath0();
1141:                if (str.length() > 0) {
1142:                    return "smb://" + url.getAuthority() + canon;
1143:                }
1144:                return "smb://";
1145:            }
1146:
1147:            /**
1148:             * Retrieves the share associated with this SMB resource. In
1149:             * the case of <code>smb://</code>, <code>smb://workgroup/</code>,
1150:             * and <code>smb://server/</code> URLs which do not specify a share,
1151:             * <code>null</code> will be returned.
1152:             *
1153:             * @return  The share component or <code>null</code> if there is no share
1154:             */
1155:
1156:            public String getShare() {
1157:                return share;
1158:            }
1159:
1160:            /** 
1161:             * Retrieve the hostname of the server for this SMB resource. If this
1162:             * <code>SmbFile</code> references a workgroup, the name of the workgroup
1163:             * is returned. If this <code>SmbFile</code> refers to the root of this
1164:             * SMB network hierarchy, <code>null</code> is returned.
1165:             * 
1166:             * @return  The server or workgroup name or <code>null</code> if this
1167:             *          <code>SmbFile</code> refers to the root <code>smb://</code> resource.
1168:             */
1169:
1170:            public String getServer() {
1171:                String str = url.getHost();
1172:                if (str.length() == 0) {
1173:                    return null;
1174:                }
1175:                return str;
1176:            }
1177:
1178:            /**
1179:             * Returns type of of object this <tt>SmbFile</tt> represents.
1180:             * @return <tt>TYPE_FILESYSTEM, TYPE_WORKGROUP, TYPE_SERVER, TYPE_SHARE,
1181:             * TYPE_PRINTER, TYPE_NAMED_PIPE</tt>, or <tt>TYPE_COMM</tt>.
1182:             */
1183:            public int getType() throws SmbException {
1184:                if (type == 0) {
1185:                    if (getUncPath0().length() > 1) {
1186:                        type = TYPE_FILESYSTEM;
1187:                    } else if (share != null) {
1188:                        // treeConnect good enough to test service type
1189:                        connect0();
1190:                        if (share.equals("IPC$")) {
1191:                            type = TYPE_NAMED_PIPE;
1192:                        } else if (tree.service.equals("LPT1:")) {
1193:                            type = TYPE_PRINTER;
1194:                        } else if (tree.service.equals("COMM")) {
1195:                            type = TYPE_COMM;
1196:                        } else {
1197:                            type = TYPE_SHARE;
1198:                        }
1199:                    } else if (url.getAuthority().length() == 0) {
1200:                        type = TYPE_WORKGROUP;
1201:                    } else {
1202:                        UniAddress addr;
1203:                        try {
1204:                            addr = getAddress();
1205:                        } catch (UnknownHostException uhe) {
1206:                            throw new SmbException(url.toString(), uhe);
1207:                        }
1208:                        if (addr.getAddress() instanceof  NbtAddress) {
1209:                            int code = ((NbtAddress) addr.getAddress())
1210:                                    .getNameType();
1211:                            if (code == 0x1d || code == 0x1b) {
1212:                                type = TYPE_WORKGROUP;
1213:                                return type;
1214:                            }
1215:                        }
1216:                        type = TYPE_SERVER;
1217:                    }
1218:                }
1219:                return type;
1220:            }
1221:
1222:            boolean isWorkgroup0() throws UnknownHostException {
1223:                if (type == TYPE_WORKGROUP || url.getHost().length() == 0) {
1224:                    type = TYPE_WORKGROUP;
1225:                    return true;
1226:                } else {
1227:                    getUncPath0();
1228:                    if (share == null) {
1229:                        UniAddress addr = getAddress();
1230:                        if (addr.getAddress() instanceof  NbtAddress) {
1231:                            int code = ((NbtAddress) addr.getAddress())
1232:                                    .getNameType();
1233:                            if (code == 0x1d || code == 0x1b) {
1234:                                type = TYPE_WORKGROUP;
1235:                                return true;
1236:                            }
1237:                        }
1238:                        type = TYPE_SERVER;
1239:                    }
1240:                }
1241:                return false;
1242:            }
1243:
1244:            Info queryPath(String path, int infoLevel) throws SmbException {
1245:                connect0();
1246:
1247:                if (log.level > 2)
1248:                    log.println("queryPath: " + path);
1249:
1250:                /* normally we'd check the negotiatedCapabilities for CAP_NT_SMBS
1251:                 * however I can't seem to get a good last modified time from
1252:                 * SMB_COM_QUERY_INFORMATION so if NT_SMBs are requested
1253:                 * by the server than in this case that's what it will get
1254:                 * regardless of what jcifs.smb.client.useNTSmbs is set
1255:                 * to(overrides negotiatedCapabilities).
1256:                 */
1257:
1258:                /* We really should do the referral before this in case
1259:                 * the redirected target has different capabilities. But
1260:                 * the way we have been doing that is to call exists() which
1261:                 * calls this method so another technique will be necessary
1262:                 * to support DFS referral _to_ Win95/98/ME.
1263:                 */
1264:
1265:                if (tree.session.transport
1266:                        .hasCapability(ServerMessageBlock.CAP_NT_SMBS)) {
1267:
1268:                    /*
1269:                     * Trans2 Query Path Information Request / Response
1270:                     */
1271:
1272:                    Trans2QueryPathInformationResponse response = new Trans2QueryPathInformationResponse(
1273:                            infoLevel);
1274:                    sendTransaction(new Trans2QueryPathInformation(path,
1275:                            infoLevel), response);
1276:
1277:                    return response.info;
1278:                } else {
1279:
1280:                    /*
1281:                     * Query Information Request / Response
1282:                     */
1283:
1284:                    SmbComQueryInformationResponse response = new SmbComQueryInformationResponse(
1285:                            tree.session.transport.server.serverTimeZone * 1000 * 60L);
1286:                    send(new SmbComQueryInformation(path), response);
1287:                    return response;
1288:                }
1289:            }
1290:
1291:            /**
1292:             * Tests to see if the SMB resource exists. If the resource refers
1293:             * only to a server, this method determines if the server exists on the
1294:             * network and is advertising SMB services. If this resource refers to
1295:             * a workgroup, this method determines if the workgroup name is valid on
1296:             * the local SMB network. If this <code>SmbFile</code> refers to the root
1297:             * <code>smb://</code> resource <code>true</code> is always returned. If
1298:             * this <code>SmbFile</code> is a traditional file or directory, it will
1299:             * be queried for on the specified server as expected.
1300:             *
1301:             * @return <code>true</code> if the resource exists or is alive or
1302:             *         <code>false</code> otherwise
1303:             */
1304:
1305:            public boolean exists() throws SmbException {
1306:
1307:                if (attrExpiration > System.currentTimeMillis()) {
1308:                    return isExists;
1309:                }
1310:
1311:                attributes = ATTR_READONLY | ATTR_DIRECTORY;
1312:                createTime = 0L;
1313:                lastModified = 0L;
1314:                isExists = false;
1315:
1316:                try {
1317:                    if (url.getHost().length() == 0) {
1318:                    } else if (share == null) {
1319:                        if (getType() == TYPE_WORKGROUP) {
1320:                            UniAddress.getByName(url.getHost(), true);
1321:                        } else {
1322:                            UniAddress.getByName(url.getHost()).getHostName();
1323:                        }
1324:                    } else if (getUncPath0().length() == 1
1325:                            || share.equalsIgnoreCase("IPC$")) {
1326:                        connect0(); // treeConnect is good enough
1327:                    } else {
1328:                        Info info = queryPath(
1329:                                getUncPath0(),
1330:                                Trans2QueryPathInformationResponse.SMB_QUERY_FILE_BASIC_INFO);
1331:                        attributes = info.getAttributes();
1332:                        createTime = info.getCreateTime();
1333:                        lastModified = info.getLastWriteTime();
1334:                    }
1335:
1336:                    /* If any of the above fail, isExists will not be set true
1337:                     */
1338:
1339:                    isExists = true;
1340:
1341:                } catch (UnknownHostException uhe) {
1342:                } catch (SmbException se) {
1343:                    switch (se.getNtStatus()) {
1344:                    case NtStatus.NT_STATUS_NO_SUCH_FILE:
1345:                    case NtStatus.NT_STATUS_OBJECT_NAME_INVALID:
1346:                    case NtStatus.NT_STATUS_OBJECT_NAME_NOT_FOUND:
1347:                    case NtStatus.NT_STATUS_OBJECT_PATH_NOT_FOUND:
1348:                        break;
1349:                    default:
1350:                        throw se;
1351:                    }
1352:                }
1353:
1354:                attrExpiration = System.currentTimeMillis()
1355:                        + attrExpirationPeriod;
1356:
1357:                return isExists;
1358:            }
1359:
1360:            /**
1361:             * Tests to see if the file this <code>SmbFile</code> represents can be
1362:             * read. Because any file, directory, or other resource can be read if it
1363:             * exists, this method simply calls the <code>exists</code> method.
1364:             *
1365:             * @return <code>true</code> if the file is read-only
1366:             */
1367:
1368:            public boolean canRead() throws SmbException {
1369:                if (getType() == TYPE_NAMED_PIPE) { // try opening the pipe for reading?
1370:                    return true;
1371:                }
1372:                return exists(); // try opening and catch sharing violation?
1373:            }
1374:
1375:            /**
1376:             * Tests to see if the file this <code>SmbFile</code> represents
1377:             * exists and is not marked read-only. By default, resources are
1378:             * considered to be read-only and therefore for <code>smb://</code>,
1379:             * <code>smb://workgroup/</code>, and <code>smb://server/</code> resources
1380:             * will be read-only.
1381:             *
1382:             * @return  <code>true</code> if the resource exists is not marked
1383:             *          read-only
1384:             */
1385:
1386:            public boolean canWrite() throws SmbException {
1387:                if (getType() == TYPE_NAMED_PIPE) { // try opening the pipe for writing?
1388:                    return true;
1389:                }
1390:                return exists() && (attributes & ATTR_READONLY) == 0;
1391:            }
1392:
1393:            /**
1394:             * Tests to see if the file this <code>SmbFile</code> represents is a directory.
1395:             *
1396:             * @return <code>true</code> if this <code>SmbFile</code> is a directory
1397:             */
1398:
1399:            public boolean isDirectory() throws SmbException {
1400:                if (getUncPath0().length() == 1) {
1401:                    return true;
1402:                }
1403:                if (!exists())
1404:                    return false;
1405:                return (attributes & ATTR_DIRECTORY) == ATTR_DIRECTORY;
1406:            }
1407:
1408:            /**
1409:             * Tests to see if the file this <code>SmbFile</code> represents is not a directory.
1410:             *
1411:             * @return <code>true</code> if this <code>SmbFile</code> is not a directory
1412:             */
1413:
1414:            public boolean isFile() throws SmbException {
1415:                if (getUncPath0().length() == 1) {
1416:                    return false;
1417:                }
1418:                exists();
1419:                return (attributes & ATTR_DIRECTORY) == 0;
1420:            }
1421:
1422:            /**
1423:             * Tests to see if the file this SmbFile represents is marked as
1424:             * hidden. This method will also return true for shares with names that
1425:             * end with '$' such as <code>IPC$</code> or <code>C$</code>.
1426:             *
1427:             * @return <code>true</code> if the <code>SmbFile</code> is marked as being hidden
1428:             */
1429:
1430:            public boolean isHidden() throws SmbException {
1431:                if (share == null) {
1432:                    return false;
1433:                } else if (getUncPath0().length() == 1) {
1434:                    if (share.endsWith("$")) {
1435:                        return true;
1436:                    }
1437:                    return false;
1438:                }
1439:                exists();
1440:                return (attributes & ATTR_HIDDEN) == ATTR_HIDDEN;
1441:            }
1442:
1443:            /**
1444:             * If the path of this <code>SmbFile</code> falls within a DFS volume,
1445:             * this method will return the referral path to which it maps. Otherwise
1446:             * <code>null</code> is returned.
1447:             */
1448:
1449:            public String getDfsPath() throws SmbException {
1450:                connect0();
1451:                if (tree.inDfs) {
1452:                    exists();
1453:                }
1454:                if (dfsReferral == null) {
1455:                    return null;
1456:                }
1457:                return "smb:/"
1458:                        + (new String(dfsReferral.node + unc)).replace('\\',
1459:                                '/');
1460:            }
1461:
1462:            /**
1463:             * Retrieve the time this <code>SmbFile</code> was created. The value
1464:             * returned is suitable for constructing a {@link java.util.Date} object
1465:             * (i.e. seconds since Epoch 1970). Times should be the same as those
1466:             * reported using the properties dialog of the Windows Explorer program.
1467:             *
1468:             * For Win95/98/Me this is actually the last write time. It is currently
1469:             * not possible to retrieve the create time from files on these systems.
1470:             *
1471:             * @return The number of milliseconds since the 00:00:00 GMT, January 1,
1472:             *         1970 as a <code>long</code> value
1473:             */
1474:            public long createTime() throws SmbException {
1475:                if (getUncPath0().length() > 1) {
1476:                    exists();
1477:                    return createTime;
1478:                }
1479:                return 0L;
1480:            }
1481:
1482:            /**
1483:             * Retrieve the last time the file represented by this
1484:             * <code>SmbFile</code> was modified. The value returned is suitable for
1485:             * constructing a {@link java.util.Date} object (i.e. seconds since Epoch
1486:             * 1970). Times should be the same as those reported using the properties
1487:             * dialog of the Windows Explorer program.
1488:             *
1489:             * @return The number of milliseconds since the 00:00:00 GMT, January 1,
1490:             *         1970 as a <code>long</code> value
1491:             */
1492:            public long lastModified() throws SmbException {
1493:                if (getUncPath0().length() > 1) {
1494:                    exists();
1495:                    return lastModified;
1496:                }
1497:                return 0L;
1498:            }
1499:
1500:            /**
1501:             * List the contents of this SMB resource. The list returned by this
1502:             * method will be;
1503:             *
1504:             * <ul>
1505:             * <li> files and directories contained within this resource if the
1506:             * resource is a normal disk file directory,
1507:             * <li> all available NetBIOS workgroups or domains if this resource is
1508:             * the top level URL <code>smb://</code>,
1509:             * <li> all servers registered as members of a NetBIOS workgroup if this
1510:             * resource refers to a workgroup in a <code>smb://workgroup/</code> URL,
1511:             * <li> all browseable shares of a server including printers, IPC
1512:             * services, or disk volumes if this resource is a server URL in the form
1513:             * <code>smb://server/</code>,
1514:             * <li> or <code>null</code> if the resource cannot be resolved.
1515:             * </ul>
1516:             *
1517:             * @return A <code>String[]</code> array of files and directories,
1518:             * workgroups, servers, or shares depending on the context of the
1519:             * resource URL
1520:             */
1521:            public String[] list() throws SmbException {
1522:                return list("*", ATTR_DIRECTORY | ATTR_HIDDEN | ATTR_SYSTEM,
1523:                        null, null);
1524:            }
1525:
1526:            /**
1527:             * List the contents of this SMB resource. The list returned will be
1528:             * identical to the list returned by the parameterless <code>list()</code>
1529:             * method minus filenames filtered by the specified filter.
1530:             *
1531:             * @param filter a filename filter to exclude filenames from the results
1532:             * @throws SmbException
1533:             # @return An array of filenames
1534:             */
1535:            public String[] list(SmbFilenameFilter filter) throws SmbException {
1536:                return list("*", ATTR_DIRECTORY | ATTR_HIDDEN | ATTR_SYSTEM,
1537:                        filter, null);
1538:            }
1539:
1540:            /**
1541:             * List the contents of this SMB resource as an array of
1542:             * <code>SmbFile</code> objects. This method is much more efficient than
1543:             * the regular <code>list</code> method when querying attributes of each
1544:             * file in the result set.
1545:             * <p>
1546:             * The list of <code>SmbFile</code>s returned by this method will be;
1547:             *
1548:             * <ul>
1549:             * <li> files and directories contained within this resource if the
1550:             * resource is a normal disk file directory,
1551:             * <li> all available NetBIOS workgroups or domains if this resource is
1552:             * the top level URL <code>smb://</code>,
1553:             * <li> all servers registered as members of a NetBIOS workgroup if this
1554:             * resource refers to a workgroup in a <code>smb://workgroup/</code> URL,
1555:             * <li> all browseable shares of a server including printers, IPC
1556:             * services, or disk volumes if this resource is a server URL in the form
1557:             * <code>smb://server/</code>,
1558:             * <li> or <code>null</code> if the resource cannot be resolved.
1559:             * </ul>
1560:             *
1561:             * @return An array of <code>SmbFile</code> objects representing file
1562:             * and directories, workgroups, servers, or shares depending on the context
1563:             * of the resource URL
1564:             */
1565:            public SmbFile[] listFiles() throws SmbException {
1566:                return listFiles("*", ATTR_DIRECTORY | ATTR_HIDDEN
1567:                        | ATTR_SYSTEM, null, null);
1568:            }
1569:
1570:            /**
1571:             * The CIFS protocol provides for DOS "wildcards" to be used as
1572:             * a performance enhancement. The client does not have to filter
1573:             * the names and the server does not have to return all directory
1574:             * entries.
1575:             * <p>
1576:             * The wildcard expression may consist of two special meta
1577:             * characters in addition to the normal filename characters. The '*'
1578:             * character matches any number of characters in part of a name. If
1579:             * the expression begins with one or more '?'s then exactly that
1580:             * many characters will be matched whereas if it ends with '?'s
1581:             * it will match that many characters <i>or less</i>.
1582:             * <p>
1583:             * Wildcard expressions will not filter workgroup names or server names.
1584:             *
1585:             * <blockquote><pre>
1586:             * winnt> ls c?o*
1587:             * clock.avi                  -rw--      82944 Mon Oct 14 1996 1:38 AM
1588:             * Cookies                    drw--          0 Fri Nov 13 1998 9:42 PM
1589:             * 2 items in 5ms
1590:             * </pre></blockquote>
1591:             *
1592:             * @param wildcard a wildcard expression
1593:             * @throws SmbException
1594:             * @return An array of <code>SmbFile</code> objects representing file
1595:             * and directories, workgroups, servers, or shares depending on the context
1596:             * of the resource URL
1597:             */
1598:
1599:            public SmbFile[] listFiles(String wildcard) throws SmbException {
1600:                return listFiles(wildcard, ATTR_DIRECTORY | ATTR_HIDDEN
1601:                        | ATTR_SYSTEM, null, null);
1602:            }
1603:
1604:            /**
1605:             * List the contents of this SMB resource. The list returned will be
1606:             * identical to the list returned by the parameterless <code>listFiles()</code>
1607:             * method minus files filtered by the specified filename filter.
1608:             *
1609:             * @param filter a filter to exclude files from the results
1610:             * @return An array of <tt>SmbFile</tt> objects
1611:             * @throws SmbException
1612:             */
1613:            public SmbFile[] listFiles(SmbFilenameFilter filter)
1614:                    throws SmbException {
1615:                return listFiles("*", ATTR_DIRECTORY | ATTR_HIDDEN
1616:                        | ATTR_SYSTEM, filter, null);
1617:            }
1618:
1619:            /**
1620:             * List the contents of this SMB resource. The list returned will be
1621:             * identical to the list returned by the parameterless <code>listFiles()</code>
1622:             * method minus filenames filtered by the specified filter.
1623:             *
1624:             * @param filter a file filter to exclude files from the results
1625:             * @return An array of <tt>SmbFile</tt> objects
1626:             */
1627:            public SmbFile[] listFiles(SmbFileFilter filter)
1628:                    throws SmbException {
1629:                return listFiles("*", ATTR_DIRECTORY | ATTR_HIDDEN
1630:                        | ATTR_SYSTEM, null, filter);
1631:            }
1632:
1633:            String[] list(String wildcard, int searchAttributes,
1634:                    SmbFilenameFilter fnf, SmbFileFilter ff)
1635:                    throws SmbException {
1636:                ArrayList list = new ArrayList();
1637:
1638:                try {
1639:                    if (url.getHost().length() == 0 || share == null) {
1640:                        doNetEnum(list, false, wildcard, searchAttributes, fnf,
1641:                                ff);
1642:                    } else {
1643:                        doFindFirstNext(list, false, wildcard,
1644:                                searchAttributes, fnf, ff);
1645:                    }
1646:                } catch (UnknownHostException uhe) {
1647:                    throw new SmbException(url.toString(), uhe);
1648:                } catch (MalformedURLException mue) {
1649:                    throw new SmbException(url.toString(), mue);
1650:                }
1651:
1652:                return (String[]) list.toArray(new String[list.size()]);
1653:            }
1654:
1655:            SmbFile[] listFiles(String wildcard, int searchAttributes,
1656:                    SmbFilenameFilter fnf, SmbFileFilter ff)
1657:                    throws SmbException {
1658:                ArrayList list = new ArrayList();
1659:
1660:                if (ff != null && ff instanceof  DosFileFilter) {
1661:                    DosFileFilter dff = (DosFileFilter) ff;
1662:                    if (dff.wildcard != null) {
1663:                        wildcard = dff.wildcard;
1664:                    }
1665:                    searchAttributes = dff.attributes;
1666:                }
1667:
1668:                try {
1669:                    if (url.getHost().length() == 0 || share == null) {
1670:                        doNetEnum(list, true, wildcard, searchAttributes, fnf,
1671:                                ff);
1672:                    } else {
1673:                        doFindFirstNext(list, true, wildcard, searchAttributes,
1674:                                fnf, ff);
1675:                    }
1676:                } catch (UnknownHostException uhe) {
1677:                    throw new SmbException(url.toString(), uhe);
1678:                } catch (MalformedURLException mue) {
1679:                    throw new SmbException(url.toString(), mue);
1680:                }
1681:
1682:                return (SmbFile[]) list.toArray(new SmbFile[list.size()]);
1683:            }
1684:
1685:            void doNetEnum(ArrayList list, boolean files, String wildcard,
1686:                    int searchAttributes, SmbFilenameFilter fnf,
1687:                    SmbFileFilter ff) throws SmbException,
1688:                    UnknownHostException, MalformedURLException {
1689:                SmbComTransaction req;
1690:                SmbComTransactionResponse resp;
1691:                int listType = url.getHost().length() == 0 ? 0 : getType();
1692:                String p = url.getPath();
1693:
1694:                if (p.lastIndexOf('/') != (p.length() - 1)) {
1695:                    throw new SmbException(url.toString()
1696:                            + " directory must end with '/'");
1697:                }
1698:
1699:                switch (listType) {
1700:                case 0:
1701:                    connect0();
1702:                    req = new NetServerEnum2(
1703:                            tree.session.transport.server.oemDomainName,
1704:                            NetServerEnum2.SV_TYPE_DOMAIN_ENUM);
1705:                    resp = new NetServerEnum2Response();
1706:                    break;
1707:                case TYPE_WORKGROUP:
1708:                    req = new NetServerEnum2(url.getHost(),
1709:                            NetServerEnum2.SV_TYPE_ALL);
1710:                    resp = new NetServerEnum2Response();
1711:                    break;
1712:                case TYPE_SERVER:
1713:                    req = new NetShareEnum();
1714:                    resp = new NetShareEnumResponse();
1715:                    break;
1716:                default:
1717:                    throw new SmbException(
1718:                            "The requested list operations is invalid: "
1719:                                    + url.toString());
1720:                }
1721:
1722:                boolean more;
1723:                do {
1724:                    int n;
1725:
1726:                    sendTransaction(req, resp);
1727:
1728:                    more = resp.status == SmbException.ERROR_MORE_DATA;
1729:
1730:                    if (resp.status != SmbException.ERROR_SUCCESS
1731:                            && resp.status != SmbException.ERROR_MORE_DATA) {
1732:                        throw new SmbException(resp.status, true);
1733:                    }
1734:
1735:                    n = more ? resp.numEntries - 1 : resp.numEntries;
1736:                    for (int i = 0; i < n; i++) {
1737:                        FileEntry e = resp.results[i];
1738:                        String name = e.getName();
1739:                        if (fnf != null && fnf.accept(this , name) == false) {
1740:                            continue;
1741:                        }
1742:                        if (name.length() > 0) {
1743:                            SmbFile f = new SmbFile(this , name,
1744:                                    listType == 0 ? TYPE_WORKGROUP
1745:                                            : (listType << 1), ATTR_READONLY
1746:                                            | ATTR_DIRECTORY, 0L, 0L, 0L);
1747:                            if (ff != null && ff.accept(f) == false) {
1748:                                continue;
1749:                            }
1750:                            if (files) {
1751:                                list.add(f);
1752:                            } else {
1753:                                list.add(name);
1754:                            }
1755:                        }
1756:                    }
1757:                    if (listType != 0 && listType != TYPE_WORKGROUP) {
1758:                        break;
1759:                    }
1760:                    req.subCommand = (byte) SmbComTransaction.NET_SERVER_ENUM3;
1761:                    req.reset(0, ((NetServerEnum2Response) resp).lastName);
1762:                    resp.reset();
1763:                } while (more);
1764:            }
1765:
1766:            void doFindFirstNext(ArrayList list, boolean files,
1767:                    String wildcard, int searchAttributes,
1768:                    SmbFilenameFilter fnf, SmbFileFilter ff)
1769:                    throws SmbException, UnknownHostException,
1770:                    MalformedURLException {
1771:                SmbComTransaction req;
1772:                Trans2FindFirst2Response resp;
1773:                int sid;
1774:                String path = getUncPath0();
1775:                String p = url.getPath();
1776:
1777:                if (p.lastIndexOf('/') != (p.length() - 1)) {
1778:                    throw new SmbException(url.toString()
1779:                            + " directory must end with '/'");
1780:                }
1781:
1782:                req = new Trans2FindFirst2(path, wildcard, searchAttributes);
1783:                resp = new Trans2FindFirst2Response();
1784:
1785:                if (log.level > 2)
1786:                    log.println("doFindFirstNext: " + req.path);
1787:
1788:                sendTransaction(req, resp);
1789:
1790:                sid = resp.sid;
1791:                req = new Trans2FindNext2(sid, resp.resumeKey, resp.lastName);
1792:
1793:                /* The only difference between first2 and next2 responses is subCommand
1794:                 * so let's recycle the response object.
1795:                 */
1796:                resp.subCommand = SmbComTransaction.TRANS2_FIND_NEXT2;
1797:
1798:                for (;;) {
1799:                    for (int i = 0; i < resp.numEntries; i++) {
1800:                        FileEntry e = resp.results[i];
1801:                        String name = e.getName();
1802:                        if (name.length() < 3) {
1803:                            int h = name.hashCode();
1804:                            if (h == HASH_DOT || h == HASH_DOT_DOT) {
1805:                                continue;
1806:                            }
1807:                        }
1808:                        if (fnf != null && fnf.accept(this , name) == false) {
1809:                            continue;
1810:                        }
1811:                        if (name.length() > 0) {
1812:                            SmbFile f = new SmbFile(this , name,
1813:                                    TYPE_FILESYSTEM, e.getAttributes(), e
1814:                                            .createTime(), e.lastModified(), e
1815:                                            .length());
1816:                            if (ff != null && ff.accept(f) == false) {
1817:                                continue;
1818:                            }
1819:                            if (files) {
1820:                                list.add(f);
1821:                            } else {
1822:                                list.add(name);
1823:                            }
1824:                        }
1825:                    }
1826:
1827:                    if (resp.isEndOfSearch || resp.numEntries == 0) {
1828:                        break;
1829:                    }
1830:
1831:                    req.reset(resp.resumeKey, resp.lastName);
1832:                    resp.reset();
1833:                    sendTransaction(req, resp);
1834:                }
1835:
1836:                send(new SmbComFindClose2(sid), blank_resp());
1837:            }
1838:
1839:            /**
1840:             * Changes the name of the file this <code>SmbFile</code> represents to the name
1841:             * designated by the <code>SmbFile</code> argument.
1842:             * <p/>
1843:             * <i>Remember: <code>SmbFile</code>s are immutible and therefore
1844:             * the path associated with this <code>SmbFile</code> object will not
1845:             * change). To access the renamed file it is necessary to construct a
1846:             * new <tt>SmbFile</tt></i>.
1847:             *
1848:             * @param  dest  An <code>SmbFile</code> that represents the new pathname
1849:             * @return <code>true</code> if the file or directory was successfully renamed
1850:             * @throws NullPointerException
1851:             *         If the <code>dest</code> argument is <code>null</code>
1852:             */
1853:            public void renameTo(SmbFile dest) throws SmbException {
1854:                if (getUncPath0().length() == 1
1855:                        || dest.getUncPath0().length() == 1) {
1856:                    throw new SmbException(
1857:                            "Invalid operation for workgroups, servers, or shares");
1858:                }
1859:                connect0();
1860:                dest.connect0();
1861:
1862:                if (tree.inDfs) { /* This ensures that each path is
1863:                 * resolved independantly to deal with the case where files
1864:                 * have the same base path but ultimately turn out to be
1865:                 * on different servers because of DFS. It also eliminates
1866:                 * manipulating the SMB path which is problematic because
1867:                 * there are really two that would need to be prefixed
1868:                 * with host and share as DFS requires.
1869:                 */
1870:                    exists();
1871:                    dest.exists();
1872:                }
1873:                if (tree != dest.tree) {
1874:                    throw new SmbException(
1875:                            "Invalid operation for workgroups, servers, or shares");
1876:                }
1877:
1878:                if (log.level > 2)
1879:                    log.println("renameTo: " + unc + " -> " + dest.unc);
1880:
1881:                attrExpiration = sizeExpiration = 0;
1882:                dest.attrExpiration = 0;
1883:
1884:                /*
1885:                 * Rename Request / Response
1886:                 */
1887:
1888:                send(new SmbComRename(unc, dest.unc), blank_resp());
1889:            }
1890:
1891:            class WriterThread extends Thread {
1892:                byte[] b;
1893:                int n, off;
1894:                boolean ready;
1895:                SmbFile dest;
1896:                SmbException e = null;
1897:                boolean useNTSmbs;
1898:                SmbComWriteAndX reqx;
1899:                SmbComWrite req;
1900:                ServerMessageBlock resp;
1901:
1902:                WriterThread() throws SmbException {
1903:                    super ("JCIFS-WriterThread");
1904:                    useNTSmbs = tree.session.transport
1905:                            .hasCapability(ServerMessageBlock.CAP_NT_SMBS);
1906:                    if (useNTSmbs) {
1907:                        reqx = new SmbComWriteAndX();
1908:                        resp = new SmbComWriteAndXResponse();
1909:                    } else {
1910:                        req = new SmbComWrite();
1911:                        resp = new SmbComWriteResponse();
1912:                    }
1913:                    ready = false;
1914:                }
1915:
1916:                synchronized void write(byte[] b, int n, SmbFile dest, int off) {
1917:                    this .b = b;
1918:                    this .n = n;
1919:                    this .dest = dest;
1920:                    this .off = off;
1921:                    ready = false;
1922:                    notify();
1923:                }
1924:
1925:                public void run() {
1926:                    synchronized (this ) {
1927:                        try {
1928:                            for (;;) {
1929:                                notify();
1930:                                ready = true;
1931:                                while (ready) {
1932:                                    wait();
1933:                                }
1934:                                if (n == -1) {
1935:                                    return;
1936:                                }
1937:                                if (useNTSmbs) {
1938:                                    reqx.setParam(dest.fid, off, n, b, 0, n);
1939:                                    dest.send(reqx, resp);
1940:                                } else {
1941:                                    req.setParam(dest.fid, off, n, b, 0, n);
1942:                                    dest.send(req, resp);
1943:                                }
1944:                            }
1945:                        } catch (SmbException e) {
1946:                            this .e = e;
1947:                        } catch (Exception x) {
1948:                            this .e = new SmbException("WriterThread", x);
1949:                        }
1950:                        notify();
1951:                    }
1952:                }
1953:            }
1954:
1955:            void copyTo0(SmbFile dest, byte[][] b, int bsize, WriterThread w,
1956:                    SmbComReadAndX req, SmbComReadAndXResponse resp)
1957:                    throws SmbException {
1958:                int i;
1959:
1960:                if (attrExpiration < System.currentTimeMillis()) {
1961:                    attributes = ATTR_READONLY | ATTR_DIRECTORY;
1962:                    createTime = 0L;
1963:                    lastModified = 0L;
1964:                    isExists = false;
1965:
1966:                    Info info = queryPath(
1967:                            getUncPath0(),
1968:                            Trans2QueryPathInformationResponse.SMB_QUERY_FILE_BASIC_INFO);
1969:                    attributes = info.getAttributes();
1970:                    createTime = info.getCreateTime();
1971:                    lastModified = info.getLastWriteTime();
1972:
1973:                    /* If any of the above fails, isExists will not be set true
1974:                     */
1975:
1976:                    isExists = true;
1977:                    attrExpiration = System.currentTimeMillis()
1978:                            + attrExpirationPeriod;
1979:                }
1980:
1981:                if (isDirectory()) {
1982:                    SmbFile[] files;
1983:                    SmbFile ndest;
1984:
1985:                    String path = dest.getUncPath0();
1986:                    if (path.length() > 1) {
1987:                        try {
1988:                            dest.mkdir();
1989:                            dest.setPathInformation(attributes, createTime,
1990:                                    lastModified);
1991:                        } catch (SmbException se) {
1992:                            if (se.getNtStatus() != NtStatus.NT_STATUS_ACCESS_DENIED
1993:                                    && se.getNtStatus() != NtStatus.NT_STATUS_OBJECT_NAME_COLLISION) {
1994:                                throw se;
1995:                            }
1996:                        }
1997:                    }
1998:
1999:                    files = listFiles("*", ATTR_DIRECTORY | ATTR_HIDDEN
2000:                            | ATTR_SYSTEM, null, null);
2001:                    try {
2002:                        for (i = 0; i < files.length; i++) {
2003:                            ndest = new SmbFile(dest, files[i].getName(),
2004:                                    files[i].type, files[i].attributes,
2005:                                    files[i].createTime, files[i].lastModified,
2006:                                    files[i].size);
2007:                            files[i].copyTo0(ndest, b, bsize, w, req, resp);
2008:                        }
2009:                    } catch (UnknownHostException uhe) {
2010:                        throw new SmbException(url.toString(), uhe);
2011:                    } catch (MalformedURLException mue) {
2012:                        throw new SmbException(url.toString(), mue);
2013:                    }
2014:                } else {
2015:                    int off;
2016:
2017:                    try {
2018:                        open(SmbFile.O_RDONLY, ATTR_NORMAL, 0);
2019:                        try {
2020:                            dest
2021:                                    .open(
2022:                                            SmbFile.O_CREAT
2023:                                                    | SmbFile.O_WRONLY
2024:                                                    | SmbFile.O_TRUNC
2025:                                                    | SmbComNTCreateAndX.FILE_WRITE_ATTRIBUTES << 16,
2026:                                            attributes, 0);
2027:                        } catch (SmbAuthException sae) {
2028:                            if ((dest.attributes & ATTR_READONLY) != 0) {
2029:                                /* Remove READONLY and try again
2030:                                 */
2031:                                dest.setPathInformation(dest.attributes
2032:                                        & ~ATTR_READONLY, 0L, 0L);
2033:                                dest
2034:                                        .open(
2035:                                                SmbFile.O_CREAT
2036:                                                        | SmbFile.O_WRONLY
2037:                                                        | SmbFile.O_TRUNC
2038:                                                        | SmbComNTCreateAndX.FILE_WRITE_ATTRIBUTES << 16,
2039:                                                attributes, 0);
2040:                            } else {
2041:                                throw sae;
2042:                            }
2043:                        }
2044:
2045:                        i = off = 0;
2046:                        for (;;) {
2047:                            req.setParam(fid, off, bsize);
2048:                            resp.setParam(b[i], 0);
2049:                            send(req, resp);
2050:
2051:                            synchronized (w) {
2052:                                while (!w.ready) {
2053:                                    try {
2054:                                        w.wait();
2055:                                    } catch (InterruptedException ie) {
2056:                                        throw new SmbException(dest.url
2057:                                                .toString(), ie);
2058:                                    }
2059:                                }
2060:                                if (w.e != null) {
2061:                                    throw w.e;
2062:                                }
2063:                                if (resp.dataLength <= 0) {
2064:                                    break;
2065:                                }
2066:                                w.write(b[i], resp.dataLength, dest, off);
2067:                            }
2068:
2069:                            i = i == 1 ? 0 : 1;
2070:                            off += resp.dataLength;
2071:                        }
2072:
2073:                        dest.sendTransaction(
2074:                                new Trans2SetFileInformation(dest.fid,
2075:                                        attributes, createTime, lastModified),
2076:                                new Trans2SetFileInformationResponse());
2077:                        dest.close(0L);
2078:                        close();
2079:                    } catch (Exception ex) {
2080:                        if (log.level > 1)
2081:                            ex.printStackTrace(log);
2082:                    }
2083:                }
2084:            }
2085:
2086:            /**
2087:             * This method will copy the file or directory represented by this
2088:             * <tt>SmbFile</tt> and it's sub-contents to the location specified by the
2089:             * <tt>dest</tt> parameter. This file and the destination file do not
2090:             * need to be on the same host. This operation does not copy extended
2091:             * file attibutes such as ACLs but it does copy regular attributes as
2092:             * well as create and last write times. This method is almost twice as
2093:             * efficient as manually copying as it employs an additional write
2094:             * thread to read and write data concurrently.
2095:             * <p/>
2096:             * It is not possible (nor meaningful) to copy entire workgroups or
2097:             * servers.
2098:             *
2099:             * @param dest the destination file or directory
2100:             * @throws SmbException
2101:             */
2102:            public void copyTo(SmbFile dest) throws SmbException {
2103:                SmbComReadAndX req;
2104:                SmbComReadAndXResponse resp;
2105:                WriterThread w;
2106:                int bsize;
2107:                byte[][] b;
2108:
2109:                /* Should be able to copy an entire share actually
2110:                 */
2111:                if (share == null || dest.share == null) {
2112:                    throw new SmbException(
2113:                            "Invalid operation for workgroups or servers");
2114:                }
2115:
2116:                req = new SmbComReadAndX();
2117:                resp = new SmbComReadAndXResponse();
2118:
2119:                connect0();
2120:                dest.connect0();
2121:
2122:                if (tree.inDfs) {
2123:                    /* At this point the maxBufferSize values are from the server
2124:                     * exporting the volumes, not the one that we will actually
2125:                     * end up performing IO with. If the server hosting the
2126:                     * actual files has a smaller maxBufSize this could be
2127:                     * incorrect. To handle this properly it is necessary
2128:                     * to redirect the tree to the target server first before
2129:                     * establishing buffer size. These exists() calls facilitate
2130:                     * that.
2131:                     */
2132:                    exists();
2133:                    dest.exists();
2134:                }
2135:
2136:                w = new WriterThread();
2137:                w.setDaemon(true);
2138:                w.start();
2139:
2140:                /* Downgrade one transport to the lower of the negotiated buffer sizes
2141:                 * so we can just send whatever is received.
2142:                 */
2143:
2144:                SmbTransport t1 = tree.session.transport;
2145:                SmbTransport t2 = dest.tree.session.transport;
2146:
2147:                if (t1.snd_buf_size < t2.snd_buf_size) {
2148:                    t2.snd_buf_size = t1.snd_buf_size;
2149:                } else {
2150:                    t1.snd_buf_size = t2.snd_buf_size;
2151:                }
2152:
2153:                bsize = Math.min(t1.rcv_buf_size - 70, t1.snd_buf_size - 70);
2154:                b = new byte[2][bsize];
2155:
2156:                copyTo0(dest, b, bsize, w, req, resp);
2157:                w.write(null, -1, null, 0);
2158:            }
2159:
2160:            /**
2161:             * This method will delete the file or directory specified by this
2162:             * <code>SmbFile</code>. If the target is a directory, the contents of
2163:             * the directory will be deleted as well. If a file within the directory or
2164:             * it's sub-directories is marked read-only, the read-only status will
2165:             * be removed and the file will be deleted.
2166:             *
2167:             * @throws SmbException
2168:             */
2169:            public void delete() throws SmbException {
2170:                if (tree == null || tree.inDfs) {
2171:                    exists(); /* This is necessary to ensure we
2172:                     * pass a path adjusted for DFS */
2173:                }
2174:                getUncPath0();
2175:                delete(unc);
2176:            }
2177:
2178:            void delete(String fileName) throws SmbException {
2179:                if (getUncPath0().length() == 1) {
2180:                    throw new SmbException(
2181:                            "Invalid operation for workgroups, servers, or shares");
2182:                }
2183:
2184:                if (System.currentTimeMillis() > attrExpiration) {
2185:                    attributes = ATTR_READONLY | ATTR_DIRECTORY;
2186:                    createTime = 0L;
2187:                    lastModified = 0L;
2188:                    isExists = false;
2189:
2190:                    Info info = queryPath(
2191:                            getUncPath0(),
2192:                            Trans2QueryPathInformationResponse.SMB_QUERY_FILE_BASIC_INFO);
2193:                    attributes = info.getAttributes();
2194:                    createTime = info.getCreateTime();
2195:                    lastModified = info.getLastWriteTime();
2196:
2197:                    attrExpiration = System.currentTimeMillis()
2198:                            + attrExpirationPeriod;
2199:                    isExists = true;
2200:                }
2201:
2202:                if ((attributes & ATTR_READONLY) != 0) {
2203:                    setReadWrite();
2204:                }
2205:
2206:                /*
2207:                 * Delete or Delete Directory Request / Response
2208:                 */
2209:
2210:                if (log.level > 2)
2211:                    log.println("delete: " + fileName);
2212:
2213:                if ((attributes & ATTR_DIRECTORY) != 0) {
2214:
2215:                    /* Recursively delete directory contents
2216:                     */
2217:
2218:                    try {
2219:                        SmbFile[] l = listFiles("*", ATTR_DIRECTORY
2220:                                | ATTR_HIDDEN | ATTR_SYSTEM, null, null);
2221:                        for (int i = 0; i < l.length; i++) {
2222:                            l[i].delete();
2223:                        }
2224:                    } catch (SmbException se) {
2225:                        /* Oracle FilesOnline version 9.0.4 doesn't send '.' and '..' so
2226:                         * listFiles may generate undesireable "cannot find
2227:                         * the file specified".
2228:                         */
2229:                        if (se.getNtStatus() != SmbException.NT_STATUS_NO_SUCH_FILE) {
2230:                            throw se;
2231:                        }
2232:                    }
2233:
2234:                    send(new SmbComDeleteDirectory(fileName), blank_resp());
2235:                } else {
2236:                    send(new SmbComDelete(fileName), blank_resp());
2237:                }
2238:
2239:                attrExpiration = sizeExpiration = 0;
2240:            }
2241:
2242:            /**
2243:             * Returns the length of this <tt>SmbFile</tt> in bytes. If this object
2244:             * is a <tt>TYPE_SHARE</tt> the total capacity of the disk shared in
2245:             * bytes is returned. If this object is a directory or a type other than
2246:             * <tt>TYPE_SHARE</tt>, 0L is returned.
2247:             *
2248:             * @return The length of the file in bytes or 0 if this
2249:             * <code>SmbFile</code> is not a file.
2250:             * @throws SmbException
2251:             */
2252:
2253:            public long length() throws SmbException {
2254:                if (sizeExpiration > System.currentTimeMillis()) {
2255:                    return size;
2256:                }
2257:
2258:                if (getType() == TYPE_SHARE) {
2259:                    Trans2QueryFSInformationResponse response;
2260:                    int level = Trans2QueryFSInformationResponse.SMB_INFO_ALLOCATION;
2261:
2262:                    response = new Trans2QueryFSInformationResponse(level);
2263:                    sendTransaction(new Trans2QueryFSInformation(level),
2264:                            response);
2265:
2266:                    size = response.info.getCapacity();
2267:                } else if (getUncPath0().length() > 1
2268:                        && type != TYPE_NAMED_PIPE) {
2269:                    Info info = queryPath(
2270:                            getUncPath0(),
2271:                            Trans2QueryPathInformationResponse.SMB_QUERY_FILE_STANDARD_INFO);
2272:                    size = info.getSize();
2273:                } else {
2274:                    size = 0L;
2275:                }
2276:                sizeExpiration = System.currentTimeMillis()
2277:                        + attrExpirationPeriod;
2278:                return size;
2279:            }
2280:
2281:            /**
2282:             * This method returns the free disk space in bytes of the drive this share
2283:             * represents or the drive on which the directory or file resides. Objects
2284:             * other than <tt>TYPE_SHARE</tt> or <tt>TYPE_FILESYSTEM</tt> will result
2285:             * in 0L being returned.
2286:             *
2287:             * @return the free disk space in bytes of the drive on which this file or
2288:             * directory resides
2289:             */
2290:            public long getDiskFreeSpace() throws SmbException {
2291:                if (getType() == TYPE_SHARE || type == TYPE_FILESYSTEM) {
2292:                    Trans2QueryFSInformationResponse response;
2293:                    int level = Trans2QueryFSInformationResponse.SMB_INFO_ALLOCATION;
2294:
2295:                    response = new Trans2QueryFSInformationResponse(level);
2296:                    sendTransaction(new Trans2QueryFSInformation(level),
2297:                            response);
2298:
2299:                    if (type == TYPE_SHARE) {
2300:                        size = response.info.getCapacity();
2301:                        sizeExpiration = System.currentTimeMillis()
2302:                                + attrExpirationPeriod;
2303:                    }
2304:
2305:                    return response.info.getFree();
2306:                }
2307:                return 0L;
2308:            }
2309:
2310:            /**
2311:             * Creates a directory with the path specified by this
2312:             * <code>SmbFile</code>. For this method to be successful, the target
2313:             * must not already exist. This method will fail when
2314:             * used with <code>smb://</code>, <code>smb://workgroup/</code>,
2315:             * <code>smb://server/</code>, or <code>smb://server/share/</code> URLs
2316:             * because workgroups, servers, and shares cannot be dynamically created
2317:             * (although in the future it may be possible to create shares).
2318:             *
2319:             * @throws SmbException
2320:             */
2321:            public void mkdir() throws SmbException {
2322:                String path = getUncPath0();
2323:
2324:                if (path.length() == 1) {
2325:                    throw new SmbException(
2326:                            "Invalid operation for workgroups, servers, or shares");
2327:                }
2328:
2329:                /*
2330:                 * Create Directory Request / Response
2331:                 */
2332:
2333:                if (log.level > 2)
2334:                    log.println("mkdir: " + path);
2335:
2336:                send(new SmbComCreateDirectory(path), blank_resp());
2337:
2338:                attrExpiration = sizeExpiration = 0;
2339:            }
2340:
2341:            /**
2342:             * Creates a directory with the path specified by this <tt>SmbFile</tt>
2343:             * and any parent directories that do not exist. This method will fail
2344:             * when used with <code>smb://</code>, <code>smb://workgroup/</code>,
2345:             * <code>smb://server/</code>, or <code>smb://server/share/</code> URLs
2346:             * because workgroups, servers, and shares cannot be dynamically created
2347:             * (although in the future it may be possible to create shares).
2348:             *
2349:             * @throws SmbException
2350:             */
2351:            public void mkdirs() throws SmbException {
2352:                SmbFile parent;
2353:
2354:                try {
2355:                    parent = new SmbFile(getParent(), auth);
2356:                } catch (IOException ioe) {
2357:                    return;
2358:                }
2359:                if (parent.exists() == false) {
2360:                    parent.mkdirs();
2361:                }
2362:                mkdir();
2363:            }
2364:
2365:            /**
2366:             * Create a new file but fail if it already exists. The check for
2367:             * existance of the file and it's creation are an atomic operation with
2368:             * respect to other filesystem activities.
2369:             */
2370:            public void createNewFile() throws SmbException {
2371:                if (getUncPath0().length() == 1) {
2372:                    throw new SmbException(
2373:                            "Invalid operation for workgroups, servers, or shares");
2374:                }
2375:                close(open0(O_RDWR | O_CREAT | O_EXCL, ATTR_NORMAL, 0), 0L);
2376:            }
2377:
2378:            void setPathInformation(int attrs, long ctime, long mtime)
2379:                    throws SmbException {
2380:                int f, options = 0;
2381:
2382:                if ((attrs & ATTR_DIRECTORY) != 0) {
2383:                    options = 1;
2384:                }
2385:
2386:                f = open0(O_RDONLY
2387:                        | SmbComNTCreateAndX.FILE_WRITE_ATTRIBUTES << 16,
2388:                        attrs, options);
2389:                sendTransaction(new Trans2SetFileInformation(f, attrs, ctime,
2390:                        mtime), new Trans2SetFileInformationResponse());
2391:                close(f, 0L);
2392:
2393:                attrExpiration = 0;
2394:            }
2395:
2396:            /**
2397:             * Set the create time of the file. The time is specified as milliseconds
2398:             * from Jan 1, 1970 which is the same as that which is returned by the
2399:             * <tt>createTime()</tt> method.
2400:             * <p/>
2401:             * This method does not apply to workgroups, servers, or shares.
2402:             *
2403:             * @param time the create time as milliseconds since Jan 1, 1970
2404:             */
2405:            public void setCreateTime(long time) throws SmbException {
2406:                if (getUncPath0().length() == 1) {
2407:                    throw new SmbException(
2408:                            "Invalid operation for workgroups, servers, or shares");
2409:                }
2410:
2411:                setPathInformation(0, time, 0L);
2412:            }
2413:
2414:            /**
2415:             * Set the last modified time of the file. The time is specified as milliseconds
2416:             * from Jan 1, 1970 which is the same as that which is returned by the
2417:             * <tt>lastModified()</tt>, <tt>getLastModified()</tt>, and <tt>getDate()</tt> methods.
2418:             * <p/>
2419:             * This method does not apply to workgroups, servers, or shares.
2420:             *
2421:             * @param time the last modified time as milliseconds since Jan 1, 1970
2422:             */
2423:            public void setLastModified(long time) throws SmbException {
2424:                if (getUncPath0().length() == 1) {
2425:                    throw new SmbException(
2426:                            "Invalid operation for workgroups, servers, or shares");
2427:                }
2428:
2429:                setPathInformation(0, 0L, time);
2430:            }
2431:
2432:            /**
2433:             * Return the attributes of this file. Attributes are represented as a
2434:             * bitset that must be masked with <tt>ATTR_*</tt> constants to determine
2435:             * if they are set or unset. The value returned is suitable for use with
2436:             * the <tt>setAttributes()</tt> method.
2437:             *
2438:             * @return the <tt>ATTR_*</tt> attributes associated with this file
2439:             * @throws SmbException
2440:             */
2441:            public int getAttributes() throws SmbException {
2442:                if (getUncPath0().length() == 1) {
2443:                    return 0;
2444:                }
2445:                exists();
2446:                return attributes & ATTR_GET_MASK;
2447:            }
2448:
2449:            /**
2450:             * Set the attributes of this file. Attributes are composed into a
2451:             * bitset by bitwise ORing the <tt>ATTR_*</tt> constants. Setting the
2452:             * value returned by <tt>getAttributes</tt> will result in both files
2453:             * having the same attributes.
2454:             * @throws SmbException
2455:             */
2456:            public void setAttributes(int attrs) throws SmbException {
2457:                if (getUncPath0().length() == 1) {
2458:                    throw new SmbException(
2459:                            "Invalid operation for workgroups, servers, or shares");
2460:                }
2461:
2462:                setPathInformation(attrs & ATTR_SET_MASK, 0L, 0L);
2463:            }
2464:
2465:            /**
2466:             * Make this file read-only. This is shorthand for <tt>setAttributes(
2467:             * getAttributes() | ATTR_READ_ONLY )</tt>.
2468:             *
2469:             * @throws SmbException
2470:             */
2471:            public void setReadOnly() throws SmbException {
2472:                setAttributes(getAttributes() | ATTR_READONLY);
2473:            }
2474:
2475:            /**
2476:             * Turn off the read-only attribute of this file. This is shorthand for
2477:             * <tt>setAttributes( getAttributes() & ~ATTR_READONLY )</tt>.
2478:             *
2479:             * @throws SmbException
2480:             */
2481:            public void setReadWrite() throws SmbException {
2482:                setAttributes(getAttributes() & ~ATTR_READONLY);
2483:            }
2484:
2485:            /**
2486:             * Returns a {@link java.net.URL} for this <code>SmbFile</code>. The
2487:             * <code>URL</code> may be used as any other <code>URL</code> might to
2488:             * access an SMB resource. Currently only retrieving data and information
2489:             * is supported (i.e. no <tt>doOutput</tt>).
2490:             *
2491:             * @deprecated Use getURL() instead
2492:             * @return A new <code>{@link java.net.URL}</code> for this <code>SmbFile</code>
2493:             * @throws MalformedURLException
2494:             */
2495:            public URL toURL() throws MalformedURLException {
2496:                return url;
2497:            }
2498:
2499:            /**
2500:             * Computes a hashCode for this file based on the URL string and IP
2501:             * address if the server. The hashing function uses the hashcode of the
2502:             * server address, the canonical representation of the URL, and does not
2503:             * compare authentication information. In essance, two
2504:             * <code>SmbFile</code> objects that refer to
2505:             * the same file should generate the same hashcode provided it is possible
2506:             * to make such a determination.
2507:             *
2508:             * @return  A hashcode for this abstract file
2509:             * @throws SmbException
2510:             */
2511:
2512:            public int hashCode() {
2513:                int hash;
2514:                try {
2515:                    hash = getAddress().hashCode();
2516:                } catch (UnknownHostException uhe) {
2517:                    hash = getServer().toUpperCase().hashCode();
2518:                }
2519:                getUncPath0();
2520:                return hash + canon.toUpperCase().hashCode();
2521:            }
2522:
2523:            /**
2524:             * Tests to see if two <code>SmbFile</code> objects are equal. Two
2525:             * SmbFile objects are equal when they reference the same SMB
2526:             * resource. More specifically, two <code>SmbFile</code> objects are
2527:             * equals if their server IP addresses are equal and the canonicalized
2528:             * representation of their URLs, minus authentication parameters, are
2529:             * case insensitivly and lexographically equal.
2530:             * <p/>
2531:             * For example, assuming the server <code>angus</code> resolves to the
2532:             * <code>192.168.1.15</code> IP address, the below URLs would result in
2533:             * <code>SmbFile</code>s that are equal.
2534:             *
2535:             * <p><blockquote><pre>
2536:             * smb://192.168.1.15/share/DIR/foo.txt
2537:             * smb://angus/share/data/../dir/foo.txt
2538:             * </pre></blockquote>
2539:             *
2540:             * @param   obj Another <code>SmbFile</code> object to compare for equality
2541:             * @return  <code>true</code> if the two objects refer to the same SMB resource
2542:             *          and <code>false</code> otherwise
2543:             * @throws SmbException
2544:             */
2545:
2546:            public boolean equals(Object obj) {
2547:                return obj instanceof  SmbFile && obj.hashCode() == hashCode();
2548:            }
2549:
2550:            /**
2551:             * Returns the string representation of this SmbFile object. This will
2552:             * be the same as the URL used to construct this <code>SmbFile</code>.
2553:             * This method will return the same value
2554:             * as <code>getPath</code>.
2555:             *
2556:             * @return  The original URL representation of this SMB resource
2557:             * @throws SmbException
2558:             */
2559:
2560:            public String toString() {
2561:                return url.toString();
2562:            }
2563:
2564:            /* URLConnection implementation */
2565:            /**
2566:             * This URLConnection method just returns the result of <tt>length()</tt>.
2567:             *
2568:             * @return the length of this file or 0 if it refers to a directory
2569:             */
2570:
2571:            public int getContentLength() {
2572:                try {
2573:                    return (int) (length() & 0xFFFFFFFFL);
2574:                } catch (SmbException se) {
2575:                }
2576:                return 0;
2577:            }
2578:
2579:            /**
2580:             * This URLConnection method just returns the result of <tt>lastModified</tt>.
2581:             *
2582:             * @return the last modified data as milliseconds since Jan 1, 1970
2583:             */
2584:            public long getDate() {
2585:                try {
2586:                    return lastModified();
2587:                } catch (SmbException se) {
2588:                }
2589:                return 0L;
2590:            }
2591:
2592:            /**
2593:             * This URLConnection method just returns the result of <tt>lastModified</tt>.
2594:             *
2595:             * @return the last modified data as milliseconds since Jan 1, 1970
2596:             */
2597:            public long getLastModified() {
2598:                try {
2599:                    return lastModified();
2600:                } catch (SmbException se) {
2601:                }
2602:                return 0L;
2603:            }
2604:
2605:            /**
2606:             * This URLConnection method just returns a new <tt>SmbFileInputStream</tt> created with this file.
2607:             *
2608:             * @throws IOException thrown by <tt>SmbFileInputStream</tt> constructor
2609:             */
2610:            public InputStream getInputStream() throws IOException {
2611:                return new SmbFileInputStream(this );
2612:            }
2613:
2614:            /**
2615:             * This URLConnection method just returns a new <tt>SmbFileOutputStream</tt> created with this file.
2616:             *
2617:             * @throws IOException thrown by <tt>SmbFileOutputStream</tt> constructor
2618:             */
2619:            public OutputStream getOutputStream() throws IOException {
2620:                return new SmbFileOutputStream(this);
2621:            }
2622:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.