001: /*
002: * This program is free software; you can redistribute it and/or
003: * modify it under the terms of the GNU General Public License
004: * as published by the Free Software Foundation; either version 2
005: * of the License, or (at your option) any later version.
006: *
007: * This program is distributed in the hope that it will be useful,
008: * but WITHOUT ANY WARRANTY; without even the implied warranty of
009: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
010: * GNU General Public License for more details.
011: *
012: * You should have received a copy of the GNU General Public License
013: * along with this program; if not, write to the Free Software
014: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
015: */
016: package net.sf.jftp.net;
017:
018: import java.io.BufferedInputStream;
019: import java.io.BufferedOutputStream;
020: import java.io.File;
021: import java.io.FileInputStream;
022: import java.io.FileOutputStream;
023: import java.io.IOException;
024: import java.io.InputStream;
025: import java.io.StreamTokenizer;
026: import java.util.Date;
027: import java.util.Vector;
028:
029: import jcifs.smb.NtlmAuthenticator;
030: import jcifs.smb.NtlmPasswordAuthentication;
031: import jcifs.smb.SmbAuthException;
032: import jcifs.smb.SmbFile;
033: import jcifs.smb.SmbFileOutputStream;
034: import net.sf.jftp.config.Settings;
035: import net.sf.jftp.system.StringUtils;
036: import net.sf.jftp.system.logging.Log;
037:
038: public class SmbConnection extends NtlmAuthenticator implements
039: BasicConnection {
040: public static int smbBuffer = 128000;
041: private String path = "";
042: private String pwd = "smb://";
043: private Vector listeners = new Vector();
044: private String[] files;
045: private String[] size = new String[0];
046: private int[] perms = null;
047: private String user;
048: private String pass;
049: private String host;
050: private String domain = null;
051: private String baseFile;
052: private int fileCount;
053: private boolean isDirUpload = false;
054: private boolean shortProgress = false;
055: private boolean dummy = false;
056:
057: public SmbConnection() {
058: }
059:
060: public SmbConnection(String url, String domain, String user,
061: String pass, ConnectionListener l) {
062: if (l != null) {
063: listeners.add(l);
064: }
065:
066: this .user = user;
067: this .pass = pass;
068: //TODO set hostname from smb url
069: //this.host = host;
070:
071: //***
072: if (domain.equals("NONE")) {
073: domain = null;
074: }
075:
076: this .domain = domain;
077:
078: //if(url == null) chdir(getPWD());
079: if (url.equals("(LAN)")) {
080: chdir(getPWD());
081: } else {
082: chdir(url);
083: }
084:
085: //***
086: }
087:
088: protected NtlmPasswordAuthentication getNtlmPasswordAuthentication() {
089: //Log.debug("Auth: " + domain+ ";" + user + ":" + pass);
090: try {
091: return new NtlmPasswordAuthentication(domain, user, pass);
092: } catch (Exception ex) {
093: Log.debug("Error logging in: " + ex);
094: ex.printStackTrace();
095:
096: return null;
097: }
098: }
099:
100: private NtlmPasswordAuthentication getAuth() {
101: return getNtlmPasswordAuthentication();
102: }
103:
104: public int removeFileOrDir(String file) {
105: file = toSMB(file);
106:
107: //System.out.println(file);
108: try {
109: SmbFile f = new SmbFile(file, getAuth());
110:
111: if (f.exists() && f.isDirectory()) {
112: cleanSmbDir(file);
113: }
114:
115: f.delete();
116: } catch (Exception ex) {
117: Log.debug("Removal failed (" + ex + ").");
118:
119: return -1;
120: }
121:
122: return 1;
123: }
124:
125: private void cleanSmbDir(String dir) throws Exception {
126: dir = toSMB(dir);
127:
128: SmbFile f2 = new SmbFile(dir, getAuth());
129: String[] tmp = f2.list();
130:
131: if (tmp == null) {
132: return;
133: }
134:
135: for (int i = 0; i < tmp.length; i++) {
136: SmbFile f3 = new SmbFile(dir + tmp[i], getAuth());
137:
138: if (f3.isDirectory()) {
139: //System.out.println(dir);
140: cleanSmbDir(dir + tmp[i]);
141: f3.delete();
142: } else {
143: //System.out.println(dir+tmp[i]);
144: f3.delete();
145: }
146: }
147: }
148:
149: public void sendRawCommand(String cmd) {
150: }
151:
152: public void disconnect() {
153: }
154:
155: public boolean isConnected() {
156: return true;
157: }
158:
159: public String getPWD() {
160: //Log.debug("PWD: " + pwd);
161: return toSMB(pwd);
162: }
163:
164: public boolean cdup() {
165: String tmp = pwd;
166:
167: if (pwd.endsWith("/") && !pwd.equals("smb://")) {
168: tmp = pwd.substring(0, pwd.lastIndexOf("/"));
169: }
170:
171: return chdir(tmp.substring(0, tmp.lastIndexOf("/") + 1));
172: }
173:
174: public boolean mkdir(String dirName) {
175: try {
176: if (!dirName.endsWith("/")) {
177: dirName = dirName + "/";
178: }
179:
180: dirName = toSMB(dirName);
181:
182: SmbFile f = new SmbFile(dirName, getAuth());
183: f.mkdir();
184:
185: fireDirectoryUpdate();
186:
187: return true;
188: } catch (Exception ex) {
189: Log.debug("Failed to create directory (" + ex + ").");
190:
191: return false;
192: }
193: }
194:
195: public void list() throws IOException {
196: }
197:
198: public boolean chdir(String p) {
199: return chdir(p, true);
200: }
201:
202: public boolean chdir(String p, boolean refresh) {
203: try {
204: if (p.endsWith("..")) {
205: return cdup();
206: }
207:
208: String tmp = toSMB(p);
209:
210: if (!tmp.endsWith("/")) {
211: tmp = tmp + "/";
212: }
213:
214: //Log.debug("tmp: " + tmp);
215: SmbFile f = new SmbFile(tmp, getAuth());
216: f.list();
217:
218: pwd = tmp;
219:
220: //Log.debug("pwd: " + pwd);
221: //System.out.println("chdir: " + getPWD());
222: if (refresh) {
223: fireDirectoryUpdate();
224: }
225:
226: //System.out.println("chdir2: " + getPWD());
227: dummy = false;
228:
229: return true;
230: } catch (Exception ex) {
231: if ((ex.getMessage().indexOf("MSBROWSE") > 0) && !dummy) {
232: Log.debug("\nCould not find a master server.");
233: Log
234: .debug("Please make sure you have the local IP set to the interface you want to use, and if");
235: Log.debug("that does not work try \"<default>\"...");
236: Log
237: .debug("If you still can not find a master make sure that there is one your LAN and submit a bug report.");
238: dummy = true;
239: } else {
240: Log.debug("Could not change directory (" + ex + ").");
241: }
242:
243: return false;
244: }
245: }
246:
247: public boolean chdirNoRefresh(String p) {
248: return chdir(p, false);
249: }
250:
251: public String getLocalPath() {
252: return path;
253: }
254:
255: public boolean setLocalPath(String p) {
256: if (StringUtils.isRelative(p)) {
257: p = path + p;
258: }
259:
260: p = p.replace('\\', '/');
261:
262: //System.out.println(", local 2:" + p);
263: File f = new File(p);
264:
265: if (f.exists()) {
266: try {
267: path = f.getCanonicalPath();
268: path = path.replace('\\', '/');
269:
270: if (!path.endsWith("/")) {
271: path = path + "/";
272: }
273:
274: //System.out.println("localPath: "+path);
275: } catch (IOException ex) {
276: Log.debug("Error: can not get pathname (local)!");
277:
278: return false;
279: }
280: } else {
281: Log.debug("(local) No such path: \"" + p + "\"");
282:
283: return false;
284: }
285:
286: return true;
287: }
288:
289: public String[] sortLs() {
290: try {
291: //Log.debug("sortLs: trying");
292: chdirNoRefresh(getPWD());
293:
294: SmbFile fx = new SmbFile(pwd, getAuth());
295:
296: //System.out.println(pwd);
297: //if(fx == null) System.out.println("Smb: fx null");
298: SmbFile[] f = fx.listFiles();
299:
300: //Log.debug("sortLs: file is there and listed");
301: //if(f == null) System.out.println("Smb: f null");
302: files = new String[f.length];
303: size = new String[f.length];
304: perms = new int[f.length];
305:
306: int i;
307:
308: for (i = 0; i < f.length; i++) {
309: files[i] = f[i].toURL().toString();
310:
311: int x = 0;
312:
313: for (int j = 0; j < files[i].length(); j++) {
314: if (files[i].charAt(j) == '/') {
315: x++;
316: }
317: }
318:
319: if (files[i].endsWith("/") && (x > 3)) {
320: files[i] = StringUtils.getDir(files[i]);
321: } else if (x > 3) {
322: files[i] = StringUtils.getFile(files[i]);
323: }
324:
325: size[i] = "" + f[i].length();
326:
327: if (f[i].canRead()) {
328: perms[i] = FtpConnection.R;
329: } else if (f[i].canWrite()) {
330: perms[i] = FtpConnection.R;
331: } else {
332: perms[i] = FtpConnection.DENIED;
333: }
334: }
335:
336: //Log.debug("sortLs: finished, ok");
337: return files;
338: } catch (Exception ex) {
339: if (ex instanceof SmbAuthException) {
340: Log.debug("Access denied: " + ex);
341:
342: //Log.debug("URL: " + getPWD());
343: //Log.debug("Auth (bin): " + getAuth().toString());
344: //Log.debug("Auth: " + domain+ ";" + user + ":" + pass);
345: } else {
346: Log.debug("Error: " + ex);
347: }
348:
349: return new String[0];
350: }
351: }
352:
353: public String[] sortSize() {
354: return size;
355: }
356:
357: public int[] getPermissions() {
358: return perms;
359: }
360:
361: public int handleUpload(String f) {
362: if (Settings.getEnableSmbMultiThreading()) {
363: SmbTransfer t = new SmbTransfer(getPWD(), getLocalPath(),
364: f, user, pass, domain, listeners, Transfer.UPLOAD);
365: } else {
366: upload(f);
367: }
368:
369: return 0;
370: }
371:
372: public int handleDownload(String f) {
373: if (Settings.getEnableSmbMultiThreading()) {
374: SmbTransfer t = new SmbTransfer(getPWD(), getLocalPath(),
375: f, user, pass, domain, listeners, Transfer.DOWNLOAD);
376: } else {
377: download(f);
378: }
379:
380: return 0;
381: }
382:
383: public int upload(String f) {
384: String file = toSMB(f);
385:
386: if (file.endsWith("/")) {
387: String out = StringUtils.getDir(file);
388: uploadDir(file, getLocalPath() + out);
389: fireActionFinished(this );
390: } else {
391: String outfile = StringUtils.getFile(file);
392:
393: //System.out.println("transfer: " + file + ", " + getLocalPath() + outfile);
394: work(getLocalPath() + outfile, file);
395: fireActionFinished(this );
396: }
397:
398: return 0;
399: }
400:
401: public int download(String f) {
402: String file = toSMB(f);
403:
404: if (file.endsWith("/")) {
405: String out = StringUtils.getDir(file);
406: downloadDir(file, getLocalPath() + out);
407: fireActionFinished(this );
408: } else {
409: String outfile = StringUtils.getFile(file);
410:
411: //System.out.println("transfer: " + file + ", " + getLocalPath() + outfile);
412: work(file, getLocalPath() + outfile);
413: fireActionFinished(this );
414: }
415:
416: return 0;
417: }
418:
419: private void downloadDir(String dir, String out) {
420: try {
421: //System.out.println("downloadDir: " + dir + "," + out);
422: fileCount = 0;
423: shortProgress = true;
424: baseFile = StringUtils.getDir(dir);
425:
426: SmbFile f2 = new SmbFile(dir, getAuth());
427: String[] tmp = f2.list();
428:
429: if (tmp == null) {
430: return;
431: }
432:
433: File fx = new File(out);
434: fx.mkdir();
435:
436: for (int i = 0; i < tmp.length; i++) {
437: tmp[i] = tmp[i].replace('\\', '/');
438:
439: //System.out.println("1: " + dir+tmp[i] + ", " + out +tmp[i]);
440: SmbFile f3 = new SmbFile(dir + tmp[i], getAuth());
441:
442: if (f3.isDirectory()) {
443: if (!tmp[i].endsWith("/")) {
444: tmp[i] = tmp[i] + "/";
445: }
446:
447: downloadDir(dir + tmp[i], out + tmp[i]);
448: } else {
449: fileCount++;
450: fireProgressUpdate(baseFile, DataConnection.GETDIR
451: + ":" + fileCount, -1);
452: work(dir + tmp[i], out + tmp[i]);
453: }
454: }
455:
456: fireProgressUpdate(baseFile, DataConnection.DFINISHED + ":"
457: + fileCount, -1);
458: } catch (Exception ex) {
459: ex.printStackTrace();
460:
461: //System.out.println(dir + ", " + out);
462: Log.debug("Transfer error: " + ex);
463: fireProgressUpdate(baseFile, DataConnection.FAILED + ":"
464: + fileCount, -1);
465: }
466:
467: shortProgress = false;
468: }
469:
470: private void uploadDir(String dir, String out) {
471: try {
472: //System.out.println("uploadDir: " + dir + "," + out);
473: isDirUpload = true;
474: fileCount = 0;
475: shortProgress = true;
476: baseFile = StringUtils.getDir(dir);
477:
478: File f2 = new File(out);
479: String[] tmp = f2.list();
480:
481: if (tmp == null) {
482: return;
483: }
484:
485: SmbFile fx = new SmbFile(dir, getAuth());
486: fx.mkdir();
487:
488: for (int i = 0; i < tmp.length; i++) {
489: tmp[i] = tmp[i].replace('\\', '/');
490:
491: //System.out.println("1: " + dir+tmp[i] + ", " + out +tmp[i]);
492: File f3 = new File(out + tmp[i]);
493:
494: if (f3.isDirectory()) {
495: if (!tmp[i].endsWith("/")) {
496: tmp[i] = tmp[i] + "/";
497: }
498:
499: uploadDir(dir + tmp[i], out + tmp[i]);
500: } else {
501: fileCount++;
502: fireProgressUpdate(baseFile, DataConnection.PUTDIR
503: + ":" + fileCount, -1);
504: work(out + tmp[i], dir + tmp[i]);
505: }
506: }
507:
508: fireProgressUpdate(baseFile, DataConnection.DFINISHED + ":"
509: + fileCount, -1);
510: } catch (Exception ex) {
511: ex.printStackTrace();
512:
513: //System.out.println(dir + ", " + out);
514: Log.debug("Transfer error: " + ex);
515: fireProgressUpdate(baseFile, DataConnection.FAILED + ":"
516: + fileCount, -1);
517: }
518:
519: isDirUpload = false;
520: shortProgress = true;
521: }
522:
523: private String toSMB(String f) {
524: String file;
525:
526: if (f.lastIndexOf("smb://") > 0) {
527: f = f.substring(f.lastIndexOf("smb://"));
528: }
529:
530: if (f.startsWith("smb://")) {
531: file = f;
532: } else {
533: file = getPWD() + f;
534: }
535:
536: file = file.replace('\\', '/');
537:
538: //System.out.println("file: "+file);
539: return file;
540: }
541:
542: private void work(String file, String outfile) {
543: BufferedOutputStream out = null;
544: BufferedInputStream in = null;
545:
546: try {
547: boolean outflag = false;
548:
549: if (outfile.startsWith("smb://")) {
550: outflag = true;
551: out = new BufferedOutputStream(new SmbFileOutputStream(
552: new SmbFile(outfile, getAuth())));
553: } else {
554: out = new BufferedOutputStream(new FileOutputStream(
555: outfile));
556: }
557:
558: //System.out.println("out: " + outfile + ", in: " + file);
559: if (file.startsWith("smb://")) {
560: in = new BufferedInputStream(new SmbFile(file,
561: getAuth()).getInputStream());
562: } else {
563: in = new BufferedInputStream(new FileInputStream(file));
564: }
565:
566: byte[] buf = new byte[smbBuffer];
567: int len = 0;
568: int reallen = 0;
569:
570: //System.out.println(file+":"+getLocalPath()+outfile);
571: while (true) {
572: len = in.read(buf);
573:
574: //System.out.print(".");
575: if (len == StreamTokenizer.TT_EOF) {
576: break;
577: }
578:
579: out.write(buf, 0, len);
580: reallen += len;
581:
582: //System.out.println(file + ":" + StringUtils.getFile(file));
583: if (outflag) {
584: fireProgressUpdate(StringUtils.getFile(outfile),
585: DataConnection.PUT, reallen);
586: } else {
587: fireProgressUpdate(StringUtils.getFile(file),
588: DataConnection.GET, reallen);
589: }
590: }
591:
592: fireProgressUpdate(file, DataConnection.FINISHED, -1);
593: } catch (IOException ex) {
594: Log.debug("Error with file IO (" + ex + ")!");
595: fireProgressUpdate(file, DataConnection.FAILED, -1);
596: } finally {
597: try {
598: out.flush();
599: out.close();
600: in.close();
601: } catch (Exception ex) {
602: ex.printStackTrace();
603: }
604: }
605: }
606:
607: private void update(String file, String type, int bytes) {
608: if (listeners == null) {
609: return;
610: } else {
611: for (int i = 0; i < listeners.size(); i++) {
612: ConnectionListener listener = (ConnectionListener) listeners
613: .elementAt(i);
614: listener.updateProgress(file, type, bytes);
615: }
616: }
617: }
618:
619: public void addConnectionListener(ConnectionListener l) {
620: listeners.add(l);
621: }
622:
623: public void setConnectionListeners(Vector l) {
624: listeners = l;
625: }
626:
627: /** remote directory has changed */
628: public void fireDirectoryUpdate() {
629: if (listeners == null) {
630: return;
631: } else {
632: for (int i = 0; i < listeners.size(); i++) {
633: ((ConnectionListener) listeners.elementAt(i))
634: .updateRemoteDirectory(this );
635: }
636: }
637: }
638:
639: public boolean login(String user, String pass) {
640: return true;
641: }
642:
643: /** progress update */
644: public void fireProgressUpdate(String file, String type, int bytes) {
645: //System.out.println(listener);
646: if (listeners == null) {
647: return;
648: } else {
649: for (int i = 0; i < listeners.size(); i++) {
650: ConnectionListener listener = (ConnectionListener) listeners
651: .elementAt(i);
652:
653: if (shortProgress && Settings.shortProgress) {
654: if (type.startsWith(DataConnection.DFINISHED)) {
655: listener.updateProgress(baseFile,
656: DataConnection.DFINISHED + ":"
657: + fileCount, bytes);
658: } else if (isDirUpload) {
659: listener
660: .updateProgress(baseFile,
661: DataConnection.PUTDIR + ":"
662: + fileCount, bytes);
663: } else {
664: listener
665: .updateProgress(baseFile,
666: DataConnection.GETDIR + ":"
667: + fileCount, bytes);
668: }
669: } else {
670: listener.updateProgress(file, type, bytes);
671: }
672: }
673: }
674: }
675:
676: public void fireActionFinished(SmbConnection con) {
677: if (listeners == null) {
678: return;
679: } else {
680: for (int i = 0; i < listeners.size(); i++) {
681: ((ConnectionListener) listeners.elementAt(i))
682: .actionFinished(con);
683: }
684: }
685: }
686:
687: public int upload(String file, InputStream i) {
688: BufferedOutputStream out = null;
689: BufferedInputStream in = null;
690:
691: try {
692: file = toSMB(file);
693:
694: out = new BufferedOutputStream(new SmbFileOutputStream(
695: new SmbFile(file, getAuth())));
696: in = new BufferedInputStream(i);
697:
698: byte[] buf = new byte[smbBuffer];
699: int len = 0;
700: int reallen = 0;
701:
702: while (true) {
703: len = in.read(buf);
704:
705: if (len == StreamTokenizer.TT_EOF) {
706: break;
707: }
708:
709: out.write(buf, 0, len);
710: reallen += len;
711:
712: fireProgressUpdate(StringUtils.getFile(file),
713: DataConnection.PUT, reallen);
714: }
715:
716: fireProgressUpdate(file, DataConnection.FINISHED, -1);
717:
718: return 0;
719: } catch (IOException ex) {
720: ex.printStackTrace();
721: Log.debug("Error with file IO (" + ex + ")!");
722: fireProgressUpdate(file, DataConnection.FAILED, -1);
723: } finally {
724: try {
725: out.flush();
726: out.close();
727: in.close();
728: } catch (Exception ex) {
729: ex.printStackTrace();
730: }
731: }
732:
733: return -1;
734: }
735:
736: public InputStream getDownloadInputStream(String file) {
737: file = toSMB(file);
738:
739: try {
740: return new BufferedInputStream(new SmbFile(file, getAuth())
741: .getInputStream());
742: } catch (Exception ex) {
743: ex.printStackTrace();
744: Log.debug(ex.toString()
745: + " @SmbConnection::getDownloadInputStream");
746:
747: return null;
748: }
749: }
750:
751: public Date[] sortDates() {
752: return null;
753: }
754:
755: public boolean rename(String file, String to) {
756: try {
757: file = toSMB(file);
758: to = toSMB(to);
759:
760: SmbFile src = new SmbFile(file, getAuth());
761:
762: src.renameTo(new SmbFile(to, getAuth()));
763:
764: return true;
765: } catch (Exception ex) {
766: ex.printStackTrace();
767: Log.debug(ex.toString() + " @SmbConnection::rename");
768:
769: return false;
770: }
771: }
772: }
|