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 net.sf.jftp.config.Settings;
030: import net.sf.jftp.system.StringUtils;
031: import net.sf.jftp.system.logging.Log;
032:
033: public class FilesystemConnection implements BasicConnection {
034: public static int filesystemBuffer = 128000;
035: private String path = "";
036: private String pwd = "";
037: private Vector listeners = new Vector();
038: private String[] files;
039: private String[] size = new String[0];
040: private int[] perms = null;
041: private String baseFile;
042: private int fileCount;
043: private boolean shortProgress = false;
044: public Vector dateVector = new Vector();
045:
046: public FilesystemConnection() {
047: }
048:
049: public FilesystemConnection(String path, ConnectionListener l) {
050: listeners.add(l);
051: chdir(path);
052: }
053:
054: public int removeFileOrDir(String file) {
055: try {
056: if ((file == null) || file.equals("")) {
057: return -1;
058: }
059:
060: String tmp = file;
061:
062: if (StringUtils.isRelative(file)) {
063: tmp = getPWD() + file;
064: }
065:
066: File f = new File(tmp);
067:
068: if (!f.getAbsolutePath().equals(f.getCanonicalPath())) {
069: //Log.debug("WARNING: Symlink removed");//Skipping symlink, remove failed.");
070: //Log.debug("This is necessary to prevent possible data loss when removing those symlinks.");
071: //return -1;
072: if (!f.delete()) {
073: return -1;
074: }
075: }
076:
077: if (f.exists() && f.isDirectory()) {
078: cleanLocalDir(tmp);
079: }
080:
081: //System.out.println(tmp);
082: if (!f.delete()) {
083: Log.debug("Removal failed.");
084:
085: return -1;
086: }
087: } catch (IOException ex) {
088: Log.debug("Error: " + ex.toString());
089: ex.printStackTrace();
090: }
091:
092: return -1;
093: }
094:
095: private void cleanLocalDir(String dir) {
096: try {
097: dir = dir.replace('\\', '/');
098:
099: if (!dir.endsWith("/")) {
100: dir = dir + "/";
101: }
102:
103: //String remoteDir = StringUtils.removeStart(dir,path);
104: //System.out.println(">>> " + dir);
105: File f2 = new File(dir);
106: String[] tmp = f2.list();
107:
108: if (tmp == null) {
109: return;
110: }
111:
112: for (int i = 0; i < tmp.length; i++) {
113: File f3 = new File(dir + tmp[i]);
114:
115: if (!f3.getAbsolutePath().equals(f3.getCanonicalPath())) {
116: //Log.debug("WARNING: Symlink remove");//Skipping symlink, remove may fail.");
117: f3.delete();
118:
119: //Log.debug("This is necessary to prevent possible data loss when removing those symlinks.");
120: //continue;
121: }
122:
123: if (f3.isDirectory()) {
124: //System.out.println(dir);
125: cleanLocalDir(dir + tmp[i]);
126: f3.delete();
127: } else {
128: //System.out.println(dir+tmp[i]);
129: f3.delete();
130: }
131: }
132: } catch (IOException ex) {
133: Log.debug("Error: " + ex.toString());
134: ex.printStackTrace();
135: }
136: }
137:
138: public void sendRawCommand(String cmd) {
139: }
140:
141: public void disconnect() {
142: }
143:
144: public boolean isConnected() {
145: return true;
146: }
147:
148: public String getPWD() {
149: return pwd;
150: }
151:
152: public boolean cdup() {
153: return chdir(pwd.substring(0, pwd.lastIndexOf("/") + 1));
154: }
155:
156: public boolean mkdir(String dirName) {
157: if (StringUtils.isRelative(dirName)) {
158: dirName = getPWD() + dirName;
159: }
160:
161: File f = new File(dirName);
162:
163: boolean x = f.mkdir();
164: fireDirectoryUpdate();
165:
166: return x;
167: }
168:
169: public void list() throws IOException {
170: }
171:
172: public boolean chdir(String p) {
173: String p2 = processPath(p);
174:
175: if (p2 == null) {
176: return false;
177: }
178:
179: File f = new File(p2);
180:
181: if (!f.exists() || !f.isDirectory() || !f.canRead()) {
182: Log.debug("Access denied.");
183:
184: return false;
185: }
186:
187: pwd = p2;
188:
189: fireDirectoryUpdate();
190:
191: return true;
192: }
193:
194: public boolean chdirNoRefresh(String p) {
195: String p2 = processPath(p);
196:
197: if (p2 == null) {
198: return false;
199: }
200:
201: //System.out.println(p2);
202: pwd = p2;
203:
204: return true;
205: }
206:
207: public String getLocalPath() {
208: //System.out.println("local: " + path);
209: return path;
210: }
211:
212: public String processPath(String p) {
213: p = p.replace('\\', '/');
214:
215: //System.out.print("processPath 1: "+p);
216: if (StringUtils.isRelative(p)) {
217: p = pwd + p;
218: }
219:
220: p = p.replace('\\', '/');
221:
222: //System.out.println(", processPath 2: "+p);
223: File f = new File(p);
224: String p2;
225:
226: if (f.exists()) {
227: try {
228: p2 = f.getCanonicalPath();
229: p2 = p2.replace('\\', '/');
230:
231: if (!p2.endsWith("/")) {
232: p2 = p2 + "/";
233: }
234:
235: return p2;
236: } catch (IOException ex) {
237: Log.debug("Error: can not get pathname (processPath)!");
238:
239: return null;
240: }
241: } else {
242: Log.debug("(processpPath) No such path: \"" + p + "\"");
243:
244: return null;
245: }
246: }
247:
248: public boolean setLocalPath(String p) {
249: p = p.replace('\\', '/');
250:
251: //System.out.print("local 1:" + p);
252: if (StringUtils.isRelative(p)) {
253: p = path + p;
254: }
255:
256: p = p.replace('\\', '/');
257:
258: //System.out.println(", local 2:" + p);
259: File f = new File(p);
260:
261: if (f.exists()) {
262: try {
263: path = f.getCanonicalPath();
264: path = path.replace('\\', '/');
265:
266: if (!path.endsWith("/")) {
267: path = path + "/";
268: }
269:
270: //System.out.println("localPath: "+path);
271: } catch (IOException ex) {
272: Log.debug("Error: can not get pathname (local)!");
273:
274: return false;
275: }
276: } else {
277: Log.out("(local) obsolete setLocalDir: \"" + p + "\"");
278:
279: return false;
280: }
281:
282: return true;
283: }
284:
285: public String[] sortLs() {
286: dateVector = new Vector();
287:
288: File f = new File(pwd);
289: files = f.list();
290:
291: if (files == null) {
292: return new String[0];
293: }
294:
295: size = new String[files.length];
296: perms = new int[files.length];
297:
298: int accessible = 0;
299:
300: for (int i = 0; i < files.length; i++) {
301: File f2 = new File(pwd + files[i]);
302:
303: if (f2.isDirectory() && !files[i].endsWith("/")) {
304: files[i] = files[i] + "/";
305: }
306:
307: size[i] = "" + new File(pwd + files[i]).length();
308:
309: if (f2.canWrite()) {
310: accessible = FtpConnection.W;
311: } else if (f2.canRead()) {
312: accessible = FtpConnection.R;
313: } else {
314: accessible = FtpConnection.DENIED;
315: }
316:
317: perms[i] = accessible;
318:
319: //System.out.println(pwd+files[i] +" : " +accessible + " : " + size[i]);
320: Date d = new Date(f2.lastModified());
321:
322: //System.out.println(d.toString());
323: dateVector.add(d);
324: }
325:
326: return files;
327: }
328:
329: public String[] sortSize() {
330: return size;
331: }
332:
333: public int[] getPermissions() {
334: return perms;
335: }
336:
337: public int handleDownload(String file) {
338: transfer(file);
339:
340: return 0;
341: }
342:
343: public int handleUpload(String file) {
344: transfer(file);
345:
346: return 0;
347: }
348:
349: public int download(String file) {
350: transfer(file);
351:
352: return 0;
353: }
354:
355: public int upload(String file) {
356: transfer(file);
357:
358: return 0;
359: }
360:
361: private void transferDir(String dir, String out) {
362: fileCount = 0;
363: shortProgress = true;
364: baseFile = StringUtils.getDir(dir);
365:
366: File f2 = new File(dir);
367: String[] tmp = f2.list();
368:
369: if (tmp == null) {
370: return;
371: }
372:
373: File fx = new File(out);
374:
375: if (!fx.mkdir()) {
376: Log.debug("Can not create directory: " + out
377: + " - already exist or permission denied?");
378: }
379:
380: for (int i = 0; i < tmp.length; i++) {
381: tmp[i] = tmp[i].replace('\\', '/');
382:
383: //System.out.println("1: " + dir+tmp[i] + ", " + out +tmp[i]);
384: File f3 = new File(dir + tmp[i]);
385:
386: if (f3.isDirectory()) {
387: if (!tmp[i].endsWith("/")) {
388: tmp[i] = tmp[i] + "/";
389: }
390:
391: transferDir(dir + tmp[i], out + tmp[i]);
392: } else {
393: fireProgressUpdate(baseFile, DataConnection.GETDIR
394: + ":" + fileCount, -1);
395: work(dir + tmp[i], out + tmp[i]);
396: }
397: }
398:
399: fireProgressUpdate(baseFile, DataConnection.DFINISHED + ":"
400: + fileCount, -1);
401: shortProgress = false;
402: }
403:
404: private void transfer(String file) {
405: String out = StringUtils.getDir(file);
406:
407: if (StringUtils.isRelative(file)) {
408: file = getPWD() + file;
409: }
410:
411: file = file.replace('\\', '/');
412: out = out.replace('\\', '/');
413:
414: String outfile = StringUtils.getFile(file);
415:
416: if (file.endsWith("/")) {
417: transferDir(file, getLocalPath() + out);
418:
419: return;
420: } else {
421: work(file, getLocalPath() + outfile);
422: }
423: }
424:
425: private void work(String file, String outfile) {
426: try {
427: BufferedOutputStream out = new BufferedOutputStream(
428: new FileOutputStream(outfile));
429: BufferedInputStream in = new BufferedInputStream(
430: new FileInputStream(file));
431: byte[] buf = new byte[filesystemBuffer];
432: int len = 0;
433: int reallen = 0;
434:
435: //System.out.println(file+":"+getLocalPath()+outfile);
436: while (true) {
437: len = in.read(buf);
438:
439: //System.out.print(".");
440: if (len == StreamTokenizer.TT_EOF) {
441: break;
442: }
443:
444: out.write(buf, 0, len);
445:
446: reallen += len;
447: fireProgressUpdate(StringUtils.getFile(file),
448: DataConnection.GET, reallen);
449: }
450:
451: out.flush();
452: out.close();
453: in.close();
454: fireProgressUpdate(file, DataConnection.FINISHED, -1);
455: } catch (IOException ex) {
456: Log.debug("Error with file IO (" + ex + ")!");
457: fireProgressUpdate(file, DataConnection.FAILED, -1);
458: }
459: }
460:
461: public int upload(String file, InputStream in) {
462: if (StringUtils.isRelative(file)) {
463: file = getPWD() + file;
464: }
465:
466: file = file.replace('\\', '/');
467:
468: try {
469: work(new BufferedInputStream(in), file, file);
470:
471: return 0;
472: } catch (Exception ex) {
473: Log.debug("Error: " + ex.toString());
474: ex.printStackTrace();
475:
476: return -1;
477: }
478: }
479:
480: private void work(BufferedInputStream in, String outfile,
481: String file) {
482: try {
483: BufferedOutputStream out = new BufferedOutputStream(
484: new FileOutputStream(outfile));
485: byte[] buf = new byte[filesystemBuffer];
486: int len = 0;
487: int reallen = 0;
488:
489: while (true) {
490: len = in.read(buf);
491: System.out.print(".");
492:
493: if (len == StreamTokenizer.TT_EOF) {
494: break;
495: }
496:
497: out.write(buf, 0, len);
498:
499: reallen += len;
500: fireProgressUpdate(StringUtils.getFile(file),
501: DataConnection.GET, reallen);
502: }
503:
504: out.flush();
505: out.close();
506: in.close();
507: fireProgressUpdate(file, DataConnection.FINISHED, -1);
508: } catch (IOException ex) {
509: Log.debug("Error with file IO (" + ex + ")!");
510: fireProgressUpdate(file, DataConnection.FAILED, -1);
511: }
512: }
513:
514: public InputStream getDownloadInputStream(String file) {
515: if (StringUtils.isRelative(file)) {
516: file = getPWD() + file;
517: }
518:
519: file = file.replace('\\', '/');
520:
521: try {
522: return new FileInputStream(file);
523: } catch (Exception ex) {
524: ex.printStackTrace();
525: Log.debug(ex.toString()
526: + " @Filesystemconnection::getDownloadInputStream");
527:
528: return null;
529: }
530: }
531:
532: public void addConnectionListener(ConnectionListener l) {
533: listeners.add(l);
534: fireDirectoryUpdate();
535: }
536:
537: public void setConnectionListeners(Vector l) {
538: listeners = l;
539: fireDirectoryUpdate();
540: }
541:
542: /** remote directory has changed */
543: public void fireDirectoryUpdate() {
544: if (listeners == null) {
545: return;
546: } else {
547: for (int i = 0; i < listeners.size(); i++) {
548: ((ConnectionListener) listeners.elementAt(i))
549: .updateRemoteDirectory(this );
550: }
551: }
552: }
553:
554: public boolean login(String user, String pass) {
555: return true;
556: }
557:
558: public void fireProgressUpdate(String file, String type, int bytes) {
559: if (listeners == null) {
560: return;
561: } else {
562: for (int i = 0; i < listeners.size(); i++) {
563: ConnectionListener listener = (ConnectionListener) listeners
564: .elementAt(i);
565:
566: if (shortProgress && Settings.shortProgress) {
567: if (type.startsWith(DataConnection.DFINISHED)) {
568: listener.updateProgress(baseFile,
569: DataConnection.DFINISHED + ":"
570: + fileCount, bytes);
571: }
572:
573: listener.updateProgress(baseFile,
574: DataConnection.GETDIR + ":" + fileCount,
575: bytes);
576: } else {
577: listener.updateProgress(file, type, bytes);
578: }
579: }
580: }
581: }
582:
583: public Date[] sortDates() {
584: if (dateVector.size() > 0) {
585: return (Date[]) dateVector.toArray();
586: } else {
587: return null;
588: }
589: }
590:
591: public boolean rename(String file, String to) {
592: if (StringUtils.isRelative(file)) {
593: file = getPWD() + file;
594: }
595:
596: file = file.replace('\\', '/');
597:
598: File f = new File(file);
599:
600: if (StringUtils.isRelative(to)) {
601: to = getPWD() + to;
602: }
603:
604: to = to.replace('\\', '/');
605:
606: return f.renameTo(new File(to));
607: }
608: }
|