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.FileOutputStream;
022: import java.io.IOException;
023: import java.io.InputStream;
024: import java.io.StreamTokenizer;
025: import java.util.Date;
026: import java.util.Vector;
027:
028: import net.sf.jftp.config.Settings;
029: import net.sf.jftp.system.StringUtils;
030: import net.sf.jftp.system.logging.Log;
031:
032: import org.apache.commons.httpclient.HttpException;
033: import org.apache.commons.httpclient.HttpURL;
034: import org.apache.webdav.lib.WebdavFile;
035: import org.apache.webdav.lib.WebdavResource;
036:
037: public class WebdavConnection implements BasicConnection {
038: public static int webdavBuffer = 32000;
039: private String path = "";
040: private String pwd = "";
041: private Vector listeners = new Vector();
042: private String[] files;
043: private String[] size = new String[0];
044: private int[] perms = null;
045: private String baseFile;
046: private int fileCount;
047: private boolean shortProgress = false;
048: private String user;
049: private String pass;
050:
051: public WebdavConnection(String path, String user, String pass,
052: ConnectionListener l) {
053: this .user = user;
054: this .pass = pass;
055:
056: listeners.add(l);
057: chdir(path);
058: }
059:
060: public int removeFileOrDir(String file) {
061: Log.debug("Feature is not implemented yet");
062:
063: if (true) {
064: return -1;
065: }
066:
067: try {
068: if ((file == null) || file.equals("")) {
069: return -1;
070: }
071:
072: String tmp = file;
073:
074: if (StringUtils.isRelative(file)) {
075: tmp = getPWD() + file;
076: }
077:
078: WebdavFile f = new WebdavFile(getURL(tmp));
079:
080: if (!f.getAbsolutePath().equals(f.getCanonicalPath())) {
081: //Log.debug("WARNING: Symlink removed");//Skipping symlink, remove failed.");
082: //Log.debug("This is necessary to prevent possible data loss when removing those symlinks.");
083: //return -1;
084: if (!f.delete()) {
085: return -1;
086: }
087: }
088:
089: if (f.exists() && f.isDirectory()) {
090: cleanLocalDir(tmp);
091: }
092:
093: //System.out.println(tmp);
094: if (!f.delete()) {
095: Log.debug("Removal failed.");
096:
097: return -1;
098: }
099: } catch (Exception ex) {
100: Log.debug("Error: " + ex.toString());
101: ex.printStackTrace();
102: }
103:
104: return -1;
105: }
106:
107: private void cleanLocalDir(String dir) {
108: try {
109: dir = dir.replace('\\', '/');
110:
111: if (!dir.endsWith("/")) {
112: dir = dir + "/";
113: }
114:
115: //String remoteDir = StringUtils.removeStart(dir,path);
116: //System.out.println(">>> " + dir);
117: WebdavFile f2 = new WebdavFile(getURL(dir));
118: String[] tmp = f2.list();
119:
120: if (tmp == null) {
121: return;
122: }
123:
124: for (int i = 0; i < tmp.length; i++) {
125: WebdavFile f3 = new WebdavFile(getURL(dir + tmp[i]));
126:
127: if (!f3.getAbsolutePath().equals(f3.getCanonicalPath())) {
128: //Log.debug("WARNING: Symlink remove");//Skipping symlink, remove may fail.");
129: f3.delete();
130:
131: //Log.debug("This is necessary to prevent possible data loss when removing those symlinks.");
132: //continue;
133: }
134:
135: if (f3.isDirectory()) {
136: //System.out.println(dir);
137: cleanLocalDir(dir + tmp[i]);
138: f3.delete();
139: } else {
140: //System.out.println(dir+tmp[i]);
141: f3.delete();
142: }
143: }
144: } catch (Exception ex) {
145: Log.debug("Error: " + ex.toString());
146: ex.printStackTrace();
147: }
148: }
149:
150: public void sendRawCommand(String cmd) {
151: }
152:
153: public void disconnect() {
154: }
155:
156: public boolean isConnected() {
157: return true;
158: }
159:
160: public String getPWD() {
161: return pwd;
162: }
163:
164: public boolean cdup() {
165: return chdir(pwd.substring(0, pwd.lastIndexOf("/") + 1));
166: }
167:
168: public boolean mkdir(String dirName) {
169: Log.debug("Feature is not implemented yet");
170:
171: if (true) {
172: return false;
173: }
174:
175: try {
176: if (StringUtils.isRelative(dirName)) {
177: dirName = getPWD() + dirName;
178: }
179:
180: WebdavFile f = new WebdavFile(getURL(dirName));
181:
182: boolean x = f.mkdir();
183: fireDirectoryUpdate();
184:
185: return x;
186: } catch (Exception ex) {
187: Log.debug("Error: " + ex.toString());
188: ex.printStackTrace();
189:
190: return false;
191: }
192: }
193:
194: public void list() throws IOException {
195: }
196:
197: public boolean chdir(String p) {
198: try {
199: String p2 = processPath(p);
200:
201: if (p2 == null) {
202: return false;
203: }
204:
205: //WebdavFile f = new WebdavFile(getURL(p2));
206: WebdavResource f = getResource(p2);
207:
208: if (!f.exists() || !f.isCollection()) //!f.isDirectory() || !f.canRead())
209: {
210: Log.debug("Access denied.");
211:
212: return false;
213: }
214:
215: pwd = p2;
216:
217: Log.out("PWD: " + pwd);
218:
219: fireDirectoryUpdate();
220:
221: return true;
222: } catch (Exception ex) {
223: Log.debug("Error: " + ex.toString());
224: ex.printStackTrace();
225:
226: return false;
227: }
228: }
229:
230: public boolean chdirNoRefresh(String p) {
231: String p2 = processPath(p);
232:
233: if (p2 == null) {
234: return false;
235: }
236:
237: //System.out.println(p2);
238: pwd = p2;
239:
240: return true;
241: }
242:
243: public String getLocalPath() {
244: //System.out.println("local: " + path);
245: return path;
246: }
247:
248: public String processPath(String p) {
249: try {
250: if (!p.startsWith("http://")) {
251: p = pwd + p;
252: }
253:
254: if (!p.endsWith("/")) {
255: p = p + "/";
256: }
257:
258: while (p.endsWith("/../")) {
259: p = p.substring(0, p.lastIndexOf("/../") - 1);
260: p = p.substring(0, p.lastIndexOf("/"));
261: }
262:
263: while (p.endsWith("/./")) {
264: p = p.substring(0, p.lastIndexOf("/./") - 1);
265: p = p.substring(0, p.lastIndexOf("/"));
266: }
267:
268: //System.out.println(", processPath 2: "+p);
269: //WebdavFile f = new WebdavFile(getURL(p));
270: Log.out("\n\n\nprocessPath URL: " + p);
271:
272: WebdavResource f = getResource(p);
273: String p2 = p;
274:
275: if (f.exists() && f.isCollection()) {
276: try {
277: //p2 = f.toURL(); //CanonicalPath();
278: if (!p2.endsWith("/")) {
279: p2 = p2 + "/";
280: }
281:
282: //Log.out("processPath parsed URL: " + p);
283: //Log.out("processPath URL2: " + f.getPath());
284: return p2;
285: } catch (Exception ex) {
286: Log
287: .debug("Error: can not get pathname (processPath)!");
288:
289: return null;
290: }
291: } else {
292: Log.debug("(processpPath) No such path: \"" + p + "\"");
293:
294: return null;
295: }
296: } catch (Exception ex) {
297: Log.debug("Error: " + ex.toString());
298: ex.printStackTrace();
299:
300: return null;
301: }
302: }
303:
304: public boolean setLocalPath(String p) {
305: try {
306: p = p.replace('\\', '/');
307:
308: //System.out.print("local 1:" + p);
309: if (StringUtils.isRelative(p)) {
310: p = path + p;
311: }
312:
313: p = p.replace('\\', '/');
314:
315: //System.out.println(", local 2:" + p);
316: File f = new File(p);
317:
318: if (f.exists()) {
319: try {
320: path = f.getCanonicalPath();
321: path = path.replace('\\', '/');
322:
323: if (!path.endsWith("/")) {
324: path = path + "/";
325: }
326:
327: //System.out.println("localPath: "+path);
328: } catch (Exception ex) {
329: Log.debug("Error: can not get pathname (local)!");
330:
331: return false;
332: }
333: } else {
334: Log.debug("(local) No such path: \"" + p + "\"");
335:
336: return false;
337: }
338:
339: return true;
340: } catch (Exception ex) {
341: Log.debug("Error: " + ex.toString());
342: ex.printStackTrace();
343:
344: return false;
345: }
346: }
347:
348: public String[] sortLs() {
349: try {
350: Log.out("sortLs PWD: " + pwd);
351:
352: //WebdavFile fl = new WebdavFile(new URL(pwd), user, pass);
353: WebdavResource fp = getResource(pwd);
354:
355: //new WebdavResource(getURL(pwd));
356: //files = f.list();
357: //File[] f = fl.listFiles();
358: WebdavResource[] f = fp.listWebdavResources();
359:
360: //if(files == null) return new String[0];
361: files = new String[f.length];
362: size = new String[f.length];
363: perms = new int[f.length];
364:
365: int accessible = 0;
366:
367: for (int i = 0; i < f.length; i++) {
368: files[i] = f[i].getName();
369:
370: /*
371: while(files[i].indexOf("%20") >= 0)
372: {
373: int x = files[i].indexOf("%20");
374: String tmp = files[i].substring(0,x)+" "+
375: files[i].substring(files[i].indexOf("%20")+3);
376: files[i] = tmp;
377: }
378: */
379: /*
380: try
381: {
382: f[i].exists();
383: }
384: catch(Exception ex)
385: {
386: Log.debug("ERROR: parsing problem with:" + files[i]);
387: size[i] = "-1";
388: perms[i] = FtpConnection.DENIED;
389: continue;
390: }
391: */
392: Log.out("sortLs files[" + i + "]: " + files[i]);
393:
394: //size[i] = "" + (int) f[i].length();
395: size[i] = "" + (int) f[i].getGetContentLength();
396: perms[i] = FtpConnection.R;
397:
398: if (f[i].isCollection() && !files[i].endsWith("/")) {
399: files[i] = files[i] + "/";
400: }
401:
402: /*
403: if(f[i].canWrite()) accessible = FtpConnection.W;
404: else if(f[i].canRead()) accessible = FtpConnection.R;
405: else accessible = FtpConnection.DENIED;
406: perms[i] = accessible;
407:
408: Log.out("sortLs files["+i+"]: " + files[i]);
409: WebdavFile f2 = new WebdavFile(new URL(files[i]), user, pass);
410:
411: if(!f2.exists()) continue;
412: if(f2.isDirectory() && !files[i].endsWith("/")) files[i] = files[i] + "/";
413:
414: size[i] = "" + new WebdavFile(new URL(files[i]), user, pass).length();
415: */
416: }
417:
418: return files;
419: } catch (Exception ex) {
420: Log.debug("Error: " + ex.toString());
421: ex.printStackTrace();
422:
423: return new String[0];
424: }
425: }
426:
427: public String[] sortSize() {
428: return size;
429: }
430:
431: public int[] getPermissions() {
432: return perms;
433: }
434:
435: public int handleDownload(String file) {
436: transfer(file);
437:
438: return 0;
439: }
440:
441: public int handleUpload(String file) {
442: transfer(file, true);
443:
444: return 0;
445: }
446:
447: public int download(String file) {
448: transfer(file);
449:
450: return 0;
451: }
452:
453: public int upload(String file) {
454: transfer(file, true);
455:
456: return 0;
457: }
458:
459: private void transferDir(String dir, String out) {
460: try {
461: fileCount = 0;
462: shortProgress = true;
463: baseFile = StringUtils.getDir(dir);
464:
465: WebdavFile f2 = new WebdavFile(getURL(dir));
466: String[] tmp = f2.list();
467:
468: if (tmp == null) {
469: return;
470: }
471:
472: WebdavFile fx = new WebdavFile(getURL(out));
473:
474: if (!fx.mkdir()) {
475: Log.debug("Can not create directory: " + out
476: + " - already exist or permission denied?");
477: }
478:
479: for (int i = 0; i < tmp.length; i++) {
480: tmp[i] = tmp[i].replace('\\', '/');
481:
482: //System.out.println("1: " + dir+tmp[i] + ", " + out +tmp[i]);
483: WebdavFile f3 = new WebdavFile(getURL(dir + tmp[i]));
484:
485: if (f3.isDirectory()) {
486: if (!tmp[i].endsWith("/")) {
487: tmp[i] = tmp[i] + "/";
488: }
489:
490: transferDir(dir + tmp[i], out + tmp[i]);
491: } else {
492: fireProgressUpdate(baseFile, DataConnection.GETDIR
493: + ":" + fileCount, -1);
494: work(dir + tmp[i], out + tmp[i]);
495: }
496: }
497:
498: fireProgressUpdate(baseFile, DataConnection.DFINISHED + ":"
499: + fileCount, -1);
500: shortProgress = false;
501: } catch (Exception ex) {
502: Log.debug("Error: " + ex.toString());
503: ex.printStackTrace();
504: }
505: }
506:
507: private HttpURL getURL(String u) {
508: try {
509: HttpURL url = new HttpURL(u);
510:
511: //System.out.println(user + ":"+ pass);
512: url.setUserinfo(user, pass);
513:
514: return url;
515: } catch (Exception ex) {
516: ex.printStackTrace();
517: Log.debug("ERROR: " + ex);
518:
519: return null;
520: }
521: }
522:
523: private WebdavResource getResource(String res)
524: throws HttpException, IOException {
525: return new WebdavResource(getURL(res));
526: }
527:
528: private void transfer(String file) {
529: transfer(file, false);
530: }
531:
532: private void transfer(String file, boolean up) {
533: String out = StringUtils.getDir(file);
534:
535: if (StringUtils.isRelative(file)) {
536: file = getPWD() + file;
537: }
538:
539: file = file.replace('\\', '/');
540: out = out.replace('\\', '/');
541:
542: String outfile = StringUtils.getFile(file);
543:
544: if (file.endsWith("/")) {
545: if (up) {
546: Log.debug("Directory upload not implemented yet.");
547:
548: return;
549: }
550:
551: transferDir(file, getLocalPath() + out);
552:
553: return;
554: } else {
555: if (up) {
556: work(getLocalPath() + outfile, file);
557: } else {
558: work(file, getLocalPath() + outfile);
559: }
560: }
561: }
562:
563: private void work(String file, String outfile) {
564: Log.out("transfer started\nfile: " + file + "\noutfile: "
565: + outfile);
566:
567: BufferedInputStream in = null;
568: BufferedOutputStream out = null;
569:
570: try {
571: if (outfile.startsWith("http://")) {
572: //out = new BufferedOutputStream(new FileOutputStream(new WebdavResource(new HttpURL(file)).getMethodData());
573: //new WebdavFile(new URL(outfile), user, pass)));
574: //in = new BufferedInputStream(new FileInputStream(file));
575: String resPath = outfile.substring(0, outfile
576: .lastIndexOf("/") + 1);
577: String name = outfile.substring(outfile
578: .lastIndexOf("/") + 1);
579:
580: Log.debug("Uploading " + file + " to " + resPath
581: + " as " + name);
582:
583: //HttpURL url = getURL(resPath);
584: WebdavResource res = getResource(resPath);
585:
586: //new WebdavResource(url);
587:
588: /*
589: if(res.checkinMethod()) Log.debug("Checkin OK");
590: else Log.debug("Checkin FAILED");
591:
592: Enumeration e = res.getAllowedMethods();
593: while(e != null && e.hasMoreElements())
594: {
595: Log.debug("Method: " + e.nextElement().toString());
596: }
597: */
598: if (res.putMethod(new File(file))) {
599: fireProgressUpdate(file, DataConnection.FINISHED,
600: -1);
601: } else {
602: Log.debug("Upload failed.");
603: fireProgressUpdate(file, DataConnection.FAILED, -1);
604: }
605:
606: return;
607: }
608:
609: Log.debug("Downloading " + file + " to " + outfile);
610:
611: out = new BufferedOutputStream(
612: new FileOutputStream(outfile));
613: in = new BufferedInputStream(getResource(file)
614: .getMethodData());
615:
616: //new WebdavResource(getURL(file)).getMethodData());
617: byte[] buf = new byte[webdavBuffer];
618: int len = 0;
619: int reallen = 0;
620:
621: //System.out.println(file+":"+getLocalPath()+outfile);
622: while (true) {
623: len = in.read(buf);
624:
625: //System.out.print(".");
626: if (len == StreamTokenizer.TT_EOF) {
627: break;
628: }
629:
630: out.write(buf, 0, len);
631:
632: reallen += len;
633: fireProgressUpdate(StringUtils.getFile(file),
634: DataConnection.GET, reallen);
635: }
636:
637: fireProgressUpdate(file, DataConnection.FINISHED, -1);
638: } catch (IOException ex) {
639: Log.debug("Error with file IO (" + ex + ")!");
640: ex.printStackTrace();
641: fireProgressUpdate(file, DataConnection.FAILED, -1);
642: } finally {
643: try {
644: out.flush();
645: out.close();
646: in.close();
647: } catch (Exception ex) {
648: ex.printStackTrace();
649: }
650: }
651: }
652:
653: public int upload(String file, InputStream in) {
654: /*
655: if(StringUtils.isRelative(file)) file = getPWD() + file;
656: file = file.replace('\\','/');
657:
658: try
659: {
660: work(new BufferedInputStream(in), file, file);
661: return 0;
662: }
663: catch(Exception ex)
664: {
665: Log.debug("Error: " + ex.toString());
666: ex.printStackTrace();
667: return -1;
668: }
669: */
670: Log.debug("Upload using InputStream is not implemented yet!");
671:
672: return -1;
673: }
674:
675: /*
676: private void work(BufferedInputStream in, String outfile, String file)
677: {
678: Log.out("transfer started, input from stream\noutfile: " + outfile);
679:
680: try
681: {
682: BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outfile));
683: byte buf[] = new byte[webdavBuffer];
684: int len = 0;
685: int reallen = 0;
686:
687: while(true)
688: {
689: len = in.read(buf);
690: System.out.print(".");
691: if(len == StreamTokenizer.TT_EOF) break;
692: out.write(buf,0,len);
693:
694: reallen += len;
695: fireProgressUpdate(StringUtils.getFile(file),DataConnection.GET, reallen);
696: }
697:
698: out.flush();
699: out.close();
700: in.close();
701: fireProgressUpdate(file,DataConnection.FINISHED, -1);
702: }
703: catch(IOException ex)
704: {
705: Log.debug("Error with file IO ("+ex+")!");
706: ex.printStackTrace();
707: fireProgressUpdate(file,DataConnection.FAILED, -1);
708: }
709: }
710: */
711: public InputStream getDownloadInputStream(String file) {
712: if (StringUtils.isRelative(file)) {
713: file = getPWD() + file;
714: }
715:
716: file = file.replace('\\', '/');
717:
718: try {
719: return getResource(file).getMethodData();
720: } catch (Exception ex) {
721: ex.printStackTrace();
722: Log.debug(ex.toString()
723: + " @WebdavConnection::getDownloadInputStream");
724:
725: return null;
726: }
727: }
728:
729: public void addConnectionListener(ConnectionListener l) {
730: listeners.add(l);
731: }
732:
733: public void setConnectionListeners(Vector l) {
734: listeners = l;
735: }
736:
737: /** remote directory has changed */
738: public void fireDirectoryUpdate() {
739: if (listeners == null) {
740: return;
741: } else {
742: for (int i = 0; i < listeners.size(); i++) {
743: ((ConnectionListener) listeners.elementAt(i))
744: .updateRemoteDirectory(this );
745: }
746: }
747: }
748:
749: public boolean login(String user, String pass) {
750: return true;
751: }
752:
753: public void fireProgressUpdate(String file, String type, int bytes) {
754: if (listeners == null) {
755: return;
756: } else {
757: for (int i = 0; i < listeners.size(); i++) {
758: ConnectionListener listener = (ConnectionListener) listeners
759: .elementAt(i);
760:
761: if (shortProgress && Settings.shortProgress) {
762: if (type.startsWith(DataConnection.DFINISHED)) {
763: listener.updateProgress(baseFile,
764: DataConnection.DFINISHED + ":"
765: + fileCount, bytes);
766: }
767:
768: listener.updateProgress(baseFile,
769: DataConnection.GETDIR + ":" + fileCount,
770: bytes);
771: } else {
772: listener.updateProgress(file, type, bytes);
773: }
774: }
775: }
776: }
777:
778: public Date[] sortDates() {
779: return null;
780: }
781:
782: public boolean rename(String from, String to) {
783: Log.debug("Not implemented!");
784:
785: return false;
786: }
787: }
|