CoreDiskSession.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. /*
  2. * Copyright (C) 2006-2010 Alfresco Software Limited.
  3. *
  4. * This file is part of Alfresco
  5. *
  6. * Alfresco is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Alfresco is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package org.alfresco.jlan.client;
  20. import java.io.IOException;
  21. import org.alfresco.jlan.client.info.DiskInfo;
  22. import org.alfresco.jlan.client.info.FileInfo;
  23. import org.alfresco.jlan.client.info.VolumeInfo;
  24. import org.alfresco.jlan.server.filesys.AccessMode;
  25. import org.alfresco.jlan.smb.DataType;
  26. import org.alfresco.jlan.smb.PCShare;
  27. import org.alfresco.jlan.smb.PacketType;
  28. import org.alfresco.jlan.smb.SMBException;
  29. import org.alfresco.jlan.smb.SMBStatus;
  30. /**
  31. * SMB core disk session class
  32. *
  33. * @author gkspencer
  34. */
  35. public class CoreDiskSession extends DiskSession {
  36. // Core protocol packet lengths
  37. private static final int CORE_LEN_FILEOPEN = 256;
  38. /**
  39. * Class constructor
  40. *
  41. * @param shr Remote server details.
  42. * @param dialect SMB dialect that this session is using
  43. */
  44. protected CoreDiskSession(PCShare shr, int dialect) {
  45. super(shr, dialect);
  46. }
  47. /**
  48. * Close this connection with the remote server share.
  49. *
  50. * @exception java.io.IOException If an I/O error occurs.
  51. * @exception SMBException If an SMB level error occurs
  52. */
  53. public void CloseSession()
  54. throws java.io.IOException, SMBException {
  55. // Build a tree disconnect packet
  56. SMBPacket pkt = new SMBPacket();
  57. pkt.setCommand(PacketType.TreeDisconnect);
  58. pkt.setUserId(getUserId());
  59. pkt.setTreeId(m_treeid);
  60. m_pkt.setParameterCount(0);
  61. m_pkt.setByteCount(0);
  62. // Send the tree disconnect packet
  63. pkt.ExchangeSMB(this, pkt);
  64. // Indicate that the session has been closed
  65. this.m_treeid = DiskSession.Closed;
  66. // Close the network session
  67. super.CloseSession();
  68. }
  69. /**
  70. * Create a new directory on the remote file server.
  71. *
  72. * @param dir Directory name string. If the directory name does not have a leading '\' the
  73. * current working directory for this session will be prepended to the string.
  74. * @exception java.io.IOException If an I/O error occurs.
  75. * @exception SMBException If an SMB level error occurs
  76. */
  77. public final void CreateDirectory(String dir)
  78. throws java.io.IOException, SMBException {
  79. // Create an SMB create directory packet
  80. m_pkt.setCommand(PacketType.CreateDirectory);
  81. m_pkt.setUserId(this.getUserId());
  82. m_pkt.setTreeId(this.getTreeId());
  83. m_pkt.setParameterCount(0);
  84. // Check if the directory name contains a path
  85. StringBuffer pathbuf = new StringBuffer();
  86. pathbuf.append((char) DataType.ASCII);
  87. if ( dir.startsWith("\\")) {
  88. // Use the directory names as is
  89. pathbuf.append(dir);
  90. }
  91. else {
  92. // Add the current working directory to the directory
  93. pathbuf.append(PCShare.makePath(this.getWorkingDirectory(), dir));
  94. }
  95. pathbuf.append((char) 0x00);
  96. // Copy the directory name data block to the SMB packet
  97. m_pkt.setBytes(pathbuf.toString().getBytes());
  98. // Send/receive the SMB create directory packet
  99. m_pkt.ExchangeSMB(this, m_pkt, true);
  100. }
  101. /**
  102. * Create and open a file on the remote file server.
  103. *
  104. * @param fname Remote file name string.
  105. * @return SMBFile for the opened file, else null.
  106. * @exception java.io.IOException If an I/O error occurs
  107. * @exception SMBException If an SMB error occurs
  108. */
  109. public final SMBFile CreateFile(String fname)
  110. throws java.io.IOException, SMBException {
  111. // Create a new file
  112. return OpenFile(fname, AccessMode.WriteOnly);
  113. }
  114. /**
  115. * Delete the specified directory on the remote file server.
  116. *
  117. * @param dir Directory name string. If the directory name does not have a leading '\' the
  118. * current working directory for this session will be preprended to the string.
  119. * @exception java.io.IOException If an I/O error occurs.
  120. * @exception SMBException If an SMB level error occurs
  121. */
  122. public final void DeleteDirectory(String dir)
  123. throws java.io.IOException, SMBException {
  124. // Create an SMB delete directory packet
  125. m_pkt.setCommand(PacketType.DeleteDirectory);
  126. m_pkt.setUserId(this.getUserId());
  127. m_pkt.setTreeId(this.getTreeId());
  128. m_pkt.setParameterCount(0);
  129. // Check if the directory name contains a path
  130. StringBuffer pathbuf = new StringBuffer();
  131. pathbuf.append((char) DataType.ASCII);
  132. if ( dir.startsWith("\\")) {
  133. // Use the directory names as is
  134. pathbuf.append(dir);
  135. }
  136. else {
  137. // Add the current working directory to the directory
  138. pathbuf.append(PCShare.makePath(this.getWorkingDirectory(), dir));
  139. }
  140. pathbuf.append((char) 0x00);
  141. // Copy the directory name data block to the SMB packet
  142. m_pkt.setBytes(pathbuf.toString().getBytes());
  143. // Send/receive the SMB delete directory packet
  144. m_pkt.ExchangeSMB(this, m_pkt, true);
  145. }
  146. /**
  147. * Delete the specified file on the remote server.
  148. *
  149. * @param fname File to delete on the remote server.
  150. * @param attr Attributes of the file to be deleted. @see
  151. * org.alfresco.jlan.server.filesys.FileAttribute
  152. * @exception java.io.IOException If an I/O error occurs.
  153. * @exception SMBException If an SMB level error occurs
  154. */
  155. public final void DeleteFile(String fname, int attr)
  156. throws java.io.IOException, SMBException {
  157. }
  158. /**
  159. * Get disk information for this remote disk.
  160. *
  161. * @return Disk information object, or null.
  162. * @exception java.io.IOException If an I/O error occurs.
  163. * @exception SMBException If an SMB level error occurs
  164. */
  165. public final org.alfresco.jlan.client.info.DiskInfo getDiskInformation()
  166. throws java.io.IOException, SMBException {
  167. // Create a query disk information SMB packet
  168. m_pkt.setCommand(PacketType.DiskInformation);
  169. m_pkt.setUserId(this.getUserId());
  170. m_pkt.setTreeId(this.getTreeId());
  171. m_pkt.setParameterCount(0);
  172. m_pkt.setByteCount(0);
  173. // Send/receive the SMB file information packet
  174. m_pkt.ExchangeSMB(this, m_pkt);
  175. // Check if a valid response was received
  176. if ( m_pkt.isValidResponse()) {
  177. // Extract the disk information from the received SMB packet
  178. int totunit = m_pkt.getParameter(0);
  179. int blkperunit = m_pkt.getParameter(1);
  180. int blksize = m_pkt.getParameter(2);
  181. int freeblk = m_pkt.getParameter(3);
  182. // Create a disk information object
  183. return new DiskInfo(getPCShare(), totunit, blkperunit, blksize, freeblk);
  184. }
  185. // Invalid SMB response
  186. return null;
  187. }
  188. /**
  189. * Get file information for the specified file.
  190. *
  191. * @param fname File name of the file to return information for.
  192. * @param level Information level required. @see org.alfresco.jlan.smb.FileInfoLevel
  193. * @return FileInfo if the request was successful, else null.
  194. * @exception java.io.IOException If an I/O error occurs.
  195. * @exception SMBException If an SMB level error occurs
  196. */
  197. public final FileInfo getFileInformation(String fname, int level)
  198. throws java.io.IOException, SMBException {
  199. // Create a query information SMB packet
  200. m_pkt.setCommand(PacketType.GetFileAttributes);
  201. m_pkt.setUserId(this.getUserId());
  202. m_pkt.setTreeId(this.getTreeId());
  203. m_pkt.setParameterCount(0);
  204. // Build the remote files share relative path
  205. StringBuffer pathbuf = new StringBuffer();
  206. pathbuf.append((char) DataType.ASCII);
  207. if ( fname.startsWith("\\"))
  208. pathbuf.append(fname);
  209. else
  210. pathbuf.append(PCShare.makePath(this.getWorkingDirectory(), fname));
  211. pathbuf.append((char) 0x00);
  212. m_pkt.setBytes(pathbuf.toString().getBytes());
  213. // Send/receive the SMB file information packet
  214. m_pkt.ExchangeSMB(this, m_pkt);
  215. // Check if a valid response was received
  216. if ( m_pkt.isValidResponse()) {
  217. // Extract the file information from the received SMB packet
  218. int attr = m_pkt.getParameter(0);
  219. int ftim = (m_pkt.getParameter(2) << 16) + m_pkt.getParameter(1);
  220. int fsiz = (m_pkt.getParameter(4) << 16) + m_pkt.getParameter(3);
  221. // Create a file information object
  222. return new FileInfo(fname, fsiz, attr, ftim);
  223. }
  224. // Invalid SMB response
  225. return null;
  226. }
  227. /**
  228. * Get the disk volume information
  229. *
  230. * @return VolumeInfo, or null
  231. * @exception java.io.IOException If an I/O error occurs
  232. * @exception SMBException If an SMB level error occurs
  233. */
  234. public final VolumeInfo getVolumeInformation()
  235. throws java.io.IOException, SMBException {
  236. return null;
  237. }
  238. /**
  239. * Check if the specified file name is a directory.
  240. *
  241. * @param dir Directory name string. If the directory name does not have a leading '\' the
  242. * current working directory for this session will be preprended to the string.
  243. * @return true if the specified file name is a directory, else false.
  244. * @exception java.io.IOException If an I/O error occurs.
  245. * @exception SMBException If an SMB level error occurs
  246. */
  247. public final boolean isDirectory(String dir)
  248. throws java.io.IOException, SMBException {
  249. // Allocate an SMB packet for the check directory request
  250. SMBPacket pkt = new SMBPacket();
  251. pkt.setCommand(PacketType.CheckDirectory);
  252. pkt.setUserId(this.getUserId());
  253. pkt.setTreeId(this.getTreeId());
  254. pkt.setParameterCount(0);
  255. // Build the remote directory tree relative path
  256. StringBuffer pathbuf = new StringBuffer();
  257. pathbuf.append((char) DataType.ASCII);
  258. if ( dir.startsWith("\\"))
  259. pathbuf.append(dir);
  260. else
  261. pathbuf.append(PCShare.makePath(this.getWorkingDirectory(), dir));
  262. if ( pathbuf.charAt(pathbuf.length() - 1) != '\\')
  263. pathbuf.append("\\");
  264. pathbuf.append((char) 0x00);
  265. pkt.setBytes(pathbuf.toString().getBytes());
  266. // Send/receive the SMB check directory packet
  267. pkt.ExchangeSMB(this, pkt);
  268. // Check if a valid response was received
  269. if ( pkt.isValidResponse()) {
  270. // File name is a directory
  271. return true;
  272. }
  273. // Error response, file name is not a directory
  274. return false;
  275. }
  276. /**
  277. * Open a file on the remote file server.
  278. *
  279. * @param fname Remote file name string.
  280. * @param flags File open option flags.
  281. * @return SMBFile for the opened file, else null.
  282. * @exception java.io.IOException If an I/O error occurs
  283. * @exception SMBException If an SMB level error occurs
  284. */
  285. public final SMBFile OpenFile(String fname, int flags)
  286. throws java.io.IOException, SMBException {
  287. // Check if the path is a valid file path
  288. if ( isValidFilePath(fname) == false)
  289. throw new SMBException(SMBStatus.NTErr, SMBStatus.NTInvalidParameter);
  290. // Initialize the SMB requets to open an existing file
  291. m_pkt.setCommand(PacketType.OpenFile);
  292. m_pkt.setFlags(0);
  293. // Set the parameter words
  294. m_pkt.setParameterCount(2);
  295. m_pkt.setParameter(0, flags); // access mode
  296. m_pkt.setParameter(1, 0); // search attributes
  297. // Set the user id
  298. m_pkt.setUserId(this.getUserId());
  299. // Set the tree id
  300. m_pkt.setTreeId(this.getTreeId());
  301. // Build the password and share details
  302. StringBuffer pathbuf = new StringBuffer();
  303. pathbuf.append((char) DataType.ASCII);
  304. if ( fname.startsWith("\\"))
  305. pathbuf.append(fname);
  306. else
  307. pathbuf.append(PCShare.makePath(this.getWorkingDirectory(), fname));
  308. pathbuf.append((char) 0x00);
  309. m_pkt.setBytes(pathbuf.toString().getBytes());
  310. // Send/receive the SMB file open packet
  311. m_pkt.ExchangeSMB(this, m_pkt);
  312. // Check if a valid response was received
  313. if ( m_pkt.isValidResponse()) {
  314. // Extract the file information from the received SMB packet
  315. int fid = m_pkt.getParameter(0);
  316. int attr = m_pkt.getParameter(1);
  317. int fsiz = (m_pkt.getParameter(5) << 16) + m_pkt.getParameter(4);
  318. // Create a file information object
  319. FileInfo finfo = new FileInfo(fname, fsiz, attr);
  320. // Create an SMB file object
  321. return new CoreFile(this, finfo, fid);
  322. }
  323. // Check if the error indicates that the requested file does not exist, and
  324. // this is a open for write type request, if so then try and create a new file.
  325. /*
  326. * else if ( m_pkt.getErrorClass () == SMBStatus.ErrDos && m_pkt.getErrorCode () ==
  327. * SMBStatus.DOSFileNotFound && SMBAccessMode.AccessMode ( flags) ==
  328. * SMBAccessMode.WriteOnly) {
  329. */
  330. else if ( AccessMode.getAccessMode(flags) == AccessMode.WriteOnly) {
  331. // Initialize the SMB request to create a new file
  332. m_pkt.setCommand(PacketType.CreateNew);
  333. m_pkt.setFlags(0);
  334. // Set the parameter words
  335. m_pkt.setParameterCount(3);
  336. m_pkt.setParameter(0, flags);
  337. m_pkt.setParameter(1, 0); // time file was created
  338. m_pkt.setParameter(2, 0); // date file was created
  339. // Set the user id/tree id
  340. m_pkt.setUserId(this.getUserId());
  341. m_pkt.setTreeId(this.getTreeId());
  342. // Clear the error code/class
  343. m_pkt.setErrorClass(SMBStatus.Success);
  344. m_pkt.setErrorCode(0);
  345. // Set the remote path name in the create file packet
  346. m_pkt.setBytes(pathbuf.toString().getBytes());
  347. // Send/receive the SMB file create packet
  348. m_pkt.ExchangeSMB(this, m_pkt);
  349. // Check if a valid response was received
  350. if ( m_pkt.isValidResponse()) {
  351. // Extract the file information from the received SMB packet
  352. int fid = m_pkt.getParameter(0);
  353. // Create a file information object
  354. FileInfo finfo = new FileInfo(fname, 0, 0);
  355. // Create an SMB file object
  356. return new CoreFile(this, finfo, fid);
  357. }
  358. }
  359. // Invalid response/error occurred
  360. return null;
  361. }
  362. /**
  363. * Rename a file, or set of files, on the remote file server.
  364. *
  365. * @param curnam Current file name string, may contain wildcards. If the path does not start
  366. * with a '\' the current working directory string will be preprended.
  367. * @param newnam New file name.
  368. * @param attr Search attributes, to determine which file(s) to rename.
  369. * @see org.alfresco.jlan.server.filesys.FileAttribute
  370. * @return true if the file rename request was successful, else false.
  371. * @exception java.io.IOException If an I/O error occurs.
  372. * @exception SMBException If an SMB level error occurs
  373. */
  374. public final boolean RenameFile(String curnam, String newnam, int attr)
  375. throws java.io.IOException, SMBException {
  376. // Create an SMB rename packet
  377. m_pkt.setCommand(PacketType.RenameFile);
  378. m_pkt.setUserId(this.getUserId());
  379. m_pkt.setTreeId(this.getTreeId());
  380. m_pkt.setParameterCount(1);
  381. m_pkt.setParameter(0, attr);
  382. // Check if the input file name contains a path
  383. StringBuffer pathbuf = new StringBuffer();
  384. if ( curnam.startsWith("\\")) {
  385. // Use the input/output file names as is
  386. pathbuf.append((char) DataType.ASCII);
  387. pathbuf.append(curnam);
  388. pathbuf.append((char) 0x00);
  389. pathbuf.append((char) DataType.ASCII);
  390. pathbuf.append(newnam);
  391. pathbuf.append((char) 0x00);
  392. }
  393. else {
  394. // Add the current working directory to the input path
  395. pathbuf.append(PCShare.makePath(this.getWorkingDirectory(), curnam));
  396. pathbuf.append((char) 0x00);
  397. // Check if the output file name contains a path
  398. pathbuf.append((char) DataType.ASCII);
  399. if ( newnam.startsWith("\\"))
  400. pathbuf.append(newnam);
  401. else
  402. pathbuf.append(PCShare.makePath(this.getWorkingDirectory(), newnam));
  403. pathbuf.append((char) 0x00);
  404. }
  405. // Copy the input/output file name data block to the SMB packet
  406. m_pkt.setBytes(pathbuf.toString().getBytes());
  407. // Send/receive the SMB rename file(s) packet
  408. m_pkt.ExchangeSMB(this, m_pkt, true);
  409. // Check if we got a valid response
  410. if ( m_pkt.isValidResponse())
  411. return true;
  412. // Invalid rename request
  413. return false;
  414. }
  415. /**
  416. * Set file information for the specified file.
  417. *
  418. * @param fname File name of the file to set information for.
  419. * @param finfo File information containing the new values.
  420. * @exception java.io.IOException If an I/O error occurs.
  421. * @exception SMBException If an SMB level error occurs
  422. */
  423. public final void setFileInformation(String fname, FileInfo finfo)
  424. throws java.io.IOException, SMBException {
  425. }
  426. /**
  427. * Set file information for the specified file, using the file id
  428. *
  429. * @param file File to set information for.
  430. * @param finfo File information containing the new values.
  431. * @exception java.io.IOException If an I/O error occurs.
  432. * @exception SMBException If an SMB level error occurs
  433. */
  434. public final void setFileInformation(SMBFile file, FileInfo finfo)
  435. throws java.io.IOException, SMBException {
  436. }
  437. /**
  438. * Set file attributes for the specified file, using the file name
  439. *
  440. * @param fname File name of the file to set information for.
  441. * @param attrib File attributes mask. @see org.alfresco.jlan.server.filesys.FileAttribute
  442. * @exception java.io.IOException If an I/O error occurs.
  443. * @exception SMBException If an SMB level error occurs
  444. */
  445. public final void setFileAttributes(String fname, int attrib)
  446. throws java.io.IOException, SMBException {
  447. }
  448. /**
  449. * Start a search of the specified directory returning information for each file/directory
  450. * found.
  451. *
  452. * @param dir Directory to start searching. If the directory string does not start with a '\'
  453. * then the directory name is prepended with the current working directory.
  454. * @param attr Search attributes, to determine the types of files/directories returned. @see
  455. * org.alfresco.jlan.server.filesys.FileAttribute
  456. * @param level Information level required. @see org.alfresco.jlan.smb.FileInfoLevel
  457. * @return SMBSearchContext for this search, else null
  458. * @exception java.io.IOException If an I/O error occurs
  459. * @exception SMBException If an SMB level error occurs
  460. */
  461. public final SearchContext StartSearch(String dir, int attr, int level)
  462. throws java.io.IOException, SMBException {
  463. // Create a new SMB search context
  464. CoreSearchContext srch = new CoreSearchContext(this);
  465. if ( srch == null)
  466. return null;
  467. // Start the search and return the search context
  468. srch.StartSearch(dir, attr, level);
  469. return srch;
  470. }
  471. }