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